Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion TommyPROM/Configure.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Uncomment this to enable extra debugging commands and code

//#define ENABLE_DEBUG_COMMANDS
// #define ENABLE_DEBUG_COMMANDS

// Uncomment this to enable compilation for the Arduino Mega
// #define IS_MEGA

// Uncomment ONLY ONE of these to choose the PROM device code that will be
// compiled in.
Expand Down
93 changes: 93 additions & 0 deletions TommyPROM/PromAddressDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
//
// This code will only work on Arduino Uno and Nano hardware. The ports for other
// Arduinos map to different IO pins.
//
// Ghostboo124: Arduino Mega hardware support has been added.

#include "PromAddressDriver.h"

#ifndef IS_MEGA // if this isn't an arduino mega

#define ADDR_CLK_HI A3
#define ADDR_CLK_LO A4
#define ADDR_DATA A5
Expand Down Expand Up @@ -120,3 +124,92 @@ void PromAddressDriver::setAddressRegister(uint8_t clkPin, byte addr)
delayMicroseconds(1);
PORTB &= ~RCLK_595_MASK;
}

#else // #ifndef IS_MEGA

// Address lines A0..A18 are controlled by D22..D40.
#define ADDR_MASK_A 0xff // D22..D29 = PA0..PA7 = A0..A7
#define ADDR_MASK_C 0xff // D30..D37 = PC7..PC0 = A8..A15
#define ADDR_MASK_D 0x80 // D38 = PD7 = A16
#define ADDR_MASK_G 0x06 // D39..D40 = PG2..PG1 = A17..A18

void PromAddressDriver::begin()
{
// The address control pins are always outputs.
DDRA |= ADDR_MASK_A; // Set D22..D29 as outputs
DDRC |= ADDR_MASK_C; // Set D30..D37 as outputs
DDRD |= ADDR_MASK_D; // Set D38 as output
DDRG |= ADDR_MASK_G; // Set D39..D40 as outputs

// To save time, the setAddress only writes the hi byte if it has changed.
// The value used to detect the change is initialized to a non-zero value,
// so set an initial address to avoid the the case where the first address
// written is the 'magic' initial address.
setAddress(0x0000);
}

// Set the address pins to a given address.
void PromAddressDriver::setAddress(uint32_t address)
{
static byte lastHi = 0xca;
static byte lastUpper = 0xca;
byte upper = (address >> 16) & 0xff;
byte hi = (address >> 8) & 0xff;
byte lo = address & 0xff;

if (upper != lastUpper)
{
setUpperAddress(upper);
lastUpper = upper;
}
if (hi != lastHi)
{
setLowerAddress(hi, true);
lastHi = hi;
}
setLowerAddress(lo, false);
}

// Set the upper address bits on the address pins.
void PromAddressDriver::setUpperAddress(byte addr)
{
// Set the upper address on pins D38..D40.

// D38
if (addr & 0x01)
PORTD |= ADDR_MASK_D;
else
PORTD &= ~ADDR_MASK_D;

// D39, D40
uint8_t portG = PORTG & ~ADDR_MASK_G;
if (addr & 0x02) // A17 -> PG2
portG |= 0x04;
if (addr & 0x04) // A18 -> PG1
portG |= 0x02;
PORTG = portG;
}


// Write the 8-bit low or high address values to the address pins.
void PromAddressDriver::setLowerAddress(byte addr, bool isHigh)
{
if (isHigh) { // If we are working with A8..A15
// D30..D37 = PC7..PC0 = A8..A15
uint8_t portC = 0;
if (addr & 0x01) portC |= 0x80; // A8 -> PC7 (D30)
if (addr & 0x02) portC |= 0x40; // A9 -> PC6 (D31)
if (addr & 0x04) portC |= 0x20; // A10 -> PC5 (D32)
if (addr & 0x08) portC |= 0x10; // A11 -> PC4 (D33)
if (addr & 0x10) portC |= 0x08; // A12 -> PC3 (D34)
if (addr & 0x20) portC |= 0x04; // A13 -> PC2 (D35)
if (addr & 0x40) portC |= 0x02; // A14 -> PC1 (D36)
if (addr & 0x80) portC |= 0x01; // A15 -> PC0 (D37)
PORTC = portC;
} else { // If we are working with A0..A7
// D22..D29 = PA0..PA7 = A0..A7
PORTA = addr;
}
}

#endif // #ifndef IS_MEGA
6 changes: 5 additions & 1 deletion TommyPROM/PromAddressDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@
#define INCLUDE_PROM_ADDRESS_DRIVER_H

#include "Arduino.h"
#include "Configure.h"

class PromAddressDriver {
public:
static void begin();
static void setAddress(uint32_t address);

private:
static void setUpperAddress(byte addr);
#ifndef IS_MEGA
static void setAddressRegister(uint8_t clkPin, byte addr);
#else // #ifndef IS_MEGA
static void setLowerAddress(byte addr, bool isHigh);
#endif // #ifndef IS_MEGA
};


Expand Down
51 changes: 51 additions & 0 deletions TommyPROM/PromDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ void PromDevice::printDebugStats() {
// on pins D2..D9.
void PromDevice::setDataBusMode(uint8_t mode)
{
#ifndef IS_MEGA
// 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)
Expand All @@ -117,21 +118,71 @@ void PromDevice::setDataBusMode(uint8_t mode)
PORTB |= 0x03; // set pullup resistors
PORTD |= 0xfc;
}
#else // #ifndef IS_MEGA
// On the Mega, D2..D9 maps to stupid random ports...
if (mode == OUTPUT) {
DDRE |= 0x38; // D2,D3,D5 = PE4, PE5, PE3
DDRG |= 0x20; // D4 = PG5
DDRH |= 0x78; // D6..D9 = PH3..PH6
} else {
// Set to input
DDRE &= ~0x38;
DDRG &= ~0x20;
DDRH &= ~0x78;
// set pullup resistors
PORTE |= 0x38;
PORTG |= 0x20;
PORTH |= 0x78;
}

#endif // #ifndef IS_MEGA
}


// 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()
{
#ifndef IS_MEGA
return (PINB << 6) | (PIND >> 2);
#else // #ifndef IS_MEGA
byte data = 0;
if (PINE & 0x10) data |= 0x01; // D2 = PE4
if (PINE & 0x20) data |= 0x02; // D3 = PE5
if (PING & 0x20) data |= 0x04; // D4 = PG5
if (PINE & 0x08) data |= 0x08; // D5 = PE3
if (PINH & 0x08) data |= 0x10; // D6 = PH3
if (PINH & 0x10) data |= 0x20; // D7 = PH4
if (PINH & 0x20) data |= 0x40; // D8 = PH5
if (PINH & 0x40) data |= 0x80; // D9 = PH6
return data;
#endif // #ifndef IS_MEGA
}


// 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)
{
#ifndef IS_MEGA
PORTB = (PORTB & 0xfc) | (data >> 6);
PORTD = (PORTD & 0x03) | (data << 2);
#else // #ifndef IS_MEGA
uint8_t portE = PORTE & ~0x38; // clear PE3,4,5
if (data & 0x01) portE |= 0x10; // bit0 -> PE4 (D2)
if (data & 0x02) portE |= 0x20; // bit1 -> PE5 (D3)
if (data & 0x08) portE |= 0x08; // bit3 -> PE3 (D5)
PORTE = portE;

uint8_t portG = PORTG & ~0x20; // clear PG5
if (data & 0x04) portG |= 0x20; // bit2 -> PG5 (D4)
PORTG = portG;

uint8_t portH = PORTH & ~0x78; // clear PH3..PH6
if (data & 0x10) portH |= 0x08; // bit4 -> PH3 (D6)
if (data & 0x20) portH |= 0x10; // bit5 -> PH4 (D7)
if (data & 0x40) portH |= 0x20; // bit6 -> PH5 (D8)
if (data & 0x80) portH |= 0x40; // bit7 -> PH6 (D9)
PORTH = portH;
#endif // #ifndef IS_MEGA
}
6 changes: 3 additions & 3 deletions TommyPROM/PromDevice28C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ void PromDevice28C::begin()

// 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);
digitalWrite(OE, HIGH);
pinMode(CE, OUTPUT);
digitalWrite(WE, HIGH);
digitalWrite(CE, HIGH);
pinMode(WE, OUTPUT);
digitalWrite(WE, HIGH);

// This chip uses the shift register hardware for addresses, so initialize that.
PromAddressDriver::begin();
Expand Down
2 changes: 0 additions & 2 deletions TommyPROM/TommyPROM.ino
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@
#include "CmdStatus.h"
#include "XModem.h"


static const char * MY_VERSION = "3.7";


// Global status
CmdStatus cmdStatus;

Expand Down
3 changes: 2 additions & 1 deletion docs/_docs/00-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ use this version, just compile and upload it to the Arduino.
that it can run quickly enough to meet 28C series chip timing requirements for SDP
unlocking. To use different Arduino hardware, like the Micro, the board-specific code in
PromDevice.cpp and PromAddressDriver.cpp must be changed to match the port mappings
between the ATmega chip and the Arduino I/O pins.
between the ATmega chip and the Arduino I/O pins. If you are compiling for the
Arduino Mega2560, uncomment the IS_MEGA line in Configure.

Because the Arduino has limited code and RAM space available, only one PROM driver is
compiled in at a time. To change drivers, uncomment the desired PROM_IS_xx line in
Expand Down
6 changes: 3 additions & 3 deletions docs/_docs/50-ops-500-troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ hardware allows access to individual control lines from the Arduino to verify th
hardware was assembled correctly.

The verifier sketch can be used without a chip installed to scope out address and data
lines. It also offers low-level control when the chip is installed.
lines. It also offers low-level control when the chip is installed.

THIS TOOL USES DIRECT PORT ACCESS ON THE ARDUINO. CHECK TO MAKE SURE IT IS COMPATIBLE
WITH YOUR BOARD BEFORE USING. It will work correctly on the Uno, Nano, and Boarduino. It
WILL NOT WORK on the Micro.
WITH YOUR BOARD BEFORE USING. It will work correctly on the Uno, Nano, Boarduino, and
Mega2560 with configuration changes. It WILL NOT WORK on the Micro.

Note that the commands write to the individual 28C control lines with some exceptions to
protect the chip and the host Arduino:
Expand Down
10 changes: 8 additions & 2 deletions docs/_docs/design-100-hardware.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@ The basic circuit is as follows:
* Pins A3..A5 control shift registers to produce the address lines.
* Pins D10..D12 control A<sub>16</sub>..A<sub>18</sub> for chips larger than 64K bytes.

If you use a Arduino Mega2560, the basic circuit is as follows:
* Pins D2..D9 are wired to the data lines on teh target PROM.
* Pins A0..A2 are wired to the WE, CE, and OE control lines of the target PROM.
* Pins D22..D37 control the address lines A<sub>0</sub>..A<sub>15</sub>.
* Pins D38..D40 control the address lines A<sub>16</sub>..A<sub>18</sub> for chips larger than 64K bytes

Note that the existing design uses 74LS164 shift registers, but another 8-bit parallel out
shift register, like the 74LS595, can be used instead with some pin changes. See the
[74LS595 Shift Registers](#74ls595-shift-registers) section below for details.

The two shift registers can produce a sixteen bit address, although the 28C256 only needs
15 addresses. Chips larger than 64K are supported by using the shift registers for
A<sub>0</sub>..A<sub>15</sub> and connecting Arduino pins D10..D12 to the chip's
A<sub>16</sub>..A<sub>18</sub>
A<sub>16</sub>..A<sub>18</sub> or for the Mega2560, pins D38..D40 to A<sub>16</sub>..A<sub>18</sub>.

[![TommyPROM Nano Schematic](images/TommyPROM-nano-sch.png)](images/TommyPROM-nano-sch.png)

Expand Down Expand Up @@ -59,7 +65,7 @@ larger chips like the 27C040.
3. The D13 pin controls the output register on the '595 shift registers. This pin is not
connected when using the 74LS164.

Note that the 74LS595s have two additional pins that need to be connected.
Note that the 74LS595s have two additional pins that need to be connected.
* An output enable pin, labeled as either G or OE in the datasheet, must be tied LOW for
both chips or else they will not produce any signal on their output lines.
* A reset pin, labeled as RESET or SRCLR, must be tied HIGH for both chips or else the
Expand Down
4 changes: 2 additions & 2 deletions docs/_docs/design-200-software.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ To meet the timing requirements for block writes and 28C chip unlocking, the Pro
class accesses the shift registers and data bus using direct port writes instead of 8
individual pin accesses. This greatly increases performance, but it makes the code
dependent on the particular flavor of Arduino being used. The code supports the Uno,
Nano, and Boarduino versions of Arduino hardware or any other variant that uses that same
Nano, Boarduino, and Mega2560 versions of Arduino hardware or any other variant that uses that same
mapping of ATMega ports to I/O pins. To support a different Arduino board, either change
the pins used to match the mapping in the software, or change the hardware-specific code
in PromDevice.cpp and PromAddressDriver.cpp.
Expand Down Expand Up @@ -79,5 +79,5 @@ the Vdd switching hardware that toggles the Vdd pin between the normal 5V value
### PromAddressDriver class

Although not actually a subclass of PromDevice, this contains the code to drive the shift
registers that provide the address lines. If this hardware is used, the PromDeviceXX class
registers that provide the address lines or directly control the address lines on the Mega2560. If this hardware is used, the PromDeviceXX class
can call this code to implement the SetAddress methods.
2 changes: 1 addition & 1 deletion docs/_docs/design-400-extending.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ already been used with these chips for read-only operations.

The current design can directly address chips as large as 512K bytes, like the 29C040. Use
the shift registers for A<sub>0</sub>..A<sub>15</sub> and wire Arduino pins D10..D12 to
A<sub>16</sub>..A<sub>18</sub> on the target chip.
A<sub>16</sub>..A<sub>18</sub> on the target chip or on the Mega2560, pins D38 to D40 to A<sub>16</sub>..A<sub>18</sub>.

# Software

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions schematics/TommyPROM-Mega2560/TommyPROM-Mega2560.kicad_pcb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(kicad_pcb (version 20241229) (generator "pcbnew") (generator_version "9.0")
)
Loading