Skip to content

Commit 73de790

Browse files
committed
Add supporting code (runs on PC, not device)
1 parent 30ba5db commit 73de790

File tree

13 files changed

+1458
-0
lines changed

13 files changed

+1458
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.micropico
22
.vscode/
3+
dnd-gadget.code-workspace
3.97 KB
Binary file not shown.
4.09 KB
Binary file not shown.

Supporting Code/blit_onto.png

28.3 KB
Loading

Supporting Code/driver.old.py

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# Old (non-viper) e-ink send functions
2+
# Replaced with viper as of 21 Feb 2025
3+
4+
# Send with landscape rotation
5+
# Slow (2.5s) without Viper. Also doesn't support rot3.
6+
def _send_land(self):
7+
8+
if self.rot == 3:
9+
raise NotImplementedError('Rotation #3 not implemented yet')
10+
return
11+
12+
# Output commands
13+
cmd = bytes([ 0x10, 0x13 ])
14+
15+
# Temporary store for byte values. Avoids repeated in-loop memory allocation.
16+
out = bytearray(1)
17+
18+
# For speed, cache locally all global variables that we'll need in the loop
19+
fb = self.fb.buf
20+
spi_w = self.spi.write
21+
22+
# Input byte width, input height
23+
ibw = self.width // 4
24+
ih = self.height
25+
26+
# Having these as elements of a bytearray makes things worse, for some reason
27+
col=0
28+
bit=0
29+
30+
# Set these up ahead of time
31+
rx = range(self.width)
32+
r1 = range(ibw)
33+
r2 = range(4)
34+
ry = range( 0, ih, 8 )
35+
36+
# Do everything once per colour
37+
for c in (0,1):
38+
39+
# Send data command (black/red)
40+
self._send_command( cmd[c] )
41+
42+
# Prepare for transmission
43+
self.DC(1)
44+
self.CS(0)
45+
46+
'''
47+
Input is always in rows of bytes
48+
Each byte is 4 pixels (2 bits per pixel)
49+
1-byte columns of the input image will be 4 pixels wide
50+
These columns will correspond to rows of the output image
51+
'''
52+
53+
'''
54+
# Go column by column over the source image
55+
for x in rx:
56+
57+
# Split x into the byte-column we're in (col) and the pixel within that (bit)
58+
# col = x // 4
59+
col = x>>2
60+
61+
# Convert bit from pixel position to bit position
62+
# bit = ( (x % 4 ) *2 ) +c
63+
bit = ((x&3)<<1)|c
64+
65+
# Go up the columns, 8 rows at a time
66+
for y in ry:
67+
out[0] = (
68+
((( fb[ (ibw*(ih-y-1)) + col ] & (1<<bit) ) >> bit )<<7) |
69+
((( fb[ (ibw*(ih-y-2)) + col ] & (1<<bit) ) >> bit )<<6) |
70+
((( fb[ (ibw*(ih-y-3)) + col ] & (1<<bit) ) >> bit )<<5) |
71+
((( fb[ (ibw*(ih-y-4)) + col ] & (1<<bit) ) >> bit )<<4) |
72+
((( fb[ (ibw*(ih-y-5)) + col ] & (1<<bit) ) >> bit )<<3) |
73+
((( fb[ (ibw*(ih-y-6)) + col ] & (1<<bit) ) >> bit )<<2) |
74+
((( fb[ (ibw*(ih-y-7)) + col ] & (1<<bit) ) >> bit )<<1) |
75+
((( fb[ (ibw*(ih-y-8)) + col ] & (1<<bit) ) >> bit ) )
76+
)
77+
spi_w( out )
78+
'''
79+
80+
# Input image, columns of 4 pixels, aka columns of bytes
81+
for col in r1:
82+
83+
# Input image, columns of single pixels
84+
for incol in r2:
85+
86+
# Select which bit from each byte we'll need
87+
#bit = (incol*2) +c
88+
bit = (incol<<1) | c
89+
90+
# Input image, every 8th row is the start of an output byte
91+
for y in ry:
92+
93+
# Select from framebuffer:
94+
# ( Input byte width * row of interest ) + column offset
95+
# AND with 2^bit
96+
# RSHIFT back down to zero or 1
97+
# LSHIFT to correct position within output byte
98+
# OR all 8 together
99+
out[0] = (
100+
((( fb[ (ibw*(ih-y-1)) + col ] & (1<<bit) ) >> bit )<<7) |
101+
((( fb[ (ibw*(ih-y-2)) + col ] & (1<<bit) ) >> bit )<<6) |
102+
((( fb[ (ibw*(ih-y-3)) + col ] & (1<<bit) ) >> bit )<<5) |
103+
((( fb[ (ibw*(ih-y-4)) + col ] & (1<<bit) ) >> bit )<<4) |
104+
((( fb[ (ibw*(ih-y-5)) + col ] & (1<<bit) ) >> bit )<<3) |
105+
((( fb[ (ibw*(ih-y-6)) + col ] & (1<<bit) ) >> bit )<<2) |
106+
((( fb[ (ibw*(ih-y-7)) + col ] & (1<<bit) ) >> bit )<<1) |
107+
((( fb[ (ibw*(ih-y-8)) + col ] & (1<<bit) ) >> bit ) )
108+
)
109+
spi_w( out )
110+
111+
112+
# End transmission
113+
self.CS(1)
114+
115+
# Tidy up memory
116+
del cmd, out, fb, spi_w
117+
#del ibw, ih, c, col, incol, bit, row
118+
#del ibw, ih, c, col, x
119+
gc.collect()
120+
121+
# Send with portrait rotation
122+
@micropython.native
123+
def _send_port(self):
124+
125+
# How to locate a 2-bit pixel in the buffer for a given rotation
126+
'''
127+
buflen = len(self.fb.buf)
128+
locator = [
129+
# ( self.fb.buf[ (i*2) + (j//4) ] >> ((j%4)*2 ) ) & 3
130+
lambda i, j : ( self.fb.buf[ (i<<1) + (j>>2) ] >> ((j&3)<<1) ) & 3, # Zero rotation (portrait)
131+
lambda i, j : 0,
132+
lambda i, j : ( self.fb.buf[ buflen-(i<<1)-(j>>2)-1 ] >> ((3-(j&3))<<1) ) & 3, # 180,
133+
lambda i, j : 0,
134+
][self.rot]
135+
'''
136+
137+
# Output commands
138+
cmd = bytes([ 0x10, 0x13 ])
139+
140+
# Temporary store for byte values. Avoids repeated in-loop memory allocation.
141+
out = bytearray(1)
142+
143+
# For speed, cache locally all global variables that we'll need in the loop
144+
fb = self.fb.buf
145+
spi_w = self.spi.write
146+
147+
# Range object and byte decoders for loop
148+
if self.rot == 0:
149+
r = range( 0, self.kr_fb_size * 2, 2 )
150+
nybble = [
151+
lambda b : (b&64)>>6 | (b&16)>>3 | (b&4) | (b&1)<<3, # black
152+
lambda b : (b&128)>>7 | (b&32)>>4 | (b&8)>>1 | (b&2)<<2, # red
153+
]
154+
ob = lambda i, n : ( n( fb[i] ) << 4 ) | ( n( fb[i+1] ) ) # Output byte
155+
elif self.rot == 2:
156+
r = range( self.kr_fb_size*2-1, -1, -2 )
157+
nybble = [
158+
lambda b : (b&64)>>3 | (b&16)>>2 | (b&4)>>1 | (b&1), # black
159+
lambda b : (b&128)>>4 | (b&32)>>3 | (b&8)>>2 | (b&2)>>1, # red
160+
]
161+
ob = lambda i, n : ( n( fb[i] ) << 4 ) | ( n( fb[i-1] ) ) # Output byte
162+
else:
163+
raise NotImplementedError('Landscape modes not supported yet')
164+
165+
# Do once per colour
166+
for c in (1,2):
167+
168+
# Send data command (black/red)
169+
self._send_command( cmd[c-1] )
170+
171+
# Prepare for transmission
172+
self.DC(1)
173+
self.CS(0)
174+
175+
# Which nybble do we need?
176+
n = nybble[c-1]
177+
178+
# Step through each byte of the (red or black) output
179+
for i in r:
180+
181+
# Get two nybbles and compose them into one byte for monochrome output
182+
#print(
183+
out[0] = ob( i, n )
184+
#print(hex(out[0]))
185+
#print( nybble[1]( self.fb.buf[2*i] ) << 4 )
186+
#print( nybble[1]( self.fb.buf[(2*i)+1] ) )
187+
#return
188+
189+
# Send the byte
190+
spi_w( out )
191+
192+
# End transmission
193+
self.CS(1)
194+

0 commit comments

Comments
 (0)