Hi Crossroads. OK. I' posting the entire program below.
You can see the PROGMEM arrays near the top & they are used in the synthesis engine near the bottom. In the wave update stage and in the interrupt. Oh, I have to say I'm using an XAduino board which uses an ATXMEGA128a3 and Arduino 1.0.1 which has been modified for the XMEGA. ![]()
I'vec missed out the MIDI part of the code to shorten the length so it fits. It doesn't have to do with PROGMEM calls anyway..
Hope someone can help.
![]()
//Modification of GordonJCP's FMTOY to work on XMEGA128a3.
// Uses on board DAC as opposed to PWM.
//Controlled by Bluetooth through Serial port 0 from an Android tablet.
//Thanks to Erik.T (AVR_Freaks) for the advice on using the DAC.
#include<avr/io.h>
#include<avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdint.h>
#include <avr/wdt.h>
//#define SERIAL
// table of 256 sine values / one sine period / stored in flash memory
PROGMEM byte sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
PROGMEM byte sine256_2[] = {
0, 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, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, };
int main(void)
{
setup2();
initialization();
while(1){
// st=0x90;p1=69;p2=125;
byte note = 60;
byte note2=60;
while(Serial.available()<=12) {
}
// update the voices
phaccu_lfo += tword_lfo;
lfo_icnt = phaccu_lfo >> 8;
lfo = (pgm_read_byte(sine256+lfo_icnt)-127)/128.0f;
eg1 = eg1_rate_level[eg1_phase] + eg1_rate[eg1_phase] * eg1;
if (!eg1_phase && eg1 > 0.98) eg1_phase=1;
eg2 = eg2_rate_level[eg2_phase] + eg2_rate[eg2_phase] * eg2;
if (!eg2_phase && eg2 > 0.98) eg2_phase=1;
gain1 = (current.op1_gain<<1) + (eg1 * ((current.op1_env-64)<<1));// + keyfollow ;
if (gain1 < 0) gain1 = 0;
gain2 = (current.op2_env<<1)*eg2;
dfreq=tfreq;
tword_m1 = pow(2,32)*((dfreq* current.op1_ratio)/2 * (1+(lfo*current.op1_lfo)/256.0))/refclk;
tword_m2 = pow(2,32)*((dfreq* current.op2_ratio)/2 * (1+(lfo*current.op2_lfo)/256.0))/refclk;
phaccu_lfoB += tword_lfoB;
lfo_icntB = phaccu_lfoB >> 8;
lfoB = (pgm_read_byte_near(sine256_2+lfo_icntB)-127)/128.0f;
// lfoB = (pgm_read_byte_near(saw256+lfo_icntB)-127)/128.0f;
eg3 = eg3_rate_level[eg3_phase] + eg3_rate[eg3_phase] * eg3;
if (!eg3_phase && eg3 > 0.98) eg3_phase=1;
eg4 = eg4_rate_level[eg4_phase] + eg4_rate[eg4_phase] * eg4;
if (!eg4_phase && eg4 > 0.98) eg4_phase=1;
gain1B = (current2.op3_gain<<1) + (eg3 * ((current2.op3_env-64)<<1));// + keyfollow ;
if (gain1B < 0) gain1B = 0;
gain2B = (current2.op4_env<<1)*eg4;
//dfreq = portamento*tfreq+(1-portamento)*dfreq;
dfreq2=tfreq2;
tword_m1B = pow(2,32)*((dfreq2* current2.op3_ratio)/2 * (1+(lfoB*current2.op3_lfo)/256.0))/refclk;
tword_m2B = pow(2,32)*((dfreq2* current2.op4_ratio)/2 * (1+(lfoB*current2.op4_lfo)/256.0))/refclk;
//} THIS ONE!!!!
}
}
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
// Serial timer interrupt
//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
volatile int out,out2;
ISR ( TCC0_OVF_vect ) {
// internal timer
if(icnt1++ > 31) { // slightly faster than 1ms
do_update=1;
icnt1=0;
}
// operator 1
phaccu1=phaccu1+tword_m1;
icnt=phaccu1 >> 24;
y1 = pgm_read_byte_near(sine256 + ((icnt+fb1) % 256));
fb1 = fb*(y1 + fb1) >> 8;
// operator 2
phaccu2=phaccu2+tword_m2;
icnt=phaccu2 >> 24;
//fb2 = gain1*(y1) >> 8-(gain1>>1);
y2 = pgm_read_byte_near(sine256 + ((icnt+fb2)%256));
fb2 = ((gain1*y1)>>6)-(gain1>>1);
// operator 3
phaccu1B=phaccu1B+tword_m1B;
icntB=phaccu1B >> 24;
y1B = pgm_read_byte_near(sine256_2 + ((icntB+fb1B) % 256));
fb1B = fbB*(y1B + fb1B) >> 8;
// operator 4
phaccu2B=phaccu2B+tword_m2B;
icntB=phaccu2B >> 24;
//fb2 = gain1*(y1) >> 8-(gain1>>1);
fb2B = ((gain1B*y1B)>>6)-(gain1B>>1);
y2B = pgm_read_byte_near(sine256_2 + ((icntB+fb2B)%256));
// set the PWM
out = ((gain2*y2)>>8)-(gain2>>1);
out2 = ((gain2B*y2B)>>8)-(gain2B>>1);
// DC restore and clip output
out += 127;
out >>=1;
if (out<0) out=0;
if (out>0xff) out = 0xff;
out2 += 127;
out2 >>=1;
if (out2<0) out2=0;
if (out2>0xff) out2 = 0xff;
DACB.CH0DATA=(out<<4);
DACB.CH1DATA=(out2<<4);
}