a vim plugin that displays stuff on an led matrix
1#include <stdlib.h>
2
3#include <cstring>
4#include <stdio.h>
5
6#include "pico/multicore.h"
7#include "pico/stdlib.h"
8#include <time.h>
9
10// Define GPIO pins for rows and columns
11#define ROWS 4
12#define COLS 6
13
14const uint ROW_PINS[4] = {12, 13, 14, 15};
15const uint COL_PINS[6] = {17, 18, 19, 20, 21, 22};
16
17// LED state matrix
18uint8_t led_states[ROWS][COLS] = {0};
19
20// brightness control
21uint8_t brightness = 100;
22
23// timing vars
24bool fading = false;
25absolute_time_t last_char_time;
26absolute_time_t fade_start_time;
27const uint32_t inactivity_timeout_ms = 0;
28const uint32_t fade_duration_ms = 1200;
29
30void randomize_matrix() {
31 for (int row = 0; row < ROWS; row++) {
32 for (int col = 0; col < COLS; col++) {
33 led_states[row][col] = rand() % 2;
34 }
35 }
36}
37
38// Function to update the display at variable frequencies
39void update_led_display(uint32_t refresh_rate_hz) {
40 static uint32_t last_update = 0;
41 uint32_t current_time = to_ms_since_boot(get_absolute_time());
42 uint32_t update_interval = 1000 / refresh_rate_hz;
43
44 // Only update at the specified frequency
45 if (current_time - last_update < update_interval) {
46 return;
47 }
48
49 last_update = current_time;
50
51 uint32_t time_since_last_char = absolute_time_diff_us(last_char_time, get_absolute_time()) / 1000;
52
53 if (!fading && time_since_last_char > inactivity_timeout_ms) {
54 // start fading
55 fading = true;
56 fade_start_time = get_absolute_time();
57 }
58
59 if (fading) {
60 uint32_t fade_elapsed_ms = absolute_time_diff_us(fade_start_time, get_absolute_time()) / 1000;
61
62 if (fade_elapsed_ms >= fade_duration_ms) {
63 brightness = 0;
64 } else {
65 brightness = 100 - ((fade_elapsed_ms * 100) / fade_duration_ms);
66 }
67 }
68
69 // Skip display update if brightness is 0
70 if (brightness == 0) {
71 // Turn off all rows and set all columns high to ensure LEDs are off
72 for (int i = 0; i < ROWS; i++) {
73 gpio_put(ROW_PINS[i], 0);
74 }
75 for (int j = 0; j < COLS; j++) {
76 gpio_put(COL_PINS[j], 1);
77 }
78
79 return;
80 }
81
82 // Software PWM cycle
83 for (uint8_t pwm_cycle = 0; pwm_cycle < brightness; pwm_cycle++) {
84 // For each row
85 for (int row = 0; row < ROWS; row++) {
86 // Activate row
87 gpio_put(ROW_PINS[row], 1);
88
89 // Set column states for this row
90 for (int col = 0; col < COLS; col++) {
91 gpio_put(COL_PINS[col], led_states[row][col] ? 0 : 1);
92 }
93
94 // Keep row active for a short time
95 sleep_us(50);
96
97 // Deactivate row
98 gpio_put(ROW_PINS[row], 0);
99 }
100 }
101}
102void setup_pins() {
103 // Set up row pins
104 for (int i = 0; i < ROWS; i++) {
105 gpio_init(ROW_PINS[i]);
106 gpio_set_dir(ROW_PINS[i], GPIO_OUT);
107 gpio_put(ROW_PINS[i], 0); // Start with LEDs off
108 }
109
110 // Set up column pins
111 for (int j = 0; j < COLS; j++) {
112 gpio_init(COL_PINS[j]);
113 gpio_set_dir(COL_PINS[j], GPIO_OUT);
114 gpio_put(COL_PINS[j], 1); // Start with LEDs off
115 }
116}
117
118void core1_main() {
119 while (true) {
120 update_led_display(1000); // Update at 60Hz for smoother display
121 sleep_ms(1); // Small delay to prevent tight loop
122 }
123}
124
125int main() {
126 stdio_init_all();
127 setup_pins();
128
129 // seed the random number generator
130 srand(time_us_32());
131
132 last_char_time = get_absolute_time();
133
134 multicore_launch_core1(core1_main);
135
136 while (true) {
137 // check if there are characters available from the input
138 int c = getchar_timeout_us(0);
139
140 if (c != PICO_ERROR_TIMEOUT) {
141 // echo char back
142 printf("%c", c);
143
144 last_char_time = get_absolute_time();
145
146 fading = false;
147 brightness = 100;
148
149 randomize_matrix();
150
151 while (getchar_timeout_us(0) != PICO_ERROR_TIMEOUT) {}
152 }
153
154 sleep_ms(10);
155 }
156}