

;PIC16F877, 20MHz, WDT OFF, POR ON, XTAL HS

;PROGRAM WRITTEN IN TASM VARIANT - NEEDS TRANSLATING VIA TK3 TO SUIT MPASM

;Config register bits
; CP1 CP0 CP1 CP0 NIL CPD LVP BOR MCL OS2 POR WDT OS1 OS0
;  1   1   1   1   1   1   0   0   1   0   0   0   1   0
;N.B. Logic 1/0 do NOT necessarily mean that the function is On/Off
;respectively - refer to PIC16F877 data sheet

#DEFINE BANK0 BCF STATUS,5
#DEFINE BANK1 BSF STATUS,5
#DEFINE RP1LO BCF $03,6  ; clear STATUS bit 6 (RP1)
#DEFINE RP1HI BSF $03,6  ; set   STATUS bit 6 (RP1)
#DEFINE BLOCK0 BCF $03,7 ; clear STATUS bit 7 (IRP)
#DEFINE BLOCK1 BSF $03,7 ; set   STATUS bit 7 (IRP)
#DEFINE SERIALDELAY call CYCLES25  ; set serial chip write delay value
                         ; CYCLES25 for 20MHz, CYCLES5 for 4MHz or below

        List P = PIC16F877, R=DEC;
        __CONFIG   h'3F32'

        include P16F877.inc

        CBLOCK

REGA0				;lsb
REGA1
REGA2
REGA3				;msb

REGB0				;lsb
REGB1
REGB2
REGB3				;msb

REGC0				;lsb
REGC1
REGC2
REGC3				;msb

DSIGN				;Digit Sign. 0=positive,FF(or non zero)=negative
DIGIT1				;MSD
DIGIT2
DIGIT3
DIGIT4
DIGIT5				;Decimal digits
DIGIT6
DIGIT7
DIGIT8
DIGIT9
DIGIT10				;LSD
MTEMP
MCOUNT
DCOUNT

LOOP        ; loop counter
LOOPA       ; loop counter for LCD
RSLINE      ; LCD command/data flag
CLKCNT      ; pre-counter for seconds
STORE1      ; general store
SOFTB       ; soft copy of PORTB register
BPORT       ; working copy of PORTA
CHECKIT 
MEMHI     
MEMLO     
WADDRL    
WADDRH    
RADDRH    
RADDRL    
POLLCNT     ; serial eeprom use
SLAVE       ; serial eeprom use
TXBUF       ; serial eeprom use
BCOUNT  
COUNT   
DATAI   
DATAO   
EEPROM  
RECORD  
PREVRECORD
REFERENCEMSB
REFERENCENSB
REFERENCELSB
STOREMSB
STORENSB
STORELSB
SIGNREF
ABORT

STORE
GPSLOOP     ; temp loop for simulation with data in eeprom
CHECKSUM
VALIDITY
DISPLAYCOUNT
PREVDISPLAYCOUNT
LETTER
LETTERCOUNT
STARTCOUNT
TIMEOUT
TIMEOUT2
TIMEOUT3
LATMSB
LATLSB
LONGMSB
LONGLSB
ECHAN
MEMCNT
BARGRAPH
RECORDMSB
RECORDLSB

	ENDC

; ***** VALUES HELD IN BOTH BANKS

        CBLOCK H'70'
BOTSENSMSB
BOTSENSNSB
BOTSENSLSB
TOPSENSMSB
TOPSENSNSB
TOPSENSLSB
PROMVAL
MEMFUL
        ENDC

MEM1:       .EQU $10  ; first data memory location for Bank 2 (at $120)

             ;************************************************************
             ;           Bit Definitions
             ;************************************************************

DI:         .EQU $07        ; eeprom input bit
DO:         .EQU $06        ; eeprom output bit
SDATA:      .EQU $04        ; serial EE data line (PORTC)
SCLK:       .EQU $03        ; serial EE clock line (PORTC)

        ORG 0
        goto GIEOFF
        ORG 4            ; Interrupt vector address
        goto GIEOFF
        ORG 5

GIEOFF: BCF INTCON,GIE   ; turn off global interrupts
        BTFSC INTCON,GIE
        goto GIEOFF
        goto START

LCDSET: clrf LOOP        ;clr LCD set-up loop
        clrf RSLINE      ;clear RS line for instruction send
LCDST2: movf LOOP,W      ;get table address
        call TABLCD      ;get set-up instruction
        call LCDOUT      ;perform it
        incf LOOP,F      ;inc loop
        btfss LOOP,3     ;has last LCD set-up instruction now been done?
        goto LCDST2      ;no
        return

TABLCD: addwf PCL,F      ;LCD initialisation table
        retlw %00110011  ;initialise lcd - first byte
        retlw %00110011  ;2nd byte (repeat of first)
        retlw %00110010  ;set for 4-bit operation
        retlw %00101100  ;set for 2 lines
        retlw %00000110  ;set entry mode to increment each address
        retlw %00001100  ;set display on, cursor off, blink off
        retlw %00000001  ;clear display
        retlw %00000010  ;return home, cursor & RAM to zero
                         ;end inititalisation table

MESSAG1: addwf PCL,F
        retlw 'E'
        retlw 'P'
        retlw 'E'
        retlw ' '
        retlw 'M'
        retlw 'A'
        retlw 'G'
        retlw 'N'
        retlw 'E'
        retlw 'T'
        retlw 'O'
        retlw 'M'
        retlw 'E'
        retlw 'T'
        retlw 'E'
        retlw 'R'

MESSAG2: addwf PCL,F
        retlw 'C'
        retlw 'L'
        retlw 'E'
        retlw 'A'
        retlw 'R'
        retlw 'I'
        retlw 'N'
        retlw 'G'
        retlw ' '
        retlw 'E'
        retlw 'E'
        retlw 'P'
        retlw 'R'
        retlw 'O'
        retlw 'M'
        retlw ' '

MESSAG5: addwf PCL,F
        retlw ' '
        retlw ' '
        retlw ' '
        retlw ' '
        retlw ' '
        retlw '0'
        retlw ' '
        retlw 'O'
        retlw 'F'
        retlw ' '
        retlw 'C'
        retlw 'H'
        retlw 'I'
        retlw 'P'
        retlw ' '
        retlw ' '

MESSAG7: addwf PCL,F
        retlw 'R'
        retlw 'E'
        retlw 'A'
        retlw 'C'
        retlw 'H'
        retlw 'E'
        retlw 'D'
        retlw ' '
        retlw 'L'
        retlw 'I'
        retlw 'M'
        retlw 'I'
        retlw 'T'
        retlw ' '
        retlw ' '
        retlw ' '

MESSAG7A: addwf PCL,F
        retlw 'C'
        retlw 'A'
        retlw 'N'
        retlw ' '
        retlw 'O'
        retlw 'N'
        retlw 'L'
        retlw 'Y'
        retlw ' '
        retlw 'S'
        retlw 'E'
        retlw 'N'
        retlw 'D'
        retlw ' '
        retlw 'P'
        retlw 'C'

MESSAGJ:  addwf PCL,F
           retlw 'S'
           retlw 'E'
           retlw 'R'
           retlw 'I'
           retlw 'A'
           retlw 'L'
           retlw ' '
           retlw 'O'
           retlw 'C'
           retlw 'X'
           retlw ' '
           retlw 'T'
           retlw 'O'
           retlw ' '
           retlw 'P'
           retlw 'C'

NULLED: ADDWF PCL,F       ; Nulled message
        retlw 'N'
        retlw 'U'
        retlw 'L'
        retlw 'L'
        retlw 'E'
        retlw 'D'
        retlw ' '
        retlw ' '

MESSAG10: addwf PCL,F
        retlw ' '
        retlw 'N'
        retlw 'O'
        retlw ' '
        retlw 'G'
        retlw 'P'
        retlw 'S'

        retlw ' '
        retlw 'S'
        retlw 'I'
        retlw 'G'
        retlw 'N'
        retlw 'A'
        retlw 'L'
        retlw ' '
        retlw ' '


WAITPC: addwf PCL,F
        retlw 'W'
        retlw 'A'
        retlw 'I'
        retlw 'T'
        retlw 'I'
        retlw 'N'
        retlw 'G'
        retlw ' '
        retlw 'P'
        retlw 'C'
        retlw ' '
        retlw 'T'
        retlw 'R'
        retlw 'I'
        retlw 'G'
        retlw ' '

ENDPC:  addwf PCL,F
        retlw 'T'
        retlw 'R'
        retlw 'A'
        retlw 'N'
        retlw 'S'
        retlw 'F'
        retlw 'E'
        retlw 'R'
        retlw ' '
        retlw 'E'
        retlw 'N'
        retlw 'D'
        retlw 'E'
        retlw 'D'
        retlw ' '
        retlw ' '

        retlw 'S'
        retlw 'W'
        retlw 'I'
        retlw 'T'
        retlw 'C'
        retlw 'H'
        retlw ' '
        retlw 'R'
        retlw 'U'
        retlw 'N'
        retlw ' '
        retlw 'A'
        retlw 'G'
        retlw 'A'
        retlw 'I'
        retlw 'N'

TABLELETTER: movf LETTERCOUNT,W
        addwf STARTCOUNT,W
        addwf PCL,F   ; GPS sentence ID table
        retlw '$'
        retlw 'G'
	retlw 'P'
	retlw 'R'
	retlw 'M'
	retlw 'C'

        retlw '$'
	retlw 'G'
	retlw 'P'
	retlw 'G'
	retlw 'G'
	retlw 'A'
        retlw '#'

;*******************

START:  bcf STATUS,RP0
        bcf STATUS,RP1
        clrf PORTA       ; initialise all port outputs to zero
        clrf PORTB
        clrf PORTC
        clrf PORTD
        clrf PORTE

        BANK1
        movlw %00111111
        movwf TRISB
        movlw %00000110  ; All A & E as digital

        movwf ADCON1
        movlw %00100011  ; RA0, RA1 as input
        movwf TRISA
        movlw %10000000
        movwf TRISC
	clrf TRISD
        clrf TRISE
        movlw %00000111  ; set timer ratio 1:256, pull-ups on
        movwf OPTION_REG
        BANK0

        clrf INTCON
        call PAUSIT
        call LCDSET
        clrf INTCON
        call PAUSIT

        call SHOWTITLE

        clrf BOTSENSMSB
        clrf BOTSENSNSB
        clrf BOTSENSLSB
        clrf TOPSENSMSB
        clrf TOPSENSNSB
        clrf TOPSENSLSB

        clrf REFERENCEMSB
        clrf REFERENCENSB
        clrf REFERENCELSB

        movlw 0          ; get previous reference values
        call PRMGET
        movwf REFERENCEMSB
        movlw 1
        call PRMGET
        movwf REFERENCENSB
        movlw 2
        call PRMGET
        movwf REFERENCELSB

        call JOESETBAUD  ; set baud rate
        clrf SOFTB
        movlw 5
        movwf CLKCNT

        movlw %00110000  ; set timer 1 for prescale 1/8, and timer off
        movwf T1CON
        clrf TMR1L       ; reset timer 1
        clrf TMR1H


; ****** GET CHIP COUNT

         clrf ECHAN

GETCHIP  clrf WADDRH      ; set write address MSB
         clrf WADDRL      ; set write address LSB
         clrf RADDRH      ; set read address MSB
         clrf RADDRL      ; set read address LSB

         call READ        ; read from EEPROM chip
         movf MEMLO,W     ; get LSB value
         movwf VALIDITY

         comf MEMLO,F     ; invert value
         clrf WADDRL      ; set write address LSB
         call SAVESAMPLE

         clrf RADDRL      ; set read address LSB
         call READ        ; read from EEPROM chip
         xorwf VALIDITY,W ; is 2nd read value same as 1st read?
         btfsc STATUS,Z
         goto SHOWCHIPS   ; yes

WRITEBACK comf MEMLO,F
         clrf WADDRL      ; set write address LSB
         call SAVESAMPLE
         clrf RADDRL      ; set write address LSB

         call READ        ; read from EEPROM chip
         incf ECHAN,F
         btfss ECHAN,3
         goto GETCHIP

SHOWCHIPS: call LCD21
         bsf RSLINE,4

         movf ECHAN,W
         iorlw 48
         call LCDOUT

         movlw ' '
         call LCDOUT
         movlw 'E'
         call LCDOUT
         movlw 'E'
         call LCDOUT
         movlw 'P'
         call LCDOUT
         movlw 'R'
         call LCDOUT
         movlw 'O'
         call LCDOUT
         movlw 'M'
         call LCDOUT
         movlw ' '
         call LCDOUT
         movlw 'C'
         call LCDOUT
         movlw 'H'
         call LCDOUT
         movlw 'I'
         call LCDOUT
         movlw 'P'
         call LCDOUT
         movlw ' '
         btfsc ECHAN,1
         movlw 'S'
         call LCDOUT

        movf ECHAN,W
        movwf MEMCNT
        clrf ECHAN
        clrf WADDRH
        clrf WADDRL

        btfsc PORTB,0   ; is external serial chip clearance needed?
        goto SHOWC2
        call CLEARIT    ; yes

        call CLRLINE2

SHOWC2: call SHOWTITLE
        call TIMEOUTMSG
        call CLEARADR

        call PAUSIT
        call PAUSIT
        call PAUSIT

        bcf PIR1,0       ; timer rollover flag
        bsf T1CON,0      ; start timer 1

        clrf RECORD
        movlw %00000010
        movwf PREVRECORD 

        movlw %00000100
        movwf PREVDISPLAYCOUNT

        call SETCGRAM

        movlw 3               ; get last recording count
        call PRMGET
        movwf ECHAN
        movlw 4
        call PRMGET
        movwf WADDRH
        movlw 5
        call PRMGET
        movwf WADDRL
        movlw 6
        call PRMGET
        movwf MEMFUL
        btfsc MEMFUL,0           ; is MEMFUL flag set ?
        goto SHOWMEMFUL          ; yes, so only download permitted

        clrf RECORDMSB
        clrf RECORDLSB
        clrf BARGRAPH

;********* START OF MAIN PROGRAM ********

MAIN:   btfss RECORD,1          ; is record switch on (low)
        goto MAIN00             ; yes, so bypass check for download switch

        btfsc PORTB,4           ; is PC switch on (high)?
        goto CHECKPC            ; yes, so wait for PC to ask for download
        goto MAIN0              ; no, bypass look for PC handshake

CHECKPC: call WAITINGPC
        call JOESETBAUD
        btfsc PORTB,2           ; is display on screen 2?
        goto CHECKPC2           ; no
        call BACKIT             ; yes, so set to screen 1
        bsf PREVDISPLAYCOUNT,2
;        bsf PORTE,2       ; turn on buzzer

CHECKPC2: btfss PORTB,4         ; is GPS switch on (low)?
        goto MAIN0              ; yes, so bypass/end check if PC is asking for download

        btfss   PIR1,RCIF       ; Check for any RX'd data
        goto CHECKPC2           ; Nothing RX'd
        movf    RCREG,W         ; Store the RX'd data in 'W'
        sublw   'G'             ; Is this a 'G' ?
        btfss   STATUS,Z
        goto CHECKPC2           ; not yet
        call JOEDOWNLOAD        ; Yes, a 'G'
        call PCENDED

        movlw 3                 ; get last recording count
        call PRMGET
        movwf ECHAN
        movlw 4
        call PRMGET
        movwf WADDRH
        movlw 5
        call PRMGET
        movwf WADDRL

CHECKPC3: btfsc PORTB,4         ; wait for switch to be set back to run
        goto CHECKPC3

MAIN0:  movf PORTB,W            ; check to see which screen should be displayed
        andlw %00000100
        movwf DISPLAYCOUNT
        xorwf PREVDISPLAYCOUNT,W
        btfss STATUS,Z
        call PAGECHANGE
        movf DISPLAYCOUNT,W
        movwf PREVDISPLAYCOUNT

        btfss DISPLAYCOUNT,2    ; is GPS screen needed?
        call STARTGPS           ; yes

MAIN00: movf PORTB,W            ; is record switch same as previously?
        andlw %00000010
        movwf RECORD
        xorwf PREVRECORD,W
        btfsc STATUS,Z
        goto MAIN1A             ; yes

        call TEMPERATURE

        btfsc RECORD,1          ; is record switch on (low)
        goto ENDREC             ; no, it's been switched off
        call STOREGPRMC         ; yes, so send Starting GPS lat & long values
        clrf RECORDMSB
        clrf RECORDLSB
        btfsc PORTB,2           ; is display on screen 2?
        goto MAIN1A             ; no
        call BACKIT             ; yes, so set to screen 1
        bsf PREVDISPLAYCOUNT,2
        goto MAIN1A

ENDREC: movlw 1                 ; no, it's been switched off
        movwf BOTSENSLSB        ; send four "1"s to external eeprom
        movwf BOTSENSNSB
        movwf TOPSENSLSB
        movwf TOPSENSNSB
        call STOREIT
        call STOREGPRMC         ; also send current GPS lat & long values
        call STORECOUNT

        call PAUSIT
        call PAUSIT
        call PAUSIT
        call PAUSIT

MAIN1A: movf RECORD,W     ; copy current record switch value
        movwf PREVRECORD

MAIN1:  clrf BOTSENSLSB   ; reset sensor store values
        clrf BOTSENSNSB
        clrf BOTSENSMSB
        clrf TOPSENSLSB
        clrf TOPSENSNSB
        clrf TOPSENSMSB
        movlw 10          ; set sensor sampling time
        movwf CLKCNT

        bcf T1CON,0       ; stop timer 1
        clrf TMR1L        ; reset timer 1
        clrf TMR1H
        bcf PIR1,0        ; timer rollover flag
        bsf T1CON,0       ; start timer 1
        bsf PORTA,3       ; turn on LED

        btfss PORTB,3
        bsf PORTE,2       ; turn on buzzer

        call GETFREQ      ; get sensor values

        call GETDIFF      ; get diff between top & bottom sensors
        movf REGA3,W
        andlw %10000000
        movwf SIGNREF
        btfss STATUS,Z
        call negatea      ; yes, so invert answer

        movf REGA0,W      ; store diff into STORE
        movwf STORELSB
        movf REGA1,W
        movwf STORENSB
        movf REGA2,W
        movwf STOREMSB

        clrf SIGNREF

        movf WADDRH,W
        movwf REGA1
        movf WADDRL,W
        movwf REGA0
        clrf REGA2
        clrf REGA3

MAIN10: call BIN2DEC
        call LCD1
        movf ECHAN,W      ; show recording count
        addlw 'A'
        call LCDOUT

        call SHOWDIG6
        movlw ' '
        call LCDOUT
        movlw ' '
        call LCDOUT

        movf RECORDMSB,W   ; show recording count for this column
        movwf REGA1
        movf RECORDLSB,W
        movwf REGA0
        clrf REGA2
        clrf REGA3
        call BIN2DEC
        call LCD6
        call SHOWDIG7     ; 8
        movlw ' '
        call LCDOUT

        btfsc PORTB,1        ; is S2 on (low - recording in progress)?
        goto MAIN3           ; no
        bsf PORTA,2

        goto MAIN2           ; yes

MAIN3:  btfss PORTB,0        ; is S1 pressed (Store ref vals)?
        call SETREF   
        bcf PORTA,2

MAIN2:  movf STORELSB,W      ; copy diff into REGA
        movwf REGA0
        movf STORENSB,W
        movwf REGA1
        movf STOREMSB,W
        movwf REGA2
        clrf REGA3

        movf REFERENCELSB,W  ; copy ref into REGB
        movwf REGB0
        movf REFERENCENSB,W
        movwf REGB1
        movf REFERENCEMSB,W
        movwf REGB2
        clrf REGB3

        call SUBTRACT        ; get diff - ref
        movf REGA3,W         ; is it negative?
        andlw %10000000
        movwf SIGNREF
        btfss STATUS,Z
        call negatea         ; yes, so invert answer

        btfsc PORTB,1        ; is S2 on (low - recording in progress)?
        goto MAIN5
        call STOREIT         ; yes so store it to external eeprom ******
;        bsf PORTE,2       ; turn on buzzer
        incfsz RECORDLSB,F
        goto MAIN5
        incf RECORDMSB,F

MAIN5:  movf REGA0,W         ; store result into STORE
        movwf STORELSB
        movf REGA1,W
        movwf STORENSB
        movf REGA2,W
        movwf STOREMSB

        call LCD11
        call BIN2DEC         ; show result of diff - ref
        movf DIGIT7,W
        andlw 15
        btfsc STATUS,Z
        goto MAIN4

        movlw '*'
        movwf DIGIT8
        movwf DIGIT9
        movwf DIGIT10

MAIN4:  call SHOWDIG8
        movlw '+'
        btfsc SIGNREF,7
        movlw '-'
        call LCDOUT

;        movlw ' '
;        call LCDOUT
        movlw ' '
        btfss PORTB,1      ; is recording in progress?
        movlw 'R'          ; yes
        call LCDOUT

        btfsc PORTB,3
        goto SHOWBAR
        call SHOWSENSVALS
        goto MAIN

SHOWBAR: call SHOWBARGRAPH
        goto MAIN


;********** LCD CONTROL SECTION *********

LCD1:   movlw %10000000
        goto LCDLIN
LCD6:   movlw %10000110
        goto LCDLIN
;LCD10:  movlw %10001010
;        goto LCDLIN
LCD11:  movlw %10001011
        goto LCDLIN

LCD16:  movlw %10010000
        goto LCDLIN

LCD21:  movlw %11000000
        goto LCDLIN
LCD2F:  movlw %11001111
        goto LCDLIN

LCD216: movlw %11010000
        goto LCDLIN
LCD21D: movlw %11011100
        goto LCDLIN

LCDOUT: movwf STORE1    ; temp store value that will be output to LCD
        movlw 255       ; set minimum time between sending full bytes to LCD
        movwf LOOPA
DELAY:  decfsz LOOPA,F
        goto DELAY
        call SENDIT     ; send MSB, then (by default) send LSB

SENDIT: swapf STORE1,F  ; swap byte nibbles
        movf STORE1,W   ; get nibble (MSB)
        andlw 15        ; AND to isolate nibble
        iorwf RSLINE,W  ; OR the RS bit
        movwf PORTD     ; output the byte
        nop
        bsf PORTD,5     ; set E high
        nop
        bcf PORTD,5     ; set E low
        return

LCDLIN: bcf RSLINE,4    ; sets LCD command/line
        call LCDOUT     ; and outputs cmmand code to LCD
        bsf RSLINE,4    ; set RS flag
        return

PAUSIT: movlw 14        ; 1/5th sec wait set
        movwf CLKCNT
        clrf INTCON     ; clear interupt flag
PAUSE:                  ;
        btfss INTCON,2  ; has a timer time-out been detected?
        goto PAUSE      ; no
        bcf INTCON,2    ; yes
        decfsz CLKCNT,F ; dec loop, is it zero?
        goto PAUSE      ; no
        return          ; yes

; **************

CLEARIT: call CLRLINE1        ; clear entire external serial eeprom
        call CLRLINE2

        clrf LOOP
        call LCD1
        bsf RSLINE,4
SHOWCLR: movf LOOP,W
        call MESSAG2          ; clearing eeprom
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto SHOWCLR

        clrf LOOP
        call LCD21
        bsf RSLINE,4
SHOWCL2: movf LOOP,W
        call MESSAG5          ; clearing eeprom
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto SHOWCL2
        call LCD2F
        incf ECHAN,W
        iorlw 48
        call LCDOUT
        call CLEARADR

CLEAR2: call SAVESAMPLE
        btfsc MEMFUL,0    ; is MEMFUL set from address inc routine?
        goto CLEAR4       ; yes
        btfss STATUS,C    ; is there a carry from address inc routine?
        goto CLEAR2       ; no

        movf WADDRL,W     ; yes, so show count
        movwf REGA0
        movf WADDRH,W
        movwf REGA1
        clrf REGA2
        clrf REGA3
        call BIN2DEC
        call LCD21
        bsf RSLINE,4
        call SHOWDIG5     ; show current record count
        call LCD2F
        incf ECHAN,W
        iorlw 48
        call LCDOUT
        goto CLEAR2

CLEAR4: call CLEARADR
        call STORECOUNT  ; store reset count value to eeprom

        clrf PROMVAL     ; store reset MEMFUL flag
        movlw 6
        call SETPRM
        return

; **********

SHOWTITLE: clrf LOOP
        call LCD1
        bsf RSLINE,4
SHOWMS1: movf LOOP,W
        call MESSAG1          ; EPE Magnetometer
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto SHOWMS1
        call PAUSIT
        return

; *********

;SHOWRECEND: clrf LOOP
;        call LCD1
;        bsf RSLINE,4
;SHOWREC: movf LOOP,W
;        call RECEND           ; record ended
;        call LCDOUT
;        incf LOOP,F
;        btfss LOOP,4
;        goto SHOWREC
;        call PAUSIT
;        return

; ************

CLRLINE1: call LCD1     ;set address for line 1 cell 1
        bsf RSLINE,4    ;set RS for data send
        clrf LOOP       ;
CLRL1:  movlw ' '       ;clear cell
        call LCDOUT     ;
        incf LOOP,F     ;inc loop
        btfss LOOP,4    ;has last LCD letter been sent?
        goto CLRL1      ;no
        return

CLRLINE2: call LCD21
        bsf RSLINE,4
        movlw 16
        movwf LOOP
CL2:    movlw ' '
        call LCDOUT
        decfsz LOOP,F
        goto CL2
        return

; ***************

STOREIT: movf BOTSENSNSB,W    ; store bottom sensor vals to external serial EEPROM chip
         movwf MEMHI
         movf BOTSENSLSB,W
         movwf MEMLO
         call SAVESAMPLE
         btfsc MEMFUL,0
         goto SHOWMEMFUL

         movf TOPSENSNSB,W    ; store top sensor vals to external serial EEPROM chip
         movwf MEMHI
         movf TOPSENSLSB,W
         movwf MEMLO
         call SAVESAMPLE
         btfsc MEMFUL,0
         goto SHOWMEMFUL
         return

;*********

;SERIALMEM01 30MAR02 from LOG430.ASM 29OCT99 - JOHN BECKER - EPE DATA LOGGER MODIFIED EXTRACT

SAVESAMPLE: movf MEMHI,W   ; store MSB
        call WRBYTE
        incf WADDRL,F      ; inc address
        movf MEMLO,W       ; store LSB
        call WRBYTE
        decf WADDRL,F      ; dec address back to prev count
        call INCADDRESS
        return

;*********** cycles pause called by Serial EEPROM write routines ****

; the CALL takes 2 clock cycles
; the RETURN takes 2 clock cycles
; a pause of 4 clock cycles is created by just CALLing CYCLES4 and returning
; each NOP adds a further 1 cycle pause

CYCLES25:  NOP
CYCLES24:  NOP
CYCLES23:  NOP
CYCLES22:  NOP
CYCLES21:  NOP
CYCLES20:  NOP
CYCLES19:  NOP
CYCLES18:  NOP
CYCLES17:  NOP
CYCLES16:  NOP
CYCLES15:  NOP
CYCLES14:  NOP
CYCLES13:  NOP
CYCLES12:  NOP
CYCLES11:  NOP
CYCLES10:  NOP
CYCLES9:   NOP
CYCLES8:   NOP
CYCLES7:   NOP
CYCLES6:   NOP
CYCLES5:   NOP
CYCLES4:   return

;*************

;CONVERTED MPASM FILE C:\ASMCNV\2WDPOLL.ASM
;       TO TASM  FILE C:\PIC\2WDPOLL.ASM 03-12-1999 19:28:42
; see Microchip CD-ROM disk 2, download\appnote\category\eeproms\00567.ZIP
; the original used timings based on a 4MHz clock
; this routine has been modified to enable different xtal rates
; Defining SERIALDELAY as "call CYCLE5" is for 4MHz or less xtal
; Defining SERIALDELAY as "call CYCLE25" is for 20MHz xtal

          ;***************************************************************
          ;       Byte Write Routine with data polling
          ;***************************************************************

WRBYTE:   movwf DATAO         ;entry with val to send in W, stored to DATAO
          bcf STATUS,C
          rlf ECHAN,W
          iorlw %10100000   ; set slave address and write mode
          MOVWF SLAVE

BYTE:     CALL BSTART         ; generate start bit
          MOVF SLAVE,W        ; move slave address
          MOVWF TXBUF         ; into transmit buffer
          CALL TX             ; and send it

          movf WADDRH,W       ; send address high byte
          MOVWF TXBUF         ; into transmit buffer
          CALL TX             ; and send it

          movf WADDRL,W       ; send address low byte
          MOVWF TXBUF         ; into transmit buffer
          CALL TX             ; and send it

          MOVF DATAO,W        ; move data byte
          MOVWF TXBUF         ; to tranmit buffer
          CALL TX             ; and transmit it
          CALL BSTOP          ; generate stop bit

          MOVLW 40            ; now start polling for a low ack bit
          MOVWF POLLCNT       ; set max number of times to poll
POLL:     CALL BSTART         ; generate start bit

          bcf STATUS,C
          rlf ECHAN,W
          iorlw %10100000   ; set slave address and write mode

          MOVWF TXBUF         ; into transmit buffer
          CALL TX             ; and send it
          BTFSS EEPROM,DI     ; was the ack bit low?
          GOTO EXITPOLL       ; yes, do another byte
          DECFSZ POLLCNT,F    ; is poll counter down to zero?
          GOTO POLL           ; no, poll again.
EXITPOLL: return

          ;**************************************************************
          ;       Start Bit Subroutine - generates a start bit
          ;       (Low going data line while clock is high)
          ;**************************************************************

BSTART:   BSF PORTC,SDATA    ; make sure data is high
          BANK1
          MOVLW %10100111
          MOVWF TRISC        ; set data and clock lines for output
          BANK0
          BCF PORTC,SCLK     ; make sure clock is low
          NOP                 
          BSF PORTC,SCLK     ; set clock high
          SERIALDELAY        ; timing adjustment
          BCF PORTC,SDATA    ; data line goes low during
                             ; high clock for start bit
          SERIALDELAY        ; timing adjustment
          BCF PORTC,SCLK     ; start clock train
          NOP                 
          NOP                 
          RETLW 0             

          ;************************************************************
          ;       Stop Bit Subroutine - generates a stop bit
          ;       (High going data line while clock is high)
          ;************************************************************

BSTOP:    BANK1
          MOVLW %10100111
          MOVWF TRISC        ; set data/clock lines as outputs
          BANK0
          BCF PORTC,SDATA    ; make sure data line is low
          SERIALDELAY        ; timing adjustment        
          BSF PORTC,SCLK     ; set clock high
          SERIALDELAY        ; timing adjustment
          BSF PORTC,SDATA    ; data goes high while clock high for stop bit
          SERIALDELAY        ; timing adjustment
          BCF PORTC,SCLK     ; set clock low again
          SERIALDELAY        ; timing adjustment
          RETLW 0

            ;*************************************************************
            ;       BITOUT routine takes one bit of data in 'do' and
            ;       transmits it to the serial EE device
            ;*************************************************************

BITOUT:   BANK1
          MOVLW %10100111
          MOVWF TRISC
          BANK0
          BTFSS EEPROM,DO    ; check for state of data bit to xmit
          GOTO BITLOW        ;
          BSF PORTC,SDATA    ; set data line high
          GOTO CLKOUT        ; go toggle the clock

BITLOW:   BCF PORTC,SDATA    ; output a low bit
CLKOUT:   BSF PORTC,SCLK     ; set clock line high
          SERIALDELAY        ; timing adjustment
          BCF PORTC,SCLK     ; return clock line low
          RETLW 0             

          ;**************************************************************
          ;       BITIN routine reads one bit of data from the
          ;       serial EE device and stores it in 'di'
          ;**************************************************************

BITIN:    BSF EEPROM,DI       ; assume input bit is high
          BANK1
          MOVLW %10110111     ; make sdata an input line
          MOVWF TRISC
          BANK0
          BSF PORTC,SDATA    ; set sdata line for input
          BSF PORTC,SCLK     ; set clock line high
          SERIALDELAY        ; timing adjustment
          BTFSS PORTC,SDATA  ; read the data bit
          BCF EEPROM,DI      ; input bit was low
          BCF PORTC,SCLK     ; set clock line low
          RETLW 0

          ;****************************************************************
          ;       Transmit Data Subroutine
          ;****************************************************************

TX:       MOVLW 8
          MOVWF COUNT         ; set the #bits to 8
TXLP:     BCF EEPROM,DO       ; assume bit out is low
          BTFSC TXBUF,7       ; is bit out really low?
          BSF EEPROM,DO       ; otherwise data bit =1
          CALL BITOUT         ; serial data out
          RLF TXBUF,F         ; rotate txbuf left
          DECFSZ COUNT,F      ; 8 bits done?
          GOTO TXLP           ; no - go again
          CALL BITIN          ; read ack bit
          RETLW 0             

                              
;CONVERTED MPASM FILE C:\ASMCNV\2WSEQR.ASM
;       TO TASM  FILE C:\PIC\2WSEQR.ASM 03-12-1999 19:29:04

          ;************************************************************
          ;       2-Wire Sequential Read Program
          ;************************************************************
          ;       Stop Bit Subroutine - generates a stop bit
          ;       (High going data line while clock is high)
          ;************************************************************

BSTOP2:   BANK1
          MOVLW %10100111     ;
          MOVWF TRISC         ; set data/clock lines as outputs
          BANK0
          BCF PORTC,SDATA     ; make sure data line is low
          SERIALDELAY
          BSF PORTC,SCLK      ; set clock high
          SERIALDELAY
          BSF PORTC,SDATA     ; data goes high while clock high for stop bit
          SERIALDELAY
          BCF PORTC,SCLK      ; set clock low again
          SERIALDELAY
          RETLW 0

          ;**************************************************************
          ;       BITIN2 routine reads one bit of data from the
          ;       serial EE device and stores it in 'di'
          ;**************************************************************

BITIN2:   BSF EEPROM,DI       ; assume input bit is high
          BANK1
          MOVLW %10110111     ; make sdata an input line
          MOVWF TRISC
          BANK0
          BSF PORTC,SCLK      ; set clock line high
          SERIALDELAY
          BTFSS PORTC,SDATA  ; read the data bit
          BCF EEPROM,DI       ; input bit was low, set 'di' accordingly
          BCF PORTC,SCLK     ; set clock line low
          RETLW 0             

          ;****************************************************************
          ;       Transmit Data Subroutine
          ;****************************************************************

TX2:      MOVLW 8
          MOVWF COUNT         ; set the #bits to 8
TXLP2:    BCF EEPROM,DO       ; assume bit out is low
          BTFSC TXBUF,7       ; is bit out really low?
          BSF EEPROM,DO       ; no, set it high
          CALL BITOUT         ; send the bit to serial EE
          RLF TXBUF,F         ; rotate txbuf left
          DECFSZ COUNT,F      ; 8 bits done?
          GOTO TXLP2          ; no - go again
          CALL BITIN2         ; read ack bit
          BTFSC EEPROM,DI     ; check ack bit
          NOP
          RETLW 0             

          ;****************************************************************
          ;       Receive data Routine
          ;****************************************************************

RX:       MOVLW 8             ; set # bits to 8
          MOVWF COUNT         
          CLRF DATAI          ; clear input register
          BCF STATUS,0        ; make sure carry bit is low
RXLP:     RLF DATAI,F         ; rotate DATAI 1 bit left
          CALL BITIN2         ; read a bit
          BTFSC EEPROM,DI     
          BSF DATAI,0         ; set bit 0 if necessary
          DECFSZ COUNT,F      ; 8 bits done?
          GOTO RXLP           ; no, do another
          RETLW 0             

          ;**************************************************************
          ;       READ (sequential read routine)
          ;**************************************************************

READ:     MOVLW 2             
          MOVWF BCOUNT        ; set number of bytes to read
          bcf STATUS,C
          rlf ECHAN,W
          iorlw %10100000     ; set slave address and write mode
          MOVWF SLAVE         

          CALL BSTART         ; generate start bit
          MOVF SLAVE,W        ; get slave address
          MOVWF TXBUF         ; into transmit buffer
          CALL TX2            ; and send it

          movf RADDRH,W       ; send address high byte
          MOVWF TXBUF         ; into transmit buffer
          CALL TX2            ; and send it

          MOVF RADDRL,W       ; get word address
          MOVWF TXBUF         ; into transmit buffer
          CALL TX2            ; and send it

          CALL BSTART         ; generate start bit
          bcf STATUS,C
          rlf ECHAN,W
          iorlw %10100001     ; set slave address and write mode

          MOVWF TXBUF         ; into transmit buffer
          CALL TX2            ; and transmit it
                              ;
RBYTE:    CALL RX             ; read 1 byte from device
          DECFSZ BCOUNT,F     ; are both bytes read?
          GOTO LOWACK         ; no, send low ack and do another
          BSF EEPROM,DO       ; yes, send high ack bit
          CALL BITOUT         ; to stop transmission
          CALL BSTOP2         ; and send a stop bit
          movf DATAI,W
          movwf MEMLO         ;data low byte
          return

LOWACK:   movf DATAI,W
          movwf MEMHI         ; data high byte
          BCF EEPROM,DO       ; send low ack bit
          CALL BITOUT         ; to continue transmission
          GOTO RBYTE          ; and read another byte

;**************

JOEDOWNLOAD: call CLRLINE2     ; clear LCD line 2
         clrf LOOP
         call LCD1
         bsf RSLINE,4
SHOWMSGJ movf LOOP,W
         call MESSAGJ      ; sending to PC message
         call LCDOUT
         incf LOOP,F
         btfss LOOP,4
         goto SHOWMSGJ
         clrf ECHAN
         call JOESENDPC    ; send chip 1 to PC
         movlw 1
         movwf ECHAN
         call SENDNEXT     ; send chip 2 to PC

         movlw 25          ; reset clk counter
         movwf CLKCNT
         return 

       ;*************** OUTPUT TO PC SERIAL PORT FOR DOWNLOAD

;  Modified from Joe Farr's file SAMPLE5.ASM
;  Orig Date: 10-Feb-2003, mod date 01MAR03
;---------------------------------------------------------------------
; Description:
; Sends 100 blocks of 258 bytes (256 data + 2 trailer) to the
; serial port.
; On receipt of a 'G' command from the PC, the PIC waits for 'B'
; command and then sends a 258 byte block. The PIC again waits for a 'B'
; command before sending the next block.
; The block being sent is reflected on the PORTB LEDS.
; Each block contains ASCII codes (0 to 255).
;
; The PIC waits for a character before sending back the ASCII block
;
;---------------------------------------------------------------------

JOESETBAUD
        BANK1                   ; Configure the baud rate generator
        movlw 129               ; BRG for 9600baud from 20MHz, brgh=1
	movwf   SPBRG           ; In bank 1
        movlw   b'00100100'     ; BRGH = 1(High speed, bit 2) & ASYNC transmission (bit 5)
        movwf   TXSTA           ; In bank 1
        bcf 	STATUS,RP0  	; back to RAM page 0
        movlw   b'10010000'     ; ASYNC reception
        movwf   RCSTA           ; In bank 0
        call    FlushRXBuffer   ; Flush the RX buffer in bank 0
        return

JOESENDPC
         clrf RADDRH       ; reset start address for reading EEPROM chip
         clrf RADDRL

; 'G' has been received - Confirm ready state back to PC
        movlw   'R'             ; Signal 'R'eady
        call    TxByte

        goto WAITB

WaitG 				; Wait for any character to be received
        call 	FlushRXBuffer   ; Make sure that the RX buffer is empty
        call    RecLoop         ; Wait and read from serial - character returned in W
        sublw   'G'             ; Is this a 'G'
        btfss   STATUS,Z
        goto    WaitG           ; Not a 'G'

; 'G' has been received - Confirm ready state back to PC
        movlw   'R'             ; Signal 'R'eady
        call    TxByte

; Start sending the blocks
; First, wait for the PC to send us a 'B' command (Send block)

WaitB

	call 	FlushRXBuffer   ; Make sure that the RX buffer is empty
        call    RecLoop         ; Wait and read from serial - character returned in W
        movwf   PORTB
        sublw   'B'             ; Is this a 'B'

        btfsc   STATUS,Z
        goto    SendNext        ; Yes a 'B'
        btfsc ABORT,0           ; is abort tranfser flag set?
        goto    ENDTF           ; yes, so abort transfer
        goto    WaitB           ; Not a 'B'

; 'B' received, send a block

SendNext
         call READ         ; read from EEPROM chip
         movf MEMLO,W      ; get LSB value
         call TXBYTE       ; send it to PC
         movf MEMHI,W      ; get MSB value
         call TXBYTE       ; send it to PC
       
         movlw 2
         addwf RADDRL,F    ; inc read address by 2
         btfss STATUS,C
         goto SendNext

; Data portion of the block has been sent, now send the Block terminator
        movlw   0x0D            ; CR
        call    TxByte
        movlw   0x0A            ; LF
        call    TxByte

        incf RADDRH,F
        btfss RADDRH,7    ; is bit 7 of MSB high? (32768)
        goto    WaitB

ENDTF:  clrf RADDRH       ; reset start address for reading EEPROM chip
        clrf RADDRL
        return 

; Receive a character from RS232
; (This routine does not return until a character has been received)
; The received character is in the W register

RecLoop:
        clrf TMR1L            ; reset timer 1
        clrf TMR1H
        bcf PIR1,0            ; clear timer 1 overflow

RecLoop2:
        btfss PIR1,0          ; has timer 1 overflowed?
        goto RECLOOP3         ; no
        movlw 0
        bsf ABORT,0           ; yes, set flag
        return

RECLOOP3: nop
        btfss   PIR1,RCIF       ; Check for any RX'd data
        goto    RecLoop2        ; Nothing RX'd
        movf    RCREG,W         ; Store the RX'd data in 'W'
        return

; Receive a character from RS232 modified for GPS
; (This routine does not return until a character has been received)
; The received character is in the W register

xRecLoop: nop
        incfsz TIMEOUT,F
        goto xRec2
        incfsz TIMEOUT2,F
        goto xRec2
        incfsz TIMEOUT3,F
        goto xRec2
        bsf ABORT,0
        return

xRec2:   btfss   PIR1,RCIF       ; Check for any RX'd data
        goto xRecLoop
        clrf TIMEOUT
        clrf TIMEOUT2
        movlw 230
        movwf TIMEOUT3
        movf    RCREG,W         ; Store the RX'd data in 'W'
        return


; Send byte in W to the USART

TxByte
        nop
        btfss   PIR1,TXIF       ; TX Buffer empty yet ?
        goto    TxByte          ; No - Keep waiting
        movwf   TXREG           ; Now empty - send this character
        return

; Flush the contents of the RX Buffer

FlushRXBuffer
	movf    RCREG,W        	; Flush the RX buffer in bank 0
        movf    RCREG,W
	movf    RCREG,W
        return

;******** READ DATA FROM EEPROM ROUTINE modified for PIC16F87x devices ****
;         according to data sheet DS30292A page 43

                        ;This routine is entered with W holding
                        ;the eeprom byte address to be read.
PRMGET: bsf STATUS,RP1  ;set for Page 2
        bcf STATUS,RP0
        movwf EEADR     ;copy W into EEADR to set eeprom address
        bsf STATUS,RP0  ;set for Page 3
        bcf EECON1,EEPGD ;point to data memory
        bsf EECON1,RD   ;enable read flag
        bcf STATUS,RP0  ;set for Page 2 
        movf EEDATA,W   ;read eeprom data now in EEDATA into W
        bcf STATUS,RP1  ;set for Page 0
        return

; ***********

COPY_REGA_REGB:
        movf REGA0,W    
        movwf REGB0
        movf REGA1,W
        movwf REGB1
        movf REGA2,W
        movwf REGB2
        movf REGA3,W
        movwf REGB3
        return

; *********** PART OF PETER HEMSLEY'S 32-BIT MATHS ROUTINES *******

;*** SIGNED BINARY TO DECIMAL ***
;REGA -> DIGITS 1 (MSD) TO 10 (LSD) & DSIGN
;DSIGN = 0 if REGA is positive, FF if negative
;Return carry set if overflow
;Uses FSR register

bin2dec:
        call    clrdig          ;Clear all digits
        clrf    MTEMP           ;Reset sign flag
	call	chksgna		;Make REGA positive
	skpnc
        call    negatea         ;Negative

	movlw	D'32'		;Loop counter
	movwf	MCOUNT

b2dloop	rlf	REGA0,f		;Shift msb into carry
	rlf	REGA1,f
	rlf	REGA2,f
	rlf	REGA3,f

	movlw	DIGIT10
	movwf	FSR		;Pointer to digits
	movlw	D'10'		;10 digits to do
	movwf	DCOUNT

adjlp	rlf	INDF,f		;Shift digit and carry 1 bit left
        movlw   -D'10'
	addwf	INDF,w		;Check and adjust for decimal overflow
	skpnc
	movwf	INDF

	decf	FSR,f		;Next digit
	decfsz	DCOUNT,f
	goto	adjlp

	decfsz	MCOUNT,f	;Next bit
	goto	b2dloop

	btfsc	MTEMP,0		;Check sign
	comf	DSIGN,f		;Negative
	clrc

BLANKIT: movlw 48
        iorwf DIGIT1,F
        iorwf DIGIT2,F
        iorwf DIGIT3,F
        iorwf DIGIT4,F
        iorwf DIGIT5,F
        iorwf DIGIT6,F
        iorwf DIGIT7,F
        iorwf DIGIT8,F
        iorwf DIGIT9,F
        iorwf DIGIT10,F

        movlw 10          ; blank leading zeros
        movwf LOOP
        movlw DIGIT1
        movwf FSR
BLANK:  movf LOOP,W
        movf INDF,W
        andlw 15
        btfss STATUS,Z
        return
        bcf INDF,4
        incf FSR,F
        decfsz LOOP,F
        goto BLANK
        movlw 48
        iorwf DIGIT10,F
        return

; **************

;Negate REGA
;Used by chksgna, multiply, divide, mod, bin2dec, dec2bin

negatea	movf	REGA3,w		;Save sign in w
	andlw	0x80

	comf	REGA0,f		;2's complement
	comf	REGA1,f
	comf	REGA2,f
	comf	REGA3,f
	incfsz	REGA0,f
	goto	nega1
	incfsz	REGA1,f
	goto	nega1
	incfsz	REGA2,f
	goto	nega1
	incf	REGA3,f
nega1
	incf	MTEMP,f		;flip sign flag
	addwf	REGA3,w		;Return carry set if -2147483648
	return

;Check sign of REGA and convert negative to positive
;Used by multiply, divide, bin2dec

chksgna	rlf	REGA3,w
	skpc
	return			;Positive


;Set all digits to 0
;Used by bin2dec

clrdig	clrf	DSIGN
	clrf	DIGIT1
	clrf	DIGIT2
	clrf	DIGIT3
	clrf	DIGIT4
	clrf	DIGIT5
	clrf	DIGIT6
	clrf	DIGIT7
	clrf	DIGIT8
	clrf	DIGIT9
	clrf	DIGIT10
	return

;Shift left REGA and REGC
;Used by multiply, divide

slac	rlf	REGA0,f
	rlf	REGA1,f
	rlf	REGA2,f
	rlf	REGA3,f
	rlf	REGC0,f
	rlf	REGC1,f
	rlf	REGC2,f
	rlf	REGC3,f
	return

;Check sign of REGB and negative convert to positive
;Used by multiply, divide, mod

chksgnb	rlf	REGB3,w
	skpc
	return			;Positive

;Negate REGB
;Used by chksgnb, subtract, multiply, divide, mod

negateb	movf	REGB3,w		;Save sign in w
	andlw	0x80

	comf	REGB0,f		;2's complement
	comf	REGB1,f
	comf	REGB2,f
	comf	REGB3,f
	incfsz	REGB0,f
	goto	negb1
	incfsz	REGB1,f
	goto	negb1
	incfsz	REGB2,f
	goto	negb1
	incf	REGB3,f
negb1
	incf	MTEMP,f		;flip sign flag
	addwf	REGB3,w		;Return carry set if -2147483648
	return

movac	movf	REGA0,w
	movwf	REGC0
	movf	REGA1,w
	movwf	REGC1
	movf	REGA2,w
	movwf	REGC2
	movf	REGA3,w
	movwf	REGC3
	return


;Add REGB to REGA (Unsigned)
;Used by add, multiply,

addba	movf	REGB0,w		;Add lo byte
	addwf	REGA0,f

	movf	REGB1,w		;Add mid-lo byte
	skpnc			;No carry_in, so just add
	incfsz	REGB1,w		;Add carry_in to REGB
	addwf	REGA1,f		;Add and propagate carry_out

	movf	REGB2,w		;Add mid-hi byte
	skpnc
	incfsz	REGB2,w
	addwf	REGA2,f

	movf	REGB3,w		;Add hi byte
	skpnc
	incfsz	REGB3,w
	addwf	REGA3,f
	return

;*** SIGNED SUBTRACT ***
;REGA - REGB -> REGA   ;Return carry set if overflow

subtract:
        call    negateb         ;Negate and add
	skpnc
	return			;Overflow

;*** SIGNED ADD ***
;REGA + REGB -> REGA
;Return carry set if overflow

add:    movf    REGA3,w         ;Compare signs
	xorwf	REGB3,w
	movwf	MTEMP

	call	addba		;Add REGB to REGA

	clrc			;Check signs
	movf	REGB3,w		;If signs are same
	xorwf	REGA3,w		;so must result sign
	btfss	MTEMP,7		;else overflow
	addlw	0x80
	return

;*** SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero

divide32: movf  REGB0,w         ;Trap division by zero
	iorwf	REGB1,w
	iorwf	REGB2,w
	iorwf	REGB3,w
	sublw	0
	skpnc
	return

	clrf	MTEMP
	call	chksgna		;Make dividend (REGA) positive
	skpnc
	return			;Overflow
	call	chksgnb		;Make divisor (REGB) positive
	skpnc
	return			;Overflow

	clrf	REGC0		;Clear remainder
	clrf	REGC1
	clrf	REGC2
	clrf	REGC3

	movlw	D'32'		;Loop counter
	movwf	MCOUNT

dvloop	call	slac		;Shift dividend (REGA) msb into remainder (REGC)

	movf	REGB3,w		;Test if remainder (REGC) >= divisor (REGB)
	subwf	REGC3,w
	skpz
	goto	dtstgt
	movf	REGB2,w
	subwf	REGC2,w
	skpz
	goto	dtstgt
	movf	REGB1,w
	subwf	REGC1,w
	skpz
	goto	dtstgt
	movf	REGB0,w
	subwf	REGC0,w
dtstgt	skpc			;Carry set if remainder >= divisor
	goto	dremlt

	movf	REGB0,w		;Subtract divisor (REGB) from remainder (REGC)
	subwf	REGC0,f
	movf	REGB1,w
	skpc
	incfsz	REGB1,w
	subwf	REGC1,f
	movf	REGB2,w
	skpc
	incfsz	REGB2,w
	subwf	REGC2,f
	movf	REGB3,w
	skpc
	incfsz	REGB3,w
	subwf	REGC3,f
	clrc
	bsf	REGA0,0		;Set quotient bit

dremlt	decfsz	MCOUNT,f	;Next
	goto	dvloop

	btfsc	MTEMP,0		;Check result sign
	call	negatea		;Negative
	return


; ************* GET FREQ OF BOTH SENSORS ********

GETFREQ: movf PORTA,W     ; read PORTA
        andlw %00000011  ; are there changes in RA0 or RA1?
        movwf BPORT      ; and make a working copy in BPORT
        xorwf SOFTB,W    ; sets bits in W where changes from last value read
        movwf CHECKIT    ; store answer

        andlw 1
        addwf BOTSENSLSB,F ; add result to counter LSB
        movf STATUS,W
        andlw 1
        addwf BOTSENSNSB,F ; add result to counter NSB
        movf STATUS,W
        andlw 1
        addwf BOTSENSMSB,F ; add result to counter MSB

        rrf CHECKIT,W      ; get second sensor
        andlw 1

        addwf TOPSENSLSB,F ; add result to counter LSB
        movf STATUS,W
        andlw 1
        addwf TOPSENSNSB,F ; add result to counter NSB
        movf STATUS,W
        andlw 1
        addwf TOPSENSMSB,F ; add result to counter MSB

FREQ2:  movf BPORT,W
        movwf SOFTB      ; update soft copy of PORTA

        btfss PIR1,0     ; has timer 1 overflowed?
        goto GETFREQ     ; no

        clrf TMR1L       ; reset timer 1
        clrf TMR1H
        bcf PIR1,0       ; clear timer rollover flag
        bcf PORTE,2      ; turn off buzzer

        movf CLKCNT,W    ; l.e.d. flash control
        xorlw 5
        btfss STATUS,Z
        bcf PORTA,3      ; turn off LED

        decfsz CLKCNT,F  ; dec counter, is it zero?
        goto GETFREQ     ; no
        return

;********** SHOW SENSOR VALUES *******

SHOWSENSVALS:
        call LCD21         ; show bottom sensor
        clrf REGA3
        movf BOTSENSMSB,W
        movwf REGA2
        movf BOTSENSNSB,W
        movwf REGA1
        movf BOTSENSLSB,W
        movwf REGA0
        call BIN2DEC
        movlw 'B'
        call LCDOUT
        call SHOWDIG5
        movlw ' '
        call LCDOUT

        clrf REGA3
        movf TOPSENSMSB,W  ; show top sensor
        movwf REGA2
        movf TOPSENSNSB,W
        movwf REGA1
        movf TOPSENSLSB,W
        movwf REGA0
        call BIN2DEC

        movlw 'T'
        call LCDOUT
        call SHOWDIG5
        movlw ' '
        call LCDOUT
        return

; ***********

SHOWDIG1: movf DIGIT1,W
          call LCDOUT
SHOWDIG2: movf DIGIT2,W
          call LCDOUT
SHOWDIG3: movf DIGIT3,W
          call LCDOUT
SHOWDIG4: movf DIGIT4,W
          call LCDOUT
SHOWDIG5: movf DIGIT5,W
          call LCDOUT
SHOWDIG6: movf DIGIT6,W
          call LCDOUT
SHOWDIG7: movf DIGIT7,W
          call LCDOUT
SHOWDIG8: movf DIGIT8,W
          call LCDOUT
SHOWDIG9: movf DIGIT9,W
          call LCDOUT
SHOWDIG10: movf DIGIT10,W
          call LCDOUT
        return

;****************

GETDIFF: ; subtract top sensor from bottom
;REGA - REGB -> REGA   ;Return carry set if overflow

        clrf REGA3
        movf BOTSENSMSB,W
        movwf REGA2
        movf BOTSENSNSB,W
        movwf REGA1
        movf BOTSENSLSB,W
        movwf REGA0

        clrf REGB3
        movf TOPSENSMSB,W
        movwf REGB2
        movf TOPSENSNSB,W
        movwf REGB1
        movf TOPSENSLSB,W
        movwf REGB0
        call SUBTRACT
        return

; ************

;GETFIELD: ; subtract difference from bottom
;;REGA - REGB -> REGA   ;Return carry set if overflow
;        call COPY_REGA_REGB
;
;        clrf REGA3
;        movf BOTSENSMSB,W
;        movwf REGA2
;        movf BOTSENSNSB,W
;        movwf REGA1
;        movf BOTSENSLSB,W
;        movwf REGA0
;
;        call SUBTRACT
;        return

; ***********

SETREF: movf STOREMSB,W      ; set ref vals & store into EEPROM
        movwf REFERENCEMSB
        movwf PROMVAL
        movlw 0
        call SETPRM

        movf STORENSB,W
        movwf REFERENCENSB
        movwf PROMVAL
        movlw 1
        call SETPRM

        movf STORELSB,W
        movwf REFERENCELSB
        movwf PROMVAL
        movlw 2
        call SETPRM

        clrf LOOP
        call LCD1
SETREF2: movf LOOP,W
        call NULLED           ; NULLED
        call LCDOUT
        incf LOOP,F
        btfss LOOP,3
        goto SETREF2

SETREF3: btfss PORTB,0         ; is S1 still pressed?
        goto SETREF3
        return

; ******* WRITE DATA TO EEPROM ROUTINE modified for PIC16F87x devices ********
          ;according to data sheet DS30292A page 43

                        ;This routine is entered with W holding
                        ;the eeprom byte address at which data
                        ;is to be stored. The data to be stored
                        ;is held in PROMVAL
SETPRM: bsf STATUS,RP1  ;set for Page 2
        bcf STATUS,RP0
        movwf EEADR     ;copy W into EEADR to set eeprom address
        bcf STATUS,RP1  ;set for Page 0
        MOVF PROMVAL,W  ;get data value from STORE1 and hold in W
        bsf STATUS,RP1  ;set for Page 2
        movwf EEDATA    ;copy W into eeprom data byte register
        bsf STATUS,RP0  ;set for page 3
        bcf EECON1,EEPGD ;point to Data memory
        bsf EECON1,WREN ;enable write flag

MANUAL: movlw $55       ;these lines cause the action required by
        movwf EECON2    ;by the eeprom to store the data in EEDATA
        movlw $AA       ;at the address held by EEADR.
        movwf EECON2
        bsf EECON1,WR   ;set the ``perform write'' flag
        bcf STATUS,RP1  ;set for Page 0
        bcf STATUS,RP0

CHKWRT: btfss PIR2,EEIF ;wait until bit 4 of PIR2 is set
        goto CHKWRT
        bcf PIR2,EEIF   ;clear bit 4 of PIR2
        return

; *************** START OF GPS PROG ***********

; MODIFIED FROM GPS320.ASM 26JUL03 - COPYRIGHT JOHN BECKER

STARTGPS: clrf VALIDITY
        clrf TIMEOUT
        clrf TIMEOUT2
        movlw 254
        movwf TIMEOUT3
        call SETBAUD4800     ; set baud rate to 4800 to suit standard (NEA0183) GPS protocol

MAINGPS: call FlushRXBuffer      ; Make sure that the RX buffer is empty
        clrf STARTCOUNT
        clrf ABORT
        call GETSENTENCE
        btfss ABORT,0
        goto MAING2
        call TIMEOUTMSG
        goto MAING3
MAING2: call DECODEGPRMC
MAING3: call JOESETBAUD      ; reset baud rate to 9600 to suit PC prog
        call TEMPERATURE
        return

;*****************

SUMIT:  bcf RCSTA,CREN    ; turn off reception
        clrf CHECKSUM
        movlw MEM1
        addlw 1
        movwf FSR

CHECKIT: BLOCK1           ; do checksum
        movf INDF,W
        BLOCK0
        xorlw '*'
        btfsc STATUS,Z
        goto CHECK2
	movlw '*'    	; new line 05Aug04, as per Readout Sept '04
        xorwf CHECKSUM,F
        incf FSR,F
        movf FSR,W
        xorlw $6F
        btfss STATUS,Z
        goto CHECKIT
        goto EOFPROBLEM

CHECK2: incf FSR,F
        BLOCK1
        movf INDF,W       ; get first digit of checksum
        BLOCK0
        movwf PROMVAL     ; and convert to decimal, storing full conversion in PROMVAL
        movlw 48          
        subwf PROMVAL,F
        movf PROMVAL,W    ; is val >9?
        addlw 246     	; amended from 247 05Aug04, as per Readout Sept '04
        btfss STATUS,C
        goto CHECKV1      ; no
        movlw 7           ; yes (it's between A and F)
        subwf PROMVAL,F   ; subtract 7 

CHECKV1: incf FSR,F
        BLOCK1
        movf INDF,W       ; get 2nd digit of checksum
        BLOCK0
        movwf STORE
        movlw 48
        subwf STORE,F
        movf STORE,W      ; is val >9?
        addlw 246     	; amended from 247 05Aug04, as per Readout Sept '04
        btfss STATUS,C
        goto CHECKV2      ; no
        movlw 7           ; yes (it's between A and F)
        subwf STORE,F     ; subtract 7 

CHECKV2: swapf PROMVAL,W
        addwf STORE,W
        movwf PROMVAL

        movf CHECKSUM,W   ; compare actual checksum with expected (in PROMVAL)
        xorwf PROMVAL,W   ; are both vals equal?
        btfss STATUS,Z
        goto CHECKSUMPROBLEM      ; no
        return

SETCGRAM: movlw %01000000 ;set address for CG RAM write (location 0 1st)
        call LCDLIN

        movlw 8
        movwf LOOP
CHAR0:  movlw 0      
        call LCDOUT
        decfsz LOOP,F
        goto CHAR0

;        call LCDLIN
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT
;        movlw 0
;        call LCDOUT

        movlw %00010000
        movwf REGA0
        clrf REGA1

CHAR1:  movf REGA0,W      ; set bargraph symbols
        iorwf REGA1,F
        movlw 8
        movwf LOOP
CHAR2:  movf REGA1,W
        call LCDOUT
        decfsz LOOP,F
        goto CHAR2
        bcf STATUS,C
        rrf REGA0,F
        btfss STATUS,C
        goto CHAR1

        movlw %00011100    ; put degree symbol into CGRAM 6
        call LCDOUT
	movlw %00010100
        call LCDOUT
	movlw %00011100
        call LCDOUT
	movlw 0
        call LCDOUT
	movlw 0
        call LCDOUT
	movlw 0
        call LCDOUT
	movlw 0
        call LCDOUT
	movlw 0
        call LCDOUT
        return

; ***************        

SETBAUD4800:
        bcf STATUS,RP1
        bsf STATUS,RP0
        movlw   d'64'           ; 4800 Baud with 20MHz XTAL (See PIC data sheet for these values)

;        movlw   d'42'           ; 4800 Baud with 3.2768MHz XTAL (See PIC data sheet for these values)
;        movlw   d'47'           ; 4800 Baud with 3.6864MHz XTAL (See PIC data sheet for these values)

;        movlw 23                ; 9600 Baud with 3.6864MHz XTAL (See PIC data sheet for these values)
;        movlw 20                ; 9600 Baud with 3.2768MHz XTAL (See PIC data sheet for these values)
	movwf   SPBRG           ; In bank 1
        movlw   b'00100000'     ; BRGH = 0(low speed - bit 2) & ASYNC transmission (bit 5)
        movwf   TXSTA           ; In bank 1
        bcf 	STATUS,RP0  	; back to RAM page 0
        clrf STORE
        bsf STORE,SPEN
        movf STORE,W
        movwf   RCSTA           ; In bank 0
        call 	FlushRXBuffer   ; Flush the RX buffer in bank 0
        return

; **********

CHECKSUMPROBLEM:
        movlw 1
        movwf ABORT
        return

EOFPROBLEM:
        movlw 1
        movwf ABORT
        return

; ************* GET DATA SENTENCE FROM GPS *********

GETSENTENCE:

WAIT1:  movlw MEM1
        movwf FSR               ; set FSR to address of MEM1
        clrf LETTERCOUNT
        call TABLELETTER
        movwf LETTER
        bsf RCSTA,CREN          ; turn on reception
        call FlushRXBuffer      ; Make sure that the RX buffer is empty

WAIT2:  call RecLoop            ; Wait and read from serial - character returned in W
        btfsc ABORT,0
        return

        BLOCK1
        movwf INDF              ; store received byte to INDF
        BLOCK0
        subwf LETTER,W          ; is this the required letter?
        btfss STATUS,Z
        goto Wait1              ; no, so start afresh

        incf FSR,F              ; yes, get next byte
        incf LETTERCOUNT,F      ; inc lettercount, is it = 6?
        call TABLELETTER
        movwf LETTER
        movf LETTERCOUNT,W
        xorlw 6
        btfss STATUS,Z
        goto WAIT2

GETTEXT: call RecLoop           ; Wait and read from serial - character returned in W
        btfsc ABORT,0
        return

        BLOCK1
        movwf INDF              ; store received byte to INDF
        BLOCK0
        movwf STORE
        incf FSR,F
        movf FSR,W              ; has FSR reached max? (unlikely, but possible event)
        xorlw $6F
        btfsc STATUS,Z
        goto DOCHECKSUM         ; yes

        movf STORE,W
        sublw 13                ; Is this 13 ?
        btfss STATUS,Z
        goto GETTEXT            ; Not 13

DOCHECKSUM: call SUMIT
        movlw MEM1
        addlw 7
        movwf FSR
        movwf GPSLOOP
        return

;************ DECODE GPRMC SENTENCE AND PLACE REQUIRED DATA INTO LCD ****

DECODEGPRMC:
        movlw MEM1
        addlw 14
        movwf FSR

        BLOCK1                  ; get Validity check result
        movf INDF,W
        BLOCK0
        movwf VALIDITY
        xorlw 'A'               ; is validity = A ok?
        btfsc STATUS,Z
        goto DECODE2            ; yes

        call TIMEOUTMSG
        call LCD16
        movlw 'B'
        call LCDOUT
        movlw 'A'
        call LCDOUT
        movlw 'D'
        call LCDOUT
        return

DECODE2: incf FSR,F              ; inc to bypass comma
        call LCD16              ; show latitude
        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT
        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT
        movlw 6   ;5                 ; show degrees symbol
        call LCDOUT
        incf FSR,F

        BLOCK1     
        movf INDF,W             ; 1st digit of minutes
        BLOCK0
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 2nd digit of minutes
        BLOCK0
        movwf DIGIT7
        call LCDOUT

        incf FSR,F  
        BLOCK1
        movf INDF,W             ; decimal point
        BLOCK0
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 3rd digit of minutes
        BLOCK0
        movwf DIGIT8
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 4th digit of minutes
        BLOCK0
        movwf DIGIT9
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 5th digit of minutes
        BLOCK0
        movwf DIGIT10
        call LCDOUT

        movf DIGIT10,W
        andlw 15
        movwf LATLSB
        swapf DIGIT9,W
        andlw %11110000
        iorwf LATLSB,F

        movf DIGIT8,W
        andlw 15
        movwf LATMSB
        swapf DIGIT7,W
        andlw %11110000
        iorwf LATMSB,F

        incf FSR,F            ; inc to bypass comma
        BLOCK1
        movf INDF,W           ; is it a comma?
        BLOCK0
        sublw 44              ; check for comma
        btfss STATUS,Z        ; is it zero (equal to comma)?
        incf FSR,F            ; no, so inc again (it might be 4 decimal places)

        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT           ; show N/S
        incf FSR,F            ; inc to bypass comma

        movlw ' '
        call LCDOUT
        movlw ' '
        call LCDOUT
        movlw ' '
        call LCDOUT
        movlw ' '
        call LCDOUT

        movf VALIDITY,W       ; show validity (A=OK, V=not valid)
        call LCDOUT

        call LCD216           ; show longitude
        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT
        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT
        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT
        movlw 6   ;5                 ; degrees symbol
        call LCDOUT
        incf FSR,F

        BLOCK1     
        movf INDF,W             ; 1st digit of minutes
        BLOCK0
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 2nd digit of minutes
        BLOCK0
        movwf DIGIT7
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; decimal point
        BLOCK0
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 3rd digit of minutes
        BLOCK0
        movwf DIGIT8
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 4th digit of minutes
        BLOCK0
        movwf DIGIT9
        call LCDOUT

        incf FSR,F
        BLOCK1
        movf INDF,W             ; 5th digit of minutes
        BLOCK0
        movwf DIGIT10
        call LCDOUT

        movf DIGIT10,W
        andlw 15
        movwf LONGLSB
        swapf DIGIT9,W
        andlw %11110000
        iorwf LONGLSB,F

        incf FSR,F            ; inc to bypass comma
        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        call LCDOUT           ; show W/E
        return

; ***********

TIMEOUTMSG: clrf LOOP
        call LCD16
        bsf RSLINE,4
TIMEMSG: movf LOOP,W
        call MESSAG10
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto TIMEMSG
        movlw 'L'            ; GPS signal lost
        movwf VALIDITY
        movlw 1
        movwf LATMSB
        movwf LATLSB
        movwf LONGMSB
        movwf LONGLSB

        movlw MEM1
        addlw 14
        movwf FSR
        clrf LOOP
CLRMEM: movlw 'a'        ; clear to 'a' 64 bytes of mem used for GPS lat/long
        BLOCK1
        movwf INDF
        BLOCK0
        incf FSR,F
        incf LOOP,F
        btfss LOOP,6
        goto CLRMEM
        return

; *****************

PAGECHANGE: btfsc DISPLAYCOUNT,2
        goto BACKIT

FORWARDS: call LCD1
        movlw 16
        movwf LOOP
FOR2:   movlw %00011000
        call LCDLIN
        decfsz LOOP,F
        goto FOR2
        return

BACKIT: call LCD1
        movlw 16
        movwf LOOP
BACK2:  movlw %00011100
        call LCDLIN
        decfsz LOOP,F
        goto BACK2
        return

; ***************

STOREGPRMC:          ;  store lat & long to eeprom
        movlw MEM1
        addlw 14
        movwf FSR
        clrf LOOP

STOREGP3: BLOCK1
        movf INDF,W
        BLOCK0
        movwf MEMLO

        incf FSR,F
        BLOCK1
        movf INDF,W
        BLOCK0
        movwf MEMHI

        incf FSR,F
        call SAVESAMPLE

STOREGP4: movlw 2
        addwf LOOP,F
        movf LOOP,W
        xorlw 24
        btfss STATUS,Z
        goto STOREGP3

        call TEMPERATURE
        movf ADRESH,W     ;get ADC MSB val
        movwf MEMHI
        BANK1
        movf ADRESL,W     ;get ADC LSB val
        BANK0
        movwf MEMLO
        call SAVESAMPLE
        return

; *************

SHOWBARGRAPH: movf STORELSB,W       ; restore result to REGA
        movwf REGA0
        movf STORENSB,W
        movwf REGA1
        movf STOREMSB,W
        movwf REGA2
        clrf REGA3

        bcf STATUS,C      ; divide by 2
        rrf REGA2,F
        rrf REGA1,F
        rrf REGA0,F

        movlw 6           ; divide by 6, and then use remainder
        movwf REGB0
        clrf REGB1
        clrf REGB2
        clrf REGB3
        call DIVIDE32     ; REGA / REGB -> REGA remainder in REGC

        call LCD21
        movlw '+'
        btfsc SIGNREF,7
;        btfsc REGA3,7
        movlw '-'
        call LCDOUT

        clrf LOOP

        movf REGA0,W        ; is result > 15?
        andlw %11110000
        iorwf REGA1,W
        iorwf REGA2,W
        btfsc STATUS,Z
        goto BAR2

        movlw 15
        movwf REGA0

BAR2:   movf LOOP,W
        xorwf REGA0,W
        btfsc STATUS,Z
        goto BAR4
        movlw 5             ; 255 amended 30APR04
        call LCDOUT
        incf LOOP,F
        goto BAR2

BAR4:   movf LOOP,W
        xorlw 15
        btfsc STATUS,Z
        goto BAR6

        movf REGC0,W
        call LCDOUT

BAR5:   movf LOOP,W
        xorlw 15
        btfsc STATUS,Z
        goto BAR6
        movlw ' '
        call LCDOUT
        incf LOOP,F
        goto BAR5

BAR6:   return

; ************

STORECOUNT: movf ECHAN,W      ; set recording count into EEPROM
        movwf PROMVAL
        movlw 3
        call SETPRM

        movf WADDRH,W
        movwf PROMVAL
        movlw 4
        call SETPRM

        movf WADDRL,W
        movwf PROMVAL
        movlw 5
        call SETPRM
        return

; **********

WAITINGPC: clrf LOOP
        call LCD1
        bsf RSLINE,4
WAITPC2: movf LOOP,W
        call WAITPC
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto WAITPC2
        call CLRLINE2
        return

; ************

PCENDED: clrf LOOP
        call LCD1
        bsf RSLINE,4
ENDPC2: movf LOOP,W
        call ENDPC
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto ENDPC2

        call LCD21
        bsf RSLINE,4
ENDPC3: movf LOOP,W
        call ENDPC
        call LCDOUT
        incf LOOP,F
        btfss LOOP,5
        goto ENDPC3
        return

; *************

TEMPERATURE:     ; get temp ADC value
        RP1LO
        BANK1
        movlw %10000000     ; set RHS justify, RA/RE as analog inputs
        movwf ADCON1        ; ref to +VE and 0V
        BANK0

        movlw %10000001 ; set AD on, Fosc/32
        iorlw %00100000      ; set for RA5
        movwf ADCON0
        call PAUSIT
        bsf ADCON0,GO       ;start data conversion
        call PAUSIT

GETADC: btfsc ADCON0,GO
        goto GETADC
        movf ADRESH,W     ;get ADC MSB val
        movwf REGA1

ADC2:   BANK1
        movf ADRESL,W     ;get ADC LSB val
        BANK0
        movwf REGA0

        BANK1
        movlw %00000110   ; All A & E as digital
        movwf ADCON1      ; with RA, RE digital, ref to +VE and 0V
        BANK0

        clrf REGA2
        clrf REGA3
        call BIN2DEC
        call LCD21D
        call SHOWDIG7
        return

; *****************

INCADDRESS: clrf MEMFUL
         movlw 2
         addwf WADDRL,F    ;inc write address by 2
         btfss STATUS,C
         return 
         incf WADDRH,F
         btfss WADDRH,7    ; is bit 7 of MSB now set?
         return            ; no

         clrf WADDRH       ; clear MSB
         incf ECHAN,F      ; inc channel count
         movf MEMCNT,W     ; is ECHAN now equal to MEMCNT?
         xorwf ECHAN,W
         btfsc STATUS,Z
         bsf MEMFUL,0
         return

; *****************

CLEARADR: clrf MEMHI
        clrf MEMLO
        clrf WADDRH      ; set write address MSB
        clrf WADDRL      ; set write address LSB
        clrf RADDRH      ; set read address MSB
        clrf RADDRL      ; set read address LSB
        clrf ECHAN
        clrf MEMFUL
        return

; *****************

SHOWMEMFUL: movlw 1
        movwf PROMVAL            ; store set MEMFUL flag
        movlw 6
        call SETPRM

        clrf LOOP
        call LCD1
        bsf RSLINE,4
MEMMSG: movf LOOP,W
        call MESSAG7
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto MEMMSG

        clrf LOOP
        call LCD21
        bsf RSLINE,4
MEMMSGX: movf LOOP,W
        call MESSAG7A
        call LCDOUT
        incf LOOP,F
        btfss LOOP,4
        goto MEMMSGX

MEMMSG2: btfss PORTB,4          ; is PC switch on (high)?
        goto MEMMSG2            ; not yet
        call WAITINGPC          ; yes
        call JOESETBAUD

MEMMSG3:btfss   PIR1,RCIF       ; Check for any RX'd data
        goto MEMMSG3            ; Nothing RX'd
        movf    RCREG,W         ; Store the RX'd data in 'W'
        sublw   'G'             ; Is this a 'G' ?
        btfss   STATUS,Z
        goto MEMMSG3            ; not yet
        call JOEDOWNLOAD        ; Yes, a 'G'
        call PCENDED
        call CLEARADR

        call STORECOUNT  ; store reset count value to eeprom

        clrf PROMVAL     ; store reset MEMFUL flag
        movlw 6
        call SETPRM

MEMMSG4: btfsc PORTB,4         ; wait for switch to be set back to run
        goto MEMMSG4
        return

        END



