Skip to content

Commit 7695be0

Browse files
Merge pull request #336 from bbcmicrobit/next
New micro:bit support
2 parents f4edc69 + 65a8800 commit 7695be0

27 files changed

+32990
-15248
lines changed

editor.html

Lines changed: 7 additions & 14494 deletions
Large diffs are not rendered by default.

js/fs.js

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/**
2+
* Wrapper for microbit-fs and microbit-universal-hex to perform filesystem
3+
* operations into two hex files.
4+
* https://github.com/microbit-foundation/microbit-fs
5+
* https://github.com/microbit-foundation/microbit-universal-hex
6+
*/
7+
'use strict';
8+
9+
/**
10+
* @returns An object with the fs wrapper.
11+
*/
12+
var microbitFsWrapper = function() {
13+
var fsWrapper = {};
14+
15+
var fs1 = null;
16+
var fs2 = null;
17+
18+
var commonFsSize = 20 * 1024;
19+
20+
/**
21+
* Looks up the object keys from the MicropythonFsHex prototype and
22+
* creates functions with the same name in this object to run the same
23+
* method in both instances of MicropythonFsHex()
24+
*/
25+
function duplicateKeys() {
26+
// Only start the function duplication once both instances have been created
27+
Object.keys(Object.getPrototypeOf(fs1)).forEach(function(key) {
28+
// We will duplicate all functions to call both instances
29+
if (typeof fs1[key] === 'function') {
30+
fsWrapper[key] = function() {
31+
var return1 = fs1[key].apply(fs1, arguments);
32+
var return2 = fs2[key].apply(fs2, arguments);
33+
// FIXME: Keep this during general testing, probably remove on final release for speed
34+
if (JSON.stringify(return1) !== JSON.stringify(return2)) {
35+
console.error('Return from call to ' + key + ' differs:\n\t' + return1 + '\n\t'+ return2 );
36+
}
37+
return return1;
38+
}
39+
}
40+
});
41+
}
42+
43+
/**
44+
* Fetches both MicroPython hexes and sets up the file system with the
45+
* initial main.py
46+
*/
47+
fsWrapper.setupFilesystem = function() {
48+
var deferred1 = $.get('micropython/microbit-micropython-v1.hex', function(fileStr) {
49+
fs1 = new microbitFs.MicropythonFsHex(fileStr, {
50+
'maxFsSize': commonFsSize,
51+
});
52+
}).fail(function() {
53+
console.error('Could not load the MicroPython hex 1 file.');
54+
});
55+
var deferred2 = $.get('micropython/microbit-micropython-v2.hex', function(fileStr) {
56+
fs2 = new microbitFs.MicropythonFsHex(fileStr, {
57+
'maxFsSize': commonFsSize,
58+
});
59+
}).fail(function() {
60+
console.error('Could not load the MicroPython hex 2 file.');
61+
});
62+
63+
return $.when(deferred1, deferred2).done(function() {
64+
duplicateKeys();
65+
});
66+
};
67+
68+
/**
69+
* @returns {string} Universal Hex string.
70+
*/
71+
fsWrapper.getUniversalHex = function() {
72+
return microbitUh.createUniversalHex([
73+
{ 'hex': fs1.getIntelHex(), 'boardId': 0x9900 },
74+
{ 'hex': fs2.getIntelHex(), 'boardId': 0x9903 },
75+
]);
76+
};
77+
78+
/**
79+
* @param {string} boardId String with the Board ID for the generation.
80+
* @returns Uint8Array with the data for the given Board ID.
81+
*/
82+
fsWrapper.getBytesForBoardId = function(boardId) {
83+
if (boardId == '9900' || boardId == '9901') {
84+
return fs1.getIntelHexBytes();
85+
} else if (boardId == '9903' || boardId == '9904') {
86+
return fs2.getIntelHexBytes();
87+
} else {
88+
throw Error('Could not recognise the Board ID ' + boardId);
89+
}
90+
};
91+
92+
/**
93+
* @param {string} boardId String with the Board ID for the generation.
94+
* @returns ArrayBuffer with the Intel Hex data for the given Board ID.
95+
*/
96+
fsWrapper.getIntelHexForBoardId = function(boardId) {
97+
if (boardId == '9900' || boardId == '9901') {
98+
var hexStr = fs1.getIntelHex();
99+
} else if (boardId == '9903' || boardId == '9904') {
100+
var hexStr = fs2.getIntelHex()
101+
} else {
102+
throw Error('Could not recognise the Board ID ' + boardId);
103+
}
104+
// iHex is ASCII so we can do a 1-to-1 conversion from chars to bytes
105+
var hexBuffer = new Uint8Array(hexStr.length);
106+
for (var i=0, strLen=hexStr.length; i < strLen; i++) {
107+
hexBuffer[i] = hexStr.charCodeAt(i);
108+
}
109+
return hexBuffer.buffer;
110+
};
111+
112+
/**
113+
* Import the files from the provide hex string into the filesystem.
114+
* If the import is successful this deletes all the previous files.
115+
*
116+
* @param {string} hexStr Hex (Intel or Universal) string with files to
117+
* import.
118+
* @return {string[]} Array with the filenames of all files imported.
119+
*/
120+
fsWrapper.importFiles = function(hexStr) {
121+
var hex = '';
122+
if (microbitUh.isUniversalHex(hexStr)) {
123+
// For now only extract one of the file systems
124+
microbitUh.separateUniversalHex(hexStr).forEach(function(hexObj) {
125+
if (hexObj.boardId == 0x9900 || hexObj.boardId == 0x9901) {
126+
hex = hexObj.hex;
127+
}
128+
});
129+
if (!hex) {
130+
// TODO: Add this string to the language files
131+
throw new Error('Universal Hex does not contain data for the supported boards.');
132+
}
133+
} else {
134+
hex = hexStr;
135+
}
136+
137+
// TODO: Add this string to the language files
138+
var errorMsg = 'Not a Universal Hex\n';
139+
try {
140+
var filesNames1 = fs1.importFilesFromIntelHex(hex, {
141+
overwrite: true,
142+
formatFirst: true
143+
});
144+
var filesNames2 = fs2.importFilesFromIntelHex(hex, {
145+
overwrite: true,
146+
formatFirst: true
147+
});
148+
// FIXME: Keep this during general testing, probably remove on final release for speed
149+
if (JSON.stringify(filesNames1) !== JSON.stringify(filesNames2)) {
150+
console.error('Return from importFilesFromIntelHex() differs:' +
151+
'\n\t' + return1 + '\n\t'+ return2);
152+
}
153+
return filesNames1;
154+
} catch(e) {
155+
errorMsg += e.message + '\n';
156+
}
157+
158+
// Failed during fs file import, check if there is an appended script
159+
var code = '';
160+
try {
161+
code = microbitFs.getIntelHexAppendedScript(hexStr);
162+
// If no code is found throw a dummy error to trigger the catch below
163+
if (!code) throw new Error('No appended code found.');
164+
} catch(e) {
165+
// This was originally config.translate.alerts.no_script
166+
throw new Error(errorMsg + 'Hex file does not contain an appended Python script.');
167+
}
168+
fs1.ls().forEach(function(fileName) {
169+
fs1.remove(fileName);
170+
});
171+
fs1.write('main.py', code);
172+
fs2.ls().forEach(function(fileName) {
173+
fs2.remove(fileName);
174+
});
175+
fs2.write('main.py', code);
176+
return ['main.py'];
177+
};
178+
179+
return fsWrapper;
180+
};
181+
182+
if (typeof module !== 'undefined' && module.exports) {
183+
global.microbitFsWrapper = microbitFsWrapper;
184+
} else {
185+
window.microbitFsWrapper = microbitFsWrapper;
186+
}

0 commit comments

Comments
 (0)