Revamp video timing generation
* the pio file is now generated during the build by cmake * the program_init functions are now generated * the "change visible pixels" function now finds closer line timings
This commit is contained in:
parent
6d9d52c9d6
commit
b3d9919088
6 changed files with 151 additions and 200 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,3 +3,4 @@ chargen.s
|
|||
chargen.png
|
||||
build
|
||||
__pycache__
|
||||
vga_*.pio
|
||||
|
|
|
|||
|
|
@ -18,7 +18,17 @@ add_executable(cr100 chargen.c)
|
|||
|
||||
pico_enable_stdio_usb(cr100 1)
|
||||
|
||||
pico_generate_pio_header(cr100 ${CMAKE_CURRENT_LIST_DIR}/vga_660_480_60.pio)
|
||||
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vga_660x480_60.pio
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vga_660x400_70.pio
|
||||
COMMAND python ${CMAKE_CURRENT_LIST_DIR}/vgamode.py
|
||||
DEPENDS vgamode.py
|
||||
)
|
||||
|
||||
|
||||
pico_generate_pio_header(cr100 ${CMAKE_CURRENT_BINARY_DIR}/vga_660x480_60.pio)
|
||||
|
||||
target_link_libraries(cr100 pico_stdlib pico_multicore hardware_pio)
|
||||
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -95,19 +95,16 @@ coincidence and only required fudging VGA timings slightly.
|
|||
## Timing accuracy
|
||||
|
||||
Heirloom VGA 640x480@60Hz:
|
||||
* 25.125MHz dot clock
|
||||
* 640 visible pixels, 800 total pixels = 31.40kHz horizontal rate
|
||||
* 25.175MHz dot clock
|
||||
* 640 visible pixels, 800 total pixels = 31.47kHz horizontal rate
|
||||
* 480 visible lines, 525 total lines = 59.92Hz vertical rate
|
||||
|
||||
My 660x480@60Hz mode:
|
||||
* 26MHz dot clock
|
||||
* 660 visible pixels, 825 total pixels = 31.78kHz horizontal rate (1.4% high)
|
||||
* 480 visible lines, 525 total lines = 60.03Hz vertical rate (1.4% high)
|
||||
* 26.000MHz dot clock
|
||||
* 660 visible pixels, 826 total pixels = 31.48kHz horizontal rate (<1% high)
|
||||
* 480 visible lines, 525 total lines = 59.96Hz vertical rate (<1% high)
|
||||
|
||||
I don't expect there to be any problem for an old monitor to sync to this signal.
|
||||
However, a total of 828 horizontal pixels per line would be much closer to
|
||||
the real line time; my mode generating script did not take account of the specific
|
||||
attainable clocks on the rp2040.
|
||||
|
||||
# License
|
||||
|
||||
|
|
|
|||
75
chargen.c
75
chargen.c
|
|
@ -5,7 +5,7 @@
|
|||
#include "pico/platform.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "vga_660_480_60.pio.h"
|
||||
#include "vga_660x480_60.pio.h"
|
||||
|
||||
int pixels_sm;
|
||||
#else
|
||||
|
|
@ -197,74 +197,6 @@ uint16_t base_shade[] = {0, 0x554, 0xaa8, 0xffc, 0, 0x554, 0xaa8, 0xffc, 0, 0, 0
|
|||
#define VSYNC_PIN (17)
|
||||
#define G0_PIN (9) // "green 3" on VGA pico demo base
|
||||
|
||||
// TODO generate this in the pio file!
|
||||
static inline void vga_660x480_60_hsync_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
|
||||
pio_sm_config c = vga_660x480_60_hsync_program_get_default_config(offset);
|
||||
|
||||
// Map the state machine's SET pin group to one pin, namely the `pin`
|
||||
// parameter to this function.
|
||||
sm_config_set_set_pins(&c, pin, 1);
|
||||
sm_config_set_clkdiv(&c, 6.f);
|
||||
// Set this pin's GPIO function (connect PIO to the pad)
|
||||
pio_gpio_init(pio, pin);
|
||||
// Set the pin direction to output at the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
// Set the state machine running
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
// TODO generate this in the pio file!
|
||||
static inline void vga_660x480_60_vsync_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
|
||||
pio_sm_config c = vga_660x480_60_vsync_program_get_default_config(offset);
|
||||
|
||||
// Map the state machine's SIDESET to one pin, namely the `pin`
|
||||
// parameter to this function.
|
||||
// sm_config_set_sideset(&c, 1, true, false);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
sm_config_set_clkdiv(&c, 6.f);
|
||||
|
||||
// Set this pin's GPIO function (connect PIO to the pad)
|
||||
pio_gpio_init(pio, pin);
|
||||
// Set the pin direction to output at the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
// Set the state machine running
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
// TODO generate this in the pio file!
|
||||
static inline void vga_660x480_60_pixels_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
|
||||
pio_sm_config c = vga_660x480_60_pixels_program_get_default_config(offset);
|
||||
|
||||
// Map the state machine's OUT & SET pins
|
||||
sm_config_set_out_pins(&c, pin, 2);
|
||||
sm_config_set_set_pins(&c, pin, 2);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
// 15 pixels (30 bits) per word, left is MSB
|
||||
sm_config_set_out_shift(&c, false, true, 30);
|
||||
|
||||
// Set this pin's GPIO function (connect PIO to the pad)
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_gpio_init(pio, pin+1);
|
||||
// Set the pin direction to output at the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
// Set the state machine running
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
|
||||
static void setup_vga_hsync(PIO pio) {
|
||||
uint offset = pio_add_program(pio, &vga_660x480_60_hsync_program);
|
||||
uint sm = pio_claim_unused_sm(pio, true);
|
||||
|
|
@ -282,7 +214,7 @@ static void setup_vga_vsync(PIO pio) {
|
|||
static int setup_vga_pixels(PIO pio) {
|
||||
uint offset = pio_add_program(pio, &vga_660x480_60_pixels_program);
|
||||
uint sm = pio_claim_unused_sm(pio, true);
|
||||
vga_660x480_60_pixels_program_init(pio, sm, offset, G0_PIN);
|
||||
vga_660x480_60_pixels_program_init(pio, sm, offset, G0_PIN, 2);
|
||||
pio_sm_put_blocking(pio, sm, 660-1);
|
||||
return sm;
|
||||
}
|
||||
|
|
@ -331,8 +263,7 @@ void __not_in_flash_func(core1_entry)() {
|
|||
|
||||
int main() {
|
||||
#if !STANDALONE
|
||||
set_sys_clock_khz(156000, false);
|
||||
// set_sys_clock_pll(130, 5, 2);
|
||||
set_sys_clock_khz(vga_660x480_60_sys_clock_khz, false);
|
||||
stdio_init_all();
|
||||
#endif
|
||||
if(0)
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
|
||||
; Horizontal sync program for <VideoMode 660x480 31.47kHz/59.94Hz pclk=25962KHz>
|
||||
; PIO clock frequency = 25961.7/1khz = 25961.7
|
||||
;
|
||||
.program vga_660x480_60_hsync
|
||||
pull block ; Pull from FIFO to OSR (only happens once)
|
||||
|
||||
.wrap_target ; Program wraps to here
|
||||
; ACTIVE + FRONTPORCH 660 + 16 error 0
|
||||
mov x, osr ; Copy value from OSR to x scratch register
|
||||
activeporch:
|
||||
jmp x-- activeporch ; Remain high in active mode and front porch
|
||||
|
||||
|
||||
syncpulse: ; 99/1 clocks [actual 99 error 0]
|
||||
set pins, 0 [31]
|
||||
set pins, 0 [31]
|
||||
set pins, 0 [31]
|
||||
set pins, 0 [2]
|
||||
|
||||
backporch: ; 50/1 clocks [actual 50 error 0]
|
||||
set pins, 1 [31]
|
||||
set pins, 1 [16]
|
||||
|
||||
irq 0 [1]
|
||||
.wrap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.program vga_660x480_60_vsync
|
||||
.side_set 1 opt
|
||||
; Vertical sync program for <VideoMode 660x480 31.47kHz/59.94Hz pclk=25962KHz>
|
||||
;
|
||||
pull block ; Pull from FIFO to OSR (only once)
|
||||
|
||||
.wrap_target ; Program wraps to here
|
||||
; ACTIVE
|
||||
mov x, osr ; Copy value from OSR to x scratch register
|
||||
active:
|
||||
wait 1 irq 0 ; Wait for hsync to go high
|
||||
irq 1 ; Signal that we're in active mode
|
||||
jmp x-- active ; Remain in active mode, decrementing counter
|
||||
|
||||
|
||||
set y, 9
|
||||
frontporch: ; 10 lines
|
||||
wait 1 irq 0
|
||||
jmp y--, frontporch
|
||||
|
||||
syncpulse: ; 2 lines
|
||||
wait 1 irq 0 side 0
|
||||
wait 1 irq 0 side 0
|
||||
|
||||
set y, 31
|
||||
backporch: ; 33 lines
|
||||
wait 1 irq 0 side 1
|
||||
jmp y--, backporch
|
||||
wait 1 irq 0 side 1
|
||||
|
||||
.wrap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.program vga_660x480_60_pixels
|
||||
; Pixel generator program for <VideoMode 660x480 31.47kHz/59.94Hz pclk=25962KHz>
|
||||
; PIO clock frequency = 6×25961.71875khz = 155770.3125
|
||||
pull block ; Pull from FIFO to OSR (only once)
|
||||
mov y, osr ; Copy value from OSR to y scratch register
|
||||
|
||||
.wrap_target
|
||||
set pins, 0 ; Zero RGB pins in blanking
|
||||
mov x, y ; Initialize counter variable
|
||||
|
||||
wait 1 irq 1 [5] ; wait for vsync active mode
|
||||
|
||||
colorout:
|
||||
out pins, 2 [4]
|
||||
jmp x-- colorout ; Stay here thru horizontal active mode
|
||||
|
||||
.wrap
|
||||
166
vgamode.py
166
vgamode.py
|
|
@ -2,7 +2,7 @@
|
|||
import sys
|
||||
|
||||
from enum import Enum, auto
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
|
||||
class Polarity:
|
||||
Negative = 0
|
||||
|
|
@ -30,6 +30,9 @@ class VideoMode:
|
|||
def line_time_us(self):
|
||||
return 1000 / self.line_rate_khz
|
||||
|
||||
@property
|
||||
def visible_line_time_us(self):
|
||||
return 1000 * self.visible_width / self.pixel_clock_khz
|
||||
|
||||
visible_height: int
|
||||
vfront_porch: int
|
||||
|
|
@ -45,32 +48,40 @@ class VideoMode:
|
|||
def frame_rate_hz(self):
|
||||
return self.line_rate_khz / self.total_lines * 1000
|
||||
|
||||
@property
|
||||
def frame_time_ms(self):
|
||||
return 1000 / self.frame_rate_hz
|
||||
|
||||
def __repr__(self):
|
||||
return f"<VideoMode {self.visible_width}x{self.visible_height} {self.line_rate_khz:.2f}kHz/{self.frame_rate_hz:.2f}Hz pclk={self.pixel_clock_khz:.0f}KHz>"
|
||||
return f"<VideoMode {self.visible_width}x{self.visible_height} {self.line_rate_khz:.2f}kHz/{self.frame_rate_hz:.2f}Hz pclk={self.pixel_clock_khz:.0f}KHz hvis={self.visible_line_time_us:.2f}us>"
|
||||
|
||||
def change_visible_pixels(mode_in, new_w):
|
||||
ratio = new_w / mode_in.visible_width
|
||||
new_clock = mode_in.pixel_clock_khz * ratio
|
||||
new_hfront = round(mode_in.hfront_porch * ratio)
|
||||
new_hsync = round(mode_in.hsync_pulse * ratio)
|
||||
new_hback = round(mode_in.hback_porch * ratio)
|
||||
return VideoMode(
|
||||
new_clock,
|
||||
new_w,
|
||||
new_hfront,
|
||||
new_hsync,
|
||||
new_hback,
|
||||
mode_in.hsync_polarity,
|
||||
|
||||
mode_in.visible_height,
|
||||
mode_in.vfront_porch,
|
||||
mode_in.vsync_pulse,
|
||||
mode_in.vback_porch,
|
||||
mode_in.vsync_polarity,
|
||||
def change_visible_pixels(mode_in, new_w, new_clock=None):
|
||||
print(mode_in)
|
||||
if new_clock is None:
|
||||
new_clock = mode_in.pixel_clock_khz * new_w / mode_in.visible_width
|
||||
new_mode = replace(mode_in,
|
||||
pixel_clock_khz = new_clock,
|
||||
visible_width = new_w,
|
||||
)
|
||||
print(new_mode)
|
||||
ratio = new_clock / mode_in.pixel_clock_khz
|
||||
new_visible_time = new_mode.visible_line_time_us
|
||||
new_line_counts = round(mode_in.total_width * ratio)
|
||||
print(new_line_counts, mode_in.total_width * ratio)
|
||||
new_pulse = round(mode_in.hsync_pulse * ratio)
|
||||
new_porch_counts = new_line_counts - new_pulse - new_w
|
||||
porch_ratio = mode_in.hfront_porch / (mode_in.hfront_porch + mode_in.hback_porch)
|
||||
new_front = round(new_porch_counts * porch_ratio)
|
||||
new_back = new_porch_counts - new_front
|
||||
print((mode_in.hfront_porch, mode_in.hsync_pulse, mode_in.hback_porch), "->", (new_front, new_pulse, new_back))
|
||||
new_mode = replace(
|
||||
new_mode,
|
||||
hfront_porch = new_front,
|
||||
hsync_pulse = new_pulse,
|
||||
hback_porch = new_back)
|
||||
print(new_mode)
|
||||
print()
|
||||
return new_mode
|
||||
|
||||
def pio_hard_delay(instr, n, file):
|
||||
assert n > 0
|
||||
|
|
@ -81,7 +92,7 @@ def pio_hard_delay(instr, n, file):
|
|||
n -= cycles
|
||||
print(file=file)
|
||||
|
||||
def print_pio_hsync_program(program_name_base, mode, h_divisor, file=sys.stdout):
|
||||
def print_pio_hsync_program(program_name_base, mode, h_divisor, cycles_per_pixel, file=sys.stdout):
|
||||
net_khz = mode.pixel_clock_khz / h_divisor
|
||||
err = (mode.visible_width + mode.hfront_porch) % h_divisor
|
||||
print(f"""
|
||||
|
|
@ -99,6 +110,29 @@ activeporch:
|
|||
|
||||
""", file=file)
|
||||
|
||||
print(f"""
|
||||
% c-sdk {{
|
||||
static inline void {program_name_base}_program_init(PIO pio, uint sm, uint offset, uint pin) {{
|
||||
|
||||
pio_sm_config c = {program_name_base}_program_get_default_config(offset);
|
||||
|
||||
// Map the state machine's SET pin group to one pin, namely the `pin`
|
||||
// parameter to this function.
|
||||
sm_config_set_set_pins(&c, pin, 1);
|
||||
sm_config_set_clkdiv_int_frac(&c, {cycles_per_pixel * h_divisor}, 0);
|
||||
// Set this pin's GPIO function (connect PIO to the pad)
|
||||
pio_gpio_init(pio, pin);
|
||||
// Set the pin direction to output at the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
// Set the state machine running
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}}
|
||||
|
||||
%}}
|
||||
""", file=file)
|
||||
|
||||
cycles, err = divmod(mode.hsync_pulse + err, h_divisor)
|
||||
print(f"syncpulse: ; {mode.hsync_pulse}/{h_divisor} clocks [actual {cycles} error {err}]", file=file)
|
||||
|
|
@ -107,7 +141,7 @@ activeporch:
|
|||
cycles, err = divmod(mode.hback_porch + err, h_divisor)
|
||||
print(f"backporch: ; {mode.hback_porch}/{h_divisor} clocks [actual {cycles} error {err}]", file=file)
|
||||
pio_hard_delay(f"set pins, {not mode.hsync_polarity:d}", cycles - 1, file=file)
|
||||
print(" irq 0 [1]")
|
||||
print(" irq 0 [1]", file=file)
|
||||
print(".wrap", file=file)
|
||||
|
||||
def pio_yloop(instr, n, label, comment, file):
|
||||
|
|
@ -133,7 +167,7 @@ def pio_yloop(instr, n, label, comment, file):
|
|||
print(f" {instr}", file=file)
|
||||
print(file=file)
|
||||
|
||||
def print_pio_vsync_program(program_name_base, mode, file=sys.stdout):
|
||||
def print_pio_vsync_program(program_name_base, mode, cycles_per_pixel, file=sys.stdout):
|
||||
print(f"""
|
||||
.program {program_name_base}_vsync
|
||||
.side_set 1 opt
|
||||
|
|
@ -149,6 +183,34 @@ active:
|
|||
irq 1 ; Signal that we're in active mode
|
||||
jmp x-- active ; Remain in active mode, decrementing counter
|
||||
|
||||
""", file=file)
|
||||
|
||||
print(f"""
|
||||
% c-sdk {{
|
||||
static inline void {program_name_base}_vsync_program_init(PIO pio, uint sm, uint offset, uint pin) {{
|
||||
|
||||
pio_sm_config c = {program_name_base}_vsync_program_get_default_config(offset);
|
||||
|
||||
// Map the state machine's SIDESET to one pin, namely the `pin`
|
||||
// parameter to this function.
|
||||
// sm_config_set_sideset(&c, 1, true, false);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
sm_config_set_clkdiv_int_frac(&c, {cycles_per_pixel});
|
||||
|
||||
// Set this pin's GPIO function (connect PIO to the pad)
|
||||
pio_gpio_init(pio, pin);
|
||||
// Set the pin direction to output at the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
// Set the state machine running
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
|
||||
}}
|
||||
|
||||
%}}
|
||||
""", file=file)
|
||||
|
||||
|
||||
|
|
@ -181,28 +243,62 @@ colorout:
|
|||
{out_instr} [{cycles_per_pixel-2}]
|
||||
jmp x-- colorout ; Stay here thru horizontal active mode
|
||||
|
||||
.wrap""")
|
||||
.wrap""", file=file)
|
||||
|
||||
print(f"""
|
||||
% c-sdk {{
|
||||
enum {{ {program_name_base}_pixel_clock_khz = {mode.pixel_clock_khz}, {program_name_base}_sys_clock_khz = {cycles_per_pixel * mode.pixel_clock_khz} }};
|
||||
|
||||
static inline void {program_name_base}_program_init(PIO pio, uint sm, uint offset, uint pin, uint n_pin) {{
|
||||
|
||||
pio_sm_config c = {program_name_base}_program_get_default_config(offset);
|
||||
|
||||
// Map the state machine's OUT & SET pins
|
||||
sm_config_set_out_pins(&c, pin, n_pin);
|
||||
sm_config_set_set_pins(&c, pin, n_pin);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
// 15 pixels (30 bits) per word, left is MSB
|
||||
sm_config_set_out_shift(&c, false, true, 30);
|
||||
|
||||
// Set this pin's GPIO function (connect PIO to the pad)
|
||||
for(uint i=0; i<n_pin; i++) {{
|
||||
pio_gpio_init(pio, pin + i);
|
||||
}}
|
||||
// Set the pin direction to output at the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, n_pin, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
// Set the state machine running
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}}
|
||||
|
||||
%}}
|
||||
""", file=file)
|
||||
|
||||
mode_vga_640x480 = VideoMode(25_175, 640, 16, 96, 48, Polarity.Negative, 480, 10, 2, 33, Polarity.Negative)
|
||||
mode_vga_660x480 = change_visible_pixels(mode_vga_640x480, 660)
|
||||
mode_vga_660x480 = change_visible_pixels(mode_vga_640x480, 660, 26_000)
|
||||
|
||||
mode_vga_720x400 = VideoMode(28_321, 720, 18, 108, 54, Polarity.Negative, 400, 10, 2, 36, Polarity.Positive)
|
||||
mode_vga_660x400 = change_visible_pixels(mode_vga_720x400, 660)
|
||||
mode_vga_660x400 = change_visible_pixels(mode_vga_720x400, 660, 26_000)
|
||||
|
||||
if 0:
|
||||
if 1:
|
||||
print(mode_vga_640x480, 6*mode_vga_640x480.pixel_clock_khz)
|
||||
print(mode_vga_660x480, 6*mode_vga_660x480.pixel_clock_khz)
|
||||
|
||||
print(mode_vga_720x400, 6*mode_vga_720x400.pixel_clock_khz)
|
||||
print(mode_vga_660x400, 6*mode_vga_660x400.pixel_clock_khz)
|
||||
|
||||
def print_all(mode, h_divisor=2, out_instr="out pins, 2", cycles_per_pixel=6):
|
||||
def print_all(mode, h_divisor=2, out_instr="out pins, 2", cycles_per_pixel=6, file=sys.stdout):
|
||||
program_name = f"vga_{mode.visible_width}x{mode.visible_height}_{mode.frame_rate_hz:.0f}"
|
||||
print_pio_hsync_program(program_name, mode, h_divisor)
|
||||
print("\n\n\n")
|
||||
print_pio_vsync_program(program_name, mode)
|
||||
print("\n\n\n")
|
||||
print_pio_pixel_program(program_name, mode, out_instr, cycles_per_pixel)
|
||||
print_pio_hsync_program(program_name, mode, h_divisor, cycles_per_pixel, file=file)
|
||||
print("\n\n\n", file=file)
|
||||
print_pio_vsync_program(program_name, mode, cycles_per_pixel, file=file)
|
||||
print("\n\n\n", file=file)
|
||||
print_pio_pixel_program(program_name, mode, out_instr, cycles_per_pixel, file=file)
|
||||
|
||||
print_all(mode_vga_660x480, h_divisor=1)
|
||||
with open("vga_660x480_60.pio", "wt", encoding="utf-8") as f:
|
||||
print_all(mode_vga_660x480, file=f)
|
||||
|
||||
with open("vga_660x400_70.pio", "wt", encoding="utf-8") as f:
|
||||
print_all(mode_vga_660x400, file=f)
|
||||
|
|
|
|||
Loading…
Reference in a new issue