From 735e36acd1f64bc9798730897fc31557fc0952be Mon Sep 17 00:00:00 2001 From: Peter Antypas Date: Mon, 20 Sep 2021 14:26:37 -0700 Subject: [PATCH] WIP --- .../Transponder/Inc/Configuration.hpp | 2 + latest/Firmware/Transponder/Inc/TXErrors.h | 21 +++++++++++ .../Firmware/Transponder/Inc/TXScheduler.hpp | 1 + latest/Firmware/Transponder/Inc/bsp/bsp.hpp | 3 ++ latest/Firmware/Transponder/Inc/config.h | 3 +- .../Transponder/Src/CommandProcessor.cpp | 5 ++- .../Transponder/Src/Configuration.cpp | 34 +++++++++++++---- .../Firmware/Transponder/Src/LEDManager.cpp | 10 +++++ .../Firmware/Transponder/Src/RadioManager.cpp | 34 ++++++++--------- .../Firmware/Transponder/Src/TXScheduler.cpp | 37 +++++++++++++++---- .../Firmware/Transponder/Src/Transceiver.cpp | 10 +++++ .../Firmware/Transponder/Src/bsp/bsp_11_0.cpp | 2 + 12 files changed, 127 insertions(+), 35 deletions(-) create mode 100644 latest/Firmware/Transponder/Inc/TXErrors.h diff --git a/latest/Firmware/Transponder/Inc/Configuration.hpp b/latest/Firmware/Transponder/Inc/Configuration.hpp index c76de47..f861b01 100644 --- a/latest/Firmware/Transponder/Inc/Configuration.hpp +++ b/latest/Firmware/Transponder/Inc/Configuration.hpp @@ -22,6 +22,7 @@ #include "StationData.h" #include "OTPData.h" +#include "config.h" // This should be plenty big (no need to be a whole flash page though) typedef union @@ -46,6 +47,7 @@ public: void reportOTPData(); const OTPData *readOTP(); bool writeOTP(const OTPData &data); + void reportSystemData(); private: Configuration(); bool erasePage(); diff --git a/latest/Firmware/Transponder/Inc/TXErrors.h b/latest/Firmware/Transponder/Inc/TXErrors.h new file mode 100644 index 0000000..7cdd891 --- /dev/null +++ b/latest/Firmware/Transponder/Inc/TXErrors.h @@ -0,0 +1,21 @@ +/* + * TXErrors.h + * + * Created on: Sep 18, 2021 + * Author: peter + */ + +#ifndef INC_TXERRORS_H_ +#define INC_TXERRORS_H_ + +typedef enum +{ + TX_NO_ERROR = 0, + TX_ALLOC_ERROR, + TX_QUEUE_FULL, + TX_PACKET_TOO_OLD, +} TXErrorCode; + + + +#endif /* INC_TXERRORS_H_ */ diff --git a/latest/Firmware/Transponder/Inc/TXScheduler.hpp b/latest/Firmware/Transponder/Inc/TXScheduler.hpp index 1203b95..e4eae09 100644 --- a/latest/Firmware/Transponder/Inc/TXScheduler.hpp +++ b/latest/Firmware/Transponder/Inc/TXScheduler.hpp @@ -30,6 +30,7 @@ private: TXScheduler (); virtual ~TXScheduler (); time_t positionReportTimeInterval(); + void sendNMEASentence(const char *sentence); private: VHFChannel mPositionReportChannel; VHFChannel mStaticDataChannel; diff --git a/latest/Firmware/Transponder/Inc/bsp/bsp.hpp b/latest/Firmware/Transponder/Inc/bsp/bsp.hpp index f5ff4aa..4f9c5d8 100644 --- a/latest/Firmware/Transponder/Inc/bsp/bsp.hpp +++ b/latest/Firmware/Transponder/Inc/bsp/bsp.hpp @@ -83,6 +83,9 @@ void bsp_set_sotdma_timer_value(uint32_t v); uint8_t bsp_tx_spi_byte(uint8_t b); + +extern const char *BSP_HW_REV; + // BSP headers go here #if BOARD_REV == 93 diff --git a/latest/Firmware/Transponder/Inc/config.h b/latest/Firmware/Transponder/Inc/config.h index 2c08721..f8a7c77 100644 --- a/latest/Firmware/Transponder/Inc/config.h +++ b/latest/Firmware/Transponder/Inc/config.h @@ -87,7 +87,8 @@ #define CLI_FLAG_MAGIC 0x209a388d #define CONFIGURATION_ADDRESS 0x0800F800 +#define OTP_DATA 0 - +#define FW_REV "3.1.0" #endif /* CONFIG_H_ */ diff --git a/latest/Firmware/Transponder/Src/CommandProcessor.cpp b/latest/Firmware/Transponder/Src/CommandProcessor.cpp index 4ce613d..48b7a7f 100644 --- a/latest/Firmware/Transponder/Src/CommandProcessor.cpp +++ b/latest/Firmware/Transponder/Src/CommandProcessor.cpp @@ -157,6 +157,7 @@ void CommandProcessor::processCommand(const char *buff) { TXScheduler::instance().queueMessage24(CH_87); } +#if OTP_DATA else if ( s.find("otp?") == 0 ) { dumpOTPData(); @@ -165,6 +166,7 @@ void CommandProcessor::processCommand(const char *buff) { writeOTPData(s); } +#endif } void CommandProcessor::enterCLIMode() @@ -178,6 +180,7 @@ void CommandProcessor::jumpToBootloader() bsp_enter_dfu(); } +#if OTP_DATA void CommandProcessor::dumpOTPData() { Configuration::instance().reportOTPData(); @@ -204,5 +207,5 @@ void CommandProcessor::writeOTPData(const std::string &s) if ( result ) dumpOTPData(); } - +#endif diff --git a/latest/Firmware/Transponder/Src/Configuration.cpp b/latest/Firmware/Transponder/Src/Configuration.cpp index a095e63..426cd7a 100644 --- a/latest/Firmware/Transponder/Src/Configuration.cpp +++ b/latest/Firmware/Transponder/Src/Configuration.cpp @@ -23,6 +23,8 @@ #include "config.h" #include "EventQueue.hpp" #include +#include + // These are not defined in ANY CMSIS or HAL header, WTF ST??? #define OTP_ADDRESS 0x1FFF7000 @@ -60,11 +62,24 @@ void Configuration::init() bool cliBootMode = *(uint32_t*)BOOTMODE_ADDRESS == CLI_FLAG_MAGIC; if ( !cliBootMode ) { - reportOTPData(); + //reportOTPData(); + reportSystemData(); reportStationData(); } } +void Configuration::reportSystemData() +{ + Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + if ( !e ) + return; + + sprintf(e->nmeaBuffer.sentence, "$PAISYS,%s,%s,%s*", BSP_HW_REV, FW_REV, ""); + + Utils::completeNMEA(e->nmeaBuffer.sentence); + EventQueue::instance().push(e); +} + void Configuration::reportStationData() { StationData d; @@ -72,6 +87,9 @@ void Configuration::reportStationData() memset(&d, 0, sizeof d); Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + if ( !e ) + return; + sprintf(e->nmeaBuffer.sentence, "$PAISTN,%lu,%s,%s,%d,%d,%d,%d,%d*", d.mmsi, @@ -93,23 +111,23 @@ bool Configuration::isStationDataProvisioned() return readStationData(d); } +#if OTP_DATA void Configuration::reportOTPData() { const OTPData *data = readOTP(); Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + if ( !e ) + return; - if ( data == nullptr ) + if ( data ) { - strcpy(e->nmeaBuffer.sentence, "$PAISYS,,*"); - } - else - { - sprintf(e->nmeaBuffer.sentence, "$PAISYS,%s,%s*", data->serialnum, data->hwrev); + sprintf(e->nmeaBuffer.sentence, "$PAIOTP,%s,%s*", data->serialnum, data->hwrev); } Utils::completeNMEA(e->nmeaBuffer.sentence); EventQueue::instance().push(e); } +#endif bool Configuration::erasePage() { @@ -184,6 +202,7 @@ bool Configuration::readStationData(StationData &data) return data.magic == STATION_DATA_MAGIC; } +#if OTP_DATA const OTPData *Configuration::readOTP() { uint32_t address = nextAvailableOTPSlot(); @@ -231,6 +250,7 @@ uint32_t Configuration::nextAvailableOTPSlot() return OTP_ADDRESS+OTP_SIZE; } +#endif diff --git a/latest/Firmware/Transponder/Src/LEDManager.cpp b/latest/Firmware/Transponder/Src/LEDManager.cpp index c08e891..9b916d9 100644 --- a/latest/Firmware/Transponder/Src/LEDManager.cpp +++ b/latest/Firmware/Transponder/Src/LEDManager.cpp @@ -21,6 +21,16 @@ #include "bsp.hpp" #include "Configuration.hpp" + +/** + * TODO: Update this to manage the status of the TX LED without any external hardware logic. + * It must take all inputs into consideration: + * + * - Presence of station data + * - Status of TX_DISABLE signal + * - Status of "tx off" software setting + */ + LEDManager::LEDManager() { // Do nothing diff --git a/latest/Firmware/Transponder/Src/RadioManager.cpp b/latest/Firmware/Transponder/Src/RadioManager.cpp index c503032..0e24249 100644 --- a/latest/Firmware/Transponder/Src/RadioManager.cpp +++ b/latest/Firmware/Transponder/Src/RadioManager.cpp @@ -21,7 +21,7 @@ #include "RadioManager.hpp" #include "NoiseFloorDetector.hpp" #include "bsp.hpp" - +#include "TXErrors.h" void rxClockCB(); void trxClockCB(); @@ -39,7 +39,6 @@ RadioManager::RadioManager() mTransceiverIC = NULL; mReceiverIC = NULL; mInitializing = true; - //mTXQueue = new CircularQueue(4); mUTC = 0; EventQueue::instance().addObserver(this, CLOCK_EVENT); } @@ -52,24 +51,19 @@ bool RadioManager::initialized() void RadioManager::init() { NoiseFloorDetector::instance(); - //DBG("Initializing RF IC 1\r\n"); mTransceiverIC = new Transceiver(SDN1_PORT, SDN1_PIN, CS1_PORT, CS1_PIN, TRX_IC_DATA_PORT, TRX_IC_DATA_PIN, TRX_IC_CLK_PORT, TRX_IC_CLK_PIN, 0); mTransceiverIC->init(); -#ifndef TX_TEST_MODE - //DBG("Initializing RF IC 2\r\n"); mReceiverIC = new Receiver(SDN2_PORT, SDN2_PIN, CS2_PORT, CS2_PIN, RX_IC_DATA_PORT, RX_IC_DATA_PIN, RX_IC_CLK_PORT, RX_IC_CLK_PIN, 1); mReceiverIC->init(); -#endif mInitializing = false; - //DBG("Radio ICs initialized\r\n"); } void RadioManager::transmitCW(VHFChannel channel) @@ -79,7 +73,6 @@ void RadioManager::transmitCW(VHFChannel channel) void RadioManager::start() { - //DBG("Radio Manager starting\r\n"); configureInterrupts(); if ( mTransceiverIC ) mTransceiverIC->startReceiving(CH_87, true); @@ -88,7 +81,6 @@ void RadioManager::start() mReceiverIC->startReceiving(CH_88, true); GPS::instance().setDelegate(this); - //DBG("Radio Manager started\r\n"); } void RadioManager::stop() @@ -124,14 +116,11 @@ void RadioManager::processEvent(const Event &e) // Do we need to swap channels? if ( txChannel != mTransceiverIC->channel() ) { - //DBG("RadioManager swapping channels for ICs\r\n"); // The receiver needs to be explicitly told to switch channels if ( mReceiverIC ) mReceiverIC->switchToChannel(alternateChannel(txChannel)); } - //DBG("RadioManager assigned TX packet\r\n"); - // The transceiver will switch channel if the packet channel is different mTransceiverIC->assignTXPacket(packet); } @@ -170,22 +159,31 @@ void RadioManager::timeSlotStarted(uint32_t slotNumber) if ( mInitializing ) return; -#ifndef TX_TEST_MODE mTransceiverIC->timeSlotStarted(slotNumber); mReceiverIC->timeSlotStarted(slotNumber); -#endif } void RadioManager::scheduleTransmission(TXPacket *packet) { - if ( mTXQueue.push(packet) ) + Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + if ( !mTXQueue.push(packet) ) { - //DBG("RadioManager queued TX packet for channel %d\r\n", ORDINAL_TO_ITU(packet->channel())); + if ( e ) + { + sprintf(e->nmeaBuffer.sentence, "$PAISCHTX,%s,%d*", packet->messageType(), TX_QUEUE_FULL); + Utils::completeNMEA(e->nmeaBuffer.sentence); + EventQueue::instance().push(e); + } + TXPacketPool::instance().deleteTXPacket(packet); } else { - //DBG("RadioManager rejected TX packet for channel %d\r\n", ORDINAL_TO_ITU(packet->channel())); - TXPacketPool::instance().deleteTXPacket(packet); + if ( e ) + { + sprintf(e->nmeaBuffer.sentence, "$PAISCHTX,%s,%d*", packet->messageType(), TX_NO_ERROR); + Utils::completeNMEA(e->nmeaBuffer.sentence); + EventQueue::instance().push(e); + } } } diff --git a/latest/Firmware/Transponder/Src/TXScheduler.cpp b/latest/Firmware/Transponder/Src/TXScheduler.cpp index 95f6e0e..a4d6d94 100644 --- a/latest/Firmware/Transponder/Src/TXScheduler.cpp +++ b/latest/Firmware/Transponder/Src/TXScheduler.cpp @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see -*/ + */ #include "TXScheduler.hpp" @@ -29,6 +29,7 @@ #include #include "RadioManager.hpp" #include "ChannelManager.hpp" +#include "TXErrors.h" #include "printf_serial.h" #include "bsp.hpp" @@ -144,17 +145,32 @@ void TXScheduler::processEvent(const Event &e) } +void TXScheduler::sendNMEASentence(const char *sentence) +{ + Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + if ( !e ) + return; + + strlcpy(e->nmeaBuffer.sentence, sentence, sizeof e->nmeaBuffer.sentence); + Utils::completeNMEA(e->nmeaBuffer.sentence); + EventQueue::instance().push(e); +} + void TXScheduler::queueMessage18(VHFChannel channel) { + char sentence[48]; + // If we don't have valid station data we don't do anything if ( mStationData.magic != STATION_DATA_MAGIC ) return; TXPacket *p1 = TXPacketPool::instance().newTXPacket(channel); - if ( !p1 ) { - //DBG("Unable to allocate TX packet for message 18, will try again later\r\n"); + if ( !p1 ) + { + sprintf(sentence, "$PAISCHTX,18,%d*", TX_ALLOC_ERROR); + sendNMEASentence(sentence); return; - } + } AISMessage18 msg; msg.latitude = mLastGPSFix.lat; @@ -169,15 +185,19 @@ void TXScheduler::queueMessage18(VHFChannel channel) void TXScheduler::queueMessage24(VHFChannel channel) { + char sentence[48]; + // If we don't have valid station data we don't do anything if ( mStationData.magic != STATION_DATA_MAGIC ) return; TXPacket *p2 = TXPacketPool::instance().newTXPacket(channel); - if ( !p2 ) { - //DBG("Unable to allocate TX packet for 24A\r\n"); + if ( !p2 ) + { + sprintf(sentence, "$PAISCHTX,24A,%d*", TX_ALLOC_ERROR); + sendNMEASentence(sentence); return; - } + } AISMessage24A msg2; msg2.encode(mStationData, *p2); @@ -187,7 +207,8 @@ void TXScheduler::queueMessage24(VHFChannel channel) TXPacket *p3 = TXPacketPool::instance().newTXPacket(channel); if ( !p3 ) { - //DBG("Unable to allocate TX packet for 24B\r\n"); + sprintf(sentence, "$PAISCHTX,24B,%d*", TX_ALLOC_ERROR); + sendNMEASentence(sentence); return; } diff --git a/latest/Firmware/Transponder/Src/Transceiver.cpp b/latest/Firmware/Transponder/Src/Transceiver.cpp index 07ca3ad..f3f1d59 100644 --- a/latest/Firmware/Transponder/Src/Transceiver.cpp +++ b/latest/Firmware/Transponder/Src/Transceiver.cpp @@ -25,6 +25,7 @@ #include "EZRadioPRO.h" #include "AISChannels.h" #include "bsp.hpp" +#include "TXErrors.h" #include Transceiver::Transceiver(GPIO_TypeDef *sdnPort, uint32_t sdnPin, GPIO_TypeDef *csPort, @@ -214,11 +215,20 @@ void Transceiver::onBitClock() else if ( mUTC && mUTC - mTXPacket->timestamp() >= MIN_MSG_18_TX_INTERVAL ) { // The packet is way too old. Discard it. + Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + if ( e ) + { + sprintf(e->nmeaBuffer.sentence, "$PAISCHTX,%s,%d*", mTXPacket->messageType(), TX_PACKET_TOO_OLD); + Utils::completeNMEA(e->nmeaBuffer.sentence); + EventQueue::instance().push(e); + } + TXPacketPool::instance().deleteTXPacket(mTXPacket); mTXPacket = NULL; } else if ( mUTC - mLastTXTime < MIN_TX_INTERVAL ) { + // It's not time to transmit yet return; } else if ( mUTC && mSlotBitNumber == CCA_SLOT_BIT && mTXPacket->channel() == mChannel ) diff --git a/latest/Firmware/Transponder/Src/bsp/bsp_11_0.cpp b/latest/Firmware/Transponder/Src/bsp/bsp_11_0.cpp index ead1344..87cf54b 100644 --- a/latest/Firmware/Transponder/Src/bsp/bsp_11_0.cpp +++ b/latest/Firmware/Transponder/Src/bsp/bsp_11_0.cpp @@ -27,6 +27,8 @@ #if BOARD_REV==110 +const char *BSP_HW_REV = "11.x"; + SPI_HandleTypeDef hspi1; IWDG_HandleTypeDef hiwdg; UART_HandleTypeDef huart2;