# rpi - SPI read and write strings to fram MB85RS64
# provided by Anthony Vogelaar, Perth Scotland
# rev 0.10  2024-12-28  initial release

import	time
from	spidev	import	SpiDev

# ===================== 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

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

spi	= SpiDev()						# instantiate object for SPI communication

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

class Fram:
    
    def __init__(self, spi, bus_nr=0, device_nr=0, speed=20_000_000):
        spi.open(bus_nr, device_nr)
        self.spi         = spi
        spi.max_speed_hz = speed
        spi.mode         = 0x00			# idle SCK = 0 and pos edge
        
    
    # return fram status byte
    def getStatus(self):
        data_tx = [RDSR, 0x0F]
        data_rx = self.spi.xfer(data_tx)
        return(data_rx[1])
        

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


    # write list of bytes (int 0..255) to addr
    def write(self, addr=0x0000, data=[]):
        if not data: return
        self.writeProtect(False)
        data_tx  = [WRITE]
        data_tx += [addr >> 8, addr & 0xFF]
        data_tx += data
        self.spi.xfer(data_tx)
        self.writeProtect(True)
        
        
    # read n-list of bytes (int 0..255) from addr
    def read(self, addr=0x0000, n=1):
        data_tx  = [READ]
        data_tx += [addr >> 8, addr & 0xFF]
        data_tx += [0] * n
        data_rx = self.spi.xfer(data_tx)
        return data_rx[3:]
    

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


    # 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 = bytes(self.read(addr+1, lng))
        return str_b.decode()				# utf-8 is default
    
# ==================== test ========================

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

try:
    test()
except:
    print('Test aborted')
spi.close()
    
# ====================== End ==========================
