pxt-arcade 1.6.13 → 1.6.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/built/common-sim.d.ts +51 -2
- package/built/common-sim.js +296 -6
- package/built/sim.js +4 -6
- package/built/target-strings.json +2 -0
- package/built/target.js +1059 -162
- package/built/target.json +1059 -162
- package/built/targetlight.json +5 -5
- package/built/theme.json +9 -1
- package/docs/hero-banner.md +26 -0
- package/docs/hour-of-code-2021.html +470 -0
- package/docs/skillmap/educator-info/rockstar-map-info.md +63 -0
- package/docs/skillmap/rockstar/rockstar1.md +13 -13
- package/docs/skillmap/rockstar/rockstar2.md +20 -20
- package/docs/skillmap/rockstar/rockstar3.md +17 -17
- package/docs/skillmap/rockstar.md +12 -11
- package/docs/static/hero-gallery/hardware.png +0 -0
- package/docs/static/hero-gallery/how-to-code.png +0 -0
- package/docs/static/hero-gallery/skillmap.png +0 -0
- package/docs/static/hero-gallery/stream.png +0 -0
- package/docs/static/hour-of-code/2021/placeholder.png +0 -0
- package/docs/static/hour-of-code/2021/styles.css +746 -0
- package/docs/static/skillmap/backgrounds/rockstar-comp.png +0 -0
- package/docs/tutorials/makecode-jr-goal.md +2 -2
- package/package.json +3 -3
- package/pxtarget.json +9 -1
package/built/common-sim.d.ts
CHANGED
|
@@ -1075,8 +1075,8 @@ declare namespace pxsim.visuals {
|
|
|
1075
1075
|
}
|
|
1076
1076
|
}
|
|
1077
1077
|
declare namespace pxsim.settings {
|
|
1078
|
-
function _set(key: string, buf: RefBuffer):
|
|
1079
|
-
function _remove(key: string):
|
|
1078
|
+
function _set(key: string, buf: RefBuffer): -1 | 0;
|
|
1079
|
+
function _remove(key: string): -1 | 0;
|
|
1080
1080
|
function _exists(key: string): boolean;
|
|
1081
1081
|
function _get(key: string): RefBuffer;
|
|
1082
1082
|
function _userClean(): void;
|
|
@@ -1179,3 +1179,52 @@ declare namespace pxsim.TouchButtonMethods {
|
|
|
1179
1179
|
declare namespace pxsim.AnalogInOutPinMethods {
|
|
1180
1180
|
function touchButton(name: pins.AnalogInOutPin): TouchButton;
|
|
1181
1181
|
}
|
|
1182
|
+
declare namespace pxsim {
|
|
1183
|
+
interface WifiSocketBoard extends CommonBoard {
|
|
1184
|
+
wifiSocketState: WifiSocketState;
|
|
1185
|
+
}
|
|
1186
|
+
class WifiSocket {
|
|
1187
|
+
private fd;
|
|
1188
|
+
ws: WebSocket;
|
|
1189
|
+
_err: number;
|
|
1190
|
+
buffers: Uint8Array[];
|
|
1191
|
+
readers: (() => void)[];
|
|
1192
|
+
bytesAvail: number;
|
|
1193
|
+
reqInit: RequestInit;
|
|
1194
|
+
reqUrl: string;
|
|
1195
|
+
reqSent: boolean;
|
|
1196
|
+
constructor(fd: number);
|
|
1197
|
+
openReq(host: string, port: number): Promise<number>;
|
|
1198
|
+
_queue(data: string | Uint8Array | ArrayBuffer): void;
|
|
1199
|
+
openWS(url: string, proto: string[]): Promise<number>;
|
|
1200
|
+
waitRead(): Promise<void>;
|
|
1201
|
+
read(maxlen: number): number | RefBuffer;
|
|
1202
|
+
private handleFetch;
|
|
1203
|
+
write(buf: RefBuffer): Promise<number>;
|
|
1204
|
+
close(): void;
|
|
1205
|
+
}
|
|
1206
|
+
class WifiSocketState {
|
|
1207
|
+
sockets: WifiSocket[];
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
declare namespace pxsim._wifi {
|
|
1211
|
+
type int32 = number;
|
|
1212
|
+
export function _allowed(): boolean;
|
|
1213
|
+
export function socketAlloc(): int32;
|
|
1214
|
+
export function socketConnectTLS(fd: int32, host: string, port: int32): Promise<int32>;
|
|
1215
|
+
export function socketWrite(fd: int32, data: RefBuffer): Promise<int32>;
|
|
1216
|
+
export function socketRead(fd: int32, size: int32): Promise<number | RefBuffer>;
|
|
1217
|
+
export function socketBytesAvailable(fd: int32): int32;
|
|
1218
|
+
export function socketClose(fd: int32): int32;
|
|
1219
|
+
export function eventID(): int32;
|
|
1220
|
+
export function scanStart(): void;
|
|
1221
|
+
export function scanResults(): RefBuffer;
|
|
1222
|
+
export function connect(ssid: string, pass: string): int32;
|
|
1223
|
+
export function disconnect(): int32;
|
|
1224
|
+
export function isConnected(): boolean;
|
|
1225
|
+
export function _raiseEvent(id: number): void;
|
|
1226
|
+
export {};
|
|
1227
|
+
}
|
|
1228
|
+
declare namespace pxsim.crypto {
|
|
1229
|
+
function _sha256(bufs: RefCollection): Promise<RefBuffer>;
|
|
1230
|
+
}
|
package/built/common-sim.js
CHANGED
|
@@ -604,22 +604,20 @@ var pxsim;
|
|
|
604
604
|
}
|
|
605
605
|
control.profilingEnabled = profilingEnabled;
|
|
606
606
|
function __log(priority, str) {
|
|
607
|
-
let prefix = "";
|
|
608
607
|
switch (priority) {
|
|
609
608
|
case 0:
|
|
610
|
-
|
|
609
|
+
console.debug("d>" + str);
|
|
611
610
|
break;
|
|
612
611
|
case 1:
|
|
613
|
-
|
|
612
|
+
console.log("l>" + str);
|
|
614
613
|
break;
|
|
615
614
|
case 2:
|
|
616
|
-
|
|
615
|
+
console.warn("w>" + str);
|
|
617
616
|
break;
|
|
618
617
|
case 3:
|
|
619
|
-
|
|
618
|
+
console.error("e>" + str);
|
|
620
619
|
break;
|
|
621
620
|
}
|
|
622
|
-
console.log(prefix + str);
|
|
623
621
|
pxsim.runtime.board.writeSerial(str);
|
|
624
622
|
}
|
|
625
623
|
control.__log = __log;
|
|
@@ -4689,3 +4687,295 @@ var pxsim;
|
|
|
4689
4687
|
AnalogInOutPinMethods.touchButton = touchButton;
|
|
4690
4688
|
})(AnalogInOutPinMethods = pxsim.AnalogInOutPinMethods || (pxsim.AnalogInOutPinMethods = {}));
|
|
4691
4689
|
})(pxsim || (pxsim = {}));
|
|
4690
|
+
var pxsim;
|
|
4691
|
+
(function (pxsim) {
|
|
4692
|
+
class WifiSocket {
|
|
4693
|
+
constructor(fd) {
|
|
4694
|
+
this.fd = fd;
|
|
4695
|
+
this.buffers = [];
|
|
4696
|
+
this.readers = [];
|
|
4697
|
+
this.bytesAvail = 0;
|
|
4698
|
+
this.reqInit = {
|
|
4699
|
+
headers: {},
|
|
4700
|
+
credentials: "omit",
|
|
4701
|
+
mode: "cors",
|
|
4702
|
+
cache: "no-cache",
|
|
4703
|
+
redirect: "manual",
|
|
4704
|
+
referrer: "",
|
|
4705
|
+
};
|
|
4706
|
+
this.reqSent = false;
|
|
4707
|
+
}
|
|
4708
|
+
async openReq(host, port) {
|
|
4709
|
+
if (!/^[\w\-\.]+$/.test(host))
|
|
4710
|
+
throw new Error("bad host");
|
|
4711
|
+
this.reqUrl = "https://" + host + ":" + port + "/";
|
|
4712
|
+
return 0;
|
|
4713
|
+
}
|
|
4714
|
+
_queue(data) {
|
|
4715
|
+
let buf;
|
|
4716
|
+
if (data instanceof ArrayBuffer)
|
|
4717
|
+
buf = new Uint8Array(data);
|
|
4718
|
+
else if (data instanceof Uint8Array)
|
|
4719
|
+
buf = data;
|
|
4720
|
+
else
|
|
4721
|
+
buf = pxsim.U.stringToUint8Array(pxsim.U.toUTF8(data));
|
|
4722
|
+
this.buffers.push(buf);
|
|
4723
|
+
if (buf.length && this.bytesAvail == 0)
|
|
4724
|
+
pxsim._wifi._raiseEvent(1000 + this.fd);
|
|
4725
|
+
this.bytesAvail += buf.length;
|
|
4726
|
+
const rr = this.readers;
|
|
4727
|
+
this.readers = [];
|
|
4728
|
+
for (const r of rr)
|
|
4729
|
+
r();
|
|
4730
|
+
}
|
|
4731
|
+
openWS(url, proto) {
|
|
4732
|
+
this.ws = new WebSocket(url, proto);
|
|
4733
|
+
this.ws.binaryType = "arraybuffer";
|
|
4734
|
+
return new Promise((resolve) => {
|
|
4735
|
+
this.ws.onopen = () => {
|
|
4736
|
+
this.ws.onerror = err => {
|
|
4737
|
+
console.log("ws error", err);
|
|
4738
|
+
this._err = -2;
|
|
4739
|
+
};
|
|
4740
|
+
resolve(0);
|
|
4741
|
+
};
|
|
4742
|
+
this.ws.onclose = () => {
|
|
4743
|
+
console.log("ws close");
|
|
4744
|
+
this._err = -20;
|
|
4745
|
+
};
|
|
4746
|
+
this.ws.onmessage = ev => {
|
|
4747
|
+
this._queue(ev.data);
|
|
4748
|
+
};
|
|
4749
|
+
this.ws.onerror = () => resolve(-1);
|
|
4750
|
+
});
|
|
4751
|
+
}
|
|
4752
|
+
waitRead() {
|
|
4753
|
+
return new Promise(resolve => {
|
|
4754
|
+
this.readers.push(resolve);
|
|
4755
|
+
});
|
|
4756
|
+
}
|
|
4757
|
+
read(maxlen) {
|
|
4758
|
+
if (this._err)
|
|
4759
|
+
return this._err;
|
|
4760
|
+
let b = this.buffers[0];
|
|
4761
|
+
if (b) {
|
|
4762
|
+
if (b.length <= maxlen) {
|
|
4763
|
+
this.buffers.shift();
|
|
4764
|
+
}
|
|
4765
|
+
else {
|
|
4766
|
+
this.buffers[0] = b.slice(maxlen);
|
|
4767
|
+
b = b.slice(0, maxlen);
|
|
4768
|
+
}
|
|
4769
|
+
this.bytesAvail -= b.length;
|
|
4770
|
+
return new pxsim.RefBuffer(b);
|
|
4771
|
+
}
|
|
4772
|
+
return null;
|
|
4773
|
+
}
|
|
4774
|
+
async handleFetch() {
|
|
4775
|
+
// we ignore post for now
|
|
4776
|
+
this.reqSent = true;
|
|
4777
|
+
const resp = await fetch(this.reqUrl, this.reqInit);
|
|
4778
|
+
this._queue(`HTTP/1.1 ${resp.status} ${resp.statusText}\r\n`);
|
|
4779
|
+
resp.headers.forEach((v, k) => {
|
|
4780
|
+
if (k.toLowerCase() == "content-length")
|
|
4781
|
+
return;
|
|
4782
|
+
this._queue(`${k}: ${v}\r\n`);
|
|
4783
|
+
});
|
|
4784
|
+
const data = await resp.arrayBuffer();
|
|
4785
|
+
this._queue(`Content-Length: ${data.byteLength}\r\n`);
|
|
4786
|
+
this._queue(`\r\n`);
|
|
4787
|
+
this._queue(data);
|
|
4788
|
+
return 0;
|
|
4789
|
+
}
|
|
4790
|
+
async write(buf) {
|
|
4791
|
+
if (this._err)
|
|
4792
|
+
return this._err;
|
|
4793
|
+
if (this.ws)
|
|
4794
|
+
this.ws.send(buf.data);
|
|
4795
|
+
else {
|
|
4796
|
+
if (this.reqSent)
|
|
4797
|
+
return -2;
|
|
4798
|
+
let str = pxsim.U.fromUTF8(pxsim.U.uint8ArrayToString(buf.data));
|
|
4799
|
+
if (str == "\r\n") {
|
|
4800
|
+
const dummy = this.handleFetch();
|
|
4801
|
+
return 0;
|
|
4802
|
+
}
|
|
4803
|
+
str = str.replace(/\r?\n$/, "");
|
|
4804
|
+
if (!this.reqInit.method) {
|
|
4805
|
+
const m = /^\s*(\S+)\s+\/(\S+)/.exec(str);
|
|
4806
|
+
if (m) {
|
|
4807
|
+
this.reqInit.method = m[1];
|
|
4808
|
+
this.reqUrl += m[2];
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4811
|
+
else {
|
|
4812
|
+
const m = /^([^:]+):\s*(.*)/.exec(str);
|
|
4813
|
+
if (m) {
|
|
4814
|
+
this.reqInit.headers[m[1]] = m[2];
|
|
4815
|
+
}
|
|
4816
|
+
}
|
|
4817
|
+
}
|
|
4818
|
+
return 0;
|
|
4819
|
+
}
|
|
4820
|
+
close() {
|
|
4821
|
+
if (this.ws)
|
|
4822
|
+
this.ws.close();
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
pxsim.WifiSocket = WifiSocket;
|
|
4826
|
+
class WifiSocketState {
|
|
4827
|
+
constructor() {
|
|
4828
|
+
this.sockets = [null];
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
pxsim.WifiSocketState = WifiSocketState;
|
|
4832
|
+
})(pxsim || (pxsim = {}));
|
|
4833
|
+
(function (pxsim) {
|
|
4834
|
+
var _wifi;
|
|
4835
|
+
(function (_wifi) {
|
|
4836
|
+
const MAX_SOCKET = 16;
|
|
4837
|
+
const WIFI_ID = 1234;
|
|
4838
|
+
function _allowed() {
|
|
4839
|
+
var _a, _b, _c;
|
|
4840
|
+
const bid = (_c = (_b = (_a = pxsim.board()) === null || _a === void 0 ? void 0 : _a.runOptions) === null || _b === void 0 ? void 0 : _b.boardDefinition) === null || _c === void 0 ? void 0 : _c.id;
|
|
4841
|
+
return /esp32|-s2/.test(bid);
|
|
4842
|
+
}
|
|
4843
|
+
_wifi._allowed = _allowed;
|
|
4844
|
+
function getState() {
|
|
4845
|
+
const b = pxsim.board();
|
|
4846
|
+
if (!b.wifiSocketState) {
|
|
4847
|
+
if (!_allowed())
|
|
4848
|
+
throw new Error("_wifi not enabled");
|
|
4849
|
+
b.wifiSocketState = new pxsim.WifiSocketState();
|
|
4850
|
+
}
|
|
4851
|
+
return b.wifiSocketState;
|
|
4852
|
+
}
|
|
4853
|
+
function getSock(fd) {
|
|
4854
|
+
if (fd < 0 || fd >= MAX_SOCKET)
|
|
4855
|
+
return null;
|
|
4856
|
+
return getState().sockets[fd];
|
|
4857
|
+
}
|
|
4858
|
+
function socketAlloc() {
|
|
4859
|
+
const state = getState();
|
|
4860
|
+
for (let i = 1; i < state.sockets.length; ++i) {
|
|
4861
|
+
if (!state.sockets[i]) {
|
|
4862
|
+
state.sockets[i] = new pxsim.WifiSocket(i);
|
|
4863
|
+
return i;
|
|
4864
|
+
}
|
|
4865
|
+
}
|
|
4866
|
+
const idx = state.sockets.length;
|
|
4867
|
+
if (idx > MAX_SOCKET)
|
|
4868
|
+
return -1;
|
|
4869
|
+
state.sockets.push(new pxsim.WifiSocket(idx));
|
|
4870
|
+
return idx;
|
|
4871
|
+
}
|
|
4872
|
+
_wifi.socketAlloc = socketAlloc;
|
|
4873
|
+
function socketConnectTLS(fd, host, port) {
|
|
4874
|
+
const sock = getSock(fd);
|
|
4875
|
+
if (!sock)
|
|
4876
|
+
return Promise.resolve(-11);
|
|
4877
|
+
// TODO loosen this up in future
|
|
4878
|
+
if (port == 8883 && /\.azure-devices.net$/.test(host)) {
|
|
4879
|
+
return sock.openWS("wss://" + host + "/$iothub/websocket?iothub-no-client-cert=true", ["mqtt"]);
|
|
4880
|
+
}
|
|
4881
|
+
else if (port == 443 && host == "microsoft.github.io") {
|
|
4882
|
+
return sock.openReq(host, port);
|
|
4883
|
+
}
|
|
4884
|
+
else {
|
|
4885
|
+
console.log("invalid host: " + host);
|
|
4886
|
+
return Promise.resolve(-1);
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4889
|
+
_wifi.socketConnectTLS = socketConnectTLS;
|
|
4890
|
+
async function socketWrite(fd, data) {
|
|
4891
|
+
const sock = getSock(fd);
|
|
4892
|
+
if (!sock)
|
|
4893
|
+
return -11;
|
|
4894
|
+
return sock.write(data);
|
|
4895
|
+
}
|
|
4896
|
+
_wifi.socketWrite = socketWrite;
|
|
4897
|
+
async function socketRead(fd, size) {
|
|
4898
|
+
const sock = getSock(fd);
|
|
4899
|
+
if (!sock)
|
|
4900
|
+
return -11;
|
|
4901
|
+
for (;;) {
|
|
4902
|
+
const buf = sock.read(size);
|
|
4903
|
+
if (buf)
|
|
4904
|
+
return buf;
|
|
4905
|
+
await sock.waitRead();
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
_wifi.socketRead = socketRead;
|
|
4909
|
+
function socketBytesAvailable(fd) {
|
|
4910
|
+
const sock = getSock(fd);
|
|
4911
|
+
if (!sock)
|
|
4912
|
+
return -11;
|
|
4913
|
+
return sock.bytesAvail;
|
|
4914
|
+
}
|
|
4915
|
+
_wifi.socketBytesAvailable = socketBytesAvailable;
|
|
4916
|
+
function socketClose(fd) {
|
|
4917
|
+
const sock = getSock(fd);
|
|
4918
|
+
if (!sock)
|
|
4919
|
+
return -11;
|
|
4920
|
+
sock.close();
|
|
4921
|
+
return 0;
|
|
4922
|
+
}
|
|
4923
|
+
_wifi.socketClose = socketClose;
|
|
4924
|
+
function eventID() {
|
|
4925
|
+
return WIFI_ID;
|
|
4926
|
+
}
|
|
4927
|
+
_wifi.eventID = eventID;
|
|
4928
|
+
function scanStart() {
|
|
4929
|
+
_raiseEvent(1 /* ScanDone */);
|
|
4930
|
+
}
|
|
4931
|
+
_wifi.scanStart = scanStart;
|
|
4932
|
+
function scanResults() {
|
|
4933
|
+
const b = new Uint8Array(7);
|
|
4934
|
+
b[0] = -20; // rssi
|
|
4935
|
+
b[1] = 0; // authmode
|
|
4936
|
+
b.set(pxsim.U.stringToUint8Array("WiFi"), 2);
|
|
4937
|
+
return new pxsim.RefBuffer(b);
|
|
4938
|
+
}
|
|
4939
|
+
_wifi.scanResults = scanResults;
|
|
4940
|
+
function connect(ssid, pass) {
|
|
4941
|
+
_raiseEvent(2 /* GotIP */);
|
|
4942
|
+
return 0;
|
|
4943
|
+
}
|
|
4944
|
+
_wifi.connect = connect;
|
|
4945
|
+
function disconnect() {
|
|
4946
|
+
return 0;
|
|
4947
|
+
}
|
|
4948
|
+
_wifi.disconnect = disconnect;
|
|
4949
|
+
function isConnected() { return true; }
|
|
4950
|
+
_wifi.isConnected = isConnected;
|
|
4951
|
+
function _raiseEvent(id) {
|
|
4952
|
+
pxsim.control.raiseEvent(_wifi.eventID(), id, undefined);
|
|
4953
|
+
}
|
|
4954
|
+
_wifi._raiseEvent = _raiseEvent;
|
|
4955
|
+
})(_wifi = pxsim._wifi || (pxsim._wifi = {}));
|
|
4956
|
+
})(pxsim || (pxsim = {}));
|
|
4957
|
+
(function (pxsim) {
|
|
4958
|
+
var crypto;
|
|
4959
|
+
(function (crypto) {
|
|
4960
|
+
function _sha256(bufs) {
|
|
4961
|
+
var _a, _b;
|
|
4962
|
+
let len = 0;
|
|
4963
|
+
const buffers = bufs.toArray().filter(e => e instanceof pxsim.RefBuffer).map((b) => {
|
|
4964
|
+
len += b.data.length;
|
|
4965
|
+
return b.data;
|
|
4966
|
+
});
|
|
4967
|
+
const concat = new Uint8Array(len);
|
|
4968
|
+
len = 0;
|
|
4969
|
+
for (const b of buffers) {
|
|
4970
|
+
concat.set(b, len);
|
|
4971
|
+
len += b.length;
|
|
4972
|
+
}
|
|
4973
|
+
const r = (_b = (_a = window === null || window === void 0 ? void 0 : window.crypto) === null || _a === void 0 ? void 0 : _a.subtle) === null || _b === void 0 ? void 0 : _b.digest("SHA-256", concat);
|
|
4974
|
+
if (r)
|
|
4975
|
+
return r.then(buf => new pxsim.RefBuffer(new Uint8Array(buf)));
|
|
4976
|
+
else
|
|
4977
|
+
return Promise.resolve(undefined);
|
|
4978
|
+
}
|
|
4979
|
+
crypto._sha256 = _sha256;
|
|
4980
|
+
})(crypto = pxsim.crypto || (pxsim.crypto = {}));
|
|
4981
|
+
})(pxsim || (pxsim = {}));
|
package/built/sim.js
CHANGED
|
@@ -3360,22 +3360,20 @@ var pxsim;
|
|
|
3360
3360
|
}
|
|
3361
3361
|
control.profilingEnabled = profilingEnabled;
|
|
3362
3362
|
function __log(priority, str) {
|
|
3363
|
-
let prefix = "";
|
|
3364
3363
|
switch (priority) {
|
|
3365
3364
|
case 0:
|
|
3366
|
-
|
|
3365
|
+
console.debug("d>" + str);
|
|
3367
3366
|
break;
|
|
3368
3367
|
case 1:
|
|
3369
|
-
|
|
3368
|
+
console.log("l>" + str);
|
|
3370
3369
|
break;
|
|
3371
3370
|
case 2:
|
|
3372
|
-
|
|
3371
|
+
console.warn("w>" + str);
|
|
3373
3372
|
break;
|
|
3374
3373
|
case 3:
|
|
3375
|
-
|
|
3374
|
+
console.error("e>" + str);
|
|
3376
3375
|
break;
|
|
3377
3376
|
}
|
|
3378
|
-
console.log(prefix + str);
|
|
3379
3377
|
pxsim.runtime.board.writeSerial(str);
|
|
3380
3378
|
}
|
|
3381
3379
|
control.__log = __log;
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"NRF52833 board": "NRF52833 board",
|
|
44
44
|
"NRF52840 board": "NRF52840 board",
|
|
45
45
|
"Networking abstractions": "Networking abstractions",
|
|
46
|
+
"New? Start here!": "New? Start here!",
|
|
46
47
|
"Onboard light level sensor": "Onboard light level sensor",
|
|
47
48
|
"Palette manipulations": "Palette manipulations",
|
|
48
49
|
"Power and sleep management": "Power and sleep management",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"Settings storage in internal flash": "Settings storage in internal flash",
|
|
55
56
|
"Seven segment digit display": "Seven segment digit display",
|
|
56
57
|
"Skillmaps": "Skillmaps",
|
|
58
|
+
"Start Skillmap": "Start Skillmap",
|
|
57
59
|
"The accelerometer library": "The accelerometer library",
|
|
58
60
|
"The base library": "The base library",
|
|
59
61
|
"The core library for Codal-based targets": "The core library for Codal-based targets",
|