Posted at

Python で FPGA/I2C を使う(Zybo Z7編)


Zybo Z7 にラズパイカメラをつなげる

Zybo Z7 にはラズパイカメラ用の端子があるのでそこにラズパイカメラをつなげます。そしてその先にある I2C の通信をしてみます。


I2C Master

I2C Master はすでにあるものとします。長いので gist に置いておきます。

https://gist.github.com/ryos36/57bfac8a39fac9d18a1dcfcabbc558f6

これを使えば I2C との通信が簡単にできます。


IMX219 と通信

デバッグ用に write_hex16 というライブラリを使ってますが、これは本質的になくてもよいものです。imx219_init_data にデータが入っていて、ここにあるデータを次々と出力します。


imx219_go.py

from polyphony import testbench

from polyphony import rule
from polyphony import module
from polyphony.typing import bit, bit8, bit16
from polyphony.io import Queue, Port
from polyphony import is_worker_running
from polyphony.timing import clksleep, wait_value, clkfence

from i2c_master import i2c_master
from i2c_master import READ_REG_CMD, WRITE_REG_CMD
from i2c_master import READ_CMD, WRITE_CMD

from write_hex16 import write_hex16, write_ln

from imx219_init_data import INIT_DATA_MODE1, INIT_DATA_MODE7

IMX219_ADDR=0x10

@module
class imx219_go:

def __init__(self):
self.i2c = i2c_master()

self.kick_in = Port(bit, 'in')
self.done = Port(bit, 'out', init=0)
self.re_flush_in = Port(bit, 'in')

self.cam_clk = Port(bit, 'out')
self.cam_gpio = Port(bit, 'out')

self.debug_print_q = Queue(bit8, 'out')

self.append_worker(self.worker)

def read_reg(self, reg_addr:bit16) -> bit8:
self.i2c.cmd_q.wr(READ_REG_CMD)
self.i2c.cmd_q.wr(IMX219_ADDR)
reg_addr_shift8:bit16 = (reg_addr >> 8)
self.i2c.cmd_q.wr(reg_addr_shift8 & 0xFF)
self.i2c.cmd_q.wr(reg_addr & 0xFF)

res = self.i2c.res_q.rd()
data = self.i2c.res_q.rd()
return data

def write_reg(self, reg_addr:bit16, data:bit8):
self.i2c.cmd_q.wr(WRITE_REG_CMD)
self.i2c.cmd_q.wr(IMX219_ADDR)
reg_addr_shift8:bit16 = (reg_addr >> 8)
self.i2c.cmd_q.wr(reg_addr_shift8 & 0xFF)
self.i2c.cmd_q.wr(reg_addr & 0xFF)
self.i2c.cmd_q.wr(data)

res = self.i2c.res_q.rd()

def test_read_code(self):
data:bit8 = self.read_reg(0)
write_hex16(self.debug_print_q, data)

data = self.read_reg(1)
write_hex16(self.debug_print_q, data)
write_ln(self.debug_print_q)

def test_imx218_0x0114(self):
self.write_reg(0x0114, 1)

data:bit8 = self.read_reg(0x0114)
write_hex16(self.debug_print_q, data)
write_ln(self.debug_print_q)

def print_hex(self, addr:bit16, data:bit8):
write_hex16(self.debug_print_q, addr >> 8)
write_hex16(self.debug_print_q, addr & 0xFF)
self.debug_print_q(0x20)
write_hex16(self.debug_print_q, data)
write_ln(self.debug_print_q)

def init_code(self):
init_data = INIT_DATA_MODE7
for i in range(0, len(init_data), 2):
addr:bit16 = init_data[i + 0]
data:bit8 = init_data[i + 1]
self.write_reg(addr, data)
self.print_hex(addr, data)

def worker(self):
res:bit8 = 0

self.done.wr(0)
self.cam_gpio.wr(1)
self.cam_clk.wr(1)

b:bit = self.kick_in.rd()
b = self.re_flush_in.rd()

while is_worker_running():
wait_value(1, self.kick_in)

self.test_read_code()
self.test_imx218_0x0114()

self.init_code()

self.done.wr(1)
wait_value(1, self.re_flush_in)
self.done.wr(0)

@testbench
def test(m):
d:bit8 = 0
d = m.debug_print_q.rd()
print("model_id[15:8]:", d)
d = m.debug_print_q.rd()
print("model_id[7:0]", d)
print('Finished')

if __name__ == '__main__':
m = imx219_go()
test(m)



データは Python のリスト

これは Linux の imx219_modes.h からひっぱってきました。アドレスとデータの組になっています。


imx219_init_data.py

INIT_DATA_MODE1 = [

0x0100, 0x00,
中略
0x015a, 0x00,
0x015b, 0x31,
0x0100, 0x01
]

INIT_DATA_MODE7 = [
0x0100, 0x00,
中略
0x015a, 0x00,
0x015b, 0x2f,
0x0100, 0x01
]



動かしてみると、、、

image.png

波形はどうよ?できたっぽい。

image.png