最初に見たティム・バートンの作品はシザー・ハンドだったと思う。ジョニー・ディップの怪演も魅力的であったが何よりストーリーが素晴らしかった。その後「The Nightmare Before Christmas」の DVD を購入するも、この時期に見ないと意味がない気がしてDVD はほこりをかぶったままだ。先生も走る時期にはなかなか DVD をゆっくり見る時間が取れない。
秋葉原で容易に入手可能な LIS3DH という3軸加速度センサと連携してみよう。SPI との連携はすでに書いている。
spi_lis3dh.py
import polyphony
from polyphony.io import Port
from polyphony.typing import bit, uint3, uint12, uint24
from polyphony.timing import clksleep, clkfence, wait_rising, wait_falling
CONVST_PULSE_CYCLE = 10
CONVERSION_CYCLE = 39
@polyphony.module
class spi_lis3dh:
def __init__(self):
self.sclk = Port(bit, 'out')
self.mosi = Port(bit, 'out')
self.miso = Port(bit, 'in')
self.cs_n = Port(bit, 'out', init=1)
self.x_led = Port(bit, 'out')
self.y_led = Port(bit, 'out')
self.z_led = Port(bit, 'out')
self.data24 = Port(uint24, 'out', protocol='ready_valid')
self.append_worker(self.worker)
def set_addr(self, rw, ms, addr):
clksleep(1)
self.sclk.wr(0)
self.mosi.wr(rw)
clksleep(2)
self.sclk.wr(1)
clksleep(2)
self.sclk.wr(0)
self.mosi.wr(ms)
clksleep(2)
self.sclk.wr(1)
clksleep(2)
self.sclk.wr(0)
for i in range(6):
bit1 = (addr >> (5 - i)) & 1
self.mosi.wr(bit1)
clksleep(1)
self.sclk.wr(1)
clksleep(1)
self.sclk.wr(0)
clksleep(1)
def read_data(self, addr):
self.cs_n.wr(0)
self.sclk.wr(0)
clksleep(1)
self.set_addr(1, 0, addr)
data = 0
for i in range(8):
data <<= 1
clksleep(1)
self.sclk.wr(1)
clksleep(1)
bit1 = self.miso.rd() & 1
clkfence()
self.sclk.wr(0)
data |= bit1
clksleep(1)
self.cs_n.wr(1)
return data
def write_data(self, addr, data):
self.cs_n.wr(0)
self.sclk.wr(0)
clksleep(1)
self.set_addr(0, 0, addr)
for i in range(8):
bit1 = (data >> (7 - i)) & 1
self.mosi.wr(bit1)
clksleep(1)
self.sclk.wr(1)
clksleep(1)
self.sclk.wr(0)
clksleep(2)
self.cs_n.wr(1)
self.mosi.wr(0)
return data
def worker(self):
self.cs_n.wr(1)
self.sclk.wr(0)
clksleep(1)
self.write_data(0x20, 0x7F)
while polyphony.is_worker_running():
clksleep(20)
self.write_data(0x20, 0x7F)
clksleep(10)
data_who_am_i = self.read_data(0x0F)
clksleep(10)
data_x_l = self.read_data(0x29)
clksleep(10)
data_y_l = self.read_data(0x2B)
clksleep(10)
data_z_l = self.read_data(0x2D)
clksleep(10)
self.x_led.wr(1 if data_x_l > 0x30 else 0)
self.y_led.wr(1 if data_y_l > 0x30 else 0)
self.z_led.wr(1 if data_z_l > 0x30 else 0)
data_xyz = ( data_x_l << 16 ) | ( data_y_l << 8 ) | data_z_l
self.data24.wr(data_xyz)
@polyphony.testbench
def test(spic):
data = spic.data24.rd()
print("data0:" , data)
data = spic.data24.rd()
print("data1:" , data)
if __name__ == '__main__':
spic = spi_lis3dh()
test(spic)
Arty Z7 などにつなぐことで加速度センサからの情報を見て LED を光らせることが出来る。
肝となる関数は read_data と write_data そしてそこからよばれるset_addr であろう。SPI の sclk, mosi, miso, cs_n をコントロールしてLIS3DH とやりとりをする。
直接 SPI でやりとりしており CPU を介していないところが特徴だ。例えば加速度センサーを4つつけてもすべて(ほぼ)同じクロックで実行することが可能だろう。
SPI の信号線はタイミング制御があるのでソース上にはclksleep や clksleep が散在する結果となっている。この辺りはもう少し簡潔にかけるようにすべきなのだろう。