Example #1
0
// ------------------------------------------------------------------------------------------------
// Reception test with interrupt handling
int radio_receive_test_int(spi_parms_t *spi_parms, arguments_t *arguments)
// ------------------------------------------------------------------------------------------------
{
    uint8_t nb_rx, rx_bytes[RADIO_BUFSIZE];

    init_radio_int(spi_parms, arguments);
    PI_CC_SPIStrobe(spi_parms, PI_CCxxx0_SFRX); // Flush Rx FIFO

    verbprintf(0, "Starting...\n");

    while((arguments->repetition == 0) || (packets_received < arguments->repetition))
    {
        radio_init_rx(spi_parms, arguments); // Init for new packet to receive
        radio_turn_rx(spi_parms);            // Put back into Rx

        do
        {
            radio_wait_free(); // make sure no radio operation is in progress
            nb_rx = radio_receive_packet(spi_parms, arguments, rx_bytes);
        } while(nb_rx == 0);

        rx_bytes[nb_rx] = '\0';
        verbprintf(0,"\"%s\"\n", rx_bytes);
    }
}
Example #2
0
// ------------------------------------------------------------------------------------------------
// Simple echo test
void radio_test_echo(spi_parms_t *spi_parms, radio_parms_t *radio_parms, arguments_t *arguments, uint8_t active)
// ------------------------------------------------------------------------------------------------
{
    uint8_t  nb_bytes, rtx_bytes[RADIO_BUFSIZE];
    uint8_t  rtx_toggle, rtx_count;
    uint32_t timeout_value, timeout;
    struct timeval tdelay, tstart, tstop;

    init_radio_int(spi_parms, arguments);
    radio_flush_fifos(spi_parms);

    timeout_value = (uint32_t) (arguments->packet_length * 10 * radio_get_byte_time(radio_parms));
    timeout = 0;

    if (active)
    {
        nb_bytes = strlen(arguments->test_phrase);
        strcpy(rtx_bytes, arguments->test_phrase);
        rtx_toggle = 1;
    }
    else
    {
        rtx_toggle = 0;
    }

    while (packets_sent < arguments->repetition)
    {
        rtx_count = 0;

        do // Rx-Tx transaction in whichever order
        {
            if (arguments->tnc_keyup_delay)
            {
                usleep(arguments->tnc_keyup_delay);
            }

            if (rtx_toggle) // Tx
            {
                verbprintf(0, "Sending #%d\n", packets_sent);

                radio_wait_free(); // make sure no radio operation is in progress
                radio_send_packet(spi_parms, arguments, rtx_bytes, nb_bytes);
                radio_wait_a_bit(4);
                timeout = timeout_value; // arm Rx timeout
                rtx_count++;
                rtx_toggle = 0; // next is Rx
            }

            if (rtx_count >= 2)
            {
                break;
            }

            if (arguments->tnc_keydown_delay)
            {
                usleep(arguments->tnc_keydown_delay);
            }

            if (!rtx_toggle) // Rx
            {
                verbprintf(0, "Receiving #%d\n", packets_received);

                radio_init_rx(spi_parms, arguments); // Init for new packet to receive
                radio_turn_rx(spi_parms);            // Put back into Rx

                if (timeout > 0)
                {
                    gettimeofday(&tstart, NULL);
                }

                do
                {
                    radio_wait_free(); // make sure no radio operation is in progress
                    nb_bytes = radio_receive_packet(spi_parms, arguments, rtx_bytes);
                    radio_wait_a_bit(4);

                    if (timeout > 0)
                    {
                        gettimeofday(&tstop, NULL);
                        timeval_subtract(&tdelay, &tstop, &tstart);

                        if (ts_us(&tdelay) > timeout)
                        {
                            verbprintf(0, "Time out reached. Faking receiving data\n");
                            nb_bytes = strlen(arguments->test_phrase);
                            strcpy(rtx_bytes, arguments->test_phrase);
                            break;
                        }
                    }

                } while (nb_bytes == 0);

                rtx_count++;
                rtx_toggle = 1; // next is Tx
            }

        } while(rtx_count < 2);
    }
}
Example #3
0
File: tdm.c Project: gfornax/SiK
/// main loop for time division multiplexing transparent serial
///
void
tdm_serial_loop(void)
{
	__pdata uint16_t last_t = timer2_tick();
	__pdata uint16_t last_link_update = last_t;

	_canary = 42;

	for (;;) {
		__pdata uint8_t	len;
		__pdata uint16_t tnow, tdelta;
		__pdata uint8_t max_xmit;

		if (_canary != 42) {
			panic("stack blown\n");
		}

		if (pdata_canary != 0x41) {
			panic("pdata canary changed\n");
		}

		// give the AT command processor a chance to handle a command
		at_command();

		// display test data if needed
		if (test_display) {
			display_test_output();
			test_display = 0;
		}

		if (seen_mavlink && feature_mavlink_framing && !at_mode_active) {
			seen_mavlink = false;
			MAVLink_report();
		}

		// set right receive channel
		radio_set_channel(fhop_receive_channel());

		// get the time before we check for a packet coming in
		tnow = timer2_tick();

		// see if we have received a packet
		if (radio_receive_packet(&len, pbuf)) {

			// update the activity indication
			received_packet = true;
			fhop_set_locked(true);
			
			// update filtered RSSI value and packet stats
			statistics.average_rssi = (radio_last_rssi() + 7*(uint16_t)statistics.average_rssi)/8;
			statistics.receive_count++;
			
			// we're not waiting for a preamble
			// any more
			transmit_wait = 0;

			if (len < 2) {
				// not a valid packet. We always send
				// two control bytes at the end of every packet
				continue;
			}

			// extract control bytes from end of packet
			memcpy(&trailer, &pbuf[len-sizeof(trailer)], sizeof(trailer));
			len -= sizeof(trailer);

			if (trailer.window == 0 && len != 0) {
				// its a control packet
				if (len == sizeof(struct statistics)) {
					memcpy(&remote_statistics, pbuf, len);
				}

				// don't count control packets in the stats
				statistics.receive_count--;
			} else if (trailer.window != 0) {
				// sync our transmit windows based on
				// received header
				sync_tx_windows(len);
				last_t = tnow;

				if (trailer.command == 1) {
					handle_at_command(len);
				} else if (len != 0 && 
					   !packet_is_duplicate(len, pbuf, trailer.resend) &&
					   !at_mode_active) {
					// its user data - send it out
					// the serial port
					//printf("rcv(%d,[", len);
					LED_ACTIVITY = LED_ON;
					serial_write_buf(pbuf, len);
					LED_ACTIVITY = LED_OFF;
					//printf("]\n");
				}
			}
			continue;
		}

		// see how many 16usec ticks have passed and update
		// the tdm state machine. We re-fetch tnow as a bad
		// packet could have cost us a lot of time.
		tnow = timer2_tick();
		tdelta = tnow - last_t;
		tdm_state_update(tdelta);
		last_t = tnow;

		// update link status every 0.5s
		if (tnow - last_link_update > 32768) {
			link_update();
			last_link_update = tnow;
		}

		if (lbt_rssi != 0) {
			// implement listen before talk
			if (radio_current_rssi() < lbt_rssi) {
				lbt_listen_time += tdelta;
			} else {
				lbt_listen_time = 0;
				if (lbt_rand == 0) {
					lbt_rand = ((uint16_t)rand()) % lbt_min_time;
				}
			}
			if (lbt_listen_time < lbt_min_time + lbt_rand) {
				// we need to listen some more
				continue;
			}
		}

		// we are allowed to transmit in our transmit window
		// or in the other radios transmit window if we have
		// bonus ticks
#if USE_TICK_YIELD
		if (tdm_state != TDM_TRANSMIT &&
		    !(bonus_transmit && tdm_state == TDM_RECEIVE)) {
			// we cannot transmit now
			continue;
		}
#else
		if (tdm_state != TDM_TRANSMIT) {
			continue;
		}		
#endif

		if (transmit_yield != 0) {
			// we've give up our window
			continue;
		}

		if (transmit_wait != 0) {
			// we're waiting for a preamble to turn into a packet
			continue;
		}

		if (!received_packet &&
		    radio_preamble_detected() ||
		    radio_receive_in_progress()) {
			// a preamble has been detected. Don't
			// transmit for a while
			transmit_wait = packet_latency;
			continue;
		}

		// sample the background noise when it is out turn to
		// transmit, but we are not transmitting,
		// averaged over around 4 samples
		statistics.average_noise = (radio_current_rssi() + 3*(uint16_t)statistics.average_noise)/4;

		if (duty_cycle_wait) {
			// we're waiting for our duty cycle to drop
			continue;
		}

		// how many bytes could we transmit in the time we
		// have left?
		if (tdm_state_remaining < packet_latency) {
			// none ....
			continue;
		}
		max_xmit = (tdm_state_remaining - packet_latency) / ticks_per_byte;
		if (max_xmit < PACKET_OVERHEAD) {
			// can't fit the trailer in with a byte to spare
			continue;
		}
		max_xmit -= PACKET_OVERHEAD;
		if (max_xmit > max_data_packet_length) {
			max_xmit = max_data_packet_length;
		}

		// ask the packet system for the next packet to send
		if (send_at_command && 
		    max_xmit >= strlen(remote_at_cmd)) {
			// send a remote AT command
			len = strlen(remote_at_cmd);
			memcpy(pbuf, remote_at_cmd, len);
			trailer.command = 1;
			send_at_command = false;
		} else {
			// get a packet from the serial port
			memset(pbuf, 0x40, 16);
			len = packet_get_next(max_xmit-16, pbuf+16) + 16;
			trailer.command = packet_is_injected();
			if (len == 16)
				len = 0;
		}

		if (len > max_data_packet_length) {
			panic("oversized tdm packet");
		}

		trailer.bonus = (tdm_state == TDM_RECEIVE);
		trailer.resend = packet_is_resend();

		if (tdm_state == TDM_TRANSMIT &&
		    len == 0 && 
		    send_statistics && 
		    max_xmit >= sizeof(statistics)) {
			// send a statistics packet
			send_statistics = 0;
			memcpy(pbuf, &statistics, sizeof(statistics));
			len = sizeof(statistics);
		
			// mark a stats packet with a zero window
			trailer.window = 0;
			trailer.resend = 0;
		} else {
			// calculate the control word as the number of
			// 16usec ticks that will be left in this
			// tdm state after this packet is transmitted
			trailer.window = (uint16_t)(tdm_state_remaining - flight_time_estimate(len+sizeof(trailer)));
		}

		// set right transmit channel
		radio_set_channel(fhop_transmit_channel());

		memcpy(&pbuf[len], &trailer, sizeof(trailer));

		if (len != 0 && trailer.window != 0) {
			// show the user that we're sending real data
			LED_ACTIVITY = LED_ON;
		}

		if (len == 0) {
			// sending a zero byte packet gives up
			// our window, but doesn't change the
			// start of the next window
			transmit_yield = 1;
		}

		// after sending a packet leave a bit of time before
		// sending the next one. The receivers don't cope well
		// with back to back packets
		transmit_wait = packet_latency;

		// if we're implementing a duty cycle, add the
		// transmit time to the number of ticks we've been transmitting
		if ((duty_cycle - duty_cycle_offset) != 100) {
			transmitted_ticks += flight_time_estimate(len+sizeof(trailer));
		}

		// start transmitting the packet
		if (!radio_transmit(len + sizeof(trailer), pbuf, tdm_state_remaining + (silence_period/2)) &&
		    len != 0 && trailer.window != 0 && trailer.command == 0) {
			packet_force_resend();
		}

		if (lbt_rssi != 0) {
			// reset the LBT listen time
			lbt_listen_time = 0;
			lbt_rand = 0;
		}

		// set right receive channel
		radio_set_channel(fhop_receive_channel());

		// re-enable the receiver
		radio_receiver_on();

		if (len != 0 && trailer.window != 0) {
			LED_ACTIVITY = LED_OFF;
		}
	}
}
Example #4
0
// ------------------------------------------------------------------------------------------------
// Run the KISS virtual TNC
void kiss_run(serial_t *serial_parms, spi_parms_t *spi_parms, arguments_t *arguments)
// ------------------------------------------------------------------------------------------------
{
    static const size_t   bufsize = RADIO_BUFSIZE;
    uint32_t timeout_value;
    uint8_t  rx_buffer[bufsize], tx_buffer[bufsize];
    uint8_t  rtx_toggle; // 1:Tx, 0:Rx
    uint8_t  rx_trigger; 
    uint8_t  tx_trigger; 
    uint8_t  force_mode;
    int      rx_count, tx_count, byte_count, ret;
    uint64_t timestamp;
    struct timeval tp;  

    set_serial_parameters(serial_parms, arguments);
    init_radio_int(spi_parms, arguments);
    memset(rx_buffer, 0, bufsize);
    memset(tx_buffer, 0, bufsize);
    radio_flush_fifos(spi_parms);
    
    verbprintf(1, "Starting...\n");

    force_mode = 1;
    rtx_toggle = 0;
    rx_trigger = 0;
    tx_trigger = 0;
    rx_count = 0;
    tx_count = 0;
    radio_init_rx(spi_parms, arguments); // init for new packet to receive Rx
    radio_turn_rx(spi_parms);            // Turn Rx on

    while(1)
    {    
        byte_count = radio_receive_packet(spi_parms, arguments, &rx_buffer[rx_count]); // check if anything was received on radio link

        if (byte_count > 0)
        {
            rx_count += byte_count;  // Accumulate Rx
            
            gettimeofday(&tp, NULL);
            timestamp = tp.tv_sec * 1000000ULL + tp.tv_usec;
            timeout_value = arguments->tnc_radio_window;
            force_mode = (timeout_value == 0);

            if (rtx_toggle) // Tx to Rx transition
            {
                tx_trigger = 1; // Push Tx
            }
            else
            {
                tx_trigger = 0;
            }

            radio_init_rx(spi_parms, arguments); // Init for new packet to receive
            rtx_toggle = 0;
        }

        byte_count = read_serial(serial_parms, &tx_buffer[tx_count], bufsize - tx_count);

        if (byte_count > 0)
        {
            tx_count += byte_count;  // Accumulate Tx

            gettimeofday(&tp, NULL);
            timestamp = tp.tv_sec * 1000000ULL + tp.tv_usec;
            timeout_value = arguments->tnc_serial_window;
            force_mode = (timeout_value == 0);

            if (!rtx_toggle) // Rx to Tx transition
            {
                rx_trigger = 1;
            }
            else
            {
                rx_trigger = 0;
            }

            rtx_toggle = 1;
        }

        if ((rx_count > 0) && ((rx_trigger) || (force_mode))) // Send bytes received on air to serial
        {
            radio_wait_free();            // Make sure no radio operation is in progress
            radio_turn_idle(spi_parms);   // Inhibit radio operations
            verbprintf(2, "Received %d bytes\n", rx_count);
            ret = write_serial(serial_parms, rx_buffer, rx_count);
            verbprintf(2, "Sent %d bytes on serial\n", ret);
            radio_init_rx(spi_parms, arguments); // Init for new packet to receive Rx
            radio_turn_rx(spi_parms);            // Put back into Rx
            rx_count = 0;
            rx_trigger = 0;
        }

        if ((tx_count > 0) && ((tx_trigger) || (force_mode))) // Send bytes received on serial to air 
        {
            if (!kiss_command(tx_buffer))
            {
                radio_wait_free();            // Make sure no radio operation is in progress
                radio_turn_idle(spi_parms);   // Inhibit radio operations (should be superfluous since both Tx and Rx turn to IDLE after a packet has been processed)
                radio_flush_fifos(spi_parms); // Flush result of any Rx activity

                verbprintf(2, "%d bytes to send\n", tx_count);

                if (tnc_tx_keyup_delay)
                {
                    usleep(tnc_tx_keyup_delay);
                }

                radio_send_packet(spi_parms, arguments, tx_buffer, tx_count);

                radio_init_rx(spi_parms, arguments); // init for new packet to receive Rx
                radio_turn_rx(spi_parms);            // put back into Rx
            }

            tx_count = 0;
            tx_trigger = 0;            
        }

        if (!force_mode)
        {
            gettimeofday(&tp, NULL);

            if ((tp.tv_sec * 1000000ULL + tp.tv_usec) > timestamp + timeout_value)
            {
                force_mode = 1;
            }                        
        }

        radio_wait_a_bit(4);
    }
}