'---------------------------------------------------------------
' AT24C32 EEPROM Library for PIC18 Basic
' BY COS, 2024/10/07
' Description: This library handles communication with the AT24C32
'              EEPROM module using PIC18 via the I2C protocol.
'              It includes functions to read, write, and manage the
'              EEPROM memory.
'---------------------------------------------------------------

' I2C address of the AT24C32 EEPROM (0x50 is the base address).
Const AT24C32_ADDR = 0x50
Const DLY_WR_I2C = 2 'mSec, EEPROM requires a write cycle delay.
'---------------------------------------------------------------
' Proc:        EEPROM_WriteByte
' Description: Writes a byte of data to a specific address in the EEPROM.
' Arguments:   address (Word) - The memory address (16 bits).
'              data (Byte) - The data byte to write.
' Returns:     None.
'---------------------------------------------------------------
Proc EEPROM_WriteByte(address As Word, data As Byte)
    Dim high_byte As Byte
    Dim low_byte As Byte
    high_byte = address >> 8  ' Extract the high byte of the address.
    low_byte = address & 0xFF  ' Extract the low byte of the address.

    Call Start_I2C()  ' Generate a start condition.
    Call Write_I2C(AT24C32_ADDR << 1)  ' Send the EEPROM address with the write bit (0).
    Call Write_I2C(high_byte)  ' Send the high byte of the memory address.
    Call Write_I2C(low_byte)  ' Send the low byte of the memory address.
    Call Write_I2C(data)  ' Send the data byte to write.
    Call Stop_I2C()  ' Generate a stop condition.

    ' EEPROM requires a write cycle delay (5ms typical) for the data to be written.
    WaitMs DLY_WR_I2C
End Proc
'---------------------------------------------------------------
' Function:    EEPROM_ReadByte
' Description: Reads a byte of data from a specific address in the EEPROM.
' Arguments:   address (Word) - The memory address (16 bits).
' Returns:     The byte of data read from the EEPROM.
'---------------------------------------------------------------
Function EEPROM_ReadByte(address As Word) As Byte
    Dim high_byte As Byte
    Dim low_byte As Byte
    Dim data As Byte

    high_byte = address >> 8  ' Extract the high byte of the address.
    low_byte = address & 0xFF  ' Extract the low byte of the address.

    Call Start_I2C()  ' Generate a start condition.
    Call Write_I2C(AT24C32_ADDR << 1)  ' Send the EEPROM address with the write bit (0).
    Call Write_I2C(high_byte)  ' Send the high byte of the memory address.
    Call Write_I2C(low_byte)  ' Send the low byte of the memory address.
    Call ReStart_I2C()  ' Generate a restart condition.
    Call Write_I2C((AT24C32_ADDR  << 1) | 1)  ' Send the EEPROM address with the read bit (1).
    data = Read_I2C(1)  ' Read the data and send NACK.
    Call Stop_I2C()  ' Generate a stop condition.

    ReturnValue data  ' Return the read data byte.
End Function
'---------------------------------------------------------------
' Proc:        EEPROM_WritePage
' Description: Writes a page (up to 32 bytes) of data to the EEPROM.
' Arguments:   address (Word) - The memory address (16 bits).
'              dataArray() (Byte array) - Array of data to write.
'              length (Byte) - Number of bytes to write (up to 32).
' Returns:     None.
'---------------------------------------------------------------
Proc EEPROM_WritePage(address As Word, p_dataArray As Word, length As Byte)
    Dim high_byte As Byte
    Dim low_byte As Byte
    Dim i As Byte

    If length > 32 Then length = 32  ' Ensure we don't exceed the page size.

    high_byte = address >> 8  ' Extract the high byte of the address.
    low_byte = address & 0xFF  ' Extract the low byte of the address.

    Call Start_I2C()  ' Generate a start condition.
    Call Write_I2C(AT24C32_ADDR << 1)  ' Send the EEPROM address with the write bit (0).
    Call Write_I2C(high_byte)  ' Send the high byte of the memory address.
    Call Write_I2C(low_byte)  ' Send the low byte of the memory address.

    ' Write the data bytes to the EEPROM.
    For i = 0 To length - 1
        Call Write_I2C(Pointer(p_dataArray  +i))  ' Send each byte in the array.
    Next i

    Call Stop_I2C()  ' Generate a stop condition.

    ' EEPROM requires a write cycle delay (5ms typical) for the data to be written.
    WaitMs DLY_WR_I2C
End Proc
'---------------------------------------------------------------
' Proc:        EEPROM_ReadSequential
' Description: Reads multiple bytes from the EEPROM starting from a specific address.
' Arguments:   address (Word) - The memory address (16 bits).
'              dataArray() (Byte array) - Array to store the read data.
'              length (Byte) - Number of bytes to read.
' Returns:     None.
'---------------------------------------------------------------
Proc EEPROM_ReadSequential(address As Word, p_dataArray As Word, length As Byte)
    Dim high_byte As Byte
    Dim low_byte As Byte
    Dim i As Byte

    high_byte = address >> 8  ' Extract the high byte of the address.
    low_byte = address & 0xFF  ' Extract the low byte of the address.

    Call Start_I2C()  ' Generate a start condition.
    Call Write_I2C(AT24C32_ADDR << 1)  ' Send the EEPROM address with the write bit (0).
    Call Write_I2C(high_byte)  ' Send the high byte of the memory address.
    Call Write_I2C(low_byte)  ' Send the low byte of the memory address.
    Call ReStart_I2C()  ' Generate a restart condition.
    Call Write_I2C((AT24C32_ADDR << 1) | 1)  ' Send the EEPROM address with the read bit (1).

    ' Read the data bytes from the EEPROM.
    For i = 0 To length - 1
        If i = length - 1 Then
            Pointer(p_dataArray + i) = Read_I2C(1)  ' Send NACK after the last byte.
        Else
            Pointer(p_dataArray + i) = Read_I2C(0)  ' Send ACK after each byte.
        Endif
    Next i

    Call Stop_I2C()  ' Generate a stop condition.
End Proc
