Compare commits

...

21 Commits

Author SHA1 Message Date
62e4b04931 0.2.101 2016-05-05 12:50:36 -07:00
17e33cc34f updated white space 2016-05-05 12:50:26 -07:00
d4ad150cba Bump pxt-core to 0.2.114 2016-05-05 12:48:59 -07:00
52bfd4e535 Merge branch 'master' of https://github.com/Microsoft/pxt-microbit 2016-05-05 12:35:26 -07:00
f854dfd9c8 updated generated docs 2016-05-05 12:32:40 -07:00
d905f24f9c updated generated strings.json 2016-05-05 11:32:35 -07:00
81b8b1b69c updated docs 2016-05-05 11:16:14 -07:00
efce4c3698 linting 2016-05-05 08:57:44 -07:00
b5e4a36e9c Add libraries docs 2016-05-05 14:20:18 +01:00
04a60a5b47 fixing various lint violations 2016-05-04 23:31:55 -07:00
29b28e7f0d adding aspect ratio 2016-05-04 22:44:11 -07:00
979381eaef Merge branch 'master' of https://github.com/Microsoft/pxt-microbit 2016-05-04 14:46:46 -07:00
e4370f4e3c 0.2.100 2016-05-04 15:25:52 +01:00
ba707f080d Bump pxt-core to 0.2.112 2016-05-04 15:25:51 +01:00
3816e01f87 Add locale-specific theme 2016-05-04 15:23:04 +01:00
548d215b48 0.2.99 2016-05-04 13:31:59 +01:00
43da58f214 Bump pxt-core to 0.2.111 2016-05-04 13:31:57 +01:00
f90d052538 Add example localized doc 2016-05-04 13:25:56 +01:00
13ff7cd0ec removing readme.md from template 2016-05-03 14:45:10 -07:00
a3b34518b0 0.2.98 2016-05-02 21:24:17 -07:00
5a33dc8a81 updated thank you 2016-05-02 21:24:10 -07:00
25 changed files with 594 additions and 388 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
// Place your settings in this file to overwrite default and user settings.
{
"tslint.enable": true,
"tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib"
}

View File

@ -0,0 +1,22 @@
{
"name": "koduj z micro:bit",
"title": "koduj z micro:bit",
"docMenu": [
{
"name": "O nas",
"path": "/about"
},
{
"name": "Lekcje",
"path": "/lessons"
},
{
"name": "Instrukcja obsługi",
"path": "/reference"
},
{
"name": "Urządzenie",
"path": "/device"
}
]
}

7
docs/_locales/pl/docs.md Normal file
View File

@ -0,0 +1,7 @@
# Dokumentacja
Witamy na stronach dokumentacji!
* Przeglądnij [instrukcje obsługi](/reference)
* Dowiedz się więcej o [urządzeniu](/device)
* Wystartuj z [lekcjami](/lessons)

View File

@ -2,6 +2,7 @@
Welcome to the documentation.
* Browse the [reference](/reference)
* Browse the [API reference](/reference)
* Learn more about the [device](/device)
* Get started with [lessons](/lessons)
* Learn about [libraries](/libraries) (possibly using C++)

14
docs/libraries.md Normal file
View File

@ -0,0 +1,14 @@
# Extensions
You can publish libraries (also known as packages or extensions)
that users can then add to their scripts. These typically
provide a driver for a particular hardware device you can connect
to a microbit.
* [Sample C++ extension](https://github.com/Microsoft/pxt-microbit-cppsample)
* [Sample TypeScript extension](https://github.com/Microsoft/pxt-microbit/tree/master/libs/i2c-fram)
## Finding libraries
## Publishing libraries

View File

@ -0,0 +1,23 @@
# microbit Reference
```namespaces
basic.showNumber(0);
input.onButtonPressed(Button.A, () => {
});
led.plot(0, 0);
music.playTone(0, 0);
game.addScore(1);
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . .
`);
pins.digitalReadPin(DigitalPin.P0);
serial.writeValue(x, 0);
control.inBackground(() => {
});
```

View File

@ -1,17 +1,27 @@
# Reference
```namespaces
basic.showString("Hello!");
input.onButtonPressed(Button.A, () => {});
for (let i = 0;i<5;++i) {}
if (true){}
let x = 0;
Math.random(5);
led.plot(0,0);
radio.sendNumber(0);
music.playTone(music.noteFrequency(Note.C), music.beat(BeatFraction.Whole));
game.createSprite(2,2);
basic.showNumber(0);
input.onButtonPressed(Button.A, () => {
});
led.plot(0, 0);
music.playTone(0, 0);
game.addScore(1);
images.createImage(`
. . . . .
. . . . .
. . # . .
. . . . .
. . . . .
`);
pins.digitalReadPin(DigitalPin.P0);
serial.writeLine("Hello!");
control.inBackground(() => {});
```
serial.writeValue(x, 0);
control.inBackground(() => {
});

View File

@ -2,7 +2,6 @@
Provides access to basic micro:bit functionality.
```cards
basic.showNumber(0);
basic.showLeds(`

View File

@ -1,7 +1,6 @@
# Control
Runtime and event utilities.
```cards
control.inBackground(() => {

View File

@ -1,7 +1,6 @@
# Game
A single-LED sprite game engine
```cards
game.addScore(1);

View File

@ -1,7 +1,6 @@
# Images
Creation, manipulation and display of LED images.
```cards
images.createImage(`

View File

@ -1,7 +1,6 @@
# Input
Events and data from sensors
```cards
input.onButtonPressed(Button.A, () => {

View File

@ -1,7 +1,6 @@
# Led
Control of the LED screen.
```cards
led.plot(0, 0);
@ -10,7 +9,7 @@ led.point(0, 0);
led.brightness();
led.setBrightness(255);
led.stopAnimation();
led.plotBarGraph(0, 1023);
led.plotBarGraph(0, 0);
led.fadeIn();
led.fadeOut();
led.plotAll();

View File

@ -1,14 +1,13 @@
# Music
Generation of music tones through pin ``P0``.
```cards
music.playTone(0, 0);
music.ringTone(0);
music.rest(0);
music.noteFrequency(Note.C);
music.beat();
music.beat(BeatFraction.Whole);
music.tempo();
music.changeTempoBy(20);
music.setTempo(120);

View File

@ -1,7 +1,6 @@
# Pins
Control currents in Pins for analog/digital signals, servos, i2c, ...
```cards
pins.digitalReadPin(DigitalPin.P0);

View File

@ -1,7 +1,6 @@
# Radio
Communicate data using radio packets
```cards
radio.sendNumber(0);

View File

@ -1,8 +1,8 @@
# Serial
[Serial communication](/device/serial) between the BBC micro:bit and another computer.
Reading and writing data over a serial connection.
```cards
serial.writeValue(x, 0);
serial.writeLine("");
serial.writeValue("x", 0);
```

View File

@ -6,5 +6,4 @@ basic.forever(() => { basic.showString("THANK YOU") })
Thank you for participating in this survey.
Please contact Michael Braun at WW PS Edu [v-braum@microsoft.com](mailto:v-braum@microsoft.com)
or Claudine OLeary at WW PS Edu [clolea@microsoft.com](clolea@microsoft.com) with any information you think we might find useful.
Please [contact us](mailto:microbitpilots@microsoft.com) with any information you think we might find useful.

View File

@ -36,7 +36,7 @@ namespace i2c_fram {
pins.i2cWriteBuffer(devaddr, buf)
}
export function readBuffer(addr: number, length: number) {
if (addr < 0 || length < 0 || (addr + length) > memend)
die();
@ -45,8 +45,8 @@ namespace i2c_fram {
buf[i] = readByte(addr + i)
return buf
}
export function writeBuffer(addr:number, buf: Buffer) {
export function writeBuffer(addr: number, buf: Buffer) {
if (addr < 0 || (addr + buf.length) > memend)
die();
for (let i = 0; i < buf.length; ++i)

View File

@ -0,0 +1,79 @@
{
"A single-LED sprite game engine": "A single-LED sprite game engine",
"Adds points to the current score": "Adds points to the current score",
"Attaches code to run when the device is shaken.": "Attaches code to run when the device is shaken.",
"Attaches code to run when the logo is oriented downwards and the board is vertical.": "Attaches code to run when the logo is oriented downwards and the board is vertical.",
"Attaches code to run when the logo is oriented upwards and the board is vertical.": "Attaches code to run when the logo is oriented upwards and the board is vertical.",
"Attaches code to run when the screen is facing down.": "Attaches code to run when the screen is facing down.",
"Attaches code to run when the screen is facing up.": "Attaches code to run when the screen is facing up.",
"Cancels the current animation and clears other pending animations.": "Cancels the current animation and clears other pending animations.",
"Change the tempo by the specified amount": "Change the tempo by the specified amount",
"Configures the Pulse-width modulation (PWM) of the analog output to the given value in **microseconds** or `1/1000` milliseconds.\nIf this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.": "Configures the Pulse-width modulation (PWM) of the analog output to the given value in **microseconds** or `1/1000` milliseconds.\nIf this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.",
"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.": "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.",
"Control currents in Pins for analog/digital signals, servos, i2c, ...": "Control currents in Pins for analog/digital signals, servos, i2c, ...",
"Control of the LED screen.": "Control of the LED screen.",
"Creates an image that fits on the LED screen.": "Creates an image that fits on the LED screen.",
"Creates an image with 2 frames.": "Creates an image with 2 frames.",
"Creation, manipulation and display of LED images.": "Creation, manipulation and display of LED images.",
"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.",
"Displays a game over animation.": "Displays a game over animation.",
"Displays a vertical bar graph based on the `value` and `high` value.\nIf `high` is 0, the chart gets adjusted automatically.": "Displays a vertical bar graph based on the `value` and `high` value.\nIf `high` is 0, the chart gets adjusted automatically.",
"Do something when a button (``A``, ``B`` or both ``A+B``) is pressed": "Do something when a button (``A``, ``B`` or both ``A+B``) is pressed",
"Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.": "Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.",
"Draws an image on the LED screen.": "Draws an image on the LED screen.",
"Emits a Pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.": "Emits a Pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.",
"Events and data from sensors": "Events and data from sensors",
"Fades in the screen display.": "Fades in the screen display.",
"Fades out the screen brightness.": "Fades out the screen brightness.",
"Generation of music tones through pin ``P0``.": "Generation of music tones through pin ``P0``.",
"Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)": "Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)",
"Get the button state (pressed or not) for ``A`` and ``B``.": "Get the button state (pressed or not) for ``A`` and ``B``.",
"Get the current compass compass heading in degrees.": "Get the current compass compass heading in degrees.",
"Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.": "Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.",
"Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.": "Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.",
"Get the pin state (pressed or not). Requires to hold the ground to close the circuit.": "Get the pin state (pressed or not). Requires to hold the ground to close the circuit.",
"Get the screen brightness from 0 (off) to 255 (full bright).": "Get the screen brightness from 0 (off) to 255 (full bright).",
"Gets the current score": "Gets the current score",
"Gets the frequency of a note.": "Gets the frequency of a note.",
"Gets the number of milliseconds elapsed since power on.": "Gets the number of milliseconds elapsed since power on.",
"Gets the temperature in Celsius degrees (°C).": "Gets the temperature in Celsius degrees (°C).",
"Inverts the current LED display": "Inverts the current LED display",
"Obsolete, compass calibration is automatic.": "Obsolete, compass calibration is automatic.",
"Pause for the specified time in milliseconds": "Pause for the specified time in milliseconds",
"Plays a tone through pin ``P0`` for the given duration.": "Plays a tone through pin ``P0`` for the given duration.",
"Plays a tone through pin ``P0``.": "Plays a tone through pin ``P0``.",
"Prints a line of text to the serial": "Prints a line of text to the serial",
"Provides access to basic micro:bit functionality.": "Provides access to basic micro:bit functionality.",
"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.": "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.",
"Read the connector value as analog, that is, as a value comprised between 0 and 1023.": "Read the connector value as analog, that is, as a value comprised between 0 and 1023.",
"Read the specified pin or connector as either 0 or 1": "Read the specified pin or connector as either 0 or 1",
"Reading and writing data over a serial connection.": "Reading and writing data over a serial connection.",
"Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.": "Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.",
"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.",
"Resets the BBC micro:bit.": "Resets the BBC micro:bit.",
"Rests (plays nothing) for a specified time through pin ``P0``.": "Rests (plays nothing) for a specified time through pin ``P0``.",
"Returns the duration of a beat in milli-seconds": "Returns the duration of a beat in milli-seconds",
"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.": "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.",
"Runtime and event utilities.": "Runtime and event utilities.",
"Schedules code that run in the background.": "Schedules code that run in the background.",
"Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.": "Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.",
"Set a pin or connector value to either 0 or 1.": "Set a pin or connector value to either 0 or 1.",
"Set the connector value as analog. Value must be comprised between 0 and 1023.": "Set the connector value as analog. Value must be comprised between 0 and 1023.",
"Set the screen brightness from 0 (off) to 255 (full bright).": "Set the screen brightness from 0 (off) to 255 (full bright).",
"Sets the accelerometer sample range in gravities.": "Sets the accelerometer sample range in gravities.",
"Sets the current score value": "Sets the current score value",
"Sets the display mode between black and white and greyscale for rendering LEDs.": "Sets the display mode between black and white and greyscale for rendering LEDs.",
"Sets the pin used when using `pins->analog pitch`.": "Sets the pin used when using `pins->analog pitch`.",
"Sets the tempo to the specified amount": "Sets the tempo to the specified amount",
"Shows a sequence of LED screens as an animation.": "Shows a sequence of LED screens as an animation.",
"Starts a game countdown timer": "Starts a game countdown timer",
"Takes a screenshot of the LED screen and returns an image.": "Takes a screenshot of the LED screen and returns an image.",
"The pitch of the device, rotation along the ``x-axis``, in degrees.": "The pitch of the device, rotation along the ``x-axis``, in degrees.",
"Toggles a particular pixel": "Toggles a particular pixel",
"Turn off all LEDs": "Turn off all LEDs",
"Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.": "Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.",
"Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.": "Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.",
"Turns all LEDS on": "Turns all LEDS on",
"Writes a ``name: value`` pair line to the serial.": "Writes a ``name: value`` pair line to the serial.",
"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).": "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)."
}

View File

@ -1,6 +1,6 @@
{
"name": "pxt-microbit",
"version": "0.2.97",
"version": "0.2.101",
"description": "BBC micro:bit target for PXT",
"keywords": [
"JavaScript",
@ -29,6 +29,6 @@
"typescript": "^1.8.7"
},
"dependencies": {
"pxt-core": "0.2.107"
"pxt-core": "0.2.114"
}
}

View File

@ -22,14 +22,12 @@
"description": "",
"files": [
"main.blocks",
"main.ts",
"README.md"
"main.ts"
]
},
"files": {
"main.blocks": "<xml xmlns=\"http://www.w3.org/1999/xhtml\"><block type=\"device_print_message\"><value name=\"text\"><shadow type=\"text\"><field name=\"TEXT\">Hello!</field></shadow></value></block></xml>",
"main.ts": "\n",
"README.md": "Describe your project here!"
"main.ts": "\n"
}
},
"tsprj": {
@ -42,13 +40,11 @@
},
"description": "",
"files": [
"main.ts",
"README.md"
"main.ts"
]
},
"files": {
"main.ts": "basic.showString('Hello!')\n",
"README.md": "Describe your project here!"
"main.ts": "basic.showString('Hello!')\n"
}
},
"compile": {
@ -63,7 +59,8 @@
"variablesBlocks": true
},
"simulator": {
"autoRun": true
"autoRun": true,
"aspectRatio": 1.22
},
"compileService": {
"gittag": "v0.1.8",

View File

@ -4,12 +4,12 @@
namespace pxsim {
pxsim.initCurrentRuntime = () => {
U.assert(!runtime.board)
runtime.board = new Board()
U.assert(!runtime.board);
runtime.board = new Board();
}
export function board() {
return runtime.board as Board
return runtime.board as Board;
}
export interface AnimationOptions {
@ -77,7 +77,7 @@ namespace pxsim {
})
}
}
/**
* Error codes used in the micro:bit runtime.
*/
@ -115,7 +115,7 @@ namespace pxsim {
img.set(3, 1, 255);
img.set(4, 1, 255);
runtime.updateDisplay();
throw new Error("PANIC " + code)
}
@ -125,9 +125,9 @@ namespace pxsim {
export namespace AudioContextManager {
var _context: any; // AudioContext
var _vco: any; //OscillatorNode;
var _vca: any; // GainNode;
let _context: any; // AudioContext
let _vco: any; // OscillatorNode;
let _vca: any; // GainNode;
function context(): any {
if (!_context) _context = freshContext();
@ -152,7 +152,7 @@ namespace pxsim {
export function tone(frequency: number, gain: number) {
if (frequency <= 0) return;
var ctx = context();
let ctx = context();
if (!ctx) return;
gain = Math.max(0, Math.min(1, gain));
@ -198,10 +198,10 @@ namespace pxsim.basic {
pause(interval * 5);
} else {
if (s.length == 1) showLeds(createImageFromString(s), interval * 5)
else ImageMethods.scrollImage(createImageFromString(s + ' '), interval, 1);
else ImageMethods.scrollImage(createImageFromString(s + " "), interval, 1);
}
}
export function showLeds(leds: Image, delay: number): void {
showAnimation(leds, delay);
}
@ -226,19 +226,19 @@ namespace pxsim.control {
export function reset() {
U.userError("reset not implemented in simulator yet")
}
export function deviceName() : string {
export function deviceName(): string {
let b = board();
return b && b.id
? b.id.slice(0, 4)
: 'abcd';
return b && b.id
? b.id.slice(0, 4)
: "abcd";
}
export function deviceSerialNumber(): number {
let b = board();
return parseInt(b && b.id
? b.id.slice(1)
: '42');
return parseInt(b && b.id
? b.id.slice(1)
: "42");
}
export function onEvent(id: number, evid: number, handler: RefAction) {
@ -306,7 +306,7 @@ namespace pxsim.input {
export function compassHeading(): number {
var b = board();
let b = board();
if (!b.usesHeading) {
b.usesHeading = true;
runtime.queueDisplayUpdate();
@ -315,7 +315,7 @@ namespace pxsim.input {
}
export function temperature(): number {
var b = board();
let b = board();
if (!b.usesTemperature) {
b.usesTemperature = true;
runtime.queueDisplayUpdate();
@ -565,29 +565,29 @@ namespace pxsim.images {
namespace pxsim.ImageMethods {
export function showImage(leds: Image, offset: number) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
leds.copyTo(offset, 5, board().image, 0)
runtime.queueDisplayUpdate()
}
export function plotImage(leds: Image, offset: number): void {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
leds.copyTo(offset, 5, board().image, 0)
runtime.queueDisplayUpdate()
}
export function height(leds: Image) : number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
export function height(leds: Image): number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
return Image.height;
}
export function width(leds: Image) : number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
export function width(leds: Image): number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
return leds.width;
}
export function plotFrame(leds: Image, frame: number) {
ImageMethods.plotImage(leds, frame * Image.height);
}
@ -595,38 +595,38 @@ namespace pxsim.ImageMethods {
export function showFrame(leds: Image, frame: number) {
ImageMethods.showImage(leds, frame * Image.height);
}
export function pixel(leds: Image, x: number, y: number) : number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
return leds.get(x,y);
export function pixel(leds: Image, x: number, y: number): number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
return leds.get(x, y);
}
export function setPixel(leds: Image, x: number, y: number, v:number) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
leds.set(x,y,v);
export function setPixel(leds: Image, x: number, y: number, v: number) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
leds.set(x, y, v);
}
export function clear(leds: Image) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
leds.clear();
}
export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
i.set(x, y, b);
}
export function pixelBrightness(i: Image, x: number, y: number): number {
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
return i.get(x, y);
}
export function scrollImage(leds: Image, interval: number, stride: number): void {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
let cb = getResume()
let off = stride > 0 ? 0 : leds.width - 1;
let display = board().image;

View File

@ -1,5 +1,5 @@
namespace pxsim.micro_bit {
const Svg = pxsim.Svg;
const svg = pxsim.svg;
export interface IBoardTheme {
accent?: string;
@ -15,7 +15,7 @@ namespace pxsim.micro_bit {
virtualButtonOuter?: string;
virtualButtonUp?: string;
virtualButtonDown?: string;
lightLevelOn?:string;
lightLevelOn?: string;
lightLevelOff?: string;
}
@ -25,7 +25,7 @@ namespace pxsim.micro_bit {
display: "#000",
pin: "#D4AF37",
pinTouched: "#FFA500",
pinActive:"#FF5500",
pinActive: "#FF5500",
ledOn: "#ff7f7f",
ledOff: "#202020",
buttonOuter: "#979797",
@ -35,44 +35,44 @@ namespace pxsim.micro_bit {
virtualButtonUp: "#fff",
lightLevelOn: "yellow",
lightLevelOff: "#555"
}});
}
});
export function randomTheme() : IBoardTheme {
export function randomTheme(): IBoardTheme {
return themes[Math.floor(Math.random() * themes.length)];
}
export interface IBoardProps {
runtime: pxsim.Runtime;
theme?: IBoardTheme;
disableTilt?:boolean;
disableTilt?: boolean;
}
const pointerEvents = !!(window as any).PointerEvent ? {
up: "pointerup",
down: "pointerdown",
move: "pointermove",
leave: "pointerleave"
} : {
up: "mouseup",
down: "mousedown",
move: "mousemove",
leave: "mouseleave"
};
up: "mouseup",
down: "mousedown",
move: "mousemove",
leave: "mouseleave"
};
export class MicrobitBoardSvg
{
public element : SVGSVGElement;
export class MicrobitBoardSvg {
public element: SVGSVGElement;
private style: SVGStyleElement;
private defs : SVGDefsElement;
private defs: SVGDefsElement;
private g: SVGElement;
private logos: SVGElement[];
private head: SVGGElement; private headInitialized = false;
private headText: SVGTextElement;
private display: SVGElement;
private buttons: SVGElement[];
private buttonsOuter: SVGElement[];
private buttonABText:SVGTextElement;
private buttonABText: SVGTextElement;
private pins: SVGElement[];
private pinGradients: SVGLinearGradientElement[];
private pinTexts: SVGTextElement[];
@ -81,111 +81,111 @@ namespace pxsim.micro_bit {
private systemLed: SVGCircleElement;
private antenna: SVGPolylineElement;
private lightLevelButton: SVGCircleElement;
private lightLevelGradient : SVGLinearGradientElement;
private lightLevelGradient: SVGLinearGradientElement;
private lightLevelText: SVGTextElement;
private thermometerGradient : SVGLinearGradientElement;
private thermometerGradient: SVGLinearGradientElement;
private thermometer: SVGRectElement;
private thermometerText: SVGTextElement;
private shakeButton: SVGCircleElement;
private shakeText: SVGTextElement;
public board: pxsim.Board;
public board: pxsim.Board;
constructor(public props: IBoardProps) {
this.board = this.props.runtime.board as pxsim.Board;
this.board.updateView = () => this.updateState();
this.buildDom();
this.buildDom();
this.updateTheme();
this.updateState();
this.attachEvents();
}
private updateTheme() {
let theme = this.props.theme;
Svg.fill(this.display, theme.display);
Svg.fills(this.leds, theme.ledOn);
Svg.fills(this.ledsOuter, theme.ledOff);
Svg.fills(this.buttonsOuter.slice(0, 2), theme.buttonOuter);
Svg.fills(this.buttons.slice(0, 2), theme.buttonUp);
Svg.fill(this.buttonsOuter[2], theme.virtualButtonOuter);
Svg.fill(this.buttons[2], theme.virtualButtonUp);
Svg.fills(this.logos, theme.accent);
if (this.shakeButton) Svg.fill(this.shakeButton, theme.virtualButtonUp);
this.pinGradients.forEach(lg => Svg.setGradientColors(lg, theme.pin, theme.pinActive));
Svg.setGradientColors(this.lightLevelGradient, theme.lightLevelOn, theme.lightLevelOff);
Svg.setGradientColors(this.thermometerGradient, theme.ledOff, theme.ledOn);
svg.fill(this.display, theme.display);
svg.fills(this.leds, theme.ledOn);
svg.fills(this.ledsOuter, theme.ledOff);
svg.fills(this.buttonsOuter.slice(0, 2), theme.buttonOuter);
svg.fills(this.buttons.slice(0, 2), theme.buttonUp);
svg.fill(this.buttonsOuter[2], theme.virtualButtonOuter);
svg.fill(this.buttons[2], theme.virtualButtonUp);
svg.fills(this.logos, theme.accent);
if (this.shakeButton) svg.fill(this.shakeButton, theme.virtualButtonUp);
this.pinGradients.forEach(lg => svg.setGradientColors(lg, theme.pin, theme.pinActive));
svg.setGradientColors(this.lightLevelGradient, theme.lightLevelOn, theme.lightLevelOff);
svg.setGradientColors(this.thermometerGradient, theme.ledOff, theme.ledOn);
}
public updateState() {
let state = this.board;
if (!state) return;
let theme = this.props.theme;
state.buttons.forEach((btn, index) => {
Svg.fill(this.buttons[index], btn.pressed ? theme.buttonDown : theme.buttonUp);
svg.fill(this.buttons[index], btn.pressed ? theme.buttonDown : theme.buttonUp);
});
var bw = state.displayMode == pxsim.DisplayMode.bw
var img = state.image;
this.leds.forEach((led,i) => {
var sel = (<SVGStylable><any>led)
let bw = state.displayMode == pxsim.DisplayMode.bw
let img = state.image;
this.leds.forEach((led, i) => {
let sel = (<SVGStylable><any>led)
sel.style.opacity = ((bw ? img.data[i] > 0 ? 255 : 0 : img.data[i]) / 255.0) + "";
})
this.updatePins();
this.updateTilt();
this.updateHeading();
this.updateHeading();
this.updateLightLevel();
this.updateTemperature();
this.updateButtonAB();
this.updateGestures();
if (!runtime || runtime.dead) Svg.addClass(this.element, "grayscale");
else Svg.removeClass(this.element, "grayscale");
this.updateTemperature();
this.updateButtonAB();
this.updateGestures();
if (!runtime || runtime.dead) svg.addClass(this.element, "grayscale");
else svg.removeClass(this.element, "grayscale");
}
private updateGestures() {
let state = this.board;
if (state.useShake && !this.shakeButton) {
this.shakeButton = Svg.child(this.g, "circle", {cx:380, cy:100, r:16.5}) as SVGCircleElement;
Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp)
this.shakeButton = svg.child(this.g, "circle", { cx: 380, cy: 100, r: 16.5 }) as SVGCircleElement;
svg.fill(this.shakeButton, this.props.theme.virtualButtonUp)
this.shakeButton.addEventListener(pointerEvents.down, ev => {
let state = this.board;
Svg.fill(this.shakeButton, this.props.theme.buttonDown);
svg.fill(this.shakeButton, this.props.theme.buttonDown);
})
this.shakeButton.addEventListener(pointerEvents.leave, ev => {
let state = this.board;
Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp);
svg.fill(this.shakeButton, this.props.theme.virtualButtonUp);
})
this.shakeButton.addEventListener(pointerEvents.up, ev => {
let state = this.board;
Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp);
svg.fill(this.shakeButton, this.props.theme.virtualButtonUp);
this.board.bus.queue(DAL.MICROBIT_ID_GESTURE, 11); // GESTURE_SHAKE
})
this.shakeText = Svg.child(this.g, "text", {x:400, y:110, class:'sim-text'}) as SVGTextElement;
this.shakeText.textContent = "SHAKE"
}
})
this.shakeText = svg.child(this.g, "text", { x: 400, y: 110, class: "sim-text" }) as SVGTextElement;
this.shakeText.textContent = "SHAKE"
}
}
private updateButtonAB() {
let state = this.board;
if (state.usesButtonAB && !this.buttonABText) {
(<any>this.buttonsOuter[2]).style.visibility = 'visible';
(<any>this.buttons[2]).style.visibility = 'visible';
this.buttonABText = Svg.child(this.g, "text", {class: 'sim-text', x:370, y:272 }) as SVGTextElement;
(<any>this.buttonsOuter[2]).style.visibility = "visible";
(<any>this.buttons[2]).style.visibility = "visible";
this.buttonABText = svg.child(this.g, "text", { class: "sim-text", x: 370, y: 272 }) as SVGTextElement;
this.buttonABText.textContent = "A+B";
this.updateTheme();
}
}
}
private updatePin(pin : Pin, index: number) {
private updatePin(pin: Pin, index: number) {
if (!pin) return;
let text = this.pinTexts[index];
let v = '';
let v = "";
if (pin.mode & PinMode.Analog) {
v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + '%';
if(text) text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + "";
v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + "%";
if (text) text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + "";
}
else if (pin.mode & PinMode.Digital) {
v = pin.value > 0 ? '0%' : '100%';
@ -196,48 +196,48 @@ namespace pxsim.micro_bit {
if (text) text.textContent = "";
} else {
v = '100%';
if(text) text.textContent = '';
if (text) text.textContent = '';
}
if (v) Svg.setGradientValue(this.pinGradients[index], v);
if (v) svg.setGradientValue(this.pinGradients[index], v);
}
private updateTemperature() {
let state = this.board;
if (!state || !state.usesTemperature) return;
let tmin = -5;
let tmax = 50;
if (!this.thermometer) {
if (!this.thermometer) {
let gid = "gradient-thermometer";
this.thermometerGradient = Svg.linearGradient(this.defs, gid);
this.thermometer = <SVGRectElement> Svg.child(this.g, "rect", {
class: "sim-thermometer",
x:120,
y:110,
width:20,
height:160,
rx:5, ry:5,
fill:`url(#${gid})`
this.thermometerGradient = svg.linearGradient(this.defs, gid);
this.thermometer = <SVGRectElement>svg.child(this.g, "rect", {
class: "sim-thermometer",
x: 120,
y: 110,
width: 20,
height: 160,
rx: 5, ry: 5,
fill: `url(#${gid})`
});
this.thermometerText = Svg.child(this.g, "text", { class:'sim-text', x:58, y:130}) as SVGTextElement;
this.thermometerText = svg.child(this.g, "text", { class: 'sim-text', x: 58, y: 130 }) as SVGTextElement;
this.updateTheme();
let pt = this.element.createSVGPoint();
Svg.buttonEvents(this.thermometer,
svg.buttonEvents(this.thermometer,
(ev) => {
let cur = Svg.cursorPoint(pt, this.element, ev);
let cur = svg.cursorPoint(pt, this.element, ev);
let t = Math.max(0, Math.min(1, (260 - cur.y) / 140))
state.temperature = Math.floor(tmin + t * (tmax-tmin));
state.temperature = Math.floor(tmin + t * (tmax - tmin));
this.updateTemperature();
}, ev => {}, ev => {})
}, ev => { }, ev => { })
}
let t = Math.max(tmin, Math.min(tmax, state.temperature))
let per = Math.floor((state.temperature - tmin) / (tmax-tmin)*100)
Svg.setGradientValue(this.thermometerGradient, 100 - per + '%');
let per = Math.floor((state.temperature - tmin) / (tmax - tmin) * 100)
svg.setGradientValue(this.thermometerGradient, 100 - per + '%');
this.thermometerText.textContent = t + '°C';
}
private updateHeading() {
let xc = 258;
let yc = 75;
@ -247,98 +247,99 @@ namespace pxsim.micro_bit {
let p = this.head.firstChild.nextSibling as SVGPathElement;
p.setAttribute("d", "m269.9,50.134647l0,0l-39.5,0l0,0c-14.1,0.1 -24.6,10.7 -24.6,24.8c0,13.9 10.4,24.4 24.3,24.7l0,0l39.6,0c14.2,0 40.36034,-22.97069 40.36034,-24.85394c0,-1.88326 -26.06034,-24.54606 -40.16034,-24.64606m-0.2,39l0,0l-39.3,0c-7.7,-0.1 -14,-6.4 -14,-14.2c0,-7.8 6.4,-14.2 14.2,-14.2l39.1,0c7.8,0 14.2,6.4 14.2,14.2c0,7.9 -6.4,14.2 -14.2,14.2l0,0l0,0z");
let pt = this.element.createSVGPoint();
Svg.buttonEvents(
svg.buttonEvents(
this.head,
(ev : MouseEvent) => {
let cur = Svg.cursorPoint(pt, this.element, ev);
state.heading = Math.floor(Math.atan2(cur.y - yc, cur.x - xc) * 180 / Math.PI+90);
if (state.heading < 0) state.heading += 360;
console.log('heading: ' + state.heading)
this.updateHeading();
(ev: MouseEvent) => {
let cur = svg.cursorPoint(pt, this.element, ev);
state.heading = Math.floor(Math.atan2(cur.y - yc, cur.x - xc) * 180 / Math.PI + 90);
if (state.heading < 0) state.heading += 360;
console.log('heading: ' + state.heading)
this.updateHeading();
});
this.headInitialized = true;
}
let txt = state.heading.toString() + '°';
if (txt != this.headText.textContent) {
Svg.rotateElement(this.head, xc, yc, state.heading+180);
if (txt != this.headText.textContent) {
svg.rotateElement(this.head, xc, yc, state.heading + 180);
this.headText.textContent = txt;
}
}
}
private lastFlashTime : number = 0;
private lastFlashTime: number = 0;
public flashSystemLed() {
if (!this.systemLed)
this.systemLed = <SVGCircleElement>Svg.child(this.g, "circle", {class:"sim-systemled", cx:300, cy:20, r:5})
this.systemLed = <SVGCircleElement>svg.child(this.g, "circle", { class: "sim-systemled", cx: 300, cy: 20, r: 5 })
let now = Date.now();
if (now - this.lastFlashTime > 150) {
this.lastFlashTime = now;
Svg.animate(this.systemLed, 'sim-flash')
svg.animate(this.systemLed, 'sim-flash')
}
}
private lastAntennaFlash : number = 0;
private lastAntennaFlash: number = 0;
public flashAntenna() {
if (!this.antenna) {
if (!this.antenna) {
let ax = 380;
let dax = 18;
let ayt = 10;
let ayb = 40;
this.antenna = <SVGPolylineElement>Svg.child(this.g, "polyline", { class:"sim-antenna", points: `${ax},${ayb} ${ax},${ayt} ${ax+=dax},${ayt} ${ax},${ayb} ${ax+=dax},${ayb} ${ax},${ayt} ${ax+=dax},${ayt} ${ax},${ayb} ${ax+=dax},${ayb} ${ax},${ayt} ${ax+=dax},${ayt}`})
this.antenna = <SVGPolylineElement>svg.child(this.g, "polyline", { class: "sim-antenna", points: `${ax},${ayb} ${ax},${ayt} ${ax += dax},${ayt} ${ax},${ayb} ${ax += dax},${ayb} ${ax},${ayt} ${ax += dax},${ayt} ${ax},${ayb} ${ax += dax},${ayb} ${ax},${ayt} ${ax += dax},${ayt}` })
}
let now = Date.now();
if (now - this.lastAntennaFlash > 200) {
this.lastAntennaFlash = now;
Svg.animate(this.antenna, 'sim-flash-stroke')
svg.animate(this.antenna, 'sim-flash-stroke')
}
}
private updatePins() {
let state = this.board;
if (!state) return;
state.pins.forEach((pin,i) => this.updatePin(pin,i));
}
state.pins.forEach((pin, i) => this.updatePin(pin, i));
}
private updateLightLevel() {
let state = this.board;
if (!state || !state.usesLightLevel) return;
if (!this.lightLevelButton) {
let gid= "gradient-light-level";
this.lightLevelGradient = Svg.linearGradient(this.defs, gid)
let gid = "gradient-light-level";
this.lightLevelGradient = svg.linearGradient(this.defs, gid)
let cy = 50;
let r = 35;
this.lightLevelButton = Svg.child(this.g, "circle", {
cx: `50px`, cy: `${cy}px`, r: `${r}px`,
class:'sim-light-level-button',
fill: `url(#${gid})` }) as SVGCircleElement;
this.lightLevelButton = svg.child(this.g, "circle", {
cx: `50px`, cy: `${cy}px`, r: `${r}px`,
class: 'sim-light-level-button',
fill: `url(#${gid})`
}) as SVGCircleElement;
let pt = this.element.createSVGPoint();
Svg.buttonEvents(this.lightLevelButton,
svg.buttonEvents(this.lightLevelButton,
(ev) => {
let pos = Svg.cursorPoint(pt, this.element, ev);
let rs = r/2;
let level = Math.max(0, Math.min(255, Math.floor((pos.y - (cy-rs)) / (2*rs) * 255)));
let pos = svg.cursorPoint(pt, this.element, ev);
let rs = r / 2;
let level = Math.max(0, Math.min(255, Math.floor((pos.y - (cy - rs)) / (2 * rs) * 255)));
if (level != this.board.lightLevel) {
this.board.lightLevel = level;
this.applyLightLevel();
}
}, ev => {},
ev => {})
this.lightLevelText = Svg.child(this.g, "text", { x:85, y:cy+r-5, text:'', class:'sim-text'}) as SVGTextElement;
}, ev => { },
ev => { })
this.lightLevelText = svg.child(this.g, "text", { x: 85, y: cy + r - 5, text: '', class: 'sim-text' }) as SVGTextElement;
this.updateTheme();
}
Svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(state.lightLevel * 100 / 255))) + '%')
}
svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(state.lightLevel * 100 / 255))) + '%')
this.lightLevelText.textContent = state.lightLevel.toString();
}
}
private applyLightLevel() {
let lv = this.board.lightLevel;
Svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(lv * 100 / 255))) + '%')
this.lightLevelText.textContent = lv.toString();
svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(lv * 100 / 255))) + '%')
this.lightLevelText.textContent = lv.toString();
}
private updateTilt() {
if (this.props.disableTilt) return;
let state = this.board;
@ -348,21 +349,22 @@ namespace pxsim.micro_bit {
let y = state.accelerometer.getY();
let af = 8 / 1023;
this.element.style.transform = "perspective(30em) rotateX(" + y*af + "deg) rotateY(" + x*af +"deg)"
this.element.style.transform = "perspective(30em) rotateX(" + y * af + "deg) rotateY(" + x * af + "deg)"
this.element.style.perspectiveOrigin = "50% 50% 50%";
this.element.style.perspective = "30em";
this.element.style.perspective = "30em";
}
private buildDom() {
this.element = <SVGSVGElement>Svg.elt("svg")
Svg.hydrate(this.element, {
"version": "1.0",
this.element = <SVGSVGElement>svg.elt("svg")
svg.hydrate(this.element, {
"version": "1.0",
"viewBox": "0 0 498 406",
"enable-background": "new 0 0 498 406",
"class":"sim",
"class": "sim",
"x": "0px",
"y": "0px"});
this.style = <SVGStyleElement>Svg.child(this.element, "style", {});
"y": "0px"
});
this.style = <SVGStyleElement>svg.child(this.element, "style", {});
this.style.textContent = `
svg.sim {
margin-bottom:1em;
@ -457,127 +459,127 @@ svg.sim.grayscale {
}
`;
this.defs = <SVGDefsElement>Svg.child(this.element, "defs", {});
this.g = Svg.elt("g");
this.defs = <SVGDefsElement>svg.child(this.element, "defs", {});
this.g = svg.elt("g");
this.element.appendChild(this.g);
// filters
let glow = Svg.child(this.defs, "filter", {id:"filterglow", x:"-5%", y:"-5%", width:"120%", height:"120%"});
Svg.child(glow, "feGaussianBlur", {stdDeviation:"5", result: "glow" });
let merge = Svg.child(glow, "feMerge", {});
for(let i=0;i<3;++i) Svg.child(merge, "feMergeNode", {in:"glow"})
let glow = svg.child(this.defs, "filter", { id: "filterglow", x: "-5%", y: "-5%", width: "120%", height: "120%" });
svg.child(glow, "feGaussianBlur", { stdDeviation: "5", result: "glow" });
let merge = svg.child(glow, "feMerge", {});
for (let i = 0; i < 3; ++i) svg.child(merge, "feMergeNode", { in: "glow" })
// outline
Svg.path(this.g, "sim-board", "M498,31.9C498,14.3,483.7,0,466.1,0H31.9C14.3,0,0,14.3,0,31.9v342.2C0,391.7,14.3,406,31.9,406h434.2c17.6,0,31.9-14.3,31.9-31.9V31.9z M14.3,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.7,2.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C19.2,204.6,17,206.7,14.3,206.7z M486.2,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.72.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C491,204.6,488.8,206.7,486.2,206.7z");
svg.path(this.g, "sim-board", "M498,31.9C498,14.3,483.7,0,466.1,0H31.9C14.3,0,0,14.3,0,31.9v342.2C0,391.7,14.3,406,31.9,406h434.2c17.6,0,31.9-14.3,31.9-31.9V31.9z M14.3,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.7,2.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C19.2,204.6,17,206.7,14.3,206.7z M486.2,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.72.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C491,204.6,488.8,206.7,486.2,206.7z");
// script background
this.display = Svg.path(this.g, "sim-display", "M333.8,310.3H165.9c-8.3,0-15-6.7-15-15V127.5c0-8.3,6.7-15,15-15h167.8c8.3,0,15,6.7,15,15v167.8C348.8,303.6,342.1,310.3,333.8,310.3z");
this.display = svg.path(this.g, "sim-display", "M333.8,310.3H165.9c-8.3,0-15-6.7-15-15V127.5c0-8.3,6.7-15,15-15h167.8c8.3,0,15,6.7,15,15v167.8C348.8,303.6,342.1,310.3,333.8,310.3z");
this.logos = [];
this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"115,56.7 173.1,0 115,0"}));
this.logos.push(Svg.path(this.g, "sim-theme", "M114.2,0H25.9C12.1,2.1,0,13.3,0,27.7v83.9L114.2,0z"));
this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"173,27.9 202.5,0 173,0"}));
this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"54.1,242.4 54.1,274.1 22.4,274.1"}));
this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"446.2,164.6 446.2,132.8 477.9,132.8"}));
this.logos.push(svg.child(this.g, "polygon", { class: "sim-theme", points: "115,56.7 173.1,0 115,0" }));
this.logos.push(svg.path(this.g, "sim-theme", "M114.2,0H25.9C12.1,2.1,0,13.3,0,27.7v83.9L114.2,0z"));
this.logos.push(svg.child(this.g, "polygon", { class: "sim-theme", points: "173,27.9 202.5,0 173,0" }));
this.logos.push(svg.child(this.g, "polygon", { class: "sim-theme", points: "54.1,242.4 54.1,274.1 22.4,274.1" }));
this.logos.push(svg.child(this.g, "polygon", { class: "sim-theme", points: "446.2,164.6 446.2,132.8 477.9,132.8" }));
// leds
this.leds = [];
this.ledsOuter = [];
var left = 154, top = 113, ledoffw = 46, ledoffh = 44;
for (var i = 0; i < 5; ++i) {
var ledtop = i * ledoffh + top;
for (var j = 0; j < 5; ++j) {
var ledleft = j * ledoffw + left;
var k = i * 5 + j;
this.ledsOuter.push(Svg.child(this.g, "rect", { class:"sim-led-back", x:ledleft, y:ledtop, width:10, height:20, rx:2, ry:2 }));
this.leds.push(Svg.child(this.g, "rect", { class:"sim-led", x:ledleft-2, y:ledtop-2, width:14, height:24, rx:3, ry:3, title:`(${j},${i})`}));
let left = 154, top = 113, ledoffw = 46, ledoffh = 44;
for (let i = 0; i < 5; ++i) {
let ledtop = i * ledoffh + top;
for (let j = 0; j < 5; ++j) {
let ledleft = j * ledoffw + left;
let k = i * 5 + j;
this.ledsOuter.push(svg.child(this.g, "rect", { class: "sim-led-back", x: ledleft, y: ledtop, width: 10, height: 20, rx: 2, ry: 2 }));
this.leds.push(svg.child(this.g, "rect", { class: "sim-led", x: ledleft - 2, y: ledtop - 2, width: 14, height: 24, rx: 3, ry: 3, title: `(${j},${i})` }));
}
}
// head
this.head = <SVGGElement>Svg.child(this.g, "g", {});
Svg.child(this.head, "circle", { cx: 258, cy: 75, r: 100, fill:'transparent'})
this.logos.push(Svg.path(this.head, "sim-theme","M269.9,50.2L269.9,50.2l-39.5,0v0c-14.1,0.1-24.6,10.7-24.6,24.8c0,13.9,10.4,24.4,24.3,24.7v0h39.6c14.2,0,24.8-10.6,24.8-24.7C294.5,61,284,50.3,269.9,50.2 M269.7,89.2L269.7,89.2l-39.3,0c-7.7-0.1-14-6.4-14-14.2c0-7.8,6.4-14.2,14.2-14.2h39.1c7.8,0,14.2,6.4,14.2,14.2C283.9,82.9,277.5,89.2,269.7,89.2"));
this.logos.push(Svg.path(this.head, "sim-theme","M230.6,69.7c-2.9,0-5.3,2.4-5.3,5.3c0,2.9,2.4,5.3,5.3,5.3c2.9,0,5.3-2.4,5.3-5.3C235.9,72.1,233.5,69.7,230.6,69.7"));
this.logos.push(Svg.path(this.head, "sim-theme","M269.7,80.3c2.9,0,5.3-2.4,5.3-5.3c0-2.9-2.4-5.3-5.3-5.3c-2.9,0-5.3,2.4-5.3,5.3C264.4,77.9,266.8,80.3,269.7,80.3"));
this.headText = <SVGTextElement>Svg.child(this.g, "text", { x: 310, y: 100, class:'sim-text' })
this.head = <SVGGElement>svg.child(this.g, "g", {});
svg.child(this.head, "circle", { cx: 258, cy: 75, r: 100, fill: "transparent" })
this.logos.push(svg.path(this.head, "sim-theme", "M269.9,50.2L269.9,50.2l-39.5,0v0c-14.1,0.1-24.6,10.7-24.6,24.8c0,13.9,10.4,24.4,24.3,24.7v0h39.6c14.2,0,24.8-10.6,24.8-24.7C294.5,61,284,50.3,269.9,50.2 M269.7,89.2L269.7,89.2l-39.3,0c-7.7-0.1-14-6.4-14-14.2c0-7.8,6.4-14.2,14.2-14.2h39.1c7.8,0,14.2,6.4,14.2,14.2C283.9,82.9,277.5,89.2,269.7,89.2"));
this.logos.push(svg.path(this.head, "sim-theme", "M230.6,69.7c-2.9,0-5.3,2.4-5.3,5.3c0,2.9,2.4,5.3,5.3,5.3c2.9,0,5.3-2.4,5.3-5.3C235.9,72.1,233.5,69.7,230.6,69.7"));
this.logos.push(svg.path(this.head, "sim-theme", "M269.7,80.3c2.9,0,5.3-2.4,5.3-5.3c0-2.9-2.4-5.3-5.3-5.3c-2.9,0-5.3,2.4-5.3,5.3C264.4,77.9,266.8,80.3,269.7,80.3"));
this.headText = <SVGTextElement>svg.child(this.g, "text", { x: 310, y: 100, class: "sim-text" })
// https://www.microbit.co.uk/device/pins
// P0, P1, P2
this.pins = [
"M16.5,341.2c0,0.4-0.1,0.9-0.1,1.3v60.7c4.1,1.7,8.6,2.7,12.9,2.7h34.4v-64.7h0.3c0,0,0-0.1,0-0.1c0-13-10.6-23.6-23.7-23.6C27.2,317.6,16.5,328.1,16.5,341.2z M21.2,341.6c0-10.7,8.7-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3c0,10.7-8.6,19.3-19.3,19.3C29.9,360.9,21.2,352.2,21.2,341.6z",
"M139.1,317.3c-12.8,0-22.1,10.3-23.1,23.1V406h46.2v-65.6C162.2,327.7,151.9,317.3,139.1,317.3zM139.3,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C158.6,351.5,150,360.1,139.3,360.1z",
"M249,317.3c-12.8,0-22.1,10.3-23.1,23.1V406h46.2v-65.6C272.1,327.7,261.8,317.3,249,317.3z M249.4,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C268.7,351.5,260.1,360.1,249.4,360.1z"
].map((p,pi) => Svg.path(this.g, "sim-pin sim-pin-touch", p, `P${pi}, ANALOG IN`));
].map((p, pi) => svg.path(this.g, "sim-pin sim-pin-touch", p, `P${pi}, ANALOG IN`));
// P3
this.pins.push(Svg.path(this.g, "sim-pin", "M0,357.7v19.2c0,10.8,6.2,20.2,14.4,25.2v-44.4H0z", "P3, ANALOG IN, LED Col 1"));
this.pins.push(svg.path(this.g, "sim-pin", "M0,357.7v19.2c0,10.8,6.2,20.2,14.4,25.2v-44.4H0z", "P3, ANALOG IN, LED Col 1"));
[66.7,79.1,91.4,103.7,164.3,176.6,188.9,201.3,213.6,275.2,287.5,299.8,312.1,324.5,385.1,397.4,409.7,422].forEach(x => {
this.pins.push(Svg.child(this.g, "rect", {x:x, y:356.7, width:10, height:50, class:"sim-pin"}));
[66.7, 79.1, 91.4, 103.7, 164.3, 176.6, 188.9, 201.3, 213.6, 275.2, 287.5, 299.8, 312.1, 324.5, 385.1, 397.4, 409.7, 422].forEach(x => {
this.pins.push(svg.child(this.g, "rect", { x: x, y: 356.7, width: 10, height: 50, class: "sim-pin" }));
})
Svg.title(this.pins[4], "P4, ANALOG IN, LED Col 2")
Svg.title(this.pins[5], "P5, BUTTON A")
Svg.title(this.pins[6], "P6, LED Col 9")
Svg.title(this.pins[7], "P7, LED Col 8")
Svg.title(this.pins[8], "P8")
Svg.title(this.pins[9], "P9, LED Col 7")
Svg.title(this.pins[10], "P10, ANALOG IN, LED Col 3")
Svg.title(this.pins[11], "P11, BUTTON B")
Svg.title(this.pins[12], "P12, RESERVED ACCESSIBILITY")
Svg.title(this.pins[13], "P13, SPI - SCK")
Svg.title(this.pins[14], "P14, SPI - MISO")
Svg.title(this.pins[15], "P15, SPI - MOSI")
Svg.title(this.pins[16], "P16, SPI - Chip Select")
Svg.title(this.pins[17], "P17, +3v3")
Svg.title(this.pins[18], "P18, +3v3")
Svg.title(this.pins[19], "P19, I2C - SCL")
Svg.title(this.pins[20], "P20, I2C - SDA")
Svg.title(this.pins[21], "GND")
this.pins.push(Svg.path(this.g, "sim-pin", "M483.6,402c8.2-5,14.4-14.4,14.4-25.1v-19.2h-14.4V402z", "GND"));
this.pins.push(Svg.path(this.g, "sim-pin", "M359.9,317.3c-12.8,0-22.1,10.3-23.1,23.1V406H383v-65.6C383,327.7,372.7,317.3,359.9,317.3z M360,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C379.3,351.5,370.7,360.1,360,360.1z", "+3v3"));
this.pins.push(Svg.path(this.g, "sim-pin", "M458,317.6c-13,0-23.6,10.6-23.6,23.6c0,0,0,0.1,0,0.1h0V406H469c4.3,0,8.4-1,12.6-2.7v-60.7c0-0.4,0-0.9,0-1.3C481.6,328.1,471,317.6,458,317.6z M457.8,360.9c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C477.1,352.2,468.4,360.9,457.8,360.9z", "GND"));
this.pinGradients = this.pins.map((pin,i) => {
let gid= "gradient-pin-" + i
let lg = Svg.linearGradient(this.defs, gid)
svg.title(this.pins[4], "P4, ANALOG IN, LED Col 2")
svg.title(this.pins[5], "P5, BUTTON A")
svg.title(this.pins[6], "P6, LED Col 9")
svg.title(this.pins[7], "P7, LED Col 8")
svg.title(this.pins[8], "P8")
svg.title(this.pins[9], "P9, LED Col 7")
svg.title(this.pins[10], "P10, ANALOG IN, LED Col 3")
svg.title(this.pins[11], "P11, BUTTON B")
svg.title(this.pins[12], "P12, RESERVED ACCESSIBILITY")
svg.title(this.pins[13], "P13, SPI - SCK")
svg.title(this.pins[14], "P14, SPI - MISO")
svg.title(this.pins[15], "P15, SPI - MOSI")
svg.title(this.pins[16], "P16, SPI - Chip Select")
svg.title(this.pins[17], "P17, +3v3")
svg.title(this.pins[18], "P18, +3v3")
svg.title(this.pins[19], "P19, I2C - SCL")
svg.title(this.pins[20], "P20, I2C - SDA")
svg.title(this.pins[21], "GND")
this.pins.push(svg.path(this.g, "sim-pin", "M483.6,402c8.2-5,14.4-14.4,14.4-25.1v-19.2h-14.4V402z", "GND"));
this.pins.push(svg.path(this.g, "sim-pin", "M359.9,317.3c-12.8,0-22.1,10.3-23.1,23.1V406H383v-65.6C383,327.7,372.7,317.3,359.9,317.3z M360,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C379.3,351.5,370.7,360.1,360,360.1z", "+3v3"));
this.pins.push(svg.path(this.g, "sim-pin", "M458,317.6c-13,0-23.6,10.6-23.6,23.6c0,0,0,0.1,0,0.1h0V406H469c4.3,0,8.4-1,12.6-2.7v-60.7c0-0.4,0-0.9,0-1.3C481.6,328.1,471,317.6,458,317.6z M457.8,360.9c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C477.1,352.2,468.4,360.9,457.8,360.9z", "GND"));
this.pinGradients = this.pins.map((pin, i) => {
let gid = "gradient-pin-" + i
let lg = svg.linearGradient(this.defs, gid)
pin.setAttribute("fill", `url(#${gid})`);
return lg;
})
this.pinTexts = [67,165,275].map(x => <SVGTextElement>Svg.child(this.g, "text", { class:'sim-text-pin', x:x, y:345}));
this.pinTexts = [67, 165, 275].map(x => <SVGTextElement>svg.child(this.g, "text", { class: 'sim-text-pin', x: x, y: 345 }));
this.buttonsOuter = []; this.buttons = [];
this.buttonsOuter.push(Svg.path(this.g, "sim-button-outer", "M82.1,232.6H25.9c-0.5,0-1-0.4-1-1v-56.2c0-0.5,0.4-1,1-1h56.2c0.5,0,1,0.4,1,1v56.2C83,232.2,82.6,232.6,82.1,232.6", "A"));
this.buttons.push(Svg.path(this.g, "sim-button", "M69.7,203.5c0,8.7-7,15.7-15.7,15.7s-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7S69.7,194.9,69.7,203.5"));
this.buttonsOuter.push(Svg.path(this.g, "sim-button-outer", "M474.3,232.6h-56.2c-0.5,0-1-0.4-1-1v-56.2c0-0.5,0.4-1,1-1h56.2c0.5,0,1,0.4,1,1v56.2C475.3,232.2,474.8,232.6,474.3,232.6", "B"));
this.buttons.push(Svg.path(this.g, "sim-button", "M461.9,203.5c0,8.7-7,15.7-15.7,15.7c-8.7,0-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7C454.9,187.8,461.9,194.9,461.9,203.5"));
this.buttonsOuter.push(Svg.child(this.g, "rect", {class:"sim-button-outer", x:417, y:250, width:58, height:58, rx:1, ry:1, title:"A+B"}));
this.buttons.push(Svg.child(this.g, "circle", {class:"sim-button", cx:446, cy:278, r:16.5}));
this.buttonsOuter.push(svg.path(this.g, "sim-button-outer", "M82.1,232.6H25.9c-0.5,0-1-0.4-1-1v-56.2c0-0.5,0.4-1,1-1h56.2c0.5,0,1,0.4,1,1v56.2C83,232.2,82.6,232.6,82.1,232.6", "A"));
this.buttons.push(svg.path(this.g, "sim-button", "M69.7,203.5c0,8.7-7,15.7-15.7,15.7s-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7S69.7,194.9,69.7,203.5"));
this.buttonsOuter.push(svg.path(this.g, "sim-button-outer", "M474.3,232.6h-56.2c-0.5,0-1-0.4-1-1v-56.2c0-0.5,0.4-1,1-1h56.2c0.5,0,1,0.4,1,1v56.2C475.3,232.2,474.8,232.6,474.3,232.6", "B"));
this.buttons.push(svg.path(this.g, "sim-button", "M461.9,203.5c0,8.7-7,15.7-15.7,15.7c-8.7,0-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7C454.9,187.8,461.9,194.9,461.9,203.5"));
this.buttonsOuter.push(svg.child(this.g, "rect", { class: "sim-button-outer", x: 417, y: 250, width: 58, height: 58, rx: 1, ry: 1, title: "A+B" }));
this.buttons.push(svg.child(this.g, "circle", { class: "sim-button", cx: 446, cy: 278, r: 16.5 }));
(<any>this.buttonsOuter[2]).style.visibility = 'hidden';
(<any>this.buttons[2]).style.visibility = 'hidden';
Svg.path(this.g, "sim-label", "M35.7,376.4c0-2.8,2.1-5.1,5.5-5.1c3.3,0,5.5,2.4,5.5,5.1v4.7c0,2.8-2.2,5.1-5.5,5.1c-3.3,0-5.5-2.4-5.5-5.1V376.4zM43.3,376.4c0-1.3-0.8-2.3-2.2-2.3c-1.3,0-2.1,1.1-2.1,2.3v4.7c0,1.2,0.8,2.3,2.1,2.3c1.3,0,2.2-1.1,2.2-2.3V376.4z");
Svg.path(this.g, "sim-label", "M136.2,374.1c2.8,0,3.4-0.8,3.4-2.5h2.9v14.3h-3.4v-9.5h-3V374.1z");
Svg.path(this.g, "sim-label", "M248.6,378.5c1.7-1,3-1.7,3-3.1c0-1.1-0.7-1.6-1.6-1.6c-1,0-1.8,0.6-1.8,2.1h-3.3c0-2.6,1.8-4.6,5.1-4.6c2.6,0,4.9,1.3,4.9,4.3c0,2.4-2.3,3.9-3.8,4.7c-2,1.3-2.5,1.8-2.5,2.9h6.1v2.7h-10C244.8,381.2,246.4,379.9,248.6,378.5z");
Svg.path(this.g, "sim-label", "M48.1,270.9l-0.6-1.7h-5.1l-0.6,1.7h-3.5l5.1-14.3h3.1l5.2,14.3H48.1z M45,260.7l-1.8,5.9h3.5L45,260.7z");
Svg.path(this.g, "sim-label", "M449.1,135.8h5.9c3.9,0,4.7,2.4,4.7,3.9c0,1.8-1.4,2.9-2.5,3.2c0.9,0,2.6,1.1,2.6,3.3c0,1.5-0.8,4-4.7,4h-6V135.8zM454.4,141.7c1.6,0,2-1,2-1.7c0-0.6-0.3-1.7-2-1.7h-2v3.4H454.4z M452.4,144.1v3.5h2.1c1.6,0,2-1,2-1.8c0-0.7-0.4-1.8-2-1.8H452.4z")
Svg.path(this.g, "sim-label", "M352.1,381.1c0,1.6,0.9,2.5,2.2,2.5c1.2,0,1.9-0.9,1.9-1.9c0-1.2-0.6-2-2.1-2h-1.3v-2.6h1.3c1.5,0,1.9-0.7,1.9-1.8c0-1.1-0.7-1.6-1.6-1.6c-1.4,0-1.8,0.8-1.8,2.1h-3.3c0-2.4,1.5-4.6,5.1-4.6c2.6,0,5,1.3,5,4c0,1.6-1,2.8-2.1,3.2c1.3,0.5,2.3,1.6,2.3,3.5c0,2.7-2.4,4.3-5.2,4.3c-3.5,0-5.5-2.1-5.5-5.1H352.1z")
Svg.path(this.g, "sim-label", "M368.5,385.9h-3.1l-5.1-14.3h3.5l3.1,10.1l3.1-10.1h3.6L368.5,385.9z")
Svg.path(this.g, "sim-label", "M444.4,378.3h7.4v2.5h-1.5c-0.6,3.3-3,5.5-7.1,5.5c-4.8,0-7.5-3.5-7.5-7.5c0-3.9,2.8-7.5,7.5-7.5c3.8,0,6.4,2.3,6.6,5h-3.5c-0.2-1.1-1.4-2.2-3.1-2.2c-2.7,0-4.1,2.3-4.1,4.7c0,2.5,1.4,4.7,4.4,4.7c2,0,3.2-1.2,3.4-2.7h-2.5V378.3z")
Svg.path(this.g, "sim-label", "M461.4,380.9v-9.3h3.3v14.3h-3.5l-5.2-9.2v9.2h-3.3v-14.3h3.5L461.4,380.9z")
Svg.path(this.g, "sim-label", "M472.7,371.6c4.8,0,7.5,3.5,7.5,7.2s-2.7,7.2-7.5,7.2h-5.3v-14.3H472.7z M470.8,374.4v8.6h1.8c2.7,0,4.2-2.1,4.2-4.3s-1.6-4.3-4.2-4.3H470.8z")
svg.path(this.g, "sim-label", "M35.7,376.4c0-2.8,2.1-5.1,5.5-5.1c3.3,0,5.5,2.4,5.5,5.1v4.7c0,2.8-2.2,5.1-5.5,5.1c-3.3,0-5.5-2.4-5.5-5.1V376.4zM43.3,376.4c0-1.3-0.8-2.3-2.2-2.3c-1.3,0-2.1,1.1-2.1,2.3v4.7c0,1.2,0.8,2.3,2.1,2.3c1.3,0,2.2-1.1,2.2-2.3V376.4z");
svg.path(this.g, "sim-label", "M136.2,374.1c2.8,0,3.4-0.8,3.4-2.5h2.9v14.3h-3.4v-9.5h-3V374.1z");
svg.path(this.g, "sim-label", "M248.6,378.5c1.7-1,3-1.7,3-3.1c0-1.1-0.7-1.6-1.6-1.6c-1,0-1.8,0.6-1.8,2.1h-3.3c0-2.6,1.8-4.6,5.1-4.6c2.6,0,4.9,1.3,4.9,4.3c0,2.4-2.3,3.9-3.8,4.7c-2,1.3-2.5,1.8-2.5,2.9h6.1v2.7h-10C244.8,381.2,246.4,379.9,248.6,378.5z");
svg.path(this.g, "sim-label", "M48.1,270.9l-0.6-1.7h-5.1l-0.6,1.7h-3.5l5.1-14.3h3.1l5.2,14.3H48.1z M45,260.7l-1.8,5.9h3.5L45,260.7z");
svg.path(this.g, "sim-label", "M449.1,135.8h5.9c3.9,0,4.7,2.4,4.7,3.9c0,1.8-1.4,2.9-2.5,3.2c0.9,0,2.6,1.1,2.6,3.3c0,1.5-0.8,4-4.7,4h-6V135.8zM454.4,141.7c1.6,0,2-1,2-1.7c0-0.6-0.3-1.7-2-1.7h-2v3.4H454.4z M452.4,144.1v3.5h2.1c1.6,0,2-1,2-1.8c0-0.7-0.4-1.8-2-1.8H452.4z")
svg.path(this.g, "sim-label", "M352.1,381.1c0,1.6,0.9,2.5,2.2,2.5c1.2,0,1.9-0.9,1.9-1.9c0-1.2-0.6-2-2.1-2h-1.3v-2.6h1.3c1.5,0,1.9-0.7,1.9-1.8c0-1.1-0.7-1.6-1.6-1.6c-1.4,0-1.8,0.8-1.8,2.1h-3.3c0-2.4,1.5-4.6,5.1-4.6c2.6,0,5,1.3,5,4c0,1.6-1,2.8-2.1,3.2c1.3,0.5,2.3,1.6,2.3,3.5c0,2.7-2.4,4.3-5.2,4.3c-3.5,0-5.5-2.1-5.5-5.1H352.1z")
svg.path(this.g, "sim-label", "M368.5,385.9h-3.1l-5.1-14.3h3.5l3.1,10.1l3.1-10.1h3.6L368.5,385.9z")
svg.path(this.g, "sim-label", "M444.4,378.3h7.4v2.5h-1.5c-0.6,3.3-3,5.5-7.1,5.5c-4.8,0-7.5-3.5-7.5-7.5c0-3.9,2.8-7.5,7.5-7.5c3.8,0,6.4,2.3,6.6,5h-3.5c-0.2-1.1-1.4-2.2-3.1-2.2c-2.7,0-4.1,2.3-4.1,4.7c0,2.5,1.4,4.7,4.4,4.7c2,0,3.2-1.2,3.4-2.7h-2.5V378.3z")
svg.path(this.g, "sim-label", "M461.4,380.9v-9.3h3.3v14.3h-3.5l-5.2-9.2v9.2h-3.3v-14.3h3.5L461.4,380.9z")
svg.path(this.g, "sim-label", "M472.7,371.6c4.8,0,7.5,3.5,7.5,7.2s-2.7,7.2-7.5,7.2h-5.3v-14.3H472.7z M470.8,374.4v8.6h1.8c2.7,0,4.2-2.1,4.2-4.3s-1.6-4.3-4.2-4.3H470.8z")
}
private attachEvents() {
Runtime.messagePosted = (msg) => {
switch(msg.type || '') {
switch (msg.type || '') {
case 'serial': this.flashSystemLed(); break;
case 'radiopacket': this.flashAntenna(); break;
}
@ -585,8 +587,8 @@ svg.sim.grayscale {
let tiltDecayer = 0;
this.element.addEventListener(pointerEvents.move, (ev: MouseEvent) => {
let state = this.board;
if (!state.accelerometer.isActive) return;
if (!state.accelerometer.isActive) return;
if (tiltDecayer) {
clearInterval(tiltDecayer);
tiltDecayer = 0;
@ -594,79 +596,79 @@ svg.sim.grayscale {
let ax = (ev.clientX - this.element.clientWidth / 2) / (this.element.clientWidth / 3);
let ay = (ev.clientY - this.element.clientHeight / 2) / (this.element.clientHeight / 3);
let x = - Math.max(- 1023, Math.min(1023, Math.floor(ax * 1023)));
let y = Math.max(- 1023, Math.min(1023, Math.floor(ay * 1023)));
let z2 = 1023*1023 - x * x - y * y;
let z = Math.floor((z2 > 0 ? -1 : 1)* Math.sqrt(Math.abs(z2)));
state.accelerometer.update(x,y,z);
let z2 = 1023 * 1023 - x * x - y * y;
let z = Math.floor((z2 > 0 ? -1 : 1) * Math.sqrt(Math.abs(z2)));
state.accelerometer.update(x, y, z);
this.updateTilt();
}, false);
this.element.addEventListener(pointerEvents.leave, (ev: MouseEvent) => {
let state = this.board;
if (!state.accelerometer.isActive) return;
if (!tiltDecayer) {
tiltDecayer = setInterval(() => {
let accx = state.accelerometer.getX(MicroBitCoordinateSystem.RAW);
accx = Math.floor(Math.abs(accx) * 0.85) * (accx > 0 ? 1 : -1);
let accy = state.accelerometer.getY(MicroBitCoordinateSystem.RAW);
accy = Math.floor(Math.abs(accy) * 0.85) * (accy > 0 ? 1 : -1);
let accz = -Math.sqrt(Math.max(0, 1023*1023 - accx*accx - accy*accy));
let accz = -Math.sqrt(Math.max(0, 1023 * 1023 - accx * accx - accy * accy));
if (Math.abs(accx) <= 24 && Math.abs(accy) <= 24) {
clearInterval(tiltDecayer);
tiltDecayer = 0;
clearInterval(tiltDecayer);
tiltDecayer = 0;
accx = 0;
accy = 0;
accz = -1023;
}
accz = -1023;
}
state.accelerometer.update(accx, accy, accz);
this.updateTilt();
}, 50)
this.updateTilt();
}, 50)
}
}, false);
this.pins.forEach((pin, index) => {
if (!this.board.pins[index]) return;
let pt = this.element.createSVGPoint();
Svg.buttonEvents(pin,
svg.buttonEvents(pin,
// move
ev => {
let state = this.board;
let pin = state.pins[index];
let svgpin = this.pins[index];
if (pin.mode & PinMode.Input) {
let cursor = Svg.cursorPoint(pt, this.element, ev);
let cursor = svg.cursorPoint(pt, this.element, ev);
let v = (400 - cursor.y) / 40 * 1023
pin.value = Math.max(0, Math.min(1023, Math.floor(v)));
}
this.updatePin(pin,index);
this.updatePin(pin, index);
},
// start
ev => {
let state = this.board;
let pin = state.pins[index];
let svgpin = this.pins[index];
Svg.addClass(svgpin, 'touched');
svg.addClass(svgpin, "touched");
if (pin.mode & PinMode.Input) {
let cursor = Svg.cursorPoint(pt, this.element, ev);
let cursor = svg.cursorPoint(pt, this.element, ev);
let v = (400 - cursor.y) / 40 * 1023
pin.value = Math.max(0, Math.min(1023, Math.floor(v)));
}
this.updatePin(pin,index);
this.updatePin(pin, index);
},
// stop
(ev: MouseEvent) => {
let state = this.board;
let pin = state.pins[index];
let svgpin = this.pins[index];
Svg.removeClass(svgpin, 'touched');
svg.removeClass(svgpin, "touched");
this.updatePin(pin, index);
return false;
});
});
})
this.pins.slice(0,3).forEach((btn, index) => {
this.pins.slice(0, 3).forEach((btn, index) => {
btn.addEventListener(pointerEvents.down, ev => {
let state = this.board;
state.pins[index].touched = true;
@ -682,56 +684,56 @@ svg.sim.grayscale {
state.pins[index].touched = false;
this.updatePin(state.pins[index], index);
this.board.bus.queue(state.pins[index].id, DAL.MICROBIT_BUTTON_EVT_CLICK);
})
})
})
this.buttonsOuter.slice(0,2).forEach((btn, index) => {
this.buttonsOuter.slice(0, 2).forEach((btn, index) => {
btn.addEventListener(pointerEvents.down, ev => {
let state = this.board;
state.buttons[index].pressed = true;
Svg.fill(this.buttons[index], this.props.theme.buttonDown);
svg.fill(this.buttons[index], this.props.theme.buttonDown);
})
btn.addEventListener(pointerEvents.leave, ev => {
let state = this.board;
state.buttons[index].pressed = false;
Svg.fill(this.buttons[index], this.props.theme.buttonUp);
svg.fill(this.buttons[index], this.props.theme.buttonUp);
})
btn.addEventListener(pointerEvents.up, ev => {
let state = this.board;
state.buttons[index].pressed = false;
Svg.fill(this.buttons[index], this.props.theme.buttonUp);
svg.fill(this.buttons[index], this.props.theme.buttonUp);
this.board.bus.queue(state.buttons[index].id, DAL.MICROBIT_BUTTON_EVT_CLICK);
})
})
this.buttonsOuter[2].addEventListener(pointerEvents.down, ev => {
let state = this.board;
state.buttons[0].pressed = true;
state.buttons[1].pressed = true;
state.buttons[2].pressed = true;
Svg.fill(this.buttons[0], this.props.theme.buttonDown);
Svg.fill(this.buttons[1], this.props.theme.buttonDown);
Svg.fill(this.buttons[2], this.props.theme.buttonDown);
})
let state = this.board;
state.buttons[0].pressed = true;
state.buttons[1].pressed = true;
state.buttons[2].pressed = true;
svg.fill(this.buttons[0], this.props.theme.buttonDown);
svg.fill(this.buttons[1], this.props.theme.buttonDown);
svg.fill(this.buttons[2], this.props.theme.buttonDown);
})
this.buttonsOuter[2].addEventListener(pointerEvents.leave, ev => {
let state = this.board;
state.buttons[0].pressed = false;
state.buttons[1].pressed = false;
state.buttons[2].pressed = false;
Svg.fill(this.buttons[0], this.props.theme.buttonUp);
Svg.fill(this.buttons[1], this.props.theme.buttonUp);
Svg.fill(this.buttons[2], this.props.theme.virtualButtonUp);
let state = this.board;
state.buttons[0].pressed = false;
state.buttons[1].pressed = false;
state.buttons[2].pressed = false;
svg.fill(this.buttons[0], this.props.theme.buttonUp);
svg.fill(this.buttons[1], this.props.theme.buttonUp);
svg.fill(this.buttons[2], this.props.theme.virtualButtonUp);
})
this.buttonsOuter[2].addEventListener(pointerEvents.up, ev => {
let state = this.board;
state.buttons[0].pressed = false;
state.buttons[1].pressed = false;
state.buttons[2].pressed = false;
Svg.fill(this.buttons[0], this.props.theme.buttonUp);
Svg.fill(this.buttons[1], this.props.theme.buttonUp);
Svg.fill(this.buttons[2], this.props.theme.virtualButtonUp);
this.board.bus.queue(state.buttons[2].id, DAL.MICROBIT_BUTTON_EVT_CLICK);
})
let state = this.board;
state.buttons[0].pressed = false;
state.buttons[1].pressed = false;
state.buttons[2].pressed = false;
svg.fill(this.buttons[0], this.props.theme.buttonUp);
svg.fill(this.buttons[1], this.props.theme.buttonUp);
svg.fill(this.buttons[2], this.props.theme.virtualButtonUp);
this.board.bus.queue(state.buttons[2].id, DAL.MICROBIT_BUTTON_EVT_CLICK);
})
}
}
}

56
tslint.json Normal file
View File

@ -0,0 +1,56 @@
{
"rules": {
"class-name": true,
"comment-format": [
true
],
"indent": [
true,
"spaces"
],
"no-duplicate-variable": true,
"no-eval": true,
"no-internal-module": true,
"no-trailing-whitespace": true,
"no-var-keyword": true,
"one-line": [
true,
"check-open-brace",
"check-whitespace"
],
"quotemark": [
true,
"double"
],
"semicolon": [
false,
"always"
],
"triple-equals": [
false,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"variable-name": [
true,
"ban-keywords"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}