Strange behavior with variable

I am seeing some strange behavior and I cant figure it out. I have pasted the code in question. The issue is displayStep is called and the defined string is displayed. displayStepTemp is called and displays the string built in displayStep. I have tried using bytefill before and after each call and even tried using it in each routine. I always get the same result. Any insight would be much appreciated.
  byte buffer[100]   


PUB displayStepTemp
  fmt.sprintf(@buffer,string("Temp: %-3d"),getTemp(mStep))
  disp.DrawStringSmall (106, 80, @buffer)
PUB displayStep
  fmt.sprintf(@buffer,string("Step: %-3d"),mStep)
  disp.DrawStringSmall (106, 60, @buffer)


  • Without actually creating a stand-alone variant of this program to see if I could duplicate this behavior, I have this question:

    What happens if you call "displayStepTemp" first before "displayStep"?

    Does the same issue occur with having the 2nd routine displaying the data from the 1st?
  • Yes it does
  • It would likely take a bit of work, but if you created a stand alone program which included all the code to demonstrate the problem, I think others (or possibly yourself) would have a better chance of finding the problem. Problems like this can hide in strange places.

    An archive any of us could load, would likely be a big help in finding the problem.
  • Well said posting the entire code would sure make it easier
  • I did a bunch more debugging today. My code is fine. The problem is in the ILI9341 object. I am not very well versed in assembly so I cant really debug it. I found a work around, its not pretty but it works.
  • Post all your actual code Greg, especially the objects. You can create a zip archive and post that.

    btw, my Spin may be a bit rusty, but the @ is needed for a DAT variable to get the address, but do we need it for a VAR?
  • the @ is needed for a DAT variable to get the address, but do we need it for a VAR?

    VAR and DAT variable addresses are treated the same in Spin.

    I didn't see anything obviously wrong with the code as posted.
  • Attached is all the code. I had tried all kinds of things like renaming procedures renaming variables changing the declaration orders etc. The giveaway was I started dumping variable values to the serial terminal and found the variables actually had the correct values however the values coming out of the lcd display object were not matching. for some weird reason calling the DrawString procedure in between the two display procedures which call the DrawStringSmall procedure seems to fix the issue, however now it is not drawing the screen in order from top to bottom, not a big deal but it just bugs me!

    The issue seems to be within the ILI9341-spi. It came from the OBEX and is mostly assembly. My assembly skills are nearly nil.

    The fix I found to work is the following

    disp.DrawString (91, 100, timer.showTimer)

    disp.DrawString (91, 100, timer.showTimer)
  • You zip is missing the object for the ADS1118
  • @JonnyMac I just downloaded the zip and it is definitely in there.
  • JonnyMacJonnyMac Posts: 6,995
    edited 2020-10-17 - 21:04:55
    My mistake -- I missed it when copying to a temp folder to look at the program.

    I just did a little test with this code
    pub main
      fmt.sprintf(@buffer,string("MASH Temp: %-3d"), 25)
      fmt.sprintf(@buffer,string("MASH Step: %-3d"),  7)
    The output is as expected.
    MASH Temp: 25
    MASH Step: 7
    What are you seeing when there is a problem? What do you want the output to look like?
  • The issue is the LCD driver. buffer always has the correct value, but when calling displayMashStep and DisplayMashStepTemp in succession the value set by the first call is displayed by both.
  • Have you tried to reach out to the author? That code is a bit involved.

    On another note, I was looking at the countdown timer code and thought that the timing loop looked out of whack. When doing precise timing in a loop, what you want to do is synchronize with the system counter outside of the loop, and then add your delay to the timing variable for waitcnt() inside the loop. Generically, like this:
      t := cnt
        ' so something
        waitcnt(t += LOOP_TICKS)
    In the code you have, the cnt register is being accessed during every waitcnt call. To be honest, I thought the loop would run slow, but it turns out it runs fast. I've had the code running for nearly an hour and it's fast by about 40 seconds. Funny, some of that code in that object looks like I wrote it (my styling in some parts of it -- perhaps elements were borrowed from something else I wrote). I did write another timer object, though, and compared that with the one you're using and against accumulations of the system counter. If you let the attached code run for a while you'll see that the timer you're using is fast. I think it's in the way that it's processing the values to stop at the end. In my countdown timer I use BCD registers (like RTCs do) to eliminate divide and modulus (which are slow).
  • The countdown_timer came from obex. It looks like it was derived from the original parallax timer object. It had a few bugs in it and I couldnt get it to work so I rewrote the loop. I will take a look at yours. I have not reached out to the original author. I can try that.

    here is the original loop. as you can see if it starts with the seconds register = 0 it counts negative and craps out.
       tix := 99
          if running
             waitcnt(clkfreq/ TIX_DLY + cnt)
             tix := --tix
               if (tix == 0)
                  tix := 100
                  if (scs == 0) AND (mns > 0)
                     scs := 60
                     if (mns == 0) AND (hrs > 0)
                        mns := 59
                        if (hrs == 0)
                  if (scs == 0) AND (mns == 0 )

    Thanks for the insight and the code!
  • JonnyMacJonnyMac Posts: 6,995
    edited 2020-10-18 - 17:28:19
    Try the test code I attached -- you'll see that the timer you're presently using runs fast. I used two different time sources for comparison to make sure. Again, with a synchronized loop, you want to grab count just before going into the loop, then add the loop timing in the waitcnt statement. Your object had a hold function which I duplicated, so the affects the timing loop by resynchronizing it with the system counter. That said, when the loop is in run state, there is no need to access the system counter inside the loop as this adds unnecessary padding.
Sign In or Register to comment.