/* Atmel Mega32 + Nokia 6100 (Epson controller) Christian Montoya & James Luk -Derived from: Nokia 6100 Display Test Copyright 2006 Refik Hadzialic (http://www.e-dsp.com) -Which was derived from: Thomas Pfeifer's code at http://thomaspfeifer.net/nokia_6100_display.htm and Owen Osborn's code at http://www.sparkfun.com/datasheets/LCD/Nokia6100_Demo.c This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Target: AVR-ATMega32 Compiler: Codevision's terrible compiler */ //#### CONFIG #### #define F_CPU 16000000UL // 16 MHz #define SPIPORT PORTC #define SPIDDR DDRC #define CS 4 #define CLK 7 #define SDA 5 #define RESET 6 //################# #include #include #include #include #include #include #include #define cbi(reg, bit) (reg&=~(1<1 && gameState==Dodge_Alive) { if (dodge_song[note]>0) TCCR0 = 0b00011100; //not a rest else TCCR0 = 0b00000100; note++; OCR0 = dodge_song[note]; if (note > maxDodgeSong) note = 0; //test for end of scale musicT = 0; } else if(musicT>2) { if (paint_song[note]>0) TCCR0 = 0b00011100; //not a rest else TCCR0 = 0b00000100; note++; OCR0 = paint_song[note]; if (note > maxPaintSong) note = 0; //test for end of scale musicT = 0; } musicT++; } } else if(gameState==Tunnel_Alive) { if(sound==1) { if (tunnel_song[note]>0) TCCR0 = 0b00011100; //not a rest else TCCR0 = 0b00000100; note++; OCR0 = tunnel_song[note]; if (note > maxTunnelSong) note = 8; //test for end of scale musicT = 0; } ADMUX = 0b01100000; //get the sample from accelerometer Ain = ADCH; //start another conversion ADCSR.6=1; MoveX = Ain; } else TCCR0 = 0b00000100; // sound is off switch (gameState) { case Menu: if (pushflag && BUTTON_A) { // A PRESSED TO CHANGE SELECTION delay_ms(200); switch(selection) { case 0: undraw_sprite_r_8x8(triangle,16,12); break; case 1: undraw_sprite_r_8x8(triangle,16,32); break; case 2: undraw_sprite_r_8x8(triangle,16,52); break; case 3: undraw_sprite_r_8x8(triangle,16,72); break; } selection++; if(selection>3) selection = 0; switch(selection) { case 0: draw_sprite_8x8(triangle,16,12); break; case 1: draw_sprite_8x8(triangle,16,32); break; case 2: draw_sprite_8x8(triangle,16,52); break; case 3: draw_sprite_8x8(triangle,16,72); break; } pushflag = 0; } if (BUTTON_B) { // B PRESSED TO BEGIN srand(count); // seeding rand() based on count note = 0; // music starts from beginning sc = 0; // score starts at 0 if (selection == 0){ // dodgeball /* initializing specific variables */ gameState = Dodge_Alive; currBG = 1; matrixtime = 0; moveState = 0; x = DODGE_START_X; y = DODGE_START_Y; b1_x = (rand() % 61) + 30; // ball starts at random x b2_x = (rand() % 61) + 30; b1_y = 0; b2_y = 0; spb1 = (rand() % 7) - 3; // with random direction spb2 = (rand() % 7) - 3; sprintf(word,"GET READY"); LCD_say(word,12,92); delay_ms(1500); // wait about a second before starting game // draw bg on screen draw_bg(); } else if (selection == 1){ // tunnel gameState = Tunnel_Alive; currBG = 2; tL[0] = 28; //starting left wall tR[0] = 92; for(i=1;i<10;i++) { tL[i] = tL[i-1]; tR[i] = tR[i-1]; } tunW = 64; x = TUNNEL_START_X; tt = 0; step = 0; sprintf(word,"GET READY"); LCD_say(word,12,92); delay_ms(1500); draw_bg(); } else if (selection == 2){ // paint gameState = Paint_Alive; x = PAINT_START_X; y = PAINT_START_Y; curr_color = 0; sprintf(word,"GET READY"); LCD_say(word,12,92); delay_ms(1500); draw_topbar(); draw_canvas(); sprintf(word,"EXIT"); LCD_say(word,4,4); } else if (selection == 3 && pushflag == 1){ // toggle sound if(sound==1) { LCD_unsay_r(word_soundon,28,72); sound = 0; LCD_say(word_soundoff,28,72); } else { LCD_unsay_r(word_soundoff,28,72); sound = 1; LCD_say(word_soundon,28,72); } } pushflag = 0; } break; case Dodge_Alive: if((x < DODGE_RIGHT) && (MoveX < DODGE_TILT_R2)) { // move right moveState = DODGE_MR; erase_15x16(x,y); x = x+6; } else if((x < DODGE_RIGHT) && (MoveX < DODGE_TILT_R)) { // move right less moveState = DODGE_MR; erase_15x16(x,y); x = x+3; } else if((x > DODGE_LEFT) && (MoveX > DODGE_TILT_L2)) { // move left moveState = DODGE_ML; erase_15x16(x,y); x = x-6; } else if((x > DODGE_LEFT) && (MoveX > DODGE_TILT_L)) { // move left less moveState = DODGE_ML; erase_15x16(x,y); x = x-3; } else if((y > DODGE_TOP) && (MoveY < DODGE_TILT_U2)) { // move up moveState = DODGE_MU; erase_15x16(x,y); y = y-6; } else if((y > DODGE_TOP) && (MoveY < DODGE_TILT_U)) { // move up less moveState = DODGE_MU; erase_15x16(x,y); y = y-3; } else if((y < DODGE_BOTTOM) && (MoveY > DODGE_TILT_D2)) { // move down moveState = DODGE_MD; erase_15x16(x,y); y = y+6; } else if((y < DODGE_BOTTOM) && (MoveY > DODGE_TILT_D)) { // move down less moveState = DODGE_MD; erase_15x16(x,y); y = y+3; } erase_8x8(b1_x,b1_y); // erase previous ball erase_8x8(b2_x,b2_y); if (BUTTON_B) { // matrix time b1_y=b1_y+1; // move ball down b1_x=b1_x+spb1; // move ball sideways b2_y=b2_y+1; // move ball down b2_x=b2_x+spb2; // move ball sideways } else { // normal ball movement b1_y=b1_y+6; // move ball down b1_x=b1_x+spb1; // move ball sideways b2_y=b2_y+6; // move ball down b2_x=b2_x+spb2; // move ball sideways } // if ball reaches bottom or side, start it at top again if(b1_y>DODGE_MAX || b1_xDODGE_RIGHT_B) { b1_y = 0; b1_x = (rand() % 61) + 30; if(b1_x < x) { spb1 = (rand() % 4); } else { spb1 = (rand() % 4) - 3; } sc++; // increment score by one } if(b2_y>DODGE_MAX || b2_xDODGE_RIGHT_B) { b2_y = 0; b2_x = (rand() % 61) + 30; if(b2_x < x) { spb2 = (rand() % 4); } else { spb2 = (rand() % 4) - 3; } sc++; // increment score by one } draw_nerd(x,y); // draw the character draw_sprite_8x8(ball,b1_x,b1_y); // draw the ball draw_sprite_8x8(ball,b2_x,b2_y); delay_ms(40); // collision detection with the ball if( ( (b1_y<=(y+16)) && (y<=(b1_y+7)) && (x<=(b1_x+7)) && (b1_x<=(x+16)) ) || ( (b2_y<=(y+16)) && (y<=(b2_y+7)) && (x<=(b2_x+7)) && (b2_x<=(x+16)) ) ) { gameState = Dodge_Dead; // game over if (hsc_dodge < sc) hsc_dodge = sc; delay_ms(500); gen_color(); fill_screen(r_color); // fill screen black sprintf(word,"SCORE %d",sc); LCD_say(word,6,20); sprintf(word,"HIGH %d",hsc_dodge); LCD_say(word,6,40); sprintf(word,"PRESS L"); LCD_say(word,6,60); sprintf(word,"TO RESTART"); LCD_say(word,6,80); } break; case Dodge_Dead: // reset back to menu if (pushflag && BUTTON_A){ gen_color(); fill_screen(r_color); gameState = Menu; // starting menu selection = 0; LCD_say(word_dodge,28,12); LCD_say(word_tunnel,28,32); LCD_say(word_paint,28,52); if(sound==1) LCD_say(word_soundon,28,72); else LCD_say(word_soundoff,28,72); draw_sprite_8x8(triangle,16,12); pushflag = 0; } break; case Tunnel_Alive: /* erase ship */ EShip(x,TUNNEL_RAIL); if (MoveX < TUNNEL_TILT_R) { // move right x = x + 4; } else if (MoveX > TUNNEL_TILT_L) { // move left x = x - 4; } /* draw ship */ DShip(x,TUNNEL_RAIL); step = ~step; // change state /* draw wall */ if (tt >= 10 && tunW>16) { tunW = tunW - 4; //tunnel shrinks every 100 spaces tt = 0; dir = 1; step = 1; } else if (tL[0] <= TUNNEL_LEFT) { dir = 1; //left boundary step = 1; } else if (tR[0] >= TUNNEL_RIGHT) { dir = 0; //right boundary step = 1; } else if (step) { dir = rand()%2; } if (dir) tL[0] = tL[0] + 4; //left wall of tunnel moves randomly else tL[0] = tL[0] - 4; tR[0] = tL[0] + tunW; //right wall of tunnel is always a width apart from the left wall for (i = 9; i > 0; i--) { EWall(i,tL[i]); EWall(i,tR[i]); tL[i] = tL[i-1]; tR[i] = tR[i-1]; DWall(i,tL[i]); DWall(i,tR[i]); } tt++; delay_ms(50); /* collision detection */ if (((x) < tL[9]+5) || (tR[9] <= (x+13))) { gameState = Tunnel_Dead; if (hsc_tunnel < sc) hsc_tunnel = sc; delay_ms(300); gen_color(); fill_screen(r_color); // fill screen black sprintf(word,"SCORE %d",sc); LCD_say(word,6,20); sprintf(word,"HIGH %d",hsc_tunnel); LCD_say(word,6,40); sprintf(word,"PRESS L"); LCD_say(word,6,60); sprintf(word,"TO RESTART"); LCD_say(word,6,80); } sc++; break; case Tunnel_Dead: // reset back to menu if (pushflag && BUTTON_A){ gen_color(); fill_screen(r_color); gameState = Menu; // starting menu selection = 0; LCD_say(word_dodge,28,12); LCD_say(word_tunnel,28,32); LCD_say(word_paint,28,52); if(sound==1) LCD_say(word_soundon,28,72); else LCD_say(word_soundoff,28,72); draw_sprite_8x8(triangle,16,12); pushflag = 0; } break; case Paint_Alive: if((x < PAINT_RIGHT) && (MoveX < PAINT_TILT_R)) { // move right x = x+1; } else if((x > PAINT_LEFT) && (MoveX > PAINT_TILT_L)) { // move left x = x-1; } else if((y > PAINT_TOP) && (MoveY < PAINT_TILT_U)) { // move up y = y-1; } else if((y < PAINT_BOTTOM) && (MoveY > PAINT_TILT_D)) { // move down y = y+1; } if(BUTTON_A && change_color) { // changing color curr_color = curr_color+1; if(curr_color>7) curr_color = 0; change_color = 0; } else if(~BUTTON_A) change_color = 1; if(BUTTON_B) { if(y>=6) { // painting paint[y-6][x] = colors[curr_color]; } else { // exiting gameState = Paint_Dead; delay_ms(1500); } } if(y<6) { draw_topbar(); LCD_say(word,4,4); } else { canvas_state = ~canvas_state; if(canvas_state) draw_canvas(); } draw_cursor(x,y); if(y<6) delay_ms(50); break; case Paint_Dead: gen_color(); fill_screen(r_color); gameState = Menu; // starting menu // starting menu selection = 0; LCD_say(word_dodge,28,12); LCD_say(word_tunnel,28,32); LCD_say(word_paint,28,52); if(sound==1) LCD_say(word_soundon,28,72); else LCD_say(word_soundoff,28,72); draw_sprite_8x8(triangle,16,12); break; } } } void initialize(void) { int i = 0; // Buttons on PINC PORTC.2 = 1; PORTC.3 = 1; // light LED when powered on DDRD.7 = 1; PORTD.7 = 0; PIND.7 = 0; //use OC0 (pin B.3) for music DDRB.3 = 1 ; //init the A to D converter //channel zero/ left adj /EXTERNAL Aref //!!!CONNECT Aref jumper!!!! ADMUX = 0b00100000; //enable ADC and set prescaler to 1/128*16MHz=125,000 //and clear interupt enable //and start a conversion ADCSR = 0b11000111; //init the UART UCSRB = 0x18; UBRRL = 103; // timer 0 TIMSK = 0b00000001; TCCR0 = 0b00000100; // TCCR2 = 0b00000100; // TCCR2 = 0b01011110; // I don't get this // basic variables time=0; matrixtime = 0; sc = 0; #asm sei #endasm SPIDDR=(1<800 because of faster crystal (4MHz->16MHz) for (i = 0; i < 250; i++){ // this loop adjusts the contrast, change the number of iterations to get sendCMD(0xd6); // desired contrast. This might be different for individual LCDs delay_ms(8); // same as above, 2->8 } }