Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
rumbledethumps authored Nov 12, 2023
1 parent f0557a1 commit f9651a0
Show file tree
Hide file tree
Showing 6 changed files with 340 additions and 140 deletions.
226 changes: 185 additions & 41 deletions src/ria/sys/com.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@
#include "sys/pix.h"
#include "sys/ria.h"
#include "sys/vga.h"
#include "vga/term/ansi.h"
#include "pico/stdlib.h"
#include "pico/stdio/driver.h"
#include <stdio.h>

#define COM_BUF_SIZE 256
#define COM_CSI_PARAM_MAX_LEN 16

typedef enum
{
ansi_state_C0,
ansi_state_Fe,
ansi_state_SS2,
ansi_state_SS3,
ansi_state_CSI
} ansi_state_t;

static char com_buf[COM_BUF_SIZE];
static com_read_callback_t com_callback;
static uint8_t *com_binary_buf;
Expand All @@ -25,8 +35,8 @@ static size_t com_bufsize;
static size_t com_buflen;
static size_t com_bufpos;
static ansi_state_t com_ansi_state;
static int com_ansi_param;

static uint16_t com_csi_param[COM_CSI_PARAM_MAX_LEN];
static uint8_t com_csi_param_count;
static stdio_driver_t com_stdio_app;

volatile size_t com_tx_tail;
Expand Down Expand Up @@ -80,35 +90,101 @@ void com_reclock(void)
uart_init(COM_UART, COM_UART_BAUD_RATE);
}

static void com_line_forward(size_t count)
static void com_line_home(void)
{
if (com_bufpos)
printf("\33[%dD", com_bufpos);
com_bufpos = 0;
}

static void com_line_end(void)
{
if (com_bufpos != com_buflen)
printf("\33[%dC", com_buflen - com_bufpos);
com_bufpos = com_buflen;
}

static void com_line_forward_word(void)
{
int count = 0;
if (com_bufpos < com_buflen)
while (true)
{
count++;
if (++com_bufpos >= com_buflen)
break;
if (com_buf[com_bufpos] == ' ' && com_buf[com_bufpos - 1] != ' ')
break;
}
if (count)
printf("\33[%dC", count);
}

static void com_line_forward(void)
{
uint16_t count = com_csi_param[0];
if (count < 1)
count = 1;
if (com_csi_param_count > 1 && !!(com_csi_param[1] - 1))
return com_line_forward_word();
if (count > com_buflen - com_bufpos)
count = com_buflen - com_bufpos;
if (!count)
return;
com_bufpos += count;
// clang-format off
printf(ANSI_FORWARD(%d), count);
// clang-format on
printf("\33[%dC", count);
}

static void com_line_forward_1(void)
{
com_csi_param_count = 1;
com_csi_param[0] = 1;
com_line_forward();
}

static void com_line_backward(size_t count)
static void com_line_backward_word(void)
{
int count = 0;
if (com_bufpos)
while (true)
{
count++;
if (!--com_bufpos)
break;
if (com_buf[com_bufpos] != ' ' && com_buf[com_bufpos - 1] == ' ')
break;
}
if (count)
printf("\33[%dD", count);
}

static void com_line_backward(void)
{
uint16_t count = com_csi_param[0];
if (count < 1)
count = 1;
if (com_csi_param_count > 1 && !!(com_csi_param[1] - 1))
return com_line_backward_word();
if (count > com_bufpos)
count = com_bufpos;
if (!count)
return;
com_bufpos -= count;
// clang-format off
printf(ANSI_BACKWARD(%d), count);
// clang-format on
printf("\33[%dD", count);
}

static void com_line_backward_1(void)
{
com_csi_param_count = 1;
com_csi_param[0] = 1;
com_line_backward();
}

static void com_line_delete(void)
{
if (!com_buflen || com_bufpos == com_buflen)
return;
printf(ANSI_DELETE(1));
printf("\33[P");
com_buflen--;
for (uint8_t i = com_bufpos; i < com_buflen; i++)
com_buf[i] = com_buf[i + 1];
Expand All @@ -118,18 +194,41 @@ static void com_line_backspace(void)
{
if (!com_bufpos)
return;
printf("\b" ANSI_DELETE(1));
printf("\b\33[P");
com_buflen--;
for (uint8_t i = --com_bufpos; i < com_buflen; i++)
com_buf[i] = com_buf[i + 1];
}

static void com_line_insert(char ch)
{
if (ch < 32 || com_buflen >= com_bufsize - 1)
return;
for (size_t i = com_buflen; i > com_bufpos; i--)
com_buf[i] = com_buf[i - 1];
com_buflen++;
com_buf[com_bufpos] = ch;
for (size_t i = com_bufpos; i < com_buflen; i++)
putchar(com_buf[i]);
com_bufpos++;
if (com_buflen - com_bufpos)
printf("\33[%dD", com_buflen - com_bufpos);
}

static void com_line_state_C0(char ch)
{
if (ch == '\33')
com_ansi_state = ansi_state_Fe;
else if (ch == '\b' || ch == 127)
com_line_backspace();
else if (ch == 1) // ctrl-a
com_line_home();
else if (ch == 2) // ctrl-b
com_line_backward_1();
else if (ch == 5) // ctrl-e
com_line_end();
else if (ch == 6) // ctrl-f
com_line_forward_1();
else if (ch == '\r')
{
printf("\n");
Expand All @@ -139,64 +238,107 @@ static void com_line_state_C0(char ch)
com_callback = NULL;
cc(false, com_buf, com_buflen);
}
else if (ch >= 32 && com_bufpos < com_bufsize - 1)
{
putchar(ch);
com_buf[com_bufpos] = ch;
if (++com_bufpos > com_buflen)
com_buflen = com_bufpos;
}
else
com_line_insert(ch);
}

static void com_line_state_Fe(char ch)
{
if (ch == '[')
{
com_ansi_state = ansi_state_CSI;
com_ansi_param = -1;
com_csi_param_count = 0;
com_csi_param[0] = 0;
}
else if (ch == 'O')
else if (ch == 'b' || ch == 2)
{
com_ansi_state = ansi_state_SS3;
com_ansi_state = ansi_state_C0;
com_line_backward_word();
}
else if (ch == 'f' || ch == 6)
{
com_ansi_state = ansi_state_C0;
com_line_forward_word();
}
else if (ch == 'N')
com_ansi_state = ansi_state_SS2;
else if (ch == 'O')
com_ansi_state = ansi_state_SS3;
else
{
com_ansi_state = ansi_state_C0;
com_line_delete();
if (ch == 127)
com_line_delete();
}
}

static void com_line_state_SS2(char ch)
{
(void)ch;
com_ansi_state = ansi_state_C0;
}

static void com_line_state_SS3(char ch)
{
com_ansi_state = ansi_state_C0;
if (ch == 'F')
com_line_end();
else if (ch == 'H')
com_line_home();
}

static void com_line_state_CSI(char ch)
{
// Silently discard overflow parameters but still count to + 1.
if (ch >= '0' && ch <= '9')
{
if (com_ansi_param < 0)
{
com_ansi_param = ch - '0';
}
else
if (com_csi_param_count < COM_CSI_PARAM_MAX_LEN)
{
com_ansi_param *= 10;
com_ansi_param += ch - '0';
com_csi_param[com_csi_param_count] *= 10;
com_csi_param[com_csi_param_count] += ch - '0';
}
return;
}
if (ch == ';')
if (ch == ';' || ch == ':')
{
if (++com_csi_param_count < COM_CSI_PARAM_MAX_LEN)
com_csi_param[com_csi_param_count] = 0;
else
com_csi_param_count = COM_CSI_PARAM_MAX_LEN;
return;
}
com_ansi_state = ansi_state_C0;
if (com_ansi_param < 0)
com_ansi_param = -com_ansi_param;
if (++com_csi_param_count > COM_CSI_PARAM_MAX_LEN)
com_csi_param_count = COM_CSI_PARAM_MAX_LEN;
if (ch == 'C')
com_line_forward(com_ansi_param);
com_line_forward();
else if (ch == 'D')
com_line_backward(com_ansi_param);
else if (ch == '~' && com_ansi_param == 3)
com_line_delete();
com_line_backward();
else if (ch == 'F')
com_line_end();
else if (ch == 'H')
com_line_home();
else if (ch == 'b' || ch == 2)
com_line_backward_word();
else if (ch == 'f' || ch == 6)
com_line_forward_word();
else if (ch == '~')
switch (com_csi_param[0])
{
case 1:
case 7:
return com_line_home();
case 4:
case 8:
return com_line_end();
case 3:
return com_line_delete();
}
}

static void com_line_rx(uint8_t ch)
{
if (ch == ANSI_CANCEL)
if (ch == '\30')
com_ansi_state = ansi_state_C0;
else
switch (com_ansi_state)
Expand All @@ -207,9 +349,11 @@ static void com_line_rx(uint8_t ch)
case ansi_state_Fe:
com_line_state_Fe(ch);
break;
case ansi_state_SS2:
com_line_state_SS2(ch);
break;
case ansi_state_SS3:
// all SS3 is nop
com_ansi_state = ansi_state_C0;
com_line_state_SS3(ch);
break;
case ansi_state_CSI:
com_line_state_CSI(ch);
Expand Down
Loading

0 comments on commit f9651a0

Please sign in to comment.