2025-06-15 22:02:02 +02:00
|
|
|
#include <pico/stdlib.h>
|
|
|
|
#include <pico/stdio_usb.h>
|
2025-06-17 17:34:56 +02:00
|
|
|
#include <tusb.h>
|
2025-06-15 22:02:02 +02:00
|
|
|
|
|
|
|
#include <hardware/pwm.h>
|
2025-06-17 17:34:56 +02:00
|
|
|
#include <hardware/pio.h>
|
|
|
|
#include <hardware/dma.h>
|
|
|
|
#include <hardware/clocks.h>
|
2025-06-15 22:02:02 +02:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2025-06-17 17:34:56 +02:00
|
|
|
#define SMPS_PIN 23
|
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
#define IRP_FB_PIN 2
|
|
|
|
#define IRP_RX_PIN 3
|
|
|
|
#define IRN_FB_PIN 0
|
|
|
|
#define IRN_RX_PIN 1
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
#define IR_PIO pio0
|
2025-06-18 11:41:03 +02:00
|
|
|
#define IRP_SM 0
|
|
|
|
#define IRN_SM 1
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
#define NUM_SAMPLES_BITS 10
|
2025-06-19 19:07:14 +02:00
|
|
|
#define NUM_SAMPLES (1 << NUM_SAMPLES_BITS)
|
2025-06-18 11:41:03 +02:00
|
|
|
static uint16_t irp_buffer[NUM_SAMPLES] __aligned(2 * NUM_SAMPLES);
|
|
|
|
static int dma_ch_irp_rx;
|
|
|
|
|
|
|
|
static uint16_t irn_buffer[NUM_SAMPLES] __aligned(2 * NUM_SAMPLES);
|
|
|
|
static int dma_ch_irn_rx;
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
#define BIT(n) (1 << (n))
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
static void init_pio_sm(pio_hw_t *pio, int sm, int rx_pin, int fb_pin)
|
2025-06-17 17:34:56 +02:00
|
|
|
{
|
|
|
|
const uint16_t insn[] = {
|
2025-06-18 11:41:03 +02:00
|
|
|
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),
|
2025-06-19 19:07:14 +02:00
|
|
|
pio_encode_set(pio_y, 0) | pio_encode_sideset_opt(1, 0),
|
2025-06-18 11:41:03 +02:00
|
|
|
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),
|
2025-06-17 17:34:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
pio_program_t prog = {
|
|
|
|
.instructions = insn,
|
|
|
|
.length = sizeof(insn) / sizeof(*insn),
|
|
|
|
.origin = 0,
|
|
|
|
};
|
2025-06-18 11:41:03 +02:00
|
|
|
|
|
|
|
if (pio_can_add_program(pio, &prog))
|
|
|
|
pio_add_program(pio, &prog);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
pio_sm_config pc = pio_get_default_sm_config();
|
|
|
|
sm_config_set_clkdiv_int_frac8(&pc, 1, 0);
|
2025-06-18 11:41:03 +02:00
|
|
|
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);
|
2025-06-17 17:34:56 +02:00
|
|
|
sm_config_set_sideset(&pc, 2, true, false);
|
2025-06-18 11:41:03 +02:00
|
|
|
sm_config_set_in_shift(&pc, false, true, 16);
|
|
|
|
sm_config_set_out_shift(&pc, false, false, 32);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
pio_sm_init(pio, sm, prog.origin, &pc);
|
|
|
|
pio_sm_set_wrap(pio, sm, prog.origin, prog.origin + prog.length - 1);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
pio_sm_restart(pio, sm);
|
|
|
|
pio_sm_clear_fifos(pio, sm);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
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);
|
2025-06-17 17:34:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned tail;
|
|
|
|
|
|
|
|
static bool read_sample(int *sample)
|
|
|
|
{
|
2025-06-18 11:41:03 +02:00
|
|
|
unsigned head = (dma_hw->ch[dma_ch_irn_rx].write_addr >> 1) % NUM_SAMPLES;
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
if (tail == head)
|
|
|
|
return false;
|
|
|
|
|
2025-06-19 19:07:14 +02:00
|
|
|
int pos = irp_buffer[tail] << 16;
|
|
|
|
int neg = irn_buffer[tail] << 16;
|
2025-06-17 17:34:56 +02:00
|
|
|
tail = (tail + 1) % NUM_SAMPLES;
|
|
|
|
|
2025-06-19 19:07:14 +02:00
|
|
|
int s = pos - neg;
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-19 19:07:14 +02:00
|
|
|
static int dc;
|
|
|
|
dc += (s - dc) >> 16;
|
|
|
|
s -= dc;
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-19 19:07:14 +02:00
|
|
|
*sample = s >> 16;
|
2025-06-17 17:34:56 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2025-06-15 22:02:02 +02:00
|
|
|
int main()
|
|
|
|
{
|
|
|
|
stdio_usb_init();
|
|
|
|
|
|
|
|
for (int i = 0; i < 30; i++) {
|
|
|
|
if (stdio_usb_connected())
|
|
|
|
break;
|
|
|
|
|
|
|
|
sleep_ms(100);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\nWelcome to PDM Test!\n");
|
|
|
|
|
2025-06-17 17:34:56 +02:00
|
|
|
gpio_init(SMPS_PIN);
|
|
|
|
gpio_disable_pulls(SMPS_PIN);
|
|
|
|
gpio_put(SMPS_PIN, 1);
|
|
|
|
gpio_set_dir(SMPS_PIN, GPIO_OUT);
|
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
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);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
dma_ch_irp_rx = dma_claim_unused_channel(true);
|
|
|
|
dma_ch_irn_rx = dma_claim_unused_channel(true);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
dma_channel_config dma_conf;
|
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
dma_conf = dma_channel_get_default_config(dma_ch_irp_rx);
|
2025-06-17 17:34:56 +02:00
|
|
|
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
|
|
|
|
channel_config_set_read_increment(&dma_conf, false);
|
2025-06-18 11:41:03 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
dma_conf = dma_channel_get_default_config(dma_ch_irn_rx);
|
|
|
|
channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
|
2025-06-17 17:34:56 +02:00
|
|
|
channel_config_set_read_increment(&dma_conf, false);
|
|
|
|
channel_config_set_write_increment(&dma_conf, true);
|
2025-06-18 11:41:03 +02:00
|
|
|
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);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
2025-06-18 11:41:03 +02:00
|
|
|
dma_channel_start(dma_ch_irp_rx);
|
|
|
|
|
|
|
|
pio_set_sm_mask_enabled(IR_PIO, BIT(IRP_SM) | BIT(IRN_SM), true);
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
static int8_t batch[64];
|
|
|
|
unsigned written = 0;
|
|
|
|
|
|
|
|
stdio_usb_lock();
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
int sample;
|
|
|
|
|
|
|
|
while (read_sample(&sample)) {
|
2025-06-18 11:41:03 +02:00
|
|
|
batch[written++] = sample;
|
2025-06-17 17:34:56 +02:00
|
|
|
|
|
|
|
if (written >= sizeof(batch) / sizeof(*batch)) {
|
|
|
|
while (tud_cdc_n_write_available(1) < sizeof(batch)) {
|
|
|
|
tud_cdc_n_write_flush(1);
|
|
|
|
tud_task();
|
|
|
|
sleep_us(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
tud_cdc_n_write(1, batch, sizeof(batch));
|
|
|
|
written = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tud_task();
|
|
|
|
sleep_us(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
stdio_usb_unlock();
|
2025-06-15 22:02:02 +02:00
|
|
|
}
|