This is my first arduino/C++ library so may not be perfect. I have a couple of 23LC1024 SRAM chips laying about and thought they may come in handy on an arduino project at some point so wrote this library. I also wrote a keywords.txt (though this does not seem to work for some reason) and an examples program to test/check the library and chips.
EDIT: The library has been updated. For changes see the history in the SpiRAM.cpp file.
EDIT: 20-Dec-2013 - Updated library to allow for non hardware SS pins.
EDIT 27-Dec-2013 - Fixed data type in test sketch.
EDIT 28-Dec-2013 - Few more tweaks.
// FILE: SpiRAM.h
// AUTHOR:
// VERSION: 0.1.00
// PURPOSE: Arduino library for the 23A1024/23LC1024 SRAM memory chip
// URL:
//
// HISTORY:
// see SpiRAM.cpp file
#ifndef SpiRAM_h
#define SpiRAM_h
// support for old IDE's
#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
#include <SPI.h>
#define SPIRAM_LIB_VERSION "0.1.00"
// SRAM Instructions
#define RDMR 5
#define WRMR 1
#define WRITE 2
#define READ 3
// SRAM modes
#define BYTE_MODE 0x00
#define PAGE_MODE 0x80
#define SEQUENTIAL_MODE 0x40
class SpiRAM {
public:
// Initialize and specify the SS pin
SpiRAM (byte ss_Pin);
// Read a single byte from address
byte readByte (long address);
// Write a single byte to address
void writeByte (long address, byte data_byte);
// Read several bytes starting at address and of length into a char buffer
void readBytes (long address, char *buffer, long length);
// Write several bytes starting at address and of length from a char buffer
void writeBytes (long address, char *buffer, long length);
// Write several bytes of value, starting at address and of length
void fillBytes (long address, byte value, long length);
private:
byte _ss_Pin;
};
#endif
// END OF FILE
you probably wnat to make addresses and lengths unsigned long as these cannot be negative.
probably a good idea to have the functions return an int to indicate number of bytes written/read
The length you probably wont often exceed 65000 bytes as buffer length so an unsigned int will do.
probably an byte for length (max 255 bytes is very workable!)
Thanks for all the suggestions Rob, as said in the original post this was my first attempt and I have only been tinkering with Arduino and C++ for 2 years so made several schoolboy errors.
you probably wnat to make addresses and lengths unsigned long as these cannot be negative.
First head slap moment, I figured because I only use 24 bit addresses the sign bit did not matter but now realize that something like a -1 would cock the whole thing up.
probably a good idea to have the functions return an int to indicate number of bytes written/read
I don't understand why you would need to do this unless the block read/write routines do bounds checking for end of memory as I don't use page mode.
The length you probably wont often exceed 65000 bytes as buffer length so an unsigned int will do.
Good point, I doubt many/any Arduinos have more than 64K of RAM.
mapped readbyte and writebyte upon multibyte calls reduces footprint
Another head slap moment. So tied up in writing the functions forgot to rationalize them.
I will try and find a RAM chip to test with and redo the library unless you want to adopt it as your own and add it to your playground article.
I have tried to implement the changes you suggested but came unravelled with type casting byte to char in the SpiRAM::readByte & SpiRAM::writeByte routines. I appear to have sussed the readByte but have no idea how to fix writeByte. Any ideas?
I have managed to get both the readByte & writeByte sorted and have renamed the readBytes/writeBytes to readBuffer/writeBuffer. All the tests seem to work okay apart from readBuffer that causes some strange corruption. It's probably something simple I'm missing as the memory seems to be written correctly but reading it back goes wrong. I had to attach a screen grab as cut & paste does not show the corruption.
Tests Begin.
Fill Memory with 0xFF.
0: FF FF FF FF FF FF FF FF FF FF
A: FF FF FF FF FF FF FF FF FF FF
14: FF FF FF FF FF FF FF FF FF FF
1E: FF FF FF FF FF FF FF FF FF FF
28: FF FF FF FF FF FF FF FF FF FF
32: FF FF FF FF FF FF FF FF FF FF
3C: FF FF FF FF FF FF FF FF FF FF
46: FF FF FF FF FF FF FF FF FF FF
50: FF FF FF FF FF FF FF FF FF FF
5A: FF FF FF FF FF FF FF FF FF FF
FF96: FF FF FF FF FF FF FF FF FF FF
FFA0: FF FF FF FF FF FF FF FF FF FF
FFAA: FF FF FF FF FF FF FF FF FF FF
FFB4: FF FF FF FF FF FF FF FF FF FF
FFBE: FF FF FF FF FF FF FF FF FF FF
FFC8: FF FF FF FF FF FF FF FF FF FF
FFD2: FF FF FF FF FF FF FF FF FF FF
FFDC: FF FF FF FF FF FF FF FF FF FF
FFE6: FF FF FF FF FF FF FF FF FF FF
FFF0: FF FF FF FF FF FF FF FF FF FF
Fill Memory with 0xAA.
0: AA AA AA AA AA AA AA AA AA AA
A: AA AA AA AA AA AA AA AA AA AA
14: AA AA AA AA AA AA AA AA AA AA
1E: AA AA AA AA AA AA AA AA AA AA
28: AA AA AA AA AA AA AA AA AA AA
32: AA AA AA AA AA AA AA AA AA AA
3C: AA AA AA AA AA AA AA AA AA AA
46: AA AA AA AA AA AA AA AA AA AA
50: AA AA AA AA AA AA AA AA AA AA
5A: AA AA AA AA AA AA AA AA AA AA
FF96: AA AA AA AA AA AA AA AA AA AA
FFA0: AA AA AA AA AA AA AA AA AA AA
FFAA: AA AA AA AA AA AA AA AA AA AA
FFB4: AA AA AA AA AA AA AA AA AA AA
FFBE: AA AA AA AA AA AA AA AA AA AA
FFC8: AA AA AA AA AA AA AA AA AA AA
FFD2: AA AA AA AA AA AA AA AA AA AA
FFDC: AA AA AA AA AA AA AA AA AA AA
FFE6: AA AA AA AA AA AA AA AA AA AA
FFF0: AA AA AA AA AA AA AA AA AA AA
Fill Memory with Buffer.
0: 41 42 43 44 45 46 47 48 49 4A
A: 41 42 43 44 45 46 47 48 49 4A
14: 41 42 43 44 45 46 47 48 49 4A
1E: 41 42 43 44 45 46 47 48 49 4A
28: 41 42 43 44 45 46 47 48 49 4A
32: 41 42 43 44 45 46 47 48 49 4A
3C: 41 42 43 44 45 46 47 48 49 4A
46: 41 42 43 44 45 46 47 48 49 4A
50: 41 42 43 44 45 46 47 48 49 4A
5A: 41 42 43 44 45 46 47 48 49 4A
FF96: 41 42 43 44 45 46 47 48 49 4A
FFA0: 41 42 43 44 45 46 47 48 49 4A
FFAA: 41 42 43 44 45 46 47 48 49 4A
FFB4: 41 42 43 44 45 46 47 48 49 4A
FFBE: 41 42 43 44 45 46 47 48 49 4A
FFC8: 41 42 43 44 45 46 47 48 49 4A
FFD2: 41 42 43 44 45 46 47 48 49 4A
FFDC: 41 42 43 44 45 46 47 48 49 4A
FFE6: 41 42 43 44 45 46 47 48 49 4A
FFF0: 41 42 43 44 45 46 47 48 49 4A
Read Buffer.
ABCDEFG??
FGHIJABC?
Write byte.
0: 0 0 0 0 0 0 0 0 0 0
A: 1 1 1 1 1 1 1 1 1 1
14: 2 2 2 2 2 2 2 2 2 2
1E: 3 3 3 3 3 3 3 3 3 3
28: 4 4 4 4 4 4 4 4 4 4
32: 5 5 5 5 5 5 5 5 5 5
3C: 6 6 6 6 6 6 6 6 6 6
46: 7 7 7 7 7 7 7 7 7 7
50: 8 8 8 8 8 8 8 8 8 8
5A: 9 9 9 9 9 9 9 9 9 9
FF96: F F F F F F F F F F
FFA0: 10 10 10 10 10 10 10 10 10 10
FFAA: 11 11 11 11 11 11 11 11 11 11
FFB4: 12 12 12 12 12 12 12 12 12 12
FFBE: 13 13 13 13 13 13 13 13 13 13
FFC8: 14 14 14 14 14 14 14 14 14 14
FFD2: 15 15 15 15 15 15 15 15 15 15
FFDC: 16 16 16 16 16 16 16 16 16 16
FFE6: 17 17 17 17 17 17 17 17 17 17
FFF0: 18 18 18 18 18 18 18 18 18 18
Tests Finished.
NO need to call this library my own, but you might add a line in the history to refer to my contribution
The return values can be useful in the future, when you use blocktransfers. As said it are just tips that might help to improve the lib.
Negative values for addresses are used sometimes to define an address from the end backwards. [e.g. Python ]
So writeBUffer(-10, "hello", 5) would write to 0xFFF6 and further.
Negative values for length, maybe in a hyperdrive for a starship
More serious, strange error, As i do not have the chip I cannot test it, but I will scrutinize the test code if I see something that can explain the 'bug'
ReadBuffer() code does CORRECTLY not add a terminating zero after the char array to end the 'string'.
Serial.println(buffer2) will print until it finds a \0 in memory.
you can confirm this by printing the strlen(buffer2) to see if the length == length read.
robtillaart:
ReadBuffer() code does CORRECTLY not add a terminating zero after the char array to end the 'string'.
Serial.println(buffer2) will print until it finds a \0 in memory.
you can confirm this by printing the strlen(buffer2) to see if the length == length read.
I trimmed down the test sketch a bit.
#include <SPI.h>
#include <SpiRAM.h>
const uint16_t ramSize = 0x1FFFF; // 128K x 8 bit
const byte LED = 13;
char buffer[] = {"ABCDEFGHIJ"};
char buffer2[sizeof(buffer)];
SpiRAM sRam(SS); // Initialize the RAM with SS
void setup(){
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW); // Turn off LED (Mega LED stays on else)
Serial.begin(115200);
Serial.println("Tests Begin.");
Serial.println("\r\nFill Memory with Buffer.");
for (uint32_t x = 0; x < ramSize - sizeof(buffer); x += sizeof(buffer) - 1){
sRam.writeBuffer(x, buffer, sizeof(buffer) - 1);
}
dumpSRAM(0UL,100);
Serial.println("\r\nRead Buffer. ");
Serial.print("sizeof(buffer2) = ");
Serial.print(sizeof(buffer2));
Serial.print("\tstrlen(buffer2) = ");
Serial.println(strlen(buffer2));
sRam.readBuffer(0UL,buffer2,sizeof(buffer2) - 1);
Serial.print("Serial.println(buffer2); = ");
Serial.println(buffer2);
Serial.print("sizeof(buffer2) = ");
Serial.print(sizeof(buffer2));
Serial.print("\tstrlen(buffer2) = ");
Serial.println(strlen(buffer2));
Serial.print("One at a time = ");
for(byte y = 0; y < sizeof(buffer2); y++){
char z = buffer2[y];
Serial.print(z);
}
Serial.println();
Serial.print("(byte)buffer[10] = ");
Serial.println((byte)buffer[10]);
Serial.println("\r\nTests Finished.");
}
void loop(){
}
void dumpSRAM(uint32_t addr, uint16_t length)
{
// block to 10
addr = addr / 10 * 10;
length = (length + 9)/10 * 10;
byte b = sRam.readByte(addr);
for (int i = 0; i < length; i++)
{
if (addr % 10 == 0)
{
Serial.println();
Serial.print(addr, HEX);
Serial.print(":\t");
}
Serial.print(b, HEX);
b = sRam.readByte(++addr);
Serial.print(" ");
}
Serial.println();
}
void dumpSRAM2(uint32_t addr, uint16_t length)
{
// block to 10
addr = addr / 10 * 10;
length = (length + 9)/10 * 10;
char b = sRam.readByte(addr);
for (int i = 0; i < length; i++)
{
if (addr % 10 == 0)
{
Serial.println();
Serial.print(addr);
Serial.print(":\t");
}
Serial.print(b);
b = sRam.readByte(++addr);
Serial.print(" ");
}
Serial.println();
}
but despite strlen being correct the result is still wrong. (See attached Clipboard1 image)
Some extra debug code in the readBuffer routine show the reading is corrupt.
Finally after spending so much time on this the problem seemed to be due to SPI speed. Adjusted the clock down to SPI_CLOCK_DIV8 and it works fine now.
I will repackage the zip file and replace one in first post with it.
if buffer has 10 elements their indices go from 0..9 !
Riva:
Finally after spending so much time on this the problem seemed to be due to SPI speed. Adjusted the clock down to SPI_CLOCK_DIV8 and it works fine now.
I will repackage the zip file and replace one in first post with it.
Should be in the datasheet .
What is the write latency of the EEPROM? (the time after a write the eeprom cannot accept commands)
if buffer has 10 elements their indices go from 0..9 !
But I wanted to confirm the string terminator had not been overwritten.
Riva:
Finally after spending so much time on this the problem seemed to be due to SPI speed. Adjusted the clock down to SPI_CLOCK_DIV8 and it works fine now.
Should be in the datasheet .
What is the write latency of the EEPROM? (the time after a write the eeprom cannot accept commands)
SRAM not EEPROM, the timings are all in the sub 100ns range and the chip should be able to handle 20MHz. I suspect it's an arduino thing and not a SRAM thing as the original library was written and tested on an UNO but now I'm using a MEGA to test and it fails with original library code. I arrived at the SPI speed because I had tried inserting delays in readBuffer and that increased the errors.
hey Riva,
I'm afread your lib with test script doesn't work on my Mega 2560. I've been trying to debug it but I get nowhere... All that I get as return is FF. at first I thought the problem was the buffer but when I removed it, the problem persisted.
MathiasVDA:
hey Riva,
I'm afread your lib with test script doesn't work on my Mega 2560. I've been trying to debug it but I get nowhere... All that I get as return is FF. at first I thought the problem was the buffer but when I removed it, the problem persisted.
What version of the Arduino IDE are you using? I tested it with my Mega2560 okay on 1.0.5
From the changes you made to get it to work it looks like the SS pin is not being defined properly. What value for SS get printed if you run the below sketch?
MathiasVDA:
I've got 2 of thoose RAM chips. One with SS on 30 and one on 32. I've adjusted the script accordingly with no success. I'll debug some more tonight.
Just for your information: Ive been writing that script in my previous post myself before I knew of this lib. Some problems I've had with them before:
Setting the SS pin to high in setup()
Putting 'byte' before SRAM_READ and iunt_8 before the return variable
Right, I think I see what the problem was. I had not allowed for non standard (hardware) SS pins. I have altered the library and the test sketch (zip file attached to first post in this thread) and testing it with my Mega using pin 9 as SS works fine (have also tested it using pin 30 but UNO does not have a pin 30 so altered test sketch to use 9 instead)