Skip to content

Commit 0ebf851

Browse files
committed
change request fixes; getter/setter, external objects.
1 parent 3deda9f commit 0ebf851

File tree

2 files changed

+77
-108
lines changed

2 files changed

+77
-108
lines changed

adafruit_fram.py

Lines changed: 63 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ class FRAM:
6565
def __init__(self, max_size, write_protect=False, wp_pin=None):
6666
self._max_size = max_size
6767
self._wp = write_protect
68+
self._wraparound = False
6869
if not wp_pin is None:
69-
import digitalio
70-
self._wp_pin = digitalio.DigitalInOut(wp_pin)
70+
#import digitalio
71+
self._wp_pin = wp_pin
7172
# Make sure write_prot is set to output
7273
self._wp_pin.switch_to_output()
7374
self._wp_pin.value = self._wp
@@ -81,6 +82,20 @@ def max_size(self):
8182
"""
8283
return self._max_size
8384

85+
@property
86+
def write_wraparound(self):
87+
""" Determines if sequential writes will wrapaound the ``FRAM.max_size``
88+
address. If ``False``, and a requested write will extend beyond the
89+
maximum size, an exception is raised.
90+
"""
91+
return self._wraparound
92+
93+
@write_wraparound.setter
94+
def write_wraparound(self, value):
95+
if not value in (True, False):
96+
raise ValueError("Write wraparound must be 'True' or 'False'.")
97+
self._wraparound = value
98+
8499
@property
85100
def write_protected(self):
86101
""" The status of write protection. Default value on initialization is
@@ -93,103 +108,58 @@ def write_protected(self):
93108
When no ``WP`` pin is supplied, protection is only at the software
94109
level in this library.
95110
"""
96-
if not self._wp_pin is None:
97-
status = self._wp_pin.value
98-
else:
99-
status = self._wp
100-
return status
111+
return self._wp if self._wp_pin is None else self._wp_pin.value
101112

102113
@write_protected.setter
103114
def write_protected(self, value):
104115
self._wp = value
105116
if not self._wp_pin is None:
106117
self._wp_pin.value = value
107118

108-
def write_protect_pin(self, wp_pin, write_protect=False):
109-
""" Assigns the write protection (``WP``) pin.
119+
def __getitem__(self, key):
120+
if isinstance(key, int):
121+
if key > self._max_size:
122+
raise ValueError("Register '{0}' greater than maximum FRAM size."
123+
" ({1})".format(key, self._max_size))
124+
return self._read_byte(key)[0]
125+
elif isinstance(key, slice):
126+
registers = list(range(key.start if not key.start is None else 0,
127+
key.stop if not key.stop is None else None,
128+
key.step if not key.step is None else None))
129+
if (registers[0] + len(registers)) > self._max_size:
130+
raise ValueError("Register + Length greater than maximum FRAM size."
131+
" ({0})".format(self._max_size))
132+
133+
read_buffer = bytearray(len(registers))
134+
for i, register in enumerate(registers):
135+
read_buffer[i] = self._read_byte(register)[0]
136+
return read_buffer
137+
138+
def __setitem__(self, key, value):
139+
if self.write_protected:
140+
raise RuntimeError("FRAM currently write protected.")
110141

111-
:param: wp_pin: The ``board.PIN`` object connected to the ``WP`` pin
112-
on the breakout board/chip. To remove a previously
113-
set ``WP`` pin, set this value to ``None``.
114-
:param: bool write_protect: Turn on/off write protection immediately
115-
when setting the pin. Default is ``False``
142+
if isinstance(key, int):
143+
if not isinstance(value, int):
144+
raise ValueError("Data must be an integer.")
145+
if key.start > self._max_size:
146+
raise ValueError("Requested register '{0}' greater than maximum"
147+
" FRAM size. ({1})".format(key.start,
148+
self._max_size))
116149

117-
"""
118-
if not wp_pin is None:
119-
import digitalio
120-
self._wp_pin = digitalio.DigitalInOut(wp_pin)
121-
# Make sure wp_pin is set to switch_to_output
122-
self._wp_pin.switch_to_output()
123-
self._wp_pin.value = write_protect
124-
else:
125-
if not self._wp_pin is None:
126-
# Deinit the pin to release it
127-
self._wp_pin.deinit()
128-
self._wp_pin = None
129-
130-
def read(self, register, length=1):
131-
""" Reads the data stored on the FRAM.
132-
133-
:param: int register: Register location to start reading. Range is:
134-
``0`` to ``max_size``.
135-
:param: int length: Length of registers to read from starting register.
136-
This function will create a buffer the size of
137-
``length``; larger buffers can cause memory
138-
allocation problems on some platforms.
139-
Range is ``1`` (default) to ``max_size``.
140-
However, ``register`` + ``length`` cannot be
141-
greater than ``max_size``.
142-
"""
143-
if length < 1:
144-
raise ValueError("Length must be '1' or greater.")
145-
if length > self._max_size:
146-
raise ValueError("Length '{0}' greater than maximum FRAM size."
147-
" ({1})".format(length, self._max_size))
148-
if (register + length) > self._max_size:
149-
raise ValueError("Register + Length greater than maximum FRAM size."
150-
" ({0})".format(self._max_size))
151-
read_buffer = bytearray(length)
152-
for i in range(length):
153-
read_buffer[i] = self._read_byte(register + i)[0]
154-
return read_buffer
150+
self._write_register(key.start, value)
155151

156-
def write_single(self, register, data):
157-
""" Writes a single byte to the FRAM.
152+
elif isinstance(key, slice):
153+
if not isinstance(value, (bytearray, list, tuple)):
154+
raise ValueError("Data must be either a bytearray, list, or tuple.")
155+
if (key.start > self._max_size):
156+
raise ValueError("Requested register '{0}' greater than maximum"
157+
" FRAM size. ({1})".format(key.start,
158+
self._max_size))
159+
if not key.step is None:
160+
raise ValueError("Slice steps are not allowed during write operations.")
158161

159-
:param: int register: Register location to write the byte data.
160-
:param: int data: The data to write.
161-
"""
162-
if not isinstance(data, int):
163-
raise ValueError("Data must be an integer.")
164-
if self.write_protected:
165-
raise RuntimeError("FRAM currently write protected.")
166-
if register > self._max_size:
167-
raise ValueError("Requested register '{0}' greater than maximum"
168-
" FRAM size. ({1})".format(register,
169-
self._max_size))
170-
self._write_register(register, data)
171-
172-
def write_sequence(self, start_register, data, wraparound=False):
173-
""" Writes sequential data to the FRAM.
174-
175-
:param: int start_register: Register location to start writing the
176-
data.
177-
:param: data: The data to write. Must be an iterable type of either
178-
``bytearray``, ``list``, or ``tuple``.
179-
:param: bool wraparound: Controls if sequential writes can wraparound
180-
beyond the ``max_size`` to zero, when
181-
``start_register`` + ``data length`` is
182-
greater than ``max_size``.
183-
"""
184-
if not isinstance(data, (bytearray, list, tuple)):
185-
raise ValueError("Data must be either a bytearray, list, or tuple.")
186-
if self.write_protected:
187-
raise RuntimeError("FRAM currently write protected.")
188-
if start_register > self._max_size:
189-
raise ValueError("Requested register '{0}' greater than maximum"
190-
" FRAM size. ({1})".format(start_register,
191-
self._max_size))
192-
self._write_page(start_register, data, wraparound)
162+
self._write_page(key.start, value, self._wraparound)
193163

194164
def _read_byte(self, register):
195165
return self._read_register(register)
@@ -209,19 +179,16 @@ def _write_page(self, start_register, data, wraparound):
209179
class FRAM_I2C(FRAM):
210180
""" I2C class for FRAM.
211181
212-
:param: i2c_SCL: The I2C SCL pin. Must be a ``board.PIN`` object.
213-
:param: i2c_SDA: The I2C SDA print. Must be a ``board.PIN`` object.
182+
:param: ~busio.I2C i2c_bus: The I2C bus the FRAM is connected to.
214183
:param: int address: I2C address of FRAM. Default address is ``0x50``.
215184
:param: bool write_protect: Turns on/off initial write protection.
216185
Default is ``False``.
217-
:param: wp_pin: Physical ``WP`` breakout pin. Must be a ``board.PIN``
218-
object.
186+
:param: wp_pin: Physical pin connected to the ``WP`` breakout pin.
187+
Must be a ``digitalio.DigitalInOut`` object.
219188
"""
220189
#pylint: disable=too-many-arguments
221-
def __init__(self, i2c_SCL, i2c_SDA, address=0x50, write_protect=False,
190+
def __init__(self, i2c_bus, address=0x50, write_protect=False,
222191
wp_pin=None):
223-
from busio import I2C as i2c
224-
i2c_bus = i2c(i2c_SCL, i2c_SDA)
225192
i2c_bus.try_lock()
226193
i2c_bus.writeto((0xF8 >> 1), bytearray([(address << 1)]), stop=False)
227194
read_buf = bytearray(3)
@@ -266,7 +233,7 @@ def _write_page(self, start_register, data, wraparound=False):
266233
pass
267234
else:
268235
raise ValueError("Starting register + data length extends beyond"
269-
" FRAM maximum size. Use 'wraparound=True' to"
236+
" FRAM maximum size. Use ``write_wraparound`` to"
270237
" override this warning.")
271238
with self._i2c as i2c:
272239
for i in range(0, data_length):

examples/fram_i2c_simpletest.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
11
## Simple Example For CircuitPython/Python I2C FRAM Library
22

33
import board
4+
import busio
45
import adafruit_fram
56

67
## Create a FRAM object (default address used).
7-
8-
fram = adafruit_fram.FRAM_I2C(board.SCL, board.SDA)
8+
i2c = busio.I2C(board.SCL, board.SDA)
9+
fram = adafruit_fram.FRAM_I2C(i2c)
910

1011
## Optional FRAM object with a different I2C address, as well
1112
## as a pin to control the hardware write protection ('WP'
1213
## pin on breakout). 'write_protected()' can be used
1314
## independent of the hardware pin.
1415

15-
#fram = adafruit_fram.FRAM_I2C(board.SCL,
16-
# board.SDA,
16+
#import digitalio
17+
#wp = digitalio.DigitalInOut(board.D10)
18+
#fram = adafruit_fram.FRAM_I2C(i2c,
1719
# address=0x53,
18-
# wp_pin=board.D4)
20+
# wp_pin=wp)
1921

2022
## Write a single-byte value to register address '0'
2123

22-
fram.write_single(0, 1)
24+
fram[0] = 1
2325

2426
## Read that byte to ensure a proper write.
25-
## Note: 'read()' returns a bytearray
27+
## Note: reads return a bytearray
2628

27-
print(fram.read(0)[1])
29+
print(fram[0])
2830

2931
## Or write a sequential value, then read the values back.
30-
## Note: 'read()' returns a bytearray. It also allocates
31-
## a buffer the size of 'length', which may cause
32+
## Note: reads return a bytearray. Reads also allocate
33+
## a buffer the size of slice, which may cause
3234
## problems on memory-constrained platforms.
3335

3436
#values = list(range(100)) # or bytearray or tuple
35-
#fram.write_sequence(0, values)
36-
#fram.read(0, length=100)
37+
#fram[0:100] = values
38+
#print(fram[0:100])

0 commit comments

Comments
 (0)