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

PCConnector/SWUSBServer.cpp

Committer:
hazheng
Date:
2017-02-11
Revision:
18:bf6c5f8281eb
Parent:
17:84acc292b4c2
Child:
19:c93f7fab165d

File content as of revision 18:bf6c5f8281eb:

#include "SWUSBServer.h"

#define THREAD_SIGNAL_QUEUE 0xa
#define UNRELIABLE_QUEUE_MAX_SIZE 5

#include "USBSerial.h"

namespace
{
    char recvBuf[100];
    size_t pos = 0;
    bool hasMsg = false;
    bool isReading = false;
}

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_tickMsgTimer(0.0f)
{
    this->attach(callback(this, &USBServer::RxCallback), RxIrq);
}

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

void USBServer::Terminate()
{
    m_shouldTerminate = true;
    m_usbThread->signal_set(THREAD_SIGNAL_QUEUE);
    m_usbThread->signal_set(0xffff);
    m_usbThread->terminate();
    delete m_usbThread;
}



void USBServer::Update(float deltaTime)
{
    m_tickMsgTimer += 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)
    {
        PushReliableMsg('D', "Terminal 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;
    
    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);
        }
        //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();
        }
        
        this->printf("\x02%s\x03", msg.c_str());
    }
    
}


void USBServer::RxCallback()
{
    
    if(!isReading && !hasMsg)
    {
        char ch = this->_getc();
        if(ch == '\x02')
        {
            isReading = true;
        }
    }
    
    while(this->readable())
    {
        char ch = this->_getc();
        if(ch == '\x03')
        {
            isReading = false;
            hasMsg = true;
        }
        else
        {
            recvBuf[pos++] = ch;
        }
    }
}
    
void USBServer::ConnectingThread()
{
    m_stat = SER_STAT_CONNECTING;
    
    while(m_stat != SER_STAT_CONNECTED)
    {
        
        while(!hasMsg)
        {
            this->printf("\x02%s\x03", HANDSHAKE_MSG_TER);
            wait(1.0);
        }
        
        std::string tempStr;
        if(hasMsg)
        {
            this->attach(NULL, RxIrq);
            recvBuf[pos] = '\0';
            tempStr = recvBuf;
            pos = 0;
            hasMsg = false;
            this->attach(callback(this, &USBServer::RxCallback), RxIrq);
        }
        
        if(tempStr.compare(HANDSHAKE_MSG_PC) == 0)
        {
            m_stat = SER_STAT_CONNECTED;
        }
        
    }
    
    
}


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

}