test/lpfklife.c

Tue, 26 Aug 2008 22:13:49 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 26 Aug 2008 22:13:49 +0100
changeset 9
1519a9a8d924
parent 5
2fc2b426ace9
child 10
f76c929f65e6
permissions
-rw-r--r--

added #ifdef DEBUG around "key down" debug printf

     1 // lpfklife: Conway's Game of Life for the LPFK
     3 #include <stdbool.h>
     4 #include <stdio.h>
     5 #include <string.h>
     6 #include "liblpfk.h"
     8 /************************
     9  * copied from http://linux-sxs.org/programming/kbhit.html
    10  */
    12 #include <termios.h>
    13 #include <unistd.h>   // for read()
    15 static struct termios initial_settings, new_settings;
    16 static int peek_character = -1;
    18 void init_keyboard()
    19 {
    20     tcgetattr(0,&initial_settings);
    21     new_settings = initial_settings;
    22     new_settings.c_lflag &= ~ICANON;
    23     new_settings.c_lflag &= ~ECHO;
    24     new_settings.c_lflag &= ~ISIG;
    25     new_settings.c_cc[VMIN] = 1;
    26     new_settings.c_cc[VTIME] = 0;
    27     tcsetattr(0, TCSANOW, &new_settings);
    28 }
    30 void close_keyboard()
    31 {
    32     tcsetattr(0, TCSANOW, &initial_settings);
    33 }
    35 int kbhit()
    36 {
    37 unsigned char ch;
    38 int nread;
    40     if (peek_character != -1) return 1;
    41     new_settings.c_cc[VMIN]=0;
    42     tcsetattr(0, TCSANOW, &new_settings);
    43     nread = read(0,&ch,1);
    44     new_settings.c_cc[VMIN]=1;
    45     tcsetattr(0, TCSANOW, &new_settings);
    46     if(nread == 1)
    47     {
    48         peek_character = ch;
    49         return 1;
    50     }
    51     return 0;
    52 }
    54 int readch()
    55 {
    56 char ch;
    58     if(peek_character != -1)
    59     {
    60         ch = peek_character;
    61         peek_character = -1;
    62         return ch;
    63     }
    64     read(0,&ch,1);
    65     return ch;
    66 }
    68 /***********************/
    70 int main(void)
    71 {
    72 	int i, nei, x, y;
    73 	bool old_gamegrid[6][6];
    74 	bool gamegrid[6][6];
    75 	bool steadyState = false;
    76 	unsigned long iteration = 0;
    77 	LPFK_CTX ctx;
    79 	// initialisation
    80 	memset(&gamegrid, 0, sizeof(gamegrid));
    82 	init_keyboard();
    83 	atexit(close_keyboard);
    85 	// open lpfk port
    86 	if ((i = lpfk_open(&ctx, "/dev/ttyUSB0")) != LPFK_E_OK) {
    87 		// error opening lpfk
    88 		printf("Error opening LPFK: code %d\n", i);
    89 		return -1;
    90 	}
    92 	lpfk_enable(&ctx, true);
    94 	// allow user to set up their game grid
    95 	printf("Press the keys on the LPFK to set up the game grid, then press Enter to start the simulation.\n");
    96 	while (!kbhit()) {
    97 		i = lpfk_read(&ctx);
    99 		if (i >= 0) {
   100 #ifdef DEBUG
   101 			printf("key %d\n", i);
   102 #endif
   103 			// Key down, toggle the LED
   104 			lpfk_set_led(&ctx, i, !lpfk_get_led(&ctx, i));
   106 			// update game grid
   107 			if ((i >= 0) && (i < 4)) {
   108 				gamegrid[0][i+1] = !gamegrid[0][i+1];		// +1 because 1st row is 4-column
   109 			} else if ((i >= 4) && (i < 10)) {
   110 				gamegrid[1][i-4] = !gamegrid[1][i-4];
   111 			} else if ((i >= 10) && (i < 16)) {
   112 				gamegrid[2][i-10] = !gamegrid[2][i-10];
   113 			} else if ((i >= 16) && (i < 22)) {
   114 				gamegrid[3][i-16] = !gamegrid[3][i-16];
   115 			} else if ((i >= 22) && (i < 28)) {
   116 				gamegrid[4][i-22] = !gamegrid[4][i-22];
   117 			} else {
   118 				gamegrid[5][(i-28)+1] = !gamegrid[5][(i-28)+1];	// +1 because last row is 4-column
   119 			}
   120 		}
   121 	}
   122 	// flush keyboard buffer
   123 	while (kbhit()) readch();
   125 	// disable LPFK keys
   126 	lpfk_enable(&ctx, false);
   128 #ifdef DEBUG
   129 	// print the game grid: debug only
   130 	printf("GAME GRID: [iter %lu]\n", iteration);
   131 	for (y=0; y<6; y++) {
   132 		for (x=0; x<6; x++) {
   133 			if (gamegrid[y][x]) printf("* "); else printf(". ");
   134 		}
   135 		printf("\n");
   136 	}
   137 	printf("\n");
   138 #endif
   140 	printf("Press ENTER to stop the simulation.\n");
   142 	// run game
   143 	while (!kbhit() && !steadyState) {
   144 		// increase iteration counter
   145 		iteration++;
   147 		// save current game grid
   148 		memcpy(&old_gamegrid, &gamegrid, sizeof(gamegrid));
   150 		// loop over game grid
   151 		for (y=0; y<6; y++) {
   152 			for (x=0; x<6; x++) {
   153 				nei = 0;
   155 				// count neighbours
   156 				if (y > 0) {
   157 					if (x > 0) { if (old_gamegrid[y-1][x-1]) nei++; }
   158 					if (old_gamegrid[y-1][x]) nei++;
   159 					if (x < 5) { if (old_gamegrid[y-1][x+1]) nei++; }
   160 				}
   161 				if (x > 0) { if (old_gamegrid[y][x-1]) nei++; }
   162 				// old_gamegrid[x][y] is us!
   163 				if (x < 5) { if (old_gamegrid[y][x+1]) nei++; }
   164 				if (y < 5) {
   165 					if (x > 0) { if (old_gamegrid[y+1][x-1]) nei++; }
   166 					if (old_gamegrid[y+1][x]) nei++;
   167 					if (x < 5) { if (old_gamegrid[y+1][x+1]) nei++; }
   168 				}
   170 				// so what happens to our cell?
   171 				if (old_gamegrid[y][x]) {
   172 					// --- rules for live cells ---
   173 					if ((nei < 2) || (nei > 3)) {
   174 						// <2 neighbours, death due to loneliness.
   175 						// or >3 neighbours, death due to overcrowding.
   176 						gamegrid[y][x] = false;
   177 					}
   178 				} else {
   179 					// --- rules for dead cells ---
   180 					if (nei == 3) {
   181 						// any dead cell with three neighbours comes to life
   182 						gamegrid[y][x] = true;
   183 					}
   184 				}
   185 			}
   186 		}
   188 		if (memcmp(&gamegrid, &old_gamegrid, sizeof(gamegrid)) == 0) {
   189 			steadyState = true;
   190 		}
   192 #ifdef DEBUG
   193 		printf("GAME GRID: [iter %lu]\n", iteration);
   194 		for (y=0; y<6; y++) {
   195 			for (x=0; x<6; x++) {
   196 				if (gamegrid[y][x]) printf("* "); else printf(". ");
   197 			}
   198 			printf("\n");
   199 		}
   200 		printf("\n");
   201 #endif
   203 		// now update the LPFK from the game grid
   204 		for (i=0; i<32; i++) {
   205 			if (i < 4)			lpfk_set_led_cached(&ctx, i, gamegrid[0][i+1]);
   206 			else if (i < 10)	lpfk_set_led_cached(&ctx, i, gamegrid[1][i-4]);
   207 			else if (i < 16)	lpfk_set_led_cached(&ctx, i, gamegrid[2][i-10]);
   208 			else if (i < 22)	lpfk_set_led_cached(&ctx, i, gamegrid[3][i-16]);
   209 			else if (i < 28)	lpfk_set_led_cached(&ctx, i, gamegrid[4][i-22]);
   210 			else				lpfk_set_led_cached(&ctx, i, gamegrid[5][(i-28)+1]);
   211 		}
   213 		// flush updates to the LPFK
   214 		lpfk_update_leds(&ctx);
   216 		// make sure updates aren't too fast
   217 		sleep(1);
   218 	}
   220 	if (steadyState) {
   221 		printf("Steady state reached.\n");
   222 	}
   223 	printf("LPFK Life ran for %lu iterations.\n", iteration);
   225 	// close the LPFK
   226 	lpfk_close(&ctx);
   227 }