Esempio n. 1
0
/*---------------------------------------------------------------------------*/
void
rf1a_cb_tx_ended(rtimer_clock_t *timestamp)
{
  GLOSSY_TX_STOPPED;

  g.t_tx_stop = *timestamp;

  if(WITH_SYNC()) {
    /* store the relay counter of this last transmission */
    g.relay_cnt_last_tx = g.header.relay_cnt;

    if(g.t_ref_updated == 0) {
      /* t_ref has not been updated yet: update it */
      update_t_ref(g.t_tx_start, g.header.relay_cnt);
    }
    if((g.relay_cnt_last_tx == g.relay_cnt_last_rx + 1) && (g.n_rx > 0)) {
      /* this transmission immediately followed a reception: measure T_slot */
      add_T_slot_measurement(g.t_tx_start - g.t_rx_start +
                             NS_TO_RTIMER_HF(TAU1));
    }
  }
  /* increment the transmission counter */
  g.n_tx++;

  if((g.n_tx == GET_N_TX_MAX(g.header.pkt_type)) &&
     (GET_N_TX_MAX(g.header.pkt_type) > 1 || (!IS_INITIATOR()))) {
    /* we have reached N_tx_max and either N_tx_max > 1 or we are a receiver:
     * stop Glossy */
    glossy_stop();
  } else {
#if GLOSSY_CONF_RETRANSMISSION_TIMEOUT
    if((IS_INITIATOR()) && (g.n_rx == 0)) {
      /* we are the initiator and we still have not received any packet:
       * schedule the timeout */
      schedule_timeout();
    }
#endif /* GLOSSY_CONF_RETRANSMISSION_TIMEOUT */
  }     
}
Esempio n. 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);
}
Esempio n. 3
0
/*---------------------------------------------------------------------------*/
void
rf1a_cb_rx_ended(rtimer_clock_t *timestamp, uint8_t *pkt, uint8_t pkt_len)
{
  GLOSSY_RX_STOPPED;
  /* enable timer overflow / update interrupt (since we are in an interrupt
   * context here, the timer interrupts will only be handled after this ISR)
   * Note that the RX/TX switching is constant regardless of the runtime of
   * this ISR; it is only necessary to write to the TX queue before the
   * preamble has been sent by the radio module */
  rtimer_update_enable(1);
  LWB_INT_ENABLE;
  g.t_rx_stop = *timestamp;
#if GLOSSY_CONF_COLLECT_STATS
  g.stats.pkt_cnt_crcok++;
#endif /* GLOSSY_CONF_COLLECT_STATS */
  
  /* we have received a packet and the CRC is correct, now check the header */
  if((process_glossy_header(pkt, pkt_len, 1) == GLOSSY_SUCCESS)) {
    /* we received a correct packet, and the header has been stored into
     * g.header */
    uint8_t *payload = pkt + GLOSSY_HEADER_LEN(g.header.pkt_type);

    /* store the relay counter corresponding to the first reception */
#if GLOSSY_CONF_COLLECT_STATS
    uint8_t relay_cnt = g.header.relay_cnt;
#endif /* GLOSSY_CONF_COLLECT_STATS */
    /* increment the relay counter */
    g.header.relay_cnt++;

    if((GET_N_TX_MAX(g.header.pkt_type) == 0) ||
       (g.n_tx < GET_N_TX_MAX(g.header.pkt_type))) {
      /* if n_tx_max is either unknown or not yet reached, transmit the
       * packet */
      rf1a_write_to_tx_fifo((uint8_t *)&g.header,
                            GLOSSY_HEADER_LEN(g.header.pkt_type),
                            payload, g.payload_len);
    } else {
      /* otherwise, stop Glossy */
      glossy_stop();
    }

#if GLOSSY_CONF_COLLECT_STATS
    /* stats */
    if(WITH_RELAY_CNT()) {
      /* the relay counter is part of the header */
      if(g.n_rx == 0) {
        g.stats.last_flood_relay_cnt = relay_cnt;
      }
    /* get the RSSI value */
      if(g.n_rx < 3) {
        g.stats.last_flood_rssi[g.n_rx] = rf1a_get_last_packet_rssi();
        g.stats.last_flood_hops[g.n_rx] = g.header.relay_cnt - 1;
    }
    }
    g.stats.last_flood_rssi_sum += rf1a_get_last_packet_rssi();
#endif /* GLOSSY_CONF_COLLECT_STATS */
    
    /* increment the reception counter */
    g.n_rx++;
    GLOSSY_FIRST_RX;

    if((!IS_INITIATOR()) && (g.n_rx == 1)) {
      /* we are a receiver and this was our first packet reception: */
      /* store the payload for the application */
      memcpy((uint8_t *)g.payload, payload, g.payload_len);
    }

    if(WITH_SYNC()) {
      /* store the relay counter of this last reception */
      g.relay_cnt_last_rx = g.header.relay_cnt - 1;

      if(g.t_ref_updated == 0) {
        /* t_ref has not been updated yet: update it */
        update_t_ref(g.t_rx_start - NS_TO_RTIMER_HF(TAU1),
                     g.header.relay_cnt - 1);
      }

      if((g.relay_cnt_last_rx == g.relay_cnt_last_tx + 1) &&
         (g.n_tx > 0)) {
        /* this reception immediately followed a transmission: measure
         * T_slot */
        add_T_slot_measurement(g.t_rx_start - g.t_tx_start -
                               NS_TO_RTIMER_HF(TAU1));
      }
    }
    /* notify about the successful reception */
    DEBUG_PRINT_VERBOSE("Glossy RX completed. Received a %u-byte packet with "
                        "initiator %u.", pkt_len, g.header.initiator_id);
  } else {
#if GLOSSY_CONF_COLLECT_STATS
    if(!g.stats.already_counted) {
      g.stats.last_flood_n_rx_fail++;
      g.stats.already_counted = 1;
    }
#endif /* GLOSSY_CONF_COLLECT_STATS */
    /* some fields in the header were not correct: discard it */
    rf1a_cb_rx_failed(timestamp);
  }
}
Esempio n. 4
0
/*---------------------------- Glossy interface -----------------------------*/
void
glossy_start(uint16_t initiator_id, uint8_t *payload, uint8_t payload_len,
             uint8_t n_tx_max, glossy_sync_t sync, glossy_rf_cal_t rf_cal)
{
  GLOSSY_STARTED;
  DEBUG_PRINT_VERBOSE("Glossy started: in=%u, pl=%u, n=%u, s=%u", initiator_id,
                      payload_len, n_tx_max, sync);

  /* disable undesired interrupts */
  GLOSSY_DISABLE_INTERRUPTS;

  /* reset the data structure */
  g.active = 1;
  g.payload = payload;
  g.payload_len = payload_len;
  g.n_rx = 0;
  g.n_tx = 0;
  g.relay_cnt_last_rx = 0;
  g.relay_cnt_last_tx = 0;
  g.t_ref_updated = 0;
  g.T_slot_sum = 0;
  g.n_T_slot = 0;

#if GLOSSY_CONF_COLLECT_STATS
  g.stats.last_flood_n_rx_started = 0;
  g.stats.last_flood_n_rx_fail = 0;
  g.stats.already_counted = 0;
  g.stats.last_flood_rssi_sum = 0;
  g.stats.last_flood_rssi_noise = 0;
  g.stats.last_flood_t_to_rx = 0;
  g.stats.last_flood_duration = rtimer_now_hf();
  if(WITH_RELAY_CNT()) {
    /* clear last_flood_rssi and last_flood_hops in one memset call */
    memset(g.stats.last_flood_rssi, 0, 6);
  }
#endif /* GLOSSY_CONF_COLLECT_STATS */

  /* prepare the Glossy header, with the information known so far */
  g.header.initiator_id = initiator_id;
  SET_PKT_TYPE(g.header.pkt_type, sync, n_tx_max);
  g.header.relay_cnt = 0;
  

  /* automatically switch to TX at the end of RX */
  rf1a_set_rxoff_mode(RF1A_OFF_MODE_TX);
  /* automatically switch to RX at the end of TX */
  rf1a_set_txoff_mode(RF1A_OFF_MODE_RX);
  /* do not calibrate automatically */
  rf1a_set_calibration_mode(RF1A_CALIBRATION_MODE_MANUAL);
  
  /* re-configure patable (config is lost when radio was in sleep mode) */
  rf1a_set_tx_power(RF_CONF_TX_POWER);

  if(rf_cal == GLOSSY_WITH_RF_CAL) {
    /* if instructed so, perform a manual calibration */
    rf1a_manual_calibration();
  }
  rf1a_set_header_len_rx(GLOSSY_HEADER_LEN(g.header.pkt_type));

  rf1a_go_to_idle();
  
  if(IS_INITIATOR()) {
    /* Glossy initiator */
    if(GET_SYNC(g.header.pkt_type) == GLOSSY_UNKNOWN_SYNC ||
       (g.payload_len + GLOSSY_HEADER_LEN(g.header.pkt_type) + 1) >
       RF_CONF_MAX_PKT_LEN) {
      /* the initiator must know whether there will be synchronization or
       * not and the packet length may not exceed the max. length */
      DEBUG_PRINT_ERROR("invalid parameters, Glossy stopped");
      glossy_stop();
    } else {
      /* start the first transmission */
      g.t_timeout = rtimer_now_hf() + TIMEOUT_EXTRA_TICKS;
      rf1a_start_tx();
      rf1a_write_to_tx_fifo((uint8_t *)&g.header,
                            GLOSSY_HEADER_LEN(g.header.pkt_type),
                            (uint8_t *)g.payload, g.payload_len);
      g.relay_cnt_timeout = 0;
    }
  } else {
    /* Glossy receiver */
    rf1a_start_rx();      
#if GLOSSY_CONF_COLLECT_STATS
    /* measure the channel noise (but only if waiting for the schedule */
    if(sync == GLOSSY_WITH_SYNC) {
      /* wait after entering RX mode before reading RSSI (see swra114d.pdf) */
      __delay_cycles(MCLK_SPEED / 3000);     /* wait 0.33 ms */
      g.stats.last_flood_rssi_noise = rf1a_get_rssi();  /* RSSI of the noise floor */
    }
#endif /* GLOSSY_CONF_COLLECT_STATS */
  }
  /* note: RF_RDY bit must be cleared by the radio core before entering LPM
   * after a transition from idle to RX or TX. Either poll the status of the
   * radio core (SNOP strobe) or read the GDOx signal assigned to RF_RDY */
  while(RF1AIN & BIT0);    /* check GDO0 signal (added by rdaforno) */
}