bpsk: fix chunked operation

The cache was not behaving correctly at all.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-06-10 19:16:12 +08:00
parent 6941745fe9
commit 2674bdefe5
1 changed files with 117 additions and 106 deletions

View File

@ -37,8 +37,8 @@ struct bpsk_state
/// If there aren't enough samples to convert data from q15 /// If there aren't enough samples to convert data from q15
/// to f32, store them in here and return. /// to f32, store them in here and return.
demod_sample_t cached[SAMPLES_PER_PERIOD]; demod_sample_t cache[SAMPLES_PER_PERIOD];
uint32_t cached_capacity; uint32_t cache_capacity;
arm_fir_instance_f32 fir; arm_fir_instance_f32 fir;
float32_t fir_state[SAMPLES_PER_PERIOD + FIR_STAGES - 1]; float32_t fir_state[SAMPLES_PER_PERIOD + FIR_STAGES - 1];
@ -116,7 +116,7 @@ void bpsk_demod_init(void)
// Force a buffer refill for the first iteration // Force a buffer refill for the first iteration
bpsk_state.current_offset = SAMPLES_PER_PERIOD; bpsk_state.current_offset = SAMPLES_PER_PERIOD;
bpsk_state.cached_capacity = 0; bpsk_state.cache_capacity = 0;
arm_fir_init_f32(&bpsk_state.i_lpf, LPF_STAGES, lpf_coefficients, arm_fir_init_f32(&bpsk_state.i_lpf, LPF_STAGES, lpf_coefficients,
bpsk_state.i_lpf_state, SAMPLES_PER_PERIOD); bpsk_state.i_lpf_state, SAMPLES_PER_PERIOD);
@ -145,88 +145,88 @@ struct sample_wave sample_wave;
uint32_t saved_samples_ptr; uint32_t saved_samples_ptr;
#endif #endif
static FILE *output = NULL; // static FILE *output = NULL;
static void write_wav_stereo(int16_t *left, int16_t *right, unsigned int len, // static void write_wav_stereo(int16_t *left, int16_t *right, unsigned int len,
const char *name) // const char *name)
{ // {
if (!output) // if (!output)
{ // {
static uint8_t wav_header[44] = { // static uint8_t wav_header[44] = {
0x52, // 0x52,
0x49, // 0x49,
0x46, // 0x46,
0x46, // 0x46,
0x1c, // 0x1c,
0x12, // 0x12,
0x05, // 0x05,
0x00, // 0x00,
0x57, // 0x57,
0x41, // 0x41,
0x56, // 0x56,
0x45, // 0x45,
0x66, // 0x66,
0x6d, // 0x6d,
0x74, // 0x74,
0x20, // 0x20,
0x10, // 0x10,
0x00, // 0x00,
0x00, // 0x00,
0x00, // 0x00,
0x01, // 0x01,
0x00, // 0x00,
0x02, // stereo // 0x02, // stereo
0x00, // 0x00,
0x11, // 0x11,
0x2b, // 0x2b,
0x00, // 0x00,
0x00, // 0x00,
0x22, // 0x22,
0x56, // 0x56,
0x00, // 0x00,
0x00, // 0x00,
0x02, // 0x02,
0x00, // 0x00,
0x10, // 0x10,
0x00, // 0x00,
0x64, // 0x64,
0x61, // 0x61,
0x74, // 0x74,
0x61, // 0x61,
0xf8, // 0xf8,
0x11, // 0x11,
0x05, // 0x05,
0x00, // 0x00,
}; // };
output = fopen(name, "w+b"); // output = fopen(name, "w+b");
if (!output) // if (!output)
{ // {
perror("unable to open filtered file"); // perror("unable to open filtered file");
return; // return;
} // }
if (fwrite(wav_header, sizeof(wav_header), 1, output) <= 0) // if (fwrite(wav_header, sizeof(wav_header), 1, output) <= 0)
{ // {
perror("error"); // perror("error");
fclose(output); // fclose(output);
return; // return;
} // }
} // }
for (unsigned int i = 0; i < len; i++) // for (unsigned int i = 0; i < len; i++)
{ // {
if (fwrite(&(left[i]), 2, 1, output) != 1) // if (fwrite(&(left[i]), 2, 1, output) != 1)
{ // {
perror("error"); // perror("error");
fclose(output); // fclose(output);
return; // return;
} // }
if (fwrite(&(right[i]), 2, 1, output) != 1) // if (fwrite(&(right[i]), 2, 1, output) != 1)
{ // {
perror("error"); // perror("error");
fclose(output); // fclose(output);
return; // return;
} // }
} // }
} // }
static void bpsk_core(void) static void bpsk_core(void)
{ {
@ -277,11 +277,11 @@ static void bpsk_core(void)
arm_fir_f32(&bpsk_state.i_lpf, i_mult_samps, bpsk_state.i_lpf_samples, SAMPLES_PER_PERIOD); arm_fir_f32(&bpsk_state.i_lpf, i_mult_samps, bpsk_state.i_lpf_samples, SAMPLES_PER_PERIOD);
arm_fir_f32(&bpsk_state.q_lpf, q_mult_samps, q_lpf_samples, SAMPLES_PER_PERIOD); arm_fir_f32(&bpsk_state.q_lpf, q_mult_samps, q_lpf_samples, SAMPLES_PER_PERIOD);
int16_t i_loop[SAMPLES_PER_PERIOD]; // int16_t i_loop[SAMPLES_PER_PERIOD];
int16_t q_loop[SAMPLES_PER_PERIOD]; // int16_t q_loop[SAMPLES_PER_PERIOD];
arm_float_to_q15(bpsk_state.i_lpf_samples, i_loop, SAMPLES_PER_PERIOD); // arm_float_to_q15(bpsk_state.i_lpf_samples, i_loop, SAMPLES_PER_PERIOD);
arm_float_to_q15(q_lpf_samples, q_loop, SAMPLES_PER_PERIOD); // arm_float_to_q15(q_lpf_samples, q_loop, SAMPLES_PER_PERIOD);
write_wav_stereo(i_loop, q_loop, SAMPLES_PER_PERIOD, "quadrature_loop.wav"); // write_wav_stereo(i_loop, q_loop, SAMPLES_PER_PERIOD, "quadrature_loop.wav");
float32_t errorwindow[SAMPLES_PER_PERIOD]; float32_t errorwindow[SAMPLES_PER_PERIOD];
arm_mult_f32(bpsk_state.i_lpf_samples, q_lpf_samples, errorwindow, arm_mult_f32(bpsk_state.i_lpf_samples, q_lpf_samples, errorwindow,
@ -305,36 +305,45 @@ int bpsk_demod(int *bit, demod_sample_t *samples, uint32_t nb, uint32_t *process
bpsk_state.current_offset += 1; bpsk_state.current_offset += 1;
if (bpsk_state.current_offset >= SAMPLES_PER_PERIOD) if (bpsk_state.current_offset >= SAMPLES_PER_PERIOD)
{ {
bpsk_state.current_offset = 0; // If there aren't any bytes remaining to process, return.
if (nb == 0) {
return 0;
}
// If there's data in the cache buffer, use that as the source // If there's data in the cache buffer, use that as the source
// for data. // for data.
if (bpsk_state.cached_capacity > 0) else if (bpsk_state.cache_capacity > 0)
{ {
// If there won't be enough data to process, so copy the // If there won't be enough data to process, copy the
// remainder to the cache and return. // remainder to the cache and return.
if (bpsk_state.cached_capacity + nb < SAMPLES_PER_PERIOD) if (bpsk_state.cache_capacity + nb < SAMPLES_PER_PERIOD)
{ {
memcpy(bpsk_state.cached + bpsk_state.cached_capacity, printf("Buffer not big enough, stashing in cache\n");
memcpy(&bpsk_state.cache[bpsk_state.cache_capacity],
samples, nb * sizeof(uint16_t)); samples, nb * sizeof(uint16_t));
bpsk_state.cached_capacity += nb; bpsk_state.cache_capacity += nb;
*processed_samples += nb; *processed_samples += nb;
fclose(output); // fclose(output);
return 0; return 0;
} }
uint32_t samples_to_take = (SAMPLES_PER_PERIOD - bpsk_state.cached_capacity); // There is enough data if we combine the cache with fresh data,
memcpy(bpsk_state.cached + bpsk_state.cached_capacity, samples, // so determine how many samples to take.
uint32_t samples_to_take = (SAMPLES_PER_PERIOD - bpsk_state.cache_capacity);
// printf("Pulling %d samples from cache and adding %d samples from pool of %d\n",
// bpsk_state.cache_capacity,
// samples_to_take, nb);
memcpy(&bpsk_state.cache[bpsk_state.cache_capacity], samples,
samples_to_take * sizeof(uint16_t)); samples_to_take * sizeof(uint16_t));
// There is enough data, so convert it to f32 // There is enough data, so convert it to f32 and clear the cache
arm_q15_to_float(bpsk_state.cached, bpsk_state.current, arm_q15_to_float(bpsk_state.cache, bpsk_state.current,
SAMPLES_PER_PERIOD); SAMPLES_PER_PERIOD);
bpsk_state.cached_capacity = 0; bpsk_state.cache_capacity = 0;
nb -= samples_to_take; nb -= samples_to_take;
samples += samples_to_take; samples += samples_to_take;
(*processed_samples) += SAMPLES_PER_PERIOD; (*processed_samples) += samples_to_take;
} }
// Otherwise, the cache is empty, so operate directly on sample data // Otherwise, the cache is empty, so operate directly on sample data
else else
@ -343,10 +352,10 @@ int bpsk_demod(int *bit, demod_sample_t *samples, uint32_t nb, uint32_t *process
// cache. // cache.
if (nb < SAMPLES_PER_PERIOD) if (nb < SAMPLES_PER_PERIOD)
{ {
memcpy(bpsk_state.cached, samples, nb * sizeof(uint16_t)); // printf("Only %d samples left, stashing in cache\n", nb);
bpsk_state.cached_capacity = nb; memcpy(bpsk_state.cache, samples, nb * sizeof(uint16_t));
bpsk_state.cache_capacity = nb;
(*processed_samples) += nb; (*processed_samples) += nb;
fclose(output);
return 0; return 0;
} }
@ -358,8 +367,10 @@ int bpsk_demod(int *bit, demod_sample_t *samples, uint32_t nb, uint32_t *process
} }
bpsk_core(); bpsk_core();
bpsk_state.current_offset = 0;
} }
// If the PLL crosses the 50% threshold, indicate a new bit. // If the PLL crosses the 50% threshold, indicate a new bit.
if (bpsk_state.bit_pll < 0.5 && (bpsk_state.bit_pll + bpsk_state.pll_incr) >= 0.5) if (bpsk_state.bit_pll < 0.5 && (bpsk_state.bit_pll + bpsk_state.pll_incr) >= 0.5)
{ {