Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions device/prj.conf.overlays/nrf_shared.conf
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,16 @@ CONFIG_SHELL_VT100_COMMANDS=y
CONFIG_SHELL_VT100_COLORS=y
CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH=80
CONFIG_BT_SHELL=y
CONFIG_SHELL_BT_NUS=y
CONFIG_SHELL_BT_NUS=n
CONFIG_HWINFO=y
CONFIG_HWINFO_SHELL=y
CONFIG_I2C=y
CONFIG_I2C_SHELL=y
CONFIG_STREAM_FLASH=y
CONFIG_SETTINGS_SHELL=y
CONFIG_SHELL_BACKENDS=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_BACKEND_SERIAL=n
CONFIG_UART_ASYNC_RX_HELPER=y

CONFIG_BUILD_OUTPUT_HEX=y
CONFIG_BUILD_OUTPUT_META=y
Expand Down
2 changes: 0 additions & 2 deletions device/prj.conf.overlays/uhk-80-right.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ CONFIG_PINCTRL_DYNAMIC=y

CONFIG_SHELL=y
CONFIG_SHELL_AUTOSTART=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC=y


7 changes: 5 additions & 2 deletions device/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ if(NOT CONFIG_BOARD_UHK_60_RIGHT)
resend.c
round_trip_test.c
settings.c
shell.c
shell_backend_usb.c
shell/shell_backend_usb.c
shell/shell_transport_uhk.c
shell/shell_uhk.c
shell/shell_commands.c
shell/sinks.c
state_sync.c
thread_stats.c
)
Expand Down
12 changes: 7 additions & 5 deletions device/src/keyboard/oled/screens/debug_screen.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#include "debug_screen.h"
#include "keyboard/oled/widgets/widget_store.h"
#include "keyboard/oled/widgets/widgets.h"

widget_t splitter;
widget_t* DebugScreen;

void DebugScreen_Init() {
const uint8_t totalHeight = DISPLAY_HEIGHT - 2*DISPLAY_SHIFTING_MARGIN; //56
const uint8_t debugLineHeight = 6;
const uint8_t consoleHeight = totalHeight - debugLineHeight;
splitter = SplitterWidget_BuildVertical(&ConsoleWidget, &DebugLineWidget, consoleHeight, true);
DebugScreen = &splitter;
// const uint8_t totalHeight = DISPLAY_HEIGHT - 2*DISPLAY_SHIFTING_MARGIN; //56
// const uint8_t debugLineHeight = 6;
// const uint8_t consoleHeight = totalHeight - debugLineHeight;
// splitter = SplitterWidget_BuildVertical(&ConsoleWidget, &DebugLineWidget, consoleHeight, true);
// DebugScreen = &splitter;
DebugScreen = &ConsoleWidget;
}
32 changes: 30 additions & 2 deletions device/src/keyboard/oled/widgets/console_widget.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

static char consoleBuffer[CONSOLE_BUFFER_LINE_COUNT][CONSOLE_BUFFER_LINE_LENGTH] = {};
static uint8_t consoleBufferStart = 0;
static uint8_t currentCol = 0;
static bool consoleBufferIsDirty = true;

void ConsoleWidget_LayOut(widget_t* self, uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Expand Down Expand Up @@ -60,10 +61,37 @@ widget_t ConsoleWidget_Build()
}


static void advanceLine(void)
{
consoleBufferStart = (consoleBufferStart + 1) % CONSOLE_BUFFER_LINE_COUNT;
consoleBuffer[consoleBufferStart][0] = '\0';
currentCol = 0;
}

static const char shellPrompt[] = "uhk80:right$";

static void logConstant(const char* text)
{
consoleBufferStart = (consoleBufferStart+1) % CONSOLE_BUFFER_LINE_COUNT;
snprintf(&consoleBuffer[consoleBufferStart][0], CONSOLE_BUFFER_LINE_LENGTH, "%s", text);
for (const char* p = text; *p != '\0'; p++) {
if (currentCol == 0 && strncmp(p, shellPrompt, sizeof(shellPrompt) - 1) == 0) {
p += sizeof(shellPrompt) - 2;
consoleBuffer[consoleBufferStart][currentCol++] = '$';
consoleBuffer[consoleBufferStart][currentCol] = '\0';
continue;
}
if (*p == '\n') {
if (currentCol > 0) {
advanceLine();
}
} else if (*p == '\r') {
// skip
} else {
if (currentCol < CONSOLE_BUFFER_LINE_LENGTH - 1) {
consoleBuffer[consoleBufferStart][currentCol++] = *p;
consoleBuffer[consoleBufferStart][currentCol] = '\0';
}
}
}

consoleBufferIsDirty = true;

Expand Down
2 changes: 1 addition & 1 deletion device/src/logger_priority.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ int set_thread_priority_by_name(const char *thread_name, int new_priority) {
void Logger_SetPriority(bool high) {
int8_t priority = high ? -1 : 14;
set_thread_priority_by_name("logging", K_PRIO_PREEMPT(priority));
set_thread_priority_by_name("shell_uart", K_PRIO_PREEMPT(priority));
set_thread_priority_by_name("UhkShell", K_PRIO_PREEMPT(priority));
set_thread_priority_by_name("shell_rtt", K_PRIO_PREEMPT(priority));
}

9 changes: 4 additions & 5 deletions device/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "keyboard/i2c.h"
#include "peripherals/merge_sensor.h"
#include "shell.h"
#include "shell/shell_transport_uhk.h"
#include "shell/shell_uhk.h"
#include "device.h"
#include "usb/usb.h"
#include "bt_conn.h"
Expand Down Expand Up @@ -52,7 +54,6 @@
#include "test_suite/test_suite.h"
#include "wormhole.h"
#include "power_mode.h"
#include "proxy_log_backend.h"
#include "logger_priority.h"
#include "keyboard/uart_modules.h"

Expand Down Expand Up @@ -208,13 +209,11 @@ void mainRuntime(void) {

PinWiring_Resume();

ReinitShell();
ShellUartTransport_Reinit();
}

// Needs to be after ReinitShell, probably
// Needs to be after ShellUartTransport_Reinit, probably
InitShellCommands();
InitProxyLogBackend();

Shell_WaitUntilInitialized();
Logger_SetPriority(true);

Expand Down
5 changes: 2 additions & 3 deletions device/src/pin_wiring.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "attributes.h"
#include "shell.h"
#include "shell/shell_transport_uhk.h"
#include "bt_conn.h"
#include "device.h"
#include "keyboard/charger.h"
Expand All @@ -21,7 +21,6 @@
#include "mouse_keys.h"
#include "config_manager.h"
#include <zephyr/shell/shell_backend.h>
#include <zephyr/shell/shell_uart.h>
#include <zephyr/shell/shell.h>
#include "connections.h"
#include "logger_priority.h"
Expand Down Expand Up @@ -236,7 +235,7 @@ void PinWiring_SelectRouting(void) {
}

void PinWiring_UninitShell(void) {
UninitShell();
ShellUartTransport_Uninit();
uninitUart(&uart0);
}

Expand Down
154 changes: 58 additions & 96 deletions device/src/proxy_log_backend.c
Original file line number Diff line number Diff line change
@@ -1,148 +1,110 @@
#include "proxy_log_backend.h"
#include <zephyr/logging/log_backend.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/logging/log_output.h>
#include <zephyr/logging/log_backend.h>
#include <zephyr/logging/log_msg.h>
#include <zephyr/logging/log_instance.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "attributes.h"
#include "logger.h"
#include "macros/status_buffer.h"
#include "trace.h"
#include "wormhole.h"
#include "zephyr/logging/log_core.h"
#include "shell/sinks.h"
#include "config_manager.h"
#include "usb_log_buffer.h"
#include "config_manager.h"

typedef struct {
bool outputToStatusBuffer;
bool outputToUsbBuffer;
bool outputToOled;
} proxy_log_context_t;

#define PROXY_BACKEND_BUFFER_SIZE 2048

bool ProxyLog_IsInPanicMode = false;

static void processLog(const struct log_backend *const backend, union log_msg_generic *msg);

void panic(const struct log_backend *const backend) {
StateWormhole_Open();
StateWormhole.persistStatusBuffer = true;

if (!ProxyLog_IsInPanicMode) {
ProxyLog_IsInPanicMode = true;

MacroStatusBuffer_Validate();
printk("===== PANIC =====\n");
Trace_Print(LogTarget_ErrorBuffer, "crash/panic");
}

};
// --- Log output callback ---

static int outputFunc(uint8_t *data, size_t length, void *ctx)
{
proxy_log_context_t* outputs = (proxy_log_context_t*)ctx;
shell_sinks_t *sinks = (shell_sinks_t *)ctx;

if (outputs->outputToStatusBuffer) {
if (sinks->toStatusBuffer) {
Macros_SanitizedPut(data, data + length);
}
if (outputs->outputToUsbBuffer) {
if (sinks->toUsbBuffer) {
UsbLogBuffer_Print(data, length);
}
if (outputs->outputToOled) {
LogO("%.*s", length, data);
if (sinks->toOled) {
LogO("%.*s", (int)length, data);
}
return length;
}

// Allocate memory for actual log processing
// --- Log output buffer ---

#define LOG_BUFFER_SIZE 256
static char logBuf[LOG_BUFFER_SIZE];
static struct log_output_control_block logControlBlock;
static struct log_output logOutput = {
.func = outputFunc,
.buf = logBuf,
.size = LOG_BUFFER_SIZE,
.control_block = &logControlBlock,
};

// Helper to get the log source name from a log message
ATTR_UNUSED static const char *getLogSourceName(struct log_msg *msg) {
static char logBuf[LOG_BUFFER_SIZE];
static struct log_output_control_block logControlBlock;
static struct log_output logOutput = {
.func = outputFunc,
.buf = logBuf,
.size = LOG_BUFFER_SIZE,
.control_block = &logControlBlock,
};

// --- Helpers ---

static const char *getLogSourceName(struct log_msg *msg)
{
const void *source = log_msg_get_source(msg);
if (source == NULL) {
return "unknown";
}
// The source pointer is a log_source_const_data struct which has a name field
const struct log_source_const_data *src_data = (const struct log_source_const_data *)source;
return src_data->name ? src_data->name : "unnamed";
}

static void processLog(const struct log_backend *const backend, union log_msg_generic *msg) {
proxy_log_context_t outputs = (proxy_log_context_t){
.outputToStatusBuffer = false,
.outputToUsbBuffer = false,
.outputToOled = false,
};

if (WormCfg->UsbLogEnabled) {
outputs.outputToUsbBuffer = true;
outputs.outputToOled = true;
}
// --- Log backend API ---

if (ProxyLog_IsInPanicMode) {
outputs.outputToStatusBuffer = true;
}
static void proxyProcess(const struct log_backend *const backend, union log_msg_generic *msg)
{
shell_sinks_t sinks = ShellConfig_GetLogSinks();

if (WormCfg->devMode) {
// PoC: Extract log source and level information
uint8_t level = log_msg_get_level(&msg->log);
const char *sourceName = getLogSourceName(&msg->log);
if ( level >= LOG_LEVEL_WRN && strcmp(sourceName, "c2usb") == 0) {
outputs.outputToStatusBuffer = true;
if (level >= LOG_LEVEL_WRN && strcmp(sourceName, "c2usb") == 0) {
sinks.toStatusBuffer = true;
}
}

if (outputs.outputToStatusBuffer || outputs.outputToUsbBuffer || outputs.outputToOled) {
log_output_ctx_set(&logOutput, &outputs);
if (sinks.toStatusBuffer || sinks.toUsbBuffer || sinks.toOled) {
log_output_ctx_set(&logOutput, &sinks);
uint8_t flags = LOG_OUTPUT_FLAG_CRLF_LFONLY;
log_output_msg_process(&logOutput, &msg->log, flags);
}
}

void init(const struct log_backend *const backend) {};
int format_set(const struct log_backend *const backend, uint32_t log_type) { return 0; };
void notify(const struct log_backend *const backend, enum log_backend_evt event, union log_backend_evt_arg *arg) {};
static int is_ready(const struct log_backend *const backend) { return 0; }

static struct log_backend_api proxyApi = (struct log_backend_api) {
.process = processLog,
.dropped = NULL,
.panic = panic,
.init = init,
.is_ready = is_ready,
.format_set = format_set,
.notify = notify,
};
static void proxyPanic(const struct log_backend *const backend)
{
ShellConfig_ActivatePanicMode();
}

#define PROXY_LOG_BACKEND_AUTOSTART true
static void proxyInit(const struct log_backend *const backend)
{
}

LOG_BACKEND_DEFINE(logProxy, proxyApi, PROXY_LOG_BACKEND_AUTOSTART);
static int proxyIsReady(const struct log_backend *const backend)
{
return 0;
}

void InitProxyLogBackend(void) {
#if !PROXY_LOG_BACKEND_AUTOSTART
log_init();
static int proxyFormatSet(const struct log_backend *const backend, uint32_t log_type)
{
return 0;
}

const struct log_backend *backend = log_backend_get_by_name("logProxy");
static void proxyNotify(const struct log_backend *const backend, enum log_backend_evt event, union log_backend_evt_arg *arg)
{
}

log_output_ctx_set(&logOutput, backend->cb->ctx);
static const struct log_backend_api proxyApi = {
.process = proxyProcess,
.dropped = NULL,
.panic = proxyPanic,
.init = proxyInit,
.is_ready = proxyIsReady,
.format_set = proxyFormatSet,
.notify = proxyNotify,
};

log_backend_activate(backend, backend->cb->ctx);
#endif
}
LOG_BACKEND_DEFINE(UhkLog, proxyApi, true);
Loading