commit ce1f6db630d608bdf7f0688c839f8b5728894931
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Sat, 27 Sep 2025 23:58:51 -0300
first commit
Diffstat:
6 files changed, 193 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,42 @@
+PORT ?= /dev/ttyUSB0
+BIN_DIR = bin
+SRC_DIR = src
+INC_DIR = include
+
+SRCS := $(wildcard $(SRC_DIR)/*.c)
+LIBS := $(INC_DIR/*.h)
+OBJS := $(patsubst $(SRC_DIR)/%.c,$(BIN_DIR)/%.o,$(SRCS))
+
+CC := avr-gcc
+CFLAGS := -Wall -Os -DF_CPU=16000000UL -mmcu=atmega328p -I ./$(INC_DIR)
+
+.PHONY: all
+
+all: $(BIN_DIR) compile
+
+$(BIN_DIR)/%.o: $(SRC_DIR)/%.c
+ $(CC) $(CFLAGS) \
+ -c $< -o $@
+ @echo ""
+
+compile: $(OBJS)
+ $(CC) $(CFLAGS) \
+ -o $(BIN_DIR)/main.elf $(OBJS)
+ @echo ""
+ avr-objcopy -O ihex -R .eeprom $(BIN_DIR)/main.elf $(BIN_DIR)/main.hex
+
+upload: compile
+ avrdude -F -V -c arduino -p ATMEGA328P \
+ -P $(PORT) -b 115200 -U flash:w:$(BIN_DIR)/main.hex
+
+$(BIN_DIR):
+ @if [ ! -d "$(BIN_DIR)" ]; then \
+ echo "Creating folder '$(BIN_DIR)'"; \
+ mkdir -p $(BIN_DIR); \
+ fi
+
+size:
+ avr-size --format=avr --mcu=atmega328p $(BIN_DIR)/main.elf
+
+clean:
+ rm -rf $(BIN_DIR)
diff --git a/include/scheduler.h b/include/scheduler.h
@@ -0,0 +1,20 @@
+#ifndef _SCHEDULER_H_
+#define _SCHEDULER_H_
+
+#define SCHEDULER_MAX_TASKS_CNT 10
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+void scheduler_init(void);
+void scheduler_update(void);
+void scheduler_append_task(void (*update_func)(void), uint16_t update_interval);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _SCHEDULER_H_
diff --git a/include/timer.h b/include/timer.h
@@ -0,0 +1,9 @@
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#include <stdint.h>
+
+void timer_init(void);
+void timer_add_callback(void (*func_ptr)(void));
+
+#endif // _TIMER_H_
diff --git a/src/main.c b/src/main.c
@@ -0,0 +1,37 @@
+#include <avr/io.h>
+
+#include "timer.h"
+#include "scheduler.h"
+
+#define LED_1_PIN 3
+#define LED_2_PIN 4
+
+void toggle_led_1(void) {
+ PIND = (1 << LED_1_PIN);
+}
+
+void toggle_led_2(void) {
+ PIND = (1 << LED_2_PIN);
+}
+
+void setup(void) {
+ DDRD |= (1 << LED_1_PIN) | (1 << LED_2_PIN);
+
+ scheduler_init(tasks, tasks_cnt);
+
+ // scheduler_append_task(&toggle_led_1, 1000);
+ // scheduler_append_task(&toggle_led_2, 500);
+
+ timer_init();
+ timer_add_callback(&scheduler_update);
+}
+
+int main(void) {
+ setup();
+
+ while(1) {
+ ;;
+ }
+
+ return 0;
+}
diff --git a/src/scheduler.c b/src/scheduler.c
@@ -0,0 +1,45 @@
+#include "scheduler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ void (*task_update)(void);
+ uint16_t update_interval;
+ uint16_t ticks;
+} task_t;
+
+typedef struct {
+ uint8_t task_cnt;
+ task_t tasks[SCHEDULER_MAX_TASKS_CNT];
+} scheduler_t;
+
+static scheduler_t scheduler = {0};
+
+void scheduler_init(void) {
+ scheduler.task_cnt = 0;
+}
+
+// should be called exactly every ms
+void scheduler_update(void) {
+ for (uint8_t i = 0; i < scheduler.task_cnt; ++i) {
+ if (scheduler.tasks[i].ticks > 0) {
+ scheduler.tasks[i].ticks--;
+ continue;
+ }
+
+ scheduler.tasks[i].ticks = scheduler.tasks[i].update_interval;
+ scheduler.tasks[i].task_update();
+ }
+}
+
+void scheduler_append_task(void (*update_func)(void), uint16_t update_interval) {
+ scheduler.tasks[scheduler.task_cnt].task_update = update_func;
+ scheduler.tasks[scheduler.task_cnt].update_interval = update_interval - 1;
+ scheduler.task_cnt++;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/timer.c b/src/timer.c
@@ -0,0 +1,40 @@
+#include "timer.h"
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#define TIMER_CALLBACKS_MAX_CNT 1
+
+typedef struct {
+ uint8_t callbacks_cnt;
+ void (*callbacks[TIMER_CALLBACKS_MAX_CNT])(void);
+} timer_t;
+
+static timer_t timer = {0};
+
+ISR(TIMER0_COMPA_vect) {
+ for(uint8_t i = 0; i < timer.callbacks_cnt; ++i) {
+ timer.callbacks[i]();
+ }
+}
+
+// normal mode, prescaler 64, max value 250 == exact 1 interrupt per ms
+void timer_init(void) {
+ cli();
+ TCCR0A = (1 << WGM01) | (1 << COM0A0);
+ TCCR0B = (1 << CS01) | (1 << CS00);
+ TIMSK0 = (1 << OCIE0A);
+ OCR0A = 250;
+ sei();
+
+ // timer_add_callback(&timer_increment_millis);
+}
+
+void timer_add_callback(void (*callback)(void)) {
+ if (timer.callbacks_cnt == TIMER_CALLBACKS_MAX_CNT) {
+ return;
+ }
+
+ timer.callbacks[timer.callbacks_cnt] = callback;
+ timer.callbacks_cnt++;
+}