forked from Apple-2-HW/TommyPROM
110 lines
2.8 KiB
C++
110 lines
2.8 KiB
C++
#include "Configure.h"
|
|
#include "PromDevice.h"
|
|
|
|
|
|
PromDevice::PromDevice(unsigned long size, word blockSize, unsigned maxWriteTime, bool polling)
|
|
: mSize(size),
|
|
mBlockSize(blockSize),
|
|
mMaxWriteTime(maxWriteTime),
|
|
mSupportsDataPoll(polling)
|
|
{
|
|
}
|
|
|
|
|
|
// Write a block of data to the device. If the device supports block writes,
|
|
// the data will be broken into chunks and written using the block mode.
|
|
// Otherwise, each byte will be individually written and verified.
|
|
bool PromDevice::writeData(byte data[], word len, word address)
|
|
{
|
|
bool status = true;
|
|
|
|
if (mBlockSize == 0)
|
|
{
|
|
// Device does not support block writes.
|
|
for (word ix = 0; (ix < len); ix++)
|
|
{
|
|
if (burnByte(data[ix], address + ix) == false)
|
|
{
|
|
status = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
word offset = 0;
|
|
word chunkSize;
|
|
if (address & (mBlockSize - 1))
|
|
{
|
|
// Address does not start on a block boundary. Adjust the size of
|
|
// the first block to fit within a single block.
|
|
chunkSize = mBlockSize - (address & (mBlockSize - 1));
|
|
chunkSize = (chunkSize > len) ? len : chunkSize;
|
|
if (burnBlock(data, chunkSize, address) == false)
|
|
{
|
|
return false;
|
|
}
|
|
offset += chunkSize;
|
|
len -= chunkSize;
|
|
}
|
|
|
|
// All writes are now aligned to block boundaries, so write full blocks
|
|
// or remaining length, whichever is smaller.
|
|
while (len > 0)
|
|
{
|
|
chunkSize = (len > mBlockSize) ? mBlockSize : len;
|
|
if (burnBlock(data + offset, chunkSize, address + offset) == false)
|
|
{
|
|
status = false;
|
|
break;
|
|
}
|
|
offset += chunkSize;
|
|
len -= chunkSize;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
// BEGIN PRIVATE METHODS
|
|
//
|
|
|
|
// Set the I/O state of the data bus.
|
|
// The first two bits of port D are used for serial, so the 8 bits data bus are
|
|
// on pins D2..D9.
|
|
void PromDevice::setDataBusMode(uint8_t mode)
|
|
{
|
|
// On the Uno and Nano, D2..D9 maps to the upper 6 bits of port D and the
|
|
// lower 2 bits of port B.
|
|
if (mode == OUTPUT)
|
|
{
|
|
DDRB |= 0x03;
|
|
DDRD |= 0xfc;
|
|
}
|
|
else
|
|
{
|
|
DDRB &= 0xfc;
|
|
DDRD &= 0x03;
|
|
}
|
|
}
|
|
|
|
|
|
// Read a byte from the data bus. The caller must set the bus to input_mode
|
|
// before calling this or no useful data will be returned.
|
|
byte PromDevice::readDataBus()
|
|
{
|
|
return (PINB << 6) | (PIND >> 2);
|
|
}
|
|
|
|
|
|
// Write a byte to the data bus. The caller must set the bus to output_mode
|
|
// before calling this or no data will be written.
|
|
void PromDevice::writeDataBus(byte data)
|
|
{
|
|
PORTB = (PORTB & 0xfc) | (data >> 6);
|
|
PORTD = (PORTD & 0x03) | (data << 2);
|
|
}
|
|
|
|
|