Skip to content

Commit

Permalink
Merge pull request #530 from monte-monte/master
Browse files Browse the repository at this point in the history
Add optional buffered input for terminal
  • Loading branch information
cnlohr authored Mar 5, 2025
2 parents 09098da + f7aa12b commit 3d5d3ee
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
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

0 comments on commit 3d5d3ee

Please sign in to comment.