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-10
Revision:
17:84acc292b4c2
Parent:
16:66c7a09e71ee
Child:
18:bf6c5f8281eb

File content as of revision 17:84acc292b4c2:

#include "SWUSBServer.h"

#define THREAD_SIGNAL_QUEUE 0xa
#define UNRELIABLE_QUEUE_MAX_SIZE 5

#include "USBSerial.h"

namespace SW{

USBServer::USBServer(uint16_t vendor_id, uint16_t product_id) : 
    //m_hid(HID_REPORT_LENGTH, HID_REPORT_LENGTH, vendor_id, product_id),
    m_shouldTerminate(false),
    m_stat(SER_STAT_STOPPED),
    m_usbThread(NULL),
    m_usb(NULL),
    m_tickMsgTimer(0.0f)
{
    
}

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

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

void USBServer::Update(float deltaTime)
{
    m_tickMsgTimer += deltaTime;
    if(!m_shouldTerminate && m_stat == SER_STAT_STOPPED)
    {
        if(m_usbThread)
        {
            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)
        {
            delete m_usbThread;
        }
        m_usbThread = new Thread(callback(this, &USBServer::RunningThread));
        //m_hidThread.start(callback(this, &USBServer::HIDThread));
    }
    
    //char buf[15];
    if(m_tickMsgTimer >= 2.0f)
    {
        //sprintf(buf, "%s,%f", TICKING_MSG, m_tickMsgTimer);
        PushReliableMsg('T', TICKING_MSG);
        m_tickMsgTimer = 0.0f;
    }
}

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();
        }
        
        m_usb->printf("%s\n", msg.c_str());
    }
    
}
    
void USBServer::ConnectingThread()
{
    m_stat = SER_STAT_CONNECTING;
    
    m_usb = new Serial(USBTX, USBRX, "SmartWheels");
    
    while(m_stat != SER_STAT_CONNECTED)
    {
        
        while(!m_usb->readable())
        {
            m_usb->printf("\x02%s\x03", HANDSHAKE_MSG_TER);
            wait(1.0);
        }
        
        char chBuf = m_usb->getc();
        if(chBuf == '\x02')
        {
            std::string strBuf;
            while(chBuf != '\x03')
            {
                chBuf = m_usb->getc();
                if(chBuf != '\x03')
                    strBuf.push_back(chBuf);
            }
            
            if(strBuf.compare(HANDSHAKE_MSG_PC) == 0)
            {
                m_stat = SER_STAT_CONNECTED;
            }
        }
    }
    
}


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

}