Skip to content

Commit a5288a1

Browse files
committed
Added lock checking
1 parent c67ee4a commit a5288a1

File tree

1 file changed

+113
-101
lines changed

1 file changed

+113
-101
lines changed

adafruit_bitbangio.py

Lines changed: 113 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ def unlock(self):
7171
else:
7272
raise ValueError("Not locked")
7373

74+
def _check_lock(self):
75+
if not self._locked:
76+
raise RuntimeError("First call try_lock()")
77+
return True
78+
7479
def __enter__(self):
7580
return self
7681

@@ -111,25 +116,28 @@ def __init__(self, scl, sda, *, frequency=400000, timeout=1):
111116
def scan(self):
112117
"""Perform an I2C Device Scan"""
113118
found = []
114-
for address in range(0, 0x80):
115-
if self._probe(address):
116-
found.append(address)
119+
if self._check_lock():
120+
for address in range(0, 0x80):
121+
if self._probe(address):
122+
found.append(address)
117123
return found
118124

119125
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
120126
"""Write data from the buffer to an address"""
121127
if end is None:
122128
end = len(buffer)
123-
self._write(address, buffer[start:end], stop)
129+
if self._check_lock():
130+
self._write(address, buffer[start:end], stop)
124131

125132
def readfrom_into(self, address, buffer, *, start=0, end=None):
126133
"""Read data from an address and into the buffer"""
127134
if end is None:
128135
end = len(buffer)
129136

130-
readin = self._read(address, end - start)
131-
for i in range(end - start):
132-
buffer[i + start] = readin[i]
137+
if self._check_lock():
138+
readin = self._read(address, end - start)
139+
for i in range(end - start):
140+
buffer[i + start] = readin[i]
133141

134142
def writeto_then_readfrom(
135143
self,
@@ -150,8 +158,9 @@ def writeto_then_readfrom(
150158
out_end = len(buffer_out)
151159
if in_end is None:
152160
in_end = len(buffer_in)
153-
self.writeto(address, buffer_out, start=out_start, end=out_end, stop=stop)
154-
self.readfrom_into(address, buffer_in, start=in_start, end=in_end)
161+
if self._check_lock():
162+
self.writeto(address, buffer_out, start=out_start, end=out_end, stop=stop)
163+
self.readfrom_into(address, buffer_in, start=in_start, end=in_end)
155164

156165
def _scl_low(self):
157166
self._scl.value = 0
@@ -308,7 +317,7 @@ def __init__(self, clock, MOSI=None, MISO=None):
308317

309318
def configure(self, *, baudrate=100000, polarity=0, phase=0, bits=8):
310319
"""Configures the SPI bus. Only valid when locked."""
311-
if self._locked:
320+
if self._check_lock():
312321
if not isinstance(baudrate, int):
313322
raise ValueError("baudrate must be an integer")
314323
if not isinstance(bits, int):
@@ -325,9 +334,6 @@ def configure(self, *, baudrate=100000, polarity=0, phase=0, bits=8):
325334
self._bits = bits
326335
self._half_period = (1 / self._baudrate) / 2 # 50% Duty Cyle delay
327336

328-
else:
329-
raise RuntimeError("First call try_lock()")
330-
331337
def _wait(self, start=None):
332338
"""Wait for up to one half cycle"""
333339
while (start + self._half_period) > monotonic():
@@ -344,26 +350,28 @@ def write(self, buffer, start=0, end=None):
344350
if end is None:
345351
end = len(buffer)
346352

347-
start_time = monotonic()
348-
for byte in buffer[start:end]:
349-
for bit_position in range(self._bits):
350-
bit_value = byte & 0x80 >> bit_position
351-
# Set clock to base
352-
if not self._phase: # Mode 0, 2
353-
self._mosi.value = bit_value
354-
self._sclk.value = self._polarity
355-
start_time = self._wait(start_time)
356-
357-
# Flip clock off base
358-
if self._phase: # Mode 1, 3
359-
self._mosi.value = bit_value
360-
self._sclk.value = not self._polarity
361-
start_time = self._wait(start_time)
362-
363-
# Return pins to base positions
364-
self._mosi.value = 0
365-
self._sclk.value = self._polarity
353+
if self._check_lock():
354+
start_time = monotonic()
355+
for byte in buffer[start:end]:
356+
for bit_position in range(self._bits):
357+
bit_value = byte & 0x80 >> bit_position
358+
# Set clock to base
359+
if not self._phase: # Mode 0, 2
360+
self._mosi.value = bit_value
361+
self._sclk.value = self._polarity
362+
start_time = self._wait(start_time)
366363

364+
# Flip clock off base
365+
if self._phase: # Mode 1, 3
366+
self._mosi.value = bit_value
367+
self._sclk.value = not self._polarity
368+
start_time = self._wait(start_time)
369+
370+
# Return pins to base positions
371+
self._mosi.value = 0
372+
self._sclk.value = self._polarity
373+
374+
# pylint: disable=too-many-branches
367375
def readinto(self, buffer, start=0, end=None, write_value=0):
368376
"""Read into the buffer specified by buf while writing zeroes. Requires the SPI being
369377
locked. If the number of bytes to read is 0, nothing happens.
@@ -372,43 +380,44 @@ def readinto(self, buffer, start=0, end=None, write_value=0):
372380
raise RuntimeError("Read attempted with no MISO pin specified.")
373381
if end is None:
374382
end = len(buffer)
375-
start_time = monotonic()
376-
for byte_position, _ in enumerate(buffer[start:end]):
377-
for bit_position in range(self._bits):
378-
bit_mask = 0x80 >> bit_position
379-
bit_value = write_value & 0x80 >> bit_position
380-
# Return clock to base
381-
self._sclk.value = self._polarity
382-
start_time = self._wait(start_time)
383-
# Handle read on leading edge of clock.
384-
if not self._phase: # Mode 0, 2
385-
if self._mosi is not None:
386-
self._mosi.value = bit_value
387-
if self._miso.value:
388-
# Set bit to 1 at appropriate location.
389-
buffer[byte_position] |= bit_mask
390-
else:
391-
# Set bit to 0 at appropriate location.
392-
buffer[byte_position] &= ~bit_mask
393-
# Flip clock off base
394-
self._sclk.value = not self._polarity
395-
start_time = self._wait(start_time)
396-
# Handle read on trailing edge of clock.
397-
if self._phase: # Mode 1, 3
398-
if self._mosi is not None:
399-
self._mosi.value = bit_value
400-
if self._miso.value:
401-
# Set bit to 1 at appropriate location.
402-
buffer[byte_position] |= bit_mask
403-
else:
404-
# Set bit to 0 at appropriate location.
405-
buffer[byte_position] &= ~bit_mask
406383

407-
# Return pins to base positions
408-
self._mosi.value = 0
409-
self._sclk.value = self._polarity
384+
if self._check_lock():
385+
start_time = monotonic()
386+
for byte_position, _ in enumerate(buffer[start:end]):
387+
for bit_position in range(self._bits):
388+
bit_mask = 0x80 >> bit_position
389+
bit_value = write_value & 0x80 >> bit_position
390+
# Return clock to base
391+
self._sclk.value = self._polarity
392+
start_time = self._wait(start_time)
393+
# Handle read on leading edge of clock.
394+
if not self._phase: # Mode 0, 2
395+
if self._mosi is not None:
396+
self._mosi.value = bit_value
397+
if self._miso.value:
398+
# Set bit to 1 at appropriate location.
399+
buffer[byte_position] |= bit_mask
400+
else:
401+
# Set bit to 0 at appropriate location.
402+
buffer[byte_position] &= ~bit_mask
403+
# Flip clock off base
404+
self._sclk.value = not self._polarity
405+
start_time = self._wait(start_time)
406+
# Handle read on trailing edge of clock.
407+
if self._phase: # Mode 1, 3
408+
if self._mosi is not None:
409+
self._mosi.value = bit_value
410+
if self._miso.value:
411+
# Set bit to 1 at appropriate location.
412+
buffer[byte_position] |= bit_mask
413+
else:
414+
# Set bit to 0 at appropriate location.
415+
buffer[byte_position] &= ~bit_mask
416+
417+
# Return pins to base positions
418+
self._mosi.value = 0
419+
self._sclk.value = self._polarity
410420

411-
# pylint: disable=too-many-branches
412421
def write_readinto(
413422
self,
414423
buffer_out,
@@ -435,40 +444,43 @@ def write_readinto(
435444
if len(buffer_out[out_start:out_end]) != len(buffer_in[in_start:in_end]):
436445
raise RuntimeError("Buffer slices must be equal length")
437446

438-
start_time = monotonic()
439-
for byte_position, _ in enumerate(buffer_out[out_start:out_end]):
440-
for bit_position in range(self._bits):
441-
bit_mask = 0x80 >> bit_position
442-
bit_value = buffer_out[byte_position + out_start] & 0x80 >> bit_position
443-
in_byte_position = byte_position + in_start
444-
# Return clock to 0
445-
self._sclk.value = self._polarity
446-
start_time = self._wait(start_time)
447-
# Handle read on leading edge of clock.
448-
if not self._phase: # Mode 0, 2
449-
self._mosi.value = bit_value
450-
if self._miso.value:
451-
# Set bit to 1 at appropriate location.
452-
buffer_in[in_byte_position] |= bit_mask
453-
else:
454-
# Set bit to 0 at appropriate location.
455-
buffer_in[in_byte_position] &= ~bit_mask
456-
# Flip clock off base
457-
self._sclk.value = not self._polarity
458-
start_time = self._wait(start_time)
459-
# Handle read on trailing edge of clock.
460-
if self._phase: # Mode 1, 3
461-
self._mosi.value = bit_value
462-
if self._miso.value:
463-
# Set bit to 1 at appropriate location.
464-
buffer_in[in_byte_position] |= bit_mask
465-
else:
466-
# Set bit to 0 at appropriate location.
467-
buffer_in[in_byte_position] &= ~bit_mask
468-
469-
# Return pins to base positions
470-
self._mosi.value = 0
471-
self._sclk.value = self._polarity
447+
if self._check_lock():
448+
start_time = monotonic()
449+
for byte_position, _ in enumerate(buffer_out[out_start:out_end]):
450+
for bit_position in range(self._bits):
451+
bit_mask = 0x80 >> bit_position
452+
bit_value = (
453+
buffer_out[byte_position + out_start] & 0x80 >> bit_position
454+
)
455+
in_byte_position = byte_position + in_start
456+
# Return clock to 0
457+
self._sclk.value = self._polarity
458+
start_time = self._wait(start_time)
459+
# Handle read on leading edge of clock.
460+
if not self._phase: # Mode 0, 2
461+
self._mosi.value = bit_value
462+
if self._miso.value:
463+
# Set bit to 1 at appropriate location.
464+
buffer_in[in_byte_position] |= bit_mask
465+
else:
466+
# Set bit to 0 at appropriate location.
467+
buffer_in[in_byte_position] &= ~bit_mask
468+
# Flip clock off base
469+
self._sclk.value = not self._polarity
470+
start_time = self._wait(start_time)
471+
# Handle read on trailing edge of clock.
472+
if self._phase: # Mode 1, 3
473+
self._mosi.value = bit_value
474+
if self._miso.value:
475+
# Set bit to 1 at appropriate location.
476+
buffer_in[in_byte_position] |= bit_mask
477+
else:
478+
# Set bit to 0 at appropriate location.
479+
buffer_in[in_byte_position] &= ~bit_mask
480+
481+
# Return pins to base positions
482+
self._mosi.value = 0
483+
self._sclk.value = self._polarity
472484

473485
# pylint: enable=too-many-branches
474486

0 commit comments

Comments
 (0)