-
Notifications
You must be signed in to change notification settings - Fork 0
/
sonic_sevensegment.asm
499 lines (402 loc) · 10 KB
/
sonic_sevensegment.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
; PIC16F628A Configuration Bit Settings
; ASM source line config statements
#include "p16F628A.inc"
; CONFIG
; __config 0x3F70
__CONFIG _FOSC_INTOSCIO & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _CPD_OFF & _CP_OFF
#define NUMBER_0 b'01110111'
#define NUMBER_1 b'00010100'
#define NUMBER_2 b'10110011'
#define NUMBER_3 b'10110110'
#define NUMBER_4 b'11010100'
#define NUMBER_5 b'11100110'
#define NUMBER_6 b'11100111'
#define NUMBER_7 b'00110100'
#define NUMBER_8 b'11110111'
#define NUMBER_9 b'11110110'
#define NUMBER_ERR b'11110000'
; RB0 is data
; RB1 is shift register commit
; RB2 is data clock shift register 1
; RB4 is data clock shift register 3
; RB5 is data clock shift register 2
cblock 0x20
w_temp ;0x20
status_temp ;0x21
led1_value ;0x22
led2_value ;0x23
led3_value ;0x24
write_sevensegment_parameter ;0x25
segment_tmp ;0x26
update_led_parameter ;0x27
current_led ;0x28
led_value_tmp ;0x29
tmr1_h_tmp ;0x2A
tmr1_l_tmp ;0x2B
tmr1_decr_tmp ;0x2C
tmr0_int_ignore ;0x2D
endc
org 0x000
goto prepare
; Interrupt handler
org 0x004
goto interrupt_handler
; *** Write a number to a shift register ***
; 1. Parameter: current_led - Select the shiftregister
; 2. Parameter: write_sevensegment_parameter - The value
write_sevensegment:
movlw 8
movwf segment_tmp
write_sevensegment_start:
bcf PORTB,0
rlf write_sevensegment_parameter,F
btfsc STATUS,C
bsf PORTB,0
; Clock shift register commit
btfsc current_led,0
goto write_sevensegment_led1
btfsc current_led,1
goto write_sevensegment_led2
btfsc current_led,2
goto write_sevensegment_led3
write_sevensegment_led1:
bsf PORTB,5
nop
nop
nop
bcf PORTB,5
goto write_sevensegment_continue
write_sevensegment_led2:
bsf PORTB,2
nop
nop
nop
bcf PORTB,2
goto write_sevensegment_continue
write_sevensegment_led3:
bsf PORTB,4
nop
nop
nop
bcf PORTB,4
goto write_sevensegment_continue
write_sevensegment_continue:
decfsz segment_tmp, f
goto write_sevensegment_start
bcf PORTB,0
; Make the changes in the shift register visible
bsf PORTB,1
nop
nop
nop
bcf PORTB,1
return
; *** Increment the number of led3 ***
increment_led_value3:
clrf led2_value
incf led3_value,F
movfw led3_value
movwf led_value_tmp
movlw d'10'
subwf led_value_tmp,W
; Handle overflow
btfsc STATUS,Z
call reset_led_counters
return
; *** Increment the number of led2 ***
increment_led_value2:
clrf led1_value
incf led2_value,F
movfw led2_value
movwf led_value_tmp
movlw d'10'
subwf led_value_tmp,W
; Handle overflow
btfsc STATUS,Z
call increment_led_value3
return
; *** Increment the number of led1 ***
increment_led_value1:
incf led1_value,F
movfw led1_value
movwf led_value_tmp
movlw d'10'
subwf led_value_tmp,W
; Handle overflow
btfsc STATUS,Z
call increment_led_value2
return
; *** Update the value of one led ***
; 1. Parameter update_led_parameter - the new value
; 2. Parameter: current_led - Select the shiftregister
update_led:
movfw update_led_parameter
xorlw d'0'
btfss STATUS,Z
goto $+3
movlw NUMBER_0
goto write_led_end
movfw update_led_parameter
xorlw d'1'
btfss STATUS,Z
goto $+3
movlw NUMBER_1
goto write_led_end
movfw update_led_parameter
xorlw d'2'
btfss STATUS,Z
goto $+3
movlw NUMBER_2
goto write_led_end
movfw update_led_parameter
xorlw d'3'
btfss STATUS,Z
goto $+3
movlw NUMBER_3
goto write_led_end
movfw update_led_parameter
xorlw d'4'
btfss STATUS,Z
goto $+3
movlw NUMBER_4
goto write_led_end
movfw update_led_parameter
xorlw d'5'
btfss STATUS,Z
goto $+3
movlw NUMBER_5
goto write_led_end
movfw update_led_parameter
xorlw d'6'
btfss STATUS,Z
goto $+3
movlw NUMBER_6
goto write_led_end
movfw update_led_parameter
xorlw d'7'
btfss STATUS,Z
goto $+3
movlw NUMBER_7
goto write_led_end
movfw update_led_parameter
xorlw d'8'
btfss STATUS,Z
goto $+3
movlw NUMBER_8
goto write_led_end
movfw update_led_parameter
xorlw d'9'
btfss STATUS,Z
goto $+3
movlw NUMBER_9
goto write_led_end
; Not a known number
movlw NUMBER_ERR
write_led_end:
movwf write_sevensegment_parameter
call write_sevensegment
return
; *** Set all led counters to 0 ***
reset_led_counters:
clrf led1_value
clrf led2_value
clrf led3_value
return
; *** Prepare the application ***
prepare:
clrf PORTB ; Reset all pins on PORTB
clrf PORTA ; Reset all pins on PORTA
call reset_led_counters
banksel TRISB
movlw b'11001000'
movwf TRISB
banksel TRISA
bcf TRISA,0 ; RA0 is output
banksel TMR0 ; Prepare Timer0
clrf TMR0
bcf INTCON,T0IF
; Prescaler
banksel OPTION_REG
bsf OPTION_REG,0
bsf OPTION_REG,1
bsf OPTION_REG,2
; Options
bcf OPTION_REG,3
bcf OPTION_REG,4
bcf OPTION_REG,5
banksel T1CON ; Prepare Timer1
bcf PIR1,TMR1IF
movlw b'00100001' ; Prescale 4, internal clock, timer active
movwf T1CON
; Handle TMR0 interrupt again
movlw d'0'
movwf tmr0_int_ignore
; Enable interrupts
banksel INTCON
bsf INTCON,T0IE
bsf INTCON,PEIE
bsf INTCON,GIE
; Enable CCP interupts
banksel PIE1
bsf PIE1,CCP1IE
banksel RA0
goto main
; *** Main - Loop forever ***
main:
goto main
; *** Prepare the CCP module ***
prepare_ccp:
banksel CCP1CON ; Prepare CCP
bcf CCP1CON,3
bsf CCP1CON,2
bcf CCP1CON,1
bsf CCP1CON,0
; Ignore TMR0 interrupts 25 times
; This ensures, that no new sonic measurements are prepared during
; the next moments.
;
; In normal operation, the interrupts will made available
; at the end of the mesasurement cycle. When the sensor
; does not capture a result, the timer deceases to '0'
; and the next TMR0 interrupt will trigger a new mesasurement cycle.
movlw d'25'
movwf tmr0_int_ignore
return
ccp_int_waiting:
banksel CCP1CON ; Prepare CCP
bcf CCP1CON,0
bcf PIR1,CCP1IF
; Reset TMR1 counter
banksel T1CON ; Prepare Timer1
clrf TMR1L
clrf TMR1H
return
increment_low_tmr:
movlw b'11111111'
movwf tmr1_l_tmp
decf tmr1_h_tmp,f
goto ccp_int_received_decrement_low
; *** Convert and display the ultrasoic measurement ***
ccp_int_received:
; Store a copy of tmr1 value at CCP capture.
movfw CCPR1L
movwf tmr1_l_tmp
movfw CCPR1H
movwf tmr1_h_tmp
call reset_led_counters
; Convert timer into cm
; Object: 100 cm
; Sonic 2x100cm = 200cm
; speed of sound 330 m/s
; 2/330 = 0,0060 seconds
; 250.000 Timer values per sec
; TMR0 will capture a value of 1515
; 100 * 15 = 1500 (we need to devide the result by 15)
ccp_int_received_decrement_low:
movlw d'15'
movwf tmr1_decr_tmp
ccp_int_received_decrement_low2:
movfw tmr1_l_tmp
btfsc STATUS,Z
goto ccp_int_received_low_end
decf tmr1_l_tmp,f
decfsz tmr1_decr_tmp,f
goto ccp_int_received_decrement_low2
call increment_led_value1
goto ccp_int_received_decrement_low
ccp_int_received_low_end:
; Check high bit (if not empty, decrement and set low to 255)
movfw tmr1_h_tmp
btfss STATUS,Z
goto increment_low_tmr
; Enable TMR0 interrupts
movlw d'0'
movwf tmr0_int_ignore
return
; *** Start a new ultrasonic measurement ***
send_sonic:
bsf PORTA,0
; >= 10 nops to set PORTA,0 for 10 micro seconds to high
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
bcf PORTA,0
return
; *** The interrupt handler ***
interrupt_handler:
movwf w_temp ; Save w register
swapf STATUS,w ; STATUS -> w
bcf STATUS,RP0 ; Switch to bank0
movwf status_temp ; w -> status_temp
; Handle TMR0 Interrupt
banksel INTCON
btfsc INTCON,TMR0IF
call tmr0_int
; Handle CCP Interrupt
banksel PIR1
btfsc PIR1,CCP1IF
call ccp1_int
; return from interrupt
banksel INTCON
bcf INTCON, INTF
swapf status_temp,w ; Restore status
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie
; *** Handle CCP interrupts ***
ccp1_int:
banksel PIR1
bcf PIR1,CCP1IF
btfss CCP1CON,0
call ccp_int_received
btfsc CCP1CON,0
call ccp_int_waiting
return
; *** Handle TMR0 interrupts ***
tmr0_int:
banksel INTCON
bcf INTCON,TMR0IF
; Decrease tmr0_int_ignore if > 0
; if > 0 = We are inside a measurement cycle
; Skip LED update and preparement of a
; new measurement cycle
movfw tmr0_int_ignore
btfsc STATUS,Z
goto $+3
decf tmr0_int_ignore, f ; $+1
return ; $+2
; Update led1 to new value
movlw b'00000001'
movwf current_led
movfw led1_value
movwf update_led_parameter
call update_led
; Update led2 to new value
movlw b'00000010'
movwf current_led
movfw led2_value
movwf update_led_parameter
call update_led
; Update led3 to new value
movlw b'00000100'
movwf current_led
movfw led3_value
movwf update_led_parameter
call update_led
; Start new ultrasonic measurement
call send_sonic
; Prepare ccp module to capture rising edge of the echo port
call prepare_ccp
return
;--------End of All Code Sections ---------------------------------------------
end ;End of program code in this file