#include <Arduino.h>
#include <stdint.h>
/* =======================
* Pin Definitions
* ======================= */
#define BUTTON_PIN 2
#define LED1_PIN 3
#define LED2_PIN 4
#define LED3_PIN 5
#define LED4_PIN 6
#define TIME_DELAY 400
#define PATTERN_COUNT 5
/* =======================
* LED Series Definition
* ======================= */
typedef union {
uint8_t raw;
struct {
uint8_t led1 : 1;
uint8_t led2 : 1;
uint8_t led3 : 1;
uint8_t led4 : 1;
uint8_t unused : 4;
} bits;
} Led_Series_t;
/* =======================
* Pattern State
* ======================= */
typedef struct {
uint8_t step;
} PatternState_t;
/* =======================
* Pattern Function pointer Type
* ======================= */
typedef void (*PatternFn)(Led_Series_t *leds, PatternState_t *state, bool tick);
/* =======================
* Pattern Prototypes
* ======================= */
void pattern1(Led_Series_t *, PatternState_t *, bool);
void pattern2(Led_Series_t *, PatternState_t *, bool);
void pattern3(Led_Series_t *, PatternState_t *, bool);
void pattern4(Led_Series_t *, PatternState_t *, bool);
void pattern5(Led_Series_t *, PatternState_t *, bool);
/* =======================
* Pattern Table
* ======================= */
PatternFn patterns[PATTERN_COUNT] = {
pattern1,
pattern2,
pattern3,
pattern4,
pattern5
};
/* =======================
* Utility: Non-blocking timer
* ======================= */
bool time_elapsed(unsigned long* last, unsigned long interval)
{
uint32_t now = millis();
if (now - *last >= interval) {
*last = now;
return true;
}
return false;
}
/* =======================
* Hardware Abstraction
* ======================= */
void apply_leds(const Led_Series_t *leds)
{
digitalWrite(LED1_PIN, leds->bits.led1);
digitalWrite(LED2_PIN, leds->bits.led2);
digitalWrite(LED3_PIN, leds->bits.led3);
digitalWrite(LED4_PIN, leds->bits.led4);
}
/* =======================
* Setup
* ======================= */
void setup(void)
{
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT); // external pull-down
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
pinMode(LED3_PIN, OUTPUT);
pinMode(LED4_PIN, OUTPUT);
}
/* =======================
* Main Loop
* ======================= */
void loop(void)
{
static uint8_t pattern_index = 0;
static uint8_t last_button = LOW;
static unsigned long last_tick = 0;
static PatternState_t state = {0};
Led_Series_t leds = { .raw = 0 };
bool tick = time_elapsed(&last_tick, TIME_DELAY);
uint8_t button = digitalRead(BUTTON_PIN);
/* Rising edge detection */
if (button == HIGH && last_button == LOW) {
pattern_index = (pattern_index + 1) % PATTERN_COUNT;
state.step = 0; // clean reset on pattern change
}
last_button = button;
patterns[pattern_index](&leds, &state, tick);
apply_leds(&leds);
Serial.print("Pattern: ");
Serial.println(pattern_index + 1);
}
/* =======================
* Patterns Function Implementation
* ======================= */
void pattern1(Led_Series_t *leds, PatternState_t *state, bool tick)
{
if (tick) state->step ^= 1;
leds->raw = state->step ? 0x0F : 0x00;
}
void pattern2(Led_Series_t *leds, PatternState_t *state, bool tick)
{
if (tick) state->step ^= 1;
leds->raw = state->step ? 0b0101 : 0b1010;
}
void pattern3(Led_Series_t *leds, PatternState_t *state, bool tick)
{
if (tick) state->step = (state->step + 1) % 4;
leds->raw = (1 << state->step);
}
void pattern4(Led_Series_t *leds, PatternState_t *state, bool tick)
{
if (tick) state->step ^= 1;
leds->raw = state->step ? 0b0011 : 0b1100;
}
void pattern5(Led_Series_t *leds, PatternState_t *state, bool tick)
{
if (tick) state->step ^= 1;
leds->raw = state->step ? 0b1001 : 0b0110;
}
https://wokwi.com/projects/450728352539128833
