@@ -139,9 +139,50 @@ typedef struct _pyb_dac_obj_t {
139139 mp_obj_base_t base ;
140140 uint32_t dac_channel ; // DAC_CHANNEL_1 or DAC_CHANNEL_2
141141 DMA_Stream_TypeDef * dma_stream ; // DMA1_Stream5 or DMA1_Stream6
142- pyb_dac_state_t state ;
142+ uint16_t pin ; // GPIO_PIN_4 or GPIO_PIN_5
143+ uint8_t bits ; // 8 or 12
144+ uint8_t state ;
143145} pyb_dac_obj_t ;
144146
147+ STATIC mp_obj_t pyb_dac_init_helper (pyb_dac_obj_t * self , mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
148+ static const mp_arg_t allowed_args [] = {
149+ { MP_QSTR_bits , MP_ARG_INT , {.u_int = 8 } },
150+ };
151+
152+ // parse args
153+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
154+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
155+
156+ // GPIO configuration
157+ GPIO_InitTypeDef GPIO_InitStructure ;
158+ GPIO_InitStructure .Pin = self -> pin ;
159+ GPIO_InitStructure .Mode = GPIO_MODE_ANALOG ;
160+ GPIO_InitStructure .Pull = GPIO_NOPULL ;
161+ HAL_GPIO_Init (GPIOA , & GPIO_InitStructure );
162+
163+ // DAC peripheral clock
164+ __DAC_CLK_ENABLE ();
165+
166+ // stop anything already going on
167+ HAL_DAC_Stop (& DAC_Handle , self -> dac_channel );
168+ if ((self -> dac_channel == DAC_CHANNEL_1 && DAC_Handle .DMA_Handle1 != NULL )
169+ || (self -> dac_channel == DAC_CHANNEL_2 && DAC_Handle .DMA_Handle2 != NULL )) {
170+ HAL_DAC_Stop_DMA (& DAC_Handle , self -> dac_channel );
171+ }
172+
173+ // set bit resolution
174+ if (args [0 ].u_int == 8 || args [0 ].u_int == 12 ) {
175+ self -> bits = args [0 ].u_int ;
176+ } else {
177+ nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "unsupported bits" ));
178+ }
179+
180+ // reset state of DAC
181+ self -> state = DAC_STATE_RESET ;
182+
183+ return mp_const_none ;
184+ }
185+
145186// create the dac object
146187// currently support either DAC1 on X5 (id = 1) or DAC2 on X6 (id = 2)
147188
@@ -152,7 +193,7 @@ typedef struct _pyb_dac_obj_t {
152193/// DAC(1) is on pin X5 and DAC(2) is on pin X6.
153194STATIC mp_obj_t pyb_dac_make_new (mp_obj_t type_in , mp_uint_t n_args , mp_uint_t n_kw , const mp_obj_t * args ) {
154195 // check arguments
155- mp_arg_check_num (n_args , n_kw , 1 , 1 , false );
196+ mp_arg_check_num (n_args , n_kw , 1 , MP_OBJ_FUN_ARGS_MAX , true );
156197
157198 // get pin/channel to output on
158199 mp_int_t dac_id ;
@@ -172,42 +213,32 @@ STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
172213 pyb_dac_obj_t * dac = m_new_obj (pyb_dac_obj_t );
173214 dac -> base .type = & pyb_dac_type ;
174215
175- uint32_t pin ;
176216 if (dac_id == 1 ) {
177- pin = GPIO_PIN_4 ;
217+ dac -> pin = GPIO_PIN_4 ;
178218 dac -> dac_channel = DAC_CHANNEL_1 ;
179219 dac -> dma_stream = DMA1_Stream5 ;
180220 } else if (dac_id == 2 ) {
181- pin = GPIO_PIN_5 ;
221+ dac -> pin = GPIO_PIN_5 ;
182222 dac -> dac_channel = DAC_CHANNEL_2 ;
183223 dac -> dma_stream = DMA1_Stream6 ;
184224 } else {
185225 nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "DAC %d does not exist" , dac_id ));
186226 }
187227
188- // GPIO configuration
189- GPIO_InitTypeDef GPIO_InitStructure ;
190- GPIO_InitStructure .Pin = pin ;
191- GPIO_InitStructure .Mode = GPIO_MODE_ANALOG ;
192- GPIO_InitStructure .Pull = GPIO_NOPULL ;
193- HAL_GPIO_Init (GPIOA , & GPIO_InitStructure );
194-
195- // DAC peripheral clock
196- __DAC_CLK_ENABLE ();
197-
198- // stop anything already going on
199- HAL_DAC_Stop (& DAC_Handle , dac -> dac_channel );
200- if ((dac -> dac_channel == DAC_CHANNEL_1 && DAC_Handle .DMA_Handle1 != NULL )
201- || (dac -> dac_channel == DAC_CHANNEL_2 && DAC_Handle .DMA_Handle2 != NULL )) {
202- HAL_DAC_Stop_DMA (& DAC_Handle , dac -> dac_channel );
203- }
204-
205- dac -> state = DAC_STATE_RESET ;
228+ // configure the peripheral
229+ mp_map_t kw_args ;
230+ mp_map_init_fixed_table (& kw_args , n_kw , args + n_args );
231+ pyb_dac_init_helper (dac , n_args - 1 , args + 1 , & kw_args );
206232
207233 // return object
208234 return dac ;
209235}
210236
237+ STATIC mp_obj_t pyb_dac_init (mp_uint_t n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
238+ return pyb_dac_init_helper (args [0 ], n_args - 1 , args + 1 , kw_args );
239+ }
240+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_dac_init_obj , 1 , pyb_dac_init );
241+
211242#if defined(TIM6 )
212243/// \method noise(freq)
213244/// Generate a pseudo-random noise signal. A new random sample is written
@@ -280,7 +311,11 @@ STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) {
280311 self -> state = DAC_STATE_WRITE_SINGLE ;
281312 }
282313
283- HAL_DAC_SetValue (& DAC_Handle , self -> dac_channel , DAC_ALIGN_8B_R , mp_obj_get_int (val ));
314+ // DAC output is always 12-bit at the hardware level, and we provide support
315+ // for multiple bit "resolutions" simply by shifting the input value.
316+ HAL_DAC_SetValue (& DAC_Handle , self -> dac_channel , DAC_ALIGN_12B_R ,
317+ mp_obj_get_int (val ) << (12 - self -> bits ));
318+
284319 HAL_DAC_Start (& DAC_Handle , self -> dac_channel );
285320
286321 return mp_const_none ;
@@ -365,8 +400,13 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
365400 DMA_Handle .Init .Direction = DMA_MEMORY_TO_PERIPH ;
366401 DMA_Handle .Init .PeriphInc = DMA_PINC_DISABLE ;
367402 DMA_Handle .Init .MemInc = DMA_MINC_ENABLE ;
368- DMA_Handle .Init .PeriphDataAlignment = DMA_PDATAALIGN_BYTE ;
369- DMA_Handle .Init .MemDataAlignment = DMA_MDATAALIGN_BYTE ;
403+ if (self -> bits == 8 ) {
404+ DMA_Handle .Init .PeriphDataAlignment = DMA_PDATAALIGN_BYTE ;
405+ DMA_Handle .Init .MemDataAlignment = DMA_MDATAALIGN_BYTE ;
406+ } else {
407+ DMA_Handle .Init .PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD ;
408+ DMA_Handle .Init .MemDataAlignment = DMA_MDATAALIGN_HALFWORD ;
409+ }
370410 DMA_Handle .Init .Mode = args [2 ].u_int ;
371411 DMA_Handle .Init .Priority = DMA_PRIORITY_HIGH ;
372412 DMA_Handle .Init .FIFOMode = DMA_FIFOMODE_DISABLE ;
@@ -393,7 +433,13 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
393433 self -> state = DAC_STATE_DMA_WAVEFORM + dac_trigger ;
394434 }
395435
396- HAL_DAC_Start_DMA (& DAC_Handle , self -> dac_channel , (uint32_t * )bufinfo .buf , bufinfo .len , DAC_ALIGN_8B_R );
436+ if (self -> bits == 8 ) {
437+ HAL_DAC_Start_DMA (& DAC_Handle , self -> dac_channel ,
438+ (uint32_t * )bufinfo .buf , bufinfo .len , DAC_ALIGN_8B_R );
439+ } else {
440+ HAL_DAC_Start_DMA (& DAC_Handle , self -> dac_channel ,
441+ (uint32_t * )bufinfo .buf , bufinfo .len / 2 , DAC_ALIGN_12B_R );
442+ }
397443
398444 /*
399445 // enable DMA stream
@@ -417,6 +463,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_write_timed_obj, 1, pyb_dac_write_time
417463
418464STATIC const mp_map_elem_t pyb_dac_locals_dict_table [] = {
419465 // instance methods
466+ { MP_OBJ_NEW_QSTR (MP_QSTR_init ), (mp_obj_t )& pyb_dac_init_obj },
420467 { MP_OBJ_NEW_QSTR (MP_QSTR_write ), (mp_obj_t )& pyb_dac_write_obj },
421468 #if defined(TIM6 )
422469 { MP_OBJ_NEW_QSTR (MP_QSTR_noise ), (mp_obj_t )& pyb_dac_noise_obj },
0 commit comments