;    Digital Thermometer
;    Vicsys
;    Original Project by:
;    gpTherm (http://webtomware.rhoen.de/pic/)
;    Copyright (C) 2000-2001 Thomas.Reith@rhoen.de
;    THANK YOU!
;
;    OSC 4MHz -> 1us per cycle
;    (0) DS1820 ROM 1039201b000800a2
;    (1) DS1820 ROM 10470d1b0008003d
;
;                                
;
;
#define LCD_2X16                      ; ********* 2 line display!!!!
;#define LCD_4X16                     ; ********* 4 line display!!!!
;
 list p=16f84a
 include p16f84a.inc
 __CONFIG _CP_OFF & _WDT_ON & _XT_OSC
;
VERSIONMAJOR    EQU     1
VERSIONMINOR    EQU     0
VERSIONRELEASE  EQU     0
;
LCD_DATA        EQU     PORTB          ; LCD data lines interface
LCD_DATA_TRIS   EQU     TRISB
LCD_CTRL        EQU     PORTA          ; LCD control lines interface
;
; LCD PORTA control bits
;
LCD_RS          EQU     0              ; LCD Register-Select control line
LCD_RW          EQU     1              ; LCD Read/Write control line
LCD_E           EQU     2              ; LCD Enable control line
LCD_LINE0       EQU     0x00           ; LCD Line Address
LCD_LINE1       EQU     0x40           ; LCD Line Address
LCD_LINE2       EQU     0x10           ; LCD Line Address
LCD_LINE3       EQU     0x50           ; LCD Line Address
;
; LCD PORTB data bits
;
LCD_DB7         EQU     7              ; LCD dataline 7 (MSB)
LCD_DB6         EQU     6              ; LCD dataline 6
LCD_DB5         EQU     5              ; LCD dataline 5
LCD_DB4         EQU     4              ; LCD dataline 4
LCD_DB3         EQU     3              ; LCD dataline 3
LCD_DB2         EQU     2              ; LCD dataline 2
LCD_DB1         EQU     1              ; LCD dataline 1
LCD_DB0         EQU     0              ; LCD dataline 0 (LSB)
;
; LCD variables
;
LCD_TEMP        EQU     0x10           ; lcd subroutines internal use
LCD_DELAY       EQU     0x11           ; Used in DELAYxxx routines
LCD_X_DELAY     EQU     0x12           ; Used in X_DELAYxxx routines
LCD_ASCHEXLO    EQU     0x13           ; lo ascii hex from lcdaschex routine
LCD_ASCHEXHI    EQU     0x14           ; hi ascii hex from lcdaschex routine
LCD_ASCHALF     EQU     0x15           ; 5 or 0 for half Celsius Degrees
LCD_ASCSIGN     EQU     0x16           ; sign, 0 -> '+' 255 '-' else ' '
LCD_ACTDS       EQU     0x17           ; 0->one (no rom), 1->first,2->second
; display modes
BTN_ACTMODE     EQU     0x18           ; variable for actual display mode
BTN_MODENORMAL  EQU     0              ; bit for display temperature screen
BTN_MODEMINMAX  EQU     1              ; bit display minmax screen
;
; DS 1820 variables
;
DS_BIT          EQU     4              ; porta4 is connected to the ds1820 bus
DS_RWTMP0       EQU     0x20
DS_RWTMP1       EQU     0x21
DS_DLYTMP       EQU     0x22
DS_TMP0         EQU     0x23
DS_TMP1         EQU     0x24
; area for tmp min and max variables
DS_MINTMP       EQU     0x25
DS_MAXTMP       EQU     0x26
DS_SIGNMINTMP   EQU     0x27
DS_SIGNMAXTMP   EQU     0x28
; ds1820 rom
DS_ROM0         EQU     0x30           ; ds1820 1 byte rom family code
DS_ROM1         EQU     0x31           ; ds1820 6 byte rom serial number
DS_ROM2         EQU     0x32           
DS_ROM3         EQU     0x33           
DS_ROM4         EQU     0x34
DS_ROM5         EQU     0x35
DS_ROM6         EQU     0x36
DS_ROM7         EQU     0x37           ; ds1820 1 byte rom crc code
; area for min and max variables
DS_MIN0         EQU     0x38
DS_MAX0         EQU     0x39
DS_SIGNMIN0     EQU     0x3a
DS_SIGNMAX0     EQU     0x3b
DS_MIN1         EQU     0x3c
DS_MAX1         EQU     0x3d
DS_SIGNMIN1     EQU     0x3e
DS_SIGNMAX1     EQU     0x3f
; ds1820 ram
DS_RAM0         EQU     0x40           ; ds1820 ram temperature lsb (temp)
DS_RAM1         EQU     0x41           ; ds1820 ram temperature msb (sign)
DS_RAM2         EQU     0x42           ; ds1820 ram TH user1
DS_RAM3         EQU     0x43           ; ds1820 ram TL user2
DS_RAM4         EQU     0x44           ; ds1820 ram reserved
DS_RAM5         EQU     0x45           ; ds1820 ram reserved
DS_RAM6         EQU     0x46           ; ds1820 ram count remain
DS_RAM7         EQU     0x47           ; ds1820 ram count per celsius
DS_RAM8         EQU     0x48           ; ds1820 ram crc
;
; CONVERSION Variables
;
Hund            EQU     0x49
Tens            EQU     0x4a
Ones            EQU     0x4b
NumH            EQU     0x4c
NumL            EQU     0x4d
;
 goto main
;
dswriterom0                            ; romtable from my first ds1820
 movlw       0x10                      ; ***IDE kerül a kiolvasott 1-es ROM kód***
 call        dswrite
 movlw       0x9a
 call        dswrite
 movlw       0x8d
 call        dswrite
 movlw       0x06
 call        dswrite
 movlw       0x02
 call        dswrite
 movlw       0x08
 call        dswrite
 movlw       0x00
 call        dswrite
 movlw       0x92
 call        dswrite
 return
;
dswriterom1 
 movlw       0x10                      ; romtable from my second ds1820
 call        dswrite                   ; ***IDE kerül a kiolvasott 2-es ROM kód***
 movlw       0x2a
 call        dswrite
 movlw       0x8c
 call        dswrite
 movlw       0x06
 call        dswrite
 movlw       0x02
 call        dswrite
 movlw       0x08
 call        dswrite
 movlw       0x00
 call        dswrite
 movlw       0x58
 call        dswrite
 return
;
dsprinttitle0					;**********KÜLSŐ**********
 movlw   'K'
 call    lcdputchar
 movlw   'I'
 call    lcdputchar
 movlw   'N'
 call    lcdputchar
 movlw   'T'
 call    lcdputchar
 movlw   'I'
 call    lcdputchar
 movlw   ':'
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 return
;
dsprinttitle1					;**********BELSŐ**********
 movlw   'B'
 call    lcdputchar
 movlw   'E'
 call    lcdputchar
 movlw   'N'
 call    lcdputchar
 movlw   'T'
 call    lcdputchar
 movlw   'I'
 call    lcdputchar
 movlw   ':'
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 return
;
dsprintminmax0
 movf    DS_SIGNMIN0,W
 movwf   DS_RAM1
 movf    DS_MIN0,W
 movwf   DS_RAM0
 call    lcdprintdsdata
 movlw   ' '
 call    lcdputchar
 movf    DS_SIGNMAX0,W
 movwf   DS_RAM1
 movf    DS_MAX0,W
 movwf   DS_RAM0
 call    lcdprintdsdata
 return
;
dsprintminmax1
 movf    DS_SIGNMIN1,W
 movwf   DS_RAM1
 movf    DS_MIN1,W
 movwf   DS_RAM0 
 call    lcdprintdsdata
 movlw   ' '
 call    lcdputchar
 movf    DS_SIGNMAX1,W
 movwf   DS_RAM1
 movf    DS_MAX1,W
 movwf   DS_RAM0 
 call    lcdprintdsdata
 return
;
dsminmax2tmp
 movwf   FSR
 movf    INDF,W
 movwf   DS_MINTMP
 incf    FSR,F
 movf    INDF,W
 movwf   DS_MAXTMP
 incf    FSR,F
 movf    INDF,W
 movwf   DS_SIGNMINTMP
 incf    FSR,F
 movf    INDF,W
 movwf   DS_SIGNMAXTMP
 return
;
dstmp2minmax
 movwf   FSR
 movf    DS_MINTMP,W
 movwf   INDF
 incf    FSR,F
 movf    DS_MAXTMP,W
 movwf   INDF
 incf    FSR,F
 movf    DS_SIGNMINTMP,W
 movwf   INDF
 incf    FSR,F
 movf    DS_SIGNMAXTMP,W
 movwf   INDF
 return
;
dsprintcopyright					;**********version****
 movlw   'V'
 call    lcdputchar
 movlw   'y'
 call    lcdputchar
 movlw   'c'
 call    lcdputchar
 movlw   's'
 call    lcdputchar
 movlw   'y'
 call    lcdputchar
 movlw   's'
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 movlw   'V'
 call    lcdputchar
 movlw   ' '
 call    lcdputchar
 movlw   VERSIONMAJOR + 0x30
 call    lcdputchar
 movlw   '.'
 call    lcdputchar
 movlw   VERSIONMINOR + 0x30
 call    lcdputchar
 movlw   '.'
 call    lcdputchar
 movlw   VERSIONRELEASE + 0x30
 call    lcdputchar
 return
;
lcdclear
 movlw   0x01
 call    lcdputcmd
 return
;
lcdhome
 movlw   0x02
 call    lcdputcmd
 return
;
lcdemode
 andlw   0x03               ; strip upper bits
 iorlw   0x04               ; function set
 call    lcdputcmd
 return
;
lcddmode
 andlw   0x07               ; strip upper bits
 iorlw   0x08               ; function set
 call    lcdputcmd
 return
;
lcdscga
 andlw   0x3f               ; strip upper bits
 iorlw   0x40               ; function set
 call    lcdputcmd
 return
;
lcdsdda
 iorlw   0x80               ; function set
 call    lcdputcmd
 return
;
lcdgaddr
 bsf     STATUS,RP0          ; select register page 1
 movlw   0xff                ; set PORTB for input
 movwf   LCD_DATA_TRIS
 bcf     STATUS, RP0         ; select Register page 0
 bcf     LCD_CTRL, LCD_RS    ; set LCD for command mode
 bsf     LCD_CTRL, LCD_RW    ; setup to read busy flag
 bsf     LCD_CTRL, LCD_E     ; LCD E-line high
 movf    LCD_DATA, W         ; read busy flag + RAM address
 bcf     LCD_CTRL, LCD_E     ; LCD E-line Low
 andlw   0x7f                ; strip upper bit
 bcf     LCD_CTRL, LCD_RW
 bsf     STATUS, RP0         ; select register page 1
 clrf    LCD_DATA_TRIS       ; set PORTB for output
 bcf     STATUS, RP0         ; select register page 0
 return
;
lcdputchar
 movwf   LCD_TEMP            ; character to send is in W
 call    lcdbusy             ; wait for LCD to be ready
 bcf     LCD_CTRL, LCD_RW    ; set LCD in read mode
 bsf     LCD_CTRL, LCD_RS    ; set LCD in data mode
 bsf     LCD_CTRL, LCD_E     ; LCD E-line High
 movf    LCD_TEMP, W
 movwf   LCD_DATA            ; send data to LCD
 bcf     LCD_CTRL, LCD_E     ; LCD E-line Low
 return
;
lcdputcmd
 movwf   LCD_TEMP            ; command to send is in W
 call    lcdbusy             ; wait for LCD to be ready
 bcf     LCD_CTRL, LCD_RW    ; set LCD in read mode
 bcf     LCD_CTRL, LCD_RS    ; set LCD in command mode
 bsf     LCD_CTRL, LCD_E     ; LCD E-line High
 movf    LCD_TEMP, W
 movwf   LCD_DATA            ; send data to LCD
 bcf     LCD_CTRL, LCD_E     ; LCD E-line Low
 return
;
lcdascsign
 movf    DS_RAM1,W
 btfss   STATUS,Z
 goto    lcdascsignminus			;*********PLUSSZ JEL**
 movlw   '+'
 movwf   LCD_ASCSIGN
 return
lcdascsignminus					;***MINUSZ JEL****
 movlw   '-'
 movwf   LCD_ASCSIGN
 return
;
lcdaschex
 movwf   LCD_TEMP
 swapf   LCD_TEMP,W
 andlw   B'00001111'
 addlw   -0x0a
 btfsc   STATUS,C
 addlw   0x07
 addlw   0x3a
 movwf   LCD_ASCHEXHI
 movf    LCD_TEMP,W
 andlw   B'00001111'
 addlw   -0x0a
 btfsc   STATUS,C
 addlw   0x07
 addlw   0x3a
 movwf   LCD_ASCHEXLO
 return
;
lcdbusy
 bsf     STATUS,RP0         ; Select Register page 1
 movlw   0xff               ; Set PORTB for input
 movwf   LCD_DATA_TRIS
 bcf     STATUS,RP0         ; Select Register page 0
 bcf     LCD_CTRL,LCD_RS    ; Set LCD for command mode
 bsf     LCD_CTRL,LCD_RW    ; Setup to read busy flag
 bsf     LCD_CTRL,LCD_E     ; LCD E-line High
 movf    LCD_DATA,W         ; Read busy flag + DDram address
 bcf     LCD_CTRL,LCD_E     ; LCD E-line Low
 andlw   0x80               ; Check Busy flag, High = Busy
 btfss   STATUS,Z
 goto    lcdbusy
 bcf     LCD_CTRL,LCD_RW
 bsf     STATUS,RP0         ; Select Register page 1
 clrf    LCD_DATA_TRIS      ; Set PORTB for output
 bcf     STATUS,RP0         ; Select Register page 0
 return
;
lcddelay500us
 movlw   D'165'          ; +1            1 cycle
 movwf   LCD_DELAY       ; +2            1 cycle
 decfsz  LCD_DELAY,F     ; step 1        1 cycle
 goto    $-1             ; step 2        2 cycles
 return                      ; +3            2 cycles
;
lcdxdelay500us      
 movwf   LCD_X_DELAY     ; +1            1 cycle
 call    lcddelay500us   ; step1         wait 500uSec
 decfsz  LCD_X_DELAY, F  ; step2         1 cycle
 goto    $-2             ; step3         2 cycles
 return
;
lcdinit
 clrf    LCD_CTRL        ; ALL PORT output should output Low.
 movlw   0x1e
 call    lcdxdelay500us  ; 30 * 0.5mS = 15mS
 movlw   0x38            ; 8-bit-interface, 2-lines
 call    lcdputcmd
 movlw   0x00            ; disp.off, curs.off, no-blink
 call    lcddmode
 call    lcdclear
 movlw   0x04            ; disp.on, curs.off
 call    lcddmode
 movlw   0x02            ; auto-inc (shift-cursor)
 call    lcdemode
 return
;
dssetlow macro
 bcf     PORTA,DS_BIT    ; dq bit ready lo
 bsf     STATUS,RP0
 bcf     TRISA,DS_BIT    ; dq bit now o/p
 bcf     STATUS,RP0
 endm
;
dssethigh macro
 bsf     STATUS,RP0
 bsf     TRISA,DS_BIT    ; dq bit now i/p
 bcf     STATUS,RP0
 endm
;
pause macro dlyf
 movlw   (dlyf / D'5') - D'1'
 movwf   DS_DLYTMP
 call    dly5n
 endm
;
dly5n  
 nop
 nop
 decfsz  DS_DLYTMP,F
 goto    dly5n
 return
;
dsread 
 movlw   D'8'
 movwf   DS_RWTMP0
dsrxlp
 dssetlow
 pause   D'10'
 dssethigh
 nop
 nop
 movf    PORTA,W
 andlw   B'00010000'
 addlw   0xff          
 rrf     DS_RWTMP1,F
 pause   D'60'
 decfsz  DS_RWTMP0,F
 goto    dsrxlp
 movf    DS_RWTMP1,W
 return
;
dswrite
 movwf   DS_RWTMP1       ; data to tx
 movlw   D'8'
 movwf   DS_RWTMP0       ; loop counter
dstxlp
 dssetlow
 pause   D'10'
 rrf     DS_RWTMP1,F
 btfsc   STATUS,C
 bsf     PORTA,DS_BIT    ; dq high if bit was 1
 pause   D'70'
 dssethigh
 nop
 decfsz  DS_RWTMP0,F
 goto    dstxlp
 return
;
dsreset
 dssetlow
 pause   D'600'
 dssethigh
 pause   D'65'           ;wait 67us for response bit
 nop
 nop
 movf    PORTA,W
 andlw   1 << DS_BIT
 movwf   DS_TMP0         ;save w
 pause   D'300'
 movf    DS_TMP0,W       ;restore stored w for return value
 return
;
; if DS_RAM1 is 255 -> "-", than the temperature is
; complement(DS_RAM0 - 1)
;
dsminusconvertion
 movf    DS_RAM1,W
 btfsc   STATUS,Z
 return 
 decf    DS_RAM0,F
 comf    DS_RAM0,F
 return
;
dstemperature
 call    dsreset
 btfss   STATUS,Z        ; zero flag set means resp. ok
 goto    badtmp

 ;movlw   0x00           ;uncomment for disabling romtable usage
 ;movwf   LCD_ACTDS      ;works only with one connected ds1820

 goto    switchbegin     ; switch betweeen different LCD_ACTDS values
switch0
 movlw   0x55            ; match rom first ds1820
 call    dswrite
 call    dswriterom0
 goto    switchend
switch1
 movlw   0x55            ; match rom second ds1820
 call    dswrite
 call    dswriterom1
 goto    switchend
switchbegin
 btfsc   LCD_ACTDS,0 
 goto switch0
 btfsc   LCD_ACTDS,1 
 goto switch1
 movlw   0xcc            ; default branch skip rom
 call    dswrite        
 goto    switchend
switchend

 movlw   0xbe            ; read scratch pad
 call    dswrite

 movlw   0x09            ; set counter to 9
 movwf   DS_TMP0
 movlw   DS_RAM0         ; indirect addressing
 movwf   FSR             ; put first byte (DS_RAM0) into FSR
dstemperatureloop
 call    dsread
 movwf   INDF            ; store read byte into INDF pointers target
 incf    FSR,F           ; increment FSR (now DS_RAM0 + n)
 decfsz  DS_TMP0,F
 goto    dstemperatureloop

 call    dsreset         ; ok, that's all
 movlw   0xcc            ; skip prom, it is ok for multible ds1820, too
 call    dswrite
 movlw   0x44            ; start convert
 call    dswrite
tempnotready                 ; bugfix to ds1820.asm around 
 call    dsread          ; 
 btfss   STATUS,Z        ; - wait here till conversion has been done
 goto    tempnotready    ; 
 ;
 ;       IF DSSIGN NOT 255 OR 0 THEN ERROR
 ;
 movf    DS_RAM1,W
 btfsc   STATUS,Z
 goto    oktmp
 addlw   0x01
 btfss   STATUS,Z
 goto    badtmp
oktmp
 retlw   0x00
badtmp
 retlw   0x01   
;
dsreadrom
 call    dsreset
 movlw   0x33                ; read rom command
 call    dswrite
 movlw   0x08                ; set counter to 8
 movwf   DS_TMP0
 movlw   DS_ROM0             ; indirect addressing
 movwf   FSR                 ; put first byte (DS_ROM0) into FSR
dsreadromloop
 call    dsread
 movwf   INDF                ; store read byte into INDF pointers target
 incf    FSR,F               ; increment FSR (now DS_ROM0 + n)
 decfsz  DS_TMP0,F
 goto dsreadromloop
 return
;
dsminmaxinit
 movlw   0xff                ; sign, 0 -> '+' 255 '-'
 movwf   DS_MIN0
 movwf   DS_MAX0
 movwf   DS_SIGNMAX0
 movwf   DS_MIN1
 movwf   DS_MAX1
 movwf   DS_SIGNMAX1
 clrf    DS_SIGNMIN0
 clrf    DS_SIGNMIN1
 return
;
; the are four decisions possible
;   max act
; 0 0   0     = max and act are +, newmax is the bigger value of both
; 1 0   255   = max is +, act value is not bigger 
; 2 255 0     = max is -, act value is bigger
; 3 255 255   = max and act are -, newmax is the smaller value of both
;
dscalcmax
 movf    DS_SIGNMAXTMP,W
 btfss   STATUS,Z
 goto    maxisminus
maxisplus
 movf    DS_RAM1,W
 btfss   STATUS,Z
 return                      ; case 1
 movf    DS_MAXTMP,W         ; case 0
 subwf   DS_RAM0,W
 btfss   STATUS,C
 return
 goto    copyacttomax
maxisminus
 movf    DS_RAM1,W
 btfsc   STATUS,Z
 goto    copyacttomax        ; case 2
 movf    DS_MAXTMP,W         ; case 3
 subwf   DS_RAM0,W
 btfsc   STATUS,C
 return
copyacttomax
 movf    DS_RAM0,W
 movwf   DS_MAXTMP
 movf    DS_RAM1,W
 movwf   DS_SIGNMAXTMP
 return
;
; the are four decisions possible
;   min act
; 0 0   0     = min and act are +, newmin is the smaller value of both
; 1 0   255   = min is +, act value is smaller
; 2 255 0     = min is -, act value is not smaller
; 3 255 255   = min and act are -, newmin is the bigger value of both
;
dscalcmin
 movf    DS_SIGNMINTMP,W
 btfss   STATUS,Z
 goto    minisminus
minisplus
 movf    DS_RAM1,W
 btfss   STATUS,Z
 goto    copyacttomin        ; case 1
 movf    DS_MINTMP,W         ; case 0
 subwf   DS_RAM0,W
 btfss   STATUS,C
 goto    copyacttomin
 return
minisminus
 movf    DS_RAM1,W
 btfsc   STATUS,Z
 return                      ; case 2
 movf    DS_MINTMP,W         ; case 3
 subwf   DS_RAM0,W
 btfss   STATUS,C
 return
copyacttomin
 movf    DS_RAM0,W
 movwf   DS_MINTMP
 movf    DS_RAM1,W
 movwf   DS_SIGNMINTMP
 return
;
lcdprintcelsius			;*********C fok kiírás ********
 movlw   'C'
 call    lcdputchar
 movlw   B'11011111'
 call    lcdputchar
 return
;
lcdprintrom
 movlw   0x08                ; set counter to 8
 movwf   DS_TMP0
 movlw   DS_ROM0             ; indirect addressing 
 movwf   FSR                 ; put first byte (DS_ROM0) into FSR
lcdprintromloop
 movf    INDF,W              ; load INDF pointers target into w
 call    lcdaschex           ; call hex->ascii conversion
 movf    LCD_ASCHEXHI,W
 call    lcdputchar
 movf    LCD_ASCHEXLO,W
 call    lcdputchar 
 incf    FSR,F               ; increment FSR (now DS_ROM0 + n)
 decfsz  DS_TMP0,F
 goto    lcdprintromloop
 return
;
lcdprintdsdata
 call    lcdascsign          ; calculate the sign from DS_SIGN
 movf    LCD_ASCSIGN,W
 call    lcdputchar

 movf    DS_RAM0,W
 movwf   NumL
 movlw   '5'
 movwf   LCD_ASCHALF         ; insert asc '5' into aschalf
 movlw   0x01
 andwf   NumL,W
 btfss   STATUS,Z
 goto    skipit
 movlw   '0'
 movwf   LCD_ASCHALF         ; insert asc '0' into aschalf
skipit

 bcf     STATUS,C            ; clear carry, to avoid rrf problems
 rrf     NumL,F              ; divide ds1820 temp through 2
 clrf    NumH
 call    bin2dec999
 movlw   0x30
 addwf   Tens,W
 call    lcdputchar
 movlw   0x30
 addwf   Ones,W
 call    lcdputchar
 movlw   '.'
 call    lcdputchar
 movf    LCD_ASCHALF,W
 call    lcdputchar
 call    lcdprintcelsius
 return
;
;Binary to decimal conversion (0..999)
;
;Input: NumH:NumL
;Output Hund:Tens:Ones
;
;If Input > 999 Output will roll over, e.g.
;for input=5678 output=678.
;
;
;Size: 34 instructions
;Execution  time  (max) including return:
;22+5*9-1+5*6-1+4*3-1+2 = 108 cycles
;
;5-July-2000 by Nikolai Golovchenko
bin2dec999
 movf    NumH,W
 addlw   D'241'
 addwf   NumH,W
 movwf   Hund      ;b_2 = 2a_2 - 15
 addwf   Hund,W
 addwf   Hund,W
 addlw   D'253'
 movwf   Tens
 swapf   NumL,W
 andlw   0x0f
 addwf   Tens,F
 addwf   Tens,F   ;b_1 = 6a_2 + 2a_1 - 48
 addwf   NumH,W
 sublw   D'251'
 movwf   Ones
 addwf   Ones,F
 addwf   Ones,F
 addwf   Ones,F
 movf    NumL,W
 andlw   0x0f
 addwf   Ones,F   ;b_0 = a_0 - 4(a_2 + a_1) - 20
 movlw   D'10'
bin2dec999a                  ; 9 cycles max
 addwf   Ones,F
 decf    Tens,F
 btfss   STATUS,C
 goto    bin2dec999a
bin2dec999b                  ; 6 cycles max
 addwf   Tens,F
 decf    Hund,F
 btfss   STATUS,C
 goto    bin2dec999b
bin2dec999c                  ; 3 cycles max
 addwf   Hund,F
 btfss   STATUS,C
 goto    bin2dec999c
 return
;
main
 clrf    STATUS
 clrf    INTCON
 clrf    PCLATH
 clrf    PORTA
 clrf    PORTB
 bsf     STATUS, RP0
 movlw   0xf8
 movwf   TRISA
 movlw   0x00
 movwf   TRISB
 bsf     OPTION_REG, NOT_RBPU
 bcf     STATUS, RP0

 bsf     OPTION_REG,PSA       ; enable watchdog
 bsf     OPTION_REG,PS0       ; set prescaler to 1:128 = 2.3 seconds
 bsf     OPTION_REG,PS1
 bsf     OPTION_REG,PS2

 call    dsminmaxinit         ; reset minmax values
 
 movlw   1 << BTN_MODENORMAL
 movwf   BTN_ACTMODE

 call    lcdinit
 call    lcdclear
 call    dstemperature        ; read the temperature once and put into trash

 movlw   LCD_LINE0
 call    lcdsdda
 call    dsprintcopyright
 movlw   LCD_LINE1
 call    lcdsdda
 call    dsreadrom            ; use these routines to determine**********ROM KÓD!!!!***********
 call    lcdprintrom          ; the rom codes of your ds1820 
                              ; remember to connect only one ds1820 for
                              ; rom detection
 ; wait approx. 5 sec
 clrwdt                       ; clear watchdog timer
 sleep                        ; wait...
 clrwdt                       ; clear watchdog timer
 sleep                        ; wait...

 call    lcdclear             ; clear display
 bcf     OPTION_REG,PS0     
 bcf     OPTION_REG,PS1       ; set prescaler to 1:16 = 0.25 seconds
loop

 movlw   1                    ; set bit 1 of LCD_ACTDS
 movwf   LCD_ACTDS          
 call    dstemperature        ; get temperature values of first ds1820
 call    dsminusconvertion
 movlw   DS_MIN0              ; minmax calculation 
 call    dsminmax2tmp         ; since we have not enough ram space
 call    dscalcmax            ; on 16f84, we can only have 2
 call    dscalcmin            ; minmax calculation areas
 movlw   DS_MIN0
 call    dstmp2minmax


 ifdef LCD_2X16               ; code to print values on 2x16 display
 movlw   LCD_LINE0            ; put output to line 1 of the lcd display
 call    lcdsdda
 btfss   BTN_ACTMODE,BTN_MODENORMAL
 goto    modeminmax0
 call    dsprinttitle0
 call    lcdprintdsdata
 goto    modeend0
modeminmax0
 btfss   BTN_ACTMODE,BTN_MODEMINMAX
 goto    modeend0
 call    dsprintminmax0
modeend0 
 endif


 ifdef LCD_4X16               ; code to print values on 4x16 display
 movlw   LCD_LINE0
 call    lcdsdda
 call    dsprinttitle0
 call    lcdprintdsdata
 movlw   LCD_LINE1
 call    lcdsdda
 call    dsprintminmax0
 endif
 movlw   2                    ; set bit 2 of LCD_ACTDS
 movwf   LCD_ACTDS          
 call    dstemperature        ; get temperature values of second ds1820
 call    dsminusconvertion
 movlw   DS_MIN1              ; minmax calculation
 call    dsminmax2tmp
 call    dscalcmax
 call    dscalcmin
 movlw   DS_MIN1
 call    dstmp2minmax


 ifdef LCD_2X16               ; code to print values on 2x16 display
 movlw   LCD_LINE1            ; put output to line 2 of the lcd display
 call    lcdsdda
 btfss   BTN_ACTMODE,BTN_MODENORMAL
 goto    modeminmax1
 call    dsprinttitle1
 call    lcdprintdsdata
 goto    modeend1
modeminmax1
 btfss   BTN_ACTMODE,BTN_MODEMINMAX
 goto    modeend1
 call    dsprintminmax1
modeend1
 endif


 ifdef LCD_4X16               ; code to print values on 4x16 display
 movlw   LCD_LINE2
 call    lcdsdda
 call    dsprinttitle1
 call    lcdprintdsdata
 movlw   LCD_LINE3
 call    lcdsdda
 call    dsprintminmax1
 endif

 ; more ds1820 may follow if the lcd display has enough lines

 clrwdt                      ; clear watchdog timer
 sleep                       ; wait 0.50 seconds, for screen switching
 
 ; rotate through the display modes
 bcf     STATUS,C 
 rlf     BTN_ACTMODE,F
 btfss   BTN_ACTMODE,BTN_MODEMINMAX + 1 
 goto    loop                ; there are still modes available
 movlw   1 << BTN_MODENORMAL ; no modes left, start with first mode
 movwf   BTN_ACTMODE

 goto    loop               
end
