+static
+void print_con_usage(char esc)
+{ printf_P(PSTR("\n"
+ "------------------------------------------------\n"
+ " ?,H - This Help\n"
+ " Q,X - Return to command line\n"
+ " R - Reset (Restart) CPU\n"
+ " : - Execute monitor command\n"
+ " \\ - code input:\n"
+ " \\nnn 3 decimal digits character code\n"
+ " \\Xhh 2 hexadecimal digits character code\n"
+ " ^%c - (Escape char) Type again to send itself\n"
+ "key>"
+ ), esc + 0x40);
+}
+
+command_ret_t do_console(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
+{
+ int ch;
+ uint8_t pending;
+// uint8_t help_prompt = 0;
+ uint8_t code = 0;
+ uint8_t state = 0;
+ char esc_char = (char) getenv_ulong(PSTR(ENV_ESC_CHAR), 16, CONFIG_ESC_CHAR);
+
+ (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+ printf_P(PSTR("Connecting to CPU. Escape character is '^%c'.\n"),
+ esc_char + 0x40);
+
+ while (1) {
+
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ pending = (Stat & S_CON_PENDING) != 0;
+ Stat &= ~S_CON_PENDING;
+ }
+ if (pending) {
+ uint8_t count = 100;
+ while ((ch = z80_memfifo_getc(fifo_conout)) >= 0 && --count)
+ putchar(ch);
+ }
+
+ if ((ch = my_getchar(0)) >= 0) {
+ switch (state) {
+ case 0:
+ if (ch == esc_char) {
+ state = 1;
+ /* TODO: Timer starten */
+ } else {
+ z80_memfifo_putc(fifo_conin, ch);
+ }
+ break;
+ case 2:
+ printf_P(PSTR("\n"
+ "------------------------------------------------\n"));
+ case 1:
+ state = 0;
+ switch (toupper(ch)) {
+
+ case '?':
+ case 'H':
+ print_con_usage(esc_char);
+ state = 2;
+ break;
+
+ case 'R':
+ reset_cpu(Restart);
+ break;
+
+ case 'X':
+ case 'Q':
+ printf_P(PSTR("\n"));
+ goto quit;
+ break;
+
+ case ':':
+ putchar('\n');
+ int cmdlen = cli_readline(PSTR(": "), 1);
+ if (cmdlen > 0)
+ run_command(console_buffer, 0);
+ break;
+
+ case '\\':
+ code = 0;
+ state = 3;
+ break;
+
+ default:
+ if (ch == esc_char)
+ z80_memfifo_putc(fifo_conin, ch);
+ break;
+ }
+ break;
+ case 3:
+ if (toupper(ch) == 'X') {
+ state = 6;
+ break;
+ }
+ /* fall thru */
+ case 4:
+ case 5:
+ if (isdigit(ch)) {
+ code = code * 10 + ch - '0';
+ state++;
+ } else {
+ if (state > 3)
+ z80_memfifo_putc(fifo_conin, code);
+ z80_memfifo_putc(fifo_conin, ch);
+ state = 0;
+ }
+ if (state > 5) {
+ z80_memfifo_putc(fifo_conin, code);
+ state = 0;
+ }
+ break;
+ case 6:
+ case 7:
+ if (isxdigit(ch)) {
+ ch = toupper(ch);
+ if (ch >= 'A')
+ ch -= 'A' - 10;
+ code = code * 16 + ch - '0';
+ state++;
+ }else {
+ if (state > 6)
+ z80_memfifo_putc(fifo_conin, code);
+ z80_memfifo_putc(fifo_conin, ch);
+ state = 0;
+ }
+ if (state > 7) {
+ z80_memfifo_putc(fifo_conin, code);
+ state = 0;
+ }
+ break;
+ }
+ }
+ }
+quit:
+ return CMD_RET_SUCCESS;
+}