; video_dma.pio ; ; Composite video generator: ; - SM1: sync timing + line start IRQ ; - SM0: pixel output during active video ; ; Based on the same timing structure as alanpreed/pico-composite-video: ; 4us hsync, 6us back porch, 52us active video, 2us front porch, ; 288 active lines per field, interlaced fields. .define DATA_DELAY 4 .define LINE_IRQ 0 .define PUBLIC CLOCKS_PER_BIT DATA_DELAY + 2 .program cvsync .side_set 1 ; OSR = lines_per_field - 1 ; Y = field flag: 0 = even field, !0 = odd field .wrap_target vsync_start: ; First set of short pulses: ; even field: 6 ; odd field : 5 jmp !y set_even_counter side 0 set x, 3 side 1 jmp vsync_short_pulse side 1 [13] set_even_counter: set x, 4 side 1 [14] vsync_short_pulse: nop side 0 jmp x-- vsync_short_pulse [14] side 1 ; Long sync pulses: always 5 set x, 4 side 0 [13] vsync_long_start: jmp !x vsync_long_end [1] side 1 jmp x-- vsync_long_start [13] side 0 vsync_long_end: ; Second set of short pulses: ; even field: 5 ; odd field : 4 jmp !y set_even_counter_2 side 0 set x, 2 side 1 jmp flip_field_flag side 1 [12] set_even_counter_2: set x, 3 side 1 [13] flip_field_flag: mov y, !y side 1 vsync_short_pulse_2: nop side 0 jmp x-- vsync_short_pulse_2 [14] side 1 ; 17 blank lines set x, 16 side 0 [1] hsync_blank_start: nop side 1 [14] jmp !x hsync_blank_end side 1 [14] jmp x-- hsync_blank_start side 0 [1] hsync_blank_end: ; 288 active video lines mov x, osr side 0 [1] hsync_video: nop side 1 [2] ; 6us back porch irq set LINE_IRQ side 1 [13] ; 52us active video jmp !x vsync_start side 1 [12] ; 2us front porch (+ tail of active) jmp x-- hsync_video side 0 [1] ; 4us hsync pulse .wrap .program cvdata ; X = pixels_per_line - 1, preloaded once from C ; Each line: ; clear output ; reload Y from X ; wait for sync SM to raise LINE_IRQ ; shift out one bit per loop .wrap_target set pins, 0 mov y, x wait 1 irq LINE_IRQ data_out: out pins, 1 [DATA_DELAY] jmp y-- data_out .wrap