/**********************************************\
* LOW LEVEL ROUTINES FOR RAM AND IDE ACCESS    *
\**********************************************/

void init()
{
    asm clrf STATUS
    asm bsf	STATUS,RP0
    asm movlw	0x00
    asm movwf	TRISA
    asm movwf	TRISB
    asm movwf	TRISD
    asm movwf	TRISE
    asm movlw	0x80
    asm movwf	TRISC
    asm clrf	STATUS
    asm movlw	0xF8
    asm movwf	PORTA
    asm movlw	0xFB
    asm movwf	PORTE
    while( ide_busy( 0x40, 0x40 ) != 0 );
    init_lcd();
}

void clear_ram( char ram_page )
{
    short addr, limit;
    
    asm movlw	0xFF
    asm movwf	_limit_clear_ram
    asm clrf	_addr_clear_ram
    asm movf	param00_clear_ram,W
    asm movwf	_limit_clear_ram+1
    asm movwf	_addr_clear_ram+1
    
    for( ; addr <= limit; addr++ )
    {

    	asm clrf	STATUS
    	asm bsf		STATUS,RP0
    	asm movlw	0x00
    	asm movwf	TRISB
    	asm movwf	TRISD
    	asm clrf	STATUS
    	asm movf	_addr_clear_ram,0
    	asm movwf	PORTB
    	asm movf	_addr_clear_ram+1,0
    	asm movwf	PORTD
    	asm movlw	0xFF
    	asm movwf	PORTE
    	asm movlw	0xFB
    	asm movwf	PORTE
    	asm movlw	0x00
    	asm movwf	PORTB
    	asm movwf	PORTD
    	asm movlw	0xF9
    	asm movwf	PORTE
    	asm movlw	0xFB
    	asm movwf	PORTE
    }
}

void write_ram( short addr, char dta8, char ram_page )
{
    char tmp8;
    short dta16;
    
    if( (addr % 2) == 1 )
    {
    tmp8 = read_ram( (addr-1), ram_page );
    }
    else
    {
    tmp8 = read_ram( (addr+1), ram_page );
    }
    
    dta16 = (addr / 2);
    asm movf	param02_write_ram,W
    asm movwf	_dta16_write_ram+1

    asm clrf	STATUS
    asm bsf	STATUS,RP0
    asm movlw	0x00
    asm movwf	TRISB
    asm movwf	TRISD
    asm clrf	STATUS
    asm movf	_dta16_write_ram,0
    asm movwf	PORTB
    asm movf	_dta16_write_ram+1,0
    asm movwf	PORTD
    asm movlw	0xFF
    asm movwf	PORTE
    asm movlw	0xFB
    asm movwf	PORTE
    if( (addr % 2) == 1 )
    {
    asm movf	_tmp8_write_ram,0
    asm movwf	PORTB
    asm movf	param01_write_ram,0
    asm movwf	PORTD
    }
    else
    {
    asm movf	param01_write_ram,0
    asm movwf	PORTB
    asm movf	_tmp8_write_ram,0
    asm movwf	PORTD
    }
    asm movlw	0xF9
    asm movwf	PORTE
    asm movlw	0xFB
    asm movwf	PORTE
}

char read_ram( short addr, char ram_page )
{
    char dta8;
    short dta16;
    
    dta16 = (addr / 2);
    asm movf	param01_read_ram,W
    asm movwf	_dta16_read_ram+1

    asm clrf	STATUS
    asm bsf	STATUS,RP0
    asm movlw	0x00
    asm movwf	TRISB
    asm movwf	TRISD
    asm clrf	STATUS
    asm movf	_dta16_read_ram,0
    asm movwf	PORTB
    asm movf	_dta16_read_ram+1,0
    asm movwf	PORTD
    asm movlw	0xFF
    asm movwf	PORTE
    asm movlw	0xFB
    asm movwf	PORTE
    asm clrf	STATUS
    asm bsf	STATUS,RP0
    asm movlw	0xFF
    asm movwf	TRISB
    asm movwf	TRISD
    asm clrf	STATUS
    asm movlw	0xFA
    asm movwf	PORTE
    asm nop
    asm nop
    if( (addr % 2) == 1 )
    {
    	asm movf	PORTD,0
    	asm movwf	_dta8_read_ram
    }
    else
    {
    	asm movf	PORTB,0
    	asm movwf	_dta8_read_ram
    }
    asm movlw	0xFB
    asm movwf	PORTE
    return dta8;
}

/******************************************************\
* LOW-LOW LEVEL ROUTINES - DO NOT call THESE DIRECTLY! *
\******************************************************/

void write_reg( char dta8, char reg )
{
    asm clrf	STATUS
    asm bsf	STATUS,RP0
    asm movlw	0x00
    asm movwf	TRISB
    asm movwf	TRISD
    asm clrf	STATUS
    asm movf	param00_write_reg,0
    asm movwf	PORTB
    asm movlw	0xF8
    asm iorwf	param01_write_reg,0
    asm movwf	PORTA
    asm andlw	0xEF
    asm movwf	PORTA
    asm xorlw	0x10
    asm movwf	PORTA
}

char ide_busy( char dta8, char mask )
{
    char sbyte = 0;
    char idx = 0;
    
    while ((sbyte != dta8) && (idx < 0xFF))
    {
    	asm clrf	STATUS
    	asm bsf		STATUS,RP0
    	asm movlw	0xFF
    	asm movwf	TRISB
	asm movwf	TRISD
	asm clrf	STATUS
	asm movlw	0xFF
	asm movwf	PORTA
	asm movlw	0xF7
	asm movwf	PORTA
	asm nop
	asm nop
	asm movf	PORTB,0
	asm andwf	param01_ide_busy,0
	asm movwf	_sbyte_ide_busy
	asm movlw	0xFF
	asm movwf	PORTA
	asm incf	_idx_ide_busy,1
    }
    if (sbyte == dta8)
    	return 0;
    else
    	return 1;
}

void get_ide( short lba1, short lba2, char ram_page )
{
    char dta8, retry = 1;
    while (retry !=0)
    {
    	write_reg( 0x01, 0x02 );

	asm movf	param00_get_ide,0
 	asm movwf	_dta8_get_ide
    	write_reg( dta8, 0x03 );

        asm movf	param00_get_ide+1,0
 	asm movwf	_dta8_get_ide
    	write_reg( dta8, 0x04 );
    	
        asm movf	param01_get_ide,0
	asm movwf	_dta8_get_ide
    	write_reg( dta8, 0x05 );
    	
	asm movf	param01_get_ide+1,0
	asm andlw	0x0F
	asm iorlw	0xE0
	asm movwf	_dta8_get_ide
    	write_reg( dta8, 0x06 );

    	write_reg( 0x20, 0x07 );

	retry = ide_busy( 0x48, 0xC8 );
    }
    read_sector( ram_page );
}

void get_info( char ram_page )
{
    char retry = 1;
    while (retry !=0)
    {
    	write_reg( 0xE0, 0x06 );
    	write_reg( 0xEC, 0x07 );
	retry = ide_busy( 0x48, 0xC8 );
    }
    read_sector( ram_page );
}

void read_sector( char ram_page )
{
    short addr,tempdta;
    asm clrf	_addr_read_sector
    asm	movlw	0xFF
    asm movwf	_tempdta_read_sector
    asm movf	param00_read_sector,0
    asm movwf	_addr_read_sector+1
    asm	movwf	_tempdta_read_sector+1

    while( addr <= tempdta )
    {
	asm clrf	STATUS
	asm bsf		STATUS,RP0
	asm movlw	0x00
	asm movwf	TRISB
	asm movwf	TRISD
	asm clrf	STATUS
	asm movf	_addr_read_sector,0
	asm movwf	PORTB
	asm movf	_addr_read_sector+1,0
	asm movwf	PORTD
	asm movlw	0xFF
	asm movwf	PORTE
	asm movlw	0xFB
	asm movwf	PORTE
	asm clrf	STATUS
	asm bsf		STATUS,RP0
	asm movlw	0xFF
	asm movwf	TRISB
	asm movwf	TRISD
	asm clrf	STATUS
	asm movlw	0xF8
	asm movwf	PORTA
	asm movlw	0xF0
	asm movwf	PORTA
	asm nop
	asm nop
	asm movlw	0xF9
	asm movwf	PORTE
	asm nop
	asm movlw	0xFB
	asm movwf	PORTE
	asm nop
	asm movlw	0xF8
	asm movwf	PORTA
	addr++;
    }
}

void put_ide( short lba1, short lba2, char ram_page )
{
    char dta8, retry = 1;
    short addr, tempdta;
    while (retry !=0)
    {
    	write_reg( 0x01, 0x02 );

	asm movf	param00_put_ide,0
 	asm movwf	_dta8_put_ide
    	write_reg( dta8, 0x03 );

        asm movf	param00_put_ide+1,0
 	asm movwf	_dta8_put_ide
    	write_reg( dta8, 0x04 );
    	
        asm movf	param01_put_ide,0
	asm movwf	_dta8_put_ide
    	write_reg( dta8, 0x05 );
    	
	asm movf	param01_put_ide+1,0
	asm andlw	0x0F
	asm iorlw	0xE0
	asm movwf	_dta8_put_ide
    	write_reg( dta8, 0x06 );

    	write_reg( 0x30, 0x07 );

	retry = ide_busy( 0x08, 0x88 );
    }
    asm clrf	_addr_put_ide
    asm	movlw	0xFF
    asm movwf	_tempdta_put_ide
    asm movf	param02_put_ide,0
    asm movwf	_addr_put_ide+1
    asm	movwf	_tempdta_put_ide+1

    while( addr <= tempdta )
    {
	asm clrf	STATUS
	asm bsf		STATUS,RP0
	asm movlw	0x00
	asm movwf	TRISB
	asm movwf	TRISD
	asm clrf	STATUS
	asm movf	_addr_put_ide,0
	asm movwf	PORTB
	asm movf	_addr_put_ide+1,0
	asm movwf	PORTD
	asm movlw	0xFF
	asm movwf	PORTE
	asm movlw	0xFB
	asm movwf	PORTE
	asm clrf	STATUS
	asm bsf		STATUS,RP0
	asm movlw	0xFF
	asm movwf	TRISB
	asm movwf	TRISD
	asm clrf	STATUS
	asm movlw	0xF8
	asm movwf	PORTA
	asm nop
	asm movlw	0xFA
	asm movwf	PORTE
	asm nop
	asm nop
	asm movlw	0xE8
	asm movwf	PORTA
	asm movlw	0xF8
	asm movwf	PORTA
	asm movlw	0xFB
	asm movwf	PORTE
	addr++;
    }
}