commit 82cd535a428d6d9a254c1afdc9810bdfc8c93872 Author: Thorsteinngretar Date: Fri Sep 4 18:16:15 2026 +0000 Adding Project 1 rotary encoder implementations diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b95b18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +**/.pio/ +**/.vscode/ +.DS_Store +Thumbs.db diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/include/digital_in.h b/Project_1_Rotary_Encoder/Part_1_Polling/include/digital_in.h new file mode 100644 index 0000000..a3505c6 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/include/digital_in.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_IN_H +#define DIGITAL_IN_H + +#include + +class Digital_in +{ +public: + Digital_in(int pin); + + void init(); + + bool is_hi(); + bool is_lo(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/include/digital_out.h b/Project_1_Rotary_Encoder/Part_1_Polling/include/digital_out.h new file mode 100644 index 0000000..dd2b776 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/include/digital_out.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_OUT_H +#define DIGITAL_OUT_H + +#include + +class Digital_out +{ +public: + Digital_out(int pin); + + void init(); + void set_hi(); + void set_lo(); + void toggle(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/include/encoder.h b/Project_1_Rotary_Encoder/Part_1_Polling/include/encoder.h new file mode 100644 index 0000000..7332520 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/include/encoder.h @@ -0,0 +1,25 @@ +#ifndef ENCODER_H +#define ENCODER_H + +#include +#include + +class Encoder +{ +public: + Encoder(int c1Pin, int c2Pin, int ledPin); + + void init(); + void update(); + int position(); + +private: + Digital_in c1; + Digital_in c2; + Digital_out led; + + bool previousC1; + int count; +}; + +#endif diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/platformio.ini b/Project_1_Rotary_Encoder/Part_1_Polling/platformio.ini new file mode 100644 index 0000000..8f0bdf1 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/platformio.ini @@ -0,0 +1,4 @@ +[env:nanoatmega328new] +platform = atmelavr +board = nanoatmega328new +framework = arduino diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/src/digital_in.cpp b/Project_1_Rotary_Encoder/Part_1_Polling/src/digital_in.cpp new file mode 100644 index 0000000..2bbe6ef --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/src/digital_in.cpp @@ -0,0 +1,26 @@ +#include +#include + +Digital_in::Digital_in(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_in::init() +{ + // Configure pin as input + DDRB &= static_cast(~pinMask); + + // Enable internal pull-up resistor + PORTB |= pinMask; +} + +bool Digital_in::is_hi() +{ + return (PINB & pinMask) != 0; +} + +bool Digital_in::is_lo() +{ + return (PINB & pinMask) == 0; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/src/digital_out.cpp b/Project_1_Rotary_Encoder/Part_1_Polling/src/digital_out.cpp new file mode 100644 index 0000000..2ccfa7d --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/src/digital_out.cpp @@ -0,0 +1,27 @@ +#include +#include + +Digital_out::Digital_out(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_out::init() +{ + DDRB |= pinMask; +} + +void Digital_out::set_hi() +{ + PORTB |= pinMask; +} + +void Digital_out::set_lo() +{ + PORTB &= static_cast(~pinMask); +} + +void Digital_out::toggle() +{ + PORTB ^= pinMask; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/src/encoder.cpp b/Project_1_Rotary_Encoder/Part_1_Polling/src/encoder.cpp new file mode 100644 index 0000000..9358129 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/src/encoder.cpp @@ -0,0 +1,48 @@ +#include + +Encoder::Encoder(int c1Pin, int c2Pin, int ledPin) + : c1(c1Pin), c2(c2Pin), led(ledPin), + previousC1(false), count(0) +{ +} + +void Encoder::init() +{ + c1.init(); + c2.init(); + led.init(); + + led.set_lo(); + + previousC1 = c1.is_hi(); + count = 0; +} + +void Encoder::update() +{ + led.set_lo(); + + bool currentC1 = c1.is_hi(); + + if (currentC1 != previousC1) + { + bool currentC2 = c2.is_hi(); + + if (currentC1 == currentC2) + { + count++; + } + else + { + count--; + } + + previousC1 = currentC1; + led.set_hi(); + } +} + +int Encoder::position() +{ + return count; +} diff --git a/Project_1_Rotary_Encoder/Part_1_Polling/src/main.cpp b/Project_1_Rotary_Encoder/Part_1_Polling/src/main.cpp new file mode 100644 index 0000000..93c7295 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_1_Polling/src/main.cpp @@ -0,0 +1,15 @@ +#include + +int main() +{ + Encoder encoder(0, 1, 5); + + encoder.init(); + + while (1) + { + encoder.update(); + } + + return 0; +} diff --git a/Project_1_Rotary_Encoder/Part_2_UART/include/digital_in.h b/Project_1_Rotary_Encoder/Part_2_UART/include/digital_in.h new file mode 100644 index 0000000..a3505c6 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/include/digital_in.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_IN_H +#define DIGITAL_IN_H + +#include + +class Digital_in +{ +public: + Digital_in(int pin); + + void init(); + + bool is_hi(); + bool is_lo(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_2_UART/include/digital_out.h b/Project_1_Rotary_Encoder/Part_2_UART/include/digital_out.h new file mode 100644 index 0000000..dd2b776 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/include/digital_out.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_OUT_H +#define DIGITAL_OUT_H + +#include + +class Digital_out +{ +public: + Digital_out(int pin); + + void init(); + void set_hi(); + void set_lo(); + void toggle(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_2_UART/include/encoder.h b/Project_1_Rotary_Encoder/Part_2_UART/include/encoder.h new file mode 100644 index 0000000..7332520 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/include/encoder.h @@ -0,0 +1,25 @@ +#ifndef ENCODER_H +#define ENCODER_H + +#include +#include + +class Encoder +{ +public: + Encoder(int c1Pin, int c2Pin, int ledPin); + + void init(); + void update(); + int position(); + +private: + Digital_in c1; + Digital_in c2; + Digital_out led; + + bool previousC1; + int count; +}; + +#endif diff --git a/Project_1_Rotary_Encoder/Part_2_UART/platformio.ini b/Project_1_Rotary_Encoder/Part_2_UART/platformio.ini new file mode 100644 index 0000000..023f2e5 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/platformio.ini @@ -0,0 +1,5 @@ +[env:nanoatmega328new] +platform = atmelavr +board = nanoatmega328new +framework = arduino +monitor_speed = 9600 diff --git a/Project_1_Rotary_Encoder/Part_2_UART/src/digital_in.cpp b/Project_1_Rotary_Encoder/Part_2_UART/src/digital_in.cpp new file mode 100644 index 0000000..2bbe6ef --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/src/digital_in.cpp @@ -0,0 +1,26 @@ +#include +#include + +Digital_in::Digital_in(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_in::init() +{ + // Configure pin as input + DDRB &= static_cast(~pinMask); + + // Enable internal pull-up resistor + PORTB |= pinMask; +} + +bool Digital_in::is_hi() +{ + return (PINB & pinMask) != 0; +} + +bool Digital_in::is_lo() +{ + return (PINB & pinMask) == 0; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_2_UART/src/digital_out.cpp b/Project_1_Rotary_Encoder/Part_2_UART/src/digital_out.cpp new file mode 100644 index 0000000..2ccfa7d --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/src/digital_out.cpp @@ -0,0 +1,27 @@ +#include +#include + +Digital_out::Digital_out(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_out::init() +{ + DDRB |= pinMask; +} + +void Digital_out::set_hi() +{ + PORTB |= pinMask; +} + +void Digital_out::set_lo() +{ + PORTB &= static_cast(~pinMask); +} + +void Digital_out::toggle() +{ + PORTB ^= pinMask; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_2_UART/src/encoder.cpp b/Project_1_Rotary_Encoder/Part_2_UART/src/encoder.cpp new file mode 100644 index 0000000..9358129 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/src/encoder.cpp @@ -0,0 +1,48 @@ +#include + +Encoder::Encoder(int c1Pin, int c2Pin, int ledPin) + : c1(c1Pin), c2(c2Pin), led(ledPin), + previousC1(false), count(0) +{ +} + +void Encoder::init() +{ + c1.init(); + c2.init(); + led.init(); + + led.set_lo(); + + previousC1 = c1.is_hi(); + count = 0; +} + +void Encoder::update() +{ + led.set_lo(); + + bool currentC1 = c1.is_hi(); + + if (currentC1 != previousC1) + { + bool currentC2 = c2.is_hi(); + + if (currentC1 == currentC2) + { + count++; + } + else + { + count--; + } + + previousC1 = currentC1; + led.set_hi(); + } +} + +int Encoder::position() +{ + return count; +} diff --git a/Project_1_Rotary_Encoder/Part_2_UART/src/main.cpp b/Project_1_Rotary_Encoder/Part_2_UART/src/main.cpp new file mode 100644 index 0000000..4a0044d --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_2_UART/src/main.cpp @@ -0,0 +1,22 @@ +#include +#include + +int main() +{ + init(); + + Encoder encoder(0, 1, 5); + + encoder.init(); + + Serial.begin(9600); + + while (1) + { + encoder.update(); + + Serial.println(encoder.position()); + } + + return 0; +} diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/include/digital_in.h b/Project_1_Rotary_Encoder/Part_3_Interrupt/include/digital_in.h new file mode 100644 index 0000000..a3505c6 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/include/digital_in.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_IN_H +#define DIGITAL_IN_H + +#include + +class Digital_in +{ +public: + Digital_in(int pin); + + void init(); + + bool is_hi(); + bool is_lo(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/include/digital_out.h b/Project_1_Rotary_Encoder/Part_3_Interrupt/include/digital_out.h new file mode 100644 index 0000000..dd2b776 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/include/digital_out.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_OUT_H +#define DIGITAL_OUT_H + +#include + +class Digital_out +{ +public: + Digital_out(int pin); + + void init(); + void set_hi(); + void set_lo(); + void toggle(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/include/encoder.h b/Project_1_Rotary_Encoder/Part_3_Interrupt/include/encoder.h new file mode 100644 index 0000000..272d7ce --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/include/encoder.h @@ -0,0 +1,25 @@ +#ifndef ENCODER_H +#define ENCODER_H + +#include +#include + +class Encoder +{ +public: + Encoder(int c1Pin, int c2Pin, int ledPin); + + void init(); + void update(); + int position(); + +private: + Digital_in c1; + Digital_in c2; + Digital_out led; + + bool previousC1; + volatile int count; +}; + +#endif \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/platformio.ini b/Project_1_Rotary_Encoder/Part_3_Interrupt/platformio.ini new file mode 100644 index 0000000..b1fc0bf --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/platformio.ini @@ -0,0 +1,15 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:nanoatmega328new] +platform = atmelavr +board = nanoatmega328new +framework = arduino +monitor_speed = 9600 diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/src/digital_in.cpp b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/digital_in.cpp new file mode 100644 index 0000000..2bbe6ef --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/digital_in.cpp @@ -0,0 +1,26 @@ +#include +#include + +Digital_in::Digital_in(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_in::init() +{ + // Configure pin as input + DDRB &= static_cast(~pinMask); + + // Enable internal pull-up resistor + PORTB |= pinMask; +} + +bool Digital_in::is_hi() +{ + return (PINB & pinMask) != 0; +} + +bool Digital_in::is_lo() +{ + return (PINB & pinMask) == 0; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/src/digital_out.cpp b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/digital_out.cpp new file mode 100644 index 0000000..2ccfa7d --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/digital_out.cpp @@ -0,0 +1,27 @@ +#include +#include + +Digital_out::Digital_out(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_out::init() +{ + DDRB |= pinMask; +} + +void Digital_out::set_hi() +{ + PORTB |= pinMask; +} + +void Digital_out::set_lo() +{ + PORTB &= static_cast(~pinMask); +} + +void Digital_out::toggle() +{ + PORTB ^= pinMask; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/src/encoder.cpp b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/encoder.cpp new file mode 100644 index 0000000..39f7c5a --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/encoder.cpp @@ -0,0 +1,81 @@ +#include +#include +#include + +static Encoder* activeEncoder = nullptr; + +ISR(PCINT0_vect) +{ + if (activeEncoder != nullptr) + { + activeEncoder->update(); + } +} + +Encoder::Encoder(int c1Pin, int c2Pin, int ledPin) + : c1(c1Pin), c2(c2Pin), led(ledPin), + previousC1(false), count(0) +{ +} + +void Encoder::init() +{ + c1.init(); + c2.init(); + led.init(); + + led.set_lo(); + + previousC1 = c1.is_hi(); + count = 0; + + activeEncoder = this; + + // Enable pin-change interrupts for PORTB + PCICR |= (1 << PCIE0); + + // Enable interrupt specifically for PB0 / D8 / C1 + PCMSK0 |= (1 << PCINT0); + + // Clear any pending PORTB pin-change interrupt + PCIFR |= (1 << PCIF0); + + // Enable global interrupts + sei(); +} + +void Encoder::update() +{ + led.set_lo(); + + bool currentC1 = c1.is_hi(); + + if (currentC1 != previousC1) + { + bool currentC2 = c2.is_hi(); + + if (currentC1 == currentC2) + { + count++; + } + else + { + count--; + } + + previousC1 = currentC1; + + led.set_hi(); + } +} + +int Encoder::position() +{ + uint8_t oldSREG = SREG; + + cli(); + int currentCount = count; + SREG = oldSREG; + + return currentCount; +} \ No newline at end of file diff --git a/Project_1_Rotary_Encoder/Part_3_Interrupt/src/main.cpp b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/main.cpp new file mode 100644 index 0000000..4df60e6 --- /dev/null +++ b/Project_1_Rotary_Encoder/Part_3_Interrupt/src/main.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + init(); + + Encoder encoder(0, 1, 5); + + encoder.init(); + + Serial.begin(9600); + + while (1) + { + Serial.println(encoder.position()); + } + + return 0; +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..97c7b10 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Embedded System Projects + +## Project 1 - Rotary Encoder Driver + +This repository contains the three implementations developed for Project 1 in T-738-EMBE. + +### Part 1 - Polling +Basic polling-based rotary encoder driver. + +### Part 2 - UART +Polling-based encoder driver with continuous Serial output at 9600 baud. + +### Part 3 - Interrupt +Interrupt-based encoder driver using a pin-change interrupt on C1.