1.1 diff -r 81d49d42ad6a -r 2fc2b426ace9 test/lpfklife.c 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/test/lpfklife.c Tue Aug 26 21:59:54 2008 +0100 1.4 @@ -0,0 +1,225 @@ 1.5 +// lpfklife: Conway's Game of Life for the LPFK 1.6 + 1.7 +#include <stdbool.h> 1.8 +#include <stdio.h> 1.9 +#include <string.h> 1.10 +#include "liblpfk.h" 1.11 + 1.12 +/************************ 1.13 + * copied from http://linux-sxs.org/programming/kbhit.html 1.14 + */ 1.15 + 1.16 +#include <termios.h> 1.17 +#include <unistd.h> // for read() 1.18 + 1.19 +static struct termios initial_settings, new_settings; 1.20 +static int peek_character = -1; 1.21 + 1.22 +void init_keyboard() 1.23 +{ 1.24 + tcgetattr(0,&initial_settings); 1.25 + new_settings = initial_settings; 1.26 + new_settings.c_lflag &= ~ICANON; 1.27 + new_settings.c_lflag &= ~ECHO; 1.28 + new_settings.c_lflag &= ~ISIG; 1.29 + new_settings.c_cc[VMIN] = 1; 1.30 + new_settings.c_cc[VTIME] = 0; 1.31 + tcsetattr(0, TCSANOW, &new_settings); 1.32 +} 1.33 + 1.34 +void close_keyboard() 1.35 +{ 1.36 + tcsetattr(0, TCSANOW, &initial_settings); 1.37 +} 1.38 + 1.39 +int kbhit() 1.40 +{ 1.41 +unsigned char ch; 1.42 +int nread; 1.43 + 1.44 + if (peek_character != -1) return 1; 1.45 + new_settings.c_cc[VMIN]=0; 1.46 + tcsetattr(0, TCSANOW, &new_settings); 1.47 + nread = read(0,&ch,1); 1.48 + new_settings.c_cc[VMIN]=1; 1.49 + tcsetattr(0, TCSANOW, &new_settings); 1.50 + if(nread == 1) 1.51 + { 1.52 + peek_character = ch; 1.53 + return 1; 1.54 + } 1.55 + return 0; 1.56 +} 1.57 + 1.58 +int readch() 1.59 +{ 1.60 +char ch; 1.61 + 1.62 + if(peek_character != -1) 1.63 + { 1.64 + ch = peek_character; 1.65 + peek_character = -1; 1.66 + return ch; 1.67 + } 1.68 + read(0,&ch,1); 1.69 + return ch; 1.70 +} 1.71 + 1.72 +/***********************/ 1.73 + 1.74 +int main(void) 1.75 +{ 1.76 + int i, nei, x, y; 1.77 + bool old_gamegrid[6][6]; 1.78 + bool gamegrid[6][6]; 1.79 + bool steadyState = false; 1.80 + unsigned long iteration = 0; 1.81 + LPFK_CTX ctx; 1.82 + 1.83 + // initialisation 1.84 + memset(&gamegrid, 0, sizeof(gamegrid)); 1.85 + 1.86 + init_keyboard(); 1.87 + atexit(close_keyboard); 1.88 + 1.89 + // open lpfk port 1.90 + if ((i = lpfk_open(&ctx, "/dev/ttyUSB0")) != LPFK_E_OK) { 1.91 + // error opening lpfk 1.92 + printf("Error opening LPFK: code %d\n", i); 1.93 + return -1; 1.94 + } 1.95 + 1.96 + lpfk_enable(&ctx, true); 1.97 + 1.98 + // allow user to set up their game grid 1.99 + printf("Press the keys on the LPFK to set up the game grid, then press Enter to start the simulation.\n"); 1.100 + while (!kbhit()) { 1.101 + i = lpfk_read(&ctx); 1.102 + 1.103 + if (i >= 0) { 1.104 + printf("key %d\n", i); 1.105 + // Key down, toggle the LED 1.106 + lpfk_set_led(&ctx, i, !lpfk_get_led(&ctx, i)); 1.107 + 1.108 + // update game grid 1.109 + if ((i >= 0) && (i < 4)) { 1.110 + gamegrid[0][i+1] = !gamegrid[0][i+1]; // +1 because 1st row is 4-column 1.111 + } else if ((i >= 4) && (i < 10)) { 1.112 + gamegrid[1][i-4] = !gamegrid[1][i-4]; 1.113 + } else if ((i >= 10) && (i < 16)) { 1.114 + gamegrid[2][i-10] = !gamegrid[2][i-10]; 1.115 + } else if ((i >= 16) && (i < 22)) { 1.116 + gamegrid[3][i-16] = !gamegrid[3][i-16]; 1.117 + } else if ((i >= 22) && (i < 28)) { 1.118 + gamegrid[4][i-22] = !gamegrid[4][i-22]; 1.119 + } else { 1.120 + gamegrid[5][(i-28)+1] = !gamegrid[5][(i-28)+1]; // +1 because last row is 4-column 1.121 + } 1.122 + } 1.123 + } 1.124 + // flush keyboard buffer 1.125 + while (kbhit()) readch(); 1.126 + 1.127 + // disable LPFK keys 1.128 + lpfk_enable(&ctx, false); 1.129 + 1.130 +#ifdef DEBUG 1.131 + // print the game grid: debug only 1.132 + printf("GAME GRID: [iter %lu]\n", iteration); 1.133 + for (y=0; y<6; y++) { 1.134 + for (x=0; x<6; x++) { 1.135 + if (gamegrid[y][x]) printf("* "); else printf(". "); 1.136 + } 1.137 + printf("\n"); 1.138 + } 1.139 + printf("\n"); 1.140 +#endif 1.141 + 1.142 + printf("Press ENTER to stop the simulation.\n"); 1.143 + 1.144 + // run game 1.145 + while (!kbhit() && !steadyState) { 1.146 + // increase iteration counter 1.147 + iteration++; 1.148 + 1.149 + // save current game grid 1.150 + memcpy(&old_gamegrid, &gamegrid, sizeof(gamegrid)); 1.151 + 1.152 + // loop over game grid 1.153 + for (y=0; y<6; y++) { 1.154 + for (x=0; x<6; x++) { 1.155 + nei = 0; 1.156 + 1.157 + // count neighbours 1.158 + if (y > 0) { 1.159 + if (x > 0) { if (old_gamegrid[y-1][x-1]) nei++; } 1.160 + if (old_gamegrid[y-1][x]) nei++; 1.161 + if (x < 5) { if (old_gamegrid[y-1][x+1]) nei++; } 1.162 + } 1.163 + if (x > 0) { if (old_gamegrid[y][x-1]) nei++; } 1.164 + // old_gamegrid[x][y] is us! 1.165 + if (x < 5) { if (old_gamegrid[y][x+1]) nei++; } 1.166 + if (y < 5) { 1.167 + if (x > 0) { if (old_gamegrid[y+1][x-1]) nei++; } 1.168 + if (old_gamegrid[y+1][x]) nei++; 1.169 + if (x < 5) { if (old_gamegrid[y+1][x+1]) nei++; } 1.170 + } 1.171 + 1.172 + // so what happens to our cell? 1.173 + if (old_gamegrid[y][x]) { 1.174 + // --- rules for live cells --- 1.175 + if ((nei < 2) || (nei > 3)) { 1.176 + // <2 neighbours, death due to loneliness. 1.177 + // or >3 neighbours, death due to overcrowding. 1.178 + gamegrid[y][x] = false; 1.179 + } 1.180 + } else { 1.181 + // --- rules for dead cells --- 1.182 + if (nei == 3) { 1.183 + // any dead cell with three neighbours comes to life 1.184 + gamegrid[y][x] = true; 1.185 + } 1.186 + } 1.187 + } 1.188 + } 1.189 + 1.190 + if (memcmp(&gamegrid, &old_gamegrid, sizeof(gamegrid)) == 0) { 1.191 + steadyState = true; 1.192 + } 1.193 + 1.194 +#ifdef DEBUG 1.195 + printf("GAME GRID: [iter %lu]\n", iteration); 1.196 + for (y=0; y<6; y++) { 1.197 + for (x=0; x<6; x++) { 1.198 + if (gamegrid[y][x]) printf("* "); else printf(". "); 1.199 + } 1.200 + printf("\n"); 1.201 + } 1.202 + printf("\n"); 1.203 +#endif 1.204 + 1.205 + // now update the LPFK from the game grid 1.206 + for (i=0; i<32; i++) { 1.207 + if (i < 4) lpfk_set_led_cached(&ctx, i, gamegrid[0][i+1]); 1.208 + else if (i < 10) lpfk_set_led_cached(&ctx, i, gamegrid[1][i-4]); 1.209 + else if (i < 16) lpfk_set_led_cached(&ctx, i, gamegrid[2][i-10]); 1.210 + else if (i < 22) lpfk_set_led_cached(&ctx, i, gamegrid[3][i-16]); 1.211 + else if (i < 28) lpfk_set_led_cached(&ctx, i, gamegrid[4][i-22]); 1.212 + else lpfk_set_led_cached(&ctx, i, gamegrid[5][(i-28)+1]); 1.213 + } 1.214 + 1.215 + // flush updates to the LPFK 1.216 + lpfk_update_leds(&ctx); 1.217 + 1.218 + // make sure updates aren't too fast 1.219 + sleep(1); 1.220 + } 1.221 + 1.222 + if (steadyState) { 1.223 + printf("Steady state reached.\n"); 1.224 + } 1.225 + printf("LPFK Life ran for %lu iterations.\n", iteration); 1.226 + 1.227 + // close the LPFK 1.228 + lpfk_close(&ctx); 1.229 +}