diff --git a/Board.cpp b/Board.cpp deleted file mode 100644 index cea63fc..0000000 --- a/Board.cpp +++ /dev/null @@ -1,279 +0,0 @@ -#include "Board.h" - -void Board::bin(unsigned long n) { - unsigned long k; - for (int i = 31; i >= 0; --i) { - k = (unsigned long) 1 << i; - if (k & n) { - Serial.print("1"); - } - else { - Serial.print("0"); - } - } - Serial.println(); -} - -void Board::solve() { - Serial.println("Solution: "); - bool TEMP[RC] = {false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false - }; - mvm(R, GAME_BOARD, TEMP); - for (byte i = ZERO; i < RC; ++i) { - if (TEMP[i]) { - toggle(i); - Serial.println(i); - printSerial(); - } - } -} - -/* Call reset before */ -void Board::randomize() { - unsigned long minMoves = random(5, 25); - unsigned long randomBits = nrand25(minMoves); - unsigned long k; - bool TEMP[RC] = {false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false - }; - for (unsigned long i = 0; i < 25; ++i) { - k = 1 << i; - if (k & randomBits) { - TEMP[(byte) i] = true; - } - } - mvm(A, TEMP); -} - -/* - void Board::randomize(int difficulty) { - unsigned long minMoves = 0; - if (difficulty == 1) { - minMoves = random(5, 11); - } - else if (difficulty == 2) { - minMoves = random(10, 16); - } - else if (difficulty == 3) { - minMoves = random(15, 21); - } - else if (difficulty == 4) { - minMoves = random(20, 25); - } - else { - minMoves = random(5, 25); - } - Serial.print("Min Moves: "); - Serial.println(minMoves, DEC); - unsigned long randomBits = nrand25(minMoves); - Serial.print("Random Bits Integer: "); - Serial.println(randomBits, DEC); - Serial.print("Binary: "); - bin(randomBits); - Serial.print("Binary: "); - Serial.println(randomBits, BIN); - - unsigned long k; - - bool TEMP[RC] = {false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false - }; - for (unsigned long i = 0; i < 25; ++i) { - k = 1 << i; - if (k & randomBits) { - TEMP[(byte) i] = true; - } - } - mvm(A, TEMP); - }*/ - -/* Excludes n, so call with n + 1. */ -int Board::randto(int n) { - int r = random(0, n); - return r; -} - -void Board::shuffle(int *x, int n) { - for (int i = 0; i < n; ++i) { - int j = randto(25); - int tmp = x[i]; - x[i] = x[j]; - x[j] = tmp; - } -} - -/* Produces a "random" 25 bit integer with n bits set to 1. */ -unsigned long Board::nrand25(int n) { - unsigned long v = 0; - int pos[25] = {0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24 - }; - shuffle(pos, 25); - for (int i = 0; i < n; ++i) { - unsigned long k = 1; - v |= (k << pos[i]); - } - return v; -} - -/* All lights off. */ -void Board::reset() { - for (byte row = 0; row < RC; ++row) { - GAME_BOARD[row] = false; - } -} - -bool Board::isWin() { - for (byte row = 0; row < RC; ++row) { - if (GAME_BOARD[row]) { - return false; - } - } - return true; -} - -/* Corresponds to XOR. - +|0|1| - 0|0|1| - 1|1|0| -*/ -bool Board::add(bool p1, bool p2) { - - if (p1 && !p2 || !p1 && p2) { - return true; - } - else { - return false; - } -} - -/* Corresponds to AND. - x|0|1| - 0|0|0| - 1|0|1| -*/ -bool Board::multiply(bool p1, bool p2) { - if (p1 && p2) { - return true; - } - else { - return false; - } -} - -/* Matrix Vector Multiply */ -void Board::mvm(const bool(&mat)[RC][RC], bool(&vec)[RC]) { - for (byte i = 0; i < RC; ++i) { - GAME_BOARD[i] = dot(mat[i], vec); - } -} - -/* Matrix Vector Multiply */ -void Board::mvm(const bool(&mat)[RC][RC], bool(&vec)[RC], bool(&result)[RC]) { - for (byte i = 0; i < RC; ++i) { - result[i] = dot(mat[i], vec); - } -} - -/* 25x1 Vector Dot Product */ -bool Board::dot(const bool(&v1)[RC], bool(&v2)[RC]) { - bool temp[RC] = {false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false - }; - bool result = true; - for (byte i = 0; i < RC; ++i) { - temp[i] = multiply(v1[i], v2[i]); - } - for (byte i = 0; i < RC; ++i) { - if (i == 0) { - result = temp[0]; - } else { - result = add(result, temp[i]); - } - } - return result; -} - - -/* True if board is solvable, false if not. */ -bool Board::isSolvable() { - bool s1 = false; - bool s2 = false; - - s1 = dot(SOLVABLE1, GAME_BOARD); - s2 = dot(SOLVABLE2, GAME_BOARD); - - if (!s1 && !s2) { - return true; - } - else { - return false; - } -} - -/* Sets 0-indexed grid number to true/false without toggling adjacent squares */ -void Board::set(byte gridNum, bool state) { - GAME_BOARD[gridNum] = state; -} - -/* Toggles 0-indexed square and adjacent squares. */ -void Board::toggle(byte gridNum) { - /* Error checking for valid range? */ - /* Toggle the square itself. */ - GAME_BOARD[gridNum] = !GAME_BOARD[gridNum]; - - /* North Adjacent only when row > 4 */ - if (gridNum > FOUR) { - GAME_BOARD[gridNum - FIVE] = !GAME_BOARD[gridNum - FIVE]; - } - - /* South adjacent only when row < 20 */ - if (gridNum < TWENTY) { - GAME_BOARD[gridNum + FIVE] = !GAME_BOARD[gridNum + FIVE]; - } - - /* East adjacent only when row MOD 5 != 4 */ - if (gridNum % FIVE != FOUR) { - GAME_BOARD[gridNum + ONE] = !GAME_BOARD[gridNum + ONE]; - } - - /* West adjacent only when row MOD 5 != 0 */ - if (gridNum % FIVE != ZERO) { - GAME_BOARD[gridNum - ONE] = !GAME_BOARD[gridNum - ONE]; - } -} - -void Board::printSerial() { - for (byte i = 0; i < RC; ++i) { - if (GAME_BOARD[i]) { - Serial.print("| ON"); - } - else { - Serial.print("|OFF"); - } - if (i % FIVE == 4) { - Serial.println("|"); - } - } - Serial.println(); -} - - - - - - diff --git a/Board.h b/Board.h deleted file mode 100644 index 128dc04..0000000 --- a/Board.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - FALSE = OFF 0 - TRUE = ON 1 - - | 0| 1| 2| 3| 4| - | 5| 6| 7| 8| 9| - |10|11|12|13|14| - |15|16|17|18|19| - |20|21|22|23|24| - -*/ -#ifndef BOARD_LIGHTSOUT_H -#define BOARD_LIGHTSOUT_H - -#include "Arduino.h" - -class Board { - public: - static const byte FIVE = 5; - static const byte FOUR = 4; - static const byte ZERO = 0; - static const byte TWENTY = 20; - static const byte ONE = 1; - static const byte RC = 25; - - void randomize(); - int randto(int); - void shuffle(int *, int); - unsigned long nrand25(int); - - void set(byte, bool); /* Sets 0-indexed grid number to true/false without toggling adjacent squares */ - void toggle(byte); /* Toggle by 0-indexed grid number */ - bool isWin(); - bool isSolvable(); - void reset(); - void solve(); - - bool add(bool, bool); - bool multiply(bool, bool); - void mvm(const bool(&)[RC][RC], bool(&)[RC]); - void mvm(const bool(&)[RC][RC], bool(&)[RC], bool(&)[RC]); - bool dot(const bool(&)[RC], bool(&)[RC]); - - void printSerial(); - void bin(unsigned long); - - bool GAME_BOARD[RC] = {false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false, - false, false, false, false, false - }; - - /* If board is orthogonal to these, then it is solvable. */ - const bool SOLVABLE1[RC] = {false, true, true, true, false, - true, false, true, false, true, - true, true, false, true, true, - true, false, true, false, true, - false, true, true, true, false - }; - - const bool SOLVABLE2[RC] = {true, false, true, false, true, - true, false, true, false, true, - false, false, false, false, false, - true, false, true, false, true, - true, false, true, false, true - }; - - const bool A[RC][RC] = {{true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, false, true, true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {true, false, false, false, false, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, false, false, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, true, false, false, false, false, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false}, - {false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false}, - {false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, false}, - {false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, true, true, false, false, false, true, false, false, false, false}, - {false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, false, false, false, false, true}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, true, true, false, false, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true} - }; - /* Product of the elementary matrices that make up the row operations for Gaussian elimination. */ - const bool R[RC][RC] = {{false, false, false, false, false, true, false, false, false, false, true, true, false, false, false, true, false, true, false, false, false, true, true, true, false}, - {false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, false, false, true, false, true, true, false, true, true}, - {false, false, false, true, false, false, false, false, true, true, false, false, true, true, false, false, true, false, true, false, true, true, true, false, true}, - {false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, true, false, false, false, false, false, true, true, true}, - {false, false, false, true, true, false, false, true, false, true, false, true, true, true, false, true, false, false, false, false, true, false, true, true, false}, - {false, false, true, false, true, false, true, true, false, true, false, false, true, false, false, false, false, false, true, true, false, false, false, false, false}, - {false, false, true, false, false, false, true, true, true, false, true, true, false, false, true, false, true, false, false, true, false, false, true, true, false}, - {false, false, false, false, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true}, - {false, false, true, false, false, false, true, true, true, false, true, false, false, true, true, true, false, false, true, false, false, true, true, false, false}, - {false, false, true, false, true, false, true, true, false, true, true, false, true, false, true, true, true, false, false, false, true, false, false, false, true}, - {false, false, false, false, true, false, false, false, true, true, false, false, true, false, true, true, true, true, true, false, false, true, false, false, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false}, - {false, false, false, true, true, false, false, true, false, false, false, true, true, false, true, true, false, false, false, true, true, false, true, true, false}, - {false, false, true, true, true, false, true, false, true, false, true, true, true, false, false, false, false, false, true, false, true, true, false, true, true}, - {false, false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, false, false, true, false, true, true}, - {false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, false, true, true, false, true, false, false}, - {false, false, true, true, false, false, true, false, false, true, true, true, false, false, true, false, true, true, true, false, false, false, true, false, false}, - {false, false, true, false, true, false, true, true, false, true, true, false, true, false, false, true, true, false, true, true, true, false, false, false, false}, - {false, false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, true, false, true, false}, - {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true}, - {false, false, false, true, true, false, false, true, false, false, false, true, true, false, true, true, false, true, false, true, true, true, false, false, false}, - {false, false, true, true, true, false, true, false, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, false}, - {false, false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, true, false, false, false}, - {true, false, true, false, true, true, false, true, false, true, false, false, false, false, false, true, false, true, false, true, true, false, true, false, true}, - {false, true, true, true, false, true, false, true, false, true, true, true, false, true, true, true, false, true, false, true, false, true, true, true, false} - }; -}; -#endif - - - - - - diff --git a/KeypadWrapper.cpp b/KeypadWrapper.cpp deleted file mode 100644 index dd7bde2..0000000 --- a/KeypadWrapper.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "KeypadWrapper.h" - -KeypadWrapper::KeypadWrapper() { - kpd = Keypad(makeKeymap(KEY_MAP), ROW_PINS, COL_PINS, 5, 5); - kpd.setDebounceTime(100); -} - -KeypadWrapper::KeypadWrapper(byte *rpins, byte *cpins) { - for (byte i = 0; i < 5; ++i) { - ROW_PINS[i] = rpins[i]; - COL_PINS[i] = cpins[i]; - } - kpd = Keypad(makeKeymap(KEY_MAP), ROW_PINS, COL_PINS, 5, 5); - kpd.setDebounceTime(100); -} - -int KeypadWrapper::pollKeypad() { - if (kpd.getKeys()) { - int count = 0; - for (int i = 0; i < LIST_MAX; i++) { - if (kpd.key[i].kstate == HOLD) { - ++count; - if (count == 4) { - return -1; - } - } - else if (kpd.key[i].kstate == PRESSED) { - if (kpd.key[i].kchar == 'a') { - return 0; - } - else if (kpd.key[i].kchar == 'b') { - return 1; - } - else if (kpd.key[i].kchar == 'c') { - return 2; - } - else if (kpd.key[i].kchar == 'd') { - return 3; - } - else if (kpd.key[i].kchar == 'e') { - return 4; - } - else if (kpd.key[i].kchar == 'f') { - return 5; - } - else if (kpd.key[i].kchar == 'g') { - return 6; - } - else if (kpd.key[i].kchar == 'h') { - return 7; - } - else if (kpd.key[i].kchar == 'i') { - return 8; - } - else if (kpd.key[i].kchar == 'j') { - return 9; - } - else if (kpd.key[i].kchar == 'k') { - return 10; - } - else if (kpd.key[i].kchar == 'l') { - return 11; - } - else if (kpd.key[i].kchar == 'm') { - return 12; - } - else if (kpd.key[i].kchar == 'n') { - return 13; - } - else if (kpd.key[i].kchar == 'o') { - return 14; - } - else if (kpd.key[i].kchar == 'p') { - return 15; - } - else if (kpd.key[i].kchar == 'q') { - return 16; - } - else if (kpd.key[i].kchar == 'r') { - return 17; - } - else if (kpd.key[i].kchar == 's') { - return 18; - } - else if (kpd.key[i].kchar == 't') { - return 19; - } - else if (kpd.key[i].kchar == 'u') { - return 20; - } - else if (kpd.key[i].kchar == 'v') { - return 21; - } - else if (kpd.key[i].kchar == 'w') { - return 22; - } - else if (kpd.key[i].kchar == 'x') { - return 23; - } - else if (kpd.key[i].kchar == 'y') { - return 24; - } - } - } - } - else { - return 128; - } -} - diff --git a/KeypadWrapper.h b/KeypadWrapper.h deleted file mode 100644 index d7d402b..0000000 --- a/KeypadWrapper.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Pushing and holding any four buttons at the same time will trigger a new game. -*/ - -#ifndef KEYPADWRAPPER_H -#define KEYPADWRAPPER_H - -#include "Keypad.h" - -class KeypadWrapper { - public: - KeypadWrapper(); - KeypadWrapper(byte *, byte *); - int pollKeypad(); - - private: - byte ROW_PINS[5] = {2, 3, 4, 5, 6}; - byte COL_PINS[5] = {7, 8, 9, 10, 11}; - char KEY_MAP [5][5] = {{'a', 'b', 'c', 'd', 'e'}, - {'f', 'g', 'h', 'i', 'j'}, - {'k', 'l', 'm', 'n', 'o'}, - {'p', 'q', 'r', 's', 't'}, - {'u', 'v', 'w', 'x', 'y'} - }; - Keypad &kpd; -}; - - -#endif - diff --git a/MasterController.ino b/MasterController.ino deleted file mode 100644 index e84cfcd..0000000 --- a/MasterController.ino +++ /dev/null @@ -1,193 +0,0 @@ -#include "I2C.h" -#include "Board.h" -#include "KeypadWrapper.h" - -bool inGame; -I2C_Master mcomm; -Board board; -KeypadWrapper kpdw; - -void gameReset() { - mcomm.write(RESET); - inGame = true; - board.reset(); - board.randomize(); - for (byte i = board.ZERO; i < board.RC; ++i) { - if (board.GAME_BOARD[i]) { - if (i == 0) { - mcomm.write(SET0); - } - else if (i == 1) { - mcomm.write(SET1); - } - else if (i == 2) { - mcomm.write(SET2); - } - else if (i == 3) { - mcomm.write(SET3); - } - else if (i == 4) { - mcomm.write(SET4); - } - else if (i == 5) { - mcomm.write(SET5); - } - else if (i == 6) { - mcomm.write(SET6); - } - else if (i == 7) { - mcomm.write(SET7); - } - else if (i == 8) { - mcomm.write(SET8); - } - else if (i == 9) { - mcomm.write(SET9); - } - else if (i == 10) { - mcomm.write(SET10); - } - else if (i == 11) { - mcomm.write(SET11); - } - else if (i == 12) { - mcomm.write(SET12); - } - else if (i == 13) { - mcomm.write(SET13); - } - else if (i == 14) { - mcomm.write(SET14); - } - else if (i == 15) { - mcomm.write(SET15); - } - else if (i == 16) { - mcomm.write(SET16); - } - else if (i == 17) { - mcomm.write(SET17); - } - else if (i == 18) { - mcomm.write(SET18); - } - else if (i == 19) { - mcomm.write(SET19); - } - else if (i == 20) { - mcomm.write(SET20); - } - else if (i == 21) { - mcomm.write(SET21); - } - else if (i == 22) { - mcomm.write(SET22); - } - else if (i == 23) { - mcomm.write(SET23); - } - else if (i == 24) { - mcomm.write(SET24); - } - } - } - mcomm.write(FIN); -} - -void setup() { - mcomm.init(); - inGame = false; -} - -void loop() { - int keyEvent = kpdw.pollKeypad(); - if (keyEvent == 128) {} - else if (keyEvent == -1) { - gameReset(); - } - else if (keyEvent >= 0 && keyEvent <= 24) { - if (keyEvent == 0) { - mcomm.write(TOGGLE0); - } - else if (keyEvent == 1) { - mcomm.write(TOGGLE1); - } - else if (keyEvent == 2) { - mcomm.write(TOGGLE2); - } - else if (keyEvent == 3) { - mcomm.write(TOGGLE3); - } - else if (keyEvent == 4) { - mcomm.write(TOGGLE4); - } - else if (keyEvent == 5) { - mcomm.write(TOGGLE5); - } - else if (keyEvent == 6) { - mcomm.write(TOGGLE6); - } - else if (keyEvent == 7) { - mcomm.write(TOGGLE7); - } - else if (keyEvent == 8) { - mcomm.write(TOGGLE8); - } - else if (keyEvent == 9) { - mcomm.write(TOGGLE9); - } - else if (keyEvent == 10) { - mcomm.write(TOGGLE10); - } - else if (keyEvent == 11) { - mcomm.write(TOGGLE11); - } - else if (keyEvent == 12) { - mcomm.write(TOGGLE12); - } - else if (keyEvent == 13) { - mcomm.write(TOGGLE13); - } - else if (keyEvent == 14) { - mcomm.write(TOGGLE14); - } - else if (keyEvent == 15) { - mcomm.write(TOGGLE15); - } - else if (keyEvent == 16) { - mcomm.write(TOGGLE16); - } - else if (keyEvent == 17) { - mcomm.write(TOGGLE17); - } - else if (keyEvent == 18) { - mcomm.write(TOGGLE18); - } - else if (keyEvent == 19) { - mcomm.write(TOGGLE19); - } - else if (keyEvent == 20) { - mcomm.write(TOGGLE20); - } - else if (keyEvent == 21) { - mcomm.write(TOGGLE21); - } - else if (keyEvent == 22) { - mcomm.write(TOGGLE22); - } - else if (keyEvent == 23) { - mcomm.write(TOGGLE23); - } - else if (keyEvent == 24) { - mcomm.write(TOGGLE24); - } - mcomm.write(FIN); - if (board.isWin()) { - mcomm.write(WIN); - inGame = false; - mcomm.write(FIN); - } - } - -} - diff --git a/MasterController/Board.cpp b/MasterController/Board.cpp new file mode 100644 index 0000000..a742d18 --- /dev/null +++ b/MasterController/Board.cpp @@ -0,0 +1,368 @@ +#include "Board.h" + + /* If board is orthogonal to these, then it is solvable. */ + const bool SOLVABLE1[25] = {false, true, true, true, false, + true, false, true, false, true, + true, true, false, true, true, + true, false, true, false, true, + false, true, true, true, false + }; + + const bool SOLVABLE2[25] = {true, false, true, false, true, + true, false, true, false, true, + false, false, false, false, false, + true, false, true, false, true, + true, false, true, false, true + }; + + const bool A[25][25] = {{true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, true, true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {true, false, false, false, false, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, true, false, false, false, false, true, true, false, false, false, true, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, true, true, false, false, false, true, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, true, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, false, false, false, false, true}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, true, true, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true} + }; + + /* Product of the elementary matrices that make up the row operations for Gaussian elimination. */ + const bool R[25][25] = {{false, false, false, false, false, true, false, false, false, false, true, true, false, false, false, true, false, true, false, false, false, true, true, true, false}, + {false, false, false, false, false, false, true, false, false, false, true, true, true, false, false, false, false, false, true, false, true, true, false, true, true}, + {false, false, false, true, false, false, false, false, true, true, false, false, true, true, false, false, true, false, true, false, true, true, true, false, true}, + {false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, true, false, false, false, false, false, true, true, true}, + {false, false, false, true, true, false, false, true, false, true, false, true, true, true, false, true, false, false, false, false, true, false, true, true, false}, + {false, false, true, false, true, false, true, true, false, true, false, false, true, false, false, false, false, false, true, true, false, false, false, false, false}, + {false, false, true, false, false, false, true, true, true, false, true, true, false, false, true, false, true, false, false, true, false, false, true, true, false}, + {false, false, false, false, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true}, + {false, false, true, false, false, false, true, true, true, false, true, false, false, true, true, true, false, false, true, false, false, true, true, false, false}, + {false, false, true, false, true, false, true, true, false, true, true, false, true, false, true, true, true, false, false, false, true, false, false, false, true}, + {false, false, false, false, true, false, false, false, true, true, false, false, true, false, true, true, true, true, true, false, false, true, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, true, true, false, false}, + {false, false, false, true, true, false, false, true, false, false, false, true, true, false, true, true, false, false, false, true, true, false, true, true, false}, + {false, false, true, true, true, false, true, false, true, false, true, true, true, false, false, false, false, false, true, false, true, true, false, true, true}, + {false, false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, false, false, true, false, true, true}, + {false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, false, true, true, false, true, false, false}, + {false, false, true, true, false, false, true, false, false, true, true, true, false, false, true, false, true, true, true, false, false, false, true, false, false}, + {false, false, true, false, true, false, true, true, false, true, true, false, true, false, false, true, true, false, true, true, true, false, false, false, false}, + {false, false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, true, false, true, false}, + {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true}, + {false, false, false, true, true, false, false, true, false, false, false, true, true, false, true, true, false, true, false, true, true, true, false, false, false}, + {false, false, true, true, true, false, true, false, true, false, true, true, true, false, false, false, false, false, false, false, true, true, true, false, false}, + {false, false, false, true, false, false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, true, false, false, false}, + {true, false, true, false, true, true, false, true, false, true, false, false, false, false, false, true, false, true, false, true, true, false, true, false, true}, + {false, true, true, true, false, true, false, true, false, true, true, true, false, true, true, true, false, true, false, true, false, true, true, true, false} + }; + +void Board::bin(unsigned long n) { + unsigned long k; + for (int i = 31; i >= 0; --i) { + k = (unsigned long) 1 << i; + if (k & n) { + Serial.print("1"); + } + else { + Serial.print("0"); + } + } + Serial.println(); +} + +void Board::solve() { + Serial.println("Solution: "); + bool TEMP[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; + + mvm(R, GAME_BOARD, TEMP); + for (byte i = ZERO; i < RC; ++i) { + if (TEMP[i]) { + toggle(i); + Serial.println(i); + printSerial(); + } + } +} + +void Board::setsolution(){ + bool TEMP[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; + mvm(R, GAME_BOARD, TEMP); + for (byte i = ZERO; i < RC; ++i) { + solution = "hello"; + } +} + +/* Call reset before */ +void Board::randomize() { + + unsigned long minMoves = random(5, 25); + unsigned long randomBits = nrand25(minMoves); + unsigned long k; + bool TEMP[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; + for (unsigned long i = 0; i < 25; ++i) { + k = 1 << i; + if (k & randomBits) { + TEMP[(byte) i] = true; + } + } + mvm(A, TEMP); + for (int i = 0; i < RC; ++i){ + INITIAL_BOARD[i] = GAME_BOARD[i]; + } + //setsolution(); +} + +/* + void Board::randomize(int difficulty) { + unsigned long minMoves = 0; + if (difficulty == 1) { + minMoves = random(5, 11); + } + else if (difficulty == 2) { + minMoves = random(10, 16); + } + else if (difficulty == 3) { + minMoves = random(15, 21); + } + else if (difficulty == 4) { + minMoves = random(20, 25); + } + else { + minMoves = random(5, 25); + } + Serial.print("Min Moves: "); + Serial.println(minMoves, DEC); + unsigned long randomBits = nrand25(minMoves); + Serial.print("Random Bits Integer: "); + Serial.println(randomBits, DEC); + Serial.print("Binary: "); + bin(randomBits); + Serial.print("Binary: "); + Serial.println(randomBits, BIN); + + unsigned long k; + + bool TEMP[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; + for (unsigned long i = 0; i < 25; ++i) { + k = 1 << i; + if (k & randomBits) { + TEMP[(byte) i] = true; + } + } + mvm(A, TEMP); + }*/ + +/* Excludes n, so call with n + 1. */ +int Board::randto(int n) { + int r = random(0, n); + return r; +} + +void Board::shuffle(int *x, int n) { + for (int i = 0; i < n; ++i) { + int j = randto(25); + int tmp = x[i]; + x[i] = x[j]; + x[j] = tmp; + } +} + +/* Produces a "random" 25 bit integer with n bits set to 1. */ +unsigned long Board::nrand25(int n) { + unsigned long v = 0; + int pos[25] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24 + }; + shuffle(pos, 25); + for (int i = 0; i < n; ++i) { + unsigned long k = 1; + v |= (k << pos[i]); + } + return v; +} + +/* All lights off. */ +void Board::reset() { + for (byte row = 0; row < RC; ++row) { + INITIAL_BOARD[row] = GAME_BOARD[row] = false; + } +} + +bool Board::isWin() { + for (byte row = 0; row < RC; ++row) { + if (GAME_BOARD[row]) { + return false; + } + } + return true; +} + +/* Corresponds to XOR. + +|0|1| + 0|0|1| + 1|1|0| +*/ +bool Board::add(bool p1, bool p2) { + + if (p1 && !p2 || !p1 && p2) { + return true; + } + else { + return false; + } +} + +/* Corresponds to AND. + x|0|1| + 0|0|0| + 1|0|1| +*/ +bool Board::multiply(bool p1, bool p2) { + if (p1 && p2) { + return true; + } + else { + return false; + } +} + +/* Matrix Vector Multiply */ +void Board::mvm(const bool(&mat)[RC][RC], bool(&vec)[RC]) { + for (byte i = 0; i < RC; ++i) { + GAME_BOARD[i] = dot(mat[i], vec); + } +} + +/* Matrix Vector Multiply */ +void Board::mvm(const bool(&mat)[RC][RC], bool(&vec)[RC], bool(&result)[RC]) { + for (byte i = 0; i < RC; ++i) { + result[i] = dot(mat[i], vec); + } +} + +/* 25x1 Vector Dot Product */ +bool Board::dot(const bool(&v1)[RC], bool(&v2)[RC]) { + bool temp[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; + bool result = true; + for (byte i = 0; i < RC; ++i) { + temp[i] = multiply(v1[i], v2[i]); + } + for (byte i = 0; i < RC; ++i) { + if (i == 0) { + result = temp[0]; + } else { + result = add(result, temp[i]); + } + } + return result; +} + + +/* True if board is solvable, false if not. */ +bool Board::isSolvable() { + bool s1 = false; + bool s2 = false; + + s1 = dot(SOLVABLE1, GAME_BOARD); + s2 = dot(SOLVABLE2, GAME_BOARD); + + if (!s1 && !s2) { + return true; + } + else { + return false; + } +} + +/* Sets 0-indexed grid number to true/false without toggling adjacent squares */ +void Board::set(byte gridNum, bool state) { + GAME_BOARD[gridNum] = state; +} + +/* Toggles 0-indexed square and adjacent squares. */ +void Board::toggle(byte gridNum) { + /* Error checking for valid range? */ + /* Toggle the square itself. */ + GAME_BOARD[gridNum] = !GAME_BOARD[gridNum]; + + /* North Adjacent only when row > 4 */ + if (gridNum > FOUR) { + GAME_BOARD[gridNum - FIVE] = !GAME_BOARD[gridNum - FIVE]; + } + + /* South adjacent only when row < 20 */ + if (gridNum < TWENTY) { + GAME_BOARD[gridNum + FIVE] = !GAME_BOARD[gridNum + FIVE]; + } + + /* East adjacent only when row MOD 5 != 4 */ + if (gridNum % FIVE != FOUR) { + GAME_BOARD[gridNum + ONE] = !GAME_BOARD[gridNum + ONE]; + } + + /* West adjacent only when row MOD 5 != 0 */ + if (gridNum % FIVE != ZERO) { + GAME_BOARD[gridNum - ONE] = !GAME_BOARD[gridNum - ONE]; + } +} + +void Board::printSerial() { + for (byte i = 0; i < RC; ++i) { + if (GAME_BOARD[i]) { + Serial.print("| ON"); + } + else { + Serial.print("|OFF"); + } + if (i % FIVE == 4) { + Serial.println("|"); + } + } + Serial.println(); +} + + + + + + diff --git a/MasterController/Board.h b/MasterController/Board.h new file mode 100644 index 0000000..2e91579 --- /dev/null +++ b/MasterController/Board.h @@ -0,0 +1,71 @@ +/* + FALSE = OFF 0 + TRUE = ON 1 + + | 0| 1| 2| 3| 4| + | 5| 6| 7| 8| 9| + |10|11|12|13|14| + |15|16|17|18|19| + |20|21|22|23|24| + +*/ +#ifndef BOARD_LIGHTSOUT_H +#define BOARD_LIGHTSOUT_H + +#include "Arduino.h" + + + +class Board { + public: + static const byte FIVE = 5; + static const byte FOUR = 4; + static const byte ZERO = 0; + static const byte TWENTY = 20; + static const byte ONE = 1; + static const byte RC = 25; + + void randomize(); + int randto(int); + void shuffle(int *, int); + unsigned long nrand25(int); + String solution; + + void set(byte, bool); /* Sets 0-indexed grid number to true/false without toggling adjacent squares */ + void toggle(byte); /* Toggle by 0-indexed grid number */ + bool isWin(); + bool isSolvable(); + void reset(); + void solve(); + void setsolution(); + + bool add(bool, bool); + bool multiply(bool, bool); + void mvm(const bool(&)[RC][RC], bool(&)[RC]); + void mvm(const bool(&)[RC][RC], bool(&)[RC], bool(&)[RC]); + bool dot(const bool(&)[RC], bool(&)[RC]); + + void printSerial(); + void bin(unsigned long); + + bool GAME_BOARD[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; + + bool INITIAL_BOARD[RC] = {false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false, + false, false, false, false, false + }; +}; +#endif + + + + + + diff --git a/I2C.cpp b/MasterController/I2C.cpp similarity index 100% rename from I2C.cpp rename to MasterController/I2C.cpp diff --git a/I2C.h b/MasterController/I2C.h similarity index 100% rename from I2C.h rename to MasterController/I2C.h diff --git a/MasterController/KeypadWrapper.cpp b/MasterController/KeypadWrapper.cpp new file mode 100644 index 0000000..0810b6c --- /dev/null +++ b/MasterController/KeypadWrapper.cpp @@ -0,0 +1,30 @@ +//#include "KeypadWrapper.h" +// +//KeypadWrapper::KeypadWrapper() { +// _kpd = Keypad(makeKeymap(KEY_MAP), ROW_PINS, COL_PINS, 5, 5); +// _kpd.setDebounceTime(100); +//} +// +//KeypadWrapper::KeypadWrapper(byte *rpins, byte *cpins) { +// for (byte i = 0; i < 5; ++i) { +// ROW_PINS[i] = rpins[i]; +// COL_PINS[i] = cpins[i]; +// } +// _kpd = Keypad(makeKeymap(KEY_MAP), ROW_PINS, COL_PINS, 5, 5); +// _kpd.setDebounceTime(100); +//} +// +//int KeypadWrapper::pollKeypad() { +// if (_kpd.getKeys()) { +// int count = 0; +// for (int i = 0; i < LIST_MAX; i++) { +// if (_kpd.key[i].kstate == HOLD) { +// ++count; +// if (count == 4) return -1; +// } +// else if (_kpd.key[i].kstate == PRESSED) return _kpd.key[i].kchar; +// } +// } +// else return 128; +//} + diff --git a/MasterController/KeypadWrapper.h b/MasterController/KeypadWrapper.h new file mode 100644 index 0000000..2fc310a --- /dev/null +++ b/MasterController/KeypadWrapper.h @@ -0,0 +1,30 @@ +/* + Pushing and holding any four buttons at the same time will trigger a new game. +*/ + +#ifndef KEYPADWRAPPER_H +#define KEYPADWRAPPER_H + +//#include "Keypad.h" +// +//class KeypadWrapper { +// public: +// KeypadWrapper(); +// KeypadWrapper(byte *, byte *); +// int pollKeypad(); +// +// private: +// byte ROW_PINS[5] = {6,5,4,3,2}; +// byte COL_PINS[5] = {11, 10, 9, 8, 7}; +// char KEY_MAP [5][5] = {{'a', 'b', 'c', 'd', 'e'}, +// {'f', 'g', 'h', 'i', 'j'}, +// {'k', 'l', 'm', 'n', 'o'}, +// {'p', 'q', 'r', 's', 't'}, +// {'u', 'v', 'w', 'x', 'y'} +// }; +// Keypad _kpd; +//}; + + +#endif + diff --git a/MasterController/MasterController.ino b/MasterController/MasterController.ino new file mode 100644 index 0000000..e70b26f --- /dev/null +++ b/MasterController/MasterController.ino @@ -0,0 +1,119 @@ +#include "I2C.h" +#include "Board.h" +#include +#include +#include + +LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); + +const byte ROWS = 5; +const byte COLS = 5; + +char hexaKeys[ROWS][COLS] = { + {'a','b','c','d','e'}, + {'f','g','h','i','j'}, + {'k','l','m','n','o'}, + {'p','q','r','s','t'}, + {'u','v','w','x','y'} +}; + +byte rowPins[ROWS] = {6,5,4,3,2}; +byte colPins[COLS] = {11,10,9,8,7}; +bool sol[25]; +bool ingame = false; +int score; +int hscore; +long long last_score_update = millis();; +long long start_time = millis(); +int moves = 0; + +Keypad kpad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); + +I2C_Master mcomm; +Board board; + +int pollKeypad(); +void gameReset(); +void findsolution(); +void initlcd(); + +void setup() { + lcd.begin(16,2); + initlcd(); + score = 0; + randomSeed(analogRead(0)); + mcomm.init(); + gameReset(); +} +void loop() { + if (millis() - last_score_update > 1000 && ingame){ + last_score_update = millis(); + score = max(0,9999 - moves*10*((.5*(millis()-start_time))/1000)); + lcd.setCursor(7,0); lcd.print(" "); lcd.setCursor(7,0); + lcd.print(score); + } + + int keyEvent = pollKeypad(); + if (keyEvent == 128) {} + else if (keyEvent == -1) { + gameReset(); + } + else if (keyEvent >= 0 && keyEvent <= 24) { + moves++; + mcomm.write(TOGGLE0+keyEvent); + board.toggle(keyEvent); + if (board.isWin()) { + ingame = false; + lcd.clear(); + lcd.print("You win!"); + if(score > hscore) { + lcd.setCursor(0,1); + lcd.print("New High Score!"); + EEPROM.write(0, 1); + EEPROM.put(1, score); + } + mcomm.write(WIN); + } + } +} + +int pollKeypad() { + if (kpad.getKeys()) { + int count = 0; + for (int i = 0; i < LIST_MAX; i++) { + if (kpad.key[i].kstate == HOLD) { + ++count; + if (count == 2) return -1; + } + else if (kpad.key[i].kstate == PRESSED) return kpad.key[i].kchar - 97; + } + } + + else return 128; +} + +void gameReset() { + mcomm.write(RESET); + board.reset(); + board.randomize(); + for (byte i = board.ZERO; i < board.RC; ++i) { + if (board.GAME_BOARD[i]) mcomm.write(SET0+i); + } + initlcd(); + moves = 0; + start_time = millis(); + last_score_update = -1000; + ingame = true; +} + +void initlcd(){ + lcd.clear(); + lcd.print("Score: 0"); + lcd.setCursor(0, 1); + lcd.print("Hscore: "); + if(EEPROM.read(0) == 0) hscore = 0; + else EEPROM.get(1, hscore); + lcd.print(hscore); +} + + diff --git a/MasterController/globals.h b/MasterController/globals.h new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/MasterController/globals.h @@ -0,0 +1 @@ + diff --git a/SlaveBoard/I2C.cpp b/SlaveBoard/I2C.cpp new file mode 100644 index 0000000..e21f963 --- /dev/null +++ b/SlaveBoard/I2C.cpp @@ -0,0 +1,25 @@ +#include "I2C.h" + +void I2C_Slave::init(void(*callback)()){ + Wire.begin(SLAVE_ADDR); + Wire.onReceive(callback); /* Register callback */ +} + +int I2C_Slave::available() { + return Wire.available(); +} + +EVENT I2C_Slave::read() { + return (EVENT) Wire.read(); +} + +void I2C_Master::init(){ + Wire.begin(); +} + +void I2C_Master::write(EVENT e) { + Wire.beginTransmission(SLAVE_ADDR); + Wire.write(e); + Wire.endTransmission(); +} + diff --git a/SlaveBoard/I2C.h b/SlaveBoard/I2C.h new file mode 100644 index 0000000..fdf4873 --- /dev/null +++ b/SlaveBoard/I2C.h @@ -0,0 +1,111 @@ + +#ifndef I2C_COMM_H +#define I2C_COMM_H + +#include "Wire.h" +#include "Arduino.h" + + +/* + LEDs & Switches refer to same square on grid. + + | 1| 2| 3| 4| 5| + | 6| 7| 8| 9|10| + |11|12|13|14|15| + |16|17|18|19|20| + |21|22|23|24|25| +*/ + + +enum EVENT : byte { + /* THE EVENTS LISTED HERE MAP THE ENTIRE BYTE */ + + /* TOGGLE EVENTS */ + /* UPPER 3 BITS ARE 001 */ + /* DECIMAL RANGE 33 - 57 */ + TOGGLE0 = 33, + TOGGLE1 = 34, + TOGGLE2 = 35, + TOGGLE3 = 36, + TOGGLE4 = 37, + TOGGLE5 = 38, + TOGGLE6 = 39, + TOGGLE7 = 40, + TOGGLE8 = 41, + TOGGLE9 = 42, + TOGGLE10 = 43, + TOGGLE11 = 44, + TOGGLE12 = 45, + TOGGLE13 = 46, + TOGGLE14 = 47, + TOGGLE15 = 48, + TOGGLE16 = 49, + TOGGLE17 = 50, + TOGGLE18 = 51, + TOGGLE19 = 52, + TOGGLE20 = 53, + TOGGLE21 = 54, + TOGGLE22 = 55, + TOGGLE23 = 56, + TOGGLE24 = 57, + + /* We use these for game reset. Implies board is all false, so we are setting to true. */ + /* Do not toggle neighbors. */ + SET0 = 58, + SET1 = 59, + SET2 = 60, + SET3 = 61, + SET4 = 62, + SET5 = 63, + SET6 = 64, + SET7 = 65, + SET8 = 66, + SET9 = 67, + SET10 = 68, + SET11 = 69, + SET12 = 70, + SET13 = 71, + SET14 = 72, + SET15 = 73, + SET16 = 74, + SET17 = 75, + SET18 = 76, + SET19 = 77, + SET20 = 78, + SET21 = 79, + SET22 = 80, + SET23 = 81, + SET24 = 82, + /* GAME WON */ + WIN = 96, + + /* RESET/NEW GAME */ + RESET = 160, + + /* TRANSMISSION FINISH */ + FIN = 170, + + /* MASTER ERROR */ + M_ERROR = 224 +}; + + +class I2C_Slave { + public: + const byte SLAVE_ADDR = 27; + + void init(void(*callback)()); + int available(); + EVENT read(); +}; + +class I2C_Master { + public: + const byte SLAVE_ADDR = 27; + void init(); + void write(EVENT); + +}; + +#endif + diff --git a/SlaveBoard.ino b/SlaveBoard/SlaveBoard.ino similarity index 82% rename from SlaveBoard.ino rename to SlaveBoard/SlaveBoard.ino index 6df9c27..9f5eb0b 100644 --- a/SlaveBoard.ino +++ b/SlaveBoard/SlaveBoard.ino @@ -1,5 +1,4 @@ #include "I2C.h" -#include "LiquidCrystal_I2C.h" #define ON true #define OFF false @@ -11,11 +10,16 @@ const uint8_t m_size = 5; //corresponds to current state of LEDs in matrix, 1 = on bool state[m_size*m_size]; + +//bool state[m_size*m_size] = { 0,1,1,0,1, +// 1,1,0,1,1, +// 0,0,1,0,0, +// 1,0,0,1,1, +// 1,1,1,1,1 }; uint8_t cur_row = 0; I2C_Slave slave; -LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); void eventhandle(); @@ -27,14 +31,12 @@ void setup() { digitalWrite(colpin[i], LOW); } for(int i = 0; i < m_size*m_size; ++i) state[i] = OFF; - lcd.begin(16,2); slave.init(eventhandle); } void loop() { - //turn off the other two rows - digitalWrite(rowpin[(cur_row+1)%m_size], LOW); - digitalWrite(rowpin[(cur_row+2)%m_size], LOW); + //turn off the other rows + for(int i = 1; i < m_size; ++i) digitalWrite(rowpin[(cur_row+i)%m_size], LOW); //column = LOW lets current pass, HIGH blocks current for(int col = 0; col < m_size; ++col) digitalWrite(colpin[col], !(state[(cur_row)*m_size+col])); @@ -62,20 +64,17 @@ void eventhandle(){ state[event-SET0] = ON; } else{ - lcd.clear(); switch(event){ case WIN: - lcd.write("You win"); break; case RESET: - lcd.write("Resetting"); for(byte i = 0; i < 25; ++i) state[i] = OFF; break; case M_ERROR: - lcd.write("Error"); for(byte i = 0; i < 25; ++i) state[i] = OFF; break; - default: lcd.write("Unexpected Error"); + default: + break; } } }