Вот такой был код (частота выборки 31кГц, оказывается):
uint8_t FSKdemod(int16_t FilterSample) {
//#define FreqTop 37 //Freqency counter high saturation value
//#define FreqBot 27 //Freqency counter low saturation value
#define FreqHi 34 //High freqency (space) detection threshold
#define FreqLo 30 //Low freqency (mark) detection threshold
static struct {
unsigned PrevSamp : 1; //Previous sample value, 1 means negative
unsigned NewBit : 1; //Next transition bit
unsigned Out : 1; //Output state
} FSKstate = {0};
static int Frequency = 32; //Start from nominal center frequency
static uint16_t SlideBuff[4] = {0b1010101010101010}; //Sliding average 64
//bit buffer. Center frequency (32 transitions) initially.
static uint8_t Iteration = 0; //Iteration counter for absolute freq. update
static uint8_t TransCnt = 0; //Bit counter for absolute frequency update
//Check for the transition and update NewBit value as a result
if (FilterSample & (1 << 15)) { //Check current sample sign
if (FSKstate.PrevSamp) { //When sample is negative as previous
FSKstate.NewBit = 0; //None transition detected
} else {
FSKstate.NewBit = 1; //The transition detected
}
FSKstate.PrevSamp = 1; //Update for next sample comparison
} else {
if (FSKstate.PrevSamp) { //When sample is positive but previous negative
FSKstate.NewBit = 1; //The transition detected
} else {
FSKstate.NewBit = 0; //None transition detected
}
FSKstate.PrevSamp = 0; //Update for next sample comparison
}
//Update frequency value, slide buffer and redundant slide buffer bit counter
//Update instant frequency and transition counter by new value
if (FSKstate.NewBit) {
TransCnt++; //Account transitions for absolute frequency value
}
//Update instant frequency
//Check slide buffer transition bit to remove against new arriving bit
if (!(SlideBuff[3]&(1 << 15))&&(FSKstate.NewBit)) {
Frequency++; //Increase frequency if steady bit removed but transition
//arrived
}
if ((SlideBuff[3]&(1 << 15))&&(!FSKstate.NewBit)) {
Frequency--; //Decrease frequency value if a transition removed
//but not arrived
}
//Update slide buffer. Shift left with carry
if (SlideBuff[2]&(1 << 15)) { //Check for third to fourth word carry
SlideBuff[3] = (SlideBuff[3] << 1) | 1; //Carry 3rd word MSB to 4th LSB
} else {
SlideBuff[3] = (SlideBuff[3] << 1); //None carry needed. Just shift
}
if (SlideBuff[1]&(1 << 15)) { //Check for second to third word carry
SlideBuff[2] = (SlideBuff[2] << 1) | 1; //Carry 2nd word MSB to 3rd LSB
} else {
SlideBuff[2] = (SlideBuff[2] << 1); //None carry needed. Just shift
}
if (SlideBuff[0]&(1 << 15)) { //Check for first to second word carry
SlideBuff[1] = (SlideBuff[1] << 1) | 1; //Carry 1th word MSB to 2nd LSB
} else {
SlideBuff[1] = (SlideBuff[1] << 1); //None carry needed. Just shift
}
if (FSKstate.NewBit) {
SlideBuff[0] = (SlideBuff[0] << 1) | 1; //Put new value into first LSB
} else {
SlideBuff[0] = (SlideBuff[0] << 1); //Nothing to insert. Just shift
}
//Update frequency value by robust transition counter result to avoid
//frequency error accumulation
if (!(Iteration++&0b111111)) { //Update once per 64 iterations
Frequency = TransCnt; //Slide buffer transitions number is frequency
TransCnt = 0; //Clear counter for new count
}
if (FSKstate.Out) { //Apply thresholds depending on the last state
if (Frequency <= FreqLo) { //Check for low threshold
FSKstate.Out = 0;
}
} else {
if (Frequency >= FreqHi) { //Check for high threshold
FSKstate.Out = 1;
}
}
return (FSKstate.Out);
//return (Frequency | (FSKstate.Out << 14));
}
Полный код проекта, с фильтрами, декодером и выводом результата на печать, прилагаю. 9 лет лежал без движения. Но это только декодер.
FSK_serial_20_CRC_print.zip
-
- Во вложении - генератор для среды CRAN-R (на Си-подобном языке) и файлы с образцами модулированных аудио-сигналов: Nikolay_Po(2 знак., Сегодня, 08:42, ссылка, ссылка)