Update:
I am trying to fix my history cycling thing, but even if I do shift + up/down it does nothing, so I need to figure out how to fix this.
I am trying to fix my history cycling thing, but even if I do shift + up/down it does nothing, so I need to figure out how to fix this.
No luck in trying to fix it. I may post parts of my code here tommorow (the parts in relation to the issues I have been having) for any chance of fixing this. Astrox Radio/Podcast Episode 2 2025 Releasing on Sunday!!!
History Cycling is when your on the command line, and you use the up and down arrow to cycle through your most recently used commands, but in my osâs case, you have to use shift with the up/down arrow.
add_to_history function
// Stores used commands in history so they can be used for command_history
void add_to_history(const char *command) {
if (command[0] == '\0') return; // Don't log empty commands
size_t len = strlen(command);
if (len >= MAX_COMMAND_LENGTH) len = MAX_COMMAND_LENGTH - 1;
// Add at current history_index position
strncpy(commandHistory[history_index], command, len);
commandHistory[history_index][len] = '\0';
history_index = (history_index + 1) % MAX_HISTORY; // Circular buffer advance
history_cycle_index = -1; // reset cycling on new command
}
command_history_cycle_up function
// Cycles up through command history (older entries)
void command_history_cycle_up(char *buffer, int *idx) {
bool any = false;
for (int i = 0; i < MAX_HISTORY; ++i) if (commandHistory[i][0] != '\0') { any = true; break; }
if (!any) return;
if (history_cycle_index == -1) {
history_cycle_index = (history_index - 1 + MAX_HISTORY) % MAX_HISTORY; // Most recent command
} else {
history_cycle_index = (history_cycle_index - 1 + MAX_HISTORY) % MAX_HISTORY; // older command
}
int start = history_cycle_index;
while (commandHistory[history_cycle_index][0] == '\0') {
history_cycle_index = (history_cycle_index - 1 + MAX_HISTORY) % MAX_HISTORY;
if (history_cycle_index == start) { // no commands found
history_cycle_index = -1;
return;
}
}
// Clear current line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
// Copy selected command to buffer and display
strncpy(buffer, commandHistory[history_cycle_index], MAX_COMMAND_LENGTH - 1);
buffer[MAX_COMMAND_LENGTH - 1] = '\0';
*idx = strlen(buffer);
for (int i = 0; i < *idx; i++) display_emit(buffer[i]);
}
command_history_cycle_down function
void command_history_cycle_down(char *buffer, int *idx) {
if (history_cycle_index == -1) return; // Not cycling
history_cycle_index = (history_cycle_index + 1) % MAX_HISTORY;
if (history_cycle_index == history_index) { // means clear line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
buffer[0] = '\0';
history_cycle_index = -1;
return;
}
int start = history_cycle_index;
while (commandHistory[history_cycle_index][0] == '\0') {
history_cycle_index = (history_cycle_index + 1) % MAX_HISTORY;
if (history_cycle_index == start) {
history_cycle_index = -1;
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
buffer[0] = '\0';
return;
}
}
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
strncpy(buffer, commandHistory[history_cycle_index], MAX_COMMAND_LENGTH - 1);
buffer[MAX_COMMAND_LENGTH - 1] = '\0';
*idx = strlen(buffer);
for (int i = 0; i < *idx; i++) display_emit(buffer[i]);
}
related parts from read_line function
int idx = 0;
history_cycle_index = -1; // Reset history position at start
// Detect Shift key (0xA2 or 0xA3), then wait for follow-up arrow key
if (c == 0xA2 || c == 0xA3) {
// Wait for next key (arrow key)
while (!keyboard_key_available()) {
if (user_interrupt) {
display_emit('\r');
display_emit('\n');
printf("^C\n");
user_interrupt = false;
buffer[0] = '\0';
return;
}
tight_loop_contents();
}
int next_raw = keyboard_get_key();
if (next_raw < 0) continue;
unsigned char next_c = (unsigned char)next_raw;
if (next_c == 0x48) { // Shift + Up arrow
command_history_cycle_up(buffer, &idx);
continue;
} else if (next_c == 0xB6) { // Shift + Down arrow
command_history_cycle_down(buffer, &idx);
continue;
}
// If not recognized, ignore and continue input
continue;
}
Please feel free to help, and spot any mistakes I have made.
Thanks!
Accroding to the source code of the keyboard firmware
https://github.com/clockworkpi/PicoCalc/blob/master/Code/picocalc_keyboard/keyboard.ino
The firmware deal with modify keys like alt and shift itself and the capslock status as well.
It will send you a page up/down scan code when you press shift + up/down.
If your are not going to modify the keyboard firmware to adapt your âOSâ
you need to workaround with this FEATURE
I am using Blairâs picocalc-text-starter drivers, and I am using the keyboard.c driver in there.
Here are some updated parts of my code in relation to the history cycling thing I am trying to implement, but it wonât work.
read_line
// Reads a line from keyboard into 'buffer', echoing to display, up to maxLength-1 chars
void read_line(char *buffer, int maxLength) {
int idx = 0;
history_cycle_index = -1; // Reset history position at start
bool shift_pressed = false;
while (idx < maxLength - 1) {
if (!keyboard_key_available()) {
if (user_interrupt) {
display_emit('\r');
display_emit('\n');
printf("^C\n");
user_interrupt = false;
buffer[0] = '\0';
return;
}
tight_loop_contents();
continue;
}
int raw = keyboard_get_key();
if (raw < 0) continue;
unsigned char c = (unsigned char)raw;
// Debug: Uncomment this line to see what scan codes you're getting
// printf("[DEBUG: Got key 0x%02X]\n", c);
// Check for Page Up (0x21) - this is what the keyboard sends for Shift+Up
if (c == 0x21) {
command_history_cycle_up(buffer, &idx);
continue;
}
// Check for Page Down (0x22) - this is what the keyboard sends for Shift+Down
if (c == 0x22) {
command_history_cycle_down(buffer, &idx);
continue;
}
// Alternative: Check for uppercase versions of arrow keys if shift is applied
// Some keyboards send different codes
if (c == 0x48 || c == 0x26) { // Possible Up arrow or shifted Up arrow codes
command_history_cycle_up(buffer, &idx);
continue;
}
if (c == 0x50 || c == 0x28) { // Possible Down arrow or shifted Down arrow codes
command_history_cycle_down(buffer, &idx);
continue;
}
// Handle Enter key - end input
if (c == '\r' || c == '\n') break;
// Handle backspace
if (c == 0x7F || c == 0x08) {
if (idx > 0) {
idx--;
display_emit('\b');
display_emit(' ');
display_emit('\b');
}
continue;
}
// Ignore unprintable characters (but not the special keys we're looking for)
if (c < 32 || c > 126) {
// Skip other unprintable characters
continue;
}
// Regular printable input
buffer[idx++] = (char)c;
display_emit((char)c);
}
buffer[idx] = '\0';
display_emit('\r');
display_emit('\n');
}
command cycle up
// Cycles up through command history (older entries)
void command_history_cycle_up(char *buffer, int *idx) {
bool any = false;
for (int i = 0; i < MAX_HISTORY; ++i) if (commandHistory[i][0] != '\0') { any = true; break; }
if (!any) return;
if (history_cycle_index == -1) {
history_cycle_index = (history_index - 1 + MAX_HISTORY) % MAX_HISTORY; // Most recent command
} else {
history_cycle_index = (history_cycle_index - 1 + MAX_HISTORY) % MAX_HISTORY; // older command
}
int start = history_cycle_index;
while (commandHistory[history_cycle_index][0] == '\0') {
history_cycle_index = (history_cycle_index - 1 + MAX_HISTORY) % MAX_HISTORY;
if (history_cycle_index == start) { // no commands found
history_cycle_index = -1;
return;
}
}
// Clear current line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
// Copy selected command to buffer and display
strncpy(buffer, commandHistory[history_cycle_index], MAX_COMMAND_LENGTH - 1);
buffer[MAX_COMMAND_LENGTH - 1] = '\0';
*idx = strlen(buffer);
for (int i = 0; i < *idx; i++) display_emit(buffer[i]);
}
command cycle down
void command_history_cycle_down(char *buffer, int *idx) {
if (history_cycle_index == -1) return; // Not currently cycling through history
// Move forward in history (toward newer commands)
int next_index = (history_cycle_index + 1) % MAX_HISTORY;
// Check if we've cycled back to the current position
if (next_index == history_index) {
// We've reached the end - clear the line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
buffer[0] = '\0';
history_cycle_index = -1;
return;
}
// Find the next non-empty command
int start = next_index;
while (commandHistory[next_index][0] == '\0') {
next_index = (next_index + 1) % MAX_HISTORY;
if (next_index == start || next_index == history_index) {
// No more commands found - clear line
history_cycle_index = -1;
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
buffer[0] = '\0';
return;
}
}
history_cycle_index = next_index;
// Clear current line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
// Display the command from history
strncpy(buffer, commandHistory[history_cycle_index], MAX_COMMAND_LENGTH - 1);
buffer[MAX_COMMAND_LENGTH - 1] = '\0';
*idx = strlen(buffer);
for (int i = 0; i < *idx; i++) display_emit(buffer[i]);
}
** add to history**
// Stores used commands in history so they can be used for command_history
void add_to_history(const char *command) {
if (command[0] == '\0') return; // Don't log empty commands
// Copy the command to the history buffer safely
strncpy(commandHistory[history_index], command, MAX_COMMAND_LENGTH - 1);
commandHistory[history_index][MAX_COMMAND_LENGTH - 1] = '\0'; // Ensure null termination
history_index = (history_index + 1) % MAX_HISTORY; // Circular buffer advance
history_cycle_index = -1; // reset cycling on new command
}
Please help
@jblanked @BlairLeduc (sorry for tagging, but you two are the most experienced with the drivers)
I donât understand why you are having trouble here with your code? With six months of experience, surely you can read C code that you depend upon to use it correctly?
Ya, with more then six months under his belt, heâs apparently at masters level by now⌠puzzlingâŚ
Iâve tried my best, I just canât find a fix. I have tested it, and I know the read_line function is working, but I can guarantee that the command_history_cycle_up, and command_history_cycle_down functions arenât working as indented and the add_to_history function might be working, but I donât know.
Here is some of my code, I desprately need help
function command_history_cycle_up
// Moves backward (up) through the command history
void command_history_cycle_up(char *buffer, int *idx) {
if (!history_has_entries()) return;
int original = history_cycle_idx;
if (history_cycle_idx == -1) {
// Start from most recent
history_cycle_idx = (history_next_idx - 1 + MAX_HISTORY) % MAX_HISTORY;
} else {
// Move one entry earlier
history_cycle_idx = (history_cycle_idx - 1 + MAX_HISTORY) % MAX_HISTORY;
}
// Skip over empty entries
while (history[history_cycle_idx][0] == '\0' &&
history_cycle_idx != original) {
history_cycle_idx = (history_cycle_idx - 1 + MAX_HISTORY) % MAX_HISTORY;
}
// If we went all the way around and found nothing, stop cycling
if (history[history_cycle_idx][0] == '\0') {
history_cycle_idx = original;
return;
}
// Clear current line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
strncpy(buffer, history[history_cycle_idx], MAX_COMMAND_LENGTH - 1);
buffer[MAX_COMMAND_LENGTH - 1] = '\0';
*idx = strlen(buffer);
for (int i = 0; i < *idx; i++) {
display_emit(buffer[i]);
}
}
function command_history_cycle_down
// Moves forward (down) through the command history or clears the line at newest
void command_history_cycle_down(char *buffer, int *idx) {
if (!history_has_entries() || history_cycle_idx == -1) return;
int original = history_cycle_idx;
int next_idx = (history_cycle_idx + 1) % MAX_HISTORY;
// If at or past newest command, clear line
if (next_idx == history_next_idx || history[next_idx][0] == '\0') {
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
buffer[0] = '\0';
history_cycle_idx = -1;
return;
}
history_cycle_idx = next_idx;
// Skip empty entries
while (history[history_cycle_idx][0] == '\0' &&
history_cycle_idx != original) {
history_cycle_idx = (history_cycle_idx + 1) % MAX_HISTORY;
if (history_cycle_idx == history_next_idx) {
history_cycle_idx = -1;
buffer[0] = '\0';
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
return;
}
}
// Clear current line
while (*idx > 0) {
display_emit('\b');
display_emit(' ');
display_emit('\b');
(*idx)--;
}
strncpy(buffer, history[history_cycle_idx], MAX_COMMAND_LENGTH - 1);
buffer[MAX_COMMAND_LENGTH - 1] = '\0';
*idx = strlen(buffer);
for (int i = 0; i < *idx; i++) {
display_emit(buffer[i]);
}
}
function add_to_history
// Add command to history; overwrites oldest if buffer full
void add_to_history(const char *command) {
if (command[0] == '\0') return; // Do not store empty commands
strncpy(history[history_next_idx], command, MAX_COMMAND_LENGTH - 1);
history[history_next_idx][MAX_COMMAND_LENGTH - 1] = '\0'; // Ensure null terminated
history_next_idx = (history_next_idx + 1) % MAX_HISTORY;
history_cycle_idx = -1; // Reset cycling position when new command added
}
Please help, iâve been working on this same issue for the last 5 daysâŚ
Listen @Astrox, when you wrote me with this text and snippets of code:
I interpreted this as not asking for help, it is expecting, no, telling me to help you. I am no longer going to be to be part of this circus.
No, no more, Iâm tired of it too.
Thanks to Blair Leduc for the drivers, and this whole community for any contributions.
I have made the time actually count! This may seem confusing, so let me explain. Before, time was just a static string, which wouldnât update every minute, hour, etc. So I fixed that, and now, the time actually accurately updates.
As many of you know, Astralixi OS has already seen its Alpha and Beta releases â and now, Iâm looking to create a âteamâ! Iâm currently searching for around 3 contributors to join me in pushing Astralixi even further. Whether youâre into systems programming, UI/UX (future of Astralixi OS), or just passionate about OS development, this is a great chance to get involved. If youâre interested in contributing, please fill out the application form here:
https://take.supersurvey.com/QB50PAFU4
GUIs will be added to Astralixi OS in version two or three and onwards. Version one will have more commands, and improvements.
The taskbar will show battery percentage, time, and will have a quick access menu button.