#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>
// ----- Pin Map -----
#define IR_SIG 2 // PB2, active LOW when tripped
#define RUN_BTN 3 // PB3, active LOW
#define STOP_BTN 4 // PB4, active LOW
#define RUN_SIG 0 // PB0, output
#define RUN_LED 1 // PB1, output (active LOW)
volatile bool events = false;
static inline void respond();
int main(void) {
// ----- Pin Configuration -----
// Configure IR_SIG, RUN_BTN_ and STOP_BTN as inputs
DDRB &= ~((1 << IR_SIG) | (1 << RUN_BTN) | (1 << STOP_BTN));
// Enable internal pull-up resistors
PORTB |= (1 << IR_SIG) | (1 << RUN_BTN) | (1 << STOP_BTN);
// Configure RUN_SIG and RUN_LED as outputs
DDRB |= (1 << RUN_SIG) | (1 << RUN_LED);
// Initialize RUN_LED to OFF (active LOW)
PORTB |= (1 << RUN_LED);
PORTB &= ~(1 << RUN_SIG);
// Enable pin change interrupts
GIMSK |= (1 << PCIE);
PCMSK |= (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4); // Unmask pins
sei(); // Enable global interrupts
// ---- Wait for events ----
for (;;) {
// Check for events
if (events) {
respond();
events = false;
}
_delay_ms(10);
}
}
static inline void respond() {
// Flip run bit to 1 on START_BTN active low
if (!(PINB & (1 << RUN_BTN))) {
PORTB &= ~(1 << RUN_LED);
PORTB |= (1 << RUN_SIG);
}
// Flip run bit to 0 on IR_SIG or STOP_BTN active low
if (!(PINB & (1 << STOP_BTN)) || !(PINB & (1 << IR_SIG))) {
PORTB |= (1 << RUN_LED);
PORTB &= ~(1 << RUN_SIG);
}
}
// ISR for pin change pn PB0-PB5
ISR(PCINT0_vect) {
events = true;
}
Signal
Running
Power
Start
Stop
"Sensor"