diff --git a/application/.cproject b/application/.cproject
index ec67505..6312112 100644
--- a/application/.cproject
+++ b/application/.cproject
@@ -193,44 +193,44 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
-
-
-
-
+
+
+
+
@@ -305,7 +306,7 @@
-
+
@@ -315,7 +316,7 @@
-
+
@@ -368,4 +369,5 @@
+
diff --git a/application/Release/makefile b/application/Release/makefile
index 9261951..385b984 100644
--- a/application/Release/makefile
+++ b/application/Release/makefile
@@ -61,7 +61,7 @@ all: ais_transponder.elf secondary-outputs
ais_transponder.elf: $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: Cross ARM C++ Linker'
- arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -flto -Wall -Wextra -g -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"ais_transponder.map" --specs=nano.specs -u _printf_float -o "ais_transponder.elf" $(OBJS) $(USER_OBJS) $(LIBS)
+ arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -flto -Wall -Wextra -g -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -s -L"../ldscripts" -Wl,-Map,"ais_transponder.map" --specs=nano.specs -o "ais_transponder.elf" $(OBJS) $(USER_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '
diff --git a/application/src/CommandProcessor.cpp b/application/src/CommandProcessor.cpp
index d1120ec..51840b5 100644
--- a/application/src/CommandProcessor.cpp
+++ b/application/src/CommandProcessor.cpp
@@ -12,11 +12,11 @@
#include "globals.h"
#include "stm32f30x.h"
-
-CommandProcessor &CommandProcessor::instance()
+CommandProcessor &
+CommandProcessor::instance()
{
- static CommandProcessor __instance;
- return __instance;
+ static CommandProcessor __instance;
+ return __instance;
}
CommandProcessor::CommandProcessor()
@@ -24,267 +24,291 @@ CommandProcessor::CommandProcessor()
}
-void CommandProcessor::init()
+void
+CommandProcessor::init()
{
- EventQueue::instance().addObserver(this, REQUEST_EVENT|RESET_EVENT);
+ EventQueue::instance ().addObserver (this, REQUEST_EVENT | RESET_EVENT);
}
-void CommandProcessor::processEvent(const Event &e)
+void
+CommandProcessor::processEvent(const Event &e)
{
- if ( e.type == RESET_EVENT ) {
- NVIC_SystemReset ();
- return;
- }
-
- switch(e.request.operation) {
- case OP_GET:
- if ( strcmp(e.request.field, "mmsi") == 0 )
- returnMMSI();
- else if ( strcmp(e.request.field, "name") == 0 )
- returnName();
- else if ( strcmp(e.request.field, "callsign") == 0 )
- returnCallSign();
- else if ( strcmp(e.request.field, "beam") == 0 )
- returnBeam();
- else if ( strcmp(e.request.field, "length") == 0 )
- returnLength();
- else if ( strcmp(e.request.field, "mode") == 0 )
- returnMode();
- else if ( strcmp(e.request.field, "vesseldata") == 0 )
- returnVesselData();
- else if ( strcmp(e.request.field, "version") == 0 )
- returnVersion();
- else if ( strcmp(e.request.field, "status") == 0 )
- returnStatus();
- else
- sendError("Unknown field");
- break;
- case OP_SET:
- if ( strcmp(e.request.field, "mmsi") == 0 )
- setMMSI(atoi(e.request.value));
- else if ( strcmp(e.request.field, "name") == 0 )
- setName(e.request.value);
- else if ( strcmp(e.request.field, "callsign") == 0 )
- setCallSign(e.request.value);
- else if ( strcmp(e.request.field, "beam") == 0 )
- setBeam(atoi(e.request.value));
- else if ( strcmp(e.request.field, "length") == 0 )
- setLength(atoi(e.request.value));
- else if ( strcmp(e.request.field, "mode") == 0 )
- setMode(e.request.value);
- else if ( strcmp(e.request.field, "vesseldata") == 0 )
- setVesselData(e.request.value);
- else
- sendError("Unknown field");
- break;
-
- }
-}
-
-void CommandProcessor::sendError(const char *err)
-{
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = false;
- strcpy(reply->response.data, err);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::sendEmptyReply(bool success)
-{
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = success;
- reply->response.data[0] = 0;
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnVersion()
-{
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
- strcpy(reply->response.data, REVISION);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnMMSI()
-{
- StationData data;
- EEPROM::instance().readStationData(data);
-
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
- sprintf(reply->response.data, "%lu", data.mmsi);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnCallSign()
-{
- StationData data;
- EEPROM::instance().readStationData(data);
-
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
- sprintf(reply->response.data, "%s", data.callsign);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnName()
-{
- StationData data;
- EEPROM::instance().readStationData(data);
-
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
- sprintf(reply->response.data, "%s", data.name);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnBeam()
-{
- StationData data;
- EEPROM::instance().readStationData(data);
-
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
- sprintf(reply->response.data, "%d", data.beam);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnLength()
-{
- StationData data;
- EEPROM::instance().readStationData(data);
-
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
- sprintf(reply->response.data, "%d", data.len);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnMode()
-{
-}
-
-void CommandProcessor::returnVesselData()
-{
- StationData data;
- EEPROM::instance().readStationData(data);
-
- Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
- reply->response.success = true;
-
- sprintf(reply->response.data, "%lu,%s,%s,%d,%d", data.mmsi, data.name, data.callsign, data.beam, data.len);
- EventQueue::instance().push(reply);
-}
-
-void CommandProcessor::returnStatus()
-{
-}
-
-void CommandProcessor::setMMSI(uint32_t mmsi)
-{
- StationData data;
- EEPROM::instance().readStationData(data);
- data.mmsi = mmsi;
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
-}
-
-void CommandProcessor::setName(const char* name)
-{
- StationData data;
- EEPROM::instance().readStationData(data);
- strcpy(data.name, name);
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
-}
-
-void CommandProcessor::setCallSign(const char *callsign)
-{
- StationData data;
- EEPROM::instance().readStationData(data);
- strcpy(data.callsign, callsign);
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
-}
-
-void CommandProcessor::setBeam(uint8_t beam)
-{
- StationData data;
- EEPROM::instance().readStationData(data);
- data.beam = beam;
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
-}
-
-void CommandProcessor::setLength(uint8_t len)
-{
- StationData data;
- EEPROM::instance().readStationData(data);
- data.len = len;
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
-}
-
-void CommandProcessor::setVesselData(const char *s)
-{
- StationData data;
- EEPROM::instance().readStationData(data);
- int items = sscanf(s, "%lu,%s,%s,%cu,%cu", &data.mmsi, data.name, data.callsign, &data.beam, &data.len);
- if ( items < 5 )
- sendEmptyReply(false);
- else {
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
- }
-}
-
-void CommandProcessor::setMode(const char *mode)
-{
- if (strcmp (mode, "dfu") == 0)
- {
- FLASH_Unlock ();
- FLASH_Status status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
- if ( status != FLASH_COMPLETE ) {
- sendError("Unable to unlock flash");
- return;
- }
-
- FLASH_ErasePage (METADATA_ADDRESS);
- status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
- if ( status != FLASH_COMPLETE ) {
- sendError("Unable to erase metadata page");
- return;
- }
-
- FLASH_Lock ();
- FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
- if ( status != FLASH_COMPLETE ) {
- sendError("Unable to lock flash");
- return;
- }
-
- //sendEmptyReply (true);
- Event *e = EventPool::instance().newEvent(RESET_EVENT);
- EventQueue::instance().push(e);
+ if (e.type == RESET_EVENT) {
+ NVIC_SystemReset ();
+ return;
+ }
+
+ switch (e.request.operation) {
+ case OP_GET:
+ if (strcmp (e.request.field, "mmsi") == 0)
+ returnMMSI ();
+ else if (strcmp (e.request.field, "name") == 0)
+ returnName ();
+ else if (strcmp (e.request.field, "callsign") == 0)
+ returnCallSign ();
+ else if (strcmp (e.request.field, "beam") == 0)
+ returnBeam ();
+ else if (strcmp (e.request.field, "length") == 0)
+ returnLength ();
+ else if (strcmp (e.request.field, "mode") == 0)
+ returnMode ();
+ else if (strcmp (e.request.field, "vesseldata") == 0)
+ returnVesselData ();
+ else if (strcmp (e.request.field, "version") == 0)
+ returnVersion ();
+ else if (strcmp (e.request.field, "status") == 0)
+ returnStatus ();
+ else
+ sendError ("Unknown field");
+ break;
+ case OP_SET:
+ if (strcmp (e.request.field, "mmsi") == 0)
+ setMMSI (atoi (e.request.value));
+ else if (strcmp (e.request.field, "name") == 0)
+ setName (e.request.value);
+ else if (strcmp (e.request.field, "callsign") == 0)
+ setCallSign (e.request.value);
+ else if (strcmp (e.request.field, "beam") == 0)
+ setBeam (atoi (e.request.value));
+ else if (strcmp (e.request.field, "length") == 0)
+ setLength (atoi (e.request.value));
+ else if (strcmp (e.request.field, "mode") == 0)
+ setMode (e.request.value);
+ else if (strcmp (e.request.field, "vesseldata") == 0)
+ setVesselData (e.request.value);
+ else
+ sendError ("Unknown field");
+ break;
+
}
- else if ( strcmp(mode, "rx") == 0 ) {
- StationData data;
- EEPROM::instance().readStationData(data);
- data.flags |= STATION_RX_ONLY;
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
- }
- else if ( strcmp(mode, "trx") == 0 ) {
- StationData data;
- EEPROM::instance().readStationData(data);
- data.flags &= ~(STATION_RX_ONLY);
- EEPROM::instance().writeStationData(data);
- sendEmptyReply(true);
- }
- else
- sendError("Unrecognized mode");
}
+void
+CommandProcessor::sendError(const char *err)
+{
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = false;
+ strcpy (reply->response.data, err);
+ EventQueue::instance ().push (reply);
+}
+void
+CommandProcessor::sendEmptyReply(bool success)
+{
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = success;
+ reply->response.data[0] = 0;
+ EventQueue::instance ().push (reply);
+}
+void
+CommandProcessor::returnVersion()
+{
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+ strcpy (reply->response.data, REVISION);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnMMSI()
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+ sprintf (reply->response.data, "%lu", data.mmsi);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnCallSign()
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+ sprintf (reply->response.data, "%s", data.callsign);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnName()
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+ sprintf (reply->response.data, "%s", data.name);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnBeam()
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+ sprintf (reply->response.data, "%d", data.beam);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnLength()
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+ sprintf (reply->response.data, "%d", data.len);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnMode()
+{
+}
+
+void
+CommandProcessor::returnVesselData()
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
+ reply->response.success = true;
+
+ sprintf (reply->response.data, "%lu,%s,%s,%d,%d", data.mmsi, data.name,
+ data.callsign, data.beam, data.len);
+ EventQueue::instance ().push (reply);
+}
+
+void
+CommandProcessor::returnStatus()
+{
+}
+
+void
+CommandProcessor::setMMSI(uint32_t mmsi)
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ data.mmsi = mmsi;
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+}
+
+void
+CommandProcessor::setName(const char* name)
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ strncpy (data.name, name, sizeof data.name);
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+}
+
+void
+CommandProcessor::setCallSign(const char *callsign)
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ strncpy (data.callsign, callsign, sizeof data.callsign);
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+}
+
+void
+CommandProcessor::setBeam(uint8_t beam)
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ data.beam = beam;
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+}
+
+void
+CommandProcessor::setLength(uint8_t len)
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ data.len = len;
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+}
+
+void
+CommandProcessor::setVesselData(const char *s)
+{
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+
+ /*
+ * TODO: Add to/from CSV methods in StationData and use tokenization instead of sscanf()
+ */
+ int items = sscanf (s, "%lu,%s,%s,%cu,%cu", &data.mmsi, data.name, data.callsign, &data.beam, &data.len);
+ if (items < 5)
+ sendEmptyReply (false);
+ else {
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+ }
+}
+
+void
+CommandProcessor::setMode(const char *mode)
+{
+ if (strcmp (mode, "dfu") == 0) {
+ FLASH_Unlock ();
+ FLASH_Status status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
+ if (status != FLASH_COMPLETE) {
+ sendError ("Unable to unlock flash");
+ return;
+ }
+
+ FLASH_ErasePage (METADATA_ADDRESS);
+ status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
+ if (status != FLASH_COMPLETE) {
+ sendError ("Unable to erase metadata page");
+ return;
+ }
+
+ FLASH_Lock ();
+ FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
+ if (status != FLASH_COMPLETE) {
+ sendError ("Unable to lock flash");
+ return;
+ }
+
+ /*
+ * UART takes a while to send reply, so unless we add considerable delay here, it won't make it before MCU reset
+ */
+ //sendEmptyReply (true);
+ Event *e = EventPool::instance ().newEvent (RESET_EVENT);
+ EventQueue::instance ().push (e);
+ }
+ else if (strcmp (mode, "rx") == 0) {
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ data.flags |= STATION_RX_ONLY;
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+ }
+ else if (strcmp (mode, "trx") == 0) {
+ StationData data;
+ EEPROM::instance ().readStationData (data);
+ data.flags &= ~(STATION_RX_ONLY);
+ EEPROM::instance ().writeStationData (data);
+ sendEmptyReply (true);
+ }
+ else
+ sendError ("Unrecognized mode");
+}
diff --git a/application/src/EventQueue.cpp b/application/src/EventQueue.cpp
index 00eab24..d6337dd 100644
--- a/application/src/EventQueue.cpp
+++ b/application/src/EventQueue.cpp
@@ -57,11 +57,13 @@ void EventQueue::dispatch()
if (mQueue->pop(e)) {
for ( map::iterator c = mConsumers.begin(); c != mConsumers.end(); ++c ) {
- // Utils::delay(1000);
if ( c->second & e->type )
c->first->processEvent(*e);
}
+
EventPool::instance().deleteEvent(e);
+
+ // TODO: Make LEDManager an EventConsumer instead
if ( e->type == AIS_PACKET_EVENT )
LEDManager::instance().blink(LEDManager::GREEN_LED);
}
diff --git a/application/src/TXScheduler.cpp b/application/src/TXScheduler.cpp
index 7678380..6da005a 100644
--- a/application/src/TXScheduler.cpp
+++ b/application/src/TXScheduler.cpp
@@ -65,7 +65,7 @@ void TXScheduler::processEvent(const Event &e)
if ( stationData.flags & STATION_RX_ONLY )
return;
- // Using a moving average to determine transmission rate
+ // Using a moving average of SOG to determine transmission rate
double alpha = 0.2;
mAvgSpeed = mAvgSpeed * (1.0 - alpha) + e.gpsFix.speed * alpha;
@@ -75,14 +75,13 @@ void TXScheduler::processEvent(const Event &e)
printf2("Unable to allocate TX packet for message 18, will try again later\r\n");
break;
}
- AISMessage18 msg;
+ AISMessage18 msg;
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 (stationData, *p1);
RadioManager::instance ().scheduleTransmission (p1);
@@ -98,6 +97,7 @@ void TXScheduler::processEvent(const Event &e)
printf2("Unable to allocate TX packet for 24A\r\n");
break;
}
+
AISMessage24A msg2;
msg2.encode(stationData, *p2);
RadioManager::instance().scheduleTransmission(p2);