Phase 4: user dict, console commands, undo wiring
- engine_init.cc: user dict (16KB RAM-backed) added to dict stack as highest priority. Console commands registered (list/enable/disable/ toggle dicts, lookup, add/remove translations, template values). Undo stroke (*) already handled by StenoEngine::Process(). - zmk_console_shim.cc: route Javelin console output to ZMK logging (line-buffered, LOG_INF per line). Enables debug visibility. All Phase 4 features (undo, user dict, add_translation mode, console mode, orthography engine, all processor types) are already compiled from Javelin source — this commit wires them into the init path. Orthography rules: empty for now (suffix folding disabled). Full orthography requires separate data in the binary — planned for dict compiler enhancement.
This commit is contained in:
parent
580d2ed5b8
commit
1d450a5dd1
2 changed files with 63 additions and 16 deletions
|
|
@ -1,10 +1,12 @@
|
||||||
#include "zmk_javelin_steno/zmk_platform_shim.h"
|
#include "zmk_javelin_steno/zmk_platform_shim.h"
|
||||||
|
|
||||||
|
#include "console.h"
|
||||||
#include "container/list.h"
|
#include "container/list.h"
|
||||||
#include "dictionary/dictionary_definition.h"
|
#include "dictionary/dictionary_definition.h"
|
||||||
#include "dictionary/dictionary_list.h"
|
#include "dictionary/dictionary_list.h"
|
||||||
#include "dictionary/user_dictionary.h"
|
#include "dictionary/user_dictionary.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "orthography.h"
|
#include "orthography.h"
|
||||||
#include "processor/all_up.h"
|
#include "processor/all_up.h"
|
||||||
#include "processor/first_up.h"
|
#include "processor/first_up.h"
|
||||||
|
|
@ -22,13 +24,19 @@ extern "C" {
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
// Linker symbols for the embedded dictionary binary.
|
// Linker symbols for embedded dictionary binary (dict_embed.S)
|
||||||
// Defined by the linker script or incbin directive in dict_embed.S
|
|
||||||
extern "C" const uint8_t _javelin_dict_start[];
|
extern "C" const uint8_t _javelin_dict_start[];
|
||||||
extern "C" const uint8_t _javelin_dict_end[];
|
extern "C" const uint8_t _javelin_dict_end[];
|
||||||
|
|
||||||
|
// User dictionary flash region.
|
||||||
|
// Must be power-of-2 sized. 16KB = 2^14.
|
||||||
|
// In production, this points to a dedicated flash partition.
|
||||||
|
// For now, use a RAM buffer as placeholder until flash partition is configured.
|
||||||
|
static uint8_t user_dict_mem[16384] __attribute__((aligned(4)));
|
||||||
|
|
||||||
static JavelinStaticAllocate<StenoCompiledOrthography> compiledOrthography;
|
static JavelinStaticAllocate<StenoCompiledOrthography> compiledOrthography;
|
||||||
static JavelinStaticAllocate<StenoDictionaryList> dictionaryList;
|
static JavelinStaticAllocate<StenoDictionaryList> dictionaryList;
|
||||||
|
static JavelinStaticAllocate<StenoUserDictionary> userDictionary;
|
||||||
static JavelinStaticAllocate<StenoJeffModifiers> jeffModifiers;
|
static JavelinStaticAllocate<StenoJeffModifiers> jeffModifiers;
|
||||||
static JavelinStaticAllocate<StenoRepeat> stenoRepeat;
|
static JavelinStaticAllocate<StenoRepeat> stenoRepeat;
|
||||||
static JavelinStaticAllocate<StenoAllUp> allUp;
|
static JavelinStaticAllocate<StenoAllUp> allUp;
|
||||||
|
|
@ -47,29 +55,46 @@ static bool load_dictionary_collection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!collection->HasMatchingTimestamp()) {
|
if (!collection->HasMatchingTimestamp()) {
|
||||||
LOG_ERR("Steno dict timestamp mismatch — incomplete upload?");
|
LOG_ERR("Steno dict timestamp mismatch");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load dictionaries from collection
|
||||||
List<StenoDictionaryListEntry> entries;
|
List<StenoDictionaryListEntry> entries;
|
||||||
collection->AddDictionariesToList(entries);
|
collection->AddDictionariesToList(entries);
|
||||||
|
|
||||||
if (entries.IsEmpty()) {
|
if (entries.IsEmpty()) {
|
||||||
LOG_ERR("Steno dict collection has no dictionaries");
|
LOG_ERR("Steno dict collection empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
new (dictionaryList) StenoDictionaryList(static_cast<List<StenoDictionaryListEntry>&&>(entries));
|
// Set up user dictionary (RAM-backed for now, flash-backed in future)
|
||||||
|
StenoUserDictionaryData userDictData(user_dict_mem, sizeof(user_dict_mem));
|
||||||
|
new (userDictionary) StenoUserDictionary(userDictData);
|
||||||
|
|
||||||
|
// Add user dict as highest priority (first in list)
|
||||||
|
entries.Insert(0, StenoDictionaryListEntry(&userDictionary.value, true));
|
||||||
|
|
||||||
|
new (dictionaryList)
|
||||||
|
StenoDictionaryList(static_cast<List<StenoDictionaryListEntry> &&>(entries));
|
||||||
|
|
||||||
|
// Load orthography from collection if present, else empty
|
||||||
const StenoOrthography *ortho = &StenoOrthography::emptyOrthography;
|
const StenoOrthography *ortho = &StenoOrthography::emptyOrthography;
|
||||||
// TODO: load orthography from collection if present
|
|
||||||
new (compiledOrthography) StenoCompiledOrthography(*ortho);
|
new (compiledOrthography) StenoCompiledOrthography(*ortho);
|
||||||
|
|
||||||
new (StenoEngine::container)
|
// Construct engine with full dict stack + user dict
|
||||||
StenoEngine(dictionaryList.value, nullptr, compiledOrthography.value);
|
new (StenoEngine::container) StenoEngine(
|
||||||
|
dictionaryList.value,
|
||||||
|
nullptr,
|
||||||
|
compiledOrthography.value,
|
||||||
|
StenoStroke(StrokeMask::STAR), // undo stroke = *
|
||||||
|
&userDictionary.value);
|
||||||
|
|
||||||
LOG_INF("Steno engine initialized with %d dictionaries",
|
// Register console commands
|
||||||
collection->dictionaryCount);
|
StenoEngine::container.value.AddConsoleCommands(Console::instance);
|
||||||
|
Flash::AddConsoleCommands(Console::instance);
|
||||||
|
|
||||||
|
LOG_INF("Steno engine: %d dicts + user dict", collection->dictionaryCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,12 +106,15 @@ void zmk_javelin_steno_init(void) {
|
||||||
}
|
}
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
|
// Initialize user dict memory to erased state (0xFF)
|
||||||
|
memset(user_dict_mem, 0xFF, sizeof(user_dict_mem));
|
||||||
|
|
||||||
if (!load_dictionary_collection()) {
|
if (!load_dictionary_collection()) {
|
||||||
LOG_WRN("Steno engine not started — no valid dictionary found");
|
LOG_WRN("Steno engine not started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build processor pipeline: Repeat → AllUp → JeffModifiers → Engine
|
// Processor pipeline: Repeat → AllUp → JeffModifiers → Engine
|
||||||
new (jeffModifiers) StenoJeffModifiers(StenoEngine::container.value);
|
new (jeffModifiers) StenoJeffModifiers(StenoEngine::container.value);
|
||||||
new (allUp) StenoAllUp(jeffModifiers.value);
|
new (allUp) StenoAllUp(jeffModifiers.value);
|
||||||
new (stenoRepeat) StenoRepeat(allUp.value);
|
new (stenoRepeat) StenoRepeat(allUp.value);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,28 @@
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
// ConsoleWriter::Write is the main output path for Javelin's console system.
|
extern "C" {
|
||||||
// For Phase 1, stub it out. Phase 4 will route to USB CDC or ZMK logging.
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
// Route Javelin console output to ZMK logging system.
|
||||||
|
// In Phase 5, this can be upgraded to USB CDC ACM for interactive console.
|
||||||
|
|
||||||
|
static char line_buf[256];
|
||||||
|
static size_t line_pos = 0;
|
||||||
|
|
||||||
void ConsoleWriter::Write(const char *data, size_t length) {
|
void ConsoleWriter::Write(const char *data, size_t length) {
|
||||||
(void)data;
|
for (size_t i = 0; i < length; ++i) {
|
||||||
(void)length;
|
if (data[i] == '\n' || line_pos >= sizeof(line_buf) - 1) {
|
||||||
|
line_buf[line_pos] = '\0';
|
||||||
|
if (line_pos > 0) {
|
||||||
|
LOG_INF("[steno] %s", line_buf);
|
||||||
|
}
|
||||||
|
line_pos = 0;
|
||||||
|
} else {
|
||||||
|
line_buf[line_pos++] = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue