# cPy - emulating 64 kb fram MB85RS64
# Copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-01-28  initial release

# Implemented:
# MB85RS64(spi, cs)
#    MB85RS64.getStatus(self)
#    MB85RS64.writeProtect(protect=True)
#    MB85RS64.write (addr=0x0000, data=b'\x00')
#    MB85RS64.read  (addr=0x0000, n=1)			-->  bytes
#    MB85RS64.swrite(addr=0x0000, s='')			-->  n
#    MB85RS64.sread (addr=0x0000)				-->  s
#    MB85RS64.save()

import  struct

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

class MB85RS64:

    # load from file or create fram image of 64 kb
    def __init__(self, spi, cs):
        self.size = 8192
        try:
            with open('mb85r64.img', 'rb') as f:
                self.img = bytearray(f.read())
        except: self.img = bytearray(self.size)
        self.mv_img = memoryview(self.img)


   # return fram status byte, for SPI compatiblity
    def getStatus(self):
        return 0
 
 
    # set fram write enable latch to protect, for SPI compatibility
    def writeProtect(self, protect=True):
        pass


    # write bytes / bytearray to addr
    def write(self, addr=0x0000, data=b'\x00'):
        if not isinstance(data, (bytes, bytearray)): return
        lng = len(data)
        if addr + lng > self.size:
            raise ValueError('Fram: not enough room')
        self.mv_img[addr:addr+lng] = data


    # return n bytes starting from addr as bytes
    def read(self, addr=0x0000, n=1):
        return bytes(self.mv_img[addr:addr+n])
    

    # write utf-8 string (len <= 255) to addr, store length as first byte
    # return number of bytes written
    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+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 = self.read(addr+1, lng)
        return str_b.decode()				# utf-8 is default


    # save FRAM memory image as fn
    def save(self, fn='mb85r64.img'):
        with open(fn, 'wb') as f:
            f.write(self.img)
        print('file saved')

# ======================= Test ========================

if __name__ == '__main__':

    import  os;         os.system('clear')


    def test():
        fram = MB85RS64(spi=None, cs=None)
        fram.write(0x0000, bytes([1, 2, 3, 4, 5]))
        print(fram.read(0x0000, 5))
        fram.swrite(0x0100, '12345')
        s = fram.sread(0x0100)
        print(type(s), s)
        fram.save()


    test()

# ====================== End ==========================
