Here’s a fun project – rewriting avrdude
in CoffeesCript, as I did a while back with Tcl:
{SerialPort} = require 'serialport' pageBytes = 128 avrUploader = (bytes, tty, cb) -> serial = new SerialPort tty, baudrate: 115200 done = (err) -> serial.close -> cb err timer = null state = offset = 0 reply = '' states = [ # Finite State Machine, one function per state -> ['0 '] -> buf = new Buffer(20) buf.fill 0 buf.writeInt16BE pageBytes, 12 ['B', buf, ' '] -> ['P '] -> state += 1 if offset >= bytes.length buf = new Buffer(2) buf.writeInt16LE offset >> 1, 0 ['U', buf, ' '] -> state -= 2 count = Math.min bytes.length - offset, pageBytes buf = new Buffer(2) buf.writeInt16BE count, 0 pos = offset offset += count ['d', buf, 'F', bytes.slice(pos, offset), ' '] -> ['Q '] ] next = -> if state < states.length serial.write x for x in states[state++]() serial.flush() reply = '' timer = setTimeout (-> done state), 300 else done() serial.on 'open', next serial.on 'error', done serial.on 'data', (data) -> reply += data if reply.slice(-2) is '\x14\x10' clearTimeout timer next()
And here’s a little test which uploads the RF12demo sketch into a JeeNode over serial:
fs = require 'fs' hex = fs.readFileSync '/Users/jcw/Desktop/RF12demo.cpp.hex', 'ascii' hexToBin = (code) -> data = '' for line in code.split '\n' count = parseInt line.slice(1, 3), 16 if count and line.slice(7, 9) is '00' data += line.slice 9, 9 + 2 * count new Buffer(data, 'hex') avrUploader hexToBin(hex), '/dev/tty.usbserial-AH01A0GD', (err) -> console.error 'err', err if err console.log hexToBin(hex).length
Just copy it all into a file upload.coffee
and run it as: coffee upload.coffee
It’s fairly dense code, but as you can see, the stk500v1 protocol requires very little logic!
JavaScript continues to amaze me with its power. The fact that I haven’t paid closer attention to how it was beiog used and what my browser was allowing it to do leaves me unsettled. Javascript books are now on my must read list.
Why are there no commas in the states array?