39
39
_EXTERNAL_TEMP_MSB = const (0x01 )
40
40
_EXTERNAL_TEMP_LSB = const (0x10 )
41
41
42
- _STATUS = const (0x02 )
43
42
_REG_CONFIG = const (0x03 )
44
43
_TEMP_FORCE = const (0x0C )
45
44
_TACH_LSB = const (0x46 )
49
48
_FAN_CONFIG = const (0x4A )
50
49
_FAN_SPINUP = const (0x4B )
51
50
_REG_FAN_SETTING = const (0x4C )
52
- _PWM_FREQ = const (0x4D )
53
- _PWM_DIV = const (0x4E )
54
- _LUT_HYSTERESIS = const (0x4F )
55
51
56
- _TEMP_FILTER = const (0xBF )
57
52
_REG_PARTID = const (0xFD ) # 0x16
58
53
_REG_MFGID = const (0xFE ) # 0xFF16
59
54
62
57
63
58
_I2C_ADDR = const (0x4C )
64
59
_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
- _lut_speed_setters = [
106
- _fan_lut_s1 ,
107
- _fan_lut_s2 ,
108
- _fan_lut_s3 ,
109
- _fan_lut_s4 ,
110
- _fan_lut_s5 ,
111
- _fan_lut_s6 ,
112
- _fan_lut_s7 ,
113
- _fan_lut_s8 ,
114
- ]
115
- _lut_temp_setters = [
116
- _fan_lut_t1 ,
117
- _fan_lut_t2 ,
118
- _fan_lut_t3 ,
119
- _fan_lut_t4 ,
120
- _fan_lut_t5 ,
121
- _fan_lut_t6 ,
122
- _fan_lut_t7 ,
123
- _fan_lut_t8 ,
124
- ]
125
-
126
- def __init__ (self , fan_obj ):
127
- self .emc_fan = fan_obj
128
- self .lut_values = {}
129
- self .i2c_device = fan_obj .i2c_device
130
-
131
- def __getitem__ (self , index ):
132
- if not isinstance (index , int ):
133
- raise IndexError
134
- if not index in self .lut_values :
135
- raise IndexError
136
- return self .lut_values [index ]
137
-
138
- def __setitem__ (self , index , value ):
139
- if not isinstance (index , int ):
140
- raise IndexError
141
- self .lut_values [index ] = value
142
- self ._set_lut (self .lut_values )
143
-
144
- def __repr__ (self ):
145
- """return the official string representation of the LUT"""
146
- return "FanSpeedLUT <%x>" % id (self )
147
-
148
- def __str__ (self ):
149
- """return the official string representation of the LUT"""
150
- value_strs = []
151
- lut_keys = list (self .lut_values .keys ())
152
- lut_keys .sort ()
153
- for temp in lut_keys :
154
- fan_drive = self .lut_values [temp ]
155
- value_strs .append ("%d deg C => %.1f%% duty cycle" % (temp , fan_drive ))
156
-
157
- return "\n " .join (value_strs )
158
-
159
- def __len__ (self ):
160
- return len (self .lut_values )
161
-
162
- # this function does a whole lot of work to organized the user-supplied lut dict into
163
- # their correct spot within the lut table as pairs of set registers, sorted with the lowest
164
- # temperature first
165
-
166
- def _set_lut (self , lut_dict ):
167
- lut_keys = list (lut_dict .keys ())
168
- lut_size = len (lut_dict )
169
- # Make sure we're not going to try to set more entries than we have slots
170
- if lut_size > 8 :
171
- raise AttributeError ("LUT can only contain a maximum of 8 items" )
172
-
173
- # we want to assign the lowest temperature to the lowest LUT slot, so we sort the keys/temps
174
- for k in lut_keys :
175
- # Verify that the value is a correct amount
176
- lut_value = lut_dict [k ]
177
- if lut_value > 100.0 or lut_value < 0 :
178
- raise AttributeError ("LUT values must be a fan speed from 0-100%" )
179
-
180
- # add the current temp/speed to our internal representation
181
- self .lut_values [k ] = lut_value
182
- current_mode = self .emc_fan .lut_enabled
183
-
184
- # Disable the lut to allow it to be updated
185
- self .emc_fan .lut_enabled = False
186
-
187
- # get and sort the new lut keys so that we can assign them in order
188
- lut_keys = list (self .lut_values .keys ())
189
- lut_keys .sort ()
190
- for idx in range (lut_size ):
191
- current_temp = lut_keys [idx ]
192
- current_speed = _speed_to_lsb (self .lut_values [current_temp ])
193
- getattr (self , "_fan_lut_t%d" % (idx + 1 )).__set__ (self , current_temp )
194
- getattr (self , "_fan_lut_s%d" % (idx + 1 )).__set__ (self , current_speed )
195
-
196
- # self.emc_fan._lut_temp_setters[idx].__set__(self.emc_fan, current_temp)
197
- # self.emc_fan._lut_speed_setters[idx].__set__(self.emc_fan, current_speed)
198
-
199
- # Set the remaining LUT entries to the default (Temp/Speed = max value)
200
- for idx in range (8 )[lut_size :]:
201
- getattr (self , "_fan_lut_t%d" % (idx + 1 )).__set__ (self , MAX_LUT_TEMP )
202
- getattr (self , "_fan_lut_s%d" % (idx + 1 )).__set__ (self , MAX_LUT_SPEED )
203
- self .emc_fan .lut_enabled = current_mode
204
60
205
61
206
62
class CV :
@@ -310,11 +166,6 @@ class EMC2101: # pylint: disable=too-many-instance-attributes
310
166
"""When set to True, the magnitude of the fan output signal is inverted, making 0 the maximum
311
167
value and 100 the minimum value"""
312
168
313
- _fan_pwm_clock_select = RWBit (_FAN_CONFIG , 3 )
314
- _fan_pwm_clock_override = RWBit (_FAN_CONFIG , 2 )
315
- _pwm_freq = RWBits (5 , _PWM_FREQ , 0 )
316
- _pwm_freq_div = UnaryStruct (_PWM_DIV , "<B" )
317
-
318
169
dac_output_enabled = RWBit (_REG_CONFIG , 4 )
319
170
"""When set, the fan control signal is output as a DC voltage instead of a PWM signal"""
320
171
@@ -324,27 +175,18 @@ class EMC2101: # pylint: disable=too-many-instance-attributes
324
175
_spin_time = RWBits (3 , _FAN_SPINUP , 0 )
325
176
_spin_tach_limit = RWBit (_FAN_SPINUP , 5 )
326
177
327
- lut_temperature_hysteresis = UnaryStruct (_LUT_HYSTERESIS , "<B" )
328
- """The amount of hysteresis in Degrees celcius of hysteresis applied to temperature readings
329
- used for the LUT. As the temperature drops, the controller will switch to a lower LUT entry when
330
- the measured value is belowthe lower entry's threshold, minus the hysteresis value"""
331
-
332
178
def __init__ (self , i2c_bus ):
333
179
self .i2c_device = i2cdevice .I2CDevice (i2c_bus , _I2C_ADDR )
334
180
335
181
if not self ._part_id in [0x16 , 0x28 ] or self ._mfg_id != 0x5D :
336
182
raise AttributeError ("Cannot find a EMC2101" )
337
- # self._lut = {}
338
183
339
184
self .initialize ()
340
- self ._lut = FanSpeedLUT (self )
341
185
342
186
def initialize (self ):
343
187
"""Reset the controller to an initial default configuration"""
344
188
self ._tach_mode_enable = True
345
- self .lut_enabled = False
346
189
self ._enabled_forced_temp = False
347
- self ._fan_pwm_clock_override = True
348
190
self ._spin_tach_limit = False
349
191
350
192
@property
@@ -364,54 +206,6 @@ def external_temperature(self):
364
206
365
207
return full_tmp
366
208
367
- def set_pwm_clock (self , use_preset = False , use_slow = False ):
368
- """
369
- Select the PWM clock source, chosing between two preset clocks or by configuring the
370
- clock using `pwm_frequency` and `pwm_frequency_divisor`.
371
-
372
- :param bool use_preset:
373
- True: Select between two preset clock sources
374
- False: The PWM clock is set by `pwm_frequency` and `pwm_frequency_divisor`
375
- :param bool use_slow:
376
- True: Use the 1.4kHz clock
377
- False: Use the 360kHz clock.
378
- :type priority: integer or None
379
- :return: None
380
- :raises AttributeError: if use_preset is not a `bool`
381
- :raises AttributeError: if use_slow is not a `bool`
382
-
383
- """
384
-
385
- if not isinstance (use_preset , bool ):
386
- raise AttributeError ("use_preset must be given a bool" )
387
- if not isinstance (use_slow , bool ):
388
- raise AttributeError ("use_slow_pwm must be given a bool" )
389
-
390
- self ._fan_pwm_clock_override = not use_preset
391
- self ._fan_pwm_clock_select = use_slow
392
-
393
- @property
394
- def pwm_frequency (self ):
395
- """Selects the base clock frequency used for the fan PWM output"""
396
- return self ._pwm_freq
397
-
398
- @pwm_frequency .setter
399
- def pwm_frequency (self , value ):
400
- if value < 0 or value > 0x1F :
401
- raise AttributeError ("pwm_frequency must be from 0-31" )
402
- self ._pwm_freq = value
403
-
404
- @property
405
- def pwm_frequency_divisor (self ):
406
- """The Divisor applied to the PWM frequency to set the final frequency"""
407
- return self ._pwm_freq_div
408
-
409
- @pwm_frequency_divisor .setter
410
- def pwm_frequency_divisor (self , divisor ):
411
- if divisor < 0 or divisor > 255 :
412
- raise AttributeError ("pwm_frequency_divisor must be from 0-255" )
413
- self ._pwm_freq_div = divisor
414
-
415
209
@property
416
210
def fan_speed (self ):
417
211
"""The current speed in Revolutions per Minute (RPM)"""
@@ -447,15 +241,6 @@ def lut_enabled(self):
447
241
to a fan speed. When the LUT is disabled fan speed can be changed with `manual_fan_speed`"""
448
242
return not self ._fan_lut_prog
449
243
450
- @lut_enabled .setter
451
- def lut_enabled (self , enable_lut ):
452
- self ._fan_lut_prog = not enable_lut
453
-
454
- @property
455
- def lut (self ):
456
- """The dict-like representation of the LUT"""
457
- return self ._lut
458
-
459
244
@property
460
245
def tach_limit (self ):
461
246
"""The maximum /minimum speed expected for the fan"""
0 commit comments