@@ -54,8 +54,6 @@ class SerialLockTimeout(Exception):
5454
5555 pass
5656
57- use_i2c_lock = not use_periphery and sys .implementation .name != 'micropython'
58-
5957NOTECARD_I2C_ADDRESS = 0x17
6058
6159# The notecard is a real-time device that has a fixed size interrupt buffer.
@@ -109,8 +107,8 @@ def i2c_lock(fn):
109107
110108 def decorator (self , * args , ** kwargs ):
111109 retries = 5
112- while use_i2c_lock and retries != 0 :
113- if self .i2c . try_lock ():
110+ while retries != 0 :
111+ if self .lock ():
114112 break
115113
116114 retries -= 1
@@ -123,8 +121,7 @@ def decorator(self, *args, **kwargs):
123121 try :
124122 ret = fn (self , * args , ** kwargs )
125123 finally :
126- if use_i2c_lock :
127- self .i2c .unlock ()
124+ self .unlock ()
128125
129126 return ret
130127
@@ -306,24 +303,24 @@ def __init__(self, uart_id, debug=False):
306303class OpenI2C (Notecard ):
307304 """Notecard class for I2C communication."""
308305
306+ def _write (self , data ):
307+ write_length = bytearray (1 )
308+ write_length [0 ] = len (data )
309+
310+ # Send a message with the length of the incoming bytes followed
311+ # by the bytes themselves.
312+ self ._platform_write (write_length , data )
313+
309314 def _transmit (self , data ):
310315 chunk_offset = 0
311316 data_left = len (data )
312317 sent_in_seg = 0
313- write_length = bytearray (1 )
314318
315319 while data_left > 0 :
316320 chunk_len = min (data_left , self .max )
317- write_length [0 ] = chunk_len
318321 write_data = data [chunk_offset :chunk_offset + chunk_len ]
319322
320- # Send a message with the length of the incoming bytes followed
321- # by the bytes themselves.
322- if use_periphery :
323- msgs = [I2C .Message (write_length + write_data )]
324- self .i2c .transfer (self .addr , msgs )
325- else :
326- self .i2c .writeto (self .addr , write_length + write_data )
323+ self ._write (write_data )
327324
328325 chunk_offset += chunk_len
329326 data_left -= chunk_len
@@ -335,35 +332,29 @@ def _transmit(self, data):
335332
336333 time .sleep (I2C_CHUNK_DELAY_MS / 1000 )
337334
335+ def _read (self , length ):
336+ initiate_read = bytearray (2 )
337+ # 0 indicates we are reading from the Notecard.
338+ initiate_read [0 ] = 0
339+ # This indicates how many bytes we are prepared to read.
340+ initiate_read [1 ] = length
341+ # read_buf is a buffer to store the data we're reading.
342+ # length accounts for the payload and the +2 is for the header. The
343+ # header sent by the Notecard has one byte to indicate the number of
344+ # bytes still available to read and a second byte to indicate the number
345+ # of bytes coming in the current chunk.
346+ read_buf = bytearray (length + 2 )
347+
348+ return self ._platform_read (initiate_read , read_buf )
349+
338350 def _receive (self , timeout_secs , chunk_delay_secs , wait_for_newline ):
339351 chunk_len = 0
340352 received_newline = False
341353 start = start_timeout ()
342354 read_data = bytearray ()
343355
344356 while True :
345- initiate_read = bytearray (2 )
346- # 0 indicates we are reading from the Notecard.
347- initiate_read [0 ] = 0
348- # This indicates how many bytes we are prepared to read.
349- initiate_read [1 ] = chunk_len
350- # read_buf is a buffer to store the data we're reading.
351- # chunk_len accounts for the payload and the +2 is for the
352- # header. The header sent by the Notecard has one byte to
353- # indicate the number of bytes still available to read and a
354- # second byte to indicate the number of bytes coming in the
355- # current chunk.
356- read_buf = bytearray (chunk_len + 2 )
357-
358- if use_periphery :
359- msgs = [I2C .Message (initiate_read ), I2C .Message (read_buf , read = True )]
360- self .i2c .transfer (self .addr , msgs )
361- read_buf = msgs [1 ].data
362- elif sys .implementation .name == 'micropython' :
363- self .i2c .writeto (self .addr , initiate_read , False )
364- self .i2c .readfrom_into (self .addr , read_buf )
365- else :
366- self .i2c .writeto_then_readfrom (self .addr , initiate_read , read_buf )
357+ read_buf = self ._read (chunk_len )
367358
368359 # The number of bytes still available to read.
369360 num_bytes_available = read_buf [0 ]
@@ -420,13 +411,55 @@ def Reset(self):
420411 # Read from the Notecard until there's nothing left to read.
421412 self ._receive (0 , .001 , False )
422413
414+ def _linux_write (self , length , data ):
415+ msgs = [I2C .Message (length + data )]
416+ self .i2c .transfer (self .addr , msgs )
417+
418+ def _non_linux_write (self , length , data ):
419+ self .i2c .writeto (self .addr , length + data )
420+
421+ def _linux_read (self , initiate_read_msg , read_buf ):
422+ msgs = [I2C .Message (initiate_read_msg ), I2C .Message (read_buf , read = True )]
423+ self .i2c .transfer (self .addr , msgs )
424+ read_buf = msgs [1 ].data
425+
426+ return read_buf
427+
428+ def _micropython_read (self , initiate_read_msg , read_buf ):
429+ self .i2c .writeto (self .addr , initiate_read_msg , False )
430+ self .i2c .readfrom_into (self .addr , read_buf )
431+
432+ return read_buf
433+
434+ def _circuitpython_read (self , initiate_read_msg , read_buf ):
435+ self .i2c .writeto_then_readfrom (self .addr , initiate_read_msg , read_buf )
436+
437+ return read_buf
438+
423439 def __init__ (self , i2c , address , max_transfer , debug = False ):
424440 """Initialize the Notecard before a reset."""
425441 super ().__init__ (debug )
426442 self ._user_agent ['req_interface' ] = 'i2c'
427443 self ._user_agent ['req_port' ] = address
428444
429445 self .i2c = i2c
446+
447+ def i2c_no_op_try_lock (* args , ** kwargs ):
448+ """No-op lock function."""
449+ return True
450+
451+ def i2c_no_op_unlock (* args , ** kwargs ):
452+ """No-op unlock function."""
453+ pass
454+
455+ use_i2c_lock = not use_periphery and sys .implementation .name != 'micropython'
456+ if use_i2c_lock :
457+ self .lock = self .i2c .try_lock
458+ self .unlock = self .i2c .unlock
459+ else :
460+ self .lock = i2c_no_op_try_lock
461+ self .unlock = i2c_no_op_unlock
462+
430463 if address == 0 :
431464 self .addr = NOTECARD_I2C_ADDRESS
432465 else :
@@ -436,4 +469,16 @@ def __init__(self, i2c, address, max_transfer, debug=False):
436469 else :
437470 self .max = max_transfer
438471
472+ if use_periphery :
473+ self ._platform_write = self ._linux_write
474+ self ._platform_read = self ._linux_read
475+ elif sys .implementation .name == 'micropython' :
476+ self ._platform_write = self ._non_linux_write
477+ self ._platform_read = self ._micropython_read
478+ elif sys .implementation .name == 'circuitpython' :
479+ self ._platform_write = self ._non_linux_write
480+ self ._platform_read = self ._circuitpython_read
481+ else :
482+ raise NotImplementedError (f'Unsupported platform: { sys .implementation .name } ' )
483+
439484 self .Reset ()
0 commit comments