Skip to content

Commit ce24611

Browse files
committed
Code for the xerox 820 to digital video project
1 parent 96ed6bf commit ce24611

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

  • CircuitPython_Feather_DVI_Xerox_820
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# SPDX-FileCopyrightText: 2024 Jeff Epler for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
import array
6+
7+
import ulab
8+
import rp2pio
9+
import board
10+
import adafruit_pioasm
11+
import picodvi
12+
import displayio
13+
14+
vdata = board.D9 # Followed by hsync on D10 & vsync on D11
15+
pixel_sync_out = board.D5
16+
pixel_frequency = 10_694_250 # oddly specific
17+
clocks_per_pixel = 10
18+
fine_pixel = 0
19+
active_lines = 240
20+
blanking_lines = 18
21+
active_pixels = 640
22+
blanking_pixels = 58
23+
total_lines = active_lines + blanking_lines
24+
25+
displayio.release_displays()
26+
27+
dvi_pins = dict(
28+
clk_dp=board.CKP,
29+
clk_dn=board.CKN,
30+
red_dp=board.D0P,
31+
red_dn=board.D0N,
32+
green_dp=board.D1P,
33+
green_dn=board.D1N,
34+
blue_dp=board.D2P,
35+
blue_dn=board.D2N,
36+
)
37+
38+
try:
39+
dvi = picodvi.Framebuffer(640, 240, **dvi_pins, color_depth=1)
40+
except ValueError:
41+
print(
42+
"Note: This version of CircuitPython does not support 640x240\n."
43+
"Display will be compressed vertically."
44+
)
45+
displayio.release_displays()
46+
dvi = picodvi.Framebuffer(640, 480, **dvi_pins, color_depth=1)
47+
48+
# Clear the display
49+
ulab.numpy.frombuffer(dvi, dtype=ulab.numpy.uint8)[:] = 0
50+
51+
def instruction_gen():
52+
yield total_lines - 2
53+
for _ in range(blanking_lines):
54+
yield from (1, 0) # 0 active pixels is special-cased
55+
for _ in range(active_lines):
56+
yield from (blanking_pixels - 1, active_pixels - 1)
57+
58+
59+
instruction = array.array("L", instruction_gen())
60+
print(instruction)
61+
62+
jmp_0 = adafruit_pioasm.Program("jmp 0")
63+
64+
program = adafruit_pioasm.Program(
65+
f"""
66+
.side_set 1
67+
68+
.wrap_target
69+
out y, 32 ; get total line count
70+
wait 0, pin 2
71+
wait 1, pin 2 ; wait for vsync
72+
73+
wait_line_inactive:
74+
out x, 32 ; get total line count
75+
wait 0, pin 1
76+
wait 1, pin 1; wait for hsync
77+
78+
wait_line_active:
79+
nop [{clocks_per_pixel-2}]
80+
jmp x--, wait_line_active ; count off non-active pixels
81+
82+
out x, 32 [{fine_pixel}] ; get line active pixels & perform fine pixel adjust
83+
jmp !x, wait_line_inactive ; no pixels this line, wait next hsync
84+
85+
capture_active_pixels:
86+
in pins, 1 side 1
87+
jmp x--, capture_active_pixels [{clocks_per_pixel-2}] ; more pixels
88+
jmp y--, wait_line_inactive ; more lines?
89+
.wrap
90+
"""
91+
)
92+
93+
pio = rp2pio.StateMachine(
94+
program.assembled,
95+
frequency=pixel_frequency * clocks_per_pixel,
96+
first_in_pin=vdata,
97+
in_pin_count=3,
98+
# in_pin_pull_up=True,
99+
first_sideset_pin=pixel_sync_out,
100+
auto_pull=True,
101+
pull_threshold=32,
102+
auto_push=True,
103+
push_threshold=32,
104+
offset=0,
105+
**program.pio_kwargs,
106+
)
107+
108+
words_per_row = 640 // 32
109+
first_row = (dvi.height - 240) // 2 # adjust text to center if in 640x480 mode
110+
buf = memoryview(dvi).cast("L")[
111+
first_row * words_per_row : (first_row + active_lines) * words_per_row
112+
]
113+
assert len(buf) == 4800 # Check that the right amount will be transferred
114+
115+
b = array.array("L", [0])
116+
117+
while True:
118+
pio.run(jmp_0.assembled)
119+
pio.clear_rxfifo()
120+
pio.write_readinto(instruction, buf)

0 commit comments

Comments
 (0)