{
*****************************************************************************
*  Name    : MemoryAccess.bas                                               *
*  Author  : Tim Box                                                        *
*  Notice  : Copyright (c) 2007 TJB Systems Ltd                             *
*          : All Rights Reserved                                            *
*  Date    : 03/08/2007                                                     *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
} 

Module MemoryAccess

// module option - just put some values in here for testing...
    #option ROM_BLOCK_SIZE = 8
    #if Not (ROM_BLOCK_SIZE in (8, 16, 32, 64))
      #error ROM_BLOCK_SIZE, "Invalid option. ROM_BLOCK_SIZE must be 8, 16 or whatever..."
    #endif

// bring option into the program...
    Const
        WriteBlockSize = ROM_BLOCK_SIZE // - 1

// some local aliases... 
    Dim
      EEPGD As EECON1.7,
      WR As EECON1.1,
      WREN As EECON1.2

// inline delay
    Inline Sub Delay()
      Asm
      GoTo $ + 2
      End Asm
    End Sub

// table read
    Inline Sub TableRead()
      Asm
      TBLRD*+
      End Asm
    End Sub

// table write
    Inline Sub TableWrite()
      Asm
      TBLWT*
      End Asm
    End Sub

// Functions =======================

// read a byte from ROM 
    Public Function ReadByte (pAddress As TABLEPTR) As TABLAT
      EECON1 = 0
      EEPGD = 1
      TableRead
    End Function

// read a Word from ROM 
    Public Function ReadWord (pAddress As TABLEPTR) As Word
      EECON1 = 0
      EEPGD = 1
      TableRead
      result.Byte0 = TABLAT
      TableRead
      result.Byte1 = TABLAT
    End Function

// read a LongWord from ROM 
    Public Function ReadLongWord (pAddress As TABLEPTR) As LongWord
      EECON1 = 0
      EEPGD = 1
      TableRead
      result.Byte0 = TABLAT
      TableRead
      result.Byte1 = TABLAT
      TableRead
      result.Byte2 = TABLAT
      TableRead
      result.Byte3 = TABLAT
    End Function

// Subroutines =======================

// erase ROM block...
    Public Sub EraseBlock (pAddress As TABLEPTR)
      EECON1 = $94
      EECON2 = $55
      EECON2 = $AA
      WR = 1
      Delay
      WREN = 0
    End Sub

// close a write
    Public Sub CloseWrite()
      EECON1 = $84
      EECON2 = $55
      EECON2 = $AA
      WR = 1
      Delay
      WREN = 0
    End Sub

{
****************************************************************************
* Name    : WriteItem                                                      *
* Purpose : Write a byte to program memory                                 *
****************************************************************************
}
    Public Sub WriteItem (pValue As TABLAT)
      TableWrite       
      If (TBLPTRL And (WriteBlockSize-1)) = (WriteBlockSize-1) Then
         CloseWrite
      EndIf
      Inc(TABLEPTR)
    End Sub

{
****************************************************************************
* Name    : WriteAt (OVERLOAD)                                             *
* Purpose : Write a Byte at an address from program memory                 *
****************************************************************************
}   
    Public Inline Sub WriteAt (pAddress As TABLEPTR, pValue As TABLAT)
      WriteItem(TABLAT)
    End Sub

{
****************************************************************************
* Name    : WriteAt (OVERLOAD)                                             *
* Purpose : Write a Word at an address from Program memory                 *
****************************************************************************
}   
    Public Sub WriteAt (pAddress As TABLEPTR, pValue As Word)     
      WriteItem(pValue.byte0)
      WriteItem(pValue.byte1)
    End Sub

{
****************************************************************************
* Name    : WriteAt (OVERLOAD)                                             *
* Purpose : Write a LongWord at an address from Program memory             *
****************************************************************************
}
    Public Sub WriteAt (pAddress As TABLEPTR, pValue As LongWord)
      WriteItem(pValue.byte0)
      WriteItem(pValue.byte1)
      WriteItem(pValue.byte2)
      WriteItem(pValue.byte3)
    End Sub 

End Module
