Skip to content

Commit 9bc2b20

Browse files
committed
Refactor display driver folder
Split HM01B0 driver into multiple files for easier addition of other cameras and interfaces
1 parent a34c4e9 commit 9bc2b20

File tree

5 files changed

+422
-341
lines changed

5 files changed

+422
-341
lines changed

cv2_drivers/cameras/cv2_camera.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from ulab import numpy as np
2+
3+
class CV2_Camera():
4+
def __init__(self, buffer_size):
5+
self.buffer = np.zeros(buffer_size, dtype=np.uint8)

cv2_drivers/cameras/dvp_camera.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from .cv2_camera import CV2_Camera
2+
from machine import Pin
3+
from time import sleep_us
4+
5+
class DVP_Camera(CV2_Camera):
6+
def __init__(
7+
self,
8+
i2c,
9+
i2c_address,
10+
buffer_size
11+
):
12+
super().__init__(buffer_size)
13+
14+
self.i2c = i2c
15+
self.i2c_address = i2c_address
16+
17+
def readRegister(self, reg, nbytes=1):
18+
self.i2c.writeto(self.i2c_address, bytes([reg >> 8, reg & 0xFF]))
19+
return self.i2c.readfrom(self.i2c_address, nbytes)
20+
21+
def writeRegister(self, reg, data):
22+
if isinstance(data, int):
23+
data = bytes([data])
24+
elif isinstance(data, (list, tuple)):
25+
data = bytes(data)
26+
self.i2c.writeto(self.i2c_address, bytes([reg >> 8, reg & 0xFF]) + data)

cv2_drivers/cameras/dvp_rp2_pio.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import rp2
2+
from machine import Pin, PWM
3+
4+
class DVP_RP2_PIO():
5+
def __init__(
6+
self,
7+
pin_d0,
8+
pin_vsync,
9+
pin_hsync,
10+
pin_pclk,
11+
pin_xclk,
12+
sm_id,
13+
num_data_pins
14+
):
15+
self.pin_d0 = pin_d0
16+
self.pin_vsync = pin_vsync
17+
self.pin_hsync = pin_hsync
18+
self.pin_pclk = pin_pclk
19+
self.pin_xclk = pin_xclk
20+
self.sm_id = sm_id
21+
22+
for i in range(num_data_pins):
23+
Pin(pin_d0+i, Pin.IN)
24+
Pin(pin_vsync, Pin.IN)
25+
Pin(pin_hsync, Pin.IN)
26+
Pin(pin_pclk, Pin.IN)
27+
28+
if self.pin_xclk is not None:
29+
self.xclk = PWM(Pin(pin_xclk))
30+
# self.xclk.freq(25_000_000)
31+
self.xclk.freq(15_000_000)
32+
self.xclk.duty_u16(32768)
33+
34+
self.start_pio_dma(num_data_pins)
35+
36+
def start_pio_dma(self, num_data_pins):
37+
program = self._pio_read_dvp
38+
# Mask in the GPIO pins
39+
program[0][0] |= self.pin_hsync & 0x1F
40+
program[0][1] |= self.pin_pclk & 0x1F
41+
program[0][3] |= self.pin_pclk & 0x1F
42+
43+
# Mask in the number of data pins
44+
program[0][2] &= 0xFFFFFFE0
45+
program[0][2] |= num_data_pins
46+
47+
self.sm = rp2.StateMachine(
48+
self.sm_id,
49+
program,
50+
in_base = self.pin_d0
51+
)
52+
self.sm.active(1)
53+
54+
self.dma = rp2.DMA()
55+
req_num = ((self.sm_id // 4) << 3) + (self.sm_id % 4) + 4
56+
dma_ctrl = self.dma.pack_ctrl(
57+
# size = 2, # 0 = 8-bit, 1 = 16-bit, 2 = 32-bit
58+
size = 2, # 0 = 8-bit, 1 = 16-bit, 2 = 32-bit
59+
inc_read = False,
60+
treq_sel = req_num,
61+
bswap = False
62+
# irq_quiet = False
63+
)
64+
self.dma.config(
65+
read = self.sm,
66+
# count = 244 * 324 // 4,
67+
count = 240 * 320 * 2 // 4,
68+
ctrl = dma_ctrl
69+
)
70+
71+
def active(self, active = None):
72+
if active == None:
73+
return self.sm.active()
74+
75+
self.sm.active(active)
76+
77+
if active:
78+
Pin(self.pin_vsync).irq(
79+
trigger = Pin.IRQ_FALLING,
80+
handler = lambda pin: self._vsync_handler()
81+
)
82+
else:
83+
Pin(self.pin_vsync).irq(
84+
handler = None
85+
)
86+
87+
def _vsync_handler(self):
88+
# print("VSYNC")
89+
# Disable DMA before reconfiguring it
90+
self.dma.active(False)
91+
92+
# Reset state machine to ensure ISR is cleared
93+
self.sm.restart()
94+
95+
# Ensure PIO RX FIFO is empty (it's not emptied by `sm.restart()`)
96+
while self.sm.rx_fifo() > 0:
97+
self.sm.get()
98+
99+
# Reset the DMA write address
100+
self.dma.write = self.buffer
101+
102+
# Start the DMA
103+
self.dma.active(True)
104+
105+
@rp2.asm_pio(
106+
in_shiftdir = rp2.PIO.SHIFT_LEFT,
107+
push_thresh = 32,
108+
autopush = True,
109+
fifo_join = rp2.PIO.JOIN_RX
110+
)
111+
def _pio_read_dvp():
112+
wait(1, gpio, 0) # Mask in HSYNC pin
113+
wait(1, gpio, 0) # Mask in PCLK pin
114+
in_(pins, 1) # Mask in number of pins
115+
wait(0, gpio, 0) # Mask in PCLK pin

0 commit comments

Comments
 (0)