mirror of
https://github.com/markqvist/OpenModem.git
synced 2024-10-01 03:15:46 -04:00
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
|
||||
|
||||
// CSMA Settings
|
||||
#define CONFIG_FULL_DUPLEX false // TODO: Actually implement fdx
|
||||
#define CONFIG_CSMA_P 255
|
||||
|
||||
// Packet settings
|
||||
|
@ -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; i<SAMPLESPERBIT / 2; i++) {
|
||||
for (int i = 0; i<ADC_SAMPLESPERBIT / 2; i++) {
|
||||
fifo_push(&afsk->delayFifo, 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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) |
|
||||
|
@ -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);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <util/atomic.h>
|
||||
|
||||
#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;
|
||||
|
Loading…
Reference in New Issue
Block a user