From 3d6957d757f24ac58c958f399632ca940b66be11 Mon Sep 17 00:00:00 2001 From: Julija <julia.ivaskeviciute@gmail.com> Date: Sat, 8 Mar 2025 10:39:40 +0200 Subject: [PATCH 1/6] Queue and Switch classes added --- CMakeLists.txt | 0 InputQueue.cpp | 5 +++++ InputQueue.h | 16 ++++++++++++++++ Switch.cpp | 5 +++++ Switch.h | 16 ++++++++++++++++ main.cpp | 3 +++ 6 files changed, 45 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 InputQueue.cpp create mode 100644 InputQueue.h create mode 100644 Switch.cpp create mode 100644 Switch.h create mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/InputQueue.cpp b/InputQueue.cpp new file mode 100644 index 0000000..d28fd4d --- /dev/null +++ b/InputQueue.cpp @@ -0,0 +1,5 @@ +// +// Created by Lenovo on 8.3.2025. +// + +#include "InputQueue.h" diff --git a/InputQueue.h b/InputQueue.h new file mode 100644 index 0000000..ba6d06c --- /dev/null +++ b/InputQueue.h @@ -0,0 +1,16 @@ +// +// Created by Lenovo on 8.3.2025. +// + +#ifndef INPUTQUEUE_H +#define INPUTQUEUE_H + + + +class InputQueue { + +}; + + + +#endif //INPUTQUEUE_H diff --git a/Switch.cpp b/Switch.cpp new file mode 100644 index 0000000..9a76731 --- /dev/null +++ b/Switch.cpp @@ -0,0 +1,5 @@ +// +// Created by Lenovo on 8.3.2025. +// + +#include "Switch.h" diff --git a/Switch.h b/Switch.h new file mode 100644 index 0000000..cecbabc --- /dev/null +++ b/Switch.h @@ -0,0 +1,16 @@ +// +// Created by Lenovo on 8.3.2025. +// + +#ifndef SWITCH_H +#define SWITCH_H + + + +class Switch { + +}; + + + +#endif //SWITCH_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..af2714a --- /dev/null +++ b/main.cpp @@ -0,0 +1,3 @@ +// +// Created by Lenovo on 8.3.2025. +// -- GitLab From da6f47629eb841e4f657cb77f94b15e57ba68bb3 Mon Sep 17 00:00:00 2001 From: julijai <julija.ivaskeviciute@metropolia.fi> Date: Sat, 8 Mar 2025 08:53:15 +0000 Subject: [PATCH 2/6] Update main.cpp --- main.cpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index af2714a..6a24aed 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,27 @@ -// -// Created by Lenovo on 8.3.2025. -// +#include <iostream> +#include <pico/stdio.h> + +#include "InputQueue.h" +#include "Switch.h" + +int main() { + stdio_init_all(); + + InputQueue inputQueue; + + Switch sw0 (9, InputQueue::SW0_PRESSED, &inputQueue, true, true); + Switch sw1 (8, InputQueue::SW1_PRESSED, &inputQueue, true, false); + Switch sw2 (7, InputQueue::SW2_PRESSED, &inputQueue, true, false); + Switch upLimit (27, InputQueue::LIMIT_UP_TRIGGERED, &inputQueue, true, false); + Switch downLimit (28, InputQueue::LIMIT_DOWN_TRIGGERED, &inputQueue, true, false); + + while (true) { + if (!inputQueue.isEmpty()) { + InputQueue::InputType event; + if (inputQueue.pop(event)) { + std::cout << event << std::endl; + } + } + //sleep_ms(10); + } +} \ No newline at end of file -- GitLab From 37f6883611700f7f0304ad13cc06f164cff3543c Mon Sep 17 00:00:00 2001 From: julijai <julija.ivaskeviciute@metropolia.fi> Date: Sat, 8 Mar 2025 08:57:42 +0000 Subject: [PATCH 3/6] Update 5 files - /CMakeLists.txt - /InputQueue.cpp - /InputQueue.h - /Switch.cpp - /Switch.h --- CMakeLists.txt | 45 ++++++++++++++++++++++++++++++++++++ InputQueue.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++---- InputQueue.h | 41 ++++++++++++++++++++++++++------- Switch.cpp | 49 +++++++++++++++++++++++++++++++++++---- Switch.h | 27 ++++++++++++++++++---- 5 files changed, 203 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e69de29..a2ddb90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -0,0 +1,45 @@ +# Set minimum required version of CMake +cmake_minimum_required(VERSION 3.12) + +# Include build functions from Pico SDK +include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) + +# Set board type because we are building for PicoW +set(PICO_BOARD pico_w) + +# Set name of project (as PROJECT_NAME) and C/C standards +project(GarageController C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +# Creates a pico-sdk subdirectory in our project for the libraries +pico_sdk_init() + +add_compile_options(-Wall + -Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int + -Wno-unused-function # we have some for the docs that aren't called + -Wno-maybe-uninitialized +) + +# Tell CMake where to find the executable source file +add_executable(${PROJECT_NAME} + InputQueue.cpp + InputQueue.h + Switch.cpp + Switch.h + main.cpp +) + +# Create map/bin/hex/uf2 files +pico_add_extra_outputs(${PROJECT_NAME}) + +# Link to pico_stdlib (gpio, time, etc. functions) +target_link_libraries(${PROJECT_NAME} + pico_stdlib + hardware_pwm + hardware_gpio +) + +# Disable usb output, enable uart output +pico_enable_stdio_usb(${PROJECT_NAME} 0) +pico_enable_stdio_uart(${PROJECT_NAME} 1) \ No newline at end of file diff --git a/InputQueue.cpp b/InputQueue.cpp index d28fd4d..a782c29 100644 --- a/InputQueue.cpp +++ b/InputQueue.cpp @@ -1,5 +1,59 @@ -// -// Created by Lenovo on 8.3.2025. -// - #include "InputQueue.h" + + +InputQueue::InputQueue(size_t size): queueSize(size) { + queue_init(&events, sizeof(InputType), size); +} + +InputQueue::~InputQueue() { + queue_free(&events); +} + +bool InputQueue::push(InputType type) { + return queue_try_add(&events, &type); +} + +//Getting events from the queue +bool InputQueue::pop(InputType &event) { + return queue_try_remove(&events, &event); +} + +bool InputQueue::isEmpty() { + return queue_is_empty(&events); +} + +// Emptying the queue +void InputQueue::clear() { + InputType event; + while (!isEmpty()) { + pop(event); + } +} + +std::ostream& operator<<(std::ostream& os, const InputQueue::InputType& type) { + switch (type) { + case InputQueue::SW0_PRESSED: + os << "SW0_PRESSED"; + break; + case InputQueue::SW1_PRESSED: + os << "SW1_PRESSED"; + break; + case InputQueue::SW2_PRESSED: + os << "SW2_PRESSED"; + break; + case InputQueue::LIMIT_UP_TRIGGERED: + os << "DOOR OPENED"; + break; + case InputQueue::LIMIT_DOWN_TRIGGERED: + os << "DOOR CLOSED"; + break; + case InputQueue::ENCODER_LEFT: + os << "DOOR CLOSING"; + break; + case InputQueue::ENCODER_RIGHT: + os << "DOOR OPENING"; + break; + } + return os; +} + diff --git a/InputQueue.h b/InputQueue.h index ba6d06c..4bac503 100644 --- a/InputQueue.h +++ b/InputQueue.h @@ -1,14 +1,39 @@ -// -// Created by Lenovo on 8.3.2025. -// - #ifndef INPUTQUEUE_H #define INPUTQUEUE_H - - -class InputQueue { - +#include "pico/util/queue.h" +#include "pico/time.h" +#include <iostream> + +class InputQueue { // Shared queue to store events triggered by irq handlers +public: + enum InputType { + ENCODER_LEFT, + ENCODER_RIGHT, + SW0_PRESSED, + SW1_PRESSED, + SW2_PRESSED, + LIMIT_UP_TRIGGERED, + LIMIT_DOWN_TRIGGERED + }; + + friend std::ostream& operator<<(std::ostream& os, const InputQueue::InputType& type); + + struct InputEvent { + InputType type; + }; + + InputQueue(size_t size = 100); + ~InputQueue(); + //void initialize(); + bool push(InputType event); + bool pop(InputType& event); + bool isEmpty( ); + void clear( ); + +private: + queue_t events{}; + size_t queueSize; }; diff --git a/Switch.cpp b/Switch.cpp index 9a76731..d5a980a 100644 --- a/Switch.cpp +++ b/Switch.cpp @@ -1,5 +1,46 @@ -// -// Created by Lenovo on 8.3.2025. -// - #include "Switch.h" + +uint64_t Switch::lastEventTime = 0; +std::map<uint, Switch*> Switch::switches; + +Switch::Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp, bool callback) : + pin(pin), eventType(eventType), inputQueue(queue), pullUp(pullUp), callback(callback) { + //Switch pin initialization + gpio_init(pin); + + if (pullUp) { + gpio_pull_up(pin); + } + gpio_set_dir(pin, GPIO_IN); + + switches[pin] = this; + + if (callback) { + gpio_set_irq_enabled_with_callback(pin, GPIO_IRQ_EDGE_FALL, true, &Switch::gpio_handler); + } else { + gpio_set_irq_enabled(pin, GPIO_IRQ_EDGE_FALL, true); + } + +} + +bool Switch::isPressed() const { + return pullUp ? !gpio_get(pin) : gpio_get(pin); +} + +void Switch::gpio_handler(uint gpio, uint32_t events) { + uint64_t current_time = time_us_64(); + uint64_t elapsed_time = current_time - lastEventTime; + + if (elapsed_time > DEBOUNCE_TIME) { + lastEventTime = current_time; + } + auto it = switches.find(gpio); + if (it != switches.end()) { + Switch* sw = it->second; + + if (sw->isPressed()) { + sw->inputQueue->push(sw->eventType); + } + } +} + diff --git a/Switch.h b/Switch.h index cecbabc..727322b 100644 --- a/Switch.h +++ b/Switch.h @@ -1,14 +1,31 @@ -// -// Created by Lenovo on 8.3.2025. -// - #ifndef SWITCH_H #define SWITCH_H +#include <cstdint> +#include "InputQueue.h" +#include <hardware/gpio.h> +#include "pico/time.h" +#include <iostream> +#include <map> class Switch { - +public: + Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp = true, bool callback = false); + bool isPressed() const; + + static void gpio_handler(uint gpio, uint32_t events); + +private: + uint8_t pin; + InputQueue::InputType eventType; + InputQueue* inputQueue; + bool pullUp; + bool callback; + + static constexpr uint64_t DEBOUNCE_TIME = 100000; + static uint64_t lastEventTime; + static std::map<uint, Switch*> switches; }; -- GitLab From bf126746d4df124ee0185befff9442371dbc2e6a Mon Sep 17 00:00:00 2001 From: Julija <julia.ivaskeviciute@gmail.com> Date: Sat, 8 Mar 2025 13:44:04 +0200 Subject: [PATCH 4/6] Added general GPIO class, switch inherits from GPIO. No LED class needed --- GPIO.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ GPIO.h | 25 +++++++++++++++++++++++++ Switch.cpp | 29 +++++++++++++++-------------- Switch.h | 7 +++++-- main.cpp | 17 ++++++++++++----- 5 files changed, 101 insertions(+), 21 deletions(-) create mode 100644 GPIO.cpp create mode 100644 GPIO.h diff --git a/GPIO.cpp b/GPIO.cpp new file mode 100644 index 0000000..765b8fa --- /dev/null +++ b/GPIO.cpp @@ -0,0 +1,44 @@ +#include "gpio.h" + +GPIO::GPIO(uint8_t pin, bool input, bool pullup, bool invert) + : pin_number(pin), is_input(input), is_pullup(pullup), is_inverted(invert) { + gpio_init(pin); + + if (input) { + gpio_set_dir(pin, GPIO_IN); + if (pullup) { + gpio_pull_up(pin); + } + if (invert) { + gpio_set_inover(pin, GPIO_OVERRIDE_INVERT); + } + } else { + gpio_set_dir(pin, GPIO_OUT); + if (invert) { + gpio_set_outover(pin, GPIO_OVERRIDE_INVERT); + } + } +} + +bool GPIO::read() const { + return gpio_get(pin_number); +} + +bool GPIO::operator()() const { + return read(); +} + +void GPIO::write(bool value) { + if (!is_input) { + gpio_put(pin_number, value); + } +} + +void GPIO::operator()(bool value) { + write(value); +} + +GPIO::operator int() const { + return pin_number; +} + diff --git a/GPIO.h b/GPIO.h new file mode 100644 index 0000000..c6969a4 --- /dev/null +++ b/GPIO.h @@ -0,0 +1,25 @@ +#ifndef GPIO_H +#define GPIO_H + +#include "pico/stdlib.h" + +class GPIO { +public: + GPIO(uint8_t pin, bool input = true, bool pullup = true, bool invert = false); + GPIO(const GPIO &) = delete; + + bool read() const; + bool operator() () const; + void write(bool value); + void operator() (bool); + operator int() const; +private: + int pin_number; + bool is_input; + bool is_pullup; + bool is_inverted; +}; + + + +#endif //GPIO_H diff --git a/Switch.cpp b/Switch.cpp index d5a980a..cc48322 100644 --- a/Switch.cpp +++ b/Switch.cpp @@ -3,28 +3,30 @@ uint64_t Switch::lastEventTime = 0; std::map<uint, Switch*> Switch::switches; -Switch::Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp, bool callback) : - pin(pin), eventType(eventType), inputQueue(queue), pullUp(pullUp), callback(callback) { +Switch::Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp, bool callback, bool invert) : + GPIO(pin, true, pullUp, invert), + eventType(eventType), inputQueue(queue), callback(callback) { //Switch pin initialization - gpio_init(pin); + switches[pin] = this; - if (pullUp) { - gpio_pull_up(pin); - } - gpio_set_dir(pin, GPIO_IN); + uint32_t irq_type; - switches[pin] = this; + if ((pullUp && invert) || (!pullUp && !invert)) { + irq_type = GPIO_IRQ_EDGE_RISE; + } else { + irq_type = GPIO_IRQ_EDGE_FALL; + } if (callback) { - gpio_set_irq_enabled_with_callback(pin, GPIO_IRQ_EDGE_FALL, true, &Switch::gpio_handler); + gpio_set_irq_enabled_with_callback(pin, irq_type, true, &Switch::gpio_handler); } else { - gpio_set_irq_enabled(pin, GPIO_IRQ_EDGE_FALL, true); + gpio_set_irq_enabled(pin, irq_type, true); } } bool Switch::isPressed() const { - return pullUp ? !gpio_get(pin) : gpio_get(pin); + return read(); } void Switch::gpio_handler(uint gpio, uint32_t events) { @@ -38,9 +40,8 @@ void Switch::gpio_handler(uint gpio, uint32_t events) { if (it != switches.end()) { Switch* sw = it->second; - if (sw->isPressed()) { - sw->inputQueue->push(sw->eventType); - } + + sw->inputQueue->push(sw->eventType); } } diff --git a/Switch.h b/Switch.h index 727322b..931c215 100644 --- a/Switch.h +++ b/Switch.h @@ -8,10 +8,13 @@ #include <iostream> #include <map> +#include "gpio.h" -class Switch { + +class Switch: public GPIO { public: - Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp = true, bool callback = false); + Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp = true, + bool callback = false, bool invert=false); bool isPressed() const; static void gpio_handler(uint gpio, uint32_t events); diff --git a/main.cpp b/main.cpp index 6a24aed..80c772a 100644 --- a/main.cpp +++ b/main.cpp @@ -9,17 +9,24 @@ int main() { InputQueue inputQueue; - Switch sw0 (9, InputQueue::SW0_PRESSED, &inputQueue, true, true); - Switch sw1 (8, InputQueue::SW1_PRESSED, &inputQueue, true, false); - Switch sw2 (7, InputQueue::SW2_PRESSED, &inputQueue, true, false); - Switch upLimit (27, InputQueue::LIMIT_UP_TRIGGERED, &inputQueue, true, false); - Switch downLimit (28, InputQueue::LIMIT_DOWN_TRIGGERED, &inputQueue, true, false); + Switch sw0 (9, InputQueue::SW0_PRESSED, &inputQueue, true, true, true); + Switch sw1 (8, InputQueue::SW1_PRESSED, &inputQueue, true, false, true); + Switch sw2 (7, InputQueue::SW2_PRESSED, &inputQueue, true, false, true); + Switch upLimit (27, InputQueue::LIMIT_UP_TRIGGERED, &inputQueue, true, false, true); + Switch downLimit (28, InputQueue::LIMIT_DOWN_TRIGGERED, &inputQueue, true, false, true); + + GPIO led1 (22, false, false, false); while (true) { if (!inputQueue.isEmpty()) { InputQueue::InputType event; if (inputQueue.pop(event)) { std::cout << event << std::endl; + if (event == InputQueue::SW0_PRESSED) { + led1.write(true); + } else if (event == InputQueue::SW1_PRESSED) { + led1.write(false); + } } } //sleep_ms(10); -- GitLab From d492c3bf975d2290a7e60206f9090922a0126804 Mon Sep 17 00:00:00 2001 From: Julija <julia.ivaskeviciute@gmail.com> Date: Sun, 9 Mar 2025 12:23:53 +0200 Subject: [PATCH 5/6] B Encoder class added. Interrupts need fixing --- CMakeLists.txt | 6 +++++- Encoder.cpp | 26 ++++++++++++++++++++++++++ Encoder.h | 25 +++++++++++++++++++++++++ main.cpp | 3 +++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 Encoder.cpp create mode 100644 Encoder.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a2ddb90..8faf614 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) set(PICO_BOARD pico_w) # Set name of project (as PROJECT_NAME) and C/C standards -project(GarageController C CXX ASM) +project(TestGarage C CXX ASM) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) @@ -23,10 +23,14 @@ add_compile_options(-Wall # Tell CMake where to find the executable source file add_executable(${PROJECT_NAME} + GPIO.cpp + GPIO.h InputQueue.cpp InputQueue.h Switch.cpp Switch.h + Encoder.cpp + Encoder.h main.cpp ) diff --git a/Encoder.cpp b/Encoder.cpp new file mode 100644 index 0000000..70ff43a --- /dev/null +++ b/Encoder.cpp @@ -0,0 +1,26 @@ +#include "Encoder.h" + +Encoder* Encoder::instance = nullptr; + +Encoder::Encoder(uint8_t pinANum, uint8_t pinBNum, InputQueue::InputType rotLeft, InputQueue::InputType rotRight, InputQueue *queue) : + pinA(pinANum, true, false, false), + pinB(pinBNum, true, false, false), + rotLeft(rotLeft), rotRight(rotRight), queue(queue) { + + instance = this; + gpio_set_irq_enabled_with_callback(pinANum, GPIO_IRQ_EDGE_RISE, true, &Encoder::gpio_handler); + //gpio_set_irq_enabled(pinBNum, GPIO_IRQ_EDGE_RISE, true); +} + +void Encoder::gpio_handler(uint gpio, uint32_t events) { + if (instance->pinB.read()) { + instance->queue->push(instance->rotRight); + } else { + instance->queue->push(instance->rotLeft); + } +} + +Encoder::~Encoder() { + gpio_set_irq_enabled(int(pinA), GPIO_IRQ_EDGE_RISE, false); + instance = nullptr; +} diff --git a/Encoder.h b/Encoder.h new file mode 100644 index 0000000..029562f --- /dev/null +++ b/Encoder.h @@ -0,0 +1,25 @@ +#ifndef ENCODER_H +#define ENCODER_H + +#include <iostream> + +#include "gpio.h" +#include "InputQueue.h" + +class Encoder { + public: + Encoder(uint8_t pinANum, uint8_t pinBNum, InputQueue::InputType rotLeft, InputQueue::InputType rotRight, InputQueue * queue); + ~Encoder(); + private: + static Encoder * instance; + GPIO pinA; + GPIO pinB; + InputQueue::InputType rotLeft; + InputQueue::InputType rotRight; + InputQueue * queue; + static void gpio_handler(uint pin, uint32_t events); +}; + + + +#endif //ENCODER_H diff --git a/main.cpp b/main.cpp index 80c772a..68c83ab 100644 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include "InputQueue.h" #include "Switch.h" +#include "Encoder.h" int main() { stdio_init_all(); @@ -17,6 +18,8 @@ int main() { GPIO led1 (22, false, false, false); + Encoder rotEncoder(10, 11, InputQueue::ENCODER_LEFT, InputQueue::ENCODER_RIGHT, &inputQueue); + while (true) { if (!inputQueue.isEmpty()) { InputQueue::InputType event; -- GitLab From 2de1f470b003f3b8e717c31660e21dfb3e1aec8e Mon Sep 17 00:00:00 2001 From: Julija <julia.ivaskeviciute@gmail.com> Date: Sun, 9 Mar 2025 21:54:20 +0200 Subject: [PATCH 6/6] Interrupt class created to have one global interrupt handler for switches and encoder. --- CMakeLists.txt | 18 ++++--- Encoder.cpp | 26 ---------- GPIO.cpp => IOcontrols/GPIO.cpp | 0 GPIO.h => IOcontrols/GPIO.h | 0 InputQueue.cpp => IOcontrols/InputQueue.cpp | 0 InputQueue.h => IOcontrols/InputQueue.h | 0 IOcontrols/Interrupt.cpp | 56 +++++++++++++++++++++ IOcontrols/Interrupt.h | 38 ++++++++++++++ Inputs/Encoder.cpp | 19 +++++++ Encoder.h => Inputs/Encoder.h | 13 +++-- Inputs/Switch.cpp | 29 +++++++++++ Switch.h => Inputs/Switch.h | 22 ++++---- Switch.cpp | 47 ----------------- main.cpp | 16 +++--- 14 files changed, 183 insertions(+), 101 deletions(-) delete mode 100644 Encoder.cpp rename GPIO.cpp => IOcontrols/GPIO.cpp (100%) rename GPIO.h => IOcontrols/GPIO.h (100%) rename InputQueue.cpp => IOcontrols/InputQueue.cpp (100%) rename InputQueue.h => IOcontrols/InputQueue.h (100%) create mode 100644 IOcontrols/Interrupt.cpp create mode 100644 IOcontrols/Interrupt.h create mode 100644 Inputs/Encoder.cpp rename Encoder.h => Inputs/Encoder.h (56%) create mode 100644 Inputs/Switch.cpp rename Switch.h => Inputs/Switch.h (53%) delete mode 100644 Switch.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8faf614..d96a075 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,14 +23,16 @@ add_compile_options(-Wall # Tell CMake where to find the executable source file add_executable(${PROJECT_NAME} - GPIO.cpp - GPIO.h - InputQueue.cpp - InputQueue.h - Switch.cpp - Switch.h - Encoder.cpp - Encoder.h + IOcontrols/GPIO.cpp + IOcontrols/GPIO.h + IOcontrols/InputQueue.cpp + IOcontrols/InputQueue.h + IOcontrols/Interrupt.cpp + IOcontrols/Interrupt.h + Inputs/Switch.cpp + Inputs/Switch.h + Inputs/Encoder.cpp + Inputs/Encoder.h main.cpp ) diff --git a/Encoder.cpp b/Encoder.cpp deleted file mode 100644 index 70ff43a..0000000 --- a/Encoder.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "Encoder.h" - -Encoder* Encoder::instance = nullptr; - -Encoder::Encoder(uint8_t pinANum, uint8_t pinBNum, InputQueue::InputType rotLeft, InputQueue::InputType rotRight, InputQueue *queue) : - pinA(pinANum, true, false, false), - pinB(pinBNum, true, false, false), - rotLeft(rotLeft), rotRight(rotRight), queue(queue) { - - instance = this; - gpio_set_irq_enabled_with_callback(pinANum, GPIO_IRQ_EDGE_RISE, true, &Encoder::gpio_handler); - //gpio_set_irq_enabled(pinBNum, GPIO_IRQ_EDGE_RISE, true); -} - -void Encoder::gpio_handler(uint gpio, uint32_t events) { - if (instance->pinB.read()) { - instance->queue->push(instance->rotRight); - } else { - instance->queue->push(instance->rotLeft); - } -} - -Encoder::~Encoder() { - gpio_set_irq_enabled(int(pinA), GPIO_IRQ_EDGE_RISE, false); - instance = nullptr; -} diff --git a/GPIO.cpp b/IOcontrols/GPIO.cpp similarity index 100% rename from GPIO.cpp rename to IOcontrols/GPIO.cpp diff --git a/GPIO.h b/IOcontrols/GPIO.h similarity index 100% rename from GPIO.h rename to IOcontrols/GPIO.h diff --git a/InputQueue.cpp b/IOcontrols/InputQueue.cpp similarity index 100% rename from InputQueue.cpp rename to IOcontrols/InputQueue.cpp diff --git a/InputQueue.h b/IOcontrols/InputQueue.h similarity index 100% rename from InputQueue.h rename to IOcontrols/InputQueue.h diff --git a/IOcontrols/Interrupt.cpp b/IOcontrols/Interrupt.cpp new file mode 100644 index 0000000..7909c4f --- /dev/null +++ b/IOcontrols/Interrupt.cpp @@ -0,0 +1,56 @@ +#include "Interrupt.h" + +#include "../Inputs/Encoder.h" +#include "../Inputs/Switch.h" + +static std::map<uint, Interrupt*> interrupts; +bool Interrupt::initialized = false; + +void Interrupt::initializeInterrupts() { + if (!initialized) { + gpio_set_irq_enabled_with_callback(0, GPIO_IRQ_EDGE_RISE, true, &Interrupt::globalHandler); + initialized = true; + } +} + +Interrupt::Interrupt(uint pin, InputQueue* queue, std::string input_type) : + pin(pin), queue(queue), input_type(input_type) { + + interrupts[pin] = this; + + if (!initialized) { + initializeInterrupts(); + } +} + +Interrupt::~Interrupt() { + interrupts.erase(pin); +} + +bool Interrupt::handleInterrupt(uint gpio, uint32_t events) { + if (input_type == "Switch" && button != nullptr) { + static uint64_t lastTime = 0; + uint64_t currentTime = time_us_64(); + + if (currentTime - lastTime > 50000) { + lastTime = currentTime; + queue->push(button->getEventType()); + } + return true; + } else if (input_type == "Encoder" && encoder != nullptr) { + if (encoder->getPinB().read()) { + queue->push(encoder->getRotLeft()); + } else { + queue->push(encoder->getRotRight()); + } + return true; + } + return false; +} + +void Interrupt::globalHandler(uint gpio, uint32_t events) { + auto it = interrupts.find(gpio); + if (it != interrupts.end() && it->second != nullptr) { + it->second->handleInterrupt(gpio, events); + } +} diff --git a/IOcontrols/Interrupt.h b/IOcontrols/Interrupt.h new file mode 100644 index 0000000..3e9f582 --- /dev/null +++ b/IOcontrols/Interrupt.h @@ -0,0 +1,38 @@ +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include "../IOcontrols/InputQueue.h" +#include <map> + +class GPIO; +class Switch; +class Encoder; + +class Interrupt { + public: + Interrupt(uint pin, InputQueue* queue, std::string input_type); + ~Interrupt(); + + std::string getType() const {return input_type; } + uint getPin() const {return pin;} + InputQueue* getQueue() const {return queue;} + + void setSwitch(Switch* sw) {button = sw; } + void setEncoder(Encoder* enc) {encoder = enc; } + + bool handleInterrupt(uint gpio, uint32_t events); + static void globalHandler(uint gpio, uint32_t events); + static void initializeInterrupts(); + + private: + uint pin; + InputQueue* queue; + std::string input_type; + + Switch* button = nullptr; + Encoder* encoder = nullptr; + + static bool initialized; +}; + +#endif //INTERRUPT_H diff --git a/Inputs/Encoder.cpp b/Inputs/Encoder.cpp new file mode 100644 index 0000000..37751dc --- /dev/null +++ b/Inputs/Encoder.cpp @@ -0,0 +1,19 @@ +#include "Encoder.h" + +//Encoder* Encoder::instance = nullptr; + +Encoder::Encoder(uint8_t pinANum, uint8_t pinBNum, InputQueue::InputType rotLeft, InputQueue::InputType rotRight, InputQueue *queue) : + pinA(pinANum, true, false, false), + pinB(pinBNum, true, false, false), + rotLeft(rotLeft), rotRight(rotRight), queue(queue) { + + interrupt = std::make_unique<Interrupt>(pinANum, queue, "Encoder"); + interrupt->setEncoder(this); + + gpio_set_irq_enabled(pinANum, GPIO_IRQ_EDGE_RISE, true); +} + +Encoder::~Encoder() { + gpio_set_irq_enabled(int(pinA), GPIO_IRQ_EDGE_RISE, false); + +} diff --git a/Encoder.h b/Inputs/Encoder.h similarity index 56% rename from Encoder.h rename to Inputs/Encoder.h index 029562f..5410034 100644 --- a/Encoder.h +++ b/Inputs/Encoder.h @@ -2,14 +2,21 @@ #define ENCODER_H #include <iostream> +#include <memory> -#include "gpio.h" -#include "InputQueue.h" +#include "../IOcontrols/GPIO.h" +#include "../IOcontrols/InputQueue.h" +#include "../IOcontrols/Interrupt.h" class Encoder { public: Encoder(uint8_t pinANum, uint8_t pinBNum, InputQueue::InputType rotLeft, InputQueue::InputType rotRight, InputQueue * queue); ~Encoder(); + + GPIO& getPinB() { return pinB; } + InputQueue::InputType getRotLeft() const { return rotLeft; } + InputQueue::InputType getRotRight() const { return rotRight; } + private: static Encoder * instance; GPIO pinA; @@ -17,7 +24,7 @@ class Encoder { InputQueue::InputType rotLeft; InputQueue::InputType rotRight; InputQueue * queue; - static void gpio_handler(uint pin, uint32_t events); + std::unique_ptr<Interrupt> interrupt; }; diff --git a/Inputs/Switch.cpp b/Inputs/Switch.cpp new file mode 100644 index 0000000..9ddd300 --- /dev/null +++ b/Inputs/Switch.cpp @@ -0,0 +1,29 @@ +#include "Switch.h" + +Switch::Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, + bool pullUp, bool enableInterrupt, bool invert) : + GPIO(pin, true, pullUp, invert), + eventType(eventType), inputQueue(queue) { + if (enableInterrupt) { + uint32_t irq_type; + if ((pullUp && invert) || (!pullUp && !invert)) { + irq_type = GPIO_IRQ_EDGE_RISE; + } else { + irq_type = GPIO_IRQ_EDGE_FALL; + } + interrupt = std::make_unique<Interrupt>(pin, queue, "Switch"); + interrupt->setSwitch(this); + + gpio_set_irq_enabled(pin, irq_type, true); + } +} + +Switch::~Switch() { + if (interrupt) { + gpio_set_irq_enabled(int(pin), GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); + } +} + +bool Switch::isPressed() const { + return read(); +} diff --git a/Switch.h b/Inputs/Switch.h similarity index 53% rename from Switch.h rename to Inputs/Switch.h index 931c215..aaeccbb 100644 --- a/Switch.h +++ b/Inputs/Switch.h @@ -2,33 +2,35 @@ #define SWITCH_H #include <cstdint> -#include "InputQueue.h" +#include "../IOcontrols/InputQueue.h" #include <hardware/gpio.h> #include "pico/time.h" #include <iostream> #include <map> +#include <memory> -#include "gpio.h" +#include "../IOcontrols/GPIO.h" +#include "../IOcontrols/Interrupt.h" class Switch: public GPIO { public: Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp = true, - bool callback = false, bool invert=false); + bool enableInterrupt = false, bool invert=false); + ~Switch(); + bool isPressed() const; - static void gpio_handler(uint gpio, uint32_t events); + InputQueue::InputType getEventType() const { return eventType; } private: uint8_t pin; InputQueue::InputType eventType; InputQueue* inputQueue; - bool pullUp; - bool callback; - - static constexpr uint64_t DEBOUNCE_TIME = 100000; - static uint64_t lastEventTime; - static std::map<uint, Switch*> switches; + /*bool pullUp; + bool callback;*/ + bool useInterrupt; + std::unique_ptr<Interrupt> interrupt; }; diff --git a/Switch.cpp b/Switch.cpp deleted file mode 100644 index cc48322..0000000 --- a/Switch.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "Switch.h" - -uint64_t Switch::lastEventTime = 0; -std::map<uint, Switch*> Switch::switches; - -Switch::Switch(uint8_t pin, InputQueue::InputType eventType, InputQueue* queue, bool pullUp, bool callback, bool invert) : - GPIO(pin, true, pullUp, invert), - eventType(eventType), inputQueue(queue), callback(callback) { - //Switch pin initialization - switches[pin] = this; - - uint32_t irq_type; - - if ((pullUp && invert) || (!pullUp && !invert)) { - irq_type = GPIO_IRQ_EDGE_RISE; - } else { - irq_type = GPIO_IRQ_EDGE_FALL; - } - - if (callback) { - gpio_set_irq_enabled_with_callback(pin, irq_type, true, &Switch::gpio_handler); - } else { - gpio_set_irq_enabled(pin, irq_type, true); - } - -} - -bool Switch::isPressed() const { - return read(); -} - -void Switch::gpio_handler(uint gpio, uint32_t events) { - uint64_t current_time = time_us_64(); - uint64_t elapsed_time = current_time - lastEventTime; - - if (elapsed_time > DEBOUNCE_TIME) { - lastEventTime = current_time; - } - auto it = switches.find(gpio); - if (it != switches.end()) { - Switch* sw = it->second; - - - sw->inputQueue->push(sw->eventType); - } -} - diff --git a/main.cpp b/main.cpp index 68c83ab..8a9bf38 100644 --- a/main.cpp +++ b/main.cpp @@ -1,20 +1,22 @@ #include <iostream> #include <pico/stdio.h> -#include "InputQueue.h" -#include "Switch.h" -#include "Encoder.h" +#include "IOcontrols/InputQueue.h" +#include "Inputs/Switch.h" +#include "Inputs/Encoder.h" int main() { stdio_init_all(); + Interrupt::initializeInterrupts(); + InputQueue inputQueue; Switch sw0 (9, InputQueue::SW0_PRESSED, &inputQueue, true, true, true); - Switch sw1 (8, InputQueue::SW1_PRESSED, &inputQueue, true, false, true); - Switch sw2 (7, InputQueue::SW2_PRESSED, &inputQueue, true, false, true); - Switch upLimit (27, InputQueue::LIMIT_UP_TRIGGERED, &inputQueue, true, false, true); - Switch downLimit (28, InputQueue::LIMIT_DOWN_TRIGGERED, &inputQueue, true, false, true); + Switch sw1 (8, InputQueue::SW1_PRESSED, &inputQueue, true, true, true); + Switch sw2 (7, InputQueue::SW2_PRESSED, &inputQueue, true, true, true); + Switch upLimit (27, InputQueue::LIMIT_UP_TRIGGERED, &inputQueue, true, true, true); + Switch downLimit (28, InputQueue::LIMIT_DOWN_TRIGGERED, &inputQueue, true, true, true); GPIO led1 (22, false, false, false); -- GitLab