V4 Updates from remote Repo

This commit is contained in:
JW 2021-11-25 17:27:39 +01:00
parent 438c8bcf66
commit e8471373a1
110 changed files with 9653 additions and 7169 deletions

8
.github/lock.yml vendored
View File

@ -30,13 +30,7 @@ lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
lockComment: false

51
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,51 @@
name: "Code scanning - action"
on:
push:
pull_request:
schedule:
- cron: '0 19 * * 0'
jobs:
CodeQL-Build:
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: javascript
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -1,12 +0,0 @@
name: Compress images
on: pull_request
jobs:
build:
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: calibreapp/image-actions
uses: calibreapp/image-actions@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,9 +1,10 @@
name: pxt-buildtarget
name: pxt-buildmain
on:
push:
branches:
- master
branches:
- 'master'
- 'main'
create:
jobs:

31
.github/workflows/pxt-buildpr.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: pxt-buildpr
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [8.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: |
sudo apt-get install xvfb
sudo npm install -g pxt
npm install
- name: pxt ci
run: |
pxt ci
env:
CHROME_BIN: chromium-browser
DISPLAY: :99.0
CI: true

39
.github/workflows/pxt-buildpush.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: pxt-buildpush
on:
push:
# main/master has its own build that includes the crowdin key
branches-ignore:
- 'main'
- 'master'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [8.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: |
sudo apt-get install xvfb
sudo npm install -g pxt
npm install
- name: pxt ci
run: |
pxt ci
env:
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
CHROME_BIN: chromium-browser
DISPLAY: :99.0
CI: true

View File

@ -11,9 +11,12 @@ jobs:
strategy:
matrix:
node-version: [8.x]
branch: [stable3.0]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
with:
ref: ${{ matrix.branch }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
@ -45,5 +48,5 @@ jobs:
uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: logs
name: logs-${{ matrix.branch }}
path: temp/ghpkgs/*.txt

View File

@ -1,27 +0,0 @@
language: node_js
os: linux
dist: trusty
node_js:
- "8.9.4"
before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script:
- "node node_modules/pxt-core/built/pxt.js travis"
# - "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js run)"
# - "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js run)"
# - "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js test)"
# - "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js test)"
# - "node node_modules/pxt-core/built/pxt.js testdir tests"
# - "(cd libs/hello; node ../../node_modules/pxt-core/built/pxt.js testconv http://az851932.vo.msecnd.net/files/td-converter-tests-v1.json)"
sudo: false
notifications:
email:
- touchdevelop-build@microsoft.com
cache:
directories:
- node_modules
- built/cache
- libs/hello/built/cache

19
.vscode/tasks.json vendored
View File

@ -1,20 +1,19 @@
{
"version": "0.1.0",
"version": "2.0.0",
// Task runner is jake
"command": "pxt",
// Need to be executed in shell / cmd
"isShellCommand": true,
"showOutput": "always",
"tasks": [
{
// TS build command is local.
"taskName": "serve",
// Make this the default build command.
"isBuildCommand": true,
// Use the redefined Typescript output problem matcher.
"label": "serve",
"type": "shell",
"command": "pxt",
"args": [
"serve"
],
"problemMatcher": [
"$tsc"
]
],
"group": "build"
}
]
}

View File

@ -1,4 +1,4 @@
# micro:bit target for PXT
# calliope target for PXT

View File

@ -1,13 +0,0 @@
{
"folders": [
{
"path": "../pxt"
},
{
"path": "../pxt-common-packages"
},
{
"path": "."
}
]
}

131
compiler/combiner.ts Normal file
View File

@ -0,0 +1,131 @@
/// <reference path="../node_modules/pxt-core/built/pxtcompiler.d.ts"/>
namespace ts.pxtc.extension {
pxtc.compilerHooks.postBinary = (program: ts.Program, opts: CompileOptions, res: CompileResult) => {
if (!opts.target.isNative)
return
const mbdal = res.outfiles["mbdal-binary.hex"]
const mbcodal = res.outfiles["mbcodal-binary.hex"]
if (!mbdal || !mbcodal)
return
let outp = ""
wrapHex(mbdal, 0x00, [0x99, 0x01, 0xc0, 0xde])
wrapHex(mbcodal, 0x0D, [0x99, 0x03, 0xc0, 0xde], true)
outp += ":00000001FF\n"
res.outfiles["binary.hex"] = outp
function hex2str(bytes: number[]) {
return ts.pxtc.hexfile.hexBytes([bytes.length - 3].concat(bytes)) + "\n"
}
function paddingString(len: number) {
let r = ""
const len0 = len
while (len >= 44) {
r += hex2str([0x00, 0x00, 0x0C,
0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42])
len -= 44
}
if (len >= 12) {
const numBytes = (len - 11) >> 1
const bytes = [0x00, 0x00, 0x0C]
for (let i = 0; i < numBytes; ++i) bytes.push(0x42)
const add = hex2str(bytes)
r += add
len -= add.length
}
while (len--)
r += "\n"
U.assert(r.length == len0)
return r
}
function addBlock(blk: string) {
const leftoff = blk.length & 511
outp += blk + paddingString(512 - leftoff)
}
function wrapHex(inpHex: string, dataType: number, deviceType: number[], keepSrc = false) {
let blk =
hex2str([0x00, 0x00, 0x04, 0x00, 0x00])
+ hex2str([0x00, 0x00, 0x0A].concat(deviceType))
let upperAddr = 0
const lines = inpHex.split(/\r?\n/)
for (let i = 0; i < lines.length; ++i) {
const line = lines[i]
if (!line)
continue
const parsed = ts.pxtc.hexfile.parseHexRecord(line)
switch (parsed.type) {
case 0x00:
/*
const parsed2 = parsed.len <= 16 && lines[i + 1] ?
ts.pxtc.hexfile.parseHexRecord(lines[i + 1])
: null
// if this and next line can fit in 32 bytes, concat them
if (parsed2 && parsed2.type == 0x00 &&
parsed2.addr == parsed.addr + parsed.len &&
parsed.len + parsed2.len <= 32) {
parsed.data = parsed.data.concat(parsed2.data)
parsed.len += parsed2.len
i++
}
*/
addData([parsed.addr >> 8, parsed.addr & 0xff, dataType]
.concat(parsed.data))
break
case 0x01:
flush()
if (keepSrc) break
else return
case 0x04:
const newUpper = ((parsed.data[0] << 8) | parsed.data[1]) << 16
if (upperAddr != newUpper) {
upperAddr = newUpper
addData([0, 0, 0x04, parsed.data[0], parsed.data[1]])
}
break
case 0x03:
case 0x05:
// ignore
break
case 0x0E:
// src record
addData([parsed.addr >> 8, parsed.addr & 0xff, 0x0E]
.concat(parsed.data))
break
default:
U.oops(`unknown hex record type: ${line}`)
break
}
}
flush()
function addData(bytes: number[]) {
const newData = hex2str(bytes)
blk += newData
}
function flush() {
if (blk)
addBlock(blk)
blk = ""
}
}
}
}

23
compiler/tsconfig.json Normal file
View File

@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "es2017",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"declaration": true,
"moduleResolution": "node",
"isolatedModules": false,
"out": "../built/compiler.js",
"rootDir": ".",
"newLine": "LF",
"sourceMap": false,
"typeRoots": ["../node_modules/@types"],
"lib": [
"dom",
"dom.iterable",
"scripthost",
"es2017",
"ES2018.Promise"
]
}
}

View File

@ -0,0 +1,2 @@
Micro:bit and micro:bit logo are trademarks and/ or copyrights of the Micro:bit
Educational Foundation. &copy; Micro:bit Educational Foundation. All rights reserved.

View File

@ -78,6 +78,13 @@ input.onButtonPressed(Button.B, () => {
We have tons of [projects](/projects), [examples](/examples) and [courses](/courses) to get your started!
## C++ Runtime
The [C++ micro:bit runtime](http://lancaster-university.github.io/microbit-docs/), created at [Lancaster University](http://www.lancaster.ac.uk/), provides access to the hardware functions of the micro:bit,
as well as a set of helper functions (such as displaying a number/image/string on the LED screen).
The [micro:bit library](/reference) mirrors the functions of the C++ library.
When code is compiled to ARM machine code, the calls to JavaScript micro:bit functions are replaced with calls to the corresponding C++ functions.
## [Command Line Tools](/cli)

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

21
docs/hero-banner.md Normal file
View File

@ -0,0 +1,21 @@
# Hero Banner
Here are some cool activities to get you started with your @boardname@!
## Intro Content
### ~ codecard
* name: CalliopEO
* description: CALLIOPEO Taking the Calliope mini to the ISS.
* imageUrl: /calliope/02_Hero_CalliopEO.png
* url: https://calliope.cc/calliopeo
* buttonLabel: Participate!
* cardType: link
---
* name: The 5x5 LED matrix
* description: KIDS LAB play, learn and hack!
* imageUrl: /calliope/03_Hero_KidsLab.png
* url: https://calliope.cc/programmieren/kidslab
* buttonLabel: Explore!
* cardType: link
### ~

View File

@ -6,7 +6,7 @@ Tell everyone who you are. Show you name on the LEDs.
![Name scrolling on the LEDs](/calliope/tutorials/02_nametag_animation.gif)
## Step 1 @fullscreen
## Step 1
Place the ``||basic:show string||`` block in the ``||basic:forever||`` block to repeat it. Change the text to your name.
@ -16,13 +16,12 @@ basic.forever(() => {
});
```
## Step 2 @fullscreen
## Step 2
Look at the simulator and make sure it shows your name on the screen.
![Name scrolling on the LEDs](/calliope/tutorials/02_nametag_animation.gif)
## Step 3 @fullscreen
Place more ``||basic:show string||`` blocks to create your own story.
@ -33,6 +32,6 @@ basic.forever(() => {
})
```
## Step 4 @unplugged
## Step 4
If you have a @boardname@ connected, click ``|Download|`` to transfer your code and watch your name scroll!

BIN
docs/skillmap/img/space.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

37
docs/skillmap/mini.md Normal file
View File

@ -0,0 +1,37 @@
# Build a mini Explorer
* name: Build a mini Explorer
* description: Learn to make a Galga-style game by following this short series of tutorials.
* bannerUrl: /skillmap/img/spacet4.gif
* backgroundurl: /skillmap/img/space.png
* primarycolor: #2EA9B0
* secondarycolor: #d6f7fa
* tertiarycolor: #5d416b
* highlightcolor: #FFFFFF
* completednodecolor: #504c52
* tags: beginner, mini, first steps
## mini
* name: Design a mini Explorer
* description: Let's explore the depths of mini! We'll add a vessel for mini travel, create some enemies, and make sure we have plenty of fuel for the journey.
* completionUrl: /skillmap/img/spacet4.gif
### mini-activity1
* allowcodecarryover: false
* name: Prepare Your Ship
* type: tutorial
* description: Get your miniship ready for an adventure!
* tags: easy, sprites, scroller
* url: /calliope/firststeps/firstSteps
* imageUrl: /skillmap/img/spacet4.gif
### mini-cert-1
* name: Congrats!
* kind: completion
* type: certificate
* imageUrl: /skillmap/img/spacet4.gif
* url: /skillmap/img/spacet4.gif

81
docs/skillmap/space.md Normal file
View File

@ -0,0 +1,81 @@
# Build a Space Explorer
* name: Build a Space Explorer
* description: Learn to make a Galga-style game by following this short series of tutorials.
* infoUrl: skillmap/educator-info/int-map-info
* bannerUrl: /static/skillmap/space/spacet4.gif
* backgroundurl: /static/skillmap/backgrounds/space-comp.png
* primarycolor: #2EA9B0
* secondarycolor: #d6f7fa
* tertiarycolor: #5d416b
* highlightcolor: #FFFFFF
* completednodecolor: #504c52
* tags: intermediate, space, projectiles
* alternatesources: github:https://github.com/microsoft/pxt-skillmap-sample/skillmap.md
## space
* name: Design a Space Explorer
* description: Let's explore the depths of space! We'll add a vessel for space travel, create some enemies, and make sure we have plenty of fuel for the journey.
* completionUrl: /static/skillmap/certificates/design-a-space-explorer.pdf
### space-activity1
* allowcodecarryover: false
* name: Prepare Your Ship
* type: tutorial
* description: Get your spaceship ready for an adventure!
* tags: easy, sprites, scroller
* next: space-activity2, pusher1
* url: /skillmap/space/space1
* imageUrl: /static/skillmap/space/spacet1.gif
### space-activity2
* name: Ready, aim, fire!
* type: tutorial
* description: Equip your ship with projectiles and special effects.
* tags: easy, projectiles, kinds
* next: pusher2, space-activity3
* url: /skillmap/space/space2
* imageUrl: /static/skillmap/space/spacet2.gif
### space-activity3
* name: Here comes trouble!
* description: Watch out for danger! Add enemies and countdown lives in your game.
* type: tutorial
* tags: intermediate, enemies, kinds
* next: space-activity4
* url: /skillmap/space/space3
* imageUrl: /static/skillmap/space/spacet3.gif
### space-activity4
* name: Fuel Up!
* type: tutorial
* description: Use an extension to add a fuel gauge to your ship. Make sure to refuel often!
* tags: intermediate, extensions
* next: space-cert-1
* url: /skillmap/space/space4
* imageUrl: /static/skillmap/space/spacet4.gif
### space-cert-1
* name: Congrats!
* kind: completion
* type: certificate
* imageUrl: /static/skillmap/certificates/space-cert.png
* url: /static/skillmap/certificates/design-a-space-explorer.pdf
### pusher1
* name: Blank node
* kind: layout
### pusher2
* name: Blank node
* kind: layout

View File

@ -0,0 +1,172 @@
# Space Explorer
## Introduction @showdialog
** Let's explore the depths of space! **
In this tutorial, you'll design a spaceship for your journey.
![Flying through space](/static/skillmap/space/space1.gif "Blasting through a starfield" )
## Set the scene
**Give 'em something to look at** 🔭
---
► Drag the ``||scene:start screen [confetti] effect ⊕||`` from the ``||scene:Scene||`` category and
into the ``||loops:on start||`` block that's already in the workspace.
► Next, select ``||scene:star field||`` (instead of ``||scene:confetti||``) from the dropdown
and watch as you blast into space! 🚀
---
```blocks
// @highlight
effects.starField.startScreenEffect()
```
## Draw your ship
**🧑🏿‍🚀 Time to choose our ship! 👩🏾‍🚀**
---
► From the ``||sprites:Sprites||`` category, drag the ``||variables:set [mySprite] to sprite [ ] of kind [Player]||``
block and place it at the end of the ``||loops:on start||`` container.
► Click on the grey box in the middle of your
``||variables:set [mySprite] to sprite [ ] of kind [Player]||`` block
to design a ship of your own! Are you a rusty pile of scraps or a sleek, futuristic rocket?
---
**Tip:** Don't feel like drawing your ship? Once you're in the sprite editor,
flip to the gallery and choose from premade images.
```blocks
effects.starField.startScreenEffect()
// @highlight
let mySprite = sprites.create(img`
. . . . . . . 9 9 . . . . . . .
. . . . . . 9 . . 9 . . . . . .
. . . . . . 9 . . 9 . . . . . .
. . . . . 9 . 9 9 . 9 . . . . .
. . . . . 9 . 9 9 . 9 . . . . .
. . . . 9 . 9 9 9 9 . 9 . . . .
. . . . 9 . 9 9 9 9 . 9 . . . .
. . . 9 . 9 9 9 9 9 9 . 9 . . .
. . . 9 . 9 . . . . 9 . 9 . . .
. . 9 . 9 9 . 9 9 . 9 9 . 9 . .
. . 9 . 9 9 . . . . 9 9 . 9 . .
. 9 . 9 9 9 . 9 9 9 9 9 9 . 9 .
. 9 . 9 9 9 . 9 9 9 9 9 9 . 9 .
9 . 9 9 9 9 9 9 9 9 9 9 9 9 . 9
9 . . . . . . . . . . . . . . 9
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
`, SpriteKind.Player)
```
## Control your ship
🌟 Let's get your ship moving 🌟
---
► Find the ``||controller:move [mySprite] with buttons ⊕||`` block
and drag it into the bottom of the ``||loops:on start||`` container.
** Now try moving your ship around on the game screen! **
Your ship will move with the joystick, arrow keys, or **W A S D** keys.
```blocks
effects.starField.startScreenEffect()
let mySprite = sprites.create(img`
. . . . . . . 9 9 . . . . . . .
. . . . . . 9 . . 9 . . . . . .
. . . . . . 9 . . 9 . . . . . .
. . . . . 9 . 9 9 . 9 . . . . .
. . . . . 9 . 9 9 . 9 . . . . .
. . . . 9 . 9 9 9 9 . 9 . . . .
. . . . 9 . 9 9 9 9 . 9 . . . .
. . . 9 . 9 9 9 9 9 9 . 9 . . .
. . . 9 . 9 . . . . 9 . 9 . . .
. . 9 . 9 9 . 9 9 . 9 9 . 9 . .
. . 9 . 9 9 . . . . 9 9 . 9 . .
. 9 . 9 9 9 . 9 9 9 9 9 9 . 9 .
. 9 . 9 9 9 . 9 9 9 9 9 9 . 9 .
9 . 9 9 9 9 9 9 9 9 9 9 9 9 . 9
9 . . . . . . . . . . . . . . 9
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
`, SpriteKind.Player)
// @highlight
controller.moveSprite(mySprite)
```
## Stay in screen
**Uh-oh, if you move off screen, your ship disappears!**
---
► To keep your ship from exploring beyond the edges, find
the ``||sprites:set [mySprite] stay in screen <on>||`` block and
snap it in at the end of the program.
```blocks
effects.starField.startScreenEffect()
let mySprite = sprites.create(img`
. . . . . . . 9 9 . . . . . . .
. . . . . . 9 . . 9 . . . . . .
. . . . . . 9 . . 9 . . . . . .
. . . . . 9 . 9 9 . 9 . . . . .
. . . . . 9 . 9 9 . 9 . . . . .
. . . . 9 . 9 9 9 9 . 9 . . . .
. . . . 9 . 9 9 9 9 . 9 . . . .
. . . 9 . 9 9 9 9 9 9 . 9 . . .
. . . 9 . 9 . . . . 9 . 9 . . .
. . 9 . 9 9 . 9 9 . 9 9 . 9 . .
. . 9 . 9 9 . . . . 9 9 . 9 . .
. 9 . 9 9 9 . 9 9 9 9 9 9 . 9 .
. 9 . 9 9 9 . 9 9 9 9 9 9 . 9 .
9 . 9 9 9 9 9 9 9 9 9 9 9 9 . 9
9 . . . . . . . . . . . . . . 9
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
`, SpriteKind.Player)
controller.moveSprite(mySprite)
// @highlight
mySprite.setStayInScreen(true)
```
## Finale @showdialog
**Great Job!**
---
**Try your project on the game screen
before you click finish on the tutorial.**
Is everything how you want it? You can always go back and edit steps if you discover you'd like them to work differently.
## Byeeee
** 🚀 That's it! 🚀**
You're all set to travel the universe!
Click **Finish** to return to the main page where you can share your game
with family and friends!

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

19
docs/skillmaps.md Normal file
View File

@ -0,0 +1,19 @@
# Skillmaps
## Getting started
```codecard
[
{
"name": "Beginner Skillmap",
"cardType": "link",
"description": "Learn to make exciting and shareable arcade games by following a few quick tutorials!",
"imageUrl": "/static/skillmap/backgrounds/beginner.png",
"url": "http://localhost:3232--skillmap#mini",
"label": "New? Try This!",
"labelClass": "orange ribbon large",
"directOpen": true
}
]
```

View File

@ -12,7 +12,7 @@ export function renderUsbPairDialog(firmwareUrl?: string, failedOnce?: boolean):
<div className="column">
<div className="ui">
<div className="image">
<img alt={lf("Comic connecting micro:bit to computer")} className="ui medium rounded image" src="./static/download/connect.png" />
<img alt={lf("Comic connecting calliope mini to computer")} className="ui medium rounded image" src="./static/download/connect.png" />
</div>
<div className="content">
<div className="description">
@ -27,7 +27,7 @@ export function renderUsbPairDialog(firmwareUrl?: string, failedOnce?: boolean):
<div className="column">
<div className="ui">
<div className="image">
<img alt={lf("Comic of successful micro:bit connection")} className="ui medium rounded image" src="./static/download/pair.png" />
<img alt={lf("Comic of successful calliope mini connection")} className="ui medium rounded image" src="./static/download/pair.png" />
</div>
<div className="content">
<div className="description">
@ -51,7 +51,7 @@ export function renderUsbPairDialog(firmwareUrl?: string, failedOnce?: boolean):
<div className="ui header inverted">{lf("Update Firmware")}</div>
<strong className="ui small">{lf("You must have version 0249 or above of the firmware")}</strong>
<div className="image">
<img alt={lf("Comic rainbow updating micro:bit firmware")} className="ui image" src="./static/download/firmware.png" />
<img alt={lf("Comic rainbow updating calliope mini firmware")} className="ui image" src="./static/download/firmware.png" />
</div>
<a className="ui button" role="button" href={firmwareUrl} target="_blank">{lf("Check Firmware")}</a>
</div>
@ -73,7 +73,7 @@ export function renderBrowserDownloadInstructions(): JSX.Element {
<div className="column">
<div className="ui">
<div className="image">
<img alt={lf("Comic connecting micro:bit to computer")} className="ui medium rounded image" src="./static/download/connect.png" />
<img alt={lf("Comic connecting calliope mini to computer")} className="ui medium rounded image" src="./static/download/connect.png" />
</div>
<div className="content">
<div className="description">
@ -88,7 +88,7 @@ export function renderBrowserDownloadInstructions(): JSX.Element {
<div className="column">
<div className="ui">
<div className="image">
<img alt={lf("Comic moving hex file to micro:bit")} className="ui medium rounded image" src="./static/download/transfer.png" />
<img alt={lf("Comic moving hex file to calliope mini")} className="ui medium rounded image" src="./static/download/transfer.png" />
</div>
<div className="content">
<div className="description">

View File

@ -9,7 +9,7 @@ import * as flash from "./flash";
import * as patch from "./patch";
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
pxt.debug('loading microbit target extensions...')
pxt.debug('loading calliope mini target extensions...')
const manyAny = Math as any;
if (!manyAny.imul)
@ -24,35 +24,22 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
};
const res: pxt.editor.ExtensionResult = {
hexFileImporters: [{
id: "blockly",
canImport: data => data.meta.cloudId == "microbit.co.uk" && data.meta.editor == "blockly",
importAsync: (project, data) => {
pxt.tickEvent('import.legacyblocks.redirect');
return dialogs.cantImportAsync(project);
}
}, {
id: "td",
canImport: data => data.meta.cloudId == "microbit.co.uk" && data.meta.editor == "touchdevelop",
importAsync: (project, data) => {
pxt.tickEvent('import.legacytd.redirect');
return dialogs.cantImportAsync(project);
}
}]
hexFileImporters: []
};
pxt.usb.setFilters([{
vendorId: 0x1366,
productId: 0x1025
},
{
vendorId: 0x0D28,
productId: 0x0204
productId: 0x0204,
classCode: 0xff,
subclassCode: 0x03 // the ctrl pipe endpoint
}, {
vendorId: 0x0D28,
productId: 0x0204,
classCode: 0xff,
subclassCode: 0x00 // the custom CMSIS2 endpoint
}])
res.mkPacketIOWrapper = flash.mkDAPLinkPacketIOWrapper;
res.blocklyPatch = patch.patchBlocks;
res.renderBrowserDownloadInstructions = dialogs.renderBrowserDownloadInstructions;
res.renderUsbPairDialog = dialogs.renderUsbPairDialog;
return Promise.resolve<pxt.editor.ExtensionResult>(res);
}

View File

@ -1,9 +1,11 @@
const imul = (Math as any).imul;
const timeoutMessage = "timeout"
const membase = 0x20000000
const loadAddr = membase
const dataAddr = 0x20002000
const stackAddr = 0x20001000
const timeoutMessage = "timeout";
const membase = 0x20000000;
const loadAddr = membase;
const dataAddr = 0x20002000;
const stackAddr = 0x20001000;
const FULL_FLASH_TIMEOUT = 100000; // 100s
const PARTIAL_FLASH_TIMEOUT = 60000; // 60s
const flashPageBIN = new Uint32Array([
0xbe00be00, // bkpt - LR is set to this
@ -35,7 +37,7 @@ function log(msg: string) {
let ts = ("00000" + now).slice(-5)
pxt.debug(`dap ${ts}: ${msg}`)
}
const logV = /webusbdbg=1/.test(window.location.href) ? log : (msg: string) => { }
function murmur3_core(data: Uint8Array) {
let h0 = 0x2F9BE6CC;
@ -57,23 +59,41 @@ function murmur3_core(data: Uint8Array) {
return [h0, h1]
}
function bufferConcat(a: Uint8Array, b: Uint8Array) {
const r = new Uint8Array(a.length + b.length)
r.set(a, 0)
r.set(b, a.length)
return r
}
class DAPWrapper implements pxt.packetio.PacketIOWrapper {
familyID: number;
private dap: DapJS.DAP;
private cortexM: DapJS.CortexM
private cmsisdap: any;
private flashing = false;
private flashAborted = false;
private readSerialId = 0;
private pbuf = new pxt.U.PromiseBuffer<Uint8Array>();
private pageSize = 1024;
private numPages = 256;
private binName = pxtc.BINARY_HEX;
private usesCODAL = false;
private forceFullFlash = /webusbfullflash=1/.test(window.location.href);
private get useJACDAC() {
return this.usesCODAL;
}
onSerial = (buf: Uint8Array, isStderr: boolean) => { };
onCustomEvent = (type: string, payload: Uint8Array) => { };
constructor(public readonly io: pxt.packetio.PacketIO) {
this.familyID = 0x1366; // this is the microbit vendor id, not quite UF2 family id
this.io.onDeviceConnectionChanged = (connect) =>
this.familyID = 0x0D28; // this is the microbit vendor id, not quite UF2 family id
this.io.onDeviceConnectionChanged = (connect) => {
log(`device connection changed`);
this.disconnectAsync()
.then(() => connect && this.reconnectAsync());
}
this.io.onData = buf => {
// console.log("RD: " + pxt.Util.toHex(buf))
this.pbuf.push(buf);
@ -82,96 +102,199 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
this.allocDAP();
}
icon = "usb";
icon = "xicon microbit";
private pendingSerial: Uint8Array
private lastPendingSerial: number
private processSerialLine(line: Uint8Array) {
if (this.onSerial) {
try {
// catch encoding bugs
this.onSerial(line, false)
}
catch (err) {
log(`serial decoding error: ${err.message}`);
pxt.tickEvent("hid.flash.serial.decode.error");
console.error({ err, line })
}
}
}
private async readSerial(): Promise<number> {
let buf = await this.dapCmdNums(0x83)
const len = buf[1]
// concat received data with previous data
if (len) {
buf = buf.slice(2, 2 + len)
if (this.pendingSerial) buf = bufferConcat(this.pendingSerial, buf)
let ptr = 0
let beg = 0
while (ptr < buf.length) {
if (buf[ptr] == 10 || buf[ptr] == 13) {
ptr++;
// eat \r\n
while (ptr < buf.length && (buf[ptr] == 10 || buf[ptr] == 13))
ptr++;
const line = buf.slice(beg, ptr)
if (line.length)
this.processSerialLine(line);
beg = ptr
}
else
ptr++
}
buf = buf.slice(beg)
this.pendingSerial = buf.length ? buf : null
if (this.pendingSerial) {
this.lastPendingSerial = Date.now()
//logV(`pending serial ${this.pendingSerial.length}`)
}
} else if (this.pendingSerial) {
const d = Date.now() - this.lastPendingSerial
if (d > 500) {
this.processSerialLine(this.pendingSerial)
this.pendingSerial = null
}
}
return len
}
private startReadSerial() {
log(`start read serial`)
const rid = this.readSerialId;
const readSerial = () => {
if (rid != this.readSerialId) {
log(`stopped read serial ${rid}`)
return;
}
if (this.flashing) {
setTimeout(readSerial, 500);
return;
}
// done
this.cmsisdap.cmdNums(0x83, [])
.then((r: number[]) => {
const len = r[1]
let str = ""
for (let i = 2; i < len + 2; ++i) {
str += String.fromCharCode(r[i])
const startTime = Date.now();
log(`start read serial ${rid}`)
const readSerialLoop = async () => {
try {
while (rid === this.readSerialId) {
const len = await this.readSerial()
const hasData = len > 0
//if (hasData)
// logV(`serial read ${len} bytes`)
await this.jacdacProcess(hasData)
}
log(`stopped serial reader ${rid}`)
} catch (err) {
log(`serial error ${rid}: ${err.message}`);
console.error(err)
if (rid != this.readSerialId) {
log(`stopped serial reader ${rid}`)
} else {
pxt.tickEvent("hid.flash.serial.error");
const timeRunning = Date.now() - startTime
await this.disconnectAsync(); // force disconnect
// if we've been running for a while, try reconnecting
if (timeRunning > 1000) {
log(`auto-reconnect`)
await this.reconnectAsync();
}
if (str.length > 0) {
pxt.U.nextTick(readSerial)
if (this.onSerial) {
const utf8Str = pxt.U.toUTF8(str);
this.onSerial(pxt.U.stringToUint8Array(utf8Str), false)
}
} else
setTimeout(readSerial, 50)
}, (err: any) => {
log(`read error: ` + err.message);
this.disconnectAsync(); // force disconnect
});
}
}
}
readSerial();
readSerialLoop();
}
private stopSerialAsync() {
log(`stopping serial reader`)
log(`cancelling serial reader ${this.readSerialId}`)
this.readSerialId++;
return Promise.delay(200);
return pxt.Util.delay(200);
}
onSerial: (buf: Uint8Array, isStderr: boolean) => void;
private allocDAP() {
log(`alloc dap`);
const h = this.io;
this.dap = new DapJS.DAP({
write: writeAsync,
write: data => h.sendPacketAsync(new Uint8Array(data)),
close: this.disconnectAsync,
read: readAsync,
read: () => this.recvPacketAsync(),
//sendMany: sendMany
});
this.cmsisdap = (this.dap as any).dap;
this.cortexM = new DapJS.CortexM(this.dap);
}
const h = this.io;
const pbuf = this.pbuf;
function writeAsync(data: ArrayBuffer) {
//console.log("WR: " + pxt.Util.toHex(new Uint8Array(data)));
return h.sendPacketAsync(new Uint8Array(data));
get binName() {
return (this.usesCODAL ? "mbcodal-" : "mbdal-") + pxtc.BINARY_HEX;
}
unsupportedParts() {
if (!this.usesCODAL) {
return ["logotouch", "builtinspeaker", "microphone", "flashlog"]
}
return [];
}
async reconnectAsync(): Promise<void> {
log(`reconnect`)
this.flashAborted = false;
function stringResponse(buf: Uint8Array) {
return pxt.U.uint8ArrayToString(buf.slice(2, 2 + buf[1]))
}
function readAsync() {
return pbuf.shiftAsync();
await this.stopSerialAsync()
this.allocDAP(); // clean dap apis
await this.io.reconnectAsync()
// before calling into dapjs, we use our dapCmdNums() a few times, which which will make sure the responses
// to commends from previous sessions (if any) are flushed
const info = await this.dapCmdNums(0x00, 0x04) // info
const daplinkVersion = stringResponse(info)
log(`daplink version: ${daplinkVersion}`)
const r = await this.dapCmdNums(0x80)
this.usesCODAL = r[2] == 57 && r[3] == 57 && r[5] >= 51;
const binVersion = stringResponse(r);
log(`bin name: ${this.binName} v:${binVersion}`);
pxt.tickEvent("hid.flash.connect", { codal: this.usesCODAL ? 1 : 0, daplink: daplinkVersion, bin: binVersion });
const baud = new Uint8Array(5)
baud[0] = 0x82 // set baud
pxt.HF2.write32(baud, 1, 115200)
await this.dapCmd(baud)
// setting the baud rate on serial may reset NRF (depending on daplink version), so delay after
await pxt.Util.delay(200);
// only init after setting baud rate, in case we got reset
await this.cortexM.init()
const res = await this.readWords(0x10000010, 2);
this.pageSize = res[0]
this.numPages = res[1]
log(`page size ${this.pageSize}, num pages ${this.numPages}`);
await this.checkStateAsync(true);
await this.jacdacSetup();
this.startReadSerial();
}
private async checkStateAsync(resume?: boolean): Promise<void> {
const states = ["reset", "lockup", "sleeping", "halted", "running"]
try {
const state = await this.cortexM.getState();
log(`cortex state: ${states[state]}`)
if (resume && state == DapJS.CoreState.TARGET_HALTED)
await this.cortexM.resume();
} catch (e) {
log(`cortex state failed`)
pxt.tickEvent("hid.checkstate.error")
console.debug(e)
}
}
reconnectAsync(): Promise<void> {
log(`reconnect`)
// configure serial at 115200
return this.stopSerialAsync()
.then(() => this.io.reconnectAsync())
.then(() => this.cortexM.init())
.then(() => this.cmsisdap.cmdNums(0x80, []))
.then(r => {
this.binName = (r[2] == 57 && r[3] == 57 && r[5] >= 51 ? "mbcodal-" : "") + pxtc.BINARY_HEX
})
.then(() => this.cortexM.memory.readBlock(0x10000010, 2, this.pageSize))
.then(res => {
this.pageSize = pxt.HF2.read32(res, 0)
this.numPages = pxt.HF2.read32(res, 4)
})
.then(() => this.cmsisdap.cmdNums(0x82, [0x00, 0xC2, 0x01, 0x00]))
.then(() => this.startReadSerial());
private checkAborted() {
if (this.flashAborted)
throw new Error(lf("Download cancelled"));
}
disconnectAsync() {
log(`disconnect`)
this.flashAborted = true;
return this.stopSerialAsync()
.then(() => this.io.disconnectAsync());
}
@ -180,72 +303,195 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
log("reflash")
startTime = 0
pxt.tickEvent("hid.flash.start");
this.flashAborted = false;
this.flashing = true;
return (this.io.isConnected() ? Promise.resolve() : this.io.reconnectAsync())
.then(() => this.stopSerialAsync())
.then(() => this.cortexM.init())
.then(() => this.cortexM.reset(true))
.then(() => this.cortexM.memory.readBlock(0x10001014, 1, this.pageSize))
.then(v => {
if ((pxt.HF2.read32(v, 0) & 0xff) != 0) {
.then(() => this.checkStateAsync())
.then(() => this.readUICR())
.then(uicr => {
pxt.tickEvent("hid.flash.uicr", { uicr });
// shortcut, do a full flash
if (uicr != 0 || this.forceFullFlash) {
pxt.tickEvent("hid.flash.uicrfail");
return this.fullVendorCommandFlashAsync(resp);
}
return this.quickHidFlashAsync(resp);
// check flash checksums
return this.computeFlashChecksum(resp)
.then(chk => {
pxt.tickEvent("hid.flash.checksum", { quick: chk.quick ? 1 : 0, changed: chk.changed ? chk.changed.length : 0 });
// let's do a quick flash!
if (chk.quick)
return this.quickHidFlashAsync(chk.changed);
else
return this.fullVendorCommandFlashAsync(resp);
});
})
.then(() => this.checkStateAsync(true))
.then(() => pxt.tickEvent("hid.flash.success"))
.finally(() => { this.flashing = false })
.then(() => Promise.delay(100))
.then(() => this.disconnectAsync())
// don't disconnect here
// the micro:bit will automatically disconnect and reconnect
// via the webusb events
}
private recvPacketAsync() {
if (this.io.recvPacketAsync)
return this.io.recvPacketAsync()
else
return this.pbuf.shiftAsync()
}
private dapCmd(buf: Uint8Array) {
return this.io.sendPacketAsync(buf)
.then(() => this.recvPacketAsync())
.then(resp => {
if (resp[0] != buf[0]) {
pxt.tickEvent('hid.flash.cmderror', { req: buf[0], resp: resp[0] })
const msg = `bad dapCmd response: ${buf[0]} -> ${resp[0]}`
// in case we got an invalid response, try to get another response, in case the current
// response is a left-over from previous communications
log(msg + "; retrying")
return this.recvPacketAsync()
.then(resp => {
if (resp[0] == buf[0])
return resp
throw new Error(msg)
}, err => {
throw new Error(msg)
})
}
return resp
})
}
private dapCmdNums(...nums: number[]) {
return this.dapCmd(new Uint8Array(nums))
}
private fullVendorCommandFlashAsync(resp: pxtc.CompileResult): Promise<void> {
log("full flash")
pxt.tickEvent("hid.flash.full.start");
const chunkSize = 62;
let aborted = false;
return Promise.resolve()
let sentPages = 0;
return pxt.Util.promiseTimeout(
FULL_FLASH_TIMEOUT,
Promise.resolve()
.then(() => this.dapCmdNums(0x8A /* DAPLinkFlash.OPEN */, 1))
.then((res) => {
log(`daplinkflash open: ${pxt.U.toHex(res)}`)
if (res[1] !== 0) {
pxt.tickEvent('hid.flash.full.error.open', { res: res[1] })
throw new Error(lf("Download failed, please try again"));
}
const binFile = resp.outfiles[this.binName];
log(`bin file ${this.binName} in ${Object.keys(resp.outfiles).join(', ')}, ${binFile?.length || -1}b`)
const hexUint8 = pxt.U.stringToUint8Array(binFile);
log(`hex ${hexUint8?.byteLength || -1}b, ~${(hexUint8.byteLength / chunkSize) | 0} chunks of ${chunkSize}b`)
const sendPages = (offset: number = 0): Promise<void> => {
const end = Math.min(hexUint8.length, offset + chunkSize);
const nextPageData = hexUint8.slice(offset, end);
const cmdData = new Uint8Array(2 + nextPageData.length)
cmdData[0] = 0x8C /* DAPLinkFlash.WRITE */
cmdData[1] = nextPageData.length
cmdData.set(nextPageData, 2)
if (sentPages % 128 == 0) // reduce logging
log(`next page ${sentPages}: [${offset.toString(16)}, ${end.toString(16)}] (${Math.ceil((hexUint8.length - end) / 1000)}kb left)`)
return this.dapCmd(cmdData)
.then(() => {
this.checkAborted()
if (end < hexUint8.length) {
sentPages++;
return sendPages(end);
}
return Promise.resolve()
});
}
return sendPages();
})
.then(() => {
log(`close`)
return this.dapCmdNums(0x8B /* DAPLinkFlash.CLOSE */);
})
.then(res => {
log(`daplinkclose: ${pxt.U.toHex(res)}`)
return this.dapCmdNums(0x89 /* DAPLinkFlash.RESET */);
})
.then((res) => {
log(`daplinkreset: ${pxt.U.toHex(res)}`)
log(`full flash done`);
pxt.tickEvent("hid.flash.full.success");
}),
timeoutMessage
).catch((e) => {
log(`error: abort`)
pxt.tickEvent("hid.flash.full.error");
this.flashAborted = true;
return this.resetAndThrowAsync(e);
});
}
private resetAndThrowAsync(e: any) {
log(`reset on error`)
pxt.tickEvent("hid.flash.reset");
console.debug(e)
// reset any pending daplink
return this.dapCmdNums(0x89 /* DAPLinkFlash.RESET */)
.catch((e2: any) => {
// Best effort reset, no-op if there's an error
})
.then(() => this.cortexM.reset(false))
.catch((e2: any) => {
// Best effort reset, no-op if there's an error
})
.then(() => {
return this.cmsisdap.cmdNums(0x8A /* DAPLinkFlash.OPEN */, [1]);
})
.then((res) => {
const hexUint8 = pxt.U.stringToUint8Array(resp.outfiles[this.binName]);
const hexArray: number[] = Array.prototype.slice.call(hexUint8);
const sendPages = (offset: number = 0): Promise<void> => {
const end = Math.min(hexArray.length, offset + chunkSize);
const nextPage = hexArray.slice(offset, end);
nextPage.unshift(nextPage.length);
return this.cmsisdap.cmdNums(0x8C /* DAPLinkFlash.WRITE */, nextPage)
.then(() => {
if (!aborted && end < hexArray.length) {
return sendPages(end);
}
return Promise.resolve();
});
}
return sendPages();
})
.then((res) => {
return this.cmsisdap.cmdNums(0x8B /* DAPLinkFlash.CLOSE */, []);
})
.timeout(60000, timeoutMessage)
.catch((e) => {
aborted = true;
return this.cmsisdap.cmdNums(0x89 /* DAPLinkFlash.RESET */, [])
.catch((e2: any) => {
// Best effort reset, no-op if there's an error
})
.then(() => {
return Promise.reject(e);
});
throw e;
});
}
private quickHidFlashAsync(resp: pxtc.CompileResult): Promise<void> {
private readUICR() {
return this.readWords(0x10001014, 1)
.then(v => {
const uicr = v[0] & 0xff;
log(`uicr: ${uicr.toString(16)} (${v[0].toString(16)})`);
return uicr;
});
}
private computeFlashChecksum(resp: pxtc.CompileResult) {
const binFile = resp.outfiles[this.binName];
if (!binFile)
throw new Error(`unable to find ${this.binName} in outfiles ${Object.keys(resp.outfiles).join(', ')}`);
return this.getFlashChecksumsAsync()
.then(checksums => {
log(`checksums ${pxt.Util.toHex(checksums)}`);
// TODO this is seriously inefficient (130ms on a fast machine)
const uf2 = ts.pxtc.UF2.newBlockFile();
ts.pxtc.UF2.writeHex(uf2, binFile.split(/\r?\n/));
const bytes = pxt.U.stringToUint8Array(ts.pxtc.UF2.serializeFile(uf2));
const parsed = ts.pxtc.UF2.parseFile(bytes);
const aligned = DAPWrapper.pageAlignBlocks(parsed, this.pageSize);
const changed = DAPWrapper.onlyChanged(aligned, checksums, this.pageSize);
const quick = changed.length < aligned.length / 2;
log(`pages: ${aligned.length}, changed ${changed.length}, ${quick ? "quick" : "full"}`);
return {
quick,
changed
}
});
}
private quickHidFlashAsync(changed: ts.pxtc.UF2.Block[]): Promise<void> {
log("quick flash")
let logV = (msg: string) => { }
//let logV = log
let aborted = false;
pxt.tickEvent("hid.flash.quick.start");
const runFlash = (b: ts.pxtc.UF2.Block, dataAddr: number) => {
const cmd = this.cortexM.prepareCommand();
@ -266,45 +512,39 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
return cmd.go()
})
.then(() => {
logV("dbg en")
// starts the program
logV(`cortex.debug.enable`)
return this.cortexM.debug.enable()
})
}
let checksums: Uint8Array
return this.getFlashChecksumsAsync()
.then(buf => {
checksums = buf;
log("write code");
return this.cortexM.memory.writeBlock(loadAddr, flashPageBIN);
})
.then(() => {
log("convert");
// TODO this is seriously inefficient (130ms on a fast machine)
let uf2 = ts.pxtc.UF2.newBlockFile();
ts.pxtc.UF2.writeHex(uf2, resp.outfiles[this.binName].split(/\r?\n/));
let bytes = pxt.U.stringToUint8Array(ts.pxtc.UF2.serializeFile(uf2));
let parsed = ts.pxtc.UF2.parseFile(bytes);
let aligned = DAPWrapper.pageAlignBlocks(parsed, this.pageSize);
log(`initial: ${aligned.length} pages`);
aligned = DAPWrapper.onlyChanged(aligned, checksums, this.pageSize);
log(`incremental: ${aligned.length} pages`);
return Promise.mapSeries(pxt.U.range(aligned.length),
return pxt.Util.promiseTimeout(
PARTIAL_FLASH_TIMEOUT,
Promise.resolve()
.then(() => this.cortexM.memory.writeBlock(loadAddr, flashPageBIN))
.then(() => pxt.Util.promiseMapAllSeries(pxt.U.range(changed.length),
i => {
if (aborted) return Promise.resolve();
let b = aligned[i];
if (b.targetAddr >= 0x10000000)
this.checkAborted();
let b = changed[i];
if (b.targetAddr >= 0x10000000) {
log(`target address 0x${b.targetAddr.toString(16)} > 0x10000000`)
return Promise.resolve();
}
logV("about to write at 0x" + b.targetAddr.toString(16));
let writeBl = Promise.resolve();
log(`about to write at 0x${b.targetAddr.toString(16)}`);
let thisAddr = (i & 1) ? dataAddr : dataAddr + this.pageSize;
let nextAddr = (i & 1) ? dataAddr + this.pageSize : dataAddr;
let writeBl;
if (i == 0) {
let u32data = new Uint32Array(b.data.length / 4);
for (let i = 0; i < b.data.length; i += 4)
u32data[i >> 2] = pxt.HF2.read32(b.data, i);
writeBl = this.cortexM.memory.writeBlock(thisAddr, u32data);
}
if (i == 0) {
let u32data = new Uint32Array(b.data.length / 4);
@ -316,7 +556,7 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
return writeBl
.then(() => runFlash(b, thisAddr))
.then(() => {
let next = aligned[i + 1];
let next = changed[i + 1];
if (!next)
return Promise.resolve();
logV("write next");
@ -330,18 +570,21 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
.then(() => {
logV("done block");
});
})
.then(() => {
log("flash done");
pxt.tickEvent("hid.flash.done");
return this.cortexM.reset(false);
});
})
.timeout(25000, timeoutMessage)
.catch((e) => {
aborted = true;
return Promise.reject(e);
});
}))
.then(() => {
log("quick flash done");
return this.cortexM.reset(false);
})
.then(() => {
pxt.tickEvent("hid.flash.quick.success");
return this.checkStateAsync(true)
}),
timeoutMessage
).catch((e) => {
pxt.tickEvent("hid.flash.quick.error");
this.flashAborted = true;
return this.resetAndThrowAsync(e);
});
}
private getFlashChecksumsAsync() {
@ -352,6 +595,21 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
.then(() => this.cortexM.memory.readBlock(dataAddr, pages * 2, this.pageSize))
}
private readWords(addr: number, numWords: number) {
return this.cortexM.memory.readBlock(addr, numWords, this.pageSize)
// assume browser is little-endian
.then(u8 => new Uint32Array(u8.buffer))
}
private writeWords(addr: number, buf: Uint32Array) {
return this.cortexM.memory.writeBlock(addr, buf)
}
private readBytes(addr: number, numBytes: number) {
return this.cortexM.memory.readBlock(addr, (numBytes + 3) >> 2, this.pageSize)
.then(u8 => u8.length == numBytes ? u8 : u8.slice(0, numBytes))
}
static onlyChanged(blocks: ts.pxtc.UF2.Block[], checksums: Uint8Array, pageSize: number) {
return blocks.filter(b => {
let idx = b.targetAddr / pageSize
@ -392,6 +650,184 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
}
return res
}
//
// jacdac stuff starts here
//
private irqn: number
private xchgAddr: number = null
private lastXchg: number
private currSend: SendItem
private sendQ: SendItem[] = []
private lastSend: number
sendCustomEventAsync(type: string, buf: Uint8Array): Promise<void> {
if (type == "jacdac") {
if (this.xchgAddr == null)
return Promise.resolve()
if (buf.length & 3) {
const tmp = new Uint8Array((buf.length + 3) & ~3)
tmp.set(buf)
buf = tmp
}
return new Promise<void>(resolve => {
this.sendQ.push({
buf,
cb: resolve
})
})
}
return Promise.reject(new Error("invalid custom event type"))
}
private writeWord(addr: number, val: number) {
return this.cortexM.memory.write32(addr, val)
}
private async findJacdacXchgAddr() {
const memStart = 0x2000_0000
const memStop = memStart + 128 * 1024
const checkSize = 1024
let p0 = 0x20006000
let p1 = 0x20006000 + checkSize
const check = async (addr: number) => {
if (addr < memStart)
return null
if (addr + checkSize > memStop)
return null
const buf = await this.readWords(addr, checkSize >> 2)
for (let i = 0; i < buf.length; ++i) {
if (buf[i] == 0x786D444A && buf[i + 1] == 0xB0A6C0E9)
return addr + (i << 2)
}
return 0
}
while (true) {
const a0 = await check(p0)
if (a0) return a0
const a1 = await check(p1)
if (a1) return a1
if (a0 === null && a1 === null)
return null
p0 -= checkSize
p1 += checkSize
}
}
private async jacdacSetup() {
this.xchgAddr = null
if (!this.useJACDAC) {
log(`jacdac: disabled`)
return
}
await pxt.Util.delay(700); // wait for the program to start and setup memory correctly
const xchg = await this.findJacdacXchgAddr()
if (xchg == null) {
log("jacdac: xchg address not found")
pxt.tickEvent("hid.flash.jacdac.error.missingxchg");
return
}
const info = await this.readBytes(xchg, 16)
this.irqn = info[8]
if (info[12 + 2] != 0xff) {
log("jacdac: invalid memory; try power-cycling the micro:bit")
pxt.tickEvent("hid.flash.jacdac.error.invalidmemory");
console.debug({ info, xchg })
return
}
this.xchgAddr = xchg
// clear initial lock
await this.writeWord(xchg + 12, 0)
log(`jacdac: exchange address 0x${xchg.toString(16)}; irqn=${this.irqn}`)
pxt.tickEvent("hid.flash.jacdac.connected");
}
private async triggerIRQ(irqn: number) {
const addr = 0xE000E200 + (irqn >> 5) * 4
await this.writeWord(addr, 1 << (irqn & 31))
}
private async jacdacProcess(hadSerial: boolean) {
if (this.xchgAddr == null) {
if (!hadSerial)
await this.dapDelay(5000)
return
}
const now = Date.now()
if (this.lastXchg && now - this.lastXchg > 50) {
logV("slow xchg: " + (now - this.lastXchg) + "ms")
}
this.lastXchg = now
let numev = 0
// TODO only read say 32 bytes first, and more if needed
let inp = await this.readBytes(this.xchgAddr + 12, 256)
if (inp[2]) {
await this.writeWord(this.xchgAddr + 12, 0)
await this.triggerIRQ(this.irqn)
inp = inp.slice(0, inp[2] + 12)
this.onCustomEvent("jacdac", inp)
numev++
}
let sendFree = false
if (this.currSend) {
const send = await this.readBytes(this.xchgAddr + 12 + 256, 4)
if (!send[2]) {
this.currSend.cb()
this.currSend = null
sendFree = true
numev++
}
}
if (!this.currSend && this.sendQ.length) {
if (!sendFree) {
const send = await this.readBytes(this.xchgAddr + 12 + 256, 4)
if (!send[2])
sendFree = true
}
if (sendFree) {
this.currSend = this.sendQ.shift()
const bbody = this.currSend.buf.slice(4)
await this.writeWords(this.xchgAddr + 12 + 256 + 4, new Uint32Array(bbody.buffer))
const bhead = this.currSend.buf.slice(0, 4)
await this.writeWords(this.xchgAddr + 12 + 256, new Uint32Array(bhead.buffer))
await this.triggerIRQ(this.irqn)
this.lastSend = Date.now()
numev++
} else {
if (this.lastSend) {
const d = Date.now() - this.lastSend
if (d > 50) {
this.lastSend = 0
console.error("failed to send packet fast enough")
}
}
}
}
if (numev == 0 && !hadSerial)
await this.dapDelay(5000)
}
private dapDelay(micros: number) {
if (micros > 0xffff)
throw new Error("too large delay")
const cmd = new Uint8Array([0x09, 0, 0])
pxt.HF2.write16(cmd, 1, micros)
return this.dapCmd(cmd)
}
}
interface SendItem {
buf: Uint8Array
cb: () => void
}
export function mkDAPLinkPacketIOWrapper(io: pxt.packetio.PacketIO): pxt.packetio.PacketIOWrapper {

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2017",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
@ -12,6 +12,13 @@
"rootDir": ".",
"newLine": "LF",
"sourceMap": false,
"jsx": "react"
"jsx": "react",
"lib": [
"dom",
"dom.iterable",
"scripthost",
"es2017",
"ES2018.Promise"
]
}
}

View File

@ -1,6 +1,6 @@
{
"masterPicture": "docs/static/microbit.simplified.svg",
"iconsPath": "/static/icons",
"iconsPath": "/docs/static/icons",
"design": {
"ios": {
"pictureAspect": "backgroundAndMargin",

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2017",
"noImplicitAny": false,
"noImplicitReturns": true,
"module": "commonjs",

View File

@ -1,8 +1,58 @@
#include "MicroBitConfig.h"
#include "ble/UUID.h"
#include "BLEHF2Service.h"
#include "MicroBitEvent.h"
//================================================================
#if MICROBIT_CODAL
//================================================================
const uint8_t BLEHF2Service::service_base_uuid[ 16] =
{ 0xb1,0x12,0x00,0x00,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49 };
const uint8_t BLEHF2Service::char_base_uuid[ 16] =
{ 0xb1,0x12,0x00,0x00,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a };
const uint16_t BLEHF2Service::serviceUUID = 0xf5e6;
const uint16_t BLEHF2Service::charUUID[ mbbs_cIdxCOUNT] = { 0xf5e6 };
BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
ble(_ble)
{
// Initialise our characteristic values.
memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));
// Register the base UUID and create the service.
RegisterBaseUUID( service_base_uuid);
CreateService( serviceUUID);
RegisterBaseUUID( char_base_uuid);
CreateCharacteristic( mbbs_cIdxMESSAGE, charUUID[ mbbs_cIdxMESSAGE],
(uint8_t *)&txCharacteristicMessage,
sizeof(txCharacteristicMessage), sizeof(txCharacteristicMessage),
microbit_propNOTIFY);
}
void BLEHF2Service::sendSerial(const char *data, int len, bool isError) {
if (getConnected())
{
int32_t sent = 0;
while(sent < len) {
int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);
txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;
memcpy(&txCharacteristicMessage.data, data + sent, n);
notifyChrValue(mbbs_cIdxMESSAGE,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
sent += n;
}
}
}
//================================================================
#else // MICROBIT_CODAL
//================================================================
#include "ble/UUID.h"
BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
ble(_ble)
{
@ -47,4 +97,8 @@ const uint8_t BLEHF2ServiceUUID[] = {
const uint8_t BLEHF2TxCharacteristicUUID[] = {
0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a
};
};
//================================================================
#endif // MICROBIT_CODAL
//================================================================

View File

@ -2,7 +2,6 @@
#define BLE_HF2_SERVICE_H
#include "MicroBitConfig.h"
#include "ble/BLE.h"
#include "MicroBitThermometer.h"
#include "EventModel.h"
#include "pxt.h"
@ -22,6 +21,65 @@ struct BLEHF2Packet {
uint8_t data[BLEHF2_DATA_LENGTH];
};
//================================================================
#if MICROBIT_CODAL
//================================================================
#include "MicroBitBLEManager.h"
#include "MicroBitBLEService.h"
class BLEHF2Service : public MicroBitBLEService
{
public:
/**
* Constructor.
* Create a representation of the TemperatureService
* @param _ble The instance of a BLE device that we're running on.
*/
BLEHF2Service(BLEDevice &_ble);
/**
* Sends text
*/
void sendSerial(const char *data, int len, bool isError);
private:
// Bluetooth stack we're running on.
BLEDevice &ble;
// memory for buffers.
BLEHF2Packet txCharacteristicMessage;
// Index for each charactersitic in arrays of handles and UUIDs
typedef enum mbbs_cIdx
{
mbbs_cIdxMESSAGE,
mbbs_cIdxCOUNT
} mbbs_cIdx;
// UUIDs for our service and characteristics
static const uint8_t service_base_uuid[ 16];
static const uint8_t char_base_uuid[ 16];
static const uint16_t serviceUUID;
static const uint16_t charUUID[ mbbs_cIdxCOUNT];
// Data for each characteristic when they are held by Soft Device.
MicroBitBLEChar chars[ mbbs_cIdxCOUNT];
public:
int characteristicCount() { return mbbs_cIdxCOUNT; };
MicroBitBLEChar *characteristicPtr( int idx) { return &chars[ idx]; };
};
//================================================================
#else // MICROBIT_CODAL
//================================================================
#include "ble/BLE.h"
class BLEHF2Service
{
public:
@ -50,5 +108,8 @@ class BLEHF2Service
GattAttribute::Handle_t txCharacteristicHandle;
};
//================================================================
#endif // MICROBIT_CODAL
//================================================================
#endif
#endif

View File

@ -14,7 +14,7 @@ namespace bluetooth {
BLEHF2Service* pHF2 = NULL;
//%
void __log(String msg) {
void __log(int priority, String msg) {
if (NULL == pHF2)
pHF2 = new BLEHF2Service(*uBit.ble);
pHF2->sendSerial(msg->getUTF8Data(), msg->getUTF8Size(), false);
@ -125,19 +125,18 @@ namespace bluetooth {
startUartService();
int bytes = uart->rxBufferedSize();
auto buffer = mkBuffer(NULL, bytes);
auto res = buffer;
registerGCObj(buffer);
int read = uart->read(buffer->data, buffer->length);
// read failed
if (read < 0) {
decrRC(buffer);
return mkBuffer(NULL, 0);
res = mkBuffer(NULL, 0);
} else if (read != buffer->length) {
// could not fill the buffer
res = mkBuffer(buffer->data, read);
}
// could not fill the buffer
if (read != buffer->length) {
auto tmp = mkBuffer(buffer->data, read);
decrRC(buffer);
buffer = tmp;
}
return buffer;
unregisterGCObj(buffer);
return res;
}
/**
@ -184,6 +183,7 @@ namespace bluetooth {
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
//% parts=bluetooth weight=11 blockGap=8
//% help=bluetooth/advertise-url blockExternalInputs=1
//% hidden=1 deprecated=1
void advertiseUrl(String url, int power, bool connectable) {
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL)
power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));
@ -199,7 +199,7 @@ namespace bluetooth {
* @param power power level between 0 and 7, eg: 7
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
*/
//% parts=bluetooth weight=12 advanced=true
//% parts=bluetooth weight=12 advanced=true deprecated=1
void advertiseUidBuffer(Buffer nsAndInstance, int power, bool connectable) {
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID)
auto buf = nsAndInstance;
@ -227,6 +227,7 @@ namespace bluetooth {
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
//% parts=bluetooth weight=10
//% help=bluetooth/stop-advertising advanced=true
//% hidden=1 deprecated=1
void stopAdvertising() {
uBit.bleManager.stopAdvertising();
}

View File

@ -10,10 +10,10 @@ namespace bluetooth {
* Internal use
*/
//% shim=bluetooth::__log
export function __log(msg: string) {
export function __log(priority: number, msg: string) {
return;
}
console.addListener(function (msg) { __log(msg) });
console.addListener(function (_pri, msg) { __log(_pri, msg) });
/**
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
@ -78,6 +78,7 @@ namespace bluetooth {
//% blockId=eddystone_advertise_uid block="bluetooth advertise UID|namespace (bytes 6-9)%ns|instance (bytes 2-6)%instance|with power %power|connectable %connectable"
//% parts=bluetooth weight=12 blockGap=8
//% help=bluetooth/advertise-uid blockExternalInputs=1
//% hidden=1 deprecated=1
export function advertiseUid(ns: number, instance: number, power: number, connectable: boolean) {
const buf = pins.createBuffer(16);
buf.setNumber(NumberFormat.Int32BE, 6, ns);

View File

@ -10,12 +10,13 @@
"BLEHF2Service.h",
"BLEHF2Service.cpp"
],
"weight": 10,
"searchOnly": true,
"icon": "./static/packages/bluetooth/icon.png",
"public": true,
"dependencies": {
"core": "file:../core"
},
"disablesVariants": ["mbcodal"],
"yotta": {
"config": {
"microbit-dal": {
@ -29,7 +30,18 @@
"stack_size": 1280,
"gatt_table_size": "0x700"
}
}
},
"installedVersion": "vzlhfd"
}
},
"userConfigs": [
{
"description": "Disable Bluetooth Event Service",
"config": {
"microbit-dal": {
"bluetooth": {
"event_service": 0
}
}
}
}
]
}
}

View File

@ -109,7 +109,8 @@ declare namespace bluetooth {
*/
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
//% parts=bluetooth weight=11 blockGap=8
//% help=bluetooth/advertise-url blockExternalInputs=1 shim=bluetooth::advertiseUrl
//% help=bluetooth/advertise-url blockExternalInputs=1
//% hidden=1 deprecated=1 shim=bluetooth::advertiseUrl
function advertiseUrl(url: string, power: int32, connectable: boolean): void;
/**
@ -118,7 +119,7 @@ declare namespace bluetooth {
* @param power power level between 0 and 7, eg: 7
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
*/
//% parts=bluetooth weight=12 advanced=true shim=bluetooth::advertiseUidBuffer
//% parts=bluetooth weight=12 advanced=true deprecated=1 shim=bluetooth::advertiseUidBuffer
function advertiseUidBuffer(nsAndInstance: Buffer, power: int32, connectable: boolean): void;
/**
@ -134,7 +135,8 @@ declare namespace bluetooth {
*/
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
//% parts=bluetooth weight=10
//% help=bluetooth/stop-advertising advanced=true shim=bluetooth::stopAdvertising
//% help=bluetooth/stop-advertising advanced=true
//% hidden=1 deprecated=1 shim=bluetooth::stopAdvertising
function stopAdvertising(): void;
}

View File

@ -4,6 +4,7 @@
"AcceleratorRange.OneG": "The accelerator measures forces up to 1 gravity",
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
"Array": "Add, remove, and replace items in lists.",
"Array._pickRandom": "Return a random value from the array",
"Array._popStatement": "Remove the last element from an array and return it.",
"Array._removeAtStatement": "Remove the element at a certain index.",
"Array._shiftStatement": "Remove the first element from an array and return it. This method changes the length of the array.",
@ -41,6 +42,7 @@
"Array.reverse": "Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.",
"Array.set": "Store a value at a particular index",
"Array.set|param|index": "the zero-based position in the list to store the value, eg: 0",
"Array.set|param|value": "the value to insert, eg: 0",
"Array.shift": "Remove the first element from an array and return it. This method changes the length of the array.",
"Array.slice": "Return a section of an array.",
"Array.slice|param|end": "The end of the specified portion of the array. eg: 0",
@ -124,9 +126,15 @@
"Image.showFrame": "Show a particular frame of the image strip.",
"Image.showFrame|param|frame": "image frame to show",
"Image.showImage": "Shows an frame from the image at offset ``x offset``.",
"Image.showImage|param|interval": "time in milliseconds to pause after drawing",
"Image.showImage|param|xOffset": "column index to start displaying the image",
"Image.width": "Gets the width in columns",
"Infinity": "Constant representing positive infinity.",
"JSON.parse": "Converts a JavaScript Object Notation (JSON) string into an object.",
"JSON.stringify": "Converts a JavaScript value to a JavaScript Object Notation (JSON) string.",
"JSON.stringify|param|indent": "Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.",
"JSON.stringify|param|replacer": "Not supported; use null.",
"JSON.stringify|param|value": "A JavaScript value, usually an object or array, to be converted.",
"Math": "More complex operations with numbers.",
"Math.abs": "Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5.",
"Math.abs|param|x": "A numeric expression for which the absolute value is needed.",
@ -225,7 +233,7 @@
"String.split": "Splits the string according to the separators",
"String.split|param|separator": "@param limit",
"String.substr": "Return a substring of the current string.",
"String.substr|param|length": "number of characters to extract",
"String.substr|param|length": "number of characters to extract, eg: 10",
"String.substr|param|start": "first character index; can be negative from counting from the end, eg:0",
"String.toLowerCase": "Converts the string to lower case characters.",
"String.trim": "Return a substring of the current string with whitespace removed from both ends",
@ -245,11 +253,15 @@
"basic.pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000",
"basic.plotLeds": "Draws an image on the LED screen.",
"basic.plotLeds|param|leds": "pattern of LEDs to turn on/off",
"basic.rgb": "Converts red, green, blue channels into a RGB color",
"basic.rgbw": "Converts red, green, blue channels into a RGB color",
"basic.rgbw|param|blue": "value of the blue channel between 0 and 255. eg: 255",
"basic.rgbw|param|green": "value of the green channel between 0 and 255. eg: 255",
"basic.rgbw|param|red": "value of the red channel between 0 and 255. eg: 255",
"basic.rgbw|param|white": "value of the white channel between 0 and 255. eg: 0",
"basic.rgb|param|blue": "value of the blue channel between 0 and 255. eg: 255",
"basic.rgb|param|green": "value of the green channel between 0 and 255. eg: 255",
"basic.rgb|param|red": "value of the red channel between 0 and 255. eg: 255",
"basic.setLedColor": "Sets the color on the build-in LED. Set to 0 to turn off.",
"basic.showAnimation": "Shows a sequence of LED screens as an animation.",
"basic.showAnimation|param|interval": "time in milliseconds between each redraw",
@ -280,31 +292,48 @@
"console.logValue": "Write a name:value pair as a line of text to the console output.",
"console.logValue|param|name": "name of the value stream, eg: \"x\"",
"console.logValue|param|value": "to write",
"console.log|param|value": "to send",
"console.minPriority": "Minimum priority to send messages to listeners",
"console.removeListener": "Removes a listener",
"control": "Runtime and event utilities.",
"control.allocateNotifyEvent": "Allocates the next user notification event",
"control.assert": "If the condition is false, display msg on serial console, and panic with code 098.",
"control.benchmark": "Runs the function and returns run time in microseconds.",
"control.createBuffer": "Create a new zero-initialized buffer.",
"control.createBufferFromUTF8": "Create a new buffer with UTF8-encoded string",
"control.createBufferFromUTF8|param|str": "the string to put in the buffer",
"control.createBuffer|param|size": "number of bytes in the buffer",
"control.deviceLongSerialNumber": "Derive a unique, consistent 64-bit serial number of this device from internal data.",
"control.deviceName": "Make a friendly name for the device based on its serial number",
"control.deviceSerialNumber": "Derive a unique, consistent serial number of this device from internal data.",
"control.dmesg": "Write a message to DMESG debugging buffer.",
"control.dmesgPerfCounters": "Dump values of profiling performance counters.",
"control.dmesgPtr": "Write a message and value (pointer) to DMESG debugging buffer.",
"control.enablePerfCounter": "Enable profiling for current function.",
"control.eventSourceId": "Returns the value of a C++ runtime constant",
"control.eventTimestamp": "Gets the timestamp of the last event executed on the bus",
"control.eventValue": "Gets the value of the last event executed on the bus",
"control.eventValueId": "Returns the value of a C++ runtime constant",
"control.gc": "Force GC and dump basic information about heap.",
"control.gcStats": "Get various statistics about the garbage collector (GC)",
"control.heapDump": "Force GC and halt waiting for debugger to do a full heap dump.",
"control.heapSnapshot": "Record a heap snapshot to debug memory leaks.",
"control.inBackground": "Schedules code that run in the background.",
"control.micros": "Gets current time in microseconds. Overflows every ~18 minutes.",
"control.millis": "Gets the number of milliseconds elapsed since power on.",
"control.onEvent": "Registers an event handler.",
"control.panic": "Display specified error code and stop the program.",
"control.profilingEnabled": "Return true if profiling is enabled in the current build.",
"control.raiseEvent": "Raises an event in the event bus.",
"control.raiseEvent|param|mode": "optional definition of how the event should be processed after construction (default is CREATE_AND_FIRE).",
"control.raiseEvent|param|src": "ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.",
"control.raiseEvent|param|value": "Component specific code indicating the cause of the event.",
"control.ramSize": "Returns estimated size of memory in bytes.",
"control.reset": "Resets the BBC micro:bit.",
"control.runInParallel": "Run other code in the parallel.",
"control.runtimeWarning": "Display warning in the simulator.",
"control.setDebugFlags": "Set flags used when connecting an external debugger.",
"control.simmessages.onReceived": "Registers the handler for a message on a given channel",
"control.waitForEvent": "Blocks the calling thread until the specified event is raised.",
"control.waitMicros": "Blocks the current fiber for the given microseconds",
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
@ -398,41 +427,42 @@
"images": "Creation, manipulation and display of LED images.",
"images.createBigImage": "Creates an image with 2 frames.",
"images.createImage": "Creates an image that fits on the LED screen.",
"input": "Events and data from sensors",
"input": "Events and data from sensors\n\r\nEvents and data from sensors",
"input.acceleration": "Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)",
"input.acceleration|param|dimension": "x, y, or z dimension, eg: Dimension.X",
"input.assumeCalibrationCompass": "Obsolete, compass calibration is automatic.",
"input.buttonEventValueId": "Returns the value of a C++ runtime constant",
"input.buttonIsPressed": "Get the button state (pressed or not) for ``A`` and ``B``.",
"input.buttonIsPressed|param|button": "the button to query the request, eg: Button.A",
"input.calibrate": "Obsolete, use input.calibrateCompass instead.",
"input.calibrateCompass": "Obsolete, compass calibration is automatic.",
"input.clearCalibrationCompass": "Obsolete, compass calibration is automatic.",
"input.compassHeading": "Get the current compass heading in degrees.",
"input.isCalibratedCompass": "Returns 'true' when the compass is calibrated. Otherwise returns 'false'.",
"input.isGesture": "Tests if a gesture is currently detected.",
"input.isGesture|param|gesture": "the type of gesture to detect, eg: Gesture.Shake",
"input.lightLevel": "Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.",
"input.loudness": "gets the level of loudness from 0 (silent) to 255 (loud)",
"input.magneticForce": "Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.",
"input.magneticForce|param|dimension": "the x, y, or z dimension, eg: Dimension.X",
"input.onButtonEvent": "Do something when a button (A, B or both A+B) receives an event.",
"input.onButtonEvent|param|body": "code to run when event is raised",
"input.onButtonEvent|param|button": "the button",
"input.onButtonEvent|param|eventType": "event Type",
"input.onButtonPressed": "Do something when a button (A, B or both A+B) is pushed down and released again.",
"input.onButtonPressed|param|body": "code to run when event is raised",
"input.onButtonPressed|param|button": "the button that needs to be pressed",
"input.onGesture": "Do something when when a gesture is done (like shaking the micro:bit).",
"input.onGesture|param|body": "code to run when gesture is raised",
"input.onGesture|param|gesture": "the type of gesture to track, eg: Gesture.Shake",
"input.onLogoDown": "Attaches code to run when the logo is oriented downwards and the board is vertical.",
"input.onLogoDown|param|body": "TODO",
"input.onLogoUp": "Attaches code to run when the logo is oriented upwards and the board is vertical.",
"input.onLogoUp|param|body": "TODO",
"input.onPinPressed": "Do something when a pin is touched and released again (while also touching the GND pin).",
"input.onPinPressed|param|body": "the code to run when the pin is pressed",
"input.onPinPressed|param|name": "the pin that needs to be pressed, eg: TouchPin.P0",
"input.onPinReleased": "Do something when a pin is released.",
"input.onPinReleased|param|body": "the code to run when the pin is released",
"input.onPinReleased|param|name": "the pin that needs to be released, eg: TouchPin.P0",
"input.onScreenDown": "Attaches code to run when the screen is facing down.",
"input.onScreenDown|param|body": "TODO",
"input.onScreenUp": "Attaches code to run when the screen is facing up.",
"input.onScreenUp|param|body": "TODO",
"input.onShake": "Attaches code to run when the device is shaken.",
"input.onShake|param|body": "TODO",
"input.onPinTouchEvent": "Do something when a pin receives an touch event (while also touching the GND pin).",
"input.onPinTouchEvent|param|body": "the code to run when event is fired on pin",
"input.onPinTouchEvent|param|name": "the pin, eg: TouchPin.P0",
"input.pinIsPressed": "Get the pin state (pressed or not). Requires to hold the ground to close the circuit.",
"input.pinIsPressed|param|name": "pin used to detect the touch, eg: TouchPin.P0",
"input.rotation": "The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.",
@ -441,7 +471,7 @@
"input.runningTimeMicros": "Gets the number of microseconds elapsed since power on.",
"input.setAccelerometerRange": "Sets the accelerometer sample range in gravities.",
"input.setAccelerometerRange|param|range": "a value describe the maximum strengh of acceleration measured",
"input.soundLevel": "gets the level of loudness in 0-100%",
"input.soundLevel": "gets the level of loudness from 0 (silent) to 255 (loud)",
"input.temperature": "Gets the temperature in Celsius degrees (°C).",
"led": "Control of the LED screen.",
"led.brightness": "Get the screen brightness from 0 (off) to 255 (full bright).",
@ -482,7 +512,10 @@
"led.unplot|param|x": "the horizontal coordinate of the LED",
"led.unplot|param|y": "the vertical coordinate of the LED",
"light.sendWS2812Buffer": "Sends a color buffer to a light strip",
"light.sendWS2812BufferWithBrightness": "Sends a color buffer to a light strip",
"light.setMode": "Sets the light mode of a pin",
"loops.everyInterval": "Repeats the code forever in the background.\nAfter each iteration, allows other codes to run for a set duration\nso that it runs on a timer",
"loops.everyInterval|param|interval": "time (in ms) to wait between each iteration of the action.",
"motors": "Blocks to control the onboard motors",
"motors.dualMotorPower": "Controls two motors attached to the board. Switches to dual-motor mode!",
"motors.motorCommand": "Send break, coast or sleep commands to the motor. Has no effect in dual-motor mode.",
@ -522,6 +555,7 @@
"music.startMelody": "Starts playing a melody.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
"music.startMelody|param|melodyArray": "the melody array to play",
"music.startMelody|param|options": "melody options, once / forever, in the foreground / background",
"music.stopAllSounds": "Stop all sounds and melodies currently playing.",
"music.stopMelody": "Stops the melodies",
"music.stopMelody|param|options": "which melody to stop",
"music.tempo": "Returns the tempo in beats per minute. Tempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play.",
@ -531,6 +565,9 @@
"parseInt|param|radix": "optional A value between 2 and 36 that specifies the base of the number in text.",
"parseInt|param|text": "A string to convert into an integral number. eg: \"123\"",
"pause": "Pause for the specified time in milliseconds",
"pauseUntil": "Busy wait for a condition to be true",
"pauseUntil|param|condition": "condition to test for",
"pauseUntil|param|timeOut": "if positive, maximum duration to wait for in milliseconds",
"pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000",
"pins": "Control currents in Pins for analog/digital signals, servos, i2c, ...",
"pins.C10": "Pin C10",
@ -597,9 +634,12 @@
"pins.servoWritePin": "Write a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).",
"pins.servoWritePin|param|name": "pin to write to, eg: AnalogPin.P1",
"pins.servoWritePin|param|value": "angle or rotation speed, eg:180,90,0",
"pins.setAudioPin": "Set the pin used when producing sounds and melodies. Default is P0.",
"pins.setAudioPin|param|name": "pin to modulate pitch from",
"pins.setEvents": "Configure the events emitted by this pin. Events can be subscribed to\nusing ``control.onEvent()``.",
"pins.setEvents|param|name": "pin to set the event mode on, eg: DigitalPin.P0",
"pins.setEvents|param|type": "the type of events for this pin to emit, eg: PinEventType.Edge",
"pins.setMatrixWidth": "Set the matrix width for Neopixel strip (already assigned to a pin).\nShould be used in conjunction with `set matrix width` from Neopixel package.",
"pins.setPull": "Configure the pull directiion of of a pin.",
"pins.setPull|param|name": "pin to set the pull mode on, eg: DigitalPin.P0",
"pins.setPull|param|pull": "one of the mbed pull configurations, eg: PinPullMode.PullUp",
@ -622,8 +662,8 @@
"serial.delimiters": "Return the corresponding delimiter string",
"serial.onDataReceived": "Register an event to be fired when one of the delimiter is matched.",
"serial.onDataReceived|param|delimiters": "the characters to match received characters against.",
"serial.readBuffer": "Read multiple characters from the receive buffer. Pause until enough characters are present.",
"serial.readBuffer|param|length": "default buffer length, eg: 64",
"serial.readBuffer": "Read multiple characters from the receive buffer. \nIf length is positive, pauses until enough characters are present.",
"serial.readBuffer|param|length": "default buffer length",
"serial.readLine": "Read a line of text from the serial port.",
"serial.readString": "Read the buffered received data as a string",
"serial.readUntil": "Read a line of text from the serial port and return the buffer when the delimiter is met.",

View File

@ -7,6 +7,7 @@
"AcceleratorRange.OneG|block": "1g",
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
"AcceleratorRange.TwoG|block": "2g",
"Array._pickRandom|block": "get random value from %list",
"Array._popStatement|block": "remove last value from %list",
"Array._removeAtStatement|block": "%list| remove value at %index",
"Array._shiftStatement|block": "remove first value from %list",
@ -49,6 +50,10 @@
"BeatFraction.Whole|block": "1",
"Buffer|block": "Buffer",
"Button.AB|block": "A+B",
"ButtonEvent.Click|block": "clicked",
"ButtonEvent.Down|block": "pressed down",
"ButtonEvent.LongClick|block": "long clicked",
"ButtonEvent.Up|block": "released up",
"Colors.Blue|block": "blue",
"Colors.Green|block": "green",
"Colors.Indigo|block": "indigo",
@ -112,46 +117,24 @@
"IconNames.ArrowSouth|block": "arrow south",
"IconNames.ArrowWest|block": "arrow west",
"IconNames.Asleep|block": "asleep",
"IconNames.Butterfly|block": "butterfly",
"IconNames.Chessboard|block": "chess board",
"IconNames.Confused|block": "confused",
"IconNames.Cow|block": "cow",
"IconNames.Diamond|block": "diamond",
"IconNames.Duck|block": "duck",
"IconNames.EigthNote|block": "eigth note",
"IconNames.Fabulous|block": "fabulous",
"IconNames.Ghost|block": "ghost",
"IconNames.Giraffe|block": "giraffe",
"IconNames.Happy|block": "happy",
"IconNames.Heart|block": "heart",
"IconNames.House|block": "house",
"IconNames.LeftTriangle|block": "left triangle",
"IconNames.Meh|block": "meh",
"IconNames.No|block": "no",
"IconNames.Pitchfork|block": "pitchfork",
"IconNames.QuarterNote|block": "quarter note",
"IconNames.Rabbit|block": "rabbit",
"IconNames.Rollerskate|block": "roller skate",
"IconNames.Sad|block": "sad",
"IconNames.Scissors|block": "scissors",
"IconNames.Silly|block": "silly",
"IconNames.Skull|block": "skull",
"IconNames.SmallDiamond|block": "small diamond",
"IconNames.SmallHeart|block": "small heart",
"IconNames.SmallSquare|block": "small square",
"IconNames.Snake|block": "snake",
"IconNames.Square|block": "square",
"IconNames.StickFigure|block": "stick figure",
"IconNames.Surprised|block": "surprised",
"IconNames.Sword|block": "sword",
"IconNames.TShirt|block": "t-shirt",
"IconNames.Target|block": "target",
"IconNames.Tortoise|block": "tortoise",
"IconNames.Triangle|block": "triangle",
"IconNames.Umbrella|block": "umbrella",
"IconNames.Yes|block": "yes",
"Image.scrollImage|block": "scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay",
"Image.showImage|block": "show image %sprite(myImage)|at offset %offset",
"Image.scrollImage|block": "scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %interval",
"Image.showImage|block": "show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval",
"JSON|block": "JSON",
"LedSpriteProperty.Blink|block": "blink",
"LedSpriteProperty.Brightness|block": "brightness",
"LedSpriteProperty.Direction|block": "direction",
@ -264,13 +247,14 @@
"basic.forever|block": "forever",
"basic.pause|block": "pause (ms) %pause",
"basic.rgbw|block": "red %red|green %green|blue %blue|white %white",
"basic.rgb|block": "red %red|green %green|blue %blue",
"basic.setLedColor|block": "set led to %color=colorNumberPicker",
"basic.showArrow|block": "show arrow %i=device_arrow",
"basic.showCompass|block": "show compass needle for $interval|ms",
"basic.showIcon|block": "show icon %i",
"basic.showIcon|block": "show icon %i || for %interval ms",
"basic.showLeds|block": "show leds",
"basic.showNumber|block": "show|number %number",
"basic.showString|block": "show|string %text",
"basic.showNumber|block": "show|number %number || in an interval of %interval ms",
"basic.showString|block": "show|string %text || in an interval of %interval ms",
"basic.turnRgbLedOff|block": "turn build-in LED off",
"basic|block": "basic",
"console|block": "console",
@ -315,28 +299,34 @@
"game.startCountdown|block": "start countdown|(ms) %duration",
"game|block": "game",
"images.arrowImage|block": "arrow image %i",
"images.arrowNumber|block": "%arrow",
"images.createBigImage|block": "create big image",
"images.createImage|block": "create image",
"images.iconImage|block": "icon image %i",
"images|block": "images",
"input.acceleration|block": "acceleration (mg)|%NAME",
"input.assumeCalibrationCompass|block": "assume calibration compass",
"input.buttonEventValueId|block": "%id",
"input.buttonIsPressed|block": "button|%NAME|is pressed",
"input.calibrateCompass|block": "calibrate compass",
"input.clearCalibrationCompass|block": "clear calibration compass",
"input.compassHeading|block": "compass heading (°)",
"input.isCalibratedCompass|block": "is compass calibrated",
"input.isGesture|block": "is %gesture gesture",
"input.lightLevel|block": "light level",
"input.loudness|block": "Loudness",
"input.magneticForce|block": "magnetic force (µT)|%NAME",
"input.onButtonEvent|block": "on button %NAME| %eventType=control_button_event_value_id",
"input.onButtonPressed|block": "on button|%NAME|pressed",
"input.onGesture|block": "on |%NAME",
"input.onPinPressed|block": "on pin %name|pressed",
"input.onPinReleased|block": "on pin %NAME|released",
"input.onPinTouchEvent|block": "on pin %name| %eventType=control_button_event_value_id",
"input.pinIsPressed|block": "pin %NAME|is pressed",
"input.rotation|block": "rotation (°)|%NAME",
"input.runningTimeMicros|block": "running time (micros)",
"input.runningTime|block": "running time (ms)",
"input.setAccelerometerRange|block": "set accelerometer|range %range",
"input.soundLevel|block": "Loudness",
"input.soundLevel|block": "soundLevel",
"input.temperature|block": "temperature (°C)",
"input|block": "input",
"led.brightness|block": "brightness",
@ -353,6 +343,8 @@
"led.unplot|block": "unplot|x %x|y %y",
"led|block": "led",
"light|block": "light",
"loops.everyInterval|block": "every $interval ms",
"loops|block": "loops",
"motors.dualMotorPower|block": "motor %motor|at %percent \\%",
"motors.motorCommand|block": "motor %command",
"motors.motorPower|block": "motor on at %percent \\%",
@ -371,6 +363,7 @@
"music.setTempo|block": "set tempo to (bpm)|%value",
"music.setVolume|block": "set volume %volume",
"music.startMelody|block": "start melody %melody=device_builtin_melody| repeating %options",
"music.stopAllSounds|block": "stop all sounds",
"music.stopMelody|block": "stop melody $options",
"music.tempo|block": "tempo (bpm)",
"music.volume|block": "volume",
@ -394,7 +387,9 @@
"pins.pulseIn|block": "pulse in (µs)|pin %name|pulsed %value",
"pins.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %micros",
"pins.servoWritePin|block": "servo write|pin %name|to %value",
"pins.setAudioPin|block": "set audio pin $name",
"pins.setEvents|block": "set pin %pin|to emit %type|events",
"pins.setMatrixWidth|block": "neopixel matrix width|pin %pin %width",
"pins.setPull|block": "set pull|pin %pin|to %pull",
"pins.spiFormat|block": "spi format|bits %bits|mode %mode",
"pins.spiFrequency|block": "spi frequency %frequency",
@ -438,8 +433,10 @@
"{id:category}Image": "Image",
"{id:category}Images": "Images",
"{id:category}Input": "Input",
"{id:category}JSON": "JSON",
"{id:category}Led": "Led",
"{id:category}Light": "Light",
"{id:category}Loops": "Loops",
"{id:category}Math": "Math",
"{id:category}MicrobitPin": "MicrobitPin",
"{id:category}Motors": "Motors",
@ -454,11 +451,19 @@
"{id:category}Text": "Text",
"{id:category}_py": "_py",
"{id:group}Configuration": "Configuration",
"{id:group}Control": "Control",
"{id:group}Events": "Events",
"{id:group}LED matrix": "LED matrix",
"{id:group}Melody": "Melody",
"{id:group}Melody Advanced": "Melody Advanced",
"{id:group}Modify": "Modify",
"{id:group}Operations": "Operations",
"{id:group}RGB LED": "RGB LED",
"{id:group}Read": "Read",
"{id:group}Sensors": "Sensors",
"{id:group}Silence": "Silence",
"{id:group}States": "States",
"{id:group}System": "System",
"{id:group}Tempo": "Tempo",
"{id:group}Tone": "Tone",
"{id:group}Volume": "Volume"

View File

@ -1,210 +1,214 @@
{
"Math.abs": "Gibt den absoluten Wert einer Zahl aus (den Wert unabhängig davon, ob er positiv oder negativ ist).\nDer absolute Wert von -5 ist zum Beispiel der gleiche wie der von 5.",
"Math.abs|param|x": "Ein numerischer Ausdruck, für den der absolute Wert benötigt wird.",
"Math.max": "Gibt den größeren von zwei vorhandenen numerischen Ausdrücken aus.",
"Math.min": "Gibt den niedrigeren von zwei vorhandenen numerischen Ausdrücken aus.",
"Math.pow": "Gibt den Wert eines grundlegenden Ausdrucks bis zu einer bestimmten Stärke aus.",
"Math.pow|param|x": "Der Basiswert des Ausdrucks.",
"Math.pow|param|y": "Der exponentielle Wert des Ausdrucks.",
"Math.random": "Gibt eine pseudozufüllige Zahl zwischen 0 und `max`aus.",
"Math.randomBoolean": "Erzeugt zufällig einen \"wahr\" oder \"falsch\"-Wert, wie bei einem Münzwurf.",
"Math.sign": "Gibt das Vorzeichen von x aus und zeigt an, ob dieses positiv, negativ oder null ist.",
"Math.sign|param|x": "Der numerische Ausdruck, der getestet werden soll",
"Math.sqrt": "Gibt die Quadratwurzel einer Zahl aus.",
"Math.sqrt|param|x": "Ein numerischer Ausdruck.",
"String.charAt": "Gibt den Buchstaben beim angegebenen Index aus.",
"String.charAt|param|index": "Der null-basierte index des gewünschten Zeichens.",
"String.charCodeAt": "Gibt den Unicode-Wert des Zeichens am vorgegebenen Ort aus.",
"String.charCodeAt|param|index": "Der null-basierte Index des gewünschten Zeichens. Wenn kein Zeichen am angegeben Index vorhanden ist, wird NaN ausgegeben.",
"String.compare": "Bestimmt die relative Reihenfolge zweier Strings (in ASCII).",
"String.compare|param|that": "Zeichenfolge, die mit der Zielzeichenfolge verglichen werden soll",
"String.concat": "Gibt eine Zeichenfolge aus, die die Verkettung von zwei oder mehr Zeichenfolgen ist.",
"String.concat|param|other": "Die Zeichenfolge, die an das Ende einer Zeichenfolge angehängt werden soll.",
"String.fromCharCode": "Erstelle Sie eine Zeichenfolge aus dem angegebenen ASCII-Zeichencode.",
"String.isEmpty": "Gibt einen Wert aus, der anzeigt, ob die Zeichenfolge leer ist",
"String.length": "Gibt die Länge einer Zeichenfolge aus.",
"String.substr": "Gibt eine Teilzeichenfolge der aktuellen Zeichenfolge aus.",
"String.substr|param|length": "Anzahl der zu extrahierenden Zeichen",
"String.substr|param|start": "Erster Zeichenindex, kann beim zählen vom Ende negativ sein, zum Beispiel: 0",
"basic": "Bietet Zugriff auf grundlegende mini-Funktionalität.",
"basic.clearScreen": "Schalte alle LEDs aus",
"basic.color": "Konvertiert den Farbnamen in eine Nummer",
"basic.forever": "Wiederholt immer wieder den Code im Hintergrund. Bei jeder Iteration ist es möglich, anderen Code auszuführen.",
"basic.pause": "Pausiere für die angegebene Zeit in Millisekunden",
"basic.pause|param|ms": "wie lange pausieren, z.B.: 100, 200, 500, 1000, 2000",
"basic.plotLeds": "Zeichnet ein Bild auf dem LED-Bildschirm.",
"basic.plotLeds|param|leds": "Muster der LEDs, die ein-/ und ausgeschaltet werden",
"basic.rgbw": "Konvertiert Rot-, Grün- und Blau-Kanäle in eine RGB-Farbe",
"basic.rgbw|param|blue": "Blauwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|green": "Grünwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|red": "Rotwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|white": "Weißwert zwischen 0 und 255, z.B. 0",
"basic.setLedColor": "Legt die Farbe der eingebauten LED fest. Setze auf 0, um diese abzuschalten.",
"basic.showAnimation": "Zeigt eine Abfolge von LED-Anzeigen als Animation.",
"basic.showAnimation|param|interval": "Zeit in Millisekunden zwischen jedem Neuzeichnen",
"basic.showAnimation|param|leds": "Muster der LEDs, die ein-/ und ausgeschaltet werden",
"basic.showLeds": "Zeichnet ein Bild auf dem LED-Bildschirm.",
"basic.showLeds|param|interval": "Zeit in Millisekunden, die nach der Zeichnung gewartet wird",
"basic.showLeds|param|leds": "Muster der LEDs, die ein- und ausgeschaltet werden",
"basic.showNumber": "Zeige eine Nummer auf dem Display. Wenn die Nummer auf das Display passt (es sich also um eine einstellige Zahl handelt), scrolle nicht weiter.",
"basic.showNumber|param|interval": "Scroll-Geschwindigkeit; z.B. 150, 100, 200,-100",
"basic.showString": "Zeige Text auf dem Display an, Buchstabe für Buchstabe. Wenn die Zeichenfolge in das Display passt (also wenn es sich um einen einzelnen Buchstaben handelt), scrolle nicht weiter.",
"basic.showString|param|interval": "Wie schnell die Zeichen geändert werden; z.B. 150, 100, 200,-100",
"basic.showString|param|text": "Text auf dem Bildschirm dargestellt werden soll, z.B.: \"Hallo!\"",
"control": "Laufzeit- und Event-Dienstprogramme.",
"control.assert": "Wenn die Bedingung falsch ist, zeige eine Nachricht auf der seriellen Konsole und gebe Panic-Code 098 aus",
"control.deviceName": "Erzeugt einen Namen für das Gerät, basierend auf der Seriennummer",
"control.eventSourceId": "Gibt den Wert einer C++-Laufzeitkonstanten aus",
"control.eventTimestamp": "Holt den Zeitstempel des letzten Events auf dem Bus",
"control.eventValue": "Holt den Wert des letzten ausgeführten Events auf dem Bus",
"control.eventValueId": "Gibt den Wert einer C++-Laufzeitkonstanten aus",
"control.inBackground": "Plant Code, der im Hintergrund wiedergegeben wird.",
"control.onEvent": "Startet ein Event auf dem Event-Bus.",
"control.panic": "Zeigt einen spezifizierten Fehlercode und hält das Programm an.",
"control.raiseEvent": "Startet ein Event auf dem Event-Bus.",
"control.raiseEvent|param|mode": "optionale Definition davon, wie ein Event nach dem Erstellen ausgeführt wird (Standard ist \"CREATE_AND_FIRE).",
"control.raiseEvent|param|src": "ID der Calliope mini-Komponente, die das Event generiert hat, zum Beispiel CALLIOPE_ID_BUTTON_A.",
"control.raiseEvent|param|value": "Komponentenspezifischer Code, der den Grund des Events angibt.",
"control.reset": "Seit den mini zurück.",
"control.runtimeWarning": "Zeige Warnmeldung im Simulator.",
"control.waitMicros": "Sperrt die aktuelle Leitung für die Dauer der angegebenen Mikrosekunden",
"control.waitMicros|param|micros": "Anzahl der Mikrosekunden, die gewartet werden soll, z.B.: 4",
"game": "Eine Einzel-LED-Sprite-Spielumgebung",
"game.addLife": "Fügt Leben zum aktuellen Spielstand hinzu",
"game.addScore": "Fügt zum aktuellen Spielstand Punkte hinzu",
"game.addScore|param|points": "Anzahl von zu verändernden Punkten, z.B.: 1",
"game.createSprite": "Erzeugt einen neuen LED-Sprite, der nach rechts zeigt.",
"game.createSprite|param|x": "horizontale Koordinate des Sprites, z.B. 2",
"game.createSprite|param|y": "vertikale Koordinate des Sprites, z.B. 2",
"game.currentTime": "Ruft die verbliebene Zeit (seit `starte Countdown`) oder die aktuelle Zeit (seit das Gerät gestartet wurde oder eine Stoppuhr aktiviert wurde) an.",
"game.gameOver": "Gibt über eine Animation ein Spiel wieder.",
"game.invalidSprite": "Ruft einen invaliden Sprite ab; wird genutzt, um Locale zu initialisieren.",
"game.isGameOver": "Zeigt an, ob das Spil die \"Game Over\"-Sequenz angezeigt hat.",
"game.isRunning": "Holt einen Wert, der anzeigt, ob das Spiel noch läuft. Gibt `falsch`aus, wenn das Spiel zu Ende ist.",
"game.level": "Ruft das aktuelle Level ab",
"game.levelUp": "Erhöht das Level und zeigt eine Nachricht an.",
"game.life": "Ruft das aktuelle Leben ab",
"game.removeLife": "Entfernt ein Leben",
"game.score": "Ruft den aktuellen Punktestand ab",
"game.setLife": "Setzt den aktuellen Wert der Leben",
"game.setScore": "Setzt den aktuellen Wert des Spielstands",
"game.showScore": "Zeigt den Spielstand auf dem Display.",
"game.startCountdown": "Startet einen Spiel-Countdown",
"game.startCountdown|param|ms": "Countdown-Dauer in Millisekunden, z.B.: 10000",
"game.startStopwatch": "Startet eine Stoppuhr.`aktuelle Zeit`gibt die vergangene Zeit an.",
"images": "Erstellung, Bearbeitung und Anzeige von LED-Bildern.",
"images.createBigImage": "Erstellt ein Bild mit zwei Einzelbildern.",
"images.createImage": "Erstellt ein Bild, das auf den LED-Bildschirm passt.",
"input": "Ereignisse und Daten der Sensoren",
"input.acceleration": "Holt den Beschleunigungswert in Milli-Erdanziehung (wenn das Board flach mit dem Display nach oben liegt, X = 0, y = 0 und Z =-1024)",
"input.buttonIsPressed": "Erhalte den Sie den Tastenstatus (gepresst oder nicht) für ``A`` und ``B``.",
"input.calibrate": "Veraltet, Kompasskalibrierung erfolgt automatisch.",
"input.compassHeading": "Holt die aktuelle Kompassrichtung in Grad.",
"input.lightLevel": "Liest die Lichtintensität auf dem LED-Bildschirm im Bereich von ``0`` (dunkel) und `` 255`` (hell).",
"input.magneticForce": "Ruft den Wert der Magnetkraft in ``Mikro-Tesla`` (``µT``) ab. Diese Funktion wird im Simulator nicht unterstützt.",
"input.onButtonPressed": "Tue etwas, wenn eine Taste (``A``, ``B`` oder ``A + B``) gedrückt wird",
"input.onGesture": "Mache etwas, wenn eine Geste gemacht wird (wie den mini zu schütteln).",
"input.onLogoDown": "Fügt Code hinzu, der ausgeführt wird, wenn das Logo nach unten zeigt und das Board vertikal ausgerichtet ist.",
"input.onLogoUp": "Fügt Code hinzu, der ausgeführt wird, wenn das Logo nach oben zeigt und das Board vertikal ausgerichtet ist.",
"input.onPinPressed": "Mache etwas, wenn eine Pin gehalten wird.",
"input.onPinPressed|param|body": "Code, der ausführt wird, wenn ein Pin gehalten wird",
"input.onPinReleased": "Mache etwas, wenn der Pin losgelassen wird.",
"input.onPinReleased|param|body": "Code, der ausgeführt werden soll, wenn der Pin losgelassen wird",
"input.onScreenDown": "Hängt Code an, der ausgeführt wird, wenn der Bildschirm nach unten zeigt.",
"input.onScreenUp": "Hängt Code an, der ausgeführt wird, wenn der Bildschirm nach oben zeigt.",
"input.onShake": "Hängt Code an, der ausgeführt wird, wenn der mini geschüttelt wird.",
"input.pinIsPressed": "Ruft den Pin-Zustand (gehalten oder nicht) ab. Die Erdung muss gehalten werden, um den Stromkreis zu schließen.",
"input.rotation": "Die Neigung und Drehung des mini Drehung auf ``X-Achse``oder ``Y-Achse``, in Grad.",
"input.runningTime": "Ruft die Anzahl der Millisekunden auf, die seit dem Einschalten vergangen sind.",
"input.setAccelerometerRange": "Legt die Stichprobenbereich des Beschleunigungssensors in Schwerkraft fest.",
"input.setAccelerometerRange|param|range": "Ein Wert, der die maximale Stärke der gemessenen Beschleunigung beschreibt",
"input.temperature": "Ruft die aktuelle Temperatur in Grad Celsius (°C) ab.",
"led": "Steuerung des LED-Bildschirms.",
"led.brightness": "Ruft die Helligkeit des Bildschirms ab, von 0 (aus) bis 255 (volle Helligkeit).",
"led.enable": "Schaltet das Display an und aus",
"led.fadeIn": "Blendet die Bildschirmanzeige ein.",
"led.fadeOut": "Blendet die Bildschirmhelligkeit aus.",
"led.plot": "Schalte die angegebene LED mit Hilfe von X- und Y-Koordinaten ein (X ist horizontal, Y ist vertikal). (0,0) ist die obere linke Ecke.",
"led.plotAll": "Schaltet alle LEDs an",
"led.plotBarGraph": "Zeigt ein vertikales Balkendiagramm an, basierend auf dem `Wert`und dem `Hoch`-Wert. Wenn `Hoch`0 ist, wird das Diagramm automatisch angepasst.",
"led.plotBarGraph|param|high": "maximalen Wert. Wenn dieser 0 ist, wird der Maximalwert automatisch angepasst, z.B.: 0",
"led.plotBarGraph|param|value": "aktueller Wert zum Darstellen",
"led.point": "Ruft den An/Aus-Status einer vorgegebenen LED mittels X-/Y-Koordinaten ab. (0,0) ist oben links.",
"led.screenshot": "Macht einen Screenshot vom LED-Bildschirm und gibt ein Bild aus.",
"led.setBrightness": "Lege die Helligkeit des Bildschirms fest, von 0 (aus) bis 255 (volle Helligkeit).",
"led.setBrightness|param|value": "Helligkeitswert, z.B.: 255, 127, 0",
"led.setDisplayMode": "Legt den Anzeigemodus von Wiedergabe-LEDs zwischen Schwarz und Weiß und Graustufen fest.",
"led.setDisplayMode|param|mode": "TODO",
"led.stopAnimation": "Bricht die aktuelle Animation ab und löscht andere ausstehende Animationen.",
"led.toggle": "Schaltet ein bestimmtes Pixel ein",
"led.toggleAll": "Invertiert die aktuelle LED-Anzeige",
"led.unplot": "Schalte die angegebene LED mit x-und y-Koordinaten ab (X ist horizontal, y ist vertikal). (0,0) ist oben links.",
"motors": "Blöcke, die genutzt werden, um Onboard-Motoren zu steuern",
"motors.dualMotorPower": "Steuert zwei an das Board angeschlossene Motoren. Schaltet auf Dual-Motor-Modus um!",
"motors.motorCommand": "Schicke Anhalten, Ausrollen oder Anhalten-Befehle an den Motor. Hat im Dual-Motor-Modus keinen Effekt.",
"motors.motorPower": "Schaltet den Motor bei einer bestimmten Prozentzahl der Kraft an. Schaltet um auf den Single-Motor-Modus!",
"motors.motorPower|param|power": "%percent der Kraft, die an den Motor geschickt wird. Negative Werte laufen rückwärts, z.B. 50",
"music": "Generierung von von Musik durch Pin ``P0``.",
"music.beat": "Gibt die Dauer eines Taktes in Milli-Sekunden aus",
"music.changeTempoBy": "Ändere die Geschwindigkeit um den angegebenen Betrag",
"music.changeTempoBy|param|bpm": "Die Änderung in Schlägen pro Minute auf das Tempo, z.B.: 20",
"music.noteFrequency": "Ruft die Frequenz einer Note ab.",
"music.playTone": "Spielt einen Ton für den angegebenen Zeitraum auf dem Lautsprecher ab.",
"music.playTone|param|ms": "Tondauer in Millisekunden (ms)",
"music.rest": "Ruht (spielt nichts) für eine bestimmte Zeit auf Pin ``P0``.",
"music.rest|param|ms": "Restdauer in Millisekunden (ms)",
"music.ringTone": "Spielt einen Ton durch den Lautsprecher ab.",
"music.ringTone|param|frequency": "Tonhöhe des abzuspielenden Tones in Hertz (Hz)",
"music.setTempo": "Legt die Geschwindigkeit auf den angegebenen Wert fest.",
"music.setTempo|param|bpm": "Die neue Geschwindigkeit in Schlägen pro Minute, z.B.: 120",
"music.tempo": "Gibt die Geschwindigkeit in Schlägen pro Minute aus. Die Geschwindigkeit ist Schnelligkeit (Bpm = Beats pro Minute), in der Töne abgespielt werden. Je größer der Wert, desto schneller werden die Töne abgespielt.",
"pins": "Steuere die Stromstärke über die Pins für analoge/digitale Signale, Servos, I2C,...",
"pins.analogPitch": "Gibt ein Pulsweiten Modulation (PWM)-Signal über den aktuellen Pitch-Pin. Benutze `analog set pitch pin`, um den Pitch-Pin festzulegen.",
"pins.analogReadPin": "Lese den Anschlusswert als Analog aus, d. h. als einen Wert zwischen 0 und 1023.",
"pins.analogSetPeriod": "Stellt die Pulsweite Modulation (PWM) des Analogausganges auf den angegebenen Wert in ** Mikrosekunden ** oder `1/1000` Millisekunden ein.\nWenn dieser Pin nicht als einen Analogausgang (mit `analog write pin`) konfiguriert ist, hat der Vorgang keine Auswirkungen.",
"pins.analogSetPeriod|param|micros": "Zeit in Mikrosekunden. z.B.: 20000",
"pins.analogWritePin": "Legt den Wert des Verbinders auf analog fest. Der Wert muss zwischen 0 und 1023 liegen.",
"pins.analogWritePin|param|value": "Wert, der auf den Pin geschrieben werden soll, zwischen ``0`` und ``1023`` z.B.: 1023,0",
"pins.createBuffer": "Erstellt einen Null-initialisierten Zwischenspeicher.",
"pins.createBuffer|param|size": "Anzahl der Bytes im Zwischenspeicher",
"pins.digitalReadPin": "Lese den angegebene Pin oder Verbinder als 0 oder 1",
"pins.digitalWritePin": "Setzt einen Pin- oder Verbinder-Wert auf 0 oder 1.",
"pins.digitalWritePin|param|value": "Wert, der auf dem Pin 1 gesetzt werden soll, z.B. 0",
"pins.i2cReadBuffer": "Lese `Größe`bytes aus einer 7-bit I2C-Adresse.",
"pins.i2cReadNumber": "Lese eine Nummer aus einer 7-bit I2C-Adresse.",
"pins.i2cWriteBuffer": "Schreibt Bytes in eine 7-bit I2C-Adresse.",
"pins.i2cWriteNumber": "Schreibe eine Nummer in eine 7-bit I2C-Adresse.",
"pins.map": "Definiert eine Nummer von einer Auswahl zu einer anderen um. Ein Wert ``von niedrig``wird so auf ``zu niedrig``umgeändert, ein Wert ``von hoch`` zu ``zu hoch`` etc.",
"pins.map|param|fromHigh": "die obere Grenze des aktuellen Wertebereichs, z.B.: 1023",
"pins.map|param|fromLow": "die untere Grenze des aktuellen Wertebereichs",
"pins.map|param|toHigh": "die Obergrenze des Wertezielbereichs, z.B.: 4",
"pins.map|param|toLow": "die Untergrenze des Wertezielbereichs",
"pins.map|param|value": "Wert in Bereichen zuordnen",
"pins.onPulsed": "Stellt diesen Pin als einen Digitaleingang ein und generiert Ereignisse, deren Zeitstempel die Dauer darstellt, in der der Pin entweder ``hoch``oder ``niedrig``war.",
"pins.pulseDuration": "Ruft die Dauer des letzten Impulses in Mikrosendungen ab. Diese Funktion soll von einem `onPulsed`-Handler aufgerufen werden.",
"pins.pulseIn": "Gibt die Dauer eines Pulses in Mikrosekunden an",
"pins.pulseIn|param|name": "der Pin, der den Puls misst",
"pins.pulseIn|param|value": "der Wert des Pulses (Standard hoch)",
"pins.servoSetPulse": "Konfiguriert diesen IO-Pin als einen analogen/PWM-Ausgang, stellt den Zeitraum auf 20 ms ein und setzt die Pulsweite fest, basieren auf dem angegeben Wert **Mikrosekunden** oder `1/1000`Millisekunden.",
"pins.servoSetPulse|param|micros": "Impulsdauer in Mikrosekunden, z.B.: 1500",
"pins.servoSetPulse|param|name": "PIN-Name",
"pins.servoWritePin": "Schreibt einen Wert in den Servo, der die Welle entsprechend kontroliert. Auf einem Standard-Servo wird so der Winkel der Welle (in Grad) eingestellt, sodass sich die Welle entsprechend anpasst. Auf einem kontinuierlich drehenden Servo wird dadurch die Geschwindigkeit des Servos festgelegt, wobei ``0``die volle Geschwindigkeit in eine Richtung darstellt, ``180``die volle Geschwindigkeit in die andere, und ein Wert von ``90`` einen Stillstand erzeugt.",
"pins.servoWritePin|param|value": "Winkel oder Rotationsbeschleunigung, z.B.: 180,90,0",
"pins.setPull": "Stellt die Anziehungskraft des Pins ein.",
"pins.sizeOf": "Ruft die Bytegröße im spezifierten Nummernformat ab.",
"pins.spiWrite": "Schreibe in den SPI-Slave und gebe die Antwort aus",
"pins.spiWrite|param|value": "Daten, die an den SPI-Slave geschickt werden sollen",
"serial": "Lesen und Schreiben von Daten über eine serielle Verbindung.",
"serial.delimiters": "Gibt die mit dem Begrenzer korrespondierende Zeichenfolge aus.",
"serial.onLineReceived": "Registriert ein Event, das ausgeführt wird, wenn eine Zeile empfangen wurde",
"serial.readLine": "Liest eine Textzeile aus der seriellen Schnittstelle.",
"serial.readUntil": "Liest aus eine Textzeile aus dem seriellen Anschluss und gibt den Puffer aus, wenn die Begrenzung erreicht wurde.",
"serial.readUntil|param|delimiter": "Text-Begrenzung, die die Textblöcke voneinander trennt",
"serial.redirect": "Konfiguriert dynamisch die serielle Instanz, damit sie andere Pins als USBTX und USBRX benutzt.",
"serial.writeLine": "Gibt eine Zeile des Textes an die serielle",
"serial.writeNumber": "Gibt einen numerischen Wert an die serielle",
"serial.writeString": "Sendet ein Stück Text über serielle Verbindung.",
"serial.writeValue": "Schreibt ein ``Namen: Wert`` Wertepaar auf die serielle Schnittstelle.",
"serial.writeValue|param|name": "Name des Wertestreams, z.B.: x",
"serial.writeValue|param|value": "Schreiben"
"Math.abs": "Gibt den absoluten Wert einer Zahl aus (den Wert unabhängig davon, ob er positiv oder negativ ist).\nDer absolute Wert von -5 ist zum Beispiel der gleiche wie der von 5.",
"Math.abs|param|x": "Ein numerischer Ausdruck, für den der absolute Wert benötigt wird.",
"Math.max": "Gibt den größeren von zwei vorhandenen numerischen Ausdrücken aus.",
"Math.min": "Gibt den niedrigeren von zwei vorhandenen numerischen Ausdrücken aus.",
"Math.pow": "Gibt den Wert eines grundlegenden Ausdrucks bis zu einer bestimmten Stärke aus.",
"Math.pow|param|x": "Der Basiswert des Ausdrucks.",
"Math.pow|param|y": "Der exponentielle Wert des Ausdrucks.",
"Math.random": "Gibt eine pseudozufüllige Zahl zwischen 0 und `max`aus.",
"Math.randomBoolean": "Erzeugt zufällig einen \"wahr\" oder \"falsch\"-Wert, wie bei einem Münzwurf.",
"Math.sign": "Gibt das Vorzeichen von x aus und zeigt an, ob dieses positiv, negativ oder null ist.",
"Math.sign|param|x": "Der numerische Ausdruck, der getestet werden soll",
"Math.sqrt": "Gibt die Quadratwurzel einer Zahl aus.",
"Math.sqrt|param|x": "Ein numerischer Ausdruck.",
"String.charAt": "Gibt den Buchstaben beim angegebenen Index aus.",
"String.charAt|param|index": "Der null-basierte index des gewünschten Zeichens.",
"String.charCodeAt": "Gibt den Unicode-Wert des Zeichens am vorgegebenen Ort aus.",
"String.charCodeAt|param|index": "Der null-basierte Index des gewünschten Zeichens. Wenn kein Zeichen am angegeben Index vorhanden ist, wird NaN ausgegeben.",
"String.compare": "Bestimmt die relative Reihenfolge zweier Strings (in ASCII).",
"String.compare|param|that": "Zeichenfolge, die mit der Zielzeichenfolge verglichen werden soll",
"String.concat": "Gibt eine Zeichenfolge aus, die die Verkettung von zwei oder mehr Zeichenfolgen ist.",
"String.concat|param|other": "Die Zeichenfolge, die an das Ende einer Zeichenfolge angehängt werden soll.",
"String.fromCharCode": "Erstelle Sie eine Zeichenfolge aus dem angegebenen ASCII-Zeichencode.",
"String.isEmpty": "Gibt einen Wert aus, der anzeigt, ob die Zeichenfolge leer ist",
"String.length": "Gibt die Länge einer Zeichenfolge aus.",
"String.substr": "Gibt eine Teilzeichenfolge der aktuellen Zeichenfolge aus.",
"String.substr|param|length": "Anzahl der zu extrahierenden Zeichen",
"String.substr|param|start": "Erster Zeichenindex, kann beim zählen vom Ende negativ sein, zum Beispiel: 0",
"basic": "Bietet Zugriff auf grundlegende mini-Funktionalität.",
"basic.clearScreen": "Schalte alle LEDs aus",
"basic.color": "Konvertiert den Farbnamen in eine Nummer",
"basic.forever": "Wiederholt immer wieder den Code im Hintergrund. Bei jeder Iteration ist es möglich, anderen Code auszuführen.",
"basic.pause": "Pausiere für die angegebene Zeit in Millisekunden",
"basic.pause|param|ms": "wie lange pausieren, z.B.: 100, 200, 500, 1000, 2000",
"basic.plotLeds": "Zeichnet ein Bild auf dem LED-Bildschirm.",
"basic.plotLeds|param|leds": "Muster der LEDs, die ein-/ und ausgeschaltet werden",
"basic.rgbw": "Konvertiert Rot-, Grün- und Blau-Kanäle in eine RGB-Farbe",
"basic.rgbw|param|blue": "Blauwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|green": "Grünwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|red": "Rotwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|white": "Weißwert zwischen 0 und 255, z.B. 0",
"basic.rgb": "Konvertiert Rot-, Grün- und Blau-Kanäle in eine RGB-Farbe",
"basic.rgb|param|blue": "Blauwert zwischen 0 und 255, z.B. 255",
"basic.rgb|param|green": "Grünwert zwischen 0 und 255, z.B. 255",
"basic.rgb|param|red": "Rotwert zwischen 0 und 255, z.B. 255",
"basic.setLedColor": "Legt die Farbe der eingebauten LED fest. Setze auf 0, um diese abzuschalten.",
"basic.showAnimation": "Zeigt eine Abfolge von LED-Anzeigen als Animation.",
"basic.showAnimation|param|interval": "Zeit in Millisekunden zwischen jedem Neuzeichnen",
"basic.showAnimation|param|leds": "Muster der LEDs, die ein-/ und ausgeschaltet werden",
"basic.showLeds": "Zeichnet ein Bild auf dem LED-Bildschirm.",
"basic.showLeds|param|interval": "Zeit in Millisekunden, die nach der Zeichnung gewartet wird",
"basic.showLeds|param|leds": "Muster der LEDs, die ein- und ausgeschaltet werden",
"basic.showNumber": "Zeige eine Nummer auf dem Display. Wenn die Nummer auf das Display passt (es sich also um eine einstellige Zahl handelt), scrolle nicht weiter.",
"basic.showNumber|param|interval": "Scroll-Geschwindigkeit; z.B. 150, 100, 200,-100",
"basic.showString": "Zeige Text auf dem Display an, Buchstabe für Buchstabe. Wenn die Zeichenfolge in das Display passt (also wenn es sich um einen einzelnen Buchstaben handelt), scrolle nicht weiter.",
"basic.showString|param|interval": "Wie schnell die Zeichen geändert werden; z.B. 150, 100, 200,-100",
"basic.showString|param|text": "Text auf dem Bildschirm dargestellt werden soll, z.B.: \"Hallo!\"",
"control": "Laufzeit- und Event-Dienstprogramme.",
"control.assert": "Wenn die Bedingung falsch ist, zeige eine Nachricht auf der seriellen Konsole und gebe Panic-Code 098 aus",
"control.deviceName": "Erzeugt einen Namen für das Gerät, basierend auf der Seriennummer",
"control.eventSourceId": "Gibt den Wert einer C++-Laufzeitkonstanten aus",
"control.eventTimestamp": "Holt den Zeitstempel des letzten Events auf dem Bus",
"control.eventValue": "Holt den Wert des letzten ausgeführten Events auf dem Bus",
"control.eventValueId": "Gibt den Wert einer C++-Laufzeitkonstanten aus",
"control.inBackground": "Plant Code, der im Hintergrund wiedergegeben wird.",
"control.onEvent": "Startet ein Event auf dem Event-Bus.",
"control.panic": "Zeigt einen spezifizierten Fehlercode und hält das Programm an.",
"control.raiseEvent": "Startet ein Event auf dem Event-Bus.",
"control.raiseEvent|param|mode": "optionale Definition davon, wie ein Event nach dem Erstellen ausgeführt wird (Standard ist \"CREATE_AND_FIRE).",
"control.raiseEvent|param|src": "ID der Calliope mini-Komponente, die das Event generiert hat, zum Beispiel CALLIOPE_ID_BUTTON_A.",
"control.raiseEvent|param|value": "Komponentenspezifischer Code, der den Grund des Events angibt.",
"control.reset": "Seit den mini zurück.",
"control.runtimeWarning": "Zeige Warnmeldung im Simulator.",
"control.waitMicros": "Sperrt die aktuelle Leitung für die Dauer der angegebenen Mikrosekunden",
"control.waitMicros|param|micros": "Anzahl der Mikrosekunden, die gewartet werden soll, z.B.: 4",
"game": "Eine Einzel-LED-Sprite-Spielumgebung",
"game.addLife": "Fügt Leben zum aktuellen Spielstand hinzu",
"game.addScore": "Fügt zum aktuellen Spielstand Punkte hinzu",
"game.addScore|param|points": "Anzahl von zu verändernden Punkten, z.B.: 1",
"game.createSprite": "Erzeugt einen neuen LED-Sprite, der nach rechts zeigt.",
"game.createSprite|param|x": "horizontale Koordinate des Sprites, z.B. 2",
"game.createSprite|param|y": "vertikale Koordinate des Sprites, z.B. 2",
"game.currentTime": "Ruft die verbliebene Zeit (seit `starte Countdown`) oder die aktuelle Zeit (seit das Gerät gestartet wurde oder eine Stoppuhr aktiviert wurde) an.",
"game.gameOver": "Gibt über eine Animation ein Spiel wieder.",
"game.invalidSprite": "Ruft einen invaliden Sprite ab; wird genutzt, um Locale zu initialisieren.",
"game.isGameOver": "Zeigt an, ob das Spil die \"Game Over\"-Sequenz angezeigt hat.",
"game.isRunning": "Holt einen Wert, der anzeigt, ob das Spiel noch läuft. Gibt `falsch`aus, wenn das Spiel zu Ende ist.",
"game.level": "Ruft das aktuelle Level ab",
"game.levelUp": "Erhöht das Level und zeigt eine Nachricht an.",
"game.life": "Ruft das aktuelle Leben ab",
"game.removeLife": "Entfernt ein Leben",
"game.score": "Ruft den aktuellen Punktestand ab",
"game.setLife": "Setzt den aktuellen Wert der Leben",
"game.setScore": "Setzt den aktuellen Wert des Spielstands",
"game.showScore": "Zeigt den Spielstand auf dem Display.",
"game.startCountdown": "Startet einen Spiel-Countdown",
"game.startCountdown|param|ms": "Countdown-Dauer in Millisekunden, z.B.: 10000",
"game.startStopwatch": "Startet eine Stoppuhr.`aktuelle Zeit`gibt die vergangene Zeit an.",
"images": "Erstellung, Bearbeitung und Anzeige von LED-Bildern.",
"images.createBigImage": "Erstellt ein Bild mit zwei Einzelbildern.",
"images.createImage": "Erstellt ein Bild, das auf den LED-Bildschirm passt.",
"input": "Ereignisse und Daten der Sensoren",
"input.acceleration": "Holt den Beschleunigungswert in Milli-Erdanziehung (wenn das Board flach mit dem Display nach oben liegt, X = 0, y = 0 und Z =-1024)",
"input.buttonIsPressed": "Erhalte den Sie den Tastenstatus (gepresst oder nicht) für ``A`` und ``B``.",
"input.calibrate": "Veraltet, Kompasskalibrierung erfolgt automatisch.",
"input.compassHeading": "Holt die aktuelle Kompassrichtung in Grad.",
"input.lightLevel": "Liest die Lichtintensität auf dem LED-Bildschirm im Bereich von ``0`` (dunkel) und `` 255`` (hell).",
"input.magneticForce": "Ruft den Wert der Magnetkraft in ``Mikro-Tesla`` (``µT``) ab. Diese Funktion wird im Simulator nicht unterstützt.",
"input.onButtonPressed": "Tue etwas, wenn eine Taste (``A``, ``B`` oder ``A + B``) gedrückt wird",
"input.onGesture": "Mache etwas, wenn eine Geste gemacht wird (wie den mini zu schütteln).",
"input.onLogoDown": "Fügt Code hinzu, der ausgeführt wird, wenn das Logo nach unten zeigt und das Board vertikal ausgerichtet ist.",
"input.onLogoUp": "Fügt Code hinzu, der ausgeführt wird, wenn das Logo nach oben zeigt und das Board vertikal ausgerichtet ist.",
"input.onPinPressed": "Mache etwas, wenn eine Pin gehalten wird.",
"input.onPinPressed|param|body": "Code, der ausführt wird, wenn ein Pin gehalten wird",
"input.onPinReleased": "Mache etwas, wenn der Pin losgelassen wird.",
"input.onPinReleased|param|body": "Code, der ausgeführt werden soll, wenn der Pin losgelassen wird",
"input.onScreenDown": "Hängt Code an, der ausgeführt wird, wenn der Bildschirm nach unten zeigt.",
"input.onScreenUp": "Hängt Code an, der ausgeführt wird, wenn der Bildschirm nach oben zeigt.",
"input.onShake": "Hängt Code an, der ausgeführt wird, wenn der mini geschüttelt wird.",
"input.pinIsPressed": "Ruft den Pin-Zustand (gehalten oder nicht) ab. Die Erdung muss gehalten werden, um den Stromkreis zu schließen.",
"input.rotation": "Die Neigung und Drehung des mini Drehung auf ``X-Achse``oder ``Y-Achse``, in Grad.",
"input.runningTime": "Ruft die Anzahl der Millisekunden auf, die seit dem Einschalten vergangen sind.",
"input.setAccelerometerRange": "Legt die Stichprobenbereich des Beschleunigungssensors in Schwerkraft fest.",
"input.setAccelerometerRange|param|range": "Ein Wert, der die maximale Stärke der gemessenen Beschleunigung beschreibt",
"input.temperature": "Ruft die aktuelle Temperatur in Grad Celsius (°C) ab.",
"led": "Steuerung des LED-Bildschirms.",
"led.brightness": "Ruft die Helligkeit des Bildschirms ab, von 0 (aus) bis 255 (volle Helligkeit).",
"led.enable": "Schaltet das Display an und aus",
"led.fadeIn": "Blendet die Bildschirmanzeige ein.",
"led.fadeOut": "Blendet die Bildschirmhelligkeit aus.",
"led.plot": "Schalte die angegebene LED mit Hilfe von X- und Y-Koordinaten ein (X ist horizontal, Y ist vertikal). (0,0) ist die obere linke Ecke.",
"led.plotAll": "Schaltet alle LEDs an",
"led.plotBarGraph": "Zeigt ein vertikales Balkendiagramm an, basierend auf dem `Wert`und dem `Hoch`-Wert. Wenn `Hoch`0 ist, wird das Diagramm automatisch angepasst.",
"led.plotBarGraph|param|high": "maximalen Wert. Wenn dieser 0 ist, wird der Maximalwert automatisch angepasst, z.B.: 0",
"led.plotBarGraph|param|value": "aktueller Wert zum Darstellen",
"led.point": "Ruft den An/Aus-Status einer vorgegebenen LED mittels X-/Y-Koordinaten ab. (0,0) ist oben links.",
"led.screenshot": "Macht einen Screenshot vom LED-Bildschirm und gibt ein Bild aus.",
"led.setBrightness": "Lege die Helligkeit des Bildschirms fest, von 0 (aus) bis 255 (volle Helligkeit).",
"led.setBrightness|param|value": "Helligkeitswert, z.B.: 255, 127, 0",
"led.setDisplayMode": "Legt den Anzeigemodus von Wiedergabe-LEDs zwischen Schwarz und Weiß und Graustufen fest.",
"led.setDisplayMode|param|mode": "TODO",
"led.stopAnimation": "Bricht die aktuelle Animation ab und löscht andere ausstehende Animationen.",
"led.toggle": "Schaltet ein bestimmtes Pixel ein",
"led.toggleAll": "Invertiert die aktuelle LED-Anzeige",
"led.unplot": "Schalte die angegebene LED mit x-und y-Koordinaten ab (X ist horizontal, y ist vertikal). (0,0) ist oben links.",
"motors": "Blöcke, die genutzt werden, um Onboard-Motoren zu steuern",
"motors.dualMotorPower": "Steuert zwei an das Board angeschlossene Motoren. Schaltet auf Dual-Motor-Modus um!",
"motors.motorCommand": "Schicke Anhalten, Ausrollen oder Anhalten-Befehle an den Motor. Hat im Dual-Motor-Modus keinen Effekt.",
"motors.motorPower": "Schaltet den Motor bei einer bestimmten Prozentzahl der Kraft an. Schaltet um auf den Single-Motor-Modus!",
"motors.motorPower|param|power": "%percent der Kraft, die an den Motor geschickt wird. Negative Werte laufen rückwärts, z.B. 50",
"music": "Generierung von von Musik durch Pin ``P0``.",
"music.beat": "Gibt die Dauer eines Taktes in Milli-Sekunden aus",
"music.changeTempoBy": "Ändere die Geschwindigkeit um den angegebenen Betrag",
"music.changeTempoBy|param|bpm": "Die Änderung in Schlägen pro Minute auf das Tempo, z.B.: 20",
"music.noteFrequency": "Ruft die Frequenz einer Note ab.",
"music.playTone": "Spielt einen Ton für den angegebenen Zeitraum auf dem Lautsprecher ab.",
"music.playTone|param|ms": "Tondauer in Millisekunden (ms)",
"music.rest": "Ruht (spielt nichts) für eine bestimmte Zeit auf Pin ``P0``.",
"music.rest|param|ms": "Restdauer in Millisekunden (ms)",
"music.ringTone": "Spielt einen Ton durch den Lautsprecher ab.",
"music.ringTone|param|frequency": "Tonhöhe des abzuspielenden Tones in Hertz (Hz)",
"music.setTempo": "Legt die Geschwindigkeit auf den angegebenen Wert fest.",
"music.setTempo|param|bpm": "Die neue Geschwindigkeit in Schlägen pro Minute, z.B.: 120",
"music.tempo": "Gibt die Geschwindigkeit in Schlägen pro Minute aus. Die Geschwindigkeit ist Schnelligkeit (Bpm = Beats pro Minute), in der Töne abgespielt werden. Je größer der Wert, desto schneller werden die Töne abgespielt.",
"pins": "Steuere die Stromstärke über die Pins für analoge/digitale Signale, Servos, I2C,...",
"pins.analogPitch": "Gibt ein Pulsweiten Modulation (PWM)-Signal über den aktuellen Pitch-Pin. Benutze `analog set pitch pin`, um den Pitch-Pin festzulegen.",
"pins.analogReadPin": "Lese den Anschlusswert als Analog aus, d. h. als einen Wert zwischen 0 und 1023.",
"pins.analogSetPeriod": "Stellt die Pulsweite Modulation (PWM) des Analogausganges auf den angegebenen Wert in ** Mikrosekunden ** oder `1/1000` Millisekunden ein.\nWenn dieser Pin nicht als einen Analogausgang (mit `analog write pin`) konfiguriert ist, hat der Vorgang keine Auswirkungen.",
"pins.analogSetPeriod|param|micros": "Zeit in Mikrosekunden. z.B.: 20000",
"pins.analogWritePin": "Legt den Wert des Verbinders auf analog fest. Der Wert muss zwischen 0 und 1023 liegen.",
"pins.analogWritePin|param|value": "Wert, der auf den Pin geschrieben werden soll, zwischen ``0`` und ``1023`` z.B.: 1023,0",
"pins.createBuffer": "Erstellt einen Null-initialisierten Zwischenspeicher.",
"pins.createBuffer|param|size": "Anzahl der Bytes im Zwischenspeicher",
"pins.digitalReadPin": "Lese den angegebene Pin oder Verbinder als 0 oder 1",
"pins.digitalWritePin": "Setzt einen Pin- oder Verbinder-Wert auf 0 oder 1.",
"pins.digitalWritePin|param|value": "Wert, der auf dem Pin 1 gesetzt werden soll, z.B. 0",
"pins.i2cReadBuffer": "Lese `Größe`bytes aus einer 7-bit I2C-Adresse.",
"pins.i2cReadNumber": "Lese eine Nummer aus einer 7-bit I2C-Adresse.",
"pins.i2cWriteBuffer": "Schreibt Bytes in eine 7-bit I2C-Adresse.",
"pins.i2cWriteNumber": "Schreibe eine Nummer in eine 7-bit I2C-Adresse.",
"pins.map": "Definiert eine Nummer von einer Auswahl zu einer anderen um. Ein Wert ``von niedrig``wird so auf ``zu niedrig``umgeändert, ein Wert ``von hoch`` zu ``zu hoch`` etc.",
"pins.map|param|fromHigh": "die obere Grenze des aktuellen Wertebereichs, z.B.: 1023",
"pins.map|param|fromLow": "die untere Grenze des aktuellen Wertebereichs",
"pins.map|param|toHigh": "die Obergrenze des Wertezielbereichs, z.B.: 4",
"pins.map|param|toLow": "die Untergrenze des Wertezielbereichs",
"pins.map|param|value": "Wert in Bereichen zuordnen",
"pins.onPulsed": "Stellt diesen Pin als einen Digitaleingang ein und generiert Ereignisse, deren Zeitstempel die Dauer darstellt, in der der Pin entweder ``hoch``oder ``niedrig``war.",
"pins.pulseDuration": "Ruft die Dauer des letzten Impulses in Mikrosendungen ab. Diese Funktion soll von einem `onPulsed`-Handler aufgerufen werden.",
"pins.pulseIn": "Gibt die Dauer eines Pulses in Mikrosekunden an",
"pins.pulseIn|param|name": "der Pin, der den Puls misst",
"pins.pulseIn|param|value": "der Wert des Pulses (Standard hoch)",
"pins.servoSetPulse": "Konfiguriert diesen IO-Pin als einen analogen/PWM-Ausgang, stellt den Zeitraum auf 20 ms ein und setzt die Pulsweite fest, basieren auf dem angegeben Wert **Mikrosekunden** oder `1/1000`Millisekunden.",
"pins.servoSetPulse|param|micros": "Impulsdauer in Mikrosekunden, z.B.: 1500",
"pins.servoSetPulse|param|name": "PIN-Name",
"pins.servoWritePin": "Schreibt einen Wert in den Servo, der die Welle entsprechend kontroliert. Auf einem Standard-Servo wird so der Winkel der Welle (in Grad) eingestellt, sodass sich die Welle entsprechend anpasst. Auf einem kontinuierlich drehenden Servo wird dadurch die Geschwindigkeit des Servos festgelegt, wobei ``0``die volle Geschwindigkeit in eine Richtung darstellt, ``180``die volle Geschwindigkeit in die andere, und ein Wert von ``90`` einen Stillstand erzeugt.",
"pins.servoWritePin|param|value": "Winkel oder Rotationsbeschleunigung, z.B.: 180,90,0",
"pins.setPull": "Stellt die Anziehungskraft des Pins ein.",
"pins.sizeOf": "Ruft die Bytegröße im spezifierten Nummernformat ab.",
"pins.spiWrite": "Schreibe in den SPI-Slave und gebe die Antwort aus",
"pins.spiWrite|param|value": "Daten, die an den SPI-Slave geschickt werden sollen",
"serial": "Lesen und Schreiben von Daten über eine serielle Verbindung.",
"serial.delimiters": "Gibt die mit dem Begrenzer korrespondierende Zeichenfolge aus.",
"serial.onLineReceived": "Registriert ein Event, das ausgeführt wird, wenn eine Zeile empfangen wurde",
"serial.readLine": "Liest eine Textzeile aus der seriellen Schnittstelle.",
"serial.readUntil": "Liest aus eine Textzeile aus dem seriellen Anschluss und gibt den Puffer aus, wenn die Begrenzung erreicht wurde.",
"serial.readUntil|param|delimiter": "Text-Begrenzung, die die Textblöcke voneinander trennt",
"serial.redirect": "Konfiguriert dynamisch die serielle Instanz, damit sie andere Pins als USBTX und USBRX benutzt.",
"serial.writeLine": "Gibt eine Zeile des Textes an die serielle",
"serial.writeNumber": "Gibt einen numerischen Wert an die serielle",
"serial.writeString": "Sendet ein Stück Text über serielle Verbindung.",
"serial.writeValue": "Schreibt ein ``Namen: Wert`` Wertepaar auf die serielle Schnittstelle.",
"serial.writeValue|param|name": "Name des Wertestreams, z.B.: x",
"serial.writeValue|param|value": "Schreiben"
}

View File

@ -1,201 +1,202 @@
{
"AcceleratorRange.EightG": "Der Bewegungssensor misst Kräfte bis 8g",
"AcceleratorRange.EightG|block": "8g",
"AcceleratorRange.FourG": "Der Bewegungssensor misst Kräfte bis 4g",
"AcceleratorRange.FourG|block": "4g",
"AcceleratorRange.OneG": "Der Bewegungssensor misst Kräfte bis 1g",
"AcceleratorRange.OneG|block": "1g",
"AcceleratorRange.TwoG": "Der Bewegungssensor misst Kräfte bis 2g",
"AcceleratorRange.TwoG|block": "2g",
"BaudRate.BaudRate115200|block": "115200",
"BaudRate.BaudRate9600|block": "9600",
"BeatFraction.Eighth|block": "1/8",
"BeatFraction.Half|block": "1/2",
"BeatFraction.Quarter|block": "1/4",
"BeatFraction.Sixteenth|block": "1/16",
"BeatFraction.Whole|block": "1",
"Button.AB|block": "A+B",
"Colors.Blue|block": "Blau",
"Colors.Green|block": "Grün",
"Colors.Indigo|block": "Indigo",
"Colors.Orange|block": "Orange",
"Colors.Purple|block": "Violett",
"Colors.Red|block": "Rot",
"Colors.Violet|block": "Veilchenblau",
"Colors.White|block": "Weiß",
"Colors.Yellow|block": "Gelb",
"Delimiters.Dollar|block": "$",
"Delimiters.Hash|block": "#",
"Delimiters.NewLine|block": "Neue Zeile",
"Dimension.Strength|block": "Stärke",
"Dimension.X|block": "x",
"Dimension.Y|block": "y",
"Dimension.Z|block": "z",
"Direction.Left|block": "links",
"Direction.Right|block": "rechts",
"DisplayMode.BackAndWhite|block": "Schwarz-Weiß",
"DisplayMode.Greyscale|block": "Graustufen",
"EventCreationMode.CreateAndFire": "Calliope mini-Event wurde initialisiert, seine Event-Handler werden unverzüglich ausgeführt (nicht geeignet für die Nutzung bei Unterbrechungen!).",
"EventCreationMode.CreateOnly": "Calliope mini-Event wurde initialisiert, es wird keine weitere Verarbeitung vorgenommen.",
"Gesture.FreeFall": "Wird ausgeführt, wenn das Board fällt!",
"Gesture.FreeFall|block": "freier Fall",
"Gesture.LogoDown": "Wird ausgeführt, wenn das Logo nach unten zeigt und das Display vertikal ist.",
"Gesture.LogoDown|block": "Logo nach unten",
"Gesture.LogoUp": "Wird ausgeführt, wenn das Logo nach oben zeigt und das Display vertikal ist.",
"Gesture.LogoUp|block": "Logo oben",
"Gesture.ScreenDown": "Wird ausgeführt, wenn das Display nach oben zeigt und das Board horizontal ist.",
"Gesture.ScreenDown|block": "Display nach unten",
"Gesture.ScreenUp": "Wird ausgeführt, wenn das Display nach unten zeigt und das Board horizontal ist.",
"Gesture.ScreenUp|block": "Display nach oben",
"Gesture.Shake": "Wird erhöht, wenn geschüttelt",
"Gesture.Shake|block": "geschüttelt",
"Gesture.SixG": "Wird ausgeführt, ein 6g starker Stoß erkannt wird",
"Gesture.SixG|block": "6g",
"Gesture.ThreeG": "Wird ausgeführt, ein 3g starker Stoß erkannt wird",
"Gesture.ThreeG|block": "3g",
"Gesture.TiltLeft": "Wird ausgeführt, wenn das Display nach links zeigt",
"Gesture.TiltLeft|block": "nach links neigen",
"Gesture.TiltRight": "Wird ausgeführt, wenn das Display nach rechts zeigt",
"Gesture.TiltRight|block": "nach rechts neigen",
"LedSpriteProperty.Blink|block": "blinken",
"LedSpriteProperty.Brightness|block": "Helligkeit",
"LedSpriteProperty.Direction|block": "Richtung",
"LedSpriteProperty.X|block": "x",
"LedSpriteProperty.Y|block": "y",
"Math.randomBoolean|block": "wähle zufälligen Wahr- oder Falsch-Wert",
"Math|block": "Mathematik",
"Motor.AB|block": "A und B",
"MotorCommand.Break|block": "Pause",
"MotorCommand.Coast|block": "auslaufen",
"MotorCommand.Sleep|block": "schlafen",
"Note.CSharp3|block": "C#3",
"Note.CSharp4|block": "C#4",
"Note.CSharp5|block": "C#5",
"Note.CSharp|block": "C#",
"Note.FSharp3|block": "F#3",
"Note.FSharp4|block": "F#4",
"Note.FSharp5|block": "F#5",
"Note.FSharp|block": "F#",
"Note.GSharp3|block": "G#3",
"Note.GSharp4|block": "G#4",
"Note.GSharp5|block": "G#5",
"Note.GSharp|block": "G#",
"PinPullMode.PullDown|block": "nach unten",
"PinPullMode.PullUp|block": "nach oben",
"Rotation.Pitch|block": "Winkel",
"Rotation.Roll|block": "rollen",
"String.charAt|block": "Zeichen an Position %pos aus|%this",
"String.compare|block": "vergleiche %this| mit %that",
"String.concat|block": "hänge %this| mit %other aneinander",
"String.fromCharCode|block": "Text aus ASCII-Code %code",
"String.isEmpty|block": "%this| ist leer",
"String.length|block": "Länge von %VALUE",
"String.substr|block": "extrahiere aus %this|beginnend mit %start|%length Zeichen",
"String|block": "Zeichenfolge",
"basic.clearScreen|block": "Bildschirminhalt löschen",
"basic.color|block": "%c",
"basic.forever|block": "dauerhaft",
"basic.pause|block": "pausiere (ms) %pause",
"basic.rgbw|block": "Rot %red|Grün %green|Blau %blue|Weiß %white",
"basic.setLedColor|block": "setze LED-Farbe auf %color=color_id",
"basic.showLeds|block": "zeige LEDs",
"basic.showNumber|block": "zeige|Nummer %number",
"basic.showString|block": "zeige|Zeichenfolge %text",
"basic|block": "Grundlagen",
"control.deviceName|block": "Gerätename",
"control.deviceSerialNumber|block": "Seriennnummer",
"control.eventSourceId|block": "%id",
"control.eventTimestamp|block": "Ereigniszeitstempel",
"control.eventValueId|block": "%id",
"control.eventValue|block": "Ereigniswert",
"control.inBackground|block": "im Hintergrund ausführen",
"control.onEvent|block": "wenn Ereignis|von Quelle %src=control_event_source_id|mit Wert %value=control_event_value_id",
"control.raiseEvent|block": "Ereignis auslösen|von Quelle %src=control_event_source_id|mit Wert %value=control_event_value_id",
"control.reset|block": "zurücksetzen",
"control.waitMicros|block": "Warte (µs)%micros",
"control|block": "Steuerung",
"game.addScore|block": "Ändere Spielstand um|%points",
"game.createSprite|block": "erzeuge Sprite an Position|x: %x|y:%y",
"game.gameOver|block": "Spiel beendet",
"game.score|block": "Spielstand",
"game.startCountdown|block": "Countdown| starten (ms) %duration",
"game|block": "Spiel",
"images.createBigImage|block": "erstelle großes Bild",
"images.createImage|block": "erstelle Bild",
"images|block": "Bilder",
"input.acceleration|block": "Beschleunigung (mg) |%NAME",
"input.buttonIsPressed|block": "Button|%NAME|ist gedrückt",
"input.compassHeading|block": "Kompassausrichtung (°)",
"input.lightLevel|block": "Lichtstärke",
"input.magneticForce|block": "Magnetkraft (µT) |%NAME",
"input.onButtonPressed|block": "wenn Knopf|%NAME|gedrückt",
"input.onGesture|block": "wenn |%NAME",
"input.onPinPressed|block": "wenn Pin %NAME|gedrückt",
"input.onPinReleased|block": "wenn Pin %NAME|losgelassen",
"input.pinIsPressed|block": "Pin %NAME|ist gedrückt",
"input.rotation|block": "Rotation (°)|%NAME",
"input.runningTime|block": "Laufzeit (ms)",
"input.setAccelerometerRange|block": "setze Bewegungsmesser auf|%range",
"input.temperature|block": "Temperatur (°C)",
"input|block": "Eingabe",
"led.brightness|block": "Helligkeit",
"led.plotBarGraph|block": "zeichne Balkendiagramm von %value|bis %high",
"led.plot|block": "Zeichne|x %x|y %y",
"led.point|block": "Punkt|x %x|y %y",
"led.setBrightness|block": "setze Helligkeit auf %value",
"led.stopAnimation|block": "halte Animation an",
"led.toggle|block": "Schalte zwischen|x %x|y %y",
"led.unplot|block": "schalte Pixel|x %x|y %y aus",
"led|block": "LED",
"motors.dualMotorPower|block": "Motor %motor an|mit %percent",
"motors.motorCommand|block": "Motor %command",
"motors.motorPower|block": "Motor an mit %percent",
"motors|block": "Motoren",
"music.beat|block": "%fraction|Takt",
"music.changeTempoBy|block": "ändere die Geschwindigkeit (bpm)|%value",
"music.noteFrequency|block": "%note",
"music.playTone|block": "spiele|Note %note=device_note|für %duration=device_beat",
"music.rest|block": "pausiere (ms)|%duration=device_beat",
"music.ringTone|block": "Klingelton (Hz) |%note = Device_note",
"music.setTempo|block": "ändere Geschwindigkeit auf (bpm)|%value",
"music.tempo|block": "Geschwindkeit (bpm)",
"music|block": "Musik",
"pins.analogReadPin|block": "lese analoge Werte von|Pin %name",
"pins.analogSetPeriod|block": "setze Zeitraum für analogen|Pin %pin|auf (µs)%micros",
"pins.analogWritePin|block": "schreibe analogen|Pin %name|auf %value",
"pins.digitalReadPin|block": "lese digitale Werte von|Pin %name",
"pins.digitalWritePin|block": "schreibe digitalen Wert von|pin %name|auf %value",
"pins.i2cReadNumber|block": "lese Nummer aus I2C|auf Adresse %address|im Format %format=i2c_sizeof",
"pins.i2cWriteNumber|block": "schreibe Nummer aus I2C|auf Adresse %address|mit Wert %value|im Format %format=i2c_sizeof",
"pins.map|block": "verteile %value|von niedrig %fromLow|von hoch %fromHigh| bis niedrig %toLow|bis hoch %toHigh",
"pins.onPulsed|block": "wenn|Pin %pin|gepulst %pulse",
"pins.pulseDuration|block": "Impulsdauer (µs)",
"pins.pulseIn|block": "Impuls in (µs)|Pin %name|mit %value",
"pins.servoSetPulse|block": "setze den Puls von Servo an|Pin %value|auf (µs) %micros",
"pins.servoWritePin|block": "schreibe Servo an|Pin %name|auf %value",
"pins.setPull|block": "setze Anziehungskraft von|Pin %pin|auf %pull",
"pins.spiWrite|block": "schreibe %value in SPI",
"pins|block": "Pins",
"serial.delimiters|block": "%del",
"serial.readLine|block": "serial|read line",
"serial.readUntil|block": "serial|read until %delimiter=serial_delimiter_conv",
"serial.redirect|block": "serial|redirect to|TX %tx|RX %rx|at baud rate %rate",
"serial.writeLine|block": "serial|write line %text",
"serial.writeNumber|block": "serial|write number %value",
"serial.writeString|block": "serial|write string %text",
"serial.writeValue|block": "serial|write value %name|= %value",
"serial|block": "Konsole",
"{id:category}Basic": "Grundlagen",
"{id:category}Control": "Steuerung",
"{id:category}Game": "Spiel",
"{id:category}Images": "Bilder",
"{id:category}Input": "Eingabe",
"{id:category}Led": "LED",
"{id:category}Math": "Mathematik",
"{id:category}Motors": "Motoren",
"{id:category}Music": "Musik",
"{id:category}Pins": "Pins",
"{id:category}Serial": "Konsole",
"{id:category}String": "Zeichenfolge",
"{id:category}Text": "Text"
"AcceleratorRange.EightG": "Der Bewegungssensor misst Kräfte bis 8g",
"AcceleratorRange.EightG|block": "8g",
"AcceleratorRange.FourG": "Der Bewegungssensor misst Kräfte bis 4g",
"AcceleratorRange.FourG|block": "4g",
"AcceleratorRange.OneG": "Der Bewegungssensor misst Kräfte bis 1g",
"AcceleratorRange.OneG|block": "1g",
"AcceleratorRange.TwoG": "Der Bewegungssensor misst Kräfte bis 2g",
"AcceleratorRange.TwoG|block": "2g",
"BaudRate.BaudRate115200|block": "115200",
"BaudRate.BaudRate9600|block": "9600",
"BeatFraction.Eighth|block": "1/8",
"BeatFraction.Half|block": "1/2",
"BeatFraction.Quarter|block": "1/4",
"BeatFraction.Sixteenth|block": "1/16",
"BeatFraction.Whole|block": "1",
"Button.AB|block": "A+B",
"Colors.Blue|block": "Blau",
"Colors.Green|block": "Grün",
"Colors.Indigo|block": "Indigo",
"Colors.Orange|block": "Orange",
"Colors.Purple|block": "Violett",
"Colors.Red|block": "Rot",
"Colors.Violet|block": "Veilchenblau",
"Colors.White|block": "Weiß",
"Colors.Yellow|block": "Gelb",
"Delimiters.Dollar|block": "$",
"Delimiters.Hash|block": "#",
"Delimiters.NewLine|block": "Neue Zeile",
"Dimension.Strength|block": "Stärke",
"Dimension.X|block": "x",
"Dimension.Y|block": "y",
"Dimension.Z|block": "z",
"Direction.Left|block": "links",
"Direction.Right|block": "rechts",
"DisplayMode.BackAndWhite|block": "Schwarz-Weiß",
"DisplayMode.Greyscale|block": "Graustufen",
"EventCreationMode.CreateAndFire": "Calliope mini-Event wurde initialisiert, seine Event-Handler werden unverzüglich ausgeführt (nicht geeignet für die Nutzung bei Unterbrechungen!).",
"EventCreationMode.CreateOnly": "Calliope mini-Event wurde initialisiert, es wird keine weitere Verarbeitung vorgenommen.",
"Gesture.FreeFall": "Wird ausgeführt, wenn das Board fällt!",
"Gesture.FreeFall|block": "freier Fall",
"Gesture.LogoDown": "Wird ausgeführt, wenn das Logo nach unten zeigt und das Display vertikal ist.",
"Gesture.LogoDown|block": "Logo nach unten",
"Gesture.LogoUp": "Wird ausgeführt, wenn das Logo nach oben zeigt und das Display vertikal ist.",
"Gesture.LogoUp|block": "Logo oben",
"Gesture.ScreenDown": "Wird ausgeführt, wenn das Display nach oben zeigt und das Board horizontal ist.",
"Gesture.ScreenDown|block": "Display nach unten",
"Gesture.ScreenUp": "Wird ausgeführt, wenn das Display nach unten zeigt und das Board horizontal ist.",
"Gesture.ScreenUp|block": "Display nach oben",
"Gesture.Shake": "Wird erhöht, wenn geschüttelt",
"Gesture.Shake|block": "geschüttelt",
"Gesture.SixG": "Wird ausgeführt, ein 6g starker Stoß erkannt wird",
"Gesture.SixG|block": "6g",
"Gesture.ThreeG": "Wird ausgeführt, ein 3g starker Stoß erkannt wird",
"Gesture.ThreeG|block": "3g",
"Gesture.TiltLeft": "Wird ausgeführt, wenn das Display nach links zeigt",
"Gesture.TiltLeft|block": "nach links neigen",
"Gesture.TiltRight": "Wird ausgeführt, wenn das Display nach rechts zeigt",
"Gesture.TiltRight|block": "nach rechts neigen",
"LedSpriteProperty.Blink|block": "blinken",
"LedSpriteProperty.Brightness|block": "Helligkeit",
"LedSpriteProperty.Direction|block": "Richtung",
"LedSpriteProperty.X|block": "x",
"LedSpriteProperty.Y|block": "y",
"Math.randomBoolean|block": "wähle zufälligen Wahr- oder Falsch-Wert",
"Math|block": "Mathematik",
"Motor.AB|block": "A und B",
"MotorCommand.Break|block": "Pause",
"MotorCommand.Coast|block": "auslaufen",
"MotorCommand.Sleep|block": "schlafen",
"Note.CSharp3|block": "C#3",
"Note.CSharp4|block": "C#4",
"Note.CSharp5|block": "C#5",
"Note.CSharp|block": "C#",
"Note.FSharp3|block": "F#3",
"Note.FSharp4|block": "F#4",
"Note.FSharp5|block": "F#5",
"Note.FSharp|block": "F#",
"Note.GSharp3|block": "G#3",
"Note.GSharp4|block": "G#4",
"Note.GSharp5|block": "G#5",
"Note.GSharp|block": "G#",
"PinPullMode.PullDown|block": "nach unten",
"PinPullMode.PullUp|block": "nach oben",
"Rotation.Pitch|block": "Winkel",
"Rotation.Roll|block": "rollen",
"String.charAt|block": "Zeichen an Position %pos aus|%this",
"String.compare|block": "vergleiche %this| mit %that",
"String.concat|block": "hänge %this| mit %other aneinander",
"String.fromCharCode|block": "Text aus ASCII-Code %code",
"String.isEmpty|block": "%this| ist leer",
"String.length|block": "Länge von %VALUE",
"String.substr|block": "extrahiere aus %this|beginnend mit %start|%length Zeichen",
"String|block": "Zeichenfolge",
"basic.clearScreen|block": "Bildschirminhalt löschen",
"basic.color|block": "%c",
"basic.forever|block": "dauerhaft",
"basic.pause|block": "pausiere (ms) %pause",
"basic.rgbw|block": "Rot %red|Grün %green|Blau %blue|Weiß %white",
"basic.rgb|block": "Rot %red|Grün %green|Blau %blue",
"basic.setLedColor|block": "setze LED-Farbe auf %color=color_id",
"basic.showLeds|block": "zeige LEDs",
"basic.showNumber|block": "zeige|Nummer %number",
"basic.showString|block": "zeige|Zeichenfolge %text",
"basic|block": "Grundlagen",
"control.deviceName|block": "Gerätename",
"control.deviceSerialNumber|block": "Seriennnummer",
"control.eventSourceId|block": "%id",
"control.eventTimestamp|block": "Ereigniszeitstempel",
"control.eventValueId|block": "%id",
"control.eventValue|block": "Ereigniswert",
"control.inBackground|block": "im Hintergrund ausführen",
"control.onEvent|block": "wenn Ereignis|von Quelle %src=control_event_source_id|mit Wert %value=control_event_value_id",
"control.raiseEvent|block": "Ereignis auslösen|von Quelle %src=control_event_source_id|mit Wert %value=control_event_value_id",
"control.reset|block": "zurücksetzen",
"control.waitMicros|block": "Warte (µs)%micros",
"control|block": "Steuerung",
"game.addScore|block": "Ändere Spielstand um|%points",
"game.createSprite|block": "erzeuge Sprite an Position|x: %x|y:%y",
"game.gameOver|block": "Spiel beendet",
"game.score|block": "Spielstand",
"game.startCountdown|block": "Countdown| starten (ms) %duration",
"game|block": "Spiel",
"images.createBigImage|block": "erstelle großes Bild",
"images.createImage|block": "erstelle Bild",
"images|block": "Bilder",
"input.acceleration|block": "Beschleunigung (mg) |%NAME",
"input.buttonIsPressed|block": "Button|%NAME|ist gedrückt",
"input.compassHeading|block": "Kompassausrichtung (°)",
"input.lightLevel|block": "Lichtstärke",
"input.magneticForce|block": "Magnetkraft (µT) |%NAME",
"input.onButtonPressed|block": "wenn Knopf|%NAME|gedrückt",
"input.onGesture|block": "wenn |%NAME",
"input.onPinPressed|block": "wenn Pin %NAME|gedrückt",
"input.onPinReleased|block": "wenn Pin %NAME|losgelassen",
"input.pinIsPressed|block": "Pin %NAME|ist gedrückt",
"input.rotation|block": "Rotation (°)|%NAME",
"input.runningTime|block": "Laufzeit (ms)",
"input.setAccelerometerRange|block": "setze Bewegungsmesser auf|%range",
"input.temperature|block": "Temperatur (°C)",
"input|block": "Eingabe",
"led.brightness|block": "Helligkeit",
"led.plotBarGraph|block": "zeichne Balkendiagramm von %value|bis %high",
"led.plot|block": "Zeichne|x %x|y %y",
"led.point|block": "Punkt|x %x|y %y",
"led.setBrightness|block": "setze Helligkeit auf %value",
"led.stopAnimation|block": "halte Animation an",
"led.toggle|block": "Schalte zwischen|x %x|y %y",
"led.unplot|block": "schalte Pixel|x %x|y %y aus",
"led|block": "LED",
"motors.dualMotorPower|block": "Motor %motor an|mit %percent",
"motors.motorCommand|block": "Motor %command",
"motors.motorPower|block": "Motor an mit %percent",
"motors|block": "Motoren",
"music.beat|block": "%fraction|Takt",
"music.changeTempoBy|block": "ändere die Geschwindigkeit (bpm)|%value",
"music.noteFrequency|block": "%note",
"music.playTone|block": "spiele|Note %note=device_note|für %duration=device_beat",
"music.rest|block": "pausiere (ms)|%duration=device_beat",
"music.ringTone|block": "Klingelton (Hz) |%note = Device_note",
"music.setTempo|block": "ändere Geschwindigkeit auf (bpm)|%value",
"music.tempo|block": "Geschwindkeit (bpm)",
"music|block": "Musik",
"pins.analogReadPin|block": "lese analoge Werte von|Pin %name",
"pins.analogSetPeriod|block": "setze Zeitraum für analogen|Pin %pin|auf (µs)%micros",
"pins.analogWritePin|block": "schreibe analogen|Pin %name|auf %value",
"pins.digitalReadPin|block": "lese digitale Werte von|Pin %name",
"pins.digitalWritePin|block": "schreibe digitalen Wert von|pin %name|auf %value",
"pins.i2cReadNumber|block": "lese Nummer aus I2C|auf Adresse %address|im Format %format=i2c_sizeof",
"pins.i2cWriteNumber|block": "schreibe Nummer aus I2C|auf Adresse %address|mit Wert %value|im Format %format=i2c_sizeof",
"pins.map|block": "verteile %value|von niedrig %fromLow|von hoch %fromHigh| bis niedrig %toLow|bis hoch %toHigh",
"pins.onPulsed|block": "wenn|Pin %pin|gepulst %pulse",
"pins.pulseDuration|block": "Impulsdauer (µs)",
"pins.pulseIn|block": "Impuls in (µs)|Pin %name|mit %value",
"pins.servoSetPulse|block": "setze den Puls von Servo an|Pin %value|auf (µs) %micros",
"pins.servoWritePin|block": "schreibe Servo an|Pin %name|auf %value",
"pins.setPull|block": "setze Anziehungskraft von|Pin %pin|auf %pull",
"pins.spiWrite|block": "schreibe %value in SPI",
"pins|block": "Pins",
"serial.delimiters|block": "%del",
"serial.readLine|block": "serial|read line",
"serial.readUntil|block": "serial|read until %delimiter=serial_delimiter_conv",
"serial.redirect|block": "serial|redirect to|TX %tx|RX %rx|at baud rate %rate",
"serial.writeLine|block": "serial|write line %text",
"serial.writeNumber|block": "serial|write number %value",
"serial.writeString|block": "serial|write string %text",
"serial.writeValue|block": "serial|write value %name|= %value",
"serial|block": "Konsole",
"{id:category}Basic": "Grundlagen",
"{id:category}Control": "Steuerung",
"{id:category}Game": "Spiel",
"{id:category}Images": "Bilder",
"{id:category}Input": "Eingabe",
"{id:category}Led": "LED",
"{id:category}Math": "Mathematik",
"{id:category}Motors": "Motoren",
"{id:category}Music": "Musik",
"{id:category}Pins": "Pins",
"{id:category}Serial": "Konsole",
"{id:category}String": "Zeichenfolge",
"{id:category}Text": "Text"
}

View File

@ -4,14 +4,122 @@
/**
* Provides access to basic micro:bit functionality.
*/
//% color=#1E90FF weight=116 icon="\uf00a"
namespace basic {
/**
/**
* Draws an image on the LED screen.
* @param leds the pattern of LED to turn on/off
* @param interval time in milliseconds to pause after drawing
*/
//% help=basic/show-leds
//% weight=85 blockGap=8
//% imageLiteral=1 async
//% blockId=device_show_leds
//% block="show leds" icon="\uf00a"
//% parts="ledmatrix"
//% group="LED matrix"
void showLeds(ImageLiteral_ leds, int interval = 400) {
uBit.display.print(MicroBitImage(imageBytes(leds)), 0, 0, 0, interval);
}
/**
* Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.
* @param text the text to scroll on the screen, eg: "hi!"
* @param interval how fast to shift characters; eg: 150, 100, 200, -100
*/
//% help=basic/show-string
//% weight=100 blockGap=16
//% block="show|string %text || in an interval of %interval ms"
//% async
//% blockId=device_print_message
//% parts="ledmatrix"
//% text.shadowOptions.toString=true
//% expandableArgumentMode="toggle"
//% interval.defl=150
//% group="LED matrix"
void showString(String text, int interval = 150) {
if (interval <= 0)
interval = 1;
int l = text ? text->getUTF8Size() : 0;
if (l == 0) {
uBit.display.clear();
fiber_sleep(interval * 5);
} else if (l > 1) {
uBit.display.scroll(MSTR(text), interval);
} else {
uBit.display.printChar(text->getUTF8Data()[0], interval * 5);
}
}
/**
* Shows a sequence of LED screens as an animation.
* @param leds pattern of LEDs to turn on/off
* @param interval time in milliseconds between each redraw
*/
//% help=basic/show-animation weight=83 imageLiteral=1 async
//% parts="ledmatrix"
//% group="LED matrix"
void showAnimation(ImageLiteral_ leds, int interval = 400) {
uBit.display.animate(MicroBitImage(imageBytes(leds)), interval, 5, 0, 0);
}
/**
* Draws an image on the LED screen.
* @param leds pattern of LEDs to turn on/off
*/
//% help=basic/plot-leds weight=80
//% parts="ledmatrix"
//% group="LED matrix"
void plotLeds(ImageLiteral_ leds) {
MicroBitImage i(imageBytes(leds));
uBit.display.print(i, 0, 0, 0, 0);
}
/**
* Turn off all LEDs
*/
//% help=basic/clear-screen weight=75
//% blockId=device_clear_display block="clear screen"
//% parts="ledmatrix"
//% group="LED matrix"
//% advanced=true
void clearScreen() {
uBit.display.image.clear();
}
/**
* Repeats the code forever in the background. On each iteration, allows other codes to run.
* @param body code to execute
*/
//% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true
//% blockId=device_forever block="forever" icon="\uf01e"
//% group="Control"
void forever(Action a) {
runForever(a);
}
/**
* Pause for the specified time in milliseconds
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/
//% help=basic/pause weight=50
//% async block="pause (ms) %pause" blockGap=16
//% blockId=device_pause icon="\uf110"
//% pause.shadow=timePicker
//% group="Control"
void pause(int ms) {
fiber_sleep(ms);
}
/**
* Sets the color on the build-in LED. Set to 0 to turn off.
*/
//% blockId=device_set_led_color
//% block="set led to %color=colorNumberPicker"
//% weight=50
//% weight=10
//% group="RGB LED"
void setLedColor(int color) {
if (!color) {
uBit.rgb.off();
@ -31,104 +139,12 @@ namespace basic {
* Sets the color on the build-in LED. Set to 0 to turn off.
*/
//% blockId=device_turn_rgb_led_off block="turn build-in LED off"
//% weight=50
//% weight=10
//% group="RGB LED"
//% advanced=true
void turnRgbLedOff() {
uBit.rgb.off();
}
/**
* Draws an image on the LED screen.
* @param leds the pattern of LED to turn on/off
* @param interval time in milliseconds to pause after drawing
*/
//% help=basic/show-leds
//% weight=95 blockGap=8
//% imageLiteral=1 async
//% blockId=device_show_leds
//% block="show leds" icon="\uf00a"
//% parts="ledmatrix"
void showLeds(ImageLiteral_ leds, int interval = 400) {
uBit.display.print(MicroBitImage(imageBytes(leds)), 0, 0, 0, interval);
}
/**
* Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.
* @param text the text to scroll on the screen, eg: "hi!"
* @param interval how fast to shift characters; eg: 150, 100, 200, -100
*/
//% help=basic/show-string
//% weight=87 blockGap=16
//% block="show|string %text"
//% async
//% blockId=device_print_message
//% parts="ledmatrix"
//% text.shadowOptions.toString=true
void showString(String text, int interval = 150) {
if (interval <= 0)
interval = 1;
int l = text ? text->getUTF8Size() : 0;
if (l == 0) {
uBit.display.clear();
fiber_sleep(interval * 5);
} else if (l > 1) {
uBit.display.scroll(MSTR(text), interval);
} else {
uBit.display.printChar(text->getUTF8Data()[0], interval * 5);
}
}
/**
* Turn off all LEDs
*/
//% help=basic/clear-screen weight=79
//% blockId=device_clear_display block="clear screen"
//% parts="ledmatrix"
//% advanced=true
void clearScreen() {
uBit.display.image.clear();
}
/**
* Shows a sequence of LED screens as an animation.
* @param leds pattern of LEDs to turn on/off
* @param interval time in milliseconds between each redraw
*/
//% help=basic/show-animation imageLiteral=1 async
//% parts="ledmatrix"
void showAnimation(ImageLiteral_ leds, int interval = 400) {
uBit.display.animate(MicroBitImage(imageBytes(leds)), interval, 5, 0, 0);
}
/**
* Draws an image on the LED screen.
* @param leds pattern of LEDs to turn on/off
*/
//% help=basic/plot-leds weight=80
//% parts="ledmatrix"
void plotLeds(ImageLiteral_ leds) {
MicroBitImage i(imageBytes(leds));
uBit.display.print(i, 0, 0, 0, 0);
}
/**
* Repeats the code forever in the background. On each iteration, allows other codes to run.
* @param body code to execute
*/
//% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true
//% blockId=device_forever block="forever" icon="\uf01e"
void forever(Action a) {
runForever(a);
}
/**
* Pause for the specified time in milliseconds
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/
//% help=basic/pause weight=54
//% async block="pause (ms) %pause" blockGap=16
//% blockId=device_pause icon="\uf110"
//% pause.shadow=timePicker
void pause(int ms) {
fiber_sleep(ms);
}
}

View File

@ -37,17 +37,52 @@ enum Colors {
/**
* Provides access to basic micro:bit functionality.
*/
//% color=#54C9C9 weight=100
//% color=#54C9C9 weight=100 icon="\uf00a"
//% groups=['LED matrix', 'Control', 'RGB LED', 'others']
namespace basic {
/**
* Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.
* @param interval speed of scroll; eg: 150, 100, 200, -100
*/
//% help=basic/show-number
//% weight=95
//% blockId=device_show_number
//% block="show|number %number || in an interval of %interval ms" blockGap=8
//% async
//% parts="ledmatrix"
//% expandableArgumentMode="toggle"
//% interval.defl=150
//% group="LED matrix"
export function showNumber(value: number, interval?: number) {
showString(Math.roundWithPrecision(value, 2).toString(), interval);
}
/**
* Converts the color name to a number
*/
//% blockId=color_id block="%c" shim=TD_ID
//% group="RGB LED"
//% weight=1
//% deprecated=true
export function color(c: Colors): number {
return c;
}
/**
* Converts red, green, blue channels into a RGB color
* @param red value of the red channel between 0 and 255. eg: 255
* @param green value of the green channel between 0 and 255. eg: 255
* @param blue value of the blue channel between 0 and 255. eg: 255
*/
//% weight=3
//% blockId="core_rgb" block="red %red|green %green|blue %blue"
//% group="RGB LED"
export function rgb(red: number, green: number, blue: number): number {
return ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
}
/**
* Converts red, green, blue channels into a RGB color
* @param red value of the red channel between 0 and 255. eg: 255
@ -55,31 +90,21 @@ namespace basic {
* @param blue value of the blue channel between 0 and 255. eg: 255
* @param white value of the white channel between 0 and 255. eg: 0
*/
//% weight=1
//% blockId="core_rgb" block="red %red|green %green|blue %blue|white %white"
//% weight=2
//% blockId="core_rgbw" block="red %red|green %green|blue %blue|white %white"
//% group="RGB LED"
//% deprecated=true
export function rgbw(red: number, green: number, blue: number, white:number): number {
return ((white & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
}
/**
* Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.
* @param interval speed of scroll; eg: 150, 100, 200, -100
*/
//% help=basic/show-number
//% weight=96
//% blockId=device_show_number block="show|number %number" blockGap=8
//% async
//% parts="ledmatrix" interval.defl=150
export function showNumber(value: number, interval?: number) {
showString(Math.roundWithPrecision(value, 2).toString(), interval);
}
}
/**
* Pause for the specified time in milliseconds
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/
function pause(ms: number): void {
function pause(ms: number): void {
basic.pause(ms);
}
@ -89,4 +114,4 @@ function pause(ms: number): void {
*/
function forever(a: () => void): void {
basic.forever(a);
}
}

View File

@ -1,10 +1,10 @@
<xml xmlns="http://www.w3.org/1999/xhtml">
<block type="pins_on_pulsed" x="-157" y="130">
<field name="pin">DigitalPin.C5</field>
<field name="pin">DigitalPin.P5</field>
<field name="pulse">PulseValue.Low</field>
<statement name="HANDLER">
<block type="device_set_analog_pin">
<field name="name">AnalogPin.C6</field>
<field name="name">AnalogPin.P9</field>
<value name="value">
<shadow type="math_number">
<field name="NUM">5</field>
@ -12,7 +12,7 @@
</value>
<next>
<block type="device_set_analog_period">
<field name="pin">AnalogPin.C6</field>
<field name="pin">AnalogPin.P10</field>
<value name="micros">
<shadow type="math_number">
<field name="NUM">20000</field>
@ -20,7 +20,7 @@
</value>
<next>
<block type="device_set_digital_pin">
<field name="name">DigitalPin.C6</field>
<field name="name">DigitalPin.P6</field>
<value name="value">
<shadow type="math_number">
<field name="NUM">5</field>
@ -28,7 +28,7 @@
</value>
<next>
<block type="device_set_servo_pin">
<field name="name">AnalogPin.C5</field>
<field name="name">AnalogPin.P13</field>
<value name="value">
<shadow type="math_number">
<field name="NUM">5</field>
@ -36,7 +36,7 @@
</value>
<next>
<block type="device_set_servo_pulse">
<field name="value">AnalogPin.C6</field>
<field name="value">AnalogPin.P8</field>
<value name="micros">
<shadow type="math_number" id="Hx4bpmg|8KSH=b_`+XtP">
<field name="NUM">1500</field>
@ -65,7 +65,7 @@
<field name="NUM">0</field>
</shadow>
<block type="pins_pulse_in">
<field name="name">DigitalPin.C9</field>
<field name="name">DigitalPin.P9</field>
<field name="value">PulseValue.Low</field>
</block>
</value>
@ -102,7 +102,7 @@
<field name="NUM">0</field>
</shadow>
<block type="device_get_digital_pin">
<field name="name">DigitalPin.C9</field>
<field name="name">DigitalPin.P9</field>
</block>
</value>
<value name="value">
@ -110,7 +110,7 @@
<field name="NUM">0</field>
</shadow>
<block type="device_get_analog_pin">
<field name="name">AnalogPin.C6</field>
<field name="name">AnalogPin.P9</field>
</block>
</value>
<value name="repeat">
@ -120,12 +120,12 @@
</value>
<next>
<block type="spi_pins">
<field name="mosi">DigitalPin.C11</field>
<field name="miso">DigitalPin.C9</field>
<field name="sck">DigitalPin.C10</field>
<field name="mosi">DigitalPin.P11</field>
<field name="miso">DigitalPin.P9</field>
<field name="sck">DigitalPin.P10</field>
<next>
<block type="device_set_pull">
<field name="pin">DigitalPin.C9</field>
<field name="pin">DigitalPin.P9</field>
<field name="pull">PinPullMode.PullDown</field>
<next>
<block type="device_analog_pitch">
@ -141,11 +141,11 @@
</value>
<next>
<block type="device_set_pin_events">
<field name="pin">DigitalPin.C8</field>
<field name="pin">DigitalPin.P8</field>
<field name="type">PinEventType.Touch</field>
<next>
<block type="device_analog_set_pitch_pin">
<field name="name">AnalogPin.C6</field>
<field name="name">AnalogPin.P9</field>
<next>
<block type="spi_format">
<value name="bits">

View File

@ -150,31 +150,31 @@
<field name="mode">DisplayMode.Greyscale</field>
<next>
<block type="device_set_analog_pin">
<field name="name">AnalogPin.C4</field>
<field name="name">AnalogPin.P4</field>
<value name="value">
<shadow type="math_number_minmax" id=",:%8N*FL3wa-zFQ[+^$9">
<mutation min="0" max="1023" label="Value"></mutation>
<field name="SLIDER">1023</field>
</shadow>
<block type="device_get_analog_pin">
<field name="name">AnalogPin.C5</field>
<field name="name">AnalogPin.P13</field>
</block>
</value>
<next>
<block type="device_set_digital_pin">
<field name="name">DigitalPin.C10</field>
<field name="name">DigitalPin.P10</field>
<value name="value">
<shadow type="math_number_minmax" id="W~pvdj%jFEj?EHmT{81Z">
<mutation min="0" max="1" label="Value"></mutation>
<field name="SLIDER">0</field>
</shadow>
<block type="device_get_digital_pin">
<field name="name">DigitalPin.C15</field>
<field name="name">DigitalPin.P15</field>
</block>
</value>
<next>
<block type="device_set_analog_period">
<field name="pin">AnalogPin.C6</field>
<field name="pin">AnalogPin.P9</field>
<value name="micros">
<shadow type="math_number" id="4a@.1MdG`n=p;34mQOpC">
<field name="NUM">1234</field>
@ -230,7 +230,7 @@
</value>
<next>
<block type="device_set_servo_pulse">
<field name="value">AnalogPin.C4</field>
<field name="value">AnalogPin.P14</field>
<value name="micros">
<shadow type="math_number" id="@*C3kzJkeeUQ@s$N5?K}">
<field name="NUM">1500</field>
@ -510,7 +510,7 @@
</statement>
</block>
<block type="pins_on_pulsed" x="1538" y="929">
<field name="pin">DigitalPin.C10</field>
<field name="pin">DigitalPin.P10</field>
<field name="pulse">PulseValue.Low</field>
<statement name="HANDLER">
<block type="i2c_writenumber">
@ -575,8 +575,8 @@
<next>
<block type="spi_pins">
<field name="mosi">DigitalPin.P9</field>
<field name="miso">DigitalPin.C14</field>
<field name="sck">DigitalPin.C16</field>
<field name="miso">DigitalPin.P14</field>
<field name="sck">DigitalPin.P16</field>
<next>
<block type="control_reset"></block>
</next>

View File

@ -8,6 +8,21 @@ PXT_ABI(__aeabi_dsub)
PXT_ABI(__aeabi_ddiv)
PXT_ABI(__aeabi_dmul)
#if MICROBIT_CODAL
namespace codal {
int list_fibers(Fiber **dest) {
int i = 0;
for (Fiber *fib = codal::get_fiber_list(); fib; fib = fib->next) {
if (dest)
dest[i] = fib;
i++;
}
return i;
}
} // namespace codal
#endif
extern "C" void target_panic(int error_code) {
#if !MICROBIT_CODAL
// wait for serial to flush
@ -28,6 +43,7 @@ namespace pxt {
MicroBit uBit;
MicroBitEvent lastEvent;
bool serialLoggingDisabled;
void platform_init() {
microbit_seed_random();
@ -152,7 +168,8 @@ int current_time_ms() {
}
static void logwriten(const char *msg, int l) {
uBit.serial.send((uint8_t *)msg, l);
if (!serialLoggingDisabled)
uBit.serial.send((uint8_t *)msg, l);
}
static void logwrite(const char *msg) {

View File

@ -1,174 +1,4 @@
let compassImages = [
images.createImage(`
. . # . .
. . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. # . . .
. . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
# . . . .
. . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . . .
# . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . . .
. . . . .
# . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
# . . . .
. . . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
# . . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. # . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . # . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . # .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . #
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . #
. . . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . #
. . . . .
. . . . .
`),
images.createImage(`
. . . . .
. . . . #
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . . #
. . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . # .
. . . . .
. . # . .
. . . . .
. . . . .
`)];
let compassImagesDownside = [
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . # . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . # .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . #
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . #
. . . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . #
. . . . .
. . . . .
`),
images.createImage(`
. . . . .
. . . . #
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . . #
. . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . # .
. . . . .
. . # . .
. . . . .
. . . . .
`),
const compassImagesLeft = [
images.createImage(`
. . # . .
. . . . .
@ -226,7 +56,66 @@ let compassImagesDownside = [
. # . . .
`)];
const compassImagesRight = [
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . # . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . # .
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . #
`),
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . #
. . . . .
`),
images.createImage(`
. . . . .
. . . . .
. . # . #
. . . . .
. . . . .
`),
images.createImage(`
. . . . .
. . . . #
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . . #
. . . . .
. . # . .
. . . . .
. . . . .
`),
images.createImage(`
. . . # .
. . . . .
. . # . .
. . . . .
. . . . .
`)];
const compassImages = compassImagesLeft.concat(compassImagesRight);
const compassImagesDownside = compassImagesRight.concat(compassImagesLeft);
namespace basic {
@ -242,6 +131,7 @@ namespace basic {
//% interval.defl=600
//% parts="ledmatrix"
//% advanced=true
//% group="LED matrix"
export function showCompass(interval = 600) {
let i = 0
let startTime = input.runningTime()
@ -251,22 +141,15 @@ namespace basic {
while ((endTime) > (input.runningTime() + refreshRate)) {
i = Math.round((input.compassHeading() - 11.25) / 22.5)
if (input.isGesture(Gesture.ScreenDown)) {
compassImagesDownside[i].showImage(0, refreshRate)
} else {
compassImages[i].showImage(0, refreshRate)
}
let images = (input.isGesture(Gesture.ScreenDown)) ? compassImagesDownside : compassImages;
images[i].showImage(0, refreshRate)
}
rest = (endTime - input.runningTime())
if(rest > 0) {
i = Math.round((input.compassHeading() - 11.25) / 22.5)
if (input.isGesture(Gesture.ScreenDown)) {
compassImagesDownside[i].showImage(0, rest)
} else {
compassImages[i].showImage(0, rest)
}
let images = (input.isGesture(Gesture.ScreenDown)) ? compassImagesDownside : compassImages;
images[i].showImage(0, rest)
}
}

View File

@ -1,15 +1,51 @@
/// <reference no-default-lib="true"/>
enum ConsolePriority {
Debug = 0,
Log = 1,
Warning = 2,
Error = 3,
Silent = 4
}
/**
* Reading and writing data to the console output.
*/
//% weight=12 color=#002050 icon="\uf120"
//% advanced=true
namespace console {
type Listener = (text: string) => void;
type Listener = (priority: ConsolePriority, text: string) => void;
//% whenUsed
let listeners: Listener[] = undefined;
/**
* Minimum priority to send messages to listeners
*/
export let minPriority = ConsolePriority.Log;
let listeners: Listener[]
export function add(priority: ConsolePriority, message: any) {
if (priority < minPriority) return;
let text = inspect(message);
// add new line
text += "\n";
control.__log(priority, text)
// send to listeners
if (listeners)
for (let i = 0; i < listeners.length; ++i)
listeners[i](priority, text);
}
export function debug(text: any) {
add(ConsolePriority.Debug, text);
}
export function warn(text: any) {
add(ConsolePriority.Warning, text);
}
export function error(text: any) {
add(ConsolePriority.Error, text);
}
/**
* Write a line of text to the console output.
@ -17,15 +53,8 @@ namespace console {
*/
//% weight=90
//% help=console/log blockGap=8
export function log(text: any): void {
let stringified = inspect(text);
// pad text on the 32byte boundar
stringified += "\r\n";
control.__log(stringified);
// send to listeners
if (listeners)
for (let i = 0; i < listeners.length; ++i)
listeners[i](stringified);
export function log(value: any): void {
add(ConsolePriority.Log, value);
}
/**
@ -35,21 +64,8 @@ namespace console {
*/
//% weight=88 blockGap=8
//% help=console/log-value
export function logValue(name: any, value: number): void {
const nameText = inspect(name);
log(nameText ? `${nameText}: ${value}` : `${value}`)
}
/**
* Adds a listener for the log messages
* @param listener
*/
//%
export function addListener(listener: (text: string) => void) {
if (!listener) return;
if (!listeners)
listeners = [];
listeners.push(listener);
export function logValue(name: any, value: any): void {
log(name ? `${inspect(name)}: ${inspect(value)}` : `${inspect(value)}`)
}
/**
@ -82,13 +98,35 @@ namespace console {
keys = keys.slice(0, maxElements);
}
return `{${
keys.reduce(
(prev, currKey) => prev + `\n ${currKey}: ${obj[currKey]}`,
""
) + (snipped ? "\n ..." : "")
}
return `{${keys.reduce(
(prev, currKey) => prev + `\n ${currKey}: ${obj[currKey]}`,
""
) + (snipped ? "\n ..." : "")
}
}`;
}
}
/**
* Adds a listener for the log messages
* @param listener
*/
//%
export function addListener(listener: (priority: ConsolePriority, text: string) => void) {
if (!listeners) listeners = []
if (!listener || listeners.indexOf(listener) > -1) return;
listeners.push(listener);
}
/**
* Removes a listener
* @param listener
*/
//%
export function removeListener(listener: (priority: ConsolePriority, text: string) => void) {
if (!listener || !listeners) return;
const i = listeners.indexOf(listener);
if (i > -1)
listeners.splice(i, 1);
}
}

View File

@ -1,5 +1,7 @@
#include "pxt.h"
extern uint32_t __StackTop;
/**
* How to create the event.
*/
@ -271,8 +273,9 @@ namespace control {
* Blocks the current fiber for the given microseconds
* @param micros number of micro-seconds to wait. eg: 4
*/
//% help=control/wait-micros weight=29
//% help=control/wait-micros weight=29 async
//% blockId="control_wait_us" block="wait (µs)%micros"
//% micros.min=0 micros.max=6000
void waitMicros(int micros) {
sleep_us(micros);
}
@ -341,6 +344,15 @@ namespace control {
return microbit_serial_number();
}
/**
* Derive a unique, consistent 64-bit serial number of this device from internal data.
*/
//% help=control/device-long-serial-number
//% advanced=true
Buffer deviceLongSerialNumber() {
return mkBuffer((uint8_t*)&NRF_FICR->DEVICEID[0], sizeof(uint64_t));
}
/**
* Informs simulator/runtime of a MIDI message
* Internal function to support the simulator.
@ -354,8 +366,44 @@ namespace control {
*
*/
//%
void __log(String text) {
void __log(int priority, String text) {
if (NULL == text) return;
pxt::sendSerial(text->getUTF8Data(), text->getUTF8Size());
}
/**
* Allocates the next user notification event
*/
//% help=control/allocate-notify-event
int allocateNotifyEvent() {
#if MICROBIT_CODAL
return ::allocateNotifyEvent();
#else
static int notifyEv = 1024;
return ++notifyEv;
#endif
}
/** Write a message to DMESG debugging buffer. */
//%
void dmesg(String s) {
// this is no-op on v1
DMESG("# %s", s->getUTF8Data());
}
/** Write a message and value (pointer) to DMESG debugging buffer. */
//%
void dmesgPtr(String str, Object_ ptr) {
// this is no-op on v1
DMESG("# %s: %p", str->getUTF8Data(), ptr);
}
//%
uint32_t _ramSize()
{
return (uint32_t)&__StackTop & 0x1fffffff;
}
}

View File

@ -12,6 +12,11 @@ namespace control {
control.inBackground(a);
}
//% hidden=1 deprecated=1
export function runInBackground(a: () => void) {
control.inBackground(a);
}
/**
* Returns the value of a C++ runtime constant
*/
@ -31,6 +36,50 @@ namespace control {
return id;
}
export const enum PXT_PANIC {
CODAL_OOM = 20,
GC_OOM = 21,
GC_TOO_BIG_ALLOCATION = 22,
CODAL_HEAP_ERROR = 30,
CODAL_NULL_DEREFERENCE = 40,
CODAL_USB_ERROR = 50,
CODAL_HARDWARE_CONFIGURATION_ERROR = 90,
INVALID_BINARY_HEADER = 901,
OUT_OF_BOUNDS = 902,
REF_DELETED = 903,
SIZE = 904,
INVALID_VTABLE = 905,
INTERNAL_ERROR = 906,
NO_SUCH_CONFIG = 907,
NO_SUCH_PIN = 908,
INVALID_ARGUMENT = 909,
MEMORY_LIMIT_EXCEEDED = 910,
SCREEN_ERROR = 911,
MISSING_PROPERTY = 912,
INVALID_IMAGE = 913,
CALLED_FROM_ISR = 914,
HEAP_DUMPED = 915,
STACK_OVERFLOW = 916,
BLOCKING_TO_STRING = 917,
VM_ERROR = 918,
SETTINGS_CLEARED = 920,
SETTINGS_OVERLOAD = 921,
SETTINGS_SECRET_MISSING = 922,
DELETE_ON_CLASS = 923,
CAST_FIRST = 980,
CAST_FROM_UNDEFINED = 980,
CAST_FROM_BOOLEAN = 981,
CAST_FROM_NUMBER = 982,
CAST_FROM_STRING = 983,
CAST_FROM_OBJECT = 984,
CAST_FROM_FUNCTION = 985,
CAST_FROM_NULL = 989,
UNHANDLED_EXCEPTION = 999,
}
/**
* Display specified error code and stop the program.
*/
@ -61,6 +110,28 @@ namespace control {
*/
//% shim=pxtrt::runtimeWarning
export function runtimeWarning(message: string) { }
//% shim=pxt::programHash
export declare function programHash(): number;
//% shim=pxt::programName
export declare function programName(): string;
/** Returns estimated size of memory in bytes. */
//% shim=control::_ramSize
export function ramSize() {
return 32 * 1024 * 1024;
}
/** Runs the function and returns run time in microseconds. */
export function benchmark(f: () => void) {
const t0 = micros()
f()
let t = micros() - t0
if (t < 0)
t += 0x3fffffff
return t
}
}
/**

16
libs/core/enums.d.ts vendored
View File

@ -39,6 +39,22 @@ declare namespace basic {
}
declare const enum ButtonEvent {
//% blockIdentity="input.buttonEventValueId"
//% block="pressed down"
Down = 1, // MICROBIT_BUTTON_EVT_DOWN
//% blockIdentity="input.buttonEventValueId"
//% block="released up"
Up = 2, // MICROBIT_BUTTON_EVT_UP
//% blockIdentity="input.buttonEventValueId"
//% block="clicked"
Click = 3, // MICROBIT_BUTTON_EVT_CLICK
//% blockIdentity="input.buttonEventValueId"
//% block="long clicked"
LongClick = 4, // MICROBIT_BUTTON_EVT_LONG_CLICK
}
declare const enum Dimension {
//% block=x
X = 0,

View File

@ -188,9 +188,10 @@ enum ArrowNames {
//% blockIdentity=images.arrowNumber block="West"
West,
//% blockIdentity=images.arrowNumber block="North West"
NorthWest
NorthWest,
}
namespace basic {
/**
@ -200,13 +201,16 @@ namespace basic {
*/
//% weight=90 blockGap=8
//% blockId=basic_show_icon
//% block="show icon %i" icon="\uf00a"
//% block="show icon %i || for %interval ms" icon="\uf00a"
//% parts="ledmatrix"
//% help=basic/show-icon
//% icon.fieldEditor="imagedropdown"
//% icon.fieldOptions.columns="5"
//% icon.fieldOptions.width="380"
//% icon.fieldOptions.maxRows=4
//% expandableArgumentMode="toggle"
//% interval.defl=600
//% group="LED matrix"
export function showIcon(icon: IconNames, interval = 600) {
let res = images.iconImage(icon)
res.showImage(0, interval)
@ -221,18 +225,19 @@ namespace basic {
//% blockId=basic_show_arrow
//% block="show arrow %i=device_arrow"
//% parts="ledmatrix"
//% advanced=true
//% help=basic/show-arrow
//% deprecated=true
//% deprecated
//% group="LED matrix"
export function showArrow(direction: number, interval = 600) {
let res = images.arrowImage(direction)
res.showImage(0, interval)
}
}
namespace images {
//% weight=50 blockGap=8
//% help=images/arrow-image
//% blockId=builtin_arrow_image block="arrow image %i"
@ -298,6 +303,7 @@ namespace images {
}
}
//% weight=50 blockGap=8
//% help=images/icon-image
//% blockId=builtin_image block="icon image %i"

View File

@ -83,9 +83,11 @@ void plotImage(Image i, int xOffset = 0) {
/**
* Shows an frame from the image at offset ``x offset``.
* @param xOffset column index to start displaying the image
* @param interval time in milliseconds to pause after drawing
*/
//% help=images/show-image weight=80 blockNamespace=images
//% blockId=device_show_image_offset block="show image %sprite(myImage)|at offset %offset"
//% blockId=device_show_image_offset block="show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval"
//% interval.defl=400
//% blockGap=8 parts="ledmatrix" async
void showImage(Image sprite, int xOffset, int interval = 400) {
uBit.display.print(MicroBitImage(sprite->img), -xOffset, 0, 0, interval);
@ -109,7 +111,7 @@ void plotFrame(Image i, int xOffset) {
*/
//% help=images/scroll-image weight=79 async blockNamespace=images
//% blockId=device_scroll_image
//% block="scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay"
//% block="scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %interval"
//% blockGap=8 parts="ledmatrix"
void scrollImage(Image id, int frameOffset, int interval) {
MicroBitImage i(id->img);

View File

@ -7,6 +7,21 @@ enum class Button {
AB = MICROBIT_ID_BUTTON_AB,
};
enum class ButtonEvent {
//% blockIdentity="input.buttonEventValueId"
//% block="pressed down"
Down = MICROBIT_BUTTON_EVT_DOWN,
//% blockIdentity="input.buttonEventValueId"
//% block="released up"
Up = MICROBIT_BUTTON_EVT_UP,
//% blockIdentity="input.buttonEventValueId"
//% block="clicked"
Click = MICROBIT_BUTTON_EVT_CLICK,
//% blockIdentity="input.buttonEventValueId"
//% block="long clicked"
LongClick = MICROBIT_BUTTON_EVT_LONG_CLICK,
};
enum class Dimension {
//% block=x
X = 0,
@ -161,6 +176,21 @@ enum class MesDpadButtonInfo {
//% color=#B4009E weight=99 icon="\uf192"
namespace input {
/**
* Do something when a button (A, B or both A+B) receives an event.
* @param button the button
* @param body code to run when event is raised
* @param eventType event Type
*/
//% help=input/on-button-event weight=100 blockGap=16
//% blockId=device_button_selected_event block="on button %NAME| %eventType=control_button_event_value_id"
//% parts="buttonpair"
//% group="Events"
void onButtonEvent(Button button, int eventType, Action body) {
registerWithDal((int)button, eventType, body);
}
/**
* Do something when a button (A, B or both A+B) is pushed down and released again.
* @param button the button that needs to be pressed
@ -169,6 +199,8 @@ namespace input {
//% help=input/on-button-pressed weight=85 blockGap=16
//% blockId=device_button_event block="on button|%NAME|pressed"
//% parts="buttonpair"
//% deprecated=true
//% group="Events"
void onButtonPressed(Button button, Action body) {
registerWithDal((int)button, MICROBIT_BUTTON_EVT_CLICK, body);
}
@ -178,10 +210,11 @@ namespace input {
* @param gesture the type of gesture to track, eg: Gesture.Shake
* @param body code to run when gesture is raised
*/
//% help=input/on-gesture weight=84 blockGap=16
//% help=input/on-gesture weight=98 blockGap=16
//% blockId=device_gesture_event block="on |%NAME"
//% parts="accelerometer"
//% NAME.fieldEditor="gestures" NAME.fieldOptions.columns=4
//% group="Events"
void onGesture(Gesture gesture, Action body) {
int gi = (int)gesture;
if (gi == MICROBIT_ACCELEROMETER_EVT_3G && uBit.accelerometer.getRange() < 3)
@ -195,10 +228,11 @@ namespace input {
* Tests if a gesture is currently detected.
* @param gesture the type of gesture to detect, eg: Gesture.Shake
*/
//% help=input/is-gesture weight=10 blockGap=8
//% help=input/is-gesture weight=86 blockGap=8
//% blockId=deviceisgesture block="is %gesture gesture"
//% parts="accelerometer"
//% gesture.fieldEditor="gestures" gesture.fieldOptions.columns=4
//% group="States"
bool isGesture(Gesture gesture) {
// turn on acceleration
uBit.accelerometer.getX();
@ -206,13 +240,33 @@ namespace input {
return uBit.accelerometer.getGesture() == gi;
}
/**
* Do something when a pin receives an touch event (while also touching the GND pin).
* @param name the pin, eg: TouchPin.P0
* @param body the code to run when event is fired on pin
*/
//% help=input/on-pin-touch weight=99 blockGap=16
//% blockId=device_pin_custom_event block="on pin %name| %eventType=control_button_event_value_id"
//% group="Events"
void onPinTouchEvent(TouchPin name, int eventType, Action body) {
auto pin = getPin((int)name);
if (!pin) return;
// Forces the PIN to switch to makey-makey style detection.
pin->isTouched();
registerWithDal((int)name, eventType, body);
}
/**
* Do something when a pin is touched and released again (while also touching the GND pin).
* @param name the pin that needs to be pressed, eg: TouchPin.P0
* @param body the code to run when the pin is pressed
*/
//% help=input/on-pin-pressed weight=83 blockGap=32
//% help=input/on-pin-pressed weight=83 blockGap=16
//% blockId=device_pin_event block="on pin %name|pressed"
//% group="Events"
//% deprecated=true
void onPinPressed(TouchPin name, Action body) {
auto pin = getPin((int)name);
if (!pin) return;
@ -230,6 +284,8 @@ namespace input {
//% help=input/on-pin-released weight=6 blockGap=16
//% blockId=device_pin_released block="on pin %NAME|released"
//% advanced=true
//% group="Events"
//% deprecated=true
void onPinReleased(TouchPin name, Action body) {
auto pin = getPin((int)name);
if (!pin) return;
@ -243,11 +299,12 @@ namespace input {
* Get the button state (pressed or not) for ``A`` and ``B``.
* @param button the button to query the request, eg: Button.A
*/
//% help=input/button-is-pressed weight=60
//% help=input/button-is-pressed weight=89
//% block="button|%NAME|is pressed"
//% blockId=device_get_button2
//% icon="\uf192" blockGap=8
//% parts="buttonpair"
//% group="States"
bool buttonIsPressed(Button button) {
if (button == Button::A)
return uBit.buttonA.isPressed();
@ -262,9 +319,10 @@ namespace input {
* Get the pin state (pressed or not). Requires to hold the ground to close the circuit.
* @param name pin used to detect the touch, eg: TouchPin.P0
*/
//% help=input/pin-is-pressed weight=58
//% help=input/pin-is-pressed weight=87
//% blockId="device_pin_is_pressed" block="pin %NAME|is pressed"
//% blockGap=8
//% group="States"
bool pinIsPressed(TouchPin name) {
auto pin = getPin((int)name);
return pin && pin->isTouched();
@ -284,6 +342,7 @@ namespace input {
//% help=input/acceleration weight=58
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
//% parts="accelerometer"
//% group="Sensors"
int acceleration(Dimension dimension) {
switch (dimension) {
case Dimension::X: return uBit.accelerometer.getX();
@ -297,13 +356,37 @@ namespace input {
/**
* Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.
*/
//% help=input/light-level weight=57
//% help=input/light-level weight=59
//% blockId=device_get_light_level block="light level" blockGap=8
//% parts="ledmatrix"
//% group="Sensors"
int lightLevel() {
return uBit.display.readLightLevel();
}
/**
* gets the level of loudness from 0 (silent) to 255 (loud)
*/
//% blockId="soundLevel" weight=58
//% block="soundLevel" blockGap=8
//% group="Sensors"
int soundLevel() {
int level = uBit.io.P21.getAnalogValue();
int min = level;
int max = level;
for (int i = 0; i < 32; i++) {
level = uBit.io.P21.getAnalogValue();
if (level > max) {
max = level;
} else if (level < min) {
min = level;
}
}
level = floor((max - min + 0.5) / 4); //max can be up to 1023; + 0,5 to prevent division by 0, floor to get rid of decimals, divide by 4 to get a value between 0 and 255
return level;
}
/**
* Get the current compass heading in degrees.
*/
@ -311,6 +394,7 @@ namespace input {
//% weight=56
//% blockId=device_heading block="compass heading (°)" blockGap=8
//% parts="compass"
//% group="Sensors"
int compassHeading() {
return uBit.compass.heading();
}
@ -319,10 +403,11 @@ namespace input {
/**
* Gets the temperature in Celsius degrees (°C).
*/
//% weight=55
//% weight=57
//% help=input/temperature
//% blockId=device_temperature block="temperature (°C)" blockGap=8
//% parts="thermometer"
//% group="Sensors"
int temperature() {
return uBit.thermometer.getTemperature();
}
@ -334,6 +419,7 @@ namespace input {
//% help=input/rotation weight=52
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8
//% parts="accelerometer" advanced=true
//% group="Sensors"
int rotation(Rotation kind) {
switch (kind) {
case Rotation::Pitch: return uBit.accelerometer.getPitch();
@ -346,10 +432,11 @@ namespace input {
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
* @param dimension the x, y, or z dimension, eg: Dimension.X
*/
//% help=input/magnetic-force weight=51
//% help=input/magnetic-force weight=49
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8
//% parts="compass"
//% advanced=true
//% group="Sensors"
TNumber magneticForce(Dimension dimension) {
if (!uBit.compass.isCalibrated())
uBit.compass.calibrate();
@ -368,20 +455,58 @@ namespace input {
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_calibrate" block="calibrate compass"
//% weight=45
//% weight=20 gap=8
//% group="Configuration"
void calibrateCompass() {
uBit.compass.calibrate();
}
/**
* Returns 'true' when the compass is calibrated. Otherwise returns 'false'.
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_is_calibrated" block="is compass calibrated"
//% weight=19
//% group="System"
bool isCalibratedCompass() {
return (uBit.compass.isCalibrated() == 1);
}
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_clear_calibration" block="clear calibration compass"
//% weight=17
//% group="Configuration"
//% blockHidden=true
void clearCalibrationCompass() {
uBit.compass.clearCalibration();
}
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_assume_calibration" block="assume calibration compass"
//% weight=16
//% group="Configuration"
//% blockHidden=true
void assumeCalibrationCompass() {
uBit.compass.assumeCalibration();
}
/**
* Sets the accelerometer sample range in gravities.
* @param range a value describe the maximum strengh of acceleration measured
*/
//% help=input/set-accelerometer-range
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range"
//% weight=5
//% weight=22 gap=8
//% parts="accelerometer"
//% advanced=true
//% group="Configuration"
void setAccelerometerRange(AcceleratorRange range) {
uBit.accelerometer.setRange((int)range);
}

View File

@ -1,69 +1,26 @@
/**
* Events and data from sensors
*/
//% color=#C90072 weight=99
//% color=#C90072 weight=99 icon="\uf192"
//% groups=['Events', 'States', 'Sensors', 'Configuration', 'System', 'others']
namespace input {
/**
* Attaches code to run when the screen is facing up.
* @param body TODO
* Returns the value of a C++ runtime constant
*/
//% help=input/on-screen-up
export function onScreenUp(body: () => void): void {
onGesture(Gesture.ScreenUp, body);
//% weight=1 weight=19 blockId="control_button_event_value_id" block="%id"
//% shim=TD_ID advanced=true
//% blockHidden=true
export function buttonEventValueId(id: ButtonEvent): number {
return id;
}
/**
* Attaches code to run when the screen is facing down.
* @param body TODO
*/
//% help=input/on-screen-down
export function onScreenDown(body: () => void): void {
onGesture(Gesture.ScreenDown, body);
}
/**
* Attaches code to run when the device is shaken.
* @param body TODO
*/
//% deprecated=true
//% help=input/on-shake
export function onShake(body: () => void): void {
onGesture(Gesture.Shake, body);
}
/**
* Attaches code to run when the logo is oriented upwards and the board is vertical.
* @param body TODO
*/
//% help=input/on-logo-up
export function onLogoUp(body: () => void): void {
onGesture(Gesture.LogoUp, body);
}
/**
* Attaches code to run when the logo is oriented downwards and the board is vertical.
* @param body TODO
*/
//% help=input/on-logo-down
export function onLogoDown(body: () => void): void {
onGesture(Gesture.LogoDown, body);
}
/**
* Obsolete, use input.calibrateCompass instead.
*/
//% weight=0 help=input/calibrate-compass
export function calibrate() {
input.calibrateCompass();
}
/**
* Gets the number of milliseconds elapsed since power on.
*/
//% help=input/running-time weight=50 blockGap=8
//% blockId=device_get_running_time block="running time (ms)"
//% advanced=true
//% group="System"
export function runningTime() {
return control.millis();
}
@ -71,33 +28,12 @@ namespace input {
/**
* Gets the number of microseconds elapsed since power on.
*/
//% help=input/running-time-micros weight=49
//% help=input/running-time-micros weight=49 blockGap=8
//% blockId=device_get_running_time_micros block="running time (micros)"
//% advanced=true
//% group="System"
export function runningTimeMicros() {
return control.micros();
}
/**
* gets the level of loudness in 0-100%
*/
//% blockId="loudness"
//% block="Loudness"
export function soundLevel(): number {
let value = 0
let max = 0
let min = 1023
for (let index = 0; index < 32; index++) {
value = pins.analogReadPin(AnalogPin.MIC)
if (value > max) {
max = value
} else if (value < min) {
min = value
}
}
value = (max - min) * 977 / 10000
return value
}
}

View File

@ -1,7 +1,41 @@
#include "pxt.h"
#if MICROBIT_CODAL
#include "neopixel.h"
// WS2812B timings, datasheet v1
// 0 - 0.25-0.55us hi 0.70-1.00us low
// 1 - 0.65-0.95us hi 0.30-0.60us low
// datasheet v5
// 0 - 0.22-0.38us hi 0.58-1.00us low
// 1 - 0.58-1.00us hi 0.58-1.00us low
// nrf52 asm timings:
// 0 0.34 - 0.78
// 1 0.80 - 0.59
extern "C" void __attribute__((long_call, section(".data")))
neopixel_send_buffer_nrf52(void *port500, uint32_t pinbr, const uint8_t *ptr, int numBytes);
__attribute__((noinline)) static void
neopixel_send_buffer_brightness(DevicePin &pin, const uint8_t *ptr, int numBytes, uint32_t br) {
if (br > 0x100)
br = 0x100;
pin.setDigitalValue(0);
target_wait_us(300); // initial reset
auto port = pin.name < 32 ? NRF_P0 : NRF_P1;
__disable_irq();
neopixel_send_buffer_nrf52((uint8_t *)(void *)port + 0x500, (pin.name & 31) | (br << 20), ptr,
numBytes);
__enable_irq();
}
static void neopixel_send_buffer(DevicePin &pin, const uint8_t *ptr, int numBytes) {
neopixel_send_buffer_brightness(pin, ptr, numBytes, 0x100);
}
#else
extern "C" void neopixel_send_buffer_core(DevicePin *pin, const uint8_t *ptr, int numBytes);
__attribute__((noinline)) static void neopixel_send_buffer(DevicePin &pin, const uint8_t *ptr,
@ -9,19 +43,32 @@ __attribute__((noinline)) static void neopixel_send_buffer(DevicePin &pin, const
// setup pin as digital
pin.setDigitalValue(0);
wait_us(300); // initial reset
__disable_irq();
neopixel_send_buffer_core(&pin, ptr, numBytes);
__enable_irq();
}
extern "C" void neopixel_send_buffer_brightness_core(DevicePin *pin, const uint8_t *ptr,
int numBytes, int br);
__attribute__((noinline)) static void
neopixel_send_buffer_brightness(DevicePin &pin, const uint8_t *ptr, int numBytes, int br) {
// setup pin as digital
pin.setDigitalValue(0);
wait_us(300); // initial reset
__disable_irq();
neopixel_send_buffer_brightness_core(&pin, ptr, numBytes, br);
__enable_irq();
}
#endif
namespace light {
/**
* Sends a color buffer to a light strip
**/
* Sends a color buffer to a light strip
**/
//% advanced=true
//%
void sendWS2812Buffer(Buffer buf, int pin) {
if (!buf || !buf->length)
return;
@ -29,12 +76,21 @@ void sendWS2812Buffer(Buffer buf, int pin) {
}
/**
* Sets the light mode of a pin
**/
* Sends a color buffer to a light strip
**/
//% advanced=true
//%
void setMode(int pin, int mode) {
void sendWS2812BufferWithBrightness(Buffer buf, int pin, int brightness) {
if (!buf || !buf->length)
return;
neopixel_send_buffer_brightness(*pxt::getPin(pin), buf->data, buf->length, brightness);
}
/**
* Sets the light mode of a pin
**/
//% advanced=true
//%
void setMode(int pin, int mode) {}
} // namespace light

38
libs/core/loops.ts Normal file
View File

@ -0,0 +1,38 @@
namespace loops {
/**
* Repeats the code forever in the background.
* After each iteration, allows other codes to run for a set duration
* so that it runs on a timer
* @param interval time (in ms) to wait between each iteration of the action.
* @param body code to execute
*/
//% weight=45 blockAllowMultiple=1
//% interval.shadow=longTimePicker
//% afterOnStart=true help=loops/every-interval
//% blockId=every_interval block="every $interval ms"
export function everyInterval(interval: number, a: () => void): void {
control.runInParallel(() => {
let start = 0;
let now = 0;
while (true) {
start = control.millis();
a();
now = control.millis();
pause(Math.max(0, interval - (now - start)));
}
});
}
/**
* Get the time field editor
* @param ms time duration in milliseconds, eg: 500, 1000
*/
//% blockId=longTimePicker block="%ms"
//% blockHidden=true shim=TD_ID
//% colorSecondary="#FFFFFF"
//% ms.fieldEditor="numberdropdown" ms.fieldOptions.decompileLiterals=true
//% ms.fieldOptions.data='[["100 ms", 100], ["200 ms", 200], ["500 ms", 500], ["1 second", 1000], ["1 minute", 60000], ["1 hour", 3600000]]'
export function __timePicker(ms: number): number {
return ms;
}
}

27
libs/core/microphone.ts Normal file
View File

@ -0,0 +1,27 @@
/**
* Events and data from sensors
*/
//% color=#C90072 weight=99
namespace input {
/**
* gets the level of loudness from 0 (silent) to 255 (loud)
*/
//% blockId="loudness"
//% block="Loudness"
//% deprecated=true
export function loudness(): number {
let value = 0
let max = pins.analogReadPin(AnalogPin.MIC)
let min = max
for (let index = 0; index < 32; index++) {
value = pins.analogReadPin(AnalogPin.MIC)
if (value > max) {
max = value
} else if (value < min) {
min = value
}
}
value = Math.floor((max - min) / 4)
return value
}
}

View File

@ -27,7 +27,8 @@ namespace motors {
*/
//% blockId=motor_on block="motor on at %percent \\%"
//% parts=dcmotor weight=90 blockGap=8
//% percent.shadow="speedPicker"
//% percent.shadow="speedPicker"
//% power.defl=100
void motorPower(int power) {
uBit.soundmotor.motorOn(power);
}
@ -51,6 +52,7 @@ namespace motors {
//% blockId=block_dual_motor block="motor %motor|at %percent \\%"
//% percent.shadow="speedPicker"
//% weight=80
//% duty_percent.defl=100
void dualMotorPower(Motor motor, int duty_percent) {
switch(motor) {
case Motor::A: if (duty_percent <= 0) uBit.soundmotor.motorAOff();

View File

@ -1,5 +1,10 @@
#include "pxt.h"
namespace pins {
void analogSetPitchVolume(int volume);
int analogPitchVolume();
}
namespace music {
/**
* Plays a tone through ``speaker`` for the given duration.
@ -18,4 +23,41 @@ namespace music {
}
/**
* Set the default output volume of the sound synthesizer.
* @param volume the volume 0...255
*/
//% blockId=synth_set_volume block="set volume %volume"
//% volume.min=0 volume.max=255
//% volume.defl=127
//% help=music/set-volume
//% weight=70
//% group="Volume"
//% blockGap=8
//% blockHidden=true
void setVolume(int volume) {
#if MICROBIT_CODAL
uBit.audio.setVolume(max(0, min(255, volume)));
#else
pins::analogSetPitchVolume(volume);
#endif
}
/**
* Returns the current output volume of the sound synthesizer.
*/
//% blockId=synth_get_volume block="volume"
//% help=music/volume
//% weight=69
//% group="Volume"
//% blockGap=8
//% blockHidden=true
int volume() {
#if MICROBIT_CODAL
return uBit.audio.getVolume();
#else
return pins::analogPitchVolume();
#endif
}
}

View File

@ -223,7 +223,7 @@ namespace music {
//% help=music/rest weight=79
//% blockId=device_rest block="rest(ms)|%duration=device_beat"
//% parts="speaker"
//% group="Tone"
//% group="Silence"
export function rest(ms: number): void {
playTone(0, ms);
}
@ -233,7 +233,7 @@ namespace music {
* Gets the frequency of a note.
* @param name the note name
*/
//% weight=50 help=music/note-frequency
//% weight=50
//% blockId=device_note block="%name"
//% shim=TD_ID color="#FFFFFF" colorSecondary="#FFFFFF"
//% name.fieldEditor="note" name.defl="262"
@ -241,6 +241,7 @@ namespace music {
//% useEnumVal=1
//% group="Tone"
//% blockGap=8
//% blockHidden=true
export function noteFrequency(name: Note): number {
return name;
}
@ -289,6 +290,7 @@ namespace music {
//% help=music/change-tempo-by weight=39
//% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8
//% group="Tempo"
//% weight=100
export function changeTempoBy(bpm: number): void {
init();
setTempo(beatsPerMinute + bpm);
@ -302,6 +304,7 @@ namespace music {
//% blockId=device_set_tempo block="set tempo to (bpm)|%value"
//% bpm.min=4 bpm.max=400
//% group="Tempo"
//% weight=99
export function setTempo(bpm: number): void {
init();
if (bpm > 0) {
@ -330,6 +333,7 @@ namespace music {
//% blockId=melody_on_event block="music on %value"
//% help=music/on-event weight=59 blockGap=32
//% group="Melody Advanced"
//% blockHidden=true
export function onEvent(value: MusicEvent, handler: () => void) {
control.onEvent(MICROBIT_MELODY_ID, value, handler);
}
@ -354,6 +358,7 @@ namespace music {
//% blockId=device_start_melody block="start melody %melody=device_builtin_melody| repeating %options"
//% parts="speaker"
//% group="Melody Advanced"
//% blockHidden=true
export function startMelody(melodyArray: string[], options: MelodyOptions = 1) {
init();
if (currentMelody != undefined) {
@ -453,7 +458,7 @@ namespace music {
//% help=music/stop-melody weight=59 blockGap=16
//% blockId=device_stop_melody block="stop melody $options"
//% parts="speaker"
//% group="Melody Advanced"
//% group="Silence"
export function stopMelody(options: MelodyStopOptions) {
if (options & MelodyStopOptions.Background)
startMelody([], MelodyOptions.OnceInBackground);
@ -461,6 +466,19 @@ namespace music {
startMelody([], MelodyOptions.Once);
}
/**
* Stop all sounds and melodies currently playing.
*/
//% help=music/stop-all-sounds
//% blockId=music_stop_all_sounds block="stop all sounds"
//% weight=10
//% group="Silence"
export function stopAllSounds() {
rest(0);
stopMelody(MelodyStopOptions.All);
}
/**
* Sets a custom playTone function for playing melodies
*/
@ -471,35 +489,6 @@ namespace music {
_playTone = f;
}
/**
* Set the default output volume of the sound synthesizer.
* @param volume the volume 0...255
*/
//% blockId=synth_set_volume block="set volume %volume"
//% parts="speaker"
//% volume.min=0 volume.max=255
//% volume.defl=127
//% help=music/set-volume
//% weight=70
//% group="Volume"
//% deprecated=true
export function setVolume(volume: number): void {
pins.analogSetPitchVolume(volume);
}
/**
* Returns the current output volume of the sound synthesizer.
*/
//% blockId=synth_get_volume block="volume"
//% parts="speaker"
//% help=music/volume
//% weight=69
//% group="Volume"
//% deprecated=true
export function volume(): number {
return pins.analogPitchVolume();
}
function playNextNote(melody: Melody): void {
// cache elements
let currNote = melody.nextNote();

View File

@ -1,5 +1,12 @@
#include "pxt.h"
#if MICROBIT_CODAL
#include "Pin.h"
#define PinCompat codal::Pin
#else
#define PinCompat MicroBitPin
#endif
enum class DigitalPin {
P0 = MICROBIT_ID_IO_P12, // edge connector 0
P1 = MICROBIT_ID_IO_P0, // edge connector 1
@ -111,7 +118,7 @@ namespace pins {
/**
* Read the specified pin or connector as either 0 or 1
* @param name pin to read from, eg: DigitalPin.P1
* @param name pin to read from, eg: DigitalPin.P0
*/
//% help=pins/digital-read-pin weight=30
//% blockId=device_get_digital_pin block="digital read|pin %name" blockGap=8
@ -123,7 +130,7 @@ namespace pins {
/**
* Set a pin or connector value to either 0 or 1.
* @param name pin to write to, eg: DigitalPin.P1
* @param name pin to write to, eg: DigitalPin.P0
* @param value value to set on the pin, 1 eg,0
*/
//% help=pins/digital-write-pin weight=29
@ -177,7 +184,7 @@ namespace pins {
/**
* Configure the pin as a digital input and generate an event when the pin is pulsed either high or low.
* @param name digital pin to register to, eg: DigitalPin.P1
* @param name digital pin to register to, eg: DigitalPin.P0
* @param pulse the value of the pulse, eg: PulseValue.High
*/
//% help=pins/on-pulsed weight=22 blockGap=16 advanced=true
@ -204,7 +211,7 @@ namespace pins {
/**
* Return the duration of a pulse at a pin in microseconds.
* @param name the pin which measures the pulse, eg: DigitalPin.P1
* @param name the pin which measures the pulse, eg: DigitalPin.P0
* @param value the value of the pulse, eg: PulseValue.High
* @param maximum duration in microseconds
*/
@ -217,6 +224,17 @@ namespace pins {
MicroBitPin* pin = getPin((int)name);
if (!pin) return 0;
#if MICROBIT_CODAL
// set polarity
pin->setPolarity(PulseValue::High == value ? 1 : 0);
// record pulse
int period = pin->getPulseUs(maxDuration);
// timeout
if (DEVICE_CANCELLED == period)
return 0;
// success!
return period;
#else
int pulse = value == PulseValue::High ? 1 : 0;
uint64_t tick = system_timer_current_time_us();
uint64_t maxd = (uint64_t)maxDuration;
@ -232,6 +250,7 @@ namespace pins {
}
uint64_t end = system_timer_current_time_us();
return end - start;
#endif
}
// TODO FIX THIS IN THE DAL!
@ -257,7 +276,6 @@ namespace pins {
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
void servoWritePin(AnalogPin name, int value) {
fixMotorIssue(name);
PINOP(setServoValue(value));
}
@ -284,9 +302,10 @@ namespace pins {
}
MicroBitPin* pitchPin = NULL;
MicroBitPin* pitchPin2 = NULL;
PinCompat* pitchPin = NULL;
PinCompat* pitchPin2 = NULL;
uint8_t pitchVolume = 0xff;
bool analogTonePlaying = false;
/**
* Set the pin used when using analog pitch or music.
@ -296,12 +315,13 @@ namespace pins {
//% help=pins/analog-set-pitch-pin weight=3 advanced=true
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
//% blockHidden=true
void analogSetPitchPin(AnalogPin name) {
pitchPin = getPin((int)name);
pitchPin2 = NULL;
}
void pinAnalogSetPitch(MicroBitPin* pin, int frequency, int ms) {
void pinAnalogSetPitch(PinCompat* pin, int frequency, int ms) {
if (frequency <= 0 || pitchVolume == 0) {
pin->setAnalogValue(0);
} else {
@ -318,8 +338,15 @@ namespace pins {
//% blockId=device_analog_set_pitch_volume block="analog set pitch volume $volume"
//% help=pins/analog-set-pitch-volume weight=3 advanced=true
//% volume.min=0 volume.max=255
//% blockHidden=true
void analogSetPitchVolume(int volume) {
pitchVolume = max(0, min(0xff, volume));
if (analogTonePlaying) {
int v = pitchVolume == 0 ? 0 : 1 << (pitchVolume >> 5);
if (NULL != pitchPin)
pitchPin->setAnalogValue(v);
}
}
/**
@ -327,6 +354,7 @@ namespace pins {
*/
//% blockId=device_analog_pitch_volume block="analog pitch volume"
//% help=pins/analog-pitch-volume weight=3 advanced=true
//% blockHidden=true
int analogPitchVolume() {
return pitchVolume;
}
@ -338,6 +366,7 @@ namespace pins {
*/
//% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms"
//% help=pins/analog-pitch weight=4 async advanced=true blockGap=8
//% blockHidden=true
void analogPitch(int frequency, int ms) {
// init pins if needed
if (NULL == pitchPin) {
@ -347,6 +376,7 @@ namespace pins {
#endif
}
// set pitch
analogTonePlaying = true;
if (NULL != pitchPin)
pinAnalogSetPitch(pitchPin, frequency, ms);
if (NULL != pitchPin2)
@ -356,16 +386,16 @@ namespace pins {
fiber_sleep(ms);
if (NULL != pitchPin)
pitchPin->setAnalogValue(0);
if (NULL != pitchPin2)
pitchPin2->setAnalogValue(0);
fiber_sleep(5);
analogTonePlaying = false;
// causes issues with v2 DMA.
// fiber_sleep(5);
}
}
/**
* Configure the pull directiion of of a pin.
* @param name pin to set the pull mode on, eg: DigitalPin.P1
* @param name pin to set the pull mode on, eg: DigitalPin.P0
* @param pull one of the mbed pull configurations, eg: PinPullMode.PullUp
*/
//% help=pins/set-pull weight=3 advanced=true
@ -373,7 +403,7 @@ namespace pins {
//% pin.fieldEditor="gridpicker" pin.fieldOptions.columns=4
//% pin.fieldOptions.tooltips="false" pin.fieldOptions.width="250"
void setPull(DigitalPin name, PinPullMode pull) {
#if MICROBIT_CODAL
#if MICROBIT_CODAL
codal::PullMode m = pull == PinPullMode::PullDown
? codal::PullMode::Down
: pull == PinPullMode::PullUp ? codal::PullMode::Up
@ -391,7 +421,7 @@ namespace pins {
/**
* Configure the events emitted by this pin. Events can be subscribed to
* using ``control.onEvent()``.
* @param name pin to set the event mode on, eg: DigitalPin.P1
* @param name pin to set the event mode on, eg: DigitalPin.P0
* @param type the type of events for this pin to emit, eg: PinEventType.Edge
*/
//% help=pins/set-events weight=4 advanced=true
@ -412,6 +442,21 @@ namespace pins {
return mkBuffer(NULL, size);
}
/**
* Set the matrix width for Neopixel strip (already assigned to a pin).
* Should be used in conjunction with `set matrix width` from Neopixel package.
* @param name pin of Neopixel strip, eg: DigitalPin.P1
* @param value width of matrix (at least ``2``)
*/
//% help=pins/neopixel-matrix-width weight=3 advanced=true
//% blockId=pin_neopixel_matrix_width block="neopixel matrix width|pin %pin %width" blockGap=8
//% pin.fieldEditor="gridpicker" pin.fieldOptions.columns=4
//% pin.fieldOptions.tooltips="false" pin.fieldOptions.width="250"
//% width.defl=5 width.min=2
//% blockHidden=true
void setMatrixWidth(DigitalPin pin, int width) {}
#if MICROBIT_CODAL
#define BUFFER_TYPE uint8_t*
#else
@ -500,7 +545,7 @@ namespace pins {
//% blockId=spi_format block="spi format|bits %bits|mode %mode"
void spiFormat(int bits, int mode) {
auto p = allocSPI();
p->format(bits, mode);
p->format(bits, mode);
}
#if MICROBIT_CODAL
@ -534,10 +579,26 @@ namespace pins {
*/
//% help=pins/push-button advanced=true
void pushButton(DigitalPin pin) {
new MicroBitButton((PinName)getPin((int)(pin))->name, (int)pin, MICROBIT_BUTTON_ALL_EVENTS, PinMode::PullUp);
}
/**
* Set the pin used when producing sounds and melodies. Default is P0.
* @param name pin to modulate pitch from
*/
//% blockId=pin_set_audio_pin block="set audio pin $name"
//% help=pins/set-audio-pin weight=3
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
//% weight=1
//% blockHidden=true
void setAudioPin(AnalogPin name) {
#if MICROBIT_CODAL
new MicroBitButton(PIN_ARG(pin), (int)pin, DEVICE_BUTTON_ALL_EVENTS, ACTIVE_LOW, codal::PullMode::Up);
uBit.audio.setPin(*getPin((int)name));
uBit.audio.setPinEnabled(true);
#else
new MicroBitButton(PIN_ARG(pin), PinMode::PullUp);
// v1 behavior
pins::analogSetPitchPin(name);
#endif
}
}
}

View File

@ -45,6 +45,7 @@ typedef RefMImage *Image;
extern MicroBit uBit;
extern MicroBitEvent lastEvent;
extern bool serialLoggingDisabled;
MicroBitPin *getPin(int id);

View File

@ -33,12 +33,16 @@
"gestures.jres",
"control.ts",
"control.cpp",
"controlgc.cpp",
"perfcounters.ts",
"interval.ts",
"gcstats.ts",
"console.ts",
"game.ts",
"led.cpp",
"led.ts",
"loops.ts",
"microphone.ts",
"motors.cpp",
"music.cpp",
"music.ts",
@ -49,12 +53,17 @@
"serial.ts",
"buffer.cpp",
"buffer.ts",
"json.ts",
"poll.ts",
"controlmessage.ts",
"pxtparts.json",
"advmath.cpp",
"trig.cpp",
"fixed.ts",
"templates.ts",
"sendbuffer.s",
"sendbuffernrf52.s",
"sendbufferbrightness.s",
"light.cpp",
"compass.ts",
"parts/speaker.svg",
@ -94,7 +103,8 @@
"yotta": {
"config": {
"microbit-dal": {
"fiber_user_data": 1
"fiber_user_data": 1,
"pxt": 1
}
},
"optionalConfig": {
@ -116,8 +126,7 @@
}
}
},
"userConfigs": [
{
"userConfigs": [{
"description": "No Pairing Required: Anyone can connect via Bluetooth.",
"config": {
"microbit-dal": {
@ -140,19 +149,7 @@
}
}
}
},
{
"description": "Passkey pairing: Pairing requires 6 digit key to pair.",
"config": {
"microbit-dal": {
"bluetooth": {
"open": 0,
"whitelist": 1,
"security_level": "SECURITY_MODE_ENCRYPTION_WITH_MITM"
}
}
}
}
]
}
}
}

View File

@ -16,14 +16,13 @@ void debuglog(const char *format, ...);
#define GC_MAX_ALLOC_SIZE 9000
#define GC_BLOCK_SIZE 256
#define NON_GC_HEAP_RESERVATION 1024
#ifdef CODAL_CONFIG_H
#define MICROBIT_CODAL 1
#else
#define MICROBIT_CODAL 0
#define GC_BLOCK_SIZE 256
#endif
#if !MICROBIT_CODAL

View File

@ -0,0 +1,53 @@
.syntax unified
.section .text.neopixel_send_buffer_brightness_core
.global neopixel_send_buffer_brightness_core
neopixel_send_buffer_brightness_core:
push {r4,r5,r6,r7,lr}
mov r4, r1 // ptr
mov r5, r2 // len
mov r7, r3 // get the brightness figure
ldr r0, [r0, #8] // get mbed DigitalOut from MicroBitPin
ldr r1, [r0, #4] // r1-mask for this pin
ldr r2, [r0, #16] // r2-clraddr
ldr r3, [r0, #12] // r3-setaddr
b .start
.nextbit: // C0
str r1, [r3, #0] // pin := hi C2
tst r6, r0 // C3
bne .islate // C4
str r1, [r2, #0] // pin := lo C6
.islate:
lsrs r6, r6, #1 // r6 >>= 1 C7
bne .justbit // C8
// not just a bit - need new byte
adds r4, #1 // r4++ C9
subs r5, #1 // r5-- C10
bcc .stop // if (r5<0) goto .stop C11
.start:
movs r6, #0x80 // reset mask C12
ldrb r0, [r4, #0] // r0 := *r4
muls r0, r7 // hope we have single cycle multiplier...
lsrs r0, r0, #8 // r0 >>= 8 following multiplication
.common: // C13
str r1, [r2, #0] // pin := lo C15
nop // twiddle
nop // twaddle
b .nextbit // C20
.justbit: // C10
// no nops, branch taken is already 3 cycles
b .common // C13
.stop:
str r1, [r2, #0] // pin := lo
pop {r4,r5,r6,r7,pc}

View File

@ -0,0 +1,82 @@
.syntax unified
#ifndef NRF51
// put it in RAM
.section .data.neopixel_send_buffer_nrf52
.global neopixel_send_buffer_nrf52
.thumb
.type neopixel_send_buffer_nrf52, %function
neopixel_send_buffer_nrf52:
push {r4,r5,r6,r7,lr}
lsrs r7, r1, #20 // r7 - brightness
ands r1, #0xff
movs r4, #1
lsls r1, r4, r1 // r1 - mask
mov r4, r2 // ptr
mov r5, r3 // len
mov r3, r0 // port+0x500
b .start
.nextbit:
str r1, [r3, #0x8] // pin := hi
movs r2, #8
tst r6, r0
it eq
movseq r2, #3
.d1:
subs r2, #1
bne .d1
str r1, [r3, #0xC] // pin := lo
movs r2, #4
tst r6, r0
it eq
movseq r2, #6
lsrs r6, r6, #1 // r6 >>= 1
beq .reload
nop
nop
nop
.d0:
subs r2, #1
bne .d0
b .nextbit
.reload:
subs r2, #2 // offset following operations
.d2:
subs r2, #1
bne .d2
// not just a bit - need new byte
adds r4, #1 // r4++
subs r5, #1 // r5--
ble .stop // if (r5<=0) goto .stop
.start:
movs r6, #0x80 // reset mask
ldrb r0, [r4, #0] // r0 := *r4
muls r0, r7
lsrs r0, r0, #8 // r0 >>= 8
str r1, [r3, #0xC] // pin := lo
b .nextbit //
.stop:
str r1, [r3, #0xC] // pin := lo
pop {r4,r5,r6,r7,pc}
#endif

View File

@ -106,24 +106,29 @@ namespace serial {
}
/**
* Read multiple characters from the receive buffer. Pause until enough characters are present.
* @param length default buffer length, eg: 64
* Read multiple characters from the receive buffer.
* If length is positive, pauses until enough characters are present.
* @param length default buffer length
*/
//% blockId=serial_readbuffer block="serial|read buffer %length"
//% help=serial/read-buffer advanced=true weight=5
Buffer readBuffer(int length) {
if (length <= 0)
length = MICROBIT_SERIAL_READ_BUFFER_LENGTH;
auto buf = mkBuffer(NULL, length);
int read = uBit.serial.read(buf->data, buf->length);
if (read != length) {
auto prev = buf;
buf = mkBuffer(buf->data, read);
decrRC(prev);
auto mode = SYNC_SLEEP;
if (length <= 0) {
length = uBit.serial.getRxBufferSize();
mode = ASYNC;
}
return buf;
auto buf = mkBuffer(NULL, length);
auto res = buf;
registerGCObj(buf); // make sure buffer is pinned, while we wait for data
int read = uBit.serial.read(buf->data, buf->length, mode);
if (read != length) {
res = mkBuffer(buf->data, read);
}
unregisterGCObj(buf);
return res;
}
bool tryResolvePin(SerialPin p, PinName& name) {

362
libs/core/shims.d.ts vendored
View File

@ -37,9 +37,11 @@ declare interface Image {
/**
* Shows an frame from the image at offset ``x offset``.
* @param xOffset column index to start displaying the image
* @param interval time in milliseconds to pause after drawing
*/
//% help=images/show-image weight=80 blockNamespace=images
//% blockId=device_show_image_offset block="show image %sprite(myImage)|at offset %offset"
//% blockId=device_show_image_offset block="show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval"
//%
//% blockGap=8 parts="ledmatrix" async interval.defl=400 shim=ImageMethods::showImage
showImage(xOffset: int32, interval?: int32): void;
@ -58,7 +60,7 @@ declare interface Image {
*/
//% help=images/scroll-image weight=79 async blockNamespace=images
//% blockId=device_scroll_image
//% block="scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay"
//% block="scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %interval"
//% blockGap=8 parts="ledmatrix" shim=ImageMethods::scrollImage
scrollImage(frameOffset: int32, interval: int32): void;
@ -127,35 +129,21 @@ declare interface Image {
/**
* Provides access to basic micro:bit functionality.
*/
//% color=#1E90FF weight=116 icon="\uf00a"
declare namespace basic {
/**
* Sets the color on the build-in LED. Set to 0 to turn off.
*/
//% blockId=device_set_led_color
//% block="set led to %color=colorNumberPicker"
//% weight=50 shim=basic::setLedColor
function setLedColor(color: int32): void;
/**
* Sets the color on the build-in LED. Set to 0 to turn off.
*/
//% blockId=device_turn_rgb_led_off block="turn build-in LED off"
//% weight=50 shim=basic::turnRgbLedOff
function turnRgbLedOff(): void;
/**
* Draws an image on the LED screen.
* @param leds the pattern of LED to turn on/off
* @param interval time in milliseconds to pause after drawing
*/
//% help=basic/show-leds
//% weight=95 blockGap=8
//% weight=85 blockGap=8
//% imageLiteral=1 async
//% blockId=device_show_leds
//% block="show leds" icon="\uf00a"
//% parts="ledmatrix" interval.defl=400 shim=basic::showLeds
//% parts="ledmatrix"
//% group="LED matrix" interval.defl=400 shim=basic::showLeds
function showLeds(leds: string, interval?: int32): void;
/**
@ -164,30 +152,25 @@ declare namespace basic {
* @param interval how fast to shift characters; eg: 150, 100, 200, -100
*/
//% help=basic/show-string
//% weight=87 blockGap=16
//% block="show|string %text"
//% weight=100 blockGap=16
//% block="show|string %text || in an interval of %interval ms"
//% async
//% blockId=device_print_message
//% parts="ledmatrix"
//% text.shadowOptions.toString=true interval.defl=150 shim=basic::showString
//% text.shadowOptions.toString=true
//% expandableArgumentMode="toggle"
//%
//% group="LED matrix" interval.defl=150 shim=basic::showString
function showString(text: string, interval?: int32): void;
/**
* Turn off all LEDs
*/
//% help=basic/clear-screen weight=79
//% blockId=device_clear_display block="clear screen"
//% parts="ledmatrix"
//% advanced=true shim=basic::clearScreen
function clearScreen(): void;
/**
* Shows a sequence of LED screens as an animation.
* @param leds pattern of LEDs to turn on/off
* @param interval time in milliseconds between each redraw
*/
//% help=basic/show-animation imageLiteral=1 async
//% parts="ledmatrix" interval.defl=400 shim=basic::showAnimation
//% help=basic/show-animation weight=83 imageLiteral=1 async
//% parts="ledmatrix"
//% group="LED matrix" interval.defl=400 shim=basic::showAnimation
function showAnimation(leds: string, interval?: int32): void;
/**
@ -195,26 +178,57 @@ declare namespace basic {
* @param leds pattern of LEDs to turn on/off
*/
//% help=basic/plot-leds weight=80
//% parts="ledmatrix" imageLiteral=1 shim=basic::plotLeds
//% parts="ledmatrix"
//% group="LED matrix" imageLiteral=1 shim=basic::plotLeds
function plotLeds(leds: string): void;
/**
* Turn off all LEDs
*/
//% help=basic/clear-screen weight=75
//% blockId=device_clear_display block="clear screen"
//% parts="ledmatrix"
//% group="LED matrix"
//% advanced=true shim=basic::clearScreen
function clearScreen(): void;
/**
* Repeats the code forever in the background. On each iteration, allows other codes to run.
* @param body code to execute
*/
//% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true
//% blockId=device_forever block="forever" icon="\uf01e" shim=basic::forever
//% blockId=device_forever block="forever" icon="\uf01e"
//% group="Control" shim=basic::forever
function forever(a: () => void): void;
/**
* Pause for the specified time in milliseconds
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/
//% help=basic/pause weight=54
//% help=basic/pause weight=50
//% async block="pause (ms) %pause" blockGap=16
//% blockId=device_pause icon="\uf110"
//% pause.shadow=timePicker shim=basic::pause
//% pause.shadow=timePicker
//% group="Control" shim=basic::pause
function pause(ms: int32): void;
/**
* Sets the color on the build-in LED. Set to 0 to turn off.
*/
//% blockId=device_set_led_color
//% block="set led to %color=colorNumberPicker"
//% weight=10
//% group="RGB LED" shim=basic::setLedColor
function setLedColor(color: int32): void;
/**
* Sets the color on the build-in LED. Set to 0 to turn off.
*/
//% blockId=device_turn_rgb_led_off block="turn build-in LED off"
//% weight=10
//% group="RGB LED"
//% advanced=true shim=basic::turnRgbLedOff
function turnRgbLedOff(): void;
}
@ -222,6 +236,18 @@ declare namespace basic {
//% color=#B4009E weight=99 icon="\uf192"
declare namespace input {
/**
* Do something when a button (A, B or both A+B) receives an event.
* @param button the button
* @param body code to run when event is raised
* @param eventType event Type
*/
//% help=input/on-button-event weight=100 blockGap=16
//% blockId=device_button_selected_event block="on button %NAME| %eventType=control_button_event_value_id"
//% parts="buttonpair"
//% group="Events" shim=input::onButtonEvent
function onButtonEvent(button: Button, eventType: int32, body: () => void): void;
/**
* Do something when a button (A, B or both A+B) is pushed down and released again.
* @param button the button that needs to be pressed
@ -229,7 +255,9 @@ declare namespace input {
*/
//% help=input/on-button-pressed weight=85 blockGap=16
//% blockId=device_button_event block="on button|%NAME|pressed"
//% parts="buttonpair" shim=input::onButtonPressed
//% parts="buttonpair"
//% deprecated=true
//% group="Events" shim=input::onButtonPressed
function onButtonPressed(button: Button, body: () => void): void;
/**
@ -237,29 +265,43 @@ declare namespace input {
* @param gesture the type of gesture to track, eg: Gesture.Shake
* @param body code to run when gesture is raised
*/
//% help=input/on-gesture weight=84 blockGap=16
//% help=input/on-gesture weight=98 blockGap=16
//% blockId=device_gesture_event block="on |%NAME"
//% parts="accelerometer"
//% NAME.fieldEditor="gestures" NAME.fieldOptions.columns=4 shim=input::onGesture
//% NAME.fieldEditor="gestures" NAME.fieldOptions.columns=4
//% group="Events" shim=input::onGesture
function onGesture(gesture: Gesture, body: () => void): void;
/**
* Tests if a gesture is currently detected.
* @param gesture the type of gesture to detect, eg: Gesture.Shake
*/
//% help=input/is-gesture weight=10 blockGap=8
//% help=input/is-gesture weight=86 blockGap=8
//% blockId=deviceisgesture block="is %gesture gesture"
//% parts="accelerometer"
//% gesture.fieldEditor="gestures" gesture.fieldOptions.columns=4 shim=input::isGesture
//% gesture.fieldEditor="gestures" gesture.fieldOptions.columns=4
//% group="States" shim=input::isGesture
function isGesture(gesture: Gesture): boolean;
/**
* Do something when a pin receives an touch event (while also touching the GND pin).
* @param name the pin, eg: TouchPin.P0
* @param body the code to run when event is fired on pin
*/
//% help=input/on-pin-touch weight=99 blockGap=16
//% blockId=device_pin_custom_event block="on pin %name| %eventType=control_button_event_value_id"
//% group="Events" shim=input::onPinTouchEvent
function onPinTouchEvent(name: TouchPin, eventType: int32, body: () => void): void;
/**
* Do something when a pin is touched and released again (while also touching the GND pin).
* @param name the pin that needs to be pressed, eg: TouchPin.P0
* @param body the code to run when the pin is pressed
*/
//% help=input/on-pin-pressed weight=83 blockGap=32
//% blockId=device_pin_event block="on pin %name|pressed" shim=input::onPinPressed
//% help=input/on-pin-pressed weight=83 blockGap=16
//% blockId=device_pin_event block="on pin %name|pressed"
//% group="Events"
//% deprecated=true shim=input::onPinPressed
function onPinPressed(name: TouchPin, body: () => void): void;
/**
@ -269,27 +311,31 @@ declare namespace input {
*/
//% help=input/on-pin-released weight=6 blockGap=16
//% blockId=device_pin_released block="on pin %NAME|released"
//% advanced=true shim=input::onPinReleased
//% advanced=true
//% group="Events"
//% deprecated=true shim=input::onPinReleased
function onPinReleased(name: TouchPin, body: () => void): void;
/**
* Get the button state (pressed or not) for ``A`` and ``B``.
* @param button the button to query the request, eg: Button.A
*/
//% help=input/button-is-pressed weight=60
//% help=input/button-is-pressed weight=89
//% block="button|%NAME|is pressed"
//% blockId=device_get_button2
//% icon="\uf192" blockGap=8
//% parts="buttonpair" shim=input::buttonIsPressed
//% parts="buttonpair"
//% group="States" shim=input::buttonIsPressed
function buttonIsPressed(button: Button): boolean;
/**
* Get the pin state (pressed or not). Requires to hold the ground to close the circuit.
* @param name pin used to detect the touch, eg: TouchPin.P0
*/
//% help=input/pin-is-pressed weight=58
//% help=input/pin-is-pressed weight=87
//% blockId="device_pin_is_pressed" block="pin %NAME|is pressed"
//% blockGap=8 shim=input::pinIsPressed
//% blockGap=8
//% group="States" shim=input::pinIsPressed
function pinIsPressed(name: TouchPin): boolean;
/**
@ -298,33 +344,45 @@ declare namespace input {
*/
//% help=input/acceleration weight=58
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
//% parts="accelerometer" shim=input::acceleration
//% parts="accelerometer"
//% group="Sensors" shim=input::acceleration
function acceleration(dimension: Dimension): int32;
/**
* Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.
*/
//% help=input/light-level weight=57
//% help=input/light-level weight=59
//% blockId=device_get_light_level block="light level" blockGap=8
//% parts="ledmatrix" shim=input::lightLevel
//% parts="ledmatrix"
//% group="Sensors" shim=input::lightLevel
function lightLevel(): int32;
/**
* gets the level of loudness from 0 (silent) to 255 (loud)
*/
//% blockId="soundLevel" weight=58
//% block="soundLevel" blockGap=8
//% group="Sensors" shim=input::soundLevel
function soundLevel(): int32;
/**
* Get the current compass heading in degrees.
*/
//% help=input/compass-heading
//% weight=56
//% blockId=device_heading block="compass heading (°)" blockGap=8
//% parts="compass" shim=input::compassHeading
//% parts="compass"
//% group="Sensors" shim=input::compassHeading
function compassHeading(): int32;
/**
* Gets the temperature in Celsius degrees (°C).
*/
//% weight=55
//% weight=57
//% help=input/temperature
//% blockId=device_temperature block="temperature (°C)" blockGap=8
//% parts="thermometer" shim=input::temperature
//% parts="thermometer"
//% group="Sensors" shim=input::temperature
function temperature(): int32;
/**
@ -333,17 +391,19 @@ declare namespace input {
*/
//% help=input/rotation weight=52
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8
//% parts="accelerometer" advanced=true shim=input::rotation
//% parts="accelerometer" advanced=true
//% group="Sensors" shim=input::rotation
function rotation(kind: Rotation): int32;
/**
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
* @param dimension the x, y, or z dimension, eg: Dimension.X
*/
//% help=input/magnetic-force weight=51
//% help=input/magnetic-force weight=49
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8
//% parts="compass"
//% advanced=true shim=input::magneticForce
//% advanced=true
//% group="Sensors" shim=input::magneticForce
function magneticForce(dimension: Dimension): number;
/**
@ -351,18 +411,49 @@ declare namespace input {
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_calibrate" block="calibrate compass"
//% weight=45 shim=input::calibrateCompass
//% weight=20 gap=8
//% group="Configuration" shim=input::calibrateCompass
function calibrateCompass(): void;
/**
* Returns 'true' when the compass is calibrated. Otherwise returns 'false'.
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_is_calibrated" block="is compass calibrated"
//% weight=19
//% group="System" shim=input::isCalibratedCompass
function isCalibratedCompass(): boolean;
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_clear_calibration" block="clear calibration compass"
//% weight=17
//% group="Configuration"
//% blockHidden=true shim=input::clearCalibrationCompass
function clearCalibrationCompass(): void;
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate-compass advanced=true
//% blockId="input_compass_assume_calibration" block="assume calibration compass"
//% weight=16
//% group="Configuration"
//% blockHidden=true shim=input::assumeCalibrationCompass
function assumeCalibrationCompass(): void;
/**
* Sets the accelerometer sample range in gravities.
* @param range a value describe the maximum strengh of acceleration measured
*/
//% help=input/set-accelerometer-range
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range"
//% weight=5
//% weight=22 gap=8
//% parts="accelerometer"
//% advanced=true shim=input::setAccelerometerRange
//% advanced=true
//% group="Configuration" shim=input::setAccelerometerRange
function setAccelerometerRange(range: AcceleratorRange): void;
}
@ -410,8 +501,9 @@ declare namespace control {
* Blocks the current fiber for the given microseconds
* @param micros number of micro-seconds to wait. eg: 4
*/
//% help=control/wait-micros weight=29
//% blockId="control_wait_us" block="wait (µs)%micros" shim=control::waitMicros
//% help=control/wait-micros weight=29 async
//% blockId="control_wait_us" block="wait (µs)%micros"
//% micros.min=0 micros.max=6000 shim=control::waitMicros
function waitMicros(micros: int32): void;
/**
@ -465,6 +557,13 @@ declare namespace control {
//% advanced=true shim=control::deviceSerialNumber
function deviceSerialNumber(): int32;
/**
* Derive a unique, consistent 64-bit serial number of this device from internal data.
*/
//% help=control/device-long-serial-number
//% advanced=true shim=control::deviceLongSerialNumber
function deviceLongSerialNumber(): Buffer;
/**
* Informs simulator/runtime of a MIDI message
* Internal function to support the simulator.
@ -476,7 +575,53 @@ declare namespace control {
*
*/
//% shim=control::__log
function __log(text: string): void;
function __log(priority: int32, text: string): void;
/**
* Allocates the next user notification event
*/
//% help=control/allocate-notify-event shim=control::allocateNotifyEvent
function allocateNotifyEvent(): int32;
/** Write a message to DMESG debugging buffer. */
//% shim=control::dmesg
function dmesg(s: string): void;
/** Write a message and value (pointer) to DMESG debugging buffer. */
//% shim=control::dmesgPtr
function dmesgPtr(str: string, ptr: Object): void;
}
declare namespace control {
/**
* Force GC and dump basic information about heap.
*/
//% shim=control::gc
function gc(): void;
/**
* Force GC and halt waiting for debugger to do a full heap dump.
*/
//% shim=control::heapDump
function heapDump(): void;
/**
* Set flags used when connecting an external debugger.
*/
//% shim=control::setDebugFlags
function setDebugFlags(flags: int32): void;
/**
* Record a heap snapshot to debug memory leaks.
*/
//% shim=control::heapSnapshot
function heapSnapshot(): void;
/**
* Return true if profiling is enabled in the current build.
*/
//% shim=control::profilingEnabled
function profilingEnabled(): boolean;
}
@ -607,8 +752,9 @@ declare namespace motors {
*/
//% blockId=motor_on block="motor on at %percent \\%"
//% parts=dcmotor weight=90 blockGap=8
//% percent.shadow="speedPicker" shim=motors::motorPower
function motorPower(power: int32): void;
//% percent.shadow="speedPicker"
//% power.defl=100 shim=motors::motorPower
function motorPower(power?: int32): void;
/**
* Send break, coast or sleep commands to the motor. Has no effect in dual-motor mode.
@ -622,8 +768,9 @@ declare namespace motors {
*/
//% blockId=block_dual_motor block="motor %motor|at %percent \\%"
//% percent.shadow="speedPicker"
//% weight=80 shim=motors::dualMotorPower
function dualMotorPower(motor: Motor, duty_percent: int32): void;
//% weight=80
//% duty_percent.defl=100 shim=motors::dualMotorPower
function dualMotorPower(motor: Motor, duty_percent?: int32): void;
}
declare namespace music {
@ -635,6 +782,31 @@ declare namespace music {
//%
//% parts="speaker" async useEnumVal=1 shim=music::speakerPlayTone
function speakerPlayTone(frequency: int32, ms: int32): void;
/**
* Set the default output volume of the sound synthesizer.
* @param volume the volume 0...255
*/
//% blockId=synth_set_volume block="set volume %volume"
//% volume.min=0 volume.max=255
//%
//% help=music/set-volume
//% weight=70
//% group="Volume"
//% blockGap=8
//% blockHidden=true volume.defl=127 shim=music::setVolume
function setVolume(volume?: int32): void;
/**
* Returns the current output volume of the sound synthesizer.
*/
//% blockId=synth_get_volume block="volume"
//% help=music/volume
//% weight=69
//% group="Volume"
//% blockGap=8
//% blockHidden=true shim=music::volume
function volume(): int32;
}
declare namespace pins {
@ -763,7 +935,8 @@ declare namespace pins {
//% blockId=device_analog_set_pitch_pin block="analog set pitch pin %name"
//% help=pins/analog-set-pitch-pin weight=3 advanced=true
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250" shim=pins::analogSetPitchPin
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
//% blockHidden=true shim=pins::analogSetPitchPin
function analogSetPitchPin(name: AnalogPin): void;
/**
@ -772,14 +945,16 @@ declare namespace pins {
*/
//% blockId=device_analog_set_pitch_volume block="analog set pitch volume $volume"
//% help=pins/analog-set-pitch-volume weight=3 advanced=true
//% volume.min=0 volume.max=255 shim=pins::analogSetPitchVolume
//% volume.min=0 volume.max=255
//% blockHidden=true shim=pins::analogSetPitchVolume
function analogSetPitchVolume(volume: int32): void;
/**
* Gets the volume the pitch pin from 0..255
*/
//% blockId=device_analog_pitch_volume block="analog pitch volume"
//% help=pins/analog-pitch-volume weight=3 advanced=true shim=pins::analogPitchVolume
//% help=pins/analog-pitch-volume weight=3 advanced=true
//% blockHidden=true shim=pins::analogPitchVolume
function analogPitchVolume(): int32;
/**
@ -788,7 +963,8 @@ declare namespace pins {
* @param ms duration of the pitch in milli seconds.
*/
//% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms"
//% help=pins/analog-pitch weight=4 async advanced=true blockGap=8 shim=pins::analogPitch
//% help=pins/analog-pitch weight=4 async advanced=true blockGap=8
//% blockHidden=true shim=pins::analogPitch
function analogPitch(frequency: int32, ms: int32): void;
/**
@ -821,6 +997,20 @@ declare namespace pins {
//% shim=pins::createBuffer
function createBuffer(size: int32): Buffer;
/**
* Set the matrix width for Neopixel strip (already assigned to a pin).
* Should be used in conjunction with `set matrix width` from Neopixel package.
* @param name pin of Neopixel strip, eg: DigitalPin.P1
* @param value width of matrix (at least ``2``)
*/
//% help=pins/neopixel-matrix-width weight=3 advanced=true
//% blockId=pin_neopixel_matrix_width block="neopixel matrix width|pin %pin %width" blockGap=8
//% pin.fieldEditor="gridpicker" pin.fieldOptions.columns=4
//% pin.fieldOptions.tooltips="false" pin.fieldOptions.width="250"
//% width.min=2
//% blockHidden=true width.defl=5 shim=pins::setMatrixWidth
function setMatrixWidth(pin: DigitalPin, width?: int32): void;
/**
* Read `size` bytes from a 7-bit I2C `address`.
*/
@ -885,6 +1075,18 @@ declare namespace pins {
*/
//% help=pins/push-button advanced=true shim=pins::pushButton
function pushButton(pin: DigitalPin): void;
/**
* Set the pin used when producing sounds and melodies. Default is P0.
* @param name pin to modulate pitch from
*/
//% blockId=pin_set_audio_pin block="set audio pin $name"
//% help=pins/set-audio-pin weight=3
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
//% weight=1
//% blockHidden=true shim=pins::setAudioPin
function setAudioPin(name: AnalogPin): void;
}
@ -935,8 +1137,9 @@ declare namespace serial {
function writeBuffer(buffer: Buffer): void;
/**
* Read multiple characters from the receive buffer. Pause until enough characters are present.
* @param length default buffer length, eg: 64
* Read multiple characters from the receive buffer.
* If length is positive, pauses until enough characters are present.
* @param length default buffer length
*/
//% blockId=serial_readbuffer block="serial|read buffer %length"
//% help=serial/read-buffer advanced=true weight=5 shim=serial::readBuffer
@ -1110,10 +1313,15 @@ declare namespace light {
/**
* Sends a color buffer to a light strip
**/
//% advanced=true
//% shim=light::sendWS2812Buffer
//% advanced=true shim=light::sendWS2812Buffer
function sendWS2812Buffer(buf: Buffer, pin: int32): void;
/**
* Sends a color buffer to a light strip
**/
//% advanced=true shim=light::sendWS2812BufferWithBrightness
function sendWS2812BufferWithBrightness(buf: Buffer, pin: int32, brightness: int32): void;
/**
* Sets the light mode of a pin
**/

View File

@ -0,0 +1,28 @@
#include "pxt.h"
namespace music {
/**
* Internal use only
**/
//% async
void __playSoundExpression(String nodes, bool waitTillDone) {
#if MICROBIT_CODAL
if (waitTillDone)
uBit.audio.soundExpressions.play(MSTR(nodes));
else
uBit.audio.soundExpressions.playAsync(MSTR(nodes));
#else
target_panic(PANIC_VARIANT_NOT_SUPPORTED);
#endif
}
/**
* Internal use only
*/
//%
void __stopSoundExpressions() {
#if MICROBIT_CODAL
uBit.audio.soundExpressions.stop();
#endif
}
}

View File

@ -0,0 +1,59 @@
/**
* A sound expression.
*/
//% fixedInstances
//% blockNamespace=music
//% group="micro:bit (V2)"
class SoundExpression {
constructor(private notes: string) {
}
/**
* Starts to play a sound expression.
*/
//% block="play sound $this"
//% weight=80
//% blockGap=8
//% help=music/play
//% group="micro:bit (V2)"
//% parts=builtinspeaker
play() {
music.__playSoundExpression(this.notes, false)
}
/**
* Plays a sound expression until finished
*/
//% block="play sound $this until done"
//% weight=81
//% blockGap=8
//% help=music/play-until-done
//% group="micro:bit (V2)"
//% parts=builtinspeaker
playUntilDone() {
music.__playSoundExpression(this.notes, true)
}
}
namespace soundExpression {
//% fixedInstance whenUsed block="{id:soundexpression}giggle"
export const giggle = new SoundExpression("giggle");
//% fixedInstance whenUsed block="{id:soundexpression}happy"
export const happy = new SoundExpression("happy");
//% fixedInstance whenUsed block="{id:soundexpression}hello"
export const hello = new SoundExpression("hello");
//% fixedInstance whenUsed block="{id:soundexpression}mysterious"
export const mysterious = new SoundExpression("mysterious");
//% fixedInstance whenUsed block="{id:soundexpression}sad"
export const sad = new SoundExpression("sad");
//% fixedInstance whenUsed block="{id:soundexpression}slide"
export const slide = new SoundExpression("slide");
//% fixedInstance whenUsed block="{id:soundexpression}soaring"
export const soaring = new SoundExpression("soaring");
//% fixedInstance whenUsed block="{id:soundexpression}spring"
export const spring = new SoundExpression("spring");
//% fixedInstance whenUsed block="{id:soundexpression}twinkle"
export const twinkle = new SoundExpression("twinkle");
//% fixedInstance whenUsed block="{id:soundexpression}yawn"
export const yawn = new SoundExpression("yawn");
}

53
libs/core/touchmode.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "pxt.h"
#if MICROBIT_CODAL
#else
#define MICROBIT_ID_LOGO 121
#endif
enum class TouchTargetMode {
//% block="capacitive"
Capacitive = 1,
//% block="resistive"
Resistive = 0
};
enum class TouchTarget {
//% block="P0"
P0 = MICROBIT_ID_IO_P0,
//% block="P1"
P1 = MICROBIT_ID_IO_P1,
//% block="P2"
P2 = MICROBIT_ID_IO_P2,
//% block="logo"
LOGO = MICROBIT_ID_LOGO
};
namespace pins {
/**
* Configure the touch detection for the pins and logo.
* P0, P1, P2 use resistive touch by default.
* The logo uses capacitative touch by default.
* @param name target to change the touch mode for
* @param mode the touch mode to use
*/
//% weight=60
//% blockId=device_touch_set_type block="set %name to touch mode %mode"
//% advanced=true
//% group="micro:bit (V2)"
//% help=pins/touch-set-mode
void touchSetMode(TouchTarget name, TouchTargetMode mode) {
#if MICROBIT_CODAL
const auto pin = name == TouchTarget::LOGO
? &uBit.io.logo : getPin((int)name);
if (pin) {
pin->isTouched(mode == TouchTargetMode::Capacitive
? codal::TouchMode::Capacitative : codal::TouchMode::Resistive);
}
#else
target_panic(PANIC_VARIANT_NOT_SUPPORTED);
#endif
}
}

View File

@ -9,6 +9,7 @@
"devices.ts"
],
"icon": "./static/packages/devices/icon.png",
"hidden": true,
"public": true,
"dependencies": {
"core": "file:../core",

View File

@ -1,6 +1,6 @@
{
"input": "Events and data from sensors",
"input": "Events and data from sensors\n\r\nEvents and data from sensors",
"input.onLoudSound": "Registers an event that runs when a loud sound is detected",
"input.setLoudSoundThreshold": "Sets the minimum threshold for a loud sound",
"input.soundLevel": "gets the level of loudness in 0-100%\n\nReads the loudness through the microphone from 0 (silent) to 255 (loud)"
"input.soundLevel": "gets the level of loudness from 0 (silent) to 255 (loud)\n\nReads the loudness through the microphone from 0 (silent) to 255 (loud)"
}

View File

@ -6,5 +6,6 @@
"input.soundLevel|block": "sound level",
"input|block": "input",
"{id:category}Input": "Input",
"{id:group}More": "More"
"{id:group}More": "More",
"{id:group}Sensors": "Sensors"
}

View File

@ -11,4 +11,4 @@
"dependencies": {
"core": "file:../core"
}
}
}

10833
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
{
"name": "pxt-calliopemini",
"version": "3.0.36",
"version": "3.0.67",
"description": "calliope mini target for Microsoft MakeCode (PXT)",
"keywords": [
"JavaScript",
"education",
"calliope",
"mini"
"microbit"
],
"repository": {
"type": "git",
@ -33,19 +32,19 @@
"docs/static/icons/favicon.ico"
],
"devDependencies": {
"@types/bluebird": "2.0.33",
"@types/marked": "0.3.0",
"@types/node": "8.0.53",
"@types/react": "16.0.25",
"@types/node": "8.10.66",
"@types/react": "16.4.7",
"@types/react-dom": "16.0.3",
"@types/web-bluetooth": "0.0.4",
"less": "2.7.3",
"react": "16.8.3",
"react-dom": "16.11.0",
"semantic-ui-less": "2.2.14",
"typescript": "^3.7.5"
"typescript": "4.2.3"
},
"dependencies": {
"pxt-common-packages": "7.0.4",
"pxt-core": "6.0.24"
"pxt-common-packages": "9.0.1",
"pxt-core": "7.0.12"
}
}

View File

@ -42,10 +42,10 @@
"gc": true,
"imageRefTag": 9,
"shimRenames": {
"sendBufferAsm": "light::sendWS2812Buffer"
},
"patches": {
"0.0.0 - 1.0.0": [
{
"0.0.0 - 1.0.0": [{
"type": "package",
"map": {
"microbit": "core",
@ -92,23 +92,19 @@
}
}
],
"0.0.0 - 1.4.12": [
{
"type": "api",
"map": {
"DisplayMode\\s*\\.\\s*BackAndWhite": "DisplayMode.BlackAndWhite"
}
"0.0.0 - 1.4.12": [{
"type": "api",
"map": {
"DisplayMode\\s*\\.\\s*BackAndWhite": "DisplayMode.BlackAndWhite"
}
]
}]
},
"hidSelectors": [
{
"usagePage": "0xFF00",
"usageId": "0x0001",
"vid": "0x1366",
"pid": "0x1025"
}
],
"hidSelectors": [{
"usagePage": "0xFF00",
"usageId": "0x0001",
"vid": "0x1366",
"pid": "0x1025"
}],
"webUSB": false,
"useNewFunctions": true
},
@ -116,7 +112,7 @@
"yottaTarget": "calliope-mini-classic-gcc",
"yottaCorePackage": "microbit",
"githubCorePackage": "calliope-mini/microbit",
"gittag": "v2.2.0-rc6-calliope.rc3",
"gittag": "v2.2.0-rc6-calliope.rc3-iss0.3",
"serviceId": "calliope",
"dockerImage": "pext/yotta:latest"
},
@ -132,8 +128,7 @@
"continueBlock": true,
"functionsOptions": {
"useNewFunctions": true,
"extraFunctionEditorTypes": [
{
"extraFunctionEditorTypes": [{
"typeName": "game.LedSprite",
"label": "LedSprite",
"icon": "send",
@ -149,7 +144,8 @@
},
"onStartColor": "#54C9C9",
"onStartNamespace": "basic",
"onStartWeight": 54
"onStartWeight": 60,
"onStartGroup": "Control"
},
"simulator": {
"autoRun": true,
@ -208,9 +204,9 @@
"C15": "C_P15",
"C19": "C_P19",
"C20": "C_P20",
"EXT_PWR":"EXT_PWR",
"SPKR":"SPKR",
"BTN_A": "BTN_A",
"EXT_PWR": "EXT_PWR",
"SPKR": "SPKR",
"BTN_A": "BTN_A",
"BTN_B": "BTN_B",
"MOTOR1": "M_OUT1",
"MOTOR2": "M_OUT2"
@ -299,7 +295,14 @@
"organizationUrl": "https://makecode.com/",
"organizationLogo": "./static/Microsoft-logo_rgb_c-gray-square.png",
"organizationWideLogo": "./static/Microsoft-logo_rgb_c-white.png",
"homeScreenHero": "./static/hero.jpg",
"homeScreenHero": {
"imageUrl": "./static/hero.jpg",
"name": "Flashing Heart",
"url": "/calliope/firststeps/firstSteps",
"description": "Let's go start your first tutorial with Calliope mini",
"cardType": "tutorial"
},
"homeScreenHeroGallery": "/hero-banner",
"homeUrl": "https://makecode.calliope.cc/",
"embedUrl": "https://makecode.calliope.cc/",
"shareUrl": "https://makecode.calliope.cc/",
@ -313,22 +316,23 @@
"extendEditor": true,
"extendFieldEditors": true,
"enableTrace": true,
"ignoreDocsErrors": false,
"errorList": true,
"allowPackageExtensions": true,
"addNewTypeScriptFile": true,
"experiments": [
"allowPackageExtensions",
"instructions",
"accessibleBlocks",
"debugExtensionCode",
"bluetoothUartConsole",
"bluetoothPartialFlashing",
"simScreenshot",
"simGif"
"simGif",
"blocksErrorList"
],
"bluetoothUartFilters": [
{
"namePrefix": "Calliope mini"
}
],
"docMenu": [
{
"bluetoothUartFilters": [{
"namePrefix": "Calliope mini"
}],
"docMenu": [{
"name": "Support",
"path": "https://calliope.cc/en/impressum"
},
@ -416,6 +420,7 @@
"ru",
"si-LK",
"sk",
"sr",
"sv-SE",
"tr",
"uk",
@ -428,7 +433,8 @@
"browserDbPrefixes": {
"1": "v1",
"2": "v2",
"3": "v3"
"3": "v3",
"4": "v4"
},
"editorVersionPaths": {
"0": "v0"
@ -447,15 +453,46 @@
"chooseLanguageRestrictionOnNewProject": true,
"openProjectNewTab": true,
"python": true,
"appFlashingTroubleshoot": "/device/windows-app/troubleshoot"
"appFlashingTroubleshoot": "/device/windows-app/troubleshoot",
"immersiveReader": true,
"tutorialCodeValidation": true,
"downloadDialogTheme": {
"webUSBDeviceNames": ["Calliope mini CMSIS-DAP", "DAPLink CMSIS-DAP"],
"minimumFirmwareVersion": "0249",
"deviceIcon": "xicon microbit",
"deviceSuccessIcon": "xicon microbit-check",
"downloadMenuHelpURL": "/device/usb",
"downloadHelpURL": "/device/usb",
"firmwareHelpURL": "/device/usb/webusb/troubleshoot",
"troubleshootWebUSBHelpURL": "/device/usb/webusb/troubleshoot",
"incompatibleHardwareHelpURL": "/device/v2",
"dragFileImage": "./static/download/transfer.png",
"connectDeviceImage": "./static/download/connect.png",
"selectDeviceImage": "./static/download/pair.png",
"connectionSuccessImage": "/static/download/connected.png",
"checkFirmwareVersionImage": "./static/download/firmware.png",
"checkUSBCableImage": "./static/download/connect.pn",
"incompatibleHardwareImage": "/static/download/incompatible.png"
},
"winAppDeprImage": "/static/winapp.PNG",
"showWinAppDeprBanner": false
},
"queryVariants": {
"hidemenu": {
"appTheme": {
"hideMenuBar": true
}
},
"androidapp": {
"compile": {
"webUSB": false
},
"appTheme": {
"disableBlobObjectDownload": true
}
}
},
"uploadDocs": true,
"ignoreDocsErrors": true
}
"uploadDocs": true
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap uap3 mp">
<Identity Name="MicrobitEducationalFounda.196216C47839B" Version="1.1.0.0" Publisher="CN=DA0852B7-E38D-4F10-9429-7A96575322FD" />
<mp:PhoneIdentity PhoneProductId="5ddd542e-5ab4-48bc-b116-0782dc08ab97" PhonePublisherId="00000000-0000-0000-0000-000000000000" />

7
sim/compat.ts Normal file
View File

@ -0,0 +1,7 @@
namespace pxsim {
export interface CommonBoard extends CoreBoard
, EventBusBoard {
bus: EventBus;
edgeConnectorState: EdgeConnectorState;
}
}

View File

@ -4,7 +4,11 @@
namespace pxsim {
export class DalBoard extends CoreBoard
implements RadioBoard, LightBoard {
implements CommonBoard
, RadioBoard
, LightBoard
, MicrophoneBoard
, ControlMessageBoard {
// state & update logic for component services
ledMatrixState: LedMatrixState;
edgeConnectorState: EdgeConnectorState;
@ -20,17 +24,24 @@ namespace pxsim {
rgbLedState: number;
speakerState: SpeakerState;
fileSystem: FileSystemState;
logoTouch: Button;
speakerEnabled: boolean = true;
controlMessageState: ControlMessageState;
// visual
viewHost: visuals.BoardHost;
view: SVGElement;
// board hardware version
hardwareVersion = 1;
constructor() {
super()
// components
this.lightState = {};
this.fileSystem = new FileSystemState();
this.controlMessageState = new ControlMessageState(this);
this.builtinParts["ledmatrix"] = this.ledMatrixState = new LedMatrixState(runtime);
this.builtinParts["buttonpair"] = this.buttonPairState = new ButtonPairState({
ID_BUTTON_A: DAL.MICROBIT_ID_BUTTON_A,
@ -41,8 +52,10 @@ namespace pxsim {
});
this.builtinParts["edgeconnector"] = this.edgeConnectorState = new EdgeConnectorState({
pins: [
DAL.MICROBIT_ID_IO_P12,
DAL.MICROBIT_ID_IO_P0,
DAL.MICROBIT_ID_IO_P1,
DAL.MICROBIT_ID_IO_P16,
DAL.MICROBIT_ID_IO_P2,
DAL.MICROBIT_ID_IO_P3,
DAL.MICROBIT_ID_IO_P4,
@ -52,12 +65,10 @@ namespace pxsim {
DAL.MICROBIT_ID_IO_P8,
DAL.MICROBIT_ID_IO_P9,
DAL.MICROBIT_ID_IO_P10,
DAL.MICROBIT_ID_IO_P11,
DAL.MICROBIT_ID_IO_P12,
DAL.MICROBIT_ID_IO_P11,
DAL.MICROBIT_ID_IO_P13,
DAL.MICROBIT_ID_IO_P14,
DAL.MICROBIT_ID_IO_P15,
DAL.MICROBIT_ID_IO_P16,
0,
0,
DAL.MICROBIT_ID_IO_P19,
@ -71,13 +82,13 @@ namespace pxsim {
"P3": DAL.MICROBIT_ID_IO_P16
}
});
this.builtinParts["radio"] = this.radioState = new RadioState(runtime, {
this.builtinParts["radio"] = this.radioState = new RadioState(runtime, this, {
ID_RADIO: DAL.MICROBIT_ID_RADIO,
RADIO_EVT_DATAGRAM: DAL.MICROBIT_RADIO_EVT_DATAGRAM
});
this.builtinParts["microphone"] = this.microphoneState = new AnalogSensorState(3001 /* DEVICE_ID_MICROPHONE */, 52, 120, 75, 96);
this.builtinParts["microphone"] = this.microphoneState = new AnalogSensorState(3001 /* DEVICE_ID_MICROPHONE */, 0, 255, 75, 180);
this.builtinParts["accelerometer"] = this.accelerometerState = new AccelerometerState(runtime);
this.builtinParts["serial"] = this.serialState = new SerialState();
this.builtinParts["serial"] = this.serialState = new SerialState(runtime, this);
this.builtinParts["thermometer"] = this.thermometerState = new ThermometerState();
this.builtinParts["lightsensor"] = this.lightSensorState = new LightSensorState();
this.builtinParts["compass"] = this.compassState = new CompassState();
@ -97,25 +108,14 @@ namespace pxsim {
this.builtinPartVisuals["microservo"] = (xy: visuals.Coord) => visuals.mkMicroServoPart(xy);
}
receiveMessage(msg: SimulatorMessage) {
if (!runtime || runtime.dead) return;
switch (msg.type || "") {
case "eventbus":
const ev = <SimulatorEventBusMessage>msg;
this.bus.queue(ev.id, ev.eventid, ev.value);
break;
case "serial":
const data = (<SimulatorSerialMessage>msg).data || "";
this.serialState.receiveData(data);
break;
case "radiopacket":
const packet = <SimulatorRadioPacketMessage>msg;
this.radioState.receivePacket(packet);
break;
ensureHardwareVersion(version: number) {
if (version > this.hardwareVersion) {
this.hardwareVersion = version;
this.updateView();
}
}
initAsync(msg: SimulatorRunMessage): Promise<void> {
super.initAsync(msg);
@ -124,6 +124,21 @@ namespace pxsim {
const cmpDefs = msg.partDefinitions || {};
const fnArgs = msg.fnArgs;
const v2Parts: pxt.Map<boolean> = {
"microphone": true,
"logotouch": true,
"builtinspeaker": true,
"v2": true
};
if (msg.builtinParts) {
const v2PartsUsed = msg.builtinParts.filter(k => v2Parts[k])
if (v2PartsUsed.length) {
console.log(`detected v2 feature`, v2PartsUsed);
cmpsList.push(...v2PartsUsed);
this.hardwareVersion = 2;
}
}
const opts: visuals.BoardHostOpts = {
state: this,
boardDef: boardDef,
@ -134,6 +149,7 @@ namespace pxsim {
maxHeight: "100%",
highContrast: msg.highContrast
};
this.viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({
visual: boardDef.visual,
boardDef: boardDef,

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#009900" stroke="none" d="M13.922 2.495V19.3a2.35 2.35 0 11-3.845 0V2.495c0-.826.67-1.495 1.495-1.495h.855c.825 0 1.495.67 1.495 1.495zm-1.923 16.723a1.431 1.431 0 100 2.863 1.431 1.431 0 000-2.863zm5.426.001a1.431 1.431 0 100 2.863 1.431 1.431 0 000-2.863zm1.922-14.587V19.3a2.35 2.35 0 11-3.844 0V4.632c0-.826.67-1.495 1.495-1.495h.854c.826 0 1.495.67 1.495 1.495zM7.002 1.002c.826 0 1.495.669 1.495 1.494V19.3a2.35 2.35 0 11-3.848.006l.004-.006V2.496C4.653 1.67 5.323 1 6.148 1zM6.575 19.22a1.431 1.431 0 100 2.862 1.431 1.431 0 000-2.862z"/></svg>

After

Width:  |  Height:  |  Size: 646 B

View File

@ -1,9 +1,19 @@
CACHE MANIFEST
CACHE:
/cdn/bluebird.min.js
/cdn/pxtsim.js
/sim/sim.js
/sim/sounds/giggle.wav
/sim/sounds/happy.wav
/sim/sounds/hello.wav
/sim/sounds/mysterious.wav
/sim/sounds/sad.wav
/sim/sounds/slide.wav
/sim/sounds/soaring.wav
/sim/sounds/spring.wav
/sim/sounds/twinkle.wav
/sim/sounds/yawn.wav
NETWORK:
*

View File

@ -19,10 +19,22 @@ body {
margin: 0;
}
</style>
<script src="/cdn/bluebird.min.js"></script>
<script src="/cdn/pxtsim.js"></script>
<script src="/sim/sim.js"></script>
</head>
<script>
pxsim.soundExpressionFiles = {
"giggle": "/sim/sounds/giggle.wav",
"happy": "/sim/sounds/happy.wav",
"hello": "/sim/sounds/hello.wav",
"mysterious": "/sim/sounds/mysterious.wav",
"sad": "/sim/sounds/sad.wav",
"slide": "/sim/sounds/slide.wav",
"soaring": "/sim/sounds/soaring.wav",
"spring": "/sim/sounds/spring.wav",
"twinkle": "/sim/sounds/twinkle.wav",
"yawn": "/sim/sounds/yawn.wav"
}
</script>
</head>
<body>
</body>

Binary file not shown.

BIN
sim/public/sounds/happy.wav Normal file

Binary file not shown.

BIN
sim/public/sounds/hello.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
sim/public/sounds/sad.wav Normal file

Binary file not shown.

BIN
sim/public/sounds/slide.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
sim/public/sounds/yawn.wav Normal file

Binary file not shown.

View File

@ -1,4 +1,14 @@
namespace pxsim.input {
export function onButtonEvent(button: number, buttonEvent: number, handler: RefAction): void {
let b = board().buttonPairState;
if (button == b.props.ID_BUTTON_AB && !b.usesButtonAB) {
b.usesButtonAB = true;
runtime.queueDisplayUpdate();
}
pxtcore.registerWithDal(button, buttonEvent, handler);
}
// Deprecated
export function onButtonPressed(button: number, handler: RefAction): void {
let b = board().buttonPairState;
if (button == b.props.ID_BUTTON_AB && !b.usesButtonAB) {

View File

@ -8,8 +8,22 @@ namespace pxsim.input {
return b.heading;
}
export function assumeCalibrationCompass(){
}
export function clearCalibrationCompass(){
}
export function isCalibratedCompass(): boolean {
// let b = board().compassState;
// return b.isCalibrated;
// TODO
return true;
}
export function magneticForce(): number {
// TODO
return 0;
}
}

Some files were not shown because too many files have changed in this diff Show More