Adding Project 1 rotary encoder implementations

This commit is contained in:
Thorsteinngretar
2026-09-04 18:16:15 +00:00
commit 82cd535a42
26 changed files with 630 additions and 0 deletions
@@ -0,0 +1,20 @@
#ifndef DIGITAL_IN_H
#define DIGITAL_IN_H
#include <stdint.h>
class Digital_in
{
public:
Digital_in(int pin);
void init();
bool is_hi();
bool is_lo();
private:
uint8_t pinMask;
};
#endif
@@ -0,0 +1,20 @@
#ifndef DIGITAL_OUT_H
#define DIGITAL_OUT_H
#include <stdint.h>
class Digital_out
{
public:
Digital_out(int pin);
void init();
void set_hi();
void set_lo();
void toggle();
private:
uint8_t pinMask;
};
#endif
@@ -0,0 +1,25 @@
#ifndef ENCODER_H
#define ENCODER_H
#include <digital_in.h>
#include <digital_out.h>
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
@@ -0,0 +1,4 @@
[env:nanoatmega328new]
platform = atmelavr
board = nanoatmega328new
framework = arduino
@@ -0,0 +1,26 @@
#include <digital_in.h>
#include <avr/io.h>
Digital_in::Digital_in(int pin)
{
pinMask = static_cast<uint8_t>(1U << pin);
}
void Digital_in::init()
{
// Configure pin as input
DDRB &= static_cast<uint8_t>(~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;
}
@@ -0,0 +1,27 @@
#include <digital_out.h>
#include <avr/io.h>
Digital_out::Digital_out(int pin)
{
pinMask = static_cast<uint8_t>(1U << pin);
}
void Digital_out::init()
{
DDRB |= pinMask;
}
void Digital_out::set_hi()
{
PORTB |= pinMask;
}
void Digital_out::set_lo()
{
PORTB &= static_cast<uint8_t>(~pinMask);
}
void Digital_out::toggle()
{
PORTB ^= pinMask;
}
@@ -0,0 +1,48 @@
#include <encoder.h>
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;
}
@@ -0,0 +1,15 @@
#include <encoder.h>
int main()
{
Encoder encoder(0, 1, 5);
encoder.init();
while (1)
{
encoder.update();
}
return 0;
}
@@ -0,0 +1,20 @@
#ifndef DIGITAL_IN_H
#define DIGITAL_IN_H
#include <stdint.h>
class Digital_in
{
public:
Digital_in(int pin);
void init();
bool is_hi();
bool is_lo();
private:
uint8_t pinMask;
};
#endif
@@ -0,0 +1,20 @@
#ifndef DIGITAL_OUT_H
#define DIGITAL_OUT_H
#include <stdint.h>
class Digital_out
{
public:
Digital_out(int pin);
void init();
void set_hi();
void set_lo();
void toggle();
private:
uint8_t pinMask;
};
#endif
@@ -0,0 +1,25 @@
#ifndef ENCODER_H
#define ENCODER_H
#include <digital_in.h>
#include <digital_out.h>
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
@@ -0,0 +1,5 @@
[env:nanoatmega328new]
platform = atmelavr
board = nanoatmega328new
framework = arduino
monitor_speed = 9600
@@ -0,0 +1,26 @@
#include <digital_in.h>
#include <avr/io.h>
Digital_in::Digital_in(int pin)
{
pinMask = static_cast<uint8_t>(1U << pin);
}
void Digital_in::init()
{
// Configure pin as input
DDRB &= static_cast<uint8_t>(~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;
}
@@ -0,0 +1,27 @@
#include <digital_out.h>
#include <avr/io.h>
Digital_out::Digital_out(int pin)
{
pinMask = static_cast<uint8_t>(1U << pin);
}
void Digital_out::init()
{
DDRB |= pinMask;
}
void Digital_out::set_hi()
{
PORTB |= pinMask;
}
void Digital_out::set_lo()
{
PORTB &= static_cast<uint8_t>(~pinMask);
}
void Digital_out::toggle()
{
PORTB ^= pinMask;
}
@@ -0,0 +1,48 @@
#include <encoder.h>
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;
}
@@ -0,0 +1,22 @@
#include <Arduino.h>
#include <encoder.h>
int main()
{
init();
Encoder encoder(0, 1, 5);
encoder.init();
Serial.begin(9600);
while (1)
{
encoder.update();
Serial.println(encoder.position());
}
return 0;
}
@@ -0,0 +1,20 @@
#ifndef DIGITAL_IN_H
#define DIGITAL_IN_H
#include <stdint.h>
class Digital_in
{
public:
Digital_in(int pin);
void init();
bool is_hi();
bool is_lo();
private:
uint8_t pinMask;
};
#endif
@@ -0,0 +1,20 @@
#ifndef DIGITAL_OUT_H
#define DIGITAL_OUT_H
#include <stdint.h>
class Digital_out
{
public:
Digital_out(int pin);
void init();
void set_hi();
void set_lo();
void toggle();
private:
uint8_t pinMask;
};
#endif
@@ -0,0 +1,25 @@
#ifndef ENCODER_H
#define ENCODER_H
#include <digital_in.h>
#include <digital_out.h>
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
@@ -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
@@ -0,0 +1,26 @@
#include <digital_in.h>
#include <avr/io.h>
Digital_in::Digital_in(int pin)
{
pinMask = static_cast<uint8_t>(1U << pin);
}
void Digital_in::init()
{
// Configure pin as input
DDRB &= static_cast<uint8_t>(~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;
}
@@ -0,0 +1,27 @@
#include <digital_out.h>
#include <avr/io.h>
Digital_out::Digital_out(int pin)
{
pinMask = static_cast<uint8_t>(1U << pin);
}
void Digital_out::init()
{
DDRB |= pinMask;
}
void Digital_out::set_hi()
{
PORTB |= pinMask;
}
void Digital_out::set_lo()
{
PORTB &= static_cast<uint8_t>(~pinMask);
}
void Digital_out::toggle()
{
PORTB ^= pinMask;
}
@@ -0,0 +1,81 @@
#include <encoder.h>
#include <avr/io.h>
#include <avr/interrupt.h>
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;
}
@@ -0,0 +1,20 @@
#include <Arduino.h>
#include <encoder.h>
int main()
{
init();
Encoder encoder(0, 1, 5);
encoder.init();
Serial.begin(9600);
while (1)
{
Serial.println(encoder.position());
}
return 0;
}