#include #include #include #include #include // define a new I/O register for easier programming sfrw ICR1=0x26; //I like these #define begin { #define end } //Tasks void initialize(void); //set up ADC, Timers, LCD void keyscan(void); //keypad scanner int mult_opt(int a, int b); //fixed point multiply void gets_int(void); //intialize receive from hyperterm void puts_int(void); //intialize send from hyperterm unsigned char time1; //timeout counters char sample; //used to indicate if we detect noise int sum; //sum up 25 ADC values int i; //iterator // wave generation variables unsigned long accumulator @0x2f0; //accumulator used to generate plain sinewave unsigned char highbyte @0x2f3; //the HIGH byte of the accumulator variable unsigned long increment; //set sinewave frequency char sineTable[256] @0x300; //need loc to avoid glitch //RXC ISR variables unsigned char r_index; //current string index unsigned char r_buffer[17]; //input string unsigned char r_ready; //flag for receive done unsigned char r_char; //current character //TX empth ISR variables unsigned char t_index; //current string index unsigned char t_buffer[17]; //output string unsigned char t_ready; //flag for transmit done unsigned char t_char; //current character //************STATE MACHINES ************** //Top Level state machine unsigned char job_state; #define WAIT_FOR_INPUT 0 #define SEND_DATA 1 #define REC_DATA 2 #define LISTEN_NOTE 3 #define PLAY_NOTE 4 //WAIT FOR INPUT state machine unsigned char initial_state; #define START 1 #define Release 2 #define Debounce 3 #define EndChar 4 #define StillPressed 5 #define DebounceReleased 6 #define LOW1 7 #define LOW2 8 #define LOW3 9 #define HIGH1 10 #define HIGH2 11 #define HIGH3 12 int exit_timer; //used to check for inactivity int initial_timer; //SEND DATA state machine unsigned char send_state; #define PAUSE 0 #define SEND 1 //REC DATA state machine unsigned char posedge_state; //uses LOW1,LOW2,LOW3,HIGH1,HIGH2,HIGH3 states //slave state machine unsigned char slave_state; #define WAIT_FOR_INIT 0 #define SEND_INIT 1 #define WAIT_FOR_ACKI 3 #define WAIT_FOR_SONG 4 #define SEND_SONG 5 #define ACK_SONG 6 #define WAIT_FOR_ACKS 7 #define LISTEN_SONG 8 #define PLAY_SONG 9 #define SEND_ACKS 10 #define SEND_ACKI 11 //Communication pulse variables //For WAIT FOR INPUT state unsigned char pulse_length_WFI; //length of current incoming pulse unsigned char pulse_count_WFI; //number of pulses received unsigned char input_string_WFI; //received string from WAIT FOR INIT state //for SEND DATA state unsigned char pulse_length_SEND; //length of pulse to be transmitted unsigned char pulse_count_SEND; //number of pulses transmitted so far unsigned char s_data; //string to be transmitted //for REC DATA state unsigned char pulse_length_REC; //length of current incoming pulse unsigned char pulse_count_REC; //number of pulses received unsigned char input_string_REC; //received string //Communication Pulse Lengths #define PULSE_LONG 20 //length of a '1' #define PULSE_SHORT 10 //length of a '0' #define PULSE_THRESHOLD 15 #define EXIT_TIME 300 //Time out timer //Sound generation States unsigned char sgen_state; #define SINUSOID 0 //Play Soundwave #define BANJO 1 //Play Banjo Sound #define NO_NOTE 2 //Play No sound unsigned char song_timer; //used to set wait periods between notes unsigned char peer_note_count, wait_notes; unsigned char songID; //position in songList array unsigned char INIT_SEQ; //0x99 unsigned char char_one; //0x01 //PLAYER ID - player 1 plays first / possitive notes - player 2 plays second / negative notes unsigned char player_id; #define P1 0 #define P2 1 //array of our songs positive number = player 1 notes, negative notes = player 2 notes, 0 = no sound //with sum summing up 25 samples, each number represents 1/8 of a second of play time //player 1 must go first flash signed char songList [11][240] = {{0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, //0-Test song #1 0,0,0,6, 0,0,0,7, 0,0,0,8, 0,0,0,9, 0,0,0,10, 0,0,0,11, 0,0,0,12, 0,0,0,13, 0,0,0,14, 0,0,0,15, 0,0,0,16, 0,0,0,17, 0,0,0,18, 0,0,0,19, 0,0,0,20, 0,0,0,21, 0,0,0,22, 0,0,0,23, 0,0,0,24, 0,0,0,25, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5, 0,0,0,-6, 0,0,0,-7, 0,0,0,-8, 0,0,0,-9, 0,0,0,-10, 0,0,0,-11, 0,0,0,-12, 0,0,0,-13, 0,0,0,-14, 0,0,0,-15, 0,0,0,-16, 0,0,0,-17, 0,0,0,-18, 0,0,0,-19, 0,0,0,-20, 0,0,0,-21, 0,0,0,-22, 0,0,0,-23, 0,0,0,-24, 0,0,0,-25, 0,0,0,1, 0,0,0,3, 0,0,0,5, 0,0,0,6, 0,0,0,8, 0,0,0,10, 0,0,0,12, 0,0,0,13, 0,0,0,0, 0,0,0,0}, {0,1,0,1, 0,2,0,2, 0,3,0,3, 0,4,0,4, 0,5,0,5, //1-Test song #2 0,6,0,6, 0,7,0,7, 0,8,0,8, 0,9,0,9, 0,10,0,10, 0,11,0,11, 0,12,0,12, 0,13,0,13, 0,14,0,14, 0,15,0,15, 0,16,0,16, 0,17,0,17, 0,18,0,18, 0,19,0,19, 0,20,0,20, 0,21,0,21, 0,22,0,22, 0,23,0,23, 0,24,0,24, 0,25,0,25, 0,-1,0,-1, 0,-2,0,-2, 0,-3,0,-3, 0,-4,0,-4, 0,-5,0,-5, 0,-6,0,-6, 0,-7,0,-7, 0,-8,0,-8, 0,-9,0,-9, 0,-10,0,-10, 0,-11,0,-11, 0,-12,0,-12, 0,-13,0,-13, 0,-14,0,-14, 0,-15,0,-15, 0,-16,0,-16, 0,-17,0,-17, 0,-18,0,-18, 0,-19,0,-19, 0,-20,0,-20, 0,-21,0,-21, 0,-22,0,-22, 0,-23,0,-23, 0,-24,0,-24, 0,-25,0,-25, 0,0,0,1, 0,0,0,3, 0,0,0,5, 0,0,0,6, 0,0,0,8, 0,0,0,10, 0,0,0,12, 0,0,0,13, 0,0,0,0, 0,0,0,0}, {1,3,5,6, 8,10,12,13, 15,17,18,20, 22,24,25,0, 0,0,0,0, //2-Test song #3 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-3,-5,-6, -8,-10,-12,-13, -15,-17,-18,-20, -22,-24,-25,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,3,5,6, 8,10,12,13, 15,17,18,20, 22,24,25,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-3,-5,-6, -8,-10,-12,-13, -15,-17,-18,-20, -22,-24,-25,0, 0,0,0,0, 1,3,5,6, 8,10,12,13, 15,17,18,20, 22,24,25,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-3,-5,-6, -8,-10,-12,-13, -15,-17,-18,-20, -22,-24,-25,0, 0,0,0,0, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5}, {0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, //3-Test song #4 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,0,4, 0,0,0,5, 0,0,0,-1, 0,0,0,-2, 0,0,0,-3, 0,0,0,-4, 0,0,0,-5}, {1,-3,5,-6, 8,-10,12,-13, 15,-17,18,-20, 22,-24,25,-25, 24,-22,20,-18, //4-Test song #5 17,-15,13,-12, 10,-8,6,-5, 3,-1,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0, 0,0,0,-2, 0,0,0,0, 0,0,0,1, 0,0,0,0, 0,0,0,-2, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,-2,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,-2, 0,0,0,0, 0,1,0,0, 0,0,0,-2, 0,0,0,0, 0,1,0,0, 0,0,0,-2, 0,0,0,0, 1,0,0,0, 0,-2,0,0, 0,0,1,0, 0,0,0,-2, 0,0,0,-1, 0,0,0,-2, 0,0,0,1, 0,0,0,-2, 0,0,1,0, 0,-2,0,0, 1,0,0,-2, 0,1,0,-2, 0,1,0,-2, 1,-2,1,-2, 1,-1,1,-1, 0,1,0,0, -1,0,0,0, 1,0,0,0, 0,-1,0,0, 0,0,0,-1, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,-1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, {1,0,-1,0, 2,0,-2,0, 3,0,-3,0, 4,0,-4,0, 5,0,-5,0, //5-Dueling Banjos short 6,0,-6,0, 7,0,-7,0, 8,0,-8,0, 9,0,-9,0, 10,0,-10,0, 11,0,-11,0, 12,0,-12,0, 13,0,-13,0, 14,0,-14,0, 15,0,-15,0, 16,0,-16,0, 17,0,-17,0, 18,0,-18,0, 19,0,-19,0, 20,0,-20,0, 21,0,-21,0, 22,0,-22,0, 23,0,-23,0, 24,0,-24,0, 25,0,25,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, {9,0,0,-11, 13,0,0,-11, 9,0,-6,0, 6,0,-4,0, //6-cornell almameter 11,0,0,-9, 8,0,-9,0, -11,0,0,0, 0,0,0,0, 9,0,0,-11, 13,0,0,-11, 9,0,-6,0, 6,0,-4,0, 11,0,0,-13, 14,0,-8,0, 9,0,0,0, 0,0,0,0, -13,0,0,13, -11,0,11,0, -9,0,0,9, -8,0,8,0, -6,0,0,6, -4,0,9,0, -11,0,0,0, 0,0,0,0, 9,0,0,-11, 13,0,0,-11, 9,0,-6,0, 6,0,-4,0, 11,0,0,-13, 14,0,-8,0, 9,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, {5,6,8,5, 6,3,5,1, 3,0,0,0, 0,0,0,0, //7-Dueling banjos #2 -17,-18,-20,-17, -18,-15,-17,-13, -15,0,0,0, 0,0,0,0, 3,8,8,10, 12,8,12,10, 0,0,0,0, 0,0,0,0, -15,-20,-20,-22, -24,-20,-24,-22, 0,0,0,0, 0,0,0,0, 1,1,1,3, 5,6,8,6, 5,0,0,0, 0,0,0,0, -13,-13,-13,-15, -17,-18,-20,-18, -17,0,0,0, 0,0,0,0, 6,6,6,8, 10,11,13,11, 10,0,0,0, 0,0,0,0, -18,-18,-18,-20, -22,-23,-25,-23, -22,0,0,0, 0,0,0,0, 2,2,2,3, 5,6,8,6, 5,0,0,0, 0,0,0,0, -14,-14,-14,-15, -17,-18,-20,-18, -17,0,0,0, 0,0,0,0, 8,8,8,10, 12,12,13,12, 12,0,0,0, 0,0,0,0, -15,-15,-15,-17, -19,-20,-22,-20, -19,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, {12,13,15,12, 13,10,12,8, 10,0,0,0, 0,0,0,0, //8-dueling banjos #1 -12,-13,-15,-12, -13,-10,-12,-8, -10,0,0,0, 0,0,0,0, 10,15,15,17, 19,15,19,17, 0,0,0,0, 0,0,0,0, -10,-15,-15,-17, -19,-15,-19,-17, 0,0,0,0, 0,0,0,0, 8,8,8,10, 12,13,15,13, 12,0,0,0, 0,0,0,0, -8,-8,-8,-10, -12,-13,-15,-13, -12,0,0,0, 0,0,0,0, 13,13,13,15, 17,18,20,18, 17,0,0,0, 0,0,0,0, -13,-13,-13,-15, -17,-18,-20,-18, -17,0,0,0, 0,0,0,0, 9,9,9,10, 12,13,15,13, 12,0,0,0, 0,0,0,0, -9,-9,-9,-10, -12,-13,-15,-13, -12,0,0,0, 0,0,0,0, 8,8,8,10, 12,12,13,12, 12,0,0,0, 0,0,0,0, -15,-15,-15,-17, -19,-20,-22,-20, -19,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, {12,0,10,0, 8,0,10,0, -12,0,-12,0, -12,0,0,0, 10,0,10,0, //9-mary had a little lamb 10,0,0,0, -12,0,-15,0, -15,0,0,0, 12,0,10,0, 8,0,10,0, -12,0,-12,0, -12,0,-12,0, 10,0,10,0, 12,0,10,0, 8,0,0,0, 0,0,0,0, -12,0,-10,0, -8,0,-10,0, 12,0,12,0, 12,0,0,0, -10,0,-10,0, -10,0,0,0, 12,0,15,0, 15,0,0,0, -12,0,-10,0, -8,0,-10,0, 12,0,12,0, 12,0,12,0, -10,0,-10,0, -12,0,-10,0, -8,0,0,0, 0,0,15,0, -12,0,-10,0, -8,0,-10,0, 12,0,12,0, 12,0,0,0, -10,0,-10,0, -10,0,0,0, 12,0,15,0, 15,0,15,0, -12,0,-10,0, -8,0,-10,0, 12,0,12,0, 12,0,0,0, -10,0,-10,0, -10,0,0,0, 12,0,15,0, 15,0,15,0, -12,0,-10,0, -8,0,-10,0, 12,0,12,0, 12,0,12,0, -10,0,-10,0, -12,0,-10,0, 8,0,8,0, 8,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, {0,10,10,10, 6,6,3,3, 14,0,0,0, 0,0,16,0, 0,0,0,0, //*-bad rick roll 0,0,9,0, 16,0,0,0, 0,0,18,0, 0,0,0,0, 21,19,18,14, 0,0,0,0, 16,0,0,0, 0,0,9,0, 0,0,0,0, 14,14,0,14, 0,14,14,14, 0,0,0,0, 0,0,16,0, 0,0,0,0, 0,0,9,0, 16,0,0,0, 0,0,18,0, 0,0,0,0, 21,19,18,14, 0,0,0,0, 16,0,0,0, 0,0,9,0, 0,0,0,0, 14,14,0,14, 0,14,14,14, 0,0,0,0, 11,11,12,0, 14,0,14,0, 16,0,13,12, 10,9,0,0, 0,0,0,0, 0,0,0,0, 0,0,11,0, 11,0,13,0, 14,14,11,0, 0,9,0,0, 21,21,0,0, 21,21,0,0, 0,0,0,0, 0,0,11,0, 11,11,13,0, 0,0,11,0, 14,14,16,0, 0,0,13,13, 11,0,13,11, 9,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0} } ; //song position - these variable are used to keep track of where are you in the song unsigned char song_pos; //current position in song signed char count_note; //current note we are on signed char count_note2; //next note to play unsigned char num_notes; //number notes we are listening for int count_done; //done counting notes we are listening for //25 notes from c2 - c4 including sharps and flats //delay length = (sample rate)/(frequnecy) - .5 unsigned int sr_lengths[25]={ 152, //C2 144, //C#2/Db2 132, //D2 128, //D#2/Eb2 121, //E2 114, //F2 108, //F#2/Gb2 102, //G2 96, //G#2/Ab2 90, //A2 85, //A#2/Bb2 80, //B2 76, //C3 72, //C#3/Db3 68, //D3 64, //D#3/Eb3 60, //E3 57, //F3 54, //F#3/Gb3 51, //G3 48, //G#3/Ab3 45, //A3 42, //A#3/Bb3 40, //B3 38 //C4 }; int a_note; //is there a note? int dif; //difference between current sum and previous sum int prev_sum; //last cycles sum int total_rise; //total increase in sum char delay_timer; //state machine used to check whether or not a note was played unsigned char check_note; #define UP 0 #define DOWN 1 #define DELAY 2 #define INC_T 275 //Note Threshold if total_rise > INC_T then we register a note // BANJO/wave generation variables (Karplus Strong) unsigned int shift_register[153]; //Karplus Strong shift register - large enough for our lowest note unsigned int random_table[153]; //random value table used to set intial shift register's value unsigned int length; //shift register length unsigned int ptr_in, ptr_out; //ptr's used to iterate through shift register unsigned int ptr_in_h, ptr_out_h; unsigned int factor; //multiplication factor //Keypad stuff*************** #define maxkeys 12 unsigned char key, butnum; unsigned char compnum; //store number to compare to for debouncer unsigned char termnum = 12; // '#' is the termination number //key pad scan table(1-9. *, 0, #) flash unsigned char keytbl[12] = {0xee, 0xde, 0xbe, 0xed, 0xdd, 0xbd, 0xeb, 0xdb, 0xbb, 0xe7,0xd7, 0xb7}; // experimentally determined threshold // sum for 25 total samples #define THRESHOLD 75 // Hardware // Port C is connected to the ADC // The output of the op-amp signal is fed into Port A.0 //******************************************************** //timer 2 compare ISR -- Audio sampling //Interrupt for the Slave Node interrupt [TIM0_COMP] void audio_sample(void) { //Decrement the three times if they are not already zero if (time1<25) { //accumulate sample sum += (int)ADCH; //increment timer time1++; //start another conversion ADCSR.6=1; } else { // every 25 samples, 12.5 milliseconds time1=0; //if sum of last 25 ADC values is great than TRESHOLD, say that we have sound sample = (sum>THRESHOLD)? 1 : 0; switch(job_state) { case WAIT_FOR_INPUT: switch(initial_state) { //Wait for some noise or input from keypad //If a button is pressed go into keypad debouncer //if noise is heard go into noise debouncer case START: //time out - if a noise was heard but nothing has not been heard in 3.75 ms then //reset to initial state if(initial_timer>0) { initial_timer--; if(initial_timer==0) { pulse_length_WFI = 0; pulse_count_WFI = 0; input_string_WFI = 0; } } if(sample==1) { //noise heard initial_state=LOW2; initial_timer = EXIT_TIME; //intialize time out counter } else { keyscan(); //scan keypad for button press if(butnum!=0) { compnum=butnum; initial_state = Debounce; } } break; //Key pad debouncer case Debounce: keyscan(); if(butnum == compnum) initial_state = EndChar; else { initial_state = START;; } break; case EndChar: if(compnum == termnum) { //check if term buton(#) is presed. if so start intialization sequence job_state = SEND_DATA; slave_state= SEND_INIT; // set SEND_DATA variables to SEND_INIT sequence s_data = INIT_SEQ; send_state = PAUSE; pulse_length_SEND = 10; pulse_count_SEND = 0; } else { // set song number if(compnum == 11) songID = 0; else songID=compnum; initial_state = StillPressed; } break; case StillPressed: keyscan(); if(butnum == compnum) initial_state = StillPressed; else initial_state = DebounceReleased; break; case DebounceReleased: keyscan(); if(butnum == compnum) initial_state = StillPressed; else { initial_state = START; } break; //noise debouncer case LOW2: if(sample==1) initial_state=LOW3; else { initial_state = START; } break; //determine that a sound was legitimately heard and //start measuring the length of the sound pulse case LOW3: if(sample==1) { initial_state=HIGH1; pulse_length_WFI++; } else { initial_state=START; } break; case HIGH1: pulse_length_WFI++; if(sample==1) initial_state=HIGH1; else initial_state= HIGH2; break; case HIGH2: pulse_length_WFI++; if(sample==1) initial_state=HIGH1; else initial_state=HIGH3; break; case HIGH3: if(sample==1) { initial_state=HIGH1; pulse_length_WFI++; } else { initial_state=START; //if sound pulse lenght is greater than PULSE THRESHOLD, record as a '1' //if less than PULSE THRESHOLD record as a '0' if(pulse_length_WFI>PULSE_THRESHOLD) { input_string_WFI = input_string_WFI | (char_one<0) { increment=0; pulse_length_SEND--; } else { //send long pulse to indicate 1, and short pulse to indicate 0 send_state = SEND; pulse_length_SEND = (((s_data>>pulse_count_SEND)&char_one) == 1) ? PULSE_LONG : PULSE_SHORT; sgen_state = SINUSOID; increment = 0x01ACA362; } break; case SEND: if(pulse_length_SEND>0) pulse_length_SEND--; else { increment=0; sgen_state = NO_NOTE; pulse_count_SEND++; //once all data is sent go to next state if(pulse_count_SEND==8) { if(slave_state == SEND_INIT){ slave_state = WAIT_FOR_ACKI; job_state = REC_DATA; input_string_REC = 0; pulse_length_REC = 0; pulse_count_REC = 0; posedge_state = LOW1; exit_timer = EXIT_TIME; } else if(slave_state == SEND_ACKI){ slave_state = WAIT_FOR_SONG; job_state = REC_DATA; input_string_REC = 0; pulse_length_REC = 0; pulse_count_REC = 0; posedge_state = LOW1; exit_timer = EXIT_TIME; } else if(slave_state == SEND_SONG){ slave_state = WAIT_FOR_ACKS; job_state = REC_DATA; input_string_REC = 0; pulse_length_REC = 0; pulse_count_REC = 0; posedge_state = LOW1; exit_timer = EXIT_TIME; } else if(slave_state == SEND_ACKS){ slave_state = LISTEN_SONG; job_state = LISTEN_NOTE; // set more song variables?? posedge_state = LOW1; peer_note_count=0; //set song to beginning and set player id to P2 (play second) player_id = P2; song_pos = 0; num_notes = 0; count_done = 0; wait_notes = 0; total_rise = 0; check_note = UP; } } else { send_state = PAUSE; pulse_length_SEND=10; } } break; } //End switch(send_state) break; case REC_DATA: //exit timer -> if no sound is heard wait for a certain amount of time //before going back into the WAIT_FOR_INPUT/START state if(exit_timer>0){ exit_timer--; //noise debouncer switch(posedge_state) { case LOW1: if(sample==1) posedge_state=LOW2; else posedge_state=LOW1; break; case LOW2: if(sample==1) posedge_state=LOW3; else posedge_state=LOW1; break; case LOW3: if(sample==1) { posedge_state=HIGH1; pulse_length_REC++; } else posedge_state=LOW1; break; case HIGH1: pulse_length_REC++; if(sample==1) posedge_state=HIGH1; else posedge_state= HIGH2; break; case HIGH2: pulse_length_REC++; if(sample==1) posedge_state=HIGH1; else posedge_state=HIGH3; break; case HIGH3: if(sample==1) { posedge_state=HIGH1; pulse_length_REC++; } else { posedge_state=LOW1; exit_timer = EXIT_TIME; if(pulse_length_REC>PULSE_THRESHOLD) { input_string_REC = input_string_REC | (char_one< 0) { count_done = 1; } else { song_pos++; wait_notes++; } } else if(player_id == P2 && !count_done) { count_note = songList[songID][song_pos]; if(count_note > 0) { num_notes++; song_pos++; wait_notes = 0; } else if(count_note < 0) { count_done = 1; } else { song_pos++; wait_notes++; } } a_note = 0; dif = sum - prev_sum; //this simply totals up only consecutive increase in sound amplitude //if it is above our set threshold, we register that a note was played //also we do not register notes for 4 cycles after we indicate that a note was played //to prevent double counting a single note switch(check_note) { case UP: if((dif) > 0) { total_rise += dif; check_note = DOWN; } break; case DOWN: if((dif) > 0) { total_rise+=dif; } else{ sprintf(t_buffer,"%i ",total_rise); puts_int(); if( total_rise > INC_T){ a_note = 1; check_note = DELAY; delay_timer = 4; total_rise = 0; putchar('n'); } else { total_rise = 0; check_note = UP; } } break; case DELAY: if(delay_timer > 0) delay_timer--; else check_note = UP; break; } //if a note was played, record it! if(a_note) peer_note_count++; //if the number of notes listened to equals the number of expected notes, //then head to PLAY_NOTE state if(peer_note_count == num_notes) { job_state = PLAY_NOTE; slave_state = PLAY_SONG; song_timer = 7; } break; case PLAY_NOTE: //makes node wait propler amount of time if(song_timer > 0 || wait_notes > 0 ){ if(song_timer == 0 && wait_notes > 0) { song_timer = 10; wait_notes--; } song_timer--; } else { //if song_pos == 240 we have reached the end of the song if(song_pos == 240) { //DONE song go back to initial state // return to waiting for new song sgen_state=NO_NOTE; job_state = WAIT_FOR_INPUT; slave_state = WAIT_FOR_INIT; increment=0; posedge_state = LOW1; initial_state = START; pulse_length_WFI = 0; pulse_count_WFI = 0; input_string_WFI = 0; break; } count_note = songList[songID][song_pos]; if(song_pos != 239) { count_note2 = songList[songID][song_pos+1]; } else count_note2 = 0; //if note corresponds to player id then play note if((player_id == P1 && count_note > 0) || (player_id == P2 && count_note < 0)) { song_pos++; //get delay length of note if(player_id == P1) length = sr_lengths[count_note-1]; else { length = sr_lengths[(-(int)count_note)-1]; } //load shift register with random values for(i = 0; i 0 && player_id == P2)) song_timer = 0; else song_timer = 9; sgen_state = BANJO; } else if((player_id == P1 && count_note < 0) || (player_id == P2 && count_note > 0)) { //if note does not correspond to player id then end of play time -> go to listen state job_state = LISTEN_NOTE; slave_state = LISTEN_SONG; posedge_state = LOW1; num_notes = 0; count_done = 0; peer_note_count = 0; check_note = UP; total_rise = 0; } else { //count_note == 0 -> do nothing, let note play out if((count_note2 < 0 && player_id == P1) || (count_note2 > 0 && player_id == P2)) song_timer = 0; else song_timer=9; song_pos++; } } break; } //End switch(job_state) prev_sum = sum; sum = 0; } } //*************************************************** //timer 0 compare ISR - Audio generation interrupt [TIM2_COMP] void signal_gen(void) { if(sgen_state==SINUSOID) { accumulator = accumulator + increment; PORTC = 128 + sineTable[highbyte]; } else if(sgen_state==BANJO) { PORTC = (char)(shift_register[ptr_in]>>6); shift_register[ptr_in] = mult_opt(shift_register[ptr_in]+shift_register[ptr_out], factor); if(ptr_in > (length-1)) ptr_in=0; else ptr_in++; if(ptr_out > (length-1)) ptr_out=0; else ptr_out++; } } /**********************************************************/ //UART xmit-empty ISR interrupt [USART_DRE] void uart_send(void) { t_char = t_buffer[++t_index]; if (t_char == 0) { UCSRB.5=0; //kill isr t_ready=1; //transmit done } else UDR = t_char ; //send the char } /**********************************************************/ //********************************************************** //Entry point and task scheduler loop void main(void) { initialize(); //main task scheduler loop while(1) { } } //********************************************************** //Set it all up void initialize(void) { //serial setop for debugging using printf, etc. UCSRB = 0x18 ; UBRRL = 103 ; putsf("\r\nStarting...\r\n"); r_ready=0; t_ready=1; //set up timer 2 for sound generation - 10khz TIMSK = 0x80; // turn on timer 2 output compare ISR TCCR2 = 0b00001010; // prescale the clock by 8 OCR2 = 199; //set up timer 0 for 1/2 mSec timebase TIMSK = TIMSK | 0x02; TCCR0 = 0b00001011; OCR0 = 125; DDRC=0xff; // Port C is an output PORTC=0xff; //DDRD=0x00; // Port D is a keypad input DDRB= 0x00; //for now keypad = Port B time1=0; //init the A to D converter ADMUX = 0b11100000; //enable ADC and set prescaler to 1/128*16MHz=125,000 ADCSR = 0b11000111; //start first conversion ADCSR.6=1; //Ain = 0x42; sum=0; //init the sine table for (i=0; i<256; i++) { sineTable[i] = (char)(127.0 * sin(6.283*((float)i)/256.0)); } for(i=0; i<153; i++) { random_table[i]=rand()>>1; } //init the DDS phase increment // inc = f*2^32/62500 increment = 0; accumulator = 0; //initialize state machines posedge_state = LOW1; job_state = WAIT_FOR_INPUT; initial_state = START; slave_state = WAIT_FOR_INIT; sgen_state = NO_NOTE; send_state = PAUSE; posedge_state = LOW1; initial_timer = 0; //initialize state machine variables pulse_length_WFI = 0; pulse_count_WFI = 0; input_string_WFI=0; songID=0; song_timer=0; peer_note_count=0; // set constants INIT_SEQ = 0x99; char_one = 0x01; // set up sgen variables // f = Fs/n factor = 0x007D; ptr_in = 0; ptr_out = 1; length = sr_lengths[0]; for(i=0; i<=length; i++) { shift_register[i]=0; } //crank up the ISRs #asm sei #endasm } //******************************* //Keyscan void keyscan(void) { //time2 = t2; //get lower nibble DDRB = 0x0f; PORTB = 0xf0; delay_us(5); key = PINB; //get upper nibble DDRB = 0xf0; PORTB = 0x0f; delay_us(5); key = key | PINB; //find matching keycode in keytbl if (key != 0xff) { for (butnum=0; butnum0) { putchar(t_buffer[0]); UCSRB.5=1; } } //optimized fixed point multiply int mult_opt(int a, int b) { #asm ;push r20 ;push r21 mov r24,r20 mov r25,r21 ldd R22,Y+2 ;load a ldd R23,Y+3 ld r20,Y ;load b ldd r21,Y+1 muls r23, r21 ; (signed)ah * (signed)bh mov r31, r0 ; mul r22, r20 ; al * bl mov r30, r1 ; ;mov r16, r0 mulsu r23, r20 ; (signed)ah * bl add r30, r0 ; adc r31, r1 ; mulsu r21, r22 ; (signed)bh * al add r30, r0 ; adc r31, r1 ; mov r20,r24 mov r21,r25 ;pop r21 ;pop r20 #endasm }