# uPy - RPi Pico SPI read and strings to fram MB85RS64
# provided by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-01-12  initial release

# ================== Fram Constants ===================

WREN	= 0x06						# MB85R64 set   write enable latch
WRDI	= 0x04						# MB85R64 reset write enable latch
RDSR	= 0x05						# MB85R64 read  status register
WRSR	= 0x01						# MB85R64 write status register, protected by /WP = gnd
READ	= 0x03						# MB85R64 read  date
WRITE	= 0x02						# MB85R64 write data

# ==================== class Fram =====================

class Fram:
    
    def __init__(self, spi, cs):
        self.spi     = spi
        self.cs		 = cs
        self.buf1	 = bytearray(1)
        
    
    # return fram status byte
    def getStatus(self):
        self.cs(0)
        data_rx = self.spi.read(2, RDSR)
        self.cs(1)
        return(data_rx[1])
        

    # set fram write enable latch to protect
    def writeProtect(self, protect=True):
        self.cs(0)
        self.buf1[0] = WRDI if protect else WREN
        self.spi.write(self.buf1)
        self.cs(1)


    # write bytes / bytearray to addr
    def write(self, addr=0x0000, data=b'\x00'):
        if not isinstance(data, (bytes, bytearray)): return
        self.data_tx = bytes([WRITE, addr >> 8, addr & 0xFF]) + data
        self.writeProtect(False)
        self.cs(0)
        self.spi.write(self.data_tx)
        self.cs(1)
        self.writeProtect(True)
        
        
    # read n bytearray from addr
    def read(self, addr=0x0000, n=1):
        data_tx = bytes([READ, addr >> 8, addr & 0xFF]) + bytes(n)
        data_rx = bytearray(3+n)
        self.cs(0)
        self.spi.write_readinto(data_tx, data_rx)
        self.cs(1)
        return data_rx[3:]
    

    # write utf-8 string (len <= 255) to addr
    def swrite(self, addr=0x0000, s=''):
        if not s: return
        data 	 = bytes(s, 'utf-8')
        lng = len(data)
        if lng > 255: return				# error, string too long
        data_tx = bytearray([lng])
        data_tx.extend(data)
        self.write(addr, data_tx)
        return lng


    # read utf-8 string from addr
    def sread(self, addr=0x0000):
        lng = self.read(addr)[0]
        if not lng: return					# exit if no string available
        str_b = self.read(addr+1, lng)
        return str_b.decode()				# utf-8 is default
    
# ==================== test ========================

if __name__ == '__main__':
    
    from	machine		import	Pin, SPI

    # ============ Hardware definitions ============

    pin_led         = 25				# on-board green led
    pin_spi_sck		= 18
    pin_spi_mosi	= 19
    pin_spi_miso	= 16
    pin_spi_cs		= 17

    # ============ Hardware setup  =================

    led		= Pin(pin_led, Pin.OUT, value=1)
    spi	    = SPI(0, 10_000_000, sck=pin_spi_sck, mosi=pin_spi_mosi,
                  miso=pin_spi_miso)
    spi_cs  = Pin(pin_spi_cs, Pin.OUT, value=1)


    def test():
        fram = Fram(spi, spi_cs)
        s1 = 'het kost \u20ac101.15'			# euro 101.15
        l  = fram.swrite(0x0100, s1)
        print('read :', fram.read(0x0100, l+1))
        print('sread:', fram.sread(0x0100))
    

    test()
    spi.deinit()
    
# ====================== End ==========================
