Browse Source

working on more modems

pull/32/head
sq8vps 2 years ago
parent
commit
e4f659d9da
4 changed files with 301 additions and 145 deletions
  1. +29
    -11
      Inc/drivers/modem.h
  2. +5
    -5
      Src/ax25.c
  3. +261
    -121
      Src/drivers/modem.c
  4. +6
    -8
      Src/main.c

+ 29
- 11
Inc/drivers/modem.h View File

@ -20,13 +20,18 @@ along with VP-Digi. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
//number of parallel demodulators
//number of maximum parallel demodulators
//each demodulator must be explicitly configured in code
#define MODEM_DEMODULATOR_COUNT 2
//currently used only for 1200 Bd modem
#define MODEM_MAX_DEMODULATOR_COUNT 2
#define MODEM_BAUDRATE 1200.f
#define MODEM_MARK_FREQUENCY 1200.f
#define MODEM_SPACE_FREQUENCY 2200.f
enum ModemType
{
MODEM_1200 = 0,
MODEM_1200_V23,
MODEM_300,
MODEM_9600,
};
enum ModemTxTestMode
{
@ -39,26 +44,39 @@ enum ModemTxTestMode
struct ModemDemodConfig
{
enum ModemType modem;
uint8_t usePWM : 1; //0 - use R2R, 1 - use PWM
uint8_t flatAudioIn : 1; //0 - normal (deemphasized) audio input, 1 - flat audio (unfiltered) input
};
extern struct ModemDemodConfig ModemConfig;
enum ModemEmphasis
enum ModemPrefilter
{
PREEMPHASIS,
DEEMPHASIS,
EMPHASIS_NONE
PREFILTER_PREEMPHASIS,
PREFILTER_DEEMPHASIS,
PREFILTER_FLAT,
PREFILTER_NONE,
};
/**
* @brief Get current modem baudrate
* @return Baudrate
*/
float ModemGetBaudrate(void);
/**
* @brief Get count of demodulators running in parallel
* @return Count of demodulators
*/
uint8_t ModemGetDemodulatorCount(void);
/**
* @brief Get filter type (preemphasis, deemphasis etc.) for given modem
* @brief Get prefilter type (preemphasis, deemphasis etc.) for given modem
* @param modem Modem number
* @return Filter type
*/
enum ModemEmphasis ModemGetFilterType(uint8_t modem);
enum ModemPrefilter ModemGetFilterType(uint8_t modem);
/**
* @brief Get current DCD state


+ 5
- 5
Src/ax25.c View File

@ -105,7 +105,7 @@ struct RxState
uint8_t frameReceived; //frame received flag
};
static volatile struct RxState rxState[MODEM_DEMODULATOR_COUNT];
static volatile struct RxState rxState[MODEM_MAX_DEMODULATOR_COUNT];
static uint16_t lastCrc = 0; //CRC of the last received frame. If not 0, a frame was successfully received
static uint16_t rxMultiplexDelay = 0; //simple delay for decoder multiplexer to avoid receiving the same frame twice
@ -229,11 +229,11 @@ void Ax25BitParse(uint8_t bit, uint8_t modem)
if(lastCrc != 0) //there was a frame received
{
rxMultiplexDelay++;
if(rxMultiplexDelay > (4 * MODEM_DEMODULATOR_COUNT)) //hold it for a while and wait for other decoders to receive the frame
if(rxMultiplexDelay > (4 * MODEM_MAX_DEMODULATOR_COUNT)) //hold it for a while and wait for other decoders to receive the frame
{
lastCrc = 0;
rxMultiplexDelay = 0;
for(uint8_t i = 0; i < MODEM_DEMODULATOR_COUNT; i++)
for(uint8_t i = 0; i < MODEM_MAX_DEMODULATOR_COUNT; i++)
{
frameReceived |= ((rxState[i].frameReceived > 0) << i);
rxState[i].frameReceived = 0;
@ -588,6 +588,6 @@ void Ax25Init(void)
for(uint8_t i = 0; i < (sizeof(rxState) / sizeof(rxState[0])); i++)
rxState[i].crc = 0xFFFF;
txDelay = ((float)Ax25Config.txDelayLength / (8.f * 1000.f / (float)MODEM_BAUDRATE)); //change milliseconds to byte count
txTail = ((float)Ax25Config.txTailLength / (8.f * 1000.f / (float)MODEM_BAUDRATE));
txDelay = ((float)Ax25Config.txDelayLength / (8.f * 1000.f / ModemGetBaudrate())); //change milliseconds to byte count
txTail = ((float)Ax25Config.txTailLength / (8.f * 1000.f / ModemGetBaudrate()));
}

+ 261
- 121
Src/drivers/modem.c View File

@ -35,17 +35,42 @@ along with VP-Digi. If not, see <http://www.gnu.org/licenses/>.
* The DCD mechanism is described in afsk_demod().
* All values were selected by trial and error
*/
#define DCD_MAXPULSE 100
#define DCD_THRES 30
#define DCD_DEC 1
#define DCD_INC 7
#define DCD_PLLTUNE 0
#define DCD1200_MAXPULSE 100
#define DCD1200_THRES 30
#define DCD1200_DEC 1
#define DCD1200_INC 7
#define DCD1200_PLLTUNE 0
#define DCD9600_MAXPULSE 200
#define DCD9600_THRES 80
#define DCD9600_DEC 3
#define DCD9600_INC 6
#define DCD9600_PLLTUNE 0
#define DCD300_MAXPULSE 50
#define DCD300_THRES 6
#define DCD300_DEC 1
#define DCD300_INC 5
#define DCD300_PLLTUNE 0
#define N1200 8 //samples per symbol
#define N9600 4
#define N300 16
#define NMAX 16 //keep this value equal to the biggest Nx
#define PLL1200_STEP (((uint64_t)1 << 32) / N1200) //PLL tick increment value
#define PLL9600_STEP (((uint64_t)1 << 32) / N9600)
#define PLL300_STEP (((uint64_t)1 << 32) / N300)
#define PLL1200_LOCKED_TUNE 0.74f
#define PLL1200_NOT_LOCKED_TUNE 0.50f
#define PLL9600_LOCKED_TUNE 0.89f
#define PLL9600_NOT_LOCKED_TUNE 0.50f //I have 0.67 noted somewhere as possibly better value
#define PLL300_LOCKED_TUNE 0.74f
#define PLL300_NOT_LOCKED_TUNE 0.50f
#define N 8 //samples per symbol
#define DAC_SINE_SIZE 32 //DAC sine table size
#define PLLINC 536870912 //PLL tick increment value
#define PLLLOCKED 0.74 //PLL adjustment value when locked
#define PLLNOTLOCKED 0.50 //PLL adjustment value when not locked
#define PTT_ON GPIOB->BSRR = GPIO_BSRR_BS7
#define PTT_OFF GPIOB->BSRR = GPIO_BSRR_BR7
@ -54,22 +79,27 @@ along with VP-Digi. If not, see <http://www.gnu.org/licenses/>.
struct ModemDemodConfig ModemConfig;
static uint8_t N; //samples per symbol
static enum ModemTxTestMode txTestState; //current TX test mode
static uint8_t demodCount; //actual number of parallel demodulators
static uint16_t dacSine[DAC_SINE_SIZE]; //sine samples for DAC
static uint8_t dacSineIdx; //current sine sample index
static uint16_t samples[4]; //very raw received samples, filled directly by DMA
static uint8_t currentSymbol; //current symbol for NRZI encoding
static uint8_t markFreq; //mark frequency (inter-sample interval)
static uint8_t spaceFreq; //space frequency (inter-sample interval)
static uint16_t baudRate; //baudrate
static int32_t coeffHiI[N], coeffLoI[N], coeffHiQ[N], coeffLoQ[N]; //correlator IQ coefficients
static float markFreq; //mark frequency
static float spaceFreq; //space frequency
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 uint8_t dcd = 0; //multiplexed DCD state from both demodulators
/**
* @brief BPF filter with 2200 Hz tone 6 dB preemphasis (it actually attenuates 1200 Hz tone by 6 dB)
*/
static const int16_t bpfCoeffs[8] =
static int16_t bpf1200[8] =
{
728,
-13418,
@ -84,7 +114,7 @@ static const int16_t bpfCoeffs[8] =
/**
* @brief BPF filter with 2200 Hz tone 6 dB deemphasis
*/
static const int16_t invBpfCoeffs[8] =
static int16_t bpf1200Inv[8] =
{
-10513,
-10854,
@ -96,14 +126,29 @@ static const int16_t invBpfCoeffs[8] =
-879
};
#define BPF_TAPS (sizeof(bpfCoeffs) / sizeof(*bpfCoeffs) > sizeof(invBpfCoeffs) / sizeof(*invBpfCoeffs) ? \
sizeof(bpfCoeffs) / sizeof(*bpfCoeffs) : sizeof(invBpfCoeffs) / sizeof(*invBpfCoeffs))
//fs=4800, rectangular, fc1=1400, fc2=2000, 0 dB @ 1600 Hz and 1800 Hz, N = 15, gain 65536
static int16_t bpf300[15] =
{
-2327, 3557, 1048, -9284, 12210, -3989, -9849, 17268, -9849, -3989, 12210, -9284, 1048, 3557, -2327,
};
/**
* @brief Output LPF filter to remove data faster than 1200 baud
* It actually is a 600 Hz filter: symbols can change at 1200 Hz, but it takes 2 "ticks" to return to the same symbol - that's why it's 600 Hz
*/
static const int16_t lpfCoeffs[15] =
#define BPF_MAX_TAPS 15
//fs=4800 Hz, raised cosine, fc=300 Hz (BR=600 Bd), beta=0.8, N=14, gain=65536
static int16_t lpf300[14] =
{
741, 1834, 3216, 4756, 6268, 7547, 8402, 8402, 7547, 6268, 4756, 3216, 1834, 741,
};
#ifdef EXPERIMENTAL_LPF1200
//fs=9600 Hz, raised cosine, fc=600Hz (BR=1200 Bd), beta=0.8, N=14, gain=65536
static const int16_t lpf1200[14] =
{
741, 1834, 3216, 4756, 6268, 7547, 8402, 8402, 7547, 6268, 4756, 3216, 1834, 741,
};
#define LPF_MAX_TAPS 14
#else
static int16_t lpf1200[15] =
{
-6128,
-5974,
@ -122,34 +167,86 @@ static const int16_t lpfCoeffs[15] =
-6128
};
#define LPF_TAPS (sizeof(lpfCoeffs) / sizeof(*lpfCoeffs))
#define LPF_MAX_TAPS 15
#endif
//fs=38400 Hz, Gaussian, fc=4800 Hz (9600 Bd), N=9, gain=65536
//seems like there is no difference between N=9 and any higher order
static int16_t lpf9600[9] = {497, 2360, 7178, 13992, 17478, 13992, 7178, 2360, 497};
#define FILTER_MAX_TAPS ((LPF_MAX_TAPS > BPF_MAX_TAPS) ? LPF_MAX_TAPS : BPF_MAX_TAPS)
struct Filter
{
int16_t *coeffs;
uint8_t taps;
int32_t samples[FILTER_MAX_TAPS];
uint8_t gainShift;
};
struct DemodState
{
enum ModemEmphasis emphasis; //preemphasis/deemphasis
uint8_t rawSymbols; //raw, unsynchronized symbols
uint8_t syncSymbols; //synchronized symbols
int16_t rawSample[BPF_TAPS]; //input (raw) samples
int32_t rxSample[BPF_TAPS]; //rx samples after pre/deemphasis filter
uint8_t rxSampleIdx; //index for the array above
int64_t lpfSample[LPF_TAPS]; //rx samples after final filtering
enum ModemPrefilter prefilter;
struct Filter bpf;
int32_t correlatorSamples[NMAX];
uint8_t correlatorSamplesIdx;
struct Filter lpf;
uint8_t dcd : 1; //DCD state
uint64_t RMSenergy; //frame energy counter (sum of samples squared)
uint32_t RMSsampleCount; //number of samples for RMS
int32_t pll; //bit recovery PLL counter
int32_t lastPll; //last bit recovery PLL counter value
int32_t pllStep;
float pllLockedAdjust;
float pllNotLockedAdjust;
int32_t dcdPll; //DCD PLL main counter
uint8_t dcdLastSymbol; //last symbol for DCD
uint8_t dcdCounter; //DCD "pulse" counter (incremented when RX signal is correct)
int32_t dcdMax;
int32_t dcdThres;
int32_t dcdInc;
int32_t dcdDec;
float dcdAdjust;
};
static volatile struct DemodState demodState[MODEM_DEMODULATOR_COUNT];
static struct DemodState demodState[MODEM_MAX_DEMODULATOR_COUNT];
static void decode(uint8_t symbol, uint8_t demod);
static int32_t demodulate(int16_t sample, struct DemodState *dem);
static void setPtt(uint8_t state);
static int32_t filter(struct Filter *filter, int32_t input)
{
int32_t out = 0;
for(uint8_t i = filter->taps - 1; i > 0; i--)
filter->samples[i] = filter->samples[i - 1]; //shift old samples
filter->samples[0] = input; //store new sample
for(uint8_t i = 0; i < filter->taps; i++)
{
out += filter->coeffs[i] * filter->samples[i];
}
return out >> filter->gainShift;
}
float ModemGetBaudrate(void)
{
return baudRate;
}
uint8_t ModemGetDemodulatorCount(void)
{
return demodCount;
}
uint8_t ModemDcdState(void)
{
return dcd;
@ -176,9 +273,9 @@ uint16_t ModemGetRMS(uint8_t modem)
return sqrtf((float)demodState[modem].RMSenergy / (float)demodState[modem].RMSsampleCount);
}
enum ModemEmphasis ModemGetFilterType(uint8_t modem)
enum ModemPrefilter ModemGetFilterType(uint8_t modem)
{
return demodState[modem].emphasis;
return demodState[modem].prefilter;
}
/**
@ -213,14 +310,14 @@ void DMA1_Channel2_IRQHandler(void)
int32_t sample = ((samples[0] + samples[1] + samples[2] + samples[3]) >> 1) - 4095; //calculate input sample (decimation)
uint8_t partialDcd = 0;
bool partialDcd = false;
for(uint8_t i = 0; i < MODEM_DEMODULATOR_COUNT; i++)
for(uint8_t i = 0; i < demodCount; i++)
{
uint8_t symbol = (demodulate(sample, (struct DemodState*)&demodState[i]) > 0); //demodulate sample
decode(symbol, i); //recover bits, decode NRZI and call higher level function
if(demodState[i].dcd)
partialDcd |= 1;
partialDcd = true;
}
if(partialDcd) //DCD on any of the demodulators
@ -285,9 +382,9 @@ void TIM3_IRQHandler(void)
TIM1->CNT = 0;
if(currentSymbol) //current symbol is space
TIM1->ARR = spaceFreq;
TIM1->ARR = spaceStep;
else //mark
TIM1->ARR = markFreq;
TIM1->ARR = markStep;
}
@ -300,48 +397,37 @@ void TIM3_IRQHandler(void)
*/
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->emphasis != EMPHASIS_NONE) //preemphasis/deemphasis is used
if(dem->prefilter != PREFILTER_NONE) //filter is used
{
int32_t out = 0; //filtered output
for(uint8_t i = BPF_TAPS - 1; i > 0; i--)
dem->rawSample[i] = dem->rawSample[i - 1]; //shift old samples
dem->rawSample[0] = sample; //store new sample
for(uint8_t i = 0; i < BPF_TAPS; i++)
{
if(dem->emphasis == PREEMPHASIS)
out += bpfCoeffs[i] * dem->rawSample[i]; //use preemphasis
else
out += invBpfCoeffs[i] * dem->rawSample[i]; //use deemphasis
}
dem->rxSample[dem->rxSampleIdx] = (out >> 15); //store filtered sample
dem->correlatorSamples[dem->correlatorSamplesIdx++] = filter(&dem->bpf, sample);
}
else //no pre/deemphasis
{
dem->rxSample[dem->rxSampleIdx] = sample; //store incoming sample
dem->correlatorSamples[dem->correlatorSamplesIdx++] = sample;
}
dem->rxSampleIdx = (dem->rxSampleIdx + 1) % BPF_TAPS; //increment sample pointer and wrap around if needed
dem->correlatorSamplesIdx %= N;
int64_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->rxSample[(dem->rxSampleIdx + i) % BPF_TAPS]; //read sample
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];
}
uint64_t hi = 0, lo = 0;
hi = ((outHiI >> 12) * (outHiI >> 12)) + ((outHiQ >> 12) * (outHiQ >> 12)); //calculate output tone levels
lo = ((outLoI >> 12) * (outLoI >> 12)) + ((outLoQ >> 12) * (outLoQ >> 12));
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)
@ -355,45 +441,33 @@ static int32_t demodulate(int16_t sample, struct DemodState *dem)
//when configured properly, it's generally immune to noise, as the detected tone changes much faster than 1200 baud
//it's also important to set some maximum value for DCD counter, otherwise the DCD is "sticky"
dem->dcdPll = (signed)((unsigned)(dem->dcdPll) + ((unsigned)PLLINC)); //keep PLL ticking at the frequency equal to baudrate
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(abs(dem->dcdPll) < PLLINC) //tone change occurred near zero
dem->dcdCounter += DCD_INC; //increase DCD counter
if(abs(dem->dcdPll) < dem->dcdInc) //tone change occurred near zero
dem->dcdCounter += dem->dcdInc; //increase DCD counter
else //tone change occurred far from zero
{
if(dem->dcdCounter >= DCD_DEC) //avoid overflow
dem->dcdCounter -= DCD_DEC; //decrease DCD counter
if(dem->dcdCounter >= dem->dcdDec) //avoid overflow
dem->dcdCounter -= dem->dcdDec; //decrease DCD counter
}
dem->dcdPll = (int)(dem->dcdPll * DCD_PLLTUNE); //adjust PLL
dem->dcdPll = (int)(dem->dcdPll * dem->dcdAdjust); //adjust PLL
}
dem->dcdLastSymbol = dcdSymbol; //store last symbol for symbol change detection
if(dem->dcdCounter > DCD_MAXPULSE) //maximum DCD counter value reached
dem->dcdCounter = DCD_MAXPULSE; //avoid "sticky" DCD and counter overflow
if(dem->dcdCounter > dem->dcdMax) //maximum DCD counter value reached
dem->dcdCounter = dem->dcdMax; //avoid "sticky" DCD and counter overflow
if(dem->dcdCounter > DCD_THRES) //DCD threshold reached
if(dem->dcdCounter > dem->dcdThres) //DCD threshold reached
dem->dcd = 1; //DCD!
else //below DCD threshold
dem->dcd = 0; //no DCD
//filter out signal faster than 1200 baud
int64_t out = 0;
for(uint8_t i = LPF_TAPS - 1; i > 0; i--)
dem->lpfSample[i] = dem->lpfSample[i - 1];
dem->lpfSample[0] = (int64_t)hi - (int64_t)lo;
for(uint8_t i = 0; i < LPF_TAPS; i++)
{
out += lpfCoeffs[i] * dem->lpfSample[i];
}
return out > 0;
return filter(&dem->lpf, hi - lo) > 0;
}
@ -411,15 +485,15 @@ static void decode(uint8_t symbol, uint8_t demod)
//This function provides bit/clock recovery and NRZI decoding
//Bit recovery is based on PLL which is described in the function above (DCD PLL)
//Current symbol is sampled at PLL counter overflow, so symbol transition should occur at PLL counter zero
dem->lastPll = dem->pll; //store last clock state
int32_t previous = dem->pll; //store last clock state
dem->pll = (signed)((unsigned)(dem->pll) + (unsigned)PLLINC); //keep PLL running
dem->pll = (signed)((unsigned)(dem->pll) + (unsigned)dem->pllStep); //keep PLL running
dem->rawSymbols <<= 1; //store received unsynchronized symbol
dem->rawSymbols |= (symbol & 1);
if ((dem->pll < 0) && (dem->lastPll > 0)) //PLL counter overflow, sample symbol, decode NRZI and process in higher layer
if ((dem->pll < 0) && (previous > 0)) //PLL counter overflow, sample symbol, decode NRZI and process in higher layer
{
dem->syncSymbols <<= 1; //shift recovered (received, synchronized) bit register
@ -446,11 +520,11 @@ static void decode(uint8_t symbol, uint8_t demod)
if(Ax25GetRxStage(demod) != RX_STAGE_FRAME) //not in a frame
{
dem->pll = (int)(dem->pll * PLLNOTLOCKED); //adjust PLL faster
dem->pll = (int)(dem->pll * dem->pllNotLockedAdjust); //adjust PLL faster
}
else //in a frame
{
dem->pll = (int)(dem->pll * PLLLOCKED); //adjust PLL slower
dem->pll = (int)(dem->pll * dem->pllLockedAdjust); //adjust PLL slower
}
}
@ -478,17 +552,17 @@ void ModemTxTestStart(enum ModemTxTestMode type)
if(type == TEST_MARK)
{
TIM1->ARR = markFreq;
TIM1->ARR = markStep;
} else if(type == TEST_SPACE)
{
TIM1->ARR = spaceFreq;
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 = baudRate; //set timer interval
TIM3->ARR = baudRateStep; //set timer interval
TIM3->CR1 = TIM_CR1_CEN; //enable timer
NVIC_EnableIRQ(TIM3_IRQn); //enable interrupt in NVIC
}
@ -521,7 +595,7 @@ void ModemTransmitStart(void)
TIM3->PSC = 71;
TIM3->DIER |= TIM_DIER_UIE;
TIM3->ARR = baudRate;
TIM3->ARR = baudRateStep;
TIM3->CR1 = TIM_CR1_CEN;
TIM1->CR1 = TIM_CR1_CEN;
@ -565,12 +639,102 @@ static void setPtt(uint8_t state)
}
/**
* @brief Initialize AFSK module
*/
void ModemInit(void)
{
memset(demodState, 0, sizeof(demodState));
if((ModemConfig.modem == MODEM_1200) || (ModemConfig.modem == MODEM_1200_V23))
{
demodCount = 2;
N = N1200;
baudRate = 1200.f;
demodState[0].pllStep = PLL1200_STEP;
demodState[0].pllLockedAdjust = PLL1200_LOCKED_TUNE;
demodState[0].pllNotLockedAdjust = PLL1200_NOT_LOCKED_TUNE;
demodState[0].dcdMax = DCD1200_MAXPULSE;
demodState[0].dcdThres = DCD1200_THRES;
demodState[0].dcdInc = DCD1200_INC;
demodState[0].dcdDec = DCD1200_DEC;
demodState[0].dcdAdjust = DCD1200_PLLTUNE;
demodState[1].pllStep = PLL1200_STEP;
demodState[1].pllLockedAdjust = PLL1200_LOCKED_TUNE;
demodState[1].pllNotLockedAdjust = PLL1200_NOT_LOCKED_TUNE;
demodState[1].dcdMax = DCD1200_MAXPULSE;
demodState[1].dcdThres = DCD1200_THRES;
demodState[1].dcdInc = DCD1200_INC;
demodState[1].dcdDec = DCD1200_DEC;
demodState[1].dcdAdjust = DCD1200_PLLTUNE;
demodState[0].prefilter = PREFILTER_NONE;
demodState[0].lpf.coeffs = lpf1200;
demodState[0].lpf.taps = sizeof(lpf1200) / sizeof(*lpf1200);
demodState[0].lpf.gainShift = 0; //not important, output is always compared with 0
demodState[1].lpf.coeffs = lpf1200;
demodState[1].lpf.taps = sizeof(lpf1200) / sizeof(*lpf1200);
demodState[1].lpf.gainShift = 0; //not important, output is always compared with 0
if(ModemConfig.flatAudioIn) //when used with flat audio input, use deemphasis and flat modems
{
demodState[1].prefilter = PREFILTER_DEEMPHASIS;
demodState[1].bpf.coeffs = bpf1200Inv;
demodState[1].bpf.taps = sizeof(bpf1200Inv) / sizeof(*bpf1200Inv);
demodState[1].bpf.gainShift = 15;
}
else //when used with normal (filtered) audio input, use flat and preemphasis modems
{
demodState[1].prefilter = PREFILTER_PREEMPHASIS;
demodState[1].bpf.coeffs = bpf1200;
demodState[1].bpf.taps = sizeof(bpf1200) / sizeof(*bpf1200);
demodState[1].bpf.gainShift = 15;
}
if(ModemConfig.modem == MODEM_1200) //Bell 202
{
markFreq = 1200.f;
spaceFreq = 2200.f;
}
else //V.23
{
markFreq = 1300.f;
spaceFreq = 2100.f;
}
}
else if(ModemConfig.modem == MODEM_300)
{
demodCount = 1;
N = N300;
baudRate = 300.f;
markFreq = 1600.f;
markFreq = 1800.f;
demodState[0].pllStep = PLL300_STEP;
demodState[0].pllLockedAdjust = PLL300_LOCKED_TUNE;
demodState[0].pllNotLockedAdjust = PLL300_NOT_LOCKED_TUNE;
demodState[0].dcdMax = DCD300_MAXPULSE;
demodState[0].dcdThres = DCD300_THRES;
demodState[0].dcdInc = DCD300_INC;
demodState[0].dcdDec = DCD300_DEC;
demodState[0].dcdAdjust = DCD300_PLLTUNE;
demodState[0].prefilter = PREFILTER_FLAT;
demodState[0].bpf.coeffs = bpf300;
demodState[0].bpf.taps = sizeof(bpf300) / sizeof(*bpf300);
demodState[0].bpf.gainShift = 16;
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
@ -647,19 +811,14 @@ void ModemInit(void)
TIM2->ARR = 103; //4MHz / 104 =~38400 Hz (4*9600 Hz for 4x oversampling)
TIM2->CR1 |= TIM_CR1_CEN; //enable timer
markFreq = 4000000 / (DAC_SINE_SIZE * (uint32_t)MODEM_MARK_FREQUENCY) - 1; //set mark frequency
spaceFreq = 4000000 / (DAC_SINE_SIZE * (uint32_t)MODEM_SPACE_FREQUENCY) - 1; //set space frequency
baudRate = 1000000 / (uint32_t)MODEM_BAUDRATE - 1; //set baudrate
for(uint8_t i = 0; i < N; i++) //calculate correlator coefficients
{
coeffLoI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)N * MODEM_MARK_FREQUENCY / MODEM_BAUDRATE);
coeffLoQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)N * MODEM_MARK_FREQUENCY / MODEM_BAUDRATE);
coeffHiI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)N * MODEM_SPACE_FREQUENCY / MODEM_BAUDRATE);
coeffHiQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)N * MODEM_SPACE_FREQUENCY / MODEM_BAUDRATE);
coeffLoI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)N * markFreq / baudRate);
coeffLoQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)N * markFreq / baudRate);
coeffHiI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)N * spaceFreq / baudRate);
coeffHiQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)N * spaceFreq / baudRate);
}
for(uint8_t i = 0; i < DAC_SINE_SIZE; i++) //calculate DAC sine samples
{
if(ModemConfig.usePWM)
@ -668,17 +827,6 @@ void ModemInit(void)
dacSine[i] = ((7.f * sinf(2.f * 3.1416f * (float)i / (float)DAC_SINE_SIZE)) + 8.f);
}
if(ModemConfig.flatAudioIn) //when used with flat audio input, use deemphasis and flat modems
{
demodState[0].emphasis = EMPHASIS_NONE;
demodState[1].emphasis = DEEMPHASIS;
}
else //when used with normal (filtered) audio input, use flat and preemphasis modems
{
demodState[0].emphasis = EMPHASIS_NONE;
demodState[1].emphasis = PREEMPHASIS;
}
if(ModemConfig.usePWM)
{
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //configure timer
@ -699,11 +847,3 @@ void ModemInit(void)
}
}
/**
* @}
*/

+ 6
- 8
Src/main.c View File

@ -127,24 +127,22 @@ static void handleFrame(void)
TermSendToAll(MODE_MONITOR, (uint8_t*)"(AX.25) Frame received [", 0); //show which modem received the frame: [FP] (flat and preemphasized), [FD] (flat and deemphasized - in flat audio input mode)
//[F_] (only flat), [_P] (only preemphasized) or [_D] (only deemphasized - in flat audio input mode)
for(uint8_t i = 0; i < MODEM_DEMODULATOR_COUNT; i++)
for(uint8_t i = 0; i < ModemGetDemodulatorCount(); i++)
{
if(modemBitmap & (1 << i))
{
enum ModemEmphasis m = ModemGetFilterType(i);
enum ModemPrefilter m = ModemGetFilterType(i);
switch(m)
{
case PREEMPHASIS:
case PREFILTER_PREEMPHASIS:
TermSendToAll(MODE_MONITOR, (uint8_t*)"P", 1);
break;
case DEEMPHASIS:
case PREFILTER_DEEMPHASIS:
TermSendToAll(MODE_MONITOR, (uint8_t*)"D", 1);
break;
case EMPHASIS_NONE:
TermSendToAll(MODE_MONITOR, (uint8_t*)"F", 1);
break;
case PREFILTER_FLAT:
default:
TermSendToAll(MODE_MONITOR, (uint8_t*)"*", 1);
TermSendToAll(MODE_MONITOR, (uint8_t*)"F", 1);
break;
}
}


Loading…
Cancel
Save