|
|
@ -96,11 +96,18 @@ STATIC void TIM6_Config(uint freq) { |
|
|
|
/******************************************************************************/ |
|
|
|
// Micro Python bindings
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
DAC_STATE_RESET, |
|
|
|
DAC_STATE_WRITE_SINGLE, |
|
|
|
DAC_STATE_BUILTIN_WAVEFORM, |
|
|
|
DAC_STATE_DMA_WAVEFORM, |
|
|
|
} pyb_dac_state_t; |
|
|
|
|
|
|
|
typedef struct _pyb_dac_obj_t { |
|
|
|
mp_obj_base_t base; |
|
|
|
uint32_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2
|
|
|
|
DMA_Stream_TypeDef *dma_stream; // DMA1_Stream5 or DMA1_Stream6
|
|
|
|
mp_uint_t state; |
|
|
|
pyb_dac_state_t state; |
|
|
|
} pyb_dac_obj_t; |
|
|
|
|
|
|
|
// create the dac object
|
|
|
@ -163,7 +170,7 @@ STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n |
|
|
|
HAL_DAC_Stop_DMA(&DAC_Handle, dac->dac_channel); |
|
|
|
} |
|
|
|
|
|
|
|
dac->state = 0; |
|
|
|
dac->state = DAC_STATE_RESET; |
|
|
|
|
|
|
|
// return object
|
|
|
|
return dac; |
|
|
@ -179,13 +186,13 @@ STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) { |
|
|
|
// set TIM6 to trigger the DAC at the given frequency
|
|
|
|
TIM6_Config(mp_obj_get_int(freq)); |
|
|
|
|
|
|
|
if (self->state != 2) { |
|
|
|
if (self->state != DAC_STATE_BUILTIN_WAVEFORM) { |
|
|
|
// configure DAC to trigger via TIM6
|
|
|
|
DAC_ChannelConfTypeDef config; |
|
|
|
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; |
|
|
|
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; |
|
|
|
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); |
|
|
|
self->state = 2; |
|
|
|
self->state = DAC_STATE_BUILTIN_WAVEFORM; |
|
|
|
} |
|
|
|
|
|
|
|
// set noise wave generation
|
|
|
@ -209,13 +216,13 @@ STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) { |
|
|
|
// set TIM6 to trigger the DAC at the given frequency
|
|
|
|
TIM6_Config(mp_obj_get_int(freq)); |
|
|
|
|
|
|
|
if (self->state != 2) { |
|
|
|
if (self->state != DAC_STATE_BUILTIN_WAVEFORM) { |
|
|
|
// configure DAC to trigger via TIM6
|
|
|
|
DAC_ChannelConfTypeDef config; |
|
|
|
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; |
|
|
|
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; |
|
|
|
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); |
|
|
|
self->state = 2; |
|
|
|
self->state = DAC_STATE_BUILTIN_WAVEFORM; |
|
|
|
} |
|
|
|
|
|
|
|
// set triangle wave generation
|
|
|
@ -233,12 +240,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_triangle_obj, pyb_dac_triangle); |
|
|
|
STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) { |
|
|
|
pyb_dac_obj_t *self = self_in; |
|
|
|
|
|
|
|
if (self->state != 1) { |
|
|
|
if (self->state != DAC_STATE_WRITE_SINGLE) { |
|
|
|
DAC_ChannelConfTypeDef config; |
|
|
|
config.DAC_Trigger = DAC_TRIGGER_NONE; |
|
|
|
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; |
|
|
|
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); |
|
|
|
self->state = 1; |
|
|
|
self->state = DAC_STATE_WRITE_SINGLE; |
|
|
|
} |
|
|
|
|
|
|
|
HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_8B_R, mp_obj_get_int(val)); |
|
|
@ -258,26 +265,24 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write); |
|
|
|
/// TIM6 is used to control the frequency of the transfer.
|
|
|
|
// TODO add callback argument, to call when transfer is finished
|
|
|
|
// TODO add double buffer argument
|
|
|
|
STATIC const mp_arg_t pyb_dac_write_timed_args[] = { |
|
|
|
mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
|
|
|
static const mp_arg_t allowed_args[] = { |
|
|
|
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, |
|
|
|
{ MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, |
|
|
|
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DMA_NORMAL} }, |
|
|
|
}; |
|
|
|
#define PYB_DAC_WRITE_TIMED_NUM_ARGS MP_ARRAY_SIZE(pyb_dac_write_timed_args) |
|
|
|
|
|
|
|
mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { |
|
|
|
pyb_dac_obj_t *self = args[0]; |
|
|
|
|
|
|
|
// parse args
|
|
|
|
mp_arg_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_args, vals); |
|
|
|
pyb_dac_obj_t *self = pos_args[0]; |
|
|
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; |
|
|
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); |
|
|
|
|
|
|
|
// get the data to write
|
|
|
|
mp_buffer_info_t bufinfo; |
|
|
|
mp_get_buffer_raise(vals[0].u_obj, &bufinfo, MP_BUFFER_READ); |
|
|
|
mp_get_buffer_raise(args[0].u_obj, &bufinfo, MP_BUFFER_READ); |
|
|
|
|
|
|
|
// set TIM6 to trigger the DAC at the given frequency
|
|
|
|
TIM6_Config(vals[1].u_int); |
|
|
|
TIM6_Config(args[1].u_int); |
|
|
|
|
|
|
|
__DMA1_CLK_ENABLE(); |
|
|
|
|
|
|
@ -313,7 +318,7 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k |
|
|
|
DMA_Handle.Init.MemInc = DMA_MINC_ENABLE; |
|
|
|
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; |
|
|
|
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; |
|
|
|
DMA_Handle.Init.Mode = vals[2].u_int; |
|
|
|
DMA_Handle.Init.Mode = args[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; |
|
|
@ -331,12 +336,12 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k |
|
|
|
DAC_Handle.State = HAL_DAC_STATE_RESET; |
|
|
|
HAL_DAC_Init(&DAC_Handle); |
|
|
|
|
|
|
|
if (self->state != 3) { |
|
|
|
if (self->state != DAC_STATE_DMA_WAVEFORM) { |
|
|
|
DAC_ChannelConfTypeDef config; |
|
|
|
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; |
|
|
|
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; |
|
|
|
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); |
|
|
|
self->state = 3; |
|
|
|
self->state = DAC_STATE_DMA_WAVEFORM; |
|
|
|
} |
|
|
|
|
|
|
|
HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R); |
|
|
|