Developing for the Canute protocol
Developers can implement support for Canute using BRLTTY’s BrlAPI.
To implement support for the Canute protocol directly, without BrlAPI, see framing and commands below.
The serial line is 9600 Baud, 8n1.
This packetises (frames) data on the wire in the same way as SDLC’s/HDLC’s/PPP’s asynchronous mode, but replacing that structuring of the payload with your own application-specific one. To be explicit on the detail, this code:
- uses the standard HDLC/PPP flag
- frames separated by a single flag are (probably) not supported
- uses the standard byte-stuffing and the standard HDLC/PPP escape octet
- only ever to escape the flag and the escape itself, although it’d be simple to extend to escape more (some implementations escape XON/XOFF, for instance)
- uses your own application-defined packet payload instead of subdividing it into Address/Control/Information as HDLC/PPP would
- uses CRC-16/ISO-HDLC (aka X-25) for the Frame Check Sequence, because it has been the default for as long as SDLC/HDLC/PPP have existed, is standardised by widespread use in PPP, and tends to be clearly defined where it crops up
When choosing or writing something to talk to this at the other end of the link, note that:
- following SDLC/HDLC/PPP, CRC bytes are sent least-significant-byte-first (contrary to the widespread “network byte order” standard!)
- implementations that update a running CRC call by call, but don’t offer any way to finalise it, may expect you to perform the final XOR
- CRC naming is frequently completely wrong, and/or may assume certain initial values or XORs that you’re free to change; e.g. avr-libc’s _crc_ccitt_update() could behave as any of CRC-16/CCITT-TRUE aka KERMIT; CRC-16/ISO-HDLC aka X-25; or CRC-16/MCRF4XX depending on what init/XOR values you use
- http://reveng.sourceforge.net/crc-catalogue/16.htm is an excellent reference on CRC16 details and naming
Every command echos the command being responded to followed by any return data which is mostly just a status byte. On the status byte 0 indicates an ok status.
|Command Name||Code||Data to Send||Description||Returns|
|COMMAND_N_CHARACTERS||0x00||Nothing||Number of characters pair row in the hardware||1+3 bytes|
|COMMAND_N_ROWS||0x01||Nothing||Number of rows on the display||1+2 bytes|
|COMMAND_VERSION||0x03||Nothing||Outputs the protocol version||1+3 bytes|
|COMMAND_SEND_LINE||0x06||Braille data (see below)||Send the canute a row of braille to display||1+2 bytes (zeros)|
|COMMAND_RESET||0x07||Nothing||Reset the display||1+2 bytes (zeros)|
|COMMAND_LOWER_ALL||0x09||Nothing||Lowers the rods of all rows||1+2 bytes (zeros)|
|COMMAND_SEND_BUTTONS||0x0A||Nothing||Outputs the button presses (a bit-field)||1+2 bytes|
|COMMAND_PMCU_FW_VERSION||0x0B||Nothing||Outputs the firmware version||1+variable length|
|COMMAND_POLL||0x0D||Nothing||Poll the status of Canute motion (sends 0b1 if in motion)||1+2 bytes|
|COMMAND_SET_LIFT_POSITION||0x0E||2 bytes - the row number||Set the rod to up or down||1+2 bytes (zeros)|
COMMAND_SEND_LINE is the most useful command. With the first byte you indicate the line number (0 - 8) your are trying to set followed by the Braille data.
|Command||Line number (0 - 8)||Braille Data|
Canute only supports 6-dot braille and it is encoded as integers 0-64 in a binary fashion.
- 0b000000 is a space
- 0b000001 is a dot-1 i.e. ‘a’ i.e. ‘⠁’
- 0b000010 is a dot-2
- 0b000011 is a dots 1 and 2
- 0b111111 is a braille cell with every dot raised
Effectively this means we are using unicode braille minus 10240.
You probably don’t need these.
|COMMAND_SEND_OK||0x05||Command the Canute to make a confirmation sound (currently unused)||1+nothing|
|COMMAND_SEND_ERROR||0x04||Command the Canute to make an error sound (currently unused)||1+nothing|
|COMMAND_TEST_MODE||ascii ‘t’||Go into a test mode (currently unused)||1+nothing|
Useful links for reference (please credit as appropriate you find any of the following useful in writing your own implementation): - brltty/Drivers/Braille/Canute/brldefs-cn.h - brltty/Drivers/Braille/Canute/braille.c