Dies ist eine alte Version des Dokuments!
/* Game of Life demo eHaJo Blinkenlights Bausatz www.eHaJo.de */ /* * Led_Matrix_mega8.c * * Created: 16.06.2012 10:54:30 * Authors: CalM -> calm@calm-solutuions.de * /joggl -> info@ehajo.de */ #define F_CPU 8000000UL #include <inttypes.h> #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <stdlib.h> //Es sind 16 defines noetig //Zeile 1 #define ZEILE1_PORT PORTB #define ZEILE1_PIN PB4 //Zeile 2 #define ZEILE2_PORT PORTB #define ZEILE2_PIN PB5 //Zeile 3 #define ZEILE3_PORT PORTB #define ZEILE3_PIN PB6 //Zeile 4 #define ZEILE4_PORT PORTB #define ZEILE4_PIN PB7 //Zeile 5 #define ZEILE5_PORT PORTC #define ZEILE5_PIN PC7 //Zeile 6 #define ZEILE6_PORT PORTC #define ZEILE6_PIN PC6 //Zeile 7 #define ZEILE7_PORT PORTC #define ZEILE7_PIN PC5 //Zeile 8 #define ZEILE8_PORT PORTC #define ZEILE8_PIN PC4 //Spalte 1 #define SPALTE8_PORT PORTD #define SPALTE8_PIN PD4 //Spalte 2 #define SPALTE7_PORT PORTD #define SPALTE7_PIN PD5 //Spalte 3 #define SPALTE6_PORT PORTD #define SPALTE6_PIN PD6 //Spalte 4 #define SPALTE5_PORT PORTD #define SPALTE5_PIN PD7 //Spalte 5 #define SPALTE4_PORT PORTB #define SPALTE4_PIN PB0 //Spalte 6 #define SPALTE3_PORT PORTB #define SPALTE3_PIN PB1 //Spalte 7 #define SPALTE2_PORT PORTB #define SPALTE2_PIN PB2 //Spalte 8 #define SPALTE1_PORT PORTB #define SPALTE1_PIN PB3 //Defines fuer Spalten/Zeilen an/aus #define SPALTE1_AN SPALTE1_PORT &= ~(1<<SPALTE1_PIN) #define SPALTE2_AN SPALTE2_PORT &= ~(1<<SPALTE2_PIN) #define SPALTE3_AN SPALTE3_PORT &= ~(1<<SPALTE3_PIN) #define SPALTE4_AN SPALTE4_PORT &= ~(1<<SPALTE4_PIN) #define SPALTE5_AN SPALTE5_PORT &= ~(1<<SPALTE5_PIN) #define SPALTE6_AN SPALTE6_PORT &= ~(1<<SPALTE6_PIN) #define SPALTE7_AN SPALTE7_PORT &= ~(1<<SPALTE7_PIN) #define SPALTE8_AN SPALTE8_PORT &= ~(1<<SPALTE8_PIN) #define SPALTE1_AUS SPALTE1_PORT |= (1<<SPALTE1_PIN) #define SPALTE2_AUS SPALTE2_PORT |= (1<<SPALTE2_PIN) #define SPALTE3_AUS SPALTE3_PORT |= (1<<SPALTE3_PIN) #define SPALTE4_AUS SPALTE4_PORT |= (1<<SPALTE4_PIN) #define SPALTE5_AUS SPALTE5_PORT |= (1<<SPALTE5_PIN) #define SPALTE6_AUS SPALTE6_PORT |= (1<<SPALTE6_PIN) #define SPALTE7_AUS SPALTE7_PORT |= (1<<SPALTE7_PIN) #define SPALTE8_AUS SPALTE8_PORT |= (1<<SPALTE8_PIN) #define ZEILE1_AN ZEILE1_PORT |= (1<<ZEILE1_PIN) #define ZEILE2_AN ZEILE2_PORT |= (1<<ZEILE2_PIN) #define ZEILE3_AN ZEILE3_PORT |= (1<<ZEILE3_PIN) #define ZEILE4_AN ZEILE4_PORT |= (1<<ZEILE4_PIN) #define ZEILE5_AN ZEILE5_PORT |= (1<<ZEILE5_PIN) #define ZEILE6_AN ZEILE6_PORT |= (1<<ZEILE6_PIN) #define ZEILE7_AN ZEILE7_PORT |= (1<<ZEILE7_PIN) #define ZEILE8_AN ZEILE8_PORT |= (1<<ZEILE8_PIN) #define ZEILE1_AUS ZEILE1_PORT &= ~(1<<ZEILE1_PIN) #define ZEILE2_AUS ZEILE2_PORT &= ~(1<<ZEILE2_PIN) #define ZEILE3_AUS ZEILE3_PORT &= ~(1<<ZEILE3_PIN) #define ZEILE4_AUS ZEILE4_PORT &= ~(1<<ZEILE4_PIN) #define ZEILE5_AUS ZEILE5_PORT &= ~(1<<ZEILE5_PIN) #define ZEILE6_AUS ZEILE6_PORT &= ~(1<<ZEILE6_PIN) #define ZEILE7_AUS ZEILE7_PORT &= ~(1<<ZEILE7_PIN) #define ZEILE8_AUS ZEILE8_PORT &= ~(1<<ZEILE8_PIN) #define ALLE_ZEILEN_AN {ZEILE1_AN; ZEILE2_AN; ZEILE3_AN; ZEILE4_AN;ZEILE5_AN; ZEILE6_AN; ZEILE7_AN; ZEILE8_AN;} #define ALLE_ZEILEN_AUS {ZEILE1_AUS; ZEILE2_AUS; ZEILE3_AUS; ZEILE4_AUS;ZEILE5_AUS; ZEILE6_AUS; ZEILE7_AUS; ZEILE8_AUS;} #define ALLE_SPALTEN_AN {SPALTE1_AN; SPALTE2_AN; SPALTE3_AN; SPALTE4_AN;SPALTE5_AN; SPALTE6_AN; SPALTE7_AN; SPALTE8_AN;} #define ALLE_SPALTEN_AUS {SPALTE1_AUS; SPALTE2_AUS; SPALTE3_AUS;SPALTE4_AUS; SPALTE5_AUS; SPALTE6_AUS; SPALTE7_AUS; SPALTE8_AUS;} //Nicht schoen tut aber seinen dienst #define ZEILE_AUS(zeile) { switch(zeile){case 0: ZEILE1_AUS; break; case 1: ZEILE2_AUS; break; case 2: ZEILE3_AUS; break; case 3: ZEILE4_AUS; break; case 4: ZEILE5_AUS; break; case 5: ZEILE6_AUS; break; case 6: ZEILE7_AUS; break; case 7: ZEILE8_AUS; break; default: break; }} #define ZEILE_AN(zeile) {switch(zeile) { case 0: ZEILE1_AN; break; case 1: ZEILE2_AN; break; case 2: ZEILE3_AN; break; case 3: ZEILE4_AN; break; case 4: ZEILE5_AN; break; case 5: ZEILE6_AN; break; case 6: ZEILE7_AN; break; case 7: ZEILE8_AN; break; default: break;}} #define SPALTE_AUS(zeile) { switch(zeile){case 0: SPALTE1_AUS; break; case 1: SPALTE2_AUS; break; case 2: SPALTE3_AUS; break; case 3: SPALTE4_AUS; break; case 4: SPALTE5_AUS; break; case 5: SPALTE6_AUS; break; case 6: SPALTE7_AUS; break; case 7: SPALTE8_AUS; break; default: break; }} #define SPALTE_AN(zeile) {switch(zeile) { case 0: SPALTE1_AN; break; case 1: SPALTE2_AN; break; case 2: SPALTE3_AN; break; case 3: SPALTE4_AN; break; case 4: SPALTE5_AN; break; case 5: SPALTE6_AN; break; case 6: SPALTE7_AN; break; case 7: SPALTE8_AN; break; default: break;}} volatile uint8_t Bildspeicher[8] = {0xaa,0xbb,0xcc,0xdd,0xee,0xff,0xaf,0xfe}; //Der Bildspeicher des Systems als 1D-Array volatile uint8_t akt_zeile=0, akt_spalte=0, zaehler = 0, orientation = 0; void led_check(void); void zeile_an(uint8_t); void spalte_an(uint8_t); void update_Array(void); void rand_array(void); unsigned short get_seed(void); void bild_copy(void); uint8_t bild_check(void); void rand_array() { for(uint8_t i = 0; i < 8; i++) for(uint8_t j = 0; j < 8; j++) Bildspeicher[i] = rand(); } /* void update_Array() { uint8_t i, j; uint8_t temp[8][8]; uint8_t mask[8][8]; for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { temp[i][j] = Bildspeicher[i][j]; } } for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { mask[i][j] = 0; } } for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { //Angrenzende lebende Zellen zählen if(temp[i-1][j-1] == 1 && i > 0 && j > 0) ++mask[i][j]; if(temp[i ][j-1] == 1 && j > 0) ++mask[i][j]; if(temp[i-1][j ] == 1 && i > 0 ) ++mask[i][j]; if(temp[i-1][j+1] == 1 && i > 0 && j + 1 < 8) ++mask[i][j]; if(temp[i ][j+1] == 1 && j + 1 < 8) ++mask[i][j]; if(temp[i+1][j ] == 1 && i + 1 < 8 ) ++mask[i][j]; if(temp[i+1][j-1] == 1 && i + 1 < 8 && j > 0) ++mask[i][j]; if(temp[i+1][j+1] == 1 && i + 1 < 8 && j + 1 < 8) ++mask[i][j]; if(mask[i][j] < 2 || mask[i][j] > 3) { Bildspeicher[i][j] = 0; //Sterben durch Vereinsamung/Überbevölkerung } else if(mask[i][j] == 3) { Bildspeicher[i][j] = 1; //Neues Leben schaffen } } } }*/ ISR(TIMER0_COMPA_vect) { // Timer-Compare interrupt, dieser zeigt die Matrix an cli(); ALLE_ZEILEN_AUS; SPALTE_AUS(akt_spalte); akt_spalte++; akt_spalte &= 0x07; // maximal 8 zeilen //Zeile 1 if(Bildspeicher[akt_spalte] & 0x01) ZEILE1_AN; //Zeile 2 if(Bildspeicher[akt_spalte] & 0x02) ZEILE2_AN; //Zeile 3 if(Bildspeicher[akt_spalte] & 0x04) ZEILE3_AN; //Zeile 4 if(Bildspeicher[akt_spalte] & 0x08) ZEILE4_AN; //Zeile 5 if(Bildspeicher[akt_spalte] & 0x10) ZEILE5_AN; //Zeile 6 if(Bildspeicher[akt_spalte] & 0x20) ZEILE6_AN; //Zeile 7 if(Bildspeicher[akt_spalte] & 0x40) ZEILE7_AN; //Zeile 8 if(Bildspeicher[akt_spalte] & 0x80) ZEILE8_AN; SPALTE_AN(akt_spalte); sei(); } unsigned short get_seed() { // Aus dem RAM zufallswert holen fuer random-seed unsigned short seed = 0; unsigned short *p = (unsigned short*) (RAMEND+1); extern unsigned short __heap_start; while (p >= &__heap_start + 1) seed ^= * (--p); return seed; } int main(void) { uint8_t lifetimer = 0; uint8_t i = 0; //Setup der IO PORTB=0; PORTC=0; PORTD=0; DDRB=0xFF; //Alles auf Ausgang, alles low DDRC=0xFF; //Alles auf Ausgang, alles low DDRD=0xFF; DDRD &= ~(1<<PD0); PORTD |= (1<<PD0); MCUSR = 0; //MCUCR &= ~(1<<PUD); CLKSEL0 = (1<<EXTE); // externe Taktquelle einschalten CLKPR = (1<<CLKPCE); // Prescaler-Change aktivieren CLKPR = 0; // Prescaler Teilefaktor 1 TCCR0A |= (1<<WGM01); // Timer im CTC-Mode TCCR0B |= (1<<FOC0A) | (1<<CS01); // Compare output A aktivieren, 64er Teiler OCR0A = 50; // Hier gibts nen Compare-Match Interrupt TIMSK0 |= (1<<OCIE0A); // Capture Interrupt enable Timer 0 Capture A SREG |= (0b10000000); // Global Interrupt enable //srand(get_seed()); // Seed fuer den zufallsgenerator holen //rand_array(); // Array mit zufallszahlen betanken //bild_copy(); // temp-array mit array betanken while(1) { if(!(PIND & (1<<PD0))) { // Zum Bootloader springen for(i = 0; i<8; i++) { Bildspeicher[i] = 0; } DDRB = 0; DDRC = 0; DDRD = 0; PORTB=0; PORTC=0; PORTD=0; cli(); ((void (*)(void))0x1000)(); // Achtung, das hier ist eine Word-Adresse! } } { //update_Array(); // game of life algorythmus ueber das array schicken //if((bild_check() == 0)) //{ // wenn array gleich wie davor dann zaehler erhoehen // i++; //} if (i >4) { // wenn array 5 mal gleich dann neu berechnen //rand_array(); i = 0; lifetimer = 0; } if(lifetimer++ == 255) { // Wenn lifetimer abgelaufen dann neu berechnen -> oszillator kann mit // temp-array vergleich nicht erkannt werden... //rand_array(); } bild_copy(); // aktuelles array in das temp array kopieren } } void bild_copy() { // array in temp speicher kopieren for(uint8_t n = 0; n < 8; n++) { //Bildspeicher_temp[n] = Bildspeicher[n]; } } uint8_t bild_check() { // temp array mit bildspeicher vergleichen for(uint8_t n = 0; n < 8; n++) { for(uint8_t m = 0; m<8; m++) { //if(Bildspeicher_temp[n][m] != Bildspeicher[n][m]) return 1; } } return 0; } void zeile_an(uint8_t zeile) { switch(zeile) { case 0: ZEILE1_AN; break; case 1: ZEILE2_AN; break; case 2: ZEILE3_AN; break; case 3: ZEILE4_AN; break; case 4: ZEILE5_AN; break; case 5: ZEILE6_AN; break; case 6: ZEILE7_AN; break; case 7: ZEILE8_AN; break; default: break; } } void spalte_an(uint8_t spalte) { switch(spalte) { case 0: SPALTE1_AN; break; case 1: SPALTE2_AN; break; case 2: SPALTE3_AN; break; case 3: SPALTE4_AN; break; case 4: SPALTE5_AN; break; case 5: SPALTE6_AN; break; case 6: SPALTE7_AN; break; case 7: SPALTE8_AN; break; default: break; } }