2848 lines
190 KiB
JavaScript
2848 lines
190 KiB
JavaScript
|
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 = {}));
|