Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@448 cc03376c-175c-47c8-b038-4cd826a8556b
250 lines
5.2 KiB
C
250 lines
5.2 KiB
C
/* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "libsys.h"
|
|
|
|
|
|
#define NX 200 // 70 // 128 // 48 // 128
|
|
#define NY 150 // 31 // 64 // 27 // 64
|
|
|
|
#define SCREEN_X 800
|
|
#define SCREEN_Y 600
|
|
|
|
#define SCALE_X (4)
|
|
#define SCALE_Y (4)
|
|
#define OFFSET_X ((SCREEN_X-(SCALE_X*NX))/2)
|
|
#define OFFSET_Y ((SCREEN_Y-(SCALE_Y*NY))/2)
|
|
|
|
// OCCUPIED must be uneven, EMPTY even.
|
|
#define OCCUPIED 0x77771111
|
|
#define EMPTY 0xeeee0000
|
|
|
|
#define MATRIX( row, col ) (*(matrix + (NX*col) + row ))
|
|
#define FUTURE( row, col ) (*(future + (NX*col) + row ))
|
|
|
|
UINT32 *g_gx_buff;
|
|
|
|
int clock_lfsr32()
|
|
{
|
|
return rand();
|
|
}
|
|
|
|
|
|
/* return a pseudo-random integer in the range 0..1023 */
|
|
int random1023() {
|
|
int tmp;
|
|
|
|
tmp = clock_lfsr32();
|
|
return tmp & 0x000003ff;
|
|
}
|
|
|
|
typedef struct _scolor_t
|
|
{
|
|
UINT8 r, g, b, a;
|
|
} __attribute__ ((__packed__)) color_t;
|
|
|
|
|
|
void DrawPixel(UINT32 x, UINT32 y, color_t *pColor)
|
|
{
|
|
int i, j;
|
|
for (i=0; i < SCALE_Y; i++)
|
|
for (j=0; j < SCALE_X; j++)
|
|
g_gx_buff[(OFFSET_X+SCALE_X*x+j) + SCREEN_X*(OFFSET_Y+SCALE_Y*y+i)] = *((UINT32*)pColor);
|
|
}
|
|
|
|
|
|
/* MSB/LSB in y-Richtung vertauscht */
|
|
void displayBoard1( int* matrix )
|
|
{
|
|
int x, y;
|
|
int mask, accu;
|
|
UINT32 color;
|
|
|
|
for( x=0; x < NX; x++ )
|
|
{
|
|
mask = 0x80;
|
|
accu = 0x00;
|
|
for( y=0; y < NY; y++ )
|
|
{
|
|
color = (UINT32)-(MATRIX(x,y) & 0x1);
|
|
DrawPixel(x, y, (color_t*)&color);
|
|
// if (MATRIX( x, y ) != OCCUPIED)
|
|
// {
|
|
// accu |= mask;
|
|
// }
|
|
// mask = mask >> 1;
|
|
|
|
// color = 0;
|
|
// DrawPixel(x, (y>>3), (color_t*)&color);
|
|
// if (mask == 0)
|
|
// {
|
|
// color = accu;
|
|
// DrawPixel(x, (y>>3), (color_t*)&color);
|
|
// mask = 0x80;
|
|
// accu = 0x00;
|
|
// }
|
|
}
|
|
// color = accu;
|
|
// DrawPixel(x, (y>>3), (color_t*)&color);
|
|
|
|
}
|
|
// *(matrix-15) = 0xdead0000;
|
|
// *(matrix-16) = *(matrix-16) + 1;
|
|
}
|
|
|
|
void initializeBoard( int* matrix ) {
|
|
int x, y;
|
|
for( x=0; x < NX; x++ ) {
|
|
for( y=0; y < NY; y++ ) {
|
|
int d = random1023();
|
|
if (d > 920) 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gx_init(void)
|
|
{
|
|
volatile UINT32 *pVGA_mctrl = (UINT32*)sys_vga_mctrl;
|
|
volatile UINT32 *pVGA_moffs = (UINT32*)sys_vga_moffs;
|
|
|
|
sleep(500);
|
|
|
|
g_gx_buff = (UINT32*)malloc(SCREEN_X*SCREEN_Y*sizeof(UINT32));
|
|
memset(g_gx_buff, 0, SCREEN_X*SCREEN_Y*sizeof(UINT32));
|
|
printf("g_gx_buff : %8.8X\n", (UINT32)g_gx_buff);
|
|
|
|
*pVGA_mctrl = 1;
|
|
*pVGA_moffs = (UINT32)g_gx_buff;
|
|
|
|
}
|
|
|
|
int main( int argc, char* argv[] ) {
|
|
|
|
int* ptr, cnt = 0;
|
|
|
|
int* matrix;
|
|
int* future;
|
|
volatile UINT32 *pBtn = (UINT32*)sys_gpio0;
|
|
|
|
// 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) );
|
|
|
|
|
|
gx_init();
|
|
|
|
// matrix = (void *) 0x00004000;
|
|
// future = (void *) 0x00014000;
|
|
|
|
// init_lfsr32( 0xcafebabe );
|
|
// init_lfsr32( 0x13 );
|
|
|
|
srand(clock());
|
|
initializeBoard( matrix );
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
if (*pBtn)
|
|
{
|
|
srand(clock());
|
|
initializeBoard( matrix );
|
|
cnt = 0;
|
|
}
|
|
sputs("Generation #"); print_word(cnt++); sputs("\n");
|
|
displayBoard1( matrix );
|
|
nextGeneration( matrix, future );
|
|
}
|
|
|
|
// return 0
|
|
}
|