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