summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/microtch.cpp
blob: 0cb51054aab54c99cb886d0e07b4e76a861e4605 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                       
  
                                      
 
                                 
 

                                   
                                                                                          


  
                

                     

                     
 

                                                                                         
 
                                                                                                                       


                                                                                                                                   
                                 
                              

                                   


                                          
 

 
                                                                                                          
 
                                                             


                                                                                                                








                         
                                                                            
 
                                              
                                             
                                                  
                                              
                                                         
                                             
                                                  
                                              

                                                         
 
                                                                










                           
                                              
                                       


                                                                  
                            
                                             
                                       


                                                                  
                     
                                              

 
                                           
 

                                  
 
                                       
                                                         


                                 
                                  

                                           
                                                                       

                                            
                                                                   



                                            


                                       


         
                                                                                                
 
                
         
                                                        
                 











                                                                          
                 
 


                                                               
                 
                               
                 
 





                                            
                 
                                                      
                         











                                                                                                   
                         

                 
 
 
                                      
 




























                                                                               







                                                              
 
 
 
                                      
 

                                                           




                                                                            
         
                            


                                                            
                                                                                              
                                                                          
                 
                                
                                                                          
                 
                                             
                 
                                                                               
                 
                                               
                 
                                                                               
                 
                                            
                 
                                                                              
                 

                                            
                 
                                                                               
                 
                                                 
                 
                                                                               
                 
                                                  
                 
                                                                              

                                                            








                                                              

                               

























                                                                                    
                                



                                                      
         
 
 
                                                
 
                                                 
         
                                    


         
                                    
                           
                                                                                                                                                      
                             
                                                                                                                        
                             


                                                                                                                        




                                                                
                                      



                                                         
                                      

                          
         

                                                  
         
 
// 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 "emu.h"
#include "microtch.h"

//#define VERBOSE 1
#include "logmacro.h"


DEFINE_DEVICE_TYPE(MICROTOUCH, microtouch_device, "microtouch", "Microtouch Touchscreen")

microtouch_device::microtouch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, MICROTOUCH, tag, owner, clock),
	device_serial_interface(mconfig, *this),
	m_rx_buffer_ptr(0), m_tx_buffer_num(0), m_tx_buffer_ptr(0), m_reset_done(0), m_format(0), m_mode(0), m_last_touch_state(0),
	m_last_x(0), m_last_y(0),
	m_out_stx_func(*this),
	m_touch(*this, "TOUCH"),
	m_touchx(*this, "TOUCH_X"),
	m_touchy(*this, "TOUCH_Y"),
	m_timer(nullptr),
	m_output_valid(false), m_output(0)
{
}

int microtouch_device::check_command( const char* commandtocheck, int command_len, uint8_t* 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_t 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)
	{
		if ( m_tx_buffer_ptr < m_tx_buffer_num )
		{
			if(is_transmit_register_empty())
			{
				m_output = m_tx_buffer[m_tx_buffer_ptr++];
				m_output_valid = true;
				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 (VERBOSE)
		{
			char command[16];
			memset(command, 0, sizeof(command));
			strncpy( command, (const char*)m_rx_buffer + 1, m_rx_buffer_ptr - 2 );
			LOG("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;
		}
		else if ( check_command("OS", m_rx_buffer_ptr, m_rx_buffer ) )
		{
			// output status
			m_tx_buffer[m_tx_buffer_num++] = 0x01;

			// ---- ---x    RAM error
			// ---- --x-    ROM error
			// ---- -x--    Analog-to-digital error
			// ---- x---    NOVRAM error
			// ---x ----    ASIC error
			// --x- ----    Power on flag
			// -x-- ----    Always 1
			// x--- ----    Always 0
			m_tx_buffer[m_tx_buffer_num++] = 0x40;

			// ---- ---x    Cable NOVRAM error
			// ---- --x-    Hard NOVRAM error
			// ---x xx--    Reserved
			// --x- ----    Software reset flag
			// -x-- ----    Always 1
			// x--- ----    Always 0
			m_tx_buffer[m_tx_buffer_num++] = 0x40 | (m_reset_done << 5);
			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, nullptr )
	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;
	}
}