void generic_terminal_device::adm_term_write(uint8_t data)
{
// printf("data = %x %c\n",data,data < 127 && data > 32 ? data : '_');
/*
from https://retrocmp.de/kaypro/kay-p7_terminal.htm
Kaypro Terminal Emulation
The Kaypro's emulate the Lear-Seigler ADM-3A terminal.
CURSOR CONTROL
ring bell - 7 dec - 07H
cursor left - 8 dec - 08H
cursor right - 12 dec - 0CH
cursor down - 10 dec - 0AH
cursor up - 11 dec - 0BH
home cursor - 30 dec - 1EH
clear scr & home 26 dec - 1AH
carriage return 13 dec - 0DH
CURSOR POSITIONING
rows = 0 - 23 dec
columns = 0 - 79 dec
escape sequence = 27, 61 dec - 1BH, 3DH
constant offset = 20 dec - 14H
So in Mbasic to position the cursor at row 12, col 40
print chr$(27)chr$(61)chr$(20+12)chr$(20+40)
ESC = row col
LINE INSERT / DELETE
insert line - 27, 69 dec - 1BH, 45H { scroll down }
delete line - 27, 82 dec - 1BH, 52H { scroll up }
CLEAR TO END OF LINE / SCREEN
clear to EOL - 24 dec - 18H
clear to EOS - 23 dec - 17H
CHANGE CHARACTER SETS
set ASCII - 27,65 dec - 1BH,41H
set greek - 27,71 dec - 1BH,47H
*/
// check for ESC
// if (m_esc_counter) printf("esc_counter = %x\n",m_esc_counter);
if ((m_esc_counter == 0) && (data == 0x1b))
{
m_esc_buffer[m_esc_counter++] = data;
return;
}
else if ((m_esc_counter >= 1))
{
m_esc_buffer[m_esc_counter++] = data;
if (m_esc_buffer[1] == '=')
{
if (m_esc_counter > 3) // 3 characters for ESC =
{
if (m_esc_buffer[2] >= 32) m_y_pos = m_esc_buffer[2] - 32;
if (m_esc_buffer[3] >= 32) m_x_pos = m_esc_buffer[3] - 32;
if (m_y_pos > 23) m_y_pos = 23;
if (m_x_pos > 79) m_x_pos = 79;
m_esc_counter = 0;
return;
}
}
else if (m_esc_buffer[1] == 'B' || m_esc_buffer[1] == 'C') // attribute on/off
{
if (m_esc_counter > 2) // 2 characters for ESC B, ESC C
{
// just gobble the ESC B 0 or 1
m_esc_counter = 0;
return;
}
}
else
{
m_esc_counter = 0; // gobble the next character after ESC for undefined.
}
return;
}
if (data > 0x1f)
{
// printable char
if (data != 0x7f) write_char(data);
}
else
{
const uint16_t options = m_io_term_conf->read();
switch(data)
{
case 0x07: // bell
m_beeper->set_state(1);
m_bell_timer->reset(attotime::from_msec(250));
break;
case 0x08: // backspace CTRL+H = cursor move left
if (m_x_pos) m_x_pos--;
break;
case 0x09: // horizontal tab
m_x_pos = (std::min<uint8_t>)((m_x_pos & 0xf8) + 8, m_width - 1);
break;
case 0x0d: // carriage return
m_x_pos = 0;
if (!(options & 0x080)) break;
[[fallthrough]];
case 0x0a: // linefeed CTRL+J = cursor move down
m_y_pos++;
if (m_y_pos >= m_height)
{
scroll_line();
m_y_pos = m_height - 1;
}
if (options & 0x040) m_x_pos = 0;
break;
case 0x0b: // vertical tab CTRL+K = cursor move up
if (m_y_pos) m_y_pos--;
break;
case 0x0c: // form feed - CTRL+L = cursor move right
m_x_pos++;
if (m_x_pos >= m_width)
{
m_x_pos = 0;
m_y_pos++;
if (m_y_pos >= m_height)
{
scroll_line();
m_y_pos = m_height-1;
}
}
break;
// clear to EOL - 24 dec - 18H
// clear to EOS - 23 dec - 17H
case 0x17: // clear to eos
memset(m_buffer.get() + m_width * m_y_pos + m_x_pos, 0x20, (m_width * m_height) - (m_x_pos + m_width * m_y_pos));
break;
case 0x18: // clear to eol
memset(m_buffer.get() + m_width * m_y_pos + m_x_pos, 0x20, m_width - m_x_pos);
break;
case 0x1a: // CTRL+Z = clear screen
clear();
break;
case 0x1e: // record separator
m_x_pos = 0;
m_y_pos = 0;
break;
}
}
}