;====================================================================================
;
;	File:
;		f1023.asm	(PIC16F871 EXE a Letöltohöz)
;	Leírás:
;		LED fényerejének változtatása potenciométer segítségével
;		PWM megvalósítással.
;	Megj:
;		Az egyes I/O meghajtók kódjai tipikusan egy-egy relokálható
;		object file-ban (vagy egy közös library-ban) lennének a kód
;		újra felhasználása végett. Csak a feladat kedvéért került az
;		egész program egy forrásfájlba és a Letölto monitor-program 
;		miatt abszolút címre.
;		A program megszakításokat nem használ.
;====================================================================================

;====================================================================================
;	Fejlesztő környezet:
;		MPLAB IDE 	v7.00 (XP Pro)
;		MPASM		v3.90
;		MPLINK		v3.90
;		SIM		v8.70
;====================================================================================


;===============[  INCLUDES  ]=======================================================

LIST P=16F877A
 #INCLUDE "P16F877A.INC"
 __CONFIG _XT_OSC&_CP_OFF&_WDT_OFF&_LVP_OFF
	CBLOCK	0x20			;memóriaszelet lefoglalása
	ENDC
; A hardware..

;===============[  SETTINGS  ]=======================================================

	RADIX				dec		; mint ANSI-c

;===============[  DEFINES   ]=======================================================

	#define BANK1 		bsf STATUS,RP0		; Abszolút szimbólumok esetén elég a direkt
	#define BANK0 		bcf STATUS,RP0		; register-bank váltás (rövidebb a kód).




;===============[  SECTION CODE ABS ]==================================================
;	 ________	
;	/        \
;	|  main  |
;	\________/	

		ORG	0				; Ez a Gyakorló userprg entry point.
	
		call		AD_Init			; I/O meghajtók inicializálása
		call		PWM_Init

	hurok:
		call		AD_GetResult		; Biztonságos A/D mintavétel (8-bites felbontás: W)
		call		PWM_SetDuty		; 2 bit lsb mindig 00. 8 bites érték W-ben.
		goto 		hurok


;===============[  SECTION CODE RELOC ]==========================================
;	 ______________	
;	/              \
;	|  A/D Driver  |
;	\______________/

	AD_Init:
		BANK1
		bsf		TRISA, 0		; RA0 bemenet (itt AN0 analóg csatorna)
		movlw		B'00001110'		; Result left-justified, AN0 only, Vcc 
		movwf		ADCON1			; internal voltage reference 
		BANK0	
		movlw		B'10000001'		; 32Tosc (Note.1), select AN0, A/D ON
		movwf		ADCON0
		return
			
	AD_GetResult:					; min. 20us Acquisition Time (Note.2)
		movlw 		-50			; 10MHz => 50 utasítás ciklus
		addlw		1			; wait..
		btfss		STATUS,Z	
		goto		$-2
		bsf		ADCON0, GO		; Ready to set GO: start conversion..
		btfsc		ADCON0, GO		; 
		goto		$-1			; ..poll until DONE
		movf		ADRESH, W		; return 8-bit MSB
		return


;===============[  SECTION CODE RELOC ]==========================================
;	 ______________	
;	/              \
;	|  PWM Driver  |
;	\______________/
		
	PWM_Init:					; T period in W-reg
		clrf		CCP1CON			; shut down CCP module
		BANK1
		movlw		0xff			; (Note.3)
		movwf		PR2			; set PWM T period
		bcf		TRISC,2			; RC2 out: CCP1 pin
		BANK0
		movlw		B'00000110'		; 1:16 Prescaler
		movwf		T2CON			; TMR2 run!
		clrf		CCPR1L			; Duty cycle: 0 for init.
		movlw		B'00001100'		; 
		movwf		CCP1CON			; Duty cycle zero 2 LSB + PWM kick in
		return 

	PWM_SetDuty:					; PWM_SetDuty(W) sets PWM-dynamic duty cycle
		movwf		CCPR1L			; prepare new value to latch
		return 



;===============[  KÓD VÉGE     ]==============================================
	
	END

;===============[  MEGJEGYZÉSEK ]==============================================

;Note 1.
-------
;	A Gyakorlóból kiindulva: Fosc=10MHz => Tosc=1E-7 (0.1 us).

;	A/D konverziónál a minimális, egy bitre jutó konverziós idő:
;	mTad = 1.6 us [DS30569B-page83]. Ezt csak a 32-es Fosc 
;	Prescaler tudja biztosítani, mert ha:

;	32×Tosc => Tad=3.2 us (ekkor Tad > mTad, ami OK).

;	(8×Tosc nem elég: Tad=0.8 us..)


;Note 2.
;-------
;	A teljes A/D konverzió egy beállási és a mintavételi időből áll.
;	A mintavételi idő a GO/DONE bittel könnyen figyelhető.
;	A beállási idő (Acquisition Time) azonban függ többek között
;	a bemenő impedanciától, vagy a chip hőmérsékletétől. Követve [DS30569B-page82]
;	A/D Acquisition Requirements képletét, erre 20us-mal lehet számolni, 
;	amit programból és aktív várakozással kell eltölteni. 

;	10MHz-es Fosc esetén a ciklusidő (Tcy) 0.4 us. Ez 20/0.4=50 utasítás ciklus 
;	alatt telik el. 

;	Mivel pontosabban 4 utasítás van a rutinban, így a végrahajtási idő valójában 
;	80us lesz (Stopwatch..)


;Magyarázat:
;----------- 
;	Fosc: 	külső HS-oscillator freq
;	Tosc:	1/Fosc
;	Fcy:	utasítás műveleti freq (Fosc/4)
;	Tcy:	1/Fcy
;	Tad:	1 bit A/D átalakítás ideje successiv approx-val
		

;Note 3.
;-------

;	Az 1 bites PWM D/A esetén a következő paramétereink vannak:
	
;		1. T periódusidő,
;		2. W kitöltési tényező (Duty Cycle),
;		3. kimeneti feszültség értéke (Vcc*W/T),
;		4. kimeneti feszültség bit-felbontása.
;	
;	PWM esetén a kimeneti feszültséggel megpróbáljuk a legnagyobb kitöltési 
;	spektrumot elérni, azaz ideális esetben a W/T hányadost a [0..1] zárt intervallumba
;	szorítani. Ekkor a kimeneti feszültség 0-tól 5V-ig vezérelhető.
;	
;	A T periódusidőt a legnagyobbra állítjuk (PR2=0xFF), ezzel a TMR2 a 0x00-0xFF
;	értékeket veszi fel. Ez kerül összehasonlításra a W kitöltési tényező (Duty 
;	Cycle) értékével. 
;
;	Előzetesen kimértem, hogy a Gyakorló esetében az A/D átalakítás milyen 
;	digitális értékeket helyez el ADRESH-ban (left-justified, 8 MSB), 
;	az értékeket hex számként terminálra küldve (9600,8,N,1 UART).
;	A spektrum 0x00-0xFF. Ezért lett a PR2 is 0xFF, hogy a hányados az előbb
;	említett maximális határok közt változhasson. 
;
;	Mivel a kimeneti feszültség középértéke nem függ PWM frekvenciájától, ezért
;	különböző PWM frekvenciákkal próbálkoztam. A vezérelt LED esetében nem láttam
;	különbséget, azért - az áramköri elemek "kímélése" érdekében - a legnagyobb T 
;	periódusidőt használom (16-os TMR2 Prescaler).
;
;	Az egyszerűség kedvéért a vezérlés 8 bites felbontásban történik, azaz 256 különböző 
;	kimeneti feszültség jelenhet meg, mert a Duty Cycle 2 LSB bitje  mindig 0. 
;	Hasonló okból az A/D átalakító 10 bites kimeneti értékének 2 LSB bitje sem használt.
;