Advertisement
Guest User

Untitled

a guest
Sep 26th, 2017
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.34 KB | None | 0 0
  1. #ifndef F_CPU
  2. /// @brief Die Geschwindigkeit des Mikrocontroller in Hertz, für _delay_ms von Bedeutung
  3. #define F_CPU 1000000UL
  4. #endif
  5.  
  6. /// @brief Dieser Pin wird als Clock-Signal für die seriellen Daten am 74HC595 benutzt
  7. #define SCK PB4
  8. /// @brief Dieser Pin wird als Clock-Signal zum Schalten der internen Register an die Output-Pins des 74HC595 benutzt
  9. #define OCK PB3
  10. /// @brief Dieser Pin wird zur Übertragung der seriellen Daten zum 74HC595 benutzt
  11. #define DS PB1
  12.  
  13. #include <avr/io.h>
  14. #include <util/delay.h>
  15. #include <avr/interrupt.h>
  16. #include <avr/pgmspace.h>
  17. #include <inttypes.h>
  18. #include <stdlib.h>
  19.  
  20. /**
  21.  * @file pms_tiny.c
  22.  * @brief Diese Datei enth&auml;lt das gesamte Programm/Spiel für den Mikrocontroller
  23.  */
  24.  
  25. void clock_serial();
  26. void clock_output();
  27. void shift_high();
  28. void shift_low();
  29. void output(volatile uint8_t*,uint8_t);
  30. void matrix_output();
  31. void matrix_screen_pixel(uint32_t);
  32.  
  33. void adc_init();
  34. void get_adcval(uint16_t *);
  35. uint8_t getkey();
  36.  
  37. void timer_init();
  38.  
  39. void clear_screen();
  40. void start_game();
  41. void game_failed();
  42. void output_game();
  43. void cursor_a_down();
  44. void cursor_a_up();
  45. void cursor_b_down();
  46. void cursor_b_up();
  47.  
  48. void next_r_ball();
  49. void check_ball_pos();
  50. uint8_t check_ball_coll();
  51.  
  52. ///@brief Diese Variable enth&auml;lt einen freundlichen Smiley zur Ausgabe auf der Punktmatrix
  53. volatile uint8_t friendly_sm[5] PROGMEM = {0x0C,0x12,0x0,0x12,0x0};
  54. ///@brief Diese Variable enth&auml;lt einen freundlichen Smiley zur Ausgabe auf der Punktmatrix
  55. volatile uint8_t unfriendly_sm[5] PROGMEM = {0x12,0x0C,0x0,0x12,0x0};
  56. ///@brief Diese Variable enth&auml;lt einen das Alphabet und alle Ziffern zur Ausgabe auf der Punktmatrix
  57. volatile uint8_t ansi[37][5] PROGMEM = {
  58.                 {0x12,0x12,0x1E,0x12,0x0C}, //A
  59.                 {0x0E,0x12,0x0E,0x12,0x0E}, //B
  60.                 {0x0C,0x02,0x02,0x02,0x0C}, //C
  61.                 {0x0E,0x12,0x12,0x12,0x0E}, //D
  62.                 {0x0E,0x02,0x0E,0x02,0x0E}, //E
  63.                 {0x0E,0x02,0x0E,0x02,0x02}, //F
  64.                 {0x1C,0x12,0x1A,0x02,0x1C}, //G
  65.                 {0x12,0x12,0x1E,0x12,0x12}, //H
  66.                 {0x0E,0x04,0x04,0x04,0x0E}, //I
  67.                 {0x06,0x08,0x08,0x08,0x0E}, //J
  68.                 {0x12,0x0A,0x06,0x0A,0x12}, //K
  69.                 {0x0E,0x02,0x02,0x02,0x02}, //L
  70.                 {0x12,0x12,0x12,0x1E,0x12}, //M
  71.                 {0x22,0x32,0x2A,0x26,0x22}, //N
  72.                 {0x0C,0x12,0x12,0x12,0x0C}, //O
  73.                 {0x04,0x04,0x1C,0x14,0x0C}, //P
  74.                 {0x14,0x0A,0x12,0x12,0x0C}, //Q
  75.                 {0x14,0x14,0x0C,0x14,0x0C}, //R
  76.                 {0x1C,0x10,0x08,0x04,0x1C}, //S
  77.                 {0x08,0x08,0x08,0x08,0x1C}, //T
  78.                 {0x1C,0x14,0x14,0x14,0x14}, //U
  79.                 {0x08,0x14,0x14,0x14,0x14}, //V
  80.                 {0x14,0x2A,0x2A,0x22,0x22}, //W
  81.                 {0x22,0x14,0x08,0x14,0x22}, //X
  82.                 {0x08,0x08,0x08,0x14,0x22}, //Y
  83.                 {0x1E,0x04,0x08,0x10,0x1E}, //Z
  84.                 {0x0E,0x0A,0x0A,0x0A,0x0E}, //0
  85.                 {0x1C,0x08,0x08,0x0C,0x08}, //1
  86.                 {0x1E,0x04,0x08,0x12,0x0C}, //2
  87.                 {0x0C,0x12,0x08,0x10,0x1E}, //3
  88.                 {0x08,0x08,0x0E,0x0A,0x0A}, //4
  89.                 {0x0E,0x08,0x0E,0x02,0x0E}, //5
  90.                 {0x0E,0x0A,0x0E,0x02,0x0E}, //6
  91.                 {0x08,0x08,0x0A,0x0A,0x0E}, //7
  92.                 {0x0E,0x0A,0x0E,0x0A,0x0E}, //8
  93.                 {0x0E,0x08,0x0E,0x0A,0x0E}, //9
  94.                 {0x00,0x40,0x00,0x40,0x00}}; //:
  95.                
  96.  
  97. ///@brief Diese Variable enth&auml;lt den Cursor des Spielers A. Diese Variable wird ebenfalls zur Kollisionsüberprüfung benutzt.
  98. volatile uint8_t cursor_a[5] = {0x0,0x1,0x1,0x0,0x0};
  99. ///@brief Diese Variable enth&auml;lt den Cursor des Spielers B. Diese Variable wird ebenfalls zur Kollisionsüberprüfung benutzt.
  100. volatile uint8_t cursor_b[5] = {0x0,0x00,0x40,0x40,0x00};
  101. ///@brief Diese Variable enth&auml;lt den Spielball. Diese Variable wird ebenfalls zur Kollisionsüberprüfung benutzt.
  102. volatile uint8_t ball[5] = {0x0,0x0,0x4,0x0,0x0};
  103.  
  104. ///@brief Diese Variable enth&auml;lten den Video-Buffer für die linke Punktmatrix. Dieser Buffer wird auf der Punktmatrix ausgegeben
  105. volatile uint8_t screen_buffer_first[5];
  106. ///@brief Diese Variable enth&auml;lten den Video-Buffer für die rechte Punktmatrix. Dieser Buffer wird auf der Punktmatrix ausgegeben
  107. volatile uint8_t screen_buffer_second[5];
  108.  
  109. ///@brief Diese Variable gibt an, in welche Richtung der Ball steuert. 0 = links, 1 = rechts
  110. volatile uint8_t ball_dir = 0;
  111. ///@brief Diese Variable enth&auml;lt eine Zeitverzögerung für die Spielzyklen, damit das Spiel in angenehmer Zeit abläuft. Alle 100 Zählungen, ein Zyklus
  112. volatile uint32_t ball_timer = 0;
  113. ///@brief Diese Variable gibt an, ob das Spiel derzeit läuft, oder nicht. 0 = läuft nicht, 1 = läuft
  114. volatile uint8_t game_running = 0;
  115. ///@brief Diese Variable gibt an, ob der Ball an einem Rand das Spielfeld verlassen hat. 1 = rechter Rand, 2 = linker Rand
  116. uint8_t game_failed_var = 0x0;
  117. ///@brief Diese Variable enth&auml;lt den Spielstand für den Spieler A
  118. uint8_t points_a = 0;
  119. ///@brief Diese Variable enth&auml;lt den Spielstand für den Spieler B
  120. uint8_t points_b = 0;
  121.  
  122. ///////////////////////////////////////////////////////////
  123. /**
  124.  * @brief Diese Funktion ist der Einsprungspunkt des Programmes und nimmt alle nötigen Initialisierungen vor
  125.  *
  126.  * Zunächst werden die Pins PB0 (KontrollLED), PB1 (serielle Daten), PB3 (Datenausgabe-Clock) und PB4 (serielle Daten-Clock) auf Ausgang gesetzt,
  127.  * damit man dessen Zustände setzen kann. Danach wird der ADC initialisiert, welcher zum Einlesen der Tasten benötigt wird. Als nächster wird
  128.  * der Timer initialisert, welcher regelmäßig einen Interrupt auslöst, welcher sich dann um die Ausgabe und die Spielzyklen kümmert. Mit der
  129.  * Funktion start_game() werden da die Spieldaten initialisiert und das Spiel gestartet. In der unendlichen Schleife wird für eine bestimmte
  130.  * kurze Zeitdauer abgefragt, ob eine Taste gedrückt wurde. Danach wird überprüft, ob der Ball das Spielfeld inzwischen verlassen hat, wenn nicht
  131.  * wird überprüft, welche Taste gedrückt wurde. Je nach Taste wird die dazu gehörige Funktion ausgeführt. Danach beginnt die Schleife wieder von
  132.  * vorne.
  133.  * @return Der Rückgabewert ist 0, dieser wird jedoch nie erreicht.
  134.  */
  135.  
  136. int main() {
  137.   uint8_t key = 0;
  138.   DDRB = (1 << PB0) | (1 << PB1)| (1 << PB3) | (1 << PB4);
  139.  
  140.   adc_init();
  141.   timer_init();
  142.   sei();
  143.  
  144.   start_game();
  145.  
  146.   while(1) {
  147.    key = getkey();
  148.    srand(ball_timer);
  149.    if(game_failed_var != 0) game_failed();
  150.    if(key == 1) cursor_a_down();
  151.    if(key == 2) cursor_a_up();
  152.    if(key == 3) cursor_b_down();
  153.    if(key == 4) cursor_b_up();
  154.   }
  155. return 0;
  156. }
  157.  
  158. ///////////////////////////////////////////////////////////
  159. /**
  160.  * @brief Diese Funktion kümmert sich um eine HIGH-LOW-Taktflanke bei dem Clockeingang für die seriellen Daten des 74HC595
  161.  *
  162.  * Dabei wird der dafür benutzte Pin PB4 auf High und danach wieder auf Low gesetzt, indem das entsprechende Bit im PORTB gesetzt und wieder
  163.  * gelöscht wird. Dadurch wird erreicht, dass alle Zustände der internen Register einen Platz weiterrücken (shift) und im ersten Register
  164.  * der anliegende Zustand am seriellen Dateneingang des 74HC595 übernommen wird.
  165.  */
  166.  
  167. void clock_serial() {
  168.   PORTB |= (1 << SCK);
  169.   PORTB &= ~(1 << SCK);
  170. }
  171.  
  172. ///////////////////////////////////////////////////////////
  173. /**
  174.  * @brief Diese Funktion kümmert sich um eine HIGH-LOW-Taktflanke bei dem Clockeingang des Output der internen Register des 74HC595
  175.  *
  176.  * Dabei wird der dafür benutzte Pin PB3 auf High und danach wieder auf Low gesetzt, indem das entsprechende Bit im PORTB gesetzt und wieder
  177.  * gelöscht wird. Dadurch werden die Zustände der internen Register des 74HC595 auf die Output-Pins gelegt.
  178.  */
  179.  
  180. void clock_output() {
  181.   PORTB |= (1 << OCK);
  182.   PORTB &= ~(1 << OCK);
  183. }
  184.  
  185. ///////////////////////////////////////////////////////////
  186. /**
  187.  * @brief Diese Funktion schiebt einen HIGH-Zustand in den 74HC595
  188.  *
  189.  * Dabei wird der serielle Datenpin PB1 auf HIGH gesetzt und ein Shift auf dem 74HC595 vollzogen.
  190.  */
  191.  
  192. void shift_high() {
  193.   PORTB |= (1 << DS);
  194.   clock_serial();
  195. }
  196.  
  197. ///////////////////////////////////////////////////////////
  198. /**
  199.  * @brief Diese Funktion schiebt einen LOW-Zustand in den 74HC595
  200.  *
  201.  * Dabei wird der serielle Datenpin PB1 auf LOW gesetzt und ein Shift auf dem 74HC595 vollzogen.
  202.  */
  203.  
  204. void shift_low() {
  205.   PORTB &= ~(1 << DS);
  206.   clock_serial();
  207. }
  208.  
  209. ///////////////////////////////////////////////////////////
  210. /**
  211.  * @brief Diese Funktion gibt den übergebenen 5 x 8 Bit großen Speicherbereich aus
  212.  *
  213.  * Dabei wird der  5 x 8 Bit großen Speicherbereich Byte für Byte in den screen_buffer_second kopiert. Der Screen-Buffer enthält die Ausgaben
  214.  * auf der Punktmatrix und wird mit jedem Timer-Interrupt ausgegeben.
  215.  * @param in Dieser Parameter ist der Pointer, der auf den 5 x 8 Bit großen Speicherbereich zeigt
  216.  */
  217.  
  218. void output(volatile uint8_t* in, uint8_t screen) {
  219.  uint8_t i = 0;
  220.  if(screen == 1) { for(i = 0; i < 5; i++) screen_buffer_first[i] = in[i]; }
  221.  if(screen == 2) { for(i = 0; i < 5; i++) screen_buffer_second[i] = in[i]; }
  222. }
  223.  
  224. ///////////////////////////////////////////////////////////
  225. /**
  226.  * @brief
  227.  *
  228.  *
  229.  */
  230.  
  231. void matrix_output() {
  232.   uint8_t k,i,j,col,row = 0;
  233.   uint32_t out = 0;
  234.      
  235.   for(k = 0; k < 2; k++){ //Für beide Punktmatrix
  236.     for(i = 0; i < 5; i++) { //Jede Spalte muss auf Punkte überprüft werden
  237.       if(k == 0) row = screen_buffer_second[i]; //Erst die rechte Punktmatrix
  238.       else row = screen_buffer_first[i]; //Dann die linke Punktmatrix
  239.       for(j = 0; j < 7; j++) { //Dann wird jede Zeile auf ein Punkt überprüft
  240.         if(row & 0x01) { //Wurde einer gefunden,
  241.           out = (1 << j); //muss die jeweilige Zeile aktiviert werden
  242.           out <<=5; //(Die Zeilen stehen in der Ausgabe 5 Bits weiter
  243.           out |= (1 << i); //und es muss die jeweilige Spalte aktiviert werden
  244.           out <<=1; //Welche erst ab Bit 1 anfangen
  245.           if(k == 1) out <<= 16; //Für den linken Bildschirm muss das Ganze 16 Bits verschoben werden (aufgrund der Schieberegister)
  246.           matrix_screen_pixel(out);
  247.         }
  248.         row >>=1; // Das nächste Bit wird überprüft
  249.       }
  250.     }
  251.   }
  252. }
  253.  
  254. ///////////////////////////////////////////////////////////
  255. /**
  256.  * @brief
  257.  *
  258.  *
  259.  */
  260.  
  261. void matrix_screen_pixel(uint32_t input) {
  262.   uint8_t i = 0;
  263.  
  264.     for(i = 0; i < 32; i++) {
  265.     if((i < 26 && i > 16) || (i < 10)) {
  266.       if(input & 0x80000000) shift_low();
  267.       else shift_high();
  268.     }
  269.     else {
  270.       if(input & 0x80000000) shift_high();
  271.       else shift_low();
  272.     }
  273.     input <<= 1;
  274.     }
  275.     clock_output();
  276.  
  277.   PORTB &= ~(1 << DS);
  278.   PORTB &= ~(1 << SCK);
  279.   PORTB &= ~(1 << OCK);
  280.  
  281. }
  282.  
  283. ///////////////////////////////////////////////////////////
  284. /**
  285.  * @brief Diese Funktion initialisiert den ADC (Analog to Digtial Converter) mit Werten
  286.  *
  287.  * Dabei wird zunächst eine trash-Variable (Müll-Variable, d.h diese Variable wird mit unsinnigen Daten belegt) angelegt, da der ADC am Ende der
  288.  * Initialisierung einen Wert auslesen lassen muss, bevor dieser korrekt funktioniert. Als nächstes wird im Register ADMUX das Bit MUX0 gesetzt,
  289.  * welches bedeutet, das Analog-Daten für die ADC-Konvertierungen aus dem Pin PB2 gelesen werden sollen. Im nächsten Schritt wird im Register
  290.  * DIDR0 das Bit ADC0D gesetzt, womit angewiesen wird, dass aus dem Pin PB2 keine digitalen Daten mehr gelesen werden müssen. Das Register
  291.  * ADCSRA wird mit den Bits ADPS1 und ADPS0 belegt, womit erreicht wird, dass der ADC einen Prescaler von 8 besitzt. Da dieser AVR Atmel Attiny45
  292.  * mit einem Megahertz betrieben wird, wird mit dem Prescaler erreicht, dass die Frequenzahl im Bereich zwischen 50kHz und 200kHz liegt (Hier:
  293.  * 125kHz). Dies wird benötigt, damit der ADC mit genauer Auflösung arbeiten kann. Das Bit ADEN wird gesetzt, damit der ADC angeschaltet wird.
  294.  * Damit startet jedoch noch keine Konvertierung. Im letzten Schritt wird ein ADC-Wert ausgelesen, danach ist der ADC vollständig einsatzbereit.
  295.  */
  296.  
  297. void adc_init() {
  298.     uint16_t trash;
  299.     ADMUX =  (1 << MUX0); //PB2
  300.     DIDR0 |= (1<<ADC0D); //PB2  (ADC0)
  301.     ADCSRA = (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN); //Division 8
  302.     get_adcval(&trash); //First Conversion
  303. }
  304.  
  305. ///////////////////////////////////////////////////////////
  306. /**
  307.  * @brief Diese Funktion startet den ADC (Analog to Digital Converter)
  308.  *
  309.  * Dabei wird das ADSC Bit im Zustandsregister ADCSRA gesetzt, womit eine ADC-Konvertierung gestartet wird.
  310.  */
  311.  
  312. void adc_start() {
  313.     ADCSRA |= (1 << ADSC);
  314. }
  315.  
  316. ///////////////////////////////////////////////////////////
  317. /**
  318.  * @brief Diese Funktion liest einen ADC-Wert aus und schreibt diesen in den angegeben 16-Bit-Buffer
  319.  *
  320.  * Dabei wird zunächst mit adc_start() eine ADC-Konvertierung gestartet. Danach wird solange eine Schleife durchlaufen, bis das Bit ADSC im Register
  321.  * ADCSRA nicht mehr gesetzt ist. Ist dies der Fall, bedeutet es, dass die Konvertierung abgeschlossen ist. Danach wird der ausgelesene Wert in
  322.  * den angegebenen 16-Bit-Buffer geschrieben.
  323.  * @param val Dieser Parameter enthält die Adresse des 16-Bit-Buffer, in dem der ausgelesene ADC-Wert gespeichert werden soll
  324.  */
  325.  
  326. void get_adcval(uint16_t *val) {
  327.   adc_start();
  328.   while(ADCSRA & (1 << ADSC));
  329.   *val = ADCW;
  330. }
  331.  
  332. ///////////////////////////////////////////////////////////
  333. /**
  334.  * @brief Diese Funktion wartet auf eine Tasteneingabe
  335.  *
  336.  * Dabei wird der an dem Pin 2 angelegten Spannungswert über die get_adcval-Funktion ausgelesen. Handelt es sich um einen in Referenz zu 5V
  337.  * angelegten Wert von 50 oder weniger, ist die Taste 4 gedrückt worden. Zwischen 51 und 280 liegt die Taste 3, die Taste 2 hat einen Wertebereich
  338.  * von 281 bis 540. Die Taste 1 ist gedrückt worden, wenn der Wert 790 bis 1023 beträgt. Alles über diesen Werte ist keine angeschlossene Taste.
  339.  * Wurde nach zehn Auslese- und Verarbeitungsvorgängen keine gültige Taste gedrückt oder wurde eine Taste gedrückt, wird die Schleife beendet und
  340.  * die angegebene Taste zurückgegeben. Bei keiner gültigen Taste wird 0 zurückgegeben.
  341.  * @return Der Rückgabewert ist die gedrückte Taste
  342.  */
  343.  
  344. uint8_t getkey() {
  345.   uint8_t key = 0;
  346.   uint16_t adc_wert = 0;
  347.   uint16_t zaehl = 0;  
  348.   while(1) {
  349.     get_adcval(&adc_wert);
  350.     zaehl++;
  351.     if(adc_wert <= 50) { //Taste 4 von links
  352.         key = 4;
  353.         break;
  354.     }
  355.     else if(adc_wert <= 280 ) { //Taste 3 von links
  356.         key = 3;
  357.         break;
  358.     }
  359.     else if(adc_wert <= 540) { //Taste 2 von links
  360.         key = 2;
  361.         break;
  362.     }// bis hier
  363.     else if (adc_wert <= 790){ //Taste 1 von links
  364.         key = 1;
  365.         break;
  366.     }  
  367.    
  368.     else if(adc_wert <= 1024) { //keine Taste
  369.         key = 0;  
  370.     }
  371.     if(zaehl >= 10) break;
  372.  }
  373.  return key;
  374. }
  375.  
  376. ///////////////////////////////////////////////////////////
  377. /**
  378.  * @brief In dieser Funktion wird der Timer initialisiert
  379.  *
  380.  * Dabei wird zunächst mit dem TOIE0-Bit im TIMSK-Register erreicht, dass bei einem Timer-Overflow Interrupts ausgelöst werden. Mit dem
  381.  * CS01-Bit im TCCR0B-Register wird der Prescaler auf 8 gesetzt, sodass nur bei jedem achten Taktzyklus der Timer inkrementiert. Mit dem Wert
  382.  * 0x0 im TCNT0-Register wird der Startwert des Timer0 gesetzt.
  383.  */
  384.  
  385. void timer_init() {
  386.   TIMSK |= (1 << TOIE0);
  387.   TCCR0B |= (1 << CS01); //Prescaler 8
  388.   TCNT0 = 0x0;  //Startwert 1
  389. }
  390.  
  391. ///////////////////////////////////////////////////////////
  392. /**
  393.  * @brief Diese Funktion bildet die anzuspringende Interrupt-Funktion bei einem Timer0-Overflow
  394.  *
  395.  * Während dieser Funktion werden verschiedene Aufgaben erledigt. Zum einem wird die Bildschirmausgabe aktualisiert, solange das Spiel
  396.  * am Laufen ist, zum anderen aktualisiert diese Funktion bei allen hundert Timer0-Overflows die Ballposition.
  397.  * @param TIMER0_OVF_vect Dieser Parameter gibt den Typ des Interrupt an, bei dem diese Funktion angesprungen werden soll
  398.  */
  399.  
  400. ISR(TIMER0_OVF_vect) { //Bildschirmausgabe
  401.   if(game_running) output_game();
  402.   matrix_output();
  403.   ball_timer++;
  404.   if(ball_timer >= 100) {
  405.     ball_timer = 0;
  406.     next_r_ball();
  407.   }
  408. }
  409.  
  410. ///////////////////////////////////////////////////////////
  411. /**
  412.  * @brief Diese Funktion dient zur Löschung der Punktmatrix
  413.  *
  414.  * Dabei wird der screen_buffer_second, der als Ausgabebereich für die Punktmatrix definiert ist, mit 0x0 überschrieben.
  415.  */
  416.  
  417. void clear_screen() {
  418.   uint8_t i = 0;
  419.   for(i = 0; i < 5; i++) screen_buffer_second[i]= 0x0;
  420.   for(i = 0; i < 5; i++) screen_buffer_first[i] = 0x0;
  421. }
  422.  
  423. ///////////////////////////////////////////////////////////
  424. /**
  425.  * @brief
  426.  *
  427.  *
  428.  */
  429.  
  430. void start_game() {
  431.   uint8_t i = 0;
  432.   game_failed_var = 0x0;
  433.   for(i = 0; i < 5; i++) cursor_a[i] = 0x0;
  434.   for(i = 0; i < 5; i++) cursor_b[i] = 0x0;
  435.   cursor_a[1] = 0x1;
  436.   cursor_a[2] = 0x1;
  437.   cursor_b[2] = 0x40;
  438.   cursor_b[3] = 0x40;
  439.   for(i = 0; i < 5; i++) ball[i]= 0x0;
  440.   ball[2]= 0x4;
  441.   ball_dir = 0;
  442.   game_running = 1;
  443.   output_game();
  444. }
  445.  
  446. ///////////////////////////////////////////////////////////
  447. /**
  448.  * @brief
  449.  *
  450.  *
  451.  */
  452.  
  453. void output_game() {
  454.   uint8_t i = 0;
  455.   clear_screen();
  456.  
  457.   for(i = 0; i < 5; i++) screen_buffer_second[i]|= cursor_a[i];
  458.   for(i = 0; i < 5; i++) screen_buffer_second[i] |= cursor_b[i];
  459.   for(i = 0; i < 5; i++) screen_buffer_second[i] |= ball[i];
  460. }
  461.  
  462. ///////////////////////////////////////////////////////////
  463. /**
  464.  * @brief
  465.  *
  466.  *
  467.  */
  468.  
  469. void cursor_a_down() {
  470.  uint8_t i = 0;
  471.  if(cursor_a[0]== 0x01) return;
  472.  else {
  473.   for(i = 0; i < 4; i++) cursor_a[i]= cursor_a[i+1];
  474.   cursor_a[4] = 0x0;
  475.  }
  476. }
  477.  
  478. ///////////////////////////////////////////////////////////
  479. /**
  480.  * @brief
  481.  *
  482.  *
  483.  */
  484.  
  485. void cursor_a_up() {
  486.  uint8_t i = 0;
  487.  if(cursor_a[4]== 0x01) return;
  488.  else {
  489.   for(i = 4; i > 0; i--) cursor_a[i]= cursor_a[i-1];
  490.   cursor_a[0]= 0x0;
  491.  }
  492. }
  493.  
  494. ///////////////////////////////////////////////////////////
  495.  
  496. void cursor_b_down() {
  497.  uint8_t i = 0;
  498.  if(cursor_b[0] == 0x40) return;
  499.  else {
  500.   for(i = 0; i < 4; i++) cursor_b[i]= cursor_b[i+1];
  501.   cursor_b[4] = 0x0;
  502.  }
  503. }
  504.  
  505. ///////////////////////////////////////////////////////////
  506. /**
  507.  * @brief
  508.  *
  509.  *
  510.  */
  511.  
  512. void cursor_b_up() {
  513.  uint8_t i = 0;
  514.  if(cursor_b[4] == 0x40) return;
  515.  else {
  516.   for(i = 4; i > 0; i--) cursor_b[i] = cursor_b[i-1];
  517.   cursor_b[0] = 0x0;
  518.  }
  519. }
  520.  
  521. ///////////////////////////////////////////////////////////
  522. /**
  523.  * @brief
  524.  *
  525.  *
  526.  */
  527.  
  528. void next_r_ball() {
  529.   uint8_t col = 0;
  530.   uint8_t i = 0;
  531.  
  532.   i = check_ball_coll();
  533.  
  534.  
  535.   if(i != 0) {  
  536.       if(i % 2) {  //Rechte Seite aufgeschlagen
  537.     i = rand() % 4;
  538.     if(i == 1) i = 0;
  539.       }
  540.       else {    //Linke Seite aufgeschlagen
  541.     i = rand() % 4;
  542.     if(i == 0) i = 1;
  543.     else i += 2;
  544.       }
  545.         ball_dir = i;
  546.   }
  547.  
  548.   for(i = 0; i < 5; i++) { if(ball[i] != 0) col = i; }
  549.  
  550.   switch(ball_dir) {
  551.    
  552.     case 0x0: //links
  553.       ball[col] <<= 1;
  554.       break;
  555.     case 0x1: //rechts
  556.       ball[col] >>= 1;
  557.       break;
  558.     case 0x2: //links-hoch
  559.  
  560.       if(col == 4) { ball_dir = 3; break; }
  561.       ball[col+1] = ball[col] << 1;
  562.       ball[col] = 0x0;
  563.       break;
  564.     case 0x3: //links-runter
  565.       if(col == 0) { ball_dir = 2; break; }
  566.       ball[col-1] = ball[col] << 1;
  567.       ball[col] = 0x0;
  568.       break;
  569.     case 0x4: //rechts-hoch
  570.       if(col == 4) { ball_dir = 5; break; }
  571.       ball[col+1] = ball[col] >> 1;
  572.       ball[col] = 0x0;
  573.       break;
  574.     case 0x5: //rechts-runter
  575.       if(col == 0) { ball_dir = 4; break; }
  576.       ball[col-1] = ball[col] >> 1;
  577.       ball[col] = 0x0;
  578.       break;
  579.     default:
  580.       break;
  581.      
  582.   }
  583. }
  584.  
  585.  
  586. ///////////////////////////////////////////////////////////
  587. /**
  588.  * @brief
  589.  *
  590.  *
  591.  */
  592.  
  593. uint8_t check_ball_coll() {
  594.   uint8_t temp_coll[5] = {0x0,0x0,0x0,0x0,0x0};
  595.   uint8_t col = 0;
  596.   uint8_t i = 0;
  597.   uint8_t col_point = 0;
  598.  
  599.   for(i = 0; i < 5; i++) temp_coll[i] |= cursor_a[i];
  600.   for(i = 0; i < 5; i++) temp_coll[i] |= cursor_b[i];
  601.  
  602.   for(i = 0; i < 5; i++) { if(ball[i] != 0) col = i; }
  603.  
  604.   if( (temp_coll[col] << 1 ) & ball[col] && col == 2) col_point = 1; //Rechte Seite
  605.   if( (temp_coll[col] >> 1 ) & ball[col] && col == 2) col_point = 2; //Linke Seite
  606.   if( (temp_coll[col] << 1 ) & ball[col] && col < 2) col_point = 3;
  607.   if( (temp_coll[col] >> 1 ) & ball[col] && col > 2) col_point = 4;
  608.   if( (temp_coll[col] << 1 ) & ball[col] && col < 2) col_point = 5;
  609.   if( (temp_coll[col] >> 1 ) & ball[col] && col > 2) col_point = 6;
  610.  
  611.  
  612.   if(ball[col] == 0x80) game_failed_var = 0x1; // Bei B-Spieler raus
  613.   if(ball[col] == 0x0)  game_failed_var = 0x2; //Bei A-Spieler raus
  614.   if(ball[col] != 0x80 && ball[col] != 0x0) game_failed_var = 0x0;
  615.   return col_point;
  616. }
  617.  
  618.  
  619. ///////////////////////////////////////////////////////////
  620. /**
  621.  * @brief
  622.  *
  623.  *
  624.  */
  625.  
  626. void game_failed() {
  627.   uint8_t temp_show[5] = {0,0,0,0,0};
  628.   uint8_t i = 0;
  629.  
  630.   game_running = 0;
  631.   clear_screen();
  632.  
  633.   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&unfriendly_sm[i]);
  634.   output(temp_show,2);
  635.   _delay_ms(1);
  636.   clear_screen();
  637.  
  638.   if(game_failed_var == 2) { //B hat ein Punkt gemacht
  639.     for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[0][i]);
  640.     points_b++;
  641.   }
  642.   else if(game_failed_var == 1) { //A hat ein Punkt gemacht
  643.     for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[1][i]);
  644.     points_a++;
  645.   }
  646.   output(temp_show,2);
  647.   _delay_ms(1);
  648.  
  649.   clear_screen();
  650.   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[26+points_a][i]);
  651.   for(i = 0; i < 5; i++) temp_show[i] |= pgm_read_byte(&ansi[36][i]);
  652.   output(temp_show,1);
  653.   for(i = 0; i < 5; i++) temp_show[i] = pgm_read_byte(&ansi[26+points_b][i]);
  654.   output(temp_show,2);
  655.  
  656.    _delay_us(300);
  657.   start_game();
  658.  
  659. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement