uvbox.asm
;Ver. 0.0  20111213
;Johnny Apell
;
;Programmet gjort i MPLAB IDE v8.70
;
;Program för simulera en timer i en UV-BOX. för att belysa kretskort
;UV-Lysdioderna startas med START
;Kan stoppas med STOPP
;Och på utgång GPIO,2 sitter en MOS-Transistor som styr UV-LED
;som skvaller och 'live' diod blinkar det på utgång GPIO,1 under processen
;och som indikation att tiden gått ut ljuder en summer på utgång GPIO,5
;
;Intern RC-klocka 4MHz i kretsen 12f675, ingen watchdog eller andra finesser
;
;Processorn har 8 ben varav 5 ben är universiella, bl.a kan 4 analoga ingångar
;användas. GPIO,3 kan bara användas som ingång.
;Weak pullup motstånd är aktiverad på GPIO,0 START. GPIO,3 STOPP har inte den funktionen ..tyvärr.
;Insignalerna är START och STOPP, samt analog ingång för inställning
;av den önskade tidsfördröjningen
;
;Önskad tid är 0 - 10 minuter = 0 - 600 sekunder
;med 10 bitars upplösning på analogingången så får vi 600/1024= ca 0,59 sek per steg i upplösning
;
;12F675 Kretsens benfördelning
;
;ben 1		VDD			+5V
;ben 8		VSS			0V
;ben 7 		GPIO,0		Ingång START
;ben 6 		GPIO,1		Liveutgång
;ben 5		GPIO,2		Utgång UV-LED
;ben 4		GPIO,3	    Ingång STOPP
;ben 3		GPIO,4		Analogingång
;ben 2		GPIO,5		Utgång summer



;**********************************************************************************
;Placering av de olika registren i minnesarean

ANlo		equ	20h				;Analogingång  
ANhi		equ 21h
slask		equ	22h				;slaskregister för tidsförsdröjningarna
slask1		equ	23h				;"
slask2		equ 24h
zerohi		equ 25h				;jämför register som alltid skall vara noll
zerolo		equ 26h

aHI			equ	30h				;Ge olika register ett "namn"
aLO			equ	31h				;vilka användes vid anropande av 
bHI			equ	32h				;subrutinen "sub" subtraktion
bLO			equ	33h
posit		equ	34h				;här hamnar flaggorna =,<,> av resultatet vid subtraktion
Temp		equ 35h				;temorärt register i subtraktionen

#define 	START			GPIO,0	
#define		STOPP			GPIO,3
#define		SUMMER			GPIO,5
#define		BLINKA			GPIO,1
#define 	UV_LED			GPIO,2

;**********************************************************************************


;Här talar vi om för assemblerprogrammet vilken processor vi har och vilka adresser
;som vi ska starta ifrån

	list    p=12f675	;direktiv till assemblern om vilken process. som valts

	#include <p12f675.inc>  ; processor specific variable definitions
	
					  		;ställ configbitarna i MPLAB manuellt
							;intern osc 4MHz, ingen watchdog, ingen MCLR osv.
	
	ERRORLEVEL -302 		; suppress message because of page change

	org     0	     		;adress vid power on eller reset
	goto    init    		;gå till initiering av kretsen, islutet av programmet


;**********************************************************************************


			;Subrutin för att läsa in analogvärdet från potentiometern
ANALOG

	clrf	zerolo			;nollställ lite register innan beräkningen
	clrf	zerohi			;kanske lite onödigt...men...
	clrf	ADRESH
	clrf	ADRESL
	clrf	ANhi
	clrf	ANlo
	clrwdt					;Ett fläskben till hunden!
	bsf		ADCON0,3		;välj ad-ingång 3
	bsf		ADCON0,2		;"
	nop						;vänta något... no operation
	nop
	nop
	bsf		ADCON0,1		;starta ad-omvandlingen
	btfsc	ADCON0,1		;kolla om ad-omvandlingen är färdig
	goto	$-1				;vänta tills ad-omvandlingen är färdig
	movfw	ADRESH			;ladda det nya höga ad-värdet från AD-omvandlaren
	movwf   ANhi			;placera i höga registret 
	bsf		STATUS,5		;banka om minnesarea				
	movfw	ADRESL			;hämta låga värdet
	bcf		STATUS,5		;banka tebaks minnesarea
	movwf	ANlo			;placera i låga registret
	return		
;***************************************************************************
				;subrutin för subtrahering av 2 16-bitarstal A-B=A

sub				;Subrutin för 16 bitars subtraktion a-b=a
				;samt kontroll om resultatet blev 
				;lika, mindre eller större

	clrwdt				;mata hunden så han inte bits
	clrf	posit		;rensa flaggbitarna
	movf	bHI,w		;ladda in höga b
	subwf	aHI,w		;minska med höga a
	movwf	Temp		;spara i reg Temp
	movf	bLO,w		;ladda in låga b
	subwf	aLO,w		;minska med låga a
	movwf	Temp+1		;spara i nästa Temregister
	btfss	STATUS,C	;testa om det blev negativt
	decf	Temp,1		;minska isåfall Tempregistret 
	iorwf	Temp,w		
	btfss	STATUS,Z	;kolla om det blev lika
	goto	$+3
	bsf		posit,2		;om lika sätt flagga 2 i reg posit
	goto	$+5
	btfsc	Temp,7		;kolla om det blev negativt resultat
	bsf		posit,1		;negativt, sätt flagga 1
	btfss	Temp,7		;kolla om det blev positivt resultat
	bsf		posit,0		;positivt sätt flagga 0
	movfw	Temp		;flytta över resultatet
	movwf	aHI			;till höga a
	movfw	Temp+1
	movwf	aLO			;låga a
	return

;********************************************************************************	
delay					;rutinen att skapa "sekundpulsen" 0,59sek ... att räkna ner värdet
						;från potentiometern till noll. Maxtiden blev 10minuter och 15sek
						;med denna fördröjning... helt ok noggranhet för UV-lådan.

	movlw	.90			;ladda in ett lämpligt värde för att skapa "0,59 sekundpulsen"
	movwf	slask2		;ladda in i sista räkneregistret
	movlw	.10			;ett värde i slask1 för att få bättre upplösning i slask2
	movwf	slask1	


jmp2
	movlw	.10			;för att skapa bättre upplösning i slask1
	movwf	slask1		;placeras i slask2
	decfsz	slask,f		;
	goto	$-1			;här dumjobbar processorn för att slösa tid
	decfsz	slask1,f	;
	goto	$-3			;
	decfsz	slask2,f	;när denna räknat ner till 0 är vi klara
	goto	jmp2		;inte färdig än... tebaks till ett nytt varv
	return				;'sekunden' har gått...färdigt...tebaks


;***********************************************************************************
			
starta					;Tänd UV-dioderna och börja att räkna ner tiden
				

	btfss	START		;kolla om UV-LED skall tändas? Är START aktiv?
	goto 	kör
	return				;om inte...tebaks till main

;********************************************************************************
						;Genom att läsa in potentiometerns läge, så får vi motsvarande
						;värde som 16 bitar i två 8-bitarsregister 0...1024
						;Nu kan vi räkna ner detta värde till noll och skapa tidsfördröjningen. 
kör	
	call 	ANALOG		;läs in potentiometerns värde till räkneregistren
	call	ON			;tänd UV-dioderna
	goto	jmp4		;kolla först om potentiometern står på 0!! innan vi räknar ner ett steg

jmp1
	btfss	STOPP		;kolla om vi ska avbryta proceduren??	
	goto	OFF
	call	toggla		;skifta livediodens status
	call	delay		;anropa tidsfördröjningen
dec		
	movf    ANlo,f		;räkna ner registret ett steg
 	skpnz
   	decf   	ANhi,f
  	decf    ANlo,f

jmp4					;kolla om det blev noll
 	movfw	ANhi
	movwf	aHI			;flytta över värdena i 'sub-räkneregistren'
	movfw	ANlo
	movwf	aLO
	clrf	bHI			;nollställ jämförregistren till beräkningen
	clrf	bLO
	call	sub			;gå och gör räkneoperationen, subtraktion
	btfss	posit,2		;blev resultatet lika men 0 ??
	goto	jmp1		;om inte lika = 0 kör ett nytt varv
	goto	OFF			;det var 0 stoppa proceduren..gå och släck UV-dioderna
	return
;*******************************************************************************
ON				
	bsf		UV_LED		;sätt utgång GPIO,2, starta UV-dioderna
	return

;***********************************************************************************
OFF						;Släck UV-dioderna och tuta lite i summern
	bcf		UV_LED		;släck UV-dioderna
	bcf		BLINKA		;släck "live" dioden		
	bsf		SUMMER		;starta summern

	movlw	.6			;skapa en 2sek lång tutning av summern
	movwf	slask1		;och förställ register slask1

jmp3
	decfsz	slask,f		;börja att dumräkna ner registren för att slösa tid
	goto	jmp3		;
	decfsz	slask2,f	;
	goto	jmp3		;
	decfsz	slask1,f	;
	goto	jmp3		;
	bcf		SUMMER		;tiden är ute...släck summern
	return				;färdigt...tebaks till main

;********************************************************************************
						;Endast för att visa att kretsen lever, låt en lysdiod blinka
						;när UV-dioderna är tända och tiden räknas ner
toggla
	btfss	BLINKA		;växla status på utgången varannan gång rutinen anropas
	goto	$+3
	bcf		BLINKA
	return
	bsf		BLINKA
	return				;tebaks

;********************************************************************************

						;Huvudprogrammet
						;Här anropas respektive subrutin en i taget
						;Här snurrar programmet när inte UV-dioderna är tända

main
	clrf	GPIO		;se till att utgångarna är släckta
	call	starta		;läs in analogvärdet från potentiometern och börja räkna ned
	goto	main		;kör ett nytt varv i detta program

;********************************************************************
	
			;Initiering av kretsen
			;detta sker endast vid uppstart av processorn
init    
	
	bcf     STATUS,5     	;banka tebaks till registersida 0
	clrf	GPIO			;rensa portutgångarna
	movlw	b'00000111'		;move 00000111 =digitala i I/O på pinnarna komparatoringångarna
	movwf	CMCON			;placeras i CMCON registret
	movlw   b'10000001'  	;vänsterjustera analogvärdet i de två 8-bitarsregistren, AD=on
	movwf   ADCON0    		;placera i ADCON0 1Fh
	bsf     STATUS,5     	;banka till registersida 1
	movlw	b'01101000'		;aktivera AD-modulen och välj klockhastighet i AD-omvandlingen
	movwf	ANSEL			;placera i ANSEL
	movlw	b'00011001'		;välj vilka pinnar som skall vara IN=1, START, STOPP och AD-ingång
	movwf   TRISIO      	;Placera i TRISIO registret
	movlw	b'00000001'		;välj vilka ingångar som skall ha weak pullup
	movwf	WPU				;placera i WPU. Tyvärr har inte GPIO,3 weak pullup...
	movlw	b'00000000'		;aktivera weakpullup bit 7=0
	movwf	OPTION_REG		;placera i OPTION_REG registret
	bcf     STATUS,5     	;banka tebaks till registersida 0
	clrf	GPIO			;säkerställ att utgångarna är OFF
	goto    main   			;gå till huvudprogrammet
	
	end			;programslut