Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional buffered input for terminal #530

Merged
merged 5 commits into from
Mar 5, 2025
Merged
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
105 changes: 105 additions & 0 deletions minichlink/minichlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "../ch32fun/ch32fun.h"

#if defined(WINDOWS) || defined(WIN32) || defined(_WIN32)
extern int isatty(int);
#if !defined(_SYNCHAPI_H_) && !defined(__TINYC__)
void Sleep(uint32_t dwMilliseconds);
#endif
Expand Down Expand Up @@ -365,13 +366,83 @@ int main( int argc, char ** argv )

CaptureKeyboardInput();

#if TERMINAL_INPUT_BUFFER
char pline_buf[256]; // Buffer that contains current line that is being printed to
char input_buf[128]; // Buffer that contains user input until it is sent out
memset( pline_buf, 0, sizeof( pline_buf ) );
memset( input_buf, 0, sizeof( input_buf ) );
uint8_t input_pos = 0;
uint8_t to_send = 0;
uint8_t nice_terminal = isatty(1);
#endif
printf( "Terminal started\n\n" );
uint32_t appendword = 0;
do
{
uint8_t buffer[256];
#if TERMINAL_INPUT_BUFFER
char print_buf[TERMINAL_BUFFER_SIZE]; // Buffer that is filled with everything and will be written to stdout (basically it's for formatting)
uint8_t update = 0;
#endif
if( !IsGDBServerInShadowHaltState( dev ) )
{
// Handle keyboard input.
#if TERMINAL_INPUT_BUFFER
if ( nice_terminal > 0 )
{
if( IsKBHit() && to_send == 0 )
{
uint8_t c = ReadKBByte();
if ( c == 8 || c == 127 )
{
input_buf[input_pos - 1] = 0;
if ( input_pos > 0 ) input_pos--;
}
else if ( c > 31 && c < 127 )
{
input_buf[input_pos] = c;
input_pos++;
}
else if ( c == '\n' || c == 10 )
{
to_send = input_pos;
}
update = 1;
}
// Process incomming buffer during sending
if( to_send > 0 && appendword == 0 )
{
for( int i = 0; i < 3; i++ )
{
appendword |= input_buf[input_pos - to_send] << ( i * 8 + 8 );
to_send--;
if ( to_send == 0 ) break;
}
if( to_send == 0 )
{
snprintf(print_buf, TERMINAL_BUFFER_SIZE - 1, "%s%s%s\n%s%s", TERMINAL_CLEAR_CUR, TERMIANL_INPUT_SENT, input_buf, pline_buf, TERMINAL_SEND_LABEL);
fwrite( print_buf, strlen( print_buf ), 1, stdout );
fflush( stdout );
input_pos = 0;
memset( input_buf, 0, sizeof( input_buf ) );
}
appendword |= i + 4;
}
}
else
{
if( appendword == 0 )
{
int i;
for( i = 0; i < 3; i++ )
{
if( !IsKBHit() ) break;
appendword |= ReadKBByte() << (i*8+8);
}
appendword |= i+4; // Will go into DATA0.
}
}
#else
if( appendword == 0 )
{
int i;
Expand All @@ -382,7 +453,19 @@ int main( int argc, char ** argv )
}
appendword |= i+4; // Will go into DATA0.
}
#endif
int r = MCF.PollTerminal( dev, buffer, sizeof( buffer ), appendword, 0 );
#if TERMINAL_INPUT_BUFFER
if( (nice_terminal > 0) && ( r == -1 || r == 0 ) && update > 0 )
{
strncpy( print_buf, TERMINAL_CLEAR_CUR, TERMINAL_BUFFER_SIZE - 1 );
if ( to_send > 0 ) strncat( print_buf, TERMINAL_DIM, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) );
strncat( print_buf, TERMINAL_SEND_LABEL, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) );
strncat( print_buf, input_buf, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) );
fwrite( print_buf, strlen( print_buf ), 1, stdout );
fflush( stdout );
}
#endif
if( r < -5 )
{
fprintf( stderr, "Terminal dead. code %d\n", r );
Expand All @@ -395,7 +478,29 @@ int main( int argc, char ** argv )
}
else if( r > 0 )
{
#if TERMINAL_INPUT_BUFFER
if ( nice_terminal )
{
uint8_t new_line = 0;
if( buffer[r - 1] == '\n' ) new_line = 1;
if( new_line == 0 ) strncpy( print_buf, TERMINAL_CLEAR_PREV, TERMINAL_BUFFER_SIZE - 1 ); // Go one line up and erase it
else strncpy( print_buf, TERMINAL_CLEAR_CUR, TERMINAL_BUFFER_SIZE - 1 ); // Go to the start of the line and erase it
strncat( pline_buf, (char *)buffer, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) ); // Add newely received chars to line buffer
strncat( print_buf, pline_buf, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) ); // Add line to buffer
if( to_send > 0 ) strncat( print_buf, TERMINAL_DIM, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) );
strncat( print_buf, TERMINAL_SEND_LABEL, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) ); // Print styled "Send" label
strncat( print_buf, input_buf, TERMINAL_BUFFER_SIZE - 1 - strlen(print_buf) ); // Print current input
fwrite( print_buf, strlen( print_buf ), 1, stdout );
print_buf[0] = 0;
if( new_line == 1 ) pline_buf[0] = 0;
}
else
{
fwrite( buffer, r, 1, stdout );
}
#else
fwrite( buffer, r, 1, stdout );
#endif
fflush( stdout );
// Otherwise it's basically just an ack for appendword.
appendword = 0;
Expand Down
21 changes: 21 additions & 0 deletions minichlink/minichlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,27 @@ struct InternalState
#define DLLDECORATE
#endif

#ifndef TERMINAL_INPUT_BUFFER
#define TERMINAL_INPUT_BUFFER 0
#endif

#define TERMINAL_BUFFER_SIZE 512

#define STR_(x) #x
#define STR(x) STR_(x)

#ifndef TERMINAL_ACCENT_COLOR
#define TERMINAL_ACCENT_COLOR 5;208 // Chose color from predefined palette
// #define TERMINAL_ACCENT_COLOR 2;180;11;64 // Use R;G;B for color (can't be dimmed though)
#endif

#define TERMIANL_INPUT_SENT "\x1b[1F\x1b[2K\x1b[2K\033[38;" STR(TERMINAL_ACCENT_COLOR) "m> "
#define TERMINAL_SEND_LABEL "\n\x1b[2K\033[7m\033[1m\033[38;" STR(TERMINAL_ACCENT_COLOR) "mSend:\x1b[0m "
#define TERMINAL_SEND_BUSY "\n\x1b[2K\033[7m\033[1m\033[2m\033[38;" STR(TERMINAL_ACCENT_COLOR) "mSend:\x1b[0m "
#define TERMINAL_CLEAR_PREV "\x1b[1F\x1b[2K"
#define TERMINAL_CLEAR_CUR "\x1b[2K\x1b[F"
#define TERMINAL_DIM "\x1b[2m"

/* initialization hints for init functions */
/* could be expanded with more in the future (e.g., PID/VID hints, priorities, ...)*/
/* not all init functions currently need these hints. */
Expand Down
2 changes: 1 addition & 1 deletion minichlink/terminalhelp.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ static int ReadKBByte()

static void CtrlC()
{
fprintf( stderr, "Minichlink Closing\n" );
fprintf( stderr, "\nMinichlink Closing\n" );
ResetKeyboardInput();
exit( 0 );
}
Expand Down
Loading