Compare commits

...

29 Commits

Author SHA1 Message Date
721ae893bb 0.2.12 2016-04-02 21:40:55 -07:00
45dd3fc1bf Bump kindscript to 0.2.14 2016-04-02 21:40:54 -07:00
9626207a61 Try to run lang-test0 during build 2016-04-02 21:36:00 -07:00
87b6e0aba1 Make lang-test0 work 2016-04-02 21:34:29 -07:00
0d9890cfac Add some image methods 2016-04-02 20:53:51 -07:00
5d40750542 Add missing control stuff 2016-04-02 20:47:27 -07:00
bd09754466 Move pin stuff to pins 2016-04-02 20:44:29 -07:00
5740133921 Moving simulator stuff into namespaces to match C++ 2016-04-02 20:35:38 -07:00
4e23553824 Naming fixes 2016-04-02 20:35:22 -07:00
9b68519aff Disable two image blocks - they crash block injection 2016-04-02 18:09:31 -07:00
e6dc3b8974 Remove shims 2016-04-02 17:49:31 -07:00
53634f4d6a Convert bluetooth to new style 2016-04-02 17:47:49 -07:00
3ee0c6ea42 Radio stuff moved for new style 2016-04-02 17:34:06 -07:00
ef098cbd28 Use -core v0.1.2 2016-04-02 14:18:10 -07:00
356b17cb13 Moving lang-test0 from kindscript main 2016-04-02 14:18:00 -07:00
47d382135b Use new APIs in the core 2016-04-02 13:44:29 -07:00
241da7fbed Add remaining shims 2016-04-02 11:22:36 -07:00
feb17c5e45 Remove remaining external shims 2016-04-01 22:46:06 -07:00
6559f386d2 Move most of core stuff 2016-04-01 22:32:33 -07:00
6bf46577f9 Migrate serial 2016-04-01 22:00:42 -07:00
0130ecb0c2 Remove shim=s 2016-04-01 21:53:50 -07:00
9820a035ce Migrate LED shims 2016-04-01 21:52:25 -07:00
88acd9254d Remove redundant shim annotations 2016-04-01 21:27:22 -07:00
650fe61dcd Move more stuff to C++ 2016-04-01 21:26:06 -07:00
c4e57e0165 0.2.11 2016-04-01 20:10:45 -07:00
a55ddcbab3 Bump kindscript to 0.2.11 2016-04-01 20:10:44 -07:00
f58508afa2 Event implementation 2016-04-01 19:59:14 -07:00
4b92de7516 Implement Images 2016-04-01 19:55:51 -07:00
6176963504 Fix pin names 2016-04-01 18:29:39 -07:00
38 changed files with 3083 additions and 1150 deletions

View File

@ -3,6 +3,7 @@ node_js:
- "5.7.0"
script:
- "node node_modules/kindscript/built/kind.js travis"
- "cd libs/lang-test0; node ../../node_modules/kindscript/built/kind.js run"
- "node node_modules/kindscript/built/kind.js uploaddoc"
sudo: false
notifications:

12
libs/lang-test0/kind.json Normal file
View File

@ -0,0 +1,12 @@
{
"name": "lang-test0",
"description": "Test for the TypeScript -> HEX compiler",
"installedVersion": "file:.",
"files": [
"lang-test0.ts"
],
"public": true,
"dependencies": {
"microbit": "file:../microbit"
}
}

View File

@ -0,0 +1,724 @@
//
// Note that this is supposed to run from command line.
// Do not use anything besides basic.pause, control.inBackground, console.log
//
//% shim=ksrt::panic
function panic(code2: number): void { }
function msg(s: string): void {
//console.log(s)
//basic.pause(50);
}
function assert(cond: boolean, msg_: string) {
if (!cond) {
console.log("ASSERT: " + msg_);
panic(45);
}
}
//
// start tests
//
var glb1: number;
var s2: string;
var x: number;
var action: Action;
var tot: string;
var lazyAcc: number;
var sum: number;
var xyz = 12;
console.log("Starting...")
//lib.print_17(3);
basic.showNumber(0);
//assert(lib3.getX() == 17 * 3, "");
testNums();
testStrings();
testNumCollection();
testStringCollection();
testStringOps();
testReccoll();
inBg();
testAction(1);
testAction(7);
testIter();
testActionSave();
testLazyOps();
testRefLocals();
testByRefParams();
testFunDecl();
testDefaultArgs();
testMemoryFree();
testMemoryFreeHOF();
postPreFix()
eqOp()
testEnums()
// test some top-level code
let xsum = 0;
for (let i = 0; i < 11; ++i) {
xsum = xsum + i;
}
assert(xsum == 55, "mainfor")
control.inBackground(() => {
xsum = xsum + 10;
})
basic.pause(20)
assert(xsum == 65, "mainforBg")
assert(xyz == 12, "init")
function incrXyz() {
xyz++;
return 0;
}
var unusedInit = incrXyz();
assert(xyz == 13, "init2")
testClass()
basic.showNumber(1)
console.log("ALL TESTS OK")
function defaultArgs(x: number, y = 3, z = 7) {
return x + y + z;
}
function testDefaultArgs() {
msg("testDefaultArgs");
assert(defaultArgs(1) == 11, "defl0")
assert(defaultArgs(1, 4) == 12, "defl1")
assert(defaultArgs(1, 4, 8) == 13, "defl2")
assert(optargs(1) == 1, "opt0");
assert(optargs(1, 2) == 3, "opt1");
assert(optargs(1, 2, 3) == 3, "opt2");
assert(optstring(3) == 6, "os0")
assert(optstring(3, "7") == 10, "os1")
assert(optstring2(3) == 6, "os0")
assert(optstring2(3, "7") == 10, "os1")
}
function optargs(x: number, y ?: number, z ?: number) {
return x + y;
}
function optstring(x: number, s ?: string) {
if (s != null) {
return parseInt(s) + x;
}
return x * 2;
}
function optstring2(x: number, s: string = null) {
if (s != null) {
return parseInt(s) + x;
}
return x * 2;
}
function testNums(): void {
let x = 40 + 2;
assert(x == 42, "add");
x = 40 / 2;
assert(x == 20, "div");
let r = fib(15);
msg("FIB" + r);
assert(r == 987, "fib");
let x3 = doStuff(x, 2);
assert(x3 == 10, "call order");
glb1 = 5;
incrBy_2();
assert(glb1 == 7, "glb1");
incrBy_2();
assert(glb1 == 9, "glb2");
assert(Math.abs(-42) == 42, "abs");
assert(Math.abs(42) == 42, "abs");
assert(Math.sign(42) == 1, "abs");
testIf();
assert((3 & 6) == 2, "&")
assert((3 | 6) == 7, "|")
assert((3 ^ 6) == 5, "^")
assert((-10 >> 2) == -3, ">>")
assert((-10 >>> 20) == 4095, ">>>")
assert((-10 << 2) == -40, "<<")
assert((10 << 2) == 40, "<<+")
assert((10 >> 2) == 2, ">>+")
assert((10 >>> 2) == 2, ">>>+")
assert(1000000 * 1000000 == -727379968, "*")
assert(100000001 * 100000001 == 2074919425, "*2")
assert(105 % 100 == 5, "perc")
}
function fib(p: number): number {
if (p <= 2) {
return p;
}
let p2 = p - 1;
return fib(p2) + fib(p - 2);
}
function doStuff(x: number, x2: number): number {
let x3 = x / x2;
return x3;
}
function testIf(): void {
let b = false;
if (!b) {
glb1 = 7;
} else {
assert(false, "b0");
}
assert(glb1 == 7, "glb3");
if (b) {
assert(false, "b1");
} else {
glb1 = 8;
}
assert(glb1 == 8, "glb3");
}
function incrBy_2(): void {
glb1 = glb1 + 2;
}
function testStrings(): void {
assert((42).toString() == "42", "42");
let s = "live";
assert(s == "live", "hello eq");
s = s + "4OK";
s2 = s;
assert(s.charCodeAt(4) == 52, "hello eq2");
assert(s.charAt(4) == "4", "hello eq2X");
assert(s[4] == "4", "hello eq2X");
assert(s.length == 7, "len7");
s = "";
for (let i = 0; i < 10; i++) {
s = s + i;
}
assert(s == "0123456789", "for");
let x = 10;
s = "";
while (x >= 0) {
s = s + x;
x = x - 1;
}
assert(s == "109876543210", "while");
msg(s);
msg(s2);
s2 = "";
// don't leak ref
x = 21
s = "foo"
s = `a${ x * 2 }X${ s }X${ s }Z`
assert(s == "a42XfooXfoo" + "Z", "`")
assert("X" + true == "Xt" + "rue", "boolStr")
}
function testNumCollection(): void {
let collXYZ: number[] =[];
assert(collXYZ.length == 0, "");
collXYZ.push(42);
assert(collXYZ.length == 1, "");
collXYZ.push(22);
assert(collXYZ[1] == 22, "");
collXYZ.splice(0, 1);
assert(collXYZ[0] == 22, "");
collXYZ.removeElement(22);
assert(collXYZ.length == 0, "");
for (let i = 0; i < 100; i++) {
collXYZ.push(i);
}
assert(collXYZ.length == 100, "");
collXYZ =[1, 2, 3];
assert(collXYZ.length == 3, "cons");
assert(collXYZ[0] == 1, "cons0");
assert(collXYZ[1] == 2, "cons1");
assert(collXYZ[2] == 3, "cons2");
}
function testStringCollection(): void {
let coll = (< string[] >[]);
coll.push("foobar");
coll.push((12).toString());
coll.push(coll[0] + "xx");
assert(coll.indexOf("12") == 1, "idx");
coll =[
"a" + "b",
coll[2],
]
assert(coll[0] == "ab", "")
assert(coll[1] == "foob" + "arxx", "")
assert(coll.length == 2, "")
}
function testStringOps(): void {
assert("foo".concat("bar") == "foobar", "concat");
assert("xAb".charCodeAt(1) == 65, "code at");
assert("B".charCodeAt(0) == 66, "tcc");
assert(parseInt("-123") == -123, "tonum");
assert("fo"[1] == "o", "at");
assert("fo".length == 2, "count");
assert("fo".charCodeAt(17) == 0, "ct oor");
}
class Testrec {
str: string;
num: number;
bool: boolean;
str2: string;
}
function recordId(x: Testrec) {
lazyAcc++
return x
}
function postPreFix() {
msg("postPref")
let x = new Testrec()
lazyAcc = 0
recordId(x).num = 12
assert(x.num == 12 && lazyAcc == 1, "X0")
let y = recordId(x).num++
assert(x.num == 13 && lazyAcc == 2, "X1")
assert(y == 12, "X2")
y = ++recordId(x).num
assert(y == 14 && x.num == 14 && lazyAcc == 3, "X2")
recordId(x).num >>= 1
assert(x.num == 7, "X3")
assert(lazyAcc == 4, "X4")
}
function eqOp() {
msg("eqOp")
let x = 12
assert((x += 10) == 22, "Y0")
assert(x == 22, "Y1")
x /= 2
assert(x == 11, "Y2")
let s = ("fo" + 1)
let t = ("ba" + 2)
s += t
assert(s == "fo1b" + "a2", "fb")
}
function testRec0(): Testrec {
let testrec = new Testrec();
testrec.str2 = "Hello" + " world";
testrec.str = testrec.str2;
testrec.num = 42;
assert(testrec.str == "Hello world", "recstr");
assert(testrec.num == 42, "recnum");
msg(testrec.str2);
let testrec2 = < Testrec > null;
assert(testrec2 == null, "isinv");
assert(testrec == testrec, "eq");
assert(testrec != null, "non inv");
return testrec;
}
function testReccoll(): void {
let coll: Testrec[] =[];
let item = testRec0();
msg("in reccoll");
coll.push(item);
}
function inBg() {
let k = 7
let q = 14
let rec = new Testrec();
glb1 = 0
control.inBackground(() => {
glb1 = glb1 + 10 + (q - k)
rec.str = "foo"
})
control.inBackground(() => {
glb1 = glb1 + 1
})
basic.pause(50)
assert(glb1 == 18, "inbg0")
assert(rec.str == "foo", "inbg1")
}
function runTwice(fn: Action): void {
msg("r2 start");
fn();
fn();
msg("r2 stop");
}
function iter(max: number, fn: (v: number) => void) {
for (var i = 0; i < max; ++i) {
fn(i);
}
}
function testIter() {
x = 0
iter(10, v => {
x = x + (v + 1)
})
assert(x == 55, "55")
}
function testAction(p: number): void {
let s = "hello" + "1";
let coll =[] as number[];
let p2 = p * 2;
x = 42;
runTwice(() => {
x = x + p + p2;
coll.push(x);
msg(s + x);
});
assert(x == 42 + p * 6, "run2");
assert(coll.length == 2, "run2");
}
function add7() {
sum = sum + 7;
}
function testFunDecl() {
msg("testFunDecl");
let x = 12;
sum = 0;
function addX() {
sum = sum + x;
}
function add10() {
sum = sum + 10;
}
runTwice(addX)
assert(sum == 24, "cap")
msg("testAdd10");
runTwice(add10);
msg("end-testAdd10");
assert(sum == 44, "nocap");
runTwice(add7);
assert(sum == 44 + 14, "glb")
addX();
add10();
assert(sum == 44 + 14 + x + 10, "direct");
}
function saveAction(fn: Action): void {
action = fn;
}
function saveGlobalAction(): void {
let s = "foo" + "42";
tot = "";
saveAction(() => {
tot = tot + s;
});
}
function testActionSave(): void {
saveGlobalAction();
runTwice(action);
msg(tot);
assert(tot == "foo42foo42", "");
tot = "";
action = null;
}
function testLazyOps(): void {
lazyAcc = 0;
if (incrLazyAcc(10, false) && incrLazyAcc(1, true)) {
assert(false, "");
} else {
assert(lazyAcc == 10, "lazy1");
}
assert(lazyAcc == 10, "lazy2");
if (incrLazyAcc(100, true) && incrLazyAcc(1, false)) {
assert(false, "");
} else {
assert(lazyAcc == 111, "lazy4");
}
lazyAcc = 0;
if (incrLazyAcc(100, true) && incrLazyAcc(8, true)) {
assert(lazyAcc == 108, "lazy5");
} else {
assert(false, "");
}
lazyAcc = 0;
if (incrLazyAcc(10, true) || incrLazyAcc(1, true)) {
assert(lazyAcc == 10, "lazy1b");
} else {
assert(false, "");
}
assert(lazyAcc == 10, "lazy2xx");
if (incrLazyAcc(100, false) || incrLazyAcc(1, false)) {
assert(false, "");
} else {
assert(lazyAcc == 111, "lazy4x");
}
lazyAcc = 0;
if (incrLazyAcc(100, false) || incrLazyAcc(8, true)) {
assert(lazyAcc == 108, "lazy5");
} else {
assert(false, "");
}
lazyAcc = 0;
if (incrLazyAcc(10, true) && incrLazyAcc(1, true) && incrLazyAcc(100, false)) {
assert(false, "");
} else {
assert(lazyAcc == 111, "lazy10");
}
lazyAcc = 0;
if (incrLazyAcc(10, true) && incrLazyAcc(1, true) || incrLazyAcc(100, false)) {
assert(lazyAcc == 11, "lazy101");
} else {
assert(false, "");
}
lazyAcc = 0;
assert((true ? incrLazyNum(1, 42): incrLazyNum(10, 36)) == 42, "?:")
assert(lazyAcc == 1, "?:0");
assert((false ? incrLazyNum(1, 42): incrLazyNum(10, 36)) == 36, "?:1")
assert(lazyAcc == 11, "?:2");
}
function incrLazyAcc(delta: number, res: boolean): boolean {
lazyAcc = lazyAcc + delta;
return res;
}
function incrLazyNum(delta: number, res: number) {
lazyAcc = lazyAcc + delta;
return res;
}
function testRefLocals(): void {
msg("start test ref locals");
let s = "";
// For 4 or more it runs out of memory
for (let i = 0; i < 3; i++) {
msg(i + "");
let copy = i;
control.inBackground(() => {
basic.pause(10 * i);
copy = copy + 10;
});
control.inBackground(() => {
basic.pause(20 * i);
s = s + copy;
});
}
basic.pause(200);
assert(s == "101112", "reflocals");
}
function byRefParam_0(p: number): void {
control.inBackground(() => {
basic.pause(1);
sum = sum + p;
});
p = p + 1;
}
function byRefParam_2(pxx: number): void {
pxx = pxx + 1;
control.inBackground(() => {
basic.pause(1);
sum = sum + pxx;
});
}
function testByRefParams(): void {
msg("testByRefParams");
refparamWrite("a" + "b");
refparamWrite2(new Testrec());
refparamWrite3(new Testrec());
sum = 0;
let x = 1;
control.inBackground(() => {
basic.pause(1);
sum = sum + x;
});
x = 2;
byRefParam_0(4);
byRefParam_2(10);
basic.pause(30);
assert(sum == 18, "by ref");
}
function refparamWrite(s: string): void {
s = s + "c";
assert(s == "abc", "abc");
}
function refparamWrite2(testrec: Testrec): void {
testrec = new Testrec();
assert(testrec.bool == false, "");
}
function refparamWrite3(testrecX: Testrec): void {
control.inBackground(() => {
basic.pause(1);
assert(testrecX.str == "foo", "ff");
testrecX.str = testrecX.str + "x";
});
testrecX = new Testrec();
testrecX.str = "foo";
basic.pause(30);
assert(testrecX.str == "foox", "ff2");
}
function testMemoryFree(): void {
msg("testMemoryFree");
for (let i = 0; i < 1000; i++) {
allocImage();
}
}
function runOnce(fn: Action): void {
fn();
}
function createObj() {
return new Testrec();
}
function testMemoryFreeHOF(): void {
msg("testMemoryFreeHOF");
for (let i = 0; i < 1000; i++) {
runOnce(() => {
let tmp = createObj();
});
}
}
function allocImage(): void {
let tmp = createObj();
}
class Foo {
pin: number;
buf: number[];
constructor(k: number, l: number) {
this.pin = k - l
}
setPin(p: number) {
this.pin = p
}
getPin() {
return this.pin
}
init() {
this.buf =[1, 2]
}
}
function testClass() {
let f = new Foo(272, 100);
assert(f.getPin() == 172, "ctor")
f.setPin(42)
assert(f.getPin() == 42, "getpin")
}
enum En {
A,
B,
C,
D = 4200,
E,
}
enum En2 {
D0 = En.D,
D1,
D2 = 1,
}
function testEnums() {
msg("enums")
let k = En.C as number
assert(k == 2, "e0")
k = En.D as number
assert(k == 4200, "e1")
k = En.E as number
assert(k == 4201, "e43")
k = En2.D0 as number
assert(k == 4200, "eX0")
k = En2.D1 as number
assert(k == 4201, "eX1")
msg("enums0")
assert(switchA(En.A) == 7, "s1")
assert(switchA(En.B) == 7, "s2")
assert(switchA(En.C) == 12, "s3")
assert(switchA(En.D) == 13, "s4")
assert(switchA(En.E) == 12, "s5")
assert(switchA(-3 as En) == 12, "s6")
msg("enums1")
assert(switchB(En.A) == 7, "x1")
assert(switchB(En.B) == 7, "x2")
assert(switchB(En.C) == 17, "x3")
assert(switchB(En.D) == 13, "x4")
assert(switchB(En.E) == 14, "x5")
}
function switchA(e: En) {
let r = 12;
switch (e) {
case En.A:
case En.B: return 7;
case En.D: r = 13; break;
}
return r
}
function switchB(e: En) {
let r = 33;
switch (e) {
case En.A:
case En.B: return 7;
case En.D: r = 13; break;
case En.E: r = 14; break;
default: return 17;
}
return r;
}

View File

@ -1,6 +1,8 @@
#include "BitVM.h"
#include "kindscript.h"
#include "MESEvents.h"
using namespace kindscript;
enum class MesCameraEvent {
//% block="take photo"
TakePhoto = MES_CAMERA_EVT_TAKE_PHOTO,
@ -119,3 +121,96 @@ enum class MesDpadButtonInfo {
};
//% color=156 weight=80
namespace devices {
static void genEvent(int id, int event) {
MicroBitEvent e(id, event);
}
/**
* Sends a ``camera`` command to the parent device.
* @param event TODO
*/
//% weight=30 help=devices/tell-camera-to
//% blockId=devices_camera icon="\uf030" block="tell camera to|%property" blockGap=8
void tellCameraTo(MesCameraEvent event) {
genEvent(MES_CAMERA_ID, (int)event);
}
/**
* Sends a ``remote control`` command to the parent device.
* @param event TODO
*/
//% weight=29 help=devices/tell-remote-control-to
//% blockId=devices_remote_control block="tell remote control to|%property" blockGap=14 icon="\uf144"
void tellRemoteControlTo(MesRemoteControlEvent event) {
genEvent(MES_REMOTE_CONTROL_ID, (int)event);
}
/**
* Sends an ``alert`` command to the parent device.
* @param event TODO
*/
//% weight=27 help=devices/raise-alert-to
//% blockId=devices_alert block="raise alert to|%property" icon="\uf0f3"
void raiseAlertTo(MesAlertEvent event) {
genEvent(MES_ALERTS_ID, (int)event);
}
/**
* Registers code to run when the device notifies about a particular event.
* @param event TODO
* @param body TODO
*/
//% help=devices/on-notified weight=26
//% blockId=devices_device_info_event block="on notified" icon="\uf10a"
void onNotified(MesDeviceInfo event, Action body) {
registerWithDal(MES_DEVICE_INFO_ID, (int)event, body);
}
/**
* Register code to run when the micro:bit receives a command from the paired gamepad.
* @param name TODO
* @param body TODO
*/
//% help=devices/on-gamepad-button weight=40
//% weight=25
//% blockId=devices_gamepad_event block="on gamepad button|%NAME" icon="\uf11b"
void onGamepadButton(MesDpadButtonInfo name, Action body) {
registerWithDal(MES_DPAD_CONTROLLER_ID, (int)name, body);
}
static int _signalStrength = -1;
static void signalStrengthHandler(MicroBitEvent ev) {
// keep in sync with MESEvents.h
_signalStrength = ev.value - 1;
}
static void initSignalStrength() {
if (_signalStrength < 0) {
_signalStrength = 0;
uBit.MessageBus.listen(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, signalStrengthHandler);
}
}
/**
* Returns the last signal strength reported by the paired device.
*/
//% help=devices/signal-strength weight=24
//% blockId=devices_signal_strength block="signal strength" blockGap=14 icon="\uf012" blockGap=14
int signalStrength() {
initSignalStrength();
return _signalStrength;
}
/**
* Registers code to run when the device notifies about a change of signal strength.
* @param body TODO
*/
//% weight=23 help=devices/on-signal-strength-changed
//% blockId=devices_signal_strength_changed_event block="on signal strength changed" icon="\uf012"
void onSignalStrengthChanged(Action body) {
initSignalStrength();
registerWithDal(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, body);
}
}

View File

@ -1,64 +0,0 @@
//% color=156 weight=80
namespace devices {
/**
* Sends a ``camera`` command to the parent device.
* @param event TODO
*/
//% weight=30 help=devices/tell-camera-to shim=micro_bit::devices::camera
//% blockId=devices_camera icon="\uf030" block="tell camera to|%property" blockGap=8
export function tellCameraTo(event: MesCameraEvent): void { }
/**
* Sends a ``remote control`` command to the parent device.
* @param event TODO
*/
//% weight=29 help=devices/tell-remote-control-to shim=micro_bit::devices::remote_control
//% blockId=devices_remote_control block="tell remote control to|%property" blockGap=14 icon="\uf144"
export function tellRemoteControlTo(event: MesRemoteControlEvent): void { }
/**
* Sends an ``alert`` command to the parent device.
* @param event TODO
*/
//% weight=27 help=devices/raise-alert-to shim=micro_bit::devices::alert
//% blockId=devices_alert block="raise alert to|%property" icon="\uf0f3"
export function raiseAlertTo(event: MesAlertEvent): void { }
/**
* Registers code to run when the device notifies about a particular event.
* @param event TODO
* @param body TODO
*/
//% shim=micro_bit::onDeviceInfo help=devices/on-notified
//% weight=26
//% blockId=devices_device_info_event block="on notified" icon="\uf10a"
export function onNotified(event: MesDeviceInfo, body: Action): void { }
/**
* Register code to run when the micro:bit receives a command from the paired gamepad.
* @param name TODO
* @param body TODO
*/
//% help=devices/on-gamepad-button weight=40 shim=micro_bit::onGamepadButton
//% weight=25
//% blockId=devices_gamepad_event block="on gamepad button|%NAME" icon="\uf11b"
export function onGamepadButton(name: MesDpadButtonInfo, body: Action): void { }
/**
* Returns the last signal strength reported by the paired device.
*/
//% help=devices/signal-strength weight=24 shim=micro_bit::signalStrength
//% blockId=devices_signal_strength block="signal strength" blockGap=14 icon="\uf012" blockGap=14
export function signalStrength(): number {
return 0;
}
/**
* Registers code to run when the device notifies about a change of signal strength.
* @param body TODO
*/
//% shim=micro_bit::onSignalStrengthChanged weight=23 help=devices/on-signal-strength-changed
//% blockId=devices_signal_strength_changed_event block="on signal strength changed" icon="\uf012"
export function onSignalStrengthChanged(body: Action): void { }
}

View File

@ -121,5 +121,7 @@
//% block="4 up"
_4Up = 16, // MES_DPAD_BUTTON_4_UP
}
declare namespace devices {
}
// Auto-generated. Do not edit. Really.

View File

@ -4,8 +4,8 @@
"files": [
"README.md",
"enums.d.ts",
"devices.cpp",
"devices.ts"
"shims.d.ts",
"devices.cpp"
],
"public": true,
"dependencies": {

67
libs/microbit-devices/shims.d.ts vendored Normal file
View File

@ -0,0 +1,67 @@
// Auto-generated. Do not edit.
//% color=156 weight=80
declare namespace devices {
/**
* Sends a ``camera`` command to the parent device.
* @param event TODO
*/
//% weight=30 help=devices/tell-camera-to
//% blockId=devices_camera icon="\uf030" block="tell camera to|%property" blockGap=8 shim=devices::tellCameraTo
function tellCameraTo(event: MesCameraEvent): void;
/**
* Sends a ``remote control`` command to the parent device.
* @param event TODO
*/
//% weight=29 help=devices/tell-remote-control-to
//% blockId=devices_remote_control block="tell remote control to|%property" blockGap=14 icon="\uf144" shim=devices::tellRemoteControlTo
function tellRemoteControlTo(event: MesRemoteControlEvent): void;
/**
* Sends an ``alert`` command to the parent device.
* @param event TODO
*/
//% weight=27 help=devices/raise-alert-to
//% blockId=devices_alert block="raise alert to|%property" icon="\uf0f3" shim=devices::raiseAlertTo
function raiseAlertTo(event: MesAlertEvent): void;
/**
* Registers code to run when the device notifies about a particular event.
* @param event TODO
* @param body TODO
*/
//% help=devices/on-notified weight=26
//% blockId=devices_device_info_event block="on notified" icon="\uf10a" shim=devices::onNotified
function onNotified(event: MesDeviceInfo, body: () => void): void;
/**
* Register code to run when the micro:bit receives a command from the paired gamepad.
* @param name TODO
* @param body TODO
*/
//% help=devices/on-gamepad-button weight=40
//% weight=25
//% blockId=devices_gamepad_event block="on gamepad button|%NAME" icon="\uf11b" shim=devices::onGamepadButton
function onGamepadButton(name: MesDpadButtonInfo, body: () => void): void;
/**
* Returns the last signal strength reported by the paired device.
*/
//% help=devices/signal-strength weight=24
//% blockId=devices_signal_strength block="signal strength" blockGap=14 icon="\uf012" blockGap=14 shim=devices::signalStrength
function signalStrength(): number;
/**
* Registers code to run when the device notifies about a change of signal strength.
* @param body TODO
*/
//% weight=23 help=devices/on-signal-strength-changed
//% blockId=devices_signal_strength_changed_event block="on signal strength changed" icon="\uf012" shim=devices::onSignalStrengthChanged
function onSignalStrengthChanged(body: () => void): void;
}
// Auto-generated. Do not edit. Really.

5
libs/microbit-radio/enums.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
// Auto-generated. Do not edit.
declare namespace radio {
}
// Auto-generated. Do not edit. Really.

View File

@ -3,6 +3,9 @@
"description": "The radio services",
"files": [
"README.md",
"shims.d.ts",
"enums.d.ts",
"radio.cpp",
"radio.ts"
],
"public": true,

View File

@ -0,0 +1,124 @@
#include "kindscript.h"
using namespace kindscript;
//% color=270 weight=34
namespace radio {
// -------------------------------------------------------------------------
// Radio
// -------------------------------------------------------------------------
bool radioEnabled = false;
PacketBuffer packet;
int radioEnable() {
int r = uBit.radio.enable();
if (r != MICROBIT_OK) return r;
if (!radioEnabled) {
uBit.radio.setGroup(kindscript::programHash());
radioEnabled = true;
}
return r;
}
void broadcastMessage(int message) {
if (radioEnable() != MICROBIT_OK) return;
uBit.radio.event.eventReceived(MicroBitEvent(MES_BROADCAST_GENERAL_ID, message, CREATE_ONLY));
}
void onBroadcastMessageReceived(int message, Action f) {
if (radioEnable() != MICROBIT_OK) return;
registerWithDal(MES_BROADCAST_GENERAL_ID, message, f);
}
/**
* Broadcasts 4 numbers over radio to any connected micro:bit in the group.
*/
//% help=radio/send-numbers
//% weight=59
//% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3"
void sendNumbers(int value_0, int value_1, int value_2, int value_3) {
if (radioEnable() != MICROBIT_OK) return;
int buf[] = { value_0, value_1, value_2, value_3 };
uBit.radio.datagram.send((uint8_t*)buf, 4*sizeof(int));
}
/**
* Registers code to run when a packet is received over radio.
*/
//% help=radio/on-data-received
//% weight=50
//% blockId=radio_datagram_received_event block="on data received" blockGap=8
void onDataReceived(Action body) {
if (radioEnable() != MICROBIT_OK) return;
registerWithDal(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, body);
}
/**
* Reads a number at a given index, between ``0`` and ``3``, from the packet received by ``receive number``. Not supported in simulator.
* @param index index of the number to read from 0 to 3. 1 eg
*/
//% help=radio/received-number-at
//% weight=45
//% blockId=radio_datagram_received_number_at block="receive number|at %VALUE" blockGap=8
int receivedNumberAt(int index) {
if (radioEnable() != MICROBIT_OK) return 0;
if (0 <= index && index < packet.length() / 4) {
// packet.getBytes() is not aligned
int r;
memcpy(&r, packet.getBytes() + index * 4, 4);
return r;
}
return 0;
}
/**
* Reads the next packet as a number from the radio queue.
*/
//% help=radio/receive-number
//% weight=46
//% blockId=radio_datagram_receive block="receive number" blockGap=8
int receiveNumber()
{
if (radioEnable() != MICROBIT_OK) return 0;
packet = uBit.radio.datagram.recv();
return receivedNumberAt(0);
}
/**
* Gets the received signal strength indicator (RSSI) from the packet received by ``receive number``. Not supported in simulator.
* namespace=radio
*/
//% help=radio/received-signal-strength
//% weight=40
//% blockId=radio_datagram_rssi block="received signal strength"
int receivedSignalStrength() {
if (radioEnable() != MICROBIT_OK) return 0;
return packet.getRSSI();
}
/**
* Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.
* @ param id the group id between ``0`` and ``255``, 1 eg
*/
//% help=radio/set-group
//% weight=10
//% blockId=radio_set_group block="set group %ID"
void setGroup(int id) {
if (radioEnable() != MICROBIT_OK) return;
uBit.radio.setGroup(id);
}
/**
* Change the output power level of the transmitter to the given value.
* @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest, 7 eg
*/
//% help=radio/set-transmit-power
//% weight=9
//% blockId=radio_set_transmit_power block="set transmit power %power"
void setTransmitPower(int power) {
if (radioEnable() != MICROBIT_OK) return;
uBit.radio.setTransmitPower(power);
}
}

View File

@ -9,89 +9,4 @@ namespace radio {
export function sendNumber(value: number) : void {
sendNumbers(value, 0, 0, 0);
}
/**
* Broadcasts 4 numbers over radio to any connected micro:bit in the group.
*/
//% help=radio/send-numbers
//% shim=micro_bit::datagramSendNumbers
//% weight=59
//% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3"
export function sendNumbers(value_0: number, value_1: number, value_2: number, value_3: number) : void {
// noBleWarning();
}
/**
* Registers code to run when a packet is received over radio.
*/
//% help=radio/on-data-received
//% shim=micro_bit::onDatagramReceived
//% weight=50
//% blockId=radio_datagram_received_event block="on data received" blockGap=8
export function onDataReceived(body:Action) : void {
// noBleWarning();
}
/**
* Reads the next packet as a number from the radio queue.
*/
//% help=radio/receive-number
//% shim=micro_bit::datagramReceiveNumber
//% weight=46
//% blockId=radio_datagram_receive block="receive number" blockGap=8
export function receiveNumber() : number
{
//noBleWarning();
return 0;
}
/**
* Reads a number at a given index, between ``0`` and ``3``, from the packet received by ``receive number``. Not supported in simulator.
* @param index index of the number to read from 0 to 3. eg: 1
*/
//% help=radio/received-number-at
//% shim=micro_bit::datagramGetNumber
//% weight=45
//% blockId=radio_datagram_received_number_at block="receive number|at %VALUE" blockGap=8
export function receivedNumberAt(index: number) : number {
/* if (index < 0 || index >= 4) {
TD.simulator.warning("index should be between ``0`` and ``3``.");
}*/
return 0;
}
/**
* Gets the received signal strength indicator (RSSI) from the packet received by ``receive number``. Not supported in simulator.
* namespace=radio
*/
//% help=radio/received-signal-strength
//% shim=micro_bit::datagramGetRSSI
//% weight=40
//% blockId=radio_datagram_rssi block="received signal strength"
export function receivedSignalStrength() : number {
return 0;
}
/**
* Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.
* @ param id the group id between ``0`` and ``255``, eg: 1
*/
//% help=radio/set-group
//% shim=micro_bit::setGroup
//% weight=10
//% blockId=radio_set_group block="set group %ID"
export function setGroup(id: number) : void {
}
/**
* Change the output power level of the transmitter to the given value.
* @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest, eg: 7
*/
//% help=radio/set-transmit-power
//% shim=micro_bit::setTransmitPower
//% weight=9
//% blockId=radio_set_transmit_power block="set transmit power %power"
export function setTransmitPower(power:number) {
}
}

69
libs/microbit-radio/shims.d.ts vendored Normal file
View File

@ -0,0 +1,69 @@
// Auto-generated. Do not edit.
//% color=270 weight=34
declare namespace radio {
/**
* Broadcasts 4 numbers over radio to any connected micro:bit in the group.
*/
//% help=radio/send-numbers
//% weight=59
//% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3" shim=radio::sendNumbers
function sendNumbers(value_0: number, value_1: number, value_2: number, value_3: number): void;
/**
* Registers code to run when a packet is received over radio.
*/
//% help=radio/on-data-received
//% weight=50
//% blockId=radio_datagram_received_event block="on data received" blockGap=8 shim=radio::onDataReceived
function onDataReceived(body: () => void): void;
/**
* Reads a number at a given index, between ``0`` and ``3``, from the packet received by ``receive number``. Not supported in simulator.
* @param index index of the number to read from 0 to 3. 1 eg
*/
//% help=radio/received-number-at
//% weight=45
//% blockId=radio_datagram_received_number_at block="receive number|at %VALUE" blockGap=8 shim=radio::receivedNumberAt
function receivedNumberAt(index: number): number;
/**
* Reads the next packet as a number from the radio queue.
*/
//% help=radio/receive-number
//% weight=46
//% blockId=radio_datagram_receive block="receive number" blockGap=8 shim=radio::receiveNumber
function receiveNumber(): number;
/**
* Gets the received signal strength indicator (RSSI) from the packet received by ``receive number``. Not supported in simulator.
* namespace=radio
*/
//% help=radio/received-signal-strength
//% weight=40
//% blockId=radio_datagram_rssi block="received signal strength" shim=radio::receivedSignalStrength
function receivedSignalStrength(): number;
/**
* Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.
* @ param id the group id between ``0`` and ``255``, 1 eg
*/
//% help=radio/set-group
//% weight=10
//% blockId=radio_set_group block="set group %ID" shim=radio::setGroup
function setGroup(id: number): void;
/**
* Change the output power level of the transmitter to the given value.
* @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest, 7 eg
*/
//% help=radio/set-transmit-power
//% weight=9
//% blockId=radio_set_transmit_power block="set transmit power %power" shim=radio::setTransmitPower
function setTransmitPower(power: number): void;
}
// Auto-generated. Do not edit. Really.

View File

@ -1,4 +1,4 @@
#include "BitVM.h"
#include "ksbit.h"
/**
@ -38,7 +38,7 @@ namespace basic {
//% blockId=device_show_leds
//% block="show leds" icon="\uf00a"
void showLeds(ImageLiteral leds, int interval = 400) {
uBit.display.print(MicroBitImage(getbytes(leds)), 0, 0, 0, interval);
uBit.display.print(MicroBitImage(imageBytes(leds)), 0, 0, 0, interval);
}
/**
@ -80,24 +80,24 @@ namespace basic {
* @param leds TODO
* @param interval TODO
*/
//% help=basic/show-animation shim=micro_bit::showAnimation imageLiteral=1 async
//% help=basic/show-animation imageLiteral=1 async
void showAnimation(ImageLiteral leds, int interval = 400) {
uBit.display.animate(MicroBitImage(getbytes(leds)), interval, 5, 0);
uBit.display.animate(MicroBitImage(imageBytes(leds)), interval, 5, 0);
}
/**
* Draws an image on the LED screen.
* @param leds TODO
*/
//% help=basic/plot-leds weight=80 shim=micro_bit::plotLeds
//% help=basic/plot-leds weight=80
void plotLeds(ImageLiteral leds) {
MicroBitImage i(getbytes(leds));
MicroBitImage i(imageBytes(leds));
uBit.display.print(i, 0, 0, 0, 0);
}
void forever_stub(void *a) {
while (true) {
action::run((Action)a);
runAction0((Action)a);
uBit.sleep(20);
}
}

View File

@ -1,4 +1,4 @@
#include "BitVM.h"
#include "ksbit.h"
/**
* How to create the event.
@ -127,10 +127,7 @@ namespace control {
//% help=control/in-background
//% blockId="control_in_background" block="run in background" blockGap=8
void inBackground(Action a) {
if (a != 0) {
incr(a);
create_fiber((void(*)(void*))action::run, (void*)a, fiberDone);
}
runInBackground(a);
}
/**
@ -150,12 +147,16 @@ namespace control {
*/
//% weight=21 blockGap=12 blockId="control_raise_event" block="raise event|from source %src=control_event_source|with value %value=control_event_value" blockExternalInputs=1
//% mode.defl=CREATE_AND_QUEUE
void raiseEvent(int src, int value, EventCreationMode mode) { }
void raiseEvent(int src, int value, EventCreationMode mode) {
MicroBitEvent evt(src, value, (MicroBitEventLaunchMode)mode);
}
/**
* Raises an event in the event bus.
*/
//% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src=control_event_source|with value %value=control_event_value"
//% blockExternalInputs=1 blockStatement=1
void onEvent(int src, int value, Action handler) { }
void onEvent(int src, int value, Action handler) {
registerWithDal(src, value, handler);
}
}

398
libs/microbit/core.cpp Normal file
View File

@ -0,0 +1,398 @@
#include "ksbit.h"
#include <limits.h>
namespace StringMethods {
/**
* Returns the character at the specified index.
* @param pos The zero-based index of the desired character.
*/
//%
StringData *charAt(StringData *s, int pos) {
return ManagedString((char)ManagedString(s).charAt(pos)).leakData();
}
/**
* Returns the Unicode value of the character at the specified location.
* @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
*/
//%
int charCodeAt(StringData *s, int index) {
return ManagedString(s).charAt(index);
}
/**
* Returns a string that contains the concatenation of two or more strings.
* @param other The string to append to the end of the string.
*/
//%
StringData *concat(StringData *s, StringData *other) {
ManagedString a(s), b(other);
return (a + b).leakData();
}
/**
* Determines whether relative order of two strings (in ASCII encoding).
* @param that String to compare to target string
*/
//%
int compare(StringData *s, StringData *that) {
return strcmp(s->data, that->data);
}
/** Returns the length of a String object. */
//% property
int length(StringData *s) {
return s->len;
}
}
namespace BooleanMethods {
// Cache the string literals "true" and "false" when used.
// Note that the representation of booleans stays the usual C-one.
static const char sTrue[] __attribute__ ((aligned (4))) = "\xff\xff\x04\x00" "true\0";
static const char sFalse[] __attribute__ ((aligned (4))) = "\xff\xff\x05\x00" "false\0";
/**
* Returns a string representation of an object.
*/
//%
StringData* toString(bool v)
{
if (v) {
return (StringData*)(void*)sTrue;
} else {
return (StringData*)(void*)sFalse;
}
}
//%
bool bang(bool v) { return !v; }
}
namespace String_ {
/**
* Make a string from the given ASCII character code.
*/
//%
StringData *fromCharCode(int code)
{
return ManagedString((char)code).leakData();
}
//%
int toNumber(StringData *s) {
return atoi(s->data);
}
//%
StringData *mkEmpty()
{
return ManagedString::EmptyString.leakData();
}
}
namespace NumberMethods {
/**
* Returns a string representation of a number.
*/
//%
StringData* toString(int n)
{
return ManagedString(n).leakData();
}
}
namespace NumberImpl {
// +, - and friends are handled directly by assembly instructions
// The comparisons are here as they are more code-size efficient
//%
bool lt(int x, int y) { return x < y; }
//%
bool le(int x, int y) { return x <= y; }
//%
bool neq(int x, int y) { return x != y; }
//%
bool eq(int x, int y) { return x == y; }
//%
bool gt(int x, int y) { return x > y; }
//%
bool ge(int x, int y) { return x >= y; }
// These in fact call into C runtime on Cortex-M0
//%
int div(int x, int y) { return x / y; }
//%
int mod(int x, int y) { return x % y; }
}
namespace Math_ {
/**
* Returns the value of a base expression taken to a specified power.
* @param x The base value of the expression.
* @param y The exponent value of the expression.
*/
//%
int pow(int x, int y)
{
if (y < 0)
return 0;
int r = 1;
while (y) {
if (y & 1)
r *= x;
y >>= 1;
x *= x;
}
return r;
}
/**
* Returns a pseudorandom number between 0 and `max`.
*/
//%
int random(int max) {
if (max == INT_MIN)
return -uBit.random(INT_MAX);
else if (max < 0)
return -uBit.random(-max);
else if (max == 0)
return 0;
else
return uBit.random(max);
}
/**
* Returns the square root of a number.
* @param x A numeric expression.
*/
//%
int sqrt(int x)
{
return ::sqrt(x);
}
}
namespace ArrayImpl {
//%
RefCollection *mk(uint32_t flags)
{
return new RefCollection(flags);
}
//%
int length(RefCollection *c) { return c->length(); }
//%
void push(RefCollection *c, uint32_t x) { c->push(x); }
//%
uint32_t getAt(RefCollection *c, int x) { return c->getAt(x); }
//%
void removeAt(RefCollection *c, int x) { c->removeAt(x); }
//%
void setAt(RefCollection *c, int x, uint32_t y) { c->setAt(x, y); }
//%
int indexOf(RefCollection *c, uint32_t x, int start) { return c->indexOf(x, start); }
//%
int removeElement(RefCollection *c, uint32_t x) { return c->removeElement(x); }
}
// Import some stuff directly
namespace kindscript {
//%
void registerWithDal(int id, int event, Action a);
//%
void runAction0(Action a);
//%
void runAction1(Action a, int arg);
//%
Action mkAction(int reflen, int totallen, int startptr);
//%
RefRecord* mkRecord(int reflen, int totallen);
//%
void debugMemLeaks();
//%
int incr(uint32_t e);
//%
void decr(uint32_t e);
//%
uint32_t *allocate(uint16_t sz);
//%
int templateHash();
//%
int programHash();
//%
void *ptrOfLiteral(int offset);
}
namespace ksrt {
//%
uint32_t ldloc(RefLocal *r) {
return r->v;
}
//%
uint32_t ldlocRef(RefRefLocal *r) {
uint32_t tmp = r->v;
incr(tmp);
return tmp;
}
//%
void stloc(RefLocal *r, uint32_t v) {
r->v = v;
}
//%
void stlocRef(RefRefLocal *r, uint32_t v) {
decr(r->v);
r->v = v;
}
//%
RefLocal *mkloc() {
return new RefLocal();
}
//%
RefRefLocal *mklocRef() {
return new RefRefLocal();
}
// All of the functions below unref() self. This is for performance reasons -
// the code emitter will not emit the unrefs for them.
//%
uint32_t ldfld(RefRecord *r, int idx) {
auto tmp = r->ld(idx);
r->unref();
return tmp;
}
//%
uint32_t ldfldRef(RefRecord *r, int idx) {
auto tmp = r->ldref(idx);
r->unref();
return tmp;
}
//%
void stfld(RefRecord *r, int idx, uint32_t val) {
r->st(idx, val);
r->unref();
}
//%
void stfldRef(RefRecord *r, int idx, uint32_t val) {
r->stref(idx, val);
r->unref();
}
//%
uint32_t ldglb(int idx) {
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
return globals[idx];
}
//%
uint32_t ldglbRef(int idx) {
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
uint32_t tmp = globals[idx];
incr(tmp);
return tmp;
}
// note the idx comes last - it's more convenient that way in the emitter
//%
void stglb(uint32_t v, int idx)
{
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
globals[idx] = v;
}
//%
void stglbRef(uint32_t v, int idx)
{
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
decr(globals[idx]);
globals[idx] = v;
}
// Store a captured local in a closure. It returns the action, so it can be chained.
//%
RefAction *stclo(RefAction *a, int idx, uint32_t v)
{
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
a->st(idx, v);
return a;
}
//%
void panic(int code)
{
uBit.panic(code);
}
}
namespace buffer {
RefBuffer *mk(uint32_t size)
{
RefBuffer *r = new RefBuffer();
r->data.resize(size);
return r;
}
char *cptr(RefBuffer *c)
{
return (char*)&c->data[0];
}
int count(RefBuffer *c) { return c->data.size(); }
void fill(RefBuffer *c, int v)
{
memset(cptr(c), v, count(c));
}
void fill_random(RefBuffer *c)
{
int len = count(c);
for (int i = 0; i < len; ++i)
c->data[i] = uBit.random(0x100);
}
void add(RefBuffer *c, uint32_t x) {
c->data.push_back(x);
}
inline bool in_range(RefBuffer *c, int x) {
return (0 <= x && x < (int)c->data.size());
}
uint32_t at(RefBuffer *c, int x) {
if (in_range(c, x)) {
return c->data[x];
}
else {
error(ERR_OUT_OF_BOUNDS);
return 0;
}
}
void set(RefBuffer *c, int x, uint32_t y) {
if (!in_range(c, x))
return;
c->data[x] = y;
}
}
namespace bitvm_bits {
RefBuffer *create_buffer(int size)
{
return buffer::mk(size);
}
}

View File

@ -4,14 +4,14 @@ interface Array<T> {
/**
* Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
*/
//% shim=collection::count
//% shim=ArrayImpl::length
length: number;
/**
* Appends new elements to an array.
* @param items New elements of the Array.
*/
//% shim=collection::add
//% shim=ArrayImpl::push
push(item: T): void;
/**
@ -41,11 +41,11 @@ interface Array<T> {
slice(start: number, end: number): T[];
/** Removes the first occurence of an object. Returns true if removed. */
//% shim=collection::remove
//% shim=ArrayImpl::removeElement
removeElement(element:T) : boolean;
/** Removes the object at position index. */
//% shim=collection::remove_at
//% shim=ArrayImpl::removeAt
removeAt(idx:number) : void;
@ -69,7 +69,7 @@ interface Array<T> {
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/
//% shim=collection::index_of
//% shim=ArrayImpl::indexOf
indexOf(searchElement: T, fromIndex?: number): number;
@ -78,75 +78,6 @@ interface Array<T> {
interface String {
/**
* Returns the character at the specified index.
* @param pos The zero-based index of the desired character.
*/
//% shim=string::at
charAt(pos: number): string;
/**
* Returns the Unicode value of the character at the specified location.
* @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
*/
//% shim=string::code_at
charCodeAt(index: number): number;
/**
* Returns a string that contains the concatenation of two or more strings.
* @param strings The strings to append to the end of the string.
*/
//% shim=string::concat
concat(other: string): string;
/**
* Returns the position of the first occurrence of a substring.
* @param searchString The substring to search for in the string
* @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string.
*/
indexOf(searchString: string, position?: number): number;
/**
* Returns the last occurrence of a substring in the string.
* @param searchString The substring to search for.
* @param position The index at which to begin searching. If omitted, the search begins at the end of the string.
*/
lastIndexOf(searchString: string, position?: number): number;
/**
* Determines whether two strings are equivalent in the current locale.
* @param that String to compare to target string
*/
localeCompare(that: string): number;
/**
* Returns a section of a string.
* @param start The index to the beginning of the specified portion of stringObj.
* @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end.
* If this value is not specified, the substring continues to the end of stringObj.
*/
slice(start?: number, end?: number): string;
/**
* Returns the substring at the specified location within a String object.
* @param start The zero-based index number indicating the beginning of the substring.
* @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.
* If end is omitted, the characters from start through the end of the original string are returned.
*/
substring(start: number, end?: number): string;
/** Converts all the alphabetic characters in a string to lowercase. */
toLowerCase(): string;
/** Converts all the alphabetic characters in a string to uppercase. */
toUpperCase(): string;
/** Returns the length of a String object. */
//% shim=string::count
length: number;
//% shim=string::at
[index: number]: string;
}
@ -155,7 +86,7 @@ interface String {
* Converts A string to an integer.
* @param s A string to convert into a number.
*/
//% shim=string::to_number
//% shim=String_::toNumber
declare function parseInt(s: string): number;
interface Object {}
@ -163,74 +94,3 @@ interface Function {}
interface IArguments {}
interface RegExp {}
interface Boolean {
/**
* Returns a string representation of an object.
*/
//% shim=boolean::to_string
toString(): string;
}
declare namespace String {
/**
* Make a string from the given ASCII character code.
*/
//% shim=number::to_character
export function fromCharCode(code:number): string;
}
interface Number {
/**
* Returns a string representation of an object.
*/
//% shim=number::to_string
toString(): string;
}
declare namespace Math {
/**
* Returns the absolute value of a number (the value without regard to whether it is positive or negative).
* For example, the absolute value of -5 is the same as the absolute value of 5.
* @param x A numeric expression for which the absolute value is needed.
*/
//% shim=math::abs
export function abs(x: number): number;
/**
* Returns the sign of the x, indicating whether x is positive, negative or zero.
* @param x The numeric expression to test
*/
//% shim=math::sign
export function sign(x: number): number;
/**
* Returns the larger of two supplied numeric expressions.
*/
//% shim=math::max
export function max(a:number, b:number): number;
/**
* Returns the smaller of two supplied numeric expressions.
*/
//% shim=math::min
export function min(a:number, b:number): number;
/**
* Returns the value of a base expression taken to a specified power.
* @param x The base value of the expression.
* @param y The exponent value of the expression.
*/
//% shim=math::pow
export function pow(x: number, y: number): number;
/** Returns a pseudorandom number between 0 and `max`. */
//% shim=math::random
export function random(max:number): number;
/**
* Returns the square root of a number.
* @param x A numeric expression.
*/
//% shim=math::sqrt
export function sqrt(x: number): number;
}

View File

@ -1,4 +1,6 @@
// Auto-generated. Do not edit.
declare namespace images {
}
declare namespace basic {
}
@ -32,12 +34,9 @@ declare namespace basic {
declare enum TouchPin {
//% enumval=uBit.io.P0
P0 = 0,
//% enumval=uBit.io.P1
P1 = 1,
//% enumval=uBit.io.P2
P2 = 2,
P0 = 7, // MICROBIT_ID_IO_P0
P1 = 8, // MICROBIT_ID_IO_P1
P2 = 9, // MICROBIT_ID_IO_P2
}
@ -107,6 +106,8 @@ declare namespace basic {
//% block="free fall"
FreeFall = 7, // GESTURE_FREEFALL
}
declare namespace input {
}
/**
@ -222,4 +223,52 @@ declare namespace basic {
declare namespace control {
}
declare enum DisplayMode {
//% block="black and white"
BackAndWhite = 0, // DISPLAY_MODE_BLACK_AND_WHITE
//% block="greyscale"
Greyscale = 1, // DISPLAY_MODE_GREYSCALE
// TODO DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE
}
declare namespace led {
}
declare enum DigitalPin {
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 = 15, // MICROBIT_ID_IO_P8
P9 = 16, // MICROBIT_ID_IO_P9
P10 = 17, // MICROBIT_ID_IO_P10
P11 = 18, // MICROBIT_ID_IO_P11
P12 = 19, // MICROBIT_ID_IO_P12
P13 = 20, // MICROBIT_ID_IO_P13
P14 = 21, // MICROBIT_ID_IO_P14
P15 = 22, // MICROBIT_ID_IO_P15
P16 = 23, // MICROBIT_ID_IO_P16
P19 = 24, // MICROBIT_ID_IO_P19
P20 = 25, // MICROBIT_ID_IO_P20
}
declare enum AnalogPin {
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
P10 = 17, // MICROBIT_ID_IO_P10
}
declare namespace pins {
}
declare namespace serial {
}
// Auto-generated. Do not edit. Really.

View File

@ -28,7 +28,7 @@ namespace game {
var _countdownPause: number = 0;
var _level: number = 1;
var _gameId: number = 0;
var img: images.Image;
var img: Image;
var sprites: LedSprite[];
/**
@ -284,8 +284,8 @@ namespace game {
private _blink: number;
constructor(x: number, y: number) {
this._x = math.clamp(0, 4, x);
this._y = math.clamp(0, 4, y);
this._x = Math.clamp(0, 4, x);
this._y = Math.clamp(0, 4, y);
this._dir = 90;
this._brightness = 255;
init();
@ -322,8 +322,8 @@ namespace game {
this._x = this._x - leds;
this._y = this._y + leds;
}
this._x = math.clamp(0, 4, this._x);
this._y = math.clamp(0, 4, this._y);
this._x = Math.clamp(0, 4, this._x);
this._y = Math.clamp(0, 4, this._y);
plot();
}
@ -336,8 +336,8 @@ namespace game {
public goTo(x: number, y: number): void {
this._x = x;
this._y = y;
this._x = math.clamp(0, 4, this._x);
this._y = math.clamp(0, 4, this._y);
this._x = Math.clamp(0, 4, this._x);
this._y = Math.clamp(0, 4, this._y);
plot();
}
@ -594,7 +594,7 @@ namespace game {
* @param brightness TODO
*/
public setBrightness(brightness: number): void {
this._brightness = math.clamp(0, 255, brightness);
this._brightness = Math.clamp(0, 255, brightness);
plot();
}
@ -639,7 +639,7 @@ namespace game {
* @param ms TODO
*/
public setBlink(ms: number): void {
this._blink = math.clamp(0, 10000, ms);
this._blink = Math.clamp(0, 10000, ms);
}
/**

85
libs/microbit/images.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "ksbit.h"
//% color=45 weight=31
namespace images {
/**
* Creates an image that fits on the LED screen.
*/
//% weight=75 help=images/create-image
//% blockId=device_build_image block="create image"
Image createImage(ImageLiteral leds) {
return MicroBitImage(imageBytes(leds)).clone().leakData();
}
/**
* Creates an image with 2 frames.
*/
//% weight=74 help=images/create-big-image
//% blockId=device_build_big_image block="create big image" imageLiteral=2
Image createBigImage(ImageLiteral leds) {
return createImage(leds);
}
}
namespace ImageMethods {
/**
* Shows an frame from the image at offset ``x offset``.
* @param xOffset TODO
*/
//% help=images/show-image weight=80 async
//% BUGblockId=device_show_image_offset block="show image %sprite|at offset %offset" blockGap=8
void showImage(Image i, int xOffset = 0) {
uBit.display.print(MicroBitImage(i), -xOffset, 0, 0);
}
/**
* Scrolls an image .
* @param frameOffset x offset moved on each animation step, eg: 5, 1, -1
* @param interval time between each animation step in milli seconds, eg: 200
*/
//% help=images/show-image weight=79 async
//% BUGblockId=device_scroll_image block="scroll image %sprite|with offset %frameoffset|and interval (ms) %delay" blockGap=8
void scrollImage(Image id, int frameOffset = 0, int interval = 200) {
MicroBitImage i(id);
if (i.getWidth() <= 5)
showImage(id, 0);
else
uBit.display.animate(i, interval, frameOffset, 0);
}
/**
* Plots the image at a given column to the screen
*/
//% help=images/plot-image
void plotImage(Image i, int xOffset = 0) {
uBit.display.print(MicroBitImage(i), -xOffset, 0, 0, 0);
}
/**
* Sets all pixels off.
*/
//% help=images/clear
void clear(Image i) {
MicroBitImage(i).clear();
}
/**
* Sets a specific pixel brightness at a given position
*/
//% help=
void setPixelBrightness(Image i, int x, int y, int value) {
MicroBitImage(i).setPixelValue(x, y, value);
}
/**
* Gets the pixel brightness ([0..255]) at a given position
*/
//% help=
int pixelBrightness(Image i, int x, int y) {
int pix = MicroBitImage(i).getPixelValue(x, y);
if (pix < 0) return 0;
return pix;
}
}

View File

@ -1,63 +0,0 @@
//% color=45 weight=31
namespace images {
/**
* Creates an image that fits on the LED screen.
*/
//% weight=75 help=images/create-image
//% blockId=device_build_image block="create image" imageLiteral=1
export function createImage(leds: string): Image {
return null;
}
/**
* Creates an image with 2 frames.
*/
//% weight=74 help=images/create-big-image
//% blockId=device_build_big_image block="create big image" imageLiteral=2
export function createBigImage(leds: string): Image {
return null;
}
export class Image {
/**
* Shows an frame from the image at offset ``x offset``.
* @param xOffset TODO
*/
//% help=images/show-image weight=80 shim=micro_bit::showImage
//% blockId=device_show_image_offset block="show image %sprite|at offset %offset" blockGap=8
public showImage(xOffset: number = 0): void {}
/**
* Scrolls an image .
* @param frameOffset x offset moved on each animation step, eg: 5, 1, -1
* @param interval time between each animation step in milli seconds, eg: 200
*/
//% help=images/show-image weight=79 shim=micro_bit::scrollImage async
//% blockId=device_scroll_image block="scroll image %sprite|with offset %frameoffset|and interval (ms) %delay" blockGap=8
public scrollImage(frameOffset: number = 0, interval : number = 200) {
}
/**
* Plots the image at a given column to the screen
*/
public plotImage(xOffset: number = 0): void {}
/**
* Sets all pixels off.
*/
public clear(): void {}
/**
* Sets a specific pixel brightness at a given position
*/
public setPixelBrightness(x: number, y: number, v: number): void {}
/**
* Gets the pixel brightness ([0..255]) at a given position
*/
public pixelBrightness(x: number, y: number): number {
return 0;
}
}
}

View File

@ -1,4 +1,4 @@
#include "BitVM.h"
#include "ksbit.h"
enum class Button {
A = MICROBIT_ID_BUTTON_A,
@ -26,12 +26,9 @@ enum class Rotation {
};
enum class TouchPin {
//% enumval=uBit.io.P0
P0,
//% enumval=uBit.io.P1
P1,
//% enumval=uBit.io.P2
P2,
P0 = MICROBIT_ID_IO_P0,
P1 = MICROBIT_ID_IO_P1,
P2 = MICROBIT_ID_IO_P2,
};
enum class AcceleratorRange {
@ -99,3 +96,186 @@ enum class Gesture {
//% block="free fall"
FreeFall = GESTURE_FREEFALL
};
//% color=300 weight=99
namespace input {
/**
* Do something when a button (``A``, ``B`` or both ``A+B``) is pressed
* @param button TODO
* @param body TODO
*/
//% help=input/on-button-pressed weight=85
//% blockId=device_button_event
//% block="on button|%NAME|pressed"
//% icon="\uf192"
void onButtonPressed(Button button, Action body) {
registerWithDal((int)button, MICROBIT_BUTTON_EVT_CLICK, body);
}
/**
* Attaches code to run when the screen is facing up.
* @param body TODO
*/
//% help=input/on-gesture weight=84
//% blockId=device_gesture_event block="on |%NAME" icon="\uf135"
void onGesture(Gesture gesture, Action body) {
registerWithDal(MICROBIT_ID_GESTURE, (int)gesture, body);
}
/**
* Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.
* @param name TODO
* @param body TODO
*/
//% help=input/on-pin-pressed weight=83
//% blockId=device_pin_event block="on pin|%NAME|pressed" icon="\uf094"
void onPinPressed(TouchPin name, Action body) {
auto pin = getPin((int)name);
if (!pin) return;
// Forces the PIN to switch to makey-makey style detection.
pin->isTouched();
registerWithDal((int)name, MICROBIT_BUTTON_EVT_CLICK, body);
}
/**
* Get the button state (pressed or not) for ``A`` and ``B``.
*/
//% help=input/button-is-pressed weight=57
//% block="button|%NAME|is pressed"
//% blockId=device_get_button2
//% icon="\uf192" blockGap=8
bool buttonIsPressed(Button button) {
if (button == Button::A)
return uBit.buttonA.isPressed();
else if (button == Button::B)
return uBit.buttonB.isPressed();
else if (button == Button::AB)
return uBit.buttonAB.isPressed();
return false;
}
/**
* Get the current compass compass heading in degrees.
*/
//% help=input/compass-heading
//% weight=56 icon="\uf14e"
//% blockId=device_heading block="compass heading (°)" blockGap=8
int compassHeading() {
return uBit.compass.heading();
}
/**
* Gets the temperature in Celsius degrees (°C).
*/
//% weight=55 icon="\uf06d"
//% help=input/temperature
//% blockId=device_temperature block="temperature (°C)" blockGap=8
int temperature() {
return uBit.thermometer.getTemperature();
}
int getAccelerationStrength() {
double x = uBit.accelerometer.getX();
double y = uBit.accelerometer.getY();
double z = uBit.accelerometer.getZ();
return (int)sqrt(x*x+y*y+z*z);
}
/**
* Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)
* @param dimension TODO
*/
//% help=input/acceleration weight=54 icon="\uf135"
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
int acceleration(Dimension dimension) {
switch (dimension) {
case Dimension::X: return uBit.accelerometer.getX();
case Dimension::Y: return uBit.accelerometer.getY();
case Dimension::Z: return uBit.accelerometer.getZ();
case Dimension::Strength: return getAccelerationStrength();
}
return 0;
}
/**
* Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright. In the simulator, the ``acceleration y`` is used to emulate this value.
*/
//% help=input/light-level weight=53
//% blockId=device_get_light_level block="light level" blockGap=8 icon="\uf185"
int lightLevel() {
return uBit.display.readLightLevel();
}
/**
* The pitch of the device, rotation along the ``x-axis``, in degrees.
* @param kind TODO
*/
//% help=/input/rotation weight=52
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8 icon="\uf197"
int rotation(Rotation kind) {
switch (kind) {
case Rotation::Pitch: return uBit.accelerometer.getPitch();
case Rotation::Roll: return uBit.accelerometer.getRoll();
}
return 0;
}
/**
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
* @param dimension TODO
*/
//% help=input/magnetic-force weight=51
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8 icon="\uf076"
int magneticForce(Dimension dimension) {
if (!uBit.compass.isCalibrated())
uBit.compass.calibrate();
switch (dimension) {
case Dimension::X: return uBit.compass.getX() / 1000;
case Dimension::Y: return uBit.compass.getY() / 1000;
case Dimension::Z: return uBit.compass.getZ() / 1000;
case Dimension::Strength: return uBit.compass.getFieldStrength() / 1000;
}
return 0;
}
/**
* Gets the number of milliseconds elapsed since power on.
*/
//% help=input/running-time weight=50
//% blockId=device_get_running_time block="running time (ms)" icon="\uf017"
int runningTime() {
return uBit.systemTime();
}
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate weight=0
void calibrate() { }
/**
* Get the pin state (pressed or not). Requires to hold the ground to close the circuit.
* @param name pin used to detect the touch
*/
//% help=input/pin-is-pressed weight=58 block="pin|%NAME|is pressed" icon="\uf094"
bool pinIsPressed(TouchPin name) {
auto pin = getPin((int)name);
return pin && pin->isTouched();
}
/**
* Sets the accelerometer sample range in gravities.
* @param range a value describe the maximum strengh of acceleration measured
*/
//% help=input/set-accelerator-range
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range" icon="\uf135"
//% weight=5
void setAccelerometerRange(AcceleratorRange range) {
uBit.accelerometer.setRange((int)range);
}
}

View File

@ -1,134 +1,5 @@
//% color=300 weight=99
namespace input {
/**
* Do something when a button (``A``, ``B`` or both ``A+B``) is pressed
* @param button TODO
* @param body TODO
*/
//% help=input/on-button-pressed weight=85
//% shim=micro_bit::onButtonPressed
//% blockId=device_button_event
//% block="on button|%NAME|pressed"
//% icon="\uf192"
export function onButtonPressed(button: Button, body: Action): void { }
/**
* Attaches code to run when the screen is facing up.
* @param body TODO
*/
//% help=input/on-gesture shim=micro_bit::onGesture weight=84
//% blockId=device_gesture_event block="on |%NAME" icon="\uf135"
export function onGesture(gesture: Gesture, body: Action): void { }
/**
* Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.
* @param name TODO
* @param body TODO
*/
//% help=input/on-pin-pressed weight=83 shim=micro_bit::onPinPressed
//% blockId=device_pin_event block="on pin|%NAME|pressed" icon="\uf094"
export function onPinPressed(name: TouchPin, body: Action): void { }
/**
* Get the button state (pressed or not) for ``A`` and ``B``.
*/
//% help=input/button-is-pressed weight=57
//% shim=micro_bit::isButtonPressed
//% block="button|%NAME|is pressed"
//% blockId=device_get_button2
//% icon="\uf192" blockGap=8
export function buttonIsPressed(button: Button): boolean {
return false;
}
/**
* Get the current compass compass heading in degrees.
*/
//% help=input/compass-heading
//% weight=56 icon="\uf14e"
//% shim=micro_bit::compassHeading
//% blockId=device_heading block="compass heading (°)" blockGap=8
export function compassHeading(): number {
return 0;
}
/**
* Gets the temperature in Celsius degrees (°C).
*/
//% weight=55 icon="\uf06d"
//% help=input/temperature shim=micro_bit::temperature
//% blockId=device_temperature block="temperature (°C)" blockGap=8
export function temperature(): number {
return 0;
}
/**
* Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)
* @param dimension TODO
*/
//% help=input/acceleration weight=54 icon="\uf135"
//% shim=micro_bit::getAcceleration
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
export function acceleration(dimension: Dimension): number {
return 0;
}
/**
* Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright. In the simulator, the ``acceleration y`` is used to emulate this value.
*/
//% help=input/light-level weight=53 shim=micro_bit::lightLevel
//% blockId=device_get_light_level block="light level" blockGap=8 icon="\uf185"
export function lightLevel(): number {
return 0;
}
/**
* The pitch of the device, rotation along the ``x-axis``, in degrees.
* @param kind TODO
*/
//% help=/input/rotation weight=52 shim=micro_bit::getRotation
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8 icon="\uf197"
export function rotation(kind: Rotation): number {
return 0;
}
/**
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
* @param dimension TODO
*/
//% help=input/magnetic-force weight=51 shim=micro_bit::getMagneticForce
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8 icon="\uf076"
export function magneticForce(dimension: Dimension): number {
return 0;
}
/**
* Gets the number of milliseconds elapsed since power on.
*/
//% help=input/running-time shim=micro_bit::getCurrentTime weight=50
//% blockId=device_get_running_time block="running time (ms)" icon="\uf017"
export function runningTime(): number {
return 0;
}
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate weight=0 shim=TD_NOOP
export function calibrate(): void { }
/**
* Get the pin state (pressed or not). Requires to hold the ground to close the circuit.
* @param name pin used to detect the touch
*/
//% help=input/pin-is-pressed weight=58 shim=micro_bit::isPinTouched block="pin|%NAME|is pressed" icon="\uf094"
export function pinIsPressed(name: TouchPin): boolean {
return false;
}
/**
* Attaches code to run when the screen is facing up.
* @param body TODO
@ -173,16 +44,4 @@ namespace input {
export function onLogoDown(body: Action): void {
onGesture(Gesture.LogoDown, body);
}
/**
* Sets the accelerometer sample range in gravities.
* @param range a value describe the maximum strengh of acceleration measured
*/
//% help=input/set-accelerator-range
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range" icon="\uf135"
//% weight=5
//% shim=micro_bit::setAccelerometerRange
export function setAccelerometerRange(range : AcceleratorRange) : void {
}
}

View File

@ -8,21 +8,30 @@
"enums.d.ts",
"shims.d.ts",
"core.d.ts",
"ksbit.h",
"core.cpp",
"mbit.ts",
"images.ts",
"images.cpp",
"basic.cpp",
"input.cpp",
"input.ts",
"control.ts",
"control.cpp",
"game.ts",
"led.cpp",
"led.ts",
"music.ts",
"pins.ts",
"pins.cpp",
"serial.cpp",
"serial.ts"
],
"public": true,
"dependencies": {},
"microbit": {
"config": {
"MESSAGE_BUS_LISTENER_DEFAULT_FLAGS": "MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY"
}
},
"target": {
"id": "microbit",
"name": "BBC micro:bit",
@ -79,7 +88,7 @@
"autoRun": true
},
"compileService": {
"gittag": "v0",
"gittag": "v0.1.2",
"serviceId": "ws"
},
"serial": {

6
libs/microbit/ksbit.h Normal file
View File

@ -0,0 +1,6 @@
#include "kindscript.h"
using namespace kindscript;
MicroBitPin *getPin(int id);
typedef ImageData* Image;

104
libs/microbit/led.cpp Normal file
View File

@ -0,0 +1,104 @@
#include "ksbit.h"
enum class DisplayMode_ {
//% block="black and white"
BackAndWhite = DISPLAY_MODE_BLACK_AND_WHITE,
//% block="greyscale"
Greyscale = DISPLAY_MODE_GREYSCALE,
// TODO DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE
};
//% color=3 weight=35
namespace led {
/**
* Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/plot weight=78
//% blockId=device_plot block="plot|x %x|y %y" icon="\uf205" blockGap=8
void plot(int x, int y) {
uBit.display.image.setPixelValue(x, y, 1);
}
/**
* Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/unplot weight=77
//% blockId=device_unplot block="unplot|x %x|y %y" icon="\uf204" blockGap=8
void unplot(int x, int y) {
uBit.display.image.setPixelValue(x, y, 0);
}
/**
* Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/point weight=76
//% blockId=device_point block="point|x %x|y %y" icon="\uf10c"
bool point(int x, int y) {
int pix = uBit.display.image.getPixelValue(x, y);
return pix > 0;
}
/**
* Get the screen brightness from 0 (off) to 255 (full bright).
*/
//% help=led/brightness weight=60
//% blockId=device_get_brightness block="brightness" icon="\uf042" blockGap=8
int brightness() {
return uBit.display.getBrightness();
}
/**
* Set the screen brightness from 0 (off) to 255 (full bright).
* @param value the brightness value, eg:255, 127, 0
*/
//% help=led/set-brightness weight=59
//% blockId=device_set_brightness block="set brightness %value" icon="\uf042"
void setBrightness(int value) {
uBit.display.setBrightness(value);
}
/**
* Cancels the current animation and clears other pending animations.
*/
//% weight=50 help=led/stop-animation
//% blockId=device_stop_animation block="stop animation" icon="\uf04d"
void stopAnimation() {
uBit.display.stopAnimation();
}
/**
* Sets the display mode between black and white and greyscale for rendering LEDs.
* @param mode TODO
*/
//% weight=1 help=/led/set-display-mode
void setDisplayMode(DisplayMode_ mode) {
uBit.display.setDisplayMode((DisplayMode)mode);
}
/**
* Takes a screenshot of the LED screen and returns an image.
*/
//% help=led/screenshot
Image screenshot() {
return uBit.display.screenShot().leakData();
/*
let Image img;
img = image.createImage("");
for (let i = 0; i < 5; i++) {
for (let j = 0; j < 5; j++) {
if (led.point(i, j)) {
img.setPixel(i, j, true);
}
}
}
return img;
*/
}
}

View File

@ -1,64 +1,5 @@
enum DisplayMode {
//% block="black and white"
BackAndWhite = 0,
//% block="greyscale"
Greyscale = 1,
}
//% color=3 weight=35
namespace led {
/**
* Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/plot weight=78 shim=micro_bit::plot
//% blockId=device_plot block="plot|x %x|y %y" icon="\uf205" blockGap=8
export function plot(x: number, y: number): void { }
/**
* Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/unplot weight=77 shim=micro_bit::unPlot
//% blockId=device_unplot block="unplot|x %x|y %y" icon="\uf204" blockGap=8
export function unplot(x: number, y: number): void { }
/**
* Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/point weight=76 shim=micro_bit::point
//% blockId=device_point block="point|x %x|y %y" icon="\uf10c"
export function point(x: number, y: number): boolean {
return false;
}
/**
* Get the screen brightness from 0 (off) to 255 (full bright).
*/
//% help=led/brightness weight=60 shim=micro_bit::getBrightness
//% blockId=device_get_brightness block="brightness" icon="\uf042" blockGap=8
export function brightness(): number {
return 0;
}
/**
* Set the screen brightness from 0 (off) to 255 (full bright).
* @param value the brightness value, eg:255, 127, 0
*/
//% help=led/set-brightness weight=59 shim=micro_bit::setBrightness
//% blockId=device_set_brightness block="set brightness %value" icon="\uf042"
export function setBrightness(value: number): void { }
/**
* Cancels the current animation and clears other pending animations.
*/
//% weight=50 shim=uBit.display.stopAnimation help=led/stop-animation
//% blockId=device_stop_animation block="stop animation" icon="\uf04d"
export function stopAnimation(): void { }
/**
* Displays a vertical bar graph based on the ``value`` and ``high`` value.
@ -69,7 +10,7 @@ namespace led {
//% blockId=device_plot_bar_graph block="plot bar graph of %value |up to %high" icon="\uf080" blockExternalInputs=true
export function plotBarGraph(value: number, high: number): void {
writeString(value.toString() + "\r\n");
serial.writeString(value.toString() + "\r\n");
let v = Math.abs((value * 15) / high);
let k = 0;
@ -87,19 +28,6 @@ namespace led {
}
}
/**
* Writes a string to serial
*/
//% shim=micro_bit::serialSendString
function writeString(text: string): void { }
/**
* Sets the display mode between black and white and greyscale for rendering LEDs.
* @param mode TODO
*/
//% shim=micro_bit::setDisplayMode weight=1 help=/led/set-display-mode
export function setDisplayMode(mode: DisplayMode): void { }
/**
* Toggles a particular pixel
* @param x TODO
@ -182,25 +110,5 @@ namespace led {
led.setBrightness(0);
}
/**
* Takes a screenshot of the LED screen and returns an image.
*/
//% shim=uBit.display.screenShot help=led/screenshot
export function screenshot(): images.Image {
/*
let img: Image;
img = image.createImage("");
for (let i = 0; i < 5; i++) {
for (let j = 0; j < 5; j++) {
if (led.point(i, j)) {
img.setPixel(i, j, true);
}
}
}
return img;
*/
return null;
}
}

View File

@ -13,16 +13,52 @@ namespace helpers {
namespace console {
export function log(msg: string) {
writeString(msg);
writeString("\r\n");
serial.writeString(msg);
serial.writeString("\r\n");
}
//% shim=micro_bit::serialSendString
function writeString(text: string): void { }
}
namespace math {
namespace Math {
export function clamp(min: number, max:number, value:number): number {
return Math.min(max, Math.max(min, value));
}
/**
* Returns the absolute value of a number (the value without regard to whether it is positive or negative).
* For example, the absolute value of -5 is the same as the absolute value of 5.
* @param x A numeric expression for which the absolute value is needed.
*/
export function abs(x: number): number
{
return x < 0 ? -x : x;
}
/**
* Returns the sign of the x, indicating whether x is positive, negative or zero.
* @param x The numeric expression to test
*/
export function sign(x: number): number
{
if (x == 0) return 0;
if (x > 0) return 1;
return -1;
}
/**
* Returns the larger of two supplied numeric expressions.
*/
export function max(a:number, b:number): number
{
if (a >= b) return a;
return b;
}
/**
* Returns the smaller of two supplied numeric expressions.
*/
export function min(a:number, b:number): number
{
if (a <= b) return a;
return b;
}
}

View File

@ -116,7 +116,7 @@ namespace music {
* Gets the frequency of a note.
* @param name TODO
*/
//% shim=TD_ID weight=50 help=music/note-frequency
//% weight=50 help=music/note-frequency
//% blockId=device_note block="%note"
export function noteFrequency(name: Note): number {
return name;

202
libs/microbit/pins.cpp Normal file
View File

@ -0,0 +1,202 @@
#include "ksbit.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,
P16 = MICROBIT_ID_IO_P16,
P19 = MICROBIT_ID_IO_P19,
P20 = MICROBIT_ID_IO_P20,
};
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,
};
MicroBitPin *getPin(int id) {
switch (id) {
case MICROBIT_ID_IO_P0: return &uBit.io.P0;
case MICROBIT_ID_IO_P1: return &uBit.io.P1;
case MICROBIT_ID_IO_P2: return &uBit.io.P2;
case MICROBIT_ID_IO_P3: return &uBit.io.P3;
case MICROBIT_ID_IO_P4: return &uBit.io.P4;
case MICROBIT_ID_IO_P5: return &uBit.io.P5;
case MICROBIT_ID_IO_P6: return &uBit.io.P6;
case MICROBIT_ID_IO_P7: return &uBit.io.P7;
case MICROBIT_ID_IO_P8: return &uBit.io.P8;
case MICROBIT_ID_IO_P9: return &uBit.io.P9;
case MICROBIT_ID_IO_P10: return &uBit.io.P10;
case MICROBIT_ID_IO_P11: return &uBit.io.P11;
case MICROBIT_ID_IO_P12: return &uBit.io.P12;
case MICROBIT_ID_IO_P13: return &uBit.io.P13;
case MICROBIT_ID_IO_P14: return &uBit.io.P14;
case MICROBIT_ID_IO_P15: return &uBit.io.P15;
case MICROBIT_ID_IO_P16: return &uBit.io.P16;
case MICROBIT_ID_IO_P19: return &uBit.io.P19;
case MICROBIT_ID_IO_P20: return &uBit.io.P20;
default: return NULL;
}
}
//% color=351 weight=30
namespace pins {
#define PINOP(op) \
MicroBitPin *pin = getPin((int)name); \
if (!pin) return; \
pin->op
#define PINREAD(op) \
MicroBitPin *pin = getPin((int)name); \
if (!pin) return 0; \
return pin->op
/**
* Read the specified pin or connector as either 0 or 1
* @param name pin to read from
*/
//% help=pins/digital-read-pin weight=30
//% blockId=device_get_digital_pin block="digital read|pin %name" blockGap=8
int digitalReadPin(DigitalPin name) {
PINREAD(getDigitalValue());
}
/**
* Set a pin or connector value to either 0 or 1.
* @param name pin to write to
* @param value value to set on the pin, 1 eg,0
*/
//% help=pins/digital-write-pin weight=29
//% blockId=device_set_digital_pin block="digital write|pin %name|to %value"
void digitalWritePin(DigitalPin name, int value) {
PINOP(setDigitalValue(value));
}
/**
* Read the connector value as analog, that is, as a value comprised between 0 and 1023.
* @param name pin to write to
*/
//% help=pins/analog-read-pin weight=25
//% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8"
int analogReadPin(AnalogPin name) {
PINREAD(getAnalogValue());
}
/**
* Set the connector value as analog. Value must be comprised between 0 and 1023.
* @param name pin name to write to
* @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0
*/
//% help=pins/analog-write-pin weight=24
//% blockId=device_set_analog_pin block="analog write|pin %name|to %value" blockGap=8
void analogWritePin(AnalogPin name, int value) {
PINOP(setAnalogValue(value));
}
/**
* Configures the Pulse-width modulation (PWM) of the analog output to the given value in **microseconds** or `1/1000` milliseconds.
* If this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.
* @param name analog pin to set period to
* @param micros period in micro seconds. eg:20000
*/
//% help=pins/analog-set-period weight=23
//% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%micros"
void analogSetPeriod(AnalogPin name, int micros) {
PINOP(setAnalogPeriodUs(micros));
}
/**
* Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).
* @param name pin to write to
* @param value angle or rotation speed, eg:180,90,0
*/
//% help=pins/servo-write-pin weight=20
//% blockId=device_set_servo_pin block="servo write|pin %name|to %value" blockGap=8
void servoWritePin(AnalogPin name, int value) {
PINOP(setServoValue(value));
}
/**
* Configures this IO pin as an analog/pwm output, configures the period to be 20 ms, and sets the pulse width, based on the value it is given **microseconds** or `1/1000` milliseconds.
* @param name pin name
* @param micros pulse duration in micro seconds, eg:1500
*/
//% help=pins/serial-set-pulse weight=19
//% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %micros"
void servoSetPulse(AnalogPin name, int micros) {
PINOP(setServoPulseUs(micros));
}
MicroBitPin* pitchPin = NULL;
/**
* Sets the pin used when using `pins->analog pitch`.
* @param name TODO
*/
//% help=pins/analog-set-pitch weight=12
void analogSetPitchPin(AnalogPin name) {
pitchPin = getPin((int)name);
}
/**
* Emits a Pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.
* @param frequency TODO
* @param ms TODO
*/
//% help=pins/analog-pitch weight=14 async
void analogPitch(int frequency, int ms) {
if (pitchPin == NULL) return;
if (frequency <= 0) {
pitchPin->setAnalogValue(0);
} else {
pitchPin->setAnalogValue(512);
pitchPin->setAnalogPeriodUs(1000000/frequency);
}
if (ms > 0) {
uBit.sleep(ms);
pitchPin->setAnalogValue(0);
wait_ms(5);
}
}
// TODO:
void i2cReadBuffer(int address, RefBuffer *buf)
{
uBit.i2c.read(address << 1, buf->cptr(), buf->size());
}
void i2cWriteBuffer(int address, RefBuffer *buf)
{
uBit.i2c.write(address << 1, buf->cptr(), buf->size());
}
int i2cReadRaw(int address, char *data, int length, int repeated)
{
return uBit.i2c.read(address, data, length, repeated);
}
int i2cWriteRaw(int address, const char *data, int length, int repeated)
{
return uBit.i2c.write(address, data, length, repeated);
}
}

View File

@ -1,129 +1,5 @@
enum DigitalPin {
//% enumval=uBit.io.P0
P0,
//% enumval=uBit.io.P1
P1,
//% enumval=uBit.io.P2
P2,
//% enumval=uBit.io.P3
P3,
//% enumval=uBit.io.P4
P4,
//% enumval=uBit.io.P5
P5,
//% enumval=uBit.io.P6
P6,
//% enumval=uBit.io.P7
P7,
//% enumval=uBit.io.P8
P8,
//% enumval=uBit.io.P9
P9,
//% enumval=uBit.io.P10
P10,
//% enumval=uBit.io.P11
P11,
//% enumval=uBit.io.P12
P12,
//% enumval=uBit.io.P13
P13,
//% enumval=uBit.io.P14
P14,
//% enumval=uBit.io.P15
P15,
//% enumval=uBit.io.P16
P16,
//% enumval=uBit.io.P19
P19,
//% enumval=uBit.io.P20
P20,
}
enum AnalogPin {
//% enumval=uBit.io.P0
P0,
//% enumval=uBit.io.P1
P1,
//% enumval=uBit.io.P2
P2,
//% enumval=uBit.io.P3
P3,
//% enumval=uBit.io.P4
P4,
//% enumval=uBit.io.P10
P10,
}
//% color=351 weight=30
namespace pins {
/**
* Read the specified pin or connector as either 0 or 1
* @param name pin to read from
*/
//% help=pins/digital-read-pin weight=30 shim=micro_bit::digitalReadPin
//% blockId=device_get_digital_pin block="digital read|pin %name" blockGap=8
export function digitalReadPin(name: DigitalPin): number {
return 0;
}
/**
* Set a pin or connector value to either 0 or 1.
* @param name pin to write to
* @param value value to set on the pin, eg: 1,0
*/
//% help=pins/digital-write-pin weight=29 shim=micro_bit::digitalWritePin
//% blockId=device_set_digital_pin block="digital write|pin %name|to %value"
export function digitalWritePin(name: DigitalPin, value: number): void { }
/**
* Read the connector value as analog, that is, as a value comprised between 0 and 1023.
* @param name pin to write to
*/
//% help=pins/analog-read-pin weight=25 shim=micro_bit::analogReadPin
//% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8"
export function analogReadPin(name: AnalogPin): number {
return 0;
}
/**
* Set the connector value as analog. Value must be comprised between 0 and 1023.
* @param name pin name to write to
* @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0
*/
//% help=pins/analog-write-pin weight=24 shim=micro_bit::analogWritePin
//% blockId=device_set_analog_pin block="analog write|pin %name|to %value" blockGap=8
export function analogWritePin(name: AnalogPin, value: number): void { }
/**
* Configures the Pulse-width modulation (PWM) of the analog output to the given value in **microseconds** or `1/1000` milliseconds.
* If this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.
* @param pin analog pin to set period to
* @param micros period in micro seconds. eg:20000
*/
//% shim=micro_bit::setAnalogPeriodUs help=pins/analog-set-period weight=23
//% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%micros"
export function analogSetPeriod(pin: AnalogPin, micros: number): void { }
/**
* Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).
* @param name pin to write to
* @param value angle or rotation speed, eg:180,90,0
*/
//% help=pins/servo-write-pin weight=20 shim=micro_bit::servoWritePin
//% blockId=device_set_servo_pin block="servo write|pin %name|to %value" blockGap=8
export function servoWritePin(name: AnalogPin, value: number): void { }
/**
* Configures this IO pin as an analog/pwm output, configures the period to be 20 ms, and sets the pulse width, based on the value it is given **microseconds** or `1/1000` milliseconds.
* @param pin pin name
* @param micros pulse duration in micro seconds, eg:1500
*/
//% shim=micro_bit::setServoPulseUs help=pins/serial-set-pulse weight=19
//% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %micros"
export function servoSetPulse(pin: AnalogPin, micros: number): void { }
/**
* Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.
* @param value value to map in ranges
@ -137,19 +13,4 @@ namespace pins {
export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number {
return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow;
}
/**
* Sets the pin used when using `pins->analog pitch`.
* @param name TODO
*/
//% shim=micro_bit::enablePitch help=pins/analog-set-pitch weight=12
export function analogSetPitchPin(name: AnalogPin): void { }
/**
* Emits a Pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.
* @param frequency TODO
* @param ms TODO
*/
//% shim=micro_bit::pitch help=pins/analog-pitch weight=14 async
export function analogPitch(frequency: number, ms: number): void { }
}

38
libs/microbit/serial.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "ksbit.h"
//% weight=2 color=30
namespace serial {
// note that at least one // followed by % is needed per declaration!
/**
* Reads a line of text from the serial port.
*/
//%
StringData* readString() {
return uBit.serial.readString().leakData();
}
/**
* Sends a piece of text through Serial connection.
*/
//%
void writeString(StringData *text) {
uBit.serial.sendString(ManagedString(text));
}
/**
* Sends the current pixel values, byte-per-pixel, over serial.
*/
//%
void writeScreen() {
uBit.serial.sendDisplayState();
}
/**
* Reads the screen from serial.
*/
//%
void readScreen() {
uBit.serial.readDisplayState();
}
}

View File

@ -17,32 +17,6 @@ namespace serial {
writeString(value.toString());
}
/**
* Reads a line of text from the serial port.
*/
//% shim=micro_bit::serialReadString
export function readString(): string {
return ""
}
/**
* Sends a piece of text through Serial connection.
*/
//% shim=micro_bit::serialSendString
export function writeString(text: string): void { }
/**
* Sends the current pixel values, byte-per-pixel, over serial.
*/
//% shim=micro_bit::serialSendDisplayState
export function writeScreen(): void { }
/**
* Reads the screen from serial.
*/
//% shim=micro_bit::serialReadDisplayState
export function readScreen(): void { }
/**
* Writes a ``name: value`` pair line to the serial.
* @param name name of the value stream, eg: x

View File

@ -1,6 +1,154 @@
// Auto-generated. Do not edit.
declare interface String {
/**
* Returns the character at the specified index.
* @param pos The zero-based index of the desired character.
*/
//% shim=StringMethods::charAt
charAt(pos: number): string;
/**
* Returns the Unicode value of the character at the specified location.
* @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
*/
//% shim=StringMethods::charCodeAt
charCodeAt(index: number): number;
/**
* Returns a string that contains the concatenation of two or more strings.
* @param other The string to append to the end of the string.
*/
//% shim=StringMethods::concat
concat(other: string): string;
/**
* Determines whether relative order of two strings (in ASCII encoding).
* @param that String to compare to target string
*/
//% shim=StringMethods::compare
compare(that: string): number;
/** Returns the length of a String object. */
//% property shim=StringMethods::length
length: number;
}
declare interface Boolean {
/**
* Returns a string representation of an object.
*/
//% shim=BooleanMethods::toString
toString(): string;
}
declare namespace String {
/**
* Make a string from the given ASCII character code.
*/
//% shim=String_::fromCharCode
function fromCharCode(code: number): string;
}
declare interface Number {
/**
* Returns a string representation of a number.
*/
//% shim=NumberMethods::toString
toString(): string;
}
declare namespace Math {
/**
* Returns the value of a base expression taken to a specified power.
* @param x The base value of the expression.
* @param y The exponent value of the expression.
*/
//% shim=Math_::pow
function pow(x: number, y: number): number;
/**
* Returns a pseudorandom number between 0 and `max`.
*/
//% shim=Math_::random
function random(max: number): number;
/**
* Returns the square root of a number.
* @param x A numeric expression.
*/
//% shim=Math_::sqrt
function sqrt(x: number): number;
}
//% color=45 weight=31
declare namespace images {
/**
* Creates an image that fits on the LED screen.
*/
//% weight=75 help=images/create-image
//% blockId=device_build_image block="create image" imageLiteral=1 shim=images::createImage
function createImage(leds: string): Image;
/**
* Creates an image with 2 frames.
*/
//% weight=74 help=images/create-big-image
//% blockId=device_build_big_image block="create big image" imageLiteral=2 shim=images::createBigImage
function createBigImage(leds: string): Image;
}
declare interface Image {
/**
* Shows an frame from the image at offset ``x offset``.
* @param xOffset TODO
*/
//% help=images/show-image weight=80 async
//% BUGblockId=device_show_image_offset block="show image %sprite|at offset %offset" blockGap=8 xOffset.defl=0 shim=ImageMethods::showImage
showImage(xOffset?: number): void;
/**
* Scrolls an image .
* @param frameOffset x offset moved on each animation step, eg: 5, 1, -1
* @param interval time between each animation step in milli seconds, eg: 200
*/
//% help=images/show-image weight=79 async
//% BUGblockId=device_scroll_image block="scroll image %sprite|with offset %frameoffset|and interval (ms) %delay" blockGap=8 frameOffset.defl=0 interval.defl=200 shim=ImageMethods::scrollImage
scrollImage(frameOffset?: number, interval?: number): void;
/**
* Plots the image at a given column to the screen
*/
//% help=images/plot-image xOffset.defl=0 shim=ImageMethods::plotImage
plotImage(xOffset?: number): void;
/**
* Sets all pixels off.
*/
//% help=images/clear shim=ImageMethods::clear
clear(): void;
/**
* Sets a specific pixel brightness at a given position
*/
//% help= shim=ImageMethods::setPixelBrightness
setPixelBrightness(x: number, y: number, value: number): void;
/**
* Gets the pixel brightness ([0..255]) at a given position
*/
//% help= shim=ImageMethods::pixelBrightness
pixelBrightness(x: number, y: number): number;
}
/**
* Provides access to basic micro:bit functionality.
*/
@ -14,8 +162,7 @@ declare namespace basic {
//% help=basic/show-number
//% weight=96
//% blockId=device_show_number block="show|number %number" blockGap=8 icon="\uf1ec"
//% async
//% interval.defl=150 shim=basic::showNumber
//% async interval.defl=150 shim=basic::showNumber
function showNumber(value: number, interval?: number): void;
/**
@ -27,8 +174,7 @@ declare namespace basic {
//% weight=95 blockGap=8
//% imageLiteral=1 async
//% blockId=device_show_leds
//% block="show leds" icon="\uf00a"
//% interval.defl=400 imageLiteral=1 shim=basic::showLeds
//% block="show leds" icon="\uf00a" interval.defl=400 shim=basic::showLeds
function showLeds(leds: string, interval?: number): void;
/**
@ -40,8 +186,7 @@ declare namespace basic {
//% weight=87 blockGap=8
//% block="show|string %text" icon="\uf031"
//% async
//% blockId=device_print_message
//% interval.defl=150 shim=basic::showString
//% blockId=device_print_message interval.defl=150 shim=basic::showString
function showString(text: string, interval?: number): void;
/**
@ -56,15 +201,14 @@ declare namespace basic {
* @param leds TODO
* @param interval TODO
*/
//% help=basic/show-animation shim=micro_bit::showAnimation imageLiteral=1 async
//% interval.defl=400 imageLiteral=1 shim=basic::showAnimation
//% help=basic/show-animation imageLiteral=1 async interval.defl=400 shim=basic::showAnimation
function showAnimation(leds: string, interval?: number): void;
/**
* Draws an image on the LED screen.
* @param leds TODO
*/
//% help=basic/plot-leds weight=80 shim=micro_bit::plotLeds imageLiteral=1 shim=basic::plotLeds
//% help=basic/plot-leds weight=80 imageLiteral=1 shim=basic::plotLeds
function plotLeds(leds: string): void;
/**
@ -87,6 +231,125 @@ declare namespace basic {
//% color=300 weight=99
declare namespace input {
/**
* Do something when a button (``A``, ``B`` or both ``A+B``) is pressed
* @param button TODO
* @param body TODO
*/
//% help=input/on-button-pressed weight=85
//% blockId=device_button_event
//% block="on button|%NAME|pressed"
//% icon="\uf192" shim=input::onButtonPressed
function onButtonPressed(button: Button, body: () => void): void;
/**
* Attaches code to run when the screen is facing up.
* @param body TODO
*/
//% help=input/on-gesture weight=84
//% blockId=device_gesture_event block="on |%NAME" icon="\uf135" shim=input::onGesture
function onGesture(gesture: Gesture, body: () => void): void;
/**
* Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.
* @param name TODO
* @param body TODO
*/
//% help=input/on-pin-pressed weight=83
//% blockId=device_pin_event block="on pin|%NAME|pressed" icon="\uf094" shim=input::onPinPressed
function onPinPressed(name: TouchPin, body: () => void): void;
/**
* Get the button state (pressed or not) for ``A`` and ``B``.
*/
//% help=input/button-is-pressed weight=57
//% block="button|%NAME|is pressed"
//% blockId=device_get_button2
//% icon="\uf192" blockGap=8 shim=input::buttonIsPressed
function buttonIsPressed(button: Button): boolean;
/**
* Get the current compass compass heading in degrees.
*/
//% help=input/compass-heading
//% weight=56 icon="\uf14e"
//% blockId=device_heading block="compass heading (°)" blockGap=8 shim=input::compassHeading
function compassHeading(): number;
/**
* Gets the temperature in Celsius degrees (°C).
*/
//% weight=55 icon="\uf06d"
//% help=input/temperature
//% blockId=device_temperature block="temperature (°C)" blockGap=8 shim=input::temperature
function temperature(): number;
/**
* Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)
* @param dimension TODO
*/
//% help=input/acceleration weight=54 icon="\uf135"
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8 shim=input::acceleration
function acceleration(dimension: Dimension): number;
/**
* Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright. In the simulator, the ``acceleration y`` is used to emulate this value.
*/
//% help=input/light-level weight=53
//% blockId=device_get_light_level block="light level" blockGap=8 icon="\uf185" shim=input::lightLevel
function lightLevel(): number;
/**
* The pitch of the device, rotation along the ``x-axis``, in degrees.
* @param kind TODO
*/
//% help=/input/rotation weight=52
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8 icon="\uf197" shim=input::rotation
function rotation(kind: Rotation): number;
/**
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
* @param dimension TODO
*/
//% help=input/magnetic-force weight=51
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8 icon="\uf076" shim=input::magneticForce
function magneticForce(dimension: Dimension): number;
/**
* Gets the number of milliseconds elapsed since power on.
*/
//% help=input/running-time weight=50
//% blockId=device_get_running_time block="running time (ms)" icon="\uf017" shim=input::runningTime
function runningTime(): number;
/**
* Obsolete, compass calibration is automatic.
*/
//% help=input/calibrate weight=0 shim=input::calibrate
function calibrate(): void;
/**
* Get the pin state (pressed or not). Requires to hold the ground to close the circuit.
* @param name pin used to detect the touch
*/
//% help=input/pin-is-pressed weight=58 block="pin|%NAME|is pressed" icon="\uf094" shim=input::pinIsPressed
function pinIsPressed(name: TouchPin): boolean;
/**
* Sets the accelerometer sample range in gravities.
* @param range a value describe the maximum strengh of acceleration measured
*/
//% help=input/set-accelerator-range
//% blockId=device_set_accelerometer_range block="set accelerometer|range %range" icon="\uf135"
//% weight=5 shim=input::setAccelerometerRange
function setAccelerometerRange(range: AcceleratorRange): void;
}
//% weight=1 color="#333333"
declare namespace control {
@ -111,8 +374,8 @@ declare namespace control {
* @param mode optional definition of how the event should be processed after construction (default is CREATE_AND_QUEUE).
*/
//% weight=21 blockGap=12 blockId="control_raise_event" block="raise event|from source %src=control_event_source|with value %value=control_event_value" blockExternalInputs=1
//% mode.defl=CREATE_AND_QUEUE shim=control::raiseEvent
function raiseEvent(src: number, value: number, mode: EventCreationMode ): void;
//% mode.defl=1 shim=control::raiseEvent
function raiseEvent(src: number, value: number, mode: EventCreationMode): void;
/**
* Raises an event in the event bus.
@ -122,4 +385,185 @@ declare namespace control {
function onEvent(src: number, value: number, handler: () => void): void;
}
//% color=3 weight=35
declare namespace led {
/**
* Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/plot weight=78
//% blockId=device_plot block="plot|x %x|y %y" icon="\uf205" blockGap=8 shim=led::plot
function plot(x: number, y: number): void;
/**
* Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/unplot weight=77
//% blockId=device_unplot block="unplot|x %x|y %y" icon="\uf204" blockGap=8 shim=led::unplot
function unplot(x: number, y: number): void;
/**
* Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.
* @param x TODO
* @param y TODO
*/
//% help=led/point weight=76
//% blockId=device_point block="point|x %x|y %y" icon="\uf10c" shim=led::point
function point(x: number, y: number): boolean;
/**
* Get the screen brightness from 0 (off) to 255 (full bright).
*/
//% help=led/brightness weight=60
//% blockId=device_get_brightness block="brightness" icon="\uf042" blockGap=8 shim=led::brightness
function brightness(): number;
/**
* Set the screen brightness from 0 (off) to 255 (full bright).
* @param value the brightness value, eg:255, 127, 0
*/
//% help=led/set-brightness weight=59
//% blockId=device_set_brightness block="set brightness %value" icon="\uf042" shim=led::setBrightness
function setBrightness(value: number): void;
/**
* Cancels the current animation and clears other pending animations.
*/
//% weight=50 help=led/stop-animation
//% blockId=device_stop_animation block="stop animation" icon="\uf04d" shim=led::stopAnimation
function stopAnimation(): void;
/**
* Sets the display mode between black and white and greyscale for rendering LEDs.
* @param mode TODO
*/
//% weight=1 help=/led/set-display-mode shim=led::setDisplayMode
function setDisplayMode(mode: DisplayMode): void;
/**
* Takes a screenshot of the LED screen and returns an image.
*/
//% help=led/screenshot shim=led::screenshot
function screenshot(): Image;
}
//% color=351 weight=30
declare namespace pins {
/**
* Read the specified pin or connector as either 0 or 1
* @param name pin to read from
*/
//% help=pins/digital-read-pin weight=30
//% blockId=device_get_digital_pin block="digital read|pin %name" blockGap=8 shim=pins::digitalReadPin
function digitalReadPin(name: DigitalPin): number;
/**
* Set a pin or connector value to either 0 or 1.
* @param name pin to write to
* @param value value to set on the pin, 1 eg,0
*/
//% help=pins/digital-write-pin weight=29
//% blockId=device_set_digital_pin block="digital write|pin %name|to %value" shim=pins::digitalWritePin
function digitalWritePin(name: DigitalPin, value: number): void;
/**
* Read the connector value as analog, that is, as a value comprised between 0 and 1023.
* @param name pin to write to
*/
//% help=pins/analog-read-pin weight=25
//% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8" shim=pins::analogReadPin
function analogReadPin(name: AnalogPin): number;
/**
* Set the connector value as analog. Value must be comprised between 0 and 1023.
* @param name pin name to write to
* @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0
*/
//% help=pins/analog-write-pin weight=24
//% blockId=device_set_analog_pin block="analog write|pin %name|to %value" blockGap=8 shim=pins::analogWritePin
function analogWritePin(name: AnalogPin, value: number): void;
/**
* Configures the Pulse-width modulation (PWM) of the analog output to the given value in **microseconds** or `1/1000` milliseconds.
* If this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.
* @param name analog pin to set period to
* @param micros period in micro seconds. eg:20000
*/
//% help=pins/analog-set-period weight=23
//% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%micros" shim=pins::analogSetPeriod
function analogSetPeriod(name: AnalogPin, micros: number): void;
/**
* Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).
* @param name pin to write to
* @param value angle or rotation speed, eg:180,90,0
*/
//% help=pins/servo-write-pin weight=20
//% blockId=device_set_servo_pin block="servo write|pin %name|to %value" blockGap=8 shim=pins::servoWritePin
function servoWritePin(name: AnalogPin, value: number): void;
/**
* Configures this IO pin as an analog/pwm output, configures the period to be 20 ms, and sets the pulse width, based on the value it is given **microseconds** or `1/1000` milliseconds.
* @param name pin name
* @param micros pulse duration in micro seconds, eg:1500
*/
//% help=pins/serial-set-pulse weight=19
//% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %micros" shim=pins::servoSetPulse
function servoSetPulse(name: AnalogPin, micros: number): void;
/**
* Sets the pin used when using `pins->analog pitch`.
* @param name TODO
*/
//% help=pins/analog-set-pitch weight=12 shim=pins::analogSetPitchPin
function analogSetPitchPin(name: AnalogPin): void;
/**
* Emits a Pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.
* @param frequency TODO
* @param ms TODO
*/
//% help=pins/analog-pitch weight=14 async shim=pins::analogPitch
function analogPitch(frequency: number, ms: number): void;
}
//% weight=2 color=30
declare namespace serial {
/**
* Reads a line of text from the serial port.
*/
//% shim=serial::readString
function readString(): string;
/**
* Sends a piece of text through Serial connection.
*/
//% shim=serial::writeString
function writeString(text: string): void;
/**
* Sends the current pixel values, byte-per-pixel, over serial.
*/
//% shim=serial::writeScreen
function writeScreen(): void;
/**
* Reads the screen from serial.
*/
//% shim=serial::readScreen
function readScreen(): void;
}
// Auto-generated. Do not edit. Really.

View File

@ -1,6 +1,6 @@
{
"name": "kindscript-microbit",
"version": "0.2.10",
"version": "0.2.12",
"description": "BBC micro:bit target for KindScript",
"keywords": [
"JavaScript",
@ -30,6 +30,6 @@
"typescript": "^1.8.7"
},
"dependencies": {
"kindscript": "0.2.10"
"kindscript": "0.2.14"
}
}

View File

@ -2,14 +2,12 @@
/// <reference path="../node_modules/kindscript/built/kindsim.d.ts"/>
/// <reference path="../libs/microbit/dal.d.ts"/>
namespace ks.rt.micro_bit {
export function initCurrentRuntime() {
namespace ks.rt {
ks.rt.initCurrentRuntime = () => {
U.assert(!runtime.board)
runtime.board = new Board()
}
ks.rt.initCurrentRuntime = initCurrentRuntime;
export function board() {
return runtime.board as Board
}
@ -85,206 +83,12 @@ namespace ks.rt.micro_bit {
throw new Error("PANIC " + code)
}
/* leds */
export function plot(x: number, y: number) {
board().image.set(x, y, 255);
runtime.queueDisplayUpdate()
export function getPin(id: number) {
return board().pins.filter(p => p && p.id == id)[0] || null
}
export function unPlot(x: number, y: number) {
board().image.set(x, y, 0);
runtime.queueDisplayUpdate()
}
export function point(x: number, y: number): boolean {
return !!board().image.get(x, y);
}
export function brightness(): number {
return board().brigthness;
}
export function setBrightness(value: number): void {
board().brigthness = value;
runtime.queueDisplayUpdate()
}
export function stopAnimation(): void {
board().animationQ.cancelAll();
}
export function plotLeds(leds: micro_bit.Image): void {
leds.copyTo(0, 5, board().image, 0)
runtime.queueDisplayUpdate()
}
export function setDisplayMode(mode: DisplayMode): void {
board().displayMode = mode;
runtime.queueDisplayUpdate()
}
/* serial */
export function serialSendString(s: string) {
board().writeSerial(s);
}
export function serialReadString(): string {
return board().readSerial();
}
/* input */
export function onButtonPressed(button: number, handler: RefAction): void {
let b = board();
if (button == DAL.MICROBIT_ID_BUTTON_AB && !board().usesButtonAB) {
b.usesButtonAB = true;
runtime.queueDisplayUpdate();
}
b.bus.listen(button, DAL.MICROBIT_BUTTON_EVT_CLICK, handler);
}
export function isButtonPressed(button: number): boolean {
let b = board();
if (button == DAL.MICROBIT_ID_BUTTON_AB && !board().usesButtonAB) {
b.usesButtonAB = true;
runtime.queueDisplayUpdate();
}
let bts = b.buttons;
if (button == DAL.MICROBIT_ID_BUTTON_A) return bts[0].pressed;
if (button == DAL.MICROBIT_ID_BUTTON_B) return bts[1].pressed;
return bts[2].pressed || (bts[0].pressed && bts[1].pressed);
}
export function onGesture(gesture: number, handler: RefAction) {
let b = board();
b.accelerometer.activate();
if (gesture == 11 && !b.useShake) { // SAKE
b.useShake = true;
runtime.queueDisplayUpdate();
}
b.bus.listen(DAL.MICROBIT_ID_GESTURE, gesture, handler);
}
export function onPinPressed(pin: Pin, handler: RefAction) {
pin.isTouched();
onButtonPressed(pin.id, handler);
}
export function ioP0() { return board().pins[0]; }
export function ioP1() { return board().pins[1]; }
export function ioP2() { return board().pins[2]; }
export function ioP3() { return board().pins[3]; }
export function ioP4() { return board().pins[4]; }
export function ioP5() { return board().pins[5]; }
export function ioP6() { return board().pins[6]; }
export function ioP7() { return board().pins[7]; }
export function ioP8() { return board().pins[8]; }
export function ioP9() { return board().pins[9]; }
export function ioP10() { return board().pins[10]; }
export function ioP11() { return board().pins[11]; }
export function ioP12() { return board().pins[12]; }
export function ioP13() { return board().pins[13]; }
export function ioP14() { return board().pins[14]; }
export function ioP15() { return board().pins[15]; }
export function ioP16() { return board().pins[16]; }
export function ioP19() { return board().pins[19]; }
export function ioP20() { return board().pins[20]; }
export function isPinTouched(pin: Pin): boolean {
return pin.isTouched();
}
export function compassHeading(): number {
var b = board();
if (!b.usesHeading) {
b.usesHeading = true;
runtime.queueDisplayUpdate();
}
return b.heading;
}
export function temperature(): number {
var b = board();
if (!b.usesTemperature) {
b.usesTemperature = true;
runtime.queueDisplayUpdate();
}
return b.temperature;
}
export function getAcceleration(dimension: number): number {
let b = board();
let acc = b.accelerometer;
acc.activate();
switch (dimension) {
case 0: return acc.getX();
case 1: return acc.getY();
case 2: return acc.getZ();
default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
}
}
export function setAccelerometerRange(range: number) {
let b = board();
b.accelerometer.setSampleRange(range);
}
export function lightLevel(): number {
let b = board();
if (!b.usesLightLevel) {
b.usesLightLevel = true;
runtime.queueDisplayUpdate();
}
return b.lightLevel;
}
export function getMagneticForce(): number {
// TODO
return 0;
}
export function getCurrentTime(): number {
return runtime.runningTime();
}
/* pins */
export function digitalReadPin(pin: Pin): number {
pin.mode = PinMode.Digital | PinMode.Input;
return pin.value > 100 ? 1 : 0;
}
export function digitalWritePin(pin: Pin, value: number) {
pin.mode = PinMode.Digital | PinMode.Output;
pin.value = value > 0 ? 1023 : 0;
runtime.queueDisplayUpdate();
}
export function analogReadPin(pin: Pin): number {
pin.mode = PinMode.Analog | PinMode.Input;
return pin.value || 0;
}
export function analogWritePin(pin: Pin, value: number) {
pin.mode = PinMode.Analog | PinMode.Output;
pin.value = value ? 1 : 0;
runtime.queueDisplayUpdate();
}
export function setAnalogPeriodUs(pin: Pin, micros: number) {
pin.mode = PinMode.Analog | PinMode.Output;
pin.period = micros;
runtime.queueDisplayUpdate();
}
export function servoWritePin(pin: Pin, value: number) {
setAnalogPeriodUs(pin, 20000);
// TODO
}
export function servoSetPulse(pin: Pin, micros: number) {
}
module AudioContextManager {
export namespace AudioContextManager {
var _context: any; // AudioContext
var _vco: any; //OscillatorNode;
var _vca: any; // GainNode;
@ -336,12 +140,350 @@ namespace ks.rt.micro_bit {
}
}
export function enablePitch(pin: Pin) {
}
namespace ks.rt.basic {
export var pause = thread.pause;
export function showNumber(x: number, interval: number) {
if (interval < 0) return;
let leds = createImageFromString(x.toString());
if (x < 0 || x >= 10) scrollImage(leds, interval, 1);
else showLeds(leds, interval * 5);
}
export function showString(s: string, interval: number) {
if (interval < 0) return;
if (s.length == 0) {
clearScreen();
pause(interval * 5);
} else {
let leds = createImageFromString(s);
if (s.length == 1) showLeds(leds, interval * 5)
else scrollImage(leds, interval, 1);
}
}
export function showLeds(leds: Image, delay: number): void {
showAnimation(leds, delay);
}
export function clearScreen() {
board().image.clear();
runtime.queueDisplayUpdate()
}
function scrollImage(leds: Image, interval: number, stride: number): void {
let cb = getResume()
let off = stride > 0 ? 0 : leds.width - 1;
let display = board().image;
board().animationQ.enqueue({
interval: interval,
frame: () => {
if (off >= leds.width || off < 0) return false;
stride > 0 ? display.shiftLeft(stride) : display.shiftRight(-stride);
let c = Math.min(stride, leds.width - off);
leds.copyTo(off, c, display, 5 - stride)
off += stride;
return true;
},
whenDone: cb
})
}
export function showAnimation(leds: Image, interval: number = 400): void {
scrollImage(leds, interval, 5);
}
export function forever(a: RefAction) {
function loop() {
runtime.runFiberAsync(a)
.then(() => Promise.delay(20))
.then(loop)
.done()
}
incr(a)
loop()
}
export function plotLeds(leds: Image): void {
leds.copyTo(0, 5, board().image, 0)
runtime.queueDisplayUpdate()
}
}
namespace ks.rt.control {
export var inBackground = thread.runInBackground;
export function reset() {
U.userError("reset not implemented in simulator yet")
}
export function onEvent(id: number, evid: number, handler: RefAction) {
kindscript.registerWithDal(id, evid, handler)
}
export function raiseEvent(id: number, evid: number, mode: number) {
// TODO mode?
board().bus.queue(id, evid)
}
}
namespace ks.rt.kindscript {
export function registerWithDal(id: number, evid: number, handler: RefAction) {
board().bus.listen(id, evid, handler);
}
}
namespace ks.rt.input {
export function onButtonPressed(button: number, handler: RefAction): void {
let b = board();
if (button == DAL.MICROBIT_ID_BUTTON_AB && !board().usesButtonAB) {
b.usesButtonAB = true;
runtime.queueDisplayUpdate();
}
b.bus.listen(button, DAL.MICROBIT_BUTTON_EVT_CLICK, handler);
}
export function buttonIsPressed(button: number): boolean {
let b = board();
if (button == DAL.MICROBIT_ID_BUTTON_AB && !board().usesButtonAB) {
b.usesButtonAB = true;
runtime.queueDisplayUpdate();
}
let bts = b.buttons;
if (button == DAL.MICROBIT_ID_BUTTON_A) return bts[0].pressed;
if (button == DAL.MICROBIT_ID_BUTTON_B) return bts[1].pressed;
return bts[2].pressed || (bts[0].pressed && bts[1].pressed);
}
export function onGesture(gesture: number, handler: RefAction) {
let b = board();
b.accelerometer.activate();
if (gesture == 11 && !b.useShake) { // SAKE
b.useShake = true;
runtime.queueDisplayUpdate();
}
b.bus.listen(DAL.MICROBIT_ID_GESTURE, gesture, handler);
}
export function onPinPressed(pinId: number, handler: RefAction) {
let pin = getPin(pinId);
if (!pin) return;
pin.isTouched();
input.onButtonPressed(pin.id, handler);
}
export function pinIsPressed(pinId: number): boolean {
let pin = getPin(pinId);
if (!pin) return false;
return pin.isTouched();
}
export function compassHeading(): number {
var b = board();
if (!b.usesHeading) {
b.usesHeading = true;
runtime.queueDisplayUpdate();
}
return b.heading;
}
export function temperature(): number {
var b = board();
if (!b.usesTemperature) {
b.usesTemperature = true;
runtime.queueDisplayUpdate();
}
return b.temperature;
}
export function acceleration(dimension: number): number {
let b = board();
let acc = b.accelerometer;
acc.activate();
switch (dimension) {
case 0: return acc.getX();
case 1: return acc.getY();
case 2: return acc.getZ();
default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
}
}
export function setAccelerometerRange(range: number) {
let b = board();
b.accelerometer.setSampleRange(range);
}
export function lightLevel(): number {
let b = board();
if (!b.usesLightLevel) {
b.usesLightLevel = true;
runtime.queueDisplayUpdate();
}
return b.lightLevel;
}
export function magneticForce(): number {
// TODO
return 0;
}
export function runningTime(): number {
return runtime.runningTime();
}
export function calibrate() {
}
}
namespace ks.rt.led {
export function plot(x: number, y: number) {
board().image.set(x, y, 255);
runtime.queueDisplayUpdate()
}
export function unplot(x: number, y: number) {
board().image.set(x, y, 0);
runtime.queueDisplayUpdate()
}
export function point(x: number, y: number): boolean {
return !!board().image.get(x, y);
}
export function brightness(): number {
return board().brigthness;
}
export function setBrightness(value: number): void {
board().brigthness = value;
runtime.queueDisplayUpdate()
}
export function stopAnimation(): void {
board().animationQ.cancelAll();
}
export function setDisplayMode(mode: DisplayMode): void {
board().displayMode = mode;
runtime.queueDisplayUpdate()
}
}
namespace ks.rt.serial {
export function writeString(s: string) {
board().writeSerial(s);
}
export function readString(): string {
return board().readSerial();
}
}
namespace ks.rt.radio {
export function broadcastMessage(msg: number): void {
board().radio.broadcast(msg);
}
export function onBroadcastMessageReceived(msg: number, handler: RefAction): void {
board().bus.listen(DAL.MES_BROADCAST_GENERAL_ID, msg, handler);
}
export function setGroup(id: number): void {
board().radio.setGroup(id);
}
export function setTransmitPower(power: number): void {
board().radio.setTransmitPower(power);
}
export function sendNumbers(value0: number, value1: number, value2: number, value3: number): void {
board().radio.datagram.send([value0, value1, value2, value3]);
}
export function receiveNumber(): number {
return board().radio.datagram.recv().data[0];
}
export function receivedNumberAt(index: number): number {
return board().radio.datagram.lastReceived.data[index] || 0;
}
export function receivedSignalStrength(): number {
return board().radio.datagram.lastReceived.rssi;
}
export function onDataReceived(handler: RefAction): void {
board().bus.listen(DAL.MICROBIT_ID_RADIO, DAL.MICROBIT_RADIO_EVT_DATAGRAM, handler);
}
}
namespace ks.rt.pins {
export function digitalReadPin(pinId: number): number {
let pin = getPin(pinId);
if (!pin) return;
pin.mode = PinMode.Digital | PinMode.Input;
return pin.value > 100 ? 1 : 0;
}
export function digitalWritePin(pinId: number, value: number) {
let pin = getPin(pinId);
if (!pin) return;
pin.mode = PinMode.Digital | PinMode.Output;
pin.value = value > 0 ? 1023 : 0;
runtime.queueDisplayUpdate();
}
export function analogReadPin(pinId: number): number {
let pin = getPin(pinId);
if (!pin) return;
pin.mode = PinMode.Analog | PinMode.Input;
return pin.value || 0;
}
export function analogWritePin(pinId: number, value: number) {
let pin = getPin(pinId);
if (!pin) return;
pin.mode = PinMode.Analog | PinMode.Output;
pin.value = value ? 1 : 0;
runtime.queueDisplayUpdate();
}
export function analogSetPeriod(pinId: number, micros: number) {
let pin = getPin(pinId);
if (!pin) return;
pin.mode = PinMode.Analog | PinMode.Output;
pin.period = micros;
runtime.queueDisplayUpdate();
}
export function servoWritePin(pinId: number, value: number) {
analogSetPeriod(pinId, 20000);
// TODO
}
export function servoSetPulse(pinId: number, micros: number) {
let pin = getPin(pinId);
if (!pin) return;
// TODO
}
export function analogSetPitchPin(pinId: number) {
let pin = getPin(pinId);
if (!pin) return;
board().pins.filter(p => !!p).forEach(p => p.pitch = false);
pin.pitch = true;
}
export function pitch(frequency: number, ms: number) {
export function analogPitch(frequency: number, ms: number) {
// update analog output
let pin = board().pins.filter(pin => !!pin && pin.pitch)[0] || board().pins[0];
pin.mode = PinMode.Analog | PinMode.Output;
@ -370,117 +512,19 @@ namespace ks.rt.micro_bit {
}
/* radio */
export function broadcastMessage(msg: number): void {
board().radio.broadcast(msg);
}
export function onBroadcastMessageReceived(msg: number, handler: RefAction): void {
board().bus.listen(DAL.MES_BROADCAST_GENERAL_ID, msg, handler);
}
export function setGroup(id: number): void {
board().radio.setGroup(id);
}
export function setTransmitPower(power: number): void {
board().radio.setTransmitPower(power);
}
export function datagramSendNumbers(value0: number, value1: number, value2: number, value3: number): void {
board().radio.datagram.send([value0, value1, value2, value3]);
}
export function datagramReceiveNumber(): number {
return board().radio.datagram.recv().data[0];
}
export function datagramGetNumber(index: number): number {
return board().radio.datagram.lastReceived.data[index] || 0;
}
export function datagramGetRSSI(): number {
return board().radio.datagram.lastReceived.rssi;
}
export function onDatagramReceived(handler: RefAction): void {
board().bus.listen(DAL.MICROBIT_ID_RADIO, DAL.MICROBIT_RADIO_EVT_DATAGRAM, handler);
}
}
namespace ks.rt.basic {
var board = micro_bit.board;
namespace ks.rt.images {
export function createImage(img: Image) { return img }
export function createBigImage(img: Image) { return img }
}
export var pause = thread.pause;
export function showNumber(x: number, interval: number) {
if (interval < 0) return;
let leds = micro_bit.createImageFromString(x.toString());
if (x < 0 || x >= 10) scrollImage(leds, interval, 1);
else showLeds(leds, interval * 5);
}
export function showString(s: string, interval: number) {
if (interval < 0) return;
if (s.length == 0) {
clearScreen();
pause(interval * 5);
} else {
let leds = micro_bit.createImageFromString(s);
if (s.length == 1) showLeds(leds, interval * 5)
else scrollImage(leds, interval, 1);
}
}
export function showLeds(leds: micro_bit.Image, delay: number): void {
showAnimation(leds, delay);
}
export function clearScreen() {
board().image.clear();
namespace ks.rt.ImageMethods {
export function showImage(i: Image, offset: number) {
// TODO offset?
i.copyTo(0, 5, board().image, 0)
runtime.queueDisplayUpdate()
}
function scrollImage(leds: micro_bit.Image, interval: number, stride: number): void {
let cb = getResume()
let off = stride > 0 ? 0 : leds.width - 1;
let display = board().image;
board().animationQ.enqueue({
interval: interval,
frame: () => {
if (off >= leds.width || off < 0) return false;
stride > 0 ? display.shiftLeft(stride) : display.shiftRight(-stride);
let c = Math.min(stride, leds.width - off);
leds.copyTo(off, c, display, 5 - stride)
off += stride;
return true;
},
whenDone: cb
})
}
export function showAnimation(leds: micro_bit.Image, interval: number = 400): void {
scrollImage(leds, interval, 5);
}
export function forever(a: RefAction) {
function loop() {
runtime.runFiberAsync(a)
.then(() => Promise.delay(20))
.then(loop)
.done()
}
incr(a)
loop()
}
}
namespace ks.rt.control {
export var inBackground = thread.runInBackground;
export function reset() {
U.userError("reset not implemented in simulator yet")
}
}
// TODO ...
}

View File

@ -188,10 +188,10 @@ namespace ks.rt.micro_bit {
private thermometerText: SVGTextElement;
private shakeButton: SVGCircleElement;
private shakeText: SVGTextElement;
public board: rt.micro_bit.Board;
public board: rt.Board;
constructor(public props: IBoardProps) {
this.board = this.props.runtime.board as rt.micro_bit.Board;
this.board = this.props.runtime.board as rt.Board;
this.board.updateView = () => this.updateState();
this.buildDom();
this.updateTheme();
@ -227,7 +227,7 @@ namespace ks.rt.micro_bit {
Svg.fill(this.buttons[index], btn.pressed ? theme.buttonDown : theme.buttonUp);
});
var bw = state.displayMode == rt.micro_bit.DisplayMode.bw
var bw = state.displayMode == rt.DisplayMode.bw
var img = state.image;
this.leds.forEach((led,i) => {
var sel = (<SVGStylable><any>led)

View File

@ -1,4 +1,4 @@
namespace ks.rt.micro_bit {
namespace ks.rt {
export interface RuntimeOptions {
theme: string;
}
@ -468,21 +468,6 @@ namespace ks.rt.micro_bit {
}
export interface SimulatorEventBusMessage extends SimulatorMessage {
id: number;
eventid: number;
value?: number;
}
export interface SimulatorSerialMessage extends SimulatorMessage {
id: string;
data: string;
}
export interface SimulatorRadioPacketMessage extends SimulatorMessage {
data: number[];
rssi?: number;
}
export class Board extends BaseBoard {
id: string;