Sei sulla pagina 1di 17

/* 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 #define #define #define #define #define SPIPORT PORTC SPIDDR DDRC CS 4 CLK 7 SDA 5 RESET 6

//################# #include #include #include #include #include #include #include <mega32.h> <io.h> <delay.h> <stdio.h> <stdlib.h> <math.h> <spi.h>

#define cbi(reg, bit) (reg&=~(1<<bit)) #define sbi(reg, bit) (reg|= (1<<bit))

#define #define #define #define #define #define #define #define

CS0 cbi(SPIPORT,CS); CS1 sbi(SPIPORT,CS); CLK0 cbi(SPIPORT,CLK); CLK1 sbi(SPIPORT,CLK); SDA0 cbi(SPIPORT,SDA); SDA1 sbi(SPIPORT,SDA); RESET0 cbi(SPIPORT,RESET); RESET1 sbi(SPIPORT,RESET);

#define byte unsigned char //byte n=0; //byte s1,s2; //byte r,g,b; // Epson S1D15G10 Command Set #define DISON 0xaf #define DISOFF 0xae #define DISNOR 0xa6 #define DISINV 0xa7 #define COMSCN 0xbb #define DISCTL 0xca #define SLPIN 0x95 #define SLPOUT 0x94 #define PASET 0x75 #define CASET 0x15 #define DATCTL 0xbc #define RGBSET8 0xce #define RAMWR 0x5c #define RAMRD 0x5d #define PTLIN 0xa8 #define PTLOUT 0xa9 #define RMWIN 0xe0 #define RMWOUT 0xee #define ASCSET 0xaa #define SCSTART 0xab #define OSCON 0xd1 #define OSCOFF 0xd2 #define PWRCTR 0x20 #define VOLCTR 0x81 #define VOLUP 0xd6 #define VOLDOWN 0xd7 #define TMPGRD 0x82 #define EPCTIN 0xcd #define EPCOUT 0xcc #define EPMWR 0xfc #define EPMRD 0xfd #define EPSRRD1 0x7c #define EPSRRD2 0x7d #define NOP 0x25 /******** Timing ********/ #define countMS 62 // 1 mSec /******** Useful colors ********/ #define lightgray 0x6E #define brown 137

#define #define #define #define #define #define #define #define #define #define #define #define #define

yellow 252 blue 7 red 128 white 255 black 0 orange 236 brightred 224 lightpurple 227 darkpurple 34 teal 31 aqua 30 green 28 trans 1

/******** States ********/ #define Menu 0 #define Dodge_Alive 1 #define Dodge_Dead 2 #define Tunnel_Alive 3 #define Tunnel_Dead 4 #define Paint_Alive 5 #define Paint_Dead 6 unsigned char gameState, currBG, selection, moveState, sound; /******** Buttons ********/ #define BUTTON_B ~PINC.2 //&0x02 #define BUTTON_A ~PINC.3 //&0x04 /******** Game-specific defines ********/ #define DODGE_TOP 72 #define DODGE_BOTTOM 112 #define DODGE_LEFT 10 #define DODGE_RIGHT 110 #define DODGE_MAX 120 #define DODGE_LEFT_B 4 #define DODGE_RIGHT_B 120 #define DODGE_TILT_L 80 #define DODGE_TILT_R 70 #define DODGE_TILT_U 70 #define DODGE_TILT_D 85 #define DODGE_TILT_L2 90 #define DODGE_TILT_R2 60 #define DODGE_TILT_U2 60 #define DODGE_TILT_D2 95 #define DODGE_START_X 56 #define DODGE_START_Y 100 #define DODGE_ML 2 #define DODGE_MR 3 #define DODGE_MD 0 #define DODGE_MU 1 #define TUNNEL_LEFT 3 #define TUNNEL_RIGHT 125 #define TUNNEL_RAIL 108 #define TUNNEL_TILT_L 80

#define #define #define #define #define #define #define #define #define #define #define #define

TUNNEL_TILT_R 70 TUNNEL_START_X 60 PAINT_TILT_L 80 PAINT_TILT_R 70 PAINT_TILT_U 70 PAINT_TILT_D 85 PAINT_LEFT 0 PAINT_RIGHT 25 PAINT_TOP 0 PAINT_BOTTOM 25 PAINT_START_X 0 PAINT_START_Y 6

/******** de-bouncing ********/ #define NoPush 0 #define Maybe 1 #define Pushed 2 #define MaybeNot 3 unsigned char pushState, pushflag, key; /******** sound ********/ #define maxDodgeSong 143 #define maxTunnelSong 95 #define maxPaintSong 15 unsigned char note, musicT; // random color for fill_screen unsigned char r_color; // index to array for selecting paint color unsigned char curr_color; #include #include #include #include #include #include #include "basic.c"; "fonts.c"; "dodgeball.c"; "tunnel.c"; "display.c"; "paint.c"; "music.c";

// score variables eeprom unsigned int hsc_dodge, hsc_tunnel; unsigned int sc = 0; // user score // strings unsigned char unsigned char unsigned char unsigned char unsigned char unsigned char word[16]; // string for writing word_dodge[16] = "DODGE"; word_tunnel[16] = "TUNNEL"; word_paint[16] = "PAINT"; word_soundon[16] = "SND ON"; word_soundoff[16] = "SND OFF";

// counts 62 to get 1 mSec unsigned char count; // mSec timer unsigned int time;

// matrix timer unsigned int matrixtime; // timer for counting milliseconds interrupt [TIM0_OVF] void timer(void) { //generate rising amplitude // 62 counts is about 1 mSec count--; if (0 == count) { count=countMS; time++; } switch(pushState) // debouncing logic { case NoPush: if(BUTTON_A^BUTTON_B) { pushState = Maybe; } break; case Maybe: if(BUTTON_A^BUTTON_B) { pushState = Pushed; pushflag = 1; if(BUTTON_A) key = 1; else key = 2; } else pushState = NoPush; break; case Pushed: if(BUTTON_A^BUTTON_B) pushState = Pushed; else pushState = MaybeNot; break; case MaybeNot: if(BUTTON_A^BUTTON_B) pushState = Pushed; else pushState = NoPush; break; } } void initialize(void); void main (void) { /* variables for all games */ unsigned char Ain; // ADC variable - input from accelerometer unsigned char x, y; unsigned char MoveX, MoveY; unsigned char WhichMove = 0; // check x or y unsigned char i; // for all games /* variables for dodgeball unsigned char b1_x = 0; // unsigned char b2_x = 0; // unsigned char b1_y = 0; // unsigned char b2_y = 0; // char spb1 = 0; // x motion */ x coord for x coord for y coord for y coord for for ball 1 ball ball ball ball 1 2 1 2

char spb2 = 0; // x motion for ball 2 /* variables for tunnel */ unsigned char tL[10], tR[10]; unsigned char tunW = 64; //width of tunnel unsigned char tt = 0; // counter to shrink tunnel unsigned char step = 0; // two state for random direction char dir = 0; /* variables for paint */ unsigned char canvas_state, change_color; initialize(); // starting everything up //init musical scale note = 0; musicT = 0; gameState = Menu; sound = 1; sprintf(word,"WEEBOY"); LCD_say(word,17,59); delay_ms(2000); gen_color(); fill_screen(r_color); // starting menu selection = 0; LCD_say(word_dodge,28,12); LCD_say(word_tunnel,28,32); LCD_say(word_paint,28,52); LCD_say(word_soundon,28,72); draw_sprite_8x8(triangle,16,12); while(1){ /* code always running regardless of current state */ /* music and ADC code is mixed together here */ if(gameState==Dodge_Alive || gameState==Paint_Alive) // 1 second { // alternate between sampling x and y // on accelerometer to ADC if (WhichMove == 0) { ADMUX = 0b01100000; //get the sample from accelerometer Ain = ADCH; //start another conversion ADCSR.6=1; MoveY = Ain; WhichMove = 1; } else { ADMUX = 0b01100001; //get the sample from accelerometer Ain = ADCH;

//start another conversion ADCSR.6=1; MoveX = Ain; WhichMove = 0; } if(sound==1) { if(musicT>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); case 1: undraw_sprite_r_8x8(triangle,16,32); case 2: undraw_sprite_r_8x8(triangle,16,52); case 3: undraw_sprite_r_8x8(triangle,16,72); } selection++; break; break; break; break;

if(selection>3) selection = 0; switch(selection) { case 0: draw_sprite_8x8(triangle,16,12); case 1: draw_sprite_8x8(triangle,16,32); case 2: draw_sprite_8x8(triangle,16,52); case 3: draw_sprite_8x8(triangle,16,72); } 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; break; break; break; break;

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 les s 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 les s 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_x<DODGE_LEFT_B || b1_x>DODGE_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_x<DODGE_LEFT_B || b2_x>DODGE_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; else tL[0] = tL[0] - 4; tR[0] = tL[0] + tunW; 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]); //left wall of tunnel moves randomly //right wall of tunnel is always a width

} 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<<SDA)|(1<<CLK)|(1<<CS)|(1<<RESET); //Port-Direction Setup CS0 SDA0 CLK1 RESET1 RESET0 RESET1 CLK1 SDA1 CLK1 delay_ms(10); //Software Reset sendCMD(DISCTL); //added sendData(0x03); sendData(32); sendData(12); sendData(0x00); sendCMD(0xbb); // comscn sendData(0x01); sendCMD(0xd1); // oscon sendCMD(0x94); // sleep out sendCMD(0x81); // electronic volume, this is kinda contrast/brightness sendData(5);//ff); // this might be different for individual LCDs sendData(0x01);//01); // sendCMD(0x20); // power ctrl sendData(0x0f); //everything on, no external reference resistors delay_ms(100); sendCMD(0xa7); // display mode sendCMD(0xbc); // datctl sendData(0x00); sendData(0); sendData(0x01); sendData(0x00); sendCMD(0xce); // setup color lookup table // color table //RED sendData(0); sendData(2); sendData(4); sendData(6); sendData(8); sendData(10); sendData(12); sendData(15);

// GREEN sendData(0); sendData(2); sendData(4); sendData(6); sendData(8); sendData(10); sendData(12); sendData(15); //BLUE sendData(0); sendData(4); sendData(9); sendData(15); sendCMD(NOP); // nop sendCMD(PASET); sendData(2); sendData(131); sendCMD(CASET); sendData(0); sendData(131); sendCMD(RAMWR); gen_color(); fill_screen(r_color); sendCMD(DISON); // fills screen black // page start/end ram // for some reason starts at 2 // column start/end ram

// write some stuff (background)

// display on

delay_ms(800); // had to go 200->800 because of faster crystal (4MHz->16MHz) for (i = 0; i < 250; i++){ // this loop adjusts the contrast, change the num ber of iterations to get sendCMD(0xd6); // desired contrast. This might be different for individual LCDs delay_ms(8); // same as above, 2->8 } }

Potrebbero piacerti anche