#include #include //macro definitions #define AVERAGE4(a,b,c,d) ((unsigned char)((((int)(a))+((int)(b))+((int)(c))+((int)(d)))>>2)) #define COUNT2X(a) ((unsigned char)((255.0/((float)(xindextable[8]-xindextable[0])))*((float)(a-xindextable[0])))) #define COUNT2Y(a) ((unsigned char)((255.0/((float)(yindextable[7]-yindextable[0])))*((float)(a-yindextable[0])))) #define COUNTMS 62 //62.5 ticks per ms //border index reference table flash unsigned char xindextable[9] = {73,88,103,119,134,147,163,177,193}; flash unsigned char yindextable[8] = {71,96,110,126,142,158,172,184}; //DDS tone frequency reference table C 3 C#/Db 3 D 3 D#/Eb 3 E 3 // F 3 F#/Db 3 G 3 G#/Ab 3 A 3 // A#/Bb 3 B 3 (middle)C 4 C#/Db 4 D 4 // D#/Eb 4 E 4 F 4 F#/Db 4 G 4 // G#/Ab 4 (440) A 4 A#/Bb 4 B 4 C 5 flash unsigned long freqtable[25] = { 0x892AC9, 0x9152D2, 0x99F704, 0xA31EC1, 0xACD1DC, 0xB7189E, 0xC1FBCF, 0xCD84BC, 0xD9BD40, 0xE6AFCC, 0xF46770, 0x102EFE5, 0x1125593, 0x122A5A5, 0x133EE09, 0x1463D83, 0x159A3B9, 0x16E313D, 0x183F79F, 0x19B0979, 0x1B37A81, 0x1CD5F99, 0x1E8CEE1, 0x205DFCA, 0x224AB27}; //beat mask reference table flash unsigned char masktable[4] = {0b00001000, 0b00000100, 0b00000010, 0b00000001}; //BPM reference table flash unsigned char bpmtable[25] = { 75, 79, 83, 87, 92, 96,101,107,112,118, 124,130,137,144,151, 159,167,176,185,195, 205,215,226,238,250}; unsigned char countms, countbpm, count3ms; //timer counters unsigned int i,j; //loop variables //TOUCH unsigned char Ain; //ADC input unsigned char touchindex; //toggle to read x or y unsigned char x, y; //raw x-y coordinates unsigned char xprev, yprev; //previous raw x-y coordinates for debouncing unsigned char xindex, yindex; //mapped x-y coordinates unsigned char xindexprev, yindexprev; //previous mapped x-y coordinates for debouncing unsigned char indextemp; //even or odd index? //WAVEFORMS unsigned char tempvalue; //interpolation y coordinate unsigned char tempindex; //interpolation x coordinate unsigned char tempx1,tempx2,tempy1,tempy2; //interpolation variables long multx1,multx2,multxn,multy1,multy2; //casted interpolation variables //DDS unsigned long accumulator1 @0x2f0; //long accumulators for calculation accuracy unsigned long accumulator2 @0x2e0; // unsigned long accumulator3 @0x2d0; // unsigned long accumulator4 @0x2c0; // unsigned char highbyte1 @0x2f3; //the HIGH byte of the accumulator variables unsigned char highbyte2 @0x2e3; // unsigned char highbyte3 @0x2d3; // unsigned char highbyte4 @0x2c3; // unsigned char incindex[4]; //stores the increment indices for all waveforms unsigned long increment1; //increment values unsigned long increment2; // unsigned long increment3; // unsigned long increment4; // unsigned char table1[256] @0x400; //stores PWM values for one waveform each unsigned char table2[256] @0x500; //need locations to avoid glitch unsigned char table3[256] @0x600; // unsigned char table4[256] @0x700; // unsigned char tabletemp[256] @0x300; //temporary table for input/interpolation //BEATS unsigned char bpmindex; //stores tempo index unsigned char buttonpress; //operation code for beat modifications unsigned char buttonprev; //previous operation code for debouncing unsigned char mask; //selects which beat to affect char beat, beatstate; //alternating state counters for beats //neccesary for off period between consecutive ibeats char beatflag; //alternatingly increment beat or beatstate unsigned char beattable[16]; //stores values for 16 beats unsigned char beatenable; //enables selective beats //FUNCTION PROTOTYPES void main(void); void parsein(void); void toindex(void); void touchin(void); void playbeat(void); void modbeat(void); void stopbeat(void); void playwave(char c); void pausewave(char c); void stopwave(char c); void recwave(char c); void interpolate(void); void playall(void); void pauseall(void); void stopall(void); void interpol(void); void initialize(void); /////////////////////////////////////////////////////////////////// //decrements counters //gets touch values //DDS operations /////////////////////////////////////////////////////////////////// interrupt [TIM0_OVF] void voicegen(void) { //decrement counters if(countms>0) countms--; if(countms==0) { countms = COUNTMS; if(countbpm>0) countbpm--; if(count3ms>0) count3ms--; //run touchin every 3ms if(count3ms==16 || count3ms==13 || count3ms==10 || count3ms== 7 || count3ms== 4 || count3ms== 1) { touchin(); } } //PWM DDS accumulator1 = accumulator1 + increment1; accumulator2 = accumulator2 + increment2; accumulator3 = accumulator3 + increment3; accumulator4 = accumulator4 + increment4; OCR0 = 255-(AVERAGE4(table1[highbyte1],table2[highbyte2],table3[highbyte3],table4[highbyte4])); } /////////////////////////////////////////////////////////////////// //run everything /////////////////////////////////////////////////////////////////// void main(void) { initialize(); while(1) { //parse input every 13 ms for the sake of debouncing if(count3ms==0) { count3ms = 19; parsein(); } //play beats every ???s if(countbpm==0) { countbpm = bpmtable[bpmindex]; playbeat(); } } } /////////////////////////////////////////////////////////////////// //read in raw coordinates from touchpad /////////////////////////////////////////////////////////////////// void touchin(void) { //ADC comparison Ain = ADCH; ADCSR.6=1; if(touchindex==0) //reading x coordinate { //debounce if(xprev == x) { if(Ain > xindextable[0]) x = Ain; else x = 0; xprev = x; } else xprev = Ain; //set for y reading PORTC.7=0; PORTC.6=1; touchindex = 1; } else //reading y coordinate { //debounce if(yprev == y) { if(Ain > yindextable[0]) y = Ain; else y = 0; yprev = y; } else yprev = Ain; //set for x reading PORTC.7=1; PORTC.6=0; touchindex = 0; } } /////////////////////////////////////////////////////////////////// //call functions depending on button indices /////////////////////////////////////////////////////////////////// void parsein(void) { toindex(); if(xindexprev != xindex || yindexprev != yindex ) { if(yindex == 7) //play-pause row { if(xindex & 0b00000001) playwave(xindex-1>>1); else pausewave(xindex-1>>1); } else if(yindex == 6) //stop-record row { if(xindex & 0b00000001) stopwave(xindex-1>>1); else recwave(xindex-1>>1); } else if(yindex == 5) //frequency row { indextemp = xindex-1>>1; if(xindex & 0b00000001) //decrement frequency index { if(incindex[indextemp] != 0) incindex[indextemp] = incindex[indextemp]-1; printf("decrement %d\n\r",incindex[indextemp]); } else //increment frequency index { if(incindex[indextemp] != 24) incindex[indextemp] = incindex[indextemp]+1; printf("increment %d\n\r",incindex[indextemp]); } playwave(indextemp); //refresh waveform } else if(yindex == 4 || yindex == 3) //beat rows { mask = masktable[xindex-1>>1]; if(xindex & 0b00000001 == 0) { if(yindex == 4) buttonpress = 2; //pause else buttonpress = 4; //record } else { if(yindex == 4) buttonpress = 1; //play else buttonpress = 3; //stop } modbeat(); //refresh beats } else if(yindex != 0) { if(xindex < 7) { if(xindex < 4) //increment tempo index { if(bpmindex != 24) bpmindex++; } else //decrement frequency index { if(bpmindex != 0) bpmindex--; } } else { if(xindex == 8) { if(yindex == 2) pauseall(); } else { if(yindex == 2) playall(); else stopall(); } } } } xindexprev = xindex; yindexprev = yindex; xindex = 0; yindex = 0; } /////////////////////////////////////////////////////////////////// //parse raw coordinates to button indices /////////////////////////////////////////////////////////////////// void toindex(void) { if(x == 0 || y == 0) { xindex = 0; yindex = 0; } else { if(xyindextable[1]) { if(count3ms==0) { count3ms = 19; if(x == 0 || y == 0) { x = 0; y = 0; } else { tempx1 = COUNT2X(x); tempy1 = COUNT2Y(y); } tabletemp[tempx1] = tempy1; printf("%03d:%03d\n\r",x,y); } } //interpolate temp waveform printf("interpolating %d...\n\r",c); interpolate(); //copy temp waveform over printf("copying %d...\n\r",c); switch(c) { case 1: for (i=0; i<256; i++) table1[i] = tabletemp[i]; break; case 2: for (i=0; i<256; i++) table2[i] = tabletemp[i]; break; case 3: for (i=0; i<256; i++) table3[i] = tabletemp[i]; break; case 4: for (i=0; i<256; i++) table4[i] = tabletemp[i]; break; default:break; } //print results if needed for(i=0; i<256; i++) { printf("%02x ",tabletemp[i]); if(i== 15||i== 31||i== 47||i== 63||i== 79||i== 95||i==111||i==127|| i==143||i==159||i==175||i==191||i==207||i==223||i==239||i==255) printf("\n\r"); } printf("done\n\r"); playwave(c-1); c = 0; } /////////////////////////////////////////////////////////////////// //linearly interpolate temporary waveform array /////////////////////////////////////////////////////////////////// void interpolate(void) { //{ if(tabletemp[0] == 0) // if(a[0] == 0) { // { tempvalue = 0; // for(i=1; i<256; i++) // for(loop) { // { if(tabletemp[i] != 0) // find first nonzero at a[n] { // tempvalue = tabletemp[i]; // tempindex = i; // i = 255; // } // } // } if(tempvalue == 0) // if(all zeros) return; // exit function for(i=0; i0; i--) // for(bloop) { // { if(tabletemp[i] != 0) // find last nonzero at a[n] { // tempvalue = tabletemp[i]; // tempindex = i; // i = 1; // } // } // } for(i=tempindex; i<256; i++) // set a[n+1] to a[255] to a[n] { // tabletemp[i] = tempvalue; // } // } // } // for(i=0; i<256; i++) // for(loop) { // { if(tabletemp[i] == 0) // if(a[m] == 0) { // { for(j=i+1; j<256;j++) // find next nonzero at a[n] { // if(tabletemp[j] != 0) // { // tempvalue = tabletemp[j]; // tempindex = j; // j=255; // } // } // tempx1 = i-1; // set a[m] to a[n-1] to interpolated values tempx2 = tempindex; // tempy1 = tabletemp[tempx1]; // tempy2 = tabletemp[tempx2]; // for(j=i;j