 TITLE  "pwm_led.asm"           	; PWM test with LCD
 List P=PIC16F684, R=DEC
 INCLUDE "p16f684.inc"

; data segment
 CBLOCK 0x20                   
 del  					; variable used for delay
 temp					; local temp variable	
 ENDC

; code segment
 PAGE
 __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
  org 0                      		; start program at the beginning of mem
	bcf	STATUS, RP0		; activate BANK 0
	clrf	PORTA			; initialize PORT A
	clrf	PORTC			; initialize PORT C
	movlw	0x07
	movwf	CMCON0			; comparators OFF
	bsf    	STATUS, RP0      	; change to BANK 1

 	; ADC and PWM configuration
	bsf	TRISA ^ 0x80, 0		; enable input on pin A0
	bsf	ANSEL ^ 0x80, 0		; configure A0 as analog input
	movlw 	b'01110000' 		; set ADC Frc clock
	movwf 	ADCON1 ^ 0x80
	movlw	0xFF	
	movwf	PR2 ^ 0x80		; PWM period 244Hz
	bcf	TRISC ^ 0x80, 5		; enable RC5 for output
	bcf    	STATUS, RP0        	; back to BANK 0

	bsf 	ADCON0, 0 		; Left justify, Vdd Vref, AN0, On	
	movlw	7
	movwf	T2CON			; enable Timer 2 with 1:16 prescaler
	movlw	0x0C			; enable single output PWM
	movwf	CCP1CON 	

loop
	movlw	20
	movwf	del
	call	delay			; 20 msec delay

	bsf	ADCON0, GO		; start ADC operation
	btfsc	ADCON0, GO		; and wait for its completion	
	goto 	$-1

	bsf    	STATUS, RP0      	; change to BANK 1
	movf	ADRESL ^ 0x80, w	; read 2 lower bits of ADC
	bcf	STATUS, RP0
	movwf	temp
	rrf	temp, f
	rrf 	temp, f
	movf	temp, w
	iorlw	b'11001111'
	andwf	CCP1CON, f		; setup the 2 lower bits of PWM
	movf	ADRESH, w		; get high 8 bits of ADC
	movwf	CCPR1L			; setup PWM duty cycle

  	goto 	loop			; endless loop


; procedures
delay					; a delay for del milliseconds
	movlw 	200
	
	sublw	1			; this loop takes 5us*200 = 1ms
	sublw	0			; for PIC16F684 @ 4 MHz
	btfss	STATUS, Z
	goto 	$-3

	decfsz	del, f
	goto 	delay
	return

 end
