Merge branch 'cpp'
This commit is contained in:
commit
5922135073
@ -1,7 +1,3 @@
|
|||||||
//% shim=foo::bar
|
|
||||||
function test() {
|
|
||||||
}
|
|
||||||
|
|
||||||
basic.plotLeds(`
|
basic.plotLeds(`
|
||||||
# # . # #
|
# # . # #
|
||||||
. . # . .
|
. . # . .
|
||||||
@ -10,4 +6,5 @@ basic.plotLeds(`
|
|||||||
. # # # .
|
. # # # .
|
||||||
`);
|
`);
|
||||||
basic.pause(300);
|
basic.pause(300);
|
||||||
test();
|
basic.showString("Hello");
|
||||||
|
// foo.bar();
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
#include "BitVM.h"
|
||||||
|
#include "MicroBitTouchDevelop.h"
|
||||||
|
|
||||||
namespace foo {
|
namespace foo {
|
||||||
GLUE void bar()
|
//%
|
||||||
|
void bar()
|
||||||
{
|
{
|
||||||
micro_bit::scrollNumber(108108, 50);
|
touch_develop::micro_bit::scrollNumber(108108, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
],
|
],
|
||||||
"public": true,
|
"public": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core": "file:../microbit"
|
"microbit": "file:../microbit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#include "BitVM.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to basic micro:bit functionality.
|
* Provides access to basic micro:bit functionality.
|
||||||
*/
|
*/
|
||||||
@ -10,10 +13,19 @@ namespace basic {
|
|||||||
*/
|
*/
|
||||||
//% help=basic/show-number
|
//% help=basic/show-number
|
||||||
//% weight=96
|
//% weight=96
|
||||||
//% shim=micro_bit::scrollNumber
|
|
||||||
//% blockId=device_show_number block="show|number %number" blockGap=8 icon="\uf1ec"
|
//% blockId=device_show_number block="show|number %number" blockGap=8 icon="\uf1ec"
|
||||||
//% async
|
//% async
|
||||||
export function showNumber(value: number, interval: number = 150): void { }
|
void showNumber(int value, int interval = 150) {
|
||||||
|
if (interval < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ManagedString t(value);
|
||||||
|
if (value < 0 || value >= 10) {
|
||||||
|
uBit.display.scroll(t, interval);
|
||||||
|
} else {
|
||||||
|
uBit.display.print(t.charAt(0), interval * 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws an image on the LED screen.
|
* Draws an image on the LED screen.
|
||||||
@ -22,11 +34,12 @@ namespace basic {
|
|||||||
*/
|
*/
|
||||||
//% help=basic/show-leds
|
//% help=basic/show-leds
|
||||||
//% weight=95 blockGap=8
|
//% weight=95 blockGap=8
|
||||||
//% shim=micro_bit::showLeds
|
|
||||||
//% imageLiteral=1 async
|
//% imageLiteral=1 async
|
||||||
//% blockId=device_show_leds
|
//% blockId=device_show_leds
|
||||||
//% block="show leds" icon="\uf00a"
|
//% block="show leds" icon="\uf00a"
|
||||||
export function showLeds(leds: string, interval: number = 400): void { }
|
void showLeds(ImageLiteral leds, int interval = 400) {
|
||||||
|
uBit.display.print(MicroBitImage(getbytes(leds)), 0, 0, 0, interval);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.
|
* Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.
|
||||||
@ -35,19 +48,32 @@ namespace basic {
|
|||||||
*/
|
*/
|
||||||
//% help=basic/show-string
|
//% help=basic/show-string
|
||||||
//% weight=87 blockGap=8
|
//% weight=87 blockGap=8
|
||||||
//% shim=micro_bit::scrollString async
|
|
||||||
//% block="show|string %text" icon="\uf031"
|
//% block="show|string %text" icon="\uf031"
|
||||||
//% async
|
//% async
|
||||||
//% blockId=device_print_message
|
//% blockId=device_print_message
|
||||||
export function showString(text: string, interval: number = 150): void { }
|
void showString(StringData *text, int interval = 150) {
|
||||||
|
if (interval < 0)
|
||||||
|
return;
|
||||||
|
ManagedString s(text);
|
||||||
|
int l = s.length();
|
||||||
|
if (l == 0) {
|
||||||
|
uBit.display.clear();
|
||||||
|
uBit.sleep(interval * 5);
|
||||||
|
} else if (l > 1) {
|
||||||
|
uBit.display.scroll(s, interval);
|
||||||
|
} else {
|
||||||
|
uBit.display.print(s.charAt(0), interval * 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn off all LEDs
|
* Turn off all LEDs
|
||||||
*/
|
*/
|
||||||
//% help=basic/clear-screen weight=79
|
//% help=basic/clear-screen weight=79
|
||||||
//% shim=micro_bit::clearScreen
|
|
||||||
//% blockId=device_clear_display block="clear screen" icon="\uf12d"
|
//% blockId=device_clear_display block="clear screen" icon="\uf12d"
|
||||||
export function clearScreen(): void { }
|
void clearScreen() {
|
||||||
|
uBit.display.image.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows a sequence of LED screens as an animation.
|
* Shows a sequence of LED screens as an animation.
|
||||||
@ -55,29 +81,48 @@ namespace basic {
|
|||||||
* @param interval TODO
|
* @param interval TODO
|
||||||
*/
|
*/
|
||||||
//% help=basic/show-animation shim=micro_bit::showAnimation imageLiteral=1 async
|
//% help=basic/show-animation shim=micro_bit::showAnimation imageLiteral=1 async
|
||||||
export function showAnimation(leds: string, interval: number = 400): void { }
|
void showAnimation(ImageLiteral leds, int interval = 400) {
|
||||||
|
uBit.display.animate(MicroBitImage(getbytes(leds)), interval, 5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws an image on the LED screen.
|
* Draws an image on the LED screen.
|
||||||
* @param leds TODO
|
* @param leds TODO
|
||||||
*/
|
*/
|
||||||
//% help=basic/plot-leds weight=80 shim=micro_bit::plotLeds imageLiteral=1
|
//% help=basic/plot-leds weight=80 shim=micro_bit::plotLeds
|
||||||
export function plotLeds(leds: string): void { }
|
void plotLeds(ImageLiteral leds) {
|
||||||
|
MicroBitImage i(getbytes(leds));
|
||||||
|
uBit.display.print(i, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forever_stub(void *a) {
|
||||||
|
while (true) {
|
||||||
|
action::run((Action)a);
|
||||||
|
uBit.sleep(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repeats the code forever in the background. On each iteration, allows other codes to run.
|
* Repeats the code forever in the background. On each iteration, allows other codes to run.
|
||||||
* @param body TODO
|
* @param body TODO
|
||||||
*/
|
*/
|
||||||
//% help=basic/forever weight=55 blockGap=8
|
//% help=basic/forever weight=55 blockGap=8
|
||||||
//% blockId=device_forever block="forever" icon="\uf01e" shim=micro_bit::forever
|
//% blockId=device_forever block="forever" icon="\uf01e"
|
||||||
export function forever(body: () => void): void { }
|
void forever(Action a) {
|
||||||
|
if (a != 0) {
|
||||||
|
incr(a);
|
||||||
|
create_fiber(forever_stub, (void*)a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause for the specified time in milliseconds
|
* Pause for the specified time in milliseconds
|
||||||
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
|
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
|
||||||
*/
|
*/
|
||||||
//% help=basic/pause weight=54
|
//% help=basic/pause weight=54
|
||||||
//% shim=micro_bit::pause async block="pause (ms) %pause"
|
//% async block="pause (ms) %pause"
|
||||||
//% blockId=device_pause icon="\uf110"
|
//% blockId=device_pause icon="\uf110"
|
||||||
export function pause(ms: number): void { }
|
void pause(int ms) {
|
||||||
|
uBit.sleep(ms);
|
||||||
|
}
|
||||||
}
|
}
|
30
libs/microbit/control.cpp
Normal file
30
libs/microbit/control.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "BitVM.h"
|
||||||
|
|
||||||
|
namespace control {
|
||||||
|
void fiberDone(void *a)
|
||||||
|
{
|
||||||
|
decr((Action)a);
|
||||||
|
release_fiber();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules code that run in the background.
|
||||||
|
*/
|
||||||
|
//% 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the BBC micro:bit.
|
||||||
|
*/
|
||||||
|
//% weight=30 async help=control/reset
|
||||||
|
//% blockId="control_reset" block="reset"
|
||||||
|
void reset() {
|
||||||
|
uBit.reset();
|
||||||
|
}
|
||||||
|
}
|
@ -192,26 +192,28 @@ enum EventBusValue {
|
|||||||
|
|
||||||
//% weight=1 color="#333333"
|
//% weight=1 color="#333333"
|
||||||
namespace control {
|
namespace control {
|
||||||
/**
|
|
||||||
* Schedules code that run in the background.
|
|
||||||
*/
|
|
||||||
//% help=control/in-background shim=micro_bit::runInBackground
|
|
||||||
//% blockId="control_in_background" block="run in background" blockGap=8
|
|
||||||
export function inBackground(body: Action): void { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the BBC micro:bit.
|
* Returns the value of a C++ runtime constant
|
||||||
*/
|
*/
|
||||||
//% weight=30 shim=uBit.reset async help=control/reset
|
//% weight=19 weight=19 blockId="control_event_source" block="%id"
|
||||||
//% blockId="control_reset" block="reset"
|
export function eventSource(id: EventBusSource) : number {
|
||||||
export function reset(): void { }
|
return id;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the value of a C++ runtime constant
|
||||||
|
*/
|
||||||
|
//% weight=19 weight=19 blockId="control_event_value" block="%id"
|
||||||
|
export function eventValue(id: EventBusValue) : number {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raises an event in the event bus.
|
* Raises an event in the event bus.
|
||||||
@param src ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.
|
* @param src ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.
|
||||||
@param value Component specific code indicating the cause of the event.
|
* @param value Component specific code indicating the cause of the event.
|
||||||
@param mode optional definition of how the event should be processed after construction (default is CREATE_AND_QUEUE).
|
* @param mode optional definition of how the event should be processed after construction (default is CREATE_AND_QUEUE).
|
||||||
*/
|
*/
|
||||||
// shim=micro_bit::busRaiseEvent
|
// shim=micro_bit::busRaiseEvent
|
||||||
//% 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
|
//% 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
|
||||||
export function raiseEvent(src: number, value: number, mode: EventCreationMode = EventCreationMode.CreateAndQueue): void { }
|
export function raiseEvent(src: number, value: number, mode: EventCreationMode = EventCreationMode.CreateAndQueue): void { }
|
||||||
@ -223,19 +225,4 @@ namespace control {
|
|||||||
//% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src=control_event_source|with value %value=control_event_value"
|
//% 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
|
//% blockExternalInputs=1 blockStatement=1
|
||||||
export function onEvent(src: number, value: number, handler: Action): void { }
|
export function onEvent(src: number, value: number, handler: Action): void { }
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of a C++ runtime constant
|
|
||||||
*/
|
|
||||||
//% weight=19 shimw=TD_ID weight=19 blockId="control_event_source" block="%id"
|
|
||||||
export function eventSource(id: EventBusSource) : number {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns the value of a C++ runtime constant
|
|
||||||
*/
|
|
||||||
//% weight=19 shimw=TD_ID weight=19 blockId="control_event_value" block="%id"
|
|
||||||
export function eventValue(id: EventBusValue) : number {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,10 @@
|
|||||||
"core.d.ts",
|
"core.d.ts",
|
||||||
"mbit.ts",
|
"mbit.ts",
|
||||||
"images.ts",
|
"images.ts",
|
||||||
"basic.ts",
|
"basic.cpp",
|
||||||
"input.ts",
|
"input.ts",
|
||||||
"control.ts",
|
"control.ts",
|
||||||
|
"control.cpp",
|
||||||
"game.ts",
|
"game.ts",
|
||||||
"led.ts",
|
"led.ts",
|
||||||
"music.ts",
|
"music.ts",
|
||||||
|
291
sim/libmbit.ts
291
sim/libmbit.ts
@ -88,78 +88,6 @@ namespace ks.rt.micro_bit {
|
|||||||
throw new Error("PANIC " + code)
|
throw new Error("PANIC " + code)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* basic */
|
|
||||||
export function showDigit(v: number) {
|
|
||||||
if (!quiet)
|
|
||||||
console.log("DIGIT:", v)
|
|
||||||
plotLeds(createImageFromString(v.toString()[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function clearScreen() {
|
|
||||||
board().image.clear();
|
|
||||||
runtime.queueDisplayUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function showLeds(leds: micro_bit.Image, delay: number): void {
|
|
||||||
showAnimation(leds, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 scrollNumber(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 scrollString(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 forever(a: RefAction) {
|
|
||||||
function loop() {
|
|
||||||
runtime.runFiberAsync(a)
|
|
||||||
.then(() => Promise.delay(20))
|
|
||||||
.then(loop)
|
|
||||||
.done()
|
|
||||||
}
|
|
||||||
incr(a)
|
|
||||||
loop()
|
|
||||||
}
|
|
||||||
|
|
||||||
export var pause = thread.pause;
|
|
||||||
|
|
||||||
/* leds */
|
/* leds */
|
||||||
export function plot(x: number, y: number) {
|
export function plot(x: number, y: number) {
|
||||||
board().image.set(x, y, 255);
|
board().image.set(x, y, 255);
|
||||||
@ -198,20 +126,17 @@ namespace ks.rt.micro_bit {
|
|||||||
runtime.queueDisplayUpdate()
|
runtime.queueDisplayUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* control */
|
|
||||||
export var runInBackground = thread.runInBackground;
|
|
||||||
|
|
||||||
/* serial */
|
/* serial */
|
||||||
export function serialSendString(s: string) {
|
export function serialSendString(s: string) {
|
||||||
board().writeSerial(s);
|
board().writeSerial(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serialReadString() : string {
|
export function serialReadString(): string {
|
||||||
return board().readSerial();
|
return board().readSerial();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* input */
|
/* input */
|
||||||
export function onButtonPressed(button : number, handler: RefAction) : void {
|
export function onButtonPressed(button: number, handler: RefAction): void {
|
||||||
let ens = enums();
|
let ens = enums();
|
||||||
let b = board();
|
let b = board();
|
||||||
if (button == ens.MICROBIT_ID_BUTTON_AB && !board().usesButtonAB) {
|
if (button == ens.MICROBIT_ID_BUTTON_AB && !board().usesButtonAB) {
|
||||||
@ -220,7 +145,7 @@ namespace ks.rt.micro_bit {
|
|||||||
}
|
}
|
||||||
b.bus.listen(button, ens.MICROBIT_BUTTON_EVT_CLICK, handler);
|
b.bus.listen(button, ens.MICROBIT_BUTTON_EVT_CLICK, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isButtonPressed(button: number): boolean {
|
export function isButtonPressed(button: number): boolean {
|
||||||
let ens = enums();
|
let ens = enums();
|
||||||
let b = board();
|
let b = board();
|
||||||
@ -233,19 +158,19 @@ namespace ks.rt.micro_bit {
|
|||||||
if (button == ens.MICROBIT_ID_BUTTON_B) return bts[1].pressed;
|
if (button == ens.MICROBIT_ID_BUTTON_B) return bts[1].pressed;
|
||||||
return bts[2].pressed || (bts[0].pressed && bts[1].pressed);
|
return bts[2].pressed || (bts[0].pressed && bts[1].pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onGesture(gesture: number, handler: RefAction) {
|
export function onGesture(gesture: number, handler: RefAction) {
|
||||||
let ens = enums();
|
let ens = enums();
|
||||||
let b = board();
|
let b = board();
|
||||||
b.accelerometer.activate();
|
b.accelerometer.activate();
|
||||||
|
|
||||||
if (gesture == 11 && !b.useShake) { // SAKE
|
if (gesture == 11 && !b.useShake) { // SAKE
|
||||||
b.useShake = true;
|
b.useShake = true;
|
||||||
runtime.queueDisplayUpdate();
|
runtime.queueDisplayUpdate();
|
||||||
}
|
}
|
||||||
b.bus.listen(ens.MICROBIT_ID_GESTURE, gesture, handler);
|
b.bus.listen(ens.MICROBIT_ID_GESTURE, gesture, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onPinPressed(pin: Pin, handler: RefAction) {
|
export function onPinPressed(pin: Pin, handler: RefAction) {
|
||||||
pin.isTouched();
|
pin.isTouched();
|
||||||
onButtonPressed(pin.id, handler);
|
onButtonPressed(pin.id, handler);
|
||||||
@ -283,7 +208,7 @@ namespace ks.rt.micro_bit {
|
|||||||
}
|
}
|
||||||
return b.heading;
|
return b.heading;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function temperature(): number {
|
export function temperature(): number {
|
||||||
var b = board();
|
var b = board();
|
||||||
if (!b.usesTemperature) {
|
if (!b.usesTemperature) {
|
||||||
@ -292,7 +217,7 @@ namespace ks.rt.micro_bit {
|
|||||||
}
|
}
|
||||||
return b.temperature;
|
return b.temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAcceleration(dimension: number): number {
|
export function getAcceleration(dimension: number): number {
|
||||||
let b = board();
|
let b = board();
|
||||||
let acc = b.accelerometer;
|
let acc = b.accelerometer;
|
||||||
@ -304,8 +229,8 @@ namespace ks.rt.micro_bit {
|
|||||||
default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
|
default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAccelerometerRange(range : number) {
|
export function setAccelerometerRange(range: number) {
|
||||||
let b = board();
|
let b = board();
|
||||||
b.accelerometer.setSampleRange(range);
|
b.accelerometer.setSampleRange(range);
|
||||||
}
|
}
|
||||||
@ -327,76 +252,76 @@ namespace ks.rt.micro_bit {
|
|||||||
export function getCurrentTime(): number {
|
export function getCurrentTime(): number {
|
||||||
return runtime.runningTime();
|
return runtime.runningTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pins */
|
/* pins */
|
||||||
export function digitalReadPin(pin : Pin) : number {
|
export function digitalReadPin(pin: Pin): number {
|
||||||
pin.mode = PinMode.Digital | PinMode.Input;
|
pin.mode = PinMode.Digital | PinMode.Input;
|
||||||
return pin.value > 100 ? 1 : 0;
|
return pin.value > 100 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function digitalWritePin(pin : Pin, value: number) {
|
export function digitalWritePin(pin: Pin, value: number) {
|
||||||
pin.mode = PinMode.Digital | PinMode.Output;
|
pin.mode = PinMode.Digital | PinMode.Output;
|
||||||
pin.value = value > 0 ? 1023 : 0;
|
pin.value = value > 0 ? 1023 : 0;
|
||||||
runtime.queueDisplayUpdate();
|
runtime.queueDisplayUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function analogReadPin(pin : Pin) : number {
|
export function analogReadPin(pin: Pin): number {
|
||||||
pin.mode = PinMode.Analog | PinMode.Input;
|
pin.mode = PinMode.Analog | PinMode.Input;
|
||||||
return pin.value || 0;
|
return pin.value || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function analogWritePin(pin : Pin, value: number) {
|
export function analogWritePin(pin: Pin, value: number) {
|
||||||
pin.mode = PinMode.Analog | PinMode.Output;
|
pin.mode = PinMode.Analog | PinMode.Output;
|
||||||
pin.value = value ? 1 : 0;
|
pin.value = value ? 1 : 0;
|
||||||
runtime.queueDisplayUpdate();
|
runtime.queueDisplayUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAnalogPeriodUs(pin: Pin, micros:number) {
|
export function setAnalogPeriodUs(pin: Pin, micros: number) {
|
||||||
pin.mode = PinMode.Analog | PinMode.Output;
|
pin.mode = PinMode.Analog | PinMode.Output;
|
||||||
pin.period = micros;
|
pin.period = micros;
|
||||||
runtime.queueDisplayUpdate();
|
runtime.queueDisplayUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function servoWritePin(pin: Pin, value: number) {
|
export function servoWritePin(pin: Pin, value: number) {
|
||||||
setAnalogPeriodUs(pin, 20000);
|
setAnalogPeriodUs(pin, 20000);
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
export function servoSetPulse(pin: Pin, micros:number) {
|
export function servoSetPulse(pin: Pin, micros: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module AudioContextManager {
|
module AudioContextManager {
|
||||||
var _context : any; // AudioContext
|
var _context: any; // AudioContext
|
||||||
var _vco : any; //OscillatorNode;
|
var _vco: any; //OscillatorNode;
|
||||||
var _vca: any; // GainNode;
|
var _vca: any; // GainNode;
|
||||||
|
|
||||||
function context() : any {
|
function context(): any {
|
||||||
if (!_context) _context = freshContext();
|
if (!_context) _context = freshContext();
|
||||||
return _context;
|
return _context;
|
||||||
}
|
}
|
||||||
|
|
||||||
function freshContext() : any {
|
function freshContext(): any {
|
||||||
(<any>window).AudioContext = (<any>window).AudioContext || (<any>window).webkitAudioContext;
|
(<any>window).AudioContext = (<any>window).AudioContext || (<any>window).webkitAudioContext;
|
||||||
if ((<any>window).AudioContext) {
|
if ((<any>window).AudioContext) {
|
||||||
try {
|
try {
|
||||||
// this call my crash.
|
// this call my crash.
|
||||||
// SyntaxError: audio resources unavailable for AudioContext construction
|
// SyntaxError: audio resources unavailable for AudioContext construction
|
||||||
return new (<any>window).AudioContext();
|
return new (<any>window).AudioContext();
|
||||||
} catch(e) {}
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stop() {
|
export function stop() {
|
||||||
if (_vca) _vca.gain.value = 0;
|
if (_vca) _vca.gain.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tone(frequency: number, gain: number) {
|
export function tone(frequency: number, gain: number) {
|
||||||
if (frequency <= 0) return;
|
if (frequency <= 0) return;
|
||||||
var ctx = context();
|
var ctx = context();
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
|
|
||||||
gain = Math.max(0, Math.min(1, gain));
|
gain = Math.max(0, Math.min(1, gain));
|
||||||
if (!_vco) {
|
if (!_vco) {
|
||||||
try {
|
try {
|
||||||
_vco = ctx.createOscillator();
|
_vco = ctx.createOscillator();
|
||||||
@ -405,89 +330,165 @@ namespace ks.rt.micro_bit {
|
|||||||
_vca.connect(ctx.destination);
|
_vca.connect(ctx.destination);
|
||||||
_vca.gain.value = gain;
|
_vca.gain.value = gain;
|
||||||
_vco.start(0);
|
_vco.start(0);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
_vco = undefined;
|
_vco = undefined;
|
||||||
_vca = undefined;
|
_vca = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_vco.frequency.value = frequency;
|
_vco.frequency.value = frequency;
|
||||||
_vca.gain.value = gain;
|
_vca.gain.value = gain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function enablePitch(pin: Pin) {
|
export function enablePitch(pin: Pin) {
|
||||||
board().pins.filter(p => !!p).forEach(p => p.pitch = false);
|
board().pins.filter(p => !!p).forEach(p => p.pitch = false);
|
||||||
pin.pitch = true;
|
pin.pitch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pitch(frequency: number, ms: number) {
|
export function pitch(frequency: number, ms: number) {
|
||||||
// update analog output
|
// update analog output
|
||||||
let pin = board().pins.filter(pin => !!pin && pin.pitch)[0] || board().pins[0];
|
let pin = board().pins.filter(pin => !!pin && pin.pitch)[0] || board().pins[0];
|
||||||
pin.mode = PinMode.Analog | PinMode.Output;
|
pin.mode = PinMode.Analog | PinMode.Output;
|
||||||
if (frequency <= 0) {
|
if (frequency <= 0) {
|
||||||
pin.value = 0;
|
pin.value = 0;
|
||||||
pin.period = 0;
|
pin.period = 0;
|
||||||
} else {
|
} else {
|
||||||
pin.value = 512;
|
pin.value = 512;
|
||||||
pin.period = 1000000/frequency;
|
pin.period = 1000000 / frequency;
|
||||||
}
|
}
|
||||||
runtime.queueDisplayUpdate();
|
runtime.queueDisplayUpdate();
|
||||||
|
|
||||||
let cb = getResume();
|
let cb = getResume();
|
||||||
AudioContextManager.tone(frequency, 1);
|
AudioContextManager.tone(frequency, 1);
|
||||||
if (ms <= 0) cb();
|
if (ms <= 0) cb();
|
||||||
else {
|
else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
AudioContextManager.stop();
|
AudioContextManager.stop();
|
||||||
pin.value = 0;
|
pin.value = 0;
|
||||||
pin.period = 0;
|
pin.period = 0;
|
||||||
pin.mode = PinMode.Unused;
|
pin.mode = PinMode.Unused;
|
||||||
runtime.queueDisplayUpdate();
|
runtime.queueDisplayUpdate();
|
||||||
cb()
|
cb()
|
||||||
}, ms);
|
}, ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* radio */
|
/* radio */
|
||||||
export function broadcastMessage(msg: number) : void {
|
export function broadcastMessage(msg: number): void {
|
||||||
board().radio.broadcast(msg);
|
board().radio.broadcast(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onBroadcastMessageReceived(msg: number, handler: RefAction) : void {
|
export function onBroadcastMessageReceived(msg: number, handler: RefAction): void {
|
||||||
let ens = enums()
|
let ens = enums()
|
||||||
board().bus.listen(ens.MES_BROADCAST_GENERAL_ID, msg, handler);
|
board().bus.listen(ens.MES_BROADCAST_GENERAL_ID, msg, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setGroup(id : number) : void {
|
export function setGroup(id: number): void {
|
||||||
board().radio.setGroup(id);
|
board().radio.setGroup(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setTransmitPower(power: number) : void {
|
export function setTransmitPower(power: number): void {
|
||||||
board().radio.setTransmitPower(power);
|
board().radio.setTransmitPower(power);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function datagramSendNumbers(value0 : number, value1: number, value2: number, value3: number) : void {
|
export function datagramSendNumbers(value0: number, value1: number, value2: number, value3: number): void {
|
||||||
board().radio.datagram.send([value0, value1, value2, value3]);
|
board().radio.datagram.send([value0, value1, value2, value3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function datagramReceiveNumber() : number {
|
export function datagramReceiveNumber(): number {
|
||||||
return board().radio.datagram.recv().data[0];
|
return board().radio.datagram.recv().data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function datagramGetNumber(index : number) : number {
|
export function datagramGetNumber(index: number): number {
|
||||||
return board().radio.datagram.lastReceived.data[index] || 0;
|
return board().radio.datagram.lastReceived.data[index] || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function datagramGetRSSI() : number {
|
export function datagramGetRSSI(): number {
|
||||||
return board().radio.datagram.lastReceived.rssi;
|
return board().radio.datagram.lastReceived.rssi;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onDatagramReceived(handler: RefAction) : void {
|
export function onDatagramReceived(handler: RefAction): void {
|
||||||
let ens = enums();
|
let ens = enums();
|
||||||
board().bus.listen(ens.MICROBIT_ID_RADIO, ens.MICROBIT_RADIO_EVT_DATAGRAM, handler);
|
board().bus.listen(ens.MICROBIT_ID_RADIO, ens.MICROBIT_RADIO_EVT_DATAGRAM, handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ks.rt.basic {
|
||||||
|
var board = micro_bit.board;
|
||||||
|
|
||||||
|
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();
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user