diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..af5e14eb
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,22 @@
+# enforce unix style line endings
+*.ts text eol=lf
+*.tsx text eol=lf
+*.md text eol=lf
+*.txt text eol=lf
+*.js text eol=lf
+*.json text eol=lf
+*.xml text eol=lf
+*.svg text eol=lf
+*.yaml text eol=lf
+*.css text eol=lf
+*.html text eol=lf
+*.py text eol=lf
+*.exp text eol=lf
+
+# do not enforce text for everything - it causes issues with random binary files
+
+*.sln text eol=crlf
+
+*.png binary
+*.jpg binary
+*.jpeg binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..07bbeed6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+node_modules
+*.sw?
+built
+typings/
+tmp/
+*.ts.new
+temp/
diff --git a/kindtarget.json b/kindtarget.json
new file mode 100644
index 00000000..853a1687
--- /dev/null
+++ b/kindtarget.json
@@ -0,0 +1,72 @@
+{
+ "id": "microbit",
+ "name": "microbit",
+ "cloud": true,
+ "bundleddirs": [
+ "libs/microbit",
+ "libs/microbit-led",
+ "libs/microbit-music",
+ "libs/microbit-radio",
+ "libs/microbit-game",
+ "libs/microbit-pins",
+ "libs/microbit-serial"
+ ],
+
+ "blocksprj": {
+ "id": "blocksprj",
+ "config": {
+ "name": "{0} block",
+ "dependencies": {
+ "microbit": "*",
+ "microbit-led": "*",
+ "microbit-music": "*",
+ "microbit-radio": "*",
+ "microbit-game": "*",
+ "microbit-pins": "*",
+ "microbit-serial": "*"
+ },
+ "description": "",
+ "files": [
+ "main.blocks",
+ "main.blocks.ts",
+ "README.md"
+ ]
+ },
+ "files": {
+ "main.blocks": "\n\n",
+ "main.blocks.ts": "\n",
+ "README.md": "Describe your project here!"
+ }
+ },
+
+ "tsprj": {
+ "id": "tsprj",
+ "config": {
+ "name": "{0} bit",
+ "dependencies": {
+ "microbit": "*",
+ "microbit-led": "*",
+ "microbit-music": "*",
+ "microbit-radio": "*",
+ "microbit-game": "*",
+ "microbit-pins": "*",
+ "microbit-serial": "*"
+ },
+ "description": "",
+ "files": [
+ "main.ts",
+ "README.md"
+ ]
+ },
+ "files": {
+ "main.ts": "basic.showString('Hi!')\n",
+ "README.md": "Describe your project here!"
+ }
+ },
+ "koduvscode": true,
+
+ "compile": {
+ "isNative": false,
+ "hasHex": true
+ }
+}
diff --git a/libs/cpp-test/hello.ts b/libs/cpp-test/hello.ts
new file mode 100644
index 00000000..6f4776d1
--- /dev/null
+++ b/libs/cpp-test/hello.ts
@@ -0,0 +1,13 @@
+//% shim=foo::bar
+function test() {
+}
+
+basic.plotLeds(`
+# # . # #
+. . # . .
+. . # . .
+# . . . #
+. # # # .
+`);
+basic.pause(300);
+test();
diff --git a/libs/cpp-test/support.cpp b/libs/cpp-test/support.cpp
new file mode 100644
index 00000000..1474159a
--- /dev/null
+++ b/libs/cpp-test/support.cpp
@@ -0,0 +1,6 @@
+namespace foo {
+ GLUE void bar()
+ {
+ micro_bit::scrollNumber(108108, 50);
+ }
+}
diff --git a/libs/cpp-test/yelm.json b/libs/cpp-test/yelm.json
new file mode 100644
index 00000000..3c660dab
--- /dev/null
+++ b/libs/cpp-test/yelm.json
@@ -0,0 +1,17 @@
+{
+ "name": "cpp-test",
+ "description": "Testing C++",
+ "files": [
+ "support.cpp",
+ "hello.ts"
+ ],
+ "public": true,
+ "microbit": {
+ "config": {
+ "MICROBIT_BLE_ENABLED": "0"
+ }
+ },
+ "dependencies": {
+ "core": "file:../microbit"
+ }
+}
diff --git a/libs/hello/hello.ts b/libs/hello/hello.ts
new file mode 100644
index 00000000..a1c168a9
--- /dev/null
+++ b/libs/hello/hello.ts
@@ -0,0 +1,7 @@
+basic.plotLeds(`
+# # . # #
+. . # . .
+. . # . .
+# . . . #
+. # # # .
+`);
diff --git a/libs/hello/yelm.json b/libs/hello/yelm.json
new file mode 100644
index 00000000..d7f7e7c1
--- /dev/null
+++ b/libs/hello/yelm.json
@@ -0,0 +1,11 @@
+{
+ "name": "hello",
+ "description": "Hello world",
+ "files": [
+ "hello.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "core": "file:../microbit"
+ }
+}
diff --git a/libs/microbit-devices/README.md b/libs/microbit-devices/README.md
new file mode 100644
index 00000000..8bba447d
--- /dev/null
+++ b/libs/microbit-devices/README.md
@@ -0,0 +1 @@
+# devices
diff --git a/libs/microbit-devices/devices.ts b/libs/microbit-devices/devices.ts
new file mode 100644
index 00000000..665a7ed3
--- /dev/null
+++ b/libs/microbit-devices/devices.ts
@@ -0,0 +1,181 @@
+enum MesCameraEvent {
+ //% enumval=MES_CAMERA_EVT_TAKE_PHOTO blockId="take photo"
+ TakePhoto,
+ //% enumval=MES_CAMERA_EVT_START_VIDEO_CAPTURE blockId="start video capture"
+ StartVideoCapture,
+ //% enumval=MES_CAMERA_EVT_STOP_VIDEO_CAPTURE blockId="stop video capture"
+ StopVideoCapture,
+ //% enumval=MES_CAMERA_EVT_TOGGLE_FRONT_REAR blockId="toggle front-rear"
+ ToggleFrontRear,
+ //% enumval=MES_CAMERA_EVT_LAUNCH_PHOTO_MODE blockId="launch photo mode"
+ LaunchPhotoMode,
+ //% enumval=MES_CAMERA_EVT_LAUNCH_VIDEO_MODE blockId="launch video mode"
+ LaunchVideoMode,
+ //% enumval=MES_CAMERA_EVT_STOP_PHOTO_MODE blockId="stop photo mode"
+ StopPhotoMode,
+ //% enumval=MES_CAMERA_EVT_STOP_VIDEO_MODE blockId="stop video mode"
+ StopVideoMode,
+}
+
+enum MesAlertEvent {
+ //% enumval=MES_ALERT_EVT_DISPLAY_TOAST blockId="display toast"
+ DisplayToast,
+ //% enumval=MES_ALERT_EVT_VIBRATE blockId="vibrate"
+ Vibrate,
+ //% enumval=MES_ALERT_EVT_PLAY_SOUND blockId="play sound"
+ PlaySound,
+ //% enumval=MES_ALERT_EVT_PLAY_RINGTONE blockId="play ring tone"
+ PlayRingtone,
+ //% enumval=MES_ALERT_EVT_FIND_MY_PHONE blockId="find my phone"
+ FindMyPhone,
+ //% enumval=MES_ALERT_EVT_ALARM1 blockId="ring alarm"
+ RingAlarm,
+ //% enumval=MES_ALERT_EVT_ALARM2 blockId="ring alarm 2"
+ RingAlarm2,
+ //% enumval=MES_ALERT_EVT_ALARM3 blockId="ring alarm 3"
+ RingAlarm3,
+ //% enumval=MES_ALERT_EVT_ALARM4 blockId="ring alarm 4"
+ RingAlarm4,
+ //% enumval=MES_ALERT_EVT_ALARM5 blockId="ring alarm 5"
+ RingAlarm5,
+ //% enumval=MES_ALERT_EVT_ALARM6 blockId="ring alarm 6"
+ RingAlarm6,
+}
+
+enum MesDeviceInfo {
+ //% enumval=MES_DEVICE_INCOMING_CALL blockId="incoming call"
+ IncomingCall,
+ //% enumval=MES_DEVICE_INCOMING_MESSAGE blockId="incoming message"
+ IncomingMessage,
+ //% enumval=MES_DEVICE_ORIENTATION_LANDSCAPE blockId="orientation landscape"
+ OrientationLandscape,
+ //% enumval=MES_DEVICE_ORIENTATION_PORTRAIT blockId="orientation portrait"
+ OrientationPortrait,
+ //% enumval=MES_DEVICE_GESTURE_DEVICE_SHAKEN blockId="shaken"
+ Shaken,
+ //% enumval=MES_DEVICE_DISPLAY_OFF blockId="display off"
+ DisplayOff,
+ //% enumval=MES_DEVICE_DISPLAY_ON blockId="display on"
+ DisplayOn,
+}
+
+enum MesRemoteControlEvent {
+ //% enumval=MES_REMOTE_CONTROL_EVT_PLAY blockId="play"
+ play,
+ //% enumval=MES_REMOTE_CONTROL_EVT_PAUSE blockId="pause"
+ pause,
+ //% enumval=MES_REMOTE_CONTROL_EVT_STOP blockId="stop"
+ stop,
+ //% enumval=MES_REMOTE_CONTROL_EVT_NEXTTRACK blockId="next track"
+ nextTrack,
+ //% enumval=MES_REMOTE_CONTROL_EVT_PREVTRACK blockId="previous track"
+ previousTrack,
+ //% enumval=MES_REMOTE_CONTROL_EVT_FORWARD blockId="forward"
+ forward,
+ //% enumval=MES_REMOTE_CONTROL_EVT_REWIND blockId="rewind"
+ rewind,
+ //% enumval=MES_REMOTE_CONTROL_EVT_VOLUMEUP blockId="volume up"
+ volumeUp,
+ //% enumval=MES_REMOTE_CONTROL_EVT_VOLUMEDOWN blockId="volume down"
+ volumeDown,
+}
+
+enum MesDpadButtonInfo {
+ //% enumval=MES_DPAD_BUTTON_A_DOWN blockId="A down"
+ ADown,
+ //% enumval=MES_DPAD_BUTTON_A_UP blockId="A up"
+ AUp,
+ //% enumval=MES_DPAD_BUTTON_B_DOWN blockId="B down"
+ BDown,
+ //% enumval=MES_DPAD_BUTTON_B_UP blockId="B up"
+ BUp,
+ //% enumval=MES_DPAD_BUTTON_C_DOWN blockId="C down"
+ CDown,
+ //% enumval=MES_DPAD_BUTTON_C_UP blockId="C up"
+ CUp,
+ //% enumval=MES_DPAD_BUTTON_D_DOWN blockId="D down"
+ DDown,
+ //% enumval=MES_DPAD_BUTTON_D_UP blockId="D up"
+ DUp,
+ //% enumval=MES_DPAD_BUTTON_1_UP blockId="1 down"
+ _1Down,
+ //% enumval=MES_DPAD_BUTTON_1_DOWN blockId="1 up"
+ _1Up,
+ //% enumval=MES_DPAD_BUTTON_2_DOWN blockId="2 down"
+ _2Down,
+ //% enumval=MES_DPAD_BUTTON_2_UP blockId="2 up"
+ _2Up,
+ //% enumval=MES_DPAD_BUTTON_3_DOWN blockId="3 down"
+ _3Down,
+ //% enumval=MES_DPAD_BUTTON_3_UP blockId="3 up"
+ _3Up,
+ //% enumval=MES_DPAD_BUTTON_4_DOWN blockId="4 down"
+ _4Down,
+ //% enumval=MES_DPAD_BUTTON_4_UP blockId="4 up"
+ _4Up,
+}
+
+//% color=156 weight=80
+namespace devices {
+ /**
+ * Sends a ``camera`` command to the parent device.
+ * @param event TODO
+ */
+ //% weight=30 help=functions/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=functions/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=functions/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=functions/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=functions/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=functions/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=functions/on-signal-strength-changed
+ //% blockId=devices_signal_strength_changed_event block="on signal strength changed" icon="\uf012"
+ export function onSignalStrengthChanged(body: Action): void { }
+}
+
diff --git a/libs/microbit-devices/yelm.json b/libs/microbit-devices/yelm.json
new file mode 100644
index 00000000..fc9dfa5e
--- /dev/null
+++ b/libs/microbit-devices/yelm.json
@@ -0,0 +1,13 @@
+{
+ "name": "microbit-devices",
+ "description": "The BLE specific services",
+ "files": [
+ "README.md",
+ "devices.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit"
+ },
+ "installedVersion": "zakvul"
+}
diff --git a/libs/microbit-game/README.md b/libs/microbit-game/README.md
new file mode 100644
index 00000000..0ed2bde3
--- /dev/null
+++ b/libs/microbit-game/README.md
@@ -0,0 +1,4 @@
+# game
+
+The game library.
+
diff --git a/libs/microbit-game/game.ts b/libs/microbit-game/game.ts
new file mode 100644
index 00000000..c00345fd
--- /dev/null
+++ b/libs/microbit-game/game.ts
@@ -0,0 +1,723 @@
+enum Direction {
+ //% blockId=right
+ Right,
+ //% blockId=left
+ Left
+}
+
+enum LedSpriteProperty {
+ //% blockId=x
+ X,
+ //% blockId=y
+ Y,
+ //% blockId=direction
+ Direction,
+ //% blockId=brightness
+ Brightness,
+ //% blockId=blink
+ Blink
+}
+
+//% color=176 weight=32
+namespace game {
+ var _score: number = 0;
+ var _life: number = 3;
+ var _startTime: number = 0;
+ var _endTime: number = 0;
+ var _isGameOver: boolean = false;
+ var _countdownPause: number = 0;
+ var _level: number = 1;
+ var _gameId: number = 0;
+ var img: images.Image;
+ var sprites: LedSprite[];
+
+ /**
+ * Creates a new LED sprite pointing to the right.
+ * @param x sprite horizontal coordinate, eg: 2
+ * @param y sprite vertical coordinate, eg: 2
+ */
+ //% weight=60
+ //% blockId=game_create_sprite block="create sprite at|x: %x|y: %y"
+ export function createSprite(x: number, y: number): LedSprite {
+ init();
+ let p = new LedSprite(x, y);
+ sprites.push(p);
+ plot();
+ return p;
+ }
+
+ /**
+ * Gets the current score
+ */
+ //% weight=9 help=td/game-library
+ //% blockId=game_score block="score" blockGap=8
+ export function score(): number {
+ return _score;
+ }
+
+ /**
+ * Adds points to the current score
+ * @param points amount of points to change, eg: 1
+ */
+ //% weight=10 help=td/game-library
+ //% blockId=game_add_score block="change score by|%points" blockGap=8
+ export function addScore(points: number): void {
+ setScore(_score + points);
+ control.inBackground(() => {
+ led.stopAnimation();
+ basic.showAnimation(`0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0
+0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0
+0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0`, 20);
+ });
+ }
+
+ /**
+ * Starts a game countdown timer
+ * @param ms countdown duration in milliseconds, eg: 10000
+ */
+ //% weight=9 help=td/game-library
+ //% blockId=game_start_countdown block="start countdown|(ms) %duration" blockGap=8
+ export function startCountdown(ms: number): void {
+ if (checkStart()) {
+ basic.showAnimation(`1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
+0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
+1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
+0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
+1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0`, 400);
+ _countdownPause = Math.max(500, ms);
+ _startTime = -1;
+ _endTime = input.runningTime() + _countdownPause;
+ control.inBackground(() => {
+ basic.pause(_countdownPause);
+ gameOver();
+ });
+ }
+ }
+
+ /**
+ * Displays a game over animation.
+ */
+ //% weight=8 help=td/game-library
+ //% blockId=game_game_over block="game over"
+ export function gameOver(): void {
+ if (!_isGameOver) {
+ _isGameOver = true;
+ unplugEvents();
+ led.stopAnimation();
+ led.setBrightness(255);
+ led.setDisplayMode(DisplayMode.BackAndWhite);
+ while (true) {
+ for (let i = 0; i < 8; i++) {
+ basic.clearScreen();
+ basic.pause(100);
+ basic.showLeds(`1 1 1 1 1
+1 1 1 1 1
+1 1 1 1 1
+1 1 1 1 1
+1 1 1 1 1`, 300);
+ }
+ basic.showAnimation(`1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1 1 0 1 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0`, 100);
+ for (let j = 0; j < 3; j++) {
+ basic.showString(" GAMEOVER ", 100);
+ showScore();
+ }
+ }
+ } else {
+ // already in game over mode in another fiber
+ while (true) {
+ basic.pause(10000);
+ }
+ }
+ }
+
+ /**
+ * Sets the current score value
+ * @param value TODO
+ */
+ //% weight=10 help=td/game-library
+ export function setScore(value: number): void {
+ _score = Math.max(0, value);
+ }
+
+ /**
+ * Gets the current life
+ */
+ //% weight=10 help=td/game-library
+ export function life(): number {
+ return _life;
+ }
+
+ /**
+ * Sets the current life value
+ * @param value TODO
+ */
+ //% weight=10 help=td/game-library
+ export function setLife(value: number): void {
+ _life = Math.max(0, value);
+ if (_life <= 0) {
+ gameOver();
+ }
+ }
+
+ /**
+ * Adds life points to the current life
+ * @param lives TODO
+ */
+ //% weight=10 help=td/game-library
+ export function addLife(lives: number): void {
+ setLife(_life + lives);
+ }
+
+ /**
+ * Gets the remaining time (since `start countdown`) or current time (since the device started or `start stopwatch`) in milliseconds.
+ */
+ //% weight=10 help=td/game-library
+ export function currentTime(): number {
+ if (_endTime > 0) {
+ return Math.max(0, _endTime - input.runningTime());
+ } else {
+ return input.runningTime() - _startTime;
+ }
+ }
+
+ /**
+ * Removes some life
+ * @param life TODO
+ */
+ //% weight=10 help=td/game-library
+ export function removeLife(life: number): void {
+ setLife(_life - life);
+ control.inBackground(() => {
+ led.stopAnimation();
+ basic.showAnimation(`1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0
+0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
+0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
+0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
+1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0`, 40);
+ });
+ }
+
+ /**
+ * Increments the level and display a message.
+ */
+ //% weight=10 help=td/game-library
+ export function levelUp(): void {
+ _level = _level + 1;
+ basic.showString("LEVEL:", 150);
+ basic.showNumber(_level, 150);
+ }
+
+ /**
+ * Gets the current level
+ */
+ //% weight=10 help=td/game-library
+ export function level(): number {
+ return _level;
+ }
+
+ /**
+ * Starts a stopwatch timer. `current time` will return the elapsed time.
+ */
+ //% weight=10 help=td/game-library
+ export function startStopwatch(): void {
+ _startTime = input.runningTime();
+ _endTime = -1;
+ }
+
+ /**
+ * Gets a value indicating if the game is still running. Returns `false` if game over.
+ */
+ //% weight=10 help=td/game-library
+ export function isRunning(): boolean {
+ let running: boolean;
+ return !_isGameOver;
+ }
+
+ /**
+ * Displays the score on the screen.
+ */
+ //% help=td/game-library weight=60
+ export function showScore(): void {
+ basic.showString(" SCORE ", 100);
+ basic.showNumber(_score, 150);
+ basic.showString(" ", 150);
+ }
+
+ /**
+ * Indicates if the game is display the game over sequence.
+ */
+ //% help=/functions/game-library
+ export function isGameOver(): boolean {
+ let over: boolean;
+ return _isGameOver;
+ }
+
+ /**
+ * returns false if game can't start
+ */
+ function checkStart(): boolean {
+ if (_countdownPause > 0 || _startTime > 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ function unplugEvents(): void {
+ input.onButtonPressed(Button.A, () => { });
+ input.onButtonPressed(Button.B, () => { });
+ input.onButtonPressed(Button.AB, () => {
+ control.reset();
+ });
+ }
+
+ export class LedSprite {
+ private _x: number;
+ private _y: number;
+ private _dir: number;
+ private _brightness: number;
+ private _blink: number;
+
+ constructor(x: number, y: number) {
+ this._x = math.clamp(0, 4, x);
+ this._y = math.clamp(0, 4, y);
+ this._dir = 90;
+ this._brightness = 255;
+ init();
+ sprites.push(this);
+ plot();
+ }
+
+ /**
+ * Move a certain number of LEDs
+ * @param this the sprite to move
+ * @param leds number of leds to move, eg: 1, -1
+ */
+ //% weight=50
+ //% blockId=game_move_sprite block="%sprite|move by %leds" blockGap=8
+ public move(leds: number): void {
+ if (this._dir == 0) {
+ this._y = this._y - leds;
+ } else if (this._dir == 45) {
+ this._x = this._x + leds;
+ this._y = this._y - leds;
+ } else if (this._dir == 90) {
+ this._x = this._x + leds;
+ } else if (this._dir == 135) {
+ this._x = this._x + leds;
+ this._y = this._y + leds;
+ } else if (this._dir == 180) {
+ this._y = this._y + leds;
+ } else if (this._dir == -45) {
+ this._x = this._x - leds;
+ this._y = this._y - leds;
+ } else if (this._dir == -90) {
+ this._x = this._x - leds;
+ } else {
+ 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);
+ plot();
+ }
+
+ /**
+ * Go to this position on the screen
+ * @param this TODO
+ * @param x TODO
+ * @param y TODO
+ */
+ 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);
+ plot();
+ }
+
+ /**
+ * If touching the edge of the stage, then bounce away.
+ * @param this TODO
+ */
+ //% weight=18
+ //% blockId=game_sprite_bounce block="%sprite|if on edge, bounce"
+ public ifOnEdgeBounce(): void {
+ if (this._dir == 0 && this._y == 0) {
+ this._dir = 180;
+ } else if (this._dir == 45 && (this._x == 4 || this._y == 0)) {
+ if (this._x == 0 && this._y == 0) {
+ this._dir = -135;
+ } else if (this._y == 0) {
+ this._dir = 135;
+ } else {
+ this._dir = -45;
+ }
+ } else if (this._dir == 90 && this._x == 4) {
+ this._dir = -90;
+ } else if (this._dir == 135 && (this._x == 4 || this._y == 4)) {
+ if (this.x() == 4 && this.y() == 4) {
+ this._dir = -45;
+ } else if (this._y == 4) {
+ this._dir = 45;
+ } else {
+ this._dir = -135;
+ }
+ } else if (this._dir == 180 && this._y == 4) {
+ this._dir = 0;
+ } else if (this._dir == -45 && (this._x == 0 || this._y == 0)) {
+ if (this.x() == 0 && this.y() == 0) {
+ this._dir = 135;
+ } else if (this._y == 0) {
+ this._dir = -135;
+ } else {
+ this._dir = 45;
+ }
+ } else if (this._dir == -90 && this._x == 0) {
+ this._dir = 90;
+ } else if (this._dir == -135 && (this._x == 0 || this._y == 4)) {
+ if (this._x == 0 && this._y == 4) {
+ this._dir = 45;
+ } else if (this._y == 4) {
+ this._dir = -45;
+ } else {
+ this._dir = 135;
+ }
+ }
+ plot();
+ }
+
+ /**
+ * Turn the sprite
+ * @param this TODO
+ * @param direction left or right
+ * @param degrees angle in degrees to turn, eg: 45, 90, 180, 135
+ */
+ //% weight=49
+ //% blockId=game_turn_sprite block="%sprite|turn %direction|by (°) %degrees"
+ public turn(direction : Direction, degrees: number) {
+ if (direction == Direction.Right)
+ this.setDirection(this._dir + degrees);
+ else
+ this.setDirection(this._dir - degrees);
+ }
+
+ /**
+ * Turn to the right (clockwise)
+ * @param this TODO
+ * @param degrees TODO
+ */
+ public turnRight(degrees: number): void {
+ this.turn(Direction.Right, degrees);
+ }
+
+ /**
+ * Turn to the left (counter-clockwise)
+ * @param this TODO
+ * @param degrees TODO
+ */
+ public turnLeft(degrees: number): void {
+ this.turn(Direction.Left, degrees);
+ }
+
+ /**
+ * Sets a property of the sprite
+ * @param property the name of the property to change
+ * @param the updated value
+ */
+ //% weight=29
+ //% blockId=game_sprite_set_property block="%sprite|set %property|to %value" blockGap=8
+ public set(property : LedSpriteProperty, value:number) {
+ switch(property) {
+ case LedSpriteProperty.X: this.setX(value); break;
+ case LedSpriteProperty.Y: this.setY(value); break;
+ case LedSpriteProperty.Direction: this.setDirection(value); break;
+ case LedSpriteProperty.Brightness: this.setBrightness(value); break;
+ case LedSpriteProperty.Blink: this.setBlink(value); break;
+ }
+ }
+
+ /**
+ * Changes a property of the sprite
+ * @param property the name of the property to change
+ * @param value amount of change, eg: 1
+ */
+ //% weight=30
+ //% blockId=game_sprite_change_xy block="%sprite|change %property|by %value" blockGap=8
+ public change(property : LedSpriteProperty, value:number) {
+ switch(property) {
+ case LedSpriteProperty.X: this.changeXBy(value); break;
+ case LedSpriteProperty.Y: this.changeYBy(value); break;
+ case LedSpriteProperty.Direction: this.changeDirectionBy(value); break;
+ case LedSpriteProperty.Brightness: this.changeBrightnessBy(value); break;
+ case LedSpriteProperty.Blink: this.changeBlinkBy(value); break;
+ }
+ }
+
+ /**
+ * Gets a property of the sprite
+ * @param property the name of the property to change
+ */
+ //% weight=28
+ //% blockId=game_sprite_property block="%sprite|%property"
+ public get(property : LedSpriteProperty) {
+ switch(property) {
+ case LedSpriteProperty.X: return this.x();
+ case LedSpriteProperty.Y: return this.y();
+ case LedSpriteProperty.Direction: return this.direction()
+ case LedSpriteProperty.Brightness: return this.brightness();
+ case LedSpriteProperty.Blink: return this.blink();
+ default: return 0;
+ }
+ }
+
+ /**
+ * Set the direction of the current sprite, rounded to the nearest multiple of 45
+ * @param this TODO
+ * @param degrees TODO
+ */
+ public setDirection(degrees: number): void {
+ this._dir = ((degrees / 45) % 8) * 45;
+ if (this._dir <= -180) {
+ this._dir = this._dir + 360;
+ } else if (this._dir > 180) {
+ this._dir = this._dir - 360;
+ }
+ plot();
+ }
+
+ /**
+ * Reports the ``x`` position of a sprite on the LED screen
+ * @param this TODO
+ */
+ public x(): number {
+ return this._x;
+ }
+
+ /**
+ * Reports the ``y`` position of a sprite on the LED screen
+ * @param this TODO
+ */
+ public y(): number {
+ return this._y;
+ }
+
+ /**
+ * Reports the current direction of a sprite
+ * @param this TODO
+ */
+ public direction(): number {
+ return this._dir;
+ }
+
+ /**
+ * Set the ``x`` position of a sprite
+ * @param this TODO
+ * @param x TODO
+ */
+ public setX(x: number): void {
+ this.goTo(x, this._y);
+ }
+
+ /**
+ * Set the ``y`` position of a sprite
+ * @param this TODO
+ * @param y TODO
+ */
+ public setY(y: number): void {
+ this.goTo(this._x, y);
+ }
+
+ /**
+ * Changes the ``y`` position by the given amount
+ * @param this TODO
+ * @param y TODO
+ */
+ public changeYBy(y: number): void {
+ this.goTo(this._x, this._y + y);
+ }
+
+ /**
+ * Changes the ``x`` position by the given amount
+ * @param this TODO
+ * @param x TODO
+ */
+ public changeXBy(x: number): void {
+ this.goTo(this._x + x, this._y);
+ }
+
+ /**
+ * Reports true if sprite is touching specified sprite
+ * @param this TODO
+ * @param other TODO
+ */
+ //% weight=20
+ //% blockId=game_sprite_touching_sprite block="%sprite|touching %other|?" blockGap=8
+ public isTouching(other: LedSprite): boolean {
+ return this._x == other._x && this._y == other._y;
+ }
+
+ /**
+ * Reports true if sprite is touching an edge
+ * @param this TODO
+ */
+ //% weight=19
+ //% blockId=game_sprite_touching_edge block="%sprite|touching edge?" blockGap=8
+ public isTouchingEdge(): boolean {
+ return this._x == 0 || this._x == 4 || this._y == 0 || this._y == 4;
+ }
+
+ /**
+ * Turns on the sprite (on by default)
+ * @param this TODO
+ */
+ public on(): void {
+ this.setBrightness(255);
+ }
+
+ /**
+ * Turns off the sprite (on by default)
+ * @param this TODO
+ */
+ public off(): void {
+ this.setBrightness(0);
+ }
+
+ /**
+ * Set the ``brightness`` of a sprite
+ * @param this TODO
+ * @param brightness TODO
+ */
+ public setBrightness(brightness: number): void {
+ this._brightness = math.clamp(0, 255, brightness);
+ plot();
+ }
+
+ /**
+ * Reports the ``brightness` of a sprite on the LED screen
+ * @param this TODO
+ */
+ public brightness(): number {
+ let r: number;
+ return this._brightness;
+ }
+
+ /**
+ * Changes the ``y`` position by the given amount
+ * @param this TODO
+ * @param value TODO
+ */
+ public changeBrightnessBy(value: number): void {
+ this.setBrightness(this._brightness + value);
+ }
+
+ /**
+ * Changes the ``direction`` position by the given amount by turning right
+ * @param this TODO
+ * @param angle TODO
+ */
+ public changeDirectionBy(angle: number): void {
+ this.turnRight(angle);
+ }
+
+ /**
+ * Deletes the sprite from the game engine. All further operation of the sprite will not have any effect.
+ * @param sprite TODO
+ */
+ public delete(sprite: LedSprite): void {
+ sprites.removeElement(sprite);
+ }
+
+ /**
+ * Sets the blink duration interval in millisecond.
+ * @param sprite TODO
+ * @param ms TODO
+ */
+ public setBlink(ms: number): void {
+ this._blink = math.clamp(0, 10000, ms);
+ }
+
+ /**
+ * Changes the ``blink`` duration by the given amount of millisecons
+ * @param this TODO
+ * @param ms TODO
+ */
+ public changeBlinkBy(ms: number): void {
+ this.setBlink(this._blink + ms);
+ }
+
+ /**
+ * Reports the ``blink`` duration of a sprite
+ * @param this TODO
+ */
+ public blink(): number {
+ let r: number;
+ return this._blink;
+ }
+
+ //% weight=-1
+ public _plot(now: number) {
+ let ps = this
+ if (ps._brightness > 0) {
+ let r = 0;
+ if (ps._blink > 0) {
+ r = (now / ps._blink) % 2;
+ }
+ if (r == 0) {
+ img.setPixelBrightness(ps._x, ps._y, img.pixelBrightness(ps._x, ps._y) + ps._brightness);
+ }
+ }
+ }
+ }
+
+ function init(): void {
+ if (img == null) {
+ img = images.createImage(
+`0 0 0 0 0
+0 0 0 0 0
+0 0 0 0 0
+0 0 0 0 0
+0 0 0 0 0`);
+ sprites = ([]);
+ led.setDisplayMode(DisplayMode.Greyscale);
+ basic.forever(() => {
+ basic.pause(30);
+ plot();
+ if (game.isGameOver()) {
+ basic.pause(600);
+ }
+ });
+ }
+ }
+
+ /**
+ * Plots the current sprites on the screen
+ */
+ function plot(): void {
+ if (game.isGameOver()) {
+ return;
+ }
+ let now = input.runningTime();
+ img.clear();
+ for (let i = 0; i < sprites.length; i++) {
+ sprites[i]._plot(now);
+ }
+ img.plotImage(0);
+ }
+
+ /**
+ * Gets an invalid sprite; used to initialize locals.
+ */
+ //% weight=0
+ export function invalidSprite(): LedSprite {
+ return null;
+ }
+
+}
+
diff --git a/libs/microbit-game/yelm.json b/libs/microbit-game/yelm.json
new file mode 100644
index 00000000..09020b09
--- /dev/null
+++ b/libs/microbit-game/yelm.json
@@ -0,0 +1,14 @@
+{
+ "name": "microbit-game",
+ "description": "The game services",
+ "files": [
+ "README.md",
+ "game.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit",
+ "microbit-led": "file:../microbit-led"
+ },
+ "installedVersion": "zxxhqa"
+}
diff --git a/libs/microbit-led/README.md b/libs/microbit-led/README.md
new file mode 100644
index 00000000..535d3d54
--- /dev/null
+++ b/libs/microbit-led/README.md
@@ -0,0 +1,4 @@
+# led
+
+The led library.
+
diff --git a/libs/microbit-led/led.ts b/libs/microbit-led/led.ts
new file mode 100644
index 00000000..c4ecc8a0
--- /dev/null
+++ b/libs/microbit-led/led.ts
@@ -0,0 +1,208 @@
+enum DisplayMode {
+ //% enumval=0 blockId="black and white"
+ BackAndWhite,
+ //% enumval=1 blockId="greyscale"
+ Greyscale,
+}
+
+//% 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=functions/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=functions/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=functions/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=functions/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=functions/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=functions/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.
+ * @param value current value to plot
+ * @param high maximum value, eg: 1023, 255
+ */
+ //% help=/functions/plot-bar-graph weight=20
+ //% 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 = 1023): void {
+
+ writeString("v: ");
+ writeString(value.toString());
+ writeString("\n");
+
+ let v = Math.abs((value * 15) / high);
+ let k = 0;
+ for(let y = 4; y >= 0; --y) {
+ for (let x = 0; x < 3; ++x) {
+ if (k > v) {
+ unplot(2-x,y);
+ unplot(2+x,y);
+ } else {
+ plot(2-x, y);
+ plot(2+x, y);
+ }
+ ++k;
+ }
+ }
+ }
+
+ /**
+ * 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=/functions/set-display-mode
+ export function setDisplayMode(mode: DisplayMode): void { }
+
+ /**
+ * Toggles a particular pixel
+ * @param x TODO
+ * @param y TODO
+ */
+ //% help=functions/toggle
+ export function toggle(x: number, y: number): void {
+ if (led.point(x, y)) {
+ led.unplot(x, y);
+ } else {
+ led.plot(x, y);
+ }
+ }
+
+ /**
+ * Turns all LEDS on
+ */
+ //% help=functions/plot-all
+ export function plotAll(): void {
+ for (let i = 0; i < 5; i++) {
+ for (let j = 0; j < 5; j++) {
+ led.plot(i, j);
+ }
+ }
+ }
+
+ /**
+ * Inverts the current LED display
+ */
+ //% help=functions/toggle-all
+ export function toggleAll(): void {
+ for (let i = 0; i < 5; i++) {
+ for (let j = 0; j < 5; j++) {
+ led.toggle(i, j);
+ }
+ }
+ }
+
+ /**
+ * Fades in the screen display.
+ * @param ms TODO
+ */
+ //% help=functions/fade-in
+ export function fadeIn(ms: number = 700): void {
+ if (ms < 20) {
+ led.setBrightness(255);
+ return;
+ }
+ let dt = 50;
+ let brightness = led.brightness();
+ let start = input.runningTime();
+ let elapsed = 0;
+ while (elapsed < ms) {
+ led.setBrightness(brightness + ((255 - brightness) * elapsed) / ms);
+ basic.pause(dt);
+ elapsed = input.runningTime() - start;
+ }
+ led.setBrightness(255);
+ }
+
+ /**
+ * Fades out the screen brightness.
+ * @param ms TODO
+ */
+ //% help=functions/fade-out
+ export function fadeOut(ms: number = 700): void {
+ if (ms < 20) {
+ led.setBrightness(0);
+ return;
+ }
+ let brightness = led.brightness();
+ let dt = 50;
+ let start = input.runningTime();
+ let elapsed = 0;
+ while (elapsed < ms) {
+ led.setBrightness(brightness - (brightness * elapsed) / ms);
+ basic.pause(dt);
+ elapsed = input.runningTime() - start;
+ }
+ led.setBrightness(0);
+ }
+
+ /**
+ * Takes a screenshot of the LED screen and returns an image.
+ */
+ //% shim=uBit.display.screenShot help=functions/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;
+ }
+
+
+}
diff --git a/libs/microbit-led/yelm.json b/libs/microbit-led/yelm.json
new file mode 100644
index 00000000..5a4630bc
--- /dev/null
+++ b/libs/microbit-led/yelm.json
@@ -0,0 +1,13 @@
+{
+ "name": "microbit-led",
+ "description": "The led services",
+ "files": [
+ "README.md",
+ "led.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit"
+ },
+ "installedVersion": "pjryly"
+}
diff --git a/libs/microbit-music/README.md b/libs/microbit-music/README.md
new file mode 100644
index 00000000..e659935f
--- /dev/null
+++ b/libs/microbit-music/README.md
@@ -0,0 +1,2 @@
+# music
+
diff --git a/libs/microbit-music/music.ts b/libs/microbit-music/music.ts
new file mode 100644
index 00000000..ca737e0d
--- /dev/null
+++ b/libs/microbit-music/music.ts
@@ -0,0 +1,201 @@
+enum Notes {
+ //% enumval=262
+ C,
+ //% enumval=277 blockId=C#
+ CSharp,
+ //% enumval=294
+ D,
+ //% enumval=311
+ Eb,
+ //% enumval=330
+ E,
+ //% enumval=349
+ F,
+ //% enumval=370 blockId=F#
+ FSharp,
+ //% enumval=392
+ G,
+ //% enumval=415 blockId=G#
+ GSharp,
+ //% enumval=440
+ A,
+ //% enumval=466
+ Bb,
+ //% enumval=494
+ B,
+ //% enumval=131
+ C3,
+ //% enumval=139 blockId=C#3
+ CSharp3,
+ //% enumval=147
+ D3,
+ //% enumval=156
+ Eb3,
+ //% enumval=165
+ E3,
+ //% enumval=175
+ F3,
+ //% enumval=185 blockId=F#3
+ FSharp3,
+ //% enumval=196
+ G3,
+ //% enumval=208 blockId=G#3
+ GSharp3,
+ //% enumval=220
+ A3,
+ //% enumval=233
+ Bb3,
+ //% enumval=247
+ B3,
+ //% enumval=262
+ C4,
+ //% enumval=277 blockId=C#4
+ CSharp4,
+ //% enumval=294
+ D4,
+ //% enumval=311
+ Eb4,
+ //% enumval=330
+ E4,
+ //% enumval=349
+ F4,
+ //% enumval=370 blockId=F#3
+ FSharp4,
+ //% enumval=392
+ G4,
+ //% enumval=415 blockId=G#3
+ GSharp4,
+ //% enumval=440
+ A4,
+ //% enumval=466
+ Bb4,
+ //% enumval=494
+ B4,
+ //% enumval=523
+ C5,
+ //% enumval=555 blockId=C#5
+ CSharp5,
+ //% enumval=587
+ D5,
+ //% enumval=622
+ Eb5,
+ //% enumval=659
+ E5,
+ //% enumval=698
+ F5,
+ //% enumval=740 blockId=F#5
+ FSharp5,
+ //% enumval=784
+ G5,
+ //% enumval=831 blockId=G#5
+ GSharp5,
+ //% enumval=880
+ A5,
+ //% enumval=932
+ Bb5,
+ //% enumval=989
+ B5,
+}
+
+enum BeatFraction {
+ //% enumVal=1 blockId=1
+ Whole = 1,
+ //% enumVal=2 blockId="1/2"
+ Half = 2,
+ //% enumVal=4 blockId="1/4"
+ Quater = 4,
+ //% enumVal=8 blockId="1/8"
+ Heighth = 8,
+ //% enumVal=16 blockId="1/16"
+ Sixteenth = 16
+}
+
+//% color=52 weight=33
+namespace music {
+ var beatsPerMinute: number = 120;
+
+ /**
+ * Plays a tone through pin ``P0`` for the given duration.
+ * @param frequency TODO
+ * @param ms TODO
+ */
+ //% help=functions/play-tone weight=90
+ //% blockId=device_play_note block="play|tone (Hz) %note=device_note|for (ms) %duration=device_beat" icon="\uf025" blockGap=8
+ export function playTone(frequency: number, ms: number): void {
+ pins.analogSetPitchPin(AnalogPins.P0);
+ pins.analogPitch(frequency, ms);
+ }
+
+ /**
+ * Plays a tone through pin ``P0``.
+ * @param frequency TODO
+ */
+ //% help=functions/ring-tone weight=80
+ //% blockId=device_ring block="ring tone (Hz)|%note=device_note" icon="\uf025" blockGap=8
+ export function ringTone(frequency: number): void {
+ pins.analogSetPitchPin(AnalogPins.P0);
+ pins.analogPitch(frequency, 0);
+ }
+
+ /**
+ * Rests (plays nothing) for a specified time through pin ``P0``.
+ * @param ms TODO
+ */
+ //% help=functions/rest weight=79
+ //% blockId=device_rest block="rest(ms)|%duration=device_beat"
+ export function rest(ms: number): void {
+ playTone(0, ms);
+ }
+
+
+ /**
+ * Gets the frequency of a note.
+ * @param name TODO
+ */
+ //% shim=TD_ID weight=50 help=functions/note-frequency
+ //% blockId=device_note block="%note"
+ export function noteFrequency(name: Notes): number {
+ return name;
+ }
+
+ /**
+ * Returns the duration of a beat in milli-seconds
+ */
+ //% help=/functions/beat weight=49
+ //% blockId=device_beat block="%fraction|beat"
+ export function beat(fraction : BeatFraction = BeatFraction.Whole): number {
+ let ms: number;
+ return 60000 / fraction / beatsPerMinute;
+ }
+
+ /**
+ * Returns the tempo in beats per minute. Tempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play.
+ */
+ //% help=/functions/tempo weight=40
+ //% blockId=device_tempo block="tempo (bpm)" blockGap=8
+ export function tempo(): number {
+ return beatsPerMinute;
+ }
+
+ /**
+ * Change the tempo by the specified amount
+ * @param bpm The change in beats per minute to the tempo, eg: 20
+ */
+ //% help=/functions/tempo weight=39
+ //% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8
+ export function changeTempoBy(bpm: number): void {
+ setTempo(beatsPerMinute + bpm);
+ }
+
+ /**
+ * Sets the tempo to the specified amount
+ * @param bpm The new tempo in beats per minute, eg: 120
+ */
+ //% help=/functions/tempo weight=38
+ //% blockId=device_set_tempo block="set tempo to (bpm)|%value"
+ export function setTempo(bpm: number): void {
+ if (bpm > 0) {
+ beatsPerMinute = Math.max(1, bpm);
+ }
+ }
+}
diff --git a/libs/microbit-music/yelm.json b/libs/microbit-music/yelm.json
new file mode 100644
index 00000000..b79cb106
--- /dev/null
+++ b/libs/microbit-music/yelm.json
@@ -0,0 +1,13 @@
+{
+ "name": "microbit-music",
+ "description": "The music library",
+ "files": [
+ "README.md",
+ "music.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit"
+ },
+ "installedVersion": "vlwlid"
+}
diff --git a/libs/microbit-pins/README.md b/libs/microbit-pins/README.md
new file mode 100644
index 00000000..1ffdf2b7
--- /dev/null
+++ b/libs/microbit-pins/README.md
@@ -0,0 +1,4 @@
+# radio
+
+The radio library.
+
diff --git a/libs/microbit-pins/pins.ts b/libs/microbit-pins/pins.ts
new file mode 100644
index 00000000..13f8dacc
--- /dev/null
+++ b/libs/microbit-pins/pins.ts
@@ -0,0 +1,155 @@
+enum DigitalPins {
+ //% 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 AnalogPins {
+ //% 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=functions/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: DigitalPins): 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=functions/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: DigitalPins, 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=functions/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: AnalogPins): 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=functions/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: AnalogPins, 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=functions/analog-set-period weight=23
+ //% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%micros"
+ export function analogSetPeriod(pin: AnalogPins, 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=functions/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: AnalogPins, 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=functions/serial-set-pulse weight=19
+ //% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %micros"
+ export function servoSetPulse(pin: AnalogPins, 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
+ * @param fromLow the lower bound of the value's current range
+ * @param fromHigh the upper bound of the value's current range, eg: 1023
+ * @param toLow the lower bound of the value's target range
+ * @param toHigh the upper bound of the value's target range, eg: 4
+ */
+ //% help=functions/map weight=15
+ //% blockId=math_map block="map %value|from low %fromLow|from high %fromHigh|to low %toLow|to high %toHigh"
+ 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=functions/analog-set-pitch weight=12
+ export function analogSetPitchPin(name: AnalogPins): 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=functions/analog-pitch weight=14 async
+ export function analogPitch(frequency: number, ms: number): void { }
+}
diff --git a/libs/microbit-pins/yelm.json b/libs/microbit-pins/yelm.json
new file mode 100644
index 00000000..d803ef02
--- /dev/null
+++ b/libs/microbit-pins/yelm.json
@@ -0,0 +1,13 @@
+{
+ "name": "microbit-pins",
+ "description": "The pins services",
+ "files": [
+ "README.md",
+ "pins.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit"
+ },
+ "installedVersion": "bornqs"
+}
diff --git a/libs/microbit-radio/README.md b/libs/microbit-radio/README.md
new file mode 100644
index 00000000..1ffdf2b7
--- /dev/null
+++ b/libs/microbit-radio/README.md
@@ -0,0 +1,4 @@
+# radio
+
+The radio library.
+
diff --git a/libs/microbit-radio/radio.ts b/libs/microbit-radio/radio.ts
new file mode 100644
index 00000000..7c763a53
--- /dev/null
+++ b/libs/microbit-radio/radio.ts
@@ -0,0 +1,85 @@
+//% color=270 weight=34
+namespace radio {
+ /**
+ * Broadcasts a number over radio to any connected micro:bit in the group.
+ */
+ //% help=/functions/send-number
+ //% weight=60
+ //% blockId=radio_datagram_send block="send number %MESSAGE" blockGap=8
+ 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=/functions/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=/functions/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=/functions/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=/functions/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=/functions/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=/functions/set-group
+ //% shim=micro_bit::setGroup
+ //% weight=10
+ //% blockId=radio_set_group block="set group %ID"
+ export function setGroup(id: number) : void {
+ }
+}
diff --git a/libs/microbit-radio/yelm.json b/libs/microbit-radio/yelm.json
new file mode 100644
index 00000000..03b28324
--- /dev/null
+++ b/libs/microbit-radio/yelm.json
@@ -0,0 +1,13 @@
+{
+ "name": "microbit-radio",
+ "description": "The radio services",
+ "files": [
+ "README.md",
+ "radio.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit"
+ },
+ "installedVersion": "phykjp"
+}
diff --git a/libs/microbit-serial/README.md b/libs/microbit-serial/README.md
new file mode 100644
index 00000000..7907b1b9
--- /dev/null
+++ b/libs/microbit-serial/README.md
@@ -0,0 +1,4 @@
+# serial
+
+The serial library.
+
diff --git a/libs/microbit-serial/serial.ts b/libs/microbit-serial/serial.ts
new file mode 100644
index 00000000..038457e8
--- /dev/null
+++ b/libs/microbit-serial/serial.ts
@@ -0,0 +1,59 @@
+//% weight=1
+namespace serial {
+ /**
+ * Prints a line of text to the serial
+ * @param value to send over serial
+ */
+ //% blockId=serial_writeline block="serial|write %text"
+ export function writeLine(text: string): void {
+ writeString(text);
+ writeString("\r\n");
+ }
+
+ /**
+ * Prints a numeric value to the serial
+ */
+ export function writeNumber(value: number): void {
+ 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
+ * @param value to write
+ */
+ //% weight=80
+ //% blockId=serial_writevalue block="serial|write %name|= %value"
+ export function writeValue(name: string, value: number): void {
+ writeString(name);
+ writeString(": ");
+ writeNumber(value);
+ writeLine("");
+ }
+}
diff --git a/libs/microbit-serial/yelm.json b/libs/microbit-serial/yelm.json
new file mode 100644
index 00000000..2e020ace
--- /dev/null
+++ b/libs/microbit-serial/yelm.json
@@ -0,0 +1,13 @@
+{
+ "name": "microbit-serial",
+ "description": "The serial services",
+ "files": [
+ "README.md",
+ "serial.ts"
+ ],
+ "public": true,
+ "dependencies": {
+ "microbit": "file:../microbit"
+ },
+ "installedVersion": "vykmvx"
+}
diff --git a/libs/microbit/README.md b/libs/microbit/README.md
new file mode 100644
index 00000000..3abad658
--- /dev/null
+++ b/libs/microbit/README.md
@@ -0,0 +1,4 @@
+# core
+
+The core library.
+
diff --git a/libs/microbit/basic.ts b/libs/microbit/basic.ts
new file mode 100644
index 00000000..f6393955
--- /dev/null
+++ b/libs/microbit/basic.ts
@@ -0,0 +1,83 @@
+/**
+ * Provides access to basic micro:bit functionality.
+ */
+//% color=190 weight=100
+namespace basic {
+
+ /**
+ * Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.
+ * @param interval speed of scroll; eg: 150, 100, 200, -100
+ */
+ //% help=functions/show-number
+ //% weight=96
+ //% shim=micro_bit::scrollNumber
+ //% blockId=device_show_number block="show|number %number" blockGap=8 icon="\uf1ec"
+ //% async
+ export function showNumber(value: number, interval: number = 150): void { }
+
+ /**
+ * Draws an image on the LED screen.
+ * @param leds TODO
+ * @param interval TODO
+ */
+ //% help=functions/show-leds
+ //% weight=95 blockGap=8
+ //% shim=micro_bit::showLeds
+ //% imageLiteral=1 async
+ //% blockId=device_show_leds
+ //% block="show leds" icon="\uf00a"
+ export function showLeds(leds: string, interval: number = 400): void { }
+
+ /**
+ * Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.
+ * @param text the text to scroll on the screen, eg: "Hello!"
+ * @param interval how fast to shift characters; eg: 150, 100, 200, -100
+ */
+ //% help=functions/show-string
+ //% weight=87 blockGap=8
+ //% shim=micro_bit::scrollString async
+ //% block="show|string %text" icon="\uf031"
+ //% async
+ //% blockId=device_print_message
+ export function showString(text: string, interval: number = 150): void { }
+
+ /**
+ * Turn off all LEDs
+ */
+ //% help=functions/clear-screen weight=79
+ //% shim=micro_bit::clearScreen
+ //% blockId=device_clear_display block="clear screen" icon="\uf12d"
+ export function clearScreen(): void { }
+
+ /**
+ * Shows a sequence of LED screens as an animation.
+ * @param leds TODO
+ * @param interval TODO
+ */
+ //% help=functions/show-animation shim=micro_bit::showAnimation imageLiteral=1 async
+ export function showAnimation(leds: string, interval: number = 400): void { }
+
+ /**
+ * Draws an image on the LED screen.
+ * @param leds TODO
+ */
+ //% help=functions/plot-leds weight=80 shim=micro_bit::plotLeds imageLiteral=1
+ export function plotLeds(leds: string): void { }
+
+ /**
+ * Repeats the code forever in the background. On each iteration, allows other codes to run.
+ * @param body TODO
+ */
+ //% help=functions/forever weight=55 blockGap=8
+ //% blockId=device_forever block="forever" icon="\uf01e" shim=micro_bit::forever
+ export function forever(body: () => void): void { }
+
+ /**
+ * Pause for the specified time in milliseconds
+ * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
+ */
+ //% help=functions/pause weight=54
+ //% shim=micro_bit::pause async block="pause (ms) %pause"
+ //% blockId=device_pause icon="\uf110"
+ export function pause(ms: number): void { }
+}
diff --git a/libs/microbit/control.ts b/libs/microbit/control.ts
new file mode 100644
index 00000000..02c04cd9
--- /dev/null
+++ b/libs/microbit/control.ts
@@ -0,0 +1,13 @@
+namespace control {
+ /**
+ * Schedules code that run in the background.
+ //% help=functions/in-background shim=micro_bit::runInBackground
+ */
+ export function inBackground(body: Action): void { }
+
+ /**
+ * Resets the BBC micro:bit.
+ */
+ //% weight=1 shim=uBit.reset async help=functions/reset
+ export function reset() : void { }
+}
diff --git a/libs/microbit/core.d.ts b/libs/microbit/core.d.ts
new file mode 100644
index 00000000..e81b586d
--- /dev/null
+++ b/libs/microbit/core.d.ts
@@ -0,0 +1,236 @@
+///
+
+interface Array {
+ /**
+ * 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
+ length: number;
+
+ /**
+ * Appends new elements to an array.
+ * @param items New elements of the Array.
+ */
+ //% shim=collection::add
+ push(item: T): void;
+
+ /**
+ * Removes the last element from an array and returns it.
+ */
+ //% helper=arrayPop
+ pop(): T;
+
+ /**
+ * Reverses the elements in an Array.
+ */
+ //% helper=arrayReverse
+ reverse(): void;
+
+ /**
+ * Removes the first element from an array and returns it.
+ */
+ //% helper=arrayShift
+ shift(): T;
+
+ /**
+ * Returns a section of an array.
+ * @param start The beginning of the specified portion of the array.
+ * @param end The end of the specified portion of the array.
+ */
+ //% helper=arraySlice
+ slice(start: number, end: number): T[];
+
+ /** Removes the first occurence of an object. Returns true if removed. */
+ //% shim=collection::remove
+ removeElement(element:T) : boolean;
+
+ /** Removes the object at position index. */
+ //% shim=collection::remove_at
+ removeAt(idx:number) : void;
+
+
+ /**
+ * Removes elements from an array.
+ * @param start The zero-based location in the array from which to start removing elements.
+ * @param deleteCount The number of elements to remove.
+ */
+ //% helper=arraySplice
+ splice(start: number, deleteCount: number): void;
+
+ /**
+ * Inserts new elements at the start of an array.
+ * @param items Elements to insert at the start of the Array.
+ */
+ //% helper=arrayUnshift
+ unshift(item:T): void;
+
+ /**
+ * Returns the index of the first occurrence of a value in an array.
+ * @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
+ indexOf(searchElement: T, fromIndex?: number): number;
+
+
+ [n: number]: 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;
+}
+
+
+/**
+ * Converts A string to an integer.
+ * @param s A string to convert into a number.
+ */
+ //% shim=string::to_number
+declare function parseInt(s: string): number;
+
+interface Object {}
+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;
+}
diff --git a/libs/microbit/images.ts b/libs/microbit/images.ts
new file mode 100644
index 00000000..62a01d47
--- /dev/null
+++ b/libs/microbit/images.ts
@@ -0,0 +1,50 @@
+//% color=45 weight=31
+namespace images {
+ /**
+ * Creates an image that fits on the LED screen.
+ */
+ //% weight=75
+ //% 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
+ //% 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=functions/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): 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=functions/show-image weight=79 shim=micro_bit::showImage async
+ //% blockId=device_scroll_image block="scroll image %sprite|with offset %frameoffset|and interval (ms) %delay" blockGap=8
+ public scrollImage(frameOffset: number, interval : number = 200) {
+ }
+
+ public plotImage(xOffset: number): void {}
+
+ public clear(): void {}
+
+ public setPixelBrightness(x: number, y: number, v: number): void {}
+
+ public pixelBrightness(x: number, y: number): number {
+ return 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/microbit/input.ts b/libs/microbit/input.ts
new file mode 100644
index 00000000..b6b6b335
--- /dev/null
+++ b/libs/microbit/input.ts
@@ -0,0 +1,226 @@
+enum Button {
+ //% enumval=MICROBIT_ID_BUTTON_A
+ A,
+ //% enumval=MICROBIT_ID_BUTTON_B
+ B,
+ //% enumval=MICROBIT_ID_BUTTON_AB
+ //% blockId="A+B"
+ AB,
+}
+
+enum Dimension {
+ //% enumval=0 blockId=x
+ X,
+ //% enumval=1 blockId=y
+ Y,
+ //% enumval=2 blockId=z
+ Z,
+ //% enumval=3 blockId=strength
+ Strength,
+}
+
+enum Rotation {
+ //% enumval=0 blockId=pitch
+ Pitch,
+ //% enumval=1 blockId=roll
+ Roll,
+}
+
+enum TouchPins {
+ //% enumval=uBit.io.P0
+ P0,
+ //% enumval=uBit.io.P1
+ P1,
+ //% enumval=uBit.io.P2
+ P2,
+}
+
+enum Gestures {
+ //% blockId=shake enumval=MICROBIT_ACCELEROMETER_EVT_SHAKE
+ Shake,
+ //% blockId="logo up" enumval=MICROBIT_ACCELEROMETER_EVT_TILT_UP
+ LogoUp,
+ //% blockId="logo down" enumval=MICROBIT_ACCELEROMETER_EVT_TILT_DOWN
+ LogoDown,
+ //% blockId="screen up" enumval=MICROBIT_ACCELEROMETER_EVT_FACE_UP
+ ScreenUp,
+ //% blockId="screen down" enumval=MICROBIT_ACCELEROMETER_EVT_FACE_DOWN
+ ScreenDown
+}
+
+//% 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=functions/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=functions/on-gesture shim=micro_bit::on_event weight=84
+ //% blockId=device_gesture_event block="on |%NAME" icon="\uf135"
+ export function onGesture(gesture: Gestures, body: Action): void { }
+
+ /**
+ * Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.
+ * @param name TODO
+ * @param body TODO
+ */
+ //% help=functions/on-pin-pressed weight=83 shim=micro_bit::onPinPressed
+ //% blockId=device_pin_event block="on pin|%NAME|pressed" icon="\uf094"
+ export function onPinPressed(name: TouchPins, body: Action): void { }
+
+ /**
+ * Get the button state (pressed or not) for ``A`` and ``B``.
+ */
+ //% help=functions/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=functions/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=functions/temperature shim=uBit.thermometer.getTemperature
+ //% 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=functions/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=functions/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=/functions/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=functions/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=functions/running-time shim=micro_bit::getCurrentTime weight=50
+ //% blockId=device_get_running_time block="running time (ms)" blockGap=8 icon="\uf017"
+ export function runningTime(): number {
+ return 0;
+ }
+
+ /**
+ * Obsolete, compass calibration is automatic.
+ */
+ //% help=functions/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 TODO
+ */
+ //% help=functions/pin-is-pressed weight=58 shim=micro_bit::isPinTouched block="pin|%NAME|is pressed" icon="\uf094"
+ export function pinIsPressed(name: TouchPins): boolean {
+ return false;
+ }
+
+ /**
+ * Attaches code to run when the screen is facing up.
+ * @param body TODO
+ */
+ //% help=functions/on-screen-up
+ export function onScreenUp(body: Action): void {
+ onGesture(Gestures.ScreenUp, body);
+ }
+
+ /**
+ * Attaches code to run when the screen is facing down.
+ * @param body TODO
+ */
+ //% help=functions/on-screen-down
+ export function onScreenDown(body: Action): void {
+ onGesture(Gestures.ScreenDown, body);
+ }
+
+ /**
+ * Attaches code to run when the device is shaken.
+ * @param body TODO
+ */
+ //% help=functions/on-shake
+ export function onShake(body: Action): void {
+ onGesture(Gestures.Shake, body);
+ }
+
+ /**
+ * Attaches code to run when the logo is oriented upwards and the board is vertical.
+ * @param body TODO
+ */
+ //% help=functions/on-logo-up
+ export function onLogoUp(body: Action): void {
+ onGesture(Gestures.LogoUp, body);
+ }
+
+ /**
+ * Attaches code to run when the logo is oriented downwards and the board is vertical.
+ * @param body TODO
+ */
+ //% help=functions/on-logo-down
+ export function onLogoDown(body: Action): void {
+ onGesture(Gestures.LogoDown, body);
+ }
+}
diff --git a/libs/microbit/mbit.ts b/libs/microbit/mbit.ts
new file mode 100644
index 00000000..52f6b1c9
--- /dev/null
+++ b/libs/microbit/mbit.ts
@@ -0,0 +1,28 @@
+type Action = () => void;
+
+namespace helpers {
+ export function arraySplice(arr: T[], start: number, len: number) {
+ if (start < 0) {
+ return;
+ }
+ for (let i = 0; i < len; ++i) {
+ arr.removeAt(start)
+ }
+ }
+}
+
+namespace console {
+ export function log(msg: string) {
+ writeString(msg);
+ writeString("\r\n");
+ }
+
+ //% shim=micro_bit::serialSendString
+ function writeString(text: string): void { }
+}
+
+namespace math {
+ export function clamp(min: number, max:number, value:number): number {
+ return Math.min(max, Math.max(min, value));
+ }
+}
diff --git a/libs/microbit/yelm.json b/libs/microbit/yelm.json
new file mode 100644
index 00000000..c7e4c9a7
--- /dev/null
+++ b/libs/microbit/yelm.json
@@ -0,0 +1,76 @@
+{
+ "name": "microbit",
+ "description": "The microbit core library",
+ "installedVersion": "xdvxev",
+ "files": [
+ "README.md",
+ "core.d.ts",
+ "mbit.ts",
+ "images.ts",
+ "basic.ts",
+ "input.ts",
+ "control.ts"
+ ],
+ "public": true,
+ "dependencies": {},
+ "target": {
+ "id": "microbit",
+ "name": "microbit",
+ "cloud": true,
+ "blocksprj": {
+ "id": "blocksprj",
+ "config": {
+ "name": "{0} block",
+ "dependencies": {
+ "microbit": "*",
+ "microbit-led": "*",
+ "microbit-music": "*",
+ "microbit-radio": "*",
+ "microbit-game": "*",
+ "microbit-pins": "*",
+ "microbit-serial": "*"
+ },
+ "description": "",
+ "files": [
+ "main.blocks",
+ "main.blocks.ts",
+ "README.md"
+ ]
+ },
+ "files": {
+ "main.blocks": "\n\n",
+ "main.blocks.ts": "\n",
+ "README.md": "Describe your project here!"
+ }
+ },
+ "tsprj": {
+ "id": "tsprj",
+ "config": {
+ "name": "{0} bit",
+ "dependencies": {
+ "microbit": "*",
+ "microbit-led": "*",
+ "microbit-music": "*",
+ "microbit-radio": "*",
+ "microbit-game": "*",
+ "microbit-pins": "*",
+ "microbit-serial": "*"
+ },
+ "description": "",
+ "files": [
+ "main.ts",
+ "README.md"
+ ]
+ },
+ "files": {
+ "main.ts": "basic.showString('Hi!')\n",
+ "README.md": "Describe your project here!"
+ }
+ },
+ "koduvscode": true,
+ "compile": {
+ "isNative": false,
+ "hasHex": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/tsconfig.json b/libs/tsconfig.json
new file mode 100644
index 00000000..4a1a04d5
--- /dev/null
+++ b/libs/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "outDir": "../built",
+ "rootDir": ".",
+ "newLine": "LF",
+ "sourceMap": true
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..b90b5cfe
--- /dev/null
+++ b/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "kindscript-microbit",
+ "version": "0.0.0",
+ "private": true,
+ "description": "microbit target for KindScript",
+ "keywords": [
+ "JavaScript",
+ "education",
+ "microbit"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/Microsoft/kindscript-microbit.git"
+ },
+ "author": "",
+ "license": "MIT",
+ "homepage": "https://github.com/Microsoft/kindscript-microbit#readme",
+ "files": [
+ "README.md"
+ ],
+ "dependencies": {
+ "kindscript": "*"
+ }
+}