Add serial support
This commit is contained in:
		
							
								
								
									
										11
									
								
								aux/build.sh
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								aux/build.sh
									
									
									
									
									
								
							@@ -3,8 +3,15 @@
 | 
			
		||||
LEGO=$HOME/src/lego/lms2012
 | 
			
		||||
P="`pwd`"
 | 
			
		||||
F="$P"/pxt
 | 
			
		||||
set -xe
 | 
			
		||||
set -e
 | 
			
		||||
cd $LEGO/lmssrc/adk/lmsasm
 | 
			
		||||
echo "Compiling..."
 | 
			
		||||
java -jar assembler.jar $F
 | 
			
		||||
cd "$P"
 | 
			
		||||
node -p 'require("fs").readFileSync("pxt.rbf").toString("hex").replace(/5858585858(58)+/, "XX")'
 | 
			
		||||
echo "Hex to paste:"
 | 
			
		||||
echo
 | 
			
		||||
echo "const rbfTemplate = \`"
 | 
			
		||||
node -p 'require("fs").readFileSync("pxt.rbf").toString("hex").replace(/5858585858(58)+/, "XX").replace(/.{1,80}/g, f => f + "\n").trim()'
 | 
			
		||||
echo "\`"
 | 
			
		||||
echo
 | 
			
		||||
rm -f pxt.rbf
 | 
			
		||||
 
 | 
			
		||||
@@ -4,12 +4,15 @@ vmthread  MAIN
 | 
			
		||||
  DATA8   State
 | 
			
		||||
  DATA32  Status
 | 
			
		||||
  //DATA32  Timer
 | 
			
		||||
  DATA16 Serial
 | 
			
		||||
 | 
			
		||||
  UI_WRITE(LED,LED_RED)
 | 
			
		||||
  UI_DRAW(TEXT,FG_COLOR,48,62,'Starting...')
 | 
			
		||||
  UI_DRAW(UPDATE)
 | 
			
		||||
  // Make sure VM knows that /tmp/serial.txt is open for writing and can stream the content
 | 
			
		||||
  FILE(OPEN_WRITE, '/tmp/serial.txt', Serial)
 | 
			
		||||
  // Actual filename is patched-in here
 | 
			
		||||
  SYSTEM('XXXXXXXXX', Status)
 | 
			
		||||
  //SYSTEM('../prjs/BrkProg_SAVE/binary.elf', Status)
 | 
			
		||||
Loop:
 | 
			
		||||
  UI_BUTTON(WAIT_FOR_PRESS)
 | 
			
		||||
  UI_BUTTON(SHORTPRESS,BACK_BUTTON,State)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								aux/pxt.rbf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								aux/pxt.rbf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -8,7 +8,11 @@ eval("if (typeof process === 'object' && process + '' === '[object process]') px
 | 
			
		||||
 | 
			
		||||
namespace pxt.editor {
 | 
			
		||||
    // this comes from aux/pxt.lms
 | 
			
		||||
    const rbfTemplate = "4c45474f5d0000006d000100000000001c0000000000000008000000821b028405018130813e805374617274696e672e2e2e0084006080XX0044830383010640414082f5ff8405018130813e80427965210084000a";
 | 
			
		||||
    const rbfTemplate = `
 | 
			
		||||
4c45474f710000006d000100000000001c000000000000000a000000821b028405018130813e8053
 | 
			
		||||
74617274696e672e2e2e008400c002802f746d702f73657269616c2e74787400486080XX00448303
 | 
			
		||||
83010640414082f5ff8405018130813e80427965210084000a
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
    function hf2Async() {
 | 
			
		||||
        return pxt.HF2.mkPacketIOAsync()
 | 
			
		||||
@@ -44,7 +48,9 @@ namespace pxt.editor {
 | 
			
		||||
                let f = U.stringToUint8Array(atob(resp.outfiles[pxt.outputName()]))
 | 
			
		||||
                return w.flashAsync(elfPath, f)
 | 
			
		||||
            }).then(() => {
 | 
			
		||||
                let rbfHex = rbfTemplate.replace("XX", U.toHex(U.stringToUint8Array(elfPath)))
 | 
			
		||||
                let rbfHex = rbfTemplate
 | 
			
		||||
                    .replace(/\s+/g, "")
 | 
			
		||||
                    .replace("XX", U.toHex(U.stringToUint8Array(elfPath)))
 | 
			
		||||
                let rbf = U.fromHex(rbfHex)
 | 
			
		||||
                HF2.write16(rbf, 4, rbf.length)
 | 
			
		||||
                return w.flashAsync(rbfPath, rbf)
 | 
			
		||||
@@ -59,10 +65,19 @@ namespace pxt.editor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
 | 
			
		||||
        pxt.debug('loading pxt-adafruit target extensions...')
 | 
			
		||||
        pxt.debug('loading pxt-ev3 target extensions...')
 | 
			
		||||
        const res: pxt.editor.ExtensionResult = {
 | 
			
		||||
            deployCoreAsync,
 | 
			
		||||
        };
 | 
			
		||||
        initAsync()
 | 
			
		||||
            .then(w => w.streamFileAsync("/tmp/serial.txt", buf => {
 | 
			
		||||
                let str = Util.fromUTF8(Util.uint8ArrayToString(buf))
 | 
			
		||||
                window.postMessage({
 | 
			
		||||
                    type: 'serial',
 | 
			
		||||
                    id: 'n/a', // TODO
 | 
			
		||||
                    data: str
 | 
			
		||||
                }, "*")
 | 
			
		||||
            }))
 | 
			
		||||
        return Promise.resolve<pxt.editor.ExtensionResult>(res);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,11 +17,12 @@ namespace pxt.editor {
 | 
			
		||||
    export class Ev3Wrapper {
 | 
			
		||||
        msgs = new U.PromiseBuffer<Uint8Array>()
 | 
			
		||||
        private cmdSeq = U.randomUint32() & 0xffff;
 | 
			
		||||
        private lock = new U.PromiseQueue();
 | 
			
		||||
 | 
			
		||||
        constructor(public io: pxt.HF2.PacketIO) {
 | 
			
		||||
            io.onData = buf => {
 | 
			
		||||
                buf = buf.slice(0, HF2.read16(buf, 0) + 2)
 | 
			
		||||
                // log("DATA: " + U.toHex(buf))
 | 
			
		||||
                //log("DATA: " + U.toHex(buf))
 | 
			
		||||
                this.msgs.push(buf)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -53,27 +54,27 @@ namespace pxt.editor {
 | 
			
		||||
                })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        talkAsync(buf: Uint8Array) {
 | 
			
		||||
            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 (resp[5] != buf[5])
 | 
			
		||||
                            U.userError("cmd de-sync")
 | 
			
		||||
                        if (resp[6] != 0 && resp[6] != 1 /* LS? */ && resp[6] != 8 /* EOF */)
 | 
			
		||||
                            U.userError("cmd error: " + resp[6])
 | 
			
		||||
                    }
 | 
			
		||||
                    return resp
 | 
			
		||||
                })
 | 
			
		||||
        talkAsync(buf: Uint8Array, altResponse = 0) {
 | 
			
		||||
            return this.lock.enqueue("talk", () =>
 | 
			
		||||
                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 (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} to ${path}`)
 | 
			
		||||
            let begin = this.allocSystem(4 + path.length + 1, 0x92)
 | 
			
		||||
            HF2.write32(begin, 6, file.length) // fileSize
 | 
			
		||||
            U.memcpy(begin, 10, U.stringToUint8Array(path))
 | 
			
		||||
 | 
			
		||||
            let handle = -1
 | 
			
		||||
 | 
			
		||||
            let loopAsync = (pos: number): Promise<void> => {
 | 
			
		||||
                if (pos >= file.length) return Promise.resolve()
 | 
			
		||||
@@ -82,11 +83,13 @@ namespace pxt.editor {
 | 
			
		||||
                let upl = this.allocSystem(1 + size, 0x93, 0x1)
 | 
			
		||||
                upl[6] = handle
 | 
			
		||||
                U.memcpy(upl, 6 + 1, file, pos, size)
 | 
			
		||||
                return this.talkAsync(upl)
 | 
			
		||||
                return this.talkAsync(upl, 8) // 8=EOF
 | 
			
		||||
                    .then(() => loopAsync(pos + size))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let handle = -1
 | 
			
		||||
            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.talkAsync(begin)
 | 
			
		||||
                .then(resp => {
 | 
			
		||||
                    handle = resp[7]
 | 
			
		||||
@@ -99,7 +102,7 @@ namespace pxt.editor {
 | 
			
		||||
            HF2.write16(lsReq, 6, 1024) // maxRead
 | 
			
		||||
            U.memcpy(lsReq, 8, U.stringToUint8Array(path))
 | 
			
		||||
 | 
			
		||||
            return this.talkAsync(lsReq)
 | 
			
		||||
            return this.talkAsync(lsReq, 8)
 | 
			
		||||
                .then(resp =>
 | 
			
		||||
                    U.uint8ArrayToString(resp.slice(12)).split(/\n/).map(s => {
 | 
			
		||||
                        if (!s) return null as DirEntry
 | 
			
		||||
@@ -118,6 +121,7 @@ namespace pxt.editor {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rmAsync(path: string): Promise<void> {
 | 
			
		||||
            log(`rm ${path}`)
 | 
			
		||||
            let rmReq = this.allocSystem(path.length + 1, 0x9c)
 | 
			
		||||
            U.memcpy(rmReq, 6, U.stringToUint8Array(path))
 | 
			
		||||
 | 
			
		||||
@@ -125,6 +129,47 @@ namespace pxt.editor {
 | 
			
		||||
                .then(resp => { })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        streamFileAsync(path: string, cb: (d: Uint8Array) => void) {
 | 
			
		||||
            let fileSize = 0
 | 
			
		||||
            let filePtr = 0
 | 
			
		||||
            let handle = -1
 | 
			
		||||
            let restart = () => Promise.delay(500).then(() => this.streamFileAsync(path, cb))
 | 
			
		||||
            let resp = (buf: Uint8Array): Promise<void> => {
 | 
			
		||||
                if (buf[6] == 2) {
 | 
			
		||||
                    // handle not ready - file is missing
 | 
			
		||||
                    return restart()
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (buf[6] != 0 && buf[6] != 8)
 | 
			
		||||
                    U.userError("bad response when streaming file: " + buf[6])
 | 
			
		||||
 | 
			
		||||
                fileSize = HF2.read32(buf, 7)
 | 
			
		||||
                if (handle == -1)
 | 
			
		||||
                    handle = buf[11]
 | 
			
		||||
                let data = buf.slice(12)
 | 
			
		||||
                filePtr += data.length
 | 
			
		||||
                if (data.length > 0)
 | 
			
		||||
                    cb(data)
 | 
			
		||||
 | 
			
		||||
                if (buf[6] == 8) {
 | 
			
		||||
                    // end of file
 | 
			
		||||
                    return this.rmAsync(path).then(restart)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                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)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private initAsync() {
 | 
			
		||||
            return Promise.resolve()
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user