DotMatrixPong 1.0

/home/christian/Desktop/C_Sachen/AVR/pms/pong.c

gehe zur Dokumentation dieser Datei
00001 #ifndef F_CPU
00002 
00003 #define F_CPU 1000000
00004 #endif
00005 
00007 #define SCK PB4
00008 
00009 #define OCK PB3
00010 
00011 #define DS PB1
00012 
00014 #define STATIC 0
00015 
00016 #define SCROLLING 1
00017 
00018 #include <avr/io.h>
00019 #include <util/delay.h>
00020 #include <avr/interrupt.h>
00021 #include <avr/pgmspace.h>
00022 #include <inttypes.h>
00023 
00029 void clock_serial();
00030 void clock_output();
00031 void shift_high();
00032 void shift_low();
00033 void output(uint8_t*,uint8_t);
00034 void matrix_output();
00035 void matrix_screen_pixel(uint32_t);
00036 
00037 void adc_init();
00038 void get_adcval(uint16_t *);
00039 uint8_t getkey();
00040 
00041 void timer_init();
00042 
00043 void clear_screen();
00044 void start_game();
00045 void game_failed();
00046 void output_game();
00047 void cursor_a_down();
00048 void cursor_a_up();
00049 void cursor_b_down();
00050 void cursor_b_up();
00051 
00052 void next_r_ball();
00053 uint8_t check_ball_coll();
00054 
00055 uint32_t rand();
00056 
00057 void output_text(char*,uint8_t);
00058 
00060  uint8_t friendly_sm[5] PROGMEM = {0x0C,0x12,0x0,0x12,0x0};
00062  uint8_t unfriendly_sm[5] PROGMEM = {0x12,0x0C,0x0,0x12,0x0};
00064  uint8_t ansi[38][5] PROGMEM = {
00065                             {0x12,0x12,0x1E,0x12,0x0C}, //A
00066                             {0x0E,0x12,0x0E,0x12,0x0E}, //B
00067                             {0x0C,0x02,0x02,0x02,0x0C}, //C
00068                             {0x0E,0x12,0x12,0x12,0x0E}, //D
00069                             {0x0E,0x02,0x0E,0x02,0x0E}, //E
00070                             {0x0E,0x02,0x0E,0x02,0x02}, //F
00071                             {0x1C,0x12,0x1A,0x02,0x1C}, //G
00072                             {0x12,0x12,0x1E,0x12,0x12}, //H
00073                             {0x0E,0x04,0x04,0x04,0x0E}, //I
00074                             {0x06,0x08,0x08,0x08,0x0E}, //J
00075                             {0x12,0x0A,0x06,0x0A,0x12}, //K
00076                             {0x0E,0x02,0x02,0x02,0x02}, //L
00077                             {0x12,0x12,0x12,0x1E,0x12}, //M 
00078                             {0x22,0x32,0x2A,0x26,0x22}, //N
00079                             {0x0C,0x12,0x12,0x12,0x0C}, //O
00080                             {0x04,0x04,0x1C,0x14,0x0C}, //P
00081                             {0x14,0x0A,0x12,0x12,0x0C}, //Q
00082                             {0x14,0x14,0x0C,0x14,0x0C}, //R
00083                             {0x1C,0x10,0x08,0x04,0x1C}, //S
00084                             {0x08,0x08,0x08,0x08,0x1C}, //T
00085                             {0x1C,0x14,0x14,0x14,0x14}, //U
00086                             {0x08,0x14,0x14,0x14,0x14}, //V
00087                             {0x14,0x2A,0x2A,0x22,0x22}, //W
00088                             {0x22,0x14,0x08,0x14,0x22}, //X
00089                             {0x08,0x08,0x08,0x14,0x22}, //Y
00090                             {0x1E,0x04,0x08,0x10,0x1E}, //Z
00091                             {0x0E,0x0A,0x0A,0x0A,0x0E}, //0
00092                             {0x1C,0x08,0x08,0x0C,0x08}, //1
00093                             {0x1E,0x04,0x08,0x12,0x0C}, //2
00094                             {0x0C,0x12,0x08,0x10,0x1E}, //3
00095                             {0x08,0x08,0x0E,0x0A,0x0A}, //4
00096                             {0x0E,0x08,0x0E,0x02,0x0E}, //5
00097                             {0x0E,0x0A,0x0E,0x02,0x0E}, //6
00098                             {0x08,0x08,0x0A,0x0A,0x0E}, //7
00099                             {0x0E,0x0A,0x0E,0x0A,0x0E}, //8
00100                             {0x0E,0x08,0x0E,0x0A,0x0E}, //9
00101                             {0x00,0x40,0x00,0x40,0x00}, //:
00102                             {0x00,0x00,0x00,0x00,0x00}}; //
00103                             
00104 
00106  uint8_t cursor_a[5] = {0x0,0x1,0x1,0x0,0x0};
00108  uint8_t cursor_b[5] = {0x0,0x00,0x40,0x40,0x00};
00110  uint8_t ball[5] = {0x0,0x0,0x4,0x0,0x0};
00111 
00113  uint8_t screen_buffer_first[5];
00115  uint8_t screen_buffer_second[5];
00116 
00118 volatile uint8_t ball_dir = 0;
00120 volatile uint16_t ball_timer = 0;
00122  uint8_t rand_timer = 0;
00124  uint8_t game_running = 0;
00126 volatile uint8_t game_failed_var = 0x0;
00128 uint8_t points_a = 0;
00130 uint8_t points_b = 0;
00131 
00133 
00146 int main() {
00147   uint8_t key = 0;
00148   DDRB = (1 << PB0) | (1 << PB1)| (1 << PB3) | (1 << PB4);
00149   
00150   adc_init();
00151   timer_init();
00152   sei();
00153   
00154   clear_screen();
00155   output_text("PONG",SCROLLING);
00156   start_game();
00157 
00158   while(1) {
00159    key = getkey();
00160    if(game_failed_var == 0x1 || game_failed_var == 0x2) game_failed();
00161    switch(key) {
00162      case 1: cursor_a_down(); break;
00163      case 2: cursor_a_up(); break;
00164      case 3: cursor_b_down(); break;
00165      case 4: cursor_b_up(); break;
00166      default: break;
00167    }
00168   }
00169 return 0;
00170 }
00171 
00173 
00181 void clock_serial() {
00182   PORTB |= (1 << SCK);
00183   PORTB &= ~(1 << SCK);
00184 }
00185 
00187 
00194 void clock_output() {
00195   PORTB |= (1 << OCK);
00196   PORTB &= ~(1 << OCK);
00197 }
00198 
00200 
00206 void shift_high() {
00207   PORTB |= (1 << DS);
00208   clock_serial();
00209 }
00210 
00212 
00218 void shift_low() {
00219   PORTB &= ~(1 << DS);
00220   clock_serial();
00221 }
00222 
00224 
00232 void output(uint8_t* in, uint8_t screen) {
00233  uint8_t i = 0;
00234  switch(screen) {
00235    case 1: for(i = 0; i < 5; i++) screen_buffer_first[i] = in[i]; break;
00236    case 2: for(i = 0; i < 5; i++) screen_buffer_second[i] = in[i]; break;
00237    default: break;
00238  }
00239 }
00240 
00242 
00256 void matrix_output() {
00257   uint8_t k,i,j,col,row = 0;
00258   uint32_t out = 0;
00259       
00260   for(k = 0; k < 2; k++){ //F&uuml;r beide Punktmatrix
00261     for(i = 0; i < 5; i++) { //Jede Spalte muss auf Punkte &uuml;berpr&uuml;ft werden
00262           if(k == 0) row = screen_buffer_second[i]; //Erst die rechte Punktmatrix
00263           else row = screen_buffer_first[i]; //Dann die linke Punktmatrix
00264           for(j = 0; j < 7; j++) { //Dann wird jede Zeile auf ein Punkt &uuml;berpr&uuml;ft
00265             if(row & 0x01) { //Wurde einer gefunden,
00266               out = (1 << j); //muss die jeweilige Zeile aktiviert werden
00267               out <<=5; //(Die Zeilen stehen in der Ausgabe 5 Bits weiter
00268               out |= (1 << i); //und es muss die jeweilige Spalte aktiviert werden
00269               out <<=1; //Welche erst ab Bit 1 anfangen
00270               if(k == 1) out <<= 16; //F&uuml;r den linken Bildschirm muss das Ganze 16 Bits verschoben werden (aufgrund der Schieberegister)
00271               matrix_screen_pixel(out);
00272             }
00273             row >>=1; // Das n&auml;chste Bit wird &uuml;berpr&uuml;ft
00274           }
00275     }
00276   }
00277 }
00278 
00280 
00291 void matrix_screen_pixel(uint32_t input) {
00292   uint8_t i = 0;
00293  
00294     for(i = 0; i < 32; i++) {
00295         if((i < 26 && i > 16) || (i < 10)) {
00296           if(input & 0x80000000) shift_low();
00297           else shift_high();
00298         }
00299         else {
00300           if(input & 0x80000000) shift_high();
00301           else shift_low();
00302         }
00303         input <<= 1;
00304     }
00305     clock_output();
00306 
00307   PORTB &= ~(1 << DS);
00308   PORTB &= ~(1 << SCK);
00309   PORTB &= ~(1 << OCK);
00310   
00311 }
00312 
00314 
00327 void adc_init() {
00328     uint16_t trash;
00329     ADMUX =  (1 << MUX0); //PB2
00330     DIDR0 |= (1<<ADC0D); //PB2  (ADC0)
00331     ADCSRA = (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN); //Division 8
00332     get_adcval(&trash); //First Conversion
00333 }
00334 
00336 
00342 void adc_start() { 
00343     ADCSRA |= (1 << ADSC);
00344 }
00345 
00347 
00356 void get_adcval(uint16_t *val) {
00357   adc_start();
00358   while(ADCSRA & (1 << ADSC));
00359   *val = ADCW;
00360 }
00361 
00363 
00374 uint8_t getkey() {
00375   uint8_t key = 0;
00376   uint16_t adc_wert = 0;
00377   uint16_t zaehl = 0;  
00378   while(1) { 
00379         get_adcval(&adc_wert);
00380         zaehl++;
00381         if(adc_wert <= 50) { //Taste 4 von links
00382             key = 4;
00383             break;
00384         }
00385         else if(adc_wert <= 280 ) { //Taste 3 von links
00386             key = 3;
00387             break;
00388         }
00389         else if(adc_wert <= 540) { //Taste 2 von links
00390             key = 2;
00391             break;
00392         }// bis hier
00393         else if (adc_wert <= 790){ //Taste 1 von links
00394             key = 1;
00395             break;
00396         }  
00397         
00398         else if(adc_wert <= 1024) { //keine Taste
00399             key = 0;   
00400         }
00401         if(zaehl >= 10) break;
00402  }
00403  rand_timer += zaehl+key;
00404  return key;
00405 }
00406 
00408 
00416 void timer_init() {
00417   TIMSK |= (1 << TOIE0);
00418   TCCR0B |= (1 << CS01); //Prescaler 8
00419   TCNT0 = 0x0;  //Startwert 1
00420 }
00421 
00423 
00431 ISR(TIMER0_OVF_vect) { //Bildschirmausgabe
00432   ball_timer++;
00433   if(ball_timer % 2 && !(game_running)) return; //Bei der m&ouml;glichen Textausgabe darf nur jedes zweite Mal der Interrupt vollst&auml;ndig ablaufen
00434   if(game_running) output_game();
00435   matrix_output();
00436   if((ball_timer % 10) == 0) rand_timer++;
00437   if(ball_timer >= 100  && game_running) {
00438     ball_timer = 0;
00439     next_r_ball();
00440   }
00441 }
00442 
00444 
00450 void clear_screen() {
00451   uint8_t i = 0;
00452   for(i = 0; i < 5; i++) {
00453     screen_buffer_second[i]= 0x0; 
00454     screen_buffer_first[i] = 0x0;
00455   }
00456 }
00457 
00459 
00468 void start_game() {
00469   uint8_t i = 0;
00470   game_failed_var = 0x0;
00471   for(i = 0; i < 5; i++) {
00472     cursor_a[i] = 0x0;
00473     cursor_b[i] = 0x0;
00474   }
00475   cursor_a[1] = 0x1;
00476   cursor_a[2] = 0x1;
00477   cursor_b[2] = 0x40;
00478   cursor_b[3] = 0x40;
00479   for(i = 0; i < 5; i++) ball[i]= 0x0;
00480   ball[2]= 0x4;
00481   ball_dir = 0;
00482   game_running = 1;
00483   output_game(); 
00484 }
00485 
00487 
00494 void output_game() {
00495   uint8_t i = 0;
00496   clear_screen();
00497   for(i = 0; i < 5; i++) screen_buffer_second[i] |= cursor_a[i] | cursor_b[i] | ball[i];
00498 }
00499 
00501 
00509 void cursor_a_down() {
00510  uint8_t i = 0;
00511  if(cursor_a[0]== 0x01) return;
00512  else {
00513   for(i = 0; i < 4; i++) cursor_a[i]= cursor_a[i+1];
00514   cursor_a[4] = 0x0;
00515  }
00516 }
00517 
00519 
00527 void cursor_a_up() {
00528  uint8_t i = 0;
00529  if(cursor_a[4]== 0x01) return;
00530  else {
00531   for(i = 4; i > 0; i--) cursor_a[i]= cursor_a[i-1];
00532   cursor_a[0]= 0x0;
00533  }
00534 }
00535 
00537 
00545 void cursor_b_down() {
00546  uint8_t i = 0;
00547  if(cursor_b[0] == 0x40) return;
00548  else {
00549   for(i = 0; i < 4; i++) cursor_b[i]= cursor_b[i+1];
00550   cursor_b[4] = 0x0;
00551  }
00552 }
00553 
00555 
00563 void cursor_b_up() {
00564  uint8_t i = 0;
00565  if(cursor_b[4] == 0x40) return;
00566  else {
00567   for(i = 4; i > 0; i--) cursor_b[i] = cursor_b[i-1];
00568   cursor_b[0] = 0x0;
00569  }
00570 }
00571 
00573 
00587 void next_r_ball() {
00588   uint8_t col = 5;
00589   uint8_t i = 0;
00590   
00591   i = check_ball_coll();
00592   
00593   if(i != 0) {  
00594       if(i % 2) {  //Rechte Seite aufgeschlagen
00595         i = rand() % 4;
00596         if(i == 1) i = 0;
00597       } 
00598       else {    //Linke Seite aufgeschlagen
00599         i = rand() % 4;
00600         if(i == 0 || i == 1) i = 1;
00601         else i += 2;
00602       }
00603         ball_dir = i;
00604   }
00605   
00606   for(i = 0; i < 5; i++) if(ball[i] != 0) col = i; 
00607 
00608   
00609   switch(ball_dir) {
00610     
00611     case 0x0: //links
00612       ball[col] <<= 1;
00613       break;
00614     case 0x1: //rechts
00615       ball[col] >>= 1;
00616       break;
00617     case 0x2: //links-hoch
00618 
00619       if(col == 4) { ball_dir = 3; break; }
00620       ball[col+1] = ball[col] << 1;
00621       ball[col] = 0x0;
00622       col++;
00623       break;
00624     case 0x3: //links-runter
00625       if(col == 0) { ball_dir = 2; break; }
00626       ball[col-1] = ball[col] << 1;
00627       ball[col] = 0x0;
00628       col--;
00629       break;
00630     case 0x4: //rechts-hoch
00631       if(col == 4) { ball_dir = 5; break; }
00632       ball[col+1] = ball[col] >> 1;
00633       ball[col] = 0x0;
00634       col++;
00635       break;
00636     case 0x5: //rechts-runter
00637       if(col == 0) { ball_dir = 4; break; }
00638       ball[col-1] = ball[col] >> 1;
00639       ball[col] = 0x0;
00640       col--;
00641       break;
00642     default:
00643       break;
00644       
00645   }
00646     if(ball[col] == 0x0 && game_failed_var == 0) game_failed_var = 0x2;   //Bei A-Spieler raus
00647     if(ball[col] >= 0x80 && game_failed_var == 0) game_failed_var = 0x1;  //Bei B-Spieler raus
00648 
00649   return;
00650     
00651 }
00652 
00653 
00655 
00664 uint8_t check_ball_coll() {
00665   uint8_t temp_coll[5] = {0x0,0x0,0x0,0x0,0x0};
00666   uint8_t col = 0;
00667   uint8_t i = 0;
00668   uint8_t col_point = 0;
00669   
00670   for(i = 0; i < 5; i++) { 
00671     temp_coll[i] |= cursor_a[i] | cursor_b[i]; 
00672     if(ball[i] != 0) col = i; 
00673   }
00674   
00675   if( (temp_coll[col] << 1 ) & ball[col] && col == 2) col_point = 1;//Rechte Seite
00676   if( (temp_coll[col] >> 1 ) & ball[col] && col == 2) col_point = 2;//Linke Seite
00677   if( (temp_coll[col] << 1 ) & ball[col] && col < 2) col_point = 3; //Rechte Seite
00678   if( (temp_coll[col] >> 1 ) & ball[col] && col > 2) col_point = 4; //Linke Seite
00679   if( (temp_coll[col] << 1 ) & ball[col] && col < 2) col_point = 5; //Rechte Seite
00680   if( (temp_coll[col] >> 1 ) & ball[col] && col > 2) col_point = 6; //Linke Seite
00681   
00682   return col_point;
00683 }
00684 
00685 
00687 
00696 void game_failed() {
00697   uint8_t temp_show[5] = {0,0,0,0,0};
00698   uint8_t i = 0;
00699   
00700   game_running = 0;
00701   clear_screen();
00702   
00703   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&unfriendly_sm[i]);
00704   output(temp_show,2);
00705   _delay_ms(100);
00706   clear_screen();
00707   
00708   switch(game_failed_var) {
00709     case 0x1: points_a++; break; //A hat ein Punkt gemacht
00710     case 0x2: points_b++; break; //B hat ein Punkt gemacht
00711     default: break; 
00712   }
00713 
00714   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[game_failed_var % 2][i]);
00715 
00716   output(temp_show,2);
00717   _delay_ms(100);
00718   
00719   clear_screen();
00720   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[26+points_a][i]);
00721   for(i = 0; i < 5; i++) temp_show[i] |= pgm_read_byte(&ansi[36][i]);
00722   output(temp_show,1);
00723   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[26+points_b][i]);
00724   output(temp_show,2);
00725   
00726    _delay_ms(150);
00727    
00728    if(points_a == 9) {
00729     clear_screen();
00730     output_text("A WIN",SCROLLING);
00731     points_a = points_b = 0;
00732    }
00733    if(points_b == 9) {
00734     clear_screen();
00735     output_text("B WIN",SCROLLING);
00736     points_a = points_b = 0;
00737    }
00738    
00739    start_game();
00740 
00741 }
00742 
00744 
00754 uint32_t rand() {
00755  return  (ball_timer - rand_timer);
00756 }
00757 
00759 
00781 void output_text(char* text,uint8_t func) { //Optimierung
00782   uint8_t letter = 0,i,k,j = 0;
00783   uint8_t temp_buff_1[5] = {0,0,0,0,0};
00784   uint8_t temp_buff_2[5] = {0,0,0,0,0}; //Jedes Byte bildet eine Zeile, die Bits die Spalten
00785   volatile uint8_t text_buffer[6][5] = {0};
00786 
00787   
00788    while(*text) { //Text vom Flash in RAM puffern
00789      if(*text == 32) *text = 65+37;
00790      for(i = 0; i < 5; i++) text_buffer[letter][i] = pgm_read_byte(&ansi[(*text)-65][i]);
00791      letter++;
00792      text++;
00793      if(letter > 5) break;
00794    }
00795     
00796   if(func == SCROLLING) {
00797     for(j = 0; j < (14 +(4*letter)); j++) { //Zwei Matrizen mit a 7 Spalten + die Anzahl der Pixel der Zeichen die au&szlig;erhalb des Bildschirms starten
00798       for(i = 0; i < 5; i++) { //Jede Zeile wird berechnet, es gibt 5 Zeilen und 7 Spalten
00799         for(k = 0; k < letter; k++) { //Jeder Pixel jedes Zeichens kommt in direkt zusammen in eine Zeile
00800           if(j+1 > k*5) temp_buff_1[i] |= text_buffer[k][i] << 5 >> j-(k*5); //Rechts-Shift f&uuml;r 4 Pixel Zeichenabstand, Links-Shift zum scrollen
00801           if(j > (k*5)+7) temp_buff_2[i] |= text_buffer[k][i] << 5 >> j-(k*5)-7; //Sobald j < 7, Ausgabe auch auf andere Matrix erweitern
00802         }
00803       }
00804       output(temp_buff_1,2); //Ausgabe
00805       output(temp_buff_2,1);
00806       for(i = 0; i < 5; i++) { //F&uuml;r den n&auml;chsten Scroll-Schritt, Puffer leeren
00807         temp_buff_1[i] = 0x0;
00808         temp_buff_2[i] = 0x0;
00809       } 
00810     }
00811   }
00812   
00813   if(func == STATIC) { //Baustelle
00814      for(i = 0; i < 5; i++) {
00815         for(k = 0; k < letter; k++) {
00816           temp_buff_1[i] |= text_buffer[k][i] << 5+(4*k) >> 14;
00817           temp_buff_2[i] |= text_buffer[k][i] << 5+(4*k) >> 14-7;
00818         }
00819       }
00820       output(temp_buff_1,2);
00821       output(temp_buff_2,1);    
00822 
00823   }
00824 } 
00825 
 Alle Dateien Funktionen Variablen Makrodefinitionen