'************************************************* ******************************
;* Name : PIC16F887.BAS
;* Author : CSANTEX
;* Date :
;* Version : DEFAULT
;* Notes :
'************************************************* ******************************
;Max Word count available is 8192. Max EEPROM available is 256 bytes
;************************************************* ******************************
;This code displays a number that is incremented for clockwise rotation or decremented
;for counter-clockwise rotation on a 20x4 LCD. The display has two digits to the
;left of the decimal and three digits to the right of the decimal. Each time the
;shaft is pushed in, a digit is selected starting from left to right. This code
;could be used to display voltages that are preset by a user on a diy power supply
;or for Ampere presets or any of the like.
;The code is a bit long but it works well.
;Does not use interrupts.
;Written for use on PIC16F887 but can be modified to fit any PIC microcontroller.
;COULD USE SOME OPTIMIZATION!
;************************************************* ******************************
;************************************************* ******************************
' include "PIC16F887.PBPINC" ; processor specific variable definitions
INCLUDE "Modedefs.Bas"


@ ERRORLEVEL -306 ; Suppress messages related to Page Boundries.
;************************************************* ******************************
#CONFIG
__CONFIG _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_ON & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO
__CONFIG _CONFIG2, _WRT_OFF & _BOR40V
#ENDCONFIG

DEFINE OSC 8

DEFINE LCD_DREG PORTD ' PORTA is LCD data port
DEFINE LCD_DBIT 4 ' PORTA.4 is the data LSB ( 4 BIT MODE )
DEFINE LCD_RSREG PORTB ' RS is connected to PORTA.1
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTB ' E is connected to PORTA.3
DEFINE LCD_EBIT 1
DEFINE LCD_BITS 4 ' 4 lines of data are used (4 BITS)
DEFINE LCD_LINES 4 ' It is a 4-line display
DEFINE LCD_COMMANDUS 1500 ' Use 1500uS command delay
DEFINE LCD_DATAUS 44 ' Use 44uS data delay
;************************************************* ******************************
OSCCON = 10000 ; Set PIC16F88 to 4MHz = 0100000, or 8MHz = 0110000
TRISA = 11111 ; Port A set to inputs
TRISB = 01100 ; Port B set to OUTPUTS
TRISC = 11111 ; Port C set to inputs
TRISD = 000000 ; Port D set to Ouputs
PORTD.5 = 0 ; Set output low
ANSEL = 0000 ; Set all analog pins to digital
ANSELH = 0000
' LED var PortD.7 ; LED for flashing
A_IN VAR PORTC.6
B_IN VAR PORTC.5
SW_IN VAR PORTC.4
;************************************************* ******************************
ONES VAR BYTE ; VARIABLE
TENS VAR BYTE ; VARIABLE
HUND VAR BYTE ; VARIABLE
THOU VAR BYTE ; VARIABLE
TNTH VAR BYTE ; VARIABLE
SUBTTL VAR WORD ; VARIABLE
TOTAL VAR WORD ; TOTAL VALUE
PLACE VAR BYTE ; VARIABLE


MYFLAGS VAR BYTE
;************************************************* ******************************

INIT:
PAUSE 1000
CLEAR
PLACE = 6

' LCDOUT $FE, $C0, DEC PLACE ;FOR DEBUG ONLY
' LCDOUT $FE, $94, DEC5 (TNTH*10000)+(THOU*1000)+(HUND*100)+(TENS*10)+ONES ;FOR DEBUG ONLY

LCDOUT $FE, $D4, DEC1 TNTH, DEC1 THOU, ".", DEC1 HUND, DEC1 TENS, DEC1 ONES

;************************************************* ******************************
MAIN:
IF A_IN < B_IN THEN
IF PLACE = 6 AND TOTAL < 10000 THEN
IF MYFLAGS.0 = 0 THEN
ONES = ONES + 1
IF ONES > 9 THEN
ONES = 0
TENS = TENS + 1
ENDIF
IF TENS > 9 THEN
TENS = 0
HUND = HUND + 1
ENDIF
IF HUND > 9 THEN
HUND = 0
THOU = THOU + 1
ENDIF
IF THOU > 9 THEN
THOU = 0
TNTH = TNTH + 1
ENDIF
IF TNTH > 1 THEN THOU = 0
GOSUB SHOW_TOTAL
ENDIF
ENDIF
IF MYFLAGS.0 = 1 THEN
IF TNTH = 0 THEN
IF PLACE = 5 THEN
ONES = ONES + 1
IF ONES > 9 THEN ONES = 0
GOSUB SHOW_ONES
ENDIF
IF PLACE = 4 THEN
TENS = TENS + 1
IF TENS > 9 THEN TENS = 0
GOSUB SHOW_TENS
ENDIF
IF PLACE = 3 THEN
HUND = HUND + 1
IF HUND > 9 THEN HUND = 0
GOSUB SHOW_HUND
ENDIF
IF PLACE = 1 THEN
THOU = THOU + 1
IF THOU > 9 THEN THOU = 0
GOSUB SHOW_THOU
ENDIF
ENDIF
IF SUBTTL = 0 THEN
IF PLACE = 0 THEN
TNTH = TNTH + 1
IF TNTH > 1 THEN TNTH = 0
GOSUB SHOW_TNTH
GOTO PUSHBUTTON
ENDIF
ENDIF
ENDIF
GOSUB SUM_TOTALS
IF TOTAL = 10000 THEN
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $80, "MAXIMUM LIMIT"
PAUSE 1000
LCDOUT $FE, $80, " "
ENDIF
ENDIF

PUSHBUTTON:
IF SW_IN = 0 THEN
PLACE = PLACE + 1
IF PLACE = 2 THEN PLACE = 3
IF PLACE > 6 THEN PLACE = 0
' LCDOUT $FE, $C0, DEC PLACE ;FOR DEBUG ONLY
LCDOUT $FE, $D4+PLACE

IF PLACE = 6 THEN
LCDOUT $FE, $0C ;BLINK OFF
MYFLAGS.0 = 0
ELSE
LCDOUT $FE, $0F
LCDOUT $FE, $D4+PLACE
MYFLAGS.0 = 1
ENDIF

GOSUB DEBOUNCE ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
ENDIF
GOSUB SUM_TOTALS
IF PLACE != 6 THEN
LCDOUT $FE, $0F
LCDOUT $FE, $D4+PLACE
' MYFLAGS.0 = 1
ENDIF


DECREMENT:
IF B_IN < A_IN THEN
IF PLACE = 6 AND TOTAL > 0 THEN
IF MYFLAGS.0 = 0 THEN
ONES = ONES - 1
IF ONES > 9 THEN
ONES = 9
TENS = TENS - 1
ENDIF
IF TENS > 9 THEN
TENS = 9
HUND = HUND - 1
ENDIF
IF HUND > 9 THEN
HUND = 9
THOU = THOU - 1
ENDIF
IF THOU > 9 THEN
THOU = 9
TNTH = TNTH - 1
ENDIF
IF TNTH > 1 THEN THOU = 0
GOSUB SHOW_TOTAL
ENDIF
ENDIF
IF MYFLAGS.0 = 1 THEN
IF TNTH = 0 THEN
IF PLACE = 5 THEN
ONES = ONES - 1
IF ONES > 9 THEN ONES = 9
GOSUB SHOW_ONES
GOTO MAIN
ENDIF
IF PLACE = 4 THEN
TENS = TENS - 1
IF TENS > 9 THEN TENS = 9
GOSUB SHOW_TENS
GOTO MAIN
ENDIF
IF PLACE = 3 THEN
HUND = HUND - 1
IF HUND > 9 THEN HUND = 9
GOSUB SHOW_HUND
GOTO MAIN
ENDIF
IF PLACE = 1 THEN
THOU = THOU - 1
IF THOU > 9 THEN THOU = 9
GOSUB SHOW_THOU
GOTO MAIN
ENDIF
ENDIF
IF SUBTTL = 0 THEN
IF PLACE = 0 THEN
TNTH = TNTH - 1
IF TNTH > 1 THEN TNTH = 1
GOSUB SHOW_TNTH
GOTO MAIN
ENDIF
ENDIF
ENDIF
GOSUB SUM_TOTALS
IF TOTAL = 0 THEN
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $80, "MINIMUM LIMIT"
PAUSE 1000
LCDOUT $FE, $80, " "
ENDIF
ENDIF
GOTO MAIN

SHOW_TOTAL:
' LCDOUT $FE, $94, DEC5 (TNTH*10000)+(THOU*1000)+(HUND*100)+(TENS*10)+ONES ;FOR DEBUG ONLY
LCDOUT $FE, $D4, DEC1 TNTH, DEC1 THOU, ".", DEC1 HUND, DEC1 TENS, DEC1 ONES


DEBOUNCE:
WHILE A_IN=0 OR B_IN=0 OR SW_IN=0 ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
WEND
RETURN


;************************************************* ******************************
SHOW_TNTH:
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $D4, DEC1 TNTH
LCDOUT $FE, $D4
LCDOUT $FE, $0F ;BLINK ON
GOSUB DEBOUNCE ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
RETURN
SHOW_THOU:
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $D5, DEC1 THOU
LCDOUT $FE, $D5
LCDOUT $FE, $0F
GOSUB DEBOUNCE ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
RETURN
SHOW_HUND:
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $D7, DEC1 HUND
LCDOUT $FE, $D7
LCDOUT $FE, $0F
GOSUB DEBOUNCE ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
RETURN
SHOW_TENS:
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $D8, DEC1 TENS
LCDOUT $FE, $D8
LCDOUT $FE, $0F
GOSUB DEBOUNCE ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
RETURN
SHOW_ONES:
LCDOUT $FE, $0C ;BLINK OFF
LCDOUT $FE, $D9, DEC1 ONES
LCDOUT $FE, $D9
LCDOUT $FE, $0F
GOSUB DEBOUNCE ;DO NOTHING WHILE WE WAIT TO RELEASE THE BUTTON.
RETURN
SUM_TOTALS:
TOTAL = (TNTH*10000)+(THOU*1000)+(HUND*100)+(TENS*10)+ONES
SUBTTL = (THOU*1000)+(HUND*100)+(TENS*10)+ONES
RETURN
;************************************************* ******************************

;************************************************* ******************************
END