From 79aa4620ba67c3736b884e06c7909e4c9bb52d72 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Sat, 5 Jan 2019 13:47:46 +0100 Subject: [PATCH] Independent ADC and DAC sample rates --- device.h | 1 + hardware/AFSK.c | 62 +++++++++++++++++++++++++++++++++++-------------- hardware/AFSK.h | 52 +++++++++++++++++++++-------------------- hardware/VREF.c | 4 ++-- protocol/KISS.c | 4 ++-- util/time.h | 2 +- 6 files changed, 78 insertions(+), 47 deletions(-) diff --git a/device.h b/device.h index 6fc655b..c93c530 100755 --- a/device.h +++ b/device.h @@ -22,6 +22,7 @@ #define TX_MAXWAIT 2UL // CSMA Settings +#define CONFIG_FULL_DUPLEX false // TODO: Actually implement fdx #define CONFIG_CSMA_P 255 // Packet settings diff --git a/hardware/AFSK.c b/hardware/AFSK.c index 833a165..747fc0e 100755 --- a/hardware/AFSK.c +++ b/hardware/AFSK.c @@ -22,6 +22,36 @@ int afsk_putchar(char c, FILE *stream); // ADC and clock setup void AFSK_hw_init(void) { + // Run ADC initialisation + AFSK_adc_init(); + + // Run DAC initialisation + AFSK_dac_init(); + + // Run LED initialisation + LED_TX_INIT(); + LED_RX_INIT(); +} + +void AFSK_dac_init(void) { + // DAC uses all 8 pins of one port, + // so set all to output + DAC_DDR |= 0xFF; + + // Set Timer3 to normal operation + TCCR3A = 0; + TCCR3B = _BV(CS10) | + _BV(WGM33)| + _BV(WGM32); + + ICR3 = DAC_TICKS_BETWEEN_SAMPLES; + //OCR3A = DAC_TICKS_BETWEEN_SAMPLES; + + TIMSK3 = _BV(ICIE3); + +} + +void AFSK_adc_init(void) { // Set Timer1 to normal operation TCCR1A = 0; @@ -31,7 +61,7 @@ void AFSK_hw_init(void) { // Set ICR1 register to the amount of ticks needed between // each sample capture/synthesis - ICR1 = TICKS_BETWEEN_SAMPLES; + ICR1 = ADC_TICKS_BETWEEN_SAMPLES; // Set ADMUX register to use external AREF, channel ADC0 // and left adjust result @@ -60,12 +90,6 @@ void AFSK_hw_init(void) { _BV(ADPS2); // Set ADC prescaler bits to 0b101 = 32 // At 20MHz, this gives an ADC clock of 625 KHz - // Run DAC initialisation - AFSK_DAC_INIT(); - - // Run LED initialisation - LED_TX_INIT(); - LED_RX_INIT(); } void AFSK_init(Afsk *afsk) { @@ -82,7 +106,7 @@ void AFSK_init(Afsk *afsk) { fifo_init(&afsk->txFifo, afsk->txBuf, sizeof(afsk->txBuf)); // Fill delay FIFO with zeroes - for (int i = 0; idelayFifo, 0); } @@ -185,7 +209,7 @@ uint8_t AFSK_dac_isr(Afsk *afsk) { afsk->txBit <<= 1; } - afsk->sampleIndex = SAMPLESPERBIT; + afsk->sampleIndex = DAC_SAMPLESPERBIT; } afsk->phaseAcc += afsk->phaseInc; @@ -375,7 +399,7 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) { afsk->iirX[0] = afsk->iirX[1]; - #if CONFIG_SAMPLERATE == 9600 + #if CONFIG_ADC_SAMPLERATE == 9600 #if FILTER_CUTOFF == 500 #define IIR_GAIN 4 // Really 4.082041675 #define IIR_POLE 2 // Really Y[0] * 0.5100490981 @@ -387,7 +411,7 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) { #error Unsupported filter cutoff! #endif - #elif CONFIG_SAMPLERATE == 19200 + #elif CONFIG_ADC_SAMPLERATE == 19200 #if FILTER_CUTOFF == 150 #define IIR_GAIN 2 // Really 2.172813446e #define IIR_POLE 2 // Really Y[0] * 0.9079534415 @@ -570,17 +594,21 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) { } -ISR(ADC_vect) { - TIFR1 = _BV(ICF1); - +ISR(TIMER3_CAPT_vect) { if (hw_afsk_dac_isr) { DAC_PORT = AFSK_dac_isr(AFSK_modem); LED_TX_ON(); } else { - // TODO: Enable full duplex if possible - AFSK_adc_isr(AFSK_modem, (ADCH - 128)); - DAC_PORT = 127; LED_TX_OFF(); + DAC_PORT = 127; + } +} + +ISR(ADC_vect) { + TIFR1 = _BV(ICF1); + + if (CONFIG_FULL_DUPLEX || !hw_afsk_dac_isr) { + AFSK_adc_isr(AFSK_modem, (ADCH - 128)); } ++_clock; diff --git a/hardware/AFSK.h b/hardware/AFSK.h index 800cf20..af93cdd 100755 --- a/hardware/AFSK.h +++ b/hardware/AFSK.h @@ -38,8 +38,8 @@ inline static uint8_t sinSample(uint16_t i) { #define CPU_FREQ F_CPU -#define CONFIG_AFSK_RX_BUFLEN CONFIG_SAMPLERATE/150 -#define CONFIG_AFSK_TX_BUFLEN CONFIG_SAMPLERATE/150 +#define CONFIG_AFSK_RX_BUFLEN CONFIG_ADC_SAMPLERATE/150 +#define CONFIG_AFSK_TX_BUFLEN CONFIG_ADC_SAMPLERATE/150 #define CONFIG_AFSK_RXTIMEOUT 0 #define CONFIG_AFSK_TXWAIT 0UL #define CONFIG_AFSK_PREAMBLE_LEN 150UL @@ -49,20 +49,24 @@ inline static uint8_t sinSample(uint16_t i) { #define BITRATE 1200 #if BITRATE == 1200 - #define CONFIG_SAMPLERATE 9600UL + #define CONFIG_ADC_SAMPLERATE 9600UL + #define CONFIG_DAC_SAMPLERATE 19200UL #elif BITRATE == 2400 - #define CONFIG_SAMPLERATE 19200UL + #define CONFIG_ADC_SAMPLERATE 19200UL + #define CONFIG_DAC_SAMPLERATE 38400UL #endif -#define SAMPLESPERBIT (CONFIG_SAMPLERATE / BITRATE) -#define TICKS_BETWEEN_SAMPLES ((((CPU_FREQ+FREQUENCY_CORRECTION)) / CONFIG_SAMPLERATE) - 1) +#define ADC_SAMPLESPERBIT (CONFIG_ADC_SAMPLERATE / BITRATE) +#define ADC_TICKS_BETWEEN_SAMPLES ((((CPU_FREQ+FREQUENCY_CORRECTION)) / CONFIG_ADC_SAMPLERATE) - 1) + +#define DAC_SAMPLESPERBIT (CONFIG_DAC_SAMPLERATE / BITRATE) +#define DAC_TICKS_BETWEEN_SAMPLES ((((CPU_FREQ+FREQUENCY_CORRECTION)) / CONFIG_DAC_SAMPLERATE) - 1) // TODO: Maybe revert to only looking at two samples - #if BITRATE == 1200 - #if CONFIG_SAMPLERATE == 19200 + #if CONFIG_ADC_SAMPLERATE == 19200 #define SIGNAL_TRANSITIONED(bits) QUAD_XOR((bits), (bits) >> 4) - #elif CONFIG_SAMPLERATE == 9600 + #elif CONFIG_ADC_SAMPLERATE == 9600 #define SIGNAL_TRANSITIONED(bits) DUAL_XOR((bits), (bits) >> 2) #endif #elif BITRATE == 2400 @@ -73,14 +77,14 @@ inline static uint8_t sinSample(uint16_t i) { #define PHASE_BITS 8 // Sub-sample phase counter resolution #define PHASE_INC 1 // Nudge by above resolution for each adjustment -#define PHASE_MAX (SAMPLESPERBIT * PHASE_BITS) // Size of our phase counter +#define PHASE_MAX (ADC_SAMPLESPERBIT * PHASE_BITS) // Size of our phase counter // TODO: Test which target is best in real world // For 1200, this seems a little better #if BITRATE == 1200 - #if CONFIG_SAMPLERATE == 19200 + #if CONFIG_ADC_SAMPLERATE == 19200 #define PHASE_THRESHOLD (PHASE_MAX / 2)+3*PHASE_BITS // Target transition point of our phase window - #elif CONFIG_SAMPLERATE == 9600 + #elif CONFIG_ADC_SAMPLERATE == 9600 #define PHASE_THRESHOLD (PHASE_MAX / 2) // 64 // Target transition point of our phase window #endif #elif BITRATE == 2400 @@ -88,8 +92,8 @@ inline static uint8_t sinSample(uint16_t i) { #endif -#define DCD_TIMEOUT_SAMPLES CONFIG_SAMPLERATE/100 -#define DCD_MIN_COUNT CONFIG_SAMPLERATE/1600 +#define DCD_TIMEOUT_SAMPLES CONFIG_ADC_SAMPLERATE/100 +#define DCD_MIN_COUNT CONFIG_ADC_SAMPLERATE/1600 // TODO: Revamp filtering #if BITRATE == 1200 @@ -155,10 +159,10 @@ typedef struct Afsk FIFOBuffer delayFifo; // Delayed FIFO for frequency discrimination #if BITRATE == 1200 // TODO: Clean this up - #if CONFIG_SAMPLERATE == 19200 - int8_t delayBuf[SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO - #elif CONFIG_SAMPLERATE == 9600 - int8_t delayBuf[SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO + #if CONFIG_ADC_SAMPLERATE == 19200 + int8_t delayBuf[ADC_SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO + #elif CONFIG_ADC_SAMPLERATE == 9600 + int8_t delayBuf[ADC_SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO #endif #elif BITRATE == 2400 int8_t delayBuf[7 + 1]; // Actual data storage for said FIFO @@ -170,7 +174,7 @@ typedef struct Afsk int16_t iirX[2]; // IIR Filter X cells int16_t iirY[2]; // IIR Filter Y cells - #if SAMPLESPERBIT < 17 + #if ADC_SAMPLESPERBIT < 17 uint16_t sampledBits; // Bits sampled by the demodulator (at ADC speed) #else // TODO: Enable error and set up correct size buffers @@ -185,16 +189,12 @@ typedef struct Afsk } Afsk; #define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor)) -#define MARK_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ, CONFIG_SAMPLERATE)) -#define SPACE_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ, CONFIG_SAMPLERATE)) +#define MARK_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ, CONFIG_DAC_SAMPLERATE)) +#define SPACE_INC (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ, CONFIG_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) -// DAC uses all 8 pins of one port, set all pins to -// output direction -#define AFSK_DAC_INIT() do { DAC_DDR |= 0xFF; } while (0) - // Here's some macros for controlling the RX/TX LEDs // THE _INIT() functions writes to the DDR registers // to configure the pins as output pins, and the _ON() @@ -209,6 +209,8 @@ typedef struct Afsk #define LED_RX_OFF() do { LED_PORT &= ~_BV(2); } while (0) void AFSK_init(Afsk *afsk); +void AFSK_adc_init(void); +void AFSK_dac_init(void); void AFSK_transmit(char *buffer, size_t size); void AFSK_poll(Afsk *afsk); diff --git a/hardware/VREF.c b/hardware/VREF.c index 3834ded..d463b79 100644 --- a/hardware/VREF.c +++ b/hardware/VREF.c @@ -4,8 +4,8 @@ uint8_t adcReference = CONFIG_ADC_REF; uint8_t dacReference = CONFIG_DAC_REF; void VREF_init(void) { - //DDRD |= _BV(7); - DDRD = 0xFF; + // Enable output for OC2A and OC2B (PD7 and PD6) + DDRD |= _BV(7) | _BV(6); TCCR2A = _BV(WGM20) | _BV(WGM21) | diff --git a/protocol/KISS.c b/protocol/KISS.c index 5c5248e..eaf1adc 100755 --- a/protocol/KISS.c +++ b/protocol/KISS.c @@ -28,7 +28,7 @@ void kiss_init(AX25Ctx *ax25, Afsk *afsk, Serial *ser) { } // TODO: Remove debug functions -//size_t decodes = 0; +// size_t decodes = 0; void kiss_messageCallback(AX25Ctx *ctx) { // decodes++; // printf("%d\r\n", decodes); @@ -60,7 +60,7 @@ void kiss_csma(AX25Ctx *ctx, uint8_t *buf, size_t len) { } } while (!sent) { - if(!channel->hdlc.dcd) { + if(CONFIG_FULL_DUPLEX || !channel->hdlc.dcd) { uint8_t tp = rand() & 0xFF; if (tp < p) { ax25_sendRaw(ctx, buf, len); diff --git a/util/time.h b/util/time.h index 661b05c..ef4a9ff 100755 --- a/util/time.h +++ b/util/time.h @@ -4,7 +4,7 @@ #include #define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor)) -#define CLOCK_TICKS_PER_SEC CONFIG_SAMPLERATE +#define CLOCK_TICKS_PER_SEC CONFIG_ADC_SAMPLERATE typedef int32_t ticks_t; typedef int32_t mtime_t;