Repository navigation
Expand file tree
/
Copy pathtest_i2c.py
More file actions
161 lines (116 loc) · 4.57 KB
/
Copy pathtest_i2c.py
File metadata and controls
161 lines (116 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import os
import random
import sys
import time
import periphery
from .test import ptest, pokay, passert, AssertRaises
if sys.version_info[0] == 3:
raw_input = input
i2c_devpath = None
i2c_eeprom_addr = 0x51
def test_arguments():
ptest()
# Open with invalid type
with AssertRaises("open invalid type", TypeError):
periphery.I2C(123)
def test_open_close():
ptest()
# Open non-existent device
with AssertRaises("non-existent device", periphery.I2CError):
periphery.I2C("/foo/bar")
# Open legitimate device
i2c = periphery.I2C(i2c_devpath)
passert("fd >= 0", i2c.fd >= 0)
# Close I2C
i2c.close()
def test_loopback():
ptest()
# Generate random byte vector
vector = [random.randint(0, 255) for _ in range(32)]
i2c = periphery.I2C(i2c_devpath)
# Write vector to 0x100 with list
# S [ addr W ] [ 0x01 ] [ 0x00 ] [ Data... ] P
msgs = [periphery.I2C.Message([0x01, 0x00] + vector)]
i2c.transfer(i2c_eeprom_addr, msgs)
# Wait for write cycle
time.sleep(0.01)
# Read from 0x100 with list
# S [ addr W ] [ 0x01 ] [ 0x00 ] S [ addr R ] [ Data... ] P
msgs = [periphery.I2C.Message([0x01, 0x00]), periphery.I2C.Message([0x00] * 32, read=True)]
i2c.transfer(i2c_eeprom_addr, msgs)
# Verify bytes
passert("verify bytes", msgs[1].data == vector)
# Write vector to 0x200 with bytes
# S [ addr W ] [ 0x02 ] [ 0x00 ] [ Data... ] P
msgs = [periphery.I2C.Message(b"\x02\x00" + bytes(vector))]
i2c.transfer(i2c_eeprom_addr, msgs)
# Wait for write cycle
time.sleep(0.01)
# Read from 0x200 with bytes
# S [ addr W ] [ 0x02 ] [ 0x00 ] S [ addr R ] [ Data... ] P
msgs = [periphery.I2C.Message(b"\x02\x00"), periphery.I2C.Message(b"\x00" * 32, read=True)]
i2c.transfer(i2c_eeprom_addr, msgs)
# Verify bytes
passert("verify bytes", msgs[1].data == bytes(vector))
# Read from 0x110 with bytearray, in-place
buf = bytearray(16)
msgs = [periphery.I2C.Message(bytearray([0x01, 0x10])), periphery.I2C.Message(buf, read=True)]
i2c.transfer(i2c_eeprom_addr, msgs, inplace=True)
# Verify bytes
passert("verify in-place readback", msgs[1].data == bytearray(vector[0x10:]))
passert("verify in-place readback id", msgs[1].data is buf)
i2c.close()
print("Loopback test passed.")
def test_interactive():
ptest()
# Open device 2
i2c = periphery.I2C(i2c_devpath)
print("")
print("Starting interactive test. Get out your logic analyzer, buddy!")
raw_input("Press enter to continue...")
# Check tostring
print("I2C description: {}".format(str(i2c)))
passert("interactive success", raw_input("I2C description looks ok? y/n ") == "y")
# There isn't much we can do without assuming a device on the other end,
# because I2C needs an acknowledgement bit on each transferred byte.
#
# But we can send a transaction and expect it to time out.
# S [ 0x7a W ] [0xaa] [0xbb] [0xcc] [0xdd] NA
messages = [periphery.I2C.Message([0xaa, 0xbb, 0xcc, 0xdd])]
raw_input("Press enter to start transfer...")
# Transfer to non-existent device
with AssertRaises("transfer to non-existent device", periphery.I2CError):
i2c.transfer(0x7a, messages)
i2c.close()
success = raw_input("I2C transfer occurred? y/n ")
passert("interactive success", success == "y")
if __name__ == "__main__":
if os.environ.get("CI") == "true":
test_arguments()
sys.exit(0)
if len(sys.argv) < 2:
print("Usage: python -m tests.test_i2c <I2C device>")
print("")
print("[1/4] Arguments test: No requirements.")
print("[2/4] Open/close test: I2C device should be real.")
print("[3/4] Loopback test: Expects 24XX32 EEPROM (or similar) at address 0x51.")
print("[4/4] Interactive test: I2C bus should be observed with an oscilloscope or logic analyzer.")
print("")
print("Hint: for Raspberry Pi 3, enable I2C1 with:")
print(" $ echo \"dtparam=i2c_arm=on\" | sudo tee -a /boot/config.txt")
print(" $ sudo reboot")
print("Use pins I2C1 SDA (header pin 2) and I2C1 SCL (header pin 3),")
print("and run this test with:")
print(" python -m tests.test_i2c /dev/i2c-1")
print("")
sys.exit(1)
i2c_devpath = sys.argv[1]
test_arguments()
pokay("Arguments test passed.")
test_open_close()
pokay("Open/close test passed.")
test_loopback()
pokay("Loopback test passed.")
test_interactive()
pokay("Interactive test passed.")
pokay("All tests passed!")