Files @ 0e169f68c994
Branch filter:

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

ethanzonca@CL-ENS241-08.cedarville.edu
Added support for UART1, added numerous fixes. Introduction of GPS has caused several difficulties. Lowering baud rate to 4800 has made problems worse, probably change back to 115200 baud and disable serial1 interrupts when AFSK transmitting / logging.
/*
 * Master Firmware: AFSK Generation
 *
 * Wireless Observational Modular Aerial Network
 * 
 * Ethan Zonca
 * Matthew Kanning
 * Kyle Ripperger
 * Matthew Kroening
 *
 */


#include "../config.h"
#include "afsk.h"

#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h> 
#include <util/delay.h>
#include <avr/pgmspace.h>


PROGMEM extern const uint8_t afsk_sine_table[512] = {
  127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 143, 144, 146, 147, 149, 150, 152, 153, 155, 156, 158, 
  159, 161, 163, 164, 166, 167, 168, 170, 171, 173, 174, 176, 177, 179, 180, 182, 183, 184, 186, 187, 188, 
  190, 191, 193, 194, 195, 197, 198, 199, 200, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 
  216, 217, 218, 219, 220, 221, 223, 224, 225, 226, 227, 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 
  236, 237, 238, 239, 239, 240, 241, 242, 242, 243, 244, 244, 245, 245, 246, 247, 247, 248, 248, 249, 249, 
  249, 250, 250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 
  254, 254, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 252, 252, 252, 251, 
  251, 251, 250, 250, 249, 249, 249, 248, 248, 247, 247, 246, 245, 245, 244, 244, 243, 242, 242, 241, 240, 
  239, 239, 238, 237, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 228, 227, 226, 225, 224, 223, 221, 
  220, 219, 218, 217, 216, 215, 214, 213, 211, 210, 209, 208, 207, 205, 204, 203, 202, 200, 199, 198, 197, 
  195, 194, 193, 191, 190, 188, 187, 186, 184, 183, 182, 180, 179, 177, 176, 174, 173, 171, 170, 168, 167, 
  166, 164, 163, 161, 159, 158, 156, 155, 153, 152, 150, 149, 147, 146, 144, 143, 141, 139, 138, 136, 135, 
  133, 132, 130, 129, 127, 125, 124, 122, 121, 119, 118, 116, 115, 113, 111, 110, 108, 107, 105, 104, 102, 
  101,  99,  98,  96,  95,  93,  91,  90,  88,  87,  86,  84,  83,  81,  80,  78,  77,  75,  74,  72,  71, 
   70,  68,  67,  66,  64,  63,  61,  60,  59,  57,  56,  55,  54,  52,  51,  50,  49,  47,  46,  45,  44, 
   43,  41,  40,  39,  38,  37,  36,  35,  34,  33,  31,  30,  29,  28,  27,  26,  26,  25,  24,  23,  22, 
   21,  20,  19,  18,  18,  17,  16,  15,  15,  14,  13,  12,  12,  11,  10,  10,   9,   9,   8,   7,   7, 
    6,   6,   5,   5,   5,   4,   4,   3,   3,   3,   2,   2,   2,   1,   1,   1,   1,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1, 
    2,   2,   2,   3,   3,   3,   4,   4,   5,   5,   5,   6,   6,   7,   7,   8,   9,   9,  10,  10,  11, 
   12,  12,  13,  14,  15,  15,  16,  17,  18,  18,  19,  20,  21,  22,  23,  24,  25,  26,  26,  27,  28, 
   29,  30,  31,  33,  34,  35,  36,  37,  38,  39,  40,  41,  43,  44,  45,  46,  47,  49,  50,  51,  52, 
   54,  55,  56,  57,  59,  60,  61,  63,  64,  66,  67,  68,  70,  71,  72,  74,  75,  77,  78,  80,  81, 
   83,  84,  86,  87,  88,  90,  91,  93,  95,  96,  98,  99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 
  115, 116, 118, 119, 121, 122, 124, 125
};

static inline uint8_t afsk_read_sample(int phase)
{
  return pgm_read_byte_near(afsk_sine_table + phase);
}

volatile uint16_t phase = 10;
volatile uint16_t phasedelta = 3300;
extern const uint16_t TABLE_SIZE = sizeof(afsk_sine_table);

// constants
#define MODEM_CLOCK_RATE F_CPU
#define PLAYBACK_RATE MODEM_CLOCK_RATE / 256  // Fast PWM

#define BAUD_RATE 1200
//#define SAMPLES_PER_BAUD PLAYBACK_RATE / BAUD_RATE // = 36
//#define SAMPLES_PER_BAUD 36
#define SAMPLES_PER_BAUD 36


// phase offset of 1800 gives ~1900 Hz
// phase offset of 3300 gives ~2200 Hz
//#define PHASE_DELTA_1200 1800
//#define PHASE_DELTA_2200 2200
#define PHASE_DELTA_1200 1800
#define PHASE_DELTA_2200 3300


// Module globals
volatile unsigned char current_byte;
volatile unsigned char current_sample_in_baud;    // 1 bit = SAMPLES_PER_BAUD samples
volatile bool go = false;                 

volatile unsigned int packet_pos;                 // Next bit to be sent out

volatile unsigned int afsk_packet_size = 10;
volatile const uint8_t *afsk_packet;

void afsk_ptt_off() 
{
	// turn ptt off
	PORTA &= ~(1<<PA5);
}

void afsk_ptt_on() 
{
	// turn the ptt on... possibly delay based on spec
	PORTA |= (1<<PA5);
	_delay_ms(5); // from datasheet
}

ISR(TIMER2_OVF_vect) 
{
	if (go) {

		// If done sending packet
		if (packet_pos == afsk_packet_size) 
		{
			go = false;         // End of transmission
			afsk_timer_stop();  // Disable modem
			afsk_ptt_off();    // Release PTT
			return; // done
		}

		// If sent SAMPLES_PER_BAUD already, go to the next bit
		if (current_sample_in_baud == 0)  // Load up next bit
		{   
			if ((packet_pos & 7) == 0) // Load up next byte
			{          
				current_byte = afsk_packet[packet_pos >> 3];
			}				
			else 
			{
				current_byte = current_byte / 2;  // ">>1" forces int conversion
			}			
			if ((current_byte & 1) == 0) 
			{
				// Toggle tone (1200 <> 2200)
				phasedelta ^= (PHASE_DELTA_1200 ^ PHASE_DELTA_2200);
			}
		}
	
		phase += phasedelta;
		uint8_t s = afsk_read_sample((phase >> 7) & (TABLE_SIZE - 1));
		afsk_output_sample(s);

		if(++current_sample_in_baud == SAMPLES_PER_BAUD) 
		{
			current_sample_in_baud = 0;
			packet_pos++;
		}
		
	}
}	

void afsk_output_sample(uint8_t s) 
{
	OCR2A = s;
}

void afsk_timer_start()
{
	// Clear the overflow flag, so that the interrupt doesn't go off
	// immediately and overrun the next one (p.163).
	TIFR2 |= _BV(TOV2);       // Yeah, writing a 1 clears the flag.

	// Enable interrupt when TCNT2 reaches TOP (0xFF) (p.151, 163)
	TIMSK2 |= _BV(TOIE2);
}

void afsk_timer_stop()
{
	// Resting duty cycle
	// Output 0v (could be 255/2, which is 0v after coupling... doesn't really matter)
	OCR2A = 0x80;

	// Disable playback interrupt
	TIMSK2 &= ~_BV(TOIE2);
}





// External

void afsk_start()
{
	phasedelta = PHASE_DELTA_1200;
	phase = 0;
	packet_pos = 0;
	current_sample_in_baud = 0;
	go = true;

	// Key the radio
	afsk_ptt_on();

	// Start transmission
	afsk_timer_start();
}

int afsk_busy()
{
	return go;
}

void afsk_send(const uint8_t *buffer, int len)
{
	afsk_packet_size = len;
	afsk_packet = buffer;
}


void afsk_setup() 
{
	
	// Source timer2 from clkIO (datasheet p.164)
	ASSR &= ~(_BV(EXCLK) | _BV(AS2));

	// Set fast PWM mode with TOP = 0xff: WGM22:0 = 3  (p.150)
	TCCR2A |= _BV(WGM21) | _BV(WGM20);
	TCCR2B &= ~_BV(WGM22);

	// Do non-inverting PWM on pin OC2A
	TCCR2A = (TCCR2A | _BV(COM2A1)) & ~(_BV(COM2A0) | _BV(COM2B1) | _BV(COM2B0));

	// No prescaler (p.162)
	TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20);
	
	// Enable interrupt when TCNT2 reaches TOP (0xFF) (p.151, 163)
	//TIMSK2 |= _BV(TOIE2);
	TIMSK2 |= 0b00000001;
	
	// FIXME TODO
	DDRD = 0xff;
	PORTD = 0xff;
	
	// todo: init radio, maybe in main
	
	
	
	while(afsk_busy());
}