/*
* Demo program for accessing Microchip 23lc1023 SPI SRAM chip
* using low-level bit-banged IO and Arduino environment.
*
* Written Sep, 2022 by Bill Westfield
* Released to the public domain.
*/
#define P_CS 10
#define P_SCK 13
#define P_IN 11
#define P_OUT 12
/*
* how big is the memory? The part numbers usually specify
* size in kbits (23lc1024 is 1024 kbits, but we mostly
* want bytes for our use.
*/
#define MEMSIZE_BITS (1024UL*1024) // 1024 kbits
#define MEMSIZE_BYTES (MEMSIZE_BITS/8) // 8 bits/byte
/*
* Pick a range of memory addresses for the test step.
*/
#define STARTADDR 0 // (MEMSIZE_BYTES - 123)
#define ENDADDR 123 // (MEMSIZE_BYTES - 50)
/*
* Top level functions
*/
void writeByte(uint32_t addr, uint8_t data) {
chipEnable();
writeInstr(2);
writeAddr(addr);
writeData(data);
chipOff();
}
uint8_t readByte(uint32_t addr) {
uint8_t inByte = 0;
chipEnable();
writeInstr(3);
writeAddr(addr);
for (byte i = 0; i < 8; i++) { // read 8 bits
inByte <<= 1; // Shift
inByte |= readBit(); // or in the next bit
}
chipOff();
return inByte;
}
void showMode() {
chipEnable();
writeBit(0); // send command "0x05", one bit at a time for
writeBit(0); // explicit clarity...
writeBit(0);
writeBit(0);
//
writeBit(0);
writeBit(1);
writeBit(0);
writeBit(1);
// "Read Mode" command has been sent - now show the results
Serial.print("\nMode is 0b");
Serial.print(readBit()); // Likewise, read one bit at a time.
Serial.print(readBit());
Serial.print(readBit());
Serial.print(readBit());
//
Serial.print(readBit());
Serial.print(readBit());
Serial.print(readBit());
Serial.print(readBit());
Serial.println();
chipOff();
}
void clearBytes(uint32_t start, uint32_t l) {
uint32_t i;
for (i = 0; i < l; i++) {
if ((i & 0xFF) == 0) {
Serial.print(".");
if ((i & 0x3FFF) == 0) {
Serial.println();
}
}
writeByte(start + i, 0);
}
Serial.println();
}
/*
* Low level functions
*/
void writeInstr(uint8_t inst) {
// Start with bit 7 and write all 8 bits.
for (uint8_t mask = 1 << 7; mask != 0; mask >>= 1) {
if (inst & mask) {
writeBit(1);
} else {
writeBit(0);
}
}
}
void writeData(uint8_t data) {
writeInstr(data); // writing data is the same as writing an instruction!
}
void writeAddr(uint32_t addr) {
// start with bit 23 and send all 24 bits.
for (uint32_t mask = 1UL << 23; mask != 0; mask >>= 1) { // 24 bits to write
if (addr & mask) {
writeBit(1);
} else {
writeBit(0);
}
}
}
void chipEnable() {
digitalWrite(P_CS, LOW);
}
void chipOff() {
digitalWrite(P_CS, HIGH);
}
void clockHigh() {
digitalWrite(P_SCK, HIGH);
}
void clockLow() {
digitalWrite(P_SCK, LOW);
}
void toggleClock() {
clockHigh();
clockLow();
}
/*
* Individual bits are clocked into or out of the RAM
* on the rising edge of the clock. The "default" state of
* clock is low, so writing a bit means setting the data pin,
* raising the clock, and lowering the clock again for the next bit.
* Reading a bit means raising the clock, reading the bit, and then
* lowering the clock again.
*/
void writeBit(bool bitVal) {
// write the data bit and clock it.
digitalWrite(P_OUT, bitVal);
toggleClock();
}
bool readBit() {
// read bits while clock is high.
clockHigh();
bool temp = digitalRead(P_IN);
clockLow();
return temp;
}
/*
* Sketch
*/
void setup() {
pinMode(P_OUT, OUTPUT); // Pin initialization
pinMode(P_IN, INPUT);
pinMode(P_SCK, OUTPUT); clockLow();
pinMode(P_CS, OUTPUT); chipOff();
Serial.begin(115200);
Serial.print("\n23LC1024 bit-banged SPI test\n");
Serial.println("Clearing Memory");
uint32_t startTime = millis();
clearBytes(0, MEMSIZE_BYTES); // zero all of the memory
Serial.print("(Cleared: ");
Serial.print((millis() - startTime) / 1000UL);
Serial.println(" seconds!)");
}
void loop() {
delay(1000);
showMode();
Serial.println("Writing data");
for (uint32_t addr = STARTADDR; addr < ENDADDR; addr += 5) {
// write value == address for easy visual check
writeByte(addr, (uint8_t) addr & 0xff);
Serial.print(addr);
Serial.print(": ");
Serial.println(addr & 0xFF);
}
Serial.println("Reading Data");
for (uint32_t addr = STARTADDR; addr < ENDADDR; addr += 1) {
uint8_t v = readByte(addr);
if (v != 0) { // Only show the non-zero values.
Serial.print(addr);
Serial.print(": ");
Serial.println((uint32_t)v);
}
}
Serial.println("Hit any key to run again");
while (Serial.read() < 0) {
// wait for key to continue
}
}
1 Like