test/lpfklife.c

Tue, 26 Aug 2008 21:59:54 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 26 Aug 2008 21:59:54 +0100
changeset 5
2fc2b426ace9
child 9
1519a9a8d924
permissions
-rw-r--r--

Added "Conway's Life" demo to LPFK test suite. This is a good test for
cached LED status setting, and a decent base for other LPFK games.

     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 			printf("key %d\n", i);
   101 			// Key down, toggle the LED
   102 			lpfk_set_led(&ctx, i, !lpfk_get_led(&ctx, i));
   104 			// update game grid
   105 			if ((i >= 0) && (i < 4)) {
   106 				gamegrid[0][i+1] = !gamegrid[0][i+1];		// +1 because 1st row is 4-column
   107 			} else if ((i >= 4) && (i < 10)) {
   108 				gamegrid[1][i-4] = !gamegrid[1][i-4];
   109 			} else if ((i >= 10) && (i < 16)) {
   110 				gamegrid[2][i-10] = !gamegrid[2][i-10];
   111 			} else if ((i >= 16) && (i < 22)) {
   112 				gamegrid[3][i-16] = !gamegrid[3][i-16];
   113 			} else if ((i >= 22) && (i < 28)) {
   114 				gamegrid[4][i-22] = !gamegrid[4][i-22];
   115 			} else {
   116 				gamegrid[5][(i-28)+1] = !gamegrid[5][(i-28)+1];	// +1 because last row is 4-column
   117 			}
   118 		}
   119 	}
   120 	// flush keyboard buffer
   121 	while (kbhit()) readch();
   123 	// disable LPFK keys
   124 	lpfk_enable(&ctx, false);
   126 #ifdef DEBUG
   127 	// print the game grid: debug only
   128 	printf("GAME GRID: [iter %lu]\n", iteration);
   129 	for (y=0; y<6; y++) {
   130 		for (x=0; x<6; x++) {
   131 			if (gamegrid[y][x]) printf("* "); else printf(". ");
   132 		}
   133 		printf("\n");
   134 	}
   135 	printf("\n");
   136 #endif
   138 	printf("Press ENTER to stop the simulation.\n");
   140 	// run game
   141 	while (!kbhit() && !steadyState) {
   142 		// increase iteration counter
   143 		iteration++;
   145 		// save current game grid
   146 		memcpy(&old_gamegrid, &gamegrid, sizeof(gamegrid));
   148 		// loop over game grid
   149 		for (y=0; y<6; y++) {
   150 			for (x=0; x<6; x++) {
   151 				nei = 0;
   153 				// count neighbours
   154 				if (y > 0) {
   155 					if (x > 0) { if (old_gamegrid[y-1][x-1]) nei++; }
   156 					if (old_gamegrid[y-1][x]) nei++;
   157 					if (x < 5) { if (old_gamegrid[y-1][x+1]) nei++; }
   158 				}
   159 				if (x > 0) { if (old_gamegrid[y][x-1]) nei++; }
   160 				// old_gamegrid[x][y] is us!
   161 				if (x < 5) { if (old_gamegrid[y][x+1]) nei++; }
   162 				if (y < 5) {
   163 					if (x > 0) { if (old_gamegrid[y+1][x-1]) nei++; }
   164 					if (old_gamegrid[y+1][x]) nei++;
   165 					if (x < 5) { if (old_gamegrid[y+1][x+1]) nei++; }
   166 				}
   168 				// so what happens to our cell?
   169 				if (old_gamegrid[y][x]) {
   170 					// --- rules for live cells ---
   171 					if ((nei < 2) || (nei > 3)) {
   172 						// <2 neighbours, death due to loneliness.
   173 						// or >3 neighbours, death due to overcrowding.
   174 						gamegrid[y][x] = false;
   175 					}
   176 				} else {
   177 					// --- rules for dead cells ---
   178 					if (nei == 3) {
   179 						// any dead cell with three neighbours comes to life
   180 						gamegrid[y][x] = true;
   181 					}
   182 				}
   183 			}
   184 		}
   186 		if (memcmp(&gamegrid, &old_gamegrid, sizeof(gamegrid)) == 0) {
   187 			steadyState = true;
   188 		}
   190 #ifdef DEBUG
   191 		printf("GAME GRID: [iter %lu]\n", iteration);
   192 		for (y=0; y<6; y++) {
   193 			for (x=0; x<6; x++) {
   194 				if (gamegrid[y][x]) printf("* "); else printf(". ");
   195 			}
   196 			printf("\n");
   197 		}
   198 		printf("\n");
   199 #endif
   201 		// now update the LPFK from the game grid
   202 		for (i=0; i<32; i++) {
   203 			if (i < 4)			lpfk_set_led_cached(&ctx, i, gamegrid[0][i+1]);
   204 			else if (i < 10)	lpfk_set_led_cached(&ctx, i, gamegrid[1][i-4]);
   205 			else if (i < 16)	lpfk_set_led_cached(&ctx, i, gamegrid[2][i-10]);
   206 			else if (i < 22)	lpfk_set_led_cached(&ctx, i, gamegrid[3][i-16]);
   207 			else if (i < 28)	lpfk_set_led_cached(&ctx, i, gamegrid[4][i-22]);
   208 			else				lpfk_set_led_cached(&ctx, i, gamegrid[5][(i-28)+1]);
   209 		}
   211 		// flush updates to the LPFK
   212 		lpfk_update_leds(&ctx);
   214 		// make sure updates aren't too fast
   215 		sleep(1);
   216 	}
   218 	if (steadyState) {
   219 		printf("Steady state reached.\n");
   220 	}
   221 	printf("LPFK Life ran for %lu iterations.\n", iteration);
   223 	// close the LPFK
   224 	lpfk_close(&ctx);
   225 }