From 141bf39b35cb54513a627d41b0e3f4a58248b224 Mon Sep 17 00:00:00 2001 From: Marcelo Lorenzati Date: Wed, 27 Mar 2024 21:39:23 -0300 Subject: [PATCH] hsync_pio: test purging fifo from hsync pio to resync pixel start --- config/common_configs.h | 5 ++- src/rgbScan/CMakeLists.txt | 3 +- src/rgbScan/hsync.pio | 36 ++++++++++++++++++ src/rgbScan/wm8213Afe.c | 77 +++++++++++++++++++++++++------------- src/rgbScan/wm8213Afe.h | 7 +++- 5 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 src/rgbScan/hsync.pio diff --git a/config/common_configs.h b/config/common_configs.h index aa146c3..d1ce20e 100644 --- a/config/common_configs.h +++ b/config/common_configs.h @@ -127,9 +127,10 @@ }, .verify_retries = 3, .pio = pio1, - .sm_afe = 0, + .sm = {0, 1}, .pin_base_afe_op = AFE_OP, - .pin_base_afe_ctrl = AFE_VSMP + .pin_base_afe_ctrl = AFE_VSMP, + .pin_hsync = RGB_SCAN_HSYNC_PIN }; #endif diff --git a/src/rgbScan/CMakeLists.txt b/src/rgbScan/CMakeLists.txt index 195b2b3..9038b0b 100644 --- a/src/rgbScan/CMakeLists.txt +++ b/src/rgbScan/CMakeLists.txt @@ -23,4 +23,5 @@ target_link_libraries(rgbScan INTERFACE color ) -pico_generate_pio_header(rgbScan ${CMAKE_CURRENT_LIST_DIR}/wm8213Afe.pio) \ No newline at end of file +pico_generate_pio_header(rgbScan ${CMAKE_CURRENT_LIST_DIR}/wm8213Afe.pio) +pico_generate_pio_header(rgbScan ${CMAKE_CURRENT_LIST_DIR}/hsync.pio) \ No newline at end of file diff --git a/src/rgbScan/hsync.pio b/src/rgbScan/hsync.pio new file mode 100644 index 0000000..ac69178 --- /dev/null +++ b/src/rgbScan/hsync.pio @@ -0,0 +1,36 @@ +; PIO program to sync on external HSYNC and trigger a proper timinig capture +; Independent of IRQ Code jitter issues +.program hsync +.wrap_target + //wait 0 pin 0 ; Wait for the low + //wait 1 pin 0 ; Wait for the high + pull ; Get from FIFO to release capture on AFE + pull ; Get from FIFO to release capture on AFE +.wrap + +% c-sdk { + #include "hardware/clocks.h" + static inline void hsync_program_init(PIO pio, uint sm, uint offset, uint hsync_pin) { + // Initialize HSYNC PIN + //pio_gpio_init(pio, hsync_pin); + + // Set the HSYNC pin direction to input + //pio_sm_set_consecutive_pindirs(pio, sm, hsync_pin, 1, false); + + // Create new state machine config + pio_sm_config c = hsync_program_get_default_config(offset); + + // Shift registers do not shift + //sm_config_set_out_shift(&c, true, true, 0); + //sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + // Map the HSYNC IN pin group to one pin, namely the `pin` + //sm_config_set_in_pins (&c, hsync_pin); + + // Set the Clocking to max + sm_config_set_clkdiv(&c, 1); + + // Initialize PIO + pio_sm_init(pio, sm, offset, &c); + } +%} \ No newline at end of file diff --git a/src/rgbScan/wm8213Afe.c b/src/rgbScan/wm8213Afe.c index 1dab0a4..be14ed8 100644 --- a/src/rgbScan/wm8213Afe.c +++ b/src/rgbScan/wm8213Afe.c @@ -1,6 +1,7 @@ #include "wm8213Afe.h" #include "hardware/gpio.h" #include "wm8213Afe.pio.h" +#include "hsync.pio.h" #include "hardware/timer.h" #include "hardware/structs/bus_ctrl.h" @@ -101,24 +102,34 @@ int wm8213_afe_spi_setup(const wm8213_afe_config_t* config, const wm8213_afe_set return 0; } +void wm8213_afe_clean_sm(PIO pio, uint offset, const pio_program_t *program) { + if (offset == 0) { + return; + } + pio_sm_set_enabled(pio, offset, false); + pio_remove_program(pio, program, offset); + pio_sm_restart(pio, offset); +} + // AFE Pio Capture Related uint wm8213_afe_capture_setup() { if (wm8213_afe_capture_global.config == NULL) { return 1; } - pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm_afe, false); - - const pio_program_t *program = NULL; + pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[0], false); + pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[1], false); + + const pio_program_t *capture_program = NULL; uint8_t op_bits = 0; uint op_pins = 0; switch (wm8213_afe_capture_global.bppx) { case rgb_8_332: - program = (wm8213_afe_capture_global.sampling_rate > AFE_SAMPLING_LIMIT) ? &afe_capture_332_inverted_program : &afe_capture_332_program; + capture_program = (wm8213_afe_capture_global.sampling_rate > AFE_SAMPLING_LIMIT) ? &afe_capture_332_inverted_program : &afe_capture_332_program; op_bits = 3; op_pins = wm8213_afe_capture_global.config->pin_base_afe_op + 3; break; case rgb_16_565: - program = (wm8213_afe_capture_global.sampling_rate > AFE_SAMPLING_LIMIT) ? &afe_capture_565_inverted_program : &afe_capture_565_program; + capture_program = (wm8213_afe_capture_global.sampling_rate > AFE_SAMPLING_LIMIT) ? &afe_capture_565_inverted_program : &afe_capture_565_program; op_bits = 6; op_pins = wm8213_afe_capture_global.config->pin_base_afe_op; break; @@ -127,18 +138,18 @@ uint wm8213_afe_capture_setup() { return 6; } - if (wm8213_afe_capture_global.pio_offset != 0) { - pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm_afe, false); - pio_remove_program(wm8213_afe_capture_global.config->pio, program, wm8213_afe_capture_global.pio_offset); - pio_sm_restart(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm_afe); - } + wm8213_afe_clean_sm(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[0], capture_program); + wm8213_afe_clean_sm(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[1], &hsync_program); - wm8213_afe_capture_global.pio_offset = pio_add_program(wm8213_afe_capture_global.config->pio, program); - afe_capture_program_init(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm_afe, wm8213_afe_capture_global.pio_offset, wm8213_afe_capture_global.sampling_rate, op_pins, wm8213_afe_capture_global.config->pin_base_afe_ctrl, op_bits); + wm8213_afe_capture_global.pio_offset[0] = pio_add_program(wm8213_afe_capture_global.config->pio, capture_program); + wm8213_afe_capture_global.pio_offset[1] = pio_add_program(wm8213_afe_capture_global.config->pio, &hsync_program); + afe_capture_program_init(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[0], wm8213_afe_capture_global.pio_offset[0], wm8213_afe_capture_global.sampling_rate, op_pins, wm8213_afe_capture_global.config->pin_base_afe_ctrl, op_bits); + hsync_program_init(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[1], wm8213_afe_capture_global.pio_offset[1], wm8213_afe_capture_global.config->pin_hsync); // Give DMA R/W priority over the Bus //bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS; - pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm_afe, true); + pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[0], true); + pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[1], true); return 0; } @@ -156,38 +167,54 @@ uint wm8213_afe_capture_update_bppx(color_bppx bppx, bool commit) { } // AFE DMA related -void afe_dma_prepare(PIO pio, uint sm) { +void afe_dma_prepare(PIO pio, const uint *sm) { wm8213_afe_capture_global.capture_dma = dma_claim_unused_channel(true); wm8213_afe_capture_global.front_porch_dma = dma_claim_unused_channel(true); + wm8213_afe_capture_global.hsync_dma = dma_claim_unused_channel(true); dma_channel_config front_porch_dma_channel_cfg = dma_channel_get_default_config(wm8213_afe_capture_global.front_porch_dma); channel_config_set_transfer_data_size(&front_porch_dma_channel_cfg, wm8213_afe_capture_global.bppx == rgb_8_332 ? DMA_SIZE_8 : DMA_SIZE_16); //Transfer 8/16bits words that are shifted by pio - channel_config_set_dreq(&front_porch_dma_channel_cfg, pio_get_dreq(pio, sm, false)); // Pace transfers based on PIO samples availabilty + channel_config_set_dreq(&front_porch_dma_channel_cfg, pio_get_dreq(pio, sm[0], false)); // Pace transfers based on PIO samples availabilty channel_config_set_read_increment(&front_porch_dma_channel_cfg, false); channel_config_set_write_increment(&front_porch_dma_channel_cfg, false); channel_config_set_chain_to(&front_porch_dma_channel_cfg, wm8213_afe_capture_global.capture_dma); dma_channel_configure(wm8213_afe_capture_global.front_porch_dma, &front_porch_dma_channel_cfg, - &dummy_dma_read,// Destination: dummy - &pio->rxf[sm], // Source - 0, // Size: will be set later + &dummy_dma_read, // Destination: dummy + &pio->rxf[sm[0]], // Source + 0, // Size: will be set later false ); dma_channel_config afe_dma_channel_cfg = dma_channel_get_default_config(wm8213_afe_capture_global.capture_dma); channel_config_set_transfer_data_size(&afe_dma_channel_cfg, wm8213_afe_capture_global.bppx == rgb_8_332 ? DMA_SIZE_8 : DMA_SIZE_16); //Transfer 8/16bits words that are shifted by pio - channel_config_set_dreq(&afe_dma_channel_cfg, pio_get_dreq(pio, sm, false)); // Pace transfers based on PIO samples availabilty + channel_config_set_dreq(&afe_dma_channel_cfg, pio_get_dreq(pio, sm[0], false)); // Pace transfers based on PIO samples availabilty channel_config_set_read_increment(&afe_dma_channel_cfg, false); channel_config_set_write_increment(&afe_dma_channel_cfg, true); - + channel_config_set_chain_to(&afe_dma_channel_cfg, wm8213_afe_capture_global.hsync_dma); + dma_channel_configure(wm8213_afe_capture_global.capture_dma, &afe_dma_channel_cfg, - NULL, // Destination: will be set later - &pio->rxf[sm], // Source - 0, // Size: will be set later + NULL, // Destination: will be set later + &pio->rxf[sm[0]], // Source + 0, // Size: will be set later false ); + + dma_channel_config hsync_dma_channel_cfg = dma_channel_get_default_config(wm8213_afe_capture_global.hsync_dma); + channel_config_set_transfer_data_size(&hsync_dma_channel_cfg, wm8213_afe_capture_global.bppx == rgb_8_332 ? DMA_SIZE_8 : DMA_SIZE_16); //Transfer 8/16bits words that are shifted by pio + channel_config_set_dreq(&hsync_dma_channel_cfg, pio_get_dreq(pio, sm[1], true)); // Pace transfers based on hsync SM control + channel_config_set_read_increment(&hsync_dma_channel_cfg, false); + channel_config_set_write_increment(&hsync_dma_channel_cfg, false); + + dma_channel_configure(wm8213_afe_capture_global.hsync_dma, + &hsync_dma_channel_cfg, + &pio->txf[sm[1]], // Destination: will be set later + &pio->rxf[sm[0]], // Source + 0, // Size: will be set later + false + ); } //AFE Main calls @@ -212,7 +239,7 @@ int wm8213_afe_start(uint sampling_rate) res = wm8213_afe_capture_setup(); if (res > 0) { return res; } - afe_dma_prepare(config->pio, config->sm_afe); + afe_dma_prepare(config->pio, config->sm); return res; } @@ -222,7 +249,7 @@ void wm8213_afe_capture_wait() { } void wm8213_afe_capture_stop() { - pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm_afe, false); + pio_sm_set_enabled(wm8213_afe_capture_global.config->pio, wm8213_afe_capture_global.config->sm[0], false); } uint wm8213_afe_update_gain(uint16_t red, uint16_t green, uint16_t blue, bool commit) { diff --git a/src/rgbScan/wm8213Afe.h b/src/rgbScan/wm8213Afe.h index 2902f7b..828a85c 100644 --- a/src/rgbScan/wm8213Afe.h +++ b/src/rgbScan/wm8213Afe.h @@ -153,16 +153,18 @@ typedef struct wm8213_afe_config { wm8213_afe_setups_t setups; char verify_retries; PIO pio; - uint sm_afe; + uint sm[2]; uint pin_base_afe_op; uint pin_base_afe_ctrl; + uint pin_hsync; } wm8213_afe_config_t; typedef struct wm8213_afe_capture { uint capture_dma; uint front_porch_dma; + uint hsync_dma; uint sampling_rate; - uint pio_offset; + uint pio_offset[2]; color_bppx bppx; wm8213_afe_setups_t setups; const wm8213_afe_config_t *config; @@ -183,6 +185,7 @@ static inline bool wm8213_afe_capture_run(uint hFrontPorch, uintptr_t buffer, ui dma_channel_hw_addr(capture_dma)->al1_write_addr = buffer; dma_channel_hw_addr(capture_dma)->transfer_count = size; + dma_channel_hw_addr(wm8213_afe_capture_global.hsync_dma)->transfer_count = 1000; return true; }