//-------------------------------------------------------------------- //-- Speden Spelit Speedtest PIC 18F442 4 MHz //-- //-- //-- //--Timer 1: 16-bit timer, reading buttons by interrupts //--Timer 0: 16-bit timer, seed for random number, pitkat viiveet //--Timer 2: 8-bit timer, Buzzer PWM period control //-- //-- Version 0.1 //-- 16.12.2017 P.Viljakainen--- //-------------------------------------------------------------------- #include #include #include "math.h" #include "i2c.h" #include "saa1064.h" #include "delays.h" #include #define MAXSTACK 10 // maximum number of pending button presses char next=0; char previous = 0; char button_stack[MAXSTACK]; char stacklevel = 0; char current_buttons = 4; char last_buttons = 4; char new_press=0; char mode=0; bit memorygame=0; char apu=0; void blue(void); void yellow(void); void green(void); void red(void); void alloff(void); void litnext(int allnew); void litbutton(int color); int decrease_dly(int); int check_press(void); int addtostack(int); __CONFIG (1,OSCSDIS & HS & UNPROTECT); __CONFIG (2,WDTDIS & BORDIS & PWRTDIS); void initialize(void); int check_press(void) { int i=0; if (stacklevel>0) { if (button_stack[0] == current_buttons) { stacklevel--; for (i=0;i7000) viive=(int)(0.99*viive); else viive=(int)(0.997*viive); return viive; } void main(void) { initialize(); I2CInit(); // alustetaan i2c- vayla char i=0; int pisteet=0; int viive=16000; //65535 vastaa 4 s viivett, 16000 vastaa n. 1s viivetta int hiscore; char hiscore_lowbyte; char hiscore_hibyte; int memhiscore; char memhiscore_lowbyte; char memhiscore_hibyte; int memgameseed=0; char seqlength=0; char memorybutton=0; delay_ms(0x32); // to help with power-up (?) if (EEPROM_READ(0)==0xFF && EEPROM_READ(1)==0xFF && EEPROM_READ(2)==0xFF && EEPROM_READ(3)==0xFF) { // Reprogramming has erased EEPROM EEPROM_WRITE (0, 0); // Set highscore low byte to 0 delay_longms(20); EEPROM_WRITE (1, 0); // Set highscore high byte to 0 delay_longms(20); EEPROM_WRITE (2, 0); // Set memory game highscore low byte to 0 delay_longms(20); EEPROM_WRITE (3, 0); // Set memory game highscore high byte to 0 } delay_longms(20); hiscore_hibyte = EEPROM_READ(1); delay_longms(20); hiscore_lowbyte = EEPROM_READ(0); hiscore=(hiscore_hibyte<<8 | hiscore_lowbyte); memhiscore_hibyte = EEPROM_READ(3); delay_longms(20); memhiscore_lowbyte = EEPROM_READ(2); memhiscore = (memhiscore_hibyte<<8 | memhiscore_lowbyte); send_saa1064_msg(0x70,0b01110111,0); PR2=0; // output low pwm control send_saa1064_string(0x70,"speden spelit nopeustesti versio 0.3",200, &new_press); mode=6; while(1) { switch (mode) { // DEMO case 0: PR2=0; // disable buzzer for demo mode if (new_press) { alloff(); mode=1; srand(((TMR0L)+(TMR0H<<8))); if (current_buttons==1) { // yellow button pisteet = 100; // difficult game - start from 100 for (i=0; iviive) { litnext(1); TMR0H=0; TMR0L=0; } if (((TMR0L)+(TMR0H<<8))>viive*2/3) { alloff(); } break; case 1: // GAME if (new_press) { if (check_press()==1) { pisteet++; send_saa1064_num(0x70,0b01110111,pisteet); } else mode=2; new_press=0; } if (((TMR0L)+(TMR0H<<8))>viive) // { litnext(1); if (addtostack(next)==0)//addtostack palauttaa 0 jos stack taynna mode=2; // Game over TMR0H=0; TMR0L=0; viive = decrease_dly(viive); } if (((TMR0L)+(TMR0H<<8))>viive*2/3) { alloff(); } if ((mode == 2) && (pisteet>hiscore)) mode=3; // High score break; case 2: //GAME OVER for (i=0; i<4; i++) { PR2=170; // buzzer 368 Hz (blue) LATB0=1; LATB1=1; LATB2=1; LATB3=1; delay_ms(0x32); alloff(); delay_ms(0x32); } alloff(); mode = 5; break; case 3: // HIGH SCORE if (memorygame) { memhiscore=pisteet; memhiscore_lowbyte= (memhiscore & 0xFF); memhiscore_hibyte=(memhiscore>>8&0xFF); EEPROM_WRITE (2, memhiscore_lowbyte); delay_longms(20); EEPROM_WRITE (3, memhiscore_hibyte); new_press=0; } else { hiscore=pisteet; hiscore_lowbyte= (hiscore & 0xFF); hiscore_hibyte=(hiscore>>8&0xFF); EEPROM_WRITE (0, hiscore_lowbyte); delay_longms(20); EEPROM_WRITE (1, hiscore_hibyte); new_press=0; } for (i=0; i<4; i++) { PR2=120; LATB0=1; LATB1=1; LATB2=1; LATB3=1; delay_ms(0x1E); alloff(); PR2=110; delay_ms(0x1E); send_saa1064_msg(0x70,0b01110111,0); PR2=100; delay_ms(0x1E); send_saa1064_num(0x70,0b01110111,pisteet); } alloff(); new_press=0; delay_ms(0x64); send_saa1064_string(0x70,"congratulations new high score",200, &new_press); delay_ms(0x64); send_saa1064_num(0x70,0b01110111,pisteet); mode = 5; break; case 4: // MEMORY GAME memorygame = 1; srand(memgameseed); stacklevel=0; delay_longms(0x1F); for (i=0; i<=seqlength; i++) { litnext(1);// arpoo next:in ja sytyttaa delay_longms(0x1F); alloff(); apu=addtostack(0);// pinoon button_stackiin } for (i=0; i<=seqlength; i++) { while (!new_press){} if (check_press()==1) { pisteet++; send_saa1064_num(0x70,0b01110111,pisteet); delay_ms(0xA); } else { if (pisteet>memhiscore) mode=3; else mode=2; break; } new_press=0; } if (mode == 4) delay_longms(0x50); seqlength++; break; case 5: // INIT new_press=0; pisteet=0; viive=16000; stacklevel=0; mode=0; memorygame=0; seqlength=0; break; case 6: // DISPLAY HIGH SCORES DEMO viive=16000; send_saa1064_string(0x70,"speed test high score",200, &new_press); send_saa1064_num(0x70,0b01110111,hiscore); if (new_press == 0) delay_ms(0x64); send_saa1064_string(0x70,"memory test high score",200, &new_press); send_saa1064_num(0x70,0b01110111,memhiscore); if (new_press == 0) delay_ms(0x64); send_saa1064_string(0x70,"hit blue button to start easy speed test",200, &new_press); send_saa1064_string(0x70,"hit yellow button to start hard speed test",200, &new_press); send_saa1064_string(0x70,"hit green button to start memory test",200, &new_press); send_saa1064_string(0x70,"hit red button to display high scores",200, &new_press); mode=0; break; } // END OF SWITCH } // End of endless loop } // End of Main //------ interrupts handling ------------------------------------- void interrupt tc_int(void) { if(TMR1IF) // come here every 65.53 ms { LATB4 ^= 1; if (new_press==0) { last_buttons=current_buttons; // initially both =4 current_buttons=5; if (PORTDbits.RD0==0) // blue current_buttons=0; if (PORTDbits.RD1==0) // yellow current_buttons=1; if (PORTDbits.RD2==0) // green current_buttons=2; if (PORTDbits.RD3==0) // red current_buttons=3; if (current_buttons<5 && current_buttons!=last_buttons) new_press=1; } TMR1IF = 0; } } //------ interrupts handling ------------------------------------- void initialize() { GIE=0; ADCON1 = 0xB2; //ADCON1 = 0x83; // 10-bit, right justified A,VREF,A,A,A TRISA=0b00111; //RA0 & RA1 & RA2 = input muut output TRISB=0b00000000; // LATB0=RC5 input RBPU=1; // Disable RB weak pull-upa TRISD = 0b00001111; //D-portti 0-3 intputeiksi TRISC = 0b00011000; //RC3 & RC4 inputeiksiSCL ja SDA,RC2 output for PWM TRISE0=0; //RE0=output(SD),RE1=SPARE input, RE2=output(COND) TRISE1=0; TRISE2=0; //ADON=1; // turn on the A2D conversion module //lcd_init(); // Display module initialization //delay(); //RCSTA = 0x90; // RX Setting, 8bit, enable receive, //TXSTA = 0x24; // TX Setting, 8bit, Asynchronius mode, High speed //SPBRG = 129; // Set Baudrade - 9600 (from datasheet baudrade table) //------- PWM setup, timer 2 8 bit ---------------------------------------------------------------------------------------- T2CON= 0b00000110; //Timer 2 control register prescale 1:16(xxxxxx1x) postscale 1:1 //TMR2IE=1; CCP1CON= 0b00001100; //set up for PWM and 2 LSB (CCP1CON(5:4), DC1B1, DC1B0) // These bits are the two LSbs (bit1 and bit0) of the 10-bit PWM duty cycle. The upper eight bits // of the duty cycle are found in CCPR1L CCPR1L=128; // Set up Duty cycle initial value 8 MSB = 50% PR2= 0; // Set up PERIOD, constant =255, with TMR2 Prescaler 1:4= 4.88 kHz (1:16 = 1.22 kHz) PWWM frequency //PWM period = (PR2) + 1] x 4 x TOSC x (TMR2 prescale value) //---------------------------------------------------------------------------------------------------------- //----- I2C setup------------------------------------------------------------------------------------------- I2CInit(); //---------------------------------------------------------------------------------------------------------- //-------Timer 1 Setup buttons 16 bit------------------------------------------------------------------------------------- T1CON= 0b10001001; // 16 bit read_write, 1:1 prescale, timer 1 osc enable, internal clock //TMR1ON=1; // timer on TMR1IE=1; // Timer 1 interrupt enable TMR1IP=1; // Timer 1 priority //T1CKPS0=0; // Prescaler bits, 00=1:1, 1/(4 Mhz/4)x1*x65535=65.53ms //T1CKPS1=0; //---------------------------------------------------------------------------------------------------------- //-------Timer 0 Setup long delays 16 bit ------------------------------------------------------------------------------------- TMR0ON=1; // turns timer on T08BIT=0; // 16 bit counter T0CS=0; // internal instruction cycle clock T0SE=0; //Increment on low-to-high transition on T0CKI pin PSA=0; //Timer0 prescaler is assigned. Timer0 clock input comes from prescaler output. T0PS0=1; T0PS1=0; T0PS2=1; //101= 1:64 prescale value (4MHz/4x64x65535 = 4.19424s) //TMR0L, TMR0H //--------------------------------------------------------------------------------------------------------------------- IPEN=0; // Interpup priority disable GIE=1; // Global interrupts enable PEIE=1; // Periphral interrup enable RBIE=0; }