/* 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: ;