예제 #1
0
/** \copydoc nwl_build_advp_sync_train */
void nwl_build_advp_sync_train(uint16_t duration, uint8_t spectrum_id[2], int8_t tx_eirp, uint8_t subnet)
{
	uint16_t advp_target_timestamp = timer_get_counter_value() + duration;

	phy_keep_radio_on(true);
	process_callback = false;

	uint16_t eta = duration; //advp_target_timestamp - timer_get_counter_value();

	//nwl_event.next_event =

	while (eta > 5 && eta <= duration)
	{
		tx_callback_received = false;

		nwl_build_advertising_protocol_data(eta, spectrum_id, tx_eirp, subnet);
		dll_tx_frame();

		while (!tx_callback_received);

		__delay_cycles(8000);

		eta = advp_target_timestamp - timer_get_counter_value();
	}


	phy_keep_radio_on(false);


	process_callback = true;
}
static void configure_next_event()
{
    //this function should only be called from an atomic context
	timer_tick_t next_fire_time;
    do
    {
		//find the next event that has not yet passed, and schedule
		//the 'late' events while we're at it
		NG(next_event) = get_next_event();

		if(NG(next_event) != NO_EVENT)
		{
			next_fire_time = NG(timers)[NG(next_event)].next_event;
			if ( (((int32_t)next_fire_time) - ((int32_t)timer_get_counter_value())) <= 0 )
			{
				sched_post_task_prio(NG(timers)[NG(next_event)].f, NG(timers)[NG(next_event)].priority);
				NG(timers)[NG(next_event)].f = 0x0;
			}
		}
    }
    while(NG(next_event) != NO_EVENT && ( (((int32_t)next_fire_time) - ((int32_t)timer_get_counter_value())) <= 0  ) );

    //at this point NG(next_event) is eiter equal to NO_EVENT (no tasks left)
    //or we have the next event we can schedule
    if(NG(next_event) == NO_EVENT)
    {
		//cancel the timer in case it is still running (can happen if we're called from timer_cancel_event)
		NG(hw_event_scheduled) = false;
		hw_timer_cancel(HW_TIMER_ID);
    }
    else
    {
		//calculate schedule time relative to current time rather than
		//latest overflow time, to counteract any delays in updating counter_offset
		//(eg when we're scheduling an event from an interrupt and thereby delaying
		//the updating of counter_offset)
    	timer_tick_t fire_delay = (next_fire_time - timer_get_counter_value());
		//if the timer should fire in less ticks than supported by the HW timer --> schedule it
		//(otherwise it is scheduled from timer_overflow when needed)
		if(fire_delay < COUNTER_OVERFLOW_INCREASE)
		{
			NG(hw_event_scheduled) = true;
			hw_timer_schedule_delay(HW_TIMER_ID, (hwtimer_tick_t)fire_delay);
#ifndef NDEBUG	    
			//check that we didn't try to schedule a timer in the past
			//normally this shouldn't happen but it IS theoretically possible...
			fire_delay = (next_fire_time - timer_get_counter_value());
			//fire_delay should be in [0,COUNTER_OVERFLOW_INCREASE]. if this is not the case, it is because timer_get_counter() is
			//now larger than next_fire_event, which means we 'missed' the event
			assert(((int32_t)fire_delay) > 0);
#endif
		}
		else
		{
			//set hw_event_scheduled explicitly to false to allow timer_overflow
			//to schedule the event when needed
			NG(hw_event_scheduled) = false;
		}
    }
}
void bootstrap()
{
    log_print_string("Device booted at time: %d\n", timer_get_counter_value());

    hw_radio_init(p_alloc, p_free);
    hw_radio_set_rx(&rx_cfg, rx_callback, rssi_valid);


    NG(tx_buffer).radio_packet.length = sizeof(packet_struct_t) - sizeof(hw_radio_packet_t);
    NG(tx_buffer).radio_packet.tx_meta.tx_cfg.channel_id = rx_cfg.channel_id;
    NG(tx_buffer).radio_packet.tx_meta.tx_cfg.syncword_class = rx_cfg.syncword_class;
    NG(tx_buffer).radio_packet.tx_meta.tx_cfg.eirp = 0;

	NG(tx_buffer).src_node = hw_get_unique_id();
    NG(tx_buffer).dst_node = 0xFFFF;
    NG(tx_buffer).counter = 0;


    sched_register_task(&send_packet);
    timer_post_task_delay(&send_packet, TIMER_TICKS_PER_SEC + (get_rnd() %TIMER_TICKS_PER_SEC));

//    NG(status).is_rx = false;
//    NG(status).is_sleep = true;
//    NG(status).tx_busy = false;
//    NG(status).rx_busy = false;
//    sched_register_task(&poll_status);
//    sched_post_task(poll_status);

}
예제 #4
0
void bootstrap()
{
    DPRINT("Device booted at time: %d\n", timer_get_counter_value()); // TODO not printed for some reason, debug later
    id = hw_get_unique_id();
    hw_radio_init(&alloc_new_packet, &release_packet);

    rx_cfg.channel_id = current_channel_id;
    tx_cfg.channel_id = current_channel_id;

    ubutton_register_callback(0, &userbutton_callback);
    ubutton_register_callback(1, &userbutton_callback);

    fifo_init(&uart_rx_fifo, uart_rx_buffer, sizeof(uart_rx_buffer));

    uart_set_rx_interrupt_callback(&uart_rx_cb);
    uart_rx_interrupt_enable(true);

    sched_register_task(&start_rx);
    sched_register_task(&transmit_packet);
    sched_register_task(&start);
    sched_register_task(&process_uart_rx_fifo);

    current_state = STATE_CONFIG_DIRECTION;

    sched_post_task(&start);
    sched_post_task(&process_uart_rx_fifo);
}
예제 #5
0
void bootstrap()
{
	led_on(0);
	led_on(1);

	log_print_string("Device booted at time: %d\n", timer_get_counter_value());
	console_print("Device Booted\r\n");

    sched_register_task(&led_on_callback);
    sched_register_task(&led_off_callback);
    sched_register_task(&timer1_callback);

    timer_post_task_delay(&led_on_callback, TIMER_TICKS_PER_SEC);
    //timer_post_task_delay(&timer1_callback, 0x0000FFFF + (uint32_t)100);

#if PLATFORM_NUM_BUTTONS > 0
    int i= 0;
    for (i=0;i<PLATFORM_NUM_BUTTONS;i++)
	{
    	ubutton_register_callback(i, &userbutton_callback);
	}
#endif

    led_off(0);
    led_off(1);
}
예제 #6
0
/**
 * Get the current counter value between 0 and the maximum count (HAL_timer_set_count)
 * @param  timer_num timer number to get the current count
 * @return           the current counter of the alarm
 */
hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
  const tTimerConfig timer = TimerConfig[timer_num];

  uint64_t counter_value;
  timer_get_counter_value(timer.group, timer.idx, &counter_value);

  return counter_value;
}
static void process_serial_frame(fifo_t* fifo) {
  bool command_completed = false;
  bool completed_with_error = false;
  while(fifo_get_size(fifo)) {
    alp_action_t action;
    alp_parse_action(fifo, &action);

    switch(action.operation) {
      case ALP_OP_RETURN_TAG:
        if(action.tag_response.tag_id == command.tag_id) {
          command_completed = action.tag_response.completed;
          completed_with_error = action.tag_response.error;
        } else {
          DPRINT("received resp with unexpected tag_id (%i vs %i)", action.tag_response.tag_id, command.tag_id);
          // TODO unsolicited responses
        }
        break;
      case ALP_OP_WRITE_FILE_DATA:
        if(callbacks->write_file_data_callback)
          callbacks->write_file_data_callback(action.file_data_operand.file_offset.file_id,
                                               action.file_data_operand.file_offset.offset,
                                               action.file_data_operand.provided_data_length,
                                               action.file_data_operand.data);
        break;
      case ALP_OP_RETURN_FILE_DATA:
        if(callbacks->return_file_data_callback)
          callbacks->return_file_data_callback(action.file_data_operand.file_offset.file_id,
                                               action.file_data_operand.file_offset.offset,
                                               action.file_data_operand.provided_data_length,
                                               action.file_data_operand.data);
        break;
      case ALP_OP_RETURN_STATUS:
        if(action.status.type==ALP_ITF_ID_D7ASP)
        {
          d7ap_session_result_t interface_status = *((d7ap_session_result_t*)action.status.data);
          uint8_t addressee_len = d7ap_addressee_id_length(interface_status.addressee.ctrl.id_type);
          DPRINT("received resp from: ");
          DPRINT_DATA(interface_status.addressee.id, addressee_len);
        }
        if(callbacks->modem_interface_status_callback)
          callbacks->modem_interface_status_callback(action.status.type,&action.status.data);
        break;
      default:
        assert(false);
    }
  }


  if(command_completed) {
    DPRINT("command with tag %i completed @ %i", command.tag_id, timer_get_counter_value());
    if(callbacks->command_completed_callback)
      callbacks->command_completed_callback(completed_with_error,command.tag_id);

    command.is_active = false;
  }

}
void execute_sensor_measurement() {
#if HW_NUM_LEDS >= 1
    led_toggle(0);
#endif
    // use the counter value for now instead of 'real' sensor
    uint32_t val = timer_get_counter_value();
    // file 0x40 is configured to use D7AActP trigger an ALP action which 
    // broadcasts this file data on Access Class 0
    fs_write_file(0x40, 0, (uint8_t*)&val, 4);
    timer_post_task_delay(&execute_sensor_measurement, REPORTING_INTERVAL_TICKS);
}
void read_rssi()
{
    timestamped_rssi_t rssi_measurement;
    rssi_measurement.tick = timer_get_counter_value();
    rssi_measurement.rssi = hw_radio_get_rssi();
    rssi_measurements[rssi_measurements_index] = rssi_measurement;
    rssi_measurements_index++;
    if(rssi_measurements_index < 1000)
        timer_post_task_delay(&read_rssi, 1); // TODO delay
    else
        log_print_string("done");
}
static void rx_callback(hw_radio_packet_t* tx_packet)
{
	if(tx_packet->length < sizeof(packet_struct_t) - sizeof(hw_radio_packet_t))
		log_print_string("Got an invalid packet at time %d: packet was too short: %d < %d", timer_get_counter_value(), tx_packet->length, sizeof(packet_struct_t));
	else
	{
		packet_struct_t* packet = (packet_struct_t*)tx_packet;
		if(packet->radio_packet.length != sizeof(packet_struct_t) - sizeof(hw_radio_packet_t))
			log_print_string("Got an invalid packet at time %d: packet length didn't match", timer_get_counter_value());
		log_print_string("Got packet from %u to %u, seq: %u at time %u", packet->src_node, packet->dst_node, packet->counter, timer_get_counter_value());
	}
	p_free(tx_packet);
}
__LINK_C error_t timer_post_task_prio(task_t task, timer_tick_t fire_time, uint8_t priority)
{
    error_t status = ENOMEM;
    if(priority > MIN_PRIORITY)
    	return EINVAL;

    start_atomic();
    uint32_t empty_index = FRAMEWORK_TIMER_STACK_SIZE;
    for(uint32_t i = 0; i < FRAMEWORK_TIMER_STACK_SIZE; i++)
    {
		if(NG(timers)[i].f == 0x0 && empty_index == FRAMEWORK_TIMER_STACK_SIZE)
		{
			empty_index = i;
		}
		else if(NG(timers)[i].f == task)
		{
			//for now: do not allow an event to be scheduled more than once
			//otherwise we risk having the same task being scheduled twice and only executed once
			//because the scheduler disallows the same task to be scheduled multiple times
			status = EALREADY;
			break;
		}
    }
    if(status != EALREADY && empty_index != FRAMEWORK_TIMER_STACK_SIZE)
    {
    	bool timers_reset = reset_timers();
		NG(timers)[empty_index].f = task;
		NG(timers)[empty_index].next_event = fire_time;
		NG(timers)[empty_index].priority = priority;

		//if there is no event scheduled, this event will run before the next scheduled event
		//or we reset the timers: trigger a reconfiguration of the next scheduled event

		bool do_config = NG(next_event) == NO_EVENT || timers_reset;
		if(!do_config)
		{
			uint32_t counter = timer_get_counter_value();
			//if the new event should fire sooner than the old event --> trigger reconfig
			//this is done using signed ints (compared to the current counter)
			//to ensure propper handling of timer overflows
			int32_t next_fire_delay = ((int32_t)fire_time) - ((int32_t)counter);
			int32_t old_fire_delay = ((int32_t)NG(timers)[NG(next_event)].next_event) - ((int32_t)counter);
			do_config = next_fire_delay < old_fire_delay;
		}
		if(do_config)
			configure_next_event();
		status = SUCCESS;
    }
    end_atomic();
    return status;
}
bool alloc_command() {
  if(command.is_active) {
    DPRINT("prev command still active @ %i", timer_get_counter_value());
    return false;
  }

  command.is_active = true;
  fifo_init(&command.fifo, command.buffer, CMD_BUFFER_SIZE);
  command.tag_id = next_tag_id;
  next_tag_id++;

  alp_append_tag_request_action(&command.fifo, command.tag_id, true);
  return true;
}
void bootstrap() {
    DPRINT("Device booted at time: %d\n", timer_get_counter_value());

#ifndef FRAMEWORK_LOG_BINARY
    console_print("\r\nPER TEST - commands:\r\n");
    console_print("  CHANfffriii  channel settings:\r\n");
    console_print("               fff frequency : 433, 868, 915\r\n");
    console_print("               r   rate      : L(ow) N(ormal) H(igh)\r\n");
    console_print("               iii center_freq_index\r\n");
    console_print("  TRANsss      transmit a packet every sss seconds.\r\n");
    console_print("  RECV         receive packets\r\n");
    console_print("  RSET         reset module\r\n");
#endif

    id = hw_get_unique_id();
    hw_radio_init(&alloc_new_packet, &release_packet);

    rx_cfg.channel_id = current_channel_id;
    tx_cfg.channel_id = current_channel_id;

    ubutton_register_callback(0, &userbutton_callback);
    ubutton_register_callback(1, &userbutton_callback);

    fifo_init(&uart_rx_fifo, uart_rx_buffer, sizeof(uart_rx_buffer));

    console_set_rx_interrupt_callback(&uart_rx_cb);
    console_rx_interrupt_enable();

    sched_register_task(&start_rx);
    sched_register_task(&transmit_packet);
    sched_register_task(&start);
    sched_register_task(&process_uart_rx_fifo);

    current_state = STATE_CONFIG_DIRECTION;

    sched_post_task(&start);
    sched_post_task(&process_uart_rx_fifo);


#ifdef PLATFORM_EFM32GG_STK3700
#else
    	char str[20];
    	channel_id_to_string(&current_channel_id, str, sizeof(str));
    	lcd_write_line(6, str);
#endif

    timer_post_task(&transmit_packet, TIMER_TICKS_PER_SEC * 1);

}
void read_rssi()
{
    timestamped_rssi_t rssi_measurement;
    rssi_measurement.tick = timer_get_counter_value();

    char rssi_samples_str[5 * RSSI_SAMPLES_PER_MEASUREMENT] = "";
    int16_t max_rssi_sample = -200;
    for(int i = 0; i < RSSI_SAMPLES_PER_MEASUREMENT; i++)
    {
        rssi_measurement.rssi[i] = hw_radio_get_rssi();
        if(rssi_measurement.rssi[i] > max_rssi_sample)
            max_rssi_sample = rssi_measurement.rssi[i];

        sprintf(rssi_samples_str + (i * 5), ",%04i", rssi_measurement.rssi[i]);
        // TODO delay?
    }

    char str[80];
    char channel_str[8] = "";


    channel_id_to_string(&rx_cfg.channel_id, channel_str, sizeof(channel_str));
    lcd_write_string(channel_str);
    sprintf(str, "%7s,%i%s\n", channel_str, rssi_measurement.tick, rssi_samples_str);
    console_print(str);

#ifdef PLATFORM_EFM32GG_STK3700
    //lcd_all_on();
    lcd_write_number(max_rssi_sample);
#elif defined HAS_LCD
    sprintf(str, "%7s,%d\n", channel_str, max_rssi_sample);
    lcd_write_string(str);
#endif

    if(!use_manual_channel_switching)
    {
        switch_next_channel();
        sched_post_task(&start_rx);
    }
    else
    {
    	sched_post_task(&process_uart_rx_fifo); // check for UART commands first
        uint16_t delay = rand() % 5000;
        timer_post_task_delay(&read_rssi, delay);
    }

    hw_watchdog_feed();
}
예제 #15
0
static void ezradio_handle_end_of_packet()
{
	// fill rx_meta
	rx_packet->rx_meta.rssi = hw_radio_get_latched_rssi();
	rx_packet->rx_meta.lqi = 0;
	memcpy(&(rx_packet->rx_meta.rx_cfg.channel_id), &current_channel_id, sizeof(channel_id_t));
	if (has_hardware_crc && current_rx_cfg.channel_id.channel_header.ch_coding != PHY_CODING_FEC_PN9)
		rx_packet->rx_meta.crc_status = HW_CRC_VALID;
	else
		rx_packet->rx_meta.crc_status = HW_CRC_UNAVAILABLE;

	rx_packet->rx_meta.timestamp = timer_get_counter_value();
	//memcpy((void*)rx_packet->rx_meta.rx_cfg, (void*)&current_rx_cfg, sizeof(hw_rx_metadata_t));

	ezradio_fifo_info(EZRADIO_CMD_FIFO_INFO_ARG_FIFO_RX_BIT, NULL);


	DPRINT_DATA(rx_packet->data, rx_packet->length+1);


	if (current_rx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9)
	{
		fec_decode_packet(rx_packet->data, rx_packet->length, rx_packet->length);
		//assert length and data[0] can only differ 1
		rx_packet->length =  rx_packet->data[0];
	}

	DPRINT_PACKET(rx_packet, false);


	DEBUG_RX_END();

//					if(rx_packet_callback != NULL) // TODO this can happen while doing CCA but we should not be interrupting here (disable packet handler?)
	rx_packet_callback(rx_packet);
//					else
//						release_packet_callback(packet);

	if(current_state == HW_RADIO_STATE_RX)
	{
		start_rx(&current_rx_cfg);
	}
}
예제 #16
0
void bootstrap()
{
    DPRINT("Device booted at time: %d\n", timer_get_counter_value()); // TODO not printed for some reason, debug later

    data[0] = PACKET_LENGTH-1;
    int i = 1;
    for (;i<PACKET_LENGTH;i++)
    	data[i] = i;

    hw_radio_init(&alloc_new_packet, &release_packet);

    tx_packet->tx_meta.tx_cfg = tx_cfg;

	#ifdef RX_MODE
    	sched_register_task(&start_rx);
        sched_post_task(&start_rx);
	#else
        sched_register_task(&transmit_packet);
        sched_post_task(&transmit_packet);
	#endif
}
void measureTemperature()
{
	float temp = hw_get_internal_temperature();

	int temperature = (int)(temp * 10);

#ifdef PLATFORM_EFM32GG_STK3700

	int ring_segments = temperature/100;
	ring_segments = ring_segments > 8 ? 8 : ring_segments;
	lcd_show_ring(ring_segments);

	lcd_write_temperature(temperature*10, 1);
#endif

	timer_tick_t tick = timer_get_counter_value();

	char str[80];
	sprintf(str, "%7s,%i,%2d.%2d\n", TEMPERATURE_TAG, tick, (temperature/10), abs(temperature%10));
	console_print(str);
}
//we override __assert_func to flash the leds (so we know something bad has happend)
//and to repeat the error message repeatedly (so we have a chance to attach the device to a serial console before the error message is gone)
void __assert_func( const char *file, int line, const char *func, const char *failedexpr)
{
#if defined FRAMEWORK_DEBUG_ASSERT_REBOOT // make sure this parameter is used also when including assert.h instead of debug.h
        hw_reset();
#endif

	start_atomic();
	led_on(0);
	led_on(1);
#ifdef PLATFORM_USE_USB_CDC
	// Dissable all IRQs except the one for USB
	for(uint32_t j=0;j < EMU_IRQn; j++)
		NVIC_DisableIRQ(j);

	NVIC_EnableIRQ( USB_IRQn );

	end_atomic();
#endif

	lcd_clear();
	lcd_write_string("ERROR");
	lcd_write_number(timer_get_counter_value());

    __asm__("BKPT"); // break into debugger

	while(1)
	{
		printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",failedexpr, file, line, func ? ", function: " : "", func ? func : "");

		for(uint32_t j = 0; j < 20; j++)
		{
			//blink at twice the frequency of the _exit call, so we can identify which of the two events has occurred
			for(uint32_t i = 0; i < 0xFFFFF; i++){}
			led_toggle(0);
			led_toggle(1);
		}
	}
	end_atomic();

}
void bootstrap()
{
    DPRINT("Device booted at time: %d\n", timer_get_counter_value()); // TODO not printed for some reason, debug later

#ifdef HAS_LCD
    lcd_write_string("cont tx");
#endif

    switch(current_channel_class)
    {
        // TODO only 433 for now
        case PHY_CLASS_NORMAL_RATE:
        	channel_count = NORMAL_RATE_CHANNEL_COUNT;
            realloc(channel_indexes, channel_count);
            for(int i = 0; i < channel_count; i++)
                channel_indexes[i] = i * 8;

            break;
        case PHY_CLASS_LO_RATE:
        	channel_count = LO_RATE_CHANNEL_COUNT;
            realloc(channel_indexes, channel_count);
            for(int i = 0; i < channel_count; i++)
                channel_indexes[i] = i;

            break;
    }

#if NUM_USERBUTTONS > 1
    ubutton_register_callback(0, &userbutton_callback);
    ubutton_register_callback(1, &userbutton_callback);
#endif

    hw_radio_init(NULL, NULL);

    sched_register_task(&start);
    timer_post_task_delay(&start, TIMER_TICKS_PER_SEC * 5);
}
void bootstrap()
{
    DPRINT("Device booted at time: %d\n", timer_get_counter_value()); // TODO not printed for some reason, debug later

#ifdef HAS_LCD
    lcd_write_string("cont TX \n");
#endif

    switch(current_channel_class)
    {
        case PHY_CLASS_NORMAL_RATE:
          channel_count = NORMAL_RATE_CHANNEL_COUNT;
            realloc(channel_indexes, channel_count);
            for(int i = 0; i < channel_count; i++)
                channel_indexes[i] = i * 8;

            break;
        case PHY_CLASS_LO_RATE:
          channel_count = LO_RATE_CHANNEL_COUNT;
            realloc(channel_indexes, channel_count);
            for(int i = 0; i < channel_count; i++)
                channel_indexes[i] = i;

            break;
    }

#if PLATFORM_NUM_BUTTONS > 1
    ubutton_register_callback(0, &userbutton_callback);
    ubutton_register_callback(1, &userbutton_callback);
#endif

    hw_radio_init(&alloc_packet_callback, &release_packet_callback);

    sched_register_task(&start);
    timer_post_task_delay(&start, 500);
}
static uint32_t get_next_event()
{
    //this function should only be called from an atomic context
    reset_timers();
    int32_t min_delay;
    uint32_t next_fire_event = NO_EVENT;
    uint32_t counter = timer_get_counter_value();

    for(uint32_t i = 0; i < FRAMEWORK_TIMER_STACK_SIZE; i++)
    {
    	if(NG(timers)[i].f == 0x0)
    		continue;
    	//trick borrowed from AODV: by using signed integers in this way
    	//we know that if the event has already passed delay_ticks will be < 0
    	// --> events are sorted from past -> future regardless of any (pending) overflows
    	int32_t delay_ticks = ((int32_t)NG(timers)[i].next_event) - ((int32_t)counter);
    	if(next_fire_event == NO_EVENT || delay_ticks < min_delay)
		{
    		min_delay = delay_ticks;
			next_fire_event = i;
		}
    }
    return next_fire_event;
}
	static bool reset_timers()
	{
		//this function should only be called from an atomic context
		if(NG(next_event) == NO_EVENT)
		{
			reset_counter();
			return true;
		}

		timer_tick_t cur_value = timer_get_counter_value();
		reset_counter();
		for(uint32_t i = 0; i < FRAMEWORK_TIMER_STACK_SIZE; i++)
		{
			if(NG(timers)[i].f != 0x0)
			{
				//prevent the value from 'underflowing'
				if(cur_value > NG(timers)[i].next_event)
					NG(timers)[i].next_event = 0;
				else
					NG(timers)[i].next_event -= cur_value;
			}
		}
		return true;
	}
void bootstrap()
{
	led_on(0);
	led_on(1);

	log_print_string("Device booted at time: %d\n", timer_get_counter_value());

    sched_register_task(&led_on_callback);
    sched_register_task(&led_off_callback);
    sched_register_task(&timer1_callback);

    timer_post_task_delay(&led_on_callback, TIMER_TICKS_PER_SEC);
    timer_post_task_delay(&timer1_callback, 0x0000FFFF + (uint32_t)100);

#if NUM_USERBUTTONS > 0
    ubutton_register_callback(0, &userbutton_callback);
    ubutton_register_callback(1, &userbutton_callback);
#endif

    led_off(0);
    led_off(1);


}
static void ezradio_int_callback()
{
	//DPRINT("ezradio ISR");

	ezradio_cmd_reply_t ezradioReply;
	ezradio_cmd_reply_t radioReplyLocal;
	ezradio_get_int_status(0x0, 0x0, 0x0, &ezradioReply);
	//ezradio_frr_a_read(3, &ezradioReply);

	//DPRINT(" - INT_PEND     %s", byte_to_binary(ezradioReply.FRR_A_READ.FRR_A_VALUE));
  DPRINT(" - INT_PEND     %s", byte_to_binary(ezradioReply.GET_INT_STATUS.INT_PEND));
//	DPRINT(" - INT_STATUS   %s", byte_to_binary(ezradioReply.GET_INT_STATUS.INT_STATUS));
//	DPRINT(" - PH_PEND      %s", byte_to_binary(ezradioReply.GET_INT_STATUS.PH_PEND));
	//DPRINT(" - PH_STATUS    %s", byte_to_binary(ezradioReply.GET_INT_STATUS.PH_STATUS));
	//DPRINT(" - PH_STATUS    %s", byte_to_binary(ezradioReply.FRR_A_READ.FRR_B_VALUE));
//	DPRINT(" - MODEM_PEND   %s", byte_to_binary(ezradioReply.GET_INT_STATUS.MODEM_PEND));
//	DPRINT(" - MODEM_STATUS %s", byte_to_binary(ezradioReply.GET_INT_STATUS.MODEM_STATUS));
//	DPRINT(" - CHIP_PEND    %s", byte_to_binary(ezradioReply.GET_INT_STATUS.CHIP_PEND));
//	DPRINT(" - CHIP_STATUS  %s", byte_to_binary(ezradioReply.GET_INT_STATUS.CHIP_STATUS));

	//if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_PH_INT_PEND_BIT)
	if (ezradioReply.GET_INT_STATUS.INT_PEND & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_PH_INT_PEND_BIT)
	{

		//DPRINT("PH ISR");
		switch(current_state)
		{
			case HW_RADIO_STATE_RX:
				if ((ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_PACKET_RX_BIT) ||
						(ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT))
				{
					//DPRINT("PACKET_RX IRQ");

					if(rx_packet_callback != NULL)
					{
						/* Check how many bytes we received. */
						ezradio_fifo_info(0, &radioReplyLocal);

						DPRINT("RX ISR packetLength: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);

						if (rx_fifo_data_lenght == 0)
						{
							DPRINT("RX FIFO: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
							uint8_t buffer[4];
							ezradio_read_rx_fifo(4, buffer);
							if (current_rx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9)
							{
								uint8_t fec_buffer[4];
								memcpy(fec_buffer, buffer, 4);
								fec_decode_packet(fec_buffer, 4, 4);
								expected_data_length = fec_calculated_decoded_length(fec_buffer[0]+1);
								DPRINT("RX Packet Length: %d / %d", fec_buffer[0], expected_data_length);
							} else {
								expected_data_length = buffer[0] + 1;
							}
							rx_packet = alloc_packet_callback(expected_data_length);
							memcpy(rx_packet->data, buffer, 4);
							rx_fifo_data_lenght += 4;
							radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT-=4;
						}

						if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_PACKET_RX_BIT)
						{

							/* Read out the RX FIFO content. */
							ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght]));
							//ezradio_read_rx_fifo(radioReplyLocal2.PACKET_INFO.LENGTH, packet->data);

							ezradio_handle_end_of_packet();
							return;
						}

						if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT)
						{
							while (radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT > 0)
							{
								DPRINT("RX FIFO: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
								/* Read out the FIFO Count bytes of RX FIFO */
								ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght]));
								rx_fifo_data_lenght += radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT;
								//DPRINT("%d of %d bytes collected", rx_fifo_data_lenght, rx_packet->data[0]+1);
								ezradio_fifo_info(0, &radioReplyLocal);

								if (rx_fifo_data_lenght >= expected_data_length)
								{
									ezradio_handle_end_of_packet();
									return;
								}
							}

							ezradio_int_callback();

							return;
						}

					}
				} else if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_CRC_ERROR_BIT)

				//} else if ( ezradioReply.FRR_A_READ.FRR_B_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_CRC_ERROR_BIT)
				{
					DPRINT("- PACKET_RX CRC_ERROR IRQ");
					/* Check how many bytes we received. */
					ezradio_fifo_info(0, &radioReplyLocal);
					DPRINT("RX ISR packetLength: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);

					//ezradio_cmd_reply_t radioReplyLocal2;
					//ezradio_get_packet_info(0, 0, 0, &radioReplyLocal2);

					if (rx_fifo_data_lenght == 0)
					{
						rx_packet = alloc_packet_callback(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
					}

					/* Read out the RX FIFO content. */
					ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght]));

					rx_packet->rx_meta.crc_status = HW_CRC_INVALID;
					rx_packet->length = rx_packet->data[0] + 1;


          DPRINT_DATA(rx_packet->data, rx_packet->length);


					DEBUG_RX_END();

					if(rx_packet_callback != NULL)
						rx_packet_callback(rx_packet);
					else
						release_packet_callback(rx_packet);

					if(current_state == HW_RADIO_STATE_RX)
					{
						start_rx(&current_rx_cfg);
					}

				} else {
					DPRINT((" - OTHER RX IRQ"));
				}



				break;
			case HW_RADIO_STATE_TX:
				if (ezradioReply.GET_INT_STATUS.PH_PEND & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT)
				//if (ezradioReply.FRR_A_READ.FRR_C_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT)
				{
					DPRINT("PACKET_SENT IRQ");
					DEBUG_TX_END();

					if(tx_packet_callback != 0)
          {
              current_packet->tx_meta.timestamp = timer_get_counter_value();
              DPRINT_DATA(current_packet->data, current_packet->length);
              tx_packet_callback(current_packet);
          }

          /* We can't switch back to Rx since the Rx callbacks are modified
           * during CCA, so we systematically go to idle
          */
          switch_to_idle_mode();

//				} else if (ezradioReply.FRR_A_READ.FRR_C_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_TX_FIFO_ALMOST_EMPTY_PEND_BIT)
//				{
//					DPRINT(" - TX FIFO Almost empty IRQ ");
//
//					ezradio_fifo_info(0, &radioReplyLocal);
//					DPRINT("TX FIFO Space: %d", radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE);
//
//					//Fill fifo
//					#ifdef HAL_RADIO_USE_HW_CRC
//						int16_t new_length = current_packet->length-1 - tx_fifo_data_length;
//					#else
//						int16_t new_length = current_packet->length+1 - tx_fifo_data_length;
//					#endif
//					if (new_length > radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE) new_length = radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE;
//
//					while (new_length > 0)
//					{
//						ezradio_write_tx_fifo(new_length, &(current_packet->data[tx_fifo_data_length]));
//						tx_fifo_data_length += new_length;
//						DPRINT ("%d added -> %d", new_length, tx_fifo_data_length);
//
//					#ifdef HAL_RADIO_USE_HW_CRC
//						new_length = current_packet->length-1 - tx_fifo_data_length;
//					#else
//						new_length = current_packet->length+1 - tx_fifo_data_length;
//					#endif
//						if (new_length > radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE) new_length = radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE;
//					}
//
//					if (new_length == 0)
//					{
//						DPRINT("reprocess callback");
//						ezradio_int_callback();
//						return;
//					}
//
//					DPRINT ("%d added -> %d", new_length, tx_fifo_data_length);
				} else {
					DPRINT(" - OTHER IRQ");
				}
				break;
			default:
				//assert(false);
				DPRINT("State: %d", current_state);
		}
	}

//	if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_MODEM_INT_PEND_BIT)
//	{
//		DPRINT("MODEM ISR");
//	}

//	if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_CHIP_INT_PEND_BIT)
//	{
//		DPRINT("CHIP ISR");
//
//		if (current_state != HW_RADIO_STATE_IDLE)
//		{
//			if (ezradioReply.GET_INT_STATUS.CHIP_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_CHIP_STATUS_STATE_CHANGE_BIT)
//			{
//				ezradio_request_device_state(&radioReplyLocal);
//				DPRINT(" - Current State %d", radioReplyLocal.REQUEST_DEVICE_STATE.CURR_STATE);
//				DPRINT(" - Current channel %d", radioReplyLocal.REQUEST_DEVICE_STATE.CURRENT_CHANNEL);
//			}else {
//				DPRINT(" - OTHER IRQ");
//			}
//		}
//	}


}
예제 #25
0
static void execute_csma_ca()
{
    // TODO generate random channel queue
    //hw_radio_set_rx(NULL, NULL, NULL); // put radio in RX but disable callbacks to make sure we don't receive packets when in this state
                                        // TODO use correct rx cfg + it might be interesting to switch to idle first depending on calculated offset
    uint16_t tx_duration = calculate_tx_duration();
    timer_tick_t Tc = CONVERT_TO_TI(current_packet->d7atp_tc);
    switch (dll_state)
    {
        case DLL_STATE_CSMA_CA_STARTED:
        {
            dll_tca = Tc - tx_duration;
            dll_cca_started = timer_get_counter_value();
            DPRINT("Tca= %i = %i - %i", dll_tca, Tc, tx_duration);

#ifndef FRAMEWORK_TIMER_RESET_COUNTER
            // Adjust TCA value according the time already elapsed in the response period
            if (tc_starting_time) // TODO how do manage tc_starting_time? not set for now
            {
                dll_tca -= dll_cca_started - tc_starting_time;
                DPRINT("Adjusted Tca= %i = %i - %i", dll_tca, dll_cca_started, tc_starting_time);
            }
#endif

            if (dll_tca <= 0)
            {
                DPRINT("Tca negative, CCA failed");
                // Let the upper layer decide eventually to change the channel in order to get a chance a send this frame
                switch_state(DLL_STATE_IDLE);
                d7anp_signal_packet_csma_ca_insertion_completed(false);
                break;
            }

            uint16_t t_offset = 0;

            csma_ca_mode_t csma_ca_mode = current_access_profile->control_csma_ca_mode;
            // TODO overrule mode to UNC for subsequent requests by the requester, or a single response to a unicast request

            switch(csma_ca_mode)
            {
                case CSMA_CA_MODE_UNC:
                    // no delay
                    dll_slot_duration = 0;
                    break;
                case CSMA_CA_MODE_AIND: // TODO implement AIND
                {
                    dll_slot_duration = tx_duration;
                    // no initial delay
                    break;
                }
                case CSMA_CA_MODE_RAIND: // TODO implement RAIND
                {
                    dll_slot_duration = tx_duration;
                    uint16_t max_nr_slots = dll_tca / tx_duration;
                    uint16_t slots_wait = get_rnd() % max_nr_slots;
                    t_offset = slots_wait * tx_duration;
                    break;
                }
                case CSMA_CA_MODE_RIGD: // TODO implement RAIND
                {
                    dll_rigd_n = 0;
                    dll_tca0 = dll_tca;
                    dll_slot_duration = (uint16_t) ((double)dll_tca0) / (2 << (dll_rigd_n));
                    t_offset = get_rnd() % dll_slot_duration;
                    break;
                }
            }

            DPRINT("slot duration: %i t_offset: %i csma ca mode: %i", dll_slot_duration, t_offset, csma_ca_mode);

            dll_to = dll_tca - t_offset;

            if (t_offset > 0)
            {
                switch_state(DLL_STATE_CCA1);
                timer_post_task_delay(&execute_cca, t_offset);
            }
            else
            {
                switch_state(DLL_STATE_CCA1);
                sched_post_task(&execute_cca);
            }

            break;
        }
        case DLL_STATE_CSMA_CA_RETRY:
        {
        	int32_t cca_duration = timer_get_counter_value() - dll_cca_started;
        	dll_to -= cca_duration;


            DPRINT("RETRY dll_to = %i < %i ", dll_to, t_g);

            if (dll_to < t_g)
            {
                switch_state(DLL_STATE_CCA_FAIL);
                sched_post_task(&execute_csma_ca);
                break;
            }

            dll_tca = dll_to;
            dll_cca_started = timer_get_counter_value();
            uint16_t t_offset = 0;

            switch(current_access_profile->control_csma_ca_mode)
            {
                case CSMA_CA_MODE_AIND:
                case CSMA_CA_MODE_RAIND:
                {
                    uint16_t max_nr_slots = dll_tca / tx_duration;
                    uint16_t slots_wait = get_rnd() % max_nr_slots;
                    t_offset = slots_wait * tx_duration;
                    break;
                }
                case CSMA_CA_MODE_RIGD:
                {
                    dll_rigd_n++;
                    dll_slot_duration = (uint16_t) ((double)dll_tca0) / (2 << (dll_rigd_n+1));
                    if(dll_slot_duration != 0) // TODO can be 0, validate
                        t_offset = get_rnd() % dll_slot_duration;
                    else
                        t_offset = 0;

                    DPRINT("slot duration: %i", dll_slot_duration);
                    break;
                }
            }

            DPRINT("t_offset: %i", t_offset);

            dll_to = dll_tca - t_offset;

            if (t_offset > 0)
            {
                timer_post_task_delay(&execute_csma_ca, t_offset);
            }
            else
            {
                switch_state(DLL_STATE_CCA1);
                sched_post_task(&execute_cca);
            }

            break;
        }
        case DLL_STATE_CCA_FAIL:
        {
            // TODO hw_radio_set_idle();
            switch_state(DLL_STATE_IDLE);
            d7anp_signal_packet_csma_ca_insertion_completed(false);
            if (process_received_packets_after_tx)
            {
                sched_post_task(&process_received_packets);
                process_received_packets_after_tx = false;
            }

            if (resume_fg_scan)
            {
                switch_state(DLL_STATE_FOREGROUND_SCAN);

                hw_rx_cfg_t rx_cfg = (hw_rx_cfg_t){
                    .channel_id.channel_header = current_access_profile->subbands[0].channel_header,
                    .channel_id.center_freq_index = current_access_profile->subbands[0].channel_index_start,
                    .syncword_class = PHY_SYNCWORD_CLASS1,
                };

                hw_radio_set_rx(&rx_cfg, &packet_received, NULL);
                resume_fg_scan = false;
            }
            break;
        }
    }
}

void dll_execute_scan_automation()
{
    uint8_t scan_access_class = fs_read_dll_conf_active_access_class();
    if(active_access_class != scan_access_class)
    {
        fs_read_access_class(scan_access_class, &scan_access_profile);
        active_access_class = scan_access_class;
    }

    current_access_profile = &scan_access_profile;

    if(current_access_profile->control_scan_type_is_foreground && current_access_profile->control_number_of_subbands > 0) // TODO background scan
    {
        assert(current_access_profile->control_number_of_subbands == 1); // TODO multiple not supported
        switch_state(DLL_STATE_SCAN_AUTOMATION);
        hw_rx_cfg_t rx_cfg = {
            .channel_id = {
                .channel_header = current_access_profile->subbands[0].channel_header,
                .center_freq_index = current_access_profile->subbands[0].channel_index_start
            },
            .syncword_class = PHY_SYNCWORD_CLASS1
        };
예제 #26
0
static uint64_t esp_apptrace_test_ts_get()
{
    uint64_t ts = 0;
    timer_get_counter_value(s_ts_timer_group, s_ts_timer_idx, &ts);
    return ts;
}
예제 #27
0
static void end_of_packet_isr()
{
    cc1101_interface_set_interrupts_enabled(false);
    DPRINT("end of packet ISR");
    switch(current_state)
    {
        case HW_RADIO_STATE_RX: ;
            uint8_t packet_len = cc1101_interface_read_single_reg(RXFIFO);
            DPRINT("EOP ISR packetLength: %d", packet_len);
            if(packet_len >= 63)
            {
            	// long packets not yet supported or bit error in length byte, don't assert but flush rx
                DPRINT("Packet size too big, flushing RX");
                uint8_t status = (cc1101_interface_strobe(RF_SNOP) & 0xF0);
                if(status == 0x60)
                {
                    // RX overflow
                    cc1101_interface_strobe(RF_SFRX);
                }
                else if(status == 0x10)
                {
                    // still in RX, switch to idle first
                    cc1101_interface_strobe(RF_SIDLE);
                }

                while(cc1101_interface_strobe(RF_SNOP) != 0x0F); // wait until in idle state
                cc1101_interface_strobe(RF_SRX);
                while(cc1101_interface_strobe(RF_SNOP) != 0x1F); // wait until in RX state
                cc1101_interface_set_interrupts_enabled(true);
                return;
            }

            hw_radio_packet_t* packet = alloc_packet_callback(packet_len);
            packet->length = packet_len;
            cc1101_interface_read_burst_reg(RXFIFO, packet->data + 1, packet->length);

            // fill rx_meta
            packet->rx_meta.rssi = convert_rssi(cc1101_interface_read_single_reg(RXFIFO));
            packet->rx_meta.lqi = cc1101_interface_read_single_reg(RXFIFO) & 0x7F;
            memcpy(&(packet->rx_meta.rx_cfg.channel_id), &current_channel_id, sizeof(channel_id_t));
            packet->rx_meta.crc_status = HW_CRC_UNAVAILABLE; // TODO
            packet->rx_meta.timestamp = timer_get_counter_value();

#ifdef FRAMEWORK_LOG_ENABLED
            log_print_raw_phy_packet(packet, false);
#endif

            rx_packet_callback(packet);
            if(current_state == HW_RADIO_STATE_RX) // check still in RX, could be modified by upper layer while in callback
            {
                uint8_t status = (cc1101_interface_strobe(RF_SNOP) & 0xF0);
                if(status == 0x60) // RX overflow
                {
                    cc1101_interface_strobe(RF_SFRX);
                    while(cc1101_interface_strobe(RF_SNOP) != 0x0F); // wait until in idle state
                    cc1101_interface_strobe(RF_SRX);
                    while(cc1101_interface_strobe(RF_SNOP) != 0x1F); // wait until in RX state
                }

                cc1101_interface_set_interrupts_enabled(true);
                assert(cc1101_interface_strobe(RF_SNOP) == 0x1F); // expect to be in RX mode
            }
            break;
        case HW_RADIO_STATE_TX:
        	if(!should_rx_after_tx_completed)
        		switch_to_idle_mode();

            current_packet->tx_meta.timestamp = timer_get_counter_value();

#ifdef FRAMEWORK_LOG_ENABLED
            log_print_raw_phy_packet(current_packet, true);
#endif

            if(tx_packet_callback != 0)
                tx_packet_callback(current_packet);

            if(should_rx_after_tx_completed)
            {
                // RX requested while still in TX ...
                // TODO this could probably be further optimized by not going into IDLE
                // after RX by setting TXOFF_MODE to RX (if the cfg is the same at least)
                should_rx_after_tx_completed = false;
                start_rx(&pending_rx_cfg);
            }
            break;
        default:
            assert(false);
    }
}
예제 #28
0
static void ezradio_int_callback()
{
	//DPRINT("ezradio ISR");

	ezradio_cmd_reply_t ezradioReply;
	ezradio_cmd_reply_t radioReplyLocal;
	ezradio_get_int_status(0x0, 0x0, 0x0, &ezradioReply);
	//ezradio_frr_a_read(3, &ezradioReply);

	//DPRINT(" - INT_PEND     %s", byte_to_binary(ezradioReply.FRR_A_READ.FRR_A_VALUE));
//	DPRINT(" - INT_PEND     %s", byte_to_binary(ezradioReply.GET_INT_STATUS.INT_PEND));
//	DPRINT(" - INT_STATUS   %s", byte_to_binary(ezradioReply.GET_INT_STATUS.INT_STATUS));
//	DPRINT(" - PH_PEND      %s", byte_to_binary(ezradioReply.GET_INT_STATUS.PH_PEND));
	//DPRINT(" - PH_STATUS    %s", byte_to_binary(ezradioReply.GET_INT_STATUS.PH_STATUS));
	//DPRINT(" - PH_STATUS    %s", byte_to_binary(ezradioReply.FRR_A_READ.FRR_B_VALUE));
//	DPRINT(" - MODEM_PEND   %s", byte_to_binary(ezradioReply.GET_INT_STATUS.MODEM_PEND));
//	DPRINT(" - MODEM_STATUS %s", byte_to_binary(ezradioReply.GET_INT_STATUS.MODEM_STATUS));
//	DPRINT(" - CHIP_PEND    %s", byte_to_binary(ezradioReply.GET_INT_STATUS.CHIP_PEND));
//	DPRINT(" - CHIP_STATUS  %s", byte_to_binary(ezradioReply.GET_INT_STATUS.CHIP_STATUS));

	//if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_PH_INT_PEND_BIT)
	if (ezradioReply.GET_INT_STATUS.INT_PEND & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_PH_INT_PEND_BIT)
	{
		//DPRINT("PH ISR");
		switch(current_state)
		{
			case HW_RADIO_STATE_RX:
				if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_PACKET_RX_BIT)
				//if (ezradioReply.FRR_A_READ.FRR_B_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_PACKET_RX_BIT)
				{
					DPRINT("PACKET_RX IRQ");

					if(rx_packet_callback != NULL)
					{
						/* Check how many bytes we received. */
						ezradio_fifo_info(0, &radioReplyLocal);

						DPRINT("RX ISR packetLength: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);

						//ezradio_cmd_reply_t radioReplyLocal2;
						//ezradio_get_packet_info(0, 0, 0, &radioReplyLocal2);

						if (rx_fifo_data_lenght == 0)
						{
							rx_packet = alloc_packet_callback(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
						}

			//            hw_radio_packet_t* packet = alloc_packet_callback(radioReplyLocal2.PACKET_INFO.LENGTH);
			//            packet->length = radioReplyLocal2.PACKET_INFO.LENGTH;
						/* Read out the RX FIFO content. */
						ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght]));
						//ezradio_read_rx_fifo(radioReplyLocal2.PACKET_INFO.LENGTH, packet->data);

						ezradio_handle_end_of_packet();

					}
				} else if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT)
						//} else if (ezradioReply.FRR_A_READ.FRR_B_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT)
					{
						//DPRINT("- RX FIFO almost full IRQ");

						ezradio_fifo_info(0, &radioReplyLocal);
						if (rx_fifo_data_lenght == 0)
						{
							DPRINT("RX FIFO: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
							uint8_t buffer[4];
							ezradio_read_rx_fifo(4, buffer);
							uint8_t length = buffer[0];
							if (current_rx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9)
							{
								uint8_t fec_buffer[4];
								memcpy(fec_buffer, buffer, 4);
								fec_decode_packet(fec_buffer, 4, 4);
								length = fec_calculated_decoded_length(fec_buffer[0]+1);
								DPRINT("RX Packet Length: %d / %d", fec_buffer[0], length);
							}
							rx_packet = alloc_packet_callback(length+1);
							rx_packet->length = length;
							memcpy(rx_packet->data, buffer, 4);
							rx_fifo_data_lenght += 4;
							radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT-=4;
						}
						while (radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT > 0)
						{
							DPRINT("RX FIFO: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
							/* Read out the FIFO Count bytes of RX FIFO */
							ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght]));
							rx_fifo_data_lenght += radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT;
							//DPRINT("%d of %d bytes collected", rx_fifo_data_lenght, rx_packet->data[0]+1);
							ezradio_fifo_info(0, &radioReplyLocal);

							if (rx_fifo_data_lenght >= rx_packet->length + 1)
							{
								ezradio_handle_end_of_packet();
								return;
							}
						}

						ezradio_int_callback();

						return;
				} else if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_CRC_ERROR_BIT)

				//} else if ( ezradioReply.FRR_A_READ.FRR_B_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_CRC_ERROR_BIT)
				{
					DPRINT("- PACKET_RX CRC_ERROR IRQ");
					/* Check how many bytes we received. */
					ezradio_fifo_info(0, &radioReplyLocal);
					DPRINT("RX ISR packetLength: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);

					//ezradio_cmd_reply_t radioReplyLocal2;
					//ezradio_get_packet_info(0, 0, 0, &radioReplyLocal2);

					if (rx_fifo_data_lenght == 0)
					{
						rx_packet = alloc_packet_callback(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT);
					}

					/* Read out the RX FIFO content. */
					ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght]));

					rx_packet->rx_meta.crc_status = HW_CRC_INVALID;
					rx_packet->length = rx_packet->data[0] + 1;


					DPRINT_PACKET(rx_packet, false);


					DEBUG_RX_END();

					if(rx_packet_callback != NULL)
						rx_packet_callback(rx_packet);
					else
						release_packet_callback(rx_packet);

					if(current_state == HW_RADIO_STATE_RX)
					{
						start_rx(&current_rx_cfg);
					}

				} else {
					DPRINT((" - OTHER RX IRQ"));
				}



				break;
			case HW_RADIO_STATE_TX:
				if (ezradioReply.GET_INT_STATUS.PH_PEND & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT)
				//if (ezradioReply.FRR_A_READ.FRR_C_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT)
				{
					DPRINT("PACKET_SENT IRQ");

					DEBUG_TX_END();
					if(!should_rx_after_tx_completed)
						switch_to_idle_mode();

					current_packet->tx_meta.timestamp = timer_get_counter_value();


					DPRINT_PACKET(current_packet, true);

					if(tx_packet_callback != 0)
						tx_packet_callback(current_packet);

					if(should_rx_after_tx_completed)
					{
						// RX requested while still in TX ...
						// TODO this could probably be further optimized by not going into IDLE
						// after RX by setting TXOFF_MODE to RX (if the cfg is the same at least)
						should_rx_after_tx_completed = false;
						start_rx(&current_rx_cfg);
					}
//				} else if (ezradioReply.FRR_A_READ.FRR_C_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_TX_FIFO_ALMOST_EMPTY_PEND_BIT)
//				{
//					DPRINT(" - TX FIFO Almost empty IRQ ");
//
//					ezradio_fifo_info(0, &radioReplyLocal);
//					DPRINT("TX FIFO Space: %d", radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE);
//
//					//Fill fifo
//					#ifdef HAL_RADIO_USE_HW_CRC
//						int16_t new_length = current_packet->length-1 - tx_fifo_data_length;
//					#else
//						int16_t new_length = current_packet->length+1 - tx_fifo_data_length;
//					#endif
//					if (new_length > radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE) new_length = radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE;
//
//					while (new_length > 0)
//					{
//						ezradio_write_tx_fifo(new_length, &(current_packet->data[tx_fifo_data_length]));
//						tx_fifo_data_length += new_length;
//						DPRINT ("%d added -> %d", new_length, tx_fifo_data_length);
//
//					#ifdef HAL_RADIO_USE_HW_CRC
//						new_length = current_packet->length-1 - tx_fifo_data_length;
//					#else
//						new_length = current_packet->length+1 - tx_fifo_data_length;
//					#endif
//						if (new_length > radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE) new_length = radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE;
//					}
//
//					if (new_length == 0)
//					{
//						DPRINT("reprocess callback");
//						ezradio_int_callback();
//						return;
//					}
//
//					DPRINT ("%d added -> %d", new_length, tx_fifo_data_length);
				} else {
					DPRINT(" - OTHER IRQ");
				}
				break;
			default:
				//assert(false);
				DPRINT("State: %d", current_state);
		}
	}

//	if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_MODEM_INT_PEND_BIT)
//	{
//		DPRINT("MODEM ISR");
//	}

//	if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_CHIP_INT_PEND_BIT)
//	{
//		DPRINT("CHIP ISR");
//
//		if (current_state != HW_RADIO_STATE_IDLE)
//		{
//			if (ezradioReply.GET_INT_STATUS.CHIP_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_CHIP_STATUS_STATE_CHANGE_BIT)
//			{
//				ezradio_request_device_state(&radioReplyLocal);
//				DPRINT(" - Current State %d", radioReplyLocal.REQUEST_DEVICE_STATE.CURR_STATE);
//				DPRINT(" - Current channel %d", radioReplyLocal.REQUEST_DEVICE_STATE.CURRENT_CHANNEL);
//			}else {
//				DPRINT(" - OTHER IRQ");
//			}
//		}
//	}


}
static void rssi_valid(int16_t rssi)
{
	log_print_string("Rssi valid at time %u", timer_get_counter_value());
}