; ********************************************************************************************
; Fuses e Includes
; ********************************************************************************************
PROCESSOR 16F877A
INCLUDE <P16F877A.INC>
__CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF
; ********************************************************************************************
; Definicion de registros
; ********************************************************************************************
ANVAL EQU 0x70 ; ANALOG RESULT
CNT0 EQU 0x21 ;COUNTER IN BANK 00
CNT1 EQU 0xA1 ;COUNTER IN BANK 01
d1 EQU 0x71 ; DELAY AUXILIAR
LROOM EQU 0X72 ; ROOM LUMINOSITY
TEMP EQU 0X73 ; ROOM TEMPERATURE
PRESENCE EQU 0X74 ; PRESENCE 0) BED 1)DESK 2)ANY
LBED EQU 0X75 ; BED LUMINOSITY
LDESK EQU 0X76 ; DESK LUMINOSITY
; ********************************************************************************************
; Vectores
; ********************************************************************************************
ORG 0x00 ;Vector de reset
; ********************************************************************************************
; Configuracion de Modulos
; ********************************************************************************************
; PUERTOS
BSF STATUS, 5 ;SELECT BANK 01
;A AND B ARE SET TO INPUT MODE
MOVLW B'11111111'
MOVWF TRISA
MOVLW B'11111111'
MOVWF TRISB
;C AND D ARE SET TO OUTPUT MODE
MOVLW B'00000000'
MOVWF TRISC
MOVLW B'00000000'
MOVWF TRISD
BCF STATUS, 5 ;SELECT BANK 00
; ********************************************************************************************
; Loop Principal
; ********************************************************************************************
PRESTAR:
CALL BED_RESET
CALL DESK_RESET
CALL LIGHT_RESET
BCF PORTC,0
BCF PORTC,1
GOTO MAIN
MAIN:
BTFSS PORTB,1 ;SWITCH ON SET?
GOTO PRESTAR ;NO
;YES
BTFSS PORTB,0 ;THERE'S SOMEONE ON THE ROOM?
GOTO PRESTAR ;NO
;YES
CALL TEMP_READ
CALL FAN
CALL L_ROOM
CALL P_BED
CALL P_DESK
CALL LIGHT_SELECT
CALL LIGHT_RESET
BTFSC PRESENCE,2
CALL DIM_LIGHT
CALL ROOM_LIGHT
CALL BED_RESET
BTFSC PRESENCE,0 ; SKIP IS NO ONE IN BED
CALL BED_LIGHT
CALL DESK_RESET
BTFSC PRESENCE,1 ; SKIP IS NO ONE IN DESK
CALL DESK_LIGHT
CALL DELAY_ADC
GOTO MAIN
; ********************************************************************************************
; Sub rutinas
; ********************************************************************************************
DESK_LIGHT:
BTFSS PRESENCE,0
RETURN ;PRESENCE,0 =0
CALL L_DESK
MOVLW b'00111111'
SUBWF LDESK,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTD,3
MOVLW b'01111110'
SUBWF LDESK,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTD,2
MOVLW b'10111101'
SUBWF LDESK,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTD,1
BSF PORTD,0
L_DESK:
CALL ADC_LDESK ;SET A6
CALL ADC_READ ;READ ANALOG A1 AND RETURN AS ANVAL
MOVFW ANVAL
MOVWF LDESK ;MOVE ANVAL TO LROOM
RETURN
DESK_RESET:
BCF PORTD,0
BCF PORTD,1
BCF PORTD,2
BCF PORTD,3
RETURN
BED_LIGHT:
BTFSS PRESENCE,0
RETURN ;PRESENCE,0 =0
CALL L_BED
MOVLW b'00111111'
SUBWF LBED,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTD,7
MOVLW b'01111110'
SUBWF LBED,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTD,6
MOVLW b'10111101'
SUBWF LBED,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTD,5
BSF PORTD,4
L_BED:
CALL ADC_LBED ;SET A7
CALL ADC_READ ;READ ANALOG A1 AND RETURN AS ANVAL
MOVFW ANVAL
MOVWF LBED ;MOVE ANVAL TO LROOM
RETURN
BED_RESET:
BCF PORTD,4
BCF PORTD,5
BCF PORTD,6
BCF PORTD,7
RETURN
ROOM_LIGHT:
BTFSC PRESENCE,2
RETURN ;PRESENCE,2 =1
MOVLW b'00101010' ;42 THERE'S NO LIGHT ON THE ROOM
SUBWF LROOM,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTC,7
MOVLW b'01010100' ;84
SUBWF LROOM,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTC,6
MOVLW b'01111110' ;126
SUBWF LROOM,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTC,5
MOVLW b'01010100' ;168
SUBWF LROOM,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTC,4
MOVLW b'11010010' ;210
SUBWF LROOM,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTC,3
MOVLW b'11111010' ;250
SUBWF LROOM,0
BTFSS STATUS,C ;C=0 W>LROOM C=1 W<=LROOM
BSF PORTC,2
RETURN
LIGHT_RESET:
BCF PORTC,7
BCF PORTC,6
BCF PORTC,5
BCF PORTC,4
BCF PORTC,3
BCF PORTC,2
RETURN
DIM_LIGHT:
BCF PORTC,7
BCF PORTC,6
BCF PORTC,5
BCF PORTC,4
BSF PORTC,3
BSF PORTC,2
RETURN
LIGHT_SELECT:
BCF PRESENCE,2
BTFSC PRESENCE,0
BSF PRESENCE,2 ;SOMEONE IN BED
BTFSC PRESENCE,1
BSF PRESENCE,2 ;SOMEONE IN DESK
RETURN
P_DESK:
BCF PRESENCE,1
CALL ADC_PDESK ;SET A5
CALL ADC_READ ;READ ANALOG A1 AND RETURN AS ANVAL
MOVFW ANVAL
MOVLW b'01111111' ;SET VALUE TO 50cm OBJECT REFLECTING EQUIVALENT RESISTANCE
SUBWF ANVAL,0
BTFSS STATUS,C
BSF PRESENCE,1 ;C=0 OBJECT CLOSER THAN 50cm
RETURN
P_BED:
BCF PRESENCE,0
CALL ADC_PBED ;SET A4
CALL ADC_READ ;READ ANALOG A1 AND RETURN AS ANVAL
MOVFW ANVAL
MOVLW b'01111111' ;SET VALUE TO 15cm OBJECT REFLECTING EQUIVALENT RESISTANCE
SUBWF ANVAL,0
BTFSS STATUS,C
BSF PRESENCE,0 ;C=0 OBJECT CLOSER TO 15cm
RETURN
L_ROOM:
CALL ADC_LROOM ;SET A1
CALL ADC_READ ;READ ANALOG A1 AND RETURN AS ANVAL
MOVFW ANVAL
MOVWF LROOM ;MOVE ANVAL TO LROOM
RETURN
; ****************** Temperatura******************
FAN:
BCF PORTC,0
BCF PORTC,1
MOVLW b'00000111' ;SET VALUE TO 25c EQUIVALENT
SUBWF TEMP,0
BTFSC STATUS,C
CALL FAN_1 ;C=1 TEMPERATURE>25c
;C=0 TEMPERATURE<25c
RETURN
FAN_1:
BSF PORTC,0
BCF PORTC,1
MOVLW b'00111111' ;SET VALUE TO 30c EQUIVALENT
SUBWF TEMP,0
BTFSC STATUS,C
CALL FAN_2 ;C=1 TEMPERATURE>30c
;C=0 TEMPERATURE<25
RETURN
FAN_2:
BSF PORTC,0
BSF PORTC,1
RETURN
TEMP_READ:
CALL ADC_TEMP ;SET A0
CALL ADC_READ ;READ ANALOG A0 AND RETURN AS ANVAL
MOVFW ANVAL
MOVWF TEMP
RETURN
;********************** ADC *******************
ADC_TEMP:
BSF STATUS, 5 ;SELECT BANK 01
;RIGHT JUSTIFIED RESULT, +VREF=VDD, -VREF=VSS, AN0-AN7=ANALOG
MOVLW B'10000000'
MOVWF ADCON1
BCF STATUS, 5 ;SELECT BANK 00
;FOSC/64, ADON=1
MOVLW B'10000001'
MOVWF ADCON0
RETURN
ADC_LROOM:
BSF STATUS, 5 ;SELECT BANK 01
;RIGHT JUSTIFIED RESULT, +VREF=VDD, -VREF=VSS, AN0-AN7=ANALOG
MOVLW B'10000000'
MOVWF ADCON1
BCF STATUS, 5 ;SELECT BANK 00
;FOSC/64, ADON=1
MOVLW B'10001001'
MOVWF ADCON0
RETURN
ADC_PBED:
BSF STATUS, 5 ;SELECT BANK 01
;RIGHT JUSTIFIED RESULT, +VREF=VDD, -VREF=VSS, AN0-AN7=ANALOG
MOVLW B'10000000'
MOVWF ADCON1
BCF STATUS, 5 ;SELECT BANK 00
;FOSC/64, ADON=1
MOVLW B'10100001'
MOVWF ADCON0
RETURN
ADC_PDESK:
BSF STATUS, 5 ;SELECT BANK 01
;RIGHT JUSTIFIED RESULT, +VREF=VDD, -VREF=VSS, AN0-AN7=ANALOG
MOVLW B'10000000'
MOVWF ADCON1
BCF STATUS, 5 ;SELECT BANK 00
;FOSC/64, ADON=1
MOVLW B'10101001'
MOVWF ADCON0
RETURN
ADC_LDESK:
BSF STATUS, 5 ;SELECT BANK 01
;RIGHT JUSTIFIED RESULT, +VREF=VDD, -VREF=VSS, AN0-AN7=ANALOG
MOVLW B'10000000'
MOVWF ADCON1
BCF STATUS, 5 ;SELECT BANK 00
;FOSC/64, ADON=1
MOVLW B'10110001'
MOVWF ADCON0
RETURN
ADC_LBED:
BSF STATUS, 5 ;SELECT BANK 01
;RIGHT JUSTIFIED RESULT, +VREF=VDD, -VREF=VSS, AN0-AN7=ANALOG
MOVLW B'10000000'
MOVWF ADCON1
BCF STATUS, 5 ;SELECT BANK 00
;FOSC/64, ADON=1
MOVLW B'10111001'
MOVWF ADCON0
RETURN
ADC_READ:
BCF STATUS, 5 ;SELECT BANK 00
CALL DELAY_ADC
BSF ADCON0, 2 ;START CONVERTION PROCESS (WE SET THE GO BIT)
WAIT:
BTFSC ADCON0, 2
GOTO WAIT ;WAIT FOR CONVERTION TO FINISH (WAIT FOR GO BIT TO CLEAR)
;;;WE SAVE RESULT INTO AN 8BIT REGISTER TO USE FOR OUTPUT (WE DROP THE TWO LESS SIGNIFICANT BITS);;;
;FIRST WE PROCESS THE HIGH BYTE OF RESULT
MOVLW 0x06
MOVWF CNT0
AGAIN_0:
BCF STATUS, C ;WE WANT SHIFT (NOT ROTATE), SO WE CLEAR CARRY
RLF ADRESH, 1 ;SHIFT LEFT 6 BITS A/D RESULT HIGH BYTE
DECFSZ CNT0
GOTO AGAIN_0
MOVF ADRESH, W ;MOVE ADRESH TO W
MOVWF ANVAL ;MOVE W TO ANVAL
;NOW WE PROCESS THE LOW BYTE OF RESULT
BSF STATUS, 5 ;SELECT BANK 01
MOVLW 0x02
MOVWF CNT1
AGAIN_1:
BCF STATUS, C ;WE WANT SHIFT (NOT ROTATE), SO WE CLEAR CARRY
RRF ADRESL, 1 ;SHIFT RIGHT 2 BITS A/D RESULT LOW BYTE
DECFSZ CNT1
GOTO AGAIN_1
MOVF ADRESL, W ;MOVE ADRESL TO W
BCF STATUS, 5 ;SELECT BANK 00
ADDWF ANVAL, 1 ;ADD W TO ANVAL
RETURN
DELAY_ADC:
movlw 0XFF ; Cargamos valor XX que controla duración (1)
movwf d1 ; Iniciamos Contador (1)
Repeticion
Decfsz d1 ; Decrementa contador y si es cero sale (1 si no sale, 2 si sale)
goto Repeticion ; No es 0, repetimos (2)
return
END