|
20 | 20 | CHANNEL_INDEX_I2C_ADDR = 14 |
21 | 21 | CHANNEL_INDEX_I2C_LENGTH = 15 |
22 | 22 | CHANNEL_INDEX_I2C_CONTROL = 16 |
23 | | -CHANNEL_INDEX_COLOURTAIL_LENGTH = 17 |
24 | | -CHANNEL_INDEX_COLOURTAIL_CONTROL = 18 |
| 23 | +CHANNEL_INDEX_UART_RX_OFFSET = 17 |
| 24 | +CHANNEL_INDEX_UART_RX_LENGTH = 18 |
| 25 | +CHANNEL_INDEX_UART_TX_OFFSET = 19 |
| 26 | +CHANNEL_INDEX_UART_TX_LENGTH = 20 |
| 27 | +CHANNEL_INDEX_UART_CONTROL = 21 |
| 28 | +CHANNEL_INDEX_COLOURTAIL_LENGTH = 22 |
| 29 | +CHANNEL_INDEX_COLOURTAIL_CONTROL = 23 |
25 | 30 |
|
26 | | -EXTENSION_CONF_IO = 0 |
27 | | -EXTENSION_CONF_SPI = 1 |
28 | | -EXTENSION_CONF_I2C = 2 |
| 31 | +EXTENSION_CONF_IO = 0x01 |
| 32 | +EXTENSION_CONF_SPI = 0x02 |
| 33 | +EXTENSION_CONF_I2C = 0x04 |
| 34 | +EXTENSION_CONF_UART = 0x08 |
| 35 | + |
| 36 | +UART_TX_BUFFER_INDEX = 0 |
| 37 | +UART_RX_BUFFER_INDEX = 1 |
| 38 | + |
| 39 | +UART_TX_GO_BUSY_MASK = 0x01 |
| 40 | +UART_RX_GO_BUSY_MASK = 0x02 |
| 41 | +UART_BAUD_300 = 0 << 2 |
| 42 | +UART_BAUD_1200 = 1 << 2 |
| 43 | +UART_BAUD_2400 = 2 << 2 |
| 44 | +UART_BAUD_9600 = 3 << 2 |
| 45 | +UART_BAUD_10417 = 4 << 2 |
| 46 | +UART_BAUD_19200 = 5 << 2 |
| 47 | +UART_BAUD_57600 = 6 << 2 |
| 48 | +UART_BAUD_115200 = 7 << 2 |
| 49 | + |
| 50 | +UART_DEFAULT_BAUD = 9600 |
| 51 | + |
| 52 | + |
| 53 | +class InvalidBaud(Exception): |
| 54 | + pass |
29 | 55 |
|
30 | 56 |
|
31 | 57 | class CodeBug(SerialChannelDevice): |
@@ -197,6 +223,9 @@ def config_extension_spi(self): |
197 | 223 | def config_extension_i2c(self): |
198 | 224 | self.set(CHANNEL_INDEX_EXT_CONF, EXTENSION_CONF_I2C) |
199 | 225 |
|
| 226 | + def config_extension_uart(self): |
| 227 | + self.set(CHANNEL_INDEX_EXT_CONF, EXTENSION_CONF_UART) |
| 228 | + |
200 | 229 | def spi_transaction(self, |
201 | 230 | data, |
202 | 231 | cs_idle_high=1, |
@@ -318,3 +347,94 @@ def send_msg(msg): |
318 | 347 | send_msg(message) |
319 | 348 |
|
320 | 349 | return tuple(rx_buffer) |
| 350 | + |
| 351 | + def _get_uart_control_baud(self, baud): |
| 352 | + """Returns UART control value for given baud rate. Will raise |
| 353 | + InvalidBaud exception if baud is invalid. |
| 354 | + """ |
| 355 | + baud_control = {300: 0 << 2, |
| 356 | + 1200: 1 << 2, |
| 357 | + 2400: 2 << 2, |
| 358 | + 9600: 3 << 2, |
| 359 | + 10417: 4 << 2, |
| 360 | + 19200: 5 << 2, |
| 361 | + 57600: 6 << 2, |
| 362 | + 115200: 7 << 2} |
| 363 | + if baud not in baud_control: |
| 364 | + raise InvalidBaud('{} is not a valid baud rate (valid baud ' |
| 365 | + 'rates: {}).'.format(baud, tuple(baud_control.keys()))) |
| 366 | + else: |
| 367 | + return baud_control[baud] |
| 368 | + |
| 369 | + def uart_set_baud(self, baud): |
| 370 | + self.set(CHANNEL_INDEX_UART_CONTROL, self._get_uart_control_baud(baud)) |
| 371 | + |
| 372 | + def uart_tx(self, data_bytes, baud=UART_DEFAULT_BAUD): |
| 373 | + """Transmits data bytes over UART. Use this if you just want to |
| 374 | + send X amount of data. Be sure to configure the extension pins |
| 375 | + first. For example: |
| 376 | +
|
| 377 | + >>> from codebug_tether import CodeBug |
| 378 | + >>> codebug = CodeBug() |
| 379 | + >>> codebug.config_extension_uart() |
| 380 | + >>> # send 0xAA, 0xBB over UART |
| 381 | + >>> codebug.uart_tx(bytes((0xAA, 0xBB))) |
| 382 | + >>> # send 0xAA, 0xBB over UART at 300 baud |
| 383 | + >>> codebug.uart_tx(bytes((0xAA, 0xBB)), baud=300) |
| 384 | +
|
| 385 | + """ |
| 386 | + self.uart_tx_set_buffer(data_bytes) |
| 387 | + self.uart_tx_start(len(data_bytes)) |
| 388 | + |
| 389 | + def uart_tx_start(self, length, offset=0, baud=UART_DEFAULT_BAUD): |
| 390 | + """Transmits 'length' data bytes from UART buffer starting at |
| 391 | + 'offset' over UART. Be sure to configure the extension pins |
| 392 | + first. For example, you might want to fill the buffer with two |
| 393 | + commands (0xAA and 0xBB) which are sent over UART and only send |
| 394 | + one at a time: |
| 395 | +
|
| 396 | + >>> from codebug_tether import CodeBug |
| 397 | + >>> codebug = CodeBug() |
| 398 | + >>> codebug.config_extension_uart() |
| 399 | + >>> codebug.uart_tx_set_buffer(bytes((0xAA, 0xBB))) |
| 400 | + >>> codebug.uart_tx_start(1, offset=0) # send 0xAA over UART |
| 401 | + >>> codebug.uart_tx_start(1, offset=1) # send 0xBB over UART |
| 402 | + >>> # send 0xAA over UART at 300 baud |
| 403 | + >>> codebug.uart_tx_start(1, offset=0, baud=300) |
| 404 | +
|
| 405 | + """ |
| 406 | + control = self._get_uart_control_baud(baud) | UART_TX_GO_BUSY_MASK |
| 407 | + self.set_bulk(CHANNEL_INDEX_UART_TX_OFFSET, |
| 408 | + bytes((offset, length, control))) |
| 409 | + |
| 410 | + def uart_tx_set_buffer(self, data_bytes, offset=0): |
| 411 | + """Add data_bytes to the UART buffer at offset.""" |
| 412 | + self.set_buffer(UART_TX_BUFFER_INDEX, data_bytes, offset) |
| 413 | + |
| 414 | + def uart_rx_start(self, length, baud=UART_DEFAULT_BAUD, offset=0): |
| 415 | + """Begins receiving on the UART. RX will stop when length data is |
| 416 | + reached. Be sure to configure the extension pins first. For example |
| 417 | +
|
| 418 | + >>> from codebug_tether import CodeBug |
| 419 | + >>> codebug = CodeBug() |
| 420 | + >>> codebug.config_extension_uart() |
| 421 | + >>> codebug.uart_rx_start(2) # ready to receive 2B over UART |
| 422 | + >>> # wait until data ready (alternatively, sleep X seconds) |
| 423 | + >>> while not codebug.uart_rx_is_ready(): |
| 424 | + ... pass |
| 425 | + ... |
| 426 | + >>> codebug.uart_rx_get_buffer(2) # read out the two bytes |
| 427 | +
|
| 428 | + """ |
| 429 | + self.set_bulk(CHANNEL_INDEX_UART_RX_OFFSET, bytes((offset, length))) |
| 430 | + self.set(CHANNEL_INDEX_UART_CONTROL, |
| 431 | + self._get_uart_control_baud(baud) | UART_RX_GO_BUSY_MASK) |
| 432 | + |
| 433 | + def uart_rx_is_ready(self): |
| 434 | + """Returns True if the UART has finished receiving data.""" |
| 435 | + uart_control = self.get(CHANNEL_INDEX_UART_CONTROL)[0] |
| 436 | + return uart_control & UART_RX_GO_BUSY_MASK == 0 |
| 437 | + |
| 438 | + def uart_rx_get_buffer(self, length, offset=0): |
| 439 | + """Returns data bytes from UART buffer.""" |
| 440 | + return self.get_buffer(UART_RX_BUFFER_INDEX, length, offset) |
0 commit comments