diff --git a/latest/Firmware/Inc/NoiseFloorDetector.hpp b/latest/Firmware/Inc/NoiseFloorDetector.hpp index d042922..0fa2ef0 100644 --- a/latest/Firmware/Inc/NoiseFloorDetector.hpp +++ b/latest/Firmware/Inc/NoiseFloorDetector.hpp @@ -23,8 +23,6 @@ #include "AISChannels.h" #include "Events.hpp" -#include - using namespace std; @@ -33,35 +31,35 @@ class NoiseFloorDetector : public EventConsumer public: static NoiseFloorDetector &instance(); - // Called directly by each receiver to report every RSSI reading at every SOTDMA slot - void report(VHFChannel channel, uint8_t rssi); + void report(char channel, uint8_t rssi); void reset(); // Returns the current noise floor of the channel, 0xff if unknown - uint8_t getNoiseFloor(VHFChannel channelIndex); + uint8_t getNoiseFloor(char channel); void processEvent(const Event &e); private: - typedef struct - { - uint8_t reading; - } Reading; - // TODO: Use a circular buffer instead, no need for STL here - typedef vector ChannelReadings; - typedef map ChannelData; + //typedef vector ChannelReadings; + //ChannelReadings mChannelASamples; + //ChannelReadings mChannelBSamples; + + uint8_t mChannelACurrent; + uint8_t mChannelBCurrent; + + uint8_t mAFloor; + uint8_t mBFloor; private: NoiseFloorDetector(); - void processSample(ChannelReadings &window, uint8_t rssi); - uint8_t medianValue(ChannelReadings &window); + //void processSample(ChannelReadings &window, uint8_t rssi); + //uint8_t medianValue(ChannelReadings &window); void dump(); private: uint32_t mTicks; - ChannelData mData; }; diff --git a/latest/Firmware/Src/NoiseFloorDetector.cpp b/latest/Firmware/Src/NoiseFloorDetector.cpp index 3dcadb9..623903c 100644 --- a/latest/Firmware/Src/NoiseFloorDetector.cpp +++ b/latest/Firmware/Src/NoiseFloorDetector.cpp @@ -15,16 +15,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see -*/ + */ #include "NoiseFloorDetector.hpp" #include "EventQueue.hpp" -#include #include "AISChannels.h" -#include "_assert.h" -#include "printf_serial.h" -#include "RadioManager.hpp" #define WINDOW_SIZE 10 @@ -38,34 +34,45 @@ NoiseFloorDetector &NoiseFloorDetector::instance() NoiseFloorDetector::NoiseFloorDetector() : mTicks(0xffffffff) { - EventQueue::instance().addObserver(this, CLOCK_EVENT|RSSI_SAMPLE_EVENT); + //mChannelASamples.reserve(WINDOW_SIZE); + //mChannelBSamples.reserve(WINDOW_SIZE); + mChannelACurrent = 0xff; + mChannelBCurrent = 0xff; + + mAFloor = 0xff; + mBFloor = 0xff; + EventQueue::instance().addObserver(this, CLOCK_EVENT); } -void NoiseFloorDetector::report(VHFChannel channel, uint8_t rssi) +void NoiseFloorDetector::report(char channel, uint8_t rssi) { if ( rssi < 0x20 ) // Not realistic, likely a bug return; - if ( mData.find(channel) == mData.end() ) +#if 0 + processSample(channel == 'A' ? mChannelASamples : mChannelBSamples, rssi); + + if ( channel == 'A' ) + mChannelACurrent = medianValue(mChannelASamples); + else + mChannelBCurrent = medianValue(mChannelBSamples); +#endif + + if ( channel == 'A' ) { - ChannelReadings r; - r.reserve(WINDOW_SIZE*2); - mData[channel] = r; + mAFloor = min(mAFloor, rssi); + } + else + { + mBFloor = min(mBFloor, rssi); } - - ChannelReadings &window = mData[channel]; - processSample(window, rssi); } -uint8_t NoiseFloorDetector::getNoiseFloor(VHFChannel channel) +uint8_t NoiseFloorDetector::getNoiseFloor(char channel) { - if ( mData.find(channel) == mData.end() ) - return 0xff; - - return medianValue(mData[channel]); + return channel == 'A' ? mChannelACurrent : mChannelBCurrent; } - void NoiseFloorDetector::processEvent(const Event &e) { switch(e.type) @@ -80,14 +87,17 @@ void NoiseFloorDetector::processEvent(const Event &e) ++mTicks; } - if ( mTicks == 30 ) + if ( mTicks == 10 ) { //DBG("Event pool utilization = %d, max = %d\r\n", EventPool::instance().utilization(), EventPool::instance().maxUtilization()); + mChannelACurrent = mAFloor; + mChannelBCurrent = mBFloor; dump(); reset(); mTicks = 0; } break; +#if 0 case RSSI_SAMPLE_EVENT: { report(e.rssiSample.channel, e.rssiSample.rssi); @@ -95,11 +105,13 @@ void NoiseFloorDetector::processEvent(const Event &e) RadioManager::instance().noiseFloorUpdated(e.rssiSample.channel, rssi); } break; +#endif default: break; } } +#if 0 void NoiseFloorDetector::processSample(ChannelReadings &window, uint8_t rssi) { while ( window.size() >= WINDOW_SIZE ) @@ -107,50 +119,51 @@ void NoiseFloorDetector::processSample(ChannelReadings &window, uint8_t rssi) if ( window.empty() ) { - Reading r; - r.reading = rssi; - window.push_back(r); + window.push_back(rssi); return; } // Insert the reading at the start if it qualifies for ( ChannelReadings::iterator i = window.begin(); i != window.end(); ++i ) { - if ( rssi <= i->reading ) + if ( rssi <= *i ) { - Reading r; - r.reading = rssi; - window.insert(i, r); + window.insert(i, rssi); break; } } + } uint8_t NoiseFloorDetector::medianValue(ChannelReadings &window) { - if ( window.empty() ) + if ( window.size() < WINDOW_SIZE ) return 0xff; - return window[window.size()/2].reading; + return window[window.size()/2]; } +#endif void NoiseFloorDetector::dump() { Event e(PROPR_NMEA_SENTENCE); - for ( ChannelData::iterator cIt = mData.begin(); cIt != mData.end(); ++cIt ) - { - uint8_t value = medianValue(cIt->second); - //DBG("[Channel %d noise floor: 0x%.2x]\r\n", AIS_CHANNELS[cIt->first].itu, value); - sprintf(e.nmeaBuffer.sentence, "$PAINF,%c,0x%.2x*", AIS_CHANNELS[cIt->first].designation, value); - Utils::completeNMEA(e.nmeaBuffer.sentence); - EventQueue::instance().push(e); - } + + sprintf(e.nmeaBuffer.sentence, "$PAINF,A,0x%.2x*", mChannelACurrent); + Utils::completeNMEA(e.nmeaBuffer.sentence); + EventQueue::instance().push(e); + + sprintf(e.nmeaBuffer.sentence, "$PAINF,B,0x%.2x*", mChannelBCurrent); + Utils::completeNMEA(e.nmeaBuffer.sentence); + EventQueue::instance().push(e); } void NoiseFloorDetector::reset() { - mData.clear(); + //mChannelASamples.clear(); + //mChannelBSamples.clear(); + mAFloor = 0xff; + mBFloor = 0xff; } diff --git a/latest/Firmware/Src/Receiver.cpp b/latest/Firmware/Src/Receiver.cpp index dcae981..73ed548 100644 --- a/latest/Firmware/Src/Receiver.cpp +++ b/latest/Firmware/Src/Receiver.cpp @@ -109,13 +109,14 @@ void Receiver::onBitClock() uint8_t bit = HAL_GPIO_ReadPin(mDataPort, mDataPin); processNRZIBit(bit); - ++mSlotBitNumber; -#if 0 - if ( (mSlotBitNumber != 0xffff) && (mSlotBitNumber++ == CCA_SLOT_BIT) ) +#if 1 + if ( mSlotBitNumber != 0xffff && mSlotBitNumber++ == CCA_SLOT_BIT - 1 ) { uint8_t rssi = reportRSSI(); mRXPacket.setRSSI(rssi); } +#else + ++mSlotBitNumber; #endif } @@ -257,10 +258,18 @@ void Receiver::pushPacket() uint8_t Receiver::reportRSSI() { uint8_t rssi = readRSSI(); + +#if 0 Event e(RSSI_SAMPLE_EVENT); e.rssiSample.channel = mChannel; e.rssiSample.rssi = rssi; EventQueue::instance().push(e); +#endif + + + char channel = AIS_CHANNELS[mChannel].designation; + NoiseFloorDetector::instance().report(channel, rssi); + return rssi; } diff --git a/latest/Firmware/Src/Transceiver.cpp b/latest/Firmware/Src/Transceiver.cpp index dd50d3e..64fb7b9 100644 --- a/latest/Firmware/Src/Transceiver.cpp +++ b/latest/Firmware/Src/Transceiver.cpp @@ -231,8 +231,9 @@ void Transceiver::onBitClock() } else if ( mUTC && mSlotBitNumber == CCA_SLOT_BIT && mTXPacket->channel() == mChannel ) { - uint8_t rssi = readRSSI(); - if ( rssi <= bsp_noise_floor() + TX_CCA_HEADROOM ) + int rssi = mRXPacket.rssi(); + int nf = NoiseFloorDetector::instance().getNoiseFloor(AIS_CHANNELS[mChannel].designation); + if ( rssi <= nf + TX_CCA_HEADROOM ) { startTransmitting(); }