Skip to content

Commit b30e0d2

Browse files
committed
stm32/dac: Add buffering argument to constructor and init() method.
This can be used to select the output buffer behaviour of the DAC. The default values are chosen to retain backwards compatibility with existing behaviour. Thanks to @peterhinch for the initial idea to add this feature.
1 parent aebd970 commit b30e0d2

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

docs/library/pyb.DAC.rst

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ To output a continuous sine-wave at 12-bit resolution::
4949
Constructors
5050
------------
5151

52-
.. class:: pyb.DAC(port, bits=8)
52+
.. class:: pyb.DAC(port, bits=8, \*, buffering=None)
5353

5454
Construct a new DAC object.
5555

@@ -60,12 +60,27 @@ Constructors
6060
The maximum value for the write and write_timed methods will be
6161
2\*\*``bits``-1.
6262

63+
The *buffering* parameter selects the behaviour of the DAC op-amp output
64+
buffer, whose purpose is to reduce the output impedance. It can be
65+
``None`` to select the default (buffering enabled for :meth:`DAC.noise`,
66+
:meth:`DAC.triangle` and :meth:`DAC.write_timed`, and disabled for
67+
:meth:`DAC.write`), ``False`` to disable buffering completely, or ``True``
68+
to enable output buffering.
69+
70+
When buffering is enabled the DAC pin can drive loads down to 5KΩ.
71+
Otherwise it has an output impedance of 15KΩ maximum: consequently
72+
to achieve a 1% accuracy without buffering requires the applied load
73+
to be less than 1.5MΩ. Using the buffer incurs a penalty in accuracy,
74+
especially near the extremes of range.
75+
6376
Methods
6477
-------
6578

66-
.. method:: DAC.init(bits=8)
79+
.. method:: DAC.init(bits=8, \*, buffering=None)
6780

68-
Reinitialise the DAC. ``bits`` can be 8 or 12.
81+
Reinitialise the DAC. *bits* can be 8 or 12. *buffering* can be
82+
``None``, ``False`` or ``True`; see above constructor for the meaning
83+
of this parameter.
6984
7085
.. method:: DAC.deinit()
7186

ports/stm32/dac.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,14 @@ typedef struct _pyb_dac_obj_t {
143143
uint16_t pin; // GPIO_PIN_4 or GPIO_PIN_5
144144
uint8_t bits; // 8 or 12
145145
uint8_t state;
146+
uint8_t outbuf_single;
147+
uint8_t outbuf_waveform;
146148
} pyb_dac_obj_t;
147149

148150
STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
149151
static const mp_arg_t allowed_args[] = {
150152
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
153+
{ MP_QSTR_buffering, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
151154
};
152155

153156
// parse args
@@ -194,6 +197,19 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp
194197
mp_raise_ValueError("unsupported bits");
195198
}
196199

200+
// set output buffer config
201+
if (args[1].u_obj == mp_const_none) {
202+
// due to legacy, default values differ for single and waveform outputs
203+
self->outbuf_single = DAC_OUTPUTBUFFER_DISABLE;
204+
self->outbuf_waveform = DAC_OUTPUTBUFFER_ENABLE;
205+
} else if (mp_obj_is_true(args[1].u_obj)) {
206+
self->outbuf_single = DAC_OUTPUTBUFFER_ENABLE;
207+
self->outbuf_waveform = DAC_OUTPUTBUFFER_ENABLE;
208+
} else {
209+
self->outbuf_single = DAC_OUTPUTBUFFER_DISABLE;
210+
self->outbuf_waveform = DAC_OUTPUTBUFFER_DISABLE;
211+
}
212+
197213
// reset state of DAC
198214
self->state = DAC_STATE_RESET;
199215

@@ -289,7 +305,7 @@ STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) {
289305
// configure DAC to trigger via TIM6
290306
DAC_ChannelConfTypeDef config;
291307
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
292-
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
308+
config.DAC_OutputBuffer = self->outbuf_waveform;
293309
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
294310
self->state = DAC_STATE_BUILTIN_WAVEFORM;
295311
}
@@ -319,7 +335,7 @@ STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) {
319335
// configure DAC to trigger via TIM6
320336
DAC_ChannelConfTypeDef config;
321337
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
322-
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
338+
config.DAC_OutputBuffer = self->outbuf_waveform;
323339
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
324340
self->state = DAC_STATE_BUILTIN_WAVEFORM;
325341
}
@@ -342,7 +358,7 @@ STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) {
342358
if (self->state != DAC_STATE_WRITE_SINGLE) {
343359
DAC_ChannelConfTypeDef config;
344360
config.DAC_Trigger = DAC_TRIGGER_NONE;
345-
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
361+
config.DAC_OutputBuffer = self->outbuf_single;
346362
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
347363
self->state = DAC_STATE_WRITE_SINGLE;
348364
}
@@ -454,7 +470,7 @@ mp_obj_t pyb_dac_write_timed(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
454470
if (self->state != DAC_STATE_DMA_WAVEFORM + dac_trigger) {
455471
DAC_ChannelConfTypeDef config;
456472
config.DAC_Trigger = dac_trigger;
457-
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
473+
config.DAC_OutputBuffer = self->outbuf_waveform;
458474
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
459475
self->state = DAC_STATE_DMA_WAVEFORM + dac_trigger;
460476
}

tests/pyb/dac.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@
1212
dac.write_timed(bytearray(10), 100, mode=pyb.DAC.NORMAL)
1313
pyb.delay(20)
1414
dac.write(0)
15+
16+
# test buffering arg
17+
dac = pyb.DAC(1, buffering=True)
18+
dac.write(0)

0 commit comments

Comments
 (0)