TommyPROM/TommyPROM/PromDevice27.cpp

143 lines
3.5 KiB
C++

// NOTE - The 27 series device support is a work in progress. It
// has not been tested or documented.
#include "Configure.h"
#if defined(PROM_IS_27)
#include "PromAddressDriver.h"
// IO lines for the EPROM device control
// Pins D2..D9 are used for the data bus.
#define WE A0
#define CE A1
#define OE A2
// Set the status of the device control pins
static void enableChip() { digitalWrite(CE, LOW); }
static void disableChip() { digitalWrite(CE, HIGH);}
static void enableOutput() { digitalWrite(OE, LOW); }
static void disableOutput() { digitalWrite(OE, HIGH);}
static void enableWrite() { digitalWrite(WE, LOW); }
static void disableWrite() { digitalWrite(WE, HIGH);}
PromDevice27::PromDevice27(uint32_t size, unsigned long pulseWidthUsec,
unsigned writeAttempts, unsigned overwriteMultiplier)
: PromDevice(size, 0, 0, false),
mPulseWidthUsec(pulseWidthUsec),
mWriteAttempts(writeAttempts),
mOverwriteMultiplier(overwriteMultiplier)
{
}
void PromDevice27::begin()
{
// Define the data bus as input initially so that it does not put out a
// signal that could collide with output on the data pins of the EEPROM.
setDataBusMode(INPUT);
// Define the EEPROM control pins as output, making sure they are all
// in the disabled state.
digitalWrite(OE, HIGH);
pinMode(OE, OUTPUT);
digitalWrite(CE, HIGH);
pinMode(CE, OUTPUT);
digitalWrite(WE, HIGH);
pinMode(WE, OUTPUT);
// This chip uses the shift register hardware for addresses, so initialize that.
PromAddressDriver::begin();
}
// BEGIN PRIVATE METHODS
//
// Use the PromAddressDriver to set a 16 bit address in the two address shift registers.
void PromDevice27::setAddress(uint32_t address)
{
PromAddressDriver::setAddress(address);
}
// Read a byte from a given address
byte PromDevice27::readByte(uint32_t address)
{
byte data = 0;
setAddress(address);
setDataBusMode(INPUT);
disableOutput();
disableWrite();
enableChip();
enableOutput();
data = readDataBus();
disableOutput();
disableChip();
return data;
}
// Burn a byte to the chip and verify that it was written.
bool PromDevice27::burnByte(byte value, uint32_t address)
{
bool status = false;
unsigned writeCount = 0;
disableOutput();
disableWrite();
enableChip();
setAddress(address);
while (!status && (writeCount < mWriteAttempts))
{
setDataBusMode(OUTPUT);
writeDataBus(value);
delayMicroseconds(1);
enableWrite();
myDelay(mPulseWidthUsec);
disableWrite();
++writeCount;
setDataBusMode(INPUT);
enableOutput();
data = readDataBus();
disableOutput();
status = (readDataBus() == value);
}
if (status && (mOverwriteMultiplier > 0))
{
setDataBusMode(OUTPUT);
writeDataBus(value);
delayMicroseconds(1);
enableWrite();
myDelay(mPulseWidthUsec * mOverwriteMultiplier);
disableWrite();
}
disableChip();
return status;
}
void PromDevice27::myDelay(unsigned int us)
{
if (us > 16000)
{
// The delayMicroseconds code can't do delays longer than 16ms, so use the
// ms delay code for larger values. This rounds down to the nearest ms, so
// it is not possible to delay for 40.5 ms, for example.
delay(us / 1000);
}
else
{
delayMicroseconds((unsigned int) us);
}
}
#endif // #if defined(PROM_IS_27)