Hi. Sorry if this is the wrong forum category - I have been puzzling where to post this question for the past 10 mins.
I am trying to interface with two AS6C4008 4Mbit SRAM chips. Datasheet Here
I have 2 of these chips with the same address lines attached to each so that I can retrieve 2 lots of 8 bits per "row address".
I am doing this:
- writing to address 0,
- reading address 0 (data is correct)
- reading address 2 (don't care about data returned)
- reading address 0 again (data is different)
Can somebody please help me with this? I've been staring at the timing diagrams and cannot see what I'm doing wrong. I have a similar setup with an FPGA but I had a few problems there and thought it would be easier to test out operation using Ardunio Mega instead.
Below is my sketch.
// A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18
const char ADDR[] = { 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40};
const char DATAH[] = { 41, 42, 43, 44, 45, 46, 47, 48 };
#define WE1_NOT 6
#define OE1_NOT 7
#define CE1_NOT 8
#define WE2_NOT 9
#define OE2_NOT 10
#define CE2_NOT 11
const char DATAL[] = { 49, 50, 51, 52, 53, 2, 3, 4 };
void setup() {
// put your setup code here, to run once:
for( int n = 0; n < 16; n ++ ) {
pinMode( ADDR[n], OUTPUT );
}
pinMode( CE1_NOT, OUTPUT );
pinMode( CE2_NOT, OUTPUT );
pinMode( OE1_NOT, OUTPUT );
pinMode( OE2_NOT, OUTPUT );
pinMode( WE1_NOT, OUTPUT );
pinMode( WE2_NOT, OUTPUT );
setDataMode(INPUT);
//attachInterrupt(digitalPinToInterrupt(CLOCK), onClock, RISING);
Serial.begin(115200);
}
void setDataMode( int mode ) {
for( int n = 0; n < 8; n ++ ) {
pinMode( DATAH[n], mode );
pinMode( DATAL[n], mode );
}
}
int count = 0;
enum CMD_STATE {
CMD_INIT,
CMD_IDLE,
CMD_SET_ADDRESS,
CMD_POST_SET_ADDRESS,
CMD_WRITE,
CMD_POST_WRITE,
CMD_POST_READ,
CMD_READ,
CMD_RETURN_TO_IDLE,
};
CMD_STATE rsmState = CMD_INIT;
CMD_STATE request = CMD_IDLE;
unsigned int requestWriteData = 0;
unsigned int requestReadData = 0;
unsigned long requestDataLen = 0;
unsigned long requestAddress = 0;
unsigned long requestRowAddress = 0;
unsigned long wordsLeft = 0;
char output[100];
int requestCount = 0;
char done = 0;
//--------------------------------------------------------------------------------
// getBit
//--------------------------------------------------------------------------------
char getBit( int bit, unsigned long value ) {
switch( bit ) {
case 0: return ( value & 0x0001 ) ? HIGH : LOW;
case 1: return ( value & 0x0002 ) ? HIGH : LOW;
case 2: return ( value & 0x0004 ) ? HIGH : LOW;
case 3: return ( value & 0x0008 ) ? HIGH : LOW;
case 4: return ( value & 0x0010 ) ? HIGH : LOW;
case 5: return ( value & 0x0020 ) ? HIGH : LOW;
case 6: return ( value & 0x0040 ) ? HIGH : LOW;
case 7: return ( value & 0x0080 ) ? HIGH : LOW;
case 8: return ( value & 0x0100 ) ? HIGH : LOW;
case 9: return ( value & 0x0200 ) ? HIGH : LOW;
case 10: return ( value & 0x0400 ) ? HIGH : LOW;
case 11: return ( value & 0x0800 ) ? HIGH : LOW;
case 12: return ( value & 0x1000 ) ? HIGH : LOW;
case 13: return ( value & 0x2000 ) ? HIGH : LOW;
case 14: return ( value & 0x4000 ) ? HIGH : LOW;
case 15: return ( value & 0x8000 ) ? HIGH : LOW;
}
return LOW;
}
//--------------------------------------------------------------------------------
// setAddressPins
//--------------------------------------------------------------------------------
void setAddressPins( unsigned int address ) {
// A0 thru A18
for( int n = 0; n < 19; n ++ ) {
digitalWrite(ADDR[n], getBit( n, address ) );
}
}
//--------------------------------------------------------------------------------
// setDataPins
//--------------------------------------------------------------------------------
void setDataPins( unsigned int data ) {
// D0 thru D7
for( int n = 0; n < 8; n ++ ) {
digitalWrite(DATAL[n], getBit( n, data & 0xFF ) );
}
unsigned int dataH = (data & 0xFF00) >> 8;
// D8 thru D15
for( int n = 0; n < 8; n ++ ) {
digitalWrite(DATAH[n], getBit( n, dataH ) );
}
}
//--------------------------------------------------------------------------------
// handleRSM
//--------------------------------------------------------------------------------
void handleRSM(){
switch(rsmState){
case CMD_INIT:
rsmState = CMD_RETURN_TO_IDLE;
break;
case CMD_IDLE:
// Convert actual memory address to rowAddress (rowAddress=0, two bytes)
requestRowAddress = requestAddress >> 1;
if( request == CMD_WRITE ) {
sprintf(output, "WRITE ROW: %05lx Addr: %05lx Data: %04x Repeat: %ld", requestRowAddress, requestAddress, requestWriteData, requestDataLen);
Serial.println(output);
if( requestDataLen > 1 )
wordsLeft = requestDataLen;
else
wordsLeft = 1;
rsmState = CMD_SET_ADDRESS;
}
if( request == CMD_READ ) {
sprintf(output, "READ ROW: %05lx Addr: %05lx Repeat: %ld", requestRowAddress, requestAddress, requestDataLen);
Serial.println(output);
wordsLeft = requestDataLen;
rsmState = CMD_SET_ADDRESS;
}
break;
case CMD_SET_ADDRESS:
Serial.println("-> CMD_SET_ADDRESS");
//digitalWrite(CE1_NOT, LOW);
//digitalWrite(CE2_NOT, LOW);
digitalWrite(WE1_NOT, HIGH);
digitalWrite(WE2_NOT, HIGH);
// Does OE need to be off when address asserted?
//digitalWrite(OE1_NOT, HIGH);
//digitalWrite(OE2_NOT, HIGH);
setAddressPins( requestRowAddress );
rsmState = CMD_POST_SET_ADDRESS;
break;
case CMD_POST_SET_ADDRESS:
Serial.println("-> CMD_POST_SET_ADDRESS");
digitalWrite(CE1_NOT, LOW);
digitalWrite(CE2_NOT, LOW);
// Choose read or write..
rsmState = request;
break;
case CMD_WRITE:
Serial.println("-> CMD_WRITE");
setDataMode(OUTPUT);
setDataPins( requestWriteData );
digitalWrite(WE1_NOT, LOW);
digitalWrite(WE2_NOT, LOW);
rsmState = CMD_POST_WRITE;
break;
case CMD_POST_WRITE:
Serial.println("-> CMD_POST_WRITE");
digitalWrite(WE1_NOT, HIGH);
digitalWrite(WE2_NOT, HIGH);
wordsLeft --;
if( wordsLeft > 0 ) {
rsmState = CMD_SET_ADDRESS;
} else {
rsmState = CMD_RETURN_TO_IDLE;
}
break;
case CMD_READ:
Serial.println("-> CMD_READ");
digitalWrite(OE1_NOT, LOW);
digitalWrite(OE2_NOT, LOW);
setDataMode(INPUT);
rsmState = CMD_POST_READ;
break;
case CMD_POST_READ:
{
unsigned int dataH = 0;
unsigned int dataL = 0;
int bit;
Serial.println("-> CMD_POST_READ");
for( int n = 7; n >= 0; n -- ) {
bit = digitalRead(DATAH[n]);
dataH = (dataH << 1 ) + bit;
bit = digitalRead(DATAL[n]);
dataL = (dataL << 1 ) + bit;
}
sprintf(output, "<- @%05lx Data %02x %02x", requestRowAddress, dataH, dataL);
Serial.println(output);
wordsLeft --;
// Next word
requestRowAddress ++;
if( wordsLeft > 0 ) {
rsmState = CMD_SET_ADDRESS;
} else {
rsmState = CMD_RETURN_TO_IDLE;
}
break;
}
case CMD_RETURN_TO_IDLE:
Serial.println("-> CMD_RETURN_TO_IDLE");
request = CMD_IDLE;
requestReadData = 0;
requestWriteData = 0;
requestAddress = 0;
digitalWrite(CE1_NOT, HIGH);
digitalWrite(CE2_NOT, HIGH);
digitalWrite(WE1_NOT, HIGH);
digitalWrite(WE2_NOT, HIGH);
digitalWrite(OE1_NOT, HIGH);
digitalWrite(OE2_NOT, HIGH);
rsmState = CMD_IDLE;
break;
}
}
//--------------------------------------------------------------------------------
// loop
//--------------------------------------------------------------------------------
void loop() {
if( rsmState == CMD_IDLE ) {
switch( requestCount ) {
case 0:
requestAddress = 0;
requestWriteData = 0x1234;
//requestDataLen = 307200; // bytes
//requestDataLen = 153600; // WORDs
requestDataLen = 1; // WORDs
request = CMD_WRITE;
break;
case 1:
requestAddress = 0;
requestDataLen = 1;
request = CMD_READ;
break;
case 2:
requestAddress = 0;
request = CMD_READ;
break;
case 3:
requestAddress = 2;
request = CMD_READ;
break;
case 4:
requestAddress = 0;
request = CMD_READ;
break;
case 5:
done = 1;
requestCount ++;
Serial.println("DONE");
break;
default:
break;
}
if( ! done )
requestCount ++;
}
if( ! done )
handleRSM();
//digitalWrite(CE1_NOT, LOW);
//delay( 1000 );
delay( 100 );
count ++;
}