Skip to content

Split file for low mem like samd21 #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 0 additions & 215 deletions adafruit_emc2101.py → adafruit_emc2101/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
_EXTERNAL_TEMP_MSB = const(0x01)
_EXTERNAL_TEMP_LSB = const(0x10)

_STATUS = const(0x02)
_REG_CONFIG = const(0x03)
_TEMP_FORCE = const(0x0C)
_TACH_LSB = const(0x46)
Expand All @@ -49,11 +48,7 @@
_FAN_CONFIG = const(0x4A)
_FAN_SPINUP = const(0x4B)
_REG_FAN_SETTING = const(0x4C)
_PWM_FREQ = const(0x4D)
_PWM_DIV = const(0x4E)
_LUT_HYSTERESIS = const(0x4F)

_TEMP_FILTER = const(0xBF)
_REG_PARTID = const(0xFD) # 0x16
_REG_MFGID = const(0xFE) # 0xFF16

Expand All @@ -62,145 +57,6 @@

_I2C_ADDR = const(0x4C)
_FAN_RPM_DIVISOR = const(5400000)
_TEMP_LSB = 0.125


def _speed_to_lsb(percentage):
return round((percentage / 100.0) * MAX_LUT_SPEED)


def _lsb_to_speed(lsb_speed):
return round((lsb_speed / MAX_LUT_SPEED) * 100.0)


class FanSpeedLUT:
"""A class used to provide a dict-like interface to the EMC2101's Temperature to Fan speed
Look Up Table"""

# seems like a pain but ¯\_(ツ)_/¯
_fan_lut_t1 = UnaryStruct(0x50, "<B")
_fan_lut_s1 = UnaryStruct(0x51, "<B")

_fan_lut_t2 = UnaryStruct(0x52, "<B")
_fan_lut_s2 = UnaryStruct(0x53, "<B")

_fan_lut_t3 = UnaryStruct(0x54, "<B")
_fan_lut_s3 = UnaryStruct(0x55, "<B")

_fan_lut_t4 = UnaryStruct(0x56, "<B")
_fan_lut_s4 = UnaryStruct(0x57, "<B")

_fan_lut_t5 = UnaryStruct(0x58, "<B")
_fan_lut_s5 = UnaryStruct(0x59, "<B")

_fan_lut_t6 = UnaryStruct(0x5A, "<B")
_fan_lut_s6 = UnaryStruct(0x5B, "<B")

_fan_lut_t7 = UnaryStruct(0x5C, "<B")
_fan_lut_s7 = UnaryStruct(0x5D, "<B")

_fan_lut_t8 = UnaryStruct(0x5E, "<B")
_fan_lut_s8 = UnaryStruct(0x5F, "<B")

_lut_speed_setters = [
_fan_lut_s1,
_fan_lut_s2,
_fan_lut_s3,
_fan_lut_s4,
_fan_lut_s5,
_fan_lut_s6,
_fan_lut_s7,
_fan_lut_s8,
]
_lut_temp_setters = [
_fan_lut_t1,
_fan_lut_t2,
_fan_lut_t3,
_fan_lut_t4,
_fan_lut_t5,
_fan_lut_t6,
_fan_lut_t7,
_fan_lut_t8,
]

def __init__(self, fan_obj):
self.emc_fan = fan_obj
self.lut_values = {}
self.i2c_device = fan_obj.i2c_device

def __getitem__(self, index):
if not isinstance(index, int):
raise IndexError
if not index in self.lut_values:
raise IndexError
return self.lut_values[index]

def __setitem__(self, index, value):
if not isinstance(index, int):
raise IndexError
self.lut_values[index] = value
self._set_lut(self.lut_values)

def __repr__(self):
"""return the official string representation of the LUT"""
return "FanSpeedLUT <%x>" % id(self)

def __str__(self):
"""return the official string representation of the LUT"""
value_strs = []
lut_keys = list(self.lut_values.keys())
lut_keys.sort()
for temp in lut_keys:
fan_drive = self.lut_values[temp]
value_strs.append("%d deg C => %.1f%% duty cycle" % (temp, fan_drive))

return "\n".join(value_strs)

def __len__(self):
return len(self.lut_values)

# this function does a whole lot of work to organized the user-supplied lut dict into
# their correct spot within the lut table as pairs of set registers, sorted with the lowest
# temperature first

def _set_lut(self, lut_dict):
lut_keys = list(lut_dict.keys())
lut_size = len(lut_dict)
# Make sure we're not going to try to set more entries than we have slots
if lut_size > 8:
raise AttributeError("LUT can only contain a maximum of 8 items")

# we want to assign the lowest temperature to the lowest LUT slot, so we sort the keys/temps
for k in lut_keys:
# Verify that the value is a correct amount
lut_value = lut_dict[k]
if lut_value > 100.0 or lut_value < 0:
raise AttributeError("LUT values must be a fan speed from 0-100%")

# add the current temp/speed to our internal representation
self.lut_values[k] = lut_value
current_mode = self.emc_fan.lut_enabled

# Disable the lut to allow it to be updated
self.emc_fan.lut_enabled = False

# get and sort the new lut keys so that we can assign them in order
lut_keys = list(self.lut_values.keys())
lut_keys.sort()
for idx in range(lut_size):
current_temp = lut_keys[idx]
current_speed = _speed_to_lsb(self.lut_values[current_temp])
getattr(self, "_fan_lut_t%d" % (idx + 1)).__set__(self, current_temp)
getattr(self, "_fan_lut_s%d" % (idx + 1)).__set__(self, current_speed)

# self.emc_fan._lut_temp_setters[idx].__set__(self.emc_fan, current_temp)
# self.emc_fan._lut_speed_setters[idx].__set__(self.emc_fan, current_speed)

# Set the remaining LUT entries to the default (Temp/Speed = max value)
for idx in range(8)[lut_size:]:
getattr(self, "_fan_lut_t%d" % (idx + 1)).__set__(self, MAX_LUT_TEMP)
getattr(self, "_fan_lut_s%d" % (idx + 1)).__set__(self, MAX_LUT_SPEED)
self.emc_fan.lut_enabled = current_mode


class CV:
Expand Down Expand Up @@ -310,11 +166,6 @@ class EMC2101: # pylint: disable=too-many-instance-attributes
"""When set to True, the magnitude of the fan output signal is inverted, making 0 the maximum
value and 100 the minimum value"""

_fan_pwm_clock_select = RWBit(_FAN_CONFIG, 3)
_fan_pwm_clock_override = RWBit(_FAN_CONFIG, 2)
_pwm_freq = RWBits(5, _PWM_FREQ, 0)
_pwm_freq_div = UnaryStruct(_PWM_DIV, "<B")

dac_output_enabled = RWBit(_REG_CONFIG, 4)
"""When set, the fan control signal is output as a DC voltage instead of a PWM signal"""

Expand All @@ -324,27 +175,18 @@ class EMC2101: # pylint: disable=too-many-instance-attributes
_spin_time = RWBits(3, _FAN_SPINUP, 0)
_spin_tach_limit = RWBit(_FAN_SPINUP, 5)

lut_temperature_hysteresis = UnaryStruct(_LUT_HYSTERESIS, "<B")
"""The amount of hysteresis in Degrees celcius of hysteresis applied to temperature readings
used for the LUT. As the temperature drops, the controller will switch to a lower LUT entry when
the measured value is belowthe lower entry's threshold, minus the hysteresis value"""

def __init__(self, i2c_bus):
self.i2c_device = i2cdevice.I2CDevice(i2c_bus, _I2C_ADDR)

if not self._part_id in [0x16, 0x28] or self._mfg_id != 0x5D:
raise AttributeError("Cannot find a EMC2101")
# self._lut = {}

self.initialize()
self._lut = FanSpeedLUT(self)

def initialize(self):
"""Reset the controller to an initial default configuration"""
self._tach_mode_enable = True
self.lut_enabled = False
self._enabled_forced_temp = False
self._fan_pwm_clock_override = True
self._spin_tach_limit = False

@property
Expand All @@ -364,54 +206,6 @@ def external_temperature(self):

return full_tmp

def set_pwm_clock(self, use_preset=False, use_slow=False):
"""
Select the PWM clock source, chosing between two preset clocks or by configuring the
clock using `pwm_frequency` and `pwm_frequency_divisor`.

:param bool use_preset:
True: Select between two preset clock sources
False: The PWM clock is set by `pwm_frequency` and `pwm_frequency_divisor`
:param bool use_slow:
True: Use the 1.4kHz clock
False: Use the 360kHz clock.
:type priority: integer or None
:return: None
:raises AttributeError: if use_preset is not a `bool`
:raises AttributeError: if use_slow is not a `bool`

"""

if not isinstance(use_preset, bool):
raise AttributeError("use_preset must be given a bool")
if not isinstance(use_slow, bool):
raise AttributeError("use_slow_pwm must be given a bool")

self._fan_pwm_clock_override = not use_preset
self._fan_pwm_clock_select = use_slow

@property
def pwm_frequency(self):
"""Selects the base clock frequency used for the fan PWM output"""
return self._pwm_freq

@pwm_frequency.setter
def pwm_frequency(self, value):
if value < 0 or value > 0x1F:
raise AttributeError("pwm_frequency must be from 0-31")
self._pwm_freq = value

@property
def pwm_frequency_divisor(self):
"""The Divisor applied to the PWM frequency to set the final frequency"""
return self._pwm_freq_div

@pwm_frequency_divisor.setter
def pwm_frequency_divisor(self, divisor):
if divisor < 0 or divisor > 255:
raise AttributeError("pwm_frequency_divisor must be from 0-255")
self._pwm_freq_div = divisor

@property
def fan_speed(self):
"""The current speed in Revolutions per Minute (RPM)"""
Expand Down Expand Up @@ -447,15 +241,6 @@ def lut_enabled(self):
to a fan speed. When the LUT is disabled fan speed can be changed with `manual_fan_speed`"""
return not self._fan_lut_prog

@lut_enabled.setter
def lut_enabled(self, enable_lut):
self._fan_lut_prog = not enable_lut

@property
def lut(self):
"""The dict-like representation of the LUT"""
return self._lut

@property
def tach_limit(self):
"""The maximum /minimum speed expected for the fan"""
Expand Down
Loading