# -*- coding: utf-8 -*-

'''
The RTC has memory which survives warm reboots.

These functions allow to write a string in this memory.

See:
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
Page 25
0x3FF8_0000 8kBytes RTC FAST Memory  (doesn't survive reboot)
0x5000_0000 8kBytes RTC SLOW Memory  (survives reboot)

https://github.com/micropython/micropython/pull/4046


Tesing:
import hw_rtc_mem
hw_rtc_mem.objRtcMem.writeRtcMemDict({'a': 'Hallo', 5: 4711})

import machine
machine.reset()

import hw_rtc_mem
hw_rtc_mem.objRtcMem.readRtcMemDict()

ASSERT; The dictionary above must be displayed!

'''

import machine
import uctypes

MAGIC = 0x3F2A8C1D
ADDR = 0x50000000
OFFSET_STRING_BYTES = 4
OFFSET_MAGIC_BYTES = 8
ENCODING = 'utf-8'

class RtcMem:
  def writeRtcMemBytes(self, b):
    '''
      Writes a string into the slow memory.
    '''
    l = len(b)
    l_aligned4 = l + 4 - l%4
    machine.mem32[ADDR+0] = l
    machine.mem32[ADDR+l_aligned4+OFFSET_MAGIC_BYTES] = MAGIC
    mem = uctypes.bytearray_at(ADDR+OFFSET_STRING_BYTES, l)
    mem[:l] = b

  def writeRtcMem(self, s):
    '''
      Writes a string into the slow memory.
    '''
    self.writeRtcMemBytes(bytes(s, ENCODING))

  def readRtcMemBytes(self, default=None):
    '''
      Reads a tyes from the slow memory.
    '''
    l = machine.mem32[ADDR+0]
    if (l<=0) or (l>0x2000-OFFSET_MAGIC_BYTES):
      print('RTC-Mem UNITIALIZED (wrong size).')
      return default
    l_aligned4 = l + 4 - l%4
    if machine.mem32[ADDR+l_aligned4+OFFSET_MAGIC_BYTES] != MAGIC:
      print('RTC-Mem UNITIALIZED (magic number dismatch)')
      return default
    mem = uctypes.bytearray_at(ADDR+OFFSET_STRING_BYTES, l)
    return bytes(mem)

  def readRtcMem(self, default=''):
    '''
      Reads a string from the slow memory.
    '''
    b = self.readRtcMemBytes()
    if b is None:
      return default
    return b.decode(ENCODING)

  def writeRtcMemDict(self, d):
    self.writeRtcMem(str(d))

  def readRtcMemDict(self):
    s = self.readRtcMem(default='{}')
    d = eval(s)
    return d

objRtcMem = RtcMem()
# -*- coding: utf-8 -*-

'''
The RTC has memory which survives warm reboots.

These functions allow to write a string in this memory.

See:
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
Page 25
0x3FF8_0000 8kBytes RTC FAST Memory  (doesn't survive reboot)
0x5000_0000 8kBytes RTC SLOW Memory  (survives reboot)

https://github.com/micropython/micropython/pull/4046


Tesing:
import hw_rtc_mem
hw_rtc_mem.objRtcMem.writeRtcMemDict({'a': 'Hallo', 5: 4711})

import machine
machine.reset()

import hw_rtc_mem
hw_rtc_mem.objRtcMem.readRtcMemDict()

ASSERT; The dictionary above must be displayed!

'''

import machine
import uctypes

MAGIC = 0x3F2A8C1D
ADDR = 0x50000000
OFFSET_STRING_BYTES = 4
OFFSET_MAGIC_BYTES = 8
ENCODING = 'utf-8'

class RtcMem:
  def writeRtcMemBytes(self, b):
    '''
      Writes a string into the slow memory.
    '''
    l = len(b)
    l_aligned4 = l + 4 - l%4
    machine.mem32[ADDR+0] = l
    machine.mem32[ADDR+l_aligned4+OFFSET_MAGIC_BYTES] = MAGIC
    mem = uctypes.bytearray_at(ADDR+OFFSET_STRING_BYTES, l)
    mem[:l] = b

  def writeRtcMem(self, s):
    '''
      Writes a string into the slow memory.
    '''
    self.writeRtcMemBytes(bytes(s, ENCODING))

  def readRtcMemBytes(self, default=None):
    '''
      Reads a tyes from the slow memory.
    '''
    l = machine.mem32[ADDR+0]
    if (l<=0) or (l>0x2000-OFFSET_MAGIC_BYTES):
      print('RTC-Mem UNITIALIZED (wrong size).')
      return default
    l_aligned4 = l + 4 - l%4
    if machine.mem32[ADDR+l_aligned4+OFFSET_MAGIC_BYTES] != MAGIC:
      print('RTC-Mem UNITIALIZED (magic number dismatch)')
      return default
    mem = uctypes.bytearray_at(ADDR+OFFSET_STRING_BYTES, l)
    return bytes(mem)

  def readRtcMem(self, default=''):
    '''
      Reads a string from the slow memory.
    '''
    b = self.readRtcMemBytes()
    if b is None:
      return default
    return b.decode(ENCODING)

  def writeRtcMemDict(self, d):
    self.writeRtcMem(str(d))

  def readRtcMemDict(self):
    s = self.readRtcMem(default='{}')
    d = eval(s)
    return d

objRtcMem = RtcMem()
# -*- coding: utf-8 -*- The RTC has memory which survives warm reboots.  These functions allow to write a string in this memory.  See: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf Page 25 0x3FF8_0000 8kBytes RTC FAST Memory  (doesn't survive reboot) 0x5000_0000 8kBytes RTC SLOW Memory  (survives reboot)  https://github.com/micropython/micropython/pull/4046   Tesing: import hw_rtc_mem hw_rtc_mem.objRtcMem.writeRtcMemDict({'a': 'Hallo', 5: 4711})  import machine machine.reset()  import hw_rtc_mem hw_rtc_mem.objRtcMem.readRtcMemDict()  ASSERT; The dictionary above must be displayed! Writes a string into the slow memory. Writes a string into the slow memory. Reads a tyes from the slow memory. Reads a string from the slow memory.