.program unicorn
.side_set 1 opt

; set pins:
; 0: data (base)
; 1: clock
; 2: latch
; 3: blank

; sideset pin: clock

; out pins:
; 0: row 6 select
; 1: row 5 select
; 2: row 4 select
; 3: row 3 select
; 4: row 2 select
; 5: row 1 select
; 6: row 0 select

.wrap_target

; clock out 16 pixels worth of data
    set y, 15                ; 15 because `jmp` test is pre decrement

pixels:

    pull ifempty

    ; dummy bit used to align pixel data to nibbles
    out null, 1              ; discard

    ; red bit
    out x, 1       side 0    ; pull in first bit from OSR into register X, clear clock
    set pins, 8              ; clear data bit (maintain blank)
    jmp !x endr              ; if bit was zero jump to endr
    set pins, 9              ; set data bit (maintain blank)
endr:                        ;
    nop            side 1    ; clock in bit

    ; green bit
    out x, 1       side 0    ; pull in first bit from OSR into register X, clear clock
    set pins, 8              ; clear data bit (maintain blank)
    jmp !x endg              ; if bit was zero jump to endg
    set pins, 9              ; set data bit (maintain blank)
endg:                        ;
    nop            side 1    ; clock in bit

    ; blue bit
    out x, 1       side 0    ; pull in first bit from OSR into register X, clear clock
    set pins, 8              ; clear data bit (maintain blank)
    jmp !x endb              ; if bit was zero jump to endb
    set pins, 9              ; set data bit (maintain blank)
endb:                        ;
    nop            side 1    ; clock in bit

    jmp y-- pixels           ; jump back to start of pixel loop

    pull

; dummy byte to 32 bit align row data
    out null, 8

; select active row
    out null, 1              ; discard dummy bit
    out pins, 7              ; output row selection mask

; pull bcd tick count into x register
    out x, 16

; set latch pin to output column data on shift registers
    set pins, 12             ; set latch pin (while keeping blank high)

; set blank pin to enable column drivers
    set pins, 4

bcd_count:
    jmp x-- bcd_count       ; loop until bcd delay complete

; disable all row outputs
    set x, 0                ; load x register with 0 (we can't set more than 5 bits at a time)
    mov pins, !x            ; write inverted x (0xff) to row pins latching them all high

; disable led output (blank) and clear latch pin
    set pins, 8

.wrap