DRAMARDUINO - Dram tester with Arduino
DRAMARDUINO - Dram tester with Arduino
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 .
EDIT 2020-10-29: Sketch fixed!
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 .
EDIT 2020-10-29: Sketch fixed!
Last edited by iss on Thu Oct 29, 2020 7:35 pm, edited 2 times in total.
Re: DRAMARDUINO - Dram tester with Arduino
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 CEO forum.
Have a good day !
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 CEO forum.
Have a good day !
Oric Atmos : a new life !
Re: DRAMARDUINO - Dram tester with Arduino
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.
I'm very glad that you liked this little tool and I'll be really happy if you share it on CEO forum.
Re: DRAMARDUINO - Dram tester with Arduino
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.
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.
Re: DRAMARDUINO - Dram tester with Arduino
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.
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
void setBus(unsigned int a) {
int i;
for (i = 0; i < BUS_SIZE; i++) {
digitalWrite(a_bus[i], a % 1);
a /= 2;
}
}
Code should be changed to:
Code: Select all
digitalWrite(a_bus[i], a % 2);
- HigashiJun
- Flying Officer
- Posts: 205
- Joined: Tue Dec 10, 2019 9:29 am
- Location: Tokyo (Japan)
Re: DRAMARDUINO - Dram tester with Arduino
Interesting...
I will give it a try on my DRAMARDUINO.
Thanks.
I will give it a try on my DRAMARDUINO.
Thanks.
HigashiJun
Re: DRAMARDUINO - Dram tester with Arduino
Wow, nice catch. Interesting is that in my local file it's:
Maybe I've uploaded something preliminary...
First post is now updated with the correct sketch!
Code: Select all
digitalWrite(a_bus[i], a & 1);
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.
Re: DRAMARDUINO - Dram tester with Arduino
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..."
I replaced each function's second line containing
with
to get the lower bit of v and I believe it solves the problem.
Anyway, thank you again for sharing this nice project.
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();
}
Code: Select all
v %= 1;
Code: Select all
v &= 1;
Anyway, thank you again for sharing this nice project.
Re: DRAMARDUINO - Dram tester with Arduino
Re: DRAMARDUINO - Dram tester with Arduino
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.iss wrote: ↑Thu Oct 29, 2020 7:37 pmThank you for reporting @thekorex!
First post is updated again with the correct sketch!
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
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
Re: DRAMARDUINO - Dram tester with Arduino
Hello all,
Came across this forum and topic while searching for an easy solution with Arduino to test DRAM's. Seemed like what I need, so I built it. It's working and it can identify bad chips that I have. I am relatively new to Arduino and by no means a programmer, I could only make heads and tails of 60% of the code so far, I need to learn bit banging and the operators related to get it all, I know. But still something seems strange to me, if anyone can explain why, I will be grateful. There is a pin to select 4164 and 41256 chips that changes the bus size variable accordingly, so far so good, but if I put a 4164 and test it as 41256, it still passes OK, and strangely it also takes as long as a real 41256. Shouldn't it sort of "hit a wall" and return an error when the address incrementing loop goes over XA7 and come to a non-existent XA8 bit?
This may be a very stupid question but please bear with me and explain as plainly as possible why this happens?
Thanks!
Came across this forum and topic while searching for an easy solution with Arduino to test DRAM's. Seemed like what I need, so I built it. It's working and it can identify bad chips that I have. I am relatively new to Arduino and by no means a programmer, I could only make heads and tails of 60% of the code so far, I need to learn bit banging and the operators related to get it all, I know. But still something seems strange to me, if anyone can explain why, I will be grateful. There is a pin to select 4164 and 41256 chips that changes the bus size variable accordingly, so far so good, but if I put a 4164 and test it as 41256, it still passes OK, and strangely it also takes as long as a real 41256. Shouldn't it sort of "hit a wall" and return an error when the address incrementing loop goes over XA7 and come to a non-existent XA8 bit?
This may be a very stupid question but please bear with me and explain as plainly as possible why this happens?
Thanks!
- mikeb
- Flight Lieutenant
- Posts: 282
- Joined: Wed Sep 05, 2018 8:03 pm
- Location: West Midlands, UK
- Contact:
Re: DRAMARDUINO - Dram tester with Arduino
Hello!
I suspect what you're doing is testing the 4164 completely, four times.
The extra XA8 bit has nowhere to go when testing a 4164, so each row and column address would effectively ignore the upper bit, meaning the count would loop from 65535 back to 0 -- ignoring the upper bit of a binary count doubles the possible addresses.
Because the 8 bit addresses are being used for rows, then columns, you end up with a double count, twice -- i.e. four times.
A similiar thing happens if you read a 2764 EPROM as a 27128 (you end up with two identical sets of data, end to end, not: expected valid data followed by tumbleweeds!)
Re: DRAMARDUINO - Dram tester with Arduino
Indeed! @mikeb's answer explains very good what happens. Here are 4164 and 41256:
the test is repeated 4 times. Additionally from the 'schematics' you can see that the jumper doesn't have any 'electrical' meaning and is used only to 'tell' the software that it has to include the address line A8 in the testing cycle too and so testing time is 4 times longer (per every test). Of course it's possible also autodetection .
As you can see in 4164 pin-1 is NC (Not Connected) internally, so for 4164 it really doesn't matter what logic level you put on it -the test is repeated 4 times. Additionally from the 'schematics' you can see that the jumper doesn't have any 'electrical' meaning and is used only to 'tell' the software that it has to include the address line A8 in the testing cycle too and so testing time is 4 times longer (per every test). Of course it's possible also autodetection .
- mikeb
- Flight Lieutenant
- Posts: 282
- Joined: Wed Sep 05, 2018 8:03 pm
- Location: West Midlands, UK
- Contact:
Re: DRAMARDUINO - Dram tester with Arduino
... further thought!
In an actual Oric, the memory test relies on this "missing address line" situation to distinguish between a 4164 (64k/48k Oric) and a 4116 (16k Oric) bank
With the quarter size DRAM chip (16K), now there is nowhere for A7 to go. So whether the row/col address bit 7 is high or low, you get the SAME location in memory based on bits 0..6
The RAM test writes to one location (#4500), reads back from a different one (#0500), and if it works, concludes it's only a 16K Oric (because the memory map wraps around 4 times from #0000-#3FFF, #4000-#7FFF, #8000-#BFFF, and #C000-#FFFF).
In an actual Oric, the memory test relies on this "missing address line" situation to distinguish between a 4164 (64k/48k Oric) and a 4116 (16k Oric) bank
With the quarter size DRAM chip (16K), now there is nowhere for A7 to go. So whether the row/col address bit 7 is high or low, you get the SAME location in memory based on bits 0..6
The RAM test writes to one location (#4500), reads back from a different one (#0500), and if it works, concludes it's only a 16K Oric (because the memory map wraps around 4 times from #0000-#3FFF, #4000-#7FFF, #8000-#BFFF, and #C000-#FFFF).
Possible, but caution applies -- if you "auto detect and test" a working 41256 with pin 1 snapped off, won't you get told it's a "working 4164"?