void rtt_handler(uint32_t event, gnrc_netif_t *netif) { uint32_t alarm; switch (event & 0xffff) { case GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING: { /* A new cycle starts, set sleep timing and initialize related MAC-info flags. */ netif->mac.lwmac.last_wakeup = rtt_get_alarm(); alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_DURATION_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING); gnrc_lwmac_set_quit_tx(netif, false); gnrc_lwmac_set_quit_rx(netif, false); gnrc_lwmac_set_phase_backoff(netif, false); netif->mac.rx.rx_bad_exten_count = 0; lwmac_set_state(netif, GNRC_LWMAC_LISTENING); break; } case GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING: { /* Set next wake-up timing. */ alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); break; } /* Set initial wake-up alarm that starts the cycle */ case GNRC_LWMAC_EVENT_RTT_START: { LOG_DEBUG("[LWMAC] RTT: Initialize duty cycling\n"); alarm = rtt_get_counter() + RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_DURATION_US); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING); gnrc_lwmac_set_dutycycle_active(netif, true); break; } case GNRC_LWMAC_EVENT_RTT_STOP: case GNRC_LWMAC_EVENT_RTT_PAUSE: { rtt_clear_alarm(); LOG_DEBUG("[LWMAC] RTT: Stop duty cycling, now in state %u\n", netif->mac.lwmac.state); gnrc_lwmac_set_dutycycle_active(netif, false); break; } case GNRC_LWMAC_EVENT_RTT_RESUME: { LOG_DEBUG("[LWMAC] RTT: Resume duty cycling\n"); rtt_clear_alarm(); alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); gnrc_lwmac_set_dutycycle_active(netif, true); break; } default: break; } }
int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg) { time_t t = mktime(time); rtc_callback.cb = cb; rtt_set_alarm((uint32_t)t, rtc_cb, arg); return 0; }
void lwmac_set_state(gnrc_netif_t *netif, gnrc_lwmac_state_t newstate) { gnrc_lwmac_state_t oldstate = netif->mac.lwmac.state; if (newstate == oldstate) { return; } if (newstate >= GNRC_LWMAC_STATE_COUNT) { LOG_ERROR("ERROR: [LWMAC] Trying to set invalid state %u\n", newstate); return; } /* Already change state, but might be reverted to oldstate when needed */ netif->mac.lwmac.state = newstate; /* Actions when leaving old state */ switch (oldstate) { case GNRC_LWMAC_RECEIVING: case GNRC_LWMAC_TRANSMITTING: { /* Enable duty cycling again */ rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, netif); #if (GNRC_LWMAC_ENABLE_DUTYCYLE_RECORD == 1) /* Output duty-cycle ratio */ uint64_t duty; duty = (uint64_t) rtt_get_counter(); duty = ((uint64_t) netif->mac.lwmac.awake_duration_sum_ticks) * 100 / (duty - (uint64_t)netif->mac.lwmac.system_start_time_ticks); printf("[LWMAC]: achieved duty-cycle: %lu %% \n", (uint32_t)duty); #endif break; } case GNRC_LWMAC_SLEEPING: { gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); break; } default: break; } /* Actions when entering new state */ switch (newstate) { /*********************** Operation states *********************************/ case GNRC_LWMAC_LISTENING: { _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); break; } case GNRC_LWMAC_SLEEPING: { /* Put transceiver to sleep */ _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_SLEEP); /* We may have come here through RTT handler, so timeout may still be active */ gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); if (gnrc_lwmac_get_phase_backoff(netif)) { gnrc_lwmac_set_phase_backoff(netif, false); uint32_t alarm; rtt_clear_alarm(); alarm = random_uint32_range(RTT_US_TO_TICKS((3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2)), RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US - (3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2))); LOG_WARNING("WARNING: [LWMAC] phase backoffed: %lu us\n", RTT_TICKS_TO_US(alarm)); netif->mac.lwmac.last_wakeup = netif->mac.lwmac.last_wakeup + alarm; alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); } /* Return immediately, so no rescheduling */ return; } /* Trying to send data */ case GNRC_LWMAC_TRANSMITTING: { rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif); /**< No duty cycling while RXing */ _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); /**< Power up netdev */ break; } /* Receiving incoming data */ case GNRC_LWMAC_RECEIVING: { rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif); /**< No duty cycling while TXing */ _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); /**< Power up netdev */ break; } case GNRC_LWMAC_STOPPED: { _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_OFF); break; } /*********************** Control states ***********************************/ case GNRC_LWMAC_START: { rtt_handler(GNRC_LWMAC_EVENT_RTT_START, netif); lwmac_set_state(netif, GNRC_LWMAC_LISTENING); break; } case GNRC_LWMAC_STOP: { rtt_handler(GNRC_LWMAC_EVENT_RTT_STOP, netif); lwmac_set_state(netif, GNRC_LWMAC_STOPPED); break; } case GNRC_LWMAC_RESET: { LOG_WARNING("WARNING: [LWMAC] Reset not yet implemented\n"); lwmac_set_state(netif, GNRC_LWMAC_STOP); lwmac_set_state(netif, GNRC_LWMAC_START); break; } /**************************************************************************/ default: { LOG_DEBUG("[LWMAC] No actions for entering state %u\n", newstate); return; } } lwmac_schedule_update(netif); }