/********************************************* This program was produced by the CodeWizardAVR V1.23.7a Standard Automatic Program Generator © Copyright 1998-2002 HP InfoTech s.r.l. http://www.hpinfotech.ro e-mail:office@hpinfotech.ro Project : Intelligent Multimedia System Date : 5/1/2006 Author : Ah Yud Chan, Wing Mau Cheung, Sheung Yi Shih Company : Cornell Univ, Ithaca, NY 14853 Course : ECE476 Final Project Chip type : ATmega32 Program type : Application Clock frequency : 16.000000 MHz Memory model : Small Internal SRAM size : 2KByte External SRAM size : 0 Data Stack size : 256 *********************************************/ #include #include #include //Define constant value #define begin { #define end } #define NO 0 #define YES 1 #define OFF 0 #define ON 1 #define FALSE 0 #define TRUE 1 #define MAX_VOLUME_SCALE 10 //Maximum volume scale for both voice & music #define DEFAULT_VOLUME_SCALE 5 //Default volume scale for both voice & music #define MIN_VOLUME_SCALE 0 //Minimum volume scale for both voice & music #define DATA_BUFFER_SIZE 1500 //Number of byte in SRAM used for sample buffer #define ECHO 1 //Effect: echo #define DISTORT 2 //Effect: distortion #define POSITIVE_THRESHOLD 125 //Upper threshold of voice volume for patient effect #define NEGATIVE_THRESHOLD 115 //Lower threshold of voice volume for patient effect #define PATIENT 1 //Distortion effect: processed voice is like a patient #define WALKI_TALKI 2 //Distortion effect: processed voice is like a Walki-Talki #define ROBOT 3 //Distortion effect: processed voice is like a robot #define GAUSSIAN_NOISE 4 //Distortion effect: processed voice is added with additive white Gaussian noise #define LOWER_KEY 5 //Distortion effect: processed voice is of lower key //Declare global variables unsigned char data[DATA_BUFFER_SIZE]; //sample char sineTable[256]; //Approximate sine wave array to generate robot effect int dataIndex = 0; //Indexer for sample data array unsigned char voiceScale = DEFAULT_VOLUME_SCALE; //Voice volume scale unsigned char musicScale = DEFAULT_VOLUME_SCALE; //Music volume scale unsigned char sampleScale = 8; //Sampling frequency scale, Sampling frequency = 1-8KHz int i = 0; //Parameter commonly used iterator for iterations int x = 0; //Parameter commonly used integer for data manipulation int echoDelay; //Parameter for setting range of samples for echo unsigned char effect = NO; //Effects: echo, distortion unsigned char distortOption = NO; //Distortion options: patient, Walki-Talki, robot, Gaussian noise, lower pitch bit busy = NO; //Flag to protect the critical section of ADC sampling bit onOff = NO; //Flag to indicate the on/off state of the multimedia system //Command type for command packets typedef enum { TURN_ON, TURN_OFF, SET_ECHO, SET_MUSIC_VOLUME, SET_VOICE_VOLUME, SET_SAMPLE_FREQUENCY, SET_DISTORTION } CmdIdx; //Command packet structure typedef struct CmdPktTag { CmdIdx cmd; unsigned int dataLen; } CmdPkt; //enum for state machine to receive command packet typedef enum { CMD_B1, CMD_B2, LEN_B1, LEN_B2, DATA_SEC } RecvCmdStateType; RecvCmdStateType recvCmdState; //Command state variable CmdPkt cmdPkt; //Command packet struct //********************************************************** //Sampling frequency is in KHz, range is 1-8KHz void setSampleFrequency() begin while(busy==YES); while ( !(UCSRA & (1<<7)) ); sampleScale = (unsigned char)UDR; TCCR0 = 0b00001011; OCR0= 250/sampleScale - 1; end //********************************************************** //Set distortion effect and set distortion option void setDistortion() begin while(busy==YES); while ( !(UCSRA & (1<<7)) ); x = (int)UDR; if(x==0) effect = NO; else{ effect = DISTORT; distortOption = (unsigned char)x; } end //********************************************************** //Set voice volume void setVoiceVolume() begin while(busy==YES); while ( !(UCSRA & (1<<7)) ); voiceScale = (unsigned char)UDR; end //********************************************************** //Set music volume void setMusicVolume() begin while(busy==YES); while ( !(UCSRA & (1<<7)) ); musicScale = (unsigned char)UDR; end //********************************************************** //Process command packet received from serial port void processSerialInput(unsigned char data) begin switch (recvCmdState) { case CMD_B1: cmdPkt.cmd=data; recvCmdState=CMD_B2; break; case CMD_B2: cmdPkt.cmd|=(((unsigned int)data)<<8); recvCmdState=LEN_B1; break; case LEN_B1: cmdPkt.dataLen=data; recvCmdState=LEN_B2; break; case LEN_B2: cmdPkt.dataLen|=(((unsigned int)data)<<8); recvCmdState=DATA_SEC; UCSRB.7=0; //stop rec ISR break; } end //********************************************************** //UART character-ready ISR interrupt [USART_RXC] void uart_rec(void) begin processSerialInput(UDR); //get a char end //********************************************************** //Turn on the multimedia system void turnOn() begin onOff = ON; end //********************************************************** //Turn off the multimedia system void turnOff() begin onOff = OFF; end //********************************************************** //Set echo effect and echo delay range void setEcho() begin while(busy==YES); while ( !(UCSRA & (1<<7)) ); x = (int)UDR; if(x==0) effect=NO; else{ effect = ECHO; echoDelay = (x)*100; } end //********************************************************** //Sample both voice and music signals and output the effect void sampleAudio() begin unsigned char musicSignal; unsigned char micSignal; unsigned char mixedSignal; int idx; //Check if the multimedia system is on if(onOff) { //Set busy to protect the critical section busy = YES; //get the microphone signal from the ADC on chip micSignal = ADCH; data[dataIndex] = micSignal; //start another conversion ADMUX = 0b11100000; ADCSR.6=1; // get the music signal from the external ADC musicSignal = ((PINB & 0xf)<<4)+(PINA>>4); switch(effect) { case ECHO: idx = dataIndex-echoDelay+1; if (idx < 0)idx += DATA_BUFFER_SIZE; //Current = 75%, Echo = 25% micSignal = (data[dataIndex]-(data[dataIndex]>>2)) + (data[idx]>>2); break; case DISTORT: switch(distortOption){ case PATIENT: //Apply distortion effect: patient if(micSignal>130) micSignal=130; else if(micSignal<110) micSignal=110; break; case WALKI_TALKI: //Apply distortion effect: Walki-Talki micSignal = (unsigned char)((((int)(micSignal) - 120)*((int)(micSignal) - 120)) + 120); break; case ROBOT: //Apply distortion effect: robot if(micSignal>POSITIVE_THRESHOLD || micSignal>1)) + 120); if(i>=255) i=0; else i++; break; case GAUSSIAN_NOISE: //Apply distortion effect: Gaussian noise micSignal = (unsigned char)((int)(micSignal)+ (rand()>>9)); break; case LOWER_KEY: //Apply distortion effect: lower key x = 0; for(i=0; i<16; i++) { if (i < 0) i += DATA_BUFFER_SIZE; x += (int)data[dataIndex - i]; } x >>= 4; micSignal = (unsigned char) ((x-120)*2 + 120); break; default: break; } break; } //Set volume of music signal musicSignal = (unsigned char)(((int)(musicSignal) - 120)* musicScale / MAX_VOLUME_SCALE + 120); //Set volume of voice signal micSignal = (unsigned char)(((int)(micSignal) - 120)* voiceScale / MAX_VOLUME_SCALE + 120); //Mix the voice of user and music mixedSignal = (micSignal>>1) + (musicSignal>>1); //Output mixed signal to speaker PORTC = mixedSignal; //Signal strength indicator PORTD.7 = (mixedSignal >> 3) & 1; PORTD.6 = (mixedSignal >> 2) & 1; PORTD.3 = (mixedSignal >> 1) & 1; PORTD.2 = mixedSignal & 1; PORTB.7 = (mixedSignal >> 7) & 1; PORTB.6 = (mixedSignal >> 6) & 1; PORTB.5 = (mixedSignal >> 5) & 1; PORTB.4 = (mixedSignal >> 4) & 1; //Start another music ADC conversion PORTD.4 = 0; PORTD.4 = 1; //Send the mixed signal to PC via the serial port while (!(UCSRA & (1<<5))); UDR = mixedSignal; //Increment indexer of the sample buffer dataIndex = (dataIndex == DATA_BUFFER_SIZE) ? 0 : (dataIndex+1); //Exit of critical section busy = NO; } end //********************************************************** //generate waveform interrupt [TIM0_COMP] void voiceInterrupt(void) begin sampleAudio(); //sample and generate the sound end //********************************************************** //Check the command and execute it void processCmd() begin switch (cmdPkt.cmd) { case TURN_ON: //turn on the sound turnOn(); recvCmdState=CMD_B1; break; case TURN_OFF://turn off the sound turnOff(); recvCmdState=CMD_B1; break; case SET_ECHO: // perform the effect of echo setEcho(); recvCmdState=CMD_B1; break; case SET_MUSIC_VOLUME:// set the music volume setMusicVolume(); recvCmdState=CMD_B1; break; case SET_VOICE_VOLUME:// set the voice volume setVoiceVolume(); recvCmdState=CMD_B1; break; case SET_SAMPLE_FREQUENCY:// set the sampling frequency setSampleFrequency(); recvCmdState=CMD_B1; break; case SET_DISTORTION:// set the distortion setDistortion(); recvCmdState=CMD_B1; break; } //Enable serial communication receive interrupt UCSRB.7=1; end //********************************************************** //Initialize all the registers, ports, external ADC and DAC chips, program variables void initialize() begin DDRA=0x00; //Pin 4~7 : ADC 0~3 DDRB = 0b11110000; DDRC=0xff; //Pin 0~7 : DAC 0~7 DDRD = 0b11111100; // Pin 4 : ADC ~WR , Pin 5 : ADC Clock TIMSK = 0b00000010; // rutn on timer 1 TCNT0 = 0; TCCR0 = 0b00001010; OCR0 = 249; PORTD.4 = 1; PORTC = 0; TCNT1 = 0; TCCR1A = 0b01000000; TCCR1B = 0b01001010; OCR1A = 0; PORTB.7 = 1; PORTB.6 = 1; //init the A to D converter //channel zero/ left adj /internal 2.56 voltage (5V in fact because the AREF switch is conncected) ADMUX = 0b11100000; //enable ADC and set prescaler to 1/8*16MHz=125,000 //and clear interupt enable //and start a conversion ADCSR = 0b11000111; // initialize serial port UCSRB = 0b10011000; UCSRA = 0b00100010; UBRRL = 16 ; // variable initialization onOff = OFF; recvCmdState=CMD_B1; effect = NO; distortOption = NO; dataIndex=0; echoDelay = 0; voiceScale = DEFAULT_VOLUME_SCALE; musicScale = DEFAULT_VOLUME_SCALE; sampleScale = 8; //init the sine table for (i=0; i<256; i++) sineTable[i] = (char)(127.0 * sin(6.283*((float)i)/256.0)) ; #asm sei // Enable the interrupt #endasm end //********************************************************** void main(void) begin //Initialize all the registers, ports, external ADC and DAC chips, program variables initialize(); //endless loop to check if there is serial data while(1) if (recvCmdState==DATA_SEC) processCmd(); end //end main