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

; Controllo Relay - Versione telecomando *
;**********************************************************************
; *
; Filename: P16F684_Telec_ac.asm *
; Date: *
; File Version: 1.00 *
; *
; Author: InTeAS WebMaster *
; Company: https://www.inteas.it *
; *
; *
;**********************************************************************
; *
; Files Required: P16F684.INC *
; *
;**********************************************************************
;
list p=16f684 ; list directive to define processor
#include <P16F684.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF
;
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;
;***** EEPROM MAP
;
; 00-5D Sequenza contatori durata tasto di comando
; 5E-FE Non usati
; FF Stato del Relay (OFF=0, ON=1)
;
;
;***** LOCAL VARIABLE DEFINITIONS
;
; 0x20 - 0x7F: Bank 0
;
VALFL EQU 0x20
PCOUNT1 EQU 0x21
;
; 0x22 - 0x7F: Sequenza Comando
;
; 0xA0 - 0xBF: Bank 1
;
COUNT1 EQU 0xBF
COUNT2 EQU 0xBE
ITERAZ EQU 0xBD
BYTVAL EQU 0xBC
CONFR EQU 0xBB
;
;**********************************************************************
; PROGRAM AREA
;**********************************************************************
;
ORG 0x000 ; processor reset vector
goto INIT ; go to beginning of program
;
ORG 0x004 ; interrupt vector location
goto INTERRUPT
;
INIT:
;
; OPTION Register, on reset all bits = 1
;
; bit 7 (NOT_RAPU) Weak Pull-Ups (Enabled=0)
; bit 6 (INTEDG) Interrupt Edge Select on RA2(Falling Edge=0)
; bit 5 (T0CS) Timer0 Source Selection:
; 1= T0CKI Transition (default)
; 0= Internal Instruction (CLKOUT)
; bit 4 (T0SE) Timer0 Source Edge Selection: 1 = H-to-L (default), 0= L-to-H
; bit 3 (PSA) Prescaler Assignment: 1= to WDT (default), 0= to Timer0
; bits 2:0 (PS2,PS1,PS0) Prescaler Rate Selection: 1:128 default
movlw b'00011111' ; T0CS= 0 : Internal Timer0
bsf STATUS,RP0 ; Bank 1
movwf OPTION_REG
;
; INTCON: INTERRUPT CONTROL REGISTER
;
; bit 7 (GIE) Global Interrupt Enable bit (Enabled=1)
; bit 6 (PEIE) Peripheral Interrupt Enable bit (Disabled=0)
; bit 5 (T0IE) Timer0 Overflow Interrupt Enable bit (Disabled=0)
; bit 4 (INTE) RA2/INT External Interrupt Enable bit (Disabled=0)
; bit 3 (RAIE) PORTA Change Interrupt Enable bit (Disabled=0)
; bit 2 (T0IF) Timer0 Overflow Interrupt Flag bit (not used)
; bit 1 (INTF) RA2/INT External Interrupt Flag bit (used:Active on 1)
; bit 0 (RAIF) PORTA Change Interrupt Flag bit (not used)
movlw b'10000000'
movwf INTCON
;
; I/O Summary
;
; PORTA,5 INPUT (pin 2) : NC
; PORTA,4 INPUT (pin 3) : NC
; PORTA,3 INPUT (pin 4) : NC
; PORTA,2 INPUT (pin 11) : Infra Red Interrupt (attivo su 0)
; PORTA,1 INPUT (pin 12) : NC
; PORTA,0 INPUT (pin 13) : Programming Input (attivo su 0)
;
; PORTC,5 OUTPUT (pin 5) : Power Supply Control (attivo su 0)
; PORTC,4 INPUT (pin 6) : NC
; PORTC,3 INPUT (pin 7) : AC Signal
; PORTC,2 OUTPUT (pin 8) : Program Led (attivo su 1)
; PORTC,1 INPUT (pin 9) : NC
; PORTC,0 INPUT (pin 10) : NC
;
; *******************************
; Set of the PORTA I/O (bit 5:0)
; *******************************
;
bcf STATUS,RP0 ; Bank 0
movlw h'07' ; Set RA<2:0> and RC<4,1:0> to digital I/O
movwf CMCON0
bsf STATUS,RP0 ; Bank 1
clrf ANSEL ; Digital I/O
; 1=input 0=output
movlw b'11111111'
movwf TRISA ; write in TRISA register
;
; *******************************
; Set of the PORTC I/O (bit 5:0)
; *******************************
;
; 1=input 0=output
movlw b'11011011'
movwf TRISC ; write in TRISC register
bcf STATUS,RP0 ; Bank 0
bsf PORTC,5 ; inattiva Power Supply
bcf PORTC,2 ; spegne Probe Led
;
btfss PORTA,0 ; salta se non c'è Programming Input
goto PROGRAM ; va alla Programming routine
;
; Va in stand-by
;
STAND_BY:
bsf INTCON,4 ; abilita l'interrupt su RA2
sleep

;
;***********************************************
; INTERRUPT: routine di interrupt
;***********************************************
;
INTERRUPT:
bcf STATUS,RP0 ; Bank 0
bcf INTCON,1 ; spegne il flag di interrupt
bcf INTCON,4 ; disabilita l'interrupt
btfss PORTA,0 ; salta se non c'è Programming Input
goto PROGRAM ; va alla Programming routine
;
; Acquisizione comando
;
call ACQUISIZIONE
;
; Verifica di comando completo (FSR=h'80')
;
btfss FSR,7 ; salta se FSR=80
goto STAND_BY; comando incompleto
;
; Analisi comando
;
movlw h'22'
movwf FSR ; Inizializzazione puntatore sequenza
bsf STATUS,RP0 ; Bank 1
clrf CONFR ; inizializza a zero flag
clrf EEADR ; Inizializzazione puntatore EEPROM
CmdAnLoop:
call EEREAD ; valore corrente in w
subwf INDF,0 ; esegue w = f - w
btfsc STATUS,Z ; salta se f diverso da w (Z=0)
goto EndCmdAn ; f=w (Z=1)
btfsc STATUS,C ; salta se w maggiore di f (C=0)
goto PosDiff ; w minore di f
; Risultato negativo
addlw h'05' ; massima differenza accettabile
btfsc STATUS,C ; salta se C=0 cioè diff. NON accettabile
goto EndCmdAn ; C=1 differenza accettabile
incf CONFR ;
goto EndAnalysis
; Risultato positivo
PosDiff:
sublw h'05'
btfsc STATUS,C ; salta se C=0 cioè diff. accettabile
goto EndCmdAn ; C=1 differenza NON accettabile
incf CONFR ;
goto EndAnalysis
;
EndCmdAn:
incf EEADR,1
incf FSR,1
btfss FSR,7 ; salta se FSR=80
goto CmdAnLoop
;
; Fine Analisi
;
EndAnalysis:
btfsc CONFR,0; salta se CONFR=0 (comando valido)
goto STAND_BY ; comando NON valido
;
; Comando valido
;
movlw h'FF'
movwf EEADR
call EEREAD ; valore attuale relay in w (0=OFF 1=ON)
bcf STATUS,RP0 ; Bank 0
movwf VALFL ; salva valore attuale in VALFL
;
movlw b'00000001'
xorwf VALFL,f ; salva lo stato opposto del relay
call ACTCNT ; attuazione sul relay del nuovo stato
movf VALFL,w
bsf STATUS,RP0 ; Bank 1
call STATUS_SAVE ; memorizza in EEPROM il nuovo stato
bcf STATUS,RP0 ; Bank 0
bsf PORTC,2 ; accende Probe Led
bsf STATUS,RP0 ; Bank 1
call DELAY_MAX
bcf STATUS,RP0 ; Bank 0
bcf PORTC,2 ; spegne Probe Led
bsf STATUS,RP0 ; Bank 1
call DELAY_MAX
goto STAND_BY
;
;***********************************************
; PROGRAM: routine di programmazione comando
;***********************************************
;
PROGRAM:
; Lampeggio d'attesa (16 cicli max,)
bsf STATUS,RP0 ; Bank 1
movlw h'10'
movwf ITERAZ
PrgLoop:
bcf STATUS,RP0 ; Bank 0
bsf PORTC,2 ; accende Probe Led
bsf STATUS,RP0 ; Bank 1
movlw h'FF'
movwf COUNT2
PrgDly2:
movlw h'FF'
movwf COUNT1
PrgDly1:
bcf STATUS,RP0 ; Bank 0
btfss PORTA,2 ; salta se non c'è comando
goto COMMAND_ACQ
bsf STATUS,RP0 ; Bank 1
decfsz COUNT1,1
goto PrgDly1
decfsz COUNT2,1
goto PrgDly2
bcf STATUS,RP0 ; Bank 0
bcf PORTC,2 ; spegne Probe Led
bsf STATUS,RP0 ; Bank 1
PrgDly4:
movlw h'FF'
movwf COUNT1
PrgDly3:
bcf STATUS,RP0 ; Bank 0
btfss PORTA,2 ; salta se non c'è comando
goto COMMAND_ACQ
bsf STATUS,RP0 ; Bank 1
decfsz COUNT1,1
goto PrgDly3
decfsz COUNT2,1
goto PrgDly4
decfsz ITERAZ,1
goto PrgLoop
;
; Tempo scaduto
;
goto STAND_BY
;
; Acquisizione Comando
;
COMMAND_ACQ:
bcf PORTC,2 ; spegne Probe Led
call ACQUISIZIONE
;
; Verifica di comando completo (FSR=h'80')
;
btfss FSR,7 ; salta se FSR=80
goto PROGRAM; comando incompleto
;
; Salvataggio comando in EEPROM
;
bsf STATUS,RP0 ; Bank 1
call INTEE_WR
;
; Memorizzazione stato OFF del relay
;
movlw h'00'
call STATUS_SAVE
bcf STATUS,RP0 ; Bank 0
clrf VALFL
call ACTCNT ; attuazione sul relay dello stato OFF
;
; Segnalazione avvenuta memorizzazione
;

bsf PORTC,2 ; accende Probe Led
bsf STATUS,RP0 ; Bank 1
;
movlw h'10'
call LDELAY
;
bcf STATUS,RP0 ; Bank 0
bcf PORTC,2 ; spegne Probe Led
bsf STATUS,RP0 ; Bank 1
;
movlw h'10'
call LDELAY
;
goto STAND_BY
;
;
;###############################################
;# ROUTINES #
;###############################################
;
;
;***********************************************
; ACQUISIZIONE
;***********************************************
;
ACQUISIZIONE:
movlw h'22'
movwf FSR ; inizializzazione puntatore sequenza
ZeroCount:
clrf INDF ; azzera contatore corrente
ZeroLoop:
call PAUSE
btfsc PORTA,2 ; salta se IR = 0
goto EndZeroCount
incf INDF ; incrementa contatore corrente
btfss STATUS,Z ; salta se Z=1 (>255)
goto ZeroLoop ; Z=0 (<256)
;
; Overflow on Zero
;
ZOLoop:
btfss PORTA,2 ; salta se IR = 1
goto ZOLoop ; aspetta fino a che IR=0
;
EndZeroCount:
incf FSR,1
;
OneCount:
clrf INDF ; azzera contatore corrente
OneLoop:
call PAUSE
btfss PORTA,2 ; salta se IR = 1
goto EndOneCount
incf INDF ; incrementa contatore corrente
btfss STATUS,Z ; salta se Z=1 (>255)
goto OneLoop ; Z=0 (<256)
;
; Overflow on One
;
; Se il comando si interrompe a metà, va a 1
; per impedire che il software rimanga all'infinit oin loop
; va definito un Tempo max. di attesa e poi fine comando
;
movlw h'FF'
movwf COUNT2
OODly:
movlw h'FF'
movwf COUNT1
OOLoop:
btfss PORTA,2 ; salta se IR = 1
goto EndOneCount ; IR=0
decfsz COUNT1,1
goto OOLoop
decfsz COUNT2,1
goto OODly
;
; Comando incompleto: fine prematura
;
return
;
EndOneCount:
incf FSR,1
btfss FSR,7 ; salta se FSR=80
goto ZeroCount
return
;
;***********************************************
; PAUSE
;***********************************************
;
PAUSE:
movlw h'01' ; può essere aumentato
; se troppi overflow in sequenza (intervalli lunghi)
movwf PCOUNT1
Pse1:
decfsz PCOUNT1,1
goto Pse1
return
;
;***********************************************
; DELAY Routine max 196,65 msec, min 0,771 msec
;***********************************************
;
DELAY_MAX:
movlw h'FF'
DELAY:
movwf COUNT2
Dly2:
movlw h'FF'
movwf COUNT1
Dly1:
decfsz COUNT1,1
goto Dly1
decfsz COUNT2,1
goto Dly2
return
;
;****************************************************
; LDELAY Routine lungo ritardo 1 ciclo circa 196 msec; max 49.8 sec circa
;****************************************************
;
LDELAY_STD:
movlw h'02'
LDELAY:
movwf ITERAZ
Dly3:
call DELAY_MAX
decfsz ITERAZ,1
goto Dly3
return
;
;*****************
; ACTUATOR CONTROL
;*****************
;
ACTCNT:
;
; Syncronization VALFL=0 Negative Polarity (Status Off)
; VALFL=1 Positive Polarity (Status On)
;
btfsc VALFL,0
goto Syncr2
; Negative Polarity
Syncr1:
btfss PORTC,3
goto Syncr1 ; waiting for AC=1
goto LdPr
; Positive Polarity
Syncr2:
btfsc PORTC,3
goto Syncr2 ; waiting for AC=0
;
; Loading procedure
;
LdPr:
call TRANSDET ; 0-->1
call PWSPCNT
return
;
; **********************
; Transition Detection
; **********************
;
TRANSDET:
btfsc PORTC,3
goto Tr10 ; jump if AC Signal=1
; AC Signal=0
Tr01:
btfss PORTC,3
goto Tr01 ; waiting for AC=1
return
Tr10:
btfsc PORTC,3
goto Tr10 ; waiting for AC=0
return
;
; **************************
; Power Supply Control Signal
; **************************
;
PWSPCNT:
movlw h'FF'
movwf PCOUNT1
PDly1:
decfsz PCOUNT1
goto PDly1
;
; Spike Emission
;
bcf PORTC,5 ; Signal Active
movlw h'10' ; durata spike
movwf PCOUNT1
Spk1:
decfsz PCOUNT1
goto Spk1
bsf PORTC,5 ; Signal Inactive
return
;
;******************************************
; GESTIONE EEPROM INTERNA (256 BYTE)
;******************************************
;
;******************************************
; EEREAD Routine: indirizzo in EEADR
;******************************************
;
EEREAD:
bsf EECON1,RD ;EE Read
movf EEDAT,W ;risultato in w
return
;
;*************************************************************
; EEWRITE Routine: byte in EEDAT, indirizzo in EEADR
;*************************************************************
;
EEWRITE:
bsf EECON1,WREN ;Enable write
movlw h'55' ;Unlock write
movwf EECON2
movlw h'AA'
movwf EECON2
bsf EECON1,WR ;Start the write
movlw h'0A' ; 06 è il minimo
call DELAY
return
;
;********************************************************************************
; INTEE_WR ROUTINE da RAM a EEPROM
;********************************************************************************
;
INTEE_WR:
movlw h'22'
movwf FSR ; inizializzazione puntatore di sequenza
clrf EEADR ; inizializzazione puntatore EEPROM
IntEEWrLoop:
movf INDF,w
movwf EEDAT
call EEWRITE
incf EEADR,1
incf FSR,1
btfss FSR,7 ; salta se FSR=80
goto IntEEWrLoop
return
;
; ************************************************************
; STATUS_SAVE: Memorizzazione in EEPROM; stato del relay in w
;*************************************************************
;
STATUS_SAVE:
movwf EEDAT
movlw h'FF'
movwf EEADR
call EEWRITE ; salva lo stato relay in EEPROM
return
;
;******************************************************************************
END ; directive 'end of program'
;******************************************************************************