Advertisement
Guest User

Untitled

a guest
Feb 21st, 2019
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 164.28 KB | None | 0 0
  1. var __extends = (this && this.__extends) || (function () {
  2. var extendStatics = Object.setPrototypeOf ||
  3. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  4. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  5. return function (d, b) {
  6. extendStatics(d, b);
  7. function __() { this.constructor = d; }
  8. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  9. };
  10. })();
  11. /// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
  12. var pxsim;
  13. (function (pxsim) {
  14. var DalBoard = /** @class */ (function (_super) {
  15. __extends(DalBoard, _super);
  16. function DalBoard() {
  17. var _this = _super.call(this) || this;
  18. // components
  19. _this.fileSystem = new pxsim.FileSystemState();
  20. _this.builtinParts["ledmatrix"] = _this.ledMatrixState = new pxsim.LedMatrixState(pxsim.runtime);
  21. _this.builtinParts["buttonpair"] = _this.buttonPairState = new pxsim.ButtonPairState({
  22. ID_BUTTON_A: 1 /* MICROBIT_ID_BUTTON_A */,
  23. ID_BUTTON_B: 2 /* MICROBIT_ID_BUTTON_B */,
  24. ID_BUTTON_AB: 26 /* MICROBIT_ID_BUTTON_AB */,
  25. BUTTON_EVT_UP: 2 /* MICROBIT_BUTTON_EVT_UP */,
  26. BUTTON_EVT_CLICK: 3 /* MICROBIT_BUTTON_EVT_CLICK */
  27. });
  28. _this.builtinParts["edgeconnector"] = _this.edgeConnectorState = new pxsim.EdgeConnectorState({
  29. pins: [
  30. 7 /* MICROBIT_ID_IO_P0 */,
  31. 8 /* MICROBIT_ID_IO_P1 */,
  32. 9 /* MICROBIT_ID_IO_P2 */,
  33. 10 /* MICROBIT_ID_IO_P3 */,
  34. 11 /* MICROBIT_ID_IO_P4 */,
  35. 12 /* MICROBIT_ID_IO_P5 */,
  36. 13 /* MICROBIT_ID_IO_P6 */,
  37. 14 /* MICROBIT_ID_IO_P7 */,
  38. 15 /* MICROBIT_ID_IO_P8 */,
  39. 16 /* MICROBIT_ID_IO_P9 */,
  40. 17 /* MICROBIT_ID_IO_P10 */,
  41. 18 /* MICROBIT_ID_IO_P11 */,
  42. 19 /* MICROBIT_ID_IO_P12 */,
  43. 20 /* MICROBIT_ID_IO_P13 */,
  44. 21 /* MICROBIT_ID_IO_P14 */,
  45. 22 /* MICROBIT_ID_IO_P15 */,
  46. 23 /* MICROBIT_ID_IO_P16 */,
  47. 0,
  48. 0,
  49. 24 /* MICROBIT_ID_IO_P19 */,
  50. 25 /* MICROBIT_ID_IO_P20 */
  51. ],
  52. servos: {
  53. "P0": 7 /* MICROBIT_ID_IO_P0 */,
  54. "P1": 8 /* MICROBIT_ID_IO_P1 */,
  55. "P2": 9 /* MICROBIT_ID_IO_P2 */,
  56. "P3": 10 /* MICROBIT_ID_IO_P3 */,
  57. "P4": 11 /* MICROBIT_ID_IO_P4 */,
  58. "P5": 12 /* MICROBIT_ID_IO_P5 */,
  59. "P6": 13 /* MICROBIT_ID_IO_P6 */,
  60. "P7": 14 /* MICROBIT_ID_IO_P7 */,
  61. "P8": 15 /* MICROBIT_ID_IO_P8 */,
  62. "P9": 16 /* MICROBIT_ID_IO_P9 */,
  63. "P10": 17 /* MICROBIT_ID_IO_P10 */,
  64. "P11": 18 /* MICROBIT_ID_IO_P11 */,
  65. "P12": 19 /* MICROBIT_ID_IO_P12 */,
  66. "P13": 20 /* MICROBIT_ID_IO_P13 */,
  67. "P14": 21 /* MICROBIT_ID_IO_P14 */,
  68. "P15": 22 /* MICROBIT_ID_IO_P15 */,
  69. "P16": 23 /* MICROBIT_ID_IO_P16 */,
  70. "P19": 24 /* MICROBIT_ID_IO_P19 */
  71. }
  72. });
  73. _this.builtinParts["radio"] = _this.radioState = new pxsim.RadioState(pxsim.runtime);
  74. _this.builtinParts["accelerometer"] = _this.accelerometerState = new pxsim.AccelerometerState(pxsim.runtime);
  75. _this.builtinParts["serial"] = _this.serialState = new pxsim.SerialState();
  76. _this.builtinParts["thermometer"] = _this.thermometerState = new pxsim.ThermometerState();
  77. _this.builtinParts["lightsensor"] = _this.lightSensorState = new pxsim.LightSensorState();
  78. _this.builtinParts["compass"] = _this.compassState = new pxsim.CompassState();
  79. _this.builtinParts["neopixel"] = _this.neopixelState = new pxsim.NeoPixelState();
  80. _this.builtinParts["microservo"] = _this.edgeConnectorState;
  81. _this.builtinVisuals["buttonpair"] = function () { return new pxsim.visuals.ButtonPairView(); };
  82. _this.builtinVisuals["ledmatrix"] = function () { return new pxsim.visuals.LedMatrixView(); };
  83. _this.builtinVisuals["neopixel"] = function () { return new pxsim.visuals.NeoPixelView(); };
  84. _this.builtinVisuals["microservo"] = function () { return new pxsim.visuals.MicroServoView(); };
  85. _this.builtinPartVisuals["buttonpair"] = function (xy) { return pxsim.visuals.mkBtnSvg(xy); };
  86. _this.builtinPartVisuals["ledmatrix"] = function (xy) { return pxsim.visuals.mkLedMatrixSvg(xy, 8, 8); };
  87. _this.builtinPartVisuals["neopixel"] = function (xy) { return pxsim.visuals.mkNeoPixelPart(xy); };
  88. _this.builtinPartVisuals["microservo"] = function (xy) { return pxsim.visuals.mkMicroServoPart(xy); };
  89. return _this;
  90. }
  91. DalBoard.prototype.receiveMessage = function (msg) {
  92. if (!pxsim.runtime || pxsim.runtime.dead)
  93. return;
  94. switch (msg.type || "") {
  95. case "eventbus":
  96. var ev = msg;
  97. this.bus.queue(ev.id, ev.eventid, ev.value);
  98. break;
  99. case "serial":
  100. var data = msg.data || "";
  101. this.serialState.receiveData(data);
  102. break;
  103. case "radiopacket":
  104. var packet = msg;
  105. this.radioState.receivePacket(packet);
  106. break;
  107. }
  108. };
  109. DalBoard.prototype.initAsync = function (msg) {
  110. _super.prototype.initAsync.call(this, msg);
  111. var options = (msg.options || {});
  112. var boardDef = msg.boardDefinition;
  113. var cmpsList = msg.parts;
  114. var cmpDefs = msg.partDefinitions || {};
  115. var fnArgs = msg.fnArgs;
  116. var opts = {
  117. state: this,
  118. boardDef: boardDef,
  119. partsList: cmpsList,
  120. partDefs: cmpDefs,
  121. fnArgs: fnArgs,
  122. maxWidth: "100%",
  123. maxHeight: "100%",
  124. highContrast: msg.highContrast
  125. };
  126. var viewHost = new pxsim.visuals.BoardHost(pxsim.visuals.mkBoardView({
  127. visual: boardDef.visual,
  128. highContrast: msg.highContrast
  129. }), opts);
  130. document.body.innerHTML = ""; // clear children
  131. document.body.appendChild(this.view = viewHost.getView());
  132. return Promise.resolve();
  133. };
  134. DalBoard.prototype.screenshot = function () {
  135. return pxsim.svg.toDataUri(new XMLSerializer().serializeToString(this.view));
  136. };
  137. return DalBoard;
  138. }(pxsim.CoreBoard));
  139. pxsim.DalBoard = DalBoard;
  140. function initRuntimeWithDalBoard() {
  141. pxsim.U.assert(!pxsim.runtime.board);
  142. var b = new DalBoard();
  143. pxsim.runtime.board = b;
  144. pxsim.runtime.postError = function (e) {
  145. pxsim.led.setBrightness(255);
  146. var img = board().ledMatrixState.image;
  147. img.clear();
  148. img.set(0, 4, 255);
  149. img.set(1, 3, 255);
  150. img.set(2, 3, 255);
  151. img.set(3, 3, 255);
  152. img.set(4, 4, 255);
  153. img.set(0, 0, 255);
  154. img.set(1, 0, 255);
  155. img.set(0, 1, 255);
  156. img.set(1, 1, 255);
  157. img.set(3, 0, 255);
  158. img.set(4, 0, 255);
  159. img.set(3, 1, 255);
  160. img.set(4, 1, 255);
  161. pxsim.runtime.updateDisplay();
  162. };
  163. }
  164. pxsim.initRuntimeWithDalBoard = initRuntimeWithDalBoard;
  165. if (!pxsim.initCurrentRuntime) {
  166. pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
  167. }
  168. function board() {
  169. return pxsim.runtime.board;
  170. }
  171. pxsim.board = board;
  172. })(pxsim || (pxsim = {}));
  173. var pxsim;
  174. (function (pxsim) {
  175. var input;
  176. (function (input) {
  177. function onGesture(gesture, handler) {
  178. var b = pxsim.board().accelerometerState;
  179. b.accelerometer.activate();
  180. if (gesture == 11 && !b.useShake) {
  181. b.useShake = true;
  182. pxsim.runtime.queueDisplayUpdate();
  183. }
  184. pxsim.pxtcore.registerWithDal(27 /* MICROBIT_ID_GESTURE */, gesture, handler);
  185. }
  186. input.onGesture = onGesture;
  187. function acceleration(dimension) {
  188. var b = pxsim.board().accelerometerState;
  189. var acc = b.accelerometer;
  190. switch (dimension) {
  191. case 0:
  192. acc.activate(pxsim.AccelerometerFlag.X);
  193. return acc.getX();
  194. case 1:
  195. acc.activate(pxsim.AccelerometerFlag.Y);
  196. return acc.getY();
  197. case 2:
  198. acc.activate(pxsim.AccelerometerFlag.Z);
  199. return acc.getZ();
  200. default:
  201. acc.activate();
  202. return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
  203. }
  204. }
  205. input.acceleration = acceleration;
  206. function rotation(kind) {
  207. var b = pxsim.board().accelerometerState;
  208. var acc = b.accelerometer;
  209. acc.activate();
  210. var x = acc.getX(pxsim.MicroBitCoordinateSystem.NORTH_EAST_DOWN);
  211. var y = acc.getY(pxsim.MicroBitCoordinateSystem.NORTH_EAST_DOWN);
  212. var z = acc.getZ(pxsim.MicroBitCoordinateSystem.NORTH_EAST_DOWN);
  213. var roll = Math.atan2(y, z);
  214. var pitch = Math.atan(-x / (y * Math.sin(roll) + z * Math.cos(roll)));
  215. var r = 0;
  216. switch (kind) {
  217. case 0:
  218. r = pitch;
  219. break;
  220. case 1:
  221. r = roll;
  222. break;
  223. }
  224. return Math.floor(r / Math.PI * 180);
  225. }
  226. input.rotation = rotation;
  227. function setAccelerometerRange(range) {
  228. var b = pxsim.board().accelerometerState;
  229. b.accelerometer.setSampleRange(range);
  230. }
  231. input.setAccelerometerRange = setAccelerometerRange;
  232. })(input = pxsim.input || (pxsim.input = {}));
  233. })(pxsim || (pxsim = {}));
  234. (function (pxsim) {
  235. /**
  236. * Co-ordinate systems that can be used.
  237. * RAW: Unaltered data. Data will be returned directly from the accelerometer.
  238. *
  239. * SIMPLE_CARTESIAN: Data will be returned based on an easy to understand alignment, consistent with the cartesian system taught in schools.
  240. * When held upright, facing the user:
  241. *
  242. * /
  243. * +--------------------+ z
  244. * | |
  245. * | ..... |
  246. * | * ..... * |
  247. * ^ | ..... |
  248. * | | |
  249. * y +--------------------+ x-->
  250. *
  251. *
  252. * NORTH_EAST_DOWN: Data will be returned based on the industry convention of the North East Down (NED) system.
  253. * When held upright, facing the user:
  254. *
  255. * z
  256. * +--------------------+ /
  257. * | |
  258. * | ..... |
  259. * | * ..... * |
  260. * ^ | ..... |
  261. * | | |
  262. * x +--------------------+ y-->
  263. *
  264. */
  265. var MicroBitCoordinateSystem;
  266. (function (MicroBitCoordinateSystem) {
  267. MicroBitCoordinateSystem[MicroBitCoordinateSystem["RAW"] = 0] = "RAW";
  268. MicroBitCoordinateSystem[MicroBitCoordinateSystem["SIMPLE_CARTESIAN"] = 1] = "SIMPLE_CARTESIAN";
  269. MicroBitCoordinateSystem[MicroBitCoordinateSystem["NORTH_EAST_DOWN"] = 2] = "NORTH_EAST_DOWN";
  270. })(MicroBitCoordinateSystem = pxsim.MicroBitCoordinateSystem || (pxsim.MicroBitCoordinateSystem = {}));
  271. var AccelerometerFlag;
  272. (function (AccelerometerFlag) {
  273. AccelerometerFlag[AccelerometerFlag["X"] = 1] = "X";
  274. AccelerometerFlag[AccelerometerFlag["Y"] = 2] = "Y";
  275. AccelerometerFlag[AccelerometerFlag["Z"] = 4] = "Z";
  276. })(AccelerometerFlag = pxsim.AccelerometerFlag || (pxsim.AccelerometerFlag = {}));
  277. var Accelerometer = /** @class */ (function () {
  278. function Accelerometer(runtime) {
  279. this.runtime = runtime;
  280. this.sigma = 0; // the number of ticks that the instantaneous gesture has been stable.
  281. this.lastGesture = 0; // the last, stable gesture recorded.
  282. this.currentGesture = 0; // the instantaneous, unfiltered gesture detected.
  283. this.sample = { x: 0, y: 0, z: -1023 };
  284. this.shake = { x: false, y: false, z: false, count: 0, shaken: 0, timer: 0 }; // State information needed to detect shake events.
  285. this.isActive = false;
  286. this.sampleRange = 2;
  287. this.flags = 0;
  288. this.id = 4 /* MICROBIT_ID_ACCELEROMETER */;
  289. }
  290. Accelerometer.prototype.setSampleRange = function (range) {
  291. this.activate();
  292. this.sampleRange = Math.max(1, Math.min(8, range));
  293. };
  294. Accelerometer.prototype.activate = function (flags) {
  295. if (!this.isActive) {
  296. this.isActive = true;
  297. this.runtime.queueDisplayUpdate();
  298. }
  299. if (flags)
  300. this.flags |= flags;
  301. };
  302. /**
  303. * Reads the acceleration data from the accelerometer, and stores it in our buffer.
  304. * This is called by the tick() member function, if the interrupt is set!
  305. */
  306. Accelerometer.prototype.update = function (x, y, z) {
  307. // read MSB values...
  308. this.sample.x = Math.floor(x);
  309. this.sample.y = Math.floor(y);
  310. this.sample.z = Math.floor(z);
  311. // Update gesture tracking
  312. this.updateGesture();
  313. // Indicate that a new sample is available
  314. pxsim.board().bus.queue(this.id, 1 /* MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE */);
  315. };
  316. Accelerometer.prototype.instantaneousAccelerationSquared = function () {
  317. // Use pythagoras theorem to determine the combined force acting on the device.
  318. return this.sample.x * this.sample.x + this.sample.y * this.sample.y + this.sample.z * this.sample.z;
  319. };
  320. /**
  321. * Service function. Determines the best guess posture of the device based on instantaneous data.
  322. * This makes no use of historic data (except for shake), and forms this input to the filter implemented in updateGesture().
  323. *
  324. * @return A best guess of the current posture of the device, based on instantaneous data.
  325. */
  326. Accelerometer.prototype.instantaneousPosture = function () {
  327. var force = this.instantaneousAccelerationSquared();
  328. var shakeDetected = false;
  329. // Test for shake events.
  330. // 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
  331. // 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).
  332. //
  333. // If we see enough zero crossings in succession (MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD), then we decide that the device
  334. // has been shaken.
  335. if ((this.getX() < -400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && this.shake.x) || (this.getX() > 400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && !this.shake.x)) {
  336. shakeDetected = true;
  337. this.shake.x = !this.shake.x;
  338. }
  339. if ((this.getY() < -400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && this.shake.y) || (this.getY() > 400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && !this.shake.y)) {
  340. shakeDetected = true;
  341. this.shake.y = !this.shake.y;
  342. }
  343. if ((this.getZ() < -400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && this.shake.z) || (this.getZ() > 400 /* MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE */ && !this.shake.z)) {
  344. shakeDetected = true;
  345. this.shake.z = !this.shake.z;
  346. }
  347. if (shakeDetected && this.shake.count < 4 /* MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD */ && ++this.shake.count == 4 /* MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD */)
  348. this.shake.shaken = 1;
  349. if (++this.shake.timer >= 10 /* MICROBIT_ACCELEROMETER_SHAKE_DAMPING */) {
  350. this.shake.timer = 0;
  351. if (this.shake.count > 0) {
  352. if (--this.shake.count == 0)
  353. this.shake.shaken = 0;
  354. }
  355. }
  356. if (this.shake.shaken)
  357. return 11 /* MICROBIT_ACCELEROMETER_EVT_SHAKE */;
  358. var sq = function (n) { return n * n; };
  359. if (force < sq(400 /* MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE */))
  360. return 7 /* MICROBIT_ACCELEROMETER_EVT_FREEFALL */;
  361. if (force > sq(3072 /* MICROBIT_ACCELEROMETER_3G_TOLERANCE */))
  362. return 8 /* MICROBIT_ACCELEROMETER_EVT_3G */;
  363. if (force > sq(6144 /* MICROBIT_ACCELEROMETER_6G_TOLERANCE */))
  364. return 9 /* MICROBIT_ACCELEROMETER_EVT_6G */;
  365. if (force > sq(8192 /* MICROBIT_ACCELEROMETER_8G_TOLERANCE */))
  366. return 10 /* MICROBIT_ACCELEROMETER_EVT_8G */;
  367. // Determine our posture.
  368. if (this.getX() < (-1000 + 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
  369. return 3 /* MICROBIT_ACCELEROMETER_EVT_TILT_LEFT */;
  370. if (this.getX() > (1000 - 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
  371. return 4 /* MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT */;
  372. if (this.getY() < (-1000 + 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
  373. return 2 /* MICROBIT_ACCELEROMETER_EVT_TILT_DOWN */;
  374. if (this.getY() > (1000 - 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
  375. return 1 /* MICROBIT_ACCELEROMETER_EVT_TILT_UP */;
  376. if (this.getZ() < (-1000 + 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
  377. return 5 /* MICROBIT_ACCELEROMETER_EVT_FACE_UP */;
  378. if (this.getZ() > (1000 - 200 /* MICROBIT_ACCELEROMETER_TILT_TOLERANCE */))
  379. return 6 /* MICROBIT_ACCELEROMETER_EVT_FACE_DOWN */;
  380. return 0;
  381. };
  382. Accelerometer.prototype.updateGesture = function () {
  383. // Determine what it looks like we're doing based on the latest sample...
  384. var g = this.instantaneousPosture();
  385. // Perform some low pass filtering to reduce jitter from any detected effects
  386. if (g == this.currentGesture) {
  387. if (this.sigma < 5 /* MICROBIT_ACCELEROMETER_GESTURE_DAMPING */)
  388. this.sigma++;
  389. }
  390. else {
  391. this.currentGesture = g;
  392. this.sigma = 0;
  393. }
  394. // If we've reached threshold, update our record and raise the relevant event...
  395. if (this.currentGesture != this.lastGesture && this.sigma >= 5 /* MICROBIT_ACCELEROMETER_GESTURE_DAMPING */) {
  396. this.lastGesture = this.currentGesture;
  397. pxsim.board().bus.queue(27 /* MICROBIT_ID_GESTURE */, this.lastGesture);
  398. }
  399. };
  400. /**
  401. * Reads the X axis value of the latest update from the accelerometer.
  402. * @param system The coordinate system to use. By default, a simple cartesian system is provided.
  403. * @return The force measured in the X axis, in milli-g.
  404. *
  405. * Example:
  406. * @code
  407. * uBit.accelerometer.getX();
  408. * uBit.accelerometer.getX(RAW);
  409. * @endcode
  410. */
  411. Accelerometer.prototype.getX = function (system) {
  412. if (system === void 0) { system = MicroBitCoordinateSystem.SIMPLE_CARTESIAN; }
  413. this.activate();
  414. switch (system) {
  415. case MicroBitCoordinateSystem.SIMPLE_CARTESIAN:
  416. return -this.sample.x;
  417. case MicroBitCoordinateSystem.NORTH_EAST_DOWN:
  418. return this.sample.y;
  419. //case MicroBitCoordinateSystem.SIMPLE_CARTESIAN.RAW:
  420. default:
  421. return this.sample.x;
  422. }
  423. };
  424. /**
  425. * Reads the Y axis value of the latest update from the accelerometer.
  426. * @param system The coordinate system to use. By default, a simple cartesian system is provided.
  427. * @return The force measured in the Y axis, in milli-g.
  428. *
  429. * Example:
  430. * @code
  431. * uBit.accelerometer.getY();
  432. * uBit.accelerometer.getY(RAW);
  433. * @endcode
  434. */
  435. Accelerometer.prototype.getY = function (system) {
  436. if (system === void 0) { system = MicroBitCoordinateSystem.SIMPLE_CARTESIAN; }
  437. this.activate();
  438. switch (system) {
  439. case MicroBitCoordinateSystem.SIMPLE_CARTESIAN:
  440. return -this.sample.y;
  441. case MicroBitCoordinateSystem.NORTH_EAST_DOWN:
  442. return -this.sample.x;
  443. //case RAW:
  444. default:
  445. return this.sample.y;
  446. }
  447. };
  448. /**
  449. * Reads the Z axis value of the latest update from the accelerometer.
  450. * @param system The coordinate system to use. By default, a simple cartesian system is provided.
  451. * @return The force measured in the Z axis, in milli-g.
  452. *
  453. * Example:
  454. * @code
  455. * uBit.accelerometer.getZ();
  456. * uBit.accelerometer.getZ(RAW);
  457. * @endcode
  458. */
  459. Accelerometer.prototype.getZ = function (system) {
  460. if (system === void 0) { system = MicroBitCoordinateSystem.SIMPLE_CARTESIAN; }
  461. this.activate();
  462. switch (system) {
  463. case MicroBitCoordinateSystem.NORTH_EAST_DOWN:
  464. return -this.sample.z;
  465. //case MicroBitCoordinateSystem.SIMPLE_CARTESIAN:
  466. //case MicroBitCoordinateSystem.RAW:
  467. default:
  468. return this.sample.z;
  469. }
  470. };
  471. /**
  472. * Provides a rotation compensated pitch of the device, based on the latest update from the accelerometer.
  473. * @return The pitch of the device, in degrees.
  474. *
  475. * Example:
  476. * @code
  477. * uBit.accelerometer.getPitch();
  478. * @endcode
  479. */
  480. Accelerometer.prototype.getPitch = function () {
  481. this.activate();
  482. return Math.floor((360 * this.getPitchRadians()) / (2 * Math.PI));
  483. };
  484. Accelerometer.prototype.getPitchRadians = function () {
  485. this.recalculatePitchRoll();
  486. return this.pitch;
  487. };
  488. /**
  489. * Provides a rotation compensated roll of the device, based on the latest update from the accelerometer.
  490. * @return The roll of the device, in degrees.
  491. *
  492. * Example:
  493. * @code
  494. * uBit.accelerometer.getRoll();
  495. * @endcode
  496. */
  497. Accelerometer.prototype.getRoll = function () {
  498. this.activate();
  499. return Math.floor((360 * this.getRollRadians()) / (2 * Math.PI));
  500. };
  501. Accelerometer.prototype.getRollRadians = function () {
  502. this.recalculatePitchRoll();
  503. return this.roll;
  504. };
  505. /**
  506. * Recalculate roll and pitch values for the current sample.
  507. * We only do this at most once per sample, as the necessary trigonemteric functions are rather
  508. * heavyweight for a CPU without a floating point unit...
  509. */
  510. Accelerometer.prototype.recalculatePitchRoll = function () {
  511. var x = this.getX(MicroBitCoordinateSystem.NORTH_EAST_DOWN);
  512. var y = this.getY(MicroBitCoordinateSystem.NORTH_EAST_DOWN);
  513. var z = this.getZ(MicroBitCoordinateSystem.NORTH_EAST_DOWN);
  514. this.roll = Math.atan2(y, z);
  515. this.pitch = Math.atan(-x / (y * Math.sin(this.roll) + z * Math.cos(this.roll)));
  516. };
  517. return Accelerometer;
  518. }());
  519. pxsim.Accelerometer = Accelerometer;
  520. var AccelerometerState = /** @class */ (function () {
  521. function AccelerometerState(runtime) {
  522. this.useShake = false;
  523. this.accelerometer = new Accelerometer(runtime);
  524. }
  525. return AccelerometerState;
  526. }());
  527. pxsim.AccelerometerState = AccelerometerState;
  528. })(pxsim || (pxsim = {}));
  529. var pxsim;
  530. (function (pxsim) {
  531. var input;
  532. (function (input) {
  533. function onButtonPressed(button, handler) {
  534. var b = pxsim.board().buttonPairState;
  535. if (button == b.props.ID_BUTTON_AB && !b.usesButtonAB) {
  536. b.usesButtonAB = true;
  537. pxsim.runtime.queueDisplayUpdate();
  538. }
  539. pxsim.pxtcore.registerWithDal(button, 3 /* MICROBIT_BUTTON_EVT_CLICK */, handler);
  540. }
  541. input.onButtonPressed = onButtonPressed;
  542. function buttonIsPressed(button) {
  543. var b = pxsim.board().buttonPairState;
  544. if (button == b.abBtn.id && !b.usesButtonAB) {
  545. b.usesButtonAB = true;
  546. pxsim.runtime.queueDisplayUpdate();
  547. }
  548. if (button == b.aBtn.id)
  549. return b.aBtn.pressed;
  550. if (button == b.bBtn.id)
  551. return b.bBtn.pressed;
  552. return b.abBtn.pressed || (b.aBtn.pressed && b.bBtn.pressed);
  553. }
  554. input.buttonIsPressed = buttonIsPressed;
  555. })(input = pxsim.input || (pxsim.input = {}));
  556. })(pxsim || (pxsim = {}));
  557. var pxsim;
  558. (function (pxsim) {
  559. var visuals;
  560. (function (visuals) {
  561. function mkBtnSvg(xy) {
  562. var _a = ["sim-button", "sim-button-outer"], innerCls = _a[0], outerCls = _a[1];
  563. var tabSize = visuals.PIN_DIST / 2.5;
  564. var pegR = visuals.PIN_DIST / 5;
  565. var btnR = visuals.PIN_DIST * .8;
  566. var pegMargin = visuals.PIN_DIST / 8;
  567. var plateR = visuals.PIN_DIST / 12;
  568. var pegOffset = pegMargin + pegR;
  569. var x = xy[0], y = xy[1];
  570. var left = x - tabSize / 2;
  571. var top = y - tabSize / 2;
  572. var plateH = 3 * visuals.PIN_DIST - tabSize;
  573. var plateW = 2 * visuals.PIN_DIST + tabSize;
  574. var plateL = left;
  575. var plateT = top + tabSize;
  576. var btnCX = plateL + plateW / 2;
  577. var btnCY = plateT + plateH / 2;
  578. var btng = pxsim.svg.elt("g");
  579. //tabs
  580. var mkTab = function (x, y) {
  581. pxsim.svg.child(btng, "rect", { class: "sim-button-tab", x: x, y: y, width: tabSize, height: tabSize });
  582. };
  583. mkTab(left, top);
  584. mkTab(left + 2 * visuals.PIN_DIST, top);
  585. mkTab(left, top + 3 * visuals.PIN_DIST);
  586. mkTab(left + 2 * visuals.PIN_DIST, top + 3 * visuals.PIN_DIST);
  587. //plate
  588. pxsim.svg.child(btng, "rect", { class: outerCls, x: plateL, y: plateT, rx: plateR, ry: plateR, width: plateW, height: plateH });
  589. //pegs
  590. var mkPeg = function (x, y) {
  591. pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: x, cy: y, r: pegR });
  592. };
  593. mkPeg(plateL + pegOffset, plateT + pegOffset);
  594. mkPeg(plateL + plateW - pegOffset, plateT + pegOffset);
  595. mkPeg(plateL + pegOffset, plateT + plateH - pegOffset);
  596. mkPeg(plateL + plateW - pegOffset, plateT + plateH - pegOffset);
  597. //inner btn
  598. var innerBtn = pxsim.svg.child(btng, "circle", { class: innerCls, cx: btnCX, cy: btnCY, r: btnR });
  599. //return
  600. return { el: btng, y: top, x: left, w: plateW, h: plateH + 2 * tabSize };
  601. }
  602. visuals.mkBtnSvg = mkBtnSvg;
  603. visuals.BUTTON_PAIR_STYLE = "\n .sim-button {\n pointer-events: none;\n fill: #000;\n }\n .sim-button-outer:active ~ .sim-button,\n .sim-button-virtual:active {\n fill: #FFA500;\n }\n .sim-button-outer {\n cursor: pointer;\n fill: #979797;\n }\n .sim-button-outer:hover {\n stroke:gray;\n stroke-width: " + visuals.PIN_DIST / 5 + "px;\n }\n .sim-button-nut {\n fill:#000;\n pointer-events:none;\n }\n .sim-button-nut:hover {\n stroke:" + visuals.PIN_DIST / 15 + "px solid #704A4A;\n }\n .sim-button-tab {\n fill:#FFF;\n pointer-events:none;\n }\n .sim-button-virtual {\n cursor: pointer;\n fill: rgba(255, 255, 255, 0.6);\n stroke: rgba(255, 255, 255, 1);\n stroke-width: " + visuals.PIN_DIST / 5 + "px;\n }\n .sim-button-virtual:hover {\n stroke: rgba(128, 128, 128, 1);\n }\n .sim-text-virtual {\n fill: #000;\n pointer-events:none;\n }\n ";
  604. var ButtonPairView = /** @class */ (function () {
  605. function ButtonPairView() {
  606. this.style = visuals.BUTTON_PAIR_STYLE;
  607. }
  608. ButtonPairView.prototype.init = function (bus, state) {
  609. this.state = state;
  610. this.bus = bus;
  611. this.defs = [];
  612. this.element = this.mkBtns();
  613. this.updateState();
  614. this.attachEvents();
  615. };
  616. ButtonPairView.prototype.moveToCoord = function (xy) {
  617. var btnWidth = visuals.PIN_DIST * 3;
  618. var x = xy[0], y = xy[1];
  619. visuals.translateEl(this.aBtn, [x, y]);
  620. visuals.translateEl(this.bBtn, [x + btnWidth, y]);
  621. visuals.translateEl(this.abBtn, [x + visuals.PIN_DIST * 1.5, y + visuals.PIN_DIST * 4]);
  622. };
  623. ButtonPairView.prototype.updateState = function () {
  624. var stateBtns = [this.state.aBtn, this.state.bBtn, this.state.abBtn];
  625. var svgBtns = [this.aBtn, this.bBtn, this.abBtn];
  626. if (this.state.usesButtonAB && this.abBtn.style.visibility != "visible") {
  627. this.abBtn.style.visibility = "visible";
  628. }
  629. };
  630. ButtonPairView.prototype.updateTheme = function () { };
  631. ButtonPairView.prototype.mkBtns = function () {
  632. this.aBtn = mkBtnSvg([0, 0]).el;
  633. this.bBtn = mkBtnSvg([0, 0]).el;
  634. var mkVirtualBtn = function () {
  635. var numPins = 2;
  636. var w = visuals.PIN_DIST * 2.8;
  637. var offset = (w - (numPins * visuals.PIN_DIST)) / 2;
  638. var corner = visuals.PIN_DIST / 2;
  639. var cx = 0 - offset + w / 2;
  640. var cy = cx;
  641. var txtSize = visuals.PIN_DIST * 1.3;
  642. var x = -offset;
  643. var y = -offset;
  644. var txtXOff = visuals.PIN_DIST / 7;
  645. var txtYOff = visuals.PIN_DIST / 10;
  646. var btng = pxsim.svg.elt("g");
  647. var btn = pxsim.svg.child(btng, "rect", { class: "sim-button-virtual", x: x, y: y, rx: corner, ry: corner, width: w, height: w });
  648. var btnTxt = visuals.mkTxt(cx + txtXOff, cy + txtYOff, txtSize, 0, "A+B");
  649. pxsim.svg.addClass(btnTxt, "sim-text");
  650. pxsim.svg.addClass(btnTxt, "sim-text-virtual");
  651. btng.appendChild(btnTxt);
  652. return btng;
  653. };
  654. this.abBtn = mkVirtualBtn();
  655. this.abBtn.style.visibility = "hidden";
  656. var el = pxsim.svg.elt("g");
  657. pxsim.svg.addClass(el, "sim-buttonpair");
  658. el.appendChild(this.aBtn);
  659. el.appendChild(this.bBtn);
  660. el.appendChild(this.abBtn);
  661. return el;
  662. };
  663. ButtonPairView.prototype.attachEvents = function () {
  664. var _this = this;
  665. var btnStates = [this.state.aBtn, this.state.bBtn];
  666. var btnSvgs = [this.aBtn, this.bBtn];
  667. btnSvgs.forEach(function (btn, index) {
  668. pxsim.pointerEvents.down.forEach(function (evid) { return btn.addEventListener(evid, function (ev) {
  669. btnStates[index].pressed = true;
  670. }); });
  671. btn.addEventListener(pxsim.pointerEvents.leave, function (ev) {
  672. btnStates[index].pressed = false;
  673. });
  674. btn.addEventListener(pxsim.pointerEvents.up, function (ev) {
  675. btnStates[index].pressed = false;
  676. _this.bus.queue(btnStates[index].id, _this.state.props.BUTTON_EVT_UP);
  677. _this.bus.queue(btnStates[index].id, _this.state.props.BUTTON_EVT_CLICK);
  678. });
  679. });
  680. var updateBtns = function (s) {
  681. btnStates.forEach(function (b) { return b.pressed = s; });
  682. };
  683. pxsim.pointerEvents.down.forEach(function (evid) { return _this.abBtn.addEventListener(evid, function (ev) {
  684. updateBtns(true);
  685. }); });
  686. this.abBtn.addEventListener(pxsim.pointerEvents.leave, function (ev) {
  687. updateBtns(false);
  688. });
  689. this.abBtn.addEventListener(pxsim.pointerEvents.up, function (ev) {
  690. updateBtns(false);
  691. _this.bus.queue(_this.state.abBtn.id, _this.state.props.BUTTON_EVT_UP);
  692. _this.bus.queue(_this.state.abBtn.id, _this.state.props.BUTTON_EVT_CLICK);
  693. });
  694. };
  695. return ButtonPairView;
  696. }());
  697. visuals.ButtonPairView = ButtonPairView;
  698. })(visuals = pxsim.visuals || (pxsim.visuals = {}));
  699. })(pxsim || (pxsim = {}));
  700. var pxsim;
  701. (function (pxsim) {
  702. var input;
  703. (function (input) {
  704. function compassHeading() {
  705. var b = pxsim.board().compassState;
  706. if (!b.usesHeading) {
  707. b.usesHeading = true;
  708. pxsim.runtime.queueDisplayUpdate();
  709. }
  710. return b.heading;
  711. }
  712. input.compassHeading = compassHeading;
  713. function magneticForce() {
  714. // TODO
  715. return 0;
  716. }
  717. input.magneticForce = magneticForce;
  718. })(input = pxsim.input || (pxsim.input = {}));
  719. })(pxsim || (pxsim = {}));
  720. var pxsim;
  721. (function (pxsim) {
  722. var input;
  723. (function (input) {
  724. function onPinPressed(pinId, handler) {
  725. var pin = pxsim.getPin(pinId);
  726. if (!pin)
  727. return;
  728. pin.isTouched();
  729. pxsim.runtime.queueDisplayUpdate();
  730. pxsim.pxtcore.registerWithDal(pin.id, 3 /* MICROBIT_BUTTON_EVT_CLICK */, handler);
  731. }
  732. input.onPinPressed = onPinPressed;
  733. function onPinReleased(pinId, handler) {
  734. var pin = pxsim.getPin(pinId);
  735. if (!pin)
  736. return;
  737. pin.isTouched();
  738. pxsim.runtime.queueDisplayUpdate();
  739. pxsim.pxtcore.registerWithDal(pin.id, 2 /* MICROBIT_BUTTON_EVT_UP */, handler);
  740. }
  741. input.onPinReleased = onPinReleased;
  742. function pinIsPressed(pinId) {
  743. var pin = pxsim.getPin(pinId);
  744. if (!pin)
  745. return false;
  746. return pin.isTouched();
  747. }
  748. input.pinIsPressed = pinIsPressed;
  749. })(input = pxsim.input || (pxsim.input = {}));
  750. })(pxsim || (pxsim = {}));
  751. (function (pxsim) {
  752. function getPin(id) {
  753. return pxsim.board().edgeConnectorState.getPin(id);
  754. }
  755. pxsim.getPin = getPin;
  756. })(pxsim || (pxsim = {}));
  757. (function (pxsim) {
  758. var pins;
  759. (function (pins_1) {
  760. function digitalReadPin(pinId) {
  761. var pin = pxsim.getPin(pinId);
  762. if (!pin)
  763. return -1;
  764. pin.mode = pxsim.PinFlags.Digital | pxsim.PinFlags.Input;
  765. return pin.value > 100 ? 1 : 0;
  766. }
  767. pins_1.digitalReadPin = digitalReadPin;
  768. function digitalWritePin(pinId, value) {
  769. var pin = pxsim.getPin(pinId);
  770. if (!pin)
  771. return;
  772. pin.mode = pxsim.PinFlags.Digital | pxsim.PinFlags.Output;
  773. pin.value = value > 0 ? 1023 : 0;
  774. pxsim.runtime.queueDisplayUpdate();
  775. }
  776. pins_1.digitalWritePin = digitalWritePin;
  777. function setPull(pinId, pull) {
  778. var pin = pxsim.getPin(pinId);
  779. if (!pin)
  780. return;
  781. pin.pull = pull;
  782. }
  783. pins_1.setPull = setPull;
  784. function analogReadPin(pinId) {
  785. var pin = pxsim.getPin(pinId);
  786. if (!pin)
  787. return -1;
  788. pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Input;
  789. return pin.value || 0;
  790. }
  791. pins_1.analogReadPin = analogReadPin;
  792. function analogWritePin(pinId, value) {
  793. var pin = pxsim.getPin(pinId);
  794. if (!pin)
  795. return;
  796. pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Output;
  797. pin.value = value ? 1 : 0;
  798. pxsim.runtime.queueDisplayUpdate();
  799. }
  800. pins_1.analogWritePin = analogWritePin;
  801. function analogSetPeriod(pinId, micros) {
  802. var pin = pxsim.getPin(pinId);
  803. if (!pin)
  804. return;
  805. pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Output;
  806. pin.period = micros;
  807. pxsim.runtime.queueDisplayUpdate();
  808. }
  809. pins_1.analogSetPeriod = analogSetPeriod;
  810. function servoWritePin(pinId, value) {
  811. var pin = pxsim.getPin(pinId);
  812. if (!pin)
  813. return;
  814. analogSetPeriod(pinId, 20000);
  815. pin.servoAngle = value;
  816. }
  817. pins_1.servoWritePin = servoWritePin;
  818. function servoSetPulse(pinId, micros) {
  819. var pin = pxsim.getPin(pinId);
  820. if (!pin)
  821. return;
  822. // TODO
  823. }
  824. pins_1.servoSetPulse = servoSetPulse;
  825. function analogSetPitchPin(pinId) {
  826. var pin = pxsim.getPin(pinId);
  827. if (!pin)
  828. return;
  829. pxsim.board().edgeConnectorState.pins.filter(function (p) { return !!p; }).forEach(function (p) { return p.pitch = false; });
  830. pin.pitch = true;
  831. }
  832. pins_1.analogSetPitchPin = analogSetPitchPin;
  833. function analogPitch(frequency, ms) {
  834. // update analog output
  835. var pins = pxsim.board().edgeConnectorState.pins;
  836. var pin = pins.filter(function (pin) { return !!pin && pin.pitch; })[0] || pins[0];
  837. pin.mode = pxsim.PinFlags.Analog | pxsim.PinFlags.Output;
  838. if (frequency <= 0) {
  839. pin.value = 0;
  840. pin.period = 0;
  841. }
  842. else {
  843. pin.value = 512;
  844. pin.period = 1000000 / frequency;
  845. }
  846. pxsim.runtime.queueDisplayUpdate();
  847. var cb = pxsim.getResume();
  848. pxsim.AudioContextManager.tone(frequency, 1);
  849. if (ms <= 0)
  850. cb();
  851. else {
  852. setTimeout(function () {
  853. pxsim.AudioContextManager.stop();
  854. pin.value = 0;
  855. pin.period = 0;
  856. pin.mode = pxsim.PinFlags.Unused;
  857. pxsim.runtime.queueDisplayUpdate();
  858. cb();
  859. }, ms);
  860. }
  861. }
  862. pins_1.analogPitch = analogPitch;
  863. })(pins = pxsim.pins || (pxsim.pins = {}));
  864. })(pxsim || (pxsim = {}));
  865. var pxsim;
  866. (function (pxsim) {
  867. var PinFlags;
  868. (function (PinFlags) {
  869. PinFlags[PinFlags["Unused"] = 0] = "Unused";
  870. PinFlags[PinFlags["Digital"] = 1] = "Digital";
  871. PinFlags[PinFlags["Analog"] = 2] = "Analog";
  872. PinFlags[PinFlags["Input"] = 4] = "Input";
  873. PinFlags[PinFlags["Output"] = 8] = "Output";
  874. PinFlags[PinFlags["Touch"] = 16] = "Touch";
  875. })(PinFlags = pxsim.PinFlags || (pxsim.PinFlags = {}));
  876. var Pin = /** @class */ (function () {
  877. function Pin(id) {
  878. this.id = id;
  879. this.touched = false;
  880. this.value = 0;
  881. this.period = 0;
  882. this.servoAngle = 0;
  883. this.mode = PinFlags.Unused;
  884. this.pitch = false;
  885. this.pull = 0; // PullDown
  886. }
  887. Pin.prototype.digitalReadPin = function () {
  888. this.mode = PinFlags.Digital | PinFlags.Input;
  889. return this.value > 100 ? 1 : 0;
  890. };
  891. Pin.prototype.digitalWritePin = function (value) {
  892. this.mode = PinFlags.Digital | PinFlags.Output;
  893. this.value = value > 0 ? 200 : 0;
  894. pxsim.runtime.queueDisplayUpdate();
  895. };
  896. Pin.prototype.setPull = function (pull) {
  897. this.pull = pull;
  898. };
  899. Pin.prototype.analogReadPin = function () {
  900. this.mode = PinFlags.Analog | PinFlags.Input;
  901. return this.value || 0;
  902. };
  903. Pin.prototype.analogWritePin = function (value) {
  904. value = value >> 0;
  905. this.mode = PinFlags.Analog | PinFlags.Output;
  906. this.value = Math.max(0, Math.min(1023, value));
  907. pxsim.runtime.queueDisplayUpdate();
  908. };
  909. Pin.prototype.analogSetPeriod = function (micros) {
  910. micros = micros >> 0;
  911. this.mode = PinFlags.Analog | PinFlags.Output;
  912. this.period = micros;
  913. pxsim.runtime.queueDisplayUpdate();
  914. };
  915. Pin.prototype.servoWritePin = function (value) {
  916. value = value >> 0;
  917. this.analogSetPeriod(20000);
  918. this.servoAngle = Math.max(0, Math.min(180, value));
  919. pxsim.runtime.queueDisplayUpdate();
  920. };
  921. Pin.prototype.servoSetPulse = function (pinId, micros) {
  922. // TODO
  923. };
  924. Pin.prototype.isTouched = function () {
  925. this.mode = PinFlags.Touch | PinFlags.Analog | PinFlags.Input;
  926. return this.touched;
  927. };
  928. return Pin;
  929. }());
  930. pxsim.Pin = Pin;
  931. var EdgeConnectorState = /** @class */ (function () {
  932. function EdgeConnectorState(props) {
  933. this.props = props;
  934. this.pins = props.pins.map(function (id) { return id != undefined ? new Pin(id) : null; });
  935. }
  936. EdgeConnectorState.prototype.getPin = function (id) {
  937. return this.pins.filter(function (p) { return p && p.id == id; })[0] || null;
  938. };
  939. return EdgeConnectorState;
  940. }());
  941. pxsim.EdgeConnectorState = EdgeConnectorState;
  942. })(pxsim || (pxsim = {}));
  943. var pxsim;
  944. (function (pxsim) {
  945. var files;
  946. (function (files) {
  947. function appendLine(filename, text) {
  948. var b = pxsim.board();
  949. b.fileSystem.append(filename, text + "\r\n");
  950. }
  951. files.appendLine = appendLine;
  952. function appendString(filename, text) {
  953. var b = pxsim.board();
  954. b.fileSystem.append(filename, text);
  955. }
  956. files.appendString = appendString;
  957. function appendNumber(filename, value) {
  958. var b = pxsim.board();
  959. b.fileSystem.append(filename, value.toString());
  960. }
  961. files.appendNumber = appendNumber;
  962. function remove(filename) {
  963. var b = pxsim.board();
  964. b.fileSystem.remove(filename);
  965. }
  966. files.remove = remove;
  967. function readToSerial(filename) {
  968. var b = pxsim.board();
  969. var f = b.fileSystem.files[filename];
  970. if (f)
  971. b.serialState.writeSerial(f);
  972. }
  973. files.readToSerial = readToSerial;
  974. })(files = pxsim.files || (pxsim.files = {}));
  975. })(pxsim || (pxsim = {}));
  976. var pxsim;
  977. (function (pxsim) {
  978. var DisplayMode;
  979. (function (DisplayMode) {
  980. DisplayMode[DisplayMode["bw"] = 0] = "bw";
  981. DisplayMode[DisplayMode["greyscale"] = 1] = "greyscale";
  982. })(DisplayMode = pxsim.DisplayMode || (pxsim.DisplayMode = {}));
  983. var LedMatrixState = /** @class */ (function () {
  984. function LedMatrixState(runtime) {
  985. this.image = createInternalImage(5);
  986. this.brigthness = 255;
  987. this.displayMode = DisplayMode.bw;
  988. this.font = createFont();
  989. this.animationQ = new pxsim.AnimationQueue(runtime);
  990. }
  991. return LedMatrixState;
  992. }());
  993. pxsim.LedMatrixState = LedMatrixState;
  994. var Image = /** @class */ (function (_super) {
  995. __extends(Image, _super);
  996. function Image(width, data) {
  997. var _this = _super.call(this) || this;
  998. _this.width = width;
  999. _this.data = data;
  1000. return _this;
  1001. }
  1002. Image.prototype.print = function () {
  1003. console.debug("Image id:" + this.id + " refs:" + this.refcnt + " size:" + this.width + "x" + Image.height);
  1004. };
  1005. Image.prototype.get = function (x, y) {
  1006. x = x >> 0;
  1007. y = y >> 0;
  1008. if (x < 0 || x >= this.width || y < 0 || y >= 5)
  1009. return 0;
  1010. return this.data[y * this.width + x];
  1011. };
  1012. Image.prototype.set = function (x, y, v) {
  1013. x = x >> 0;
  1014. y = y >> 0;
  1015. if (x < 0 || x >= this.width || y < 0 || y >= 5)
  1016. return;
  1017. this.data[y * this.width + x] = Math.max(0, Math.min(255, v));
  1018. };
  1019. Image.prototype.copyTo = function (xSrcIndex, length, target, xTargetIndex) {
  1020. xSrcIndex = xSrcIndex >> 0;
  1021. length = length >> 0;
  1022. xTargetIndex = xTargetIndex >> 0;
  1023. for (var x = 0; x < length; x++) {
  1024. for (var y = 0; y < 5; y++) {
  1025. var value = this.get(xSrcIndex + x, y);
  1026. target.set(xTargetIndex + x, y, value);
  1027. }
  1028. }
  1029. };
  1030. Image.prototype.shiftLeft = function (cols) {
  1031. cols = cols >> 0;
  1032. for (var x = 0; x < this.width; ++x)
  1033. for (var y = 0; y < 5; ++y)
  1034. this.set(x, y, x < this.width - cols ? this.get(x + cols, y) : 0);
  1035. };
  1036. Image.prototype.shiftRight = function (cols) {
  1037. cols = cols >> 0;
  1038. for (var x = this.width - 1; x >= 0; --x)
  1039. for (var y = 0; y < 5; ++y)
  1040. this.set(x, y, x >= cols ? this.get(x - cols, y) : 0);
  1041. };
  1042. Image.prototype.clear = function () {
  1043. for (var i = 0; i < this.data.length; ++i)
  1044. this.data[i] = 0;
  1045. };
  1046. Image.height = 5;
  1047. return Image;
  1048. }(pxsim.RefObject));
  1049. pxsim.Image = Image;
  1050. function createInternalImage(width) {
  1051. width = width >> 0;
  1052. var img = createImage(width);
  1053. pxsim.runtime.unregisterLiveObject(img, true);
  1054. return img;
  1055. }
  1056. pxsim.createInternalImage = createInternalImage;
  1057. function createImage(width) {
  1058. width = width >> 0;
  1059. return new Image(width, new Array(width * 5));
  1060. }
  1061. pxsim.createImage = createImage;
  1062. function createImageFromBuffer(data) {
  1063. return new Image(data.length / 5, data);
  1064. }
  1065. pxsim.createImageFromBuffer = createImageFromBuffer;
  1066. function createImageFromString(text) {
  1067. var font = pxsim.board().ledMatrixState.font;
  1068. var w = font.width;
  1069. var sprite = createInternalImage(6 * text.length - 1);
  1070. var k = 0;
  1071. for (var i = 0; i < text.length; i++) {
  1072. var charCode = text.charCodeAt(i);
  1073. var charStart = (charCode - 32) * 5;
  1074. if (charStart < 0 || charStart + 5 > w) {
  1075. charCode = " ".charCodeAt(0);
  1076. charStart = (charCode - 32) * 5;
  1077. }
  1078. font.copyTo(charStart, 5, sprite, k);
  1079. k = k + 5;
  1080. if (i < text.length - 1) {
  1081. k = k + 1;
  1082. }
  1083. }
  1084. return sprite;
  1085. }
  1086. pxsim.createImageFromString = createImageFromString;
  1087. function createFont() {
  1088. 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];
  1089. var nb = data.length;
  1090. var n = nb / 5;
  1091. var font = createInternalImage(nb);
  1092. for (var c = 0; c < n; c++) {
  1093. for (var row = 0; row < 5; row++) {
  1094. var char = data[c * 5 + row];
  1095. for (var col = 0; col < 5; col++) {
  1096. if ((char & (1 << col)) != 0)
  1097. font.set((c * 5 + 4) - col, row, 255);
  1098. }
  1099. }
  1100. }
  1101. return font;
  1102. }
  1103. pxsim.createFont = createFont;
  1104. })(pxsim || (pxsim = {}));
  1105. (function (pxsim) {
  1106. var images;
  1107. (function (images) {
  1108. function createImage(img) {
  1109. return img;
  1110. }
  1111. images.createImage = createImage;
  1112. function createBigImage(img) {
  1113. return img;
  1114. }
  1115. images.createBigImage = createBigImage;
  1116. })(images = pxsim.images || (pxsim.images = {}));
  1117. })(pxsim || (pxsim = {}));
  1118. (function (pxsim) {
  1119. var ImageMethods;
  1120. (function (ImageMethods) {
  1121. function showImage(leds, offset, interval) {
  1122. pxsim.pxtrt.nullCheck(leds);
  1123. offset = offset >> 0;
  1124. interval = interval >> 0;
  1125. var cb = pxsim.getResume();
  1126. var first = true;
  1127. leds = clampPixelBrightness(leds);
  1128. pxsim.board().ledMatrixState.animationQ.enqueue({
  1129. interval: interval,
  1130. frame: function () {
  1131. if (first) {
  1132. leds.copyTo(offset, 5, pxsim.board().ledMatrixState.image, 0);
  1133. first = false;
  1134. return true;
  1135. }
  1136. return false;
  1137. },
  1138. whenDone: cb
  1139. });
  1140. }
  1141. ImageMethods.showImage = showImage;
  1142. function plotImage(leds, offset) {
  1143. pxsim.pxtrt.nullCheck(leds);
  1144. offset = offset >> 0;
  1145. leds = clampPixelBrightness(leds);
  1146. pxsim.board().ledMatrixState.animationQ.enqueue({
  1147. interval: 0,
  1148. frame: function () {
  1149. leds.copyTo(offset, 5, pxsim.board().ledMatrixState.image, 0);
  1150. return false;
  1151. }
  1152. });
  1153. }
  1154. ImageMethods.plotImage = plotImage;
  1155. function height(leds) {
  1156. pxsim.pxtrt.nullCheck(leds);
  1157. return pxsim.Image.height;
  1158. }
  1159. ImageMethods.height = height;
  1160. function width(leds) {
  1161. pxsim.pxtrt.nullCheck(leds);
  1162. return leds.width;
  1163. }
  1164. ImageMethods.width = width;
  1165. function plotFrame(leds, frame) {
  1166. ImageMethods.plotImage(leds, frame * pxsim.Image.height);
  1167. }
  1168. ImageMethods.plotFrame = plotFrame;
  1169. function showFrame(leds, frame, interval) {
  1170. ImageMethods.showImage(leds, frame * pxsim.Image.height, interval);
  1171. }
  1172. ImageMethods.showFrame = showFrame;
  1173. function pixel(leds, x, y) {
  1174. pxsim.pxtrt.nullCheck(leds);
  1175. return leds.get(x, y);
  1176. }
  1177. ImageMethods.pixel = pixel;
  1178. function setPixel(leds, x, y, v) {
  1179. pxsim.pxtrt.nullCheck(leds);
  1180. leds.set(x, y, v);
  1181. }
  1182. ImageMethods.setPixel = setPixel;
  1183. function clear(leds) {
  1184. pxsim.pxtrt.nullCheck(leds);
  1185. leds.clear();
  1186. }
  1187. ImageMethods.clear = clear;
  1188. function setPixelBrightness(i, x, y, b) {
  1189. pxsim.pxtrt.nullCheck(i);
  1190. i.set(x, y, b);
  1191. }
  1192. ImageMethods.setPixelBrightness = setPixelBrightness;
  1193. function pixelBrightness(i, x, y) {
  1194. pxsim.pxtrt.nullCheck(i);
  1195. return i.get(x, y);
  1196. }
  1197. ImageMethods.pixelBrightness = pixelBrightness;
  1198. function scrollImage(leds, stride, interval) {
  1199. pxsim.pxtrt.nullCheck(leds);
  1200. stride = stride >> 0;
  1201. interval = interval >> 0;
  1202. if (stride == 0)
  1203. stride = 1;
  1204. var cb = pxsim.getResume();
  1205. var off = stride > 0 ? 0 : leds.width - 1;
  1206. var display = pxsim.board().ledMatrixState.image;
  1207. leds = clampPixelBrightness(leds);
  1208. pxsim.board().ledMatrixState.animationQ.enqueue({
  1209. interval: interval,
  1210. frame: function () {
  1211. if (off >= leds.width || off < 0)
  1212. return false;
  1213. if (stride > 0) {
  1214. display.shiftLeft(stride);
  1215. var c = Math.min(stride, leds.width - off);
  1216. leds.copyTo(off, c, display, 5 - stride);
  1217. }
  1218. else {
  1219. display.shiftRight(-stride);
  1220. var c = Math.min(-stride, leds.width - off);
  1221. leds.copyTo(off, c, display, 0);
  1222. }
  1223. off += stride;
  1224. return true;
  1225. },
  1226. whenDone: cb
  1227. });
  1228. }
  1229. ImageMethods.scrollImage = scrollImage;
  1230. function clampPixelBrightness(img) {
  1231. var res = img;
  1232. if (pxsim.led.displayMode() === pxsim.DisplayMode.greyscale && pxsim.led.brightness() < 0xff) {
  1233. res = new pxsim.Image(img.width, img.data);
  1234. var b = pxsim.led.brightness();
  1235. for (var x = 0; x < res.width; ++x) {
  1236. for (var y = 0; y < 5; ++y) {
  1237. if (pixelBrightness(res, x, y) > b) {
  1238. setPixelBrightness(res, x, y, b);
  1239. }
  1240. }
  1241. }
  1242. }
  1243. return res;
  1244. }
  1245. })(ImageMethods = pxsim.ImageMethods || (pxsim.ImageMethods = {}));
  1246. })(pxsim || (pxsim = {}));
  1247. (function (pxsim) {
  1248. var basic;
  1249. (function (basic) {
  1250. function showNumber(x, interval) {
  1251. interval = interval >> 0;
  1252. if (interval <= 0)
  1253. interval = 1;
  1254. var leds = pxsim.createImageFromString(x.toString());
  1255. if (x < 0 || x >= 10)
  1256. pxsim.ImageMethods.scrollImage(leds, 1, interval);
  1257. else
  1258. showLeds(leds, interval * 5);
  1259. }
  1260. basic.showNumber = showNumber;
  1261. function showString(s, interval) {
  1262. interval = interval >> 0;
  1263. if (interval <= 0)
  1264. interval = 1;
  1265. if (s.length == 0) {
  1266. clearScreen();
  1267. basic.pause(interval * 5);
  1268. }
  1269. else if (s.length > 1) {
  1270. pxsim.ImageMethods.scrollImage(pxsim.createImageFromString(s + " "), 1, interval);
  1271. }
  1272. else {
  1273. showLeds(pxsim.createImageFromString(s), interval * 5);
  1274. }
  1275. }
  1276. basic.showString = showString;
  1277. function showLeds(leds, interval) {
  1278. showAnimation(leds, interval);
  1279. }
  1280. basic.showLeds = showLeds;
  1281. function clearScreen() {
  1282. pxsim.board().ledMatrixState.image.clear();
  1283. pxsim.runtime.queueDisplayUpdate();
  1284. }
  1285. basic.clearScreen = clearScreen;
  1286. function showAnimation(leds, interval) {
  1287. pxsim.ImageMethods.scrollImage(leds, 5, interval);
  1288. }
  1289. basic.showAnimation = showAnimation;
  1290. function plotLeds(leds) {
  1291. pxsim.ImageMethods.plotImage(leds, 0);
  1292. }
  1293. basic.plotLeds = plotLeds;
  1294. })(basic = pxsim.basic || (pxsim.basic = {}));
  1295. })(pxsim || (pxsim = {}));
  1296. (function (pxsim) {
  1297. var led;
  1298. (function (led) {
  1299. function plot(x, y) {
  1300. pxsim.board().ledMatrixState.image.set(x, y, 0xff);
  1301. pxsim.runtime.queueDisplayUpdate();
  1302. }
  1303. led.plot = plot;
  1304. function plotBrightness(x, y, brightness) {
  1305. var state = pxsim.board().ledMatrixState;
  1306. brightness = brightness >> 0;
  1307. brightness = Math.max(0, Math.min(led.brightness(), brightness));
  1308. if (brightness != 0 && brightness != 0xff && state.displayMode != pxsim.DisplayMode.greyscale)
  1309. state.displayMode = pxsim.DisplayMode.greyscale;
  1310. state.image.set(x, y, brightness);
  1311. pxsim.runtime.queueDisplayUpdate();
  1312. }
  1313. led.plotBrightness = plotBrightness;
  1314. function unplot(x, y) {
  1315. pxsim.board().ledMatrixState.image.set(x, y, 0);
  1316. pxsim.runtime.queueDisplayUpdate();
  1317. }
  1318. led.unplot = unplot;
  1319. function point(x, y) {
  1320. return !!pxsim.board().ledMatrixState.image.get(x, y);
  1321. }
  1322. led.point = point;
  1323. function brightness() {
  1324. return pxsim.board().ledMatrixState.brigthness;
  1325. }
  1326. led.brightness = brightness;
  1327. function setBrightness(value) {
  1328. value = value >> 0;
  1329. pxsim.board().ledMatrixState.brigthness = Math.max(0, Math.min(255, value));
  1330. pxsim.runtime.queueDisplayUpdate();
  1331. }
  1332. led.setBrightness = setBrightness;
  1333. function stopAnimation() {
  1334. pxsim.board().ledMatrixState.animationQ.cancelAll();
  1335. pxsim.board().ledMatrixState.image.clear();
  1336. }
  1337. led.stopAnimation = stopAnimation;
  1338. function setDisplayMode(mode) {
  1339. pxsim.board().ledMatrixState.displayMode = mode;
  1340. pxsim.runtime.queueDisplayUpdate();
  1341. }
  1342. led.setDisplayMode = setDisplayMode;
  1343. function displayMode() {
  1344. return pxsim.board().ledMatrixState.displayMode;
  1345. }
  1346. led.displayMode = displayMode;
  1347. function screenshot() {
  1348. var img = pxsim.createImage(5);
  1349. pxsim.board().ledMatrixState.image.copyTo(0, 5, img, 0);
  1350. return img;
  1351. }
  1352. led.screenshot = screenshot;
  1353. function enable(on) {
  1354. pxsim.board().ledMatrixState.disabled = !on;
  1355. pxsim.runtime.queueDisplayUpdate();
  1356. }
  1357. led.enable = enable;
  1358. })(led = pxsim.led || (pxsim.led = {}));
  1359. })(pxsim || (pxsim = {}));
  1360. var pxsim;
  1361. (function (pxsim) {
  1362. var input;
  1363. (function (input) {
  1364. function lightLevel() {
  1365. var b = pxsim.board().lightSensorState;
  1366. if (!b.usesLightLevel) {
  1367. b.usesLightLevel = true;
  1368. pxsim.runtime.queueDisplayUpdate();
  1369. }
  1370. return b.lightLevel;
  1371. }
  1372. input.lightLevel = lightLevel;
  1373. })(input = pxsim.input || (pxsim.input = {}));
  1374. })(pxsim || (pxsim = {}));
  1375. var pxsim;
  1376. (function (pxsim) {
  1377. var visuals;
  1378. (function (visuals) {
  1379. function createMicroServoElement() {
  1380. return pxsim.svg.parseString("\n <svg xmlns=\"http://www.w3.org/2000/svg\" id=\"svg2\" width=\"112.188\" height=\"299.674\">\n <g id=\"layer1\" stroke-linecap=\"round\" stroke-linejoin=\"round\" transform=\"scale(0.8)\">\n <path id=\"path8212\" fill=\"#0061ff\" stroke-width=\"6.6\" d=\"M.378 44.61v255.064h112.188V44.61H.378z\"/>\n <path id=\"crankbase\" fill=\"#00f\" stroke-width=\"6.6\" d=\"M56.57 88.047C25.328 88.047 0 113.373 0 144.615c.02 22.352 11.807 42.596 32.238 51.66.03 3.318.095 5.24.088 7.938 0 13.947 11.307 25.254 25.254 25.254 13.947 0 25.254-11.307 25.254-25.254-.006-2.986-.415-5.442-.32-8.746 19.487-9.45 30.606-29.195 30.625-50.852 0-31.24-25.33-56.568-56.57-56.568z\"/>\n <path id=\"lowertip\" fill=\"#00a2ff\" stroke-width=\"2\" d=\"M.476 260.78v38.894h53.82v-10.486a6.82 6.566 0 0 1-4.545-6.182 6.82 6.566 0 0 1 6.82-6.566 6.82 6.566 0 0 1 6.82 6.566 6.82 6.566 0 0 1-4.545 6.182v10.486h53.82V260.78H.475z\"/>\n <path id=\"uppertip\" fill=\"#00a2ff\" stroke-width=\"2\" d=\"M112.566 83.503V44.61h-53.82v10.487a6.82 6.566 0 0 1 4.544 6.18 6.82 6.566 0 0 1-6.818 6.568 6.82 6.566 0 0 1-6.82-6.567 6.82 6.566 0 0 1 4.546-6.18V44.61H.378v38.893h112.188z\"/>\n <path id=\"VCC\" fill=\"red\" stroke-width=\"2\" d=\"M53.72 21.93h5.504v22.627H53.72z\"/>\n <path id=\"LOGIC\" fill=\"#fc0\" stroke-width=\"2\" d=\"M47.3 21.93h5.503v22.627H47.3z\"/>\n <path id=\"GND\" fill=\"#a02c2c\" stroke-width=\"2\" d=\"M60.14 21.93h5.505v22.627H60.14z\"/>\n <path id=\"connector\" stroke-width=\"2\" d=\"M45.064 0a1.488 1.488 0 0 0-1.488 1.488v24.5a1.488 1.488 0 0 0 1.488 1.487h22.71a1.488 1.488 0 0 0 1.49-1.488v-24.5A1.488 1.488 0 0 0 67.774 0h-22.71z\"/>\n <g id=\"crank\" transform=\"translate(0 -752.688)\">\n <path id=\"arm\" fill=\"#ececec\" stroke=\"#000\" stroke-width=\"1.372\" d=\"M47.767 880.88c-4.447 1.162-8.412 8.278-8.412 18.492s3.77 18.312 8.412 18.494c8.024.314 78.496 5.06 78.51-16.952.012-22.013-74.377-21.117-78.51-20.035z\"/>\n <circle id=\"path8216\" cx=\"56.661\" cy=\"899.475\" r=\"8.972\" fill=\"gray\" stroke-width=\"2\"/>\n </g>\n </g>\n </svg>\n ").firstElementChild;
  1381. }
  1382. function mkMicroServoPart(xy) {
  1383. if (xy === void 0) { xy = [0, 0]; }
  1384. return { el: createMicroServoElement(), x: xy[0], y: xy[1], w: 112.188, h: 299.674 };
  1385. }
  1386. visuals.mkMicroServoPart = mkMicroServoPart;
  1387. var MicroServoView = /** @class */ (function () {
  1388. function MicroServoView() {
  1389. this.style = "";
  1390. this.overElement = undefined;
  1391. this.defs = [];
  1392. this.currentAngle = 0;
  1393. this.targetAngle = 0;
  1394. this.lastAngleTime = 0;
  1395. }
  1396. MicroServoView.prototype.init = function (bus, state, svgEl, otherParams) {
  1397. this.state = state;
  1398. this.pin = this.state.props.servos[pxsim.readPin(otherParams["name"] || otherParams["pin"])];
  1399. this.bus = bus;
  1400. this.defs = [];
  1401. this.initDom();
  1402. this.updateState();
  1403. };
  1404. MicroServoView.prototype.initDom = function () {
  1405. this.element = createMicroServoElement();
  1406. this.crankEl = this.element.querySelector("#crank");
  1407. this.crankTransform = this.crankEl.getAttribute("transform");
  1408. };
  1409. MicroServoView.prototype.moveToCoord = function (xy) {
  1410. var x = xy[0], y = xy[1];
  1411. visuals.translateEl(this.element, [x, y]);
  1412. };
  1413. MicroServoView.prototype.updateState = function () {
  1414. this.targetAngle = 180.0 - this.state.getPin(this.pin).servoAngle;
  1415. if (this.targetAngle != this.currentAngle) {
  1416. var now = pxsim.U.now();
  1417. var cx = 56.661;
  1418. var cy = 899.475;
  1419. var speed = 300; // 0.1s/60 degree
  1420. var dt = Math.min(now - this.lastAngleTime, 50) / 1000;
  1421. var delta = this.targetAngle - this.currentAngle;
  1422. this.currentAngle += Math.min(Math.abs(delta), speed * dt) * (delta > 0 ? 1 : -1);
  1423. this.crankEl.setAttribute("transform", this.crankTransform
  1424. + (" rotate(" + this.currentAngle + ", " + cx + ", " + cy + ")"));
  1425. this.lastAngleTime = now;
  1426. setTimeout(function () { return pxsim.runtime.updateDisplay(); }, 20);
  1427. }
  1428. };
  1429. MicroServoView.prototype.updateTheme = function () {
  1430. };
  1431. return MicroServoView;
  1432. }());
  1433. visuals.MicroServoView = MicroServoView;
  1434. })(visuals = pxsim.visuals || (pxsim.visuals = {}));
  1435. })(pxsim || (pxsim = {}));
  1436. var pxsim;
  1437. (function (pxsim) {
  1438. var control;
  1439. (function (control) {
  1440. function __midiSend(data) {
  1441. var b = pxsim.board();
  1442. pxsim.AudioContextManager.sendMidiMessage(data);
  1443. }
  1444. control.__midiSend = __midiSend;
  1445. })(control = pxsim.control || (pxsim.control = {}));
  1446. })(pxsim || (pxsim = {}));
  1447. var pxsim;
  1448. (function (pxsim) {
  1449. /**
  1450. * Error codes used in the micro:bit runtime.
  1451. */
  1452. var PanicCode;
  1453. (function (PanicCode) {
  1454. // PANIC Codes. These are not return codes, but are terminal conditions.
  1455. // These induce a panic operation, where all code stops executing, and a panic state is
  1456. // entered where the panic code is diplayed.
  1457. // Out out memory error. Heap storage was requested, but is not available.
  1458. PanicCode[PanicCode["MICROBIT_OOM"] = 20] = "MICROBIT_OOM";
  1459. // Corruption detected in the micro:bit heap space
  1460. PanicCode[PanicCode["MICROBIT_HEAP_ERROR"] = 30] = "MICROBIT_HEAP_ERROR";
  1461. // Dereference of a NULL pointer through the ManagedType class,
  1462. PanicCode[PanicCode["MICROBIT_NULL_DEREFERENCE"] = 40] = "MICROBIT_NULL_DEREFERENCE";
  1463. })(PanicCode = pxsim.PanicCode || (pxsim.PanicCode = {}));
  1464. ;
  1465. function panic(code) {
  1466. console.log("PANIC:", code);
  1467. throw new Error("PANIC " + code);
  1468. }
  1469. pxsim.panic = panic;
  1470. })(pxsim || (pxsim = {}));
  1471. (function (pxsim) {
  1472. var basic;
  1473. (function (basic) {
  1474. basic.pause = pxsim.thread.pause;
  1475. basic.forever = pxsim.thread.forever;
  1476. })(basic = pxsim.basic || (pxsim.basic = {}));
  1477. })(pxsim || (pxsim = {}));
  1478. (function (pxsim) {
  1479. var control;
  1480. (function (control) {
  1481. control.inBackground = pxsim.thread.runInBackground;
  1482. function createBuffer(sz) {
  1483. return pxsim.BufferMethods.createBuffer(sz);
  1484. }
  1485. control.createBuffer = createBuffer;
  1486. function reset() {
  1487. var cb = pxsim.getResume();
  1488. pxsim.runtime.restart();
  1489. }
  1490. control.reset = reset;
  1491. function waitMicros(micros) {
  1492. // TODO
  1493. }
  1494. control.waitMicros = waitMicros;
  1495. function deviceName() {
  1496. var b = pxsim.board();
  1497. return b && b.id
  1498. ? b.id.slice(0, 4)
  1499. : "abcd";
  1500. }
  1501. control.deviceName = deviceName;
  1502. function deviceSerialNumber() {
  1503. var b = pxsim.board();
  1504. return parseInt(b && b.id
  1505. ? b.id.slice(1)
  1506. : "42");
  1507. }
  1508. control.deviceSerialNumber = deviceSerialNumber;
  1509. function onEvent(id, evid, handler) {
  1510. if (id == 26 /* MICROBIT_ID_BUTTON_AB */) {
  1511. var b = pxsim.board().buttonPairState;
  1512. if (!b.usesButtonAB) {
  1513. b.usesButtonAB = true;
  1514. pxsim.runtime.queueDisplayUpdate();
  1515. }
  1516. }
  1517. pxsim.pxtcore.registerWithDal(id, evid, handler);
  1518. }
  1519. control.onEvent = onEvent;
  1520. function raiseEvent(id, evid, mode) {
  1521. // TODO mode?
  1522. pxsim.board().bus.queue(id, evid);
  1523. }
  1524. control.raiseEvent = raiseEvent;
  1525. function eventTimestamp() {
  1526. return pxsim.board().bus.getLastEventTime();
  1527. }
  1528. control.eventTimestamp = eventTimestamp;
  1529. function eventValue() {
  1530. return pxsim.board().bus.getLastEventValue();
  1531. }
  1532. control.eventValue = eventValue;
  1533. })(control = pxsim.control || (pxsim.control = {}));
  1534. })(pxsim || (pxsim = {}));
  1535. (function (pxsim) {
  1536. var pxtcore;
  1537. (function (pxtcore) {
  1538. function registerWithDal(id, evid, handler) {
  1539. pxsim.board().bus.listen(id, evid, handler);
  1540. }
  1541. pxtcore.registerWithDal = registerWithDal;
  1542. })(pxtcore = pxsim.pxtcore || (pxsim.pxtcore = {}));
  1543. })(pxsim || (pxsim = {}));
  1544. (function (pxsim) {
  1545. var input;
  1546. (function (input) {
  1547. function runningTime() {
  1548. return pxsim.runtime.runningTime();
  1549. }
  1550. input.runningTime = runningTime;
  1551. function runningTimeMicros() {
  1552. return pxsim.runtime.runningTimeUs();
  1553. }
  1554. input.runningTimeMicros = runningTimeMicros;
  1555. function calibrateCompass() {
  1556. // device calibrates...
  1557. }
  1558. input.calibrateCompass = calibrateCompass;
  1559. })(input = pxsim.input || (pxsim.input = {}));
  1560. })(pxsim || (pxsim = {}));
  1561. (function (pxsim) {
  1562. var pins;
  1563. (function (pins) {
  1564. function onPulsed(name, pulse, body) {
  1565. }
  1566. pins.onPulsed = onPulsed;
  1567. function pulseDuration() {
  1568. return 0;
  1569. }
  1570. pins.pulseDuration = pulseDuration;
  1571. function createBuffer(sz) {
  1572. return pxsim.BufferMethods.createBuffer(sz);
  1573. }
  1574. pins.createBuffer = createBuffer;
  1575. function pulseIn(name, value, maxDuration) {
  1576. var pin = pxsim.getPin(name);
  1577. if (!pin)
  1578. return 0;
  1579. return 5000;
  1580. }
  1581. pins.pulseIn = pulseIn;
  1582. function spiWrite(value) {
  1583. // TODO
  1584. return 0;
  1585. }
  1586. pins.spiWrite = spiWrite;
  1587. function spiFrequency(f) {
  1588. // TODO
  1589. }
  1590. pins.spiFrequency = spiFrequency;
  1591. function spiFormat(bits, mode) {
  1592. // TODO
  1593. }
  1594. pins.spiFormat = spiFormat;
  1595. function spiPins(mosi, miso, sck) {
  1596. // TODO
  1597. }
  1598. pins.spiPins = spiPins;
  1599. function i2cReadBuffer(address, size, repeat) {
  1600. // fake reading zeros
  1601. return createBuffer(size);
  1602. }
  1603. pins.i2cReadBuffer = i2cReadBuffer;
  1604. function i2cWriteBuffer(address, buf, repeat) {
  1605. // fake - noop
  1606. }
  1607. pins.i2cWriteBuffer = i2cWriteBuffer;
  1608. // this likely shouldn't be called
  1609. function getPinAddress(name) {
  1610. return pxsim.getPin(name);
  1611. }
  1612. pins.getPinAddress = getPinAddress;
  1613. function setEvents(name, event) {
  1614. }
  1615. pins.setEvents = setEvents;
  1616. })(pins = pxsim.pins || (pxsim.pins = {}));
  1617. })(pxsim || (pxsim = {}));
  1618. (function (pxsim) {
  1619. var devices;
  1620. (function (devices) {
  1621. function tellCameraTo(action) {
  1622. // TODO
  1623. }
  1624. devices.tellCameraTo = tellCameraTo;
  1625. function tellRemoteControlTo(action) {
  1626. // TODO
  1627. }
  1628. devices.tellRemoteControlTo = tellRemoteControlTo;
  1629. function raiseAlertTo(action) {
  1630. // TODO
  1631. }
  1632. devices.raiseAlertTo = raiseAlertTo;
  1633. function onSignalStrengthChanged(action) {
  1634. // TODO
  1635. }
  1636. devices.onSignalStrengthChanged = onSignalStrengthChanged;
  1637. function signalStrength() {
  1638. // TODO
  1639. return 0;
  1640. }
  1641. devices.signalStrength = signalStrength;
  1642. function onGamepadButton(button, body) {
  1643. // TODO
  1644. }
  1645. devices.onGamepadButton = onGamepadButton;
  1646. })(devices = pxsim.devices || (pxsim.devices = {}));
  1647. })(pxsim || (pxsim = {}));
  1648. (function (pxsim) {
  1649. var bluetooth;
  1650. (function (bluetooth) {
  1651. function startIOPinService() {
  1652. // TODO
  1653. }
  1654. bluetooth.startIOPinService = startIOPinService;
  1655. function startLEDService() {
  1656. // TODO
  1657. }
  1658. bluetooth.startLEDService = startLEDService;
  1659. function startTemperatureService() {
  1660. // TODO
  1661. }
  1662. bluetooth.startTemperatureService = startTemperatureService;
  1663. function startMagnetometerService() {
  1664. // TODO
  1665. }
  1666. bluetooth.startMagnetometerService = startMagnetometerService;
  1667. function startAccelerometerService() {
  1668. // TODO
  1669. }
  1670. bluetooth.startAccelerometerService = startAccelerometerService;
  1671. function startButtonService() {
  1672. // TODO
  1673. }
  1674. bluetooth.startButtonService = startButtonService;
  1675. function startUartService() {
  1676. // TODO
  1677. }
  1678. bluetooth.startUartService = startUartService;
  1679. function uartWriteString(s) {
  1680. pxsim.serial.writeString(s);
  1681. }
  1682. bluetooth.uartWriteString = uartWriteString;
  1683. function uartWriteBuffer(b) {
  1684. pxsim.serial.writeBuffer(b);
  1685. }
  1686. bluetooth.uartWriteBuffer = uartWriteBuffer;
  1687. function uartReadBuffer() {
  1688. return pxsim.pins.createBuffer(0);
  1689. }
  1690. bluetooth.uartReadBuffer = uartReadBuffer;
  1691. function uartReadUntil(del) {
  1692. return pxsim.serial.readUntil(del);
  1693. }
  1694. bluetooth.uartReadUntil = uartReadUntil;
  1695. function onUartDataReceived(delimiters, handler) {
  1696. var b = pxsim.board();
  1697. b.bus.listen(1200 /* MICROBIT_ID_BLE_UART */, 1 /* MICROBIT_UART_S_EVT_DELIM_MATCH */, handler);
  1698. }
  1699. bluetooth.onUartDataReceived = onUartDataReceived;
  1700. function onBluetoothConnected(a) {
  1701. // TODO
  1702. }
  1703. bluetooth.onBluetoothConnected = onBluetoothConnected;
  1704. function onBluetoothDisconnected(a) {
  1705. // TODO
  1706. }
  1707. bluetooth.onBluetoothDisconnected = onBluetoothDisconnected;
  1708. function advertiseUrl(url, power, connectable) { }
  1709. bluetooth.advertiseUrl = advertiseUrl;
  1710. function advertiseUidBuffer(nsAndInstance, power, connectable) { }
  1711. bluetooth.advertiseUidBuffer = advertiseUidBuffer;
  1712. function stopAdvertising() { }
  1713. bluetooth.stopAdvertising = stopAdvertising;
  1714. function setTransmitPower(power) { }
  1715. bluetooth.setTransmitPower = setTransmitPower;
  1716. })(bluetooth = pxsim.bluetooth || (pxsim.bluetooth = {}));
  1717. })(pxsim || (pxsim = {}));
  1718. var pxsim;
  1719. (function (pxsim) {
  1720. function sendBufferAsm(buffer, pin) {
  1721. var b = pxsim.board();
  1722. if (b) {
  1723. var np = b.neopixelState;
  1724. if (np) {
  1725. var buf = buffer.data;
  1726. np.updateBuffer(buf, pin); // TODO this is wrong
  1727. pxsim.runtime.queueDisplayUpdate();
  1728. }
  1729. }
  1730. }
  1731. pxsim.sendBufferAsm = sendBufferAsm;
  1732. })(pxsim || (pxsim = {}));
  1733. var pxsim;
  1734. (function (pxsim) {
  1735. var RadioDatagram = /** @class */ (function () {
  1736. function RadioDatagram(runtime) {
  1737. this.runtime = runtime;
  1738. this.datagram = [];
  1739. this.lastReceived = RadioDatagram.defaultPacket();
  1740. }
  1741. RadioDatagram.prototype.queue = function (packet) {
  1742. if (this.datagram.length < 4) {
  1743. this.datagram.push(packet);
  1744. }
  1745. pxsim.runtime.board.bus.queue(29 /* MICROBIT_ID_RADIO */, 1 /* MICROBIT_RADIO_EVT_DATAGRAM */);
  1746. };
  1747. RadioDatagram.prototype.send = function (payload) {
  1748. var b = pxsim.board();
  1749. pxsim.Runtime.postMessage({
  1750. type: "radiopacket",
  1751. rssi: -42,
  1752. serial: b.radioState.transmitSerialNumber ? pxsim.control.deviceSerialNumber() : 0,
  1753. time: new Date().getTime(),
  1754. payload: payload
  1755. });
  1756. };
  1757. RadioDatagram.prototype.recv = function () {
  1758. var r = this.datagram.shift();
  1759. if (!r)
  1760. r = RadioDatagram.defaultPacket();
  1761. return this.lastReceived = r;
  1762. };
  1763. RadioDatagram.defaultPacket = function () {
  1764. return {
  1765. rssi: -1,
  1766. serial: 0,
  1767. time: 0,
  1768. payload: { type: -1, groupId: 0 }
  1769. };
  1770. };
  1771. return RadioDatagram;
  1772. }());
  1773. pxsim.RadioDatagram = RadioDatagram;
  1774. var RadioState = /** @class */ (function () {
  1775. function RadioState(runtime) {
  1776. this.power = 0;
  1777. this.transmitSerialNumber = false;
  1778. this.datagram = new RadioDatagram(runtime);
  1779. this.power = 6; // default value
  1780. this.groupId = 0;
  1781. }
  1782. RadioState.prototype.setGroup = function (id) {
  1783. this.groupId = id & 0xff; // byte only
  1784. };
  1785. RadioState.prototype.setTransmitPower = function (power) {
  1786. this.power = Math.max(0, Math.min(7, power));
  1787. };
  1788. RadioState.prototype.setTransmitSerialNumber = function (sn) {
  1789. this.transmitSerialNumber = !!sn;
  1790. };
  1791. RadioState.prototype.raiseEvent = function (id, eventid) {
  1792. pxsim.Runtime.postMessage({
  1793. type: "eventbus",
  1794. id: id,
  1795. eventid: eventid,
  1796. power: this.power,
  1797. group: this.groupId
  1798. });
  1799. };
  1800. RadioState.prototype.receivePacket = function (packet) {
  1801. if (this.groupId == packet.payload.groupId)
  1802. this.datagram.queue(packet);
  1803. };
  1804. return RadioState;
  1805. }());
  1806. pxsim.RadioState = RadioState;
  1807. })(pxsim || (pxsim = {}));
  1808. (function (pxsim) {
  1809. var radio;
  1810. (function (radio) {
  1811. var PacketPayloadType;
  1812. (function (PacketPayloadType) {
  1813. PacketPayloadType[PacketPayloadType["NUMBER"] = 0] = "NUMBER";
  1814. PacketPayloadType[PacketPayloadType["VALUE"] = 1] = "VALUE";
  1815. PacketPayloadType[PacketPayloadType["STRING"] = 2] = "STRING";
  1816. PacketPayloadType[PacketPayloadType["BUFFER"] = 3] = "BUFFER";
  1817. })(PacketPayloadType || (PacketPayloadType = {}));
  1818. function raiseEvent(id, eventid) {
  1819. pxsim.board().radioState.raiseEvent(id, eventid);
  1820. }
  1821. radio.raiseEvent = raiseEvent;
  1822. function setGroup(id) {
  1823. pxsim.board().radioState.setGroup(id);
  1824. }
  1825. radio.setGroup = setGroup;
  1826. function setTransmitPower(power) {
  1827. pxsim.board().radioState.setTransmitPower(power);
  1828. }
  1829. radio.setTransmitPower = setTransmitPower;
  1830. function setTransmitSerialNumber(transmit) {
  1831. pxsim.board().radioState.setTransmitSerialNumber(transmit);
  1832. }
  1833. radio.setTransmitSerialNumber = setTransmitSerialNumber;
  1834. function sendNumber(value) {
  1835. pxsim.board().radioState.datagram.send({
  1836. type: PacketPayloadType.NUMBER,
  1837. groupId: pxsim.board().radioState.groupId,
  1838. numberData: value,
  1839. });
  1840. }
  1841. radio.sendNumber = sendNumber;
  1842. function sendString(msg) {
  1843. if (msg === undefined)
  1844. return;
  1845. msg = msg.substr(0, 19);
  1846. pxsim.board().radioState.datagram.send({
  1847. type: PacketPayloadType.STRING,
  1848. groupId: pxsim.board().radioState.groupId,
  1849. stringData: msg,
  1850. });
  1851. }
  1852. radio.sendString = sendString;
  1853. function sendBuffer(buf) {
  1854. if (!buf)
  1855. return;
  1856. var data = buf.data.slice(0, 18);
  1857. pxsim.board().radioState.datagram.send({
  1858. type: PacketPayloadType.STRING,
  1859. groupId: pxsim.board().radioState.groupId,
  1860. bufferData: data
  1861. });
  1862. }
  1863. radio.sendBuffer = sendBuffer;
  1864. function writeValueToSerial() {
  1865. var b = pxsim.board();
  1866. writePacketToSerial(b, b.radioState.datagram.recv());
  1867. }
  1868. radio.writeValueToSerial = writeValueToSerial;
  1869. function writeReceivedPacketToSerial() {
  1870. var b = pxsim.board();
  1871. writePacketToSerial(b, b.radioState.datagram.lastReceived);
  1872. }
  1873. radio.writeReceivedPacketToSerial = writeReceivedPacketToSerial;
  1874. function sendValue(name, value) {
  1875. name = name.substr(0, 12);
  1876. var msg = [];
  1877. msg.push();
  1878. pxsim.board().radioState.datagram.send({
  1879. type: PacketPayloadType.VALUE,
  1880. groupId: pxsim.board().radioState.groupId,
  1881. stringData: name,
  1882. numberData: value
  1883. });
  1884. }
  1885. radio.sendValue = sendValue;
  1886. function receiveNumber() {
  1887. var packet = pxsim.board().radioState.datagram.recv();
  1888. return receivedNumber();
  1889. }
  1890. radio.receiveNumber = receiveNumber;
  1891. function receiveString() {
  1892. var packet = pxsim.board().radioState.datagram.recv();
  1893. return receivedString();
  1894. }
  1895. radio.receiveString = receiveString;
  1896. function receivedSignalStrength() {
  1897. return pxsim.board().radioState.datagram.lastReceived.rssi;
  1898. }
  1899. radio.receivedSignalStrength = receivedSignalStrength;
  1900. function onDataReceived(handler) {
  1901. pxsim.pxtcore.registerWithDal(29 /* MICROBIT_ID_RADIO */, 1 /* MICROBIT_RADIO_EVT_DATAGRAM */, handler);
  1902. radio.receiveNumber();
  1903. }
  1904. radio.onDataReceived = onDataReceived;
  1905. function receivedNumber() {
  1906. return pxsim.board().radioState.datagram.lastReceived.payload.numberData || 0;
  1907. }
  1908. radio.receivedNumber = receivedNumber;
  1909. function receivedSerial() {
  1910. return pxsim.board().radioState.datagram.lastReceived.serial;
  1911. }
  1912. radio.receivedSerial = receivedSerial;
  1913. function receivedString() {
  1914. return pxsim.initString(pxsim.board().radioState.datagram.lastReceived.payload.stringData || "");
  1915. }
  1916. radio.receivedString = receivedString;
  1917. function receivedBuffer() {
  1918. return new pxsim.RefBuffer(pxsim.board().radioState.datagram.lastReceived.payload.bufferData || new Uint8Array(0));
  1919. }
  1920. radio.receivedBuffer = receivedBuffer;
  1921. function receivedTime() {
  1922. return pxsim.board().radioState.datagram.lastReceived.time;
  1923. }
  1924. radio.receivedTime = receivedTime;
  1925. function writePacketToSerial(b, p) {
  1926. switch (p.payload.type) {
  1927. case PacketPayloadType.NUMBER:
  1928. b.writeSerial("{\"t\":" + p.time + ",\"s\":" + p.serial + ",\"v\":" + p.payload.numberData + "}\r\n");
  1929. break;
  1930. case PacketPayloadType.VALUE:
  1931. b.writeSerial("{\"t\":" + p.time + ",\"s\":" + p.serial + ",\"n\":\"" + p.payload.stringData + "\",\"v\":" + p.payload.numberData + "}\r\n");
  1932. break;
  1933. case PacketPayloadType.STRING:
  1934. b.writeSerial("{\"t\":" + p.time + ",\"s\":" + p.serial + ",\"n\":\"" + p.payload.stringData + "\"}\r\n");
  1935. break;
  1936. // TODO: (microbit master)
  1937. // case PacketPayloadType.BUFFER:
  1938. // const buf = new Uint8Array(p.payload.bufferData.buffer);
  1939. // let res = "";
  1940. // for (let i = 0; i < buf.length; ++i)
  1941. // res += String.fromCharCode(buf[i]);
  1942. // b.writeSerial(`{"t":${p.time},"s":${p.serial},"b":"${res}"}\r\n`)
  1943. default:
  1944. // unknown type
  1945. break;
  1946. }
  1947. }
  1948. })(radio = pxsim.radio || (pxsim.radio = {}));
  1949. })(pxsim || (pxsim = {}));
  1950. var pxsim;
  1951. (function (pxsim) {
  1952. var SERIAL_BUFFER_LENGTH = 16;
  1953. var SerialState = /** @class */ (function () {
  1954. function SerialState() {
  1955. this.serialIn = [];
  1956. this.serialOutBuffer = "";
  1957. }
  1958. SerialState.prototype.receiveData = function (data) {
  1959. this.serialIn.push();
  1960. };
  1961. SerialState.prototype.readSerial = function () {
  1962. var v = this.serialIn.shift() || "";
  1963. return v;
  1964. };
  1965. SerialState.prototype.writeSerial = function (s) {
  1966. this.serialOutBuffer += s;
  1967. if (/\n/.test(this.serialOutBuffer) || this.serialOutBuffer.length > SERIAL_BUFFER_LENGTH) {
  1968. pxsim.Runtime.postMessage({
  1969. type: 'serial',
  1970. data: this.serialOutBuffer,
  1971. id: pxsim.runtime.id,
  1972. sim: true
  1973. });
  1974. this.serialOutBuffer = '';
  1975. }
  1976. };
  1977. return SerialState;
  1978. }());
  1979. pxsim.SerialState = SerialState;
  1980. })(pxsim || (pxsim = {}));
  1981. (function (pxsim) {
  1982. var control;
  1983. (function (control) {
  1984. function __log(s) {
  1985. pxsim.board().writeSerial(s + "\r\n");
  1986. }
  1987. control.__log = __log;
  1988. })(control = pxsim.control || (pxsim.control = {}));
  1989. })(pxsim || (pxsim = {}));
  1990. (function (pxsim) {
  1991. var serial;
  1992. (function (serial) {
  1993. function writeString(s) {
  1994. pxsim.board().writeSerial(s);
  1995. }
  1996. serial.writeString = writeString;
  1997. function writeBuffer(buf) {
  1998. // TODO
  1999. }
  2000. serial.writeBuffer = writeBuffer;
  2001. function readUntil(del) {
  2002. return readString();
  2003. }
  2004. serial.readUntil = readUntil;
  2005. function readString() {
  2006. return pxsim.board().serialState.readSerial();
  2007. }
  2008. serial.readString = readString;
  2009. function onDataReceived(delimiters, handler) {
  2010. var b = pxsim.board();
  2011. b.bus.listen(32 /* MICROBIT_ID_SERIAL */, 1 /* MICROBIT_SERIAL_EVT_DELIM_MATCH */, handler);
  2012. }
  2013. serial.onDataReceived = onDataReceived;
  2014. function redirect(tx, rx, rate) {
  2015. // TODO?
  2016. }
  2017. serial.redirect = redirect;
  2018. function redirectToUSB() {
  2019. // TODO
  2020. }
  2021. serial.redirectToUSB = redirectToUSB;
  2022. function readBuffer(length) {
  2023. if (length <= 0)
  2024. length = 64;
  2025. return pxsim.pins.createBuffer(length);
  2026. }
  2027. serial.readBuffer = readBuffer;
  2028. })(serial = pxsim.serial || (pxsim.serial = {}));
  2029. })(pxsim || (pxsim = {}));
  2030. var pxsim;
  2031. (function (pxsim) {
  2032. var ThermometerState = /** @class */ (function () {
  2033. function ThermometerState() {
  2034. this.usesTemperature = false;
  2035. this.temperature = 21;
  2036. }
  2037. return ThermometerState;
  2038. }());
  2039. pxsim.ThermometerState = ThermometerState;
  2040. })(pxsim || (pxsim = {}));
  2041. (function (pxsim) {
  2042. var input;
  2043. (function (input) {
  2044. function temperature() {
  2045. var b = pxsim.board();
  2046. if (!b.thermometerState.usesTemperature) {
  2047. b.thermometerState.usesTemperature = true;
  2048. pxsim.runtime.queueDisplayUpdate();
  2049. }
  2050. return b.thermometerState.temperature;
  2051. }
  2052. input.temperature = temperature;
  2053. })(input = pxsim.input || (pxsim.input = {}));
  2054. })(pxsim || (pxsim = {}));
  2055. var pxsim;
  2056. (function (pxsim) {
  2057. var visuals;
  2058. (function (visuals) {
  2059. visuals.mkBoardView = function (opts) {
  2060. return new visuals.MicrobitBoardSvg({
  2061. runtime: pxsim.runtime,
  2062. theme: visuals.randomTheme(opts.highContrast),
  2063. wireframe: opts.wireframe
  2064. });
  2065. };
  2066. })(visuals = pxsim.visuals || (pxsim.visuals = {}));
  2067. })(pxsim || (pxsim = {}));
  2068. /// <reference path="../../node_modules/pxt-core/built/pxtsim.d.ts"/>
  2069. var pxsim;
  2070. (function (pxsim) {
  2071. var visuals;
  2072. (function (visuals) {
  2073. function mkLedMatrixSvg(xy, rows, cols) {
  2074. var result = { el: null, y: 0, x: 0, w: 0, h: 0, leds: [], ledsOuter: [], background: null };
  2075. result.el = pxsim.svg.elt("g");
  2076. var width = cols * visuals.PIN_DIST;
  2077. var height = rows * visuals.PIN_DIST;
  2078. var ledRad = Math.round(visuals.PIN_DIST * .35);
  2079. var spacing = visuals.PIN_DIST;
  2080. var padding = (spacing - 2 * ledRad) / 2.0;
  2081. var x = xy[0], y = xy[1];
  2082. var left = x - (ledRad + padding);
  2083. var top = y - (ledRad + padding);
  2084. result.x = left;
  2085. result.y = top;
  2086. result.w = width;
  2087. result.h = height;
  2088. result.background = pxsim.svg.child(result.el, "rect", { class: "sim-display", x: left, y: top, width: width, height: height });
  2089. // ledsOuter
  2090. result.leds = [];
  2091. result.ledsOuter = [];
  2092. var hoverRad = ledRad * 1.2;
  2093. for (var i = 0; i < rows; ++i) {
  2094. var y_1 = top + ledRad + i * spacing + padding;
  2095. for (var j = 0; j < cols; ++j) {
  2096. var x_1 = left + ledRad + j * spacing + padding;
  2097. result.ledsOuter.push(pxsim.svg.child(result.el, "circle", { class: "sim-led-back", cx: x_1, cy: y_1, r: ledRad }));
  2098. result.leds.push(pxsim.svg.child(result.el, "circle", { class: "sim-led", cx: x_1, cy: y_1, r: hoverRad, title: "(" + j + "," + i + ")" }));
  2099. }
  2100. }
  2101. //default theme
  2102. pxsim.svg.fill(result.background, visuals.defaultLedMatrixTheme.background);
  2103. pxsim.svg.fills(result.leds, visuals.defaultLedMatrixTheme.ledOn);
  2104. pxsim.svg.fills(result.ledsOuter, visuals.defaultLedMatrixTheme.ledOff);
  2105. //turn off LEDs
  2106. result.leds.forEach(function (l) { return l.style.opacity = 0 + ""; });
  2107. return result;
  2108. }
  2109. visuals.mkLedMatrixSvg = mkLedMatrixSvg;
  2110. visuals.defaultLedMatrixTheme = {
  2111. background: "#000",
  2112. ledOn: "#ff5f5f",
  2113. ledOff: "#DDD",
  2114. };
  2115. 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 ";
  2116. var LedMatrixView = /** @class */ (function () {
  2117. function LedMatrixView() {
  2118. this.DRAW_SIZE = 8;
  2119. this.ACTIVE_SIZE = 5;
  2120. this.style = visuals.LED_MATRIX_STYLE;
  2121. }
  2122. LedMatrixView.prototype.init = function (bus, state) {
  2123. this.bus = bus;
  2124. this.state = state;
  2125. this.theme = visuals.defaultLedMatrixTheme;
  2126. this.defs = [];
  2127. this.element = this.buildDom();
  2128. };
  2129. LedMatrixView.prototype.moveToCoord = function (xy) {
  2130. visuals.translateEl(this.element, xy);
  2131. };
  2132. LedMatrixView.prototype.updateTheme = function () {
  2133. pxsim.svg.fill(this.background, this.theme.background);
  2134. pxsim.svg.fills(this.leds, this.theme.ledOn);
  2135. pxsim.svg.fills(this.ledsOuter, this.theme.ledOff);
  2136. };
  2137. LedMatrixView.prototype.updateState = function () {
  2138. var _this = this;
  2139. if (this.state.disabled) {
  2140. this.leds.forEach(function (led, i) {
  2141. var sel = led;
  2142. sel.style.opacity = 0 + "";
  2143. });
  2144. return;
  2145. }
  2146. var bw = this.state.displayMode == pxsim.DisplayMode.bw;
  2147. var img = this.state.image;
  2148. this.leds.forEach(function (led, i) {
  2149. var sel = led;
  2150. var dx = i % _this.DRAW_SIZE;
  2151. var dy = (i - dx) / _this.DRAW_SIZE;
  2152. if (dx < _this.ACTIVE_SIZE && dy < _this.ACTIVE_SIZE) {
  2153. var j = dx + dy * _this.ACTIVE_SIZE;
  2154. sel.style.opacity = ((bw ? img.data[j] > 0 ? 255 : 0 : img.data[j]) / 255.0) + "";
  2155. }
  2156. else {
  2157. sel.style.opacity = 0 + "";
  2158. }
  2159. });
  2160. };
  2161. LedMatrixView.prototype.buildDom = function () {
  2162. var res = mkLedMatrixSvg([0, 0], this.DRAW_SIZE, this.DRAW_SIZE);
  2163. var display = res.el;
  2164. this.background = res.background;
  2165. this.leds = res.leds;
  2166. this.ledsOuter = res.ledsOuter;
  2167. return display;
  2168. };
  2169. return LedMatrixView;
  2170. }());
  2171. visuals.LedMatrixView = LedMatrixView;
  2172. })(visuals = pxsim.visuals || (pxsim.visuals = {}));
  2173. })(pxsim || (pxsim = {}));
  2174. var pxsim;
  2175. (function (pxsim) {
  2176. var visuals;
  2177. (function (visuals) {
  2178. var MB_STYLE = "\n svg.sim {\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n display: block;\n }\n svg.sim.grayscale {\n -moz-filter: grayscale(1);\n -webkit-filter: grayscale(1);\n filter: grayscale(1);\n }\n .sim-button-group {\n cursor: pointer;\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:#a0a0a0;\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:#fff;\n stroke-width: 3px;\n }\n\n .sim-antenna {\n stroke:#555;\n stroke-width: 2px;\n }\n\n .sim-text {\n font-family:\"Lucida Console\", Monaco, monospace;\n font-size:25px;\n fill:#fff;\n pointer-events: none;\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: 3px;\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 *:focus {\n outline: none;\n }\n *:focus .sim-button-outer,\n .sim-pin:focus,\n .sim-thermometer:focus,\n .sim-shake:focus,\n .sim-light-level-button:focus {\n stroke: #4D90FE;\n stroke-width: 5px !important;\n }\n .no-drag, .sim-text, .sim-text-pin {\n user-drag: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-drag: none;\n -webkit-user-select: none;\n -ms-user-select: none;\n }\n ";
  2179. var MB_HIGHCONTRAST = "\npath.sim-board {\n stroke: white;\n stroke-width: 3;\n}\n.sim-led {\n stroke: red;\n}\n*:focus .sim-button-outer,\n.sim-pin:focus,\n.sim-thermometer:focus,\n.sim-shake:focus,\n.sim-light-level-button:focus {\n stroke: #10C8CD !important;\n}\n ";
  2180. var pins4onXs = [66.7, 79.1, 91.4, 103.7, 164.3, 176.6, 188.9, 201.3, 213.6, 275.2, 287.5, 299.8, 312.1, 324.5, 385.1, 397.4, 409.7, 422];
  2181. var pins4onMids = pins4onXs.map(function (x) { return x + 5; });
  2182. var littlePinDist = pins4onMids[1] - pins4onMids[0];
  2183. var bigPinWidth = pins4onMids[4] - pins4onMids[3];
  2184. var pin0mid = pins4onXs[0] - bigPinWidth / 2.0;
  2185. var pin3mid = pin0mid - bigPinWidth / 2.0;
  2186. var pin1mid = pins4onMids[3] + bigPinWidth / 2.0;
  2187. var pin2mid = pins4onMids[8] + bigPinWidth / 2.0;
  2188. var pin3Vmid = pins4onMids[13] + bigPinWidth / 2.0;
  2189. var pinGNDmid = pins4onMids[pins4onMids.length - 1] + bigPinWidth / 2.0;
  2190. var pinGND2mid = pinGNDmid + bigPinWidth / 2.0;
  2191. var pinMids = [pin0mid, pin1mid, pin2mid, pin3mid].concat(pins4onMids).concat([pinGNDmid, pin3Vmid, pinGND2mid]);
  2192. var pinNames = [
  2193. "P0", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10",
  2194. "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20",
  2195. "GND0", "GND", "+3v3", "GND1"
  2196. ];
  2197. var pinTitles = [
  2198. "P0, ANALOG IN",
  2199. "P1, ANALOG IN",
  2200. "P2, ANALOG IN",
  2201. "P3, ANALOG IN, LED Col 1",
  2202. "P4, ANALOG IN, LED Col 2",
  2203. "P5, BUTTON A",
  2204. "P6, LED Col 9",
  2205. "P7, LED Col 8",
  2206. "P8",
  2207. "P9, LED Col 7",
  2208. "P10, ANALOG IN, LED Col 3",
  2209. "P11, BUTTON B",
  2210. "P12, RESERVED ACCESSIBILITY",
  2211. "P13, SPI - SCK",
  2212. "P14, SPI - MISO",
  2213. "P15, SPI - MOSI",
  2214. "P16, SPI - Chip Select",
  2215. "P17, +3v3",
  2216. "P18, +3v3",
  2217. "P19, I2C - SCL",
  2218. "P20, I2C - SDA",
  2219. "GND", "GND", "+3v3", "GND"
  2220. ];
  2221. var MB_WIDTH = 500;
  2222. var MB_HEIGHT = 408;
  2223. visuals.themes = ["#3ADCFE", "#FFD43A", "#3AFFB3", "#FF3A54"].map(function (accent) {
  2224. return {
  2225. accent: accent,
  2226. display: "#000",
  2227. pin: "#D4AF37",
  2228. pinTouched: "#FFA500",
  2229. pinActive: "#FF5500",
  2230. ledOn: "#ff7f7f",
  2231. ledOff: "#202020",
  2232. buttonOuter: "#979797",
  2233. buttonUp: "#000",
  2234. buttonDown: "#FFA500",
  2235. virtualButtonOuter: "#333",
  2236. virtualButtonUp: "#fff",
  2237. lightLevelOn: "yellow",
  2238. lightLevelOff: "#555"
  2239. };
  2240. });
  2241. function randomTheme(highContrast) {
  2242. var theme = visuals.themes[Math.floor(Math.random() * visuals.themes.length)];
  2243. if (highContrast) {
  2244. theme = JSON.parse(JSON.stringify(theme));
  2245. theme.highContrast = true;
  2246. theme.ledOff = "#888";
  2247. theme.ledOn = "#0000bb";
  2248. theme.display = "#ffffff";
  2249. theme.pin = "#D4AF37";
  2250. theme.accent = "#273EE2";
  2251. }
  2252. return theme;
  2253. }
  2254. visuals.randomTheme = randomTheme;
  2255. var MicrobitBoardSvg = /** @class */ (function () {
  2256. function MicrobitBoardSvg(props) {
  2257. var _this = this;
  2258. this.props = props;
  2259. this.headInitialized = false;
  2260. this.pinNmToCoord = {};
  2261. this.lastFlashTime = 0;
  2262. this.lastAntennaFlash = 0;
  2263. this.recordPinCoords();
  2264. this.buildDom();
  2265. if (props && props.wireframe)
  2266. pxsim.svg.addClass(this.element, "sim-wireframe");
  2267. if (props && props.theme)
  2268. this.updateTheme();
  2269. if (props && props.runtime) {
  2270. this.board = this.props.runtime.board;
  2271. this.board.updateSubscribers.push(function () { return _this.updateState(); });
  2272. this.updateState();
  2273. this.attachEvents();
  2274. }
  2275. }
  2276. MicrobitBoardSvg.prototype.getView = function () {
  2277. return {
  2278. el: this.element,
  2279. y: 0,
  2280. x: 0,
  2281. w: MB_WIDTH,
  2282. h: MB_HEIGHT
  2283. };
  2284. };
  2285. MicrobitBoardSvg.prototype.getCoord = function (pinNm) {
  2286. return this.pinNmToCoord[pinNm];
  2287. };
  2288. MicrobitBoardSvg.prototype.highlightPin = function (pinNm) {
  2289. //TODO: for instructions
  2290. };
  2291. MicrobitBoardSvg.prototype.getPinDist = function () {
  2292. return littlePinDist * 1.7;
  2293. };
  2294. MicrobitBoardSvg.prototype.recordPinCoords = function () {
  2295. var _this = this;
  2296. var pinsY = 356.7 + 40;
  2297. pinNames.forEach(function (nm, i) {
  2298. var x = pinMids[i];
  2299. _this.pinNmToCoord[nm] = [x, pinsY];
  2300. });
  2301. };
  2302. MicrobitBoardSvg.prototype.updateTheme = function () {
  2303. var theme = this.props.theme;
  2304. pxsim.svg.fill(this.display, theme.display);
  2305. pxsim.svg.fills(this.leds, theme.ledOn);
  2306. pxsim.svg.fills(this.ledsOuter, theme.ledOff);
  2307. pxsim.svg.fills(this.buttonsOuter.slice(0, 2), theme.buttonOuter);
  2308. pxsim.svg.fills(this.buttons.slice(0, 2), theme.buttonUp);
  2309. pxsim.svg.fill(this.buttonsOuter[2], theme.virtualButtonOuter);
  2310. pxsim.svg.fill(this.buttons[2], theme.virtualButtonUp);
  2311. pxsim.svg.fills(this.logos, theme.accent);
  2312. if (this.shakeButton)
  2313. pxsim.svg.fill(this.shakeButton, theme.virtualButtonUp);
  2314. this.pinGradients.forEach(function (lg) { return pxsim.svg.setGradientColors(lg, theme.pin, theme.pinActive); });
  2315. pxsim.svg.setGradientColors(this.lightLevelGradient, theme.lightLevelOn, theme.lightLevelOff);
  2316. pxsim.svg.setGradientColors(this.thermometerGradient, theme.ledOff, theme.ledOn);
  2317. };
  2318. MicrobitBoardSvg.prototype.updateState = function () {
  2319. var _this = this;
  2320. var state = this.board;
  2321. if (!state)
  2322. return;
  2323. var theme = this.props.theme;
  2324. var bpState = state.buttonPairState;
  2325. var buttons = [bpState.aBtn, bpState.bBtn, bpState.abBtn];
  2326. buttons.forEach(function (btn, index) {
  2327. pxsim.svg.fill(_this.buttons[index], btn.pressed ? theme.buttonDown : theme.buttonUp);
  2328. });
  2329. if (state.ledMatrixState.disabled) {
  2330. this.leds.forEach(function (led, i) {
  2331. var sel = led;
  2332. sel.style.opacity = "0";
  2333. });
  2334. }
  2335. else {
  2336. var bw_1 = state.ledMatrixState.displayMode == pxsim.DisplayMode.bw;
  2337. var img_1 = state.ledMatrixState.image;
  2338. var br_1 = state.ledMatrixState.brigthness != undefined ? state.ledMatrixState.brigthness : 255;
  2339. this.leds.forEach(function (led, i) {
  2340. var sel = led;
  2341. var imgbr = bw_1 ? (img_1.data[i] > 0 ? br_1 : 0) : img_1.data[i];
  2342. // correct brightness
  2343. var opacity = imgbr > 0 ? imgbr / 255 * 155 + 100 : 0;
  2344. var transfrom = imgbr > 0 ? imgbr / 255 * 0.4 + 0.6 : 0;
  2345. sel.style.opacity = (opacity / 255) + "";
  2346. if (transfrom > 0) {
  2347. sel.style.transformBox = 'fill-box';
  2348. sel.style.transformOrigin = '50% 50%';
  2349. sel.style.transform = "scale(" + transfrom + ")";
  2350. }
  2351. });
  2352. }
  2353. this.updatePins();
  2354. this.updateTilt();
  2355. this.updateHeading();
  2356. this.updateLightLevel();
  2357. this.updateTemperature();
  2358. this.updateButtonAB();
  2359. this.updateGestures();
  2360. if (!pxsim.runtime || pxsim.runtime.dead)
  2361. pxsim.svg.addClass(this.element, "grayscale");
  2362. else
  2363. pxsim.svg.removeClass(this.element, "grayscale");
  2364. };
  2365. MicrobitBoardSvg.prototype.updateGestures = function () {
  2366. var _this = this;
  2367. var state = this.board;
  2368. if (state.accelerometerState.useShake && !this.shakeButton) {
  2369. this.shakeButton = pxsim.svg.child(this.g, "circle", { cx: 380, cy: 100, r: 16.5, class: "sim-shake" });
  2370. pxsim.accessibility.makeFocusable(this.shakeButton);
  2371. pxsim.svg.fill(this.shakeButton, this.props.theme.virtualButtonUp);
  2372. pxsim.pointerEvents.down.forEach(function (evid) { return _this.shakeButton.addEventListener(evid, function (ev) {
  2373. var state = _this.board;
  2374. pxsim.svg.fill(_this.shakeButton, _this.props.theme.buttonDown);
  2375. }); });
  2376. this.shakeButton.addEventListener(pxsim.pointerEvents.leave, function (ev) {
  2377. var state = _this.board;
  2378. pxsim.svg.fill(_this.shakeButton, _this.props.theme.virtualButtonUp);
  2379. });
  2380. this.shakeButton.addEventListener(pxsim.pointerEvents.up, function (ev) {
  2381. var state = _this.board;
  2382. pxsim.svg.fill(_this.shakeButton, _this.props.theme.virtualButtonUp);
  2383. _this.board.bus.queue(27 /* MICROBIT_ID_GESTURE */, 11); // GESTURE_SHAKE
  2384. });
  2385. pxsim.accessibility.enableKeyboardInteraction(this.shakeButton, undefined, function () {
  2386. _this.board.bus.queue(27 /* MICROBIT_ID_GESTURE */, 11);
  2387. });
  2388. pxsim.accessibility.setAria(this.shakeButton, "button", "Shake the board");
  2389. this.shakeText = pxsim.svg.child(this.g, "text", { x: 400, y: 110, class: "sim-text" });
  2390. this.shakeText.textContent = "SHAKE";
  2391. }
  2392. };
  2393. MicrobitBoardSvg.prototype.updateButtonAB = function () {
  2394. var state = this.board;
  2395. if (state.buttonPairState.usesButtonAB && !this.buttonABText) {
  2396. this.buttonsOuter[2].style.visibility = "visible";
  2397. this.buttons[2].style.visibility = "visible";
  2398. this.buttonABText = pxsim.svg.child(this.g, "text", { class: "sim-text", x: 370, y: 272 });
  2399. this.buttonABText.textContent = "A+B";
  2400. this.updateTheme();
  2401. }
  2402. };
  2403. MicrobitBoardSvg.prototype.updatePin = function (pin, index) {
  2404. if (!pin)
  2405. return;
  2406. var text = this.pinTexts[index];
  2407. var v = "";
  2408. if (pin.mode & pxsim.PinFlags.Analog) {
  2409. v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + "%";
  2410. if (text)
  2411. text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + "";
  2412. }
  2413. else if (pin.mode & pxsim.PinFlags.Digital) {
  2414. v = pin.value > 0 ? "0%" : "100%";
  2415. if (text)
  2416. text.textContent = pin.value > 0 ? "1" : "0";
  2417. }
  2418. else if (pin.mode & pxsim.PinFlags.Touch) {
  2419. v = pin.touched ? "0%" : "100%";
  2420. if (text)
  2421. text.textContent = "";
  2422. }
  2423. else {
  2424. v = "100%";
  2425. if (text)
  2426. text.textContent = "";
  2427. }
  2428. if (v)
  2429. pxsim.svg.setGradientValue(this.pinGradients[index], v);
  2430. if (pin.mode !== pxsim.PinFlags.Unused) {
  2431. pxsim.accessibility.makeFocusable(this.pins[index]);
  2432. pxsim.accessibility.setAria(this.pins[index], "slider", this.pins[index].firstChild.textContent);
  2433. this.pins[index].setAttribute("aria-valuemin", "0");
  2434. this.pins[index].setAttribute("aria-valuemax", pin.mode & pxsim.PinFlags.Analog ? "1023" : "100");
  2435. this.pins[index].setAttribute("aria-orientation", "vertical");
  2436. this.pins[index].setAttribute("aria-valuenow", text ? text.textContent : v);
  2437. pxsim.accessibility.setLiveContent(text ? text.textContent : v);
  2438. }
  2439. };
  2440. MicrobitBoardSvg.prototype.updateTemperature = function () {
  2441. var _this = this;
  2442. var state = this.board;
  2443. if (!state || !state.thermometerState.usesTemperature)
  2444. return;
  2445. var tmin = -5;
  2446. var tmax = 50;
  2447. if (!this.thermometer) {
  2448. var gid = "gradient-thermometer";
  2449. this.thermometerGradient = pxsim.svg.linearGradient(this.defs, gid);
  2450. this.thermometer = pxsim.svg.child(this.g, "rect", {
  2451. class: "sim-thermometer no-drag",
  2452. x: 120,
  2453. y: 110,
  2454. width: 20,
  2455. height: 160,
  2456. rx: 5, ry: 5,
  2457. fill: "url(#" + gid + ")"
  2458. });
  2459. this.thermometerText = pxsim.svg.child(this.g, "text", { class: 'sim-text', x: 58, y: 130 });
  2460. this.updateTheme();
  2461. var pt_1 = this.element.createSVGPoint();
  2462. pxsim.svg.buttonEvents(this.thermometer,
  2463. // move
  2464. function (ev) {
  2465. var cur = pxsim.svg.cursorPoint(pt_1, _this.element, ev);
  2466. var t = Math.max(0, Math.min(1, (260 - cur.y) / 140));
  2467. state.thermometerState.temperature = Math.floor(tmin + t * (tmax - tmin));
  2468. _this.updateTemperature();
  2469. },
  2470. // start
  2471. function (ev) { },
  2472. // stop
  2473. function (ev) { },
  2474. // keydown
  2475. function (ev) {
  2476. var charCode = (typeof ev.which == "number") ? ev.which : ev.keyCode;
  2477. if (charCode === 40 || charCode === 37) {
  2478. state.thermometerState.temperature--;
  2479. if (state.thermometerState.temperature < -5) {
  2480. state.thermometerState.temperature = 50;
  2481. }
  2482. _this.updateTemperature();
  2483. }
  2484. else if (charCode === 38 || charCode === 39) {
  2485. state.thermometerState.temperature++;
  2486. if (state.thermometerState.temperature > 50) {
  2487. state.thermometerState.temperature = -5;
  2488. }
  2489. _this.updateTemperature();
  2490. }
  2491. });
  2492. pxsim.accessibility.makeFocusable(this.thermometer);
  2493. pxsim.accessibility.setAria(this.thermometer, "slider", "Thermometer");
  2494. this.thermometer.setAttribute("aria-valuemin", "-5");
  2495. this.thermometer.setAttribute("aria-valuemax", "50");
  2496. this.thermometer.setAttribute("aria-orientation", "vertical");
  2497. this.thermometer.setAttribute("aria-valuenow", "21");
  2498. this.thermometer.setAttribute("aria-valuetext", "21°C");
  2499. }
  2500. var t = Math.max(tmin, Math.min(tmax, state.thermometerState.temperature));
  2501. var per = Math.floor((state.thermometerState.temperature - tmin) / (tmax - tmin) * 100);
  2502. pxsim.svg.setGradientValue(this.thermometerGradient, 100 - per + "%");
  2503. this.thermometerText.textContent = t + "°C";
  2504. this.thermometer.setAttribute("aria-valuenow", t.toString());
  2505. this.thermometer.setAttribute("aria-valuetext", t + "°C");
  2506. pxsim.accessibility.setLiveContent(t + "°C");
  2507. };
  2508. MicrobitBoardSvg.prototype.updateHeading = function () {
  2509. var _this = this;
  2510. var xc = 258;
  2511. var yc = 75;
  2512. var state = this.board;
  2513. if (!state || !state.compassState.usesHeading)
  2514. return;
  2515. if (!this.headInitialized) {
  2516. var p = this.head.firstChild.nextSibling;
  2517. 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");
  2518. this.updateTheme();
  2519. var pt_2 = this.element.createSVGPoint();
  2520. pxsim.svg.buttonEvents(this.head, function (ev) {
  2521. var cur = pxsim.svg.cursorPoint(pt_2, _this.element, ev);
  2522. state.compassState.heading = Math.floor(Math.atan2(cur.y - yc, cur.x - xc) * 180 / Math.PI + 90);
  2523. if (state.compassState.heading < 0)
  2524. state.compassState.heading += 360;
  2525. _this.updateHeading();
  2526. });
  2527. this.headInitialized = true;
  2528. }
  2529. var txt = state.compassState.heading.toString() + "°";
  2530. if (txt != this.headText.textContent) {
  2531. pxsim.svg.rotateElement(this.head, xc, yc, state.compassState.heading + 180);
  2532. this.headText.textContent = txt;
  2533. }
  2534. };
  2535. MicrobitBoardSvg.prototype.flashSystemLed = function () {
  2536. if (!this.systemLed)
  2537. this.systemLed = pxsim.svg.child(this.g, "circle", { class: "sim-systemled", cx: 300, cy: 20, r: 5 });
  2538. var now = Date.now();
  2539. if (now - this.lastFlashTime > 150) {
  2540. this.lastFlashTime = now;
  2541. pxsim.svg.animate(this.systemLed, "sim-flash");
  2542. }
  2543. };
  2544. MicrobitBoardSvg.prototype.flashAntenna = function () {
  2545. if (!this.antenna) {
  2546. var ax = 380;
  2547. var dax = 18;
  2548. var ayt = 10;
  2549. var ayb = 40;
  2550. 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 });
  2551. }
  2552. var now = Date.now();
  2553. if (now - this.lastAntennaFlash > 200) {
  2554. this.lastAntennaFlash = now;
  2555. pxsim.svg.animate(this.antenna, 'sim-flash-stroke');
  2556. }
  2557. };
  2558. MicrobitBoardSvg.prototype.updatePins = function () {
  2559. var _this = this;
  2560. var state = this.board;
  2561. if (!state)
  2562. return;
  2563. state.edgeConnectorState.pins.forEach(function (pin, i) { return _this.updatePin(pin, i); });
  2564. };
  2565. MicrobitBoardSvg.prototype.updateLightLevel = function () {
  2566. var _this = this;
  2567. var state = this.board;
  2568. if (!state || !state.lightSensorState.usesLightLevel)
  2569. return;
  2570. if (!this.lightLevelButton) {
  2571. var gid = "gradient-light-level";
  2572. this.lightLevelGradient = pxsim.svg.linearGradient(this.defs, gid);
  2573. var cy_1 = 50;
  2574. var r_1 = 35;
  2575. this.lightLevelButton = pxsim.svg.child(this.g, "circle", {
  2576. cx: "50px", cy: cy_1 + "px", r: r_1 + "px",
  2577. class: 'sim-light-level-button no-drag',
  2578. fill: "url(#" + gid + ")"
  2579. });
  2580. var pt_3 = this.element.createSVGPoint();
  2581. pxsim.svg.buttonEvents(this.lightLevelButton,
  2582. // move
  2583. function (ev) {
  2584. var pos = pxsim.svg.cursorPoint(pt_3, _this.element, ev);
  2585. var rs = r_1 / 2;
  2586. var level = Math.max(0, Math.min(255, Math.floor((pos.y - (cy_1 - rs)) / (2 * rs) * 255)));
  2587. if (level != _this.board.lightSensorState.lightLevel) {
  2588. _this.board.lightSensorState.lightLevel = level;
  2589. _this.applyLightLevel();
  2590. }
  2591. },
  2592. // start
  2593. function (ev) { },
  2594. // stop
  2595. function (ev) { },
  2596. // keydown
  2597. function (ev) {
  2598. var charCode = (typeof ev.which == "number") ? ev.which : ev.keyCode;
  2599. if (charCode === 40 || charCode === 37) {
  2600. _this.board.lightSensorState.lightLevel--;
  2601. if (_this.board.lightSensorState.lightLevel < 0) {
  2602. _this.board.lightSensorState.lightLevel = 255;
  2603. }
  2604. _this.applyLightLevel();
  2605. }
  2606. else if (charCode === 38 || charCode === 39) {
  2607. _this.board.lightSensorState.lightLevel++;
  2608. if (_this.board.lightSensorState.lightLevel > 255) {
  2609. _this.board.lightSensorState.lightLevel = 0;
  2610. }
  2611. _this.applyLightLevel();
  2612. }
  2613. });
  2614. this.lightLevelText = pxsim.svg.child(this.g, "text", { x: 85, y: cy_1 + r_1 - 5, text: '', class: 'sim-text' });
  2615. this.updateTheme();
  2616. pxsim.accessibility.makeFocusable(this.lightLevelButton);
  2617. pxsim.accessibility.setAria(this.lightLevelButton, "slider", "Light level");
  2618. this.lightLevelButton.setAttribute("aria-valuemin", "0");
  2619. this.lightLevelButton.setAttribute("aria-valuemax", "255");
  2620. this.lightLevelButton.setAttribute("aria-orientation", "vertical");
  2621. this.lightLevelButton.setAttribute("aria-valuenow", "128");
  2622. }
  2623. pxsim.svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(state.lightSensorState.lightLevel * 100 / 255))) + '%');
  2624. this.lightLevelText.textContent = state.lightSensorState.lightLevel.toString();
  2625. };
  2626. MicrobitBoardSvg.prototype.applyLightLevel = function () {
  2627. var lv = this.board.lightSensorState.lightLevel;
  2628. pxsim.svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(lv * 100 / 255))) + '%');
  2629. this.lightLevelText.textContent = lv.toString();
  2630. this.lightLevelButton.setAttribute("aria-valuenow", lv.toString());
  2631. pxsim.accessibility.setLiveContent(lv.toString());
  2632. };
  2633. MicrobitBoardSvg.prototype.findParentElement = function () {
  2634. var el = this.element;
  2635. while (el.parentNode && el.parentNode.nodeName == "svg")
  2636. el = el.parentNode;
  2637. return el;
  2638. };
  2639. MicrobitBoardSvg.prototype.updateTilt = function () {
  2640. var state = this.board;
  2641. if (!state || !state.accelerometerState.accelerometer.isActive)
  2642. return;
  2643. var acc = state.accelerometerState.accelerometer;
  2644. var x = acc.getX();
  2645. var y = -acc.getY();
  2646. var z = acc.getZ();
  2647. var af = 8 / 1023;
  2648. var s = 1 - Math.min(0.1, Math.pow(Math.max(Math.abs(x), Math.abs(y)) / 1023, 2) / 35);
  2649. // fix top parent and apply style to it
  2650. var el = this.findParentElement();
  2651. el.style.transform = "perspective(30em) rotateX(" + y * af + "deg) rotateY(" + x * af + "deg) scale(" + s + ", " + s + ")";
  2652. el.style.perspectiveOrigin = "50% 50% 50%";
  2653. el.style.perspective = "30em";
  2654. // don't display acc data when AB is on
  2655. if (state.buttonPairState.usesButtonAB) {
  2656. if (this.accTextX)
  2657. this.accTextX.textContent = "";
  2658. if (this.accTextY)
  2659. this.accTextY.textContent = "";
  2660. if (this.accTextZ)
  2661. this.accTextZ.textContent = "";
  2662. }
  2663. else {
  2664. // update text
  2665. if (acc.flags & pxsim.AccelerometerFlag.X) {
  2666. if (!this.accTextX) {
  2667. this.accTextX = pxsim.svg.child(this.g, "text", { x: 365, y: 260, class: "sim-text" });
  2668. this.accTextX.textContent = "";
  2669. }
  2670. this.accTextX.textContent = "ax:" + x;
  2671. }
  2672. if (acc.flags & pxsim.AccelerometerFlag.Y) {
  2673. if (!this.accTextY) {
  2674. this.accTextY = pxsim.svg.child(this.g, "text", { x: 365, y: 285, class: "sim-text" });
  2675. this.accTextY.textContent = "";
  2676. }
  2677. this.accTextY.textContent = "ay:" + -y;
  2678. }
  2679. if (acc.flags & pxsim.AccelerometerFlag.Z) {
  2680. if (!this.accTextZ) {
  2681. this.accTextZ = pxsim.svg.child(this.g, "text", { x: 365, y: 310, class: "sim-text" });
  2682. this.accTextZ.textContent = "";
  2683. }
  2684. this.accTextZ.textContent = "az:" + z;
  2685. }
  2686. }
  2687. };
  2688. MicrobitBoardSvg.prototype.buildDom = function () {
  2689. var _this = this;
  2690. this.element = pxsim.svg.elt("svg");
  2691. pxsim.svg.hydrate(this.element, {
  2692. "version": "1.0",
  2693. "viewBox": "0 0 " + MB_WIDTH + " " + MB_HEIGHT,
  2694. "class": "sim",
  2695. "x": "0px",
  2696. "y": "0px",
  2697. "width": MB_WIDTH + "px",
  2698. "height": MB_HEIGHT + "px",
  2699. });
  2700. this.style = pxsim.svg.child(this.element, "style", {});
  2701. this.style.textContent = MB_STYLE + (this.props.theme.highContrast ? MB_HIGHCONTRAST : "");
  2702. this.defs = pxsim.svg.child(this.element, "defs", {});
  2703. this.g = pxsim.svg.elt("g");
  2704. this.element.appendChild(this.g);
  2705. // filters
  2706. var ledglow = pxsim.svg.child(this.defs, "filter", { id: "ledglow", x: "-75%", y: "-75%", width: "300%", height: "300%" });
  2707. pxsim.svg.child(ledglow, "feMorphology", { operator: "dilate", radius: "4", in: "SourceAlpha", result: "thicken" });
  2708. pxsim.svg.child(ledglow, "feGaussianBlur", { stdDeviation: "5", in: "thicken", result: "blurred" });
  2709. pxsim.svg.child(ledglow, "feFlood", { "flood-color": "rgb(255, 17, 77)", result: "glowColor" });
  2710. pxsim.svg.child(ledglow, "feComposite", { in: "glowColor", in2: "blurred", operator: "in", result: "ledglow_colored" });
  2711. var ledglowMerge = pxsim.svg.child(ledglow, "feMerge", {});
  2712. pxsim.svg.child(ledglowMerge, "feMergeNode", { in: "ledglow_colored" });
  2713. pxsim.svg.child(ledglowMerge, "feMergeNode", { in: "SourceGraphic" });
  2714. var glow = pxsim.svg.child(this.defs, "filter", { id: "filterglow", x: "-5%", y: "-5%", width: "120%", height: "120%" });
  2715. pxsim.svg.child(glow, "feGaussianBlur", { stdDeviation: "5", result: "glow" });
  2716. var merge = pxsim.svg.child(glow, "feMerge", {});
  2717. for (var i = 0; i < 3; ++i)
  2718. pxsim.svg.child(merge, "feMergeNode", { in: "glow" });
  2719. // outline
  2720. pxsim.svg.path(this.g, "sim-board", "M498,31.9C498,14.3,483.7,0,466.1,0H31.9C14.3,0,0,14.3,0,31.9v342.2C0,391.7,14.3,406,31.9,406h434.2c17.6,0,31.9-14.3,31.9-31.9V31.9z M14.3,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.7,2.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C19.2,204.6,17,206.7,14.3,206.7z M486.2,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.72.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C491,204.6,488.8,206.7,486.2,206.7z");
  2721. // script background
  2722. this.display = pxsim.svg.path(this.g, "sim-display", "M333.8,310.3H165.9c-8.3,0-15-6.7-15-15V127.5c0-8.3,6.7-15,15-15h167.8c8.3,0,15,6.7,15,15v167.8C348.8,303.6,342.1,310.3,333.8,310.3z");
  2723. this.logos = [];
  2724. this.logos.push(pxsim.svg.child(this.g, "polygon", { class: "sim-theme", points: "115,56.7 173.1,0 115,0" }));
  2725. this.logos.push(pxsim.svg.path(this.g, "sim-theme", "M114.2,0H25.9C12.1,2.1,0,13.3,0,27.7v83.9L114.2,0z"));
  2726. this.logos.push(pxsim.svg.child(this.g, "polygon", { class: "sim-theme", points: "173,27.9 202.5,0 173,0" }));
  2727. this.logos.push(pxsim.svg.child(this.g, "polygon", { class: "sim-theme", points: "54.1,242.4 54.1,274.1 22.4,274.1" }));
  2728. this.logos.push(pxsim.svg.child(this.g, "polygon", { class: "sim-theme", points: "446.2,164.6 446.2,132.8 477.9,132.8" }));
  2729. // leds
  2730. this.leds = [];
  2731. this.ledsOuter = [];
  2732. var left = 154, top = 113, ledoffw = 46, ledoffh = 44;
  2733. for (var i = 0; i < 5; ++i) {
  2734. var ledtop = i * ledoffh + top;
  2735. for (var j = 0; j < 5; ++j) {
  2736. var ledleft = j * ledoffw + left;
  2737. var k = i * 5 + j;
  2738. this.ledsOuter.push(pxsim.svg.child(this.g, "rect", { class: "sim-led-back", x: ledleft, y: ledtop, width: 10, height: 20, rx: 2, ry: 2 }));
  2739. var led_1 = pxsim.svg.child(this.g, "rect", { class: "sim-led", x: ledleft - 2, y: ledtop - 2, width: 14, height: 24, rx: 3, ry: 3, title: "(" + j + "," + i + ")" });
  2740. pxsim.svg.filter(led_1, "url(#ledglow)");
  2741. this.leds.push(led_1);
  2742. }
  2743. }
  2744. // head
  2745. this.head = pxsim.svg.child(this.g, "g", { class: "sim-head no-drag" });
  2746. pxsim.svg.child(this.head, "circle", { cx: 258, cy: 75, r: 100, fill: "transparent" });
  2747. this.logos.push(pxsim.svg.path(this.head, "sim-theme sim-theme-glow", "M269.9,50.2L269.9,50.2l-39.5,0v0c-14.1,0.1-24.6,10.7-24.6,24.8c0,13.9,10.4,24.4,24.3,24.7v0h39.6c14.2,0,24.8-10.6,24.8-24.7C294.5,61,284,50.3,269.9,50.2 M269.7,89.2L269.7,89.2l-39.3,0c-7.7-0.1-14-6.4-14-14.2c0-7.8,6.4-14.2,14.2-14.2h39.1c7.8,0,14.2,6.4,14.2,14.2C283.9,82.9,277.5,89.2,269.7,89.2"));
  2748. this.logos.push(pxsim.svg.path(this.head, "sim-theme sim-theme-glow", "M230.6,69.7c-2.9,0-5.3,2.4-5.3,5.3c0,2.9,2.4,5.3,5.3,5.3c2.9,0,5.3-2.4,5.3-5.3C235.9,72.1,233.5,69.7,230.6,69.7"));
  2749. this.logos.push(pxsim.svg.path(this.head, "sim-theme sim-theme-glow", "M269.7,80.3c2.9,0,5.3-2.4,5.3-5.3c0-2.9-2.4-5.3-5.3-5.3c-2.9,0-5.3,2.4-5.3,5.3C264.4,77.9,266.8,80.3,269.7,80.3"));
  2750. this.headText = pxsim.svg.child(this.g, "text", { x: 310, y: 100, class: "sim-text" });
  2751. // https://www.microbit.co.uk/device/pins
  2752. // P0, P1, P2
  2753. this.pins = [
  2754. "M16.5,341.2c0,0.4-0.1,0.9-0.1,1.3v60.7c4.1,1.7,8.6,2.7,12.9,2.7h34.4v-64.7h0.3c0,0,0-0.1,0-0.1c0-13-10.6-23.6-23.7-23.6C27.2,317.6,16.5,328.1,16.5,341.2z M21.2,341.6c0-10.7,8.7-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3c0,10.7-8.6,19.3-19.3,19.3C29.9,360.9,21.2,352.2,21.2,341.6z",
  2755. "M139.1,317.3c-12.8,0-22.1,10.3-23.1,23.1V406h46.2v-65.6C162.2,327.7,151.9,317.3,139.1,317.3zM139.3,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C158.6,351.5,150,360.1,139.3,360.1z",
  2756. "M249,317.3c-12.8,0-22.1,10.3-23.1,23.1V406h46.2v-65.6C272.1,327.7,261.8,317.3,249,317.3z M249.4,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C268.7,351.5,260.1,360.1,249.4,360.1z"
  2757. ].map(function (p, pi) { return pxsim.svg.path(_this.g, "sim-pin sim-pin-touch", p); });
  2758. // P3
  2759. this.pins.push(pxsim.svg.path(this.g, "sim-pin", "M0,357.7v19.2c0,10.8,6.2,20.2,14.4,25.2v-44.4H0z"));
  2760. pins4onXs.forEach(function (x) {
  2761. _this.pins.push(pxsim.svg.child(_this.g, "rect", { x: x, y: 356.7, width: 10, height: 50, class: "sim-pin" }));
  2762. });
  2763. this.pins.push(pxsim.svg.path(this.g, "sim-pin", "M483.6,402c8.2-5,14.4-14.4,14.4-25.1v-19.2h-14.4V402z"));
  2764. this.pins.push(pxsim.svg.path(this.g, "sim-pin", "M359.9,317.3c-12.8,0-22.1,10.3-23.1,23.1V406H383v-65.6C383,327.7,372.7,317.3,359.9,317.3z M360,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C379.3,351.5,370.7,360.1,360,360.1z"));
  2765. this.pins.push(pxsim.svg.path(this.g, "sim-pin", "M458,317.6c-13,0-23.6,10.6-23.6,23.6c0,0,0,0.1,0,0.1h0V406H469c4.3,0,8.4-1,12.6-2.7v-60.7c0-0.4,0-0.9,0-1.3C481.6,328.1,471,317.6,458,317.6z M457.8,360.9c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C477.1,352.2,468.4,360.9,457.8,360.9z"));
  2766. this.pins.forEach(function (p, i) { return pxsim.svg.hydrate(p, { title: pinTitles[i] }); });
  2767. this.pinGradients = this.pins.map(function (pin, i) {
  2768. var gid = "gradient-pin-" + i;
  2769. var lg = pxsim.svg.linearGradient(_this.defs, gid);
  2770. pin.setAttribute("fill", "url(#" + gid + ")");
  2771. return lg;
  2772. });
  2773. this.pinTexts = [67, 165, 275].map(function (x) { return pxsim.svg.child(_this.g, "text", { class: "sim-text-pin", x: x, y: 345 }); });
  2774. this.buttonsOuter = [];
  2775. this.buttons = [];
  2776. var outerBtn = function (left, top, label) {
  2777. var btnr = 4;
  2778. var btnw = 56.2;
  2779. var btnn = 6;
  2780. var btnnm = 10;
  2781. var btng = pxsim.svg.child(_this.g, "g", { class: "sim-button-group" });
  2782. pxsim.accessibility.makeFocusable(btng);
  2783. pxsim.accessibility.setAria(btng, "button", label);
  2784. _this.buttonsOuter.push(btng);
  2785. pxsim.svg.child(btng, "rect", { class: "sim-button-outer", x: left, y: top, rx: btnr, ry: btnr, width: btnw, height: btnw });
  2786. pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnnm, cy: top + btnnm, r: btnn });
  2787. pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnnm, cy: top + btnw - btnnm, r: btnn });
  2788. pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnw - btnnm, cy: top + btnw - btnnm, r: btnn });
  2789. pxsim.svg.child(btng, "circle", { class: "sim-button-nut", cx: left + btnw - btnnm, cy: top + btnnm, r: btnn });
  2790. };
  2791. outerBtn(25.9, 176.4, "A");
  2792. this.buttons.push(pxsim.svg.path(this.g, "sim-button", "M69.7,203.5c0,8.7-7,15.7-15.7,15.7s-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7S69.7,194.9,69.7,203.5"));
  2793. outerBtn(418.1, 176.4, "B");
  2794. this.buttons.push(pxsim.svg.path(this.g, "sim-button", "M461.9,203.5c0,8.7-7,15.7-15.7,15.7c-8.7,0-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7C454.9,187.8,461.9,194.9,461.9,203.5"));
  2795. outerBtn(417, 250, "A+B");
  2796. this.buttons.push(pxsim.svg.child(this.g, "circle", { class: "sim-button", cx: 446, cy: 278, r: 16.5 }));
  2797. this.buttonsOuter[2].style.visibility = "hidden";
  2798. this.buttons[2].style.visibility = "hidden";
  2799. pxsim.svg.path(this.g, "sim-label", "M35.7,376.4c0-2.8,2.1-5.1,5.5-5.1c3.3,0,5.5,2.4,5.5,5.1v4.7c0,2.8-2.2,5.1-5.5,5.1c-3.3,0-5.5-2.4-5.5-5.1V376.4zM43.3,376.4c0-1.3-0.8-2.3-2.2-2.3c-1.3,0-2.1,1.1-2.1,2.3v4.7c0,1.2,0.8,2.3,2.1,2.3c1.3,0,2.2-1.1,2.2-2.3V376.4z");
  2800. pxsim.svg.path(this.g, "sim-label", "M136.2,374.1c2.8,0,3.4-0.8,3.4-2.5h2.9v14.3h-3.4v-9.5h-3V374.1z");
  2801. pxsim.svg.path(this.g, "sim-label", "M248.6,378.5c1.7-1,3-1.7,3-3.1c0-1.1-0.7-1.6-1.6-1.6c-1,0-1.8,0.6-1.8,2.1h-3.3c0-2.6,1.8-4.6,5.1-4.6c2.6,0,4.9,1.3,4.9,4.3c0,2.4-2.3,3.9-3.8,4.7c-2,1.3-2.5,1.8-2.5,2.9h6.1v2.7h-10C244.8,381.2,246.4,379.9,248.6,378.5z");
  2802. pxsim.svg.path(this.g, "sim-button-label", "M48.1,270.9l-0.6-1.7h-5.1l-0.6,1.7h-3.5l5.1-14.3h3.1l5.2,14.3H48.1z M45,260.7l-1.8,5.9h3.5L45,260.7z");
  2803. pxsim.svg.path(this.g, "sim-button-label", "M449.1,135.8h5.9c3.9,0,4.7,2.4,4.7,3.9c0,1.8-1.4,2.9-2.5,3.2c0.9,0,2.6,1.1,2.6,3.3c0,1.5-0.8,4-4.7,4h-6V135.8zM454.4,141.7c1.6,0,2-1,2-1.7c0-0.6-0.3-1.7-2-1.7h-2v3.4H454.4z M452.4,144.1v3.5h2.1c1.6,0,2-1,2-1.8c0-0.7-0.4-1.8-2-1.8H452.4z");
  2804. pxsim.svg.path(this.g, "sim-label", "M352.1,381.1c0,1.6,0.9,2.5,2.2,2.5c1.2,0,1.9-0.9,1.9-1.9c0-1.2-0.6-2-2.1-2h-1.3v-2.6h1.3c1.5,0,1.9-0.7,1.9-1.8c0-1.1-0.7-1.6-1.6-1.6c-1.4,0-1.8,0.8-1.8,2.1h-3.3c0-2.4,1.5-4.6,5.1-4.6c2.6,0,5,1.3,5,4c0,1.6-1,2.8-2.1,3.2c1.3,0.5,2.3,1.6,2.3,3.5c0,2.7-2.4,4.3-5.2,4.3c-3.5,0-5.5-2.1-5.5-5.1H352.1z");
  2805. pxsim.svg.path(this.g, "sim-label", "M368.5,385.9h-3.1l-5.1-14.3h3.5l3.1,10.1l3.1-10.1h3.6L368.5,385.9z");
  2806. pxsim.svg.path(this.g, "sim-label", "M444.4,378.3h7.4v2.5h-1.5c-0.6,3.3-3,5.5-7.1,5.5c-4.8,0-7.5-3.5-7.5-7.5c0-3.9,2.8-7.5,7.5-7.5c3.8,0,6.4,2.3,6.6,5h-3.5c-0.2-1.1-1.4-2.2-3.1-2.2c-2.7,0-4.1,2.3-4.1,4.7c0,2.5,1.4,4.7,4.4,4.7c2,0,3.2-1.2,3.4-2.7h-2.5V378.3z");
  2807. pxsim.svg.path(this.g, "sim-label", "M461.4,380.9v-9.3h3.3v14.3h-3.5l-5.2-9.2v9.2h-3.3v-14.3h3.5L461.4,380.9z");
  2808. pxsim.svg.path(this.g, "sim-label", "M472.7,371.6c4.8,0,7.5,3.5,7.5,7.2s-2.7,7.2-7.5,7.2h-5.3v-14.3H472.7z M470.8,374.4v8.6h1.8c2.7,0,4.2-2.1,4.2-4.3s-1.6-4.3-4.2-4.3H470.8z");
  2809. };
  2810. MicrobitBoardSvg.prototype.attachEvents = function () {
  2811. var _this = this;
  2812. pxsim.Runtime.messagePosted = function (msg) {
  2813. switch (msg.type || "") {
  2814. case "serial":
  2815. _this.flashSystemLed();
  2816. break;
  2817. case "radiopacket":
  2818. _this.flashAntenna();
  2819. break;
  2820. case "eventbus":
  2821. if (msg.id == 2000 /* MES_BROADCAST_GENERAL_ID */)
  2822. _this.flashAntenna();
  2823. break;
  2824. }
  2825. };
  2826. var tiltDecayer = 0;
  2827. this.element.addEventListener(pxsim.pointerEvents.move, function (ev) {
  2828. var state = _this.board;
  2829. if (!state.accelerometerState.accelerometer.isActive)
  2830. return;
  2831. if (tiltDecayer) {
  2832. clearInterval(tiltDecayer);
  2833. tiltDecayer = 0;
  2834. }
  2835. var bbox = _this.element.getBoundingClientRect();
  2836. var ax = (ev.clientX - bbox.width / 2) / (bbox.width / 3);
  2837. var ay = (ev.clientY - bbox.height / 2) / (bbox.height / 3);
  2838. var x = -Math.max(-1023, Math.min(1023, Math.floor(ax * 1023)));
  2839. var y = -Math.max(-1023, Math.min(1023, Math.floor(ay * 1023)));
  2840. var z2 = 1023 * 1023 - x * x - y * y;
  2841. var z = Math.floor((z2 > 0 ? -1 : 1) * Math.sqrt(Math.abs(z2)));
  2842. state.accelerometerState.accelerometer.update(x, y, z);
  2843. _this.updateTilt();
  2844. }, false);
  2845. this.element.addEventListener(pxsim.pointerEvents.leave, function (ev) {
  2846. var state = _this.board;
  2847. if (!state.accelerometerState.accelerometer.isActive)
  2848. return;
  2849. if (!tiltDecayer) {
  2850. tiltDecayer = setInterval(function () {
  2851. var accx = state.accelerometerState.accelerometer.getX(pxsim.MicroBitCoordinateSystem.RAW);
  2852. accx = Math.floor(Math.abs(accx) * 0.85) * (accx > 0 ? 1 : -1);
  2853. var accy = state.accelerometerState.accelerometer.getY(pxsim.MicroBitCoordinateSystem.RAW);
  2854. accy = Math.floor(Math.abs(accy) * 0.85) * (accy > 0 ? 1 : -1);
  2855. var accz = -Math.sqrt(Math.max(0, 1023 * 1023 - accx * accx - accy * accy));
  2856. if (Math.abs(accx) <= 24 && Math.abs(accy) <= 24) {
  2857. clearInterval(tiltDecayer);
  2858. tiltDecayer = 0;
  2859. accx = 0;
  2860. accy = 0;
  2861. accz = -1023;
  2862. }
  2863. state.accelerometerState.accelerometer.update(accx, accy, accz);
  2864. _this.updateTilt();
  2865. }, 50);
  2866. }
  2867. }, false);
  2868. this.pins.forEach(function (pin, index) {
  2869. if (!_this.board.edgeConnectorState.pins[index])
  2870. return;
  2871. var pt = _this.element.createSVGPoint();
  2872. pxsim.svg.buttonEvents(pin,
  2873. // move
  2874. function (ev) {
  2875. var state = _this.board;
  2876. var pin = state.edgeConnectorState.pins[index];
  2877. var svgpin = _this.pins[index];
  2878. if (pin.mode & pxsim.PinFlags.Input) {
  2879. var cursor = pxsim.svg.cursorPoint(pt, _this.element, ev);
  2880. var v = (400 - cursor.y) / 40 * 1023;
  2881. pin.value = Math.max(0, Math.min(1023, Math.floor(v)));
  2882. }
  2883. _this.updatePin(pin, index);
  2884. },
  2885. // start
  2886. function (ev) {
  2887. var state = _this.board;
  2888. var pin = state.edgeConnectorState.pins[index];
  2889. var svgpin = _this.pins[index];
  2890. pxsim.svg.addClass(svgpin, "touched");
  2891. if (pin.mode & pxsim.PinFlags.Input) {
  2892. var cursor = pxsim.svg.cursorPoint(pt, _this.element, ev);
  2893. var v = (400 - cursor.y) / 40 * 1023;
  2894. pin.value = Math.max(0, Math.min(1023, Math.floor(v)));
  2895. }
  2896. _this.updatePin(pin, index);
  2897. },
  2898. // stop
  2899. function (ev) {
  2900. var state = _this.board;
  2901. var pin = state.edgeConnectorState.pins[index];
  2902. var svgpin = _this.pins[index];
  2903. pxsim.svg.removeClass(svgpin, "touched");
  2904. _this.updatePin(pin, index);
  2905. return false;
  2906. },
  2907. // keydown
  2908. function (ev) {
  2909. var charCode = (typeof ev.which == "number") ? ev.which : ev.keyCode;
  2910. var state = _this.board;
  2911. var pin = state.edgeConnectorState.pins[index];
  2912. if (charCode === 40 || charCode === 37) {
  2913. pin.value -= 10;
  2914. if (pin.value < 0) {
  2915. pin.value = 1023;
  2916. }
  2917. _this.updatePin(pin, index);
  2918. }
  2919. else if (charCode === 38 || charCode === 39) {
  2920. pin.value += 10;
  2921. if (pin.value > 1023) {
  2922. pin.value = 0;
  2923. }
  2924. _this.updatePin(pin, index);
  2925. }
  2926. });
  2927. });
  2928. this.pins.slice(0, 3).forEach(function (btn, index) {
  2929. pxsim.pointerEvents.down.forEach(function (evid) { return btn.addEventListener(evid, function (ev) {
  2930. var state = _this.board;
  2931. state.edgeConnectorState.pins[index].touched = true;
  2932. _this.updatePin(state.edgeConnectorState.pins[index], index);
  2933. _this.board.bus.queue(state.edgeConnectorState.pins[index].id, 1 /* MICROBIT_BUTTON_EVT_DOWN */);
  2934. }); });
  2935. btn.addEventListener(pxsim.pointerEvents.leave, function (ev) {
  2936. var state = _this.board;
  2937. state.edgeConnectorState.pins[index].touched = false;
  2938. _this.updatePin(state.edgeConnectorState.pins[index], index);
  2939. });
  2940. btn.addEventListener(pxsim.pointerEvents.up, function (ev) {
  2941. var state = _this.board;
  2942. state.edgeConnectorState.pins[index].touched = false;
  2943. _this.updatePin(state.edgeConnectorState.pins[index], index);
  2944. _this.board.bus.queue(state.edgeConnectorState.pins[index].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
  2945. _this.board.bus.queue(state.edgeConnectorState.pins[index].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
  2946. });
  2947. pxsim.accessibility.enableKeyboardInteraction(btn, undefined, function () {
  2948. var state = _this.board;
  2949. _this.board.bus.queue(state.edgeConnectorState.pins[index].id, 1 /* MICROBIT_BUTTON_EVT_DOWN */);
  2950. _this.board.bus.queue(state.edgeConnectorState.pins[index].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
  2951. _this.board.bus.queue(state.edgeConnectorState.pins[index].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
  2952. });
  2953. });
  2954. var bpState = this.board.buttonPairState;
  2955. var stateButtons = [bpState.aBtn, bpState.bBtn, bpState.abBtn];
  2956. this.buttonsOuter.slice(0, 2).forEach(function (btn, index) {
  2957. pxsim.pointerEvents.down.forEach(function (evid) { return btn.addEventListener(evid, function (ev) {
  2958. var state = _this.board;
  2959. stateButtons[index].pressed = true;
  2960. pxsim.svg.fill(_this.buttons[index], _this.props.theme.buttonDown);
  2961. _this.board.bus.queue(stateButtons[index].id, 1 /* MICROBIT_BUTTON_EVT_DOWN */);
  2962. }); });
  2963. btn.addEventListener(pxsim.pointerEvents.leave, function (ev) {
  2964. var state = _this.board;
  2965. stateButtons[index].pressed = false;
  2966. pxsim.svg.fill(_this.buttons[index], _this.props.theme.buttonUp);
  2967. });
  2968. btn.addEventListener(pxsim.pointerEvents.up, function (ev) {
  2969. var state = _this.board;
  2970. stateButtons[index].pressed = false;
  2971. pxsim.svg.fill(_this.buttons[index], _this.props.theme.buttonUp);
  2972. _this.board.bus.queue(stateButtons[index].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
  2973. _this.board.bus.queue(stateButtons[index].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
  2974. });
  2975. pxsim.accessibility.enableKeyboardInteraction(btn, undefined, function () {
  2976. _this.board.bus.queue(stateButtons[index].id, 1 /* MICROBIT_BUTTON_EVT_DOWN */);
  2977. _this.board.bus.queue(stateButtons[index].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
  2978. _this.board.bus.queue(stateButtons[index].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
  2979. });
  2980. });
  2981. pxsim.pointerEvents.down.forEach(function (evid) { return _this.buttonsOuter[2].addEventListener(evid, function (ev) {
  2982. var state = _this.board;
  2983. stateButtons[0].pressed = true;
  2984. stateButtons[1].pressed = true;
  2985. stateButtons[2].pressed = true;
  2986. pxsim.svg.fill(_this.buttons[0], _this.props.theme.buttonDown);
  2987. pxsim.svg.fill(_this.buttons[1], _this.props.theme.buttonDown);
  2988. pxsim.svg.fill(_this.buttons[2], _this.props.theme.buttonDown);
  2989. _this.board.bus.queue(stateButtons[2].id, 1 /* MICROBIT_BUTTON_EVT_DOWN */);
  2990. }); });
  2991. this.buttonsOuter[2].addEventListener(pxsim.pointerEvents.leave, function (ev) {
  2992. var state = _this.board;
  2993. stateButtons[0].pressed = false;
  2994. stateButtons[1].pressed = false;
  2995. stateButtons[2].pressed = false;
  2996. pxsim.svg.fill(_this.buttons[0], _this.props.theme.buttonUp);
  2997. pxsim.svg.fill(_this.buttons[1], _this.props.theme.buttonUp);
  2998. pxsim.svg.fill(_this.buttons[2], _this.props.theme.virtualButtonUp);
  2999. });
  3000. this.buttonsOuter[2].addEventListener(pxsim.pointerEvents.up, function (ev) {
  3001. var state = _this.board;
  3002. stateButtons[0].pressed = false;
  3003. stateButtons[1].pressed = false;
  3004. stateButtons[2].pressed = false;
  3005. pxsim.svg.fill(_this.buttons[0], _this.props.theme.buttonUp);
  3006. pxsim.svg.fill(_this.buttons[1], _this.props.theme.buttonUp);
  3007. pxsim.svg.fill(_this.buttons[2], _this.props.theme.virtualButtonUp);
  3008. _this.board.bus.queue(stateButtons[2].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
  3009. _this.board.bus.queue(stateButtons[2].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
  3010. });
  3011. pxsim.accessibility.enableKeyboardInteraction(this.buttonsOuter[2], undefined, function () {
  3012. _this.board.bus.queue(stateButtons[2].id, 1 /* MICROBIT_BUTTON_EVT_DOWN */);
  3013. _this.board.bus.queue(stateButtons[2].id, 2 /* MICROBIT_BUTTON_EVT_UP */);
  3014. _this.board.bus.queue(stateButtons[2].id, 3 /* MICROBIT_BUTTON_EVT_CLICK */);
  3015. });
  3016. };
  3017. return MicrobitBoardSvg;
  3018. }());
  3019. visuals.MicrobitBoardSvg = MicrobitBoardSvg;
  3020. })(visuals = pxsim.visuals || (pxsim.visuals = {}));
  3021. })(pxsim || (pxsim = {}));
  3022. /// <reference path="../../node_modules/pxt-core/built/pxtsim.d.ts"/>
  3023. /// <reference path="../../libs/core/dal.d.ts"/>
  3024. /// <reference path="../../libs/core/enums.d.ts"/>
  3025. var pxsim;
  3026. (function (pxsim) {
  3027. var visuals;
  3028. (function (visuals) {
  3029. var PIXEL_SPACING = visuals.PIN_DIST * 3;
  3030. var PIXEL_RADIUS = visuals.PIN_DIST;
  3031. var CANVAS_WIDTH = 1.2 * visuals.PIN_DIST;
  3032. var CANVAS_HEIGHT = 12 * visuals.PIN_DIST;
  3033. var CANVAS_VIEW_WIDTH = CANVAS_WIDTH;
  3034. var CANVAS_VIEW_HEIGHT = CANVAS_HEIGHT;
  3035. var CANVAS_VIEW_PADDING = visuals.PIN_DIST * 4;
  3036. var CANVAS_LEFT = 1.4 * visuals.PIN_DIST;
  3037. var CANVAS_TOP = visuals.PIN_DIST;
  3038. // For the instructions parts list
  3039. function mkNeoPixelPart(xy) {
  3040. if (xy === void 0) { xy = [0, 0]; }
  3041. var NP_PART_XOFF = -13.5;
  3042. var NP_PART_YOFF = -11;
  3043. var NP_PART_WIDTH = 87.5;
  3044. var NP_PART_HEIGHT = 190;
  3045. 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>";
  3046. var x = xy[0], y = xy[1];
  3047. var l = x + NP_PART_XOFF;
  3048. var t = y + NP_PART_YOFF;
  3049. var w = NP_PART_WIDTH;
  3050. var h = NP_PART_HEIGHT;
  3051. var img = pxsim.svg.elt("image");
  3052. pxsim.svg.hydrate(img, {
  3053. class: "sim-neopixel-strip", x: l, y: t, width: w, height: h,
  3054. href: pxsim.svg.toDataUri(NEOPIXEL_PART_IMG)
  3055. });
  3056. return { el: img, x: l, y: t, w: w, h: h };
  3057. }
  3058. visuals.mkNeoPixelPart = mkNeoPixelPart;
  3059. var NeoPixel = /** @class */ (function () {
  3060. function NeoPixel(xy) {
  3061. if (xy === void 0) { xy = [0, 0]; }
  3062. var el = pxsim.svg.elt("rect");
  3063. var r = PIXEL_RADIUS;
  3064. var cx = xy[0], cy = xy[1];
  3065. var y = cy - r;
  3066. pxsim.svg.hydrate(el, { x: "-50%", y: y, width: "100%", height: r * 2, class: "sim-neopixel" });
  3067. this.el = el;
  3068. this.cy = cy;
  3069. }
  3070. NeoPixel.prototype.setRgb = function (rgb) {
  3071. var hsl = visuals.rgbToHsl(rgb);
  3072. var h = hsl[0], s = hsl[1], l = hsl[2];
  3073. // at least 70% luminosity
  3074. l = Math.max(l, 60);
  3075. var fill = "hsl(" + h + ", " + s + "%, " + l + "%)";
  3076. this.el.setAttribute("fill", fill);
  3077. };
  3078. return NeoPixel;
  3079. }());
  3080. visuals.NeoPixel = NeoPixel;
  3081. var NeoPixelCanvas = /** @class */ (function () {
  3082. function NeoPixelCanvas(pin) {
  3083. this.pixels = [];
  3084. this.pin = pin;
  3085. var el = pxsim.svg.elt("svg");
  3086. pxsim.svg.hydrate(el, {
  3087. "class": "sim-neopixel-canvas",
  3088. "x": "0px",
  3089. "y": "0px",
  3090. "width": CANVAS_WIDTH + "px",
  3091. "height": CANVAS_HEIGHT + "px",
  3092. });
  3093. this.canvas = el;
  3094. this.background = pxsim.svg.child(el, "rect", { class: "sim-neopixel-background hidden" });
  3095. this.updateViewBox(-CANVAS_VIEW_WIDTH / 2, 0, CANVAS_VIEW_WIDTH, CANVAS_VIEW_HEIGHT);
  3096. }
  3097. NeoPixelCanvas.prototype.updateViewBox = function (x, y, w, h) {
  3098. this.viewBox = [x, y, w, h];
  3099. pxsim.svg.hydrate(this.canvas, { "viewBox": x + " " + y + " " + w + " " + h });
  3100. pxsim.svg.hydrate(this.background, { "x": x, "y": y, "width": w, "height": h });
  3101. };
  3102. NeoPixelCanvas.prototype.update = function (colors) {
  3103. if (!colors || colors.length <= 0)
  3104. return;
  3105. for (var i = 0; i < colors.length; i++) {
  3106. var pixel = this.pixels[i];
  3107. if (!pixel) {
  3108. var cxy = [0, CANVAS_VIEW_PADDING + i * PIXEL_SPACING];
  3109. pixel = this.pixels[i] = new NeoPixel(cxy);
  3110. pxsim.svg.hydrate(pixel.el, { title: "offset: " + i });
  3111. this.canvas.appendChild(pixel.el);
  3112. }
  3113. var color = colors[i];
  3114. pixel.setRgb(color);
  3115. }
  3116. //show the canvas if it's hidden
  3117. pxsim.svg.removeClass(this.background, "hidden");
  3118. //resize if necessary
  3119. var _a = [this.pixels[0], this.pixels[this.pixels.length - 1]], first = _a[0], last = _a[1];
  3120. var yDiff = last.cy - first.cy;
  3121. var newH = yDiff + CANVAS_VIEW_PADDING * 2;
  3122. var _b = this.viewBox, oldX = _b[0], oldY = _b[1], oldW = _b[2], oldH = _b[3];
  3123. if (oldH < newH) {
  3124. var scalar = newH / oldH;
  3125. var newW = oldW * scalar;
  3126. this.updateViewBox(-newW / 2, oldY, newW, newH);
  3127. }
  3128. };
  3129. NeoPixelCanvas.prototype.setLoc = function (xy) {
  3130. var x = xy[0], y = xy[1];
  3131. pxsim.svg.hydrate(this.canvas, { x: x, y: y });
  3132. };
  3133. return NeoPixelCanvas;
  3134. }());
  3135. visuals.NeoPixelCanvas = NeoPixelCanvas;
  3136. ;
  3137. function digitalPinToPinNumber(gpioPin) {
  3138. var MICROBIT_ID_IO_P0 = 7; //TODO: don't hardcode this, import enums.d.ts
  3139. if (gpioPin == "*") {
  3140. return MICROBIT_ID_IO_P0;
  3141. }
  3142. var pinSplit = gpioPin.split("DigitalPin.P");
  3143. pxsim.U.assert(pinSplit.length === 2, "Unknown format for pin (for NeoPixel): " + gpioPin);
  3144. var pinNumStr = pinSplit[1];
  3145. var pinNum = Number(pinNumStr) + MICROBIT_ID_IO_P0;
  3146. return pinNum;
  3147. }
  3148. function parseNeoPixelMode(modeStr) {
  3149. var modeMap = {
  3150. "NeoPixelMode.RGB": pxsim.NeoPixelMode.RGB,
  3151. "NeoPixelMode.RGBW": pxsim.NeoPixelMode.RGBW
  3152. };
  3153. return modeMap[modeStr] || pxsim.NeoPixelMode.RGB;
  3154. }
  3155. var NeoPixelView = /** @class */ (function () {
  3156. function NeoPixelView() {
  3157. this.style = "\n .sim-neopixel-canvas {\n }\n .sim-neopixel-canvas-parent:hover {\n transform-origin: center;\n transform: scale(4) translateY(-60px);\n -moz-transform: scale(4) translateY(-220px);\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 ";
  3158. }
  3159. NeoPixelView.prototype.init = function (bus, state, svgEl, otherParams) {
  3160. pxsim.U.assert(!!otherParams["mode"], "NeoPixels assumes a RGB vs RGBW mode is passed to it");
  3161. pxsim.U.assert(!!otherParams["pin"], "NeoPixels assumes a pin is passed to it");
  3162. var modeStr = otherParams["mode"];
  3163. this.mode = parseNeoPixelMode(modeStr);
  3164. this.state = state;
  3165. this.stripGroup = pxsim.svg.elt("g");
  3166. this.element = this.stripGroup;
  3167. var pinStr = otherParams["pin"];
  3168. this.pin = digitalPinToPinNumber(pinStr);
  3169. this.lastLocation = [0, 0];
  3170. var part = mkNeoPixelPart();
  3171. this.part = part;
  3172. this.stripGroup.appendChild(part.el);
  3173. var canvas = new NeoPixelCanvas(this.pin);
  3174. this.canvas = canvas;
  3175. var canvasG = pxsim.svg.elt("g", { class: "sim-neopixel-canvas-parent" });
  3176. this.overElement = canvasG;
  3177. canvasG.appendChild(canvas.canvas);
  3178. this.updateStripLoc();
  3179. };
  3180. NeoPixelView.prototype.moveToCoord = function (xy) {
  3181. var x = xy[0], y = xy[1];
  3182. var loc = [x, y];
  3183. this.lastLocation = loc;
  3184. this.updateStripLoc();
  3185. };
  3186. NeoPixelView.prototype.updateStripLoc = function () {
  3187. var _a = this.lastLocation, x = _a[0], y = _a[1];
  3188. pxsim.U.assert(typeof x === "number" && typeof y === "number", "invalid x,y for NeoPixel strip");
  3189. this.canvas.setLoc([x + CANVAS_LEFT, y + CANVAS_TOP]);
  3190. pxsim.svg.hydrate(this.part.el, { transform: "translate(" + x + " " + y + ")" }); //TODO: update part's l,h, etc.
  3191. };
  3192. NeoPixelView.prototype.updateState = function () {
  3193. var colors = this.state.getColors(this.pin, this.mode);
  3194. this.canvas.update(colors);
  3195. };
  3196. NeoPixelView.prototype.updateTheme = function () { };
  3197. return NeoPixelView;
  3198. }());
  3199. visuals.NeoPixelView = NeoPixelView;
  3200. })(visuals = pxsim.visuals || (pxsim.visuals = {}));
  3201. })(pxsim || (pxsim = {}));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement