News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

Better way to organise eeprom?

Started by Peter Truman, Nov 05, 2024, 04:46 AM

Previous topic - Next topic

Peter Truman

Hi - I've just been tidying up some old code and I needed to change a default value held in eeprom. I felt that my code, in this respect at least, was very hard to follow (it's 15 years old). So I rewrote the bit I was concerned about and thought I would ask here if there is a better way to do things.

The problem is - in this code I'm using about 90 bytes of eeprom to store default values, which can then be changed by the user. There is no direct visual link between the data entered using 'Edata' and the subsequent variable.

This is what I'm doing now (this is a lot tidier than when I started)
EData Word 20,_

Word 300,_
Word 150,_
Word 200,_
Word 10,_
Word 2,_
Word 2,_
Byte 40,_
Word 5,_
Byte 60,_
Byte 1,_
Word 0,_
Byte 0,_
Byte 5,_
Byte 1,_
Byte 0,_
Word 20,_
Word 300,_
Word 150,_
Word 200,_
Word 10,_
and so on. then

read_eeprom:                                                                                                'all eeprom here
'VARIABLE                       EEPROM      LOCATION    DEFAULT         NOTES
'===========================================================================================
W_prim_low_pres_val         =    ERead 0    '000,001    '20         PSI - low pressure
W_upper_pres_limit          =    ERead 2    '002,003    '300        REDUNDANT
W_high_pressure_val         =    ERead 4    '004,005    '150        PSI - high pressure
W_pres_max                  =    ERead 6    '006.007    '200        PSI burst pressure limit
W_prim_LP_BP                =    ERead 8    '008,009    '10
W_sec_LP_BP                 =    ERead 10   '010,011    '2
W_HP_BP                     =    ERead 12   '012,013    '2
B_temp_val                  =    ERead 14   '014        '40
W_temp_BP                   =    ERead 15   '015,016    '5          - end of first line
B_menu_timeout              =    ERead 17   '017        '60
'----10
B_mon_temp                  =    ERead 18   '018        '1
W_runtime                   =    ERead 19   '019,020    '0
B_use_clock                 =    ERead 21   '021        '0
B_menu_repeat               =    ERead 22   '022        '35

Is there a better way of doing this?

Thanks in advance

top204

#1
Below is demonstration code listing of a method I use in programs to organise the data elements in on-board EEPROM, and procedures to write and read it:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate On-Board EEPROM read and write routines, and a type of data structure for the elements within it.
' The procedures are using an 8-bit offset, so they are only suitable for devices with upto 256 bytes of EEPROM.
' For larger EEPROM sizes, change the Offset variables to a Word type.
'
' Written for the Positron8 compiler by Les Johnson.
'
    Device = 18F25K20                               ' Tell the compiler what device to compile for
    Declare Xtal = 16                               ' Tell the compiler what frequency the device will be operating at (in MHz)
'
' Create some on-board EEPROM data
'
EE_DataElement1  EData Byte 01                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement2  EData Byte 06                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement3  EData Byte 01                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement4  EData Byte 02                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement5  EData Byte 06                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement6  EData Byte 00                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement7  EData Byte 20                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement8  EData Byte 00                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement9  EData Word 360                     ' Holds a 16-bit EEPROM data element, regardless of its value
EE_DataElement10 EData Word 200                     ' Holds a 16-bit EEPROM data element, regardless of its value
EE_DataElement11 EData Long 36000                   ' Holds a 24-bit EEPROM data element, regardless of its value
EE_DataElement12 EData Dword 360000                 ' Holds a 32-bit EEPROM data element, regardless of its value
'
' Create some variables and alias' for the EEPROM routines, so they get re-used
'  
    Dim EEPROM_dData As Dword
    Dim EEPROM_lData As EEPROM_dData.Long
    Dim EEPROM_wData As EEPROM_lData.Word0
    Dim EEPROM_bData As EEPROM_lData.Byte0
    Dim EEPROM_dOrig As Dword
    Dim EEPROM_lOrig As EEPROM_dOrig.Long
    Dim EEPROM_wOrig As EEPROM_lOrig.Word0
    Dim EEPROM_bOrig As EEPROM_lOrig.Byte0
'
' Create some variables for the demo here
'
    Dim MyByte  As Byte
    Dim MyWord  As Word
    Dim MyLong  As Long
    Dim MyDword As Dword
       
'--------------------------------------------------------------------
' The main program starts here
' Write and read on-board EEPROM
'
Main:
'
' Write to on-board EEPROM
'
    EEPROM_Write8(EE_DataElement1, 1)               ' Write an 8-bit value or variable to on-board EEPROM
    EEPROM_Write16(EE_DataElement9, 12345)          ' Write a 16-bit value or variable to on-board EEPROM
    EEPROM_Write24(EE_DataElement11, 123456)        ' Write a 24-bit value or variable to on-board EEPROM
    EEPROM_Write32(EE_DataElement12, 12345678)      ' Write a 32-bit value or variable to on-board EEPROM
'
' Read from on-board EEPROM
'   
    MyByte = EEPROM_Read8(EE_DataElement1)          ' Read an 8-bit value from on-board EEPROM
    MyWord = EEPROM_Read16(EE_DataElement9)         ' Read a 16-bit value from on-board EEPROM
    MyLong = EEPROM_Read24(EE_DataElement11)        ' Read a 24-bit value from on-board EEPROM
    MyDword = EEPROM_Read32(EE_DataElement12)       ' Read a 32-bit value from on-board EEPROM

'-----------------------------------------------------------------------------
' Write an 8-bit value to on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
'           : pData holds the data to write
' Output    : None
' Notes     : Uses a compare before write mechanism
'             This reads from the address that is going to be written too.
'             If the value read is the same as that already in the EEPROM, no write occurs
'             This helps prolong EEPROM life span.
'             For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Write8(pOffset As EEPROM_bOffset, pData As EEPROM_bData)   
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address

    EEPROM_bOrig = ERead pOffset                    ' Read from the offset address first
    If EEPROM_bOrig <> pData Then                   ' Is the value read from the EEPROM the same as the value going to be written?
        EWrite pOffset, [pData]                     ' No. So write to the EEPROM
    EndIf
EndProc

'-----------------------------------------------------------------------------
' Write a 16-bit value to on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
'           : pData holds the data to write
' Output    : None
' Notes     : Uses a compare before write mechanism
'             This reads from the address that is going to be written too.
'             If the value read is the same as that already in the EEPROM, no write occurs
'             This helps prolong EEPROM life span.
'             For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Write16(pOffset As EEPROM_bOffset, pData As EEPROM_wData)
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address

    EEPROM_wOrig = EEPROM_Read16(pOffset)           ' Read from the offset address first
    If EEPROM_wOrig <> pData Then                   ' Is the value read from the EEPROM the same as the value going to be written?
        EWrite pOffset, [pData]                     ' No. So write to the EEPROM
    EndIf
EndProc

'-----------------------------------------------------------------------------
' Write a 24-bit value to on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
'           : pData holds the data to write
' Output    : None
' Notes     : Uses a compare before write mechanism
'             This reads from the address that is going to be written too.
'             If the value read is the same as that already in the EEPROM, no write occurs
'             This helps prolong EEPROM life span.
'             For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Write24(pOffset As EEPROM_bOffset, pData As EEPROM_lData)
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address

    EEPROM_lOrig = EEPROM_Read24(pOffset)           ' Read from the offset address first
    If EEPROM_lOrig <> pData Then                   ' Is the value read from the EEPROM the same as the value going to be written?
        EWrite pOffset, [pData]                     ' No. So write to the EEPROM
    EndIf
EndProc

'-----------------------------------------------------------------------------
' Write a 32-bit value to on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
'           : pData holds the data to write
' Output    : None
' Notes     : Uses a compare before write mechanism
'             This reads from the address that is going to be written too.
'             If the value read is the same as that already in the EEPROM, no write occurs
'             This helps prolong EEPROM life span.
'             For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Write32(pOffset As EEPROM_bOffset, pData As EEPROM_dData)
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address

    EEPROM_dOrig = EEPROM_Read32(pOffset)           ' Read from the offset address first
    If EEPROM_dOrig <> pData Then                   ' Is the value read from the EEPROM the same as the value going to be written?
        EWrite pOffset, [pData]                     ' No. So write to the EEPROM
    EndIf
EndProc

'-----------------------------------------------------------------------------
' Read an 8-bit value from on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
' Output    : None
' Notes     : For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Read8(pOffset As EEPROM_bOffset), Byte
Global Dim EEPROM_bOffset As Byte Shared        ' Holds the 8-bit EEPROM offset address
    Result = ERead pOffset
EndProc

'-----------------------------------------------------------------------------
' Read a 16-bit value from on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
' Output    : None
' Notes     : For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Read16(pOffset As EEPROM_bOffset), Word
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address
    Result = ERead pOffset
EndProc

'-----------------------------------------------------------------------------
' Read a 24-bit value from on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
' Output    : None
' Notes     : For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Read24(pOffset As EEPROM_bOffset), Long
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address
    Result = ERead pOffset
EndProc

'-----------------------------------------------------------------------------
' Read a 32-bit value from on-board EEPROM
' Input     : pOffset holds the 8-bit EEPROM offset address
' Output    : None
' Notes     : For devices with upto 256 bytes of EEPROM data
'
Proc EEPROM_Read32(pOffset As EEPROM_bOffset), Dword
Global Dim EEPROM_bOffset As Byte Shared            ' Holds the 8-bit EEPROM offset address
    Result = ERead pOffset
EndProc

Because each data element's offset address in the on-board EEPROM is given an identity name, it is easy to read and write to it, and offset values do not need to be remembered, and adding, removing or re-arranging data elements in the on-board EEPROM is simple. I always use the prefix characters; 'EE_' for the EEPROM data element offset names, so it is easy to see what they are in the code listing.

The EEPROM data is created in the assembler file as if it was in a single table, but is much more manageable in the high level language:

;---------------------------------------------
; EEPROM DATA
    org 0XF00000
    db 1,6,1,2
    db 6,0,20,0
    db 104,1,224,1
    db 160,140,0,64
    db 126,5,0

Also, notice the method in the EEPROM_WriteX procedures, that reads the data first, and if it is the same as the value being written, it ignores it and does not write to the EEPROM. This increases the life span of the EEPROM because it is not written with data that does not have to be written.

Peter Truman

Ah - ok thanks. Just so I'm clear - the first part of your code

' Create some on-board EEPROM data
'
EE_DataElement1  EData Byte 01                      ' Holds an 8-bit EEPROM data element, regardless of its value
EE_DataElement2  EData Byte 06                      ' Holds an 8-bit EEPROM data element, regardless of its value

effectively writes 2 sequential bytes to eeprom 0 and 1 (with the values 1 and 6 respectively) but gives each location a name so that each can be accessed without having to count the byte positions?

I wasn't aware I could use the Edata structure this way - I read the manual (20 years ago  ::) ) as if I could only use the 'edata' command once only and then only as 'edata Byte constant_1, word constant_2' and so on. Now I read it again it makes much more sense.

I'll try and use your code in my current project - thanks very much for the help.
 

top204

That is exacly what it does Peter. Each Edata directive stores the value/s held within it, and auto increments the offset for the next Edata (if there is one). So it operates as if they were in a single Edata table.

You can see by the assembler code listing I posted, that the values in the assembler db directives, follow the values in the Edata directives values.