Pseudo-differential ADC
This commit is contained in:
parent
574e6aa844
commit
15f05f2e4e
3 changed files with 95 additions and 203 deletions
12
grc/base.grc
12
grc/base.grc
|
@ -37,7 +37,7 @@ blocks:
|
|||
id: variable
|
||||
parameters:
|
||||
comment: ''
|
||||
value: 132e6 / 256
|
||||
value: 132e6 / (3 * 128)
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
|
@ -153,7 +153,7 @@ blocks:
|
|||
alpha8: '1.0'
|
||||
alpha9: '1.0'
|
||||
autoscale: 'False'
|
||||
average: '0.05'
|
||||
average: '0.2'
|
||||
axislabels: 'True'
|
||||
bw: samp_rate
|
||||
color1: '"blue"'
|
||||
|
@ -169,7 +169,7 @@ blocks:
|
|||
comment: ''
|
||||
ctrlpanel: 'False'
|
||||
fc: '0'
|
||||
fftsize: '16384'
|
||||
fftsize: '8192'
|
||||
freqhalf: 'False'
|
||||
grid: 'True'
|
||||
gui_hint: ''
|
||||
|
@ -210,7 +210,7 @@ blocks:
|
|||
width9: '1'
|
||||
wintype: window.WIN_BLACKMAN_hARRIS
|
||||
ymax: '0'
|
||||
ymin: '-100'
|
||||
ymin: '-120'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
|
@ -273,7 +273,7 @@ blocks:
|
|||
marker9: '-1'
|
||||
name: '""'
|
||||
nconnections: '1'
|
||||
size: '512'
|
||||
size: '4096'
|
||||
srate: samp_rate
|
||||
stemplot: 'True'
|
||||
style1: '1'
|
||||
|
@ -344,7 +344,7 @@ blocks:
|
|||
color9: '0'
|
||||
comment: ''
|
||||
fc: '0'
|
||||
fftsize: '16384'
|
||||
fftsize: '8192'
|
||||
freqhalf: 'False'
|
||||
grid: 'False'
|
||||
gui_hint: ''
|
||||
|
|
|
@ -61,7 +61,7 @@ blocks:
|
|||
id: variable
|
||||
parameters:
|
||||
comment: ''
|
||||
value: 132e6 / 256
|
||||
value: 132e6 / (3 * 128)
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
|
@ -254,7 +254,7 @@ blocks:
|
|||
alpha8: '1.0'
|
||||
alpha9: '1.0'
|
||||
autoscale: 'False'
|
||||
average: '0.05'
|
||||
average: '0.2'
|
||||
axislabels: 'True'
|
||||
bw: data_rate
|
||||
color1: '"blue"'
|
||||
|
|
282
src/main.c
282
src/main.c
|
@ -11,48 +11,35 @@
|
|||
|
||||
#define SMPS_PIN 23
|
||||
|
||||
#define IR_BIAS_PIN 3
|
||||
#define IR_RX_PIN 6
|
||||
#define IR_FB_PIN 8
|
||||
#define IRP_FB_PIN 2
|
||||
#define IRP_RX_PIN 3
|
||||
#define IRN_FB_PIN 0
|
||||
#define IRN_RX_PIN 1
|
||||
|
||||
#define IR_PIO pio0
|
||||
#define IR_SM 0
|
||||
|
||||
#define HP_GND_PIN 13
|
||||
#define HP_LEFT_PIN 14
|
||||
#define HP_RIGHT_PIN 15
|
||||
|
||||
#define HP_GND_SLICE 6
|
||||
#define HP_GND_CHAN PWM_CHAN_B
|
||||
|
||||
#define HP_LR_SLICE 7
|
||||
|
||||
#define HP_PWM_RATE (16 * 48 * 1000)
|
||||
#define HP_PWM_SCALE (SYS_CLK_HZ / HP_PWM_RATE)
|
||||
#define HP_PWM_MID (HP_PWM_SCALE / 2)
|
||||
|
||||
typedef struct Sample {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
} Sample;
|
||||
#define IRP_SM 0
|
||||
#define IRN_SM 1
|
||||
|
||||
#define NUM_SAMPLES_BITS 10
|
||||
#define NUM_SAMPLES (1 << NUM_SAMPLES_BITS)
|
||||
static Sample sample_buffer[NUM_SAMPLES] __aligned(4 * NUM_SAMPLES);
|
||||
static int dma_ch_sample;
|
||||
static int dma_ch_rx;
|
||||
static uint16_t irp_buffer[NUM_SAMPLES] __aligned(2 * NUM_SAMPLES);
|
||||
static int dma_ch_irp_rx;
|
||||
|
||||
/* Jump to 0, side-set 1. */
|
||||
static uint16_t sampling_script[] = { 0b0001100000000000 };
|
||||
static uint16_t irn_buffer[NUM_SAMPLES] __aligned(2 * NUM_SAMPLES);
|
||||
static int dma_ch_irn_rx;
|
||||
|
||||
static void init_pio_sm(void)
|
||||
#define BIT(n) (1 << (n))
|
||||
|
||||
static void init_pio_sm(pio_hw_t *pio, int sm, int rx_pin, int fb_pin)
|
||||
{
|
||||
const uint16_t insn[] = {
|
||||
pio_encode_in(pio_y, 16),
|
||||
pio_encode_in(pio_x, 16) | pio_encode_sideset_opt(1, 0),
|
||||
pio_encode_jmp_pin(4),
|
||||
pio_encode_jmp_x_dec(2) | pio_encode_sideset_opt(1, 1),
|
||||
pio_encode_jmp_y_dec(2) | pio_encode_sideset_opt(1, 0),
|
||||
pio_encode_jmp_x_dec(4),
|
||||
pio_encode_in(pio_y, 16) | pio_encode_sideset_opt(1, 1),
|
||||
pio_encode_mov(pio_x, pio_osr),
|
||||
pio_encode_nop() | pio_encode_sideset_opt(1, 0),
|
||||
pio_encode_jmp_pin(6),
|
||||
pio_encode_jmp(0) | pio_encode_sideset_opt(1, 1),
|
||||
pio_encode_jmp_y_dec(0) | pio_encode_sideset_opt(1, 0),
|
||||
};
|
||||
|
||||
pio_program_t prog = {
|
||||
|
@ -60,50 +47,74 @@ static void init_pio_sm(void)
|
|||
.length = sizeof(insn) / sizeof(*insn),
|
||||
.origin = 0,
|
||||
};
|
||||
pio_add_program(IR_PIO, &prog);
|
||||
|
||||
if (pio_can_add_program(pio, &prog))
|
||||
pio_add_program(pio, &prog);
|
||||
|
||||
pio_sm_config pc = pio_get_default_sm_config();
|
||||
sm_config_set_clkdiv_int_frac8(&pc, 1, 0);
|
||||
sm_config_set_jmp_pin(&pc, IR_RX_PIN);
|
||||
sm_config_set_in_pins(&pc, IR_RX_PIN);
|
||||
sm_config_set_out_pins(&pc, IR_FB_PIN, 1);
|
||||
sm_config_set_set_pins(&pc, IR_FB_PIN, 1);
|
||||
sm_config_set_sideset_pin_base(&pc, IR_FB_PIN);
|
||||
sm_config_set_jmp_pin(&pc, rx_pin);
|
||||
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_pin_base(&pc, fb_pin);
|
||||
sm_config_set_sideset(&pc, 2, true, false);
|
||||
sm_config_set_in_shift(&pc, false, true, 32);
|
||||
sm_config_set_fifo_join(&pc, PIO_FIFO_JOIN_RX);
|
||||
sm_config_set_in_shift(&pc, false, true, 16);
|
||||
sm_config_set_out_shift(&pc, false, false, 32);
|
||||
|
||||
pio_sm_init(IR_PIO, IR_SM, prog.origin, &pc);
|
||||
pio_sm_set_wrap(IR_PIO, IR_SM, prog.origin + 2, prog.origin + prog.length - 1);
|
||||
pio_sm_init(pio, sm, prog.origin, &pc);
|
||||
pio_sm_set_wrap(pio, sm, prog.origin, prog.origin + prog.length - 1);
|
||||
|
||||
pio_sm_set_consecutive_pindirs(IR_PIO, IR_SM, IR_RX_PIN, 1, GPIO_IN);
|
||||
pio_sm_set_consecutive_pindirs(IR_PIO, IR_SM, IR_FB_PIN, 1, GPIO_OUT);
|
||||
pio_sm_restart(pio, sm);
|
||||
pio_sm_clear_fifos(pio, sm);
|
||||
|
||||
pio_sm_restart(IR_PIO, IR_SM);
|
||||
pio_sm_clear_fifos(IR_PIO, IR_SM);
|
||||
pio->txf[sm] = 126;
|
||||
pio_sm_exec_wait_blocking(pio, sm, pio_encode_pull(false, false));
|
||||
pio_sm_exec_wait_blocking(pio, sm, pio_encode_mov(pio_x, pio_osr));
|
||||
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, rx_pin, 1, GPIO_IN);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, fb_pin, 1, GPIO_OUT);
|
||||
|
||||
gpio_disable_pulls(rx_pin);
|
||||
gpio_disable_pulls(fb_pin);
|
||||
|
||||
pio_gpio_init(pio, fb_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_FAST);
|
||||
}
|
||||
|
||||
static unsigned tail;
|
||||
|
||||
static bool read_sample(int *sample)
|
||||
{
|
||||
unsigned head = (dma_hw->ch[dma_ch_rx].write_addr >> 2) % NUM_SAMPLES;
|
||||
unsigned head = (dma_hw->ch[dma_ch_irn_rx].write_addr >> 1) % NUM_SAMPLES;
|
||||
|
||||
if (tail == head)
|
||||
return false;
|
||||
|
||||
static Sample prev;
|
||||
Sample next = sample_buffer[tail];
|
||||
uint16_t next_pos = irp_buffer[tail];
|
||||
uint16_t next_neg = irn_buffer[tail];
|
||||
tail = (tail + 1) % NUM_SAMPLES;
|
||||
|
||||
int s = (prev.y - next.y) - (prev.x - next.x);
|
||||
prev = next;
|
||||
static uint16_t prev_pos;
|
||||
int pos = prev_pos - next_pos;
|
||||
prev_pos = next_pos;
|
||||
|
||||
static int dc;
|
||||
dc += ((s << 16) - dc) >> 10;
|
||||
s -= dc >> 16;
|
||||
static uint16_t prev_neg;
|
||||
int neg = prev_neg - next_neg;
|
||||
prev_neg = next_neg;
|
||||
|
||||
*sample = s;
|
||||
static int dc_pos;
|
||||
dc_pos += ((pos << 16) - dc_pos) >> 12;
|
||||
pos -= (dc_pos >> 16);
|
||||
|
||||
static int dc_neg;
|
||||
dc_neg += ((neg << 16) - dc_neg) >> 12;
|
||||
neg -= (dc_neg >> 16);
|
||||
|
||||
*sample = pos - neg;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -125,163 +136,46 @@ int main()
|
|||
gpio_put(SMPS_PIN, 1);
|
||||
gpio_set_dir(SMPS_PIN, GPIO_OUT);
|
||||
|
||||
#if 0
|
||||
gpio_disable_pulls(HP_GND_PIN);
|
||||
gpio_disable_pulls(HP_LEFT_PIN);
|
||||
gpio_disable_pulls(HP_RIGHT_PIN);
|
||||
init_pio_sm(IR_PIO, IRP_SM, IRP_RX_PIN, IRP_FB_PIN);
|
||||
init_pio_sm(IR_PIO, IRN_SM, IRN_RX_PIN, IRN_FB_PIN);
|
||||
|
||||
gpio_set_function(HP_GND_PIN, GPIO_FUNC_PWM);
|
||||
gpio_set_function(HP_LEFT_PIN, GPIO_FUNC_PWM);
|
||||
gpio_set_function(HP_RIGHT_PIN, GPIO_FUNC_PWM);
|
||||
|
||||
gpio_set_drive_strength(HP_GND_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
gpio_set_drive_strength(HP_LEFT_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
gpio_set_drive_strength(HP_RIGHT_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
|
||||
/* LR at 48 kHz */
|
||||
pwm_config pc = pwm_get_default_config();
|
||||
pwm_config_set_clkdiv_int(&pc, 1);
|
||||
pwm_config_set_phase_correct(&pc, false);
|
||||
pwm_config_set_wrap(&pc, HP_PWM_SCALE - 1);
|
||||
pwm_init(HP_LR_SLICE, &pc, false);
|
||||
|
||||
/* GND at high rate, 50:50 for virtual ground */
|
||||
pwm_config_set_wrap(&pc, 1);
|
||||
pwm_init(HP_GND_SLICE, &pc, false);
|
||||
pwm_set_chan_level(HP_GND_SLICE, HP_GND_CHAN, 1);
|
||||
|
||||
/* Start at 50:50. */
|
||||
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID, HP_PWM_MID);
|
||||
|
||||
/* Start both */
|
||||
pwm_set_enabled(HP_GND_SLICE, true);
|
||||
pwm_set_enabled(HP_LR_SLICE, true);
|
||||
|
||||
while (true) {
|
||||
for (int i = 0; i < 50; i++) {
|
||||
sleep_us(2272);
|
||||
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID + 1, HP_PWM_MID + 1);
|
||||
|
||||
sleep_us(2272);
|
||||
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID - 1, HP_PWM_MID - 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 55; i++) {
|
||||
sleep_us(2020);
|
||||
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID + 1, HP_PWM_MID + 1);
|
||||
|
||||
sleep_us(2020);
|
||||
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID - 1, HP_PWM_MID - 1);
|
||||
}
|
||||
|
||||
sleep_ms(500);
|
||||
}
|
||||
#else
|
||||
// gpio_init(IR_BIAS_PIN);
|
||||
gpio_disable_pulls(IR_BIAS_PIN);
|
||||
// gpio_set_drive_strength(IR_BIAS_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
// gpio_put(IR_BIAS_PIN, 1);
|
||||
// gpio_set_dir(IR_BIAS_PIN, GPIO_OUT);
|
||||
|
||||
gpio_disable_pulls(IR_RX_PIN);
|
||||
gpio_disable_pulls(IR_FB_PIN);
|
||||
|
||||
pio_gpio_init(IR_PIO, IR_FB_PIN);
|
||||
|
||||
gpio_set_input_hysteresis_enabled(IR_RX_PIN, false);
|
||||
gpio_set_drive_strength(IR_FB_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
gpio_set_slew_rate(IR_FB_PIN, GPIO_SLEW_RATE_FAST);
|
||||
|
||||
init_pio_sm();
|
||||
|
||||
dma_ch_sample = dma_claim_unused_channel(true);
|
||||
dma_ch_rx = dma_claim_unused_channel(true);
|
||||
int timer = dma_claim_unused_timer(true);
|
||||
dma_ch_irp_rx = dma_claim_unused_channel(true);
|
||||
dma_ch_irn_rx = dma_claim_unused_channel(true);
|
||||
|
||||
dma_channel_config dma_conf;
|
||||
|
||||
/* Copy sampling script into the PIO. */
|
||||
dma_conf = dma_channel_get_default_config(dma_ch_sample);
|
||||
dma_conf = dma_channel_get_default_config(dma_ch_irp_rx);
|
||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
|
||||
channel_config_set_read_increment(&dma_conf, false);
|
||||
channel_config_set_write_increment(&dma_conf, false);
|
||||
channel_config_set_chain_to(&dma_conf, dma_ch_rx);
|
||||
channel_config_set_dreq(&dma_conf, dma_get_timer_dreq(timer));
|
||||
dma_channel_configure(dma_ch_sample, &dma_conf, &IR_PIO->sm[IR_SM].instr, sampling_script,
|
||||
1, false);
|
||||
channel_config_set_write_increment(&dma_conf, true);
|
||||
channel_config_set_ring(&dma_conf, true, NUM_SAMPLES_BITS + 1);
|
||||
channel_config_set_dreq(&dma_conf, pio_get_dreq(IR_PIO, IRP_SM, false));
|
||||
channel_config_set_chain_to(&dma_conf, dma_ch_irn_rx);
|
||||
dma_channel_configure(dma_ch_irp_rx, &dma_conf, irp_buffer, &IR_PIO->rxf[IRP_SM], 1, false);
|
||||
|
||||
/* Read samples from PIO. */
|
||||
dma_conf = dma_channel_get_default_config(dma_ch_rx);
|
||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32);
|
||||
dma_conf = dma_channel_get_default_config(dma_ch_irn_rx);
|
||||
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
|
||||
channel_config_set_read_increment(&dma_conf, false);
|
||||
channel_config_set_write_increment(&dma_conf, true);
|
||||
channel_config_set_ring(&dma_conf, true, NUM_SAMPLES_BITS + 2);
|
||||
channel_config_set_chain_to(&dma_conf, dma_ch_sample);
|
||||
channel_config_set_dreq(&dma_conf, pio_get_dreq(IR_PIO, IR_SM, false));
|
||||
dma_channel_configure(dma_ch_rx, &dma_conf, sample_buffer, &IR_PIO->rxf[IR_SM], 1, false);
|
||||
channel_config_set_ring(&dma_conf, true, NUM_SAMPLES_BITS + 1);
|
||||
channel_config_set_dreq(&dma_conf, pio_get_dreq(IR_PIO, IRN_SM, false));
|
||||
channel_config_set_chain_to(&dma_conf, dma_ch_irp_rx);
|
||||
dma_channel_configure(dma_ch_irn_rx, &dma_conf, irn_buffer, &IR_PIO->rxf[IRN_SM], 1, false);
|
||||
|
||||
/* 8 × 38 kHz */
|
||||
// dma_timer_set_fraction(timer, 8 * 16, 55579);
|
||||
dma_timer_set_fraction(timer, 1, 256);
|
||||
dma_channel_start(dma_ch_rx);
|
||||
pio_sm_set_enabled(IR_PIO, IR_SM, true);
|
||||
dma_channel_start(dma_ch_irp_rx);
|
||||
|
||||
pio_set_sm_mask_enabled(IR_PIO, BIT(IRP_SM) | BIT(IRN_SM), true);
|
||||
|
||||
static int8_t batch[64];
|
||||
unsigned written = 0;
|
||||
|
||||
#if 0
|
||||
static int sin_lut[16] = { 0, 98, 180, 236, 255, 236, 180, 98,
|
||||
0, -98, -180, -236, -255, -236, -180, -98 };
|
||||
static int cos_lut[16] = { 255, 236, 180, 98, 0, -98, -180, -236,
|
||||
-255, -236, -180, -98, 0, 98, 180, 236 };
|
||||
|
||||
int I = 0, Q = 0;
|
||||
int phase = 0;
|
||||
|
||||
while (true) {
|
||||
/* Get last byte written. */
|
||||
unsigned head = (dma_hw->ch[dma_ch_rx].write_addr - 8u) & ((4 * NUM_SAMPLES) - 1);
|
||||
|
||||
/* Convert to index into 4-byte array. */
|
||||
head = (head >> 2);
|
||||
|
||||
while (tail != head) {
|
||||
int sample = read_sample();
|
||||
|
||||
I += (cos_lut[phase] * sample) >> 8;
|
||||
Q += (sin_lut[phase] * sample) >> 8;
|
||||
|
||||
if (++phase >= 16) {
|
||||
I >>= 3;
|
||||
Q >>= 3;
|
||||
|
||||
batch[written++] = I;
|
||||
batch[written++] = Q;
|
||||
|
||||
I = Q = 0;
|
||||
phase = 0;
|
||||
}
|
||||
|
||||
if (written >= sizeof(batch) / sizeof(*batch)) {
|
||||
written = 0;
|
||||
if (tud_cdc_n_write_available(1) >= sizeof(batch)) {
|
||||
tud_cdc_n_write(1, batch, sizeof(batch));
|
||||
tud_cdc_n_write_flush(1);
|
||||
written = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sleep_us(10);
|
||||
}
|
||||
#else
|
||||
stdio_usb_lock();
|
||||
|
||||
while (true) {
|
||||
int sample;
|
||||
|
||||
while (read_sample(&sample)) {
|
||||
batch[written++] = sample << 1;
|
||||
batch[written++] = sample;
|
||||
|
||||
if (written >= sizeof(batch) / sizeof(*batch)) {
|
||||
while (tud_cdc_n_write_available(1) < sizeof(batch)) {
|
||||
|
@ -300,6 +194,4 @@ int main()
|
|||
}
|
||||
|
||||
stdio_usb_unlock();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue