1
2	list	p=16f819
3        include <p16f819.inc>
4        include <coff.inc>
5
6  __CONFIG _WDT_OFF
7
8	;; The purpose of this program is to test gpsim
9	;; Specifically, the a/d converter is tested.
10
11        errorlevel -302
12
13; Printf Command
14.command macro x
15  .direct "C", x
16  endm
17
18;----------------------------------------------------------------------
19;----------------------------------------------------------------------
20GPR_DATA                UDATA_SHR
21
22x  RES  1
23t1 RES  1
24t2 RES  1
25avg_lo RES  1
26avg_hi RES  1
27w_temp RES  1
28status_temp RES  1
29
30
31;----------------------------------------------------------------------
32;   ********************* RESET VECTOR LOCATION  ********************
33;----------------------------------------------------------------------
34RESET_VECTOR  CODE    0x000              ; processor reset vector
35        movlw  high  start               ; load upper byte of 'start' label
36        movwf  PCLATH                    ; initialize PCLATH
37        goto   start                     ; go to beginning of program
38
39INT_VECTOR   CODE    0x004               ; interrupt vector location
40	;;
41	;; Interrupt
42	;;
43	movwf	w_temp
44	swapf	STATUS,W
45	movwf	status_temp
46
47	bcf	STATUS,RP0	;adcon0 is in bank 0
48
49	btfsc	INTCON,ADIE
50	 btfsc	PIR1,ADIF
51	goto	inta2d
52
53  .assert "'FAILED 16F819 a2d unexpected interupt'"
54	nop
55	goto	check
56;;	An A/D interrupt has occurred
57inta2d:
58	bsf	t1,0		;Set a flag to indicate we got the int.
59	bcf	PIR1,ADIF	;Clear the a/d interrupt
60
61
62check:
63	swapf	status_temp,w
64	movwf	STATUS
65	swapf	w_temp,F
66	swapf	w_temp,W
67	retfie
68
69
70
71;----------------------------------------------------------------------
72;   ******************* MAIN CODE START LOCATION  ******************
73;----------------------------------------------------------------------
74MAIN    CODE
75start:
76
77   .sim "module library libgpsim_modules"
78   ; Use a pullup resistor as a voltage source
79   .sim "module load pullup V1"
80   .sim "V1.resistance = 100.0"
81
82   .sim "node na0"
83   .sim "attach na0 V1.pin porta0"
84
85   .sim "module load pullup V2"
86   .sim "V2.resistance = 100.0"
87
88   .sim "node na1"
89   .sim "attach na1 V2.pin porta3"
90
91	;; Let's use the ADC's interrupt
92    ; RA0 is an Analog Input.
93    ; RA1 - RA5 are all configured as outputs.
94    ;
95    ; Use VDD and VSS for Voltage references.
96    ;
97    ; PCFG = 1110  == AN0 is the only analog input
98    ; ADCS = 110   == FOSC/64
99    ; ADFM = 0     == 6 LSB of ADRESL are 0.
100    ;
101
102
103	bsf	STATUS,RP0	;adcon1 is in bank 1
104        movlw   1
105        movwf   TRISA
106
107
108        movlw   (1<<PCFG1) | (1<<PCFG2) | (1<<PCFG3)
109        movwf   ADCON1
110        movlw   (1<<ADCS1) | (1<<ADON)
111        bsf     PIE1,ADIE       ;A2D interrupts
112	bcf	STATUS,RP0	;adcon0 is in bank 0
113        movwf   ADCON0
114
115        bsf     INTCON,GIE      ;Global interrupts
116        bsf     INTCON,PEIE     ;Peripheral interrupts
117
118
119	call	Convert
120
121  .assert "adresh == 0xff, 'Failed 16F819 a2d initial test'"
122	nop
123
124	;; The next test consists of misusing the A/D converter.
125	;; TRISA is configured such that the I/O pins are digital outputs.
126	;; Normally you want them to be configued as inputs. According to
127	;; the data sheet, the A/D converter will measure the voltage produced
128	;; by the digital I/O output:	 either 0 volts or 5 volts (or Vdd).
129	;; [I wonder if this would be a useful way of measuring the power supply
130	;; level in the event that there's an external reference connected to
131	;; an3?]
132
133  .command "V1.resistance=1e6"
134
135	movlw   0
136	bsf	STATUS,RP0
137	movwf	TRISA		;Make the I/O's digital outputs
138	movwf	ADCON1		;Configure porta to be completely analog
139				;(note that this is unnecessary since that's
140				;the condition they're in at power up.)
141	bcf	STATUS,RP0
142
143	movwf	PORTA		;Drive the digital I/O's low
144
145	;;
146	;; First do a few conversion with porta configured as a digital output
147	;; that is driving low
148	;;
149
150	call	Convert
151
152  .assert "adresh == 0x00, 'Failed 16F819 a2d Digital low'"
153	nop
154
155	;;
156	;; Now do some with the digital output high
157	;;
158
159	movlw	0xff
160	movwf	PORTA
161
162	call	Convert
163
164  .assert "adresh == 0xff, 'Failed 16F819 a2d Digital high'"
165	nop
166	;;
167	;; Now make the inputs analog (like they normally would be)
168	;;
169
170  .command "V1.resistance=100.0"
171
172	bsf	STATUS,RP0
173	movlw	0xff
174	movwf	PORTA
175	bcf	STATUS,RP0
176
177	call	Convert
178
179  .assert "adresh == 0xff, 'Failed 16F819 a2d AN0=5V'"
180	nop
181
182
183  .command "V1.voltage=1.0"
184
185	call	Convert
186
187  .assert "adresh == 0x33, 'Failed 16F819 a2d AN0=1V'"
188	nop
189	;;
190	;; Now let's use the external analog signal connected to AN3
191	;; as the voltage reference
192
193	bsf	STATUS,RP0
194	movlw	1<<PCFG0
195	movwf	ADCON1 ^ 0x80
196	bcf	STATUS,RP0
197
198  .command "V2.voltage=2.0"
199
200	call	Convert
201  .assert "adresh == 0x80, 'Failed 16F819 a2d AN0=1V Vref+=2V'"
202	nop
203
204  .assert  "'*** PASSED 16F819 a2d test'"
205
206	goto	$-1
207
208
209
210Convert:
211
212	clrf	t1		;flag set by the interrupt routine
213
214	bsf	ADCON0,GO	;Start the A/D conversion
215
216	btfss	t1,0		;Wait for the interrupt to set the flag
217	 goto	$-1
218
219        movf    ADRESH,W                ;Read the high 8-bits of the result
220
221
222	return
223
224	end
225