1
2	list	p=18f26k22
3        include <p18f26k22.inc>
4        include <coff.inc>
5
6    CONFIG WDTEN=OFF, PBADEN = OFF
7
8	;; The purpose of this program is to test gpsim's ability to simulate a
9        ;; pic with more than two PWM channels. The 18F26k22 is such a device.
10
11        ;; CCP1 is set with a 50% duty cycle and used to test timing
12        ;; CCP2 is set with a 25% duty cycle and used to test order
13        ;; CCP3 is set with a 75% duty cycle
14        ;; CCP4 is set beyond the period and tied to INT0 to test 100% duty
15        ;; CCP5 is set with a 75% duty cycle to test two simultaneous PWM edges
16
17        errorlevel -302
18
19; Printf Command
20.command macro x
21  .direct "C", x
22  endm
23
24;----------------------------------------------------------------------
25;----------------------------------------------------------------------
26;GPR_DATA                UDATA
27GPR_DATA                UDATA 0
28
29t0_1 RES 1
30t0_2 RES 1
31x  RES  1
32t1 RES  1
33t2 RES  1
34avg_lo RES  1
35avg_hi RES  1
36w_temp RES  1
37status_temp RES  1
38
39
40;----------------------------------------------------------------------
41;   ********************* RESET VECTOR LOCATION  ********************
42;----------------------------------------------------------------------
43RESET_VECTOR  CODE    0x000              ; processor reset vector
44        goto   start                     ; go to beginning of program
45
46INTERRUPT     CODE    0x008
47	;;
48	;; Interrupt
49	;;
50	movwf	w_temp
51	swapf	STATUS,W
52	movwf	status_temp
53
54  .assert "'*** FAILED 18f26k22 unexpected interrupt'"
55	nop
56
57check:
58	swapf	status_temp,w
59	movwf	STATUS
60	swapf	w_temp,F
61	swapf	w_temp,W
62	retfie
63
64
65
66
67   .sim "node pwm3"
68  .sim "attach pwm3 portb5 portb1"
69  .sim "scope.ch0 = 'portc2'"
70  .sim "scope.ch1 = 'portc1'"
71  .sim "scope.ch2 = 'portb5'"
72  .sim "scope.ch3 = 'portb0'"
73
74;----------------------------------------------------------------------
75;   ******************* MAIN CODE START LOCATION  ******************
76;----------------------------------------------------------------------
77MAIN    CODE
78start:
79    BANKSEL CCP1CON
80    clrf    ANSELA
81    clrf    ANSELC
82    clrf   CCP1CON       ;  CCP Module is off
83    clrf   CCP2CON       ;  CCP Module is off
84    clrf   CCP3CON       ;  CCP Module is off
85    clrf   CCP4CON       ;  CCP Module is off
86    clrf   CCP5CON       ;  CCP Module is off
87    clrf   TMR2          ;  Clear Timer2
88    clrf   TMR0L         ;  Clear Timer0
89    movlw  0x1F          ;
90    movwf  CCPR1L        ;  CCP1 Duty Cycle is 50% of PWM Period
91    movlw  0x0F          ;
92    movwf  CCPR2L        ;  CCP2 Duty Cycle is 25% of PWM Period
93    movlw  0x4F          ;
94    movwf  CCPR3L        ;  CCP3 Duty Cycle is 125% of PWM Period
95    movlw  0x2F          ;
96    movwf  CCPR4L        ;  CCP4 Duty Cycle is 75% of PWM Period
97    movlw  0x2F          ;
98    movwf  CCPR5L        ;  CCP5 Duty Cycle is 75% of PWM Period
99    clrf   INTCON        ;  Disable interrupts and clear T0IF
100    clrf   INTCON2       ;  external interrupt pins trigger on falling edge
101    movlw  0x3F          ;
102    movwf  PR2           ;
103    bcf    TRISC, 2      ;  Make pin output CCP1
104    bcf    TRISC, 1      ;  Make pin output CCP2
105    bcf    TRISB, 5      ;  Make pin output CCP3
106    bcf    TRISB, 0      ;  Make pin output CCP4
107    bcf    TRISA, 4      ;  Make pin output CCP5
108    clrf   PIE1          ;  Disable peripheral interrupts
109    movlw  0x83		 ; Tmr0 internal clock prescaler 16
110    movwf  T0CON
111    clrf   PIR1          ;  Clear peripheral interrupts Flags
112    movlw  0x2C          ;  PWM mode, 2 LSbs of Duty cycle = 10
113    movwf  CCP1CON       ;
114    movlw  0x2C          ;  PWM mode, 2 LSbs of Duty cycle = 10
115    movwf  CCP2CON       ;
116    movwf  CCP3CON       ;
117    movwf  CCP4CON       ;
118    movwf  CCP5CON       ;
119  .assert "ccpr1l != ccpr1h, '*** FAILED pwm_26k22 CCPR1H before TMR2 reset'"
120    nop
121    movlw  0x06		 ; Start Timer2 prescaler is 16 (to match TMR0)
122    movwf  T2CON
123;
124; The CCP1 interrupt is disabled,
125; do polling on the TMR2 Interrupt flag bit
126;
127PWM_Period_Match
128    btfss  PIR1, TMR2IF
129    goto   PWM_Period_Match
130    clrf   TMR0L
131
132  .assert "ccpr1l == ccpr1h, '*** FAILED pwm_26k22 CCPR1H loaded from CCPR1H'"
133    nop
134
135 bcf    INTCON3,INT1IF       ; INT1 is tied to CCP3, which should remain always high
136
137  .assert "(portc & 0x6) == 0x6, '*** FAILED pwm_26k22 CCP1, CCP2 are high'"
138   nop
139   ; loop until CCP2 goes low
140   btfsc  PORTC,1
141   goto   $-1
142  .assert "tmr0 == 0x0f, '*** FAILED pwm_26k22 CCP2 duty cycle'"
143   nop
144   ; loop until CCP1 goes low
145   btfsc  PORTC,2
146   goto   $-1
147  .assert "tmr0 == 0x1f, '*** FAILED pwm_26k22 CCP1 duty cycle'"
148   nop
149   ; loop until CCP4 goes low
150   btfsc  PORTB,0
151   goto   $-1
152  .assert "tmr0 == 0x2f, '*** FAILED pwm_26k22 CCP3 duty cycle'"
153   nop
154;
155; Wait for end of PWM cycle
156;
157    bcf    PIR1, TMR2IF
158    btfss  PIR1, TMR2IF
159    goto   $-1
160
161  .assert "(intcon3 & 0x01) == 0, '*** FAILED pwm_26k22 PWM duty > PR2 : pin goes low'"
162   nop
163  .assert "tmr0 == 0x3f, '*** FAILED pwm_26k22 TMR2 period'"
164   nop
165;
166; Increase  TMR2 but less than first duty cycle
167;
168    movlw   0x0D
169    movwf   TMR2	; update timer
170    clrf   TMR0L
171
172   ; loop until CCP1 goes low
173    btfsc   PORTC,2
174    goto    $-1
175
176  .assert "(portc & 0x6) == 0x0, '*** FAILED pwm_26k22 TMR2 put, only change period'"
177    nop
178
179   ; loop until CCP5 goes low
180    btfsc   PORTA,4
181    goto    $-1
182
183  .assert "tmr0 == 0x22, '*** FAILED pwm_26k22 TMR2 put, only change period'"
184    nop
185
186    bcf    PIR1, TMR2IF
187    btfss  PIR1, TMR2IF
188    goto   $-1
189  .assert "tmr0 == 0x33, '*** FAILED pwm_26k22 TMR2 put, only change period'"
190    nop
191;
192; Increase  TMR2 between first and second duty cycle
193;
194    clrf   TMR0L
195
196    movlw   0x1D
197    movwf   TMR2	; update timer
198
199   ; loop until CCP1 goes low
200    btfsc   PORTC,2
201    goto    $-1
202
203  .assert "(portc & 0x6) == 0x2, '*** FAILED pwm_26k22 TMR2 put, between duty cycles'"
204    nop
205
206    bcf    PIR1, TMR2IF
207    btfss  PIR1, TMR2IF
208    goto   $-1
209  .assert "tmr0 == 0x23, '*** FAILED pwm_26k22 TMR2 put, between duty cycles'"
210    nop
211;
212;  in this test TMR2 > PR2, expect TMR2 to wrap around
213;
214    movlw  0x84		 ; Tmr0 internal clock prescaler 32
215    movwf  T0CON
216    clrf   TMR0L
217
218    movlw   0x40
219    movwf   TMR2	; update timer
220
221   ; loop until CCP1 goes low
222    btfsc  PORTC,2
223    goto   $-1
224  .assert "tmr0 == 0x6F, '*** FAILED pwm_26k22 CCP1 duty cycle after wrap'"
225    nop
226
227    bcf    PIR1, TMR2IF
228    btfss  PIR1, TMR2IF
229    goto   $-1
230
231  .assert "tmr0 == 0x80, '*** FAILED pwm_26k22 TMR2 > PR2 causes wrap'"
232    nop
233
234;
235; write reduced PR2
236;
237   clrf   TMR0L
238
239   ; loop until CCP2 goes low
240   btfsc  PORTC,1
241   goto   $-1
242  .assert "tmr0 == 0x07, '*** FAILED pwm_26k22 CCP2 duty cycle PR2 to 0x20'"
243   nop
244   ; loop until CCP1 goes low
245   btfsc  PORTC,2
246   goto   $-1
247  .assert "tmr0 == 0x0f, '*** FAILED pwm_26k22 CCP1 duty cycle PR2 to 0x20'"
248   nop
249    movlw  0x20
250    movwf  PR2
251;
252; Wait for end of PWM cycle
253;
254    bcf    PIR1, TMR2IF
255    btfss  PIR1, TMR2IF
256    goto   $-1
257  .assert "tmr0 == 0x10, '*** FAILED pwm_26k22 TMR2 period PR2 to 0x20'"
258   nop
259
260;
261; write reduced PR2 < TRM2
262;
263   clrf   TMR0L
264
265   ; loop until CCP2 goes low
266   btfsc  PORTC,1
267   goto   $-1
268  .assert "tmr0 == 0x07, '*** FAILED pwm_26k22 CCP2 duty cycle PR2 to 0x10'"
269   nop
270   ; loop until CCP1 goes low
271   btfsc  PORTC,2
272   goto   $-1
273  .assert "tmr0 == 0x0f, '*** FAILED pwm_26k22 CCP1 duty cycle PR2 to 0x10'"
274   nop
275    movlw  0x10
276    movwf  PR2
277;
278; Wait for end of PWM cycle
279;
280    bcf    PIR1, TMR2IF
281    btfss  PIR1, TMR2IF
282    goto   $-1
283  .assert "tmr0 == 0x88, '*** FAILED pwm_26k22 TMR2 period PR2 to 0x10 wraps'"
284   nop
285
286    clrf  CCP1CON       ; turn off PWM
287    clrf  CCP2CON       ; turn off PWM
288    clrf  CCP3CON       ; turn off PWM
289    clrf  CCP4CON       ; turn off PWM
290    clrf  CCP5CON       ; turn off PWM
291
292    call  use_t4
293
294
295  .assert "'*** PASSED pwm_26k22 PWM test'"
296	goto $-1
297
298use_t4:
299    movlw  0x0f		; set CCP2 outputs to all pins
300    movwf  PSTR2CON
301    bsf    CCPTMRS0,C2TSEL0	; select T4 for CCP2
302    movlw  0x3F          ;
303    movwf  PR4           ;
304    movlw  0x1F          ;
305    movwf  CCPR2L        ;  Duty Cycle is 50% of PWM Period
306    movlw  0x06		 ; Start Timer4 prescaler is 16 (to match TMR0, of course!)
307    clrf   T2CON	 ; turn off T2
308    movwf  T4CON
309    movlw  0x2C          ;  PWM mode, 2 LSbs of Duty cycle = 10
310    movwf  CCP2CON       ;
311   ; loop until CCP2 goes low
312    btfsc   PORTC,1
313    goto    $-1
314
315    return
316	end
317