uint16_t TouchADS7843::_getPos(bool y) { uint16_t recv = 0; rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_DIV4); _cs(0); spi_xfer(SPI1, BIT7 | ((y)?BIT6:0) | BIT4 | BIT2); recv |= spi_xfer(SPI1, 0)<<8; recv |= spi_xfer(SPI1, 0); _cs(1); rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); return recv; }
//Setup hardware TouchADS7843::TouchADS7843(void) { //Enable clocks rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SPI1EN); //SPI rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); //SPI rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); //PEN_INT rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); //AFIO (EXTI) //Setup GPIO gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, BIT13); //PEN_INT gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, BIT6); //MISO gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, BIT4); //CS gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, BIT5 | BIT7); //MOSI, SCK //Set up SPI as mater _cs(1); spi_enable_software_slave_management(SPI1); spi_set_nss_high(SPI1); spi_set_baudrate_prescaler(SPI1, 7); spi_set_clock_polarity_0(SPI1); spi_set_clock_phase_0(SPI1); spi_set_dff_8bit(SPI1); spi_set_master_mode(SPI1); spi_enable(SPI1); //Enable PEN_INT nvic_enable_irq(NVIC_EXTI15_10_IRQ); exti_select_source(EXTI13, GPIOC); exti_set_trigger(EXTI13, EXTI_TRIGGER_BOTH); exti_reset_request(EXTI13); exti_enable_request(EXTI13); }
void CSQLiteLapDB::GetLastLapTimeStamp(const vector<int>& lstCarNumbers, vector<unsigned int>& lstTimeStamps) const { AutoLeaveCS _cs(&m_cs); for(int x = 0;x < lstCarNumbers.size(); x++) { const int iCar = lstCarNumbers[x]; unsigned int msLatestTime = 0; { for(map<CARNUMBERCOMBO,int>::const_iterator i = mapCarNumberRaceIds.begin(); i != mapCarNumberRaceIds.end(); i++) { if(i->first.iCarNumber == iCar) { const int iRaceId = i->second; map<int,unsigned int>::const_iterator found = mapLastRaceTimes.find(iRaceId); if(found != mapLastRaceTimes.end()) { const int msLastLapTime = found->second; msLatestTime = max(msLatestTime, msLastLapTime); // figures out which one came later } else { // nothing to do, this race doesn't have a last lap time } } } lstTimeStamps.push_back(msLatestTime); } } }
void zpt::RESTServer::start() { try { if (this->__options["http"]->ok() && this->__options["http"]["bind"]->ok() && this->__options["http"]["port"]->ok()) { std::shared_ptr< std::thread > _http( new std::thread( [ & ] () -> void { zlog(std::string("starting HTTP listener on port ") + std::to_string((uint) this->__options["http"]["port"]), zpt::notice); zpt::serversocketstream_ptr _ss(new zpt::serversocketstream()); _ss->bind((uint) this->__options["http"]["port"]); for (; true; ) { int _fd = -1; _ss->accept(& _fd); zpt::socketstream_ptr _cs(new zpt::socketstream(_fd)); try { if (this->route_http(_cs)) { _cs->close(); } } catch(zpt::AssertionException& _e) { zpt::http::rep _reply = zpt::rest::zmq2http( { "performative", zpt::ev::Reply, "status", 500, "headers", zpt::ev::init_reply(), "payload", { "text", _e.what(), "assertion_failed", _e.description(), "code", _e.code() } } ); (*_cs) << _reply << flush; _cs->close(); } } } ) ); this->__threads.push_back(_http); } this->__poll->loop(); for (auto _thread : this->__threads) { _thread->join(); } } catch (zpt::InterruptedException& e) { return; } }
void CSQLiteLapDB::AddDataChannel(const IDataChannel* pChannel) { AutoLeaveCS _cs(&m_cs); m_sfDB.StartTransaction(); bool fSuccess = true; CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert into channels (lapid,channeltype) values (?,?)")) { sfQuery.BindValue(pChannel->GetLapId()); sfQuery.BindValue((int)pChannel->GetChannelType()); if(sfQuery.Next() || sfQuery.IsDone()) { // inserted new data, hooray! long long lastInsert = m_sfDB.GetLastInsertId(); vector<DataPoint> lstPoints = pChannel->GetData(); for(int x = 0;x < lstPoints.size(); x++) { const DataPoint& pt = lstPoints[x]; sfQuery.DeInit(); if(sfQuery.Init(L"insert into data (time,value,channelid) values (?,?,?)")) { sfQuery.BindValue(pt.iTimeMs); sfQuery.BindValue(pt.flValue); sfQuery.BindValue(lastInsert); if(!sfQuery.Next() && !sfQuery.IsDone()) { fSuccess = false; break; } } } } else { fSuccess = false; } } if(fSuccess) { m_pUI->NotifyChange(NOTIFY_NEWDATA,(LPARAM)this); } m_sfDB.StopTransaction(); }
const ILap* CSQLiteLapDB::GetLap(int iLapId) { AutoLeaveCS _cs(&m_cs); CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"Select laps._id,laps.laptime, laps.unixtime from laps where laps._id = %d", iLapId); if(sfQuery.Init(szQuery)) { if(sfQuery.Next()) { CSQLiteLap* pLap = (CSQLiteLap*)AllocateLap(false); pLap->Load(m_sfDB,m_rgSF,sfQuery); return pLap; } } return NULL; }
void CSQLiteLapDB::GetComments(int iLapId, vector<wstring>& lstComments) const { AutoLeaveCS _cs(&m_cs); CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select extras.comment from extras where extras.lapid = %d", iLapId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { TCHAR szComment[500]; if(sfQuery.GetCol(0,szComment, NUMCHARS(szComment))) { lstComments.push_back(szComment); } } } }
const IDataChannel* CSQLiteLapDB::GetDataChannel(int iLapId, DATA_CHANNEL eChannel) const { AutoLeaveCS _cs(&m_cs); if(eChannel == DATA_CHANNEL_VELOCITY) { // since velocity is stored as part of the points table, it is a bit different than the normal data channels CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select points.time, points.velocity from points where lapid=%d", iLapId); if(sfQuery.Init(szQuery)) { IDataChannel* pChannel = AllocateDataChannel(); pChannel->Init(iLapId,DATA_CHANNEL_VELOCITY); while(sfQuery.Next()) { int iTime = 0; double dVel = 0; if(sfQuery.GetCol(0,&iTime) && sfQuery.GetCol(1,&dVel)) { pChannel->AddPoint(iTime, dVel); } } pChannel->Lock(); return pChannel; } } else { CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select channels._id, channels.lapid, channels.channeltype from channels where channels.lapid = %d and channels.channeltype=%d", iLapId, eChannel); if(sfQuery.Init(szQuery)) { if(sfQuery.Next()) { IDataChannel* pChannel = AllocateDataChannel(); pChannel->Load(m_sfDB,sfQuery,true); // warning: massive memory leaks here return pChannel; } } } return NULL; }
bool CSQLiteLapDB::InitRaceSession(int* piRaceId, LPCTSTR lpszRaceName) { AutoLeaveCS _cs(&m_cs); bool fSuccess = true; CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert into races (name,date) values (?,?)")) { sfQuery.BindValue(lpszRaceName); sfQuery.BindValue(GetSecondsSince1970()); if(sfQuery.Next() || sfQuery.IsDone()) { // inserted new data, hooray! long long lastInsert = m_sfDB.GetLastInsertId(); *piRaceId = lastInsert; return true; } } return false; }
int CSQLiteLapDB::GetLapCount(int iRaceId) const { AutoLeaveCS _cs(&m_cs); CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select count(laps._id) from races,laps where races._id = %d and laps.raceid=races._id group by races._id", iRaceId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { int cLaps = 0; if(sfQuery.GetCol(0,&cLaps)) { return cLaps; } } } return 0; }
set<DATA_CHANNEL> CSQLiteLapDB::GetAvailableChannels(int iLapId) const { AutoLeaveCS _cs(&m_cs); set<DATA_CHANNEL> setRet; CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select channels.channeltype from channels where channels.lapid = %d", iLapId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { DATA_CHANNEL eType; if(sfQuery.GetCol(0,(int*)&eType)) { setRet.insert(eType); } } } return setRet; }
vector<const ILap*> CSQLiteLapDB::GetLaps(int iRaceId) { AutoLeaveCS _cs(&m_cs); vector<const ILap*> lstLaps; // gotta load all the laps that are in the DB, but we don't want to fully load them, just their laptimes and other directly lap-related data CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"Select laps._id,laps.laptime, laps.unixtime,extras.comment from laps left join extras on extras.lapid = laps._id where laps.raceid=%d", iRaceId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { CSQLiteLap* pLap = (CSQLiteLap*)AllocateLap(false); pLap->Load(m_sfDB,m_rgSF,sfQuery); if(pLap->IsValid()) { lstLaps.push_back(pLap); } } } return lstLaps; }
vector<RACEDATA> CSQLiteLapDB::GetRaces() { AutoLeaveCS _cs(&m_cs); vector<RACEDATA> lstRaces; CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select races.name,races.date,count(laps._id),races._id from races,laps where laps.raceid=races._id group by races._id"); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { RACEDATA raceData; TCHAR szData[1000]; if(sfQuery.GetCol(0,szData,NUMCHARS(szData))) { raceData.strName = szData; int iRaceDate = 0; if(sfQuery.GetCol(1,&iRaceDate)) { raceData.unixtime = iRaceDate; } int cLaps = 0; if(sfQuery.GetCol(2,&cLaps)) { raceData.laps = cLaps; } int iRaceId = 0; if(sfQuery.GetCol(3,&iRaceId)) { raceData.raceId = iRaceId; } lstRaces.push_back(raceData); } } } return lstRaces; }
void CSQLiteLapDB::NotifyDBArrival(LPCTSTR szPath) { AutoLeaveCS _cs(&m_cs); wcscpy(szLastNetStatus[NETSTATUS_DB],szPath); m_pUI->NotifyChange(NOTIFY_NEWDATABASE,(LPARAM)szLastNetStatus[NETSTATUS_DB]); }
double utl::Args::toDouble(size_t pos) const { _cs(); _ss << this->at(pos); double n; _ss >> n; return n;}
char utl::Args::toChar(size_t pos) const { _cs(); _ss << this->at(pos); char n; _ss >> n; return n;}
void CSQLiteLapDB::SetNetStatus(NETSTATUSSTRING eString, LPCTSTR sz) { AutoLeaveCS _cs(&m_cs); wcscpy(szLastNetStatus[eString], sz); m_pUI->NotifyChange(NOTIFY_NEWNETSTATUS,(LPARAM)this); }
size_t utl::Args::toSizet(size_t pos) const { _cs(); _ss << this->at(pos); size_t n; _ss >> n; return n;}
void CSQLiteLapDB::AddLap(const ILap* pLap, int _iRaceId) { AutoLeaveCS _cs(&m_cs); CARNUMBERCOMBO sfCarNumber = pLap->GetCarNumbers(); int iSaveRaceId = -1; if(mapCarNumberRaceIds.find(sfCarNumber) == mapCarNumberRaceIds.end()) { // we've never seen this car number combo before. Time for a new race. TCHAR szRaceName[200]; if(sfCarNumber.IsOldVersion()) { _snwprintf(szRaceName,NUMCHARS(szRaceName),L"Received from old wifilappers"); } else { _snwprintf(szRaceName,NUMCHARS(szRaceName),L"Received laps (car %d) - (%d)", sfCarNumber.iCarNumber, sfCarNumber.iSecondaryCarNumber); } int iNewRaceId = -1; if(InitRaceSession(&iNewRaceId,szRaceName)) { mapCarNumberRaceIds[sfCarNumber] = iNewRaceId; iSaveRaceId = iNewRaceId; } else { return; } } else { iSaveRaceId = mapCarNumberRaceIds[sfCarNumber]; } m_setReceivingIds.insert(iSaveRaceId); // this race ID received a lap m_iLastRaceId = iSaveRaceId; m_sfDB.StartTransaction(); bool fSuccess = true; CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert into laps (_id,laptime,unixtime,transmitted,raceid) values (?,?,?,?,?)")) { sfQuery.BindValue(pLap->GetLapId()); sfQuery.BindValue(pLap->GetTime()); sfQuery.BindValue(pLap->GetStartTime()); sfQuery.BindValue(0); sfQuery.BindValue(iSaveRaceId); if(sfQuery.Next() || sfQuery.IsDone()) { // inserted new data, hooray! vector<TimePoint2D> lstPoints = pLap->GetPoints(); for(int x = 0;x < lstPoints.size(); x++) { const TimePoint2D& pt = lstPoints[x]; sfQuery.DeInit(); if(sfQuery.Init(L"insert into points (x,y,time,velocity,lapid) values (?,?,?,?,?)")) { sfQuery.BindValue(pt.flX); sfQuery.BindValue(pt.flY); sfQuery.BindValue(pt.iTime); sfQuery.BindValue(pt.flVelocity); sfQuery.BindValue(pLap->GetLapId()); if(!sfQuery.Next() && !sfQuery.IsDone()) { fSuccess = false; break; } } } } else { fSuccess = false; } } if(fSuccess) { mapLastRaceTimes[iSaveRaceId] = timeGetTime(); m_pUI->NotifyChange(NOTIFY_NEWLAP,(LPARAM)this); } m_sfDB.StopTransaction(); }
void CSQLiteLapDB::DeInit() { AutoLeaveCS _cs(&m_cs); m_sfDB.Close(); }
utl::Args& utl::Args::operator <<(double a) { _cs(); _ss << a; this->push_back(_ss.str()); return *this;}
void CSQLiteLapDB::FreeDataChannel(IDataChannel* pChannel) const { AutoLeaveCS _cs(&m_cs); cChannels--; delete pChannel; }
IDataChannel* CSQLiteLapDB::AllocateDataChannel() const { AutoLeaveCS _cs(&m_cs); cChannels++; return new CDataChannel(); }
std::string utl::Args::toString(size_t pos) const { _cs(); _ss << this->at(pos); std::string n; _ss >> n; return n;}
float utl::Args::toFloat(size_t pos) const { _cs(); _ss << this->at(pos); float n; _ss >> n; return n;}
int utl::Args::toInt(size_t pos) const { _cs(); _ss << this->at(pos); int n; _ss >> n; return n;}
bool CSQLiteLapDB::IsActivelyReceiving(int iRaceId) const { AutoLeaveCS _cs(&m_cs); return this->m_setReceivingIds.find(iRaceId) != m_setReceivingIds.end(); }
int CSQLiteLapDB::GetLastReceivedRaceId() const { AutoLeaveCS _cs(&m_cs); DASSERT(m_iLastRaceId >= 0); // you shouldn't be calling this unless there's evidence we've received a lap! return m_iLastRaceId; }
utl::Args& utl::Args::operator <<(std::string a) { _cs(); _ss << a; this->push_back(_ss.str()); return *this;}
unsigned int utl::Args::toUnsigned(size_t pos) const { _cs(); _ss << this->at(pos); unsigned int n; _ss >> n; return n;}