summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/avigo.cpp
blob: 7488b8601002bf2bacc750e24d8c52e80f3278c0 (plain) (tree)
1
2
                   
                                               




































































                                                                                   
                
                           



                    






                                                          















                                                                                             
                                                        
            
                                                         
















                                                  













                                               

                                 




                      
 

                                



                                 
                                      
                                            
 










                                             


                                         
 
 



                                                                                                                              
 


                                                                                                                              
 
                                                                                                                         
 
 






                                                                                                                        



                                          
                            


















































                                                                      


                                                     





























                                                                       
                                                                    














                                                 
                                                                    








































                                                                                                            
                                                                                                 













                                                                                                         
                                                                      




                                                                                      
                                                                            























                                                                                       
                         





































































































                                                                                   
                                         






                                                  

                      







                                            



                                            






                                                                                                             
                                                                                           

                                                          

                                                                                                       
















































                                                                                    


                                                                                                                                                              


                                                 


                                                                                                                                                              


                                                 
                                                                                                                                                              


                                                 
                                                                                                                                                                                                     
                                                                                                                               
                                                                                                                                                                        


                                                                                              
                                                                                                                                                                                                                                        

                                               
                                                                                                                                                                                                                                        




                                          



                                                       



                                                                                                 
                                                               



                                       



                                                       



                                                                                       
                                                               



                                        



                                                       



                                                                                                           
                                                               



                                        



                                                       



                                                                                                           
                                                               



                                      



                                                      



                                                   
                                                               



                                      



                                                      



                                         
                                                               

  
                                   





                                                                    


             
                                                           
 
                        
 
                       

 
                                                          
 
                        
 
                       

 
                                                
 
                                                         
                                                












                                                                                             
                                                                                












                                                                       
                                                                                                                           

                                                  
                                                                               

                                            
                                                                                                      

                                                                                         

                                   
 
                                               

         
                                       







                                                                          

                                               
                                    


                                                                    
                                                          
 
                                                 


                                                                                      
                                                                         
 





                                                                               

                            






                                                                                      
 
                                                
 

                                                                        

                            
                                               
                                                                              

                             

                                                                          

                        


                                     

                          
                                                      
 

                                                                                                                                
 
                                                                                 

                                                                 
                                                                                                                   

                                                                   
                                                                                                                

                       
                                                                                                 
 







                                                                            
                                                         
                                               
                                               
                                             



                                                                                                                                
 
                                                         


                                                                                                                                    


                   
                                                         
                                               
                                               
                                             



                                                                                                                                
 
                                                         


                                                                                                                                   


                   
                                                         
                                               
                                               
                                             



                                                                                                                                
 
                                                         


                                                                                                                                   


                   
                                                         
                                               
                                               
                                             



                                                                                                                                
 
                                                         


                                                                                                                                    


                   
                                                         
                                               
                                               
                                             



                                                                                                                                

                                                         


                                                                                                                                    

       





                                                                                                                                                       
// license:GPL-2.0+
// copyright-holders:Kevin Thacker,Sandro Ronco
/******************************************************************************

        avigo.c

        TI "Avigo" PDA


        system driver

        Documentation:
                Hans B Pufal
                Avigo simulator


        MEMORY MAP:
            0x0000-0x03fff: flash 0 block 0
            0x4000-0x07fff: bank 1
            0x8000-0x0bfff: bank 2
            0xc000-0x0ffff: ram block 0

        Bankswitch:
            Bank 1 is controlled by ports 5 and 6, port 5 is the bank select
            and port 6 is the chip select, the known chip select are:
            - 0: flash 0
            - 1: RAM
            - 3: flash 1
            - 5: flash 2 (optional)
            - 6: VideoRAM
            - 7: flash 0

            Bank 2 have the same behavior but is controlled by ports 7 and 8

        Hardware:
            - Z80 CPU
            - 16c500c UART
            - amd29f080 flash-file memory x 3 (3mb)
            - 128k ram
            - stylus pen
            - touch-pad screen

        Flash:
            The following flash ID are checked by Avigo OS, if the returned
            ID is different the PDA doesn't boot.

            Maker ID    Device ID   Description
            0xb0        0x21        Sharp LH28F004
            0x89        0xa6        Sharp LH28F008
            0x89        0xaa        Sharp LH28F016
            0xb0        0x88        Sharp LH28F032
            0x01        0xa4        AMD AM29F040
            0x01        0xd5        AMD AM29F080
            0x01        0xad        AMD AM29F016

        TODO:
            - Found a better way to emulate the touchscreen panel out of the screen
              area (the six buttons at the bottom)
            - Alarm doesn't work
            - Serial communications and IR port.

            I don't have any documentation on the hardware, so a lot of this
            driver has been written using educated guesswork and a lot of help
            from an existing emulation written by Hans Pufal. Hans's emulator
            is also written from educated guesswork.

        MESS Driver by Kevin Thacker and Sandro Ronco

 ******************************************************************************/


#include "emu.h"
#include "includes/avigo.h"

#include "screen.h"
#include "speaker.h"

#include "avigo.lh"


#define AVIGO_LOG 0
#define LOG(x) do { if (AVIGO_LOG) logerror x; } while (0)


/*
    IRQ bits (port 3) ordered by priority:

    bit 7: power down request       high priority. When it occurs, clear this bit.
    bit 5: real time clock
    bit 3: uart int
    bit 6: pen int                  An interrupt when pen is pressed against screen.
    bit 4: 1 sec int                used for auto power off
    bit 2: synchronisation link interrupt???keyboard int            ;; check bit 5 of port 1,
    bit 1: ???      (cleared in nmi, and then set again)
    bit 0: not checked, probably unused
*/

void avigo_state::refresh_ints()
{
	if (m_irq!=0)
		m_maincpu->set_input_line(0, HOLD_LINE);
	else
		m_maincpu->set_input_line(0, CLEAR_LINE);
}

/* does not do anything yet */
WRITE_LINE_MEMBER( avigo_state::tc8521_alarm_int )
{
//#if 0
	m_irq &=~(1<<5);

	if (state)
	{
		m_irq |= (1<<5);
	}

	refresh_ints();
//#endif
}

WRITE_LINE_MEMBER( avigo_state::com_interrupt )
{
	LOG(("com int\r\n"));

	m_irq &= ~(1<<3);

	if (state)
	{
		m_irq |= (1<<3);
	}

	refresh_ints();
}

void avigo_state::machine_reset()
{
	m_irq = 0;
	m_bank1_l = 0;
	m_bank1_h = 0;
	m_bank2_l = 0;
	m_bank2_h = 0;

	m_bankdev1->set_bank(0);
	m_bankdev2->set_bank(0);
}

void avigo_state::machine_start()
{
	// bank3 always first ram bank
	membank("bank2")->set_base(m_nvram);

	m_warm_start = 1;

	// register for state saving
	save_item(NAME(m_key_line));
	save_item(NAME(m_irq));
	save_item(NAME(m_port2));
	save_item(NAME(m_bank2_l));
	save_item(NAME(m_bank2_h));
	save_item(NAME(m_bank1_l));
	save_item(NAME(m_bank1_h));
	save_item(NAME(m_ad_control_status));
	save_item(NAME(m_ad_value));
	save_item(NAME(m_screen_column));
	save_item(NAME(m_warm_start));
}

void avigo_state::avigo_banked_map(address_map &map)
{
	map(0x0000000, 0x00fffff).mirror(0x0300000).rw("flash0", FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
	map(0x0400000, 0x041ffff).mirror(0x03e0000).ram().share("nvram");

	map(0x0c00000, 0x0cfffff).mirror(0x0300000).rw(m_flash1, FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
	map(0x1400000, 0x14fffff).mirror(0x0300000).rw("flash2", FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
	map(0x1c00000, 0x1cfffff).mirror(0x0300000).rw("flash0", FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));

	map(0x1800000, 0x1803fff).mirror(0x03fc000).rw(FUNC(avigo_state::vid_memory_r), FUNC(avigo_state::vid_memory_w));
}

void avigo_state::avigo_mem(address_map &map)
{
	map(0x0000, 0x3fff).rw("flash0", FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
	map(0x4000, 0x7fff).rw(m_bankdev1, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
	map(0x8000, 0xbfff).rw(m_bankdev2, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
	map(0xc000, 0xffff).bankrw("bank2");
}


READ8_MEMBER(avigo_state::key_data_read_r)
{
	uint8_t data = 0x0f;

	if (!(m_key_line & 0x01))
	{
		data &= ioport("LINE0")->read();
	}

	if (!(m_key_line & 0x02))
	{
		data &= ioport("LINE1")->read();
	}

	if (!(m_key_line & 0x04))
	{
		data &= ioport("LINE2")->read();
	}

	/* bit 3 is cold/warm start */
	data &= ((m_warm_start<<3) ^ 0xff);

	/* if bit 5 is clear shows synchronisation logo! */
	data |= (1<<5);

	return data;
}


/* set key line(s) to read */
/* bit 0 set for line 0, bit 1 set for line 1, bit 2 set for line 2 */
WRITE8_MEMBER(avigo_state::set_key_line_w)
{
	/* 5, 101, read back 3 */
	m_key_line = data;

	m_warm_start = BIT(data, 3);
}

READ8_MEMBER(avigo_state::irq_r)
{
	return m_irq;
}

WRITE8_MEMBER(avigo_state::irq_w)
{
	m_irq &= data;

	refresh_ints();
}

WRITE8_MEMBER(avigo_state::port2_w)
{
	/*
	    bit 4     LCD backlight on/off
	    bit 5-6   source select for a/d converter
	*/

	if ((m_port2 ^ data) & 0x10)
		popmessage("Backlight %s", data & 0x10 ? "on" : "off");

	m_port2 = data;
}

READ8_MEMBER(avigo_state::bank1_r)
{
	return offset ? m_bank1_h: m_bank1_l;
}

READ8_MEMBER(avigo_state::bank2_r)
{
	return offset ? m_bank2_h: m_bank2_l;
}

WRITE8_MEMBER(avigo_state::bank1_w)
{
	if (offset)
	{
		LOG(("bank1 h w: %04x\n", data));
		m_bank1_h = data;
	}
	else
	{
		LOG(("bank1 l w: %04x\n", data));
		m_bank1_l = data & 0x3f;
	}

	m_bankdev1->set_bank(((m_bank1_h & 0x07) << 8) | m_bank1_l);
}

WRITE8_MEMBER(avigo_state::bank2_w)
{
	if (offset)
	{
		LOG(("bank2 h w: %04x\n", data));
		m_bank2_h = data;
	}
	else
	{
		LOG(("bank2 l w: %04x\n", data));
		m_bank2_l = data & 0x3f;
	}

	m_bankdev2->set_bank(((m_bank2_h & 0x07) << 8) | m_bank2_l);
}

READ8_MEMBER(avigo_state::ad_control_status_r)
{
	LOG(("avigo ad control read %02x\n", (int) m_ad_control_status));
	return m_ad_control_status;
}


WRITE8_MEMBER(avigo_state::ad_control_status_w)
{
	LOG(("avigo ad control w %02x\n",data));

	switch (m_port2 & 0x60)
	{
		case 0x20:
			// read main battery status valid range 0x000-0x3ff
			LOG(("a/d main battery status\n"));

			m_ad_value = 0x3ff;
			break;
		case 0x40:
			// read backup battery status valid range 0x000-0x3ff
			LOG(("a/d backup battery status\n"));

			m_ad_value = 0x3ff;
			break;
		case 0x60:
			if ((data & 0x070)==0x070)
			{
				/* bit 3 appears to select between 1 = x coord, 0 = y coord */
				/* when 6,5,4 = 1 */
				if ((data & 0x08)!=0)
				{
					LOG(("a/d select x coordinate\n"));
					LOG(("x coord: %d\n", ioport("POSX")->read()));

					/* on screen range 0x060->0x03a0 */
					if (ioport("LINE3")->read() & 0x01)
					{
						/* this might not be totally accurate because hitable screen
						area may include the border around the screen! */
						m_ad_value = ioport("POSX")->read();
					}
					else
					{
						m_ad_value = 0;
					}

					LOG(("ad value: %d\n",m_ad_value));

				}
				else
				{
					/* in the avigo rom, the y coordinate is inverted! */
					/* therefore a low value would be near the bottom of the display,
					and a high value at the top */

					/* total valid range 0x044->0x03a6 */
					/* 0x0350 is also checked */

					/* assumption 0x044->0x0350 is screen area and
					0x0350->0x03a6 is panel at bottom */

					LOG(("a/d select y coordinate\n"));
					LOG(("y coord: %d\n", ioport("POSY")->read()));

					if (ioport("LINE3")->read() & 0x01)
					{
						m_ad_value = ioport("POSY")->read();
					}
					else
					{
						m_ad_value = 0;
					}

					LOG(("ad value: %d\n",m_ad_value));
				}
			}
	}

	/* bit 0: 1 if a/d complete, 0 if a/d not complete */
	m_ad_control_status = data | 1;
}

READ8_MEMBER(avigo_state::ad_data_r)
{
	uint8_t data = 0;

	/* original */

	/* status AND   11110111 */
	/* status OR    01110000 -> C20F */

	switch (m_ad_control_status & 0x078)
	{
		/* x1110xxx */
		/* read upper 4 bits of 10 bit A/D number */
		case 0x060:
		case 0x070:
		case 0x078:
		{
			/* upper 4 bits of 10 bit A/D number in bits 7-4 of data */
			/* bit 0 must be 0, bit 1 must be 0 */
			/* bit 3 must be 1. bit 2 can have any value */

			LOG(("a/d read upper 4 bits\n"));
			data = ((m_ad_value>>6) & 0x0f)<<4;
			data |= 8;
		}
		break;

		/* x0111xxx */
		case 0x020:
		case 0x038:
		{
			/* lower 6 bits of 10-bit A/D number in bits 7-2 of data */
			/* bit 0 must be 1, bit 1 must be 0 */

			LOG(("a/d lower 6-bits\n"));
			data = ((m_ad_value & 0x03f)<<2);
			data |= 1;
		}
		break;

		default:
			break;
	}

	/* x coord? */
	/* wait for bit 0 of status to become 1 */
	/* read data -> d */


	/* C20f AND 10111111 */
	/* C20f OR  00001000 */
	/* x0111xxx */

	/* bit 1 must be 0, bit 0 must be 1 */
	/* read data -> e */

	/* upper 4 bits of d contain data */
	/* bits 0 and 1 do not contain data of e, but all other bits do */

	/* get bit 5 and 6 of d */
	/* and put into bit 0 and 1 of e */

	/* C20f OR  01000000 */
	/* x1111xxx */

	/* y coord? */
	/* bit 0 must be 0, bit 1 must be 0 */
	/* bit 3 must be 1. bit 2 can have any value */
	/* read data -> d */

	/* C20f AND  10111111 */
	/* x0111xxx */

	/* bit 1 must be 0, bit 0 must be 1 */
	/* read data -> e */


	/* original and 1111100 */
	/* original or  1111000 */
	/* 1111x00 */



	/* if fails! */
	/* original */
	/* AND 1001100 */
	/* OR  1001000 */
	/* 1001x00 */


	/* AND 1101100 */
	/* OR  1101000 */
	/* 1101x00 */

	/* 1111x00 */

	LOG(("avigo ad read %02x\n",data));

	return data;
}


WRITE8_MEMBER(avigo_state::speaker_w)
{
	/* Speaker output state */
	m_speaker->level_w(BIT(data, 3));
}


/* port 0x04:

  bit 7: ??? if set, does a write 0x00 to 0x02e */

	/* port 0x029:
	port 0x02e */
READ8_MEMBER(avigo_state::port_04_r)
{
	/* must be both 0 for it to boot! */
	return 0x0ff^((1<<7) | (1<<5));
}



void avigo_state::avigo_io(address_map &map)
{
	map.unmap_value_high();
	map.global_mask(0xff);
	map(0x001, 0x001).rw(FUNC(avigo_state::key_data_read_r), FUNC(avigo_state::set_key_line_w));
	map(0x002, 0x002).w(FUNC(avigo_state::port2_w));
	map(0x003, 0x003).rw(FUNC(avigo_state::irq_r), FUNC(avigo_state::irq_w));
	map(0x004, 0x004).r(FUNC(avigo_state::port_04_r));
	map(0x005, 0x006).rw(FUNC(avigo_state::bank1_r), FUNC(avigo_state::bank1_w));
	map(0x007, 0x008).rw(FUNC(avigo_state::bank2_r), FUNC(avigo_state::bank2_w));
	map(0x009, 0x009).rw(FUNC(avigo_state::ad_control_status_r), FUNC(avigo_state::ad_control_status_w));
	map(0x010, 0x01f).rw("rtc", FUNC(tc8521_device::read), FUNC(tc8521_device::write));
	map(0x028, 0x028).w(FUNC(avigo_state::speaker_w));
	map(0x02d, 0x02d).r(FUNC(avigo_state::ad_data_r));
	map(0x030, 0x037).rw(m_uart, FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w));
}


INPUT_CHANGED_MEMBER( avigo_state::pen_irq )
{
	LOG(("pen pressed interrupt\n"));

	// an irq is generated when the pen is pressed down on the screen
	// or lifted up from the screen
	m_irq |= (1<<6);

	refresh_ints();
}

INPUT_CHANGED_MEMBER( avigo_state::pen_move_irq )
{
	// an irq is generated when the pen is down on the screen and is being moved
	if (ioport("LINE3")->read() & 0x01)
	{
		LOG(("pen move interrupt\n"));
		m_irq |= (1<<6);

		refresh_ints();
	}
}

INPUT_CHANGED_MEMBER( avigo_state::kb_irq )
{
	LOG(("key pressed interrupt\n"));

	if (!newval)
	{
		m_irq |= (1<<2);

		refresh_ints();
	}
}

INPUT_CHANGED_MEMBER( avigo_state::power_down_irq )
{
	if(newval)
	{
		m_irq |= (1<<7);

		refresh_ints();
	}
}

static INPUT_PORTS_START(avigo)
	PORT_START("LINE0")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("PAGE UP")      PORT_CODE(KEYCODE_PGUP) PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("PAGE DOWN")    PORT_CODE(KEYCODE_PGDN) PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("LIGHT")        PORT_CODE(KEYCODE_L)    PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("LINE1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("TO DO")        PORT_CODE(KEYCODE_T)    PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("ADDRESS")      PORT_CODE(KEYCODE_A)    PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("SCHEDULE")     PORT_CODE(KEYCODE_S)    PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("LINE2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("MEMO")         PORT_CODE(KEYCODE_M)    PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, kb_irq, 0 )
	PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("LINE3")
	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Pen/Stylus pressed") PORT_CODE(KEYCODE_ENTER) PORT_CODE(MOUSECODE_BUTTON1)  PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, pen_irq, 0 )
	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("?? Causes a NMI") PORT_CODE(KEYCODE_W) PORT_CODE(JOYCODE_BUTTON2)
	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Power Down")       PORT_CODE(KEYCODE_Q) PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, power_down_irq, 0 )

	/* these two ports are used to emulate the position of the pen/stylus on the screen */
	PORT_START("POSX") /* Mouse - X AXIS */
	PORT_BIT(0x3ff, 0x060, IPT_LIGHTGUN_X) PORT_SENSITIVITY(100) PORT_CROSSHAIR(X, 1, 0, 0) PORT_MINMAX(0x060, 0x3a0) PORT_KEYDELTA(10) PORT_PLAYER(1)              PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, pen_move_irq, 0 )

	PORT_START("POSY") /* Mouse - Y AXIS */
	PORT_BIT(0x3ff, 0x044, IPT_LIGHTGUN_Y) PORT_SENSITIVITY(100) PORT_CROSSHAIR(Y, 1, 0, 0) PORT_MINMAX(0x044, 0x3a6) PORT_INVERT PORT_KEYDELTA(10) PORT_PLAYER(1)  PORT_CHANGED_MEMBER( DEVICE_SELF, avigo_state, pen_move_irq, 0 )
INPUT_PORTS_END

/* F4 Character Displayer */
static const gfx_layout avigo_charlayout =
{
	8, 16,                  /* 8 x 16 characters */
	96,                 /* 96 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 0, 1, 2, 3, 4, 5, 6, 7 },
	/* y offsets */
	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
	8*16                    /* every char takes 16 bytes */
};

static const gfx_layout avigo_8_by_14 =
{
	8, 14,                  /* 8 x 16 characters */
	1024,                   /* 1024 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 0, 1, 2, 3, 4, 5, 6, 7 },
	/* y offsets */
	{ 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
	8*32                    /* every char takes 32 bytes */
};

static const gfx_layout avigo_16_by_15 =
{
	16, 15,                 /* 8 x 16 characters */
	1024,                   /* 1024 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
	/* y offsets */
	{ 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 },
	16*16                   /* every char takes 16 bytes */
};

static const gfx_layout avigo_15_by_16 =
{
	15, 16,                 /* 8 x 16 characters */
	1024,                   /* 1024 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 },
	/* y offsets */
	{ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
	16*16                   /* every char takes 16 bytes */
};

static const gfx_layout avigo_8_by_8 =
{
	8, 8,                   /* 8 x 8 characters */
	256,                    /* 256 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 0, 1, 2, 3, 4, 5, 6, 7 },
	/* y offsets */
	{ 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8 },
	16*16                   /* every char takes 16 bytes */
};

static const gfx_layout avigo_6_by_8 =
{
	6, 8,                   /* 6 x 8 characters */
	255,                    /* 255 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
	/* y offsets */
	{ 7, 6, 5, 4, 3, 2, 1, 0 },
	16*16                   /* every char takes 16 bytes */
};

static GFXDECODE_START( gfx_avigo )
	GFXDECODE_ENTRY( "flash0", 0x08992, avigo_charlayout, 0, 1 )
	GFXDECODE_ENTRY( "flash0", 0x0c020, avigo_8_by_14, 0, 1 )
	GFXDECODE_ENTRY( "flash0", 0x0c020, avigo_16_by_15, 0, 1 )
	GFXDECODE_ENTRY( "flash0", 0x14020, avigo_15_by_16, 0, 1 )
	GFXDECODE_ENTRY( "flash0", 0x1c020, avigo_8_by_8, 0, 1 )
	GFXDECODE_ENTRY( "flash0", 0x1e020, avigo_6_by_8, 0, 1 )
GFXDECODE_END


TIMER_DEVICE_CALLBACK_MEMBER(avigo_state::avigo_scan_timer)
{
	m_irq |= (1<<1);

	refresh_ints();
}

TIMER_DEVICE_CALLBACK_MEMBER(avigo_state::avigo_1hz_timer)
{
	m_irq |= (1<<4);

	refresh_ints();
}

QUICKLOAD_LOAD_MEMBER(avigo_state::quickload_cb)
{
	const char *systemname = machine().system().name;
	uint32_t first_app_page = (0x50000>>14);
	int app_page;

	// german and spanish language are 4 pages bigger than other
	if ( strcmp( systemname, "avigo_de" ) == 0 || strcmp( systemname, "avigo_es" ) == 0 )
		first_app_page += 4;

	// search the first empty page
	for (app_page = first_app_page + 1; app_page<0x40; app_page++)
	{
		bool empty_page = true;

		for (int offset=0; offset<0x4000; offset++)
		{
			if (m_flash1->read_raw((app_page<<14) + offset) != 0xff)
			{
				empty_page = false;
				break;
			}
		}

		if (empty_page)
			break;
	}

	// if there is the required free space installs the application
	if ((app_page + (image.length()>>14)) < 0x40)
	{
		logerror("Application loaded at 0x%05x-0x%05x\n", app_page<<14, (app_page<<14) + (uint32_t)image.length());

		// copy app file into flash memory
		image.fread(m_flash1->base() + (app_page<<14), image.length());

		// update the application ID
		m_flash1->write_raw((app_page<<14) + 0x1a5, 0x80 + (app_page - (first_app_page>>14)));

		// reset the CPU for allow at the Avigo OS to recognize the installed app
		m_warm_start = 1;
		m_maincpu->reset();

		return image_init_result::PASS;
	}

	return image_init_result::FAIL;
}

void avigo_state::nvram_init(nvram_device &nvram, void *base, size_t size)
{
	m_warm_start = 0;
	memset(base, 0x00, size);
}

void avigo_state::avigo(machine_config &config)
{
	/* basic machine hardware */
	Z80(config, m_maincpu, 4000000);
	m_maincpu->set_addrmap(AS_PROGRAM, &avigo_state::avigo_mem);
	m_maincpu->set_addrmap(AS_IO, &avigo_state::avigo_io);
	config.set_maximum_quantum(attotime::from_hz(60));

	NS16550(config, m_uart, XTAL(1'843'200));
	m_uart->out_tx_callback().set(m_serport, FUNC(rs232_port_device::write_txd));
	m_uart->out_dtr_callback().set(m_serport, FUNC(rs232_port_device::write_dtr));
	m_uart->out_rts_callback().set(m_serport, FUNC(rs232_port_device::write_rts));
	m_uart->out_int_callback().set(FUNC(avigo_state::com_interrupt));

	RS232_PORT(config, m_serport, default_rs232_devices, nullptr);
	m_serport->rxd_handler().set(m_uart, FUNC(ins8250_uart_device::rx_w));
	m_serport->dcd_handler().set(m_uart, FUNC(ins8250_uart_device::dcd_w));
	m_serport->dsr_handler().set(m_uart, FUNC(ins8250_uart_device::dsr_w));
	m_serport->ri_handler().set(m_uart, FUNC(ins8250_uart_device::ri_w));
	m_serport->cts_handler().set(m_uart, FUNC(ins8250_uart_device::cts_w));

	/* video hardware */
	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
	screen.set_refresh_hz(50);
	screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
	screen.set_screen_update(FUNC(avigo_state::screen_update));
	screen.set_size(AVIGO_SCREEN_WIDTH, AVIGO_SCREEN_HEIGHT + AVIGO_PANEL_HEIGHT);
	screen.set_visarea_full();
	screen.set_palette(m_palette);

	config.set_default_layout(layout_avigo);

	GFXDECODE(config, "gfxdecode", m_palette, gfx_avigo);
	PALETTE(config, m_palette, palette_device::MONOCHROME_INVERTED);

	/* sound hardware */
	SPEAKER(config, "mono").front_center();
	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50);

	/* real time clock */
	tc8521_device &rtc(TC8521(config, "rtc", XTAL(32'768)));
	rtc.out_alarm_callback().set(FUNC(avigo_state::tc8521_alarm_int));

	/* flash ROMs */
	AMD_29F080(config, "flash0");
	AMD_29F080(config, "flash1");
	AMD_29F080(config, "flash2");

	/* internal ram */
	RAM(config, RAM_TAG).set_default_size("128K");

	ADDRESS_MAP_BANK(config, "bank0").set_map(&avigo_state::avigo_banked_map).set_options(ENDIANNESS_LITTLE, 8, 32, 0x4000);
	ADDRESS_MAP_BANK(config, "bank1").set_map(&avigo_state::avigo_banked_map).set_options(ENDIANNESS_LITTLE, 8, 32, 0x4000);

	NVRAM(config, "nvram").set_custom_handler(FUNC(avigo_state::nvram_init));

	// IRQ 1 is used for scan the pen and for cursor blinking
	TIMER(config, "scan_timer").configure_periodic(FUNC(avigo_state::avigo_scan_timer), attotime::from_hz(50));

	// IRQ 4 is generated every second, used for auto power off
	TIMER(config, "1hz_timer").configure_periodic(FUNC(avigo_state::avigo_1hz_timer), attotime::from_hz(1));

	/* quickload */
	QUICKLOAD(config, "quickload", "app").set_load_callback(FUNC(avigo_state::quickload_cb));
}


/***************************************************************************

  Game driver(s)

***************************************************************************/
ROM_START(avigo)
	ROM_REGION(0x100000, "flash0", ROMREGION_ERASEFF)
	ROM_SYSTEM_BIOS( 0, "v1004", "v1.004" )
	ROM_SYSTEM_BIOS( 1, "v1002", "v1.002" )
	ROM_SYSTEM_BIOS( 2, "v100", "v1.00" )

	ROMX_LOAD("os_1004.rom", 0x000000, 0x0100000, CRC(62acd55c) SHA1(b2be12f5cc1053b6026bff2a265146ba831a7ffa), ROM_BIOS(0))
	ROMX_LOAD("os_1002.rom", 0x000000, 0x0100000, CRC(484bb95c) SHA1(ddc28f22f8cbc99f60f91c58ee0e2d15170024fb), ROM_BIOS(1))
	ROMX_LOAD("os_100.rom", 0x000000, 0x0100000, CRC(13ea7b38) SHA1(85566ff142d86d504ac72613f169d8758e2daa09), ROM_BIOS(2))

	ROM_REGION(0x100000, "flash1", ROMREGION_ERASEFF)
	ROMX_LOAD("english_1004.rom", 0x000000, 0x050000, CRC(c9c3a225) SHA1(7939993a5615ca59ff2047e69b6d85122d437dca), ROM_BIOS(0))
	ROMX_LOAD("english_1002.rom", 0x000000, 0x050000, CRC(31cab0ac) SHA1(87d337830506a12514a4beb9a8502a0de94816f2), ROM_BIOS(1))
	ROMX_LOAD("english_100.rom",  0x000000, 0x050000, CRC(e2824b44) SHA1(3252454b05c3d3a4d7df1cb48dc3441ae82f2b1c), ROM_BIOS(2))
ROM_END

ROM_START(avigo_de)
	ROM_REGION(0x100000, "flash0", ROMREGION_ERASEFF)
	ROM_SYSTEM_BIOS( 0, "v1004", "v1.004" )
	ROM_SYSTEM_BIOS( 1, "v1002", "v1.002" )
	ROM_SYSTEM_BIOS( 2, "v100", "v1.00" )

	ROMX_LOAD("os_1004.rom", 0x000000, 0x0100000, CRC(62acd55c) SHA1(b2be12f5cc1053b6026bff2a265146ba831a7ffa), ROM_BIOS(0))
	ROMX_LOAD("os_1002.rom", 0x000000, 0x0100000, CRC(484bb95c) SHA1(ddc28f22f8cbc99f60f91c58ee0e2d15170024fb), ROM_BIOS(1))
	ROMX_LOAD("os_100.rom", 0x000000, 0x0100000, CRC(13ea7b38) SHA1(85566ff142d86d504ac72613f169d8758e2daa09), ROM_BIOS(2))

	ROM_REGION(0x100000, "flash1", ROMREGION_ERASEFF)
	ROMX_LOAD("german_1004.rom", 0x000000, 0x060000, CRC(0fa437b3) SHA1(e9352aa8fee6d93b898412bd129452b82baa9a21), ROM_BIOS(0))
	ROMX_LOAD("german_1002.rom", 0x000000, 0x060000, CRC(c6bf07ba) SHA1(d3185687aa510f6c3b3ab3baaabe7e8ce1a79e3b), ROM_BIOS(1))
	ROMX_LOAD("german_100.rom",  0x000000, 0x060000, CRC(117d9189) SHA1(7e959ab1381ba831821fcf87973b25d87f12d34e), ROM_BIOS(2))
ROM_END

ROM_START(avigo_fr)
	ROM_REGION(0x100000, "flash0", ROMREGION_ERASEFF)
	ROM_SYSTEM_BIOS( 0, "v1004", "v1.004" )
	ROM_SYSTEM_BIOS( 1, "v1002", "v1.002" )
	ROM_SYSTEM_BIOS( 2, "v100", "v1.00" )

	ROMX_LOAD("os_1004.rom", 0x000000, 0x0100000, CRC(62acd55c) SHA1(b2be12f5cc1053b6026bff2a265146ba831a7ffa), ROM_BIOS(0))
	ROMX_LOAD("os_1002.rom", 0x000000, 0x0100000, CRC(484bb95c) SHA1(ddc28f22f8cbc99f60f91c58ee0e2d15170024fb), ROM_BIOS(1))
	ROMX_LOAD("os_100.rom", 0x000000, 0x0100000, CRC(13ea7b38) SHA1(85566ff142d86d504ac72613f169d8758e2daa09), ROM_BIOS(2))

	ROM_REGION(0x100000, "flash1", ROMREGION_ERASEFF)
	ROMX_LOAD("french_1004.rom", 0x000000, 0x050000, CRC(5e4d90f7) SHA1(07df3af8a431ba65e079d6c987fb5d544f6541d8), ROM_BIOS(0))
	ROMX_LOAD("french_1002.rom", 0x000000, 0x050000,CRC(caa3eb91) SHA1(ab199986de301d933f069a5e1f5150967e1d7f59), ROM_BIOS(1))
	ROMX_LOAD("french_100.rom",  0x000000, 0x050000, CRC(fffa2345) SHA1(399447cede3cdd0be768952cb24f7e4431147e3d), ROM_BIOS(2))
ROM_END

ROM_START(avigo_es)
	ROM_REGION(0x100000, "flash0", ROMREGION_ERASEFF)
	ROM_SYSTEM_BIOS( 0, "v1004", "v1.004" )
	ROM_SYSTEM_BIOS( 1, "v1002", "v1.002" )
	ROM_SYSTEM_BIOS( 2, "v100", "v1.00" )

	ROMX_LOAD("os_1004.rom", 0x000000, 0x0100000, CRC(62acd55c) SHA1(b2be12f5cc1053b6026bff2a265146ba831a7ffa), ROM_BIOS(0))
	ROMX_LOAD("os_1002.rom", 0x000000, 0x0100000, CRC(484bb95c) SHA1(ddc28f22f8cbc99f60f91c58ee0e2d15170024fb), ROM_BIOS(1))
	ROMX_LOAD("os_100.rom", 0x000000, 0x0100000, CRC(13ea7b38) SHA1(85566ff142d86d504ac72613f169d8758e2daa09), ROM_BIOS(2))

	ROM_REGION(0x100000, "flash1", ROMREGION_ERASEFF)
	ROMX_LOAD("spanish_1004.rom", 0x000000, 0x060000, CRC(235a7f8d) SHA1(94da4ecafb54dcd5d80bc5063cb4024e66e6a21f), ROM_BIOS(0))
	ROMX_LOAD("spanish_1002.rom", 0x000000, 0x060000, CRC(a6e80cc4) SHA1(e741657558c11f7bce646ba3d7b5f845bfa275b7), ROM_BIOS(1))
	ROMX_LOAD("spanish_100.rom",  0x000000, 0x060000, CRC(953a5276) SHA1(b9ba1dbdc2127b1ef419c911ef66313024a7351a), ROM_BIOS(2))
ROM_END

ROM_START(avigo_it)
	ROM_REGION(0x100000, "flash0", ROMREGION_ERASEFF)
	ROM_SYSTEM_BIOS( 0, "v1004", "v1.004" )
	ROM_SYSTEM_BIOS( 1, "v1002", "v1.002" )
	ROM_SYSTEM_BIOS( 2, "v100", "v1.00" )

	ROMX_LOAD("os_1004.rom", 0x000000, 0x0100000, CRC(62acd55c) SHA1(b2be12f5cc1053b6026bff2a265146ba831a7ffa), ROM_BIOS(0))
	ROMX_LOAD("os_1002.rom", 0x000000, 0x0100000, CRC(484bb95c) SHA1(ddc28f22f8cbc99f60f91c58ee0e2d15170024fb), ROM_BIOS(1))
	ROMX_LOAD("os_100.rom", 0x000000, 0x0100000, CRC(13ea7b38) SHA1(85566ff142d86d504ac72613f169d8758e2daa09), ROM_BIOS(2))

	ROM_REGION(0x100000, "flash1", ROMREGION_ERASEFF)
	ROMX_LOAD("italian_1004.rom", 0x000000, 0x050000, CRC(fb7941ec) SHA1(230e8346a3b0da1ee24568ec090ce6860ebfe995), ROM_BIOS(0))
	ROMX_LOAD("italian_1002.rom", 0x000000, 0x050000, CRC(093bc032) SHA1(2c75d950d356a7fd1d058808e5f0be8e15b8ea2a), ROM_BIOS(1))
	ROMX_LOAD("italian_100.rom",  0x000000, 0x050000, CRC(de359218) SHA1(6185727aba8ffc98723f2df74dda388fd0d70cc9), ROM_BIOS(2))
ROM_END

//    YEAR  NAME      PARENT  COMPAT  MACHINE  INPUT  CLASS        INIT        COMPANY              FULLNAME                     FLAGS
COMP( 1997, avigo,    0,      0,      avigo,   avigo, avigo_state, empty_init, "Texas Instruments", "TI Avigo 10 PDA",           MACHINE_SUPPORTS_SAVE)
COMP( 1997, avigo_de, avigo,  0,      avigo,   avigo, avigo_state, empty_init, "Texas Instruments", "TI Avigo 10 PDA (German)",  MACHINE_SUPPORTS_SAVE)
COMP( 1997, avigo_fr, avigo,  0,      avigo,   avigo, avigo_state, empty_init, "Texas Instruments", "TI Avigo 10 PDA (French)",  MACHINE_SUPPORTS_SAVE)
COMP( 1997, avigo_es, avigo,  0,      avigo,   avigo, avigo_state, empty_init, "Texas Instruments", "TI Avigo 10 PDA (Spanish)", MACHINE_SUPPORTS_SAVE)
COMP( 1997, avigo_it, avigo,  0,      avigo,   avigo, avigo_state, empty_init, "Texas Instruments", "TI Avigo 10 PDA (Italian)", MACHINE_SUPPORTS_SAVE)