; THIS SOURCE FILE Portions Copyright David Carne ; Portions Copyright Xilinx Inc ; ; source code to camera capture module. Based of uclock.psm example ; for picoblaze microprocessor. Most code has been rewritten since then ; but included is a routine for a divide by 10 for picoblaze from an ; xilinx appnote. ; CONSTANT fw_rev_hi, 01 CONSTANT fw_rev_lo, 08 ;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 CONSTANT led_port, 00 CONSTANT uart_status_port, 00 CONSTANT uart_rx_port, 01 CONSTANT uart_tx_port, 01 CONSTANT rx_data_present, 10 CONSTANT rx_full, 08 CONSTANT rx_half_full, 04 CONSTANT tx_full, 02 CONSTANT tx_half_full, 01 CONSTANT c_read_cmd, 72 ; r CONSTANT c_id_cmd, 69 ; i CONSTANT c_ovr_cmd, 62 ; b CONSTANT c_capture_cmd, 63 ; c CONSTANT c_status_reg_cmd, 73 ; s CONSTANT c_status_freq_cmd, 66 ; f CONSTANT mem_byte_in_1, 20 CONSTANT mem_byte_in_2, 21 CONSTANT mem_byte_in_3, 22 CONSTANT mem_byte_in_4, 23 CONSTANT mem_byte_out_1, 20 CONSTANT mem_byte_out_2, 21 CONSTANT mem_byte_out_3, 22 CONSTANT mem_byte_out_4, 23 CONSTANT mem_addr_1, 24 CONSTANT mem_addr_2, 25 CONSTANT mem_addr_3, 26 CONSTANT mem_addr_4, 27 start: CALL newline LOAD s0, 62 CALL uart_write ; B LOAD s0, 6F CALL uart_write ; O LOAD s0, 6F CALL uart_write ; O LOAD s0, 74 CALL uart_write ; T CALL newline CALL addr_reset poll_loop: INPUT s0, uart_status_port TEST s0, rx_data_present JUMP Z, poll_loop INPUT s0, uart_rx_port CALL handle_cmd JUMP poll_loop ; Cmd parser handle_cmd: COMPARE s0, c_read_cmd CALL Z, do_read_mem COMPARE s0, c_id_cmd CALL Z, do_id COMPARE s0, c_ovr_cmd CALL Z, do_ovr COMPARE s0, c_capture_cmd CALL Z, do_capture COMPARE s0, c_status_reg_cmd CALL Z, do_status_reg COMPARE s0, c_status_freq_cmd CALL Z, do_status_freq COMPARE s0, character_g CALL Z, do_fast_read_mem RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; fast memory read ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Transfers a grayscale image in binary format ; Should be much quick to transfer do_fast_read_mem: CALL addr_reset __fast_next_addy: INPUT s0, 30 call uart_write INPUT s0, 32 call uart_write INPUT sA, 40 ADD sA, 01 OUTPUT sA, 40 INPUT sB, 41 ADDCY sB, 00 OUTPUT sB, 41 INPUT sC, 42 ADDCY sC, 00 OUTPUT sC, 42 COMPARE sA, 00 JUMP NZ, __fast_next_addy COMPARE sB, 58 JUMP NZ, __fast_next_addy COMPARE sC, 02 JUMP NZ, __fast_next_addy RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Memory read cmd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; do_read_mem: CALL addr_reset __slow_next_addy: INPUT s0, 30 call uart_write INPUT s0, 31 call uart_write INPUT s0, 32 call uart_write INPUT s0, 33 call uart_write INPUT sA, 40 ADD sA, 01 OUTPUT sA, 40 INPUT sB, 41 ADDCY sB, 00 OUTPUT sB, 41 INPUT sC, 42 ADDCY sC, 00 OUTPUT sC, 42 COMPARE sA, 00 JUMP NZ, __slow_next_addy COMPARE sB, 58 JUMP NZ, __slow_next_addy COMPARE sC, 02 JUMP NZ, __slow_next_addy RETURN ; Older hex based read mem routine - left in for any that want it ; CALL addr_reset ; LOAD s5, FF ; CALL mem_print_addr ; ; print_mem: ; ; ; ADD s5, 01 ; COMPARE s5, 08 ; ; JUMP NZ, no_newline ; LOAD s5, 00 ; CALL newline ; CALL mem_print_addr ; no_newline: ; ; CALL mem_trans_quad ; ; ; Check if we should end early [any character] ; INPUT s0, uart_status_port ; TEST s0, rx_data_present ; JUMP NZ, __cancel_read ; ; CALL addr_inc ; JUMP NZ, print_mem ; ; ; CALL mem_trans_quad ; ; RETURN ; ; __cancel_read: ; ; CALL newline ; RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Code to initialize the frame grabber ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; do_capture: LOAD s0, character_greater_than CALL uart_write ; Trigger the capture block ; Writing a 1 to output 50 sets capture_trigger LOAD s0, 01 OUTPUT s0, 50 ; Loop until capture_done is set __stat_wait: INPUT s0, 00 TEST s0, 20 JUMP Z, __stat_wait LOAD s0, character_C CALL uart_write LOAD s0, character_a CALL uart_write LOAD s0, character_p CALL uart_write LOAD s0, character_t CALL uart_write LOAD s0, character_u CALL uart_write LOAD s0, character_r CALL uart_write LOAD s0, character_e CALL uart_write LOAD s0, character_space CALL uart_write LOAD s0, character_C CALL uart_write LOAD s0, character_o CALL uart_write LOAD s0, character_m CALL uart_write LOAD s0, character_p CALL uart_write LOAD s0, character_l CALL uart_write LOAD s0, character_e CALL uart_write LOAD s0, character_t CALL uart_write LOAD s0, character_e CALL uart_write CALL newline ; Now we clear the capture flags LOAD s0, 00 OUTPUT s0, 50 RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Status of VCLK Frequency - helpful utility to read the VCLK frequency ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; do_status_freq: ; First - setup our stri INPUT s5, 63 INPUT s4, 62 INPUT s3, 61 INPUT s2, 60 LOAD sF, 20 __more_digit: CALL divide_32bit_by_10 ADD s1, 30 STORE s1, (sF) SUB sF, 01 COMPARE s5, 00 JUMP nZ, __more_digit COMPARE s4, 00 JUMP nZ, __more_digit COMPARE s3, 00 JUMP nZ, __more_digit COMPARE s2, 00 JUMP nZ, __more_digit __print_digit: ADD sF, 01 FETCH s0, (sF) CALL uart_write COMPARE sF, 1A JUMP NZ, __no_period LOAD s0, character_stop CALL uart_write __no_period: COMPARE sF, 20 JUMP NZ, __print_digit __done_digit: LOAD s0, character_space CALL uart_write LOAD s0, character_M CALL uart_write LOAD s0, character_h CALL uart_write LOAD s0, character_z CALL uart_write CALL newline RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Handy divide by 10 routine stolen from frequency counter example ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; divide_32bit_by_10: LOAD sA, s2 ;copy input value to set [sD,sC,sB,sA] LOAD sB, s3 LOAD sC, s4 LOAD sD, s5 LOAD s2, 00 ;clear result LOAD s3, 00 LOAD s4, 00 LOAD s5, 00 LOAD s9, A0 ;initialise '10' value into msb's of set [s9,s8,s7,s6] LOAD s8, 00 LOAD s7, 00 LOAD s6, 00 LOAD s0, 1D ;29 subtract and shift iterations to be performed div10_loop: SUB sA, s6 ;perform 32-bit subtract [sD,sC,sB,sA]-[s9,s8,s7,s6] SUBCY sB, s7 SUBCY sC, s8 SUBCY sD, s9 JUMP C, div10_restore SL1 s2 ;shift '1' into result JUMP div10_shifts div10_restore: ADD sA, s6 ;perform 32-bit addition [sD,sC,sB,sA]+[s9,s8,s7,s6] ADDCY sB, s7 ADDCY sC, s8 ADDCY sD, s9 SL0 s2 ;shift '0' into result div10_shifts: SLA s3 ;complete 32-bit shift left SLA s4 SLA s5 SR0 s9 ;divide '10' value by 2 (shift right 1 place) SRA s8 SRA s7 SRA s6 SUB s0, 01 ;count iterations JUMP NZ, div10_loop LOAD s1, sA ;remainder of division RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Display status register ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; do_status_reg: ; Now read status INPUT sF, 71 INPUT sE, 70 INPUT sD, 73 INPUT sC, 72 LOAD s0, character_X CALL uart_write LOAD s0, character_colon CALL uart_write LOAD s0, character_space CALL uart_write LOAD s0, sF CALL uart_hex LOAD s0, sE CALL uart_hex LOAD s0, character_space CALL uart_write LOAD s0, character_Y CALL uart_write LOAD s0, character_colon CALL uart_write LOAD s0, character_space CALL uart_write LOAD s0, sD CALL uart_hex LOAD s0, sC CALL uart_hex CALL newline RETURN do_ovr: CALL addr_reset LOAD s0, 22 more_ovr: ; We want to blank the memory, so we write 0 to it all LOAD s0, 00 OUTPUT s0, 30 OUTPUT s0, 31 OUTPUT s0, 32 OUTPUT s0, 33 ; 43 is the magic reg to hit to trigger a memory write OUTPUT s0, 43 CALL addr_inc JUMP NZ, more_ovr LOAD s0, 62 CALL uart_write LOAD s0, 6C CALL uart_write LOAD s0, 61 CALL uart_write LOAD s0, 6E CALL uart_write LOAD s0, 6B CALL uart_write CALL newline RETURN mem_trans_quad: INPUT s0, 30 CALL uart_hex INPUT s0, 31 CALL uart_hex INPUT s0, 32 CALL uart_hex INPUT s0, 33 CALL uart_hex RETURN mem_print_addr: INPUT s0, 42 CALL uart_hex INPUT s0, 41 CALL uart_hex INPUT s0, 40 CALL uart_hex LOAD s0, 20 CALL uart_write RETURN ; ID command do_id: ; Write out id1.00 LOAD s0,69 CALL uart_write LOAD s0,64 CALL uart_write LOAD s0,20 CALL uart_write LOAD s0, fw_rev_hi CALL uart_hex LOAD s0,3A CALL uart_write LOAD s0, fw_rev_lo CALL uart_hex CALL newline RETURN addr_reset: LOAD s0, 00 OUTPUT s0, 40 OUTPUT s0, 41 OUTPUT s0, 42 RETURN ; Z set if last one addr_inc: INPUT sA, 40 ADD sA, 01 OUTPUT sA, 40 INPUT sB, 41 ADDCY sB, 00 OUTPUT sB, 41 INPUT sC, 42 ADDCY sC, 00 OUTPUT sC, 42 COMPARE sA, FF RETURN NZ COMPARE sB, FF RETURN NZ COMPARE sC, 03 RETURN newline: LOAD s0,0D CALL uart_write RETURN ; Write a 2 hex digit to the uart uart_hex: LOAD sB, s0 SR0 S0 SR0 S0 SR0 S0 SR0 S0 CALL _uart_hex_digit LOAD s0, SB CALL _uart_hex_digit RETURN _uart_hex_digit: AND s0, 0F COMPARE s0, 0A JUMP C, _uart_hex_digit__less_10 ADD s0, 07 _uart_hex_digit__less_10: ADD s0, 30 CALL uart_write RETURN ; WRITE to the uart.. s0 is the character to write uart_write: INPUT sA, uart_status_port TEST sA, tx_full JUMP NZ, uart_write OUTPUT s0, uart_tx_port RETURN