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

	Amiga keyboard controller emulation

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

#include "mame.h"
#include "driver.h"
#include "amiga.h"
#include "amigakbd.h"
#include "machine/6526cia.h"

#define KEYBOARD_BUFFER_SIZE	256

static int	kbd_index[4] = { 0, 1, 2, 3 };
static UINT8 *key_buf = NULL;
static int key_buf_pos = 0;
static int key_cur_pos = 0;
static emu_timer *kbd_timer;

static void kbd_sendscancode( UINT8 scancode )
{
	int j;

	/* send over to the cia A */
	for( j = 0; j < 8; j++ )
	{
		cia_set_input_cnt( 0, 0 );	/* lower cnt */
		cia_set_input_sp( 0, ( scancode >> j ) & 1 ); /* set the serial data */
		cia_set_input_cnt( 0, 1 );	/* raise cnt */
	}
}

static TIMER_CALLBACK( kbd_update_callback )
{
	UINT8	scancode;

	(void)param;

	/* if we don't have pending data, bail */
	if ( key_buf_pos == key_cur_pos )
		return;

	/* fetch the next scan code and send it to the Amiga */
	scancode = key_buf[key_cur_pos++];
	key_cur_pos %= KEYBOARD_BUFFER_SIZE;
	kbd_sendscancode( scancode );

	/* if we still have more data, schedule another update */
	if ( key_buf_pos != key_cur_pos )
	{
		timer_adjust( kbd_timer, attotime_div(video_screen_get_frame_period(0),4), 0, attotime_zero);
	}
}

static void kbd_update( void *param, UINT32 oldvalue, UINT32 newvalue )
{
	int	index = *( (int*)(param) ), i;
	UINT32	delta = oldvalue ^ newvalue;

	/* Special case Page UP, which we will use as Action Replay button */
	if ( (index == 3) && ( delta & 0x80000000 ) && ( newvalue & 0x80000000 ) )
	{
		const amiga_machine_interface *amiga_intf = amiga_get_interface();

		if ( amiga_intf != NULL && amiga_intf->nmi_callback )
		{
			(*amiga_intf->nmi_callback)();
		}
	}
	else
	{
		int		key_buf_was_empty = ( key_buf_pos == key_cur_pos ) ? 1 : 0;

		for( i = 0; i < 32; i++ )
		{
			if ( delta & ( 1 << i ) )
			{
				int	down = ( newvalue & ( 1 << i ) ) ? 0 : 1;
				int	scancode = ( ( (index*32)+i ) << 1 ) | down;
				int amigacode = ~scancode;

				/* add the keycode to the buffer */
				key_buf[key_buf_pos++] = amigacode & 0xff;
				key_buf_pos %= KEYBOARD_BUFFER_SIZE;
			}
		}

		/* if the buffer was empty and we have new data, start a timer to send the keystrokes */
		if ( key_buf_was_empty && ( key_buf_pos != key_cur_pos ) )
		{
			timer_adjust( kbd_timer, attotime_div(video_screen_get_frame_period(0),4), 0, attotime_zero);
		}
	}
}

void amigakbd_init( void )
{
	/* register for changes on the keyboard ports */
	int 	i;

	for( i = 0; i < 4; i++ )
	{
		char	buf[64];

		sprintf( buf, "amiga_keyboard_%d", i );

		input_port_set_changed_callback( port_tag_to_index( buf ), 0xFFFFFFFF, kbd_update, &kbd_index[i] );
	}

	/* allocate a keyboard buffer */
	key_buf = auto_malloc( KEYBOARD_BUFFER_SIZE );
	key_buf_pos = 0;
	key_cur_pos = 0;
	kbd_timer = timer_alloc(kbd_update_callback, NULL);
	timer_reset( kbd_timer, attotime_never );
}

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

INPUT_PORTS_START( amiga_keyboard )
	PORT_START_TAG("amiga_keyboard_0")
	PORT_BIT( 0x00000001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE)		// 00
	PORT_BIT( 0x00000002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_1)		// 01
	PORT_BIT( 0x00000004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)		// 02
	PORT_BIT( 0x00000008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_3)		// 03
	PORT_BIT( 0x00000010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_4)		// 04
	PORT_BIT( 0x00000020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_5)		// 05
	PORT_BIT( 0x00000040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_6)		// 06
	PORT_BIT( 0x00000080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_7)		// 07
	PORT_BIT( 0x00000100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_8)		// 08
	PORT_BIT( 0x00000200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_9)		// 09
	PORT_BIT( 0x00000400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_0)		// 0A
	PORT_BIT( 0x00000800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS)		// 0B
	PORT_BIT( 0x00001000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS)		// 0C
	PORT_BIT( 0x00002000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH)	// 0D
	PORT_BIT( 0x00004000, 0x0000, IPT_UNUSED)					// 0E
	PORT_BIT( 0x00008000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD)		// 0F
	PORT_BIT( 0x00010000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q)		// 10
	PORT_BIT( 0x00020000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_W)		// 11
	PORT_BIT( 0x00040000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_E)		// 12
	PORT_BIT( 0x00080000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_R)		// 13
	PORT_BIT( 0x00100000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_T)		// 14
	PORT_BIT( 0x00200000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y)		// 15
	PORT_BIT( 0x00400000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_U)		// 16
	PORT_BIT( 0x00800000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_I)		// 17
	PORT_BIT( 0x01000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_O)		// 18
	PORT_BIT( 0x02000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_P)		// 19
	PORT_BIT( 0x04000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE)	// 1A
	PORT_BIT( 0x08000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE)	// 1B
	PORT_BIT( 0x10000000, 0x0000, IPT_UNUSED)					// 1C
	PORT_BIT( 0x20000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD)		// 1D
	PORT_BIT( 0x40000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD)		// 1E
	PORT_BIT( 0x80000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD)		// 1F

	PORT_START_TAG("amiga_keyboard_1")
	PORT_BIT( 0x00000001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_A)		// 20
	PORT_BIT( 0x00000002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_S)		// 21
	PORT_BIT( 0x00000004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_D)		// 22
	PORT_BIT( 0x00000008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F)		// 23
	PORT_BIT( 0x00000010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_G)		// 24
	PORT_BIT( 0x00000020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_H)		// 25
	PORT_BIT( 0x00000040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_J)		// 26
	PORT_BIT( 0x00000080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_K)		// 27
	PORT_BIT( 0x00000100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_L)		// 28
	PORT_BIT( 0x00000200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON)		// 29
	PORT_BIT( 0x00000400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE)		// 2A
	PORT_BIT( 0x00000800, 0x0000, IPT_UNUSED)					// 2B
	PORT_BIT( 0x00001000, 0x0000, IPT_UNUSED)					// 2C
	PORT_BIT( 0x00002000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD)		// 2D
	PORT_BIT( 0x00004000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)		// 2E
	PORT_BIT( 0x00008000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)		// 2F
	PORT_BIT( 0x00010000, 0x0000, IPT_UNUSED)					// 30
	PORT_BIT( 0x00020000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z)		// 31
	PORT_BIT( 0x00040000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_X)		// 32
	PORT_BIT( 0x00080000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_C)		// 33
	PORT_BIT( 0x00100000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_V)		// 34
	PORT_BIT( 0x00200000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_B)		// 35
	PORT_BIT( 0x00400000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_N)		// 36
	PORT_BIT( 0x00800000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_M)		// 37
	PORT_BIT( 0x01000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA)		// 38
	PORT_BIT( 0x02000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP)		// 39
	PORT_BIT( 0x04000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH)		// 3A
	PORT_BIT( 0x08000000, 0x0000, IPT_UNUSED)					// 3B
	PORT_BIT( 0x10000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD)		// 3C
	PORT_BIT( 0x20000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD)		// 3D
	PORT_BIT( 0x40000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD)		// 3E
	PORT_BIT( 0x80000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD)		// 3F

	PORT_START_TAG("amiga_keyboard_2")
	PORT_BIT( 0x00000001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE)		// 40
	PORT_BIT( 0x00000002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE)	// 41
	PORT_BIT( 0x00000004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB)		// 42
	PORT_BIT( 0x00000008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD)	// 43
	PORT_BIT( 0x00000010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER)		// 44
	PORT_BIT( 0x00000020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC)		// 45
	PORT_BIT( 0x00000040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL)		// 46
	PORT_BIT( 0x00000080, 0x0000, IPT_UNUSED)					// 47
	PORT_BIT( 0x00000100, 0x0000, IPT_UNUSED)					// 48
	PORT_BIT( 0x00000200, 0x0000, IPT_UNUSED)					// 49
	PORT_BIT( 0x00000400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD)	// 4A
	PORT_BIT( 0x00000800, 0x0000, IPT_UNUSED)					// 4B
	PORT_BIT( 0x00001000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP)		// 4C
	PORT_BIT( 0x00002000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN)		// 4D
	PORT_BIT( 0x00004000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT)		// 4E
	PORT_BIT( 0x00008000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT)		// 4F
	PORT_BIT( 0x00010000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1)		// 50
	PORT_BIT( 0x00020000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2)		// 51
	PORT_BIT( 0x00040000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3)		// 52
	PORT_BIT( 0x00080000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4)		// 53
	PORT_BIT( 0x00100000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5)		// 54
	PORT_BIT( 0x00200000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6)		// 55
	PORT_BIT( 0x00400000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7)		// 56
	PORT_BIT( 0x00800000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8)		// 57
	PORT_BIT( 0x01000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9)		// 58
	PORT_BIT( 0x02000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10)		// 59
	PORT_BIT( 0x04000000, 0x0000, IPT_UNUSED)					// 5A
	PORT_BIT( 0x08000000, 0x0000, IPT_UNUSED)					// 5B
	PORT_BIT( 0x10000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD)	// 5C
	PORT_BIT( 0x20000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK)		// 5D
	PORT_BIT( 0x40000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD)		// 5E
	PORT_BIT( 0x80000000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT)		// 5F

	PORT_START_TAG("amiga_keyboard_3")
	PORT_BIT( 0x00000001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT)		// 60
	PORT_BIT( 0x00000002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT)		// 61
	PORT_BIT( 0x00000004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK)		// 62
	PORT_BIT( 0x00000008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL)		// 63
	PORT_BIT( 0x00000010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT)		// 64
	PORT_BIT( 0x00000020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_RALT)		// 65
	PORT_BIT( 0x00000040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LWIN)		// 66
	PORT_BIT( 0x00000080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_RWIN)		// 67
	PORT_BIT( 0x00000100, 0x0000, IPT_UNUSED)					// 68
	PORT_BIT( 0x00000200, 0x0000, IPT_UNUSED)					// 69
	PORT_BIT( 0x00000400, 0x0000, IPT_UNUSED)					// 6A
	PORT_BIT( 0x00000800, 0x0000, IPT_UNUSED)					// 6B
	PORT_BIT( 0x00001000, 0x0000, IPT_UNUSED)					// 6C
	PORT_BIT( 0x00002000, 0x0000, IPT_UNUSED) 					// 6D
	PORT_BIT( 0x00004000, 0x0000, IPT_UNUSED) 					// 6E
	PORT_BIT( 0x00008000, 0x0000, IPT_UNUSED) 					// 6F
	PORT_BIT( 0x00010000, 0x0000, IPT_UNUSED) 					// 70
	PORT_BIT( 0x00020000, 0x0000, IPT_UNUSED) 					// 71
	PORT_BIT( 0x00040000, 0x0000, IPT_UNUSED) 					// 72
	PORT_BIT( 0x00080000, 0x0000, IPT_UNUSED)					// 73
	PORT_BIT( 0x00100000, 0x0000, IPT_UNUSED) 					// 74
	PORT_BIT( 0x00200000, 0x0000, IPT_UNUSED) 					// 75
	PORT_BIT( 0x00400000, 0x0000, IPT_UNUSED) 					// 76
	PORT_BIT( 0x00800000, 0x0000, IPT_UNUSED) 					// 77
	PORT_BIT( 0x01000000, 0x0000, IPT_UNUSED) 					// 78
	PORT_BIT( 0x02000000, 0x0000, IPT_UNUSED) 					// 79
	PORT_BIT( 0x04000000, 0x0000, IPT_UNUSED)					// 7A
	PORT_BIT( 0x08000000, 0x0000, IPT_UNUSED)					// 7B
	PORT_BIT( 0x10000000, 0x0000, IPT_UNUSED)					// 7C
	PORT_BIT( 0x20000000, 0x0000, IPT_UNUSED)					// 7D
	PORT_BIT( 0x40000000, 0x0000, IPT_UNUSED)					// 7E
	PORT_BIT( 0x80000000, 0x0000, IPT_KEYBOARD)	PORT_CODE(KEYCODE_PGUP)		// 7F NMI button

INPUT_PORTS_END
