;
; Program P95WXDS pro mereni teploty z cidla SMT 160 pomoci mikroprocesoru
; PIC 12F629 nebo 12F675 a posilani namerene hodnoty ve formatu pro 
; DIGI_NED (na telemetry vstup - paralelni port)
; verze 1.0 z 18.2.2003 (Tomas OK1VCF)
; Cidlo SMT pripojit na pin GP3, 4 bity vystupu na GP1, GP2, GP4, GP5, 
;  s tim, ze GP1 je high bit a GP5 low bit. Je-li na pinu GP0 log. 0, posle PIC
;  na GP1,2,4,4 dolni 4 bity teploty, je-li na GP0 log. 1 posle horni 4 bity
;  vysledku. Posila hodnotu ve F, (0-255), kde 0 je -40F, 1=-39F, ...
;
; Program je siren jako HamWare - tzn. pro radiomaterske vyuziti zdarma.
;
; Hodne radosti s WX na APRS preje Tomas OK1VCF!
;

	LIST P=PIC12F675, R=DEC
	include<p12f675.inc>

BIT_SELECT	EQU	000H		; Rizeni z DIGI_NEDu (GP0)
SMT_IN		EQU	003H		; INPUT PIN pro cidlo SMT 160 (GP3)
DN_BIT_A	EQU	005H		;  (GP5)
DN_BIT_B	EQU	004H		;  (GP4)
DN_BIT_C	EQU	002H		;  (GP2)
DN_BIT_D	EQU	001H		;  (GP1)

		; RAM 20h-35h pouziva aritmetika
DN_F_Tepl	EQU	036H		; Teplota v DIGI_NED formatu (F)
intWsave	EQU	037H		; Sem schovat obsah W pri preruseni
intSTATUSsave	EQU	038H		; Sem schovat STATUS pri preruseni 
intPCLATCHsave	EQU	039H		; Sem schovat PCLATCH pri preruseni

poc_mer		EQU	03AH		; registr poctu mereni 
horniSOUCET	EQU	03BH		; horni bity scitaneho mereni
SOUCET		EQU	03CH		; dolni bity scitaneho mereni
countH		EQU	03DH		; horni bity teplotni smycky
countL		EQU	03EH		; dolni bity teplotni smycky
stridaH		EQU	03FH		; namerena strida SMT horni
stridaL		EQU	040H		; namerena strida SMT dolni
	
;temp0		EQU	041H		; pomocny registr
;temp1		EQU	042H		; pomocny registr
;temp2		EQU	043H		; pomocny registr
		; RAM 44h-7Fh a v dalsich bankach rezervovany pro dalsi vyvoj
							

		ORG	0000H

Zacatek		
		MOVLW	07H			; 
		MOVWF	CMCON			; odpojit komparatory
		CALL	Init_IO			; Nastavit I/O
		GOTO	Start_Mereni		; Hop do hl. prg

		ORG	0004H

		; Obsluha_Preruseni
		BCF	INTCON, GIE		; Globalni zakaz preruseni
		MOVWF	intWsave		; uschovat W sem
		SWAPF	STATUS,W		; uschovat
		MOVWF	intSTATUSsave		; STATUS sem
		MOVF	PCLATH,W		; uschovat
		MOVWF	intPCLATCHsave		; PCLATCH sem
		BTFSS	GPIO, BIT_SELECT	; Zmena 1>>0 ?
		GOTO	Poslat_dolni		; ano, poslat dolni bity
		GOTO	Poslat_horni		; ne, poslat horni bity

Poslat_dolni
		MOVLW	b'00001001'		; Vynulovat G1,2,4,5
		ANDWF	GPIO, F			;
		BTFSC	DN_F_Tepl, 0		; A nastavit kdyz je
		BSF	GPIO, DN_BIT_A		; nastaven bit v teplote
		BTFSC	DN_F_Tepl, 1		;
		BSF	GPIO, DN_BIT_B		;
		BTFSC	DN_F_Tepl, 2		;
		BSF	GPIO, DN_BIT_C		;
		BTFSC	DN_F_Tepl, 3		;
		BSF	GPIO, DN_BIT_D		;
		GOTO	Prerus_end		; a hotovo

Poslat_horni
		MOVLW	b'00001001'		; Vynulovat G1,2,4,5
		ANDWF	GPIO, F			;
		BTFSC	DN_F_Tepl, 4		; A nastavit kdyz je
		BSF	GPIO, DN_BIT_A		; nastaven bit v teplote
		BTFSC	DN_F_Tepl, 5		;
		BSF	GPIO, DN_BIT_B		;
		BTFSC	DN_F_Tepl, 6		;
		BSF	GPIO, DN_BIT_C		;
		BTFSC	DN_F_Tepl, 7		;
		BSF	GPIO, DN_BIT_D		;
		GOTO	Prerus_end		; a hotovo

Prerus_end
		BCF	INTCON,GPIF		; shodit bit preruseni od TMR0
		MOVF	intPCLATCHsave,W	; obnovit  
		MOVWF	PCLATH			; PCLATCH
		SWAPF	intSTATUSsave,W		; obnovit
		MOVWF	STATUS			; STATUS
		SWAPF	intWsave,F		; a konecne 
		SWAPF	intWsave,W		; obnovit i W
		BSF	INTCON, GIE		; Globalni povoleni preruseni
		RETFIE				; Return from interrupt


Start_Mereni					; Mereni SMT-160 teploty 
		MOVLW	010H			; merime 16x
		MOVWF	poc_mer			; zde je pocitadlo
		CLRF	SOUCET			;
		CLRF	horniSOUCET		;

Mer_smycka	CALL	Mereni			;
		MOVF	stridaH, W		; 
		BCF	STATUS, 0		; vynulovat CY
		ADDWF	SOUCET, F		; pricist vysledek mereni
		BTFSC	STATUS,0		;
		INCF	horniSOUCET, F		; pretekl-li soucet, pricist to sem
		DECFSZ	poc_mer, F		; odecist pocet mereni
		GOTO 	Mer_smycka		; jeste budeme merit
	
 		; Spocitat prumer, tzn vydelit poctem mereni (16)
		; a dostaneme pocet pulstupnu (pocitano od -68C)
		; proto budeme delit 32 a nasobit 10 a dostaneme
		; pocet desetin stupnu (pocitano od -68C), pak
		; k vysledku pricist -680 desetin stupne a hotovo
		; 10/32 = 0.3125
		; 0.3125 = 7D 20 00 00 float (z fprep.exe)
		;   -680 = 88 AA 00 00 float (z fprep.exe)

		CLRF	AARGB0			; vynulovat
		MOVF	horniSOUCET, W		; vzit horni bity
		MOVWF	AARGB1			; a dat je sem
		MOVF	SOUCET, W		; vzit dolni bity
		MOVWF	AARGB2			; a dat je sem
		CALL	FLO2432			; prevest
		; 0.3125 = 7B 20 00 00 float (z fprep.exe)
		MOVLW	07DH			; Pripravit nasobeni cislem
		MOVWF	BEXP			; 0.078125
		MOVLW	020H			; 
		MOVWF	BARGB0			; 
		CLRF	BARGB1			; 
		CLRF	BARGB2			; 
		CALL	FPM32			; vynasobit
		;     -680 = 88 AA 00 00 float (z fprep.exe)
		MOVLW	088H			; Pripravit pricteni cisla
		MOVWF	BEXP			; -680
		MOVLW	0AAH			; 
		MOVWF	BARGB0			; 
		CLRF	BARGB1			; 
		CLRF	BARGB2			; 
		CALL	FPA32			; secist

		; Prevest C na F dle vzorce $F = (1.8 * $C) + 32
		; pro pocet desetin C je to $F = (0.18 * $C) + 32
		; a pro digined jeste offset o 40F nebot -40F = 0
		; takze pricitat se bude 32 + 40 = 72
		;    32d = 84 00 00 00 float (z fprep.exe)
		;  0.18d = 7C 38 51 EC float (z fprep.exe)
		;    72d = 85 10 00 00 float (z fprep.exe)
		MOVLW	07CH			; Pripravit nasobeni cislem
		MOVWF	BEXP			; 0.18
		MOVLW	038H			; 
		MOVWF	BARGB0			; 
		MOVLW	051H			; 
		MOVWF	BARGB1			; 
		MOVLW	0ECH			; 
		MOVWF	BARGB2			; 
		CALL	FPM32			; vynasobit
		;   32d  = 84 00 00 00 float (z fprep.exe)
		;   72d  = 85 10 00 00 float (z fprep.exe)
		MOVLW	085H			; Pripravit pricteni cisla
		MOVWF	BEXP			; 72
		MOVLW	010H			;
		MOVWF	BARGB0			; 
		CLRF	BARGB1			; 
		CLRF	BARGB2			; 
		CALL	FPA32			; secist

		CALL	INT3224			; a prevest na int 
		
		BTFSS	AARGB0, 7		; mame zaporne stupne F?
		GOTO	F_kladne		; ne, jsou kladne
		CLRF	AARGB2			; teplota pod -40F = 0 !

F_kladne					;

		MOVF	AARGB2, W		; teplota je jen v tomto BYTu
		MOVWF	DN_F_Tepl		; a ulozime ji sem, odesila se
						; pres preruseni

		GOTO	Start_Mereni		; A cele znova


Mereni		; Rutina popsana Ondrejem Vitousem na HW serveru
		MOVLW	020H			; merime 108ms (425*32*8us)
		MOVWF	countL			; 435*32*8=1360=3520 +
		MOVLW	036H			; cyklus pro countL
		MOVWF	countH			; = 3620h

		CLRF	stridaL			; vynulovat citace
		CLRF	stridaH			; stridy
		BCF	STATUS, 2		; vynulovat Z
		
smycka9		nop				; 1 kazdy 256 cykl = 9us
smycka8		BTFSC	GPIO, SMT_IN		; 1/2
		INCF	stridaL, F		; 2	zvysit, pokud je SMT_IN log. 1
		BTFSC	STATUS, 2		; 3/4 
		INCF	stridaH, F		; 4	zvysit, pokud pretekl reg
			
		DECFSZ	countL, F		; 5/6
		GOTO	smycka9			; 6+1=7
		DECFSZ	countH, F		; 7/8
		GOTO	smycka8			; 7+1=8

		BCF	STATUS, 0		; 1 vynulovat CY
		RLF	stridaL, F		; 1 a odroloval
		RLF	stridaH, F		; 1 v ramci 
		RLF	stridaL, F		; 1 dvoubajtoveho
		RLF	stridaH, F		; 1 registru
		RLF	stridaL, F		; 1 32*, tzn mame
		RLF	stridaH, F		; 1 pocet pulstupnu

		RETURN				;

Init_IO
		BSF	STATUS,RP0		; Select page 1 (80H - FFH)
		CLRF	ANSEL			; Pro 12F675 odpojeni A/D
		CALL	03FFH			; Vyzvednout OSCCAL value
		MOVLW	OSCCAL			; A ulozit ho sem
		BCF	TRISIO,DN_BIT_A		; Nastavit vystup
		BCF	TRISIO,DN_BIT_B		; Nastavit vystup
		BCF	TRISIO,DN_BIT_C		; Nastavit vystup
		BCF	TRISIO,DN_BIT_D		; Nastavit vystup
		BSF	IOCB, BIT_SELECT	; Povolit INT on CHANGE na GP0
		BSF	INTCON, GPIE		; Povolit INT on CHANGE preruseni
		BCF	STATUS,RP0		; Select page 0 (00H - 7FH)
		BCF	GPIO,DN_BIT_A		; Vystup nastavit do LOW
		BCF	GPIO,DN_BIT_B		; Vystup nastavit do LOW
		BCF	GPIO,DN_BIT_C		; Vystup nastavit do LOW
		BCF	GPIO,DN_BIT_D		; Vystup nastavit do LOW
		BCF	INTCON,GPIF		; shodit bit preruseni od GPIO
		BSF	INTCON, GIE		; Globalni povoleni preruseni

		RETURN				; Return from subroutine

;*********************************************************************************************
;*********************************************************************************************
;*********************************************************************************************
;	RCS Header $Id: math16.inc 2.4 1997/02/11 16:58:49 F.J.Testa Exp $

;	$Revision: 2.4 $

;       MATH16 INCLUDE FILE
;
;       IMPORTANT NOTE: The math library routines can be used in a dedicated application on
;       an individual basis and memory allocation may be modified with the stipulation that
;       on the PIC17, P type registers must remain so since P type specific instructions
;	were used to realize some performance improvements.

;*********************************************************************************************
;
;       GENERAL MATH LIBRARY DEFINITIONS
;
;	general literal constants

;	define assembler constants

B0		equ	0
B1		equ	1
B2		equ	2
B3		equ	3
B4		equ	4
B5		equ	5
B6		equ	6
B7		equ	7

MSB		equ	7
LSB		equ	0


;     define commonly used bits

;     STATUS bit definitions

		#define	_C		STATUS,0
		#define	_Z		STATUS,2

;
;       general register variables (od 0x20H do 0x34H vcetne)
;

ACCB7           equ     0x20
ACCB6           equ     0x21
ACCB5           equ     0x22
ACCB4           equ     0x23
ACCB3           equ     0x24
ACCB2           equ     0x25
ACCB1           equ     0x26
ACCB0           equ     0x27
ACC             equ     0x27    ; most significant byte of contiguous 8 byte accumulator
;
SIGN            equ     0x29    ; save location for sign in MSB
;
TEMPB3          equ     0x30
TEMPB2          equ     0x31
TEMPB1          equ     0x32
TEMPB0          equ     0x33
TEMP            equ     0x33    ; temporary storage
;
;       binary operation arguments
;
AARGB7          equ     0x20
AARGB6          equ     0x21
AARGB5          equ     0x22
AARGB4          equ     0x23
AARGB3          equ     0x24
AARGB2          equ     0x25
AARGB1          equ     0x26
AARGB0          equ     0x27
AARG            equ     0x27    ; most significant byte of argument A
;
BARGB3          equ     0x2B
BARGB2          equ     0x2C
BARGB1          equ     0x2D
BARGB0          equ     0x2E
BARG            equ     0x2E    ; most significant byte of argument B
;
;       Note that AARG and ACC reference the same storage locations
;
;*********************************************************************************************
;
;       FIXED POINT SPECIFIC DEFINITIONS
;
;       remainder storage
;
REMB3           equ     0x20
REMB2           equ     0x21
REMB1           equ     0x22
REMB0           equ     0x23    ; most significant byte of remainder

LOOPCOUNT       equ     0x34    ; loop counter
;
;*********************************************************************************************
;
;       FLOATING POINT SPECIFIC DEFINITIONS
;
;       literal constants
;
EXPBIAS         equ     D'127'
;
;       biased exponents
;
EXP             equ     0x28    ; 8 bit biased exponent

AEXP            equ     0x28    ; 8 bit biased exponent for argument A

BEXP            equ     0x2F    ; 8 bit biased exponent for argument B
;
;       floating point library exception flags
;
FPFLAGS         equ     0x2A    ; floating point library exception flags
                
IOV             equ     0       ; bit0 = integer overflow flag

FOV             equ     1       ; bit1 = floating point overflow flag

FUN             equ     2       ; bit2 = floating point underflow flag

FDZ             equ     3       ; bit3 = floating point divide by zero flag

NAN		equ	4	; bit4 = not-a-number exception flag

DOM		equ	5	; bit5 = domain error exception flag

RND             equ     6       ; bit6 = floating point rounding flag, 0 = truncation
                                ; 1 = unbiased rounding to nearest LSB

SAT             equ     7       ; bit7 = floating point saturate flag, 0 = terminate on
                                ; exception without saturation, 1 = terminate on
                                ; exception with saturation to appropriate value

;**********************************************************************************************

;	RCS Header $Id: fp32.a16 2.8 1996/10/07 13:50:59 F.J.Testa Exp $

;	$Revision: 2.8 $

;       PIC16 32 BIT FLOATING POINT LIBRARY
;
;       Unary operations: both input and output are in AEXP,AARG
;
;       Binary operations: input in AEXP,AARG and BEXP,BARG with output in AEXP,AARG
;
;       All routines return WREG = 0x00 for successful completion, and WREG = 0xFF
;       for an error condition specified in FPFLAGS.
;
;       All timings are worst case cycle counts
;
;         Routine               Function
;
;       FLO2432         24 bit integer to 32 bit floating point conversion
;       FLO32
;
;               Timing:            RND
;                               0       1
;
;                       0       104     104
;                  SAT
;                       1       110     110
;
;       NRM3232   32 bit normalization of unnormalized 32 bit floating point numbers
;       NRM32
;
;               Timing:            RND
;                               0       1
;
;                       0       90      90
;                  SAT
;                       1       96      96
;
;
;       INT3224         32 bit floating point to 24 bit integer conversion
;       INT32
;
;
;               Timing:            RND
;                               0       1
;
;                       0       104      112
;                  SAT
;                       1       104      114
;
;
;       NRM4032 32 bit normalization of unnormalized 40 bit floating point numbers
;
;               Timing:            RND
;                               0       1
;
;                       0       112     128
;                  SAT
;                       1       112     135
;
;
;       FPA32           32 bit floating point add
;
;               Timing:            RND
;                               0       1
;
;                       0       251     265
;                  SAT
;                       1       251     271
;
;       FPS32           32 bit floating point subtract
;
;               Timing:            RND
;                               0       1
;
;                       0       253     267
;                  SAT
;                       1       253     273
;
;       FPM32           32 bit floating point multiply
;
;               Timing:            RND
;                               0       1
;
;                       0       574     588
;                  SAT
;                       1       574     591
;
;**********************************************************************************************
;**********************************************************************************************
;
;       32 bit floating point representation
;
;       EXPONENT        8 bit biased exponent
;
;                       It is important to note that the use of biased exponents produces
;                       a unique representation of a floating point 0, given by
;                       EXP = HIGHBYTE = MIDBYTE = LOWBYTE = 0x00, with 0 being
;                       the only number with EXP = 0.
;
;       HIGHBYTE        8 bit most significant byte of fraction in sign-magnitude representation,
;                       with SIGN = MSB, implicit MSB = 1 and radix point to the right of MSB
;
;       MIDBYTE         8 bit middle significant byte of sign-magnitude fraction
;
;       LOWBYTE         8 bit least significant byte of sign-magnitude fraction
;
;       EXPONENT        HIGHBYTE        MIDBYTE         LOWBYTE
;
;       xxxxxxxx        S.xxxxxxx       xxxxxxxx        xxxxxxxx
;
;                        |
;                      RADIX
;                      POINT
;
;
;**********************************************************************************************
;**********************************************************************************************

;       Integer to float conversion

;       Input:  24 bit 2's complement integer right justified in AARGB0, AARGB1, AARGB2

;       Use:    CALL    FLO2432 or      CALL    FLO32

;       Output: 32 bit floating point number in AEXP, AARGB0, AARGB1, AARGB2

;       Result: AARG  <--  FLOAT( AARG )

;       Max Timing:     14+90 = 104 clks                SAT = 0
;                       14+96 = 110 clks                SAT = 1

;       Min Timing:     6+28 = 34 clks                  AARG = 0
;                       6+18 = 24 clks

;       PM: 14+38 = 52                                  DM: 7

;----------------------------------------------------------------------------------------------

FLO2432
FLO32           MOVLW           D'23'+EXPBIAS		; initialize exponent and add bias
                MOVWF           EXP
                CLRF            SIGN
                BTFSS           AARGB0,MSB		; test sign
                GOTO            NRM3232
                COMF            AARGB2,F                ; if < 0, negate and set MSB in SIGN
                COMF            AARGB1,F
                COMF            AARGB0,F
                INCF            AARGB2,F
                BTFSC           _Z
                INCF            AARGB1,F
                BTFSC           _Z
                INCF            AARGB0,F
                BSF             SIGN,MSB

;**********************************************************************************************

;       Normalization routine

;       Input:  32 bit unnormalized floating point number in AEXP, AARGB0, AARGB1,
;               AARGB2, with sign in SIGN,MSB

;       Use:    CALL    NRM3232 or      CALL    NRM32

;       Output: 32 bit normalized floating point number in AEXP, AARGB0, AARGB1, AARGB2

;       Result: AARG  <--  NORMALIZE( AARG )

;       Max Timing:     21+6+7*8+7 = 90 clks            SAT = 0
;                       21+6+7*8+1+12 = 96 clks SAT = 1

;       Min Timing:     22+6 = 28 clks                  AARG = 0
;                       5+9+4 = 18 clks

;       PM: 38                                          DM: 7

;----------------------------------------------------------------------------------------------

NRM3232

NRM32           CLRF            TEMP			; clear exponent decrement
                MOVF            AARGB0,W		; test if highbyte=0
                BTFSS           _Z
                GOTO            NORM3232
                MOVF            AARGB1,W		; if so, shift 8 bits by move
                MOVWF           AARGB0
                MOVF            AARGB2,W
                MOVWF           AARGB1
                CLRF            AARGB2
                BSF             TEMP,3                  ; increase decrement by 8

                MOVF            AARGB0,W		; test if highbyte=0
                BTFSS           _Z
                GOTO            NORM3232
                MOVF            AARGB1,W		; if so, shift 8 bits by move
                MOVWF           AARGB0
                CLRF            AARGB1
                BCF             TEMP,3                  ; increase decrement by 8
                BSF             TEMP,4
        
                MOVF            AARGB0,W		; if highbyte=0, result=0
                BTFSC           _Z
                GOTO            RES032

NORM3232        MOVF            TEMP,W
                SUBWF           EXP,F
                BTFSS           _Z
                BTFSS           _C
                GOTO            SETFUN32

                BCF             _C                      ; clear carry bit

NORM3232A       BTFSC           AARGB0,MSB		; if MSB=1, normalization done
                GOTO            FIXSIGN32
                RLF             AARGB2,F                ; otherwise, shift left and 
                RLF             AARGB1,F                ; decrement EXP
                RLF             AARGB0,F
                DECFSZ          EXP,F
                GOTO            NORM3232A

                GOTO            SETFUN32                ; underflow if EXP=0

FIXSIGN32       BTFSS           SIGN,MSB
                BCF             AARGB0,MSB              ; clear explicit MSB if positive
                RETLW           0

RES032          CLRF            AARGB0                  ; result equals zero
                CLRF            AARGB1
                CLRF            AARGB2
		CLRF		AARGB3
                CLRF            EXP
                RETLW           0

;**********************************************************************************************

;       Normalization routine

;       Input:  40 bit unnormalized floating point number in AEXP, AARGB0, AARGB1,
;               AARGB2, AARGB3 with sign in SIGN,MSB

;       Use:    CALL    NRM4032

;       Output: 32 bit normalized floating point number in AEXP, AARGB0, AARGB1, AARGB2,
;               AARGB3

;       Result: AARG  <--  NORMALIZE( AARG )

;       Max Timing:     38+6*9+12+8 = 112 clks  RND = 0
;                       38+6*9+12+24 = 128 clks RND = 1, SAT = 0
;                       38+6*9+12+31 = 135 clks RND = 1, SAT = 1

;       Min Timing:     33+6 = 39 clks                  AARG = 0
;                       5+9+8 = 22 clks

;       PM: 66                                          DM: 8

;----------------------------------------------------------------------------------------------

NRM4032         CLRF            TEMP			; clear exponent decrement
                MOVF            AARGB0,W		; test if highbyte=0
                BTFSS           _Z
                GOTO            NORM4032
                MOVF            AARGB1,W		; if so, shift 8 bits by move
                MOVWF           AARGB0
                MOVF            AARGB2,W
                MOVWF           AARGB1
                MOVF            AARGB3,W
                MOVWF           AARGB2
                CLRF            AARGB3
                BSF             TEMP,3                  ; increase decrement by 8

                MOVF            AARGB0,W		; test if highbyte=0
                BTFSS           _Z
                GOTO            NORM4032
                MOVF            AARGB1,W		; if so, shift 8 bits by move
                MOVWF           AARGB0
                MOVF            AARGB2,W
                MOVWF           AARGB1
                CLRF            AARGB2
                BCF             TEMP,3                  ; increase decrement by 8
                BSF             TEMP,4
        
                MOVF            AARGB0,W		; test if highbyte=0
                BTFSS           _Z
                GOTO            NORM4032
                MOVF            AARGB1,W		; if so, shift 8 bits by move
                MOVWF           AARGB0
                CLRF            AARGB1
                BSF             TEMP,3                  ; increase decrement by 8
        
                MOVF            AARGB0,W		; if highbyte=0, result=0
                BTFSC           _Z
                GOTO            RES032

NORM4032        MOVF            TEMP,W
                SUBWF           EXP,F
                BTFSS           _Z
                BTFSS           _C
                GOTO            SETFUN32

                BCF             _C                      ; clear carry bit

NORM4032A       BTFSC           AARGB0,MSB		; if MSB=1, normalization done
                GOTO            NRMRND4032
                RLF             AARGB3,F                ; otherwise, shift left and 
                RLF             AARGB2,F                ; decrement EXP
                RLF             AARGB1,F
                RLF             AARGB0,F
                DECFSZ          EXP,F
                GOTO            NORM4032A

                GOTO            SETFUN32                ; underflow if EXP=0

NRMRND4032      BTFSC           FPFLAGS,RND
                BTFSS           AARGB2,LSB
                GOTO            FIXSIGN32
		BTFSS		AARGB3,MSB		; round if next bit is set
                GOTO            FIXSIGN32
		INCF		AARGB2,F
                BTFSC           _Z
                INCF            AARGB1,F
                BTFSC           _Z
                INCF            AARGB0,F

                BTFSS           _Z                      ; has rounding caused carryout?
                GOTO            FIXSIGN32
                RRF             AARGB0,F                ; if so, right shift
                RRF             AARGB1,F
                RRF             AARGB2,F
                INCF            EXP,F
                BTFSC           _Z                      ; check for overflow
                GOTO            SETFOV32
                GOTO            FIXSIGN32

;**********************************************************************************************
;**********************************************************************************************

;       Float to integer conversion

;       Input:  32 bit floating point number in AEXP, AARGB0, AARGB1, AARGB2

;       Use:    CALL    INT3224         or      CALL    INT32

;       Output: 24 bit 2's complement integer right justified in AARGB0, AARGB1, AARGB2

;       Result: AARG  <--  INT( AARG )

;       Max Timing:     40+6*7+6+16 = 104 clks		RND = 0
;                       40+6*7+6+24 = 112 clks		RND = 1, SAT = 0
;                       40+6*7+6+26 = 114 clks  	RND = 1, SAT = 1

;       Min Timing:     4 clks

;       PM: 82                                          DM: 6

;----------------------------------------------------------------------------------------------

INT3224
INT32
		MOVF		EXP,W			; test for zero argument
		BTFSC		_Z
		RETLW		0x00

		MOVF            AARGB0,W		; save sign in SIGN
                MOVWF           SIGN
                BSF             AARGB0,MSB		; make MSB explicit

                MOVLW           EXPBIAS+D'23'		; remove bias from EXP
                SUBWF           EXP,F
                BTFSS           EXP,MSB
                GOTO            SETIOV3224
		COMF		EXP,F
		INCF		EXP,F

                MOVLW           8                       ; do byte shift if EXP >= 8
                SUBWF           EXP,W
                BTFSS           _C
                GOTO            TSHIFT3224
                MOVWF           EXP
                RLF             AARGB2,F                ; rotate next bit for rounding
                MOVF            AARGB1,W
                MOVWF           AARGB2
                MOVF            AARGB0,W
                MOVWF           AARGB1
                CLRF            AARGB0

                MOVLW           8                       ; do another byte shift if EXP >= 8
                SUBWF           EXP,W
                BTFSS           _C
                GOTO            TSHIFT3224
                MOVWF           EXP
                RLF             AARGB2,F		; rotate next bit for rounding
                MOVF            AARGB1,W
                MOVWF           AARGB2
                CLRF            AARGB1

                MOVLW           8                       ; do another byte shift if EXP >= 8
                SUBWF           EXP,W
                BTFSS           _C
                GOTO            TSHIFT3224
                MOVWF           EXP
                RLF             AARGB2,F                ; rotate next bit for rounding
                CLRF            AARGB2
		MOVF		EXP,W
		BTFSS		_Z
		BCF		_C
		GOTO		SHIFT3224OK

TSHIFT3224      MOVF            EXP,W                   ; shift completed if EXP = 0
                BTFSC           _Z
                GOTO            SHIFT3224OK

SHIFT3224       BCF             _C
                RRF             AARGB0,F                ; right shift by EXP
                RRF             AARGB1,F
                RRF             AARGB2,F
                DECFSZ          EXP,F
                GOTO            SHIFT3224

SHIFT3224OK     BTFSC           FPFLAGS,RND
                BTFSS           AARGB2,LSB
                GOTO            INT3224OK
                BTFSS           _C
                GOTO            INT3224OK
                INCF            AARGB2,F
                BTFSC           _Z
                INCF            AARGB1,F
                BTFSC           _Z
                INCF            AARGB0,F
                BTFSC           AARGB0,MSB		; test for overflow
                GOTO            SETIOV3224

INT3224OK       BTFSS           SIGN,MSB                ; if sign bit set, negate               
                RETLW           0
                COMF            AARGB0,F
                COMF            AARGB1,F
                COMF            AARGB2,F
                INCF            AARGB2,F
                BTFSC           _Z
                INCF            AARGB1,F
                BTFSC           _Z
                INCF            AARGB0,F
                RETLW           0

IRES03224	CLRF            AARGB0			; integer result equals zero
                CLRF            AARGB1
                CLRF            AARGB2
                RETLW           0

SETIOV3224	BSF             FPFLAGS,IOV             ; set integer overflow flag
                BTFSS           FPFLAGS,SAT             ; test for saturation
                RETLW           0xFF                    ; return error code in WREG

                CLRF            AARGB0			; saturate to largest two's
                BTFSS           SIGN,MSB                ; complement 24 bit integer
                MOVLW           0xFF
                MOVWF           AARGB0			; SIGN = 0, 0x 7F FF FF
                MOVWF           AARGB1			; SIGN = 1, 0x 80 00 00
                MOVWF           AARGB2
                RLF             SIGN,F
                RRF             AARGB0,F
                RETLW           0xFF                    ; return error code in WREG

;**********************************************************************************************
;**********************************************************************************************

;       Floating Point Multiply

;       Input:  32 bit floating point number in AEXP, AARGB0, AARGB1, AARGB2
;               32 bit floating point number in BEXP, BARGB0, BARGB1, BARGB2

;       Use:    CALL    FPM32

;       Output: 32 bit floating point product in AEXP, AARGB0, AARGB1, AARGB2

;       Result: AARG  <--  AARG * BARG

;       Max Timing:     26+23*22+21+21 = 574 clks       RND = 0
;                       26+23*22+21+35 = 588 clks       RND = 1, SAT = 0
;                       26+23*22+21+38 = 591 clks       RND = 1, SAT = 1

;       Min Timing:     6+6 = 12 clks                   AARG * BARG = 0
;                       24+23*11+21+17 = 315 clks

;       PM: 94                                          DM: 14

;----------------------------------------------------------------------------------------------

FPM32           MOVF            AEXP,W                  ; test for zero arguments
                BTFSS           _Z
                MOVF            BEXP,W
                BTFSC           _Z
                GOTO            RES032

M32BNE0         MOVF            AARGB0,W
                XORWF           BARGB0,W
                MOVWF           SIGN                    ; save sign in SIGN

                MOVF            BEXP,W
                ADDWF           EXP,F
                MOVLW           EXPBIAS-1
                BTFSS           _C
                GOTO            MTUN32

                SUBWF           EXP,F
                BTFSC           _C
                GOTO            SETFOV32                ; set multiply overflow flag
                GOTO            MOK32

MTUN32          SUBWF           EXP,F
                BTFSS           _C
                GOTO            SETFUN32

MOK32		MOVF		AARGB0,W
		MOVWF		AARGB3
		MOVF		AARGB1,W
		MOVWF		AARGB4
		MOVF		AARGB2,W
		MOVWF		AARGB5
		BSF             AARGB3,MSB              ; make argument MSB's explicit
                BSF             BARGB0,MSB
                BCF             _C
                CLRF            AARGB0			; clear initial partial product
                CLRF            AARGB1
                CLRF            AARGB2
                MOVLW           D'24'
                MOVWF           TEMP                    ; initialize counter

MLOOP32         BTFSS           AARGB5,LSB              ; test next bit
                GOTO            MNOADD32

MADD32          MOVF            BARGB2,W
                ADDWF           AARGB2,F
                MOVF            BARGB1,W
                BTFSC           _C
                INCFSZ          BARGB1,W
                ADDWF           AARGB1,F

                MOVF            BARGB0,W
                BTFSC           _C
                INCFSZ          BARGB0,W
                ADDWF           AARGB0,F

MNOADD32        RRF             AARGB0,F
                RRF             AARGB1,F
                RRF             AARGB2,F
                RRF             AARGB3,F
                RRF             AARGB4,F
                RRF             AARGB5,F
                BCF             _C
                DECFSZ          TEMP,F
                GOTO            MLOOP32

                BTFSC           AARGB0,MSB               ; check for postnormalization
                GOTO            MROUND32
                RLF             AARGB3,F
                RLF             AARGB2,F
                RLF             AARGB1,F
                RLF             AARGB0,F
                DECF            EXP,F

MROUND32        BTFSC           FPFLAGS,RND
                BTFSS           AARGB2,LSB
                GOTO            MUL32OK
		BTFSS		AARGB3,MSB
                GOTO            MUL32OK
		INCF		AARGB2,F
                BTFSC           _Z
                INCF            AARGB1,F
                BTFSC           _Z
                INCF            AARGB0,F

                BTFSS           _Z                      ; has rounding caused carryout?
                GOTO            MUL32OK
                RRF             AARGB0,F                ; if so, right shift
                RRF             AARGB1,F
                RRF             AARGB2,F
                INCF            EXP,F
                BTFSC           _Z                      ; check for overflow
                GOTO            SETFOV32

MUL32OK         BTFSS           SIGN,MSB
                BCF             AARGB0,MSB		; clear explicit MSB if positive

                RETLW           0  

SETFOV32        BSF             FPFLAGS,FOV             ; set floating point underflag
                BTFSS           FPFLAGS,SAT             ; test for saturation
                RETLW           0xFF                    ; return error code in WREG

                MOVLW           0xFF
                MOVWF           AEXP                    ; saturate to largest floating
                MOVWF           AARGB0                  ; point number = 0x FF 7F FF FF
                MOVWF           AARGB1                  ; modulo the appropriate sign bit
                MOVWF           AARGB2
                RLF             SIGN,F
                RRF             AARGB0,F
                RETLW           0xFF                    ; return error code in WREG

;**********************************************************************************************

SETFUN32        BSF             FPFLAGS,FUN             ; set floating point underflag
                BTFSS           FPFLAGS,SAT             ; test for saturation
                RETLW           0xFF                    ; return error code in WREG

                MOVLW           0x01                    ; saturate to smallest floating
                MOVWF           AEXP                    ; point number = 0x 01 00 00 00
                CLRF            AARGB0                  ; modulo the appropriate sign bit
                CLRF            AARGB1
                CLRF            AARGB2
                RLF             SIGN,F
                RRF             AARGB0,F
                RETLW           0xFF                    ; return error code in WREG

;**********************************************************************************************
;**********************************************************************************************

;       Floating Point Subtract

;       Input:  32 bit floating point number in AEXP, AARGB0, AARGB1, AARGB2
;               32 bit floating point number in BEXP, BARGB0, BARGB1, BARGB2

;       Use:    CALL FPS32

;       Output: 32 bit floating point sum in AEXP, AARGB0, AARGB1, AARGB2

;       Result: AARG  <--  AARG - BARG

;       Max Timing:     2+251 = 253 clks                RND = 0
;                       2+265 = 267 clks                RND = 1, SAT = 0
;                       2+271 = 273 clks                RND = 1, SAT = 1

;       Min Timing:     2+12 = 14 clks

;       PM: 2+146 = 148                         DM: 14

;----------------------------------------------------------------------------------------------

FPS32           MOVLW           0x80
                XORWF           BARGB0,F

;**********************************************************************************************

;       Floating Point Add

;       Input:  32 bit floating point number in AEXP, AARGB0, AARGB1, AARGB2
;               32 bit floating point number in BEXP, BARGB0, BARGB1, BARGB2

;       Use:    CALL FPA32

;       Output: 32 bit floating point sum in AEXP, AARGB0, AARGB1, AARGB2

;       Result: AARG  <--  AARG - BARG

;       Max Timing:     31+41+6*7+6+41+90 = 251 clks            RND = 0
;                       31+41+6*7+6+55+90 = 265 clks            RND = 1, SAT = 0
;                       31+41+6*7+6+55+96 = 271 clks            RND = 1, SAT = 1

;       Min Timing:     8+4 = 12 clks

;       PM: 146                                                 DM: 14

;----------------------------------------------------------------------------------------------

FPA32           MOVF            AARGB0,W                ; exclusive or of signs in TEMP
                XORWF           BARGB0,W
                MOVWF           TEMP

		CLRF		AARGB3			; clear extended byte
		CLRF		BARGB3

                MOVF            AEXP,W                  ; use AARG if AEXP >= BEXP
                SUBWF           BEXP,W
                BTFSS           _C
                GOTO            USEA32

                MOVF            BEXP,W                  ; use BARG if AEXP < BEXP
                MOVWF           AARGB5			; therefore, swap AARG and BARG
                MOVF            AEXP,W
                MOVWF           BEXP
                MOVF            AARGB5,W
                MOVWF           AEXP

                MOVF            BARGB0,W
                MOVWF           AARGB5
                MOVF            AARGB0,W
                MOVWF           BARGB0
                MOVF            AARGB5,W
                MOVWF           AARGB0

                MOVF            BARGB1,W
                MOVWF           AARGB5
                MOVF            AARGB1,W
                MOVWF           BARGB1
                MOVF            AARGB5,W
                MOVWF           AARGB1

                MOVF            BARGB2,W
                MOVWF           AARGB5
                MOVF            AARGB2,W
                MOVWF           BARGB2
                MOVF            AARGB5,W
                MOVWF           AARGB2

USEA32          MOVF            BEXP,W                  ; return AARG if BARG = 0
                BTFSC           _Z
                RETLW           0x00

                MOVF            AARGB0,W
                MOVWF           SIGN                    ; save sign in SIGN
                BSF             AARGB0,MSB              ; make MSB's explicit
                BSF             BARGB0,MSB

                MOVF            BEXP,W                  ; compute shift count in BEXP
                SUBWF           AEXP,W
                MOVWF           BEXP
                BTFSC           _Z
                GOTO            ALIGNED32

                MOVLW           8
                SUBWF           BEXP,W
                BTFSS           _C                      ; if BEXP >= 8, do byte shift
                GOTO            ALIGNB32
                MOVWF           BEXP
                MOVF            BARGB2,W		; keep for postnormalization
		MOVWF		BARGB3
                MOVF            BARGB1,W
		MOVWF		BARGB2
                MOVF            BARGB0,W
		MOVWF		BARGB1
                CLRF            BARGB0

                MOVLW           8
                SUBWF           BEXP,W
                BTFSS           _C                      ; if BEXP >= 8, do byte shift
                GOTO            ALIGNB32
                MOVWF           BEXP
                MOVF            BARGB2,W		; keep for postnormalization
		MOVWF		BARGB3
                MOVF            BARGB1,W
		MOVWF		BARGB2
                CLRF            BARGB1

                MOVLW           8
                SUBWF           BEXP,W
                BTFSS           _C                      ; if BEXP >= 8, BARG = 0 relative to AARG
                GOTO            ALIGNB32
                MOVF            SIGN,W
                MOVWF           AARGB0
                RETLW           0x00

ALIGNB32        MOVF            BEXP,W                  ; already aligned if BEXP = 0
                BTFSC           _Z
                GOTO            ALIGNED32

ALOOPB32        BCF             _C                      ; right shift by BEXP
                RRF             BARGB0,F
                RRF             BARGB1,F
		RRF		BARGB2,F
		RRF		BARGB3,F
                DECFSZ          BEXP,F
                GOTO            ALOOPB32

ALIGNED32       BTFSS           TEMP,MSB                ; negate if signs opposite
                GOTO            AOK32

		COMF		BARGB3,F
		COMF		BARGB2,F
                COMF            BARGB1,F
                COMF            BARGB0,F
                INCF            BARGB3,F
                BTFSC           _Z
                INCF            BARGB2,F
		BTFSC		_Z
		INCF		BARGB1,F
		BTFSC		_Z
		INCF		BARGB0,F

AOK32
                MOVF   		BARGB3,W
                ADDWF   	AARGB3,F
                MOVF            BARGB2,W
                BTFSC           _C
                INCFSZ          BARGB2,W
                ADDWF           AARGB2,F
                MOVF            BARGB1,W
                BTFSC           _C
                INCFSZ          BARGB1,W
                ADDWF           AARGB1,F
                MOVF            BARGB0,W
                BTFSC           _C
                INCFSZ          BARGB0,W
                ADDWF           AARGB0,F

                BTFSC           TEMP,MSB
                GOTO            ACOMP32
                BTFSS           _C
                GOTO            NRMRND4032

                RRF             AARGB0,F               ; shift right and increment EXP
                RRF             AARGB1,F
                RRF             AARGB2,F
		RRF		AARGB3,F
                INCFSZ          AEXP,F
                GOTO            NRMRND4032
                GOTO            SETFOV32

ACOMP32         BTFSC           _C
                GOTO            NRM4032			; normalize and fix sign

		COMF		AARGB3,F
                COMF            AARGB2,F		; negate, toggle sign bit and
                COMF            AARGB1,F		; then normalize
                COMF            AARGB0,F
                INCF            AARGB3,F
                BTFSC           _Z
                INCF            AARGB2,F
                BTFSC           _Z
                INCF            AARGB1,F
                BTFSC           _Z
                INCF            AARGB0,F

                MOVLW           0x80
                XORWF           SIGN,F
                GOTO            NRM32


		; AN670 32BIT NUMBER TO ASCII (ale zatim jen do cisla 9999!)

;****************************************************************************
;*		Floating Point to ASCII
;*
;* INPUT: 32 bit floating point number in AEXP, AARGB0, AARGB1, AARGB2
;*        For this example, the number must be between 0.000 and 9.999.
;*        (You can easily change the number range to suit your needs.)
;*
;* OUTPUT: ones, tenths, hundredths, thousandths (ASCII digit in each)
;*         
;*
;* USED: INDF,FSR,AARG,BARG,REMB,digit_count
;*
;* PROCEDURE: The floating point number in AARG is multiplied by 1000.
;*            Then the product is divided by 10 three times.  After each
;*            divide, the remainder is kept.  
;*
;*            After each digit is obtained, 30H is added to it to make it
;*            an ASCII representation of that number.  Then, the ASCII
;*            value is stored in register RAM at the locations specified
;*            in the "cblock."      
;*
;*	Note: The ASCII decimal point is not generated by this routine.
;*            You must output the decimal point in the correct decimal
;*            position for your application.  For this example, the
;*            decimal point is after the first digit: ones.
;*            
;* The following files are needed for this routine to function.
;*  p16c74a.inc		-- or any other midrange processor include file 
;*                         include the processor file in your "main" file
;*
;*  math16.inc          -- constant and variable definitions for 
;*                         AN575 floating point routines and
;*                         AN617 fixed point routines, both are used
;*                         in this float to ASCII routine
;*                         "include" this file in your "main" program
;*
;*  fxd26.a16 		-- fixed point 32/16 divide, included at the end
;*                         of this routine.
;*
;*  fp32.a16		-- 32 bit float to 32 bit integer conversion 
;*                         included at the end of this program. 
;* 
;****************************************************************************


;RAM Register Definitions       Your "main" program must have a "cblock"
                                ;directive with a RAM address so the 
                                ;following "cblock" will be located in RAM

digit_count	EQU	035H	;counter used to cycle through each digit 

int16ascii			; Prevod 16bitove binarni hodnoty na ascii
	; nasledujici tri radky udelat pred volanim rutiny, tak aby rutina dostala 
	; adresu kam ukladat vysledek ve 'W' a pocet mist byl v digit_count
	;movlw	SIG_FIG         ;load counter with the number of
	;movwf	digit_count     ;significant figures the decimal number	
	;movlw	last_digit	;

	movwf	FSR		;pointer = address of smallest digit

flo_asclp
	clrf	BARGB0		;Make the divisor 10.  
	movlw	d'10'
	movwf	BARGB1

	call	FXD1616U	;divide (16 bit fixed) / 10 (to get remainder)
	
	movf	REMB1,w		;put remainder in w register
	movwf	INDF		;put number into appropriate digit position

	movlw	0x30
	addwf	INDF,f		;add 30H to decimal number to convert to ASCII

	decf	FSR,f		;move pointer to next digit 	

	decfsz	digit_count,f
	goto	flo_asclp

	return


;**********************************************************************************************
;**********************************************************************************************

;	RCS Header $Id: fxd66.a16 2.4 1997/02/27 01:20:22 F.J.Testa Exp $

;	$Revision: 2.4 $

;       16/16 PIC16 FIXED POINT DIVIDE ROUTINES
;
;       Input:  fixed point arguments in AARG and BARG
;
;       Output: quotient AARG/BARG followed by remainder in REM
;
;       All timings are worst case cycle counts
;
;       It is useful to note that the additional unsigned routines requiring a non-power of two
;       argument can be called in a signed divide application where it is known that the
;       respective argument is nonnegative, thereby offering some improvement in
;       performance.
;
;         Routine            Clocks     Function
;
;       FXD1616U    373 16 bit/16 bit -> 16.16 unsigned fixed point divide
;
;       The above timings are based on the looped macros. If space permits,
;       approximately 65-69 clocks can be saved by using the unrolled macros.
;

;**********************************************************************************************
;**********************************************************************************************

;       16/16 Bit Division Macros


UDIV1616L       macro

;       restore = 23 clks,  nonrestore = 17 clks

;       Max Timing:     2+15*23+22 = 369 clks

;       Min Timing:     2+15*17+16 = 273 clks

;       PM: 24                                  DM: 7

                MOVLW           D'16'
                MOVWF           LOOPCOUNT

LOOPU1616       RLF             AARGB0,W
                RLF             REMB1, F
                RLF             REMB0, F
                MOVF            BARGB1,W
                SUBWF           REMB1, F
                MOVF            BARGB0,W
                BTFSS           _C
                INCFSZ          BARGB0,W
                SUBWF           REMB0, F

                BTFSC           _C
                GOTO            UOK66LL         
                MOVF            BARGB1,W
                ADDWF           REMB1, F
                MOVF            BARGB0,W
                BTFSC           _C
                INCFSZ          BARGB0,W
                ADDWF           REMB0, F

                BCF             _C

UOK66LL RLF             AARGB1, F
                RLF             AARGB0, F

                DECFSZ          LOOPCOUNT, F
                GOTO            LOOPU1616

                endm

;**********************************************************************************************
;**********************************************************************************************
        
;       16/16 Bit Unsigned Fixed Point Divide 16/16 -> 16.16

;       Input:  16 bit unsigned fixed point dividend in AARGB0, AARGB1
;               16 bit unsigned fixed point divisor in BARGB0, BARGB1

;       Use:    CALL    FXD1616U

;       Output: 16 bit unsigned fixed point quotient in AARGB0, AARGB1
;               16 bit unsigned fixed point remainder in REMB0, REMB1

;       Result: AARG, REM  <--  AARG / BARG

;       Max Timing:     2+369+2 = 373 clks

;       Min Timing:     2+273+2 = 277 clks

;       PM: 2+24+1 = 27         DM: 7

FXD1616U        CLRF            REMB0
                CLRF            REMB1

                UDIV1616L

                RETLW           0x00

;**********************************************************************************************
;**********************************************************************************************

		; Pojistky procesoru
		
		ORG	2007H

		DATA	1184H

		; EEPROM procesoru

		END				;
