Files
@ 61bd3e3de919
Branch filter:
Location: seniordesign-firmware/master/master/lib/afsk.c
61bd3e3de919
6.7 KiB
text/plain
a few updates for sd card handling
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | /*
* fsk.c
*
* Created: 10/29/2012 7:40:34 PM
* Author: ethanzonca
*/
#define F_CPU 11059200
#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
// 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
}
void afsk_ptt_on() {
// turn the ptt on... possibly delay based on spec
}
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) {
// sounds fun when this is commented out... but why??!?!
current_sample_in_baud = 0;
packet_pos++;
}
}
}
void afsk_output_sample(uint8_t s) {
OCR2B = 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)
OCR2B = 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 OC2B (arduino pin 3) (p.159).
// OC2A (arduino pin 11) stays in normal port operation:
// COM2B1=1, COM2B0=0, COM2A1=0, COM2A0=0
TCCR2A = (TCCR2A | _BV(COM2B1)) & ~(_BV(COM2B0) | _BV(COM2A1) | _BV(COM2A0));
// 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;
// Initialize PORTA
DDRA = 0xff;
PORTA = 0x00;
DDRD = 0xff;
PORTD = 0xff;
// todo: init radio, maybe in main
sei();
}
void afsk_test() {
uint8_t flap[26] = {"abcdefghijklmnopqrstuvwxyz"};
afsk_send(flap, sizeof(flap)*8);
afsk_start();
while(afsk_busy());
_delay_ms(500);
}
|