Understanding of @ptrinc and @ptrdec functions

Hi All

I've just spent a while trying to work out why some code didn't work as expected. The code copies a 16-bit data value (a temperature value with lsn being 1/16ths of degree), from a block in scratchpad, then allows the value to be increased or decreased before placing back into scratchpad. When the original code didn't work as expected, I went through many iterations to try to isolate exactly WHY it didn't work. What it seems to come down to is that the @ptrinc and @ptrdec instructions don't do what I think they should. Is it my misunderstanding, or is the editor/compiler misbehaving ?

I actually started with the instruction w3=@ptr - expecting the compiler to understand from the "W3" that this was a word instruction. I tried adding the keyword "WORD" before, in and after the instruction, but the compiler threw that out. I presume the @ptr instruction can't support words (but the manual doesn't say so and the compiler accepts it).

When it didn't work as expected I changed to byte instructions. However using @ptrinc and @ptrdec instructions also didn't work as expected. This all seems to be about moving the msb and lsb incorrectly, or the @ptrdec and @ptrinc instructions not correctly moving the ptr value as advertised.

I've used the @ptrinc instruction in other parts of the program with no apparent problems. So it's puzzling.

I'm using the latest 6.1.0.0 editor for a 28X2 chip

All suggestions appreciated - full code available if needed for debugging / analysis


;
; **************************************************************************************************************************************
; take 15
;
; try moving the ptr around "manually" instead of using @ptrinc and @ptrdec
;
; this works
;
ptr = wkday_boiler_temp1 ;******************** try forcing the pointer to the "right" place ********************************
;
b6 = @ptr
ptr = ptr + 1
b7 = @ptr
if up_key_moved=1 then
if w3 < %0000010001100000 then ; max temp 70 degrees
inc w3
endif
elseif down_key_moved=1 then
if w3 > %0000000010100000 then ; min temp 10 degrees
dec w3
endif
endif
@ptr = b7
ptr = ptr - 1
@ptr = b6
;
;
; **************************************************************************************************************************************
; take 14
;
; try removing the second force of the ptr, and changing the order of re-writing the data to sratchpad
;
; doesn't work - back to no up count, down in chunks of 16 degrees
;
;
ptr = wkday_boiler_temp1 ;******************** try forcing the pointer to the "right" place ********************************
;
b6 = @ptrinc
b7 = @ptr
if up_key_moved=1 then
if w3 < %0000010001100000 then ; max temp 70 degrees
inc w3
endif
elseif down_key_moved=1 then
if w3 > %0000000010100000 then ; min temp 10 degrees
dec w3
endif
endif
;
@ptrdec = b7
@ptr = b6
;
;
 
Not sure why your 'doesn't work' version doesn't because the Scratchpad stuff worked when I tested it in the simulator and on an actual 28X2

I suspect the issue is with your magic values and your incrementing or decrementing and display of the values.

The @ptr stuff only deals with byte values so the component parts of a word variable have to be used, for example 'b7' and 'b6' for 'w3'. The byte components of a word variable are lowest byte first, highest byte second. So 'w3=$1234' is the same as 'b7=$12 : b6 = $34", and vice-versa. It's common to use the same scheme for Scratchapd, lsb at lowest address, msb at higher. Words in Scratchpad don't need to be on an even address.

You seem to have grasped that but this may help and it runs in the Simulator -
Code:
#Picaxe 28X2

Symbol SCRATCHPAD_LOCATION = 11

Symbol value     = w3 ; b7:b6
Symbol value.lsb = b6
Symbol value.msb = b7

; Read the word at the scratchpad location

ptr = SCRATCHPAD_LOCATION
value.lsb = @ptrInc
value.msb = @ptr
SerTxd("Initial value = ", #value, CR, LF)

; Write the value 1234 to the scratchpad location

value = 1234
ptr = SCRATCHPAD_LOCATION
@ptrInc = value.lsb
@ptr    = value.msb

; Read the word at the scratchpad location

ptr = SCRATCHPAD_LOCATION
value.lsb = @ptrInc
value.msb = @ptr
SerTxd("Value after writing 1234 = ", #value, CR, LF)

; Increment the word at the scratchpad location

ptr = SCRATCHPAD_LOCATION
value.lsb = @ptrInc
value.msb = @ptrDec
value     = value + 1
@ptrInc   = value.lsb
@ptr      = value.msb

; Read the word at the scratchpad location

ptr = SCRATCHPAD_LOCATION
value.lsb = @ptrInc
value.msb = @ptr
SerTxd("Value after incrementing = ", #value, CR, LF)
Alternatively, to make the main code easy to write ...
Code:
#Picaxe 28X2

Symbol SCRATCHPAD_LOCATION = 11

Symbol value = w3

#Macro ReadScratchpadWord(loc, var)
  ptr = loc
  var = @ptrInc
  var = @ptr * 256 + var
#EndMacro

#Macro WriteScratchpadWord(loc, val)
  ptr = loc
  @ptrInc = val
  @ptr    = val / 256   
#EndMacro

; Read the word at the scratchpad location

ReadScratchpadWord(SCRATCHPAD_LOCATION, value)
SerTxd("Initial value = ", #value, CR, LF)

; Write the value 1234 to the scratchpad location

WriteScratchpadWord(SCRATCHPAD_LOCATION, 1234)

; Read the word at the scratchpad location

ReadScratchpadWord(SCRATCHPAD_LOCATION, value)
SerTxd("Value after writing 1234 = ", #value, CR, LF)

; Increment the word at the scratchpad location

ReadScratchpadword(SCRATCHPAD_LOCATION, value)
WriteScratchpadWord(SCRATCHPAD_LOCATION, value + 1)

; Read the word at the scratchpad location

ReadScratchpadWord(SCRATCHPAD_LOCATION, value)
SerTxd("Value after incrementing = ", #value, CR, LF)
 
Last edited:
Hi Hippy

Thanks for that very comprehensive info.

But in my code samples - what exactly have I done wrong in take #14 which is right in take #15 ?
 
Hi Hippy

"Not sure why your 'doesn't work' version doesn't because the Scratchpad stuff worked when I tested it in the simulator and on an actual 28X2
I suspect the issue is with your magic values and your incrementing or decrementing and display of the values"

The point is that I've been very careful to whittle the code down to the point that the ONLY differences between working and not working are in those instructions to transfer the word out of and back into scratchpad. Not a single other change in the code. So I can be pretty certain this has nothing to do with magic values (what are they?), or the display sub-system, or anything else.

I think you've agreed that the "take #14" code is "correct" and should work in exactly the same way as take #15, but it does not.

It feels like a bug, where the @ptrinc or dec commands don't do what they should. My hunch is that this is specific to the particular circumstances of my code - use of scratchpad or other memory, or particular place in my code. Probably very difficult to reproduce.

As a point of history, when I used an earlier editor/compiler a decade ago, I found areas of scratchpad memory that were unusable because they were corrupted in the runtime environment - proved it by running memory tests which would fail. I hoped such problems had been eliminated by editor updates, but this problem has a similar feel.

Could I also ask that the manual be updated to make clear that the @ptr instructions can't be used with data words, and also that the compiler flags up any attempt to do so ?

Many thanks
 
The point is that I've been very careful to whittle the code down to the point that the ONLY differences between working and not working are in those instructions to transfer the word out of and back into scratchpad. Not a single other change in the code. So I can be pretty certain this has nothing to do with magic values (what are they?), or the display sub-system, or anything else.

I think you've agreed that the "take #14" code is "correct" and should work in exactly the same way as take #15, but it does not.
Yes, AFAICT and when I tested, things worked as I expected. As you say the two should be functionally equivalent and I can't see that they are not.

I don't really understand this "back to no up count, down in chunks of 16 degrees"; I don't see how that second could even happen, how it would be related to '@ptr' operation, or even how 'dec w3' would be doing that.

The only thing I can suggest is reading the Scratchpad value before adjusting and display its value, then do the same after adjustment, then you can be assured that, at that point in the code, the value in Scratchpad is correct.

As to 'magic numbers' I was meaning those %0000010001100000 and %0000000010100000 values though I have now figured them out; temperature plus 4-bit fraction.

Could I also ask that the manual be updated to make clear that the @ptr instructions can't be used with data words, and also that the compiler flags up any attempt to do so ?
The "@ptr" can be used with data words so it's not possible to flag incorrect use even if the functionality is not what the user expected it would be.
 
Hi Hippy

Yes, I agree with almost all of that. But I also realised that there's even more strangeness here. The little snippet of code is to be able to edit the values stored for the PICAXE to work as a heating system programmer, with blocks of start and end times, with a temperature in between.

Once the edit function has been started, the code snippet is run every pass of the program, and the temperature value in scratchpad is copied into w3, then back again, regardless of whether a key is pressed to increase or decrease the value in w3. So if the @ptrinc or @ptrdec instruction is swapping around or losing the msb or lsb, why doesn't it corrupt the scratchpad every time through? It only seems to do it when a key is pressed.

The initial value in the first of the temperature positions happens to have a starting value of 32 degrees. That's %0000 0010 0000 0000. When that's decremented it should become %0000 0001 1111 1111 = 31.9 degrees. But it actually becomes 16 degrees, which is equivalent to "losing" the lsb somewhere or setting it to zero. Meanwhile an increment from 32 degrees simply increases the lsb, but if that's being cleared somehow, then nothing at all appears to change. So why does the inc w3 instruction appear to work correctly in take #15, but not in take #14 ? It's as though it only works on the msb of the word. Should it have the syntax inc word w3 ?

As far as @ptr - you said that the instruction w3 = @ptr is invalid. So I'm asking that the manual states that the @ptr instructions can only be used to move bytes of data, not words. And if the syntax checker sees something like w3 = @ptr it should recognise that the word variable won't be loaded from @ptr ( and automatically from @(ptr+1) ) and flag it as a syntax error?
 
The statement 'W3 = @ptr' isn't invalid. It might not do what you expect, but it does exactly what it is supposed to do.

@ptr is pointer to a byte, so the statement says 'Load W3 with the byte that ptr is pointing to'.

The syntax checker can't flag 'W3 = @ptr' as an error, because it is perfectly valid to store a 8 bit value in a 16 bit word.
 
That's %0000 0010 0000 0000. When that's decremented it should become %0000 0001 1111 1111 = 31.9 degrees. But it actually becomes 16 degrees, which is equivalent to "losing" the lsb somewhere or setting it to zero.

So why does the inc w3 instruction appear to work correctly in take #15, but not in take #14 ?
Thanks for the example. I would agree it appears the lsb of the value in Scratchpad is being zeroed somehow but I am not convinced it is due to an '@ptr' bug nor 'inc w3' or 'dec w3'.

I have no idea why there is different behaviour for the two examples but imagine it's because something different is happening elsewhere in the code such that the final outcome is different in each, works in one case, not in another. The issue seems coincidental rather than causal to me.

As the lsb seems to be being cleared I would suspect something else is overwriting the Scratchpad byte outside of the code presented. My gut feeling would be that you do not have correctly paced Scratchpad locations to take into account two byte storage for word values, so 'ptr' is misaligned somewhere, pointing into that word when it shouldn't, and something then consequentially corrupts Scratchpad. Or there may be an interrupt where 'ptr' is manipulated which means it's not pointing to the correct location after it returns and gets used.

Given that I agree, and suspect everyone else would, that the two are functionally the same, will do exactly the same thing, the issue must therefore lie outside that code. There being some esoteric bug which has never revealed itself previously is highly unlikely and is causing focus on an area of code which almost certainly isn't problematic in itself.

It's as though it only works on the msb of the word. Should it have the syntax inc word w3 ?
No, that's perfectly fine 'inc w3' is simply the equivalent of 'w3 = w3 + 1' and the compiler and firmware knows it is dealing with a word variable through its naming and will treat it as such.

As far as @ptr - you said that the instruction w3 = @ptr is invalid.
I don't think I did. It is entirely valid as per specification; read a byte value from Scratchpad and place it in a byte or word variable. What it won't do is load two bytes into a word variable, only the one '@ptr' points to.

Expecting it to load two bytes into a word variable when a word variable is specified is an incorrect expectation.

So I'm asking that the manual states that the @ptr instructions can only be used to move bytes of data, not words.
The documentation seems pretty clear to me in stating @ptr uses byte values, such as page 15 in PICAXE Manual 2, and elsewhere, but I will accept there's nothing explicit I could see about it not moving words.

And if the syntax checker sees something like w3 = @ptr it should recognise that the word variable won't be loaded from @ptr ( and automatically from @(ptr+1) ) and flag it as a syntax error?
But it's not a syntax error. It is perfectly valid for someone to do, and want to do, 'w3 = @ptr' or '@ptr = w3' and it will do exactly as expected if one's expectations match how '@ptr' operates, solely on bytes. To presume someone who uses 'w3 = @ptr' wants to load two bytes, a word value, is not correct.

If it were made a syntax error it would mean people doing what is perfectly valid, and what they want to do, being unable to compile that code. It would make it harder to do what they wanted to do and should be able to do.
 
The initial value in the first of the temperature positions happens to have a starting value of 32 degrees. That's %0000 0010 0000 0000. When that's decremented it should become %0000 0001 1111 1111 = 31.9 degrees. But it actually becomes 16 degrees, which is equivalent to "losing" the lsb somewhere or setting it to zero.
This is why I suggested reading the word value from Scratchpad after updating it so you can confirm the value after that operation is correct, that any corruption isn't occurring in that code but elsewhere.
 
Hi Hippy & Buzby

Thanks for the clarification of the effect of an instruction such as "w3 = @ptr". I understand and accept what you say.

HOWEVER, I think it would be of some benefit to other users to have the action of the @ptr instruction clarified for this case. To me, assuming that a word based instruction will work on a word, unless flagged by the syntax checker, or the manual page, or both, is reasonable.

And as far as the "corruption" of the scratchpad value being due to an interrupt, or mis-aligned scratchpad allocation - well, no. I understand why one would conclude that, because otherwise, what I'm seeing is "impossible". But the interrupt acts only on nominated registers, to decrement them until they reach zero. The scratchpad allocation is sound because if I use "take #15" code everything works as expected - the value can be increased or decreased as required, and when the editor function is left, the scratchpad, as displayed, is stable.

Sorry if I sound argumentative, but I've spent a lot of time trying to understand what's wrong, and am still no nearer. I've found ways to work around the problem, but that's not really the right solution.

I'm not familiar with the simulator, so if it would be of any use for me to send you the full code I'd be happy to do that, if you advise how.

Cheers
 
This is probably a very dumb question, but the suggestion of interrupt being the culprit does raise a question - I'm using all 4 slots of the 28X2 - slot 0 for initialisation, then slots 1, 2, 3 in rotation - the main loop skips between the 3, calling subroutines partitioned into each slot. I have a "subroutines" file of common subroutines which is "included" in each slot's code at compile time. That subroutines file contains a copy of the interrupt handler, which is also in slot 0. Presumably the interrupt is handled by whichever interrupt routine is in the slot which is active at that moment, but how is that routing done ?



;
;
;#############################################################################################
;
; Interrupt Routine
;
;#############################################################################################
;
;
; 1Hz signal on input 2 - use to decrement to zero any timers running
;
; Interrupt is not edge-triggered, so don't re-enable it here, but
; in main loop, once low level detected.
;
; symbol repeat=b29
; symbol i2c_timeout=b28
; symbol sunshine_pause=w13 ; (b27,b26)
; symbol change_timer=b25 ; countdown timer when in set state - to return to run state after inactivity
; symbol priority_pause=b24
;
interrupt:
;
; decrement any non-zero timer/pause registers
;
if b29>0 then dec b29 endif
if b28>0 then dec b28 endif
if w13>0 then dec w13 endif ; (b27,b26)
if b25>0 then dec b25 endif
if b24>0 then dec b24 endif
;
; show 1Hz signal
;
high flash_pin
;
return
;


and here's the scratchpad allocation - of course most of the names are never used, because the whole point is that
this is an indexable table:


;
; **********************************************************************
;
; space here that was unsafe with earlier editor - should be ok with 6.1
;
symbol circulate_flag=60
;
; **********************************************************************
;
; storage for programmer times - 3 on and off times for weekdays and weekends
;
symbol wkday_boiler_hours_on1=61
symbol wkday_boiler_mins_on1=62
symbol wkday_boiler_temp1=63 ;word
symbol wkday_boiler_hours_off1=65
symbol wkday_boiler_mins_off1=66
;
symbol wkday_boiler_hours_on2=67
symbol wkday_boiler_mins_on2=68
symbol wkday_boiler_temp2=69 ;word
symbol wkday_boiler_hours_off2=71
symbol wkday_boiler_mins_off2=72
;
symbol wkday_boiler_hours_on3=73
symbol wkday_boiler_mins_on3=74
symbol wkday_boiler_temp3=75 ;word
symbol wkday_boiler_hours_off3=77
symbol wkday_boiler_mins_off3=78
;
symbol weekend_boiler_hours_on1=79
symbol weekend_boiler_mins_on1=80
symbol weekend_boiler_temp1=81 ;word
symbol weekend_boiler_hours_off1=83
symbol weekend_boiler_mins_off1=84
;
symbol weekend_boiler_hours_on2=85
symbol weekend_boiler_mins_on2=86
symbol weekend_boiler_temp2=87 ;word
symbol weekend_boiler_hours_off2=89
symbol weekend_boiler_mins_off2=90
;
symbol weekend_boiler_hours_on3=91
symbol weekend_boiler_mins_on3=92
symbol weekend_boiler_temp3=93 ;word
symbol weekend_boiler_hours_off3=95
symbol weekend_boiler_mins_off3=96
;
; **********************************************************************
;
symbol solar_gain=98 ;solar gain temperature word
;
; settable parameters. NB this is effectively a table, do not change order



and here's a section of the defaults routine to load initial values


;
;
; programmer default values - times and temperatures
;
prgrmr_defaults:
;
; first daily on/off times
;
ptr=wkday_boiler_hours_on1
;
@ptrinc=$07 ;weekday on 1 hour
@ptrinc=$59 ; & minutes
;
@ptrinc=%11111111 ;31.9 degrees
@ptrinc=%00000001
;
@ptrinc=$08 ;weekday off hour
@ptrinc=$45 ; & minutes
;
; second daily on/off times
;
@ptrinc=$12 ;weekday on 2 hour
@ptrinc=$00 ; & minutes
;
@ptrinc=%01100000 ;38 degrees
@ptrinc=%00000010
;
@ptrinc=$14 ;weekday off hour
@ptrinc=$00 ; & minutes
;
; third daily on/off times
;
@ptrinc=$16 ;weekday on 3 hour
@ptrinc=$30 ; & minutes
;
@ptrinc=%11101000 ;46.5 degrees
@ptrinc=%00000010
;
@ptrinc=$22 ;weekday off hour
@ptrinc=$00 ; & minutes
;
; first weekend on/off times
;
 
And as far as the "corruption" of the scratchpad value being due to an interrupt, or mis-aligned scratchpad allocation - well, no. I understand why one would conclude that, because otherwise, what I'm seeing is "impossible".
Yes; that is the logical conclusion. If there's nothing wrong in that code area the issue must lie elsewhere.

But the interrupt acts only on nominated registers, to decrement them until they reach zero.
But how ?

Does it set 'ptr' ? Is it restored to the same value when the interrupt returns as it was when it was entered ?

Does it use 'w3', 'b7' or 'b6' ? Are they all restored to the same value when the interrupt returns as they were when it was entered ?

The scratchpad allocation is sound because if I use "take #15" code everything works as expected - the value can be increased or decreased as required, and when the editor function is left, the scratchpad, as displayed, is stable.
I am not convinced that proves the Scratchpad allocation is sound. I do believe it's coincidental rather than causal, that it's not writing '@ptrInc' in some other way which makes the difference.

I suspect the underlying issue hasn't actually been resolved and will emerge again later.

Sorry if I sound argumentative, but I've spent a lot of time trying to understand what's wrong, and am still no nearer. I've found ways to work around the problem, but that's not really the right solution.
It's understandable, and trying to solve problems can always be frustrating affair. It's also human nature to discount the more likely and imagine a bug in the compiler or firmware once one has convinced oneself everything else is right even when it isn't, and despite a bug being highly unlikely. It becomes a form of tunnel vision which has one fixating on the wrong thing and that's hard to break out of.

In my experience, finding a bug in a compiler or firmware as the explanation for when something doesn't work is a very rare occurrence. Almost all times it's not.

The breakthrough usually comes once one comes to accept such a bug isn't likely, that an area cannot be where the issue is, so must therefore be elsewhere.

The tip I have when stuck banging my head on the desk trying to figure out how something isn't working when it should is to step away from it for a while or overnight. That helps one to get away from trying to fix things to reflecting on what the issue may be.

It might be worthwhile posting your full code as a fresh set of eyes may be see where there may be an issue.
 
Hi Hippy

see my last post - no, the interrupt routine doesn’t alter ptr, or w3, or any of its components.

I guess my logic is almost the reverse of yours - by reducing the problem to a tiny section of code with a go / nogo result - however impossible, that must be the problem! This is entirely reproducible, not a random event.

So of course I suspect that something in the “macro” which is @ptrinc / @ptrdec can go wrong in some circumstances (such as mine).

Signing off for the weekend, but my brain will keep thinking of what else I can try to identify the root cause.
 
Here are all my files - attached for anyone with insomnia. This feels risky, as it probably opens up more questions than it answers, and the code is nowhere near a polished thing. But it does work in the broad sense of running my solar and hot water system. I'm adding new functions, such as the programmer, as I go along.
 

Attachments

The attach system wont let me select the definitions file and the subroutines file which are both included in the slot # files. How do I overcome that ?
 
I guess my logic is almost the reverse of yours - by reducing the problem to a tiny section of code with a go / nogo result - however impossible, that must be the problem! This is entirely reproducible, not a random event.
I would say that's flawed logic. Say your car frequently won't start. Stick a finger in your ear and it starts every time. Conclusion ?

The attach system wont let me select the definitions file and the subroutines file which are both included in the slot # files. How do I overcome that ?
Temporarily rename them as '.bas' and post them, put everything in a '.zip' file and post that, or just paste direct to the forum.

When things get complex they can sometimes become too difficult to debug. It can often be worth going back to first principles and using what you have learned and other techniques to create a better version of things. For example I would have abstracted away my items and initialised them as below -
Code:
#Define DecToBcd(bin) bin / 10 * 6 + bin 

#Macro Init(id, num, onHour, onMins, offHour, offMins, degInt, degDecimal)
  @ptrInc = id
  @ptrInc = num
  @ptrInc = DecToBcd(onHour)
  @ptrInc = DecToBcd(onMins)
  @ptrInc = DecToBcd(offHour)
  @ptrInc = DecToBcd(offMins)
  w0      = degDecimal * 16 / 10
  w0      = degInt * 16 + w0
  @ptrInc = w0 /  256 ; Msb
  @ptrInc = w0 // 256 ; Lsb
  @ptr    = 0
#EndMacro
 
PowerOnReset:
  ptr = 0
  Init("D",1 , 07,59 , 08,45 , 31,9) ; Weekday 1 = 07:59 on, 08:45 off, 31.9 degrees
  Init("D",2 , 12,00 , 14,00 , 38,0) ; Weekday 2 = 12:00 on, 14:00 off, 38.0 degrees
  Init("D",3 , 16,30 , 22,00 , 46,5) ; Weekday 3 = 16:30 on, 22:00 off, 46.5 degrees
  Init("E",1 , 08,00 , 22,00 , 30,0) ; Weekend 1 = 08:00 on, 22:00 off, 30.0 degrees
Not a single SYMBOL definition in sight so far, and it's easy to show each item is correctly programmed as below, singularly or as a whole -
Code:
CheckInitialisation:
  ptr = 0
  Do
    Gosub Dump
  Loop Until ptr = 0
  End

Dump:
  ; If at end of list set ptr to zero otherwise show the entry
  If @ptr = 0 Then
    ptr = 0
  Else
    If @ptrInc = "D" Then
      SerTxd("Weekday")
    Else
      SerTxd("Weekend")
    End If
    SerTxd(" ", #@ptrInc, TAB)
    Gosub DumpHour ; On time
    Gosub DumpMins
    SerTxd(" on", TAB)
    Gosub DumpHour ; Off Time
    Gosub DumpMins
    SerTxd(" off", TAB)
    w0 = @ptrInc * 256 + @ptrDec /  16           : SerTxd(#w0)
    w0 = @ptrInc * 256 + @ptrInc // 16 * 10 / 16 : SerTxd(".", #w0, CR, LF)
  End If
  Return

DumpMins:
  SerTxd(":")
DumpHour:
  b1 = @ptr    / 16
  b0 = @ptrInc // 16
  SerTxd(#b1, #b0)
  Return
Code:
Weekday 1       07:59 on        08:45 off       31.8
Weekday 2       12:00 on        14:00 off       38.0
Weekday 3       16:30 on        22:00 off       46.5
Weekend 1       08:00 on        22:00 off       30.0
 
Probably not related to the issue which seems to be Scratchpad corruption to me; your simple 'inc' and 'dec' on a temperature which has a 4-bit fraction won't work if you are dealing with .0 to .9 decimal fractions.

For example, incrementing 0.1, %0000 0000 0000 0001
gives %0000 0000 0000 0010 which will probably still show as 0.1
not %0000 0000 0000 0011 which is 0.2

Code:
0.0 0000 + 1 = 0001 0.1
0.1 0001 + 1 = 0010       ?
0.2 0011 + 1 = 0100 0.3
0.3 0100 + 1 = 0101       ?
0.4 0110 + 1 = 0111       ?
0.5 1000 + 1 = 1001 0.6
0.6 1001 + 1 = 1010       ?
0.7 1011 + 1 = 1100 0.8
0.8 1100 + 1 = 1101       ?
0.9 1110 + 1 = 1111       ?

Unless you convert from 4-bit to decimal, increment or decrement, then convert back to 4-bit again you are going to have to increment or decrement multiple times to see a decimal fraction change.

And I've discovered an even more fundamental issue with using decimal fractions; creating a 4-bit fraction from decimal with '* 16 / 10' isn't reversible with '* 10 / 16' ...
Code:
0.0 -> 0000 -> 0.0
0.1 -> 0001 -> 0.0
0.2 -> 0011 -> 0.1
0.3 -> 0100 -> 0.2
0.4 -> 0110 -> 0.3
0.5 -> 1000 -> 0.5
0.6 -> 1001 -> 0.5
0.7 -> 1011 -> 0.6
0.8 -> 1100 -> 0.7
0.9 -> 1110 -> 0.8
This is my solution for incrementing or decrementing a temperature when 'ptr' points to the temperature in Scratchpad. I am using Big Endian, storing the MSB first , the LSB next as that makes reading a word a lot easier -
Code:
  ptr = ?
  If up_key_moved = 1 Then
    Gosub IncrementTemperature
  Else If down_key_moved = 1 Then
    Gosub DecrementTempaerature
  End If
  ...

IncrementTemperature:
  Gosub ReadTemperature
  ptr = ptr - 2
  w0  = w0  Max 699 + 1 ; Max 70.0
  Gosub WriteTemperature
  Return

DecrementTemperature:
  Gosub ReadTemperature
  ptr = ptr - 2
  w0  = w0  Min 101 - 1 ; Min 10.0
  Gosub WriteTemperature
  Return

ReadTemperature:
  w0 = @ptrInc & 0   + @ptrDec & 15 * 10 / 16
  w0 = @ptrInc * 256 + @ptrInc / 16 * 10 + w0
  Return

WriteTemperature:
  @ptr = w0 // 10
  ;             0  1  2  3  4  5  6   7   8   9
  LookUp @ptr, (0, 2, 4, 6, 7, 8, 10, 12, 14, 15), @ptr
  w0 = w0 / 10 * 16 + @ptr
  @ptrInc = b1
  @ptrInc = b0
  Return
 
Last edited:
Good afternoon Hippy.

I attach a zip of the whole directory of my program - this includes the subroutines and definitions which are included in the slot sections, as needed.

I was hoping that you might try to reproduce the problem I see, by using all of my files to program a 28X2. I'm using a picaxe28 project board, and an AXE033 display & calendar board, through the I2C interface. The other parts of my system are a second 20x4 display (I2C interface), a simple 6 key keypad, and a number of output relays. For purposes of testing I don't think the string of temperature sensors is necessary. I think one could reproduce the core of my system, sufficient to test the problem, with just another sort of real or simulated "key presses". I hope this helps.

As far as some of your other comments - I think you misunderstand - this code "works" in any reasonable use of the term. Everything that I expect to work, does. The system runs reliably (the previous version ran for over a decade with no obvious problems), and this version uses most of the original subroutines. What's changed is that I've added an extra display, and I'm currently adding functions like an internal programmer. I'm using the space in the 28X2 to add these functions, whereas in the previous chip I'd completely filled the program space, and had to slim functions down, or cut them out.

Specifically, as far as the temperatures - yes, I know that the saved values are in 1/16ths of a degree - that's how they're read from the temperature chips. All storage and comparisons etc are done in that format. But for display, I convert, using a table, from 1/16ths to 1/10ths. If my recent "editing" system requires more than one key press to change the 1/10ths value, well that's ok. It's only meant to be a simple editing system which will be used very rarely. The key press system auto-repeats too.

If you need any other information to re-create the problem, please ask

Cheers
 

Attachments

Back
Top