diff --git a/compiler/obc/c/async_avr.ml b/compiler/obc/c/async_avr.ml index 96b43fa..2566d4c 100644 --- a/compiler/obc/c/async_avr.ml +++ b/compiler/obc/c/async_avr.ml @@ -49,6 +49,8 @@ struct let fold_lcm l = List.fold_left lcm (List.hd l) (List.tl l) + let fold_gcd l = List.fold_left gcd (List.hd l) (List.tl l) + let ms_of_ack = function | Timer_ms ms -> ms @@ -58,34 +60,37 @@ struct let incr = Cbop ("+", Cvar name, one_const) in Caffect (CLvar name, Cbop ("%", incr, modulo_const)) - let call_step_async tick_var (od, ack) = + let call_step_async tick_var base (od, ack) = let step = (cname_of_qn od.o_class) ^ "_async_step" in let global = async_global_var_name od in let call = Csexpr (Cfun_call (step, [Caddrof (Cvar global)])) in let zero = Cconst (Ccint 0) in - let timer = Cconst (Ccint (ms_of_ack ack)) in + let timer = Cconst (Ccint (ms_of_ack ack / base)) in let cond = Cbop ("==", Cbop ("%", tick_var, timer), zero) in Cif (cond, [call], []) - let decls_and_defs objs = - let trans = List.map + let translate_objs objs = + List.map (fun od -> let ack = Option.get od.o_ack in (od, translate_ack ack)) objs - in + + let decls_and_defs objs = + let trans = translate_objs objs in let timers = List.map - (fun (_, ack) -> match ack with Timer_ms ms -> ms) + (fun (_, ack) -> ms_of_ack ack) trans in let body = match timers with | [] -> [] | _ -> + let gcd_timer = fold_gcd timers in let lcm_timer = fold_lcm timers in let steps = - List.map (call_step_async (Cvar "tick")) trans + List.map (call_step_async (Cvar "tick") gcd_timer) trans in - let incr = incr_mod "tick" lcm_timer in + let incr = incr_mod "tick" (lcm_timer / gcd_timer) in steps @ [incr] in (* run_timers is declared in avr.h (because of the ISR macro which @@ -105,6 +110,16 @@ struct ] in [], defs - let main_init = [Csexpr (Cfun_call ("init_timer1", []))] + let main_init objs = + let trans = translate_objs objs in + let timers = List.map + (fun (_, ack) -> ms_of_ack ack) + trans + in + match timers with + | [] -> [] + | _ -> + let value = fold_gcd timers in + [Csexpr (Cfun_call ("init_timer1", [Cconst (Ccint value)]))] end diff --git a/compiler/obc/c/async_backend.mli b/compiler/obc/c/async_backend.mli index ed322b7..6107b02 100644 --- a/compiler/obc/c/async_backend.mli +++ b/compiler/obc/c/async_backend.mli @@ -7,5 +7,5 @@ sig val gen_copy_func_out : class_def -> cdef val includes : string list val decls_and_defs : obj_dec list -> cdecl list * cdef list - val main_init : cstm list + val main_init : obj_dec list -> cstm list end diff --git a/compiler/obc/c/cmain.ml b/compiler/obc/c/cmain.ml index 7780abb..a01aeab 100644 --- a/compiler/obc/c/cmain.ml +++ b/compiler/obc/c/cmain.ml @@ -418,7 +418,10 @@ let mk_main name p = * could be triggered while the initial reset of the async nodes is * not yet terminated. *) - let res_l = res_l @ AvrBackend.main_init in + let async_objs = List.flatten + (List.map filter_async_objs classes) + in + let res_l = res_l @ AvrBackend.main_init async_objs in [("_main.c", Csource (defs @ [main_skel var_l res_l step_l])); ("_main.h", Cheader ([name], []))]; diff --git a/lib/c/avr.c b/lib/c/avr.c index 7085fd0..513a6a6 100644 --- a/lib/c/avr.c +++ b/lib/c/avr.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "avr.h" ISR(TIMER1_COMPA_vect) { @@ -42,9 +43,10 @@ static inline void set_ocr1a(uint16_t value) { } /* Source: https://adnbr.co.uk/articles/counting-milliseconds */ -void init_timer1() { +void init_timer1(unsigned int ms) { + assert(ms < 1000); TCCR1B |= _BV(WGM12) | _BV(CS11); - set_ocr1a((F_CPU / 1000) / 8); + set_ocr1a(((ms * F_CPU) / 1000) / 8); TIMSK1 |= _BV(OCIE1A); sei(); } diff --git a/lib/c/avr.h b/lib/c/avr.h index 573f4d0..5b3027d 100644 --- a/lib/c/avr.h +++ b/lib/c/avr.h @@ -39,7 +39,7 @@ void run_timers(); -void init_timer1(); +void init_timer1(unsigned int ms); void atomic_memcpy(void *dest, const void *src, size_t size);