needs more cowbell
Join Date: Feb 2008
Location: ÿ
Posts: 5,038
Thanks: 158
Thanked 269 Times in 212 Posts
|
Fun and/or Games
You know you are bored when you find yourself re-implementing conways Game of Life on your mpg gauge
Lot more cells on the 4x20 though
(spoiler) It never ends very well
here is the 2x16 code, play with the 1s and 0s in the display[] to set the starting pattern.
PHP Code:
//GPL Software
#include <avr/pgmspace.h>
/* Death
If an occupied cell has 0, 1, 4, 5, 6, 7, or 8 occupied neighbors, the organism dies (0, 1: of loneliness; 4 thru 8: of overcrowding).
Survival
If an occupied cell has two or three neighbors, the organism survives to the next generation.
Birth
If an unoccupied cell has three occupied neighbors, it becomes occupied.
7 0 1 how I'm referring to neighbors
6_\|/_
/|\ 2
5 4 3
*/
#define brightness 180 //middle button cycles through these brightness settings
#define contrast 15
//LCD Pins
#define DIPin 4 // register select RS
#define DB4Pin 7
#define DB5Pin 8
#define DB6Pin 12
#define DB7Pin 13
#define ContrastPin 6
#define EnablePin 5
#define BrightnessPin 9 //control with a transistor please if you use it
typedef void (* genericFx)(void);//type for function pointers
genericFx resetFunc = 0;
//LCD prototype
class LCD{
public:
LCD( ) ;
void gotoXY(byte x, byte y);
void print(char * string);
void init();
void tickleEnable();
void cmdWriteSet();
void LcdCommandWrite(byte value);
void LcdDataWrite(byte value);
byte pushNibble(byte value);
};
LCD lcd;
int powerUp = MCUSR &1; //did we reset or power up?
#define rows 6
#define columns 16
byte tmp [] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte display [] = {
0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0
};
void loop (void){
lcd.init();
byte running=1;
while(running==1){
unsigned long loopStart=millis();
running=0;
// update the neighbor counts
for(int y = 0; y < rows; y++){
for(int x = 0; x < columns; x++)
tmp[y*columns+x]=getNeighborCount(display,x,y);
}
//display the array
for(int y = 0; y < rows; y+=3){
lcd.gotoXY(0,y/3);
for(int x = 0; x < columns; x++){
byte n1=display[y*columns+x];
byte n2=getNeighbor(display,x,y,4)*2;
byte n3=getNeighbor(display,x,y+1,4)*4;
lcd.LcdDataWrite(n1|n2|n3);
}
}
//see who lives and who dies
for(int y = 0; y < rows; y++){
for(int x = 0; x < columns; x++){
byte b = display[y*columns+x];
byte n = tmp[y*columns+x];
if(b==0){
if(n==3) {
display[y*columns+x] = 1; //birth
running=1;
}
}else{
if(n==2 || n==3)
display[y*columns+x] = 1; //survival
else {
display[y*columns+x] = 0; //death
running = 1;
}
}
}
}
}
lcd.gotoXY(0,0);
lcd.print("DONE");
delay(1500);
resetFunc(); //poor mans reset :)
}
byte getNeighborCount(byte a[], byte x, byte y){
byte c = 0;
for(byte d = 0;d < 8; d++)
if(getNeighbor(a,x,y,d) != 0)
c++;
return c;
}
byte getNeighbor(byte a[], byte x, byte y, byte dir){
byte nx=x;
byte ny=y;
if(dir == 7 || dir == 0 || dir == 1)
ny--;
if(dir == 3 || dir == 4 || dir == 5)
ny++;
if(dir == 5 || dir == 6 || dir == 7)
nx--;
if(dir == 1 || dir == 2 || dir == 3)
nx++;
if(nx==255) nx = columns - 1;
if(nx==columns) nx = 0;
if(ny==255) ny = rows - 1;
if(ny==rows) ny = 0;
return a[ny*columns+nx];
}
//get a string from flash
char mBuff[17];//used by getStr
char * getStr(prog_char * str){
strcpy_P(mBuff, str);
return mBuff;
}
//LCD functions
LCD::LCD(){
}
//x=0..16, y= 0..1
void LCD::gotoXY(byte x, byte y){
byte dr=x+0x80;
if (y==1)
dr += 0x40;
if (y==2)
dr += 0x14;
if (y==3)
dr += 0x54;
lcd.LcdCommandWrite(dr);
}
void LCD::print(char * string){
byte x = 0;
char c = string[x];
while(c != 0){
lcd.LcdDataWrite(c);
x++;
c = string[x];
}
}
//do the lcd initialization voodoo
void LCD::init(){
LcdCommandWrite(B00000010); // 4 bit operation
LcdCommandWrite(B00101000);// 4-bit interface, 2 display lines, 5x8 font
LcdCommandWrite(B00001100); // display control:
LcdCommandWrite(B00000110); // entry mode set: increment automatically, no display shift
//creating the custom fonts:
LcdCommandWrite(B01000000); // set cgram
static byte chars[] PROGMEM ={
B00000,B11111,B00000,B11111,B00000,B11111,B00000,B11111,
B00000,B11111,B00000,B11111,B00000,B11111,B00000,B11111,
B00000,B00000,B00000,B00000,B00000,B00000,B00000,B00000,
B00000,B00000,B11111,B11111,B00000,B00000,B11111,B11111,
B00000,B00000,B11111,B11111,B00000,B00000,B11111,B11111,
B00000,B00000,B00000,B00000,B00000,B00000,B00000,B00000,
B00000,B00000,B00000,B00000,B11111,B11111,B11111,B11111,
B00000,B00000,B00000,B00000,B11111,B11111,B11111,B11111};
for(byte x=0;x<8;x++)
for(byte y=0;y<8;y++)
LcdDataWrite(pgm_read_byte(&chars[y*8+x])); //write the character data to the character generator ram
LcdCommandWrite(B00000001); // clear display, set cursor position to zero
LcdCommandWrite(B10000000); // set dram to zero
}
void LCD::tickleEnable(){
// send a pulse to enable
digitalWrite(EnablePin,HIGH);
delayMicroseconds(1); // pause 1 ms according to datasheet
digitalWrite(EnablePin,LOW);
delayMicroseconds(1); // pause 1 ms according to datasheet
}
void LCD::cmdWriteSet(){
digitalWrite(EnablePin,LOW);
delayMicroseconds(1); // pause 1 ms according to datasheet
digitalWrite(DIPin,0);
}
byte LCD::pushNibble(byte value){
digitalWrite(DB7Pin, value & 128);
value <<= 1;
digitalWrite(DB6Pin, value & 128);
value <<= 1;
digitalWrite(DB5Pin, value & 128);
value <<= 1;
digitalWrite(DB4Pin, value & 128);
value <<= 1;
return value;
}
void LCD::LcdCommandWrite(byte value){
value=pushNibble(value);
cmdWriteSet();
tickleEnable();
value=pushNibble(value);
cmdWriteSet();
tickleEnable();
delay(1);
}
void LCD::LcdDataWrite(byte value){
digitalWrite(DIPin, HIGH);
value=pushNibble(value);
tickleEnable();
value=pushNibble(value);
tickleEnable();
delay(1);
}
void setup (void){
MCUSR=0;
Serial.begin(9600);
pinMode(BrightnessPin,OUTPUT);
analogWrite(BrightnessPin,255-brightness);
delay(500);
pinMode(EnablePin,OUTPUT);
pinMode(DIPin,OUTPUT);
pinMode(DB4Pin,OUTPUT);
pinMode(DB5Pin,OUTPUT);
pinMode(DB6Pin,OUTPUT);
pinMode(DB7Pin,OUTPUT);
delay(500);
if(powerUp)
lcd.init();
pinMode(ContrastPin,OUTPUT);
analogWrite(ContrastPin,contrast);
lcd.LcdCommandWrite(B00000001); // clear display, set cursor position to zero
lcd.LcdCommandWrite(B10000000); // set dram to zero
lcd.gotoXY(0,0);
lcd.print(getStr(PSTR("Game of Life")));
lcd.gotoXY(0,1);
lcd.print(getStr(PSTR(" mpguino style")));
delay(1500);
}
__________________
WINDMILLS DO NOT WORK THAT WAY!!!
Last edited by dcb; 06-29-2008 at 10:00 AM..
|