#### Visitor

##### Active Member
Since MrDEB couldn't be arrsed to try the simple experiment I suggested in posts 46 and 50, I did them. Why? Because I wasn't certain how things would work, and it was easy enough to give it a try and learn a few things in the process.

In part 1, I saved byte values in 4 adjacent EEPROM locations. Reading the values back into a byte variable yielded the results expected. Reading the values back into a word variable yielded garbage of course, because each EEPROM location is byte-sized, and when a word is read, two adjacent bytes are read as a word.

In part 2, I saved word variables, each containing a byte value, into adjacent EEPROM locations. This is of course wrong, as a word requires two bytes. Reading these locations back as bytes yielded the expected numbers, but this is a happy circumstance of the order in which they were written, because stored a word writes in two EEPROM locations. It might look ok during a quick test, but it will yield unexpected results.

Reading these values back into a word variable resulted in garbage, as this reads adjacent cells as a word.

In part 3, I wrote a byte-sized word variable into every other cell. Reading back the values as bytes shows the expected result, the byte-sized number in one cell and a zero in the other (since the value stored was less than 256). Reading the word value from the expected location yielded the expected results.

When word values were read from the wrong location of the pair, garbage was the result, as byte values from two diffent words were combined un the wrong order.

Part 4 repeated part 3 with values greater than 255 (i.e., greater than byte-sized) with the expected results.

Thd output of the tests is shown here. This picture shows the EEPROM values as read by the PICkit 2.

Code:
EEPROM Test

Part 1 - Data written as bytes

EE.0 = 42, EE.1 = 43, EE.2 = 44, EE.3 = 45, stored as bytes.

===========================================================

Part 2 - Data written as words, in adjacent locations

EE.4 = 42, EE.5 = 43, EE.6 = 44, EE.7 = 45, stored as words.
Note: a word should require 2 locations.

===========================================================

Part 3 - Data written as words, in every other location

EE.9 = 42, EE.11 = 43, EE.13 = 44, EE.15 = 45, stored as words.

Read as words, odd cell numbers

Read as words, even cell numbers

===========================================================

Part 4 - Data written as words, in every other location

EE.20 = 747, EE.22 = 748, EE.24 = 749, EE.26 = 750, stored as words.

Read as words, even cell numbers

Read as words, odd cell numbers

#### Attachments

• 85.3 KB Views: 4

#### Pommie

##### Well-Known Member
What happens if you do,
Code:
dim test as word
test=$1234 EE.write(0,test) test=0 EE.Read(0,test) (forgive syntax - may be wrong). Surely, the value read back is hex 1234. You seem to be convinced that the EE routines only deal with bytes. I think they deal with whatever type of variable you use. Mike. #### be80be ##### Well-Known Member Microcontroller EEPROM read and write library. Note that TAddress is byte size for devices that have less than 256 bytes of onboard EEPROM. For devices that have more than 256 of onboard EEPROM, TAddress is a word. Write multiple items to microcontroller EEPROM. Valid argument types include boolean, char, string, byte, shortint, word, integer, longword, longint and floating point. #### Visitor ##### Active Member You seem to be convinced that the EE routines only deal with bytes. Not at all. If a word is saved, a word will be returned as long as nothing else writes over its EEPROM locations. The same should be true for any type of variable. You can get into trouble in two ways: ¤ If you save a variable of one type and recall it as a different type. For example, if you store a byte variable (one byte) and read it into a word variable (two bytes), you'll get garbage. ¤ If you don't allow enough space for whatever type of variable is being stored (i.e., 2 bytes for a word, 4 bytes for a long word or float), depending on the order things are saved, some of the EEPROM locations will be overwritten and the returned values will be wrong. Finally, reading the byte values will always show what's stored. The value of whatever variable type was stored can be calculated. #### tumbleweed ##### Active Member So, what it boils down to is 'garbage in, garbage out'. The libraries read and write the different variable types as you would expect. Nothing extra needed except a little upfront planning for what you're saving where just like in any other system. #### MrDEB ##### Well-Known Member I did everything requested in post 46 and 50 thus I am making some progress. my code needs some work due to the fact after I ran the code in post 75 which worked as planned I inserted into my project code and it fails to work. I think I have best score in place of current score. will try it today #### granddad ##### Well-Known Member Am i missing something here , your code can write byte word to EE , then via PK2 or whatever read it take a look see what it wrote ( as the Visitor post #81 ) The SF note states SF defaults to longword for EE write . If SF automatically stops GI interrupts , why does the EE library note state to stop them for other than bytes ? Last edited: #### Visitor ##### Active Member ....The SF note states SF defaults to longword for EE write...... Where did you see this? This isn't what I observed but that may be because of how I did my tests. I set variables dimensioned as bytes or words equal to the values I wanted and then explicitly saved the variable as opposed to a raw number. Dim Vbyte as Byte Dim Vword as Word Vbyte = 42 Vword = 42 EE.Write(0, Vbyte) EE.Write(2, Vword) I did get some results I couldn't explain in my first iteration, but I attributed that to errors in my code written at two in the morning. I will make a couple more tests later today. #### granddad ##### Well-Known Member Where did you see this? Its in a note top of the SF EEprom library ... I loaded SF yesterday , and wondered .. #### Ian Rogers ##### User Extraordinaire Forum Supporter Most Helpful Member Its in a note top of the SF EEprom library ... I loaded SF yesterday , and wondered .. That'll be if you send constants.. The compiler won't be able to classify it... EE.write( 0, 23) will be the default... The trouble here is the read will have to be a longword even though the amount is tiny... #### be80be ##### Well-Known Member Mrdeb should test raw numbers And format the Result for printing Code he posted was saving everything His last code posted was much better But I would only read and write as needed pull out old value at start of game save at end there no use of using eeprom while playing game you get the writes in loop you'll ware out the eeprom #### MrDEB ##### Well-Known Member good point Burt I got my code to display current score and best score but now trying to convert the scores to decimal. as in the ET subroute. Need to look at Burts suggestion about reading writing the eeprom to much. Someone posted about the best score starting at 0 I changed it to best_score=20000 looks crazy but it worked. another issue is the eeprom is not saving info upon disconnecting power. Code: //add more sequences //add the START code //add the second speed select code //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Device = 18F43K22 Clock = 8 #option LCD_DATA = PORTD.4 #option LCD_RS = PORTD.0 #option LCD_EN = PORTD.1 '#option KEYPAD_PORT = PORTC Include "intosc.bas" Include "setdigitalio.bas" Include "keypad12mrd.bas" Include "ledmatrixREV.bas" Include "lcd.bas" Include "utils.bas" Include "convert.bas" Include "isrtimer.bas" Include "EEPROM.bas" 'Dim ledno As Byte Dim ms As Word Dim s As String 'Dim time As Word Dim best_score As Word Dim Current_Score As Word Dim str As String Dim tmpByte As Byte Sub Ontimer() Inc(ms) End Sub Sub ET_time() Timer.Stop //stop timer s=DecToStr(ms/1000)+"."+DecToStr((ms Mod 1000)) WriteAt(1,1,"your Score = " ) 'delayms(2000) WriteAt(1,1,"reaction ") //display players score WriteAt(2,1,"seconds ",s," ") DelayMS(3000) 'EE.Write(0,Current_Score) //need to write to eeprom current score Current_Score = ms WriteAt(2,1,"ms = ",DecToStr(ms))//testing change to current score DelayMS(3000) 'ms=0 DelayMS(9000) Cls 'repeat ' WriteAt(1,1,"press START") 'WriteAt(2,1,"to play again") 'until (getkey()=3) 'DelayMS(2000) Cls 'DelayMS(100) 'wend End Sub //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx //read write to eeprom //zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz Sub Score_et() EE.Write(1,best_score) EE.Read(0,tmpByte) If tmpByte =$77 Then
End If
If Current_Score < best_score Then
best_score = Current_Score  //reset BEST_SCORE if CURRENT_SCORE is lower
EE.Write(1,best_score)  //present beast score

EndIf
If Current_Score > best_score Then

EndIf
Cls

WriteAt(2,1,DecToStr(Current_Score))      //14388
WriteAt(1,1,DecToStr(best_score))   // 123

DelayMS(4000)
Cls
Current_Score=0
ms=0
End Sub

//SEQUENCES xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Sub One()
SetLed(1)
Repeat
Until (GetKey()=1)
SetLed(7)
Repeat
Until (GetKey()=7)
SetLed(4)
Repeat
Until (GetKey()=4)
SetLed(10)
Repeat
Until (GetKey()=10)
SetLed(2)
Repeat
Until (GetKey()=2)
SetLed(10)
Repeat
Until (GetKey()=10)
SetLed(6)
Repeat
Until (GetKey()=6)
SetLed(12)
Repeat
Until (GetKey()=12)
SetLed(8)
Repeat
Until (GetKey()=8)
SetLed(9)
Repeat
Until (GetKey()=9)
SetLed(1)
Repeat
Until (GetKey()=1)
SetLed(11)
Repeat
Until (GetKey()=11)
SetLed(0) //turn off led
End Sub
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

//initialize timer    PUT THIS AS A SUBROUTE
Sub Int_Timer()
Timer.Initialize(1)
Timer.Items(0).interval=1  //ms
Timer.Items(0)[email protected]  //timer event handler
//enable timers
Timer.Items(0).enabled=true
If GetKey=12 Then   //insert this into all the sub sequences but only last key in sequence
Timer.Stop       //need to insert GETKEY
End If
End Sub
'time = 0
ms=0
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
'START=(GETKEY()=3)
// turn off analog functions
SetAllDigital()
Current_Score=0
best_score=20000

// loop forever showing led X while key X is pressed
While (true)
Cls
WriteAt(1,1,"welcome")
WriteAt(2,1,"lets begin")
DelayMS(3000)
Cls
WriteAt(1,1,"when button ")
WriteAt(2,1,"lights")
DelayMS(3000)
Cls
WriteAt(2,1,"Button ")
WriteAt(1,1,"press THAT")
DelayMS(3000)
WriteAt(1,1,"you will be")
WriteAt(2,1,"TIMED ")
Cls
WriteAt(1,1,"lets begin")
DelayMS(3000)
Cls
WriteAt(1,1,"press the")
WriteAt(2,1,"START BUTTON")  //for test it is #1 SHOULD HAVE KEPT MCLR CONNECTED
DelayMS(2000)
Int_Timer()
SetLed(3)
Timer.Start//SetLed(GetKey())
If (GetKey()=3) Then
Timer.Start//SetLed(GetKey())/SetLed(GetKey())
End If
One()       // turn on led 1  INSERT SEQUENCES HERE AS SUBS in a for next loop
ET_time()
Score_et()

Wend

#### tumbleweed

##### Active Member
That'll be if you send constants.. The compiler won't be able to classify it... EE.write( 0, 23) will be the default... The trouble here is the read will have to be a longword even though the amount is tiny...
It doesn't work that way. It evaluates the const and calls the appropriate routine
EE.write( 0, 23) uses a byte write, EE.write( 0, 1234) uses a word write, etc.

EE.Write() is a generic routine and calls different underlying code based on what you pass it.
If you want to write constant values like that it would be a lot safer to use the specific 'WriteByte, WriteWord, WriteLongword' etc calls.

If SF automatically stops GI interrupts , why does the EE library note state to stop them for other than bytes ?
Let me try this again.

When it does the low-level 'write a byte to eeprom' routine, it automatically:
- saves the current GIE
- disables interrupts
- writes the byte
- restores the GIE setting that was in effect when the routine was called

All of the upper level routines end up using that low-level function at least once and maybe multiple times.
For example, writing a longword (4 bytes) will call that routine 4 times.
If interrupts are enabled before the "EE.Writexxx()' call, then they'll get disabled/reenabled, disabled/reenabled, etc four times as it writes the four bytes.

That means that you can get an interrupt in between each of the 4 individual byte writes. That can cause issues or not, entirely based on YOUR code. If it's important that the entire 4-bytes is written without interruption then disable interrupts, call ee.write, and then reenable interrupts.

Make sense?

#### be80be

##### Well-Known Member
How big is the score

#### Visitor

##### Active Member
....another issue is the eeprom is not saving info upon disconnecting power.....
I really hate to point out the obvious here (really), but the problem isn't with the EEPROM – it's with your code.

#### Visitor

##### Active Member
Code:
Sub Score_et()
EE.Write(1,best_score)
If tmpByte = $77 Then EE.Read(1,best_score) End If If Current_Score < best_score Then best_score = Current_Score //reset BEST_SCORE if CURRENT_SCORE is lower EE.Write(1,best_score) //present beast score EndIf If Current_Score > best_score Then EndIf Cls EE.Read(1,best_score) WriteAt(2,1,DecToStr(Current_Score)) //14388 WriteAt(1,1,DecToStr(best_score)) // 123 DelayMS(4000) Cls Current_Score=0 ms=0 End Sub It doesn't appear that you ever write to EE.0, so that location will never read as$77, so that If/Then will never get executed.

But no matter. You immediately write EE.1 with best_score at the start of the subroutine, and then later read it back.....trying to follow your logic here makes my head hurt.

But as a final step, you set current_scorecto zero, so do nothing and you win.

#### MrDEB

##### Well-Known Member
as it is after the first run through the
WriteAt(2,1,DecToStr(Current_Score)) //14388
WriteAt(1,1,DecToStr(best_score)) // 123
show correctly as well as all the scores thereafter BUT the scors are not converted using
s=DecToStr(ms/1000)+"."+DecToStr((ms Mod 1000))
I tried using writeat(1,1,(best_score)DecToStr(ms/1000)+"."+DecToStr((ms Mod 1000))
this worked BUT both scores are identical and I get some extra squagillie at the beginning.
will try writing to the same eeprom slot.
I looked up but no success as to what
If tmpByte = $77 Then does?? #### Visitor ##### Active Member If you'd actually done stuff I said in post 46, you'd understand the "extra squagillie" at the beginning of the line. Or in the several other posts where I explained the problems with your display statements. LOOK at the display statement. Is EVERY NUMBER handled the SAME WAY? Hint: the answer is no. As the what the$77 does, it's your code. You elected to include it despite several people commenting on it and saying you don't need it.

You can lead a Chevy to the levy but you can't make him drink.

#### MrDEB

##### Well-Known Member
the $77 seems to clear out the eeprom?? thinking of not having ms=0 but going to the subroute then write to the eeprom in a different slot then reading for the final display. going to research what the$77 actually does.

#### Visitor

##### Active Member
The term is subroutine.

The \$77 has been discussed IN THIS THREAD. You might try reading the posts here.