Shop OBEX P1 Docs P2 Docs Learn Events
Beginner: Use EEPROM to Store/Retrieve Integer Value — Parallax Forums

Beginner: Use EEPROM to Store/Retrieve Integer Value

Chad1Chad1 Posts: 26
edited 2014-11-02 13:03 in General Discussion
Hi all,

I'm trying to program what is essentially a high-score monitoring system (like in an arcade game). I have two double-digit 7 segment displays; one shows a "current score" and the other shows the "high score." For simplicity, let's say the user controls their score by button presses. Button 1 increments the user's score (win), and button 2 resets it to zero (lose). Of course all data is lost once the Propeller is powered down, but I'd like to save the "high score" number. My plan was to store the "record value" in EEPROM (256K) and then retrieve it upon power up.

I defined an array of longs called NUM. Each element in NUM is a 32-bit value which translates to a 2-digit 7SD number. Each time button 1 is pressed (win), a counter variable i increments and the 7SD displays the ith element of NUM (i =< 100). Variable i will reset to zero with power, so I have another variable MAX_Value that I want to always equal the appropriate element of NUM. I'm leveraging the Propeller Eeprom.spin object file (attached), so I know I'll be using the fromram and toram commands. My problem is I don't understand how these commands work. Can someone help me figure out the correct information to include within those two commands in order to carry out my goal of integer storage/retrieval?

Say the third element of NUM (the number 2) is a new high score and I want to store that info in EEPROM. My (likely incorrect) guess in red...

if ina[BTN1] == 1 'If WIN
|-i := i + 1 'Pretend it now equals 3 for this example and represents a new High Score
|-Display(long[@Num]) 'Pseudo code for driving the 7SD with a live score
|-if i > MAX_Value 'If a new record is set
|--|-MAX_Value := i
|--|-eeprom.fromram(MAX_Value, MAX_Value, $1F400) 'Choosing memory location to begin at 128K for safety
|--|-Display(long[@Num][MAX_Value]) 'Pseudo code for driving the 7SD with the new high score

Then say upon power up I want to retrieve the high score information (i.e. 3rd NUM element) and set it equal to MAX_Value. My blind guess...

--eeprom.fromram(MAX_Value, MAX_Value, $1F400)
--MAX_Value := MAX_Value 'This doesn't make sense! Does the above line already assign the value stored in EEPROM to MAX_Variable?
--Display(long[@Num][MAX_Value]) 'Pseudo code for driving the 7SD with the high score

Thanks in advance for the help!

Propeller Eeprom.spin

Comments

  • rosco_pcrosco_pc Posts: 464
    edited 2014-10-17 23:49
    A few things about teh eeprom.spin onbject:
    1) You need to provide address, not the parameter value. You do this by adding a '@' to the parameter name

    Using this your code will be (not tested as I have no propeller handy):

    Save MAX_Value
    eeprom.fromram(@MAX_Value, @MAX_Value, $1F400) 'Choosing memory location to begin at 128K for safety
    

    Read MAX_Value
      eeprom.toram(@MAX_Value, @MAX_Value, $1F400)
      Display(long[@Num][MAX_Value]) 'Pseudo code for driving the 7SD with the high score
    
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-10-17 23:53
    Unless you need to preserve values between program downloads there's no need to use upper EEPROM; simply write the value to the same address as your variable has in RAM and on boot-up the last saved value will be auto-loaded. Easy-peasy.
  • Chad1Chad1 Posts: 26
    edited 2014-10-18 00:13
    JonnyMac wrote: »
    simply write the value to the same address as your variable has in RAM and on boot-up the last saved value will be auto-loaded.

    This was exactly what I wanted to implement from the start, but I failed to locate the area in the manual which covers this. Could you please provide a quick example of how you would program this in spin, i.e. the commands/instructions required?
  • Chad1Chad1 Posts: 26
    edited 2014-10-25 14:28
    Bump. Can someone please help me do what JonnyMac described? I can't think of how to implement that solution.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-11-01 21:24
    Chad1 wrote: »
    Bump. Can someone please help me do what JonnyMac described? I can't think of how to implement that solution.

    As I mentioned in this other thread you started about this same topic:
    Duane Degn wrote: »

    Also from the other thread:
    Chad1 wrote: »
    Hey guys,

    I should have noted that I originally intended on storing the parameter's value in EEPROM, and I started a thread asking how to use the eeprom object file to do it (http://forums.parallax.com/showthread.php/157833-Beginner-Use-EEPROM-to-Store-Retrieve-Integer-Value). The response I mentioned (about storing the value in RAM) was from that thread, and for some reason after responding to it all activity died.

    I'd like to avoid using my EEPROM to store the value, per the response from the above thread. Any help I could get in doing that would be appreciated.

    The link I posted above shows how to do what JonnyMac suggested.

    If you don't want to store to EEPROM, then you need to store to some other memory which won't change with a power cycle. You can't store things permanently to RAM you have to use EEPROM and the link I provided will show you how.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-11-01 22:11
    One example from the above thread:
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]·[/COLOR] ...[/SIZE][/FONT][/COLOR]
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]·[/COLOR] eeprom.VarBackup(@value, @value+ 3)[COLOR=white]···[/COLOR] &#8216; Backup[/SIZE][/FONT][/COLOR]
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]·[/COLOR] ...[/SIZE][/FONT][/COLOR]
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]·[/COLOR] eeprom.VarRestore(@value, @value + 3)[COLOR=white]·······[/COLOR] &#8216; Restore[/SIZE][/FONT][/COLOR]
    

    The reason there's a "+3" is to include the extra three bytes in the long sized variable "value".

    You could do the same thing with:
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]··[/COLOR] ...[/SIZE][/FONT][/COLOR]
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]··[/COLOR] eeprom.FromRam(@value, @value+ 3, [/SIZE][/FONT][/COLOR][COLOR=#000000][FONT=Verdana]@value[/FONT][/COLOR][COLOR=black][FONT=Verdana][SIZE=2]) [/SIZE][/FONT][/COLOR][COLOR=#000000][FONT=Verdana]&#8216; Backup[/FONT][/COLOR][COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]·[/COLOR][/SIZE][/FONT][/COLOR]
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]··[/COLOR] ...[/SIZE][/FONT][/COLOR]
    [COLOR=black][FONT=Verdana][SIZE=2][COLOR=white]··[/COLOR] eeprom.ToRam(@value, @value + 3, [/SIZE][/FONT][/COLOR][COLOR=#000000][FONT=Verdana]@value[/FONT][/COLOR][COLOR=black][FONT=Verdana][SIZE=2]) [/SIZE][/FONT][/COLOR][COLOR=#000000][FONT=Verdana]&#8216; Restore[/FONT][/COLOR]
    
    ·
    If you had second long sized variable immediately after "value" you wanted to backup and restore, you'd use "+7" instead of "+3" in order to include the next four bytes in the transfer.

    Let us know if you need clarification.

    Edit: Both examples of the "Restore" portion of the code are not needed since the RAM will be automatically updated with the new value when the Propeller is rebooted (just as Jon suggested).

    Make sure you use the @ sign. The methods use the address of the variable, not the value stored in the variable.
  • T ChapT Chap Posts: 4,223
    edited 2014-11-02 04:36
    What I do for storing preference is to set up a method for each write and each read. Also declare the eeprom i2c address in CON.

    Pick any address in eeprom starting at $8000 if you have a 64k eeprom. If not then you can write to high areas in your 32k eeprom BUT the values will get nuked once you F11 program your Prop from the IDE. Programming the Prop writes over the full 32k, but does not write above 32k. So if storing values in upper 32k you will need to re-write your preferences after any F11. It is best to use a 64K eeprom and not deal with the hassles. Then you have a full 32K to play with from $8000 - $FFFF addresses.
    Con
          EEPROM1             = %1010_000_0  'eeprom address
    
    Var
          Long MinSpeedOpen, MinSpeedClose
    
    Obj  
          i2c1         : "CLEAN_minimali2cdriversmall"    'some people will remember  CLEAN_xxxx  from the good ole days
    
    PUB WriteMinSpeedOpen   'create a Pub method for each value you want to store a la carte.
        WritePage(eeprom1, $F060, @MinSpeedOpen, 4)    'write to address $F060.   the value is Var MinSpeedOpen   4bytes length
    
    PUB GetPrefs   ' recall all values in one method on boot ( place this in INIT )
      ' Read in all preferences on program launch.  
    
        ReadPage(EEPROM1, $F040, @MaxSpeedOpen, 4)   'load 4 bytes  ( a LONG) 
        ReadPage(EEPROM1, $F050, @MaxSpeedClose, 4)
        ReadPage(EEPROM1, $F060, @MinSpeedOpen, 4)
        ReadPage(EEPROM1, $F070, @MinSpeedClose, 4)   '  this could have been a byte = 1 or word = 2 or long = 4
    
        'I space out the eeprom addresses every 10 bytes as above, it is easy to view and remember the addresses
    
    PUB ReadPage(devid, address, pointer, count)         
        i2c1.i2cstart(28)
        i2c1.i2cReadPage(28, devid, address, pointer, count)   
        i2c1.i2cstop(28)
        return  pointer
    
    PUB WritePage(devid, address, pointer, count)
        i2c1.i2cWritepage(28, devid, address, pointer, count)
        waitcnt(clkfreq/200 + cnt)
        i2c1.i2cstop(28)
    
    
    
    
    
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-11-02 07:15
    Can someone please help me do what JonnyMac described? I can't think of how to implement that solution.

    Here's how I do it using my own EEPROM object.
    ee.wr_long(@someVariable, someVariable)
    

    This would save a long variable (someVariable) to the EEPROM to the same address it occupies in RAM. This will cause it to be auto-loaded on subsequent reboot cycles. Of course, you have to start the EEPROM object -- to connect to the boot EEPROM you'd do this:
    ee.start(%000)
    

    As I said before: easy-peasy.
  • Chad1Chad1 Posts: 26
    edited 2014-11-02 11:45
    All,

    Thanks for your time and help; I learned a lot from your explanations.

    JonnyMac,

    Thanks so much for your explanation and your object file. Everything works perfectly and you're right -- it was very easy!
  • JDatJDat Posts: 103
    edited 2014-11-02 12:45
    What about checksum in address $0005? Does ROM bootloader check it while booting? It's for loading and verifying while IDE upload new code to EEPROM? http://forums.parallax.com/showthread.php/86056-Video-Processing-(going-the-other-way)?p=591803&viewfull=1#post591803
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-11-02 13:03
    JDat wrote: »
    What about checksum in address $0005? Does ROM bootloader check it while booting?

    No, it's not checked when the Prop boots. I think it's only checked when a new program is loaded from the PC.

    Changing the EEPROM from within a program is very common. I've done it many times myself without any problems.
Sign In or Register to comment.