diff --git a/application/ldscripts/mem.ld b/application/ldscripts/mem.ld index 0e8365f..795afea 100644 --- a/application/ldscripts/mem.ld +++ b/application/ldscripts/mem.ld @@ -15,7 +15,8 @@ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 40K CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 0K - FLASH (rx) : ORIGIN = 0x08004000, LENGTH = 112K + FLASH (rx) : ORIGIN = 0x08004000, LENGTH = 112K + /* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K */ FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0 EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0 EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0 diff --git a/application/src/AISMessages.cpp b/application/src/AISMessages.cpp index 113eb9c..69ba3a1 100644 --- a/application/src/AISMessages.cpp +++ b/application/src/AISMessages.cpp @@ -43,7 +43,7 @@ uint32_t AISMessage::mmsi() const return mMMSI; } -bool AISMessage::decode(RXPacket &) +bool AISMessage::decode(const RXPacket &) { // The base class method should never be called ASSERT(false); @@ -211,7 +211,7 @@ AISMessage123::AISMessage123() { } -bool AISMessage123::decode(RXPacket &packet) +bool AISMessage123::decode(const RXPacket &packet) { mType = packet.messageType(); mRI = packet.repeatIndicator(); @@ -312,7 +312,7 @@ void AISMessage18::encode(const StationData &station, TXPacket &packet) finalize(payload, size, packet); } -bool AISMessage18::decode(RXPacket &packet) +bool AISMessage18::decode(const RXPacket &packet) { mType = packet.messageType(); mRI = packet.repeatIndicator(); diff --git a/application/src/AISMessages.hpp b/application/src/AISMessages.hpp index 5baba52..2ba8076 100644 --- a/application/src/AISMessages.hpp +++ b/application/src/AISMessages.hpp @@ -29,7 +29,7 @@ public: AISMessage (); virtual ~AISMessage (); - virtual bool decode(RXPacket &packet); + virtual bool decode(const RXPacket &packet); virtual void encode(const StationData &station, TXPacket &packet); uint8_t type() const; @@ -65,7 +65,7 @@ public: AISMessage123(); - bool decode(RXPacket &packet); + bool decode(const RXPacket &packet); }; class AISMessage18 : public AISMessage @@ -79,7 +79,7 @@ public: AISMessage18(); - bool decode(RXPacket &packet); + bool decode(const RXPacket &packet); void encode(const StationData &data, TXPacket &packet); }; diff --git a/application/src/ChannelManager.cpp b/application/src/ChannelManager.cpp index ec45e04..f8b29ff 100644 --- a/application/src/ChannelManager.cpp +++ b/application/src/ChannelManager.cpp @@ -44,7 +44,7 @@ bool ChannelManager::channelsDetermined() return true; } -void ChannelManager::processEvent(Event *) +void ChannelManager::processEvent(const Event &) { //AISPacketEvent *pe = static_cast(e); } diff --git a/application/src/ChannelManager.hpp b/application/src/ChannelManager.hpp index ef63cd6..2042f1a 100644 --- a/application/src/ChannelManager.hpp +++ b/application/src/ChannelManager.hpp @@ -17,7 +17,7 @@ public: static ChannelManager &instance(); virtual ~ChannelManager(); - void processEvent(Event *e); + void processEvent(const Event &e); const ais_channel &channelA(); const ais_channel &channelB(); diff --git a/application/src/DataTerminal.cpp b/application/src/DataTerminal.cpp index a9ab2ab..93a771c 100644 --- a/application/src/DataTerminal.cpp +++ b/application/src/DataTerminal.cpp @@ -12,9 +12,13 @@ #include "MenuScreens.hpp" #include "Events.hpp" #include +#include "Utils.hpp" +#include #ifdef ENABLE_TERMINAL +static char __buff[128]; + DataTerminal &DataTerminal::instance() { static DataTerminal __instance; @@ -62,45 +66,60 @@ void DataTerminal::init() } DataTerminal::DataTerminal() - : mEscapes(0), mCurrentScreen(MAIN_SCREEN), mInteractive(false) + : mCmdBuffPos(0) { - EventQueue::instance().addObserver(this, CLOCK_EVENT|KEYPRESS_EVENT); + mCmdTokens.reserve(5); + EventQueue::instance().addObserver(this, RESPONSE_EVENT); } -void DataTerminal::processEvent(Event *e) +void DataTerminal::processEvent(const Event &e) { - if ( e->type() == CLOCK_EVENT ) { - ClockEvent *c = static_cast(e); - if ( c->mTime % 2 == 0 ) { - mEscapes = 0; - } - } - else if ( e->type() == KEYPRESS_EVENT ) { - KeyPressEvent *k = static_cast(e); - processCharacter(k->key); + switch (e.type) { + case RESPONSE_EVENT: + sprintf(__buff, "[%s]%s\r\n", (e.response.success ? "OK" : "ERR"), e.response.data); + write("RESPONSE", __buff); + break; + default: + break; } } void DataTerminal::processCharacter(char c) { - if ( !mInteractive ) { - if ( c == 27 ) - ++mEscapes; - - if ( mEscapes == 3 ) { - mInteractive = true; - printf2("Entering interactive mode\r\n"); - showScreen(MAIN_SCREEN); - } + if ( c == 13 ) { + mCmdBuffer[mCmdBuffPos] = 0; + mCmdBuffPos = 0; + processCommand(); } else { - if ( c == 13 ) { - clearScreen(); - printf2("Exiting interactive mode\r\n"); - mInteractive = false; - } - } + mCmdBuffer[mCmdBuffPos++] = c; + if (mCmdBuffPos >= sizeof mCmdBuffer) + mCmdBuffPos = 0; + } +} + +void DataTerminal::processCommand() +{ + string s(mCmdBuffer); + Utils::trim(s); + Utils::tokenize(s, ' ', mCmdTokens); + + if ( mCmdTokens[0] == "set" && mCmdTokens.size() >= 3 ) { + // TODO: Extract field and value and queue a command event + Event *e = EventPool::instance().newEvent(REQUEST_EVENT); + e->request.operation = OP_SET; + strncpy(e->request.field, mCmdTokens[1].c_str(), sizeof e->request.field); + strncpy(e->request.value, mCmdTokens[2].c_str(), sizeof e->request.value); + EventQueue::instance().push(e); + } + else if ( mCmdTokens[0] == "get" && mCmdTokens.size() >= 2 ) { + // TODO: Extract field + Event *e = EventPool::instance().newEvent(REQUEST_EVENT); + e->request.operation = OP_GET; + strncpy(e->request.field, mCmdTokens[1].c_str(), sizeof e->request.field); + EventQueue::instance().push(e); + } } void write_char(USART_TypeDef* USARTx, char c) @@ -113,11 +132,8 @@ void write_char(USART_TypeDef* USARTx, char c) #ifdef MULTIPLEXED_OUTPUT -void DataTerminal::write(const char *cls, const char* s, bool interactive) +void DataTerminal::write(const char *cls, const char* s) { - if ( mInteractive && !interactive ) - return; - write_char(USART3, '['); for ( size_t i = 0; i < strlen(cls); ++i ) write_char(USART3, cls[i]); @@ -140,60 +156,17 @@ void DataTerminal::write(const char* s, bool interactive) } #endif -void DataTerminal::clearScreen() -{ - _write("\033[2J"); - _write("\033[H"); -} + void DataTerminal::_write(const char *s) { #ifdef MULTIPLEXED_OUTPUT - write("", s, true); + write("", s); #else - write(s, true); + write(s); #endif } -void DataTerminal::showScreen(MenuScreen screen) -{ - char buff[100]; - switch(screen) { - case MAIN_SCREEN: { - clearScreen(); - //_write("****************************** Interactive Mode ******************************\r\n"); - //_write("NOTICE: IT IS AGAINST USCG REGULATIONS FOR END USERS TO ALTER THEIR MMSI,\r\n"); - //_write("STATION NAME AND CALL SIGN AFTER INITIAL INSTALLATION.\r\n"); - //_write("IF YOUR UNIT HAS BEEN FACTORY PROGRAMMED, THIS TERMINAL WILL PROMPT YOU\r\n"); - //_write("FOR A SPECIAL CODE BEFORE ALLOWING THIS OPERATION. YOU CAN ONLY OBTAIN THE\r\n"); - //_write("CODE BY CONTACTING US AND PROVIDING THE UNIT'S SERIAL NUMBER AND CURRENT MMSI.\r\n\r\n"); - sprintf(buff, "Model: %s\r\n", MODEL); - _write(buff); - sprintf(buff, "Software revision: %s\r\n", REVISION); - _write(buff); -#if 0 - sprintf(buff, "MMSI: %d\r\n", STATION_MMSI); - _write(buff); - sprintf(buff, "Name: %s\r\n", STATION_NAME); - _write(buff); - sprintf(buff, "Call sign: %s\r\n", STATION_CALLSIGN); - _write(buff); -#endif - _write("\r\n"); - _write("****************************** AIS Transponder Menu ******************************\r\n\r\n"); - _write("\t\033[1mP\033[0m\tProgram MMSI, station name and call sign \r\n"); - _write("\t\033[1mD\033[0m\tPerform diagnostics \r\n"); - _write("\t\033[1m\033[0m\tReturn to AIS data mode\r\n\r\n"); - _write("**********************************************************************************\r\n\r\n"); - //_write("Note: The device will automatically return to AIS data mode if rebooted.\r\n"); - break; - } - case PROGRAMMING_SCREEN: - break; - } - - mCurrentScreen = screen; -} extern "C" { @@ -201,13 +174,7 @@ void USART3_IRQHandler(void) { if ( USART_GetITStatus(USART3, USART_IT_RXNE) ) { char c = (char) USART3->RDR; // This clears the interrupt right away - KeyPressEvent *e = static_cast(EventPool::instance().newEvent(KEYPRESS_EVENT)); - if ( e == NULL ) - return; - - e->key = c; - EventQueue::instance().push(e); - //DataTerminal::instance().processCharacter(c); + DataTerminal::instance().processCharacter(c); } } diff --git a/application/src/DataTerminal.hpp b/application/src/DataTerminal.hpp index 0db228d..3f31a47 100644 --- a/application/src/DataTerminal.hpp +++ b/application/src/DataTerminal.hpp @@ -10,6 +10,11 @@ #include "globals.h" #include "EventQueue.hpp" +#include +#include + +using namespace std; + #ifdef ENABLE_TERMINAL @@ -20,31 +25,22 @@ public: void init(); - void processEvent(Event *e); + void processEvent(const Event &e); #ifdef MULTIPLEXED_OUTPUT - void write(const char* cls, const char* line, bool interactive=false); + void write(const char* cls, const char* line); #else - void write(const char* line, bool interactive = false); + void write(const char* line); #endif void processCharacter(char c); private: DataTerminal(); + void processCommand(); - typedef enum { - MAIN_SCREEN = 0, - PROGRAMMING_SCREEN = 1 - } - MenuScreen; - - void showScreen(MenuScreen s); - - void clearScreen(); void _write(const char* s); private: - //uint32_t mTimeSlot; - uint8_t mEscapes; - MenuScreen mCurrentScreen; - bool mInteractive; + char mCmdBuffer[64]; + size_t mCmdBuffPos; + vector mCmdTokens; }; #endif diff --git a/application/src/DebugPrinter.cpp b/application/src/DebugPrinter.cpp index d48a5e7..bdd2614 100644 --- a/application/src/DebugPrinter.cpp +++ b/application/src/DebugPrinter.cpp @@ -18,9 +18,9 @@ DebugPrinter::~DebugPrinter() { } -void DebugPrinter::processEvent(Event *e) +void DebugPrinter::processEvent(const Event &e) { - DebugEvent *event = static_cast(e); - printf2(event->mBuffer); + //DebugEvent *event = static_cast(e); + printf2(e.debugMessage.buffer); } diff --git a/application/src/DebugPrinter.hpp b/application/src/DebugPrinter.hpp index 344096d..befec12 100644 --- a/application/src/DebugPrinter.hpp +++ b/application/src/DebugPrinter.hpp @@ -16,7 +16,7 @@ public: DebugPrinter(); virtual ~DebugPrinter(); - void processEvent(Event* e); + void processEvent(const Event &e); }; #endif /* DEBUGPRINTER_HPP_ */ diff --git a/application/src/EventQueue.cpp b/application/src/EventQueue.cpp index b7f7312..00eab24 100644 --- a/application/src/EventQueue.cpp +++ b/application/src/EventQueue.cpp @@ -58,11 +58,11 @@ void EventQueue::dispatch() for ( map::iterator c = mConsumers.begin(); c != mConsumers.end(); ++c ) { // Utils::delay(1000); - if ( c->second & e->type() ) - c->first->processEvent(e); + if ( c->second & e->type ) + c->first->processEvent(*e); } EventPool::instance().deleteEvent(e); - if ( e->type() == AIS_PACKET_EVENT ) + if ( e->type == AIS_PACKET_EVENT ) LEDManager::instance().blink(LEDManager::GREEN_LED); } } diff --git a/application/src/EventTypes.h b/application/src/EventTypes.h index 1a0b107..c6d63d9 100644 --- a/application/src/EventTypes.h +++ b/application/src/EventTypes.h @@ -22,7 +22,9 @@ typedef enum { AIS_PACKET_EVENT = 8, // A packet was just decoded (not necessarily valid, must still be CRC checked, etc) INTERROGATION_EVENT = 16, DEBUG_EVENT = 32, - KEYPRESS_EVENT = 64 + KEYPRESS_EVENT = 64, + REQUEST_EVENT = 128, + RESPONSE_EVENT = 256 //GPS_ERROR_EVENT = 64, // A GPS failure //TRX_ERROR_EVENT = 128 // A radio failure } diff --git a/application/src/Events.cpp b/application/src/Events.cpp index 58137da..e816e32 100644 --- a/application/src/Events.cpp +++ b/application/src/Events.cpp @@ -17,89 +17,19 @@ EventPool &EventPool::instance() void EventPool::init() { - mGenericPool = new ObjectPool(10); - mAISPacketPool = new ObjectPool(40); - mGPSNMEAPool = new ObjectPool(20); - mGPSFixPool = new ObjectPool(10); - mClockPool = new ObjectPool(10); - mDebugEventPool = new ObjectPool(2); - mKeyPressPool = new ObjectPool(20); + mGenericPool = new ObjectPool(40); } Event *EventPool::newEvent(EventType type) { - Event *result = NULL; - switch(type) { - case GPS_NMEA_SENTENCE: - result = mGPSNMEAPool->get(); - break; - case GPS_FIX_EVENT: - result = mGPSFixPool->get(); - break; - case CLOCK_EVENT: - result = mClockPool->get(); - break; - case AIS_PACKET_EVENT: { - result = mAISPacketPool->get(); - break; - } - case DEBUG_EVENT: { - result = mDebugEventPool->get(); - break; - } - case KEYPRESS_EVENT: { - result = mKeyPressPool->get(); - break; - } - default: - result = mGenericPool->get(); - result->mType = type; - break; - } - - if ( result ) - result->prepare(); - + Event *result = mGenericPool->get(); + result->type = type; return result; + } void EventPool::deleteEvent(Event *event) { - event->clear(); - switch(event->type()) { - case GPS_NMEA_SENTENCE: { - GPSNMEASentence *e = static_cast(event); - mGPSNMEAPool->put(e); - break; - } - case GPS_FIX_EVENT: { - GPSFIXEvent *e = static_cast(event); - mGPSFixPool->put(e); - break; - } - case CLOCK_EVENT:{ - ClockEvent *e = static_cast(event); - mClockPool->put(e); - break; - } - case AIS_PACKET_EVENT: { - AISPacketEvent *p = static_cast(event); - mAISPacketPool->put(p); - break; - } - case DEBUG_EVENT: { - DebugEvent *e = static_cast(event); - mDebugEventPool->put(e); - break; - } - case KEYPRESS_EVENT: { - KeyPressEvent *e = static_cast(event); - mKeyPressPool->put(e); - break; - } - default: - mGenericPool->put(event); - break; - } + mGenericPool->put(event); } diff --git a/application/src/Events.hpp b/application/src/Events.hpp index dab1cd3..d0a108e 100644 --- a/application/src/Events.hpp +++ b/application/src/Events.hpp @@ -19,37 +19,64 @@ using namespace std; +typedef struct { + char sentence[100]; +} NMEABuffer; + +typedef struct { + time_t utc; + double lat; + double lng; + double speed; + double cog; +} GPSFix; + +typedef struct { + time_t utc; +} ClockTick; + +typedef struct { + char buffer[128]; +} DebugMessage; + +typedef enum { + OP_GET, + OP_SET +} Operation; + + +typedef struct { + Operation operation; + char field[16]; + char value[64]; +} Request; + +typedef struct { + bool success; + char data[64]; +} Response; -/* - * All events extend this class - */ class Event { - friend class EventPool; public: + EventType type; + Event() - : mType(UNKNOWN_EVENT) { + : type(UNKNOWN_EVENT) { } - Event (EventType type): mType(type) { - } - - virtual ~Event () { - } - - virtual void prepare() { - } - - virtual void clear() { - } - - virtual EventType type() { - return mType; - } -protected: - EventType mType; + union { + NMEABuffer nmeaBuffer; + GPSFix gpsFix; + DebugMessage debugMessage; + RXPacket rxPacket; + ClockTick clock; + Request request; + Response response; + }; }; + /* * Event consumer abstract definition. */ @@ -58,87 +85,7 @@ class EventConsumer { public: virtual ~EventConsumer() {} - virtual void processEvent(Event *event)=0; -}; - -class GPSNMEASentence : public Event -{ -public: - GPSNMEASentence() - : Event(GPS_NMEA_SENTENCE){ - } - - char mSentence[100]; -}; - -class GPSFIXEvent: public Event -{ -public: - GPSFIXEvent() - : Event(GPS_FIX_EVENT) { - } - - time_t mUTC; - double mLat; - double mLng; - double mSpeed; - double mCOG; -}; - -class ClockEvent : public Event -{ -public: - ClockEvent() - : Event(CLOCK_EVENT) { - } - - - time_t mTime; -}; - -class AISPacketEvent: public Event -{ -public: - AISPacketEvent() - : Event(AIS_PACKET_EVENT) { - } - - - void prepare() - { - //mPacket = RXPacketPool::instance().newRXPacket(); - //mPacket->reset(); - } - - void clear() - { - RXPacketPool::instance().deleteRXPacket(mPacket); - mPacket = NULL; - } - - RXPacket *mPacket; -}; - - -class DebugEvent: public Event -{ -public: - DebugEvent() - : Event(DEBUG_EVENT) { - } - - char mBuffer[256]; -}; - -class KeyPressEvent : public Event -{ -public: - KeyPressEvent() - : Event(KEYPRESS_EVENT) { - } - - - char key; + virtual void processEvent(const Event &event)=0; }; class EventPool @@ -152,12 +99,6 @@ public: private: ObjectPool *mGenericPool; - ObjectPool *mAISPacketPool; - ObjectPool *mGPSNMEAPool; - ObjectPool *mGPSFixPool; - ObjectPool *mClockPool; - ObjectPool *mDebugEventPool; - ObjectPool *mKeyPressPool; }; diff --git a/application/src/GPS.cpp b/application/src/GPS.cpp index 53c577e..c8dea5d 100644 --- a/application/src/GPS.cpp +++ b/application/src/GPS.cpp @@ -161,9 +161,9 @@ void GPS::onRX(char c) } else if (c == '\n') { mBuff[mBuffPos] = 0; - GPSNMEASentence *event = static_cast(EventPool::instance().newEvent(GPS_NMEA_SENTENCE)); + Event *event = EventPool::instance().newEvent(GPS_NMEA_SENTENCE); if ( event ) { - memcpy(event->mSentence, mBuff, sizeof event->mSentence); + memcpy(event->nmeaBuffer.sentence, mBuff, sizeof event->nmeaBuffer.sentence); EventQueue::instance ().push (event); } mBuffPos = 0; @@ -203,20 +203,20 @@ void GPS::onPPS() } } - ClockEvent *event = static_cast(EventPool::instance().newEvent(CLOCK_EVENT)); + Event *event = EventPool::instance().newEvent(CLOCK_EVENT); if ( event ) { - event->mTime = mUTC; + event->clock.utc = mUTC; EventQueue::instance ().push(event); } } // We have a valid UTC timestamp } -void GPS::processEvent(Event *event) +void GPS::processEvent(const Event &event) { //printf2("-> GPS::processEvent()\r\n"); - GPSNMEASentence *s = static_cast(event); - processLine(s->mSentence); + + processLine(event.nmeaBuffer.sentence); //printf2("<- GPS::processEvent()\r\n"); } @@ -295,13 +295,13 @@ void GPS::parseSentence(const char *buff) mLng = Utils::longitudeFromNMEA(sentence.fields()[5], sentence.fields()[6]); mSpeed = Utils::toDouble(sentence.fields()[7]); mCOG = Utils::toDouble(sentence.fields()[8]); - GPSFIXEvent *event = static_cast(EventPool::instance().newEvent(GPS_FIX_EVENT)); + Event *event = EventPool::instance().newEvent(GPS_FIX_EVENT); if ( event ) { - event->mUTC = mUTC; - event->mLat = mLat; - event->mLng = mLng; - event->mSpeed = mSpeed; - event->mCOG = mCOG; + event->gpsFix.utc = mUTC; + event->gpsFix.lat = mLat; + event->gpsFix.lng = mLng; + event->gpsFix.speed = mSpeed; + event->gpsFix.cog = mCOG; EventQueue::instance().push(event); } //printf2("Lat: %f, Lng: %f\r\n", mLat, mLng); diff --git a/application/src/GPS.hpp b/application/src/GPS.hpp index 7b991df..395bdb5 100644 --- a/application/src/GPS.hpp +++ b/application/src/GPS.hpp @@ -43,7 +43,7 @@ public: void setDelegate(GPSDelegate *delegate); void onIRQ(uint32_t mask, void *data); - void processEvent(Event *event); + void processEvent(const Event &event); private: GPS(); void reset(); diff --git a/application/src/NoiseFloorDetector.cpp b/application/src/NoiseFloorDetector.cpp index 7fa5a60..e85f787 100644 --- a/application/src/NoiseFloorDetector.cpp +++ b/application/src/NoiseFloorDetector.cpp @@ -51,15 +51,14 @@ uint8_t NoiseFloorDetector::getNoiseFloor(VHFChannel channel) } -void NoiseFloorDetector::processEvent(Event *e) +void NoiseFloorDetector::processEvent(const Event &e) { - ClockEvent *ce = static_cast(e); - if ( mUTC == 0 ) { + if ( e.clock.utc == 0 ) { printf2("Starting RSSI sample collection\r\n"); - mStartTime = ce->mTime; + mStartTime = e.clock.utc; mLastDumpTime = mStartTime; } - mUTC = ce->mTime; + mUTC = e.clock.utc; if ( mUTC - mLastDumpTime >= 30 ) dump(); diff --git a/application/src/NoiseFloorDetector.hpp b/application/src/NoiseFloorDetector.hpp index 6520772..ce77725 100644 --- a/application/src/NoiseFloorDetector.hpp +++ b/application/src/NoiseFloorDetector.hpp @@ -28,7 +28,7 @@ public: // Returns the current noise floor of the channel, 0xff if unknown uint8_t getNoiseFloor(VHFChannel channelIndex); - void processEvent(Event *e); + void processEvent(const Event &e); private: typedef struct { time_t timestamp; diff --git a/application/src/RXPacket.cpp b/application/src/RXPacket.cpp index accefc3..75f9f77 100644 --- a/application/src/RXPacket.cpp +++ b/application/src/RXPacket.cpp @@ -26,7 +26,7 @@ void RXPacket::setChannel(VHFChannel channel) mChannel = channel; } -VHFChannel RXPacket::channel() +VHFChannel RXPacket::channel() const { return mChannel; } @@ -75,7 +75,7 @@ void RXPacket::setSlot(uint32_t slot) mSlot = slot; } -uint32_t RXPacket::slot() +uint32_t RXPacket::slot() const { return mSlot; } @@ -86,7 +86,7 @@ void RXPacket::setRSSI(uint8_t rssi) mRSSI = rssi; } -uint8_t RXPacket::rssi() +uint8_t RXPacket::rssi() const { return mRSSI; } @@ -107,7 +107,7 @@ void RXPacket::addBit(uint8_t bit) ++mSize; } -uint8_t RXPacket::bit(uint16_t pos) +uint8_t RXPacket::bit(uint16_t pos) const { if ( pos < mSize ) { uint16_t index = pos / 8; @@ -119,7 +119,7 @@ uint8_t RXPacket::bit(uint16_t pos) return 0; } -uint32_t RXPacket::bits(uint16_t pos, uint8_t count) +uint32_t RXPacket::bits(uint16_t pos, uint8_t count) const { ASSERT(count <= 32); uint32_t result = 0; @@ -166,13 +166,13 @@ void RXPacket::addByte(uint8_t byte) } -uint16_t RXPacket::size() +uint16_t RXPacket::size() const { return mSize; } -bool RXPacket::isBad() +bool RXPacket::isBad() const { /* * We don't anticipate anything less than 168 + 16 = 184 bits @@ -182,7 +182,7 @@ bool RXPacket::isBad() return mSize < 64; } -uint16_t RXPacket::crc() +uint16_t RXPacket::crc() const { return mCRC; } @@ -203,7 +203,7 @@ void RXPacket::addFillBits(uint8_t numBits) -bool RXPacket::checkCRC() +bool RXPacket::checkCRC() const { //uint16_t rcrc = ((mCRC & 0xff00) >> 8) | ((mCRC & 0x00ff) << 8); //trace_printf("%.4x %.4x %.4x\n", mCRC, ~(mCRC), ~(rcrc)); @@ -211,7 +211,7 @@ bool RXPacket::checkCRC() } -uint8_t RXPacket::messageType() +uint8_t RXPacket::messageType() const { if ( mType ) return mType; @@ -224,7 +224,7 @@ uint8_t RXPacket::messageType() return mType; } -uint8_t RXPacket::repeatIndicator() +uint8_t RXPacket::repeatIndicator() const { if ( mRI ) return mRI; @@ -233,7 +233,7 @@ uint8_t RXPacket::repeatIndicator() return mRI; } -uint32_t RXPacket::mmsi() +uint32_t RXPacket::mmsi() const { if ( mMMSI ) return mMMSI; @@ -253,6 +253,7 @@ uint32_t RXPacket::mmsi() // /////////////////////////////////////////////////////////////////////////////// +#if 0 RXPacketPool &RXPacketPool::instance() { static RXPacketPool __instance; @@ -274,6 +275,6 @@ void RXPacketPool::deleteRXPacket(RXPacket *p) ASSERT(p); mPool->put(p); } - +#endif diff --git a/application/src/RXPacket.hpp b/application/src/RXPacket.hpp index 936b0e0..205afca 100644 --- a/application/src/RXPacket.hpp +++ b/application/src/RXPacket.hpp @@ -17,20 +17,17 @@ using namespace std; class RXPacket { - friend class RXPacketPool; public: RXPacket (); -private: + ~RXPacket (); RXPacket(const RXPacket ©); RXPacket &operator=(const RXPacket ©); - ~RXPacket (); public: - //void setStuffed(bool); void setSlot(uint32_t slot); void setChannel(VHFChannel channel); - VHFChannel channel(); + VHFChannel channel() const; void discardCRC(); @@ -38,25 +35,25 @@ public: void addByte(uint8_t byte); - uint16_t size(); - uint8_t bit(uint16_t pos); - uint32_t bits(uint16_t pos, uint8_t count); + uint16_t size() const; + uint8_t bit(uint16_t pos) const; + uint32_t bits(uint16_t pos, uint8_t count) const; - uint16_t crc(); - bool checkCRC(); - bool isBad(); + uint16_t crc() const; + bool checkCRC() const; + bool isBad() const; void reset(); // Every AIS message contains these 3 attributes at a minimum, so we expose them at the packet level - uint8_t messageType(); - uint8_t repeatIndicator(); - uint32_t mmsi(); + uint8_t messageType() const; + uint8_t repeatIndicator() const; + uint32_t mmsi() const; // These are link-level attributes - uint32_t slot(); - uint8_t rssi(); + uint32_t slot() const; + uint8_t rssi() const; void setRSSI(uint8_t); private: void addBit(uint8_t bit); @@ -65,15 +62,15 @@ private: uint8_t mPacket[MAX_AIS_RX_PACKET_SIZE/8+1]; uint16_t mSize; uint16_t mCRC; - uint8_t mType; - uint8_t mRI; - uint32_t mMMSI; + mutable uint8_t mType; + mutable uint8_t mRI; + mutable uint32_t mMMSI; uint32_t mSlot; VHFChannel mChannel; uint8_t mRSSI; }; - +#if 0 class RXPacketPool { public: @@ -88,6 +85,6 @@ private: ObjectPool *mPool; }; - +#endif #endif /* RXPACKET_HPP_ */ diff --git a/application/src/RXPacketProcessor.cpp b/application/src/RXPacketProcessor.cpp index ef2bb08..1f00da1 100644 --- a/application/src/RXPacketProcessor.cpp +++ b/application/src/RXPacketProcessor.cpp @@ -31,23 +31,23 @@ RXPacketProcessor::~RXPacketProcessor () // Should never be called } -void RXPacketProcessor::processEvent(Event *e) +void RXPacketProcessor::processEvent(const Event &e) { //printf2("-> RXPacketProcessor::processEvent()\r\n"); - switch(e->type()) { + switch(e.type) { case GPS_FIX_EVENT: { - GPSFIXEvent *gfe = static_cast (e); - mLat = gfe->mLat; - mLng = gfe->mLng; + //GPSFIXEvent *gfe = static_cast (e); + mLat = e.gpsFix.lat; + mLng = e.gpsFix.lng; break; } case CLOCK_EVENT: { - ClockEvent *pe = static_cast(e); + //ClockEvent *pe = static_cast(e); if ( mLastDumpTime == 0 ) { - mLastDumpTime = pe->mTime; + mLastDumpTime = e.clock.utc; } - else if ( pe->mTime - mLastDumpTime >= 60 ) { - mLastDumpTime = pe->mTime; + else if ( e.clock.utc - mLastDumpTime >= 60 ) { + mLastDumpTime = e.clock.utc; float yield = (float)mGoodCount / (float)(mGoodCount+mBadCRCCount+mInvalidCount); printf2("\r\n"); printf2("[Yield: %.1fpct, Valid: %d, Wrong CRC: %d, Malformed: %d]\r\n", yield*100.0, mGoodCount, mBadCRCCount, mInvalidCount); @@ -63,31 +63,30 @@ void RXPacketProcessor::processEvent(Event *e) break; } case AIS_PACKET_EVENT: { - AISPacketEvent *pe = static_cast(e); - if ( pe->mPacket->isBad() ) { + //AISPacketEvent *pe = static_cast(e); + if ( e.rxPacket.isBad() ) { ++mInvalidCount; break; } - if (pe->mPacket->checkCRC ()) { + if (e.rxPacket.checkCRC ()) { ++mGoodCount; - mUniqueMMSIs.insert (pe->mPacket->mmsi ()); - switch (pe->mPacket->messageType ()) { + mUniqueMMSIs.insert (e.rxPacket.mmsi ()); + switch (e.rxPacket.messageType()) { case 1: case 2: case 3: { AISMessage123 msg; - if (msg.decode (*pe->mPacket)) { - double distance = Utils::haversineDistance ( - mLat, mLng, msg.latitude, msg.longitude); + if (msg.decode (e.rxPacket)) { + double distance = Utils::haversineDistance (mLat, mLng, msg.latitude, msg.longitude); double miles = distance / METERS_PER_NAUTICAL_MILE; printf2 ( "RSSI: %.2x, Ch: %c, Type: %d, MMSI: %d, Speed: %.1f kts, Pos: %.5f,%.5f, Dist: %.1f NM\r\n", - pe->mPacket->rssi (), - AIS_CHANNELS[pe->mPacket->channel ()].designation, + e.rxPacket.rssi(), + AIS_CHANNELS[e.rxPacket.channel()].designation, msg.type(), msg.mmsi(), msg.sog, msg.latitude, msg.longitude, miles); @@ -96,14 +95,13 @@ void RXPacketProcessor::processEvent(Event *e) } case 18: { AISMessage18 msg; - if (msg.decode (*pe->mPacket)) { - double distance = Utils::haversineDistance ( - mLat, mLng, msg.latitude, msg.longitude); + if (msg.decode (e.rxPacket)) { + double distance = Utils::haversineDistance (mLat, mLng, msg.latitude, msg.longitude); double miles = distance / METERS_PER_NAUTICAL_MILE; printf2 ("RSSI: %.2x, Ch: %c, Type: %d, MMSI: %d, Speed: %.1f kts, Pos: %.5f,%.5f, Dist: %.1f NM\r\n", - pe->mPacket->rssi (), - AIS_CHANNELS[pe->mPacket->channel ()].designation, + e.rxPacket.rssi (), + AIS_CHANNELS[e.rxPacket.channel()].designation, msg.type(), msg.mmsi(), msg.sog, msg.latitude, msg.longitude, miles); @@ -114,11 +112,11 @@ void RXPacketProcessor::processEvent(Event *e) printf2 ( "RSSI: %.2x, Ch: %c, Type: %d, RI: %d, MMSI: %d\r\n", - pe->mPacket->rssi (), - AIS_CHANNELS[pe->mPacket->channel ()].designation, - pe->mPacket->messageType (), - pe->mPacket->repeatIndicator (), - pe->mPacket->mmsi ()); + e.rxPacket.rssi (), + AIS_CHANNELS[e.rxPacket.channel()].designation, + e.rxPacket.messageType (), + e.rxPacket.repeatIndicator (), + e.rxPacket.mmsi ()); break; } @@ -126,7 +124,8 @@ void RXPacketProcessor::processEvent(Event *e) #ifdef ENABLE_TERMINAL mSentences.clear(); - mEncoder.encode(*pe->mPacket, mSentences); + RXPacket p(e.rxPacket); + mEncoder.encode(p, mSentences); for (vector::iterator i = mSentences.begin(); i != mSentences.end(); ++i) { #ifdef MULTIPLEXED_OUTPUT sprintf(__buff, "%s\r\n", i->c_str()); @@ -137,7 +136,7 @@ void RXPacketProcessor::processEvent(Event *e) #endif } #endif - switch (pe->mPacket->messageType()) { + switch (e.rxPacket.messageType()) { case 15: // TODO: This is an interrogation. If we are a target, push an appropriate event into the queue break; diff --git a/application/src/RXPacketProcessor.hpp b/application/src/RXPacketProcessor.hpp index 749d435..f44fe54 100644 --- a/application/src/RXPacketProcessor.hpp +++ b/application/src/RXPacketProcessor.hpp @@ -21,7 +21,7 @@ public: virtual ~RXPacketProcessor (); - void processEvent(Event *e); + void processEvent(const Event &e); private: NMEAEncoder mEncoder; time_t mLastDumpTime; diff --git a/application/src/RadioManager.cpp b/application/src/RadioManager.cpp index 5e82b6e..91a35f9 100644 --- a/application/src/RadioManager.cpp +++ b/application/src/RadioManager.cpp @@ -228,10 +228,10 @@ void RadioManager::configureInterrupts() } -void RadioManager::processEvent(Event *e) +void RadioManager::processEvent(const Event &e) { - ClockEvent *ce = static_cast(e); - mUTC = ce->mTime; + //ClockEvent *ce = static_cast(e); + mUTC = e.clock.utc; // Evaluate the state of the transceiver IC and our queue ... if ( mTransceiverIC->assignedTXPacket() == NULL ) { diff --git a/application/src/RadioManager.hpp b/application/src/RadioManager.hpp index 9df4ca1..de74903 100644 --- a/application/src/RadioManager.hpp +++ b/application/src/RadioManager.hpp @@ -30,7 +30,7 @@ public: void scheduleTransmission(TXPacket *p); bool initialized(); - void processEvent(Event *e); + void processEvent(const Event &e); void transmitCW(VHFChannel channel); VHFChannel alternateChannel(VHFChannel channel); private: diff --git a/application/src/Receiver.cpp b/application/src/Receiver.cpp index 2f31eff..e16b147 100644 --- a/application/src/Receiver.cpp +++ b/application/src/Receiver.cpp @@ -33,7 +33,6 @@ bool Receiver::init() { printf2("Configuring IC\r\n"); configure(); - mRXPacket = RXPacketPool::instance().newRXPacket(); resetBitScanner(); return true; } @@ -75,8 +74,7 @@ void Receiver::resetBitScanner() mRXByte = 0; mBitState = BIT_STATE_PREAMBLE_SYNC; - ASSERT(mRXPacket); - mRXPacket->reset(); + mRXPacket.reset(); } void Receiver::onBitClock() @@ -93,7 +91,7 @@ void Receiver::onBitClock() rssi = readRSSI(); rssi += mRSSIAdjustment; NoiseFloorDetector::instance().report(mChannel, rssi); - mRXPacket->setRSSI(rssi); + mRXPacket.setRSSI(rssi); } } @@ -108,7 +106,7 @@ void Receiver::timeSlotStarted(uint32_t slot) if ( mBitState == BIT_STATE_IN_PACKET ) return; - mRXPacket->setSlot(slot); + mRXPacket.setSlot(slot); if ( mSwitchAtNextSlot ) { mSwitchAtNextSlot = false; startReceiving(mSwitchToChannel); @@ -136,13 +134,13 @@ void Receiver::processNRZIBit(uint8_t bit) */ if ( mBitWindow == 0b1010101001111110 || mBitWindow == 0b0101010101111110 ) { mBitState = BIT_STATE_IN_PACKET; - mRXPacket->setChannel(mChannel); + mRXPacket.setChannel(mChannel); } break; } case BIT_STATE_IN_PACKET: { - if ( mRXPacket->size() >= MAX_AIS_RX_PACKET_SIZE ) { + if ( mRXPacket.size() >= MAX_AIS_RX_PACKET_SIZE ) { // Start over startReceiving(mChannel); //resetBitScanner(); @@ -200,7 +198,7 @@ bool Receiver::addBit(uint8_t bit) if ( mBitCount == 8 ) { // Commit to the packet! - mRXPacket->addByte(mRXByte); + mRXPacket.addByte(mRXByte); mBitCount = 0; mRXByte = 0; } @@ -210,15 +208,16 @@ bool Receiver::addBit(uint8_t bit) void Receiver::pushPacket() { - AISPacketEvent *p = static_cast(EventPool::instance().newEvent(AIS_PACKET_EVENT)); + Event *p = EventPool::instance().newEvent(AIS_PACKET_EVENT); if ( p == NULL ) { printf2("AISPacket allocation failed\r\n"); return; } - p->mPacket = mRXPacket; - mRXPacket = RXPacketPool::instance().newRXPacket(); - ASSERT(mRXPacket); + p->rxPacket = mRXPacket; + mRXPacket.reset(); + //mRXPacket = RXPacketPool::instance().newRXPacket(); + //ASSERT(mRXPacket); EventQueue::instance().push(p); } diff --git a/application/src/Receiver.hpp b/application/src/Receiver.hpp index bb736d5..0fa90a7 100644 --- a/application/src/Receiver.hpp +++ b/application/src/Receiver.hpp @@ -43,7 +43,7 @@ private: void resetBitScanner(); void configureGPIOs(); protected: - RXPacket *mRXPacket; + RXPacket mRXPacket; uint16_t mBitWindow; uint8_t mLastNRZIBit; uint32_t mBitCount; diff --git a/application/src/TXScheduler.cpp b/application/src/TXScheduler.cpp index 144463a..7743ab1 100644 --- a/application/src/TXScheduler.cpp +++ b/application/src/TXScheduler.cpp @@ -44,18 +44,18 @@ void TXScheduler::startTXTesting() mTesting = true; } -void TXScheduler::processEvent(Event *event) +void TXScheduler::processEvent(const Event &e) { #ifndef ENABLE_TX return; #endif - switch(event->type()) { + switch(e.type) { case GPS_FIX_EVENT: { if ( mTesting ) return; - GPSFIXEvent *gfe = static_cast (event); + //GPSFIXEvent *gfe = static_cast (event); //printf2("UTC: %d\r\n", mUTC); @@ -74,11 +74,11 @@ void TXScheduler::processEvent(Event *event) } AISMessage18 msg; - msg.latitude = gfe->mLat; - msg.longitude = gfe->mLng; - msg.sog = gfe->mSpeed; - msg.cog = gfe->mCOG; - msg.utc = gfe->mUTC; + msg.latitude = e.gpsFix.lat; + msg.longitude = e.gpsFix.lng; + msg.sog = e.gpsFix.speed; + msg.cog = e.gpsFix.cog; + msg.utc = e.gpsFix.utc; msg.encode (mStationData, *p1); RadioManager::instance ().scheduleTransmission (p1); @@ -116,8 +116,8 @@ void TXScheduler::processEvent(Event *event) } case CLOCK_EVENT: { // This is reliable and independent of GPS update frequency which could change to something other than 1Hz - ClockEvent *c = static_cast(event); - mUTC = c->mTime; + //ClockEvent *c = static_cast(event); + mUTC = e.clock.utc; if ( RadioManager::instance().initialized() && mTesting && mUTC % 1 == 0 ) { scheduleTestPacket(); printf2("Scheduled test packet\r\n"); diff --git a/application/src/TXScheduler.hpp b/application/src/TXScheduler.hpp index d00fbd1..b0fa16c 100644 --- a/application/src/TXScheduler.hpp +++ b/application/src/TXScheduler.hpp @@ -22,7 +22,7 @@ public: virtual ~TXScheduler (); - void processEvent(Event *event); + void processEvent(const Event &event); void startTXTesting(); private: void scheduleTestPacket(); diff --git a/application/src/Transceiver.cpp b/application/src/Transceiver.cpp index 5209cbb..d7610b3 100644 --- a/application/src/Transceiver.cpp +++ b/application/src/Transceiver.cpp @@ -162,7 +162,7 @@ void Transceiver::onBitClock() // If we have an assigned packet and we're on the correct channel, at the right bit of the time slot, // and the RSSI is within 6dB of the noise floor for this channel, then fire!!! uint8_t noiseFloor = NoiseFloorDetector::instance().getNoiseFloor(mChannel); - if ( mSlotBitNumber == CCA_SLOT_BIT+1 && mTXPacket && mTXPacket->channel() == mChannel && mRXPacket->rssi() < noiseFloor + 12 ) { + if ( mSlotBitNumber == CCA_SLOT_BIT+1 && mTXPacket && mTXPacket->channel() == mChannel && mRXPacket.rssi() < noiseFloor + 12 ) { startTransmitting(); } } diff --git a/application/src/main.cpp b/application/src/main.cpp index 1d08824..d7cbe49 100644 --- a/application/src/main.cpp +++ b/application/src/main.cpp @@ -79,7 +79,7 @@ main(int argc, char* argv[]) EventQueue::instance().init(); EventPool::instance().init(); TXPacketPool::instance().init(); - RXPacketPool::instance().init(); + LEDManager::instance().clear(); TXScheduler txScheduler; diff --git a/application/src/printf2.cpp b/application/src/printf2.cpp index 8ee568f..0c3784f 100644 --- a/application/src/printf2.cpp +++ b/application/src/printf2.cpp @@ -57,13 +57,13 @@ void USART_puts(USART_TypeDef* USARTx, const char *s) } #endif -static char __buffer[256]; +static char __buffer[128]; void printf2_now(const char *format, ...) { va_list list; va_start(list, format); - vsnprintf(__buffer, 255, format, list); + vsnprintf(__buffer, 128, format, list); va_end(list); #ifdef MULTIPLEXED_OUTPUT DataTerminal::instance().write("DEBUG", __buffer); @@ -76,13 +76,13 @@ void printf2_now(const char *format, ...) void printf2(const char *format, ...) { if ( Utils::inISR() ) { - DebugEvent *e = static_cast(EventPool::instance().newEvent(DEBUG_EVENT)); + Event *e = EventPool::instance().newEvent(DEBUG_EVENT); if ( e == NULL ) return; va_list list; va_start(list, format); - vsnprintf(e->mBuffer, 255, format, list); + vsnprintf(e->debugMessage.buffer, 128, format, list); va_end(list); EventQueue::instance().push(e); @@ -90,7 +90,7 @@ void printf2(const char *format, ...) else { va_list list; va_start(list, format); - vsnprintf(__buffer, 255, format, list); + vsnprintf(__buffer, 128, format, list); va_end(list); #ifdef MULTIPLEXED_OUTPUT DataTerminal::instance().write("DEBUG", __buffer);