; *********************************************************************** ; BIN24_SIGNED_TOSTRING - Routine convert a 24 bit *signed* value to ASCII ; string, including decimalpoint and minus sign ; True ASCII conversion, surpress leading zeroes. ; Result and input in ram variable AString (10 bytes). ; 24 bit binary value to be converted is to be stored in ram AString+6 -> AString+8 ; ASCII output will be saved in AString with first character either ' ' (positive) or '-'(negative) ; followed by ASCII digits '0'-'9' and eventual decimalpoint '.' ; Leading zeros will be converted to ' '(space) ; Last byte of AString ( AString+9 ) will be used for decimalpoint calculation ; and will always be zero if decimalpoint is used, else second last byte of AString will ; be zero instead. I.e. string ALWAYS null terminated. ; Decimalpoint placement is fetched from global var DpPlacement where >=8 = no dp ; 7 = one digits after dp, 6=two digits after dp ... 1=7 digits after dp. ; ; Some notes: AString+6 is MSB in 24 bit sample ( LSB=AString+8 ) ; AString+9 is used for temporal use to determine where to put decimalpoint ; ; Radix = decimal ; ; Input MSb = String+6 ; Input middle = String +7 ; Input Lsb = String+8 BIN24_SIGNED_TOSTRING GLOBAL BIN24_SIGNED_TOSTRING BCF _DpUsed BCF _PrevIsSpace MOVFF DpPlacement,String+9 ; copy dp placement to last byte in string ( not used for characters ) MOVLW BYTE_OFFSET ; preset with ASCII offset MOVWF AString MOVWF AString+1 MOVWF AString+2 MOVWF AString+3 MOVWF AString+4 MOVWF AString+5 BCF AString,4 ; clear bit, makes first char 'space' ; test if negative BTFSS AString+6,7 ; i.e top bit of 24 bit value set BRA TEST_TOPNIBBLE ; nope positive, test if 'small' value ; negative then make 2's complement and set first char to '-' ; make two's complement COMF AString+8,F COMF AString+7,F COMF AString+6,F ; add one MOVLW 1 ADDWF AString+8,F SKPNC ADDWF AString+7,F SKPNC ADDWF AString+6,F MOVLW SIGN_NEGATIVE MOVWF AString ; first digit minus sign TEST_TOPNIBBLE ; test if top nibble is zero, i.e. number less than 1048575 ( decimal ) ; if so we can skip to sub300k routine MOVF AString+6,W ANDLW 0x70 ; Mask out top three bits BNZ SUB4M ; nope do full conversion ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+1,4 ; cleaar bit to make second character space BRA SUB300k ; continue SUB4M: ; subtract 4 million from sample MOVLW 4 ADDWF AString+1,F MOVLW LOW(4000000) SUBWF AString+8,F MOVLW LOW(4000000>>8) SKPC MOVLW LOW(4000000>>8)+1 SUBWF AString+7,F MOVLW LOW(4000000>>16) SKPC MOVLW LOW(4000000>>16)+1 SUBWF AString+6,F SKPNC ; overfLOW, i.e. negative then add 1 million until positive again BRA SUB4M ADD1M: ; add 1 million to sample DECF AString+1,F MOVLW LOW(1000000) ADDWF AString+8,F MOVLW LOW(1000000>>8) SKPNC MOVLW LOW(1000000>>8)+1 ADDWF AString+7,F MOVLW LOW(1000000>>16) SKPNC MOVLW LOW(1000000>>16)+1 ADDWF AString+6,F SKPC ; done ? BRA ADD1M ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF AString+1,W BNZ SUB300k ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+1,4 SUB300k: ; substract 300 thousand from sample MOVLW 3 ADDWF AString+3,F MOVLW LOW(300000) SUBWF AString+8,F MOVLW LOW(300000>>8) SKPC MOVLW LOW(300000>>8)+1 SUBWF AString+7,F MOVLW LOW(300000>>16) SKPC MOVLW LOW(300000>>16) + 1 SUBWF AString+6,F SKPNC ; if negative then start adding 100k until positive again BRA SUB300k ADD100k ; add 100 thousand to sample DECF AString+3,F MOVLW LOW(100000) ADDWF AString+8,F MOVLW LOW(100000>>8) SKPNC MOVLW LOW(100000>>8) + 1 ADDWF AString+7,F MOVLW LOW(100000>>16) SKPNC MOVLW LOW(100000>>16) + 1 ADDWF AString+6,F SKPC ; done BRA ADD100k ; test for overfLOW ( AString+3 = 10 ) ; due to test on top nibble where we skip add/sub million loops MOVLW BYTE_OFFSET+0x0A SUBWF AString+3,W BTFSS STATUS,Z ; test if non zero BRA ADD100k_TstDp ; over fLOW, result is = 10, second digit = 1, third = 0 MOVLW BYTE_OFFSET MOVWF AString+3 BTFSS _DpUsed ; test if dp already used BSF AString+1,0 ; if no dp used set this digit to one BSF AString+2,0 ; set also third digit to 1 ( in case dp is used ) ; restore previous digit BTFSS _PrevIsSpace BRA ADD100k_TstDp BSF AString+1,4 ; set to space temporarily BCF _PrevIsSpace ADD100k_TstDp: ; test for dp DECFSZ AString+9,F ; test for dp placement BRA ADD100k_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF AString+2 ; dp is third digit ; restore zero before dp BTFSC _PrevIsSpace BSF AString+1,4 BRA SUB30k ; continue ADD100k_NoDp: ; no dp copy back number MOVFF AString+3String+2 ; restore ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF AString+2,W BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB30k BTFSS _PrevIsSpace BRA SUB30k ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+2,4 ; set to space SUB30k: ; subtract 30'000 from sample MOVLW 3 ADDWF AString+4,F MOVLW LOW(30000) SUBWF AString+8,F MOVLW LOW(30000>>8) SKPC MOVLW LOW(30000>>8)+1 SUBWF AString+7,F MOVLW LOW(30000>>16) SKPC MOVLW LOW(30000>>16) + 1 SUBWF AString+6,F SKPNC ; negative ? BRA SUB30k ADD10k: ; add 10'000 to sample DECF AString+4,F MOVLW LOW(10000) ADDWF AString+8,F MOVLW LOW(10000>>8) SKPNC MOVLW LOW(10000>>8) + 1 ADDWF AString+7,F MOVLW LOW(10000>>16) SKPNC MOVLW LOW(10000>>16) + 1 ADDWF AString+6,F SKPC ; done ? BRA ADD10k BTFSC _DpUsed BRA SUB3k ; dp is already used continue ; test for dp DECFSZ AString+9,F ; test for dp placement BRA ADD10k_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF AString+3 ; dp is fourth digit ; restore zero before dp BTFSC _PrevIsSpace BSF AString+2,4 ; set to zero BRA SUB3k ; continue ADD10k_NoDp: ; no dp copy back number MOVFF AString+4String+3 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF AString+3,W BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB3k BTFSS _PrevIsSpace BRA SUB3k ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+3,4 SUB3k: ; subtract 3000 from sample MOVLW 3 ADDWF AString+5,F MOVLW LOW(3000) SUBWF AString+8,F MOVLW LOW(3000>>8) SKPC MOVLW LOW(3000>>8)+1 SUBWF AString+7,F SKPNC ; negative ? BRA SUB3k ADD1k: ; add 1000 to sample DECF AString+5,F MOVLW LOW(1000) ADDWF AString+8,F MOVLW LOW(1000>>8) SKPNC MOVLW LOW(1000>>8) + 1 ADDWF AString+7,F SKPC BRA ADD1k BTFSC _DpUsed BRA SUB300_PreLoad ; dp is already used continue ; test for dp DECFSZ AString+9,F ; test for dp placement BRA ADD1k_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF AString+4 ; dp is fifth digit ; restore zero before dp BTFSC _PrevIsSpace BSF AString+3,4 BRA SUB300_PreLoad ; continue ADD1k_NoDp: ; no dp copy back number MOVFF AString+5String+4 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF AString+4,W BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB300_PreLoad BTFSS _PrevIsSpace BRA SUB300_PreLoad ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+4,4 SUB300_PreLoad MOVLW BYTE_OFFSET MOVWF AString+6 SUB300: ; subtract 300 from sample MOVLW 3 ADDWF AString+6,F MOVLW LOW(300) SUBWF AString+8,F MOVLW LOW(300>>8) SKPC MOVLW LOW(300>>8)+1 SUBWF AString+7,F SKPNC ; negative ? BRA SUB300 MOVLW 100 ADD100: ; add 100 to sample DECF AString+6,F ADDWF AString+8,F SKPC BRA ADD100 INCF AString+7,F BTFSC AString+7,7 BRA ADD100 BTFSC _DpUsed BRA SUB30_PreLoad ; dp is already used continue ; test for dp DECFSZ AString+9,F ; test for dp placement BRA ADD100_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF AString+5 ; dp is sixth digit ; restore zero before dp BTFSC _PrevIsSpace BSF AString+4,4 BRA SUB30_PreLoad ; continue ADD100_NoDp: ; no dp copy back number MOVFF AString+6String+5 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF AString+5,W BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB30_PreLoad BTFSS _PrevIsSpace BRA SUB30_PreLoad ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+5,4 SUB30_PreLoad: MOVLW 30 SUB30: ; subtract 30 from sample INCF AString+7,F SUBWF AString+8,F SKPNC BRA SUB30 MOVF AString+7,W RLCF AString+7,F ADDWF AString+7,F MOVLW 10 ADD10: ; add 10 to sample DECF AString+7,F ADDWF AString+8,F SKPC BRA ADD10 MOVLW BYTE_OFFSET ADDWF AString+7,F BTFSC _DpUsed BRA LAST_DIGIT ; dp is already used continue ; test for dp DECFSZ AString+9,F ; test for dp placement BRA ADD10_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF AString+6 ; dp is seventh digit ; restore zero before dp BTFSC _PrevIsSpace BSF AString+5,4 BRA LAST_DIGIT ; continue ADD10_NoDp ; no dp copy back number MOVFF AString+7String+6 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF AString+6,W BNZ LAST_DIGIT BTFSS _PrevIsSpace BRA LAST_DIGIT ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF AString+6,4 LAST_DIGIT: MOVLW BYTE_OFFSET ADDWF AString+8,W MOVWF AString+8 BTFSS _DpUsed MOVWF AString+7 ; save in previous byte BTFSC _DpUsed RETURN DECFSZ AString+9,F ; test for dp placement BRA CLEAR_LAST ; no dp used at all ?? MOVLW DECIMAL_POINT ; MOVWF AString+7 ; dp is eigth digit ; restore zero before dp BTFSC _PrevIsSpace BSF AString+6,4 RETURN CLEAR_LAST: ; no dp used, clear last digit BTFSS _DpUsed CLRF AString+8 ; clear last digit no dp used RETURN