SmartWheels self-driving race car. Designed for NXP Cup. Uses FRDM-KL25Z, area-scan camera, and simple image processing to detect and navigate any NXP spec track.

Dependencies:   TSI USBDevice mbed-dev

Fork of SmartWheels by haofan Zheng

RemovedSources/PCConnector/SWUSBServer.cpp.txt

Committer:
hazheng
Date:
2017-04-19
Branch:
Drift
Revision:
87:15fcf7891bf9
Parent:
PCConnector/SWUSBServer.cpp@ 26:5814404856e2

File content as of revision 87:15fcf7891bf9:

#include "SWUSBServer.h"

#define THREAD_SIGNAL_QUEUE 0xa
#define UNRELIABLE_QUEUE_MAX_SIZE 5

#define RECEIVE_BUF_SIZE 70

#include "USBSerial.h"


namespace SW{

USBServer::USBServer(uint16_t vendor_id, uint16_t product_id) : 
    Serial(USBTX, USBRX),
    //m_hid(HID_REPORT_LENGTH, HID_REPORT_LENGTH, vendor_id, product_id),
    m_shouldTerminate(false),
    m_stat(SER_STAT_STOPPED),
    m_usbThread(NULL),
    m_recvBuf(new char[RECEIVE_BUF_SIZE]),
    m_bufPos(0),
    m_hasMsgIn(false),
    m_isReading(false)
{
    this->attach(callback(this, &USBServer::RxCallback), RxIrq);
}

USBServer::~USBServer()
{
    Serial::~Serial();
    Terminate();
}

void USBServer::Terminate()
{
    m_shouldTerminate = true;
    m_usbThread->signal_set(THREAD_SIGNAL_QUEUE);
    m_usbThread->signal_set(0xffff);
    m_usbThread->terminate();
    this->attach(NULL, RxIrq);
    delete m_usbThread;
    delete m_recvBuf;
}



void USBServer::Update(float deltaTime)
{
    if(!m_shouldTerminate && m_stat == SER_STAT_STOPPED)
    {
        if(m_usbThread)
        {
            m_usbThread->terminate();
            delete m_usbThread;
        }
        m_usbThread = new Thread(callback(this, &USBServer::ConnectingThread));
        //m_hidThread.start(callback(this, &USBServer::HIDConnectingThread));
    }
    
    if(!m_shouldTerminate && m_stat == SER_STAT_CONNECTED)
    {
        
        if(m_usbThread)
        {
            m_usbThread->terminate();
            delete m_usbThread;
        }
        m_usbThread = new Thread(callback(this, &USBServer::RunningThread));
        //m_hidThread.start(callback(this, &USBServer::HIDThread));
    }
}

bool USBServer::PushReliableMsg(const char type, const std::string & msg)
{
    if(msg.length() <= HID_REPORT_LENGTH)
    {
        m_qlocker.lock();
        m_msgQueue.push_back(type + msg);
        if(m_stat == SER_STAT_RUNNING && m_usbThread)
            m_usbThread->signal_set(THREAD_SIGNAL_QUEUE);
        m_qlocker.unlock();
        return true;
    }
    else
    {
        return false;
    }
}
    
bool USBServer::PushUnreliableMsg(const char type, const std::string & msg)
{
    if(m_stat != SER_STAT_RUNNING || m_msgQueue.size() >= UNRELIABLE_QUEUE_MAX_SIZE)
        return false;
    
    if(msg.length() <= HID_REPORT_LENGTH)
    {
        m_qlocker.lock();
        m_msgQueue.push_back(type + msg);
        if(m_stat == SER_STAT_RUNNING && m_usbThread)
            m_usbThread->signal_set(THREAD_SIGNAL_QUEUE);
        m_qlocker.unlock();
        return true;
    }
    else
    {
        return false;
    }
}

void USBServer::RunningThread()
{
    m_stat = SER_STAT_RUNNING;
    Timer tickTimer;
    tickTimer.start();
    while(!m_shouldTerminate)
    {
        //m_qlocker.lock(); m_uqlocker.lock();
        if(m_msgQueue.size() <= 0)
        {
            //m_qlocker.unlock(); m_uqlocker.unlock();
            Thread::signal_wait(THREAD_SIGNAL_QUEUE, 2000);
        }
        //m_qlocker.unlock(); m_uqlocker.unlock();
        std::string msg = "";
        if(m_msgQueue.size() > 0)
        {
            m_qlocker.lock();
            msg = m_msgQueue.front();
            m_msgQueue.pop_front();
            m_qlocker.unlock();
            
            uint16_t size = static_cast<uint16_t>(msg.size());
            this->putc('\x02');
            this->write(&size, 2);
            this->write(&(msg[0]), msg.size());
            this->putc('\x03');
            //this->printf("\x02%s\x03", msg.c_str());
        }
        
        
        
        std::string tempStr;
        if(m_hasMsgIn)
        {
            this->attach(NULL, RxIrq);
            m_recvBuf[m_bufPos] = '\0';
            tempStr = m_recvBuf;
            m_bufPos = 0;
            m_hasMsgIn = false;
            this->attach(callback(this, &USBServer::RxCallback), RxIrq);
            
            if(tempStr.compare(TICK_MSG_PC) == 0)
            {
                //PushReliableMsg('D', "Got Tick!");
                tickTimer.reset();
            }
        }
        
        if(tickTimer.read_ms() > 5000)
        {
            PushReliableMsg('D', "Time out!!");
            m_stat = SER_STAT_STOPPED;
            return;
        }
    }
    
}


void USBServer::RxCallback()
{
    char ch = this->_getc();
    if(m_bufPos >= RECEIVE_BUF_SIZE)
    {
        return;
    }
    
    if(m_hasMsgIn)
    {
        return;
    }
    
    if(!m_isReading)
    {
        //char ch = this->_getc();
        if(ch == '\x02')
        {
            m_isReading = true;
        }
    }
    else
    {
        //char ch = this->_getc();
        if(ch == '\x03')
        {
            m_isReading = false;
            m_hasMsgIn = true;
        }
        else
        {
            m_recvBuf[m_bufPos++] = ch;
        }
    }
    
    //fflush(_file);
}
    
void USBServer::ConnectingThread()
{
    m_stat = SER_STAT_CONNECTING;
    
    while(m_stat != SER_STAT_CONNECTED)
    {
        
        while(!m_hasMsgIn)
        {
            std::string strBuf = HANDSHAKE_MSG_TER;
            uint16_t size = static_cast<uint16_t>(strBuf.size());
            
            this->putc('\x02');
            this->write(&size, 2);
            this->write(&(strBuf[0]), strBuf.size());
            this->putc('\x03');
            
            //this->printf("\x02%s\x03", HANDSHAKE_MSG_TER);
            wait(1.0);
        }
        
        std::string tempStr;
        if(m_hasMsgIn)
        {
            this->attach(NULL, RxIrq);
            m_recvBuf[m_bufPos] = '\0';
            tempStr = m_recvBuf;
            m_bufPos = 0;
            m_hasMsgIn = false;
            this->attach(callback(this, &USBServer::RxCallback), RxIrq);
        }
        
        if(tempStr.compare(HANDSHAKE_MSG_PC) == 0)
        {
            PushReliableMsg('D', "Terminal Connected!");
            m_stat = SER_STAT_CONNECTED;
        }
        
    }
    
    
}


uint8_t USBServer::GetStatus() const
{
    return m_stat;
}

}