-
Notifications
You must be signed in to change notification settings - Fork 0
/
usmbus.py
120 lines (79 loc) · 3.86 KB
/
usmbus.py
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
""" Provides an SMBus class for use on micropython """
import logging
# https://github.com/vroomfondel/micropython-smbus/tree/add-read_word_data
# https://github.com/matteius/micropython-smbus/blob/fix-edgecase-from-bme280-work/usmbus/__init__.py
import machine
#
# try:
# from machine import I2C, Pin
# except ImportError:
# raise ImportError("Can't find the micropython machine.I2C class: "
# "perhaps you don't need this adapter?")
class SMBus(): # machine.I2C):
""" Provides an 'SMBus' module which supports some of the py-smbus
i2c methods, as well as being a subclass of machine.I2C
Hopefully this will allow you to run code that was targeted at
py-smbus unmodified on micropython.
Use it like you would the machine.I2C class:
import usmbus.SMBus
bus = SMBus(id=0, scl=machine.Pin(15), sda=machine.Pin(10), freq=100000)
bus.read_byte_data(addr, register)
... etc
"""
__LOG_FORMAT = f"%(asctime)s - %(levelname)s - %(name)-12s - %(message)s"
def __init__(self, id, scl: machine.Pin, sda: machine.Pin, freq=400_000, log_level=logging.ERROR):
self.i2c = machine.I2C(id, scl=scl, sda=sda, freq=freq)
self.scl = scl
self.sda = sda
self.freq = freq
if len(logging.getLogger().handlers) == 0:
# Initialize the root logger only if it hasn't been done yet by a
# parent module.
logging.basicConfig(level=log_level, format=self.__LOG_FORMAT)
self.logger = logging.getLogger(__name__)
self.logger.setLevel(log_level)
#(0, scl=machine.Pin(22), sda = machine.Pin(21), freq = 400_000)
def scan(self):
return self.i2c.scan()
def read_byte_data(self, addr, register):
""" Read a single byte from register of device at addr
Returns a single byte """
self.logger(f"read_byte_data {addr=} {register=}")
return self.i2c.readfrom_mem(addr, register, 1)[0]
def read_i2c_block_data(self, addr, register, length):
""" Read a block of length from register of device at addr
Returns a bytes object filled with whatever was read """
self.logger(f"read_i2c_block_data {addr=} {register=} {length=}")
return self.i2c.readfrom_mem(addr, register, length)
def write_byte_data(self, addr, register, data):
""" Write a single byte from buffer `data` to register of device at addr
Returns None """
# writeto_mem() expects something it can treat as a buffer
if isinstance(data, int):
data = bytes([data])
return self.i2c.writeto_mem(addr, register, data)
def write_i2c_block_data(self, addr, register, data):
""" Write multiple bytes of data to register of device at addr
Returns None """
#writeto_mem() expects something it can treat as a buffer
if not isinstance(data, bytes):
if not isinstance(data, list):
data = [data]
data = bytes(data)
return self.i2c.writeto_mem(addr, register, data)
# The following haven't been implemented, but could be.
def read_byte(self, *args, **kwargs):
""" Not yet implemented """
raise RuntimeError("Not yet implemented")
def write_byte(self, *args, **kwargs):
""" Not yet implemented """
raise RuntimeError("Not yet implemented")
def read_word_data(self, addr, register) -> int:
""" Not yet implemented """
# DEBUG:root:read_word_data args=(64, 2) kwargs={}
bs: bytes = self.i2c.readfrom_mem(addr, register, 2)
self.logger.debug(f"read_word_data::{addr=} {register=} {bs=}")
return int.from_bytes(bs, 'little')
def write_word_data(self, *args, **kwargs):
""" Not yet implemented """
raise RuntimeError("Not yet implemented")