Problem with string manipulation

I'm trying to write a function that will take a signed integer (maximum 5 digits) and convert it to a string of the form XX.XXX with optional sign display. This string will then be displayed on a VFD. I know my VFD implementation is correct because if I use the Numbers or Simple_Numbers object to create the string, it displays correctly. However, the following code seems like it should work but it just shows garbled characters on the VFD.
stringvar is a global array with 8 elements. Can anyone see any glaring errors? I compared it to the string object in Simple_Numbers and the procedure seems very similar. One thing that's still tripping me up with Spin is knowing when I need to use the pointer @ symbol in front of a variable. I'm using @stringvar[0] as the argument in my VFD send string function, as I want to specify the address of the first character (I think). I'd appreciate any suggestions!
PUB PosToString(value,signdisp) | idx, divisor
bytefill(stringvar, " ", 8) 'Clear array
stringvar[7] := 0 'Add zero terminator
if signdisp == 2 AND value => 0 'Determine sign character
stringvar[0] := "+"
elseif signdisp > 0 AND value < 0
stringvar[0] := "-"
else
stringvar[0] := " "
value := ||(-99_999 #> value <#= 99_999) 'Constrain value to 5 digits, remove sign
divisor := 10_000
repeat idx from 1 to 5
stringvar[idx] := value / divisor + "0"
value //= divisor
divisor /= 10
repeat idx from 5 to 3 'Shift digits and add decimal point
stringvar[idx+1] := stringvar[idx]
stringvar[3] := "."
if stringvar[1] == "0" 'Remove leading zero
stringvar[1] := " "
stringvar is a global array with 8 elements. Can anyone see any glaring errors? I compared it to the string object in Simple_Numbers and the procedure seems very similar. One thing that's still tripping me up with Spin is knowing when I need to use the pointer @ symbol in front of a variable. I'm using @stringvar[0] as the argument in my VFD send string function, as I want to specify the address of the first character (I think). I'd appreciate any suggestions!
Comments
PUB strsend(stringptr) repeat strsize(stringptr) ser.tx(byte[stringptr++])
Strsend is called with argument @stringvar[0] as I mentioned. I can display strings on the VFD all day long using this method (including those generated by Numbers.spin), but my PosToString method just shows garbage characters. Unfortunately I don't remember exactly what characters are shown and I don't have access to the controller at the moment. I'll fire it up tonight and see if I can figure out what it's showing. Thanks for your help.
If memory serves me correct, the output I am getting on the VFD with this code is a single ASCII character $9D (at least, that's what it looks like in my ASCII chart) and the rest spaces, regardless of the input value. So I admit that "garbage characters" plural was a bit of an exaggeration--there's only one.
I will get more information tonight and post back.
pub val2display(val, showsign, spntr) | divisor, idx ' show sign if value is negative, or positive and showsign is true if (val < 0) byte[spntr++] := "-" ' always show negative sign else if (showsign) ' selective display for positives byte[spntr++] := "+" else byte[spntr++] := " " val := ||(-99_999 #> val <# 99_999) ' constrain to 5 digits divisor := 10_000 ' set intial divisor repeat idx from 0 to 5 ' 5 digits plus decimal if (idx == 2) ' if decimal position byte[spntr++] := "." ' put . else ' else result := val / divisor ' extract digit from val if ((idx == 0) and (result == 0)) ' check for leading zero byte[spntr++] := " " ' no lz else byte[spntr++] := result + "0" ' print digit val //= divisor ' update val divisor /= 10 ' update divisor byte[spntr] := 0 ' terminate string
It does the same thing you're doing, just in a single loop. Another way to skin the cat as it were....
You can move a value to the buffer like this:
val2display(someVar, true, @buffer)
... where buffer is a byte array big enough to hold the string (plus one for the trailing zero). After that, you should be able to use the .str() method in FDS:
vfd.str(@buffer)
Thanks for the code, I can't wait to try it out.
By modifying your method to accept a string pointer, you have a bit more flexibility: you could, for example, prepare two strings (requires two buffers) and via your HMI switch between them without having to re-run the conversion method.
2. It uses a FIFO buffer to retain multiple string results at once.
I haven't submitted it to the OBEX, though, because there is still one thing I want to modify. The "fixed-width" decimal-to-string routines are not really fixed-width, since they add a character position for negative numbers to accommodate the sign. This causes column misalignment in mixed-sign displays. I'd like to change that behavior, but haven't gotten around to it yet.
-Phil