49#define ANSI_GOTO(row, col) (void)printf("\033[%d;%dH", (row), (col))
52#define ANSI_SHOW_CURSOR() (void)printf("\033[?25h")
55#define ANSI_HIDE_CURSOR() (void)printf("\033[?25l")
58#define ANSI_RESET "\033[0m"
61#define ANSI_BOLD "\033[1m"
64#define ANSI_DIM "\033[2m"
67#define ANSI_GREEN "\033[32m"
70#define ANSI_YELLOW "\033[33m"
73#define ANSI_MAGENTA "\033[35m"
76#define ANSI_CYAN "\033[36m"
79#define ANSI_WHITE "\033[37m"
82#define ANSI_BG_GREEN "\033[42m"
85#define ANSI_BG_MAGENTA "\033[45m"
128 uint8_t source_id,
bool is_send) {
129 if ((hist == NULL) || (data == NULL) || (len == 0u)) {
134 uint8_t clamped_len = len;
141 (void)memcpy(entry->
data, data, clamped_len);
142 entry->
len = clamped_len;
188 start_idx = hist->
head;
193 int goto_row = (int)row + 1 + (
int)i;
196 if (i < hist->count) {
206 if (entry->
len == 1u) {
209 for (uint8_t j = 0u; (j < entry->
len) && (j < 3u); j++) {
210 (void)printf(
"%02X", entry->
data[j]);
247void display_render_bar(uint8_t row,
const char* task_name, uint32_t elapsed_ticks, uint32_t period_ticks) {
249 uint32_t period = period_ticks;
255 uint32_t elapsed = elapsed_ticks;
256 if (elapsed > period) {
263 uint32_t filled = (elapsed * (uint32_t)
BAR_WIDTH) / period;
272 (void)printf(
"[%s] ", (task_name != NULL) ? task_name :
"unknown");
275 for (uint32_t i = 0u; i < (uint32_t)
BAR_WIDTH; i++) {
284 (void)printf(
" %4" PRIu32
" / %4" PRIu32
" ticks", elapsed, period);
287 (void)printf(
"\033[K");
312 (void)printf(
"[%s] ", task_name);
314 for (uint32_t i = 0u; i < ((uint32_t)
BAR_WIDTH - 20u); i++) {
317 (void)printf(
" [%s]", task_name);
319 (void)printf(
"\033[K");
322 (void)printf(
"\033[K");
353 uint32_t mc = max_count;
357 uint32_t cnt = count;
362 uint32_t filled_rows = (cnt * (uint32_t)
VBAR_HEIGHT) / mc;
369 int label_row = (int)start_row - 1;
376 (void)printf(
"+---+");
379 for (uint8_t i = 0u; i < (uint8_t)
VBAR_HEIGHT; i++) {
380 int bar_row = (int)start_row + 1 + (
int)i;
382 uint8_t row_from_bottom = (uint8_t)((uint8_t)
VBAR_HEIGHT - 1u) - i;
383 if ((uint32_t)row_from_bottom < filled_rows) {
392 int bottom_row = (int)start_row + (
int)
VBAR_HEIGHT + 1;
395 (void)printf(
"+---+");
399 int count_row = (int)start_row + (
int)
VBAR_HEIGHT + 2;
402 (void)printf(
"%2" PRIu32
"/%2" PRIu32, cnt, mc);
432 uint8_t count, uint8_t max_count,
433 uint8_t last_sent, uint8_t last_recv,
434 bool show_sent,
bool show_recv) {
436 uint8_t mc = max_count;
446 uint8_t bar_width = 8u;
447 uint8_t filled = (uint8_t)((uint8_t)(cnt * bar_width) / mc);
451 (void)printf(
"\033[36m%s\033[0m", label);
455 int q_row = (int)start_row + 1;
459 for (uint8_t i = 0u; i < bar_width; i++) {
461 (void)printf(
"\033[33m█\033[0m");
470 int cnt_row = (int)start_row + 2;
473 (void)printf(
"%2d/%2d", cnt, mc);
477 int sent_row = (int)start_row + 3;
481 (void)printf(
"\033[32m→%3d\033[0m", last_sent);
488 int recv_row = (int)start_row + 4;
492 (void)printf(
"\033[35m←%3d\033[0m", last_recv);
517 uint32_t elapsed_ticks, uint32_t period_ticks,
518 uint8_t msg_value,
bool show_msg) {
520 uint32_t period = period_ticks;
524 uint32_t elapsed = elapsed_ticks;
525 if (elapsed > period) {
529 uint32_t filled = (elapsed * (uint32_t)
BAR_WIDTH) / period;
537 (void)printf(
"\033[32m[%s]\033[0m ", (task_name != NULL) ? task_name :
"unknown");
540 for (uint32_t i = 0u; i < (uint32_t)
BAR_WIDTH; i++) {
542 (void)printf(
"\033[32m█\033[0m");
549 (void)printf(
" %4" PRIu32
"/%4" PRIu32, elapsed, period);
554 (void)printf(
" \033[32;1m→[%3d]\033[0m", msg_value);
559 (void)printf(
"\033[K");
581 uint32_t elapsed_ticks, uint32_t period_ticks,
582 uint8_t msg_value,
bool show_msg) {
584 uint32_t period = period_ticks;
588 uint32_t elapsed = elapsed_ticks;
589 if (elapsed > period) {
593 uint32_t filled = (elapsed * (uint32_t)
BAR_WIDTH) / period;
601 (void)printf(
"\033[35m[%s]\033[0m ", (task_name != NULL) ? task_name :
"unknown");
604 for (uint32_t i = 0u; i < (uint32_t)
BAR_WIDTH; i++) {
606 (void)printf(
"\033[35m█\033[0m");
613 (void)printf(
" %4" PRIu32
"/%4" PRIu32, elapsed, period);
618 (void)printf(
" \033[35;1m←[%3d]\033[0m", msg_value);
623 (void)printf(
"\033[K");
655 static uint8_t initialized = 0u;
656 if (initialized != 0u) {
662 (void)printf(
"\033[2J");
677 (void)printf(
"\033[2K");
678 (void)printf(
"┌──────────────────────────────────────────────────────────────┐");
682 (void)printf(
"\033[2K");
683 (void)printf(
"│ ██╗ ██████╗ █████╗ ██████╗ ██╗ ██╗ ██████╗ │");
687 (void)printf(
"\033[2K");
688 (void)printf(
"│ ██║██╔════╝ ██╔══██╗██╔══██╗██║ ██║██╔════╝ │");
692 (void)printf(
"\033[2K");
693 (void)printf(
"│ ██║██║ ███████║██████╔╝██║ ██║╚█████╗ │");
697 (void)printf(
"\033[2K");
698 (void)printf(
"│ ██║██║ ██╔══██║██╔══██╗██║ ██║ ╚═══██╗ │");
702 (void)printf(
"\033[2K");
703 (void)printf(
"│ ██║╚██████╗ ██║ ██║██║ ██║╚██████╔╝██████╔╝ │");
707 (void)printf(
"\033[2K");
708 (void)printf(
"│ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ │");
712 (void)printf(
"\033[2K");
713 (void)printf(
"│ Preemptive Kernel • ARMv7E-M • STM32H750 │");
717 (void)printf(
"\033[2K");
718 (void)printf(
"└──────────────────────────────────────────────────────────────┘");
721 (void)printf(
"\r\nDTCM Protection Active - System Running\r\n");
726#if ENABLE_HEARTBEAT_VISUALIZATION
736 uint8_t user_task_count = 0u;
738 for (uint8_t i = 0u; (i < num_tasks) && (user_task_count < 3u); i++) {
742 if ((name != NULL) && (name[0] !=
'\0')) {
744 if (strncmp(name,
"ICARUS_", 7) != 0) {
746 uint8_t disp_row = (uint8_t)((uint8_t)
ROW_TASK_A + user_task_count);
748 if (user_task_count == 1u) {
750 }
else if (user_task_count == 2u) {
763#if ENABLE_HEARTBEAT_VISUALIZATION
void display_render_pipe(uint8_t start_row, uint8_t col, const char *label, uint8_t count, uint8_t max_count, uint8_t last_sent, uint8_t last_recv, bool show_sent, bool show_recv)
Render a message queue (pipe) visualization panel.
void display_render_msg_history(uint8_t row, uint8_t col, msg_history_t *hist, const char *label)
Render message history as a rolling window display.
void msg_history_add(msg_history_t *hist, const uint8_t *data, uint8_t len, uint8_t source_id, bool is_send)
Add a message to the history buffer.
void display_render_banner(uint8_t row, const char *task_name, bool is_on)
Render a flashing banner indicator (heartbeat display)
void display_init(void)
Initialize terminal display subsystem.
void msg_history_init(msg_history_t *hist)
Initialize a message history buffer.
void display_render_bar(uint8_t row, const char *task_name, uint32_t elapsed_ticks, uint32_t period_ticks)
Render a horizontal progress bar for task visualization.
void display_render_vbar(uint8_t start_row, uint8_t col, uint32_t count, uint32_t max_count)
Render a vertical bar showing semaphore fill level.
void display_render_producer(uint8_t row, const char *task_name, uint32_t elapsed_ticks, uint32_t period_ticks, uint8_t msg_value, bool show_msg)
Render a producer task progress bar with message indicator.
void display_render_consumer(uint8_t row, const char *task_name, uint32_t elapsed_ticks, uint32_t period_ticks, uint8_t msg_value, bool show_msg)
Render a consumer task progress bar with message indicator.
#define TASK_A_PERIOD_TICKS
#define TASK_C_PERIOD_TICKS
#define TASK_B_PERIOD_TICKS
#define MSG_HISTORY_MAX_BYTES
#define ANSI_HIDE_CURSOR()
Hide terminal cursor.
#define ANSI_BOLD
Bold text attribute.
#define ANSI_MAGENTA
Magenta foreground color.
#define ANSI_CYAN
Cyan foreground color.
#define ANSI_GREEN
Green foreground color.
#define ANSI_GOTO(row, col)
Move cursor to specified row and column (1-indexed)
#define ANSI_RESET
Reset all text attributes.
ICARUS Kernel Core - State and Initialization.
ICARUS Scheduler - Task Scheduling and Timing.
const char * os_get_task_name(uint8_t task_idx)
Get task name by index (safe from unprivileged mode)
uint8_t os_get_num_created_tasks(void)
Get number of created tasks (safe from unprivileged mode)
Message history entry for rolling window display.
Message history buffer for a pipe.
msg_history_entry_t entries[8]