/* 
 * File:   EEPROM.c
 * Author: mcgill
 * 
 * See https://stackoverflow.com/questions/26949500/trouble-reading-writing-internal-eeprom-pic24f16ka101
 *
 * Created on October 27, 2023, 3:09 PM
 */

#include "xc.h"
#include "EEPROM.h"

#define EXIT_SUCCESS 1

int __attribute__ ((space(eedata))) ee_addr;

void EepSetup() {
    // Disable Interrupts For 5 instructions
    asm volatile("disi #5");
    // Issue Unlock Sequence
    asm volatile(
    "mov #0x55, W0 \n"
    "mov W0, NVMKEY \n"
    "mov #0xAA, W1 \n"
    "mov W1, NVMKEY \n"
    );
} // end EepSetup()


void EepErase(void) {
    NVMCON = 0x4050;            // Set up NVMCON to bulk erase the data EEPROM
    asm volatile ("disi #5");   // Disable Interrupts For 5 Instructions
    __builtin_write_NVM();      // Issue Unlock Sequence and Start Erase Cycle
    while(_WR);                 // Wait until erase is done
} // end EepErase()


int EepRead(int index) {
    unsigned int offset;

    TBLPAG = __builtin_tblpage(&ee_addr);   // Initialize EE Data page pointer
    offset = __builtin_tbloffset(&ee_addr); // Initialize lower word of address
    offset += index * sizeof(int);
    return __builtin_tblrdl(offset);        // read EEPROM data
} // end EepRead()


int EepWrite(int index, int data) {
    unsigned int offset;
    
    NVMCON = 0x4004;    // Set up NVMCON to erase one word of data EEPROM
    TBLPAG = __builtin_tblpage(&ee_addr);    // Initialize EE Data page pointer
    offset = __builtin_tbloffset(&ee_addr);  // Initialize lower word of address
    offset += index * sizeof(int);
    __builtin_tblwtl(offset, data);
    asm volatile ("disi #5");   // Disable Interrupts For 5 Instructions
    __builtin_write_NVM();      // Issue Unlock Sequence and Start Erase Cycle
    while(_WR);                 // Wait until write is done
    return (EXIT_SUCCESS);
} // end EepWrite()
