Sunday, January 15, 2017

$0.5 2K EEPROM M93C86 for .NET, CSharp and Nusbio.net

I experimented with a cheap EEPROM the M93C86 2k byte of data for $0.5 programmed in C# with Nusbio.net (M93C86 datasheet).

The EEPROM used the SPI protocol but its API is not as straightforward as the Microchip EEPROMs.
After a day of work it seems that we can only write one byte at the time and for that we need to pass 4 bytes, of protocol. So write speed is very slow.
It does not seems that there is a concept of page per say, but since I want to re use a C# base class, I set up a page to 256 bytes, and the read performance in SPI out of the box is 10 K byte/S with Nusbio v1.
Since it is just an experiment I will not optimize the code to get 28 K byte/S like with the Microchip SPI EEPROM.
As a reminder Nusbio v 2 can transfer at the rate of 1 to 3 M byte/S in SPI and 100 K byte/S in I2C in
any .NET language. Nusbio v 2 is in prototype mode as 2017/01.


/*
   Copyright (C) 2015, 2016, 2017 MadeInTheUSB LLC
   Written by FT for MadeInTheUSB

   MIT License (MIT)
*/

using System;
using System.Collections.Generic;

namespace MadeInTheUSB.EEPROM
{
    /// 
    /// m93c86 is a 2k byte spi cheap eeprom
    /// http://www.mouser.com/ds/2/389/m93c46-w-955034.pdf
    ///     CS(PD-1k)[] [] VCC
    ///     SCK      [] [] Not used
    ///     MOSI     [] [] ORG Leave unconnected for 16kbit orf
    ///     MISO     [] [] GND
    /// 
    public class EEPROM_M93C86 : EEPROM_25AAXXX_BASE
    {

#if NUSBIO2
        public EEPROM_M93C86() : base(16)
        {
        }
#else
        public EEPROM_M93C86(Nusbio nusbio, 
            NusbioGpio clockPin, 
            NusbioGpio mosiPin, 
            NusbioGpio misoPin, 
            NusbioGpio selectPin,
            bool debug = false) : base(nusbio, clockPin, mosiPin, misoPin, selectPin, 16, 
                debug, 
                chipSelectActiveLow:false // << important
                )
        {
            var b = this.MaxByte;
            var p = this.MaxPage;
            this.SetWriteRegisterEnable();
            //this.SetWriteRegisterDisable();
        }
#endif

    
        public override bool Is3BytesAddress
        {
            get { return false; }
        }

        public override int PAGE_SIZE
        {
            get{ return 256; }
        }

        protected override bool SetWriteRegisterEnable()
        {
            var r = this.SpiTransfer( new List(){ 0x98 /*0b10011000*/, 00 } );
            return r.Succeeded;
        }

        protected override bool SetWriteRegisterDisable()
        {
            var r = this.SpiTransfer(new List() { 0x80 /*0b10000000*/, 00 });
            return r.Succeeded;
        }
        /// 
        /// http://www.mouser.com/ds/2/389/m93c46-w-955034.pdf
        /// based on the data sheet in ORG: 8 byte (low)
        /// writing one byte require 22 Clock Cycle
        /// 1 start bit, 2 bit-opCode, 11-Addr == 2 Clock cycle
        /// We send 24 bits the first 2 bits are 00
        /// I do not think that this EEPROM support write in bulk mode
        /// It does support Read in bulk
        /// 
        /// 
        /// 
        /// 
        public virtual bool WritePage(int addr, byte[] buffer)
        {
            int dt1, dt2, ans;

            for (var num = 0; num < buffer.Length; num++)
            {
                //dt1 = 0b00101000 | ((adrs & 0b0000011100000000) >> 8) ;
                //dt2 = (adrs & 0b0000000011111111) ;
                dt1           = 0x28 | ((addr & 0x700) >> 8);
                dt2           = (addr & 0xFF);
                var spiBuffer = new List() { (byte)dt1, (byte)dt2, buffer[num] };
                var writeR    = this.SpiTransfer(spiBuffer);
                var readR     = this.SpiTransfer(new List() { 0 });
                ans           = readR.Buffer[0];
                addr += 1;
            }
            return true;
        }

        public override EEPROM_BUFFER ReadPage(int addr, int len = -1)
        {
            if (len == -1)
                len = PAGE_SIZE;

            var eb = new EEPROM_BUFFER();
            int dt1, dt2;

            //dt1 = 0b00110000 | ((adrs & 0b0000011100000000) >> 8) ;
            //dt2 = (adrs & 0b0000000011111111) ;
            dt1 = 0x30 | ((addr & 0x700) >> 8);
            dt2 = (addr & 0xFF);

            var spiBufferWrite = new List() { (byte)dt1, (byte)dt2 };
            var spiBufferRead = GetEepromApiDataBuffer(len);
            var buffer = new List();
            buffer.AddRange(spiBufferWrite);
            buffer.AddRange(spiBufferRead);

            var r = this.SpiTransfer(buffer);

            if (r.Succeeded)
            {
                eb.Succeeded = true;
                eb.Buffer = r.Buffer.GetRange(spiBufferWrite.Count, r.Buffer.Count - spiBufferWrite.Count).ToArray();
            }
            return eb;
        }
      
    }
}

No comments:

Post a Comment