i2cdriver/python/tests/accept.py

361 lines
11 KiB
Python

from __future__ import print_function, division
import sys
import time
import struct
import random
import i2cdriver
import unittest
DUT = "dut" # grn0
AGG = "agg" # blk1
def bit(b, x):
return 1 & (x >> b)
def byte(x):
return struct.pack("B", x)
class TestDUT(unittest.TestCase):
def setUp(self):
self.i2 = i2cdriver.I2CDriver(DUT)
self.ag = i2cdriver.I2CDriver(AGG)
def init(self):
self.i2.reboot()
self.i2.setspeed(400)
self.i2.getstatus()
return self.i2
def lm75_read(self, i, reg):
(tr,) = struct.unpack(">h", i.regrd(0x48, reg, 2))
return tr
def lm75_slow_read(self, i, reg):
i.start(0x48, 0)
i.write(struct.pack("B", reg))
i.start(0x48, 1)
(tr,) = struct.unpack(">h", i.read(2))
i.stop()
return tr
def lm75_write(self, i, reg, v):
i.start(0x48, 0)
i.write(struct.pack(">Bh", reg, v))
i.stop()
def stack0(self):
self.s0 = self.i2.introspect()
def stacksame(self):
s1 = self.i2.introspect()
for i in ("ds", "sp"):
self.assertEqual(self.s0[i], s1[i])
def confirm(self):
# Basic i2c confirmation
self.assertEqual(self.lm75_read(self.i2, 2), 0x4b00)
def confirm_sampling(self):
# Check that analog sampling is happening
econvs = {
"i2cdriver1" : {0,1,2},
"i2cdriverm" : {0}
}[self.i2.product]
s = set()
while len(s) < len(econvs):
s.add(self.i2.introspect()["convs"])
self.assertEqual(s, econvs)
def test_temperature(self):
# Confirm onboard temperature sensor is reasonable and changing
i2 = self.i2
i2.getstatus()
onboard = i2.temp
external = (self.lm75_read(i2, 0) >> 5) * 0.125
self.assertTrue(abs(onboard - external) < 10)
# Wait up to 10 seconds for temperature to change
t0 = time.time()
while onboard == i2.temp:
i2.getstatus()
self.assertTrue(time.time() < (t0 + 10))
def test_coldstart(self):
i2 = self.init()
s = i2.introspect()
self.assertEqual(i2.scl, 1)
self.assertEqual(i2.sda, 1)
def test_scan(self):
i2 = self.init()
def det(a):
r = i2.start(a, 0)
i2.stop()
return r
scan = [det(a) for a in range(128)]
e = [(i == 0x48) for i in range(128)]
self.assertEqual(scan, e)
def test_lm75_reg(self):
i2 = self.i2
self.stack0()
vals = (0, -128, 0x7f80)
for a in vals:
self.lm75_write(i2, 2, a)
for b in vals:
self.lm75_write(i2, 3, b)
self.assertEqual(self.lm75_read(i2, 2), a)
self.assertEqual(self.lm75_read(i2, 3), b)
self.assertEqual(self.lm75_slow_read(i2, 2), a)
self.assertEqual(self.lm75_slow_read(i2, 3), b)
self.lm75_write(i2, 2, 0x4b00)
self.lm75_write(i2, 3, 0x5000)
self.assertEqual(self.lm75_read(i2, 2), 0x4b00)
self.assertEqual(self.lm75_read(i2, 3), 0x5000)
self.stacksame()
def test_regrd256(self):
i2 = self.i2
reg = 3
self.lm75_write(i2, reg, 0x7480)
for n in (127, 128, 129):
self.assertEqual(i2.regrd(0x48, reg, ">" + str(n) + "h"), (0x7480,) * n)
def test_regwr(self):
i2c = self.i2
sa0 = 0x48
wdata = []
lcnt = 16
for i in range(lcnt):
x = random.randint(0, 255)
wdata.append(x)
# print(wdata)
i2c.regwr(sa0, 0x00, wdata)
time.sleep(0.5)
x = i2c.regrd(sa0, 0x00, "<16B")
# print(x)
def test_setspeed(self):
i2 = self.init()
self.stack0()
for s in (100, 400, 400, 100, 400):
i2.setspeed(s)
i2.getstatus()
self.assertEqual(i2.speed, s)
self.confirm()
self.stacksame()
def test_cap_idle(self):
i2 = self.init()
c = i2.capture_start()
t0 = time.time()
d = i2.ser.read(15)
t1 = time.time()
i2.capture_stop()
self.assertEqual(d, b'\x00' * 15)
self.assertTrue(0.4 < (t1 - t0) < 0.6)
def test_cap_0(self):
def test_0():
self.lm75_write(ag, 2, 0x4b00)
return [
i2cdriver.START(0x48, 0, 1),
i2cdriver.BYTE(0x02, 0, True),
i2cdriver.BYTE(0x4b, 0, True),
i2cdriver.BYTE(0x00, 0, True),
i2cdriver.STOP()
]
def test_1():
self.lm75_slow_read(ag, 2)
return [
i2cdriver.START,
(0x90, True),
(0x02, True),
i2cdriver.START,
(0x91, True),
(0x4b, True),
(0x00, False),
i2cdriver.STOP
]
i2 = self.init()
ag = self.ag
for t in (test_0, ): # test_1):
c = i2.capture_start()
time.sleep(.1)
ee = t()
for e,a in zip(ee, c()):
self.assertEqual(a, e)
i2.capture_stop()
def test_pullups(self):
i2 = self.init()
i2.getstatus()
self.assertEqual(i2.pullups, 0b100100)
rr = random.sample(list(range(64)), 64)
if i2.product == "i2cdriver1":
respins = (0, 1, 3, 13, 14, 16)
else:
respins = (10, 11, 12, 6, 7, 8)
for r in rr:
i2.setpullups(r)
i2.getstatus()
self.assertEqual(i2.pullups, r)
s = i2.introspect()
p = s["P0"] + (s["P1"] << 8) + (s["P2"] << 16)
d = s["P0MDOUT"] + (s["P1MDOUT"] << 8) + (s["P2MDOUT"] << 16)
for b,pb in enumerate(respins):
self.assertEqual(bit(pb, p), 1)
self.assertEqual(bit(b, r), bit(pb, d))
def test_zz5s(self):
i2 = self.init()
time.sleep(5)
i2.getstatus()
self.assertTrue(i2.uptime in (4,5,6))
def checkmode(self, c):
self.i2.getstatus()
self.assertEqual(self.i2.mode, c)
def test_bitbang(self):
i2 = self.init()
self.checkmode('I')
self.stack0()
i2.ser.write(b'b')
for i in range(1000): # Square wave for a while
i2.ser.write(byte(0b1111) + byte(0b0101))
i2.ser.write(byte(0b1010) + byte(0b11010)) # Float, request a byte
self.assertEqual(struct.unpack("B", i2.ser.read(1)), (3, )) # both should be high
i2.ser.write(byte(0b0101)) # Leave driven low
i2.ser.write(b'@')
self.checkmode('B')
i2.restore()
self.checkmode('I')
self.stacksame()
self.assertEqual(self.lm75_read(i2, 2), 0x4b00)
def test_bitbang_idem(self):
# Confirm bitbang mode idempotence
i2 = self.init()
if i2.product != "spidriver1":
return
for n in [0b1101, 0b1011, 0b0000, 0b1111] + list(range(16)):
i2.ser.write(b'b' + byte(n) + byte(0x40))
s1 = i2.introspect()
self.assertEqual(bit(0, n), bit(2, s1["P0MDOUT"]))
self.assertEqual(bit(1, n), bit(2, s1["P0"]))
self.assertEqual(bit(2, n), bit(4, s1["P1MDOUT"]))
self.assertEqual(bit(3, n), bit(4, s1["P1"]))
i2.ser.write(b'b' + byte(0x40))
s2 = i2.introspect()
for i in ("P0", "P1", "P0MDOUT", "P1MDOUT"):
self.assertEqual(s1[i], s2[i])
self.assertEqual(i2.introspect()["SMB0CF"], 0x00)
i2.restore()
self.assertEqual(i2.introspect()["SMB0CF"], 0xd8)
def test_bitbang_bidir(self):
self.stack0()
dd = (self.i2, self.ag)
[i2.ser.write(b'b') for i2 in dd]
LOW = 0b01
HIGH = 0b11
INPUT = 0b10
def port(d, sda, scl, read = False):
d.ser.write(byte(sda | (scl << 2) | (int(read) << 4)))
if read:
(r,) = struct.unpack("B", d.ser.read(1))
return (r & 1, (r >> 1) & 1)
for sda in (LOW, HIGH, LOW):
for scl in (HIGH, LOW, HIGH):
expected = (int(sda == HIGH), int(scl == HIGH))
for (tx,rx) in [(0,1), (1,0)]:
port(dd[tx], sda, scl)
port(dd[rx], INPUT, INPUT)
self.assertEqual(expected, port(dd[rx], INPUT, INPUT, True))
[i2.ser.write(b'@') for i2 in dd]
[i2.restore() for i2 in dd]
self.stacksame()
def test_reset(self):
i2 = self.init()
self.stack0()
i2.reset()
self.stacksame()
for i in range(100):
i2.reset()
self.stacksame()
self.confirm()
def test_sampling(self):
self.confirm_sampling()
def test_weigh(self):
# Confirm resistance measurement
i2 = self.init()
ag = self.ag
self.stack0()
def sample(p, pv):
i2.setpullups(p)
i2.ser.write(b'v' + byte(pv))
while True:
i2.ser.write(b'w')
r = struct.unpack("B", i2.ser.read(1))
if r[0] == 0:
break
return struct.unpack("2B", i2.ser.read(2))
def estimate(a, hi, res):
if a == 0:
return 0
v = a / hi
return (res / v) - res
def mean(s):
return sum(s) / len(s)
def resistance(rr):
if rr == []:
return 0
return 1 / sum([1/r for r in rr])
def pullups():
sHH = sample(0b111111, 0b111111)
sAA = sample(0b001001, 0b110110)
sBB = sample(0b010010, 0b101101)
sCC = sample(0b100100, 0b011011)
sda_r = mean((estimate(sAA[0], sHH[0], 2200),
estimate(sBB[0], sHH[0], 4300),
estimate(sCC[0], sHH[0], 4700)))
scl_r = mean((estimate(sAA[1], sHH[1], 2200),
estimate(sBB[1], sHH[1], 4300),
estimate(sCC[1], sHH[1], 4700)))
return (sda_r, scl_r)
for x in range(64):
# print(x)
ag.setpullups(x)
esda = resistance([r for i,r in enumerate([2200, 4300, 4700]) if bit(i, x)])
escl = resistance([r for i,r in enumerate([2200, 4300, 4700]) if bit(3 + i, x)])
# print("expected %d" % esda, escl)
sda,scl = pullups()
# print("SDA pullup %d, SCL pullup %d" % (sda,scl))
def close(e, a):
margin = max(100, e / 10)
return abs(a - e) < margin
self.assertTrue(close(esda, sda))
self.assertTrue(close(escl, scl))
self.confirm_sampling()
self.init() # restore pullups
if __name__ == '__main__':
unittest.main()