Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4596

SDK • Tight timings PIO + USB, how to do it?

$
0
0
I'm working on a project that needs to drive a CRT screen (MDA monitor). I was able to do this with GPIO and DMA. It works nicely so far. I have 3 GPIO state machines, one for HSYNC, one for VSYNC and one for the pixel drive. There is a task that generates the pixels and it's all synced by the horizontal sync interrupt.

The pixel drive looks like this:

Code:

void irq0_callback(){    static volatile uint32_t *line_buffer;    dma_channel_set_read_addr(dma_channel, line_buffer, true);    pio_interrupt_clear(pio0, PIO0_IRQ_0);    line_buffer = line % 2 == 1 ? linebuffer0 : linebuffer1;    flag = 1;}
then the part that sets the pixels looks like this:

Code:

void handleLine(){    uint32_t *work_buffer = line % 2 == 1 ? linebuffer0 : linebuffer1;    memset(work_buffer, 0, (LINE_BUFFER_SIZE - 1) * 4);    ... individually set pixels, etc    
This is the HSYNC generation. Basically it reads the number of cycles it should wait once at the beginning of the program, and then repeats this continuously, raising an IRQ.

Code:

.program hsyncpull block.wrap_target    mov x, osr    set pins, 0iloop:    jmp x-- iloop    set pins, 1 [31]    set pins, 1 [31]    set pins, 1 [31]    set pins, 1 [31]    set pins, 1 [15]    irq 0.wrap
The pixel drive, however, depends on DMA:

Code:

.program pixel.wrap_target    out pins, 2 [7].wrap
It will just output data as fast as it can as long as there is data in the register.


The problem I have is that when I add the USB HID example, artifacts start appearing on the screen. I think it's caused by delays. It's like the irq0_callback function is being called a couple microseconds later and this causes the screen to shift lines to the right. The clocks, however, seem to work fine. I haven't noticed any jitter from the PIO SMs that depend on interrupt but not on DMA.


I also tried moving the execution of the screen drive to the second core, and also changing it to use pio1 instead of pio0. Nothing changes, so I'm very confused as of what could be causing these issues.

I've noticed the timings "fix" themselves for a split second when I plug in a USB keyboard. But with the keyboard either plugged or unplugged, the image looks wrong.

So the question would be, where should I start looking? I thought it could be related to "not enough cpu power" but I'm running the program in a core separate from the USB handling. I also thought it could be related to the USB library setting some PIO that affects mine, but moving to another pio didn't fix it either.

My initialization looks like

Code:

int main(){    board_init();    tuh_init(BOARD_TUH_RHPORT);    if (board_init_after_tusb)    {        board_init_after_tusb();    }    screen_initialize();    multicore_launch_core1(screen_worker);    serial_initialize();    while (1)    {        tuh_task();         serial_worker(); //this is the Pico's UART, not USB        hid_app_task();    }}
I did notice than my screen_initialize() function needs to be called after the board initialization functions. So I'm thinking they're overriding each other but I can't figure out how or why.

Any hints would be appreciated.

Statistics: Posted by hjf — Wed Oct 23, 2024 9:49 pm — Replies 0 — Views 8



Viewing all articles
Browse latest Browse all 4596

Trending Articles