Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 27 additions & 23 deletions LibAPRS/AFSK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void AFSK_hw_init(void) {

AFSK_hw_refDetect();

TCCR1A = 0;
TCCR1A = 0;
TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12);
ICR1 = (((CPU_FREQ+FREQUENCY_CORRECTION)) / 9600) - 1;

Expand All @@ -45,7 +45,7 @@ void AFSK_hw_init(void) {
DIDR0 |= _BV(0);
ADCSRB = _BV(ADTS2) |
_BV(ADTS1) |
_BV(ADTS0);
_BV(ADTS0);
ADCSRA = _BV(ADEN) |
_BV(ADSC) |
_BV(ADATE)|
Expand All @@ -62,33 +62,37 @@ void AFSK_init(Afsk *afsk) {
memset(afsk, 0, sizeof(*afsk));
AFSK_modem = afsk;
// Set phase increment
afsk->phaseInc = MARK_INC;
afsk->dataRate = 1200;
afsk->phaseInc = MARK_INC_1200;
// Initialise FIFO buffers
fifo_init(&afsk->delayFifo, (uint8_t *)afsk->delayBuf, sizeof(afsk->delayBuf));
fifo_init(&afsk->rxFifo, afsk->rxBuf, sizeof(afsk->rxBuf));
fifo_init(&afsk->txFifo, afsk->txBuf, sizeof(afsk->txBuf));

// Fill delay FIFO with zeroes
for (int i = 0; i<SAMPLESPERBIT / 2; i++) {
for (int i = 0; i<SAMPLESPERBIT_300 / 2; i++) {
fifo_push(&afsk->delayFifo, 0);
}

AFSK_hw_init();
}

void AFSK_setDataRate(Afsk *afsk, uint16_t dataRate) {
afsk->dataRate = dataRate;
}

static void AFSK_txStart(Afsk *afsk) {
if (!afsk->sending) {
afsk->phaseInc = MARK_INC;
afsk->phaseInc = afsk->dataRate == 1200 ? MARK_INC_1200 : MARK_INC_300;
afsk->phaseAcc = 0;
afsk->bitstuffCount = 0;
afsk->sending = true;
LED_TX_ON();
afsk->preambleLength = DIV_ROUND(custom_preamble * BITRATE, 8000);
afsk->preambleLength = DIV_ROUND(custom_preamble * afsk->dataRate, 8000);
AFSK_DAC_IRQ_START();
}
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
afsk->tailLength = DIV_ROUND(custom_tail * BITRATE, 8000);
afsk->tailLength = DIV_ROUND(custom_tail * afsk->dataRate, 8000);
}
}

Expand Down Expand Up @@ -154,18 +158,18 @@ uint8_t AFSK_dac_isr(Afsk *afsk) {

if (afsk->bitStuff && afsk->bitstuffCount >= BIT_STUFF_LEN) {
afsk->bitstuffCount = 0;
afsk->phaseInc = SWITCH_TONE(afsk->phaseInc);
afsk->phaseInc = (afsk->dataRate == 1200) ? SWITCH_TONE_1200(afsk->phaseInc) : SWITCH_TONE_300(afsk->phaseInc);
} else {
if (afsk->currentOutputByte & afsk->txBit) {
afsk->bitstuffCount++;
} else {
afsk->bitstuffCount = 0;
afsk->phaseInc = SWITCH_TONE(afsk->phaseInc);
afsk->phaseInc = (afsk->dataRate == 1200) ? SWITCH_TONE_1200(afsk->phaseInc) : SWITCH_TONE_300(afsk->phaseInc);
}
afsk->txBit <<= 1;
}

afsk->sampleIndex = SAMPLESPERBIT;
afsk->sampleIndex = (afsk->dataRate == 1200) ? SAMPLESPERBIT_1200 : SAMPLESPERBIT_300;
}

afsk->phaseAcc += afsk->phaseInc;
Expand All @@ -184,7 +188,7 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) {
// the left by one bit, to make room for the
// next incoming bit
hdlc->demodulatedBits <<= 1;
// And then put the newest bit from the
// And then put the newest bit from the
// demodulator into the byte.
hdlc->demodulatedBits |= bit ? 1 : 0;

Expand All @@ -205,9 +209,9 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) {
}
} else {
// If the buffer is full, we have a problem
// and abort by setting the return value to
// and abort by setting the return value to
// false and stopping the here.

ret = false;
hdlc->receiving = false;
LED_RX_OFF();
Expand Down Expand Up @@ -255,7 +259,7 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo) {
// a control character. Therefore, if we detect such a
// "stuffed bit", we simply ignore it and wait for the
// next bit to come in.
//
//
// We do the detection by applying an AND bit-mask to the
// stream of demodulated bits. This mask is 00111111 (0x3f)
// if the result of the operation is 00111110 (0x3e), we
Expand Down Expand Up @@ -333,7 +337,7 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
afsk->iirX[1] = ((int8_t)fifo_pop(&afsk->delayFifo) * currentSample) >> 2;

afsk->iirY[0] = afsk->iirY[1];

afsk->iirY[1] = afsk->iirX[0] + afsk->iirX[1] + (afsk->iirY[0] >> 1); // Chebyshev filter


Expand All @@ -347,7 +351,7 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
fifo_push(&afsk->delayFifo, currentSample);

// We need to check whether there is a signal transition.
// If there is, we can recalibrate the phase of our
// If there is, we can recalibrate the phase of our
// sampler to stay in sync with the transmitter. A bit of
// explanation is required to understand how this works.
// Since we have PHASE_MAX/PHASE_BITS = 8 samples per bit,
Expand All @@ -363,13 +367,13 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
// Past Future
// 0000000011111111000000001111111100000000
// |________|
// ||
// ||
// Window
//
// Every time we detect a signal transition, we adjust
// where this window is positioned little. How much we
// adjust it is defined by PHASE_INC. If our current phase
// phase counter value is less than half of PHASE_MAX (ie,
// phase counter value is less than half of PHASE_MAX (ie,
// the window size) when a signal transition is detected,
// add PHASE_INC to our phase counter, effectively moving
// the window a little bit backward (to the left in the
Expand All @@ -380,7 +384,7 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
// our timing to the transmitter, even if it's timing is
// a little off compared to our own.
if (SIGNAL_TRANSITIONED(afsk->sampledBits)) {
if (afsk->currentPhase < PHASE_THRESHOLD) {
if (afsk->currentPhase < PHASE_THRESHOLD_1200) {
afsk->currentPhase += PHASE_INC;
} else {
afsk->currentPhase -= PHASE_INC;
Expand All @@ -392,10 +396,10 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {

// Check if we have reached the end of
// our sampling window.
if (afsk->currentPhase >= PHASE_MAX) {
if (afsk->currentPhase >= PHASE_MAX_1200) {
// If we have, wrap around our phase
// counter by modulus
afsk->currentPhase %= PHASE_MAX;
afsk->currentPhase %= PHASE_MAX_1200;

// Bitshift to make room for the next
// bit in our stream of demodulated bits
Expand Down Expand Up @@ -462,7 +466,7 @@ ISR(ADC_vect) {
TIFR1 = _BV(ICF1);
AFSK_adc_isr(AFSK_modem, ((int16_t)((ADC) >> 2) - 128));
if (hw_afsk_dac_isr) {
DAC_PORT = (AFSK_dac_isr(AFSK_modem) & 0xF0) | _BV(3);
DAC_PORT = (AFSK_dac_isr(AFSK_modem) & 0xF0) | _BV(3);
} else {
DAC_PORT = 128;
}
Expand All @@ -472,4 +476,4 @@ ISR(ADC_vect) {
poll_timer = 0;
APRS_poll();
}
}
}
37 changes: 22 additions & 15 deletions LibAPRS/AFSK.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ inline static uint8_t sinSample(uint16_t i) {
return (i >= (SIN_LEN/2)) ? (255 - sine) : sine;
}


#define SWITCH_TONE(inc) (((inc) == MARK_INC) ? SPACE_INC : MARK_INC)
#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor))
#define SWITCH_TONE_300(inc) (((inc) == MARK_INC_300) ? SPACE_INC_300 : MARK_INC_300)
#define SWITCH_TONE_1200(inc) (((inc) == MARK_INC_1200) ? SPACE_INC_1200 : MARK_INC_1200)
#define BITS_DIFFER(bits1, bits2) (((bits1)^(bits2)) & 0x01)
#define DUAL_XOR(bits1, bits2) ((((bits1)^(bits2)) & 0x03) == 0x03)
#define SIGNAL_TRANSITIONED(bits) DUAL_XOR((bits), (bits) >> 2)
Expand All @@ -44,15 +45,23 @@ inline static uint8_t sinSample(uint16_t i) {
#define CONFIG_AFSK_PREAMBLE_LEN 150UL
#define CONFIG_AFSK_TRAILER_LEN 50UL
#define SAMPLERATE 9600
#define BITRATE 1200
#define SAMPLESPERBIT (SAMPLERATE / BITRATE)
#define SAMPLESPERBIT_1200 (SAMPLERATE / 1200)
#define SAMPLESPERBIT_300 (SAMPLERATE / 300)
#define BIT_STUFF_LEN 5
#define MARK_FREQ 1200
#define SPACE_FREQ 2200
#define MARK_FREQ_300 1600
#define SPACE_FREQ_300 1800
#define MARK_FREQ_1200 1200
#define SPACE_FREQ_1200 2200
#define PHASE_BITS 8 // How much to increment phase counter each sample
#define PHASE_INC 1 // Nudge by an eigth of a sample each adjustment
#define PHASE_MAX (SAMPLESPERBIT * PHASE_BITS) // Resolution of our phase counter = 64
#define PHASE_THRESHOLD (PHASE_MAX / 2) // Target transition point of our phase window
#define PHASE_MAX_300 (SAMPLESPERBIT_300 * PHASE_BITS) // Resolution of our phase counter = 64
#define PHASE_MAX_1200 (SAMPLESPERBIT_1200 * PHASE_BITS) // Resolution of our phase counter = 64
#define PHASE_THRESHOLD_300 (PHASE_MAX_300 / 2) // Target transition point of our phase window
#define PHASE_THRESHOLD_1200 (PHASE_MAX_1200 / 2) // Target transition point of our phase window
#define MARK_INC_300 (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ_300, CONFIG_AFSK_DAC_SAMPLERATE))
#define SPACE_INC_300 (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ_300, CONFIG_AFSK_DAC_SAMPLERATE))
#define MARK_INC_1200 (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ_1200, CONFIG_AFSK_DAC_SAMPLERATE))
#define SPACE_INC_1200 (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ_1200, CONFIG_AFSK_DAC_SAMPLERATE))


typedef struct Hdlc
Expand Down Expand Up @@ -85,13 +94,13 @@ typedef struct Afsk
uint16_t phaseInc; // Phase increment per sample

FIFOBuffer txFifo; // FIFO for transmit data
uint8_t txBuf[CONFIG_AFSK_TX_BUFLEN]; // Actial data storage for said FIFO
uint8_t txBuf[CONFIG_AFSK_TX_BUFLEN]; // Actual data storage for said FIFO

volatile bool sending; // Set when modem is sending

// Demodulation values
FIFOBuffer delayFifo; // Delayed FIFO for frequency discrimination
int8_t delayBuf[SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO
int8_t delayBuf[SAMPLESPERBIT_300 / 2 + 1]; // Actual data storage for said FIFO

FIFOBuffer rxFifo; // FIFO for received data
uint8_t rxBuf[CONFIG_AFSK_RX_BUFLEN]; // Actual data storage for said FIFO
Expand All @@ -100,16 +109,13 @@ typedef struct Afsk
int16_t iirY[2]; // IIR Filter Y cells

uint8_t sampledBits; // Bits sampled by the demodulator (at ADC speed)
int8_t currentPhase; // Current phase of the demodulator
int16_t currentPhase; // Current phase of the demodulator
uint8_t actualBits; // Actual found bits at correct bitrate

volatile int status; // Status of the modem, 0 means OK

uint16_t dataRate; // Data rate for the modem
} Afsk;

#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor))
#define MARK_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ, CONFIG_AFSK_DAC_SAMPLERATE))
#define SPACE_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ, CONFIG_AFSK_DAC_SAMPLERATE))

#define AFSK_DAC_IRQ_START() do { extern bool hw_afsk_dac_isr; hw_afsk_dac_isr = true; } while (0)
#define AFSK_DAC_IRQ_STOP() do { extern bool hw_afsk_dac_isr; hw_afsk_dac_isr = false; } while (0)
Expand All @@ -131,6 +137,7 @@ typedef struct Afsk
void AFSK_init(Afsk *afsk);
void AFSK_transmit(char *buffer, size_t size);
void AFSK_poll(Afsk *afsk);
void AFSK_setDataRate(Afsk *afsk, uint16_t rate);

void afsk_putchar(char c);
int afsk_getchar(void);
Expand Down
1 change: 1 addition & 0 deletions LibAPRS/AX25.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
extern int LibAPRS_vref;
extern bool LibAPRS_open_squelch;


void ax25_init(AX25Ctx *ctx, ax25_callback_t hook) {
memset(ctx, 0, sizeof(*ctx));
ctx->hook = hook;
Expand Down
Loading