3939_EXTERNAL_TEMP_MSB = const (0x01 )
4040_EXTERNAL_TEMP_LSB = const (0x10 )
4141
42- _STATUS = const (0x02 )
4342_REG_CONFIG = const (0x03 )
4443_TEMP_FORCE = const (0x0C )
4544_TACH_LSB = const (0x46 )
4948_FAN_CONFIG = const (0x4A )
5049_FAN_SPINUP = const (0x4B )
5150_REG_FAN_SETTING = const (0x4C )
52- _PWM_FREQ = const (0x4D )
53- _PWM_DIV = const (0x4E )
54- _LUT_HYSTERESIS = const (0x4F )
5551
56- _TEMP_FILTER = const (0xBF )
5752_REG_PARTID = const (0xFD ) # 0x16
5853_REG_MFGID = const (0xFE ) # 0xFF16
5954
6257
6358_I2C_ADDR = const (0x4C )
6459_FAN_RPM_DIVISOR = const (5400000 )
65- _TEMP_LSB = 0.125
66-
67-
68- def _speed_to_lsb (percentage ):
69- return round ((percentage / 100.0 ) * MAX_LUT_SPEED )
70-
71-
72- def _lsb_to_speed (lsb_speed ):
73- return round ((lsb_speed / MAX_LUT_SPEED ) * 100.0 )
74-
75-
76- class FanSpeedLUT :
77- """A class used to provide a dict-like interface to the EMC2101's Temperature to Fan speed
78- Look Up Table"""
79-
80- # seems like a pain but ¯\_(ツ)_/¯
81- _fan_lut_t1 = UnaryStruct (0x50 , "<B" )
82- _fan_lut_s1 = UnaryStruct (0x51 , "<B" )
83-
84- _fan_lut_t2 = UnaryStruct (0x52 , "<B" )
85- _fan_lut_s2 = UnaryStruct (0x53 , "<B" )
86-
87- _fan_lut_t3 = UnaryStruct (0x54 , "<B" )
88- _fan_lut_s3 = UnaryStruct (0x55 , "<B" )
89-
90- _fan_lut_t4 = UnaryStruct (0x56 , "<B" )
91- _fan_lut_s4 = UnaryStruct (0x57 , "<B" )
92-
93- _fan_lut_t5 = UnaryStruct (0x58 , "<B" )
94- _fan_lut_s5 = UnaryStruct (0x59 , "<B" )
95-
96- _fan_lut_t6 = UnaryStruct (0x5A , "<B" )
97- _fan_lut_s6 = UnaryStruct (0x5B , "<B" )
98-
99- _fan_lut_t7 = UnaryStruct (0x5C , "<B" )
100- _fan_lut_s7 = UnaryStruct (0x5D , "<B" )
101-
102- _fan_lut_t8 = UnaryStruct (0x5E , "<B" )
103- _fan_lut_s8 = UnaryStruct (0x5F , "<B" )
104-
105- def __init__ (self , fan_obj ):
106- self .emc_fan = fan_obj
107- self .lut_values = {}
108- self .i2c_device = fan_obj .i2c_device
109-
110- def __getitem__ (self , index ):
111- if not isinstance (index , int ):
112- raise IndexError
113- if not index in self .lut_values :
114- raise IndexError
115- return self .lut_values [index ]
116-
117- def __setitem__ (self , index , value ):
118- if not isinstance (index , int ):
119- raise IndexError
120- self .lut_values [index ] = value
121- self ._set_lut (self .lut_values )
122-
123- def __repr__ (self ):
124- """return the official string representation of the LUT"""
125- return "FanSpeedLUT <%x>" % id (self )
126-
127- def __str__ (self ):
128- """return the official string representation of the LUT"""
129- value_strs = []
130- lut_keys = list (self .lut_values .keys ())
131- lut_keys .sort ()
132- for temp in lut_keys :
133- fan_drive = self .lut_values [temp ]
134- value_strs .append ("%d deg C => %.1f%% duty cycle" % (temp , fan_drive ))
135-
136- return "\n " .join (value_strs )
137-
138- def __len__ (self ):
139- return len (self .lut_values )
140-
141- # this function does a whole lot of work to organized the user-supplied lut dict into
142- # their correct spot within the lut table as pairs of set registers, sorted with the lowest
143- # temperature first
144-
145- def _set_lut (self , lut_dict ):
146- lut_keys = list (lut_dict .keys ())
147- lut_size = len (lut_dict )
148- # Make sure we're not going to try to set more entries than we have slots
149- if lut_size > 8 :
150- raise AttributeError ("LUT can only contain a maximum of 8 items" )
151-
152- # we want to assign the lowest temperature to the lowest LUT slot, so we sort the keys/temps
153- for k in lut_keys :
154- # Verify that the value is a correct amount
155- lut_value = lut_dict [k ]
156- if lut_value > 100.0 or lut_value < 0 :
157- raise AttributeError ("LUT values must be a fan speed from 0-100%" )
158-
159- # add the current temp/speed to our internal representation
160- self .lut_values [k ] = lut_value
161- current_mode = self .emc_fan .lut_enabled
162-
163- # Disable the lut to allow it to be updated
164- self .emc_fan .lut_enabled = False
165-
166- # get and sort the new lut keys so that we can assign them in order
167- lut_keys = list (self .lut_values .keys ())
168- lut_keys .sort ()
169- for idx , current_temp in enumerate (sorted (self .lut_values .keys ())):
170- current_speed = _speed_to_lsb (self .lut_values [current_temp ])
171- setattr (self , "_fan_lut_t%d" % (idx + 1 ), current_temp )
172- setattr (self , "_fan_lut_s%d" % (idx + 1 ), current_speed )
173-
174- # Set the remaining LUT entries to the default (Temp/Speed = max value)
175- for idx in range (8 )[len (self .lut_values ) :]:
176- setattr (self , "_fan_lut_t%d" % (idx + 1 ), MAX_LUT_TEMP )
177- setattr (self , "_fan_lut_s%d" % (idx + 1 ), MAX_LUT_SPEED )
178- self .emc_fan .lut_enabled = current_mode
17960
18061
18162class CV :
@@ -285,11 +166,6 @@ class EMC2101: # pylint: disable=too-many-instance-attributes
285166 """When set to True, the magnitude of the fan output signal is inverted, making 0 the maximum
286167 value and 100 the minimum value"""
287168
288- _fan_pwm_clock_select = RWBit (_FAN_CONFIG , 3 )
289- _fan_pwm_clock_override = RWBit (_FAN_CONFIG , 2 )
290- _pwm_freq = RWBits (5 , _PWM_FREQ , 0 )
291- _pwm_freq_div = UnaryStruct (_PWM_DIV , "<B" )
292-
293169 dac_output_enabled = RWBit (_REG_CONFIG , 4 )
294170 """When set, the fan control signal is output as a DC voltage instead of a PWM signal"""
295171
@@ -299,27 +175,18 @@ class EMC2101: # pylint: disable=too-many-instance-attributes
299175 _spin_time = RWBits (3 , _FAN_SPINUP , 0 )
300176 _spin_tach_limit = RWBit (_FAN_SPINUP , 5 )
301177
302- lut_temperature_hysteresis = UnaryStruct (_LUT_HYSTERESIS , "<B" )
303- """The amount of hysteresis in Degrees celcius of hysteresis applied to temperature readings
304- used for the LUT. As the temperature drops, the controller will switch to a lower LUT entry when
305- the measured value is belowthe lower entry's threshold, minus the hysteresis value"""
306-
307178 def __init__ (self , i2c_bus ):
308179 self .i2c_device = i2cdevice .I2CDevice (i2c_bus , _I2C_ADDR )
309180
310181 if not self ._part_id in [0x16 , 0x28 ] or self ._mfg_id != 0x5D :
311182 raise AttributeError ("Cannot find a EMC2101" )
312- # self._lut = {}
313183
314184 self .initialize ()
315- self ._lut = FanSpeedLUT (self )
316185
317186 def initialize (self ):
318187 """Reset the controller to an initial default configuration"""
319188 self ._tach_mode_enable = True
320- self .lut_enabled = False
321189 self ._enabled_forced_temp = False
322- self ._fan_pwm_clock_override = True
323190 self ._spin_tach_limit = False
324191
325192 @property
@@ -339,54 +206,6 @@ def external_temperature(self):
339206
340207 return full_tmp
341208
342- def set_pwm_clock (self , use_preset = False , use_slow = False ):
343- """
344- Select the PWM clock source, chosing between two preset clocks or by configuring the
345- clock using `pwm_frequency` and `pwm_frequency_divisor`.
346-
347- :param bool use_preset:
348- True: Select between two preset clock sources
349- False: The PWM clock is set by `pwm_frequency` and `pwm_frequency_divisor`
350- :param bool use_slow:
351- True: Use the 1.4kHz clock
352- False: Use the 360kHz clock.
353- :type priority: integer or None
354- :return: None
355- :raises AttributeError: if use_preset is not a `bool`
356- :raises AttributeError: if use_slow is not a `bool`
357-
358- """
359-
360- if not isinstance (use_preset , bool ):
361- raise AttributeError ("use_preset must be given a bool" )
362- if not isinstance (use_slow , bool ):
363- raise AttributeError ("use_slow_pwm must be given a bool" )
364-
365- self ._fan_pwm_clock_override = not use_preset
366- self ._fan_pwm_clock_select = use_slow
367-
368- @property
369- def pwm_frequency (self ):
370- """Selects the base clock frequency used for the fan PWM output"""
371- return self ._pwm_freq
372-
373- @pwm_frequency .setter
374- def pwm_frequency (self , value ):
375- if value < 0 or value > 0x1F :
376- raise AttributeError ("pwm_frequency must be from 0-31" )
377- self ._pwm_freq = value
378-
379- @property
380- def pwm_frequency_divisor (self ):
381- """The Divisor applied to the PWM frequency to set the final frequency"""
382- return self ._pwm_freq_div
383-
384- @pwm_frequency_divisor .setter
385- def pwm_frequency_divisor (self , divisor ):
386- if divisor < 0 or divisor > 255 :
387- raise AttributeError ("pwm_frequency_divisor must be from 0-255" )
388- self ._pwm_freq_div = divisor
389-
390209 @property
391210 def fan_speed (self ):
392211 """The current speed in Revolutions per Minute (RPM)"""
@@ -422,15 +241,6 @@ def lut_enabled(self):
422241 to a fan speed. When the LUT is disabled fan speed can be changed with `manual_fan_speed`"""
423242 return not self ._fan_lut_prog
424243
425- @lut_enabled .setter
426- def lut_enabled (self , enable_lut ):
427- self ._fan_lut_prog = not enable_lut
428-
429- @property
430- def lut (self ):
431- """The dict-like representation of the LUT"""
432- return self ._lut
433-
434244 @property
435245 def tach_limit (self ):
436246 """The maximum /minimum speed expected for the fan"""
0 commit comments