a serial library to communicate with pebble time's smart strap interface
Dependents: xadow_smartstrap_for_pebble
mbedPebbleSerial.cpp@0:e4dad9e53f06, 2015-11-04 (annotated)
- Committer:
- KillingJacky
- Date:
- Wed Nov 04 09:58:41 2015 +0000
- Revision:
- 0:e4dad9e53f06
initial commit;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
KillingJacky | 0:e4dad9e53f06 | 1 | /* |
KillingJacky | 0:e4dad9e53f06 | 2 | * This is an Arduino library wrapper around the PebbleSerial library. |
KillingJacky | 0:e4dad9e53f06 | 3 | */ |
KillingJacky | 0:e4dad9e53f06 | 4 | #include "mbed.h" |
KillingJacky | 0:e4dad9e53f06 | 5 | #include "BufferedSerial.h" |
KillingJacky | 0:e4dad9e53f06 | 6 | #include "mbedPebbleSerial.h" |
KillingJacky | 0:e4dad9e53f06 | 7 | |
KillingJacky | 0:e4dad9e53f06 | 8 | static uint8_t *s_buffer; |
KillingJacky | 0:e4dad9e53f06 | 9 | static size_t s_buffer_length; |
KillingJacky | 0:e4dad9e53f06 | 10 | static uint8_t s_pin; |
KillingJacky | 0:e4dad9e53f06 | 11 | |
KillingJacky | 0:e4dad9e53f06 | 12 | extern BufferedSerial serial; |
KillingJacky | 0:e4dad9e53f06 | 13 | |
KillingJacky | 0:e4dad9e53f06 | 14 | #define _BV(bit) (1<<(bit)) |
KillingJacky | 0:e4dad9e53f06 | 15 | #define cbi(sfr, bit) ((sfr) &= ~_BV(bit)) |
KillingJacky | 0:e4dad9e53f06 | 16 | #define sbi(sfr, bit) ((sfr) |= _BV(bit)) |
KillingJacky | 0:e4dad9e53f06 | 17 | |
KillingJacky | 0:e4dad9e53f06 | 18 | |
KillingJacky | 0:e4dad9e53f06 | 19 | static void board_begin(void) { |
KillingJacky | 0:e4dad9e53f06 | 20 | } |
KillingJacky | 0:e4dad9e53f06 | 21 | |
KillingJacky | 0:e4dad9e53f06 | 22 | static void board_set_tx_enabled(bool enabled) { |
KillingJacky | 0:e4dad9e53f06 | 23 | if (enabled) { |
KillingJacky | 0:e4dad9e53f06 | 24 | // enable transmitter |
KillingJacky | 0:e4dad9e53f06 | 25 | sbi(LPC_USART->TER, 7); |
KillingJacky | 0:e4dad9e53f06 | 26 | // disable receiver |
KillingJacky | 0:e4dad9e53f06 | 27 | sbi(LPC_USART->RS485CTRL, 1); |
KillingJacky | 0:e4dad9e53f06 | 28 | } else { |
KillingJacky | 0:e4dad9e53f06 | 29 | // disable transmitter |
KillingJacky | 0:e4dad9e53f06 | 30 | cbi(LPC_USART->TER, 7); |
KillingJacky | 0:e4dad9e53f06 | 31 | // enable receiver |
KillingJacky | 0:e4dad9e53f06 | 32 | cbi(LPC_USART->RS485CTRL, 1); |
KillingJacky | 0:e4dad9e53f06 | 33 | } |
KillingJacky | 0:e4dad9e53f06 | 34 | } |
KillingJacky | 0:e4dad9e53f06 | 35 | |
KillingJacky | 0:e4dad9e53f06 | 36 | static void board_set_even_parity(bool enabled) { |
KillingJacky | 0:e4dad9e53f06 | 37 | if (enabled) { |
KillingJacky | 0:e4dad9e53f06 | 38 | sbi(LPC_USART->LCR, 3); |
KillingJacky | 0:e4dad9e53f06 | 39 | sbi(LPC_USART->LCR, 4); |
KillingJacky | 0:e4dad9e53f06 | 40 | } else { |
KillingJacky | 0:e4dad9e53f06 | 41 | cbi(LPC_USART->LCR, 3); |
KillingJacky | 0:e4dad9e53f06 | 42 | cbi(LPC_USART->LCR, 4); |
KillingJacky | 0:e4dad9e53f06 | 43 | } |
KillingJacky | 0:e4dad9e53f06 | 44 | } |
KillingJacky | 0:e4dad9e53f06 | 45 | |
KillingJacky | 0:e4dad9e53f06 | 46 | static void board_flush_uart() |
KillingJacky | 0:e4dad9e53f06 | 47 | { |
KillingJacky | 0:e4dad9e53f06 | 48 | while (serial._txbuf.available()); |
KillingJacky | 0:e4dad9e53f06 | 49 | while (!(LPC_USART->LSR & _BV(5))); |
KillingJacky | 0:e4dad9e53f06 | 50 | } |
KillingJacky | 0:e4dad9e53f06 | 51 | |
KillingJacky | 0:e4dad9e53f06 | 52 | static void prv_cmd_cb(SmartstrapCmd cmd, uint32_t arg) { |
KillingJacky | 0:e4dad9e53f06 | 53 | switch (cmd) { |
KillingJacky | 0:e4dad9e53f06 | 54 | case SmartstrapCmdSetBaudRate: |
KillingJacky | 0:e4dad9e53f06 | 55 | serial.baud(arg); |
KillingJacky | 0:e4dad9e53f06 | 56 | break; |
KillingJacky | 0:e4dad9e53f06 | 57 | case SmartstrapCmdSetTxEnabled: |
KillingJacky | 0:e4dad9e53f06 | 58 | if (!arg) board_flush_uart(); |
KillingJacky | 0:e4dad9e53f06 | 59 | board_set_tx_enabled(arg); |
KillingJacky | 0:e4dad9e53f06 | 60 | break; |
KillingJacky | 0:e4dad9e53f06 | 61 | case SmartstrapCmdWriteByte: |
KillingJacky | 0:e4dad9e53f06 | 62 | serial.putc((uint8_t)arg); |
KillingJacky | 0:e4dad9e53f06 | 63 | break; |
KillingJacky | 0:e4dad9e53f06 | 64 | case SmartstrapCmdWriteBreak: |
KillingJacky | 0:e4dad9e53f06 | 65 | board_set_even_parity(true); |
KillingJacky | 0:e4dad9e53f06 | 66 | serial.putc((uint8_t)0); |
KillingJacky | 0:e4dad9e53f06 | 67 | // need to flush before changing parity |
KillingJacky | 0:e4dad9e53f06 | 68 | board_flush_uart(); |
KillingJacky | 0:e4dad9e53f06 | 69 | board_set_even_parity(false); |
KillingJacky | 0:e4dad9e53f06 | 70 | break; |
KillingJacky | 0:e4dad9e53f06 | 71 | default: |
KillingJacky | 0:e4dad9e53f06 | 72 | break; |
KillingJacky | 0:e4dad9e53f06 | 73 | } |
KillingJacky | 0:e4dad9e53f06 | 74 | } |
KillingJacky | 0:e4dad9e53f06 | 75 | |
KillingJacky | 0:e4dad9e53f06 | 76 | static void prv_begin(uint8_t *buffer, size_t length, Baud baud, |
KillingJacky | 0:e4dad9e53f06 | 77 | const uint16_t *services, uint8_t num_services) { |
KillingJacky | 0:e4dad9e53f06 | 78 | s_buffer = buffer; |
KillingJacky | 0:e4dad9e53f06 | 79 | s_buffer_length = length; |
KillingJacky | 0:e4dad9e53f06 | 80 | |
KillingJacky | 0:e4dad9e53f06 | 81 | pebble_init(prv_cmd_cb, (PebbleBaud)baud, services, num_services); |
KillingJacky | 0:e4dad9e53f06 | 82 | pebble_prepare_for_read(s_buffer, s_buffer_length); |
KillingJacky | 0:e4dad9e53f06 | 83 | } |
KillingJacky | 0:e4dad9e53f06 | 84 | |
KillingJacky | 0:e4dad9e53f06 | 85 | void mbedPebbleSerial::begin(uint8_t *buffer, size_t length, Baud baud, |
KillingJacky | 0:e4dad9e53f06 | 86 | const uint16_t *services, uint8_t num_services) { |
KillingJacky | 0:e4dad9e53f06 | 87 | prv_begin(buffer, length, baud, services, num_services); |
KillingJacky | 0:e4dad9e53f06 | 88 | } |
KillingJacky | 0:e4dad9e53f06 | 89 | |
KillingJacky | 0:e4dad9e53f06 | 90 | static int prv_available_bytes(void) { |
KillingJacky | 0:e4dad9e53f06 | 91 | return serial.readable(); |
KillingJacky | 0:e4dad9e53f06 | 92 | } |
KillingJacky | 0:e4dad9e53f06 | 93 | |
KillingJacky | 0:e4dad9e53f06 | 94 | static uint8_t prv_read_byte(void) { |
KillingJacky | 0:e4dad9e53f06 | 95 | return (uint8_t)serial.getc(); |
KillingJacky | 0:e4dad9e53f06 | 96 | } |
KillingJacky | 0:e4dad9e53f06 | 97 | |
KillingJacky | 0:e4dad9e53f06 | 98 | bool mbedPebbleSerial::feed(uint16_t *service_id, uint16_t *attribute_id, size_t *length, |
KillingJacky | 0:e4dad9e53f06 | 99 | RequestType *type) { |
KillingJacky | 0:e4dad9e53f06 | 100 | SmartstrapRequestType request_type; |
KillingJacky | 0:e4dad9e53f06 | 101 | bool did_feed = false; |
KillingJacky | 0:e4dad9e53f06 | 102 | while (prv_available_bytes()) { |
KillingJacky | 0:e4dad9e53f06 | 103 | did_feed = true; |
KillingJacky | 0:e4dad9e53f06 | 104 | if (pebble_handle_byte(prv_read_byte(), service_id, attribute_id, length, &request_type, us_ticker_read()/1000)) { |
KillingJacky | 0:e4dad9e53f06 | 105 | // we have a full frame |
KillingJacky | 0:e4dad9e53f06 | 106 | pebble_prepare_for_read(s_buffer, s_buffer_length); |
KillingJacky | 0:e4dad9e53f06 | 107 | switch (request_type) { |
KillingJacky | 0:e4dad9e53f06 | 108 | case SmartstrapRequestTypeRead: |
KillingJacky | 0:e4dad9e53f06 | 109 | *type = RequestTypeRead; |
KillingJacky | 0:e4dad9e53f06 | 110 | break; |
KillingJacky | 0:e4dad9e53f06 | 111 | case SmartstrapRequestTypeWrite: |
KillingJacky | 0:e4dad9e53f06 | 112 | *type = RequestTypeWrite; |
KillingJacky | 0:e4dad9e53f06 | 113 | break; |
KillingJacky | 0:e4dad9e53f06 | 114 | case SmartstrapRequestTypeWriteRead: |
KillingJacky | 0:e4dad9e53f06 | 115 | *type = RequestTypeWriteRead; |
KillingJacky | 0:e4dad9e53f06 | 116 | break; |
KillingJacky | 0:e4dad9e53f06 | 117 | default: |
KillingJacky | 0:e4dad9e53f06 | 118 | break; |
KillingJacky | 0:e4dad9e53f06 | 119 | } |
KillingJacky | 0:e4dad9e53f06 | 120 | return true; |
KillingJacky | 0:e4dad9e53f06 | 121 | } |
KillingJacky | 0:e4dad9e53f06 | 122 | } |
KillingJacky | 0:e4dad9e53f06 | 123 | |
KillingJacky | 0:e4dad9e53f06 | 124 | if (!did_feed) { |
KillingJacky | 0:e4dad9e53f06 | 125 | // allow the pebble code to dicsonnect if we haven't gotten any messages recently |
KillingJacky | 0:e4dad9e53f06 | 126 | pebble_is_connected(us_ticker_read()/1000); |
KillingJacky | 0:e4dad9e53f06 | 127 | } |
KillingJacky | 0:e4dad9e53f06 | 128 | return false; |
KillingJacky | 0:e4dad9e53f06 | 129 | } |
KillingJacky | 0:e4dad9e53f06 | 130 | |
KillingJacky | 0:e4dad9e53f06 | 131 | bool mbedPebbleSerial::write(bool success, const uint8_t *payload, size_t length) { |
KillingJacky | 0:e4dad9e53f06 | 132 | return pebble_write(success, payload, length); |
KillingJacky | 0:e4dad9e53f06 | 133 | } |
KillingJacky | 0:e4dad9e53f06 | 134 | |
KillingJacky | 0:e4dad9e53f06 | 135 | void mbedPebbleSerial::notify(uint16_t service_id, uint16_t attribute_id) { |
KillingJacky | 0:e4dad9e53f06 | 136 | pebble_notify(service_id, attribute_id); |
KillingJacky | 0:e4dad9e53f06 | 137 | } |
KillingJacky | 0:e4dad9e53f06 | 138 | |
KillingJacky | 0:e4dad9e53f06 | 139 | bool mbedPebbleSerial::is_connected(void) { |
KillingJacky | 0:e4dad9e53f06 | 140 | return pebble_is_connected(us_ticker_read()/1000); |
KillingJacky | 0:e4dad9e53f06 | 141 | } |