48
48
from struct import pack_into
49
49
from time import sleep
50
50
import adafruit_bus_device .i2c_device as i2c_device
51
- from adafruit_register .i2c_struct import UnaryStruct
52
- import traceback
53
51
54
52
_MCP4728_DEFAULT_ADDRESS = 0x60
55
53
56
- _MCP4728_CH_A_MULTI_IB = 0x40
57
- _MCP4728_CH_B_MULTI_IB = 0x42
58
- _MCP4728_CH_C_MULTI_IB = 0x44
59
- _MCP4728_CH_D_MULTI_IB = 0x46
60
-
61
- _MCP4728_CH_A_SINGLE_EEPROM = 0x58
62
- _MCP4728_CH_B_SINGLE_EEPROM = 0x5A
63
- _MCP4728_CH_C_SINGLE_EEPROM = 0x5C
64
- _MCP4728_CH_D_SINGLE_EEPROM = 0x5E
65
-
66
54
_MCP4728_CH_A_MULTI_EEPROM = 0x50
67
55
68
56
class CV :
@@ -101,68 +89,49 @@ class MCP4728:
101
89
:param address: The I2C slave address of the sensor
102
90
103
91
"""
104
- _channel_a_single_write_eeprom = UnaryStruct (_MCP4728_CH_A_SINGLE_EEPROM , ">H" )
105
- _channel_b_single_write_eeprom = UnaryStruct (_MCP4728_CH_B_SINGLE_EEPROM , ">H" )
106
- _channel_c_single_write_eeprom = UnaryStruct (_MCP4728_CH_C_SINGLE_EEPROM , ">H" )
107
- _channel_d_single_write_eeprom = UnaryStruct (_MCP4728_CH_D_SINGLE_EEPROM , ">H" )
108
-
109
- _channel_a_multi_write = UnaryStruct (_MCP4728_CH_A_MULTI_IB , ">H" )
110
- _channel_b_multi_write = UnaryStruct (_MCP4728_CH_B_MULTI_IB , ">H" )
111
- _channel_c_multi_write = UnaryStruct (_MCP4728_CH_C_MULTI_IB , ">H" )
112
- _channel_d_multi_write = UnaryStruct (_MCP4728_CH_D_MULTI_IB , ">H" )
113
-
114
- _multi_write_channel_a_start = UnaryStruct (_MCP4728_CH_A_MULTI_EEPROM , ">HHHH" )
115
92
116
93
def __init__ (self , i2c_bus , address = _MCP4728_DEFAULT_ADDRESS ):
117
94
118
95
self .i2c_device = i2c_device .I2CDevice (i2c_bus , address )
119
-
96
+
120
97
raw_registers = self ._read_registers ()
121
98
122
99
self .channel_a = Channel (self , self ._cache_page (* raw_registers [0 ]), 0 )
123
100
self .channel_b = Channel (self , self ._cache_page (* raw_registers [1 ]), 1 )
124
101
self .channel_c = Channel (self , self ._cache_page (* raw_registers [2 ]), 2 )
125
102
self .channel_d = Channel (self , self ._cache_page (* raw_registers [3 ]), 3 )
126
103
127
- def _get_flags (self , high_byte ):
104
+ @staticmethod
105
+ def _get_flags (high_byte ):
128
106
vref = (high_byte & 1 << 7 ) > 0
129
107
gain = (high_byte & 1 << 4 ) > 0
130
- pd = (high_byte & 0b011 << 5 )>> 5
131
- return (vref , gain , pd )
108
+ power_state = (high_byte & 0b011 << 5 )>> 5
109
+ return (vref , gain , power_state )
132
110
133
- def _cache_page (self , value , vref , gain , pd ):
134
- return {"value" : value , "vref" : vref , "gain" : gain , "pd" : pd }
111
+ @staticmethod
112
+ def _cache_page (value , vref , gain , power_state ):
113
+ return {"value" : value , "vref" : vref , "gain" : gain , "power_state" : power_state }
135
114
136
115
def _read_registers (self ):
137
116
buf = bytearray (24 )
138
117
139
118
with self .i2c_device as i2c :
140
119
i2c .readinto (buf )
141
120
142
- self ._print_buffer (buf )
143
-
144
121
# stride is 6 because we get 6 bytes for each channel; 3 for the output regs
145
- # and 3 for the eeprom. here we only care about the output buffer so we throw out
122
+ # and 3 for the eeprom. Here we only care about the output regoster so we throw out
146
123
# the eeprom values as 'n/a'
147
124
current_values = []
148
- for header , high_byte , low_byte , na_1 , na_2 , na_3 in self ._chunk (buf , 6 ):
125
+ for header , high_byte , low_byte , na_1 , na_2 , na_3 in self ._chunk (buf , 6 ):#pylint:disable=unused-variable
149
126
value = (high_byte & 0b00001111 ) << 8 | low_byte
150
- vref , gain , pd = self ._get_flags (high_byte )
151
- current_values .append ((value , vref , gain , pd ))
127
+ vref , gain , power_state = self ._get_flags (high_byte )
128
+ current_values .append ((value , vref , gain , power_state ))
152
129
153
130
return current_values
154
131
155
- def _print_buffer (self , buf ):
156
- print ()
157
- for index , value in enumerate (buf ):
158
- if index % 3 == 0 :
159
- print ("\n %4s\t " % index , end = "" )
160
- print ("%s %s " % (format (value , '#010b' ), hex (value )), end = "" )
161
- print ()
162
-
163
-
164
132
def save_settings (self ):
165
- """Saves the currently selected values, Vref, and gain selections for each channel to the EEPROM, setting them as defaults on power up"""
133
+ """Saves the currently selected values, Vref, and gain selections for each channel
134
+ to the EEPROM, setting them as defaults on power up"""
166
135
byte_list = []
167
136
byte_list += self ._generate_bytes_with_flags (self .channel_a )
168
137
byte_list += self ._generate_bytes_with_flags (self .channel_b )
@@ -176,48 +145,36 @@ def _write_multi_eeprom(self, byte_list):
176
145
buffer_list += byte_list
177
146
178
147
buf = bytearray (buffer_list )
179
- self . _print_buffer ( buf )
148
+
180
149
with self .i2c_device as i2c :
181
150
i2c .write (buf )
182
151
183
152
sleep (0.015 ) # the better to write you with
184
153
185
- def _sync_vrefs (self ):
186
- base_values = 0b10000000
187
- base_values |= (self .channel_a .vref << 3 )
188
- base_values |= (self .channel_b .vref << 2 )
189
- base_values |= (self .channel_c .vref << 1 )
190
- base_values |= (self .channel_d .vref )
191
-
192
- print ("vref values:" )
193
- print (base_values )
194
- print (self ._lzb (base_values ))
154
+ def sync_vrefs (self ):
155
+ """Syncs the driver's vref state with the DAC"""
156
+ gain_setter_command = 0b10000000
157
+ gain_setter_command |= (self .channel_a .vref << 3 )
158
+ gain_setter_command |= (self .channel_b .vref << 2 )
159
+ gain_setter_command |= (self .channel_c .vref << 1 )
160
+ gain_setter_command |= (self .channel_d .vref )
195
161
196
162
buf = bytearray (1 )
197
- pack_into (">B" , buf , 0 , base_values )
198
- print ("buf bytes:" )
199
- self ._print_buffer (buf )
163
+ pack_into (">B" , buf , 0 , gain_setter_command )
200
164
with self .i2c_device as i2c :
201
165
i2c .write (buf )
202
166
203
- def _sync_gains (self ):
204
- # [S] 1 1 0 0 A2 A1 A0 0
205
- # [A] 1 1 0 X GXA GXB GXC GXD [A] [P]
206
- base_values = 0b11000000
207
- base_values |= (self .channel_a .gain << 3 )
208
- base_values |= (self .channel_b .gain << 2 )
209
- base_values |= (self .channel_c .gain << 1 )
210
- base_values |= (self .channel_d .gain )
211
-
167
+ def sync_gains (self ):
168
+ """Syncs the driver's gain state with the DAC"""
212
169
213
- print ("gain values:" )
214
- print (base_values )
215
- print (self ._lzb (base_values ))
170
+ sync_setter_command = 0b11000000
171
+ sync_setter_command |= (self .channel_a .gain << 3 )
172
+ sync_setter_command |= (self .channel_b .gain << 2 )
173
+ sync_setter_command |= (self .channel_c .gain << 1 )
174
+ sync_setter_command |= (self .channel_d .gain )
216
175
217
176
buf = bytearray (1 )
218
- pack_into (">B" , buf , 0 , base_values )
219
- print ("buf bytes:" )
220
- self ._print_buffer (buf )
177
+ pack_into (">B" , buf , 0 , sync_setter_command )
221
178
222
179
with self .i2c_device as i2c :
223
180
i2c .write (buf )
@@ -227,14 +184,15 @@ def _set_value(self, channel):
227
184
channel_bytes = self ._generate_bytes_with_flags (channel )
228
185
229
186
write_command_byte = 0b01000000 # 0 1 0 0 0 DAC1 DAC0 UDAC
230
- write_command_byte |= (channel ._channel_index << 1 )
187
+ write_command_byte |= (channel .channel_index << 1 )
231
188
232
189
channel_bytes .insert (0 , write_command_byte )
233
190
234
191
with self .i2c_device as i2c :
235
192
i2c .write (bytearray (channel_bytes ))
236
193
237
- def _generate_bytes_with_flags (self , channel ):
194
+ @staticmethod
195
+ def _generate_bytes_with_flags (channel ):
238
196
buf = bytearray (2 )
239
197
pack_into (">H" , buf , 0 , channel .raw_value )
240
198
@@ -243,25 +201,22 @@ def _generate_bytes_with_flags(self, channel):
243
201
244
202
return buf
245
203
246
- def _chunk (self , l , n ):
247
- # For item i in a range that is a length of l,
248
- for i in range (0 , len (l ), n ):
249
- # Create an index range for l of n items:
250
- yield l [i :i + n ]
251
-
252
- def _lzb (self , byte_val ): # leading zero bin
253
- return format (byte_val , '#010b' )
254
- def _bt (self ):
255
- for line in traceback .format_stack ():
256
- print (line .strip ())
204
+ @staticmethod
205
+ def _chunk (big_list , chunk_size ):
206
+ """Divides a given list into `chunk_size` sized chunks"""
207
+ for i in range (0 , len (big_list ), chunk_size ):
208
+ yield big_list [i :i + chunk_size ]
209
+
257
210
class Channel :
258
- """An instance of a single channel for a multi-channel DAC"""
211
+ """An instance of a single channel for a multi-channel DAC.
212
+
213
+ **All available channels are created automatically and should not be created by the user**"""
259
214
def __init__ (self , dac_instance , cache_page , index ):
260
215
self ._vref = cache_page ['vref' ]
261
216
self ._gain = cache_page ['gain' ]
262
217
self ._raw_value = cache_page ['value' ]
263
218
self ._dac = dac_instance
264
- self ._channel_index = index
219
+ self .channel_index = index
265
220
266
221
@property
267
222
def normalized_value (self ):
@@ -299,19 +254,25 @@ def raw_value(self, value):
299
254
if value < 0 or value > (2 ** 12 - 1 ):
300
255
raise AttributeError ("`raw_value` must be a 12-bit integer between 0 and %s" % (2 ** 12 - 1 ))
301
256
self ._raw_value = value
302
- self ._dac ._set_value (self )
257
+ # disabling the protected access warning here because making it public would be
258
+ # more confusing
259
+ self ._dac ._set_value (self ) #pylint:disable=protected-access
303
260
304
261
@property
305
262
def gain (self ):
306
- """Sets the gain of the channel if the Vref for the channel is ``Vref.INTERNAL``. *The gain setting has no effect if the Vref for the channel is `Vref.VDD`*. With gain set to 1, the output voltage goes from 0v to 2.048V. If a channe's gain is set to 2, the voltage goes from 0v to 4.096V. `gain` Must be 1 or 2"""
263
+ """Sets the gain of the channel if the Vref for the channel is ``Vref.INTERNAL``.
264
+ **The gain setting has no effect if the Vref for the channel is `Vref.VDD`**.
265
+
266
+ With gain set to 1, the output voltage goes from 0v to 2.048V. If a channe's gain is set
267
+ to 2, the voltage goes from 0v to 4.096V. `gain` Must be 1 or 2"""
307
268
return self ._gain
308
269
309
270
@gain .setter
310
271
def gain (self , value ):
311
- if value != 1 and value != 2 :
272
+ if not value in ( 1 , 2 ) :
312
273
raise AttributeError ("`gain` must be 1 or 2" )
313
274
self ._gain = value - 1
314
- self ._dac ._sync_gains ()
275
+ self ._dac .sync_gains ()
315
276
316
277
@property
317
278
def vref (self ):
@@ -323,4 +284,4 @@ def vref(self, value):
323
284
if not Vref .is_valid (value ):
324
285
raise AttributeError ("range must be a `Vref`" )
325
286
self ._vref = value
326
- self ._dac ._sync_vrefs ()
287
+ self ._dac .sync_vrefs ()
0 commit comments