forked from Apple-2-HW/TommyPROM
Speed up setAddr code to meet SDP timing restrictions
This commit is contained in:
parent
82acfde3e3
commit
ac512a2740
@ -1,9 +1,4 @@
|
|||||||
// Uncomment only one of the ARDUINO_IS_ lines to use the fast I/O code for
|
|
||||||
// the data bus, or comment them all out to use the slower bit-at-a-time code.
|
|
||||||
|
|
||||||
//#define ARDUINO_IS_MICRO
|
|
||||||
#define ARDUINO_IS_UNO
|
#define ARDUINO_IS_UNO
|
||||||
//#define ARDUINO_IS_NANO
|
|
||||||
|
|
||||||
|
|
||||||
#include "PromDevice28C.h"
|
#include "PromDevice28C.h"
|
||||||
|
@ -145,19 +145,20 @@ void setup()
|
|||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
word start = 0;
|
|
||||||
word end = 0xff;
|
|
||||||
byte val = 0xff;
|
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
|
{
|
||||||
|
commandLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void commandLoop()
|
||||||
{
|
{
|
||||||
byte b;
|
byte b;
|
||||||
word w;
|
word w;
|
||||||
bool error = false;
|
|
||||||
char line[20];
|
char line[20];
|
||||||
uint32_t numBytes;
|
uint32_t numBytes;
|
||||||
|
unsigned long timeStart;
|
||||||
|
unsigned long timeEnd;
|
||||||
|
bool cmdError = false;
|
||||||
|
|
||||||
Serial.print("\n#");
|
Serial.print("\n#");
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
@ -167,12 +168,6 @@ void loop()
|
|||||||
c |= 0x20;
|
c |= 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that the comamnds here allow for direct writing of the 28C control lines with some exceptions to
|
|
||||||
* protect the chip and the host arduino:
|
|
||||||
* 1) When the O command is used to enable chip output, the arduino data bus us set to INPUT
|
|
||||||
* 2) When the D command is used to write data from the arduino, the chip output is disabled
|
|
||||||
* 3) The R command sets to output enable (OE) on the chip (but not the chip enable (CE)) */
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -182,8 +177,9 @@ void loop()
|
|||||||
prom.setAddress(w);
|
prom.setAddress(w);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
error = true;
|
cmdError = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (hexDigit(line[1]) <= 15)
|
if (hexDigit(line[1]) <= 15)
|
||||||
{
|
{
|
||||||
@ -193,12 +189,18 @@ void loop()
|
|||||||
prom.writeDataBus(b);
|
prom.writeDataBus(b);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
error = true;
|
cmdError = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'w':
|
case 'w':
|
||||||
if ((line[1] == 'd') || (line[1] == 'e')) {
|
if ((line[1] != 'd') && (line[1] != 'e'))
|
||||||
|
{
|
||||||
|
cmdError = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bool enable = line[1] == 'e';
|
bool enable = line[1] == 'e';
|
||||||
if (c == 'c')
|
if (c == 'c')
|
||||||
if (enable) prom.enableChip(); else prom.disableChip();
|
if (enable) prom.enableChip(); else prom.disableChip();
|
||||||
@ -214,10 +216,6 @@ void loop()
|
|||||||
else prom.disableOutput();
|
else prom.disableOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -236,19 +234,19 @@ void loop()
|
|||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
Serial.println(F("Writing the unlock code to disable Software Write Protect mode."));
|
Serial.println(F("Writing the unlock code to disable Software Write Protect mode."));
|
||||||
unsigned long timeStart = micros();
|
timeStart = micros();
|
||||||
prom.disableSoftwareWriteProtect();
|
prom.disableSoftwareWriteProtect();
|
||||||
unsigned long timeEnd = micros();
|
timeEnd = micros();
|
||||||
Serial.print("Unlock command time in uSec=");
|
Serial.print("Unlock command time in uSec=");
|
||||||
Serial.println(timeEnd - timeStart);
|
Serial.println(timeEnd - timeStart);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error = true;
|
cmdError = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (cmdError) {
|
||||||
Serial.print(F("Hardware Verifier - "));
|
Serial.print(F("Hardware Verifier - "));
|
||||||
Serial.println(prom.getName());
|
Serial.println(prom.getName());
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
@ -33,10 +33,10 @@ void PromAddressDriver::setAddress(word address)
|
|||||||
|
|
||||||
if (hi != lastHi)
|
if (hi != lastHi)
|
||||||
{
|
{
|
||||||
setAddressRegister(ADDR_CLK_HI, hi);
|
setAddressRegisterDirect(ADDR_CLK_HI, hi);
|
||||||
lastHi = hi;
|
lastHi = hi;
|
||||||
}
|
}
|
||||||
setAddressRegister(ADDR_CLK_LO, lo);
|
setAddressRegisterDirect(ADDR_CLK_LO, lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -67,4 +67,38 @@ void PromAddressDriver::setAddressRegister(uint8_t clkPin, byte addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shift an 8-bit value into one of the address shift registers. Note that
|
||||||
|
// the data pins are tied together, selecting the high or low address register
|
||||||
|
// is a matter of using the correct clock pin to shift the data in.
|
||||||
|
void PromAddressDriver::setAddressRegisterDirect(uint8_t clkPin, byte addr)
|
||||||
|
{
|
||||||
|
byte mask = 0;
|
||||||
|
if (clkPin == A3)
|
||||||
|
mask = 0x08;
|
||||||
|
else if (clkPin == A4)
|
||||||
|
mask = 0x10;
|
||||||
|
|
||||||
|
// Make sure the clock is low to start.
|
||||||
|
PORTC &= ~mask;
|
||||||
|
|
||||||
|
// Shift 8 bits in, starting with the MSB.
|
||||||
|
for (int ix = 0; (ix < 8); ix++)
|
||||||
|
{
|
||||||
|
// Set the data bit
|
||||||
|
if (addr & 0x80)
|
||||||
|
{
|
||||||
|
PORTC |= 0x20;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PORTC &= 0xdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle the clock high then low
|
||||||
|
PORTC |= mask;
|
||||||
|
delayMicroseconds(3);
|
||||||
|
PORTC &= ~mask;
|
||||||
|
addr <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ class PromAddressDriver {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static void setAddressRegister(uint8_t clkPin, byte addr);
|
static void setAddressRegister(uint8_t clkPin, byte addr);
|
||||||
|
static void setAddressRegisterDirect(uint8_t clkPin, byte addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,7 +75,6 @@ bool PromDevice::writeData(byte data[], word len, word address)
|
|||||||
// on pins D2..D9.
|
// on pins D2..D9.
|
||||||
void PromDevice::setDataBusMode(uint8_t mode)
|
void PromDevice::setDataBusMode(uint8_t mode)
|
||||||
{
|
{
|
||||||
#if defined(ARDUINO_IS_UNO) || defined(ARDUINO_IS_NANO)
|
|
||||||
// On the Uno and Nano, D2..D9 maps to the upper 6 bits of port D and the
|
// On the Uno and Nano, D2..D9 maps to the upper 6 bits of port D and the
|
||||||
// lower 2 bits of port B.
|
// lower 2 bits of port B.
|
||||||
if (mode == OUTPUT)
|
if (mode == OUTPUT)
|
||||||
@ -88,26 +87,6 @@ void PromDevice::setDataBusMode(uint8_t mode)
|
|||||||
DDRB &= 0xfc;
|
DDRB &= 0xfc;
|
||||||
DDRD &= 0x03;
|
DDRD &= 0x03;
|
||||||
}
|
}
|
||||||
#elif defined(ARDUINO_IS_MICRO)
|
|
||||||
// On the Micro, D2..D9 maps to the upper 7 bits of port B and the
|
|
||||||
// lower bit of port D.
|
|
||||||
if (mode == OUTPUT)
|
|
||||||
{
|
|
||||||
DDRB |= 0xfe;
|
|
||||||
DDRD |= 0x01;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DDRB &= 0x01;
|
|
||||||
DDRD &= 0xfe;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
byte bit = 0x01;
|
|
||||||
for (int pin = 2; (pin <= 9); pin++) {
|
|
||||||
pinMode(pin, mode);
|
|
||||||
bit <<= 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -115,21 +94,7 @@ void PromDevice::setDataBusMode(uint8_t mode)
|
|||||||
// before calling this or no useful data will be returned.
|
// before calling this or no useful data will be returned.
|
||||||
byte PromDevice::readDataBus()
|
byte PromDevice::readDataBus()
|
||||||
{
|
{
|
||||||
#if defined(ARDUINO_IS_UNO) || defined(ARDUINO_IS_NANO)
|
|
||||||
return (PINB << 6) | (PIND >> 2);
|
return (PINB << 6) | (PIND >> 2);
|
||||||
#elif defined(ARDUINO_IS_MICRO)
|
|
||||||
return (PINB & 0xfe) | (PIND & 0x01);
|
|
||||||
#else
|
|
||||||
byte data = 0;
|
|
||||||
byte bit = 0x01;
|
|
||||||
for (int pin = 2; (pin <= 9); pin++) {
|
|
||||||
if (digitalRead(pin) == HIGH) {
|
|
||||||
data |= bit;
|
|
||||||
}
|
|
||||||
bit <<= 1;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -137,19 +102,8 @@ byte PromDevice::readDataBus()
|
|||||||
// before calling this or no data will be written.
|
// before calling this or no data will be written.
|
||||||
void PromDevice::writeDataBus(byte data)
|
void PromDevice::writeDataBus(byte data)
|
||||||
{
|
{
|
||||||
#if defined(ARDUINO_IS_UNO) || defined(ARDUINO_IS_NANO)
|
|
||||||
PORTB = (PORTB & 0xfc) | (data >> 6);
|
PORTB = (PORTB & 0xfc) | (data >> 6);
|
||||||
PORTD = (PORTD & 0x03) | (data << 2);
|
PORTD = (PORTD & 0x03) | (data << 2);
|
||||||
#elif defined(ARDUINO_IS_MICRO)
|
|
||||||
PORTB = (PORTB & 0x01) | (data & 0xfe);
|
|
||||||
PORTD = (PORTD & 0xfe) | (data & 0x01);
|
|
||||||
#else
|
|
||||||
byte bit = 0x01;
|
|
||||||
for (int pin = 2; (pin <= 9); pin++) {
|
|
||||||
digitalWrite(pin, (data & bit) ? HIGH : LOW);
|
|
||||||
bit <<= 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,8 +204,8 @@ void PromDevice28C::setByte(byte value, word address)
|
|||||||
enableChip();
|
enableChip();
|
||||||
enableWrite();
|
enableWrite();
|
||||||
delayMicroseconds(1);
|
delayMicroseconds(1);
|
||||||
disableChip();
|
|
||||||
disableWrite();
|
disableWrite();
|
||||||
|
disableChip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ Note that the comamnds allow for direct writing of the 28C control lines with so
|
|||||||
* When the O command is used to enable chip output, the arduino data bus is set to INPUT
|
* When the O command is used to enable chip output, the arduino data bus is set to INPUT
|
||||||
* When the D command is used to write data from the arduino, the chip output is disabled
|
* When the D command is used to write data from the arduino, the chip output is disabled
|
||||||
* The R command sets the output enable (OE) on the chip, but not the chip enable (CE)
|
* The R command sets the output enable (OE) on the chip, but not the chip enable (CE)
|
||||||
|
* The L and U commands reset CE, OE, and WE back to disabled on completion and change the data and address
|
||||||
|
|
||||||
The session below shows how a write fails to a locked chip and then succeeds once the chip is unlocked.
|
The session below shows how a write fails to a locked chip and then succeeds once the chip is unlocked.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user