Files @ a74fad632352
Branch filter:

Location: seniordesign-firmware/master/master/lib/ax25.c

ethanzonca@CL-ENS241-08.cedarville.edu
Added licensing information
/*
 * Master Firmware: AX25 Protocol
 *
 * This file is part of OpenTrack.
 *
 * OpenTrack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * OpenTrack is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OpenTrack. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Ethan Zonca
 * Matthew Kanning
 * Kyle Ripperger
 * Matthew Kroening
 *
 * Used under the GPL from the Trackuino project
 */

#include <inttypes.h>
#include "../config.h"
#include "ax25.h"
#include "afsk.h"

// Module globals
static uint16_t crc;
static uint8_t ones_in_a_row;
static uint8_t packet[MAX_PACKET_LEN];
static unsigned int packet_size;

// Module functions
void update_crc(uint8_t a_bit)
{
	crc ^= a_bit;
	if (crc & 1)
	crc = (crc >> 1) ^ 0x8408;  // X-modem CRC poly
	else
	crc = crc >> 1;
}

void send_byte(uint8_t a_byte)
{
	uint8_t i = 0;
	while (i++ < 8) 
	{
		uint8_t a_bit = a_byte & 1;
		a_byte >>= 1;
		update_crc(a_bit);
		if (a_bit) 
		{
			// Next bit is a '1'
			if (packet_size >= MAX_PACKET_LEN * 8)  // Prevent buffer overrun
			return;
			packet[packet_size >> 3] |= (1 << (packet_size & 7));
			packet_size++;
			if (++ones_in_a_row < 5) continue;
		}
		// Next bit is a '0' or a zero padding after 5 ones in a row
		if (packet_size >= MAX_PACKET_LEN * 8)    // Prevent buffer overrun
		return;
		packet[packet_size >> 3] &= ~(1 << (packet_size & 7));
		packet_size++;
		ones_in_a_row = 0;
	}
}

// Exported functions
void ax25_send_byte(uint8_t a_byte)
{
	// Wrap around send_byte, but prints debug info
	send_byte(a_byte);
}

void ax25_send_flag()
{
	uint8_t flag = 0x7e;
	int i;
	for (i = 0; i < 8; i++, packet_size++) 
	{
		if (packet_size >= MAX_PACKET_LEN * 8)  // Prevent buffer overrun
		return;
		if ((flag >> i) & 1)
		packet[packet_size >> 3] |= (1 << (packet_size & 7));
		else
		packet[packet_size >> 3] &= ~(1 << (packet_size & 7));
	}
}

void ax25_send_string(const char *string)
{
	int i;
	for (i = 0; string[i]; i++) 
	{
		ax25_send_byte(string[i]);
	}
}

void ax25_send_header(const struct s_address *addresses, int num_addresses)
{
	int i, j;
	packet_size = 0;
	ones_in_a_row = 0;
	crc = 0xffff;
	
	// Send flags during TX_DELAY milliseconds (8 bit-flag = 8000/1200 ms)
	for (i = 0; i < TX_DELAY * 3 / 20; i++) 
	{
		ax25_send_flag();
	}
	
	for (i = 0; i < num_addresses; i++) 
	{
		// Transmit callsign
		for (j = 0; addresses[i].callsign[j]; j++)
		send_byte(addresses[i].callsign[j] << 1);
		// Transmit pad
		for ( ; j < 6; j++)
		send_byte(' ' << 1);
		// Transmit SSID. Termination signaled with last bit = 1
		if (i == num_addresses - 1)
		send_byte(('0' + addresses[i].ssid) << 1 | 1);
		else
		send_byte(('0' + addresses[i].ssid) << 1);
	}
	
	// Control field: 3 = APRS-UI frame
	send_byte(0x03);
	
	// Protocol ID: 0xf0 = no layer 3 data
	send_byte(0xf0);
}

void ax25_send_footer()
{
	// Save the crc so that it can be treated it atomically
	uint16_t final_crc = crc;
	
	// Send the CRC
	send_byte(~(final_crc & 0xff));
	final_crc >>= 8;
	send_byte(~(final_crc & 0xff));
	
	// Signal the end of frame
	ax25_send_flag();
}

void ax25_flush_frame()
{
	// Key the transmitter and send the frame
	afsk_send(packet, packet_size);
	afsk_start();
}