
#define		ctc_0		0x10
#define		ctc_1		0x11
#define		ctc_2		0x12
#define		ctc_3		0x13
#define		sio_a		0x18
#define		sio_b		0x1a
#define		pio_a		0x1c
#define		pio_b		0x1e

#define		rx_fifo		0x8000		/* MIDI Receive */
#define		tx_fifo		0x8800		/* MIDI Transmit */
#define		lcd_fifo	0x9000		/* LCD Display */
#define		rx_top		0x9100 + 2 * 0
#define		rx_end		0x9100 + 2 * 1
#define		tx_top		0x9100 + 2 * 2
#define		tx_end		0x9100 + 2 * 3
#define		timer_flag	0x9100 + 2 * 4
#define		lcd_top		0x9100 + 2 * 5
#define		lcd_end		0x9100 + 2 * 6
#define		lcd		0x9100 + 2 * 7
#define		work		0x9200		/* unversal use */

int	i,j,k,l,m,n;			/* universal for local use */
int	midi,rsb,dcb,channel,keyno;	/* universal MIDI parameter */

/*****  Common Functions  **********************************/

void port_out( int port, int data ){
#asm
	ld	hl,4
	add	hl,sp
	ld	c,(hl)
	ld	hl,2
	add	hl,sp
	ld	a,(hl)
	out	(c),a
	nop
	ret
#endasm
}

int port_in( int port ){
#asm
	ld	hl,2
	add	hl,sp
	ld	c,(hl)
	in	a,(c)
	ld	l,a
	ld	h,0
	ret
#endasm
}

void ram_put( int address, int data ){
#asm
	ld	hl,4
	add	hl,sp
	ld	c,(hl)
	inc	hl
	ld	b,(hl)
	ld	hl,2
	add	hl,sp
	ld	a,(hl)
	ld	(bc),a
#endasm
}

int ram_get( int address ){
#asm
	ld	hl,2
	add	hl,sp
	ld	c,(hl)
	inc	hl
	ld	b,(hl)
	ld	a,(bc)
	ld	l,a
	ld	h,0
	ret
#endasm
}

void enable_interrupt(){
#asm
	ei
#endasm
}

void disable_interrupt(){
#asm
	di
#endasm
}

char hex_conv( int data ){
	switch(data){
		case 0:	 return('0');
		case 1:	 return('1');
		case 2:	 return('2');
		case 3:	 return('3');
		case 4:	 return('4');
		case 5:	 return('5');
		case 6:	 return('6');
		case 7:	 return('7');
		case 8:	 return('8');
		case 9:	 return('9');
		case 10: return('A');
		case 11: return('B');
		case 12: return('C');
		case 13: return('D');
		case 14: return('E');
		case 15: return('F');
	}
}

/*****  I/O Setting Functions  *****************************/

void pio_a_setting( int bitmap ){
	port_out( pio_a+1, 0xcf );		/* Mode 3 */
	port_out( pio_a+1, bitmap );
}

void pio_b_setting( int bitmap ){ 
	port_out( pio_b+1, 0xcf );		/* Mode 3 */
	port_out( pio_b+1, bitmap );
}

void timer_0_setting(){
	port_out( ctc_0, 0x70 );		/* Interrupt Address */
	port_out( ctc_0, 0xa5 );		/* Timer Mode */
	port_out( ctc_0, 158);			/* about 10msec */
}

void sio_dummy_read(){
#asm
	in	a,(sio_a+0)
#endasm
}

void midi_port_setting(){
	port_out( sio_b+1, 0x18 );
	port_out( sio_b+1, 0x04 );
	port_out( sio_b+1, 0xc4 );
	port_out( sio_b+1, 0x01 );
	port_out( sio_b+1, 0x00 );
	port_out( sio_b+1, 0x05 );
	port_out( sio_b+1, 0x60 );
	port_out( sio_b+1, 0x02 );
	port_out( sio_b+1, 0x20 );
	port_out( sio_a+1, 0x18 );
	port_out( sio_a+1, 0x04 );
	port_out( sio_a+1, 0xc4 );
	port_out( sio_a+1, 0x01 );
	port_out( sio_a+1, 0x10 );
	port_out( sio_a+1, 0x05 );
	port_out( sio_a+1, 0x68 );
	port_out( sio_a+1, 0x03 );
	port_out( sio_a+1, 0xc1 );
}

/*****  MIDI Functions  ************************************/

void tx_midi_check(){
#asm
	ld	de,(tx_end)
	ld	hl,(tx_top)
	and	a
	sbc	hl,de
	ret	z
	xor	a
	out	(sio_a+1),a
	in	a,(sio_a+1)
	bit	2,a
	ret	z
	ld	a,10001000b
	or	d
	ld	h,a
	ld	l,e
	ld	a,(hl)
	out	(sio_a),a
	inc	de
	res	3,d
	ld	(tx_end),de
	ret
#endasm
}

void tx_midi_set(int data){
#asm
	ld	hl,2
	add	hl,sp
	ld	b,(hl)
	ld	de,(tx_top)
	ld	a,10001000b
	or	d
	ld	h,a
	ld	l,e
	ld	(hl),b
	inc	de
	res	3,d
	ld	(tx_top),de
	ret
#endasm
}

int rx_midi_check(){
#asm
	ld	de,(rx_end)
	ld	hl,(rx_top)
	and	a
	sbc	hl,de
	jr	nz,___non_event
	ld	h,10
	ret
___non_event:
	ld	a,10000000b
	or	d
	ld	h,a
	ld	l,e
	ld	b,(hl)
	inc	de
	res	3,d
	ld	(rx_end),de
	ld	l,b
	ld	h,0
	ret
#endasm
}

/*****  LCD Functions  *************************************/

//      This Library uses [PA0-PA7] port for LCD !
//
//	Connection Mapping :
//         ===== AKI-80 ===== LCD Module =====
//		  PA 7  ---------------------(LED on AKI-80)
//		     6  --  No. 9  E
//		     5  --     10  R/W
//		     4  --     11  RS
//		     3  --      1  DB7
//		     2  --      2  DB6
//		     1  --      3  DB5
//		  PA 0  --      4  DB4
//                 +5V  --     14  Vdd
//                 GND  --     13  Vss
//         contrast VR  --     12  Vo
//                (nc)  --      5  DB3
//                (nc)  --      6  DB2
//                (nc)  --      7  DB1
//                (nc)  --      8  DB0
//
//	Work Memory Assignment :
//		(lcd + 0) -- 8 bit data buffer to be transfered
//		(lcd + 1) -- bit 7 (MSB) only for LED

void wait_37usec(){
#asm
	db	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
#endasm
}

void wait_500usec(){
	for(j=0;j<15;j++) wait_37usec();
}

void lcd_command_set( int rs, int data ){
#asm
	ld	a,(lcd+1)
	ld	b,a
	ld	hl,4
	add	hl,sp
	ld	a,(hl)
	and	00000001b
	sla	a
	sla	a
	sla	a
	sla	a
	or	b
	ld	b,a
	ld	hl,2
	add	hl,sp
	ld	a,(hl)
	ld	(lcd+0),a
	srl	a
	srl	a
	srl	a
	srl	a
	or	b
	out	(pio_a),a
	set	6,a
	out	(pio_a),a
	nop
	res	6,a
	out	(pio_a),a
	ld	a,(lcd+0)
	and	00001111b
	or	b
	out	(pio_a),a
	set	6,a
	out	(pio_a),a
	nop
	res	6,a
	out	(pio_a),a
#endasm
	wait_37usec();
}

void lcd_module_setting(){
	pio_a_setting( 0x00 );			/* bit0-7 output */
	for(i=0;i<10;i++) wait_500usec();
	port_out( pio_a, 0x83 );		/* 10000011 */
	port_out( pio_a, 0xc3 );		/* 11000011 */
	port_out( pio_a, 0x83 );		/* 10000011 */
	for(i=0;i<10;i++) wait_500usec();
	port_out( pio_a, 0x83 );		/* 10000011 */
	port_out( pio_a, 0xc3 );		/* 11000011 */
	port_out( pio_a, 0x83 );		/* 10000011 */
	wait_500usec();
	port_out( pio_a, 0x83 );		/* 10000011 */
	port_out( pio_a, 0xc3 );		/* 11000011 */
	port_out( pio_a, 0x83 );		/* 10000011 */
	wait_37usec();
	port_out( pio_a, 0x82 );		/* 10000010 */
	port_out( pio_a, 0xc2 );		/* 11000010 */
	port_out( pio_a, 0x82 );		/* 10000010 */
	wait_37usec();
	lcd_command_set( 0, 0x28 );		/* function reset */
	lcd_command_set( 0, 0x08 );		/* display off */
	lcd_command_set( 0, 0x01 );		/* all clear */
	for(i=0;i<5;i++) wait_500usec();
	lcd_command_set( 0, 0x06 );		/* entry mode */
	lcd_command_set( 0, 0x0c );		/* display ON */
}

void lcd_fifo_set( int data ){
#asm
	ld	hl,2
	add	hl,sp
	ld	c,(hl)			; [C] = raw data
	ld	a,(lcd_top)
	ld	l,a
	ld	h,090h
	ld	(hl),c
	inc	l
	ld	a,l
	ld	(lcd_top),a
	ret
#endasm
}

void lcd_display( int address, int data ){
#asm
	ld	hl,4
	add	hl,sp
	ld	a,(hl)
	or	10000000b
	ld	b,a			; [B] = address
	ld	hl,2
	add	hl,sp
	ld	a,(hl)
	and	07fh
	ld	c,a			; [C] = data
	ld	a,(lcd_top)
	ld	l,a
	ld	h,090h
	ld	(hl),b
	inc	l
	ld	(hl),c
	inc	l
	ld	a,l
	ld	(lcd_top),a
	ret
#endasm
}

void disp_string( int address, char *s ){
	char a;
	lcd_fifo_set( 0x80+address );
	i = 0;
	while(1){
		a = s[i++];
		if( a==0 ) break;
		lcd_fifo_set( a & 0x7f );
	}
}

void disp_hex( int address, int data ){
	lcd_fifo_set( 0x80+address );
	lcd_fifo_set( hex_conv(data/16) );
	lcd_fifo_set( hex_conv(data%16) );
}

void lcd_disp_check(){
#asm
	ld	a,(lcd_end)
	ld	l,a
	ld	a,(lcd_top)
	cp	l
	ret	z
	ld	h,090h
	ld	a,(lcd+1)
	ld	b,a
	ld	a,(hl)
	xor	10000000b
	and	10000000b
	srl	a
	srl	a
	srl	a
	or	b
	ld	b,a
	ld	a,(hl)
	ld	(lcd+0),a
	srl	a
	srl	a
	srl	a
	srl	a
	or	b
	out	(pio_a),a
	set	6,a
	out	(pio_a),a
	nop
	res	6,a
	out	(pio_a),a
	ld	a,(lcd+0)
	and	00001111b
	or	b
	out	(pio_a),a
	set	6,a
	out	(pio_a),a
	nop
	res	6,a
	out	(pio_a),a
	inc	l
	ld	a,l
	ld	(lcd_end),a
	ret
#endasm
}

