1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00

1263 lines
51 KiB
Plaintext

/* Symbol Table */
// BS_edit = LABEL: 211
// ISR = LABEL: 1020
// UART_data = REGISTER: 15
// UART_read_port = CONSTANT: 1
// UART_status_port = CONSTANT: 0
// UART_write = LABEL: 162
// UART_write_port = CONSTANT: 1
// _1char_to_value = LABEL: 488
// _2char_to_value = LABEL: 492
// alarm_active = CONSTANT: 1
// alarm_armed = CONSTANT: 2
// alarm_control = CONSTANT: 1
// alarm_drive = LABEL: 164
// alarm_is_off = LABEL: 186
// alarm_port = CONSTANT: 0
// alarm_status = CONSTANT: 12
// alarm_time_hours = CONSTANT: 9
// alarm_time_minutes = CONSTANT: 10
// alarm_time_seconds = CONSTANT: 11
// bad_input_command = LABEL: 28
// character_0 = CONSTANT: 48
// character_1 = CONSTANT: 49
// character_2 = CONSTANT: 50
// character_3 = CONSTANT: 51
// character_4 = CONSTANT: 52
// character_5 = CONSTANT: 53
// character_6 = CONSTANT: 54
// character_7 = CONSTANT: 55
// character_8 = CONSTANT: 56
// character_9 = CONSTANT: 57
// character_A = CONSTANT: 65
// character_B = CONSTANT: 66
// character_BS = CONSTANT: 8
// character_C = CONSTANT: 67
// character_CR = CONSTANT: 13
// character_D = CONSTANT: 68
// character_E = CONSTANT: 69
// character_F = CONSTANT: 70
// character_G = CONSTANT: 71
// character_H = CONSTANT: 72
// character_I = CONSTANT: 73
// character_J = CONSTANT: 74
// character_K = CONSTANT: 75
// character_L = CONSTANT: 76
// character_M = CONSTANT: 77
// character_N = CONSTANT: 78
// character_O = CONSTANT: 79
// character_P = CONSTANT: 80
// character_Q = CONSTANT: 81
// character_R = CONSTANT: 82
// character_S = CONSTANT: 83
// character_T = CONSTANT: 84
// character_U = CONSTANT: 85
// character_V = CONSTANT: 86
// character_W = CONSTANT: 87
// character_X = CONSTANT: 88
// character_Y = CONSTANT: 89
// character_Z = CONSTANT: 90
// character_a = CONSTANT: 97
// character_b = CONSTANT: 98
// character_c = CONSTANT: 99
// character_colon = CONSTANT: 58
// character_d = CONSTANT: 100
// character_dollar = CONSTANT: 36
// character_e = CONSTANT: 101
// character_equals = CONSTANT: 61
// character_f = CONSTANT: 102
// character_g = CONSTANT: 103
// character_greater_than = CONSTANT: 62
// character_h = CONSTANT: 104
// character_i = CONSTANT: 105
// character_j = CONSTANT: 106
// character_k = CONSTANT: 107
// character_l = CONSTANT: 108
// character_less_than = CONSTANT: 60
// character_m = CONSTANT: 109
// character_n = CONSTANT: 110
// character_o = CONSTANT: 111
// character_p = CONSTANT: 112
// character_q = CONSTANT: 113
// character_question = CONSTANT: 63
// character_r = CONSTANT: 114
// character_s = CONSTANT: 115
// character_semi_colon = CONSTANT: 59
// character_space = CONSTANT: 32
// character_t = CONSTANT: 116
// character_u = CONSTANT: 117
// character_v = CONSTANT: 118
// character_w = CONSTANT: 119
// character_x = CONSTANT: 120
// character_y = CONSTANT: 121
// character_z = CONSTANT: 122
// clear_UART_Rx_loop = LABEL: 223
// cold_start = LABEL: 0
// count_1000_lsb = CONSTANT: 232
// count_1000_msb = CONSTANT: 3
// decimal_to_ASCII = LABEL: 382
// fetch_char_from_memory = LABEL: 145
// finish_update = LABEL: 475
// hours_in_a_day = CONSTANT: 24
// inc_hours = LABEL: 447
// inc_minutes = LABEL: 439
// int_counter_lsb = REGISTER: 13
// int_counter_msb = REGISTER: 12
// invalid_time = LABEL: 139
// minutes_in_an_hour = CONSTANT: 60
// ms_time_lsb = CONSTANT: 4
// ms_time_msb = CONSTANT: 5
// next_char_tx = LABEL: 189
// prompt_input = LABEL: 18
// read_character = LABEL: 154
// read_error = LABEL: 219
// read_from_UART = LABEL: 149
// real_time_hours = CONSTANT: 6
// real_time_minutes = CONSTANT: 7
// real_time_seconds = CONSTANT: 8
// receive_full_test = LABEL: 198
// receive_string = LABEL: 195
// reset_hours = LABEL: 455
// restore_ms_time = LABEL: 429
// rx_data_present = CONSTANT: 16
// rx_full = CONSTANT: 8
// rx_half_full = CONSTANT: 4
// s0 = REGISTER: 0
// s1 = REGISTER: 1
// s2 = REGISTER: 2
// s3 = REGISTER: 3
// s4 = REGISTER: 4
// s5 = REGISTER: 5
// s6 = REGISTER: 6
// s7 = REGISTER: 7
// s8 = REGISTER: 8
// s9 = REGISTER: 9
// sA = REGISTER: 10
// sB = REGISTER: 11
// sC = REGISTER: 12
// sD = REGISTER: 13
// sE = REGISTER: 14
// sF = REGISTER: 15
// seconds_in_a_minute = CONSTANT: 60
// send_Active = LABEL: 339
// send_Alarm = LABEL: 317
// send_CR = LABEL: 228
// send_Error = LABEL: 267
// send_Invalid = LABEL: 293
// send_OFF = LABEL: 328
// send_ON = LABEL: 334
// send_Overflow_Error = LABEL: 250
// send_Syntax_Error = LABEL: 237
// send_Time = LABEL: 308
// send_backspace = LABEL: 234
// send_greater_than = LABEL: 290
// send_prompt = LABEL: 277
// send_space = LABEL: 231
// send_space_Error = LABEL: 266
// send_to_UART = LABEL: 157
// set_alarm_command = LABEL: 72
// set_alarm_on_off = LABEL: 85
// set_time_command = LABEL: 44
// store_ms_time = LABEL: 431
// store_pointer = REGISTER: 14
// store_us_time = LABEL: 415
// string_start = CONSTANT: 32
// string_start_again = LABEL: 217
// test_1000us = LABEL: 410
// test_OFF = LABEL: 96
// test_armed = LABEL: 182
// test_for_ALARM = LABEL: 55
// test_for_TIME = LABEL: 30
// test_for_ten = LABEL: 383
// test_time_string = LABEL: 109
// time_preserve0 = CONSTANT: 16
// time_preserve1 = CONSTANT: 17
// time_preserve2 = CONSTANT: 18
// time_preserve3 = CONSTANT: 19
// time_preserve4 = CONSTANT: 20
// time_preserve5 = CONSTANT: 21
// time_to_ASCII = LABEL: 352
// time_update_complete = LABEL: 457
// transmit_alarm_time = LABEL: 172
// transmit_string = LABEL: 188
// transmit_time = LABEL: 168
// tx_full = CONSTANT: 2
// tx_half_full = CONSTANT: 1
// update_time = LABEL: 389
// upper_case = LABEL: 482
// us_time_lsb = CONSTANT: 2
// us_time_msb = CONSTANT: 3
// us_time_stamp_lsb = CONSTANT: 0
// us_time_stamp_msb = CONSTANT: 1
/* Program Code */
// #1: ;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,0) ;UART status input
// #9: constant(tx_half_full,1) ; Transmitter half full - bit0
// #10: constant(tx_full,2) ; FIFO full - bit1
// #11: constant(rx_half_full,4) ; Receiver half full - bit2
// #12: constant(rx_full,8) ; FIFO full - bit3
// #13: constant(rx_data_present,16) ; data present - bit4
// #14: ;
// #15: constant(UART_read_port,1) ;UART Rx data input
// #16: ;
// #17: constant(UART_write_port,1) ;UART Tx data output
// #18: ;
// #19: constant(alarm_port,0) ;Alarm output
// #20: constant(alarm_control,1) ; bit0
// #21: ;
// #22: ;Special Register usage
// #23: ;
// #24: register(UART_data,15) ;used to pass data to and from the UART
// #25: ;
// #26: register(store_pointer,14) ;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: register(int_counter_lsb,13) ;lower 8-bits
// #32: register(int_counter_msb,12) ;upper 8-bits
// #33: ;
// #34: ;
// #35: ;Scratch Pad Memory Locations
// #36: ;
// #37: ;
// #38: constant(us_time_stamp_lsb,0) ;16-bit micro-second time stamp
// #39: constant(us_time_stamp_msb,1)
// #40: ;
// #41: constant(us_time_lsb,2) ;16-bit micro-second real time value
// #42: constant(us_time_msb,3)
// #43: ;
// #44: constant(ms_time_lsb,4) ;16-bit milli-second real time value
// #45: constant(ms_time_msb,5)
// #46: ;
// #47: constant(real_time_hours,6) ;Current clock time
// #48: constant(real_time_minutes,7)
// #49: constant(real_time_seconds,8)
// #50: ;
// #51: constant(alarm_time_hours,9) ;Alarm time
// #52: constant(alarm_time_minutes,10)
// #53: constant(alarm_time_seconds,11)
// #54: ;
// #55: constant(alarm_status,12) ;Alarm status
// #56: constant(alarm_active,1) ; bit0 - Alarm is active
// #57: constant(alarm_armed,2) ; bit1 - Alarm is armed
// #58: ;
// #59: constant(time_preserve0,16) ;storage for protection of registers
// #60: constant(time_preserve1,17) ;used by the real time clock routine.
// #61: constant(time_preserve2,18)
// #62: constant(time_preserve3,19)
// #63: constant(time_preserve4,20)
// #64: constant(time_preserve5,21)
// #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,32)
// #70: ;
// #71: ;
// #72: ;Initialise the system
// #73: ;
// #74: ;
// @000 #75: [cold_start]
00000 // @000 #75: load(s0,0) ;clear all time values
2e000 // @001 #76: store(s0,us_time_stamp_lsb)
2e001 // @002 #77: store(s0,us_time_stamp_msb)
2e002 // @003 #78: store(s0,us_time_lsb)
2e003 // @004 #79: store(s0,us_time_msb)
2e004 // @005 #80: store(s0,ms_time_lsb)
2e005 // @006 #81: store(s0,ms_time_msb)
2e006 // @007 #82: store(s0,real_time_hours)
2e007 // @008 #83: store(s0,real_time_minutes)
2e008 // @009 #84: store(s0,real_time_seconds)
2e009 // @00a #85: store(s0,alarm_time_hours)
2e00a // @00b #86: store(s0,alarm_time_minutes)
2e00b // @00c #87: store(s0,alarm_time_seconds)
2e00c // @00d #88: store(s0,alarm_status) ;clear and disable alarm
300a4 // @00e #89: call(alarm_drive) ;turn off alarm control output port
00d00 // @00f #90: load(int_counter_lsb,0) ;clear 'us' interrupt counter
00c00 // @010 #91: load(int_counter_msb,0)
3c001 // @011 #92: interrupt(enable) ;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: ;
// @012 #101: [prompt_input]
30115 // @012 #101: call(send_prompt) ;Prompt 'KCPSM3>'
300c3 // @013 #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: ;
00120 // @014 #109: load(s1,string_start)
30091 // @015 #110: call(fetch_char_from_memory)
1400d // @016 #111: compare(s0,character_CR) ;carriage return does nothing
35012 // @017 #112: jump(z,prompt_input)
14054 // @018 #113: compare(s0,character_T) ;start of 'TIME' command?
3501e // @019 #114: jump(z,test_for_TIME)
14041 // @01a #115: compare(s0,character_A) ;start of 'ALARM' command?
35037 // @01b #116: jump(z,test_for_ALARM)
// #117: ;
// #118: ;trap other command starts here
// #119: ;
// @01c #120: [bad_input_command]
300ed // @01c #120: call(send_Syntax_Error) ;no valid command
35012 // @01d #121: jump(z,prompt_input)
// #122: ;
// #123: ;
// @01e #124: [test_for_TIME]
30091 // @01e #124: call(fetch_char_from_memory)
14049 // @01f #125: compare(s0,character_I) ;test for rest of 'TIME'
3541c // @020 #126: jump(nz,bad_input_command)
30091 // @021 #127: call(fetch_char_from_memory)
1404d // @022 #128: compare(s0,character_M)
3541c // @023 #129: jump(nz,bad_input_command)
30091 // @024 #130: call(fetch_char_from_memory)
14045 // @025 #131: compare(s0,character_E)
3541c // @026 #132: jump(nz,bad_input_command)
// #133: ;now have a valid TIME command to process
30091 // @027 #134: call(fetch_char_from_memory)
1400d // @028 #135: compare(s0,character_CR) ;carriage return means display time
3542c // @029 #136: jump(nz,set_time_command)
300a8 // @02a #137: call(transmit_time) ;transmit time to UART
34012 // @02b #138: jump(prompt_input)
// @02c #139: [set_time_command]
14020 // @02c #139: compare(s0,character_space)
3541c // @02d #140: jump(nz,bad_input_command)
3006d // @02e #141: call(test_time_string) ;interpret 'hh:mm:ss' string
35812 // @02f #142: jump(c,prompt_input) ;test for invalid input
2e606 // @030 #143: store(s6,real_time_hours) ;set new time into clock
2e507 // @031 #144: store(s5,real_time_minutes)
2e408 // @032 #145: store(s4,real_time_seconds)
2e004 // @033 #146: store(s0,ms_time_lsb) ;clear 'ms' counter (s0=00)
2e005 // @034 #147: store(s0,ms_time_msb)
300a8 // @035 #148: call(transmit_time) ;transmit new time to UART
34012 // @036 #149: jump(prompt_input)
// #150: ;
// #151: ;
// @037 #152: [test_for_ALARM]
30091 // @037 #152: call(fetch_char_from_memory)
1404c // @038 #153: compare(s0,character_L) ;test for rest of 'ALARM'
3541c // @039 #154: jump(nz,bad_input_command)
30091 // @03a #155: call(fetch_char_from_memory)
14041 // @03b #156: compare(s0,character_A)
3541c // @03c #157: jump(nz,bad_input_command)
30091 // @03d #158: call(fetch_char_from_memory)
14052 // @03e #159: compare(s0,character_R)
3541c // @03f #160: jump(nz,bad_input_command)
30091 // @040 #161: call(fetch_char_from_memory)
1404d // @041 #162: compare(s0,character_M)
3541c // @042 #163: jump(nz,bad_input_command)
// #164: ;now have a valid ALARM command to process
30091 // @043 #165: call(fetch_char_from_memory)
1400d // @044 #166: compare(s0,character_CR) ;carriage return means display alarm time
35448 // @045 #167: jump(nz,set_alarm_command)
300ac // @046 #168: call(transmit_alarm_time) ;transmit time to UART
34012 // @047 #169: jump(prompt_input)
// @048 #170: [set_alarm_command]
14020 // @048 #170: compare(s0,character_space) ;test for ON or OFF command
3541c // @049 #171: jump(nz,bad_input_command)
30091 // @04a #172: call(fetch_char_from_memory)
1404f // @04b #173: compare(s0,character_O)
35055 // @04c #174: jump(z,set_alarm_on_off)
1c101 // @04d #175: sub(s1,1) ;move memory pointer back to first character of 'hh:mm:ss' string
3006d // @04e #176: call(test_time_string) ;interpret 'hh:mm:ss' string
35812 // @04f #177: jump(c,prompt_input) ;test for invalid input
2e609 // @050 #178: store(s6,alarm_time_hours) ;set new time into clock
2e50a // @051 #179: store(s5,alarm_time_minutes)
2e40b // @052 #180: store(s4,alarm_time_seconds)
300ac // @053 #181: call(transmit_alarm_time) ;transmit new alarm time and status
34012 // @054 #182: jump(prompt_input)
// @055 #183: [set_alarm_on_off]
30091 // @055 #183: call(fetch_char_from_memory)
1404e // @056 #184: compare(s0,character_N) ;test for 'ON'
35460 // @057 #185: jump(nz,test_OFF)
30091 // @058 #186: call(fetch_char_from_memory)
1400d // @059 #187: compare(s0,character_CR)
3541c // @05a #188: jump(nz,bad_input_command)
0600c // @05b #189: fetch(s0,alarm_status) ;turn alarm on
0c002 // @05c #190: or(s0,alarm_armed)
2e00c // @05d #191: store(s0,alarm_status)
300ac // @05e #192: call(transmit_alarm_time) ;transmit alarm time and status
34012 // @05f #193: jump(prompt_input)
// @060 #194: [test_OFF]
14046 // @060 #194: compare(s0,character_F) ;test for for 'OFF'
3541c // @061 #195: jump(nz,bad_input_command)
30091 // @062 #196: call(fetch_char_from_memory)
14046 // @063 #197: compare(s0,character_F)
3541c // @064 #198: jump(nz,bad_input_command)
30091 // @065 #199: call(fetch_char_from_memory)
1400d // @066 #200: compare(s0,character_CR)
3541c // @067 #201: jump(nz,bad_input_command)
00000 // @068 #202: load(s0,0) ;turn alarm off and stop an active alarm
2e00c // @069 #203: store(s0,alarm_status)
300a4 // @06a #204: call(alarm_drive) ;turn off alarm
300ac // @06b #205: call(transmit_alarm_time) ;transmit alarm time and status
34012 // @06c #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: ;
// @06d #228: [test_time_string]
301ec // @06d #228: call(_2char_to_value) ;obtain hours value
3588b // @06e #229: jump(c,invalid_time) ;test for non-decimal characters
01620 // @06f #230: load(s6,s2) ;remember hours
18101 // @070 #231: add(s1,1) ;increment memory pointer past hours
30091 // @071 #232: call(fetch_char_from_memory)
1403a // @072 #233: compare(s0,character_colon) ;test for colon
3548b // @073 #234: jump(nz,invalid_time)
301ec // @074 #235: call(_2char_to_value) ;obtain minutes value
3588b // @075 #236: jump(c,invalid_time) ;test for non-decimal characters
01520 // @076 #237: load(s5,s2) ;remember minutes
18101 // @077 #238: add(s1,1) ;increment memory pointer past minutes
30091 // @078 #239: call(fetch_char_from_memory)
1403a // @079 #240: compare(s0,character_colon) ;test for colon
3548b // @07a #241: jump(nz,invalid_time)
301ec // @07b #242: call(_2char_to_value) ;obtain seconds value
3588b // @07c #243: jump(c,invalid_time) ;test for non-decimal characters
01420 // @07d #244: load(s4,s2) ;remember minutes
18101 // @07e #245: add(s1,1) ;increment memory pointer past seconds
30091 // @07f #246: call(fetch_char_from_memory)
1400d // @080 #247: compare(s0,character_CR) ;finish with carriage return
3548b // @081 #248: jump(nz,invalid_time)
// #249: ;Have values for hh:mm:ss but need to test if each is valid range.
14618 // @082 #250: compare(s6,hours_in_a_day)
35c8b // @083 #251: jump(nc,invalid_time)
1453c // @084 #252: compare(s5,minutes_in_an_hour)
35c8b // @085 #253: jump(nc,invalid_time)
1443c // @086 #254: compare(s4,seconds_in_a_minute)
35c8b // @087 #255: jump(nc,invalid_time)
00000 // @088 #256: load(s0,0)
2000e // @089 #257: sr0(s0) ;reset CARRY flag (with s0=0)
2a000 // @08a #258: return ;time string was OK
// @08b #259: [invalid_time]
30125 // @08b #259: call(send_Invalid)
300e7 // @08c #260: call(send_space)
30134 // @08d #261: call(send_Time)
00001 // @08e #262: load(s0,1)
2000e // @08f #263: sr0(s0) ;set CARRY flag
2a000 // @090 #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: ;
// @091 #275: [fetch_char_from_memory]
07010 // @091 #275: fetch(s0,s1) ;read character
301e2 // @092 #276: call(upper_case) ;convert to upper case
18101 // @093 #277: add(s1,1) ;increment memory pointer
2a000 // @094 #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: ;
// @095 #294: [read_from_UART]
04000 // @095 #294: input(s0,UART_status_port) ;test Rx_FIFO buffer
12010 // @096 #295: test(s0,rx_data_present)
3549a // @097 #296: jump(nz,read_character)
30185 // @098 #297: call(update_time) ;Perform useful operation whilst waiting
34095 // @099 #298: jump(read_from_UART)
// @09a #299: [read_character]
04f01 // @09a #299: input(UART_data,UART_read_port) ;read from FIFO
3009d // @09b #300: call(send_to_UART) ;echo received character
2a000 // @09c #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: ;
// @09d #325: [send_to_UART]
04000 // @09d #325: input(s0,UART_status_port) ;test Tx_FIFO buffer
12002 // @09e #326: test(s0,tx_full)
350a2 // @09f #327: jump(z,UART_write)
30185 // @0a0 #328: call(update_time) ;Perform useful operation whilst waiting
3409d // @0a1 #329: jump(send_to_UART)
// @0a2 #330: [UART_write]
2cf01 // @0a2 #330: output(UART_data,UART_write_port)
2a000 // @0a3 #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: ;
// @0a4 #343: [alarm_drive]
0600c // @0a4 #343: fetch(s0,alarm_status) ;read status
0a001 // @0a5 #344: and(s0,alarm_active) ;isolate bit0
2c000 // @0a6 #345: output(s0,alarm_port)
2a000 // @0a7 #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: ;
// @0a8 #371: [transmit_time]
00e06 // @0a8 #371: load(store_pointer,real_time_hours) ;locate current time in memory
30160 // @0a9 #372: call(time_to_ASCII)
300bc // @0aa #373: call(transmit_string)
2a000 // @0ab #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: ;
// @0ac #396: [transmit_alarm_time]
00e09 // @0ac #396: load(store_pointer,alarm_time_hours) ;locate alarm time in memory
30160 // @0ad #397: call(time_to_ASCII)
300bc // @0ae #398: call(transmit_string)
3013d // @0af #399: call(send_Alarm)
300e7 // @0b0 #400: call(send_space)
0600c // @0b1 #401: fetch(s0,alarm_status) ;read alarm status
12001 // @0b2 #402: test(s0,alarm_active) ;test for active
350b6 // @0b3 #403: jump(z,test_armed)
30153 // @0b4 #404: call(send_Active)
2a000 // @0b5 #405: return
// @0b6 #406: [test_armed]
12002 // @0b6 #406: test(s0,alarm_armed) ;test for on
350ba // @0b7 #407: jump(z,alarm_is_off)
3014e // @0b8 #408: call(send_ON)
2a000 // @0b9 #409: return
// @0ba #410: [alarm_is_off]
30148 // @0ba #410: call(send_OFF)
2a000 // @0bb #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: ;
// @0bc #423: [transmit_string]
00120 // @0bc #423: load(s1,string_start) ;locate start of string
// @0bd #424: [next_char_tx]
07f10 // @0bd #424: fetch(UART_data,s1) ;read character from memory
3009d // @0be #425: call(send_to_UART) ;transmit character
14f0d // @0bf #426: compare(UART_data,character_CR) ;test for last character
2b000 // @0c0 #427: return(z)
18101 // @0c1 #428: add(s1,1) ;move to next character
340bd // @0c2 #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: ;
// @0c3 #451: [receive_string]
00120 // @0c3 #451: load(s1,string_start) ;locate start of string
01210 // @0c4 #452: load(s2,s1) ;compute 16 character address
18210 // @0c5 #453: add(s2,16)
// @0c6 #454: [receive_full_test]
04000 // @0c6 #454: input(s0,UART_status_port) ;test Rx_FIFO buffer for full
12008 // @0c7 #455: test(s0,rx_full)
354db // @0c8 #456: jump(nz,read_error)
30095 // @0c9 #457: call(read_from_UART) ;obtain and echo character
2ff10 // @0ca #458: store(UART_data,s1) ;write to memory
14f0d // @0cb #459: compare(UART_data,character_CR) ;test for end of string
2b000 // @0cc #460: return(z)
14f08 // @0cd #461: compare(UART_data,character_BS) ;test for back space
350d3 // @0ce #462: jump(z,BS_edit)
18101 // @0cf #463: add(s1,1) ;increment memory pointer
15120 // @0d0 #464: compare(s1,s2) ;test for pointer exceeding 16 characters
354c6 // @0d1 #465: jump(nz,receive_full_test) ;next character
300ea // @0d2 #466: call(send_backspace) ;hold end of string position on terminal display
// @0d3 #467: [BS_edit]
1c101 // @0d3 #467: sub(s1,1) ;memory pointer back one
14120 // @0d4 #468: compare(s1,string_start) ;test for under flow
358d9 // @0d5 #469: jump(c,string_start_again)
300e7 // @0d6 #470: call(send_space) ;clear character at current position
300ea // @0d7 #471: call(send_backspace) ;position cursor
340c6 // @0d8 #472: jump(receive_full_test) ;next character
// @0d9 #473: [string_start_again]
30122 // @0d9 #473: call(send_greater_than) ;restore '>' at prompt
340c3 // @0da #474: jump(receive_string) ;begin again
// #475: ;Receiver buffer overflow condition
// @0db #476: [read_error]
300e4 // @0db #476: call(send_CR) ;Transmit error message
2ef20 // @0dc #477: store(UART_data,string_start) ;empty string in memory (start with CR)
300fa // @0dd #478: call(send_Overflow_Error)
300e4 // @0de #479: call(send_CR)
// @0df #480: [clear_UART_Rx_loop]
04000 // @0df #480: input(s0,UART_status_port) ;test Rx_FIFO buffer for data
12010 // @0e0 #481: test(s0,rx_data_present)
2b000 // @0e1 #482: return(z) ;finish when buffer is empty
04f01 // @0e2 #483: input(UART_data,UART_read_port) ;read from FIFO and ignore
340df // @0e3 #484: jump(clear_UART_Rx_loop)
// #485: ;
// #486: ;
// #487: ;
// #488: ;Send Carriage Return to the UART
// #489: ;
// @0e4 #490: [send_CR]
00f0d // @0e4 #490: load(UART_data,character_CR)
3009d // @0e5 #491: call(send_to_UART)
2a000 // @0e6 #492: return
// #493: ;
// #494: ;
// #495: ;
// #496: ;Send a space to the UART
// #497: ;
// @0e7 #498: [send_space]
00f20 // @0e7 #498: load(UART_data,character_space)
3009d // @0e8 #499: call(send_to_UART)
2a000 // @0e9 #500: return
// #501: ;
// #502: ;
// #503: ;Send a back space to the UART
// #504: ;
// @0ea #505: [send_backspace]
00f08 // @0ea #505: load(UART_data,character_BS)
3009d // @0eb #506: call(send_to_UART)
2a000 // @0ec #507: return
// #508: ;
// #509: ;Send 'Syntax Error' to the UART
// #510: ;
// @0ed #511: [send_Syntax_Error]
00f53 // @0ed #511: load(UART_data,character_S)
3009d // @0ee #512: call(send_to_UART)
00f79 // @0ef #513: load(UART_data,character_y)
3009d // @0f0 #514: call(send_to_UART)
00f6e // @0f1 #515: load(UART_data,character_n)
3009d // @0f2 #516: call(send_to_UART)
00f74 // @0f3 #517: load(UART_data,character_t)
3009d // @0f4 #518: call(send_to_UART)
00f61 // @0f5 #519: load(UART_data,character_a)
3009d // @0f6 #520: call(send_to_UART)
00f78 // @0f7 #521: load(UART_data,character_x)
3009d // @0f8 #522: call(send_to_UART)
3410a // @0f9 #523: jump(send_space_Error)
// #524: ;
// #525: ;Send 'Overflow Error' to the UART
// #526: ;
// @0fa #527: [send_Overflow_Error]
00f4f // @0fa #527: load(UART_data,character_O)
3009d // @0fb #528: call(send_to_UART)
00f76 // @0fc #529: load(UART_data,character_v)
3009d // @0fd #530: call(send_to_UART)
00f65 // @0fe #531: load(UART_data,character_e)
3009d // @0ff #532: call(send_to_UART)
00f72 // @100 #533: load(UART_data,character_r)
3009d // @101 #534: call(send_to_UART)
00f66 // @102 #535: load(UART_data,character_f)
3009d // @103 #536: call(send_to_UART)
00f6c // @104 #537: load(UART_data,character_l)
3009d // @105 #538: call(send_to_UART)
00f6f // @106 #539: load(UART_data,character_o)
3009d // @107 #540: call(send_to_UART)
00f77 // @108 #541: load(UART_data,character_w)
3009d // @109 #542: call(send_to_UART)
// @10a #543: [send_space_Error]
300e7 // @10a #543: call(send_space)
// #544: ;
// #545: ;Send 'Error' to the UART
// #546: ;
// @10b #547: [send_Error]
00f45 // @10b #547: load(UART_data,character_E)
3009d // @10c #548: call(send_to_UART)
00f72 // @10d #549: load(UART_data,character_r)
3009d // @10e #550: call(send_to_UART)
3009d // @10f #551: call(send_to_UART)
00f6f // @110 #552: load(UART_data,character_o)
3009d // @111 #553: call(send_to_UART)
00f72 // @112 #554: load(UART_data,character_r)
3009d // @113 #555: call(send_to_UART)
2a000 // @114 #556: return
// #557: ;
// #558: ;Send 'KCPSM3>' prompt to the UART
// #559: ;
// @115 #560: [send_prompt]
300e4 // @115 #560: call(send_CR) ;start new line
00f4b // @116 #561: load(UART_data,character_K)
3009d // @117 #562: call(send_to_UART)
00f43 // @118 #563: load(UART_data,character_C)
3009d // @119 #564: call(send_to_UART)
00f50 // @11a #565: load(UART_data,character_P)
3009d // @11b #566: call(send_to_UART)
00f53 // @11c #567: load(UART_data,character_S)
3009d // @11d #568: call(send_to_UART)
00f4d // @11e #569: load(UART_data,character_M)
3009d // @11f #570: call(send_to_UART)
00f33 // @120 #571: load(UART_data,character_3)
3009d // @121 #572: call(send_to_UART)
// #573: ;
// #574: ;Send '>' character to the UART
// #575: ;
// @122 #576: [send_greater_than]
00f3e // @122 #576: load(UART_data,character_greater_than)
3009d // @123 #577: call(send_to_UART)
2a000 // @124 #578: return
// #579: ;
// #580: ;Send 'Invalid' string to the UART
// #581: ;
// @125 #582: [send_Invalid]
00f49 // @125 #582: load(UART_data,character_I)
3009d // @126 #583: call(send_to_UART)
00f6e // @127 #584: load(UART_data,character_n)
3009d // @128 #585: call(send_to_UART)
00f76 // @129 #586: load(UART_data,character_v)
3009d // @12a #587: call(send_to_UART)
00f61 // @12b #588: load(UART_data,character_a)
3009d // @12c #589: call(send_to_UART)
00f6c // @12d #590: load(UART_data,character_l)
3009d // @12e #591: call(send_to_UART)
00f69 // @12f #592: load(UART_data,character_i)
3009d // @130 #593: call(send_to_UART)
00f64 // @131 #594: load(UART_data,character_d)
3009d // @132 #595: call(send_to_UART)
2a000 // @133 #596: return
// #597: ;
// #598: ;Send 'Time' string to the UART
// #599: ;
// @134 #600: [send_Time]
00f54 // @134 #600: load(UART_data,character_T)
3009d // @135 #601: call(send_to_UART)
00f69 // @136 #602: load(UART_data,character_i)
3009d // @137 #603: call(send_to_UART)
00f6d // @138 #604: load(UART_data,character_m)
3009d // @139 #605: call(send_to_UART)
00f65 // @13a #606: load(UART_data,character_e)
3009d // @13b #607: call(send_to_UART)
2a000 // @13c #608: return
// #609: ;
// #610: ;Send 'Alarm' string to the UART
// #611: ;
// @13d #612: [send_Alarm]
00f41 // @13d #612: load(UART_data,character_A)
3009d // @13e #613: call(send_to_UART)
00f6c // @13f #614: load(UART_data,character_l)
3009d // @140 #615: call(send_to_UART)
00f61 // @141 #616: load(UART_data,character_a)
3009d // @142 #617: call(send_to_UART)
00f72 // @143 #618: load(UART_data,character_r)
3009d // @144 #619: call(send_to_UART)
00f6d // @145 #620: load(UART_data,character_m)
3009d // @146 #621: call(send_to_UART)
2a000 // @147 #622: return
// #623: ;
// #624: ;Send 'OFF' string to the UART
// #625: ;
// @148 #626: [send_OFF]
00f4f // @148 #626: load(UART_data,character_O)
3009d // @149 #627: call(send_to_UART)
00f46 // @14a #628: load(UART_data,character_F)
3009d // @14b #629: call(send_to_UART)
3009d // @14c #630: call(send_to_UART)
2a000 // @14d #631: return
// #632: ;
// #633: ;Send 'ON' string to the UART
// #634: ;
// @14e #635: [send_ON]
00f4f // @14e #635: load(UART_data,character_O)
3009d // @14f #636: call(send_to_UART)
00f4e // @150 #637: load(UART_data,character_N)
3009d // @151 #638: call(send_to_UART)
2a000 // @152 #639: return
// #640: ;
// #641: ;Send 'Active' string to the UART
// #642: ;
// @153 #643: [send_Active]
00f41 // @153 #643: load(UART_data,character_A)
3009d // @154 #644: call(send_to_UART)
00f63 // @155 #645: load(UART_data,character_c)
3009d // @156 #646: call(send_to_UART)
00f74 // @157 #647: load(UART_data,character_t)
3009d // @158 #648: call(send_to_UART)
00f69 // @159 #649: load(UART_data,character_i)
3009d // @15a #650: call(send_to_UART)
00f76 // @15b #651: load(UART_data,character_v)
3009d // @15c #652: call(send_to_UART)
00f65 // @15d #653: load(UART_data,character_e)
3009d // @15e #654: call(send_to_UART)
2a000 // @15f #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: ;
// @160 #676: [time_to_ASCII]
00220 // @160 #676: load(s2,string_start) ;location for string
070e0 // @161 #677: fetch(s0,store_pointer) ;read hours value
3017e // @162 #678: call(decimal_to_ASCII) ;convert to ASCII
2f120 // @163 #679: store(s1,s2) ;write hours to string
18201 // @164 #680: add(s2,1)
2f020 // @165 #681: store(s0,s2)
18201 // @166 #682: add(s2,1)
0003a // @167 #683: load(s0,character_colon) ;write ':' to string
2f020 // @168 #684: store(s0,s2)
18201 // @169 #685: add(s2,1)
18e01 // @16a #686: add(store_pointer,1) ;move to minutes
070e0 // @16b #687: fetch(s0,store_pointer) ;read minutes value
3017e // @16c #688: call(decimal_to_ASCII) ;convert to ASCII
2f120 // @16d #689: store(s1,s2) ;write minutes to string
18201 // @16e #690: add(s2,1)
2f020 // @16f #691: store(s0,s2)
18201 // @170 #692: add(s2,1)
0003a // @171 #693: load(s0,character_colon) ;write ':' to string
2f020 // @172 #694: store(s0,s2)
18201 // @173 #695: add(s2,1)
18e01 // @174 #696: add(store_pointer,1) ;move to seconds
070e0 // @175 #697: fetch(s0,store_pointer) ;read seconds value
3017e // @176 #698: call(decimal_to_ASCII) ;convert to ASCII
2f120 // @177 #699: store(s1,s2) ;write seconds to string
18201 // @178 #700: add(s2,1)
2f020 // @179 #701: store(s0,s2)
18201 // @17a #702: add(s2,1)
0000d // @17b #703: load(s0,character_CR) ;finish string with carriage return
2f020 // @17c #704: store(s0,s2)
2a000 // @17d #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: ;
// @17e #719: [decimal_to_ASCII]
00130 // @17e #719: load(s1,48) ;load 'tens' counter with ASCII for '0'
// @17f #720: [test_for_ten]
18101 // @17f #720: add(s1,1) ;increment 'tens' value
1c00a // @180 #721: sub(s0,10) ;try to subtract 10 from the supplied value
35d7f // @181 #722: jump(nc,test_for_ten) ;repeat if subtraction was possible without underflow.
1c101 // @182 #723: sub(s1,1) ;'tens' value one less ten due to underflow
1803a // @183 #724: add(s0,58) ;restore units value (the remainder) and convert to ASCII
2a000 // @184 #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,232) ;lower 8-bits of 1000 count value
// #745: constant(count_1000_msb,3) ;upper 8-bits of 1000 count value
// #746: constant(hours_in_a_day,24) ;24 hours in a day
// #747: constant(minutes_in_an_hour,60) ;60 minutes in an hour
// #748: constant(seconds_in_a_minute,60) ;60 seconds in a minute
// #749: ;
// @185 #750: [update_time]
2e010 // @185 #750: store(s0,time_preserve0) ;preserve contents of registers used during routine
2e111 // @186 #751: store(s1,time_preserve1)
2e212 // @187 #752: store(s2,time_preserve2)
2e313 // @188 #753: store(s3,time_preserve3)
2e414 // @189 #754: store(s4,time_preserve4)
2e515 // @18a #755: store(s5,time_preserve5)
// #756: ;
06200 // @18b #757: fetch(s2,us_time_stamp_lsb) ;read the previous 'us' time stamp into [s3,s2]
06301 // @18c #758: fetch(s3,us_time_stamp_msb)
3c000 // @18d #759: interrupt(disable) ;Read and store current 'us' time stamp provided by the interrupt
2ed00 // @18e #760: store(int_counter_lsb,us_time_stamp_lsb) ;counter. Interrupts are disabled to ensure that both bytes relate
2ec01 // @18f #761: store(int_counter_msb,us_time_stamp_msb) ;to the same count value.
3c001 // @190 #762: interrupt(enable)
06400 // @191 #763: fetch(s4,us_time_stamp_lsb) ;read the new 'us' time stamp in [s5,s4]
06501 // @192 #764: fetch(s5,us_time_stamp_msb) ;
1d420 // @193 #765: sub(s4,s2) ;calculate 'us' time difference [s5,s4] = [s5,s4] - [s3,s2]
1f530 // @194 #766: subcy(s5,s3) ; (This works correctly even if counter has rolled over)
06202 // @195 #767: fetch(s2,us_time_lsb) ;read current 'us' time into [s3,s2]
06303 // @196 #768: fetch(s3,us_time_msb)
19240 // @197 #769: add(s2,s4) ;add on the elapsed 'us' value [s3,s2] = [s3,s2] + [s5,s4]
1b350 // @198 #770: addcy(s3,s5)
// #771: ;determine how many 1000us (1ms) units there are (if any) in current 'us' time
00000 // @199 #772: load(s0,0) ;reset 'ms' counter
// @19a #773: [test_1000us]
1c2e8 // @19a #773: sub(s2,count_1000_lsb) ;subtract 1000 from [s3,s2]
1e303 // @19b #774: subcy(s3,count_1000_msb)
3599f // @19c #775: jump(c,store_us_time) ;Carry indicates [s3,s2] was less than 1000us
18001 // @19d #776: add(s0,1) ;increment 'ms' elapsed because [s3,s2] was more or equal to 1000us
3419a // @19e #777: jump(test_1000us) ;repeat to see if more than 1ms has elapsed
// @19f #778: [store_us_time]
182e8 // @19f #778: add(s2,count_1000_lsb) ;add 1000 to restore 'us' value
1a303 // @1a0 #779: addcy(s3,count_1000_msb)
2e202 // @1a1 #780: store(s2,us_time_lsb) ;store the current value of 'us'
2e303 // @1a2 #781: store(s3,us_time_msb)
// #782: ;s0 holds the number of 'ms' elapsed since last update (if any).
06204 // @1a3 #783: fetch(s2,ms_time_lsb) ;read current 'ms' time into [s3,s2]
06305 // @1a4 #784: fetch(s3,ms_time_msb)
19200 // @1a5 #785: add(s2,s0) ;add on the elapsed 'ms' value [s3,s2] = [s3,s2] + s0
1a300 // @1a6 #786: addcy(s3,0)
// #787: ;determine if there are now more than 1000ms to form 1 second.
00000 // @1a7 #788: load(s0,0) ;reset 'second' counter
1c2e8 // @1a8 #789: sub(s2,count_1000_lsb) ;subtract 1000 from [s3,s2]
1e303 // @1a9 #790: subcy(s3,count_1000_msb)
359ad // @1aa #791: jump(c,restore_ms_time) ;Carry indicates [s3,s2] was less than 1000ms
18001 // @1ab #792: add(s0,1) ;increment 'second' elapsed because [s3,s2] was more or equal to 1000ms
341af // @1ac #793: jump(store_ms_time) ;new value of 'ms' is remainder of subtraction
// @1ad #794: [restore_ms_time]
182e8 // @1ad #794: add(s2,count_1000_lsb) ;add 1000 to restore 'ms' value
1a303 // @1ae #795: addcy(s3,count_1000_msb)
// @1af #796: [store_ms_time]
2e204 // @1af #796: store(s2,ms_time_lsb) ;store the current value of 'ms'
2e305 // @1b0 #797: store(s3,ms_time_msb)
// #798: ;s0 currently determines if one second needs to be added to the hh:mm:ss clock time
06108 // @1b1 #799: fetch(s1,real_time_seconds) ;read seconds
19100 // @1b2 #800: add(s1,s0) ;add one second if required by s0
1413c // @1b3 #801: compare(s1,seconds_in_a_minute) ;test for 1 minute
351b7 // @1b4 #802: jump(z,inc_minutes)
2e108 // @1b5 #803: store(s1,real_time_seconds) ;store updated seconds
341c9 // @1b6 #804: jump(time_update_complete)
// @1b7 #805: [inc_minutes]
00100 // @1b7 #805: load(s1,0) ;seconds become zero
2e108 // @1b8 #806: store(s1,real_time_seconds)
06107 // @1b9 #807: fetch(s1,real_time_minutes) ;read minutes
18101 // @1ba #808: add(s1,1) ;increment minutes
1413c // @1bb #809: compare(s1,minutes_in_an_hour) ;test for 1 hour
351bf // @1bc #810: jump(z,inc_hours)
2e107 // @1bd #811: store(s1,real_time_minutes) ;store updated minutes
341c9 // @1be #812: jump(time_update_complete)
// @1bf #813: [inc_hours]
00100 // @1bf #813: load(s1,0) ;minutes become zero
2e107 // @1c0 #814: store(s1,real_time_minutes)
06106 // @1c1 #815: fetch(s1,real_time_hours) ;read hours
18101 // @1c2 #816: add(s1,1) ;increment hours
14118 // @1c3 #817: compare(s1,hours_in_a_day) ;test for 24 hours
351c7 // @1c4 #818: jump(z,reset_hours)
2e106 // @1c5 #819: store(s1,real_time_hours) ;store updated hours
341c9 // @1c6 #820: jump(time_update_complete)
// @1c7 #821: [reset_hours]
00100 // @1c7 #821: load(s1,0) ;hours become zero
2e106 // @1c8 #822: store(s1,real_time_hours)
// #823: ;
// #824: ;With the time updated, there is then a test for time=alarm time
// #825: ;
// @1c9 #826: [time_update_complete]
06006 // @1c9 #826: fetch(s0,real_time_hours)
06109 // @1ca #827: fetch(s1,alarm_time_hours) ;compare hours
15010 // @1cb #828: compare(s0,s1)
355db // @1cc #829: jump(nz,finish_update)
06007 // @1cd #830: fetch(s0,real_time_minutes) ;compare minutes
0610a // @1ce #831: fetch(s1,alarm_time_minutes)
15010 // @1cf #832: compare(s0,s1)
355db // @1d0 #833: jump(nz,finish_update)
06008 // @1d1 #834: fetch(s0,real_time_seconds) ;compare seconds
0610b // @1d2 #835: fetch(s1,alarm_time_seconds)
15010 // @1d3 #836: compare(s0,s1)
355db // @1d4 #837: jump(nz,finish_update)
0600c // @1d5 #838: fetch(s0,alarm_status) ;test if alarm is turned on
12002 // @1d6 #839: test(s0,alarm_armed)
351db // @1d7 #840: jump(z,finish_update) ;alarm was off
0c001 // @1d8 #841: or(s0,alarm_active) ;activate alarm
2e00c // @1d9 #842: store(s0,alarm_status)
300a4 // @1da #843: call(alarm_drive)
// @1db #844: [finish_update]
06010 // @1db #844: fetch(s0,time_preserve0) ;restore the register contents
06111 // @1dc #845: fetch(s1,time_preserve1)
06212 // @1dd #846: fetch(s2,time_preserve2)
06313 // @1de #847: fetch(s3,time_preserve3)
06414 // @1df #848: fetch(s4,time_preserve4)
06515 // @1e0 #849: fetch(s5,time_preserve5)
2a000 // @1e1 #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: ;
// @1e2 #861: [upper_case]
14061 // @1e2 #861: compare(s0,97) ;eliminate character codes below 'a' (61 hex)
2b800 // @1e3 #862: return(c)
1407b // @1e4 #863: compare(s0,123) ;eliminate character codes above 'z' (7A hex)
2bc00 // @1e5 #864: return(nc)
0a0df // @1e6 #865: and(s0,223) ;mask bit5 to convert to upper case
2a000 // @1e7 #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: ;
// @1e8 #878: [_1char_to_value]
180c6 // @1e8 #878: add(s0,198) ;reject character codes above '9' (39 hex)
2b800 // @1e9 #879: return(c) ;carry flag is set
1c0f6 // @1ea #880: sub(s0,246) ;reject character codes below '0' (30 hex)
2a000 // @1eb #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: ;
// @1ec #894: [_2char_to_value]
07010 // @1ec #894: fetch(s0,s1) ;read 'tens' character
301e8 // @1ed #895: call(_1char_to_value) ;convert to numerical value
2b800 // @1ee #896: return(c) ;bad character - CARRY set
01200 // @1ef #897: load(s2,s0)
20206 // @1f0 #898: sl0(s2) ;multiply 'tens' value by 10 (0A hex)
20206 // @1f1 #899: sl0(s2)
19200 // @1f2 #900: add(s2,s0)
20206 // @1f3 #901: sl0(s2)
18101 // @1f4 #902: add(s1,1) ;read 'units' character
07010 // @1f5 #903: fetch(s0,s1)
301e8 // @1f6 #904: call(_1char_to_value) ;convert to numerical value
2b800 // @1f7 #905: return(c) ;bad character - CARRY set
19200 // @1f8 #906: add(s2,s0) ;add units to result and clear CARRY flag
2a000 // @1f9 #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: ;
@3fc // #920: address(1020)
// @3fc #921: [ISR]
18d01 // @3fc #921: add(int_counter_lsb,1) ;add 1us to 16-bit counter
1ac00 // @3fd #922: addcy(int_counter_msb,0)
38001 // @3fe #923: returni(enable)
// #924: ;
// #925: ;Interrupt vector
// #926: ;
@3ff // #927: address(1023)
343fc // @3ff #928: jump(ISR)
// #929: ;
// #930: ;
// #931: ;Useful constants
// #932: ;
// #933: ;
// #934: ;ASCII table
// #935: ;
// #936: constant(character_a,97)
// #937: constant(character_b,98)
// #938: constant(character_c,99)
// #939: constant(character_d,100)
// #940: constant(character_e,101)
// #941: constant(character_f,102)
// #942: constant(character_g,103)
// #943: constant(character_h,104)
// #944: constant(character_i,105)
// #945: constant(character_j,106)
// #946: constant(character_k,107)
// #947: constant(character_l,108)
// #948: constant(character_m,109)
// #949: constant(character_n,110)
// #950: constant(character_o,111)
// #951: constant(character_p,112)
// #952: constant(character_q,113)
// #953: constant(character_r,114)
// #954: constant(character_s,115)
// #955: constant(character_t,116)
// #956: constant(character_u,117)
// #957: constant(character_v,118)
// #958: constant(character_w,119)
// #959: constant(character_x,120)
// #960: constant(character_y,121)
// #961: constant(character_z,122)
// #962: constant(character_A,65)
// #963: constant(character_B,66)
// #964: constant(character_C,67)
// #965: constant(character_D,68)
// #966: constant(character_E,69)
// #967: constant(character_F,70)
// #968: constant(character_G,71)
// #969: constant(character_H,72)
// #970: constant(character_I,73)
// #971: constant(character_J,74)
// #972: constant(character_K,75)
// #973: constant(character_L,76)
// #974: constant(character_M,77)
// #975: constant(character_N,78)
// #976: constant(character_O,79)
// #977: constant(character_P,80)
// #978: constant(character_Q,81)
// #979: constant(character_R,82)
// #980: constant(character_S,83)
// #981: constant(character_T,84)
// #982: constant(character_U,85)
// #983: constant(character_V,86)
// #984: constant(character_W,87)
// #985: constant(character_X,88)
// #986: constant(character_Y,89)
// #987: constant(character_Z,90)
// #988: constant(character_0,48)
// #989: constant(character_1,49)
// #990: constant(character_2,50)
// #991: constant(character_3,51)
// #992: constant(character_4,52)
// #993: constant(character_5,53)
// #994: constant(character_6,54)
// #995: constant(character_7,55)
// #996: constant(character_8,56)
// #997: constant(character_9,57)
// #998: constant(character_colon,58)
// #999: constant(character_semi_colon,59)
// #1000: constant(character_less_than,60)
// #1001: constant(character_greater_than,62)
// #1002: constant(character_equals,61)
// #1003: constant(character_space,32)
// #1004: constant(character_CR,13) ;carriage return
// #1005: constant(character_question,63) ;'?'
// #1006: constant(character_dollar,36)
// #1007: constant(character_BS,8) ;Back Space command character
// #1008: ;