// touch #include #define N_TOUCH 6 #define THRESHOLD 500 // touchpads #define UP 5 #define DOWN 2 #define LEFT 3 #define RIGHT 4 #define A 1 #define B 0 // screen #include #include #include #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define SCREEN_ADDRESS 0x3C // 0x3D or 0x3C depending on brand // LED #define PIN_LED 15 // program states #define SET_TIME 0 #define COUNTDOWN 1 #define PAUSE 2 #define DONE 3 // initialize display Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1, 1700000UL, 1700000UL); // Q touch peripherals uint8_t touch_pins[N_TOUCH] = {2, 3, 4, 5, 6, 7}; Adafruit_FreeTouch* touch_devices[N_TOUCH]; // touch state int touch_values[N_TOUCH] = {0, 0, 0, 0, 0, 0}; bool pin_touched_now[N_TOUCH] = {false, false, false, false, false, false}; bool pin_touched_past[N_TOUCH] = {false, false, false, false, false, false}; void update_touch() { Ptc *ptc = ((Ptc *)PTC); for (int i = 0; i < N_TOUCH; i++) { // start touch_devices[i]->begin(); // read touch_values[i] = touch_devices[i]->measure(); // reset ptc->CTRLA.bit.ENABLE = 0; ptc->CTRLA.bit.SWRESET = 1; // update the state pin_touched_past[i] = pin_touched_now[i]; pin_touched_now[i] = touch_values[i] > THRESHOLD; } } void print_touch() { char print_buffer[30]; for (int i=0; i < N_TOUCH; i++) { sprintf(print_buffer, "%4d ", touch_values[i]); Serial.print(print_buffer); } Serial.println(""); } bool pressed(int button) { return pin_touched_past[button] && !pin_touched_now[button]; // want to register press only when lifted } void write_text(char* s, int size, int x, int y) { display.setTextSize(size); display.setCursor(x, y); display.print(s); } void invert_screen() { display.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_INVERSE); } // program state int prog_state; int set_time = 0; int start_time = 0; int show_time = 0; int increments[4] = {600, 60, 10, 1}; int selected_digit = 3; int start_millis = 0; void display_time() { int size = 3; int len = 5; int letterHeight = size * 8; int letterWidth = size * 5; int textWidth = size * (6 * len - 1); // at size 1, 1-pixel space between letters int x = (SCREEN_WIDTH - textWidth) / 2; int y = (SCREEN_HEIGHT - letterHeight) / 2 - 8; char displayString[5]; sprintf(displayString, "%02d:%02d", show_time / 60, show_time % 60); write_text(displayString, size, x, y); if(prog_state == SET_TIME) { int selectedChar = (selected_digit > 1 ? selected_digit + 1 : selected_digit); display.fillRect(x + (letterWidth + size) * selectedChar - 1, y - size, letterWidth + 2, letterHeight + size, SSD1306_INVERSE); } } void display_state() { int size = 1; char* state; switch(prog_state) { case SET_TIME: state = "SET TIME"; break; case COUNTDOWN: state = "COUNTDOWN"; break; case PAUSE: state = "PAUSED"; break; case DONE: state = "TIME'S UP!"; break; default: state = "ERROR"; } int len = strlen(state); int letterHeight = size * 8; int textWidth = size * (6 * len - 1); int x = (SCREEN_WIDTH - textWidth) / 2; int y = (SCREEN_HEIGHT - letterHeight * 2); write_text(state, size, x, y); } void setup() { // initialize Serial port Serial.begin(0); // initialize capacitive touch peripherals for (int i = 0; i < N_TOUCH; i++) { touch_devices[i] = new Adafruit_FreeTouch(touch_pins[i], OVERSAMPLE_1, RESISTOR_100K, FREQ_MODE_NONE); } // initialize LED pinMode(PIN_LED, OUTPUT); // initialize screen display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS); display.clearDisplay(); display.display(); display.setTextColor(SSD1306_WHITE); // start program prog_state = SET_TIME; } void loop() { // update the touch sensors update_touch(); // reset the display display.clearDisplay(); display_time(); display_state(); // casework if (prog_state == SET_TIME) { if (pressed(UP)) { set_time += increments[selected_digit]; } if (pressed(DOWN)) { set_time -= increments[selected_digit]; } set_time = (set_time + 3600) % 3600; if (pressed(LEFT)) { selected_digit--; } if (pressed(RIGHT)) { selected_digit++; } selected_digit %= 4; show_time = set_time; if (pressed(A)) { prog_state = COUNTDOWN; start_time = set_time; start_millis = millis(); } } else if (prog_state == COUNTDOWN) { int current_millis = millis(); int time_elapsed = (current_millis - start_millis) / 1000; show_time = start_time - time_elapsed; if (show_time <= 0) { show_time = 0; start_millis = millis(); prog_state = DONE; } if (pressed(B)) { prog_state = PAUSE; } } else if (prog_state == PAUSE) { if (pressed(A)) { start_time = show_time; start_millis = millis(); prog_state = COUNTDOWN; } if (pressed(B)) { prog_state = SET_TIME; } } else if (prog_state == DONE) { int current_millis = millis(); if (((current_millis - start_millis) / 1000) % 2 == 0) { invert_screen(); } if(pressed(A) || pressed(B) || pressed(UP) || pressed(DOWN) || pressed(LEFT) || pressed(RIGHT)) { prog_state = SET_TIME; } } // display display.display(); // print values to Serial, for debugging // print_touch(); delay(50); }