diff --git a/fieldeditors/wrap.ts b/fieldeditors/wrap.ts deleted file mode 100644 index d27f6bf1..00000000 --- a/fieldeditors/wrap.ts +++ /dev/null @@ -1,285 +0,0 @@ -namespace pxt.editor { - import HF2 = pxt.HF2 - import U = pxt.U - - function log(msg: string) { - pxt.log("EWRAP: " + msg) - } - - export interface DirEntry { - name: string; - md5?: string; - size?: number; - } - - const runTemplate = "C00882010084XX0060640301606400" - const usbMagic = 0x3d3f - - export class Ev3Wrapper { - msgs = new U.PromiseBuffer() - private cmdSeq = U.randomUint32() & 0xffff; - private lock = new U.PromiseQueue(); - isStreaming = false; - dataDump = false; - - constructor(public io: pxt.HF2.PacketIO) { - io.onData = buf => { - buf = buf.slice(0, HF2.read16(buf, 0) + 2) - if (HF2.read16(buf, 4) == usbMagic) { - let code = HF2.read16(buf, 6) - let payload = buf.slice(8) - if (code == 1) { - let str = U.uint8ArrayToString(payload) - if (Util.isNodeJS) - console.log("SERIAL: " + str.replace(/\n+$/, "")) - else - window.postMessage({ - type: 'serial', - id: 'n/a', // TODO? - data: str - }, "*") - } else - console.log("Magic: " + code + ": " + U.toHex(payload)) - return - } - if (this.dataDump) - log("RECV: " + U.toHex(buf)) - this.msgs.push(buf) - } - } - - private allocCore(addSize: number, replyType: number) { - let len = 5 + addSize - let buf = new Uint8Array(len) - HF2.write16(buf, 0, len - 2) // pktLen - HF2.write16(buf, 2, this.cmdSeq++) // msgCount - buf[4] = replyType - return buf - } - - private allocSystem(addSize: number, cmd: number, replyType = 1) { - let buf = this.allocCore(addSize + 1, replyType) - buf[5] = cmd - return buf - } - - private allocCustom(code: number, addSize = 0) { - let buf = this.allocCore(1 + 2 + addSize, 0) - HF2.write16(buf, 4, usbMagic) - HF2.write16(buf, 6, code) - return buf - } - - stopAsync() { - return this.isVmAsync() - .then(vm => { - if (vm) return Promise.resolve(); - log(`stopping PXT app`) - let buf = this.allocCustom(2) - return this.justSendAsync(buf) - .then(() => Promise.delay(500)) - }) - } - - dmesgAsync() { - log(`asking for DMESG buffer over serial`) - let buf = this.allocCustom(3) - return this.justSendAsync(buf) - } - - runAsync(path: string) { - let codeHex = runTemplate.replace("XX", U.toHex(U.stringToUint8Array(path))) - let code = U.fromHex(codeHex) - let pkt = this.allocCore(2 + code.length, 0) - HF2.write16(pkt, 5, 0x0800) - U.memcpy(pkt, 7, code) - log(`run ${path}`) - return this.justSendAsync(pkt) - } - - justSendAsync(buf: Uint8Array) { - return this.lock.enqueue("talk", () => { - this.msgs.drain() - if (this.dataDump) - log("SEND: " + U.toHex(buf)) - return this.io.sendPacketAsync(buf) - }) - } - - talkAsync(buf: Uint8Array, altResponse = 0) { - return this.lock.enqueue("talk", () => { - this.msgs.drain() - if (this.dataDump) - log("TALK: " + U.toHex(buf)) - return this.io.sendPacketAsync(buf) - .then(() => this.msgs.shiftAsync(1000)) - .then(resp => { - if (resp[2] != buf[2] || resp[3] != buf[3]) - U.userError("msg count de-sync") - if (buf[4] == 1) { - if (altResponse != -1 && resp[5] != buf[5]) - U.userError("cmd de-sync") - if (altResponse != -1 && resp[6] != 0 && resp[6] != altResponse) - U.userError("cmd error: " + resp[6]) - } - return resp - }) - }) - } - - flashAsync(path: string, file: Uint8Array) { - log(`write ${file.length} bytes to ${path}`) - - let handle = -1 - - let loopAsync = (pos: number): Promise => { - if (pos >= file.length) return Promise.resolve() - let size = file.length - pos - if (size > 1000) size = 1000 - let upl = this.allocSystem(1 + size, 0x93, 0x1) - upl[6] = handle - U.memcpy(upl, 6 + 1, file, pos, size) - return this.talkAsync(upl, 8) // 8=EOF - .then(() => loopAsync(pos + size)) - } - - let begin = this.allocSystem(4 + path.length + 1, 0x92) - HF2.write32(begin, 6, file.length) // fileSize - U.memcpy(begin, 10, U.stringToUint8Array(path)) - return this.lock.enqueue("file", () => - this.talkAsync(begin) - .then(resp => { - handle = resp[7] - return loopAsync(0) - })) - } - - lsAsync(path: string): Promise { - let lsReq = this.allocSystem(2 + path.length + 1, 0x99) - HF2.write16(lsReq, 6, 1024) // maxRead - U.memcpy(lsReq, 8, U.stringToUint8Array(path)) - - return this.talkAsync(lsReq, 8) - .then(resp => - U.uint8ArrayToString(resp.slice(12)).split(/\n/).map(s => { - if (!s) return null as DirEntry - let m = /^([A-F0-9]+) ([A-F0-9]+) ([^\/]*)$/.exec(s) - if (m) - return { - md5: m[1], - size: parseInt(m[2], 16), - name: m[3] - } - else - return { - name: s.replace(/\/$/, "") - } - }).filter(v => !!v)) - } - - rmAsync(path: string): Promise { - log(`rm ${path}`) - let rmReq = this.allocSystem(path.length + 1, 0x9c) - U.memcpy(rmReq, 6, U.stringToUint8Array(path)) - - return this.talkAsync(rmReq, 5) - .then(resp => { }) - } - - isVmAsync(): Promise { - let path = "/no/such/dir" - let mkdirReq = this.allocSystem(path.length + 1, 0x9b) - U.memcpy(mkdirReq, 6, U.stringToUint8Array(path)) - return this.talkAsync(mkdirReq, -1) - .then(resp => { - let isVM = resp[6] == 0x05 - log(`${isVM ? "PXT app" : "VM"} running`) - return isVM - }) - } - - private streamFileOnceAsync(path: string, cb: (d: Uint8Array) => void) { - let fileSize = 0 - let filePtr = 0 - let handle = -1 - let resp = (buf: Uint8Array): Promise => { - if (buf[6] == 2) { - // handle not ready - file is missing - this.isStreaming = false - return Promise.resolve() - } - - if (buf[6] != 0 && buf[6] != 8) - U.userError("bad response when streaming file: " + buf[6] + " " + U.toHex(buf)) - - this.isStreaming = true - fileSize = HF2.read32(buf, 7) - if (handle == -1) { - handle = buf[11] - log(`stream on, handle=${handle}`) - } - let data = buf.slice(12) - filePtr += data.length - if (data.length > 0) - cb(data) - - if (buf[6] == 8) { - // end of file - this.isStreaming = false - return this.rmAsync(path) - } - - let contFileReq = this.allocSystem(1 + 2, 0x97) - HF2.write16(contFileReq, 7, 1000) // maxRead - contFileReq[6] = handle - return Promise.delay(data.length > 0 ? 0 : 500) - .then(() => this.talkAsync(contFileReq, -1)) - .then(resp) - } - - let getFileReq = this.allocSystem(2 + path.length + 1, 0x96) - HF2.write16(getFileReq, 6, 1000) // maxRead - U.memcpy(getFileReq, 8, U.stringToUint8Array(path)) - return this.talkAsync(getFileReq, -1).then(resp) - } - - streamFileAsync(path: string, cb: (d: Uint8Array) => void) { - let loop = (): Promise => - this.lock.enqueue("file", () => - this.streamFileOnceAsync(path, cb)) - .then(() => Promise.delay(500)) - .then(loop) - return loop() - } - - - downloadFileAsync(path: string, cb: (d: Uint8Array) => void) { - return this.lock.enqueue("file", () => - this.streamFileOnceAsync(path, cb)) - } - - - private initAsync() { - return Promise.resolve() - } - - private resetState() { - - } - - reconnectAsync(first = false): Promise { - this.resetState() - if (first) return this.initAsync() - log(`reconnect`); - return this.io.reconnectAsync() - .then(() => this.initAsync()) - } - - disconnectAsync() { - log(`disconnect`); - return this.io.disconnectAsync() - } - } - - -} \ No newline at end of file diff --git a/pxtarget.json b/pxtarget.json index 89a4351f..18f56d5a 100644 --- a/pxtarget.json +++ b/pxtarget.json @@ -95,7 +95,6 @@ "privacyUrl": "https://go.microsoft.com/fwlink/?LinkId=521839", "termsOfUseUrl": "https://go.microsoft.com/fwlink/?LinkID=206977", "githubUrl": "https://github.com/Microsoft/pxt-ev3", - "betaUrl": "https://makecode.mindstorms.com/about", "driveDisplayName": "EV3", "boardName": "LEGO® MINDSTORMS® Education EV3", "copyrightText": "LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of the LEGO Group. ©2018 The LEGO Group. All rights reserved.",