Skip to content

Commit

Permalink
Userspace LED Matrix Driver
Browse files Browse the repository at this point in the history
  • Loading branch information
echavemann committed Dec 8, 2024
1 parent 26acd41 commit 4f4772e
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 3 deletions.
2 changes: 2 additions & 0 deletions include/drivers/driver_enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ enum class DriverCommand {
BUTTONS = 2,
TERMINAL_OUTPUT = 3,
TIMER_CANCEL = 4,
SET_PIN = 5,
CLEAR_PIN = 6,
};

enum class DriverSubscribe { NOTIFY_BUTTON_PRESS = 0, TIMER_START = 1 };
Expand Down
4 changes: 4 additions & 0 deletions include/userlib/syscalls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ start_timer(void (*callback)(uint32_t), uint32_t microseconds, bool periodic = f

void cancel_timer(uint32_t timer_id);

void set_pin(uint32_t pin);

void clear_pin(uint32_t pin);

// We need a syscall for this because SVC will not be preempted by SysTick
// Technically this is insecure - it's mostly for debugging
void debug_print(const char* string);
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/driver_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "drivers/driver_enums.hpp"
#include "drivers/led_display.hpp"
#include "drivers/virtual_timer_controller.hpp"
#include "hal/gpio_wrapper.hpp"

#include <stdio.h>

Expand Down Expand Up @@ -35,6 +36,12 @@ etl::optional<int> handle_command(DriverCommand type, int arg1, int arg2, int ar
static_cast<uint32_t>(arg1)
);
break;
case DriverCommand::SET_PIN:
edge::aidan::set_gpio_pin(static_cast<uint32_t>(arg1));
break;
case DriverCommand::CLEAR_PIN:
edge::aidan::clear_gpio_pin(static_cast<uint32_t>(arg1));
break;
}
return etl::nullopt;
}
Expand Down
9 changes: 6 additions & 3 deletions src/entrypoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@
extern void ipc_part1(void);
extern void ipc_part2(void);
extern void exception_task(void);
extern void led_matrix_task(void);

int main(void)
{
printf("Starting EdgeOS\n");

edge::FaultHandler::get();

edge::scheduler.add_task(exception_task);
/* edge::scheduler.add_task(exception_task); */

edge::scheduler.add_task(ipc_part1);
edge::scheduler.add_task(ipc_part2);
/* edge::scheduler.add_task(ipc_part1); */
/* edge::scheduler.add_task(ipc_part2); */

edge::scheduler.add_task(led_matrix_task);

edge::scheduler.start_scheduler();
}
66 changes: 66 additions & 0 deletions src/user_programs/user_program_led_matrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "hal/gpio_wrapper.hpp"
#include "microbit_v2.h"
#include "scheduler/pending_process_callbacks.hpp"
#include "userlib/syscalls.hpp"

#include <stdint.h>

#include <cstdio>

uint8_t row_index = 0;
bool led_states[5][5] = {false};
uint32_t rows[] = {LED_ROW1, LED_ROW2, LED_ROW3, LED_ROW4, LED_ROW5};
uint32_t cols[] = {LED_COL1, LED_COL2, LED_COL3, LED_COL4, LED_COL5};

static uint8_t control_row = 0;
static uint8_t control_col = 0;

void upkeep_led_matrix(uint32_t id)
{
edge::userlib::clear_pin(rows[0]);
edge::userlib::clear_pin(rows[1]);
edge::userlib::clear_pin(rows[2]);
edge::userlib::clear_pin(rows[3]);
edge::userlib::clear_pin(rows[4]);
for (int col_index = 0; col_index < 5; ++col_index) {
bool state = led_states[row_index][col_index];
if (!state) {
edge::userlib::set_pin(cols[col_index]);
}
else {
edge::userlib::clear_pin(cols[col_index]);
}
}
edge::userlib::set_pin(rows[row_index]);
row_index++;
row_index = row_index % 5;
}

void update_led_states(uint32_t id)
{
bool st = led_states[control_row][control_col];
led_states[control_row][control_col] = !st;

control_col++;
if (control_col == 5) {
control_row++;
control_col = 0;
}
control_row %= 5;
}

void led_matrix_task(void)
{
using namespace edge::userlib;
// We want to call this so that the led_matrix driver sets up all the directions of
// the pins so we don't have to...
set_led(2, 2, true);
set_led(2, 2, false);

start_timer(upkeep_led_matrix, 2'000, true);
start_timer(update_led_states, 10'000, true);

while (1) {
yield();
}
}
14 changes: 14 additions & 0 deletions src/userlib/syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ void USER_CODE cancel_timer(uint32_t timer_id)
TRIGGER_SVC(SystemCallType::COMMAND);
}

void USER_CODE set_pin(uint32_t pin)
{
SET_REGISTER(r0, (int)drivers::DriverCommand::SET_PIN);
SET_REGISTER(r1, (int)pin);
TRIGGER_SVC(SystemCallType::COMMAND);
}

void USER_CODE clear_pin(uint32_t pin)
{
SET_REGISTER(r0, (int)drivers::DriverCommand::CLEAR_PIN);
SET_REGISTER(r1, (int)pin);
TRIGGER_SVC(SystemCallType::COMMAND);
}

void USER_CODE debug_print(const char* val)
{
SET_REGISTER(r0, (int)drivers::DriverCommand::TERMINAL_OUTPUT);
Expand Down

0 comments on commit 4f4772e

Please sign in to comment.