Interface avec une mémoire serial SRAM

J’ai testé la puce IS62WVS2568GBLL, qui est une mémoire Serial SRAM de 2Mb. Elle coûte 3,68$ à l’unité. C’est la plus grande capacité que j’ai pu trouver. Son interface est un port SPI. Voici le code que j’ai utilisé pour la tester. J’écris un signal triangulaire de 256 samples, qui se répète sur l’ensemble de la mémoire. J’utilise un fichier .wav pour visualiser les données. La consommation en write continu est d’environ 1mA, à 3.3V d’alimentation et une clock de 200kHz. On peut écrire avec une clock qui peut aller jusqu’à 45MHz (pour une consommation en courant supérieure). On peut écrire en continu sans toggler la pin CS#, ce qui fait que l’écriture peut être contrôlée simplement par la clock, une fois la commande de write envoyée, ce qui en fait un candidat intéressant pour un buffer circulaire indépendant d’un microcontrôleur.

Code arduino :

#include <SPI.h>
int sram_CSn = A2;
int mic_sel = A0;
int mic_clk = A1;

void setup() {
  pinMode(mic_enable, OUTPUT);
  pinMode(sram_CSn, OUTPUT);
  pinMode(mic_clk, INPUT);
  digitalWrite(mic_enable, LOW);
  digitalWrite(sram_CSn, HIGH);
  Serial.begin(115200);

  //Set SRAM to sequential operation
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0)); //100kHz
  digitalWrite(sram_CSn, LOW);
  SPI.transfer(0x01); //write mode register
  SPI.transfer(0x40); //01 : sequential mode + bits 0-5 set to 0
  SPI.endTransaction();
  digitalWrite(sram_CSn, HIGH);
  SPI.end();

  //Test sequential write
  SPI.begin();
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0)); //100kHz
  digitalWrite(sram_CSn, LOW);
  SPI.transfer(0x02); //write command
  SPI.transfer(0x00); //address (24 bits)
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  for (int i = 0; i < 44100; i++){
    SPI.transfer(byte(i % 256));
    SPI.transfer(0x00);
  }
  SPI.endTransaction();
  digitalWrite(sram_CSn, HIGH);
  SPI.end();

}

void loop() {
  int cmd = Serial.read();
    if (cmd == 114){
      SPI.begin();
      SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0)); //100kHz
      digitalWrite(sram_CSn, LOW);
      SPI.transfer(0x03); //read command
      SPI.transfer(0x00); //address (24 bits)
      SPI.transfer(0x00);
      SPI.transfer(0x00);

      SPI.transfer(0x00); //dummy 8 bytes
      for (int i = 0; i < 44100; i++){
        Serial.write(SPI.transfer(0x00));
      }
      SPI.endTransaction();
      digitalWrite(sram_CSn, HIGH);
      SPI.end();
      Serial.write(0xCC);
      Serial.write(0xCC); //send the stop bytes
    }
}

Code python sur l’ordi :

import serial
import wave, struct

ser = serial.Serial("/dev/ttyACM0", 115200)

ser.write(bytes("r", encoding = 'utf8')) #send read command to get flash memory content

buf = []
while(True):
    char = ser.read(2)
    sample = int.from_bytes(char, byteorder='little') #- 63000 #convert to signed int 16 bits
    if (sample > 32767) or (sample < -32768):
        sample = 0
    if char == b'\xcc\xcc':
        print(len(buf))
        break
    else:
        buf.append(sample)
        #if not (len(buf) % 44100):
        #    print('{}%'.format(int(len(buf) / sizeoffile * 100)), end='\r', flush=True)

#plt.plot(buf)
#plt.show()
with wave.open('sound.wav','w') as obj:
    obj.setnchannels(1) # mono
    obj.setsampwidth(2) #16 bits
    obj.setframerate(22050.0) #sampling frequency
    for value in buf:
        data = struct.pack('<h', value)
        obj.writeframes(data)