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;
	}
}