/* Đèn chạy 4 LED (GPIO17, 27, 22, 23), nút SW1 (GPIO26) đổi chiều.
* Ghi thẳng thanh ghi GPIO như trên Pi thật qua /dev/gpiomem.
*/
#include <stdbool.h>
#include <stdint.h>
/* Chỉ số thanh ghi (word) tính từ gpio_base */
#define GPFSEL_IDX(pin) ((pin) / 10U)
#define GPSET0_IDX (7U)
#define GPCLR0_IDX (10U)
#define GPLEV0_IDX (13U)
#define FSEL_MASK (7U)
#define FSEL_OUTPUT (1U)
#define LED_COUNT (4U)
#define BTN_PIN (26U)
#define STEP_MS (150U)
static const uint32_t led_pins[LED_COUNT] = {17U, 27U, 22U, 23U};
static void gpio_set_output(uint32_t pin)
{
uint32_t shift = (pin % 10U) * 3U;
uint32_t reg = gpio_base[GPFSEL_IDX(pin)];
reg &= ~(FSEL_MASK << shift);
reg |= (FSEL_OUTPUT << shift);
gpio_base[GPFSEL_IDX(pin)] = reg;
}
static bool is_button_pressed(void)
{
return (gpio_base[GPLEV0_IDX] & (1U << BTN_PIN)) == 0U;
}
int main(void)
{
uint32_t i;
uint32_t pos = 0U;
uint32_t all_mask = 0U;
bool is_forward = true;
bool was_pressed = false;
for (i = 0U; i < LED_COUNT; i++) {
gpio_set_output(led_pins[i]);
all_mask |= (1U << led_pins[i]);
}
while (true) {
bool pressed = is_button_pressed();
if (pressed && !was_pressed) {
is_forward = !is_forward;
}
was_pressed = pressed;
gpio_base[GPCLR0_IDX] = all_mask;
gpio_base[GPSET0_IDX] = (1U << led_pins[pos]);
if (is_forward) {
pos = (pos + 1U) % LED_COUNT;
} else {
pos = (pos + LED_COUNT - 1U) % LED_COUNT;
}
delay_ms(STEP_MS);
}
}