mirror of
https://github.com/peterantypas/maiana.git
synced 2025-06-04 00:30:16 -07:00
257 lines
6.1 KiB
C++
257 lines
6.1 KiB
C++
/*
|
|
* Receiver.cpp
|
|
*
|
|
* Created on: May 21, 2016
|
|
* Author: peter
|
|
*/
|
|
|
|
#include "Receiver.hpp"
|
|
#include "EZRadioPRO.h"
|
|
#include "Events.hpp"
|
|
#include "EventQueue.hpp"
|
|
#include "NoiseFloorDetector.hpp"
|
|
|
|
|
|
Receiver::Receiver(SPI_TypeDef *spi, GPIO_TypeDef *sdnPort, uint16_t sdnPin, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *gpio1Port, uint16_t gpio1Pin,
|
|
GPIO_TypeDef *gpio3Port, uint16_t gpio3Pin)
|
|
: RFIC(spi, sdnPort, sdnPin, csPort, csPin, gpio1Port, gpio1Pin, gpio3Port, gpio3Pin)
|
|
{
|
|
mSlotBitNumber = 0xffff;
|
|
mSwitchAtNextSlot = false;
|
|
}
|
|
|
|
Receiver::~Receiver()
|
|
{
|
|
}
|
|
|
|
VHFChannel Receiver::channel()
|
|
{
|
|
return mChannel;
|
|
}
|
|
|
|
bool Receiver::init()
|
|
{
|
|
printf2("Configuring IC\r\n");
|
|
configure();
|
|
mRXPacket = RXPacketPool::instance().newRXPacket();
|
|
resetBitScanner();
|
|
return true;
|
|
}
|
|
|
|
void Receiver::startReceiving(VHFChannel channel)
|
|
{
|
|
mChannel = channel;
|
|
startListening(mChannel);
|
|
resetBitScanner();
|
|
}
|
|
|
|
void Receiver::switchToChannel(VHFChannel channel)
|
|
{
|
|
mSwitchAtNextSlot = true;
|
|
mSwitchToChannel = channel;
|
|
}
|
|
|
|
void Receiver::startListening(VHFChannel channel)
|
|
{
|
|
mChannel = channel;
|
|
RX_OPTIONS options;
|
|
options.channel = AIS_CHANNELS[channel].ordinal;
|
|
options.condition = 0;
|
|
options.rx_len = 0;
|
|
options.next_state1 = 0;
|
|
options.next_state2 = 0;
|
|
options.next_state3 = 0;
|
|
|
|
configureGPIOs();
|
|
sendCmd (START_RX, &options, sizeof options, NULL, 0);
|
|
}
|
|
|
|
void Receiver::resetBitScanner()
|
|
{
|
|
mBitWindow = 0;
|
|
mBitCount = 0;
|
|
mOneBitCount = 0;
|
|
mLastNRZIBit = 0xff;
|
|
mRXByte = 0;
|
|
mBitState = BIT_STATE_PREAMBLE_SYNC;
|
|
|
|
ASSERT(mRXPacket);
|
|
mRXPacket->reset();
|
|
}
|
|
|
|
void Receiver::onBitClock()
|
|
{
|
|
// Don't waste time processing bits when the transceiver is transmitting
|
|
if ( gRadioState == RADIO_TRANSMITTING )
|
|
return;
|
|
|
|
uint8_t rssi = 0;
|
|
uint8_t bit = GPIO_ReadInputDataBit(mGPIO1P, mGPIO1Pin);
|
|
processNRZIBit(bit);
|
|
|
|
if ( (mSlotBitNumber != 0xffff) && (mSlotBitNumber++ == CCA_SLOT_BIT) ) {
|
|
rssi = readRSSI();
|
|
rssi += mRSSIAdjustment;
|
|
NoiseFloorDetector::instance().report(mChannel, rssi);
|
|
mRXPacket->setRSSI(rssi);
|
|
}
|
|
}
|
|
|
|
void Receiver::timeSlotStarted(uint32_t slot)
|
|
{
|
|
// This should never be called while transmitting. Transmissions start after the slot boundary and end before the end of it.
|
|
//assert(gRadioState == RADIO_RECEIVING);
|
|
if ( gRadioState != RADIO_RECEIVING )
|
|
printf2(" **** WTF??? Transmitting past slot boundary? **** \r\n");
|
|
|
|
mSlotBitNumber = 0;
|
|
if ( mBitState == BIT_STATE_IN_PACKET )
|
|
return;
|
|
|
|
mRXPacket->setSlot(slot);
|
|
if ( mSwitchAtNextSlot ) {
|
|
mSwitchAtNextSlot = false;
|
|
startReceiving(mSwitchToChannel);
|
|
}
|
|
}
|
|
|
|
void Receiver::processNRZIBit(uint8_t bit)
|
|
{
|
|
if ( mLastNRZIBit == 0xff ) {
|
|
mLastNRZIBit = bit;
|
|
return;
|
|
}
|
|
|
|
uint8_t decodedBit = !(mLastNRZIBit ^ bit);
|
|
|
|
switch (mBitState) {
|
|
case BIT_STATE_PREAMBLE_SYNC: {
|
|
mLastNRZIBit = bit;
|
|
mBitWindow <<= 1;
|
|
mBitWindow |= decodedBit;
|
|
|
|
/*
|
|
* By checking for the last few training bits plus the HDLC start flag,
|
|
* we gain enough confidence that this is not random noise.
|
|
*/
|
|
if ( mBitWindow == 0b1010101001111110 || mBitWindow == 0b0101010101111110 ) {
|
|
mBitState = BIT_STATE_IN_PACKET;
|
|
mRXPacket->setChannel(mChannel);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case BIT_STATE_IN_PACKET: {
|
|
if ( mRXPacket->size() >= MAX_AIS_RX_PACKET_SIZE ) {
|
|
// Start over
|
|
startReceiving(mChannel);
|
|
//resetBitScanner();
|
|
return;
|
|
}
|
|
|
|
if ( mOneBitCount >= 7 ) {
|
|
// Bad packet!
|
|
resetBitScanner();
|
|
startReceiving(mChannel);
|
|
return;
|
|
}
|
|
|
|
mLastNRZIBit = bit;
|
|
mBitWindow <<= 1;
|
|
mBitWindow |= decodedBit;
|
|
|
|
|
|
|
|
if ( (mBitWindow & 0x00ff) == 0x7E ) {
|
|
mBitState = BIT_STATE_PREAMBLE_SYNC;
|
|
pushPacket();
|
|
startReceiving(mChannel);
|
|
}
|
|
else {
|
|
addBit(decodedBit);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
bool Receiver::addBit(uint8_t bit)
|
|
{
|
|
bool result = true;
|
|
if ( bit ) {
|
|
++mOneBitCount;
|
|
}
|
|
else {
|
|
// Don't put stuffed bits into the packet
|
|
if ( mOneBitCount == 5 )
|
|
result = false;
|
|
|
|
mOneBitCount = 0;
|
|
}
|
|
|
|
if ( result ) {
|
|
mRXByte <<= 1;
|
|
mRXByte |= bit;
|
|
++mBitCount;
|
|
}
|
|
|
|
if ( mBitCount == 8 ) {
|
|
// Commit to the packet!
|
|
mRXPacket->addByte(mRXByte);
|
|
mBitCount = 0;
|
|
mRXByte = 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void Receiver::pushPacket()
|
|
{
|
|
AISPacketEvent *p = static_cast<AISPacketEvent*>(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);
|
|
EventQueue::instance().push(p);
|
|
}
|
|
|
|
void Receiver::configureGPIOs()
|
|
{
|
|
// Configure MCU pin for RFIC GPIO1 as input (RX_DATA below)
|
|
GPIO_InitTypeDef gpio;
|
|
gpio.GPIO_Pin = mGPIO1Pin;
|
|
gpio.GPIO_Mode = GPIO_Mode_IN;
|
|
gpio.GPIO_Speed = GPIO_Speed_Level_1;
|
|
gpio.GPIO_OType = GPIO_OType_PP;
|
|
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
|
GPIO_Init(mGPIO1P, &gpio);
|
|
|
|
|
|
/*
|
|
* Configure radio GPIOs for RX:
|
|
* GPIO 0: Don't care
|
|
* GPIO 1: RX_DATA
|
|
* GPIO 2: Don't care
|
|
* GPIO 3: RX_TX_DATA_CLK
|
|
* NIRQ : SYNC_WORD_DETECT
|
|
*/
|
|
|
|
GPIO_PIN_CFG_PARAMS gpiocfg;
|
|
gpiocfg.GPIO0 = 0x00; // No change
|
|
gpiocfg.GPIO1 = 0x14; // RX data bits
|
|
gpiocfg.GPIO2 = 0x00; // No change
|
|
gpiocfg.GPIO3 = 0x1F; // RX/TX data clock
|
|
gpiocfg.NIRQ = 0x1A; // Sync word detect
|
|
gpiocfg.SDO = 0x00; // No change
|
|
gpiocfg.GENCFG = 0x00; // No change
|
|
sendCmd(GPIO_PIN_CFG, &gpiocfg, sizeof gpiocfg, &gpiocfg, sizeof gpiocfg);
|
|
}
|
|
|