diff --git a/stmhal/dac.c b/stmhal/dac.c index db18127001..92edb24d76 100644 --- a/stmhal/dac.c +++ b/stmhal/dac.c @@ -45,9 +45,6 @@ typedef struct _pyb_dac_obj_t { machine_uint_t state; } pyb_dac_obj_t; -STATIC pyb_dac_obj_t pyb_dac_channel_1 = {{&pyb_dac_type}, DAC_CHANNEL_1, DMA1_Stream5}; -STATIC pyb_dac_obj_t pyb_dac_channel_2 = {{&pyb_dac_type}, DAC_CHANNEL_2, DMA1_Stream6}; - // create the dac object // currently support either DAC1 on X5 (id = 1) or DAC2 on X6 (id = 2) @@ -55,18 +52,21 @@ STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); + pyb_dac_obj_t *dac = m_new_obj(pyb_dac_obj_t); + dac->base.type = &pyb_dac_type; + machine_int_t dac_id = mp_obj_get_int(args[0]); uint32_t pin; - pyb_dac_obj_t *dac_obj; - if (dac_id == 1) { pin = GPIO_PIN_4; - dac_obj = &pyb_dac_channel_1; + dac->dac_channel = DAC_CHANNEL_1; + dac->dma_stream = DMA1_Stream5; } else if (dac_id == 2) { pin = GPIO_PIN_5; - dac_obj = &pyb_dac_channel_2; + dac->dac_channel = DAC_CHANNEL_2; + dac->dma_stream = DMA1_Stream6; } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Dac %d does not exist", dac_id)); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "DAC %d does not exist", dac_id)); } // GPIO configuration @@ -80,13 +80,13 @@ STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const __DAC_CLK_ENABLE(); // stop anything already going on - HAL_DAC_Stop(&DAC_Handle, dac_obj->dac_channel); - HAL_DAC_Stop_DMA(&DAC_Handle, dac_obj->dac_channel); + HAL_DAC_Stop(&DAC_Handle, dac->dac_channel); + HAL_DAC_Stop_DMA(&DAC_Handle, dac->dac_channel); - dac_obj->state = 0; + dac->state = 0; // return object - return dac_obj; + return dac; } STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) { @@ -111,7 +111,6 @@ STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) { return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_noise_obj, pyb_dac_noise); STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) { @@ -136,7 +135,6 @@ STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) { return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_triangle_obj, pyb_dac_triangle); // direct access to DAC (8 bit only at the moment) @@ -156,21 +154,34 @@ STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) { return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write); // initiates a burst of RAM->DAC using DMA // input data is treated as an array of bytes (8 bit data) // TIM6 is used to set the frequency of the transfer -// TODO still needs some attention to get it working properly -mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { +// TODO add callback argument, to call when transfer is finished +// TODO add double buffer argument + +STATIC const mp_arg_parse_t pyb_dac_write_timed_accepted_args[] = { + { MP_QSTR_data, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_freq, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_INT, {.u_int = 0} }, + { MP_QSTR_mode, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = DMA_NORMAL} }, +}; +#define PYB_DAC_WRITE_TIMED_NUM_ARGS (sizeof(pyb_dac_write_timed_accepted_args) / sizeof(pyb_dac_write_timed_accepted_args[0])) + +mp_obj_t pyb_dac_write_timed(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_dac_obj_t *self = args[0]; - // set TIM6 to trigger the DAC at the given frequency - TIM6_Config(mp_obj_get_int(args[2])); + // parse args + mp_arg_parse_val_t vals[PYB_DAC_WRITE_TIMED_NUM_ARGS]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_DAC_WRITE_TIMED_NUM_ARGS, pyb_dac_write_timed_accepted_args, vals); + // get the data to write mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(vals[0].u_obj, &bufinfo, MP_BUFFER_READ); + + // set TIM6 to trigger the DAC at the given frequency + TIM6_Config(vals[1].u_int); __DMA1_CLK_ENABLE(); @@ -206,8 +217,7 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { DMA_Handle.Init.MemInc = DMA_MINC_ENABLE; DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - mp_map_elem_t *kw_mode = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("mode")), MP_MAP_LOOKUP); - DMA_Handle.Init.Mode = kw_mode == NULL ? DMA_NORMAL : mp_obj_get_int(kw_mode->value); // normal = 0, circular = 0x100 + DMA_Handle.Init.Mode = vals[2].u_int; DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH; DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; @@ -248,17 +258,18 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { return mp_const_none; } - -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_dma_obj, 3, pyb_dac_dma); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_write_timed_obj, 1, pyb_dac_write_timed); STATIC const mp_map_elem_t pyb_dac_locals_dict_table[] = { + // instance methods { MP_OBJ_NEW_QSTR(MP_QSTR_noise), (mp_obj_t)&pyb_dac_noise_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_triangle), (mp_obj_t)&pyb_dac_triangle_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_dac_write_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_dma), (mp_obj_t)&pyb_dac_dma_obj }, - // TODO add function that does double buffering: - // dma2(freq, buf1, buf2, callback) - // where callback is called when the buffer has been drained + { MP_OBJ_NEW_QSTR(MP_QSTR_write_timed), (mp_obj_t)&pyb_dac_write_timed_obj }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_NORMAL), MP_OBJ_NEW_SMALL_INT(DMA_NORMAL) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CIRCULAR), MP_OBJ_NEW_SMALL_INT(DMA_CIRCULAR) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_dac_locals_dict, pyb_dac_locals_dict_table); diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 830514d35b..390c8fca9f 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -166,11 +166,17 @@ Q(read_core_temp) Q(read_core_vbat) Q(read_core_vref) -// for DAC object +// for DAC class Q(DAC) Q(noise) Q(triangle) -Q(dma) +Q(write) +Q(write_timed) +Q(data) +Q(freq) +Q(mode) +Q(NORMAL) +Q(CIRCULAR) // for Servo object Q(Servo)