Because the EEPROM does not use the MCLR/VPP pin on the ICSP header, it is not necessary to connect the 13 volt power supply to the shield while programming EEPROM's. The following photo shows the above circuit made up on a breadboard and connected to the programmer via an ICSP cable:
The sketch treats the EEPROM as a collection of 16-bit words (LSB first) so as to be compatible with the word-oriented operation of ProgramPIC. This means that the input HEX file must contain an even number of bytes. Each 16-bit word from the HEX file is written to two consecutive 8-bit bytes in the EEPROM's address space. This is slightly different to the handling of data memory in PIC devices which reads 16-bit words from the HEX file but writes only the LSB to the PIC.
#include <avr/pgmspace.h>
#define PIN_MCLR A1 // MCLR - not used for EEPROM mode.
#define PIN_ACTIVITY A5 // LED that indicates read/write activity
#define PIN_VDD 2 // Controls the power to the PIC
#define PIN_CLOCK 4 // Clock pin
#define PIN_DATA 7 // Data pin
#define MCLR_RESET HIGH // PIN_MCLR state to reset the PIC
#define MCLR_VPP LOW // PIN_MCLR state to apply 13v to MCLR/VPP pin
#define DELAY_SETTLE 50 // Delay for lines to settle for power off/on
#define STATE_IDLE 0 // Idle, device is held in the reset state
#define STATE_PROGRAM 1 // Active, reading and writing memory
int state = STATE_IDLE;
#define BSEL_NONE 0
#define BSEL_8BIT_ADDR 1
#define BSEL_17BIT_ADDR 2
#define BSEL_17BIT_ADDR_ALT 3
const prog_char *eepromName;
unsigned long eepromSize;
unsigned long eepromEnd;
byte eepromI2CAddress;
byte eepromBlockSelectMode;
unsigned int eepromPageSize;
const char s_24lc00[] PROGMEM = "24lc00";
const char s_24lc01[] PROGMEM = "24lc01";
const char s_24lc014[] PROGMEM = "24lc014";
const char s_24lc02[] PROGMEM = "24lc02";
const char s_24lc024[] PROGMEM = "24lc024";
const char s_24lc025[] PROGMEM = "24lc025";
const char s_24lc04[] PROGMEM = "24lc04";
const char s_24lc08[] PROGMEM = "24lc08";
const char s_24lc16[] PROGMEM = "24lc16";
const char s_24lc32[] PROGMEM = "24lc32";
const char s_24lc64[] PROGMEM = "24lc64";
const char s_24lc128[] PROGMEM = "24lc128";
const char s_24lc256[] PROGMEM = "24lc256";
const char s_24lc512[] PROGMEM = "24lc512";
const char s_24lc1025[] PROGMEM = "24lc1025";
const char s_24lc1026[] PROGMEM = "24lc1026";
struct deviceInfo
{
const prog_char *name;
prog_uint32_t size;
prog_uint16_t pageSize;
prog_uint8_t address;
prog_uint8_t blockSelect;
};
struct deviceInfo const devices[] PROGMEM = {
{s_24lc00, 16UL, 1, 0xA0, BSEL_8BIT_ADDR},
{s_24lc01, 128UL, 8, 0xA0, BSEL_8BIT_ADDR},
{s_24lc014, 128UL, 16, 0xA0, BSEL_8BIT_ADDR},
{s_24lc02, 256UL, 8, 0xA0, BSEL_8BIT_ADDR},
{s_24lc024, 256UL, 16, 0xA0, BSEL_8BIT_ADDR},
{s_24lc025, 256UL, 16, 0xA0, BSEL_8BIT_ADDR},
{s_24lc04, 512UL, 16, 0xA0, BSEL_8BIT_ADDR},
{s_24lc08, 1024UL, 16, 0xA0, BSEL_8BIT_ADDR},
{s_24lc16, 2048UL, 16, 0xA0, BSEL_8BIT_ADDR},
{s_24lc32, 4096UL, 32, 0xA0, BSEL_NONE},
{s_24lc64, 8192UL, 32, 0xA0, BSEL_NONE},
{s_24lc128, 16384UL, 64, 0xA0, BSEL_NONE},
{s_24lc256, 32768UL, 64, 0xA0, BSEL_NONE},
{s_24lc512, 65536UL, 128, 0xA0, BSEL_NONE},
{s_24lc1025, 131072UL, 128, 0xA0, BSEL_17BIT_ADDR_ALT},
{s_24lc1026, 131072UL, 128, 0xA0, BSEL_17BIT_ADDR},
{0, 0, 0, 0, 0}
};
#define BINARY_TRANSFER_MAX 64
#define BUFFER_MAX (BINARY_TRANSFER_MAX + 1)
char buffer[BUFFER_MAX];
int buflen = 0;
unsigned long lastActive = 0;
void setup()
{
Serial.begin(9600);
setDefaultDeviceInfo();
pinMode(PIN_MCLR, OUTPUT);
pinMode(PIN_VDD, OUTPUT);
digitalWrite(PIN_MCLR, MCLR_RESET);
digitalWrite(PIN_VDD, LOW);
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
digitalWrite(PIN_CLOCK, HIGH);
digitalWrite(PIN_DATA, HIGH);
pinMode(PIN_ACTIVITY, OUTPUT);
digitalWrite(PIN_ACTIVITY, LOW);
}
void loop()
{
if (Serial.available()) {
int ch = Serial.read();
if (ch == 0x0A || ch == 0x0D) {
if (buflen > 0) {
buffer[buflen] = '\0';
buflen = 0;
digitalWrite(PIN_ACTIVITY, HIGH);
processCommand(buffer);
digitalWrite(PIN_ACTIVITY, LOW);
}
} else if (ch == 0x08) {
if (buflen > 0)
--buflen;
} else if (buflen < (BUFFER_MAX - 1)) {
if (ch >= 'a' && ch <= 'z')
buffer[buflen++] = ch - 'a' + 'A';
else
buffer[buflen++] = ch;
}
lastActive = millis();
} else if (state != STATE_IDLE) {
if ((millis() - lastActive) >= 2000)
exitProgramMode();
}
}
void printHex1(unsigned int value)
{
if (value >= 10)
Serial.print((char)('A' + value - 10));
else
Serial.print((char)('0' + value));
}
void printHex4(unsigned int word)
{
printHex1((word >> 12) & 0x0F);
printHex1((word >> 8) & 0x0F);
printHex1((word >> 4) & 0x0F);
printHex1(word & 0x0F);
}
void printHex8(unsigned long word)
{
unsigned int upper = (unsigned int)(word >> 16);
if (upper)
printHex4(upper);
printHex4((unsigned int)word);
}
void printProgString(const prog_char *str)
{
for (;;) {
char ch = (char)(pgm_read_byte(str));
if (ch == '\0')
break;
Serial.print(ch);
++str;
}
}
void cmdVersion(const char *args)
{
Serial.println("ProgramPIC 1.0");
}
void setDefaultDeviceInfo()
{
eepromName = s_24lc256;
eepromSize = 32768UL;
eepromEnd = (eepromSize / 2) - 1;
eepromI2CAddress = 0xA0;
eepromBlockSelectMode = BSEL_NONE;
eepromPageSize = 64;
}
void printDeviceInfo()
{
Serial.print("DeviceName: ");
printProgString(eepromName);
Serial.println();
Serial.print("DataRange: 0000-");
printHex8(eepromEnd);
Serial.println();
Serial.println("DataBits: 16");
}
void initDevice(const struct deviceInfo *dev)
{
eepromName = (const prog_char *)pgm_read_word(&(dev->name));
eepromSize = pgm_read_dword(&(dev->size));
eepromEnd = (eepromSize / 2) - 1;
eepromI2CAddress = pgm_read_byte(&(dev->address));
eepromBlockSelectMode = pgm_read_byte(&(dev->blockSelect));
eepromPageSize = pgm_read_word(&(dev->pageSize));
}
void cmdDevice(const char *args)
{
exitProgramMode();
setDefaultDeviceInfo();
if (!probeDevice()) {
Serial.println("ERROR");
return;
}
Serial.println("OK");
Serial.println("DeviceID: 0000");
printDeviceInfo();
Serial.println(".");
}
void cmdDevices(const char *args)
{
Serial.println("OK");
int index = 0;
for (;;) {
const prog_char *name = (const prog_char *)
(pgm_read_word(&(devices[index].name)));
if (!name)
break;
if (index > 0) {
Serial.print(',');
if ((index % 6) == 0)
Serial.println();
else
Serial.print(' ');
}
printProgString(name);
unsigned long size = pgm_read_dword(&(devices[index].size));
if (size == 32768UL)
Serial.print('*');
++index;
}
Serial.println();
Serial.println(".");
}
void cmdSetDevice(const char *args)
{
exitProgramMode();
int len = 0;
for (;;) {
char ch = args[len];
if (ch == '\0' || ch == ' ' || ch == '\t')
break;
++len;
}
int index = 0;
for (;;) {
const prog_char *name = (const prog_char *)
(pgm_read_word(&(devices[index].name)));
if (!name)
break;
if (matchString(name, args, len)) {
initDevice(&(devices[index]));
if (!probeDevice()) {
setDefaultDeviceInfo();
Serial.println("ERROR");
exitProgramMode();
return;
}
Serial.println("OK");
printDeviceInfo();
Serial.println(".");
return;
}
++index;
}
setDefaultDeviceInfo();
Serial.println("ERROR");
}
int parseHex(const char *args, unsigned long *value)
{
int size = 0;
*value = 0;
for (;;) {
char ch = *args;
if (ch >= '0' && ch <= '9')
*value = (*value << 4) | (ch - '0');
else if (ch >= 'A' && ch <= 'F')
*value = (*value << 4) | (ch - 'A' + 10);
else if (ch >= 'a' && ch <= 'f')
*value = (*value << 4) | (ch - 'a' + 10);
else
break;
++size;
++args;
}
if (*args != '\0' && *args != '-' && *args != ' ' && *args != '\t')
return 0;
return size;
}
bool parseRange(const char *args, unsigned long *start, unsigned long *end)
{
int size = parseHex(args, start);
if (!size)
return false;
args += size;
while (*args == ' ' || *args == '\t')
++args;
if (*args != '-') {
*end = *start;
return true;
}
++args;
while (*args == ' ' || *args == '\t')
++args;
if (!parseHex(args, end))
return false;
return *end >= *start;
}
bool parseCheckedRange(const char *args, unsigned long *start, unsigned long *end)
{
if (!parseRange(args, start, end))
return false;
if (*start <= eepromEnd) {
if (*end > eepromEnd)
return false;
} else {
return false;
}
return true;
}
void cmdRead(const char *args)
{
unsigned long start;
unsigned long end;
if (!parseCheckedRange(args, &start, &end)) {
Serial.println("ERROR");
return;
}
if (!startRead(start)) {
Serial.println("ERROR");
return;
}
Serial.println("OK");
int count = 0;
bool activity = true;
while (start <= end) {
unsigned int word = readWord(start == end);
if (count > 0) {
if ((count % 8) == 0)
Serial.println();
else
Serial.print(' ');
}
printHex4(word);
++start;
++count;
if ((count % 32) == 0) {
activity = !activity;
if (activity)
digitalWrite(PIN_ACTIVITY, HIGH);
else
digitalWrite(PIN_ACTIVITY, LOW);
}
}
Serial.println();
Serial.println(".");
}
void cmdReadBinary(const char *args)
{
unsigned long start;
unsigned long end;
if (!parseCheckedRange(args, &start, &end)) {
Serial.println("ERROR");
return;
}
if (!startRead(start)) {
Serial.println("ERROR");
return;
}
Serial.println("OK");
int count = 0;
bool activity = true;
size_t offset = 0;
while (start <= end) {
unsigned int word = readWord(start == end);
buffer[++offset] = (char)word;
buffer[++offset] = (char)(word >> 8);
if (offset >= BINARY_TRANSFER_MAX) {
buffer[0] = (char)offset;
Serial.write((const uint8_t *)buffer, offset + 1);
offset = 0;
}
++start;
++count;
if ((count % 64) == 0) {
activity = !activity;
if (activity)
digitalWrite(PIN_ACTIVITY, HIGH);
else
digitalWrite(PIN_ACTIVITY, LOW);
}
}
if (offset > 0) {
buffer[0] = (char)offset;
Serial.write((const uint8_t *)buffer, offset + 1);
}
Serial.write((uint8_t)0x00);
}
void cmdWrite(const char *args)
{
unsigned long addr;
unsigned long limit;
unsigned long value;
int size;
size = parseHex(args, &addr);
if (!size) {
Serial.println("ERROR");
return;
}
args += size;
if (addr <= eepromEnd) {
limit = eepromEnd;
} else {
Serial.println("ERROR");
return;
}
startWrite(addr);
int count = 0;
for (;;) {
while (*args == ' ' || *args == '\t')
++args;
if (*args == '\0')
break;
if (*args == '-') {
stopWrite();
Serial.println("ERROR");
return;
}
size = parseHex(args, &value);
if (!size) {
stopWrite();
Serial.println("ERROR");
return;
}
args += size;
if (addr > limit) {
stopWrite();
Serial.println("ERROR");
return;
}
if (!writeWord((unsigned int)value)) {
stopWrite();
Serial.println("ERROR");
return;
}
++addr;
++count;
}
stopWrite();
if (!count) {
Serial.println("ERROR");
} else {
Serial.println("OK");
}
}
int readBlocking()
{
while (!Serial.available())
;
return Serial.read();
}
void cmdWriteBinary(const char *args)
{
unsigned long addr;
unsigned long limit;
int size;
size = parseHex(args, &addr);
if (!size) {
Serial.println("ERROR");
return;
}
args += size;
if (addr <= eepromEnd) {
limit = eepromEnd;
} else {
Serial.println("ERROR");
return;
}
startWrite(addr);
Serial.println("OK");
int count = 0;
bool activity = true;
for (;;) {
int len = readBlocking();
while (len == 0x0A && count == 0) {
len = readBlocking();
}
if (!len)
break;
int offset = 0;
while (offset < len) {
if (offset < BINARY_TRANSFER_MAX) {
buffer[offset++] = (char)readBlocking();
} else {
readBlocking();
++offset;
}
}
for (int posn = 0; posn < (len - 1); posn += 2) {
if (addr > limit) {
stopWrite();
Serial.println("ERROR");
return;
}
unsigned int value =
(((unsigned int)buffer[posn]) & 0xFF) |
((((unsigned int)buffer[posn + 1]) & 0xFF) << 8);
if (!writeWord((unsigned int)value)) {
stopWrite();
Serial.println("ERROR");
return;
}
++addr;
++count;
if ((count % 24) == 0) {
activity = !activity;
if (activity)
digitalWrite(PIN_ACTIVITY, HIGH);
else
digitalWrite(PIN_ACTIVITY, LOW);
}
}
Serial.println("OK");
}
stopWrite();
Serial.println("OK");
}
void cmdErase(const char *args)
{
if (eraseAll())
Serial.println("OK");
else
Serial.println("ERROR");
}
void cmdPowerOff(const char *args)
{
exitProgramMode();
Serial.println("OK");
}
typedef void (*commandFunc)(const char *args);
typedef struct
{
const prog_char *name;
commandFunc func;
const prog_char *desc;
const prog_char *args;
} command_t;
const char s_cmdRead[] PROGMEM = "READ";
const char s_cmdReadDesc[] PROGMEM =
"Reads program and data words from device memory (text)";
const char s_cmdReadArgs[] PROGMEM = "STARTADDR[-ENDADDR]";
const char s_cmdReadBinary[] PROGMEM = "READBIN";
const char s_cmdReadBinaryDesc[] PROGMEM =
"Reads program and data words from device memory (binary)";
const char s_cmdWrite[] PROGMEM = "WRITE";
const char s_cmdWriteDesc[] PROGMEM =
"Writes program and data words to device memory (text)";
const char s_cmdWriteArgs[] PROGMEM = "STARTADDR WORD [WORD ...]";
const char s_cmdWriteBinary[] PROGMEM = "WRITEBIN";
const char s_cmdWriteBinaryDesc[] PROGMEM =
"Writes program and data words to device memory (binary)";
const char s_cmdWriteBinaryArgs[] PROGMEM = "STARTADDR";
const char s_cmdErase[] PROGMEM = "ERASE";
const char s_cmdEraseDesc[] PROGMEM =
"Erases the contents of program, configuration, and data memory";
const char s_cmdDevice[] PROGMEM = "DEVICE";
const char s_cmdDeviceDesc[] PROGMEM =
"Probes the device and returns information about it";
const char s_cmdDevices[] PROGMEM = "DEVICES";
const char s_cmdDevicesDesc[] PROGMEM =
"Returns a list of all supported device types";
const char s_cmdSetDevice[] PROGMEM = "SETDEVICE";
const char s_cmdSetDeviceDesc[] PROGMEM =
"Sets a specific device type manually";
const char s_cmdSetDeviceArgs[] PROGMEM = "DEVTYPE";
const char s_cmdPowerOff[] PROGMEM = "PWROFF";
const char s_cmdPowerOffDesc[] PROGMEM =
"Powers off the device in the programming socket";
const char s_cmdVersion[] PROGMEM = "PROGRAM_PIC_VERSION";
const char s_cmdVersionDesc[] PROGMEM =
"Prints the version of ProgramPIC";
const char s_cmdHelp[] PROGMEM = "HELP";
const char s_cmdHelpDesc[] PROGMEM =
"Prints this help message";
const command_t commands[] PROGMEM = {
{s_cmdRead, cmdRead, s_cmdReadDesc, s_cmdReadArgs},
{s_cmdReadBinary, cmdReadBinary, s_cmdReadBinaryDesc, s_cmdReadArgs},
{s_cmdWrite, cmdWrite, s_cmdWriteDesc, s_cmdWriteArgs},
{s_cmdWriteBinary, cmdWriteBinary, s_cmdWriteBinaryDesc, s_cmdWriteBinaryArgs},
{s_cmdErase, cmdErase, s_cmdEraseDesc, 0},
{s_cmdDevice, cmdDevice, s_cmdDeviceDesc, 0},
{s_cmdDevices, cmdDevices, s_cmdDevicesDesc, 0},
{s_cmdSetDevice, cmdSetDevice, s_cmdSetDeviceDesc, s_cmdSetDeviceArgs},
{s_cmdPowerOff, cmdPowerOff, s_cmdPowerOffDesc, 0},
{s_cmdVersion, cmdVersion, s_cmdVersionDesc, 0},
{s_cmdHelp, cmdHelp, s_cmdHelpDesc, 0},
{0, 0}
};
void cmdHelp(const char *args)
{
Serial.println("OK");
int index = 0;
for (;;) {
const prog_char *name = (const prog_char *)
(pgm_read_word(&(commands[index].name)));
if (!name)
break;
const prog_char *desc = (const prog_char *)
(pgm_read_word(&(commands[index].desc)));
const prog_char *args = (const prog_char *)
(pgm_read_word(&(commands[index].args)));
printProgString(name);
if (args) {
Serial.print(' ');
printProgString(args);
}
Serial.println();
Serial.print(" ");
printProgString(desc);
Serial.println();
++index;
}
Serial.println(".");
}
bool matchString(const prog_char *name, const char *str, int len)
{
for (;;) {
char ch1 = (char)(pgm_read_byte(name));
if (ch1 == '\0')
return len == 0;
else if (len == 0)
break;
if (ch1 >= 'a' && ch1 <= 'z')
ch1 = ch1 - 'a' + 'A';
char ch2 = *str;
if (ch2 >= 'a' && ch2 <= 'z')
ch2 = ch2 - 'a' + 'A';
if (ch1 != ch2)
break;
++name;
++str;
--len;
}
return false;
}
void processCommand(const char *buf)
{
while (*buf == ' ' || *buf == '\t')
++buf;
if (*buf == '\0')
return;
const char *cmd = buf;
int len = 0;
for (;;) {
char ch = *buf;
if (ch == '\0' || ch == ' ' || ch == '\t')
break;
++buf;
++len;
}
while (*buf == ' ' || *buf == '\t')
++buf;
int index = 0;
for (;;) {
const prog_char *name = (const prog_char *)
(pgm_read_word(&(commands[index].name)));
if (!name)
break;
if (matchString(name, cmd, len)) {
commandFunc func =
(commandFunc)(pgm_read_word(&(commands[index].func)));
(*func)(buf);
return;
}
++index;
}
Serial.println("NOTSUPPORTED");
}
void enterProgramMode()
{
if (state != STATE_IDLE)
return;
digitalWrite(PIN_VDD, LOW);
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
digitalWrite(PIN_CLOCK, HIGH);
digitalWrite(PIN_DATA, HIGH);
delayMicroseconds(DELAY_SETTLE);
digitalWrite(PIN_VDD, HIGH);
delayMicroseconds(DELAY_SETTLE);
state = STATE_PROGRAM;
}
void exitProgramMode()
{
if (state == STATE_IDLE)
return;
digitalWrite(PIN_VDD, LOW);
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
digitalWrite(PIN_CLOCK, HIGH);
digitalWrite(PIN_DATA, HIGH);
state = STATE_IDLE;
}
#define i2cDelay() delayMicroseconds(5)
bool started = false;
void i2cStart()
{
pinMode(PIN_DATA, OUTPUT);
if (started) {
digitalWrite(PIN_DATA, HIGH);
digitalWrite(PIN_CLOCK, HIGH);
i2cDelay();
}
digitalWrite(PIN_DATA, LOW);
i2cDelay();
digitalWrite(PIN_CLOCK, LOW);
i2cDelay();
started = true;
}
void i2cStop()
{
pinMode(PIN_DATA, OUTPUT);
digitalWrite(PIN_DATA, LOW);
digitalWrite(PIN_CLOCK, HIGH);
i2cDelay();
digitalWrite(PIN_DATA, HIGH);
i2cDelay();
started = false;
}
inline void i2cWriteBit(bool bit)
{
pinMode(PIN_DATA, OUTPUT);
if (bit)
digitalWrite(PIN_DATA, HIGH);
else
digitalWrite(PIN_DATA, LOW);
i2cDelay();
digitalWrite(PIN_CLOCK, HIGH);
i2cDelay();
digitalWrite(PIN_CLOCK, LOW);
i2cDelay();
}
inline bool i2cReadBit()
{
pinMode(PIN_DATA, INPUT);
digitalWrite(PIN_DATA, HIGH);
digitalWrite(PIN_CLOCK, HIGH);
bool bit = digitalRead(PIN_DATA);
i2cDelay();
digitalWrite(PIN_CLOCK, LOW);
i2cDelay();
return bit;
}
#define I2C_ACK false
#define I2C_NACK true
bool i2cWrite(byte value)
{
byte mask = 0x80;
while (mask != 0) {
i2cWriteBit((value & mask) != 0);
mask >>= 1;
}
return i2cReadBit();
}
byte i2cRead(bool nack)
{
byte value = 0;
for (byte bit = 0; bit < 8; ++bit)
value = (value << 1) | i2cReadBit();
i2cWriteBit(nack);
return value;
}
#define I2C_READ 0x01
#define I2C_WRITE 0x00
bool writeAddress(unsigned long byteAddr)
{
byte ctrl;
switch (eepromBlockSelectMode) {
case BSEL_NONE:
if (i2cWrite(eepromI2CAddress | I2C_WRITE) == I2C_NACK)
return false;
i2cWrite((byte)(byteAddr >> 8));
i2cWrite((byte)byteAddr);
break;
case BSEL_8BIT_ADDR:
ctrl = eepromI2CAddress | ((byte)(byteAddr >> 7) & 0x0E) | I2C_WRITE;
if (i2cWrite(ctrl) == I2C_NACK)
return false;
i2cWrite((byte)byteAddr);
break;
case BSEL_17BIT_ADDR:
ctrl = eepromI2CAddress | ((byte)(byteAddr >> 15) & 0x02) | I2C_WRITE;
if (i2cWrite(ctrl) == I2C_NACK)
return false;
i2cWrite((byte)(byteAddr >> 8));
i2cWrite((byte)byteAddr);
break;
case BSEL_17BIT_ADDR_ALT:
ctrl = eepromI2CAddress | ((byte)(byteAddr >> 13) & 0x08) | I2C_WRITE;
if (i2cWrite(ctrl) == I2C_NACK)
return false;
i2cWrite((byte)(byteAddr >> 8));
i2cWrite((byte)byteAddr);
break;
}
return true;
}
bool startRead(unsigned long addr)
{
enterProgramMode();
i2cStart();
if (!writeAddress(addr * 2))
return false;
i2cStart();
return i2cWrite(eepromI2CAddress | I2C_READ) == I2C_ACK;
}
unsigned int readWord(bool last)
{
unsigned int value = i2cRead(I2C_ACK);
value |= ((unsigned int)(i2cRead(last))) << 8;
if (last)
i2cStop();
return value;
}
unsigned long writeByteAddr;
bool writeAddrNeeded;
void startWrite(unsigned long addr)
{
enterProgramMode();
writeByteAddr = addr * 2;
writeAddrNeeded = true;
}
bool writeWord(unsigned int word)
{
if (writeAddrNeeded) {
i2cStart();
if (!writeAddress(writeByteAddr)) {
i2cStop();
return false;
}
writeAddrNeeded = false;
}
i2cWrite((byte)word);
if (eepromPageSize == 1) {
i2cStop();
for (;;) {
i2cStart();
if (i2cWrite(eepromI2CAddress | I2C_WRITE) == I2C_ACK)
break;
}
i2cStop();
i2cStart();
if (!writeAddress(writeByteAddr + 1)) {
i2cStop();
return false;
}
}
i2cWrite((byte)(word >> 8));
writeByteAddr += 2;
if ((writeByteAddr % eepromPageSize) == 0) {
i2cStop();
for (;;) {
i2cStart();
if (i2cWrite(eepromI2CAddress | I2C_WRITE) == I2C_ACK)
break;
}
i2cStop();
writeAddrNeeded = true;
}
return true;
}
void stopWrite()
{
if (!writeAddrNeeded) {
i2cStop();
for (;;) {
i2cStart();
if (i2cWrite(eepromI2CAddress | I2C_WRITE) == I2C_ACK)
break;
}
i2cStop();
}
}
bool eraseAll()
{
enterProgramMode();
unsigned long startTime = millis();
unsigned long currentTime;
unsigned long addr = 0;
bool activity = true;
while (addr < eepromSize) {
i2cStart();
if (!writeAddress(addr))
return false;
for (unsigned int count = 0; count < eepromPageSize; ++count)
i2cWrite(0xFF);
i2cStop();
for (;;) {
i2cStart();
if (i2cWrite(eepromI2CAddress | I2C_WRITE) == I2C_ACK)
break;
}
i2cStop();
addr += eepromPageSize;
if ((addr % 512) == 0) {
activity = !activity;
if (activity)
digitalWrite(PIN_ACTIVITY, HIGH);
else
digitalWrite(PIN_ACTIVITY, LOW);
}
currentTime = millis();
if ((currentTime - startTime) >= 2000) {
Serial.println("PENDING");
startTime = currentTime;
}
}
return true;
}
bool probeDevice()
{
enterProgramMode();
i2cStart();
if (i2cWrite(eepromI2CAddress | I2C_READ) == I2C_NACK)
return false;
i2cRead(I2C_NACK);
i2cStop();
return true;
}