PDA

View Full Version : Signed 32bit to ASCII?



HenrikOlsson
- 5th May 2010, 11:58
Hello everyone,
I'm looking for a routine to convert a signed 32-bit variable to an ASCII string in order to send it out to a terminal or LCD. I know this is supported with PBPL but I can't afford the overhead PBPL introduces and so far I've managed to get the few 32bit operations (add & subtract) I need working without using PBPL. But now I'm a bit stuck....

Basically I have my 32bit variable declared as two word variables, myVarH and myVarL and I have 30byte array, TxBuffer, that I'm using to send things out thru the USART.

Anyone's got a suitable routine in your "toolbox" that you're willing to share? There are some over at the PICList and I'll try to digest them and get one of them working with PBP but I'd really like to cut some corners here if it's already been done.

TIA
/Henrik.

Darrel Taylor
- 5th May 2010, 21:28
Hi Henrik,

I didn't have anything already made, but using N-Bit_Math (http://www.picbasic.co.uk/forum/showthread.php?t=12433) it only took an hour or so to write and test.

The Main program just sets 4 different values and calls Signed32: to display them
You can use the MOVE? macros to put your value in the Value32 variable.


PRECISION CON 4 SYSTEM ' 4 bytes = 32-bit
INCLUDE "N-Bit_MATH.pbp"

Value32 VAR BYTE[PRECISION]
Divisor VAR BYTE[PRECISION]
Temp32 VAR BYTE[PRECISION]
B32 VAR BYTE[PRECISION]
W1 VAR WORD
Sign VAR BIT

HSEROUT ["Ready-Set-Go",13,10]


Main:
@ MOVE?CP -2147483648, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP 2147483647, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP 1234, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP -1234, _Value32
GOSUB Signed32 : HSEROUT [13,10]
STOP

;----[Send signed 32-bit value via USART]---------------------------------------------------
Signed32:
@ MATH_CLR _Temp32 ; clear Temp32 in case we need ABS
Sign = Value32.0(31) ; If the value is negative
IF Sign THEN
HSEROUT ["-"] ; display a negative sign
@ MATH_SUB _Temp32, _Value32, _Temp32 ; get the absolute value (0-value)
ELSE
@ MOVE?PP _Value32, _Temp32
ENDIF

@ MOVE?CP 1000000, _Divisor
@ MATH_DIV _Temp32, _Divisor, _B32 ; divide by 1,000,000 gets top 4 digits
@ MOVE?PW _B32, _W1 ; copy digits to PBP word var
; @ MATH_MUL _B32, _Divisor, _B32 ; multiply those digits by 1,000,000
; @ MATH_SUB _Temp32, _B32, _Temp32 ; subtract from original value

@ MOVE?CP 1000, _Divisor ; divide remainder by 1,000
@ MATH_DIV REG_Z, _Divisor, _B32 ; 3 digits are in B32, 3 digits in REG_Z

IF W1 > 0 THEN ; W1 still has top 4 digits
HSEROUT [DEC W1] ; if top 4 are > 0, display them
@ MOVE?PW _B32, _W1 ; display next 3 digits (with 0's)
HSEROUT [DEC3 W1]
@ MOVE?PW REG_Z, _W1 ; display lowest 3 digits (with 0's)
HSEROUT [DEC3 W1]
ELSE ; else - top 4 digits are 0
@ MOVE?PW _B32, _W1 ; check next 3 digits
IF W1 > 0 THEN ; if > 0 then display (without 0's)
HSEROUT [DEC W1]
@ MOVE?PW REG_Z, _W1 ; display lowest 3 digits (with 0's)
HSEROUT [DEC3 W1]
ELSE ; else - Top 7 digits are 0
@ MOVE?PW REG_Z, _W1 ; display lowest 3 (without 0's)
HSEROUT [DEC W1]
ENDIF
ENDIF
RETURN

This is the output from the test program.

http://www.pbpgroup.com/files/Signed32_Out.JPG

It could probably benefit from a little optimization, but it works.
HTH,

Darrel Taylor
- 7th May 2010, 20:41
Hi again Henrik,

Not sure if you've seen the code above yet, but I've done a bit more optimization to it.

By mapping word vars to the low word of the 32-bit vars, there's a lot less moving around of values to do between Pvars and PBP word vars.

Here's how it looks now ...

PRECISION CON 4 SYSTEM ' 4 bytes = 32-bit
INCLUDE "N-Bit_MATH.pbp"

Value32 VAR BYTE[PRECISION]
Temp32 VAR BYTE[PRECISION]
Divisor VAR BYTE[PRECISION]

;---Map Word variables onto Low Word of 32-bit variables]----------------------------------
Value32_LW VAR WORD EXT : @Value32_LW = _Value32
Temp32_LW VAR WORD EXT : @Temp32_LW = _Temp32
REG_Z_LW VAR WORD EXT : @REG_Z_LW = REG_Z
W1 VAR WORD

HSEROUT ["Ready-Set-Go",13,10]

Main:
@ MOVE?CP -2147483648, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP 2147483647, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP 1234, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP -1234, _Value32
GOSUB Signed32 : HSEROUT [13,10]

@ MOVE?CP 10, _Value32
GOSUB Signed32 : HSEROUT [13,10]
STOP

;----[Send signed 32-bit value via USART]---------------------------------------------------
Signed32:
IF Value32.0(31) THEN ; If the value is negative
HSEROUT ["-"] ; display a negative sign
@ MATH_CLR _Temp32 ; clear Temp32 for ABS
@ MATH_SUB _Temp32, _Value32, _Temp32 ; get the absolute value (0-value)
ELSE ; else - value is already positive
@ MOVE?PP _Value32, _Temp32 ; copy it to Temp var
ENDIF

@ MOVE?CP 1000000, _Divisor
@ MATH_DIV _Temp32, _Divisor, _Temp32 ; divide by 1,000,000 gets top 4 digits
@ MOVE?PW _Temp32, _W1 ; copy digits to PBP word var
@ MOVE?CP 1000, _Divisor ; divide remainder by 1,000
@ MATH_DIV REG_Z, _Divisor, _Temp32 ; 3 digits are in Temp32, 3 digits in REG_Z

IF W1 > 0 THEN ; if top 4 are > 0
HSEROUT [DEC W1, DEC3 Temp32_LW, DEC3 REG_Z_LW] ; display all 7-10 digits
ELSE ; else - top 4 digits are 0
IF Temp32_LW > 0 THEN ; check next 3 digits
HSEROUT [DEC Temp32_LW, DEC3 REG_Z_LW] ; if > 0 then display 4-6 digits
ELSE ; else - Top 7 digits are 0
HSEROUT [DEC REG_Z_LW] ; display lowest 3
ENDIF
ENDIF
RETURN

The output is identical to the previous post. (+10)

HTH,

HenrikOlsson
- 7th May 2010, 21:29
Hi Darrel,
Sorry for the late reply. I did see it and I really appreciate the help - as usual. I was hoping someone had something already - not that someone would spend the time writing it for me....it makes me feel I owe you more than I already do...

With that said, I'm not currently using N-bit_Math in may project. As I've only needed add and subtract I've been using the routines I adapted from the PICList and it's been working perfectly so I've had no need to change it. Apparently though this ASCII conversion was harder than I initially thought. If changing over my other 32-bit operations to N-bit_math in order to get the ASCII conversion going is the easiest way to go forward than I'll need to take it into consideration.

Any idea of the execution time?

Thanks again Darrel, I really appreciate all your work!

/Henrik.

Darrel Taylor
- 7th May 2010, 22:13
If changing over my other 32-bit operations to N-bit_math in order to get the ASCII conversion going is the easiest way to go forward than I'll need to take it into consideration.
I see no reason to change what you have if it works already.

In post#1 you indicated the value was in myVarH and myVarL.
If you changed those word variables so they are mapped to Value32, you could display your existing values with very little modification. Just GOSUB Signed32.


myVarH VAR WORD EXT : @myVarH = _Value32 + 2
myVarL VAR WORD EXT : @myVarL = _Value32




Any idea of the execution time?
No, I could run some tests in the SIM though.
I'll get back on that.