Simpele EEPROM programmer

Als het om de programmer naar voorbeeld van Ben Eater gaat: ik heb van de USB aansluiting naar de Arduino ALLEEN de ground doorverbonden met de schakeling. De 5 Volt voor de rest van de schakeling komt bij mij uit mijn lab-voeding. (dit nadat ik een Nano had opgeblazen)... :-(

Ain't no place like 127.0.0.1
tmdr

Golden Member

Schema:

Sorry, ben bizar slecht in het netjes maken van dit soort dingen.

Foto's:

Eerste foto is met (neppe) ZIF. Heb de 24pins socket nu geprobeerd, dacht misschien zit er een probleem in die andere 28-pins die ik heb.
Foto twee zijn de IO pinnen onder de socket ook te zien, en is duidelijk waar alles precies naar toe gaat.
Heb alles al honderd keer met een multimeter gecheckt, alles maakt contact, en ook met de goede pinnen.

Code:

c code:


#define SHIFT_DATA        2
#define SHIFT_CLK         3
#define SHIFT_LATCH       4

#define WRITE_EN_16       11
#define WRITE_EN_16_MASK  B1000
#define WRITE_EN_256      12
#define WRITE_EN_256_MASK B10000

#define ADDRESS_11        11
#define ADDRESS_13        13
#define VCC               13
#define A6                6
#define A7                5

#define DATA_PIN_COUNT    8

bool is_256 = false;
uint8_t data_pins[DATA_PIN_COUNT] = { A0, A1, A2, A3, A4, A5, A6, A7 };

/*
 * Dirty way to switch IC type.
 */
void set_is_256(bool _is_256) {
  is_256 = _is_256;
  digitalWrite(VCC, is_256); // negated signal because of PNP
  delay(500);
}

/*
 * Pulse WE for ~500ns.
 */
void pulse_write_enable() {
  byte pin_mask = is_256 ? WRITE_EN_256_MASK : WRITE_EN_16_MASK;
  PORTB &= ~pin_mask; // pin LOW
  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); // delay 500ns (8 * 62.5ns)
  PORTB |= pin_mask; // pin HIGH
  delay(10);
}

/*
 * Output the address bits and outputEnable signal using shift registers.
 */
void set_address(uint16_t address, bool outputEnable) {
  /*
   * LSB are shifted first, since the order of shift registers changed
   * as opposed to original design.
   */
  shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, address);
  shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, (address >> 8) | (outputEnable ? 0x00 : 0x80));

  digitalWrite(SHIFT_LATCH, LOW);
  digitalWrite(SHIFT_LATCH, HIGH);
  digitalWrite(SHIFT_LATCH, LOW);

  if (is_256) {
    digitalWrite(ADDRESS_11, (address >> 10) & 0x1);
    digitalWrite(ADDRESS_13, (~address >> 12) & 0x1);
  }
}

/*
 * Set pinMode on all IO pins
 */
void io_mode(uint8_t mode) {
  for (uint8_t pin = 0; pin < DATA_PIN_COUNT; pin++)
    pinMode(data_pins[pin], mode);
}

/*
 * Read a byte from the EEPROM at the specified address.
 */
byte read_rom(uint16_t address) {
  io_mode(INPUT);
  set_address(address, /*outputEnable*/ true);

  byte data = 0;
  for (uint8_t pin = DATA_PIN_COUNT; pin > 0; pin--)
    data = (data << 1) + digitalRead(data_pins[pin - 1]);
  return data;
}

/*
 * Write a byte to the EEPROM at the specified address.
 */
void write_rom(uint16_t address, byte data) {
  set_address(address, /*outputEnable*/ false);
  io_mode(OUTPUT);

  for (uint8_t pin = 0; pin < DATA_PIN_COUNT; pin++) {
    digitalWrite(data_pins[pin], data & 1);
    data = data >> 1;
  }
  pulse_write_enable();
}


/*
 * Read the contents of the EEPROM and print them to the serial monitor.
 */
void print_contents() {
  for (uint16_t base = 0; base <= 255; base += 16) {
    byte data[16];
    for (uint8_t offset = 0; offset <= 15; offset++)
      data[offset] = read_rom(base + offset);

    char buf[80];
    sprintf(buf, "%03x:  %02x %02x %02x %02x %02x %02x %02x %02x   %02x %02x %02x %02x %02x %02x %02x %02x",
            base, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
            data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);

    Serial.println(buf);
  }
}

// 4-bit hex decoder for common anode 7-segment display
byte data[] = { 0x81, 0xcf, 0x92, 0x86, 0xcc, 0xa4, 0xa0, 0x8f, 0x80, 0x84, 0x88, 0xe0, 0xb1, 0xc2, 0xb0, 0xb8 };

// 4-bit hex decoder for common cathode 7-segment display
// byte data[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47 };


void setup() {
  pinMode(SHIFT_DATA, OUTPUT);
  pinMode(SHIFT_CLK, OUTPUT);
  pinMode(SHIFT_LATCH, OUTPUT);
  
  digitalWrite(WRITE_EN_16, HIGH);
  digitalWrite(WRITE_EN_256, HIGH);
  pinMode(WRITE_EN_16, OUTPUT);
  pinMode(WRITE_EN_256, OUTPUT);
  
  pinMode(ADDRESS_11, OUTPUT);
  pinMode(ADDRESS_13, OUTPUT); // and VCC pin for 28c16
  
  Serial.begin(57600);

  set_is_256(false);

  // Erase entire EEPROM
  Serial.print("Erasing EEPROM");
  for (uint16_t address = 0; address <= 2047; address++) {
    write_rom(address, 0xff);

    if (address % 64 == 0)
      Serial.print(".");
  }
  Serial.println(" done");

  // Program data bytes
  Serial.print("Programming EEPROM");
  for (uint16_t address = 0; address < sizeof(data); address++) {
    write_rom(address, data[address]);

    if (address % 64 == 0)
      Serial.print(".");
  }
  Serial.println(" done");

  // Read and print out the contents of the EERPROM
  Serial.println("Reading EEPROM");
  print_contents();
}

void loop() {}

Ik heb de boel even samengevoegd, de interfacing functies en de main file.
De code is gebaseerd op de code van Ben Eater, maar met redelijk wat aanpassingen.
Onder andere de functie pulse_write_enable(), die niet meer met delayMicroseconds(1) werkt, maar met acht NOPs. Dat moet 500ns geven. Icm de twee directe manipulaties op PORTB moet dat maximaal nog een paar cycles opleveren á 62.5ns per stuk. Daarmee weet ik vrijwel zeker dat ik onder die 1us zit. Heb ook minder NOPs geprobeerd, maar geen effect.

Verder heb ik, zoals op de foto's te zien, de shift registers net andersom ingezet (dus het schema klopt hier niet in!). Daarom shift ik dus in een andere volgorde.

PS: was een beetje stom, had gerekend op 8 analog pins waarmee ik mooi de 8 IO bits mee kon lezen/schrijven, maar het zijn natuurlijk maar 6 analog pins. Stom van me, wist ik natuurlijk ook wel. Jammer, want dan had ik gewoon de 8-bits waarde direct naar PORTC kunnen schrijven.

Arco

Special Member

Het schema is moeilijk te volgen. Maar wat ik daar zie gaat in ieder geval nooit werken.
De adreslijnen van de eprom zitten aan de ingangen van de 4048 poort vast (en verder nergens aan), en zweven dus gewoon???
Die adreslijnen moeten wel aangestuurd worden wil er iets zinvols gaan gebeuren...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
tmdr

Golden Member

Op 22 september 2017 12:46:46 schreef Arco:
Het schema is moeilijk te volgen. Maar wat ik daar zie gaat in ieder geval nooit werken.
De adreslijnen van de eprom zitten aan de ingangen van de 4048 poort vast (en verder nergens aan), en zweven dus gewoon???
Die adreslijnen moeten wel aangestuurd worden wil er iets zinvols gaan gebeuren...

Excuses, dat rot programma heeft er bij het saven mooi een andere IC van gemaakt!
Het gaat dus om twee maal de 74HC595 shift registers.

Het schema is inderdaad een drama, excuses.

De address lines van de ROM zitten dus op de uitgangen van de shift registers. Die zweven dus nooit.

Arco

Special Member

Waarom schuifregisters? Heel ongebruikelijk voor zoiets, meestal worden er latches gebruikt als de 74HCT573. Net zoveel of minder pinnen en simpel aan te sturen.

code:


                          ,---------,
                  D0...7  |         |
----/8/--o-------o----<>--|         |
         |       |        |         |
         |       |        |         |
         |    ,-----,     |         |
         |    |     |     |         |
         |    | 573 |     | EEPROM  |   
         |    |     |     |         |
         |    |     |     |         |
         |    |     |     |         |
         |    '-----'     |         |
         |       | A0...7 |         |
      ,-----,    '---->---|         |
      |     |             |         |
      | 573 |             |         |
      |     |             |         |     
      |     |             |         |     
      |     |             |         |     
      '-----'             |         |
         |        A8...15 |         |
         '------------>---|         |
                          |         |
                          '---------'     
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
tmdr

Golden Member

Dat begrijp ik niet.
Ik gebruik de shift registers omdat ik simpelweg te weinig pinnen op de MCU heb.
En die shift registers zijn ook latched, dus zie ik het probleem niet.

Arco

Special Member

Ik gebruik de shift registers omdat ik simpelweg te weinig pinnen op de MCU heb.

Dan kun je toch ook parallel latches als de 573 gebruiken? (die zijn daarvoor bedoeld)
Is ook nog eens veel sneller en makkelijker dus qua timing.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
tmdr

Golden Member

Zou goed kunnen, maar 1) de 595 heb ik in huis en 2) dit werkt ook.
Als ik op de address pins ledjes aansluit en dan de boel test gaat het allemaal prima.
Daar zit het probleem sowieso niet.

trix

Golden Member

leuk voor mij om te volgen (leerzaam), daarom kick hem een keer voor je omhoog.

hier leer je inderdaad veel meer van dan zomaar iets kant & klaar te kopen.

eigenwijs = ook wijs
eSe

Honourable Member

Ik gebruik de shift registers omdat ik simpelweg te weinig pinnen op de MCU heb.

Heb ik ook een keer zo gemaakt. Een eprom emulator voor mijn 8051 mcu ontwikkel systeem. Ik had enkele statische rams, dacht 2 x 32kB, op een printje, een flatcable met 24 (28?) pins dip connector en wat glue logic.

Het vullen van de ram ging via de parallelpoort van een p.c. naar 3 schuifregisters in cascade. 2 voor het 12 (13,14?) bits adres en 1 voor de 8 bits data.

Een simpele routine, om de data via 2 pinnen van de parpoort uit te klokken, geschreven en ik hoefde niet na iedere bug/wijziging eprom's te programmeren/wissen. Flatcable inpluggen in eprom socket in "systeem onder test", data opsturen, enkele andere bits op de parpoort setten/resetten (om de bidirectionele poorten op de emulator print in een richting te zetten, reset signaal te geven...) en lopen maar :-)

Groetjes,
eSe

CChheecckk yyoouurr dduupplleexx sswwiittcchh..
tmdr

Golden Member

Op 25 september 2017 18:41:15 schreef trix:
leuk voor mij om te volgen (leerzaam), daarom kick hem een keer voor je omhoog.

hier leer je inderdaad veel meer van dan zomaar iets kant & klaar te kopen.

Dank voor de kick.
Inderdaad leerzaam en leuk. Ik heb de boel helaas nog steeds niet werkend, maar bijvoorbeeld wat wat meer geleerd over hoe ik de transistor aansluit.

Hier kun je een zeer uitgebreid filmpje vinden, mocht je het zelf ooit nodig hebben of interessant vinden.