Merge branch 'cpp'

This commit is contained in:
Michal Moskal 2016-03-30 16:27:32 -07:00
commit 5922135073
8 changed files with 263 additions and 198 deletions

View File

@ -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();

View File

@ -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);
} }
} }

View File

@ -6,6 +6,6 @@
], ],
"public": true, "public": true,
"dependencies": { "dependencies": {
"core": "file:../microbit" "microbit": "file:../microbit"
} }
} }

View File

@ -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
View 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();
}
}

View File

@ -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;
}
} }

View File

@ -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",

View File

@ -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) {
@ -305,7 +230,7 @@ namespace ks.rt.micro_bit {
} }
} }
export function setAccelerometerRange(range : number) { export function setAccelerometerRange(range: number) {
let b = board(); let b = board();
b.accelerometer.setSampleRange(range); b.accelerometer.setSampleRange(range);
} }
@ -329,29 +254,29 @@ namespace ks.rt.micro_bit {
} }
/* 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();
@ -362,28 +287,28 @@ namespace ks.rt.micro_bit {
// 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;
} }
@ -405,7 +330,7 @@ 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;
@ -431,7 +356,7 @@ namespace ks.rt.micro_bit {
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();
@ -452,42 +377,118 @@ namespace ks.rt.micro_bit {
/* 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")
}
}