;                            Software License Agreement
;
; The software supplied herewith by Microchip Technology Incorporated (the "Company")
; for its PICmicro® Microcontroller is intended and supplied to you, the Company’s
; customer, for use solely and exclusively on Microchip PICmicro Microcontroller
; products.
;
; The software is owned by the Company and/or its supplier, and is protected under
; applicable copyright laws. All rights are reserved. Any use in violation of the
; foregoing restrictions may subject the user to criminal sanctions under applicable
; laws, as well as to civil liability for the breach of the terms and conditions of
; this license.
;
; THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, WHETHER EXPRESS,
; IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE
; COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
; CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;
; ###############################################################################
;	filename:		USB_MAIN.ASM
;				Sample mainline program
;
; This file implements a basic interrupt service routine and shows how the
; USB interrupt would be serviced, and also how InitUSB, GetUSB and PutUSB
; should be called.  It may be used as a reference, or as a starting point 
; from which to build an application.  
;
; ###############################################################################
;
;    	Author:			Dan Butler
;    	Company:		Microchip Technology Inc
;
;	Revision:		1.10
;	Date:			07-December-2000
;	Assembled using		MPASM 2.30.07
;	Configuration Bits:	H4 Oscillator, WDT Off, Power up timer off
;
;################################################################################
;
;	include files:
;		P16C765.inc	Rev 1.00
;		usb_defs.inc	Rev 1.00
;
;################################################################################
#include <p16c745.inc>
#include "usb_defs.inc"

	__CONFIG	_H4_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF

unbanked	udata_shr
W_save		res	1

bank0	udata
Status_save	res	1	; registers for saving context
PCLATH_save	res	1
FSR_save	res	1

inner		res	1	; delay loop counters
middle		res	1
outer		res	1
;ADDED AM
buffersFilled	res	1	; # of values read from ADC
adcValue	res	1	; scaled value from ADC
;END ADDED AM

buffer		res	8	; source/destination buffer for testing...

state	res	1
counter	res	1

	extern	InitUSB
	extern	PutEP1
	extern	GetEP1
	extern	ServiceUSBInt
	extern	CheckSleep
	extern	RemoteWakeup

STARTUP	code
	pagesel	main
	goto	main
	nop
InterruptServiceVector
	movwf	W_save		; save W
	movf	STATUS,W
	clrf	STATUS		; force to page 0
	movwf	Status_save	; save STATUS
	movf	PCLATH,w
	movwf	PCLATH_save	; save PCLATH
	movf	FSR,w
	movwf	FSR_save	; save FSR

; *************************************************************
; Interrupt Service Routine
; First we step through several stages, attempting to identify the source 
; of the interrupt.
; ******************************************************************

Process_ISR
; Step 1, what triggered the interrupt?

	btfsc	INTCON,T0IF	; Timer 0
	nop
	btfsc	INTCON,RBIF	; Port B
	call	PortBChange
	btfsc	INTCON,INTF	; External Interrupt
	nop

	pagesel	ServiceUSBInt
	btfsc	PIR1,USBIF
	call	ServiceUSBInt

	btfsc	PIR1,ADIF	; AD Done?
	nop
	btfsc	PIR1,RCIF
	nop
	btfsc	PIR1,TXIF
	nop
	btfsc	PIR1,CCP1IF
	nop
	btfsc	PIR1,TMR2IF
	nop
	btfsc	PIR1,TMR1IF
	nop
	btfsc	PIR2,CCP2IF
	nop

; ******************************************************************
; End ISR, restore context and return to the main program
; ******************************************************************
EndISR
	clrf	STATUS		; select bank 0
	movf	FSR_save,w	; restore the FSR
	movwf	FSR
	movf	PCLATH_save,w	; restore PCLATH
	movwf	PCLATH
	movf	Status_save,w	; restore Status
	movwf	STATUS
	swapf	W_save,f	; restore W without corrupting STATUS
	swapf	W_save,w
	retfie


; **********************************************************************
; PortB Change Interrupt Handler, calls RemoteWakeup to perform wakeup
; **********************************************************************
PortBChange
	clrf	STATUS
	movf	PORTB,w
	bcf	INTCON,RBIF
	pagesel RemoteWakeup
	call RemoteWakeup
	return

	code
; ******************************************************************
; test program that sets up the buffers and calls the ISR for processing.
; 	
; ******************************************************************
main

	movlw	.30		; delay 16 uS to wait for USB to reset
	movwf	W_save		; SIE before initializing registers
	decfsz	W_save,f	; W_save is merely a convienient register
	goto	$-1		; to use for the delay counter.

; ******************************************************************
; Sets the probe control register to output the UCTRL register and
; USBDPRAM databus onto the probepins.  
; ******************************************************************
	bsf	STATUS,RP0
	bcf	STATUS,RP1
	bcf	OPTION_REG,NOT_RBPU  ; enable portb weak pull-up to detected change in PORTB

;ADDED AM
	movlw	B'10'		;Set to use all analog pins
	banksel	ADCON1		;Go to the ADC bank
	movwf	ADCON1		;
	banksel ADCON0		;Go to the other ADC bank
	bsf	ADCON0,ADCS1	;Set ADC Conversion Clock
	bcf	ADCON0,ADCS0	; to Fint/32
	bcf	ADCON0,CHS2	;Set the Analog Channel Pin
	bcf	ADCON0,CHS1	; to pin 0
	bcf	ADCON0,CHS0	;
	bsf	ADCON0,ADON	;Turn the ADC on
	banksel	buffersFilled	;set the # buffers filled to zero
	clrf	buffersFilled

;END ADDED AM

	pagesel	InitUSB
	call	InitUSB
	pagesel	main
	ConfiguredUSB	; wait here until the enumeration process is complete

idleloop

	banksel	inner
	clrf	inner
	clrf	middle

	incfsz	inner,f
	goto	$-1
	incfsz	middle,f
	goto	$-2

;ADDED AM
startDataCollection
	banksel buffersFilled
	clrf	buffersFilled
	banksel buffer
	clrf	buffer
	clrf	buffer+1
	clrf	buffer+2
	clrf	buffer+3
	clrf	buffer+4
	clrf	buffer+5

checkADC
	banksel	ADCON0		;Go to the ADC bank
	btfsc	ADCON0,GO_DONE	;Check if completed ADC conversion
	goto	checkADC	; busy wait for ADC to complete (GO_DONE -> 0)

	pagesel retrieveADCValue
	call retrieveADCValue	;Get the value from the ADC - value is in adcValue

	banksel inner
	clrf	inner		;wait for the ADC to get new value
	bsf	inner,7
	bsf	inner,5
	incfsz	inner,f
	goto	$-1	
	
	pagesel restartADC
	call restartADC		;start the next cycle

;	banksel adcValue
;	movf	adcValue,w
;	banksel	buffer
;	movwf	buffer

	banksel buffer
	movlw	buffer		;buffer address
	addwf	buffersFilled,w	;add the offset into the buffer
	movwf	FSR		; indirect addressing register
	banksel	adcValue
	movf	adcValue,w	;move adcvalue into W
	bankisel buffer
	movwf	INDF		;move adcValue into the buffer
	incf	buffersFilled,f	;increment

	;check if we have filled the whole buffer
	movf	buffersFilled,w	;put the number of buffers we have filled so far into w
	sublw	4		;subtract the number of buffers we have to fill
	btfss	STATUS,Z	;loop until subtraction is zero
	goto	checkADC
	
sendData
	pagesel	PutEP1
	bankisel buffer		;put the buffer address into the FSR
	movlw	buffer
	movwf	FSR
	movlw	0x4		; send 4 bytes
	call	PutEP1
	btfss	STATUS,C	; loop here until packet goes through
	goto	sendData
	
	pagesel startDataCollection
	goto	startDataCollection	;restart process

retrieveADCValue
	;assumes the ADC has finished - copies value into other register
	banksel	ADRES		;Go to the ADC result register
	movf	ADRES,w		;Get the value
	banksel	adcValue
	movwf	adcValue	;Store ADC value in register	

	return			;return - adcValue contains

restartADC
	banksel	ADCON0
	bsf	ADCON0,GO	;Set the GO bit for the ADC
	return
	end
