void adc_calibrate()
{
	// Initialises clocks
	CMU_ClockEnable(cmuClock_HFPER, true);
	CMU_ClockEnable(cmuClock_ADC0, true);

	//todo: use new calibration values
	//todo: make adaptable for other ref voltages
	uint32_t old_gain_calibration_value =
	(DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_GAIN_MASK)
	>> _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT;

	uint32_t old_offset_calibration_value =
	(DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK)
	>> _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT;

	//RTCDRV_Trigger(100, NULL);

	uint32_t calibration_value = ADC_Calibration(ADC0, adcRef1V25);

	uint32_t offset_calibration_value = (calibration_value & _ADC_CAL_SINGLEOFFSET_MASK) >> _ADC_CAL_SINGLEOFFSET_SHIFT;
	uint32_t gain_calibration_value   = (calibration_value & _ADC_CAL_SINGLEGAIN_MASK) >> _ADC_CAL_SINGLEGAIN_SHIFT;
	log_print_stack_string(LOG_STACK_FWK, "ADC Calibration offset %d -> %d", old_offset_calibration_value, offset_calibration_value);
	log_print_stack_string(LOG_STACK_FWK, "ADC Calibration gain %d -> %d", old_gain_calibration_value, gain_calibration_value);
}
Beispiel #2
0
bool timer_add_event(timer_event* event)
{
	#ifdef LOG_FWK_ENABLED
	uint16_t current_timer = hal_timer_getvalue();
	log_print_stack_string(LOG_FWK, "timer_add_event: %d.%d", event->next_event/1000,event->next_event%1000);
	log_print_stack_string(LOG_FWK, "timer_add_event timer S : %d.%d", current_timer/1000, current_timer%1000);
	#endif

    if (event->next_event == 0)
    {
        event->f(NULL);
        return true;
    }

    timer_event new_event;
    new_event.f = event->f;
    new_event.next_event = event->next_event;

    if (timer_insert_value_in_queue(&new_event))
    {
        if (!started)
        {
            hal_timer_enable_interrupt();
            started = true;
            hal_timer_setvalue(new_event.next_event);
        }
        uint16_t diff = hal_timer_getvalue() - new_event.next_event;
        if (diff < 1000)
		{
			#ifdef LOG_FWK_ENABLED
        	current_timer = hal_timer_getvalue();
        	log_print_stack_string(LOG_FWK, "timer_add_event M timer overrun : %d.%d", current_timer/1000,current_timer%1000);
        	log_print_stack_string(LOG_FWK, "timer_add_event M: %d.%d", new_event.next_event/1000,  new_event.next_event%1000);
			#endif
			timer_completed();
		}
    } else {
        //log_print_stack_string(LOG_FWK, "Cannot add event, queue is full");
        return false;
    }

	#ifdef LOG_FWK_ENABLED
	current_timer = hal_timer_getvalue();
	log_print_stack_string(LOG_FWK, "timer_add_event timer E : %d.%d", current_timer/1000,current_timer%1000);
	#endif

    return true;
}
Beispiel #3
0
bool phy_translate_and_set_settings(uint8_t spectrum_id, uint8_t sync_word_class)
{
    if (previous_spectrum_id == spectrum_id && previous_sync_word_class == sync_word_class)
        return true;

    Strobe(RF_SIDLE);

    if(!phy_translate_settings(spectrum_id, sync_word_class, &fec, &channel_center_freq_index, &channel_bandwidth_index, &preamble_size, &sync_word))
    {
#ifdef LOG_PHY_ENABLED
        log_print_stack_string(LOG_PHY, "PHY Cannot translate settings");
#endif

        return false;
    }

    set_channel(channel_center_freq_index, channel_bandwidth_index);
    set_preamble_size(preamble_size);
    set_sync_word(sync_word);

    previous_spectrum_id = spectrum_id;
    previous_sync_word_class = sync_word_class;

    return true;
}
Beispiel #4
0
void timer_completed()
{
	#ifdef LOG_FWK_ENABLED
	uint16_t current_timer = hal_timer_getvalue();
	log_print_stack_string(LOG_FWK, "timer_completed: %d.%d", current_timer/1000,current_timer%1000);
	#endif

    timer_event* event = (timer_event*) queue_pop_value(&event_queue, sizeof(timer_event));

    bool directly_fire_new_event = false;

    if (event_queue.length == 0)
    {
        hal_timer_disable_interrupt();
        started = false;
    } else {
        hal_timer_setvalue(((timer_event*) event_queue.front)->next_event);
        uint16_t diff = hal_timer_getvalue() - ((timer_event*) event_queue.front)->next_event;
        if (diff < 1000)
        	directly_fire_new_event = true;
    }

    event->f(NULL);

    if (directly_fire_new_event)
    	timer_completed();
}
Beispiel #5
0
static void tx_callback()
{
	#ifdef LOG_DLL_ENABLED
		log_print_stack_string(LOG_DLL, "DLL TX OK");
	#endif
	dll_tx_callback(DLLTxResultOK);
}
Beispiel #6
0
void rx_fifo_overflow_isr()
{
#ifdef LOG_PHY_ENABLED
    log_print_stack_string(LOG_PHY, "rx_fifo_overflow");
#endif

    rxtx_finish_isr();
    if(phy_rx_callback != NULL)
        phy_rx_callback(NULL);
}
Beispiel #7
0
bool phy_init_tx()
{
    if(get_radiostate() != Idle)
    {
#ifdef LOG_PHY_ENABLED
        log_print_stack_string(LOG_PHY, "PHY radio not idle");
#endif

        return false;
    }

    //Set radio state
    state = Transmit;

    //Go to idle and flush the txfifo
    Strobe(RF_SIDLE);
    Strobe(RF_SFTX);

    return true;
}
error_t hw_radio_send_packet(hw_radio_packet_t* packet, tx_packet_callback_t tx_cb)
{
    // TODO error handling EINVAL, ESIZE, EOFF
    if(current_state == HW_RADIO_STATE_TX)
        return EBUSY;

    assert(packet->length < 63); // long packets not yet supported

    tx_packet_callback = tx_cb;

    if(current_state == HW_RADIO_STATE_RX)
    {
        pending_rx_cfg.channel_id = current_channel_id;
        pending_rx_cfg.syncword_class = current_syncword_class;
        should_rx_after_tx_completed = true;
    }

    current_state = HW_RADIO_STATE_TX;
    current_packet = packet;
    cc1101_interface_strobe(RF_SIDLE);
    cc1101_interface_strobe(RF_SFTX);

#ifdef FRAMEWORK_LOG_ENABLED // TODO more granular
    log_print_stack_string(LOG_STACK_PHY, "Data to TX Fifo:");
    log_print_data(packet->data, packet->length + 1);
#endif

    configure_channel((channel_id_t*)&(current_packet->tx_meta.tx_cfg.channel_id));
    configure_eirp(current_packet->tx_meta.tx_cfg.eirp);
    configure_syncword_class(current_packet->tx_meta.tx_cfg.syncword_class);

    cc1101_interface_write_burst_reg(TXFIFO, packet->data, packet->length + 1);
    cc1101_interface_set_interrupts_enabled(true);
    cc1101_interface_strobe(RF_STX);
    return SUCCESS;
}
Beispiel #9
0
static void scan_timeout()
{
	if (dll_state == DllStateNone)
		return;

	#ifdef LOG_DLL_ENABLED
		log_print_stack_string(LOG_DLL, "DLL scan time-out");
	#endif
	phy_idle();

	if (current_css == NULL)
	{
		return;
	}

	//Channel scan series
	timer_event event;
	event.next_event = current_css->values[current_scan_id].time_next_scan;
	event.f = &scan_next;

	current_scan_id = current_scan_id < current_css->length - 1 ? current_scan_id + 1 : 0;

	timer_add_event(&event);
}
Beispiel #10
0
void rx_data_isr()
{

    //Read number of bytes in RXFIFO
    uint8_t rxBytes = ReadSingleReg(RXBYTES);
#ifdef LOG_PHY_ENABLED
    log_print_stack_string(LOG_PHY, "rx_data_isr (%d bytes received)", rxBytes);
#endif

#ifdef D7_PHY_USE_FEC
    if(fec)
    {
        uint8_t fecbuffer[4];

        //If length is not set get the length from RXFIFO and set PKTLEN
        if (packetLength == 0) {
            ReadBurstReg(RXFIFO, fecbuffer, 4);
            fec_decode(fecbuffer);
            fec_set_length(*buffer);
            packetLength = ((*buffer & 0xFE) + 2) << 1;
            remainingBytes = packetLength - 4;
            WriteSingleReg(PKTLEN, (uint8_t)(packetLength & 0x00FF));
            WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_17_48);
            rxBytes -= 4;
        }

        //If remaining bytes is equal or less than 255 - fifo size, set length to fixed
        if(remainingBytes < 192)
            set_length_infinite(false);

        //Read data from buffer and decode
        while (rxBytes >= 4) {
            ReadBurstReg(RXFIFO, fecbuffer, 4);

            if(fec_decode(fecbuffer) == false)
                break;

            remainingBytes -= 4;
            rxBytes -= 4;
        }
    } else {
#endif
        //If length is not set get the length from RXFIFO and set PKTLEN
        if (packetLength == 0) {
            packetLength = ReadSingleReg(RXFIFO);
            WriteSingleReg(PKTLEN, packetLength);
            WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_17_48);
            remainingBytes = packetLength - 1;
            bufferPosition[0] = packetLength;
            bufferPosition++;
            rxBytes--;
#ifdef LOG_PHY_ENABLED
            log_print_stack_string(LOG_PHY, "rx_data_isr getting packetLength (%d)", packetLength);
#endif
        }

        //Never read the entire buffer as long as more data is going to be received
        if (remainingBytes > rxBytes) {
            rxBytes--;
        } else {
            rxBytes = remainingBytes;
        }

        //Read data from buffer
        ReadBurstReg(RXFIFO, bufferPosition, rxBytes);
        remainingBytes -= rxBytes;
        bufferPosition += rxBytes;
#ifdef D7_PHY_USE_FEC
    }
#endif

    //When all data has been received read rssi and lqi value and set packetreceived flag
    if(remainingBytes == 0)
    {
        rx_data.rssi = calculate_rssi(ReadSingleReg(RXFIFO));
        rx_data.lqi = ReadSingleReg(RXFIFO) & 0x7F;
        rx_data.length = *buffer;
        rx_data.data = buffer;
#ifdef LOG_PHY_ENABLED
        log_print_stack_string(LOG_PHY, "rx_data_isr packet received");
#endif
    }

#ifdef LOG_PHY_ENABLED
    log_print_stack_string(LOG_PHY, "rx_data_isr 1");
#endif
}
Beispiel #11
0
bool phy_rx(phy_rx_cfg_t* cfg)
{
#ifdef LOG_PHY_ENABLED
    log_print_stack_string(LOG_PHY, "phy_rx");
#endif

    RadioState current_state = get_radiostate();
    if(current_state != Idle && current_state != Receive)
    {
#ifdef LOG_PHY_ENABLED
        log_print_stack_string(LOG_PHY, "PHY Cannot RX, PHy not idle");
#endif
        return false;
    }

    //Set radio state
    state = Receive;

    //Flush the txfifo
    Strobe(RF_SIDLE);
    Strobe(RF_SFRX);

    //Set configuration

    if (!phy_translate_and_set_settings(cfg->spectrum_id, cfg->sync_word_class))
        return false;

    set_timeout(cfg->timeout);

//TODO Return error if fec not enabled but requested
#ifdef D7_PHY_USE_FEC
    if (fec) {
        //Disable hardware data whitening
        set_data_whitening(false);

        //Initialize fec encoding
        fec_init_decode(buffer);

        //Configure length settings
        set_length_infinite(true);

        if(cfg->length == 0)
        {
            packetLength = 0;
            remainingBytes = 0;
            WriteSingleReg(PKTLEN, 0xFF);
            WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_61_4);
        } else {
            fec_set_length(cfg->length);
            packetLength = ((cfg->length & 0xFE) + 2) << 1;
            remainingBytes = packetLength;
            WriteSingleReg(PKTLEN, (uint8_t)(packetLength & 0x00FF));
            WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_17_48);
        }
    } else {
#endif
        //Enable hardware data whitening
        set_data_whitening(true);

        //Set buffer position
        bufferPosition = buffer;

        //Configure length settings and txfifo threshold
        set_length_infinite(false);

        if(cfg->length == 0)
        {
            packetLength = 0;
            remainingBytes = 0;
            WriteSingleReg(PKTLEN, 0xFF);
            WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_61_4);
        } else {
            packetLength = cfg->length;
            remainingBytes = packetLength;
            WriteSingleReg(PKTLEN, packetLength);
            WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_17_48);
        }
#ifdef D7_PHY_USE_FEC
    }
#endif

    //TODO: set minimum sync word rss to scan minimum energy
    //Enable interrupts
    phy_set_gdo_values(GDOLine2, GDO_EDGE_RXFilled, GDO_SETTING_RXFilled);
    phy_set_gdo_values(GDOLine0, GDO_EDGE_EndOfPacket, GDO_SETTING_EndOfPacket);
    radioClearInterruptPendingLines();
    radioEnableGDO2Interrupt();
    radioEnableGDO0Interrupt();

    //Start receiving
    Strobe(RF_SRX);

    return true;
}
Beispiel #12
0
bool timer_insert_value_in_queue(timer_event* event)
{
	uint16_t current_timer = hal_timer_getvalue();
	#ifdef LOG_FWK_ENABLED
	log_print_stack_string(LOG_FWK, "timer_insert S - Timer current value: %d.%d", current_timer/1000, current_timer%1000);
	#endif

    // TODO: substract time already gone
	uint8_t position = 0;
	uint16_t next_event =  event->next_event;
	event->next_event = current_timer + event->next_event;

	while (position < event_queue.length)
	{
		timer_event *temp_event = (timer_event*) queue_read_value(&event_queue, position, sizeof(timer_event));
		if ((temp_event->next_event - current_timer)  > next_event)
		{
			if (position == 0)
			{
				hal_timer_disable_interrupt();
				started = false;
			}
			queue_insert_value(&event_queue, (void*) event, position, sizeof(timer_event));
			position = 0;
			break;
		}
		position++;
	}

	if (position == event_queue.length)
	{
		if (!queue_push_value(&event_queue, (void*) event, sizeof(timer_event)))
			return false;
	}

	#ifdef LOG_FWK_ENABLED
	position = 0;
	for (;position<event_queue.length; position++)
	{
		timer_event *temp_event = (timer_event*) queue_read_value(&event_queue, position, sizeof(timer_event));
		log_print_stack_string(LOG_FWK, "Queue: %d.%d", temp_event->next_event/1000, temp_event->next_event%1000);
	}
	current_timer = hal_timer_getvalue();
	log_print_stack_string(LOG_FWK, "timer_insert E - Timer current value: %d.%d", current_timer/1000, current_timer%1000);
	#endif
	/*
	// code when timer was up instead of continous
    int16_t sum_next_event = - hal_timer_getvalue();

    while (position < event_queue.length)
    {
        timer_event *temp_event = (timer_event*) queue_read_value(&event_queue, position, sizeof(timer_event));
        if (event->next_event > sum_next_event + temp_event->next_event)
        {
            sum_next_event += temp_event->next_event;
        } else {
            uint16_t elapsed = 0;
            if (position == 0)
            {
                elapsed = hal_timer_getvalue();
                hal_timer_disable_interrupt();
                started = false;
            } else {
                event->next_event -= sum_next_event;
            }

            queue_insert_value(&event_queue, (void*) event, position, sizeof(timer_event));
            temp_event = (timer_event*) queue_read_value(&event_queue, position+1, sizeof(timer_event));

            temp_event->next_event -= (event->next_event + elapsed);
            return true;
        }
        position++;
    }

    if (position == event_queue.length)
    {
        if (started) event->next_event -= sum_next_event;
        return queue_push_value(&event_queue, (void*) event, sizeof(timer_event));
    }
    */

    return true;
}
void nwl_build_network_protocol_data(uint8_t control, nwl_security* security, nwl_full_access_template* source_access, uint8_t* target_address, uint8_t target_address_lenght, uint8_t subnet, uint8_t spectrum_id[2], int8_t tx_eirp)
{
	uint8_t access_tmpl_length = 0;

	dll_tx_cfg_t dll_params;
	dll_params.eirp = tx_eirp;
	memcpy(dll_params.spectrum_id, spectrum_id, 2);
	dll_params.subnet = subnet;
	dll_params.frame_type = FrameTypeForegroundFrame;

	if ((security != NULL) || (control & NWL_CONTRL_NLS))
	{
		#ifdef LOG_NWL_ENABLED
		log_print_stack_string(LOG_NWL, "NWL: security not implemented");
		#endif
	}

	if (control & NWL_CONTRL_CFG(0x0F))
	{
		#ifdef LOG_NWL_ENABLED
		log_print_stack_string(LOG_NWL, "NWL: Routing not implemented");
		#endif
	}

	switch(control & NWL_CONTRL_SRC_FULL)
	{
		case NWL_CONTRL_SRC_VID:
			access_tmpl_length = 2;
			break;
		case NWL_CONTRL_SRC_UID:
			access_tmpl_length = 8;
			break;
		case NWL_CONTRL_SRC_FULL:
		{
			nwl_full_access_template* access = (nwl_full_access_template*) source_access;
			if (access->control & NWL_ACCESS_TEMPL_CTRL_VID)
				access_tmpl_length = 4;https://www.overleaf.com/2672884dbgqvv#/7082699/
			else
				access_tmpl_length = 10;

			access_tmpl_length += (access->control & 0x0F);
			break;
		}
	}

	queue_create_header_space(&tx_queue, 1 + access_tmpl_length);

	tx_queue.front[0] = control;

	switch(control & NWL_CONTRL_SRC_FULL)
	{
		case NWL_CONTRL_SRC_VID:
			memcpy(&tx_queue.front[1], virtual_id, access_tmpl_length);
			break;
		case NWL_CONTRL_SRC_UID:
			memcpy(&tx_queue.front[1], device_id, access_tmpl_length);
			break;
		case NWL_CONTRL_SRC_FULL:
		{
			memcpy(&tx_queue.front[1], source_access, access_tmpl_length);
			break;
		}
	}


	dll_create_frame(target_address, target_address_lenght, &dll_params);
}
Beispiel #14
0
static void rx_callback(phy_rx_data_t* res)
{
	//log_packet(res->data);
	if (res == NULL)
	{
		scan_timeout();
		return;
	}

	// Data Link Filtering
	// Subnet Matching do not parse it yet
	if (dll_state == DllStateScanBackgroundFrame)
	{
		uint16_t crc = crc_calculate(res->data, 4);
		if (memcmp((uint8_t*) &(res->data[4]), (uint8_t*) &crc, 2) != 0)
		{
			#ifdef LOG_DLL_ENABLED
				log_print_stack_string(LOG_DLL, "DLL CRC ERROR");
			#endif
			scan_next(NULL); // how to reïnitiate scan on CRC Error, PHY should stay in RX
			return;
		}

		if (!check_subnet(0xFF, res->data[0])) // TODO: get device_subnet from datastore
		{
			#ifdef LOG_DLL_ENABLED
				log_print_stack_string(LOG_DLL, "DLL Subnet mismatch");
			#endif
			scan_next(NULL); // how to reïnitiate scan on subnet mismatch, PHY should stay in RX
			return;
		}
	} else if (dll_state == DllStateScanForegroundFrame)
	{
		uint16_t crc = crc_calculate(res->data, res->length - 2);
		if (memcmp((uint8_t*) &(res->data[res->length - 2]), (uint8_t*) &crc, 2) != 0)
		{
			#ifdef LOG_DLL_ENABLED
				log_print_stack_string(LOG_DLL, "DLL CRC ERROR");
			#endif
			scan_next(NULL); // how to reïnitiate scan on CRC Error, PHY should stay in RX
			return;
		}
		if (!check_subnet(0xFF, res->data[2])) // TODO: get device_subnet from datastore
		{
			#ifdef LOG_DLL_ENABLED
				log_print_stack_string(LOG_DLL, "DLL Subnet mismatch");
			#endif
				scan_next(NULL); // how to reïnitiate scan on subnet mismatch, PHY should stay in RX

			return;
		}
	} else
	{
		#ifdef LOG_DLL_ENABLED
			log_print_stack_string(LOG_DLL, "DLL You fool, you can't be here");
		#endif
	}

	// Optional Link Quality Assessment

	// parse packet
	dll_res.rssi = res->rssi;
	dll_res.lqi = res->lqi;
	dll_res.spectrum_id = current_css->values[current_scan_id].spectrum_id;

	if (dll_state == DllStateScanBackgroundFrame)
	{
		dll_background_frame_t* frame = (dll_background_frame_t*)frame_data;
		frame->subnet = res->data[0];
		memcpy(frame->payload, res->data+1, 4);

		dll_res.frame_type = FrameTypeBackgroundFrame;
		dll_res.frame = frame;
	}
	else
	{
		dll_foreground_frame_t* frame = (dll_foreground_frame_t*)frame_data;
		frame->length = res->data[0];

		frame->frame_header.tx_eirp = res->data[1] * 0.5 - 40;
		frame->frame_header.subnet = res->data[2];
		frame->frame_header.frame_ctl = res->data[3];

		uint8_t* data_pointer = res->data + 4;

		if (frame->frame_header.frame_ctl & FRAME_CTL_LISTEN) // Listen
			timeout_listen = 10;
		else
			timeout_listen = 0;

		if (frame->frame_header.frame_ctl & FRAME_CTL_DLLS) // DLLS present
		{
			// TODO parse DLLS Header
			frame->dlls_header = NULL;
		} else {
			frame->dlls_header = NULL;
		}

		if (frame->frame_header.frame_ctl & 0x20) // Enable Addressing
		{
			// Address Control Header
			dll_foreground_frame_address_ctl_t address_ctl;// = (dll_foreground_frame_address_ctl_t*) data_pointer;
			frame->address_ctl = &address_ctl;
			frame->address_ctl->dialogId = *data_pointer;
			data_pointer++;
			frame->address_ctl->flags = *data_pointer;
			data_pointer++;
			//data_pointer += sizeof(uint8_t*);

			uint8_t addressing = (frame->address_ctl->flags & 0xC0) >> 6;
			uint8_t vid = (frame->address_ctl->flags & 0x20) >> 5;
			uint8_t nls = (frame->address_ctl->flags & 0x10) >> 4;
			// TODO parse Source ID Header

			frame->address_ctl->source_id = data_pointer;
			if (vid)
			{
				data_pointer += 2;
			}
			else
			{
				data_pointer += 8;
			}

			if (addressing == 0 && nls == 0)
			{
				uint8_t id_target[8];
				if (vid)
				{
					memcpy(data_pointer, &id_target, 2);
					data_pointer += 2;
				}
				else
				{
					memcpy(data_pointer, &id_target, 8);
					data_pointer += 8;
				}
				frame->address_ctl->target_id = (uint8_t*) &id_target;
			} else {
				frame->address_ctl->target_id = NULL;
			}
		} else {