Skip to content

Commit 057a5f0

Browse files
committed
Simplify attempt using structarray
1 parent 96a3a11 commit 057a5f0

File tree

1 file changed

+26
-44
lines changed

1 file changed

+26
-44
lines changed

adafruit_emc2101/emc2101_lut.py

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
Brushless fan controller: extended functionality
99
1010
11-
* Author(s): Bryan Siepert
11+
* Author(s): Bryan Siepert, Ryan Pavlik
1212
1313
Implementation Notes
1414
--------------------
@@ -22,15 +22,16 @@
2222
* Adafruit CircuitPython firmware for the supported boards:
2323
https://github.com/adafruit/circuitpython/releases
2424
25-
# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
26-
# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
25+
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
26+
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
2727
28-
The class defined here may be used instead of adafruit_emc2101.EMC2101,
28+
The class defined here may be used instead of :class:`adafruit_emc2101.EMC2101`,
2929
if your device has enough RAM to support it. This class adds LUT control
3030
and PWM frequency control to the base feature set.
3131
"""
3232

3333
from micropython import const
34+
from adafruit_register.i2c_struct_array import StructArray
3435
from adafruit_register.i2c_struct import UnaryStruct
3536
from adafruit_register.i2c_bit import RWBit
3637
from adafruit_register.i2c_bits import RWBits
@@ -43,6 +44,7 @@
4344
_PWM_FREQ = const(0x4D)
4445
_PWM_DIV = const(0x4E)
4546
_LUT_HYSTERESIS = const(0x4F)
47+
_LUT_BASE = const(0x50)
4648

4749
MAX_LUT_SPEED = 0x3F # 6-bit value
4850
MAX_LUT_TEMP = 0x7F # 7-bit
@@ -56,30 +58,8 @@ class FanSpeedLUT:
5658
"""A class used to provide a dict-like interface to the EMC2101's Temperature to Fan speed
5759
Look Up Table"""
5860

59-
# seems like a pain but ¯\_(ツ)_/¯
60-
_fan_lut_t1 = UnaryStruct(0x50, "<B")
61-
_fan_lut_s1 = UnaryStruct(0x51, "<B")
62-
63-
_fan_lut_t2 = UnaryStruct(0x52, "<B")
64-
_fan_lut_s2 = UnaryStruct(0x53, "<B")
65-
66-
_fan_lut_t3 = UnaryStruct(0x54, "<B")
67-
_fan_lut_s3 = UnaryStruct(0x55, "<B")
68-
69-
_fan_lut_t4 = UnaryStruct(0x56, "<B")
70-
_fan_lut_s4 = UnaryStruct(0x57, "<B")
71-
72-
_fan_lut_t5 = UnaryStruct(0x58, "<B")
73-
_fan_lut_s5 = UnaryStruct(0x59, "<B")
74-
75-
_fan_lut_t6 = UnaryStruct(0x5A, "<B")
76-
_fan_lut_s6 = UnaryStruct(0x5B, "<B")
77-
78-
_fan_lut_t7 = UnaryStruct(0x5C, "<B")
79-
_fan_lut_s7 = UnaryStruct(0x5D, "<B")
80-
81-
_fan_lut_t8 = UnaryStruct(0x5E, "<B")
82-
_fan_lut_s8 = UnaryStruct(0x5F, "<B")
61+
# 8 (Temperature, Speed) pairs in increasing order
62+
_fan_lut = StructArray(_LUT_BASE, "<B", 16)
8363

8464
def __init__(self, fan_obj):
8565
self.emc_fan = fan_obj
@@ -96,10 +76,15 @@ def __getitem__(self, index):
9676
def __setitem__(self, index, value):
9777
if not isinstance(index, int):
9878
raise IndexError
99-
if value > 100.0 or value < 0:
79+
if value is None:
80+
# Assign None to remove this entry
81+
del self.lut_values[index]
82+
elif value > 100.0 or value < 0:
83+
# Range check
10084
raise AttributeError("LUT values must be a fan speed from 0-100%")
101-
self.lut_values[index] = value
102-
self._set_lut()
85+
else:
86+
self.lut_values[index] = value
87+
self._update_lut()
10388

10489
def __repr__(self):
10590
"""return the official string representation of the LUT"""
@@ -122,16 +107,11 @@ def __len__(self):
122107
# their correct spot within the lut table as pairs of set registers, sorted with the lowest
123108
# temperature first
124109

125-
def _set_lut(self):
110+
def _update_lut(self):
126111
# Make sure we're not going to try to set more entries than we have slots
127112
if len(self.lut_values) > 8:
128113
raise AttributeError("LUT can only contain a maximum of 8 items")
129114

130-
# Verify that the value is a correct amount
131-
for speed in self.lut_values.values():
132-
if speed > 100.0 or speed < 0:
133-
raise AttributeError("LUT values must be a fan speed from 0-100%")
134-
135115
# Backup state
136116
current_mode = self.emc_fan.lut_enabled
137117

@@ -142,18 +122,20 @@ def _set_lut(self):
142122
# get and sort the new lut keys so that we can assign them in order
143123
for idx, current_temp in enumerate(sorted(self.lut_values.keys())):
144124
current_speed = _speed_to_lsb(self.lut_values[current_temp])
145-
setattr(self, "_fan_lut_t%d" % (idx + 1), current_temp)
146-
setattr(self, "_fan_lut_s%d" % (idx + 1), current_speed)
125+
self._set_lut_entry(idx, current_temp, current_speed)
147126

148127
# Set the remaining LUT entries to the default (Temp/Speed = max value)
149-
for idx in range(8)[len(self.lut_values):]:
150-
setattr(self, "_fan_lut_t%d" % (idx + 1), MAX_LUT_TEMP)
151-
setattr(self, "_fan_lut_s%d" % (idx + 1), MAX_LUT_SPEED)
128+
for idx in range(len(self.lut_values), 8):
129+
self._set_lut_entry(idx, MAX_LUT_TEMP, MAX_LUT_SPEED)
152130
self.emc_fan.lut_enabled = current_mode
153131

132+
def _set_lut_entry(self, idx, temp, speed):
133+
self._fan_lut[idx * 2] = bytearray((temp,))
134+
self._fan_lut[idx * 2 + 1] = bytearray((speed,))
135+
154136

155137
class EMC2101_LUT(EMC2101): # pylint: disable=too-many-instance-attributes
156-
"""Driver for the EMC2101 Fan Controller.
138+
"""Driver for the EMC2101 Fan Controller, with PWM frequency and LUT control.
157139
:param ~busio.I2C i2c_bus: The I2C bus the EMC is connected to.
158140
"""
159141

@@ -239,5 +221,5 @@ def lut_enabled(self, enable_lut):
239221

240222
@property
241223
def lut(self):
242-
"""The dict-like representation of the LUT"""
224+
"""The dict-like representation of the LUT, actually of type :class:`FanSpeedLUT`"""
243225
return self._lut

0 commit comments

Comments
 (0)