@@ -62,17 +62,16 @@ def read_register(self, register: int, byte_count: int = 1, max_tries: int = 5)
6262 - may raise a RuntimeError if there were too many errors
6363 """
6464 _validate_inputs (register = register , value = 0 , byte_count = byte_count , max_tries = max_tries )
65- if byte_count > 1 :
66- LH .warning ("Multi byte reads are not implemented yet! Returning a single byte instead." )
67- byte_count = 1
6865 for cur_try in range (1 , 1 + max_tries ):
6966 try :
70- buf_r = bytearray (1 )
67+ buf_r = bytearray (byte_count )
7168 buf_r [0 ] = register
7269 buf_w = bytearray (byte_count )
7370 self ._i2c_bus .writeto_then_readfrom (address = self ._i2c_adr , buffer_out = buf_r , buffer_in = buf_w )
74- # TODO properly handle multi byte reads
75- return buf_w [0 ]
71+ value = 0
72+ for i in range (byte_count ):
73+ value += buf_w [i ] << i * 8
74+ return value
7675 except OSError as e :
7776 # [Errno 121] Remote I/O error
7877 LH .warning ("[%s] Failed to read register 0x%02X (%i/%i): %s" , __name__ , register , cur_try , max_tries , e )
@@ -91,15 +90,16 @@ def write_register(self, register: int, value: int, byte_count: int = 1, max_tri
9190 - may raise a RuntimeError if there were too many errors
9291 """
9392 _validate_inputs (register = register , value = value , byte_count = byte_count , max_tries = max_tries )
94- if byte_count > 1 :
95- LH .warning ("Multi byte writes are not implemented yet! Returning a single byte instead." )
96- byte_count = 1
9793 for cur_try in range (1 , 1 + max_tries ):
9894 try :
99- buf = bytearray (1 + byte_count )
95+ buf = bytearray (1 + byte_count ) # buf[0], buf[1], buf[2]
10096 buf [0 ] = register
101- buf [1 ] = value & 0xFF
102- # TODO properly handle multi byte reads
97+ # need to populate the bytes in reverse order:
98+ # 0x##.. => buf[2]
99+ # 0x..## => buf[1]
100+ for i in range (byte_count , 0 , - 1 ):
101+ buf [i ] = value & 0xFF
102+ value = value >> 8
103103 self ._i2c_bus .writeto (address = self ._i2c_adr , buffer = buf )
104104 return
105105 except OSError as e :
@@ -112,6 +112,9 @@ def write_register(self, register: int, value: int, byte_count: int = 1, max_tri
112112 else :
113113 raise RuntimeError (f"Unable to read register 0x{ register :02X} after { cur_try } attempts. Giving up." )
114114
115+ # it is unclear if it's possible to have a multi-byte state registers
116+ # (a register write looks exactly like a multi-byte state write)
117+
115118 def get_state (self , byte_count : int = 1 , max_tries : int = 5 ) -> int :
116119 """
117120 get current state of I²C device identified by `i2c_adr` and
@@ -127,7 +130,6 @@ def get_state(self, byte_count: int = 1, max_tries: int = 5) -> int:
127130 for cur_try in range (1 , 1 + max_tries ):
128131 try :
129132 buf = bytearray (byte_count )
130- # TODO properly handle multi byte reads
131133 self ._i2c_bus .readfrom_into (address = self ._i2c_adr , buffer = buf )
132134 return buf [0 ]
133135 except OSError as e :
@@ -155,7 +157,6 @@ def set_state(self, value: int, byte_count: int = 1, max_tries: int = 3):
155157 try :
156158 buf = bytearray (byte_count )
157159 buf [0 ] = value & 0xFF
158- # TODO properly handle multi byte reads
159160 self ._i2c_bus .writeto (address = self ._i2c_adr , buffer = buf )
160161 return
161162 except OSError as e :
@@ -228,7 +229,7 @@ def __exit__(self, exc_type, exc_value, exc_tb):
228229
229230
230231def _validate_inputs (register : int , value : int , byte_count : int = 1 , max_tries : int = 3 ):
231- if register < 0 or register > 255 :
232+ if register < 0 or register > pow ( 255 , byte_count ) :
232233 raise ValueError (f"Provided I²C device register { register } is out of range! (allowed range: 0 ≤ x ≤ 255)" )
233234 max_value = pow (256 , byte_count ) - 1
234235 if value < 0 or value > max_value :
0 commit comments