OpenCores
URL https://opencores.org/ocsvn/copyblaze/copyblaze/trunk

Subversion Repositories copyblaze

[/] [copyblaze/] [trunk/] [copyblaze/] [sw/] [code/] [kcpsm/] [uclock/] [uclock.psm] - Blame information for rev 61

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ameziti
                        ;KCPSM3 Program - Real Time Clock with UART communication.
2
                        ;
3
                        ;Ken Chapman - Xilinx Ltd - October 2003
4
                        ;
5
                        ;
6
                        ;Port definitions
7
                        ;
8
                        CONSTANT UART_status_port, 00            ;UART status input
9
                        CONSTANT tx_half_full, 01                ;  Transmitter     half full - bit0
10
                        CONSTANT tx_full, 02                     ;    FIFO               full - bit1
11
                        CONSTANT rx_half_full, 04                ;  Receiver        half full - bit2
12
                        CONSTANT rx_full, 08                     ;    FIFO               full - bit3
13
                        CONSTANT rx_data_present, 10             ;               data present - bit4
14
                        ;
15
                        CONSTANT UART_read_port, 01              ;UART Rx data input
16
                        ;
17
                        CONSTANT UART_write_port, 01             ;UART Tx data output
18
                        ;
19
                        CONSTANT alarm_port, 00                  ;Alarm output
20
                        CONSTANT alarm_control, 01               ;     bit0
21
                        ;
22
                        ;Special Register usage
23
                        ;
24
                        NAMEREG sF, UART_data                    ;used to pass data to and from the UART
25
                        ;
26
                        NAMEREG sE, store_pointer                ;used to pass location of data in scratch pad memory
27
                        ;
28
                        ;Two registers to form a 16-bit counter used to count
29
                        ;interrupt pulses generated at 1us intervals.
30
                        ;
31
                        NAMEREG sD, int_counter_lsb              ;lower 8-bits
32
                        NAMEREG sC, int_counter_msb              ;upper 8-bits
33
                        ;
34
                        ;
35
                        ;Scratch Pad Memory Locations
36
                        ;
37
                        ;
38
                        CONSTANT us_time_stamp_lsb, 00           ;16-bit micro-second time stamp
39
                        CONSTANT us_time_stamp_msb, 01
40
                        ;
41
                        CONSTANT us_time_lsb, 02                 ;16-bit micro-second real time value
42
                        CONSTANT us_time_msb, 03
43
                        ;
44
                        CONSTANT ms_time_lsb, 04                 ;16-bit milli-second real time value
45
                        CONSTANT ms_time_msb, 05
46
                        ;
47
                        CONSTANT real_time_hours, 06             ;Current clock time
48
                        CONSTANT real_time_minutes, 07
49
                        CONSTANT real_time_seconds, 08
50
                        ;
51
                        CONSTANT alarm_time_hours, 09            ;Alarm time
52
                        CONSTANT alarm_time_minutes, 0A
53
                        CONSTANT alarm_time_seconds, 0B
54
                        ;
55
                        CONSTANT alarm_status, 0C                ;Alarm status
56
                        CONSTANT alarm_active, 01                ;    bit0 - Alarm is active
57
                        CONSTANT alarm_armed, 02                 ;    bit1 - Alarm is armed
58
                        ;
59
                        CONSTANT time_preserve0, 10              ;storage for protection of registers
60
                        CONSTANT time_preserve1, 11              ;used by the real time clock routine.
61
                        CONSTANT time_preserve2, 12
62
                        CONSTANT time_preserve3, 13
63
                        CONSTANT time_preserve4, 14
64
                        CONSTANT time_preserve5, 15
65
                        ;
66
                        ;UART character strings will be stored in scratch pad memory ending in carriage return.
67
                        ;A string can be up to 16 characters with the start location defined by this constant.
68
                        ;
69
                        CONSTANT string_start, 20
70
                        ;
71
                        ;
72
                        ;Initialise the system
73
                        ;
74
                        ;
75
            cold_start: LOAD s0, 00                              ;clear all time values
76
                        STORE s0, us_time_stamp_lsb
77
                        STORE s0, us_time_stamp_msb
78
                        STORE s0, us_time_lsb
79
                        STORE s0, us_time_msb
80
                        STORE s0, ms_time_lsb
81
                        STORE s0, ms_time_msb
82
                        STORE s0, real_time_hours
83
                        STORE s0, real_time_minutes
84
                        STORE s0, real_time_seconds
85
                        STORE s0, alarm_time_hours
86
                        STORE s0, alarm_time_minutes
87
                        STORE s0, alarm_time_seconds
88
                        STORE s0, alarm_status                   ;clear and disable alarm
89
                        CALL alarm_drive                         ;turn off alarm control output port
90
                        LOAD int_counter_lsb, 00                 ;clear 'us' interrupt counter
91
                        LOAD int_counter_msb, 00
92
                        ENABLE INTERRUPT                         ;enable the 1us interrupts
93
                        ;
94
                        ;
95
                        ;Start of the main program loop.
96
                        ;
97
                        ;A prompt is transmitted to the UART transmitter and then
98
                        ;a command can be entered and interpreted.
99
                        ;
100
                        ;
101
          prompt_input: CALL send_prompt                         ;Prompt 'KCPSM3>'
102
                        CALL receive_string                      ;obtain input string and maintain the time
103
                        ;
104
                        ;
105
                        ;Parse the string and perform actions as required
106
                        ;
107
                        ;
108
                        ;
109
                        LOAD s1, string_start
110
                        CALL fetch_char_from_memory
111
                        COMPARE s0, character_CR                 ;carriage return does nothing
112
                        JUMP Z, prompt_input
113
                        COMPARE s0, character_T                  ;start of 'TIME' command?
114
                        JUMP Z, test_for_TIME
115
                        COMPARE s0, character_A                  ;start of 'ALARM' command?
116
                        JUMP Z, test_for_ALARM
117
                        ;
118
                        ;trap other command starts here
119
                        ;
120
     bad_input_command: CALL send_Syntax_Error                   ;no valid command
121
                        JUMP Z, prompt_input
122
                        ;
123
                        ;
124
         test_for_TIME: CALL fetch_char_from_memory
125
                        COMPARE s0, character_I                  ;test for rest of 'TIME'
126
                        JUMP NZ, bad_input_command
127
                        CALL fetch_char_from_memory
128
                        COMPARE s0, character_M
129
                        JUMP NZ, bad_input_command
130
                        CALL fetch_char_from_memory
131
                        COMPARE s0, character_E
132
                        JUMP NZ, bad_input_command
133
                        ;now have a valid TIME command to process
134
                        CALL fetch_char_from_memory
135
                        COMPARE s0, character_CR                 ;carriage return means display time
136
                        JUMP NZ, set_time_command
137
                        CALL transmit_time                       ;transmit time to UART
138
                        JUMP prompt_input
139
      set_time_command: COMPARE s0, character_space
140
                        JUMP NZ, bad_input_command
141
                        CALL test_time_string                    ;interpret 'hh:mm:ss' string
142
                        JUMP C, prompt_input                     ;test for invalid input
143
                        STORE s6, real_time_hours                ;set new time into clock
144
                        STORE s5, real_time_minutes
145
                        STORE s4, real_time_seconds
146
                        STORE s0, ms_time_lsb                    ;clear 'ms' counter (s0=00)
147
                        STORE s0, ms_time_msb
148
                        CALL transmit_time                       ;transmit new time to UART
149
                        JUMP prompt_input
150
                        ;
151
                        ;
152
        test_for_ALARM: CALL fetch_char_from_memory
153
                        COMPARE s0, character_L                  ;test for rest of 'ALARM'
154
                        JUMP NZ, bad_input_command
155
                        CALL fetch_char_from_memory
156
                        COMPARE s0, character_A
157
                        JUMP NZ, bad_input_command
158
                        CALL fetch_char_from_memory
159
                        COMPARE s0, character_R
160
                        JUMP NZ, bad_input_command
161
                        CALL fetch_char_from_memory
162
                        COMPARE s0, character_M
163
                        JUMP NZ, bad_input_command
164
                        ;now have a valid ALARM command to process
165
                        CALL fetch_char_from_memory
166
                        COMPARE s0, character_CR                 ;carriage return means display alarm time
167
                        JUMP NZ, set_alarm_command
168
                        CALL transmit_alarm_time                 ;transmit time to UART
169
                        JUMP prompt_input
170
     set_alarm_command: COMPARE s0, character_space              ;test for ON or OFF command
171
                        JUMP NZ, bad_input_command
172
                        CALL fetch_char_from_memory
173
                        COMPARE s0, character_O
174
                        JUMP Z, set_alarm_on_off
175
                        SUB s1, 01                               ;move memory pointer back to first character of 'hh:mm:ss' string
176
                        CALL test_time_string                    ;interpret 'hh:mm:ss' string
177
                        JUMP C, prompt_input                     ;test for invalid input
178
                        STORE s6, alarm_time_hours               ;set new time into clock
179
                        STORE s5, alarm_time_minutes
180
                        STORE s4, alarm_time_seconds
181
                        CALL transmit_alarm_time                 ;transmit new alarm time and status
182
                        JUMP prompt_input
183
      set_alarm_on_off: CALL fetch_char_from_memory
184
                        COMPARE s0, character_N                  ;test for 'ON'
185
                        JUMP NZ, test_OFF
186
                        CALL fetch_char_from_memory
187
                        COMPARE s0, character_CR
188
                        JUMP NZ, bad_input_command
189
                        FETCH s0, alarm_status                   ;turn alarm on
190
                        OR s0, alarm_armed
191
                        STORE s0, alarm_status
192
                        CALL transmit_alarm_time                 ;transmit alarm time and status
193
                        JUMP prompt_input
194
              test_OFF: COMPARE s0, character_F                  ;test for for 'OFF'
195
                        JUMP NZ, bad_input_command
196
                        CALL fetch_char_from_memory
197
                        COMPARE s0, character_F
198
                        JUMP NZ, bad_input_command
199
                        CALL fetch_char_from_memory
200
                        COMPARE s0, character_CR
201
                        JUMP NZ, bad_input_command
202
                        LOAD s0, 00                              ;turn alarm off and stop an active alarm
203
                        STORE s0, alarm_status
204
                        CALL alarm_drive                         ;turn off alarm
205
                        CALL transmit_alarm_time                 ;transmit alarm time and status
206
                        JUMP prompt_input
207
                        ;
208
                        ;
209
                        ;
210
                        ;
211
                        ;Read an 'hh:mm:ss' time string and provide new values.
212
                        ;
213
                        ;The string must be provided in successive scratch pad memory locations
214
                        ;with the s1 register containing the location of the first character.
215
                        ;
216
                        ;A correct time specification will result in the return of new values
217
                        ;as follows:-
218
                        ;
219
                        ;       s6 = hours
220
                        ;       s5 = minutes
221
                        ;       s4 = seconds
222
                        ;
223
                        ;If the syntax is incorrect or values are not in the correct ranges an
224
                        ;'Invalid Time' message will be transmitted and the CARRY flag will be set
225
                        ;
226
                        ;Registers used s0, s1, s6, s5 and s4
227
                        ;
228
      test_time_string: CALL 2char_to_value                      ;obtain hours value
229
                        JUMP C, invalid_time                     ;test for non-decimal characters
230
                        LOAD s6, s2                              ;remember hours
231
                        ADD s1, 01                               ;increment memory pointer past hours
232
                        CALL fetch_char_from_memory
233
                        COMPARE s0, character_colon              ;test for colon
234
                        JUMP NZ, invalid_time
235
                        CALL 2char_to_value                      ;obtain minutes value
236
                        JUMP C, invalid_time                     ;test for non-decimal characters
237
                        LOAD s5, s2                              ;remember minutes
238
                        ADD s1, 01                               ;increment memory pointer past minutes
239
                        CALL fetch_char_from_memory
240
                        COMPARE s0, character_colon              ;test for colon
241
                        JUMP NZ, invalid_time
242
                        CALL 2char_to_value                      ;obtain seconds value
243
                        JUMP C, invalid_time                     ;test for non-decimal characters
244
                        LOAD s4, s2                              ;remember minutes
245
                        ADD s1, 01                               ;increment memory pointer past seconds
246
                        CALL fetch_char_from_memory
247
                        COMPARE s0, character_CR                 ;finish with carriage return
248
                        JUMP NZ, invalid_time
249
                        ;Have values for hh:mm:ss but need to test if each is valid range.
250
                        COMPARE s6, hours_in_a_day
251
                        JUMP NC, invalid_time
252
                        COMPARE s5, minutes_in_an_hour
253
                        JUMP NC, invalid_time
254
                        COMPARE s4, seconds_in_a_minute
255
                        JUMP NC, invalid_time
256
                        LOAD s0, 00
257
                        SR0 s0                                   ;reset CARRY flag (with s0=0)
258
                        RETURN                                   ;time string was OK
259
          invalid_time: CALL send_Invalid
260
                        CALL send_space
261
                        CALL send_Time
262
                        LOAD s0, 01
263
                        SR0 s0                                   ;set CARRY flag
264
                        RETURN                                   ;time string was bad
265
                        ;
266
                        ;
267
                        ;Fetch character from memory, convert to upper case
268
                        ;and increment memory pointer.
269
                        ;
270
                        ;The memory pointer is provided in register s1.
271
                        ;The character obtained is returned in register s0.
272
                        ;
273
                        ;Registers used s0 and s1.
274
                        ;
275
fetch_char_from_memory: FETCH s0, (s1)                           ;read character
276
                        CALL upper_case                          ;convert to upper case
277
                        ADD s1, 01                               ;increment memory pointer
278
                        RETURN
279
                        ;
280
                        ;
281
                        ;
282
                        ;Read one character from the UART
283
                        ;
284
                        ;Character read will be returned in a register called 'UART_data' and will be
285
                        ;echoed to the UART transmitter.
286
                        ;
287
                        ;The routine first tests the receiver FIFO buffer to see if data is present.
288
                        ;If the FIFO is empty, the routine waits until there is a character to read.
289
                        ;As this could take any amount of time the wait loop includes a call to the
290
                        ;subroutine which updates the real time clock.
291
                        ;
292
                        ;Registers used s0 and UART_data
293
                        ;
294
        read_from_UART: INPUT s0, UART_status_port               ;test Rx_FIFO buffer
295
                        TEST s0, rx_data_present
296
                        JUMP NZ, read_character
297
                        CALL update_time                         ;Perform useful operation whilst waiting
298
                        JUMP read_from_UART
299
        read_character: INPUT UART_data, UART_read_port          ;read from FIFO
300
                        CALL send_to_UART                        ;echo received character
301
                        RETURN
302
                        ;
303
                        ;
304
                        ;
305
                        ;Transmit one character to the UART
306
                        ;
307
                        ;Character supplied in register called 'UART_data'.
308
                        ;
309
                        ;The routine first tests the transmit FIFO buffer to see if it is full.
310
                        ;If the FIFO is full, the routine waits until there is space which could
311
                        ;be as long as it takes to transmit one complete character.
312
                        ;
313
                        ;    Baud Rate    Time per Character (10 bits)
314
                        ;      9600           1,024us
315
                        ;     19200             521us
316
                        ;     38400             260us
317
                        ;     57600             174us
318
                        ;    115200              87us
319
                        ;
320
                        ;Since this is a relatively long duration, the wait loop includes a
321
                        ;call to the subroutine which updates the real time clock.
322
                        ;
323
                        ;Registers used s0
324
                        ;
325
          send_to_UART: INPUT s0, UART_status_port               ;test Tx_FIFO buffer
326
                        TEST s0, tx_full
327
                        JUMP Z, UART_write
328
                        CALL update_time                         ;Perform useful operation whilst waiting
329
                        JUMP send_to_UART
330
            UART_write: OUTPUT UART_data, UART_write_port
331
                        RETURN
332
                        ;
333
                        ;
334
                        ;
335
                        ;
336
                        ;Alarm output
337
                        ;
338
                        ;Uses the alarm status scratch pad memory to set or reset the alarm
339
                        ;control bit on the alarm output port.
340
                        ;
341
                        ;Registers used s0
342
                        ;
343
           alarm_drive: FETCH s0, alarm_status                   ;read status
344
                        AND s0, alarm_active                     ;isolate bit0
345
                        OUTPUT s0, alarm_port
346
                        RETURN
347
                        ;
348
                        ;
349
                        ;
350
                        ;
351
                        ;
352
                        ;Transmit the time to the UART port in the format hh:mm:ss and end
353
                        ;with a carriage return.
354
                        ;
355
                        ;The time to converted must be stored in 3 scratch pad memory locations as
356
                        ;defined below. A register named 'store_pointer' must provide the address of
357
                        ;first location.
358
                        ;
359
                        ;        Address                Data
360
                        ;
361
                        ;     store_pointer      ----> hours
362
                        ;     store_pointer + 1  ----> minutes
363
                        ;     store_pointer + 1  ----> seconds
364
                        ;
365
                        ;The routine first converts the time into an ASCII string stored in scratch
366
                        ;pad memory starting at a location specified by a constant named 'string_start'.
367
                        ;The string will then be transmitted.
368
                        ;
369
                        ;Registers used s0, s1, s2, 'store_pointer' and 'UART_data'.
370
                        ;
371
         transmit_time: LOAD store_pointer, real_time_hours      ;locate current time in memory
372
                        CALL time_to_ASCII
373
                        CALL transmit_string
374
                        RETURN
375
                        ;
376
                        ;
377
                        ;Transmit the alarm time and status to the UART port in the format hh:mm:ss and
378
                        ;ending with carriage return.
379
                        ;
380
                        ;The alarm time to converted must be stored in 3 scratch pad memory locations as
381
                        ;defined below. A register named 'store_pointer' must provide the address of
382
                        ;first location.
383
                        ;
384
                        ;        Address                Data
385
                        ;
386
                        ;     store_pointer      ----> hours
387
                        ;     store_pointer + 1  ----> minutes
388
                        ;     store_pointer + 1  ----> seconds
389
                        ;
390
                        ;The routine first converts the time into an ASCII string stored in scratch
391
                        ;pad memory starting at a location specified by a constant named 'string_start'.
392
                        ;The string will then be transmitted.
393
                        ;
394
                        ;Registers used s0, s1, s2, 'store_pointer' and 'UART_data'.
395
                        ;
396
   transmit_alarm_time: LOAD store_pointer, alarm_time_hours     ;locate alarm time in memory
397
                        CALL time_to_ASCII
398
                        CALL transmit_string
399
                        CALL send_Alarm
400
                        CALL send_space
401
                        FETCH s0, alarm_status                   ;read alarm status
402
                        TEST s0, alarm_active                    ;test for active
403
                        JUMP Z, test_armed
404
                        CALL send_Active
405
                        RETURN
406
            test_armed: TEST s0, alarm_armed                     ;test for on
407
                        JUMP Z, alarm_is_off
408
                        CALL send_ON
409
                        RETURN
410
          alarm_is_off: CALL send_OFF
411
                        RETURN
412
                        ;
413
                        ;
414
                        ;Transmit ASCII string to UART
415
                        ;
416
                        ;An ASCII string must be provided in scratch pad memory commencing at the
417
                        ;location specified by a constant named 'string_start'. The string must
418
                        ;end with a carriage return (0D).
419
                        ;
420
                        ;Registers used s1 and 'UART_data'.
421
                        ;               s0 is then used in subroutine 'send_to_UART'
422
                        ;
423
       transmit_string: LOAD s1, string_start                    ;locate start of string
424
          next_char_tx: FETCH UART_data, (s1)                    ;read character from memory
425
                        CALL send_to_UART                        ;transmit character
426
                        COMPARE UART_data, character_CR          ;test for last character
427
                        RETURN Z
428
                        ADD s1, 01                               ;move to next character
429
                        JUMP next_char_tx
430
                        ;
431
                        ;
432
                        ;Receive ASCII string from UART
433
                        ;
434
                        ;An ASCII string will be read from the UART and stored in scratch pad memory
435
                        ;commencing at the location specified by a constant named 'string_start'.
436
                        ;The string will will have a maximum length of 16 characters including a
437
                        ;carriage return (0D) denoting the end of the string.
438
                        ;
439
                        ;As each character is read, it is echoed to the UART transmitter.
440
                        ;Some minor editing is supported using backspace (BS=08) which is used
441
                        ;to adjust what is stored in scratch pad memory and adjust the display
442
                        ;on the terminal screen using characters sent to the UART transmitter.
443
                        ;
444
                        ;A test is made for the receiver FIFO becoming full. A full status is treated as
445
                        ;a potential error situation and will result in a 'Overflow Error' message being
446
                        ;transmitted to the UART, the receiver FIFO being purged of all data and an
447
                        ;empty string being stored (carriage return at first location).
448
                        ;
449
                        ;Registers used s0, s1, s2 and 'UART_data'.
450
                        ;
451
        receive_string: LOAD s1, string_start                    ;locate start of string
452
                        LOAD s2, s1                              ;compute 16 character address
453
                        ADD s2, 10
454
     receive_full_test: INPUT s0, UART_status_port               ;test Rx_FIFO buffer for full
455
                        TEST s0, rx_full
456
                        JUMP NZ, read_error
457
                        CALL read_from_UART                      ;obtain and echo character
458
                        STORE UART_data, (s1)                    ;write to memory
459
                        COMPARE UART_data, character_CR          ;test for end of string
460
                        RETURN Z
461
                        COMPARE UART_data, character_BS          ;test for back space
462
                        JUMP Z, BS_edit
463
                        ADD s1, 01                               ;increment memory pointer
464
                        COMPARE s1, s2                           ;test for pointer exceeding 16 characters
465
                        JUMP NZ, receive_full_test               ;next character
466
                        CALL send_backspace                      ;hold end of string position on terminal display
467
               BS_edit: SUB s1, 01                               ;memory pointer back one
468
                        COMPARE s1, string_start                 ;test for under flow
469
                        JUMP C, string_start_again
470
                        CALL send_space                          ;clear character at current position
471
                        CALL send_backspace                      ;position cursor
472
                        JUMP receive_full_test                   ;next character
473
    string_start_again: CALL send_greater_than                   ;restore '>' at prompt
474
                        JUMP receive_string                      ;begin again
475
                        ;Receiver buffer overflow condition
476
            read_error: CALL send_CR                             ;Transmit error message
477
                        STORE UART_data, string_start            ;empty string in memory (start with CR)
478
                        CALL send_Overflow_Error
479
                        CALL send_CR
480
    clear_UART_Rx_loop: INPUT s0, UART_status_port               ;test Rx_FIFO buffer for data
481
                        TEST s0, rx_data_present
482
                        RETURN Z                                 ;finish when buffer is empty
483
                        INPUT UART_data, UART_read_port          ;read from FIFO and ignore
484
                        JUMP clear_UART_Rx_loop
485
                        ;
486
                        ;
487
                        ;
488
                        ;Send Carriage Return to the UART
489
                        ;
490
               send_CR: LOAD UART_data, character_CR
491
                        CALL send_to_UART
492
                        RETURN
493
                        ;
494
                        ;
495
                        ;
496
                        ;Send a space to the UART
497
                        ;
498
            send_space: LOAD UART_data, character_space
499
                        CALL send_to_UART
500
                        RETURN
501
                        ;
502
                        ;
503
                        ;Send a back space to the UART
504
                        ;
505
        send_backspace: LOAD UART_data, character_BS
506
                        CALL send_to_UART
507
                        RETURN
508
                        ;
509
                        ;Send 'Syntax Error' to the UART
510
                        ;
511
     send_Syntax_Error: LOAD UART_data, character_S
512
                        CALL send_to_UART
513
                        LOAD UART_data, character_y
514
                        CALL send_to_UART
515
                        LOAD UART_data, character_n
516
                        CALL send_to_UART
517
                        LOAD UART_data, character_t
518
                        CALL send_to_UART
519
                        LOAD UART_data, character_a
520
                        CALL send_to_UART
521
                        LOAD UART_data, character_x
522
                        CALL send_to_UART
523
                        JUMP send_space_Error
524
                        ;
525
                        ;Send 'Overflow Error' to the UART
526
                        ;
527
   send_Overflow_Error: LOAD UART_data, character_O
528
                        CALL send_to_UART
529
                        LOAD UART_data, character_v
530
                        CALL send_to_UART
531
                        LOAD UART_data, character_e
532
                        CALL send_to_UART
533
                        LOAD UART_data, character_r
534
                        CALL send_to_UART
535
                        LOAD UART_data, character_f
536
                        CALL send_to_UART
537
                        LOAD UART_data, character_l
538
                        CALL send_to_UART
539
                        LOAD UART_data, character_o
540
                        CALL send_to_UART
541
                        LOAD UART_data, character_w
542
                        CALL send_to_UART
543
      send_space_Error: CALL send_space
544
                        ;
545
                        ;Send 'Error' to the UART
546
                        ;
547
            send_Error: LOAD UART_data, character_E
548
                        CALL send_to_UART
549
                        LOAD UART_data, character_r
550
                        CALL send_to_UART
551
                        CALL send_to_UART
552
                        LOAD UART_data, character_o
553
                        CALL send_to_UART
554
                        LOAD UART_data, character_r
555
                        CALL send_to_UART
556
                        RETURN
557
                        ;
558
                        ;Send 'KCPSM3>' prompt to the UART
559
                        ;
560
           send_prompt: CALL send_CR                             ;start new line
561
                        LOAD UART_data, character_K
562
                        CALL send_to_UART
563
                        LOAD UART_data, character_C
564
                        CALL send_to_UART
565
                        LOAD UART_data, character_P
566
                        CALL send_to_UART
567
                        LOAD UART_data, character_S
568
                        CALL send_to_UART
569
                        LOAD UART_data, character_M
570
                        CALL send_to_UART
571
                        LOAD UART_data, character_3
572
                        CALL send_to_UART
573
                        ;
574
                        ;Send '>' character to the UART
575
                        ;
576
     send_greater_than: LOAD UART_data, character_greater_than
577
                        CALL send_to_UART
578
                        RETURN
579
                        ;
580
                        ;Send 'Invalid' string to the UART
581
                        ;
582
          send_Invalid: LOAD UART_data, character_I
583
                        CALL send_to_UART
584
                        LOAD UART_data, character_n
585
                        CALL send_to_UART
586
                        LOAD UART_data, character_v
587
                        CALL send_to_UART
588
                        LOAD UART_data, character_a
589
                        CALL send_to_UART
590
                        LOAD UART_data, character_l
591
                        CALL send_to_UART
592
                        LOAD UART_data, character_i
593
                        CALL send_to_UART
594
                        LOAD UART_data, character_d
595
                        CALL send_to_UART
596
                        RETURN
597
                        ;
598
                        ;Send 'Time' string to the UART
599
                        ;
600
             send_Time: LOAD UART_data, character_T
601
                        CALL send_to_UART
602
                        LOAD UART_data, character_i
603
                        CALL send_to_UART
604
                        LOAD UART_data, character_m
605
                        CALL send_to_UART
606
                        LOAD UART_data, character_e
607
                        CALL send_to_UART
608
                        RETURN
609
                        ;
610
                        ;Send 'Alarm' string to the UART
611
                        ;
612
            send_Alarm: LOAD UART_data, character_A
613
                        CALL send_to_UART
614
                        LOAD UART_data, character_l
615
                        CALL send_to_UART
616
                        LOAD UART_data, character_a
617
                        CALL send_to_UART
618
                        LOAD UART_data, character_r
619
                        CALL send_to_UART
620
                        LOAD UART_data, character_m
621
                        CALL send_to_UART
622
                        RETURN
623
                        ;
624
                        ;Send 'OFF' string to the UART
625
                        ;
626
              send_OFF: LOAD UART_data, character_O
627
                        CALL send_to_UART
628
                        LOAD UART_data, character_F
629
                        CALL send_to_UART
630
                        CALL send_to_UART
631
                        RETURN
632
                        ;
633
                        ;Send 'ON' string to the UART
634
                        ;
635
               send_ON: LOAD UART_data, character_O
636
                        CALL send_to_UART
637
                        LOAD UART_data, character_N
638
                        CALL send_to_UART
639
                        RETURN
640
                        ;
641
                        ;Send 'Active' string to the UART
642
                        ;
643
           send_Active: LOAD UART_data, character_A
644
                        CALL send_to_UART
645
                        LOAD UART_data, character_c
646
                        CALL send_to_UART
647
                        LOAD UART_data, character_t
648
                        CALL send_to_UART
649
                        LOAD UART_data, character_i
650
                        CALL send_to_UART
651
                        LOAD UART_data, character_v
652
                        CALL send_to_UART
653
                        LOAD UART_data, character_e
654
                        CALL send_to_UART
655
                        RETURN
656
                        ;
657
                        ;
658
                        ;Convert time to ASCII string in scratch pad memory.
659
                        ;
660
                        ;The time to converted must be stored in 3 scratch pad memory locations as
661
                        ;defined below. A register named 'store_pointer' must provide the address of
662
                        ;first location.
663
                        ;
664
                        ;        Address                Data
665
                        ;
666
                        ;     store_pointer      ----> hours
667
                        ;     store_pointer + 1  ----> minutes
668
                        ;     store_pointer + 1  ----> seconds
669
                        ;
670
                        ;The resulting ASCII string will be stored in scratch pad memory starting at
671
                        ;a location specified by a constant named 'string_start'. The string will
672
                        ;take the format hh:mm:ss and end with a carriage return.
673
                        ;
674
                        ;Registers used s0, s1, s2 and 'store_pointer'.
675
                        ;
676
         time_to_ASCII: LOAD s2, string_start                    ;location for string
677
                        FETCH s0, (store_pointer)                ;read hours value
678
                        CALL decimal_to_ASCII                    ;convert to ASCII
679
                        STORE s1, (s2)                           ;write hours to string
680
                        ADD s2, 01
681
                        STORE s0, (s2)
682
                        ADD s2, 01
683
                        LOAD s0, character_colon                 ;write ':' to string
684
                        STORE s0, (s2)
685
                        ADD s2, 01
686
                        ADD store_pointer, 01                    ;move to minutes
687
                        FETCH s0, (store_pointer)                ;read minutes value
688
                        CALL decimal_to_ASCII                    ;convert to ASCII
689
                        STORE s1, (s2)                           ;write minutes to string
690
                        ADD s2, 01
691
                        STORE s0, (s2)
692
                        ADD s2, 01
693
                        LOAD s0, character_colon                 ;write ':' to string
694
                        STORE s0, (s2)
695
                        ADD s2, 01
696
                        ADD store_pointer, 01                    ;move to seconds
697
                        FETCH s0, (store_pointer)                ;read seconds value
698
                        CALL decimal_to_ASCII                    ;convert to ASCII
699
                        STORE s1, (s2)                           ;write seconds to string
700
                        ADD s2, 01
701
                        STORE s0, (s2)
702
                        ADD s2, 01
703
                        LOAD s0, character_CR                    ;finish string with carriage return
704
                        STORE s0, (s2)
705
                        RETURN
706
                        ;
707
                        ;Convert value provided in register s0 into ASCII characters
708
                        ;
709
                        ;The value provided must in the range 0 to 99 and will be converted into
710
                        ;two ASCII characters.
711
                        ;     The number of 'tens' will be representd by an ASCII character returned in register s1.
712
                        ;     The number of 'units' will be representd by an ASCII character returned in register s0.
713
                        ;
714
                        ;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex added to
715
                        ;the actual decimal value.
716
                        ;
717
                        ;Registers used s0 and s1.
718
                        ;
719
      decimal_to_ASCII: LOAD s1, 30                              ;load 'tens' counter with ASCII for '0'
720
          test_for_ten: ADD s1, 01                               ;increment 'tens' value
721
                        SUB s0, 0A                               ;try to subtract 10 from the supplied value
722
                        JUMP NC, test_for_ten                    ;repeat if subtraction was possible without underflow.
723
                        SUB s1, 01                               ;'tens' value one less ten due to underflow
724
                        ADD s0, 3A                               ;restore units value (the remainder) and convert to ASCII
725
                        RETURN
726
                        ;
727
                        ;
728
                        ;
729
                        ;
730
                        ;Real Time Clock
731
                        ;
732
                        ;Uses the 1us interrupt counter [int_counter_msb,int_counter_lsb] to determine how many
733
                        ;micro-seconds have elapsed since the last update. This allows for just over 65ms between
734
                        ;updates. Complete multiples of 1000us are used to update a 16-bit milli-second counter held
735
                        ;in scratch pad memory locations [ms_time_stamp_msb,ms_time_stamp_msb] which in turn
736
                        ;is used to update the real time hours, minutes and seconds clock held in scratch pad
737
                        ;memory locations 'real_time_hours', 'real_time_minutes' and 'real_time_seconds'.
738
                        ;
739
                        ;The routine uses default register names s0,s1,s2,s3,s4,s5. These are preserved in scratch pad
740
                        ;memory during the routine and restored before returning.
741
                        ;
742
                        ;Useful constants for real time clock operations
743
                        ;
744
                        CONSTANT count_1000_lsb, E8              ;lower 8-bits of 1000 count value
745
                        CONSTANT count_1000_msb, 03              ;upper 8-bits of 1000 count value
746
                        CONSTANT hours_in_a_day, 18              ;24 hours in a day
747
                        CONSTANT minutes_in_an_hour, 3C          ;60 minutes in an hour
748
                        CONSTANT seconds_in_a_minute, 3C         ;60 seconds in a minute
749
                        ;
750
           update_time: STORE s0, time_preserve0                 ;preserve contents of registers used during routine
751
                        STORE s1, time_preserve1
752
                        STORE s2, time_preserve2
753
                        STORE s3, time_preserve3
754
                        STORE s4, time_preserve4
755
                        STORE s5, time_preserve5
756
                        ;
757
                        FETCH s2, us_time_stamp_lsb              ;read the previous 'us' time stamp into [s3,s2]
758
                        FETCH s3, us_time_stamp_msb
759
                        DISABLE INTERRUPT                        ;Read and store current 'us' time stamp provided by the interrupt
760
                        STORE int_counter_lsb, us_time_stamp_lsb ;counter. Interrupts are disabled to ensure that both bytes relate
761
                        STORE int_counter_msb, us_time_stamp_msb ;to the same count value.
762
                        ENABLE INTERRUPT
763
                        FETCH s4, us_time_stamp_lsb              ;read the new 'us' time stamp in [s5,s4]
764
                        FETCH s5, us_time_stamp_msb              ;
765
                        SUB s4, s2                               ;calculate 'us' time difference [s5,s4] = [s5,s4] - [s3,s2]
766
                        SUBCY s5, s3                             ;   (This works correctly even if counter has rolled over)
767
                        FETCH s2, us_time_lsb                    ;read current 'us' time into [s3,s2]
768
                        FETCH s3, us_time_msb
769
                        ADD s2, s4                               ;add on the elapsed 'us' value [s3,s2] = [s3,s2] + [s5,s4]
770
                        ADDCY s3, s5
771
                        ;determine how many 1000us (1ms) units there are (if any) in current 'us' time
772
                        LOAD s0, 00                              ;reset 'ms' counter
773
           test_1000us: SUB s2, count_1000_lsb                   ;subtract 1000 from [s3,s2]
774
                        SUBCY s3, count_1000_msb
775
                        JUMP C, store_us_time                    ;Carry indicates [s3,s2] was less than 1000us
776
                        ADD s0, 01                               ;increment 'ms' elapsed because [s3,s2] was more or equal to 1000us
777
                        JUMP test_1000us                         ;repeat to see if more than 1ms has elapsed
778
         store_us_time: ADD s2, count_1000_lsb                   ;add 1000 to restore 'us' value
779
                        ADDCY s3, count_1000_msb
780
                        STORE s2, us_time_lsb                    ;store the current value of 'us'
781
                        STORE s3, us_time_msb
782
                        ;s0 holds the number of 'ms' elapsed since last update (if any).
783
                        FETCH s2, ms_time_lsb                    ;read current 'ms' time into [s3,s2]
784
                        FETCH s3, ms_time_msb
785
                        ADD s2, s0                               ;add on the elapsed 'ms' value [s3,s2] = [s3,s2] + s0
786
                        ADDCY s3, 00
787
                        ;determine if there are now more than 1000ms to form 1 second.
788
                        LOAD s0, 00                              ;reset 'second' counter
789
                        SUB s2, count_1000_lsb                   ;subtract 1000 from [s3,s2]
790
                        SUBCY s3, count_1000_msb
791
                        JUMP C, restore_ms_time                  ;Carry indicates [s3,s2] was less than 1000ms
792
                        ADD s0, 01                               ;increment 'second' elapsed because [s3,s2] was more or equal to 1000ms
793
                        JUMP store_ms_time                       ;new value of 'ms' is remainder of subtraction
794
       restore_ms_time: ADD s2, count_1000_lsb                   ;add 1000 to restore 'ms' value
795
                        ADDCY s3, count_1000_msb
796
         store_ms_time: STORE s2, ms_time_lsb                    ;store the current value of 'ms'
797
                        STORE s3, ms_time_msb
798
                        ;s0 currently determines if one second needs to be added to the hh:mm:ss clock time
799
                        FETCH s1, real_time_seconds              ;read seconds
800
                        ADD s1, s0                               ;add one second if required by s0
801
                        COMPARE s1, seconds_in_a_minute          ;test for 1 minute
802
                        JUMP Z, inc_minutes
803
                        STORE s1, real_time_seconds              ;store updated seconds
804
                        JUMP time_update_complete
805
           inc_minutes: LOAD s1, 00                              ;seconds become zero
806
                        STORE s1, real_time_seconds
807
                        FETCH s1, real_time_minutes              ;read minutes
808
                        ADD s1, 01                               ;increment minutes
809
                        COMPARE s1, minutes_in_an_hour           ;test for 1 hour
810
                        JUMP Z, inc_hours
811
                        STORE s1, real_time_minutes              ;store updated minutes
812
                        JUMP time_update_complete
813
             inc_hours: LOAD s1, 00                              ;minutes become zero
814
                        STORE s1, real_time_minutes
815
                        FETCH s1, real_time_hours                ;read hours
816
                        ADD s1, 01                               ;increment hours
817
                        COMPARE s1, hours_in_a_day               ;test for 24 hours
818
                        JUMP Z, reset_hours
819
                        STORE s1, real_time_hours                ;store updated hours
820
                        JUMP time_update_complete
821
           reset_hours: LOAD s1, 00                              ;hours become zero
822
                        STORE s1, real_time_hours
823
                        ;
824
                        ;With the time updated, there is then a test for time=alarm time
825
                        ;
826
  time_update_complete: FETCH s0, real_time_hours
827
                        FETCH s1, alarm_time_hours               ;compare hours
828
                        COMPARE s0, s1
829
                        JUMP NZ, finish_update
830
                        FETCH s0, real_time_minutes              ;compare minutes
831
                        FETCH s1, alarm_time_minutes
832
                        COMPARE s0, s1
833
                        JUMP NZ, finish_update
834
                        FETCH s0, real_time_seconds              ;compare seconds
835
                        FETCH s1, alarm_time_seconds
836
                        COMPARE s0, s1
837
                        JUMP NZ, finish_update
838
                        FETCH s0, alarm_status                   ;test if alarm is turned on
839
                        TEST s0, alarm_armed
840
                        JUMP Z, finish_update                    ;alarm was off
841
                        OR s0, alarm_active                      ;activate alarm
842
                        STORE s0, alarm_status
843
                        CALL alarm_drive
844
         finish_update: FETCH s0, time_preserve0                 ;restore the register contents
845
                        FETCH s1, time_preserve1
846
                        FETCH s2, time_preserve2
847
                        FETCH s3, time_preserve3
848
                        FETCH s4, time_preserve4
849
                        FETCH s5, time_preserve5
850
                        RETURN
851
                        ;
852
                        ;Convert character to upper case
853
                        ;
854
                        ;The character supplied in register s0.
855
                        ;If the character is in the range 'a' to 'z', it is converted
856
                        ;to the equivalent upper case character in the range 'A' to 'Z'.
857
                        ;All other characters remain unchanged.
858
                        ;
859
                        ;Registers used s0.
860
                        ;
861
            upper_case: COMPARE s0, 61                           ;eliminate character codes below 'a' (61 hex)
862
                        RETURN C
863
                        COMPARE s0, 7B                           ;eliminate character codes above 'z' (7A hex)
864
                        RETURN NC
865
                        AND s0, DF                               ;mask bit5 to convert to upper case
866
                        RETURN
867
                        ;
868
                        ;
869
                        ;Convert character '0' to '9' to numerical value in range 0 to 9
870
                        ;
871
                        ;The character supplied in register s0. If the character is in the
872
                        ;range '0' to '9', it is converted to the equivalent decimal value.
873
                        ;Characters not in the range '0' to '9' are signified by the return
874
                        ;with the CARRY flag set.
875
                        ;
876
                        ;Registers used s0.
877
                        ;
878
        1char_to_value: ADD s0, C6                               ;reject character codes above '9' (39 hex)
879
                        RETURN C                                 ;carry flag is set
880
                        SUB s0, F6                               ;reject character codes below '0' (30 hex)
881
                        RETURN                                   ;carry is set if value not in range
882
                        ;
883
                        ;
884
                        ;Determine the numerical value of a two character decimal string held in
885
                        ;scratch pad memory such the result is in the range 0 to 99 (00 to 63 hex).
886
                        ;
887
                        ;The string must be stored as in two consecutive memory locations and the
888
                        ;location of the first (tens) character supplied in the s1 register.
889
                        ;The result is provided in register s2. Strings not using characters in the
890
                        ;range '0' to '9' are signified by the return with the CARRY flag set.
891
                        ;
892
                        ;Registers used s0, s1 and s2.
893
                        ;
894
        2char_to_value: FETCH s0, (s1)                           ;read 'tens' character
895
                        CALL 1char_to_value                      ;convert to numerical value
896
                        RETURN C                                 ;bad character - CARRY set
897
                        LOAD s2, s0
898
                        SL0 s2                                   ;multiply 'tens' value by 10 (0A hex)
899
                        SL0 s2
900
                        ADD s2, s0
901
                        SL0 s2
902
                        ADD s1, 01                               ;read 'units' character
903
                        FETCH s0, (s1)
904
                        CALL 1char_to_value                      ;convert to numerical value
905
                        RETURN C                                 ;bad character - CARRY set
906
                        ADD s2, s0                               ;add units to result and clear CARRY flag
907
                        RETURN
908
                        ;
909
                        ;
910
                        ;Interrupt service routine (ISR)
911
                        ;
912
                        ;The interrupt is used to increment a 16-bit counter formed with two registers
913
                        ;called [int_counter_msb,int_counter_lsb]. This provides a count of the number
914
                        ;of micro-seconds elapsed. The counter is 'free running' in that it will count
915
                        ;up to 65,535 and then roll over to zero. The count value is then used in other
916
                        ;parts of the program as required and where it is less time critical.
917
                        ;
918
                        ;The ISR only uses the specified counter registers
919
                        ;
920
                        ADDRESS 3FC
921
                   ISR: ADD int_counter_lsb, 01                  ;add 1us to 16-bit counter
922
                        ADDCY int_counter_msb, 00
923
                        RETURNI ENABLE
924
                        ;
925
                        ;Interrupt vector
926
                        ;
927
                        ADDRESS 3FF
928
                        JUMP ISR
929
                        ;
930
                        ;
931
                        ;Useful constants
932
                        ;
933
                        ;
934
                        ;ASCII table
935
                        ;
936
                        CONSTANT character_a, 61
937
                        CONSTANT character_b, 62
938
                        CONSTANT character_c, 63
939
                        CONSTANT character_d, 64
940
                        CONSTANT character_e, 65
941
                        CONSTANT character_f, 66
942
                        CONSTANT character_g, 67
943
                        CONSTANT character_h, 68
944
                        CONSTANT character_i, 69
945
                        CONSTANT character_j, 6A
946
                        CONSTANT character_k, 6B
947
                        CONSTANT character_l, 6C
948
                        CONSTANT character_m, 6D
949
                        CONSTANT character_n, 6E
950
                        CONSTANT character_o, 6F
951
                        CONSTANT character_p, 70
952
                        CONSTANT character_q, 71
953
                        CONSTANT character_r, 72
954
                        CONSTANT character_s, 73
955
                        CONSTANT character_t, 74
956
                        CONSTANT character_u, 75
957
                        CONSTANT character_v, 76
958
                        CONSTANT character_w, 77
959
                        CONSTANT character_x, 78
960
                        CONSTANT character_y, 79
961
                        CONSTANT character_z, 7A
962
                        CONSTANT character_A, 41
963
                        CONSTANT character_B, 42
964
                        CONSTANT character_C, 43
965
                        CONSTANT character_D, 44
966
                        CONSTANT character_E, 45
967
                        CONSTANT character_F, 46
968
                        CONSTANT character_G, 47
969
                        CONSTANT character_H, 48
970
                        CONSTANT character_I, 49
971
                        CONSTANT character_J, 4A
972
                        CONSTANT character_K, 4B
973
                        CONSTANT character_L, 4C
974
                        CONSTANT character_M, 4D
975
                        CONSTANT character_N, 4E
976
                        CONSTANT character_O, 4F
977
                        CONSTANT character_P, 50
978
                        CONSTANT character_Q, 51
979
                        CONSTANT character_R, 52
980
                        CONSTANT character_S, 53
981
                        CONSTANT character_T, 54
982
                        CONSTANT character_U, 55
983
                        CONSTANT character_V, 56
984
                        CONSTANT character_W, 57
985
                        CONSTANT character_X, 58
986
                        CONSTANT character_Y, 59
987
                        CONSTANT character_Z, 5A
988
                        CONSTANT character_0, 30
989
                        CONSTANT character_1, 31
990
                        CONSTANT character_2, 32
991
                        CONSTANT character_3, 33
992
                        CONSTANT character_4, 34
993
                        CONSTANT character_5, 35
994
                        CONSTANT character_6, 36
995
                        CONSTANT character_7, 37
996
                        CONSTANT character_8, 38
997
                        CONSTANT character_9, 39
998
                        CONSTANT character_colon, 3A
999
                        CONSTANT character_semi_colon, 3B
1000
                        CONSTANT character_less_than, 3C
1001
                        CONSTANT character_greater_than, 3E
1002
                        CONSTANT character_equals, 3D
1003
                        CONSTANT character_space, 20
1004
                        CONSTANT character_CR, 0D                ;carriage return
1005
                        CONSTANT character_question, 3F          ;'?'
1006
                        CONSTANT character_dollar, 24
1007
                        CONSTANT character_BS, 08                ;Back Space command character
1008
                        ;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.