6060///
6161/// Example usage to toggle an LED at a fixed frequency:
6262///
63- /// tim = pyb.Timer(4 ) # create a timer object using timer 4
63+ /// tim = pyb.Timer(3 ) # create a timer object using timer 3
6464/// tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
6565/// tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
6666/// tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
8787#define PYBTIMER_POLARITY_POS (0x01)
8888#define PYBTIMER_POLARITY_NEG (0x02)
8989
90+ #define PYBTIMER_TIMEOUT_TRIGGER (0x01)
91+ #define PYBTIMER_MATCH_TRIGGER (0x02)
92+ #define PYBTIMER_EVENT_TRIGGER (0x04)
93+
9094#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
9195
9296/******************************************************************************
@@ -127,6 +131,7 @@ STATIC const mp_obj_type_t pyb_timer_channel_type;
127131 ******************************************************************************/
128132STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args );
129133STATIC void timer_disable (pyb_timer_obj_t * tim );
134+ STATIC void timer_channel_init (pyb_timer_channel_obj_t * ch );
130135STATIC void TIMER0AIntHandler (void );
131136STATIC void TIMER0BIntHandler (void );
132137STATIC void TIMER1AIntHandler (void );
@@ -177,22 +182,33 @@ STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
177182 pyb_timer_channel_obj_t * channel ;
178183 if ((channel = pyb_timer_channel_find (ch -> timer -> timer , ch -> channel ))) {
179184 mp_obj_list_remove (& MP_STATE_PORT (pyb_timer_channel_obj_list ), channel );
185+ // unregister it with the sleep module
186+ pyb_sleep_remove ((const mp_obj_t )channel );
180187 }
181188}
182189
183190STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t * ch ) {
184191 // remove it in case it already exists
185192 pyb_timer_channel_remove (ch );
186193 mp_obj_list_append (& MP_STATE_PORT (pyb_timer_channel_obj_list ), ch );
194+ // register it with the sleep module
195+ pyb_sleep_add ((const mp_obj_t )ch , (WakeUpCB_t )timer_channel_init );
187196}
188197
189198STATIC void timer_disable (pyb_timer_obj_t * tim ) {
190199 // disable all timers and it's interrupts
191200 MAP_TimerDisable (tim -> timer , TIMER_A | TIMER_B );
192201 MAP_TimerIntDisable (tim -> timer , tim -> irq_trigger );
193202 MAP_TimerIntClear (tim -> timer , tim -> irq_trigger );
203+ pyb_timer_channel_obj_t * ch ;
204+ // disable its channels
205+ if ((ch = pyb_timer_channel_find (tim -> timer , TIMER_A ))) {
206+ pyb_sleep_remove (ch );
207+ }
208+ if ((ch = pyb_timer_channel_find (tim -> timer , TIMER_B ))) {
209+ pyb_sleep_remove (ch );
210+ }
194211 MAP_PRCMPeripheralClkDisable (tim -> peripheral , PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK );
195- memset (& pyb_timer_obj [tim -> id ], 0 , sizeof (pyb_timer_obj_t ));
196212}
197213
198214// computes prescaler period and match value so timer triggers at freq-Hz
@@ -205,8 +221,10 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t
205221 if (period_c == 0 ) {
206222 goto error ;
207223 }
208- prescaler = period_c >> 16 ;
224+
225+ prescaler = period_c >> 16 ; // The prescaler is an extension of the timer counter
209226 * period_out = period_c ;
227+
210228 if (prescaler > 0xFF && maxcount == 0xFFFF ) {
211229 goto error ;
212230 }
@@ -217,9 +235,6 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t
217235 else {
218236 * match_out = period_c - ((period_c * ch -> duty_cycle ) / 100 );
219237 }
220- if ((ch -> timer -> config & 0x0F ) == TIMER_CFG_A_PWM && (* match_out > 0xFFFF )) {
221- goto error ;
222- }
223238 return prescaler ;
224239
225240error :
@@ -250,6 +265,7 @@ STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) {
250265 MAP_TimerControlLevel (ch -> timer -> timer , ch -> channel , (ch -> polarity == PYBTIMER_POLARITY_NEG ) ? true : false);
251266 // set the match value (which is simply the duty cycle translated to ticks)
252267 MAP_TimerMatchSet (ch -> timer -> timer , ch -> channel , match );
268+ MAP_TimerPrescaleMatchSet (ch -> timer -> timer , ch -> channel , match >> 16 );
253269 }
254270 // configure the event edge type if we are in such mode
255271 else if ((ch -> timer -> config & 0x0F ) == TIMER_CFG_A_CAP_COUNT || (ch -> timer -> config & 0x0F ) == TIMER_CFG_A_CAP_TIME ) {
@@ -282,10 +298,10 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
282298 // timer mode
283299 qstr mode_qst = MP_QSTR_PWM ;
284300 switch (mode ) {
285- case TIMER_CFG_A_ONE_SHOT :
301+ case TIMER_CFG_A_ONE_SHOT_UP :
286302 mode_qst = MP_QSTR_ONE_SHOT ;
287303 break ;
288- case TIMER_CFG_A_PERIODIC :
304+ case TIMER_CFG_A_PERIODIC_UP :
289305 mode_qst = MP_QSTR_PERIODIC ;
290306 break ;
291307 case TIMER_CFG_A_CAP_COUNT :
@@ -297,7 +313,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
297313 default :
298314 break ;
299315 }
300- mp_printf (print , "< Timer%u, mode=Timer.%q> " , (tim -> id + 1 ), mode_qst );
316+ mp_printf (print , "Timer( %u, mode=Timer.%q) " , (tim -> id + 1 ), mode_qst );
301317}
302318
303319/// \method init(mode, *, width)
@@ -325,7 +341,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
325341
326342 // check the mode
327343 uint32_t _mode = args [0 ].u_int ;
328- if (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC && _mode != TIMER_CFG_A_CAP_COUNT &&
344+ if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_CAP_COUNT &&
329345 _mode != TIMER_CFG_A_CAP_TIME && _mode != TIMER_CFG_A_PWM ) {
330346 goto error ;
331347 }
@@ -336,7 +352,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
336352 }
337353 bool is16bit = (args [1 ].u_int == 16 );
338354
339- if (!is16bit && (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC )) {
355+ if (!is16bit && (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP )) {
340356 // 32-bit mode is only available when in free running modes
341357 goto error ;
342358 }
@@ -361,7 +377,7 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args,
361377 mp_arg_check_num (n_args , n_kw , 1 , MP_OBJ_FUN_ARGS_MAX , true);
362378
363379 // create a new Timer object
364- int32_t timer_idx = mp_obj_get_int (args [0 ]) - 1 ;
380+ int32_t timer_idx = mp_obj_get_int (args [0 ]);
365381 if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1 )) {
366382 nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , mpexception_os_resource_not_avaliable ));
367383 }
@@ -478,9 +494,6 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
478494
479495 timer_channel_init (ch );
480496
481- // register it with the sleep module
482- pyb_sleep_add ((const mp_obj_t )ch , (WakeUpCB_t )timer_channel_init );
483-
484497 // add the timer to the list
485498 pyb_timer_channel_add (ch );
486499
@@ -500,13 +513,16 @@ STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
500513 // class constants
501514 { MP_OBJ_NEW_QSTR (MP_QSTR_A ), MP_OBJ_NEW_SMALL_INT (TIMER_A ) },
502515 { MP_OBJ_NEW_QSTR (MP_QSTR_B ), MP_OBJ_NEW_SMALL_INT (TIMER_B ) },
503- { MP_OBJ_NEW_QSTR (MP_QSTR_ONE_SHOT ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_ONE_SHOT ) },
504- { MP_OBJ_NEW_QSTR (MP_QSTR_PERIODIC ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_PERIODIC ) },
516+ { MP_OBJ_NEW_QSTR (MP_QSTR_ONE_SHOT ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_ONE_SHOT_UP ) },
517+ { MP_OBJ_NEW_QSTR (MP_QSTR_PERIODIC ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_PERIODIC_UP ) },
505518 { MP_OBJ_NEW_QSTR (MP_QSTR_EDGE_COUNT ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_CAP_COUNT ) },
506519 { MP_OBJ_NEW_QSTR (MP_QSTR_EDGE_TIME ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_CAP_TIME ) },
507520 { MP_OBJ_NEW_QSTR (MP_QSTR_PWM ), MP_OBJ_NEW_SMALL_INT (TIMER_CFG_A_PWM ) },
508521 { MP_OBJ_NEW_QSTR (MP_QSTR_POSITIVE ), MP_OBJ_NEW_SMALL_INT (PYBTIMER_POLARITY_POS ) },
509522 { MP_OBJ_NEW_QSTR (MP_QSTR_NEGATIVE ), MP_OBJ_NEW_SMALL_INT (PYBTIMER_POLARITY_NEG ) },
523+ { MP_OBJ_NEW_QSTR (MP_QSTR_TIMEOUT ), MP_OBJ_NEW_SMALL_INT (PYBTIMER_TIMEOUT_TRIGGER ) },
524+ { MP_OBJ_NEW_QSTR (MP_QSTR_MATCH ), MP_OBJ_NEW_SMALL_INT (PYBTIMER_MATCH_TRIGGER ) },
525+ { MP_OBJ_NEW_QSTR (MP_QSTR_EVENT ), MP_OBJ_NEW_SMALL_INT (PYBTIMER_EVENT_TRIGGER ) },
510526};
511527STATIC MP_DEFINE_CONST_DICT (pyb_timer_locals_dict , pyb_timer_locals_dict_table );
512528
@@ -528,7 +544,6 @@ STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
528544STATIC void TIMERGenericIntHandler (uint32_t timer , uint16_t channel ) {
529545 pyb_timer_channel_obj_t * self ;
530546 uint32_t status ;
531-
532547 if ((self = pyb_timer_channel_find (timer , channel ))) {
533548 status = MAP_TimerIntStatus (self -> timer -> timer , true) & self -> channel ;
534549 MAP_TimerIntClear (self -> timer -> timer , status );
@@ -574,13 +589,11 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
574589 // timer channel
575590 if (ch -> channel == TIMER_A ) {
576591 ch_id = "A" ;
577- }
578- else if (ch -> channel == TIMER_B ) {
592+ } else if (ch -> channel == TIMER_B ) {
579593 ch_id = "B" ;
580594 }
581595
582- mp_printf (print , "<%q %s, timer=%u, %q=%u" , MP_QSTR_TimerChannel ,
583- ch_id , (ch -> timer -> id + 1 ), MP_QSTR_freq , ch -> frequency );
596+ mp_printf (print , "timer.channel(Timer.%s, %q=%u" , ch_id , MP_QSTR_freq , ch -> frequency );
584597
585598 uint32_t mode = ch -> timer -> config & 0xFF ;
586599 if (mode == TIMER_CFG_A_CAP_COUNT || mode == TIMER_CFG_A_CAP_TIME || mode == TIMER_CFG_A_PWM ) {
@@ -600,7 +613,7 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
600613 mp_printf (print , ", %q=%u" , MP_QSTR_duty_cycle , ch -> duty_cycle );
601614 }
602615 }
603- mp_printf (print , "> " );
616+ mp_printf (print , ") " );
604617}
605618
606619/// \method freq([value])
@@ -658,11 +671,9 @@ STATIC mp_obj_t pyb_timer_channel_time(mp_uint_t n_args, const mp_obj_t *args) {
658671 // get
659672 value = (ch -> channel == TIMER_B ) ? HWREG (ch -> timer -> timer + TIMER_O_TBV ) : HWREG (ch -> timer -> timer + TIMER_O_TAV );
660673 // return the current timer value in microseconds
661- // substract value to period since we are always operating in count-down mode
662- uint32_t time_t = (1000 * (period_c - value )) / period_c ;
674+ uint32_t time_t = (1000 * value ) / period_c ;
663675 return mp_obj_new_int ((time_t * 1000 ) / ch -> frequency );
664- }
665- else {
676+ } else {
666677 // set
667678 value = (mp_obj_get_int (args [1 ]) * ((ch -> frequency * period_c ) / 1000 )) / 1000 ;
668679 if ((value > 0xFFFF ) && (ch -> timer -> config & TIMER_CFG_SPLIT_PAIR )) {
@@ -693,8 +704,7 @@ STATIC mp_obj_t pyb_timer_channel_event_time(mp_obj_t self_in) {
693704 uint32_t match ;
694705 (void )compute_prescaler_period_and_match_value (ch , & period_c , & match );
695706 uint32_t value = MAP_TimerValueGet (ch -> timer -> timer , ch -> channel == (TIMER_A | TIMER_B ) ? TIMER_A : ch -> channel );
696- // substract value to period since we are always operating in count-down mode
697- uint32_t time_t = (1000 * (period_c - value )) / period_c ;
707+ uint32_t time_t = (1000 * value ) / period_c ;
698708 return mp_obj_new_int ((time_t * 1000 ) / ch -> frequency );
699709}
700710STATIC MP_DEFINE_CONST_FUN_OBJ_1 (pyb_timer_channel_event_time_obj , pyb_timer_channel_event_time );
@@ -706,8 +716,7 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a
706716 if (n_args == 1 ) {
707717 // get
708718 return mp_obj_new_int (ch -> duty_cycle );
709- }
710- else {
719+ } else {
711720 // duty cycle must be converted from percentage to ticks
712721 // calculate the period, the prescaler and the match value
713722 uint32_t period_c ;
@@ -720,13 +729,13 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a
720729 MAP_TimerControlLevel (ch -> timer -> timer , ch -> channel , (ch -> polarity == PYBTIMER_POLARITY_NEG ) ? true : false);
721730 }
722731 MAP_TimerMatchSet (ch -> timer -> timer , ch -> channel , match );
732+ MAP_TimerPrescaleMatchSet (ch -> timer -> timer , ch -> channel , match >> 16 );
723733 return mp_const_none ;
724734 }
725735}
726736STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (pyb_timer_channel_duty_cycle_obj , 1 , 3 , pyb_timer_channel_duty_cycle );
727737
728738/// \method irq(trigger, priority, handler, wake)
729- /// FIXME triggers!!
730739STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
731740 mp_arg_val_t args [mp_irq_INIT_NUM_ARGS ];
732741 mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , mp_irq_INIT_NUM_ARGS , mp_irq_init_args , args );
@@ -741,25 +750,40 @@ STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_arg
741750 goto invalid_args ;
742751 }
743752
753+ // get the trigger
754+ uint trigger = mp_obj_get_int (args [0 ].u_obj );
755+
744756 // disable the callback first
745757 pyb_timer_channel_irq_disable (ch );
746758
747759 uint8_t shift = (ch -> channel == TIMER_B ) ? 8 : 0 ;
748760 uint32_t _config = (ch -> channel == TIMER_B ) ? ((ch -> timer -> config & TIMER_B ) >> 8 ) : (ch -> timer -> config & TIMER_A );
749761 switch (_config ) {
750- case TIMER_CFG_A_ONE_SHOT :
751- case TIMER_CFG_A_PERIODIC :
762+ case TIMER_CFG_A_ONE_SHOT_UP :
763+ case TIMER_CFG_A_PERIODIC_UP :
752764 ch -> timer -> irq_trigger |= TIMER_TIMA_TIMEOUT << shift ;
765+ if (trigger != PYBTIMER_TIMEOUT_TRIGGER ) {
766+ goto invalid_args ;
767+ }
753768 break ;
754769 case TIMER_CFG_A_CAP_COUNT :
755770 ch -> timer -> irq_trigger |= TIMER_CAPA_MATCH << shift ;
771+ if (trigger != PYBTIMER_MATCH_TRIGGER ) {
772+ goto invalid_args ;
773+ }
756774 break ;
757775 case TIMER_CFG_A_CAP_TIME :
758776 ch -> timer -> irq_trigger |= TIMER_CAPA_EVENT << shift ;
777+ if (trigger != PYBTIMER_EVENT_TRIGGER ) {
778+ goto invalid_args ;
779+ }
759780 break ;
760781 case TIMER_CFG_A_PWM :
761782 // special case for the PWM match interrupt
762783 ch -> timer -> irq_trigger |= ((ch -> channel & TIMER_A ) == TIMER_A ) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH ;
784+ if (trigger != PYBTIMER_MATCH_TRIGGER ) {
785+ goto invalid_args ;
786+ }
763787 break ;
764788 default :
765789 break ;
0 commit comments