; This program consists of 3 state machines communicating using state machine IRQs
;  - hsync generates the hsync signal and drives the vsync and data state machines
;  - vsync generates the vsync signal and drives the data state machine
;  - data generates the pixel data stream, synchronized with the hsync and vsync IRQs
;    generated by their respective timing state machine
;
; Overall timing (in pixel times)
;
;  Time |       hsync action      |        vsync action             | data action
; ------------------------------------------------------------------------------------------------
;     0 | assert lineclk IRQ      |                                 |
;     8 |                         | wait & reset lineclk IRQ        |
;    16 | set hsync signal low    | set vsync signal high/low       |
;   112 | set hsync signal high   |                                 |
;   144 |                         | assert vsync IRQ                |
; 144.5 |                         |                                 | 'wait irq vsync' completes
;   152 | assert hsync IRQ        |                                 |
; 152.5 |                         |                                 | 'wait irq hsync' completes
;   160 | deassert hsync IRQ      |                                 | first pixel RGB data out
;   161 |                         |                                 | second pixel RGB data out
;   216 |                         | deassert vsync IRQ              |

.define LINECLK_IRQ_NUM 4
.define HSYNC_IRQ_NUM 5
.define VSYNC_IRQ_NUM 6


; Run at 4 * pixel frequency
.program vga_data
.origin 0

.wrap_target
pixel_out:
    out PINS, 9
    out PC, 7
public wait_vsync:
    wait 0 irq VSYNC_IRQ_NUM
public wait_hsync:
    wait 0 irq HSYNC_IRQ_NUM  [1]
public extend_7:
    nop  [1]
public extend_6:
    nop  [1]
public extend_5:
    nop  [1]
public extend_4:
    nop  [1]
public extend_3:
    nop  [1]
public extend_2:
    nop  [1]
public extend_1:
    nop  [1]
.wrap


; Run at pixel frequency / 8
.program vga_hsync
    pull  ; load timing loop count from the CPU
.wrap_target
    irq set LINECLK_IRQ_NUM  [1]   ; (0) assert lineclk IRQ
    set PINS, 0  [11]              ; (16) set hsync signal low
    set PINS, 1  [4]               ; (112) set hsync signal high
    irq clear HSYNC_IRQ_NUM        ; (152) assert hsync IRQ
    irq set HSYNC_IRQ_NUM          ; (160) deassert hsync IRQ

    ; Wait until the next hsync should be generated
    mov X, OSR
skip_loop:
    jmp X--, skip_loop
.wrap


; Run at pixel frequency / 8
.program vga_vsync
    pull  ; load timing loop count from the CPU
.wrap_target
    wait 1 irq LINECLK_IRQ_NUM     ; (8) wait & reset lineclk IRQ
    set pins, 0 [15]               ; (16) set vsync signal low
    irq clear VSYNC_IRQ_NUM  [8]   ; (144) assert vsync IRQ
    irq set VSYNC_IRQ_NUM          ; (216) deassert vsync IRQ
    wait 1 irq LINECLK_IRQ_NUM
    wait 1 irq LINECLK_IRQ_NUM     ; (8) wait for lineclk & reset
    set pins, 1                    ; (16) set vsync signal high

    ; Skip the remaining scanlines
    mov X, OSR
skip_loop:
    wait 1 irq LINECLK_IRQ_NUM
    jmp X--, skip_loop
.wrap


; Pixel Frequency: 25.175MHz
;
; Horizontal timing
;
;    640x480@60Hz and 640x400@70Hz (pulse low)
; Scanline part | Pixels | Time [µs]
; ------------------------------------------
; Visible area  | 640    | 25.422045680238
; Front porch   | 16     | 0.63555114200596
; Sync pulse    | 96     | 3.8133068520357
; Back porch    | 48     | 1.9066534260179
; Whole line    | 800    | 31.777557100298
;
; Vertical timing
;
;                [640x480@60Hz (pulse low)] || [640x400@70Hz (pulse high)]
; Frame part   | Lines | Time [ms]          || Lines | Time [ms]
;------------------------------------------------------------------------
; Visible area |  480  | 15.253227408143    ||  400  | 12.711022840119
; Front porch  |   10  | 0.31777557100298   ||   12  | 0.38133068520357
; Sync pulse   |    2  | 0.063555114200596  ||    2  | 0.063555114200596
; Back porch   |   33  | 1.0486593843098    ||   35  | 1.1122144985104
; Whole frame  |  525  | 16.683217477656    ||  449  | 14.268123138034
