diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2025-08-16 12:19:09 -0230 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2025-08-16 12:19:09 -0230 |
| commit | 4a99ede565fa61005f2a6202669adaa87a8ce0ee (patch) | |
| tree | 472d4e45858d50b4f719591dc3666b5fdc129549 /sw/eeprom.c | |
| parent | 31f8d3b1edbe9dd965dba663e40c62c336fe7ca9 (diff) | |
| download | can-gauge-interface-4a99ede565fa61005f2a6202669adaa87a8ce0ee.zip | |
spi and eeprom modules
Diffstat (limited to 'sw/eeprom.c')
| -rw-r--r-- | sw/eeprom.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/sw/eeprom.c b/sw/eeprom.c new file mode 100644 index 0000000..ce8aed7 --- /dev/null +++ b/sw/eeprom.c @@ -0,0 +1,123 @@ +#include <xc.h> + +#include <stdbool.h> +#include <stdint.h> + +#include "sys.h" +#include "types.h" +#include "spi.h" + +#include "eeprom.h" + +// 16-byte page ('C' variant) +#define PAGE_SIZE 16u + +// Commands +enum { + CMD_READ = 0x03, + CMD_WRITE = 0x02, + CMD_WRITE_DISABLE = 0x04, + CMD_WRITE_ENABLE = 0x06, + CMD_READ_STATUS = 0x05, + CMD_WRITE_STATUS = 0x01, +}; + +// Status register masks +enum { + STATUS_WIP = 0x1, // write in progress + STATUS_WEL = 0x2, // write enable latch + STATUS_BP0 = 0x4, // block protection 0 + STATUS_BP1 = 0x8, // block protection 1 +}; + +// Timing +enum { + TIME_WRITE_CYCLE_MS = 5, +}; + +void +eepromInit(void) { + EEPROM_CS_TRIS = OUT; + EEPROM_CS = 1; + + eepromWriteDisable(); +} + +void +eepromWriteEnable(void) { + EEPROM_CS = 0; + (void)spiTx(CMD_WRITE_ENABLE); + EEPROM_CS = 1; +} + +void +eepromWriteDisable(void) { + EEPROM_CS = 0; + (void)spiTx(CMD_WRITE_DISABLE); + EEPROM_CS = 1; +} + +static bool +isWriteInProgress(void) { + U8 status; + + EEPROM_CS = 0; + (void)spiTx(CMD_READ_STATUS); + status = spiTx(0x00); + EEPROM_CS = 1; + return status & STATUS_WIP; +} + +static void +spiTxAddr(U16 addr) { + (void)spiTx(addr.hi); + (void)spiTx(addr.lo); +} + +static bool +isPageStart(U16 addr) { + return (addr.lo % PAGE_SIZE) == 0; +} + +void +eepromWrite(U16 addr, U8 *data, U8 size) { + while (isWriteInProgress()) {} // wait for previous write to finish + + EEPROM_CS = 0; // pull chip-select low + + (void)spiTx(CMD_WRITE); + spiTxAddr(addr); + while (size--) { + (void)spiTx(*data); + data++; + incU16(&addr); + + // Check if write crosses page boundary + if (isPageStart(addr) && size) { + // Write current page to memory + EEPROM_CS = 1; + while (isWriteInProgress()) {} + EEPROM_CS = 0; + + // Start next page + (void)spiTx(CMD_WRITE); + spiTxAddr(addr); + } + } + + EEPROM_CS = 1; // release chip-select +} + +void +eepromRead(U16 addr, U8 *data, U8 size) { + EEPROM_CS = 0; // pull chip-select low + + (void)spiTx(CMD_READ); + spiTxAddr(addr); + while (size--) { + *data = spiTx(0x00); + data++; + } + + EEPROM_CS = 1; // release chip-select +} |