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 +}