git-svn-id: http://moon:8086/svn/vhdl/trunk@1416 cc03376c-175c-47c8-b038-4cd826a8556b
1016 lines
74 KiB
Plaintext
1016 lines
74 KiB
Plaintext
KCPSM3 Assembler log file for program 'uclock.psm'.
|
|
Generated by KCPSM3 version 1.30
|
|
Ken Chapman (Xilinx Ltd) 2005.
|
|
25Sep2005-15:52:57
|
|
|
|
Addr Code
|
|
|
|
000 ;KCPSM3 Program - Real Time Clock with UART communication.
|
|
000 ;
|
|
000 ;Ken Chapman - Xilinx Ltd - October 2003
|
|
000 ;
|
|
000 ;
|
|
000 ;Port definitions
|
|
000 ;
|
|
000 CONSTANT UART_status_port, 00 ;UART status input
|
|
000 CONSTANT tx_half_full, 01 ; Transmitter half full - bit0
|
|
000 CONSTANT tx_full, 02 ; FIFO full - bit1
|
|
000 CONSTANT rx_half_full, 04 ; Receiver half full - bit2
|
|
000 CONSTANT rx_full, 08 ; FIFO full - bit3
|
|
000 CONSTANT rx_data_present, 10 ; data present - bit4
|
|
000 ;
|
|
000 CONSTANT UART_read_port, 01 ;UART Rx data input
|
|
000 ;
|
|
000 CONSTANT UART_write_port, 01 ;UART Tx data output
|
|
000 ;
|
|
000 CONSTANT alarm_port, 00 ;Alarm output
|
|
000 CONSTANT alarm_control, 01 ; bit0
|
|
000 ;
|
|
000 ;Special Register usage
|
|
000 ;
|
|
000 NAMEREG sF, UART_data ;used to pass data to and from the UART
|
|
000 ;
|
|
000 NAMEREG sE, store_pointer ;used to pass location of data in scratch pad memory
|
|
000 ;
|
|
000 ;Two registers to form a 16-bit counter used to count
|
|
000 ;interrupt pulses generated at 1us intervals.
|
|
000 ;
|
|
000 NAMEREG sD, int_counter_lsb ;lower 8-bits
|
|
000 NAMEREG sC, int_counter_msb ;upper 8-bits
|
|
000 ;
|
|
000 ;
|
|
000 ;Scratch Pad Memory Locations
|
|
000 ;
|
|
000 ;
|
|
000 CONSTANT us_time_stamp_lsb, 00 ;16-bit micro-second time stamp
|
|
000 CONSTANT us_time_stamp_msb, 01
|
|
000 ;
|
|
000 CONSTANT us_time_lsb, 02 ;16-bit micro-second real time value
|
|
000 CONSTANT us_time_msb, 03
|
|
000 ;
|
|
000 CONSTANT ms_time_lsb, 04 ;16-bit milli-second real time value
|
|
000 CONSTANT ms_time_msb, 05
|
|
000 ;
|
|
000 CONSTANT real_time_hours, 06 ;Current clock time
|
|
000 CONSTANT real_time_minutes, 07
|
|
000 CONSTANT real_time_seconds, 08
|
|
000 ;
|
|
000 CONSTANT alarm_time_hours, 09 ;Alarm time
|
|
000 CONSTANT alarm_time_minutes, 0A
|
|
000 CONSTANT alarm_time_seconds, 0B
|
|
000 ;
|
|
000 CONSTANT alarm_status, 0C ;Alarm status
|
|
000 CONSTANT alarm_active, 01 ; bit0 - Alarm is active
|
|
000 CONSTANT alarm_armed, 02 ; bit1 - Alarm is armed
|
|
000 ;
|
|
000 CONSTANT time_preserve0, 10 ;storage for protection of registers
|
|
000 CONSTANT time_preserve1, 11 ;used by the real time clock routine.
|
|
000 CONSTANT time_preserve2, 12
|
|
000 CONSTANT time_preserve3, 13
|
|
000 CONSTANT time_preserve4, 14
|
|
000 CONSTANT time_preserve5, 15
|
|
000 ;
|
|
000 ;UART character strings will be stored in scratch pad memory ending in carriage return.
|
|
000 ;A string can be up to 16 characters with the start location defined by this constant.
|
|
000 ;
|
|
000 CONSTANT string_start, 20
|
|
000 ;
|
|
000 ;
|
|
000 ;Initialise the system
|
|
000 ;
|
|
000 ;
|
|
000 00000 cold_start: LOAD s0, 00 ;clear all time values
|
|
001 2E000 STORE s0, us_time_stamp_lsb[00]
|
|
002 2E001 STORE s0, us_time_stamp_msb[01]
|
|
003 2E002 STORE s0, us_time_lsb[02]
|
|
004 2E003 STORE s0, us_time_msb[03]
|
|
005 2E004 STORE s0, ms_time_lsb[04]
|
|
006 2E005 STORE s0, ms_time_msb[05]
|
|
007 2E006 STORE s0, real_time_hours[06]
|
|
008 2E007 STORE s0, real_time_minutes[07]
|
|
009 2E008 STORE s0, real_time_seconds[08]
|
|
00A 2E009 STORE s0, alarm_time_hours[09]
|
|
00B 2E00A STORE s0, alarm_time_minutes[0A]
|
|
00C 2E00B STORE s0, alarm_time_seconds[0B]
|
|
00D 2E00C STORE s0, alarm_status[0C] ;clear and disable alarm
|
|
00E 300A4 CALL alarm_drive[0A4] ;turn off alarm control output port
|
|
00F 00D00 LOAD int_counter_lsb[sD], 00 ;clear 'us' interrupt counter
|
|
010 00C00 LOAD int_counter_msb[sC], 00
|
|
011 3C001 ENABLE INTERRUPT ;enable the 1us interrupts
|
|
012 ;
|
|
012 ;
|
|
012 ;Start of the main program loop.
|
|
012 ;
|
|
012 ;A prompt is transmitted to the UART transmitter and then
|
|
012 ;a command can be entered and interpreted.
|
|
012 ;
|
|
012 ;
|
|
012 30115 prompt_input: CALL send_prompt[115] ;Prompt 'KCPSM3>'
|
|
013 300C3 CALL receive_string[0C3] ;obtain input string and maintain the time
|
|
014 ;
|
|
014 ;
|
|
014 ;Parse the string and perform actions as required
|
|
014 ;
|
|
014 ;
|
|
014 ;
|
|
014 00120 LOAD s1, string_start[20]
|
|
015 30091 CALL fetch_char_from_memory[091]
|
|
016 1400D COMPARE s0, character_CR[0D] ;carriage return does nothing
|
|
017 35012 JUMP Z, prompt_input[012]
|
|
018 14054 COMPARE s0, character_T[54] ;start of 'TIME' command?
|
|
019 3501E JUMP Z, test_for_TIME[01E]
|
|
01A 14041 COMPARE s0, character_A[41] ;start of 'ALARM' command?
|
|
01B 35037 JUMP Z, test_for_ALARM[037]
|
|
01C ;
|
|
01C ;trap other command starts here
|
|
01C ;
|
|
01C 300ED bad_input_command: CALL send_Syntax_Error[0ED] ;no valid command
|
|
01D 35012 JUMP Z, prompt_input[012]
|
|
01E ;
|
|
01E ;
|
|
01E 30091 test_for_TIME: CALL fetch_char_from_memory[091]
|
|
01F 14049 COMPARE s0, character_I[49] ;test for rest of 'TIME'
|
|
020 3541C JUMP NZ, bad_input_command[01C]
|
|
021 30091 CALL fetch_char_from_memory[091]
|
|
022 1404D COMPARE s0, character_M[4D]
|
|
023 3541C JUMP NZ, bad_input_command[01C]
|
|
024 30091 CALL fetch_char_from_memory[091]
|
|
025 14045 COMPARE s0, character_E[45]
|
|
026 3541C JUMP NZ, bad_input_command[01C]
|
|
027 ;now have a valid TIME command to process
|
|
027 30091 CALL fetch_char_from_memory[091]
|
|
028 1400D COMPARE s0, character_CR[0D] ;carriage return means display time
|
|
029 3542C JUMP NZ, set_time_command[02C]
|
|
02A 300A8 CALL transmit_time[0A8] ;transmit time to UART
|
|
02B 34012 JUMP prompt_input[012]
|
|
02C 14020 set_time_command: COMPARE s0, character_space[20]
|
|
02D 3541C JUMP NZ, bad_input_command[01C]
|
|
02E 3006D CALL test_time_string[06D] ;interpret 'hh:mm:ss' string
|
|
02F 35812 JUMP C, prompt_input[012] ;test for invalid input
|
|
030 2E606 STORE s6, real_time_hours[06] ;set new time into clock
|
|
031 2E507 STORE s5, real_time_minutes[07]
|
|
032 2E408 STORE s4, real_time_seconds[08]
|
|
033 2E004 STORE s0, ms_time_lsb[04] ;clear 'ms' counter (s0=00)
|
|
034 2E005 STORE s0, ms_time_msb[05]
|
|
035 300A8 CALL transmit_time[0A8] ;transmit new time to UART
|
|
036 34012 JUMP prompt_input[012]
|
|
037 ;
|
|
037 ;
|
|
037 30091 test_for_ALARM: CALL fetch_char_from_memory[091]
|
|
038 1404C COMPARE s0, character_L[4C] ;test for rest of 'ALARM'
|
|
039 3541C JUMP NZ, bad_input_command[01C]
|
|
03A 30091 CALL fetch_char_from_memory[091]
|
|
03B 14041 COMPARE s0, character_A[41]
|
|
03C 3541C JUMP NZ, bad_input_command[01C]
|
|
03D 30091 CALL fetch_char_from_memory[091]
|
|
03E 14052 COMPARE s0, character_R[52]
|
|
03F 3541C JUMP NZ, bad_input_command[01C]
|
|
040 30091 CALL fetch_char_from_memory[091]
|
|
041 1404D COMPARE s0, character_M[4D]
|
|
042 3541C JUMP NZ, bad_input_command[01C]
|
|
043 ;now have a valid ALARM command to process
|
|
043 30091 CALL fetch_char_from_memory[091]
|
|
044 1400D COMPARE s0, character_CR[0D] ;carriage return means display alarm time
|
|
045 35448 JUMP NZ, set_alarm_command[048]
|
|
046 300AC CALL transmit_alarm_time[0AC] ;transmit time to UART
|
|
047 34012 JUMP prompt_input[012]
|
|
048 14020 set_alarm_command: COMPARE s0, character_space[20] ;test for ON or OFF command
|
|
049 3541C JUMP NZ, bad_input_command[01C]
|
|
04A 30091 CALL fetch_char_from_memory[091]
|
|
04B 1404F COMPARE s0, character_O[4F]
|
|
04C 35055 JUMP Z, set_alarm_on_off[055]
|
|
04D 1C101 SUB s1, 01 ;move memory pointer back to first character of 'hh:mm:ss' string
|
|
04E 3006D CALL test_time_string[06D] ;interpret 'hh:mm:ss' string
|
|
04F 35812 JUMP C, prompt_input[012] ;test for invalid input
|
|
050 2E609 STORE s6, alarm_time_hours[09] ;set new time into clock
|
|
051 2E50A STORE s5, alarm_time_minutes[0A]
|
|
052 2E40B STORE s4, alarm_time_seconds[0B]
|
|
053 300AC CALL transmit_alarm_time[0AC] ;transmit new alarm time and status
|
|
054 34012 JUMP prompt_input[012]
|
|
055 30091 set_alarm_on_off: CALL fetch_char_from_memory[091]
|
|
056 1404E COMPARE s0, character_N[4E] ;test for 'ON'
|
|
057 35460 JUMP NZ, test_OFF[060]
|
|
058 30091 CALL fetch_char_from_memory[091]
|
|
059 1400D COMPARE s0, character_CR[0D]
|
|
05A 3541C JUMP NZ, bad_input_command[01C]
|
|
05B 0600C FETCH s0, alarm_status[0C] ;turn alarm on
|
|
05C 0C002 OR s0, alarm_armed[02]
|
|
05D 2E00C STORE s0, alarm_status[0C]
|
|
05E 300AC CALL transmit_alarm_time[0AC] ;transmit alarm time and status
|
|
05F 34012 JUMP prompt_input[012]
|
|
060 14046 test_OFF: COMPARE s0, character_F[46] ;test for for 'OFF'
|
|
061 3541C JUMP NZ, bad_input_command[01C]
|
|
062 30091 CALL fetch_char_from_memory[091]
|
|
063 14046 COMPARE s0, character_F[46]
|
|
064 3541C JUMP NZ, bad_input_command[01C]
|
|
065 30091 CALL fetch_char_from_memory[091]
|
|
066 1400D COMPARE s0, character_CR[0D]
|
|
067 3541C JUMP NZ, bad_input_command[01C]
|
|
068 00000 LOAD s0, 00 ;turn alarm off and stop an active alarm
|
|
069 2E00C STORE s0, alarm_status[0C]
|
|
06A 300A4 CALL alarm_drive[0A4] ;turn off alarm
|
|
06B 300AC CALL transmit_alarm_time[0AC] ;transmit alarm time and status
|
|
06C 34012 JUMP prompt_input[012]
|
|
06D ;
|
|
06D ;
|
|
06D ;
|
|
06D ;
|
|
06D ;Read an 'hh:mm:ss' time string and provide new values.
|
|
06D ;
|
|
06D ;The string must be provided in successive scratch pad memory locations
|
|
06D ;with the s1 register containing the location of the first character.
|
|
06D ;
|
|
06D ;A correct time specification will result in the return of new values
|
|
06D ;as follows:-
|
|
06D ;
|
|
06D ; s6 = hours
|
|
06D ; s5 = minutes
|
|
06D ; s4 = seconds
|
|
06D ;
|
|
06D ;If the syntax is incorrect or values are not in the correct ranges an
|
|
06D ;'Invalid Time' message will be transmitted and the CARRY flag will be set
|
|
06D ;
|
|
06D ;Registers used s0, s1, s6, s5 and s4
|
|
06D ;
|
|
06D 301EC test_time_string: CALL 2char_to_value[1EC] ;obtain hours value
|
|
06E 3588B JUMP C, invalid_time[08B] ;test for non-decimal characters
|
|
06F 01620 LOAD s6, s2 ;remember hours
|
|
070 18101 ADD s1, 01 ;increment memory pointer past hours
|
|
071 30091 CALL fetch_char_from_memory[091]
|
|
072 1403A COMPARE s0, character_colon[3A] ;test for colon
|
|
073 3548B JUMP NZ, invalid_time[08B]
|
|
074 301EC CALL 2char_to_value[1EC] ;obtain minutes value
|
|
075 3588B JUMP C, invalid_time[08B] ;test for non-decimal characters
|
|
076 01520 LOAD s5, s2 ;remember minutes
|
|
077 18101 ADD s1, 01 ;increment memory pointer past minutes
|
|
078 30091 CALL fetch_char_from_memory[091]
|
|
079 1403A COMPARE s0, character_colon[3A] ;test for colon
|
|
07A 3548B JUMP NZ, invalid_time[08B]
|
|
07B 301EC CALL 2char_to_value[1EC] ;obtain seconds value
|
|
07C 3588B JUMP C, invalid_time[08B] ;test for non-decimal characters
|
|
07D 01420 LOAD s4, s2 ;remember minutes
|
|
07E 18101 ADD s1, 01 ;increment memory pointer past seconds
|
|
07F 30091 CALL fetch_char_from_memory[091]
|
|
080 1400D COMPARE s0, character_CR[0D] ;finish with carriage return
|
|
081 3548B JUMP NZ, invalid_time[08B]
|
|
082 ;Have values for hh:mm:ss but need to test if each is valid range.
|
|
082 14618 COMPARE s6, hours_in_a_day[18]
|
|
083 35C8B JUMP NC, invalid_time[08B]
|
|
084 1453C COMPARE s5, minutes_in_an_hour[3C]
|
|
085 35C8B JUMP NC, invalid_time[08B]
|
|
086 1443C COMPARE s4, seconds_in_a_minute[3C]
|
|
087 35C8B JUMP NC, invalid_time[08B]
|
|
088 00000 LOAD s0, 00
|
|
089 2000E SR0 s0 ;reset CARRY flag (with s0=0)
|
|
08A 2A000 RETURN ;time string was OK
|
|
08B 30125 invalid_time: CALL send_Invalid[125]
|
|
08C 300E7 CALL send_space[0E7]
|
|
08D 30134 CALL send_Time[134]
|
|
08E 00001 LOAD s0, 01
|
|
08F 2000E SR0 s0 ;set CARRY flag
|
|
090 2A000 RETURN ;time string was bad
|
|
091 ;
|
|
091 ;
|
|
091 ;Fetch character from memory, convert to upper case
|
|
091 ;and increment memory pointer.
|
|
091 ;
|
|
091 ;The memory pointer is provided in register s1.
|
|
091 ;The character obtained is returned in register s0.
|
|
091 ;
|
|
091 ;Registers used s0 and s1.
|
|
091 ;
|
|
091 07010 fetch_char_from_memory: FETCH s0, (s1) ;read character
|
|
092 301E2 CALL upper_case[1E2] ;convert to upper case
|
|
093 18101 ADD s1, 01 ;increment memory pointer
|
|
094 2A000 RETURN
|
|
095 ;
|
|
095 ;
|
|
095 ;
|
|
095 ;Read one character from the UART
|
|
095 ;
|
|
095 ;Character read will be returned in a register called 'UART_data' and will be
|
|
095 ;echoed to the UART transmitter.
|
|
095 ;
|
|
095 ;The routine first tests the receiver FIFO buffer to see if data is present.
|
|
095 ;If the FIFO is empty, the routine waits until there is a character to read.
|
|
095 ;As this could take any amount of time the wait loop includes a call to the
|
|
095 ;subroutine which updates the real time clock.
|
|
095 ;
|
|
095 ;Registers used s0 and UART_data
|
|
095 ;
|
|
095 04000 read_from_UART: INPUT s0, UART_status_port[00] ;test Rx_FIFO buffer
|
|
096 12010 TEST s0, rx_data_present[10]
|
|
097 3549A JUMP NZ, read_character[09A]
|
|
098 30185 CALL update_time[185] ;Perform useful operation whilst waiting
|
|
099 34095 JUMP read_from_UART[095]
|
|
09A 04F01 read_character: INPUT UART_data[sF], UART_read_port[01] ;read from FIFO
|
|
09B 3009D CALL send_to_UART[09D] ;echo received character
|
|
09C 2A000 RETURN
|
|
09D ;
|
|
09D ;
|
|
09D ;
|
|
09D ;Transmit one character to the UART
|
|
09D ;
|
|
09D ;Character supplied in register called 'UART_data'.
|
|
09D ;
|
|
09D ;The routine first tests the transmit FIFO buffer to see if it is full.
|
|
09D ;If the FIFO is full, the routine waits until there is space which could
|
|
09D ;be as long as it takes to transmit one complete character.
|
|
09D ;
|
|
09D ; Baud Rate Time per Character (10 bits)
|
|
09D ; 9600 1,024us
|
|
09D ; 19200 521us
|
|
09D ; 38400 260us
|
|
09D ; 57600 174us
|
|
09D ; 115200 87us
|
|
09D ;
|
|
09D ;Since this is a relatively long duration, the wait loop includes a
|
|
09D ;call to the subroutine which updates the real time clock.
|
|
09D ;
|
|
09D ;Registers used s0
|
|
09D ;
|
|
09D 04000 send_to_UART: INPUT s0, UART_status_port[00] ;test Tx_FIFO buffer
|
|
09E 12002 TEST s0, tx_full[02]
|
|
09F 350A2 JUMP Z, UART_write[0A2]
|
|
0A0 30185 CALL update_time[185] ;Perform useful operation whilst waiting
|
|
0A1 3409D JUMP send_to_UART[09D]
|
|
0A2 2CF01 UART_write: OUTPUT UART_data[sF], UART_write_port[01]
|
|
0A3 2A000 RETURN
|
|
0A4 ;
|
|
0A4 ;
|
|
0A4 ;
|
|
0A4 ;
|
|
0A4 ;Alarm output
|
|
0A4 ;
|
|
0A4 ;Uses the alarm status scratch pad memory to set or reset the alarm
|
|
0A4 ;control bit on the alarm output port.
|
|
0A4 ;
|
|
0A4 ;Registers used s0
|
|
0A4 ;
|
|
0A4 0600C alarm_drive: FETCH s0, alarm_status[0C] ;read status
|
|
0A5 0A001 AND s0, alarm_active[01] ;isolate bit0
|
|
0A6 2C000 OUTPUT s0, alarm_port[00]
|
|
0A7 2A000 RETURN
|
|
0A8 ;
|
|
0A8 ;
|
|
0A8 ;
|
|
0A8 ;
|
|
0A8 ;
|
|
0A8 ;Transmit the time to the UART port in the format hh:mm:ss and end
|
|
0A8 ;with a carriage return.
|
|
0A8 ;
|
|
0A8 ;The time to converted must be stored in 3 scratch pad memory locations as
|
|
0A8 ;defined below. A register named 'store_pointer' must provide the address of
|
|
0A8 ;first location.
|
|
0A8 ;
|
|
0A8 ; Address Data
|
|
0A8 ;
|
|
0A8 ; store_pointer ----> hours
|
|
0A8 ; store_pointer + 1 ----> minutes
|
|
0A8 ; store_pointer + 1 ----> seconds
|
|
0A8 ;
|
|
0A8 ;The routine first converts the time into an ASCII string stored in scratch
|
|
0A8 ;pad memory starting at a location specified by a constant named 'string_start'.
|
|
0A8 ;The string will then be transmitted.
|
|
0A8 ;
|
|
0A8 ;Registers used s0, s1, s2, 'store_pointer' and 'UART_data'.
|
|
0A8 ;
|
|
0A8 00E06 transmit_time: LOAD store_pointer[sE], real_time_hours[06] ;locate current time in memory
|
|
0A9 30160 CALL time_to_ASCII[160]
|
|
0AA 300BC CALL transmit_string[0BC]
|
|
0AB 2A000 RETURN
|
|
0AC ;
|
|
0AC ;
|
|
0AC ;Transmit the alarm time and status to the UART port in the format hh:mm:ss and
|
|
0AC ;ending with carriage return.
|
|
0AC ;
|
|
0AC ;The alarm time to converted must be stored in 3 scratch pad memory locations as
|
|
0AC ;defined below. A register named 'store_pointer' must provide the address of
|
|
0AC ;first location.
|
|
0AC ;
|
|
0AC ; Address Data
|
|
0AC ;
|
|
0AC ; store_pointer ----> hours
|
|
0AC ; store_pointer + 1 ----> minutes
|
|
0AC ; store_pointer + 1 ----> seconds
|
|
0AC ;
|
|
0AC ;The routine first converts the time into an ASCII string stored in scratch
|
|
0AC ;pad memory starting at a location specified by a constant named 'string_start'.
|
|
0AC ;The string will then be transmitted.
|
|
0AC ;
|
|
0AC ;Registers used s0, s1, s2, 'store_pointer' and 'UART_data'.
|
|
0AC ;
|
|
0AC 00E09 transmit_alarm_time: LOAD store_pointer[sE], alarm_time_hours[09] ;locate alarm time in memory
|
|
0AD 30160 CALL time_to_ASCII[160]
|
|
0AE 300BC CALL transmit_string[0BC]
|
|
0AF 3013D CALL send_Alarm[13D]
|
|
0B0 300E7 CALL send_space[0E7]
|
|
0B1 0600C FETCH s0, alarm_status[0C] ;read alarm status
|
|
0B2 12001 TEST s0, alarm_active[01] ;test for active
|
|
0B3 350B6 JUMP Z, test_armed[0B6]
|
|
0B4 30153 CALL send_Active[153]
|
|
0B5 2A000 RETURN
|
|
0B6 12002 test_armed: TEST s0, alarm_armed[02] ;test for on
|
|
0B7 350BA JUMP Z, alarm_is_off[0BA]
|
|
0B8 3014E CALL send_ON[14E]
|
|
0B9 2A000 RETURN
|
|
0BA 30148 alarm_is_off: CALL send_OFF[148]
|
|
0BB 2A000 RETURN
|
|
0BC ;
|
|
0BC ;
|
|
0BC ;Transmit ASCII string to UART
|
|
0BC ;
|
|
0BC ;An ASCII string must be provided in scratch pad memory commencing at the
|
|
0BC ;location specified by a constant named 'string_start'. The string must
|
|
0BC ;end with a carriage return (0D).
|
|
0BC ;
|
|
0BC ;Registers used s1 and 'UART_data'.
|
|
0BC ; s0 is then used in subroutine 'send_to_UART'
|
|
0BC ;
|
|
0BC 00120 transmit_string: LOAD s1, string_start[20] ;locate start of string
|
|
0BD 07F10 next_char_tx: FETCH UART_data[sF], (s1) ;read character from memory
|
|
0BE 3009D CALL send_to_UART[09D] ;transmit character
|
|
0BF 14F0D COMPARE UART_data[sF], character_CR[0D] ;test for last character
|
|
0C0 2B000 RETURN Z
|
|
0C1 18101 ADD s1, 01 ;move to next character
|
|
0C2 340BD JUMP next_char_tx[0BD]
|
|
0C3 ;
|
|
0C3 ;
|
|
0C3 ;Receive ASCII string from UART
|
|
0C3 ;
|
|
0C3 ;An ASCII string will be read from the UART and stored in scratch pad memory
|
|
0C3 ;commencing at the location specified by a constant named 'string_start'.
|
|
0C3 ;The string will will have a maximum length of 16 characters including a
|
|
0C3 ;carriage return (0D) denoting the end of the string.
|
|
0C3 ;
|
|
0C3 ;As each character is read, it is echoed to the UART transmitter.
|
|
0C3 ;Some minor editing is supported using backspace (BS=08) which is used
|
|
0C3 ;to adjust what is stored in scratch pad memory and adjust the display
|
|
0C3 ;on the terminal screen using characters sent to the UART transmitter.
|
|
0C3 ;
|
|
0C3 ;A test is made for the receiver FIFO becoming full. A full status is treated as
|
|
0C3 ;a potential error situation and will result in a 'Overflow Error' message being
|
|
0C3 ;transmitted to the UART, the receiver FIFO being purged of all data and an
|
|
0C3 ;empty string being stored (carriage return at first location).
|
|
0C3 ;
|
|
0C3 ;Registers used s0, s1, s2 and 'UART_data'.
|
|
0C3 ;
|
|
0C3 00120 receive_string: LOAD s1, string_start[20] ;locate start of string
|
|
0C4 01210 LOAD s2, s1 ;compute 16 character address
|
|
0C5 18210 ADD s2, 10
|
|
0C6 04000 receive_full_test: INPUT s0, UART_status_port[00] ;test Rx_FIFO buffer for full
|
|
0C7 12008 TEST s0, rx_full[08]
|
|
0C8 354DB JUMP NZ, read_error[0DB]
|
|
0C9 30095 CALL read_from_UART[095] ;obtain and echo character
|
|
0CA 2FF10 STORE UART_data[sF], (s1) ;write to memory
|
|
0CB 14F0D COMPARE UART_data[sF], character_CR[0D] ;test for end of string
|
|
0CC 2B000 RETURN Z
|
|
0CD 14F08 COMPARE UART_data[sF], character_BS[08] ;test for back space
|
|
0CE 350D3 JUMP Z, BS_edit[0D3]
|
|
0CF 18101 ADD s1, 01 ;increment memory pointer
|
|
0D0 15120 COMPARE s1, s2 ;test for pointer exceeding 16 characters
|
|
0D1 354C6 JUMP NZ, receive_full_test[0C6] ;next character
|
|
0D2 300EA CALL send_backspace[0EA] ;hold end of string position on terminal display
|
|
0D3 1C101 BS_edit: SUB s1, 01 ;memory pointer back one
|
|
0D4 14120 COMPARE s1, string_start[20] ;test for under flow
|
|
0D5 358D9 JUMP C, string_start_again[0D9]
|
|
0D6 300E7 CALL send_space[0E7] ;clear character at current position
|
|
0D7 300EA CALL send_backspace[0EA] ;position cursor
|
|
0D8 340C6 JUMP receive_full_test[0C6] ;next character
|
|
0D9 30122 string_start_again: CALL send_greater_than[122] ;restore '>' at prompt
|
|
0DA 340C3 JUMP receive_string[0C3] ;begin again
|
|
0DB ;Receiver buffer overflow condition
|
|
0DB 300E4 read_error: CALL send_CR[0E4] ;Transmit error message
|
|
0DC 2EF20 STORE UART_data[sF], string_start[20] ;empty string in memory (start with CR)
|
|
0DD 300FA CALL send_Overflow_Error[0FA]
|
|
0DE 300E4 CALL send_CR[0E4]
|
|
0DF 04000 clear_UART_Rx_loop: INPUT s0, UART_status_port[00] ;test Rx_FIFO buffer for data
|
|
0E0 12010 TEST s0, rx_data_present[10]
|
|
0E1 2B000 RETURN Z ;finish when buffer is empty
|
|
0E2 04F01 INPUT UART_data[sF], UART_read_port[01] ;read from FIFO and ignore
|
|
0E3 340DF JUMP clear_UART_Rx_loop[0DF]
|
|
0E4 ;
|
|
0E4 ;
|
|
0E4 ;
|
|
0E4 ;Send Carriage Return to the UART
|
|
0E4 ;
|
|
0E4 00F0D send_CR: LOAD UART_data[sF], character_CR[0D]
|
|
0E5 3009D CALL send_to_UART[09D]
|
|
0E6 2A000 RETURN
|
|
0E7 ;
|
|
0E7 ;
|
|
0E7 ;
|
|
0E7 ;Send a space to the UART
|
|
0E7 ;
|
|
0E7 00F20 send_space: LOAD UART_data[sF], character_space[20]
|
|
0E8 3009D CALL send_to_UART[09D]
|
|
0E9 2A000 RETURN
|
|
0EA ;
|
|
0EA ;
|
|
0EA ;Send a back space to the UART
|
|
0EA ;
|
|
0EA 00F08 send_backspace: LOAD UART_data[sF], character_BS[08]
|
|
0EB 3009D CALL send_to_UART[09D]
|
|
0EC 2A000 RETURN
|
|
0ED ;
|
|
0ED ;Send 'Syntax Error' to the UART
|
|
0ED ;
|
|
0ED 00F53 send_Syntax_Error: LOAD UART_data[sF], character_S[53]
|
|
0EE 3009D CALL send_to_UART[09D]
|
|
0EF 00F79 LOAD UART_data[sF], character_y[79]
|
|
0F0 3009D CALL send_to_UART[09D]
|
|
0F1 00F6E LOAD UART_data[sF], character_n[6E]
|
|
0F2 3009D CALL send_to_UART[09D]
|
|
0F3 00F74 LOAD UART_data[sF], character_t[74]
|
|
0F4 3009D CALL send_to_UART[09D]
|
|
0F5 00F61 LOAD UART_data[sF], character_a[61]
|
|
0F6 3009D CALL send_to_UART[09D]
|
|
0F7 00F78 LOAD UART_data[sF], character_x[78]
|
|
0F8 3009D CALL send_to_UART[09D]
|
|
0F9 3410A JUMP send_space_Error[10A]
|
|
0FA ;
|
|
0FA ;Send 'Overflow Error' to the UART
|
|
0FA ;
|
|
0FA 00F4F send_Overflow_Error: LOAD UART_data[sF], character_O[4F]
|
|
0FB 3009D CALL send_to_UART[09D]
|
|
0FC 00F76 LOAD UART_data[sF], character_v[76]
|
|
0FD 3009D CALL send_to_UART[09D]
|
|
0FE 00F65 LOAD UART_data[sF], character_e[65]
|
|
0FF 3009D CALL send_to_UART[09D]
|
|
100 00F72 LOAD UART_data[sF], character_r[72]
|
|
101 3009D CALL send_to_UART[09D]
|
|
102 00F66 LOAD UART_data[sF], character_f[66]
|
|
103 3009D CALL send_to_UART[09D]
|
|
104 00F6C LOAD UART_data[sF], character_l[6C]
|
|
105 3009D CALL send_to_UART[09D]
|
|
106 00F6F LOAD UART_data[sF], character_o[6F]
|
|
107 3009D CALL send_to_UART[09D]
|
|
108 00F77 LOAD UART_data[sF], character_w[77]
|
|
109 3009D CALL send_to_UART[09D]
|
|
10A 300E7 send_space_Error: CALL send_space[0E7]
|
|
10B ;
|
|
10B ;Send 'Error' to the UART
|
|
10B ;
|
|
10B 00F45 send_Error: LOAD UART_data[sF], character_E[45]
|
|
10C 3009D CALL send_to_UART[09D]
|
|
10D 00F72 LOAD UART_data[sF], character_r[72]
|
|
10E 3009D CALL send_to_UART[09D]
|
|
10F 3009D CALL send_to_UART[09D]
|
|
110 00F6F LOAD UART_data[sF], character_o[6F]
|
|
111 3009D CALL send_to_UART[09D]
|
|
112 00F72 LOAD UART_data[sF], character_r[72]
|
|
113 3009D CALL send_to_UART[09D]
|
|
114 2A000 RETURN
|
|
115 ;
|
|
115 ;Send 'KCPSM3>' prompt to the UART
|
|
115 ;
|
|
115 300E4 send_prompt: CALL send_CR[0E4] ;start new line
|
|
116 00F4B LOAD UART_data[sF], character_K[4B]
|
|
117 3009D CALL send_to_UART[09D]
|
|
118 00F43 LOAD UART_data[sF], character_C[43]
|
|
119 3009D CALL send_to_UART[09D]
|
|
11A 00F50 LOAD UART_data[sF], character_P[50]
|
|
11B 3009D CALL send_to_UART[09D]
|
|
11C 00F53 LOAD UART_data[sF], character_S[53]
|
|
11D 3009D CALL send_to_UART[09D]
|
|
11E 00F4D LOAD UART_data[sF], character_M[4D]
|
|
11F 3009D CALL send_to_UART[09D]
|
|
120 00F33 LOAD UART_data[sF], character_3[33]
|
|
121 3009D CALL send_to_UART[09D]
|
|
122 ;
|
|
122 ;Send '>' character to the UART
|
|
122 ;
|
|
122 00F3E send_greater_than: LOAD UART_data[sF], character_greater_than[3E]
|
|
123 3009D CALL send_to_UART[09D]
|
|
124 2A000 RETURN
|
|
125 ;
|
|
125 ;Send 'Invalid' string to the UART
|
|
125 ;
|
|
125 00F49 send_Invalid: LOAD UART_data[sF], character_I[49]
|
|
126 3009D CALL send_to_UART[09D]
|
|
127 00F6E LOAD UART_data[sF], character_n[6E]
|
|
128 3009D CALL send_to_UART[09D]
|
|
129 00F76 LOAD UART_data[sF], character_v[76]
|
|
12A 3009D CALL send_to_UART[09D]
|
|
12B 00F61 LOAD UART_data[sF], character_a[61]
|
|
12C 3009D CALL send_to_UART[09D]
|
|
12D 00F6C LOAD UART_data[sF], character_l[6C]
|
|
12E 3009D CALL send_to_UART[09D]
|
|
12F 00F69 LOAD UART_data[sF], character_i[69]
|
|
130 3009D CALL send_to_UART[09D]
|
|
131 00F64 LOAD UART_data[sF], character_d[64]
|
|
132 3009D CALL send_to_UART[09D]
|
|
133 2A000 RETURN
|
|
134 ;
|
|
134 ;Send 'Time' string to the UART
|
|
134 ;
|
|
134 00F54 send_Time: LOAD UART_data[sF], character_T[54]
|
|
135 3009D CALL send_to_UART[09D]
|
|
136 00F69 LOAD UART_data[sF], character_i[69]
|
|
137 3009D CALL send_to_UART[09D]
|
|
138 00F6D LOAD UART_data[sF], character_m[6D]
|
|
139 3009D CALL send_to_UART[09D]
|
|
13A 00F65 LOAD UART_data[sF], character_e[65]
|
|
13B 3009D CALL send_to_UART[09D]
|
|
13C 2A000 RETURN
|
|
13D ;
|
|
13D ;Send 'Alarm' string to the UART
|
|
13D ;
|
|
13D 00F41 send_Alarm: LOAD UART_data[sF], character_A[41]
|
|
13E 3009D CALL send_to_UART[09D]
|
|
13F 00F6C LOAD UART_data[sF], character_l[6C]
|
|
140 3009D CALL send_to_UART[09D]
|
|
141 00F61 LOAD UART_data[sF], character_a[61]
|
|
142 3009D CALL send_to_UART[09D]
|
|
143 00F72 LOAD UART_data[sF], character_r[72]
|
|
144 3009D CALL send_to_UART[09D]
|
|
145 00F6D LOAD UART_data[sF], character_m[6D]
|
|
146 3009D CALL send_to_UART[09D]
|
|
147 2A000 RETURN
|
|
148 ;
|
|
148 ;Send 'OFF' string to the UART
|
|
148 ;
|
|
148 00F4F send_OFF: LOAD UART_data[sF], character_O[4F]
|
|
149 3009D CALL send_to_UART[09D]
|
|
14A 00F46 LOAD UART_data[sF], character_F[46]
|
|
14B 3009D CALL send_to_UART[09D]
|
|
14C 3009D CALL send_to_UART[09D]
|
|
14D 2A000 RETURN
|
|
14E ;
|
|
14E ;Send 'ON' string to the UART
|
|
14E ;
|
|
14E 00F4F send_ON: LOAD UART_data[sF], character_O[4F]
|
|
14F 3009D CALL send_to_UART[09D]
|
|
150 00F4E LOAD UART_data[sF], character_N[4E]
|
|
151 3009D CALL send_to_UART[09D]
|
|
152 2A000 RETURN
|
|
153 ;
|
|
153 ;Send 'Active' string to the UART
|
|
153 ;
|
|
153 00F41 send_Active: LOAD UART_data[sF], character_A[41]
|
|
154 3009D CALL send_to_UART[09D]
|
|
155 00F63 LOAD UART_data[sF], character_c[63]
|
|
156 3009D CALL send_to_UART[09D]
|
|
157 00F74 LOAD UART_data[sF], character_t[74]
|
|
158 3009D CALL send_to_UART[09D]
|
|
159 00F69 LOAD UART_data[sF], character_i[69]
|
|
15A 3009D CALL send_to_UART[09D]
|
|
15B 00F76 LOAD UART_data[sF], character_v[76]
|
|
15C 3009D CALL send_to_UART[09D]
|
|
15D 00F65 LOAD UART_data[sF], character_e[65]
|
|
15E 3009D CALL send_to_UART[09D]
|
|
15F 2A000 RETURN
|
|
160 ;
|
|
160 ;
|
|
160 ;Convert time to ASCII string in scratch pad memory.
|
|
160 ;
|
|
160 ;The time to converted must be stored in 3 scratch pad memory locations as
|
|
160 ;defined below. A register named 'store_pointer' must provide the address of
|
|
160 ;first location.
|
|
160 ;
|
|
160 ; Address Data
|
|
160 ;
|
|
160 ; store_pointer ----> hours
|
|
160 ; store_pointer + 1 ----> minutes
|
|
160 ; store_pointer + 1 ----> seconds
|
|
160 ;
|
|
160 ;The resulting ASCII string will be stored in scratch pad memory starting at
|
|
160 ;a location specified by a constant named 'string_start'. The string will
|
|
160 ;take the format hh:mm:ss and end with a carriage return.
|
|
160 ;
|
|
160 ;Registers used s0, s1, s2 and 'store_pointer'.
|
|
160 ;
|
|
160 00220 time_to_ASCII: LOAD s2, string_start[20] ;location for string
|
|
161 070E0 FETCH s0, (store_pointer)[(sE)] ;read hours value
|
|
162 3017E CALL decimal_to_ASCII[17E] ;convert to ASCII
|
|
163 2F120 STORE s1, (s2) ;write hours to string
|
|
164 18201 ADD s2, 01
|
|
165 2F020 STORE s0, (s2)
|
|
166 18201 ADD s2, 01
|
|
167 0003A LOAD s0, character_colon[3A] ;write ':' to string
|
|
168 2F020 STORE s0, (s2)
|
|
169 18201 ADD s2, 01
|
|
16A 18E01 ADD store_pointer[sE], 01 ;move to minutes
|
|
16B 070E0 FETCH s0, (store_pointer)[(sE)] ;read minutes value
|
|
16C 3017E CALL decimal_to_ASCII[17E] ;convert to ASCII
|
|
16D 2F120 STORE s1, (s2) ;write minutes to string
|
|
16E 18201 ADD s2, 01
|
|
16F 2F020 STORE s0, (s2)
|
|
170 18201 ADD s2, 01
|
|
171 0003A LOAD s0, character_colon[3A] ;write ':' to string
|
|
172 2F020 STORE s0, (s2)
|
|
173 18201 ADD s2, 01
|
|
174 18E01 ADD store_pointer[sE], 01 ;move to seconds
|
|
175 070E0 FETCH s0, (store_pointer)[(sE)] ;read seconds value
|
|
176 3017E CALL decimal_to_ASCII[17E] ;convert to ASCII
|
|
177 2F120 STORE s1, (s2) ;write seconds to string
|
|
178 18201 ADD s2, 01
|
|
179 2F020 STORE s0, (s2)
|
|
17A 18201 ADD s2, 01
|
|
17B 0000D LOAD s0, character_CR[0D] ;finish string with carriage return
|
|
17C 2F020 STORE s0, (s2)
|
|
17D 2A000 RETURN
|
|
17E ;
|
|
17E ;Convert value provided in register s0 into ASCII characters
|
|
17E ;
|
|
17E ;The value provided must in the range 0 to 99 and will be converted into
|
|
17E ;two ASCII characters.
|
|
17E ; The number of 'tens' will be representd by an ASCII character returned in register s1.
|
|
17E ; The number of 'units' will be representd by an ASCII character returned in register s0.
|
|
17E ;
|
|
17E ;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex added to
|
|
17E ;the actual decimal value.
|
|
17E ;
|
|
17E ;Registers used s0 and s1.
|
|
17E ;
|
|
17E 00130 decimal_to_ASCII: LOAD s1, 30 ;load 'tens' counter with ASCII for '0'
|
|
17F 18101 test_for_ten: ADD s1, 01 ;increment 'tens' value
|
|
180 1C00A SUB s0, 0A ;try to subtract 10 from the supplied value
|
|
181 35D7F JUMP NC, test_for_ten[17F] ;repeat if subtraction was possible without underflow.
|
|
182 1C101 SUB s1, 01 ;'tens' value one less ten due to underflow
|
|
183 1803A ADD s0, 3A ;restore units value (the remainder) and convert to ASCII
|
|
184 2A000 RETURN
|
|
185 ;
|
|
185 ;
|
|
185 ;
|
|
185 ;
|
|
185 ;Real Time Clock
|
|
185 ;
|
|
185 ;Uses the 1us interrupt counter [int_counter_msb,int_counter_lsb] to determine how many
|
|
185 ;micro-seconds have elapsed since the last update. This allows for just over 65ms between
|
|
185 ;updates. Complete multiples of 1000us are used to update a 16-bit milli-second counter held
|
|
185 ;in scratch pad memory locations [ms_time_stamp_msb,ms_time_stamp_msb] which in turn
|
|
185 ;is used to update the real time hours, minutes and seconds clock held in scratch pad
|
|
185 ;memory locations 'real_time_hours', 'real_time_minutes' and 'real_time_seconds'.
|
|
185 ;
|
|
185 ;The routine uses default register names s0,s1,s2,s3,s4,s5. These are preserved in scratch pad
|
|
185 ;memory during the routine and restored before returning.
|
|
185 ;
|
|
185 ;Useful constants for real time clock operations
|
|
185 ;
|
|
185 CONSTANT count_1000_lsb, E8 ;lower 8-bits of 1000 count value
|
|
185 CONSTANT count_1000_msb, 03 ;upper 8-bits of 1000 count value
|
|
185 CONSTANT hours_in_a_day, 18 ;24 hours in a day
|
|
185 CONSTANT minutes_in_an_hour, 3C ;60 minutes in an hour
|
|
185 CONSTANT seconds_in_a_minute, 3C ;60 seconds in a minute
|
|
185 ;
|
|
185 2E010 update_time: STORE s0, time_preserve0[10] ;preserve contents of registers used during routine
|
|
186 2E111 STORE s1, time_preserve1[11]
|
|
187 2E212 STORE s2, time_preserve2[12]
|
|
188 2E313 STORE s3, time_preserve3[13]
|
|
189 2E414 STORE s4, time_preserve4[14]
|
|
18A 2E515 STORE s5, time_preserve5[15]
|
|
18B ;
|
|
18B 06200 FETCH s2, us_time_stamp_lsb[00] ;read the previous 'us' time stamp into [s3,s2]
|
|
18C 06301 FETCH s3, us_time_stamp_msb[01]
|
|
18D 3C000 DISABLE INTERRUPT ;Read and store current 'us' time stamp provided by the interrupt
|
|
18E 2ED00 STORE int_counter_lsb[sD], us_time_stamp_lsb[00] ;counter. Interrupts are disabled to ensure that both bytes relate
|
|
18F 2EC01 STORE int_counter_msb[sC], us_time_stamp_msb[01] ;to the same count value.
|
|
190 3C001 ENABLE INTERRUPT
|
|
191 06400 FETCH s4, us_time_stamp_lsb[00] ;read the new 'us' time stamp in [s5,s4]
|
|
192 06501 FETCH s5, us_time_stamp_msb[01] ;
|
|
193 1D420 SUB s4, s2 ;calculate 'us' time difference [s5,s4] = [s5,s4] - [s3,s2]
|
|
194 1F530 SUBCY s5, s3 ; (This works correctly even if counter has rolled over)
|
|
195 06202 FETCH s2, us_time_lsb[02] ;read current 'us' time into [s3,s2]
|
|
196 06303 FETCH s3, us_time_msb[03]
|
|
197 19240 ADD s2, s4 ;add on the elapsed 'us' value [s3,s2] = [s3,s2] + [s5,s4]
|
|
198 1B350 ADDCY s3, s5
|
|
199 ;determine how many 1000us (1ms) units there are (if any) in current 'us' time
|
|
199 00000 LOAD s0, 00 ;reset 'ms' counter
|
|
19A 1C2E8 test_1000us: SUB s2, count_1000_lsb[E8] ;subtract 1000 from [s3,s2]
|
|
19B 1E303 SUBCY s3, count_1000_msb[03]
|
|
19C 3599F JUMP C, store_us_time[19F] ;Carry indicates [s3,s2] was less than 1000us
|
|
19D 18001 ADD s0, 01 ;increment 'ms' elapsed because [s3,s2] was more or equal to 1000us
|
|
19E 3419A JUMP test_1000us[19A] ;repeat to see if more than 1ms has elapsed
|
|
19F 182E8 store_us_time: ADD s2, count_1000_lsb[E8] ;add 1000 to restore 'us' value
|
|
1A0 1A303 ADDCY s3, count_1000_msb[03]
|
|
1A1 2E202 STORE s2, us_time_lsb[02] ;store the current value of 'us'
|
|
1A2 2E303 STORE s3, us_time_msb[03]
|
|
1A3 ;s0 holds the number of 'ms' elapsed since last update (if any).
|
|
1A3 06204 FETCH s2, ms_time_lsb[04] ;read current 'ms' time into [s3,s2]
|
|
1A4 06305 FETCH s3, ms_time_msb[05]
|
|
1A5 19200 ADD s2, s0 ;add on the elapsed 'ms' value [s3,s2] = [s3,s2] + s0
|
|
1A6 1A300 ADDCY s3, 00
|
|
1A7 ;determine if there are now more than 1000ms to form 1 second.
|
|
1A7 00000 LOAD s0, 00 ;reset 'second' counter
|
|
1A8 1C2E8 SUB s2, count_1000_lsb[E8] ;subtract 1000 from [s3,s2]
|
|
1A9 1E303 SUBCY s3, count_1000_msb[03]
|
|
1AA 359AD JUMP C, restore_ms_time[1AD] ;Carry indicates [s3,s2] was less than 1000ms
|
|
1AB 18001 ADD s0, 01 ;increment 'second' elapsed because [s3,s2] was more or equal to 1000ms
|
|
1AC 341AF JUMP store_ms_time[1AF] ;new value of 'ms' is remainder of subtraction
|
|
1AD 182E8 restore_ms_time: ADD s2, count_1000_lsb[E8] ;add 1000 to restore 'ms' value
|
|
1AE 1A303 ADDCY s3, count_1000_msb[03]
|
|
1AF 2E204 store_ms_time: STORE s2, ms_time_lsb[04] ;store the current value of 'ms'
|
|
1B0 2E305 STORE s3, ms_time_msb[05]
|
|
1B1 ;s0 currently determines if one second needs to be added to the hh:mm:ss clock time
|
|
1B1 06108 FETCH s1, real_time_seconds[08] ;read seconds
|
|
1B2 19100 ADD s1, s0 ;add one second if required by s0
|
|
1B3 1413C COMPARE s1, seconds_in_a_minute[3C] ;test for 1 minute
|
|
1B4 351B7 JUMP Z, inc_minutes[1B7]
|
|
1B5 2E108 STORE s1, real_time_seconds[08] ;store updated seconds
|
|
1B6 341C9 JUMP time_update_complete[1C9]
|
|
1B7 00100 inc_minutes: LOAD s1, 00 ;seconds become zero
|
|
1B8 2E108 STORE s1, real_time_seconds[08]
|
|
1B9 06107 FETCH s1, real_time_minutes[07] ;read minutes
|
|
1BA 18101 ADD s1, 01 ;increment minutes
|
|
1BB 1413C COMPARE s1, minutes_in_an_hour[3C] ;test for 1 hour
|
|
1BC 351BF JUMP Z, inc_hours[1BF]
|
|
1BD 2E107 STORE s1, real_time_minutes[07] ;store updated minutes
|
|
1BE 341C9 JUMP time_update_complete[1C9]
|
|
1BF 00100 inc_hours: LOAD s1, 00 ;minutes become zero
|
|
1C0 2E107 STORE s1, real_time_minutes[07]
|
|
1C1 06106 FETCH s1, real_time_hours[06] ;read hours
|
|
1C2 18101 ADD s1, 01 ;increment hours
|
|
1C3 14118 COMPARE s1, hours_in_a_day[18] ;test for 24 hours
|
|
1C4 351C7 JUMP Z, reset_hours[1C7]
|
|
1C5 2E106 STORE s1, real_time_hours[06] ;store updated hours
|
|
1C6 341C9 JUMP time_update_complete[1C9]
|
|
1C7 00100 reset_hours: LOAD s1, 00 ;hours become zero
|
|
1C8 2E106 STORE s1, real_time_hours[06]
|
|
1C9 ;
|
|
1C9 ;With the time updated, there is then a test for time=alarm time
|
|
1C9 ;
|
|
1C9 06006 time_update_complete: FETCH s0, real_time_hours[06]
|
|
1CA 06109 FETCH s1, alarm_time_hours[09] ;compare hours
|
|
1CB 15010 COMPARE s0, s1
|
|
1CC 355DB JUMP NZ, finish_update[1DB]
|
|
1CD 06007 FETCH s0, real_time_minutes[07] ;compare minutes
|
|
1CE 0610A FETCH s1, alarm_time_minutes[0A]
|
|
1CF 15010 COMPARE s0, s1
|
|
1D0 355DB JUMP NZ, finish_update[1DB]
|
|
1D1 06008 FETCH s0, real_time_seconds[08] ;compare seconds
|
|
1D2 0610B FETCH s1, alarm_time_seconds[0B]
|
|
1D3 15010 COMPARE s0, s1
|
|
1D4 355DB JUMP NZ, finish_update[1DB]
|
|
1D5 0600C FETCH s0, alarm_status[0C] ;test if alarm is turned on
|
|
1D6 12002 TEST s0, alarm_armed[02]
|
|
1D7 351DB JUMP Z, finish_update[1DB] ;alarm was off
|
|
1D8 0C001 OR s0, alarm_active[01] ;activate alarm
|
|
1D9 2E00C STORE s0, alarm_status[0C]
|
|
1DA 300A4 CALL alarm_drive[0A4]
|
|
1DB 06010 finish_update: FETCH s0, time_preserve0[10] ;restore the register contents
|
|
1DC 06111 FETCH s1, time_preserve1[11]
|
|
1DD 06212 FETCH s2, time_preserve2[12]
|
|
1DE 06313 FETCH s3, time_preserve3[13]
|
|
1DF 06414 FETCH s4, time_preserve4[14]
|
|
1E0 06515 FETCH s5, time_preserve5[15]
|
|
1E1 2A000 RETURN
|
|
1E2 ;
|
|
1E2 ;Convert character to upper case
|
|
1E2 ;
|
|
1E2 ;The character supplied in register s0.
|
|
1E2 ;If the character is in the range 'a' to 'z', it is converted
|
|
1E2 ;to the equivalent upper case character in the range 'A' to 'Z'.
|
|
1E2 ;All other characters remain unchanged.
|
|
1E2 ;
|
|
1E2 ;Registers used s0.
|
|
1E2 ;
|
|
1E2 14061 upper_case: COMPARE s0, 61 ;eliminate character codes below 'a' (61 hex)
|
|
1E3 2B800 RETURN C
|
|
1E4 1407B COMPARE s0, 7B ;eliminate character codes above 'z' (7A hex)
|
|
1E5 2BC00 RETURN NC
|
|
1E6 0A0DF AND s0, DF ;mask bit5 to convert to upper case
|
|
1E7 2A000 RETURN
|
|
1E8 ;
|
|
1E8 ;
|
|
1E8 ;Convert character '0' to '9' to numerical value in range 0 to 9
|
|
1E8 ;
|
|
1E8 ;The character supplied in register s0. If the character is in the
|
|
1E8 ;range '0' to '9', it is converted to the equivalent decimal value.
|
|
1E8 ;Characters not in the range '0' to '9' are signified by the return
|
|
1E8 ;with the CARRY flag set.
|
|
1E8 ;
|
|
1E8 ;Registers used s0.
|
|
1E8 ;
|
|
1E8 180C6 1char_to_value: ADD s0, C6 ;reject character codes above '9' (39 hex)
|
|
1E9 2B800 RETURN C ;carry flag is set
|
|
1EA 1C0F6 SUB s0, F6 ;reject character codes below '0' (30 hex)
|
|
1EB 2A000 RETURN ;carry is set if value not in range
|
|
1EC ;
|
|
1EC ;
|
|
1EC ;Determine the numerical value of a two character decimal string held in
|
|
1EC ;scratch pad memory such the result is in the range 0 to 99 (00 to 63 hex).
|
|
1EC ;
|
|
1EC ;The string must be stored as in two consecutive memory locations and the
|
|
1EC ;location of the first (tens) character supplied in the s1 register.
|
|
1EC ;The result is provided in register s2. Strings not using characters in the
|
|
1EC ;range '0' to '9' are signified by the return with the CARRY flag set.
|
|
1EC ;
|
|
1EC ;Registers used s0, s1 and s2.
|
|
1EC ;
|
|
1EC 07010 2char_to_value: FETCH s0, (s1) ;read 'tens' character
|
|
1ED 301E8 CALL 1char_to_value[1E8] ;convert to numerical value
|
|
1EE 2B800 RETURN C ;bad character - CARRY set
|
|
1EF 01200 LOAD s2, s0
|
|
1F0 20206 SL0 s2 ;multiply 'tens' value by 10 (0A hex)
|
|
1F1 20206 SL0 s2
|
|
1F2 19200 ADD s2, s0
|
|
1F3 20206 SL0 s2
|
|
1F4 18101 ADD s1, 01 ;read 'units' character
|
|
1F5 07010 FETCH s0, (s1)
|
|
1F6 301E8 CALL 1char_to_value[1E8] ;convert to numerical value
|
|
1F7 2B800 RETURN C ;bad character - CARRY set
|
|
1F8 19200 ADD s2, s0 ;add units to result and clear CARRY flag
|
|
1F9 2A000 RETURN
|
|
1FA ;
|
|
1FA ;
|
|
1FA ;Interrupt service routine (ISR)
|
|
1FA ;
|
|
1FA ;The interrupt is used to increment a 16-bit counter formed with two registers
|
|
1FA ;called [int_counter_msb,int_counter_lsb]. This provides a count of the number
|
|
1FA ;of micro-seconds elapsed. The counter is 'free running' in that it will count
|
|
1FA ;up to 65,535 and then roll over to zero. The count value is then used in other
|
|
1FA ;parts of the program as required and where it is less time critical.
|
|
1FA ;
|
|
1FA ;The ISR only uses the specified counter registers
|
|
1FA ;
|
|
3FC ADDRESS 3FC
|
|
3FC 18D01 ISR: ADD int_counter_lsb[sD], 01 ;add 1us to 16-bit counter
|
|
3FD 1AC00 ADDCY int_counter_msb[sC], 00
|
|
3FE 38001 RETURNI ENABLE
|
|
3FF ;
|
|
3FF ;Interrupt vector
|
|
3FF ;
|
|
3FF ADDRESS 3FF
|
|
3FF 343FC JUMP ISR[3FC]
|
|
3FF ;
|
|
3FF ;
|
|
3FF ;Useful constants
|
|
3FF ;
|
|
3FF ;
|
|
3FF ;ASCII table
|
|
3FF ;
|
|
3FF CONSTANT character_a, 61
|
|
3FF CONSTANT character_b, 62
|
|
3FF CONSTANT character_c, 63
|
|
3FF CONSTANT character_d, 64
|
|
3FF CONSTANT character_e, 65
|
|
3FF CONSTANT character_f, 66
|
|
3FF CONSTANT character_g, 67
|
|
3FF CONSTANT character_h, 68
|
|
3FF CONSTANT character_i, 69
|
|
3FF CONSTANT character_j, 6A
|
|
3FF CONSTANT character_k, 6B
|
|
3FF CONSTANT character_l, 6C
|
|
3FF CONSTANT character_m, 6D
|
|
3FF CONSTANT character_n, 6E
|
|
3FF CONSTANT character_o, 6F
|
|
3FF CONSTANT character_p, 70
|
|
3FF CONSTANT character_q, 71
|
|
3FF CONSTANT character_r, 72
|
|
3FF CONSTANT character_s, 73
|
|
3FF CONSTANT character_t, 74
|
|
3FF CONSTANT character_u, 75
|
|
3FF CONSTANT character_v, 76
|
|
3FF CONSTANT character_w, 77
|
|
3FF CONSTANT character_x, 78
|
|
3FF CONSTANT character_y, 79
|
|
3FF CONSTANT character_z, 7A
|
|
3FF CONSTANT character_A, 41
|
|
3FF CONSTANT character_B, 42
|
|
3FF CONSTANT character_C, 43
|
|
3FF CONSTANT character_D, 44
|
|
3FF CONSTANT character_E, 45
|
|
3FF CONSTANT character_F, 46
|
|
3FF CONSTANT character_G, 47
|
|
3FF CONSTANT character_H, 48
|
|
3FF CONSTANT character_I, 49
|
|
3FF CONSTANT character_J, 4A
|
|
3FF CONSTANT character_K, 4B
|
|
3FF CONSTANT character_L, 4C
|
|
3FF CONSTANT character_M, 4D
|
|
3FF CONSTANT character_N, 4E
|
|
3FF CONSTANT character_O, 4F
|
|
3FF CONSTANT character_P, 50
|
|
3FF CONSTANT character_Q, 51
|
|
3FF CONSTANT character_R, 52
|
|
3FF CONSTANT character_S, 53
|
|
3FF CONSTANT character_T, 54
|
|
3FF CONSTANT character_U, 55
|
|
3FF CONSTANT character_V, 56
|
|
3FF CONSTANT character_W, 57
|
|
3FF CONSTANT character_X, 58
|
|
3FF CONSTANT character_Y, 59
|
|
3FF CONSTANT character_Z, 5A
|
|
3FF CONSTANT character_0, 30
|
|
3FF CONSTANT character_1, 31
|
|
3FF CONSTANT character_2, 32
|
|
3FF CONSTANT character_3, 33
|
|
3FF CONSTANT character_4, 34
|
|
3FF CONSTANT character_5, 35
|
|
3FF CONSTANT character_6, 36
|
|
3FF CONSTANT character_7, 37
|
|
3FF CONSTANT character_8, 38
|
|
3FF CONSTANT character_9, 39
|
|
3FF CONSTANT character_colon, 3A
|
|
3FF CONSTANT character_semi_colon, 3B
|
|
3FF CONSTANT character_less_than, 3C
|
|
3FF CONSTANT character_greater_than, 3E
|
|
3FF CONSTANT character_equals, 3D
|
|
3FF CONSTANT character_space, 20
|
|
3FF CONSTANT character_CR, 0D ;carriage return
|
|
3FF CONSTANT character_question, 3F ;'?'
|
|
3FF CONSTANT character_dollar, 24
|
|
3FF CONSTANT character_BS, 08 ;Back Space command character
|
|
3FF ;
|