

;=================================================================================
;	CLOCK: Internal RC 4MHz (instruction execution time: 1usec)
;	This is a basic start template for PIC12F683
;	Includes delay routines 
;	Note: labels and variables case sensitive!
;	Program name: Return ADC input to control PWM output
;	MCLR as digital input
;	PB1 is GPIO.5, PB2 is GPIO.3, GPIO.4 is AN3 input, 10K potentiometer wiper
;	LED1 is GPIO.0, LED2 is GPIO.1, PWM OUTPUT is GPIO.2
;	Subroutines: toggleLED1, toggleLED2, togglePWM 
;	Date: 7/28/2024
;	Author: Lewis Loflin
;		
;==================================================================================
        list     P=12F683, ST=OFF   ; Turnoff Symbol Table in List file.

        errorlevel  -302        ; Ignore error message when storing to Bank 1.
;==================================================================================

        #include   <p12f683.inc>

   __config _INTOSCIO & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF &  _CP_OFF & _CPD_OFF & _BOD_NSLEEP & _IESO_OFF & _FCMEN_OFF

; ------------------------------------
; Configuration Bit Settings Explained
; ------------------------------------
; Internal RC Oscillator, No Clock Out
; Watch Dog Timer = OFF
; Power Up Timer = ON
; MCLR = INTERNAL
; Code Protect = OFF
; Data EE Read Protect = OFF
; Brown Out Detect = Enabled in Run, Disabled in Sleep, SBOREN Disabled
; Internal External Switch Over Mode (2-speed Startup) = OFF
; Monitor Clock Fail-safe = OFF
;======================================================================

;*****[ Data Storage Reg's ]*****
	; Assign each reg. from Bank 0 RAM area.
	; total 96 bytes from 0x20 - 0x7F
	CBLOCK  0x20 
	B0
	B1
	B2
	temp1
	temp2
	CNT1
	CNT2
	CNT3
	CNT4
	ENDC         ; Conclude Bank 0 RAM assignments.

;**********************************************************************
	ORG     0x000             ; processor reset vector
	goto    setup              ; go to beginning of program
	
	ORG     0x004             ; interrupt vector location
	retfie                    ; return from interrupt

;**********************************************************************

	;Define
	LED1 EQU 0
	LED2 EQU 1
	pwmPIN EQU 2 ; pwm out
	PB1 EQU 5
	pot EQU 4 ; 10K potentiometer wiper used AN3
	PB2 EQU 3		
			
setup
	BANKSEL OPTION_REG          ; Switch to Bank 1.
	MOVLW   B'01100001'     ; 4MHz Clk, IntOsc, SysClk via IntOsc
	MOVWF   OSCCON
	; GPIO 6-bit port GPIO.0 - GPIO.5
	; GPIO.0 - GPIO.2 output; GPIO.3 pwm out
	; GPIO3 must be output for pwm
	; GPIO.3, GPIO.5 digital input
	; GPIO.4 analog 3 in, must be input
	; 1 = INPUT, 0 = OUTPUT
	MOVLW B'111000'
	MOVWF TRISIO ;
	; pull ups
	BCF OPTION_REG, 7 ; turn on PU
	MOVLW B'111000' ; bit 3 use external pullup
	MOVWF WPU
	BANKSEL GPIO          ; Switch to Bank 0.
	MOVLW   b'00000111'     ; Turn off Comparator.
	MOVWF   CMCON0  
	CLRF    GPIO  

;************************************************************
	; https://www.micro-examples.com//public/microex-navig/doc/097-pwm-calculator
	; PR2 = %11111001 'Timer2 Module Period Register - Bank 1
	; rest bank 0
	; T2CON = %00000101  
	; P52, Bits 6-3 postscaler, 0000 = 1:1
	; Bit 2 TMR2ON, 1 = ON, 0 = OFF
	; Bits 1-0 prescaler value 01 = 1:4
	; CCPR1L = %0  ' duty cycle 0-255
	; CCP1CON = %00001100  'CCP1 control register 
	; Buts 3-0 CCP mode select, 110x =  PWM active high
	; Bits 5-4 PWM LSB
	; Bits 7-6 unused
	; pwm registers
	; for PWM
	; PR2 = %11111001 'Timer2 Module Period Register - Bank 1	
	BANKSEL 1 ; Bank 1
	MOVLW B'11111001'
	MOVWF PR2
	BANKSEL 0 ; Back Bank 0
	MOVLW B'00000101'
	MOVWF T2CON
	CLRF  CCPR1L ; duty cycle 0-255
	MOVLW B'00001100'
	MOVWF CCP1CON     

;*****************************************************************
	; ADC registers setup
	
	; ANSEL = %00111000 ' Set AN3 analog, rest digital
	; Bits 2-0 is clock source P64
    ; Digital, pullups, and IRQ disabled when analog input
    ; TRISIO bit must be set to input
    ; Always clear ANSEL when not using ADC
	BANKSEL ANSEL
	MOVLW B'00111000' 
	MOVWF ANSEL ;
	BANKSEL ADCON0
    MOVLW B'00001101'
    MOVWF ADCON0	
    ; ADCON0 = %00001101  ' P63 
    ; Bit 7 determines bit order 
    ; 1 is Right justify result, 0 is left justify
    ; Use left justify
    ; Right justified: ADRESL = low byte, ADRESH 2 upper bits D8, D9
    ; Left justified ADRESL 2 LSB, ADRESH 8 MSB
    ; bit 6 ref. 1 = Vref pin, 0 = VDD
    ; bits 5-4 XX
    ; bit 3-2 AN select: 00 = AN0; 01 = AN1; 10 = AN2; 11 = AN3
    ; bit 1 GO = HIGH, 0 = Done
    ; bit 0 ADON, 1 = enable ADC, 0 = disable ADC 
    

	; Uses 0x71 bytes =  113 bytes out of 2048 bytes

goto main

main

	CALL toggleLED1 ; Toggle LED0 if PB0 pressed
	CALL toggleLED2 ; Toggle LED1 if PB1 pressed
	CALL checkPWM ; Turn ON PWM if LED1 OR LED2 ON
	; else PWM OFF


goto main
		
;**************************	;Delay routine.
; Calculating a 1mSec delay. 4mHz is divided by 4 internally to
; At 4mHz / 4 = 1uSec. 1000 uSec. = 1 mSec.
; GOTO uses 3 cycles DECFSZ 1 cycle = 3 cycles or 3uSec.
; 3 * 82 * 4 =~ 1000uSec. or 1mSec.

DELAY_1ms
	; 4 mHz crystal
	MOVLW D'4'
	MOVWF CNT1
	MOVLW D'82'
	MOVWF CNT2
	DECFSZ CNT2, F
	GOTO $-1 ; count 82 times at ~3.05 uSEC per count
	DECFSZ CNT1, F
	GOTO $-5 
	RETLW 0

DELAY_100ms
	MOVLW D'100' ; value * DELAY_1ms = total delay
	MOVWF CNT3
	CALL DELAY_1ms
	DECFSZ CNT3, F
	GOTO $-2 
	RETLW 0


toggleLED1
	BTFSC GPIO, PB1
	RETLW 0 ; not pressed
	CALL pwmOFF
	CALL DELAY_100ms
	BTFSS GPIO, PB1 ; wait for release
	GOTO $-2
	BCF GPIO, LED2 ; turn off LED2
	CALL DELAY_100ms
	MOVLW 0x01
	XORWF GPIO, F
	CALL pwmON
	RETLW 0 ; pressed

toggleLED2
	BTFSC GPIO, PB2
	RETLW 0 ; not pressed
	CALL pwmOFF
	CALL DELAY_100ms
	BTFSS GPIO, PB2 ; wait for release
	GOTO $-2
	BCF GPIO, LED1 ; turn off LED1
	CALL DELAY_100ms
	MOVLW 0x02
	XORWF GPIO, F
	CALL pwmON
	RETLW 0 ; pressed

togglePWM
	; turn PWM ON-OFF with DDR bit 2
	BANKSEL TRISIO ; Bank 1
	MOVLW 0x04 ; toggle bit 
	XORWF TRISIO, F
	BANKSEL GPIO ; back Bank 0
	RETLW 0 ; pressed


checkPWM
	; ADCON0.1 = 1 ' begin conversion
    ; while  ADCON0.1 = 1  ' wait for bit to clear
    ; pause 1 mSec.
    ; wend
    
    ; Read GPIO latch, H is LED ON
    ; if GPIO.0 = H OR GPIO.1 = H 
    ; then pwm output is ON
	BTFSC GPIO, LED1 ; LED1 = H?
	GOTO $+5 ; if H init read ADC3 else
	BTFSC GPIO, LED2 ; LED2 = H?
	GOTO $+3 ; if H init read ADC3
	CLRF CCPR1L ;  if L 0% duty cycle
	GOTO $+7 ; skip conversion
	BSF ADCON0, 1 ; begin conversion
	CALL DELAY_1ms
	BTFSC ADCON0, 1
	GOTO $-2
	MOVFW ADRESH ; high 8-bits
	MOVWF CCPR1L ; duty cycle 0-255
	RETLW 0 ; no conversion




pwmOFF
	BANKSEL TRISIO
	; 1 = INPUT, 0 = OUTPUT
	BSF TRISIO, pwmPIN
	BANKSEL GPIO
	RETLW 0
	
pwmON
	BANKSEL TRISIO
	; 1 = INPUT, 0 = OUTPUT
	BCF TRISIO, pwmPIN
	BANKSEL GPIO
	RETLW 0
	
end
