stmhal: Add support for quadrature encoder mode to pyb.TimerChannel.

This commit is contained in:
Dave Hylands 2015-03-09 01:04:12 -07:00 committed by Damien George
parent b57b56f293
commit b4c9a25eab
3 changed files with 73 additions and 2 deletions

View File

@ -76,6 +76,9 @@ Methods
- ``Timer.OC_FORCED_ACTIVE`` --- the pin is forced active (compare match is ignored).
- ``Timer.OC_FORCED_INACTIVE`` --- the pin is forced inactive (compare match is ignored).
- ``Timer.IC`` --- configure the timer in Input Capture mode.
- ``Timer.ENC_A`` --- configure the timer in Encoder mode. The counter only changes when CH1 changes.
- ``Timer.ENC_B`` --- configure the timer in Encoder mode. The counter only changes when CH2 changes.
- ``Timer.ENC_AB`` --- configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes.
- ``callback`` - as per TimerChannel.callback()
@ -94,12 +97,14 @@ Methods
- ``compare`` - determines the initial value of the compare register.
- ``polarity`` can be one of:
- ``Timer.HIGH`` - output is active high
- ``Timer.LOW`` - output is acive low
Optional keyword arguments for Timer.IC modes:
- ``polarity`` can be one of:
- ``Timer.RISING`` - captures on rising edge.
- ``Timer.FALLING`` - captures on falling edge.
- ``Timer.BOTH`` - captures on both edges.
@ -107,6 +112,14 @@ Methods
Note that capture only works on the primary channel, and not on the
complimentary channels.
Notes for Timer.ENC modes:
- Requires 2 pins, so one or both pins will need to be configured to use
the appropriate timer AF using the Pin API.
- Read the encoder value using the timer.counter() method.
- Only works on CH1 and CH2 (and not on CH1N or CH2N)
- The channel number is ignored when setting the encoder mode.
PWM Example::
timer = pyb.Timer(2, freq=1000)

View File

@ -247,6 +247,9 @@ Q(OC_INACTIVE)
Q(OC_TOGGLE)
Q(OC_FORCED_ACTIVE)
Q(OC_FORCED_INACTIVE)
Q(ENC_A)
Q(ENC_B)
Q(ENC_AB)
Q(HIGH)
Q(LOW)
Q(RISING)

View File

@ -96,6 +96,9 @@ typedef enum {
CHANNEL_MODE_OC_FORCED_ACTIVE,
CHANNEL_MODE_OC_FORCED_INACTIVE,
CHANNEL_MODE_IC,
CHANNEL_MODE_ENC_A,
CHANNEL_MODE_ENC_B,
CHANNEL_MODE_ENC_AB,
} pyb_channel_mode;
STATIC const struct {
@ -111,6 +114,9 @@ STATIC const struct {
{ MP_QSTR_OC_FORCED_ACTIVE, TIM_OCMODE_FORCED_ACTIVE },
{ MP_QSTR_OC_FORCED_INACTIVE, TIM_OCMODE_FORCED_INACTIVE },
{ MP_QSTR_IC, 0 },
{ MP_QSTR_ENC_A, TIM_ENCODERMODE_TI1 },
{ MP_QSTR_ENC_B, TIM_ENCODERMODE_TI2 },
{ MP_QSTR_ENC_AB, TIM_ENCODERMODE_TI12 },
};
typedef struct _pyb_timer_channel_obj_t {
@ -719,6 +725,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
/// - `Timer.OC_FORCED_ACTIVE` - the pin is forced active (compare match is ignored).
/// - `Timer.OC_FORCED_INACTIVE` - the pin is forced inactive (compare match is ignored).
/// - `Timer.IC` - configure the timer in Input Capture mode.
/// - `Timer.ENC_A` --- configure the timer in Encoder mode. The counter only changes when CH1 changes.
/// - `Timer.ENC_B` --- configure the timer in Encoder mode. The counter only changes when CH2 changes.
/// - `Timer.ENC_AB` --- configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes.
///
/// - `callback` - as per TimerChannel.callback()
///
@ -750,6 +759,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
/// Note that capture only works on the primary channel, and not on the
/// complimentary channels.
///
/// Notes for Timer.ENC modes:
///
/// - Requires 2 pins, so one or both pins will need to be configured to use
/// the appropriate timer AF using the Pin API.
/// - Read the encoder value using the timer.counter() method.
/// - Only works on CH1 and CH2 (and not on CH1N or CH2N)
/// - The channel number is ignored when setting the encoder mode.
///
/// PWM Example:
///
/// timer = pyb.Timer(2, freq=1000)
@ -941,6 +958,41 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
break;
}
case CHANNEL_MODE_ENC_A:
case CHANNEL_MODE_ENC_B:
case CHANNEL_MODE_ENC_AB: {
TIM_Encoder_InitTypeDef enc_config;
enc_config.EncoderMode = channel_mode_info[chan->mode].oc_mode;
enc_config.IC1Polarity = args[6].u_int;
if (enc_config.IC1Polarity == 0xffffffff) {
enc_config.IC1Polarity = TIM_ICPOLARITY_RISING;
}
enc_config.IC2Polarity = enc_config.IC1Polarity;
enc_config.IC1Selection = TIM_ICSELECTION_DIRECTTI;
enc_config.IC2Selection = TIM_ICSELECTION_DIRECTTI;
enc_config.IC1Prescaler = TIM_ICPSC_DIV1;
enc_config.IC2Prescaler = TIM_ICPSC_DIV1;
enc_config.IC1Filter = 0;
enc_config.IC2Filter = 0;
if (!IS_TIM_IC_POLARITY(enc_config.IC1Polarity)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", enc_config.IC1Polarity));
}
// Only Timers 1, 2, 3, 4, 5, and 8 support encoder mode
if (self->tim.Instance != TIM1
&& self->tim.Instance != TIM2
&& self->tim.Instance != TIM3
&& self->tim.Instance != TIM4
&& self->tim.Instance != TIM5
&& self->tim.Instance != TIM8 ) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "encoder not supported on timer %d", self->tim_id));
}
HAL_TIM_Encoder_Init(&self->tim, &enc_config);
__HAL_TIM_SetCounter(&self->tim, 0);
break;
}
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid mode (%d)", chan->mode));
}
@ -1077,6 +1129,9 @@ STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_OC_FORCED_ACTIVE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_FORCED_ACTIVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OC_FORCED_INACTIVE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_FORCED_INACTIVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IC), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_IC) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ENC_A), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_ENC_A) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ENC_B), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_ENC_B) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ENC_AB), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_ENC_AB) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HIGH), MP_OBJ_NEW_SMALL_INT(TIM_OCPOLARITY_HIGH) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOW), MP_OBJ_NEW_SMALL_INT(TIM_OCPOLARITY_LOW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RISING), MP_OBJ_NEW_SMALL_INT(TIM_ICPOLARITY_RISING) },