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