V4 updates for beta testing (#147)
* change simulator svg
* change radio image
* Remove google fonts cdn
* change color of 'advanced' button
* font fix
* font fix 2
* display fix
* change fullsceen simulator bg
* Continuous servo
* handle continuous state
* adding shims
* update rendering for continuous servos
* fixing sim
* fix sig
* typo
* fix sim
* bump pxt
* bump pxt
* rerun travis
* Input blocks revision
- add Button and Pin event types
- merge onPinPressed & onPinReleased in new onPinEvent function
- create new onButtonEvent function
* update input blocks in docs and tests
* remove device_pin_release block
* Hide DAL.x behind Enum
* bring back deprecated blocks, but hide them
* shims and locales files
* fix input.input. typing
* remove buildpr
* bump V3
* update simulator aspect ratio
* add Loudness Block
* revoke loudness block
* Adds soundLevel
To be replaced by pxt-common-packages when DAL is updated.
* Remove P0 & P3 from AnalogPin
* Fix Sound and replace AnalogPin.P0
* remove approved extensions
* V4 Updates from remote Repo
* locales
* add storage functions
* fix storage functions
* fix int/float values
* decrease decimal precision
* reorder blocks
* Update BLE Settings and Storage Blocks
* Fetch MicroBit changes up to v4.0.18
* Update timing for LED Matrix usage
* use 32kb ram (mini v2)
* resize gatt table
* Revert "use 32kb ram (mini v2)"
This reverts commit 4b15592f0f
.
* fix missleading indentation
* add support for 32kb and 16kb ram
* only MIT extensions in preferredRepos
* remove extensions without MIT License file
* add updated extensions
* add extensions with MIT license
Co-authored-by: Juri <gitkraken@juriwolf.de>
Co-authored-by: Juri <info@juriwolf.de>
8
.github/lock.yml
vendored
@ -30,13 +30,7 @@ lockLabel: false
|
|||||||
|
|
||||||
# Comment to post before locking. Set to `false` to disable
|
# Comment to post before locking. Set to `false` to disable
|
||||||
|
|
||||||
lockComment: >
|
lockComment: false
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
51
.github/workflows/codeql.yml
vendored
Normal 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
|
@ -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 }}
|
|
@ -1,9 +1,10 @@
|
|||||||
name: pxt-buildtarget
|
name: pxt-buildmain
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- 'master'
|
||||||
|
- 'main'
|
||||||
create:
|
create:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
31
.github/workflows/pxt-buildpr.yml
vendored
Normal 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
@ -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
|
7
.github/workflows/testghpkgs.yml
vendored
@ -11,9 +11,12 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [8.x]
|
node-version: [8.x]
|
||||||
|
branch: [stable3.0]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: ${{ matrix.branch }}
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
@ -45,5 +48,5 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
with:
|
with:
|
||||||
name: logs
|
name: logs-${{ matrix.branch }}
|
||||||
path: temp/ghpkgs/*.txt
|
path: temp/ghpkgs/*.txt
|
||||||
|
27
.travis.yml
@ -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
|
|
||||||
|
|
1
.vscode/settings.json
vendored
@ -1,6 +1,5 @@
|
|||||||
// Place your settings in this file to overwrite default and user settings.
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
{
|
{
|
||||||
"files.autoSave": "afterDelay",
|
|
||||||
"files.watcherExclude": {
|
"files.watcherExclude": {
|
||||||
"**/.git/objects/**": true,
|
"**/.git/objects/**": true,
|
||||||
"**/built/**": true,
|
"**/built/**": true,
|
||||||
|
19
.vscode/tasks.json
vendored
@ -1,20 +1,19 @@
|
|||||||
{
|
{
|
||||||
"version": "0.1.0",
|
"version": "2.0.0",
|
||||||
// Task runner is jake
|
// Task runner is jake
|
||||||
"command": "pxt",
|
"command": "pxt",
|
||||||
// Need to be executed in shell / cmd
|
|
||||||
"isShellCommand": true,
|
|
||||||
"showOutput": "always",
|
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
// TS build command is local.
|
"label": "serve",
|
||||||
"taskName": "serve",
|
"type": "shell",
|
||||||
// Make this the default build command.
|
"command": "pxt",
|
||||||
"isBuildCommand": true,
|
"args": [
|
||||||
// Use the redefined Typescript output problem matcher.
|
"serve"
|
||||||
|
],
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$tsc"
|
"$tsc"
|
||||||
]
|
],
|
||||||
|
"group": "build"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"folders": [
|
|
||||||
{
|
|
||||||
"path": "../pxt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "../pxt-common-packages"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
131
compiler/combiner.ts
Normal 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
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
2
docfiles/offline-app-trademarks.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Micro:bit and micro:bit logo are trademarks and/ or copyrights of the Micro:bit
|
||||||
|
Educational Foundation. © Micro:bit Educational Foundation. All rights reserved.
|
@ -78,6 +78,13 @@ input.onButtonPressed(Button.B, () => {
|
|||||||
|
|
||||||
We have tons of [projects](/projects), [examples](/examples) and [courses](/courses) to get your started!
|
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)
|
## [Command Line Tools](/cli)
|
||||||
|
|
||||||
|
BIN
docs/calliope/02_Hero_CalliopEO.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
docs/calliope/03_Hero_KidsLab.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/calliope/calliopeo-header.png
Normal file
After Width: | Height: | Size: 220 KiB |
21
docs/hero-banner.md
Normal 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
|
||||||
|
### ~
|
@ -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)
|
![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.
|
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.
|
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)
|
![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.
|
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!
|
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
After Width: | Height: | Size: 17 KiB |
BIN
docs/skillmap/img/spacet4.gif
Normal file
After Width: | Height: | Size: 84 KiB |
37
docs/skillmap/mini.md
Normal 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
@ -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
|
172
docs/skillmap/space/activity1.md
Normal 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!
|
BIN
docs/skillmap/space/img/space.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
docs/skillmap/space/img/spacet4.gif
Normal file
After Width: | Height: | Size: 84 KiB |
19
docs/skillmaps.md
Normal 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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
@ -12,7 +12,7 @@ export function renderUsbPairDialog(firmwareUrl?: string, failedOnce?: boolean):
|
|||||||
<div className="column">
|
<div className="column">
|
||||||
<div className="ui">
|
<div className="ui">
|
||||||
<div className="image">
|
<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>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<div className="description">
|
<div className="description">
|
||||||
@ -27,7 +27,7 @@ export function renderUsbPairDialog(firmwareUrl?: string, failedOnce?: boolean):
|
|||||||
<div className="column">
|
<div className="column">
|
||||||
<div className="ui">
|
<div className="ui">
|
||||||
<div className="image">
|
<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>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<div className="description">
|
<div className="description">
|
||||||
@ -51,7 +51,7 @@ export function renderUsbPairDialog(firmwareUrl?: string, failedOnce?: boolean):
|
|||||||
<div className="ui header inverted">{lf("Update Firmware")}</div>
|
<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>
|
<strong className="ui small">{lf("You must have version 0249 or above of the firmware")}</strong>
|
||||||
<div className="image">
|
<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>
|
</div>
|
||||||
<a className="ui button" role="button" href={firmwareUrl} target="_blank">{lf("Check Firmware")}</a>
|
<a className="ui button" role="button" href={firmwareUrl} target="_blank">{lf("Check Firmware")}</a>
|
||||||
</div>
|
</div>
|
||||||
@ -73,7 +73,7 @@ export function renderBrowserDownloadInstructions(): JSX.Element {
|
|||||||
<div className="column">
|
<div className="column">
|
||||||
<div className="ui">
|
<div className="ui">
|
||||||
<div className="image">
|
<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>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<div className="description">
|
<div className="description">
|
||||||
@ -88,7 +88,7 @@ export function renderBrowserDownloadInstructions(): JSX.Element {
|
|||||||
<div className="column">
|
<div className="column">
|
||||||
<div className="ui">
|
<div className="ui">
|
||||||
<div className="image">
|
<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>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<div className="description">
|
<div className="description">
|
||||||
|
@ -9,7 +9,7 @@ import * as flash from "./flash";
|
|||||||
import * as patch from "./patch";
|
import * as patch from "./patch";
|
||||||
|
|
||||||
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
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;
|
const manyAny = Math as any;
|
||||||
if (!manyAny.imul)
|
if (!manyAny.imul)
|
||||||
@ -24,35 +24,22 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
|
|||||||
};
|
};
|
||||||
|
|
||||||
const res: pxt.editor.ExtensionResult = {
|
const res: pxt.editor.ExtensionResult = {
|
||||||
hexFileImporters: [{
|
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);
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pxt.usb.setFilters([{
|
pxt.usb.setFilters([{
|
||||||
vendorId: 0x1366,
|
|
||||||
productId: 0x1025
|
|
||||||
},
|
|
||||||
{
|
|
||||||
vendorId: 0x0D28,
|
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.mkPacketIOWrapper = flash.mkDAPLinkPacketIOWrapper;
|
||||||
res.blocklyPatch = patch.patchBlocks;
|
res.blocklyPatch = patch.patchBlocks;
|
||||||
res.renderBrowserDownloadInstructions = dialogs.renderBrowserDownloadInstructions;
|
|
||||||
res.renderUsbPairDialog = dialogs.renderUsbPairDialog;
|
|
||||||
return Promise.resolve<pxt.editor.ExtensionResult>(res);
|
return Promise.resolve<pxt.editor.ExtensionResult>(res);
|
||||||
}
|
}
|
||||||
|
710
editor/flash.ts
@ -1,9 +1,11 @@
|
|||||||
const imul = (Math as any).imul;
|
const imul = (Math as any).imul;
|
||||||
const timeoutMessage = "timeout"
|
const timeoutMessage = "timeout";
|
||||||
const membase = 0x20000000
|
const membase = 0x20000000;
|
||||||
const loadAddr = membase
|
const loadAddr = membase;
|
||||||
const dataAddr = 0x20002000
|
const dataAddr = 0x20002000;
|
||||||
const stackAddr = 0x20001000
|
const stackAddr = 0x20001000;
|
||||||
|
const FULL_FLASH_TIMEOUT = 100000; // 100s
|
||||||
|
const PARTIAL_FLASH_TIMEOUT = 60000; // 60s
|
||||||
|
|
||||||
const flashPageBIN = new Uint32Array([
|
const flashPageBIN = new Uint32Array([
|
||||||
0xbe00be00, // bkpt - LR is set to this
|
0xbe00be00, // bkpt - LR is set to this
|
||||||
@ -35,7 +37,7 @@ function log(msg: string) {
|
|||||||
let ts = ("00000" + now).slice(-5)
|
let ts = ("00000" + now).slice(-5)
|
||||||
pxt.debug(`dap ${ts}: ${msg}`)
|
pxt.debug(`dap ${ts}: ${msg}`)
|
||||||
}
|
}
|
||||||
|
const logV = /webusbdbg=1/.test(window.location.href) ? log : (msg: string) => { }
|
||||||
|
|
||||||
function murmur3_core(data: Uint8Array) {
|
function murmur3_core(data: Uint8Array) {
|
||||||
let h0 = 0x2F9BE6CC;
|
let h0 = 0x2F9BE6CC;
|
||||||
@ -57,23 +59,41 @@ function murmur3_core(data: Uint8Array) {
|
|||||||
return [h0, h1]
|
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 {
|
class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
||||||
familyID: number;
|
familyID: number;
|
||||||
private dap: DapJS.DAP;
|
private dap: DapJS.DAP;
|
||||||
private cortexM: DapJS.CortexM
|
private cortexM: DapJS.CortexM
|
||||||
private cmsisdap: any;
|
private cmsisdap: any;
|
||||||
private flashing = false;
|
private flashing = false;
|
||||||
|
private flashAborted = false;
|
||||||
private readSerialId = 0;
|
private readSerialId = 0;
|
||||||
private pbuf = new pxt.U.PromiseBuffer<Uint8Array>();
|
private pbuf = new pxt.U.PromiseBuffer<Uint8Array>();
|
||||||
private pageSize = 1024;
|
private pageSize = 1024;
|
||||||
private numPages = 256;
|
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) {
|
constructor(public readonly io: pxt.packetio.PacketIO) {
|
||||||
this.familyID = 0x1366; // this is the microbit vendor id, not quite UF2 family id
|
this.familyID = 0x0D28; // this is the microbit vendor id, not quite UF2 family id
|
||||||
this.io.onDeviceConnectionChanged = (connect) =>
|
this.io.onDeviceConnectionChanged = (connect) => {
|
||||||
|
log(`device connection changed`);
|
||||||
this.disconnectAsync()
|
this.disconnectAsync()
|
||||||
.then(() => connect && this.reconnectAsync());
|
.then(() => connect && this.reconnectAsync());
|
||||||
|
}
|
||||||
|
|
||||||
this.io.onData = buf => {
|
this.io.onData = buf => {
|
||||||
// console.log("RD: " + pxt.Util.toHex(buf))
|
// console.log("RD: " + pxt.Util.toHex(buf))
|
||||||
this.pbuf.push(buf);
|
this.pbuf.push(buf);
|
||||||
@ -82,96 +102,199 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
this.allocDAP();
|
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() {
|
private startReadSerial() {
|
||||||
log(`start read serial`)
|
|
||||||
const rid = this.readSerialId;
|
const rid = this.readSerialId;
|
||||||
const readSerial = () => {
|
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) {
|
if (rid != this.readSerialId) {
|
||||||
log(`stopped read serial ${rid}`)
|
log(`stopped serial reader ${rid}`)
|
||||||
return;
|
} 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 (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])
|
|
||||||
}
|
}
|
||||||
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)
|
readSerialLoop();
|
||||||
}, (err: any) => {
|
|
||||||
log(`read error: ` + err.message);
|
|
||||||
this.disconnectAsync(); // force disconnect
|
|
||||||
});
|
|
||||||
}
|
|
||||||
readSerial();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private stopSerialAsync() {
|
private stopSerialAsync() {
|
||||||
log(`stopping serial reader`)
|
log(`cancelling serial reader ${this.readSerialId}`)
|
||||||
this.readSerialId++;
|
this.readSerialId++;
|
||||||
return Promise.delay(200);
|
return pxt.Util.delay(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSerial: (buf: Uint8Array, isStderr: boolean) => void;
|
|
||||||
|
|
||||||
private allocDAP() {
|
private allocDAP() {
|
||||||
log(`alloc dap`);
|
log(`alloc dap`);
|
||||||
|
const h = this.io;
|
||||||
this.dap = new DapJS.DAP({
|
this.dap = new DapJS.DAP({
|
||||||
write: writeAsync,
|
write: data => h.sendPacketAsync(new Uint8Array(data)),
|
||||||
close: this.disconnectAsync,
|
close: this.disconnectAsync,
|
||||||
read: readAsync,
|
read: () => this.recvPacketAsync(),
|
||||||
//sendMany: sendMany
|
//sendMany: sendMany
|
||||||
});
|
});
|
||||||
this.cmsisdap = (this.dap as any).dap;
|
this.cmsisdap = (this.dap as any).dap;
|
||||||
this.cortexM = new DapJS.CortexM(this.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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function readAsync() {
|
get binName() {
|
||||||
return pbuf.shiftAsync();
|
return (this.usesCODAL ? "mbcodal-" : "mbdal-") + pxtc.BINARY_HEX;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reconnectAsync(): Promise<void> {
|
unsupportedParts() {
|
||||||
|
if (!this.usesCODAL) {
|
||||||
|
return ["logotouch", "builtinspeaker", "microphone", "flashlog"]
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async reconnectAsync(): Promise<void> {
|
||||||
log(`reconnect`)
|
log(`reconnect`)
|
||||||
// configure serial at 115200
|
this.flashAborted = false;
|
||||||
return this.stopSerialAsync()
|
|
||||||
.then(() => this.io.reconnectAsync())
|
function stringResponse(buf: Uint8Array) {
|
||||||
.then(() => this.cortexM.init())
|
return pxt.U.uint8ArrayToString(buf.slice(2, 2 + buf[1]))
|
||||||
.then(() => this.cmsisdap.cmdNums(0x80, []))
|
}
|
||||||
.then(r => {
|
|
||||||
this.binName = (r[2] == 57 && r[3] == 57 && r[5] >= 51 ? "mbcodal-" : "") + pxtc.BINARY_HEX
|
await this.stopSerialAsync()
|
||||||
})
|
|
||||||
.then(() => this.cortexM.memory.readBlock(0x10000010, 2, this.pageSize))
|
this.allocDAP(); // clean dap apis
|
||||||
.then(res => {
|
|
||||||
this.pageSize = pxt.HF2.read32(res, 0)
|
await this.io.reconnectAsync()
|
||||||
this.numPages = pxt.HF2.read32(res, 4)
|
|
||||||
})
|
// before calling into dapjs, we use our dapCmdNums() a few times, which which will make sure the responses
|
||||||
.then(() => this.cmsisdap.cmdNums(0x82, [0x00, 0xC2, 0x01, 0x00]))
|
// to commends from previous sessions (if any) are flushed
|
||||||
.then(() => this.startReadSerial());
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkAborted() {
|
||||||
|
if (this.flashAborted)
|
||||||
|
throw new Error(lf("Download cancelled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectAsync() {
|
disconnectAsync() {
|
||||||
log(`disconnect`)
|
log(`disconnect`)
|
||||||
|
this.flashAborted = true;
|
||||||
return this.stopSerialAsync()
|
return this.stopSerialAsync()
|
||||||
.then(() => this.io.disconnectAsync());
|
.then(() => this.io.disconnectAsync());
|
||||||
}
|
}
|
||||||
@ -180,72 +303,195 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
log("reflash")
|
log("reflash")
|
||||||
startTime = 0
|
startTime = 0
|
||||||
pxt.tickEvent("hid.flash.start");
|
pxt.tickEvent("hid.flash.start");
|
||||||
|
this.flashAborted = false;
|
||||||
this.flashing = true;
|
this.flashing = true;
|
||||||
return (this.io.isConnected() ? Promise.resolve() : this.io.reconnectAsync())
|
return (this.io.isConnected() ? Promise.resolve() : this.io.reconnectAsync())
|
||||||
|
.then(() => this.stopSerialAsync())
|
||||||
.then(() => this.cortexM.init())
|
.then(() => this.cortexM.init())
|
||||||
.then(() => this.cortexM.reset(true))
|
.then(() => this.cortexM.reset(true))
|
||||||
.then(() => this.cortexM.memory.readBlock(0x10001014, 1, this.pageSize))
|
.then(() => this.checkStateAsync())
|
||||||
.then(v => {
|
.then(() => this.readUICR())
|
||||||
if ((pxt.HF2.read32(v, 0) & 0xff) != 0) {
|
.then(uicr => {
|
||||||
|
pxt.tickEvent("hid.flash.uicr", { uicr });
|
||||||
|
// shortcut, do a full flash
|
||||||
|
if (uicr != 0 || this.forceFullFlash) {
|
||||||
pxt.tickEvent("hid.flash.uicrfail");
|
pxt.tickEvent("hid.flash.uicrfail");
|
||||||
return this.fullVendorCommandFlashAsync(resp);
|
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 })
|
.finally(() => { this.flashing = false })
|
||||||
.then(() => Promise.delay(100))
|
// don't disconnect here
|
||||||
.then(() => this.disconnectAsync())
|
// 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> {
|
private fullVendorCommandFlashAsync(resp: pxtc.CompileResult): Promise<void> {
|
||||||
log("full flash")
|
log("full flash")
|
||||||
|
pxt.tickEvent("hid.flash.full.start");
|
||||||
|
|
||||||
const chunkSize = 62;
|
const chunkSize = 62;
|
||||||
let aborted = false;
|
let sentPages = 0;
|
||||||
return Promise.resolve()
|
return pxt.Util.promiseTimeout(
|
||||||
.then(() => {
|
FULL_FLASH_TIMEOUT,
|
||||||
return this.cmsisdap.cmdNums(0x8A /* DAPLinkFlash.OPEN */, [1]);
|
Promise.resolve()
|
||||||
})
|
.then(() => this.dapCmdNums(0x8A /* DAPLinkFlash.OPEN */, 1))
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const hexUint8 = pxt.U.stringToUint8Array(resp.outfiles[this.binName]);
|
log(`daplinkflash open: ${pxt.U.toHex(res)}`)
|
||||||
const hexArray: number[] = Array.prototype.slice.call(hexUint8);
|
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 sendPages = (offset: number = 0): Promise<void> => {
|
||||||
const end = Math.min(hexArray.length, offset + chunkSize);
|
const end = Math.min(hexUint8.length, offset + chunkSize);
|
||||||
const nextPage = hexArray.slice(offset, end);
|
const nextPageData = hexUint8.slice(offset, end);
|
||||||
nextPage.unshift(nextPage.length);
|
const cmdData = new Uint8Array(2 + nextPageData.length)
|
||||||
return this.cmsisdap.cmdNums(0x8C /* DAPLinkFlash.WRITE */, nextPage)
|
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(() => {
|
.then(() => {
|
||||||
if (!aborted && end < hexArray.length) {
|
this.checkAborted()
|
||||||
|
if (end < hexUint8.length) {
|
||||||
|
sentPages++;
|
||||||
return sendPages(end);
|
return sendPages(end);
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendPages();
|
return sendPages();
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then(() => {
|
||||||
return this.cmsisdap.cmdNums(0x8B /* DAPLinkFlash.CLOSE */, []);
|
log(`close`)
|
||||||
|
return this.dapCmdNums(0x8B /* DAPLinkFlash.CLOSE */);
|
||||||
})
|
})
|
||||||
.timeout(60000, timeoutMessage)
|
.then(res => {
|
||||||
.catch((e) => {
|
log(`daplinkclose: ${pxt.U.toHex(res)}`)
|
||||||
aborted = true;
|
return this.dapCmdNums(0x89 /* DAPLinkFlash.RESET */);
|
||||||
return this.cmsisdap.cmdNums(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) => {
|
.catch((e2: any) => {
|
||||||
// Best effort reset, no-op if there's an error
|
// Best effort reset, no-op if there's an error
|
||||||
})
|
})
|
||||||
.then(() => {
|
.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")
|
log("quick flash")
|
||||||
let logV = (msg: string) => { }
|
pxt.tickEvent("hid.flash.quick.start");
|
||||||
//let logV = log
|
|
||||||
let aborted = false;
|
|
||||||
|
|
||||||
const runFlash = (b: ts.pxtc.UF2.Block, dataAddr: number) => {
|
const runFlash = (b: ts.pxtc.UF2.Block, dataAddr: number) => {
|
||||||
const cmd = this.cortexM.prepareCommand();
|
const cmd = this.cortexM.prepareCommand();
|
||||||
@ -266,45 +512,39 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
return cmd.go()
|
return cmd.go()
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logV("dbg en")
|
|
||||||
// starts the program
|
// starts the program
|
||||||
|
logV(`cortex.debug.enable`)
|
||||||
return this.cortexM.debug.enable()
|
return this.cortexM.debug.enable()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let checksums: Uint8Array
|
return pxt.Util.promiseTimeout(
|
||||||
return this.getFlashChecksumsAsync()
|
PARTIAL_FLASH_TIMEOUT,
|
||||||
.then(buf => {
|
Promise.resolve()
|
||||||
checksums = buf;
|
.then(() => this.cortexM.memory.writeBlock(loadAddr, flashPageBIN))
|
||||||
log("write code");
|
.then(() => pxt.Util.promiseMapAllSeries(pxt.U.range(changed.length),
|
||||||
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),
|
|
||||||
i => {
|
i => {
|
||||||
if (aborted) return Promise.resolve();
|
this.checkAborted();
|
||||||
let b = aligned[i];
|
let b = changed[i];
|
||||||
if (b.targetAddr >= 0x10000000)
|
if (b.targetAddr >= 0x10000000) {
|
||||||
|
log(`target address 0x${b.targetAddr.toString(16)} > 0x10000000`)
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
logV("about to write at 0x" + b.targetAddr.toString(16));
|
log(`about to write at 0x${b.targetAddr.toString(16)}`);
|
||||||
|
|
||||||
let writeBl = Promise.resolve();
|
|
||||||
|
|
||||||
let thisAddr = (i & 1) ? dataAddr : dataAddr + this.pageSize;
|
let thisAddr = (i & 1) ? dataAddr : dataAddr + this.pageSize;
|
||||||
let nextAddr = (i & 1) ? dataAddr + this.pageSize : dataAddr;
|
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) {
|
if (i == 0) {
|
||||||
let u32data = new Uint32Array(b.data.length / 4);
|
let u32data = new Uint32Array(b.data.length / 4);
|
||||||
@ -316,7 +556,7 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
return writeBl
|
return writeBl
|
||||||
.then(() => runFlash(b, thisAddr))
|
.then(() => runFlash(b, thisAddr))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let next = aligned[i + 1];
|
let next = changed[i + 1];
|
||||||
if (!next)
|
if (!next)
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
logV("write next");
|
logV("write next");
|
||||||
@ -330,17 +570,20 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
logV("done block");
|
logV("done block");
|
||||||
});
|
});
|
||||||
|
}))
|
||||||
|
.then(() => {
|
||||||
|
log("quick flash done");
|
||||||
|
return this.cortexM.reset(false);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
log("flash done");
|
pxt.tickEvent("hid.flash.quick.success");
|
||||||
pxt.tickEvent("hid.flash.done");
|
return this.checkStateAsync(true)
|
||||||
return this.cortexM.reset(false);
|
}),
|
||||||
});
|
timeoutMessage
|
||||||
})
|
).catch((e) => {
|
||||||
.timeout(25000, timeoutMessage)
|
pxt.tickEvent("hid.flash.quick.error");
|
||||||
.catch((e) => {
|
this.flashAborted = true;
|
||||||
aborted = true;
|
return this.resetAndThrowAsync(e);
|
||||||
return Promise.reject(e);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,6 +595,21 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
.then(() => this.cortexM.memory.readBlock(dataAddr, pages * 2, this.pageSize))
|
.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) {
|
static onlyChanged(blocks: ts.pxtc.UF2.Block[], checksums: Uint8Array, pageSize: number) {
|
||||||
return blocks.filter(b => {
|
return blocks.filter(b => {
|
||||||
let idx = b.targetAddr / pageSize
|
let idx = b.targetAddr / pageSize
|
||||||
@ -392,6 +650,184 @@ class DAPWrapper implements pxt.packetio.PacketIOWrapper {
|
|||||||
}
|
}
|
||||||
return res
|
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 {
|
export function mkDAPLinkPacketIOWrapper(io: pxt.packetio.PacketIO): pxt.packetio.PacketIOWrapper {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es2017",
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true,
|
||||||
@ -12,6 +12,13 @@
|
|||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"newLine": "LF",
|
"newLine": "LF",
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"jsx": "react"
|
"jsx": "react",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost",
|
||||||
|
"es2017",
|
||||||
|
"ES2018.Promise"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"masterPicture": "docs/static/microbit.simplified.svg",
|
"masterPicture": "docs/static/microbit.simplified.svg",
|
||||||
"iconsPath": "/static/icons",
|
"iconsPath": "/docs/static/icons",
|
||||||
"design": {
|
"design": {
|
||||||
"ios": {
|
"ios": {
|
||||||
"pictureAspect": "backgroundAndMargin",
|
"pictureAspect": "backgroundAndMargin",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es2017",
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "{0} block",
|
"name": "{0} block",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core": "file:../core",
|
"core": "file:../core"
|
||||||
"radio": "file:../radio"
|
|
||||||
},
|
},
|
||||||
"description": "",
|
"description": "",
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -1,8 +1,58 @@
|
|||||||
#include "MicroBitConfig.h"
|
#include "MicroBitConfig.h"
|
||||||
#include "ble/UUID.h"
|
|
||||||
#include "BLEHF2Service.h"
|
#include "BLEHF2Service.h"
|
||||||
#include "MicroBitEvent.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) :
|
BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
|
||||||
ble(_ble)
|
ble(_ble)
|
||||||
{
|
{
|
||||||
@ -48,3 +98,7 @@ const uint8_t BLEHF2ServiceUUID[] = {
|
|||||||
const uint8_t BLEHF2TxCharacteristicUUID[] = {
|
const uint8_t BLEHF2TxCharacteristicUUID[] = {
|
||||||
0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a
|
0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//================================================================
|
||||||
|
#endif // MICROBIT_CODAL
|
||||||
|
//================================================================
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#define BLE_HF2_SERVICE_H
|
#define BLE_HF2_SERVICE_H
|
||||||
|
|
||||||
#include "MicroBitConfig.h"
|
#include "MicroBitConfig.h"
|
||||||
#include "ble/BLE.h"
|
|
||||||
#include "MicroBitThermometer.h"
|
#include "MicroBitThermometer.h"
|
||||||
#include "EventModel.h"
|
#include "EventModel.h"
|
||||||
#include "pxt.h"
|
#include "pxt.h"
|
||||||
@ -22,6 +21,65 @@ struct BLEHF2Packet {
|
|||||||
uint8_t data[BLEHF2_DATA_LENGTH];
|
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
|
class BLEHF2Service
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -50,5 +108,8 @@ class BLEHF2Service
|
|||||||
GattAttribute::Handle_t txCharacteristicHandle;
|
GattAttribute::Handle_t txCharacteristicHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//================================================================
|
||||||
|
#endif // MICROBIT_CODAL
|
||||||
|
//================================================================
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -14,7 +14,7 @@ namespace bluetooth {
|
|||||||
BLEHF2Service* pHF2 = NULL;
|
BLEHF2Service* pHF2 = NULL;
|
||||||
|
|
||||||
//%
|
//%
|
||||||
void __log(String msg) {
|
void __log(int priority, String msg) {
|
||||||
if (NULL == pHF2)
|
if (NULL == pHF2)
|
||||||
pHF2 = new BLEHF2Service(*uBit.ble);
|
pHF2 = new BLEHF2Service(*uBit.ble);
|
||||||
pHF2->sendSerial(msg->getUTF8Data(), msg->getUTF8Size(), false);
|
pHF2->sendSerial(msg->getUTF8Data(), msg->getUTF8Size(), false);
|
||||||
@ -125,19 +125,18 @@ namespace bluetooth {
|
|||||||
startUartService();
|
startUartService();
|
||||||
int bytes = uart->rxBufferedSize();
|
int bytes = uart->rxBufferedSize();
|
||||||
auto buffer = mkBuffer(NULL, bytes);
|
auto buffer = mkBuffer(NULL, bytes);
|
||||||
|
auto res = buffer;
|
||||||
|
registerGCObj(buffer);
|
||||||
int read = uart->read(buffer->data, buffer->length);
|
int read = uart->read(buffer->data, buffer->length);
|
||||||
// read failed
|
// read failed
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
decrRC(buffer);
|
res = mkBuffer(NULL, 0);
|
||||||
return mkBuffer(NULL, 0);
|
} else if (read != buffer->length) {
|
||||||
}
|
|
||||||
// could not fill the buffer
|
// could not fill the buffer
|
||||||
if (read != buffer->length) {
|
res = mkBuffer(buffer->data, read);
|
||||||
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"
|
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
|
||||||
//% parts=bluetooth weight=11 blockGap=8
|
//% parts=bluetooth weight=11 blockGap=8
|
||||||
//% help=bluetooth/advertise-url blockExternalInputs=1
|
//% help=bluetooth/advertise-url blockExternalInputs=1
|
||||||
|
//% hidden=1 deprecated=1
|
||||||
void advertiseUrl(String url, int power, bool connectable) {
|
void advertiseUrl(String url, int power, bool connectable) {
|
||||||
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL)
|
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL)
|
||||||
power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));
|
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 power power level between 0 and 7, eg: 7
|
||||||
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
|
* @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) {
|
void advertiseUidBuffer(Buffer nsAndInstance, int power, bool connectable) {
|
||||||
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID)
|
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID)
|
||||||
auto buf = nsAndInstance;
|
auto buf = nsAndInstance;
|
||||||
@ -227,6 +227,7 @@ namespace bluetooth {
|
|||||||
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
|
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
|
||||||
//% parts=bluetooth weight=10
|
//% parts=bluetooth weight=10
|
||||||
//% help=bluetooth/stop-advertising advanced=true
|
//% help=bluetooth/stop-advertising advanced=true
|
||||||
|
//% hidden=1 deprecated=1
|
||||||
void stopAdvertising() {
|
void stopAdvertising() {
|
||||||
uBit.bleManager.stopAdvertising();
|
uBit.bleManager.stopAdvertising();
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,10 @@ namespace bluetooth {
|
|||||||
* Internal use
|
* Internal use
|
||||||
*/
|
*/
|
||||||
//% shim=bluetooth::__log
|
//% shim=bluetooth::__log
|
||||||
export function __log(msg: string) {
|
export function __log(priority: number, msg: string) {
|
||||||
return;
|
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.
|
* 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"
|
//% 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
|
//% parts=bluetooth weight=12 blockGap=8
|
||||||
//% help=bluetooth/advertise-uid blockExternalInputs=1
|
//% help=bluetooth/advertise-uid blockExternalInputs=1
|
||||||
|
//% hidden=1 deprecated=1
|
||||||
export function advertiseUid(ns: number, instance: number, power: number, connectable: boolean) {
|
export function advertiseUid(ns: number, instance: number, power: number, connectable: boolean) {
|
||||||
const buf = pins.createBuffer(16);
|
const buf = pins.createBuffer(16);
|
||||||
buf.setNumber(NumberFormat.Int32BE, 6, ns);
|
buf.setNumber(NumberFormat.Int32BE, 6, ns);
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
"BLEHF2Service.h",
|
"BLEHF2Service.h",
|
||||||
"BLEHF2Service.cpp"
|
"BLEHF2Service.cpp"
|
||||||
],
|
],
|
||||||
|
"weight": 10,
|
||||||
|
"searchOnly": true,
|
||||||
"icon": "./static/packages/bluetooth/icon.png",
|
"icon": "./static/packages/bluetooth/icon.png",
|
||||||
"public": true,
|
"public": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core": "file:../core"
|
"core": "file:../core"
|
||||||
},
|
},
|
||||||
"disablesVariants": ["mbcodal"],
|
|
||||||
"yotta": {
|
"yotta": {
|
||||||
"config": {
|
"config": {
|
||||||
"microbit-dal": {
|
"microbit-dal": {
|
||||||
@ -29,7 +30,8 @@
|
|||||||
"stack_size": 1280,
|
"stack_size": 1280,
|
||||||
"gatt_table_size": "0x700"
|
"gatt_table_size": "0x700"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"installedVersion": "vzlhfd"
|
"userConfigs": [
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
8
libs/bluetooth/shims.d.ts
vendored
@ -109,7 +109,8 @@ declare namespace bluetooth {
|
|||||||
*/
|
*/
|
||||||
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
|
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
|
||||||
//% parts=bluetooth weight=11 blockGap=8
|
//% 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;
|
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 power power level between 0 and 7, eg: 7
|
||||||
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
|
* @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;
|
function advertiseUidBuffer(nsAndInstance: Buffer, power: int32, connectable: boolean): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,7 +135,8 @@ declare namespace bluetooth {
|
|||||||
*/
|
*/
|
||||||
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
|
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
|
||||||
//% parts=bluetooth weight=10
|
//% 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;
|
function stopAdvertising(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"AcceleratorRange.OneG": "The accelerator measures forces up to 1 gravity",
|
"AcceleratorRange.OneG": "The accelerator measures forces up to 1 gravity",
|
||||||
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
|
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
|
||||||
"Array": "Add, remove, and replace items in lists.",
|
"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._popStatement": "Remove the last element from an array and return it.",
|
||||||
"Array._removeAtStatement": "Remove the element at a certain index.",
|
"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.",
|
"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.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": "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|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.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": "Return a section of an array.",
|
||||||
"Array.slice|param|end": "The end of the specified portion of the array. eg: 0",
|
"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": "Show a particular frame of the image strip.",
|
||||||
"Image.showFrame|param|frame": "image frame to show",
|
"Image.showFrame|param|frame": "image frame to show",
|
||||||
"Image.showImage": "Shows an frame from the image at offset ``x offset``.",
|
"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.showImage|param|xOffset": "column index to start displaying the image",
|
||||||
"Image.width": "Gets the width in columns",
|
"Image.width": "Gets the width in columns",
|
||||||
"Infinity": "Constant representing positive infinity.",
|
"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": "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": "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.",
|
"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": "Splits the string according to the separators",
|
||||||
"String.split|param|separator": "@param limit",
|
"String.split|param|separator": "@param limit",
|
||||||
"String.substr": "Return a substring of the current string.",
|
"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.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.toLowerCase": "Converts the string to lower case characters.",
|
||||||
"String.trim": "Return a substring of the current string with whitespace removed from both ends",
|
"String.trim": "Return a substring of the current string with whitespace removed from both ends",
|
||||||
@ -245,30 +253,31 @@
|
|||||||
"basic.pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000",
|
"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": "Draws an image on the LED screen.",
|
||||||
"basic.plotLeds|param|leds": "pattern of LEDs to turn on/off",
|
"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": "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|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|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|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.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.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": "Shows a sequence of LED screens as an animation.",
|
||||||
"basic.showAnimation|param|interval": "time in milliseconds between each redraw",
|
"basic.showAnimation|param|interval": "time in milliseconds between each redraw",
|
||||||
"basic.showAnimation|param|leds": "pattern of LEDs to turn on/off",
|
"basic.showAnimation|param|leds": "pattern of LEDs to turn on/off",
|
||||||
"basic.showArrow": "Draws an arrow on the LED screen",
|
|
||||||
"basic.showArrow|param|direction": "the direction of the arrow",
|
|
||||||
"basic.showArrow|param|interval": "the amount of time (milliseconds) to show the icon. Default is 600.",
|
|
||||||
"basic.showCompass": "Draws needle on the screen which always points to north",
|
"basic.showCompass": "Draws needle on the screen which always points to north",
|
||||||
"basic.showCompass|param|interval": "the amount of time (milliseconds) to show the needle. Default is 600.",
|
"basic.showCompass|param|interval": "the amount of time (milliseconds) to show the needle. Default is 600.",
|
||||||
"basic.showIcon": "Draws the selected icon on the LED screen",
|
"basic.showIcon": "Draws the selected icon on the LED screen",
|
||||||
"basic.showIcon|param|icon": "the predefined icon id",
|
"basic.showIcon|param|icon": "the predefined icon id",
|
||||||
"basic.showIcon|param|interval": "the amount of time (milliseconds) to show the icon. Default is 600.",
|
"basic.showIcon|param|interval": "the amount of time (milliseconds) to block the LED Matrix for showing the icon. Default is 200.",
|
||||||
"basic.showLeds": "Draws an image on the LED screen.",
|
"basic.showLeds": "Draws an image on the LED screen.",
|
||||||
"basic.showLeds|param|interval": "time in milliseconds to pause after drawing",
|
"basic.showLeds|param|interval": "time in milliseconds to pause after drawing",
|
||||||
"basic.showLeds|param|leds": "the pattern of LED to turn on/off",
|
"basic.showLeds|param|leds": "the pattern of LED to turn on/off",
|
||||||
"basic.showNumber": "Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.",
|
"basic.showNumber": "Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.",
|
||||||
"basic.showNumber|param|interval": "speed of scroll; eg: 150, 100, 200, -100",
|
"basic.showNumber|param|interval": "speed of scroll; eg: 50, 100, 150, 200",
|
||||||
"basic.showString": "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.",
|
"basic.showString": "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.",
|
||||||
"basic.showString|param|interval": "how fast to shift characters; eg: 150, 100, 200, -100",
|
"basic.showString|param|interval": "how fast to shift characters; eg: 50, 100, 150, 200",
|
||||||
"basic.showString|param|text": "the text to scroll on the screen, eg: \"hi!\"",
|
"basic.showString|param|text": "the text to scroll on the screen, eg: \"hi!\"",
|
||||||
"basic.turnRgbLedOff": "Sets the color on the build-in LED. Set to 0 to turn off.",
|
"basic.turnRgbLedOff": "Sets the color on the build-in LED. Set to 0 to turn off.",
|
||||||
"console": "Reading and writing data to the console output.",
|
"console": "Reading and writing data to the console output.",
|
||||||
@ -280,31 +289,48 @@
|
|||||||
"console.logValue": "Write a name:value pair as a line of text to the console output.",
|
"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|name": "name of the value stream, eg: \"x\"",
|
||||||
"console.logValue|param|value": "to write",
|
"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": "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.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.createBuffer": "Create a new zero-initialized buffer.",
|
||||||
"control.createBufferFromUTF8": "Create a new buffer with UTF8-encoded string",
|
"control.createBufferFromUTF8": "Create a new buffer with UTF8-encoded string",
|
||||||
"control.createBufferFromUTF8|param|str": "the string to put in the buffer",
|
"control.createBufferFromUTF8|param|str": "the string to put in the buffer",
|
||||||
"control.createBuffer|param|size": "number of bytes 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.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.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.eventSourceId": "Returns the value of a C++ runtime constant",
|
||||||
"control.eventTimestamp": "Gets the timestamp of the last event executed on the bus",
|
"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.eventValue": "Gets the value of the last event executed on the bus",
|
||||||
"control.eventValueId": "Returns the value of a C++ runtime constant",
|
"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.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.inBackground": "Schedules code that run in the background.",
|
||||||
"control.micros": "Gets current time in microseconds. Overflows every ~18 minutes.",
|
"control.micros": "Gets current time in microseconds. Overflows every ~18 minutes.",
|
||||||
"control.millis": "Gets the number of milliseconds elapsed since power on.",
|
"control.millis": "Gets the number of milliseconds elapsed since power on.",
|
||||||
"control.onEvent": "Registers an event handler.",
|
"control.onEvent": "Registers an event handler.",
|
||||||
"control.panic": "Display specified error code and stop the program.",
|
"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": "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|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|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.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.reset": "Resets the BBC micro:bit.",
|
||||||
"control.runInParallel": "Run other code in the parallel.",
|
"control.runInParallel": "Run other code in the parallel.",
|
||||||
"control.runtimeWarning": "Display warning in the simulator.",
|
"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.waitForEvent": "Blocks the calling thread until the specified event is raised.",
|
||||||
"control.waitMicros": "Blocks the current fiber for the given microseconds",
|
"control.waitMicros": "Blocks the current fiber for the given microseconds",
|
||||||
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
|
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
|
||||||
@ -401,38 +427,39 @@
|
|||||||
"input": "Events and data from sensors",
|
"input": "Events 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": "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.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": "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.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.calibrateCompass": "Obsolete, compass calibration is automatic.",
|
||||||
|
"input.clearCalibrationCompass": "Obsolete, compass calibration is automatic.",
|
||||||
"input.compassHeading": "Get the current compass heading in degrees.",
|
"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": "Tests if a gesture is currently detected.",
|
||||||
"input.isGesture|param|gesture": "the type of gesture to detect, eg: Gesture.Shake",
|
"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.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": "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.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": "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|body": "code to run when event is raised",
|
||||||
"input.onButtonPressed|param|button": "the button that needs to be pressed",
|
"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": "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|body": "code to run when gesture is raised",
|
||||||
"input.onGesture|param|gesture": "the type of gesture to track, eg: Gesture.Shake",
|
"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": "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|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.onPinPressed|param|name": "the pin that needs to be pressed, eg: TouchPin.P0",
|
||||||
"input.onPinReleased": "Do something when a pin is released.",
|
"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|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.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.onPinTouchEvent": "Do something when a pin receives an touch event (while also touching the GND pin).",
|
||||||
"input.onScreenDown|param|body": "TODO",
|
"input.onPinTouchEvent|param|body": "the code to run when event is fired on pin",
|
||||||
"input.onScreenUp": "Attaches code to run when the screen is facing up.",
|
"input.onPinTouchEvent|param|name": "the pin, eg: TouchPin.P0",
|
||||||
"input.onScreenUp|param|body": "TODO",
|
|
||||||
"input.onShake": "Attaches code to run when the device is shaken.",
|
|
||||||
"input.onShake|param|body": "TODO",
|
|
||||||
"input.pinIsPressed": "Get the pin state (pressed or not). Requires to hold the ground to close the circuit.",
|
"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.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.",
|
"input.rotation": "The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.",
|
||||||
@ -441,7 +468,7 @@
|
|||||||
"input.runningTimeMicros": "Gets the number of microseconds elapsed since power on.",
|
"input.runningTimeMicros": "Gets the number of microseconds elapsed since power on.",
|
||||||
"input.setAccelerometerRange": "Sets the accelerometer sample range in gravities.",
|
"input.setAccelerometerRange": "Sets the accelerometer sample range in gravities.",
|
||||||
"input.setAccelerometerRange|param|range": "a value describe the maximum strengh of acceleration measured",
|
"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).",
|
"input.temperature": "Gets the temperature in Celsius degrees (°C).",
|
||||||
"led": "Control of the LED screen.",
|
"led": "Control of the LED screen.",
|
||||||
"led.brightness": "Get the screen brightness from 0 (off) to 255 (full bright).",
|
"led.brightness": "Get the screen brightness from 0 (off) to 255 (full bright).",
|
||||||
@ -482,7 +509,10 @@
|
|||||||
"led.unplot|param|x": "the horizontal coordinate of the LED",
|
"led.unplot|param|x": "the horizontal coordinate of the LED",
|
||||||
"led.unplot|param|y": "the vertical 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.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",
|
"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": "Blocks to control the onboard motors",
|
||||||
"motors.dualMotorPower": "Controls two motors attached to the board. Switches to dual-motor mode!",
|
"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.",
|
"motors.motorCommand": "Send break, coast or sleep commands to the motor. Has no effect in dual-motor mode.",
|
||||||
@ -522,6 +552,7 @@
|
|||||||
"music.startMelody": "Starts playing a melody.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
|
"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|melodyArray": "the melody array to play",
|
||||||
"music.startMelody|param|options": "melody options, once / forever, in the foreground / background",
|
"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": "Stops the melodies",
|
||||||
"music.stopMelody|param|options": "which melody to stop",
|
"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.",
|
"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 +562,9 @@
|
|||||||
"parseInt|param|radix": "optional A value between 2 and 36 that specifies the base of the number in text.",
|
"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\"",
|
"parseInt|param|text": "A string to convert into an integral number. eg: \"123\"",
|
||||||
"pause": "Pause for the specified time in milliseconds",
|
"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",
|
"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": "Control currents in Pins for analog/digital signals, servos, i2c, ...",
|
||||||
"pins.C10": "Pin C10",
|
"pins.C10": "Pin C10",
|
||||||
@ -597,9 +631,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": "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|name": "pin to write to, eg: AnalogPin.P1",
|
||||||
"pins.servoWritePin|param|value": "angle or rotation speed, eg:180,90,0",
|
"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": "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|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.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": "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|name": "pin to set the pull mode on, eg: DigitalPin.P0",
|
||||||
"pins.setPull|param|pull": "one of the mbed pull configurations, eg: PinPullMode.PullUp",
|
"pins.setPull|param|pull": "one of the mbed pull configurations, eg: PinPullMode.PullUp",
|
||||||
@ -622,8 +659,8 @@
|
|||||||
"serial.delimiters": "Return the corresponding delimiter string",
|
"serial.delimiters": "Return the corresponding delimiter string",
|
||||||
"serial.onDataReceived": "Register an event to be fired when one of the delimiter is matched.",
|
"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.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": "Read multiple characters from the receive buffer. \nIf length is positive, pauses until enough characters are present.",
|
||||||
"serial.readBuffer|param|length": "default buffer length, eg: 64",
|
"serial.readBuffer|param|length": "default buffer length",
|
||||||
"serial.readLine": "Read a line of text from the serial port.",
|
"serial.readLine": "Read a line of text from the serial port.",
|
||||||
"serial.readString": "Read the buffered received data as a string",
|
"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.",
|
"serial.readUntil": "Read a line of text from the serial port and return the buffer when the delimiter is met.",
|
||||||
@ -647,5 +684,20 @@
|
|||||||
"serial.writeString": "Send a piece of text through the serial connection.",
|
"serial.writeString": "Send a piece of text through the serial connection.",
|
||||||
"serial.writeValue": "Write a name:value pair as a line to the serial port.",
|
"serial.writeValue": "Write a name:value pair as a line to the serial port.",
|
||||||
"serial.writeValue|param|name": "name of the value stream, eg: x",
|
"serial.writeValue|param|name": "name of the value stream, eg: x",
|
||||||
"serial.writeValue|param|value": "to write"
|
"serial.writeValue|param|value": "to write",
|
||||||
|
"storage": "Provides access to persistent storage functionality.\n\nProvides access to persistent storage functionality.",
|
||||||
|
"storage.getNumber": "Reads a key value pair from the non volatile storage as a number",
|
||||||
|
"storage.getNumber|param|key": "the key for accesing the value",
|
||||||
|
"storage.getValueInt": "Reads a key value pair from the non volatile storage",
|
||||||
|
"storage.getValueInt|param|key": "the key for accesing the value",
|
||||||
|
"storage.putNumber": "Saves a key value pair in the non volatile storage",
|
||||||
|
"storage.putNumber|param|key": "the key for accesing the value",
|
||||||
|
"storage.putNumber|param|value": "value to store",
|
||||||
|
"storage.putValueInt": "Saves a key value pair in the non volatile storage",
|
||||||
|
"storage.putValueInt|param|key": "the key for accesing the value",
|
||||||
|
"storage.putValueInt|param|value": "value to store",
|
||||||
|
"storage.remove": "Removes a key value pair from the non volatile storage",
|
||||||
|
"storage.removeKeyInt": "Deletes the key from the non volatile storage",
|
||||||
|
"storage.removeKeyInt|param|key": "the key for accesing the value",
|
||||||
|
"storage.remove|param|key": "the key for accesing the value"
|
||||||
}
|
}
|
@ -7,6 +7,7 @@
|
|||||||
"AcceleratorRange.OneG|block": "1g",
|
"AcceleratorRange.OneG|block": "1g",
|
||||||
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
|
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
|
||||||
"AcceleratorRange.TwoG|block": "2g",
|
"AcceleratorRange.TwoG|block": "2g",
|
||||||
|
"Array._pickRandom|block": "get random value from %list",
|
||||||
"Array._popStatement|block": "remove last value from %list",
|
"Array._popStatement|block": "remove last value from %list",
|
||||||
"Array._removeAtStatement|block": "%list| remove value at %index",
|
"Array._removeAtStatement|block": "%list| remove value at %index",
|
||||||
"Array._shiftStatement|block": "remove first value from %list",
|
"Array._shiftStatement|block": "remove first value from %list",
|
||||||
@ -21,14 +22,6 @@
|
|||||||
"Array.shift|block": "get and remove first value from %list",
|
"Array.shift|block": "get and remove first value from %list",
|
||||||
"Array.unshift|block": "%list| insert %value| at beginning",
|
"Array.unshift|block": "%list| insert %value| at beginning",
|
||||||
"Array|block": "Array",
|
"Array|block": "Array",
|
||||||
"ArrowNames.East|block": "East",
|
|
||||||
"ArrowNames.NorthEast|block": "North East",
|
|
||||||
"ArrowNames.NorthWest|block": "North West",
|
|
||||||
"ArrowNames.North|block": "North",
|
|
||||||
"ArrowNames.SouthEast|block": "South East",
|
|
||||||
"ArrowNames.SouthWest|block": "South West",
|
|
||||||
"ArrowNames.South|block": "South",
|
|
||||||
"ArrowNames.West|block": "West",
|
|
||||||
"BaudRate.BaudRate115200|block": "115200",
|
"BaudRate.BaudRate115200|block": "115200",
|
||||||
"BaudRate.BaudRate1200|block": "1200",
|
"BaudRate.BaudRate1200|block": "1200",
|
||||||
"BaudRate.BaudRate14400|block": "14400",
|
"BaudRate.BaudRate14400|block": "14400",
|
||||||
@ -49,6 +42,10 @@
|
|||||||
"BeatFraction.Whole|block": "1",
|
"BeatFraction.Whole|block": "1",
|
||||||
"Buffer|block": "Buffer",
|
"Buffer|block": "Buffer",
|
||||||
"Button.AB|block": "A+B",
|
"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.Blue|block": "blue",
|
||||||
"Colors.Green|block": "green",
|
"Colors.Green|block": "green",
|
||||||
"Colors.Indigo|block": "indigo",
|
"Colors.Indigo|block": "indigo",
|
||||||
@ -112,46 +109,20 @@
|
|||||||
"IconNames.ArrowSouth|block": "arrow south",
|
"IconNames.ArrowSouth|block": "arrow south",
|
||||||
"IconNames.ArrowWest|block": "arrow west",
|
"IconNames.ArrowWest|block": "arrow west",
|
||||||
"IconNames.Asleep|block": "asleep",
|
"IconNames.Asleep|block": "asleep",
|
||||||
"IconNames.Butterfly|block": "butterfly",
|
|
||||||
"IconNames.Chessboard|block": "chess board",
|
|
||||||
"IconNames.Confused|block": "confused",
|
"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.Fabulous|block": "fabulous",
|
||||||
"IconNames.Ghost|block": "ghost",
|
|
||||||
"IconNames.Giraffe|block": "giraffe",
|
|
||||||
"IconNames.Happy|block": "happy",
|
"IconNames.Happy|block": "happy",
|
||||||
"IconNames.Heart|block": "heart",
|
"IconNames.Heart|block": "heart",
|
||||||
"IconNames.House|block": "house",
|
|
||||||
"IconNames.LeftTriangle|block": "left triangle",
|
|
||||||
"IconNames.Meh|block": "meh",
|
"IconNames.Meh|block": "meh",
|
||||||
"IconNames.No|block": "no",
|
"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.Sad|block": "sad",
|
||||||
"IconNames.Scissors|block": "scissors",
|
|
||||||
"IconNames.Silly|block": "silly",
|
"IconNames.Silly|block": "silly",
|
||||||
"IconNames.Skull|block": "skull",
|
|
||||||
"IconNames.SmallDiamond|block": "small diamond",
|
|
||||||
"IconNames.SmallHeart|block": "small heart",
|
"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.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",
|
"IconNames.Yes|block": "yes",
|
||||||
"Image.scrollImage|block": "scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay",
|
"Image.scrollImage|block": "scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %interval",
|
||||||
"Image.showImage|block": "show image %sprite(myImage)|at offset %offset",
|
"Image.showImage|block": "show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval",
|
||||||
|
"JSON|block": "JSON",
|
||||||
"LedSpriteProperty.Blink|block": "blink",
|
"LedSpriteProperty.Blink|block": "blink",
|
||||||
"LedSpriteProperty.Brightness|block": "brightness",
|
"LedSpriteProperty.Brightness|block": "brightness",
|
||||||
"LedSpriteProperty.Direction|block": "direction",
|
"LedSpriteProperty.Direction|block": "direction",
|
||||||
@ -248,6 +219,13 @@
|
|||||||
"PulseValue.Low|block": "low",
|
"PulseValue.Low|block": "low",
|
||||||
"Rotation.Pitch|block": "pitch",
|
"Rotation.Pitch|block": "pitch",
|
||||||
"Rotation.Roll|block": "roll",
|
"Rotation.Roll|block": "roll",
|
||||||
|
"StorageSlots.s1|block": "Slot 1",
|
||||||
|
"StorageSlots.s2|block": "Slot 2",
|
||||||
|
"StorageSlots.s3|block": "Slot 3",
|
||||||
|
"StorageSlots.s4|block": "Slot 4",
|
||||||
|
"StorageSlots.s5|block": "Slot 5",
|
||||||
|
"StorageSlots.s6|block": "Slot 6",
|
||||||
|
"StorageSlots.s7|block": "Slot 7",
|
||||||
"String.charAt|block": "char from %this=text|at %pos",
|
"String.charAt|block": "char from %this=text|at %pos",
|
||||||
"String.compare|block": "compare %this=text| to %that",
|
"String.compare|block": "compare %this=text| to %that",
|
||||||
"String.fromCharCode|block": "text from char code %code",
|
"String.fromCharCode|block": "text from char code %code",
|
||||||
@ -264,13 +242,13 @@
|
|||||||
"basic.forever|block": "forever",
|
"basic.forever|block": "forever",
|
||||||
"basic.pause|block": "pause (ms) %pause",
|
"basic.pause|block": "pause (ms) %pause",
|
||||||
"basic.rgbw|block": "red %red|green %green|blue %blue|white %white",
|
"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.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.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.showLeds|block": "show leds",
|
||||||
"basic.showNumber|block": "show|number %number",
|
"basic.showNumber|block": "show|number %number || in an interval of %interval ms",
|
||||||
"basic.showString|block": "show|string %text",
|
"basic.showString|block": "show|string %text || in an interval of %interval ms",
|
||||||
"basic.turnRgbLedOff|block": "turn build-in LED off",
|
"basic.turnRgbLedOff|block": "turn build-in LED off",
|
||||||
"basic|block": "basic",
|
"basic|block": "basic",
|
||||||
"console|block": "console",
|
"console|block": "console",
|
||||||
@ -314,29 +292,34 @@
|
|||||||
"game.setScore|block": "set score %points",
|
"game.setScore|block": "set score %points",
|
||||||
"game.startCountdown|block": "start countdown|(ms) %duration",
|
"game.startCountdown|block": "start countdown|(ms) %duration",
|
||||||
"game|block": "game",
|
"game|block": "game",
|
||||||
"images.arrowImage|block": "arrow image %i",
|
|
||||||
"images.arrowNumber|block": "%arrow",
|
|
||||||
"images.createBigImage|block": "create big image",
|
"images.createBigImage|block": "create big image",
|
||||||
"images.createImage|block": "create image",
|
"images.createImage|block": "create image",
|
||||||
"images.iconImage|block": "icon image %i",
|
"images.iconImage|block": "icon image %i",
|
||||||
"images|block": "images",
|
"images|block": "images",
|
||||||
"input.acceleration|block": "acceleration (mg)|%NAME",
|
"input.acceleration|block": "acceleration (mg)|%NAME",
|
||||||
|
"input.assumeCalibrationCompass|block": "assume calibration compass",
|
||||||
|
"input.buttonEventValueId|block": "%id",
|
||||||
"input.buttonIsPressed|block": "button|%NAME|is pressed",
|
"input.buttonIsPressed|block": "button|%NAME|is pressed",
|
||||||
"input.calibrateCompass|block": "calibrate compass",
|
"input.calibrateCompass|block": "calibrate compass",
|
||||||
|
"input.clearCalibrationCompass|block": "clear calibration compass",
|
||||||
"input.compassHeading|block": "compass heading (°)",
|
"input.compassHeading|block": "compass heading (°)",
|
||||||
|
"input.isCalibratedCompass|block": "is compass calibrated",
|
||||||
"input.isGesture|block": "is %gesture gesture",
|
"input.isGesture|block": "is %gesture gesture",
|
||||||
"input.lightLevel|block": "light level",
|
"input.lightLevel|block": "light level",
|
||||||
|
"input.loudness|block": "Loudness",
|
||||||
"input.magneticForce|block": "magnetic force (µT)|%NAME",
|
"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.onButtonPressed|block": "on button|%NAME|pressed",
|
||||||
"input.onGesture|block": "on |%NAME",
|
"input.onGesture|block": "on |%NAME",
|
||||||
"input.onPinPressed|block": "on pin %name|pressed",
|
"input.onPinPressed|block": "on pin %name|pressed",
|
||||||
"input.onPinReleased|block": "on pin %NAME|released",
|
"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.pinIsPressed|block": "pin %NAME|is pressed",
|
||||||
"input.rotation|block": "rotation (°)|%NAME",
|
"input.rotation|block": "rotation (°)|%NAME",
|
||||||
"input.runningTimeMicros|block": "running time (micros)",
|
"input.runningTimeMicros|block": "running time (micros)",
|
||||||
"input.runningTime|block": "running time (ms)",
|
"input.runningTime|block": "running time (ms)",
|
||||||
"input.setAccelerometerRange|block": "set accelerometer|range %range",
|
"input.setAccelerometerRange|block": "set accelerometer|range %range",
|
||||||
"input.soundLevel|block": "Loudness",
|
"input.soundLevel|block": "soundLevel",
|
||||||
"input.temperature|block": "temperature (°C)",
|
"input.temperature|block": "temperature (°C)",
|
||||||
"input|block": "input",
|
"input|block": "input",
|
||||||
"led.brightness|block": "brightness",
|
"led.brightness|block": "brightness",
|
||||||
@ -353,6 +336,8 @@
|
|||||||
"led.unplot|block": "unplot|x %x|y %y",
|
"led.unplot|block": "unplot|x %x|y %y",
|
||||||
"led|block": "led",
|
"led|block": "led",
|
||||||
"light|block": "light",
|
"light|block": "light",
|
||||||
|
"loops.everyInterval|block": "every $interval ms",
|
||||||
|
"loops|block": "loops",
|
||||||
"motors.dualMotorPower|block": "motor %motor|at %percent \\%",
|
"motors.dualMotorPower|block": "motor %motor|at %percent \\%",
|
||||||
"motors.motorCommand|block": "motor %command",
|
"motors.motorCommand|block": "motor %command",
|
||||||
"motors.motorPower|block": "motor on at %percent \\%",
|
"motors.motorPower|block": "motor on at %percent \\%",
|
||||||
@ -371,6 +356,7 @@
|
|||||||
"music.setTempo|block": "set tempo to (bpm)|%value",
|
"music.setTempo|block": "set tempo to (bpm)|%value",
|
||||||
"music.setVolume|block": "set volume %volume",
|
"music.setVolume|block": "set volume %volume",
|
||||||
"music.startMelody|block": "start melody %melody=device_builtin_melody| repeating %options",
|
"music.startMelody|block": "start melody %melody=device_builtin_melody| repeating %options",
|
||||||
|
"music.stopAllSounds|block": "stop all sounds",
|
||||||
"music.stopMelody|block": "stop melody $options",
|
"music.stopMelody|block": "stop melody $options",
|
||||||
"music.tempo|block": "tempo (bpm)",
|
"music.tempo|block": "tempo (bpm)",
|
||||||
"music.volume|block": "volume",
|
"music.volume|block": "volume",
|
||||||
@ -394,7 +380,9 @@
|
|||||||
"pins.pulseIn|block": "pulse in (µs)|pin %name|pulsed %value",
|
"pins.pulseIn|block": "pulse in (µs)|pin %name|pulsed %value",
|
||||||
"pins.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %micros",
|
"pins.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %micros",
|
||||||
"pins.servoWritePin|block": "servo write|pin %name|to %value",
|
"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.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.setPull|block": "set pull|pin %pin|to %pull",
|
||||||
"pins.spiFormat|block": "spi format|bits %bits|mode %mode",
|
"pins.spiFormat|block": "spi format|bits %bits|mode %mode",
|
||||||
"pins.spiFrequency|block": "spi frequency %frequency",
|
"pins.spiFrequency|block": "spi frequency %frequency",
|
||||||
@ -421,6 +409,13 @@
|
|||||||
"serial.writeString|block": "serial|write string %text",
|
"serial.writeString|block": "serial|write string %text",
|
||||||
"serial.writeValue|block": "serial|write value %name|= %value",
|
"serial.writeValue|block": "serial|write value %name|= %value",
|
||||||
"serial|block": "serial",
|
"serial|block": "serial",
|
||||||
|
"storage.getNumber|block": "read from number %key",
|
||||||
|
"storage.getValueInt|block": "get number from %key",
|
||||||
|
"storage.putNumber|block": "Save into number %key a value of %value",
|
||||||
|
"storage.putValueInt|block": "Put into %key a value of %value as Int",
|
||||||
|
"storage.removeKeyInt|block": "Clear number %key",
|
||||||
|
"storage.remove|block": "remove %key",
|
||||||
|
"storage|block": "storage",
|
||||||
"{id:category}AnalogInPin": "AnalogInPin",
|
"{id:category}AnalogInPin": "AnalogInPin",
|
||||||
"{id:category}AnalogOutPin": "AnalogOutPin",
|
"{id:category}AnalogOutPin": "AnalogOutPin",
|
||||||
"{id:category}Array": "Array",
|
"{id:category}Array": "Array",
|
||||||
@ -438,8 +433,10 @@
|
|||||||
"{id:category}Image": "Image",
|
"{id:category}Image": "Image",
|
||||||
"{id:category}Images": "Images",
|
"{id:category}Images": "Images",
|
||||||
"{id:category}Input": "Input",
|
"{id:category}Input": "Input",
|
||||||
|
"{id:category}JSON": "JSON",
|
||||||
"{id:category}Led": "Led",
|
"{id:category}Led": "Led",
|
||||||
"{id:category}Light": "Light",
|
"{id:category}Light": "Light",
|
||||||
|
"{id:category}Loops": "Loops",
|
||||||
"{id:category}Math": "Math",
|
"{id:category}Math": "Math",
|
||||||
"{id:category}MicrobitPin": "MicrobitPin",
|
"{id:category}MicrobitPin": "MicrobitPin",
|
||||||
"{id:category}Motors": "Motors",
|
"{id:category}Motors": "Motors",
|
||||||
@ -450,15 +447,27 @@
|
|||||||
"{id:category}Pins": "Pins",
|
"{id:category}Pins": "Pins",
|
||||||
"{id:category}PwmOnlyPin": "PwmOnlyPin",
|
"{id:category}PwmOnlyPin": "PwmOnlyPin",
|
||||||
"{id:category}Serial": "Serial",
|
"{id:category}Serial": "Serial",
|
||||||
|
"{id:category}Storage": "Storage",
|
||||||
"{id:category}String": "String",
|
"{id:category}String": "String",
|
||||||
"{id:category}Text": "Text",
|
"{id:category}Text": "Text",
|
||||||
"{id:category}_py": "_py",
|
"{id:category}_py": "_py",
|
||||||
"{id:group}Configuration": "Configuration",
|
"{id:group}Configuration": "Configuration",
|
||||||
|
"{id:group}Control": "Control",
|
||||||
|
"{id:group}Events": "Events",
|
||||||
|
"{id:group}Get": "Get",
|
||||||
|
"{id:group}LED matrix": "LED matrix",
|
||||||
"{id:group}Melody": "Melody",
|
"{id:group}Melody": "Melody",
|
||||||
"{id:group}Melody Advanced": "Melody Advanced",
|
"{id:group}Melody Advanced": "Melody Advanced",
|
||||||
"{id:group}Modify": "Modify",
|
"{id:group}Modify": "Modify",
|
||||||
"{id:group}Operations": "Operations",
|
"{id:group}Operations": "Operations",
|
||||||
|
"{id:group}Put": "Put",
|
||||||
|
"{id:group}RGB LED": "RGB LED",
|
||||||
"{id:group}Read": "Read",
|
"{id:group}Read": "Read",
|
||||||
|
"{id:group}Remove": "Remove",
|
||||||
|
"{id:group}Sensors": "Sensors",
|
||||||
|
"{id:group}Silence": "Silence",
|
||||||
|
"{id:group}States": "States",
|
||||||
|
"{id:group}System": "System",
|
||||||
"{id:group}Tempo": "Tempo",
|
"{id:group}Tempo": "Tempo",
|
||||||
"{id:group}Tone": "Tone",
|
"{id:group}Tone": "Tone",
|
||||||
"{id:group}Volume": "Volume"
|
"{id:group}Volume": "Volume"
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
"basic.rgbw|param|green": "Grünwert 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|red": "Rotwert zwischen 0 und 255, z.B. 255",
|
||||||
"basic.rgbw|param|white": "Weißwert zwischen 0 und 255, z.B. 0",
|
"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.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": "Zeigt eine Abfolge von LED-Anzeigen als Animation.",
|
||||||
"basic.showAnimation|param|interval": "Zeit in Millisekunden zwischen jedem Neuzeichnen",
|
"basic.showAnimation|param|interval": "Zeit in Millisekunden zwischen jedem Neuzeichnen",
|
||||||
|
@ -97,6 +97,7 @@
|
|||||||
"basic.forever|block": "dauerhaft",
|
"basic.forever|block": "dauerhaft",
|
||||||
"basic.pause|block": "pausiere (ms) %pause",
|
"basic.pause|block": "pausiere (ms) %pause",
|
||||||
"basic.rgbw|block": "Rot %red|Grün %green|Blau %blue|Weiß %white",
|
"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.setLedColor|block": "setze LED-Farbe auf %color=color_id",
|
||||||
"basic.showLeds|block": "zeige LEDs",
|
"basic.showLeds|block": "zeige LEDs",
|
||||||
"basic.showNumber|block": "zeige|Nummer %number",
|
"basic.showNumber|block": "zeige|Nummer %number",
|
||||||
|
@ -4,14 +4,122 @@
|
|||||||
/**
|
/**
|
||||||
* Provides access to basic micro:bit functionality.
|
* Provides access to basic micro:bit functionality.
|
||||||
*/
|
*/
|
||||||
//% color=#1E90FF weight=116 icon="\uf00a"
|
|
||||||
namespace basic {
|
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: 50, 100, 150, 200
|
||||||
|
*/
|
||||||
|
//% 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=80
|
||||||
|
//% group="LED matrix"
|
||||||
|
void showString(String text, int interval = 80) {
|
||||||
|
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.
|
* Sets the color on the build-in LED. Set to 0 to turn off.
|
||||||
*/
|
*/
|
||||||
//% blockId=device_set_led_color
|
//% blockId=device_set_led_color
|
||||||
//% block="set led to %color=colorNumberPicker"
|
//% block="set led to %color=colorNumberPicker"
|
||||||
//% weight=50
|
//% weight=10
|
||||||
|
//% group="RGB LED"
|
||||||
void setLedColor(int color) {
|
void setLedColor(int color) {
|
||||||
if (!color) {
|
if (!color) {
|
||||||
uBit.rgb.off();
|
uBit.rgb.off();
|
||||||
@ -31,104 +139,12 @@ namespace basic {
|
|||||||
* Sets the color on the build-in LED. Set to 0 to turn off.
|
* 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"
|
//% blockId=device_turn_rgb_led_off block="turn build-in LED off"
|
||||||
//% weight=50
|
//% weight=10
|
||||||
|
//% group="RGB LED"
|
||||||
|
//% advanced=true
|
||||||
void turnRgbLedOff() {
|
void turnRgbLedOff() {
|
||||||
uBit.rgb.off();
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -37,17 +37,52 @@ enum Colors {
|
|||||||
/**
|
/**
|
||||||
* Provides access to basic micro:bit functionality.
|
* 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 {
|
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: 50, 100, 150, 200
|
||||||
|
*/
|
||||||
|
//% 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=80
|
||||||
|
//% group="LED matrix"
|
||||||
|
export function showNumber(value: number, interval?: number) {
|
||||||
|
showString(Math.roundWithPrecision(value, 2).toString(), interval);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the color name to a number
|
* Converts the color name to a number
|
||||||
*/
|
*/
|
||||||
//% blockId=color_id block="%c" shim=TD_ID
|
//% blockId=color_id block="%c" shim=TD_ID
|
||||||
|
//% group="RGB LED"
|
||||||
|
//% weight=1
|
||||||
|
//% deprecated=true
|
||||||
export function color(c: Colors): number {
|
export function color(c: Colors): number {
|
||||||
return c;
|
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
|
* Converts red, green, blue channels into a RGB color
|
||||||
* @param red value of the red channel between 0 and 255. eg: 255
|
* @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 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
|
* @param white value of the white channel between 0 and 255. eg: 0
|
||||||
*/
|
*/
|
||||||
//% weight=1
|
//% weight=2
|
||||||
//% blockId="core_rgb" block="red %red|green %green|blue %blue|white %white"
|
//% 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 {
|
export function rgbw(red: number, green: number, blue: number, white:number): number {
|
||||||
return ((white & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
|
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
|
* Pause for the specified time in milliseconds
|
||||||
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
|
* @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);
|
basic.pause(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<block type="pins_on_pulsed" x="-157" y="130">
|
<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>
|
<field name="pulse">PulseValue.Low</field>
|
||||||
<statement name="HANDLER">
|
<statement name="HANDLER">
|
||||||
<block type="device_set_analog_pin">
|
<block type="device_set_analog_pin">
|
||||||
<field name="name">AnalogPin.C6</field>
|
<field name="name">AnalogPin.P9</field>
|
||||||
<value name="value">
|
<value name="value">
|
||||||
<shadow type="math_number">
|
<shadow type="math_number">
|
||||||
<field name="NUM">5</field>
|
<field name="NUM">5</field>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_analog_period">
|
<block type="device_set_analog_period">
|
||||||
<field name="pin">AnalogPin.C6</field>
|
<field name="pin">AnalogPin.P10</field>
|
||||||
<value name="micros">
|
<value name="micros">
|
||||||
<shadow type="math_number">
|
<shadow type="math_number">
|
||||||
<field name="NUM">20000</field>
|
<field name="NUM">20000</field>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_digital_pin">
|
<block type="device_set_digital_pin">
|
||||||
<field name="name">DigitalPin.C6</field>
|
<field name="name">DigitalPin.P6</field>
|
||||||
<value name="value">
|
<value name="value">
|
||||||
<shadow type="math_number">
|
<shadow type="math_number">
|
||||||
<field name="NUM">5</field>
|
<field name="NUM">5</field>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_servo_pin">
|
<block type="device_set_servo_pin">
|
||||||
<field name="name">AnalogPin.C5</field>
|
<field name="name">AnalogPin.P13</field>
|
||||||
<value name="value">
|
<value name="value">
|
||||||
<shadow type="math_number">
|
<shadow type="math_number">
|
||||||
<field name="NUM">5</field>
|
<field name="NUM">5</field>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_servo_pulse">
|
<block type="device_set_servo_pulse">
|
||||||
<field name="value">AnalogPin.C6</field>
|
<field name="value">AnalogPin.P8</field>
|
||||||
<value name="micros">
|
<value name="micros">
|
||||||
<shadow type="math_number" id="Hx4bpmg|8KSH=b_`+XtP">
|
<shadow type="math_number" id="Hx4bpmg|8KSH=b_`+XtP">
|
||||||
<field name="NUM">1500</field>
|
<field name="NUM">1500</field>
|
||||||
@ -65,7 +65,7 @@
|
|||||||
<field name="NUM">0</field>
|
<field name="NUM">0</field>
|
||||||
</shadow>
|
</shadow>
|
||||||
<block type="pins_pulse_in">
|
<block type="pins_pulse_in">
|
||||||
<field name="name">DigitalPin.C9</field>
|
<field name="name">DigitalPin.P9</field>
|
||||||
<field name="value">PulseValue.Low</field>
|
<field name="value">PulseValue.Low</field>
|
||||||
</block>
|
</block>
|
||||||
</value>
|
</value>
|
||||||
@ -102,7 +102,7 @@
|
|||||||
<field name="NUM">0</field>
|
<field name="NUM">0</field>
|
||||||
</shadow>
|
</shadow>
|
||||||
<block type="device_get_digital_pin">
|
<block type="device_get_digital_pin">
|
||||||
<field name="name">DigitalPin.C9</field>
|
<field name="name">DigitalPin.P9</field>
|
||||||
</block>
|
</block>
|
||||||
</value>
|
</value>
|
||||||
<value name="value">
|
<value name="value">
|
||||||
@ -110,7 +110,7 @@
|
|||||||
<field name="NUM">0</field>
|
<field name="NUM">0</field>
|
||||||
</shadow>
|
</shadow>
|
||||||
<block type="device_get_analog_pin">
|
<block type="device_get_analog_pin">
|
||||||
<field name="name">AnalogPin.C6</field>
|
<field name="name">AnalogPin.P9</field>
|
||||||
</block>
|
</block>
|
||||||
</value>
|
</value>
|
||||||
<value name="repeat">
|
<value name="repeat">
|
||||||
@ -120,12 +120,12 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="spi_pins">
|
<block type="spi_pins">
|
||||||
<field name="mosi">DigitalPin.C11</field>
|
<field name="mosi">DigitalPin.P11</field>
|
||||||
<field name="miso">DigitalPin.C9</field>
|
<field name="miso">DigitalPin.P9</field>
|
||||||
<field name="sck">DigitalPin.C10</field>
|
<field name="sck">DigitalPin.P10</field>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_pull">
|
<block type="device_set_pull">
|
||||||
<field name="pin">DigitalPin.C9</field>
|
<field name="pin">DigitalPin.P9</field>
|
||||||
<field name="pull">PinPullMode.PullDown</field>
|
<field name="pull">PinPullMode.PullDown</field>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_analog_pitch">
|
<block type="device_analog_pitch">
|
||||||
@ -141,11 +141,11 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_pin_events">
|
<block type="device_set_pin_events">
|
||||||
<field name="pin">DigitalPin.C8</field>
|
<field name="pin">DigitalPin.P8</field>
|
||||||
<field name="type">PinEventType.Touch</field>
|
<field name="type">PinEventType.Touch</field>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_analog_set_pitch_pin">
|
<block type="device_analog_set_pitch_pin">
|
||||||
<field name="name">AnalogPin.C6</field>
|
<field name="name">AnalogPin.P9</field>
|
||||||
<next>
|
<next>
|
||||||
<block type="spi_format">
|
<block type="spi_format">
|
||||||
<value name="bits">
|
<value name="bits">
|
||||||
|
@ -150,31 +150,31 @@
|
|||||||
<field name="mode">DisplayMode.Greyscale</field>
|
<field name="mode">DisplayMode.Greyscale</field>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_analog_pin">
|
<block type="device_set_analog_pin">
|
||||||
<field name="name">AnalogPin.C4</field>
|
<field name="name">AnalogPin.P4</field>
|
||||||
<value name="value">
|
<value name="value">
|
||||||
<shadow type="math_number_minmax" id=",:%8N*FL3wa-zFQ[+^$9">
|
<shadow type="math_number_minmax" id=",:%8N*FL3wa-zFQ[+^$9">
|
||||||
<mutation min="0" max="1023" label="Value"></mutation>
|
<mutation min="0" max="1023" label="Value"></mutation>
|
||||||
<field name="SLIDER">1023</field>
|
<field name="SLIDER">1023</field>
|
||||||
</shadow>
|
</shadow>
|
||||||
<block type="device_get_analog_pin">
|
<block type="device_get_analog_pin">
|
||||||
<field name="name">AnalogPin.C5</field>
|
<field name="name">AnalogPin.P13</field>
|
||||||
</block>
|
</block>
|
||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_digital_pin">
|
<block type="device_set_digital_pin">
|
||||||
<field name="name">DigitalPin.C10</field>
|
<field name="name">DigitalPin.P10</field>
|
||||||
<value name="value">
|
<value name="value">
|
||||||
<shadow type="math_number_minmax" id="W~pvdj%jFEj?EHmT{81Z">
|
<shadow type="math_number_minmax" id="W~pvdj%jFEj?EHmT{81Z">
|
||||||
<mutation min="0" max="1" label="Value"></mutation>
|
<mutation min="0" max="1" label="Value"></mutation>
|
||||||
<field name="SLIDER">0</field>
|
<field name="SLIDER">0</field>
|
||||||
</shadow>
|
</shadow>
|
||||||
<block type="device_get_digital_pin">
|
<block type="device_get_digital_pin">
|
||||||
<field name="name">DigitalPin.C15</field>
|
<field name="name">DigitalPin.P15</field>
|
||||||
</block>
|
</block>
|
||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_analog_period">
|
<block type="device_set_analog_period">
|
||||||
<field name="pin">AnalogPin.C6</field>
|
<field name="pin">AnalogPin.P9</field>
|
||||||
<value name="micros">
|
<value name="micros">
|
||||||
<shadow type="math_number" id="4a@.1MdG`n=p;34mQOpC">
|
<shadow type="math_number" id="4a@.1MdG`n=p;34mQOpC">
|
||||||
<field name="NUM">1234</field>
|
<field name="NUM">1234</field>
|
||||||
@ -230,7 +230,7 @@
|
|||||||
</value>
|
</value>
|
||||||
<next>
|
<next>
|
||||||
<block type="device_set_servo_pulse">
|
<block type="device_set_servo_pulse">
|
||||||
<field name="value">AnalogPin.C4</field>
|
<field name="value">AnalogPin.P14</field>
|
||||||
<value name="micros">
|
<value name="micros">
|
||||||
<shadow type="math_number" id="@*C3kzJkeeUQ@s$N5?K}">
|
<shadow type="math_number" id="@*C3kzJkeeUQ@s$N5?K}">
|
||||||
<field name="NUM">1500</field>
|
<field name="NUM">1500</field>
|
||||||
@ -510,7 +510,7 @@
|
|||||||
</statement>
|
</statement>
|
||||||
</block>
|
</block>
|
||||||
<block type="pins_on_pulsed" x="1538" y="929">
|
<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>
|
<field name="pulse">PulseValue.Low</field>
|
||||||
<statement name="HANDLER">
|
<statement name="HANDLER">
|
||||||
<block type="i2c_writenumber">
|
<block type="i2c_writenumber">
|
||||||
@ -575,8 +575,8 @@
|
|||||||
<next>
|
<next>
|
||||||
<block type="spi_pins">
|
<block type="spi_pins">
|
||||||
<field name="mosi">DigitalPin.P9</field>
|
<field name="mosi">DigitalPin.P9</field>
|
||||||
<field name="miso">DigitalPin.C14</field>
|
<field name="miso">DigitalPin.P14</field>
|
||||||
<field name="sck">DigitalPin.C16</field>
|
<field name="sck">DigitalPin.P16</field>
|
||||||
<next>
|
<next>
|
||||||
<block type="control_reset"></block>
|
<block type="control_reset"></block>
|
||||||
</next>
|
</next>
|
||||||
|
@ -8,6 +8,21 @@ PXT_ABI(__aeabi_dsub)
|
|||||||
PXT_ABI(__aeabi_ddiv)
|
PXT_ABI(__aeabi_ddiv)
|
||||||
PXT_ABI(__aeabi_dmul)
|
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) {
|
extern "C" void target_panic(int error_code) {
|
||||||
#if !MICROBIT_CODAL
|
#if !MICROBIT_CODAL
|
||||||
// wait for serial to flush
|
// wait for serial to flush
|
||||||
@ -28,6 +43,7 @@ namespace pxt {
|
|||||||
|
|
||||||
MicroBit uBit;
|
MicroBit uBit;
|
||||||
MicroBitEvent lastEvent;
|
MicroBitEvent lastEvent;
|
||||||
|
bool serialLoggingDisabled;
|
||||||
|
|
||||||
void platform_init() {
|
void platform_init() {
|
||||||
microbit_seed_random();
|
microbit_seed_random();
|
||||||
@ -152,6 +168,7 @@ int current_time_ms() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void logwriten(const char *msg, int l) {
|
static void logwriten(const char *msg, int l) {
|
||||||
|
if (!serialLoggingDisabled)
|
||||||
uBit.serial.send((uint8_t *)msg, l);
|
uBit.serial.send((uint8_t *)msg, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,174 +1,4 @@
|
|||||||
let compassImages = [
|
const compassImagesLeft = [
|
||||||
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(`
|
|
||||||
. . . # .
|
|
||||||
. . . . .
|
|
||||||
. . # . .
|
|
||||||
. . . . .
|
|
||||||
. . . . .
|
|
||||||
`),
|
|
||||||
images.createImage(`
|
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 {
|
namespace basic {
|
||||||
@ -242,6 +131,7 @@ namespace basic {
|
|||||||
//% interval.defl=600
|
//% interval.defl=600
|
||||||
//% parts="ledmatrix"
|
//% parts="ledmatrix"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
|
//% group="LED matrix"
|
||||||
export function showCompass(interval = 600) {
|
export function showCompass(interval = 600) {
|
||||||
let i = 0
|
let i = 0
|
||||||
let startTime = input.runningTime()
|
let startTime = input.runningTime()
|
||||||
@ -251,22 +141,15 @@ namespace basic {
|
|||||||
|
|
||||||
while ((endTime) > (input.runningTime() + refreshRate)) {
|
while ((endTime) > (input.runningTime() + refreshRate)) {
|
||||||
i = Math.round((input.compassHeading() - 11.25) / 22.5)
|
i = Math.round((input.compassHeading() - 11.25) / 22.5)
|
||||||
if (input.isGesture(Gesture.ScreenDown)) {
|
let images = (input.isGesture(Gesture.ScreenDown)) ? compassImagesDownside : compassImages;
|
||||||
compassImagesDownside[i].showImage(0, refreshRate)
|
images[i].showImage(0, refreshRate)
|
||||||
} else {
|
|
||||||
compassImages[i].showImage(0, refreshRate)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rest = (endTime - input.runningTime())
|
rest = (endTime - input.runningTime())
|
||||||
if(rest > 0) {
|
if(rest > 0) {
|
||||||
i = Math.round((input.compassHeading() - 11.25) / 22.5)
|
i = Math.round((input.compassHeading() - 11.25) / 22.5)
|
||||||
if (input.isGesture(Gesture.ScreenDown)) {
|
let images = (input.isGesture(Gesture.ScreenDown)) ? compassImagesDownside : compassImages;
|
||||||
compassImagesDownside[i].showImage(0, rest)
|
images[i].showImage(0, rest)
|
||||||
} else {
|
|
||||||
compassImages[i].showImage(0, rest)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,51 @@
|
|||||||
/// <reference no-default-lib="true"/>
|
/// <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.
|
* Reading and writing data to the console output.
|
||||||
*/
|
*/
|
||||||
//% weight=12 color=#002050 icon="\uf120"
|
//% weight=12 color=#002050 icon="\uf120"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
namespace console {
|
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.
|
* Write a line of text to the console output.
|
||||||
@ -17,15 +53,8 @@ namespace console {
|
|||||||
*/
|
*/
|
||||||
//% weight=90
|
//% weight=90
|
||||||
//% help=console/log blockGap=8
|
//% help=console/log blockGap=8
|
||||||
export function log(text: any): void {
|
export function log(value: any): void {
|
||||||
let stringified = inspect(text);
|
add(ConsolePriority.Log, value);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,21 +64,8 @@ namespace console {
|
|||||||
*/
|
*/
|
||||||
//% weight=88 blockGap=8
|
//% weight=88 blockGap=8
|
||||||
//% help=console/log-value
|
//% help=console/log-value
|
||||||
export function logValue(name: any, value: number): void {
|
export function logValue(name: any, value: any): void {
|
||||||
const nameText = inspect(name);
|
log(name ? `${inspect(name)}: ${inspect(value)}` : `${inspect(value)}`)
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,8 +98,7 @@ namespace console {
|
|||||||
keys = keys.slice(0, maxElements);
|
keys = keys.slice(0, maxElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `{${
|
return `{${keys.reduce(
|
||||||
keys.reduce(
|
|
||||||
(prev, currKey) => prev + `\n ${currKey}: ${obj[currKey]}`,
|
(prev, currKey) => prev + `\n ${currKey}: ${obj[currKey]}`,
|
||||||
""
|
""
|
||||||
) + (snipped ? "\n ..." : "")
|
) + (snipped ? "\n ..." : "")
|
||||||
@ -91,4 +106,27 @@ namespace console {
|
|||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#include "pxt.h"
|
#include "pxt.h"
|
||||||
|
|
||||||
|
extern uint32_t __StackTop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How to create the event.
|
* How to create the event.
|
||||||
*/
|
*/
|
||||||
@ -271,8 +273,9 @@ namespace control {
|
|||||||
* Blocks the current fiber for the given microseconds
|
* Blocks the current fiber for the given microseconds
|
||||||
* @param micros number of micro-seconds to wait. eg: 4
|
* @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"
|
//% blockId="control_wait_us" block="wait (µs)%micros"
|
||||||
|
//% micros.min=0 micros.max=6000
|
||||||
void waitMicros(int micros) {
|
void waitMicros(int micros) {
|
||||||
sleep_us(micros);
|
sleep_us(micros);
|
||||||
}
|
}
|
||||||
@ -341,6 +344,15 @@ namespace control {
|
|||||||
return microbit_serial_number();
|
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
|
* Informs simulator/runtime of a MIDI message
|
||||||
* Internal function to support the simulator.
|
* 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;
|
if (NULL == text) return;
|
||||||
pxt::sendSerial(text->getUTF8Data(), text->getUTF8Size());
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,11 @@ namespace control {
|
|||||||
control.inBackground(a);
|
control.inBackground(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//% hidden=1 deprecated=1
|
||||||
|
export function runInBackground(a: () => void) {
|
||||||
|
control.inBackground(a);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of a C++ runtime constant
|
* Returns the value of a C++ runtime constant
|
||||||
*/
|
*/
|
||||||
@ -31,6 +36,50 @@ namespace control {
|
|||||||
return id;
|
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.
|
* Display specified error code and stop the program.
|
||||||
*/
|
*/
|
||||||
@ -61,6 +110,28 @@ namespace control {
|
|||||||
*/
|
*/
|
||||||
//% shim=pxtrt::runtimeWarning
|
//% shim=pxtrt::runtimeWarning
|
||||||
export function runtimeWarning(message: string) { }
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
18
libs/core/enums.d.ts
vendored
@ -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 {
|
declare const enum Dimension {
|
||||||
//% block=x
|
//% block=x
|
||||||
X = 0,
|
X = 0,
|
||||||
@ -548,5 +564,7 @@ declare namespace motors {
|
|||||||
}
|
}
|
||||||
declare namespace serial {
|
declare namespace serial {
|
||||||
}
|
}
|
||||||
|
declare namespace storage {
|
||||||
|
}
|
||||||
|
|
||||||
// Auto-generated. Do not edit. Really.
|
// Auto-generated. Do not edit. Really.
|
||||||
|
@ -65,87 +65,6 @@ enum IconNames {
|
|||||||
//% block="meh"
|
//% block="meh"
|
||||||
//% jres=icons.meh
|
//% jres=icons.meh
|
||||||
Meh,
|
Meh,
|
||||||
//% block="t-shirt"
|
|
||||||
//% jres=icons.tshirt
|
|
||||||
TShirt,
|
|
||||||
//% block="roller skate"
|
|
||||||
//% jres=icons.rollerskate
|
|
||||||
Rollerskate,
|
|
||||||
//% block="duck"
|
|
||||||
//% jres=icons.duck
|
|
||||||
Duck,
|
|
||||||
//% block="house"
|
|
||||||
//% jres=icons.house
|
|
||||||
House,
|
|
||||||
//% block="tortoise"
|
|
||||||
//% jres=icons.tortoise
|
|
||||||
Tortoise,
|
|
||||||
//% block="butterfly"
|
|
||||||
//% jres=icons.butterfly
|
|
||||||
Butterfly,
|
|
||||||
//% block="stick figure"
|
|
||||||
//% jres=icons.stickfigure
|
|
||||||
StickFigure,
|
|
||||||
//% block="ghost"
|
|
||||||
//% jres=icons.ghost
|
|
||||||
Ghost,
|
|
||||||
//% block="sword"
|
|
||||||
//% jres=icons.sword
|
|
||||||
Sword,
|
|
||||||
//% block="giraffe"
|
|
||||||
//% jres=icons.giraffe
|
|
||||||
Giraffe,
|
|
||||||
//% block="skull"
|
|
||||||
//% jres=icons.skull
|
|
||||||
Skull,
|
|
||||||
//% block="umbrella"
|
|
||||||
//% jres=icons.umbrella
|
|
||||||
Umbrella,
|
|
||||||
//% block="snake"
|
|
||||||
//% jres=icons.snake
|
|
||||||
Snake,
|
|
||||||
//% block="rabbit"
|
|
||||||
//% jres=icons.rabbit
|
|
||||||
Rabbit,
|
|
||||||
//% block="cow"
|
|
||||||
//% jres=icons.cow
|
|
||||||
Cow,
|
|
||||||
//% block="quarter note"
|
|
||||||
//% jres=icons.quarternote
|
|
||||||
QuarterNote,
|
|
||||||
//% block="eigth note"
|
|
||||||
//% jres=icons.eigthnote
|
|
||||||
EigthNote,
|
|
||||||
//% block="pitchfork"
|
|
||||||
//% jres=icons.pitchfork
|
|
||||||
Pitchfork,
|
|
||||||
//% block="target"
|
|
||||||
//% jres=icons.target
|
|
||||||
Target,
|
|
||||||
//% block="triangle"
|
|
||||||
//% jres=icons.triangle
|
|
||||||
Triangle,
|
|
||||||
//% block="left triangle"
|
|
||||||
//% jres=icons.lefttriangle
|
|
||||||
LeftTriangle,
|
|
||||||
//% block="chess board"
|
|
||||||
//% jres=icons.chessboard
|
|
||||||
Chessboard,
|
|
||||||
//% block="diamond"
|
|
||||||
//% jres=icons.diamond
|
|
||||||
Diamond,
|
|
||||||
//% block="small diamond"
|
|
||||||
//% jres=icons.smalldiamond
|
|
||||||
SmallDiamond,
|
|
||||||
//% block="square"
|
|
||||||
//% jres=icons.square
|
|
||||||
Square,
|
|
||||||
//% block="small square"
|
|
||||||
//% jres=icons.smallsquare
|
|
||||||
SmallSquare,
|
|
||||||
//% block="scissors"
|
|
||||||
//% jres=icons.scissors
|
|
||||||
Scissors,
|
|
||||||
//% block="arrow north"
|
//% block="arrow north"
|
||||||
//% jres=icons.arrownorth
|
//% jres=icons.arrownorth
|
||||||
ArrowNorth,
|
ArrowNorth,
|
||||||
@ -172,132 +91,36 @@ enum IconNames {
|
|||||||
ArrowNorthWest
|
ArrowNorthWest
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ArrowNames {
|
|
||||||
//% blockIdentity=images.arrowNumber block="North"
|
|
||||||
North = 0,
|
|
||||||
//% blockIdentity=images.arrowNumber block="North East"
|
|
||||||
NorthEast,
|
|
||||||
//% blockIdentity=images.arrowNumber block="East"
|
|
||||||
East,
|
|
||||||
//% blockIdentity=images.arrowNumber block="South East"
|
|
||||||
SouthEast,
|
|
||||||
//% blockIdentity=images.arrowNumber block="South"
|
|
||||||
South,
|
|
||||||
//% blockIdentity=images.arrowNumber block="South West"
|
|
||||||
SouthWest,
|
|
||||||
//% blockIdentity=images.arrowNumber block="West"
|
|
||||||
West,
|
|
||||||
//% blockIdentity=images.arrowNumber block="North West"
|
|
||||||
NorthWest
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace basic {
|
namespace basic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the selected icon on the LED screen
|
* Draws the selected icon on the LED screen
|
||||||
* @param icon the predefined icon id
|
* @param icon the predefined icon id
|
||||||
* @param interval the amount of time (milliseconds) to show the icon. Default is 600.
|
* @param interval the amount of time (milliseconds) to block the LED Matrix for showing the icon. Default is 200.
|
||||||
*/
|
*/
|
||||||
//% weight=90 blockGap=8
|
//% weight=90 blockGap=8
|
||||||
//% blockId=basic_show_icon
|
//% blockId=basic_show_icon
|
||||||
//% block="show icon %i" icon="\uf00a"
|
//% block="show icon %i || for %interval ms" icon="\uf00a"
|
||||||
//% parts="ledmatrix"
|
//% parts="ledmatrix"
|
||||||
//% help=basic/show-icon
|
//% help=basic/show-icon
|
||||||
//% icon.fieldEditor="imagedropdown"
|
//% icon.fieldEditor="imagedropdown"
|
||||||
//% icon.fieldOptions.columns="5"
|
//% icon.fieldOptions.columns="5"
|
||||||
//% icon.fieldOptions.width="380"
|
//% icon.fieldOptions.width="380"
|
||||||
//% icon.fieldOptions.maxRows=4
|
//% icon.fieldOptions.maxRows=4
|
||||||
export function showIcon(icon: IconNames, interval = 600) {
|
//% expandableArgumentMode="toggle"
|
||||||
|
//% interval.defl=200
|
||||||
|
//% group="LED matrix"
|
||||||
|
export function showIcon(icon: IconNames, interval = 200) {
|
||||||
let res = images.iconImage(icon)
|
let res = images.iconImage(icon)
|
||||||
res.showImage(0, interval)
|
res.showImage(0, interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws an arrow on the LED screen
|
|
||||||
* @param direction the direction of the arrow
|
|
||||||
* @param interval the amount of time (milliseconds) to show the icon. Default is 600.
|
|
||||||
*/
|
|
||||||
//% weight=50 blockGap=8
|
|
||||||
//% blockId=basic_show_arrow
|
|
||||||
//% block="show arrow %i=device_arrow"
|
|
||||||
//% parts="ledmatrix"
|
|
||||||
//% advanced=true
|
|
||||||
//% help=basic/show-arrow
|
|
||||||
//% deprecated=true
|
|
||||||
export function showArrow(direction: number, interval = 600) {
|
|
||||||
let res = images.arrowImage(direction)
|
|
||||||
res.showImage(0, interval)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace images {
|
namespace images {
|
||||||
|
|
||||||
//% weight=50 blockGap=8
|
|
||||||
//% help=images/arrow-image
|
|
||||||
//% blockId=builtin_arrow_image block="arrow image %i"
|
|
||||||
//% deprecated=true
|
|
||||||
export function arrowImage(i: ArrowNames): Image {
|
|
||||||
switch (i) {
|
|
||||||
// compass directions
|
|
||||||
case ArrowNames.North: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. # # # .
|
|
||||||
# . # . #
|
|
||||||
. . # . .
|
|
||||||
. . # . .`);
|
|
||||||
case ArrowNames.NorthEast: return images.createImage(`
|
|
||||||
. . # # #
|
|
||||||
. . . # #
|
|
||||||
. . # . #
|
|
||||||
. # . . .
|
|
||||||
# . . . .`);
|
|
||||||
case ArrowNames.East: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. . . # .
|
|
||||||
# # # # #
|
|
||||||
. . . # .
|
|
||||||
. . # . .`);
|
|
||||||
case ArrowNames.SouthEast: return images.createImage(`
|
|
||||||
# . . . .
|
|
||||||
. # . . .
|
|
||||||
. . # . #
|
|
||||||
. . . # #
|
|
||||||
. . # # #`);
|
|
||||||
case ArrowNames.South: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. . # . .
|
|
||||||
# . # . #
|
|
||||||
. # # # .
|
|
||||||
. . # . .`);
|
|
||||||
case ArrowNames.SouthWest: return images.createImage(`
|
|
||||||
. . . . #
|
|
||||||
. . . # .
|
|
||||||
# . # . .
|
|
||||||
# # . . .
|
|
||||||
# # # . .`);
|
|
||||||
case ArrowNames.West: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. # . . .
|
|
||||||
# # # # #
|
|
||||||
. # . . .
|
|
||||||
. . # . .`);
|
|
||||||
case ArrowNames.NorthWest: return images.createImage(`
|
|
||||||
# # # . .
|
|
||||||
# # . . .
|
|
||||||
# . # . .
|
|
||||||
. . . # .
|
|
||||||
. . . . #`);
|
|
||||||
default: return images.createImage(`
|
|
||||||
. . . . .
|
|
||||||
. . . . .
|
|
||||||
. . . . .
|
|
||||||
. . . . .
|
|
||||||
. . . . .
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//% weight=50 blockGap=8
|
//% weight=50 blockGap=8
|
||||||
//% help=images/icon-image
|
//% help=images/icon-image
|
||||||
//% blockId=builtin_image block="icon image %i"
|
//% blockId=builtin_image block="icon image %i"
|
||||||
@ -387,173 +210,6 @@ namespace images {
|
|||||||
. . # . .
|
. . # . .
|
||||||
. # . # .
|
. # . # .
|
||||||
# . . . #`);
|
# . . . #`);
|
||||||
case IconNames.Triangle: return images.createImage(`
|
|
||||||
. . . . .
|
|
||||||
. . # . .
|
|
||||||
. # . # .
|
|
||||||
# # # # #
|
|
||||||
. . . . .`);
|
|
||||||
case IconNames.LeftTriangle: return images.createImage(`
|
|
||||||
# . . . .
|
|
||||||
# # . . .
|
|
||||||
# . # . .
|
|
||||||
# . . # .
|
|
||||||
# # # # #`);
|
|
||||||
case IconNames.Chessboard: return images.createImage(`
|
|
||||||
. # . # .
|
|
||||||
# . # . #
|
|
||||||
. # . # .
|
|
||||||
# . # . #
|
|
||||||
. # . # .`);
|
|
||||||
case IconNames.Diamond: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. # . # .
|
|
||||||
# . . . #
|
|
||||||
. # . # .
|
|
||||||
. . # . .`);
|
|
||||||
case IconNames.SmallDiamond: return images.createImage(`
|
|
||||||
. . . . .
|
|
||||||
. . # . .
|
|
||||||
. # . # .
|
|
||||||
. . # . .
|
|
||||||
. . . . .`);
|
|
||||||
case IconNames.Square: return images.createImage(`
|
|
||||||
# # # # #
|
|
||||||
# . . . #
|
|
||||||
# . . . #
|
|
||||||
# . . . #
|
|
||||||
# # # # #`);
|
|
||||||
case IconNames.SmallSquare: return images.createImage(`
|
|
||||||
. . . . .
|
|
||||||
. # # # .
|
|
||||||
. # . # .
|
|
||||||
. # # # .
|
|
||||||
. . . . .`);
|
|
||||||
|
|
||||||
case IconNames.Scissors: return images.createImage(`
|
|
||||||
# # . . #
|
|
||||||
# # . # .
|
|
||||||
. . # . .
|
|
||||||
# # . # .
|
|
||||||
# # . . #`);
|
|
||||||
// The following images were designed by Abbie Brooks.
|
|
||||||
case IconNames.TShirt: return images.createImage(`
|
|
||||||
# # . # #
|
|
||||||
# # # # #
|
|
||||||
. # # # .
|
|
||||||
. # # # .
|
|
||||||
. # # # .`);
|
|
||||||
case IconNames.Rollerskate: return images.createImage(`
|
|
||||||
. . . # #
|
|
||||||
. . . # #
|
|
||||||
# # # # #
|
|
||||||
# # # # #
|
|
||||||
. # . # .`);
|
|
||||||
case IconNames.Duck: return images.createImage(`
|
|
||||||
. # # . .
|
|
||||||
# # # . .
|
|
||||||
. # # # #
|
|
||||||
. # # # .
|
|
||||||
. . . . .`);
|
|
||||||
case IconNames.House: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. # # # .
|
|
||||||
# # # # #
|
|
||||||
. # # # .
|
|
||||||
. # . # .`);
|
|
||||||
case IconNames.Tortoise: return images.createImage(`
|
|
||||||
. . . . .
|
|
||||||
. # # # .
|
|
||||||
# # # # #
|
|
||||||
. # . # .
|
|
||||||
. . . . .`);
|
|
||||||
case IconNames.Butterfly: return images.createImage(`
|
|
||||||
# # . # #
|
|
||||||
# # # # #
|
|
||||||
. . # . .
|
|
||||||
# # # # #
|
|
||||||
# # . # #`);
|
|
||||||
case IconNames.StickFigure: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
# # # # #
|
|
||||||
. . # . .
|
|
||||||
. # . # .
|
|
||||||
# . . . #`);
|
|
||||||
case IconNames.Ghost: return images.createImage(`
|
|
||||||
. # # # .
|
|
||||||
# . # . #
|
|
||||||
# # # # #
|
|
||||||
# # # # #
|
|
||||||
# . # . #`);
|
|
||||||
case IconNames.Sword: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. . # . .
|
|
||||||
. . # . .
|
|
||||||
. # # # .
|
|
||||||
. . # . .`);
|
|
||||||
case IconNames.Giraffe: return images.createImage(`
|
|
||||||
# # . . .
|
|
||||||
. # . . .
|
|
||||||
. # . . .
|
|
||||||
. # # # .
|
|
||||||
. # . # .`);
|
|
||||||
case IconNames.Skull: return images.createImage(`
|
|
||||||
. # # # .
|
|
||||||
# . # . #
|
|
||||||
# # # # #
|
|
||||||
. # # # .
|
|
||||||
. # # # .`);
|
|
||||||
case IconNames.Umbrella: return images.createImage(`
|
|
||||||
. # # # .
|
|
||||||
# # # # #
|
|
||||||
. . # . .
|
|
||||||
# . # . .
|
|
||||||
# # # . .`);
|
|
||||||
case IconNames.Snake: return images.createImage(`
|
|
||||||
# # . . .
|
|
||||||
# # . # #
|
|
||||||
. # . # .
|
|
||||||
. # # # .
|
|
||||||
. . . . .`);
|
|
||||||
// animals
|
|
||||||
case IconNames.Rabbit: return images.createImage(`
|
|
||||||
# . # . .
|
|
||||||
# . # . .
|
|
||||||
# # # # .
|
|
||||||
# # . # .
|
|
||||||
# # # # .`);
|
|
||||||
case IconNames.Cow: return images.createImage(`
|
|
||||||
# . . . #
|
|
||||||
# . . . #
|
|
||||||
# # # # #
|
|
||||||
. # # # .
|
|
||||||
. . # . .`);
|
|
||||||
// musical notes
|
|
||||||
case IconNames.QuarterNote: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. . # . .
|
|
||||||
. . # . .
|
|
||||||
# # # . .
|
|
||||||
# # # . .`);
|
|
||||||
case IconNames.EigthNote: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. . # # .
|
|
||||||
. . # . #
|
|
||||||
# # # . .
|
|
||||||
# # # . .`);
|
|
||||||
// other icons
|
|
||||||
case IconNames.Pitchfork: return images.createImage(`
|
|
||||||
# . # . #
|
|
||||||
# . # . #
|
|
||||||
# # # # #
|
|
||||||
. . # . .
|
|
||||||
. . # . .`);
|
|
||||||
case IconNames.Target: return images.createImage(`
|
|
||||||
. . # . .
|
|
||||||
. # # # .
|
|
||||||
# # . # #
|
|
||||||
. # # # .
|
|
||||||
. . # . .`);
|
|
||||||
// arrows
|
// arrows
|
||||||
case IconNames.ArrowNorth: return images.createImage(`
|
case IconNames.ArrowNorth: return images.createImage(`
|
||||||
. . # . .
|
. . # . .
|
||||||
@ -613,12 +269,4 @@ namespace images {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//% weight=50 blockGap=8
|
|
||||||
//% help=images/arrow-number
|
|
||||||
//% blockId=device_arrow block="%arrow"
|
|
||||||
//% shim=TD_ID
|
|
||||||
//% deprecated=true
|
|
||||||
export function arrowNumber(arrow: ArrowNames): number {
|
|
||||||
return arrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -83,9 +83,11 @@ void plotImage(Image i, int xOffset = 0) {
|
|||||||
/**
|
/**
|
||||||
* Shows an frame from the image at offset ``x offset``.
|
* Shows an frame from the image at offset ``x offset``.
|
||||||
* @param xOffset column index to start displaying the image
|
* @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
|
//% 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
|
//% blockGap=8 parts="ledmatrix" async
|
||||||
void showImage(Image sprite, int xOffset, int interval = 400) {
|
void showImage(Image sprite, int xOffset, int interval = 400) {
|
||||||
uBit.display.print(MicroBitImage(sprite->img), -xOffset, 0, 0, interval);
|
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
|
//% help=images/scroll-image weight=79 async blockNamespace=images
|
||||||
//% blockId=device_scroll_image
|
//% 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"
|
//% blockGap=8 parts="ledmatrix"
|
||||||
void scrollImage(Image id, int frameOffset, int interval) {
|
void scrollImage(Image id, int frameOffset, int interval) {
|
||||||
MicroBitImage i(id->img);
|
MicroBitImage i(id->img);
|
||||||
|
@ -7,6 +7,21 @@ enum class Button {
|
|||||||
AB = MICROBIT_ID_BUTTON_AB,
|
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 {
|
enum class Dimension {
|
||||||
//% block=x
|
//% block=x
|
||||||
X = 0,
|
X = 0,
|
||||||
@ -161,6 +176,21 @@ enum class MesDpadButtonInfo {
|
|||||||
|
|
||||||
//% color=#B4009E weight=99 icon="\uf192"
|
//% color=#B4009E weight=99 icon="\uf192"
|
||||||
namespace input {
|
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.
|
* 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
|
* @param button the button that needs to be pressed
|
||||||
@ -169,6 +199,8 @@ namespace input {
|
|||||||
//% help=input/on-button-pressed weight=85 blockGap=16
|
//% help=input/on-button-pressed weight=85 blockGap=16
|
||||||
//% blockId=device_button_event block="on button|%NAME|pressed"
|
//% blockId=device_button_event block="on button|%NAME|pressed"
|
||||||
//% parts="buttonpair"
|
//% parts="buttonpair"
|
||||||
|
//% deprecated=true
|
||||||
|
//% group="Events"
|
||||||
void onButtonPressed(Button button, Action body) {
|
void onButtonPressed(Button button, Action body) {
|
||||||
registerWithDal((int)button, MICROBIT_BUTTON_EVT_CLICK, 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 gesture the type of gesture to track, eg: Gesture.Shake
|
||||||
* @param body code to run when gesture is raised
|
* @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"
|
//% blockId=device_gesture_event block="on |%NAME"
|
||||||
//% parts="accelerometer"
|
//% parts="accelerometer"
|
||||||
//% NAME.fieldEditor="gestures" NAME.fieldOptions.columns=4
|
//% NAME.fieldEditor="gestures" NAME.fieldOptions.columns=4
|
||||||
|
//% group="Events"
|
||||||
void onGesture(Gesture gesture, Action body) {
|
void onGesture(Gesture gesture, Action body) {
|
||||||
int gi = (int)gesture;
|
int gi = (int)gesture;
|
||||||
if (gi == MICROBIT_ACCELEROMETER_EVT_3G && uBit.accelerometer.getRange() < 3)
|
if (gi == MICROBIT_ACCELEROMETER_EVT_3G && uBit.accelerometer.getRange() < 3)
|
||||||
@ -195,10 +228,11 @@ namespace input {
|
|||||||
* Tests if a gesture is currently detected.
|
* Tests if a gesture is currently detected.
|
||||||
* @param gesture the type of gesture to detect, eg: Gesture.Shake
|
* @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"
|
//% blockId=deviceisgesture block="is %gesture gesture"
|
||||||
//% parts="accelerometer"
|
//% parts="accelerometer"
|
||||||
//% gesture.fieldEditor="gestures" gesture.fieldOptions.columns=4
|
//% gesture.fieldEditor="gestures" gesture.fieldOptions.columns=4
|
||||||
|
//% group="States"
|
||||||
bool isGesture(Gesture gesture) {
|
bool isGesture(Gesture gesture) {
|
||||||
// turn on acceleration
|
// turn on acceleration
|
||||||
uBit.accelerometer.getX();
|
uBit.accelerometer.getX();
|
||||||
@ -206,13 +240,33 @@ namespace input {
|
|||||||
return uBit.accelerometer.getGesture() == gi;
|
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).
|
* 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 name the pin that needs to be pressed, eg: TouchPin.P0
|
||||||
* @param body the code to run when the pin is pressed
|
* @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"
|
//% blockId=device_pin_event block="on pin %name|pressed"
|
||||||
|
//% group="Events"
|
||||||
|
//% deprecated=true
|
||||||
void onPinPressed(TouchPin name, Action body) {
|
void onPinPressed(TouchPin name, Action body) {
|
||||||
auto pin = getPin((int)name);
|
auto pin = getPin((int)name);
|
||||||
if (!pin) return;
|
if (!pin) return;
|
||||||
@ -230,6 +284,8 @@ namespace input {
|
|||||||
//% help=input/on-pin-released weight=6 blockGap=16
|
//% help=input/on-pin-released weight=6 blockGap=16
|
||||||
//% blockId=device_pin_released block="on pin %NAME|released"
|
//% blockId=device_pin_released block="on pin %NAME|released"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
|
//% group="Events"
|
||||||
|
//% deprecated=true
|
||||||
void onPinReleased(TouchPin name, Action body) {
|
void onPinReleased(TouchPin name, Action body) {
|
||||||
auto pin = getPin((int)name);
|
auto pin = getPin((int)name);
|
||||||
if (!pin) return;
|
if (!pin) return;
|
||||||
@ -243,11 +299,12 @@ namespace input {
|
|||||||
* Get the button state (pressed or not) for ``A`` and ``B``.
|
* Get the button state (pressed or not) for ``A`` and ``B``.
|
||||||
* @param button the button to query the request, eg: Button.A
|
* @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"
|
//% block="button|%NAME|is pressed"
|
||||||
//% blockId=device_get_button2
|
//% blockId=device_get_button2
|
||||||
//% icon="\uf192" blockGap=8
|
//% icon="\uf192" blockGap=8
|
||||||
//% parts="buttonpair"
|
//% parts="buttonpair"
|
||||||
|
//% group="States"
|
||||||
bool buttonIsPressed(Button button) {
|
bool buttonIsPressed(Button button) {
|
||||||
if (button == Button::A)
|
if (button == Button::A)
|
||||||
return uBit.buttonA.isPressed();
|
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.
|
* 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
|
* @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"
|
//% blockId="device_pin_is_pressed" block="pin %NAME|is pressed"
|
||||||
//% blockGap=8
|
//% blockGap=8
|
||||||
|
//% group="States"
|
||||||
bool pinIsPressed(TouchPin name) {
|
bool pinIsPressed(TouchPin name) {
|
||||||
auto pin = getPin((int)name);
|
auto pin = getPin((int)name);
|
||||||
return pin && pin->isTouched();
|
return pin && pin->isTouched();
|
||||||
@ -284,6 +342,7 @@ namespace input {
|
|||||||
//% help=input/acceleration weight=58
|
//% help=input/acceleration weight=58
|
||||||
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
|
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
|
||||||
//% parts="accelerometer"
|
//% parts="accelerometer"
|
||||||
|
//% group="Sensors"
|
||||||
int acceleration(Dimension dimension) {
|
int acceleration(Dimension dimension) {
|
||||||
switch (dimension) {
|
switch (dimension) {
|
||||||
case Dimension::X: return uBit.accelerometer.getX();
|
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.
|
* 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
|
//% blockId=device_get_light_level block="light level" blockGap=8
|
||||||
//% parts="ledmatrix"
|
//% parts="ledmatrix"
|
||||||
|
//% group="Sensors"
|
||||||
int lightLevel() {
|
int lightLevel() {
|
||||||
return uBit.display.readLightLevel();
|
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.
|
* Get the current compass heading in degrees.
|
||||||
*/
|
*/
|
||||||
@ -311,6 +394,7 @@ namespace input {
|
|||||||
//% weight=56
|
//% weight=56
|
||||||
//% blockId=device_heading block="compass heading (°)" blockGap=8
|
//% blockId=device_heading block="compass heading (°)" blockGap=8
|
||||||
//% parts="compass"
|
//% parts="compass"
|
||||||
|
//% group="Sensors"
|
||||||
int compassHeading() {
|
int compassHeading() {
|
||||||
return uBit.compass.heading();
|
return uBit.compass.heading();
|
||||||
}
|
}
|
||||||
@ -319,10 +403,11 @@ namespace input {
|
|||||||
/**
|
/**
|
||||||
* Gets the temperature in Celsius degrees (°C).
|
* Gets the temperature in Celsius degrees (°C).
|
||||||
*/
|
*/
|
||||||
//% weight=55
|
//% weight=57
|
||||||
//% help=input/temperature
|
//% help=input/temperature
|
||||||
//% blockId=device_temperature block="temperature (°C)" blockGap=8
|
//% blockId=device_temperature block="temperature (°C)" blockGap=8
|
||||||
//% parts="thermometer"
|
//% parts="thermometer"
|
||||||
|
//% group="Sensors"
|
||||||
int temperature() {
|
int temperature() {
|
||||||
return uBit.thermometer.getTemperature();
|
return uBit.thermometer.getTemperature();
|
||||||
}
|
}
|
||||||
@ -334,6 +419,7 @@ namespace input {
|
|||||||
//% help=input/rotation weight=52
|
//% help=input/rotation weight=52
|
||||||
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8
|
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8
|
||||||
//% parts="accelerometer" advanced=true
|
//% parts="accelerometer" advanced=true
|
||||||
|
//% group="Sensors"
|
||||||
int rotation(Rotation kind) {
|
int rotation(Rotation kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Rotation::Pitch: return uBit.accelerometer.getPitch();
|
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.
|
* 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
|
* @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
|
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8
|
||||||
//% parts="compass"
|
//% parts="compass"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
|
//% group="Sensors"
|
||||||
TNumber magneticForce(Dimension dimension) {
|
TNumber magneticForce(Dimension dimension) {
|
||||||
if (!uBit.compass.isCalibrated())
|
if (!uBit.compass.isCalibrated())
|
||||||
uBit.compass.calibrate();
|
uBit.compass.calibrate();
|
||||||
@ -368,20 +455,58 @@ namespace input {
|
|||||||
*/
|
*/
|
||||||
//% help=input/calibrate-compass advanced=true
|
//% help=input/calibrate-compass advanced=true
|
||||||
//% blockId="input_compass_calibrate" block="calibrate compass"
|
//% blockId="input_compass_calibrate" block="calibrate compass"
|
||||||
//% weight=45
|
//% weight=20 gap=8
|
||||||
|
//% group="Configuration"
|
||||||
void calibrateCompass() {
|
void calibrateCompass() {
|
||||||
uBit.compass.calibrate();
|
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.
|
* Sets the accelerometer sample range in gravities.
|
||||||
* @param range a value describe the maximum strengh of acceleration measured
|
* @param range a value describe the maximum strengh of acceleration measured
|
||||||
*/
|
*/
|
||||||
//% help=input/set-accelerometer-range
|
//% help=input/set-accelerometer-range
|
||||||
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range"
|
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range"
|
||||||
//% weight=5
|
//% weight=22 gap=8
|
||||||
//% parts="accelerometer"
|
//% parts="accelerometer"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
|
//% group="Configuration"
|
||||||
void setAccelerometerRange(AcceleratorRange range) {
|
void setAccelerometerRange(AcceleratorRange range) {
|
||||||
uBit.accelerometer.setRange((int)range);
|
uBit.accelerometer.setRange((int)range);
|
||||||
}
|
}
|
||||||
|
@ -1,69 +1,26 @@
|
|||||||
/**
|
/**
|
||||||
* Events and data from sensors
|
* Events and data from sensors
|
||||||
*/
|
*/
|
||||||
//% color=#C90072 weight=99
|
//% color=#C90072 weight=99 icon="\uf192"
|
||||||
|
//% groups=['Events', 'States', 'Sensors', 'Configuration', 'System', 'others']
|
||||||
namespace input {
|
namespace input {
|
||||||
/**
|
/**
|
||||||
* Attaches code to run when the screen is facing up.
|
* Returns the value of a C++ runtime constant
|
||||||
* @param body TODO
|
|
||||||
*/
|
*/
|
||||||
//% help=input/on-screen-up
|
//% weight=1 weight=19 blockId="control_button_event_value_id" block="%id"
|
||||||
export function onScreenUp(body: () => void): void {
|
//% shim=TD_ID advanced=true
|
||||||
onGesture(Gesture.ScreenUp, body);
|
//% 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.
|
* Gets the number of milliseconds elapsed since power on.
|
||||||
*/
|
*/
|
||||||
//% help=input/running-time weight=50 blockGap=8
|
//% help=input/running-time weight=50 blockGap=8
|
||||||
//% blockId=device_get_running_time block="running time (ms)"
|
//% blockId=device_get_running_time block="running time (ms)"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
|
//% group="System"
|
||||||
export function runningTime() {
|
export function runningTime() {
|
||||||
return control.millis();
|
return control.millis();
|
||||||
}
|
}
|
||||||
@ -71,33 +28,12 @@ namespace input {
|
|||||||
/**
|
/**
|
||||||
* Gets the number of microseconds elapsed since power on.
|
* 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)"
|
//% blockId=device_get_running_time_micros block="running time (micros)"
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
|
//% group="System"
|
||||||
export function runningTimeMicros() {
|
export function runningTimeMicros() {
|
||||||
return control.micros();
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,41 @@
|
|||||||
#include "pxt.h"
|
#include "pxt.h"
|
||||||
|
|
||||||
#if MICROBIT_CODAL
|
#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
|
#else
|
||||||
extern "C" void neopixel_send_buffer_core(DevicePin *pin, const uint8_t *ptr, int numBytes);
|
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,
|
__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
|
// setup pin as digital
|
||||||
pin.setDigitalValue(0);
|
pin.setDigitalValue(0);
|
||||||
|
wait_us(300); // initial reset
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
neopixel_send_buffer_core(&pin, ptr, numBytes);
|
neopixel_send_buffer_core(&pin, ptr, numBytes);
|
||||||
__enable_irq();
|
__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
|
#endif
|
||||||
|
|
||||||
namespace light {
|
namespace light {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a color buffer to a light strip
|
* Sends a color buffer to a light strip
|
||||||
**/
|
**/
|
||||||
//% advanced=true
|
//% advanced=true
|
||||||
//%
|
|
||||||
void sendWS2812Buffer(Buffer buf, int pin) {
|
void sendWS2812Buffer(Buffer buf, int pin) {
|
||||||
if (!buf || !buf->length)
|
if (!buf || !buf->length)
|
||||||
return;
|
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
|
//% advanced=true
|
||||||
//%
|
void sendWS2812BufferWithBrightness(Buffer buf, int pin, int brightness) {
|
||||||
void setMode(int pin, int mode) {
|
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
|
} // namespace light
|
||||||
|
38
libs/core/loops.ts
Normal 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
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ namespace motors {
|
|||||||
//% blockId=motor_on block="motor on at %percent \\%"
|
//% blockId=motor_on block="motor on at %percent \\%"
|
||||||
//% parts=dcmotor weight=90 blockGap=8
|
//% parts=dcmotor weight=90 blockGap=8
|
||||||
//% percent.shadow="speedPicker"
|
//% percent.shadow="speedPicker"
|
||||||
|
//% power.defl=100
|
||||||
void motorPower(int power) {
|
void motorPower(int power) {
|
||||||
uBit.soundmotor.motorOn(power);
|
uBit.soundmotor.motorOn(power);
|
||||||
}
|
}
|
||||||
@ -51,13 +52,19 @@ namespace motors {
|
|||||||
//% blockId=block_dual_motor block="motor %motor|at %percent \\%"
|
//% blockId=block_dual_motor block="motor %motor|at %percent \\%"
|
||||||
//% percent.shadow="speedPicker"
|
//% percent.shadow="speedPicker"
|
||||||
//% weight=80
|
//% weight=80
|
||||||
|
//% duty_percent.defl=100
|
||||||
void dualMotorPower(Motor motor, int duty_percent) {
|
void dualMotorPower(Motor motor, int duty_percent) {
|
||||||
switch(motor) {
|
switch(motor) {
|
||||||
case Motor::A: if (duty_percent <= 0) uBit.soundmotor.motorAOff();
|
case Motor::A:
|
||||||
else uBit.soundmotor.motorAOn(duty_percent); break;
|
if (duty_percent <= 0) uBit.soundmotor.motorAOff();
|
||||||
case Motor::B: if (duty_percent <= 0) uBit.soundmotor.motorBOff();
|
else uBit.soundmotor.motorAOn(duty_percent);
|
||||||
else uBit.soundmotor.motorBOn(duty_percent); break;
|
break;
|
||||||
case Motor::AB: if (duty_percent <= 0) {
|
case Motor::B:
|
||||||
|
if (duty_percent <= 0) uBit.soundmotor.motorBOff();
|
||||||
|
else uBit.soundmotor.motorBOn(duty_percent);
|
||||||
|
break;
|
||||||
|
case Motor::AB:
|
||||||
|
if (duty_percent <= 0) {
|
||||||
uBit.soundmotor.motorAOff();
|
uBit.soundmotor.motorAOff();
|
||||||
uBit.soundmotor.motorBOff();
|
uBit.soundmotor.motorBOff();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
#include "pxt.h"
|
#include "pxt.h"
|
||||||
|
|
||||||
|
namespace pins {
|
||||||
|
void analogSetPitchVolume(int volume);
|
||||||
|
int analogPitchVolume();
|
||||||
|
}
|
||||||
|
|
||||||
namespace music {
|
namespace music {
|
||||||
/**
|
/**
|
||||||
* Plays a tone through ``speaker`` for the given duration.
|
* 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
|
||||||
|
}
|
||||||
}
|
}
|
@ -223,7 +223,7 @@ namespace music {
|
|||||||
//% help=music/rest weight=79
|
//% help=music/rest weight=79
|
||||||
//% blockId=device_rest block="rest(ms)|%duration=device_beat"
|
//% blockId=device_rest block="rest(ms)|%duration=device_beat"
|
||||||
//% parts="speaker"
|
//% parts="speaker"
|
||||||
//% group="Tone"
|
//% group="Silence"
|
||||||
export function rest(ms: number): void {
|
export function rest(ms: number): void {
|
||||||
playTone(0, ms);
|
playTone(0, ms);
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ namespace music {
|
|||||||
* Gets the frequency of a note.
|
* Gets the frequency of a note.
|
||||||
* @param name the note name
|
* @param name the note name
|
||||||
*/
|
*/
|
||||||
//% weight=50 help=music/note-frequency
|
//% weight=50
|
||||||
//% blockId=device_note block="%name"
|
//% blockId=device_note block="%name"
|
||||||
//% shim=TD_ID color="#FFFFFF" colorSecondary="#FFFFFF"
|
//% shim=TD_ID color="#FFFFFF" colorSecondary="#FFFFFF"
|
||||||
//% name.fieldEditor="note" name.defl="262"
|
//% name.fieldEditor="note" name.defl="262"
|
||||||
@ -241,6 +241,7 @@ namespace music {
|
|||||||
//% useEnumVal=1
|
//% useEnumVal=1
|
||||||
//% group="Tone"
|
//% group="Tone"
|
||||||
//% blockGap=8
|
//% blockGap=8
|
||||||
|
//% blockHidden=true
|
||||||
export function noteFrequency(name: Note): number {
|
export function noteFrequency(name: Note): number {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -289,6 +290,7 @@ namespace music {
|
|||||||
//% help=music/change-tempo-by weight=39
|
//% help=music/change-tempo-by weight=39
|
||||||
//% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8
|
//% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8
|
||||||
//% group="Tempo"
|
//% group="Tempo"
|
||||||
|
//% weight=100
|
||||||
export function changeTempoBy(bpm: number): void {
|
export function changeTempoBy(bpm: number): void {
|
||||||
init();
|
init();
|
||||||
setTempo(beatsPerMinute + bpm);
|
setTempo(beatsPerMinute + bpm);
|
||||||
@ -302,6 +304,7 @@ namespace music {
|
|||||||
//% blockId=device_set_tempo block="set tempo to (bpm)|%value"
|
//% blockId=device_set_tempo block="set tempo to (bpm)|%value"
|
||||||
//% bpm.min=4 bpm.max=400
|
//% bpm.min=4 bpm.max=400
|
||||||
//% group="Tempo"
|
//% group="Tempo"
|
||||||
|
//% weight=99
|
||||||
export function setTempo(bpm: number): void {
|
export function setTempo(bpm: number): void {
|
||||||
init();
|
init();
|
||||||
if (bpm > 0) {
|
if (bpm > 0) {
|
||||||
@ -330,6 +333,7 @@ namespace music {
|
|||||||
//% blockId=melody_on_event block="music on %value"
|
//% blockId=melody_on_event block="music on %value"
|
||||||
//% help=music/on-event weight=59 blockGap=32
|
//% help=music/on-event weight=59 blockGap=32
|
||||||
//% group="Melody Advanced"
|
//% group="Melody Advanced"
|
||||||
|
//% blockHidden=true
|
||||||
export function onEvent(value: MusicEvent, handler: () => void) {
|
export function onEvent(value: MusicEvent, handler: () => void) {
|
||||||
control.onEvent(MICROBIT_MELODY_ID, value, handler);
|
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"
|
//% blockId=device_start_melody block="start melody %melody=device_builtin_melody| repeating %options"
|
||||||
//% parts="speaker"
|
//% parts="speaker"
|
||||||
//% group="Melody Advanced"
|
//% group="Melody Advanced"
|
||||||
|
//% blockHidden=true
|
||||||
export function startMelody(melodyArray: string[], options: MelodyOptions = 1) {
|
export function startMelody(melodyArray: string[], options: MelodyOptions = 1) {
|
||||||
init();
|
init();
|
||||||
if (currentMelody != undefined) {
|
if (currentMelody != undefined) {
|
||||||
@ -453,7 +458,7 @@ namespace music {
|
|||||||
//% help=music/stop-melody weight=59 blockGap=16
|
//% help=music/stop-melody weight=59 blockGap=16
|
||||||
//% blockId=device_stop_melody block="stop melody $options"
|
//% blockId=device_stop_melody block="stop melody $options"
|
||||||
//% parts="speaker"
|
//% parts="speaker"
|
||||||
//% group="Melody Advanced"
|
//% group="Silence"
|
||||||
export function stopMelody(options: MelodyStopOptions) {
|
export function stopMelody(options: MelodyStopOptions) {
|
||||||
if (options & MelodyStopOptions.Background)
|
if (options & MelodyStopOptions.Background)
|
||||||
startMelody([], MelodyOptions.OnceInBackground);
|
startMelody([], MelodyOptions.OnceInBackground);
|
||||||
@ -461,6 +466,19 @@ namespace music {
|
|||||||
startMelody([], MelodyOptions.Once);
|
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
|
* Sets a custom playTone function for playing melodies
|
||||||
*/
|
*/
|
||||||
@ -471,35 +489,6 @@ namespace music {
|
|||||||
_playTone = f;
|
_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 {
|
function playNextNote(melody: Melody): void {
|
||||||
// cache elements
|
// cache elements
|
||||||
let currNote = melody.nextNote();
|
let currNote = melody.nextNote();
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
#include "pxt.h"
|
#include "pxt.h"
|
||||||
|
|
||||||
|
#if MICROBIT_CODAL
|
||||||
|
#include "Pin.h"
|
||||||
|
#define PinCompat codal::Pin
|
||||||
|
#else
|
||||||
|
#define PinCompat MicroBitPin
|
||||||
|
#endif
|
||||||
|
|
||||||
enum class DigitalPin {
|
enum class DigitalPin {
|
||||||
P0 = MICROBIT_ID_IO_P12, // edge connector 0
|
P0 = MICROBIT_ID_IO_P12, // edge connector 0
|
||||||
P1 = MICROBIT_ID_IO_P0, // edge connector 1
|
P1 = MICROBIT_ID_IO_P0, // edge connector 1
|
||||||
@ -217,6 +224,17 @@ namespace pins {
|
|||||||
MicroBitPin* pin = getPin((int)name);
|
MicroBitPin* pin = getPin((int)name);
|
||||||
if (!pin) return 0;
|
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;
|
int pulse = value == PulseValue::High ? 1 : 0;
|
||||||
uint64_t tick = system_timer_current_time_us();
|
uint64_t tick = system_timer_current_time_us();
|
||||||
uint64_t maxd = (uint64_t)maxDuration;
|
uint64_t maxd = (uint64_t)maxDuration;
|
||||||
@ -232,6 +250,7 @@ namespace pins {
|
|||||||
}
|
}
|
||||||
uint64_t end = system_timer_current_time_us();
|
uint64_t end = system_timer_current_time_us();
|
||||||
return end - start;
|
return end - start;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO FIX THIS IN THE DAL!
|
// TODO FIX THIS IN THE DAL!
|
||||||
@ -257,7 +276,6 @@ namespace pins {
|
|||||||
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
|
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
|
||||||
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
|
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
|
||||||
void servoWritePin(AnalogPin name, int value) {
|
void servoWritePin(AnalogPin name, int value) {
|
||||||
fixMotorIssue(name);
|
|
||||||
PINOP(setServoValue(value));
|
PINOP(setServoValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,9 +302,10 @@ namespace pins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MicroBitPin* pitchPin = NULL;
|
PinCompat* pitchPin = NULL;
|
||||||
MicroBitPin* pitchPin2 = NULL;
|
PinCompat* pitchPin2 = NULL;
|
||||||
uint8_t pitchVolume = 0xff;
|
uint8_t pitchVolume = 0xff;
|
||||||
|
bool analogTonePlaying = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the pin used when using analog pitch or music.
|
* 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
|
//% help=pins/analog-set-pitch-pin weight=3 advanced=true
|
||||||
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
|
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
|
||||||
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
|
//% name.fieldOptions.tooltips="false" name.fieldOptions.width="250"
|
||||||
|
//% blockHidden=true
|
||||||
void analogSetPitchPin(AnalogPin name) {
|
void analogSetPitchPin(AnalogPin name) {
|
||||||
pitchPin = getPin((int)name);
|
pitchPin = getPin((int)name);
|
||||||
pitchPin2 = NULL;
|
pitchPin2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pinAnalogSetPitch(MicroBitPin* pin, int frequency, int ms) {
|
void pinAnalogSetPitch(PinCompat* pin, int frequency, int ms) {
|
||||||
if (frequency <= 0 || pitchVolume == 0) {
|
if (frequency <= 0 || pitchVolume == 0) {
|
||||||
pin->setAnalogValue(0);
|
pin->setAnalogValue(0);
|
||||||
} else {
|
} else {
|
||||||
@ -318,8 +338,15 @@ namespace pins {
|
|||||||
//% blockId=device_analog_set_pitch_volume block="analog set pitch volume $volume"
|
//% blockId=device_analog_set_pitch_volume block="analog set pitch volume $volume"
|
||||||
//% help=pins/analog-set-pitch-volume weight=3 advanced=true
|
//% help=pins/analog-set-pitch-volume weight=3 advanced=true
|
||||||
//% volume.min=0 volume.max=255
|
//% volume.min=0 volume.max=255
|
||||||
|
//% blockHidden=true
|
||||||
void analogSetPitchVolume(int volume) {
|
void analogSetPitchVolume(int volume) {
|
||||||
pitchVolume = max(0, min(0xff, 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"
|
//% blockId=device_analog_pitch_volume block="analog pitch volume"
|
||||||
//% help=pins/analog-pitch-volume weight=3 advanced=true
|
//% help=pins/analog-pitch-volume weight=3 advanced=true
|
||||||
|
//% blockHidden=true
|
||||||
int analogPitchVolume() {
|
int analogPitchVolume() {
|
||||||
return pitchVolume;
|
return pitchVolume;
|
||||||
}
|
}
|
||||||
@ -338,6 +366,7 @@ namespace pins {
|
|||||||
*/
|
*/
|
||||||
//% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms"
|
//% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms"
|
||||||
//% help=pins/analog-pitch weight=4 async advanced=true blockGap=8
|
//% help=pins/analog-pitch weight=4 async advanced=true blockGap=8
|
||||||
|
//% blockHidden=true
|
||||||
void analogPitch(int frequency, int ms) {
|
void analogPitch(int frequency, int ms) {
|
||||||
// init pins if needed
|
// init pins if needed
|
||||||
if (NULL == pitchPin) {
|
if (NULL == pitchPin) {
|
||||||
@ -347,6 +376,7 @@ namespace pins {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// set pitch
|
// set pitch
|
||||||
|
analogTonePlaying = true;
|
||||||
if (NULL != pitchPin)
|
if (NULL != pitchPin)
|
||||||
pinAnalogSetPitch(pitchPin, frequency, ms);
|
pinAnalogSetPitch(pitchPin, frequency, ms);
|
||||||
if (NULL != pitchPin2)
|
if (NULL != pitchPin2)
|
||||||
@ -356,9 +386,9 @@ namespace pins {
|
|||||||
fiber_sleep(ms);
|
fiber_sleep(ms);
|
||||||
if (NULL != pitchPin)
|
if (NULL != pitchPin)
|
||||||
pitchPin->setAnalogValue(0);
|
pitchPin->setAnalogValue(0);
|
||||||
if (NULL != pitchPin2)
|
analogTonePlaying = false;
|
||||||
pitchPin2->setAnalogValue(0);
|
// causes issues with v2 DMA.
|
||||||
fiber_sleep(5);
|
// fiber_sleep(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,6 +442,21 @@ namespace pins {
|
|||||||
return mkBuffer(NULL, size);
|
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
|
#if MICROBIT_CODAL
|
||||||
#define BUFFER_TYPE uint8_t*
|
#define BUFFER_TYPE uint8_t*
|
||||||
#else
|
#else
|
||||||
@ -534,10 +579,26 @@ namespace pins {
|
|||||||
*/
|
*/
|
||||||
//% help=pins/push-button advanced=true
|
//% help=pins/push-button advanced=true
|
||||||
void pushButton(DigitalPin pin) {
|
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
|
#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
|
#else
|
||||||
new MicroBitButton(PIN_ARG(pin), PinMode::PullUp);
|
// v1 behavior
|
||||||
|
pins::analogSetPitchPin(name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -45,6 +45,7 @@ typedef RefMImage *Image;
|
|||||||
|
|
||||||
extern MicroBit uBit;
|
extern MicroBit uBit;
|
||||||
extern MicroBitEvent lastEvent;
|
extern MicroBitEvent lastEvent;
|
||||||
|
extern bool serialLoggingDisabled;
|
||||||
|
|
||||||
MicroBitPin *getPin(int id);
|
MicroBitPin *getPin(int id);
|
||||||
|
|
||||||
|
@ -33,12 +33,16 @@
|
|||||||
"gestures.jres",
|
"gestures.jres",
|
||||||
"control.ts",
|
"control.ts",
|
||||||
"control.cpp",
|
"control.cpp",
|
||||||
|
"controlgc.cpp",
|
||||||
|
"perfcounters.ts",
|
||||||
"interval.ts",
|
"interval.ts",
|
||||||
"gcstats.ts",
|
"gcstats.ts",
|
||||||
"console.ts",
|
"console.ts",
|
||||||
"game.ts",
|
"game.ts",
|
||||||
"led.cpp",
|
"led.cpp",
|
||||||
"led.ts",
|
"led.ts",
|
||||||
|
"loops.ts",
|
||||||
|
"microphone.ts",
|
||||||
"motors.cpp",
|
"motors.cpp",
|
||||||
"music.cpp",
|
"music.cpp",
|
||||||
"music.ts",
|
"music.ts",
|
||||||
@ -49,12 +53,19 @@
|
|||||||
"serial.ts",
|
"serial.ts",
|
||||||
"buffer.cpp",
|
"buffer.cpp",
|
||||||
"buffer.ts",
|
"buffer.ts",
|
||||||
|
"json.ts",
|
||||||
|
"poll.ts",
|
||||||
|
"controlmessage.ts",
|
||||||
"pxtparts.json",
|
"pxtparts.json",
|
||||||
"advmath.cpp",
|
"advmath.cpp",
|
||||||
"trig.cpp",
|
"trig.cpp",
|
||||||
"fixed.ts",
|
"fixed.ts",
|
||||||
"templates.ts",
|
"templates.ts",
|
||||||
"sendbuffer.s",
|
"sendbuffer.s",
|
||||||
|
"sendbuffernrf52.s",
|
||||||
|
"sendbufferbrightness.s",
|
||||||
|
"storage.cpp",
|
||||||
|
"storage.ts",
|
||||||
"light.cpp",
|
"light.cpp",
|
||||||
"compass.ts",
|
"compass.ts",
|
||||||
"parts/speaker.svg",
|
"parts/speaker.svg",
|
||||||
@ -94,63 +105,63 @@
|
|||||||
"yotta": {
|
"yotta": {
|
||||||
"config": {
|
"config": {
|
||||||
"microbit-dal": {
|
"microbit-dal": {
|
||||||
"fiber_user_data": 1
|
"fiber_user_data": 1,
|
||||||
|
"pxt": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"optionalConfig": {
|
"optionalConfig": {
|
||||||
"microbit-dal": {
|
"microbit-dal": {
|
||||||
"bluetooth": {
|
"bluetooth": {
|
||||||
|
"enabled": 1,
|
||||||
|
"pairing_mode": 1,
|
||||||
"private_addressing": 0,
|
"private_addressing": 0,
|
||||||
|
"open": 1,
|
||||||
|
"security_level": null,
|
||||||
|
"whitelist": 1,
|
||||||
"advertising_timeout": 0,
|
"advertising_timeout": 0,
|
||||||
"tx_power": 6,
|
"tx_power": 6,
|
||||||
"dfu_service": 1,
|
"dfu_service": 1,
|
||||||
"event_service": 1,
|
"event_service": 0,
|
||||||
"device_info_service": 1,
|
"device_info_service": 0
|
||||||
"eddystone_url": 1,
|
},
|
||||||
"eddystone_uid": 1,
|
"stack_size": 2048,
|
||||||
"open": 0,
|
"gatt_table_size": "0x600",
|
||||||
"pairing_mode": 1,
|
"panic_on_heap_full": 0,
|
||||||
"whitelist": 1,
|
"debug": 0,
|
||||||
"security_level": "SECURITY_MODE_ENCRYPTION_NO_MITM",
|
"heap_debug": 0,
|
||||||
"partial_flashing": 1
|
"sram_end": "0x20008000"
|
||||||
}
|
},
|
||||||
}
|
"RAM_SIZE": "\"32K\""
|
||||||
},
|
},
|
||||||
"userConfigs": [
|
"userConfigs": [
|
||||||
{
|
{
|
||||||
"description": "No Pairing Required: Anyone can connect via Bluetooth.",
|
"description": "Limit bluetooth access to BLE mode (A + B + Reset)",
|
||||||
"config": {
|
"config": {
|
||||||
"microbit-dal": {
|
"microbit-dal": {
|
||||||
"bluetooth": {
|
"bluetooth": {
|
||||||
"open": 1,
|
"enabled": 0
|
||||||
"whitelist": 0,
|
|
||||||
"security_level": null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "JustWorks pairing (default): Pairing is automatic once the pairing is initiated.",
|
"description": "32K RAM (mini v2 and some v1.3)",
|
||||||
"config": {
|
"config": {
|
||||||
"microbit-dal": {
|
"microbit-dal": {
|
||||||
"bluetooth": {
|
"stack_size": 2048,
|
||||||
"open": 0,
|
"sram_end": "0x20008000"
|
||||||
"whitelist": 1,
|
},
|
||||||
"security_level": "SECURITY_MODE_ENCRYPTION_NO_MITM"
|
"RAM_SIZE": "\"32K\""
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Passkey pairing: Pairing requires 6 digit key to pair.",
|
"description": "16K RAM (mini v1.3 and below)",
|
||||||
"config": {
|
"config": {
|
||||||
"microbit-dal": {
|
"microbit-dal": {
|
||||||
"bluetooth": {
|
"stack_size": 1280,
|
||||||
"open": 0,
|
"sram_end": "0x20004000"
|
||||||
"whitelist": 1,
|
},
|
||||||
"security_level": "SECURITY_MODE_ENCRYPTION_WITH_MITM"
|
"RAM_SIZE": "\"16K\""
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -16,14 +16,13 @@ void debuglog(const char *format, ...);
|
|||||||
|
|
||||||
#define GC_MAX_ALLOC_SIZE 9000
|
#define GC_MAX_ALLOC_SIZE 9000
|
||||||
|
|
||||||
#define GC_BLOCK_SIZE 256
|
|
||||||
#define NON_GC_HEAP_RESERVATION 1024
|
#define NON_GC_HEAP_RESERVATION 1024
|
||||||
|
|
||||||
|
|
||||||
#ifdef CODAL_CONFIG_H
|
#ifdef CODAL_CONFIG_H
|
||||||
#define MICROBIT_CODAL 1
|
#define MICROBIT_CODAL 1
|
||||||
#else
|
#else
|
||||||
#define MICROBIT_CODAL 0
|
#define MICROBIT_CODAL 0
|
||||||
|
#define GC_BLOCK_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !MICROBIT_CODAL
|
#if !MICROBIT_CODAL
|
||||||
|
53
libs/core/sendbufferbrightness.s
Normal 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}
|
82
libs/core/sendbuffernrf52.s
Normal 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
|
@ -106,24 +106,29 @@ namespace serial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read multiple characters from the receive buffer. Pause until enough characters are present.
|
* Read multiple characters from the receive buffer.
|
||||||
* @param length default buffer length, eg: 64
|
* If length is positive, pauses until enough characters are present.
|
||||||
|
* @param length default buffer length
|
||||||
*/
|
*/
|
||||||
//% blockId=serial_readbuffer block="serial|read buffer %length"
|
//% blockId=serial_readbuffer block="serial|read buffer %length"
|
||||||
//% help=serial/read-buffer advanced=true weight=5
|
//% help=serial/read-buffer advanced=true weight=5
|
||||||
Buffer readBuffer(int length) {
|
Buffer readBuffer(int length) {
|
||||||
if (length <= 0)
|
auto mode = SYNC_SLEEP;
|
||||||
length = MICROBIT_SERIAL_READ_BUFFER_LENGTH;
|
if (length <= 0) {
|
||||||
|
length = uBit.serial.getRxBufferSize();
|
||||||
auto buf = mkBuffer(NULL, length);
|
mode = ASYNC;
|
||||||
int read = uBit.serial.read(buf->data, buf->length);
|
|
||||||
if (read != length) {
|
|
||||||
auto prev = buf;
|
|
||||||
buf = mkBuffer(buf->data, read);
|
|
||||||
decrRC(prev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
bool tryResolvePin(SerialPin p, PinName& name) {
|
||||||
|
407
libs/core/shims.d.ts
vendored
@ -37,9 +37,11 @@ declare interface Image {
|
|||||||
/**
|
/**
|
||||||
* Shows an frame from the image at offset ``x offset``.
|
* Shows an frame from the image at offset ``x offset``.
|
||||||
* @param xOffset column index to start displaying the image
|
* @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
|
//% 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
|
//% blockGap=8 parts="ledmatrix" async interval.defl=400 shim=ImageMethods::showImage
|
||||||
showImage(xOffset: int32, interval?: int32): void;
|
showImage(xOffset: int32, interval?: int32): void;
|
||||||
|
|
||||||
@ -58,7 +60,7 @@ declare interface Image {
|
|||||||
*/
|
*/
|
||||||
//% help=images/scroll-image weight=79 async blockNamespace=images
|
//% help=images/scroll-image weight=79 async blockNamespace=images
|
||||||
//% blockId=device_scroll_image
|
//% 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
|
//% blockGap=8 parts="ledmatrix" shim=ImageMethods::scrollImage
|
||||||
scrollImage(frameOffset: int32, interval: int32): void;
|
scrollImage(frameOffset: int32, interval: int32): void;
|
||||||
|
|
||||||
@ -127,67 +129,48 @@ declare interface Image {
|
|||||||
/**
|
/**
|
||||||
* Provides access to basic micro:bit functionality.
|
* Provides access to basic micro:bit functionality.
|
||||||
*/
|
*/
|
||||||
//% color=#1E90FF weight=116 icon="\uf00a"
|
|
||||||
declare namespace basic {
|
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.
|
* Draws an image on the LED screen.
|
||||||
* @param leds the pattern of LED to turn on/off
|
* @param leds the pattern of LED to turn on/off
|
||||||
* @param interval time in milliseconds to pause after drawing
|
* @param interval time in milliseconds to pause after drawing
|
||||||
*/
|
*/
|
||||||
//% help=basic/show-leds
|
//% help=basic/show-leds
|
||||||
//% weight=95 blockGap=8
|
//% weight=85 blockGap=8
|
||||||
//% imageLiteral=1 async
|
//% imageLiteral=1 async
|
||||||
//% blockId=device_show_leds
|
//% blockId=device_show_leds
|
||||||
//% block="show leds" icon="\uf00a"
|
//% 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;
|
function showLeds(leds: string, interval?: int32): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* 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 text the text to scroll on the screen, eg: "hi!"
|
||||||
* @param interval how fast to shift characters; eg: 150, 100, 200, -100
|
* @param interval how fast to shift characters; eg: 50, 100, 150, 200
|
||||||
*/
|
*/
|
||||||
//% help=basic/show-string
|
//% help=basic/show-string
|
||||||
//% weight=87 blockGap=16
|
//% weight=100 blockGap=16
|
||||||
//% block="show|string %text"
|
//% block="show|string %text || in an interval of %interval ms"
|
||||||
//% async
|
//% async
|
||||||
//% blockId=device_print_message
|
//% blockId=device_print_message
|
||||||
//% parts="ledmatrix"
|
//% parts="ledmatrix"
|
||||||
//% text.shadowOptions.toString=true interval.defl=150 shim=basic::showString
|
//% text.shadowOptions.toString=true
|
||||||
|
//% expandableArgumentMode="toggle"
|
||||||
|
//%
|
||||||
|
//% group="LED matrix" interval.defl=80 shim=basic::showString
|
||||||
function showString(text: string, interval?: int32): void;
|
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.
|
* Shows a sequence of LED screens as an animation.
|
||||||
* @param leds pattern of LEDs to turn on/off
|
* @param leds pattern of LEDs to turn on/off
|
||||||
* @param interval time in milliseconds between each redraw
|
* @param interval time in milliseconds between each redraw
|
||||||
*/
|
*/
|
||||||
//% help=basic/show-animation imageLiteral=1 async
|
//% help=basic/show-animation weight=83 imageLiteral=1 async
|
||||||
//% parts="ledmatrix" interval.defl=400 shim=basic::showAnimation
|
//% parts="ledmatrix"
|
||||||
|
//% group="LED matrix" interval.defl=400 shim=basic::showAnimation
|
||||||
function showAnimation(leds: string, interval?: int32): void;
|
function showAnimation(leds: string, interval?: int32): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,26 +178,57 @@ declare namespace basic {
|
|||||||
* @param leds pattern of LEDs to turn on/off
|
* @param leds pattern of LEDs to turn on/off
|
||||||
*/
|
*/
|
||||||
//% help=basic/plot-leds weight=80
|
//% 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;
|
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.
|
* Repeats the code forever in the background. On each iteration, allows other codes to run.
|
||||||
* @param body code to execute
|
* @param body code to execute
|
||||||
*/
|
*/
|
||||||
//% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true
|
//% 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;
|
function forever(a: () => void): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause for the specified time in milliseconds
|
* Pause for the specified time in milliseconds
|
||||||
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
|
* @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
|
//% async block="pause (ms) %pause" blockGap=16
|
||||||
//% blockId=device_pause icon="\uf110"
|
//% blockId=device_pause icon="\uf110"
|
||||||
//% pause.shadow=timePicker shim=basic::pause
|
//% pause.shadow=timePicker
|
||||||
|
//% group="Control" shim=basic::pause
|
||||||
function pause(ms: int32): void;
|
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"
|
//% color=#B4009E weight=99 icon="\uf192"
|
||||||
declare namespace input {
|
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.
|
* 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
|
* @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
|
//% help=input/on-button-pressed weight=85 blockGap=16
|
||||||
//% blockId=device_button_event block="on button|%NAME|pressed"
|
//% 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;
|
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 gesture the type of gesture to track, eg: Gesture.Shake
|
||||||
* @param body code to run when gesture is raised
|
* @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"
|
//% blockId=device_gesture_event block="on |%NAME"
|
||||||
//% parts="accelerometer"
|
//% 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;
|
function onGesture(gesture: Gesture, body: () => void): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if a gesture is currently detected.
|
* Tests if a gesture is currently detected.
|
||||||
* @param gesture the type of gesture to detect, eg: Gesture.Shake
|
* @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"
|
//% blockId=deviceisgesture block="is %gesture gesture"
|
||||||
//% parts="accelerometer"
|
//% 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;
|
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).
|
* 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 name the pin that needs to be pressed, eg: TouchPin.P0
|
||||||
* @param body the code to run when the pin is pressed
|
* @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" shim=input::onPinPressed
|
//% blockId=device_pin_event block="on pin %name|pressed"
|
||||||
|
//% group="Events"
|
||||||
|
//% deprecated=true shim=input::onPinPressed
|
||||||
function onPinPressed(name: TouchPin, body: () => void): void;
|
function onPinPressed(name: TouchPin, body: () => void): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,27 +311,31 @@ declare namespace input {
|
|||||||
*/
|
*/
|
||||||
//% help=input/on-pin-released weight=6 blockGap=16
|
//% help=input/on-pin-released weight=6 blockGap=16
|
||||||
//% blockId=device_pin_released block="on pin %NAME|released"
|
//% 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;
|
function onPinReleased(name: TouchPin, body: () => void): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the button state (pressed or not) for ``A`` and ``B``.
|
* Get the button state (pressed or not) for ``A`` and ``B``.
|
||||||
* @param button the button to query the request, eg: Button.A
|
* @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"
|
//% block="button|%NAME|is pressed"
|
||||||
//% blockId=device_get_button2
|
//% blockId=device_get_button2
|
||||||
//% icon="\uf192" blockGap=8
|
//% icon="\uf192" blockGap=8
|
||||||
//% parts="buttonpair" shim=input::buttonIsPressed
|
//% parts="buttonpair"
|
||||||
|
//% group="States" shim=input::buttonIsPressed
|
||||||
function buttonIsPressed(button: Button): boolean;
|
function buttonIsPressed(button: Button): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the pin state (pressed or not). Requires to hold the ground to close the circuit.
|
* 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
|
* @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"
|
//% 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;
|
function pinIsPressed(name: TouchPin): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,33 +344,45 @@ declare namespace input {
|
|||||||
*/
|
*/
|
||||||
//% help=input/acceleration weight=58
|
//% help=input/acceleration weight=58
|
||||||
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
|
//% 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;
|
function acceleration(dimension: Dimension): int32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.
|
* 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
|
//% 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;
|
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.
|
* Get the current compass heading in degrees.
|
||||||
*/
|
*/
|
||||||
//% help=input/compass-heading
|
//% help=input/compass-heading
|
||||||
//% weight=56
|
//% weight=56
|
||||||
//% blockId=device_heading block="compass heading (°)" blockGap=8
|
//% blockId=device_heading block="compass heading (°)" blockGap=8
|
||||||
//% parts="compass" shim=input::compassHeading
|
//% parts="compass"
|
||||||
|
//% group="Sensors" shim=input::compassHeading
|
||||||
function compassHeading(): int32;
|
function compassHeading(): int32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the temperature in Celsius degrees (°C).
|
* Gets the temperature in Celsius degrees (°C).
|
||||||
*/
|
*/
|
||||||
//% weight=55
|
//% weight=57
|
||||||
//% help=input/temperature
|
//% help=input/temperature
|
||||||
//% blockId=device_temperature block="temperature (°C)" blockGap=8
|
//% blockId=device_temperature block="temperature (°C)" blockGap=8
|
||||||
//% parts="thermometer" shim=input::temperature
|
//% parts="thermometer"
|
||||||
|
//% group="Sensors" shim=input::temperature
|
||||||
function temperature(): int32;
|
function temperature(): int32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -333,17 +391,19 @@ declare namespace input {
|
|||||||
*/
|
*/
|
||||||
//% help=input/rotation weight=52
|
//% help=input/rotation weight=52
|
||||||
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8
|
//% 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;
|
function rotation(kind: Rotation): int32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
|
* 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
|
* @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
|
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8
|
||||||
//% parts="compass"
|
//% parts="compass"
|
||||||
//% advanced=true shim=input::magneticForce
|
//% advanced=true
|
||||||
|
//% group="Sensors" shim=input::magneticForce
|
||||||
function magneticForce(dimension: Dimension): number;
|
function magneticForce(dimension: Dimension): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -351,18 +411,49 @@ declare namespace input {
|
|||||||
*/
|
*/
|
||||||
//% help=input/calibrate-compass advanced=true
|
//% help=input/calibrate-compass advanced=true
|
||||||
//% blockId="input_compass_calibrate" block="calibrate compass"
|
//% blockId="input_compass_calibrate" block="calibrate compass"
|
||||||
//% weight=45 shim=input::calibrateCompass
|
//% weight=20 gap=8
|
||||||
|
//% group="Configuration" shim=input::calibrateCompass
|
||||||
function calibrateCompass(): void;
|
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.
|
* Sets the accelerometer sample range in gravities.
|
||||||
* @param range a value describe the maximum strengh of acceleration measured
|
* @param range a value describe the maximum strengh of acceleration measured
|
||||||
*/
|
*/
|
||||||
//% help=input/set-accelerometer-range
|
//% help=input/set-accelerometer-range
|
||||||
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range"
|
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range"
|
||||||
//% weight=5
|
//% weight=22 gap=8
|
||||||
//% parts="accelerometer"
|
//% parts="accelerometer"
|
||||||
//% advanced=true shim=input::setAccelerometerRange
|
//% advanced=true
|
||||||
|
//% group="Configuration" shim=input::setAccelerometerRange
|
||||||
function setAccelerometerRange(range: AcceleratorRange): void;
|
function setAccelerometerRange(range: AcceleratorRange): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,8 +501,9 @@ declare namespace control {
|
|||||||
* Blocks the current fiber for the given microseconds
|
* Blocks the current fiber for the given microseconds
|
||||||
* @param micros number of micro-seconds to wait. eg: 4
|
* @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" shim=control::waitMicros
|
//% blockId="control_wait_us" block="wait (µs)%micros"
|
||||||
|
//% micros.min=0 micros.max=6000 shim=control::waitMicros
|
||||||
function waitMicros(micros: int32): void;
|
function waitMicros(micros: int32): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -465,6 +557,13 @@ declare namespace control {
|
|||||||
//% advanced=true shim=control::deviceSerialNumber
|
//% advanced=true shim=control::deviceSerialNumber
|
||||||
function deviceSerialNumber(): int32;
|
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
|
* Informs simulator/runtime of a MIDI message
|
||||||
* Internal function to support the simulator.
|
* Internal function to support the simulator.
|
||||||
@ -476,7 +575,53 @@ declare namespace control {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
//% shim=control::__log
|
//% 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 \\%"
|
//% blockId=motor_on block="motor on at %percent \\%"
|
||||||
//% parts=dcmotor weight=90 blockGap=8
|
//% parts=dcmotor weight=90 blockGap=8
|
||||||
//% percent.shadow="speedPicker" shim=motors::motorPower
|
//% percent.shadow="speedPicker"
|
||||||
function motorPower(power: int32): void;
|
//% 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.
|
* 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 \\%"
|
//% blockId=block_dual_motor block="motor %motor|at %percent \\%"
|
||||||
//% percent.shadow="speedPicker"
|
//% percent.shadow="speedPicker"
|
||||||
//% weight=80 shim=motors::dualMotorPower
|
//% weight=80
|
||||||
function dualMotorPower(motor: Motor, duty_percent: int32): void;
|
//% duty_percent.defl=100 shim=motors::dualMotorPower
|
||||||
|
function dualMotorPower(motor: Motor, duty_percent?: int32): void;
|
||||||
}
|
}
|
||||||
declare namespace music {
|
declare namespace music {
|
||||||
|
|
||||||
@ -635,6 +782,31 @@ declare namespace music {
|
|||||||
//%
|
//%
|
||||||
//% parts="speaker" async useEnumVal=1 shim=music::speakerPlayTone
|
//% parts="speaker" async useEnumVal=1 shim=music::speakerPlayTone
|
||||||
function speakerPlayTone(frequency: int32, ms: int32): void;
|
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 {
|
declare namespace pins {
|
||||||
|
|
||||||
@ -763,7 +935,8 @@ declare namespace pins {
|
|||||||
//% blockId=device_analog_set_pitch_pin block="analog set pitch pin %name"
|
//% blockId=device_analog_set_pitch_pin block="analog set pitch pin %name"
|
||||||
//% help=pins/analog-set-pitch-pin weight=3 advanced=true
|
//% help=pins/analog-set-pitch-pin weight=3 advanced=true
|
||||||
//% name.fieldEditor="gridpicker" name.fieldOptions.columns=4
|
//% 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;
|
function analogSetPitchPin(name: AnalogPin): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -772,14 +945,16 @@ declare namespace pins {
|
|||||||
*/
|
*/
|
||||||
//% blockId=device_analog_set_pitch_volume block="analog set pitch volume $volume"
|
//% blockId=device_analog_set_pitch_volume block="analog set pitch volume $volume"
|
||||||
//% help=pins/analog-set-pitch-volume weight=3 advanced=true
|
//% 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;
|
function analogSetPitchVolume(volume: int32): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the volume the pitch pin from 0..255
|
* Gets the volume the pitch pin from 0..255
|
||||||
*/
|
*/
|
||||||
//% blockId=device_analog_pitch_volume block="analog pitch volume"
|
//% 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;
|
function analogPitchVolume(): int32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -788,7 +963,8 @@ declare namespace pins {
|
|||||||
* @param ms duration of the pitch in milli seconds.
|
* @param ms duration of the pitch in milli seconds.
|
||||||
*/
|
*/
|
||||||
//% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms"
|
//% 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;
|
function analogPitch(frequency: int32, ms: int32): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -821,6 +997,20 @@ declare namespace pins {
|
|||||||
//% shim=pins::createBuffer
|
//% shim=pins::createBuffer
|
||||||
function createBuffer(size: int32): Buffer;
|
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`.
|
* 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
|
//% help=pins/push-button advanced=true shim=pins::pushButton
|
||||||
function pushButton(pin: DigitalPin): void;
|
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;
|
function writeBuffer(buffer: Buffer): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read multiple characters from the receive buffer. Pause until enough characters are present.
|
* Read multiple characters from the receive buffer.
|
||||||
* @param length default buffer length, eg: 64
|
* If length is positive, pauses until enough characters are present.
|
||||||
|
* @param length default buffer length
|
||||||
*/
|
*/
|
||||||
//% blockId=serial_readbuffer block="serial|read buffer %length"
|
//% blockId=serial_readbuffer block="serial|read buffer %length"
|
||||||
//% help=serial/read-buffer advanced=true weight=5 shim=serial::readBuffer
|
//% help=serial/read-buffer advanced=true weight=5 shim=serial::readBuffer
|
||||||
@ -1105,15 +1308,63 @@ declare namespace control {
|
|||||||
//% deprecated=1 shim=control::createBufferFromUTF8
|
//% deprecated=1 shim=control::createBufferFromUTF8
|
||||||
function createBufferFromUTF8(str: string): Buffer;
|
function createBufferFromUTF8(str: string): Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to persistent storage functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare namespace storage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a key value pair in the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
//% weight=100 blockGap=16
|
||||||
|
//% block="Put into %key a value of %value as Int"
|
||||||
|
//% blockId=storage_put_value_int
|
||||||
|
//%
|
||||||
|
//% group="Put"
|
||||||
|
//% blockHidden=true value.defl=0 shim=storage::putValueInt
|
||||||
|
function putValueInt(key: string, value?: int32): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a key value pair from the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
*/
|
||||||
|
//% weight=100 blockGap=16
|
||||||
|
//% block="get number from %key"
|
||||||
|
//% blockId=storage_get_value_int
|
||||||
|
//% group="Get"
|
||||||
|
//% blockHidden=true shim=storage::getValueInt
|
||||||
|
function getValueInt(key: string): int32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a key value pair from the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
*/
|
||||||
|
//% weight=100 blockGap=16
|
||||||
|
//% block="remove %key"
|
||||||
|
//% blockId=storage_remove
|
||||||
|
//% group="Remove"
|
||||||
|
//% blockHidden=true shim=storage::remove
|
||||||
|
function remove(key: string): void;
|
||||||
|
}
|
||||||
declare namespace light {
|
declare namespace light {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a color buffer to a light strip
|
* Sends a color buffer to a light strip
|
||||||
**/
|
**/
|
||||||
//% advanced=true
|
//% advanced=true shim=light::sendWS2812Buffer
|
||||||
//% shim=light::sendWS2812Buffer
|
|
||||||
function sendWS2812Buffer(buf: Buffer, pin: int32): void;
|
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
|
* Sets the light mode of a pin
|
||||||
**/
|
**/
|
||||||
|
28
libs/core/soundexpressions.cpp
Normal 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
|
||||||
|
}
|
||||||
|
}
|
59
libs/core/soundexpressions.ts
Normal 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");
|
||||||
|
}
|
57
libs/core/storage.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "pxt.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to persistent storage functionality.
|
||||||
|
*/
|
||||||
|
namespace storage {
|
||||||
|
/**
|
||||||
|
* Saves a key value pair in the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
//% weight=100 blockGap=16
|
||||||
|
//% block="Put into %key a value of %value as Int"
|
||||||
|
//% blockId=storage_put_value_int
|
||||||
|
//% value.defl=0
|
||||||
|
//% group="Put"
|
||||||
|
//% blockHidden=true
|
||||||
|
void putValueInt(String key, int value) {
|
||||||
|
ManagedString managedKey = MSTR(key);
|
||||||
|
uBit.storage.put(managedKey, (uint8_t *)&value, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a key value pair from the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
*/
|
||||||
|
//% weight=100 blockGap=16
|
||||||
|
//% block="get number from %key"
|
||||||
|
//% blockId=storage_get_value_int
|
||||||
|
//% group="Get"
|
||||||
|
//% blockHidden=true
|
||||||
|
int getValueInt(String key) {
|
||||||
|
KeyValuePair* data = uBit.storage.get(MSTR(key));
|
||||||
|
int stored;
|
||||||
|
if(data == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
memcpy(&stored, data->value, sizeof(int));
|
||||||
|
delete data;
|
||||||
|
return stored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a key value pair from the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
*/
|
||||||
|
//% weight=100 blockGap=16
|
||||||
|
//% block="remove %key"
|
||||||
|
//% blockId=storage_remove
|
||||||
|
//% group="Remove"
|
||||||
|
//% blockHidden=true
|
||||||
|
void remove(String key) {
|
||||||
|
uBit.storage.remove(MSTR(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
68
libs/core/storage.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
enum StorageSlots {
|
||||||
|
//% block="Slot 1"
|
||||||
|
s1 = 0,
|
||||||
|
//% block="Slot 2"
|
||||||
|
s2 = 1,
|
||||||
|
//% block="Slot 3"
|
||||||
|
s3 = 2,
|
||||||
|
//% block="Slot 4"
|
||||||
|
s4 = 3,
|
||||||
|
//% block="Slot 5"
|
||||||
|
s5 = 4,
|
||||||
|
//% block="Slot 6"
|
||||||
|
s6 = 5,
|
||||||
|
//% block="Slot 7"
|
||||||
|
s7 = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
// let storagesStr = ['s1', 's2', 's3', 's4', 's5', 's6', 's7'];
|
||||||
|
let storagesInt = ['i1', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to persistent storage functionality.
|
||||||
|
*/
|
||||||
|
//% color=#FFBB00 weight=10 icon="\uf187"
|
||||||
|
//% advanced=true
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a key value pair in the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
//% weight=90 blockGap=16
|
||||||
|
//% block="Save into number %key a value of %value"
|
||||||
|
//% blockId=storage_put_number
|
||||||
|
//% group="Put"
|
||||||
|
export function putNumber(key: StorageSlots, value: number) : void {
|
||||||
|
let managedValue = Math.floor(value * 100);
|
||||||
|
putValueInt(storagesInt[key], managedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a key value pair from the non volatile storage as a number
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
*/
|
||||||
|
//% weight=70 blockGap=16
|
||||||
|
//% block="read from number %key"
|
||||||
|
//% blockId=storage_get_number
|
||||||
|
//% group="Get"
|
||||||
|
export function getNumber(key: StorageSlots) : number {
|
||||||
|
let value = getValueInt(storagesInt[key]);
|
||||||
|
return value / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the key from the non volatile storage
|
||||||
|
* @param key the key for accesing the value
|
||||||
|
*/
|
||||||
|
//% weight=50 blockGap=16
|
||||||
|
//% block="Clear number %key"
|
||||||
|
//% blockId=storage_remove_key_int
|
||||||
|
//% group="Remove"
|
||||||
|
export function removeKeyInt(key: StorageSlots) : void {
|
||||||
|
remove(storagesInt[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
53
libs/core/touchmode.cpp
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
"devices.ts"
|
"devices.ts"
|
||||||
],
|
],
|
||||||
"icon": "./static/packages/devices/icon.png",
|
"icon": "./static/packages/devices/icon.png",
|
||||||
|
"hidden": true,
|
||||||
"public": true,
|
"public": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core": "file:../core",
|
"core": "file:../core",
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
"input": "Events and data from sensors",
|
"input": "Events and data from sensors",
|
||||||
"input.onLoudSound": "Registers an event that runs when a loud sound is detected",
|
"input.onLoudSound": "Registers an event that runs when a loud sound is detected",
|
||||||
"input.setLoudSoundThreshold": "Sets the minimum threshold for a loud sound",
|
"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)"
|
||||||
}
|
}
|
@ -6,5 +6,6 @@
|
|||||||
"input.soundLevel|block": "sound level",
|
"input.soundLevel|block": "sound level",
|
||||||
"input|block": "input",
|
"input|block": "input",
|
||||||
"{id:category}Input": "Input",
|
"{id:category}Input": "Input",
|
||||||
"{id:group}More": "More"
|
"{id:group}More": "More",
|
||||||
|
"{id:group}Sensors": "Sensors"
|
||||||
}
|
}
|
8753
package-lock.json
generated
14
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-calliopemini",
|
"name": "pxt-calliopemini",
|
||||||
"version": "3.0.36",
|
"version": "4.0.18",
|
||||||
"description": "calliope mini target for Microsoft MakeCode (PXT)",
|
"description": "calliope mini target for Microsoft MakeCode (PXT)",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"JavaScript",
|
"JavaScript",
|
||||||
@ -33,19 +33,19 @@
|
|||||||
"docs/static/icons/favicon.ico"
|
"docs/static/icons/favicon.ico"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bluebird": "2.0.33",
|
|
||||||
"@types/marked": "0.3.0",
|
"@types/marked": "0.3.0",
|
||||||
"@types/node": "8.0.53",
|
"@types/node": "8.10.66",
|
||||||
"@types/react": "16.0.25",
|
"@types/react": "16.4.7",
|
||||||
"@types/react-dom": "16.0.3",
|
"@types/react-dom": "16.0.3",
|
||||||
"@types/web-bluetooth": "0.0.4",
|
"@types/web-bluetooth": "0.0.4",
|
||||||
"less": "2.7.3",
|
"less": "2.7.3",
|
||||||
"react": "16.8.3",
|
"react": "16.8.3",
|
||||||
|
"react-dom": "16.11.0",
|
||||||
"semantic-ui-less": "2.2.14",
|
"semantic-ui-less": "2.2.14",
|
||||||
"typescript": "^3.7.5"
|
"typescript": "4.2.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pxt-common-packages": "7.0.4",
|
"pxt-common-packages": "9.0.1",
|
||||||
"pxt-core": "6.0.24"
|
"pxt-core": "7.0.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
102
pxtarget.json
@ -42,10 +42,10 @@
|
|||||||
"gc": true,
|
"gc": true,
|
||||||
"imageRefTag": 9,
|
"imageRefTag": 9,
|
||||||
"shimRenames": {
|
"shimRenames": {
|
||||||
|
"sendBufferAsm": "light::sendWS2812Buffer"
|
||||||
},
|
},
|
||||||
"patches": {
|
"patches": {
|
||||||
"0.0.0 - 1.0.0": [
|
"0.0.0 - 1.0.0": [{
|
||||||
{
|
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"map": {
|
"map": {
|
||||||
"microbit": "core",
|
"microbit": "core",
|
||||||
@ -92,31 +92,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"0.0.0 - 1.4.12": [
|
"0.0.0 - 1.4.12": [{
|
||||||
{
|
|
||||||
"type": "api",
|
"type": "api",
|
||||||
"map": {
|
"map": {
|
||||||
"DisplayMode\\s*\\.\\s*BackAndWhite": "DisplayMode.BlackAndWhite"
|
"DisplayMode\\s*\\.\\s*BackAndWhite": "DisplayMode.BlackAndWhite"
|
||||||
}
|
}
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"hidSelectors": [
|
"hidSelectors": [{
|
||||||
{
|
|
||||||
"usagePage": "0xFF00",
|
"usagePage": "0xFF00",
|
||||||
"usageId": "0x0001",
|
"usageId": "0x0001",
|
||||||
"vid": "0x1366",
|
"vid": "0x1366",
|
||||||
"pid": "0x1025"
|
"pid": "0x1025"
|
||||||
}
|
}],
|
||||||
],
|
|
||||||
"webUSB": false,
|
"webUSB": false,
|
||||||
"useNewFunctions": true
|
"useNewFunctions": true
|
||||||
},
|
},
|
||||||
"compileService": {
|
"compileService": {
|
||||||
"yottaTarget": "calliope-mini-classic-gcc",
|
"yottaTarget": "calliope-mini-classic-gcc@https://github.com/calliope-mini/target-calliope-mini-classic-gcc#v1.2.3",
|
||||||
"yottaCorePackage": "microbit",
|
"yottaCorePackage": "microbit",
|
||||||
"githubCorePackage": "calliope-mini/microbit",
|
"githubCorePackage": "calliope-mini/microbit",
|
||||||
"gittag": "v2.2.0-rc6-calliope.rc3",
|
"gittag": "v2.2.0-rc6-calliope.rc3-iss0.3",
|
||||||
"serviceId": "calliope",
|
"serviceId": "calliope",
|
||||||
"dockerImage": "pext/yotta:latest"
|
"dockerImage": "pext/yotta:latest"
|
||||||
},
|
},
|
||||||
@ -132,8 +128,7 @@
|
|||||||
"continueBlock": true,
|
"continueBlock": true,
|
||||||
"functionsOptions": {
|
"functionsOptions": {
|
||||||
"useNewFunctions": true,
|
"useNewFunctions": true,
|
||||||
"extraFunctionEditorTypes": [
|
"extraFunctionEditorTypes": [{
|
||||||
{
|
|
||||||
"typeName": "game.LedSprite",
|
"typeName": "game.LedSprite",
|
||||||
"label": "LedSprite",
|
"label": "LedSprite",
|
||||||
"icon": "send",
|
"icon": "send",
|
||||||
@ -149,7 +144,8 @@
|
|||||||
},
|
},
|
||||||
"onStartColor": "#54C9C9",
|
"onStartColor": "#54C9C9",
|
||||||
"onStartNamespace": "basic",
|
"onStartNamespace": "basic",
|
||||||
"onStartWeight": 54
|
"onStartWeight": 60,
|
||||||
|
"onStartGroup": "Control"
|
||||||
},
|
},
|
||||||
"simulator": {
|
"simulator": {
|
||||||
"autoRun": true,
|
"autoRun": true,
|
||||||
@ -208,8 +204,8 @@
|
|||||||
"C15": "C_P15",
|
"C15": "C_P15",
|
||||||
"C19": "C_P19",
|
"C19": "C_P19",
|
||||||
"C20": "C_P20",
|
"C20": "C_P20",
|
||||||
"EXT_PWR":"EXT_PWR",
|
"EXT_PWR": "EXT_PWR",
|
||||||
"SPKR":"SPKR",
|
"SPKR": "SPKR",
|
||||||
"BTN_A": "BTN_A",
|
"BTN_A": "BTN_A",
|
||||||
"BTN_B": "BTN_B",
|
"BTN_B": "BTN_B",
|
||||||
"MOTOR1": "M_OUT1",
|
"MOTOR1": "M_OUT1",
|
||||||
@ -299,7 +295,14 @@
|
|||||||
"organizationUrl": "https://makecode.com/",
|
"organizationUrl": "https://makecode.com/",
|
||||||
"organizationLogo": "./static/Microsoft-logo_rgb_c-gray-square.png",
|
"organizationLogo": "./static/Microsoft-logo_rgb_c-gray-square.png",
|
||||||
"organizationWideLogo": "./static/Microsoft-logo_rgb_c-white.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/",
|
"homeUrl": "https://makecode.calliope.cc/",
|
||||||
"embedUrl": "https://makecode.calliope.cc/",
|
"embedUrl": "https://makecode.calliope.cc/",
|
||||||
"shareUrl": "https://makecode.calliope.cc/",
|
"shareUrl": "https://makecode.calliope.cc/",
|
||||||
@ -309,26 +312,27 @@
|
|||||||
"boardName": "Calliope mini",
|
"boardName": "Calliope mini",
|
||||||
"driveDisplayName": "MINI",
|
"driveDisplayName": "MINI",
|
||||||
"appStoreID": "1309545545",
|
"appStoreID": "1309545545",
|
||||||
"crowdinProject": "kindscript",
|
"crowdinProject": "makecode",
|
||||||
"extendEditor": true,
|
"extendEditor": true,
|
||||||
"extendFieldEditors": true,
|
"extendFieldEditors": true,
|
||||||
"enableTrace": true,
|
"enableTrace": true,
|
||||||
|
"ignoreDocsErrors": false,
|
||||||
|
"errorList": true,
|
||||||
|
"allowPackageExtensions": true,
|
||||||
|
"addNewTypeScriptFile": true,
|
||||||
"experiments": [
|
"experiments": [
|
||||||
"allowPackageExtensions",
|
"accessibleBlocks",
|
||||||
"instructions",
|
|
||||||
"debugExtensionCode",
|
"debugExtensionCode",
|
||||||
"bluetoothUartConsole",
|
"bluetoothUartConsole",
|
||||||
"bluetoothPartialFlashing",
|
"bluetoothPartialFlashing",
|
||||||
"simScreenshot",
|
"simScreenshot",
|
||||||
"simGif"
|
"simGif",
|
||||||
|
"blocksErrorList"
|
||||||
],
|
],
|
||||||
"bluetoothUartFilters": [
|
"bluetoothUartFilters": [{
|
||||||
{
|
|
||||||
"namePrefix": "Calliope mini"
|
"namePrefix": "Calliope mini"
|
||||||
}
|
}],
|
||||||
],
|
"docMenu": [{
|
||||||
"docMenu": [
|
|
||||||
{
|
|
||||||
"name": "Support",
|
"name": "Support",
|
||||||
"path": "https://calliope.cc/en/impressum"
|
"path": "https://calliope.cc/en/impressum"
|
||||||
},
|
},
|
||||||
@ -395,6 +399,7 @@
|
|||||||
"ar",
|
"ar",
|
||||||
"bg",
|
"bg",
|
||||||
"cs",
|
"cs",
|
||||||
|
"cy",
|
||||||
"da",
|
"da",
|
||||||
"de",
|
"de",
|
||||||
"el",
|
"el",
|
||||||
@ -416,6 +421,7 @@
|
|||||||
"ru",
|
"ru",
|
||||||
"si-LK",
|
"si-LK",
|
||||||
"sk",
|
"sk",
|
||||||
|
"sr",
|
||||||
"sv-SE",
|
"sv-SE",
|
||||||
"tr",
|
"tr",
|
||||||
"uk",
|
"uk",
|
||||||
@ -428,7 +434,8 @@
|
|||||||
"browserDbPrefixes": {
|
"browserDbPrefixes": {
|
||||||
"1": "v1",
|
"1": "v1",
|
||||||
"2": "v2",
|
"2": "v2",
|
||||||
"3": "v3"
|
"3": "v3",
|
||||||
|
"4": "v4"
|
||||||
},
|
},
|
||||||
"editorVersionPaths": {
|
"editorVersionPaths": {
|
||||||
"0": "v0"
|
"0": "v0"
|
||||||
@ -447,15 +454,46 @@
|
|||||||
"chooseLanguageRestrictionOnNewProject": true,
|
"chooseLanguageRestrictionOnNewProject": true,
|
||||||
"openProjectNewTab": true,
|
"openProjectNewTab": true,
|
||||||
"python": 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": {
|
"queryVariants": {
|
||||||
"hidemenu": {
|
"hidemenu": {
|
||||||
"appTheme": {
|
"appTheme": {
|
||||||
"hideMenuBar": true
|
"hideMenuBar": true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"androidapp": {
|
||||||
|
"compile": {
|
||||||
|
"webUSB": false
|
||||||
|
},
|
||||||
|
"appTheme": {
|
||||||
|
"disableBlobObjectDownload": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"uploadDocs": true,
|
"uploadDocs": true
|
||||||
"ignoreDocsErrors": true
|
|
||||||
}
|
}
|
@ -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">
|
<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" />
|
<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" />
|
<mp:PhoneIdentity PhoneProductId="5ddd542e-5ab4-48bc-b116-0782dc08ab97" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||||
|
7
sim/compat.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace pxsim {
|
||||||
|
export interface CommonBoard extends CoreBoard
|
||||||
|
, EventBusBoard {
|
||||||
|
bus: EventBus;
|
||||||
|
edgeConnectorState: EdgeConnectorState;
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
export class DalBoard extends CoreBoard
|
export class DalBoard extends CoreBoard
|
||||||
implements RadioBoard, LightBoard {
|
implements CommonBoard
|
||||||
|
, RadioBoard
|
||||||
|
, LightBoard
|
||||||
|
, MicrophoneBoard
|
||||||
|
, ControlMessageBoard {
|
||||||
// state & update logic for component services
|
// state & update logic for component services
|
||||||
ledMatrixState: LedMatrixState;
|
ledMatrixState: LedMatrixState;
|
||||||
edgeConnectorState: EdgeConnectorState;
|
edgeConnectorState: EdgeConnectorState;
|
||||||
@ -20,17 +24,24 @@ namespace pxsim {
|
|||||||
rgbLedState: number;
|
rgbLedState: number;
|
||||||
speakerState: SpeakerState;
|
speakerState: SpeakerState;
|
||||||
fileSystem: FileSystemState;
|
fileSystem: FileSystemState;
|
||||||
|
logoTouch: Button;
|
||||||
|
speakerEnabled: boolean = true;
|
||||||
|
controlMessageState: ControlMessageState;
|
||||||
|
|
||||||
// visual
|
// visual
|
||||||
viewHost: visuals.BoardHost;
|
viewHost: visuals.BoardHost;
|
||||||
view: SVGElement;
|
view: SVGElement;
|
||||||
|
|
||||||
|
// board hardware version
|
||||||
|
hardwareVersion = 1;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
// components
|
// components
|
||||||
this.lightState = {};
|
this.lightState = {};
|
||||||
this.fileSystem = new FileSystemState();
|
this.fileSystem = new FileSystemState();
|
||||||
|
this.controlMessageState = new ControlMessageState(this);
|
||||||
this.builtinParts["ledmatrix"] = this.ledMatrixState = new LedMatrixState(runtime);
|
this.builtinParts["ledmatrix"] = this.ledMatrixState = new LedMatrixState(runtime);
|
||||||
this.builtinParts["buttonpair"] = this.buttonPairState = new ButtonPairState({
|
this.builtinParts["buttonpair"] = this.buttonPairState = new ButtonPairState({
|
||||||
ID_BUTTON_A: DAL.MICROBIT_ID_BUTTON_A,
|
ID_BUTTON_A: DAL.MICROBIT_ID_BUTTON_A,
|
||||||
@ -41,8 +52,10 @@ namespace pxsim {
|
|||||||
});
|
});
|
||||||
this.builtinParts["edgeconnector"] = this.edgeConnectorState = new EdgeConnectorState({
|
this.builtinParts["edgeconnector"] = this.edgeConnectorState = new EdgeConnectorState({
|
||||||
pins: [
|
pins: [
|
||||||
|
DAL.MICROBIT_ID_IO_P12,
|
||||||
DAL.MICROBIT_ID_IO_P0,
|
DAL.MICROBIT_ID_IO_P0,
|
||||||
DAL.MICROBIT_ID_IO_P1,
|
DAL.MICROBIT_ID_IO_P1,
|
||||||
|
DAL.MICROBIT_ID_IO_P16,
|
||||||
DAL.MICROBIT_ID_IO_P2,
|
DAL.MICROBIT_ID_IO_P2,
|
||||||
DAL.MICROBIT_ID_IO_P3,
|
DAL.MICROBIT_ID_IO_P3,
|
||||||
DAL.MICROBIT_ID_IO_P4,
|
DAL.MICROBIT_ID_IO_P4,
|
||||||
@ -53,11 +66,9 @@ namespace pxsim {
|
|||||||
DAL.MICROBIT_ID_IO_P9,
|
DAL.MICROBIT_ID_IO_P9,
|
||||||
DAL.MICROBIT_ID_IO_P10,
|
DAL.MICROBIT_ID_IO_P10,
|
||||||
DAL.MICROBIT_ID_IO_P11,
|
DAL.MICROBIT_ID_IO_P11,
|
||||||
DAL.MICROBIT_ID_IO_P12,
|
|
||||||
DAL.MICROBIT_ID_IO_P13,
|
DAL.MICROBIT_ID_IO_P13,
|
||||||
DAL.MICROBIT_ID_IO_P14,
|
DAL.MICROBIT_ID_IO_P14,
|
||||||
DAL.MICROBIT_ID_IO_P15,
|
DAL.MICROBIT_ID_IO_P15,
|
||||||
DAL.MICROBIT_ID_IO_P16,
|
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
DAL.MICROBIT_ID_IO_P19,
|
DAL.MICROBIT_ID_IO_P19,
|
||||||
@ -71,13 +82,13 @@ namespace pxsim {
|
|||||||
"P3": DAL.MICROBIT_ID_IO_P16
|
"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,
|
ID_RADIO: DAL.MICROBIT_ID_RADIO,
|
||||||
RADIO_EVT_DATAGRAM: DAL.MICROBIT_RADIO_EVT_DATAGRAM
|
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["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["thermometer"] = this.thermometerState = new ThermometerState();
|
||||||
this.builtinParts["lightsensor"] = this.lightSensorState = new LightSensorState();
|
this.builtinParts["lightsensor"] = this.lightSensorState = new LightSensorState();
|
||||||
this.builtinParts["compass"] = this.compassState = new CompassState();
|
this.builtinParts["compass"] = this.compassState = new CompassState();
|
||||||
@ -97,24 +108,13 @@ namespace pxsim {
|
|||||||
this.builtinPartVisuals["microservo"] = (xy: visuals.Coord) => visuals.mkMicroServoPart(xy);
|
this.builtinPartVisuals["microservo"] = (xy: visuals.Coord) => visuals.mkMicroServoPart(xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveMessage(msg: SimulatorMessage) {
|
ensureHardwareVersion(version: number) {
|
||||||
if (!runtime || runtime.dead) return;
|
if (version > this.hardwareVersion) {
|
||||||
|
this.hardwareVersion = version;
|
||||||
|
this.updateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initAsync(msg: SimulatorRunMessage): Promise<void> {
|
initAsync(msg: SimulatorRunMessage): Promise<void> {
|
||||||
super.initAsync(msg);
|
super.initAsync(msg);
|
||||||
@ -124,6 +124,21 @@ namespace pxsim {
|
|||||||
const cmpDefs = msg.partDefinitions || {};
|
const cmpDefs = msg.partDefinitions || {};
|
||||||
const fnArgs = msg.fnArgs;
|
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 = {
|
const opts: visuals.BoardHostOpts = {
|
||||||
state: this,
|
state: this,
|
||||||
boardDef: boardDef,
|
boardDef: boardDef,
|
||||||
@ -134,6 +149,7 @@ namespace pxsim {
|
|||||||
maxHeight: "100%",
|
maxHeight: "100%",
|
||||||
highContrast: msg.highContrast
|
highContrast: msg.highContrast
|
||||||
};
|
};
|
||||||
|
|
||||||
this.viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({
|
this.viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({
|
||||||
visual: boardDef.visual,
|
visual: boardDef.visual,
|
||||||
boardDef: boardDef,
|
boardDef: boardDef,
|
||||||
|
1
sim/public/icons/jacdac.svg
Normal 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 |
@ -1,9 +1,19 @@
|
|||||||
CACHE MANIFEST
|
CACHE MANIFEST
|
||||||
|
|
||||||
CACHE:
|
CACHE:
|
||||||
/cdn/bluebird.min.js
|
|
||||||
/cdn/pxtsim.js
|
/cdn/pxtsim.js
|
||||||
/sim/sim.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:
|
NETWORK:
|
||||||
*
|
*
|
||||||
|
@ -19,10 +19,22 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="/cdn/bluebird.min.js"></script>
|
|
||||||
<script src="/cdn/pxtsim.js"></script>
|
<script src="/cdn/pxtsim.js"></script>
|
||||||
<script src="/sim/sim.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>
|
||||||
</body>
|
</body>
|
||||||
|