diff options
Diffstat (limited to 'src/devices/machine/microtch.cpp')
-rw-r--r-- | src/devices/machine/microtch.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/src/devices/machine/microtch.cpp b/src/devices/machine/microtch.cpp new file mode 100644 index 00000000000..eee87447495 --- /dev/null +++ b/src/devices/machine/microtch.cpp @@ -0,0 +1,307 @@ +// license:BSD-3-Clause +// copyright-holders:Mariusz Wojcieszek +/* + Microtouch touch screen controller + + Written by Mariusz Wojcieszek + + Notes/ToDo: + - calibration mode (command CX) + - only tablet format and decimal format are supported for returning touch screen state + +*/ + +#include "microtch.h" + +#define LOG 0 + +const device_type MICROTOUCH = &device_creator<microtouch_device>; + +microtouch_device::microtouch_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, MICROTOUCH, "Microtouch Touchscreen", tag, owner, clock, "microtouch", __FILE__), + device_serial_interface(mconfig, *this), + m_out_stx_func(*this), + m_touch(*this, "TOUCH"), + m_touchx(*this, "TOUCH_X"), + m_touchy(*this, "TOUCH_Y") +{ +} + +int microtouch_device::check_command( const char* commandtocheck, int command_len, UINT8* command_data ) +{ + if ( (command_len == (strlen(commandtocheck) + 2)) && + (command_data[0] == 0x01) && + (strncmp(commandtocheck, (const char*)command_data + 1, strlen(commandtocheck)) == 0) && + (command_data[command_len-1] == 0x0d) ) + { + return 1; + } + else + { + return 0; + } +} + +void microtouch_device::send_format_table_packet(UINT8 flag, int x, int y) +{ + m_tx_buffer[m_tx_buffer_num++] = flag; + // lower byte (7bits) of x coordinate + m_tx_buffer[m_tx_buffer_num++] = x & 0x7f; + // higher byte (7bits) of x coordinate + m_tx_buffer[m_tx_buffer_num++] = (x >> 7) & 0x7f; + // lower byte (7bits) of y coordinate + m_tx_buffer[m_tx_buffer_num++] = y & 0x7f; + // higher byte (7bits) of y coordinate + m_tx_buffer[m_tx_buffer_num++] = (y >> 7) & 0x7f; +} + +void microtouch_device::send_format_decimal_packet(int x, int y) +{ + int decx, decy; + + decx = x / 16; + if ( decx > 999 ) + decx = 999; + decy = y / 16; + if ( decy > 999 ) + decy = 999; + + // header byte + m_tx_buffer[m_tx_buffer_num++] = 0x01; + // x coordinate in decimal mode + m_tx_buffer[m_tx_buffer_num++] = (decx / 100) + '0'; + m_tx_buffer[m_tx_buffer_num++] = ((decx / 10) % 10) + '0'; + m_tx_buffer[m_tx_buffer_num++] = (decx % 10) + '0'; + // comma (separator) + m_tx_buffer[m_tx_buffer_num++] = ','; + // y coordinate in decimal mode + m_tx_buffer[m_tx_buffer_num++] = (decy / 100) + '0'; + m_tx_buffer[m_tx_buffer_num++] = ((decy / 10) % 10) + '0'; + m_tx_buffer[m_tx_buffer_num++] = (decy % 10) + '0'; + // terminator + m_tx_buffer[m_tx_buffer_num++] = 0x0d; +} + +void microtouch_device::send_touch_packet() +{ + int tx = m_touchx->read(); + int ty = m_touchy->read(); + + if ( m_out_touch_cb.isnull() || + m_out_touch_cb( &tx, &ty ) != 0 ) + { + ty = 0x4000 - ty; + + switch( m_format ) + { + case FORMAT_TABLET: + send_format_table_packet(0xc8, tx, ty); + break; + case FORMAT_DECIMAL: + send_format_decimal_packet(tx, ty); + break; + case FORMAT_UNKNOWN: + break; + } + m_last_touch_state = 1; + m_last_x = tx; + m_last_y = ty; + } +} + +void microtouch_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if(id) + { + device_serial_interface::device_timer(timer, id, param, ptr); + return; + } + + if ( m_tx_buffer_ptr < m_tx_buffer_num ) + { + m_output = m_tx_buffer[m_tx_buffer_ptr++]; + m_output_valid = true; + if(is_transmit_register_empty()) + tra_complete(); + + if ( m_tx_buffer_ptr == m_tx_buffer_num ) + { + m_tx_buffer_ptr = m_tx_buffer_num = 0; + } + return; + } + + if ( (m_reset_done == 0) || + (m_format == FORMAT_UNKNOWN) || + (m_mode != MODE_STREAM)) + { + return; + } + + // send format tablet packet + if (m_touch->read()) + { + send_touch_packet(); + } + else + { + if ( m_last_touch_state == 1 ) + { + m_last_touch_state = 0; + switch( m_format ) + { + case FORMAT_TABLET: + send_format_table_packet(0x88, m_last_x, m_last_y); + break; + case FORMAT_DECIMAL: + send_format_decimal_packet(m_last_x, m_last_y); + break; + case FORMAT_UNKNOWN: + break; + } + } + } +} + +void microtouch_device::device_start() +{ + memset(m_rx_buffer, 0, sizeof(m_rx_buffer)); + memset(m_tx_buffer, 0, sizeof(m_tx_buffer)); + m_rx_buffer_ptr = 0; + m_tx_buffer_ptr = 0; + m_tx_buffer_num = 0; + m_reset_done = 0; + m_format = 0; + m_mode = 0; + m_last_x = 0; + m_last_y = 0; + m_last_touch_state = -1; + + m_timer = timer_alloc(); + m_timer->adjust(attotime::from_hz(167*5), 0, attotime::from_hz(167*5)); + + m_format = FORMAT_UNKNOWN; + m_mode = MODE_INACTIVE; + + save_item(NAME(m_reset_done)); + save_item(NAME(m_last_touch_state)); + save_item(NAME(m_last_x)); + save_item(NAME(m_last_y)); + save_item(NAME(m_rx_buffer)); + save_item(NAME(m_rx_buffer_ptr)); + save_item(NAME(m_tx_buffer)); + save_item(NAME(m_tx_buffer_num)); + save_item(NAME(m_tx_buffer_ptr)); + save_item(NAME(m_format)); + save_item(NAME(m_mode)); + set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1); //8N1? + set_tra_rate(clock()); + set_rcv_rate(clock()); + m_out_stx_func.resolve_safe(); + m_output_valid = false; + + save_item(NAME(m_output_valid)); + save_item(NAME(m_output)); +} + + +void microtouch_device::rcv_complete() +{ + receive_register_extract(); + m_rx_buffer[m_rx_buffer_ptr] = get_received_char(); + m_rx_buffer_ptr++; + if(m_rx_buffer_ptr == 16) + return; + + if (m_rx_buffer_ptr > 0 && (m_rx_buffer[m_rx_buffer_ptr-1] == 0x0d)) + { + if (LOG) + { + char command[16]; + memset(command, 0, sizeof(command)); + strncpy( command, (const char*)m_rx_buffer + 1, m_rx_buffer_ptr - 2 ); + logerror("Microtouch: received command %s\n", command); + } + // check command + if ( check_command( "MS", m_rx_buffer_ptr, m_rx_buffer ) ) + { + m_mode = MODE_STREAM; + } + else if ( check_command( "MI", m_rx_buffer_ptr, m_rx_buffer ) ) + { + m_mode = MODE_INACTIVE; + } + else if ( check_command( "MP", m_rx_buffer_ptr, m_rx_buffer ) ) + { + m_mode = MODE_POINT; + } + else if ( check_command( "R", m_rx_buffer_ptr, m_rx_buffer ) ) + { + m_tx_buffer_num = 0; + m_reset_done = 1; + } + else if ( check_command( "FT", m_rx_buffer_ptr, m_rx_buffer ) ) + { + m_format = FORMAT_TABLET; + } + else if ( check_command( "FD", m_rx_buffer_ptr, m_rx_buffer ) ) + { + m_format = FORMAT_DECIMAL; + } + else if ( check_command("OI", m_rx_buffer_ptr, m_rx_buffer ) ) + { + // output identity - SMT3, ver 01.00 + m_tx_buffer[m_tx_buffer_num++] = 0x01; + m_tx_buffer[m_tx_buffer_num++] = 'Q'; + m_tx_buffer[m_tx_buffer_num++] = '1'; + m_tx_buffer[m_tx_buffer_num++] = '0'; + m_tx_buffer[m_tx_buffer_num++] = '1'; + m_tx_buffer[m_tx_buffer_num++] = '0'; + m_tx_buffer[m_tx_buffer_num++] = '0'; + m_tx_buffer[m_tx_buffer_num++] = 0x0d; + m_rx_buffer_ptr = 0; + return; + } + // send response + m_tx_buffer[m_tx_buffer_num++] = 0x01; + m_tx_buffer[m_tx_buffer_num++] = 0x30; + m_tx_buffer[m_tx_buffer_num++] = 0x0d; + m_rx_buffer_ptr = 0; + } +} + +INPUT_CHANGED_MEMBER( microtouch_device::touch ) +{ + if ( newval && ( m_mode == MODE_POINT ) ) + { + send_touch_packet(); + } +} + +static INPUT_PORTS_START(microtouch) + PORT_START("TOUCH") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME( "Touch screen" ) PORT_CHANGED_MEMBER( DEVICE_SELF,microtouch_device, touch, 0 ) + PORT_START("TOUCH_X") + PORT_BIT( 0x3fff, 0x2000, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15) + PORT_START("TOUCH_Y") + PORT_BIT( 0x3fff, 0x2000, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15) +INPUT_PORTS_END + +ioport_constructor microtouch_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(microtouch); +} + +void microtouch_device::tra_callback() +{ + m_out_stx_func(transmit_register_get_data_bit()); +} + +void microtouch_device::tra_complete() +{ + if(m_output_valid) + { + transmit_register_setup(m_output); + m_output_valid = false; + } +} |