/* Symbol Table */ // AB_switch = CONSTANT: 16 // A_count0_port = CONSTANT: 0 // A_count1_port = CONSTANT: 16 // A_count2_port = CONSTANT: 32 // A_count3_port = CONSTANT: 48 // B_count0_port = CONSTANT: 64 // B_count1_port = CONSTANT: 80 // B_count2_port = CONSTANT: 96 // B_count3_port = CONSTANT: 112 // ISR = LABEL: 541 // ISR_count = CONSTANT: 4 // LCD_DB4 = CONSTANT: 16 // LCD_DB5 = CONSTANT: 32 // LCD_DB6 = CONSTANT: 64 // LCD_DB7 = CONSTANT: 128 // LCD_E = CONSTANT: 1 // LCD_RS = CONSTANT: 4 // LCD_RW = CONSTANT: 2 // LCD_clear = LABEL: 526 // LCD_cursor = LABEL: 531 // LCD_drive = CONSTANT: 8 // LCD_input_port = CONSTANT: 9 // LCD_output_port = CONSTANT: 4 // LCD_pulse_E = LABEL: 442 // LCD_read_DB4 = CONSTANT: 16 // LCD_read_DB5 = CONSTANT: 32 // LCD_read_DB6 = CONSTANT: 64 // LCD_read_DB7 = CONSTANT: 128 // LCD_read_data8 = LABEL: 484 // LCD_read_spare0 = CONSTANT: 1 // LCD_read_spare1 = CONSTANT: 2 // LCD_read_spare2 = CONSTANT: 4 // LCD_read_spare3 = CONSTANT: 8 // LCD_reset = LABEL: 509 // LCD_write_data = LABEL: 467 // LCD_write_inst4 = LABEL: 448 // LCD_write_inst8 = LABEL: 452 // LED_port = CONSTANT: 1 // Ring_select = LABEL: 63 // a_count_reset = CONSTANT: 1 // b_count_reset = CONSTANT: 2 // blank_digit = LABEL: 145 // capture_A_count = LABEL: 575 // capture_B_count = LABEL: 584 // character_0 = CONSTANT: 48 // character_1 = CONSTANT: 49 // character_2 = CONSTANT: 50 // character_3 = CONSTANT: 51 // character_4 = CONSTANT: 52 // character_5 = CONSTANT: 53 // character_6 = CONSTANT: 54 // character_7 = CONSTANT: 55 // character_8 = CONSTANT: 56 // character_9 = CONSTANT: 57 // character_A = CONSTANT: 65 // character_B = CONSTANT: 66 // character_BS = CONSTANT: 8 // character_C = CONSTANT: 67 // character_CR = CONSTANT: 13 // character_D = CONSTANT: 68 // character_E = CONSTANT: 69 // character_F = CONSTANT: 70 // character_G = CONSTANT: 71 // character_H = CONSTANT: 72 // character_I = CONSTANT: 73 // character_J = CONSTANT: 74 // character_K = CONSTANT: 75 // character_L = CONSTANT: 76 // character_M = CONSTANT: 77 // character_N = CONSTANT: 78 // character_O = CONSTANT: 79 // character_P = CONSTANT: 80 // character_Q = CONSTANT: 81 // character_R = CONSTANT: 82 // character_S = CONSTANT: 83 // character_T = CONSTANT: 84 // character_U = CONSTANT: 85 // character_V = CONSTANT: 86 // character_W = CONSTANT: 87 // character_X = CONSTANT: 88 // character_Y = CONSTANT: 89 // character_Z = CONSTANT: 90 // character_a = CONSTANT: 97 // character_b = CONSTANT: 98 // character_c = CONSTANT: 99 // character_colon = CONSTANT: 58 // character_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_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_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_stop = CONSTANT: 46 // character_t = CONSTANT: 116 // character_u = CONSTANT: 117 // character_v = CONSTANT: 118 // character_w = CONSTANT: 119 // character_x = CONSTANT: 120 // character_y = CONSTANT: 121 // character_z = CONSTANT: 122 // clear_A_count = LABEL: 565 // clear_B_count = LABEL: 567 // clear_counter = LABEL: 568 // clear_spm = LABEL: 32 // cold_start = LABEL: 0 // count0 = CONSTANT: 0 // count1 = CONSTANT: 1 // count2 = CONSTANT: 2 // count3 = CONSTANT: 3 // count_resetport = CONSTANT: 2 // counters_read = LABEL: 592 // dcm_kick = CONSTANT: 128 // decimal0 = CONSTANT: 17 // decimal1 = CONSTANT: 18 // decimal2 = CONSTANT: 19 // decimal3 = CONSTANT: 20 // decimal4 = CONSTANT: 21 // decimal5 = CONSTANT: 22 // decimal6 = CONSTANT: 23 // decimal7 = CONSTANT: 24 // decimal8 = CONSTANT: 25 // decimal9 = CONSTANT: 26 // delay_1ms = LABEL: 427 // delay_1s = LABEL: 437 // delay_1us = LABEL: 418 // delay_1us_constant = CONSTANT: 11 // delay_20ms = LABEL: 432 // delay_40us = LABEL: 422 // disp_50MHz_Crystal = LABEL: 276 // disp_Counter = LABEL: 230 // disp_DCM_Oscillator = LABEL: 304 // disp_Frequency = LABEL: 211 // disp_Oscillator = LABEL: 310 // disp_PicoBlaze = LABEL: 192 // disp_Ring_Oscillator = LABEL: 334 // disp_SMA_input = LABEL: 256 // disp_digit = LABEL: 140 // disp_digits = LABEL: 78 // disp_menu = LABEL: 349 // disp_spaces = LABEL: 343 // disp_version = LABEL: 245 // div10_loop = LABEL: 169 // div10_restore = LABEL: 176 // div10_shifts = LABEL: 181 // divide_32bit_by_10 = LABEL: 156 // hz_digits = LABEL: 116 // hz_space = LABEL: 114 // int_to_BCD_loop = LABEL: 150 // integer_to_BCD = LABEL: 148 // khz_digits = LABEL: 97 // khz_space = LABEL: 95 // kick_loop = LABEL: 26 // normal_isr = LABEL: 572 // preserve_s0 = CONSTANT: 48 // preserve_s1 = CONSTANT: 49 // preserve_s2 = CONSTANT: 50 // preserve_s3 = CONSTANT: 51 // preserve_s4 = CONSTANT: 52 // preserve_s5 = CONSTANT: 53 // preserve_s6 = CONSTANT: 54 // preserve_s7 = CONSTANT: 55 // preserve_s8 = CONSTANT: 56 // preserve_s9 = CONSTANT: 57 // preserve_sA = CONSTANT: 58 // preserve_sB = CONSTANT: 59 // preserve_sC = CONSTANT: 60 // preserve_sD = CONSTANT: 61 // preserve_sE = CONSTANT: 62 // preserve_sF = CONSTANT: 63 // restore_reg = LABEL: 598 // ring_reset = CONSTANT: 64 // 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 // select_source = LABEL: 65 // set_line2 = LABEL: 537 // source_control_port = CONSTANT: 8 // source_sel0 = CONSTANT: 1 // source_sel1 = CONSTANT: 2 // status_port = CONSTANT: 128 // switch0 = CONSTANT: 1 // switch1 = CONSTANT: 2 // switch2 = CONSTANT: 4 // switch3 = CONSTANT: 8 // test_50M = LABEL: 49 // test_DCM = LABEL: 54 // test_Ring = LABEL: 59 // test_SMA = LABEL: 44 // wait_1ms = LABEL: 428 // wait_1s = LABEL: 438 // wait_1us = LABEL: 419 // wait_20ms = LABEL: 433 // wait_40us = LABEL: 423 // warm_start = LABEL: 36 // zero_test = LABEL: 136 /* Program Code */ // #1: ;KCPSM3 Program - FC_CTRL // #2: ; // #3: ;Frequency Generator Control // #4: ;Calculates and displays results on the 16x2 LCD display. // #5: ; // #6: ; // #7: ; Version : 1.12 // #8: ; Date : 28th February 2006 // #9: ; // #10: ; Ken Chapman // #11: ; Xilinx Ltd // #12: ; // #13: ; chapman@xilinx.com // #14: ; // #15: ; // #16: ; // #17: ;************************************************************************************** // #18: ;Port definitions // #19: ;************************************************************************************** // #20: ; // #21: CONSTANT(A_count0_port,0) ;32-bit A-counter (LSByte first) // #22: CONSTANT(A_count1_port,16) // #23: CONSTANT(A_count2_port,32) // #24: CONSTANT(A_count3_port,48) // #25: ; // #26: CONSTANT(B_count0_port,64) ;32-bit B-counter (LSByte first) // #27: CONSTANT(B_count1_port,80) // #28: CONSTANT(B_count2_port,96) // #29: CONSTANT(B_count3_port,112) // #30: ; // #31: CONSTANT(status_port,128) ;4 switches and counter status // #32: CONSTANT(switch0,1) ; Switches SW0 - bit0 // #33: CONSTANT(switch1,2) ; active High SW1 - bit1 // #34: CONSTANT(switch2,4) ; SW2 - bit2 // #35: CONSTANT(switch3,8) ; SW3 - bit3 // #36: CONSTANT(AB_switch,16) ; 0=A-count enabled 1=B-count enabled // #37: ; // #38: ; // #39: CONSTANT(count_resetport,2) ;Reset frequency counter controls // #40: CONSTANT(a_count_reset,1) ; A-count = bit0 // #41: CONSTANT(b_count_reset,2) ; B-count = bit1 // #42: ; // #43: CONSTANT(LED_port,1) ;8 simple LEDs - active high // #44: ; // #45: ; // #46: CONSTANT(source_control_port,8) ;Select and control test sources // #47: CONSTANT(source_sel0,1) ; 00 = SMA clock 01=50MHz // #48: CONSTANT(source_sel1,2) ; 10 = DCM Osc 11=Ring Osc // #49: CONSTANT(ring_reset,64) ; active High rest of ring osc - bit6 // #50: CONSTANT(dcm_kick,128) ; DCM kick start signal - bit7 // #51: ; // #52: ; // #53: ;LCD interface ports // #54: ; // #55: ;The master enable signal is not used by the LCD display itself // #56: ;but may be required to confirm that LCD communication is active. // #57: ;This is required on the Spartan-3E Starter Kit if the StrataFLASH // #58: ;is used because it shares the same data pins and conflicts must be avoided. // #59: ; // #60: CONSTANT(LCD_output_port,4) ;LCD character module output data and control // #61: CONSTANT(LCD_E,1) ; active High Enable E - bit0 // #62: CONSTANT(LCD_RW,2) ; Read=1 Write=0 RW - bit1 // #63: CONSTANT(LCD_RS,4) ; Instruction=0 Data=1 RS - bit2 // #64: CONSTANT(LCD_drive,8) ; Master enable (active High) - bit3 // #65: CONSTANT(LCD_DB4,16) ; 4-bit Data DB4 - bit4 // #66: CONSTANT(LCD_DB5,32) ; interface Data DB5 - bit5 // #67: CONSTANT(LCD_DB6,64) ; Data DB6 - bit6 // #68: CONSTANT(LCD_DB7,128) ; Data DB7 - bit7 // #69: ; // #70: ; // #71: CONSTANT(LCD_input_port,9) ;LCD character module input data // #72: CONSTANT(LCD_read_spare0,1) ; Spare bits - bit0 // #73: CONSTANT(LCD_read_spare1,2) ; are zero - bit1 // #74: CONSTANT(LCD_read_spare2,4) ; - bit2 // #75: CONSTANT(LCD_read_spare3,8) ; - bit3 // #76: CONSTANT(LCD_read_DB4,16) ; 4-bit Data DB4 - bit4 // #77: CONSTANT(LCD_read_DB5,32) ; interface Data DB5 - bit5 // #78: CONSTANT(LCD_read_DB6,64) ; Data DB6 - bit6 // #79: CONSTANT(LCD_read_DB7,128) ; Data DB7 - bit7 // #80: ; // #81: ; // #82: ; // #83: ;Special Register usage // #84: ; // #85: ; // #86: ; // #87: ;************************************************************************************** // #88: ;Scratch Pad Memory Locations // #89: ;************************************************************************************** // #90: ; // #91: ; // #92: CONSTANT(count0,0) ;last 32-bit counter value (LSByte first) // #93: CONSTANT(count1,1) // #94: CONSTANT(count2,2) // #95: CONSTANT(count3,3) // #96: ; // #97: CONSTANT(ISR_count,4) ;count number of interrupts for a clean start // #98: ; // #99: CONSTANT(decimal0,17) ;10 digit decimal value up to 4,294,967,295 // #100: CONSTANT(decimal1,18) // #101: CONSTANT(decimal2,19) // #102: CONSTANT(decimal3,20) // #103: CONSTANT(decimal4,21) // #104: CONSTANT(decimal5,22) // #105: CONSTANT(decimal6,23) // #106: CONSTANT(decimal7,24) // #107: CONSTANT(decimal8,25) // #108: CONSTANT(decimal9,26) // #109: ; // #110: ; // #111: ; // #112: CONSTANT(preserve_s0,48) ;place to save register contents // #113: CONSTANT(preserve_s1,49) // #114: CONSTANT(preserve_s2,50) // #115: CONSTANT(preserve_s3,51) // #116: CONSTANT(preserve_s4,52) // #117: CONSTANT(preserve_s5,53) // #118: CONSTANT(preserve_s6,54) // #119: CONSTANT(preserve_s7,55) // #120: CONSTANT(preserve_s8,56) // #121: CONSTANT(preserve_s9,57) // #122: CONSTANT(preserve_sA,58) // #123: CONSTANT(preserve_sB,59) // #124: CONSTANT(preserve_sC,60) // #125: CONSTANT(preserve_sD,61) // #126: CONSTANT(preserve_sE,62) // #127: CONSTANT(preserve_sF,63) // #128: ; // #129: ; // #130: ; // #131: ;************************************************************************************** // #132: ;Useful data constants // #133: ;************************************************************************************** // #134: ; // #135: ; // #136: ; // #137: ;Constant to define a software delay of 1us. This must be adjusted to reflect the // #138: ;clock applied to KCPSM3. Every instruction executes in 2 clock cycles making the // #139: ;calculation highly predictable. The '6' in the following equation even allows for // #140: ;'CALL delay_1us' instruction in the initiating code. // #141: ; // #142: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz // #143: ; // #144: ;Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex). // #145: ;For clock rates below 10MHz the value of 1 must be used and the operation will // #146: ;become lower than intended. // #147: ; // #148: CONSTANT(delay_1us_constant,11) // #149: ; // #150: ; // #151: ; // #152: ;ASCII table // #153: ; // #154: CONSTANT(character_a,97) // #155: CONSTANT(character_b,98) // #156: CONSTANT(character_c,99) // #157: CONSTANT(character_d,100) // #158: CONSTANT(character_e,101) // #159: CONSTANT(character_f,102) // #160: CONSTANT(character_g,103) // #161: CONSTANT(character_h,104) // #162: CONSTANT(character_i,105) // #163: CONSTANT(character_j,106) // #164: CONSTANT(character_k,107) // #165: CONSTANT(character_l,108) // #166: CONSTANT(character_m,109) // #167: CONSTANT(character_n,110) // #168: CONSTANT(character_o,111) // #169: CONSTANT(character_p,112) // #170: CONSTANT(character_q,113) // #171: CONSTANT(character_r,114) // #172: CONSTANT(character_s,115) // #173: CONSTANT(character_t,116) // #174: CONSTANT(character_u,117) // #175: CONSTANT(character_v,118) // #176: CONSTANT(character_w,119) // #177: CONSTANT(character_x,120) // #178: CONSTANT(character_y,121) // #179: CONSTANT(character_z,122) // #180: CONSTANT(character_A,65) // #181: CONSTANT(character_B,66) // #182: CONSTANT(character_C,67) // #183: CONSTANT(character_D,68) // #184: CONSTANT(character_E,69) // #185: CONSTANT(character_F,70) // #186: CONSTANT(character_G,71) // #187: CONSTANT(character_H,72) // #188: CONSTANT(character_I,73) // #189: CONSTANT(character_J,74) // #190: CONSTANT(character_K,75) // #191: CONSTANT(character_L,76) // #192: CONSTANT(character_M,77) // #193: CONSTANT(character_N,78) // #194: CONSTANT(character_O,79) // #195: CONSTANT(character_P,80) // #196: CONSTANT(character_Q,81) // #197: CONSTANT(character_R,82) // #198: CONSTANT(character_S,83) // #199: CONSTANT(character_T,84) // #200: CONSTANT(character_U,85) // #201: CONSTANT(character_V,86) // #202: CONSTANT(character_W,87) // #203: CONSTANT(character_X,88) // #204: CONSTANT(character_Y,89) // #205: CONSTANT(character_Z,90) // #206: CONSTANT(character_0,48) // #207: CONSTANT(character_1,49) // #208: CONSTANT(character_2,50) // #209: CONSTANT(character_3,51) // #210: CONSTANT(character_4,52) // #211: CONSTANT(character_5,53) // #212: CONSTANT(character_6,54) // #213: CONSTANT(character_7,55) // #214: CONSTANT(character_8,56) // #215: CONSTANT(character_9,57) // #216: CONSTANT(character_colon,58) // #217: CONSTANT(character_stop,46) // #218: CONSTANT(character_semi_colon,59) // #219: CONSTANT(character_minus,45) // #220: CONSTANT(character_divide,47) ;'/' // #221: CONSTANT(character_plus,43) // #222: CONSTANT(character_comma,44) // #223: CONSTANT(character_less_than,60) // #224: CONSTANT(character_greater_than,62) // #225: CONSTANT(character_equals,61) // #226: CONSTANT(character_space,32) // #227: CONSTANT(character_CR,13) ;carriage return // #228: CONSTANT(character_question,63) ;'?' // #229: CONSTANT(character_dollar,36) // #230: CONSTANT(character_exclaim,33) ;'!' // #231: CONSTANT(character_BS,8) ;Back Space command character // #232: ; // #233: ; // #234: ; // #235: ; // #236: ; // #237: ;************************************************************************************** // #238: ;Initialise the system // #239: ;************************************************************************************** // #240: ; // @000 #241: [cold_start] 301fd // @000 #241: CALL(LCD_reset) ;initialise LCD display 00000 // @001 #242: LOAD(s0,0) ;Turn off LEDs 2c001 // @002 #243: OUTPUT(s0,LED_port) // #244: ; // #245: ; // #246: ;Write welcome message to LCD display // #247: ; 00510 // @003 #248: LOAD(s5,16) ;Line 1 position 0 30213 // @004 #249: CALL(LCD_cursor) 300c0 // @005 #250: CALL(disp_PicoBlaze) ;Display 'PicoBlaze Inside' 301b5 // @006 #251: CALL(delay_1s) ;wait 3 seconds 301b5 // @007 #252: CALL(delay_1s) 301b5 // @008 #253: CALL(delay_1s) 00510 // @009 #254: LOAD(s5,16) ;Line 1 position 0 30213 // @00a #255: CALL(LCD_cursor) 300d3 // @00b #256: CALL(disp_Frequency) ;Display 'Frequency Counter V1.00' 00521 // @00c #257: LOAD(s5,33) ;Line 2 position 1 30213 // @00d #258: CALL(LCD_cursor) 300e6 // @00e #259: CALL(disp_Counter) 0052b // @00f #260: LOAD(s5,43) ;Line 2 position 11 30213 // @010 #261: CALL(LCD_cursor) 300f5 // @011 #262: CALL(disp_version) 301b5 // @012 #263: CALL(delay_1s) ;wait 5 seconds 301b5 // @013 #264: CALL(delay_1s) 301b5 // @014 #265: CALL(delay_1s) 301b5 // @015 #266: CALL(delay_1s) 301b5 // @016 #267: CALL(delay_1s) 3020e // @017 #268: CALL(LCD_clear) ;Clear display // #269: ; // #270: ;Kick start the DCM oscillator. // #271: ; Just requires a few cyles of activity // #272: ; 000ff // @018 #273: LOAD(s0,FF) 00100 // @019 #274: LOAD(s1,0) // @01a #275: [kick_loop] 2c108 // @01a #275: OUTPUT(s1,source_control_port) 0e180 // @01b #276: XOR(s1,dcm_kick) ;toggle kick start signal 1c001 // @01c #277: SUB(s0,1) 3541a // @01d #278: JUMP(NZ,kick_loop) // #279: ; // #280: ;clear all scratch pad memory locations // #281: ; 0013f // @01e #282: LOAD(s1,63) 00000 // @01f #283: LOAD(s0,0) // @020 #284: [clear_spm] 2f010 // @020 #284: STORE(s0,s1) 1c101 // @021 #285: SUB(s1,1) 35c20 // @022 #286: JUMP(NC,clear_spm) // #287: ; 3c001 // @023 #288: ENABLE(INTERRUPT) // #289: ; // #290: ;************************************************************************************** // #291: ;Main Program // #292: ;************************************************************************************** // #293: ; // #294: ;The task of the main program is just to read the most recent values from // #295: ;scratch pad memory and display them as fast as it can. // #296: ; // #297: ;It also reads the slide switches controls the selection of the source frequency to // #298: ;be measured. // #299: ; // @024 #300: [warm_start] 00521 // @024 #300: LOAD(s5,33) ;Line 2 position 1 30213 // @025 #301: CALL(LCD_cursor) 04f80 // @026 #302: INPUT(sF,status_port) ;select source based on switches 14f00 // @027 #303: COMPARE(sF,0) ;test for no switches active 0af0f // @028 #304: AND(sF,15) ;isolate switches 3542c // @029 #305: JUMP(NZ,test_SMA) 3015d // @02a #306: CALL(disp_menu) 34024 // @02b #307: JUMP(warm_start) // @02c #308: [test_SMA] 14f01 // @02c #308: COMPARE(sF,switch0) 35431 // @02d #309: JUMP(NZ,test_50M) 30100 // @02e #310: CALL(disp_SMA_input) 00f00 // @02f #311: LOAD(sF,0) 34041 // @030 #312: JUMP(select_source) // @031 #313: [test_50M] 14f02 // @031 #313: COMPARE(sF,switch1) 35436 // @032 #314: JUMP(NZ,test_DCM) 30114 // @033 #315: CALL(disp_50MHz_Crystal) 00f01 // @034 #316: LOAD(sF,1) 34041 // @035 #317: JUMP(select_source) // @036 #318: [test_DCM] 14f04 // @036 #318: COMPARE(sF,switch2) 3543b // @037 #319: JUMP(NZ,test_Ring) 30130 // @038 #320: CALL(disp_DCM_Oscillator) 00f02 // @039 #321: LOAD(sF,2) 34041 // @03a #322: JUMP(select_source) // @03b #323: [test_Ring] 14f08 // @03b #323: COMPARE(sF,switch3) 3503f // @03c #324: JUMP(Z,Ring_select) 3015d // @03d #325: CALL(disp_menu) ;more than one switch is set 34024 // @03e #326: JUMP(warm_start) // @03f #327: [Ring_select] 3014e // @03f #327: CALL(disp_Ring_Oscillator) 00f03 // @040 #328: LOAD(sF,3) // @041 #329: [select_source] 2cf08 // @041 #329: OUTPUT(sF,source_control_port) ;select source control // #330: ; // #331: ;Read the most recent values from display on LCD. // #332: ; // #333: ;Interrupts will be disabled during the reading of values to ensure a clean // #334: ;value is obtained when reading multi-byte values. // #335: ; // #336: ; // #337: ;Display the count value in the top right of the LCD display // #338: ;Up to 999,999,999 // #339: ; 3c000 // @042 #340: DISABLE(INTERRUPT) ;copy cycle count to register set [s5,s4,s3,s2] 06200 // @043 #341: FETCH(s2,count0) 06301 // @044 #342: FETCH(s3,count1) 06402 // @045 #343: FETCH(s4,count2) 06503 // @046 #344: FETCH(s5,count3) 3c001 // @047 #345: ENABLE(INTERRUPT) 30094 // @048 #346: CALL(integer_to_BCD) ;convert last 32-bit value to BCD digits 00510 // @049 #347: LOAD(s5,16) ;Line 1 position 0 30213 // @04a #348: CALL(LCD_cursor) 00619 // @04b #349: LOAD(s6,decimal8) ;up to 999,999,999 Hz 3004e // @04c #350: CALL(disp_digits) 34024 // @04d #351: JUMP(warm_start) // #352: ; // #353: ; // #354: ; // #355: ;************************************************************************************** // #356: ; Display frequency value on LCD display // #357: ;************************************************************************************** // #358: ; // #359: ; // #360: ;Display value on the LCD display at current position. // #361: ;The values to be displayed must be stored in scratch pad memory // #362: ;locations 'decimal0' to 'decimal9' which must be in ascending locations. // #363: ; // #364: ;The routing performs leading zero suppression and scales to Hz, KHz or MHz ranges. // #365: ; // #366: ;Registers used s0,s1,s4,s5,sE,sF // #367: ; // @04e #368: [disp_digits] 00fff // @04e #368: LOAD(sF,FF) ;set blanking flag 00e20 // @04f #369: LOAD(sE,character_space) ;scaling character for MHz, KHz or Hz 06519 // @050 #370: FETCH(s5,decimal8) ;100MHz digit 30088 // @051 #371: CALL(zero_test) 3008c // @052 #372: CALL(disp_digit) 06518 // @053 #373: FETCH(s5,decimal7) ;10MHz digit 30088 // @054 #374: CALL(zero_test) 3008c // @055 #375: CALL(disp_digit) 06517 // @056 #376: FETCH(s5,decimal6) ;1MHz digit 30088 // @057 #377: CALL(zero_test) 3008c // @058 #378: CALL(disp_digit) 14fff // @059 #379: COMPARE(sF,FF) ;check if any MHz were active 3505f // @05a #380: JUMP(Z,khz_space) 0052e // @05b #381: LOAD(s5,character_stop) 301d3 // @05c #382: CALL(LCD_write_data) 00e4d // @05d #383: LOAD(sE,character_M) 34061 // @05e #384: JUMP(khz_digits) // @05f #385: [khz_space] 00520 // @05f #385: LOAD(s5,character_space) 301d3 // @060 #386: CALL(LCD_write_data) // @061 #387: [khz_digits] 06516 // @061 #387: FETCH(s5,decimal5) ;100KHz digit 30088 // @062 #388: CALL(zero_test) 3008c // @063 #389: CALL(disp_digit) 06515 // @064 #390: FETCH(s5,decimal4) ;10KHz digit 30088 // @065 #391: CALL(zero_test) 3008c // @066 #392: CALL(disp_digit) 06514 // @067 #393: FETCH(s5,decimal3) ;1KHz digit 30088 // @068 #394: CALL(zero_test) 3008c // @069 #395: CALL(disp_digit) 14e4d // @06a #396: COMPARE(sE,character_M) ;check if any MHz were active 35072 // @06b #397: JUMP(Z,hz_space) 14fff // @06c #398: COMPARE(sF,FF) ;check if any KHz were active 35072 // @06d #399: JUMP(Z,hz_space) 0052e // @06e #400: LOAD(s5,character_stop) 301d3 // @06f #401: CALL(LCD_write_data) 00e4b // @070 #402: LOAD(sE,character_K) 34074 // @071 #403: JUMP(hz_digits) // @072 #404: [hz_space] 00520 // @072 #404: LOAD(s5,character_space) 301d3 // @073 #405: CALL(LCD_write_data) // @074 #406: [hz_digits] 06513 // @074 #406: FETCH(s5,decimal2) ;100KHz digit 30088 // @075 #407: CALL(zero_test) 3008c // @076 #408: CALL(disp_digit) 06512 // @077 #409: FETCH(s5,decimal1) ;10KHz digit 30088 // @078 #410: CALL(zero_test) 3008c // @079 #411: CALL(disp_digit) 06511 // @07a #412: FETCH(s5,decimal0) ;1KHz digit (always displayed) 18530 // @07b #413: ADD(s5,character_0) ;convert number to ASCII 301d3 // @07c #414: CALL(LCD_write_data) 00520 // @07d #415: LOAD(s5,character_space) 301d3 // @07e #416: CALL(LCD_write_data) 015e0 // @07f #417: LOAD(s5,sE) 301d3 // @080 #418: CALL(LCD_write_data) 00548 // @081 #419: LOAD(s5,character_H) 301d3 // @082 #420: CALL(LCD_write_data) 0057a // @083 #421: LOAD(s5,character_z) 301d3 // @084 #422: CALL(LCD_write_data) 00520 // @085 #423: LOAD(s5,character_space) ;ensure end of line is clear 301d3 // @086 #424: CALL(LCD_write_data) 2a000 // @087 #425: RETURN // #426: ; // #427: ;Check digit for zero. If not zero then clear // #428: ;blanking flag (sF=00) // @088 #429: [zero_test] 14500 // @088 #429: COMPARE(s5,0) 2b000 // @089 #430: RETURN(Z) 00f00 // @08a #431: LOAD(sF,0) 2a000 // @08b #432: RETURN // #433: ; // #434: ;Display single digit at current position // #435: ;or space if blanking (sF=FF) is active // #436: ; // @08c #437: [disp_digit] 14fff // @08c #437: COMPARE(sF,FF) 35091 // @08d #438: JUMP(Z,blank_digit) 18530 // @08e #439: ADD(s5,character_0) ;convert number to ASCII 301d3 // @08f #440: CALL(LCD_write_data) 2a000 // @090 #441: RETURN // @091 #442: [blank_digit] 00520 // @091 #442: LOAD(s5,character_space) 301d3 // @092 #443: CALL(LCD_write_data) 2a000 // @093 #444: RETURN // #445: ; // #446: ; // #447: ; // #448: ;************************************************************************************** // #449: ; 32-bit integer to BCD conversion // #450: ;************************************************************************************** // #451: ; // #452: ;Convert the 32 bit value in register set [s5,s4,s3,s2] // #453: ;into the BCD decimal equivalent located in the scratch pad memory // #454: ;locations 'decimal0' to 'decimal9' which must be in ascending locations. // #455: ; // #456: ;Each digit is formed in turn starting with the least significant. // #457: ; // #458: ;Registers used s0,s2,s3,s4,s5,s6,s7,s8,s9,sA,sB,sC,sD,sE,sF // #459: ; // @094 #460: [integer_to_BCD] 00e0a // @094 #460: LOAD(sE,10) ;10 digits to be formed from value upto 4294967295 00f11 // @095 #461: LOAD(sF,decimal0) ;pointer for LS-Digit // @096 #462: [int_to_BCD_loop] 3009c // @096 #462: CALL(divide_32bit_by_10) 2f1f0 // @097 #463: STORE(s1,sF) ;remainder becomes digit value 18f01 // @098 #464: ADD(sF,1) ;move to next most significant digit 1ce01 // @099 #465: SUB(sE,1) ;one less digit to compute 35496 // @09a #466: JUMP(NZ,int_to_BCD_loop) 2a000 // @09b #467: RETURN // #468: ; // #469: ;Divide 32-bit binary integer by 10 // #470: ; // #471: ;The value to be divided is held in register set [s5,s4,s3,s2] // #472: ;and this is where the result is returned to. // #473: ; // #474: ;At then end of the integer division the remainder in the range 0 to 9 // #475: ;will be in register s1. // #476: ; // #477: ;Registers used s0, s2,s3,s4,s5,s6,s7,s8,s9,sA,sB,sC,sD // #478: ; // @09c #479: [divide_32bit_by_10] 01a20 // @09c #479: LOAD(sA,s2) ;copy input value to set [sD,sC,sB,sA] 01b30 // @09d #480: LOAD(sB,s3) 01c40 // @09e #481: LOAD(sC,s4) 01d50 // @09f #482: LOAD(sD,s5) 00200 // @0a0 #483: LOAD(s2,0) ;clear result 00300 // @0a1 #484: LOAD(s3,0) 00400 // @0a2 #485: LOAD(s4,0) 00500 // @0a3 #486: LOAD(s5,0) 009a0 // @0a4 #487: LOAD(s9,A0) ;initialise '10' value into msb's of set [s9,s8,s7,s6] 00800 // @0a5 #488: LOAD(s8,0) 00700 // @0a6 #489: LOAD(s7,0) 00600 // @0a7 #490: LOAD(s6,0) 0001d // @0a8 #491: LOAD(s0,29) ;29 subtract and shift iterations to be performed // @0a9 #492: [div10_loop] 1da60 // @0a9 #492: SUB(sA,s6) ;perform 32-bit subtract [sD,sC,sB,sA]-[s9,s8,s7,s6] 1fb70 // @0aa #493: SUBCY(sB,s7) 1fc80 // @0ab #494: SUBCY(sC,s8) 1fd90 // @0ac #495: SUBCY(sD,s9) 358b0 // @0ad #496: JUMP(C,div10_restore) 20207 // @0ae #497: SL1(s2) ;shift '1' into result 340b5 // @0af #498: JUMP(div10_shifts) // @0b0 #499: [div10_restore] 19a60 // @0b0 #499: ADD(sA,s6) ;perform 32-bit addition [sD,sC,sB,sA]+[s9,s8,s7,s6] 1bb70 // @0b1 #500: ADDCY(sB,s7) 1bc80 // @0b2 #501: ADDCY(sC,s8) 1bd90 // @0b3 #502: ADDCY(sD,s9) 20206 // @0b4 #503: SL0(s2) ;shift '0' into result // @0b5 #504: [div10_shifts] 20300 // @0b5 #504: SLA(s3) ;complete 32-bit shift left 20400 // @0b6 #505: SLA(s4) 20500 // @0b7 #506: SLA(s5) 2090e // @0b8 #507: SR0(s9) ;divide '10' value by 2 (shift right 1 place) 20808 // @0b9 #508: SRA(s8) 20708 // @0ba #509: SRA(s7) 20608 // @0bb #510: SRA(s6) 1c001 // @0bc #511: SUB(s0,1) ;count iterations 354a9 // @0bd #512: JUMP(NZ,div10_loop) 011a0 // @0be #513: LOAD(s1,sA) ;remainder of division 2a000 // @0bf #514: RETURN // #515: ; // #516: ; // #517: ; // #518: ; // #519: ;************************************************************************************** // #520: ;LCD text messages // #521: ;************************************************************************************** // #522: ; // #523: ; // #524: ;Display 'PicoBlaze' on LCD at current cursor position // #525: ; // #526: ; // @0c0 #527: [disp_PicoBlaze] 00550 // @0c0 #527: LOAD(s5,character_P) 301d3 // @0c1 #528: CALL(LCD_write_data) 00569 // @0c2 #529: LOAD(s5,character_i) 301d3 // @0c3 #530: CALL(LCD_write_data) 00563 // @0c4 #531: LOAD(s5,character_c) 301d3 // @0c5 #532: CALL(LCD_write_data) 0056f // @0c6 #533: LOAD(s5,character_o) 301d3 // @0c7 #534: CALL(LCD_write_data) 00542 // @0c8 #535: LOAD(s5,character_B) 301d3 // @0c9 #536: CALL(LCD_write_data) 0056c // @0ca #537: LOAD(s5,character_l) 301d3 // @0cb #538: CALL(LCD_write_data) 00561 // @0cc #539: LOAD(s5,character_a) 301d3 // @0cd #540: CALL(LCD_write_data) 0057a // @0ce #541: LOAD(s5,character_z) 301d3 // @0cf #542: CALL(LCD_write_data) 00565 // @0d0 #543: LOAD(s5,character_e) 301d3 // @0d1 #544: CALL(LCD_write_data) 2a000 // @0d2 #545: RETURN // #546: ; // #547: ; // #548: ;Display 'Frequency' on LCD at current cursor position // #549: ; // #550: ; // @0d3 #551: [disp_Frequency] 00546 // @0d3 #551: LOAD(s5,character_F) 301d3 // @0d4 #552: CALL(LCD_write_data) 00572 // @0d5 #553: LOAD(s5,character_r) 301d3 // @0d6 #554: CALL(LCD_write_data) 00565 // @0d7 #555: LOAD(s5,character_e) 301d3 // @0d8 #556: CALL(LCD_write_data) 00571 // @0d9 #557: LOAD(s5,character_q) 301d3 // @0da #558: CALL(LCD_write_data) 00575 // @0db #559: LOAD(s5,character_u) 301d3 // @0dc #560: CALL(LCD_write_data) 00565 // @0dd #561: LOAD(s5,character_e) 301d3 // @0de #562: CALL(LCD_write_data) 0056e // @0df #563: LOAD(s5,character_n) 301d3 // @0e0 #564: CALL(LCD_write_data) 00563 // @0e1 #565: LOAD(s5,character_c) 301d3 // @0e2 #566: CALL(LCD_write_data) 00579 // @0e3 #567: LOAD(s5,character_y) 301d3 // @0e4 #568: CALL(LCD_write_data) 2a000 // @0e5 #569: RETURN // #570: ; // #571: ; // #572: ;Display 'Counter' on LCD at current cursor position // #573: ; // #574: ; // @0e6 #575: [disp_Counter] 00543 // @0e6 #575: LOAD(s5,character_C) 301d3 // @0e7 #576: CALL(LCD_write_data) 0056f // @0e8 #577: LOAD(s5,character_o) 301d3 // @0e9 #578: CALL(LCD_write_data) 00575 // @0ea #579: LOAD(s5,character_u) 301d3 // @0eb #580: CALL(LCD_write_data) 0056e // @0ec #581: LOAD(s5,character_n) 301d3 // @0ed #582: CALL(LCD_write_data) 00574 // @0ee #583: LOAD(s5,character_t) 301d3 // @0ef #584: CALL(LCD_write_data) 00565 // @0f0 #585: LOAD(s5,character_e) 301d3 // @0f1 #586: CALL(LCD_write_data) 00572 // @0f2 #587: LOAD(s5,character_r) 301d3 // @0f3 #588: CALL(LCD_write_data) 2a000 // @0f4 #589: RETURN // #590: ; // #591: ;Display version number on LCD at current cursor position // #592: ; // #593: ; // @0f5 #594: [disp_version] 00576 // @0f5 #594: LOAD(s5,character_v) 301d3 // @0f6 #595: CALL(LCD_write_data) 00531 // @0f7 #596: LOAD(s5,character_1) 301d3 // @0f8 #597: CALL(LCD_write_data) 0052e // @0f9 #598: LOAD(s5,character_stop) 301d3 // @0fa #599: CALL(LCD_write_data) 00530 // @0fb #600: LOAD(s5,character_0) 301d3 // @0fc #601: CALL(LCD_write_data) 00530 // @0fd #602: LOAD(s5,character_0) 301d3 // @0fe #603: CALL(LCD_write_data) 2a000 // @0ff #604: RETURN // #605: ; // #606: ; // #607: ;Display 'SMA input' at current cursor position // #608: ; // #609: ; // @100 #610: [disp_SMA_input] 00553 // @100 #610: LOAD(s5,character_S) 301d3 // @101 #611: CALL(LCD_write_data) 0054d // @102 #612: LOAD(s5,character_M) 301d3 // @103 #613: CALL(LCD_write_data) 00541 // @104 #614: LOAD(s5,character_A) 301d3 // @105 #615: CALL(LCD_write_data) 00520 // @106 #616: LOAD(s5,character_space) 301d3 // @107 #617: CALL(LCD_write_data) 00569 // @108 #618: LOAD(s5,character_i) 301d3 // @109 #619: CALL(LCD_write_data) 0056e // @10a #620: LOAD(s5,character_n) 301d3 // @10b #621: CALL(LCD_write_data) 00570 // @10c #622: LOAD(s5,character_p) 301d3 // @10d #623: CALL(LCD_write_data) 00575 // @10e #624: LOAD(s5,character_u) 301d3 // @10f #625: CALL(LCD_write_data) 00574 // @110 #626: LOAD(s5,character_t) 301d3 // @111 #627: CALL(LCD_write_data) 00f06 // @112 #628: LOAD(sF,6) 34157 // @113 #629: JUMP(disp_spaces) // #630: ; // #631: ; // #632: ; // #633: ;Display '50MHz Crystal' at current cursor position // #634: ; // #635: ; // @114 #636: [disp_50MHz_Crystal] 00535 // @114 #636: LOAD(s5,character_5) 301d3 // @115 #637: CALL(LCD_write_data) 00530 // @116 #638: LOAD(s5,character_0) 301d3 // @117 #639: CALL(LCD_write_data) 0054d // @118 #640: LOAD(s5,character_M) 301d3 // @119 #641: CALL(LCD_write_data) 00548 // @11a #642: LOAD(s5,character_H) 301d3 // @11b #643: CALL(LCD_write_data) 0057a // @11c #644: LOAD(s5,character_z) 301d3 // @11d #645: CALL(LCD_write_data) 00520 // @11e #646: LOAD(s5,character_space) 301d3 // @11f #647: CALL(LCD_write_data) 00543 // @120 #648: LOAD(s5,character_C) 301d3 // @121 #649: CALL(LCD_write_data) 00572 // @122 #650: LOAD(s5,character_r) 301d3 // @123 #651: CALL(LCD_write_data) 00579 // @124 #652: LOAD(s5,character_y) 301d3 // @125 #653: CALL(LCD_write_data) 00573 // @126 #654: LOAD(s5,character_s) 301d3 // @127 #655: CALL(LCD_write_data) 00574 // @128 #656: LOAD(s5,character_t) 301d3 // @129 #657: CALL(LCD_write_data) 00561 // @12a #658: LOAD(s5,character_a) 301d3 // @12b #659: CALL(LCD_write_data) 0056c // @12c #660: LOAD(s5,character_l) 301d3 // @12d #661: CALL(LCD_write_data) 00f02 // @12e #662: LOAD(sF,2) 34157 // @12f #663: JUMP(disp_spaces) // #664: ; // #665: ; // #666: ; // #667: ;Display 'DCM oscillator' at current cursor position // #668: ; // #669: ; // @130 #670: [disp_DCM_Oscillator] 00544 // @130 #670: LOAD(s5,character_D) 301d3 // @131 #671: CALL(LCD_write_data) 00543 // @132 #672: LOAD(s5,character_C) 301d3 // @133 #673: CALL(LCD_write_data) 0054d // @134 #674: LOAD(s5,character_M) 301d3 // @135 #675: CALL(LCD_write_data) // @136 #676: [disp_Oscillator] 00520 // @136 #676: LOAD(s5,character_space) 301d3 // @137 #677: CALL(LCD_write_data) 0054f // @138 #678: LOAD(s5,character_O) 301d3 // @139 #679: CALL(LCD_write_data) 00573 // @13a #680: LOAD(s5,character_s) 301d3 // @13b #681: CALL(LCD_write_data) 00563 // @13c #682: LOAD(s5,character_c) 301d3 // @13d #683: CALL(LCD_write_data) 00569 // @13e #684: LOAD(s5,character_i) 301d3 // @13f #685: CALL(LCD_write_data) 0056c // @140 #686: LOAD(s5,character_l) 301d3 // @141 #687: CALL(LCD_write_data) 301d3 // @142 #688: CALL(LCD_write_data) 00561 // @143 #689: LOAD(s5,character_a) 301d3 // @144 #690: CALL(LCD_write_data) 00574 // @145 #691: LOAD(s5,character_t) 301d3 // @146 #692: CALL(LCD_write_data) 0056f // @147 #693: LOAD(s5,character_o) 301d3 // @148 #694: CALL(LCD_write_data) 00572 // @149 #695: LOAD(s5,character_r) 301d3 // @14a #696: CALL(LCD_write_data) 00520 // @14b #697: LOAD(s5,character_space) 301d3 // @14c #698: CALL(LCD_write_data) 2a000 // @14d #699: RETURN // #700: ; // #701: ; // #702: ; // #703: ;Display 'Ring oscillator' at current cursor position // #704: ; // #705: ; // @14e #706: [disp_Ring_Oscillator] 00552 // @14e #706: LOAD(s5,character_R) 301d3 // @14f #707: CALL(LCD_write_data) 00569 // @150 #708: LOAD(s5,character_i) 301d3 // @151 #709: CALL(LCD_write_data) 0056e // @152 #710: LOAD(s5,character_n) 301d3 // @153 #711: CALL(LCD_write_data) 00567 // @154 #712: LOAD(s5,character_g) 301d3 // @155 #713: CALL(LCD_write_data) 34136 // @156 #714: JUMP(disp_Oscillator) // #715: ; // #716: ; // #717: ;Display spaces at current cursor position // #718: ;Number of spaces to be specified in register sF // #719: ; // @157 #720: [disp_spaces] 14f00 // @157 #720: COMPARE(sF,0) 2b000 // @158 #721: RETURN(Z) 00520 // @159 #722: LOAD(s5,character_space) 301d3 // @15a #723: CALL(LCD_write_data) 1cf01 // @15b #724: SUB(sF,1) 34157 // @15c #725: JUMP(disp_spaces) // #726: ; // #727: ;Display switch setting menu on entire display. // #728: ; // @15d #729: [disp_menu] 00510 // @15d #729: LOAD(s5,16) ;Line 1 position 0 30213 // @15e #730: CALL(LCD_cursor) 00552 // @15f #731: LOAD(s5,character_R) 301d3 // @160 #732: CALL(LCD_write_data) 00569 // @161 #733: LOAD(s5,character_i) 301d3 // @162 #734: CALL(LCD_write_data) 0056e // @163 #735: LOAD(s5,character_n) 301d3 // @164 #736: CALL(LCD_write_data) 00567 // @165 #737: LOAD(s5,character_g) 301d3 // @166 #738: CALL(LCD_write_data) 00520 // @167 #739: LOAD(s5,character_space) 301d3 // @168 #740: CALL(LCD_write_data) 00544 // @169 #741: LOAD(s5,character_D) 301d3 // @16a #742: CALL(LCD_write_data) 00543 // @16b #743: LOAD(s5,character_C) 301d3 // @16c #744: CALL(LCD_write_data) 0054d // @16d #745: LOAD(s5,character_M) 301d3 // @16e #746: CALL(LCD_write_data) 00520 // @16f #747: LOAD(s5,character_space) 301d3 // @170 #748: CALL(LCD_write_data) 00535 // @171 #749: LOAD(s5,character_5) 301d3 // @172 #750: CALL(LCD_write_data) 00530 // @173 #751: LOAD(s5,character_0) 301d3 // @174 #752: CALL(LCD_write_data) 0054d // @175 #753: LOAD(s5,character_M) 301d3 // @176 #754: CALL(LCD_write_data) 00520 // @177 #755: LOAD(s5,character_space) 301d3 // @178 #756: CALL(LCD_write_data) 00553 // @179 #757: LOAD(s5,character_S) 301d3 // @17a #758: CALL(LCD_write_data) 0054d // @17b #759: LOAD(s5,character_M) 301d3 // @17c #760: CALL(LCD_write_data) 00541 // @17d #761: LOAD(s5,character_A) 301d3 // @17e #762: CALL(LCD_write_data) 00520 // @17f #763: LOAD(s5,32) ;Line 2 position 0 30213 // @180 #764: CALL(LCD_cursor) 00520 // @181 #765: LOAD(s5,character_space) 301d3 // @182 #766: CALL(LCD_write_data) 00553 // @183 #767: LOAD(s5,character_S) 301d3 // @184 #768: CALL(LCD_write_data) 00557 // @185 #769: LOAD(s5,character_W) 301d3 // @186 #770: CALL(LCD_write_data) 00533 // @187 #771: LOAD(s5,character_3) 301d3 // @188 #772: CALL(LCD_write_data) 00520 // @189 #773: LOAD(s5,character_space) 301d3 // @18a #774: CALL(LCD_write_data) 00553 // @18b #775: LOAD(s5,character_S) 301d3 // @18c #776: CALL(LCD_write_data) 00557 // @18d #777: LOAD(s5,character_W) 301d3 // @18e #778: CALL(LCD_write_data) 00532 // @18f #779: LOAD(s5,character_2) 301d3 // @190 #780: CALL(LCD_write_data) 00520 // @191 #781: LOAD(s5,character_space) 301d3 // @192 #782: CALL(LCD_write_data) 00553 // @193 #783: LOAD(s5,character_S) 301d3 // @194 #784: CALL(LCD_write_data) 00557 // @195 #785: LOAD(s5,character_W) 301d3 // @196 #786: CALL(LCD_write_data) 00531 // @197 #787: LOAD(s5,character_1) 301d3 // @198 #788: CALL(LCD_write_data) 00520 // @199 #789: LOAD(s5,character_space) 301d3 // @19a #790: CALL(LCD_write_data) 00553 // @19b #791: LOAD(s5,character_S) 301d3 // @19c #792: CALL(LCD_write_data) 00557 // @19d #793: LOAD(s5,character_W) 301d3 // @19e #794: CALL(LCD_write_data) 00530 // @19f #795: LOAD(s5,character_0) 301d3 // @1a0 #796: CALL(LCD_write_data) 2a000 // @1a1 #797: RETURN // #798: ; // #799: ; // #800: ; // #801: ; // #802: ;************************************************************************************** // #803: ;Software delay routines // #804: ;************************************************************************************** // #805: ; // #806: ; // #807: ; // #808: ;Delay of 1us. // #809: ; // #810: ;Constant value defines reflects the clock applied to KCPSM3. Every instruction // #811: ;executes in 2 clock cycles making the calculation highly predictable. The '6' in // #812: ;the following equation even allows for 'CALL delay_1us' instruction in the initiating code. // #813: ; // #814: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz // #815: ; // #816: ;Registers used s0 // #817: ; // @1a2 #818: [delay_1us] 0000b // @1a2 #818: LOAD(s0,delay_1us_constant) // @1a3 #819: [wait_1us] 1c001 // @1a3 #819: SUB(s0,1) 355a3 // @1a4 #820: JUMP(NZ,wait_1us) 2a000 // @1a5 #821: RETURN // #822: ; // #823: ;Delay of 40us. // #824: ; // #825: ;Registers used s0, s1 // #826: ; // @1a6 #827: [delay_40us] 00128 // @1a6 #827: LOAD(s1,40) ;40 x 1us = 40us // @1a7 #828: [wait_40us] 301a2 // @1a7 #828: CALL(delay_1us) 1c101 // @1a8 #829: SUB(s1,1) 355a7 // @1a9 #830: JUMP(NZ,wait_40us) 2a000 // @1aa #831: RETURN // #832: ; // #833: ; // #834: ;Delay of 1ms. // #835: ; // #836: ;Registers used s0, s1, s2 // #837: ; // @1ab #838: [delay_1ms] 00219 // @1ab #838: LOAD(s2,25) ;25 x 40us = 1ms // @1ac #839: [wait_1ms] 301a6 // @1ac #839: CALL(delay_40us) 1c201 // @1ad #840: SUB(s2,1) 355ac // @1ae #841: JUMP(NZ,wait_1ms) 2a000 // @1af #842: RETURN // #843: ; // #844: ;Delay of 20ms. // #845: ; // #846: ;Delay of 20ms used during initialisation. // #847: ; // #848: ;Registers used s0, s1, s2, s3 // #849: ; // @1b0 #850: [delay_20ms] 00314 // @1b0 #850: LOAD(s3,20) ;20 x 1ms = 20ms // @1b1 #851: [wait_20ms] 301ab // @1b1 #851: CALL(delay_1ms) 1c301 // @1b2 #852: SUB(s3,1) 355b1 // @1b3 #853: JUMP(NZ,wait_20ms) 2a000 // @1b4 #854: RETURN // #855: ; // #856: ;Delay of approximately 1 second. // #857: ; // #858: ;Registers used s0, s1, s2, s3, s4 // #859: ; // @1b5 #860: [delay_1s] 00432 // @1b5 #860: LOAD(s4,50) ;50 x 20ms = 1000ms // @1b6 #861: [wait_1s] 301b0 // @1b6 #861: CALL(delay_20ms) 1c401 // @1b7 #862: SUB(s4,1) 355b6 // @1b8 #863: JUMP(NZ,wait_1s) 2a000 // @1b9 #864: RETURN // #865: ; // #866: ; // #867: ; // #868: ;************************************************************************************** // #869: ;LCD Character Module Routines // #870: ;************************************************************************************** // #871: ; // #872: ;LCD module is a 16 character by 2 line display but all displays are very similar // #873: ;The 4-wire data interface will be used (DB4 to DB7). // #874: ; // #875: ;The LCD modules are relatively slow and software delay loops are used to slow down // #876: ;KCPSM3 adequately for the LCD to communicate. The delay routines are provided in // #877: ;a different section (see above in this case). // #878: ; // #879: ; // #880: ;Pulse LCD enable signal 'E' high for greater than 230ns (1us is used). // #881: ; // #882: ;Register s4 should define the current state of the LCD output port. // #883: ; // #884: ;Registers used s0, s4 // #885: ; // @1ba #886: [LCD_pulse_E] 0e401 // @1ba #886: XOR(s4,LCD_E) ;E=1 2c404 // @1bb #887: OUTPUT(s4,LCD_output_port) 301a2 // @1bc #888: CALL(delay_1us) 0e401 // @1bd #889: XOR(s4,LCD_E) ;E=0 2c404 // @1be #890: OUTPUT(s4,LCD_output_port) 2a000 // @1bf #891: RETURN // #892: ; // #893: ;Write 4-bit instruction to LCD display. // #894: ; // #895: ;The 4-bit instruction should be provided in the upper 4-bits of register s4. // #896: ;Note that this routine does not release the master enable but as it is only // #897: ;used during initialisation and as part of the 8-bit instruction write it // #898: ;should be acceptable. // #899: ; // #900: ;Registers used s4 // #901: ; // @1c0 #902: [LCD_write_inst4] 0a4f8 // @1c0 #902: AND(s4,F8) ;Enable=1 RS=0 Instruction, RW=0 Write, E=0 2c404 // @1c1 #903: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 301ba // @1c2 #904: CALL(LCD_pulse_E) 2a000 // @1c3 #905: RETURN // #906: ; // #907: ; // #908: ;Write 8-bit instruction to LCD display. // #909: ; // #910: ;The 8-bit instruction should be provided in register s5. // #911: ;Instructions are written using the following sequence // #912: ; Upper nibble // #913: ; wait >1us // #914: ; Lower nibble // #915: ; wait >40us // #916: ; // #917: ;Registers used s0, s1, s4, s5 // #918: ; // @1c4 #919: [LCD_write_inst8] 01450 // @1c4 #919: LOAD(s4,s5) 0a4f0 // @1c5 #920: AND(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 0c408 // @1c6 #921: OR(s4,LCD_drive) ;Enable=1 301c0 // @1c7 #922: CALL(LCD_write_inst4) ;write upper nibble 301a2 // @1c8 #923: CALL(delay_1us) ;wait >1us 01450 // @1c9 #924: LOAD(s4,s5) ;select lower nibble with 20407 // @1ca #925: SL1(s4) ;Enable=1 20406 // @1cb #926: SL0(s4) ;RS=0 Instruction 20406 // @1cc #927: SL0(s4) ;RW=0 Write 20406 // @1cd #928: SL0(s4) ;E=0 301c0 // @1ce #929: CALL(LCD_write_inst4) ;write lower nibble 301a6 // @1cf #930: CALL(delay_40us) ;wait >40us 004f0 // @1d0 #931: LOAD(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 2c404 // @1d1 #932: OUTPUT(s4,LCD_output_port) ;Release master enable 2a000 // @1d2 #933: RETURN // #934: ; // #935: ; // #936: ; // #937: ;Write 8-bit data to LCD display. // #938: ; // #939: ;The 8-bit data should be provided in register s5. // #940: ;Data bytes are written using the following sequence // #941: ; Upper nibble // #942: ; wait >1us // #943: ; Lower nibble // #944: ; wait >40us // #945: ; // #946: ;Registers used s0, s1, s4, s5 // #947: ; // @1d3 #948: [LCD_write_data] 01450 // @1d3 #948: LOAD(s4,s5) 0a4f0 // @1d4 #949: AND(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 0c40c // @1d5 #950: OR(s4,12) ;Enable=1 RS=1 Data, RW=0 Write, E=0 2c404 // @1d6 #951: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 301ba // @1d7 #952: CALL(LCD_pulse_E) ;write upper nibble 301a2 // @1d8 #953: CALL(delay_1us) ;wait >1us 01450 // @1d9 #954: LOAD(s4,s5) ;select lower nibble with 20407 // @1da #955: SL1(s4) ;Enable=1 20407 // @1db #956: SL1(s4) ;RS=1 Data 20406 // @1dc #957: SL0(s4) ;RW=0 Write 20406 // @1dd #958: SL0(s4) ;E=0 2c404 // @1de #959: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 301ba // @1df #960: CALL(LCD_pulse_E) ;write lower nibble 301a6 // @1e0 #961: CALL(delay_40us) ;wait >40us 004f0 // @1e1 #962: LOAD(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 2c404 // @1e2 #963: OUTPUT(s4,LCD_output_port) ;Release master enable 2a000 // @1e3 #964: RETURN // #965: ; // #966: ; // #967: ; // #968: ; // #969: ;Read 8-bit data from LCD display. // #970: ; // #971: ;The 8-bit data will be read from the current LCD memory address // #972: ;and will be returned in register s5. // #973: ;It is advisable to set the LCD address (cursor position) before // #974: ;using the data read for the first time otherwise the display may // #975: ;generate invalid data on the first read. // #976: ; // #977: ;Data bytes are read using the following sequence // #978: ; Upper nibble // #979: ; wait >1us // #980: ; Lower nibble // #981: ; wait >40us // #982: ; // #983: ;Registers used s0, s1, s4, s5 // #984: ; // @1e4 #985: [LCD_read_data8] 0040e // @1e4 #985: LOAD(s4,14) ;Enable=1 RS=1 Data, RW=1 Read, E=0 2c404 // @1e5 #986: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 0e401 // @1e6 #987: XOR(s4,LCD_E) ;E=1 2c404 // @1e7 #988: OUTPUT(s4,LCD_output_port) 301a2 // @1e8 #989: CALL(delay_1us) ;wait >260ns to access data 04509 // @1e9 #990: INPUT(s5,LCD_input_port) ;read upper nibble 0e401 // @1ea #991: XOR(s4,LCD_E) ;E=0 2c404 // @1eb #992: OUTPUT(s4,LCD_output_port) 301a2 // @1ec #993: CALL(delay_1us) ;wait >1us 0e401 // @1ed #994: XOR(s4,LCD_E) ;E=1 2c404 // @1ee #995: OUTPUT(s4,LCD_output_port) 301a2 // @1ef #996: CALL(delay_1us) ;wait >260ns to access data 04009 // @1f0 #997: INPUT(s0,LCD_input_port) ;read lower nibble 0e401 // @1f1 #998: XOR(s4,LCD_E) ;E=0 2c404 // @1f2 #999: OUTPUT(s4,LCD_output_port) 0a5f0 // @1f3 #1000: AND(s5,F0) ;merge upper and lower nibbles 2000e // @1f4 #1001: SR0(s0) 2000e // @1f5 #1002: SR0(s0) 2000e // @1f6 #1003: SR0(s0) 2000e // @1f7 #1004: SR0(s0) 0d500 // @1f8 #1005: OR(s5,s0) 00404 // @1f9 #1006: LOAD(s4,4) ;Enable=0 RS=1 Data, RW=0 Write, E=0 2c404 // @1fa #1007: OUTPUT(s4,LCD_output_port) ;Stop reading 5V device and release master enable 301a6 // @1fb #1008: CALL(delay_40us) ;wait >40us 2a000 // @1fc #1009: RETURN // #1010: ; // #1011: ; // #1012: ;Reset and initialise display to communicate using 4-bit data mode // #1013: ;Includes routine to clear the display. // #1014: ; // #1015: ;Requires the 4-bit instructions 3,3,3,2 to be sent with suitable delays // #1016: ;following by the 8-bit instructions to set up the display. // #1017: ; // #1018: ; 28 = '001' Function set, '0' 4-bit mode, '1' 2-line, '0' 5x7 dot matrix, 'xx' // #1019: ; 06 = '000001' Entry mode, '1' increment, '0' no display shift // #1020: ; 0C = '00001' Display control, '1' display on, '0' cursor off, '0' cursor blink off // #1021: ; 01 = '00000001' Display clear // #1022: ; // #1023: ;Registers used s0, s1, s2, s3, s4 // #1024: ; // @1fd #1025: [LCD_reset] 301b0 // @1fd #1025: CALL(delay_20ms) ;wait more that 15ms for display to be ready 00430 // @1fe #1026: LOAD(s4,48) 301c0 // @1ff #1027: CALL(LCD_write_inst4) ;send '3' 301b0 // @200 #1028: CALL(delay_20ms) ;wait >4.1ms 301c0 // @201 #1029: CALL(LCD_write_inst4) ;send '3' 301ab // @202 #1030: CALL(delay_1ms) ;wait >100us 301c0 // @203 #1031: CALL(LCD_write_inst4) ;send '3' 301a6 // @204 #1032: CALL(delay_40us) ;wait >40us 00420 // @205 #1033: LOAD(s4,32) 301c0 // @206 #1034: CALL(LCD_write_inst4) ;send '2' 301a6 // @207 #1035: CALL(delay_40us) ;wait >40us 00528 // @208 #1036: LOAD(s5,40) ;Function set 301c4 // @209 #1037: CALL(LCD_write_inst8) 00506 // @20a #1038: LOAD(s5,6) ;Entry mode 301c4 // @20b #1039: CALL(LCD_write_inst8) 0050c // @20c #1040: LOAD(s5,12) ;Display control 301c4 // @20d #1041: CALL(LCD_write_inst8) // @20e #1042: [LCD_clear] 00501 // @20e #1042: LOAD(s5,1) ;Display clear 301c4 // @20f #1043: CALL(LCD_write_inst8) 301ab // @210 #1044: CALL(delay_1ms) ;wait >1.64ms for display to clear 301ab // @211 #1045: CALL(delay_1ms) 2a000 // @212 #1046: RETURN // #1047: ; // #1048: ;Position the cursor ready for characters to be written. // #1049: ;The display is formed of 2 lines of 16 characters and each // #1050: ;position has a corresponding address as indicated below. // #1051: ; // #1052: ; Character position // #1053: ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // #1054: ; // #1055: ; Line 1 - 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F // #1056: ; Line 2 - C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF // #1057: ; // #1058: ;This routine will set the cursor position using the value provided // #1059: ;in register s5. The upper nibble will define the line and the lower // #1060: ;nibble the character position on the line. // #1061: ; Example s5 = 2B will position the cursor on line 2 position 11 // #1062: ; // #1063: ;Registers used s0, s1, s2, s3, s4 // #1064: ; // @213 #1065: [LCD_cursor] 12510 // @213 #1065: TEST(s5,16) ;test for line 1 35219 // @214 #1066: JUMP(Z,set_line2) 0a50f // @215 #1067: AND(s5,15) ;make address in range 80 to 8F for line 1 0c580 // @216 #1068: OR(s5,128) 301c4 // @217 #1069: CALL(LCD_write_inst8) ;instruction write to set cursor 2a000 // @218 #1070: RETURN // @219 #1071: [set_line2] 0a50f // @219 #1071: AND(s5,15) ;make address in range C0 to CF for line 2 0c5c0 // @21a #1072: OR(s5,C0) 301c4 // @21b #1073: CALL(LCD_write_inst8) ;instruction write to set cursor 2a000 // @21c #1074: RETURN // #1075: ; // #1076: ; // #1077: ; // #1078: ;************************************************************************************** // #1079: ;Interrupt Service Routine // #1080: ;************************************************************************************** // #1081: ; // #1082: ; // #1083: ;Each interrupt means that there is a new count value to be read. // #1084: ;However the first 4 interrupts are ignored other than to clear the counter to // #1085: ;ensure that even the first reading is for one complete period. // #1086: ; // #1087: ;After reading the active counter, all calculations are performed and values stored // #1088: ;in scratch pad memory are updated to reflect the new values. // #1089: ; // #1090: ;Registers are preserved and restored by the ISR so main program is unaffected. // #1091: ; // @21d #1092: [ISR] 2e030 // @21d #1092: STORE(s0,preserve_s0) ;preserve registers 2e131 // @21e #1093: STORE(s1,preserve_s1) 2e232 // @21f #1094: STORE(s2,preserve_s2) 2e333 // @220 #1095: STORE(s3,preserve_s3) 2e434 // @221 #1096: STORE(s4,preserve_s4) 2e535 // @222 #1097: STORE(s5,preserve_s5) 2e636 // @223 #1098: STORE(s6,preserve_s6) 2e737 // @224 #1099: STORE(s7,preserve_s7) 2e838 // @225 #1100: STORE(s8,preserve_s8) 2e939 // @226 #1101: STORE(s9,preserve_s9) 2ea3a // @227 #1102: STORE(sA,preserve_sA) 2eb3b // @228 #1103: STORE(sB,preserve_sB) 2ec3c // @229 #1104: STORE(sC,preserve_sC) 2ed3d // @22a #1105: STORE(sD,preserve_sD) 2ee3e // @22b #1106: STORE(sE,preserve_sE) 2ef3f // @22c #1107: STORE(sF,preserve_sF) // #1108: ; // #1109: ;Ignore the first 4 interrupts except to clear the counter. // #1110: ;This will ensure a clean start up after reset. // #1111: ; 06004 // @22d #1112: FETCH(s0,ISR_count) ;test to see if more that 4 interrupts have occurred 14004 // @22e #1113: COMPARE(s0,4) 3523c // @22f #1114: JUMP(Z,normal_isr) 18001 // @230 #1115: ADD(s0,1) ;increment ISR counter until reaching 4 2e004 // @231 #1116: STORE(s0,ISR_count) 04080 // @232 #1117: INPUT(s0,status_port) ;Check which counter to clear 12010 // @233 #1118: TEST(s0,AB_switch) ;if bit0 is Low then A is counting 35237 // @234 #1119: JUMP(Z,clear_B_count) // @235 #1120: [clear_A_count] 00001 // @235 #1120: LOAD(s0,a_count_reset) ;clear the active counter 34238 // @236 #1121: JUMP(clear_counter) // @237 #1122: [clear_B_count] 00002 // @237 #1122: LOAD(s0,b_count_reset) ;clear the active counter // @238 #1123: [clear_counter] 2c002 // @238 #1123: OUTPUT(s0,count_resetport) ;reset counter with pulse 00000 // @239 #1124: LOAD(s0,0) ;end reset pulse to either counter 2c002 // @23a #1125: OUTPUT(s0,count_resetport) 34256 // @23b #1126: JUMP(restore_reg) // #1127: ; // #1128: ;Normal ISR Routine // #1129: ; // #1130: ; // #1131: ;Read the new counter value and then clear it ready to start again // #1132: ; // #1133: ; // @23c #1134: [normal_isr] 04080 // @23c #1134: INPUT(s0,status_port) ;test for active counter 12010 // @23d #1135: TEST(s0,AB_switch) ;if bit is low then A is counting 35248 // @23e #1136: JUMP(Z,capture_B_count) // @23f #1137: [capture_A_count] 000f0 // @23f #1137: LOAD(s0,F0) ;set LEDs to indicate active counter 2c001 // @240 #1138: OUTPUT(s0,LED_port) 04c00 // @241 #1139: INPUT(sC,A_count0_port) ;read counter A into [sF,sE,SD,sC] 04d10 // @242 #1140: INPUT(sD,A_count1_port) 04e20 // @243 #1141: INPUT(sE,A_count2_port) 04f30 // @244 #1142: INPUT(sF,A_count3_port) 00001 // @245 #1143: LOAD(s0,a_count_reset) ;reset counter A 2c002 // @246 #1144: OUTPUT(s0,count_resetport) 34250 // @247 #1145: JUMP(counters_read) // #1146: ; // @248 #1147: [capture_B_count] 0000f // @248 #1147: LOAD(s0,15) ;set LEDs to indicate active counter 2c001 // @249 #1148: OUTPUT(s0,LED_port) 04c40 // @24a #1149: INPUT(sC,B_count0_port) ;read counter A into [sF,sE,SD,sC] 04d50 // @24b #1150: INPUT(sD,B_count1_port) 04e60 // @24c #1151: INPUT(sE,B_count2_port) 04f70 // @24d #1152: INPUT(sF,B_count3_port) 00002 // @24e #1153: LOAD(s0,b_count_reset) ;reset counter B 2c002 // @24f #1154: OUTPUT(s0,count_resetport) // @250 #1155: [counters_read] 00000 // @250 #1155: LOAD(s0,0) ;end reset pulse to either counter 2c002 // @251 #1156: OUTPUT(s0,count_resetport) // #1157: ; 2ec00 // @252 #1158: STORE(sC,count0) ;store new counter value 2ed01 // @253 #1159: STORE(sD,count1) 2ee02 // @254 #1160: STORE(sE,count2) 2ef03 // @255 #1161: STORE(sF,count3) // #1162: ; // #1163: ; // #1164: ; // #1165: ;Restore registers and end ISR // #1166: ; // @256 #1167: [restore_reg] 06f3f // @256 #1167: FETCH(sF,preserve_sF) ;restore registers 06e3e // @257 #1168: FETCH(sE,preserve_sE) 06d3d // @258 #1169: FETCH(sD,preserve_sD) 06c3c // @259 #1170: FETCH(sC,preserve_sC) 06b3b // @25a #1171: FETCH(sB,preserve_sB) 06a3a // @25b #1172: FETCH(sA,preserve_sA) 06939 // @25c #1173: FETCH(s9,preserve_s9) 06838 // @25d #1174: FETCH(s8,preserve_s8) 06737 // @25e #1175: FETCH(s7,preserve_s7) 06636 // @25f #1176: FETCH(s6,preserve_s6) 06535 // @260 #1177: FETCH(s5,preserve_s5) 06434 // @261 #1178: FETCH(s4,preserve_s4) 06333 // @262 #1179: FETCH(s3,preserve_s3) 06232 // @263 #1180: FETCH(s2,preserve_s2) 06131 // @264 #1181: FETCH(s1,preserve_s1) 06030 // @265 #1182: FETCH(s0,preserve_s0) 38001 // @266 #1183: RETURNI(ENABLE) // #1184: ; // #1185: ; // #1186: ;Interrupt vector // #1187: ; @3ff // #1188: ADDRESS(1023) 3421d // @3ff #1189: JUMP(ISR) // #1190: ; // #1191: ; // #1192: ;************************************************************************************** // #1193: ;End of Program // #1194: ;************************************************************************************** // #1195: ; // #1196: ;