stmhal: Make DAC dynamically allocate instances; rename dma->write_timed.

This commit is contained in:
Damien George 2014-04-21 13:06:19 +01:00
parent 83407ad082
commit 764af4b7c5
2 changed files with 47 additions and 30 deletions

View File

@ -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);

View File

@ -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)