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
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; } }