Variant for superhet + amplifier
This commit is contained in:
parent
1fe4633601
commit
36ca06f31b
|
@ -37,7 +37,7 @@ blocks:
|
||||||
id: variable
|
id: variable
|
||||||
parameters:
|
parameters:
|
||||||
comment: ''
|
comment: ''
|
||||||
value: '88_200_000'
|
value: '94_600_000'
|
||||||
states:
|
states:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
|
@ -70,7 +70,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [640, 336.0]
|
coordinate: [832, 336.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: analog_wfm_rcv_pll_0
|
- name: analog_wfm_rcv_pll_0
|
||||||
|
@ -88,7 +88,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [640, 440.0]
|
coordinate: [832, 440.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: audio_sink_0
|
- name: audio_sink_0
|
||||||
|
@ -105,7 +105,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [928, 448.0]
|
coordinate: [1120, 448.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: blocks_message_debug_0
|
- name: blocks_message_debug_0
|
||||||
|
@ -120,7 +120,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [928, 32.0]
|
coordinate: [1120, 32.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: blocks_probe_rate_0
|
- name: blocks_probe_rate_0
|
||||||
|
@ -140,7 +140,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [640, 40.0]
|
coordinate: [832, 40.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: low_pass_filter_0
|
- name: low_pass_filter_0
|
||||||
|
@ -164,7 +164,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [928, 284.0]
|
coordinate: [1120, 284.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: enabled
|
state: enabled
|
||||||
- name: osmosdr_source_0
|
- name: osmosdr_source_0
|
||||||
|
@ -374,7 +374,7 @@ blocks:
|
||||||
freq7: 100e6
|
freq7: 100e6
|
||||||
freq8: 100e6
|
freq8: 100e6
|
||||||
freq9: 100e6
|
freq9: 100e6
|
||||||
gain0: '30'
|
gain0: '0'
|
||||||
gain1: '10'
|
gain1: '10'
|
||||||
gain10: '10'
|
gain10: '10'
|
||||||
gain11: '10'
|
gain11: '10'
|
||||||
|
@ -618,7 +618,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [640, 232.0]
|
coordinate: [832, 232.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: qtgui_time_sink_x_0_0
|
- name: qtgui_time_sink_x_0_0
|
||||||
|
@ -676,7 +676,7 @@ blocks:
|
||||||
marker9: '-1'
|
marker9: '-1'
|
||||||
name: '"FM Demodulation"'
|
name: '"FM Demodulation"'
|
||||||
nconnections: '1'
|
nconnections: '1'
|
||||||
size: '512'
|
size: '128'
|
||||||
srate: samp_rate // (2 ** 3)
|
srate: samp_rate // (2 ** 3)
|
||||||
stemplot: 'False'
|
stemplot: 'False'
|
||||||
style1: '1'
|
style1: '1'
|
||||||
|
@ -715,7 +715,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [1128, 312.0]
|
coordinate: [1320, 312.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: qtgui_waterfall_sink_x_0_0
|
- name: qtgui_waterfall_sink_x_0_0
|
||||||
|
@ -776,7 +776,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [640, 128.0]
|
coordinate: [832, 128.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
- name: qtgui_waterfall_sink_x_0_0_0_0
|
- name: qtgui_waterfall_sink_x_0_0_0_0
|
||||||
|
@ -837,7 +837,7 @@ blocks:
|
||||||
bus_sink: false
|
bus_sink: false
|
||||||
bus_source: false
|
bus_source: false
|
||||||
bus_structure: null
|
bus_structure: null
|
||||||
coordinate: [928, 184.0]
|
coordinate: [1120, 184.0]
|
||||||
rotation: 0
|
rotation: 0
|
||||||
state: true
|
state: true
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ target_link_libraries(
|
||||||
pico_stdlib
|
pico_stdlib
|
||||||
pico_util
|
pico_util
|
||||||
hardware_divider
|
hardware_divider
|
||||||
|
hardware_adc
|
||||||
hardware_dma
|
hardware_dma
|
||||||
hardware_pio
|
hardware_pio
|
||||||
hardware_pwm
|
hardware_pwm
|
||||||
|
|
405
src/main.c
405
src/main.c
|
@ -4,6 +4,7 @@
|
||||||
#include <pico/util/queue.h>
|
#include <pico/util/queue.h>
|
||||||
|
|
||||||
#include <hardware/clocks.h>
|
#include <hardware/clocks.h>
|
||||||
|
#include <hardware/adc.h>
|
||||||
#include <hardware/dma.h>
|
#include <hardware/dma.h>
|
||||||
#include <hardware/gpio.h>
|
#include <hardware/gpio.h>
|
||||||
#include <hardware/pll.h>
|
#include <hardware/pll.h>
|
||||||
|
@ -28,20 +29,19 @@
|
||||||
#define INIT_FREQ 94600000
|
#define INIT_FREQ 94600000
|
||||||
#define INIT_GAIN 127
|
#define INIT_GAIN 127
|
||||||
|
|
||||||
#define LO_PIN 9
|
#define LO_PIN 21
|
||||||
#define RX_PIN 13
|
#define RX_PIN 26
|
||||||
#define FB_PIN 5
|
|
||||||
#define PSU_PIN 23
|
#define PSU_PIN 23
|
||||||
|
|
||||||
#define PIO pio1
|
#define PIO pio1
|
||||||
#define SM_LO 0
|
#define SM_LO 0
|
||||||
#define SM_FB 1
|
|
||||||
#define SM_RX 2
|
|
||||||
#define SM_AD 3
|
|
||||||
|
|
||||||
#define IQ_SAMPLES 32
|
#define IQ_SAMPLES 32
|
||||||
#define IQ_BLOCK_LEN (2 * IQ_SAMPLES)
|
#define IQ_BLOCK_LEN (2 * IQ_SAMPLES)
|
||||||
#define IQ_QUEUE_LEN 8
|
#define IQ_QUEUE_LEN 4
|
||||||
|
|
||||||
|
#define ADC_RATE (2 * MHZ)
|
||||||
|
#define DECIMATE 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: Must have 256 phases with 256 bytes each.
|
* NOTE: Must have 256 phases with 256 bytes each.
|
||||||
|
@ -61,39 +61,19 @@ static uint32_t lo_phase[LO_NUM_PHASES][LO_PHASE_WORDS]
|
||||||
|
|
||||||
static uint32_t nco_addr = (uint32_t)lo_phase;
|
static uint32_t nco_addr = (uint32_t)lo_phase;
|
||||||
|
|
||||||
#define DECIMATE 16
|
|
||||||
#define RX_BITS_DEPTH 8
|
|
||||||
#define RX_WORDS (1 << (RX_BITS_DEPTH - 2))
|
|
||||||
#define RX_STRIDE (2 * DECIMATE)
|
|
||||||
|
|
||||||
static_assert(RX_WORDS >= 2 * RX_STRIDE, "RX_WORDS >= 2 * RX_STRIDE");
|
|
||||||
|
|
||||||
static uint32_t rx_cos[RX_WORDS] __attribute__((__aligned__(1 << RX_BITS_DEPTH)));
|
|
||||||
|
|
||||||
#define NUM_GAINS 29
|
#define NUM_GAINS 29
|
||||||
static int gains[NUM_GAINS] = { 0, 9, 14, 27, 37, 77, 87, 125, 144, 157,
|
static int gains[NUM_GAINS] = { 0, 9, 14, 27, 37, 77, 87, 125, 144, 157,
|
||||||
166, 197, 207, 229, 254, 280, 297, 328, 338, 364,
|
166, 197, 207, 229, 254, 280, 297, 328, 338, 364,
|
||||||
372, 386, 402, 421, 434, 439, 445, 480, 496 };
|
372, 386, 402, 421, 434, 439, 445, 480, 496 };
|
||||||
static int sample_rate = INIT_SAMPLE_RATE;
|
static int sample_rate = INIT_SAMPLE_RATE;
|
||||||
static int max_amplitude = CLK_SYS_HZ / INIT_SAMPLE_RATE / 2;
|
|
||||||
static int max_amplitude_mul = 65536 / (CLK_SYS_HZ / INIT_SAMPLE_RATE / 2);
|
|
||||||
static int gain = INIT_GAIN;
|
static int gain = INIT_GAIN;
|
||||||
static int frequency = INIT_FREQ;
|
static int frequency = INIT_FREQ;
|
||||||
|
|
||||||
static int dma_ch_rx1 = -1;
|
|
||||||
static int dma_ch_rx2 = -1;
|
|
||||||
|
|
||||||
static int dma_ch_nco1 = -1;
|
static int dma_ch_nco1 = -1;
|
||||||
static int dma_ch_nco2 = -1;
|
static int dma_ch_nco2 = -1;
|
||||||
static int dma_ch_nco3 = -1;
|
static int dma_ch_nco3 = -1;
|
||||||
static int dma_ch_mix = -1;
|
static int dma_ch_mix = -1;
|
||||||
|
|
||||||
static int dma_ch_samp_cos = -1;
|
|
||||||
|
|
||||||
static int dma_t_samp = -1;
|
|
||||||
|
|
||||||
static int dma_ch_in_cos = -1;
|
|
||||||
|
|
||||||
static queue_t iq_queue;
|
static queue_t iq_queue;
|
||||||
static uint8_t iq_queue_buffer[IQ_QUEUE_LEN][IQ_BLOCK_LEN];
|
static uint8_t iq_queue_buffer[IQ_QUEUE_LEN][IQ_BLOCK_LEN];
|
||||||
static size_t iq_queue_pos = 0;
|
static size_t iq_queue_pos = 0;
|
||||||
|
@ -101,9 +81,6 @@ static size_t iq_queue_pos = 0;
|
||||||
static uint32_t rnd = 0;
|
static uint32_t rnd = 0;
|
||||||
|
|
||||||
static int origin_lo = -1;
|
static int origin_lo = -1;
|
||||||
static int origin_rx = -1;
|
|
||||||
static int origin_fb = -1;
|
|
||||||
static int origin_ad = 0;
|
|
||||||
|
|
||||||
inline static __unused uint32_t rnd_next()
|
inline static __unused uint32_t rnd_next()
|
||||||
{
|
{
|
||||||
|
@ -124,8 +101,8 @@ static void init_lo()
|
||||||
gpio_disable_pulls(LO_PIN);
|
gpio_disable_pulls(LO_PIN);
|
||||||
pio_gpio_init(PIO, LO_PIN);
|
pio_gpio_init(PIO, LO_PIN);
|
||||||
|
|
||||||
gpio_set_drive_strength(LO_PIN, GPIO_DRIVE_STRENGTH_12MA);
|
gpio_set_drive_strength(LO_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||||
gpio_set_slew_rate(LO_PIN, GPIO_SLEW_RATE_FAST);
|
gpio_set_slew_rate(LO_PIN, GPIO_SLEW_RATE_SLOW);
|
||||||
|
|
||||||
const uint16_t insn[] = {
|
const uint16_t insn[] = {
|
||||||
pio_encode_out(pio_pindirs, 1),
|
pio_encode_out(pio_pindirs, 1),
|
||||||
|
@ -156,136 +133,6 @@ static void init_lo()
|
||||||
pio_sm_exec_wait_blocking(PIO, SM_LO, pio_encode_set(pio_pins, 0));
|
pio_sm_exec_wait_blocking(PIO, SM_LO, pio_encode_set(pio_pins, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_fb()
|
|
||||||
{
|
|
||||||
gpio_disable_pulls(FB_PIN);
|
|
||||||
pio_gpio_init(PIO, FB_PIN);
|
|
||||||
|
|
||||||
// NOTE: Not sure if this is ideal.
|
|
||||||
hw_set_bits(&PIO->input_sync_bypass, 1u << RX_PIN);
|
|
||||||
|
|
||||||
gpio_set_input_hysteresis_enabled(RX_PIN, false);
|
|
||||||
gpio_set_drive_strength(FB_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
|
||||||
gpio_set_slew_rate(FB_PIN, GPIO_SLEW_RATE_SLOW);
|
|
||||||
|
|
||||||
const uint16_t insn[] = {
|
|
||||||
pio_encode_mov_not(pio_pins, pio_pins) | pio_encode_sideset(1, 1) |
|
|
||||||
pio_encode_delay(0),
|
|
||||||
//pio_encode_nop() | pio_encode_sideset(1, 0) | pio_encode_delay(0),
|
|
||||||
};
|
|
||||||
|
|
||||||
pio_program_t prog = {
|
|
||||||
.instructions = insn,
|
|
||||||
.length = sizeof(insn) / sizeof(*insn),
|
|
||||||
.origin = origin_fb,
|
|
||||||
};
|
|
||||||
|
|
||||||
pio_sm_restart(PIO, SM_FB);
|
|
||||||
pio_sm_clear_fifos(PIO, SM_FB);
|
|
||||||
|
|
||||||
if (pio_can_add_program(PIO, &prog))
|
|
||||||
origin_fb = pio_add_program(PIO, &prog);
|
|
||||||
|
|
||||||
pio_sm_config pc = pio_get_default_sm_config();
|
|
||||||
sm_config_set_sideset(&pc, 1, false, true);
|
|
||||||
sm_config_set_in_pins(&pc, RX_PIN);
|
|
||||||
sm_config_set_out_pins(&pc, FB_PIN, 1);
|
|
||||||
sm_config_set_set_pins(&pc, FB_PIN, 1);
|
|
||||||
sm_config_set_sideset_pins(&pc, FB_PIN);
|
|
||||||
sm_config_set_wrap(&pc, origin_fb, origin_fb + prog.length - 1);
|
|
||||||
sm_config_set_clkdiv_int_frac(&pc, 1, 0);
|
|
||||||
pio_sm_init(PIO, SM_FB, origin_fb, &pc);
|
|
||||||
|
|
||||||
pio_sm_set_consecutive_pindirs(PIO, SM_FB, FB_PIN, 1, GPIO_OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_rx()
|
|
||||||
{
|
|
||||||
gpio_disable_pulls(RX_PIN);
|
|
||||||
pio_gpio_init(PIO, RX_PIN);
|
|
||||||
|
|
||||||
const uint16_t insn[] = {
|
|
||||||
pio_encode_in(pio_pins, 1) | pio_encode_delay(0),
|
|
||||||
};
|
|
||||||
|
|
||||||
pio_program_t prog = {
|
|
||||||
.instructions = insn,
|
|
||||||
.length = sizeof(insn) / sizeof(*insn),
|
|
||||||
.origin = origin_rx,
|
|
||||||
};
|
|
||||||
|
|
||||||
pio_sm_restart(PIO, SM_RX);
|
|
||||||
pio_sm_clear_fifos(PIO, SM_RX);
|
|
||||||
|
|
||||||
if (pio_can_add_program(PIO, &prog))
|
|
||||||
origin_rx = pio_add_program(PIO, &prog);
|
|
||||||
|
|
||||||
pio_sm_config pc = pio_get_default_sm_config();
|
|
||||||
sm_config_set_in_pins(&pc, RX_PIN);
|
|
||||||
sm_config_set_wrap(&pc, origin_rx, origin_rx + prog.length - 1);
|
|
||||||
sm_config_set_clkdiv_int_frac(&pc, 1, 0);
|
|
||||||
sm_config_set_fifo_join(&pc, PIO_FIFO_JOIN_RX);
|
|
||||||
sm_config_set_in_shift(&pc, false, true, 32);
|
|
||||||
pio_sm_init(PIO, SM_RX, origin_rx, &pc);
|
|
||||||
|
|
||||||
pio_sm_set_consecutive_pindirs(PIO, SM_RX, RX_PIN, 1, GPIO_IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint32_t samp_insn = 16;
|
|
||||||
|
|
||||||
static void init_ad()
|
|
||||||
{
|
|
||||||
const uint16_t insn[] = {
|
|
||||||
pio_encode_out(pio_pc, 4), // 0000 +0
|
|
||||||
pio_encode_jmp_x_dec(0), // 0001 +1
|
|
||||||
pio_encode_jmp_x_dec(0), // 0010 +1
|
|
||||||
pio_encode_jmp_y_dec(0), // 0011 +2
|
|
||||||
pio_encode_jmp_x_dec(0), // 0100 +1
|
|
||||||
pio_encode_jmp_y_dec(0), // 0101 +2
|
|
||||||
pio_encode_jmp_y_dec(0), // 0110 +2
|
|
||||||
pio_encode_jmp_y_dec(1), // 0111 +2 +1
|
|
||||||
pio_encode_jmp_x_dec(0), // 1000 +1
|
|
||||||
pio_encode_jmp_y_dec(0), // 1001 +2
|
|
||||||
pio_encode_jmp_y_dec(0), // 1010 +2
|
|
||||||
pio_encode_jmp_y_dec(1), // 1011 +2 +1
|
|
||||||
pio_encode_jmp_y_dec(0), // 1100 +2
|
|
||||||
pio_encode_jmp_y_dec(1), // 1101 +2 +1
|
|
||||||
pio_encode_jmp_y_dec(1), // 1110 +2 +1
|
|
||||||
pio_encode_jmp_y_dec(3), // 1111 +2 +2
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Should wrap here.
|
|
||||||
* Jump to this portion must be inserted from the outside.
|
|
||||||
*/
|
|
||||||
pio_encode_in(pio_y, 32),
|
|
||||||
pio_encode_in(pio_x, 32),
|
|
||||||
pio_encode_set(pio_y, 0),
|
|
||||||
pio_encode_set(pio_x, 0),
|
|
||||||
pio_encode_jmp_y_dec(21),
|
|
||||||
pio_encode_jmp_x_dec(22),
|
|
||||||
pio_encode_out(pio_pc, 4),
|
|
||||||
};
|
|
||||||
|
|
||||||
pio_program_t prog = {
|
|
||||||
.instructions = insn,
|
|
||||||
.length = sizeof(insn) / sizeof(*insn),
|
|
||||||
.origin = origin_ad,
|
|
||||||
};
|
|
||||||
|
|
||||||
pio_sm_restart(PIO, SM_AD);
|
|
||||||
pio_sm_clear_fifos(PIO, SM_AD);
|
|
||||||
|
|
||||||
if (pio_can_add_program(PIO, &prog))
|
|
||||||
pio_add_program(PIO, &prog);
|
|
||||||
|
|
||||||
pio_sm_config pc = pio_get_default_sm_config();
|
|
||||||
sm_config_set_wrap(&pc, origin_ad, origin_ad + 15);
|
|
||||||
sm_config_set_clkdiv_int_frac(&pc, 1, 0);
|
|
||||||
sm_config_set_in_shift(&pc, false, true, 32);
|
|
||||||
sm_config_set_out_shift(&pc, false, true, 32);
|
|
||||||
pio_sm_init(PIO, SM_AD, origin_ad, &pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lo_generate_phase(uint32_t *buf, size_t len, uint32_t step, uint32_t phase)
|
static void lo_generate_phase(uint32_t *buf, size_t len, uint32_t step, uint32_t phase)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
@ -313,37 +160,13 @@ static void rx_lo_init(double freq)
|
||||||
|
|
||||||
static void rf_rx_start()
|
static void rf_rx_start()
|
||||||
{
|
{
|
||||||
dma_ch_rx1 = dma_claim_unused_channel(true);
|
|
||||||
dma_ch_rx2 = dma_claim_unused_channel(true);
|
|
||||||
|
|
||||||
dma_ch_nco1 = dma_claim_unused_channel(true);
|
dma_ch_nco1 = dma_claim_unused_channel(true);
|
||||||
dma_ch_nco2 = dma_claim_unused_channel(true);
|
dma_ch_nco2 = dma_claim_unused_channel(true);
|
||||||
dma_ch_nco3 = dma_claim_unused_channel(true);
|
dma_ch_nco3 = dma_claim_unused_channel(true);
|
||||||
dma_ch_mix = dma_claim_unused_channel(true);
|
dma_ch_mix = dma_claim_unused_channel(true);
|
||||||
|
|
||||||
dma_ch_samp_cos = dma_claim_unused_channel(true);
|
|
||||||
|
|
||||||
dma_channel_config dma_conf;
|
dma_channel_config dma_conf;
|
||||||
|
|
||||||
/* Copy PDM bitstream into decimator. */
|
|
||||||
dma_conf = dma_channel_get_default_config(dma_ch_rx1);
|
|
||||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
|
||||||
channel_config_set_read_increment(&dma_conf, false);
|
|
||||||
channel_config_set_write_increment(&dma_conf, false);
|
|
||||||
channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, SM_RX, GPIO_IN));
|
|
||||||
channel_config_set_chain_to(&dma_conf, dma_ch_rx2);
|
|
||||||
dma_channel_configure(dma_ch_rx1, &dma_conf, &PIO->txf[SM_AD], &PIO->rxf[SM_RX], UINT_MAX,
|
|
||||||
false);
|
|
||||||
|
|
||||||
dma_conf = dma_channel_get_default_config(dma_ch_rx2);
|
|
||||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
|
||||||
channel_config_set_read_increment(&dma_conf, false);
|
|
||||||
channel_config_set_write_increment(&dma_conf, false);
|
|
||||||
channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, SM_RX, GPIO_IN));
|
|
||||||
channel_config_set_chain_to(&dma_conf, dma_ch_rx1);
|
|
||||||
dma_channel_configure(dma_ch_rx2, &dma_conf, &PIO->txf[SM_AD], &PIO->rxf[SM_RX], UINT_MAX,
|
|
||||||
false);
|
|
||||||
|
|
||||||
/* Step the NCO. */
|
/* Step the NCO. */
|
||||||
dma_conf = dma_channel_get_default_config(dma_ch_nco1);
|
dma_conf = dma_channel_get_default_config(dma_ch_nco1);
|
||||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
||||||
|
@ -382,191 +205,105 @@ static void rf_rx_start()
|
||||||
dma_channel_configure(dma_ch_mix, &dma_conf, &PIO->txf[SM_LO], lo_phase, LO_PHASE_WORDS,
|
dma_channel_configure(dma_ch_mix, &dma_conf, &PIO->txf[SM_LO], lo_phase, LO_PHASE_WORDS,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
/* Trigger accumulator values push. */
|
|
||||||
dma_conf = dma_channel_get_default_config(dma_ch_samp_cos);
|
|
||||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
|
||||||
channel_config_set_read_increment(&dma_conf, false);
|
|
||||||
channel_config_set_write_increment(&dma_conf, false);
|
|
||||||
channel_config_set_high_priority(&dma_conf, true);
|
|
||||||
channel_config_set_dreq(&dma_conf, dma_get_timer_dreq(dma_t_samp));
|
|
||||||
dma_channel_configure(dma_ch_samp_cos, &dma_conf, &PIO->sm[SM_AD].instr, &samp_insn,
|
|
||||||
UINT_MAX, false);
|
|
||||||
|
|
||||||
init_ad();
|
|
||||||
init_lo();
|
init_lo();
|
||||||
init_fb();
|
|
||||||
init_rx();
|
|
||||||
|
|
||||||
dma_channel_start(dma_ch_rx1);
|
|
||||||
dma_channel_start(dma_ch_nco1);
|
dma_channel_start(dma_ch_nco1);
|
||||||
dma_channel_start(dma_ch_samp_cos);
|
|
||||||
|
|
||||||
pio_set_sm_mask_enabled(PIO, 0x0f, true);
|
pio_sm_set_enabled(PIO, SM_LO, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rf_rx_stop(void)
|
static void rf_rx_stop(void)
|
||||||
{
|
{
|
||||||
pio_set_sm_mask_enabled(PIO, 0x0f, false);
|
pio_sm_set_enabled(PIO, SM_LO, false);
|
||||||
|
|
||||||
sleep_us(10);
|
sleep_us(10);
|
||||||
|
|
||||||
dma_channel_clear_chain_to(dma_ch_rx1);
|
|
||||||
dma_channel_clear_chain_to(dma_ch_rx2);
|
|
||||||
dma_channel_clear_chain_to(dma_ch_nco1);
|
dma_channel_clear_chain_to(dma_ch_nco1);
|
||||||
dma_channel_clear_chain_to(dma_ch_nco2);
|
dma_channel_clear_chain_to(dma_ch_nco2);
|
||||||
dma_channel_clear_chain_to(dma_ch_nco3);
|
dma_channel_clear_chain_to(dma_ch_nco3);
|
||||||
dma_channel_clear_chain_to(dma_ch_mix);
|
dma_channel_clear_chain_to(dma_ch_mix);
|
||||||
dma_channel_clear_chain_to(dma_ch_samp_cos);
|
|
||||||
|
|
||||||
dma_channel_abort(dma_ch_rx1);
|
|
||||||
dma_channel_abort(dma_ch_rx2);
|
|
||||||
dma_channel_abort(dma_ch_nco1);
|
dma_channel_abort(dma_ch_nco1);
|
||||||
dma_channel_abort(dma_ch_nco2);
|
dma_channel_abort(dma_ch_nco2);
|
||||||
dma_channel_abort(dma_ch_nco3);
|
dma_channel_abort(dma_ch_nco3);
|
||||||
dma_channel_abort(dma_ch_mix);
|
dma_channel_abort(dma_ch_mix);
|
||||||
dma_channel_abort(dma_ch_samp_cos);
|
|
||||||
|
|
||||||
dma_channel_cleanup(dma_ch_rx1);
|
|
||||||
dma_channel_cleanup(dma_ch_rx2);
|
|
||||||
dma_channel_cleanup(dma_ch_nco1);
|
dma_channel_cleanup(dma_ch_nco1);
|
||||||
dma_channel_cleanup(dma_ch_nco2);
|
dma_channel_cleanup(dma_ch_nco2);
|
||||||
dma_channel_cleanup(dma_ch_nco3);
|
dma_channel_cleanup(dma_ch_nco3);
|
||||||
dma_channel_cleanup(dma_ch_mix);
|
dma_channel_cleanup(dma_ch_mix);
|
||||||
dma_channel_cleanup(dma_ch_samp_cos);
|
|
||||||
|
|
||||||
dma_channel_unclaim(dma_ch_rx1);
|
|
||||||
dma_channel_unclaim(dma_ch_rx2);
|
|
||||||
dma_channel_unclaim(dma_ch_nco1);
|
dma_channel_unclaim(dma_ch_nco1);
|
||||||
dma_channel_unclaim(dma_ch_nco2);
|
dma_channel_unclaim(dma_ch_nco2);
|
||||||
dma_channel_unclaim(dma_ch_nco3);
|
dma_channel_unclaim(dma_ch_nco3);
|
||||||
dma_channel_unclaim(dma_ch_mix);
|
dma_channel_unclaim(dma_ch_mix);
|
||||||
dma_channel_unclaim(dma_ch_samp_cos);
|
|
||||||
|
|
||||||
dma_ch_rx1 = -1;
|
|
||||||
dma_ch_rx2 = -1;
|
|
||||||
dma_ch_nco1 = -1;
|
dma_ch_nco1 = -1;
|
||||||
dma_ch_nco2 = -1;
|
dma_ch_nco2 = -1;
|
||||||
dma_ch_nco3 = -1;
|
dma_ch_nco3 = -1;
|
||||||
dma_ch_mix = -1;
|
dma_ch_mix = -1;
|
||||||
dma_ch_samp_cos = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IQ {
|
struct IQ {
|
||||||
int I, Q;
|
int I, Q;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static const uint32_t *next_stride()
|
inline static int nextQ(void)
|
||||||
{
|
{
|
||||||
static int tail = 0;
|
static int dc = 0;
|
||||||
|
|
||||||
int head, delta;
|
int x = adc_fifo_get_blocking();
|
||||||
|
int Q = ((x << 16) - dc) >> 16;
|
||||||
|
dc += Q;
|
||||||
|
|
||||||
loop:
|
return Q;
|
||||||
head = (dma_hw->ch[dma_ch_in_cos].write_addr >> 2) & (RX_WORDS - 1);
|
|
||||||
delta = head - tail;
|
|
||||||
|
|
||||||
if (delta < 0)
|
|
||||||
delta += RX_WORDS;
|
|
||||||
|
|
||||||
if (delta < RX_STRIDE)
|
|
||||||
goto loop;
|
|
||||||
|
|
||||||
const uint32_t *stride = rx_cos + tail;
|
|
||||||
|
|
||||||
tail = (tail + RX_STRIDE) & (RX_WORDS - 1);
|
|
||||||
|
|
||||||
return stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int nextQ(const uint32_t **stride)
|
|
||||||
{
|
|
||||||
int x2 = *(*stride)++;
|
|
||||||
int x1 = *(*stride)++;
|
|
||||||
|
|
||||||
return x2 + x2 + x1 + max_amplitude;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static struct IQ next_sample()
|
inline static struct IQ next_sample()
|
||||||
{
|
{
|
||||||
int I = 0, Q = 0;
|
int I = 0, Q = 0;
|
||||||
|
|
||||||
const uint32_t *stride = next_stride();
|
int x07 = nextQ();
|
||||||
|
I += 36 * x07;
|
||||||
|
Q += 36 * x07;
|
||||||
|
|
||||||
int x15 = nextQ(&stride);
|
int x06 = nextQ();
|
||||||
I += 93 * x15;
|
I += 0 * x06;
|
||||||
Q += 39 * x15;
|
Q += 51 * x06;
|
||||||
|
|
||||||
int x14 = nextQ(&stride);
|
int x05 = nextQ();
|
||||||
I += 71 * x14;
|
I += -36 * x05;
|
||||||
Q += 71 * x14;
|
Q += 36 * x05;
|
||||||
|
|
||||||
int x13 = nextQ(&stride);
|
int x04 = nextQ();
|
||||||
I += 39 * x13;
|
I += -51 * x04;
|
||||||
Q += 93 * x13;
|
Q += 0 * x04;
|
||||||
|
|
||||||
int x12 = nextQ(&stride);
|
int x03 = nextQ();
|
||||||
I += 0 * x12;
|
I += -36 * x03;
|
||||||
Q += 101 * x12;
|
Q += -36 * x03;
|
||||||
|
|
||||||
int x11 = nextQ(&stride);
|
int x02 = nextQ();
|
||||||
I += -39 * x11;
|
I += 0 * x02;
|
||||||
Q += 93 * x11;
|
Q += -51 * x02;
|
||||||
|
|
||||||
int x10 = nextQ(&stride);
|
int x01 = nextQ();
|
||||||
I += -71 * x10;
|
I += 36 * x01;
|
||||||
Q += 71 * x10;
|
Q += -36 * x01;
|
||||||
|
|
||||||
int x09 = nextQ(&stride);
|
int x00 = nextQ();
|
||||||
I += -93 * x09;
|
I += 51 * x00;
|
||||||
Q += 39 * x09;
|
|
||||||
|
|
||||||
int x08 = nextQ(&stride);
|
|
||||||
I += -101 * x08;
|
|
||||||
Q += 0 * x08;
|
|
||||||
|
|
||||||
int x07 = nextQ(&stride);
|
|
||||||
I += -93 * x07;
|
|
||||||
Q += -39 * x07;
|
|
||||||
|
|
||||||
int x06 = nextQ(&stride);
|
|
||||||
I += -71 * x06;
|
|
||||||
Q += -71 * x06;
|
|
||||||
|
|
||||||
int x05 = nextQ(&stride);
|
|
||||||
I += -39 * x05;
|
|
||||||
Q += -93 * x05;
|
|
||||||
|
|
||||||
int x04 = nextQ(&stride);
|
|
||||||
I += 0 * x04;
|
|
||||||
Q += -101 * x04;
|
|
||||||
|
|
||||||
int x03 = nextQ(&stride);
|
|
||||||
I += 39 * x03;
|
|
||||||
Q += -93 * x03;
|
|
||||||
|
|
||||||
int x02 = nextQ(&stride);
|
|
||||||
I += 71 * x02;
|
|
||||||
Q += -71 * x02;
|
|
||||||
|
|
||||||
int x01 = nextQ(&stride);
|
|
||||||
I += 93 * x01;
|
|
||||||
Q += -39 * x01;
|
|
||||||
|
|
||||||
int x00 = nextQ(&stride);
|
|
||||||
I += 101 * x00;
|
|
||||||
Q += 0 * x00;
|
Q += 0 * x00;
|
||||||
|
|
||||||
I *= gain;
|
I *= gain;
|
||||||
I /= 1024;
|
I >>= 8;
|
||||||
I *= max_amplitude_mul;
|
I += 127.4 * 256;
|
||||||
I += 127.4 * (1 << 16);
|
I >>= 8;
|
||||||
I /= (1 << 16);
|
|
||||||
|
|
||||||
Q *= gain;
|
Q *= gain;
|
||||||
Q /= 1024;
|
Q >>= 8;
|
||||||
Q *= max_amplitude_mul;
|
Q += 127.4 * 256;
|
||||||
Q += 127.4 * (1 << 16);
|
Q >>= 8;
|
||||||
Q /= (1 << 16);
|
|
||||||
|
|
||||||
return (struct IQ){ I, Q };
|
return (struct IQ){ I, Q };
|
||||||
}
|
}
|
||||||
|
@ -617,11 +354,11 @@ static void run_command(uint8_t cmd, uint32_t arg)
|
||||||
rx_lo_init(frequency + sample_rate);
|
rx_lo_init(frequency + sample_rate);
|
||||||
} else if (0x02 == cmd) {
|
} else if (0x02 == cmd) {
|
||||||
/* Set the rate at which IQ sample pairs are sent */
|
/* Set the rate at which IQ sample pairs are sent */
|
||||||
|
if (arg > (ADC_RATE / DECIMATE))
|
||||||
|
arg = ADC_RATE / DECIMATE;
|
||||||
|
|
||||||
sample_rate = arg;
|
sample_rate = arg;
|
||||||
max_amplitude = CLK_SYS_HZ / sample_rate / 2;
|
adc_set_clkdiv(96.0f * ((float)ADC_RATE / (sample_rate * DECIMATE)) - 1.0f);
|
||||||
max_amplitude_mul = 65536 / max_amplitude;
|
|
||||||
dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE));
|
|
||||||
rx_lo_init(frequency + sample_rate);
|
|
||||||
} else if (0x04 == cmd) {
|
} else if (0x04 == cmd) {
|
||||||
/* Set the tuner gain level */
|
/* Set the tuner gain level */
|
||||||
gain = INIT_GAIN * powf(10.0f, arg / 200.0f);
|
gain = INIT_GAIN * powf(10.0f, arg / 200.0f);
|
||||||
|
@ -664,18 +401,6 @@ static void do_rx()
|
||||||
rf_rx_start();
|
rf_rx_start();
|
||||||
sleep_us(100);
|
sleep_us(100);
|
||||||
|
|
||||||
dma_ch_in_cos = dma_claim_unused_channel(true);
|
|
||||||
|
|
||||||
dma_channel_config dma_conf;
|
|
||||||
|
|
||||||
dma_conf = dma_channel_get_default_config(dma_ch_in_cos);
|
|
||||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
|
||||||
channel_config_set_read_increment(&dma_conf, false);
|
|
||||||
channel_config_set_write_increment(&dma_conf, true);
|
|
||||||
channel_config_set_ring(&dma_conf, GPIO_OUT, RX_BITS_DEPTH);
|
|
||||||
channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, SM_AD, false));
|
|
||||||
dma_channel_configure(dma_ch_in_cos, &dma_conf, rx_cos, &PIO->rxf[SM_AD], UINT_MAX, true);
|
|
||||||
|
|
||||||
multicore_launch_core1(rf_rx);
|
multicore_launch_core1(rf_rx);
|
||||||
|
|
||||||
const uint8_t *block;
|
const uint8_t *block;
|
||||||
|
@ -708,18 +433,24 @@ done:
|
||||||
multicore_reset_core1();
|
multicore_reset_core1();
|
||||||
|
|
||||||
rf_rx_stop();
|
rf_rx_stop();
|
||||||
|
|
||||||
dma_channel_clear_chain_to(dma_ch_in_cos);
|
|
||||||
dma_channel_abort(dma_ch_in_cos);
|
|
||||||
dma_channel_cleanup(dma_ch_in_cos);
|
|
||||||
dma_channel_unclaim(dma_ch_in_cos);
|
|
||||||
dma_ch_in_cos = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
vreg_set_voltage(VREG_VOLTAGE);
|
vreg_set_voltage(VREG_VOLTAGE);
|
||||||
|
|
||||||
|
/* Step the USB PLL up to 192 MHz and overclock ADC with it. */
|
||||||
|
pll_init(pll_usb, 1, 1536 * MHZ, 4, 2);
|
||||||
|
|
||||||
|
clock_configure(clk_usb, 0, CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||||
|
4 * USB_CLK_KHZ * KHZ, USB_CLK_KHZ * KHZ);
|
||||||
|
|
||||||
|
clock_configure(clk_adc, 0, CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||||
|
4 * USB_CLK_KHZ * KHZ, 4 * USB_CLK_KHZ * KHZ);
|
||||||
|
|
||||||
|
/* Adjust system clock as well. */
|
||||||
set_sys_clock_khz(CLK_SYS_HZ / KHZ, true);
|
set_sys_clock_khz(CLK_SYS_HZ / KHZ, true);
|
||||||
|
|
||||||
clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, CLK_SYS_HZ,
|
clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, CLK_SYS_HZ,
|
||||||
CLK_SYS_HZ);
|
CLK_SYS_HZ);
|
||||||
|
|
||||||
|
@ -735,10 +466,16 @@ int main()
|
||||||
|
|
||||||
queue_init(&iq_queue, sizeof(uint8_t *), IQ_QUEUE_LEN);
|
queue_init(&iq_queue, sizeof(uint8_t *), IQ_QUEUE_LEN);
|
||||||
|
|
||||||
rx_lo_init(frequency + sample_rate);
|
/* Init ADC */
|
||||||
|
adc_init();
|
||||||
|
gpio_disable_pulls(RX_PIN);
|
||||||
|
adc_gpio_init(RX_PIN);
|
||||||
|
adc_select_input(RX_PIN - 26);
|
||||||
|
adc_fifo_setup(true, true, 1, false, false);
|
||||||
|
adc_set_clkdiv(96.0f * ((ADC_RATE / ((float)sample_rate / DECIMATE)) - 1.0f) - 1.0f);
|
||||||
|
adc_run(true);
|
||||||
|
|
||||||
dma_t_samp = dma_claim_unused_timer(true);
|
rx_lo_init(frequency + sample_rate);
|
||||||
dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE));
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (check_command() > 0) {
|
if (check_command() > 0) {
|
||||||
|
|
Loading…
Reference in a new issue