// PC_Comm.c// Doug Bemis// S. Haynes, Microprocessors// 12/14/06// Project 3, Light direction/speed change// when interrupt (push) thrown#include "Demonstrator.h"#include "PC_Comm.h"extern int go;extern int milliseconds;extern int seconds;extern int totalS;extern int tries;extern int running;extern int trials[];extern int times[];extern int success;extern int lit;int main(void){ // run the initialization routines initializer(); // Init port pins DDRB = 0x00; // set port B for input DDRD = 0xFF; // set port D for output //used for outputting values to the PC if it is connected //char* buf = (char *)(malloc(20*sizeof(char))); //Begin forever chatting with the PC for(;;) { if (go != 0) { /* initialize random generator */ srand ( milliseconds ); tries=0; //used for outputting values to the PC if it is connected char* buf = (char *)(malloc(30*sizeof(char))); while (tries < 10) { _delay_loop_2(30000); sendString("Get ready!\r"); running = 1; PORTD=0x00; //random time between 1 second and 5 seconds int tmax = (abs(rand())*1000)%4000; //make sure tmax is positive if (tmax <0) tmax *= -1; //tmax min is 1second, or 1000 ms, so add it incase rand=0 tmax += 1000; int compare = 0; milliseconds=0; //wait the random time while (getMillis() < tmax); //reset milliseconds to count for user now milliseconds = 0; compare =0; lit=1; //light it up! PORTD=0xFF; //wait till they push the button, or 8 seconds elapse while (getMillis() < 8000 && running==1); PORTD=0x00; lit=0; //didnt press in 8 seconds, mark it if (success==0) { trials[tries] = 8000; tries++; running = 0; } //store the time wait times[tries-1] = tmax; success=0; if (tries <10) { buf = (char *)(malloc(20*sizeof(char))); sprintf(buf,"Got it... %d left",9-tries); sendString(buf); sendChar('\r'); free(buf); } } int total = 0; for (int x=0; x< 10; x++) { total += trials[x]; buf = (char *)(malloc(20*sizeof(char))); sprintf(buf,"Try %d: You took %dms on a wait of %d",x+1,trials[x],times[x]); sendString(buf); sendChar('\r'); free(buf); } float avg = (float)total/10.0; sendString("-----------\r"); buf = (char *)(malloc(40*sizeof(char))); sprintf(buf,"Your average response time: %.3g",avg); sendString(buf); sendChar('\r'); free(buf); tries=0; go = 0; } } return 0;}char isCharAvailable(){ // Does the RX0 bit of the USART Status and Control Register // indicate a char has been received? if ( (UCSR0A & (0x80)) ) return 1; else return 0;}char receiveChar(){ // Return the char in the UDR0 register return UDR0;}void sendChar(char data){ int i = 0; // To send data with the USART put the data in the USART data register UDR0 = data; // Check to see if the global interrupts are enabled if(SREG & 0x80) { // Wait until the byte is sent or we count out while ( !(UCSR0A&0x40) && (i<10000) ) { i++; } } else // Wait until the byte is sent while( !(UCSR0A&0x40) ); // Clear the TXCflag UCSR0A=UCSR0A|0x40; }void sendString(char s[]){ int i = 0; while(i < 64) // don't get stuck if it is a bad string { if( s[i] == '\0' ) break; // quit on string terminator sendChar(s[i++]); }}void USARTinit(){ // Increase the oscillator to 2 Mhz for the 19200 baudrate: CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable // set prescaler = 4, Inter RC 8Mhz / 4 = 2Mhz CLKPR = (1<<CLKPS1); // Set the USART baudrate registers for 19200 UBRR0H = 0;//(unsigned char)(baudrate>>8); UBRR0L = 12;//(unsigned char)baudrate; // Enable 2x speed change UCSR0A = (1<<U2X0); // Enable receiver and transmitter UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(0<<RXCIE0)|(0<<UDRIE0); // Set the USART to asynchronous at 8 bits no parity and 1 stop bit UCSR0C = (0<<UMSEL0)|(0<<UPM00)|(0<<USBS0)|(3<<UCSZ00)|(0<<UCPOL0); // Enable interrupts sei(); // Setup the interrupt mask and flags PCMSK1 = (1<<PINB6) | (1<<PINB4); // set pin-change interrupt mask EIFR = (1<<PCIF1); // clear external intterupt flag 1 EIMSK = (1<<PCIE1); // enable external interrupt 1 }//Calibrate the internal OSCCAL byte, using the external //32,768 kHz crystal as referencevoid OSCCAL_calibration(void){ unsigned char calibrate = 0;//FALSE; int temp; unsigned char tempL; CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz CLKPR = (1<<CLKPS1) | (1<<CLKPS0); TIMSK2 = 0; //disable OCIE2A and TOIE2 ASSR = (1<<AS2); //select asynchronous operation of timer2 (32,768kHz) OCR2A = 200; // set timer2 compare value TIMSK0 = 0; // delete any interrupt sources TCCR1B = (1<<CS10); // start timer1 with no prescaling TCCR2A = (1<<CS20); // start timer2 with no prescaling while((ASSR & 0x01) | (ASSR & 0x04)); //wait for TCN2UB and TCR2UB to be cleared // wait for external crystal to stabilise for(int i = 0; i < 10; i++) _delay_loop_2(30000); while(!calibrate) { cli(); // mt __disable_interrupt(); // disable global interrupt TIFR1 = 0xFF; // delete TIFR1 flags TIFR2 = 0xFF; // delete TIFR2 flags TCNT1H = 0; // clear timer1 counter TCNT1L = 0; TCNT2 = 0; // clear timer2 counter while ( !(TIFR2 && (1<<OCF2A)) ); // wait for timer2 compareflag TCCR1B = 0; // stop timer1 sei(); // __enable_interrupt(); // enable global interrupt if ( (TIFR1 && (1<<TOV1)) ) { temp = 0xFFFF; // if timer1 overflows, set the temp to 0xFFFF } else { // read out the timer1 counter value tempL = TCNT1L; temp = TCNT1H; temp = (temp << 8); temp += tempL; } if (temp > 6250) { OSCCAL--; // the internRC oscillator runs to fast, decrease the OSCCAL } else if (temp < 6120) { OSCCAL++; // the internRC oscillator runs to slow, increase the OSCCAL } else calibrate = 1;//TRUE; // the interRC is correct TCCR1B = (1<<CS10); // start timer1 }}