Independent ADC and DAC sample rates
This commit is contained in:
parent
8b2e66eb57
commit
79aa4620ba
1
device.h
1
device.h
|
@ -22,6 +22,7 @@
|
||||||
#define TX_MAXWAIT 2UL
|
#define TX_MAXWAIT 2UL
|
||||||
|
|
||||||
// CSMA Settings
|
// CSMA Settings
|
||||||
|
#define CONFIG_FULL_DUPLEX false // TODO: Actually implement fdx
|
||||||
#define CONFIG_CSMA_P 255
|
#define CONFIG_CSMA_P 255
|
||||||
|
|
||||||
// Packet settings
|
// Packet settings
|
||||||
|
|
|
@ -22,6 +22,36 @@ int afsk_putchar(char c, FILE *stream);
|
||||||
|
|
||||||
// ADC and clock setup
|
// ADC and clock setup
|
||||||
void AFSK_hw_init(void) {
|
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
|
// Set Timer1 to normal operation
|
||||||
TCCR1A = 0;
|
TCCR1A = 0;
|
||||||
|
|
||||||
|
@ -31,7 +61,7 @@ void AFSK_hw_init(void) {
|
||||||
|
|
||||||
// Set ICR1 register to the amount of ticks needed between
|
// Set ICR1 register to the amount of ticks needed between
|
||||||
// each sample capture/synthesis
|
// each sample capture/synthesis
|
||||||
ICR1 = TICKS_BETWEEN_SAMPLES;
|
ICR1 = ADC_TICKS_BETWEEN_SAMPLES;
|
||||||
|
|
||||||
// Set ADMUX register to use external AREF, channel ADC0
|
// Set ADMUX register to use external AREF, channel ADC0
|
||||||
// and left adjust result
|
// and left adjust result
|
||||||
|
@ -60,12 +90,6 @@ void AFSK_hw_init(void) {
|
||||||
_BV(ADPS2); // Set ADC prescaler bits to 0b101 = 32
|
_BV(ADPS2); // Set ADC prescaler bits to 0b101 = 32
|
||||||
// At 20MHz, this gives an ADC clock of 625 KHz
|
// 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) {
|
void AFSK_init(Afsk *afsk) {
|
||||||
|
@ -82,7 +106,7 @@ void AFSK_init(Afsk *afsk) {
|
||||||
fifo_init(&afsk->txFifo, afsk->txBuf, sizeof(afsk->txBuf));
|
fifo_init(&afsk->txFifo, afsk->txBuf, sizeof(afsk->txBuf));
|
||||||
|
|
||||||
// Fill delay FIFO with zeroes
|
// Fill delay FIFO with zeroes
|
||||||
for (int i = 0; i<SAMPLESPERBIT / 2; i++) {
|
for (int i = 0; i<ADC_SAMPLESPERBIT / 2; i++) {
|
||||||
fifo_push(&afsk->delayFifo, 0);
|
fifo_push(&afsk->delayFifo, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +209,7 @@ uint8_t AFSK_dac_isr(Afsk *afsk) {
|
||||||
afsk->txBit <<= 1;
|
afsk->txBit <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
afsk->sampleIndex = SAMPLESPERBIT;
|
afsk->sampleIndex = DAC_SAMPLESPERBIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
afsk->phaseAcc += afsk->phaseInc;
|
afsk->phaseAcc += afsk->phaseInc;
|
||||||
|
@ -375,7 +399,7 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
|
||||||
|
|
||||||
afsk->iirX[0] = afsk->iirX[1];
|
afsk->iirX[0] = afsk->iirX[1];
|
||||||
|
|
||||||
#if CONFIG_SAMPLERATE == 9600
|
#if CONFIG_ADC_SAMPLERATE == 9600
|
||||||
#if FILTER_CUTOFF == 500
|
#if FILTER_CUTOFF == 500
|
||||||
#define IIR_GAIN 4 // Really 4.082041675
|
#define IIR_GAIN 4 // Really 4.082041675
|
||||||
#define IIR_POLE 2 // Really Y[0] * 0.5100490981
|
#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!
|
#error Unsupported filter cutoff!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif CONFIG_SAMPLERATE == 19200
|
#elif CONFIG_ADC_SAMPLERATE == 19200
|
||||||
#if FILTER_CUTOFF == 150
|
#if FILTER_CUTOFF == 150
|
||||||
#define IIR_GAIN 2 // Really 2.172813446e
|
#define IIR_GAIN 2 // Really 2.172813446e
|
||||||
#define IIR_POLE 2 // Really Y[0] * 0.9079534415
|
#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) {
|
ISR(TIMER3_CAPT_vect) {
|
||||||
TIFR1 = _BV(ICF1);
|
|
||||||
|
|
||||||
if (hw_afsk_dac_isr) {
|
if (hw_afsk_dac_isr) {
|
||||||
DAC_PORT = AFSK_dac_isr(AFSK_modem);
|
DAC_PORT = AFSK_dac_isr(AFSK_modem);
|
||||||
LED_TX_ON();
|
LED_TX_ON();
|
||||||
} else {
|
} else {
|
||||||
// TODO: Enable full duplex if possible
|
|
||||||
AFSK_adc_isr(AFSK_modem, (ADCH - 128));
|
|
||||||
DAC_PORT = 127;
|
|
||||||
LED_TX_OFF();
|
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;
|
++_clock;
|
||||||
|
|
|
@ -38,8 +38,8 @@ inline static uint8_t sinSample(uint16_t i) {
|
||||||
|
|
||||||
#define CPU_FREQ F_CPU
|
#define CPU_FREQ F_CPU
|
||||||
|
|
||||||
#define CONFIG_AFSK_RX_BUFLEN CONFIG_SAMPLERATE/150
|
#define CONFIG_AFSK_RX_BUFLEN CONFIG_ADC_SAMPLERATE/150
|
||||||
#define CONFIG_AFSK_TX_BUFLEN CONFIG_SAMPLERATE/150
|
#define CONFIG_AFSK_TX_BUFLEN CONFIG_ADC_SAMPLERATE/150
|
||||||
#define CONFIG_AFSK_RXTIMEOUT 0
|
#define CONFIG_AFSK_RXTIMEOUT 0
|
||||||
#define CONFIG_AFSK_TXWAIT 0UL
|
#define CONFIG_AFSK_TXWAIT 0UL
|
||||||
#define CONFIG_AFSK_PREAMBLE_LEN 150UL
|
#define CONFIG_AFSK_PREAMBLE_LEN 150UL
|
||||||
|
@ -49,20 +49,24 @@ inline static uint8_t sinSample(uint16_t i) {
|
||||||
#define BITRATE 1200
|
#define BITRATE 1200
|
||||||
|
|
||||||
#if BITRATE == 1200
|
#if BITRATE == 1200
|
||||||
#define CONFIG_SAMPLERATE 9600UL
|
#define CONFIG_ADC_SAMPLERATE 9600UL
|
||||||
|
#define CONFIG_DAC_SAMPLERATE 19200UL
|
||||||
#elif BITRATE == 2400
|
#elif BITRATE == 2400
|
||||||
#define CONFIG_SAMPLERATE 19200UL
|
#define CONFIG_ADC_SAMPLERATE 19200UL
|
||||||
|
#define CONFIG_DAC_SAMPLERATE 38400UL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SAMPLESPERBIT (CONFIG_SAMPLERATE / BITRATE)
|
#define ADC_SAMPLESPERBIT (CONFIG_ADC_SAMPLERATE / BITRATE)
|
||||||
#define TICKS_BETWEEN_SAMPLES ((((CPU_FREQ+FREQUENCY_CORRECTION)) / CONFIG_SAMPLERATE) - 1)
|
#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
|
// TODO: Maybe revert to only looking at two samples
|
||||||
|
|
||||||
#if BITRATE == 1200
|
#if BITRATE == 1200
|
||||||
#if CONFIG_SAMPLERATE == 19200
|
#if CONFIG_ADC_SAMPLERATE == 19200
|
||||||
#define SIGNAL_TRANSITIONED(bits) QUAD_XOR((bits), (bits) >> 4)
|
#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)
|
#define SIGNAL_TRANSITIONED(bits) DUAL_XOR((bits), (bits) >> 2)
|
||||||
#endif
|
#endif
|
||||||
#elif BITRATE == 2400
|
#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_BITS 8 // Sub-sample phase counter resolution
|
||||||
#define PHASE_INC 1 // Nudge by above resolution for each adjustment
|
#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
|
// TODO: Test which target is best in real world
|
||||||
// For 1200, this seems a little better
|
// For 1200, this seems a little better
|
||||||
#if BITRATE == 1200
|
#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
|
#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
|
#define PHASE_THRESHOLD (PHASE_MAX / 2) // 64 // Target transition point of our phase window
|
||||||
#endif
|
#endif
|
||||||
#elif BITRATE == 2400
|
#elif BITRATE == 2400
|
||||||
|
@ -88,8 +92,8 @@ inline static uint8_t sinSample(uint16_t i) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DCD_TIMEOUT_SAMPLES CONFIG_SAMPLERATE/100
|
#define DCD_TIMEOUT_SAMPLES CONFIG_ADC_SAMPLERATE/100
|
||||||
#define DCD_MIN_COUNT CONFIG_SAMPLERATE/1600
|
#define DCD_MIN_COUNT CONFIG_ADC_SAMPLERATE/1600
|
||||||
|
|
||||||
// TODO: Revamp filtering
|
// TODO: Revamp filtering
|
||||||
#if BITRATE == 1200
|
#if BITRATE == 1200
|
||||||
|
@ -155,10 +159,10 @@ typedef struct Afsk
|
||||||
FIFOBuffer delayFifo; // Delayed FIFO for frequency discrimination
|
FIFOBuffer delayFifo; // Delayed FIFO for frequency discrimination
|
||||||
#if BITRATE == 1200
|
#if BITRATE == 1200
|
||||||
// TODO: Clean this up
|
// TODO: Clean this up
|
||||||
#if CONFIG_SAMPLERATE == 19200
|
#if CONFIG_ADC_SAMPLERATE == 19200
|
||||||
int8_t delayBuf[SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO
|
int8_t delayBuf[ADC_SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO
|
||||||
#elif CONFIG_SAMPLERATE == 9600
|
#elif CONFIG_ADC_SAMPLERATE == 9600
|
||||||
int8_t delayBuf[SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO
|
int8_t delayBuf[ADC_SAMPLESPERBIT / 2 + 1]; // Actual data storage for said FIFO
|
||||||
#endif
|
#endif
|
||||||
#elif BITRATE == 2400
|
#elif BITRATE == 2400
|
||||||
int8_t delayBuf[7 + 1]; // Actual data storage for said FIFO
|
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 iirX[2]; // IIR Filter X cells
|
||||||
int16_t iirY[2]; // IIR Filter Y 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)
|
uint16_t sampledBits; // Bits sampled by the demodulator (at ADC speed)
|
||||||
#else
|
#else
|
||||||
// TODO: Enable error and set up correct size buffers
|
// TODO: Enable error and set up correct size buffers
|
||||||
|
@ -185,16 +189,12 @@ typedef struct Afsk
|
||||||
} Afsk;
|
} Afsk;
|
||||||
|
|
||||||
#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor))
|
#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 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_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_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)
|
#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
|
// Here's some macros for controlling the RX/TX LEDs
|
||||||
// THE _INIT() functions writes to the DDR registers
|
// THE _INIT() functions writes to the DDR registers
|
||||||
// to configure the pins as output pins, and the _ON()
|
// 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)
|
#define LED_RX_OFF() do { LED_PORT &= ~_BV(2); } while (0)
|
||||||
|
|
||||||
void AFSK_init(Afsk *afsk);
|
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_transmit(char *buffer, size_t size);
|
||||||
void AFSK_poll(Afsk *afsk);
|
void AFSK_poll(Afsk *afsk);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ uint8_t adcReference = CONFIG_ADC_REF;
|
||||||
uint8_t dacReference = CONFIG_DAC_REF;
|
uint8_t dacReference = CONFIG_DAC_REF;
|
||||||
|
|
||||||
void VREF_init(void) {
|
void VREF_init(void) {
|
||||||
//DDRD |= _BV(7);
|
// Enable output for OC2A and OC2B (PD7 and PD6)
|
||||||
DDRD = 0xFF;
|
DDRD |= _BV(7) | _BV(6);
|
||||||
|
|
||||||
TCCR2A = _BV(WGM20) |
|
TCCR2A = _BV(WGM20) |
|
||||||
_BV(WGM21) |
|
_BV(WGM21) |
|
||||||
|
|
|
@ -60,7 +60,7 @@ void kiss_csma(AX25Ctx *ctx, uint8_t *buf, size_t len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!sent) {
|
while (!sent) {
|
||||||
if(!channel->hdlc.dcd) {
|
if(CONFIG_FULL_DUPLEX || !channel->hdlc.dcd) {
|
||||||
uint8_t tp = rand() & 0xFF;
|
uint8_t tp = rand() & 0xFF;
|
||||||
if (tp < p) {
|
if (tp < p) {
|
||||||
ax25_sendRaw(ctx, buf, len);
|
ax25_sendRaw(ctx, buf, len);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <util/atomic.h>
|
#include <util/atomic.h>
|
||||||
|
|
||||||
#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor))
|
#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 ticks_t;
|
||||||
typedef int32_t mtime_t;
|
typedef int32_t mtime_t;
|
||||||
|
|
Loading…
Reference in New Issue