Tue, 26 Aug 2008 21:59:54 +0100
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.
Makefile | file | annotate | diff | revisions | |
test/lpfklife.c | file | annotate | diff | revisions |
1.1 --- a/Makefile Tue Aug 26 19:14:23 2008 +0100 1.2 +++ b/Makefile Tue Aug 26 21:59:54 2008 +0100 1.3 @@ -3,17 +3,20 @@ 1.4 1.5 .PHONY: all clean 1.6 1.7 -all: liblpfk.so lpfktest 1.8 +all: liblpfk.so lpfktest lpfklife 1.9 ldconfig -n . 1.10 1.11 clean: 1.12 - -rm -f lpfktest 1.13 - -rm -f liblpfk.so* 1.14 - -rm -f src/*.o 1.15 - -rm -f test/*.o 1.16 + -rm -f lpfktest liblpfk.so* 1.17 + -rm -f src/*.o test/*.o 1.18 + -rf -f src/*~ test/*~ *~ 1.19 1.20 liblpfk.so: src/liblpfk.o 1.21 $(CC) -shared -Wl,-soname,$(SONAME) -o $@ $< 1.22 1.23 lpfktest: test/lpfktest.o 1.24 $(CC) -o $@ $< -L. -llpfk 1.25 + 1.26 +lpfklife: test/lpfklife.o 1.27 + $(CC) -o $@ $< -L. -llpfk 1.28 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/lpfklife.c Tue Aug 26 21:59:54 2008 +0100 2.3 @@ -0,0 +1,225 @@ 2.4 +// lpfklife: Conway's Game of Life for the LPFK 2.5 + 2.6 +#include <stdbool.h> 2.7 +#include <stdio.h> 2.8 +#include <string.h> 2.9 +#include "liblpfk.h" 2.10 + 2.11 +/************************ 2.12 + * copied from http://linux-sxs.org/programming/kbhit.html 2.13 + */ 2.14 + 2.15 +#include <termios.h> 2.16 +#include <unistd.h> // for read() 2.17 + 2.18 +static struct termios initial_settings, new_settings; 2.19 +static int peek_character = -1; 2.20 + 2.21 +void init_keyboard() 2.22 +{ 2.23 + tcgetattr(0,&initial_settings); 2.24 + new_settings = initial_settings; 2.25 + new_settings.c_lflag &= ~ICANON; 2.26 + new_settings.c_lflag &= ~ECHO; 2.27 + new_settings.c_lflag &= ~ISIG; 2.28 + new_settings.c_cc[VMIN] = 1; 2.29 + new_settings.c_cc[VTIME] = 0; 2.30 + tcsetattr(0, TCSANOW, &new_settings); 2.31 +} 2.32 + 2.33 +void close_keyboard() 2.34 +{ 2.35 + tcsetattr(0, TCSANOW, &initial_settings); 2.36 +} 2.37 + 2.38 +int kbhit() 2.39 +{ 2.40 +unsigned char ch; 2.41 +int nread; 2.42 + 2.43 + if (peek_character != -1) return 1; 2.44 + new_settings.c_cc[VMIN]=0; 2.45 + tcsetattr(0, TCSANOW, &new_settings); 2.46 + nread = read(0,&ch,1); 2.47 + new_settings.c_cc[VMIN]=1; 2.48 + tcsetattr(0, TCSANOW, &new_settings); 2.49 + if(nread == 1) 2.50 + { 2.51 + peek_character = ch; 2.52 + return 1; 2.53 + } 2.54 + return 0; 2.55 +} 2.56 + 2.57 +int readch() 2.58 +{ 2.59 +char ch; 2.60 + 2.61 + if(peek_character != -1) 2.62 + { 2.63 + ch = peek_character; 2.64 + peek_character = -1; 2.65 + return ch; 2.66 + } 2.67 + read(0,&ch,1); 2.68 + return ch; 2.69 +} 2.70 + 2.71 +/***********************/ 2.72 + 2.73 +int main(void) 2.74 +{ 2.75 + int i, nei, x, y; 2.76 + bool old_gamegrid[6][6]; 2.77 + bool gamegrid[6][6]; 2.78 + bool steadyState = false; 2.79 + unsigned long iteration = 0; 2.80 + LPFK_CTX ctx; 2.81 + 2.82 + // initialisation 2.83 + memset(&gamegrid, 0, sizeof(gamegrid)); 2.84 + 2.85 + init_keyboard(); 2.86 + atexit(close_keyboard); 2.87 + 2.88 + // open lpfk port 2.89 + if ((i = lpfk_open(&ctx, "/dev/ttyUSB0")) != LPFK_E_OK) { 2.90 + // error opening lpfk 2.91 + printf("Error opening LPFK: code %d\n", i); 2.92 + return -1; 2.93 + } 2.94 + 2.95 + lpfk_enable(&ctx, true); 2.96 + 2.97 + // allow user to set up their game grid 2.98 + printf("Press the keys on the LPFK to set up the game grid, then press Enter to start the simulation.\n"); 2.99 + while (!kbhit()) { 2.100 + i = lpfk_read(&ctx); 2.101 + 2.102 + if (i >= 0) { 2.103 + printf("key %d\n", i); 2.104 + // Key down, toggle the LED 2.105 + lpfk_set_led(&ctx, i, !lpfk_get_led(&ctx, i)); 2.106 + 2.107 + // update game grid 2.108 + if ((i >= 0) && (i < 4)) { 2.109 + gamegrid[0][i+1] = !gamegrid[0][i+1]; // +1 because 1st row is 4-column 2.110 + } else if ((i >= 4) && (i < 10)) { 2.111 + gamegrid[1][i-4] = !gamegrid[1][i-4]; 2.112 + } else if ((i >= 10) && (i < 16)) { 2.113 + gamegrid[2][i-10] = !gamegrid[2][i-10]; 2.114 + } else if ((i >= 16) && (i < 22)) { 2.115 + gamegrid[3][i-16] = !gamegrid[3][i-16]; 2.116 + } else if ((i >= 22) && (i < 28)) { 2.117 + gamegrid[4][i-22] = !gamegrid[4][i-22]; 2.118 + } else { 2.119 + gamegrid[5][(i-28)+1] = !gamegrid[5][(i-28)+1]; // +1 because last row is 4-column 2.120 + } 2.121 + } 2.122 + } 2.123 + // flush keyboard buffer 2.124 + while (kbhit()) readch(); 2.125 + 2.126 + // disable LPFK keys 2.127 + lpfk_enable(&ctx, false); 2.128 + 2.129 +#ifdef DEBUG 2.130 + // print the game grid: debug only 2.131 + printf("GAME GRID: [iter %lu]\n", iteration); 2.132 + for (y=0; y<6; y++) { 2.133 + for (x=0; x<6; x++) { 2.134 + if (gamegrid[y][x]) printf("* "); else printf(". "); 2.135 + } 2.136 + printf("\n"); 2.137 + } 2.138 + printf("\n"); 2.139 +#endif 2.140 + 2.141 + printf("Press ENTER to stop the simulation.\n"); 2.142 + 2.143 + // run game 2.144 + while (!kbhit() && !steadyState) { 2.145 + // increase iteration counter 2.146 + iteration++; 2.147 + 2.148 + // save current game grid 2.149 + memcpy(&old_gamegrid, &gamegrid, sizeof(gamegrid)); 2.150 + 2.151 + // loop over game grid 2.152 + for (y=0; y<6; y++) { 2.153 + for (x=0; x<6; x++) { 2.154 + nei = 0; 2.155 + 2.156 + // count neighbours 2.157 + if (y > 0) { 2.158 + if (x > 0) { if (old_gamegrid[y-1][x-1]) nei++; } 2.159 + if (old_gamegrid[y-1][x]) nei++; 2.160 + if (x < 5) { if (old_gamegrid[y-1][x+1]) nei++; } 2.161 + } 2.162 + if (x > 0) { if (old_gamegrid[y][x-1]) nei++; } 2.163 + // old_gamegrid[x][y] is us! 2.164 + if (x < 5) { if (old_gamegrid[y][x+1]) nei++; } 2.165 + if (y < 5) { 2.166 + if (x > 0) { if (old_gamegrid[y+1][x-1]) nei++; } 2.167 + if (old_gamegrid[y+1][x]) nei++; 2.168 + if (x < 5) { if (old_gamegrid[y+1][x+1]) nei++; } 2.169 + } 2.170 + 2.171 + // so what happens to our cell? 2.172 + if (old_gamegrid[y][x]) { 2.173 + // --- rules for live cells --- 2.174 + if ((nei < 2) || (nei > 3)) { 2.175 + // <2 neighbours, death due to loneliness. 2.176 + // or >3 neighbours, death due to overcrowding. 2.177 + gamegrid[y][x] = false; 2.178 + } 2.179 + } else { 2.180 + // --- rules for dead cells --- 2.181 + if (nei == 3) { 2.182 + // any dead cell with three neighbours comes to life 2.183 + gamegrid[y][x] = true; 2.184 + } 2.185 + } 2.186 + } 2.187 + } 2.188 + 2.189 + if (memcmp(&gamegrid, &old_gamegrid, sizeof(gamegrid)) == 0) { 2.190 + steadyState = true; 2.191 + } 2.192 + 2.193 +#ifdef DEBUG 2.194 + printf("GAME GRID: [iter %lu]\n", iteration); 2.195 + for (y=0; y<6; y++) { 2.196 + for (x=0; x<6; x++) { 2.197 + if (gamegrid[y][x]) printf("* "); else printf(". "); 2.198 + } 2.199 + printf("\n"); 2.200 + } 2.201 + printf("\n"); 2.202 +#endif 2.203 + 2.204 + // now update the LPFK from the game grid 2.205 + for (i=0; i<32; i++) { 2.206 + if (i < 4) lpfk_set_led_cached(&ctx, i, gamegrid[0][i+1]); 2.207 + else if (i < 10) lpfk_set_led_cached(&ctx, i, gamegrid[1][i-4]); 2.208 + else if (i < 16) lpfk_set_led_cached(&ctx, i, gamegrid[2][i-10]); 2.209 + else if (i < 22) lpfk_set_led_cached(&ctx, i, gamegrid[3][i-16]); 2.210 + else if (i < 28) lpfk_set_led_cached(&ctx, i, gamegrid[4][i-22]); 2.211 + else lpfk_set_led_cached(&ctx, i, gamegrid[5][(i-28)+1]); 2.212 + } 2.213 + 2.214 + // flush updates to the LPFK 2.215 + lpfk_update_leds(&ctx); 2.216 + 2.217 + // make sure updates aren't too fast 2.218 + sleep(1); 2.219 + } 2.220 + 2.221 + if (steadyState) { 2.222 + printf("Steady state reached.\n"); 2.223 + } 2.224 + printf("LPFK Life ran for %lu iterations.\n", iteration); 2.225 + 2.226 + // close the LPFK 2.227 + lpfk_close(&ctx); 2.228 +}