/* ------------------------------------------------------------------------------------
* Conway's Game of Life
*
* Really just a test for big pixel mode. Display now uses 64x32 resolution.
* Now with sound! Invention 13 by Bach.
* ToDo: Fix drawAll()
Move all arrays/matrices to header files
Annoying bug with pixels in rightmost column
*
* Auth: EA
* Last rev: 2024-01-21
* ------------------------------------------------------------------------------------
*/
#include <TinyWireM.h>
#define GRID_WIDTH 48
#define GRID_HEIGHT 32
#define PAGE_HEIGHT 4
#define I2C_ADDRESS 0x3C
//#define PIN_BTN_R 3
//#define PIN_BTN_B 4
//#define PIN_BTN_G 5
#define UINT_MAX 65535
#define SPEAKER_PIN 1
const int BTN_2_VAL PROGMEM = 646; // 590 Ω 643-647
const int BTN_3_VAL PROGMEM = 513; // 1k Ω // Rock steady 513
const byte BTN_1_2_VAL PROGMEM = 108;
const byte BTN_1_3_VAL PROGMEM = 130;
const byte BTN_TOLERANCE PROGMEM = 15;
const int BTN_REST PROGMEM = 1023;
const byte BTN_PIN PROGMEM = 3;
const byte B1_PIN PROGMEM = 4;
/*
const byte GRID_WIDTH = 48;
const byte GRID_HEIGHT = 32;
const byte PAGE_HEIGHT = 4;
const byte I2C_ADDRESS = 0x3C;
const byte PIN_BTN_R = 3;
const byte PIN_BTN_B = 4;
const byte PIN_BTN_G = 5;
*/
// 'GoL_logo', 128x64px, 1024 bytes
const byte logo[1024] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xe0, 0xf8, 0x78, 0x38, 0x38, 0x38, 0x78, 0xf8,
0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x30, 0x00, 0x00,
0x00, 0x40, 0xa0, 0x40, 0x40, 0xa0, 0x40, 0x00, 0x00, 0x00, 0xc0, 0xcc, 0x4c, 0x80, 0x00, 0x00,
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x70, 0x88, 0x04, 0x04, 0x20, 0x88, 0x70, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x80,
0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x04, 0xfc, 0x00,
0x8c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xe0, 0xf8, 0xff, 0x1f, 0x07, 0x01, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x1f,
0x07, 0x01, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0x60, 0xe0, 0xe0, 0x80, 0x00, 0x00, 0x00,
0x00, 0x82, 0xc5, 0xe2, 0xe2, 0xe5, 0x02, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xe3, 0x83, 0x00, 0x00,
0x01, 0x01, 0x00, 0x80, 0xe0, 0xe0, 0xe0, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xe0,
0x00, 0x00, 0x01, 0x01, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x80,
0x80, 0xe0, 0x60, 0x60, 0xe0, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xe1, 0xe2,
0x85, 0x05, 0x34, 0x34, 0x04, 0x05, 0x0d, 0x80, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xe0, 0x60, 0xe0, 0xe0, 0xc0, 0x00, 0x00,
0x00, 0xc0, 0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x70, 0x7c, 0x0f, 0x03, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xfc, 0x00, 0x0c,
0x0f, 0x03, 0x03, 0xff, 0xff, 0xff, 0xf0, 0xfc, 0x3f, 0x0f, 0x03, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x30, 0x3c, 0x0f, 0x03, 0x03, 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
0xc0, 0x00, 0x00, 0x80, 0xbf, 0xbf, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7c, 0x3c, 0x0f,
0x03, 0x03, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x0f, 0x00, 0x00, 0x80, 0x8c, 0x8f, 0x83, 0x3f, 0xff,
0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xc3, 0x00, 0x0f, 0x0f, 0x03, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, 0x03, 0x01,
0x01, 0x29, 0xeb, 0xe7, 0x20, 0x00, 0x90, 0xc8, 0x48, 0x48, 0xf8, 0xf3, 0x07, 0x33, 0x08, 0xf8,
0xf8, 0x10, 0xca, 0x0b, 0xfb, 0xf3, 0x13, 0x09, 0x08, 0xf8, 0xf2, 0x07, 0x07, 0xf1, 0xf8, 0x48,
0x48, 0x48, 0x78, 0x70, 0x00, 0x00, 0x00, 0xff, 0x07, 0xf3, 0xf8, 0x08, 0xeb, 0x0b, 0xfb, 0xf3,
0x03, 0x08, 0xff, 0xff, 0x08, 0x08, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xff, 0xff, 0x01, 0x00,
0x00, 0x00, 0xb0, 0x08, 0xfb, 0xfb, 0x00, 0x00, 0x08, 0xff, 0xff, 0x08, 0x08, 0x01, 0xf0, 0xfb,
0x4b, 0x4b, 0x48, 0x78, 0x70, 0x00, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3f, 0xff, 0xff, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1f, 0x7f, 0xff, 0xfc, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x02,
0x02, 0x7a, 0xfb, 0xfb, 0x80, 0x00, 0x01, 0x03, 0x82, 0xe2, 0x7b, 0x1b, 0x02, 0x00, 0x02, 0x03,
0x03, 0x82, 0xf8, 0xfa, 0x7b, 0x03, 0x02, 0x00, 0x02, 0xfb, 0xfb, 0xfa, 0x00, 0x81, 0x83, 0xe2,
0x62, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfd, 0x7b, 0x02, 0x02, 0x02, 0xfb, 0xf9,
0xfc, 0x7a, 0x03, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfa, 0xfb, 0x83, 0x82, 0xe2,
0xfa, 0x7b, 0x1b, 0xfa, 0xfb, 0xfb, 0x82, 0xe0, 0x62, 0x63, 0x03, 0x02, 0x00, 0x00, 0x01, 0xfb,
0xfa, 0xfa, 0xfa, 0xfa, 0x79, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xe0, 0xe0, 0x80, 0x00, 0x03, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x07, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x07, 0x03, 0x00, 0x00,
0x00, 0x00, 0x03, 0x07, 0x0f, 0x0c, 0x0c, 0x0e, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x0f, 0xcf, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0c, 0x0f, 0x03, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03,
0x03, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x0f, 0x0f, 0x0f, 0x03, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x07, 0x0f, 0x0f, 0x0c, 0x0c, 0x8f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe0, 0x50, 0x10, 0x0c, 0x42, 0xa7, 0x42, 0x0c, 0x10,
0x50, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07,
0x08, 0x00, 0x18, 0x00, 0x00, 0x00, 0x80, 0x20, 0x60, 0x00, 0x00, 0xc0, 0x80, 0x80, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x34, 0x02, 0x10, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x08, 0x48,
0x30, 0x30, 0x48, 0x08, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x1c, 0x08, 0x06, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x25, 0x2d, 0x60, 0x1c, 0x10, 0x0a, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x0a, 0x04, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x7c, 0x60,
0x60, 0x70, 0x3c, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x0c,
0x68, 0x68, 0x0c, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 64x32 pixels, 256 bytes
byte grid1[192] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
byte grid2[192] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/*
byte grid[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
*/
// 'side_menu_24x64', 24x64px, 192 bytes
const byte sideMenu[192] PROGMEM = {
0xff, 0x41, 0x51, 0x41, 0x51, 0x41, 0x59, 0x41, 0x59, 0x41, 0x59, 0x41, 0x5d, 0x41, 0x5d, 0x41,
0x5d, 0x41, 0x41, 0x45, 0x5d, 0x45, 0x41, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x02, 0x32, 0x4a, 0x8a, 0x02, 0xf2, 0x4a, 0x0a, 0x02, 0xf2, 0x4a, 0x0a, 0x02, 0xfa, 0x0a,
0xf2, 0x02, 0x32, 0x4a, 0x8a, 0x02, 0x02, 0xff, 0xff, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x0a,
0x0a, 0x08, 0x09, 0x0a, 0x0a, 0x08, 0x0b, 0x0a, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x08, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0xe2, 0xf2, 0xf2, 0x3a, 0x0a, 0x0a,
0x0a, 0x1a, 0x7a, 0x02, 0x02, 0x02, 0x02, 0xe2, 0x12, 0x12, 0x12, 0xe2, 0x02, 0x02, 0x02, 0xff,
0xff, 0x00, 0x0f, 0x1f, 0x3f, 0x38, 0xa0, 0xa2, 0x22, 0x3e, 0x1e, 0x1e, 0x0a, 0x08, 0xf8, 0xf9,
0xfa, 0x0a, 0x0a, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x80, 0x80, 0x82, 0xbf, 0x82, 0x80,
0x80, 0x80, 0x80, 0x80, 0xa0, 0xa0, 0xbf, 0xbf, 0xbf, 0xa0, 0xa0, 0xa0, 0xb0, 0xb8, 0x80, 0xff
/*
0xff, 0x41, 0x51, 0x41, 0x51, 0x41, 0x59, 0x41, 0x59, 0x41, 0x59, 0x41, 0x5d, 0x41, 0x5d, 0x41,
0x5d, 0x41, 0x41, 0x45, 0x5d, 0x45, 0x41, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x02, 0x32, 0x4a, 0x8a, 0x02, 0xf2, 0x4a, 0x0a, 0x02, 0xf2, 0x4a, 0x0a, 0x02, 0xfa, 0x0a,
0xf2, 0x02, 0x32, 0x4a, 0x8a, 0x02, 0x02, 0xff, 0xff, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x0a,
0x0a, 0x08, 0x09, 0x0a, 0x0a, 0x08, 0x0b, 0x0a, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x08, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff
*/
/*
0xff, 0x41, 0x51, 0x41, 0x51, 0x41, 0x59, 0x41, 0x59, 0x41, 0x59, 0x41, 0x5d, 0x41, 0x5d, 0x41,
0x5d, 0x41, 0x41, 0x45, 0x5d, 0x45, 0x41, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x02, 0xb2, 0xaa, 0x6a, 0x02, 0x72, 0xaa, 0x8a, 0x02, 0x72, 0xaa, 0x8a, 0x02, 0xfa, 0x8a,
0x72, 0x02, 0xb2, 0xaa, 0x6a, 0x02, 0x02, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff
*/
/*
0xff, 0x47, 0x43, 0x43, 0x41, 0x41, 0x71, 0x49, 0x49, 0x6d, 0x65, 0x65, 0x65, 0x65, 0x6d, 0x49, 0x49, 0x71, 0x41, 0x41, 0x43, 0x43, 0x47, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x02, 0x02, 0x02, 0x82, 0xc2, 0x42, 0x22, 0x32, 0x12, 0x12, 0x12, 0x32, 0xe2, 0xc2, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xff,
0xff, 0x00, 0xf8, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x06, 0xcc, 0xcc, 0x4e, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x03, 0x07, 0x06, 0xe6, 0x96, 0xd3, 0x7d, 0x3f, 0x07, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0xf0, 0xf8, 0x08, 0x08, 0xf0, 0x00, 0xe0, 0xf0, 0xb0, 0x90, 0x10, 0x00, 0x80, 0xc0, 0x40, 0x20, 0x20, 0x20, 0xe0, 0xc0, 0x00, 0xff,
0xff, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x80, 0xfe, 0x3f, 0x00, 0x00, 0x0c, 0x0c, 0x0e, 0x07, 0x03, 0x00, 0xff,
0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8e, 0x8e, 0x87, 0x83, 0x87, 0x87, 0x8f, 0x8e, 0x8c, 0x8c, 0x84, 0x86, 0x83, 0x80, 0xff
*/
};
const byte initializeCmds[] PROGMEM ={
// -------------- Basic settings
0xAE, // Screen Off
0x81, // Set contrast control
0x7F, // 0-FF ... default half way
0xA6, // Set normal display
//0xA7, // Inverted display
// -------------- Scrolling Commands
0x2E, // Deactivate scroll
// -------------- Addressing Commands
0x20, // Set memory addressing mode
0x00, // 0x00 Horizontal, 0x01 Vertical, 0x02 Page
// -------------- Hardware Configuration Commands
0xA1, // Set segment re-map
0xA8, // Set multiplex ratio
0x3F, // Vertical Size-1: 0x3F=63=128x64, 0x1F=31=128x32
//0x5F, // Test, stolen from library
//0x6F, // Just throwing things at it
0xC8, // Vertical scan direction: 0xC8 = TopDown, 0xC0 = DownTop
0xD3, 0x00, // Set Display Offset (default 0x00)
0xDA, // Set COM pins hardware configuration
0x12, // Alternate com config & disable com left/right
// -------------- Select screen work area
0x22, // Command, set page address range
0, // From top
7, // ..to bottom page (128x32 has, of course, 3)
0x21, // Command, set column range
0, // From col
127, // To col
// -------------- Timing and Driving Settings
0xD5, // Set display oscillator frequency 0-0xF /clock divide ratio 0-0xF
0x80, // Default value
0xD9, // Set pre-changed period
0x22, // Default 0x22
0xDB, // Set VCOMH Deselected level
0x20, // Default
// -------------- Charge pump regulator
0x8D, // Set charge pump
0x14, // VCC generated by internal DC/DC circuit
// -------------- Turn the screen back on
0xA4, // 0xA4, //Set entire display on/off
0xAF // Set display on
};
const byte digits[10][4] PROGMEM =
{
{ 0x7e, 0x81, 0x81, 0x7e },
{ 0x82, 0xff, 0x80, 0x00 },
{ 0xc2, 0xa1, 0x91, 0x8e },
{ 0x42, 0x91, 0x91, 0x6e },
{ 0x1f, 0x10, 0x10, 0xff },
{ 0x4f, 0x91, 0x91, 0x61 },
{ 0x7c, 0x92, 0x91, 0x61 },
{ 0x01, 0xf1, 0x09, 0x07 },
{ 0x6e, 0x91, 0x91, 0x6e },
{ 0x0e, 0x91, 0x51, 0x3e }
};
const int melody[] PROGMEM = {
0, 330, 440, 523, 494, 330, 494, 587, 523,
659, 415, 659, 440, 330, 440, 523, 494, 330,
494, 587,
523, 440,
0, 0, 659, 523, 659, 440, 523, 330, 392, 349, 440, 587, 698, 698, 587, 494, 587, 392, 494,
294, 349, 330, 392, 523, 659, 659, 523, 440, 523, 349, 587, 587, 494, 392, 494, 330, 523, 523, 440,
349, 440, 294, 494, 523
/*
0, 0, 0, 392, 523, 659, 587, 392, 587, 698, 659, 784, 494, 784, 523, 392,
523, 659, 587, 392, 587, 698, 659, 523, 784, 659, 1047, 880, 659, 880, 523, 659, 440, 523, 587, 740,
880, 1047, 988, 784, 587, 784, 494, 587, 392, 494, 523, 659, 784, 988, 880, 740, 622, 740, 494, 622,
370, 440, 392, 784, 784, 659, 523, 659, 440, 740, 740, 587, 494, 587, 392, 659, 659, 523, 440, 523,
370, 784, 740, 659, 622, 740, 494, 622, 659, 0, 0, 0, 784, 932, 784, 659, 784, 554, 659, 784, 659,
554, 659, 440, 0, 0, 0, 698, 880, 698, 587, 698, 494, 587, 698, 587, 494, 587, 392, 0, 0, 0, 659, 784,
659, 523, 659, 440, 523, 622, 523, 440, 523, 370, 0, 0, 0, 587, 698, 587, 494, 587, 415, 494, 587, 494,
415, 494, 330, 0, 0, 0, 330, 440, 523, 494, 330, 494, 587, 523, 440, 415, 330, 440, 523, 659, 523, 440,
523, 370, 440, 523, 440, 370, 440, 311, 523, 494, 440, 415, 494, 587, 494, 415, 494, 294, 349, 415, 349,
294, 349, 247, 349, 330, 294, 262, 330, 440, 330, 262, 330, 220, 262, 311, 262, 220, 262, 185, 262, 247,
220, 208, 494, 415, 330, 0, 330, 440, 523, 494, 330, 494, 587, 523, 440, 523, 659, 587, 494, 587, 698,
659, 523, 659, 784, 698, 659, 587, 523, 494, 523, 587, 659, 698, 587, 831, 587, 988, 587, 523, 880, 698,
587, 494, 587, 415, 494, 523, 440, 330, 440, 494, 415, 440, 330, 262, 330, 220, 0
*/
};
// 0 = 125
// 1 = 250
// 2 = 500
const byte noteDurations[] PROGMEM = {
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1,
1, 1, 1, 2, 2, 3
};
int start_seeds;
bool R_DOWN;
bool B_DOWN;
bool currentGrid = true;
int count;
bool resetting = false;
void drawSplash() {
cursorTo(0,0);
for (int i=0; i<1024; i++) {
send_data(pgm_read_byte(logo + i));
}
}
bool splashMusic() {
bool skip = false;
for (int thisNote = 0; thisNote < sizeof(melody) / sizeof(int); thisNote++)
{
long del = (long)( ( (int)pgm_read_byte(¬eDurations[thisNote]) * 250) );
int note = pgm_read_word(&melody[thisNote]);
beep(note, del);
if(digitalRead(B1_PIN) == LOW) {
skip = true;
break;
}
}
return skip;
}
// ------------------------------------------------------------------------------------
// SETUP
// ------------------------------------------------------------------------------------
void setup() {
TinyWireM.begin();
config_display();
pinMode(B1_PIN, INPUT_PULLUP);
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(SPEAKER_PIN, OUTPUT);
start_seeds = 150;
// Splash screen, intro
drawSplash();
//playEventSound(0);
if (!splashMusic())
delay(2000);
// Start everything up by resetting game.
resetGame();
/*
clearDisplay();
memset(grid1, 0, 192);
memset(grid2, 0, 192);
currentGrid = true;
count = 0;
// Wait for button input, use time taken for random seed.
// ToDo: Use millis() instead of delay().
unsigned long start = millis();
while(digitalRead(PIN_BTN_G) == HIGH) {
putPixel(0, 0, cursor, grid1);
cursor = !cursor;
delay(300);
}
//int randSeed = (int)abs(millis() - start);
int randSeed = 767;
displayNumberAt(52, 2, randSeed);
delay(2000);
//clearDisplay();
//delay(500);
drawSideMenu();
delay(1000);
displayNumberAt(107, 4, start_seeds);
delay(1000);
drawRandomDots(start_seeds, 888, grid1);
delay(1000);
*/
}
// Don't ask about this function.
unsigned int trunc_long(unsigned long val) {
unsigned int retVal;
unsigned long tmp = val;
int denm = 10;
while (tmp > UINT_MAX) {
tmp = val / denm;
denm *= 10;
}
return (unsigned int)(val / denm);
}
void resetGame() {
bool cursor = HIGH;
clearDisplay();
memset(grid1, 0, 192);
memset(grid2, 0, 192);
currentGrid = true;
count = 0;
long randSeed = millis();
int delayTime = 500;
//displayNumberAt(42, 2, (unsigned int)(randSeed & UINT_MAX));
//displayNumberAt(42, 2, static_cast<unsigned int>(randSeed));
displayNumberAt(42, 2, trunc_long(randSeed));
beep(420, 80);
delay(delayTime);
drawSideMenu();
beep(420, 80);
delay(delayTime);
displayNumberAt(107, 1, count);
beep(420, 80);
delay(delayTime);
displayNumberAt(107, 4, start_seeds);
beep(420, 80);
delay(delayTime);
drawRandomDots(start_seeds, randSeed, grid1);
delay(delayTime);
}
// ------------------------------------------------------------------------------------
// LOOP
// ------------------------------------------------------------------------------------
void loop() {
resetting = false;
// ------------------------------------------------------------------
// Main program
// ------------------------------------------------------------------
// grid1 is default from setup()
// currentGrid starts as true
byte *grd = currentGrid ? grid1 : grid2;
byte *grdBuf = currentGrid ? grid2 : grid1;
for (byte y=0; y<GRID_HEIGHT; y++) {
for (byte x=0; x<GRID_WIDTH; x++) {
bool val = pixelState(x, y, grd);
byte crowd = crowdSize(x, y, grd);
// Active cell, live or die?
if (val) {
// Underpopulation, die
if (crowd < 2)
putPixel(x, y, LOW, grdBuf);
// Overpopulation, die
if (crowd > 3)
putPixel(x, y, LOW, grdBuf);
// Stay alive
if (crowd == 2 || crowd == 3)
putPixel(x, y, HIGH, grdBuf);
}
// Empty cell, enough neighbours to come to life?
if (!val) {
if (crowd == 3)
putPixel(x, y, HIGH, grdBuf);
}
}
}
// ------------------------------------------------------------------
// Button inputs
// ------------------------------------------------------------------
int state = 0;
byte button = 0x00;
unsigned long start = millis();
while (abs(millis() - start) < 200) {
bool BTN1 = !digitalRead(B1_PIN);
state = analogRead(BTN_PIN);
if (BTN1) {
button = 1;
}
else if (state > (BTN_2_VAL - BTN_TOLERANCE) && state < (BTN_2_VAL + BTN_TOLERANCE))
button = 2;
else if (state > (BTN_3_VAL - BTN_TOLERANCE) && state < (BTN_3_VAL + BTN_TOLERANCE))
button = 3;
switch (button) {
case 1:
resetting = true;
resetGame();
break;
case 2:
if (!R_DOWN)
start_seeds += (start_seeds > 5) ? -5 : 0;
displayNumberAt(107, 4, start_seeds);
R_DOWN = true;
break;
case 3:
if (!B_DOWN)
start_seeds += (start_seeds < 9995) ? 5 : 0;
displayNumberAt(107, 4, start_seeds);
B_DOWN = true;
break;
}
}
R_DOWN = false;
B_DOWN = false;
if (!resetting) {
drawAll(grdBuf);
memset(grd, 0, 192);
currentGrid = !currentGrid;
count += 1;
// Show number of steps
displayNumberAt(107, 1, count);
}
}
void drawSideMenu() {
// 'side_menu_24x64', 24x64px, 192 bytes
for (byte y=0; y<8; y++) {
cursorTo(104, y);
for (byte x=0; x<24; x++) {
byte slice = pgm_read_byte(sideMenu + (y*24+x));
send_data(slice);
}
}
}
// ToDo: Ok, now it works. Rewrite this with for-loops instead.
//
byte crowdSize(byte x, byte y, byte *grd) {
byte crwd = 0;
if (y>0 && x>0)
if (pixelState(x-1,y-1,grd))
crwd++;
if (y>0)
if (pixelState(x,y-1,grd))
crwd++;
if (y>0 && x<GRID_WIDTH)
if (pixelState(x+1,y-1,grd))
crwd++;
if (x<GRID_WIDTH)
if (pixelState(x+1,y,grd))
crwd++;
if (y<GRID_HEIGHT-1 && x<GRID_WIDTH)
if (pixelState(x+1,y+1,grd))
crwd++;
if (y<GRID_HEIGHT-1)
if (pixelState(x,y+1,grd))
crwd++;
if (y<GRID_HEIGHT-1 && x>0)
if (pixelState(x-1,y+1,grd))
crwd++;
if (x>0)
if (pixelState(x-1,y,grd))
crwd++;
return crwd;
}
bool pixelState(byte x, byte y, byte *grd) {
byte page = y/8;
byte sy = y%8;
byte index = (page*GRID_WIDTH)+x;
// REVERSE, we'll be checking states on the other grid.
//byte *grd = currentGrid ? grid2 : grid1;
byte slice = grd[index];
return(bit_check(slice, sy));
}
/*
void drawVerify() {
for(byte y=0; y<GRID_HEIGHT*8; y++) {
for(byte x=0; x<GRID_WIDTH; x++) {
if (pixelState(x, y, grid))
putPixel(x, y, 1);
}
}
}
*/
inline byte bit_set(byte number, byte n) {
return number | ((byte)1 << n);
}
inline bool bit_check(byte number, byte n) {
return (number >> n) & (byte)1;
}
inline byte bit_set_to(byte number, byte n, bool x) {
return (number & ~((byte)1 << n)) | ((byte)x << n);
}
inline byte bit_toggle(byte number, byte n) {
return number ^ ((byte)1 << n);
}
inline byte bit_clear(byte number, byte n) {
return number & ~((byte)1 << n);
}
void clearDisplay() {
cursorTo(0,0);
for(int i=0; i<1024; i++) {
send_data(0x00);
}
}
void drawRandomDots(int num, unsigned long seed, byte *grd) {
byte x;
byte y;
randomSeed(seed);
for(int i=0; i<num; i++) {
x = random() % (GRID_WIDTH - 1);
y = random() % (GRID_HEIGHT - 1);
putPixel(x, y, HIGH, grd);
if (i % 10 == 0) {
beep(random(70, 600), 80);
}
}
}
/*
inline bool bit_check(byte number, byte n) {
return (number >> n) & (byte)1;
}
inline byte bit_set_to(byte number, byte n, bool x) {
return (number & ~((byte)1 << n)) | ((byte)x << n);
}
*/
/*
void putPixel2(byte x, byte y, bool state, byte *grd) {
byte page = y/8;
byte sy = y%8;
byte index = (page*GRID_WIDTH)+x;
byte slice1;
byte slice2;
byte slice = grd[index];
slice1 = (slice1 & ~((byte)1 << pos1)) | ((byte)((number >> n) & (byte)1) << pos1);
slice1 = (slice1 & ~((byte)1 << pos1+1)) | ((byte)((number >> n) & (byte)1) << pos1+1);
}
*/
void putPixel(byte x, byte y, bool state, byte *grd) {
byte page = y/8;
byte sy = y%8;
byte index = (page*GRID_WIDTH)+x;
// REVERSED
//byte *grd = currentGrid ? grid2 : grid;
//if (currentGrid)
byte slice = grd[index];
// Small resolution
/*
slice = bit_set(slice, sy);
grid[index] = slice;
cursorTo(x, page);
send_data(slice);
*/
// Big pixels
slice = bit_set_to(slice, sy, state);
grd[index] = slice;
byte slice1 = 0x00;
byte slice2 = 0x00;
byte pos1 = 0;
byte pos2 = 0;
for(byte i=0; i<8; i++) {
if (i<4) {
//slice1 = (slice1 & ~((byte)1 << pos1)) | ((byte)((number >> n) & (byte)1) << pos1);
//slice1 = (slice1 & ~((byte)1 << pos1+1)) | ((byte)((number >> n) & (byte)1) << pos1+1);
slice1 = bit_set_to(slice1, pos1, bit_check(slice, i));
slice1 = bit_set_to(slice1, pos1+1, bit_check(slice, i));
pos1 += 2;
}
if (i>3) {
slice2 = bit_set_to(slice2, pos2, bit_check(slice, i));
slice2 = bit_set_to(slice2, pos2+1, bit_check(slice, i));
pos2 += 2;
}
}
// Draw the 2x2 pixel
cursorTo(x*2, page*2);
send_data(slice1);
send_data(slice1);
if (pos2 > 0) {
cursorTo(x*2, page*2+1);
send_data(slice2);
send_data(slice2);
}
}
/*
void drawAllSmall() {
byte *grd = currentGrid ? grid1 : grid2;
cursorTo(0, 0);
for(int i=0; i<PAGE_HEIGHT*GRID_WIDTH; i++) {
send_data(grd[i]);
}
}
*/
void drawAll2(byte *grd) {
byte slice;
byte newSlice1 = 0x00;
byte newSlice2 = 0x00;
byte pageEven;
for (byte p=0; p<PAGE_HEIGHT; p++) {
cursorTo(0, pageEven);
for (byte x=0; x<GRID_WIDTH; x++) {
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 1), 1);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 1), 2);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 2), 3);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 2), 4);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 3), 5);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 3), 6);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 4), 7);
newSlice1 = bit_set_to(newSlice1, bit_check(slice, 4), 8);
send_data(newSlice1);
send_data(newSlice1);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 5), 1);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 5), 2);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 6), 3);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 6), 4);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 7), 5);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 7), 6);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 8), 7);
newSlice2 = bit_set_to(newSlice2, bit_check(slice, 8), 8);
}
}
}
//void drawAll_trying_to_do_it_smart_but_failing(byte *grd) {
void drawAll(byte *grd) {
byte slice;
byte newSlice1;
byte newSlice2;
byte seg;
byte pageEven = 0;
byte pageOdd = 1;
//byte *grd = currentGrid ? grid : grid2;
cursorTo(0, 0);
// Two separate loops, because having to cursorTo() between each byte is bloody awkward.
// ToDo: Just find a nicer way to do this!
for (byte p=0; p<PAGE_HEIGHT; p++) {
cursorTo(0, pageEven);
for (byte i=0; i<GRID_WIDTH; i++) {
slice = grd[p*GRID_WIDTH+i];
seg = 0;
newSlice1 = 0B00000000;
newSlice2 = 0B00000000;
for (byte ind=0; ind<4; ind++) {
if (bit_check(slice, ind)) {
newSlice1 = bit_set(newSlice1, seg);
newSlice1 = bit_set(newSlice1, seg+1);
}
seg += 2;
}
send_data(newSlice1);
send_data(newSlice1);
}
pageEven += 2;
}
for (byte p=0; p<PAGE_HEIGHT; p++) {
cursorTo(0, pageOdd);
for (byte i=0; i<GRID_WIDTH; i++) {
slice = grd[p*GRID_WIDTH+i];
seg = 0;
newSlice2 = 0B00000000;
for (byte ind=0; ind<4; ind++) {
if (bit_check(slice, ind+4)) {
newSlice2 = bit_set(newSlice2, seg);
newSlice2 = bit_set(newSlice2, seg+1);
}
seg += 2;
}
send_data(newSlice2);
send_data(newSlice2);
}
pageOdd += 2;
}
}
void cursorTo(byte x, byte page) {
send_command(0x22);
send_command(page);
send_command(7);
send_command(0x21);
send_command(x);
send_command(127);
}
void config_display() {
for(int i=0; i<sizeof(initializeCmds); i++) {
send_command(pgm_read_byte(initializeCmds+i));
}
}
void send_command(unsigned char cmd) {
TinyWireM.beginTransmission(I2C_ADDRESS);
TinyWireM.write(0x00);
TinyWireM.write(cmd);
TinyWireM.endTransmission();
}
void send_data(byte slice) {
TinyWireM.beginTransmission(I2C_ADDRESS);
TinyWireM.write(0x40);
TinyWireM.write(slice);
TinyWireM.endTransmission();
}
void send_batch(byte slice, byte width) {
for(int i=0; i<width; i++) {
send_data(slice);
}
}
void displayNumberAt(byte x, byte y, unsigned int number) {
// count number of digits
int c = 0; // digit position
int n = number;
cursorTo(x, y);
while (n != 0) {
n /= 10;
c++;
}
if (number == 0) {
// pgm_read_byte
// pgm_read_byte( &(digits[number][i]) );
send_data( pgm_read_byte( &(digits[0][0])) );
send_data( pgm_read_byte( &(digits[0][1])) );
send_data( pgm_read_byte( &(digits[0][2])) );
send_data( pgm_read_byte( &(digits[0][3])) );
send_data( 0x00 );
return;
}
int numberArray[c];
c = 0;
n = number;
// extract each digit
while (n != 0) {
numberArray[c] = n % 10;
n /= 10;
c++;
}
//for (int i=0; i<c; i++) {
for (int i=c-1; i>=0; i--) {
byte digit = numberArray[i];
send_data( pgm_read_byte( &(digits[digit][0])) );
send_data( pgm_read_byte( &(digits[digit][1])) );
send_data( pgm_read_byte( &(digits[digit][2])) );
send_data( pgm_read_byte( &(digits[digit][3])) );
if (i > 0)
send_data( 0x00 );
}
}
void displayNumberAtVert(byte x, byte y, int number) {
// count number of digits
int c = 0; // digit position
int n = number;
while (n != 0) {
n /= 10;
c++;
}
/*
if (number == 0) {
send_data( digits[0][0] );
send_data( digits[0][1] );
send_data( digits[0][2] );
send_data( digits[0][3] );
send_data( 0x00 );
return;
}
*/
int numberArray[c];
c = 0;
n = number;
// extract each digit
while (n != 0) {
numberArray[c] = n % 10;
n /= 10;
c++;
}
cursorTo(x, y);
for (int i=c-1; i>=0; i--) {
//for (int i=0; i<c; i++) {
byte digit = numberArray[i];
send_data( digits[digit][0] );
send_data( digits[digit][1] );
send_data( digits[digit][2] );
send_data( digits[digit][3] );
send_data( 0x00 );
y++;
cursorTo(x, y);
}
}
/*
void beep (int frequencyInHertz, int timeInMilliseconds) {
int delayAmount PROGMEM = (long)(1000000 / frequencyInHertz);
int loopTime PROGMEM = (int)((timeInMilliseconds) / (delayAmount * 2));
for (int x = 0; x < loopTime; x++) {
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds(delayAmount);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds(delayAmount);
}
}
*/
void beep (int frequencyInHertz, long timeInMilliseconds)
{
int x;
long delayAmount = (long)(1000000 / frequencyInHertz);
long loopTime = (long)((timeInMilliseconds * 1000) / (delayAmount * 2));
for (x = 0; x < loopTime; x++)
{
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds(delayAmount);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds(delayAmount);
}
delay(20);
//a little delay to make all notes sound separate
}
void playEventSound(byte type) {
if (type == 0) {
// Intro
beep(262, 170);
delay(50);
beep(262, 170);
delay(30);
beep(294, 150);
delay(30);
beep(262, 200);
beep(294, 200);
beep(523, 600);
}
}