1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-28 13:20:15 -07:00
This commit is contained in:
Peter Antypas 2020-11-25 11:51:25 -08:00
parent 3cd8ed4e22
commit f9280b35ea
11 changed files with 53 additions and 74 deletions

View File

@ -34,7 +34,7 @@ public:
// Called directly by each receiver to report every RSSI reading at every SOTDMA slot
void report(char channel, uint8_t rssi);
void reset();
void recalculate();
// Returns the current noise floor of the channel, 0xff if unknown
uint8_t getNoiseFloor(char channel);

View File

@ -73,8 +73,18 @@
// Maximum allowed backlog in TX queue
#define MAX_TX_PACKETS_IN_QUEUE 4
// Set to true to force RSSI sampling at every SOTDMA timer slot on both channels
#define FULL_RSSI_SAMPLING 1
// Headroom above noise floor (in dB) that constitutes a clear channel for transmission
#define TX_CCA_HEADROOM 3
#if FULL_RSSI_SAMPLING
#define TX_CCA_HEADROOM 2
#else
// When sampling RSSI sparsely, there is a tendency to overestimate the noise floor, so there is no need for headroom
#define TX_CCA_HEADROOM 0
#endif
// Transmission intervals in seconds
#define MIN_TX_INTERVAL 5

View File

@ -107,8 +107,8 @@ void AISMessage::addString(uint8_t *bitVector, uint16_t &size, const string &val
ASSERT(value.length() <= maxChars);
ASSERT(maxChars < 30); // There should be no application for such long strings here
char s[30];
memset(s, 0, sizeof s);
strncpy(s, value.c_str(), value.length());
//memset(s, 0, sizeof s);
strlcpy(s, value.c_str(), sizeof s);
uint8_t buffer[32];
for ( uint8_t c = 0; c < maxChars; ++c ) {

View File

@ -107,8 +107,8 @@ void CommandProcessor::processCommand(const char *buff)
memset(&station, 0, sizeof station);
station.mmsi = Utils::toInt(tokens[0]);
strncpy(station.name, tokens[1].c_str(), sizeof station.name);
strncpy(station.callsign, tokens[2].c_str(), sizeof station.callsign);
strlcpy(station.name, tokens[1].c_str(), sizeof station.name);
strlcpy(station.callsign, tokens[2].c_str(), sizeof station.callsign);
int type = (VesselType)Utils::toInt(tokens[3]);
if ( type == 30 || type == 34 || type == 36 || type == 37 )
station.type = (VesselType)type;

View File

@ -112,7 +112,7 @@ void termInputCB(char c)
{
__rxbuff[__rxpos++] = 0;
Event *e = EventPool::instance().newEvent(COMMAND_EVENT);
strncpy(e->command.buffer, __rxbuff, sizeof e->command.buffer);
strlcpy(e->command.buffer, __rxbuff, sizeof e->command.buffer);
EventQueue::instance().push(e);
}
}

View File

@ -116,7 +116,7 @@ void GPS::onRX(char c)
Event *e = EventPool::instance().newEvent(GPS_NMEA_SENTENCE);
if ( e )
{
strncpy(e->nmeaBuffer.sentence, mBuff, sizeof e->nmeaBuffer.sentence);
strlcpy(e->nmeaBuffer.sentence, mBuff, sizeof e->nmeaBuffer.sentence);
EventQueue::instance ().push(e);
}
mBuffPos = 0;

View File

@ -46,18 +46,9 @@ NoiseFloorDetector::NoiseFloorDetector()
void NoiseFloorDetector::report(char channel, uint8_t rssi)
{
if ( rssi < 0x20 ) // Not realistic, likely a bug
if ( rssi < 0x32 ) // Not realistic, likely a bug
return;
#if 0
processSample(channel == 'A' ? mChannelASamples : mChannelBSamples, rssi);
if ( channel == 'A' )
mChannelACurrent = medianValue(mChannelASamples);
else
mChannelBCurrent = medianValue(mChannelBSamples);
#endif
if ( channel == 'A' )
{
mAFloor = min(mAFloor, rssi);
@ -90,61 +81,16 @@ void NoiseFloorDetector::processEvent(const Event &e)
if ( mTicks == 30 )
{
//DBG("Event pool utilization = %d, max = %d\r\n", EventPool::instance().utilization(), EventPool::instance().maxUtilization());
mChannelACurrent = mAFloor;
mChannelBCurrent = mBFloor;
recalculate();
dump();
reset();
mTicks = 0;
}
break;
#if 0
case RSSI_SAMPLE_EVENT:
{
report(e.rssiSample.channel, e.rssiSample.rssi);
uint8_t rssi = getNoiseFloor(e.rssiSample.channel);
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 )
window.pop_back();
if ( window.empty() )
{
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 )
{
window.insert(i, rssi);
break;
}
}
}
uint8_t NoiseFloorDetector::medianValue(ChannelReadings &window)
{
if ( window.size() < WINDOW_SIZE )
return 0xff;
return window[window.size()/2];
}
#endif
void NoiseFloorDetector::dump()
{
Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE);
@ -164,10 +110,19 @@ void NoiseFloorDetector::dump()
EventQueue::instance().push(e);
}
void NoiseFloorDetector::reset()
void NoiseFloorDetector::recalculate()
{
//mChannelASamples.clear();
//mChannelBSamples.clear();
if ( mChannelACurrent == 0xff || mChannelBCurrent == 0xff )
{
mChannelACurrent = mAFloor;
mChannelBCurrent = mBFloor;
}
else
{
mChannelACurrent = (mChannelACurrent + mAFloor) / 2;
mChannelBCurrent = (mChannelBCurrent + mBFloor) / 2;
}
mAFloor = 0xff;
mBFloor = 0xff;
}

View File

@ -150,16 +150,24 @@ void Receiver::onBitClock()
}
#if ENABLE_TX
/**
* This trick ensures that we only sample RSSI every 17 time slots and never in the
* This trick ensures that we only sample RSSI every N time slots and never in the
* same time slot for both ICs, so we don't conduct long SPI operations on consecutive
* interrupt handlers that might exceed the bit clock period. There is no reason for RSSI
* collection to have a high duty cycle anyway, it just serves to establish the noise floor.
*/
else if ( mTimeSlot != 0xffffffff && mSlotBitNumber != 0xffff &&
mTimeSlot % 17 == mChipID && mSlotBitNumber == CCA_SLOT_BIT - 1 )
#if FULL_RSSI_SAMPLING
else if ( mTimeSlot != 0xffffffff && mSlotBitNumber != 0xffff && mSlotBitNumber == CCA_SLOT_BIT )
{
reportRSSI();
mRXPacket->setRSSI(reportRSSI());
}
#else
else if ( mTimeSlot != 0xffffffff && mSlotBitNumber != 0xffff &&
mTimeSlot % 17 == mChipID &&
mSlotBitNumber == CCA_SLOT_BIT - 1 )
{
mRXPacket->setRSSI(reportRSSI());
}
#endif
#endif
//bsp_signal_low();

View File

@ -73,7 +73,7 @@ time_t TXPacket::timestamp()
void TXPacket::setMessageType(const char *t)
{
strncpy(mMessageType, t, sizeof mMessageType);
strlcpy(mMessageType, t, sizeof mMessageType);
}
bool TXPacket::isTestPacket()

View File

@ -217,7 +217,12 @@ void Transceiver::onBitClock()
}
else if ( mUTC && mSlotBitNumber == CCA_SLOT_BIT && mTXPacket->channel() == mChannel )
{
#if FULL_RSSI_SAMPLING
// It has already been sampled during Receiver::onBitClock();
int rssi = mRXPacket->rssi();
#else
int rssi = readRSSI();
#endif
int nf = NoiseFloorDetector::instance().getNoiseFloor(AIS_CHANNELS[mChannel].designation);
if ( rssi <= nf + TX_CCA_HEADROOM )
{

View File

@ -58,7 +58,7 @@ static const GPIO __gpios[] = {
{TX_DISABLE_PORT, {TX_DISABLE_PIN, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET},
{CS2_PORT, {CS2_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, 0}, GPIO_PIN_SET},
{RX_EVT_PORT, {RX_EVT_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET},
{GNSS_1PPS_PORT, {GNSS_1PPS_PIN, GPIO_MODE_IT_FALLING, GPIO_PULLUP, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET},
{GNSS_1PPS_PORT, {GNSS_1PPS_PIN, GPIO_MODE_IT_FALLING, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET},
{GNSS_NMEA_RX_PORT, {GNSS_NMEA_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_LOW, GPIO_AF7_USART2}, GPIO_PIN_RESET},
{CS1_PORT, {CS1_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, 0}, GPIO_PIN_SET},
{SCK_PORT, {SCK_PIN, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF5_SPI1}, GPIO_PIN_SET},
@ -384,7 +384,6 @@ void bsp_gnss_on()
void bsp_gnss_off()
{
HAL_GPIO_WritePin(GNSS_EN_PORT, GNSS_EN_PIN, GPIO_PIN_RESET);
HAL_Delay(10);
}
@ -541,6 +540,8 @@ void bsp_enter_dfu()
// Cut off the GPS signals immediately to prevent its UART from transmitting and hijacking the bootloader upon reset
bsp_gnss_off();
HAL_Delay(1000);
// This flag simply tells main() to jump to the ROM bootloader immediately upon reset, before initializing anything
*(uint32_t*)DFU_FLAG_ADDRESS = DFU_FLAG_MAGIC;