Beispiel #1
0
static inline void estimate_period_skew(void) {
	// Estimate clock skew over a period only if the reference time has been updated.
	if (GLOSSY_IS_SYNCED()) {
		// Estimate clock skew based on previous reference time and the Glossy period.
		period_skew = get_t_ref_l() - (t_ref_l_old + (rtimer_clock_t)GLOSSY_PERIOD);
		// Update old reference time with the newer one.
		t_ref_l_old = get_t_ref_l();
		// If Glossy is still bootstrapping, count the number of consecutive updates of the reference time.
		if (GLOSSY_IS_BOOTSTRAPPING()) {
			// Increment number of consecutive updates of the reference time.
			skew_estimated++;
			// Check if Glossy has exited from bootstrapping.
			if (!GLOSSY_IS_BOOTSTRAPPING()) {
				// Glossy has exited from bootstrapping.
				leds_off(LEDS_RED);
				// Initialize Energest values.
				energest_init();
#if GLOSSY_DEBUG
				high_T_irq = 0;
				bad_crc = 0;
				bad_length = 0;
				bad_header = 0;
#endif /* GLOSSY_DEBUG */

			}
		}
	}
}
Beispiel #2
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);
}
Beispiel #3
0
//--------------------------------------------------------------------------------------------------
static inline void compute_new_sync_state() {

    if (GLOSSY_IS_SYNCED()) {
        // Reference time of Glossy is updated.
        LWB_STATS_SYNC(n_synced)++;

        if ((lwb_context.sync_state == LWB_SYNC_STATE_QUASI_SYNCED ||
             lwb_context.sync_state == LWB_SYNC_STATE_SYNCED) &&
                        (CURRENT_SCHEDULE_INFO().time < OLD_SCHEDULE_INFO().time)) {
            // 16-bit overflow
            UI32_SET_HIGH(lwb_context.time, UI32_GET_HIGH(lwb_context.time) + 1);
        }

        UI32_SET_LOW(lwb_context.time, CURRENT_SCHEDULE_INFO().time);

        switch (lwb_context.sync_state) {
            case LWB_SYNC_STATE_BOOTSTRAP:
            {
                lwb_context.sync_state = LWB_SYNC_STATE_QUASI_SYNCED;

                lwb_context.t_sync_guard = T_GUARD_3;
                lwb_context.t_last_sync_ref = GLOSSY_T_REF;
                lwb_context.t_sync_ref = GLOSSY_T_REF;
            }
            break;
            default:
            {
                // If Glossy's reference time is updated while in any other states,
                // we consider LWB is synchronized.
                lwb_context.sync_state = LWB_SYNC_STATE_SYNCED;

                lwb_context.t_sync_guard = T_GUARD;
                lwb_context.t_sync_ref = GLOSSY_T_REF;
                lwb_estimate_skew();
            }
            break;
        }

    } else {
        // Reference time of Glossy is not updated.

        LWB_STATS_SYNC(n_sync_missed)++;

        switch (lwb_context.sync_state) {
            case LWB_SYNC_STATE_SYNCED:
            {
                lwb_context.sync_state = LWB_SYNC_STATE_UNSYNCED_1;
                lwb_context.t_sync_guard = T_GUARD_1;
            }
            break;
            case LWB_SYNC_STATE_UNSYNCED_1:
            {
                lwb_context.sync_state = LWB_SYNC_STATE_UNSYNCED_2;
                lwb_context.t_sync_guard = T_GUARD_2;
            }
            break;
            case LWB_SYNC_STATE_UNSYNCED_2:
            {
                lwb_context.sync_state = LWB_SYNC_STATE_UNSYNCED_3;
                lwb_context.t_sync_guard = T_GUARD_3;
            }
            break;
            case LWB_SYNC_STATE_UNSYNCED_3:
            case LWB_SYNC_STATE_QUASI_SYNCED:
            {
                // go back to bootstrap
                lwb_context.sync_state = LWB_SYNC_STATE_BOOTSTRAP;
                lwb_context.t_sync_guard = T_GUARD_3;
                lwb_context.skew = 0;
            }
            break;
            default:
                break;
        }

        if (lwb_context.sync_state != LWB_SYNC_STATE_BOOTSTRAP) {
            // We are not bootstrapping. So, we calculate the new schedule information based on the old one.

            // set new time based on old time
            if (OLD_SCHEDULE_INFO().round_period == 1) {
                CURRENT_SCHEDULE_INFO().time = OLD_SCHEDULE_INFO().time + 1;
            } else {
                /// @todo Find why sched_info.round_period - 1 is used
                CURRENT_SCHEDULE_INFO().time = OLD_SCHEDULE_INFO().time + OLD_SCHEDULE_INFO().round_period;
            }

            CURRENT_SCHEDULE_INFO().round_period = OLD_SCHEDULE_INFO().round_period;

            // compute new reference time
            // Why "ui16_t_diff % 2" is used is explained under lwb_estimate_skew().
            uint16_t ui16_t_diff = CURRENT_SCHEDULE_INFO().time - OLD_SCHEDULE_INFO().time;
            uint16_t new_t_ref = lwb_context.t_last_sync_ref +
                                 ((int32_t)ui16_t_diff * lwb_context.skew / (int32_t)64) +
                                 ((uint32_t)RTIMER_SECOND * (ui16_t_diff % 2));
            set_t_ref_l(new_t_ref);
            lwb_context.t_last_sync_ref = new_t_ref;
            lwb_context.t_sync_ref = new_t_ref;

        } else {
            // The new state is bootstrap. We do not calculate things based on old information.
        }

    }
}