CONSTANT LED_port, 80 ;8 simple LEDs CONSTANT LED0, 01 ; LED 0 - bit0 CONSTANT LED1, 02 ; 1 - bit1 CONSTANT LED2, 04 ; 2 - bit2 CONSTANT LED3, 08 ; 3 - bit3 CONSTANT LED4, 10 ; 4 - bit4 CONSTANT LED5, 20 ; 5 - bit5 CONSTANT LED6, 40 ; 6 - bit6 CONSTANT LED7, 80 ; 7 - bit7 ; CONSTANT switch_port, 00 ;Read switches and press buttons CONSTANT switch0, 01 ; Switches SW0 - bit0 CONSTANT switch1, 02 ; SW1 - bit1 CONSTANT switch2, 04 ; SW2 - bit2 CONSTANT switch3, 08 ; SW3 - bit3 CONSTANT BTN_east, 10 ; Buttons East - bit4 CONSTANT BTN_south, 20 ; South - bit5 CONSTANT BTN_north, 40 ; North - bit6 CONSTANT BTN_west, 80 ; West - bit7 ; CONSTANT rotary_port, 01 ;Read status of rotary encoder CONSTANT rotary_left, 01 ; Direction of last move Left=1 Right=0 - bit0 CONSTANT rotary_press, 02 ; Centre press contact (active High) - bit1 ; ;LCD interface ports ; ;The master enable signal is not used by the LCD display itself ;but may be required to confirm that LCD communication is active. ;This is required on the Spartan-3E Starter Kit if the StrataFLASH ;is used because it shares the same data pins and conflicts must be avoided. ; CONSTANT LCD_output_port, 40 ;LCD character module output data and control CONSTANT LCD_E, 01 ; active High Enable E - bit0 CONSTANT LCD_RW, 02 ; Read=1 Write=0 RW - bit1 CONSTANT LCD_RS, 04 ; Instruction=0 Data=1 RS - bit2 CONSTANT LCD_drive, 08 ; Master enable (active High) - bit3 CONSTANT LCD_DB4, 10 ; 4-bit Data DB4 - bit4 CONSTANT LCD_DB5, 20 ; interface Data DB5 - bit5 CONSTANT LCD_DB6, 40 ; Data DB6 - bit6 CONSTANT LCD_DB7, 80 ; Data DB7 - bit7 ; CONSTANT LCD_input_port, 02 ;LCD character module input data CONSTANT LCD_read_spare0, 01 ; Spare bits - bit0 CONSTANT LCD_read_spare1, 02 ; are zero - bit1 CONSTANT LCD_read_spare2, 04 ; - bit2 CONSTANT LCD_read_spare3, 08 ; - bit3 CONSTANT LCD_read_DB4, 10 ; 4-bit Data DB4 - bit4 CONSTANT LCD_read_DB5, 20 ; interface Data DB5 - bit5 CONSTANT LCD_read_DB6, 40 ; Data DB6 - bit6 CONSTANT LCD_read_DB7, 80 ; Data DB7 - bit7 CONSTANT BIT7, 80 ; CONSTANT BIT6, 40 ; CONSTANT BIT5, 20 ; CONSTANT BIT4, 10 ; CONSTANT BIT3, 08 ; CONSTANT BIT2, 04 ; CONSTANT BIT1, 02 ; CONSTANT BIT0, 01 ; ; ;************************************************************************************** ;Scratch Pad Memory Locations ;************************************************************************************** ; CONSTANT rotary_status, 00 ;Status of rotary encoder CONSTANT ISR_s0, 01 ;Preserve s0 contents during ISR CONSTANT LED_pattern, 02 ;LED pattern used in rotation mode ; CONSTANT mode, 03 ;control mode 00=switch and button FF=rotary CONSTANT ms1, 04 CONSTANT secL, 05 CONSTANT secH, 06 CONSTANT minL, 07 CONSTANT minH, 08 CONSTANT hourL, 09 CONSTANT hourH, 0A CONSTANT week, 0B CONSTANT year1, 0C CONSTANT year2, 0D CONSTANT year3, 0E CONSTANT year4, 0F CONSTANT ms2, 10 CONSTANT ms500, 11 CONSTANT ISR_s1, 12 CONSTANT ms100, 13 CONSTANT ROTA_CNT, 14 CONSTANT ISR_s2, 15 CONSTANT temp, 16 CONSTANT pressed, 17 CONSTANT disp_flag, 18 CONSTANT blink_flag, 19 CONSTANT disp_flag2, 1A ;;;;;no use CONSTANT monH, 1B CONSTANT monL, 1C CONSTANT dayH, 1D CONSTANT dayL, 1E CONSTANT DAY_UP, 1F CONSTANT year100, 20 CONSTANT hourB, 21 CONSTANT minB, 22 CONSTANT secB, 23 CONSTANT yearB, 24 CONSTANT monB, 25 CONSTANT dayB, 26 CONSTANT DMAX, 27 ; CONSTANT JAN, 28 ; CONSTANT FEB, 29 ; CONSTANT MAR, 2A ; CONSTANT APR, 2B ; CONSTANT MAY, 2C ; CONSTANT JUN, 2D ; CONSTANT JUL, 2E ; CONSTANT AUG, 2F ; CONSTANT SEP, 30 ; CONSTANT OCT, 31 ; CONSTANT NOV, 32 ; CONSTANT DEC, 33 ; CONSTANT JAN2, 34 ; CONSTANT FEB2, 35 ; CONSTANT MAR2, 36 ; CONSTANT APR2, 37 ; CONSTANT MAY2, 38 ; CONSTANT JUN2, 39 ; CONSTANT JUL2, 3A ; CONSTANT AUG2, 3B ; CONSTANT SEP2, 3C ; CONSTANT OCT2, 3D ; CONSTANT NOV2, 3E ; CONSTANT DEC2, 3F ; ;The main operation of the program uses 1ms delays to set the shift rate ;of the LCD display. A 16-bit value determines how many milliseconds ;there are between shifts ; ;Tests indicate that the fastest shift rate that the LCD display supports is ;500ms. Faster than this and the display becomes less clear to read. ; CONSTANT shift_delay_msb, 01 ;delay is 500ms (01F4 hex) CONSTANT shift_delay_lsb, F4 ; ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz ; ;Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex). ;For clock rates below 10MHz the value of 1 must be used and the operation will ;become lower than intended. ; CONSTANT delay_1us_constant, 0B ;ASCII table ; CONSTANT character_a, 61 CONSTANT character_b, 62 CONSTANT character_c, 63 CONSTANT character_d, 64 CONSTANT character_e, 65 CONSTANT character_f, 66 CONSTANT character_g, 67 CONSTANT character_h, 68 CONSTANT character_i, 69 CONSTANT character_j, 6A CONSTANT character_k, 6B CONSTANT character_l, 6C CONSTANT character_m, 6D CONSTANT character_n, 6E CONSTANT character_o, 6F CONSTANT character_p, 70 CONSTANT character_q, 71 CONSTANT character_r, 72 CONSTANT character_s, 73 CONSTANT character_t, 74 CONSTANT character_u, 75 CONSTANT character_v, 76 CONSTANT character_w, 77 CONSTANT character_x, 78 CONSTANT character_y, 79 CONSTANT character_z, 7A CONSTANT character_A, 41 CONSTANT character_B, 42 CONSTANT character_C, 43 CONSTANT character_D, 44 CONSTANT character_E, 45 CONSTANT character_F, 46 CONSTANT character_G, 47 CONSTANT character_H, 48 CONSTANT character_I, 49 CONSTANT character_J, 4A CONSTANT character_K, 4B CONSTANT character_L, 4C CONSTANT character_M, 4D CONSTANT character_N, 4E CONSTANT character_O, 4F CONSTANT character_P, 50 CONSTANT character_Q, 51 CONSTANT character_R, 52 CONSTANT character_S, 53 CONSTANT character_T, 54 CONSTANT character_U, 55 CONSTANT character_V, 56 CONSTANT character_W, 57 CONSTANT character_X, 58 CONSTANT character_Y, 59 CONSTANT character_Z, 5A CONSTANT character_0, 30 CONSTANT character_1, 31 CONSTANT character_2, 32 CONSTANT character_3, 33 CONSTANT character_4, 34 CONSTANT character_5, 35 CONSTANT character_6, 36 CONSTANT character_7, 37 CONSTANT character_8, 38 CONSTANT character_9, 39 CONSTANT character_colon, 3A CONSTANT character_stop, 2E CONSTANT character_semi_colon, 3B CONSTANT character_minus, 2D CONSTANT character_divide, 2F ;'/' CONSTANT character_plus, 2B CONSTANT character_comma, 2C CONSTANT character_less_than, 3C CONSTANT character_greater_than, 3E CONSTANT character_equals, 3D CONSTANT character_space, 20 CONSTANT character_CR, 0D ;carriage return CONSTANT character_question, 3F ;'?' CONSTANT character_dollar, 24 CONSTANT character_exclaim, 21 ;'!' CONSTANT character_BS, 08 ;Back Space command character ; reset: CALL LCD_reset ENABLE INTERRUPT LOAD sD, FF LOAD s0, 00 ; STORE s0, hourH STORE s0, minL STORE s0, minH STORE s0, secH STORE s0, secL STORE s0, year2 STORE s0, year3 STORE s0, monH STORE s0, minB ;;;;;;;;;; STORE s0, secB ;;;;;;;;;; LOAD s0, 09 ; STORE s0, hourL STORE s0, hourB ;;;;;;;;; LOAD s0, 02 ; STORE s0, year1 STORE s0, dayH LOAD s0, 06 ; STORE s0, dayL STORE s0, year4 STORE s0, yearB ;;;;;;;;; LOAD s0, 05 ; STORE s0, monL STORE s0, week STORE s0, monB ;;;;;;;;; LOAD s0, 1A STORE s0, dayB ;;;;;;;;; LOAD s0, 1F STORE s0, JAN ;1 STORE s0, MAR ;3 STORE s0, MAY ;5 STORE s0, JUL ;7 STORE s0, AUG ;8 STORE s0, OCT ;10 STORE s0, DEC ;12 LOAD s0, 1E STORE s0, APR ;4 STORE s0, JUN ;6 STORE s0, SEP ;9 STORE s0, NOV ;11 LOAD s0, 1C STORE s0, FEB ;2 LOAD s0, 03 STORE s0, JAN2 STORE s0, OCT2 LOAD s0, 06 STORE s0, FEB2 STORE s0, MAR2 STORE s0, NOV2 LOAD s0, 02 STORE s0, APR2 STORE s0, JUL2 LOAD s0, 04 STORE s0, MAY2 LOAD s0, 00 STORE s0, JUN2 LOAD s0, 05 STORE s0, AUG2 LOAD s0, 01 STORE s0, SEP2 STORE s0, DEC2 LOAD sF, 00 ; restart: LOAD s5, 10 CALL LCD_cursor CALL disp_msg1 LOAD s5, 20 CALL LCD_cursor CALL disp_msg2 LOAD s3, 35 STORE s3, temp BLINK10: LOAD s3, 00 STORE s3, ms100 BLINK1: FETCH s3, ms100 COMPARE s3, 05 JUMP C, BLINK1 LOAD s5, 2F CALL LCD_cursor FETCH s5, temp CALL LCD_write_data LOAD s3, 00 STORE s3, ms100 wait1: FETCH s3, ms100 COMPARE s3, 05 JUMP C, wait1 LOAD s5, 2F CALL LCD_cursor LOAD s5, 20 CALL LCD_write_data FETCH s5, temp ADD s5, FF STORE s5, temp COMPARE s5, 2F JUMP NZ, BLINK10 RRESTART: LOAD s5, 10 CALL LCD_cursor CALL disp_msg3 LOAD s5, 20 CALL LCD_cursor CALL disp_msg4 LOAD s3, 35 STORE s3, temp BLINK20: LOAD s3, 00 STORE s3, ms100 BLINK2: FETCH s3, ms100 COMPARE s3, 05 JUMP C, BLINK2 LOAD s5, 2F CALL LCD_cursor FETCH s5, temp CALL LCD_write_data LOAD s3, 00 STORE s3, ms100 wait2: FETCH s3, ms100 COMPARE s3, 05 JUMP C, wait2 LOAD s5, 2F CALL LCD_cursor LOAD s5, 20 CALL LCD_write_data FETCH s5, temp ADD s5, FF STORE s5, temp COMPARE s5, 2F JUMP NZ, BLINK20 LOAD s0, 00 STORE s0, LED_pattern STORE s0, mode STORE s0, blink_flag STORE s0, ms100 LOAD s5, 10 CALL LCD_cursor CALL disp_msg5 LOAD s5, 20 CALL LCD_cursor CALL disp_msg6 PAUSE: FETCH s0, ms100 COMPARE s0, 32 JUMP C, PAUSE CALL LCD_clear INPUT s0, 00 STORE s0, disp_flag2 STORE s0, ms100 loop: FETCH s0, hourB CALL B2BCD STORE s0, hourL STORE s1, hourH FETCH s0, minB CALL B2BCD STORE s0, minL STORE s1, minH FETCH s0, secB CALL B2BCD STORE s0, secL STORE s1, secH FETCH s0, dayB CALL B2BCD STORE s0, dayL STORE s1, dayH FETCH s0, monB CALL B2BCD STORE s0, monL STORE s1, monH FETCH s0, yearB CALL B2BCD STORE s0, year4 STORE s1, year3 AND sF, FF JUMP NZ, SKIP1 ;;;DISP HH LOAD s5, 11 CALL LCD_cursor FETCH s3, mode COMPARE s3, 01 JUMP NZ, DSP_HH FETCH s3, ms500 TEST s3, 01 JUMP NZ, SPACE7 DSP_HH: FETCH s5, hourH ADD s5, 30 CALL LCD_write_data FETCH s5, hourL ADD s5, 30 CALL LCD_write_data JUMP MODE_2 SPACE7: CALL disp_space CALL disp_space MODE_2: ;;;DISP MM LOAD s5, 14 CALL LCD_cursor FETCH s3, mode COMPARE s3, 02 JUMP NZ, DSP_MM FETCH s3, ms500 TEST s3, 01 JUMP NZ, SPACE6 DSP_MM: FETCH s5, minH ADD s5, 30 CALL LCD_write_data FETCH s5, minL ADD s5, 30 CALL LCD_write_data JUMP MODE_3 SPACE6: CALL disp_space CALL disp_space MODE_3: ;;;DISP SS LOAD s5, 17 CALL LCD_cursor FETCH s3, mode COMPARE s3, 03 JUMP NZ, DSP_SS FETCH s3, ms500 TEST s3, 01 JUMP NZ, SPACE5 DSP_SS: FETCH s5, secH ADD s5, 30 CALL LCD_write_data FETCH s5, secL ADD s5, 30 CALL LCD_write_data JUMP MODE_4 SPACE5: CALL disp_space CALL disp_space MODE_4: ;;;DISP week LOAD s5, 1C CALL LCD_cursor FETCH s3, week COMPARE s3, 00 JUMP NZ, MON LOAD s5, character_S CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data JUMP TEST_BIT0 MON: FETCH s3, week COMPARE s3, 01 JUMP NZ, TUE LOAD s5, character_M CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data JUMP TEST_BIT0 TUE: FETCH s3, week COMPARE s3, 02 JUMP NZ, WED LOAD s5, character_T CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data JUMP TEST_BIT0 WED: FETCH s3, week COMPARE s3, 03 JUMP NZ, THU LOAD s5, character_W CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_d CALL LCD_write_data JUMP TEST_BIT0 THU: FETCH s3, week COMPARE s3, 04 JUMP NZ, FRI LOAD s5, character_T CALL LCD_write_data LOAD s5, character_h CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data JUMP TEST_BIT0 FRI: FETCH s3, week COMPARE s3, 05 JUMP NZ, SAT LOAD s5, character_F CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data JUMP TEST_BIT0 SAT: LOAD s5, character_S CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data JUMP TEST_BIT0 TEST_BIT0: ROTARY_PRESS1: ROTARY_PRESS2: SKIP1: ;;;DISP month LOAD s5, 26 CALL LCD_cursor FETCH s3, mode COMPARE s3, 04 JUMP NZ, DSP_MON FETCH s3, ms500 TEST s3, 01 JUMP NZ, SPACE4 DSP_MON: FETCH s5, monH ADD s5, 30 CALL LCD_write_data FETCH s5, monL ADD s5, 30 CALL LCD_write_data JUMP MODE_5 SPACE4: CALL disp_space CALL disp_space MODE_5: ;;;DISP day LOAD s5, 29 CALL LCD_cursor FETCH s3, mode COMPARE s3, 05 JUMP NZ, DSP_DD FETCH s3, ms500 TEST s3, 01 JUMP NZ, SPACE3 DSP_DD: FETCH s5, dayH ADD s5, 30 CALL LCD_write_data FETCH s5, dayL ADD s5, 30 CALL LCD_write_data JUMP MODE_6 SPACE3: CALL disp_space CALL disp_space MODE_6: ;;;DISP year LOAD s5, 2C CALL LCD_cursor FETCH s3, mode COMPARE s3, 06 JUMP NZ, DSP_YY FETCH s3, ms500 TEST s3, 01 JUMP NZ, SPACE2 DSP_YY: FETCH s5, year1 ADD s5, 30 CALL LCD_write_data FETCH s5, year2 ADD s5, 30 CALL LCD_write_data FETCH s5, year3 ADD s5, 30 CALL LCD_write_data FETCH s5, year4 ADD s5, 30 CALL LCD_write_data JUMP MODE_END SPACE2: CALL disp_space CALL disp_space CALL disp_space CALL disp_space MODE_END: FETCH s0, monB LOAD s1, DMAX ADD s1, s0 FETCH s2, (s1) ;;28 COMPARE s0, 02 ;;Y JUMP NZ, NO_FEB FETCH s1, yearB AND s1, 03 JUMP NZ, NO_FEB ADD s2, 01 NO_RUNNIAN: NO_FEB: STORE s2, DMAX FETCH s1, dayB COMPARE s2, s1 JUMP NC, UNDER STORE s2, dayB UNDER: FETCH s1, DAY_UP AND s1, s1 JUMP Z, NO_DAY_UP FETCH s1, dayB ADD s1, 01 STORE s1, dayB FETCH s2, DMAX ADD s2, 01 COMPARE s1, s2 JUMP NZ, NO_MON_UP LOAD s1, 01 STORE s1, dayB FETCH s1, monB ADD s1, 01 STORE s1, monB COMPARE s1, 0D JUMP NZ, NO_YEAR_UP LOAD s1, 01 STORE s1, monB FETCH s1, yearB ADD s1, 01 STORE s1, yearB COMPARE s1, 64 JUMP NZ, NO_YEAR_UP LOAD s1, 00 STORE s1, yearB JUMP NO_YEAR_UP NO_MON_UP: NO_DAY_UP: NO_YEAR_UP: LOAD s0, 00 STORE s0, DAY_UP LOAD s0, DEC FETCH s2, monB ADD s0, s2 FETCH s1, (s0) ;;;K FETCH s0, yearB ADD s1, s0 ;;;;;;;K+Y COMPARE s2, 03 JUMP C, RN ADD s0, 01 ;;;;100+Y >2(3..12) RN: ADD s0, 63 ;;;;;99+Y 1,2 SR0 s0 SR0 s0 ;;;/4 ADD s0, s1 ADD s0, 06 FETCH s2, dayB ADD s0, s2 MOD7: ADD s0, F9 JUMP NC, M7_END JUMP MOD7 M7_END: ADD s0, 07 STORE s0, week FETCH s0, mode AND s0, FF JUMP NZ, SETUP ;;;RUN LOAD s5, 20 CALL LCD_cursor FETCH s5, disp_flag CALL LCD_write_data CALL LCD_write_data CALL LCD_write_data JUMP MODEUPDATE SETUP: ;;;SET LOAD s5, 20 CALL LCD_cursor LOAD s5, 53 ;;;;;;;;;;;;;;;;;;;;;;; S CALL LCD_write_data LOAD s5, 45 ;;;;;;;;;;;;;;;;;;;;;;; E CALL LCD_write_data LOAD s5, 54 ;;;;;;;;;;;;;;;;;;;;;;; T CALL LCD_write_data MODEUPDATE: FETCH s0, mode STORE s0, blink_flag NOCHANGE: INPUT s0, 00 FETCH s1, disp_flag2 XOR s1, s0 JUMP NZ, restart STORE s0, disp_flag2 FETCH s0, monB COMPARE s0, 05 JUMP NZ, chk_sf FETCH s0, dayB COMPARE s0, 11 JUMP NZ, chk_sf FETCH s0, minB COMPARE s0, 00 JUMP Z, msg7 chk_sf: COMPARE sF, FF JUMP NZ, NO_BD CALL LCD_reset JUMP NO_BD msg7: LOAD s5, 10 CALL LCD_cursor CALL disp_msg7 ; FETCH s0, ms100 COMPARE s0, 32 JUMP C, WAIT LOAD sF, 00 JUMP restart WAIT: LOAD sF, FF JUMP loop NO_BD: LOAD sF, 00 STORE sF, ms100 JUMP loop ;;;;;;;;;s0---BINARY, s1---BCD_H, s0---BCD_L B2BCD: LOAD s1, 00 ; BCD_LP: ADD s0, F6 JUMP NC, H_END ADD s1, 01 ; JUMP BCD_LP H_END: ADD s0, 0A RETURN ; ; normal_mode: INPUT s0, switch_port ;Read switches and buttons and directly drive LEDs ; OUTPUT s0, LED_port ; RETURN ; ; ; ;This procedure will poll the status of the rotary encoder. ;If rotation occurs, then the LED pattern will adjust appropriately. ; ; rotate_mode: FETCH sA, LED_pattern ;last known position ; FETCH s0, rotary_status ;check status of rotation ; TEST s0, 80 ;test flag ; JUMP Z, update_pattern ; AND s0, 7F ;clear flag ; STORE s0, rotary_status ; TEST s0, rotary_left ;event occurred so update pattern ; JUMP Z, move_right ; RL sA ; JUMP update_pattern ; move_right: RR sA ; update_pattern: STORE sA, LED_pattern ; OUTPUT sA, LED_port ;drive LEDs with current pattern ; RETURN ; ; ; ; ; ;************************************************************************************** ;LCD text messages ;************************************************************************************** ; ; ;Display 'SPARTAN-3E STARTER KIT' on LCD at current cursor position ; ; disp_msg1: CALL disp_space LOAD s5, character_A CALL LCD_write_data CALL disp_space LOAD s5, character_C CALL LCD_write_data LOAD s5, character_l CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_c CALL LCD_write_data LOAD s5, character_k CALL LCD_write_data CALL disp_space LOAD s5, character_B CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_s CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_d CALL LCD_write_data CALL disp_space RETURN ; ; ; disp_msg2: LOAD s5, character_S CALL LCD_write_data LOAD s5, character_3 CALL LCD_write_data LOAD s5, character_E CALL LCD_write_data CALL disp_space LOAD s5, character_S CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data CALL disp_space LOAD s5, character_K CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_3 CALL LCD_write_data RETURN disp_msg3: CALL disp_space CALL disp_space CALL disp_space CALL disp_space CALL disp_space LOAD s5, character_X CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_l CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_x CALL LCD_write_data CALL disp_space CALL disp_space CALL disp_space CALL disp_space CALL disp_space RETURN disp_msg4: LOAD s5, character_P CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_c CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_B CALL LCD_write_data LOAD s5, character_l CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_z CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data CALL disp_space LOAD s5, character_T CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_s CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data CALL disp_space RETURN disp_msg5: LOAD s5, character_P CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_s CALL LCD_write_data LOAD s5, character_s CALL LCD_write_data CALL disp_space LOAD s5, 26 CALL LCD_write_data CALL disp_space LOAD s5, character_T CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data CALL disp_space LOAD s5, character_t CALL LCD_write_data LOAD s5, character_h CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data RETURN disp_msg6: CALL disp_space LOAD s5, character_E CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_c CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_d CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data CALL disp_space LOAD s5, character_t CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data CALL disp_space LOAD s5, character_S CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data CALL disp_space RETURN disp_msg7: LOAD s5, character_H CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_p CALL LCD_write_data LOAD s5, character_p CALL LCD_write_data LOAD s5, character_y CALL LCD_write_data CALL disp_space LOAD s5, character_B CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_h CALL LCD_write_data LOAD s5, character_d CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_y CALL LCD_write_data LOAD s5, 21 CALL LCD_write_data RETURN ; ;Display a space on LCD at current cursor position ; ; disp_space: LOAD s5, character_space CALL LCD_write_data RETURN ; ; ; ; ;************************************************************************************** ;Software delay routines ;************************************************************************************** ; ; ; ;Delay of 1us. ; ;Constant value defines reflects the clock applied to KCPSM3. Every instruction ;executes in 2 clock cycles making the calculation highly predictable. The '6' in ;the following equation even allows for 'CALL delay_1us' instruction in the initiating code. ; ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz ; ;Registers used s0 ; delay_1us: LOAD s0, delay_1us_constant wait_1us: SUB s0, 01 JUMP NZ, wait_1us RETURN ; ;Delay of 40us. ; ;Registers used s0, s1 ; delay_40us: LOAD s1, 28 ;40 x 1us = 40us wait_40us: CALL delay_1us SUB s1, 01 JUMP NZ, wait_40us RETURN ; ; ;Delay of 1ms. ; ;Registers used s0, s1, s2 ; delay_1ms: LOAD s2, 19 ;25 x 40us = 1ms wait_1ms: CALL delay_40us SUB s2, 01 JUMP NZ, wait_1ms RETURN ; ;Delay of 20ms. ; ;Delay of 20ms used during initialisation. ; ;Registers used s0, s1, s2, s3 ; delay_20ms: LOAD s3, 14 ;20 x 1ms = 20ms wait_20ms: CALL delay_1ms SUB s3, 01 JUMP NZ, wait_20ms RETURN ; ;Delay of approximately 1 second. ; ;Registers used s0, s1, s2, s3, s4 ; delay_1s: LOAD s4, 32 ;50 x 20ms = 1000ms wait_1s: CALL delay_20ms SUB s4, 01 JUMP NZ, wait_1s RETURN ; ; ; ;************************************************************************************** ;LCD Character Module Routines ;************************************************************************************** ; ;LCD module is a 16 character by 2 line display but all displays are very similar ;The 4-wire data interface will be used (DB4 to DB7). ; ;The LCD modules are relatively slow and software delay loops are used to slow down ;KCPSM3 adequately for the LCD to communicate. The delay routines are provided in ;a different section (see above in this case). ; ; ;Pulse LCD enable signal 'E' high for greater than 230ns (1us is used). ; ;Register s4 should define the current state of the LCD output port. ; ;Registers used s0, s4 ; LCD_pulse_E: XOR s4, LCD_E ;E=1 OUTPUT s4, LCD_output_port CALL delay_1us XOR s4, LCD_E ;E=0 OUTPUT s4, LCD_output_port RETURN ; ;Write 4-bit instruction to LCD display. ; ;The 4-bit instruction should be provided in the upper 4-bits of register s4. ;Note that this routine does not release the master enable but as it is only ;used during initialisation and as part of the 8-bit instruction write it ;should be acceptable. ; ;Registers used s4 ; LCD_write_inst4: AND s4, F8 ;Enable=1 RS=0 Instruction, RW=0 Write, E=0 OUTPUT s4, LCD_output_port ;set up RS and RW >40ns before enable pulse CALL LCD_pulse_E RETURN ; ; ;Write 8-bit instruction to LCD display. ; ;The 8-bit instruction should be provided in register s5. ;Instructions are written using the following sequence ; Upper nibble ; wait >1us ; Lower nibble ; wait >40us ; ;Registers used s0, s1, s4, s5 ; LCD_write_inst8: LOAD s4, s5 AND s4, F0 ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 OR s4, LCD_drive ;Enable=1 CALL LCD_write_inst4 ;write upper nibble CALL delay_1us ;wait >1us LOAD s4, s5 ;select lower nibble with SL1 s4 ;Enable=1 SL0 s4 ;RS=0 Instruction SL0 s4 ;RW=0 Write SL0 s4 ;E=0 CALL LCD_write_inst4 ;write lower nibble CALL delay_40us ;wait >40us LOAD s4, F0 ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 OUTPUT s4, LCD_output_port ;Release master enable RETURN ; ; ; ;Write 8-bit data to LCD display. ; ;The 8-bit data should be provided in register s5. ;Data bytes are written using the following sequence ; Upper nibble ; wait >1us ; Lower nibble ; wait >40us ; ;Registers used s0, s1, s4, s5 ; LCD_write_data: LOAD s4, s5 AND s4, F0 ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 OR s4, 0C ;Enable=1 RS=1 Data, RW=0 Write, E=0 OUTPUT s4, LCD_output_port ;set up RS and RW >40ns before enable pulse CALL LCD_pulse_E ;write upper nibble CALL delay_1us ;wait >1us LOAD s4, s5 ;select lower nibble with SL1 s4 ;Enable=1 SL1 s4 ;RS=1 Data SL0 s4 ;RW=0 Write SL0 s4 ;E=0 OUTPUT s4, LCD_output_port ;set up RS and RW >40ns before enable pulse CALL LCD_pulse_E ;write lower nibble CALL delay_40us ;wait >40us LOAD s4, F0 ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 OUTPUT s4, LCD_output_port ;Release master enable RETURN ; ; ; ; ;Read 8-bit data from LCD display. ; ;The 8-bit data will be read from the current LCD memory address ;and will be returned in register s5. ;It is advisable to set the LCD address (cursor position) before ;using the data read for the first time otherwise the display may ;generate invalid data on the first read. ; ;Data bytes are read using the following sequence ; Upper nibble ; wait >1us ; Lower nibble ; wait >40us ; ;Registers used s0, s1, s4, s5 ; ;LCD_read_data8: LOAD s4, 0E ;Enable=1 RS=1 Data, RW=1 Read, E=0 ; OUTPUT s4, LCD_output_port ;set up RS and RW >40ns before enable pulse ; XOR s4, LCD_E ;E=1 ; OUTPUT s4, LCD_output_port ; CALL delay_1us ;wait >260ns to access data ; INPUT s5, LCD_input_port ;read upper nibble ; XOR s4, LCD_E ;E=0 ; OUTPUT s4, LCD_output_port ; CALL delay_1us ;wait >1us ; XOR s4, LCD_E ;E=1 ; OUTPUT s4, LCD_output_port ; CALL delay_1us ;wait >260ns to access data ; INPUT s0, LCD_input_port ;read lower nibble ; XOR s4, LCD_E ;E=0 ; OUTPUT s4, LCD_output_port ; AND s5, F0 ;merge upper and lower nibbles ; SR0 s0 ; SR0 s0 ; SR0 s0 ; SR0 s0 ; OR s5, s0 ; LOAD s4, 04 ;Enable=0 RS=1 Data, RW=0 Write, E=0 ; OUTPUT s4, LCD_output_port ;Stop reading 5V device and release master enable ; CALL delay_40us ;wait >40us ; RETURN ; ; ;Reset and initialise display to communicate using 4-bit data mode ;Includes routine to clear the display. ; ;Requires the 4-bit instructions 3,3,3,2 to be sent with suitable delays ;following by the 8-bit instructions to set up the display. ; ; 28 = '001' Function set, '0' 4-bit mode, '1' 2-line, '0' 5x7 dot matrix, 'xx' ; 06 = '000001' Entry mode, '1' increment, '0' no display shift ; 0C = '00001' Display control, '1' display on, '0' cursor off, '0' cursor blink off ; 01 = '00000001' Display clear ; ;Registers used s0, s1, s2, s3, s4 ; LCD_reset: CALL delay_20ms ;wait more that 15ms for display to be ready LOAD s4, 30 CALL LCD_write_inst4 ;send '3' CALL delay_20ms ;wait >4.1ms CALL LCD_write_inst4 ;send '3' CALL delay_1ms ;wait >100us CALL LCD_write_inst4 ;send '3' CALL delay_40us ;wait >40us LOAD s4, 20 CALL LCD_write_inst4 ;send '2' CALL delay_40us ;wait >40us LOAD s5, 28 ;Function set CALL LCD_write_inst8 LOAD s5, 06 ;Entry mode CALL LCD_write_inst8 LOAD s5, 0C ;Display control CALL LCD_write_inst8 LCD_clear: LOAD s5, 01 ;Display clear CALL LCD_write_inst8 CALL delay_1ms ;wait >1.64ms for display to clear CALL delay_1ms LOAD s5, 13 CALL LCD_cursor LOAD s5, 3A ;;;;;;;;;;;;;;;;;;;;;;; : CALL LCD_write_data LOAD s5, 16 CALL LCD_cursor LOAD s5, 2D ;;;;;;;;;;;;;;;;;;;;;; - CALL LCD_write_data LOAD s5, 20 CALL LCD_cursor LOAD s5, 2D ;;;;;;;;;;;;;;;;;;;;;; - CALL LCD_write_data LOAD s5, 2D ;;;;;;;;;;;;;;;;;;;;;; - CALL LCD_write_data LOAD s5, 2D ;;;;;;;;;;;;;;;;;;;;;; - CALL LCD_write_data LOAD s5, 28 CALL LCD_cursor LOAD s5, 2F ;;;;;;;;;;;;;;;;;;;;;; / CALL LCD_write_data LOAD s5, 2B CALL LCD_cursor LOAD s5, 2F ;;;;;;;;;;;;;;;;;;;;;; - CALL LCD_write_data RETURN ; ;Position the cursor ready for characters to be written. ;The display is formed of 2 lines of 16 characters and each ;position has a corresponding address as indicated below. ; ; Character position ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; ; Line 1 - 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F ; Line 2 - C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF ; ;This routine will set the cursor position using the value provided ;in register s5. The upper nibble will define the line and the lower ;nibble the character position on the line. ; Example s5 = 2B will position the cursor on line 2 position 11 ; ;Registers used s0, s1, s2, s3, s4 ; LCD_cursor: TEST s5, 10 ;test for line 1 JUMP Z, set_line2 AND s5, 0F ;make address in range 80 to 8F for line 1 OR s5, 80 CALL LCD_write_inst8 ;instruction write to set cursor RETURN set_line2: AND s5, 0F ;make address in range C0 to CF for line 2 OR s5, C0 CALL LCD_write_inst8 ;instruction write to set cursor RETURN ; ;This routine will shift the complete display one position to the left. ;The cursor position and LCD memory contents will not change. ; ; ;Registers used s0, s1, s2, s3, s4, s5 ; ;LCD_shift_left: LOAD s5, 18 ;shift display left ; CALL LCD_write_inst8 ; RETURN ; ;************************************************************************************** ;Interrupt Service Routine (ISR) ;************************************************************************************** ISR: STORE s0, ISR_s0 ;preserve s0 STORE s1, ISR_s1 STORE s2, ISR_s2 INPUT s1, rotary_port LOAD s0, 00 TEST s1, rotary_press JUMP Z, no_press FETCH s0, pressed COMPARE s0, 00 JUMP NZ, no_press FETCH s2, LED_pattern ADD s2, 01 STORE s2, LED_pattern FETCH s2, mode ADD s2, 01 COMPARE s2, 07 JUMP NZ, mode_save AND s2, 00 mode_save: STORE s2, mode ;;;;;0-normal;1-hour;2-min;3-sec;4-day,5-mon,6-year LOAD s0, FF no_press: STORE s0, pressed TEST s1, 40 ;;;rotary INT ? JUMP Z, T2_5m_INT ;;NOT rotary INT,JUMP away CLR_INT2: LOAD s0, 40 ;;;;;CLR_INT1 OUTPUT s0, 20 FETCH s0, LED_pattern TEST s1, rotary_left JUMP Z, ITS_RIGHT ADD s0, FF STORE s0, LED_pattern ;;;turn left,-- FETCH s0, mode COMPARE s0, 00 JUMP Z, CLR_INT1 ; COMPARE s0, 01 JUMP NZ, MODE2N FETCH s1, hourB ADD s1, FF COMPARE s1, FF ;;;24 JUMP NZ, SAVE_HHN LOAD s1, 17 SAVE_HHN: STORE s1, hourB JUMP real_time_end MODE2N: COMPARE s0, 02 JUMP NZ, MODE3N FETCH s1, minB ADD s1, FF COMPARE s1, FF ;;;3C;;60 JUMP NZ, SAVE_MMN LOAD s1, 3B SAVE_MMN: STORE s1, minB JUMP real_time_end MODE3N: COMPARE s0, 03 JUMP NZ, MODE4N FETCH s1, secB ADD s1, FF COMPARE s1, FF ;;;60 JUMP NZ, SAVE_SSN LOAD s1, 3B SAVE_SSN: STORE s1, secB JUMP real_time_end MODE4N: COMPARE s0, 04 JUMP NZ, MODE5N FETCH s1, monB ADD s1, FF COMPARE s1, 00 ;;;12 JUMP NZ, SAVE_MONN LOAD s1, 0C SAVE_MONN: STORE s1, monB JUMP real_time_end MODE5N: COMPARE s0, 05 JUMP NZ, MODE6N FETCH s1, dayB ADD s1, FF COMPARE s1, 00 ;;;12 JUMP NZ, SAVE_DAYN FETCH s1, DMAX SAVE_DAYN: STORE s1, dayB JUMP real_time_end MODE6N: COMPARE s0, 06 JUMP NZ, MODE7N FETCH s1, yearB ADD s1, FF COMPARE s1, FF ;;;12 JUMP NZ, SAVE_YEARN LOAD s1, 63 SAVE_YEARN: STORE s1, yearB MODE7N: JUMP real_time_end ITS_RIGHT: ADD s0, 01 STORE s0, LED_pattern ;;;turn right++ FETCH s0, mode COMPARE s0, 00 JUMP Z, CLR_INT1 ; COMPARE s0, 01 JUMP NZ, MODE2P FETCH s1, hourB ADD s1, 01 COMPARE s1, 18 ;;;24 JUMP NZ, SAVE_HHP LOAD s1, 00 SAVE_HHP: STORE s1, hourB JUMP real_time_end MODE2P: COMPARE s0, 02 JUMP NZ, MODE3P FETCH s1, minB ADD s1, 01 COMPARE s1, 3C ;;;3C;;60 JUMP NZ, SAVE_MMP LOAD s1, 00 SAVE_MMP: STORE s1, minB JUMP real_time_end MODE3P: COMPARE s0, 03 JUMP NZ, MODE4P FETCH s1, secB ADD s1, 01 COMPARE s1, 3C ;;;60 JUMP NZ, SAVE_SSP LOAD s1, 00 SAVE_SSP: STORE s1, secB JUMP real_time_end MODE4P: COMPARE s0, 04 JUMP NZ, MODE5P FETCH s1, monB ADD s1, 01 COMPARE s1, 0D ;;;12 JUMP NZ, SAVE_MONP LOAD s1, 01 SAVE_MONP: STORE s1, monB JUMP real_time_end MODE5P: COMPARE s0, 05 JUMP NZ, MODE6P FETCH s1, dayB ADD s1, 01 FETCH s2, DMAX ADD s2, 01 COMPARE s1, s2 JUMP NZ, SAVE_DAYP LOAD s1, 01 SAVE_DAYP: STORE s1, dayB JUMP real_time_end MODE6P: COMPARE s0, 06 JUMP NZ, MODE7P FETCH s1, yearB ADD s1, 01 COMPARE s1, 64 ;;;12 JUMP NZ, SAVE_YEARP LOAD s1, 00 SAVE_YEARP: STORE s1, yearB MODE7P: JUMP real_time_end CLR_INT1: LOAD s0, 40 ;;;;;CLR_INT1 OUTPUT s0, 20 ;;;TIMER interrupt process;;;;mode:::0-normal;1-hour;2-min;3-sec;4-day,5-mon,6-year T2_5m_INT: TEST s1, 80 JUMP Z, end_ISR LOAD s0, 80 ;;;;;;;;;;clr_int2 OUTPUT s0, 20 FETCH s0, ms1 ADD s0, 01 STORE s0, ms1 COMPARE s0, 64 JUMP NZ, real_time_end AND s0, 00 ;;;;;;;;;;;;;CLR ms1 STORE s0, ms1 FETCH s0, LED_pattern ; ADD s0, 10 STORE s0, LED_pattern FETCH s1, ms500 ADD s1, 01 STORE s1, ms500 COMPARE s1, 01 ; JUMP NZ, CMP_2 LOAD s0, 2D ;;;------ JUMP CMP_4 CMP_2: COMPARE s1, 02 ; JUMP NZ, CMP_3 LOAD s0, 60 ;;;\\\\\\ JUMP CMP_4 CMP_3: COMPARE s1, 03 ; JUMP NZ, CMP_4 LOAD s0, 7C ;;;|||| CMP_4: STORE s0, disp_flag COMPARE s1, 04 JUMP NZ, real_time_end LOAD s0, 2F ;;;//// ;;FETCH s0,disp_flag ;;ADD s0,01 STORE s0, disp_flag AND s1, 00 ;;;;;;;;;;;;;CLR ms500 STORE s1, ms500 FETCH s0, secB ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CLOCK PROCESS START ADD s0, 01 STORE s0, secB COMPARE s0, 3C ;;;60 JUMP NZ, real_time_end AND s0, 00 STORE s0, secB FETCH s0, minB ADD s0, 01 STORE s0, minB COMPARE s0, 3C JUMP NZ, real_time_end AND s0, 00 STORE s0, minB ;;;24 Hours FETCH s0, hourB ADD s0, 01 STORE s0, hourB COMPARE s0, 18 JUMP NZ, real_time_end AND s0, 00 STORE s0, hourB DAY_P: FETCH s0, DAY_UP LOAD s0, 01 STORE s0, DAY_UP real_time_end: FETCH s0, ms2 ;;;;;;;;2.5ms counter ADD s0, 01 COMPARE s0, 28 ;;;;;;counter to 100ms JUMP NZ, store_ms2 FETCH s1, ms100 ADD s1, 01 SAV_ms100: STORE s1, ms100 LOAD s0, 00 store_ms2: STORE s0, ms2 FETCH s0, LED_pattern OUTPUT s0, LED_port end_ISR: FETCH s0, ISR_s0 ;restore s0 FETCH s1, ISR_s1 ;restore s1 FETCH s2, ISR_s2 ;restore s2 RETURNI ENABLE ;************************************************************************************** ;Interrupt Vector ;************************************************************************************** ; ADDRESS 3FF JUMP ISR ;First Screen: ;1234567890123456 ; Clock Based ;S3E Starter kit ;Second Screen: ;1234567890123456 ; X Xilinx ;PicoBlaze Test ;Third Screen: ;1234567890123456 ; Press & Turn ;Encoder to Adjust ;1234567890123456 ;09:00:00 Mon ;<-> 05/01/2006 ;Based on Ken C's ;S3ESK_STARTUP ;Modified By ; George W. ;Dear Mr. Chapman, ;I have just finished a design with PicoBlaze Based the hardware of S3E Starter kit platform. ;It's amazing that the BicoBlaze works perfect,not bad than any other professional MCU I have ever used.I like it very much. ;I have used up all the programme space that MicroBlaze supports and I had to remove some functions from the designs for the programme space reason ;My question is ,wether can I make the programme counter wider in PicoBlaze to support more programme space. ;Another problem,I cannot update the PROM on the starter kit PCB,I'm not sure whether it is caused by the MCS file I generated or other problem.The screen shot and bitstream are attached.Please help me to have a check. Thank you.