Experiment with FSK, separate BPSK

This commit is contained in:
Jan Hamal Dvořák 2024-02-25 18:55:57 +01:00
parent 437b23e68c
commit b3422c5674

View file

@ -59,6 +59,9 @@ static uint32_t lo_sin[LO_WORDS] __attribute__((__aligned__(LO_WORDS * 4)));
static uint32_t rx_cos[RX_WORDS] __attribute__((__aligned__(RX_WORDS * 4))); static uint32_t rx_cos[RX_WORDS] __attribute__((__aligned__(RX_WORDS * 4)));
static uint32_t rx_sin[RX_WORDS] __attribute__((__aligned__(RX_WORDS * 4))); static uint32_t rx_sin[RX_WORDS] __attribute__((__aligned__(RX_WORDS * 4)));
#define SIN_PHASE (UINT_MAX / 4)
#define COS_PHASE (0)
static_assert(RX_WORDS > RX_BLOCK_LEN, "RX buffers too short for given decimation"); static_assert(RX_WORDS > RX_BLOCK_LEN, "RX buffers too short for given decimation");
/* rx -> cp -> cos -> sin -> pio_cos -> pio_sin -> rx ... */ /* rx -> cp -> cos -> sin -> pio_cos -> pio_sin -> rx ... */
@ -244,35 +247,51 @@ static void adder_init()
pio_sm_set_enabled(pio1, 3, true); pio_sm_set_enabled(pio1, 3, true);
} }
static float lo_freq_init(double req_freq) inline static float lo_round_freq(size_t bits, float req_freq)
{ {
const double step_hz = (double)CLK_SYS_HZ / (LO_WORDS * 32); const double step_hz = (double)CLK_SYS_HZ / bits;
double freq = round(req_freq / step_hz) * step_hz; return round(req_freq / step_hz) * step_hz;
}
static void lo_generate(uint32_t *buf, size_t len, double freq, unsigned phase)
{
unsigned step = ((double)UINT_MAX + 1.0) / (double)CLK_SYS_HZ * freq; unsigned step = ((double)UINT_MAX + 1.0) / (double)CLK_SYS_HZ * freq;
unsigned asin = UINT_MAX / 4; unsigned accum = phase;
unsigned acos = 0;
for (int i = 0; i < LO_WORDS; i++) { for (size_t i = 0; i < len; i++) {
unsigned bsin = 0, bcos = 0; unsigned bits = 0;
for (int j = 0; j < 32; j++) { for (int j = 0; j < 32; j++) {
bsin |= asin >> 31; bits |= accum >> 31;
bsin <<= 1; bits <<= 1;
asin += step; accum += step;
bcos |= acos >> 31;
bcos <<= 1;
acos += step;
} }
lo_sin[i] = bsin; buf[i] = bits;
lo_cos[i] = bcos;
} }
}
static float rx_lo_init(double req_freq)
{
float freq = lo_round_freq(LO_WORDS * 32, req_freq);
lo_generate(lo_cos, LO_WORDS, freq, COS_PHASE);
lo_generate(lo_sin, LO_WORDS, freq, SIN_PHASE);
return freq; return freq;
} }
static float tx_fsk_lo_init(float req_freq, float separation)
{
float hi = lo_round_freq(LO_WORDS * 32, req_freq + separation / 2);
float lo = lo_round_freq(LO_WORDS * 32, hi - separation);
lo_generate(lo_cos, LO_WORDS, hi, COS_PHASE);
lo_generate(lo_sin, LO_WORDS, lo, SIN_PHASE);
return (hi + lo) / 2.0f;
}
inline static __unused int cheap_atan2(int y, int x) inline static __unused int cheap_atan2(int y, int x)
{ {
if (y > 0) { if (y > 0) {
@ -428,7 +447,7 @@ static float rf_rx_start(int rx_pin, int bias_pin, float freq, int frac_num, int
bias_init(rx_pin, bias_pin); bias_init(rx_pin, bias_pin);
adder_init(); adder_init();
float actual = lo_freq_init(freq); float actual = rx_lo_init(freq);
dma_channel_start(dma_ch_rx); dma_channel_start(dma_ch_rx);
dma_channel_start(dma_ch_samp_trig); dma_channel_start(dma_ch_samp_trig);
@ -817,7 +836,8 @@ static void command(const char *cmd)
puts("bias I O - output negated I to O"); puts("bias I O - output negated I to O");
puts("rx N FREQ - receive on pin N"); puts("rx N FREQ - receive on pin N");
puts("brx N FREQ - receive on pin N, binary output"); puts("brx N FREQ - receive on pin N, binary output");
puts("tx N FREQ - transmit on pin N"); puts("bpsk N FREQ - transmit on pin N with BPSK");
puts("fsk N FREQ - transmit on pin N with FSK");
puts("sweep N F G S - sweep from F to G with given step"); puts("sweep N F G S - sweep from F to G with given step");
puts("noise N - transmit random noise"); puts("noise N - transmit random noise");
return; return;
@ -850,8 +870,8 @@ static void command(const char *cmd)
return; return;
} }
if (3 == sscanf(cmd, " tx %i %f %[\a]", &n, &f, tmp)) { if (3 == sscanf(cmd, " bpsk %i %f %[\a]", &n, &f, tmp)) {
float actual = lo_freq_init(f); float actual = rx_lo_init(f);
printf("Frequency: %.0f\n", actual); printf("Frequency: %.0f\n", actual);
rf_tx_start(n); rf_tx_start(n);
@ -869,10 +889,10 @@ static void command(const char *cmd)
phase = !phase; phase = !phase;
gpio_set_outover(n, phase); gpio_set_outover(n, phase);
} else if ('+' == c) { } else if ('+' == c) {
actual = lo_freq_init(actual + step_hz); actual = rx_lo_init(actual + step_hz);
printf("Frequency: %.0f\n", actual); printf("Frequency: %.0f\n", actual);
} else if ('-' == c) { } else if ('-' == c) {
actual = lo_freq_init(actual - step_hz); actual = rx_lo_init(actual - step_hz);
printf("Frequency: %.0f\n", actual); printf("Frequency: %.0f\n", actual);
} }
} }
@ -883,6 +903,44 @@ static void command(const char *cmd)
return; return;
} }
if (4 == sscanf(cmd, " fsk %i %f %f %[\a]", &n, &f, &g, tmp)) {
g = lo_round_freq(LO_WORDS * 32, g);
f = tx_fsk_lo_init(f, g);
printf("Frequency: %.0f +/- %.f\n", f, g / 2.0f);
rf_tx_start(n);
puts("Transmitting, press ENTER to stop.");
bool high = true;
const double step_hz = (double)CLK_SYS_HZ / (LO_WORDS * 32);
while (true) {
int c = getchar_timeout_us(10000);
if ('\r' == c) {
break;
} else if (' ' == c) {
high = !high;
if (high) {
dma_hw->ch[dma_ch_tx_cos].read_addr = (uint32_t)lo_cos;
} else {
dma_hw->ch[dma_ch_tx_cos].read_addr = (uint32_t)lo_sin;
}
} else if ('+' == c) {
f = tx_fsk_lo_init(f + step_hz, g);
printf("Frequency: %.0f +/- %.f\n", f, g / 2.0f);
} else if ('-' == c) {
f = tx_fsk_lo_init(f - step_hz, g);
printf("Frequency: %.0f +/- %.f\n", f, g / 2.0f);
}
}
rf_tx_stop();
puts("Done.");
return;
}
if (5 == sscanf(cmd, " sweep %i %f %f %i %[\a]", &n, &f, &g, &x, tmp)) { if (5 == sscanf(cmd, " sweep %i %f %f %i %[\a]", &n, &f, &g, &x, tmp)) {
const float step_hz = (float)CLK_SYS_HZ / (LO_WORDS * 32); const float step_hz = (float)CLK_SYS_HZ / (LO_WORDS * 32);
const float start = roundf(f / step_hz) * step_hz; const float start = roundf(f / step_hz) * step_hz;
@ -900,7 +958,7 @@ static void command(const char *cmd)
if ('\r' == c) if ('\r' == c)
break; break;
float actual = lo_freq_init(start + i * step_hz); float actual = rx_lo_init(start + i * step_hz);
printf("Frequency: %.0f\n", actual); printf("Frequency: %.0f\n", actual);
} }