usb vritual serial to uart
Dependencies: BufferedSerial USBDevice mbed
Fork of USB2UART by
main.cpp@7:630d09697776, 2017-05-22 (annotated)
- Committer:
- swxu
- Date:
- Mon May 22 07:47:13 2017 +0000
- Revision:
- 7:630d09697776
- Parent:
- 6:40182fd79c75
refactor and add BREAK support
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yihui | 0:8c4eea221dcf | 1 | /** |
yihui | 0:8c4eea221dcf | 2 | * USB to UART Bridge |
yihui | 0:8c4eea221dcf | 3 | */ |
yihui | 0:8c4eea221dcf | 4 | |
yihui | 0:8c4eea221dcf | 5 | #include "mbed.h" |
yihui | 0:8c4eea221dcf | 6 | #include "USBSerial.h" |
yihui | 4:9c038f12d460 | 7 | #include "BufferedSerial.h" |
yihui | 0:8c4eea221dcf | 8 | |
swxu | 7:630d09697776 | 9 | #define CDC_SEND_BREAK 0x23 |
swxu | 7:630d09697776 | 10 | |
swxu | 7:630d09697776 | 11 | class USB_UART_Bridge : public USBSerial |
swxu | 7:630d09697776 | 12 | { |
swxu | 7:630d09697776 | 13 | public: |
swxu | 7:630d09697776 | 14 | static USB_UART_Bridge& instance() { |
swxu | 7:630d09697776 | 15 | static USB_UART_Bridge stub; |
swxu | 7:630d09697776 | 16 | return stub; |
swxu | 7:630d09697776 | 17 | } |
swxu | 7:630d09697776 | 18 | |
swxu | 7:630d09697776 | 19 | void update_txrx_indicator() |
swxu | 7:630d09697776 | 20 | { |
swxu | 7:630d09697776 | 21 | if (_tx_flag) { |
swxu | 7:630d09697776 | 22 | _tx_indicator = !_tx_indicator; |
swxu | 7:630d09697776 | 23 | _tx_flag = false; |
swxu | 7:630d09697776 | 24 | } else { |
swxu | 7:630d09697776 | 25 | _tx_indicator = 1; |
swxu | 7:630d09697776 | 26 | } |
swxu | 7:630d09697776 | 27 | |
swxu | 7:630d09697776 | 28 | if (_rx_flag) { |
swxu | 7:630d09697776 | 29 | _rx_indicator = !_rx_indicator; |
swxu | 7:630d09697776 | 30 | _rx_flag = false; |
swxu | 7:630d09697776 | 31 | } else { |
swxu | 7:630d09697776 | 32 | _rx_indicator = 1; |
swxu | 7:630d09697776 | 33 | } |
swxu | 7:630d09697776 | 34 | } |
swxu | 7:630d09697776 | 35 | |
swxu | 7:630d09697776 | 36 | void update_state_indicator() |
swxu | 7:630d09697776 | 37 | { |
swxu | 7:630d09697776 | 38 | _state_indicator = !_state_indicator; |
swxu | 7:630d09697776 | 39 | } |
swxu | 7:630d09697776 | 40 | |
swxu | 7:630d09697776 | 41 | void check_reset_button() |
swxu | 7:630d09697776 | 42 | { |
swxu | 7:630d09697776 | 43 | if (!_reset_button.read()) { |
swxu | 7:630d09697776 | 44 | _reset_pin = 0; |
swxu | 7:630d09697776 | 45 | _state_indicator = 0; |
swxu | 7:630d09697776 | 46 | } |
swxu | 7:630d09697776 | 47 | } |
swxu | 7:630d09697776 | 48 | |
swxu | 7:630d09697776 | 49 | protected: |
swxu | 7:630d09697776 | 50 | virtual bool USBCallback_request() { |
swxu | 7:630d09697776 | 51 | if (USBSerial::USBCallback_request()) { |
swxu | 7:630d09697776 | 52 | return true; |
swxu | 7:630d09697776 | 53 | } |
swxu | 7:630d09697776 | 54 | |
swxu | 7:630d09697776 | 55 | /* Called in ISR context */ |
swxu | 7:630d09697776 | 56 | bool success = false; |
swxu | 7:630d09697776 | 57 | CONTROL_TRANSFER * transfer = getTransferPtr(); |
swxu | 7:630d09697776 | 58 | |
swxu | 7:630d09697776 | 59 | /* Process class-specific requests */ |
swxu | 7:630d09697776 | 60 | if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { |
swxu | 7:630d09697776 | 61 | switch (transfer->setup.bRequest) { |
swxu | 7:630d09697776 | 62 | case CDC_SEND_BREAK: |
swxu | 7:630d09697776 | 63 | _uart.send_break(); |
swxu | 7:630d09697776 | 64 | success = true; |
swxu | 7:630d09697776 | 65 | default: |
swxu | 7:630d09697776 | 66 | break; |
swxu | 7:630d09697776 | 67 | } |
swxu | 7:630d09697776 | 68 | } |
swxu | 7:630d09697776 | 69 | |
swxu | 7:630d09697776 | 70 | return success; |
swxu | 7:630d09697776 | 71 | } |
swxu | 7:630d09697776 | 72 | |
swxu | 7:630d09697776 | 73 | // Called by ISR |
swxu | 7:630d09697776 | 74 | static void on_setting_changed(int baud, int bits, int parity, int stop) |
swxu | 7:630d09697776 | 75 | { |
swxu | 7:630d09697776 | 76 | static const Serial::Parity parityTable[] = {Serial::None, Serial::Odd, Serial::Even, Serial::Forced0, Serial::Forced1}; |
swxu | 7:630d09697776 | 77 | |
swxu | 7:630d09697776 | 78 | instance()._state_indicator = 1; |
swxu | 7:630d09697776 | 79 | if (stop != 2) { |
swxu | 7:630d09697776 | 80 | stop = 1; // stop bit(s) = 1 or 1.5 |
swxu | 7:630d09697776 | 81 | } |
swxu | 7:630d09697776 | 82 | instance()._uart.baud(baud); |
swxu | 7:630d09697776 | 83 | instance()._uart.format(bits, parityTable[parity], stop); |
swxu | 7:630d09697776 | 84 | instance()._state_indicator = 0; |
swxu | 7:630d09697776 | 85 | } |
swxu | 7:630d09697776 | 86 | |
swxu | 7:630d09697776 | 87 | void on_usb_received() { |
swxu | 7:630d09697776 | 88 | while (this->readable()) { |
swxu | 7:630d09697776 | 89 | char c = this->getc(); |
swxu | 7:630d09697776 | 90 | _tx_flag = true; |
swxu | 7:630d09697776 | 91 | _uart.putc(c); |
swxu | 7:630d09697776 | 92 | } |
swxu | 7:630d09697776 | 93 | } |
swxu | 7:630d09697776 | 94 | |
swxu | 7:630d09697776 | 95 | void on_uart_received() { |
swxu | 7:630d09697776 | 96 | while (_uart.readable()) { |
swxu | 7:630d09697776 | 97 | char c = _uart.getc(); |
swxu | 7:630d09697776 | 98 | _rx_flag = true; |
swxu | 7:630d09697776 | 99 | this->putc(c); |
swxu | 7:630d09697776 | 100 | } |
swxu | 7:630d09697776 | 101 | } |
swxu | 7:630d09697776 | 102 | |
swxu | 7:630d09697776 | 103 | private: |
swxu | 7:630d09697776 | 104 | USB_UART_Bridge() : |
swxu | 7:630d09697776 | 105 | _uart(P0_19, P0_18, 512), |
swxu | 7:630d09697776 | 106 | _tx_indicator(P0_20), |
swxu | 7:630d09697776 | 107 | _rx_indicator(P0_21), |
swxu | 7:630d09697776 | 108 | _state_indicator(P0_11), |
swxu | 7:630d09697776 | 109 | _reset_pin(P0_2), |
swxu | 7:630d09697776 | 110 | _reset_button(P0_1, PullUp), |
swxu | 7:630d09697776 | 111 | _rx_flag(false), |
swxu | 7:630d09697776 | 112 | _tx_flag(false) |
swxu | 7:630d09697776 | 113 | { |
swxu | 7:630d09697776 | 114 | this->attach(&USB_UART_Bridge::on_setting_changed); |
swxu | 7:630d09697776 | 115 | this->attach(this, &USB_UART_Bridge::on_usb_received); |
swxu | 7:630d09697776 | 116 | _uart.attach(this, &USB_UART_Bridge::on_uart_received); |
swxu | 7:630d09697776 | 117 | } |
swxu | 7:630d09697776 | 118 | |
swxu | 7:630d09697776 | 119 | private: |
swxu | 7:630d09697776 | 120 | BufferedSerial _uart; |
swxu | 7:630d09697776 | 121 | DigitalOut _tx_indicator; |
swxu | 7:630d09697776 | 122 | DigitalOut _rx_indicator; |
swxu | 7:630d09697776 | 123 | DigitalOut _state_indicator; |
swxu | 7:630d09697776 | 124 | DigitalOut _reset_pin; |
swxu | 7:630d09697776 | 125 | DigitalIn _reset_button; |
swxu | 7:630d09697776 | 126 | |
swxu | 7:630d09697776 | 127 | volatile bool _rx_flag; |
swxu | 7:630d09697776 | 128 | volatile bool _tx_flag; |
swxu | 7:630d09697776 | 129 | }; |
swxu | 7:630d09697776 | 130 | |
swxu | 6:40182fd79c75 | 131 | Ticker txrx_ticker; |
swxu | 6:40182fd79c75 | 132 | Ticker state_ticker; |
swxu | 6:40182fd79c75 | 133 | Ticker reset_ticker; |
yihui | 3:2b4d2284bab0 | 134 | |
swxu | 7:630d09697776 | 135 | int main() |
yihui | 5:10fccccbbb11 | 136 | { |
swxu | 7:630d09697776 | 137 | USB_UART_Bridge& bridge = USB_UART_Bridge::instance(); |
swxu | 7:630d09697776 | 138 | |
swxu | 7:630d09697776 | 139 | #ifndef callback |
swxu | 7:630d09697776 | 140 | #define callback(obj, mfp) FunctionPointer(obj, mfp).get_function() |
swxu | 7:630d09697776 | 141 | #endif |
swxu | 7:630d09697776 | 142 | |
swxu | 7:630d09697776 | 143 | state_ticker.attach(callback(&bridge, &USB_UART_Bridge::update_state_indicator), 1); |
swxu | 7:630d09697776 | 144 | txrx_ticker.attach_us(callback(&bridge, &USB_UART_Bridge::update_txrx_indicator), 10*1000); |
swxu | 7:630d09697776 | 145 | reset_ticker.attach_us(callback(&bridge, &USB_UART_Bridge::check_reset_button), 20*1000); |
swxu | 7:630d09697776 | 146 | |
swxu | 7:630d09697776 | 147 | while (1) { |
swxu | 7:630d09697776 | 148 | __WFI(); |
swxu | 6:40182fd79c75 | 149 | } |
swxu | 6:40182fd79c75 | 150 | } |