test/lpfklife.c

changeset 5
2fc2b426ace9
child 9
1519a9a8d924
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/test/lpfklife.c	Tue Aug 26 21:59:54 2008 +0100
     1.3 @@ -0,0 +1,225 @@
     1.4 +// lpfklife: Conway's Game of Life for the LPFK
     1.5 +
     1.6 +#include <stdbool.h>
     1.7 +#include <stdio.h>
     1.8 +#include <string.h>
     1.9 +#include "liblpfk.h"
    1.10 +
    1.11 +/************************
    1.12 + * copied from http://linux-sxs.org/programming/kbhit.html
    1.13 + */
    1.14 +
    1.15 +#include <termios.h>
    1.16 +#include <unistd.h>   // for read()
    1.17 +
    1.18 +static struct termios initial_settings, new_settings;
    1.19 +static int peek_character = -1;
    1.20 +
    1.21 +void init_keyboard()
    1.22 +{
    1.23 +    tcgetattr(0,&initial_settings);
    1.24 +    new_settings = initial_settings;
    1.25 +    new_settings.c_lflag &= ~ICANON;
    1.26 +    new_settings.c_lflag &= ~ECHO;
    1.27 +    new_settings.c_lflag &= ~ISIG;
    1.28 +    new_settings.c_cc[VMIN] = 1;
    1.29 +    new_settings.c_cc[VTIME] = 0;
    1.30 +    tcsetattr(0, TCSANOW, &new_settings);
    1.31 +}
    1.32 +
    1.33 +void close_keyboard()
    1.34 +{
    1.35 +    tcsetattr(0, TCSANOW, &initial_settings);
    1.36 +}
    1.37 +
    1.38 +int kbhit()
    1.39 +{
    1.40 +unsigned char ch;
    1.41 +int nread;
    1.42 +
    1.43 +    if (peek_character != -1) return 1;
    1.44 +    new_settings.c_cc[VMIN]=0;
    1.45 +    tcsetattr(0, TCSANOW, &new_settings);
    1.46 +    nread = read(0,&ch,1);
    1.47 +    new_settings.c_cc[VMIN]=1;
    1.48 +    tcsetattr(0, TCSANOW, &new_settings);
    1.49 +    if(nread == 1)
    1.50 +    {
    1.51 +        peek_character = ch;
    1.52 +        return 1;
    1.53 +    }
    1.54 +    return 0;
    1.55 +}
    1.56 +
    1.57 +int readch()
    1.58 +{
    1.59 +char ch;
    1.60 +
    1.61 +    if(peek_character != -1)
    1.62 +    {
    1.63 +        ch = peek_character;
    1.64 +        peek_character = -1;
    1.65 +        return ch;
    1.66 +    }
    1.67 +    read(0,&ch,1);
    1.68 +    return ch;
    1.69 +}
    1.70 +
    1.71 +/***********************/
    1.72 +
    1.73 +int main(void)
    1.74 +{
    1.75 +	int i, nei, x, y;
    1.76 +	bool old_gamegrid[6][6];
    1.77 +	bool gamegrid[6][6];
    1.78 +	bool steadyState = false;
    1.79 +	unsigned long iteration = 0;
    1.80 +	LPFK_CTX ctx;
    1.81 +
    1.82 +	// initialisation
    1.83 +	memset(&gamegrid, 0, sizeof(gamegrid));
    1.84 +
    1.85 +	init_keyboard();
    1.86 +	atexit(close_keyboard);
    1.87 +
    1.88 +	// open lpfk port
    1.89 +	if ((i = lpfk_open(&ctx, "/dev/ttyUSB0")) != LPFK_E_OK) {
    1.90 +		// error opening lpfk
    1.91 +		printf("Error opening LPFK: code %d\n", i);
    1.92 +		return -1;
    1.93 +	}
    1.94 +
    1.95 +	lpfk_enable(&ctx, true);
    1.96 +
    1.97 +	// allow user to set up their game grid
    1.98 +	printf("Press the keys on the LPFK to set up the game grid, then press Enter to start the simulation.\n");
    1.99 +	while (!kbhit()) {
   1.100 +		i = lpfk_read(&ctx);
   1.101 +
   1.102 +		if (i >= 0) {
   1.103 +			printf("key %d\n", i);
   1.104 +			// Key down, toggle the LED
   1.105 +			lpfk_set_led(&ctx, i, !lpfk_get_led(&ctx, i));
   1.106 +
   1.107 +			// update game grid
   1.108 +			if ((i >= 0) && (i < 4)) {
   1.109 +				gamegrid[0][i+1] = !gamegrid[0][i+1];		// +1 because 1st row is 4-column
   1.110 +			} else if ((i >= 4) && (i < 10)) {
   1.111 +				gamegrid[1][i-4] = !gamegrid[1][i-4];
   1.112 +			} else if ((i >= 10) && (i < 16)) {
   1.113 +				gamegrid[2][i-10] = !gamegrid[2][i-10];
   1.114 +			} else if ((i >= 16) && (i < 22)) {
   1.115 +				gamegrid[3][i-16] = !gamegrid[3][i-16];
   1.116 +			} else if ((i >= 22) && (i < 28)) {
   1.117 +				gamegrid[4][i-22] = !gamegrid[4][i-22];
   1.118 +			} else {
   1.119 +				gamegrid[5][(i-28)+1] = !gamegrid[5][(i-28)+1];	// +1 because last row is 4-column
   1.120 +			}
   1.121 +		}
   1.122 +	}
   1.123 +	// flush keyboard buffer
   1.124 +	while (kbhit()) readch();
   1.125 +
   1.126 +	// disable LPFK keys
   1.127 +	lpfk_enable(&ctx, false);
   1.128 +
   1.129 +#ifdef DEBUG
   1.130 +	// print the game grid: debug only
   1.131 +	printf("GAME GRID: [iter %lu]\n", iteration);
   1.132 +	for (y=0; y<6; y++) {
   1.133 +		for (x=0; x<6; x++) {
   1.134 +			if (gamegrid[y][x]) printf("* "); else printf(". ");
   1.135 +		}
   1.136 +		printf("\n");
   1.137 +	}
   1.138 +	printf("\n");
   1.139 +#endif
   1.140 +
   1.141 +	printf("Press ENTER to stop the simulation.\n");
   1.142 +
   1.143 +	// run game
   1.144 +	while (!kbhit() && !steadyState) {
   1.145 +		// increase iteration counter
   1.146 +		iteration++;
   1.147 +
   1.148 +		// save current game grid
   1.149 +		memcpy(&old_gamegrid, &gamegrid, sizeof(gamegrid));
   1.150 +
   1.151 +		// loop over game grid
   1.152 +		for (y=0; y<6; y++) {
   1.153 +			for (x=0; x<6; x++) {
   1.154 +				nei = 0;
   1.155 +
   1.156 +				// count neighbours
   1.157 +				if (y > 0) {
   1.158 +					if (x > 0) { if (old_gamegrid[y-1][x-1]) nei++; }
   1.159 +					if (old_gamegrid[y-1][x]) nei++;
   1.160 +					if (x < 5) { if (old_gamegrid[y-1][x+1]) nei++; }
   1.161 +				}
   1.162 +				if (x > 0) { if (old_gamegrid[y][x-1]) nei++; }
   1.163 +				// old_gamegrid[x][y] is us!
   1.164 +				if (x < 5) { if (old_gamegrid[y][x+1]) nei++; }
   1.165 +				if (y < 5) {
   1.166 +					if (x > 0) { if (old_gamegrid[y+1][x-1]) nei++; }
   1.167 +					if (old_gamegrid[y+1][x]) nei++;
   1.168 +					if (x < 5) { if (old_gamegrid[y+1][x+1]) nei++; }
   1.169 +				}
   1.170 +
   1.171 +				// so what happens to our cell?
   1.172 +				if (old_gamegrid[y][x]) {
   1.173 +					// --- rules for live cells ---
   1.174 +					if ((nei < 2) || (nei > 3)) {
   1.175 +						// <2 neighbours, death due to loneliness.
   1.176 +						// or >3 neighbours, death due to overcrowding.
   1.177 +						gamegrid[y][x] = false;
   1.178 +					}
   1.179 +				} else {
   1.180 +					// --- rules for dead cells ---
   1.181 +					if (nei == 3) {
   1.182 +						// any dead cell with three neighbours comes to life
   1.183 +						gamegrid[y][x] = true;
   1.184 +					}
   1.185 +				}
   1.186 +			}
   1.187 +		}
   1.188 +
   1.189 +		if (memcmp(&gamegrid, &old_gamegrid, sizeof(gamegrid)) == 0) {
   1.190 +			steadyState = true;
   1.191 +		}
   1.192 +
   1.193 +#ifdef DEBUG
   1.194 +		printf("GAME GRID: [iter %lu]\n", iteration);
   1.195 +		for (y=0; y<6; y++) {
   1.196 +			for (x=0; x<6; x++) {
   1.197 +				if (gamegrid[y][x]) printf("* "); else printf(". ");
   1.198 +			}
   1.199 +			printf("\n");
   1.200 +		}
   1.201 +		printf("\n");
   1.202 +#endif
   1.203 +
   1.204 +		// now update the LPFK from the game grid
   1.205 +		for (i=0; i<32; i++) {
   1.206 +			if (i < 4)			lpfk_set_led_cached(&ctx, i, gamegrid[0][i+1]);
   1.207 +			else if (i < 10)	lpfk_set_led_cached(&ctx, i, gamegrid[1][i-4]);
   1.208 +			else if (i < 16)	lpfk_set_led_cached(&ctx, i, gamegrid[2][i-10]);
   1.209 +			else if (i < 22)	lpfk_set_led_cached(&ctx, i, gamegrid[3][i-16]);
   1.210 +			else if (i < 28)	lpfk_set_led_cached(&ctx, i, gamegrid[4][i-22]);
   1.211 +			else				lpfk_set_led_cached(&ctx, i, gamegrid[5][(i-28)+1]);
   1.212 +		}
   1.213 +
   1.214 +		// flush updates to the LPFK
   1.215 +		lpfk_update_leds(&ctx);
   1.216 +
   1.217 +		// make sure updates aren't too fast
   1.218 +		sleep(1);
   1.219 +	}
   1.220 +
   1.221 +	if (steadyState) {
   1.222 +		printf("Steady state reached.\n");
   1.223 +	}
   1.224 +	printf("LPFK Life ran for %lu iterations.\n", iteration);
   1.225 +
   1.226 +	// close the LPFK
   1.227 +	lpfk_close(&ctx);
   1.228 +}