Created
January 15, 2014 06:00
-
-
Save antonl/8431542 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef cbi | |
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | |
#endif | |
#ifndef sbi | |
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | |
#endif | |
#include <avr/pgmspace.h> | |
unsigned char byte_n = 0; // byte count | |
#define HDR_LEN 10 | |
#define MAX_TUNING_WORD 0x3FFFFFFFul | |
#define ONE_HZ_CORRECTION 3036 | |
#define TBL_LEN 512 | |
#define LED 13 | |
#define PB5 9 | |
unsigned char cmd_header[HDR_LEN]; | |
bool cmd_ready = false; | |
// Generated in python with np.array((np.sin(2*pi*arange(256)/256)+1)*128, int) | |
PROGMEM prog_uint16_t sin_table[TBL_LEN] = | |
{2048,2073,2098,2123,2148,2173,2198,2223,2248,2273,2298,2323,2348,2373,2398, | |
2422,2447,2472,2496,2521,2545,2569,2594,2618,2642,2666,2690,2714,2737,2761, | |
2785,2808,2831,2854,2877,2900,2923,2946,2968,2991,3013,3035,3057,3079,3100, | |
3122,3143,3164,3185,3206,3227,3247,3267,3288,3307,3327,3347,3366,3385,3404, | |
3423,3441,3460,3478,3496,3513,3531,3548,3565,3582,3598,3615,3631,3646,3662, | |
3677,3692,3707,3722,3736,3750,3764,3778,3791,3804,3817,3829,3842,3854,3865, | |
3877,3888,3899,3909,3920,3930,3940,3949,3958,3967,3976,3984,3992,4000,4007, | |
4014,4021,4028,4034,4040,4046,4051,4056,4061,4065,4069,4073,4077,4080,4083, | |
4086,4088,4090,4092,4093,4094,4095,4095,4096,4095,4095,4094,4093,4092,4090, | |
4088,4086,4083,4080,4077,4073,4069,4065,4061,4056,4051,4046,4040,4034,4028, | |
4021,4014,4007,4000,3992,3984,3976,3967,3958,3949,3940,3930,3920,3909,3899, | |
3888,3877,3865,3854,3842,3829,3817,3804,3791,3778,3764,3750,3736,3722,3707, | |
3692,3677,3662,3646,3631,3615,3598,3582,3565,3548,3531,3513,3496,3478,3460, | |
3441,3423,3404,3385,3366,3347,3327,3307,3288,3267,3247,3227,3206,3185,3164, | |
3143,3122,3100,3079,3057,3035,3013,2991,2968,2946,2923,2900,2877,2854,2831, | |
2808,2785,2761,2737,2714,2690,2666,2642,2618,2594,2569,2545,2521,2496,2472, | |
2447,2422,2398,2373,2348,2323,2298,2273,2248,2223,2198,2173,2148,2123,2098, | |
2073,2048,2022,1997,1972,1947,1922,1897,1872,1847,1822,1797,1772,1747,1722, | |
1697,1673,1648,1623,1599,1574,1550,1526,1501,1477,1453,1429,1405,1381,1358, | |
1334,1310,1287,1264,1241,1218,1195,1172,1149,1127,1104,1082,1060,1038,1016, | |
995, 973, 952, 931, 910, 889, 868, 848, 828, 807, 788, 768, 748, 729, 710, | |
691, 672, 654, 635, 617, 599, 582, 564, 547, 530, 513, 497, 480, 464, 449, | |
433, 418, 403, 388, 373, 359, 345, 331, 317, 304, 291, 278, 266, 253, 241, | |
230, 218, 207, 196, 186, 175, 165, 155, 146, 137, 128, 119, 111, 103, 95, | |
88, 81, 74, 67, 61, 55, 49, 44, 39, 34, 30, 26, 22, 18, 15, | |
12, 9, 7, 5, 3, 2, 1, 0, 0, 0, 0, 0, 1, 2, 3, | |
5, 7, 9, 12, 15, 18, 22, 26, 30, 34, 39, 44, 49, 55, 61, | |
67, 74, 81, 88, 95, 103, 111, 119, 128, 137, 146, 155, 165, 175, 186, | |
196, 207, 218, 230, 241, 253, 266, 278, 291, 304, 317, 331, 345, 359, 373, | |
388, 403, 418, 433, 449, 464, 480, 497, 513, 530, 547, 564, 582, 599, 617, | |
635, 654, 672, 691, 710, 729, 748, 768, 788, 807, 828, 848, 868, 889, 910, | |
931, 952, 973, 995,1016,1038,1060,1082,1104,1127,1149,1172,1195,1218,1241, | |
1264,1287,1310,1334,1358,1381,1405,1429,1453,1477,1501,1526,1550,1574,1599, | |
1623,1648,1673,1697,1722,1747,1772,1797,1822,1847,1872,1897,1922,1947,1972, | |
1997,2022}; | |
uint16_t memory_table[TBL_LEN]; | |
volatile uint32_t phase = 0ul; | |
volatile uint32_t tuning_word= 100ul; | |
inline void setup_timer1() { | |
noInterrupts(); | |
TCCR1A = 0; | |
TCCR1B = 0; | |
// Set phase and frequency correct pwm mode | |
TCCR1A |= (1<<WGM10) | (1 << COM1A0); // clear on up count | |
TCCR1B |= (1<<WGM13); // Match to OCR1A | |
TCCR1B |= (1<<CS11) | (1<<CS10); | |
OCR1A = memory_table[phase >> 23]; // Take the top 9 bits | |
TIMSK1 |= (1<<OCIE1A) | (1<<TOIE1); // Enable timer | |
interrupts(); | |
} | |
void setup() { | |
pinMode(LED, OUTPUT); | |
pinMode(9, OUTPUT); | |
TIMSK0 &= (1 << TOIE0); | |
setup_timer1(); // reference clock for DDS | |
Serial.begin(115200ul); | |
} | |
inline void load_sin() { | |
noInterrupts(); | |
memcpy_P(memory_table, sin_table, TBL_LEN*sizeof(uint16_t)); | |
Serial.println('K'); | |
interrupts(); | |
} | |
inline void set_freq() { | |
uint32_t a = 0, b = 0; | |
b = cmd_header[1]; | |
a |= b << 24; | |
b = cmd_header[2]; | |
a |= b << 16; | |
b = cmd_header[3]; | |
a |= b << 8; | |
b = cmd_header[4]; | |
a |= b; | |
if(a > MAX_TUNING_WORD) { | |
Serial.println('X'); | |
} else { | |
noInterrupts(); | |
tuning_word = a; | |
interrupts(); | |
Serial.println('K'); | |
} | |
} | |
inline void read_freq() { | |
Serial.print(tuning_word); | |
Serial.println('K'); | |
} | |
inline void read_pts() { | |
for(int i=0; i < TBL_LEN; ++i) { | |
Serial.print(memory_table[i]); | |
Serial.print(','); | |
} | |
Serial.println('K'); | |
} | |
inline void debug() { | |
Serial.print('P'); | |
Serial.print(phase); | |
Serial.print(",O"); | |
Serial.print(OCR1A); | |
Serial.print(",T"); | |
Serial.print(TBL_LEN); | |
Serial.print(",S"); | |
Serial.print(sizeof(unsigned long)); | |
Serial.print(",N"); | |
Serial.print(phase >> 23); | |
Serial.print(",mem"); | |
Serial.print(memory_table[phase >> 23]); | |
Serial.println('K'); | |
} | |
void loop() { | |
if(cmd_ready) { | |
noInterrupts(); | |
switch(cmd_header[0]) { | |
case 'S': load_sin(); break; // load sin table | |
case 'F': set_freq(); break; // set frequency | |
case 'f': read_freq(); break;// read frequency | |
case 'p': read_pts(); break; // number of points | |
case 'd': debug(); break; // debug | |
default: Serial.println('X'); | |
} | |
memset(cmd_header, 0, HDR_LEN); | |
cmd_ready = false; | |
byte_n = 0; | |
interrupts(); | |
} else { | |
while (Serial.available()) { | |
// get the new byte: | |
cmd_header[byte_n] = (char)Serial.read(); | |
// if the incoming character is a newline, set a flag | |
// so the main loop can do something about it: | |
if (cmd_header[byte_n] == '\n') { | |
cmd_ready = true; | |
byte_n = 0; | |
} | |
++byte_n; | |
if(byte_n > HDR_LEN) { | |
byte_n = 0; | |
cmd_ready = false; | |
memset(cmd_header, 0, HDR_LEN); | |
} | |
} | |
} | |
} | |
ISR(TIMER1_COMPA_vect) { | |
} | |
ISR(TIMER1_OVF_vect) { | |
phase += tuning_word; | |
OCR1A = memory_table[phase >> 23]; // Take the top 9 bits | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment