//-------------------------------------------------------------------------------------------------- static inline void lwb_estimate_skew() { uint16_t t_diff = CURRENT_SCHEDULE_INFO().time - OLD_SCHEDULE_INFO().time; // The maximum time that can be measured with rtimer (32 kHz) is 2.048 seconds before integer wrap-round. // This is due to 16-bit counters are used in Glossy. // Therefore, if t_diff is a multiple of 2, then we do not need to use it for skew calculation. int16_t skew_tmp = lwb_context.t_sync_ref - (lwb_context.t_last_sync_ref + (uint16_t)RTIMER_SECOND * (t_diff % 2)); if (skew_tmp < 500 && t_diff != 0) { /// @todo Why 64 is used in here. /// I think 64 is used to make skew_tmp large. The skew_tmp is calculated in rtimer /// clock ticks. If it is smaller than t_diff, clock skew per unit time becomes zero. /// Therefore, skew_tmp is multiplied by 64 to make it larger. lwb_context.skew = (int32_t)(64 * (int32_t)skew_tmp) / (int32_t)t_diff; /// @todo "dirty hack" to temporary fix a Glossy bug that rarely occurs in disconnected networks OLD_SCHEDULE_INFO().time = CURRENT_SCHEDULE_INFO().time; lwb_context.t_last_sync_ref = GLOSSY_T_REF; } else { lwb_context.sync_state = LWB_SYNC_STATE_BOOTSTRAP; set_t_ref_l_updated(0); } }
char glossy_scheduler(struct rtimer *t, void *ptr) { PT_BEGIN(&pt); if (IS_INITIATOR()) { // Glossy initiator. while (1) { printf("[SCHEDULER]: Get Data from queue\n"); // Increment sequence number. glossy_data.seq_no++; // Glossy phase. leds_on(LEDS_GREEN); rtimer_clock_t t_stop = RTIMER_TIME(t) + GLOSSY_DURATION; // Start Glossy. glossy_start((uint8_t *)&glossy_data, DATA_LEN, GLOSSY_INITIATOR, GLOSSY_SYNC, N_TX, APPLICATION_HEADER, t_stop, (rtimer_callback_t)glossy_scheduler, t, ptr); // Store time at which Glossy has started. t_start = RTIMER_TIME(t); // Yield the protothread. It will be resumed when Glossy terminates. PT_YIELD(&pt); // Off phase. leds_off(LEDS_GREEN); // Stop Glossy. glossy_stop(); if (!GLOSSY_IS_BOOTSTRAPPING()) { // Glossy has already successfully bootstrapped. if (!GLOSSY_IS_SYNCED()) { // The reference time was not updated: increment reference time by GLOSSY_PERIOD. set_t_ref_l(GLOSSY_REFERENCE_TIME + GLOSSY_PERIOD); set_t_ref_l_updated(1); } } // Schedule begin of next Glossy phase based on GLOSSY_PERIOD. rtimer_set(t, t_start + GLOSSY_PERIOD, 1, (rtimer_callback_t)glossy_scheduler, ptr); // Estimate the clock skew over the last period. estimate_period_skew(); // Poll the process that prints statistics (will be activated later by Contiki). process_poll(&glossy_print_stats_process); // Yield the protothread. PT_YIELD(&pt); } } else { // Glossy receiver. while (1) { // Glossy phase. leds_on(LEDS_GREEN); rtimer_clock_t t_stop; if (GLOSSY_IS_BOOTSTRAPPING()) { // Glossy is still bootstrapping: // Schedule end of Glossy phase based on GLOSSY_INIT_DURATION. t_stop = RTIMER_TIME(t) + GLOSSY_INIT_DURATION; } else { // Glossy has already successfully bootstrapped: // Schedule end of Glossy phase based on GLOSSY_DURATION. t_stop = RTIMER_TIME(t) + GLOSSY_DURATION; } // Start Glossy. glossy_start((uint8_t *)&glossy_data, DATA_LEN, GLOSSY_RECEIVER, GLOSSY_SYNC, N_TX, APPLICATION_HEADER, t_stop, (rtimer_callback_t)glossy_scheduler, t, ptr); // Yield the protothread. It will be resumed when Glossy terminates. PT_YIELD(&pt); // Off phase. leds_off(LEDS_GREEN); // Stop Glossy. glossy_stop(); if (GLOSSY_IS_BOOTSTRAPPING()) { // Glossy is still bootstrapping. if (!GLOSSY_IS_SYNCED()) { // The reference time was not updated: reset skew_estimated to zero. skew_estimated = 0; } } else { // Glossy has already successfully bootstrapped. if (!GLOSSY_IS_SYNCED()) { // The reference time was not updated: // increment reference time by GLOSSY_PERIOD + period_skew. set_t_ref_l(GLOSSY_REFERENCE_TIME + GLOSSY_PERIOD + period_skew); set_t_ref_l_updated(1); // Increment sync_missed. sync_missed++; } else { // The reference time was not updated: reset sync_missed to zero. sync_missed = 0; } } // Estimate the clock skew over the last period. estimate_period_skew(); if (GLOSSY_IS_BOOTSTRAPPING()) { // Glossy is still bootstrapping. if (skew_estimated == 0) { // The reference time was not updated: // Schedule begin of next Glossy phase based on last begin and GLOSSY_INIT_PERIOD. rtimer_set(t, RTIMER_TIME(t) + GLOSSY_INIT_PERIOD, 1, (rtimer_callback_t)glossy_scheduler, ptr); } else { // The reference time was updated: // Schedule begin of next Glossy phase based on reference time and GLOSSY_INIT_PERIOD. rtimer_set(t, GLOSSY_REFERENCE_TIME + GLOSSY_PERIOD - GLOSSY_INIT_GUARD_TIME, 1, (rtimer_callback_t)glossy_scheduler, ptr); } } else { // Glossy has already successfully bootstrapped: // Schedule begin of next Glossy phase based on reference time and GLOSSY_PERIOD. rtimer_set(t, GLOSSY_REFERENCE_TIME + GLOSSY_PERIOD + period_skew - GLOSSY_GUARD_TIME * (1 + sync_missed), 1, (rtimer_callback_t)glossy_scheduler, ptr); } // Poll the process that prints statistics (will be activated later by Contiki). process_poll(&glossy_print_stats_process); // Yield the protothread. PT_YIELD(&pt); } } PT_END(&pt); }