You are reading a single comment by @allObjects and its replies. Click here to read the full conversation.
  • Inspired by @DrAzzy's AT25 module implementations, I implemented a dedicated module for FRAM/MRAM. Here the code with usage example, tests, and test output. Documentation is in code (Attachment includes all in one file ready to be pasted into IDE editor, uploaded, and run. - Chip used: 256 Kbit / 32KB - 32K*8 - Cypress FRAM FM25V02-G about 4$). For more about FRAM/MRAM see 256-Kbit (32 K × 8) Serial (SPI) F-RAM - Ferroelecric RAM - SPI challenges.

    var FRAM = (function(){
    
    /* Copyright (C) 2014 allObjects aka Markus Muetschard. See the file LICENSE for copying permission. */
    
    /*
    
    FRAM/MRAM SPI Module - Fero-electric / Magneto-resistive nonvolatile RAM
    ========================================================================
    Supports up to 1 MByte capacity FRAM/MRAM such as
      - Cypress.com 256Kbit (32 K x 8) SPI FRAM - FM25V02-G
      - Fujitsu.com  64Kbit ( 8 K x 8) SPI FRAM - MB85RS64V
    *** usage:
    var FRAM = require("FRAM");
      returns FRAM 'class' (function(), 'default' constructor) for oo-style use.
      Note: You can name the class what ever you want it to be.
    var fram = new FRAM(spi,cap,cs,md);
      creates a connected FRAM instance (same as connect(), see next)
    var fram = new (require("FRAM"))(spi,cap,cs,md);
      is a combination of require and new and can be used when there is
      no need for the application to have access to the class object
      Note: new directly on (require("..."))(...); requires require() to be in ()s.
    var fram = require("FRAM").connect(spi,cap,cs,md);
      is there for connect()-style usage.
    Parameters to pass on new ... or connect() are: 
      - spi - SPI instance (hard or soft)
      - cap - capacity in Kbits
      - cs  - pin that drives FRAM/MRAM chip select
      - md  - optional - for pinMode(cs,md); // pass "output" when no external pull-up
      if undefined is returned on new or connect, error happened (not implemented yet)
    fram.read(a,n,f);
      reads n bytes starting at address a; f is optional return format:
      - f - absent or === 0: Uint8Array
      - f - === 1: String
      if a === undefined, last read/written address+1 is used; initialized on new to 0
      if undefined is returned, error happened (not implemented yet)
    fram.write(a,d);
      writes String | Array d at address a and returns number of written bytes
      if a === undefined, last read/written addr+1 is used; initialized on new w/ 0
      if -1 is returned, error happened (not implemented yet)
      
    *** example:
    SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 18000000}); // setup hw SPI2
    var fram = new (require("FRAM"))(SPI2,256,A2,"output"); // FRAM w/ CS on A2
    console.log("Capacity: " + fram.cap*128/8 + " KBytes"); // 32KBytes w/ 256Kbits
    console.log("Bytes written @ 0: "+fram.write(0,"String at addr 0.")); // 17
    console.log("17 bytes read @ 0: "+fram.read(0,17,1)); // 'String at addr 0.'
    console.log("17 bytes read @ 0: "+fram.read(0,17)); // ...[83, 116, 105,...46]...
    console.log("Bytes written @ 0: "+fram.write(0,[65,66,67,68,69,70])); // 6 (0..5)
    console.log("Bytes written @ n: "+fram.write(undefined,": @")); // 3 (@ next addr)
    console.log("17 bytes read @ 0: "+fram.read(0,17,1)); // 'ABCDEF: @ addr 0.'
    */
      
    var ca2 = function(c,a) { this.cs.reset(); this.spi.send([c,a>>8,a]); };
    var ca3 = function(c,a) { this.cs.reset(); this.spi.send([c,a>>16,a>>8,a]); };
    
    var FRAM = function(spi,cap,cs,md) {
      cs.set(); if (md) { pinMode(cs,md); }
      this.spi = spi;
      this.cap = cap>>7;
      this.cs = cs;
      this.ca = (cap>8388608) ? ca3 : ca2;
      this.a=0;
    };
    FRAM.connect = function(spi,cap,cs,md) { 
      return new FRAM(spi,cap,cs,md);
    };
    FRAM.prototype.read = function(a,n,f){
      a = (a===undefined) ? this.a : a; this.ca(3,a);
      var r = this.spi.send(new Uint8Array(n),this.cs); this.a += n;
      return (f===1) ? E.toString(r) : r;
    };
    FRAM.prototype.write = function(a,d){
      a = (a===undefined) ? this.a : a;
      this.spi.send(0x06,this.cs); this.ca(2,a);
      this.spi.send(d); this.cs.set(); this.a += d.length;
      return d.length;
    };
    
    return FRAM; // exports = FRAM;
    
    })();
    

    Usage example and test code (256 Kbit / 32KB - 32K*8 - Cypress FRAM F25V02-G):

    SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 18000000});
    // var FRAM = require("FRAM"); // get module
    var fram = new FRAM(SPI2,256,A2,"output");
    // var fram = FRAM.connect(SPI2,256,A2,"output"); // alternative 1 w/ get module
    // var fram = new (require("FRAM")).connect(SPI2,256,A2,"output"); // alternative 2
    // var fram = require("FRAM").connect(SPI2,256,A2,"output"); // classical
    
    console.log("~");
    console.log("fram.cap(acity)" +
                " = " + fram.cap*128 + " Kbit" +
                " = " + (fram.cap*128)*(1024/8) + " Bytes" +
                " = " + (fram.cap*128)*(1024/8)/1024 + " KBytes");
    
    function writes() {console.log("~");
    console.log("*** writes ***");
    console.log("@000:10: 'FRAM@000 A':       " + fram.write(  0,"FRAM@000 A"));
    console.log("@008:11: 'FRAM@016 AB':      " + fram.write( 16,"FRAM@016 AB"));
    console.log("@032:12: 'FRAM@032 ACD':     " + fram.write( 32,"FRAM@032 ABC"));
    console.log("@128:13: 'FRAM@128 ABCD':    " + fram.write(128,"FRAM@128 ABCD"));
    console.log("@256:14: 'FRAM@256 ABCDE':   " + fram.write(256,"FRAM@256 ABCDE"));
    console.log("@512:15: 'FRAM@512 ABCDEF':  " + fram.write(512,"FRAM@512 ABCDEF"));
    }
    function reads() {console.log("~");
    console.log("*** reads ***");
    console.log("@000:10:",fram.read(  0, 10));
    console.log("@016:11:",fram.read( 16, 11));
    console.log("@032:12:",fram.read( 32, 12));
    console.log("@128:13:",fram.read(128, 13));
    console.log("@256:14:",fram.read(256, 14));
    console.log("@512:15:",fram.read(512, 15));
    console.log("@000:10:",fram.read(  0, 10,1));
    console.log("@016:11:",fram.read( 16, 11,1));
    console.log("@032:12:",fram.read( 32, 12,1));
    console.log("@128:13:",fram.read(128, 13,1));
    console.log("@256:14:",fram.read(256, 14,1));
    console.log("@512:15:",fram.read(512, 15,1));
    }
    function hurray() {console.log("~");
    console.log("*** reads, overwrite, and reads ***");
    console.log("read  @000:44: " + fram.read( 0,44));
    console.log("read  @000:44: " + fram.read( 0,44,1));
    console.log("               0....'....1....'....2....'....3....'....4....'");
    console.log("write @010:20: 'Hurray! ...it works!':  " + 
                fram.write( 10,"Hurray! ...it works!"));
    console.log("read  @010:20: " + fram.read(10,20));
    console.log("read  @010:20: " + fram.read(10,20,1));
    console.log("read  @000:44: " + fram.read( 0,44));
    console.log("read  @000:44: " + fram.read( 0,44,1));
    console.log("               0....'....1....'....2....'....3....'....4....'");
    }
    function clear() {console.log("~");
      console.log("*** clear (fill all with '~' ***");
      var x = 0, b = 256, r = fram.cap * 16 * 1024 ; // bytes;
      var f = new Uint8Array(b); f.fill(126,0,b); f = E.toString(f);
      while(r > 0) { 
        x += fram.write(x,(r > b) ? f : f.substr(0,r));
        r -= b;
      }
    }
    

    Test output:

     1v72 Copyright 2015 G.Williams
    >echo(0);
    ~
    fram.cap(acity) = 256 Kbit = 32768 Bytes = 32 KBytes
    ~
    *** clear (fill all with '~' ***
    ~
    *** reads ***
    @000:10: new Uint8Array([126, 126, 126, 126, 126, 126, 126, 126, 126, 126])
    @016:11: new Uint8Array([126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126])
    @032:12: new Uint8Array([126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126])
    @128:13: new Uint8Array([126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126])
    @256:14: new Uint8Array([126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126])
    @512:15: new Uint8Array([126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126])
    @000:10: ~~~~~~~~~~
    @016:11: ~~~~~~~~~~~
    @032:12: ~~~~~~~~~~~~
    @128:13: ~~~~~~~~~~~~~
    @256:14: ~~~~~~~~~~~~~~
    @512:15: ~~~~~~~~~~~~~~~
    ~
    *** reads, overwrite, and reads ***
    read  @000:44: 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126
    read  @000:44: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                   0....'....1....'....2....'....3....'....4....'
    write @010:20: 'Hurray! ...it works!':  20
    read  @010:20: 72,117,114,114,97,121,33,32,46,46,46,105,116,32,119,111,114,107,115,33
    read  @010:20: Hurray! ...it works!
    read  @000:44: 126,126,126,126,126,126,126,126,126,126,72,117,114,114,97,121,33,32,46,46,46,105,116,32,119,111,114,107,115,33,126,126,126,126,126,126,126,126,126,126,126,126,126,126
    read  @000:44: ~~~~~~~~~~Hurray! ...it works!~~~~~~~~~~~~~~
                   0....'....1....'....2....'....3....'....4....'
    ~
    *** clear (fill all with '~' ***
    ~
    *** writes ***
    @000:10: 'FRAM@000 A':       10
    @008:11: 'FRAM@016 AB':      11
    @032:12: 'FRAM@032 ACD':     12
    @128:13: 'FRAM@128 ABCD':    13
    @256:14: 'FRAM@256 ABCDE':   14
    @512:15: 'FRAM@512 ABCDEF':  15
    ~
    *** reads ***
    @000:10: new Uint8Array([70, 82, 65, 77, 64, 48, 48, 48, 32, 65])
    @016:11: new Uint8Array([70, 82, 65, 77, 64, 48, 49, 54, 32, 65, 66])
    @032:12: new Uint8Array([70, 82, 65, 77, 64, 48, 51, 50, 32, 65, 66, 67])
    @128:13: new Uint8Array([70, 82, 65, 77, 64, 49, 50, 56, 32, 65, 66, 67, 68])
    @256:14: new Uint8Array([70, 82, 65, 77, 64, 50, 53, 54, 32, 65, 66, 67, 68, 69])
    @512:15: new Uint8Array([70, 82, 65, 77, 64, 53, 49, 50, 32, 65, 66, 67, 68, 69, 70])
    @000:10: FRAM@000 A
    @016:11: FRAM@016 AB
    @032:12: FRAM@032 ABC
    @128:13: FRAM@128 ABCD
    @256:14: FRAM@256 ABCDE
    @512:15: FRAM@512 ABCDEF
    ~
    *** reads, overwrite, and reads ***
    read  @000:44: 70,82,65,77,64,48,48,48,32,65,126,126,126,126,126,126,70,82,65,77,64,48,49,54,32,65,66,126,126,126,126,126,70,82,65,77,64,48,51,50,32,65,66,67
    read  @000:44: FRAM@000 A~~~~~~FRAM@016 AB~~~~~FRAM@032 ABC
                   0....'....1....'....2....'....3....'....4....'
    write @010:20: 'Hurray! ...it works!':  20
    read  @010:20: 72,117,114,114,97,121,33,32,46,46,46,105,116,32,119,111,114,107,115,33
    read  @010:20: Hurray! ...it works!
    read  @000:44: 70,82,65,77,64,48,48,48,32,65,72,117,114,114,97,121,33,32,46,46,46,105,116,32,119,111,114,107,115,33,126,126,70,82,65,77,64,48,51,50,32,65,66,67
    read  @000:44: FRAM@000 AHurray! ...it works!~~FRAM@032 ABC
                   0....'....1....'....2....'....3....'....4....'
    =undefined
    >
    

    1 Attachment

About

Avatar for allObjects @allObjects started