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

2219 lines
130 KiB
Plaintext

; KCPSM3 Program - Implementation of the SHA-1 algorithm for use with the
; DS2432 secure memory on the Spartan-3E Starter Kit.
;
; Ken Chapman - Xilinx Ltd
;
; Version v1.00 - 19th April 2006
;
;
; IMPORTANT - This design builds on the reference design called "PicoBlaze
; DS2432 communicator". It is highly recommend that you look at that
; design before proceeding with this one.
;
;
; This program uses a 9600 baud UART connection to allow communication with the
; 1-wire interface of the DS2432 memory device from Dallas Semiconductor.
;
; The program only supports a limited number of the DS2432 commands to focus on
; those aspects which use the SHA-1 algorithm.
;
; Note that the code performing the SHA-1 algorithm interacts with the hardware of
; this complete reference design. The hardware provides a 16 word (32-bit) buffer
; combined used in the initialisation of the algorithm and subsequent computation
; of the Wt words.
;
;
; The DS2432 should be programmed with a 64-bit secret. The following constants
; define the secret which will be used. Obviously this would be be changed in a
; real application and further measures taken to prevent it easily being found.
; The secret is 64-bits formed of 8 bytes. 'secret0' would be stored at address
; 0080 of the DS2432 and 'secret7' at address 0087. The write buffer and load
; first secret commands allow you to set any secret into the DS2432 device but
; this program always uses the secret defined in these constants such that you can
; experiment with secrets which do and do not match.
;
;
CONSTANT secret0, 01
CONSTANT secret1, 23
CONSTANT secret2, 45
CONSTANT secret3, 67
CONSTANT secret4, 89
CONSTANT secret5, AB
CONSTANT secret6, CD
CONSTANT secret7, EF
;
;
; Bytes 4, 5 and 6 of the DS2432 scratch pad memory are used in the SHA-1 algorithm.
; These should be set using the write scratchpad memory command before using the
; read authenticated page command. HOWEVER, it is also important that you also use
; the read scratchpad command BEFORE using the read authenticated page command. This
; is because this program only copies the bytes 4, 5 and 6 during a read such that
; they are can be used by the PicoBlaze SHA-1 algorithm. This limitation is deliberate
; so that you can experiment and prove that the SHA-1 results will not match if
; the same 'challenge' bytes are not used.
;
;
;**************************************************************************************
; Port definitions
;**************************************************************************************
;
;
CONSTANT status_port, 40 ;UART status input
CONSTANT tx_half_full, 01 ; Transmitter half full - bit0
CONSTANT tx_full, 02 ; FIFO full - bit1
CONSTANT rx_data_present, 04 ; Receiver data present - bit2
CONSTANT rx_half_full, 08 ; FIFO half full - bit3
CONSTANT rx_full, 10 ; full - bit4
CONSTANT spare1, 20 ; spare '0' - bit5
CONSTANT spare2, 40 ; spare '0' - bit6
CONSTANT spare3, 80 ; spare '0' - bit7
;
CONSTANT UART_read_port, 80 ;UART Rx data input
;
CONSTANT UART_write_port, 04 ;UART Tx data output
;
;
CONSTANT DS_wire_in_port, C0 ;Read signal from DS2432 device
CONSTANT DS_wire_out_port, 08 ;Drive signal to DS2432 device (open collector)
CONSTANT DS_wire, 01 ; Signal is bit0 in both cases
;
;
;
; The following ports access the 'Wt' word buffer. This buffer holds 16 words
; of 32-bits organised as a 64-byte shift register. Hence each word is stored
; by writing 4 bytes. As each byte is written, all bytes shift along such that
; older Wt values can be read from consistent port addresses.
;
CONSTANT W_word_write_port, 10 ;Write byte to Wt buffer
;
CONSTANT Wt_minus3_byte0_read_port, 08 ;Read of Wt-3
CONSTANT Wt_minus3_byte1_read_port, 09
CONSTANT Wt_minus3_byte2_read_port, 0A
CONSTANT Wt_minus3_byte3_read_port, 0B
;
CONSTANT Wt_minus8_byte0_read_port, 1C ;Read of Wt-8
CONSTANT Wt_minus8_byte1_read_port, 1D
CONSTANT Wt_minus8_byte2_read_port, 1E
CONSTANT Wt_minus8_byte3_read_port, 1F
;
CONSTANT Wt_minus14_byte0_read_port, 34 ;Read of Wt-14
CONSTANT Wt_minus14_byte1_read_port, 35
CONSTANT Wt_minus14_byte2_read_port, 36
CONSTANT Wt_minus14_byte3_read_port, 37
;
CONSTANT Wt_minus16_byte0_read_port, 3C ;Read of Wt-16
CONSTANT Wt_minus16_byte1_read_port, 3D
CONSTANT Wt_minus16_byte2_read_port, 3E
CONSTANT Wt_minus16_byte3_read_port, 3F
;
;
;**************************************************************************************
; Special Register usage
;**************************************************************************************
;
NAMEREG sF, UART_data ;used to pass data to and from the UART
;
;
;**************************************************************************************
; Scratch Pad Memory Locations
;**************************************************************************************
;
; Scratch pad memory provides 64 bytes in the address range 00 to 3F hex.
;
;
; Locations for device family code, serial number and 8-bit CRC value
;
CONSTANT family_code, 00
CONSTANT serial_number0, 01 ;48-bit serial number LS-Byte first
CONSTANT serial_number1, 02
CONSTANT serial_number2, 03
CONSTANT serial_number3, 04
CONSTANT serial_number4, 05
CONSTANT serial_number5, 06
CONSTANT read_ROM_CRC, 07 ;8-bit CRC
;
;
; Locations for variables used in SHA-1 algorithm.
; Each variable is 32-bits and requires 4 bytes to store.
; '0' indicates the least significant byte and '3' the most significant byte.
;
; Note that the concatenation of 'A', 'B', 'C', 'D' and 'E' will be the 160-bit MAC.
;
CONSTANT var_A0, 08 ;Variable 'A'
CONSTANT var_A1, 09
CONSTANT var_A2, 0A
CONSTANT var_A3, 0B
;
CONSTANT var_B0, 0C ;Variable 'B'
CONSTANT var_B1, 0D
CONSTANT var_B2, 0E
CONSTANT var_B3, 0F
;
CONSTANT var_C0, 10 ;Variable 'C'
CONSTANT var_C1, 11
CONSTANT var_C2, 12
CONSTANT var_C3, 13
;
CONSTANT var_D0, 14 ;Variable 'D'
CONSTANT var_D1, 15
CONSTANT var_D2, 16
CONSTANT var_D3, 17
;
CONSTANT var_E0, 18 ;Variable 'E'
CONSTANT var_E1, 19
CONSTANT var_E2, 1A
CONSTANT var_E3, 1B
;
;
; Copy of data in the scratchpad memory of the DS2432.
; This is only updated by the read scratchpad memory command.
; '0' indicates the data in the least significant location.
;
CONSTANT scratchpad0, 1C
CONSTANT scratchpad1, 1D
CONSTANT scratchpad2, 1E
CONSTANT scratchpad3, 1F
CONSTANT scratchpad4, 20
CONSTANT scratchpad5, 21
CONSTANT scratchpad6, 22
CONSTANT scratchpad7, 23
;
;
;
;**************************************************************************************
; Useful data constants
;**************************************************************************************
;
; Constant to define a software delay of 1us. This must be adjusted to reflect the
; clock applied to KCPSM3. Every instruction executes in 2 clock cycles making the
; calculation highly predictable. The '6' in the following equation even allows for
; 'CALL delay_1us' instruction in the initiating code.
;
; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
;
; Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex).
; For clock rates below 10MHz the value of 1 must be used and the operation will
; become lower than intended.
;
CONSTANT delay_1us_constant, 0B
;
;
;
;ASCII table
;
CONSTANT character_a, 61
CONSTANT character_b, 62
CONSTANT character_c, 63
CONSTANT character_d, 64
CONSTANT character_e, 65
CONSTANT character_f, 66
CONSTANT character_g, 67
CONSTANT character_h, 68
CONSTANT character_i, 69
CONSTANT character_j, 6A
CONSTANT character_k, 6B
CONSTANT character_l, 6C
CONSTANT character_m, 6D
CONSTANT character_n, 6E
CONSTANT character_o, 6F
CONSTANT character_p, 70
CONSTANT character_q, 71
CONSTANT character_r, 72
CONSTANT character_s, 73
CONSTANT character_t, 74
CONSTANT character_u, 75
CONSTANT character_v, 76
CONSTANT character_w, 77
CONSTANT character_x, 78
CONSTANT character_y, 79
CONSTANT character_z, 7A
CONSTANT character_A, 41
CONSTANT character_B, 42
CONSTANT character_C, 43
CONSTANT character_D, 44
CONSTANT character_E, 45
CONSTANT character_F, 46
CONSTANT character_G, 47
CONSTANT character_H, 48
CONSTANT character_I, 49
CONSTANT character_J, 4A
CONSTANT character_K, 4B
CONSTANT character_L, 4C
CONSTANT character_M, 4D
CONSTANT character_N, 4E
CONSTANT character_O, 4F
CONSTANT character_P, 50
CONSTANT character_Q, 51
CONSTANT character_R, 52
CONSTANT character_S, 53
CONSTANT character_T, 54
CONSTANT character_U, 55
CONSTANT character_V, 56
CONSTANT character_W, 57
CONSTANT character_X, 58
CONSTANT character_Y, 59
CONSTANT character_Z, 5A
CONSTANT character_0, 30
CONSTANT character_1, 31
CONSTANT character_2, 32
CONSTANT character_3, 33
CONSTANT character_4, 34
CONSTANT character_5, 35
CONSTANT character_6, 36
CONSTANT character_7, 37
CONSTANT character_8, 38
CONSTANT character_9, 39
CONSTANT character_colon, 3A
CONSTANT character_fullstop, 2E
CONSTANT character_semi_colon, 3B
CONSTANT character_minus, 2D
CONSTANT character_plus, 2B
CONSTANT character_comma, 2C
CONSTANT character_less_than, 3C ;'<'
CONSTANT character_greater_than, 3E ;'>'
CONSTANT character_open, 28 ;'('
CONSTANT character_close, 29 ;')'
CONSTANT character_divide, 2F ;'/'
CONSTANT character_equals, 3D
CONSTANT character_space, 20
CONSTANT character_CR, 0D ;carriage return
CONSTANT character_LF, 0A ;line feed
CONSTANT character_question, 3F ;'?'
CONSTANT character_dollar, 24
CONSTANT character_exclaim, 21 ;'!'
CONSTANT character_BS, 08 ;Back Space command character
CONSTANT character_XON, 11 ;Flow control ON
CONSTANT character_XOFF, 13 ;Flow control OFF
;
;
;**************************************************************************************
; Initialise the system and welcome message
;**************************************************************************************
;
cold_start: CALL DS_wire_init ;Ensure DS_wire is not driven (pulled High)
CALL delay_1s ;Allow everything to settle!
welcome_start: CALL send_welcome ;start up message and version number
;
;
;**************************************************************************************
; Reset Main menu and command selection
;**************************************************************************************
;
; The main program allows you to use four of the DS2432 memory and SHA function
; commands. A simple menu is displayed and you are guided to enter more information
; when required. All the communication and protocol required to get the DS2432 ready
; to receive memory and SHA function commands has been automated although information
; is displayed to indicate the procedures being executed.
;
; Before any memory and function commands are available a master reset and read ROM
; command must be issued.
;
warm_start: CALL send_CR
CALL send_CR
CALL DS_init_regular_mode ;master reset
JUMP C, warm_start ;repeat reset if no presence pulse detected
CALL read_ROM_command ;read ROM command and display results
;
; After a valid ROM command the DS2432 specific memory commands and SHA-1
; functions become accessible. This program assumes that the ROM command did
; 'Pass' so you will need to check yourself. If this program automatically
; reset the DS2432 and tried again and there was a fault it would just cause
; the display to roll continuously and not be very informative!
;
; Each of the DS2432 commands selected from the menu will require the master reset
; and read ROM command to be repeated before being able to proceed with the next
; memory or SHA-1 function. This is automated by the program.
;
;
DS2432_menu: CALL send_DS2432_menu ;Menu and command selection
CALL send_CR
;
DS2432_prompt: CALL send_CR ;prompt for user input
CALL send_CR
LOAD UART_data, character_greater_than ;prompt for input
CALL send_to_UART
CALL read_upper_case
COMPARE s0, character_1 ;test for commands and execute as required
JUMP Z, write_scratchpad_command
COMPARE s0, character_2
JUMP Z, read_scratchpad_command
COMPARE s0, character_3
JUMP Z, load_first_secret_command
COMPARE s0, character_4
JUMP Z, read_auth_page_command
CALL send_CR ;no valid command input
LOAD UART_data, character_question ;display ???
CALL send_to_UART
CALL send_to_UART
CALL send_to_UART
JUMP DS2432_prompt ;Try again!
;
;
;
;
;**************************************************************************************
; DS2432 Read ROM Command.
;**************************************************************************************
;
; The read ROM command (33 hex) allows the 8-bit family code, 48-bit unique serial
; number and 8-bit CRC to be read from the DS2432 device.
;
; This routine reads the values and places them in KCPSM3 scratch pad memory
; locations for future reference. These locations should be defined with constants
; as follows and MUST be in consecutive ascending locations.
;
; family_code
; Location to store family code which should be 33 hex
; serial_number0 to serial_number5
; 6 bytes to hold 48-bit serial number (LS-byte first).
; read_ROM_CRC
; 8-bit CRC value for the above data.
;
;
; The routine also displays the values read and performs a verification of the
; 8-bit CRC displaying a 'Pass' or 'Fail' message as appropriate.
;
read_ROM_command: LOAD s3, 33 ;Read ROM Command
CALL write_byte_slow ;transmit command
LOAD s5, family_code ;memory pointer
read_ROM_loop: CALL read_byte_slow ;read response into s3
STORE s3, (s5) ;store value
COMPARE s5, read_ROM_CRC ;8-bytes to read
JUMP Z, display_ROM
ADD s5, 01
JUMP read_ROM_loop
display_ROM: CALL send_CR
CALL send_code ;'code=' to display family code
FETCH s0, family_code
CALL send_hex_byte
CALL send_CR
CALL send_sn ;'s/n=' to display family code
LOAD s5, serial_number5 ;memory pointer starting MS-byte first
disp_serial_loop: FETCH s0, (s5)
CALL send_hex_byte
COMPARE s5, serial_number0
JUMP Z, end_serial
SUB s5, 01
JUMP disp_serial_loop
end_serial: CALL send_CR
CALL send_crc ;'CRC=' to display CRC value
FETCH s0, read_ROM_CRC
CALL send_hex_byte
CALL send_CR
CALL compute_CRC8 ;compute CRC value in s0
FETCH s1, read_ROM_CRC ;compare with received value
COMPARE s0, s1
JUMP NZ, crc8_fail
CALL send_Pass
RETURN
crc8_fail: CALL send_Fail
RETURN
;
;
;
;**************************************************************************************
; DS2432 Load First Secret Command.
;**************************************************************************************
;
; This command will only be valid if the write scratchpad memory command has previously
; been used to define the new secret to be stored at address 0080.
;
; The Load First Secret Command (5A hex) will only copy the scratchpad contents into ;
; the EEPROM array of the DS2432 if the address was correctly specified in the
; write scratchpad command. This routine will assume that the address specified
; was 0080. If everything is OK with the programming of the secret, the DS2432 responds
; with 'AA' hex after the command and this routine will report 'Pass'. You can further
; check using a read scratchpad command and look to see if E/S has changed from '5F'
; to 'DF' which indicates the successful write.
;
; Note that this program defines the secret to be used by the PicoBlaze SHA-1 algorithm
; in the constants 'secret0' through to 'secret7'. Only if you program the DS2432
; with a matching secret will the read authenticated message command result in a
; 'Pass' being reported for the MAC. This Load First Secret Command routine deliberately
; does not update the secret used by the PicoBlaze SHA-1 algorithm so that you can
; prove that only a DS2432 with the matching secret will generate matching MAC
; responses.
;
;
;
load_first_secret_command: LOAD s3, 5A ;Load First Secret Command
CALL write_byte_slow ;transmit command
LOAD s3, 80 ;TA1 value for secret = 80 hex
CALL write_byte_slow
LOAD s3, 00 ;TA2 value for secret = 00 hex
CALL write_byte_slow
LOAD s3, 5F ;E/S value before writing = 5F hex
CALL write_byte_slow
CALL delay_20ms ;write takes place in 10ms
CALL send_CR
CALL send_secret
CALL send_space
CALL read_byte_slow ;read data into s3
COMPARE s3, AA ;test response
JUMP Z, secret_pass
CALL send_Fail
JUMP warm_start
secret_pass: CALL send_Pass
JUMP warm_start
;
;
;**************************************************************************************
; DS2432 Write Scratchpad Memory Command.
;**************************************************************************************
;
; The write scratchpad memory command (0F hex) allows 8-bytes of data to be written
; together with a target address for final storage in the main memory map. The
; DS2432 scratch pad is also used to define a 3 byte 'challenge' used in the
; SHA-1 algorithm.
;
; The DS2432 provides an initial confirmation of the write by returning a 16-bit CRC
; value which KCPSM3 tests. The CRC is computed based on the command, address and
; data transmitted (11 bytes). PicoBlaze also computes the CRC and and tests this
; against the value received from the DS2432.
;
; This routine prompts the user to enter the 16-bit target address is to be loaded
; into the target address registers TA2 and TA1 in the DS2432 device. Note that only
; address values below 0090 hex are valid. If the address is too high, then the
; DS2432 aborts the command and this routine will too.
;
; Also note that the address will be forced internally to the DS2432 to match an
; 8-byte boundary address in which the least significant 3-bits are reset to '000'
; regardless of the address provided. The CRC still reflects the transmitted address.
;
; After providing a valid address, the routine then prompts the user to enter
; 8 bytes of data which are written to the DS2432.
;
;
;
write_scratchpad_command: CALL clear_CRC16 ;prepare CRC registers [sE,sD]
LOAD s3, 0F ;write scratchpad memory Command
CALL write_byte_slow ;transmit command
CALL compute_CRC16 ;compute CRC for value in 's3'
wsc_addr_loop: CALL send_address ;obtain 16-bit address 0000 to FFFF in [s5,s4]
CALL obtain_8bits
JUMP C, wsc_addr_loop ;bad input address
LOAD s5, s0
CALL obtain_8bits
JUMP C, wsc_addr_loop ;bad input address
LOAD s4, s0
LOAD s3, s4 ;transmit target address TA1 (LS-Byte)
CALL write_byte_slow
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s3, s5 ;transmit target address TA2 (MS-Byte)
CALL write_byte_slow
CALL compute_CRC16 ;compute CRC for value in 's3'
COMPARE s5, 00 ;check address less than 0090 hex
JUMP NZ, warm_start ;DS2432 aborts command and so do we!
COMPARE s4, 90 ;no need to read data bytes.
JUMP NC, warm_start
LOAD s4, 00 ;initialise byte counter
wsc_data_loop: CALL send_data ;obtain a byte of data
LOAD UART_data, s4 ;display which byte requested
ADD UART_data, character_0 ;convert to ASCII
CALL send_to_UART
CALL send_equals
CALL obtain_8bits
JUMP C, wsc_data_loop ;bad input data
LOAD s3, s0 ;transmit byte
CALL write_byte_slow
CALL compute_CRC16 ;compute CRC for value in 's3'
ADD s4, 01 ;count bytes
COMPARE s4, 08
JUMP NZ, wsc_data_loop
CALL send_CR
CALL read_send_test_CRC16 ;read, display and test CRC value
JUMP warm_start
;
;
;
;**************************************************************************************
; DS2432 Read Scratchpad Memory Command.
;**************************************************************************************
;
; The read scratchpad memory command (AA hex) allows the 8-bytes of data previously
; to be written into the scratchpad memory to be read back for verification together with
; the target address, a transfer status register (E/S) and a 16-bit CRC value.
;
; The 16-bit CRC is formed of the command byte, address TA1 and TA2, E/S byte and 8 data
; bytes as transmitted (12 bytes). These may not be the same as the values provided
; during a previous write to scratchpad memory. PicoBlaze also computes the CRC and
; and tests this against the value received from the DS2432.
;
; The 8 bytes of data are also copied to PicoBlaze memory at locations defined by the
; constants 'scratchpad0' to 'scratchpad7'. Three bytes are used as a 'challenge'
; by the SHA-1 algorithm.
;
;
;
read_scratchpad_command: CALL clear_CRC16 ;prepare CRC registers [sE,sD]
LOAD s3, AA ;read scratchpad memory Command
CALL write_byte_slow ;transmit command
CALL compute_CRC16 ;compute CRC for value in 's3'
CALL send_address ;display 'Address='
CALL read_byte_slow ;read address into [s5,s4]
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s4, s3
CALL read_byte_slow
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s5, s3
LOAD s0, s5 ;display address
CALL send_hex_byte
LOAD s0, s4
CALL send_hex_byte
CALL send_ES ;display 'E/S='
CALL read_byte_slow ;read E/S register
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s0, s3 ;display value
CALL send_hex_byte
CALL send_data ;display 'Data='
CALL send_equals
LOAD s4, scratchpad0 ;pointer to memory and byte counter
rsc_loop: CALL send_space
CALL read_byte_slow ;read data byte
CALL compute_CRC16 ;compute CRC for value in 's3'
STORE s3, (s4) ;store value in memory
LOAD s0, s3 ;display value
CALL send_hex_byte
COMPARE s4, scratchpad7 ;count bytes
JUMP Z, end_rsc_data_loop
ADD s4, 01
JUMP rsc_loop
end_rsc_data_loop: CALL send_CR
CALL read_send_test_CRC16 ;read, display and test CRC value
JUMP warm_start
;
;
;
;
;
;**************************************************************************************
; DS2432 Read Authenticated Page Command.
;**************************************************************************************
;
; The read authenticated page command (A5 hex) allows the 8-byte secret to be tested
; without it actually being read (which would obviously give away the secret!).
;
; This routine has been written to work with page 0 but could easily be changed and
; is documented below. During the first part of the command, the 32 bytes
; contained in the page are read back from the DS2432 and these are used in
; the preparation of the table required for the for SHA-1 algorithm. Other values
; stored in the table are the secret, serial number of the DS2432, family code, some
; constants, 4-bits of the page address and a 3 byte 'challenge' currently set into
; the DS2432 scratchpad memory.
;
; NOTE - The read scratchpad command must be executed before this routine in order
; that the 3 byte 'challenge' of scratchpad memory is known to PicoBlaze.
;
; During this command, two 16-bit CRC values are generated which PicoBlaze also
; computes and tests. The first is formed of the command byte, address TA1 and TA2,
; all the bytes of the page read and an 'FF' byte. The second is formed of the 20
; bytes of the 160-but message authentication code (MAC).
;
;
; Preparing the table.
;
; The table is stored in the external 'Wt' buffer and must first be initialised with the
; 16 'M' words (32-bit words each requiring 4 bytes). This is achieved by shifting in
; each word in sequence. Storing each word most significant byte first is a natural
; fit with the reading of the page data from the DS2432 and the way each 'M' word
; is organised. Notice how this causes least significant bytes to be swapped with most
; significant bytes!
;
; [31:24] [23:16] [15:8] [7:0]
;
; M0 = [secret0 , secret1 , secret2 , secret3 ]
; M1 = [page_data0 , page_data1 , page_data2 , page_data3 ]
; M2 = [page_data4 , page_data5 , page_data6 , page_data7 ]
; M3 = [page_data8 , page_data9 , page_data10, page_data11]
; M4 = [page_data12, page_data13, page_data14, page_data15]
; M5 = [page_data16, page_data17, page_data18, page_data19]
; M6 = [page_data20, page_data21, page_data22, page_data23]
; M7 = [page_data24, page_data25, page_data26, page_data27]
; M8 = [page_data28, page_data29, page_data30, page_data31]
; M9 = [ FF , FF , FF , FF ]
; M10 = [ 40 , 33 , serial_num0, serial_num1]
; M11 = [serial_num2, serial_num3, serial_num4, serial_num5]
; M12 = [secret4 , secret5 , secret6 , secret7 ]
; M13 = [scratchpad4, scratchpad5, scratchpad6, 80 ]
; M14 = [ 00 , 00 , 00 , 00 ]
; M15 = [ 00 , 00 , 01 , B8 ]
;
; In M10, the '33' is the family code and the '40' is made up of a constant bit
; pattern '0100' and then bits [8:5] of the page address. This gives 4 possible values
; for this byte during a Read Authenticated Page Command, but this routine is currently
; fixed to work with page 0 only.
; 40 - page 0
; 41 - page 1
; 42 - page 2
; 43 - page 3
;
; M13 contains the 3 byte challenge from the scratch pad memory. This assumes that a
; read scratchpad command has previously been used and the bytes held in the DS2432
; scratchpad match those held in the PicoBlaze memory.
;
;
; The 160-bit Message Authentication Code (MAC) is computed from the table using the SHA-1
; algorithm. This algorithm actually results in 5 variables 'A', 'B', 'C', 'D' and 'E'
; which are 32-bit values each formed of 4 bytes. The MAC is the concatenation of
; the variables. To match the same order in which the Read Authenticated Page Command
; sends the MAC, the variables must be read in the order 'E', 'D', 'C', 'B' and 'A' and
; with the least significant byte of each variable first.
;
;
;
;
;
read_auth_page_command: LOAD s0, secret0 ;store M0 (secret 0, 1, 2 and 3) in Wt buffer.
OUTPUT s0, W_word_write_port
LOAD s0, secret1
OUTPUT s0, W_word_write_port
LOAD s0, secret2
OUTPUT s0, W_word_write_port
LOAD s0, secret3
OUTPUT s0, W_word_write_port
;
;Start of DS2432 command
;
CALL clear_CRC16 ;prepare CRC registers [sE,sD]
LOAD s3, A5 ;read authenticated page command
CALL write_byte_slow ;transmit command
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s5, 00 ;set address for page 0
LOAD s4, 00 ; [TA2,TA1]=0000 hex
LOAD s3, s4 ;transmit TA1
CALL write_byte_slow
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s3, s5 ;transmit TA2
CALL write_byte_slow
CALL compute_CRC16 ;compute CRC for value in 's3'
;
;Read 32-bytes of data associated with page 0
;Store these as M1 through to M8
;
rapc_line_loop: CALL send_CR
LOAD s0, s5 ;display 16-bit address
CALL send_hex_byte
LOAD s0, s4
CALL send_hex_byte
CALL send_space
CALL send_space
rapc_data_loop: CALL send_space
CALL read_byte_slow ;read data into s3
CALL compute_CRC16 ;compute CRC for value in 's3'
OUTPUT s3, W_word_write_port ;store as 'M' word
LOAD s0, s3 ;display byte
CALL send_hex_byte
ADD s4, 01 ;increment address
ADDCY s5, 00
TEST s4, 07 ;test for 8-byte boundary
JUMP NZ, rapc_data_loop
COMPARE s4, 20 ;test for last address
JUMP NZ, rapc_line_loop
CALL send_CR
;
;Read one byte that should be value FF hex
;
CALL read_byte_slow ;read data into s3
CALL compute_CRC16 ;compute CRC for value in 's3'
LOAD s0, s3 ;display byte
CALL send_hex_byte
CALL send_CR
CALL read_send_test_CRC16 ;read, display and test CRC value
;
;Complete table by stroring M9 through to M15
;
LOAD s0, FF ;W9 = FF FF FF FF
LOAD s1, 04
store_W9: OUTPUT s0, W_word_write_port
SUB s1, 01
JUMP NZ, store_W9
;
LOAD s0, 40 ;W10 begins with 40 for page 0
OUTPUT s0, W_word_write_port
;
;W10 ends with family code and serial number 0 and 1.
;W11 is formed of serial number 2, 3, 4 and 5.
;All of this information is in PicoBlaze memory having been read by the
;read ROM command.
;
LOAD s1, family_code ;pointer to memory
LOAD s2, 07 ;7 bytes to read and store
next_M10_M11: FETCH s0, (s1)
OUTPUT s0, W_word_write_port
ADD s1, 01 ;increment pointer
SUB s2, 01
JUMP NZ, next_M10_M11
;
LOAD s0, secret4 ;store M12 (secret 4, 5, 6 and 7) in Wt buffer
OUTPUT s0, W_word_write_port
LOAD s0, secret5
OUTPUT s0, W_word_write_port
LOAD s0, secret6
OUTPUT s0, W_word_write_port
LOAD s0, secret7
OUTPUT s0, W_word_write_port
;
FETCH s0, scratchpad4 ;M13 uses scratchpad 4, 5, and 6 and '80' hex
OUTPUT s0, W_word_write_port
FETCH s0, scratchpad5
OUTPUT s0, W_word_write_port
FETCH s0, scratchpad6
OUTPUT s0, W_word_write_port
LOAD s0, 80
OUTPUT s0, W_word_write_port
;
LOAD s0, 00 ;W14 = 00 00 00 00 W15 = 00 00 01 B8
LOAD s1, 06
store_W14_W15: OUTPUT s0, W_word_write_port
SUB s1, 01
JUMP NZ, store_W14_W15
LOAD s0, 01
OUTPUT s0, W_word_write_port
LOAD s0, B8
OUTPUT s0, W_word_write_port
;
;Compute the SHA-1 algorithm at the same time that the DS2432 is also computing (2ms).
;
CALL compute_sha1
;
;The 160-bit Message Authentication Code is read from the DS2432 as 20 bytes
;and compared with the concatenation of variables E, D, C, B and A in that order
;with each variable received from the DS2432 least significant byte first.
;Each received byte is also used to form a 16-bit CRC value which is tested to
;reveal any communication errors.
;
;
CALL send_mac ;display 'mac='
CALL clear_CRC16 ;prepare CRC registers [sE,sD]
LOAD sC, 00 ;Clear byte match counter
LOAD sB, var_E0 ;start match with LS-Byte of variable 'E'
mac_match_var: LOAD sA, 04 ;4 bytes to match in each variable
mac_match_byte: FETCH s9, (sB) ;read variable byte from local SHA-1
CALL read_byte_slow ;read DS2432 byte into s3
CALL compute_CRC16 ;compute CRC for value in 's3'
COMPARE s3, s9 ;compare MAC values
JUMP NZ, display_mac_byte ;count matching bytes
ADD sC, 01 ;decrement match counter
display_mac_byte: LOAD s0, s3 ;display byte
CALL send_hex_byte
CALL send_space
SUB sA, 01 ;counts bytes per variable
JUMP Z, next_mac_var
ADD sB, 01
JUMP mac_match_byte
next_mac_var: COMPARE sB, var_A3 ;test for last byte
JUMP Z, report_mac
SUB sB, 07 ;point to next variable
JUMP mac_match_var
;
;MAC has passed if all 20 bytes matched
;
report_mac: CALL send_CR
COMPARE sC, 14 ;20 bytes should have matched
JUMP NZ, mac_fail
CALL send_Pass
JUMP read_mac_CRC
mac_fail: CALL send_Fail
;
;Next two bytes received are the 16-bit CRC
;Read 16-bit CRC into [s5,s4] and send value to UART
;
read_mac_CRC: CALL read_send_test_CRC16 ;read, display and test CRC value
;
;Read one byte that should be value AA hex.
; Would actually read AA hex continuously until master reset
;
CALL read_byte_slow ;read data into s3
LOAD s0, s3 ;display byte
CALL send_hex_byte
CALL send_CR
;
JUMP warm_start
;
;
;**************************************************************************************
; Compute SHA-1 Algorithm.
;**************************************************************************************
;
; Computes the SHA-1 algorithm based on the initial table of values (M0 through to M15)
; which are stored in the external Wt buffer.
;
; The SHA-1 algorithms uses 5 variables called 'A', 'B', 'C', 'D' and 'E'. Each variable
; is 32-bits and stored as 4 bytes in PicoBlaze scratch pad memory. The locations must
; be defined using constants 'var_A0' thought to 'var_E3' in ascending locations.
;
; Constants must also be used to define access to the external Wt buffer.
;
; During this process, register 'sE' is used to count iterations from 0 to 79 (4F hex).
; Other registers are consistently grouped as follows to support 32-bit operations.
;
; Register set [s5,s4,s3,s2] is used as a temporary 32-bit word
; Register set [s9,s8,s7,s6] is used as a temporary 32-bit word
; Register set [sD,sC,sB,sA] is used as a temporary 32-bit word
;
;
; Initialise the 32-bit variables
;
;
compute_sha1: LOAD s0, 01 ;A=67452301
STORE s0, var_A0
LOAD s0, 23
STORE s0, var_A1
LOAD s0, 45
STORE s0, var_A2
LOAD s0, 67
STORE s0, var_A3
LOAD s0, 89 ;B=EFCDAB89
STORE s0, var_B0
LOAD s0, AB
STORE s0, var_B1
LOAD s0, CD
STORE s0, var_B2
LOAD s0, EF
STORE s0, var_B3
LOAD s0, FE ;C=98BADCFE
STORE s0, var_C0
LOAD s0, DC
STORE s0, var_C1
LOAD s0, BA
STORE s0, var_C2
LOAD s0, 98
STORE s0, var_C3
LOAD s0, 76 ;D=10325476
STORE s0, var_D0
LOAD s0, 54
STORE s0, var_D1
LOAD s0, 32
STORE s0, var_D2
LOAD s0, 10
STORE s0, var_D3
LOAD s0, F0 ;E=C3D2E1F0
STORE s0, var_E0
LOAD s0, E1
STORE s0, var_E1
LOAD s0, D2
STORE s0, var_E2
LOAD s0, C3
STORE s0, var_E3
;
;
LOAD sE, 00 ;reset iteration counter
;
;
;Compute ft(B,C,D) in register set [s5,s4,s3,s2] and then add constant Kt.
;
;Iterations 0 to 19 - process type 1
; ft = (B and C) or ((not B) and D)
; Then the constant Kt=5A827999 will be added
;
;Iterations 20 to 39 and iterations 60 to 79 - process type 2
; ft = B xor C xor D
; Then the constant Kt=6ED9EBA1 will be added for iterations 20 to 39
; Then the constant Kt=CA62C1D6 will be added for iterations 60 to 79
;
;Iterations 40 to 59 - process type 3
; ft = (B and C) or (B and D) or (C and D)
; Then the constant Kt=8F1BBCDC will be added
;
next_sha1_iteration: FETCH s5, var_B3 ;B in [s5,s4,s3,s2]
FETCH s4, var_B2
FETCH s3, var_B1
FETCH s2, var_B0
CALL fetch_C ;C in [s9,s8,s7,s6]
FETCH sD, var_D3 ;D in [sD,sC,sB,sA]
FETCH sC, var_D2
FETCH sB, var_D1
FETCH sA, var_D0
;
;Determine process type
;
COMPARE sE, 14 ;set carry flag for iterations <20
JUMP C, ft_type1
COMPARE sE, 28 ;set carry flag for iterations <40
JUMP C, ft_type2
COMPARE sE, 3C ;set carry flag for iterations <60
JUMP C, ft_type3
;
; ft = B xor C xor D
;
; B xor C = B xor C
; [s5,s4,s3,s2] = [s5,s4,s3,s2] xor [s9,s8,s7,s6]
;
; B xor C xor D = (B xor C) xor D
; [s5,s4,s3,s2] = [s5,s4,s3,s2] xor [sD,sC,sB,sA]
;
;
ft_type2: XOR s5, s9 ;B xor C in [s5,s4,s3,s2]
XOR s4, s8
XOR s3, s7
XOR s2, s6
XOR s5, sD ;(B xor C) xor D in [s5,s4,s3,s2]
XOR s4, sC
XOR s3, sB
XOR s2, sA
COMPARE sE, 3C ;set carry flag for iterations <60
JUMP NC, Kt_CA62C1D6
ADD s2, A1 ;add Kt=6ED9EBA1
ADDCY s3, EB
ADDCY s4, D9
ADDCY s5, 6E
JUMP compute_TMP
Kt_CA62C1D6: ADD s2, D6 ;add Kt=CA62C1D6
ADDCY s3, C1
ADDCY s4, 62
ADDCY s5, CA
JUMP compute_TMP
;
; ft = (B and C) or ((not B) and D)
;
; B and C = C and B
; [s9,s8,s7,s6] = [s9,s8,s7,s6] and [s5,s4,s3,s2]
;
; not B = B xor FFFFFFFF
; [s5,s4,s3,s2] = [s5,s4,s3,s2] xor [FF,FF,FF,FF]
;
; (not B) and D = (not B) and D
; [s5,s4,s3,s2] = [s5,s4,s3,s2] and [sD,sC,sB,sA]
;
; ;(B and C) or ((not B) and D) = ((not B) and D) or (B and C)
; [s5,s4,s3,s2] = [s5,s4,s3,s2] or [s9,s8,s7,s6]
;
ft_type1: AND s9, s5 ;B and C in [s9,s8,s7,s6]
AND s8, s4
AND s7, s3
AND s6, s2
XOR s5, FF ;(not B) in [s5,s4,s3,s2]
XOR s4, FF
XOR s3, FF
XOR s2, FF
AND s5, sD ;((not B) and D) in [s5,s4,s3,s2]
AND s4, sC
AND s3, sB
AND s2, sA
OR s5, s9 ;(B and C) or ((not B) and D) in [s5,s4,s3,s2]
OR s4, s8
OR s3, s7
OR s2, s6
ADD s2, 99 ;add Kt=5A827999
ADDCY s3, 79
ADDCY s4, 82
ADDCY s5, 5A
JUMP compute_TMP
;
;Routine to fetch variable 'C' into register set [s9,s8,s7,s6]
;
fetch_C: FETCH s9, var_C3
FETCH s8, var_C2
FETCH s7, var_C1
FETCH s6, var_C0
RETURN
;
; ft = (B and C) or (B and D) or (C and D)
;
; B and C = C and B
; [s9,s8,s7,s6] = [s9,s8,s7,s6] and [s5,s4,s3,s2]
;
; B and D = B and D
; [s5,s4,s3,s2] = [s5,s4,s3,s2] and [sD,sC,sB,sA]
;
; (B and C) or (B and D) = (B and D) or (B and C)
; [s5,s4,s3,s2] = [s5,s4,s3,s2] or [s9,s8,s7,s6]
;
; read C again into [s9,s8,s7,s6]
;
; C and D = C and D
; [s9,s8,s7,s6] = [s9,s8,s7,s6] and [sD,sC,sB,sA]
;
; ((B and C) or (B and D)) or (C and D) = ((B and C) or (B and D)) or (C and D)
; [s5,s4,s3,s2] = [s5,s4,s3,s2] or [s9,s8,s7,s6]
;
ft_type3: AND s9, s5 ;(B and C) in [s9,s8,s7,s6]
AND s8, s4
AND s7, s3
AND s6, s2
AND s5, sD ;(B and D) in [s5,s4,s3,s2]
AND s4, sC
AND s3, sB
AND s2, sA
OR s5, s9 ;(B and C) or (B and D) in [s5,s4,s3,s2]
OR s4, s8
OR s3, s7
OR s2, s6
CALL fetch_C ;C in [s9,s8,s7,s6]
AND s9, sD ;(C and D) in [s9,s8,s7,s6]
AND s8, sC
AND s7, sB
AND s6, sA
OR s5, s9 ;(B and C) or (B and D) or (C and D) in [s5,s4,s3,s2]
OR s4, s8
OR s3, s7
OR s2, s6
ADD s2, DC ;add Kt=8F1BBCDC
ADDCY s3, BC
ADDCY s4, 1B
ADDCY s5, 8F
;
;Add variable 'E' to [s5,s4,s3,s2]
;
compute_TMP: FETCH s0, var_E0
ADD s2, s0
FETCH s0, var_E1
ADDCY s3, s0
FETCH s0, var_E2
ADDCY s4, s0
FETCH s0, var_E3
ADDCY s5, s0
;
;Add variable 'A' rotated left 5 places
;
FETCH s9, var_A3 ;A in [s9,s8,s7,s6]
FETCH s8, var_A2
FETCH s7, var_A1
FETCH s6, var_A0
LOAD s0, 05 ;rotate left 5 places
CALL rotate_word_left_N_places
ADD s2, s6 ;add to TMP
ADDCY s3, s7
ADDCY s4, s8
ADDCY s5, s9
;
;
;Compute Wt in register set [s9,s8,s7,s6]
; Value computed is also stored back in the external buffer for
; use in later iterations as well as being added to TMP.
;
;Iterations 0 to 15
; Wt = Mt
; This only requires Wt-16 to be read and then shifted back into the buffer again.
;
;Iterations 0 to 15
; Wt = rotate_left_1_place(Wt-3 xor Wt-8 xor Wt-14 xor Wt-16)
; This requires all data values to be read first. Then XORed and rotated before
; shifting the new Wt word into the buffer.
;
;
INPUT s9, Wt_minus16_byte3_read_port ;Read Wt-16 value
INPUT s8, Wt_minus16_byte2_read_port
INPUT s7, Wt_minus16_byte1_read_port
INPUT s6, Wt_minus16_byte0_read_port
COMPARE sE, 10 ;set carry flag for iterations 0 to 15
JUMP C, store_Wt
;
;Read other Wt words and perform XOR
;
INPUT s0, Wt_minus14_byte3_read_port ;XOR with Wt-14 value
XOR s9, s0
INPUT s0, Wt_minus14_byte2_read_port
XOR s8, s0
INPUT s0, Wt_minus14_byte1_read_port
XOR s7, s0
INPUT s0, Wt_minus14_byte0_read_port
XOR s6, s0
INPUT s0, Wt_minus8_byte3_read_port ;XOR with Wt-8 value
XOR s9, s0
INPUT s0, Wt_minus8_byte2_read_port
XOR s8, s0
INPUT s0, Wt_minus8_byte1_read_port
XOR s7, s0
INPUT s0, Wt_minus8_byte0_read_port
XOR s6, s0
INPUT s0, Wt_minus3_byte3_read_port ;XOR with Wt-3 value
XOR s9, s0
INPUT s0, Wt_minus3_byte2_read_port
XOR s8, s0
INPUT s0, Wt_minus3_byte1_read_port
XOR s7, s0
INPUT s0, Wt_minus3_byte0_read_port
XOR s6, s0
CALL rotate_word_left ;rotate XORed word left by one place
;
;Store new Wt value in external buffer
;
store_Wt: OUTPUT s9, W_word_write_port
OUTPUT s8, W_word_write_port
OUTPUT s7, W_word_write_port
OUTPUT s6, W_word_write_port
;
;Add new computed Wt value to TMP in [s5,s4,s3,s2]
;
ADD s2, s6
ADDCY s3, s7
ADDCY s4, s8
ADDCY s5, s9
;
;TMP is now complete in [s5,s4,s3,s2]
;
;
;copy values
; E <= D
; D <= C
; C <= B (this will need to be rotated 30 places afterwards)
; B <= A
;
LOAD sD, 04 ;4 bytes per word to copy
copy_var_loop: LOAD sC, var_E3
LOAD sB, var_E2
move_var_loop: FETCH sA, (sB)
STORE sA, (sC)
SUB sC, 01
SUB sB, 01
COMPARE sC, var_A0
JUMP NZ, move_var_loop
SUB sD, 01
JUMP NZ, copy_var_loop
;
;rotate 'C' (the previous 'B') left 30 places
;
CALL fetch_C ;C in [s9,s8,s7,s6]
LOAD s0, 1E ;rotate left 30 places
CALL rotate_word_left_N_places
STORE s9, var_C3
STORE s8, var_C2
STORE s7, var_C1
STORE s6, var_C0
;
; A <= TMP
;
STORE s5, var_A3
STORE s4, var_A2
STORE s3, var_A1
STORE s2, var_A0
;
;count iterations
;
COMPARE sE, 4F ;test for last iteration = 79 decimal (4F hex)
RETURN Z
ADD sE, 01
JUMP next_sha1_iteration
;
; Routine to rotate left the contents of Register set [s9,s8,s7,s6]
; by the number of places specified in register 's0'.
;
rotate_word_left_N_places: CALL rotate_word_left
SUB s0, 01
JUMP NZ, rotate_word_left_N_places
RETURN
;
; Routine to rotate left the contents of Register set [s9,s8,s7,s6]
; by one place.
;
rotate_word_left: TEST s9, 80 ;test MSB of word
SLA s6
SLA s7
SLA s8
SLA s9
RETURN
;
;**************************************************************************************
; Compute 8-bit CRC used by DS2432.
;**************************************************************************************
;
; The DS2432 computes an 8-bit CRC using the polynomial X8 + X5 + X4 + 1.
; See the DS2432 data sheet for full details.
;
; Test input value of value 00 00 00 01 B8 1C 02
; should produce CRC=A2.
;
; This routine computes the same CRC based on the values stored in the KCPSM3
; scratch pad memory by the read ROM command. The result is returned in register s0.
;
; Registers used s0,s1,s2,s3,s4,s5,s6,s7,s8,s9
;
;
; Start by loading family code and serial number (56-bits) into register set
; [s9,s8,s7,s6,s5,s4,s3] so that it can be shifted out LSB first.
;
;
compute_CRC8: FETCH s3, family_code
FETCH s4, serial_number0
FETCH s5, serial_number1
FETCH s6, serial_number2
FETCH s7, serial_number3
FETCH s8, serial_number4
FETCH s9, serial_number5
LOAD s2, 38 ;56 bits to shift (38 hex)
LOAD s0, 00 ;clear CRC value
crc8_loop: LOAD s1, s0 ;copy current CRC value
XOR s1, s3 ;Need to know LSB XOR next input bit
TEST s1, 01 ;test result of XOR in LSB
JUMP NC, crc8_shift
XOR s0, 18 ;compliment bits 3 and 4 of CRC
crc8_shift: SR0 s1 ;Carry gets LSB XOR next input bit
SRA s0 ;shift Carry into MSB to form new CRC value
SR0 s9 ;shift input value
SRA s8
SRA s7
SRA s6
SRA s5
SRA s4
SRA s3
SUB s2, 01 ;count iterations
JUMP NZ, crc8_loop
RETURN
;
;
;
;**************************************************************************************
; Clear or Compute 16-bit CRC used by DS2432.
;**************************************************************************************
;
; The DS2432 computes a 16-bit CRC using the polynomial X16 + X15 + X2 + 1.
; See the DS2432 data sheet for full details.
;
; Note that the value formed in the CRC shift register MUST BE INVERTED to give the
; same value as that sent from the DS2432 during scratchpad write, scratchpad read
; and read auth page commands.
;
; The 16-bit CRC is computed using a different number of bytes depending on the
; command. This routine has been written such that the CRC can be computed one
; byte at a time. The byte to be processed should be provided in register 's3'
; and the contents of this register are preserved.
;
; This routine computes the 16-bit CRC in the register pair [sE,sD] and these
; registers must not be disturbed between calls of this routine.
;
; Before starting a CRC computation the 'clear_CRC16' should be used.
;
; Registers used s0,s1,s3,sD,sE
; s3 is preserved.
; sD and sE should not be disturbed between calls if CRC value is required.
;
;
clear_CRC16: LOAD sE, 00 ;[sE,sD]=0000
LOAD sD, 00
RETURN
;
compute_CRC16: LOAD s1, 08 ;8-bits to shift
crc16_loop: LOAD s0, sD ;copy current CRC value
XOR s0, s3 ;Need to know LSB XOR next input bit
TEST s0, 01 ;test result of XOR in LSB
JUMP NC, crc16_shift
XOR sD, 02 ;compliment bit 1 of CRC
XOR sE, 40 ;compliment bit 14 of CRC
crc16_shift: SR0 s0 ;Carry gets LSB XOR next input bit
SRA sE ;shift Carry into MSB to form new CRC value
SRA sD
RR s3 ;shift input value
SUB s1, 01 ;count bits
JUMP NZ, crc16_loop ;next bit
RETURN
;
;
;**************************************************************************************
; Read 16-bit CRC from DS2432, send value received to UART and test result.
;**************************************************************************************
;
; The computed CRC value for comparison must be in register pair [sE,sD]
;
read_send_test_CRC16: CALL read_byte_slow ;read 16-bit CRC into [s5,s4]
LOAD s4, s3
CALL read_byte_slow
LOAD s5, s3
CALL send_crc ;'crc=' to display CRC value
LOAD s0, s5
CALL send_hex_byte
LOAD s0, s4
CALL send_hex_byte
CALL send_CR
XOR sD, FF ;1's complement the computed CRC value
XOR sE, FF
COMPARE s4, sD ;test received value with computed value
JUMP NZ, crc16_fail
COMPARE s5, sE
JUMP NZ, crc16_fail
CALL send_Pass ;display 'Pass' with carriage return
RETURN
crc16_fail: CALL send_Fail ;display 'Fail' with carriage return
RETURN
;
;
;**************************************************************************************
; Initialise the DS2432 1-wire interface.
;**************************************************************************************
;
; The 1-wire interface is an open-collector communication scheme employing an external
; pull-up resistor of 680 Ohms.
;
; The hardware section of this translates the one bit signal from PicoBlaze such that
; when this signal is Low the output is driven Low, but when it is High, it turns off
; the output buffer and the signal is pulled High externally.
;
; This initialisation routine simply ensures that the line is High after configuration.
; It is vital that DS_wire is generally in the High state because it is the only way in
; which the DS2432 device derives power to operate.
;
; Registers used s0
;
DS_wire_init: LOAD s0, DS_wire
OUTPUT s0, DS_wire_out_port
RETURN
;
;
;**************************************************************************************
; DS2432 initialisation - Regular Speed.
;**************************************************************************************
;
; The initialisation sequence must be performed before any communication can be
; made with the DS2432 device. This involves the application of an active Low master
; reset pulse.
;
; The regular (slow) speed communication is established by transmitting an active
; Low reset pulse for a duration of at least 480us. This design generates a 500us pulse.
;
; The DS2432 acknowledges the reset and the setting of regular mode by generating an
; active Low 'Rx Presence Pulse'. This presence pulse can start 15 to 60us after the
; reset pulse and will end between 120 and 300us after the reset pulse.
;
; To confirm that regular mode has been set, this routine confirms that the presence pulse
; is active only after 60us have elapsed since the reset pulse. This ensures that the
; faster presence pulse of overdrive mode can not be detected.
;
; The carry flag will be set if no valid presence pulse was received (wire remained High) and
; can be used to indicate an initialisation failure or success.
;
; The routine only completes 300us after the presence pulse to ensure the DS2432 has
; completed the presence pulse and is ready for the first operation.
;
; Registers used s0,s1,s2
;
DS_init_regular_mode: LOAD s0, 00 ;transmit reset pulse
OUTPUT s0, DS_wire_out_port
;Delay of 500us is equivalent to 12500 instructions at 50MHz.
;This delay loop is formed of 28 instructions requiring 446 repetitions.
LOAD s2, 01 ;[s3,s2]=445 decimal (01BD hex)
LOAD s1, BD
rm_wait_500us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
SUBCY s2, 00
JUMP NC, rm_wait_500us ;repeat until -1
LOAD s0, 01 ;end of regular reset pulse
OUTPUT s0, DS_wire_out_port
;Delay of 60us is equivalent to 1500 instructions at 50MHz.
;This delay and is formed of 27 instructions requiring 56 repetitions.
LOAD s1, 38 ;56 (38 hex)
rm_wait_60us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, rm_wait_60us ;repeat until zero
;The DS_wire is now checked at approximately 1us intervals for the next 240us looking
;to detect an active Low presence pulse. The 240us is equivalent to 6000 instructions
;at 50MHz and this polling loop is formed of 33 instructions requiring 182 repetitions.
LOAD s2, 01 ;set bit which will be reset by a presence pulse
LOAD s1, B6 ;182 (B6 hex)
rm_poll_240us: CALL delay_1us ;25 instructions including CALL
CALL read_DS_wire ;read wire - 5 instructions including CALL
AND s2, s0 ;clear flag if DS_wire was Low
SUB s1, 01 ;decrement delay counter
JUMP NZ, rm_poll_240us ;repeat until zero
TEST s2, 01 ;set carry flag if no pulse detected
RETURN
;
;
;**************************************************************************************
; Read the DS_wire
;**************************************************************************************
;
; The DS_wire signal is read and returned in bit0 of register 's0'.
; Additionally the carry flag is set if the signal is High and reset if Low
;
; Registers used s0
;
read_DS_wire: INPUT s0, DS_wire_in_port
AND s0, DS_wire ;ensure only bit0 is active
TEST s0, DS_wire ;set carry flag if DS_wire is High
RETURN
;
;
;
;**************************************************************************************
; Write a byte to DS2432 in regular speed mode.
;**************************************************************************************
;
; Bytes are written to the DS2432 with LSB first.
;
; The byte to be written should be provided in register 's3' and this will be preserved.
;
; Registers used s0,s1,s2,s3
;
write_byte_slow: LOAD s2, 08 ;8 bits to transmit
wbs_loop: RR s3 ;test next bit LSB first
JUMP C, wbs1 ;transmit '0' or '1'
CALL write_Low_slow
JUMP next_slow_bit
wbs1: CALL write_High_slow
next_slow_bit: SUB s2, 01 ;count bits
JUMP NZ, wbs_loop ;repeat until 8-bits transmitted
RETURN
;
;
;
;**************************************************************************************
; Write a '0' to DS_wire in regular speed mode.
;**************************************************************************************
;
; To write a '0' to the DS_wire the signal must be Low for 60 to 120us. This design
; generates a 78us active Low pulse.
;
; The DS2432 then requires at least 1us of recovery time for which this routine
; provides a 2us delay such that the entire write Low process (slot time) is 80us.
; A recovery time of 1us was also found to be marginal in practice probably due
; to the rise time of the DS_wire via the external pull up resistor.
;
; Registers used s0,s1
;
write_Low_slow: LOAD s0, 00 ;transmit Low pulse
OUTPUT s0, DS_wire_out_port
;Delay of 78us is equivalent to 1950 instructions at 50MHz.
;This delay loop is formed of 27 instructions requiring 72 repetitions.
LOAD s1, 48 ;72 (48 hex)
wls_wait_78us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, wls_wait_78us ;repeat until zero
LOAD s0, 01 ;end of Low pulse
OUTPUT s0, DS_wire_out_port
CALL delay_1us ;2us recovery time
CALL delay_1us
RETURN
;
;
;**************************************************************************************
; Write a '1' to DS_wire in regular speed mode.
;**************************************************************************************
;
; To write a '1' to the DS_wire the signal must be Low for 1 to 15us to instigate the
; write of the data. This design generates an 8us active Low pulse for this purpose.
;
; Then the output must be High for 53 to 114us to provide the '1' for the DS2432 to
; read and then provide recovery time. This design implements a 72us delay such that
; the entire write High process (slot time) is 80us
;
; Registers used s0,s1
;
write_High_slow: LOAD s0, 00 ;transmit Low pulse
OUTPUT s0, DS_wire_out_port
;Delay of 8us is equivalent to 200 instructions at 50MHz.
;This delay loop is formed of 27 instructions requiring 8 repetitions.
LOAD s1, 08 ;8 (08 hex)
whs_wait_8us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, whs_wait_8us ;repeat until zero
LOAD s0, 01 ;end of Low pulse
OUTPUT s0, DS_wire_out_port
;Delay of 72us is equivalent to 1800 instructions at 50MHz.
;This delay loop is formed of 27 instructions requiring 67 repetitions.
LOAD s1, 43 ;67 (43 hex)
whs_wait_72us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, whs_wait_72us ;repeat until zero
RETURN
;
;
;
;**************************************************************************************
; Read a byte from DS2432 in regular speed mode.
;**************************************************************************************
;
; Bytes are read from the DS2432 with LSB first.
;
; The byte read will be returned in register 's3'.
;
; Registers used s0,s1,s2,s3
;
read_byte_slow: LOAD s2, 08 ;8 bits to receive
rbs_loop: CALL read_bit_slow ;read next bit LSB first
SUB s2, 01 ;count bits
JUMP NZ, rbs_loop ;repeat until 8-bits received
RETURN
;
;
;
;
;**************************************************************************************
; Read a data bit sent from the DS2432 in regular speed mode.
;**************************************************************************************
;
; To read a bit, PicoBlaze must initiate the processed with an active Low pulse of
; 1 to 15us. This design generates a 4us active Low pulse for this purpose.
;
; Then DS2432 responds to the Low pulse by diving DS_wire in two different ways
; depending on the logic level it is trying to send back.
;
; For a logic '0' the DS2432 will drive the DS-wire Low for up to 15us after
; the start of the instigating pulse. Therefore PicoBlaze must read the DS-wire
; before this time has elapsed but only after it has itself released the wire.
;
; For a logic '1' the DS2432 will do nothing and hence the DS-wire will be pulled
; High by the external resistor after PicoBlaze has released the wire. PicoBlaze
; will sample the wire and detect the High level.
;
; In this design, PicoBlaze needs to detect the logic state of the wire after
; releasing the wire at 4us. Sampling the wire too quickly would not provide
; adequate time for a High signal to be formed by the pull up resistor. However, it
; must sample the wire before 15us have elapsed and any potential Low is removed.
; This design samples the wire at 12us which is 8us after the initiation pulse ends.
;
; A further delay of 68us is then allowed for the DS2432 to stop transmitting and
; to recover. This also mean that the entire read process (slot time) is 80us.
;
; The received data bit is SHIFTED into the MSB of register 's3'. In this way
; the reception of 8-bits will shift the first bit into the LSB position of 's3'.
;
; Registers used s0,s1,s3
;
read_bit_slow: LOAD s0, 00 ;transmit Low pulse
OUTPUT s0, DS_wire_out_port
;Delay of 4us is equivalent to 100 instructions at 50MHz.
;This delay loop is formed of 27 instructions requiring 4 repetitions.
LOAD s1, 04 ;4 (04 hex)
rbs_wait_4us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, rbs_wait_4us ;repeat until zero
LOAD s0, 01 ;end of Low pulse
OUTPUT s0, DS_wire_out_port
;Delay of 8us is equivalent to 200 instructions at 50MHz.
;This delay loop is formed of 27 instructions requiring 8 repetitions.
LOAD s1, 08 ;8 (08 hex)
rbs_wait_8us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, rbs_wait_8us ;repeat until zero
CALL read_DS_wire ;sample wire (carry = state)
SRA s3 ;shift received bit into MSB of s3
;Delay of 68us is equivalent to 1700 instructions at 50MHz.
;This delay loop is formed of 27 instructions requiring 63 repetitions.
LOAD s1, 3F ;63 (3F hex)
rbs_wait_68us: CALL delay_1us ;25 instructions including CALL
SUB s1, 01 ;decrement delay counter
JUMP NZ, rbs_wait_68us ;repeat until zero
RETURN
;
;
;**************************************************************************************
; Software delay routines
;**************************************************************************************
;
; Delay of 1us.
;
; Constant value defines reflects the clock applied to KCPSM3. Every instruction
; executes in 2 clock cycles making the calculation highly predictable. The '6' in
; the following equation even allows for 'CALL delay_1us' instruction in the initiating code.
;
; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
;
; Register used s0
;
delay_1us: LOAD s0, delay_1us_constant
wait_1us: SUB s0, 01
JUMP NZ, wait_1us
RETURN
;
; Delay of 40us.
;
; Registers used s0, s1
;
delay_40us: LOAD s1, 28 ;40 x 1us = 40us
wait_40us: CALL delay_1us
SUB s1, 01
JUMP NZ, wait_40us
RETURN
;
;
; Delay of 1ms.
;
; Registers used s0, s1, s2
;
delay_1ms: LOAD s2, 19 ;25 x 40us = 1ms
wait_1ms: CALL delay_40us
SUB s2, 01
JUMP NZ, wait_1ms
RETURN
;
; Delay of 20ms.
;
; Registers used s0, s1, s2, s3
;
delay_20ms: LOAD s3, 14 ;20 x 1ms = 20ms
wait_20ms: CALL delay_1ms
SUB s3, 01
JUMP NZ, wait_20ms
RETURN
;
; Delay of approximately 1 second.
;
; Registers used s0, s1, s2, s3, s4
;
delay_1s: LOAD s4, 14 ;50 x 20ms = 1000ms
wait_1s: CALL delay_20ms
SUB s4, 01
JUMP NZ, wait_1s
RETURN
;
;
;**************************************************************************************
; UART communication routines
;**************************************************************************************
;
; Read one character from the UART
;
; Character read will be returned in a register called 'UART_data'.
;
; The routine first tests the receiver FIFO buffer to see if data is present.
; If the FIFO is empty, the routine waits until there is a character to read.
; As this could take any amount of time the wait loop could include a call to a
; subroutine which performs a useful function.
;
;
; Registers used s0 and UART_data
;
read_from_UART: INPUT s0, status_port ;test Rx_FIFO buffer
TEST s0, rx_data_present ;wait if empty
JUMP NZ, read_character
JUMP read_from_UART
read_character: INPUT UART_data, UART_read_port ;read from FIFO
RETURN
;
;
;
; Transmit one character to the UART
;
; Character supplied in register called 'UART_data'.
;
; The routine first tests the transmit FIFO buffer to see if it is full.
; If the FIFO is full, then the routine waits until it there is space.
;
; Registers used s0
;
send_to_UART: INPUT s0, status_port ;test Tx_FIFO buffer
TEST s0, tx_full ;wait if full
JUMP Z, UART_write
JUMP send_to_UART
UART_write: OUTPUT UART_data, UART_write_port
RETURN
;
;
;**************************************************************************************
; Useful ASCII conversion and handling routines
;**************************************************************************************
;
;
; Convert character to upper case
;
; The character supplied in register s0.
; If the character is in the range 'a' to 'z', it is converted
; to the equivalent upper case character in the range 'A' to 'Z'.
; All other characters remain unchanged.
;
; Registers used s0.
;
upper_case: COMPARE s0, 61 ;eliminate character codes below 'a' (61 hex)
RETURN C
COMPARE s0, 7B ;eliminate character codes above 'z' (7A hex)
RETURN NC
AND s0, DF ;mask bit5 to convert to upper case
RETURN
;
;
; Convert hexadecimal value provided in register s0 into ASCII characters
;
; The value provided must can be any value in the range 00 to FF and will be converted into
; two ASCII characters.
; The upper nibble will be represented by an ASCII character returned in register s2.
; The lower nibble will be represented by an ASCII character returned in register s1.
;
; The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex
; added to the actual decimal value. The ASCII representations of 'A' to 'F' are 41 to 46
; hexadecimal requiring a further addition of 07 to the 30 already added.
;
; Registers used s0, s1 and s2.
;
hex_byte_to_ASCII: LOAD s1, s0 ;remember value supplied
SR0 s0 ;isolate upper nibble
SR0 s0
SR0 s0
SR0 s0
CALL hex_to_ASCII ;convert
LOAD s2, s0 ;upper nibble value in s2
LOAD s0, s1 ;restore complete value
AND s0, 0F ;isolate lower nibble
CALL hex_to_ASCII ;convert
LOAD s1, s0 ;lower nibble value in s1
RETURN
;
; Convert hexadecimal value provided in register s0 into ASCII character
;
;Register used s0
;
hex_to_ASCII: SUB s0, 0A ;test if value is in range 0 to 9
JUMP C, number_char
ADD s0, 07 ;ASCII char A to F in range 41 to 46
number_char: ADD s0, 3A ;ASCII char 0 to 9 in range 30 to 40
RETURN
;
;
; Send the two character HEX value of the register contents 's0' to the UART
;
; Registers used s0, s1, s2
;
send_hex_byte: CALL hex_byte_to_ASCII
LOAD UART_data, s2
CALL send_to_UART
LOAD UART_data, s1
CALL send_to_UART
RETURN
;
;
;
; Convert the HEX ASCII characters contained in 's3' and 's2' into
; an equivalent hexadecimal value in register 's0'.
; The upper nibble is represented by an ASCII character in register s3.
; The lower nibble is represented by an ASCII character in register s2.
;
; Input characters must be in the range 00 to FF hexadecimal or the CARRY flag
; will be set on return.
;
; Registers used s0, s2 and s3.
;
ASCII_byte_to_hex: LOAD s0, s3 ;Take upper nibble
CALL ASCII_to_hex ;convert to value
RETURN C ;reject if out of range
LOAD s3, s0 ;remember value
SL0 s3 ;multiply value by 16 to put in upper nibble
SL0 s3
SL0 s3
SL0 s3
LOAD s0, s2 ;Take lower nibble
CALL ASCII_to_hex ;convert to value
RETURN C ;reject if out of range
OR s0, s3 ;merge in the upper nibble with CARRY reset
RETURN
;
;
; Routine to convert ASCII data in 's0' to an equivalent HEX value.
;
; If character is not valid for hex, then CARRY is set on return.
;
; Register used s0
;
ASCII_to_hex: ADD s0, B9 ;test for above ASCII code 46 ('F')
RETURN C
SUB s0, E9 ;normalise 0 to 9 with A-F in 11 to 16 hex
RETURN C ;reject below ASCII code 30 ('0')
SUB s0, 11 ;isolate A-F down to 00 to 05 hex
JUMP NC, ASCII_letter
ADD s0, 07 ;test for above ASCII code 46 ('F')
RETURN C
SUB s0, F6 ;convert to range 00 to 09
RETURN
ASCII_letter: ADD s0, 0A ;convert to range 0A to 0F
RETURN
;
;
; Read one character from UART and echo.
; Convert to upper case and return.
;
;
read_upper_case: CALL read_from_UART ;read command character from UART
CALL send_to_UART ;echo character
LOAD s0, UART_data ;convert to upper case
CALL upper_case
RETURN
;
;
; Read two hex characters from UART and convert to single byte data
;
obtain_8bits: CALL read_upper_case ;obtain one byte from UART
LOAD s3, s0
CALL read_upper_case
LOAD s2, s0
CALL ASCII_byte_to_hex
RETURN
;
;**************************************************************************************
; Text messages
;**************************************************************************************
;
;
; Send Carriage Return to the UART
;
send_CR: LOAD UART_data, character_CR
CALL send_to_UART
RETURN
;
; Send a space to the UART
;
send_space: LOAD UART_data, character_space
CALL send_to_UART
RETURN
;
;
; Send a minus sign to the UART
;
send_minus: LOAD UART_data, character_minus
CALL send_to_UART
RETURN
;
;
; Send the letter 't' to the UART
;
send_t: LOAD UART_data, character_t
CALL send_to_UART
RETURN
;
; Send the letter 'e' to the UART
;
send_e: LOAD UART_data, character_e
CALL send_to_UART
RETURN
;
; Send the letter 'a' to the UART
;
send_a: LOAD UART_data, character_a
CALL send_to_UART
RETURN
;
;
; Send the letter 'd' to the UART
;
send_d: LOAD UART_data, character_d
CALL send_to_UART
RETURN
;
;
; Send the letter 'r' to the UART
;
send_r: LOAD UART_data, character_r
CALL send_to_UART
RETURN
;
;
; Send the letter 's' to the UART
;
send_s: LOAD UART_data, character_s
CALL send_to_UART
RETURN
;
;
; Send the letter 'c' to the UART
;
send_c: LOAD UART_data, character_c
CALL send_to_UART
RETURN
;
;
; Send 'PicoBlaze SHA-1 Algorithm v1.00' string to the UART
;
send_welcome: CALL send_CR
CALL send_CR
LOAD UART_data, character_P
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
CALL send_c
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_B
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
CALL send_a
LOAD UART_data, character_z
CALL send_to_UART
CALL send_e
CALL send_space
LOAD UART_data, character_S
CALL send_to_UART
LOAD UART_data, character_H
CALL send_to_UART
LOAD UART_data, character_A
CALL send_to_UART
CALL send_minus
LOAD UART_data, character_1
CALL send_to_UART
CALL send_space
LOAD UART_data, character_A
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
LOAD UART_data, character_g
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
CALL send_r
LOAD UART_data, character_i
CALL send_to_UART
CALL send_t
LOAD UART_data, character_h
CALL send_to_UART
LOAD UART_data, character_m
CALL send_to_UART
CALL send_space
LOAD UART_data, character_v
CALL send_to_UART
LOAD UART_data, character_1
CALL send_to_UART
LOAD UART_data, character_fullstop
CALL send_to_UART
LOAD UART_data, character_0
CALL send_to_UART
LOAD UART_data, character_0
CALL send_to_UART
CALL send_CR
CALL send_CR
RETURN
;
;
;
;
;
;
; Send DS2432 menu to the UART
;
send_DS2432_menu: CALL send_CR
CALL send_CR
LOAD UART_data, character_1
CALL send_to_UART
CALL send_minus
CALL send_Write
CALL send_space
CALL send_scratchpad
CALL send_CR
LOAD UART_data, character_2
CALL send_to_UART
CALL send_minus
CALL send_Read
CALL send_space
CALL send_scratchpad
CALL send_CR
LOAD UART_data, character_3
CALL send_to_UART
CALL send_minus
LOAD UART_data, character_L
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
CALL send_a
CALL send_d
CALL send_space
LOAD UART_data, character_f
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
CALL send_r
CALL send_s
CALL send_t
CALL send_space
CALL send_secret
CALL send_CR
LOAD UART_data, character_4
CALL send_to_UART
CALL send_minus
CALL send_Read
CALL send_space
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_u
CALL send_to_UART
CALL send_t
LOAD UART_data, character_h
CALL send_to_UART
CALL send_space
LOAD UART_data, character_P
CALL send_to_UART
CALL send_a
LOAD UART_data, character_g
CALL send_to_UART
CALL send_e
CALL send_CR
RETURN
;
;
;
; Send carriage return, 'OK' and carriage return to the UART
;
send_OK: CALL send_CR
LOAD UART_data, character_O
CALL send_to_UART
LOAD UART_data, character_K
CALL send_to_UART
CALL send_CR
RETURN
;
;
; Send 'scratchpad' to the UART
;
send_scratchpad: CALL send_s
CALL send_c
CALL send_r
CALL send_a
CALL send_t
CALL send_c
LOAD UART_data, character_h
CALL send_to_UART
LOAD UART_data, character_p
CALL send_to_UART
CALL send_a
CALL send_d
RETURN
;
;
; Send 'secret' to the UART
;
send_secret: CALL send_s
CALL send_e
CALL send_c
CALL send_r
CALL send_e
CALL send_t
RETURN
;
;
; Send 'Byte' to the UART
;
send_Byte: LOAD UART_data, character_B
CALL send_to_UART
LOAD UART_data, character_y
CALL send_to_UART
CALL send_t
CALL send_e
RETURN
;
;
; Send 'Read' to the UART
;
send_Read: LOAD UART_data, character_R
CALL send_to_UART
CALL send_e
CALL send_a
CALL send_d
RETURN
;
;
; Send 'Write' to the UART
;
send_Write: LOAD UART_data, character_W
CALL send_to_UART
CALL send_r
LOAD UART_data, character_i
CALL send_to_UART
CALL send_t
CALL send_e
RETURN
;
;
; Send 'Pass' to the UART
;
send_Pass: LOAD UART_data, character_P
CALL send_to_UART
CALL send_a
CALL send_s
CALL send_s
CALL send_CR
RETURN
;
;
; Send 'Fail' to the UART
;
send_Fail: LOAD UART_data, character_F
CALL send_to_UART
CALL send_a
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
CALL send_CR
RETURN
;
;
; Send 'address=' to the UART
;
send_address: CALL send_CR
CALL send_a
CALL send_d
CALL send_d
CALL send_r
CALL send_e
CALL send_s
CALL send_s
send_equals: LOAD UART_data, character_equals
CALL send_to_UART
RETURN
;
;
; Send 'data' to the UART
;
send_data: CALL send_CR
CALL send_d
CALL send_a
CALL send_t
CALL send_a
RETURN
;
;
; Send 'E/S=' to the UART
;
send_ES: CALL send_CR
LOAD UART_data, character_E
CALL send_to_UART
LOAD UART_data, character_divide
CALL send_to_UART
LOAD UART_data, character_S
CALL send_to_UART
JUMP send_equals
;
;
; Send 'code=' to the UART
;
send_code: CALL send_c
LOAD UART_data, character_o
CALL send_to_UART
CALL send_d
CALL send_e
JUMP send_equals
;
;
; Send 's/n=' to the UART
;
send_sn: CALL send_s
LOAD UART_data, character_divide
CALL send_to_UART
LOAD UART_data, character_n
CALL send_to_UART
JUMP send_equals
;
;
; Send 'crc=' to the UART
;
send_crc: CALL send_c
LOAD UART_data, character_r
CALL send_to_UART
CALL send_c
JUMP send_equals
;
;
;
; Send 'mac=' to the UART
;
send_mac: LOAD UART_data, character_m
CALL send_to_UART
CALL send_a
CALL send_c
JUMP send_equals
;
;
;**************************************************************************************
; Interrupt Service Routine (ISR)
;**************************************************************************************
;
; Interrupts are not used in this design. This is a place keeper only.
;
ADDRESS 3FE
ISR: RETURNI ENABLE
;
;
;**************************************************************************************
; Interrupt Vector
;**************************************************************************************
;
ADDRESS 3FF
JUMP ISR
;
;