DRAMARDUINO - Dram tester with Arduino

This is the right place to discuss on how to implement hardware vsync, adding a VIA or AY chipset, puting multiple roms, or how to design a new flash expansion card.
Post Reply
User avatar
iss
Wing Commander
Posts: 1155
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

DRAMARDUINO - Dram tester with Arduino

Post by iss »

Hi all!

Below you can see all details of my 2-hours 2-dollar project 'DramArduino'.
It's simple and very handy DRAM chip tester. It works with 4164 and 41256 IC's.
Testing is not too fast but acceptable - 4 different passes are performed in about 80 seconds total.
Results are 100% reliable only if the test FAILS - you can throw away the chip without fear.
If the test passes, this doesn't certainly mean that it will work in Oric, because as you know Oric's are very 'sensitive' to DRAM.
Actually this was my goal exactly - to sort out the working chips from about 200 before I'm get bored :).

Working with the tool is easy: place the chip in the ZIF socket, press small reset button, wait until GREEN LED blinks,
if it remains permanently on - chip is OK, if the chip is bad - RED LED lights.
If USB is connected, status is reported in your serial console. This helped me to detect some 'lazy' chips - they failed in
different, on every next test, growing addresses but when they become 'hot' test passes always.
IIRC such fail to boot Oric was reported somewhere in this forum...

Attached are 'schematic', source code and pictures - do with them what you want :).
dramarduino.png
da.jpg
EDIT 2020-10-29: Sketch fixed!
dramarduino.ino.2020-10-29.zip
(1.4 KiB) Downloaded 198 times
Last edited by iss on Thu Oct 29, 2020 7:35 pm, edited 2 times in total.

User avatar
Voyageur
2nd Star Corporal
Posts: 26
Joined: Thu Oct 18, 2018 8:25 am
Location: Sydney

Re: DRAMARDUINO - Dram tester with Arduino

Post by Voyageur »

Hi Iss,
Thank you for sharing the DramTester.
I've made one and it works !
I just controlled some 4164 and it is a good and not so long test :)
If you agree, I will show this Arduino shield on flag_fr CEO forum.
Have a good day !
Oric Atmos : a new life !

User avatar
iss
Wing Commander
Posts: 1155
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: DRAMARDUINO - Dram tester with Arduino

Post by iss »

Hello, Voyageur!
I'm very glad that you liked this little tool and I'll be really happy if you share it on CEO forum.

witchy
1st Star Corporal
Posts: 13
Joined: Wed Jun 22, 2016 11:26 pm

Re: DRAMARDUINO - Dram tester with Arduino

Post by witchy »

Hi Iss,

This was timed beautifully, for an upcoming 'Japanese Computing' exhibition at the Centre For Computing History in Cambridge I was testing my Sanyo MBC555 and the CGA card in there has 8x41256 chips on board. I built the tester on a breadboard and it works perfectly, thanks! Unfortunately it passed all 8 so the fault I have is elsewhere on the board.
dramArduino.jpg

john
Private
Posts: 1
Joined: Mon Oct 05, 2020 8:11 am

Re: DRAMARDUINO - Dram tester with Arduino

Post by john »

Resurrecting a old thread here but looks like there is a critical bug in this code which causes only memory location 0x0000 to be tested.

Code: Select all

void setBus(unsigned int a) {
  int i;
  for (i = 0; i < BUS_SIZE; i++) {
    digitalWrite(a_bus[i], a % 1);
    a /= 2;
  }
}
a%1 will always result in 0 so no matter what value a is, 0 will always be written to the address lines.

Code should be changed to:

Code: Select all

digitalWrite(a_bus[i], a % 2);

User avatar
HigashiJun
Flying Officer
Posts: 163
Joined: Tue Dec 10, 2019 9:29 am
Location: Tokyo (Japan)

Re: DRAMARDUINO - Dram tester with Arduino

Post by HigashiJun »

Interesting...

I will give it a try on my DRAMARDUINO.

Thanks.
HigashiJun

User avatar
iss
Wing Commander
Posts: 1155
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: DRAMARDUINO - Dram tester with Arduino

Post by iss »

Wow, nice catch. Interesting is that in my local file it's:

Code: Select all

digitalWrite(a_bus[i], a & 1);
Maybe I've uploaded something preliminary...
First post is now updated with the correct sketch!
Last edited by iss on Thu Oct 29, 2020 9:27 pm, edited 1 time in total.

User avatar
thekorex
Private
Posts: 1
Joined: Thu Oct 29, 2020 11:48 am
Location: Portugal
Contact:

Re: DRAMARDUINO - Dram tester with Arduino

Post by thekorex »

Hello everyone, yesterday I got a pack of KM4164B-15 ICs and quickly built a big mess of wires on a breadboard to test them using DramArduino which I want to thank @iss for creating and sharing.

After testing a few of the ICs I noticed the sketch still contains two more occurrences of the problematic % 1 in both fill(int v) and fillx(int v) functions.

I think this will cause fill(int v) to simply test the RAM with zeros, regardeless of the value of v and fillx(int v) to always generate the sequence "0 1 0 1..." and never the opposite one "1 0 1 0..."

Code: Select all

void fill(int v) {
  int r, c, g = 0;
  v %= 1;
  for (c = 0; c < (1<<bus_size); c++) {
    green(g? HIGH : LOW);
    for (r = 0; r < (1<<bus_size); r++) {
      writeAddress(r, c, v);
      if (v != readAddress(r, c))
        error(r, c);
    }
    g ^= 1;
  }
  blink();
}

void fillx(int v) {
  int r, c, g = 0;
  v %= 1;
  for (c = 0; c < (1<<bus_size); c++) {
    green(g? HIGH : LOW);
    for (r = 0; r < (1<<bus_size); r++) {
      writeAddress(r, c, v);
      if (v != readAddress(r, c))
        error(r, c);
      v ^= 1;
    }
    g ^= 1;
  }
  blink();
}
I replaced each function's second line containing

Code: Select all

  v %= 1;
with

Code: Select all

  v &= 1;
to get the lower bit of v and I believe it solves the problem.

Anyway, thank you again for sharing this nice project.

User avatar
iss
Wing Commander
Posts: 1155
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: DRAMARDUINO - Dram tester with Arduino

Post by iss »

thekorex wrote:
Thu Oct 29, 2020 5:42 pm
...
Thank you for reporting @thekorex!

First post is updated again with the correct sketch!

shift838
Private
Posts: 1
Joined: Wed Dec 09, 2020 10:55 pm

Re: DRAMARDUINO - Dram tester with Arduino

Post by shift838 »

iss wrote:
Thu Oct 29, 2020 7:37 pm
thekorex wrote:
Thu Oct 29, 2020 5:42 pm
...
Thank you for reporting @thekorex!

First post is updated again with the correct sketch!
I was looking for exactly one of these and found the schematics and sketch here. It works great, but I would like to be able to interface a button to execute the DRAM test, which I have done in the below code. But I want it to stop when it fails, I then want to be able to change the DRAM and hit the button again to start a new test. Currently with the 'While (1);' statement it will put the unit in the endless loop where you have to RESET the arduino to start a new test. I don't want to have to restart the arduino.

I have tried to remove the While statement and put in a 'return;' but that generates just a constant loop of FAILED being printed via the serial monitor and I have to reset the Arduino to stop it.

Looks like this in the serial monitor:

Code: Select all

DRAM TESTER Selected: 256K x 1 
Pass #1...
 FAILED $1
 FAILED $3
 FAILED $5
 FAILED $7
 FAILED $9
 FAILED $B
 FAILED $D
 FAILED $F
 FAILED $11
 FAILED $13
 FAILED $15
 FAILED $17
 FAILED $19
the code is below. any help would be greatly appreciated.

Code: Select all


#include <Bounce2.h>
#include <SoftwareSerial.h>

#define DI          15  // PC1
#define DO           8  // PB0
#define CAS          9  // PB1
#define RAS         17  // PC3
#define WE          16  // PC2

#define XA0         18  // PC4
#define XA1          2  // PD2
#define XA2         19  // PC5
#define XA3          6  // PD6
#define XA4          5  // PD5
#define XA5          4  // PD4
#define XA6          7  // PD7
#define XA7          3  // PD3
#define XA8         14  // PC0

#define M_TYPE      10  // PB2
#define R_LED       11  // PB3
#define G_LED       12  // PB4

#define RXD          0  // PD0
#define TXD          1  // PD1

#define BUS_SIZE     9

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 13;     // the number of the pushbutton pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 205;    // the debounce time; increase if the output flickers

/* ================================================================== */
volatile int bus_size;

//SoftwareSerial USB(RXD, TXD);

const unsigned int a_bus[BUS_SIZE] = {
  XA0, XA1, XA2, XA3, XA4, XA5, XA6, XA7, XA8
};

//-----------------------------------------------------

void setBus(unsigned int a) {
  int i;
  for (i = 0; i < BUS_SIZE; i++) {
    digitalWrite(a_bus[i], a & 1);
    a /= 2;
  }
}

void writeAddress(unsigned int r, unsigned int c, int v) {
  /* row */
  setBus(r);
  digitalWrite(RAS, LOW);

  /* rw */
  digitalWrite(WE, LOW);

  /* val */
  digitalWrite(DI, (v & 1)? HIGH : LOW);

  /* col */
  setBus(c);
  digitalWrite(CAS, LOW);

  digitalWrite(WE, HIGH);
  digitalWrite(CAS, HIGH);
  digitalWrite(RAS, HIGH);
}

int readAddress(unsigned int r, unsigned int c) {
  int ret = 0;

  /* row */
  setBus(r);
  digitalWrite(RAS, LOW);

  /* col */
  setBus(c);
  digitalWrite(CAS, LOW);

  /* get current value */
  ret = digitalRead(DO);

  digitalWrite(CAS, HIGH);
  digitalWrite(RAS, HIGH);

  return ret;
}

void error(int r, int c)
{
  unsigned long a = ((unsigned long)c << bus_size) + r;
  digitalWrite(R_LED, LOW);
  digitalWrite(G_LED, HIGH);
  interrupts();
  Serial.print(" FAILED $");
  Serial.println(a, HEX);
  Serial.flush();
  //while(1);
  return;
}

void ok(void)
{
  digitalWrite(R_LED, HIGH);
  digitalWrite(G_LED, LOW);
  interrupts();
  Serial.println(" PASSED!");
  Serial.flush();
  //while(1);
  return;
}

void blink(void)
{
  digitalWrite(G_LED, LOW);
  digitalWrite(R_LED, LOW);
  delay(1000);
  digitalWrite(R_LED, HIGH);
  digitalWrite(G_LED, HIGH);
}

void green(int v) {
  digitalWrite(G_LED, v);
}

void fill(int v) {
  int r, c, g = 0;
  v &= 1;
  for (c = 0; c < (1<<bus_size); c++) {
    green(g? HIGH : LOW);
    for (r = 0; r < (1<<bus_size); r++) {
      writeAddress(r, c, v);
      if (v != readAddress(r, c))
        error(r, c);
    }
    g ^= 1;
  }
  blink();
}

void fillx(int v) {
  int r, c, g = 0;
  v &= 1;
  for (c = 0; c < (1<<bus_size); c++) {
    green(g? HIGH : LOW);
    for (r = 0; r < (1<<bus_size); r++) {
      writeAddress(r, c, v);
      if (v != readAddress(r, c))
        error(r, c);
      v ^= 1;
    }
    g ^= 1;
  }
  blink();
}

void setup() {
  int i;
  
// initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  Serial.begin(115200);
  while (!Serial)
    ; /* wait */

  Serial.println();
  Serial.print("DRAM TESTER ");

  for (i = 0; i < BUS_SIZE; i++)
    pinMode(a_bus[i], OUTPUT);
  pinMode(CAS, OUTPUT);
  pinMode(RAS, OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(DI, OUTPUT);

  pinMode(R_LED, OUTPUT);
  pinMode(G_LED, OUTPUT);

  pinMode(M_TYPE, INPUT);
  pinMode(DO, INPUT);

  digitalWrite(WE, HIGH);
  digitalWrite(RAS, HIGH);
  digitalWrite(CAS, HIGH);

  digitalWrite(R_LED, HIGH);
  digitalWrite(G_LED, HIGH);

if (digitalRead(M_TYPE)) {
    /* jumper not set - 41256 */
    bus_size = BUS_SIZE;
    Serial.print("Selected: 256K x 1 ");
  } else {
    /* jumper set - 4164 */
    bus_size = BUS_SIZE - 1;
    Serial.print("Selected: 64K x 1 ");
  }
  Serial.flush();
  digitalWrite(R_LED, LOW);
  digitalWrite(G_LED, LOW);
  
  //noInterrupts();
  for (i = 0; i < (1 << BUS_SIZE); i++) {
    digitalWrite(RAS, LOW);
    digitalWrite(RAS, HIGH);
  }
  digitalWrite(R_LED, HIGH);
  digitalWrite(G_LED, HIGH);
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  
  if ( (millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState == LOW) {
        Serial.println("");
        interrupts(); Serial.println("Pass #1..."); Serial.flush(); noInterrupts(); fillx(0);
        interrupts(); Serial.println("Pass #2..."); Serial.flush(); noInterrupts(); fillx(1);
        interrupts(); Serial.println("Pass #3..."); Serial.flush(); noInterrupts(); fill(0);
        interrupts(); Serial.println("Pass #4..."); Serial.flush(); noInterrupts(); fill(1);
        ok();
        
        lastDebounceTime = millis(); //set the current time
      }
      else if (buttonState == HIGH) {
        lastDebounceTime = millis(); //set the current time
      }//close if/else
  
    }//close if(time buffer)
}//close void loop


Post Reply