Hi John,
The cost of an R3 isn’t bad at all and since this is going to be a dedicated project, leaving the R3 attached would free up my R4 for other things.
I like the idea of using the R3.
Thanks!
Hi John,
The cost of an R3 isn’t bad at all and since this is going to be a dedicated project, leaving the R3 attached would free up my R4 for other things.
I like the idea of using the R3.
Thanks!
The code just needs 4 lines amending to make it compile with IDR 1.8.19 or 2.3.6.
Did you want me to post the code that compiles, or can you work it out from the information I gave in post #10?
That would be very helpful, thank you!
Here's the modified code that will compile for an Uno R3.
// Rough-and-ready Arduino code for testing, calibrating and using core memory shield.
//
// Copyright 2011 Ben North and Oliver Nash.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ADDRSIZE 5
#define WORDSIZE (1 << ADDRSIZE)
#define ENABLE B00000100 // PORTD
#define DRD B00000010 // PORTB
#define DWR B00000001 // PORTB
static unsigned int WRITE_ON_US = 2;
static unsigned int WRITE_OFF_US = 2; // May not be necessary.
static unsigned long errs = 0;
static unsigned int sense_test_addr = 0;
static int n_test_iters = 1000;
static char report_errors_p = 0;
static char trace_core_calls_p = 0;
void write_bit(byte n, const int v)
{
if (trace_core_calls_p)
{
char buf[64];
sprintf(buf, "x[0%02o] <- %d", n, v);
Serial.println(buf);
}
// Assert 0 <= n <= 31, v == 0 or 1.
noInterrupts();
if(v == 0)
{
PORTB &= (~DWR);
}
else
{
PORTB |= DWR;
}
PORTD = ((n << 3) & (~ENABLE));
PORTD |= ENABLE; // Enable separately to be safe.
delayMicroseconds(WRITE_ON_US);
PORTD &= (~ENABLE);
delayMicroseconds(WRITE_OFF_US);
interrupts();
}
int exchg_bit(byte n, const int v)
{
write_bit(n, v);
if(PINB & DRD)
{
// Switching occurred so core held opposite of
// what we just set it to.
if (trace_core_calls_p)
Serial.println("___ -> CHANGE");
return !v;
}
else
{
// No switching occurred so core held whatever
// we just wrote to it.
if (trace_core_calls_p)
Serial.println("___ -> NO-CHANGE");
return v;
}
}
int read_bit(const int n)
{
char buf[64];
if (trace_core_calls_p)
{
sprintf(buf, "x[0%02o] -> ___", n);
Serial.println(buf);
}
write_bit(n, 0);
if(PINB & DRD)
{
// Switching occurred so core held 1.
if (trace_core_calls_p)
Serial.println("___ -> 1");
write_bit(n, 1); // Put it back!
return 1;
}
else
{
// No switching occurred so core held 0 (and still holds it).
if (trace_core_calls_p)
Serial.println("___ -> 0");
return 0;
}
}
void write_word(unsigned long v)
{
int n;
for(n = 0; n < WORDSIZE; n++)
{
write_bit(n, v & 1);
v >>= 1;
}
}
unsigned long read_word(void)
{
unsigned long v = 0;
int n;
for(n = WORDSIZE-1; n >= 0; n--)
{
v <<= 1;
v |= read_bit(n);
}
return v;
}
unsigned long exchg_word(unsigned long v)
{
unsigned long v_prev;
int n;
for (n = 0; n < WORDSIZE; ++n)
{
unsigned long b = exchg_bit(n, v & 1);
v >>= 1;
v_prev >>= 1;
v_prev |= (b << 31);
}
return v_prev;
}
static void maybe_report_error(int i, int j, const char * lbl)
{
char buf[64];
if (!report_errors_p)
return;
sprintf(buf, "(%o, %o): %s", i, j, lbl);
Serial.println(buf);
}
static void toggle_error_reporting()
{
char buf[64];
report_errors_p = !report_errors_p;
sprintf(buf, "report-errors-p now %d", report_errors_p);
Serial.println(buf);
}
static void toggle_tracing()
{
char buf[64];
trace_core_calls_p = !trace_core_calls_p;
sprintf(buf, "trace-core-calls-p now %d", trace_core_calls_p);
Serial.println(buf);
}
static void current_calibration()
{
Serial.print("pulsing for current calibration...");
while (Serial.available() == 0)
{
int i;
for (i = 0; i < WORDSIZE; ++i)
{
write_bit(i, 0);
write_bit(i, 1);
}
delayMicroseconds(100);
}
Serial.println(" stopped");
Serial.read(); /* discard typed character */
}
static void timing_exchange_word()
{
unsigned long val_0 = read_word();
unsigned long i;
Serial.print("start...");
for (i = 0; i < 12000; ++i)
{
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
exchg_word(val_0);
}
Serial.println("stop");
}
static void echo_comment()
{
Serial.print("# ");
char c;
do {
while (Serial.available() == 0);
c = Serial.read();
//Serial.print(c, BYTE);
Serial.write(c);
} while (c != '\r');
Serial.println("");
}
static void corewise_set_test()
{
char buf[64];
for (int b = 0; b < 2; ++b)
{
errs = 0;
for (int n = 0; n < n_test_iters; ++n)
for (int i = 0; i < WORDSIZE; ++i)
{
write_bit(i, b);
if (read_bit(i) != b) ++errs;
}
sprintf(buf, "set %d %lu %d", b, errs, n_test_iters);
Serial.println(buf);
}
}
static void corewise_interfere_test()
{
char buf[64];
for (int b0 = 0; b0 < 2; ++b0)
{
for (int b1 = 0; b1 < 2; ++b1)
{
errs = 0;
for (int n = 0; n < n_test_iters; ++n)
{
for (int i = 0; i < WORDSIZE; ++i)
{
for (int j = 0; j < WORDSIZE; ++j)
{
if (j == i) continue;
write_bit(i, b0);
write_bit(j, b1);
if (read_bit(i) != b0) {
if (report_errors_p)
{
// Redundant test but sprintf() takes time.
sprintf(buf, "%d %d", b0, b1);
maybe_report_error(i, j, buf);
}
++errs;
}
}
}
}
sprintf(buf, "interfere %d %d %lu %d", b0, b1, errs, n_test_iters);
Serial.println(buf);
}
}
}
static void corewise_tests()
{
corewise_set_test();
corewise_interfere_test();
}
static void R_test()
{
unsigned long d = read_word();
Serial.print("Core data read: 0x");
Serial.print(d, HEX);
Serial.print(" = B");
Serial.println(d, BIN);
}
static void s_test()
{
char buf[64];
write_bit(sense_test_addr, 0);
write_bit(sense_test_addr, 0);
write_bit(sense_test_addr, 1);
write_bit(sense_test_addr, 1);
sprintf(buf, "Pulsed core 0%02o", sense_test_addr);
Serial.println(buf);
}
static void report_sense_addr()
{
char buf[64];
sprintf(buf, "Ready to pulse core 0%02o", sense_test_addr);
Serial.println(buf);
}
static void a_test()
{
sense_test_addr += 1;
sense_test_addr %= 32;
report_sense_addr();
}
static void A_test()
{
sense_test_addr -= 1;
sense_test_addr %= 32;
report_sense_addr();
}
static void W_test()
{
int i, x;
unsigned long d = 0;
Serial.print("Please enter 8 hexadecimal digits: ");
for(i = 0; i < 8; i++)
{
d <<= 4;
while(Serial.available() == 0) ;
x = Serial.read();
if('0' <= x && x <= '9')
{
d += x - '0';
}
else if('A' <= x && x <= 'F')
{
d += x - 'A' + 10;
}
else if('a' <= x && x <= 'f')
{
d += x - 'a' + 10;
}
else
{
Serial.print("Assuming 0 for non-hexadecimal digit: ");
// Serial.println(x, BYTE);
Serial.write(x);
Serial.println("");
}
}
write_word(d);
Serial.print("\r\nCore data write: 0x");
Serial.print(d, HEX);
Serial.print(" = B");
Serial.println(d, BIN);
}
static void X_test()
{
char buf[64];
int i, x;
unsigned long d1, d = 0;
Serial.print("Please enter 8 hexadecimal digits: ");
for(i = 0; i < 8; i++)
{
d <<= 4;
while(Serial.available() == 0) ;
x = Serial.read();
if('0' <= x && x <= '9')
{
d += x - '0';
}
else if('A' <= x && x <= 'F')
{
d += x - 'A' + 10;
}
else if ('a' <= x && x <= 'f')
{
d += x - 'a' + 10;
}
else
{
Serial.print("Assuming 0 for non-hexadecimal digit: ");
// Serial.println(x, BYTE);
Serial.write(x);
Serial.println("");
}
}
d1 = exchg_word(d);
Serial.print("\r\nCore data write: 0x");
sprintf(buf, "%08lx; read 0x%08lx", d, d1);
Serial.println(buf);
}
static void r_test()
{
int i, x, a = 0;
Serial.print("Please enter address of bit to read: ");
for(i = 0; i < ADDRSIZE; i++)
{
a <<= 1;
while(Serial.available() == 0) ;
x = Serial.read();
if(x != '0') // Assert x == '1'
{
a += 1;
}
}
Serial.print("\r\nCore data read from address: ");
Serial.print(a, BIN);
Serial.print(" found: ");
Serial.println(read_bit(a));
}
static void w_test()
{
int i, x, a = 0;
Serial.print("Please enter address of bit to write: ");
for(i = 0; i < ADDRSIZE; i++)
{
a <<= 1;
while(Serial.available() == 0) ;
x = Serial.read();
if(x != '0') // Assert x == '1'
{
a += 1;
}
}
Serial.print("\r\nPlease enter bit to write: ");
while(Serial.available() == 0) ;
x = Serial.read();
Serial.print("\r\nCore data write to address: ");
Serial.print(a, BIN);
Serial.print(" value: ");
if(x == '0')
{
write_bit(a, 0);
Serial.println("0");
}
else // Assert x == '1'
{
write_bit(a, 1);
Serial.println("1");
}
}
static void t_test()
{
int i;
unsigned long d;
for(i = 0; i < WORDSIZE; i++)
{
write_bit(i, 0);
d = read_bit(i);
Serial.print("Address (");
Serial.print(i >> 3);
Serial.print(i & 7);
Serial.print(") ");
Serial.print(i, BIN);
Serial.print(" wrote 0 read ");
Serial.print(d);
write_bit(i, 1);
d = read_bit(i);
Serial.print(" wrote 1 read ");
Serial.println(d);
}
}
static void T_test()
{
unsigned long d;
int i, j;
Serial.print("log10(iters)? ");
while(Serial.available() == 0) ;
int n = Serial.read() - '0';
if (n < 0 || n > 9)
Serial.println("bad power-of-10 arg to T");
else
{
unsigned long n_iters = 1, n_iters_done = 0;
while (n--) n_iters *= 10;
errs = 0;
for (n_iters_done = 0; n_iters_done < n_iters; ++n_iters_done)
{
for(i = 0; i < WORDSIZE; i++)
{
for(j = 0; j < WORDSIZE; j++)
{
if(j == i) { continue; }
write_bit(i, 0);
d = read_bit(i);
if(d != 0) { errs++; maybe_report_error(i, j, "0-0"); }
d = read_bit(i);
if(d != 0) { errs++; maybe_report_error(i, j, "0-1"); }
write_bit(i, 0);
write_bit(j, 0);
d = read_bit(i);
if(d != 0) { errs++; maybe_report_error(i, j, "000"); }
d = read_bit(i);
if(d != 0) { errs++; maybe_report_error(i, j, "001"); }
write_bit(i, 0);
write_bit(j, 1);
d = read_bit(i);
if(d != 0) { errs++; maybe_report_error(i, j, "010"); }
d = read_bit(i);
if(d != 0) { errs++; maybe_report_error(i, j, "011"); }
write_bit(i, 1);
d = read_bit(i);
if(d != 1) { errs++; maybe_report_error(i, j, "1-0"); }
d = read_bit(i);
if(d != 1) { errs++; maybe_report_error(i, j, "1-1"); }
write_bit(i, 1);
write_bit(j, 0);
d = read_bit(i);
if(d != 1) { errs++; maybe_report_error(i, j, "100"); }
d = read_bit(i);
if(d != 1) { errs++; maybe_report_error(i, j, "101"); }
write_bit(i, 1);
write_bit(j, 1);
d = read_bit(i);
if(d != 1) { errs++; maybe_report_error(i, j, "110"); }
d = read_bit(i);
if(d != 1) { errs++; maybe_report_error(i, j, "111"); }
}
}
if (n_iters_done % 100 == 0)
{
Serial.print(n_iters_done, DEC);
Serial.print(" iters; ");
Serial.print(errs, DEC);
Serial.println(" errors");
}
}
Serial.print(n_iters_done, DEC);
Serial.print(" iters; ");
Serial.print(errs, DEC);
Serial.println(" errors");
}
}
static void U_test()
{
unsigned long n_iters_done = 0;
unsigned long prev_datum = 0UL;
errs = 0;
write_word(prev_datum);
while (1)
{
if (Serial.available() > 0)
{
(void)Serial.read();
Serial.println("stopping");
break;
}
unsigned rnd_0 = random(0x10000);
unsigned rnd_1 = random(0x10000);
unsigned long rnd = (unsigned long)(rnd_1) << 16 | rnd_0;
unsigned long read_datum = exchg_word(rnd);
// sprintf(buf, "rnd %08lx; read %08lx", rnd, read_datum);
// Serial.println(buf);
if (read_datum != prev_datum)
++errs;
prev_datum = rnd;
if (n_iters_done % 20000 == 0)
{
char buf[64];
sprintf(buf, "%lu iters-done; %lu errors", n_iters_done, errs);
Serial.println(buf);
}
++n_iters_done;
}
}
void setup(void)
{
DDRD |= B11111100;
PORTD = (~ENABLE);
DDRB |= DWR;
DDRB &= (~DRD);
Serial.begin(115200);
randomSeed(0xdeadbeef);
Serial.println("Welcome! If you're new, try using the commands 'r', 'w', 't' and 'R', 'W', 'T' to get started.");
}
void loop(void)
{
byte c;
if(Serial.available() > 0)
{
c = Serial.read();
switch(c)
{
case 'c':
current_calibration();
break;
case '#':
echo_comment();
break;
case 'e':
corewise_tests();
break;
case 'v':
toggle_tracing();
break;
case 'f':
toggle_error_reporting();
break;
case 'm':
timing_exchange_word();
break;
case 'R':
R_test();
break;
case 's':
s_test();
break;
case 'a':
a_test();
break;
case 'A':
A_test();
break;
case 'W':
W_test();
break;
case 'X':
X_test();
break;
case 'r':
r_test();
break;
case 'w':
w_test();
break;
case 't':
t_test();
break;
case 'T':
T_test();
break;
case 'U':
U_test();
break;
case 'z':
errs = 0;
Serial.println("error-count = 0");
break;
default:
Serial.print("Ignoring unknown command: ");
Serial.print(c, HEX);
Serial.print(" ");
// Serial.println(c, BYTE);
Serial.write(c);
Serial.println("");
}
}
}
Thanks John, that’s super helpful! I’ll get the R3 on order and give it a try (o-scope the pins while I’m waiting on the pcb’s and parts to arrive).
Before trying IDE 1.8.19, I put your code into 2.3.6 and it compiled without issues and the serial monitor shows the program running.
I’ll put it on the o-scope tomorrow and see how it looks.
Thanks for all your help!