diff --git a/Inc/common.h b/Inc/common.h
index fb2262c..8f309ef 100644
--- a/Inc/common.h
+++ b/Inc/common.h
@@ -22,6 +22,7 @@ along with VP-Digi. If not, see .
#define IS_UPPERCASE_ALPHANUMERIC(x) ((((x) >= '0') && ((x) <= '9')) || (((x) >= 'A') && ((x) <= 'Z')))
#define IS_NUMBER(x) (((x) >= '0') && ((x) <= '9'))
+#define ABS(x) (((x) > 0) ? (x) : (-x))
#define CRC32_INIT 0xFFFFFFFF
diff --git a/Src/drivers/modem.c b/Src/drivers/modem.c
index ec9497b..006b7a3 100644
--- a/Src/drivers/modem.c
+++ b/Src/drivers/modem.c
@@ -69,13 +69,13 @@ along with VP-Digi. If not, see .
#define PLL300_LOCKED_TUNE 0.74f
#define PLL300_NOT_LOCKED_TUNE 0.50f
+#define AGC9600_ATTACK 0.08f
+#define AGC9600_DECAY 0.0008f
+
#define DAC_SINE_SIZE 32 //DAC sine table size
-#define PTT_ON GPIOB->BSRR = GPIO_BSRR_BS7
-#define PTT_OFF GPIOB->BSRR = GPIO_BSRR_BR7
-#define DCD_ON (GPIOC->BSRR = GPIO_BSRR_BR13)
-#define DCD_OFF (GPIOC->BSRR = GPIO_BSRR_BS13)
+
struct ModemDemodConfig ModemConfig;
@@ -92,9 +92,9 @@ static float baudRate; //baudrate
static uint8_t markStep; //mark timer step
static uint8_t spaceStep; //space timer step
static uint16_t baudRateStep; //baudrate timer step
-static int32_t coeffHiI[NMAX], coeffLoI[NMAX], coeffHiQ[NMAX], coeffLoQ[NMAX]; //correlator IQ coefficients
+static int16_t coeffHiI[NMAX], coeffLoI[NMAX], coeffHiQ[NMAX], coeffLoQ[NMAX]; //correlator IQ coefficients
static uint8_t dcd = 0; //multiplexed DCD state from both demodulators
-
+static uint32_t lfsr = 0; //LFSR for 9600 Bd
/**
* @brief BPF filter with 2200 Hz tone 6 dB preemphasis (it actually attenuates 1200 Hz tone by 6 dB)
@@ -193,7 +193,7 @@ struct DemodState
enum ModemPrefilter prefilter;
struct Filter bpf;
- int32_t correlatorSamples[NMAX];
+ int16_t correlatorSamples[NMAX];
uint8_t correlatorSamplesIdx;
struct Filter lpf;
@@ -214,6 +214,9 @@ struct DemodState
int32_t dcdInc;
int32_t dcdDec;
float dcdAdjust;
+
+ int16_t peak;
+ int16_t valley;
};
static struct DemodState demodState[MODEM_MAX_DEMODULATOR_COUNT];
@@ -296,6 +299,15 @@ static void setDcd(uint8_t state)
}
}
+static inline uint8_t scramble(uint8_t in)
+{
+ //G3RUH scrambling (x^17+x^12+1)
+ uint8_t bit = ((lfsr & 0x10000) > 0) ^ ((lfsr & 0x800) > 0) ^ (in > 0);
+
+ lfsr <<= 1;
+ lfsr |= bit;
+ return bit;
+}
/**
* @brief ISR for demodulator
@@ -343,18 +355,34 @@ void TIM1_UP_IRQHandler(void)
{
TIM1->SR &= ~TIM_SR_UIF;
+ int32_t sample = 0;
+
+ if(ModemConfig.modem == MODEM_9600)
+ {
+ if(ModemConfig.usePWM)
+ sample = currentSymbol ? 90 : 0;
+ else
+ sample = currentSymbol ? 15 : 1;
+
+ sample = filter(&demodState[0].lpf, sample);
+ }
+ else
+ {
+ sample = dacSine[dacSineIdx];
+ dacSineIdx++;
+ dacSineIdx &= (DAC_SINE_SIZE - 1);
+ }
+
if(ModemConfig.usePWM)
{
- TIM4->CCR1 = dacSine[dacSineIdx];
+ TIM4->CCR1 = sample;
}
else
{
GPIOB->ODR &= ~0xF000; //zero 4 oldest bits
- GPIOB->ODR |= (dacSine[dacSineIdx] << 12); //write sample to 4 oldest bits
+ GPIOB->ODR |= (sample << 12); //write sample to 4 oldest bits
}
- dacSineIdx++;
- dacSineIdx &= (DAC_SINE_SIZE - 1);
}
@@ -381,10 +409,17 @@ void TIM3_IRQHandler(void)
TIM1->CNT = 0;
- if(currentSymbol) //current symbol is space
- TIM1->ARR = spaceStep;
- else //mark
- TIM1->ARR = markStep;
+ if(ModemConfig.modem == MODEM_9600)
+ {
+ currentSymbol = scramble(currentSymbol);
+ }
+ else
+ {
+ if(currentSymbol) //current symbol is space
+ TIM1->ARR = spaceStep;
+ else //mark
+ TIM1->ARR = markStep;
+ }
}
@@ -400,34 +435,38 @@ static int32_t demodulate(int16_t sample, struct DemodState *dem)
dem->RMSenergy += ((sample >> 1) * (sample >> 1)); //square the sample and add it to the sum
dem->RMSsampleCount++; //increment number of samples
- if(dem->prefilter != PREFILTER_NONE) //filter is used
- {
- dem->correlatorSamples[dem->correlatorSamplesIdx++] = filter(&dem->bpf, sample);
- }
- else //no pre/deemphasis
+ if(ModemConfig.modem != MODEM_9600)
{
- dem->correlatorSamples[dem->correlatorSamplesIdx++] = sample;
- }
+ if(dem->prefilter != PREFILTER_NONE) //filter is used
+ {
+ dem->correlatorSamples[dem->correlatorSamplesIdx++] = filter(&dem->bpf, sample);
+ }
+ else //no pre/deemphasis
+ {
+ dem->correlatorSamples[dem->correlatorSamplesIdx++] = sample;
+ }
- dem->correlatorSamplesIdx %= N;
+ dem->correlatorSamplesIdx %= N;
- int64_t outLoI = 0, outLoQ = 0, outHiI = 0, outHiQ = 0; //output values after correlating
+ int32_t outLoI = 0, outLoQ = 0, outHiI = 0, outHiQ = 0; //output values after correlating
- for(uint8_t i = 0; i < N; i++)
- {
- int32_t t = dem->correlatorSamples[(dem->correlatorSamplesIdx + i) % N]; //read sample
- outLoI += t * coeffLoI[i]; //correlate sample
- outLoQ += t * coeffLoQ[i];
- outHiI += t * coeffHiI[i];
- outHiQ += t * coeffHiQ[i];
+ for(uint8_t i = 0; i < N; i++)
+ {
+ int16_t t = dem->correlatorSamples[(dem->correlatorSamplesIdx + i) % N]; //read sample
+ outLoI += t * coeffLoI[i]; //correlate sample
+ outLoQ += t * coeffLoQ[i];
+ outHiI += t * coeffHiI[i];
+ outHiQ += t * coeffHiQ[i];
+ }
+
+ outHiI >>= 12;
+ outHiQ >>= 12;
+ outLoI >>= 12;
+ outLoQ >>= 12;
+
+ sample = ABS(outHiI) + ABS(outHiQ) - ABS(outLoI) - ABS(outLoQ);
}
- outHiI >>= 12;
- outHiQ >>= 12;
- outLoI >>= 12;
- outLoQ >>= 12;
- uint64_t hi = (outHiI * outHiI) + (outHiQ * outHiQ); //calculate output tone levels
- uint64_t lo = (outLoI * outLoI) + (outLoQ * outLoQ);
//DCD using PLL
//PLL is running nominally at 1200 Hz (= baudrate)
@@ -443,9 +482,7 @@ static int32_t demodulate(int16_t sample, struct DemodState *dem)
dem->dcdPll = (signed)((unsigned)(dem->dcdPll) + ((unsigned)dem->pll)); //keep PLL ticking at the frequency equal to baudrate
- uint8_t dcdSymbol = (hi > lo); //get current symbol
-
- if(dcdSymbol != dem->dcdLastSymbol) //tone changed
+ if((sample > 0) != dem->dcdLastSymbol) //tone changed
{
if(abs(dem->dcdPll) < dem->dcdInc) //tone change occurred near zero
dem->dcdCounter += dem->dcdInc; //increase DCD counter
@@ -457,7 +494,7 @@ static int32_t demodulate(int16_t sample, struct DemodState *dem)
dem->dcdPll = (int)(dem->dcdPll * dem->dcdAdjust); //adjust PLL
}
- dem->dcdLastSymbol = dcdSymbol; //store last symbol for symbol change detection
+ dem->dcdLastSymbol = sample > 0; //store last symbol for symbol change detection
if(dem->dcdCounter > dem->dcdMax) //maximum DCD counter value reached
dem->dcdCounter = dem->dcdMax; //avoid "sticky" DCD and counter overflow
@@ -467,10 +504,41 @@ static int32_t demodulate(int16_t sample, struct DemodState *dem)
else //below DCD threshold
dem->dcd = 0; //no DCD
- return filter(&dem->lpf, hi - lo) > 0;
-}
+ //TODO: check if demodulator works well after all changes
+ sample = filter(&dem->lpf, sample);
+
+ if(ModemConfig.modem == MODEM_9600)
+ {
+ //AGC
+ if(sample >= dem->peak)
+ {
+ dem->peak += (((int32_t)(AGC9600_ATTACK * (float)32768) * (int32_t)(sample - dem->peak)) >> 15);
+ }
+ else
+ {
+ dem->peak += (((int32_t)(AGC9600_DECAY * (float)32768) * (int32_t)(sample - dem->peak)) >> 15);
+ }
+
+ if(sample <= dem->valley)
+ {
+ dem->valley += (((int32_t)(AGC9600_ATTACK * (float)32768) * (int32_t)(sample - dem->valley)) >> 15);
+ }
+ else
+ {
+ dem->valley += (((int32_t)(AGC9600_DECAY * (float)32768) * (int32_t)(sample - dem->valley)) >> 15);
+ }
+ //remove DC component (subtract average value of peaks)
+ //and normalize to 32768 peak-to-peak (-16384:16384)
+ //32768 is equal to 1 << 15
+ if(dem->peak > dem->valley)
+ {
+ sample = ((((int32_t)(sample) - ((int32_t)(dem->peak + dem->valley) >> 1)) << 15) / (int32_t)(dem->peak - dem->valley));
+ }
+ }
+ return sample > 0;
+}
/**
@@ -497,12 +565,16 @@ static void decode(uint8_t symbol, uint8_t demod)
{
dem->syncSymbols <<= 1; //shift recovered (received, synchronized) bit register
- uint8_t t = dem->rawSymbols & 0x07; //take last three symbols for sampling. Seems that 1 symbol is not enough, but 3 symbols work well
- if(t == 0b111 || t == 0b110 || t == 0b101 || t == 0b011) //if there are 2 or 3 ones, then the received symbol is 1
- {
- dem->syncSymbols |= 1; //push to recovered symbols register
- }
- //if there 2 or 3 zeros, no need to add anything to the register
+ uint8_t sym = dem->rawSymbols & 0x07; //take last three symbols for sampling. Seems that 1 symbol is not enough, but 3 symbols work well
+ if(sym == 0b111 || sym == 0b110 || sym == 0b101 || sym == 0b011) //if there are 2 or 3 ones, then the received symbol is 1
+ sym = 1;
+ else
+ sym = 0;
+
+ if(ModemConfig.modem == MODEM_9600)
+ sym = scramble(sym); //descramble
+
+ dem->syncSymbols |= sym;
//NRZI decoding
if (((dem->syncSymbols & 0x03) == 0b11) || ((dem->syncSymbols & 0x03) == 0b00)) //two last symbols are the same - no symbol transition - decoded bit 1
@@ -540,29 +612,23 @@ void ModemTxTestStart(enum ModemTxTestMode type)
setPtt(1); //PTT on
txTestState = type;
- //DAC timer
- TIM1->PSC = 17; //72/18=4 MHz
- TIM1->DIER = TIM_DIER_UIE; //enable interrupt
- TIM1->CR1 |= TIM_CR1_CEN; //enable timer
-
TIM2->CR1 &= ~TIM_CR1_CEN; //disable RX timer
+ TIM1->CR1 |= TIM_CR1_CEN; //enable DAC timer
NVIC_DisableIRQ(DMA1_Channel2_IRQn); //disable RX DMA interrupt
- NVIC_EnableIRQ(TIM1_UP_IRQn); //enable timer 1 for PWM
+ NVIC_EnableIRQ(TIM1_UP_IRQn); //enable DAC interrupt
if(type == TEST_MARK)
{
TIM1->ARR = markStep;
- } else if(type == TEST_SPACE)
+ }
+ else if(type == TEST_SPACE)
{
TIM1->ARR = spaceStep;
}
else //alternating tones
{
//enable baudrate generator
- TIM3->PSC = 71; //72/72=1 MHz
- TIM3->DIER = TIM_DIER_UIE; //enable interrupt
- TIM3->ARR = baudRateStep; //set timer interval
TIM3->CR1 = TIM_CR1_CEN; //enable timer
NVIC_EnableIRQ(TIM3_IRQn); //enable interrupt in NVIC
}
@@ -573,8 +639,8 @@ void ModemTxTestStop(void)
{
txTestState = TEST_DISABLED;
- TIM3->CR1 &= ~TIM_CR1_CEN; //turn off timers
- TIM1->CR1 &= ~TIM_CR1_CEN;
+ TIM3->CR1 &= ~TIM_CR1_CEN; //disable baudrate timer
+ TIM1->CR1 &= ~TIM_CR1_CEN; //disable DAC timer
TIM2->CR1 |= TIM_CR1_CEN; //enable RX timer
NVIC_DisableIRQ(TIM3_IRQn);
@@ -589,14 +655,6 @@ void ModemTransmitStart(void)
{
setPtt(1); //PTT on
- TIM1->PSC = 17;
- TIM1->DIER |= TIM_DIER_UIE;
-
-
- TIM3->PSC = 71;
- TIM3->DIER |= TIM_DIER_UIE;
- TIM3->ARR = baudRateStep;
-
TIM3->CR1 = TIM_CR1_CEN;
TIM1->CR1 = TIM_CR1_CEN;
TIM2->CR1 &= ~TIM_CR1_CEN;
@@ -612,7 +670,6 @@ void ModemTransmitStart(void)
*/
void ModemTransmitStop(void)
{
-
TIM2->CR1 |= TIM_CR1_CEN;
TIM3->CR1 &= ~TIM_CR1_CEN;
TIM1->CR1 &= ~TIM_CR1_CEN;
@@ -628,14 +685,14 @@ void ModemTransmitStop(void)
/**
* @brief Controls PTT output
- * @param[in] state 0 - PTT off, 1 - PTT on
+ * @param state 0 - PTT off, 1 - PTT on
*/
static void setPtt(uint8_t state)
{
if(state)
- PTT_ON;
+ GPIOB->BSRR = GPIO_BSRR_BS7;
else
- PTT_OFF;
+ GPIOB->BSRR = GPIO_BSRR_BR7;
}
@@ -646,6 +703,90 @@ void ModemInit(void)
{
memset(demodState, 0, sizeof(demodState));
+ /**
+ * TIM1 is used for pushing samples to DAC (R2R or PWM) (clocked at 4 MHz)
+ * TIM3 is the baudrate generator for TX (clocked at 1 MHz)
+ * TIM4 is the PWM generator with no software interrupt
+ * TIM2 is the RX sampling timer with no software interrupt, but it directly calls DMA
+ */
+
+ RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
+ RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
+ RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
+ RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
+ RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
+ RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
+ RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
+ RCC->AHBENR |= RCC_AHBENR_DMA1EN;
+
+
+ GPIOC->CRH |= GPIO_CRH_MODE13_1; //DCD LED on PC13
+ GPIOC->CRH &= ~GPIO_CRH_MODE13_0;
+ GPIOC->CRH &= ~GPIO_CRH_CNF13;
+
+ GPIOB->CRH &= ~0xFFFF0000; //R2R output on PB12-PB15
+ GPIOB->CRH |= 0x22220000;
+
+ GPIOA->CRL &= ~GPIO_CRL_CNF0; //ADC input on PA0
+ GPIOA->CRL &= ~GPIO_CRL_MODE0;
+
+
+ GPIOB->CRL |= GPIO_CRL_MODE7_1; //PTT output on PB7
+ GPIOB->CRL &= ~GPIO_CRL_MODE7_0;
+ GPIOB->CRL &= ~GPIO_CRL_CNF7;
+
+ GPIOB->CRL |= GPIO_CRL_MODE5_1; //2nd DCD LED on PB5
+ GPIOB->CRL &= ~GPIO_CRL_MODE5_0;
+ GPIOB->CRL &= ~GPIO_CRL_CNF5;
+
+
+ RCC->CFGR |= RCC_CFGR_ADCPRE_1; //ADC prescaler /6
+ RCC->CFGR &= ~RCC_CFGR_ADCPRE_0;
+
+ ADC1->CR2 |= ADC_CR2_CONT; //continuous conversion
+ ADC1->CR2 |= ADC_CR2_EXTSEL;
+ ADC1->SQR1 &= ~ADC_SQR1_L; //1 conversion
+ ADC1->SMPR2 |= ADC_SMPR2_SMP0_2; //41.5 cycle sampling
+ ADC1->SQR3 &= ~ADC_SQR3_SQ1; //channel 0 is first in the sequence
+ ADC1->CR2 |= ADC_CR2_ADON; //ADC on
+
+ ADC1->CR2 |= ADC_CR2_RSTCAL; //calibrate ADC
+ while(ADC1->CR2 & ADC_CR2_RSTCAL)
+ ;
+ ADC1->CR2 |= ADC_CR2_CAL;
+ while(ADC1->CR2 & ADC_CR2_CAL)
+ ;
+
+ ADC1->CR2 |= ADC_CR2_EXTTRIG;
+ ADC1->CR2 |= ADC_CR2_SWSTART; //start ADC conversion
+
+ //prepare DMA
+ DMA1_Channel2->CCR |= DMA_CCR_MSIZE_0; //16 bit memory region
+ DMA1_Channel2->CCR &= ~DMA_CCR_MSIZE_1;
+ DMA1_Channel2->CCR |= DMA_CCR_PSIZE_0;
+ DMA1_Channel2->CCR &= ~DMA_CCR_PSIZE_1;
+
+ DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_CIRC| DMA_CCR_TCIE; //circular mode, memory increment and interrupt
+ DMA1_Channel2->CNDTR = 4; //4 samples
+ DMA1_Channel2->CPAR = (uint32_t)&(ADC1->DR); //ADC data register address
+ DMA1_Channel2->CMAR = (uint32_t)samples; //sample buffer address
+ DMA1_Channel2->CCR |= DMA_CCR_EN; //enable DMA
+
+ NVIC_EnableIRQ(DMA1_Channel2_IRQn);
+
+
+ //RX sampling timer
+ TIM2->PSC = 8; //72/9=8 MHz
+ TIM2->DIER |= TIM_DIER_UDE; //enable calling DMA on timer tick
+
+ //TX DAC timer
+ TIM1->PSC = 17; //72/18=4 MHz
+ TIM1->DIER |= TIM_DIER_UIE;
+
+ //baudrate timer
+ TIM3->PSC = 71; //72/72=1 MHz
+ TIM3->DIER |= TIM_DIER_UIE;
+
if((ModemConfig.modem == MODEM_1200) || (ModemConfig.modem == MODEM_1200_V23))
{
demodCount = 2;
@@ -703,6 +844,8 @@ void ModemInit(void)
markFreq = 1300.f;
spaceFreq = 2100.f;
}
+
+ TIM2->ARR = 207; //8MHz / 208 =~38400 Hz (4*9600 Hz for 4x oversampling)
}
else if(ModemConfig.modem == MODEM_300)
{
@@ -710,7 +853,7 @@ void ModemInit(void)
N = N300;
baudRate = 300.f;
markFreq = 1600.f;
- markFreq = 1800.f;
+ spaceFreq = 1800.f;
demodState[0].pllStep = PLL300_STEP;
demodState[0].pllLockedAdjust = PLL300_LOCKED_TUNE;
@@ -728,88 +871,41 @@ void ModemInit(void)
demodState[0].lpf.coeffs = lpf300;
demodState[0].lpf.taps = sizeof(lpf300) / sizeof(*lpf300);
demodState[0].lpf.gainShift = 0; //not important, output is always compared with 0
- }
-
- markStep = 4000000 / (DAC_SINE_SIZE * markFreq) - 1;
- spaceStep = 4000000 / (DAC_SINE_SIZE * spaceFreq) - 1;
- baudRateStep = 1000000 / baudRate - 1;
-
-
- /**
- * TIM1 is used for pushing samples to DAC (R2R or PWM) at 4 MHz
- * TIM3 is the baudrate generator for TX running at 1 MHz
- * TIM4 is the PWM generator with no software interrupt
- * TIM2 is the RX sampling timer with no software interrupt, but it directly calls DMA
- */
-
- RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
- RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
- RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
- RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
- RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
- RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
- RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
- RCC->AHBENR |= RCC_AHBENR_DMA1EN;
-
-
- GPIOC->CRH |= GPIO_CRH_MODE13_1; //DCD LED on PC13
- GPIOC->CRH &= ~GPIO_CRH_MODE13_0;
- GPIOC->CRH &= ~GPIO_CRH_CNF13;
-
- GPIOB->CRH &= ~0xFFFF0000; //R2R output on PB12-PB15
- GPIOB->CRH |= 0x22220000;
- GPIOA->CRL &= ~GPIO_CRL_CNF0; //ADC input on PA0
- GPIOA->CRL &= ~GPIO_CRL_MODE0;
-
-
- GPIOB->CRL |= GPIO_CRL_MODE7_1; //PTT output on PB7
- GPIOB->CRL &= ~GPIO_CRL_MODE7_0;
- GPIOB->CRL &= ~GPIO_CRL_CNF7;
-
- GPIOB->CRL |= GPIO_CRL_MODE5_1; //2nd DCD LED on PB5
- GPIOB->CRL &= ~GPIO_CRL_MODE5_0;
- GPIOB->CRL &= ~GPIO_CRL_CNF5;
-
-
- RCC->CFGR |= RCC_CFGR_ADCPRE_1; //ADC prescaler /6
- RCC->CFGR &= ~RCC_CFGR_ADCPRE_0;
-
- ADC1->CR2 |= ADC_CR2_CONT; //continuous conversion
- ADC1->CR2 |= ADC_CR2_EXTSEL;
- ADC1->SQR1 &= ~ADC_SQR1_L; //1 conversion
- ADC1->SMPR2 |= ADC_SMPR2_SMP0_2; //41.5 cycle sampling
- ADC1->SQR3 &= ~ADC_SQR3_SQ1; //channel 0 is first in the sequence
- ADC1->CR2 |= ADC_CR2_ADON; //ADC on
+ TIM2->ARR = 416; //8MHz / 416 =~19200 Hz (4*4800 Hz for 4x oversampling)
+ }
+ else if(ModemConfig.modem == MODEM_9600)
+ {
+ demodCount = 1;
+ N = N9600;
+ baudRate = 9600.f;
+
+ demodState[0].pllStep = PLL9600_STEP;
+ demodState[0].pllLockedAdjust = PLL9600_LOCKED_TUNE;
+ demodState[0].pllNotLockedAdjust = PLL9600_NOT_LOCKED_TUNE;
+ demodState[0].dcdMax = DCD9600_MAXPULSE;
+ demodState[0].dcdThres = DCD9600_THRES;
+ demodState[0].dcdInc = DCD9600_INC;
+ demodState[0].dcdDec = DCD9600_DEC;
+ demodState[0].dcdAdjust = DCD9600_PLLTUNE;
- ADC1->CR2 |= ADC_CR2_RSTCAL; //calibrate ADC
- while(ADC1->CR2 & ADC_CR2_RSTCAL)
- ;
- ADC1->CR2 |= ADC_CR2_CAL;
- while(ADC1->CR2 & ADC_CR2_CAL)
- ;
+ demodState[0].prefilter = PREFILTER_NONE;
+ //this filter will be used for RX and TX
+ demodState[0].lpf.coeffs = lpf9600;
+ demodState[0].lpf.taps = sizeof(lpf9600) / sizeof(*lpf9600);
+ demodState[0].lpf.gainShift = 16;
- ADC1->CR2 |= ADC_CR2_EXTTRIG;
- ADC1->CR2 |= ADC_CR2_SWSTART; //start ADC conversion
+ TIM2->ARR = 51; //8MHz / 52 =~153600 Hz (4*38400 Hz for 4x oversampling)
+ }
- //prepare DMA
- DMA1_Channel2->CCR |= DMA_CCR_MSIZE_0; //16 bit memory region
- DMA1_Channel2->CCR &= ~DMA_CCR_MSIZE_1;
- DMA1_Channel2->CCR |= DMA_CCR_PSIZE_0;
- DMA1_Channel2->CCR &= ~DMA_CCR_PSIZE_1;
+ TIM2->CR1 |= TIM_CR1_CEN; //enable DMA timer
- DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_CIRC| DMA_CCR_TCIE; //circular mode, memory increment and interrupt
- DMA1_Channel2->CNDTR = 4; //4 samples
- DMA1_Channel2->CPAR = (uint32_t)&(ADC1->DR); //ADC data register address
- DMA1_Channel2->CMAR = (uint32_t)samples; //sample buffer address
- DMA1_Channel2->CCR |= DMA_CCR_EN; //enable DMA
+ markStep = 4000000 / (DAC_SINE_SIZE * markFreq) - 1;
+ spaceStep = 4000000 / (DAC_SINE_SIZE * spaceFreq) - 1;
+ baudRateStep = 1000000 / baudRate - 1;
- NVIC_EnableIRQ(DMA1_Channel2_IRQn);
- TIM2->PSC = 17; //72/18=4 MHz
- TIM2->DIER |= TIM_DIER_UDE; //enable calling DMA on timer tick
- TIM2->ARR = 103; //4MHz / 104 =~38400 Hz (4*9600 Hz for 4x oversampling)
- TIM2->CR1 |= TIM_CR1_CEN; //enable timer
+ TIM3->ARR = baudRateStep;
for(uint8_t i = 0; i < N; i++) //calculate correlator coefficients
{