mirror of
https://github.com/peterantypas/maiana.git
synced 2025-05-28 13:20:15 -07:00
WIP
This commit is contained in:
parent
3cd8ed4e22
commit
f9280b35ea
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user