Skip to content

Commit 74b617c

Browse files
committed
worked out some kinks, ready for dox
1 parent ff47ba6 commit 74b617c

File tree

2 files changed

+108
-85
lines changed

2 files changed

+108
-85
lines changed

adafruit_mcp4728.py

Lines changed: 80 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -49,32 +49,10 @@
4949
from time import sleep
5050
import adafruit_bus_device.i2c_device as i2c_device
5151
from adafruit_register.i2c_struct import UnaryStruct
52+
import traceback
5253

5354
_MCP4728_DEFAULT_ADDRESS = 0x60
5455

55-
"""
56-
# DAC1, DAC0 DAC Channel Selection bits:
57-
# 00 = Channel A
58-
# 01 = Channel B
59-
# 10 = Channel C
60-
# 11 = Channel D
61-
62-
0 = slave addr(auto)
63-
0 1 0 0 0 DAC1 DAC0 UDAC[A]
64-
01000 + 00 + UDAC =
65-
0b01000000 = 0x40 (+2 for each successive)
66-
VREF PD1 PD0 Gx D11 D10 D9 D8 [A]
67-
D7 D6 D5 D4 D3 D2 D1 D0 [A]
68-
69-
0 1 0 0 0 Multi-Write for DAC
70-
0 1 0 1 0 Sequential Write for DAC Input Registers and EEPROM
71-
0 1 0 1 1 Single Write for DAC Input Register and EEPROM
72-
73-
1 0 0 0 0 Write Reference (VREF) selection bits to Input Registers
74-
1 1 0 0 0 Write Gain selection bits to Input Registers
75-
1 0 1 0 0 Write Power-Down bits to Input Registers
76-
"""
77-
7856
_MCP4728_CH_A_MULTI_IB = 0x40
7957
_MCP4728_CH_B_MULTI_IB = 0x42
8058
_MCP4728_CH_C_MULTI_IB = 0x44
@@ -87,8 +65,35 @@
8765

8866
_MCP4728_CH_A_MULTI_EEPROM = 0x50
8967

90-
#TODO: REMOVE THIS
91-
#pylint: disable=unused-variable,no-self-use,invalid-name,too-few-public-methods
68+
class CV:
69+
"""struct helper"""
70+
71+
@classmethod
72+
def add_values(cls, value_tuples):
73+
"creates CV entires"
74+
cls.string = {}
75+
cls.lsb = {}
76+
77+
for value_tuple in value_tuples:
78+
name, value, string, lsb = value_tuple
79+
setattr(cls, name, value)
80+
cls.string[value] = string
81+
cls.lsb[value] = lsb
82+
83+
@classmethod
84+
def is_valid(cls, value):
85+
"Returns true if the given value is a member of the CV"
86+
return value in cls.string
87+
88+
class Vref(CV):
89+
"""Options for ``vref``"""
90+
pass #pylint: disable=unnecessary-pass
91+
92+
Vref.add_values((
93+
('VDD', 0, "VDD", None),
94+
('INTERNAL', 1, "Internal 2.048V", None),
95+
))
96+
9297
class MCP4728:
9398
"""Helper library for the Microchip MCP4728 I2C 12-bit Quad DAC.
9499
@@ -111,16 +116,13 @@ class MCP4728:
111116
def __init__(self, i2c_bus, address=_MCP4728_DEFAULT_ADDRESS):
112117

113118
self.i2c_device = i2c_device.I2CDevice(i2c_bus, address)
114-
self._create_channels()
115-
116-
def _chunk(self, l, n):
117-
# For item i in a range that is a length of l,
118-
for i in range(0, len(l), n):
119-
# Create an index range for l of n items:
120-
yield l[i:i+n]
119+
120+
raw_registers = self._read_registers()
121121

122-
def _lzb(self, byte_val): # leading zero bin
123-
return format(byte_val, '#010b')
122+
self.channel_a = Channel(self, self._cache_page(*raw_registers[0]), 0)
123+
self.channel_b = Channel(self, self._cache_page(*raw_registers[1]), 1)
124+
self.channel_c = Channel(self, self._cache_page(*raw_registers[2]), 2)
125+
self.channel_d = Channel(self, self._cache_page(*raw_registers[3]), 3)
124126

125127
def _get_flags(self, high_byte):
126128
vref = (high_byte & 1<<7) > 0
@@ -131,14 +133,6 @@ def _get_flags(self, high_byte):
131133
def _cache_page(self, value, vref, gain, pd):
132134
return {"value": value, "vref": vref, "gain": gain, "pd": pd}
133135

134-
def _create_channels(self):
135-
raw_registers = self._read_registers()
136-
137-
self.channel_a = Channel(self, self._cache_page(*raw_registers[0]), 0)
138-
self.channel_b = Channel(self, self._cache_page(*raw_registers[1]), 1)
139-
self.channel_c = Channel(self, self._cache_page(*raw_registers[2]), 2)
140-
self.channel_d = Channel(self, self._cache_page(*raw_registers[3]), 3)
141-
142136
def _read_registers(self):
143137
buf = bytearray(24)
144138

@@ -182,36 +176,51 @@ def _write_multi_eeprom(self, byte_list):
182176
buffer_list += byte_list
183177

184178
buf = bytearray(buffer_list)
185-
print("buffers to eeprom:")
186179
self._print_buffer(buf)
187180
with self.i2c_device as i2c:
188181
i2c.write(buf)
189182

190183
sleep(0.015) # the better to write you with
191184

192-
def _set_vrefs(self):
193-
base_values = 0b100000000
185+
def _sync_vrefs(self):
186+
base_values = 0b10000000
194187
base_values |= (self.channel_a.vref<<3)
195188
base_values |= (self.channel_b.vref<<2)
196189
base_values |= (self.channel_c.vref<<1)
197190
base_values |= (self.channel_d.vref)
198-
print("VREP VALUES: %s"%(self._lzb(base_values)))
199-
191+
192+
print("vref values:")
193+
print(base_values)
194+
print(self._lzb(base_values))
195+
196+
buf = bytearray(1)
197+
pack_into(">B", buf, 0, base_values)
198+
print("buf bytes:")
199+
self._print_buffer(buf)
200200
with self.i2c_device as i2c:
201-
i2c.write(bytearray(base_values))
201+
i2c.write(buf)
202202

203-
def _set_gains(self):
203+
def _sync_gains(self):
204204
# [S] 1 1 0 0 A2 A1 A0 0
205205
# [A] 1 1 0 X GXA GXB GXC GXD [A] [P]
206-
base_values = 0b110000000
206+
base_values = 0b11000000
207207
base_values |= (self.channel_a.gain<<3)
208208
base_values |= (self.channel_b.gain<<2)
209209
base_values |= (self.channel_c.gain<<1)
210210
base_values |= (self.channel_d.gain)
211-
print("GAINZ VALUES: %s"%(self._lzb(base_values)))
211+
212+
213+
print("gain values:")
214+
print(base_values)
215+
print(self._lzb(base_values))
216+
217+
buf = bytearray(1)
218+
pack_into(">B", buf, 0, base_values)
219+
print("buf bytes:")
220+
self._print_buffer(buf)
212221

213222
with self.i2c_device as i2c:
214-
i2c.write(bytearray(base_values))
223+
i2c.write(buf)
215224

216225
def _set_value(self, channel):
217226

@@ -221,28 +230,33 @@ def _set_value(self, channel):
221230
write_command_byte |= (channel._channel_index<<1)
222231

223232
channel_bytes.insert(0, write_command_byte)
224-
# print("sending buffer:")
225-
# self._print_buffer(channel_bytes)
233+
226234
with self.i2c_device as i2c:
227235
i2c.write(bytearray(channel_bytes))
228236

229237
def _generate_bytes_with_flags(self, channel):
230238
buf = bytearray(2)
231239
pack_into(">H", buf, 0, channel.raw_value)
232-
# print("Value is ", channel.raw_value)
233-
# print("packed into buffer:")
234-
# self._print_buffer(buf)
235240

236241
buf[0] |= channel.vref << 7
237242
buf[0] |= channel.gain << 4
238-
# print("after setting of flags:")
239-
# self._print_buffer(buf)
243+
240244
return buf
241245

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())
242257
class Channel:
243258
"""An instance of a single channel for a multi-channel DAC"""
244259
def __init__(self, dac_instance, cache_page, index):
245-
print("Channel", index, "cache_page:", cache_page)
246260
self._vref = cache_page['vref']
247261
self._gain = cache_page['gain']
248262
self._raw_value = cache_page['value']
@@ -289,16 +303,15 @@ def raw_value(self, value):
289303

290304
@property
291305
def gain(self):
292-
"""Sets the gain of the channel. Must be 1 or 2"""
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"""
293307
return self._gain
294308

295309
@gain.setter
296310
def gain(self, value):
297-
if value < 1 or value > 2:
311+
if value != 1 and value != 2:
298312
raise AttributeError("`gain` must be 1 or 2")
299313
self._gain = value-1
300-
# needs to call gain setter with all gains.
301-
self._dac._set_gains()
314+
self._dac._sync_gains()
302315

303316
@property
304317
def vref(self):
@@ -307,7 +320,7 @@ def vref(self):
307320

308321
@vref.setter
309322
def vref(self, value):
310-
if value < 0 or value > 3:
311-
raise AttributeError("`vref` must be a ``VREF``")
323+
if not Vref.is_valid(value):
324+
raise AttributeError("range must be a `Vref`")
312325
self._vref = value
313-
self._dac._set_vrefs()
326+
self._dac._sync_vrefs()

examples/mcp4728_setter_test.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
import board
22
import busio
33
import adafruit_mcp4728
4-
4+
from adafruit_mcp4728 import Vref
5+
import digitalio
56
i2c = busio.I2C(board.SCL, board.SDA)
67
mcp4728 = adafruit_mcp4728.MCP4728(i2c)
78

8-
# mcp4728.channel_a.value = 0 # Voltage = VCC
9-
# mcp4728.channel_b.value = 50 # VCC/2
10-
# mcp4728.channel_c.value = 100 # VCC/4
11-
# mcp4728.channel_d.value = 65535 # VCC/8
9+
mcp4728.channel_a.value = 32768 # Voltage = VCC
10+
mcp4728.channel_b.value = 32768 # VCC/2
11+
mcp4728.channel_c.value = 32768 # VCC/4
12+
mcp4728.channel_d.value = 32768 # VCC/8
13+
1214

13-
# mcp4728.channel_a.gain = 2
14-
# mcp4728.channel_b.gain = 2
15-
# mcp4728.channel_c.gain = 2
16-
# mcp4728.channel_d.gain = 2
15+
mcp4728.channel_a.gain = 1
16+
mcp4728.channel_b.gain = 2
17+
mcp4728.channel_c.gain = 1
18+
mcp4728.channel_d.gain = 2
1719

18-
# mcp4728.channel_a.vref = 0
19-
# mcp4728.channel_b.vref = 0
20-
# mcp4728.channel_c.vref = 0
21-
# mcp4728.channel_d.vref = 0
20+
mcp4728.channel_a.vref = Vref.INTERNAL
21+
mcp4728.channel_b.vref = Vref.INTERNAL
22+
mcp4728.channel_c.vref = Vref.INTERNAL
23+
mcp4728.channel_d.vref = Vref.INTERNAL
2224

25+
print("cha raw value:", mcp4728.channel_a.raw_value)
26+
print("chb raw value:", mcp4728.channel_b.raw_value)
27+
print("chc raw value:", mcp4728.channel_c.raw_value)
28+
print("chd raw value:", mcp4728.channel_d.raw_value)
29+
print()
2330
print("cha value:", mcp4728.channel_a.value)
2431
print("chb value:", mcp4728.channel_b.value)
2532
print("chc value:", mcp4728.channel_c.value)
@@ -31,10 +38,13 @@
3138
print("chc gain:", mcp4728.channel_c.gain)
3239
print("chd gain:", mcp4728.channel_d.gain)
3340
print()
34-
print("cha vref:", mcp4728.channel_a.vref)
35-
print("chb vref:", mcp4728.channel_b.vref)
36-
print("chc vref:", mcp4728.channel_c.vref)
37-
print("chd vref:", mcp4728.channel_d.vref)
41+
print("cha vref:", Vref.string[mcp4728.channel_a.vref])
42+
print("chb vref:", Vref.string[mcp4728.channel_b.vref])
43+
print("chc vref:", Vref.string[mcp4728.channel_c.vref])
44+
print("chd vref:", Vref.string[mcp4728.channel_d.vref])
3845

46+
mcp4728._read_registers()
3947

40-
# mcp4728.save_settings()
48+
print("saving regs")
49+
mcp4728.save_settings()
50+
mcp4728._read_registers()

0 commit comments

Comments
 (0)