Compare commits

...

106 Commits

Author SHA1 Message Date
e95d29286a 0.7.5 2016-12-22 23:12:46 -08:00
14d50810cb Bump pxt-core to 0.7.9 2016-12-22 23:12:43 -08:00
250e21b5c9 fixed toolbox color 2016-12-22 22:41:13 -08:00
98eab3672f updated css breakpoints 2016-12-22 22:36:06 -08:00
360e2b7ba6 0.7.4 2016-12-22 21:14:29 -08:00
f255e1a903 Bump pxt-core to 0.7.8 2016-12-22 21:14:27 -08:00
d4762cc5b5 deploy 0.7.3 to web 2016-12-22 10:05:52 +01:00
749b5266cb 0.7.3 2016-12-20 16:30:40 -08:00
bbd23f6d26 Bump pxt-core to 0.7.5 2016-12-20 16:30:38 -08:00
4bef7d50bd 0.7.2 2016-12-16 15:01:13 -08:00
bf423ca037 Bump pxt-core to 0.6.4 2016-12-16 15:01:05 -08:00
7556796eb6 merging more memory fixes 2016-12-16 14:57:16 -08:00
0a380a70d1 0.7.1 2016-12-16 07:26:11 -08:00
5c57e0faa4 fixing ver issues 2016-12-16 07:26:01 -08:00
41abeb62c3 0.6.2 2016-12-16 07:25:07 -08:00
b6eeeef4d5 0.6.1 2016-12-16 07:24:44 -08:00
b5b7edb978 moved to 0.6 2016-12-16 07:24:36 -08:00
a65fe1343c 0.5.98 2016-12-16 07:23:54 -08:00
3165fb3749 Bump pxt-core to 0.6.2 2016-12-16 07:23:48 -08:00
2789887f3b 0.5.97 2016-12-09 15:02:44 -08:00
d230fdd2fb Bump pxt-core to 0.5.99 2016-12-09 15:02:40 -08:00
88c9ef5b22 deploy feature now implemented in PXT 2016-12-08 21:11:50 -08:00
154115cc66 0.5.96 2016-12-08 16:38:10 -08:00
145dbaeb8f Merge pull request #8 from Microsoft/coreupdate
merging runtime memory leaks
2016-12-08 16:37:48 -08:00
1c8ceaef17 merging runtime memory leaks 2016-12-08 16:29:53 -08:00
e30c6f7149 0.5.95 2016-12-08 14:24:14 -08:00
e69174ed0f Bump pxt-core to 0.5.96 2016-12-08 14:24:09 -08:00
303d37ac9b toolbox buttons for tablet mode 2016-12-06 16:16:50 -08:00
69e2b41c40 Supporting new blockly toolbox buttons 2016-12-06 15:29:53 -08:00
8f04c8c20a 0.5.94 2016-12-02 12:59:04 -08:00
7661df09c8 Bump pxt-core to 0.5.87 2016-12-02 12:59:02 -08:00
62cbacc8ba theming the add package button 2016-12-01 23:53:38 -08:00
a9fd336093 Using white organisation logo for wide logo 2016-12-01 23:46:53 -08:00
d800f5fcb9 0.5.93 2016-11-30 15:21:10 -08:00
29e6f51798 Bump pxt-core to 0.5.85 2016-11-30 15:21:08 -08:00
ffb671d6b1 0.5.92 2016-11-30 03:33:14 -08:00
8eb4200b46 Bump pxt-core to 0.5.84 2016-11-30 03:33:08 -08:00
dfc7a1ddb9 nicer simulator animation 2016-11-30 03:32:53 -08:00
5e2ea5056b Merge pull request #7 from Microsoft/coregone
pxt-calliope-core gone
2016-11-30 03:16:44 -08:00
c417f0ed93 using microbit service 2016-11-29 22:17:51 -08:00
ce85907019 removing ksbit.h file 2016-11-29 21:55:37 -08:00
8cf0984a3f removing dependency on pxt-calliope-core 2016-11-29 21:51:14 -08:00
8eb1b98cd4 0.5.91 2016-11-29 00:19:49 -08:00
53f55c031c restoring microsoft 2016-11-29 00:12:00 -08:00
61b1150b8f 0.5.90 2016-11-29 00:06:17 -08:00
f574b91098 Bump pxt-core to 0.5.81 2016-11-29 00:06:16 -08:00
4a52f93367 updated cmds build options 2016-11-29 00:06:09 -08:00
fd0193e983 Updating with the MIT license text and contributing guideline 2016-11-28 17:14:09 -08:00
566326ea17 Fixing scrollimage for calliope 2016-11-17 10:14:12 -08:00
d7e1ec41b8 Setting blockly toolbox top / bottom radius in css after recent change. Setting loading to pulsar. 2016-11-16 21:17:00 -08:00
620297b95e update master, fixes sound bug 2016-11-16 07:53:56 +01:00
e9862751ba 0.5.89 2016-11-15 22:35:12 -08:00
5df83bb079 quick style fix 2016-11-15 22:35:02 -08:00
903c0ec6bd fixing music simulator 2016-11-15 22:28:05 -08:00
4be57eee9a 0.5.88 2016-11-15 20:10:37 -08:00
89a2178ff5 Bump pxt-core to 0.5.75 2016-11-15 20:10:35 -08:00
b3ffabba41 updated translations 2016-11-14 11:25:27 -08:00
c98e65a68c bumped to 0.5.87 2016-11-14 10:36:18 -08:00
2c70784251 0.5.87 2016-11-14 10:26:42 -08:00
00333b0257 Bump pxt-core to 0.5.74 2016-11-14 10:26:40 -08:00
d01c801f63 updated mutable block 2016-11-14 10:25:26 -08:00
05828ddcd9 0.5.86 2016-11-14 10:21:59 -08:00
f473835604 updated serial tranlsations 2016-11-14 10:06:39 -08:00
d82da1f877 updated localizations 2016-11-14 09:44:46 -08:00
94706adc40 0.5.85 2016-11-14 06:10:19 -08:00
79fb4e4ff7 fix missing radio strings 2016-11-14 06:07:19 -08:00
dae84afded add SPI pins 2016-11-14 10:12:35 +01:00
82d93a2b91 0.5.84 2016-11-13 22:10:34 +01:00
45cbbd342b fix naming 2016-11-13 22:09:57 +01:00
5c7779927c bumped to v0.5.83 2016-11-12 05:42:44 -08:00
df3d3b41ab 0.5.83 2016-11-12 05:21:03 -08:00
d691ebfd52 updated strings 2016-11-12 05:20:39 -08:00
a7bd9f6708 0.5.82 2016-11-11 15:25:33 -08:00
c3d3747cd8 Bump pxt-core to 0.5.72 2016-11-11 15:25:31 -08:00
7bc5488f25 updated translations 2016-11-11 15:25:18 -08:00
f27aa28f8e updated translations 2016-11-11 13:27:53 -08:00
12ccf21e28 adding missing strings 2016-11-11 10:56:45 -08:00
c557929fb2 0.5.81 2016-11-11 17:08:39 +01:00
2e58a31b07 update dependencies for motor fix in DAL 2016-11-11 17:01:53 +01:00
081a56550d 0.5.80 2016-11-11 06:49:28 -08:00
3d665d5505 Bump pxt-core to 0.5.68 2016-11-11 06:49:26 -08:00
f991733e04 0.5.79 2016-11-10 15:07:53 -08:00
020b7e9bbe Bump pxt-core to 0.5.67 2016-11-10 15:07:51 -08:00
f3bf46f691 0.5.78 2016-11-10 14:25:36 -08:00
c3bb56da0c 0.5.77 2016-11-10 14:22:00 -08:00
1f98257984 added missing files for pxtrequire 2016-11-10 14:15:55 -08:00
1cec654342 0.5.76 2016-11-10 14:01:30 -08:00
bb027ec75a Bump pxt-core to 0.5.66 2016-11-10 14:01:27 -08:00
ceeb366be5 removing outdated tests 2016-11-10 13:14:19 -08:00
d6cc95112c AnalogPin.P0 not supported 2016-11-10 13:08:45 -08:00
ce24e9d923 0.5.75 2016-11-10 21:22:25 +01:00
7ee5b4112b remove undefined pins 2016-11-10 21:20:48 +01:00
d903901de2 Merge branch 'pin-update' 2016-11-10 21:05:31 +01:00
c1025b8658 fix naming and pin selection 2016-11-10 21:00:03 +01:00
cdb9682a8b intermediate fix for accelerometer used in pxt 2016-11-10 20:45:40 +01:00
9d589971f5 0.5.74 2016-11-10 11:33:48 -08:00
c6807d67d8 0.5.73 2016-11-10 11:31:21 -08:00
05ff9282ac Bump pxt-core to 0.5.65 2016-11-10 11:31:19 -08:00
2825d09eae 0.5.72 2016-11-10 10:11:16 -08:00
15d4a594ae adding hover style on categories 2016-11-10 10:10:03 -08:00
a0b426bdf0 disable simulator crash, disable parts 2016-11-10 10:06:38 -08:00
580f1bf24e 0.5.71 2016-11-10 09:35:40 -08:00
29cc6eaded Bump pxt-core to 0.5.64 2016-11-10 09:35:36 -08:00
6671d1864c updated dal.d.ts 2016-11-10 09:13:25 -08:00
42d21dea28 fix pin name for SDA 2016-11-10 15:30:49 +01:00
c4e427c090 fix pins to be in sync with the naming in the simulator and on the board 2016-11-10 15:11:12 +01:00
70 changed files with 2381 additions and 3756 deletions

26
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,26 @@
# Contributing Code
PXT accepts bug fix pull requests. For a bug fix PR to be accepted, it must first have a tracking issue that has been marked approved. Your PR should link to the bug you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
PXT also accepts new feature pull requests. For a feature-level PR to be accepted, it first needs to have design discussion. Design discussion can take one of two forms a) a feature request in the issue tracker that has been marked as approved or b) the PR must be accompanied by a full design spec and this spec is later approved in the open design discussion. Features are evaluated against their complexity, impact on other features, roadmap alignment, and maintainability.
These two blogs posts on contributing code to open source projects are a good reference: [Open Source Contribution Etiquette](http://tirania.org/blog/archive/2010/Dec-31.html) by Miguel de Icaza and [Don't "Push" Your Pull Requests](https://www.igvita.com/2011/12/19/dont-push-your-pull-requests/) by Ilya Grigorik.
## Security
If you believe you have found a security issue in PXT, please share it with us privately following the guidance at the Microsoft [Security TechCenter](https://technet.microsoft.com/en-us/security/ff852094). Reporting it via this channel helps minimize risk to projects built with PXT.
## Legal
You will need to complete a Contributor License Agreement (CLA) before your pull request can be accepted. This agreement testifies that you are granting us permission to use the source code you are submitting, and that this work is being submitted under appropriate license that we can use it.
You can complete the CLA by going through the steps at https://cla.microsoft.com. Once we have received the signed CLA, we'll review the request. You will only need to do this once.
## Housekeeping
Your pull request should:
* Include a description of what your change intends to do
* Be a child commit of a reasonably recent commit in the master branch
* Pass all unit tests
* Have a clear commit message
* Include adequate tests

25
LICENSE.txt Normal file
View File

@ -0,0 +1,25 @@
PXT - Programming Experience Toolkit
The MIT License (MIT)
Copyright (c) Microsoft Corporation
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,59 +0,0 @@
/// <reference path="../node_modules/pxt-core/built/pxt.d.ts"/>
import * as fs from "fs";
import * as path from "path";
import * as child_process from "child_process";
let writeFileAsync: any = Promise.promisify(fs.writeFile)
let execAsync: (cmd: string, options?: { cwd?: string }) => Promise<Buffer> = Promise.promisify(child_process.exec)
let readDirAsync = Promise.promisify(fs.readdir)
export function deployCoreAsync(res: ts.pxtc.CompileResult) {
return getBitDrivesAsync()
.then(drives => {
if (drives.length == 0) {
console.log("cannot find any drives to deploy to");
return Promise.resolve(0);
}
console.log(`copy ${ts.pxtc.BINARY_HEX} to ` + drives.join(", "));
let writeHexFile = (filename: string) => {
return writeFileAsync(filename + ts.pxtc.BINARY_HEX, res.outfiles[ts.pxtc.BINARY_HEX])
.then(() => console.log("wrote hex file to " + filename));
};
return Promise.map(drives, d => writeHexFile(d))
.then(() => drives.length);
});
}
function getBitDrivesAsync(): Promise<string[]> {
if (process.platform == "win32") {
const rx = new RegExp("^([A-Z]:).* " + pxt.appTarget.compile.deployDrives)
return execAsync("wmic PATH Win32_LogicalDisk get DeviceID, VolumeName, FileSystem")
.then(buf => {
let res: string[] = []
buf.toString("utf8").split(/\n/).forEach(ln => {
let m = rx.exec(ln)
if (m) {
res.push(m[1] + "/")
}
})
return res
})
}
else if (process.platform == "darwin") {
const rx = new RegExp(pxt.appTarget.compile.deployDrives)
return readDirAsync("/Volumes")
.then(lst => lst.filter(s => rx.test(s)).map(s => "/Volumes/" + s + "/"))
} else if (process.platform == "linux") {
const rx = new RegExp(pxt.appTarget.compile.deployDrives)
const user = process.env["USER"]
return readDirAsync(`/media/${user}`)
.then(lst => lst.filter(s => rx.test(s)).map(s => `/media/${user}/${s}/`))
} else {
return Promise.resolve([])
}
}

7
cmds/pxtrequire.ts Normal file
View File

@ -0,0 +1,7 @@
/// <reference path="../node_modules/pxt-core/typings/node/node.d.ts"/>
/// <reference path="../node_modules/pxt-core/built/pxtlib.d.ts" />
import * as path from "path";
export let pxtCore = require("pxt-core");
// require.resolve() gives path to [pxt dir]/built/pxt.js, so move up twice to get pxt root dir
export let pxtCoreDir = path.resolve(require.resolve("pxt-core"), "..", "..");

View File

@ -1,3 +1,3 @@
{
"appref": "v0.5.63"
"appref": "v0.7.3"
}

View File

@ -5,23 +5,23 @@ Control currents in Pins for analog/digital signals, servos, i2c, ...
```cards
pins.digitalReadPin(DigitalPin.P0);
pins.digitalWritePin(DigitalPin.P0, 0);
pins.analogReadPin(AnalogPin.P0);
pins.analogWritePin(AnalogPin.P0, 1023);
pins.analogSetPeriod(AnalogPin.P0, 20000);
pins.analogReadPin(AnalogPin.P1);
pins.analogWritePin(AnalogPin.P1, 1023);
pins.analogSetPeriod(AnalogPin.P1, 20000);
pins.map(0, 0, 1023, 0, 4);
pins.onPulsed(DigitalPin.P0, PulseValue.High, () => {
});
pins.pulseDuration();
pins.pulseIn(DigitalPin.P0, PulseValue.High);
pins.servoWritePin(AnalogPin.P0, 180);
pins.servoSetPulse(AnalogPin.P0, 1500);
pins.servoWritePin(AnalogPin.P1, 180);
pins.servoSetPulse(AnalogPin.P1, 1500);
pins.i2cReadNumber(0, NumberFormat.Int8LE);
pins.i2cWriteNumber(0, 0, NumberFormat.Int8LE);
pins.spiWrite(0);
pins.setPull(DigitalPin.P0, PinPullMode.PullDown);
pins.analogPitch(0, 0);
pins.analogSetPitchPin(AnalogPin.P0);
pins.analogSetPitchPin(AnalogPin.P1);
```
### See Also

View File

@ -4,7 +4,7 @@ Read an **analog** signal (`0` through `1023`) from the
[pin](/device/pins) you say.
```sig
pins.analogReadPin(AnalogPin.P0)
pins.analogReadPin(AnalogPin.P1)
```
### Parameters

View File

@ -5,7 +5,7 @@ analog [pin](/device/pins).
Before you call this function, you should set the specified pin as analog.
```sig
pins.analogSetPeriod(AnalogPin.P0, 20000)
pins.analogSetPeriod(AnalogPin.P1, 20000)
```
### Parameters
@ -17,8 +17,8 @@ The following code first sets `P0` to analog with **analog write
pin**, and then sets the PWM period of `P0` to 20,000 microseconds.
```blocks
pins.analogWritePin(AnalogPin.P0, 512)
pins.analogSetPeriod(AnalogPin.P0, 20000)
pins.analogWritePin(AnalogPin.P1, 512)
pins.analogSetPeriod(AnalogPin.P1, 20000)
```
### See also

View File

@ -3,7 +3,7 @@
Specify which [pin](/device/pins) (P0, P1, P2) is used to generate tones.
```sig
pins.analogSetPitchPin(AnalogPin.P0)
pins.analogSetPitchPin(AnalogPin.P1)
```
### Parameters
@ -13,7 +13,7 @@ pins.analogSetPitchPin(AnalogPin.P0)
### Example
```blocks
pins.analogSetPitchPin(AnalogPin.P0)
pins.analogSetPitchPin(AnalogPin.P1)
let frequency = 440
let duration = 1000
pins.analogPitch(frequency, duration)

View File

@ -4,7 +4,7 @@ Write an **analog** signal (`0` through `1023`) to the
[pin](/device/pins) you say.
```sig
pins.analogWritePin(AnalogPin.P0, 400)
pins.analogWritePin(AnalogPin.P1, 400)
```
### Parameters
@ -17,7 +17,7 @@ pins.analogWritePin(AnalogPin.P0, 400)
This program writes `1023` to pin `P0`.
```blocks
pins.analogWritePin(AnalogPin.P0, 1023)
pins.analogWritePin(AnalogPin.P1, 1023)
```
#### ~hint

View File

@ -28,7 +28,7 @@ This example maps the value read from the analog pin `P0` to an LED
coordinate between `0` and `4`.
```blocks
let value1 = pins.analogReadPin(AnalogPin.P0)
let value1 = pins.analogReadPin(AnalogPin.P1)
let index = pins.map(value1, 0, 1023, 0, 4)
led.plot(0, index)
```

View File

@ -17,7 +17,7 @@ pins.servoSetPulse(AnalogPin.P1, 1500)
The following code sets the servo pulse to `1000` microseconds.
```blocks
pins.servoSetPulse(AnalogPin.P0, 1000)
pins.servoSetPulse(AnalogPin.P1, 1000)
```
### See also

View File

@ -9,7 +9,7 @@ full speed in one direction, `180` specifies full speed in the other,
and approximately `90` specifies no movement.)
```sig
pins.servoWritePin(AnalogPin.P0, 180)
pins.servoWritePin(AnalogPin.P1, 180)
```
### Parameters
@ -22,7 +22,7 @@ pins.servoWritePin(AnalogPin.P0, 180)
#### Setting the shaft angle to midpoint on a servo
```blocks
pins.servoWritePin(AnalogPin.P0, 90)
pins.servoWritePin(AnalogPin.P1, 90)
```
#### Controlling the shaft by using the tilt information of the accelerometer
@ -32,14 +32,14 @@ basic.forever(() => {
let millig = input.acceleration(Dimension.X)
// map accelerometer readings to angle
let angle = pins.map(millig, -1023, 1023, 0, 180)
pins.servoWritePin(AnalogPin.P0, angle)
pins.servoWritePin(AnalogPin.P1, angle)
})
```
#### Setting the full speed on a continuous servo
```blocks
pins.servoWritePin(AnalogPin.P0, 0)
pins.servoWritePin(AnalogPin.P1, 0)
```
### See also

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -33,7 +33,7 @@
"pictureAspect": "noChange",
"themeColor": "#ffffff",
"manifest": {
"name": "Calliope MINI",
"name": "Calliope mini",
"display": "standalone",
"orientation": "notSet",
"onConflict": "override",

View File

@ -1,5 +1,5 @@
{
"name": "Calliope MINI",
"name": "Calliope mini",
"icons": [
{
"src": "\/android-chrome-36x36.png",

View File

@ -1,5 +1,5 @@
{
"bluetooth": "Support for additional Bluetooth services.",
"bluetooth": "Support for additional Bluetooth services.\n\nSupport for additional Bluetooth services.",
"bluetooth.onBluetoothConnected": "Register code to run when the micro:bit is connected to over Bluetooth",
"bluetooth.onBluetoothConnected|param|body": "Code to run when a Bluetooth connection is established",
"bluetooth.onBluetoothDisconnected": "Register code to run when a bluetooth connection to the micro:bit is lost",

View File

@ -0,0 +1,6 @@
{
"bluetooth.uartWriteNumber": "Gibt einen numerischen Wert an die serielle",
"bluetooth.uartWriteValue": "Schreibt ein ``Namen: Wert`` Wertepaar auf die serielle Schnittstelle.",
"bluetooth.uartWriteValue|param|name": "Name des Wertestreams, z.B.: x",
"bluetooth.uartWriteValue|param|value": "Schreiben"
}

View File

@ -6,7 +6,8 @@
"enums.d.ts",
"shims.d.ts",
"bluetooth.ts",
"bluetooth.cpp"
"bluetooth.cpp",
"_locales/de/bluetooth-jsdoc-strings.json"
],
"public": true,
"dependencies": {

373
libs/core/ManagedBuffer.cpp Normal file
View File

@ -0,0 +1,373 @@
#include "MicroBit.h"
#include "ManagedBuffer.h"
#include <limits.h>
static const char empty[] __attribute__ ((aligned (4))) = "\xff\xff\0\0\0";
/**
* Internal constructor helper.
* Configures this ManagedBuffer to refer to the static empty buffer.
*/
void ManagedBuffer::initEmpty()
{
ptr = (BufferData*)(void*)empty;
}
/**
* Default Constructor.
* Creates an empty ManagedBuffer.
*
* Example:
* @code
* ManagedBuffer p();
* @endcode
*/
ManagedBuffer::ManagedBuffer()
{
initEmpty();
}
/**
* Constructor.
* Creates an empty ManagedBuffer of the given size.
*
* @param length The length of the buffer to create.
*
* Example:
* @code
* ManagedBuffer p(16); // Creates a ManagedBuffer 16 bytes long.
* @endcode
*/
ManagedBuffer::ManagedBuffer(int length)
{
this->init(NULL, length);
}
/**
* Constructor.
* Creates a new ManagedBuffer of the given size,
* and fills it with the data provided.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
* Example:
* @code
* uint8_t buf = {13,5,2};
* ManagedBuffer p(buf, 3); // Creates a ManagedBuffer 3 bytes long.
* @endcode
*/
ManagedBuffer::ManagedBuffer(uint8_t *data, int length)
{
this->init(data, length);
}
/**
* Copy Constructor.
* Add ourselves as a reference to an existing ManagedBuffer.
*
* @param buffer The ManagedBuffer to reference.
*
* Example:
* @code
* ManagedBuffer p();
* ManagedBuffer p2(i); // Refers to the same buffer as p.
* @endcode
*/
ManagedBuffer::ManagedBuffer(const ManagedBuffer &buffer)
{
ptr = buffer.ptr;
ptr->incr();
}
/**
* Constructor.
* Create a buffer from a raw BufferData pointer. It will ptr->incr(). This is to be used by specialized runtimes.
*
* @param p The pointer to use.
*/
ManagedBuffer::ManagedBuffer(BufferData *p)
{
ptr = p;
ptr->incr();
}
/**
* Internal constructor-initialiser.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
*/
void ManagedBuffer::init(uint8_t *data, int length)
{
if (length <= 0) {
initEmpty();
return;
}
ptr = (BufferData *) malloc(sizeof(BufferData) + length);
ptr->init();
ptr->length = length;
// Copy in the data buffer, if provided.
if (data)
memcpy(ptr->payload, data, length);
else
memset(ptr->payload, 0, length);
}
/**
* Destructor.
* Removes buffer resources held by the instance.
*/
ManagedBuffer::~ManagedBuffer()
{
ptr->decr();
}
/**
* Copy assign operation.
*
* Called when one ManagedBuffer is assigned the value of another using the '=' operator.
* Decrements our reference count and free up the buffer as necessary.
* Then, update our buffer to refer to that of the supplied ManagedBuffer,
* and increase its reference count.
*
* @param p The ManagedBuffer to reference.
*
* Example:
* @code
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* p1 = p2;
* @endcode
*/
ManagedBuffer& ManagedBuffer::operator = (const ManagedBuffer &p)
{
if(ptr == p.ptr)
return *this;
ptr->decr();
ptr = p.ptr;
ptr->incr();
return *this;
}
/**
* Equality operation.
*
* Called when one ManagedBuffer is tested to be equal to another using the '==' operator.
*
* @param p The ManagedBuffer to test ourselves against.
* @return true if this ManagedBuffer is identical to the one supplied, false otherwise.
*
* Example:
* @code
*
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* if(p1 == p2) // will be true
* uBit.display.scroll("same!");
* @endcode
*/
bool ManagedBuffer::operator== (const ManagedBuffer& p)
{
if (ptr == p.ptr)
return true;
else
return (ptr->length == p.ptr->length && (memcmp(ptr->payload, p.ptr->payload, ptr->length)==0));
}
/**
* Sets the byte at the given index to value provided.
* @param position The index of the byte to change.
* @param value The new value of the byte (0-255).
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the firts byte in the buffer to the value 255.
* @endcode
*/
int ManagedBuffer::setByte(int position, uint8_t value)
{
if (0 <= position && position < ptr->length)
{
ptr->payload[position] = value;
return MICROBIT_OK;
}
else
{
return MICROBIT_INVALID_PARAMETER;
}
}
/**
* Determines the value of the given byte in the buffer.
*
* @param position The index of the byte to read.
* @return The value of the byte at the given position, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the firts byte in the buffer to the value 255.
* p1.getByte(0); // Returns 255.
* @endcode
*/
int ManagedBuffer::getByte(int position)
{
if (0 <= position && position < ptr->length)
return ptr->payload[position];
else
return MICROBIT_INVALID_PARAMETER;
}
/**
* Get current ptr, do not decr() it, and set the current instance to an empty buffer.
* This is to be used by specialized runtimes which pass BufferData around.
*/
BufferData *ManagedBuffer::leakData()
{
BufferData* res = ptr;
initEmpty();
return res;
}
int ManagedBuffer::fill(uint8_t value, int offset, int length)
{
if (offset < 0 || offset > ptr->length)
return MICROBIT_INVALID_PARAMETER;
if (length < 0)
length = ptr->length;
length = min(length, ptr->length - offset);
memset(ptr->payload + offset, value, length);
return MICROBIT_OK;
}
ManagedBuffer ManagedBuffer::slice(int offset, int length) const
{
offset = min(ptr->length, offset);
if (length < 0)
length = ptr->length;
length = min(length, ptr->length - offset);
return ManagedBuffer(ptr->payload + offset, length);
}
void ManagedBuffer::shift(int offset, int start, int len)
{
if (len < 0) len = ptr->length - start;
if (start < 0 || start + len > ptr->length || start + len < start
|| len == 0 || offset == 0 || offset == INT_MIN) return;
if (offset <= -len || offset >= len) {
fill(0);
return;
}
uint8_t *data = ptr->payload + start;
if (offset < 0) {
offset = -offset;
memmove(data + offset, data, len - offset);
memset(data, 0, offset);
} else {
len = len - offset;
memmove(data, data + offset, len);
memset(data + len, 0, offset);
}
}
void ManagedBuffer::rotate(int offset, int start, int len)
{
if (len < 0) len = ptr->length - start;
if (start < 0 || start + len > ptr-> length || start + len < start
|| len == 0 || offset == 0 || offset == INT_MIN) return;
if (offset < 0)
offset += len << 8; // try to make it positive
offset %= len;
if (offset < 0)
offset += len;
uint8_t *data = ptr->payload + start;
uint8_t *n_first = data + offset;
uint8_t *first = data;
uint8_t *next = n_first;
uint8_t *last = data + len;
while (first != next) {
uint8_t tmp = *first;
*first++ = *next;
*next++ = tmp;
if (next == last) {
next = n_first;
} else if (first == n_first) {
n_first = next;
}
}
}
int ManagedBuffer::writeBuffer(int dstOffset, const ManagedBuffer &src, int srcOffset, int length)
{
if (length < 0)
length = src.length();
if (srcOffset < 0 || dstOffset < 0 || dstOffset > ptr->length)
return MICROBIT_INVALID_PARAMETER;
length = min(src.length() - srcOffset, ptr->length - dstOffset);
if (length < 0)
return MICROBIT_INVALID_PARAMETER;
if (ptr == src.ptr) {
memmove(getBytes() + dstOffset, src.ptr->payload + srcOffset, length);
} else {
memcpy(getBytes() + dstOffset, src.ptr->payload + srcOffset, length);
}
return MICROBIT_OK;
}
int ManagedBuffer::writeBytes(int offset, uint8_t *src, int length, bool swapBytes)
{
if (offset < 0 || length < 0 || offset + length > ptr->length)
return MICROBIT_INVALID_PARAMETER;
if (swapBytes) {
uint8_t *p = ptr->payload + offset + length;
for (int i = 0; i < length; ++i)
*--p = src[i];
} else {
memcpy(ptr->payload + offset, src, length);
}
return MICROBIT_OK;
}
int ManagedBuffer::readBytes(uint8_t *dst, int offset, int length, bool swapBytes) const
{
if (offset < 0 || length < 0 || offset + length > ptr->length)
return MICROBIT_INVALID_PARAMETER;
if (swapBytes) {
uint8_t *p = ptr->payload + offset + length;
for (int i = 0; i < length; ++i)
dst[i] = *--p;
} else {
memcpy(dst, ptr->payload + offset, length);
}
return MICROBIT_OK;
}

257
libs/core/ManagedBuffer.h Normal file
View File

@ -0,0 +1,257 @@
#ifndef MICROBIT_MANAGED_BUFFER_H
#define MICROBIT_MANAGED_BUFFER_H
#include "mbed.h"
#include "RefCounted.h"
struct BufferData : RefCounted
{
uint16_t length; // The length of the payload in bytes
uint8_t payload[0]; // ManagedBuffer data
};
/**
* Class definition for a ManagedBuffer.
* A ManagedBuffer holds a series of bytes, used with MicroBitRadio channels and in other places.
* n.b. This is a mutable, managed type.
*/
class ManagedBuffer
{
BufferData *ptr; // Pointer to payload data
public:
/**
* Default Constructor.
* Creates an empty ManagedBuffer. The 'ptr' field in all empty buffers is shared.
*
* Example:
* @code
* ManagedBuffer p();
* @endcode
*/
ManagedBuffer();
/**
* Constructor.
* Creates a new ManagedBuffer of the given size.
*
* @param length The length of the buffer to create.
*
* Example:
* @code
* ManagedBuffer p(16); // Creates a ManagedBuffer 16 bytes long.
* @endcode
*/
ManagedBuffer(int length);
/**
* Constructor.
* Creates an empty ManagedBuffer of the given size,
* and fills it with the data provided.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
* Example:
* @code
* uint8_t buf[] = {13,5,2};
* ManagedBuffer p(buf, 3); // Creates a ManagedBuffer 3 bytes long.
* @endcode
*/
ManagedBuffer(uint8_t *data, int length);
/**
* Copy Constructor.
* Add ourselves as a reference to an existing ManagedBuffer.
*
* @param buffer The ManagedBuffer to reference.
*
* Example:
* @code
* ManagedBuffer p();
* ManagedBuffer p2(i); // Refers to the same buffer as p.
* @endcode
*/
ManagedBuffer(const ManagedBuffer &buffer);
/**
* Constructor.
* Create a buffer from a raw BufferData pointer. It will ptr->incr(). This is to be used by specialized runtimes.
*
* @param p The pointer to use.
*/
ManagedBuffer(BufferData *p);
/**
* Internal constructor helper.
* Configures this ManagedBuffer to refer to the static empty buffer.
*/
void initEmpty();
/**
* Internal constructor-initialiser.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
*/
void init(uint8_t *data, int length);
/**
* Destructor.
* Removes buffer resources held by the instance.
*/
~ManagedBuffer();
/**
* Provide an array containing the buffer data.
* @return The contents of this buffer, as an array of bytes.
*/
uint8_t *getBytes()
{
return ptr->payload;
}
/**
* Get current ptr, do not decr() it, and set the current instance to an empty buffer.
* This is to be used by specialized runtimes which pass BufferData around.
*/
BufferData *leakData();
/**
* Copy assign operation.
*
* Called when one ManagedBuffer is assigned the value of another using the '=' operator.
* Decrements our reference count and free up the buffer as necessary.
* Then, update our buffer to refer to that of the supplied ManagedBuffer,
* and increase its reference count.
*
* @param p The ManagedBuffer to reference.
*
* Example:
* @code
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* p1 = p2;
* @endcode
*/
ManagedBuffer& operator = (const ManagedBuffer& p);
/**
* Array access operation (read).
*
* Called when a ManagedBuffer is dereferenced with a [] operation.
* Transparently map this through to the underlying payload for elegance of programming.
*
* Example:
* @code
* ManagedBuffer p1(16);
* uint8_t data = p1[0];
* @endcode
*/
uint8_t operator [] (int i) const
{
return ptr->payload[i];
}
/**
* Array access operation (modify).
*
* Called when a ManagedBuffer is dereferenced with a [] operation.
* Transparently map this through to the underlying payload for elegance of programming.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1[0] = 42;
* @endcode
*/
uint8_t& operator [] (int i)
{
return ptr->payload[i];
}
/**
* Equality operation.
*
* Called when one ManagedBuffer is tested to be equal to another using the '==' operator.
*
* @param p The ManagedBuffer to test ourselves against.
* @return true if this ManagedBuffer is identical to the one supplied, false otherwise.
*
* Example:
* @code
*
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* if(p1 == p2) // will be true
* uBit.display.scroll("same!");
* @endcode
*/
bool operator== (const ManagedBuffer& p);
/**
* Sets the byte at the given index to value provided.
* @param position The index of the byte to change.
* @param value The new value of the byte (0-255).
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the first byte in the buffer to the value 255.
* @endcode
*/
int setByte(int position, uint8_t value);
/**
* Determines the value of the given byte in the buffer.
*
* @param position The index of the byte to read.
* @return The value of the byte at the given position, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the first byte in the buffer to the value 255.
* p1.getByte(0); // Returns 255.
* @endcode
*/
int getByte(int position);
/**
* Gets number of bytes in this buffer
* @return The size of the buffer in bytes.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.length(); // Returns 16.
* @endcode
*/
int length() const { return ptr->length; }
int fill(uint8_t value, int offset = 0, int length = -1);
ManagedBuffer slice(int offset = 0, int length = -1) const;
void shift(int offset, int start = 0, int length = -1);
void rotate(int offset, int start = 0, int length = -1);
int readBytes(uint8_t *dst, int offset, int length, bool swapBytes = false) const;
int writeBytes(int dstOffset, uint8_t *src, int length, bool swapBytes = false);
int writeBuffer(int dstOffset, const ManagedBuffer &src, int srcOffset = 0, int length = -1);
bool isReadOnly() const { return ptr->isReadOnly(); }
};
#endif

View File

@ -26,7 +26,7 @@
"String.substr": "Return substring of the current string.",
"String.substr|param|length": "number of characters to extract",
"String.substr|param|start": "first character index; can be negative from counting from the end, eg:0",
"basic": "Provides access to basic micro:bit functionality.",
"basic": "Provides access to basic micro:bit functionality.\n\nProvides access to basic micro:bit functionality.",
"basic.clearScreen": "Turn off all LEDs",
"basic.color": "Converts the color name to a number",
"basic.forever": "Repeats the code forever in the background. On each iteration, allows other codes to run.",
@ -169,9 +169,9 @@
"led.unplot|param|x": "TODO",
"led.unplot|param|y": "TODO",
"motors": "Blocks to control the onboard motors",
"motors.dualMotorPower": "Controls two motors attached to the board.",
"motors.motorCommand": "Send break, coast or sleep commands to the motor",
"motors.motorPower": "Turns on the motor at a certain percent of power.",
"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.motorPower": "Turns on the motor at a certain percent of power. Switches to single motor mode!",
"motors.motorPower|param|power": "%percent of power sent to the motor. Negative power goes backward. eg: 50",
"music": "Generation of music tones through pin ``P0``.",
"music.beat": "Returns the duration of a beat in milli-seconds",
@ -180,7 +180,6 @@
"music.noteFrequency": "Gets the frequency of a note.",
"music.noteFrequency|param|name": "the note name",
"music.playTone": "Plays a tone through ``speaker`` for the given duration.",
"music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
"music.playTone|param|ms": "tone duration in milliseconds (ms)",
"music.rest": "Rests (plays nothing) for a specified time through pin ``P0``.",
"music.rest|param|ms": "rest duration in milliseconds (ms)",

View File

@ -1,6 +1,93 @@
{
"AcceleratorRange.EightG": "The accelerator measures forces up to 8 gravity",
"AcceleratorRange.EightG|block": "8g",
"AcceleratorRange.FourG": "The accelerator measures forces up to 4 gravity",
"AcceleratorRange.FourG|block": "4g",
"AcceleratorRange.OneG": "The accelerator measures forces up to 1 gravity",
"AcceleratorRange.OneG|block": "1g",
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
"AcceleratorRange.TwoG|block": "2g",
"BaudRate.BaudRate115200|block": "115200",
"BaudRate.BaudRate9600|block": "9600",
"BeatFraction.Eighth|block": "1/8",
"BeatFraction.Half|block": "1/2",
"BeatFraction.Quarter|block": "1/4",
"BeatFraction.Sixteenth|block": "1/16",
"BeatFraction.Whole|block": "1",
"Button.AB|block": "A+B",
"Colors.Blue|block": "blue",
"Colors.Green|block": "green",
"Colors.Indigo|block": "indigo",
"Colors.Orange|block": "orange",
"Colors.Purple|block": "purple",
"Colors.Red|block": "red",
"Colors.Violet|block": "violet",
"Colors.White|block": "white",
"Colors.Yellow|block": "yellow",
"Delimiters.Colon|block": ":",
"Delimiters.Comma|block": ",",
"Delimiters.Dollar|block": "$",
"Delimiters.Fullstop|block": ".",
"Delimiters.Hash|block": "#",
"Delimiters.NewLine|block": "new line",
"Dimension.Strength|block": "strength",
"Dimension.X|block": "x",
"Dimension.Y|block": "y",
"Dimension.Z|block": "z",
"Direction.Left|block": "left",
"Direction.Right|block": "right",
"DisplayMode.BackAndWhite|block": "black and white",
"DisplayMode.Greyscale|block": "greyscale",
"EventCreationMode.CreateAndFire": "MicroBitEvent is initialised, and its event handlers are immediately fired (not suitable for use in interrupts!).",
"EventCreationMode.CreateOnly": "MicroBitEvent is initialised, and no further processing takes place.",
"Gesture.FreeFall": "Raised when the board is falling!",
"Gesture.FreeFall|block": "free fall",
"Gesture.LogoDown": "Raised when the logo is downward and the screen is vertical",
"Gesture.LogoDown|block": "logo down",
"Gesture.LogoUp": "Raised when the logo is upward and the screen is vertical",
"Gesture.LogoUp|block": "logo up",
"Gesture.ScreenDown": "Raised when the screen is pointing up and the board is horizontal",
"Gesture.ScreenDown|block": "screen down",
"Gesture.ScreenUp": "Raised when the screen is pointing down and the board is horizontal",
"Gesture.ScreenUp|block": "screen up",
"Gesture.Shake": "Raised when shaken",
"Gesture.Shake|block": "shake",
"Gesture.SixG": "Raised when a 6G shock is detected",
"Gesture.SixG|block": "6g",
"Gesture.ThreeG": "Raised when a 3G shock is detected",
"Gesture.ThreeG|block": "3g",
"Gesture.TiltLeft": "Raised when the screen is pointing left",
"Gesture.TiltLeft|block": "tilt left",
"Gesture.TiltRight": "Raised when the screen is pointing right",
"Gesture.TiltRight|block": "tilt right",
"LedSpriteProperty.Blink|block": "blink",
"LedSpriteProperty.Brightness|block": "brightness",
"LedSpriteProperty.Direction|block": "direction",
"LedSpriteProperty.X|block": "x",
"LedSpriteProperty.Y|block": "y",
"Math.randomBoolean|block": "pick random true or false",
"Math|block": "Math",
"Motor.AB|block": "A and B",
"MotorCommand.Break|block": "break",
"MotorCommand.Coast|block": "coast",
"MotorCommand.Sleep|block": "sleep",
"Note.CSharp3|block": "C#3",
"Note.CSharp4|block": "C#4",
"Note.CSharp5|block": "C#5",
"Note.CSharp|block": "C#",
"Note.FSharp3|block": "F#3",
"Note.FSharp4|block": "F#4",
"Note.FSharp5|block": "F#5",
"Note.FSharp|block": "F#",
"Note.GSharp3|block": "G#3",
"Note.GSharp4|block": "G#4",
"Note.GSharp5|block": "G#5",
"Note.GSharp|block": "G#",
"PinPullMode.PullDown|block": "down",
"PinPullMode.PullNone|block": "none",
"PinPullMode.PullUp|block": "up",
"Rotation.Pitch|block": "pitch",
"Rotation.Roll|block": "roll",
"String.charAt|block": "char from %this|at %pos",
"String.compare|block": "compare %this| to %that",
"String.concat|block": "join %this|%other",

View File

@ -1,13 +1,45 @@
{
"Math.abs": "Gibt den absoluten Wert einer Zahl aus (den Wert unabhängig davon, ob er positiv oder negativ ist).\nDer absolute Wert von -5 ist zum Beispiel der gleiche wie der von 5.",
"Math.abs|param|x": "Ein numerischer Ausdruck, für den der absolute Wert benötigt wird.",
"Math.max": "Gibt den größeren von zwei vorhandenen numerischen Ausdrücken aus.",
"Math.min": "Gibt den niedrigeren von zwei vorhandenen numerischen Ausdrücken aus.",
"Math.pow": "Gibt den Wert eines grundlegenden Ausdrucks bis zu einer bestimmten Stärke aus.",
"Math.pow|param|x": "Der Basiswert des Ausdrucks.",
"Math.pow|param|y": "Der exponentielle Wert des Ausdrucks.",
"Math.random": "Gibt eine pseudozufüllige Zahl zwischen 0 und `max`aus.",
"Math.randomBoolean": "Erzeugt zufällig einen \"wahr\" oder \"falsch\"-Wert, wie bei einem Münzwurf.",
"Math.sign": "Gibt das Vorzeichen von x aus und zeigt an, ob dieses positiv, negativ oder null ist.",
"Math.sign|param|x": "Der numerische Ausdruck, der getestet werden soll",
"Math.sqrt": "Gibt die Quadratwurzel einer Zahl aus.",
"Math.sqrt|param|x": "Ein numerischer Ausdruck.",
"String.charAt": "Gibt den Buchstaben beim angegebenen Index aus.",
"String.charAt|param|index": "Der null-basierte index des gewünschten Zeichens.",
"String.charCodeAt": "Gibt den Unicode-Wert des Zeichens am vorgegebenen Ort aus.",
"String.charCodeAt|param|index": "Der null-basierte Index des gewünschten Zeichens. Wenn kein Zeichen am angegeben Index vorhanden ist, wird NaN ausgegeben.",
"String.compare": "Bestimmt die relative Reihenfolge zweier Strings (in ASCII).",
"String.compare|param|that": "Zeichenfolge, die mit der Zielzeichenfolge verglichen werden soll",
"String.concat": "Gibt eine Zeichenfolge aus, die die Verkettung von zwei oder mehr Zeichenfolgen ist.",
"String.concat|param|other": "Die Zeichenfolge, die an das Ende einer Zeichenfolge angehängt werden soll.",
"String.fromCharCode": "Erstelle Sie eine Zeichenfolge aus dem angegebenen ASCII-Zeichencode.",
"String.isEmpty": "Gibt einen Wert aus, der anzeigt, ob die Zeichenfolge leer ist",
"String.length": "Gibt die Länge einer Zeichenfolge aus.",
"String.substr": "Gibt eine Teilzeichenfolge der aktuellen Zeichenfolge aus.",
"String.substr|param|length": "Anzahl der zu extrahierenden Zeichen",
"String.substr|param|start": "Erster Zeichenindex, kann beim zählen vom Ende negativ sein, zum Beispiel: 0",
"basic": "Bietet Zugriff auf grundlegende mini-Funktionalität.",
"basic.clearScreen": "Schalte alle LEDs aus",
"basic.color": "Konvertiert den Farbnamen in eine Nummer",
"basic.forever": "Wiederholt immer wieder den Code im Hintergrund. Bei jeder Iteration ist es möglich, anderen Code auszuführen.",
"basic.pause": "Pausiere für die angegebene Zeit in Millisekunden",
"basic.pause|param|ms": "wie lange pausieren, z.B.: 100, 200, 500, 1000, 2000",
"basic.plotLeds": "Zeichnet ein Bild auf dem LED-Bildschirm.",
"basic.plotLeds|param|leds": "Muster der LEDs, die ein-/ und ausgeschaltet werden",
"basic.rgbw": "Konvertiert Rot-, Grün- und Blau-Kanäle in eine RGB-Farbe",
"basic.rgbw|param|blue": "Blauwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|green": "Grünwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|red": "Rotwert zwischen 0 und 255, z.B. 255",
"basic.rgbw|param|white": "Weißwert zwischen 0 und 255, z.B. 0",
"basic.setLedColor": "Legt die Farbe der eingebauten LED fest. Setze auf 0, um diese abzuschalten.",
"basic.showAnimation": "Zeigt eine Abfolge von LED-Anzeigen als Animation.",
"basic.showAnimation|param|interval": "Zeit in Millisekunden zwischen jedem Neuzeichnen",
"basic.showAnimation|param|leds": "Muster der LEDs, die ein-/ und ausgeschaltet werden",
@ -20,19 +52,50 @@
"basic.showString|param|interval": "Wie schnell die Zeichen geändert werden; z.B. 150, 100, 200,-100",
"basic.showString|param|text": "Text auf dem Bildschirm dargestellt werden soll, z.B.: \"Hallo!\"",
"control": "Laufzeit- und Event-Dienstprogramme.",
"control.assert": "Wenn die Bedingung falsch ist, zeige eine Nachricht auf der seriellen Konsole und gebe Panic-Code 098 aus",
"control.deviceName": "Erzeugt einen Namen für das Gerät, basierend auf der Seriennummer",
"control.eventSourceId": "Gibt den Wert einer C++-Laufzeitkonstanten aus",
"control.eventTimestamp": "Holt den Zeitstempel des letzten Events auf dem Bus",
"control.eventValue": "Holt den Wert des letzten ausgeführten Events auf dem Bus",
"control.eventValueId": "Gibt den Wert einer C++-Laufzeitkonstanten aus",
"control.inBackground": "Plant Code, der im Hintergrund wiedergegeben wird.",
"control.onEvent": "Startet ein Event auf dem Event-Bus.",
"control.panic": "Zeigt einen spezifizierten Fehlercode und hält das Programm an.",
"control.raiseEvent": "Startet ein Event auf dem Event-Bus.",
"control.raiseEvent|param|mode": "optionale Definition davon, wie ein Event nach dem Erstellen ausgeführt wird (Standard ist \"CREATE_AND_FIRE).",
"control.raiseEvent|param|src": "ID der Calliope mini-Komponente, die das Event generiert hat, zum Beispiel CALLIOPE_ID_BUTTON_A.",
"control.raiseEvent|param|value": "Komponentenspezifischer Code, der den Grund des Events angibt.",
"control.reset": "Seit den mini zurück.",
"control.runtimeWarning": "Zeige Warnmeldung im Simulator.",
"control.waitMicros": "Sperrt die aktuelle Leitung für die Dauer der angegebenen Mikrosekunden",
"control.waitMicros|param|micros": "Anzahl der Mikrosekunden, die gewartet werden soll, z.B.: 4",
"game": "Eine Einzel-LED-Sprite-Spielumgebung",
"game.addLife": "Fügt Leben zum aktuellen Spielstand hinzu",
"game.addLife|param|lives": "TODO",
"game.addScore": "Fügt zum aktuellen Spielstand Punkte hinzu",
"game.addScore|param|points": "Anzahl von zu verändernden Punkten, z.B.: 1",
"game.createSprite": "Erzeugt einen neuen LED-Sprite, der nach rechts zeigt.",
"game.createSprite|param|x": "horizontale Koordinate des Sprites, z.B. 2",
"game.createSprite|param|y": "vertikale Koordinate des Sprites, z.B. 2",
"game.currentTime": "Ruft die verbliebene Zeit (seit `starte Countdown`) oder die aktuelle Zeit (seit das Gerät gestartet wurde oder eine Stoppuhr aktiviert wurde) an.",
"game.gameOver": "Gibt über eine Animation ein Spiel wieder.",
"game.invalidSprite": "Ruft einen invaliden Sprite ab; wird genutzt, um Locale zu initialisieren.",
"game.isGameOver": "Zeigt an, ob das Spil die \"Game Over\"-Sequenz angezeigt hat.",
"game.isRunning": "Holt einen Wert, der anzeigt, ob das Spiel noch läuft. Gibt `falsch`aus, wenn das Spiel zu Ende ist.",
"game.level": "Ruft das aktuelle Level ab",
"game.levelUp": "Erhöht das Level und zeigt eine Nachricht an.",
"game.life": "Ruft das aktuelle Leben ab",
"game.removeLife": "Entfernt ein Leben",
"game.removeLife|param|life": "TODO",
"game.score": "Ruft den aktuellen Punktestand ab",
"game.setLife": "Setzt den aktuellen Wert der Leben",
"game.setLife|param|value": "TODO",
"game.setScore": "Setzt den aktuellen Wert des Spielstands",
"game.setScore|param|value": "TODO",
"game.showScore": "Zeigt den Spielstand auf dem Display.",
"game.startCountdown": "Startet einen Spiel-Countdown",
"game.startCountdown|param|ms": "Countdown-Dauer in Millisekunden, z.B.: 10000",
"game.startStopwatch": "Startet eine Stoppuhr.`aktuelle Zeit`gibt die vergangene Zeit an.",
"images": "Erstellung, Bearbeitung und Anzeige von LED-Bildern.",
"images.createBigImage": "Erstellt ein Bild mit zwei Einzelbildern.",
"images.createImage": "Erstellt ein Bild, das auf den LED-Bildschirm passt.",
@ -76,6 +139,7 @@
"input.temperature": "Ruft die aktuelle Temperatur in Grad Celsius (°C) ab.",
"led": "Steuerung des LED-Bildschirms.",
"led.brightness": "Ruft die Helligkeit des Bildschirms ab, von 0 (aus) bis 255 (volle Helligkeit).",
"led.enable": "Schaltet das Display an und aus",
"led.fadeIn": "Blendet die Bildschirmanzeige ein.",
"led.fadeIn|param|ms": "TODO",
"led.fadeOut": "Blendet die Bildschirmhelligkeit aus.",
@ -103,18 +167,22 @@
"led.unplot": "Schalte die angegebene LED mit x-und y-Koordinaten ab (X ist horizontal, y ist vertikal). (0,0) ist oben links.",
"led.unplot|param|x": "TODO",
"led.unplot|param|y": "TODO",
"motors": "Blöcke, die genutzt werden, um Onboard-Motoren zu steuern",
"motors.dualMotorPower": "Steuert zwei an das Board angeschlossene Motoren. Schaltet auf Dual-Motor-Modus um!",
"motors.motorCommand": "Schicke Anhalten, Ausrollen oder Anhalten-Befehle an den Motor. Hat im Dual-Motor-Modus keinen Effekt.",
"motors.motorPower": "Schaltet den Motor bei einer bestimmten Prozentzahl der Kraft an. Schaltet um auf den Single-Motor-Modus!",
"motors.motorPower|param|power": "%percent der Kraft, die an den Motor geschickt wird. Negative Werte laufen rückwärts, z.B. 50",
"music": "Generierung von von Musik durch Pin ``P0``.",
"music.beat": "Gibt die Dauer eines Taktes in Milli-Sekunden aus",
"music.changeTempoBy": "Ändere die Geschwindigkeit um den angegebenen Betrag",
"music.changeTempoBy|param|bpm": "Die Änderung in Schlägen pro Minute auf das Tempo, z.B.: 20",
"music.noteFrequency": "Ruft die Frequenz einer Note ab.",
"music.noteFrequency|param|name": "der Name der Notiz",
"music.playTone": "Spielt einen Ton für den angegebenen Zeitraum über Pin ``P0`` ab.",
"music.playTone|param|frequency": "Tonhöhe des abzuspielenden Tones in Hertz (Hz)",
"music.playTone": "Spielt einen Ton für den angegebenen Zeitraum auf dem Lautsprecher ab.",
"music.playTone|param|ms": "Tondauer in Millisekunden (ms)",
"music.rest": "Ruht (spielt nichts) für eine bestimmte Zeit auf Pin ``P0``.",
"music.rest|param|ms": "Restdauer in Millisekunden (ms)",
"music.ringTone": "Spielt einen Ton über Pin ``P0``.",
"music.ringTone": "Spielt einen Ton durch den Lautsprecher ab.",
"music.ringTone|param|frequency": "Tonhöhe des abzuspielenden Tones in Hertz (Hz)",
"music.setTempo": "Legt die Geschwindigkeit auf den angegebenen Wert fest.",
"music.setTempo|param|bpm": "Die neue Geschwindigkeit in Schlägen pro Minute, z.B.: 120",
@ -133,12 +201,16 @@
"pins.analogWritePin": "Legt den Wert des Verbinders auf analog fest. Der Wert muss zwischen 0 und 1023 liegen.",
"pins.analogWritePin|param|name": "PIN-Name, auf den geschrieben werden soll",
"pins.analogWritePin|param|value": "Wert, der auf den Pin geschrieben werden soll, zwischen ``0`` und ``1023`` z.B.: 1023,0",
"pins.createBuffer": "Erstellt einen Null-initialisierten Zwischenspeicher.",
"pins.createBuffer|param|size": "Anzahl der Bytes im Zwischenspeicher",
"pins.digitalReadPin": "Lese den angegebene Pin oder Verbinder als 0 oder 1",
"pins.digitalReadPin|param|name": "Pin, aus dem gelesen werden soll",
"pins.digitalWritePin": "Setzt einen Pin- oder Verbinder-Wert auf 0 oder 1.",
"pins.digitalWritePin|param|name": "Pin, auf den geschrieben werden soll",
"pins.digitalWritePin|param|value": "Wert, der auf dem Pin 1 gesetzt werden soll, z.B. 0",
"pins.i2cReadBuffer": "Lese `Größe`bytes aus einer 7-bit I2C-Adresse.",
"pins.i2cReadNumber": "Lese eine Nummer aus einer 7-bit I2C-Adresse.",
"pins.i2cWriteBuffer": "Schreibt Bytes in eine 7-bit I2C-Adresse.",
"pins.i2cWriteNumber": "Schreibe eine Nummer in eine 7-bit I2C-Adresse.",
"pins.map": "Definiert eine Nummer von einer Auswahl zu einer anderen um. Ein Wert ``von niedrig``wird so auf ``zu niedrig``umgeändert, ein Wert ``von hoch`` zu ``zu hoch`` etc.",
"pins.map|param|fromHigh": "die obere Grenze des aktuellen Wertebereichs, z.B.: 1023",
@ -148,6 +220,9 @@
"pins.map|param|value": "Wert in Bereichen zuordnen",
"pins.onPulsed": "Stellt diesen Pin als einen Digitaleingang ein und generiert Ereignisse, deren Zeitstempel die Dauer darstellt, in der der Pin entweder ``hoch``oder ``niedrig``war.",
"pins.pulseDuration": "Ruft die Dauer des letzten Impulses in Mikrosendungen ab. Diese Funktion soll von einem `onPulsed`-Handler aufgerufen werden.",
"pins.pulseIn": "Gibt die Dauer eines Pulses in Mikrosekunden an",
"pins.pulseIn|param|name": "der Pin, der den Puls misst",
"pins.pulseIn|param|value": "der Wert des Pulses (Standard hoch)",
"pins.servoSetPulse": "Konfiguriert diesen IO-Pin als einen analogen/PWM-Ausgang, stellt den Zeitraum auf 20 ms ein und setzt die Pulsweite fest, basieren auf dem angegeben Wert **Mikrosekunden** oder `1/1000`Millisekunden.",
"pins.servoSetPulse|param|micros": "Impulsdauer in Mikrosekunden, z.B.: 1500",
"pins.servoSetPulse|param|name": "PIN-Name",
@ -156,10 +231,13 @@
"pins.servoWritePin|param|value": "Winkel oder Rotationsbeschleunigung, z.B.: 180,90,0",
"pins.setPull": "Stellt die Anziehungskraft des Pins ein.",
"pins.setPull|param|name": "Pin, auf dem der Pull-Modus aktiviert wird",
"pins.setPull|param|pull": "eine der mbed-Pull-Konfigurationen: PullUp, PullDown, PullNone ",
"pins.setPull|param|pull": "eine der mbed-Pull-Konfigurationen: PullUp, PullDown, PullNone",
"pins.sizeOf": "Ruft die Bytegröße im spezifierten Nummernformat ab.",
"pins.spiWrite": "Schreibe in den SPI-Slave und gebe die Antwort aus",
"pins.spiWrite|param|value": "Daten, die an den SPI-Slave geschickt werden sollen",
"serial": "Lesen und Schreiben von Daten über eine serielle Verbindung.",
"serial.delimiters": "Gibt die mit dem Begrenzer korrespondierende Zeichenfolge aus.",
"serial.onLineReceived": "Registriert ein Event, das ausgeführt wird, wenn eine Zeile empfangen wurde",
"serial.readLine": "Liest eine Textzeile aus der seriellen Schnittstelle.",
"serial.readUntil": "Liest aus eine Textzeile aus dem seriellen Anschluss und gibt den Puffer aus, wenn die Begrenzung erreicht wurde.",
"serial.readUntil|param|delimiter": "Text-Begrenzung, die die Textblöcke voneinander trennt",
@ -167,7 +245,7 @@
"serial.redirect|param|rx": "der neue Empfangs-Pin",
"serial.redirect|param|tx": "Der neue Übertragungs-Pin",
"serial.writeLine": "Gibt eine Zeile des Textes an die serielle",
"serial.writeNumber": " Gibt einen numerischen Wert an die serielle",
"serial.writeNumber": "Gibt einen numerischen Wert an die serielle",
"serial.writeString": "Sendet ein Stück Text über serielle Verbindung.",
"serial.writeValue": "Schreibt ein ``Namen: Wert`` Wertepaar auf die serielle Schnittstelle.",
"serial.writeValue|param|name": "Name des Wertestreams, z.B.: x",

View File

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

View File

@ -1,31 +1,6 @@
{
"Math.abs": "",
"Math.abs|param|x": "",
"Math.max": "",
"Math.min": "",
"Math.pow": "",
"Math.pow|param|x": "",
"Math.pow|param|y": "",
"Math.random": "",
"Math.randomBoolean": "Génère une valeur « true » ou « false » au hasard, comme si vous lanciez une pièce de monnaie.",
"Math.sign": "",
"Math.sign|param|x": "",
"Math.sqrt": "",
"Math.sqrt|param|x": "",
"String.charAt": "",
"String.charAt|param|index": "",
"String.charCodeAt": "",
"String.charCodeAt|param|index": "",
"String.compare": "",
"String.compare|param|that": "",
"String.concat": "",
"String.concat|param|other": "",
"String.fromCharCode": "Construit une chaîne à partir du code ASCII d'un caractère donné.",
"String.isEmpty": "",
"String.length": "",
"String.substr": "",
"String.substr|param|length": "",
"String.substr|param|start": "",
"basic": "Permet daccéder aux fonctionnalités de base de la micro:bit.",
"basic.clearScreen": "Éteindre toutes les LEDs",
"basic.forever": "Répète le code indéfiniment en tâche de fond. A chaque itération, permet aux autres codes de sexécuter.",
@ -44,200 +19,63 @@
"basic.showString": "Afficher du texte à lécran, un caractère à la fois. Si la chaîne rentre sur lécran (c'est-à-dire une seule lettre), ne défile pas.",
"basic.showString|param|interval": "à quelle vitesse se déplacent les caractères ; par ex. : 150, 100, 200, -100",
"basic.showString|param|text": "le texte à faire défiler sur lécran, par exemple : « Bonjour ! »",
"control": "",
"control.assert": "",
"control.deviceName": "",
"control.deviceSerialNumber": "",
"control.eventSourceId": "",
"control.eventTimestamp": "",
"control.eventValue": "",
"control.eventValueId": "",
"control.inBackground": "Planifie le code qui sexécute en arrière-plan.",
"control.onEvent": "",
"control.panic": "",
"control.raiseEvent": "",
"control.raiseEvent|param|mode": "",
"control.raiseEvent|param|src": "",
"control.raiseEvent|param|value": "",
"control.reset": "Réinitialise le micro:bit de BBC.",
"control.runtimeWarning": "",
"control.waitMicros": "",
"control.waitMicros|param|micros": "nombre de microsecondes à attendre. par ex. : 4",
"game": "Un moteur de jeu avec une unique LED",
"game.addLife": "",
"game.addLife|param|lives": "",
"game.addLife|param|lives": "TODO",
"game.addScore": "Ajoute des points au score actuel",
"game.addScore|param|points": "nombre de points à changer, par ex. : 1",
"game.createSprite": "",
"game.createSprite|param|x": "",
"game.createSprite|param|y": "",
"game.currentTime": "",
"game.gameOver": "Affiche un animation de fin de jeu.",
"game.invalidSprite": "",
"game.isGameOver": "",
"game.isRunning": "",
"game.level": "",
"game.levelUp": "",
"game.life": "",
"game.removeLife": "",
"game.removeLife|param|life": "",
"game.removeLife|param|life": "TODO",
"game.score": "Obtient le score actuel",
"game.setLife": "",
"game.setLife|param|value": "",
"game.setLife|param|value": "TODO",
"game.setScore": "Définit la valeur du score actuel",
"game.setScore|param|value": "",
"game.showScore": "",
"game.startCountdown": "",
"game.startCountdown|param|ms": "",
"game.startStopwatch": "",
"images": "",
"images.createBigImage": "",
"images.createImage": "",
"input": "",
"input.acceleration": "",
"input.acceleration|param|dimension": "",
"input.buttonIsPressed": "",
"input.calibrate": "",
"input.compassHeading": "",
"input.lightLevel": "",
"input.magneticForce": "",
"input.magneticForce|param|dimension": "",
"input.onButtonPressed": "",
"input.onButtonPressed|param|body": "",
"input.onButtonPressed|param|button": "",
"input.onGesture": "",
"input.onGesture|param|body": "",
"input.onLogoDown": "",
"input.onLogoDown|param|body": "",
"input.onLogoUp": "",
"input.onLogoUp|param|body": "",
"input.onPinPressed": "",
"input.onPinPressed|param|body": "",
"input.onPinPressed|param|name": "",
"input.onPinReleased": "",
"input.onPinReleased|param|body": "",
"input.onPinReleased|param|name": "",
"input.onScreenDown": "",
"input.onScreenDown|param|body": "",
"input.onScreenUp": "",
"input.onScreenUp|param|body": "",
"input.onShake": "",
"input.onShake|param|body": "",
"input.pinIsPressed": "",
"input.pinIsPressed|param|name": "",
"input.rotation": "",
"input.rotation|param|kind": "",
"input.runningTime": "",
"input.setAccelerometerRange": "",
"input.setAccelerometerRange|param|range": "",
"input.temperature": "",
"led": "",
"led.brightness": "",
"led.enable": "",
"led.fadeIn": "",
"led.fadeIn|param|ms": "",
"led.fadeOut": "",
"led.fadeOut|param|ms": "",
"led.plot": "",
"led.plotAll": "",
"led.plotBarGraph": "",
"led.plotBarGraph|param|high": "",
"led.plotBarGraph|param|value": "",
"led.plot|param|x": "",
"led.plot|param|y": "",
"led.point": "",
"led.point|param|x": "",
"led.point|param|y": "",
"led.screenshot": "",
"led.setBrightness": "",
"led.setBrightness|param|value": "",
"led.setDisplayMode": "",
"led.setDisplayMode|param|mode": "",
"led.stopAnimation": "",
"led.toggle": "",
"led.toggleAll": "",
"led.toggle|param|x": "",
"led.toggle|param|y": "",
"led.unplot": "",
"led.unplot|param|x": "",
"led.unplot|param|y": "",
"music": "",
"music.beat": "",
"music.changeTempoBy": "",
"music.changeTempoBy|param|bpm": "",
"music.noteFrequency": "",
"music.noteFrequency|param|name": "",
"music.playTone": "",
"music.playTone|param|frequency": "",
"music.playTone|param|ms": "",
"game.setScore|param|value": "TODO",
"game.startCountdown": "Démarre un compte à rebours de jeu",
"game.startCountdown|param|ms": "durée du compte à rebours en millisecondes, par ex. : 10000",
"images": "Création, manipulation et affichage dimages LED.",
"images.createBigImage": "Crée une image à partir de 2 images.",
"images.createImage": "Crée une image qui sadapte aux dimensions de lécran LED.",
"input": "Événements et des données provenant de capteurs",
"input.acceleration|param|dimension": "TODO",
"input.calibrate": "Obsolète, le calibrage de la boussole est automatique.",
"input.compassHeading": "Obtient la direction actuelle du compas en degrés.",
"input.magneticForce|param|dimension": "TODO",
"input.onButtonPressed|param|body": "TODO",
"input.onButtonPressed|param|button": "TODO",
"input.onGesture|param|body": "TODO",
"input.onLogoDown|param|body": "TODO",
"input.onLogoUp|param|body": "TODO",
"input.onPinPressed": "Faire quelque chose lorsque vous appuyez sur une broche.",
"input.onPinPressed|param|body": "code à exécuter lorsque la broche est enfoncée",
"input.onPinPressed|param|name": "la broche qui doit être pressée",
"input.onPinReleased": "Faire quelque chose quand une broche est relâchée.",
"input.onPinReleased|param|body": "le code à exécuter lorsque la broche est relâchée",
"input.onPinReleased|param|name": "la broche qui doit être relâchée",
"input.onScreenDown|param|body": "TODO",
"input.onScreenUp|param|body": "TODO",
"input.onShake|param|body": "TODO",
"input.pinIsPressed|param|name": "broche utilisée pour détecter le contact",
"input.rotation|param|kind": "TODO",
"input.temperature": "Obtient la température en degrés Celsius (°C).",
"led": "Contrôle de lécran LED.",
"led.enable": "Active ou désactive laffichage",
"led.fadeIn|param|ms": "TODO",
"led.fadeOut|param|ms": "TODO",
"led.plotAll": "Allume toutes les LEDS",
"led.plotBarGraph|param|value": "valeur actuelle à tracer",
"led.plot|param|x": "TODO",
"led.plot|param|y": "TODO",
"led.point|param|x": "TODO",
"led.point|param|y": "TODO",
"led.setBrightness|param|value": "valeur de la luminosité, par ex. : 255, 127, 0",
"led.toggle|param|x": "TODO",
"led.toggle|param|y": "TODO",
"led.unplot|param|x": "TODO",
"led.unplot|param|y": "TODO",
"music.rest": "Repose (joue rien) pendant une durée spécifiée via broche '' P0''.",
"music.rest|param|ms": "",
"music.ringTone": "",
"music.ringTone|param|frequency": "",
"music.setTempo": "",
"music.setTempo|param|bpm": "",
"music.tempo": "",
"pins": "",
"pins.analogPitch": "",
"pins.analogPitch|param|frequency": "",
"pins.analogPitch|param|ms": "",
"pins.analogReadPin": "",
"pins.analogReadPin|param|name": "",
"pins.analogSetPeriod": "",
"pins.analogSetPeriod|param|micros": "",
"pins.analogSetPeriod|param|name": "",
"pins.analogSetPitchPin": "",
"pins.analogSetPitchPin|param|name": "",
"pins.analogWritePin": "",
"pins.analogWritePin|param|name": "",
"pins.analogWritePin|param|value": "",
"pins.createBuffer": "",
"pins.createBuffer|param|size": "",
"pins.digitalReadPin": "",
"pins.digitalReadPin|param|name": "",
"pins.digitalWritePin": "",
"pins.digitalWritePin|param|name": "",
"pins.digitalWritePin|param|value": "",
"pins.i2cReadNumber": "",
"pins.i2cReadBuffer": "",
"pins.i2cWriteBuffer": "",
"pins.i2cWriteNumber": "",
"pins.map": "",
"pins.map|param|fromHigh": "",
"pins.map|param|fromLow": "",
"pins.map|param|toHigh": "",
"pins.map|param|toLow": "",
"pins.map|param|value": "",
"pins.onPulsed": "",
"pins.pulseDuration": "",
"pins.pulseIn": "",
"pins.pulseIn|param|name": "",
"pins.pulseIn|param|value": "",
"pins.servoSetPulse": "",
"pins.servoSetPulse|param|micros": "",
"pins.servoSetPulse|param|name": "",
"pins.servoWritePin": "",
"pins.servoWritePin|param|name": "",
"pins.servoWritePin|param|value": "",
"pins.setPull": "",
"pins.setPull|param|name": "",
"pins.setPull|param|pull": "",
"pins.spiWrite": "",
"pins.spiWrite|param|value": "",
"serial": "",
"pins.sizeOf": "",
"serial.delimiters": "",
"serial.onLineReceived": "",
"serial.readLine": "",
"serial.readUntil": "",
"serial.readUntil|param|delimiter": "",
"serial.redirect": "",
"serial.redirect|param|rx": "",
"serial.redirect|param|tx": "",
"serial.writeLine": "",
"serial.writeNumber": "",
"serial.writeString": "",
"serial.writeValue": "",
"serial.writeValue|param|name": "",
"serial.writeValue|param|value": ""
"pins.analogPitch|param|frequency": "TODO",
"pins.analogPitch|param|ms": "TODO",
"pins.analogSetPitchPin|param|name": "TODO"
}

View File

@ -1,46 +1,21 @@
{
"LedSpriteProperty.Brightness|block": "luminosité",
"Math.randomBoolean|block": "choisir au hasard vrai ou faux",
"Math|block": "Maths",
<<<<<<< HEAD
"String.fromCharCode|block": "texte du code de charactère %code",
=======
"String.charAt|block": "",
"String.compare|block": "",
"String.concat|block": "",
"String.fromCharCode|block": "texte du code de charactère %code",
"String.isEmpty|block": "",
"String.length|block": "",
"String.substr|block": "",
>>>>>>> microbit/master
"String|block": "Texte",
"basic.clearScreen|block": "effacer lécran",
"basic.forever|block": "toujours",
"basic.pause|block": "pause (ms) %pause",
"basic.showLeds|block": "montrer LEDs",
"basic.showNumber|block": "montrer|nombre %number",
"basic.showString|block": "montrer|texte %text",
"basic.showString|block": "afficher|texte %text",
"basic|block": "base",
<<<<<<< HEAD
"control.inBackground|block": "exécuter en arrière-plan",
=======
"control.deviceName|block": "",
"control.deviceSerialNumber|block": "",
"control.eventSourceId|block": "",
"control.eventTimestamp|block": "",
"control.eventValueId|block": "",
"control.eventValue|block": "",
"control.inBackground|block": "exécuter en arrière-plan",
"control.onEvent|block": "",
"control.raiseEvent|block": "",
>>>>>>> microbit/master
"control.reset|block": "remise à zéro",
"control.waitMicros|block": "attendre (µs) %micros",
"control|block": "contrôle",
"game.addScore|block": "changer le score par|%points",
<<<<<<< HEAD
=======
"game.createSprite|block": "",
>>>>>>> microbit/master
"game.gameOver|block": "fin du jeu",
"game.score|block": "score",
"game.startCountdown|block": "commencer compte à rebours|(ms) %duration",
@ -82,32 +57,15 @@
"music.tempo|block": "tempo (bpm)",
"music|block": "musique",
"pins.analogReadPin|block": "lire|la broche analogique %name",
"pins.analogSetPeriod|block": "",
"pins.analogWritePin|block": "",
"pins.digitalReadPin|block": "lire en numérique|broche %name",
<<<<<<< HEAD
"pins.digitalWritePin|block": "écrire en numérique|la broche %name|%value",
=======
"pins.digitalWritePin|block": "écrire en numérique|la broche %name|à %value",
>>>>>>> microbit/master
"pins.i2cReadNumber|block": "i2c lire nombre|à ladresse %address|de format %format=i2c_sizeof",
"pins.i2cWriteNumber|block": "i2c écrire nombre|à ladresse %address|avec value %value|de format %format=i2c_sizeof",
"pins.map|block": "",
"pins.onPulsed|block": "lorsque|la broche %pin|est pulsée %pulse",
"pins.pulseDuration|block": "durée de limpulsion (µs)",
<<<<<<< HEAD
=======
"pins.pulseIn|block": "",
>>>>>>> microbit/master
"pins.servoSetPulse|block": "",
"pins.servoWritePin|block": "servo écrire|broche %name|à %value",
"pins.setPull|block": "",
"pins.spiWrite|block": "spi écrire %value",
"pins|block": "broches",
<<<<<<< HEAD
=======
"serial.delimiters|block": "",
>>>>>>> microbit/master
"serial.readLine|block": "série|lire ligne",
"serial.readUntil|block": "série|lire jusque %delimiter=serial_delimiter_conv",
"serial.redirect|block": "série|rediriger vers|TX %tx|RX %rx|au débit en baudes %rate",
@ -125,11 +83,6 @@
"{id:category}Math": "Maths",
"{id:category}Music": "Musique",
"{id:category}Pins": "Broches",
<<<<<<< HEAD
"{id:category}Serial": "Communication Série"
=======
"{id:category}Serial": "Communication Série",
"{id:category}String": "Texte",
"{id:category}Text": ""
>>>>>>> microbit/master
"{id:category}String": "Texte"
}

View File

@ -0,0 +1,5 @@
{
"Math.abs": "Returnerar absolutbeloppet av ett tal (värdet utan hänsyn till huruvida det är positivt eller negativt). \nTill exempel är absolutbeloppet av -5 detsamma som absolutbeloppet av 5.",
"Math.max": "Returnerar det större av två givna numeriska uttryck.",
"Math.min": "Returnerar det mindre av två givna numeriska uttryck."
}

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
/**

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
// keep in sync with github/pxt/pxtsim/libgeneric.ts
enum class NumberFormat {

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
/**
* How to create the event.

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
#include <limits.h>

1
libs/core/dal.d.ts vendored
View File

@ -431,6 +431,7 @@ declare const enum DAL {
MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE = 400,
MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE = 400,
MICROBIT_ACCELEROMETER_2G_TOLERANCE = 2048,
MICROBIT_ACCELEROMETER_3G_TOLERANCE = 3072,
MICROBIT_ACCELEROMETER_6G_TOLERANCE = 6144,
MICROBIT_ACCELEROMETER_8G_TOLERANCE = 8192,
MICROBIT_ACCELEROMETER_GESTURE_DAMPING = 5,

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

@ -266,37 +266,33 @@ declare namespace motors {
P0 = 7, // MICROBIT_ID_IO_P0
P1 = 8, // MICROBIT_ID_IO_P1
P2 = 9, // MICROBIT_ID_IO_P2
P3 = 10, // MICROBIT_ID_IO_P3
P4 = 11, // MICROBIT_ID_IO_P4
P5 = 12, // MICROBIT_ID_IO_P5
P6 = 13, // MICROBIT_ID_IO_P6
P7 = 14, // MICROBIT_ID_IO_P7
//P8 = MICROBIT_ID_IO_P8,
P9 = 16, // MICROBIT_ID_IO_P9
P10 = 17, // MICROBIT_ID_IO_P10
P11 = 18, // MICROBIT_ID_IO_P11
//P12 = MICROBIT_ID_IO_P12,
//P13 = MICROBIT_ID_IO_P13,
//P14 = MICROBIT_ID_IO_P14,
//P15 = MICROBIT_ID_IO_P15,
P3 = 40, // CALLIOPE_ID_IO_P22
C4 = 10, // MICROBIT_ID_IO_P3
C5 = 11, // MICROBIT_ID_IO_P4
C6 = 17, // MICROBIT_ID_IO_P10
C7 = 34, // CALLIOPE_ID_IO_P7
C8 = 35, // CALLIOPE_ID_IO_P8
C9 = 36, // CALLIOPE_ID_IO_P9
C10 = 16, // MICROBIT_ID_IO_P9
C11 = 14, // MICROBIT_ID_IO_P7
C12 = 13, // MICROBIT_ID_IO_P6
C13 = 37, // CALLIOPE_ID_IO_P13
C14 = 38, // CALLIOPE_ID_IO_P14
C15 = 39, // CALLIOPE_ID_IO_P15
//P16 = MICROBIT_ID_IO_P16,
P19 = 24, // MICROBIT_ID_IO_P19
P20 = 25, // MICROBIT_ID_IO_P20
P28 = 41, // CALLIOPE_ID_IO_P28
P29 = 42, // CALLIOPE_ID_IO_P29
P30 = 43, // CALLIOPE_ID_IO_P30
C19 = 24, // MICROBIT_ID_IO_P19
C20 = 25, // MICROBIT_ID_IO_P20
}
declare enum AnalogPin {
P0 = 7, // MICROBIT_ID_IO_P0
//P0 = MICROBIT_ID_IO_P0, -- does not work analogue
P1 = 8, // MICROBIT_ID_IO_P1
P2 = 9, // MICROBIT_ID_IO_P2
P3 = 10, // MICROBIT_ID_IO_P3
P4 = 11, // MICROBIT_ID_IO_P4
P10 = 17, // MICROBIT_ID_IO_P10
P29 = 42, // CALLIOPE_ID_IO_P29
P30 = 43, // CALLIOPE_ID_IO_P30
//P3 = CALLIOPE_ID_IO_P22, -- does not work analogue
C4 = 10, // MICROBIT_ID_IO_P3
C5 = 11, // MICROBIT_ID_IO_P4
C6 = 17, // MICROBIT_ID_IO_P10
}

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
/**
* Creation, manipulation and display of LED images.
@ -61,7 +61,7 @@ namespace ImageMethods {
/**
* Scrolls an image .
* @param frameOffset x offset moved on each animation step, eg: 5, 1, -1
* @param frameOffset x offset moved on each animation step, eg: 1, 2, 5
* @param interval time between each animation step in milli seconds, eg: 200
*/
//% help=images/show-image weight=79 async blockNamespace=images
@ -69,10 +69,7 @@ namespace ImageMethods {
//% parts="ledmatrix"
void scrollImage(Image id, int frameOffset, int interval) {
MicroBitImage i(id);
if (i.getWidth() <= 5)
showImage(id, 0);
else
uBit.display.animate(i, interval, frameOffset, 0);
uBit.display.animate(i, interval, frameOffset, MICROBIT_DISPLAY_WIDTH - 1);
}

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
enum class Button {
A = MICROBIT_ID_BUTTON_A,

View File

@ -1,12 +0,0 @@
#include "pxt.h"
#include "ManagedBuffer.h"
using namespace pxt;
MicroBitPin *getPin(int id);
typedef ImageData* Image;
typedef BufferData* Buffer;
namespace pxt {
uint32_t programSize();
uint32_t afterProgramPage();
}

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
enum class DisplayMode_ {
//% block="black and white"

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
enum MotorCommand {
//% block=coast

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
namespace music {
/**
@ -8,21 +8,10 @@ namespace music {
*/
//% help=music/play-tone weight=90
//% blockId=device_play_note block="play|tone %note=device_note|for %duration=device_beat" icon="\uf025" blockGap=8
//% parts="speaker"
//% parts="speaker" async
void playTone(int freqency, int ms) {
uBit.soundmotor.soundOn(freqency);
if(ms > 0) uBit.sleep(ms);
uBit.soundmotor.soundOff();
}
/**
* Plays a tone through ``speaker``.
* @param frequency pitch of the tone to play in Hertz (Hz)
*/
//% help=music/ring-tone weight=80
//% blockId=device_ring block="ring tone (Hz)|%note=device_note" icon="\uf025" blockGap=8
//% parts="speaker"
void ringTone(int frequency) {
playTone(frequency, 0);
}
}

View File

@ -140,6 +140,16 @@ namespace music {
playTone(0, ms);
}
/**
* Plays a tone through ``speaker``.
* @param frequency pitch of the tone to play in Hertz (Hz)
*/
//% help=music/ring-tone weight=80
//% blockId=device_ring block="ring tone (Hz)|%note=device_note" icon="\uf025" blockGap=8
//% parts="speaker" async
export function ringTone(frequency: number) {
playTone(frequency, 0);
}
/**
* Gets the frequency of a note.

View File

@ -1,39 +1,35 @@
#include "ksbit.h"
#include "pxt.h"
enum class DigitalPin {
P0 = MICROBIT_ID_IO_P0,
P1 = MICROBIT_ID_IO_P1,
P2 = MICROBIT_ID_IO_P2,
P3 = MICROBIT_ID_IO_P3,
P4 = MICROBIT_ID_IO_P4,
P5 = MICROBIT_ID_IO_P5,
P6 = MICROBIT_ID_IO_P6,
P7 = MICROBIT_ID_IO_P7,
//P8 = MICROBIT_ID_IO_P8,
P9 = MICROBIT_ID_IO_P9,
P10 = MICROBIT_ID_IO_P10,
P11 = MICROBIT_ID_IO_P11,
//P12 = MICROBIT_ID_IO_P12,
//P13 = MICROBIT_ID_IO_P13,
//P14 = MICROBIT_ID_IO_P14,
//P15 = MICROBIT_ID_IO_P15,
P0 = MICROBIT_ID_IO_P0, // edge connector 0
P1 = MICROBIT_ID_IO_P1, // edge connector 1
P2 = MICROBIT_ID_IO_P2, // edge connector 2
P3 = CALLIOPE_ID_IO_P22, // edge connector 3
C4 = MICROBIT_ID_IO_P3, // LED matrix C1
C5 = MICROBIT_ID_IO_P4, // LED matrix C2
C6 = MICROBIT_ID_IO_P10, // LED matrix C3
C7 = CALLIOPE_ID_IO_P7, // LED matrix C4
C8 = CALLIOPE_ID_IO_P8, // LED matrix C5
C9 = CALLIOPE_ID_IO_P9, // LED matrix C6
C10 = MICROBIT_ID_IO_P9, // LED matrix C7
C11 = MICROBIT_ID_IO_P7, // LED matrix C8
C12 = MICROBIT_ID_IO_P6, // LED matrix C9
C13 = CALLIOPE_ID_IO_P13, // LED matrix R1
C14 = CALLIOPE_ID_IO_P14, // LED matrix R2
C15 = CALLIOPE_ID_IO_P15, // LED matrix R3
//P16 = MICROBIT_ID_IO_P16,
P19 = MICROBIT_ID_IO_P19,
P20 = MICROBIT_ID_IO_P20,
P28 = CALLIOPE_ID_IO_P28,
P29 = CALLIOPE_ID_IO_P29,
P30 = CALLIOPE_ID_IO_P30
C19 = MICROBIT_ID_IO_P19, // SCL
C20 = MICROBIT_ID_IO_P20 // SDA
};
enum class AnalogPin {
P0 = MICROBIT_ID_IO_P0,
P1 = MICROBIT_ID_IO_P1,
P2 = MICROBIT_ID_IO_P2,
P3 = MICROBIT_ID_IO_P3,
P4 = MICROBIT_ID_IO_P4,
P10 = MICROBIT_ID_IO_P10,
P29 = CALLIOPE_ID_IO_P29,
P30 = CALLIOPE_ID_IO_P30
//P0 = MICROBIT_ID_IO_P0, -- does not work analogue
P1 = MICROBIT_ID_IO_P1, // edge connector 1
P2 = MICROBIT_ID_IO_P2, // edge connector 2
//P3 = CALLIOPE_ID_IO_P22, -- does not work analogue
C4 = MICROBIT_ID_IO_P3,
C5 = MICROBIT_ID_IO_P4,
C6 = MICROBIT_ID_IO_P10,
};
enum class PulseValue {

481
libs/core/pxt.cpp Normal file
View File

@ -0,0 +1,481 @@
#include "pxt.h"
#include <map>
MicroBit uBit;
namespace pxt {
int incr(uint32_t e)
{
if (e) {
if (hasVTable(e))
((RefObject*)e)->ref();
else
((RefCounted*)e)->incr();
}
return e;
}
void decr(uint32_t e)
{
if (e) {
if (hasVTable(e))
((RefObject*)e)->unref();
else
((RefCounted*)e)->decr();
}
}
Action mkAction(int reflen, int totallen, int startptr)
{
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
check(bytecode[startptr] == 0xffff, ERR_INVALID_BINARY_HEADER, 3);
check(bytecode[startptr + 1] == 0, ERR_INVALID_BINARY_HEADER, 4);
uint32_t tmp = (uint32_t)&bytecode[startptr];
if (totallen == 0) {
return tmp; // no closure needed
}
void *ptr = ::operator new(sizeof(RefAction) + totallen * sizeof(uint32_t));
RefAction *r = new (ptr) RefAction();
r->len = totallen;
r->reflen = reflen;
r->func = (ActionCB)((tmp + 4) | 1);
memset(r->fields, 0, r->len * sizeof(uint32_t));
return (Action)r;
}
uint32_t runAction3(Action a, int arg0, int arg1, int arg2)
{
if (hasVTable(a))
return ((RefAction*)a)->runCore(arg0, arg1, arg2);
else {
check(*(uint16_t*)a == 0xffff, ERR_INVALID_BINARY_HEADER, 4);
return ((ActionCB)((a + 4) | 1))(NULL, arg0, arg1, arg2);
}
}
uint32_t runAction2(Action a, int arg0, int arg1)
{
return runAction3(a, arg0, arg1, 0);
}
uint32_t runAction1(Action a, int arg0)
{
return runAction3(a, arg0, 0, 0);
}
uint32_t runAction0(Action a)
{
return runAction3(a, 0, 0, 0);
}
RefRecord* mkClassInstance(int vtableOffset)
{
VTable *vtable = (VTable*)&bytecode[vtableOffset];
intcheck(vtable->methods[0] == &RefRecord_destroy, ERR_SIZE, 3);
intcheck(vtable->methods[1] == &RefRecord_print, ERR_SIZE, 4);
void *ptr = ::operator new(vtable->numbytes);
RefRecord *r = new (ptr) RefRecord(PXT_VTABLE_TO_INT(vtable));
memset(r->fields, 0, vtable->numbytes - sizeof(RefRecord));
return r;
}
uint32_t RefRecord::ld(int idx)
{
//intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, ERR_OUT_OF_BOUNDS, 1);
return fields[idx];
}
uint32_t RefRecord::ldref(int idx)
{
//printf("LD %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
//intcheck(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 2);
uint32_t tmp = fields[idx];
incr(tmp);
return tmp;
}
void RefRecord::st(int idx, uint32_t v)
{
//intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, ERR_OUT_OF_BOUNDS, 3);
fields[idx] = v;
}
void RefRecord::stref(int idx, uint32_t v)
{
//printf("ST %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
//intcheck(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 4);
decr(fields[idx]);
fields[idx] = v;
}
void RefObject::destroy() {
((RefObjectMethod)getVTable()->methods[0])(this);
}
void RefObject::print() {
((RefObjectMethod)getVTable()->methods[1])(this);
}
void RefRecord_destroy(RefRecord *r) {
auto tbl = r->getVTable();
uint8_t *refmask = (uint8_t*)&tbl->methods[tbl->userdata & 0xff];
int len = (tbl->numbytes >> 2) - 1;
for (int i = 0; i < len; ++i) {
if (refmask[i]) decr(r->fields[i]);
r->fields[i] = 0;
}
//RefRecord is allocated using placement new
r->~RefRecord();
::operator delete(r);
}
void RefRecord_print(RefRecord *r)
{
printf("RefRecord %p r=%d size=%d bytes\n", r, r->refcnt, r->getVTable()->numbytes);
}
void RefCollection::push(uint32_t x) {
if (isRef()) incr(x);
data.push_back(x);
}
uint32_t RefCollection::getAt(int x) {
if (in_range(x)) {
uint32_t tmp = data.at(x);
if (isRef()) incr(tmp);
return tmp;
}
else {
error(ERR_OUT_OF_BOUNDS);
return 0;
}
}
void RefCollection::removeAt(int x) {
if (!in_range(x))
return;
if (isRef()) decr(data.at(x));
data.erase(data.begin()+x);
}
void RefCollection::setAt(int x, uint32_t y) {
if (!in_range(x))
return;
if (isRef()) {
decr(data.at(x));
incr(y);
}
data.at(x) = y;
}
int RefCollection::indexOf(uint32_t x, int start) {
if (!in_range(start))
return -1;
if (isString()) {
StringData *xx = (StringData*)x;
for (uint32_t i = start; i < data.size(); ++i) {
StringData *ee = (StringData*)data.at(i);
if (xx->len == ee->len && memcmp(xx->data, ee->data, xx->len) == 0)
return (int)i;
}
} else {
for (uint32_t i = start; i < data.size(); ++i)
if (data.at(i) == x)
return (int)i;
}
return -1;
}
int RefCollection::removeElement(uint32_t x) {
int idx = indexOf(x, 0);
if (idx >= 0) {
removeAt(idx);
return 1;
}
return 0;
}
namespace Coll0 {
PXT_VTABLE_BEGIN(RefCollection, 0, 0)
PXT_VTABLE_END
}
namespace Coll1 {
PXT_VTABLE_BEGIN(RefCollection, 1, 0)
PXT_VTABLE_END
}
namespace Coll3 {
PXT_VTABLE_BEGIN(RefCollection, 3, 0)
PXT_VTABLE_END
}
RefCollection::RefCollection(uint16_t flags) : RefObject(0) {
switch (flags) {
case 0:
vtable = PXT_VTABLE_TO_INT(&Coll0::RefCollection_vtable);
break;
case 1:
vtable = PXT_VTABLE_TO_INT(&Coll1::RefCollection_vtable);
break;
case 3:
vtable = PXT_VTABLE_TO_INT(&Coll3::RefCollection_vtable);
break;
default:
error(ERR_SIZE);
break;
}
}
void RefCollection::destroy()
{
if (this->isRef())
for (uint32_t i = 0; i < this->data.size(); ++i) {
decr(this->data[i]);
this->data[i] = 0;
}
this->data.resize(0);
delete this;
}
void RefCollection::print()
{
printf("RefCollection %p r=%d flags=%d size=%d [%p, ...]\n", this, refcnt, getFlags(), data.size(), data.size() > 0 ? data[0] : 0);
}
PXT_VTABLE_CTOR(RefAction) {}
// fields[] contain captured locals
void RefAction::destroy()
{
for (int i = 0; i < this->reflen; ++i) {
decr(fields[i]);
fields[i] = 0;
}
//RefAction is allocated using placement new
this->~RefAction();
::operator delete(this);
}
void RefAction::print()
{
printf("RefAction %p r=%d pc=0x%lx size=%d (%d refs)\n", this, refcnt, (const uint8_t*)func - (const uint8_t*)bytecode, len, reflen);
}
void RefLocal::print()
{
printf("RefLocal %p r=%d v=%d\n", this, refcnt, v);
}
void RefLocal::destroy()
{
delete this;
}
PXT_VTABLE_CTOR(RefLocal) {
v = 0;
}
PXT_VTABLE_CTOR(RefRefLocal) {
v = 0;
}
void RefRefLocal::print()
{
printf("RefRefLocal %p r=%d v=%p\n", this, refcnt, (void*)v);
}
void RefRefLocal::destroy()
{
decr(v);
delete this;
}
PXT_VTABLE_BEGIN(RefMap, 0, RefMapMarker)
PXT_VTABLE_END
RefMap::RefMap() : PXT_VTABLE_INIT(RefMap) {}
void RefMap::destroy() {
for (unsigned i = 0; i < data.size(); ++i) {
if (data[i].key & 1) {
decr(data[i].val);
}
data[i].val = 0;
}
data.resize(0);
delete this;
}
int RefMap::findIdx(uint32_t key) {
for (unsigned i = 0; i < data.size(); ++i) {
if (data[i].key >> 1 == key)
return i;
}
return -1;
}
void RefMap::print()
{
printf("RefMap %p r=%d size=%d\n", this, refcnt, data.size());
}
#ifdef DEBUG_MEMLEAKS
std::set<RefObject*> allptrs;
void debugMemLeaks()
{
printf("LIVE POINTERS:\n");
for(std::set<RefObject*>::iterator itr = allptrs.begin();itr!=allptrs.end();itr++)
{
(*itr)->print();
}
printf("\n");
}
#else
void debugMemLeaks() {}
#endif
// ---------------------------------------------------------------------------
// An adapter for the API expected by the run-time.
// ---------------------------------------------------------------------------
map<pair<int, int>, Action> handlersMap;
MicroBitEvent lastEvent;
// We have the invariant that if [dispatchEvent] is registered against the DAL
// for a given event, then [handlersMap] contains a valid entry for that
// event.
void dispatchEvent(MicroBitEvent e) {
lastEvent = e;
Action curr = handlersMap[{ e.source, e.value }];
if (curr)
runAction1(curr, e.value);
curr = handlersMap[{ e.source, MICROBIT_EVT_ANY }];
if (curr)
runAction1(curr, e.value);
}
void registerWithDal(int id, int event, Action a) {
Action prev = handlersMap[{ id, event }];
if (prev)
decr(prev);
else
uBit.messageBus.listen(id, event, dispatchEvent);
incr(a);
handlersMap[{ id, event }] = a;
}
void fiberDone(void *a)
{
decr((Action)a);
release_fiber();
}
void runInBackground(Action a) {
if (a != 0) {
incr(a);
create_fiber((void(*)(void*))runAction0, (void*)a, fiberDone);
}
}
void error(ERROR code, int subcode)
{
printf("Error: %d [%d]\n", code, subcode);
uBit.panic(42);
}
uint16_t *bytecode;
uint32_t *globals;
int numGlobals;
uint32_t *allocate(uint16_t sz)
{
uint32_t *arr = new uint32_t[sz];
memset(arr, 0, sz * 4);
return arr;
}
void checkStr(bool cond, const char *msg)
{
if (!cond) {
while (true) {
uBit.display.scroll(msg, 100);
uBit.sleep(100);
}
}
}
int templateHash()
{
return ((int*)bytecode)[4];
}
int programHash()
{
return ((int*)bytecode)[6];
}
int getNumGlobals()
{
return bytecode[16];
}
void exec_binary(int32_t *pc)
{
// XXX re-enable once the calibration code is fixed and [editor/embedded.ts]
// properly prepends a call to [internal_main].
// ::touch_develop::internal_main();
// unique group for radio based on source hash
// ::touch_develop::micro_bit::radioDefaultGroup = programHash();
// repeat error 4 times and restart as needed
microbit_panic_timeout(4);
int32_t ver = *pc++;
checkStr(ver == 0x4209, ":( Bad runtime version");
bytecode = *((uint16_t**)pc++); // the actual bytecode is here
globals = allocate(getNumGlobals());
// just compare the first word
checkStr(((uint32_t*)bytecode)[0] == 0x923B8E70 &&
templateHash() == *pc,
":( Failed partial flash");
uint32_t startptr = (uint32_t)bytecode;
startptr += 48; // header
startptr |= 1; // Thumb state
((uint32_t (*)())startptr)();
#ifdef DEBUG_MEMLEAKS
pxt::debugMemLeaks();
#endif
return;
}
void start()
{
exec_binary((int32_t*)functionsAndBytecode);
}
}
// vim: ts=2 sw=2 expandtab

341
libs/core/pxt.h Normal file
View File

@ -0,0 +1,341 @@
#ifndef __PXT_H
#define __PXT_H
// #define DEBUG_MEMLEAKS 1
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include "MicroBit.h"
#include "MicroBitImage.h"
#include "ManagedString.h"
#include "ManagedType.h"
#include "ManagedBuffer.h"
#define printf(...) uBit.serial.printf(__VA_ARGS__)
// #define printf(...)
#define intcheck(...) check(__VA_ARGS__)
//#define intcheck(...) do {} while (0)
#include <stdio.h>
#include <string.h>
#include <vector>
#include <stdint.h>
#ifdef DEBUG_MEMLEAKS
#include <set>
#endif
extern MicroBit uBit;
namespace pxt {
typedef uint32_t Action;
typedef uint32_t ImageLiteral;
typedef enum {
ERR_INVALID_BINARY_HEADER = 5,
ERR_OUT_OF_BOUNDS = 8,
ERR_REF_DELETED = 7,
ERR_SIZE = 9,
} ERROR;
extern const uint32_t functionsAndBytecode[];
extern uint32_t *globals;
extern uint16_t *bytecode;
class RefRecord;
// Utility functions
extern MicroBitEvent lastEvent;
void registerWithDal(int id, int event, Action a);
void runInBackground(Action a);
uint32_t runAction3(Action a, int arg0, int arg1, int arg2);
uint32_t runAction2(Action a, int arg0, int arg1);
uint32_t runAction1(Action a, int arg0);
uint32_t runAction0(Action a);
Action mkAction(int reflen, int totallen, int startptr);
void error(ERROR code, int subcode = 0);
void exec_binary(uint16_t *pc);
void start();
void debugMemLeaks();
// allocate [sz] words and clear them
uint32_t *allocate(uint16_t sz);
int templateHash();
int programHash();
uint32_t programSize();
uint32_t afterProgramPage();
int getNumGlobals();
RefRecord* mkClassInstance(int vtableOffset);
// The standard calling convention is:
// - when a pointer is loaded from a local/global/field etc, and incr()ed
// (in other words, its presence on stack counts as a reference)
// - after a function call, all pointers are popped off the stack and decr()ed
// This does not apply to the RefRecord and st/ld(ref) methods - they unref()
// the RefRecord* this.
int incr(uint32_t e);
void decr(uint32_t e);
inline void *ptrOfLiteral(int offset)
{
return &bytecode[offset];
}
inline ImageData* imageBytes(int offset)
{
return (ImageData*)(void*)&bytecode[offset];
}
// Checks if object has a VTable, or if its RefCounted* from the runtime.
inline bool hasVTable(uint32_t e)
{
return (*((uint32_t*)e) & 1) == 0;
}
inline void check(int cond, ERROR code, int subcode = 0)
{
if (!cond) error(code, subcode);
}
class RefObject;
#ifdef DEBUG_MEMLEAKS
extern std::set<RefObject*> allptrs;
#endif
typedef void (*RefObjectMethod)(RefObject *self);
typedef void *PVoid;
typedef void **PPVoid;
const PPVoid RefMapMarker = (PPVoid)(void*)43;
struct VTable {
uint16_t numbytes; // in the entire object, including the vtable pointer
uint16_t userdata;
PVoid *ifaceTable;
PVoid methods[2]; // we only use up to two methods here; pxt will generate more
// refmask sits at &methods[nummethods]
};
const int vtableShift = 2;
// A base abstract class for ref-counted objects.
class RefObject
{
public:
uint16_t refcnt;
uint16_t vtable;
RefObject(uint16_t vt)
{
refcnt = 2;
vtable = vt;
#ifdef DEBUG_MEMLEAKS
allptrs.insert(this);
#endif
}
inline VTable *getVTable() {
return (VTable*)(vtable << vtableShift);
}
void destroy();
void print();
// Call to disable pointer tracking on the current instance (in destructor or some other hack)
inline void untrack() {
#ifdef DEBUG_MEMLEAKS
allptrs.erase(this);
#endif
}
// Increment/decrement the ref-count. Decrementing to zero deletes the current object.
inline void ref()
{
check(refcnt > 0, ERR_REF_DELETED);
//printf("INCR "); this->print();
refcnt += 2;
}
inline void unref()
{
//printf("DECR "); this->print();
refcnt -= 2;
if (refcnt == 0) {
destroy();
}
}
};
// A ref-counted collection of either primitive or ref-counted objects (String, Image,
// user-defined record, another collection)
class RefCollection
: public RefObject
{
public:
// 1 - collection of refs (need decr)
// 2 - collection of strings (in fact we always have 3, never 2 alone)
inline uint32_t getFlags() { return getVTable()->userdata; }
inline bool isRef() { return getFlags() & 1; }
inline bool isString() { return getFlags() & 2; }
std::vector<uint32_t> data;
RefCollection(uint16_t f);
inline bool in_range(int x) {
return (0 <= x && x < (int)data.size());
}
inline int length() { return data.size(); }
void destroy();
void print();
void push(uint32_t x);
uint32_t getAt(int x);
void removeAt(int x);
void setAt(int x, uint32_t y);
int indexOf(uint32_t x, int start);
int removeElement(uint32_t x);
};
struct MapEntry {
uint32_t key;
uint32_t val;
};
class RefMap
: public RefObject
{
public:
std::vector<MapEntry> data;
RefMap();
void destroy();
void print();
int findIdx(uint32_t key);
};
// A ref-counted, user-defined JS object.
class RefRecord
: public RefObject
{
public:
// The object is allocated, so that there is space at the end for the fields.
uint32_t fields[];
RefRecord(uint16_t v) : RefObject(v) {}
uint32_t ld(int idx);
uint32_t ldref(int idx);
void st(int idx, uint32_t v);
void stref(int idx, uint32_t v);
};
// these are needed when constructing vtables for user-defined classes
void RefRecord_destroy(RefRecord *r);
void RefRecord_print(RefRecord *r);
class RefAction;
typedef uint32_t (*ActionCB)(uint32_t *captured, uint32_t arg0, uint32_t arg1, uint32_t arg2);
// Ref-counted function pointer. It's currently always a ()=>void procedure pointer.
class RefAction
: public RefObject
{
public:
// This is the same as for RefRecord.
uint8_t len;
uint8_t reflen;
ActionCB func; // The function pointer
// fields[] contain captured locals
uint32_t fields[];
void destroy();
void print();
RefAction();
inline void stCore(int idx, uint32_t v)
{
//printf("ST [%d] = %d ", idx, v); this->print();
intcheck(0 <= idx && idx < len, ERR_OUT_OF_BOUNDS, 10);
intcheck(fields[idx] == 0, ERR_OUT_OF_BOUNDS, 11); // only one assignment permitted
fields[idx] = v;
}
inline uint32_t runCore(int arg0, int arg1, int arg2) // internal; use runAction*() functions
{
this->ref();
uint32_t r = this->func(&this->fields[0], arg0, arg1, arg2);
this->unref();
return r;
}
};
// These two are used to represent locals written from inside inline functions
class RefLocal
: public RefObject
{
public:
uint32_t v;
void destroy();
void print();
RefLocal();
};
class RefRefLocal
: public RefObject
{
public:
uint32_t v;
void destroy();
void print();
RefRefLocal();
};
}
using namespace pxt;
MicroBitPin *getPin(int id);
typedef ImageData* Image;
typedef BufferData* Buffer;
// The ARM Thumb generator in the JavaScript code is parsing
// the hex file and looks for the magic numbers as present here.
//
// Then it fetches function pointer addresses from there.
#define PXT_SHIMS_BEGIN \
namespace pxt { \
const uint32_t functionsAndBytecode[] __attribute__((aligned(0x20))) = { \
0x08010801, 0x42424242, 0x08010801, 0x8de9d83e,
#define PXT_SHIMS_END }; }
#pragma GCC diagnostic ignored "-Wpmf-conversions"
#define PXT_VTABLE_TO_INT(vt) ((uint32_t)(vt) >> vtableShift)
#define PXT_VTABLE_BEGIN(classname, flags, iface) \
const VTable classname ## _vtable \
__attribute__((aligned(1 << vtableShift))) \
= { \
sizeof(classname), \
flags, \
iface, \
{ \
(void*)&classname::destroy, \
(void*)&classname::print,
#define PXT_VTABLE_END } };
#define PXT_VTABLE_INIT(classname) \
RefObject(PXT_VTABLE_TO_INT(&classname ## _vtable))
#define PXT_VTABLE_CTOR(classname) \
PXT_VTABLE_BEGIN(classname, 0, 0) PXT_VTABLE_END \
classname::classname() : PXT_VTABLE_INIT(classname)
#endif
// vim: ts=2 sw=2 expandtab

View File

@ -4,11 +4,14 @@
"installedVersion": "tsmdvf",
"files": [
"README.md",
"ManagedBuffer.cpp",
"ManagedBuffer.h",
"pxt.cpp",
"pxt.h",
"dal.d.ts",
"enums.d.ts",
"shims.d.ts",
"pxt-core.d.ts",
"ksbit.h",
"core.cpp",
"pxt-helpers.ts",
"helpers.ts",
@ -49,4 +52,4 @@
}
}
}
}
}

View File

@ -185,7 +185,7 @@
"pinDistance": 65,
"pinLocations": [
{"x": 89, "y": 48},
{"x": 395, "y": 48} ]
{"x": 393, "y": 48} ]
},
"pinDefinitions": [
{ "target": "M_OUT1", "style": "croc", "orientation": "-Z"},

View File

@ -1,4 +1,4 @@
#include "ksbit.h"
#include "pxt.h"
enum SerialPin {
P0 = MICROBIT_ID_IO_P0,

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

@ -53,7 +53,7 @@ declare interface Image {
/**
* Scrolls an image .
* @param frameOffset x offset moved on each animation step, eg: 5, 1, -1
* @param frameOffset x offset moved on each animation step, eg: 1, 2, 5
* @param interval time between each animation step in milli seconds, eg: 200
*/
//% help=images/show-image weight=79 async blockNamespace=images
@ -554,17 +554,8 @@ declare namespace music {
*/
//% help=music/play-tone weight=90
//% blockId=device_play_note block="play|tone %note=device_note|for %duration=device_beat" icon="\uf025" blockGap=8
//% parts="speaker" shim=music::playTone
//% parts="speaker" async shim=music::playTone
function playTone(freqency: number, ms: number): void;
/**
* Plays a tone through ``speaker``.
* @param frequency pitch of the tone to play in Hertz (Hz)
*/
//% help=music/ring-tone weight=80
//% blockId=device_ring block="ring tone (Hz)|%note=device_note" icon="\uf025" blockGap=8
//% parts="speaker" shim=music::ringTone
function ringTone(frequency: number): void;
}
declare namespace pins {

View File

@ -1,4 +1,55 @@
{
"MesAlertEvent.DisplayToast|block": "display toast",
"MesAlertEvent.FindMyPhone|block": "find my phone",
"MesAlertEvent.PlayRingtone|block": "play ring tone",
"MesAlertEvent.PlaySound|block": "play sound",
"MesAlertEvent.RingAlarm2|block": "ring alarm 2",
"MesAlertEvent.RingAlarm3|block": "ring alarm 3",
"MesAlertEvent.RingAlarm4|block": "ring alarm 4",
"MesAlertEvent.RingAlarm5|block": "ring alarm 5",
"MesAlertEvent.RingAlarm6|block": "ring alarm 6",
"MesAlertEvent.RingAlarm|block": "ring alarm",
"MesAlertEvent.Vibrate|block": "vibrate",
"MesCameraEvent.LaunchPhotoMode|block": "launch photo mode",
"MesCameraEvent.LaunchVideoMode|block": "launch video mode",
"MesCameraEvent.StartVideoCapture|block": "start video capture",
"MesCameraEvent.StopPhotoMode|block": "stop photo mode",
"MesCameraEvent.StopVideoCapture|block": "stop video capture",
"MesCameraEvent.StopVideoMode|block": "stop video mode",
"MesCameraEvent.TakePhoto|block": "take photo",
"MesCameraEvent.ToggleFrontRear|block": "toggle front-rear",
"MesDeviceInfo.DisplayOff|block": "display off",
"MesDeviceInfo.DisplayOn|block": "display on",
"MesDeviceInfo.IncomingCall|block": "incoming call",
"MesDeviceInfo.IncomingMessage|block": "incoming message",
"MesDeviceInfo.OrientationLandscape|block": "orientation landscape",
"MesDeviceInfo.OrientationPortrait|block": "orientation portrait",
"MesDeviceInfo.Shaken|block": "shaken",
"MesDpadButtonInfo.ADown|block": "A down",
"MesDpadButtonInfo.AUp|block": "A up",
"MesDpadButtonInfo.BDown|block": "B down",
"MesDpadButtonInfo.BUp|block": "B up",
"MesDpadButtonInfo.CDown|block": "C down",
"MesDpadButtonInfo.CUp|block": "C up",
"MesDpadButtonInfo.DDown|block": "D down",
"MesDpadButtonInfo.DUp|block": "D up",
"MesDpadButtonInfo._1Down|block": "1 down",
"MesDpadButtonInfo._1Up|block": "1 up",
"MesDpadButtonInfo._2Down|block": "2 down",
"MesDpadButtonInfo._2Up|block": "2 up",
"MesDpadButtonInfo._3Down|block": "3 down",
"MesDpadButtonInfo._3Up|block": "3 up",
"MesDpadButtonInfo._4Down|block": "4 down",
"MesDpadButtonInfo._4Up|block": "4 up",
"MesRemoteControlEvent.forward|block": "forward",
"MesRemoteControlEvent.nextTrack|block": "next track",
"MesRemoteControlEvent.pause|block": "pause",
"MesRemoteControlEvent.play|block": "play",
"MesRemoteControlEvent.previousTrack|block": "previous track",
"MesRemoteControlEvent.rewind|block": "rewind",
"MesRemoteControlEvent.stop|block": "stop",
"MesRemoteControlEvent.volumeDown|block": "volume down",
"MesRemoteControlEvent.volumeUp|block": "volume up",
"devices.onGamepadButton|block": "on gamepad button|%NAME",
"devices.onNotified|block": "on notified|%event",
"devices.onSignalStrengthChanged|block": "on signal strength changed",

View File

@ -21,4 +21,4 @@
}
},
"installedVersion": "ljipgq"
}
}

View File

@ -0,0 +1,23 @@
{
"radio": "Daten mithilfe von Funk-Paketen übertragen",
"radio.onDataPacketReceived": "Registriert Funktionen, die ausgeführt werden, wenn das Radio ein Datenpaket empfängt. Entnimmt das empfangene Paket aus der Warteschlange des Radios.",
"radio.onDataReceived": "Registriert Code der ausgeführt wird, wenn ein Paket über Funk empfangen wird.",
"radio.receiveNumber": "Liest das nächste Paket aus der Funk-Warteschlange und gibt die Paketnummer oder 0 aus, wenn das Paket keine Nummer enthält.",
"radio.receiveString": "Liest das nächste Paket aus der Funk-Warteschlange und gibt die enthaltene Zeichenfolge oder die leere Zeichenfolge aus, wenn das Paket keine Zeichenfolge enthält.",
"radio.receivedNumber": "Extrahiert eine Zahl aus dem Inhalt des letzten Datenpakets, welches aus der Warteschlange des Radios (via ``Zahl empfangen``, ``Zeichenkette empfangen``, etc) entnommen wurde oder eine 0, wenn das Paket keine Zahl enthält.",
"radio.receivedSerial": "Extrahiert die Seriennummer des Calliope mini Senders aus dem Inhalt des letzten Datenpakets, welches aus der Warteschlange des Radios entnommen wurde oder eine 0, wenn der Absender keine Seriennummer gesendet hat.",
"radio.receivedSignalStrength": "Ruft den empfangenen Signalstärkeindikator (RSSI) aus dem letzten Paket aus der Funk-Warteschlange aus (via ``receiveNumber``, ``receiveString``, etc). Wird im Simulator nicht unterstützt.\nnamespace=radio",
"radio.receivedString": "Extrahiert die Zeichenkette aus dem Inhalt des letzten Datenpakets, welches aus der Warteschlange des Radios (via ``Zahl empfangen``, ``Zeichenkette empfangen``, etc) entnommen wurde oder eine leere Zeichenkette, wenn das Paket keine Zeichenkette enthält.",
"radio.receivedTime": "Extrahiert die Systemzeit des Absenders aus dem Inhalt des letzten Datenpakets, welches aus der Warteschlange des Radios (via ``Zahl empfangen``, ``Zeichenkette empfangen``, etc) entnommen wurde.",
"radio.sendNumber": "Überträgt eine Nummer über Funk an jeden angeschlossenen mini in der Gruppe.",
"radio.sendString": "Überträgt eine Zeichenfolge über Funk mit Seriennummer des Geräts und Laufzeit an jeden angeschlossenen mini in der Gruppe.",
"radio.sendValue": "Sendet ein Name / Wert-Paar zusammen mit der Seriennummer des Geräts und die Laufzeit auf alle angeschlossenen minis in der Gruppe.",
"radio.sendValue|param|value": "der numerische Wert",
"radio.setGroup": "Setzt die Gruppen-ID für Funkverbindungen. Ein mini kann nur ein Gruppen-ID hören.\nDie Gruppen-ID zwischen liegt zwischen 0 und 255, z.B. 1",
"radio.setTransmitPower": "Ändere die Ausgabeleistung des Senders auf den angegebenen Wert.",
"radio.setTransmitPower|param|power": "ein Wert im Bereich 0.. 7, wo 0 die niedrigste Leistung und 7 ist ist die höchste. z.B. 7",
"radio.setTransmitSerialNumber": "Stelle den Dunk so ein, dass die Seriennummer in jeder Nachricht übertragen wird.",
"radio.setTransmitSerialNumber|param|transmit": "Wert, der anzeigt, ob die Seriennummer übertragen wird, z.B. wahr",
"radio.writeReceivedPacketToSerial": "Schreibt das letzte empfangene Paket als JSON auf Seriell. Sollte in einem ´´onDataPacketReceived``-Callback aufgerufen werden.",
"radio.writeValueToSerial": "Liest das nächste Paket aus der Funk-Warteschlange und schreibt dieses als JSON auf Seriell."
}

View File

@ -0,0 +1,17 @@
{
"radio.onDataPacketReceived|block": "wenn Datenpaket empfangen",
"radio.onDataReceived|block": "Funk auf empfangenen Daten",
"radio.receiveNumber|block": "empfange Nummer über Funk",
"radio.receiveString|block": "empfange Zeichenfolge über Funk",
"radio.receivedSignalStrength|block": "über Funk empfangene Signalstärke",
"radio.sendNumber|block": "sende Nummer %value über Funk",
"radio.sendString|block": "sende Zeichenfolge %msg über Funk",
"radio.sendValue|block": "schicke |Wert %name|= %value über Funk",
"radio.setGroup|block": "setze Gruppe %ID über Funk",
"radio.setTransmitPower|block": "setze Übertragungsstärke %power über Funk",
"radio.setTransmitSerialNumber|block": "setze Übertragungsseriennummer %transmit über Funk",
"radio.writeReceivedPacketToSerial|block": "schreibe das über Funk übertragene Paket auf Seriell",
"radio.writeValueToSerial|block": "schreibe Wert über Funk auf Seriell",
"radio|block": "Funk",
"{id:category}Radio": "Funk"
}

View File

@ -6,7 +6,9 @@
"shims.d.ts",
"enums.d.ts",
"radio.cpp",
"radio.ts"
"radio.ts",
"_locales/de/radio-jsdoc-strings.json",
"_locales/de/radio-strings.json"
],
"public": true,
"dependencies": {

View File

@ -33,7 +33,7 @@ namespace radio {
* received packet from the radio queue.
*/
//% help=radio/on-data-packet-received
//% mutate=true
//% mutate=objectdestructuring
//% mutateText=Packet
//% mutateDefaults="receivedNumber;receivedString:name,receivedNumber:value;receivedString"
//% blockId=radio_on_packet block="on radio received" blockGap=8

View File

@ -1,6 +1,6 @@
{
"name": "pxt-calliope",
"version": "0.5.70",
"version": "0.7.5",
"description": "calliope target for PXT",
"keywords": [
"JavaScript",
@ -26,12 +26,14 @@
"docs/*/*.md",
"docs/*/*/*.md"
],
"main": "built/pxtrequire.js",
"typings": "built/pxtrequire.d.ts",
"devDependencies": {
"typescript": "^1.8.7"
},
"dependencies": {
"pxt-core": "0.5.62",
"typescript": "^1.8.7",
"less": "^2.6.0",
"semantic-ui-less": "^2.2.4"
},
"dependencies": {
"pxt-core": "0.7.9"
}
}

View File

@ -60,7 +60,7 @@
"autoRun": true,
"streams": true,
"aspectRatio": 1.13,
"parts": true,
"parts": false,
"partsAspectRatio": 0.69,
"boardDefinition": {
"visual": "calliope",
@ -99,43 +99,42 @@
"P1": "EDGE_P1",
"P2": "EDGE_P2",
"P3": "EDGE_P3",
"P4": "C_P4",
"P5": "C_P5",
"P6": "C_P6",
"P7": "C_P7",
"P8": "C_P8",
"P9": "C_P9",
"P10": "C_P10",
"P11": "C_P11",
"P12": "C_P12",
"P13": "C_P13",
"P14": "C_P14",
"P15": "C_P15",
"P16": "C_P16",
"P19": "C_P19",
"P20": "C_P20",
"C4": "C_P4",
"C5": "C_P5",
"C6": "C_P6",
"C7": "C_P7",
"C8": "C_P8",
"C9": "C_P9",
"C10": "C_P10",
"C11": "C_P11",
"C12": "C_P12",
"C13": "C_P13",
"C14": "C_P14",
"C15": "C_P15",
"C19": "C_P19",
"C20": "C_P20",
"EXT_PWR":"EXT_PWR",
"SPKR":"EXT_PWR",
"BTN_A": "BTN_A",
"BTN_B": "BTN_B",
"M_OUT1": "M_OUT1",
"M_OUT2": "M_OUT2"
"MOTOR1": "M_OUT1",
"MOTOR2": "M_OUT2"
},
"spiPins": {
"MOSI": "P15",
"MISO": "P14",
"SCK": "P13"
"MOSI": "C_P15",
"MISO": "C_P14",
"SCK": "C_P13"
},
"i2cPins": {
"SDA": "P20",
"SCL": "P19"
"SDA": "C_P20",
"SCL": "C_P19"
},
"analogInPins": [
"P0",
"P1",
"P2",
"P3",
"P10"
"C4",
"C5",
"C6"
],
"groundPins": [
"EDGE_GND"
@ -167,10 +166,10 @@
},
"compileService": {
"yottaTarget": "bbc-microbit-classic-gcc",
"yottaCorePackage": "pxt-calliope-core",
"githubCorePackage": "microsoft/pxt-calliope-core",
"gittag": "v0.5.13",
"serviceId": "calliope"
"yottaCorePackage": "microbit",
"githubCorePackage": "calliope-mini/microbit",
"gittag": "v1.0.2-calliope",
"serviceId": "microbit"
},
"serial": {
"manufacturerFilter": "^mbed$",
@ -192,6 +191,10 @@
"privacyUrl": "https://go.microsoft.com/fwlink/?LinkId=521839",
"termsOfUseUrl": "https://go.microsoft.com/fwlink/?LinkID=206977",
"githubUrl": "https://github.com/Microsoft/pxt-calliope",
"organization": "Microsoft",
"organizationUrl": "https://pxt.io/",
"organizationLogo": "./static/Microsoft-logo_rgb_c-gray.png",
"organizationWideLogo": "./static/Microsoft-logo_rgb_c-white.png",
"browserSupport": [
{
"name": "unsupported",
@ -219,7 +222,7 @@
"path": "/browsers/windows"
}
],
"boardName": "Calliope MINI",
"boardName": "Calliope mini",
"hideSideDocs": true,
"usbDocs": "/device/usb",
"usbHelp": [
@ -286,6 +289,16 @@
],
"invertedMenu": true,
"invertedToolbox": true,
"blocklyOptions": { }
"monacoToolbox": false,
"simAnimationEnter": "rotate in",
"simAnimationExit": "rotate out",
"blocklyOptions": {
"grid": {
"spacing": 45,
"length": 7,
"colour": "rgba(189, 195, 199, 0.30)",
"snap": false
}
}
}
}

View File

@ -199,8 +199,9 @@ namespace pxsim {
if (force < sq(DAL.MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE))
return DAL.MICROBIT_ACCELEROMETER_EVT_FREEFALL;
if (force > sq(DAL.MICROBIT_ACCELEROMETER_3G_TOLERANCE))
return DAL.MICROBIT_ACCELEROMETER_EVT_3G;
// TODO: fix this
//if (force > sq(DAL.MICROBIT_ACCELEROMETER_3G_TOLERANCE))
// return DAL.MICROBIT_ACCELEROMETER_EVT_3G;
if (force > sq(DAL.MICROBIT_ACCELEROMETER_6G_TOLERANCE))
return DAL.MICROBIT_ACCELEROMETER_EVT_6G;

View File

@ -1,222 +0,0 @@
let AWasPressed: boolean
let BWasPressed: boolean
let ABWasPressed: boolean
let wasShake: boolean
let scoreA: number
let scoreB: number
scoreA = 0
scoreB = 0
startIOMonitor()
let gameTime = getGameTime()
basic.showLeds(`
. . # . .
. . # . .
. . # # #
. . . . .
. . . . .
`)
while (!BWasPressed) {
basic.pause(100)
}
BWasPressed = false
playOneGame(gameTime)
showFinalScores(scoreA, scoreB)
function startIOMonitor() {
input.onButtonPressed(Button.A, () => {
AWasPressed = true
})
input.onButtonPressed(Button.B, () => {
BWasPressed = true
})
input.onButtonPressed(Button.AB, () => {
ABWasPressed = true
AWasPressed = false
BWasPressed = false
})
input.onShake(() => {
wasShake = true
})
AWasPressed = false
BWasPressed = false
ABWasPressed = false
wasShake = false
}
/**
* display score for A and B on same screen as a graphic
* this shows a tug of war line, in the middle if scores the same,
* Can cope with differences +/-10
* @param scoreA1 TODO
* @param scoreB1 TODO
*/
function showScore(scoreA1: number, scoreB1: number) {
let img = images.createImage(`
# . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . #
# . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . #
# . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . #
# . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . #
# . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . . #
`)
let diff = Math.clamp(-10, 10, scoreB1 - scoreA1)
diff = diff + 10
img.plotFrame(diff)
}
/**
* show digits 0..10
* @param digits TODO
*/
function showDigits(digits: number) {
digits = Math.clamp(0, 10, digits)
let img = images.createImage(`
. . # . . . . # . . . # # . . . # # . . . # . . . . # # # . . . # # . . # # # . . . # . . . . # . . # . . # .
. # . # . . # # . . . . . # . . . . # . . # . . . . # . . . . # . . . . . . # . . # . # . . # . # . # . # . #
. # . # . . . # . . . . # . . . . # . . . # # # . . . # # . . # # . . . . # . . . . # . . . . # # . # . # . #
. # . # . . . # . . . # . . . . . . # . . . # . . . . . # . . # . # . . # . . . . # . # . . . . # . # . # . #
. . # . . . # # # . . # # # . . # # . . . . # . . . # # . . . . # . . . # . . . . . # . . . # # . . # . . # .
`)
img.plotFrame(digits)
}
/**
* show time graphic for time remaining
* @param gameTime TODO
*/
function showTime(gameTime: number) {
let minutes = Math.clamp(0, 10, gameTime / 60)
let seconds = gameTime % 60
// divide seconds into 10 second stripes
let stripes = seconds / 10
let img = images.createImage(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . # . . . . # # . . . # # # . . # # # # . # # # # #
. . . . . # . . . . # # . . . # # # . . # # # # . # # # # #
`)
img.plotFrame(stripes)
// leave middle row blank
// display up to 10 dots in raster on top two rows
if (minutes > 0) {
for (let i = 0; i < minutes; i++) {
let y = i / 5
let x = i % 5
led.plot(x, y)
}
}
}
function getGameTime(): number {
let chosenGameTime = 7
showDigits(chosenGameTime)
while (!BWasPressed) {
if (AWasPressed) {
if (chosenGameTime < 10) {
chosenGameTime = chosenGameTime + 1
} else {
chosenGameTime = 1
}
showDigits(chosenGameTime)
AWasPressed = false
} else {
basic.pause(100)
}
}
BWasPressed = false
return chosenGameTime
}
function playOneGame(gameTime: number) {
let gameStartTime = input.runningTime()
let gameElapsedTime = 0
let gameTimeRemaining = gameTime * 60
let timeout = 0
let lastDisplayedTime = 0
showScore(scoreA, scoreB)
let state = "TIME"
while (gameTimeRemaining >= 0) {
// Tick the game time
gameElapsedTime = (input.runningTime() - gameStartTime) / 1000
gameTimeRemaining = gameTime * 60 - gameElapsedTime
// Handle any global events such as point buttons
if (AWasPressed) {
AWasPressed = false
scoreA = scoreA + 1
if (state != "LAST10") {
showScore(scoreA, scoreB)
state = "SCORE"
}
} else if (BWasPressed) {
BWasPressed = false
scoreB = scoreB + 1
if (state != "LAST10") {
showScore(scoreA, scoreB)
state = "SCORE"
}
}
// Handle global transitions
if (gameTimeRemaining <= 10 && state != "LAST10") {
state = "LAST10"
}
// Handle game states
if (state == "SCORE") {
if (wasShake) {
wasShake = false
showTime(gameTimeRemaining)
lastDisplayedTime = gameTimeRemaining
timeout = input.runningTime() + 5 * 1000
state = "TIME"
}
} else if (state == "TIME") {
if (input.runningTime() > timeout) {
showScore(scoreA, scoreB)
state = "SCORE"
}
} else if (state == "LAST10") {
if (gameTimeRemaining != lastDisplayedTime) {
showDigits(gameTimeRemaining)
lastDisplayedTime = gameTimeRemaining
}
}
basic.pause(100)
}
}
function showFinalScores(scoreA1: number, scoreB1: number) {
basic.showLeds(`
# . . . #
. # . # .
. . # . .
. # . # .
# . . . #
`)
while (true) {
if (AWasPressed) {
basic.showString("A", 150)
basic.showNumber(scoreA1, 150)
basic.showLeds(`
# . . . #
. # . # .
. . # . .
. # . # .
# . . . #
`)
AWasPressed = false
} else if (BWasPressed) {
basic.showString("B", 150)
basic.showNumber(scoreB1, 150)
basic.showLeds(`
# . . . #
. # . # .
. . # . .
. # . # .
# . . . #
`)
BWasPressed = false
} else {
basic.pause(100)
}
}
}

View File

@ -1,248 +0,0 @@
let speed: number
let cupCapacity: number
let maxMisses: number
let autoEmpty: boolean
let movement: boolean
let sensitivity: number
let cupX: number
let cupInverted: boolean
let highscore = 0
while (true) {
// configure game settings
// ##CHALLENGE1: reconfigure game
cupCapacity = 5
speed = 6
maxMisses = 3
autoEmpty = false
movement = true
sensitivity = 400
cupX = 2
// show the spash screen
// ##CHALLENGE 2: CHANGE SPLASH SCREEN
basic.showAnimation(`
. . . . . . . . . .
. . . . . . # . # .
. . . . . . . . . .
. # . # . . # . # .
. # # # . . # # # .
`, 400)
// Decide what to do based on which button is pressed
if (input.buttonIsPressed(Button.A)) {
let finalScore = playGame()
// ##CHALLENGE 3 ADD HIGH SCORE
if (finalScore > highscore) {
basic.showString("HIGH", 150)
highscore = finalScore
}
basic.showNumber(finalScore, 150)
} else if (input.buttonIsPressed(Button.B)) {
testMovement()
} else {
basic.pause(100)
}
}
function playGame(): number {
let cup = images.createImage(`
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . # . # . . . . . .
. . . . . . # # # . . . . . .
`)
let score = 0
let dropsInCup = 0
let misses = 0
let dropX = 0
let dropY = 0
let prevDropY = -1
let cupX1 = 2
let prevCupX = -1
let state = "NEWDROP"
startGame()
while (true) {
if (state == "NEWDROP") {
// create a new drop at a random position
dropX = Math.random(5)
dropY = 0
state = "RAINING"
} else if (state == "RAINING") {
// calculate new positions
cupX1 = getCupPosition()
let thisDropY = dropY / speed
// Only redraw the screen if something has changed (prevent flashing)
if (cupX1 != prevCupX || thisDropY != prevDropY) {
basic.clearScreen()
// draw cup
cup.showImage(7 - cupX1)
if (dropsInCup == cupCapacity) {
// a full cup
led.plot(cupX1, 3)
}
// draw drop
led.plot(dropX, thisDropY)
prevCupX = cupX1
prevDropY = thisDropY
}
basic.pause(100)
if (thisDropY >= 4) {
state = "ATCUP"
} else {
dropY = dropY + 1
}
if (cupInverted && dropsInCup >= cupCapacity) {
state = "EMPTYING"
}
} else if (state == "ATCUP") {
if (dropX == cupX1) {
state = "CATCH"
} else {
state = "MISS"
}
} else if (state == "MISS") {
// ##CHALLENGE: long beep on miss
beep(500)
misses = misses + 1
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . .
. . . . . . # . # . . . . . . . . . . .
. . . . . . # # # . . # . # . . . . . .
. # . # . . . . . . . # # # . . # . # .
. # # # . . . # . . . . . . . . # # # .
`, 400)
if (misses > maxMisses) {
state = "GAMEOVER"
} else {
state = "NEWDROP"
}
} else if (state == "CATCH") {
// ##CHALLENGE: short beep on catch
beep(200)
dropsInCup = dropsInCup + 1
basic.showAnimation(`
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. # # # . # . # . # . # . # .
. # # # . # # # # # . # # # .
`, 400)
if (dropsInCup == cupCapacity) {
state = "FULL"
score = score + 1
} else if (dropsInCup > cupCapacity) {
state = "OVERFLOW"
} else {
score = score + 1
state = "NEWDROP"
}
} else if (state == "FULL") {
basic.showAnimation(`
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . # # # . . . . . .
. # # # . . # # # . . # # # .
. # # # . . # # # . . # # # .
`, 400)
if (autoEmpty) {
state = "EMPTYING"
} else {
state = "NEWDROP"
}
} else if (state == "EMPTYING") {
if (cupInverted) {
basic.showAnimation(`
. . . . . . . . . . . . . . . . . # . . . . . . .
. . . . . . . . . . . . # . . . . . . . . . . . .
. . . . . . . # . . . . . . . . . . . . . . . . .
. # # # . . # . # . . # . # . . # . # . . # . # .
. # # # . . # # # . . # # # . . # # # . . # # # .
`, 400)
} else {
basic.showAnimation(`
. . . . . . . . . . . # # # . . # # # . . # # # . . # # # . . # # # . . . . . . . . . . .
. . . . . . # # . . . # # # . . # . # . . # . # . . # . # . . # . # . . # # . . . . . . .
. . . . . . # # . . . . . . . . . # . . . . . . . . . . . . . . . . . . # . . . . . . . .
. # # # . . # # . . . . . . . . . . . . . . # . . . . . . . . . . . . . # # . . . # . # .
. # # # . . . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . . . . # # # .
`, 400)
}
dropsInCup = 0
// ##CHALLENGE: Speed up on every level change
if (speed > 1) {
speed = speed - 1
}
state = "NEWDROP"
} else if (state == "OVERFLOW") {
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . # # # . . # . # . . . . . . . . . . . . . . . .
. # # # . . # # # . # # # # # # # # # # . # # # . . # # # .
. # # # . . # # # . . # # # . . # # # . # # # # # . # # # .
`, 400)
state = "GAMEOVER"
} else if (state == "GAMEOVER") {
// ##CHALLENGE: Make a sound on game over
beep(700)
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . # . # . . . . . . . . . . . . # . # . . . . . .
. . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . # . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. # . # . . . . . . . # # # . # # # # # . # . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. # # # . # # # # # . # . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, 400)
break
}
}
return score
}
function testMovement() {
while (!input.buttonIsPressed(Button.A)) {
// ##CHALLENGE 5: Add accelerometer test mode
let x = getCupPosition()
basic.clearScreen()
led.plot(x, 2)
basic.pause(200)
}
}
function getCupPosition(): number {
if (movement) {
let acc = input.acceleration(Dimension.X) / sensitivity
cupX = Math.clamp(0, 4, acc + 2)
return cupX
}
if (input.buttonIsPressed(Button.A)) {
if (cupX > 0) {
cupX = cupX - 1
}
} else if (input.buttonIsPressed(Button.B)) {
if (cupX < 4) {
cupX = cupX + 1
}
}
return cupX
}
function startGame() {
basic.clearScreen()
// If button still held from start-game, wait until it is released
while (input.buttonIsPressed(Button.A)) {
// wait for button to be released
}
// handlers that work out if cup is turned upside down or not
input.onLogoDown(() => {
cupInverted = true
})
input.onLogoUp(() => {
cupInverted = false
})
}
function beep(p: number) {
pins.digitalWritePin(DigitalPin.P0, 1)
basic.pause(p)
pins.digitalWritePin(DigitalPin.P0, 0)
}

View File

@ -1,716 +0,0 @@
let AWasPressed: boolean
let BWasPressed: boolean
let ABWasPressed: boolean
let wasShake: boolean
startIOMonitor()
let gameNo = 0
while (true) {
// select a new game
if (AWasPressed) {
gameNo = (gameNo + 1) % 4
AWasPressed = false
}
// show selected game
if (gameNo == 0) {
basic.showLeds(`
# # # # #
# . . . #
. # . # .
. . . . .
. # # # .
`)
} else if (gameNo == 1) {
basic.showLeds(`
# # # . .
# . . . .
# # # # #
# # . . .
# # # . .
`)
} else if (gameNo == 2) {
basic.showLeds(`
. . . . .
# . . . .
# # # # #
# . . . .
. . . . .
`)
} else if (gameNo == 3) {
basic.showLeds(`
# . # # #
# # # # #
. . . # #
# # # # #
# # # # #
`)
}
// start selected game
if (BWasPressed) {
// Play the selected game
basic.clearScreen()
waitBReleased()
resetButtons()
let finalScore = 0
basic.clearScreen()
if (gameNo == 0) {
finalScore = playCybermen()
} else if (gameNo == 1) {
finalScore = playDalek()
} else if (gameNo == 2) {
finalScore = playSonicScrewdriver()
} else if (gameNo == 3) {
finalScore = playJudoonLanguage()
}
flashDigit(finalScore, 3)
resetButtons()
waitBPressed()
basic.clearScreen()
waitBReleased()
resetButtons()
} else {
basic.pause(100)
}
}
/**
* Game parameters
* Percentage chance that cyberman will move left/right to line up with you
*/
function playCybermen(): number {
let maxGameTime = 60
let cybermanMoveXProbability = 20
// How long (in 100ms ticks) cyberman must line up before moving forward
let cybermanMoveYCount = 10
// Game variables
let startTime = input.runningTime()
let gameTime = 0
let playerX = 2
let cybermanX = 1
let cybermanY = 0
let cybermanLineupCount = 0
let redraw = true
while (gameTime < maxGameTime) {
if (redraw) {
basic.clearScreen()
led.plot(playerX, 4)
led.plot(cybermanX, cybermanY)
redraw = false
}
// Handle Player Movement
if (AWasPressed) {
if (playerX > 0) {
playerX = playerX - 1
redraw = true
}
AWasPressed = false
} else if (BWasPressed) {
if (playerX < 4) {
playerX = playerX + 1
redraw = true
}
BWasPressed = false
}
// Handle Cyberman line-of-sight checking
if (cybermanX == playerX) {
cybermanLineupCount = cybermanLineupCount + 1
if (cybermanLineupCount >= cybermanMoveYCount) {
if (cybermanY == 4) {
// Cyberman caught you, game over
break
} else {
cybermanY = cybermanY + 1
redraw = true
cybermanLineupCount = 0
}
}
} else {
cybermanLineupCount = 0
// Move Cyberman closer to player, slowly
if (Math.random(100) < cybermanMoveXProbability) {
if (cybermanX > playerX) {
cybermanX = cybermanX - 1
} else if (cybermanX < playerX) {
cybermanX = cybermanX + 1
}
redraw = true
}
}
basic.pause(100)
gameTime = (input.runningTime() - startTime) / 1000
}
return convertSurvivalTimeToScore(gameTime)
}
/**
* Game parameters, all probabilities as a percentage
*/
function playDalek(): number {
let maxGameTime = 60
let userMoveSensitivity = 40
let dalekMoveSensitivity = 20
let dalekShootChance = 10
let dalekHitChance = 10
// Game variables
let gameTime = 0
let startTime = input.runningTime()
let dalekY = 2
let userY = 1
let redraw = true
while (gameTime < maxGameTime) {
// Redraw screen if necessary
if (redraw) {
basic.clearScreen()
led.plot(0, dalekY)
led.plot(4, userY)
redraw = false
}
// Work out if the user has moved, and move them
let tilt = getTilt()
if (tilt > 2) {
// Moving up, slowly
if (userY < 4) {
if (Math.random(100) < userMoveSensitivity) {
userY = userY + 1
redraw = true
}
}
} else if (tilt < 2) {
// Moving down (slowly)
if (userY > 0) {
if (Math.random(100) < userMoveSensitivity) {
userY = userY - 1
redraw = true
}
}
}
// Move the Dalek to line up with user
if (dalekY < userY) {
if (Math.random(100) < dalekMoveSensitivity) {
dalekY = dalekY + 1
redraw = true
}
} else if (dalekY > userY) {
if (Math.random(100) < dalekMoveSensitivity) {
dalekY = dalekY - 1
redraw = true
}
} else {
// Dalek lines up
if (Math.random(100) < dalekShootChance) {
// Shoot a raygun at the user
for (let i = 0; i < 3; i++) {
led.plot(i + 1, dalekY)
basic.pause(100)
}
if (Math.random(100) < dalekHitChance) {
// User has been hit, game over
break
}
redraw = true
}
}
gameTime = (input.runningTime() - startTime) / 1000
basic.pause(100)
}
return convertSurvivalTimeToScore(gameTime)
}
/**
* Set this in steps of 60
*/
function playSonicScrewdriver(): number {
let maxGameTime = 120
let gameTime = 0
// @=0, A=1 etc
// bit0=N, bit1=E, bit2=S, bit3=W
// bit=0 means it is a wall (can not be opened)
// bit=1 means it is a door (can be opened)
let mazestr = "BLFL@GOIFIGLCJIA"
let maze = ([] as number[])
// Locks use same number encoding (bits 0,1,2,3)
// bit=0 means door is locked (cannot be walked through)
// bit=1 means door is open (can be walked through)
let doorOpen = ([] as number[])
for (let i = 0; i < 16; i++) {
doorOpen.push(0)
maze.push(mazestr.charCodeAt(i) - 64)
}
let redraw = true
let cellno = 0
let direction = "N"
let startTime = input.runningTime()
while (gameTime < maxGameTime) {
// Draw the screen
if (redraw) {
basic.clearScreen()
// Always draw the maze with N at the top
drawMazeCell(doorOpen[cellno])
// draw user standing next to selected wall
if (direction == "N") {
led.plot(2, 1)
} else if (direction == "E") {
led.plot(3, 2)
} else if (direction == "S") {
led.plot(2, 3)
} else if (direction == "W") {
led.plot(1, 2)
}
redraw = false
}
// Sense any button presses
if (AWasPressed) {
if (direction == "N") {
direction = "E"
} else if (direction == "E") {
direction = "S"
} else if (direction == "S") {
direction = "W"
} else if (direction == "W") {
direction = "N"
}
redraw = true
AWasPressed = false
} else if (BWasPressed) {
// Try to walk through an open door
if (isDoorOpen(doorOpen[cellno], direction)) {
cellno = mazeForward(cellno, 4, 4, direction)
redraw = true
}
BWasPressed = false
} else if (wasShake) {
// energise sonic screwdriver
if (isDoorOpen(maze[cellno], direction)) {
// It is a door, but is the door open or closed?
if (!(isDoorOpen(doorOpen[cellno], direction))) {
// Open the door in front of us
doorOpen[cellno] = openDoor(doorOpen[cellno], direction)
// Also open the return door for when we walk through this door
let forwardCellno = mazeForward(cellno, 4, 4, direction)
doorOpen[forwardCellno] = openDoor(doorOpen[forwardCellno], opposite(direction))
}
} else {
// Not a door
basic.showLeds(`
. . . . .
. # . # .
. . # . .
. # . # .
. . . . .
`)
basic.pause(500)
}
redraw = true
wasShake = false
}
if (cellno == 15) {
// Have reached the exit cell
break
}
basic.pause(100)
gameTime = (input.runningTime() - startTime) / 1000
}
return convertPenaltyTimeToScore(gameTime / maxGameTime / 60)
}
function playJudoonLanguage(): number {
let maxGameTime = 60
let gameTime = 0
let startTime = input.runningTime()
let font = images.createImage(`
# . # # # # . # . # . . . . # # # . . . # # # # # # . # . # # # # . . . . . # # # . . . # # # # # #
# # # # # # # # # # . . . # # . # # # # . # . . . # # # # # # # # # # # # # # . # # # # # . . # . .
. . . . # # # # . . . . # # # . . . . # . # . . . . . . . # . . . # # . . # # # . . # . . # # # # #
# # # # # # # # # # . . # . . # # # # # # # # # # # # # # # # # # # . # # # # # # # # # # # # # . .
# # # # # # # # # # # # # # # # . . . . # . . . # # . . . . . . . # # # # # . . # # # # # # # # # #
`)
let answers = images.createImage(`
# # # # # # # # . . . # # # . . . # . . # . # . #
# . . . # # . . . . # # # # # . . . . . . . . . .
. # . # . # # # # . # . # . # . # . # . # . # . #
. . . . . # # # . . # . # . # . . . . . . . . . .
. # # # . # # # . . # . # . # # # # # # # . . . #
`)
let pages = "029 041 167 208 283"
let actualAnswer = Math.random(5)
let pos = 0
let redraw = true
while (gameTime < maxGameTime) {
// Draw the current frame from pos (0,1,2 codeword, 3,4,5,6,7 answers)
if (redraw) {
if (pos <= 2) {
// Draw codeword symbol for this choice and this position
let digit = parseInt(pages[actualAnswer * 4 + pos])
font.plotFrame(digit)
} else {
// Draw answer
let item = pos - 3
answers.plotFrame(item)
}
redraw = false
}
// Process button presses
if (AWasPressed) {
// Move left, unless at far left already
AWasPressed = false
if (pos > 0) {
pos = pos - 1
redraw = true
}
} else if (BWasPressed) {
// Move right, unless already at far right
BWasPressed = false
if (pos < 7) {
pos = pos + 1
redraw = true
}
} else if (wasShake) {
// User trying to select an answer, are we at an answer position?
wasShake = false
if (pos >= 3) {
// Is it the right answer?
let userChoice = pos - 3
if (userChoice == actualAnswer) {
// CORRECT
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . #
. . . . . . . . . . . . . . . . . . # . . . . # .
# . . . . # . . . . # . # . . # . # . . # . # . .
. . . . . . # . . . . # . . . . # . . . . # . . .
`, 400)
basic.pause(1000)
break
} else {
// WRONG
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . # # . . . # # . . . # # . . . # # . . . #
. . . . . . . . . . . . . . . . . . # . . . . # . . . . # . . # . # . . # . # . . # . # .
. . . . . . . . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . .
. . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . # . . # . # .
# . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . #
`, 400)
basic.pause(1000)
redraw = true
}
}
}
gameTime = (input.runningTime() - startTime) / 1000
basic.pause(100)
}
return convertPenaltyTimeToScore(gameTime)
}
function getDirection(): string {
let bearing = input.compassHeading()
if (bearing < 45 || bearing > 315) {
return "N"
} else if (bearing < 135) {
return "E"
} else if (bearing < 225) {
return "S"
} else {
return "W"
}
}
function calibrateCompass() {
if (input.compassHeading() == -4) {
input.calibrate()
}
}
function waitBReleased() {
while (input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}
function waitBPressed() {
while (!input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}
/**
* Show the score 0..9
* @param digit TODO
* @param times TODO
*/
function flashDigit(digit: number, times: number) {
digit = Math.clamp(0, 9, digit)
for (let i = 0; i < times; i++) {
basic.showNumber(digit, 0)
basic.pause(500)
basic.clearScreen()
basic.pause(500)
}
basic.showNumber(digit, 0)
}
/**
* score is calculated as the amount of time you lasted
* @param gameTime TODO
*/
function convertSurvivalTimeToScore(gameTime: number): number {
if (gameTime <= 4) {
return 0
} else if (gameTime <= 9) {
return 1
} else if (gameTime <= 14) {
return 2
} else if (gameTime <= 19) {
return 3
} else if (gameTime <= 24) {
return 4
} else if (gameTime <= 29) {
return 5
} else if (gameTime <= 39) {
return 6
} else if (gameTime <= 49) {
return 7
} else if (gameTime <= 59) {
return 8
} else {
return 9
}
}
function convertPenaltyTimeToScore(penaltyTime: number): number {
if (penaltyTime <= 4) {
return 9
} else if (penaltyTime <= 9) {
return 8
} else if (penaltyTime <= 14) {
return 7
} else if (penaltyTime <= 19) {
return 6
} else if (penaltyTime <= 24) {
return 5
} else if (penaltyTime <= 29) {
return 4
} else if (penaltyTime <= 39) {
return 3
} else if (penaltyTime <= 49) {
return 2
} else if (penaltyTime <= 59) {
return 1
} else {
return 0
}
}
function startIOMonitor() {
input.onButtonPressed(Button.A, () => {
AWasPressed = true
})
input.onButtonPressed(Button.B, () => {
BWasPressed = true
})
input.onButtonPressed(Button.AB, () => {
ABWasPressed = true
})
input.onShake(() => {
wasShake = true
})
AWasPressed = false
BWasPressed = false
ABWasPressed = false
wasShake = false
}
/**
* maze is always drawn with north at top
* @param cell TODO
*/
function drawMazeCell(cell: number) {
let n = !(isNorth(cell))
let e = !(isEast(cell))
let s = !(isSouth(cell))
let w = !(isWest(cell))
// Draw any visible walls
if (n) {
for (let i = 0; i < 5; i++) {
led.plot(i, 0)
}
}
if (e) {
for (let l = 0; l < 5; l++) {
led.plot(4, l)
}
}
if (s) {
for (let k = 0; k < 5; k++) {
led.plot(k, 4)
}
}
if (w) {
for (let j = 0; j < 5; j++) {
led.plot(0, j)
}
}
}
/**
* work out the cell number in front of this cell
* given the direction N E S W (N points to button B)
* returns the forward cell number, -1 if outside of maze
* Turn cellno into an x and y based on width and height
* @param cellno TODO
* @param width TODO
* @param height TODO
* @param direction TODO
*/
function mazeForward(cellno: number, width: number, height: number, direction: string): number {
let y = cellno / width
let x = cellno % width
// Work out change in x/y and therefore change in cellno
// But bounds-check against width and height
// as user cannot walk outside of the maze
if (direction == "N") {
// sub 1 from y
if (y > 0) {
return cellno - width
}
} else if (direction == "E") {
// Add 1 to x
if (x < width - 1) {
return cellno + 1
}
} else if (direction == "S") {
// add 1 to y
if (y < height - 1) {
return cellno + width
}
} else if (direction == "W") {
// sub 1 from x
if (x > 0) {
return cellno - 1
}
}
// Not allowed to move in this direction, it will go outside of maze
return - 1
}
/**
* A door is open if the lock bit is 1
* A door is present if the maze bit is 1
* @param cell TODO
* @param direction TODO
*/
function isDoorOpen(cell: number, direction: string): boolean {
if (direction == "N") {
return isNorth(cell)
} else if (direction == "E") {
return isEast(cell)
}
if (direction == "S") {
return isSouth(cell)
} else if (direction == "W") {
return isWest(cell)
}
return false
}
function getTilt(): number {
let tilt: number
tilt = input.acceleration(Dimension.Y)
tilt = Math.clamp(-1024, 1023, tilt)
tilt = (tilt + 1024) / 512
return tilt
}
function waitAReleased() {
while (input.buttonIsPressed(Button.A)) {
basic.pause(100)
}
}
function waitNoButtons() {
while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B) || input.buttonIsPressed(Button.AB)) {
basic.pause(100)
}
}
function resetButtons() {
AWasPressed = false
BWasPressed = false
ABWasPressed = false
}
/**
* The appropriate bit (0,1,2,3) is set, which unlocks the door
* @param cell TODO
* @param direction TODO
*/
function openDoor(cell: number, direction: string): number {
if (direction == "N") {
return cell | 1
} else if (direction == "E") {
return cell | 2
} else if (direction == "S") {
return cell | 4
} else if (direction == "W") {
return cell | 8
}
return cell
}
/**
* is the north bit set in the cell?
* @param cell TODO
*/
function isNorth(cell: number): boolean {
if ((cell & 1) != 0) {
return true
}
return false
}
/**
* is the east bit set in the cell?
* @param cell TODO
*/
function isEast(cell: number): boolean {
if ((cell & 2) != 0) {
return true
}
return false
}
/**
* is the south bit set in the cell?
* @param cell TODO
*/
function isSouth(cell: number): boolean {
if ((cell & 4) != 0) {
return true
}
return false
}
/**
* is the west bit set in the cell?
* @param cell TODO
*/
function isWest(cell: number): boolean {
if ((cell & 8) != 0) {
return true
}
return false
}
function opposite(direction: string): string {
if (direction == "N") {
return "S"
} else if (direction == "E") {
return "W"
} else if (direction == "S") {
return "N"
} else if (direction == "W") {
return "E"
}
return direction
}
function isSount() { }

View File

@ -1,165 +0,0 @@
let sensorType: string
// ANALOG or TILT
sensorType = "TILT"
while (true) {
// splash screen (flood monitor)
basic.showLeds(`
# # # . .
# . . . .
# # . # .
# . . # .
# . . # #
`)
while (true) {
if (input.buttonIsPressed(Button.A)) {
// test that the sensor works
testMode()
break
} else if (input.buttonIsPressed(Button.B)) {
// run the real flood monitor
floodMonitor()
break
} else {
basic.pause(100)
}
}
}
/**
* test mode - test that the monitor and buzzer work
* no filtering in this mode, direct screen update
*/
function testMode() {
basic.showLeds(`
# # # # #
. . # . .
. . # . .
. . # . .
. . # . .
`)
waitNoButtons()
let img = images.createImage(`
. . . . . . . . . . . . . . . . . . . . # # # # #
. . . . . . . . . . . . . . . # # # # # . . . . .
. . . . . . . . . . # # # # # . . . . . . . . . .
. . . . . # # # # # . . . . . . . . . . . . . . .
# # # # # . . . . . . . . . . . . . . . . . . . .
`)
while (!input.buttonIsPressed(Button.A)) {
// Show live reading on display
let value = readSensor()
img.showImage(value * 5)
// Turn beeper on only if maximum value seen
if (value >= 4) {
pins.digitalWritePin(DigitalPin.P1, 1)
} else {
pins.digitalWritePin(DigitalPin.P1, 0)
}
basic.pause(50)
}
waitNoButtons()
}
function floodMonitor() {
basic.showLeds(`
# . . . #
# # . # #
# . # . #
# . . . #
# . . . #
`)
waitNoButtons()
let line = images.createImage(`
. . . . . . . . . . . . . . . . . . . . # # # # #
. . . . . . . . . . . . . . . # # # # # . . . . .
. . . . . . . . . . # # # # # . . . . . . . . . .
. . . . . # # # # # . . . . . . . . . . . . . . .
# # # # # . . . . . . . . . . . . . . . . . . . .
`)
let state = "SAFE"
let averagedValue = 0
while (!input.buttonIsPressed(Button.A)) {
let value = readSensor()
// Apply some 'lag' filtering to the value, so that 'bobbing' doesn't set off alarm
// i.e. to go from 0 to 4 takes 4 times round the loop
if (value > averagedValue) {
// On the way up, changes in reading are slowed down
averagedValue = averagedValue + 1
} else if (value < averagedValue) {
// On the way down, changes in reading happen immediately
averagedValue = value
}
// Work out what to do based on the averaged value (non bobbing value)
if (state == "SAFE") {
if (averagedValue >= 4) {
pins.digitalWritePin(DigitalPin.P1, 1)
state = "ALARMING"
} else {
// Display raw value as a line
line.showImage(value * 5)
// fill in based on averaged value (long term reading)
for (let i = 0; i < averagedValue; i++) {
led.plot(2, 4 - i)
}
}
} else if (state == "ALARMING") {
if (input.buttonIsPressed(Button.B)) {
pins.digitalWritePin(DigitalPin.P1, 0)
state = "SAFE"
} else {
basic.showAnimation(`
# # # # # . . . . .
# # # # # . . . . .
# # # # # . . . . .
# # # # # . . . . .
# # # # # . . . . .
`, 400)
}
}
basic.pause(300)
}
waitNoButtons()
}
/**
* Read a value 0,1,2,3,4 from either ANALOG or TILT
*/
function readSensor(): number {
let value = 0
// Produce a sensor value in range 0..1023
if (sensorType == "ANALOG") {
// Input range is 0..1023
value = pins.analogReadPin(AnalogPin.P0)
} else if (sensorType == "TILT") {
// Input range is -1024 (pads highest)..1023 (pads lowest)
value = input.acceleration(Dimension.Y)
// Emulator sometimes returns out of range values, so clamp to expected range
value = Math.clamp(-1024, 1023, value)
// Convert to an entirely positive range from 0 pads full up to 2047 pads full down
// (hinged at the 'eyes' end)
value = value + 1024
// Invert the direction, so that "pads up" is largest, "pads down" is smallest
value = 2047 - value
// We want the same range as the analog, so halve the range
value = value / 2
}
// 5 possible values (0,1,2,3,4) based on sensible thresholds
// We do this by thresholds, so that we have more control over the 5 levels
if (value < 200) {
return 0
} else if (value < 400) {
return 1
} else if (value < 600) {
return 2
} else if (value < 800) {
return 3
}
return 4
}
function waitNoButtons() {
while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}

View File

@ -1,529 +0,0 @@
let opMaxTime: number
let procMaxTime: number
let procsToDo: number
let recoveryTriesMax: number
let tenseTime: number
let flatlineTimeMax: number
let recoveryProbability: number
let aWasPressed: boolean
let bWasPressed: boolean
let digitsImg: Image
let tweezerCount_: number
let wasTweezers: boolean
let wasNose: boolean
let isTweezers: boolean
// P0 blue wire, tweezers (active high)
// P1, green wire nose button/LED (active high)
// P2/red speaker (not a self toned beeper, but a piezo or a speaker)
opMaxTime = 120 * 1000
procsToDo = 3
procMaxTime = 60 * 1000
tenseTime = 4000
flatlineTimeMax = 15 * 1000
recoveryTriesMax = 3
recoveryProbability = 60
let highScore = 0
digitsImg = images.createImage(`
. . # . . . . # . . . # # . . . # # . . . # . . . . # # # . . . # # . . # # # . . . # . . . . # . .
. # . # . . # # . . . . . # . . . . # . . # . . . . # . . . . # . . . . . . . . . # . # . . # . # .
. # . # . . . # . . . . # . . . . # . . . # # # . . . # . . . # # . . . . # . . . . # . . . . # # .
. # . # . . . # . . . # . . . . . . # . . . # . . . . . # . . # . # . . # . . . . # . # . . . . # .
. . # . . . # # # . . # # # . . # # . . . . # . . . # # . . . . # . . . # . . . . . # . . . # # . .
`)
startIOMonitor()
while (true) {
splashScreen()
if (buttonB()) {
basic.showAnimation(`
. . . . . # # . . . . # . . . . # . . . . . . # . . . . . .
. . . . # . . . . # # # . . # . # . . # . . # . # . . . . #
. . . . # . . . . # . . . . # # # . . # # # . . # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# . . . # # . . . # # . . . # # . . . # # . . . # # . . . #
`, 400)
let finalScore = surgery()
if (game.score() > highScore) {
basic.showString("HI", 150)
highScore = finalScore
}
flashDigit(finalScore)
waitButtonB()
} else if (buttonA()) {
testMode()
} else {
basic.pause(100)
}
}
function surgery(): number {
let score = 0
let speed = 150
let opStartTime = input.runningTime()
let procStartTime = -1
let procNumber = -1
let procsDone = 0
let recoveryTry = 0
let timer = 0
let state = "CHOOSE PROC"
resetButtons()
while (true) {
basic.pause(10)
let event = getEvent(state)
if (event == "CUT") {
state = "ARREST"
}
// CHECK TIMERS
if (!(procStartTime == -1)) {
if (input.runningTime() - procStartTime > procMaxTime) {
state = "LOST"
} else {
// TODO add code here to speed up near end of proc
}
}
if (input.runningTime() - opStartTime > opMaxTime) {
state = "LOST"
} else {
// TODO add code here to speed up near end of op
}
// PROCESS SPECIFIC STATES
if (state == "CHOOSE PROC") {
if (procNumber == -1) {
procNumber = 1
showDigit(procNumber)
} else if (event == "SCROLL") {
procNumber = procNumber + 1
if (procNumber > 9) {
procNumber = 1
}
showDigit(procNumber)
} else if (event == "SELECT") {
procStartTime = input.runningTime()
state = "HEALTHY"
speed = 100
}
} else if (state == "HEALTHY") {
speed = 100
ecg(speed)
if (event == "TWINGE") {
state = "TENSE"
timer = input.runningTime()
} else if (event == "DONE") {
state = "PROC DONE"
}
} else if (state == "TENSE") {
speed = 25
ecg(speed)
if (event == "TWINGE") {
state = "ARREST"
} else if (input.runningTime() - timer > tenseTime) {
state = "HEALTHY"
}
} else if (state == "ARREST") {
timer = input.runningTime()
recoveryTry = recoveryTriesMax
state = "FLATLINE"
} else if (state == "FLATLINE") {
basic.showLeds(`
. . . . .
. # . # .
. . . . .
. . . . .
# # # # #
`)
beepOn()
if (event == "SHOCK") {
state = "SHOCKING"
} else if (input.runningTime() - timer > flatlineTimeMax) {
state = "LOST"
}
} else if (state == "SHOCKING") {
charging()
basic.showAnimation(`
. . . . # . . . . # . . . . . . . . . .
. . . # . . . . # . . . . # . . . . . .
. . . . . . . # . . . . # . . . . # . .
. . . . . . . . . . . # . . . . # . . .
. . . . . . . . . . . . . . . . # . . .
`, 150)
beepNTimesFor(15, 500)
basic.showAnimation(`
. . . . . . . . . . . . . . . # . . . #
. . . . . . . . . . # . . # . . . . . .
. . . . . # . # . . . . . . . . . . . .
. # . . . . # . . . . . . . . . . . . .
. # . . . . # . . . . # . . . . # . . .
`, 150)
state = "SHOCKED"
} else if (state == "SHOCKED") {
let recover = Math.random(100)
if (recover >= recoveryProbability) {
state = "RECOVERED"
} else {
state = "FAILED"
}
} else if (state == "RECOVERED") {
beepOff()
basic.pause(500)
beep()
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . .
. # . # . . . . . . . # . # . . . . . . . # . # .
. . . . . . . . . . . . . . . . . . . . . . . . .
# . . . # . . . . . # . . . # . . . . . # . . . #
. # # # . . . . . . . # # # . . . . . . . # # # .
`, 400)
state = "HEALTHY"
} else if (state == "FAILED") {
recoveryTry = recoveryTry - 1
if (recoveryTry > 0) {
state = "FLATLINE"
} else {
state = "LOST"
}
} else if (state == "PROC DONE") {
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . #
. . . . . . . . . . . . . . . . . . # . . . . # .
# . . . . # . . . . # . # . . # . # . . # . # . .
. . . . . . # . . . . # . . . . # . . . . # . . .
`, 400)
score = score + pointsForProc(procNumber)
procsDone = procsDone + 1
procStartTime = -1
if (procsDone == procsToDo) {
state = "OP DONE"
} else {
procNumber = -1
state = "CHOOSE PROC"
}
} else if (state == "OP DONE") {
basic.showAnimation(`
. . . . . . . . # . . # . . . . . # . . . . . # . . . . . # . . # . . . . # . . . . . . . . . . . . . . . . .
. . . . # . . # . # . # . . # . . # . . . . . # . . . . . # . . # . . . . # . . . # . . . # . . . . . . . . .
# # # # # # # . . # # # . . # . # # . . . . # # . . . . # # . # # . . . . # . . . # . . . # . . . . . . . . .
# # # # # # # # # # # # # # # . # # # # . . # # # . . . # # . . . # # . . # # # . # . # # # . . # # . . . # #
# . . . # # . . . # # . . . # . # . . . . . # . . . . . # . . . . # . . . . # . . # . # . # . . # . . . . # .
`, 400)
return score
} else if (state == "LOST") {
beepOn()
basic.showLeds(`
. # . # .
. . # . .
. # . # .
. . . . .
# # # # #
`)
basic.pause(3000)
beepOff()
basic.showAnimation(`
. . . . . . . . . . # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . # # # # # # . . . . # . . . . # . . . . # # . # . # . . . . # # . # . # . . . . #
# # # # # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# . . . # # . . . # # . . . # # . . . # # . . . # # . . . # # . . . # # . . . # # . . . #
`, 400)
return score
}
}
}
/**
* if any button pressed, terminate the animation immediately
*/
function splashScreen() {
let img = images.createImage(`
. # . # . . # . # . . # . # . . # . # . . . # . . . # # . .
# # # # # # . # . # # # # # # # . # . # . # . # . . # . # .
# # # # # # . . . # # # # # # # . . . # . # . # . . # # . .
. # # # . . # . # . . # # # . . # . # . . # . # . . # . . .
. . # . . . . # . . . . # . . . . # . . . . # . . . # . . .
`)
let x = 0
while (!aWasPressed && !bWasPressed) {
img.showImage(x)
basic.pause(500)
x = x + 5
if (x >= img.width()) {
x = 0
}
}
}
/**
* Test sensing and buzzing
* I/O at moment is (assuming self toning beeper)
* P0 is beeper and nose LED
* P1 is the tweezer sense wire
* P2 is possibly the nose button
* If we want amplification, might have to use piezo library
* which means using extra pins
*/
function testMode() {
while (!(buttonA())) {
if (pins.digitalReadPin(DigitalPin.P1) == 1) {
pins.digitalWritePin(DigitalPin.P0, 1)
basic.showLeds(`
. . . . .
. . . . #
. . . # .
# . # . .
. # . . .
`)
} else {
pins.digitalWritePin(DigitalPin.P0, 0)
basic.showLeds(`
# # # # #
. . # . .
. . # . .
. . # . .
. . # . .
`)
}
basic.pause(100)
}
}
/**
* SENSE TWINGE/CUT FROM TWEEZERS (10ms per sample)
* @param state TODO
*/
function getEvent(state: string): string {
if (wasTweezers) {
if (tweezerCount_ > 20) {
wasTweezers = false
tweezerCount_ = 0
return "CUT"
} else if (!isTweezers) {
wasTweezers = false
tweezerCount_ = 0
return "TWINGE"
}
}
// SENSE A OR B BUTTON PRESSES
if (state == "CHOOSE PROC") {
if (buttonA()) {
return "SCROLL"
} else if (buttonB()) {
return "SELECT"
}
} else if (state == "FLATLINE") {
if (buttonB()) {
return "SHOCK"
} else if (nose()) {
return "SHOCK"
}
} else if (state == "HEALTHY") {
if (buttonB()) {
return "DONE"
}
}
// Clear any flags for unnecessary events in a given state to prevent latching
aWasPressed = false
bWasPressed = false
return "NONE"
}
function flashDigit(digit: number) {
for (let i = 0; i < 4; i++) {
showDigit(digit)
basic.pause(200)
basic.clearScreen()
basic.pause(200)
}
showDigit(digit)
basic.pause(1000)
}
/**
* Make a short beep sound
*/
function beep() {
beepOn()
basic.pause(200)
beepOff()
}
/**
* work out score for a procedure
* @param procNumber TODO
*/
function pointsForProc(procNumber: number): number {
if (procNumber < 4) {
return 1
} else if (procNumber < 7) {
return 2
} else {
return 3
}
}
/**
* beep n times, for a total duration of m
* @param times TODO
* @param duration TODO
*/
function beepNTimesFor(times: number, duration: number) {
let halfCycle = duration / (times * 2)
for (let i = 0; i < times; i++) {
beepOn()
basic.pause(halfCycle)
beepOff()
basic.pause(halfCycle)
}
}
function startIOMonitor() {
aWasPressed = false
input.onButtonPressed(Button.A, () => {
aWasPressed = true
})
bWasPressed = false
input.onButtonPressed(Button.B, () => {
bWasPressed = true
})
wasTweezers = false
isTweezers = false
tweezerCount_ = 0
control.inBackground(() => {
let buzzCount = 0
while (true) {
if (pins.digitalReadPin(DigitalPin.P0) == 1) {
wasTweezers = true
isTweezers = true
tweezerCount_ = tweezerCount_ + 1
if (buzzCount == 0) {
pins.analogWritePin(AnalogPin.P2, 512)
pins.analogSetPeriod(AnalogPin.P2, 5000)
}
buzzCount = 10
} else {
isTweezers = false
}
if (buzzCount > 0) {
buzzCount = buzzCount - 1
if (buzzCount == 0) {
pins.analogWritePin(AnalogPin.P2, 0)
}
}
basic.pause(10)
}
})
}
/**
* Shows a single digit, with a nicer font than the standard micro:bit font
* @param digit TODO
*/
function showDigit(digit: number) {
digit = Math.clamp(0, 9, digit)
digitsImg.showImage(digit * 5)
}
/**
* check to see if button A was pressed recently
*/
function buttonA(): boolean {
if (aWasPressed) {
aWasPressed = false
return true
}
return false
}
function waitButtonA() {
while (!(buttonA())) {
basic.pause(100)
}
}
function buttonB(): boolean {
if (bWasPressed) {
bWasPressed = false
return true
}
return false
}
function waitButtonB() {
while (!(buttonB())) {
basic.pause(100)
}
}
function beepOn() {
pins.analogWritePin(AnalogPin.P2, 512)
pins.analogSetPeriod(AnalogPin.P2, 2272)
}
function beepOff() {
pins.analogWritePin(AnalogPin.P2, 0)
}
function resetButtons() {
aWasPressed = false
bWasPressed = false
}
function ecg(speed: number) {
beepOn()
pins.digitalWritePin(DigitalPin.P1, 1)
basic.pause(50)
beepOff()
basic.showAnimation(`
. . . . # . . . # . . . # . . . # . . . # . . . . . . . . . . . . . .
. . . . # . . . # . . . # . . . # . . . # . . . . . . . . . . . . . .
. . . . # . . . # . . . # . . . # . . . # . . . . . . . . . . . . . .
. . . . # . . . # # . . # # . . # # . . # # . . . # . . . . . . . . .
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
`, speed)
pins.digitalWritePin(DigitalPin.P1, 0)
basic.pause(speed * 10)
}
function nose(): boolean {
if (wasNose) {
wasNose = false
return true
}
return false
}
/**
* start period in microseconds
*/
function charging() {
let period = 2000
let dec = 500
pins.analogWritePin(AnalogPin.P2, 512)
pins.analogSetPeriod(AnalogPin.P2, period)
basic.showLeds(`
. # # . .
. . . # .
. . # . .
. . . # .
. # # . .
`)
basic.pause(500)
pins.analogSetPeriod(AnalogPin.P2, period - dec)
basic.showLeds(`
. # # . .
. . . # .
. . # . .
. # . . .
. # # # .
`)
basic.pause(500)
pins.analogSetPeriod(AnalogPin.P2, period - dec * 2)
basic.showLeds(`
. . # . .
. # # . .
. . # . .
. . # . .
. # # # .
`)
basic.pause(500)
beepOff()
}

View File

@ -1,178 +0,0 @@
let wasShake: boolean
input.onShake(() => {
wasShake = true
})
wait_6Hours()
timeForTest()
alertnessTest()
wait_2Hours()
timeForTest()
alertnessTest()
wait_2Hours()
timeForTest()
alertnessTest()
/**
* animate back to work
* animate take a rest
*/
function animations() { }
/**
* wait 6 hours
* because this is a test program, we only wait for a short time
*/
function wait_6Hours() {
basic.showAnimation(`
. . # . . . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . # . . . .
. . # . . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . .
. . # . . . . # . . . . # # # . . # . . . . # . . . . # . . # # # . . . . # . .
. . . . . . . . . . . . . . . . . . # . . . # . . . # . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . # . . # . . # . . . . . . . . . . . . . .
`, 500)
}
/**
* wait for 2 hours
* because this is test code, we only wait a few seconds
*/
function wait_2Hours() {
basic.showAnimation(`
. . # . . . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . # . . . .
. . # . . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . .
. . # . . . . # . . . . # # # . . # . . . . # . . . . # . . # # # . . . . # . .
. . . . . . . . . . . . . . . . . . # . . . # . . . # . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . # . . # . . # . . . . . . . . . . . . . .
`, 500)
}
function alertnessTest() {
let goodResponse = 1000
let threshold = 5
let score = 0
// Start test on button press
let x = 0
let start = images.createImage(`
. . # . . . . # . .
. . # . . . # . # .
. . # . . . . . # .
. . . . . . . # . .
. . # . . . . # . .
`)
while (!input.buttonIsPressed(Button.B)) {
start.showImage(x)
x = x + 5
if (x >= start.width()) {
x = 0
}
basic.pause(300)
}
// Wait for button(s) to be released
while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
// Run 10 random cognition response tests
for (let i = 0; i < 9; i++) {
// Choose random delay and random outcome
let delay = Math.random(5) + 5
let outcome = Math.random(2)
// Draw moving dots on screen until delay expires
basic.clearScreen()
for (let j = 0; j < delay; j++) {
led.plot(j % 5, 2)
basic.pause(200)
basic.clearScreen()
}
// Show shake or button icon
if (outcome == 0) {
// Press the button!
basic.showLeds(`
. . . . .
. # # # .
. # # # .
. # # # .
. . . . .
`)
} else {
// Shake the bit!
basic.showLeds(`
# . # . .
# . . # .
# # # # #
# . . # .
# . # . .
`)
}
// Wait up to 3 seconds for button, shake, or timeout
wasShake = false
let timer = input.runningTime()
let timeout = 3000
while (input.runningTime() < timer + timeout) {
if (wasShake) {
break
} else if (input.buttonIsPressed(Button.B)) {
break
} else {
basic.pause(100)
}
}
// Assess the response and the response time
let response = input.runningTime() - timer
if (outcome == 0 && input.buttonIsPressed(Button.B) && response <= goodResponse) {
score = score + 1
} else if (outcome == 1 && wasShake && response <= goodResponse) {
score = score + 1
}
}
// Show final score flashing 5 times (0..9)
for (let k = 0; k < 5; k++) {
basic.showNumber(score, 0)
basic.pause(250)
basic.clearScreen()
basic.pause(250)
}
basic.showNumber(score, 0)
basic.pause(500)
if (score < threshold) {
// Time for a break, show coffee cup animation
for (let l = 0; l < 3; l++) {
basic.showAnimation(`
. . . . . . . . . . . # . . . . # . . . . . . . . . . # . . . . # . . . . . . .
. . . . . . # . . . . # . . . . . . . . . . # . . . . # . . . . . . . . . . . .
# . . # . # # . # . # . . # . # . . # . # . # # . # . . # . # . . # . # . . # .
# . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # #
# # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # .
`, 400)
}
} else {
// All ok, back to work, show digging animation
for (let m = 0; m < 3; m++) {
basic.showAnimation(`
# . # . . # . . . . # . . . .
. # # . . . # . # . . # . . .
# # # . . . . # # . . . # . #
. . . . . . # # # . . . . # #
. . . . . . . . . . . . # # #
`, 400)
}
}
// Wait for any button press to finish test
while (!input.buttonIsPressed(Button.A) && !input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}
/**
* alert the user it is time to take the test
* in a real system, this might give them 5 1 minute warnings
*/
function timeForTest() {
basic.showAnimation(`
. # # # . . # . . . . # # . . . # # . . . . # . .
. # . . . . # . . . . . . # . . . . # . . # # . .
. . # . . . # # # . . # # . . . . # . . . . # . .
. . . # . . . # . . . . . # . . # . . . . . # . .
. # # . . . . # . . . # # . . . # # # . . # # # .
`, 700)
}

View File

@ -1,157 +0,0 @@
let maxGameTime: number
let wasShake: boolean
maxGameTime = 60000
input.onShake(() => {
wasShake = true
})
while (true) {
splashScreen()
if (input.buttonIsPressed(Button.B)) {
basic.showAnimation(`
# # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # . . # # # # #
# # # . . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # . . # . . . . # . . . . # . . . . # . . . . # # # # # # # # # #
# # # . . # # # . . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # . . # # # . . # # # . . # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # # . . # # # . # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
`, 400)
let score = playOneGame()
flashDigit(score, 5)
waitButtonB()
basic.showAnimation(`
# # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# # # # # # # # # # . . . . . . . . . . . . . . . . . . . . . # . # . . . . . . . # . # . . . . . .
# # # # # # # # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# # # # # # # # # # # # # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# # # # # # # # # # # # # # # # # # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . .
`, 400)
} else if (input.buttonIsPressed(Button.A)) {
calibrate()
}
}
function playOneGame(): number {
let countDots = 0
let x = 2
let y = 2
let xdir = true
let canvas = images.createImage(`
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
`)
wasShake = false
let bearing = input.compassHeading()
let startTime = input.runningTime()
while (countDots < 25 && input.runningTime() - startTime < maxGameTime) {
if (wasShake) {
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . # # # . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . # # # . . . # . . . # # # . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . # # # . . . # . . . . # . . . . # . . . # # # . . . . . . . . . . . . . . . .
. . . . . . # # # . . . # . . . . # . . . . # . . . . # . . . . # . . . # # # . . . . . . . . . . .
. # # # . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . # # # . . . . . .
`, 50)
let pos = Math.random(5)
if (xdir) {
if (!canvas.pixel(pos, y)) {
canvas.setPixel(pos, y, true)
countDots = countDots + 1
}
} else if (!canvas.pixel(x, pos)) {
canvas.setPixel(x, pos, true)
countDots = countDots + 1
}
wasShake = false
canvas.showImage(0)
} else if (Math.abs(input.compassHeading() - bearing) > 60) {
xdir = !xdir
bearing = input.compassHeading()
if (xdir) {
x = Math.random(5)
} else {
y = Math.random(5)
}
} else {
basic.pause(100)
}
}
return dotsToScore(countDots)
}
function splashScreen() {
let img = images.createImage(`
# # # # . # # # # . # # # # . # # # # . # # # # . # # # # . . # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . # # . . # # # . # # # # . # # # # . . # # # . . . # # . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # . # # # # . # # # # . # # # # . # # # # .
# . . . # # . . . # # . . . # # . . . # # . . . # . # # # . . . # . . . # # # . . . . . . . . . . . . . . . . . . . . . # . . . . . # . . . . . # . . . . . # . . . . . # . . . # # . . # . # . # . . # # . . . # # . . . # # . . . # # . . . # . # . . # . . # . # . . . # # . . . . # . . . # . . . # . . . # . . . # . . . . . . . . . . . . . . . . . . . . . . . . . # # # . . . # . . . # # # . # . . . # # . . . # # . . . # # . . . #
# # # # . # # # # . # # # # . # # # # . . # # # . . . # . . . . # . . . . # . . . # # # . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # . # # # # # # # # # . # # # . . # # . . . # . . . . . . . . . . . . . . . . . . . . # # # . . . # . . . . # . . . . # . . . # # # . # # # # . # # # # . # # # # .
# . . . . # . . . . # . . . . . # # # . . . # . . . . # . . . . # . . . . # . . . . # . . . # # # . . . . . . . . . . . # . . . . . # . . . . . # . . . . . # . . . . . # . . . # . . . # # . . # . # . # . . # . # . . # . # . . # . # . . # . . # . # . . . # # . . . . # . . . . . # . . . # . . . # . . . # . . . # . . . . . . . . . . . . . . . # # # . . . # . . . . # . . . . # . . . . # . . . . # . . . # # # . # . . . . # . . . .
# . . . . # . . . . . # # # . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # . . . . # . . . . # # . . . # # . . . # . . . . # . . . . # . . . . # . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . # # # . # . . . .
`)
let x = 0
while (!input.buttonIsPressed(Button.A) && !input.buttonIsPressed(Button.B)) {
img.showImage(x)
basic.pause(200)
x = x + 5
if (x >= img.width()) {
x = 0
}
}
}
/**
* rotate canvas
*/
function rotateImage() { }
function flashDigit(digit: number, times: number) {
for (let i = 0; i < times; i++) {
basic.showNumber(digit, 0)
basic.pause(500)
basic.clearScreen()
basic.pause(500)
}
basic.showNumber(digit, 0)
}
function waitButtonB() {
while (!input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}
function dotsToScore(dots: number): number {
if (dots == 25) {
return 9
} else if (dots >= 22) {
return 8
} else if (dots >= 19) {
return 7
} else if (dots >= 16) {
return 6
} else if (dots >= 13) {
return 5
} else if (dots >= 10) {
return 4
} else if (dots >= 7) {
return 3
} else if (dots >= 4) {
return 2
} else if (dots >= 1) {
return 1
} else {
return 0
}
}
function calibrate() {
basic.showString("CAL", 150)
if (input.compassHeading() == -4) {
input.calibrate()
}
while (!input.buttonIsPressed(Button.B)) {
let h = input.compassHeading()
basic.showNumber(h, 150)
}
}

View File

@ -1,267 +0,0 @@
let state: string
let timer: number
let gesturesRunning: boolean
let wasShake: boolean
let wasLogoUp: boolean
let wasLogoDown: boolean
let wasScreenUp: boolean
let wasScreenDown: boolean
while (true) {
splashScreen()
if (input.buttonIsPressed(Button.B)) {
// animate: add pancake
basic.showAnimation(`
# # # # # # . . . # . . . . . . . . . . . . . . .
. . . . . . # # # . . # # # . . . . . . . . . . .
. . . . . . . . . . # . . . # # . . . # . . . . .
. . . . . . . . . . . . . . . . # # # . . # # # .
. . . . . . . . . . . . . . . . . . . . # . . . #
`, 250)
runGameOnce()
// animate: pancake done
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . # . . . # # # # # # # . . . # . . . . . . . . . . . # . # . . . . . . . # . # . . . . . .
. . . . . . . . . . . # # # . # # # # # . # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . # # # # # # # . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, 250)
} else if (input.buttonIsPressed(Button.A)) {
testShake()
}
}
/**
* Runs one complete game from start to end
*/
function runGameOnce() {
let score = 0
let cooks = 0
let target_time = 0
// make sure no gestures are outstanding from last game
wasShake = false
wasLogoUp = false
wasLogoDown = false
wasScreenUp = false
wasScreenDown = false
state = "NEWSIDE"
while (true) {
// Handle any gestures that can happen at any time
let gesture = getGesture()
if (gesture == "FLOOR") {
state = "DROPPED"
}
// Run code appropriate to the present state of the game
if (state == "NEWSIDE") {
target_time = 5 + Math.random(5)
state = "COOKING"
startTimer()
} else if (state == "COOKING") {
// animate: cooking
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . # . . . . . . . . . . . . . #
# # # # # . # # # # # # # # # # # # # .
`, 100)
if (gesture == "FLIP") {
state = "FLIPPING"
} else if (getTimerSec() >= target_time) {
state = "READY"
score = score + 1
startTimer()
}
} else if (state == "READY") {
// animate: ready
basic.showAnimation(`
. . . . .
. . . . .
. . . . .
# . . . #
. # # # .
`, 100)
if (getTimerSec() > 2) {
state = "BURNING"
score = score - 1
startTimer()
} else if (gesture == "FLIP") {
state = "FLIPPING"
}
} else if (state == "BURNING") {
// animate: burning
basic.showAnimation(`
. . . . . . . . . . . . . # . . . . # .
. . . . . . . . # . . # . # . . # . . .
. . . . . . # . # . . # . . . . . . . .
. . . . . . # . . . . . . . . . . . . .
# # # # # # # # # # # # # # # # # # # #
`, 100)
if (gesture == "SKY") {
state = "NEWSIDE"
} else if (getTimerSec() > 2) {
state = "BURNT"
}
} else if (state == "FLIPPING") {
// animate: flipping
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . . . . # . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . # # # # # . # # . . . # # # . . . # # . # # # # # . . . . . . . . . .
. . . . . . . . . . # # # # # . . . . . . . . # # . # # # . # # . . . . . . . . # # # # # . . . . .
. . . . . # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # #
# # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, 100)
// Prevent a spurious double-flip from happening
wasShake = false
cooks = cooks + 1
if (cooks == 5) {
state = "GAMEOVER"
} else {
state = "NEWSIDE"
}
} else if (state == "DROPPED") {
// animate: dropped
basic.showAnimation(`
# . . . # . . . . . # . . . # . . . . .
. # . # . . . . . . . # . # . . . . . .
. . # . . . . . . . . . # . . . . . . .
. # . # . . . . . . . # . # . . . . . .
# . . . # . . . . . # . . . # . . . . .
`, 250)
score = 0
state = "GAMEOVER"
} else if (state == "BURNT") {
// animate: burnt
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . # . # . . . . . . . # # # .
. . . . . . . . . . . . . . . . . # . . . . . . . . # . # . . . . . . . # # # . . . . . .
. . . . . . . . . . . . . . . . . . . . . # . # . . . . . . . # # # . . . . . . . . . . .
. . . . . . # . # . . # # # . . # . # . . . . . . . # # # . . . . . . . . . . . . . . . .
# # # # # . # # # . . # # # . . # # # . . # # # . . . . . . . . . . . . . . . . . . . . .
`, 250)
score = 0
state = "GAMEOVER"
} else if (state == "GAMEOVER") {
animateScore(score)
state = "WAITEJECT"
} else if (state == "WAITEJECT") {
if (gesture == "UPSIDEDOWN") {
return
}
}
}
}
/**
* show score (0..9) flashing
* @param score TODO
*/
function animateScore(score: number) {
score = Math.clamp(0, 9, score)
for (let i = 0; i < 5; i++) {
basic.showNumber(score, 0)
basic.pause(500)
basic.clearScreen()
basic.pause(500)
}
basic.showNumber(score, 0)
}
/**
* NOTE: Eventually this will move into a gesture library
* It hides all the nasty detail of detecting gestures
*/
function getGesture(): string {
if (!gesturesRunning) {
input.onShake(() => {
wasShake = true
})
input.onLogoUp(() => {
wasLogoUp = true
})
input.onLogoDown(() => {
wasLogoDown = true
})
input.onScreenUp(() => {
wasScreenUp = true
})
input.onScreenDown(() => {
wasScreenDown = true
})
gesturesRunning = true
}
// work out which of a possible set of gestures has occurred:
// Button gestures and movement gestures both handled
// This is so that it is easy to also use this on the simulator too
// Generally, B is used for normal OK, A is used for abnormal RECOVERY
// (flip is a normal action, touch sky to turn off smoke alarm is recovery)
let a = input.buttonIsPressed(Button.A)
let b = input.buttonIsPressed(Button.B)
if (state == "COOKING" || state == "READY") {
if (b || wasShake) {
wasShake = false
return "FLIP"
}
} else if (state == "FLIPPING") {
if (a || wasLogoDown) {
wasLogoDown = false
return "FLOOR"
}
} else if (state == "BURNING") {
if (a || wasLogoUp) {
wasLogoUp = false
return "SKY"
}
} else if (state == "GAMEOVER" || state == "WAITEJECT") {
if (b || wasScreenDown) {
wasScreenDown = false
return "UPSIDEDOWN"
}
}
return "NONE"
}
/**
* start timer by sampling runningtime and storing into starttime
*/
function startTimer() {
timer = input.runningTime()
}
/**
* get the elapsed time from the global starttime with ref to running time
* in seconds.
*/
function getTimerSec(): number {
let t = (input.runningTime() - timer) / 1000
return t
}
/**
* Show a splash screen "Perfect Pancakes >>>"
* Splash screen "PP" with little arrow pointing to the start button
*/
function splashScreen() {
let splash = images.createImage(`
# # # # . . . . . . # # # # . . . . . . . . . . . . . . . . . . . . .
# . . . # . . . . . # . . . # # . . . . . # . . . . . # . . . . . # .
# # # # . . . . . . # # # # . . # . . . . . # . . . . . # . . . . . #
# . . . . . . . . . # . . . . # . . . . . # . . . . . # . . . . . # .
# . . . . . . . . . # . . . . . . . . . . . . . . . . . . . . . . . .
`)
// use show image (not show animation) so that button press is more responsive
let index = 0
// Any button press finishes the splash screen
while (!input.buttonIsPressed(Button.B) && !input.buttonIsPressed(Button.A)) {
splash.showImage(index * 5)
index = index + 1
if (index > splash.width() / 5) {
index = 0
}
basic.pause(250)
}
}
function testShake() { }

View File

@ -1,242 +0,0 @@
let sugarThreshold: number
let ketoneThreshold: number
// Important parameters
sugarThreshold = 14
ketoneThreshold = 6
while (true) {
// splash screen sugar cube (just the right sugar)
basic.showAnimation(`
# # # . . . . . . . . . . . . . . . . .
# # # . . . # # # . . . . . . . . . . .
# # # . . . # # # . . . # # # . . # # #
. . . . . . # # # . . . # # # . . # # #
. . . . . . . . . . . . # # # . . # # #
`, 400)
// ask questions and give advice
quiz()
// wait for button press before restart
waitAnyButton()
}
function getSugar(): string {
waitNoButtons()
let selection = "MID"
while (!input.buttonIsPressed(Button.B)) {
// high, low, normal?
basic.showAnimation(`
. . . . . # . # . . . . # . .
. # # # . # . # . . . # . # .
. # # # . # . # # # . . . # .
. # # # . # . . # . . . # . .
. . . . . # . . # . . . # . .
`, 400)
// show low, mid, or high as a bar
selection = getLowMidHigh(selection)
}
return selection
}
function getKetone(): string {
waitNoButtons()
let selection = "MID"
while (!input.buttonIsPressed(Button.B)) {
// high, low, normal?
basic.showAnimation(`
. . . . . . . . # . . . # . .
# # . . . . . # . . . # . # .
# # # # # . . # # . . . . # .
# # . . # . . # . # . . # . .
. . . . . # . . # . . . # . .
`, 400)
// show low, mid, or high as a bar
selection = getLowMidHigh(selection)
}
return selection
}
function getIll(): boolean {
waitNoButtons()
let selection = false
while (!input.buttonIsPressed(Button.B)) {
// ask question 'happy or sad'
basic.showAnimation(`
. . . . . . . . . . . . # . . . . # . .
. # . # . . # . # . . # . # . . # . # .
. . . . . . . . . . . . . # . . . . # .
# . . . # . # # # . . . # . . . . # . .
. # # # . # . . . # . . # . . . . # . .
`, 400)
// get answer from user
selection = getHappySad(selection)
}
// if we are happy, we are not ill
return !selection
}
function getLowMidHigh(selection: string): string {
let timeout = 2000
let timer = input.runningTime()
while (true) {
// show the present level as a line
if (selection == "LOW") {
basic.showLeds(`
. . . . .
. . . . .
. . . . .
. . . . .
# # # # #
`)
} else if (selection == "HIGH") {
basic.showLeds(`
# # # # #
. . . . .
. . . . .
. . . . .
. . . . .
`)
} else {
basic.showLeds(`
. . . . .
. . . . .
# # # # #
. . . . .
. . . . .
`)
}
// process any user input
if (input.buttonIsPressed(Button.A)) {
// cycle round the 3 possible levels
if (selection == "LOW") {
selection = "MID"
} else if (selection == "MID") {
selection = "HIGH"
} else {
selection = "LOW"
}
// This is the 'hold repeat' time if you hold the A button
basic.pause(300)
// restart timer, 2 seconds of inactivity before return to main
timer = input.runningTime()
} else if (input.buttonIsPressed(Button.B)) {
// user is selecting so better return quickly
return selection
} else if (input.runningTime() > timer + timeout) {
// timeout, so return to main to re-prompt user
return selection
} else {
// This slows the loop down to stop the emulator being busy
// and also preserves battery life on the micro:bit
// it also affects the worst case response time
// it also affects the response time
basic.pause(100)
}
}
}
/**
* Wait for all buttons to be released
* This prevents spurious selection in next question
*/
function waitNoButtons() {
while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}
function getHappySad(selection: boolean): boolean {
let timeout = 2000
let timer = input.runningTime()
while (!input.buttonIsPressed(Button.B)) {
// Show present selection
if (selection) {
basic.showLeds(`
. . . . .
. # . # .
. . . . .
# . . . #
. # # # .
`)
} else {
basic.showLeds(`
. . . . .
. # . # .
. . . . .
. # # # .
# . . . #
`)
}
// Wait for any change in the selection
if (input.buttonIsPressed(Button.A)) {
selection = !selection
// This is the repeat time if button A held down
basic.pause(500)
timer = input.runningTime()
} else if (input.runningTime() > timer + timeout) {
return selection
} else {
// Preserve battery life on micro:bit and prevent emulator being busy
// This is also the response time to a button press
basic.pause(100)
}
}
return selection
}
/**
* Button A changes value, Button B selects value
*/
function quiz() {
let sugar = getSugar()
if (sugar != "HIGH") {
// All is ok (tick)
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . #
. . . . . . . . . . . . . . . . . . # . . . . # .
# . . . . # . . . . # . # . . # . # . . # . # . .
. . . . . . # . . . . # . . . . # . . . . # . . .
`, 400)
} else {
// Button A changes value, Button B selects value
let ketone = getKetone()
if (ketone != "HIGH") {
// Button A changes value, Button B selects value
let ill = getIll()
if (!ill) {
// Time to rest (jump into bed)
basic.showAnimation(`
. . . . . # # . . . . # . . . . # . . . . . . # . . . . . .
. . . . # . . . . # # # . . # . # . . # . . # . # . . . . #
. . . . # . . . . # . . . . # # # . . # # # . . # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# . . . # # . . . # # . . . # # . . . # # . . . # # . . . #
`, 400)
} else {
// Test more often (clock shows 2 hour interval)
basic.showAnimation(`
. . # . . . . . . . . . . . . . . . . . . # # . . . . . . . . # # . . . . . . . . # # . .
. . # . . . . . . . . . . . . . . . . . . . . # . . . . . . . . . # . . . . . . . . . # .
. . # . . . . # # # . . # . . # # # . . . . # . . . . . . . . . # . . . . . . . . . # . .
. . . . . . . . . . . . # . . . . . . . . # . . . . . . . . . # . . . . . . . . . # . . .
. . . . . . . . . . . . # . . . . . . . . # # # . . . . . . . # # # . . . . . . . # # # .
`, 400)
}
} else {
// Get some help (call the diabetes care team on the phone)
basic.showAnimation(`
. . . . . . . . . . # # # # # # # . . . # # . . . # # . . . # # . . . # # # . . # # . # . # # . . #
. . . . . # # # # # # . . . # # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . .
# # # # # # . . . # . . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . .
# . # . # . . # . . . . # . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . . # . . . .
. # # # . . # # # . . # # # . # # . . . # # . . # # # . # . # # # . . # # . . . # # . . . # # . . .
`, 400)
}
}
}
function waitAnyButton() {
while (!input.buttonIsPressed(Button.A) && !input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
}

View File

@ -1,488 +0,0 @@
let AWasPressed: boolean
let BWasPressed: boolean
let wasShake: boolean
let dots025: Image
dots025 = images.createImage(`
. . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # #
`)
let tests = "DABPXYZSCT"
let test = 0
let prevTest = -1
startIOMonitor()
while (true) {
let testLetter = tests[test]
let autoRun = false
if (testLetter == "D" || testLetter == "A" || testLetter == "B") {
autoRun = true
}
if (!(test == prevTest)) {
basic.showString(tests[test], 200)
prevTest = test
}
if (AWasPressed || autoRun) {
AWasPressed = false
if (testLetter == "D") {
testDisplay()
test = test + 1
} else if (testLetter == "A") {
testButtonA()
test = test + 1
} else if (testLetter == "B") {
testButtonB()
test = test + 1
} else if (testLetter == "P") {
testPads()
} else if (testLetter == "X") {
testTiltX()
} else if (testLetter == "Y") {
testTiltY()
} else if (testLetter == "Z") {
testTiltZ()
} else if (testLetter == "S") {
testShake()
} else if (testLetter == "C") {
testCompass()
} else if (testLetter == "T") {
testTemperature()
} else {
// end of tests
basic.showLeds(`
. . . . .
. . . . #
. . . # .
# . # . .
. # . . .
`, 400)
}
prevTest = -1
AWasPressed = false
BWasPressed = false
} else if (BWasPressed) {
BWasPressed = false
if (test < tests.length - 1) {
test = test + 1
} else {
test = 3
}
} else {
basic.pause(100)
}
}
/**
* flash all LEDs 5 times
*/
function testDisplay() {
for (let i = 0; i < 5; i++) {
basic.plotLeds(`
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
`)
basic.pause(200)
basic.clearScreen()
basic.pause(200)
}
// cycle all LEDs from 1 to 25
basic.showAnimation(`
# . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # # . . . # # # . . # # # # . # # # # #
`, 400)
}
function testButtonA() {
basic.plotLeds(`
. . # . .
. # . # .
. # # # .
. # . # .
. # . # .
`)
// wait for A pressed
while (!input.buttonIsPressed(Button.A)) {
basic.pause(100)
}
basic.plotLeds(`
. # . . .
# . # . .
# # # . .
# . # . .
# . # . .
`)
// wait for A released
while (input.buttonIsPressed(Button.A)) {
basic.pause(100)
}
basic.plotLeds(`
. . # . .
. # . # .
. # # # .
. # . # .
. # . # .
`)
basic.pause(1000)
}
function testTiltX() {
basic.clearScreen()
let prevx = 0
while (!AWasPressed && !BWasPressed) {
basic.pause(100)
let x = input.acceleration(Dimension.X)
let x2 = x / 512 + 2
let x3 = Math.clamp(0, 4, x2)
// sticky trace
led.plot(x3, 0)
// middle line is actual/live
if (x3 != prevx) {
led.unplot(prevx, 2)
prevx = x3
}
led.plot(x3, 2)
// bottom line is -4G, -2G, 1G, +2G, +4G
if (x <= -2048) {
led.plot(0, 4)
} else if (x <= -1024) {
led.plot(1, 4)
} else if (x <= 1024) {
led.plot(2, 4)
} else if (x <= 2048) {
led.plot(3, 4)
} else {
led.plot(4, 4)
}
}
}
function testShake() {
wasShake = false
basic.plotLeds(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . .
`)
while (!AWasPressed && !BWasPressed) {
if (wasShake) {
wasShake = false
basic.plotLeds(`
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
`)
basic.pause(500)
basic.plotLeds(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . .
`)
} else {
basic.pause(100)
}
}
}
function testCompass() {
if (input.compassHeading() < 0) {
input.calibrate()
}
basic.clearScreen()
while (!AWasPressed && !BWasPressed) {
let d = input.compassHeading()
d = d / 22
d = Math.clamp(0, 15, d)
d = (d + 2) % 16
if (d < 4) {
led.plot(d, 0)
} else if (d < 8) {
led.plot(4, d - 4)
} else if (d < 12) {
led.plot(4 - d - 8, 4)
} else {
led.plot(0, 4 - d - 12)
}
basic.pause(100)
}
}
function testPads() {
let TESTSPEED = 500
AWasPressed = false
BWasPressed = false
// Make sure all pins are inputs, before test starts
let p0 = pins.digitalReadPin(DigitalPin.P0)
let p1 = pins.digitalReadPin(DigitalPin.P1)
let p2 = pins.digitalReadPin(DigitalPin.P2)
let ok0 = 0
let ok1 = 0
let ok2 = 0
while (!AWasPressed && !BWasPressed) {
basic.clearScreen()
// ## P0 out low, read from P1 and P2
ok0 = 0
pins.digitalWritePin(DigitalPin.P0, 0)
basic.pause(TESTSPEED)
p1 = pins.digitalReadPin(DigitalPin.P1)
p2 = pins.digitalReadPin(DigitalPin.P2)
if (p1 == 0) {
led.plot(0, 0)
ok0 = ok0 + 1
}
if (p2 == 0) {
led.plot(1, 0)
ok0 = ok0 + 1
}
// ## P0 out high, read from P1 and P2
pins.digitalWritePin(DigitalPin.P0, 1)
basic.pause(TESTSPEED)
p1 = pins.digitalReadPin(DigitalPin.P1)
p2 = pins.digitalReadPin(DigitalPin.P2)
if (p1 == 1) {
led.plot(2, 0)
ok0 = ok0 + 1
}
if (p2 == 1) {
led.plot(3, 0)
ok0 = ok0 + 1
}
// set back to an input
p0 = pins.digitalReadPin(DigitalPin.P0)
// ## P1 out low, read from P0 and P2
ok1 = 0
pins.digitalWritePin(DigitalPin.P1, 0)
basic.pause(TESTSPEED)
p0 = pins.digitalReadPin(DigitalPin.P0)
p2 = pins.digitalReadPin(DigitalPin.P2)
if (p0 == 0) {
led.plot(0, 1)
ok1 = ok1 + 1
}
if (p2 == 0) {
led.plot(1, 1)
ok1 = ok1 + 1
}
// ## P1 out high, read from P0 and P2
pins.digitalWritePin(DigitalPin.P1, 1)
basic.pause(TESTSPEED)
p0 = pins.digitalReadPin(DigitalPin.P0)
p2 = pins.digitalReadPin(DigitalPin.P2)
if (p0 == 1) {
led.plot(2, 1)
ok1 = ok1 + 1
}
if (p2 == 1) {
led.plot(3, 1)
ok1 = ok1 + 1
}
// set back to an input
p0 = pins.digitalReadPin(DigitalPin.P1)
// ## P2 out low, read from P0 and P1
ok2 = 0
pins.digitalWritePin(DigitalPin.P2, 0)
basic.pause(TESTSPEED)
p0 = pins.digitalReadPin(DigitalPin.P0)
p1 = pins.digitalReadPin(DigitalPin.P1)
if (p0 == 0) {
led.plot(0, 2)
ok2 = ok2 + 1
}
if (p1 == 0) {
led.plot(1, 2)
ok2 = ok2 + 1
}
// ## P2 out high, read from P0 and P1
pins.digitalWritePin(DigitalPin.P2, 1)
basic.pause(TESTSPEED)
p0 = pins.digitalReadPin(DigitalPin.P0)
p1 = pins.digitalReadPin(DigitalPin.P1)
if (p0 == 1) {
led.plot(2, 2)
ok2 = ok2 + 1
}
if (p1 == 1) {
led.plot(3, 2)
ok2 = ok2 + 1
}
p2 = pins.digitalReadPin(DigitalPin.P2)
// ## Assess final test status
if (ok0 == 4) {
led.plot(4, 0)
}
basic.pause(TESTSPEED)
if (ok1 == 4) {
led.plot(4, 1)
}
basic.pause(TESTSPEED)
if (ok2 == 4) {
led.plot(4, 2)
}
basic.pause(TESTSPEED)
if (ok0 + ok1 + ok2 == 12) {
// all tests passed
led.plot(4, 4)
}
// ## Test cycle finished
basic.pause(1000)
}
// intentionally don't clear A and B flags, so main loop can process them.
}
/**
* - show number of dots on screen (0..25) to represent temperature in celcius
*/
function testTemperature() {
while (!AWasPressed && !BWasPressed) {
let temp = input.temperature() - 10
temp = Math.clamp(0, 25, temp)
dots025.plotFrame(temp)
basic.pause(500)
}
}
function testButtonB() {
basic.plotLeds(`
. # # . .
. # . # .
. # # . .
. # . # .
. # # . .
`)
// wait for B pressed
while (!input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
basic.plotLeds(`
. . # # .
. . # . #
. . # # .
. . # . #
. . # # .
`)
// wait for B released
while (input.buttonIsPressed(Button.B)) {
basic.pause(100)
}
basic.plotLeds(`
. # # . .
. # . # .
. # # . .
. # . # .
. # # . .
`)
basic.pause(1000)
}
function testTiltY() {
basic.clearScreen()
let prevy = 0
while (!AWasPressed && !BWasPressed) {
basic.pause(100)
let y = input.acceleration(Dimension.Y)
let y2 = y / 512 + 2
let y3 = Math.clamp(0, 4, y2)
// sticky trace
led.plot(0, y3)
// middle line is actual/live
if (y3 != prevy) {
led.unplot(2, prevy)
prevy = y3
}
led.plot(2, y3)
// bottom line is -4G, -2G, 1G, +2G, +4G
if (y <= -2048) {
led.plot(4, 0)
} else if (y <= -1024) {
led.plot(4, 1)
} else if (y <= 1024) {
led.plot(4, 2)
} else if (y <= 2048) {
led.plot(4, 3)
} else {
led.plot(4, 4)
}
}
}
function testTiltZ() {
basic.clearScreen()
while (!AWasPressed && !BWasPressed) {
let z = input.acceleration(Dimension.Z)
if (z < -2000) {
basic.plotLeds(`
# . . . #
# . . . #
# . . . #
# . . . #
# . . . #
`)
} else if (z <= -1030) {
basic.plotLeds(`
. # . # .
. # . # .
. # . # .
. # . # .
. # . # .
`)
} else if (z <= 1000) {
basic.plotLeds(`
. . # . .
. . # . .
. . # . .
. . # . .
. . # . .
`)
} else if (z <= 1030) {
basic.plotLeds(`
. . . . .
. . . . .
# # # # #
. . . . .
. . . . .
`)
} else if (z <= 2000) {
basic.plotLeds(`
. . . . .
# # # # #
. . . . .
# # # # #
. . . . .
`)
} else {
basic.plotLeds(`
# # # # #
. . . . .
. . . . .
. . . . .
# # # # #
`)
}
basic.pause(100)
}
}
function startIOMonitor() {
input.onButtonPressed(Button.A, () => {
AWasPressed = true
})
input.onButtonPressed(Button.B, () => {
BWasPressed = true
})
input.onShake(() => {
wasShake = true
})
}

View File

@ -1,3 +1,175 @@
/*******************************
Site Overrides
*******************************/
/*--------------
Rotate In
---------------*/
/* Inward */
.transition.rotate {
animation-duration: 0.6s;
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
.transition.rotate.in {
animation-name: rotateIn;
}
.transition[class*="rotate down left"].in {
animation-name: rotateInDownLeft;
}
.transition[class*="rotate down right"].in {
animation-name: rotateInDownRight;
}
.transition[class*="rotate up left"].in {
animation-name: rotateInUpLeft;
}
.transition[class*="rotate up right"].in {
animation-name: rotateInUpRight;
}
/* Outward */
.transition.rotate.out {
animation-name: rotateOut;
}
.transition[class*="rotate down left"].out {
animation-name: rotateOutDownLeft;
}
.transition[class*="rotate down right"].out {
animation-name: rotateOutDownRight;
}
.transition[class*="rotate up left"].out {
animation-name: rotateOutUpLeft;
}
.transition[class*="rotate up right"].out {
animation-name: rotateOutUpRight;
}
/* In */
@keyframes rotateIn {
from {
transform-origin: center;
transform: rotate3d(0, 0, 1, -200deg);
opacity: 0;
}
to {
transform-origin: center;
transform: none;
opacity: 1;
}
}
@keyframes rotateInDownLeft {
from {
transform-origin: left bottom;
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
to {
transform-origin: left bottom;
transform: none;
opacity: 1;
}
}
@keyframes rotateInDownRight {
from {
transform-origin: right bottom;
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
to {
transform-origin: right bottom;
transform: none;
opacity: 1;
}
}
@keyframes rotateInUpLeft {
from {
transform-origin: left bottom;
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
to {
transform-origin: left bottom;
transform: none;
opacity: 1;
}
}
@keyframes rotateInUpRight {
from {
transform-origin: right bottom;
transform: rotate3d(0, 0, 1, -90deg);
opacity: 0;
}
to {
transform-origin: right bottom;
transform: none;
opacity: 1;
}
}
/* Out */
@keyframes rotateOut {
from {
transform-origin: center;
opacity: 1;
}
to {
transform-origin: center;
transform: rotate3d(0, 0, 1, 200deg);
opacity: 0;
}
}
@keyframes rotateOutDownLeft {
from {
transform-origin: left bottom;
opacity: 1;
}
to {
transform-origin: left bottom;
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
}
@keyframes rotateOutDownRight {
from {
transform-origin: right bottom;
opacity: 1;
}
to {
transform-origin: right bottom;
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
}
@keyframes rotateOutUpLeft {
from {
transform-origin: left bottom;
opacity: 1;
}
to {
transform-origin: left bottom;
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
}
@keyframes rotateOutUpRight {
from {
transform-origin: right bottom;
opacity: 1;
}
to {
transform-origin: right bottom;
transform: rotate3d(0, 0, 1, 90deg);
opacity: 0;
}
}

View File

@ -4,6 +4,7 @@
@import 'themes/default/globals/site.variables';
@import 'themes/pxt/globals/site.variables';
@import 'site/globals/site.variables';
@import 'themes/default/collections/menu.variables';
/* Reference import */
@import (reference) "semantic.less";
@ -36,6 +37,10 @@
&:extend(.yellow all);
}
#filelist .menu {
width: 100%;
}
/*******************************
Blockly
*******************************/
@ -44,6 +49,21 @@
border-radius:5px;
}
/* Specifying top and bottom rounded toolbox borders. */
.blocklyTreeRow.blocklyTreeRowTop {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
.blocklyTreeRow.blocklyTreeRowBottom {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.blocklyTreeRow:hover {
background: @invertedBackground !important;
}
/* This removes any padding at the top of the toolbox */
.blocklyTreeRoot {
padding: 0px !important;
@ -67,31 +87,68 @@
padding:7px;
}
/* Blockly Toolbox Buttons */
#blocklyToolboxButtons .blocklyAddPackageButton {
background-color: rgba(0, 0, 0, 0.3);
color: white;
}
#blocklyToolboxButtons .blocklyUndoButton {
background-color: rgba(0, 0, 0, 0.3);
color: white;
}
.organization {
top: 1.6em;
}
/* Mobile */
@media only screen and (max-width: @largestMobileScreen) {
@media only screen and (max-width: @largestMobileEditorBreakpoint) {
.blocklyTreeLabel {
font-size: 0.5rem !important;
}
.organization {
top: auto;
}
}
/* Tablet */
@media only screen and (min-width: @tabletBreakpoint) and (max-width: @largestTabletScreen) {
@media only screen and (min-width: @tabletEditorBreakpoint) and (max-width: @largestTabletEditorBreakpoint) {
.organization {
top: auto;
}
/* Blockly Toolbox buttons */
#blocklyToolboxButtons {
margin-right: 0.5rem;
margin-left: 0.5rem;
}
}
/* Small Monitor */
@media only screen and (min-width: @computerBreakpoint) and (max-width: @largestSmallMonitor) {
@media only screen and (min-width: @computerEditorBreakpoint) and (max-width: @largestSmallMonitorEditorBreakpoint) {
.organization {
top: auto;
}
.blocklyTreeRow {
width: 230px;
}
/* Blockly Toolbox buttons */
#blocklyToolboxButtons {
margin-right: 1rem;
margin-left: 1rem;
}
}
/* Large Monitor */
@media only screen and (min-width: @largeMonitorBreakpoint) {
@media only screen and (min-width: @largeMonitorEditorBreakpoint) {
.blocklyTreeRow {
width: 230px;
}
/* Blockly Toolbox buttons */
#blocklyToolboxButtons {
margin-right: 2rem;
margin-left: 2rem;
}
}
/*******************************

View File

@ -32,7 +32,7 @@
@input : 'pxt';
@label : 'pxt';
@list : 'pxt';
@loader : 'pxt';
@loader : 'pulsar';
@rail : 'pxt';
@reveal : 'pxt';
@segment : 'pxt';
@ -41,7 +41,7 @@
/* Collections */
@breadcrumb : 'default';
@form : 'default';
@grid : 'default';
@grid : 'pxt';
@menu : 'pxt';
@message : 'default';
@table : 'default';