pxt-calliope/sim.js

2848 lines
190 KiB
JavaScript
Raw Normal View History

2017-08-19 17:16:35 +02:00
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
var pxsim;
(function (pxsim) {
var DalBoard = (function (_super) {
__extends(DalBoard, _super);
function DalBoard() {
_super.call(this);
// components
this.fileSystem = new pxsim.FileSystemState();
this.builtinParts["ledmatrix"] = this.ledMatrixState = new pxsim.LedMatrixState(pxsim.runtime);
this.builtinParts["buttonpair"] = this.buttonPairState = new pxsim.ButtonPairState({
ID_BUTTON_A: 1 /* MICROBIT_ID_BUTTON_A */,
ID_BUTTON_B: 2 /* MICROBIT_ID_BUTTON_B */,
ID_BUTTON_AB: 26 /* MICROBIT_ID_BUTTON_AB */,
BUTTON_EVT_UP: 2 /* MICROBIT_BUTTON_EVT_UP */,
BUTTON_EVT_CLICK: 3 /* MICROBIT_BUTTON_EVT_CLICK */
});
this.builtinParts["edgeconnector"] = this.edgeConnectorState = new pxsim.EdgeConnectorState({
pins: [
7 /* MICROBIT_ID_IO_P0 */,
8 /* MICROBIT_ID_IO_P1 */,
9 /* MICROBIT_ID_IO_P2 */,
10 /* MICROBIT_ID_IO_P3 */,
11 /* MICROBIT_ID_IO_P4 */,
12 /* MICROBIT_ID_IO_P5 */,
13 /* MICROBIT_ID_IO_P6 */,
14 /* MICROBIT_ID_IO_P7 */,
15 /* MICROBIT_ID_IO_P8 */,
16 /* MICROBIT_ID_IO_P9 */,
17 /* MICROBIT_ID_IO_P10 */,
18 /* MICROBIT_ID_IO_P11 */,
19 /* MICROBIT_ID_IO_P12 */,
20 /* MICROBIT_ID_IO_P13 */,
21 /* MICROBIT_ID_IO_P14 */,
22 /* MICROBIT_ID_IO_P15 */,
23 /* MICROBIT_ID_IO_P16 */,
0,
0,
24 /* MICROBIT_ID_IO_P19 */,
25 /* MICROBIT_ID_IO_P20 */,
50 /* MICROBIT_ID_IO_P21 */
],
servos: {
"P0": 19 /* MICROBIT_ID_IO_P12 */,
"P1": 7 /* MICROBIT_ID_IO_P0 */,
"P2": 8 /* MICROBIT_ID_IO_P1 */,
"P3": 23 /* MICROBIT_ID_IO_P16 */
}
});
this.builtinParts["radio"] = this.radioState = new pxsim.RadioState(pxsim.runtime);
this.builtinParts["accelerometer"] = this.accelerometerState = new pxsim.AccelerometerState(pxsim.runtime);
this.builtinParts["serial"] = this.serialState = new pxsim.SerialState();
this.builtinParts["thermometer"] = this.thermometerState = new pxsim.ThermometerState();
this.builtinParts["lightsensor"] = this.lightSensorState = new pxsim.LightSensorState();
this.builtinParts["compass"] = this.compassState = new pxsim.CompassState();
this.builtinParts["neopixel"] = this.neopixelState = new pxsim.NeoPixelState();
this.builtinParts["speaker"] = this.speakerState = new pxsim.SpeakerState();
this.builtinParts["microservo"] = this.edgeConnectorState;
this.builtinVisuals["buttonpair"] = function () { return new pxsim.visuals.ButtonPairView(); };
this.builtinVisuals["ledmatrix"] = function () { return new pxsim.visuals.LedMatrixView(); };
this.builtinVisuals["neopixel"] = function () { return new pxsim.visuals.NeoPixelView(); };
this.builtinVisuals["microservo"] = function () { return new pxsim.visuals.MicroServoView(); };
this.builtinPartVisuals["buttonpair"] = function (xy) { return pxsim.visuals.mkBtnSvg(xy); };
this.builtinPartVisuals["ledmatrix"] = function (xy) { return pxsim.visuals.mkLedMatrixSvg(xy, 8, 8); };
this.builtinPartVisuals["neopixel"] = function (xy) { return pxsim.visuals.mkNeoPixelPart(xy); };
this.builtinPartVisuals["microservo"] = function (xy) { return pxsim.visuals.mkMicroServoPart(xy); };
}
DalBoard.prototype.receiveMessage = function (msg) {
if (!pxsim.runtime || pxsim.runtime.dead)
return;
switch (msg.type || "") {
case "eventbus":
var ev = msg;
this.bus.queue(ev.id, ev.eventid, ev.value);
break;
case "serial":
var data = msg.data || "";
this.serialState.recieveData(data);
break;
case "radiopacket":
var packet = msg;
this.radioState.recievePacket(packet);
break;
}
};
DalBoard.prototype.initAsync = function (msg) {
_super.prototype.initAsync.call(this, msg);
var options = (msg.options || {});
var boardDef = msg.boardDefinition;
var cmpsList = msg.parts;
var cmpDefs = msg.partDefinitions || {};
var fnArgs = msg.fnArgs;
var opts = {
state: this,
boardDef: boardDef,
partsList: cmpsList,
partDefs: cmpDefs,
fnArgs: fnArgs,
maxWidth: "100%",
maxHeight: "100%",
};
var viewHost = new pxsim.visuals.BoardHost(pxsim.visuals.mkBoardView({
visual: boardDef.visual
}), opts);
document.body.innerHTML = ""; // clear children
document.body.appendChild(viewHost.getView());
return Promise.resolve();
};
return DalBoard;
}(pxsim.CoreBoard));
pxsim.DalBoard = DalBoard;
function initRuntimeWithDalBoard() {
pxsim.U.assert(!pxsim.runtime.board);
var b = new DalBoard();
pxsim.runtime.board = b;
pxsim.runtime.postError = function (e) {
pxsim.led.setBrightness(255);
var img = board().ledMatrixState.image;
img.clear();
img.set(0, 4, 255);
img.set(1, 3, 255);
img.set(2, 3, 255);
img.set(3, 3, 255);
img.set(4, 4, 255);
img.set(0, 0, 255);
img.set(1, 0, 255);
img.set(0, 1, 255);
img.set(1, 1, 255);
img.set(3, 0, 255);
img.set(4, 0, 255);
img.set(3, 1, 255);
img.set(4, 1, 255);
pxsim.runtime.updateDisplay();
};
}
pxsim.initRuntimeWithDalBoard = initRuntimeWithDalBoard;
if (!pxsim.initCurrentRuntime) {
pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
}
function board() {
return pxsim.runtime.board;
}
pxsim.board = board;
})(pxsim || (pxsim = {}));
/// <reference path="../node_modules/pxt-core/typings/globals/bluebird/index.d.ts"/>
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
/// <reference path="../node_modules/pxt-core/built/pxtrunner.d.ts"/>
//HACK: allows instructions.html to access pxtblocks without requiring simulator.html to import blocks as well
if (!window.pxt)
window.pxt = {};
var pxtrunner = pxt.runner;
var pxtdocs = pxt.docs;
var pxsim;
(function (pxsim) {
var instructions;
(function (instructions) {
function drawInstructions() {
pxsim.visuals.mkBoardView = function (opts) {
return new pxsim.visuals.MicrobitBoardSvg({
runtime: pxsim.runtime,
theme: pxsim.visuals.randomTheme(),
disableTilt: false,
wireframe: opts.wireframe,
});
};
var getQsVal = pxsim.parseQueryString();
//project name
var name = getQsVal("name") || "Untitled";
// board def
var boardDef = JSON.parse(getQsVal("board"));
//parts list
var parts = (getQsVal("parts") || "").split(" ");
parts.sort();
// parts definitions
var partDefinitions = JSON.parse(getQsVal("partdefs") || "{}");
//fn args
var fnArgs = JSON.parse((getQsVal("fnArgs") || "{}"));
//project code
var tsCode = getQsVal("code");
var tsPackage = getQsVal("package") || "";
var codeSpinnerDiv = document.getElementById("proj-code-spinner");
var codeContainerDiv = document.getElementById("proj-code-container");
if (tsCode) {
//we use the docs renderer to decompile the code to blocks and render it
//TODO: render the blocks code directly
var md = "```blocks\n" + tsCode + "\n```\n```package\n" + tsPackage + "\n```\n";
pxtdocs.requireMarked = function () { return window.marked; };
pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
.done(function () {
var codeSvg = $("#proj-code-container svg");
if (codeSvg.length > 0) {
//code rendered successfully as blocks
codeSvg.css("width", "inherit");
codeSvg.css("height", "inherit");
//takes the svg out of the wrapper markdown
codeContainerDiv.innerHTML = "";
codeContainerDiv.appendChild(codeSvg[0]);
}
else {
//code failed to convert to blocks, display as typescript instead
codeContainerDiv.innerText = tsCode;
}
$(codeContainerDiv).show();
$(codeSpinnerDiv).hide();
});
}
if (name)
$("#proj-title").text(name);
//init runtime
if (!pxsim.initCurrentRuntime)
pxsim.initCurrentRuntime = pxsim.initRuntimeWithDalBoard;
instructions.renderParts({
name: name,
boardDef: boardDef,
parts: parts,
partDefinitions: partDefinitions,
fnArgs: fnArgs
});
}
instructions.drawInstructions = drawInstructions;
})(instructions = pxsim.instructions || (pxsim.instructions = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function onGesture(gesture, handler) {
var b = pxsim.board().accelerometerState;
b.accelerometer.activate();
if (gesture == 11 && !b.useShake) {
b.useShake = true;
pxsim.runtime.queueDisplayUpdate();
}
pxsim.pxtcore.registerWithDal(27 /* MICROBIT_ID_GESTURE */, gesture, handler);
}
input.onGesture = onGesture;
function acceleration(dimension) {
var b = pxsim.board().accelerometerState;
var acc = b.accelerometer;
acc.activate();
switch (dimension) {
case 0: return acc.getX();
case 1: return acc.getY();
case 2: return acc.getZ();
default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
}
}
input.acceleration = acceleration;
function rotation(kind) {
var b = pxsim.board().accelerometerState;
var acc = b.accelerometer;
acc.activate();
var x = acc.getX(pxsim.MicroBitCoordinateSystem.NORTH_EAST_DOWN);
var y = acc.getX(pxsim.MicroBitCoordinateSystem.NORTH_EAST_DOWN);
var z = acc.getX(pxsim.MicroBitCoordinateSystem.NORTH_EAST_DOWN);
var roll = Math.atan2(y, z);
var pitch = Math.atan(-x / (y * Math.sin(roll) + z * Math.cos(roll)));
var r = 0;
switch (kind) {
case 0:
r = pitch;
break;
case 1:
r = roll;
break;
}
return Math.floor(r / Math.PI * 180);
}
input.rotation = rotation;
function setAccelerometerRange(range) {
var b = pxsim.board().accelerometerState;
b.accelerometer.setSampleRange(range);
}
input.setAccelerometerRange = setAccelerometerRange;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
/**
* Co-ordinate systems that can be used.
* RAW: Unaltered data. Data will be returned directly from the accelerometer.
*
* SIMPLE_CARTESIAN: Data will be returned based on an easy to understand alignment, consistent with the cartesian system taught in schools.
* When held upright, facing the user:
*
* /
* +--------------------+ z
* | |
* | ..... |
* | * ..... * |
* ^ | ..... |
* | | |
* y +--------------------+ x-->
*
*
* NORTH_EAST_DOWN: Data will be returned based on the industry convention of the North East Down (NED) system.
* When held upright, facing the user:
*
* z
* +--------------------+ /
* | |
* | ..... |
* | * ..... * |
* ^ | ..... |
* | | |
* x +--------------------+ y-->
*
*/
(function (MicroBitCoordinateSystem) {
MicroBitCoordinateSystem[MicroBitCoordinateSystem["RAW"] = 0] = "RAW";
MicroBitCoordinateSystem[MicroBitCoordinateSystem["SIMPLE_CARTESIAN"] = 1] = "SIMPLE_CARTESIAN";
MicroBitCoordinateSystem[MicroBitCoordinateSystem["NORTH_EAST_DOWN"] = 2] = "NORTH_EAST_DOWN";
})(pxsim.MicroBitCoordinateSystem || (pxsim.MicroBitCoordinateSystem = {}));
var MicroBitCoordinateSystem = pxsim.MicroBitCoordinateSystem;
var Accelerometer = (function () {
function Accelerometer(runtime) {
this.runtime = runtime;
this.sigma = 0; // the number of ticks that the instantaneous gesture has been stable.
this.lastGesture = 0; // the last, stable gesture recorded.
this.currentGesture = 0; // the instantaneous, unfiltered gesture detected.
this.sample = { x: 0, y: 0, z: -1023 };
this.shake = { x: false, y: false, z: false, count: 0, shaken: 0, timer: 0 }; // State information needed to detect shake events.
this.isActive = false;
this.sampleRange = 2;
this.id = 4 /* MICROBIT_ID_ACCELEROMETER */;
}
Accelerometer.prototype.setSampleRange = function (range) {
this.activate();
this.sampleRange = Math.max(1, Math.min(8, range));
};
Accelerometer.prototype.activate = function () {
if (!this.isActive) {
this.isActive = true;
this.runtime.queueDisplayUpdate();
}
};
/**
* Reads the acceleration data from the accelerometer, and stores it in our buffer.
* This is called by the tick() member function, if the interrupt is set!
*/
Accelerometer.prototype.update = function (x, y, z) {
// read MSB values...
this.sample.x = Math.floor(x);
this.sample.y = Math.floor(y);
this.sample.z = Math.floor(z);
// Update gesture tracking
this.updateGesture();
// Indicate that a new sample is available
pxsim.board().bus.queue(this.id, 1 /* MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE */);
};
Accelerometer.prototype.instantaneousAccelerationSquared = function () {
// Use pythagoras theorem to determine the combined force acting on the device.
return this.sample.x * this.sample.x + this.sample.y * this.sample.y + this.sample.z * this.sample.z;
};
/**
* Service function. Determines the best guess posture of the device based on instantaneous data.
* This makes no use of historic data (except for shake), and forms this input to the filter implemented in updateGesture().
*
* @return A best guess of the current posture of the device, based on instantaneous data.
*/
Accelerometer.prototype.instantaneousPosture = function () {
var force = this.instantaneousAccelerationSquared();
var shakeDetected = false;
// Test for shake events.
// We detect a shake by measuring zero crossings in each axis. In other words, if we see a strong acceleration to the left followed by
// a string acceleration to the right, then we can infer a shake. Similarly, we can do this for each acxis (left/right, up/down, in/out).
//
// If we see enough zero crossings in succession (MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD), then we decide that the device
// has been shaken.
if ((this.getX() < -400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && this.shake.x) || (this.getX() > 400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && !this.shake.x)) {
shakeDetected = true;
this.shake.x = !this.shake.x;
}
if ((this.getY() < -400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && this.shake.y) || (this.getY() > 400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && !this.shake.y)) {
shakeDetected = true;
this.shake.y = !this.shake.y;
}
if ((this.getZ() < -400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && this.shake.z) || (this.getZ() > 400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && !this.shake.z)) {
shakeDetected = true;
this.shake.z = !this.shake.z;
}
if (shakeDetected && this.shake.count < 4 /* MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD */ && ++this.shake.count == 4 /* MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD */)
this.shake.shaken = 1;
if (++this.shake.timer >= 10 /* MICROBIT_ACCELEROMETER_SHAKE_DAMPING */) {
this.shake.timer = 0;
if (this.shake.count > 0) {
if (--this.shake.count == 0)
this.shake.shaken = 0;
}
}
if (this.shake.shaken)
return 12 /* MICROBIT_ACCELEROMETER_EVT_SHAKE */;
var sq = function (n) { return n * n; };
if (force < sq(400 /* MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE */))
return 7 /* MICROBIT_ACCELEROMETER_EVT_FREEFALL */;
// TODO: fix this
//if (force > sq(DAL.MICROBIT_ACCELEROMETER_3G_TOLERANCE))
// return DAL.MICROBIT_ACCELEROMETER_EVT_3G;
if (force > sq(6144 /* MICROBIT_ACCELEROMETER_6G_TOLERANCE */))
return 10 /* MICROBIT_ACCELEROMETER_EVT_6G */;
if (force > sq(8192 /* MICROBIT_ACCELEROMETER_8G_TOLERANCE */))
return 11 /* MICROBIT_ACCELEROMETER_EVT_8G */;
// Determine our posture.
if (this.getX() < (-1000 + 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
return 3 /* MICROBIT_ACCELEROMETER_EVT_TILT_LEFT */;
if (this.getX() > (1000 - 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
return 4 /* MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT */;
if (this.getY() < (-1000 + 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
return 2 /* MICROBIT_ACCELEROMETER_EVT_TILT_DOWN */;
if (this.getY() > (1000 - 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
return 1 /* MICROBIT_ACCELEROMETER_EVT_TILT_UP */;
if (this.getZ() < (-1000 + 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
return 6 /* MICROBIT_ACCELEROMETER_EVT_FACE_DOWN */;
if (this.getZ() > (1000 - 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
return 5 /* MICROBIT_ACCELEROMETER_EVT_FACE_UP */;
return 0;
};
Accelerometer.prototype.updateGesture = function () {
// Determine what it looks like we're doing based on the latest sample...
var g = this.instantaneousPosture();
// Perform some low pass filtering to reduce jitter from any detected effects
if (g == this.currentGesture) {
if (this.sigma < 5 /* MICROBIT_ACCELEROMETER_GESTURE_DAMPING */)
this.sigma++;
}
else {
this.currentGesture = g;
this.sigma = 0;
}
// If we've reached threshold, update our record and raise the relevant event...
if (this.currentGesture != this.lastGesture && this.sigma >= 5 /* MICROBIT_ACCELEROMETER_GESTURE_DAMPING */) {
this.lastGesture = this.currentGesture;
pxsim.board().bus.queue(27 /* MICROBIT_ID_GESTURE */, this.lastGesture);
}
};
/**
* Reads the X axis value of the latest update from the accelerometer.
* @param system The coordinate system to use. By default, a simple cartesian system is provided.
* @return The force measured in the X axis, in milli-g.
*
* Example:
* @code
* uBit.accelerometer.getX();
* uBit.accelerometer.getX(RAW);
* @endcode
*/
Accelerometer.prototype.getX = function (system) {
if (system === void 0) { system = MicroBitCoordinateSystem.SIMPLE_CARTESIAN; }
this.activate();
switch (system) {
case MicroBitCoordinateSystem.SIMPLE_CARTESIAN:
return -this.sample.x;
case MicroBitCoordinateSystem.NORTH_EAST_DOWN:
return this.sample.y;
//case MicroBitCoordinateSystem.SIMPLE_CARTESIAN.RAW:
default:
return this.sample.x;
}
};
/**
* Reads the Y axis value of the latest update from the accelerometer.
* @param system The coordinate system to use. By default, a simple cartesian system is provided.
* @return The force measured in the Y axis, in milli-g.
*
* Example:
* @code
* uBit.accelerometer.getY();
* uBit.accelerometer.getY(RAW);
* @endcode
*/
Accelerometer.prototype.getY = function (system) {
if (system === void 0) { system = MicroBitCoordinateSystem.SIMPLE_CARTESIAN; }
this.activate();
switch (system) {
case MicroBitCoordinateSystem.SIMPLE_CARTESIAN:
return -this.sample.y;
case MicroBitCoordinateSystem.NORTH_EAST_DOWN:
return -this.sample.x;
//case RAW:
default:
return this.sample.y;
}
};
/**
* Reads the Z axis value of the latest update from the accelerometer.
* @param system The coordinate system to use. By default, a simple cartesian system is provided.
* @return The force measured in the Z axis, in milli-g.
*
* Example:
* @code
* uBit.accelerometer.getZ();
* uBit.accelerometer.getZ(RAW);
* @endcode
*/
Accelerometer.prototype.getZ = function (system) {
if (system === void 0) { system = MicroBitCoordinateSystem.SIMPLE_CARTESIAN; }
this.activate();
switch (system) {
case MicroBitCoordinateSystem.NORTH_EAST_DOWN:
return -this.sample.z;
//case MicroBitCoordinateSystem.SIMPLE_CARTESIAN:
//case MicroBitCoordinateSystem.RAW:
default:
return this.sample.z;
}
};
/**
* Provides a rotation compensated pitch of the device, based on the latest update from the accelerometer.
* @return The pitch of the device, in degrees.
*
* Example:
* @code
* uBit.accelerometer.getPitch();
* @endcode
*/
Accelerometer.prototype.getPitch = function () {
this.activate();
return Math.floor((360 * this.getPitchRadians()) / (2 * Math.PI));
};
Accelerometer.prototype.getPitchRadians = function () {
this.recalculatePitchRoll();
return this.pitch;
};
/**
* Provides a rotation compensated roll of the device, based on the latest update from the accelerometer.
* @return The roll of the device, in degrees.
*
* Example:
* @code
* uBit.accelerometer.getRoll();
* @endcode
*/
Accelerometer.prototype.getRoll = function () {
this.activate();
return Math.floor((360 * this.getRollRadians()) / (2 * Math.PI));
};
Accelerometer.prototype.getRollRadians = function () {
this.recalculatePitchRoll();
return this.roll;
};
/**
* Recalculate roll and pitch values for the current sample.
* We only do this at most once per sample, as the necessary trigonemteric functions are rather
* heavyweight for a CPU without a floating point unit...
*/
Accelerometer.prototype.recalculatePitchRoll = function () {
var x = this.getX(MicroBitCoordinateSystem.NORTH_EAST_DOWN);
var y = this.getY(MicroBitCoordinateSystem.NORTH_EAST_DOWN);
var z = this.getZ(MicroBitCoordinateSystem.NORTH_EAST_DOWN);
this.roll = Math.atan2(y, z);
this.pitch = Math.atan(-x / (y * Math.sin(this.roll) + z * Math.cos(this.roll)));
};
return Accelerometer;
}());
pxsim.Accelerometer = Accelerometer;
var AccelerometerState = (function () {
function AccelerometerState(runtime) {
this.useShake = false;
this.accelerometer = new Accelerometer(runtime);
}
return AccelerometerState;
}());
pxsim.AccelerometerState = AccelerometerState;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function onButtonPressed(button, handler) {
var b = pxsim.board().buttonPairState;
if (button == b.props.ID_BUTTON_AB && !b.usesButtonAB) {
b.usesButtonAB = true;
pxsim.runtime.queueDisplayUpdate();
}
pxsim.pxtcore.registerWithDal(button, 3 /* MICROBIT_BUTTON_EVT_CLICK */, handler);
}
input.onButtonPressed = onButtonPressed;
function buttonIsPressed(button) {
var b = pxsim.board().buttonPairState;
if (button == b.abBtn.id && !b.usesButtonAB) {
b.usesButtonAB = true;
pxsim.runtime.queueDisplayUpdate();
}
if (button == b.aBtn.id)
return b.aBtn.pressed;
if (button == b.bBtn.id)
return b.bBtn.pressed;
return b.abBtn.pressed || (b.aBtn.pressed && b.bBtn.pressed);
}
input.buttonIsPressed = buttonIsPressed;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function compassHeading() {
var b = pxsim.board().compassState;
if (!b.usesHeading) {
b.usesHeading = true;
pxsim.runtime.queueDisplayUpdate();
}
return b.heading;
}
input.compassHeading = compassHeading;
function magneticForce() {
// TODO
return 0;
}
input.magneticForce = magneticForce;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function onPinPressed(pinId, handler) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.isTouched();
pxsim.pxtcore.registerWithDal(pin.id, 3 /* MICROBIT_BUTTON_EVT_CLICK */, handler);
}
input.onPinPressed = onPinPressed;
function onPinReleased(pinId, handler) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.isTouched();
pxsim.pxtcore.registerWithDal(pin.id, 2 /* MICROBIT_BUTTON_EVT_UP */, handler);
}
input.onPinReleased = onPinReleased;
function pinIsPressed(pinId) {
var pin = pxsim.getPin(pinId);
if (!pin)
return false;
return pin.isTouched();
}
input.pinIsPressed = pinIsPressed;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
function getPin(id) {
return pxsim.board().edgeConnectorState.getPin(id);
}
pxsim.getPin = getPin;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var pins;
(function (pins_1) {
function digitalReadPin(pinId) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.mode = pxsim.PinFlags.Digital | pxsim.PinFlags.Input;
return pin.value > 100 ? 1 : 0;
}
pins_1.digitalReadPin = digitalReadPin;
function digitalWritePin(pinId, value) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.mode = pxsim.PinFlags.Digital | pxsim.PinFlags.Output;
pin.value = value > 0 ? 1023 : 0;
pxsim.runtime.queueDisplayUpdate();
}
pins_1.digitalWritePin = digitalWritePin;
function setPull(pinId, pull) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.pull = pull;
}
pins_1.setPull = setPull;
function analogReadPin(pinId) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Input;
return pin.value || 0;
}
pins_1.analogReadPin = analogReadPin;
function analogWritePin(pinId, value) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Output;
pin.value = value ? 1 : 0;
pxsim.runtime.queueDisplayUpdate();
}
pins_1.analogWritePin = analogWritePin;
function analogSetPeriod(pinId, micros) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Output;
pin.period = micros;
pxsim.runtime.queueDisplayUpdate();
}
pins_1.analogSetPeriod = analogSetPeriod;
function servoWritePin(pinId, value) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
analogSetPeriod(pinId, 20000);
pin.servoAngle = Math.max(0, Math.min(180, value));
}
pins_1.servoWritePin = servoWritePin;
function servoSetPulse(pinId, micros) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
// TODO
}
pins_1.servoSetPulse = servoSetPulse;
function analogSetPitchPin(pinId) {
var pin = pxsim.getPin(pinId);
if (!pin)
return;
pxsim.board().edgeConnectorState.pins.filter(function (p) { return !!p; }).forEach(function (p) { return p.pitch = false; });
pin.pitch = true;
}
pins_1.analogSetPitchPin = analogSetPitchPin;
function analogPitch(frequency, ms) {
// update analog output
var pins = pxsim.board().edgeConnectorState.pins;
var pin = pins.filter(function (pin) { return !!pin && pin.pitch; })[0] || pins[0];
pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Output;
if (frequency <= 0) {
pin.value = 0;
pin.period = 0;
}
else {
pin.value = 512;
pin.period = 1000000 / frequency;
}
pxsim.runtime.queueDisplayUpdate();
var cb = pxsim.getResume();
pxsim.AudioContextManager.tone(frequency, 1);
if (ms <= 0)
cb();
else {
setTimeout(function () {
pxsim.AudioContextManager.stop();
pin.value = 0;
pin.period = 0;
pin.mode = pxsim.PinFlags.Unused;
pxsim.runtime.queueDisplayUpdate();
cb();
}, ms);
}
}
pins_1.analogPitch = analogPitch;
})(pins = pxsim.pins || (pxsim.pins = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var files;
(function (files) {
function appendLine(filename, text) {
var b = pxsim.board();
b.fileSystem.append(filename, text + "\r\n");
}
files.appendLine = appendLine;
function appendString(filename, text) {
var b = pxsim.board();
b.fileSystem.append(filename, text);
}
files.appendString = appendString;
function appendNumber(filename, value) {
var b = pxsim.board();
b.fileSystem.append(filename, value.toString());
}
files.appendNumber = appendNumber;
function remove(filename) {
var b = pxsim.board();
b.fileSystem.remove(filename);
}
files.remove = remove;
})(files = pxsim.files || (pxsim.files = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
(function (DisplayMode) {
DisplayMode[DisplayMode["bw"] = 0] = "bw";
DisplayMode[DisplayMode["greyscale"] = 1] = "greyscale";
})(pxsim.DisplayMode || (pxsim.DisplayMode = {}));
var DisplayMode = pxsim.DisplayMode;
var LedMatrixState = (function () {
function LedMatrixState(runtime) {
this.image = createInternalImage(5);
this.brigthness = 255;
this.displayMode = DisplayMode.bw;
this.font = createFont();
this.animationQ = new pxsim.AnimationQueue(runtime);
}
return LedMatrixState;
}());
pxsim.LedMatrixState = LedMatrixState;
var Image = (function (_super) {
__extends(Image, _super);
function Image(width, data) {
_super.call(this);
this.width = width;
this.data = data;
}
Image.prototype.print = function () {
console.log("Image id:" + this.id + " refs:" + this.refcnt + " size:" + this.width + "x" + Image.height);
};
Image.prototype.get = function (x, y) {
if (x < 0 || x >= this.width || y < 0 || y >= 5)
return 0;
return this.data[y * this.width + x];
};
Image.prototype.set = function (x, y, v) {
if (x < 0 || x >= this.width || y < 0 || y >= 5)
return;
this.data[y * this.width + x] = Math.max(0, Math.min(255, v));
};
Image.prototype.copyTo = function (xSrcIndex, length, target, xTargetIndex) {
for (var x = 0; x < length; x++) {
for (var y = 0; y < 5; y++) {
var value = this.get(xSrcIndex + x, y);
target.set(xTargetIndex + x, y, value);
}
}
};
Image.prototype.shiftLeft = function (cols) {
for (var x = 0; x < this.width; ++x)
for (var y = 0; y < 5; ++y)
this.set(x, y, x < this.width - cols ? this.get(x + cols, y) : 0);
};
Image.prototype.shiftRight = function (cols) {
for (var x = this.width - 1; x >= 0; --x)
for (var y = 0; y < 5; ++y)
this.set(x, y, x >= cols ? this.get(x - cols, y) : 0);
};
Image.prototype.clear = function () {
for (var i = 0; i < this.data.length; ++i)
this.data[i] = 0;
};
Image.height = 5;
return Image;
}(pxsim.RefObject));
pxsim.Image = Image;
function createInternalImage(width) {
var img = createImage(width);
pxsim.noLeakTracking(img);
return img;
}
pxsim.createInternalImage = createInternalImage;
function createImage(width) {
return new Image(width, new Array(width * 5));
}
pxsim.createImage = createImage;
function createImageFromBuffer(data) {
return new Image(data.length / 5, data);
}
pxsim.createImageFromBuffer = createImageFromBuffer;
function createImageFromString(text) {
var font = pxsim.board().ledMatrixState.font;
var w = font.width;
var sprite = createInternalImage(6 * text.length - 1);
var k = 0;
for (var i = 0; i < text.length; i++) {
var charCode = text.charCodeAt(i);
var charStart = (charCode - 32) * 5;
if (charStart < 0 || charStart + 5 > w) {
charCode = " ".charCodeAt(0);
charStart = (charCode - 32) * 5;
}
font.copyTo(charStart, 5, sprite, k);
k = k + 5;
if (i < text.length - 1) {
k = k + 1;
}
}
return sprite;
}
pxsim.createImageFromString = createImageFromString;
function createFont() {
var data = [0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0x8, 0xa, 0x4a, 0x40, 0x0, 0x0, 0xa, 0x5f, 0xea, 0x5f, 0xea, 0xe, 0xd9, 0x2e, 0xd3, 0x6e, 0x19, 0x32, 0x44, 0x89, 0x33, 0xc, 0x92, 0x4c, 0x92, 0x4d, 0x8, 0x8, 0x0, 0x0, 0x0, 0x4, 0x88, 0x8, 0x8, 0x4, 0x8, 0x4, 0x84, 0x84, 0x88, 0x0, 0xa, 0x44, 0x8a, 0x40, 0x0, 0x4, 0x8e, 0xc4, 0x80, 0x0, 0x0, 0x0, 0x4, 0x88, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x22, 0x44, 0x88, 0x10, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x4, 0x8c, 0x84, 0x84, 0x8e, 0x1c, 0x82, 0x4c, 0x90, 0x1e, 0x1e, 0xc2, 0x44, 0x92, 0x4c, 0x6, 0xca, 0x52, 0x5f, 0xe2, 0x1f, 0xf0, 0x1e, 0xc1, 0x3e, 0x2, 0x44, 0x8e, 0xd1, 0x2e, 0x1f, 0xe2, 0x44, 0x88, 0x10, 0xe, 0xd1, 0x2e, 0xd1, 0x2e, 0xe, 0xd1, 0x2e, 0xc4, 0x88, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x4, 0x80, 0x4, 0x88, 0x2, 0x44, 0x88, 0x4, 0x82, 0x0, 0xe, 0xc0, 0xe, 0xc0, 0x8, 0x4, 0x82, 0x44, 0x88, 0xe, 0xd1, 0x26, 0xc0, 0x4, 0xe, 0xd1, 0x35, 0xb3, 0x6c, 0xc, 0x92, 0x5e, 0xd2, 0x52, 0x1c, 0x92, 0x5c, 0x92, 0x5c, 0xe, 0xd0, 0x10, 0x10, 0xe, 0x1c, 0x92, 0x52, 0x52, 0x5c, 0x1e, 0xd0, 0x1c, 0x90, 0x1e, 0x1e, 0xd0, 0x1c, 0x90, 0x10, 0xe, 0xd0, 0x13, 0x71, 0x2e, 0x12, 0x52, 0x5e, 0xd2, 0x52, 0x1c, 0x88, 0x8, 0x8, 0x1c, 0x1f, 0xe2, 0x42, 0x52, 0x4c, 0x12, 0x54, 0x98, 0x14, 0x92, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x3b, 0x75, 0xb1, 0x31, 0x11, 0x39, 0x35, 0xb3, 0x71, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x1c, 0x92, 0x5c, 0x90, 0x10, 0xc, 0x92, 0x52, 0x4c, 0x86, 0x1c, 0x92, 0x5c, 0x92, 0x51, 0xe, 0xd0, 0xc, 0x82, 0x5c, 0x1f, 0xe4, 0x84, 0x84, 0x84, 0x12, 0x52, 0x52, 0x52, 0x4c, 0x11, 0x31, 0x31, 0x2a, 0x44, 0x11, 0x31, 0x35, 0xbb, 0x71, 0x12, 0x52, 0x4c, 0x92, 0x52, 0x11, 0x2a, 0x44, 0x84, 0x84, 0x1e, 0xc4, 0x88, 0x10, 0x1e, 0xe, 0xc8, 0x8, 0x8, 0xe, 0x10, 0x8, 0x4, 0x82, 0x41, 0xe, 0xc2, 0x42, 0x42, 0x4e, 0x4, 0x8a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x8, 0x4, 0x80, 0x0, 0x0, 0x0, 0xe, 0xd2, 0x52, 0x4f, 0x10, 0x10, 0x1c, 0x92, 0x5c, 0x0, 0xe, 0xd0, 0x10, 0xe, 0x2, 0x42, 0x4e, 0xd2, 0x4e, 0xc, 0x92, 0x5c, 0x90, 0xe, 0x6, 0xc8, 0x1c, 0x88, 0x8, 0xe, 0xd2, 0x4e, 0xc2, 0x4c, 0x10, 0x10, 0x1c, 0x92, 0x52, 0x8, 0x0, 0x8, 0x8, 0x8, 0x2, 0x40, 0x2, 0x42, 0x4c, 0x10, 0x14, 0x98, 0x14, 0x92, 0x8, 0x8, 0x8, 0x8, 0x6, 0x0, 0x1b, 0x75, 0xb1, 0x31, 0x0, 0x1c, 0x92, 0x52, 0x52, 0x0, 0xc, 0x92, 0x52, 0x4c, 0x0, 0x1c, 0x92, 0x5c, 0x90, 0x0, 0xe, 0xd2, 0x4e, 0xc2, 0x0, 0xe, 0xd0, 0x10, 0x10, 0x0, 0x6, 0xc8, 0x4, 0x98, 0x8, 0x8, 0xe, 0xc8, 0x7, 0x0, 0x12, 0x52, 0x52, 0x4f, 0x0, 0x11, 0x31, 0x2a, 0x44, 0x0, 0x11, 0x31, 0x35, 0xbb, 0x0, 0x12, 0x4c, 0x8c, 0x92, 0x0, 0x11, 0x2a, 0x44, 0x98, 0x0, 0x1e, 0xc4, 0x88, 0x1e, 0x6, 0xc4, 0x8c, 0x84, 0x86, 0x8, 0x8, 0x8, 0x8, 0x8, 0x18, 0x8, 0xc, 0x88, 0x18, 0x0, 0x0, 0xc, 0x83, 0x60];
var nb = data.length;
var n = nb / 5;
var font = createInternalImage(nb);
for (var c = 0; c < n; c++) {
for (var row = 0; row < 5; row++) {
var char = data[c * 5 + row];
for (var col = 0; col < 5; col++) {
if ((char & (1 << col)) != 0)
font.set((c * 5 + 4) - col, row, 255);
}
}
}
return font;
}
pxsim.createFont = createFont;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var images;
(function (images) {
function createImage(img) {
return img;
}
images.createImage = createImage;
function createBigImage(img) {
return img;
}
images.createBigImage = createBigImage;
})(images = pxsim.images || (pxsim.images = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var ImageMethods;
(function (ImageMethods) {
function showImage(leds, offset, interval) {
pxsim.pxtrt.nullCheck(leds);
leds.copyTo(offset, 5, pxsim.board().ledMatrixState.image, 0);
pxsim.runtime.queueDisplayUpdate();
pxsim.basic.pause(interval);
}
ImageMethods.showImage = showImage;
function plotImage(leds, offset) {
pxsim.pxtrt.nullCheck(leds);
leds.copyTo(offset, 5, pxsim.board().ledMatrixState.image, 0);
pxsim.runtime.queueDisplayUpdate();
}
ImageMethods.plotImage = plotImage;
function height(leds) {
pxsim.pxtrt.nullCheck(leds);
return pxsim.Image.height;
}
ImageMethods.height = height;
function width(leds) {
pxsim.pxtrt.nullCheck(leds);
return leds.width;
}
ImageMethods.width = width;
function plotFrame(leds, frame) {
ImageMethods.plotImage(leds, frame * pxsim.Image.height);
}
ImageMethods.plotFrame = plotFrame;
function showFrame(leds, frame, interval) {
ImageMethods.showImage(leds, frame * pxsim.Image.height, interval);
}
ImageMethods.showFrame = showFrame;
function pixel(leds, x, y) {
pxsim.pxtrt.nullCheck(leds);
return leds.get(x, y);
}
ImageMethods.pixel = pixel;
function setPixel(leds, x, y, v) {
pxsim.pxtrt.nullCheck(leds);
leds.set(x, y, v);
}
ImageMethods.setPixel = setPixel;
function clear(leds) {
pxsim.pxtrt.nullCheck(leds);
leds.clear();
}
ImageMethods.clear = clear;
function setPixelBrightness(i, x, y, b) {
pxsim.pxtrt.nullCheck(i);
i.set(x, y, b);
}
ImageMethods.setPixelBrightness = setPixelBrightness;
function pixelBrightness(i, x, y) {
pxsim.pxtrt.nullCheck(i);
return i.get(x, y);
}
ImageMethods.pixelBrightness = pixelBrightness;
function scrollImage(leds, stride, interval) {
pxsim.pxtrt.nullCheck(leds);
if (stride == 0)
stride = 1;
var cb = pxsim.getResume();
var off = stride > 0 ? 0 : leds.width - 1;
var display = pxsim.board().ledMatrixState.image;
pxsim.board().ledMatrixState.animationQ.enqueue({
interval: interval,
frame: function () {
if (off >= leds.width || off < 0)
return false;
if (stride > 0) {
display.shiftLeft(stride);
var c = Math.min(stride, leds.width - off);
leds.copyTo(off, c, display, 5 - stride);
}
else {
display.shiftRight(-stride);
var c = Math.min(-stride, leds.width - off);
leds.copyTo(off, c, display, 0);
}
off += stride;
return true;
},
whenDone: cb
});
}
ImageMethods.scrollImage = scrollImage;
})(ImageMethods = pxsim.ImageMethods || (pxsim.ImageMethods = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var basic;
(function (basic) {
function showNumber(x, interval) {
if (interval < 0)
return;
var leds = pxsim.createImageFromString(x.toString());
if (x < 0 || x >= 10)
pxsim.ImageMethods.scrollImage(leds, 1, interval);
else
showLeds(leds, interval * 5);
}
basic.showNumber = showNumber;
function showString(s, interval) {
if (interval < 0)
return;
if (s.length == 0) {
clearScreen();
basic.pause(interval * 5);
}
else {
if (s.length == 1)
showLeds(pxsim.createImageFromString(s), 0);
else
pxsim.ImageMethods.scrollImage(pxsim.createImageFromString(s + " "), 1, interval);
}
}
basic.showString = showString;
function showLeds(leds, delay) {
showAnimation(leds, delay);
}
basic.showLeds = showLeds;
function clearScreen() {
pxsim.board().ledMatrixState.image.clear();
pxsim.runtime.queueDisplayUpdate();
}
basic.clearScreen = clearScreen;
function showAnimation(leds, interval) {
pxsim.ImageMethods.scrollImage(leds, 5, interval);
}
basic.showAnimation = showAnimation;
function plotLeds(leds) {
pxsim.ImageMethods.plotImage(leds, 0);
}
basic.plotLeds = plotLeds;
})(basic = pxsim.basic || (pxsim.basic = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var led;
(function (led) {
function plot(x, y) {
pxsim.board().ledMatrixState.image.set(x, y, 255);
pxsim.runtime.queueDisplayUpdate();
}
led.plot = plot;
function unplot(x, y) {
pxsim.board().ledMatrixState.image.set(x, y, 0);
pxsim.runtime.queueDisplayUpdate();
}
led.unplot = unplot;
function point(x, y) {
return !!pxsim.board().ledMatrixState.image.get(x, y);
}
led.point = point;
function brightness() {
return pxsim.board().ledMatrixState.brigthness;
}
led.brightness = brightness;
function setBrightness(value) {
pxsim.board().ledMatrixState.brigthness = value;
pxsim.runtime.queueDisplayUpdate();
}
led.setBrightness = setBrightness;
function stopAnimation() {
pxsim.board().ledMatrixState.animationQ.cancelAll();
pxsim.board().ledMatrixState.image.clear();
}
led.stopAnimation = stopAnimation;
function setDisplayMode(mode) {
pxsim.board().ledMatrixState.displayMode = mode;
pxsim.runtime.queueDisplayUpdate();
}
led.setDisplayMode = setDisplayMode;
function screenshot() {
var img = pxsim.createImage(5);
pxsim.board().ledMatrixState.image.copyTo(0, 5, img, 0);
return img;
}
led.screenshot = screenshot;
function enable(on) {
pxsim.board().ledMatrixState.disabled = !on;
pxsim.runtime.queueDisplayUpdate();
}
led.enable = enable;
})(led = pxsim.led || (pxsim.led = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function lightLevel() {
var b = pxsim.board().lightSensorState;
if (!b.usesLightLevel) {
b.usesLightLevel = true;
pxsim.runtime.queueDisplayUpdate();
}
return b.lightLevel;
}
input.lightLevel = lightLevel;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
/**
* Error codes used in the micro:bit runtime.
*/
(function (PanicCode) {
// PANIC Codes. These are not return codes, but are terminal conditions.
// These induce a panic operation, where all code stops executing, and a panic state is
// entered where the panic code is diplayed.
// Out out memory error. Heap storage was requested, but is not available.
PanicCode[PanicCode["MICROBIT_OOM"] = 20] = "MICROBIT_OOM";
// Corruption detected in the micro:bit heap space
PanicCode[PanicCode["MICROBIT_HEAP_ERROR"] = 30] = "MICROBIT_HEAP_ERROR";
// Dereference of a NULL pointer through the ManagedType class,
PanicCode[PanicCode["MICROBIT_NULL_DEREFERENCE"] = 40] = "MICROBIT_NULL_DEREFERENCE";
})(pxsim.PanicCode || (pxsim.PanicCode = {}));
var PanicCode = pxsim.PanicCode;
;
function panic(code) {
console.log("PANIC:", code);
throw new Error("PANIC " + code);
}
pxsim.panic = panic;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var basic;
(function (basic) {
basic.pause = pxsim.thread.pause;
basic.forever = pxsim.thread.forever;
})(basic = pxsim.basic || (pxsim.basic = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var control;
(function (control) {
control.inBackground = pxsim.thread.runInBackground;
function reset() {
pxsim.U.userError("reset not implemented in simulator yet");
}
control.reset = reset;
function waitMicros(micros) {
// TODO
}
control.waitMicros = waitMicros;
function deviceName() {
var b = pxsim.board();
return b && b.id
? b.id.slice(0, 4)
: "abcd";
}
control.deviceName = deviceName;
function deviceSerialNumber() {
var b = pxsim.board();
return parseInt(b && b.id
? b.id.slice(1)
: "42");
}
control.deviceSerialNumber = deviceSerialNumber;
function onEvent(id, evid, handler) {
pxsim.pxtcore.registerWithDal(id, evid, handler);
}
control.onEvent = onEvent;
function raiseEvent(id, evid, mode) {
// TODO mode?
pxsim.board().bus.queue(id, evid);
}
control.raiseEvent = raiseEvent;
})(control = pxsim.control || (pxsim.control = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var pxtcore;
(function (pxtcore) {
function registerWithDal(id, evid, handler) {
pxsim.board().bus.listen(id, evid, handler);
}
pxtcore.registerWithDal = registerWithDal;
})(pxtcore = pxsim.pxtcore || (pxsim.pxtcore = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function runningTime() {
return pxsim.runtime.runningTime();
}
input.runningTime = runningTime;
function calibrate() {
}
input.calibrate = calibrate;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var pins;
(function (pins) {
function onPulsed(name, pulse, body) {
}
pins.onPulsed = onPulsed;
function pulseDuration() {
return 0;
}
pins.pulseDuration = pulseDuration;
function createBuffer(sz) {
return pxsim.BufferMethods.createBuffer(sz);
}
pins.createBuffer = createBuffer;
function pulseIn(name, value, maxDuration) {
var pin = pxsim.getPin(name);
if (!pin)
return 0;
return 5000;
}
pins.pulseIn = pulseIn;
function spiWrite(value) {
// TODO
return 0;
}
pins.spiWrite = spiWrite;
function i2cReadBuffer(address, size, repeat) {
// fake reading zeros
return createBuffer(size);
}
pins.i2cReadBuffer = i2cReadBuffer;
function i2cWriteBuffer(address, buf, repeat) {
// fake - noop
}
pins.i2cWriteBuffer = i2cWriteBuffer;
// this likely shouldn't be called
function getPinAddress(name) {
return pxsim.getPin(name);
}
pins.getPinAddress = getPinAddress;
function setEvents(name, event) {
}
pins.setEvents = setEvents;
})(pins = pxsim.pins || (pxsim.pins = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var devices;
(function (devices) {
function tellCameraTo(action) {
// TODO
}
devices.tellCameraTo = tellCameraTo;
function tellRemoteControlTo(action) {
// TODO
}
devices.tellRemoteControlTo = tellRemoteControlTo;
function raiseAlertTo(action) {
// TODO
}
devices.raiseAlertTo = raiseAlertTo;
function onSignalStrengthChanged(action) {
// TODO
}
devices.onSignalStrengthChanged = onSignalStrengthChanged;
function signalStrength() {
// TODO
return 0;
}
devices.signalStrength = signalStrength;
function onGamepadButton(button, body) {
// TODO
}
devices.onGamepadButton = onGamepadButton;
})(devices = pxsim.devices || (pxsim.devices = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var bluetooth;
(function (bluetooth) {
function startIOPinService() {
// TODO
}
bluetooth.startIOPinService = startIOPinService;
function startLEDService() {
// TODO
}
bluetooth.startLEDService = startLEDService;
function startTemperatureService() {
// TODO
}
bluetooth.startTemperatureService = startTemperatureService;
function startMagnetometerService() {
// TODO
}
bluetooth.startMagnetometerService = startMagnetometerService;
function startAccelerometerService() {
// TODO
}
bluetooth.startAccelerometerService = startAccelerometerService;
function startButtonService() {
// TODO
}
bluetooth.startButtonService = startButtonService;
function startUartService() {
// TODO
}
bluetooth.startUartService = startUartService;
function uartWrite(s) {
// TODO
}
bluetooth.uartWrite = uartWrite;
function uartReadUntil(del) {
// TODO
return "";
}
bluetooth.uartReadUntil = uartReadUntil;
function onBluetoothConnected(a) {
// TODO
}
bluetooth.onBluetoothConnected = onBluetoothConnected;
function onBluetoothDisconnected(a) {
// TODO
}
bluetooth.onBluetoothDisconnected = onBluetoothDisconnected;
})(bluetooth = pxsim.bluetooth || (pxsim.bluetooth = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var SpeakerState = (function () {
function SpeakerState() {
}
return SpeakerState;
}());
pxsim.SpeakerState = SpeakerState;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var music;
(function (music) {
function playTone(frequency, ms) {
var b = pxsim.board();
b.speakerState.frequency = frequency;
b.speakerState.ms = ms;
pxsim.runtime.queueDisplayUpdate();
var cb = pxsim.getResume();
pxsim.AudioContextManager.tone(frequency, 1);
if (ms <= 0)
cb();
else {
setTimeout(function () {
pxsim.AudioContextManager.stop();
b.speakerState.frequency = 0;
b.speakerState.ms = 0;
pxsim.runtime.queueDisplayUpdate();
cb();
}, ms);
}
}
music.playTone = playTone;
})(music = pxsim.music || (pxsim.music = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
function sendBufferAsm(buffer, pin) {
var b = pxsim.board();
if (b) {
var np = b.neopixelState;
if (np) {
var buf = buffer.data;
np.updateBuffer(buf, pin);
pxsim.runtime.queueDisplayUpdate();
}
}
}
pxsim.sendBufferAsm = sendBufferAsm;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var RadioDatagram = (function () {
function RadioDatagram(runtime) {
this.runtime = runtime;
this.datagram = [];
this.lastReceived = RadioDatagram.defaultPacket();
}
RadioDatagram.prototype.queue = function (packet) {
if (this.datagram.length < 4) {
this.datagram.push(packet);
}
pxsim.runtime.board.bus.queue(29 /* MICROBIT_ID_RADIO */, 1 /* MICROBIT_RADIO_EVT_DATAGRAM */);
};
RadioDatagram.prototype.send = function (payload) {
pxsim.Runtime.postMessage({
type: "radiopacket",
rssi: 0,
serial: pxsim.board().radioState.bus.transmitSerialNumber ? pxsim.board().radioState.bus.serial : 0,
time: 0,
payload: payload
});
};
RadioDatagram.prototype.recv = function () {
var r = this.datagram.shift();
if (!r)
r = RadioDatagram.defaultPacket();
return this.lastReceived = r;
};
RadioDatagram.defaultPacket = function () {
return {
rssi: -1,
serial: 0,
time: 0,
payload: { type: -1 }
};
};
return RadioDatagram;
}());
pxsim.RadioDatagram = RadioDatagram;
var RadioBus = (function () {
function RadioBus(runtime) {
this.runtime = runtime;
// uint8_t radioDefaultGroup = MICROBIT_RADIO_DEFAULT_GROUP;
this.groupId = 0; // todo
this.power = 0;
this.serial = 0;
this.transmitSerialNumber = false;
this.datagram = new RadioDatagram(runtime);
this.serial = Math.floor(Math.random() * Math.pow(2, 32)) - Math.pow(2, 31); // 32 bit signed integer
}
RadioBus.prototype.setGroup = function (id) {
this.groupId = id & 0xff; // byte only
};
RadioBus.prototype.setTransmitPower = function (power) {
this.power = Math.max(0, Math.min(7, power));
};
RadioBus.prototype.setTransmitSerialNumber = function (sn) {
this.transmitSerialNumber = !!sn;
};
RadioBus.prototype.broadcast = function (msg) {
pxsim.Runtime.postMessage({
type: "eventbus",
id: 2000 /* MES_BROADCAST_GENERAL_ID */,
eventid: msg,
power: this.power,
group: this.groupId
});
};
return RadioBus;
}());
pxsim.RadioBus = RadioBus;
var RadioState = (function () {
function RadioState(runtime) {
this.bus = new RadioBus(runtime);
}
RadioState.prototype.recievePacket = function (packet) {
this.bus.datagram.queue(packet);
};
return RadioState;
}());
pxsim.RadioState = RadioState;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var radio;
(function (radio) {
var PacketPayloadType;
(function (PacketPayloadType) {
PacketPayloadType[PacketPayloadType["NUMBER"] = 0] = "NUMBER";
PacketPayloadType[PacketPayloadType["VALUE"] = 1] = "VALUE";
PacketPayloadType[PacketPayloadType["STRING"] = 2] = "STRING";
})(PacketPayloadType || (PacketPayloadType = {}));
function broadcastMessage(msg) {
pxsim.board().radioState.bus.broadcast(msg);
}
radio.broadcastMessage = broadcastMessage;
function onBroadcastMessageReceived(msg, handler) {
pxsim.pxtcore.registerWithDal(2000 /* MES_BROADCAST_GENERAL_ID */, msg, handler);
}
radio.onBroadcastMessageReceived = onBroadcastMessageReceived;
function setGroup(id) {
pxsim.board().radioState.bus.setGroup(id);
}
radio.setGroup = setGroup;
function setTransmitPower(power) {
pxsim.board().radioState.bus.setTransmitPower(power);
}
radio.setTransmitPower = setTransmitPower;
function setTransmitSerialNumber(transmit) {
pxsim.board().radioState.bus.setTransmitSerialNumber(transmit);
}
radio.setTransmitSerialNumber = setTransmitSerialNumber;
function sendNumber(value) {
pxsim.board().radioState.bus.datagram.send({
type: PacketPayloadType.NUMBER,
numberData: value
});
}
radio.sendNumber = sendNumber;
function sendString(msg) {
msg = msg.substr(0, 19);
pxsim.board().radioState.bus.datagram.send({
type: PacketPayloadType.STRING,
stringData: msg
});
}
radio.sendString = sendString;
function writeValueToSerial() {
var b = pxsim.board();
writePacketToSerial(b, b.radioState.bus.datagram.recv());
}
radio.writeValueToSerial = writeValueToSerial;
function writeReceivedPacketToSerial() {
var b = pxsim.board();
writePacketToSerial(b, b.radioState.bus.datagram.lastReceived);
}
radio.writeReceivedPacketToSerial = writeReceivedPacketToSerial;
function sendValue(name, value) {
name = name.substr(0, 12);
var msg = [];
msg.push();
pxsim.board().radioState.bus.datagram.send({
type: PacketPayloadType.VALUE,
stringData: name,
numberData: value
});
}
radio.sendValue = sendValue;
function receiveNumber() {
var packet = pxsim.board().radioState.bus.datagram.recv();
return receivedNumber();
}
radio.receiveNumber = receiveNumber;
function receiveString() {
var packet = pxsim.board().radioState.bus.datagram.recv();
return receivedString();
}
radio.receiveString = receiveString;
function receivedSignalStrength() {
return pxsim.board().radioState.bus.datagram.lastReceived.rssi;
}
radio.receivedSignalStrength = receivedSignalStrength;
function onDataReceived(handler) {
pxsim.pxtcore.registerWithDal(29 /* MICROBIT_ID_RADIO */, 1 /* MICROBIT_RADIO_EVT_DATAGRAM */, handler);
radio.receiveNumber();
}
radio.onDataReceived = onDataReceived;
function receivedNumber() {
return pxsim.board().radioState.bus.datagram.lastReceived.payload.numberData || 0;
}
radio.receivedNumber = receivedNumber;
function receivedSerial() {
return pxsim.board().radioState.bus.datagram.lastReceived.serial;
}
radio.receivedSerial = receivedSerial;
function receivedString() {
return pxsim.board().radioState.bus.datagram.lastReceived.payload.stringData || "";
}
radio.receivedString = receivedString;
function receivedTime() {
return pxsim.board().radioState.bus.datagram.lastReceived.time;
}
radio.receivedTime = receivedTime;
function writePacketToSerial(b, p) {
switch (p.payload.type) {
case PacketPayloadType.NUMBER:
b.writeSerial("{\"t\":" + p.time + ",\"s\":" + p.serial + ",\"v\":" + p.payload.numberData + "}\r\n");
break;
case PacketPayloadType.VALUE:
b.writeSerial("{\"t\":" + p.time + ",\"s\":" + p.serial + ",\"n\":\"" + p.payload.stringData + "\",\"v\":" + p.payload.numberData + "}\r\n");
break;
case PacketPayloadType.STRING:
b.writeSerial("{\"t\":" + p.time + ",\"s\":" + p.serial + ",\"n\":\"" + p.payload.stringData + "\"}\r\n");
break;
default:
}
}
})(radio = pxsim.radio || (pxsim.radio = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var basic;
(function (basic) {
function setLedColor(c) {
pxsim.board().rgbLedState = c;
pxsim.runtime.queueDisplayUpdate();
}
basic.setLedColor = setLedColor;
})(basic = pxsim.basic || (pxsim.basic = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var SerialState = (function () {
function SerialState() {
this.serialIn = [];
this.serialOutBuffer = "";
}
SerialState.prototype.recieveData = function (data) {
this.serialIn.push();
};
SerialState.prototype.readSerial = function () {
var v = this.serialIn.shift() || "";
return v;
};
SerialState.prototype.writeSerial = function (s) {
for (var i = 0; i < s.length; ++i) {
var c = s[i];
this.serialOutBuffer += c;
if (c == "\n") {
pxsim.Runtime.postMessage({
type: "serial",
data: this.serialOutBuffer,
id: pxsim.runtime.id
});
this.serialOutBuffer = "";
break;
}
}
};
return SerialState;
}());
pxsim.SerialState = SerialState;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var serial;
(function (serial) {
function writeString(s) {
pxsim.board().writeSerial(s);
}
serial.writeString = writeString;
function readUntil(del) {
return readString();
}
serial.readUntil = readUntil;
function readString() {
return pxsim.board().serialState.readSerial();
}
serial.readString = readString;
function onDataReceived(delimiters, handler) {
var b = pxsim.board();
b.bus.listen(32 /* MICROBIT_ID_SERIAL */, 1 /* MICROBIT_SERIAL_EVT_DELIM_MATCH */, handler);
}
serial.onDataReceived = onDataReceived;
function redirect(tx, rx, rate) {
// TODO?
}
serial.redirect = redirect;
})(serial = pxsim.serial || (pxsim.serial = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var motors;
(function (motors) {
function motorPower(power) {
// TODO
}
motors.motorPower = motorPower;
function motorCommand(command) {
}
motors.motorCommand = motorCommand;
function dualMotorPower(motor, percent) {
}
motors.dualMotorPower = dualMotorPower;
})(motors = pxsim.motors || (pxsim.motors = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var ThermometerState = (function () {
function ThermometerState() {
this.usesTemperature = false;
this.temperature = 21;
}
return ThermometerState;
}());
pxsim.ThermometerState = ThermometerState;
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var input;
(function (input) {
function temperature() {
var b = pxsim.board();
if (!b.thermometerState.usesTemperature) {
b.thermometerState.usesTemperature = true;
pxsim.runtime.queueDisplayUpdate();
}
return b.thermometerState.temperature;
}
input.temperature = temperature;
})(input = pxsim.input || (pxsim.input = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var visuals;
(function (visuals) {
visuals.mkBoardView = function (opts) {
return new visuals.MicrobitBoardSvg({
runtime: pxsim.runtime,
theme: visuals.randomTheme(),
disableTilt: false,
wireframe: opts.wireframe,
});
};
})(visuals = pxsim.visuals || (pxsim.visuals = {}));
})(pxsim || (pxsim = {}));
/// <reference path="../../node_modules/pxt-core/typings/globals/bluebird/index.d.ts"/>
/// <reference path="../../node_modules/pxt-core/built/pxtsim.d.ts"/>
var pxsim;
(function (pxsim) {
var visuals;
(function (visuals) {
function mkLedMatrixSvg(xy, rows, cols) {
var result = { el: null, y: 0, x: 0, w: 0, h: 0, leds: [], ledsOuter: [], background: null };
result.el = pxsim.svg.elt("g");
var width = cols * visuals.PIN_DIST;
var height = rows * visuals.PIN_DIST;
var ledRad = Math.round(visuals.PIN_DIST * .35);
var spacing = visuals.PIN_DIST;
var padding = (spacing - 2 * ledRad) / 2.0;
var x = xy[0], y = xy[1];
var left = x - (ledRad + padding);
var top = y - (ledRad + padding);
result.x = left;
result.y = top;
result.w = width;
result.h = height;
result.background = pxsim.svg.child(result.el, "rect", { class: "sim-display", x: left, y: top, width: width, height: height });
// ledsOuter
result.leds = [];
result.ledsOuter = [];
var hoverRad = ledRad * 1.2;
for (var i = 0; i < rows; ++i) {
var y_1 = top + ledRad + i * spacing + padding;
for (var j = 0; j < cols; ++j) {
var x_1 = left + ledRad + j * spacing + padding;
result.ledsOuter.push(pxsim.svg.child(result.el, "circle", { class: "sim-led-back", cx: x_1, cy: y_1, r: ledRad }));
result.leds.push(pxsim.svg.child(result.el, "circle", { class: "sim-led", cx: x_1, cy: y_1, r: hoverRad, title: "(" + j + "," + i + ")" }));
}
}
//default theme
pxsim.svg.fill(result.background, visuals.defaultLedMatrixTheme.background);
pxsim.svg.fills(result.leds, visuals.defaultLedMatrixTheme.ledOn);
pxsim.svg.fills(result.ledsOuter, visuals.defaultLedMatrixTheme.ledOff);
//turn off LEDs
result.leds.forEach(function (l) { return l.style.opacity = 0 + ""; });
return result;
}
visuals.mkLedMatrixSvg = mkLedMatrixSvg;
visuals.defaultLedMatrixTheme = {
background: "#000",
ledOn: "#ff5f5f",
ledOff: "#DDD",
};
visuals.LED_MATRIX_STYLE = "\n .sim-led-back:hover {\n stroke:#a0a0a0;\n stroke-width:3px;\n }\n .sim-led:hover {\n stroke:#ff7f7f;\n stroke-width:3px;\n }\n ";
var LedMatrixView = (function () {
function LedMatrixView() {
this.DRAW_SIZE = 8;
this.ACTIVE_SIZE = 5;
this.style = visuals.LED_MATRIX_STYLE;
}
LedMatrixView.prototype.init = function (bus, state) {
this.bus = bus;
this.state = state;
this.theme = visuals.defaultLedMatrixTheme;
this.defs = [];
this.element = this.buildDom();
};
LedMatrixView.prototype.moveToCoord = function (xy) {
visuals.translateEl(this.element, xy);
};
LedMatrixView.prototype.updateTheme = function () {
pxsim.svg.fill(this.background, this.theme.background);
pxsim.svg.fills(this.leds, this.theme.ledOn);
pxsim.svg.fills(this.ledsOuter, this.theme.ledOff);
};
LedMatrixView.prototype.updateState = function () {
var _this = this;
if (this.state.disabled) {
this.leds.forEach(function (led, i) {
var sel = led;
sel.style.opacity = 0 + "";
});
return;
}
var bw = this.state.displayMode == pxsim.DisplayMode.bw;
var img = this.state.image;
this.leds.forEach(function (led, i) {
var sel = led;
var dx = i % _this.DRAW_SIZE;
var dy = (i - dx) / _this.DRAW_SIZE;
if (dx < _this.ACTIVE_SIZE && dy < _this.ACTIVE_SIZE) {
var j = dx + dy * _this.ACTIVE_SIZE;
sel.style.opacity = ((bw ? img.data[j] > 0 ? 255 : 0 : img.data[j]) / 255.0) + "";
}
else {
sel.style.opacity = 0 + "";
}
});
};
LedMatrixView.prototype.buildDom = function () {
var res = mkLedMatrixSvg([0, 0], this.DRAW_SIZE, this.DRAW_SIZE);
var display = res.el;
this.background = res.background;
this.leds = res.leds;
this.ledsOuter = res.ledsOuter;
return display;
};
return LedMatrixView;
}());
visuals.LedMatrixView = LedMatrixView;
})(visuals = pxsim.visuals || (pxsim.visuals = {}));
})(pxsim || (pxsim = {}));
var pxsim;
(function (pxsim) {
var visuals;
(function (visuals) {
var MB_STYLE = "\n svg.sim {\n margin-bottom:1em;\n }\n svg.sim.grayscale {\n -moz-filter: grayscale(1);\n -webkit-filter: grayscale(1);\n filter: grayscale(1);\n }\n .sim-button {\n pointer-events: none;\n }\n\n .sim-button-outer:hover {\n stroke:grey;\n stroke-width: 3px;\n }\n .sim-button-nut {\n fill:#704A4A;\n pointer-events:none;\n }\n .sim-button-nut:hover {\n stroke:1px solid #704A4A;\n }\n .sim-pin:hover {\n stroke:#D4AF37;\n stroke-width:2px;\n }\n\n .sim-pin-touch.touched:hover {\n stroke:darkorange;\n }\n\n .sim-led-back:hover {\n stroke:#fff;\n stroke-width:3px;\n }\n .sim-led:hover {\n stroke:#ff7f7f;\n stroke-width:3px;\n }\n\n .sim-systemled {\n fill:#333;\n stroke:#555;\n stroke-width: 1px;\n }\n\n .sim-light-level-button {\n stroke:#ccc;\n stroke-width: 2px;\n }\n\n .sim-antenna {\n fill-opacity:0.0;\n stroke:#555;\n stroke-width: 4px;\n }\n\n .sim-text {\n font-family:\"Lucida Console\", Monaco, monospace;\n font-size:14px;\n fill:#fff;\n pointer-events: none; user-select: none;\n }\n .sim-text.inverted {\n fill:#000;\n }\n\n .sim-text-pin {\n font-family:\"Lucida Console\", Monaco, monospace;\n font-size:20px;\n fill:#fff;\n pointer-events: none;\n }\n\n .sim-thermometer {\n stroke:#aaa;\n stroke-width: 2px;\n }\n\n #rgbledcircle:hover {\n r:8px;\n }\n\n /* animations */\n .sim-theme-glow {\n animation-name: sim-theme-glow-animation;\n animation-timing-function: ease-in-out;\n animation-direction: alternate;\n animation-iteration-count: infinite;\n animation-duration: 1.25s;\n }\n @keyframes sim-theme-glow-animation {\n from { opacity: 1; }\n to { opacity: 0.75; }\n }\n\n .sim-flash {\n animation-name: sim-flash-animation;\n animation-duration: 0.1s;\n }\n\n @keyframes sim-flash-animation {\n from { fill: yellow; }\n to { fill: default; }\n }\n\n .sim-flash-stroke {\n animation-name: sim-flash-stroke-animation;\n animation-duration: 0.4s;\n animation-timing-function: ease-in;\n }\n\n @keyframes sim-flash-stroke-animation {\n from { stroke: yellow; }\n to { stroke: default; }\n }\n\n /* wireframe */\n .sim-wireframe * {\n fill: none;\n stroke: black;\n }\n .sim-wireframe .sim-display,\n .sim-wireframe .sim-led,\n .sim-wireframe .sim-led-back,\n .sim-wireframe .sim-head,\n .sim-wireframe .sim-theme,\n .sim-wireframe .sim-button-group,\n .sim-wireframe .sim-button-label,\n .sim-wireframe .sim-button,\n .sim-wireframe .sim-text-pin\n {\n visibility: hidden;\n }\n .sim-wireframe .sim-label\n {\n stroke: none;\n fill: #777;\n }\n .sim-wireframe .sim-board {\n stroke-width: 2px;\n }\n ";
var BOARD_SVG = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg version=\"1.1\" id=\"Ebene_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\t width=\"530px\" height=\"530px\" viewBox=\"0 0 530 530\" enable-background=\"new 0 0 530 530\" xml:space=\"preserve\">\n<path fill=\"#034854\" d=\"M520.5,298.5c-18.2,0-32.9-14.7-32.9-32.9s14.7-32.9,32.9-32.9c0.6,0,1.3,0,1.9,0.1\n\tc-19.4-9-44.4-27.4-72.1-63.3c-28.8-37.8-28.6-84.7-25.8-115c0.2-2.3,0.4-4.5,0.7-6.6c1.5-14.7-7.2-28.6-21.3-33.6l-1.1-0.4\n\tc-9.5-3.4-20.1-2-28.4,3.9c-1.4,1-2.9,2-4.5,3.1c-22.1,14.8-62.8,37.6-104.6,37.6c-39.2,0-80.1-22.2-104.7-38.3\n\tc5.7,5.9,9.3,14,9.3,22.9c0,18.2-14.7,32.9-32.9,32.9c-12.4,0-23.2-6.9-28.8-17c2.3,27.8-0.7,71.6-26.4,109.2\n\tC60.1,199.2,27,220.2,3.3,232.3c2-0.4,4.1-0.6,6.2-0.6c18.2,0,33,14.4,32.9,32.8c0,18.2-14.7,32.9-32.9,32.9c-2,0-4-0.2-5.9-0.5\n\tc17.2,5.6,37.6,16.2,71.3,56.2c34.4,40.4,35.9,94.5,32.3,124.1c-1.8,13.7,1.6,27.9,12.5,36.3c10.4,8.1,28.8,5.4,39.5-2.5\n\tc12.4-9.3,25.8-18.2,39.5-24.5c15.5-7.2,30.1-11.1,39.6-11.8c5-0.5,9.8-2.3,11.4-7.1c2-5.7,6.2-12.7,15.9-12.7\n\tc9.3,0,13.8,6.4,15.9,12c1.6,4.3,5.4,7.3,10,7.7c6.6,0.5,18.4,3.2,39.3,11.2c17,6.6,29.6,16.2,40.2,23.2\n\tc18.4,11.8,32.1,8.8,41.4,2.9c8.3-5.2,12.7-14.9,11.4-24.8c-3.1-22-5.8-73,22-121.1c21.5-36.7,54.4-56.1,77.5-67.5\n\tC522.3,298.5,521.4,298.5,520.5,298.5z M138,502.8c-8.7,0-15.7-7-15.7-15.7s7-15.7,15.7-15.7s15.7,7,15.7,15.7\n\tS146.6,502.8,138,502.8z M393.4,501.5c-8.7,0-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7s15.7,7,15.7,15.7\n\tC409.1,494.5,402.1,501.5,393.4,501.5z M393.4,59.2c-8.6,0-15.7-6.9-15.7-15.7c0-8.8,6.9-15.7,15.7-15.7c8.8,0,15.7,6.9,15.7,15.7\n\tC409.1,52.3,401.9,59.2,393.4,59.2z\"/>\n<path id=\"EDGE_VCC\" fill=\"#EFDA48\" d=\"M393.4,10.8c-9.2,0-17.6,3.8-23.6,9.9c-5.8,5.9-9.3,14-9.3,22.9c0,18.2,14.7,32.9,32.9,32.9\n\tc14.4,0,26.6-9.3,31.1-22.1c1.2-3.4,1.8-7,1.8-10.8C426.3,25.5,411.5,10.8,393.4,10.8z M393.4,59.2c-8.6,0-15.7-6.9-15.7-15.7\n\tc0-8.8,6.9-15.7,15.7-15.7c8.8,0,15.7,6.9,15.7,15.7C409.1,52.3,401.9,59.2,393.4,59.2z\"/>\n<path fill=\"#BDD1CF\" d=\"M286.9,94h-41.7c-1.7,0-2.8-1.1-2.8-2.8v-32c0-1.7,1.1-2.8,2.8-2.8h41.7c1.7,0,2.8,1.1,2.8,2.8v32\n\tC289.7,92.8,288.3,94,286.9,94z\"/>\n<path id=\"EXT_PWR\" fill=\"#F2F2C8\" d=\"M449.4,343l-37-15.7c-0.3-0.1-0.7-0.2-1.1-0.2l-15.9-6.7l-3,7.4l13.5,5.6l-15.7,37.4l-13.6-5.8\n\tl-3,7.4l22.5,9.8l0.1-0.2l31.3,13.2c1.9,0.7,4.1,0,4.7-1.9l19.2-45.7C452,345.8,451.3,343.7,449.4,343z\"/>\n<polygon fill=\"#F8B133\" points=\"354,361 326.3,361 326.3,311.2 354,311.2 \"/>\n<polygon fill=\"#1D1D1B\" points=\"190.7,364.4 162.5,336.2 190.7,308 218.9,336.2 \"/>\n<polygon fill=\"#FFFFFF\" points=\"184.6,379.7 165.5,379.6 165.5,362.4 184.6,362.6 \"/>\n<rect id=\"ACCEL\" x=\"132.3\" y=\"241.8\" fill=\"#1D1D1B\" width=\"23.8\" height=\"14.4\"/>\n<path fill=\"#BDD1CF\" d=\"M326.6,84.1h-10.3c-1,0-2-0.9-2-2V66.9c0-1,0.9-2,2-2h10.3c1,0,2,0.9,2,2v15.2\n\tC328.4,83.2,327.6,84.1,326.6,84.1z\"/>\n<path fill=\"#FFFFFF\" d=\"M325.9,74.5c0-3.2-0.3-8.4-4.6-8.4c-5.1,0-4.6,5-4.6,8.4c0,3.2-0.2,8.4,4.6,8.4\n\tC326.6,82.9,325.9,77.6,325.9,74.5z\"/>\n<rect id=\"FLASH\" x=\"350\" y=\"90\" fill=\"#1D1D1B\" width=\"25.3\" height=\"30.8\"/>\n<rect id=\"G_A0\" x=\"80.5\" y=\"144.4\" transform=\"matrix(-0.5687 0.8226 -0.8226 -0.5687 301.6608 150.839)\" fill=\"#FFFFFF\" width=\"61.5\" height=\"20.3\"/>\n<circle id=\"G_A0_GND\" fill=\"#BDD1CF\" cx=\"124.8\" cy=\"135.6\" r=\"2.7\"/>\n<circle id=\"G_A0_VCC\" fill=\"#BDD1CF\" cx=\"115.6\" cy=\"148.2\" r=\"2.7\"/>\n<circle id=\"G_A0_SDA\" fill=\"#BDD1CF\" cx=\"107.4\" cy=\"160\" r=\"2.7\"/>\n<circle id=\"G_A0_SCL\" fill=\"#BDD1CF\" cx=\"98\" cy=\"173.5\" r=\"2.7\"/>\n<rect id=\"G_A1\" x=\"412.2\" y=\"123.3\" transform=\"matrix(-0.8226 0.5687 -0.5687 -0.8226 857.3843 40.5361)\" fill=\"#FFFFFF\" width=\"20.3\" height=\"61.5\"/>\n<circle id=\"G_A1_RX\" fil
var pinNames = [
"BTN_A", "BTN_B",
"EDGE_P0", "EDGE_P1", "EDGE_P2", "EDGE_P3", "EDGE_GND", "EDGE_VCC",
"C_GND1", "C_GND2", "C_GND3", "C_GND4", "C_VCC1", "C_VCC2",
"C_P0", "C_P2", "C_P4", "C_P6", "C_P8", "C_P10", "C_P12", "C_P14", "C_P16", "C_P18",
"C_P1", "C_P3", "C_P5", "C_P7", "C_P9", "C_P11", "C_P13", "C_P15", "C_P17", "C_P19",
"M_GND1", "M_GND2", "M_OUT1", "M_OUT2", "M_VM",
"G_A0_GND", "G_A0_VCC", "G_A0_SDA", "G_A0_SCL",
"G_A1_RX", "G_A1_TX", "G_A1_VCC", "G_A1_GND"
];
var pinTitles = [
"Button A", "Button B",
"P0", "P1, ANALOG IN", "P2, ANALOG IN", "P3", "GND", "+3v3",
"GND", "GND", "GND", "GND", "+3v3", "+3v3",
"C0", "C2", "C4", "C6", "C8", "C10", "C12", "C14", "C16", "C18",
"C1", "C3", "C5", "C7", "C9", "C11", "C13", "C15", "C17", "C19",
"GND", "GND", "MOTOR B", "MOTOR A", "MOTOR VM",
"GND", "+3v3", "C18, I2C - SDA", "C19, I2C - SCL",
"C16, Serial - RX", "C17, Serial - TX", "+3v3", "GND"
];
var MB_WIDTH = 530;
var MB_HEIGHT = 530;
visuals.themes = ["#3ADCFE"].map(function (accent) {
return {
accent: accent,
pin: "#EFDA48",
pinTouched: "#FFA500",
pinActive: "#FF5500",
ledOn: "#ff5555",
ledOff: "#e0e1e2",
buttonOuter: "#979797",
buttonUps: ["#186A8C", "#D82E50"],
buttonDown: "#FFA500",
virtualButtonDown: "#FFA500",
virtualButtonOuter: "#333",
virtualButtonUp: "#fff",
lightLevelOn: "yellow",
lightLevelOff: "#555"
};
});
function randomTheme() {
return visuals.themes[Math.floor(Math.random() * visuals.themes.length)];
}
visuals.randomTheme = randomTheme;
var MicrobitBoardSvg = (function () {
function MicrobitBoardSvg(props) {
var _this = this;
this.props = props;
this.pinNmToCoord = {
"EXT_PWR": [
92.30997467041016,
-42.92474937438965
],
"SPKR": [
106.44635391235352,
-16.370698928833008
],
"BTN_A": [
93.8138427734375,
56.631452560424805
],
"BTN_B": [
204.92835235595703,
56.631452560424805
],
// rings
"EDGE_P0": [
56.002254486083984,
95.43130111694336
],
"EDGE_P1": [
103.00893783569336,
175.82388305664062
],
"EDGE_P2": [
195.90512084960938,
175.3082733154297
],
"EDGE_P3": [
241.79466247558594,
95.3883285522461
],
"EDGE_GND": [
103.00893783569336,
14.86682915687561
],
"EDGE_VCC": [
195.64733123779297,
14.86682915687561
],
"C_GND1": [
113.1493148803711,
159.83989715576172
],
"C_GND2": [
150.27342987060547,
159.83989715576172
],
"C_GND3": [
150.27342987060547,
153.5666275024414
],
"C_GND4": [
187.39752960205078,
153.5666275024414
],
"C_VCC1": [
187.39752960205078,
159.83989715576172
],
"C_VCC2": [
113.1922836303711,
153.5666275024414
],
"C_P0": [
119.33667373657227,
159.83989715576172
],
"C_P2": [
125.52401733398438,
159.83989715576172
],
"C_P4": [
131.71136474609375,
159.83989715576172
],
"C_P6": [
137.89871978759766,
159.83989715576172
],
"C_P8": [
144.08607482910156,
159.83989715576172
],
"C_P10": [
156.46077728271484,
159.83989715576172
],
"C_P12": [
162.64812469482422,
159.83989715576172
],
"C_P14": [
168.83545684814453,
159.83989715576172
],
"C_P16": [
175.02281951904297,
159.83989715576172
],
"C_P20": [
181.2101821899414,
159.83989715576172
],
"C_P1": [
119.379638671875,
153.5666275024414
],
"C_P3": [
125.56698226928711,
153.5666275024414
],
"C_P5": [
131.71136474609375,
153.5666275024414
],
"C_P7": [
137.89871978759766,
153.5666275024414
],
"C_P9": [
144.08607482910156,
153.5666275024414
],
"C_P11": [
156.46077728271484,
153.5666275024414
],
"C_P13": [
162.64812469482422,
153.5666275024414
],
"C_P15": [
168.83545684814453,
153.5666275024414
],
"C_P21": [
175.02281951904297,
153.5666275024414
],
"C_P19": [
181.2101821899414,
153.5666275024414
],
"M_GND1": [
137.89871978759766,
141.70752716064453
],
"M_GND2": [
156.46077728271484,
141.70752716064453
],
"M_OUT1": [
144.08607482910156,
141.70752716064453
],
"M_OUT2": [
150.27342987060547,
141.70752716064453
],
"M_VM": [
162.64812469482422,
141.70752716064453
],
"G_A0_GND": [
82.47036743164062,
72.35763549804688
],
"G_A0_VCC": [
78.34546279907227,
76.3106689453125
],
"G_A0_SDA": [
74.65023803710938,
80.00588989257812
],
"G_A0_SCL": [
70.43940734863281,
84.21672821044922
],
"G_A1_RX": [
216.52963256835938,
71.4982795715332
],
"G_A1_TX": [
220.65453338623047,
75.53724670410156
],
"G_A1_VCC": [
224.34976959228516,
79.23247528076172
],
"G_A1_GND": [
228.56060028076172,
83.44330978393555
]
};
this.lastFlashTime = 0;
this.lastAntennaFlash = 0;
this.buildDom();
if (props && props.wireframe)
pxsim.svg.addClass(this.element, "sim-wireframe");
if (props && props.theme)
this.updateTheme();
if (props && props.runtime) {
this.board = this.props.runtime.board;
this.board.updateSubscribers.push(function () { return _this.updateState(); });
this.updateState();
this.attachEvents();
}
}
MicrobitBoardSvg.prototype.getView = function () {
return {
el: this.element,
y: 0,
x: 0,
w: MB_WIDTH,
h: MB_HEIGHT
};
};
MicrobitBoardSvg.prototype.getCoord = function (pinNm) {
return this.pinNmToCoord[pinNm];
};
MicrobitBoardSvg.prototype.highlightPin = function (pinNm) {
//TODO: for instructions
};
MicrobitBoardSvg.prototype.getPinDist = function () {
return 10;
};
MicrobitBoardSvg.prototype.recordPinCoords = function () {
var _this = this;
pinNames.forEach(function (nm, i) {
var p = _this.pins[i];
var r = p.getBoundingClientRect();
_this.pinNmToCoord[nm] = [r.left + r.width / 2, r.top + r.height / 2];
});
console.log(JSON.stringify(this.pinNmToCoord, null, 2));
};
MicrobitBoardSvg.prototype.updateTheme = function () {
var theme = this.props.theme;
pxsim.svg.fills(this.leds, theme.ledOn);
pxsim.svg.fills(this.ledsOuter, theme.ledOff);
pxsim.svg.fills(this.buttonsOuter.slice(0, 2), theme.buttonOuter);
pxsim.svg.fill(this.buttons[0], theme.buttonUps[0]);
pxsim.svg.fill(this.buttons[1], theme.buttonUps[1]);
pxsim.svg.fill(this.buttonsOuter[2], theme.virtualButtonOuter);
pxsim.svg.fill(this.buttons[2], theme.virtualButtonUp);
this.pinGradients.forEach(function (lg) { return pxsim.svg.setGradientColors(lg, theme.pin, theme.pinActive); });
pxsim.svg.setGradientColors(this.lightLevelGradient, theme.lightLevelOn, theme.lightLevelOff);
pxsim.svg.setGradientColors(this.thermometerGradient, theme.ledOff, theme.ledOn);
};
MicrobitBoardSvg.prototype.updateState = function () {
var _this = this;
var state = this.board;
if (!state)
return;
var theme = this.props.theme;
var bpState = state.buttonPairState;
var buttons = [bpState.aBtn, bpState.bBtn, bpState.abBtn];
buttons.forEach(function (btn, index) {
pxsim.svg.fill(_this.buttons[index], btn.pressed ? (btn.virtual ? theme.virtualButtonDown : theme.buttonDown) : (btn.virtual ? theme.virtualButtonUp : theme.buttonUps[index]));
});
if (state.ledMatrixState.disabled) {
this.leds.forEach(function (led, i) {
var sel = led;
sel.style.opacity = "0";
});
}
else {
var bw_1 = state.ledMatrixState.displayMode == pxsim.DisplayMode.bw;
var img_1 = state.ledMatrixState.image;
this.leds.forEach(function (led, i) {
var sel = led;
sel.style.opacity = ((bw_1 ? img_1.data[i] > 0 ? 255 : 0 : img_1.data[i]) / 255.0) + "";
});
}
this.updatePins();
this.updateTilt();
this.updateHeading();
this.updateLightLevel();
this.updateTemperature();
this.updateButtonAB();
this.updateGestures();
this.updateRgbLed();
this.updateSpeaker();
if (!pxsim.runtime || pxsim.runtime.dead)
pxsim.svg.addClass(this.element, "grayscale");
else
pxsim.svg.removeClass(this.element, "grayscale");
};
MicrobitBoardSvg.prototype.updateRgbLed = function () {
var state = this.board;
if (state.rgbLedState) {
if (!this.rgbLed)
this.rgbLed = this.element.getElementById("rgbledcircle");
var c = state.rgbLedState;
var b = c & 0xFF;
var g = (c >> 8) & 0xFF;
var r = (c >> 16) & 0xFF;
var w = (c >> 24) & 0xFF;
var ch = "rgba(" + r + ", " + g + ", " + b + ", 1)";
pxsim.svg.fill(this.rgbLed, ch);
}
else if (this.rgbLed) {
pxsim.svg.fill(this.rgbLed, 'white');
}
};
MicrobitBoardSvg.prototype.updateSpeaker = function () {
var state = this.board;
if (state.speakerState.frequency) {
}
else {
}
};
MicrobitBoardSvg.prototype.updateGestures = function () {
var _this = this;
var state = this.board;
if (state.accelerometerState.useShake && !this.shakeButton) {
var shake = this.mkBtn(26, MB_HEIGHT - 45);
this.shakeButton = shake.inner;
pxsim.svg.fill(this.shakeButton, this.props.theme.virtualButtonUp);
pxsim.svg.buttonEvents(shake.outer, function (ev) { }, function (ev) {
pxsim.svg.fill(_this.shakeButton, _this.props.theme.virtualButtonDown);
}, function (ev) {
pxsim.svg.fill(_this.shakeButton, _this.props.theme.virtualButtonUp);
_this.board.bus.queue(27 /* MICROBIT_ID_GESTURE */, 11); // GESTURE_SHAKE
});
var shakeText = pxsim.svg.child(shake.outer, "text", { x: 15, y: MB_HEIGHT - 10, class: "sim-text inverted" });
shakeText.textContent = "SHAKE";
}
};
MicrobitBoardSvg.prototype.updateButtonAB = function () {
var state = this.board;
if (state.buttonPairState.usesButtonAB && this.buttons[2].style.visibility != "visible") {
this.buttonsOuter[2].style.visibility = "visible";
this.buttons[2].style.visibility = "visible";
this.updateTheme();
}
};
MicrobitBoardSvg.prototype.updatePin = function (pin, index) {
if (!pin)
return;
var text = this.pinTexts[index];
var v = "";
if (pin.mode & pxsim.PinFlags.Analog) {
v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + "%";
if (text)
text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + "";
}
else if (pin.mode & pxsim.PinFlags.Digital) {
v = pin.value > 0 ? "0%" : "100%";
if (text)
text.textContent = pin.value > 0 ? "1" : "0";
}
else if (pin.mode & pxsim.PinFlags.Touch) {
v = pin.touched ? "0%" : "100%";
if (text)
text.textContent = "";
}
else {
v = "100%";
if (text)
text.textContent = "";
}
if (v)
pxsim.svg.setGradientValue(this.pinGradients[index], v);
};
MicrobitBoardSvg.prototype.updateTemperature = function () {
var _this = this;
var state = this.board;
if (!state || !state.thermometerState.usesTemperature)
return;
var tmin = -5;
var tmax = 50;
if (!this.thermometer) {
var gid = "gradient-thermometer";
this.thermometerGradient = pxsim.svg.linearGradient(this.defs, gid);
var ty_1 = MB_HEIGHT - 180;
this.thermometer = pxsim.svg.child(this.g, "rect", {
class: "sim-thermometer",
x: 28,
y: ty_1,
width: 10,
height: 80,
rx: 5, ry: 5,
fill: "url(#" + gid + ")"
});
this.thermometerText = pxsim.svg.child(this.g, "text", {
class: 'sim-text',
x: 48, y: ty_1 + 78
});
this.updateTheme();
var pt_1 = this.element.createSVGPoint();
pxsim.svg.buttonEvents(this.thermometer, function (ev) {
var cur = pxsim.svg.cursorPoint(pt_1, _this.element, ev);
var t = Math.max(0, Math.min(1, (cur.y - ty_1 - 5) / 70));
state.thermometerState.temperature = Math.floor(tmax - t * (tmax - tmin));
_this.updateTemperature();
}, function (ev) { }, function (ev) { });
}
var t = Math.max(tmin, Math.min(tmax, state.thermometerState.temperature));
var per = Math.floor((state.thermometerState.temperature - tmin) / (tmax - tmin) * 100);
pxsim.svg.setGradientValue(this.thermometerGradient, 100 - per + "%");
this.thermometerText.textContent = t + "°C";
};
MicrobitBoardSvg.prototype.updateHeading = function () {
var xc = 258;
var yc = 75;
var state = this.board;
if (!state || !state.compassState.usesHeading)
return;
/*
if (!this.headInitialized) {
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");
this.updateTheme();
let pt = this.element.createSVGPoint();
svg.buttonEvents(
this.head,
(ev: MouseEvent) => {
let cur = svg.cursorPoint(pt, this.element, ev);
state.compassState.heading = Math.floor(Math.atan2(cur.y - yc, cur.x - xc) * 180 / Math.PI + 90);
if (state.compassState.heading < 0) state.compassState.heading += 360;
this.updateHeading();
});
this.headInitialized = true;
}
let txt = state.compassState.heading.toString() + "°";
if (txt != this.headText.textContent) {
svg.rotateElement(this.head, xc, yc, state.compassState.heading + 180);
this.headText.textContent = txt;
} */
};
MicrobitBoardSvg.prototype.flashSystemLed = function () {
if (!this.systemLed)
this.systemLed = pxsim.svg.child(this.g, "circle", { class: "sim-systemled", cx: 160.8, cy: 150.9, r: 4 });
var now = Date.now();
if (now - this.lastFlashTime > 150) {
this.lastFlashTime = now;
pxsim.svg.animate(this.systemLed, "sim-flash");
}
};
MicrobitBoardSvg.prototype.flashAntenna = function () {
if (!this.antenna) {
var ax = 480;
var dax = 18;
var ayt = 10;
var ayb = 40;
this.antenna = pxsim.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 });
}
var now = Date.now();
if (now - this.lastAntennaFlash > 200) {
this.lastAntennaFlash = now;
pxsim.svg.animate(this.antenna, 'sim-flash-stroke');
}
};
MicrobitBoardSvg.prototype.updatePins = function () {
var _this = this;
var state = this.board;
if (!state)
return;
state.edgeConnectorState.pins.forEach(function (pin, i) { return _this.updatePin(pin, i); });
};
MicrobitBoardSvg.prototype.updateLightLevel = function () {
var _this = this;
var state = this.board;
if (!state || !state.lightSensorState.usesLightLevel)
return;
if (!this.lightLevelButton) {
var gid = "gradient-light-level";
this.lightLevelGradient = pxsim.svg.linearGradient(this.defs, gid);
var cx = 30;
var cy_1 = 45;
var r_1 = 20;
this.lightLevelButton = pxsim.svg.child(this.g, "circle", {
cx: cx + "px", cy: cy_1 + "px", r: r_1 + "px",
class: 'sim-light-level-button',
fill: "url(#" + gid + ")"
});
var pt_2 = this.element.createSVGPoint();
pxsim.svg.buttonEvents(this.lightLevelButton, function (ev) {
var pos = pxsim.svg.cursorPoint(pt_2, _this.element, ev);
var rs = r_1 / 2;
var level = Math.max(0, Math.min(255, Math.floor((pos.y - (cy_1 - rs)) / (2 * rs) * 255)));
if (level != _this.board.lightSensorState.lightLevel) {
_this.board.lightSensorState.lightLevel = level;
_this.applyLightLevel();
}
}, function (ev) { }, function (ev) { });
this.lightLevelText = pxsim.svg.child(this.g, "text", { x: cx - r_1 - 7, y: cy_1 + r_1 + 8, text: '', class: 'sim-text inverted' });
this.updateTheme();
}
pxsim.svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(state.lightSensorState.lightLevel * 100 / 255))) + '%');
this.lightLevelText.textContent = state.lightSensorState.lightLevel.toString();
};
MicrobitBoardSvg.prototype.applyLightLevel = function () {
var lv = this.board.lightSensorState.lightLevel;
pxsim.svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(lv * 100 / 255))) + '%');
this.lightLevelText.textContent = lv.toString();
};
MicrobitBoardSvg.prototype.updateTilt = function () {
if (this.props.disableTilt)
return;
var state = this.board;
if (!state || !state.accelerometerState.accelerometer.isActive)
return;
var x = state.accelerometerState.accelerometer.getX();
var y = -state.accelerometerState.accelerometer.getY();
var af = 8 / 1023;
var s = 1 - Math.min(0.1, Math.pow(Math.max(Math.abs(x), Math.abs(y)) / 1023, 2) / 35);
this.element.style.transform = "perspective(30em) rotateX(" + y * af + "deg) rotateY(" + x * af + "deg) scale(" + s + ", " + s + ")";
this.element.style.perspectiveOrigin = "50% 50% 50%";
this.element.style.perspective = "30em";
};
MicrobitBoardSvg.prototype.buildDom = function () {
var _this = this;
this.element = new DOMParser().parseFromString(BOARD_SVG, "image/svg+xml").querySelector("svg");
pxsim.svg.hydrate(this.element, {
"version": "1.0",
"viewBox": "0 0 " + MB_WIDTH + " " + MB_HEIGHT,
"class": "sim",
"x": "0px",
"y": "0px",
"width": MB_WIDTH + "px",
"height": MB_HEIGHT + "px",
});
this.style = pxsim.svg.child(this.element, "style", {});
this.style.textContent = MB_STYLE;
this.defs = pxsim.svg.child(this.element, "defs", {});
this.g = pxsim.svg.elt("g");
this.element.appendChild(this.g);
// filters
var glow = pxsim.svg.child(this.defs, "filter", { id: "filterglow", x: "-5%", y: "-5%", width: "120%", height: "120%" });
pxsim.svg.child(glow, "feGaussianBlur", { stdDeviation: "5", result: "glow" });
var merge = pxsim.svg.child(glow, "feMerge", {});
for (var i = 0; i < 3; ++i)
pxsim.svg.child(merge, "feMergeNode", { in: "glow" });
// leds
this.leds = [];
this.ledsOuter = [];
var left = Number(this.element.getElementById("LED_0_0").getAttribute("x"));
var top = Number(this.element.getElementById("LED_0_0").getAttribute("y"));
var ledoffw = Number(this.element.getElementById("LED_1_0").getAttribute("x")) - left;
var ledoffh = Number(this.element.getElementById("LED_0_1").getAttribute("y")) - top;
var ledw = 5.1;
var ledh = 12.9;
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(pxsim.svg.child(this.g, "rect", { class: "sim-led-back", x: ledleft, y: ledtop, width: ledw, height: ledh }));
this.leds.push(pxsim.svg.child(this.g, "rect", { class: "sim-led", x: ledleft - 1, y: ledtop - 1, width: ledw + 2, height: ledh + 2, rx: 2, ry: 2, title: "(" + j + "," + i + ")" }));
}
}
// https://www.microbit.co.uk/device/pins
// P0, P1, P2
this.pins = pinNames.map(function (n) {
var p = _this.element.getElementById(n);
if (!p)
console.log("missing " + n);
pxsim.svg.addClass(p, "sim-pin");
return p;
});
this.pins.forEach(function (p, i) { return pxsim.svg.hydrate(p, { title: pinTitles[i] }); });
this.pinGradients = this.pins.map(function (pin, i) {
var gid = "gradient-pin-" + i;
var lg = pxsim.svg.linearGradient(_this.defs, gid);
pin.setAttribute("fill", "url(#" + gid + ")");
return lg;
});
this.pinTexts = [67, 165, 275].map(function (x) { return pxsim.svg.child(_this.g, "text", { class: "sim-text-pin", x: x, y: 345 }); });
// BTN A, B
var btnids = ["BTN_A", "BTN_B"];
this.buttonsOuter = btnids.map(function (n) { return _this.element.getElementById(n + "_BOX"); });
this.buttonsOuter.forEach(function (b) { return pxsim.svg.addClass(b, "sim-button-outer"); });
this.buttons = btnids.map(function (n) { return _this.element.getElementById(n); });
this.buttons.forEach(function (b) { return pxsim.svg.addClass(b, "sim-button"); });
// BTN A+B
var outerBtn = function (left, top) {
var button = _this.mkBtn(left, top);
_this.buttonsOuter.push(button.outer);
_this.buttons.push(button.inner);
return button;
};
var ab = outerBtn(69, MB_HEIGHT - 45);
var abtext = pxsim.svg.child(ab.outer, "text", { x: 67, y: MB_HEIGHT - 10, class: "sim-text inverted" });
abtext.textContent = "A+B";
this.buttonsOuter[2].style.visibility = "hidden";
this.buttons[2].style.visibility = "hidden";
};
MicrobitBoardSvg.prototype.mkBtn = function (left, top) {
var btnr = 2;
var btnw = 20;
var btnn = 1.6;
var btnnm = 2;
var btnb = 5;
var btng = pxsim.svg.child(this.g, "g", { class: "sim-button-group" });
pxsim.svg.child(btng, "rect", { class: "sim-button-outer", x: left, y: top, rx: btnr, ry: btnr, width: btnw, height: btnw });
pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnnm, cy: top + btnnm, r: btnn });
pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnnm, cy: top + btnw - btnnm, r: btnn });
pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnw - btnnm, cy: top + btnw - btnnm, r: btnn });
pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnw - btnnm, cy: top + btnnm, r: btnn });
var outer = btng;
var inner = pxsim.svg.child(btng, "circle", {
class: "sim-button",
cx: left + btnw / 2,
cy: top + btnw / 2,
r: btnb
});
return { outer: outer, inner: inner };
};
MicrobitBoardSvg.prototype.attachEvents = function () {
var _this = this;
pxsim.Runtime.messagePosted = function (msg) {
switch (msg.type || "") {
case "serial":
_this.flashSystemLed();
break;
case "radiopacket":
_this.flashAntenna();
break;
}
};
var tiltDecayer = 0;
this.element.addEventListener(pxsim.pointerEvents.move, function (ev) {
var state = _this.board;
if (!state.accelerometerState.accelerometer.isActive)
return;
if (tiltDecayer) {
clearInterval(tiltDecayer);
tiltDecayer = 0;
}
var bbox = _this.element.getBoundingClientRect();
var ax = (ev.clientX - bbox.width / 2) / (bbox.width / 3);
var ay = (ev.clientY - bbox.height / 2) / (bbox.height / 3);
var x = -Math.max(-1023, Math.min(1023, Math.floor(ax * 1023)));
var y = -Math.max(-1023, Math.min(1023, Math.floor(ay * 1023)));
var z2 = 1023 * 1023 - x * x - y * y;
var z = Math.floor((z2 > 0 ? -1 : 1) * Math.sqrt(Math.abs(z2)));
state.accelerometerState.accelerometer.update(x, y, z);
_this.updateTilt();
}, false);
this.element.addEventListener(pxsim.pointerEvents.leave, function (ev) {
var state = _this.board;
if (!state.accelerometerState.accelerometer.isActive)
return;
if (!tiltDecayer) {
tiltDecayer = setInterval(function () {
var accx = state.accelerometerState.accelerometer.getX(pxsim.MicroBitCoordinateSystem.RAW);
accx = Math.floor(Math.abs(accx) * 0.85) * (accx > 0 ? 1 : -1);
var accy = state.accelerometerState.accelerometer.getY(pxsim.MicroBitCoordinateSystem.RAW);
accy = Math.floor(Math.abs(accy) * 0.85) * (accy > 0 ? 1 : -1);
var 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;
accx = 0;
accy = 0;
accz = -1023;
}
state.accelerometerState.accelerometer.update(accx, accy, accz);
_this.updateTilt();
}, 50);
}
}, false);
this.pins.forEach(function (pin, index) {
if (!_this.board.edgeConnectorState.pins[index])
return;
var pt = _this.element.createSVGPoint();
pxsim.svg.buttonEvents(pin,
// move
function (ev) {
var state = _this.board;
var pin = state.edgeConnectorState.pins[index];
var svgpin = _this.pins[index];
if (pin.mode & pxsim.PinFlags.Input) {
var cursor = pxsim.svg.cursorPoint(pt, _this.element, ev);
var v = (400 - cursor.y) / 40 * 1023;
pin.value = Math.max(0, Math.min(1023, Math.floor(v)));
}
_this.updatePin(pin, index);
},
// start
function (ev) {
var state = _this.board;
var pin = state.edgeConnectorState.pins[index];
var svgpin = _this.pins[index];
pxsim.svg.addClass(svgpin, "touched");
if (pin.mode & pxsim.PinFlags.Input) {
var cursor = pxsim.svg.cursorPoint(pt, _this.element, ev);
var v = (400 - cursor.y) / 40 * 1023;
pin.value = Math.max(0, Math.min(1023, Math.floor(v)));
}
_this.updatePin(pin, index);
},
// stop
function (ev) {
var state = _this.board;
var pin = state.edgeConnectorState.pins[index];
var svgpin = _this.pins[index];
pxsim.svg.removeClass(svgpin, "touched");
_this.updatePin(pin, index);
return false;
});
});
this.pins.slice(0, 3).forEach(function (btn, index) {
btn.addEventListener(pxsim.pointerEvents.down, function (ev) {
var state = _this.board;
state.edgeConnectorState.pins[index].touched = true;
_this.updatePin(state.edgeConnectorState.pins[index], index);
});
btn.addEventListener(pxsim.pointerEvents.leave, function (ev) {
var state = _this.board;
state.edgeConnectorState.pins[index].touched = false;
_this.updatePin(state.edgeConnectorState.pins[index], index);
});
btn.addEventListener(pxsim.pointerEvents.up, function (ev) {
var state = _this.board;
state.edgeConnectorState.pins[index].touched = false;
_this.updatePin(state.edgeConnectorState.pins[index], index);
_this.board.bus.queue(state.edgeConnectorState.pins[index].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
_this.board.bus.queue(state.edgeConnectorState.pins[index].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
});
});
var bpState = this.board.buttonPairState;
var stateButtons = [bpState.aBtn, bpState.bBtn, bpState.abBtn];
this.buttonsOuter.slice(0, 2).forEach(function (btn, index) {
btn.addEventListener(pxsim.pointerEvents.down, function (ev) {
var state = _this.board;
stateButtons[index].pressed = true;
pxsim.svg.fill(_this.buttons[index], _this.props.theme.buttonDown);
});
btn.addEventListener(pxsim.pointerEvents.leave, function (ev) {
var state = _this.board;
stateButtons[index].pressed = false;
pxsim.svg.fill(_this.buttons[index], _this.props.theme.buttonUps[index]);
});
btn.addEventListener(pxsim.pointerEvents.up, function (ev) {
var state = _this.board;
stateButtons[index].pressed = false;
pxsim.svg.fill(_this.buttons[index], _this.props.theme.buttonUps[index]);
_this.board.bus.queue(stateButtons[index].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
_this.board.bus.queue(stateButtons[index].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
});
});
this.buttonsOuter[2].addEventListener(pxsim.pointerEvents.down, function (ev) {
var state = _this.board;
stateButtons[0].pressed = true;
stateButtons[1].pressed = true;
stateButtons[2].pressed = true;
pxsim.svg.fill(_this.buttons[0], _this.props.theme.buttonDown);
pxsim.svg.fill(_this.buttons[1], _this.props.theme.buttonDown);
pxsim.svg.fill(_this.buttons[2], _this.props.theme.buttonDown);
});
this.buttonsOuter[2].addEventListener(pxsim.pointerEvents.leave, function (ev) {
var state = _this.board;
stateButtons[0].pressed = false;
stateButtons[1].pressed = false;
stateButtons[2].pressed = false;
pxsim.svg.fill(_this.buttons[0], _this.props.theme.buttonUps[0]);
pxsim.svg.fill(_this.buttons[1], _this.props.theme.buttonUps[1]);
pxsim.svg.fill(_this.buttons[2], _this.props.theme.virtualButtonUp);
});
this.buttonsOuter[2].addEventListener(pxsim.pointerEvents.up, function (ev) {
var state = _this.board;
stateButtons[0].pressed = false;
stateButtons[1].pressed = false;
stateButtons[2].pressed = false;
pxsim.svg.fill(_this.buttons[0], _this.props.theme.buttonUps[0]);
pxsim.svg.fill(_this.buttons[1], _this.props.theme.buttonUps[1]);
pxsim.svg.fill(_this.buttons[2], _this.props.theme.virtualButtonUp);
_this.board.bus.queue(stateButtons[2].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
_this.board.bus.queue(stateButtons[2].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
});
};
return MicrobitBoardSvg;
}());
visuals.MicrobitBoardSvg = MicrobitBoardSvg;
})(visuals = pxsim.visuals || (pxsim.visuals = {}));
})(pxsim || (pxsim = {}));
/// <reference path="../../node_modules/pxt-core/built/pxtsim.d.ts"/>
/// <reference path="../../libs/core/dal.d.ts"/>
/// <reference path="../../libs/core/shims.d.ts"/>
/// <reference path="../../libs/core/enums.d.ts"/>
var pxsim;
(function (pxsim) {
var visuals;
(function (visuals) {
var PIXEL_SPACING = visuals.PIN_DIST * 3;
var PIXEL_RADIUS = visuals.PIN_DIST;
var CANVAS_WIDTH = 1.2 * visuals.PIN_DIST;
var CANVAS_HEIGHT = 12 * visuals.PIN_DIST;
var CANVAS_VIEW_WIDTH = CANVAS_WIDTH;
var CANVAS_VIEW_HEIGHT = CANVAS_HEIGHT;
var CANVAS_VIEW_PADDING = visuals.PIN_DIST * 4;
var CANVAS_LEFT = 1.4 * visuals.PIN_DIST;
var CANVAS_TOP = visuals.PIN_DIST;
// For the instructions parts list
function mkNeoPixelPart(xy) {
if (xy === void 0) { xy = [0, 0]; }
var NP_PART_XOFF = -13.5;
var NP_PART_YOFF = -11;
var NP_PART_WIDTH = 87.5;
var NP_PART_HEIGHT = 190;
var NEOPIXEL_PART_IMG = "<svg viewBox=\"-5 -1 53 112\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:bx=\"https://boxy-svg.com\">\n <rect x=\"2.5\" width=\"38\" height=\"100\" style=\"fill: rgb(68, 68, 68);\"/>\n <rect x=\"11.748\" y=\"3.2\" width=\"1.391\" height=\"2.553\" style=\"fill: none; stroke-linejoin: round; stroke-width: 3; stroke: rgb(165, 103, 52);\"/>\n <rect x=\"20.75\" y=\"3.2\" width=\"1.391\" height=\"2.553\" style=\"fill: none; stroke-linejoin: round; stroke-width: 3; stroke: rgb(165, 103, 52);\"/>\n <rect x=\"29.75\" y=\"3.2\" width=\"1.391\" height=\"2.553\" style=\"fill: none; stroke-linejoin: round; stroke-width: 3; stroke: rgb(165, 103, 52);\"/>\n <g>\n <rect x=\"9\" y=\"16.562\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"9\" y=\"22.562\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"9\" y=\"28.563\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"11.607\" y=\"14.833\" width=\"19.787\" height=\"18.697\" style=\"fill: rgb(0, 0, 0);\"/>\n <ellipse style=\"fill: rgb(216, 216, 216);\" cx=\"21.5\" cy=\"24.181\" rx=\"7\" ry=\"7\"/>\n </g>\n <path d=\"M -7.25 -103.2 L -2.5 -100.003 L -12 -100.003 L -7.25 -103.2 Z\" style=\"fill: rgb(68, 68, 68);\" transform=\"matrix(-1, 0, 0, -1, 0, 0)\" bx:shape=\"triangle -12 -103.2 9.5 3.197 0.5 0 1@ad6f5cac\"/>\n <path d=\"M -16.75 -103.197 L -12 -100 L -21.5 -100 L -16.75 -103.197 Z\" style=\"fill: rgb(68, 68, 68);\" transform=\"matrix(-1, 0, 0, -1, 0, 0)\" bx:shape=\"triangle -21.5 -103.197 9.5 3.197 0.5 0 1@07d73149\"/>\n <path d=\"M -26.25 -103.2 L -21.5 -100.003 L -31 -100.003 L -26.25 -103.2 Z\" style=\"fill: rgb(68, 68, 68);\" transform=\"matrix(-1, 0, 0, -1, 0, 0)\" bx:shape=\"triangle -31 -103.2 9.5 3.197 0.5 0 1@54403e2d\"/>\n <path d=\"M -35.75 -103.197 L -31 -100 L -40.5 -100 L -35.75 -103.197 Z\" style=\"fill: rgb(68, 68, 68);\" transform=\"matrix(-1, 0, 0, -1, 0, 0)\" bx:shape=\"triangle -40.5 -103.197 9.5 3.197 0.5 0 1@21c9b772\"/>\n <g transform=\"matrix(1, 0, 0, 1, 0.000002, 29.999994)\">\n <rect x=\"9\" y=\"16.562\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"9\" y=\"22.562\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"9\" y=\"28.563\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"11.607\" y=\"14.833\" width=\"19.787\" height=\"18.697\" style=\"fill: rgb(0, 0, 0);\"/>\n <ellipse style=\"fill: rgb(216, 216, 216);\" cx=\"21.5\" cy=\"24.181\" rx=\"7\" ry=\"7\"/>\n </g>\n <g transform=\"matrix(1, 0, 0, 1, 0.000005, 59.999992)\">\n <rect x=\"9\" y=\"16.562\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"9\" y=\"22.562\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"9\" y=\"28.563\" width=\"25\" height=\"3.238\" style=\"fill: rgb(216, 216, 216);\"/>\n <rect x=\"11.607\" y=\"14.833\" width=\"19.787\" height=\"18.697\" style=\"fill: rgb(0, 0, 0);\"/>\n <ellipse style=\"fill: rgb(216, 216, 216);\" cx=\"21.5\" cy=\"24.181\" rx=\"7\" ry=\"7\"/>\n </g>\n</svg>";
var x = xy[0], y = xy[1];
var l = x + NP_PART_XOFF;
var t = y + NP_PART_YOFF;
var w = NP_PART_WIDTH;
var h = NP_PART_HEIGHT;
var img = pxsim.svg.elt("image");
pxsim.svg.hydrate(img, {
class: "sim-neopixel-strip", x: l, y: t, width: w, height: h,
href: pxsim.svg.toDataUri(NEOPIXEL_PART_IMG)
});
return { el: img, x: l, y: t, w: w, h: h };
}
visuals.mkNeoPixelPart = mkNeoPixelPart;
var NeoPixel = (function () {
function NeoPixel(xy) {
if (xy === void 0) { xy = [0, 0]; }
var el = pxsim.svg.elt("rect");
var r = PIXEL_RADIUS;
var cx = xy[0], cy = xy[1];
var y = cy - r;
pxsim.svg.hydrate(el, { x: "-50%", y: y, width: "100%", height: r * 2, class: "sim-neopixel" });
this.el = el;
this.cy = cy;
}
NeoPixel.prototype.setRgb = function (rgb) {
var hsl = visuals.rgbToHsl(rgb);
var h = hsl[0], s = hsl[1], l = hsl[2];
// at least 70% luminosity
l = Math.max(l, 60);
var fill = "hsl(" + h + ", " + s + "%, " + l + "%)";
this.el.setAttribute("fill", fill);
};
return NeoPixel;
}());
visuals.NeoPixel = NeoPixel;
var NeoPixelCanvas = (function () {
function NeoPixelCanvas(pin) {
this.pixels = [];
this.pin = pin;
var el = pxsim.svg.elt("svg");
pxsim.svg.hydrate(el, {
"class": "sim-neopixel-canvas",
"x": "0px",
"y": "0px",
"width": CANVAS_WIDTH + "px",
"height": CANVAS_HEIGHT + "px",
});
this.canvas = el;
this.background = pxsim.svg.child(el, "rect", { class: "sim-neopixel-background hidden" });
this.updateViewBox(-CANVAS_VIEW_WIDTH / 2, 0, CANVAS_VIEW_WIDTH, CANVAS_VIEW_HEIGHT);
}
NeoPixelCanvas.prototype.updateViewBox = function (x, y, w, h) {
this.viewBox = [x, y, w, h];
pxsim.svg.hydrate(this.canvas, { "viewBox": x + " " + y + " " + w + " " + h });
pxsim.svg.hydrate(this.background, { "x": x, "y": y, "width": w, "height": h });
};
NeoPixelCanvas.prototype.update = function (colors) {
if (!colors || colors.length <= 0)
return;
for (var i = 0; i < colors.length; i++) {
var pixel = this.pixels[i];
if (!pixel) {
var cxy = [0, CANVAS_VIEW_PADDING + i * PIXEL_SPACING];
pixel = this.pixels[i] = new NeoPixel(cxy);
pxsim.svg.hydrate(pixel.el, { title: "offset: " + i });
this.canvas.appendChild(pixel.el);
}
var color = colors[i];
pixel.setRgb(color);
}
//show the canvas if it's hidden
pxsim.svg.removeClass(this.background, "hidden");
//resize if necessary
var _a = [this.pixels[0], this.pixels[this.pixels.length - 1]], first = _a[0], last = _a[1];
var yDiff = last.cy - first.cy;
var newH = yDiff + CANVAS_VIEW_PADDING * 2;
var _b = this.viewBox, oldX = _b[0], oldY = _b[1], oldW = _b[2], oldH = _b[3];
if (oldH < newH) {
var scalar = newH / oldH;
var newW = oldW * scalar;
this.updateViewBox(-newW / 2, oldY, newW, newH);
}
};
NeoPixelCanvas.prototype.setLoc = function (xy) {
var x = xy[0], y = xy[1];
pxsim.svg.hydrate(this.canvas, { x: x, y: y });
};
return NeoPixelCanvas;
}());
visuals.NeoPixelCanvas = NeoPixelCanvas;
;
function digitalPinToPinNumber(gpioPin) {
var MICROBIT_ID_IO_P0 = 7; //TODO: don't hardcode this, import enums.d.ts
if (gpioPin == "*") {
return MICROBIT_ID_IO_P0;
}
var pinSplit = gpioPin.split("DigitalPin.P");
pxsim.U.assert(pinSplit.length === 2, "Unknown format for pin (for NeoPixel): " + gpioPin);
var pinNumStr = pinSplit[1];
var pinNum = Number(pinNumStr) + MICROBIT_ID_IO_P0;
return pinNum;
}
function parseNeoPixelMode(modeStr) {
var modeMap = {
"NeoPixelMode.RGB": pxsim.NeoPixelMode.RGB,
"NeoPixelMode.RGBW": pxsim.NeoPixelMode.RGBW
};
return modeMap[modeStr] || pxsim.NeoPixelMode.RGB;
}
var NeoPixelView = (function () {
function NeoPixelView() {
this.style = "\n .sim-neopixel-canvas {\n }\n .sim-neopixel-canvas-parent:hover {\n transform-origin: center;\n transform: scale(4) translateY(-60px);\n }\n .sim-neopixel-canvas .hidden {\n visibility:hidden;\n }\n .sim-neopixel-background {\n fill: rgba(255,255,255,0.9);\n }\n .sim-neopixel-strip {\n }\n ";
}
NeoPixelView.prototype.init = function (bus, state, svgEl, otherParams) {
pxsim.U.assert(!!otherParams["mode"], "NeoPixels assumes a RGB vs RGBW mode is passed to it");
pxsim.U.assert(!!otherParams["pin"], "NeoPixels assumes a pin is passed to it");
var modeStr = otherParams["mode"];
this.mode = parseNeoPixelMode(modeStr);
this.state = state;
this.stripGroup = pxsim.svg.elt("g");
this.element = this.stripGroup;
var pinStr = otherParams["pin"];
this.pin = digitalPinToPinNumber(pinStr);
this.lastLocation = [0, 0];
var part = mkNeoPixelPart();
this.part = part;
this.stripGroup.appendChild(part.el);
var canvas = new NeoPixelCanvas(this.pin);
this.canvas = canvas;
var canvasG = pxsim.svg.elt("g", { class: "sim-neopixel-canvas-parent" });
this.overElement = canvasG;
canvasG.appendChild(canvas.canvas);
this.updateStripLoc();
};
NeoPixelView.prototype.moveToCoord = function (xy) {
var x = xy[0], y = xy[1];
var loc = [x, y];
this.lastLocation = loc;
this.updateStripLoc();
};
NeoPixelView.prototype.updateStripLoc = function () {
var _a = this.lastLocation, x = _a[0], y = _a[1];
pxsim.U.assert(typeof x === "number" && typeof y === "number", "invalid x,y for NeoPixel strip");
this.canvas.setLoc([x + CANVAS_LEFT, y + CANVAS_TOP]);
pxsim.svg.hydrate(this.part.el, { transform: "translate(" + x + " " + y + ")" }); //TODO: update part's l,h, etc.
};
NeoPixelView.prototype.updateState = function () {
var colors = this.state.getColors(this.pin, this.mode);
this.canvas.update(colors);
};
NeoPixelView.prototype.updateTheme = function () { };
return NeoPixelView;
}());
visuals.NeoPixelView = NeoPixelView;
})(visuals = pxsim.visuals || (pxsim.visuals = {}));
})(pxsim || (pxsim = {}));