summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2015-07-21 23:37:45 +0100
committerDamien George <damien.p.george@gmail.com>2015-07-21 23:39:49 +0100
commitabc24c187614e358faa10ed6a3e239151f70b9f8 (patch)
treeed64fc0a71077f8d6de04c4eee4544aaa57c1699 /stmhal
parent6f5e0fe9555c935fa0bca81f56d0bfa2993636a2 (diff)
downloadmicropython-abc24c187614e358faa10ed6a3e239151f70b9f8.tar.gz
micropython-abc24c187614e358faa10ed6a3e239151f70b9f8.zip
stmhal: Allow DAC.write_timed to take Timer object in place of freq.
This allows the DAC to use a user-specified Timer for the triggering (instead of the default Timer(6)), while still supporting original behaviour. Addresses issues #1129 and #1388.
Diffstat (limited to 'stmhal')
-rw-r--r--stmhal/dac.c70
-rw-r--r--stmhal/timer.c5
-rw-r--r--stmhal/timer.h2
3 files changed, 69 insertions, 8 deletions
diff --git a/stmhal/dac.c b/stmhal/dac.c
index e59f1b8d40..d71543ff2e 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -93,6 +93,43 @@ STATIC void TIM6_Config(uint freq) {
}
#endif
+STATIC uint32_t TIMx_Config(mp_obj_t timer) {
+ // make sure the given object is a timer
+ if (mp_obj_get_type(timer) != &pyb_timer_type) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "need a Timer object"));
+ }
+
+ // TRGO selection to trigger DAC
+ TIM_HandleTypeDef *tim = pyb_timer_get_handle(timer);
+ TIM_MasterConfigTypeDef config;
+ config.MasterOutputTrigger = TIM_TRGO_UPDATE;
+ config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+ HAL_TIMEx_MasterConfigSynchronization(tim, &config);
+
+ // work out the trigger channel (only certain ones are supported)
+ if (tim->Instance == TIM2) {
+ return DAC_TRIGGER_T2_TRGO;
+ } else if (tim->Instance == TIM4) {
+ return DAC_TRIGGER_T4_TRGO;
+ } else if (tim->Instance == TIM5) {
+ return DAC_TRIGGER_T5_TRGO;
+ #if defined(TIM6)
+ } else if (tim->Instance == TIM6) {
+ return DAC_TRIGGER_T6_TRGO;
+ #endif
+ #if defined(TIM7)
+ } else if (tim->Instance == TIM7) {
+ return DAC_TRIGGER_T7_TRGO;
+ #endif
+ #if defined(TIM8)
+ } else if (tim->Instance == TIM8) {
+ return DAC_TRIGGER_T8_TRGO;
+ #endif
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Timer does not support DAC triggering"));
+ }
+}
+
/******************************************************************************/
// Micro Python bindings
@@ -100,7 +137,7 @@ typedef enum {
DAC_STATE_RESET,
DAC_STATE_WRITE_SINGLE,
DAC_STATE_BUILTIN_WAVEFORM,
- DAC_STATE_DMA_WAVEFORM,
+ DAC_STATE_DMA_WAVEFORM, // should be last enum since we use space beyond it
} pyb_dac_state_t;
typedef struct _pyb_dac_obj_t {
@@ -260,15 +297,25 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write);
/// Initiates a burst of RAM to DAC using a DMA transfer.
/// The input data is treated as an array of bytes (8 bit data).
///
+/// `freq` can be an integer specifying the frequency to write the DAC
+/// samples at, using Timer(6). Or it can be an already-initialised
+/// Timer object which is used to trigger the DAC sample. Valid timers
+/// are 2, 4, 5, 6, 7 and 8.
+///
/// `mode` can be `DAC.NORMAL` or `DAC.CIRCULAR`.
///
-/// 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
+//
+// TODO reconsider API, eg: write_trig(data, *, trig=None, loop=False)
+// Then trigger can be timer (preinitialised with desired freq) or pin (extint9),
+// and we can reuse the same timer for both DACs (and maybe also ADC) without
+// setting the freq twice.
+// Can still do 1-liner: dac.write_trig(buf, trig=Timer(6, freq=100), loop=True)
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_freq, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DMA_NORMAL} },
};
@@ -281,8 +328,15 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0].u_obj, &bufinfo, MP_BUFFER_READ);
- // set TIM6 to trigger the DAC at the given frequency
- TIM6_Config(args[1].u_int);
+ uint32_t dac_trigger;
+ if (mp_obj_is_integer(args[1].u_obj)) {
+ // set TIM6 to trigger the DAC at the given frequency
+ TIM6_Config(mp_obj_get_int(args[1].u_obj));
+ dac_trigger = DAC_TRIGGER_T6_TRGO;
+ } else {
+ // set the supplied timer to trigger the DAC (timer should be initialised)
+ dac_trigger = TIMx_Config(args[1].u_obj);
+ }
__DMA1_CLK_ENABLE();
@@ -336,12 +390,12 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
DAC_Handle.State = HAL_DAC_STATE_RESET;
HAL_DAC_Init(&DAC_Handle);
- if (self->state != DAC_STATE_DMA_WAVEFORM) {
+ if (self->state != DAC_STATE_DMA_WAVEFORM + dac_trigger) {
DAC_ChannelConfTypeDef config;
- config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
+ config.DAC_Trigger = dac_trigger;
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
- self->state = DAC_STATE_DMA_WAVEFORM;
+ self->state = DAC_STATE_DMA_WAVEFORM + dac_trigger;
}
HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R);
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 68f295b748..3519c3c150 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -470,6 +470,11 @@ STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks) {
HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig);
}
+TIM_HandleTypeDef *pyb_timer_get_handle(mp_obj_t timer) {
+ pyb_timer_obj_t *self = timer;
+ return &self->tim;
+}
+
STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_obj_t *self = self_in;
diff --git a/stmhal/timer.h b/stmhal/timer.h
index 2a892db285..879d7ae5d7 100644
--- a/stmhal/timer.h
+++ b/stmhal/timer.h
@@ -43,3 +43,5 @@ void timer_tim6_init(uint freq);
void timer_deinit(void);
void timer_irq_handler(uint tim_id);
+
+TIM_HandleTypeDef *pyb_timer_get_handle(mp_obj_t timer);