usb vritual serial to uart

Dependencies:   BufferedSerial USBDevice mbed

Fork of USB2UART by Yihui Xiong

main.cpp

Committer:
swxu
Date:
2017-05-22
Revision:
7:630d09697776
Parent:
6:40182fd79c75

File content as of revision 7:630d09697776:

/**
 * USB to UART Bridge
 */
 
#include "mbed.h"
#include "USBSerial.h"
#include "BufferedSerial.h"

#define CDC_SEND_BREAK             0x23

class USB_UART_Bridge : public USBSerial
{
public:
    static USB_UART_Bridge& instance() {
        static USB_UART_Bridge stub;
        return stub;
    }

    void update_txrx_indicator()
    {
        if (_tx_flag) {
            _tx_indicator = !_tx_indicator;
            _tx_flag = false;
        } else {
            _tx_indicator = 1;
        }
        
        if (_rx_flag) {
            _rx_indicator = !_rx_indicator;
            _rx_flag = false;
        } else {
            _rx_indicator = 1;
        }
    }

    void update_state_indicator()
    {
        _state_indicator = !_state_indicator;
    }

    void check_reset_button()
    {
        if (!_reset_button.read()) {
            _reset_pin = 0;
            _state_indicator = 0;
        }
    }

protected:
    virtual bool USBCallback_request() {
        if (USBSerial::USBCallback_request()) {
            return true;
        }
        
        /* Called in ISR context */
        bool success = false;
        CONTROL_TRANSFER * transfer = getTransferPtr();

        /* Process class-specific requests */
        if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
            switch (transfer->setup.bRequest) {
                case CDC_SEND_BREAK:
                    _uart.send_break();
                    success = true;
                default:
                    break;
            }
        }

        return success;
    }

    // Called by ISR
    static void on_setting_changed(int baud, int bits, int parity, int stop)
    {
        static const Serial::Parity parityTable[] = {Serial::None, Serial::Odd, Serial::Even, Serial::Forced0, Serial::Forced1};
        
        instance()._state_indicator = 1;
        if (stop != 2) {
            stop = 1;   // stop bit(s) = 1 or 1.5
        }
        instance()._uart.baud(baud);
        instance()._uart.format(bits, parityTable[parity], stop);
        instance()._state_indicator = 0;
    }

    void on_usb_received() {
        while (this->readable()) {
            char c = this->getc();
            _tx_flag = true;
            _uart.putc(c);
        }
    }

    void on_uart_received() {
        while (_uart.readable()) {
            char c = _uart.getc();
            _rx_flag = true;
            this->putc(c);
        }
    }

private:
    USB_UART_Bridge() :
        _uart(P0_19, P0_18, 512),
        _tx_indicator(P0_20),
        _rx_indicator(P0_21),
        _state_indicator(P0_11),
        _reset_pin(P0_2),
        _reset_button(P0_1, PullUp),
        _rx_flag(false),
        _tx_flag(false)
    {
        this->attach(&USB_UART_Bridge::on_setting_changed);
        this->attach(this, &USB_UART_Bridge::on_usb_received);
        _uart.attach(this, &USB_UART_Bridge::on_uart_received);
    }
    
private:
    BufferedSerial _uart;
    DigitalOut _tx_indicator;
    DigitalOut _rx_indicator;
    DigitalOut _state_indicator;
    DigitalOut _reset_pin;
    DigitalIn _reset_button;

    volatile bool _rx_flag;
    volatile bool _tx_flag;
};

Ticker txrx_ticker;
Ticker state_ticker;
Ticker reset_ticker;

int main()
{
    USB_UART_Bridge& bridge = USB_UART_Bridge::instance();

#ifndef callback
#define callback(obj, mfp) FunctionPointer(obj, mfp).get_function()
#endif

    state_ticker.attach(callback(&bridge, &USB_UART_Bridge::update_state_indicator), 1);
    txrx_ticker.attach_us(callback(&bridge, &USB_UART_Bridge::update_txrx_indicator), 10*1000);
    reset_ticker.attach_us(callback(&bridge, &USB_UART_Bridge::check_reset_button), 20*1000);

    while (1) {
        __WFI();
    }
}