// SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012-2024 Scott Penrose and WII5 Buoy contributors // // This file is part of WII5 Buoy firmware. // See LICENSE for full terms. /** * @file WII5Sh3dIO.cpp * @brief I/O abstraction: buttons, LEDs, and the IO loop tick. */ /* TODO 2024 - Check this is only valid IO for Buttons and LEDs */ #include //assumes Arduino IDE v1.0 or greater #include "WII5Sh3dIO.h" #include "WII5Sh3dConsole.h" #include // Include the PushButton library #include /* ---------------------------------------------------------------------- */ // TODO Can we use NUM_PINS #define LED_MAX 100 #define BUTTON_MAX 100 void WII5Sh3dIO::begin(uint8_t led1, uint8_t led2, uint8_t btn1, uint8_t btn2) { begin(led1, led2, 0, 0, btn1, btn2, 0, 0); } // Quick method to save buttons before begin void WII5Sh3dIO::preButton(PushButton* btn1, PushButton* btn2, PushButton* btn3, PushButton* btn4) { button1 = btn1; button2 = btn2; button3 = btn3; button4 = btn4; } void WII5Sh3dIO::begin(uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t btn1, uint8_t btn2, uint8_t btn3, uint8_t btn4) { console.log(LOG_DEBUG, F("LEDS: %d,%d,%d,%d BUTTONS: %d,%d,%d,%d"), int(led1), int(led2), int(led3), int(led4), int(btn1), int(btn2), int(btn3), int(btn4)); if (_begin) return; _begin = true; if (led1 > 0 && led1 < LED_MAX) { led1_pin = led1; pinMode(led1_pin, OUTPUT); } if (led2 > 0 && led2 < LED_MAX) { led2_pin = led2; pinMode(led2_pin, OUTPUT); } if (led3 > 0 && led3 < LED_MAX) { led3_pin = led2; pinMode(led3_pin, OUTPUT); } if (led4 > 0 && led4 < LED_MAX) { led4_pin = led2; pinMode(led4_pin, OUTPUT); } if (btn1 > 0 && btn1 < BUTTON_MAX) { pinMode(btn1, INPUT_PULLUP); if (!button1) button1 = new PushButton(btn1); button1_pin = btn1; // TODO button1_activelow = true; button1->setActiveLogic(LOW); } if (btn2 > 0 && btn2 < BUTTON_MAX) { pinMode(btn2, INPUT_PULLUP); if (!button2) button2 = new PushButton(btn2); button2->setActiveLogic(LOW); button2_pin = btn2; button2_activelow = true; } if (btn3 > 0 && btn3 < BUTTON_MAX) { pinMode(btn3, INPUT_PULLUP); if (!button3) button3 = new PushButton(btn3); button3_pin = btn3; button3_activelow = true; button3->setActiveLogic(LOW); } if (btn4 > 0 && btn4 < BUTTON_MAX) { pinMode(btn4, INPUT_PULLUP); if (!button4) button4 = new PushButton(btn4); button4_pin = btn4; button4_activelow = true; button4->setActiveLogic(LOW); } return; } void WII5Sh3dIO::loop() { if (lastLedLoop > 100) { if (led1_pin > 0) { // Max time and not default mode if ((led1_max > 0) && (led1_mode != led1_default) && (led1_timeon > led1_max)) led1Set(led1_default); if (!updateLED(led1_pin, led1_mode, led1_state)) { led1Set(led1_default); } led1_state++; } if (led2_pin > 0) { if ((led2_max > 0) && (led2_mode != led2_default) && (led2_timeon > led2_max)) led2Set(led2_default); if (!updateLED(led2_pin, led2_mode, led2_state)) { led2Set(led2_default); } led2_state++; } if (led3_pin > 0) { if ((led3_max > 0) && (led3_mode != led3_default) && (led3_timeon > led3_max)) led3Set(led3_default); if (!updateLED(led3_pin, led3_mode, led3_state)) { led3Set(led3_default); } led3_state++; } if (led4_pin > 0) { if ((led4_max > 0) && (led4_mode != led4_default) && (led4_timeon > led4_max)) led4Set(led4_default); if (!updateLED(led4_pin, led4_mode, led4_state)) { led4Set(led4_default); } led4_state++; } lastLedLoop = 0; } if (button1) button1->update(); if (button2) button2->update(); if (button3) button3->update(); if (button4) button4->update(); } // Return 0 - nothing, or button number, 1,2,3 // TODO - Improve the performance of this to be tiny, so it does not have to be run every singel 8 seconds uint8_t WII5Sh3dIO::buttonSleepCheck() { if (button1) { // pinMode(button1_pin, button1_activelow ? INPUT_PULLUP : INPUT); if (digitalRead(button1_pin) == (button1_activelow ? LOW : HIGH)) { return 1; } } if (button2) { // pinMode(button2_pin, button2_activelow ? INPUT_PULLUP : INPUT); if (digitalRead(button2_pin) == (button2_activelow ? LOW : HIGH)) { return 2; } } return 0; } // TODO - Consider adding automatic getting Temperature at timed internval (except for blocking issue) // TODO - Consider adding ability to read ALL sensors, not just one void WII5Sh3dIO::sleep() { // TODO - Toun off 18B20 // TODO - Turn off GPS // TODO - Turn off LED (which may mean make them float/pull high) // TODO - Make sure the LEDs are actually off // digitalWrite(LED1, HIGH); // digitalWrite(LED2, HIGH); } void WII5Sh3dIO::wake() { } #define inverted false // Called once per 100ms bool WII5Sh3dIO::updateLED(uint8_t pin, uint8_t mode, uint8_t state) { // console.log(LOG_INFO, F("Updating LED %d, %d, %d"), pin, mode, state); switch (mode) { case LED_OFF: // Off digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_ON: // On digitalWrite(pin, inverted ? LOW : HIGH); break; case LED_SLOW: // Slow if ((state % 4) == 0) digitalWrite(pin, !digitalRead(pin)); break; case LED_FAST: // Fast if ((state % 2) == 0) digitalWrite(pin, !digitalRead(pin)); break; case LED_SHORT: // Short - on for a short period if ((state % 6) == 0) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_DOUBLE: // Double - 2 short, long off if ( ((state % 8) == 0) || ((state % 8) == 2) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_TRIPPLE: // Trpple - 3 short, long off if ( ((state % 12) == 0) || ((state % 12) == 2) || ((state % 12) == 4) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_SHORT_LONG: // Long - very slow long on and off if ((state % 12) == 0) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_DOUBLE_LONG: if ( ((state % 16) == 0) || ((state % 16) == 2) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_TRIPPLE_LONG: if ( ((state % 20) == 0) || ((state % 20) == 2) || ((state % 20) == 4) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_SHORT_GAP: // Long - very slow long on and off if ((state % 12) == 0) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_DOUBLE_GAP: if ( ((state % 48) == 0) || ((state % 48) == 2) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_TRIPPLE_GAP: if ( ((state % 50) == 0) || ((state % 50) == 2) || ((state % 50) == 4) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_ONE: if ((state % 12) == 0) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_TWO: if ( ((state % 16) == 0) || ((state % 16) == 2) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_THREE: if ( ((state % 20) == 0) || ((state % 20) == 2) || ((state % 20) == 4) ) digitalWrite(pin, inverted ? LOW : HIGH); else digitalWrite(pin, inverted ? HIGH : LOW); break; case LED_FOUR: // TODO Simplify break; case LED_FIVE: break; case LED_SIX: break; case LED_SEVEN: break; case LED_EIGHT: break; case LED_NINE: break; case LED_TEN: break; case LED_ONCE: if (state < 10) digitalWrite(pin, inverted ? LOW : HIGH); else if (state < 20) digitalWrite(pin, inverted ? HIGH : LOW); else { return false; } break; // TODO seemed to be just one long beep case LED_TWICE: if (state < 10) digitalWrite(pin, inverted ? LOW : HIGH); else if (state < 20) digitalWrite(pin, inverted ? HIGH : LOW); else if (state < 30) digitalWrite(pin, inverted ? LOW : HIGH); else if (state < 40) digitalWrite(pin, inverted ? HIGH : LOW); else { return false; } break; } return true; } WII5Sh3dIO sh3dNodeIO;