/* life.c - demonstrator for later Mips+LCD game of life * * 23.03.06 - MACRO-based version * 22.02.06 - new file */ #include "ks0108.h" // #include // #include #define NX 70 // 128 // 48 // 128 #define NY 31 // 64 // 27 // 64 #define LOGNX 7 #define LOGNY 5 // OCCUPIED must be uneven, EMPTY even. #define OCCUPIED 0x77771111 #define EMPTY 0xeeee0000 // #define ADDR_LFSR32 0x00003FF0 // #define ADDR_LFSRMASK 0x00003FF4 #define ADDR_LFSR32 0x00001500 #define ADDR_LFSRMASK 0x00001504 #define MATRIX( row, col ) (*(matrix + (col << LOGNX) + row )) #define FUTURE( row, col ) (*(future + (col << LOGNX) + row )) // static int lfsr32; // static int lfsrmask; int init_lfsr32( int seed ) { int *lfsr32; int *lfsrmask; lfsr32 = (int*) ADDR_LFSR32; lfsrmask = (int*) ADDR_LFSRMASK; if (seed != 0) *lfsr32 = seed; else *lfsr32 = 0xdeadbeef; *lfsrmask = 0x00000009; } /* (31 3 0) polynom linear-feedback shift-register (Numerical Recipes) */ int clock_lfsr32() { int bit31; int *lfsr32; int *lfsrmask; lfsr32 = (int*) ADDR_LFSR32; lfsrmask = (int*) ADDR_LFSRMASK; if (*lfsr32 == 0) { // emergency initialization *lfsr32 = 0xdeadbeef; *lfsrmask = 0x00000009; } bit31 = *lfsr32 & 0x80000000; if (bit31 != 0) { *lfsr32 = ((*lfsr32 ^ *lfsrmask) << 1) + 1; } else { *lfsr32 = (*lfsr32 << 1); } return *lfsr32; } /* return a pseudo-random integer in the range 0..1023 */ int random1023() { int tmp; tmp = clock_lfsr32(); return tmp & 0x000003ff; } void putch( char c ) { ; // empty for the MIPS version // printf( "%c", c ); } void clearDisplay() { ; // printf( "Clear display...\n" ); } void display( int* matrix ) { int ix, iy; for( iy=0; iy < NY; iy++ ) { putch( '\n' ); for( ix=0; ix < NX; ix++ ) { if (MATRIX( ix, iy ) != 0) putch( 'X' ); else putch( '.' ); } } putch( '\n' ); putch( '\n' ); } /* MSB/LSB in y-Richtung vertauscht void displayBoard( int* matrix ) { int x, y; int mask, accu; // lcdClearDisplay(); for( x=0; x < NX; x++ ) { mask = 0x80; accu = 0x00; for( y=0; y < NY; y++ ) { // if ((MATRIX(x,y) & 0x1) == 1) lcdSetPixel( x, y ); if (MATRIX( x, y ) != OCCUPIED) { accu |= mask; } mask = mask >> 1; if (mask == 0) { lcdDrawByte( x, (y >> 3), accu ); mask = 0x80; accu = 0x00; } } lcdDrawByte( x, (y >> 3), accu ); } *(matrix-15) = 0xdead0000; *(matrix-16) = *(matrix-16) + 1; } */ /** * convert the given unsigned value to a decimal-formatted 4-digit * string. * Negative values or value greater than 9999 are converted to * the strings "----" or "++++"; */ void dec4( int value, char* buffer ) { int i, j; if (value < 0) { for( i=0; i<4; i++) { *(buffer+i) = '-'; } *(buffer+4) = (char) 0; return; } if (value > 9999) { for( i=0; i<4; i++) { *(buffer+i) = '+'; } *(buffer+4) = (char) 0; return; } j = 0; while( value >= 1000) { value = value - 1000; j++; } *(buffer+0) = (char) ('0' + j); j = 0; while( value >= 100) { value = value - 100; j++; } *(buffer+1) = (char) ('0' + j); j = 0; while( value >= 10) { value = value - 10; j++; } *(buffer+2) = (char) ('0' + j); j = 0; while( value >= 1) { value = value - 1; j++; } *(buffer+3) = (char) ('0' + j); *(buffer+4) = (char) 0; return; } void displayBoard( int* matrix ) { int x, y; int mask, accu; // lcdClearDisplay(); for( x=0; x < 128; x++ ) { // each column of the display mask = 0x01; accu = 0x00; for( y=0; y < 64; y++ ) { // each row of the display if ((x < NX) && (y < NY)) { // inside the matrix if (MATRIX(x,y) == OCCUPIED) { accu |= mask; } } else { // outside ; } mask = mask << 1; if (mask == 0x100) { // one byte complete, draw it lcdDrawByte( x, (y >> 3), accu ); mask = 0x01; accu = 0x00; } } } *(matrix-15) = 0xdead0000; *(matrix-16) = *(matrix-16) + 1; // display population, iteration, lifes counters /* lcdSetTextPos( 0, 7 ); lcdText( dec4(population, matrix-24) ); lcdSetTextPos( 7, 7 ); lcdText( dec4(iteration, matrix-24) ); lcdSetTextPos( 14, 7 ); lcdText( dec4(lifes, matrix-24) ); */ } void initializeBoard( int* matrix ) { int x, y; for( x=0; x < NX; x++ ) { for( y=0; y < NY; y++ ) { int d = random1023(); if (d > 490) MATRIX( x, y ) = OCCUPIED; else MATRIX( x, y ) = EMPTY; } } } int countNeighbors( int* matrix, int i, int j ) { int im = i-1; int ip = i+1; int jm = j-1; int jp = j+1; int n = 0; // wrap-around if (ip >= NX) ip = 0; if (jp >= NY) jp = 0; if (im < 0) im = NX-1; if (jm < 0) jm = NY-1; // check eight neighbors n += MATRIX(im, jm ) & 0x1; // nw n += MATRIX(im, j ) & 0x1; // west n += MATRIX(im, jp ) & 0x1; // sw n += MATRIX(i, jm ) & 0x1; // north // n += MATRIX(i, j ) & 0x1; // center n += MATRIX(i, jp ) & 0x1; // south n += MATRIX(ip, jm ) & 0x1; // ne n += MATRIX(ip, j ) & 0x1; // east n += MATRIX(ip, jp ) & 0x1; // se return n; } /** * the actual game of life algorithm: cell is born when three neighbors, * survives when exactly two live neighbors, dies otherwise. */ void nextGeneration( int* matrix, int* future ) { int i, j; int lifes = 0; for( i=0; i < NX; i++ ) { for( j=0; j < NY; j++ ) { // count neighbors int n = countNeighbors( matrix, i, j ); //if ((n != 0) && (random1023() > 990)) { // some slight random offset // if (random1023() > 500) FUTURE(i,j) = OCCUPIED; // else FUTURE(i,j) = EMPTY; //} // else if (n == 3) FUTURE(i,j) = OCCUPIED; if (n == 3) FUTURE(i,j) = OCCUPIED; else if ((n == 2) && (MATRIX(i,j) == OCCUPIED)) FUTURE(i,j) = OCCUPIED; else FUTURE(i,j) = EMPTY; if (FUTURE(i,j) == OCCUPIED) lifes++; } } // generation ++; // avoid extinction :-) if (lifes < 10) { // printf( "CREATING A NEW POPULATION\n\n\n" ); initializeBoard( matrix ); } else { // swap buffers: C PROHIBITS ASSIGNING TO ARRAY TYPES for( i=0; i < NX; i++ ) { for( j=0; j < NY; j++ ) { MATRIX(i,j) = FUTURE(i,j); } } } } int main( int argc, char* argv[] ) { int* ptr; int* matrix; int* future; lcdEnableDisplay( 1 ); lcdSetColor( 1 ); lcdSetPixel( 0, 0 ); lcdSetPixel( 3, 5 ); // if we have stdlib: // matrix = (void*) malloc( NX*NY*sizeof(int) ); // future = (void*) malloc( NX*NY*sizeof(int) ); matrix = (void *) 0x00004000; future = (void *) 0x00014000; // init_lfsr32( 0xcafebabe ); // init_lfsr32( 0x13 ); initializeBoard( matrix ); displayBoard( matrix ); while( 1 ) { nextGeneration( matrix, future ); // display( matrix ); displayBoard( matrix ); } // return 0 }