1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-18 00:10:08 -07:00

Overhauled event processing

This commit is contained in:
Peter Antypas 2016-06-15 14:06:44 -07:00
parent db0a282699
commit f080b18872
30 changed files with 254 additions and 422 deletions

View File

@ -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

View File

@ -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();

View File

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

View File

@ -44,7 +44,7 @@ bool ChannelManager::channelsDetermined()
return true;
}
void ChannelManager::processEvent(Event *)
void ChannelManager::processEvent(const Event &)
{
//AISPacketEvent *pe = static_cast<AISPacketEvent*>(e);
}

View File

@ -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();

View File

@ -12,9 +12,13 @@
#include "MenuScreens.hpp"
#include "Events.hpp"
#include <stdio.h>
#include "Utils.hpp"
#include <cstring>
#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<ClockEvent*>(e);
if ( c->mTime % 2 == 0 ) {
mEscapes = 0;
}
}
else if ( e->type() == KEYPRESS_EVENT ) {
KeyPressEvent *k = static_cast<KeyPressEvent*>(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<Enter>\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<KeyPressEvent*>(EventPool::instance().newEvent(KEYPRESS_EVENT));
if ( e == NULL )
return;
e->key = c;
EventQueue::instance().push(e);
//DataTerminal::instance().processCharacter(c);
DataTerminal::instance().processCharacter(c);
}
}

View File

@ -10,6 +10,11 @@
#include "globals.h"
#include "EventQueue.hpp"
#include <vector>
#include <string>
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<string> mCmdTokens;
};
#endif

View File

@ -18,9 +18,9 @@ DebugPrinter::~DebugPrinter()
{
}
void DebugPrinter::processEvent(Event *e)
void DebugPrinter::processEvent(const Event &e)
{
DebugEvent *event = static_cast<DebugEvent*>(e);
printf2(event->mBuffer);
//DebugEvent *event = static_cast<DebugEvent*>(e);
printf2(e.debugMessage.buffer);
}

View File

@ -16,7 +16,7 @@ public:
DebugPrinter();
virtual ~DebugPrinter();
void processEvent(Event* e);
void processEvent(const Event &e);
};
#endif /* DEBUGPRINTER_HPP_ */

View File

@ -58,11 +58,11 @@ void EventQueue::dispatch()
for ( map<EventConsumer*, uint32_t>::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);
}
}

View File

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

View File

@ -17,89 +17,19 @@ EventPool &EventPool::instance()
void EventPool::init()
{
mGenericPool = new ObjectPool<Event>(10);
mAISPacketPool = new ObjectPool<AISPacketEvent>(40);
mGPSNMEAPool = new ObjectPool<GPSNMEASentence>(20);
mGPSFixPool = new ObjectPool<GPSFIXEvent>(10);
mClockPool = new ObjectPool<ClockEvent>(10);
mDebugEventPool = new ObjectPool<DebugEvent>(2);
mKeyPressPool = new ObjectPool<KeyPressEvent>(20);
mGenericPool = new ObjectPool<Event>(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<GPSNMEASentence*>(event);
mGPSNMEAPool->put(e);
break;
}
case GPS_FIX_EVENT: {
GPSFIXEvent *e = static_cast<GPSFIXEvent*>(event);
mGPSFixPool->put(e);
break;
}
case CLOCK_EVENT:{
ClockEvent *e = static_cast<ClockEvent*>(event);
mClockPool->put(e);
break;
}
case AIS_PACKET_EVENT: {
AISPacketEvent *p = static_cast<AISPacketEvent*>(event);
mAISPacketPool->put(p);
break;
}
case DEBUG_EVENT: {
DebugEvent *e = static_cast<DebugEvent*>(event);
mDebugEventPool->put(e);
break;
}
case KEYPRESS_EVENT: {
KeyPressEvent *e = static_cast<KeyPressEvent*>(event);
mKeyPressPool->put(e);
break;
}
default:
mGenericPool->put(event);
break;
}
mGenericPool->put(event);
}

View File

@ -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<Event> *mGenericPool;
ObjectPool<AISPacketEvent> *mAISPacketPool;
ObjectPool<GPSNMEASentence> *mGPSNMEAPool;
ObjectPool<GPSFIXEvent> *mGPSFixPool;
ObjectPool<ClockEvent> *mClockPool;
ObjectPool<DebugEvent> *mDebugEventPool;
ObjectPool<KeyPressEvent> *mKeyPressPool;
};

View File

@ -161,9 +161,9 @@ void GPS::onRX(char c)
}
else if (c == '\n') {
mBuff[mBuffPos] = 0;
GPSNMEASentence *event = static_cast<GPSNMEASentence*>(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<ClockEvent*>(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<GPSNMEASentence*>(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<GPSFIXEvent*>(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);

View File

@ -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();

View File

@ -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<ClockEvent*>(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();

View File

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

View File

@ -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

View File

@ -17,20 +17,17 @@ using namespace std;
class RXPacket
{
friend class RXPacketPool;
public:
RXPacket ();
private:
~RXPacket ();
RXPacket(const RXPacket &copy);
RXPacket &operator=(const RXPacket &copy);
~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<RXPacket> *mPool;
};
#endif
#endif /* RXPACKET_HPP_ */

View File

@ -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<GPSFIXEvent*> (e);
mLat = gfe->mLat;
mLng = gfe->mLng;
//GPSFIXEvent *gfe = static_cast<GPSFIXEvent*> (e);
mLat = e.gpsFix.lat;
mLng = e.gpsFix.lng;
break;
}
case CLOCK_EVENT: {
ClockEvent *pe = static_cast<ClockEvent*>(e);
//ClockEvent *pe = static_cast<ClockEvent*>(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<AISPacketEvent*>(e);
if ( pe->mPacket->isBad() ) {
//AISPacketEvent *pe = static_cast<AISPacketEvent*>(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<string>::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;

View File

@ -21,7 +21,7 @@ public:
virtual
~RXPacketProcessor ();
void processEvent(Event *e);
void processEvent(const Event &e);
private:
NMEAEncoder mEncoder;
time_t mLastDumpTime;

View File

@ -228,10 +228,10 @@ void RadioManager::configureInterrupts()
}
void RadioManager::processEvent(Event *e)
void RadioManager::processEvent(const Event &e)
{
ClockEvent *ce = static_cast<ClockEvent*>(e);
mUTC = ce->mTime;
//ClockEvent *ce = static_cast<ClockEvent*>(e);
mUTC = e.clock.utc;
// Evaluate the state of the transceiver IC and our queue ...
if ( mTransceiverIC->assignedTXPacket() == NULL ) {

View File

@ -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:

View File

@ -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<AISPacketEvent*>(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);
}

View File

@ -43,7 +43,7 @@ private:
void resetBitScanner();
void configureGPIOs();
protected:
RXPacket *mRXPacket;
RXPacket mRXPacket;
uint16_t mBitWindow;
uint8_t mLastNRZIBit;
uint32_t mBitCount;

View File

@ -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<GPSFIXEvent*> (event);
//GPSFIXEvent *gfe = static_cast<GPSFIXEvent*> (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<ClockEvent*>(event);
mUTC = c->mTime;
//ClockEvent *c = static_cast<ClockEvent*>(event);
mUTC = e.clock.utc;
if ( RadioManager::instance().initialized() && mTesting && mUTC % 1 == 0 ) {
scheduleTestPacket();
printf2("Scheduled test packet\r\n");

View File

@ -22,7 +22,7 @@ public:
virtual
~TXScheduler ();
void processEvent(Event *event);
void processEvent(const Event &event);
void startTXTesting();
private:
void scheduleTestPacket();

View File

@ -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();
}
}

View File

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

View File

@ -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<DebugEvent*>(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);