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

2017 lines
83 KiB
Plaintext

/* Symbol Table */
// ASCII_byte_to_hex = LABEL: 516
// ASCII_letter = LABEL: 539
// ASCII_to_hex = LABEL: 529
// ID_command = LABEL: 34
// ISR = LABEL: 1013
// ISR_preserve_s0 = CONSTANT: 0
// MCS_address = LABEL: 185
// MCS_address_boundary = LABEL: 161
// SPI_FLASH_ID_fail = LABEL: 267
// SPI_FLASH_ID_result = LABEL: 268
// SPI_FLASH_tx_rx = LABEL: 274
// SPI_adc_conv = CONSTANT: 16
// SPI_amp_cs = CONSTANT: 8
// SPI_amp_sdi = CONSTANT: 64
// SPI_amp_shdn = CONSTANT: 64
// SPI_control_port = CONSTANT: 8
// SPI_control_status = CONSTANT: 4
// SPI_dac_clr = CONSTANT: 128
// SPI_dac_cs = CONSTANT: 32
// SPI_init = LABEL: 270
// SPI_input_port = CONSTANT: 2
// SPI_output_port = CONSTANT: 4
// SPI_rom_cs = CONSTANT: 2
// SPI_sck = CONSTANT: 1
// SPI_sdi = CONSTANT: 128
// SPI_sdo = CONSTANT: 128
// SPI_spare_control = CONSTANT: 4
// UART_data = REGISTER: 15
// UART_read_port = CONSTANT: 1
// UART_write = LABEL: 453
// UART_write_port = CONSTANT: 16
// abort_erase = LABEL: 62
// addr_out_of_sequence = LABEL: 134
// bulk_erase_spi = LABEL: 371
// bulk_erase_wait = LABEL: 381
// byte_programmed = LABEL: 154
// character_0 = CONSTANT: 48
// character_1 = CONSTANT: 49
// character_2 = CONSTANT: 50
// character_3 = CONSTANT: 51
// character_4 = CONSTANT: 52
// character_5 = CONSTANT: 53
// character_6 = CONSTANT: 54
// character_7 = CONSTANT: 55
// character_8 = CONSTANT: 56
// character_9 = CONSTANT: 57
// character_A = CONSTANT: 65
// character_B = CONSTANT: 66
// character_BS = CONSTANT: 8
// character_C = CONSTANT: 67
// character_CR = CONSTANT: 13
// character_D = CONSTANT: 68
// character_E = CONSTANT: 69
// character_F = CONSTANT: 70
// character_G = CONSTANT: 71
// character_H = CONSTANT: 72
// character_I = CONSTANT: 73
// character_J = CONSTANT: 74
// character_K = CONSTANT: 75
// character_L = CONSTANT: 76
// character_LF = CONSTANT: 10
// character_M = CONSTANT: 77
// character_N = CONSTANT: 78
// character_O = CONSTANT: 79
// character_P = CONSTANT: 80
// character_Q = CONSTANT: 81
// character_R = CONSTANT: 82
// character_S = CONSTANT: 83
// character_T = CONSTANT: 84
// character_U = CONSTANT: 85
// character_V = CONSTANT: 86
// character_W = CONSTANT: 87
// character_X = CONSTANT: 88
// character_XOFF = CONSTANT: 19
// character_XON = CONSTANT: 17
// character_Y = CONSTANT: 89
// character_Z = CONSTANT: 90
// character_a = CONSTANT: 97
// character_b = CONSTANT: 98
// character_c = CONSTANT: 99
// character_close = CONSTANT: 41
// character_colon = CONSTANT: 58
// character_comma = CONSTANT: 44
// character_d = CONSTANT: 100
// character_divide = CONSTANT: 47
// character_dollar = CONSTANT: 36
// character_e = CONSTANT: 101
// character_equals = CONSTANT: 61
// character_exclaim = CONSTANT: 33
// character_f = CONSTANT: 102
// character_fullstop = CONSTANT: 46
// character_g = CONSTANT: 103
// character_greater_than = CONSTANT: 62
// character_h = CONSTANT: 104
// character_i = CONSTANT: 105
// character_j = CONSTANT: 106
// character_k = CONSTANT: 107
// character_l = CONSTANT: 108
// character_less_than = CONSTANT: 60
// character_m = CONSTANT: 109
// character_minus = CONSTANT: 45
// character_n = CONSTANT: 110
// character_o = CONSTANT: 111
// character_open = CONSTANT: 40
// character_p = CONSTANT: 112
// character_plus = CONSTANT: 43
// character_q = CONSTANT: 113
// character_question = CONSTANT: 63
// character_r = CONSTANT: 114
// character_s = CONSTANT: 115
// character_semi_colon = CONSTANT: 59
// character_space = CONSTANT: 32
// character_t = CONSTANT: 116
// character_u = CONSTANT: 117
// character_v = CONSTANT: 118
// character_w = CONSTANT: 119
// character_x = CONSTANT: 120
// character_y = CONSTANT: 121
// character_z = CONSTANT: 122
// close_prog_page_spi = LABEL: 399
// cold_start = LABEL: 0
// decimal_to_ASCII = LABEL: 455
// delay_1ms = LABEL: 416
// delay_1s = LABEL: 426
// delay_1us = LABEL: 407
// delay_1us_constant = CONSTANT: 11
// delay_20ms = LABEL: 421
// delay_40us = LABEL: 411
// end_program_MCS = LABEL: 165
// erase_command = LABEL: 51
// erase_spi_sector = LABEL: 351
// erase_test_sector = LABEL: 241
// hex_byte_to_ASCII = LABEL: 486
// hex_to_ASCII = LABEL: 498
// isr_send_character = LABEL: 1020
// isr_send_xon = LABEL: 1019
// line_start = CONSTANT: 43
// memory_blank_fail = LABEL: 255
// memory_blank_result = LABEL: 256
// memory_comms_test = LABEL: 258
// memory_test = LABEL: 219
// memory_verify_fail = LABEL: 238
// memory_verify_result = LABEL: 239
// new_low_address = LABEL: 196
// next_SPI_FLASH_bit = LABEL: 276
// next_prog_line = LABEL: 112
// number_char = LABEL: 501
// obtain_8bits = LABEL: 105
// onechar_to_value = LABEL: 468
// open_prog_page_spi = LABEL: 385
// page_address_h = CONSTANT: 1
// page_address_l = CONSTANT: 3
// page_address_m = CONSTANT: 2
// page_is_open = LABEL: 140
// page_prog_wait = LABEL: 403
// pattern_loop = LABEL: 223
// program_MCS = LABEL: 111
// program_byte = LABEL: 136
// program_command = LABEL: 84
// prompt = LABEL: 6
// read_MCS_byte = LABEL: 173
// read_MCS_line = LABEL: 169
// read_XON = LABEL: 445
// read_character = LABEL: 436
// read_command = LABEL: 89
// read_from_UART = LABEL: 431
// read_spi_byte = LABEL: 334
// read_spi_flash_ID = LABEL: 318
// read_spi_flash_status = LABEL: 287
// read_upper_case = LABEL: 29
// reset_spi_flash_WREN = LABEL: 308
// rx_data_present = CONSTANT: 8
// rx_full = CONSTANT: 32
// rx_half_full = CONSTANT: 16
// s0 = REGISTER: 0
// s1 = REGISTER: 1
// s2 = REGISTER: 2
// s3 = REGISTER: 3
// s4 = REGISTER: 4
// s5 = REGISTER: 5
// s6 = REGISTER: 6
// s7 = REGISTER: 7
// s8 = REGISTER: 8
// s9 = REGISTER: 9
// sA = REGISTER: 10
// sB = REGISTER: 11
// sC = REGISTER: 12
// sD = REGISTER: 13
// sE = REGISTER: 14
// sF = REGISTER: 15
// sector_erase_command = LABEL: 64
// sector_erase_wait = LABEL: 367
// send_Abort = LABEL: 842
// send_CR = LABEL: 541
// send_Confirm = LABEL: 813
// send_Erase = LABEL: 682
// send_Erase_in_progress = LABEL: 659
// send_ID = LABEL: 808
// send_MCS_file = LABEL: 641
// send_Menu = LABEL: 701
// send_OK = LABEL: 694
// send_Waiting_MCS_file = LABEL: 620
// send_hex_3bytes = LABEL: 509
// send_hex_byte = LABEL: 503
// send_page = LABEL: 799
// send_page_address = LABEL: 855
// send_space = LABEL: 544
// send_spi_byte = LABEL: 206
// send_spi_line = LABEL: 202
// send_spi_page = LABEL: 201
// send_to_UART = LABEL: 449
// send_welcome = LABEL: 547
// set_spi_flash_WREN = LABEL: 298
// status_port = CONSTANT: 0
// swap_bits = LABEL: 142
// test_for_ten = LABEL: 456
// twochar_to_value = LABEL: 472
// tx_data_present = CONSTANT: 1
// tx_full = CONSTANT: 4
// tx_half_full = CONSTANT: 2
// upper_case = LABEL: 462
// verify_blank_page = LABEL: 249
// verify_test_page = LABEL: 232
// wait_1ms = LABEL: 417
// wait_1s = LABEL: 427
// wait_1us = LABEL: 408
// wait_20ms = LABEL: 422
// wait_40us = LABEL: 412
// wait_MCS_line_Start = LABEL: 170
// wait_Rx_character = LABEL: 432
// wait_XON = LABEL: 441
// warm_start = LABEL: 5
// welcome_start = LABEL: 3
/* Program Code */
// #1: ;KCPSM3 Program - UART programming of SPI Flash memory on Spartan-3E Starter Kit.
// #2: ;
// #3: ;
// #4: ;Ken Chapman - Xilinx Ltd
// #5: ;
// #6: ;Version v1.00 - 11th November 2005
// #7: ;
// #8: ;This program uses a 115200 baud UART connection with XON/XOFF flow control
// #9: ;to allow a standard MCS file for the configuration of a Spartan-3E device to
// #10: ;be programmed into the ST Microelectronics M25P16 device on the board.
// #11: ;
// #12: ;
// #13: ;
// #14: ;As well as the port connections vital to communication with the UART and the SPI
// #15: ;FLASH memory, there are additional port connections used to disable the other
// #16: ;devices sharing the SPI bus on the Starter Kit board. Although these could have been
// #17: ;controlled at the hardware level, they are included in this code to aid
// #18: ;future investigations of communication with the other SPI devices using PicoBlaze.
// #19: ;
// #20: ;
// #21: ;
// #22: ;
// #23: ;Port definitions
// #24: ;
// #25: CONSTANT(status_port,0) ;UART and filter status input
// #26: CONSTANT(tx_data_present,1) ; Transmitter data present - bit0
// #27: CONSTANT(tx_half_full,2) ; FIFO half full - bit1
// #28: CONSTANT(tx_full,4) ; full - bit2
// #29: CONSTANT(rx_data_present,8) ; data present - bit3
// #30: CONSTANT(rx_half_full,16) ; Receiver half full - bit4
// #31: CONSTANT(rx_full,32) ; FIFO full - bit5
// #32: ;
// #33: CONSTANT(UART_read_port,1) ;UART Rx data input
// #34: ;
// #35: CONSTANT(UART_write_port,16) ;UART Tx data output
// #36: ;
// #37: ;
// #38: CONSTANT(SPI_control_port,8) ;SPI clock and chip selects
// #39: CONSTANT(SPI_sck,1) ; SCK - bit0
// #40: CONSTANT(SPI_rom_cs,2) ; serial rom select - bit1
// #41: CONSTANT(SPI_spare_control,4) ; spare - bit2
// #42: CONSTANT(SPI_amp_cs,8) ; amplifier select - bit3
// #43: CONSTANT(SPI_adc_conv,16) ; A/D convert - bit4
// #44: CONSTANT(SPI_dac_cs,32) ; D/A select - bit5
// #45: CONSTANT(SPI_amp_shdn,64) ; amplifier SHDN - bit6
// #46: CONSTANT(SPI_dac_clr,128) ; D/A clear - bit7
// #47: ;
// #48: CONSTANT(SPI_output_port,4) ;SPI data output
// #49: CONSTANT(SPI_sdo,128) ; SDO - bit7
// #50: ;
// #51: CONSTANT(SPI_input_port,2) ;SPI data input
// #52: CONSTANT(SPI_sdi,128) ; SDI - bit7
// #53: CONSTANT(SPI_amp_sdi,64) ; amplifier SDI - bit6
// #54: ;
// #55: ;
// #56: ;
// #57: ;
// #58: ;Special Register usage
// #59: ;
// #60: NAMEREG(sF,UART_data) ;used to pass data to and from the UART
// #61: ;
// #62: ;
// #63: ;Useful data constants
// #64: ;
// #65: ;
// #66: ;Constant to define a software delay of 1us. This must be adjusted to reflect the
// #67: ;clock applied to KCPSM3. Every instruction executes in 2 clock cycles making the
// #68: ;calculation highly predictable. The '6' in the following equation even allows for
// #69: ;'CALL delay_1us' instruction in the initiating code.
// #70: ;
// #71: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
// #72: ;
// #73: ;Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex).
// #74: ;For clock rates below 10MHz the value of 1 must be used and the operation will
// #75: ;become lower than intended.
// #76: ;
// #77: CONSTANT(delay_1us_constant,11)
// #78: ;
// #79: ;
// #80: ;Useful constants
// #81: ;
// #82: ;
// #83: ;ASCII table
// #84: ;
// #85: CONSTANT(character_a,97)
// #86: CONSTANT(character_b,98)
// #87: CONSTANT(character_c,99)
// #88: CONSTANT(character_d,100)
// #89: CONSTANT(character_e,101)
// #90: CONSTANT(character_f,102)
// #91: CONSTANT(character_g,103)
// #92: CONSTANT(character_h,104)
// #93: CONSTANT(character_i,105)
// #94: CONSTANT(character_j,106)
// #95: CONSTANT(character_k,107)
// #96: CONSTANT(character_l,108)
// #97: CONSTANT(character_m,109)
// #98: CONSTANT(character_n,110)
// #99: CONSTANT(character_o,111)
// #100: CONSTANT(character_p,112)
// #101: CONSTANT(character_q,113)
// #102: CONSTANT(character_r,114)
// #103: CONSTANT(character_s,115)
// #104: CONSTANT(character_t,116)
// #105: CONSTANT(character_u,117)
// #106: CONSTANT(character_v,118)
// #107: CONSTANT(character_w,119)
// #108: CONSTANT(character_x,120)
// #109: CONSTANT(character_y,121)
// #110: CONSTANT(character_z,122)
// #111: CONSTANT(character_A,65)
// #112: CONSTANT(character_B,66)
// #113: CONSTANT(character_C,67)
// #114: CONSTANT(character_D,68)
// #115: CONSTANT(character_E,69)
// #116: CONSTANT(character_F,70)
// #117: CONSTANT(character_G,71)
// #118: CONSTANT(character_H,72)
// #119: CONSTANT(character_I,73)
// #120: CONSTANT(character_J,74)
// #121: CONSTANT(character_K,75)
// #122: CONSTANT(character_L,76)
// #123: CONSTANT(character_M,77)
// #124: CONSTANT(character_N,78)
// #125: CONSTANT(character_O,79)
// #126: CONSTANT(character_P,80)
// #127: CONSTANT(character_Q,81)
// #128: CONSTANT(character_R,82)
// #129: CONSTANT(character_S,83)
// #130: CONSTANT(character_T,84)
// #131: CONSTANT(character_U,85)
// #132: CONSTANT(character_V,86)
// #133: CONSTANT(character_W,87)
// #134: CONSTANT(character_X,88)
// #135: CONSTANT(character_Y,89)
// #136: CONSTANT(character_Z,90)
// #137: CONSTANT(character_0,48)
// #138: CONSTANT(character_1,49)
// #139: CONSTANT(character_2,50)
// #140: CONSTANT(character_3,51)
// #141: CONSTANT(character_4,52)
// #142: CONSTANT(character_5,53)
// #143: CONSTANT(character_6,54)
// #144: CONSTANT(character_7,55)
// #145: CONSTANT(character_8,56)
// #146: CONSTANT(character_9,57)
// #147: CONSTANT(character_colon,58)
// #148: CONSTANT(character_fullstop,46)
// #149: CONSTANT(character_semi_colon,59)
// #150: CONSTANT(character_minus,45)
// #151: CONSTANT(character_plus,43)
// #152: CONSTANT(character_comma,44)
// #153: CONSTANT(character_less_than,60) ;'<'
// #154: CONSTANT(character_greater_than,62) ;'>'
// #155: CONSTANT(character_open,40) ;'('
// #156: CONSTANT(character_close,41) ;')'
// #157: CONSTANT(character_divide,47) ;'/'
// #158: CONSTANT(character_equals,61)
// #159: CONSTANT(character_space,32)
// #160: CONSTANT(character_CR,13) ;carriage return
// #161: CONSTANT(character_LF,10) ;line feed
// #162: CONSTANT(character_question,63) ;'?'
// #163: CONSTANT(character_dollar,36)
// #164: CONSTANT(character_exclaim,33) ;'!'
// #165: CONSTANT(character_BS,8) ;Back Space command character
// #166: CONSTANT(character_XON,17) ;Flow control ON
// #167: CONSTANT(character_XOFF,19) ;Flow control OFF
// #168: ;
// #169: ;
// #170: ;Scratch Pad Memory Locations
// #171: ;
// #172: ;
// #173: CONSTANT(ISR_preserve_s0,0) ;preserve register during ISR
// #174: ;
// #175: CONSTANT(page_address_h,1) ;Remember page address for SPI boundary checking.
// #176: CONSTANT(page_address_m,2) ;high, middle and low bytes
// #177: CONSTANT(page_address_l,3)
// #178: ;
// #179: CONSTANT(SPI_control_status,4) ;SPI status signals
// #180: ;
// #181: ;
// #182: ;
// #183: ;Store up to one line of an MCS file as bytes
// #184: ;A typical data line consists of:-
// #185: ;: Start character which is not stored
// #186: ;10 Number of data bytes included (16 in this case)
// #187: ;aaaa Lower 16-bits of the storage address
// #188: ;00 Record type (data in this case)
// #189: ;dddd... Data bytes (typically 16 which is the maximum)
// #190: ;cc Checksum
// #191: ;CR/LF Line will end in carriage return and/or line feed which is not stored.
// #192: ;
// #193: ;So a total of 21 could be stored before processing.
// #194: ;
// #195: CONSTANT(line_start,43) ;21 bytes until end of memory
// #196: ;
// #197: ;
// #198: ;Initialise the system and welcome message
// #199: ;
// #200: ;
// @000 #201: [cold_start]
3010e // @000 #201: CALL(SPI_init) ;initialise SPI bus ports
301aa // @001 #202: CALL(delay_1s) ;delay because UART is fast and JTAG startup sequence can be slow
3c001 // @002 #203: ENABLE(INTERRUPT) ;Interrupt is used for XON/XOFF flow control
// @003 #204: [welcome_start]
3021d // @003 #204: CALL(send_CR)
30223 // @004 #205: CALL(send_welcome) ;start up message and version number
// #206: ;
// #207: ;Main menu and command selection
// #208: ;
// #209: ;
// #210: ;
// @005 #211: [warm_start]
302bd // @005 #211: CALL(send_Menu) ;Menu and command selection
// @006 #212: [prompt]
3021d // @006 #212: CALL(send_CR)
3021d // @007 #213: CALL(send_CR)
00f3e // @008 #214: LOAD(UART_data,character_greater_than) ;prompt for input
301c1 // @009 #215: CALL(send_to_UART)
3001d // @00a #216: CALL(read_upper_case)
14045 // @00b #217: COMPARE(s0,character_E) ;command test
35033 // @00c #218: JUMP(Z,erase_command)
14053 // @00d #219: COMPARE(s0,character_S) ;command test
35040 // @00e #220: JUMP(Z,sector_erase_command)
14050 // @00f #221: COMPARE(s0,character_P) ;command test
35054 // @010 #222: JUMP(Z,program_command)
14052 // @011 #223: COMPARE(s0,character_R) ;command test
35059 // @012 #224: JUMP(Z,read_command)
14049 // @013 #225: COMPARE(s0,character_I) ;command test
35022 // @014 #226: JUMP(Z,ID_command)
14048 // @015 #227: COMPARE(s0,character_H) ;command test
35003 // @016 #228: JUMP(Z,welcome_start)
3021d // @017 #229: CALL(send_CR) ;no valid command input
00f3f // @018 #230: LOAD(UART_data,character_question) ;display ???
301c1 // @019 #231: CALL(send_to_UART)
301c1 // @01a #232: CALL(send_to_UART)
301c1 // @01b #233: CALL(send_to_UART)
34006 // @01c #234: JUMP(prompt) ;Try again!
// #235: ;
// #236: ;
// @01d #237: [read_upper_case]
301af // @01d #237: CALL(read_from_UART) ;read command character from UART
301c1 // @01e #238: CALL(send_to_UART) ;echo character
010f0 // @01f #239: LOAD(s0,UART_data) ;convert to upper case
301ce // @020 #240: CALL(upper_case)
2a000 // @021 #241: RETURN
// #242: ;
// #243: ;**************************************************************************************
// #244: ;ID Command - Read and display the ID for the SPI FLASH memory
// #245: ;**************************************************************************************
// #246: ;
// #247: ;Normal response should be
// #248: ; s9 = Manufacturer Identification = 20 hex
// #249: ; s8 = Memory Type = 20 hex
// #250: ; s7 = Memory Capacity = 15 hex
// #251: ;
// @022 #252: [ID_command]
3021d // @022 #252: CALL(send_CR)
3013e // @023 #253: CALL(read_spi_flash_ID)
30328 // @024 #254: CALL(send_ID)
00f3d // @025 #255: LOAD(UART_data,character_equals)
301c1 // @026 #256: CALL(send_to_UART)
30220 // @027 #257: CALL(send_space)
01090 // @028 #258: LOAD(s0,s9)
301f7 // @029 #259: CALL(send_hex_byte)
30220 // @02a #260: CALL(send_space)
01080 // @02b #261: LOAD(s0,s8)
301f7 // @02c #262: CALL(send_hex_byte)
30220 // @02d #263: CALL(send_space)
01070 // @02e #264: LOAD(s0,s7)
301f7 // @02f #265: CALL(send_hex_byte)
30220 // @030 #266: CALL(send_space)
3021d // @031 #267: CALL(send_CR)
34006 // @032 #268: JUMP(prompt)
// #269: ;
// #270: ;**************************************************************************************
// #271: ;Erase Command - Perform bulk erase of the SPI FLASH memory and display messages
// #272: ;**************************************************************************************
// #273: ;
// @033 #274: [erase_command]
3021d // @033 #274: CALL(send_CR)
3032d // @034 #275: CALL(send_Confirm) ;confirm command with a 'Y' which must be upper case
301af // @035 #276: CALL(read_from_UART) ;read command character from UART
301c1 // @036 #277: CALL(send_to_UART) ;echo input
14f59 // @037 #278: COMPARE(UART_data,character_Y)
3543e // @038 #279: JUMP(NZ,abort_erase)
3021d // @039 #280: CALL(send_CR)
30293 // @03a #281: CALL(send_Erase_in_progress)
30173 // @03b #282: CALL(bulk_erase_spi)
302b6 // @03c #283: CALL(send_OK)
34006 // @03d #284: JUMP(prompt)
// #285: ;
// @03e #286: [abort_erase]
3034a // @03e #286: CALL(send_Abort)
34006 // @03f #287: JUMP(prompt)
// #288: ;
// #289: ;
// #290: ;**************************************************************************************
// #291: ;Sector Erase Command - Performs erase of lowest 5 sectors SPI FLASH memory which
// #292: ;covers the address range 000000 to 04FFFF in which the configuration for an XC3S500E
// #293: ;would be able to fit.
// #294: ;**************************************************************************************
// #295: ;
// @040 #296: [sector_erase_command]
3021d // @040 #296: CALL(send_CR)
3032d // @041 #297: CALL(send_Confirm) ;confirm command with a 'Y' which must be upper case
301af // @042 #298: CALL(read_from_UART) ;read command character from UART
301c1 // @043 #299: CALL(send_to_UART) ;echo input
14f59 // @044 #300: COMPARE(UART_data,character_Y)
3543e // @045 #301: JUMP(NZ,abort_erase)
3021d // @046 #302: CALL(send_CR)
30293 // @047 #303: CALL(send_Erase_in_progress)
00900 // @048 #304: LOAD(s9,0) ;any address inside sector 0
3015f // @049 #305: CALL(erase_spi_sector)
00901 // @04a #306: LOAD(s9,1) ;any address inside sector 1
3015f // @04b #307: CALL(erase_spi_sector)
00902 // @04c #308: LOAD(s9,2) ;any address inside sector 2
3015f // @04d #309: CALL(erase_spi_sector)
00903 // @04e #310: LOAD(s9,3) ;any address inside sector 3
3015f // @04f #311: CALL(erase_spi_sector)
00904 // @050 #312: LOAD(s9,4) ;any address inside sector 4
3015f // @051 #313: CALL(erase_spi_sector)
302b6 // @052 #314: CALL(send_OK)
34006 // @053 #315: JUMP(prompt)
// #316: ;
// #317: ;
// #318: ;**************************************************************************************
// #319: ;Program Command - Program SPI FLASH memory with MCS file
// #320: ;**************************************************************************************
// #321: ;
// @054 #322: [program_command]
3021d // @054 #322: CALL(send_CR)
3026c // @055 #323: CALL(send_Waiting_MCS_file)
3006f // @056 #324: CALL(program_MCS)
302b6 // @057 #325: CALL(send_OK)
34006 // @058 #326: JUMP(prompt)
// #327: ;
// #328: ;
// #329: ;**************************************************************************************
// #330: ;Read Command - Read one page of memory at specified address
// #331: ;**************************************************************************************
// #332: ;
// @059 #333: [read_command]
30357 // @059 #333: CALL(send_page_address) ;obtain 24-bit address
30069 // @05a #334: CALL(obtain_8bits)
35859 // @05b #335: JUMP(C,read_command) ;bad input address
14020 // @05c #336: COMPARE(s0,32) ;test for address greater than 1FFFFF
35c59 // @05d #337: JUMP(NC,read_command) ;value too big
01900 // @05e #338: LOAD(s9,s0)
30069 // @05f #339: CALL(obtain_8bits)
35859 // @060 #340: JUMP(C,read_command) ;bad input address
01800 // @061 #341: LOAD(s8,s0)
30069 // @062 #342: CALL(obtain_8bits)
35859 // @063 #343: JUMP(C,read_command) ;bad input address
01700 // @064 #344: LOAD(s7,s0)
3021d // @065 #345: CALL(send_CR)
300c9 // @066 #346: CALL(send_spi_page)
302b6 // @067 #347: CALL(send_OK)
34006 // @068 #348: JUMP(prompt)
// @069 #349: [obtain_8bits]
3001d // @069 #349: CALL(read_upper_case) ;obtain one byte from UART
01300 // @06a #350: LOAD(s3,s0)
3001d // @06b #351: CALL(read_upper_case)
01200 // @06c #352: LOAD(s2,s0)
30204 // @06d #353: CALL(ASCII_byte_to_hex)
2a000 // @06e #354: RETURN
// #355: ;
// #356: ;
// #357: ;
// #358: ;**************************************************************************************
// #359: ;Program SPI FLASH with MCS file
// #360: ;**************************************************************************************
// #361: ;
// #362: ;Reads the MCS file from the UART and programs the SPI FLASH device at the locations.
// #363: ;specified by the file contents.
// #364: ;
// #365: ;One important factor of programming the SPI FLASH for use as configuration
// #366: ;memory is that the bits within each byte must be in reverse order. This
// #367: ;is because an SPI device outputs data MSB first compared with a Xilinx
// #368: ;serial PROM which outputs LSB first. Therefore this routine will swap
// #369: ;the bits of each byte provided by the MCS file before programming.
// #370: ;
// #371: ;This routine will continue until an end of file record is detected.
// #372: ;For each line of MCS received, the current address will be output so that
// #373: ;progress can be monitored.
// #374: ;
// #375: ;Register sA is used to remember if a page is currently open (01) or closed (00)
// #376: ;for writing on the SPI memory.
// #377: ;
// @06f #378: [program_MCS]
00a00 // @06f #378: LOAD(sA,0) ;page is closed
// @070 #379: [next_prog_line]
300a9 // @070 #379: CALL(read_MCS_line) ;read line
300b9 // @071 #380: CALL(MCS_address) ;find start address and record type
14b01 // @072 #381: COMPARE(sB,1) ;test for end record
350a5 // @073 #382: JUMP(Z,end_program_MCS)
301fd // @074 #383: CALL(send_hex_3bytes) ;send address for other lines
3021d // @075 #384: CALL(send_CR)
14b04 // @076 #385: COMPARE(sB,4) ;test for extended address record
350a1 // @077 #386: JUMP(Z,MCS_address_boundary)
// #387: ;
// #388: ;Assume data record type 00 now and program SPI page
// #389: ;
1ce01 // @078 #390: SUB(sE,1) ;location of checksum just after last stored data byte
00d2b // @079 #391: LOAD(sD,line_start) ;Point to first data byte
18d04 // @07a #392: ADD(sD,4)
14a00 // @07b #393: COMPARE(sA,0) ;check if page is closed
35088 // @07c #394: JUMP(Z,program_byte) ;jump if page needs to be opened
06201 // @07d #395: FETCH(s2,page_address_h) ;check new address is sequential
15290 // @07e #396: COMPARE(s2,s9)
35486 // @07f #397: JUMP(NZ,addr_out_of_sequence)
06202 // @080 #398: FETCH(s2,page_address_m) ;check new address is sequential
15280 // @081 #399: COMPARE(s2,s8)
35486 // @082 #400: JUMP(NZ,addr_out_of_sequence)
06203 // @083 #401: FETCH(s2,page_address_l) ;check new address is sequential
15270 // @084 #402: COMPARE(s2,s7)
35088 // @085 #403: JUMP(Z,program_byte) ;continue with open page
// @086 #404: [addr_out_of_sequence]
3018f // @086 #404: CALL(close_prog_page_spi) ;close page because address out of sequence
00a00 // @087 #405: LOAD(sA,0) ;page is now closed
// @088 #406: [program_byte]
14a00 // @088 #406: COMPARE(sA,0) ;check if page is closed
3548c // @089 #407: JUMP(NZ,page_is_open) ;jump is page already open
30181 // @08a #408: CALL(open_prog_page_spi) ;open page with address [s9,s8,s7]
00a01 // @08b #409: LOAD(sA,1) ;page is open
// @08c #410: [page_is_open]
071d0 // @08c #410: FETCH(s1,sD) ;fetch data byte
00008 // @08d #411: LOAD(s0,8) ;reverse order of bits
// @08e #412: [swap_bits]
2010e // @08e #412: SR0(s1)
20200 // @08f #413: SLA(s2)
1c001 // @090 #414: SUB(s0,1)
3548e // @091 #415: JUMP(NZ,swap_bits) ;swapped bits now in s2
30112 // @092 #416: CALL(SPI_FLASH_tx_rx) ;program byte into SPI memory
18701 // @093 #417: ADD(s7,1) ;increment address to keep track
1a800 // @094 #418: ADDCY(s8,0)
1a900 // @095 #419: ADDCY(s9,0)
14700 // @096 #420: COMPARE(s7,0) ;test if crossing page boundary FF to 00
3549a // @097 #421: JUMP(NZ,byte_programmed)
3018f // @098 #422: CALL(close_prog_page_spi)
00a00 // @099 #423: LOAD(sA,0) ;page is now closed
// @09a #424: [byte_programmed]
18d01 // @09a #424: ADD(sD,1) ;move to next byte
15de0 // @09b #425: COMPARE(sD,sE) ;check for last on line
35488 // @09c #426: JUMP(NZ,program_byte) ;fetch next byte to program
2e901 // @09d #427: STORE(s9,page_address_h) ;remember next address in sequence
2e802 // @09e #428: STORE(s8,page_address_m)
2e703 // @09f #429: STORE(s7,page_address_l)
34070 // @0a0 #430: JUMP(next_prog_line) ;read next line for programming
// @0a1 #431: [MCS_address_boundary]
14a00 // @0a1 #431: COMPARE(sA,0) ;check if page needs to be closed
35070 // @0a2 #432: JUMP(Z,next_prog_line)
3018f // @0a3 #433: CALL(close_prog_page_spi)
3406f // @0a4 #434: JUMP(program_MCS)
// @0a5 #435: [end_program_MCS]
14a00 // @0a5 #435: COMPARE(sA,0) ;check if page needs to be closed
2b000 // @0a6 #436: RETURN(Z)
3018f // @0a7 #437: CALL(close_prog_page_spi)
2a000 // @0a8 #438: RETURN
// #439: ;
// #440: ;**************************************************************************************
// #441: ;Read one line of an MCS file into scratch pad memory
// #442: ;**************************************************************************************
// #443: ;
// #444: ;Reads one line of MCS file format into scratch pad memory starting at location 'line_start'.
// #445: ;
// #446: ;The routine detects the line start character ':' ignoring any preceding characters. This
// #447: ;will remove any additional CR or LF characters.
// #448: ;
// #449: ;It then reads each subsequent pair of ASCII characters, converts them to true hex in the
// #450: ;range 00 to FF and stores them in scratch pad memory.
// #451: ;
// #452: ;The end of the line is determined by either a CR or LF character.
// #453: ;
// #454: ;The value last returned in register 'sE' will be the pointer to the location in
// #455: ;scratch pad memory following the last byte for the line read.
// #456: ;
// @0a9 #457: [read_MCS_line]
00e2b // @0a9 #457: LOAD(sE,line_start) ;initialise SPM memory pointer
// @0aa #458: [wait_MCS_line_Start]
301af // @0aa #458: CALL(read_from_UART) ;read character
14f3a // @0ab #459: COMPARE(UART_data,character_colon) ;test for start character
354aa // @0ac #460: JUMP(NZ,wait_MCS_line_Start)
// @0ad #461: [read_MCS_byte]
301af // @0ad #461: CALL(read_from_UART) ;read character
14f0d // @0ae #462: COMPARE(UART_data,character_CR) ;test for end of line
2b000 // @0af #463: RETURN(Z)
14f0a // @0b0 #464: COMPARE(UART_data,character_LF) ;test for end of line
2b000 // @0b1 #465: RETURN(Z)
013f0 // @0b2 #466: LOAD(s3,UART_data) ;upper nibble character
301af // @0b3 #467: CALL(read_from_UART) ;read character
012f0 // @0b4 #468: LOAD(s2,UART_data) ;lower nibble character
30204 // @0b5 #469: CALL(ASCII_byte_to_hex) ;convert to true hex value
2f0e0 // @0b6 #470: STORE(s0,sE) ;write to SPM
18e01 // @0b7 #471: ADD(sE,1) ;increment pointer
340ad // @0b8 #472: JUMP(read_MCS_byte)
// #473: ;
// #474: ;
// #475: ;**************************************************************************************
// #476: ;Determine the current address for the line of an MCS file in scratch pad memory
// #477: ;**************************************************************************************
// #478: ;
// #479: ;Checks the existing line data stored in scratch pad memory starting at location
// #480: ;'line_start' and determines the current address.
// #481: ;
// #482: ;The address is in the register set [s9,s8,s7] before and after this routine is
// #483: ;executed because not all address bits are defined by a given line of MCS and
// #484: ;the undefined bits remain constant.
// #485: ;
// #486: ;A record type of 04 will update [s9].
// #487: ;A record type of 00 will update [s8,s7].
// #488: ;
// #489: ;On return, the register sB will contain the record type and
// #490: ;register sC will indicate the number of data bytes stored.
// #491: ;
// @0b9 #492: [MCS_address]
00d2b // @0b9 #492: LOAD(sD,line_start) ;initialise SPM memory pointer
07cd0 // @0ba #493: FETCH(sC,sD) ;read number of bytes on line
18d03 // @0bb #494: ADD(sD,3) ;move to record type
07bd0 // @0bc #495: FETCH(sB,sD) ;read record type
14b00 // @0bd #496: COMPARE(sB,0) ;test for data record
350c4 // @0be #497: JUMP(Z,new_low_address)
14b04 // @0bf #498: COMPARE(sB,4) ;test for data record
2b400 // @0c0 #499: RETURN(NZ)
18d02 // @0c1 #500: ADD(sD,2) ;read upper 8-bits
079d0 // @0c2 #501: FETCH(s9,sD)
2a000 // @0c3 #502: RETURN
// @0c4 #503: [new_low_address]
1cd01 // @0c4 #503: SUB(sD,1) ;read lower 8-bits
077d0 // @0c5 #504: FETCH(s7,sD)
1cd01 // @0c6 #505: SUB(sD,1) ;read middle 8-bits
078d0 // @0c7 #506: FETCH(s8,sD)
2a000 // @0c8 #507: RETURN
// #508: ;
// #509: ;**************************************************************************************
// #510: ;Read a page from SPI FLASH memory and display
// #511: ;**************************************************************************************
// #512: ;
// #513: ;The start address should be provided in register set [s9,s8,s7].
// #514: ;The display will be next 256 bytes displayed as 16 lines of 16 bytes
// #515: ;with each line commencing with the address of the first byte.
// #516: ;
// #517: ;
// @0c9 #518: [send_spi_page]
00610 // @0c9 #518: LOAD(s6,16) ;16 lines to display
// @0ca #519: [send_spi_line]
3021d // @0ca #519: CALL(send_CR)
301fd // @0cb #520: CALL(send_hex_3bytes) ;display address
30220 // @0cc #521: CALL(send_space)
00510 // @0cd #522: LOAD(s5,16) ;16 lines to display
// @0ce #523: [send_spi_byte]
30220 // @0ce #523: CALL(send_space)
3014e // @0cf #524: CALL(read_spi_byte) ;read byte into s2
18701 // @0d0 #525: ADD(s7,1) ;increment SPI FLASH address
1a800 // @0d1 #526: ADDCY(s8,0)
1a900 // @0d2 #527: ADDCY(s9,0)
01020 // @0d3 #528: LOAD(s0,s2) ;display byte
301f7 // @0d4 #529: CALL(send_hex_byte)
1c501 // @0d5 #530: SUB(s5,1) ;count bytes per line
354ce // @0d6 #531: JUMP(NZ,send_spi_byte)
1c601 // @0d7 #532: SUB(s6,1) ;count lines
354ca // @0d8 #533: JUMP(NZ,send_spi_line)
3021d // @0d9 #534: CALL(send_CR)
2a000 // @0da #535: RETURN
// #536: ;
// #537: ;**************************************************************************************
// #538: ;Test of SPI FLASH memory operations
// #539: ;**************************************************************************************
// #540: ;
// #541: ;Sector 18 (120000 to 12FFFF) is used.
// #542: ;A page (123400 to 1234FF) is programmed with a test pattern 00 to FF.
// #543: ;The pattern is verified and then the sector erased and a blank check performed.
// #544: ;
// #545: ;Note that the page used is already blank (all locations contain FF hex)
// #546: ;as with any device supplied (initial delivery state).
// #547: ;
// #548: ;Program page with test pattern
// #549: ;
// @0db #550: [memory_test]
00912 // @0db #550: LOAD(s9,18) ;select page address 123400
00834 // @0dc #551: LOAD(s8,52)
00700 // @0dd #552: LOAD(s7,0)
30181 // @0de #553: CALL(open_prog_page_spi) ; program test pattern 00 to FF
// @0df #554: [pattern_loop]
01270 // @0df #554: LOAD(s2,s7)
30112 // @0e0 #555: CALL(SPI_FLASH_tx_rx)
18701 // @0e1 #556: ADD(s7,1)
35cdf // @0e2 #557: JUMP(NC,pattern_loop)
3018f // @0e3 #558: CALL(close_prog_page_spi) ; program test pattern 00 to FF
// #559: ;
// #560: ;Verify test pattern by reading back page
// #561: ;
00f70 // @0e4 #562: LOAD(UART_data,character_p) ;p for pass
00912 // @0e5 #563: LOAD(s9,18) ;select page address 123400
00834 // @0e6 #564: LOAD(s8,52)
00700 // @0e7 #565: LOAD(s7,0)
// @0e8 #566: [verify_test_page]
3014e // @0e8 #566: CALL(read_spi_byte) ;read byte into s2
15270 // @0e9 #567: COMPARE(s2,s7) ;check test pattern data value
354ee // @0ea #568: JUMP(NZ,memory_verify_fail)
18701 // @0eb #569: ADD(s7,1) ;next location
354e8 // @0ec #570: JUMP(NZ,verify_test_page) ;loop until roll over page
340ef // @0ed #571: JUMP(memory_verify_result)
// @0ee #572: [memory_verify_fail]
00f66 // @0ee #572: LOAD(UART_data,character_f) ;f for fail
// @0ef #573: [memory_verify_result]
301c1 // @0ef #573: CALL(send_to_UART)
2a000 // @0f0 #574: RETURN
// #575: ;
// #576: ;Erase sector with test pattern and verify blank
// #577: ;
// @0f1 #578: [erase_test_sector]
00912 // @0f1 #578: LOAD(s9,18) ;sector 18 start address 120000
00800 // @0f2 #579: LOAD(s8,0)
00700 // @0f3 #580: LOAD(s7,0)
3015f // @0f4 #581: CALL(erase_spi_sector)
00f70 // @0f5 #582: LOAD(UART_data,character_p) ;p for pass
00912 // @0f6 #583: LOAD(s9,18) ;select page address 123400
00834 // @0f7 #584: LOAD(s8,52)
00700 // @0f8 #585: LOAD(s7,0)
// @0f9 #586: [verify_blank_page]
3014e // @0f9 #586: CALL(read_spi_byte) ;read byte into s2
142ff // @0fa #587: COMPARE(s2,FF) ;check blank 'FF'
354ff // @0fb #588: JUMP(NZ,memory_blank_fail)
18701 // @0fc #589: ADD(s7,1) ;next location
354f9 // @0fd #590: JUMP(NZ,verify_blank_page) ;loop until roll over page
34100 // @0fe #591: JUMP(memory_blank_result)
// @0ff #592: [memory_blank_fail]
00f66 // @0ff #592: LOAD(UART_data,character_f) ;f for fail
// @100 #593: [memory_blank_result]
301c1 // @100 #593: CALL(send_to_UART)
2a000 // @101 #594: RETURN
// #595: ;
// #596: ;
// #597: ;
// #598: ;**************************************************************************************
// #599: ;Test of SPI FLASH memory communications
// #600: ;**************************************************************************************
// #601: ;Link must be installed in J11 to link ROM-CS to CSO_B
// #602: ;
// #603: ;Read the identification ID from SPI FLASH memory (ST type M25P16)
// #604: ;and compare with expected response.
// #605: ; s9 = Manufacturer Identification = 20 hex
// #606: ; s8 = Memory Type = 20 hex
// #607: ; s7 = Memory Capacity = 15 hex
// #608: ;
// @102 #609: [memory_comms_test]
3013e // @102 #609: CALL(read_spi_flash_ID)
00f70 // @103 #610: LOAD(UART_data,character_p) ;p for pass
14920 // @104 #611: COMPARE(s9,32)
3550b // @105 #612: JUMP(NZ,SPI_FLASH_ID_fail)
14820 // @106 #613: COMPARE(s8,32)
3550b // @107 #614: JUMP(NZ,SPI_FLASH_ID_fail)
14715 // @108 #615: COMPARE(s7,21)
3550b // @109 #616: JUMP(NZ,SPI_FLASH_ID_fail)
3410c // @10a #617: JUMP(SPI_FLASH_ID_result)
// @10b #618: [SPI_FLASH_ID_fail]
00f66 // @10b #618: LOAD(UART_data,character_f) ;f for fail
// @10c #619: [SPI_FLASH_ID_result]
301c1 // @10c #619: CALL(send_to_UART)
2a000 // @10d #620: RETURN
// #621: ;
// #622: ;
// #623: ;
// #624: ;
// #625: ;
// #626: ;
// #627: ;**************************************************************************************
// #628: ;SPI FLASH memory routines
// #629: ;**************************************************************************************
// #630: ;
// #631: ;These routines will work with two output ports and one input port which should be
// #632: ;defined as follows using CONSTANT directives.
// #633: ; (replace 'pp' with appropriate port address in each case)
// #634: ;In the list of CONSTANT directives, only the ones marked with a * are really required
// #635: ;in an SPI FLASH memory system. The other directives are to control (disable) or
// #636: ;communicate with the other SPI components on the same SPI bus of the Spartan-3E Starter Kit.
// #637: ;
// #638: ;
// #639: ;
// #640: ;CONSTANT SPI_control_port, pp ;SPI clock and chip selects *
// #641: ;CONSTANT SPI_sck, 01 ; SCK - bit0 *
// #642: ;CONSTANT SPI_rom_cs, 02 ; serial rom select - bit1 *
// #643: ;CONSTANT SPI_spare_control, 04 ; spare - bit2
// #644: ;CONSTANT SPI_amp_cs, 08 ; amplifier select - bit3
// #645: ;CONSTANT SPI_adc_conv, 10 ; A/D convert - bit4
// #646: ;CONSTANT SPI_dac_cs, 20 ; D/A select - bit5
// #647: ;CONSTANT SPI_amp_shdn, 40 ; amplifier SHDN - bit6
// #648: ;CONSTANT SPI_dac_clr, 80 ; D/A clear - bit7
// #649: ;
// #650: ;CONSTANT SPI_output_port, pp ;SPI data output *
// #651: ;CONSTANT SPI_sdo, 80 ; SDO - bit7 *
// #652: ;
// #653: ;CONSTANT SPI_input_port, pp ;SPI data input *
// #654: ;CONSTANT SPI_sdi, 80 ; SDI - bit7 *
// #655: ;CONSTANT SPI_amp_sdi, 40 ; amplifier SDI - bit6
// #656: ;
// #657: ;
// #658: ;A single scratch pad memory location is also employed to remember the status of
// #659: ;the SPI_control_port. This memory location must be defined as follows.
// #660: ; (replace 'ss' with appropriate memory location)
// #661: ;
// #662: ;CONSTANT SPI_control_status, ss ;SPI status signals
// #663: ;
// #664: ;Not all the SPI routines will use this memory location because although they
// #665: ;will change the bits on the control port, they will leave them in the same state
// #666: ;as they were in when they started.
// #667: ;
// #668: ;
// #669: ;
// #670: ;
// #671: ;Initialise SPI bus
// #672: ;
// #673: ;This routine should be used to initialise the SPI bus.
// #674: ;The SCK clock is made low.
// #675: ;Device selections are made inactive as follows
// #676: ; SPI_sck = 0 Clock is Low (required)
// #677: ; SPI_rom_cs = 1 Deselect ROM
// #678: ; spare = 1 spare control bit
// #679: ; SPI_amp_cs = 1 Deselect amplifier
// #680: ; SPI_adc_conv = 0 A/D convert ready to apply positive pulse
// #681: ; SPI_dac_cs = 1 Deselect D/A
// #682: ; SPI_amp_shdn = 0 Amplifier active and available
// #683: ; SPI_dac_clr = 1 D/A clear off
// #684: ;
// @10e #685: [SPI_init]
000ae // @10e #685: LOAD(s0,AE) ;normally AE
2c008 // @10f #686: OUTPUT(s0,SPI_control_port)
2e004 // @110 #687: STORE(s0,SPI_control_status) ;preserve status
2a000 // @111 #688: RETURN
// #689: ;
// #690: ;
// #691: ;Send and receive one byte to or from the SPI FLASH memory.
// #692: ;
// #693: ;The data supplied in register 's2' is transmitted to the SPI bus and
// #694: ;at the same time any received byte is used to replace the value in 's2'.
// #695: ;The SCK clock is generated by software and results in a communication rate of
// #696: ;2.5Mbit/s with a 50MHz clock.
// #697: ;
// #698: ;Note that you must have previously selected the required device on the bus
// #699: ;before attempting communication and you must subsequently deselect the device
// #700: ;when appropriate.
// #701: ;
// #702: ;Entry to this routine assumes that SCK is already Low and the clock will be Low
// #703: ;at the end of execution (provided in scratch pad memory location SPI_control_status).
// #704: ;
// #705: ;As a 'master' the signal sequence is as follows..
// #706: ; Receive data bit from SDI line (Flash transmits on previous falling edge)
// #707: ; Transmit data bit on SDO line
// #708: ; Drive SCK transition from low to high
// #709: ; Drive SCK transition from high to low.
// #710: ;
// @112 #711: [SPI_FLASH_tx_rx]
00108 // @112 #711: LOAD(s1,8) ;8-bits to transmit and receive
06004 // @113 #712: FETCH(s0,SPI_control_status) ;read control status bits
// @114 #713: [next_SPI_FLASH_bit]
2c204 // @114 #713: OUTPUT(s2,SPI_output_port) ;output data bit ready to be used on rising edge
04302 // @115 #714: INPUT(s3,SPI_input_port) ;read input bit
12380 // @116 #715: TEST(s3,SPI_sdi) ;detect state of received bit
20200 // @117 #716: SLA(s2) ;shift new data into result and move to next transmit bit
0e001 // @118 #717: XOR(s0,SPI_sck) ;clock High (bit0)
2c008 // @119 #718: OUTPUT(s0,SPI_control_port) ;drive clock High
0e001 // @11a #719: XOR(s0,SPI_sck) ;clock Low (bit0)
2c008 // @11b #720: OUTPUT(s0,SPI_control_port) ;drive clock Low
1c101 // @11c #721: SUB(s1,1) ;count bits
35514 // @11d #722: JUMP(NZ,next_SPI_FLASH_bit) ;repeat until finished
2a000 // @11e #723: RETURN
// #724: ;
// #725: ;
// #726: ;Read status register from SPI FLASH memory (ST type M25P16)
// #727: ;
// #728: ;Transmits instruction 05hex and then receives one byte in response
// #729: ;which is returned in register s2.
// #730: ;
// #731: ; bit meaning
// #732: ; 7 SRWD Status Register Write Protect
// #733: ; 6 '0'
// #734: ; 5 '0'
// #735: ; 4 BP2 Block protect bit
// #736: ; 3 BP1 Block protect bit
// #737: ; 2 BP0 Block protect bit
// #738: ; 1 WEL Write Enable Latch Bit
// #739: ; 0 WIP Write In Progress
// #740: ;
// #741: ;
// @11f #742: [read_spi_flash_status]
3010e // @11f #742: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @120 #743: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @121 #744: OUTPUT(s0,SPI_control_port)
2e004 // @122 #745: STORE(s0,SPI_control_status) ;preserve status
00205 // @123 #746: LOAD(s2,5) ;Read Status register instruction
30112 // @124 #747: CALL(SPI_FLASH_tx_rx) ;transmit instruction
30112 // @125 #748: CALL(SPI_FLASH_tx_rx) ;Receive status register information
0e002 // @126 #749: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @127 #750: OUTPUT(s0,SPI_control_port)
2e004 // @128 #751: STORE(s0,SPI_control_status) ;preserve status
2a000 // @129 #752: RETURN
// #753: ;
// #754: ;Set write enable mode in SPI FLASH memory (ST type M25P16)
// #755: ;
// #756: ;Transmits instruction 06hex.
// #757: ;
// @12a #758: [set_spi_flash_WREN]
3010e // @12a #758: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @12b #759: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @12c #760: OUTPUT(s0,SPI_control_port)
2e004 // @12d #761: STORE(s0,SPI_control_status) ;preserve status
00206 // @12e #762: LOAD(s2,6) ;Set write enable mode instruction
30112 // @12f #763: CALL(SPI_FLASH_tx_rx) ;transmit instruction
0e002 // @130 #764: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @131 #765: OUTPUT(s0,SPI_control_port)
2e004 // @132 #766: STORE(s0,SPI_control_status) ;preserve status
2a000 // @133 #767: RETURN
// #768: ;
// #769: ;Reset the write enable mode in SPI FLASH memory (ST type M25P16)
// #770: ;
// #771: ;Transmits instruction 04hex.
// #772: ;
// @134 #773: [reset_spi_flash_WREN]
3010e // @134 #773: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @135 #774: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @136 #775: OUTPUT(s0,SPI_control_port)
2e004 // @137 #776: STORE(s0,SPI_control_status) ;preserve status
00204 // @138 #777: LOAD(s2,4) ;Reset write enable mode instruction
30112 // @139 #778: CALL(SPI_FLASH_tx_rx) ;transmit instruction
0e002 // @13a #779: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @13b #780: OUTPUT(s0,SPI_control_port)
2e004 // @13c #781: STORE(s0,SPI_control_status) ;preserve status
2a000 // @13d #782: RETURN
// #783: ;
// #784: ;Read the identification ID from SPI FLASH memory (ST type M25P16)
// #785: ;
// #786: ;Transmits instruction 9Fhex and then reads the 3 byte response into [s9,s8,s7]
// #787: ;
// #788: ;response should be
// #789: ; s9 = Manufacturer Identification = 20 hex
// #790: ; s8 = Memory Type = 20 hex
// #791: ; s7 = Memory Capacity = 15 hex
// #792: ;
// @13e #793: [read_spi_flash_ID]
3010e // @13e #793: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @13f #794: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @140 #795: OUTPUT(s0,SPI_control_port)
2e004 // @141 #796: STORE(s0,SPI_control_status) ;preserve status
0029f // @142 #797: LOAD(s2,159) ;Read ID instruction
30112 // @143 #798: CALL(SPI_FLASH_tx_rx) ;transmit instruction
30112 // @144 #799: CALL(SPI_FLASH_tx_rx) ;receive Manufacturer ID
01920 // @145 #800: LOAD(s9,s2)
30112 // @146 #801: CALL(SPI_FLASH_tx_rx) ;receive Memory Type
01820 // @147 #802: LOAD(s8,s2)
30112 // @148 #803: CALL(SPI_FLASH_tx_rx) ;receive Memory Capacity
01720 // @149 #804: LOAD(s7,s2)
0e002 // @14a #805: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @14b #806: OUTPUT(s0,SPI_control_port)
2e004 // @14c #807: STORE(s0,SPI_control_status) ;preserve status
2a000 // @14d #808: RETURN
// #809: ;
// #810: ;Read a single byte from the SPI FLASH memory (ST type M25P16)
// #811: ;
// #812: ;Transmits instruction 03hex followed by a 24-bit address which must be supplied in the
// #813: ;register set [s9,s8,s7]. It then transmits a dummy byte to retrieve the memory data
// #814: ;which is returned in register s2.
// #815: ;
// @14e #816: [read_spi_byte]
3010e // @14e #816: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @14f #817: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @150 #818: OUTPUT(s0,SPI_control_port)
2e004 // @151 #819: STORE(s0,SPI_control_status) ;preserve status
00203 // @152 #820: LOAD(s2,3) ;Read Data Bytes instruction
30112 // @153 #821: CALL(SPI_FLASH_tx_rx) ;transmit instruction
01290 // @154 #822: LOAD(s2,s9) ;Transmit 24-bit address
30112 // @155 #823: CALL(SPI_FLASH_tx_rx)
01280 // @156 #824: LOAD(s2,s8)
30112 // @157 #825: CALL(SPI_FLASH_tx_rx)
01270 // @158 #826: LOAD(s2,s7)
30112 // @159 #827: CALL(SPI_FLASH_tx_rx)
30112 // @15a #828: CALL(SPI_FLASH_tx_rx) ;read data byte
0e002 // @15b #829: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @15c #830: OUTPUT(s0,SPI_control_port)
2e004 // @15d #831: STORE(s0,SPI_control_status) ;preserve status
2a000 // @15e #832: RETURN
// #833: ;
// #834: ;
// #835: ;Erase a single sector from the SPI FLASH memory (ST type M25P16)
// #836: ;
// #837: ;Sets the WREN instruction and then transmits instruction D8 hex followed by a 24-bit
// #838: ;address which must be supplied in the register set [s9,s8,s7]. The address must be
// #839: ;at some location within the sector to be erased. A sector erase can take up to
// #840: ;3 seconds to complete. The routine therefore reads the FLASH status and tests
// #841: ;the write in progress (WIP) bit to test for completion
// #842: ;
// @15f #843: [erase_spi_sector]
3012a // @15f #843: CALL(set_spi_flash_WREN) ;set write enable mode
3010e // @160 #844: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @161 #845: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @162 #846: OUTPUT(s0,SPI_control_port)
2e004 // @163 #847: STORE(s0,SPI_control_status) ;preserve status
002d8 // @164 #848: LOAD(s2,D8) ;Sector erase mode
30112 // @165 #849: CALL(SPI_FLASH_tx_rx) ;transmit instruction
01290 // @166 #850: LOAD(s2,s9) ;Transmit 24-bit address [s9,s8,s7].
30112 // @167 #851: CALL(SPI_FLASH_tx_rx)
01280 // @168 #852: LOAD(s2,s8)
30112 // @169 #853: CALL(SPI_FLASH_tx_rx)
01270 // @16a #854: LOAD(s2,s7)
30112 // @16b #855: CALL(SPI_FLASH_tx_rx)
0e002 // @16c #856: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @16d #857: OUTPUT(s0,SPI_control_port)
2e004 // @16e #858: STORE(s0,SPI_control_status) ;preserve status
// @16f #859: [sector_erase_wait]
3011f // @16f #859: CALL(read_spi_flash_status) ;test WIP bit until finished
12201 // @170 #860: TEST(s2,1)
3556f // @171 #861: JUMP(NZ,sector_erase_wait)
2a000 // @172 #862: RETURN
// #863: ;
// #864: ;
// #865: ;
// #866: ;Bulk erase the whole SPI FLASH memory (ST type M25P16)
// #867: ;
// #868: ;Sets the WREN instruction and then transmits instruction C7 hex.
// #869: ;A bulk erase can take up to 40 seconds to complete. The routine therefore reads the
// #870: ;FLASH status and tests the write in progress (WIP) bit to test for completion
// #871: ;
// @173 #872: [bulk_erase_spi]
3012a // @173 #872: CALL(set_spi_flash_WREN) ;set write enable mode
3010e // @174 #873: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @175 #874: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @176 #875: OUTPUT(s0,SPI_control_port)
2e004 // @177 #876: STORE(s0,SPI_control_status) ;preserve status
002c7 // @178 #877: LOAD(s2,C7) ;Sector erase mode
30112 // @179 #878: CALL(SPI_FLASH_tx_rx) ;transmit instruction
0e002 // @17a #879: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @17b #880: OUTPUT(s0,SPI_control_port)
2e004 // @17c #881: STORE(s0,SPI_control_status) ;preserve status
// @17d #882: [bulk_erase_wait]
3011f // @17d #882: CALL(read_spi_flash_status) ;test WIP bit until finished
12201 // @17e #883: TEST(s2,1)
3557d // @17f #884: JUMP(NZ,bulk_erase_wait)
2a000 // @180 #885: RETURN
// #886: ;
// #887: ;
// #888: ;
// #889: ;Open a page for programming.
// #890: ;The 24-bit start address to be supplied in the register set [s9,s8,s7].
// #891: ;Note that s7=00 hex for normal page boundaries but you could start at any address.
// #892: ;Caution : Exceeding s7=FF hex will result in the roll over to 00 hex but without
// #893: ;incrementing to the next page.
// #894: ;
// #895: ;Transmits instruction 02hex followed by the 24-bit start address.
// #896: ;It is then ready to transmit data bytes using the s2 register and the SPI_FLASH_tx_rx
// #897: ;subroutine. After transmitting bytes, close the page with the close_prog_page_spi
// #898: ;routine.
// #899: ;
// @181 #900: [open_prog_page_spi]
3012a // @181 #900: CALL(set_spi_flash_WREN) ;set write enable mode
3010e // @182 #901: CALL(SPI_init) ;ensure known state of bus and s0 register
0e002 // @183 #902: XOR(s0,SPI_rom_cs) ;select (Low) FLASH
2c008 // @184 #903: OUTPUT(s0,SPI_control_port)
2e004 // @185 #904: STORE(s0,SPI_control_status) ;preserve status
00202 // @186 #905: LOAD(s2,2) ;Page program mode
30112 // @187 #906: CALL(SPI_FLASH_tx_rx) ;transmit instruction
01290 // @188 #907: LOAD(s2,s9) ;Transmit 24-bit address [s9,s8,s7].
30112 // @189 #908: CALL(SPI_FLASH_tx_rx)
01280 // @18a #909: LOAD(s2,s8)
30112 // @18b #910: CALL(SPI_FLASH_tx_rx)
01270 // @18c #911: LOAD(s2,s7)
30112 // @18d #912: CALL(SPI_FLASH_tx_rx)
2a000 // @18e #913: RETURN
// #914: ;
// #915: ;
// #916: ;This routine completes a page program operation started with
// #917: ;open_prog_page_spi and data bytes sent with SPI_FLASH_tx_rx.
// #918: ;
// #919: ;A page program can take up to 5ms to complete. The routine therefore reads the
// #920: ;FLASH status and tests the write in progress (WIP) bit to test for completion
// #921: ;
// #922: ;
// @18f #923: [close_prog_page_spi]
06004 // @18f #923: FETCH(s0,SPI_control_status) ;read control status bits
0e002 // @190 #924: XOR(s0,SPI_rom_cs) ;deselect (High) FLASH
2c008 // @191 #925: OUTPUT(s0,SPI_control_port)
2e004 // @192 #926: STORE(s0,SPI_control_status) ;preserve status
// @193 #927: [page_prog_wait]
3011f // @193 #927: CALL(read_spi_flash_status) ;test WIP bit until finished
12201 // @194 #928: TEST(s2,1)
35593 // @195 #929: JUMP(NZ,page_prog_wait)
2a000 // @196 #930: RETURN
// #931: ;
// #932: ;**************************************************************************************
// #933: ;Software delay routines
// #934: ;**************************************************************************************
// #935: ;
// #936: ;
// #937: ;
// #938: ;Delay of 1us.
// #939: ;
// #940: ;Constant value defines reflects the clock applied to KCPSM3. Every instruction
// #941: ;executes in 2 clock cycles making the calculation highly predictable. The '6' in
// #942: ;the following equation even allows for 'CALL delay_1us' instruction in the initiating code.
// #943: ;
// #944: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
// #945: ;
// #946: ;Registers used s0
// #947: ;
// @197 #948: [delay_1us]
0000b // @197 #948: LOAD(s0,delay_1us_constant)
// @198 #949: [wait_1us]
1c001 // @198 #949: SUB(s0,1)
35598 // @199 #950: JUMP(NZ,wait_1us)
2a000 // @19a #951: RETURN
// #952: ;
// #953: ;Delay of 40us.
// #954: ;
// #955: ;Registers used s0, s1
// #956: ;
// @19b #957: [delay_40us]
00128 // @19b #957: LOAD(s1,40) ;40 x 1us = 40us
// @19c #958: [wait_40us]
30197 // @19c #958: CALL(delay_1us)
1c101 // @19d #959: SUB(s1,1)
3559c // @19e #960: JUMP(NZ,wait_40us)
2a000 // @19f #961: RETURN
// #962: ;
// #963: ;
// #964: ;Delay of 1ms.
// #965: ;
// #966: ;Registers used s0, s1, s2
// #967: ;
// @1a0 #968: [delay_1ms]
00219 // @1a0 #968: LOAD(s2,25) ;25 x 40us = 1ms
// @1a1 #969: [wait_1ms]
3019b // @1a1 #969: CALL(delay_40us)
1c201 // @1a2 #970: SUB(s2,1)
355a1 // @1a3 #971: JUMP(NZ,wait_1ms)
2a000 // @1a4 #972: RETURN
// #973: ;
// #974: ;Delay of 20ms.
// #975: ;
// #976: ;Delay of 20ms used during initialisation.
// #977: ;
// #978: ;Registers used s0, s1, s2, s3
// #979: ;
// @1a5 #980: [delay_20ms]
00314 // @1a5 #980: LOAD(s3,20) ;20 x 1ms = 20ms
// @1a6 #981: [wait_20ms]
301a0 // @1a6 #981: CALL(delay_1ms)
1c301 // @1a7 #982: SUB(s3,1)
355a6 // @1a8 #983: JUMP(NZ,wait_20ms)
2a000 // @1a9 #984: RETURN
// #985: ;
// #986: ;Delay of approximately 1 second.
// #987: ;
// #988: ;Registers used s0, s1, s2, s3, s4
// #989: ;
// @1aa #990: [delay_1s]
00414 // @1aa #990: LOAD(s4,20) ;50 x 20ms = 1000ms
// @1ab #991: [wait_1s]
301a5 // @1ab #991: CALL(delay_20ms)
1c401 // @1ac #992: SUB(s4,1)
355ab // @1ad #993: JUMP(NZ,wait_1s)
2a000 // @1ae #994: RETURN
// #995: ;
// #996: ;**************************************************************************************
// #997: ;UART communication routines
// #998: ;**************************************************************************************
// #999: ;
// #1000: ;Read one character from the UART
// #1001: ;
// #1002: ;Character read will be returned in a register called 'UART_data'.
// #1003: ;
// #1004: ;The routine first tests the receiver FIFO buffer to see if data is present.
// #1005: ;If the FIFO is empty, the routine waits until there is a character to read.
// #1006: ;As this could take any amount of time the wait loop could include a call to a
// #1007: ;subroutine which performs a useful function.
// #1008: ;
// #1009: ;If the received character is an XOFF, then the routine will then wait
// #1010: ;for an XON to be received. This means that the rest of the program is held
// #1011: ;in suspense and therefore it can not transmit. Once an XON is received, it will
// #1012: ;again wait for a normal character before returning.
// #1013: ;
// #1014: ;NOTE: Characters between the XOFF and XON will be ignored in this version of the
// #1015: ;program!!!
// #1016: ;
// #1017: ;Interrupt is disabled during this routine to prevent a false situation. If the
// #1018: ;receiver half-full flag went High it should result in an interrupt transmitting
// #1019: ;an XOFF character. However, if this routine were able to read the receiver buffer
// #1020: ;at just about the same as the hardware detects the half-full flag, then it could
// #1021: ;think that an XON needs to be transmitted.
// #1022: ;
// #1023: ;
// #1024: ;Registers used s0 and UART_data
// #1025: ;
// @1af #1026: [read_from_UART]
3c000 // @1af #1026: DISABLE(INTERRUPT)
// @1b0 #1027: [wait_Rx_character]
04000 // @1b0 #1027: INPUT(s0,status_port) ;test Rx_FIFO buffer
12008 // @1b1 #1028: TEST(s0,rx_data_present)
355b4 // @1b2 #1029: JUMP(NZ,read_character)
341b0 // @1b3 #1030: JUMP(wait_Rx_character)
// @1b4 #1031: [read_character]
04f01 // @1b4 #1031: INPUT(UART_data,UART_read_port) ;read from FIFO
14f13 // @1b5 #1032: COMPARE(UART_data,character_XOFF) ;test for XOFF
351b9 // @1b6 #1033: JUMP(Z,wait_XON)
3c001 // @1b7 #1034: ENABLE(INTERRUPT) ;normal finish
2a000 // @1b8 #1035: RETURN
// @1b9 #1036: [wait_XON]
04000 // @1b9 #1036: INPUT(s0,status_port) ;test Rx_FIFO buffer
12008 // @1ba #1037: TEST(s0,rx_data_present)
355bd // @1bb #1038: JUMP(NZ,read_XON)
341b9 // @1bc #1039: JUMP(wait_XON)
// @1bd #1040: [read_XON]
04f01 // @1bd #1040: INPUT(UART_data,UART_read_port) ;read from FIFO
14f11 // @1be #1041: COMPARE(UART_data,character_XON) ;test for XON
351b0 // @1bf #1042: JUMP(Z,wait_Rx_character) ;now wait for normal character
341b9 // @1c0 #1043: JUMP(wait_XON) ;continue to wait for XON
// #1044: ;
// #1045: ;
// #1046: ;
// #1047: ;Transmit one character to the UART
// #1048: ;
// #1049: ;Character supplied in register called 'UART_data'.
// #1050: ;
// #1051: ;The routine first tests the transmit FIFO buffer is empty.
// #1052: ;If the FIFO currently has any data, the routine waits until it is empty.
// #1053: ;Ultimately this means that only one character is sent at a time which
// #1054: ;could be important if the PC at the other end of the link transmits
// #1055: ;an XOFF and needs the flow of data to terminate as soon as possible.
// #1056: ;
// #1057: ;Registers used s0
// #1058: ;
// @1c1 #1059: [send_to_UART]
04000 // @1c1 #1059: INPUT(s0,status_port) ;test Tx_FIFO buffer
12001 // @1c2 #1060: TEST(s0,tx_data_present)
351c5 // @1c3 #1061: JUMP(Z,UART_write)
341c1 // @1c4 #1062: JUMP(send_to_UART)
// @1c5 #1063: [UART_write]
2cf10 // @1c5 #1063: OUTPUT(UART_data,UART_write_port)
2a000 // @1c6 #1064: RETURN
// #1065: ;
// #1066: ;Convert value provided in register s0 into ASCII characters
// #1067: ;
// #1068: ;The value provided must in the range 0 to 99 and will be converted into
// #1069: ;two ASCII characters.
// #1070: ; The number of 'tens' will be represented by an ASCII character returned in register s1.
// #1071: ; The number of 'units' will be represented by an ASCII character returned in register s0.
// #1072: ;
// #1073: ;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex added to
// #1074: ;the actual decimal value.
// #1075: ;
// #1076: ;Registers used s0 and s1.
// #1077: ;
// @1c7 #1078: [decimal_to_ASCII]
00130 // @1c7 #1078: LOAD(s1,48) ;load 'tens' counter with ASCII for '0'
// @1c8 #1079: [test_for_ten]
18101 // @1c8 #1079: ADD(s1,1) ;increment 'tens' value
1c00a // @1c9 #1080: SUB(s0,10) ;try to subtract 10 from the supplied value
35dc8 // @1ca #1081: JUMP(NC,test_for_ten) ;repeat if subtraction was possible without underflow.
1c101 // @1cb #1082: SUB(s1,1) ;'tens' value one less ten due to underflow
1803a // @1cc #1083: ADD(s0,58) ;restore units value (the remainder) and convert to ASCII
2a000 // @1cd #1084: RETURN
// #1085: ;
// #1086: ;
// #1087: ;
// #1088: ;Convert character to upper case
// #1089: ;
// #1090: ;The character supplied in register s0.
// #1091: ;If the character is in the range 'a' to 'z', it is converted
// #1092: ;to the equivalent upper case character in the range 'A' to 'Z'.
// #1093: ;All other characters remain unchanged.
// #1094: ;
// #1095: ;Registers used s0.
// #1096: ;
// @1ce #1097: [upper_case]
14061 // @1ce #1097: COMPARE(s0,97) ;eliminate character codes below 'a' (61 hex)
2b800 // @1cf #1098: RETURN(C)
1407b // @1d0 #1099: COMPARE(s0,123) ;eliminate character codes above 'z' (7A hex)
2bc00 // @1d1 #1100: RETURN(NC)
0a0df // @1d2 #1101: AND(s0,DF) ;mask bit5 to convert to upper case
2a000 // @1d3 #1102: RETURN
// #1103: ;
// #1104: ;
// #1105: ;Convert character '0' to '9' to numerical value in range 0 to 9
// #1106: ;
// #1107: ;The character supplied in register s0. If the character is in the
// #1108: ;range '0' to '9', it is converted to the equivalent decimal value.
// #1109: ;Characters not in the range '0' to '9' are signified by the return
// #1110: ;with the CARRY flag set.
// #1111: ;
// #1112: ;Registers used s0.
// #1113: ;
// @1d4 #1114: [onechar_to_value]
180c6 // @1d4 #1114: ADD(s0,C6) ;reject character codes above '9' (39 hex)
2b800 // @1d5 #1115: RETURN(C) ;carry flag is set
1c0f6 // @1d6 #1116: SUB(s0,F6) ;reject character codes below '0' (30 hex)
2a000 // @1d7 #1117: RETURN ;carry is set if value not in range
// #1118: ;
// #1119: ;
// #1120: ;Determine the numerical value of a two character decimal string held in
// #1121: ;scratch pad memory such the result is in the range 0 to 99 (00 to 63 hex).
// #1122: ;
// #1123: ;The string must be stored in two consecutive memory locations and the
// #1124: ;location of the first (tens) character supplied in the s1 register.
// #1125: ;The result is provided in register s2. Strings not using characters in the
// #1126: ;range '0' to '9' are signified by the return with the CARRY flag set.
// #1127: ;
// #1128: ;Registers used s0, s1 and s2.
// #1129: ;
// @1d8 #1130: [twochar_to_value]
07010 // @1d8 #1130: FETCH(s0,s1) ;read 'tens' character
301d4 // @1d9 #1131: CALL(onechar_to_value) ;convert to numerical value
2b800 // @1da #1132: RETURN(C) ;bad character - CARRY set
01200 // @1db #1133: LOAD(s2,s0)
20206 // @1dc #1134: SL0(s2) ;multiply 'tens' value by 10 (0A hex)
20206 // @1dd #1135: SL0(s2)
19200 // @1de #1136: ADD(s2,s0)
20206 // @1df #1137: SL0(s2)
18101 // @1e0 #1138: ADD(s1,1) ;read 'units' character
07010 // @1e1 #1139: FETCH(s0,s1)
301d4 // @1e2 #1140: CALL(onechar_to_value) ;convert to numerical value
2b800 // @1e3 #1141: RETURN(C) ;bad character - CARRY set
19200 // @1e4 #1142: ADD(s2,s0) ;add units to result and clear CARRY flag
2a000 // @1e5 #1143: RETURN
// #1144: ;
// #1145: ;
// #1146: ;Convert hexadecimal value provided in register s0 into ASCII characters
// #1147: ;
// #1148: ;The value provided must can be any value in the range 00 to FF and will be converted into
// #1149: ;two ASCII characters.
// #1150: ; The upper nibble will be represented by an ASCII character returned in register s2.
// #1151: ; The lower nibble will be represented by an ASCII character returned in register s1.
// #1152: ;
// #1153: ;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex
// #1154: ;added to the actual decimal value. The ASCII representations of 'A' to 'F' are 41 to 46
// #1155: ;hexadecimal requiring a further addition of 07 to the 30 already added.
// #1156: ;
// #1157: ;Registers used s0, s1 and s2.
// #1158: ;
// @1e6 #1159: [hex_byte_to_ASCII]
01100 // @1e6 #1159: LOAD(s1,s0) ;remember value supplied
2000e // @1e7 #1160: SR0(s0) ;isolate upper nibble
2000e // @1e8 #1161: SR0(s0)
2000e // @1e9 #1162: SR0(s0)
2000e // @1ea #1163: SR0(s0)
301f2 // @1eb #1164: CALL(hex_to_ASCII) ;convert
01200 // @1ec #1165: LOAD(s2,s0) ;upper nibble value in s2
01010 // @1ed #1166: LOAD(s0,s1) ;restore complete value
0a00f // @1ee #1167: AND(s0,15) ;isolate lower nibble
301f2 // @1ef #1168: CALL(hex_to_ASCII) ;convert
01100 // @1f0 #1169: LOAD(s1,s0) ;lower nibble value in s1
2a000 // @1f1 #1170: RETURN
// #1171: ;
// #1172: ;Convert hexadecimal value provided in register s0 into ASCII character
// #1173: ;
// #1174: ;Register used s0
// #1175: ;
// @1f2 #1176: [hex_to_ASCII]
1c00a // @1f2 #1176: SUB(s0,10) ;test if value is in range 0 to 9
359f5 // @1f3 #1177: JUMP(C,number_char)
18007 // @1f4 #1178: ADD(s0,7) ;ASCII char A to F in range 41 to 46
// @1f5 #1179: [number_char]
1803a // @1f5 #1179: ADD(s0,58) ;ASCII char 0 to 9 in range 30 to 40
2a000 // @1f6 #1180: RETURN
// #1181: ;
// #1182: ;
// #1183: ;Send the two character HEX value of the register contents 's0' to the UART
// #1184: ;
// #1185: ;Registers used s0, s1, s2
// #1186: ;
// @1f7 #1187: [send_hex_byte]
301e6 // @1f7 #1187: CALL(hex_byte_to_ASCII)
01f20 // @1f8 #1188: LOAD(UART_data,s2)
301c1 // @1f9 #1189: CALL(send_to_UART)
01f10 // @1fa #1190: LOAD(UART_data,s1)
301c1 // @1fb #1191: CALL(send_to_UART)
2a000 // @1fc #1192: RETURN
// #1193: ;
// #1194: ;
// #1195: ;
// #1196: ;Send the six character HEX value of the register contents [s9,s8,s7] to the UART
// #1197: ;
// #1198: ;Registers used s0, s1, s2
// #1199: ;
// @1fd #1200: [send_hex_3bytes]
01090 // @1fd #1200: LOAD(s0,s9)
301f7 // @1fe #1201: CALL(send_hex_byte)
01080 // @1ff #1202: LOAD(s0,s8)
301f7 // @200 #1203: CALL(send_hex_byte)
01070 // @201 #1204: LOAD(s0,s7)
301f7 // @202 #1205: CALL(send_hex_byte)
2a000 // @203 #1206: RETURN
// #1207: ;
// #1208: ;
// #1209: ;Convert the HEX ASCII characters contained in 's3' and 's2' into
// #1210: ;an equivalent hexadecimal value in register 's0'.
// #1211: ; The upper nibble is represented by an ASCII character in register s3.
// #1212: ; The lower nibble is represented by an ASCII character in register s2.
// #1213: ;
// #1214: ;Input characters must be in the range 00 to FF hexadecimal or the CARRY flag
// #1215: ;will be set on return.
// #1216: ;
// #1217: ;Registers used s0, s2 and s3.
// #1218: ;
// @204 #1219: [ASCII_byte_to_hex]
01030 // @204 #1219: LOAD(s0,s3) ;Take upper nibble
30211 // @205 #1220: CALL(ASCII_to_hex) ;convert to value
2b800 // @206 #1221: RETURN(C) ;reject if out of range
01300 // @207 #1222: LOAD(s3,s0) ;remember value
20306 // @208 #1223: SL0(s3) ;multiply value by 16 to put in upper nibble
20306 // @209 #1224: SL0(s3)
20306 // @20a #1225: SL0(s3)
20306 // @20b #1226: SL0(s3)
01020 // @20c #1227: LOAD(s0,s2) ;Take lower nibble
30211 // @20d #1228: CALL(ASCII_to_hex) ;convert to value
2b800 // @20e #1229: RETURN(C) ;reject if out of range
0d030 // @20f #1230: OR(s0,s3) ;merge in the upper nibble with CARRY reset
2a000 // @210 #1231: RETURN
// #1232: ;
// #1233: ;
// #1234: ;Routine to convert ASCII data in 's0' to an equivalent HEX value.
// #1235: ;
// #1236: ;If character is not valid for hex, then CARRY is set on return.
// #1237: ;
// #1238: ;Register used s0
// #1239: ;
// @211 #1240: [ASCII_to_hex]
180b9 // @211 #1240: ADD(s0,B9) ;test for above ASCII code 46 ('F')
2b800 // @212 #1241: RETURN(C)
1c0e9 // @213 #1242: SUB(s0,E9) ;normalise 0 to 9 with A-F in 11 to 16 hex
2b800 // @214 #1243: RETURN(C) ;reject below ASCII code 30 ('0')
1c011 // @215 #1244: SUB(s0,17) ;isolate A-F down to 00 to 05 hex
35e1b // @216 #1245: JUMP(NC,ASCII_letter)
18007 // @217 #1246: ADD(s0,7) ;test for above ASCII code 46 ('F')
2b800 // @218 #1247: RETURN(C)
1c0f6 // @219 #1248: SUB(s0,F6) ;convert to range 00 to 09
2a000 // @21a #1249: RETURN
// @21b #1250: [ASCII_letter]
1800a // @21b #1250: ADD(s0,10) ;convert to range 0A to 0F
2a000 // @21c #1251: RETURN
// #1252: ;
// #1253: ;
// #1254: ;
// #1255: ;Send Carriage Return to the UART
// #1256: ;
// @21d #1257: [send_CR]
00f0d // @21d #1257: LOAD(UART_data,character_CR)
301c1 // @21e #1258: CALL(send_to_UART)
2a000 // @21f #1259: RETURN
// #1260: ;
// #1261: ;Send a space to the UART
// #1262: ;
// @220 #1263: [send_space]
00f20 // @220 #1263: LOAD(UART_data,character_space)
301c1 // @221 #1264: CALL(send_to_UART)
2a000 // @222 #1265: RETURN
// #1266: ;
// #1267: ;
// #1268: ;**************************************************************************************
// #1269: ;Text messages
// #1270: ;**************************************************************************************
// #1271: ;
// #1272: ;
// #1273: ;Send 'PicoBlaze SPI FLASH Programmer' string to the UART
// #1274: ;
// @223 #1275: [send_welcome]
3021d // @223 #1275: CALL(send_CR)
3021d // @224 #1276: CALL(send_CR)
00f50 // @225 #1277: LOAD(UART_data,character_P)
301c1 // @226 #1278: CALL(send_to_UART)
00f69 // @227 #1279: LOAD(UART_data,character_i)
301c1 // @228 #1280: CALL(send_to_UART)
00f63 // @229 #1281: LOAD(UART_data,character_c)
301c1 // @22a #1282: CALL(send_to_UART)
00f6f // @22b #1283: LOAD(UART_data,character_o)
301c1 // @22c #1284: CALL(send_to_UART)
00f42 // @22d #1285: LOAD(UART_data,character_B)
301c1 // @22e #1286: CALL(send_to_UART)
00f6c // @22f #1287: LOAD(UART_data,character_l)
301c1 // @230 #1288: CALL(send_to_UART)
00f61 // @231 #1289: LOAD(UART_data,character_a)
301c1 // @232 #1290: CALL(send_to_UART)
00f7a // @233 #1291: LOAD(UART_data,character_z)
301c1 // @234 #1292: CALL(send_to_UART)
00f65 // @235 #1293: LOAD(UART_data,character_e)
301c1 // @236 #1294: CALL(send_to_UART)
30220 // @237 #1295: CALL(send_space)
00f53 // @238 #1296: LOAD(UART_data,character_S)
301c1 // @239 #1297: CALL(send_to_UART)
00f50 // @23a #1298: LOAD(UART_data,character_P)
301c1 // @23b #1299: CALL(send_to_UART)
00f49 // @23c #1300: LOAD(UART_data,character_I)
301c1 // @23d #1301: CALL(send_to_UART)
30220 // @23e #1302: CALL(send_space)
00f46 // @23f #1303: LOAD(UART_data,character_F)
301c1 // @240 #1304: CALL(send_to_UART)
00f4c // @241 #1305: LOAD(UART_data,character_L)
301c1 // @242 #1306: CALL(send_to_UART)
00f41 // @243 #1307: LOAD(UART_data,character_A)
301c1 // @244 #1308: CALL(send_to_UART)
00f53 // @245 #1309: LOAD(UART_data,character_S)
301c1 // @246 #1310: CALL(send_to_UART)
00f48 // @247 #1311: LOAD(UART_data,character_H)
301c1 // @248 #1312: CALL(send_to_UART)
30220 // @249 #1313: CALL(send_space)
00f50 // @24a #1314: LOAD(UART_data,character_P)
301c1 // @24b #1315: CALL(send_to_UART)
00f72 // @24c #1316: LOAD(UART_data,character_r)
301c1 // @24d #1317: CALL(send_to_UART)
00f6f // @24e #1318: LOAD(UART_data,character_o)
301c1 // @24f #1319: CALL(send_to_UART)
00f67 // @250 #1320: LOAD(UART_data,character_g)
301c1 // @251 #1321: CALL(send_to_UART)
00f72 // @252 #1322: LOAD(UART_data,character_r)
301c1 // @253 #1323: CALL(send_to_UART)
00f61 // @254 #1324: LOAD(UART_data,character_a)
301c1 // @255 #1325: CALL(send_to_UART)
00f6d // @256 #1326: LOAD(UART_data,character_m)
301c1 // @257 #1327: CALL(send_to_UART)
00f6d // @258 #1328: LOAD(UART_data,character_m)
301c1 // @259 #1329: CALL(send_to_UART)
00f65 // @25a #1330: LOAD(UART_data,character_e)
301c1 // @25b #1331: CALL(send_to_UART)
00f72 // @25c #1332: LOAD(UART_data,character_r)
301c1 // @25d #1333: CALL(send_to_UART)
30220 // @25e #1334: CALL(send_space)
00f76 // @25f #1335: LOAD(UART_data,character_v)
301c1 // @260 #1336: CALL(send_to_UART)
00f31 // @261 #1337: LOAD(UART_data,character_1)
301c1 // @262 #1338: CALL(send_to_UART)
00f2e // @263 #1339: LOAD(UART_data,character_fullstop)
301c1 // @264 #1340: CALL(send_to_UART)
00f30 // @265 #1341: LOAD(UART_data,character_0)
301c1 // @266 #1342: CALL(send_to_UART)
00f30 // @267 #1343: LOAD(UART_data,character_0)
301c1 // @268 #1344: CALL(send_to_UART)
3021d // @269 #1345: CALL(send_CR)
3021d // @26a #1346: CALL(send_CR)
2a000 // @26b #1347: RETURN
// #1348: ;
// #1349: ;
// #1350: ;
// #1351: ;Send 'Waiting_MCS_file' string to the UART
// #1352: ;
// @26c #1353: [send_Waiting_MCS_file]
00f57 // @26c #1353: LOAD(UART_data,character_W)
301c1 // @26d #1354: CALL(send_to_UART)
00f61 // @26e #1355: LOAD(UART_data,character_a)
301c1 // @26f #1356: CALL(send_to_UART)
00f69 // @270 #1357: LOAD(UART_data,character_i)
301c1 // @271 #1358: CALL(send_to_UART)
00f74 // @272 #1359: LOAD(UART_data,character_t)
301c1 // @273 #1360: CALL(send_to_UART)
00f69 // @274 #1361: LOAD(UART_data,character_i)
301c1 // @275 #1362: CALL(send_to_UART)
00f6e // @276 #1363: LOAD(UART_data,character_n)
301c1 // @277 #1364: CALL(send_to_UART)
00f67 // @278 #1365: LOAD(UART_data,character_g)
301c1 // @279 #1366: CALL(send_to_UART)
30220 // @27a #1367: CALL(send_space)
00f66 // @27b #1368: LOAD(UART_data,character_f)
301c1 // @27c #1369: CALL(send_to_UART)
00f6f // @27d #1370: LOAD(UART_data,character_o)
301c1 // @27e #1371: CALL(send_to_UART)
00f72 // @27f #1372: LOAD(UART_data,character_r)
301c1 // @280 #1373: CALL(send_to_UART)
// @281 #1374: [send_MCS_file]
30220 // @281 #1374: CALL(send_space)
00f4d // @282 #1375: LOAD(UART_data,character_M)
301c1 // @283 #1376: CALL(send_to_UART)
00f43 // @284 #1377: LOAD(UART_data,character_C)
301c1 // @285 #1378: CALL(send_to_UART)
00f53 // @286 #1379: LOAD(UART_data,character_S)
301c1 // @287 #1380: CALL(send_to_UART)
30220 // @288 #1381: CALL(send_space)
00f46 // @289 #1382: LOAD(UART_data,character_F)
301c1 // @28a #1383: CALL(send_to_UART)
00f69 // @28b #1384: LOAD(UART_data,character_i)
301c1 // @28c #1385: CALL(send_to_UART)
00f6c // @28d #1386: LOAD(UART_data,character_l)
301c1 // @28e #1387: CALL(send_to_UART)
00f65 // @28f #1388: LOAD(UART_data,character_e)
301c1 // @290 #1389: CALL(send_to_UART)
3021d // @291 #1390: CALL(send_CR)
2a000 // @292 #1391: RETURN
// #1392: ;
// #1393: ;
// #1394: ;Send 'Erase in progress' string to the UART
// #1395: ;
// @293 #1396: [send_Erase_in_progress]
302aa // @293 #1396: CALL(send_Erase)
00f69 // @294 #1397: LOAD(UART_data,character_i)
301c1 // @295 #1398: CALL(send_to_UART)
00f6e // @296 #1399: LOAD(UART_data,character_n)
301c1 // @297 #1400: CALL(send_to_UART)
30220 // @298 #1401: CALL(send_space)
00f50 // @299 #1402: LOAD(UART_data,character_P)
301c1 // @29a #1403: CALL(send_to_UART)
00f72 // @29b #1404: LOAD(UART_data,character_r)
301c1 // @29c #1405: CALL(send_to_UART)
00f6f // @29d #1406: LOAD(UART_data,character_o)
301c1 // @29e #1407: CALL(send_to_UART)
00f67 // @29f #1408: LOAD(UART_data,character_g)
301c1 // @2a0 #1409: CALL(send_to_UART)
00f72 // @2a1 #1410: LOAD(UART_data,character_r)
301c1 // @2a2 #1411: CALL(send_to_UART)
00f65 // @2a3 #1412: LOAD(UART_data,character_e)
301c1 // @2a4 #1413: CALL(send_to_UART)
00f73 // @2a5 #1414: LOAD(UART_data,character_s)
301c1 // @2a6 #1415: CALL(send_to_UART)
301c1 // @2a7 #1416: CALL(send_to_UART)
3021d // @2a8 #1417: CALL(send_CR)
2a000 // @2a9 #1418: RETURN
// #1419: ;
// #1420: ;
// #1421: ;Send 'Erase ' string to the UART
// #1422: ;
// @2aa #1423: [send_Erase]
00f45 // @2aa #1423: LOAD(UART_data,character_E)
301c1 // @2ab #1424: CALL(send_to_UART)
00f72 // @2ac #1425: LOAD(UART_data,character_r)
301c1 // @2ad #1426: CALL(send_to_UART)
00f61 // @2ae #1427: LOAD(UART_data,character_a)
301c1 // @2af #1428: CALL(send_to_UART)
00f73 // @2b0 #1429: LOAD(UART_data,character_s)
301c1 // @2b1 #1430: CALL(send_to_UART)
00f65 // @2b2 #1431: LOAD(UART_data,character_e)
301c1 // @2b3 #1432: CALL(send_to_UART)
30220 // @2b4 #1433: CALL(send_space)
2a000 // @2b5 #1434: RETURN
// #1435: ;
// #1436: ;
// #1437: ;Send carriage return, 'OK' and carriage return to the UART
// #1438: ;
// @2b6 #1439: [send_OK]
3021d // @2b6 #1439: CALL(send_CR)
00f4f // @2b7 #1440: LOAD(UART_data,character_O)
301c1 // @2b8 #1441: CALL(send_to_UART)
00f4b // @2b9 #1442: LOAD(UART_data,character_K)
301c1 // @2ba #1443: CALL(send_to_UART)
3021d // @2bb #1444: CALL(send_CR)
2a000 // @2bc #1445: RETURN
// #1446: ;
// #1447: ;
// #1448: ;
// #1449: ;Send menu to the UART
// #1450: ;
// @2bd #1451: [send_Menu]
3021d // @2bd #1451: CALL(send_CR)
00f45 // @2be #1452: LOAD(UART_data,character_E)
301c1 // @2bf #1453: CALL(send_to_UART)
00f2d // @2c0 #1454: LOAD(UART_data,character_minus)
301c1 // @2c1 #1455: CALL(send_to_UART)
302aa // @2c2 #1456: CALL(send_Erase)
00f61 // @2c3 #1457: LOAD(UART_data,character_a)
301c1 // @2c4 #1458: CALL(send_to_UART)
00f6c // @2c5 #1459: LOAD(UART_data,character_l)
301c1 // @2c6 #1460: CALL(send_to_UART)
301c1 // @2c7 #1461: CALL(send_to_UART)
3021d // @2c8 #1462: CALL(send_CR)
00f53 // @2c9 #1463: LOAD(UART_data,character_S)
301c1 // @2ca #1464: CALL(send_to_UART)
00f2d // @2cb #1465: LOAD(UART_data,character_minus)
301c1 // @2cc #1466: CALL(send_to_UART)
00f53 // @2cd #1467: LOAD(UART_data,character_S)
301c1 // @2ce #1468: CALL(send_to_UART)
00f65 // @2cf #1469: LOAD(UART_data,character_e)
301c1 // @2d0 #1470: CALL(send_to_UART)
00f63 // @2d1 #1471: LOAD(UART_data,character_c)
301c1 // @2d2 #1472: CALL(send_to_UART)
00f74 // @2d3 #1473: LOAD(UART_data,character_t)
301c1 // @2d4 #1474: CALL(send_to_UART)
00f6f // @2d5 #1475: LOAD(UART_data,character_o)
301c1 // @2d6 #1476: CALL(send_to_UART)
00f72 // @2d7 #1477: LOAD(UART_data,character_r)
301c1 // @2d8 #1478: CALL(send_to_UART)
30220 // @2d9 #1479: CALL(send_space)
302aa // @2da #1480: CALL(send_Erase)
3021d // @2db #1481: CALL(send_CR)
00f50 // @2dc #1482: LOAD(UART_data,character_P)
301c1 // @2dd #1483: CALL(send_to_UART)
00f2d // @2de #1484: LOAD(UART_data,character_minus)
301c1 // @2df #1485: CALL(send_to_UART)
00f50 // @2e0 #1486: LOAD(UART_data,character_P)
301c1 // @2e1 #1487: CALL(send_to_UART)
00f72 // @2e2 #1488: LOAD(UART_data,character_r)
301c1 // @2e3 #1489: CALL(send_to_UART)
00f6f // @2e4 #1490: LOAD(UART_data,character_o)
301c1 // @2e5 #1491: CALL(send_to_UART)
00f67 // @2e6 #1492: LOAD(UART_data,character_g)
301c1 // @2e7 #1493: CALL(send_to_UART)
00f72 // @2e8 #1494: LOAD(UART_data,character_r)
301c1 // @2e9 #1495: CALL(send_to_UART)
00f61 // @2ea #1496: LOAD(UART_data,character_a)
301c1 // @2eb #1497: CALL(send_to_UART)
00f6d // @2ec #1498: LOAD(UART_data,character_m)
301c1 // @2ed #1499: CALL(send_to_UART)
30281 // @2ee #1500: CALL(send_MCS_file)
00f52 // @2ef #1501: LOAD(UART_data,character_R)
301c1 // @2f0 #1502: CALL(send_to_UART)
00f2d // @2f1 #1503: LOAD(UART_data,character_minus)
301c1 // @2f2 #1504: CALL(send_to_UART)
00f52 // @2f3 #1505: LOAD(UART_data,character_R)
301c1 // @2f4 #1506: CALL(send_to_UART)
00f65 // @2f5 #1507: LOAD(UART_data,character_e)
301c1 // @2f6 #1508: CALL(send_to_UART)
00f61 // @2f7 #1509: LOAD(UART_data,character_a)
301c1 // @2f8 #1510: CALL(send_to_UART)
00f64 // @2f9 #1511: LOAD(UART_data,character_d)
301c1 // @2fa #1512: CALL(send_to_UART)
30220 // @2fb #1513: CALL(send_space)
3031f // @2fc #1514: CALL(send_page)
3021d // @2fd #1515: CALL(send_CR)
00f49 // @2fe #1516: LOAD(UART_data,character_I)
301c1 // @2ff #1517: CALL(send_to_UART)
00f2d // @300 #1518: LOAD(UART_data,character_minus)
301c1 // @301 #1519: CALL(send_to_UART)
00f44 // @302 #1520: LOAD(UART_data,character_D)
301c1 // @303 #1521: CALL(send_to_UART)
00f65 // @304 #1522: LOAD(UART_data,character_e)
301c1 // @305 #1523: CALL(send_to_UART)
00f76 // @306 #1524: LOAD(UART_data,character_v)
301c1 // @307 #1525: CALL(send_to_UART)
00f69 // @308 #1526: LOAD(UART_data,character_i)
301c1 // @309 #1527: CALL(send_to_UART)
00f63 // @30a #1528: LOAD(UART_data,character_c)
301c1 // @30b #1529: CALL(send_to_UART)
00f65 // @30c #1530: LOAD(UART_data,character_e)
301c1 // @30d #1531: CALL(send_to_UART)
30220 // @30e #1532: CALL(send_space)
30328 // @30f #1533: CALL(send_ID)
3021d // @310 #1534: CALL(send_CR)
00f48 // @311 #1535: LOAD(UART_data,character_H)
301c1 // @312 #1536: CALL(send_to_UART)
00f2d // @313 #1537: LOAD(UART_data,character_minus)
301c1 // @314 #1538: CALL(send_to_UART)
00f48 // @315 #1539: LOAD(UART_data,character_H)
301c1 // @316 #1540: CALL(send_to_UART)
00f65 // @317 #1541: LOAD(UART_data,character_e)
301c1 // @318 #1542: CALL(send_to_UART)
00f6c // @319 #1543: LOAD(UART_data,character_l)
301c1 // @31a #1544: CALL(send_to_UART)
00f70 // @31b #1545: LOAD(UART_data,character_p)
301c1 // @31c #1546: CALL(send_to_UART)
3021d // @31d #1547: CALL(send_CR)
2a000 // @31e #1548: RETURN
// #1549: ;
// #1550: ;
// #1551: ;Send 'page' to the UART
// #1552: ;
// @31f #1553: [send_page]
00f70 // @31f #1553: LOAD(UART_data,character_p)
301c1 // @320 #1554: CALL(send_to_UART)
00f61 // @321 #1555: LOAD(UART_data,character_a)
301c1 // @322 #1556: CALL(send_to_UART)
00f67 // @323 #1557: LOAD(UART_data,character_g)
301c1 // @324 #1558: CALL(send_to_UART)
00f65 // @325 #1559: LOAD(UART_data,character_e)
301c1 // @326 #1560: CALL(send_to_UART)
2a000 // @327 #1561: RETURN
// #1562: ;
// #1563: ;Send 'ID' to the UART
// #1564: ;
// @328 #1565: [send_ID]
00f49 // @328 #1565: LOAD(UART_data,character_I)
301c1 // @329 #1566: CALL(send_to_UART)
00f44 // @32a #1567: LOAD(UART_data,character_D)
301c1 // @32b #1568: CALL(send_to_UART)
2a000 // @32c #1569: RETURN
// #1570: ;
// #1571: ;
// #1572: ;Send 'Confirm Erase (Y/n) ' to the UART
// #1573: ;
// @32d #1574: [send_Confirm]
3021d // @32d #1574: CALL(send_CR)
00f43 // @32e #1575: LOAD(UART_data,character_C)
301c1 // @32f #1576: CALL(send_to_UART)
00f6f // @330 #1577: LOAD(UART_data,character_o)
301c1 // @331 #1578: CALL(send_to_UART)
00f6e // @332 #1579: LOAD(UART_data,character_n)
301c1 // @333 #1580: CALL(send_to_UART)
00f66 // @334 #1581: LOAD(UART_data,character_f)
301c1 // @335 #1582: CALL(send_to_UART)
00f69 // @336 #1583: LOAD(UART_data,character_i)
301c1 // @337 #1584: CALL(send_to_UART)
00f72 // @338 #1585: LOAD(UART_data,character_r)
301c1 // @339 #1586: CALL(send_to_UART)
00f6d // @33a #1587: LOAD(UART_data,character_m)
301c1 // @33b #1588: CALL(send_to_UART)
30220 // @33c #1589: CALL(send_space)
302aa // @33d #1590: CALL(send_Erase)
00f28 // @33e #1591: LOAD(UART_data,character_open)
301c1 // @33f #1592: CALL(send_to_UART)
00f59 // @340 #1593: LOAD(UART_data,character_Y)
301c1 // @341 #1594: CALL(send_to_UART)
00f2f // @342 #1595: LOAD(UART_data,character_divide)
301c1 // @343 #1596: CALL(send_to_UART)
00f6e // @344 #1597: LOAD(UART_data,character_n)
301c1 // @345 #1598: CALL(send_to_UART)
00f29 // @346 #1599: LOAD(UART_data,character_close)
301c1 // @347 #1600: CALL(send_to_UART)
30220 // @348 #1601: CALL(send_space)
2a000 // @349 #1602: RETURN
// #1603: ;
// #1604: ;
// #1605: ;Send 'Abort' to the UART
// #1606: ;
// @34a #1607: [send_Abort]
3021d // @34a #1607: CALL(send_CR)
00f41 // @34b #1608: LOAD(UART_data,character_A)
301c1 // @34c #1609: CALL(send_to_UART)
00f62 // @34d #1610: LOAD(UART_data,character_b)
301c1 // @34e #1611: CALL(send_to_UART)
00f6f // @34f #1612: LOAD(UART_data,character_o)
301c1 // @350 #1613: CALL(send_to_UART)
00f72 // @351 #1614: LOAD(UART_data,character_r)
301c1 // @352 #1615: CALL(send_to_UART)
00f74 // @353 #1616: LOAD(UART_data,character_t)
301c1 // @354 #1617: CALL(send_to_UART)
3021d // @355 #1618: CALL(send_CR)
2a000 // @356 #1619: RETURN
// #1620: ;
// #1621: ;Send 'page address' to the UART
// #1622: ;
// @357 #1623: [send_page_address]
3021d // @357 #1623: CALL(send_CR)
3031f // @358 #1624: CALL(send_page)
30220 // @359 #1625: CALL(send_space)
00f61 // @35a #1626: LOAD(UART_data,character_a)
301c1 // @35b #1627: CALL(send_to_UART)
00f64 // @35c #1628: LOAD(UART_data,character_d)
301c1 // @35d #1629: CALL(send_to_UART)
301c1 // @35e #1630: CALL(send_to_UART)
00f72 // @35f #1631: LOAD(UART_data,character_r)
301c1 // @360 #1632: CALL(send_to_UART)
00f65 // @361 #1633: LOAD(UART_data,character_e)
301c1 // @362 #1634: CALL(send_to_UART)
00f73 // @363 #1635: LOAD(UART_data,character_s)
301c1 // @364 #1636: CALL(send_to_UART)
301c1 // @365 #1637: CALL(send_to_UART)
00f3d // @366 #1638: LOAD(UART_data,character_equals)
301c1 // @367 #1639: CALL(send_to_UART)
2a000 // @368 #1640: RETURN
// #1641: ;
// #1642: ;
// #1643: ;**************************************************************************************
// #1644: ;Interrupt Service Routine (ISR)
// #1645: ;**************************************************************************************
// #1646: ;
// #1647: ;An interrupt occurs whenever the status of the UART receiver FIFO 'half_full' flag
// #1648: ;changes.
// #1649: ;
// #1650: ;A change from Low to High means that the buffer is becoming full and therefore
// #1651: ;an XOFF character must be transmitted.
// #1652: ;
// #1653: ;A change from High to Low means that the buffer is starting to empty and therefore
// #1654: ;an XON character can be transmitted to restart the flow of new characters.
// #1655: ;
// #1656: ;
@3f5 // #1657: ADDRESS(1013) ;place at end of memory to keep separate
// @3f5 #1658: [ISR]
2e000 // @3f5 #1658: STORE(s0,ISR_preserve_s0) ;preserve register contents
04000 // @3f6 #1659: INPUT(s0,status_port) ;test 'half_full' status of receiver buffer.
12010 // @3f7 #1660: TEST(s0,rx_half_full)
353fb // @3f8 #1661: JUMP(Z,isr_send_xon)
00013 // @3f9 #1662: LOAD(s0,character_XOFF)
343fc // @3fa #1663: JUMP(isr_send_character)
// @3fb #1664: [isr_send_xon]
00011 // @3fb #1664: LOAD(s0,character_XON)
// @3fc #1665: [isr_send_character]
2c010 // @3fc #1665: OUTPUT(s0,UART_write_port)
06000 // @3fd #1666: FETCH(s0,ISR_preserve_s0) ;restore register contents
38001 // @3fe #1667: RETURNI(ENABLE)
// #1668: ;
// #1669: ;
// #1670: ;**************************************************************************************
// #1671: ;Interrupt Vector
// #1672: ;**************************************************************************************
// #1673: ;
@3ff // #1674: ADDRESS(1023)
343f5 // @3ff #1675: JUMP(ISR)
// #1676: ;
// #1677: ;