Appendix C - Code Listing
Transcription
Appendix C - Code Listing
1 Appendix C – Code Listing 1 Appendix C – Code Listing ........................................................................................................... 1 1.1 DCM – Spartan 6 FPGA: HDL Code ................................................................................................... 2 1.1.1 adg714s3w.vhdl ............................................................................................................................................... 2 1.1.2 clockmanager.vhdl .......................................................................................................................................... 4 1.1.3 comm_fpga.vhdl ................................................................................................................................................ 7 1.1.4 dac_count.vhdl ................................................................................................................................................ 10 1.1.5 emulator.vhdl ................................................................................................................................................. 11 1.1.6 FSM.vhdl ........................................................................................................................................................... 19 1.1.7 FSM2.vhdl ......................................................................................................................................................... 21 1.1.8 ipm_fifo.vhdl .................................................................................................................................................... 24 1.1.9 platform.ucf ..................................................................................................................................................... 29 1.1.10 top_level.vhdl ............................................................................................................................................... 31 1.2 SOM – AtTiny261 ............................................................................................................................... 37 1.2.1 Makefile ............................................................................................................................................................. 37 1.2.2 USI_I2C_Port.c ................................................................................................................................................. 43 1.2.3 USI_I2C_Master.c ........................................................................................................................................... 47 1.2.4 USI_TWI_Master_h ........................................................................................................................................ 52 1.3 UIM – Cross Platform GTK Client .................................................................................................. 53 1.3.1 complile.sh ....................................................................................................................................................... 53 1.3.2 dcm_compile.sh ............................................................................................................................................. 53 1.3.3 dcmusb.c ........................................................................................................................................................... 53 1.3.4 dcmusb.h ........................................................................................................................................................... 57 1.3.5 dcmusb_unitTest.c ........................................................................................................................................ 58 1.3.6 dosa.c .................................................................................................................................................................. 59 1.3.7 fpga.sh ................................................................................................................................................................ 73 1.3.8 fpgaComm.c ..................................................................................................................................................... 74 1.3.9 ini.c ...................................................................................................................................................................... 76 1.3.10 ini.h ................................................................................................................................................................... 78 1.3.11 support.h ........................................................................................................................................................ 79 1.3.12 uim_config.c .................................................................................................................................................. 81 1.3.13 uim_config.h .................................................................................................................................................. 85 1.3.14 uim_functions.c ........................................................................................................................................... 87 1.4 uim_functions.h .................................................................................................................................. 92 1.4.1 uim_settings.txt .............................................................................................................................................. 93 1.4.2 userIOusb.c ...................................................................................................................................................... 94 1.4.3 userIOusb.h ................................................................................................................................................... 100 1.5 UIM-‐E – Propeller P8X32A Embedded Controller ................................................................ 102 1.5.1 Basic_I2C_Driver.spin ................................................................................................................................ 102 1.5.2 Front_Panel_Control_001.spin .............................................................................................................. 106 1.5.3 Front_Panel_Inputs_001.spin ................................................................................................................. 111 1.5.4 pcFullDuplexSerial.spin ........................................................................................................................... 113 1.5.5 Quadrature_Encoder.spin ....................................................................................................................... 117 1.5.6 web4robot_lcd_001.spin .......................................................................................................................... 122 1.6 IPM ........................................................................................................................................................ 125 1.6.1 IPM VGA Spice Simulation (With Parasitics) .................................................................................. 125 1 1.1 DCM – Spartan 6 FPGA: HDL Code 1.1.1 adg714s3w.vhdl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 ----------------------------------------------------------------------------- Company: Team Spectrum -- Engineer: Jacob Dilles --- Create Date: 13:02:12 11/21/2012 -- Design Name: ADG714 Serial Protocol Adapter ---------------------------------------------------------------------------library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity adg714s3w is Port ( clk : in STD_LOGIC; reset : in STD_LOGIC; reg_data : in STD_LOGIC_VECTOR (7 downto 0); adg_sclk : out STD_LOGIC; adg_sync : out STD_LOGIC; adg_dout : out STD_LOGIC; adg_reset : out STD_LOGIC); end adg714s3w; architecture Behavioral of adg714s3w is -- signal holds the last data to check for a change signal last_reg_data : STD_LOGIC_VECTOR (7 downto 0); -- triggers latch and reset of different flag signal latch_reg_data : STD_LOGIC; signal last_is_different : STD_LOGIC; signal shifting, shifting_done -- internal signals signal adg_reset_flag : STD_LOGIC; : STD_LOGIC; constant sreg_shift_ctl : STD_LOGIC_VECTOR(0 to 63) := X"000000000000FFFF"; constant sclk_shift_reg : STD_LOGIC_VECTOR(0 to 63) := X"AAAAAAAAAAAAAAAA";-- X"AAAA" & "10 10 10 10 10 10 10 10" & X"AAAA"; constant sync_shift_reg : STD_LOGIC_VECTOR(0 to 63) := X"FFFF0000FFFFFFFF";-- X"FFFF" & "00 00 00 00 00 00 00 00" & X"FFFF"; signal dout_shift_reg : STD_LOGIC_VECTOR(0 to 63); -- X"0000" & d7 d6 d5 d4 d3 d2 d1 d0 & X"0000"; alias d : STD_LOGIC_VECTOR(7 downto 0) is reg_data; -- counters constant RESET_NCOUNTS : INTEGER := 7 ;--2**15 - 1; signal shift_reg_cnt : INTEGER RANGE 0 to 63; begin mux_proc: process(clk) is begin if rising_edge(clk) then shifting_done <= sreg_shift_ctl(shift_reg_cnt); adg_sync <= sync_shift_reg(shift_reg_cnt); adg_dout <= dout_shift_reg(shift_reg_cnt); adg_sclk <= sclk_shift_reg(shift_reg_cnt); adg_reset <= adg_reset_flag; end if; end process; -- The actual shifted out data shift_reg_proc: process(clk, reset) is begin if rising_edge(clk) then 2 68 if reset = '1' then 69 shift_reg_cnt <= 0; 70 else 71 if shifting = '0' then 72 shift_reg_cnt <= 0; 73 else 74 shift_reg_cnt <= shift_reg_cnt + 1; 75 end if; 76 end if; 77 end if; 78 end process shift_reg_proc; 79 80 81 -82 -- ensure we are not shifting before latching in data 83 -84 latch_in_proc: process(clk, reset) is 85 begin 86 if rising_edge(clk) then 87 if reset = '1' then 88 shifting <= '0'; 89 dout_shift_reg <= (others => '0'); 90 else 91 if shifting = '0' then 92 -- not shifting 93 if last_is_different = '0' then 94 -- no shift, no difference 95 shifting <= '0'; 96 dout_shift_reg <= dout_shift_reg; 97 else 98 -- shifting start! 99 shifting <= '1'; 100 dout_shift_reg <= X"0000" & 101 d(7) & d(7) & d(6) & d(6) & d(5) & 102 d(5) & d(4) & d(4) & 103 d(3) & d(3) & d(2) & d(2) & d(1) & 104 d(1) & d(0) & d(0) & 105 X"0000" & X"0000"; 106 end if; 107 else 108 -- we are shifting 109 if shifting_done = '0' then 110 -- not done yet 111 dout_shift_reg <= dout_shift_reg; 112 shifting <= '1'; 113 else 114 -- done 115 shifting <= '0'; 116 dout_shift_reg <= dout_shift_reg; 117 end if; 118 end if; 119 end if; 120 end if; 121 end process latch_in_proc; 122 123 124 125 -126 -- Hold reset for a specified delay 127 -128 reset_proc: process(clk, reset) is 129 variable reset_cnt : INTEGER RANGE 0 to RESET_NCOUNTS; 130 begin 131 if rising_edge(clk) then 132 if reset = '1' then 133 reset_cnt := RESET_NCOUNTS; 134 adg_reset_flag <= '0'; -- active low 135 else 136 if reset_cnt = 0 then 137 reset_cnt := 0; 138 adg_reset_flag <= '1'; -- active low 139 else 140 reset_cnt := reset_cnt - 1; 3 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 end adg_reset_flag <= '0'; -- active low end if; end if; end if; end process reset_proc; --- Monitor the register for change -change_flag: process (clk, reset) is begin if rising_edge(clk) then if reset = '1' then last_reg_data <= (others => '0'); last_is_different <= '0'; else -- change value last_reg_data <= reg_data; if last_reg_data = reg_data then last_is_different <= '0'; else last_is_different <= '1'; end if; end if; end if; end process change_flag; Behavioral; 1.1.2 clockmanager.vhdl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ------------------------------------ file: Clockmanager.vhd (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved. This file contains confidential and proprietary information of Xilinx, Inc. and is protected under U.S. and international copyright and other intellectual property laws. DISCLAIMER This disclaimer is not a license and does not grant any rights to the materials distributed herewith. Except as otherwise provided in a valid license issued to you by Xilinx, and to the maximum extent permitted by applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract or tort, including negligence, or under any other theory of liability) for any loss or damage of any kind or nature related to, arising under or in connection with these materials, including for any direct, or any indirect, special, incidental, or consequential loss or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered as a result of any action brought by a third party) even if such damage or loss was reasonably foreseeable or Xilinx had been advised of the possibility of the same. CRITICAL APPLICATIONS Xilinx products are not designed or intended to be failsafe, or for use in any application requiring fail-safe performance, such as life-support or safety devices or 4 36 -- systems, Class III medical devices, nuclear facilities, 37 -- applications related to the deployment of airbags, or any 38 -- other applications that could lead to death, personal 39 -- injury, or severe property or environmental damage 40 -- (individually and collectively, "Critical 41 -- Applications"). Customer assumes the sole risk and 42 -- liability of any use of Xilinx products in Critical 43 -- Applications, subject only to applicable laws and 44 -- regulations governing limitations on product liability. 45 -46 -- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 -- PART OF THIS FILE AT ALL TIMES. 48 -49 -----------------------------------------------------------------------------50 -- User entered comments 51 -----------------------------------------------------------------------------52 -- None 53 -54 -----------------------------------------------------------------------------55 -- "Output Output Phase Duty Pk-to-Pk Phase" 56 -- "Clock Freq (MHz) (degrees) Cycle (%) Jitter (ps) Error (ps)" 57 -----------------------------------------------------------------------------58 -- CLK_OUT1___200.000______0.000______50.0______150.969____235.738 59 -- CLK_OUT2____20.000______0.000______50.0______239.358____235.738 60 -- CLK_OUT3____50.000______0.000______50.0______198.618____235.738 61 -62 -----------------------------------------------------------------------------63 -- "Input Clock Freq (MHz) Input Jitter (UI)" 64 -----------------------------------------------------------------------------65 -- __primary_________100.000____________0.010 66 67 library ieee; 68 use ieee.std_logic_1164.all; 69 use ieee.std_logic_unsigned.all; 70 use ieee.std_logic_arith.all; 71 use ieee.numeric_std.all; 72 73 library unisim; 74 use unisim.vcomponents.all; 75 76 entity Clockmanager is 77 port 78 (-- Clock in ports 79 CLK_IN1 : in std_logic; 80 -- Clock out ports 81 sys_clk : out std_logic; 82 IPM_clk : out std_logic; 83 SOM_clk : out std_logic; 84 -- Status and control signals 85 RESET_Clk : in std_logic; 86 LOCKED_clk : out std_logic 87 ); 88 end Clockmanager; 89 90 architecture xilinx of Clockmanager is 91 attribute CORE_GENERATION_INFO : string; 92 attribute CORE_GENERATION_INFO of xilinx : architecture is "Clockmanager,clk_wiz_v3_2,{comp onent_name=Clockmanager,use_phase_alignment=false,use_min_o_jitter=false,use_max_i_jitter=false,u se_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,feedback_source=FDBK_A UTO,primtype_sel=PLL_BASE,num_out_clk=3,clkin1_period=10.0,clkin2_period=10.0,use_power_down=fals e,use_reset=true,use_locked=true,use_inclk_stopped=false,use_status=false,use_freeze=false,use_cl k_valid=false,feedback_type=SINGLE,clock_mgr_type=AUTO,manual_override=false}"; 93 -- Input clock buffering / unused connectors 94 signal clkin1 : std_logic; 95 -- Output clock buffering / unused connectors 96 signal clkfbout : std_logic; 97 signal clkout0 : std_logic; 98 signal clkout1 : std_logic; 99 signal clkout2 : std_logic; 100 signal clkout3_unused : std_logic; 101 signal clkout4_unused : std_logic; 102 signal clkout5_unused : std_logic; 103 -- Unused status signals 5 104 105 begin 106 107 108 -- Input buffering 109 -------------------------------------110 clkin1_buf : IBUFG 111 port map 112 (O => clkin1, 113 I => CLK_IN1); 114 115 116 -- Clocking primitive 117 -------------------------------------118 -- Instantiation of the PLL primitive 119 -* Unused inputs are tied off 120 -* Unused outputs are labeled unused 121 122 pll_base_inst : PLL_BASE 123 generic map 124 (BANDWIDTH => "OPTIMIZED", 125 CLK_FEEDBACK => "CLKFBOUT", 126 COMPENSATION => "INTERNAL", 127 DIVCLK_DIVIDE => 1, 128 CLKFBOUT_MULT => 4, 129 CLKFBOUT_PHASE => 0.000, 130 CLKOUT0_DIVIDE => 2, 131 CLKOUT0_PHASE => 0.000, 132 CLKOUT0_DUTY_CYCLE => 0.500, 133 CLKOUT1_DIVIDE => 16, 134 CLKOUT1_PHASE => 0.000, 135 CLKOUT1_DUTY_CYCLE => 0.500, 136 CLKOUT2_DIVIDE => 80, 137 CLKOUT2_PHASE => 0.000, 138 CLKOUT2_DUTY_CYCLE => 0.500, 139 CLKIN_PERIOD => 10.0, 140 REF_JITTER => 0.010) 141 port map 142 -- Output clocks 143 (CLKFBOUT => clkfbout, 144 CLKOUT0 => clkout0, 145 CLKOUT1 => clkout1, 146 CLKOUT2 => clkout2, 147 CLKOUT3 => clkout3_unused, 148 CLKOUT4 => clkout4_unused, 149 CLKOUT5 => clkout5_unused, 150 -- Status and control signals 151 LOCKED => LOCKED_clk, 152 RST => RESET_Clk, 153 -- Input clock control 154 CLKFBIN => clkfbout, 155 CLKIN => clkin1); 156 157 -- Output buffering 158 ------------------------------------159 160 161 clkout1_buf : BUFG 162 port map 163 (O => sys_clk, 164 I => clkout0); 165 166 167 168 clkout2_buf : BUFG 169 port map 170 (O => IPM_clk, 171 I => clkout1); 172 173 clkout3_buf : BUFG 174 port map 175 (O => SOM_clk, 176 I => clkout2); 6 177 178 end xilinx; 1.1.3 comm_fpga.vhdl 1 -2 -- Copyright (C) 2009-2012 Chris McClelland 3 -4 -- This program is free software: you can redistribute it and/or modify 5 -- it under the terms of the GNU Lesser General Public License as published by 6 -- the Free Software Foundation, either version 3 of the License, or 7 -- (at your option) any later version. 8 -9 -- This program is distributed in the hope that it will be useful, 10 -- but WITHOUT ANY WARRANTY; without even the implied warranty of 11 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 -- GNU Lesser General Public License for more details. 13 -14 -- You should have received a copy of the GNU Lesser General Public License 15 -- along with this program. If not, see <http://www.gnu.org/licenses/>. 16 -17 library ieee; 18 19 use ieee.std_logic_1164.all; 20 use ieee.numeric_std.all; 21 22 entity comm_fpga is 23 port( 24 -- FX2 interface 25 fx2Clk_in : in std_logic; -- 48MHz clock from FX2 26 fx2FifoSel_out : out std_logic; -select FIFO: '0' for EP6OUT, '1' for EP8IN 27 fx2Data_io : inout std_logic_vector(7 downto 0); -- 8-bit data to/from FX2 28 fx2Read_out : out std_logic; -- asserted (activelow) when reading from FX2 29 fx2GotData_in : in std_logic; -- asserted (activehigh) when FX2 has data for us 30 fx2Write_out : out std_logic; -- asserted (activelow) when writing to FX2 31 fx2GotRoom_in : in std_logic; -- asserted (activehigh) when FX2 has room for more data from us 32 fx2PktEnd_out : out std_logic; -- asserted (activelow) when a host read needs to be committed early 33 34 -- Channel read/write interface 35 chanAddr_out : out std_logic_vector(6 downto 0); -- the selected channel (0-127) 36 chanData_in : in std_logic_vector(7 downto 0); -data lines used when the host reads from a channel 37 chanRead_out : out std_logic; -'1' means "on the next clock rising edge, put your next byte of data on chanData_in" 38 chanGotData_in : in std_logic; -channel logic can drive this low to say "I don't have data ready for you" 39 chanData_out : out std_logic_vector(7 downto 0); -data lines used when the host writes to a channel 40 chanWrite_out : out std_logic; -'1' means "on the next clock rising edge, please accept the data on chanData_out" 41 chanGotRoom_in : in std_logic -channel logic can drive this low to say "I'm not ready for more data yet" 42 ); 43 end comm_fpga; 44 45 architecture behavioural of comm_fpga is 46 -The read/write nomenclature here refers to the FPGA reading and writing the FX2 FIFOs, and is th erefore 47 -of the opposite sense to the host's read and write. So host reads are fulfilled in the S_WRITE s tate, and 48 -- vice-versa. Apologies for the confusion. 7 49 type StateType is ( 50 S_IDLE, 51 S_GET_COUNT0, 52 S_GET_COUNT1, 53 S_GET_COUNT2, 54 S_GET_COUNT3, 55 S_BEGIN_WRITE, 56 S_WRITE, 57 S_END_WRITE_ALIGNED, 58 S_END_WRITE_NONALIGNED, 59 S_READ 60 ); 61 constant FIFO_READ : std_logic_vector(1 downto 0) := "10"; -assert fx2Read_out (active-low) 62 constant FIFO_WRITE : std_logic_vector(1 downto 0) := "01"; -assert fx2Write_out (active-low) 63 constant FIFO_NOP : std_logic_vector(1 downto 0) := "11"; -assert nothing 64 constant OUT_FIFO : std_logic := '0'; -EP6OUT 65 constant IN_FIFO : std_logic := '1'; -EP8IN 66 signal state, state_next : StateType := S_IDLE; 67 signal fifoOp : std_logic_vector(1 downto 0) := FIFO_NOP; 68 signal count, count_next : unsigned(31 downto 0) := (others => '0'); -read/write count 69 signal addr, addr_next : std_logic_vector(6 downto 0) := (others => '0'); -channel being accessed (0-127) 70 signal isWrite, isWrite_next : std_logic := '0'; -is this access is an FX2 FIFO write or a read? 71 signal isAligned, isAligned_next : std_logic := '0'; -is this FX2 FIFO write block-aligned? 72 signal dataOut : std_logic_vector(7 downto 0); -data to be driven on fx2Data_io 73 signal driveBus : std_logic; -whether or not to drive fx2Data_io 74 begin 75 -- Infer registers 76 process(fx2Clk_in) 77 begin 78 if ( rising_edge(fx2Clk_in) ) then 79 state <= state_next; 80 count <= count_next; 81 addr <= addr_next; 82 isWrite <= isWrite_next; 83 isAligned <= isAligned_next; 84 end if; 85 end process; 86 87 -- Next state logic 88 process( 89 state, fx2Data_io, fx2GotData_in, fx2GotRoom_in, count, isAligned, isWrite, addr, 90 chanData_in, chanGotData_in, chanGotRoom_in) 91 begin 92 state_next <= state; 93 count_next <= count; 94 addr_next <= addr; 95 isWrite_next <= isWrite; -- is the FPGA writing to the FX2? 96 isAligned_next <= isAligned; -- does this FIFO write end on a block (512-byte) boundary? 97 dataOut <= (others => '0'); 98 driveBus <= '0'; -- don't drive fx2Data_io by default 99 fifoOp <= FIFO_READ; -- read the FX2 FIFO by default 100 fx2PktEnd_out <= '1'; -- inactive: FPGA does not commit a short packet. 101 chanRead_out <= '0'; 102 chanWrite_out <= '0'; 103 104 case state is 105 when S_GET_COUNT0 => 106 fx2FifoSel_out <= OUT_FIFO; -- Reading from FX2 107 if ( fx2GotData_in = '1' ) then 108 -- The count high word high byte will be available on the next clock edge. 109 count_next(31 downto 24) <= unsigned(fx2Data_io); 110 state_next <= S_GET_COUNT1; 8 111 end if; 112 113 when S_GET_COUNT1 => 114 fx2FifoSel_out <= OUT_FIFO; -- Reading from FX2 115 if ( fx2GotData_in = '1' ) then 116 -- The count high word low byte will be available on the next clock edge. 117 count_next(23 downto 16) <= unsigned(fx2Data_io); 118 state_next <= S_GET_COUNT2; 119 end if; 120 121 when S_GET_COUNT2 => 122 fx2FifoSel_out <= OUT_FIFO; -- Reading from FX2 123 if ( fx2GotData_in = '1' ) then 124 -- The count low word high byte will be available on the next clock edge. 125 count_next(15 downto 8) <= unsigned(fx2Data_io); 126 state_next <= S_GET_COUNT3; 127 end if; 128 129 when S_GET_COUNT3 => 130 fx2FifoSel_out <= OUT_FIFO; -- Reading from FX2 131 if ( fx2GotData_in = '1' ) then 132 -- The count low word low byte will be available on the next clock edge. 133 count_next(7 downto 0) <= unsigned(fx2Data_io); 134 if ( isWrite = '1' ) then 135 state_next <= S_BEGIN_WRITE; 136 else 137 state_next <= S_READ; 138 end if; 139 end if; 140 141 when S_BEGIN_WRITE => 142 fx2FifoSel_out <= IN_FIFO; -- Writing to FX2 143 fifoOp <= FIFO_NOP; 144 if ( count(8 downto 0) = "000000000" ) then 145 isAligned_next <= '1'; 146 else 147 isAligned_next <= '0'; 148 end if; 149 state_next <= S_WRITE; 150 151 when S_WRITE => 152 fx2FifoSel_out <= IN_FIFO; -- Writing to FX2 153 if ( fx2GotRoom_in = '1' and chanGotData_in = '1' ) then 154 fifoOp <= FIFO_WRITE; 155 dataOut <= chanData_in; 156 driveBus <= '1'; 157 chanRead_out <= '1'; 158 count_next <= count - 1; 159 if ( count = 1 ) then 160 if ( isAligned = '1' ) then 161 state_next <= S_END_WRITE_ALIGNED; -- don't assert fx2PktEnd 162 else 163 state_next <= S_END_WRITE_NONALIGNED; -assert fx2PktEnd to commit small packet 164 end if; 165 end if; 166 else 167 fifoOp <= FIFO_NOP; 168 end if; 169 170 when S_END_WRITE_ALIGNED => 171 fx2FifoSel_out <= IN_FIFO; -- Writing to FX2 172 fifoOp <= FIFO_NOP; 173 state_next <= S_IDLE; 174 175 when S_END_WRITE_NONALIGNED => 176 fx2FifoSel_out <= IN_FIFO; -- Writing to FX2 177 fifoOp <= FIFO_NOP; 178 fx2PktEnd_out <= '0'; -- Active: FPGA commits the packet early. 179 state_next <= S_IDLE; 180 181 when S_READ => 182 fx2FifoSel_out <= OUT_FIFO; -- Reading from FX2 9 183 if ( fx2GotData_in = '1' and chanGotRoom_in = '1') then 184 -- A data byte will be available on the next clock edge 185 chanWrite_out <= '1'; 186 count_next <= count - 1; 187 if ( count = 1 ) then 188 state_next <= S_IDLE; 189 end if; 190 else 191 fifoOp <= FIFO_NOP; 192 end if; 193 194 -- S_IDLE and others 195 when others => 196 fx2FifoSel_out <= OUT_FIFO; -- Reading from FX2 197 if ( fx2GotData_in = '1' ) then 198 -- The read/write flag and a seven-bit channel address will be available on the 199 -- next clock edge. 200 addr_next <= fx2Data_io(6 downto 0); 201 isWrite_next <= fx2Data_io(7); 202 state_next <= S_GET_COUNT0; 203 end if; 204 end case; 205 end process; 206 207 -- Drive stateless signals 208 fx2Read_out <= fifoOp(0); 209 fx2Write_out <= fifoOp(1); 210 chanAddr_out <= addr; 211 chanData_out <= fx2Data_io; 212 fx2Data_io <= dataOut when driveBus = '1' else (others => 'Z'); 213 end behavioural; 1.1.4 dac_count.vhdl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity dac_count is PORT( scan_pos : in STD_LOGIC_VECTOR(31 downto 0); dac_clk : in STD_LOGIC; dac_out : out STD_LOGIC; wrld_clk : out STD_LOGIC ); end dac_count; architecture Behavioral of dac_count is signal count : STD_LOGIC_VECTOR(4 downto 0); signal shft_reg : STD_LOGIC_VECTOR(31 downto 0); begin PROCESS(dac_clk) begin if(rising_edge(dac_clk))then dac_out <= shft_reg(conv_integer(count)); count <= count + 1; if(count = "00000")then shft_reg <= x"00" & scan_pos(31 downto 8); end if; end if; end process; wrld_clk <= count(4); end Behavioral; 10 1.1.5 emulator.vhdl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity analog_interface is port ( dac_clk : in std_logic; adc_clk : in std_logic; -- data signals dac_data: in std_logic_vector(23 downto 0); -- 24 bit from DCM adc_data: out std_logic_vector(15 downto 0); -- 16 bit to DCM -- status signals control: in std_logic_vector(7 downto 0); -- control register (TBD) status : out std_logic_vector(7 downto 0) -- status register (TBD) ); end entity; architecture black_box_emulator of analog_interface is type bram_rom is array(natural range <>) of std_logic_vector(15 downto 0); -- this should fit in 4x 16x1K BRAMs (i.e. in the S3E-100) constant EMULATOR_DATA : bram_rom(0 to 4095) := ( X"0000", X"0131", X"0126", X"0086", X"0089", X"0412", X"05f1", X"02b8", X"03a0", X"0305", X"029a", X"0411", X"02f1", X"0533", X"041b", X"0334", X"0023", X"04ac", X"0078", X"0284", X"0213", X"0504", X"00a4", X"02b4", X"02f0", X"0382", X"0123", X"0373", X"038b", X"056d", X"01f1", X"0391", X"0208", X"03c8", X"0236", X"0196", X"0408", X"01a5", X"02c4", X"0365", X"0319", X"0392", X"010c", X"01ec", X"05da", X"05fd", X"0130", X"0174", X"03bd", X"02a3", X"048c", X"02b1", X"019d", X"059f", X"035d", X"0186", X"028e", X"0414", X"01a8", X"0050", X"0497", X"035e", X"0263", X"01c1", X"048e", X"0248", X"006e", X"021f", X"01f1", X"037a", X"0352", X"02e2", X"0322", X"004d", X"02f9", X"048a", X"004b", X"0374", X"00f8", X"0380", X"04ac", X"0227", X"04c2", X"05e1", X"0487", X"016c", X"03dd", X"01af", X"04e3", X"03c8", X"00c7", X"04a6", X"0387", X"00a8", X"01c4", X"0171", X"0309", X"05df", X"00ef", X"024d", X"002e", X"0252", X"01c9", X"059a", X"035e", X"0203", X"027e", X"0287", X"0394", X"0405", X"0277", X"0377", X"0295", X"02e9", X"0262", X"0510", X"00c9", X"0138", X"012e", X"0548", X"0260", X"036b", X"055b", X"0013", X"0164", X"01f9", X"0599", X"04eb", X"028b", X"00c4", X"01a8", X"03b1", X"0285", X"021c", X"023a", X"00f4", X"05ae", X"0233", X"0323", X"0073", X"022c", X"012d", X"0679", X"0170", X"04df", X"0385", X"02e2", X"01fe", X"03b6", X"0335", X"0046", X"02ca", X"02f3", X"0145", X"042d", X"00c3", X"028a", X"02e7", X"03c8", X"025f", X"0207", X"03fa", X"0566", X"0071", X"02e9", X"0501", X"02bb", X"0210", X"025a", X"004d", X"0352", X"0362", X"01b6", X"0316", X"000b", X"062c", X"0213", X"040e", X"0546", X"02ae", X"0332", X"0295", X"00bb", X"02e4", X"0269", X"02a6", X"03e2", X"0006", X"00b2", X"02a4", X"03b3", X"039b", X"0357", X"02b3", X"01bb", X"01a6", X"01ee", X"025e", X"0085", X"0169", X"01c0", X"0690", X"034e", X"02df", X"0143", X"02e3", X"0475", X"01bd", X"0351", X"0165", X"0226", X"0119", X"00f9", X"03b3", X"013f", X"03a0", X"03c0", X"0480", X"05ad", X"012f", X"01bf", X"0412", X"0021", X"04e9", X"0292", X"0083", X"05aa", X"02a2", X"02da", X"028f", X"0373", X"020f", X"02b3", X"03ba", X"01da", X"0293", X"03cb", X"0016", X"00d4", X"0468", X"027e", X"0110", X"024a", X"0398", X"022c", X"03dd", X"0198", X"0456", X"0397", X"00cf", X"0270", X"0310", X"0317", X"0162", X"0317", X"000f", X"00fb", X"0147", X"0016", X"0472", X"00b1", X"02c8", X"02ec", X"0292", X"027b", X"0495", X"0093", X"04bd", X"02f1", X"01dd", X"0111", X"0203", X"02d7", X"0264", X"0408", X"016f", X"05c8", X"0267", X"02ba", X"020a", X"033f", X"02d8", X"037a", X"03c3", X"028c", X"0095", X"02a8", X"02ad", X"021f", X"039d", X"050e", X"00c8", X"01fe", X"04b0", X"04f1", X"021a", X"03be", X"028a", X"0622", X"0066", X"0234", X"0135", X"0292", X"0466", X"01f2", X"0256", X"02b7", X"040a", X"0208", X"0041", X"009a", X"029b", X"01c1", X"01d8", X"0267", X"0279", X"03f7", X"02d6", X"035d", X"01be", X"03ad", X"02c1", X"004e", X"0213", X"0381", X"0250", X"008b", X"0285", X"0097", X"00dc", X"0507", X"0407", X"02c9", X"0020", X"035b", X"03c0", X"023d", X"0224", X"02c0", X"03d3", X"0521", X"0227", X"03eb", X"034d", 11 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 X"02ee", X"0083", X"04d0", X"037d", X"0358", X"03ab", X"01d9", X"0227", X"0107", X"03c7", X"0452", X"03a2", X"0361", X"01a8", X"02fa", X"038a", X"053f", X"0410", X"04f9", X"05d6", X"05b5", X"0367", X"02f3", X"01fb", X"040f", X"020e", X"0263", X"01ba", X"0459", X"04cc", X"0039", X"03b0", X"00b6", X"032b", X"0430", X"0796", X"02f3", X"0144", X"0270", X"0480", X"0a49", X"15f0", X"8e3e", X"3421", X"0e40", X"05d7", X"053a", X"054f", X"02f5", X"0419", X"054d", X"02f6", X"0247", X"01d0", X"0338", X"0109", X"01e6", X"0426", X"04f0", X"0572", X"01e1", X"03f8", X"02b1", X"0568", X"0262", X"0071", X"02b8", X"043c", X"0448", X"00f7", X"012b", X"0154", X"040e", X"028d", X"0377", X"0423", X"0323", X"0315", X"03f7", X"023c", X"0264", X"0284", X"022e", X"01a6", X"0244", X"01e3", X"00fd", X"0415", X"0226", X"024f", X"01b6", X"02bb", X"020d", X"0023", X"04d3", X"00ed", X"01f9", X"04a2", X"0116", X"027a", X"02e1", X"020f", X"02db", X"0455", X"0236", X"0140", X"0396", X"0404", X"006a", X"0306", X"03d9", X"080b", X"08f1", X"0b52", X"1a9e", X"afdf", X"2b2e", X"0c59", X"054f", X"04ce", X"05cc", X"0634", X"03ea", X"040d", X"0342", X"03e1", X"034a", X"050d", X"0114", X"011c", X"04a9", X"036d", X"01e9", X"00d3", X"0216", X"01a2", X"0290", X"02bd", X"040f", X"007a", X"0491", X"03a2", X"0414", X"0296", X"049b", X"019a", X"0141", X"04b0", X"03d8", X"03b5", X"0353", X"0015", X"0431", X"038c", X"0309", X"02f5", X"029a", X"0271", X"02b5", X"0182", X"03d4", X"0340", X"0395", X"01f9", X"01be", X"0048", X"0660", X"041e", X"024a", X"0215", X"00a5", X"018a", X"00f8", X"03af", X"05e1", X"02d1", X"04f1", X"046c", X"01bc", X"01a3", X"036e", X"053b", X"0384", X"05bb", X"0439", X"0447", X"0b42", X"214c", X"c0cb", X"2020", X"0b95", X"058a", X"05a6", X"029d", X"04e3", X"002c", X"0135", X"0463", X"052f", X"02df", X"026f", X"0232", X"00f9", X"0160", X"05c6", X"033f", X"021a", X"0127", X"03f6", X"01bd", X"00aa", X"02de", X"03bd", X"044b", X"026f", X"017b", X"007c", X"03b8", X"00bd", X"0265", X"001b", X"0307", X"00f6", X"01f8", X"018c", X"04ea", X"030d", X"0205", X"035d", X"04e7", X"0442", X"02dc", X"04fa", X"01d5", X"01ba", X"024a", X"0292", X"0009", X"037b", X"0236", X"006c", X"04ff", X"031f", X"0394", X"030c", X"049b", X"0161", X"01e9", X"035b", X"0449", X"052f", X"03af", X"0266", X"033d", X"02e8", X"01ae", X"02f8", X"0553", X"05ce", X"0b2d", X"24ec", X"b78b", X"1d4a", X"0cf3", X"047c", X"0724", X"0280", X"017a", X"049b", X"028e", X"02e3", X"00d5", X"0344", X"0043", X"021b", X"0341", X"045d", X"05e8", X"0360", X"0146", X"008f", X"019f", X"006c", X"03da", X"0240", X"0367", X"0224", X"0114", X"0006", X"0392", X"0483", X"030a", X"0108", X"00e7", X"01f5", X"037a", X"04c1", X"0369", X"0196", X"012d", X"0291", X"002b", X"023b", X"00ba", X"03dc", X"0279", X"0550", X"044f", X"03be", X"022e", X"049c", X"027c", X"02b1", X"040b", X"0151", X"0258", X"01ab", X"04fc", X"03c0", X"04da", X"038a", X"017a", X"032d", X"0514", X"0328", X"00fb", X"047e", X"02cd", X"025b", X"0435", X"04cc", X"0774", X"0e10", X"305e", X"9c10", X"17f0", X"086e", X"04d9", X"0333", X"045f", X"00d1", X"01a3", X"0243", X"0673", X"006b", X"00c5", X"0377", X"03fe", X"0166", X"0030", X"02bc", X"0228", X"049f", X"033f", X"02c7", X"0022", X"017a", X"0212", X"01ff", X"03bb", X"03c2", X"02cb", X"005d", X"044c", X"014f", X"0414", X"003e", X"0126", X"009e", X"008f", X"03d0", X"0250", X"02f1", X"01ec", X"0332", X"033d", X"02c3", X"02f5", X"0264", X"02f9", X"04ef", X"021b", X"0214", X"02f6", X"01a9", X"03e1", X"00d6", X"0371", X"03df", X"01a6", X"0060", X"0012", X"0476", X"03f9", X"03ed", X"039a", X"0159", X"02a1", X"023b", X"04e9", X"02de", X"05e1", X"06b2", X"0702", X"0a47", X"0fcf", X"3e0f", X"770f", X"13c9", X"071f", X"0954", X"049b", X"0262", X"020d", X"03f3", X"05a4", X"06a0", X"038f", X"038d", X"01da", X"0428", X"0040", X"02b6", X"00dd", X"00df", X"009a", X"0231", X"070f", X"0134", X"0323", X"06ed", X"008e", X"0124", X"01d8", X"02be", X"02a7", X"04e4", X"0164", X"03fb", X"02ab", X"02c5", X"0500", X"0094", X"02cb", X"03d0", X"02ed", X"00a8", X"04b7", X"0215", X"01c7", X"0262", X"023a", X"0375", X"0374", X"00a0", X"016b", X"005f", X"02c5", X"028d", X"0300", X"0368", X"01e0", X"0418", X"03aa", X"04da", X"0364", X"02d7", X"018a", X"034a", X"031c", X"01f4", X"01f8", X"06ba", X"02bb", X"03cd", X"0368", X"04f1", X"09a4", X"1150", X"4ff5", X"581f", X"12c7", X"0abf", X"06a2", X"04cf", X"03fe", X"0088", X"05b3", X"0310", X"03c0", X"04a7", X"0236", X"0532", X"02b0", X"046a", X"01d4", X"020d", X"0056", X"0390", X"023c", X"04e7", X"0527", X"0376", X"02ba", X"03b9", X"00b3", X"0261", X"0074", X"04a8", X"035c", X"03af", X"0326", X"033a", X"0533", X"035d", X"010c", X"02c2", X"05a5", X"021e", X"01b8", X"02ec", X"02e5", X"069f", X"0278", X"0529", X"06db", X"047a", X"0430", X"0584", X"0287", X"0129", X"0312", X"0031", X"0371", X"0484", X"0145", X"0372", X"027e", X"01bd", X"025f", X"0556", X"04b6", X"040d", X"013b", X"0362", X"0365", X"05d0", X"0486", X"042b", X"0779", X"08f9", X"1437", X"6d8c", X"457e", X"0e6a", X"0619", X"04ea", X"01c5", X"02e3", X"0157", X"0201", X"0027", X"0416", X"040a", X"0341", X"03a0", X"0210", X"021f", X"016e", X"01e3", X"05dc", X"00c6", X"0301", X"034b", X"02d3", X"0121", X"0056", X"0322", X"019e", X"004b", X"0649", X"01ca", X"023d", X"031e", 12 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 X"032d", X"005c", X"03ac", X"0324", X"0218", X"01b7", X"02b8", X"0371", X"0183", X"0075", X"03b2", X"043f", X"0318", X"01a9", X"0382", X"00cd", X"0290", X"01e8", X"01ec", X"01a7", X"00df", X"013b", X"001f", X"0431", X"0193", X"0022", X"0262", X"0425", X"028b", X"0475", X"01d2", X"032d", X"0403", X"0088", X"02b5", X"07b0", X"01b5", X"01da", X"02e8", X"0371", X"0116", X"005a", X"0322", X"0199", X"0228", X"026f", X"02ab", X"0579", X"0210", X"0082", X"0153", X"0367", X"01e4", X"030b", X"0296", X"035f", X"03bd", X"03b0", X"0429", X"02cb", X"039e", X"0442", X"01a2", X"04c2", X"01c4", X"02a1", X"01a7", X"04c4", X"0553", X"03cf", X"0662", X"05b3", X"005f", X"01a4", X"00b0", X"0210", X"0366", X"0121", X"0484", X"01ec", X"00b6", X"061b", X"026f", X"02fe", X"0383", X"05e2", X"00db", X"0101", X"0303", X"025d", X"03cf", X"03ca", X"0289", X"06b4", X"042e", X"02cc", X"0253", X"055e", X"01f6", X"00a6", X"0316", X"022a", X"0354", X"0345", X"0459", X"015a", X"0296", X"0311", X"0473", X"02b5", X"01a2", X"022d", X"0363", X"006c", X"01a6", X"005c", X"00ed", X"00eb", X"01ee", X"02d8", X"04e6", X"0008", X"023d", X"009b", X"0303", X"0219", X"017a", X"0009", X"01d3", X"01d7", X"0075", X"02c0", X"041f", X"008f", X"0376", X"0485", X"0213", X"037c", X"043c", X"01b9", X"043f", X"0569", X"021e", X"041c", X"0574", X"00ed", X"04d6", X"0425", X"0026", X"0228", X"0379", X"0315", X"01da", X"0450", X"003d", X"03f3", X"00f9", X"0277", X"0370", X"036a", X"0045", X"0303", X"02a0", X"0325", X"0493", X"01ec", X"0213", X"00c3", X"001f", X"02fe", X"0151", X"0271", X"030d", X"05fd", X"02b7", X"0095", X"0272", X"038d", X"0424", X"0306", X"00ad", X"0030", X"009b", X"0267", X"051b", X"028c", X"01d7", X"03f1", X"03a0", X"0252", X"05f4", X"01b6", X"0009", X"04ba", X"02f8", X"038a", X"02e1", X"0340", X"0119", X"05e2", X"04ca", X"0569", X"0690", X"0528", X"04c2", X"01cd", X"01bf", X"00cd", X"01cf", X"0172", X"043a", X"04b0", X"021f", X"0249", X"00b8", X"01a6", X"031d", X"02fb", X"0493", X"0186", X"0034", X"031d", X"022f", X"01ec", X"0217", X"0181", X"0197", X"0531", X"01de", X"0525", X"0458", X"04b0", X"0577", X"03d3", X"029e", X"0343", X"01bb", X"0431", X"0163", X"0256", X"020f", X"0236", X"015f", X"00f6", X"00fc", X"03d0", X"02cd", X"0145", X"0306", X"03c8", X"012c", X"01d8", X"03a9", X"034c", X"0321", X"0141", X"03d9", X"01e4", X"02f9", X"0310", X"031d", X"01b1", X"0351", X"020d", X"01b0", X"01c3", X"001b", X"0555", X"017b", X"0567", X"026e", X"0508", X"01fe", X"0384", X"02f5", X"0181", X"0331", X"0290", X"0146", X"01f1", X"039c", X"03e9", X"02d8", X"0565", X"0657", X"034e", X"0184", X"0228", X"040b", X"0491", X"015b", X"03e8", X"0305", X"0308", X"0026", X"017f", X"0569", X"0035", X"0103", X"0230", X"0079", X"051f", X"0409", X"0231", X"0364", X"022c", X"0293", X"02b2", X"0289", X"006f", X"0383", X"01cd", X"039b", X"059b", X"02d1", X"0404", X"0217", X"04a1", X"007b", X"0239", X"0558", X"0371", X"0272", X"00ee", X"0238", X"0017", X"03f5", X"0152", X"0140", X"0383", X"031f", X"02b0", X"01bc", X"031c", X"0306", X"0177", X"036d", X"0206", X"0186", X"05bb", X"00e0", X"0226", X"01f5", X"063b", X"02ba", X"0220", X"020e", X"009d", X"015d", X"0081", X"0307", X"04e4", X"04e9", X"01aa", X"00d0", X"0367", X"032c", X"03b5", X"031d", X"0293", X"030c", X"02dd", X"0611", X"01f9", X"0108", X"00ef", X"0291", X"0373", X"03d0", X"01c2", X"03f0", X"02fc", X"049a", X"0130", X"00d2", X"0435", X"006e", X"00e2", X"03e7", X"0315", X"01be", X"0150", X"03ec", X"00cb", X"00f2", X"03aa", X"0342", X"03c1", X"0342", X"06fe", X"040a", X"058d", X"03f0", X"0247", X"049c", X"02a1", X"005d", X"052e", X"02d5", X"0400", X"03b4", X"01f0", X"01ca", X"01d6", X"0437", X"02fe", X"0103", X"0250", X"00b8", X"00ac", X"0265", X"02cf", X"02b5", X"05a6", X"01e7", X"0264", X"03b5", X"03a7", X"02b3", X"0377", X"0356", X"019a", X"0302", X"02ce", X"026c", X"019e", X"0654", X"0473", X"02dd", X"02fe", X"049a", X"010c", X"0303", X"0030", X"0350", X"0352", X"01ba", X"0293", X"02c6", X"00e0", X"0334", X"01b1", X"0153", X"0034", X"02d6", X"034a", X"0117", X"02a5", X"02f8", X"004e", X"01d4", X"0150", X"0321", X"05d9", X"01e2", X"04c1", X"05af", X"03ba", X"01f6", X"020d", X"0478", X"00fb", X"03f6", X"041e", X"01db", X"01b0", X"0416", X"0176", X"025a", X"027c", X"043d", X"031a", X"053f", X"00b3", X"0118", X"0358", X"0421", X"005c", X"02b8", X"0230", X"03c0", X"0545", X"03a9", X"02f5", X"00c9", X"01e5", X"02ba", X"05e3", X"00b2", X"03dc", X"0031", X"0023", X"0209", X"0218", X"0234", X"01e5", X"0403", X"031a", X"0425", X"00f8", X"0299", X"01ac", X"0369", X"038c", X"028d", X"0216", X"044b", X"033c", X"001a", X"05d1", X"0258", X"0158", X"0001", X"039a", X"0506", X"038e", X"0377", X"00b9", X"0272", X"049a", X"0494", X"04fd", X"0467", X"034d", X"0228", X"057b", X"047d", X"005e", X"0223", X"0456", X"03a6", X"0600", X"01aa", X"0468", X"012c", X"00fa", X"00be", X"0313", X"010a", X"01ad", X"0052", X"005d", X"01c0", X"02e0", X"03b8", X"01e9", X"02e9", X"0270", X"02a3", X"02cb", X"0324", X"02bd", X"0287", X"055c", X"008d", X"021d", X"03a1", X"01c8", X"02bc", X"0054", X"0318", X"01d5", X"04c3", X"01d0", X"014b", X"00d3", X"0473", X"0418", X"0444", X"021e", X"03d3", X"0243", X"0160", X"0005", X"0322", X"0245", X"0399", X"025f", X"0041", X"03e4", X"0444", X"0161", X"0297", X"0366", 13 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 X"04c5", X"053f", X"02b9", X"0272", X"0529", X"053f", X"0030", X"0635", X"0bed", X"1db5", X"bc74", X"263d", X"0a6f", X"094c", X"0678", X"020b", X"0383", X"05ed", X"0345", X"0318", X"0195", X"0300", X"04b8", X"0186", X"0323", X"01f6", X"03ee", X"031b", X"030e", X"00ec", X"031e", X"0119", X"0237", X"01bb", X"0463", X"02b1", X"0093", X"0210", X"02ac", X"04c6", X"00e1", X"00e3", X"03ea", X"03b0", X"0129", X"0336", X"01c6", X"0470", X"01b7", X"01ad", X"0321", X"04a7", X"0236", X"0050", X"020c", X"02e7", X"035a", X"02b0", X"02cd", X"00da", X"01d2", X"016f", X"0694", X"033f", X"00f0", X"0334", X"00cc", X"0112", X"02d6", X"037c", X"002c", X"0170", X"01d3", X"01b1", X"03f5", X"046a", X"03cb", X"0223", X"06a8", X"04f8", X"0546", X"0aaa", X"2422", X"bf2b", X"1e78", X"0b27", X"083b", X"0500", X"0360", X"0500", X"04f1", X"0451", X"0390", X"026b", X"0067", X"03e9", X"0151", X"034b", X"027b", X"0326", X"03a4", X"0194", X"022e", X"038e", X"03cb", X"017b", X"0694", X"0516", X"025a", X"020f", X"015c", X"0265", X"002d", X"03b9", X"025b", X"04dc", X"00c9", X"023e", X"01de", X"0061", X"0192", X"00ef", X"0337", X"0188", X"03b8", X"0047", X"0407", X"0486", X"036d", X"031e", X"02e0", X"009e", X"025d", X"043b", X"038e", X"036d", X"026b", X"0417", X"0190", X"04cd", X"0083", X"03e4", X"0311", X"04af", X"0294", X"0270", X"03a1", X"0119", X"058b", X"02fb", X"049d", X"0550", X"03e3", X"0771", X"0cbc", X"2d54", X"a400", X"18b5", X"0aa4", X"0695", X"042b", X"019a", X"03ad", X"053e", X"0326", X"0128", X"021a", X"0504", X"02c8", X"05d4", X"0432", X"0447", X"00dd", X"04a0", X"055b", X"0129", X"03ab", X"03db", X"017d", X"0280", X"0318", X"01c4", X"03da", X"0237", X"0270", X"01c2", X"02f1", X"037c", X"01b9", X"01ee", X"0495", X"015e", X"0113", X"0117", X"038c", X"03b3", X"0244", X"02cc", X"0143", X"02a6", X"0234", X"00e1", X"0187", X"023e", X"00a7", X"03e2", X"011f", X"05cf", X"03ca", X"028d", X"0009", X"04cc", X"05ac", X"0258", X"0082", X"011e", X"03b1", X"03bb", X"026a", X"02f8", X"0296", X"0432", X"047f", X"0442", X"02a0", X"060a", X"0a91", X"0e62", X"3b52", X"7d38", X"121b", X"0951", X"0639", X"04e7", X"04c5", X"025e", X"03b7", X"02d2", X"0244", X"02bf", X"030f", X"02bb", X"045d", X"04df", X"0297", X"018e", X"00d0", X"02bd", X"01e0", X"0203", X"01f9", X"01bf", X"01d1", X"026a", X"0543", X"01f5", X"04e6", X"01f9", X"01bb", X"0245", X"02e1", X"025f", X"03d6", X"0118", X"01fc", X"0208", X"01d8", X"036b", X"041e", X"03b2", X"03d3", X"021f", X"0263", X"023f", X"01f1", X"026b", X"014e", X"044b", X"04fb", X"035d", X"0301", X"0201", X"005c", X"04b9", X"02be", X"03af", X"0216", X"041d", X"01f2", X"00a1", X"0215", X"03af", X"033f", X"0369", X"05ce", X"0133", X"0774", X"0537", X"0722", X"0bc9", X"1281", X"4d81", X"5f9d", X"12e0", X"0891", X"0317", X"0491", X"04ca", X"0608", X"0516", X"029b", X"04f8", X"02e8", X"0530", X"02ca", X"0533", X"0194", X"016d", X"0441", X"040d", X"05cf", X"03d2", X"05ed", X"02de", X"0279", X"02d8", X"0216", X"0233", X"01ec", X"030a", X"0224", X"005d", X"03e1", X"02b8", X"01b1", X"00d8", X"02bd", X"0349", X"02f3", X"02af", X"02f6", X"0406", X"03f8", X"04b3", X"035c", X"0217", X"006b", X"0131", X"0338", X"01fe", X"0373", X"0407", X"024d", X"01d5", X"06e4", X"00a1", X"018f", X"0122", X"0233", X"0263", X"0176", X"04a3", X"03da", X"0322", X"0110", X"037f", X"0350", X"0284", X"0215", X"02c9", X"029e", X"05b8", X"0694", X"1308", X"6652", X"468e", X"0fdd", X"081b", X"05b4", X"02e7", X"03c4", X"04af", X"01fa", X"0516", X"012c", X"0252", X"047e", X"02ef", X"029f", X"0409", X"0086", X"0194", X"0237", X"03dc", X"0423", X"03fe", X"010f", X"0496", X"02f3", X"0529", X"043e", X"0327", X"01a9", X"0079", X"00c8", X"043f", X"0439", X"05ee", X"014c", X"0232", X"03e0", X"03ba", X"0276", X"0496", X"02c0", X"02a5", X"02d9", X"02a6", X"046a", X"03e1", X"0155", X"02c7", X"032a", X"0325", X"03e9", X"0445", X"02cd", X"01e0", X"02ec", X"0446", X"0079", X"0104", X"0164", X"03f9", X"0534", X"036a", X"00fc", X"04cc", X"0337", X"018f", X"075c", X"0317", X"0294", X"05f8", X"04a2", X"083a", X"18a2", X"8523", X"366a", X"0f50", X"07a9", X"06ea", X"0429", X"0266", X"03fe", X"01f5", X"0542", X"036e", X"040e", X"0261", X"02aa", X"0564", X"01c4", X"0093", X"03b7", X"0540", X"052e", X"0215", X"01a6", X"01bf", X"016d", X"0128", X"04fb", X"01b4", X"042e", X"0239", X"0148", X"02c9", X"054f", X"0272", X"0336", X"00b9", X"0072", X"0079", X"036b", X"0266", X"0489", X"0737", X"0539", X"0259", X"031a", X"0374", X"008e", X"009d", X"0382", X"0187", X"02b5", X"024b", X"0508", X"01ac", X"039b", X"0063", X"02ef", X"04d7", X"0342", X"02b1", X"02ac", X"023f", X"0574", X"05a5", X"0401", X"0391", X"04c5", X"055e", X"0341", X"03f6", X"0324", X"0546", X"08e6", X"19cb", X"a9ce", X"2ed3", X"0b2a", X"0826", X"085e", X"053a", X"05e2", X"0191", X"0358", X"0262", X"0184", X"0500", X"0392", X"00c8", X"0383", X"0115", X"0209", X"0162", X"032a", X"02a0", X"0225", X"017b", X"0692", X"03a5", X"0089", X"02f1", X"041b", X"0391", X"0500", X"03a7", X"003e", X"038b", X"0219", X"0158", X"0519", X"0153", X"0481", X"04e8", X"04ab", X"0536", X"064d", X"00d0", X"0284", X"0228", X"0400", X"0310", X"0103", X"047e", X"030e", X"0397", X"0618", X"03ae", X"0430", X"01ad", X"00aa", X"02ce", X"01ee", X"0343", X"01d1", X"05a9", X"01bf", X"0082", X"05fd", X"020c", 14 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 X"0154", X"030b", X"0367", X"05f8", X"03db", X"020d", X"0238", X"01fa", X"0522", X"02a9", X"0228", X"0103", X"00e3", X"02f7", X"0152", X"0167", X"01cc", X"02bc", X"03fb", X"0329", X"012e", X"027c", X"039e", X"0493", X"0153", X"035c", X"0223", X"031d", X"027e", X"03d6", X"007f", X"004f", X"002f", X"00d7", X"02bf", X"034b", X"04dc", X"04d4", X"02bc", X"038f", X"04b2", X"021e", X"02b5", X"0181", X"05e1", X"04f6", X"031e", X"0608", X"0597", X"0d9e", X"2aab", X"a9bd", X"1b33", X"08f2", X"0435", X"040e", X"047e", X"0606", X"0380", X"05df", X"02a9", X"03d1", X"050e", X"01dd", X"01d5", X"0402", X"0640", X"0227", X"0265", X"0184", X"025d", X"030b", X"0312", X"01e5", X"0079", X"01f7", X"03c5", X"0252", X"01e4", X"0517", X"000d", X"0494", X"04ab", X"058a", X"02eb", X"0281", X"02a3", X"0077", X"04c5", X"04a3", X"01f7", X"0272", X"0027", X"025a", X"04e2", X"014e", X"03b9", X"0399", X"0389", X"02d3", X"02e3", X"037e", X"018d", X"033c", X"075b", X"0016", X"0466", X"0212", X"03d8", X"0406", X"04fc", X"054d", X"0351", X"0405", X"0230", X"08fe", X"0482", X"04a9", X"02d9", X"0833", X"04d3", X"0654", X"0d17", X"34f8", X"85ad", X"1797", X"04e7", X"025d", X"053d", X"0105", X"040a", X"05d7", X"02cc", X"0200", X"03e9", X"021b", X"01cd", X"059b", X"047e", X"02fa", X"03e7", X"0193", X"00f8", X"02ce", X"0219", X"0396", X"0167", X"04f9", X"04d1", X"03c7", X"0386", X"02a1", X"046a", X"0019", X"0372", X"025b", X"00a0", X"02ff", X"04f7", X"03eb", X"036b", X"010b", X"00f7", X"03c2", X"038a", X"0326", X"009c", X"011a", X"071d", X"03b2", X"0201", X"00da", X"0353", X"0303", X"011a", X"047b", X"0420", X"01ef", X"02e5", X"027f", X"00bd", X"02d9", X"0399", X"033b", X"00cc", X"0279", X"03bf", X"02bb", X"01ce", X"022b", X"0769", X"0228", X"06ee", X"06d5", X"0803", X"0fbd", X"48c7", X"65ef", X"12a2", X"0d4f", X"060f", X"0245", X"0279", X"02c3", X"059f", X"02af", X"02b4", X"021a", X"0195", X"078c", X"02aa", X"0350", X"02d8", X"03de", X"034c", X"028e", X"0403", X"02b0", X"01e7", X"0467", X"03c5", X"03eb", X"04d9", X"0193", X"031f", X"00f0", X"01ea", X"03ab", X"022c", X"031e", X"03e6", X"01e6", X"04b8", X"03d0", X"0206", X"01bb", X"0026", X"02c7", X"032c", X"02b2", X"00bc", X"02de", X"02ee", X"01a2", X"0029", X"0529", X"03d2", X"0471", X"0154", X"028d", X"02a7", X"00ec", X"0401", X"03d4", X"0302", X"02bb", X"033b", X"0317", X"0250", X"019c", X"02e3", X"0299", X"05bc", X"0350", X"042b", X"04a2", X"05bf", X"06f2", X"1326", X"6374", X"494e", X"11a8", X"063a", X"06d7", X"038f", X"0655", X"03b7", X"0185", X"0435", X"0332", X"0154", X"0501", X"02d2", X"007a", X"01c0", X"0226", X"05b4", X"02ad", X"030a", X"01ce", X"0210", X"0318", X"040c", X"0311", X"02de", X"0429", X"0234", X"03e0", X"0159", X"0329", X"02e8", X"0519", X"01aa", X"04f2", X"0350", X"03e2", X"044a", X"0394", X"04d6", X"025e", X"030e", X"0410", X"03f6", X"0329", X"0546", X"032e", X"03c2", X"0244", X"01c9", X"0252", X"004f", X"04c5", X"000a", X"018b", X"022a", X"053a", X"02a8", X"0379", X"0192", X"02b5", X"01d5", X"0511", X"050f", X"042e", X"0602", X"0240", X"03da", X"030c", X"05ad", X"066a", X"0b13", X"15ac", X"7e55", X"3d90", X"0df3", X"060d", X"0547", X"0305", X"0334", X"001c", X"0543", X"036c", X"01ec", X"04c8", X"02bd", X"0232", X"050c", X"03ef", X"02a6", X"016f", X"0086", X"037a", X"0498", X"0238", X"0118", X"0741", X"0416", X"00c1", X"01ff", X"0406", X"0216", X"04ba", X"03e1", X"0630", X"01eb", X"0774", X"00b7", X"0404", X"031d", X"0248", X"04d8", X"001e", X"034b", X"0115", X"01c4", X"016a", X"00e4", X"0291", X"035b", X"0436", X"03b4", X"019a", X"02a6", X"0163", X"00e6", X"029e", X"03af", X"02ae", X"032b", X"0289", X"0364", X"05fa", X"0062", X"02d1", X"01fa", X"028f", X"03dc", X"03d4", X"02f7", X"04db", X"0367", X"0698", X"068f", X"099a", X"179d", X"a224", X"2e4a", X"0cb8", X"0582", X"0507", X"039b", X"0456", X"027c", X"0277", X"0347", X"01d1", X"01a2", X"0330", X"03df", X"02f7", X"038d", X"0211", X"00a7", X"01ea", X"02c5", X"02bd", X"01d3", X"0359", X"03a0", X"01e4", X"0299", X"0360", X"019d", X"03b8", X"03ff", X"02ec", X"02dd", X"0267", X"014c", X"022a", X"0038", X"02eb", X"01dc", X"01d1", X"05e2", X"039c", X"025b", X"03b6", X"018f", X"03be", X"02ab", X"012f", X"04be", X"0419", X"02ce", X"0300", X"028c", X"040e", X"0342", X"046c", X"019e", X"008b", X"016e", X"0262", X"032b", X"016a", X"0070", X"01ad", X"059a", X"027e", X"04f0", X"0284", X"0262", X"0460", X"0281", X"086c", X"0c23", X"1da6", X"bd43", X"269e", X"0d44", X"074b", X"016f", X"052b", X"05cb", X"0358", X"03e7", X"02eb", X"02fc", X"004a", X"00c2", X"03e9", X"031a", X"00b3", X"0359", X"0282", X"0457", X"01f8", X"0116", X"031e", X"029a", X"02eb", X"0456", X"03b1", X"04c6", X"01a8", X"03d5", X"046a", X"045b", X"05ca", X"024f", X"0499", X"0588", X"0243", X"0226", X"0128", X"0445", X"0149", X"0035", X"0397", X"02ef", X"02d6", X"0439", X"0168", X"0459", X"0408", X"025b", X"0082", X"009f", X"01fc", X"02b4", X"00e0", X"026f", X"040f", X"026d", X"042e", X"054b", X"02ad", X"0280", X"04c5", X"0481", X"01b4", X"019a", X"02c9", X"03da", X"02f0", X"055b", X"0781", X"0a70", X"0c2a", X"2395", X"c187", X"1db4", X"0b5c", X"0a13", X"039b", X"01df", X"05c5", X"01d4", X"0380", X"00c8", X"0361", X"042a", X"02e5", X"00fb", X"01fe", X"038b", X"0214", X"00eb", X"03dc", X"01e1", X"00eb", X"0394", X"03ef", 15 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 X"0497", X"0316", X"0076", X"0505", X"046c", X"00dc", X"033c", X"01e7", X"043a", X"02da", X"0520", X"0246", X"01e4", X"00e4", X"021f", X"03af", X"0204", X"02d1", X"02b1", X"0254", X"01c0", X"0367", X"02c7", X"027c", X"00dc", X"026a", X"01b1", X"00d3", X"004a", X"01bf", X"0042", X"030b", X"0399", X"0389", X"00b7", X"0373", X"049f", X"01d9", X"027e", X"03b4", X"00eb", X"00f5", X"0181", X"040b", X"0268", X"03f2", X"00d6", X"00ab", X"0464", X"0706", X"00f7", X"03c9", X"026d", X"0259", X"01a8", X"0331", X"01bc", X"04e2", X"02e7", X"03a1", X"00e4", X"046b", X"02df", X"03aa", X"037f", X"016a", X"04c6", X"039b", X"0453", X"022e", X"053d", X"0074", X"0302", X"0195", X"0334", X"03f0", X"0314", X"00ca", X"02c7", X"01ed", X"021f", X"048c", X"0100", X"061f", X"02a9", X"01aa", X"0324", X"0162", X"0293", X"0491", X"0225", X"026e", X"0478", X"0255", X"02e6", X"00b6", X"035d", X"03fa", X"0472", X"0503", X"0165", X"0319", X"03b5", X"01cc", X"0572", X"0197", X"0127", X"03e5", X"032b", X"0693", X"0331", X"02c0", X"0410", X"007d", X"0277", X"0081", X"0102", X"052b", X"01d3", X"0446", X"0435", X"00fc", X"0181", X"0102", X"02be", X"0455", X"01bf", X"0164", X"00e4", X"040b", X"024f", X"03c1", X"02eb", X"000b", X"0332", X"0606", X"058a", X"00c5", X"0395", X"00ae", X"0338", X"0179", X"0475", X"01f8", X"02c9", X"01b1", X"04be", X"02e6", X"0212", X"05d1", X"039c", X"0440", X"029c", X"02ba", X"0117", X"024c", X"045c", X"03e8", X"012c", X"019f", X"031d", X"0160", X"0164", X"0237", X"05bf", X"027d", X"04c8", X"035f", X"00ca", X"0020", X"03bf", X"0200", X"0110", X"01e2", X"00a8", X"007a", X"0144", X"0289", X"057d", X"0299", X"0413", X"03c0", X"0348", X"05c1", X"06a8", X"0549", X"01de", X"047b", X"0327", X"0394", X"02ad", X"04b8", X"0035", X"02ac", X"01e9", X"026e", X"00e8", X"0346", X"026a", X"02d6", X"01ed", X"0303", X"0430", X"0390", X"01d8", X"0168", X"001e", X"0424", X"03b2", X"032e", X"03d6", X"034b", X"027f", X"0228", X"02fd", X"00b8", X"03a9", X"01d6", X"038e", X"03b8", X"009b", X"00a6", X"05f9", X"0363", X"0389", X"0297", X"01be", X"0412", X"01c0", X"02d8", X"0409", X"03a8", X"0230", X"023d", X"0354", X"0261", X"049c", X"03da", X"045f", X"0390", X"012f", X"0420", X"0269", X"0015", X"012b", X"0166", X"03dc", X"04c1", X"03d8", X"0710", X"0068", X"0357", X"043b", X"01e5", X"02bc", X"0110", X"03c1", X"0152", X"0303", X"01b7", X"0412", X"01c7", X"0230", X"0194", X"034a", X"0438", X"0135", X"0346", X"0074", X"03a9", X"03a3", X"03b5", X"0329", X"02f2", X"0310", X"0253", X"00bb", X"02cb", X"034a", X"0027", X"013d", X"0282", X"027f", X"03a8", X"01f4", X"012e", X"01d2", X"00c8", X"0257", X"01be", X"019c", X"057f", X"0175", X"0405", X"016e", X"0276", X"04a2", X"02b0", X"02bc", X"0410", X"0489", X"014e", X"0494", X"05cf", X"03d0", X"0003", X"02b6", X"048f", X"0054", X"0350", X"0075", X"02eb", X"0263", X"0323", X"04ef", X"0250", X"0265", X"0126", X"01e6", X"0207", X"0240", X"0255", X"0282", X"0656", X"02aa", X"035c", X"05cf", X"015f", X"03e0", X"0219", X"0214", X"00ee", X"028f", X"0388", X"0091", X"0271", X"02fc", X"0234", X"0276", X"0400", X"0213", X"04fe", X"01d4", X"0253", X"0010", X"0138", X"0278", X"0487", X"0411", X"00db", X"0096", X"0472", X"03e3", X"023d", X"02ad", X"0284", X"021a", X"01e8", X"022d", X"0416", X"01f3", X"0138", X"0260", X"03fd", X"0280", X"0253", X"03fb", X"003d", X"005b", X"046c", X"0387", X"005a", X"0557", X"00ee", X"0343", X"04f9", X"02bf", X"0282", X"007a", X"04b2", X"05ee", X"04a6", X"0469", X"00b5", X"03fb", X"0221", X"0597", X"0336", X"038a", X"0011", X"0388", X"0461", X"01c3", X"01d9", X"009b", X"0527", X"004d", X"017a", X"0209", X"0770", X"005a", X"0131", X"03ca", X"01bc", X"0392", X"0450", X"01d4", X"02ff", X"02d6", X"011c", X"02cd", X"0180", X"0087", X"0244", X"002d", X"0238", X"030d", X"0474", X"0226", X"017b", X"03c3", X"01be", X"017a", X"0371", X"022e", X"03a0", X"03fa", X"04e5", X"0152", X"0022", X"02e7", X"038e", X"04a9", X"0418", X"03fc", X"0327", X"0340", X"01ac", X"00f7", X"001a", X"0264", X"00f2", X"0325", X"02e2", X"0201", X"02a5", X"03da", X"0010", X"033b", X"04f6", X"00da", X"020f", X"022c", X"029e", X"03de", X"02d8", X"0392", X"0205", X"03a6", X"00a0", X"0328", X"0182", X"07c9", X"0051", X"0310", X"0281", X"03f0", X"0002", X"047a", X"02a2", X"0435", X"0307", X"02e4", X"0000", X"050a", X"0163", X"030d", X"0326", X"0134", X"041a", X"0259", X"02d2", X"0493", X"00f8", X"0363", X"03c3", X"0070", X"000e", X"0316", X"039a", X"0307", X"01d6", X"0266", X"0071", X"02db", X"05d6", X"03ee", X"047d", X"0561", X"03f2", X"0241", X"0271", X"0577", X"0197", X"0458", X"01dd", X"03a3", X"02c9", X"044b", X"02ef", X"0339", X"01bd", X"041f", X"0288", X"013e", X"0354", X"021a", X"0041", X"0563", X"02c8", X"0411", X"01ac", X"0269", X"05a4", X"0308", X"0636", X"0574", X"02e4", X"0215", X"015e", X"01f0", X"038c", X"0138", X"01d5", X"0340", X"00bb", X"030d", X"029e", X"02c1", X"01cb", X"021e", X"0067", X"0256", X"03e5", X"0156", X"02c7", X"03ab", X"0377", X"02a5", X"02a1", X"02b5", X"022b", X"0233", X"0290", X"00e2", X"007c", X"028e", X"021c", X"03a7", X"067b", X"0378", X"01f9", X"0200", X"047d", X"0384", X"0266", X"03c0", X"0296", X"0420", X"02ac", X"0151", X"0231", X"05e3", X"0383", X"05de", X"0468", X"041f", X"031b", X"0380", X"00ca", X"04b7", X"0366", X"0103", X"01ea", 16 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 X"0420", X"0391", X"03b5", X"048c", X"0249", X"040d", X"0461", X"02ce", X"00c0", X"0335", X"025a", X"0514", X"05f5", X"0547", X"03a0", X"045d", X"0b00", X"0fc7", X"4630", X"6c6f", X"12f7", X"079e", X"060b", X"0589", X"04af", X"0451", X"057f", X"04d5", X"037c", X"0486", X"02f4", X"0255", X"035d", X"02f6", X"0306", X"01a7", X"044c", X"02a9", X"04ce", X"0417", X"0411", X"029c", X"028f", X"0334", X"0176", X"03bd", X"02ad", X"019a", X"0382", X"01a6", X"004a", X"0615", X"00fd", X"05a7", X"00da", X"001d", X"0373", X"0525", X"0350", X"00cc", X"0258", X"0429", X"03a2", X"05fb", X"02a9", X"0146", X"02ff", X"01e7", X"00d7", X"022d", X"012c", X"04b4", X"03c2", X"0424", X"02c8", X"021e", X"053d", X"00ab", X"0101", X"0361", X"02e6", X"00fe", X"0450", X"02e5", X"0367", X"0470", X"0244", X"0605", X"0a55", X"09d9", X"14aa", X"5b63", X"52c1", X"110a", X"096a", X"048d", X"0671", X"0145", X"0372", X"035c", X"0353", X"0313", X"012e", X"029b", X"03cb", X"038c", X"030e", X"006b", X"0520", X"01fc", X"01ae", X"0213", X"01bd", X"01dd", X"03a3", X"0528", X"044a", X"0238", X"0337", X"04e9", X"0267", X"0543", X"03a5", X"0194", X"02dd", X"0016", X"00c8", X"044b", X"00b5", X"0355", X"0323", X"005c", X"05ad", X"03ab", X"02a4", X"00b1", X"056b", X"043d", X"0131", X"03a2", X"03ba", X"01b8", X"030f", X"024b", X"005f", X"02c0", X"0084", X"02af", X"0277", X"02b5", X"0239", X"0234", X"039a", X"01ab", X"030e", X"011f", X"020d", X"0432", X"04bd", X"01d7", X"0560", X"0637", X"09e1", X"1683", X"7638", X"3d41", X"107b", X"08a8", X"04c8", X"0551", X"0430", X"03fb", X"0458", X"007d", X"03c6", X"028f", X"0302", X"02fa", X"045d", X"0450", X"01e2", X"0522", X"0103", X"021a", X"0276", X"02cf", X"013e", X"005f", X"02cf", X"0319", X"019d", X"05c2", X"03dd", X"0237", X"0194", X"031b", X"037a", X"01fb", X"0139", X"0135", X"0139", X"0064", X"020d", X"0135", X"00dd", X"0143", X"0044", X"02a0", X"0489", X"008b", X"0153", X"04c0", X"0245", X"01b7", X"040a", X"0442", X"01e5", X"031f", X"036d", X"036f", X"015b", X"021d", X"04fe", X"00ae", X"039a", X"039a", X"0176", X"0007", X"0266", X"00fc", X"0367", X"0346", X"078d", X"0448", X"0821", X"0a26", X"19c6", X"9ab7", X"31d2", X"0e88", X"07ae", X"06b5", X"0352", X"0688", X"0292", X"0336", X"058f", X"0278", X"0019", X"036c", X"03e5", X"03a6", X"0011", X"022c", X"029b", X"0342", X"0094", X"02a1", X"033e", X"04c9", X"0063", X"0260", X"032a", X"033a", X"03fc", X"0221", X"0243", X"041f", X"01f9", X"023b", X"020b", X"0038", X"0513", X"016a", X"0195", X"0426", X"02b7", X"04de", X"00c7", X"0354", X"0189", X"02db", X"00a6", X"0021", X"0097", X"0151", X"01d6", X"029f", X"014d", X"0225", X"02c8", X"0559", X"026d", X"019f", X"0184", X"03c6", X"00cc", X"04ee", X"022b", X"05d0", X"0292", X"0452", X"059c", X"0416", X"0036", X"01cd", X"06c0", X"0654", X"08fc", X"1e77", X"b64a", X"28dd", X"0b8f", X"085a", X"05cb", X"0478", X"04b7", X"00dc", X"037f", X"00f3", X"0026", X"002e", X"0411", X"0371", X"0219", X"03d3", X"03e2", X"00d7", X"04e8", X"00a6", X"01d7", X"01d3", X"03b2", X"045e", X"02a5", X"03c2", X"01c5", X"0317", X"0278", X"0165", X"03ac", X"006d", X"0577", X"00b6", X"031c", X"0236", X"0301", X"02a4", X"037e", X"04d9", X"01b9", X"0453", X"0236", X"0099", X"0071", X"0329", X"0036", X"009e", X"023d", X"01fd", X"0648", X"020e", X"0352", X"0460", X"0446", X"0274", X"009c", X"006b", X"04b8", X"029a", X"062b", X"012f", X"01a7", X"04bb", X"021e", X"0352", X"050a", X"0309", X"0577", X"0567", X"0bb6", X"0b64", X"21e6", X"c547", X"21a2", X"0a52", X"069b", X"0519", X"030b", X"07fa", X"0319", X"02cd", X"03f8", X"03f7", X"0010", X"0213", X"02c8", X"03f5", X"03b2", X"01c3", X"013e", X"0444", X"0158", X"0364", X"043d", X"0026", X"0160", X"00fd", X"0425", X"0197", X"047b", X"00f4", X"03eb", X"0503", X"0387", X"0341", X"04ea", X"03fd", X"0392", X"010c", X"0129", X"03ad", X"0087", X"044a", X"03cf", X"02a6", X"01fd", X"01d6", X"0508", X"04f0", X"0113", X"0276", X"0144", X"0022", X"011a", X"038e", X"0187", X"003e", X"028d", X"01dd", X"02d3", X"01df", X"01dc", X"0199", X"03b4", X"023e", X"01bb", X"026a", X"022b", X"0326", X"0381", X"04fd", X"0297", X"0899", X"0aba", X"270d", X"ae41", X"19a0", X"09ce", X"094c", X"06fa", X"04f4", X"0300", X"0130", X"024b", X"03e9", X"0367", X"02e7", X"066f", X"0573", X"0438", X"03ee", X"02ea", X"00b3", X"055b", X"022a", X"0285", X"0262", X"0515", X"0527", X"03c9", X"01b1", X"0231", X"01f7", X"0164", X"033b", X"0097", X"02ba", X"009e", X"02d0", X"026e", X"024f", X"01bf", X"00bc", X"0407", X"029a", X"02a2", X"03a3", X"037d", X"04cb", X"01da", X"0094", X"036b", X"0061", X"0241", X"037f", X"00bc", X"0209", X"026a", X"0403", X"0381", X"058a", X"0338", X"01d5", X"05a8", X"0440", X"02d5", X"02d4", X"043f", X"069d", X"030e", X"03ca", X"0326", X"07d2", X"02b8", X"052e", X"050b", X"0e64", X"34ff", X"8dfa", X"190f", X"09f2", X"0724", X"040b", X"0660", X"034a", X"045e", X"0582", X"048c", X"02a5", X"0177", X"02a7", X"03d5", X"0501", X"016d", X"01db", X"0192", X"00a1", X"03cd", X"0192", X"02a7", X"037a", X"031a", X"00d0", X"01d5", X"038c", X"0266", X"0448", X"01d2", X"028a", X"0416", X"021a", X"0249", X"03af", X"03b0", X"04e8", X"021f", X"0106", X"03fe", X"03ac", X"017a", X"0502", X"022a", X"04ce", X"0594", X"0080", X"045c", X"0798", X"028d", X"0249", X"0285", X"0250", X"012f", X"0368", 17 507 X"05ed", X"028d", X"0530", X"04db", X"037d", X"01d6", X"03f9", X"0009", 508 X"0509", X"029d", X"00da", X"001d", X"0205", X"04a5", X"02cf", X"023f", 509 X"020a", X"01c2", X"01ad", X"02c6", X"02b8", X"0150", X"00f7", X"0178", 510 X"0266", X"0442", X"0163", X"01e5", X"0280", X"0192", X"01ff", X"0040", 511 X"01d6", X"0209", X"0307", X"0186", X"037e", X"01db", X"01df", X"029f", 512 X"0370", X"03e1", X"00e6", X"0313", X"003f", X"0542", X"01c6", X"022c", 513 X"0275", X"0417", X"003f", X"03b6", X"023f", X"068d", X"02a8", X"036a", 514 X"02b2", X"013f", X"01f3", X"03a9", X"02db", X"04ca", X"03ce", X"02ca", 515 X"02b9", X"0184", X"02c2", X"01fb", X"011e", X"021b", X"04bf", X"02e7", 516 X"0212", X"046d", X"01b2", X"03a7", X"018c", X"0434", X"0228", X"05a8", 517 X"00f9", X"01e8", X"01da", X"02fb", X"014b", X"0430", X"0328", X"064e", 518 X"02c0", X"04e0", X"01cc", X"01dd", X"02bb", X"004d", X"01d0", X"06be", 519 X"01b6", X"0084", X"0519", X"0326", X"024d", X"04ba", X"02df", X"032e", 520 X"0406", X"0298", X"00d5", X"030a", X"012f", X"04cd", X"0196", X"0334", 521 X"00ab", X"019e", X"059d", X"049e", X"001a", X"0289", X"0421", X"0341", 522 X"0124", X"0348", X"0038", X"0102", X"0351", X"039e", X"00a8", X"01ea", 523 X"012b", X"01a6", X"02ec", X"03d6", X"037a", X"0312", X"048d", X"0336", 524 X"02a6", X"0508", X"019f", X"01b5", X"0188", X"0529", X"026f", X"031e", 525 X"02f8", X"0190", X"0059", X"02b1", X"0369", X"0012", X"0555", X"0386", 526 X"0130", X"0357", X"02ab", X"0156", X"0149", X"0380", X"0290", X"028a", 527 X"0155", X"004e", X"01b1", X"016f", X"0117", X"00ef", X"0361", X"00a1", 528 X"054e", X"00d2", X"01b2", X"03ee", X"02d2", X"017b", X"04b4", X"00a7", 529 X"02a8", X"0236", X"0234", X"0453", X"02eb", X"0302", X"0372", X"0221", 530 X"022e", X"04d3", X"0244", X"0538", X"00ad", X"0324", X"02b1", X"0235", 531 X"00c8", X"0460", X"0404", X"030f", X"018b", X"025b", X"0457", X"0474", 532 X"0059", X"0142", X"02b7", X"034e", X"02eb", X"037f", X"0053", X"041e", 533 X"03c4", X"0319", X"01ad", X"00f7", X"0509", X"024b", X"0245", X"0357", 534 X"0238", X"04e0", X"03c2", X"041e", X"0069", X"0211", X"0295", X"05e9", 535 X"0169", X"013a", X"01d4", X"0306", X"0056", X"0036", X"041c", X"0164", 536 X"00df", X"034d", X"01d5", X"015b", X"037e", X"03d8", X"047c", X"03c9", 537 X"05d2", X"0215", X"0008", X"007e", X"0397", X"0193", X"01cd", X"01f0" 538 ); 539 540 signal z0, z1, z2, z3, z4, sv : unsigned(13 downto 0) := (others => '0'); -fir filter on input 541 542 signal bram_addr, bram_addr_reg : unsigned(11 downto 0):=(others => '0'); -for BRAM inference 543 signal bram_data : std_logic_vector(15 downto 0):= (others => '0'); 544 545 begin 546 547 fir_proc: 548 process(adc_clk) is begin 549 if rising_edge(adc_clk) then 550 -if sys_rst = '1' then 551 -- z1 <= (others => '0'); 552 -- z2 <= (others => '0'); 553 -- z3 <= (others => '0'); 554 -- z4 <= (others => '0'); 555 -else 556 z1 <= z0; 557 z2 <= z1; 558 z3 <= z2; 559 z4 <= z3; 560 -end if; 561 end if; 562 end process; 563 564 z0 <= "00"&unsigned(dac_data(23 downto 12));-- take top 12 bits 565 sv <= z1+z2+z3+z4; 566 bram_addr <= sv(13 downto 2); -- 4th order FIR v1/4 + v2/4 + v3/4 + v4/4 567 568 569 read_bram: 570 process(dac_clk) is begin 571 if rising_edge(dac_clk) then 572 bram_addr_reg <= bram_addr; 573 end if; 574 end process; 575 bram_data <= EMULATOR_DATA(to_integer(bram_addr_reg)); 576 577 adc_data <= bram_data; 18 578 579 580 end architecture black_box_emulator; 1.1.6 FSM.vhdl 1 library IEEE; 2 use IEEE.STD_LOGIC_1164.ALL; 3 use IEEE.STD_LOGIC_UNSIGNED.ALL; 4 5 -- Uncomment the following library declaration if using 6 -- arithmetic functions with Signed or Unsigned values 7 --use IEEE.NUMERIC_STD.ALL; 8 9 -- Uncomment the following library declaration if instantiating 10 -- any Xilinx primitives in this code. 11 --library UNISIM; 12 --use UNISIM.VComponents.all; 13 14 entity FSM is 15 PORT( 16 clk : in STD_LOGIC; 17 reset : in STD_LOGIC; 18 ipm_fifo_empty : in STD_LOGIC; 19 cmd : in STD_LOGIC_VECTOR(7 downto 0); 20 scan_min : in STD_LOGIC_VECTOR(31 downto 0); 21 scan_max : in STD_LOGIC_VECTOR(31 downto 0); 22 scan_step : in STD_LOGIC_VECTOR(31 downto 0); 23 smp_step : in STD_LOGIC_VECTOR(31 downto 0); 24 scan_pos : out STD_LOGIC_VECTOR(31 downto 0); 25 status : out STD_LOGIC_VECTOR(7 downto 0); 26 sample_en : out STD_LOGIC; 27 cmd_reg_reset : out STD_LOGIC); 28 end FSM; 29 30 architecture Behavioral of FSM is 31 TYPE state IS (ST_WAIT,ST_INIT,ST_CHK,ST_ERR_PAR,ST_ERR_MEM,ST_ERR_SCAN,ST_PRESCAN,ST_SCAN,ST _FIFO_WAIT); 32 signal cur_state,next_state : state; 33 34 TYPE status_array_type IS ARRAY(state) of STD_LOGIC_VECTOR(7 downto 0); -array of potential statuses 35 constant state_to_status : status_array_type :=( 36 ST_WAIT => x"00", 37 ST_INIT => x"43", 38 ST_CHK => x"54", 39 ST_ERR_PAR => x"60", 40 ST_ERR_MEM => x"62", 41 ST_ERR_SCAN => x"61", 42 ST_PRESCAN => x"54", 43 ST_SCAN => x"55", 44 ST_FIFO_WAIT=> x"56" 45 ); 46 47 --TEMP SIGNALS 48 signal track_sps,scan_diff, t_sps,t_scan_pos : STD_LOGIC_VECTOR(31 downto 0):=(others=>'0'); 49 signal check_nsamp1, check_nsamp2 : STD_LOGIC_VECTOR(63 downto 0):=(others=>'0'); 50 --random constants to take care of 51 constant SCAN_BEGIN : STD_LOGIC_VECTOR(7 downto 0) := x"53"; 52 constant SCAN_ABORT_CMD : STD_LOGIC_VECTOR(7 downto 0) := x"00"; 53 constant SCAN_PRECOLL : STD_LOGIC_VECTOR(7 downto 0) := x"54"; 54 constant SCAN_COLL : STD_LOGIC_VECTOR(7 downto 0) := x"55"; 55 constant SCAN_POSTCOLL : STD_LOGIC_VECTOR(7 downto 0) := x"56"; 56 constant ERR_BADPAR : STD_LOGIC_VECTOR(7 downto 0) := x"60"; 57 constant ERR_FAULTSCAN : STD_LOGIC_VECTOR(7 downto 0) := x"61"; 58 constant ERR_NOMEM : STD_LOGIC_VECTOR(7 downto 0) := x"61"; 59 constant MAXMEM : STD_LOGIC_VECTOR(31 downto 0) := x"01000000"; 60 61 begin 19 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 --heavy_math: process(clk) is --begin -- if rising_edge(clk) then scan_diff <= scan_max - scan_min; check_nsamp1 <= ((scan_max - scan_min)*smp_step) ; check_nsamp2 <= (MAXMEM*scan_step); -- end if; --end process; --process for moore based output mealy_fsm:process(clk,reset) begin if(reset = '1')then cur_state <= ST_WAIT; elsif(rising_edge(clk))then cmd_reg_reset <= '0'; sample_en <= '0'; CASE cur_state IS --wait until UIM has asked for values WHEN ST_WAIT => sample_en <= '0'; --don't write values from the FIFO t_scan_pos <=x"00000000"; if(cmd = SCAN_BEGIN) then next_state <= ST_INIT; else next_state <= cur_state; end if; --load values into registers WHEN ST_INIT => --fpga_ready <= '1'; --write values to FIFO next_state <= ST_CHK; --check for correct parameters WHEN ST_CHK => --if(ipm_fifo_empty = '1')then --is FIFO empty? --next_state <= ST_FIFO_WAIT; if(scan_min >= scan_max) then -- failing here? next_state <= ST_ERR_PAR; elsif(scan_step > scan_diff) then -- failing here? next_state <= ST_ERR_PAR; --elsif ( check_nsamp1 < check_nsamp2 )then -- next_state <= ST_ERR_MEM; else next_state <= ST_PRESCAN; end if; --scan the minimum WHEN ST_PRESCAN => --fpga_ready <= '1'; --start writing values to FIFO t_scan_pos <= scan_min; next_state <= ST_SCAN; track_sps <= (others=>'0'); --full scanning function WHEN ST_SCAN => if(cmd = SCAN_ABORT_CMD) then next_state <= ST_ERR_SCAN; else sample_en <= '1'; --begin writing values from FIFO if (track_sps >= smp_step) then track_sps <= (others=>'0'); t_scan_pos <= t_scan_pos + scan_step; else track_sps <= track_sps + x"00000001"; -- increment to SPS value end if; if(t_scan_pos > scan_max) then --sample_en <= '0'; next_state <= ST_FIFO_WAIT; 20 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 else --sample_en <= '0'; next_state <= cur_state; end if; end if; --Wait until FIFO has WHEN ST_FIFO_WAIT => if(ipm_fifo_empty cmd_reg_reset next_state <= else next_state <= end if; finished being read = '1') then <= '1'; ST_WAIT; cur_state; --invalid scan input state WHEN ST_ERR_PAR => if(cmd = x"00") then next_state <= ST_WAIT; else next_state <= cur_state; --I think this is wrong (infinite loop) end if; --no memory available WHEN ST_ERR_MEM => if(cmd = ERR_NOMEM) then next_state <= ST_WAIT; else next_state <= cur_state; end if; --Something went wrong with the scanning WHEN ST_ERR_SCAN => if(cmd = ERR_FAULTSCAN) then next_state <= ST_WAIT; else next_state <= cur_state; end if; END CASE; cur_state <= next_state; end if; END process; scan_pos <= t_scan_pos; status <= state_to_status(cur_state); end Behavioral; 1.1.7 FSM2.vhdl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity FSM2 is PORT( clk reset ipm_fifo_empty : in : in : in STD_LOGIC; STD_LOGIC; STD_LOGIC; 21 19 cmd : in STD_LOGIC_VECTOR(7 downto 0); 20 scan_min : in STD_LOGIC_VECTOR(31 downto 0); 21 scan_max : in STD_LOGIC_VECTOR(31 downto 0); 22 scan_step : in STD_LOGIC_VECTOR(31 downto 0); 23 smp_step : in STD_LOGIC_VECTOR(31 downto 0); 24 scan_start : in STD_LOGIC_VECTOR(31 downto 0); 25 scan_stop : in STD_LOGIC_VECTOR(31 downto 0); 26 overview_scan_step : in STD_LOGIC_VECTOR(31 downto 0); 27 scan_pos : out STD_LOGIC_VECTOR(31 downto 0); 28 status : out STD_LOGIC_VECTOR(7 downto 0); 29 overview_en : out STD_LOGIC; 30 sample_en : out STD_LOGIC; 31 som_status : out STD_LOGIC; 32 cmd_reg_reset : out STD_LOGIC); 33 end FSM2; 34 35 architecture Behavioral of FSM2 is 36 TYPE state IS (ST_WAIT,ST_INIT,ST_CHK,ST_ERR_PAR,ST_ERR_MEM,ST_ERR_SCAN,ST_PRESCAN,ST_SCAN,ST _FIFO_WAIT); 37 signal 38 --cur_state, 39 next_state : state; 40 alias cur_state : state is next_state ; 41 42 TYPE status_array_type IS ARRAY(state) of STD_LOGIC_VECTOR(7 downto 0); -array of potential statuses 43 constant state_to_status : status_array_type :=( 44 ST_WAIT => x"00", 45 ST_INIT => x"43", 46 ST_CHK => x"54", 47 ST_ERR_PAR => x"60", 48 ST_ERR_MEM => x"62", 49 ST_ERR_SCAN => x"61", 50 ST_PRESCAN => x"54", 51 ST_SCAN => x"55", 52 ST_FIFO_WAIT=> x"56" 53 ); 54 55 --TEMP SIGNALS 56 signal track_sps,track_oss, t_sps,t_scan_pos : STD_LOGIC_VECTOR(31 downto 0); 57 --signal scan_diff : STD_LOGIC_VECTOR(31 downto 0); 58 signal t_sample_en,t_overview_en : STD_LOGIC; 59 -signal check_nsamp1, check_nsamp2 : STD_LOGIC_VECTOR(63 downto 0) :=(others=>'0'); 60 --random constants to take care of 61 constant SCAN_BEGIN : STD_LOGIC_VECTOR(7 downto 0) := x"53"; 62 constant SCAN_ABORT_CMD : STD_LOGIC_VECTOR(7 downto 0) := x"00"; 63 constant SCAN_PRECOLL : STD_LOGIC_VECTOR(7 downto 0) := x"54"; 64 constant SCAN_COLL : STD_LOGIC_VECTOR(7 downto 0) := x"55"; 65 constant SCAN_POSTCOLL : STD_LOGIC_VECTOR(7 downto 0) := x"56"; 66 constant ERR_BADPAR : STD_LOGIC_VECTOR(7 downto 0) := x"60"; 67 constant ERR_FAULTSCAN : STD_LOGIC_VECTOR(7 downto 0) := x"61"; 68 constant ERR_NOMEM : STD_LOGIC_VECTOR(7 downto 0) := x"62"; 69 constant MAXMEM : STD_LOGIC_VECTOR(31 downto 0) := x"01000000"; 70 71 begin 72 73 74 --process for moore based output 75 mealy_fsm:process(clk,reset) 76 begin 77 if(reset = '1')then 78 cur_state <= ST_WAIT; 79 elsif(rising_edge(clk))then 80 --som_status <= '1'; 81 cmd_reg_reset <= '0'; 82 83 CASE cur_state IS 84 85 --wait until UIM has asked for values 86 WHEN ST_WAIT => 87 t_scan_pos <= (others=>'0'); 22 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 track_sps track_oss <= (others=>'0'); <= (others=>'0'); if(cmd = SCAN_BEGIN) then next_state <= ST_INIT; else next_state <= ST_WAIT; end if; --load values into registers WHEN ST_INIT => t_scan_pos <= (others=>'0'); track_sps <= (others=>'0'); track_oss <= (others=>'0'); next_state <= ST_CHK; --check for correct parameters WHEN ST_CHK => t_scan_pos <= (others=>'0'); track_sps <= (others=>'0'); track_oss <= (others=>'0'); --if(ipm_fifo_empty = '1')then --is FIFO empty? --next_state <= ST_FIFO_WAIT; --if(scan_min >= scan_max) then -- failing here? -- next_state <= ST_ERR_PAR; --elsif(scan_step > scan_diff) then -- failing here? -- next_state <= ST_ERR_PAR; --elsif ( check_nsamp1 < check_nsamp2 )then -- next_state <= ST_ERR_MEM; --else next_state <= ST_PRESCAN; --end if; --scan the minimum WHEN ST_PRESCAN => t_scan_pos <= scan_start; next_state <= ST_SCAN; track_sps track_oss <= (others=>'0'); <= (others=>'0'); --full scanning function WHEN ST_SCAN => --som_status <= '0'; t_scan_pos <= t_scan_pos + scan_step; if(t_sample_en='1')then track_sps <= (others=>'0'); else track_sps <= track_sps + 1; end if; if(t_overview_en ='1')then track_oss <= (others=>'0'); else track_oss <= track_oss + 1; end if; if(cmd = SCAN_ABORT_CMD) then next_state <= ST_ERR_SCAN; elsif (t_scan_pos > scan_stop) then next_state <= ST_FIFO_WAIT; else next_state <= ST_SCAN; end if; --Wait until FIFO WHEN ST_FIFO_WAIT t_scan_pos <= track_sps <= track_oss <= has finished being read => (others=>'0'); (others=>'0'); (others=>'0'); 23 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 if(ipm_fifo_empty cmd_reg_reset next_state <= else next_state <= end if; = '1') then <= '1'; ST_WAIT; ST_FIFO_WAIT; --invalid scan input state WHEN ST_ERR_PAR => t_scan_pos <= (others=>'0'); track_sps <= (others=>'0'); track_oss <= (others=>'0'); if(cmd = x"00") then next_state <= ST_WAIT; else next_state <= ST_ERR_PAR; end if; --no memory available WHEN ST_ERR_MEM => t_scan_pos <= (others=>'0'); track_sps <= (others=>'0'); track_oss <= (others=>'0'); if(cmd = ERR_NOMEM) then next_state <= ST_WAIT; else next_state <= ST_ERR_MEM; end if; --Something went wrong with the scanning WHEN ST_ERR_SCAN => t_scan_pos <= (others=>'0'); track_sps <= (others=>'0'); track_oss <= (others=>'0'); if(cmd = ERR_FAULTSCAN) then next_state <= ST_WAIT; else next_state <= ST_ERR_SCAN; end if; END CASE; -- cur_state <= next_state; end if; END process; t_sample_en <= '1' when ((t_scan_pos > scan_min) AND (t_scan_pos < scan_max) AND (cur_state = ST_SCAN) AND (track_sps >= smp_step)) else '0'; t_overview_en <= '1' when ((t_scan_pos > scan_start) AND (t_scan_pos < scan_stop) AND (cur_state = ST_SCAN) AND (track_oss >= overview_scan_step)) else '0'; sample_en <= t_sample_en; overview_en <= t_overview_en; scan_pos <= t_scan_pos; status <= state_to_status(cur_state); end Behavioral; 1.1.8 ipm_fifo.vhdl 1 2 3 4 5 6 --------------------------------------------------------------------------------This file is owned and controlled by Xilinx and must be used solely --for design, simulation, implementation and creation of design files --limited to Xilinx devices or technologies. Use with non-Xilinx --devices or technologies is expressly prohibited and immediately --terminates your license. -- 24 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 ---XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" SOLELY --FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY --PROVIDING THIS DESIGN, CODE, OR INFORMATION AS ONE POSSIBLE --IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, XILINX IS --MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE FROM ANY --CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING ANY --RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY --DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE --IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR --REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF --INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --PARTICULAR PURPOSE. ----Xilinx products are not intended for use in life support appliances, --devices, or systems. Use in such applications are expressly --prohibited. ----(c) Copyright 1995-2012 Xilinx, Inc. --All rights reserved. ----------------------------------------------------------------------------------------------------------------------------------------------------------------- You must compile the wrapper file IPM_FIFO.vhd when simulating -- the core, IPM_FIFO. When compiling the wrapper file, be sure to -- reference the XilinxCoreLib VHDL simulation library. For detailed -- instructions, please refer to the "CORE Generator Help". -- The synthesis directives "translate_off/translate_on" specified -- below are supported by Xilinx, Mentor Graphics and Synplicity -- synthesis tools. Ensure they are correct for your synthesis tool(s). LIBRARY ieee; USE ieee.std_logic_1164.ALL; -- synthesis translate_off LIBRARY XilinxCoreLib; -- synthesis translate_on ENTITY IPM_FIFO IS PORT ( rst : IN STD_LOGIC; wr_clk : IN STD_LOGIC; rd_clk : IN STD_LOGIC; din : IN STD_LOGIC_VECTOR(63 DOWNTO 0); wr_en : IN STD_LOGIC; rd_en : IN STD_LOGIC; dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); full : OUT STD_LOGIC; overflow : OUT STD_LOGIC; empty : OUT STD_LOGIC; rd_data_count : OUT STD_LOGIC_VECTOR(10 DOWNTO 0) ); END IPM_FIFO; ARCHITECTURE IPM_FIFO_a OF IPM_FIFO IS -- synthesis translate_off COMPONENT wrapped_IPM_FIFO PORT ( rst : IN STD_LOGIC; wr_clk : IN STD_LOGIC; rd_clk : IN STD_LOGIC; din : IN STD_LOGIC_VECTOR(63 DOWNTO 0); wr_en : IN STD_LOGIC; rd_en : IN STD_LOGIC; dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); full : OUT STD_LOGIC; overflow : OUT STD_LOGIC; empty : OUT STD_LOGIC; rd_data_count : OUT STD_LOGIC_VECTOR(10 DOWNTO 0) ); END COMPONENT; -- Configuration specification FOR ALL : wrapped_IPM_FIFO USE ENTITY XilinxCoreLib.fifo_generator_v8_3(behavioral) GENERIC MAP ( 25 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 c_add_ngc_constraint => 0, c_application_type_axis => 0, c_application_type_rach => 0, c_application_type_rdch => 0, c_application_type_wach => 0, c_application_type_wdch => 0, c_application_type_wrch => 0, c_axi_addr_width => 32, c_axi_aruser_width => 1, c_axi_awuser_width => 1, c_axi_buser_width => 1, c_axi_data_width => 64, c_axi_id_width => 4, c_axi_ruser_width => 1, c_axi_type => 0, c_axi_wuser_width => 1, c_axis_tdata_width => 64, c_axis_tdest_width => 4, c_axis_tid_width => 8, c_axis_tkeep_width => 4, c_axis_tstrb_width => 4, c_axis_tuser_width => 4, c_axis_type => 0, c_common_clock => 0, c_count_type => 0, c_data_count_width => 13, c_default_value => "BlankString", c_din_width => 64, c_din_width_axis => 1, c_din_width_rach => 32, c_din_width_rdch => 64, c_din_width_wach => 32, c_din_width_wdch => 64, c_din_width_wrch => 2, c_dout_rst_val => "0", c_dout_width => 8, c_enable_rlocs => 0, c_enable_rst_sync => 1, c_error_injection_type => 0, c_error_injection_type_axis => 0, c_error_injection_type_rach => 0, c_error_injection_type_rdch => 0, c_error_injection_type_wach => 0, c_error_injection_type_wdch => 0, c_error_injection_type_wrch => 0, c_family => "spartan6", c_full_flags_rst_val => 1, c_has_almost_empty => 0, c_has_almost_full => 0, c_has_axi_aruser => 0, c_has_axi_awuser => 0, c_has_axi_buser => 0, c_has_axi_rd_channel => 0, c_has_axi_ruser => 0, c_has_axi_wr_channel => 0, c_has_axi_wuser => 0, c_has_axis_tdata => 0, c_has_axis_tdest => 0, c_has_axis_tid => 0, c_has_axis_tkeep => 0, c_has_axis_tlast => 0, c_has_axis_tready => 1, c_has_axis_tstrb => 0, c_has_axis_tuser => 0, c_has_backup => 0, c_has_data_count => 0, c_has_data_counts_axis => 0, c_has_data_counts_rach => 0, c_has_data_counts_rdch => 0, c_has_data_counts_wach => 0, c_has_data_counts_wdch => 0, c_has_data_counts_wrch => 0, c_has_int_clk => 0, 26 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 c_has_master_ce => 0, c_has_meminit_file => 0, c_has_overflow => 1, c_has_prog_flags_axis => 0, c_has_prog_flags_rach => 0, c_has_prog_flags_rdch => 0, c_has_prog_flags_wach => 0, c_has_prog_flags_wdch => 0, c_has_prog_flags_wrch => 0, c_has_rd_data_count => 1, c_has_rd_rst => 0, c_has_rst => 1, c_has_slave_ce => 0, c_has_srst => 0, c_has_underflow => 0, c_has_valid => 0, c_has_wr_ack => 0, c_has_wr_data_count => 0, c_has_wr_rst => 0, c_implementation_type => 2, c_implementation_type_axis => 1, c_implementation_type_rach => 1, c_implementation_type_rdch => 1, c_implementation_type_wach => 1, c_implementation_type_wdch => 1, c_implementation_type_wrch => 1, c_init_wr_pntr_val => 0, c_interface_type => 0, c_memory_type => 1, c_mif_file_name => "BlankString", c_msgon_val => 1, c_optimization_mode => 0, c_overflow_low => 0, c_preload_latency => 0, c_preload_regs => 1, c_prim_fifo_type => "8kx4", c_prog_empty_thresh_assert_val => 4, c_prog_empty_thresh_assert_val_axis => 1022, c_prog_empty_thresh_assert_val_rach => 1022, c_prog_empty_thresh_assert_val_rdch => 1022, c_prog_empty_thresh_assert_val_wach => 1022, c_prog_empty_thresh_assert_val_wdch => 1022, c_prog_empty_thresh_assert_val_wrch => 1022, c_prog_empty_thresh_negate_val => 5, c_prog_empty_type => 0, c_prog_empty_type_axis => 5, c_prog_empty_type_rach => 5, c_prog_empty_type_rdch => 5, c_prog_empty_type_wach => 5, c_prog_empty_type_wdch => 5, c_prog_empty_type_wrch => 5, c_prog_full_thresh_assert_val => 8189, c_prog_full_thresh_assert_val_axis => 1023, c_prog_full_thresh_assert_val_rach => 1023, c_prog_full_thresh_assert_val_rdch => 1023, c_prog_full_thresh_assert_val_wach => 1023, c_prog_full_thresh_assert_val_wdch => 1023, c_prog_full_thresh_assert_val_wrch => 1023, c_prog_full_thresh_negate_val => 8188, c_prog_full_type => 0, c_prog_full_type_axis => 5, c_prog_full_type_rach => 5, c_prog_full_type_rdch => 5, c_prog_full_type_wach => 5, c_prog_full_type_wdch => 5, c_prog_full_type_wrch => 5, c_rach_type => 0, c_rd_data_count_width => 11, c_rd_depth => 65536, c_rd_freq => 1, c_rd_pntr_width => 16, c_rdch_type => 0, c_reg_slice_mode_axis => 0, 27 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 c_reg_slice_mode_rach => 0, c_reg_slice_mode_rdch => 0, c_reg_slice_mode_wach => 0, c_reg_slice_mode_wdch => 0, c_reg_slice_mode_wrch => 0, c_underflow_low => 0, c_use_common_overflow => 0, c_use_common_underflow => 0, c_use_default_settings => 0, c_use_dout_rst => 1, c_use_ecc => 0, c_use_ecc_axis => 0, c_use_ecc_rach => 0, c_use_ecc_rdch => 0, c_use_ecc_wach => 0, c_use_ecc_wdch => 0, c_use_ecc_wrch => 0, c_use_embedded_reg => 0, c_use_fifo16_flags => 0, c_use_fwft_data_count => 1, c_valid_low => 0, c_wach_type => 0, c_wdch_type => 0, c_wr_ack_low => 0, c_wr_data_count_width => 14, c_wr_depth => 8192, c_wr_depth_axis => 1024, c_wr_depth_rach => 16, c_wr_depth_rdch => 1024, c_wr_depth_wach => 16, c_wr_depth_wdch => 1024, c_wr_depth_wrch => 16, c_wr_freq => 1, c_wr_pntr_width => 13, c_wr_pntr_width_axis => 10, c_wr_pntr_width_rach => 4, c_wr_pntr_width_rdch => 10, c_wr_pntr_width_wach => 4, c_wr_pntr_width_wdch => 10, c_wr_pntr_width_wrch => 4, c_wr_response_latency => 1, c_wrch_type => 0 ); -- synthesis translate_on BEGIN -- synthesis translate_off U0 : wrapped_IPM_FIFO PORT MAP ( rst => rst, wr_clk => wr_clk, rd_clk => rd_clk, din => din, wr_en => wr_en, rd_en => rd_en, dout => dout, full => full, overflow => overflow, empty => empty, rd_data_count => rd_data_count ); -- synthesis translate_on END IPM_FIFO_a; 28 1.1.9 platform.ucf # # # # # # # # # # # # # # # # Copyright (C) 2009-2012 Chris McClelland This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #=============================================================================== # Standard interfaces #=============================================================================== NET "clk" LOC="L15"; NET "reset" LOC="T15"; #=============================================================================== # USB interface #=============================================================================== NET "fx2Clk_in" LOC="C10" | IOSTANDARD=LVTTL; # IFCLK NET "fx2Addr_out<0>" LOC="A14" | IOSTANDARD=LVTTL; # PA4/FIFOADR0 NET "fx2Addr_out<1>" LOC="B14" | IOSTANDARD=LVTTL; # PA5/FIFOADR1 NET NET NET NET NET NET NET NET "fx2Data_io<0>" "fx2Data_io<1>" "fx2Data_io<2>" "fx2Data_io<3>" "fx2Data_io<4>" "fx2Data_io<5>" "fx2Data_io<6>" "fx2Data_io<7>" LOC="A2" LOC="D6" LOC="C6" LOC="B3" LOC="A3" LOC="B4" LOC="A4" LOC="C5" | | | | | | | | IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; # # # # # # # # PB0/FD0 PB1/FD1 PB2/FD2 PB3/FD3 PB4/FD4 PB5/FD5 PB6/FD6 PB7/FD7 NET "fx2Read_out" NET "fx2OE_out" NET "fx2GotData_in" LOC="F13" LOC="A15" LOC="C15" | IOSTANDARD=LVTTL; | IOSTANDARD=LVTTL; | IOSTANDARD=LVTTL; # RDY0/SLRD # PA2/SLOE # CTL2/FLAGC NET "fx2Write_out" NET "fx2GotRoom_in" NET "fx2PktEnd_out" LOC="E13" LOC="A9" LOC="C4" | IOSTANDARD=LVTTL; | IOSTANDARD=LVTTL; | IOSTANDARD=LVTTL; # RDY1/SLWR # CTL1/FLAGB # PA6/PKTEND #=============================================================================== # On-board peripheral signals #=============================================================================== NET "led_out<0>" LOC="U18" | IOSTANDARD=LVTTL; NET "led_out<1>" LOC="M14" | IOSTANDARD=LVTTL; NET "led_out<2>" LOC="N14" | IOSTANDARD=LVTTL; NET "led_out<3>" LOC="L14" | IOSTANDARD=LVTTL; NET "led_out<4>" LOC="M13" | IOSTANDARD=LVTTL; NET "led_out<5>" LOC="D4" | IOSTANDARD=LVTTL; NET "led_out<6>" LOC="P16" | IOSTANDARD=LVTTL; NET "led_out<7>" LOC="N12" | IOSTANDARD=LVTTL; NET NET NET NET NET NET NET NET "sw_in<0>" "sw_in<1>" "sw_in<2>" "sw_in<3>" "sw_in<4>" "sw_in<5>" "sw_in<6>" "sw_in<7>" LOC="A10" LOC="D14" LOC="C14" LOC="P15" LOC="P12" LOC="R5" LOC="T5" LOC="E4" | | | | | | | | IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; # # # # # # # # SW0 SW1 SW2 SW3 SW4 SW5 SW6 SW7 29 #=============================================================================== #VGA GAIN SIGNALS #=============================================================================== NET "adg_dout" LOC="R11" | IOSTANDARD=LVTTL; #5 NET "adg_sclk" LOC="T12" | IOSTANDARD=LVTTL; #6 NET "adg_sync" LOC="N10" | IOSTANDARD=LVTTL; #7 NET "adg_reset" LOC="M10" | IOSTANDARD=LVTTL; #8 #=============================================================================== #SOM SIGNALS #=============================================================================== PIN "clk_mngr_inst/clkout2_buf.O" CLOCK_DEDICATED_ROUTE = FALSE; #PIN "clk_mngr_inst/clkout3_buf.O" CLOCK_DEDICATED_ROUTE = FALSE; #For higher quality SOM #NET "SOM_wclk" LOC="V9" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L62P_D5 JA CLK_N - 1 #NET "SOM_bclk" LOC="T3" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L62N_D6 JA D0_N - 2 #NET "som_start" LOC ="V4" | IOSTANDARD=LVTTL; #JA D0_P - 4 #NET "som_data" LOC="T9" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L64N_D9, JA CLK_P - 3 #NET "som_error" LOC="T4" | IOSTANDARD=LVTTL; #For low quality SOM NET "som_data<0>" LOC name = JA-D0_N NET "som_data<1>" LOC name = JA-D0_P NET "som_data<2>" LOC name = JA-D2_N NET "som_data<3>" LOC name = JA-D2_P NET "som_data<4>" LOC name = JA-CLK_N NET "som_data<5>" LOC name = JA-CLK_P NET "som_data<6>" LOC name = JA-D1_N NET "som_data<7>" LOC name = JA-D1_P = "T3" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L62N_D6, Sch = "R3" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L62P_D5, Sch = "P6" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L64N_D9, Sch = "N5" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L64P_D8, Sch = "V9" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L32N_GCLK28, Sch = "T9" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L32P_GCLK29, Sch = "V4" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L63N, Sch = "T4" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L63P, Sch NET "hv_en" LOC = "U16"| IOSTANDARD=LVTTL; #=============================================================================== #IPM SIGNALS #=============================================================================== NET "IPM_clk_out" LOC="R10" | IOSTANDARD=LVTTL; NET "IPM_clk_in" LOC="U10" | IOSTANDARD=LVTTL; #NET "IPM_clk_in" CLOCK_DEDICATED_ROUTE=FALSE; ## onboard VHDCI #IPM IO #0 BB1-14 VHCDI FPGA 25 IO14-P U8 NET "IPM_Data<0>" LOC = Sch name = EXP-IO14_P #1 BB1-13 23 IO13-P M8 UCF "U8"| IOSTANDARD=LVTTL; NET "IPM_Data<1>" LOC = "M8"| Sch name = EXP-IO13_P #2 BB2-28 59 IO14-N V8 IOSTANDARD=LVTTL; NET "IPM_Data<2>" LOC Sch name = EXP-IO14_N #3 BB2-27 57 IO13-N = "V8"| IOSTANDARD=LVTTL; # # Bank Bank Bank = = = 2, 2, 2, Pin Pin Pin name name name = = = IO_L41P, *IO_L40P, IO_L41N_VREF, N8 NET "IPM_Data<3>" LOC = "N8"| Sch name = EXP-IO13_N #4 BB2-26 56 IO12-N T8 IOSTANDARD=LVTTL; NET "IPM_Data<4>" LOC = "T8"| IOSTANDARD=LVTTL; Sch name = EXP-IO12_N #5 BB2-25 54 IO11-N V10 NET "IPM_Data<5>" LOC = "V10"| IOSTANDARD=LVTTL; Sch name = EXP-IO11_N #6 BB2-24 49 IO10-N T10 # # Bank # Bank = 2, # Bank = 2, = 2, Pin name = *IO_L40N, Pin name = IO_L31N_GCLK30_D15, Pin name = IO_L30N_GCLK0_USERCCLK, 30 NET "IPM_Data<6>" LOC = "T10"| IOSTANDARD=LVTTL; Sch name = EXP-IO10_N #7 BB2-23 47 IO9-N V11 NET "IPM_Data<7>" LOC = Sch name = EXP-IO9_N #8 BB2-22 46 IO8-N N9 "V11"| NET "IPM_Data<8>" LOC = Sch name = EXP-IO8_N #9 BB2-21 44 IO7-N P11 "N9"| NET "IPM_Data<9>" LOC = Sch name = EXP-IO7_N #10 BB2-20 43 IO6-N V12 "P11"| NET "IPM_Data<10>" LOC = Sch name = EXP-IO6_N #11 BB2-19 41 IO5-N T11 IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; "V12"| IOSTANDARD=LVTTL; IOSTANDARD=LVTTL; NET "IPM_Data<11>" LOC = "T11"| IOSTANDARD=LVTTL; Sch name = EXP-IO5_N #12 BB2-18 40 IO4-N N11 NET "IPM_Data<12>" LOC = Sch name = EXP-IO4_N #13 BB2-17 38 IO3-N V13 "N11"| IOSTANDARD=LVTTL; NET "IPM_Data<13>" LOC = "V13"| IOSTANDARD=LVTTL; Sch name = EXP-IO3_N #14 BB2-16 37 IO2-N V15 NET "IPM_Data<14>" LOC = Sch name = EXP-IO2_N #15 BB2-15 35 IO1-N V16 "V15"| IOSTANDARD=LVTTL; NET "IPM_Data<15>" LOC = "V16"| IOSTANDARD=LVTTL; Sch name = EXP-IO1_N # Bank = 2, Pin name = IO_L29N_GCLK2, # Bank = 2, # Bank = 2, Pin name = *IO_L22N, # Bank = 2, Pin name = *IO_L20N, Bank = 2, Pin name = *IO_L19N, # # Bank = 2, # Bank = Bank = # Bank = 2, name = IO_L23N, Pin name = IO_L16N_VREF, 2, # Bank = 2, # Pin Pin name = *IO_L15N, Pin name = IO_L14N_D12, 2, Pin name = *IO_L5N, Pin name = IO_L2N_CMPMOSI, #=============================================================================== # Timing constraint of FX2 48MHz clock "fx2Clk_in" #=============================================================================== NET "fx2Clk_in" TNM_NET = "fx2Clk_in"; TIMESPEC "TS_clk" = PERIOD "fx2Clk_in" 20 ns HIGH 50 %; 1.1.10 top_level.vhdl 1 library ieee; 2 3 use ieee.std_logic_1164.all; 4 use ieee.STD_LOGIC_UNSIGNED.all; 5 6 entity top_level is 7 port( 8 --Clocks 9 clk : in STD_LOGIC; -standard atlys clock 10 IPM_clk_in : in STD_LOGIC; --IPM input clock 11 IPM_data : in STD_LOGIC_VECTOR(15 downto 0); -- IPM DATA 12 IPM_clk_out : out STD_LOGIC; --IPM output clock 13 --SOM_bclk : out STD_LOGIC; --bit clock for SOM 14 --SOM_wclk : out STD_LOGIC; --World clock for SOM 15 som_data : out STD_LOGIC_VECTOR(7 downto 0); --signal to send DAC data from 16 adg_sclk : out STD_LOGIC; 17 adg_sync : out STD_LOGIC; 18 adg_dout : out STD_LOGIC; 31 19 adg_reset : out STD_LOGIC; 20 hv_en : out STD_LOGIC; 21 -- FX2 interface ---------------------------------------------------------------------------22 fx2Clk_in : in std_logic; -- 48MHz clock from FX2 23 fx2Addr_out : out std_logic_vector(1 downto 0); -select FIFO: "10" for EP6OUT, "11" for EP8IN 24 fx2Data_io : inout std_logic_vector(7 downto 0); -- 8-bit data to/from FX2 25 26 -- When EP6OUT selected: 27 fx2Read_out : out std_logic; -- asserted (activelow) when reading from FX2 28 fx2OE_out : out std_logic; -- asserted (activelow) to tell FX2 to drive bus 29 fx2GotData_in : in std_logic; -- asserted (activehigh) when FX2 has data for us 30 31 -- When EP8IN selected: 32 fx2Write_out : out std_logic; -- asserted (activelow) when writing to FX2 33 fx2GotRoom_in : in std_logic; -- asserted (activehigh) when FX2 has room for more data from us 34 fx2PktEnd_out : out std_logic; -- asserted (activelow) when a host read needs to be committed early 35 36 -- Onboard peripherals ---------------------------------------------------------------------37 reset : in STD_LOGIC; 38 led_out : out std_logic_vector(7 downto 0); -- eight LEDs 39 sw_in : in std_logic_vector(7 downto 0) -- eight switches 40 ); 41 end top_level; 42 43 architecture behavioral of top_level is 44 --CONSTANTS 45 constant stream_reg : INTEGER := 1; 46 constant overview_stream_reg : INTEGER := 2; 47 constant minval_min_addr : INTEGER := 32; 48 constant maxval_min_addr : INTEGER := 36; 49 constant increment_min_addr : INTEGER := 40; 50 constant sps_min_addr : INTEGER := 44; 51 constant scanstart_min_addr : INTEGER := 48; 52 constant scanstop_min_addr : INTEGER := 52; 53 constant overview_min_addr : INTEGER := 56; 54 55 constant vga_gain_reg : INTEGER := 64; 56 constant gpio_reg : INTEGER := 68; 57 constant uim_cmd_reg : INTEGER := 126; 58 constant fsm_status : INTEGER := 127; 59 --random signals 60 signal rst_high : STD_LOGIC := '0'; --make a default level high reset 61 -- Channel read/write interface ---------------------------------------------------------------62 signal chanAddr : std_logic_vector(6 downto 0); -- the selected channel (0-127) 63 64 -- Host >> FPGA pipe: 65 signal h2fData : std_logic_vector(7 downto 0); -data lines used when the host writes to a channel 66 signal h2fValid : std_logic; -'1' means "on the next clock rising edge, please accept the data on h2fData" 67 signal h2fReady : std_logic; -channel logic can drive this low to say "I'm not ready for more data yet" 68 69 -- Host << FPGA pipe: 70 signal f2hData : std_logic_vector(7 downto 0); -data lines used when the host reads from a channel 71 signal f2hValid : std_logic; -channel logic can drive this low to say "I don't have data ready for you" 72 signal f2hReady : std_logic; -'1' means "on the next clock rising edge, put your next byte of data on f2hData" 73 -- --------------------------------------------------------------------------------------------74 signal t_IPM_data : STD_LOGIC_VECTOR(15 downto 0); -- IPM DATA 32 75 -- Needed so that the comm_fpga module can drive both fx2Read_out and fx2OE_out 76 signal fx2Read : std_logic; 77 --CLOCK_MANAGER SIGNALS 78 signal sys_clko : STD_LOGIC; 79 signal SOM_clko : STD_LOGIC; 80 signal clk_lck : STD_LOGIC; 81 signal IPM_clko : STD_LOGIC; 82 signal bclk : STD_LOGIC; 83 84 --FIFO signals 85 signal ipm_fifo_in : STD_LOGIC_VECTOR(63 dow nto 0); 86 signal rd_data_count,rd_data_count_overview : STD_LOGIC_VECTOR(10 downto 0); 87 signal get_sample,data_stream_enable,ipm_fifo_empty : STD_LOGIC; 88 signal ipm_fifo_empty_overview,get_overview_sample,data_stream_enable_overview : STD _LOGIC; 89 signal ready : STD_LOGIC; 90 signal ipm_fifo_out,ipm_fifo_out_overview : STD_LOGIC_VECTOR(7 downto 0 ); 91 92 --FSM signals 93 signal t_scan_min,t_scan_max,t_scan_step,t_sps,scan_posit : STD_LOGIC_VECTOR(31 downto 0) :=(others=>'0'); 94 signal t_scan_start,t_scan_stop,t_overview_scan : STD_LOGIC_VECTOR(31 downto 0):=(others= >'0'); 95 -signal fsm_status : STD_LOGIC_VECTOR(7 downto 0); 96 signal cmd_rst : STD_LOGIC; 97 signal t_f2hReady : STD_LOGIC; 98 signal t_ipm_fifo_empty : STD_LOGIC; 99 signal t_som_start : STD_LOGIC; 100 --register Signals 101 TYPE regArray IS ARRAY (0 TO 127) OF STD_LOGIC_VECTOR(7 downto 0); 102 signal reg_next,reg : regArray :=((others=>(others=>'0'))); 103 begin 104 --reset is active high 105 rst_high <= NOT(reset); 106 IPM_clk_out <= IPM_clko; 107 hv_en <= reg(gpio_reg)(0); 108 --t_IPM_data <= IPM_data; 109 110 111 fakefir: block is 112 signal d0, d1, d2, d3, d4, d5, d6, d7 : std_logic_vector(18 downto 0); 113 signal sum : std_logic_vector(18 downto 0); 114 begin 115 116 fakefirproc: process is 117 begin 118 if rising_edge(IPM_clk_in) then 119 if rst_high = '1' then 120 d0 <= (others => '0'); 121 d1 <= (others => '0'); 122 d2 <= (others => '0'); 123 d3 <= (others => '0'); 124 d4 <= (others => '0'); 125 d5 <= (others => '0'); 126 d6 <= (others => '0'); 127 d7 <= (others => '0'); 128 else 129 d0 <= "000" & IPM_data; 130 d1 <= d0; 131 d2 <= d1; 132 d3 <= d2; 133 d4 <= d3; 134 d5 <= d4; 135 d6 <= d5; 136 d7 <= d6; 137 sum <= d0+d1+d2+d3+d4+d5+d6+d7; 138 end if; 139 end if; 140 end process fakefirproc; 141 33 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 t_IPM_data <= sum(18 downto 3); end block fakefir; gain_stage: entity work.adg714s3w port map( clk => bclk, reset => rst_high, reg_data => reg(vga_gain_reg), adg_sclk => adg_sclk, adg_sync => adg_sync, adg_dout => adg_dout, adg_reset => adg_reset ); --filter_FIR: entity work.IPM_filt --port map( -- clk => IPM_clk_in, -- rfd => open, -- rdy => open, -- din => IPM_data, -- dout => t_IPM_data --); -- som_start <= t_som_start; -- SOM_bclk <= bclk; --fake values to test -- test_blockram: entity work.analog_interface -- port map( -dac_clk => bclk, -adc_clk => IPM_clko, -dac_data => scan_posit(31 downto 8), -adc_data => t_IPM_data, -control => x"00", -status => open -- ); --SOM Instantiation -- som_inst : entity work.dac_count -- port map( -scan_pos => scan_posit, -dac_clk => bclk, -dac_out => som_data, -wrld_clk => SOM_wclk -); --CLOCK GENERATOR GOES HERE clk_mngr_inst: entity work.clockmanager port map( --CLOCK INPUT CLK_IN1 => clk, --CLOCK OUTPUTS sys_clk => sys_clko, IPM_clk => IPM_clko, SOM_clk => bclk, --Status/Control signals RESET_Clk => rst_high, LOCKED_clk => clk_lck ); --IPM FIFO DECLARATION GOES HERE ipm_fifo : entity work.IPM_FIFO PORT MAP ( rst => rst_high, --wr_clk => IPM_clk_in, wr_clk => IPM_clk_in, rd_clk => fx2Clk_in, din => ipm_fifo_in, wr_en => get_sample, rd_en => data_stream_enable, dout => ipm_fifo_out, full => open, --needs work overflow => open, --needs work empty => ipm_fifo_empty, rd_data_count => rd_data_count ); 34 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 -283 284 285 286 287 ipm_fifo_overview: entity work.IPM_FIFO port map( rst => rst_high, --wr_clk => IPM_clk_in, wr_clk => IPM_clk_in, rd_clk => fx2Clk_in, din => ipm_fifo_in, wr_en => get_overview_sample, rd_en => data_stream_enable_overview, dout => ipm_fifo_out_overview, full => open, --needs work overflow => open, --needs work empty => ipm_fifo_empty_overview, rd_data_count => rd_data_count_overview ); som_data <= scan_posit(31 downto 24); ipm_fifo_in <= scan_posit(31 downto 0) & t_IPM_data(15 downto 0) & x"0BAD"; data_stream_enable <= (f2hReady) when chanAddr = "0000001" else '0'; data_stream_enable_overview <= (f2hReady) when chanAddr = "0000010" else '0'; --Generator for 128 registers and for the code for registers to take in new data decodeGen: FOR I IN 2 TO 126 GENERATE blk1: block is signal reset_reg : std_logic; begin cmd_rst_gen:if i = 126 generate reset_reg <= cmd_rst or rst_high ; end generate; everything_else: if i < 126 generate reset_reg <= rst_high ; end generate; reg_next(i) <= h2fdata when i = CONV_INTEGER(chanAddr) else reg(i); -- Infer registers process(reset_reg, fx2Clk_in, h2fValid) begin if reset_reg='1' then reg(i) <= x"00"; elsif ( rising_edge(fx2Clk_in) ) and h2fValid = '1' then reg(i) <= reg_next(i); end if; end process; end block; END GENERATE; t_ipm_fifo_empty <= ipm_fifo_empty AND ipm_fifo_empty_overview; --FINITE STATE MACHINE GOES HERE sys_FSM: entity work.FSM2 port map( clk => IPM_clk_in, --ipm_clk => IPM_clk_in, reset => rst_high, ipm_fifo_empty => t_ipm_fifo_empty, cmd => reg(uim_cmd_reg), scan_min => t_scan_min, scan_max => t_scan_max, scan_step => t_scan_step, smp_step => t_sps, scan_start => t_scan_start, scan_stop => t_scan_stop, overview_scan_step => t_overview_scan, scan_pos => scan_posit, status => reg(fsm_status), sample_en => get_sample, overview_en => get_overview_sample, som_status => open, --t_som_start, cmd_reg_reset => cmd_rst ); t_scan_min <= (reg(minval_min_addr +3) & reg(minval_min_addr +2) 35 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 & & t_scan_max <= (reg(maxval_min_addr +3) & reg(maxval_min_addr +2) & reg(maxval_min_addr +1) & reg(maxval_min_addr +0)); t_scan_step <= t_sps reg(minval_min_addr +1) reg(minval_min_addr +0)); (reg(increment_min_addr +3) & reg(increment_min_addr +2) & reg(increment_min_addr +1) & reg(increment_min_addr +0)); <= & & & t_scan_start<= t_scan_stop<= (reg(sps_min_addr +3) reg(sps_min_addr +2) reg(sps_min_addr +1) reg(sps_min_addr +0)); (reg(scanstart_min_addr +3) & reg(scanstart_min_addr +2) & reg(scanstart_min_addr +1) & reg(scanstart_min_addr +0)); (reg(scanstop_min_addr +3) & reg(scanstop_min_addr +2) & reg(scanstop_min_addr +1) & reg(scanstop_min_addr +0)); t_overview_scan<=(reg(overview_min_addr +3) & reg(overview_min_addr +2) & reg(overview_min_addr +1) & reg(overview_min_addr +0)); WITH chanAddr SELECT f2hdata <= ipm_fifo_out when "0000001", ipm_fifo_out_overview when "0000010", reg(fsm_status) when "1111111", reg(CONV_INTEGER(chanAddr)) when others; led_out <= reg(CONV_INTEGER(sw_in(6 downto 0))) when sw_in(7) = '1' else scan_posit(31 downto 24) when sw_in = "00000001" --"0000001" & t_som_start when sw_in(7) = '1' else rd_data_count(10 downto 3); h2fReady <= '1'; f2hValid <= '1'; -- CommFPGA module fx2Read_out <= fx2Read; fx2OE_out <= fx2Read; fx2Addr_out(1) <= '1'; -- Use EP6OUT/EP8IN, not EP2OUT/EP4IN. comm_fpga : entity work.comm_fpga port map( -- FX2 interface fx2Clk_in => fx2Clk_in, fx2FifoSel_out => fx2Addr_out(0), fx2Data_io => fx2Data_io, fx2Read_out => fx2Read, fx2GotData_in => fx2GotData_in, fx2Write_out => fx2Write_out, fx2GotRoom_in => fx2GotRoom_in, fx2PktEnd_out => fx2PktEnd_out, -- Channel read/write interface chanAddr_out => chanAddr, h2fData_out => h2fData, h2fValid_out => h2fValid, h2fReady_in => h2fReady, f2hData_in => f2hData, 36 361 f2hValid_in 362 f2hReady_out 363 ); 364 365 end behavioral; 366 367 368 => f2hValid, => f2hReady 1.2 SOM – AtTiny261 1.2.1 Makefile 1 # ---------------------------------------------------------------------------2 # Makefile to compile and link test program 3 # Based on makefile by: Peter Fleury 4 # Originally based on WinAVR Makefile Template written by Eric B. Weddington, Jˆrg Wunsch, et al. 5 # 6 # Adjust F_CPU below to the clock frequency in Mhz of your AVR target 7 # 8 # ---------------------------------------------------------------------------9 10 # MCU name 11 MCU = attiny261 12 13 14 # Processor frequency. 15 # This will define a symbol, F_CPU, in all source code files equal to the 16 # processor frequency. You can then use this symbol in your source code to 17 # calculate timings. Do NOT tack on a 'UL' at the end, this will be done 18 # automatically to create a 32-bit value in your source code. 19 F_CPU = 7372800 20 21 22 # Output format. (can be srec, ihex, binary) 23 FORMAT = ihex 24 25 26 # Target file name (without extension). 27 TARGET = USI_I2C_Port 28 29 30 # List C source files here. (C dependencies are automatically generated.) 31 SRC = $(TARGET).c USI_TWI_Master.c 32 33 34 # List Assembler source files here. 35 # Make them always end in a capital .S. Files ending in a lowercase .s 36 # will not be considered source files but generated files (assembler 37 # output from the compiler), and will be deleted upon "make clean"! 38 # Even though the DOS/Win* filesystem matches both .s and .S the same, 39 # it will preserve the spelling of the filenames, and gcc itself does 40 # care about how the name is spelled on its command-line. 41 ASRC = 42 43 44 # Optimization level, can be [0, 1, 2, 3, s]. 45 # 0 = turn off optimization. s = optimize for size. 46 # (Note: 3 is not always the best optimization level. See avr-libc FAQ.) 47 OPT = s 48 49 50 # Debugging format. 51 # Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. 52 # AVR Studio 4.10 requires dwarf-2. 53 # AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. 54 DEBUG = dwarf-2 37 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 # List any extra directories to look for include files here. # Each directory must be seperated by a space. # Use forward slashes for directory separators. # For a directory that has spaces, enclose it in quotes. EXTRAINCDIRS = # Compiler flag to set the C Standard level. # c89 = "ANSI" C # gnu89 = c89 plus GCC extensions # c99 = ISO C99 standard (not yet fully implemented) # gnu99 = c99 plus GCC extensions CSTANDARD = -std=gnu99 # Place -D or -U options here #CDEFS = -DF_CPU=$(F_CPU)UL # Place -I options here CINCS = #---------------- Compiler Options ---------------# -g*: generate debugging information # -O*: optimization level # -f...: tuning, see GCC manual and avr-libc documentation # -Wall...: warning level # -Wa,...: tell GCC to pass this to the assembler. # -adhlns...: create assembler listing CFLAGS = -g$(DEBUG) CFLAGS += $(CDEFS) $(CINCS) CFLAGS += -O$(OPT) CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums CFLAGS += -Wall -Wstrict-prototypes CFLAGS += -Wa,-adhlns=$(<:.c=.lst) CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) CFLAGS += $(CSTANDARD) #---------------- Assembler Options ---------------# -Wa,...: tell GCC to pass this to the assembler. # -ahlms: create listing # -gstabs: have the assembler create line number information; note that # for use in COFF files, additional information about filenames # and function names needs to be present in the assembler source # files -- see avr-libc docs [FIXME: not yet described there] ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs #---------------- Library Options ---------------# Minimalistic printf version PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min # Floating point printf version (requires MATH_LIB = -lm below) PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt # If this is left blank, then it will use the Standard printf version. PRINTF_LIB = #PRINTF_LIB = $(PRINTF_LIB_MIN) #PRINTF_LIB = $(PRINTF_LIB_FLOAT) # Minimalistic scanf version SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min # Floating point + %[ scanf version (requires MATH_LIB = -lm below) SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt # If this is left blank, then it will use the Standard scanf version. 38 128 SCANF_LIB = 129 #SCANF_LIB = $(SCANF_LIB_MIN) 130 #SCANF_LIB = $(SCANF_LIB_FLOAT) 131 132 133 MATH_LIB = -lm 134 135 136 137 #---------------- External Memory Options ---------------138 139 # 64 KB of external RAM, starting after internal RAM (ATmega128!), 140 # used for variables (.data/.bss) and heap (malloc()). 141 #EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff 142 143 # 64 KB of external RAM, starting after internal RAM (ATmega128!), 144 # only used for heap (malloc()). 145 #EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff 146 147 EXTMEMOPTS = 148 149 150 151 #---------------- Linker Options ---------------152 # -Wl,...: tell GCC to pass this to linker. 153 # -Map: create map file 154 # --cref: add cross reference to map file 155 LDFLAGS = -Wl,-Map=$(TARGET).map,--cref 156 LDFLAGS += $(EXTMEMOPTS) 157 LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) 158 159 160 161 #---------------- Programming Options (avrdude) ---------------162 163 # Programming hardware: alf avr910 avrisp bascom bsd 164 # dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 165 # 166 # Type: avrdude -c ? 167 # to get a full listing. 168 # 169 AVRDUDE_PROGRAMMER = usbtiny 170 171 # com1 = serial port. Use lpt1 to connect to parallel port. 172 #AVRDUDE_PORT = lpt1 # programmer connected to serial device 173 174 AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m U efuse:w:0x01:m 175 #AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep 176 177 178 # Uncomment the following if you want avrdude's erase cycle counter. 179 # Note that this counter needs to be initialized first using -Yn, 180 # see avrdude manual. 181 #AVRDUDE_ERASE_COUNTER = -y 182 183 # Uncomment the following if you do /not/ wish a verification to be 184 # performed after programming the device. 185 #AVRDUDE_NO_VERIFY = -V 186 187 # Increase verbosity level. Please use this when submitting bug 188 # reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 189 # to submit bug reports. 190 #AVRDUDE_VERBOSE = -v -v 191 192 AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) 193 AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) 194 AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) 195 AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) 196 197 198 199 #---------------- Debugging Options ---------------- 39 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 # For simulavr only - target MCU frequency. DEBUG_MFREQ = $(F_CPU) # Set the DEBUG_UI to either gdb or insight. # DEBUG_UI = gdb DEBUG_UI = insight # Set the debugging back-end to either avarice, simulavr. DEBUG_BACKEND = avarice #DEBUG_BACKEND = simulavr # GDB Init Filename. GDBINIT_FILE = __avr_gdbinit # When using avarice settings for the JTAG JTAG_DEV = /dev/com1 # Debugging port used to communicate between GDB / avarice / simulavr. DEBUG_PORT = 4242 # Debugging host used to communicate between GDB / avarice / simulavr, normally # just set to localhost unless doing some sort of crazy debugging when # avarice is running on a different computer. DEBUG_HOST = localhost #============================================================================ # Define programs and commands. SHELL = sh CC = avr-gcc OBJCOPY = avr-objcopy OBJDUMP = avr-objdump SIZE = avr-size NM = avr-nm AVRDUDE = avrdude REMOVE = rm -f COPY = cp WINSHELL = cmd # Define Messages # English MSG_ERRORS_NONE = Errors: none MSG_BEGIN = -------- begin -------MSG_END = -------- end -------MSG_SIZE_BEFORE = Size before: MSG_SIZE_AFTER = Size after: MSG_COFF = Converting to AVR COFF: MSG_EXTENDED_COFF = Converting to AVR Extended COFF: MSG_FLASH = Creating load file for Flash: MSG_EEPROM = Creating load file for EEPROM: MSG_EXTENDED_LISTING = Creating Extended Listing: MSG_SYMBOL_TABLE = Creating Symbol Table: MSG_LINKING = Linking: MSG_COMPILING = Compiling: MSG_ASSEMBLING = Assembling: MSG_CLEANING = Cleaning project: # Define all object files. OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) # Define all listing files. LST = $(SRC:.c=.lst) $(ASRC:.S=.lst) # Compiler flags to generate dependency files. 40 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d # Combine all necessary flags and optional flags. # Add target processor to flags. ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) # Default target. all: begin gccversion sizebefore build sizeafter end build: elf hex eep lss sym elf: hex: eep: lss: sym: $(TARGET).elf $(TARGET).hex $(TARGET).eep $(TARGET).lss $(TARGET).sym # Eye candy. # AVR Studio 3.x does not check make's exit code but relies on # the following magic strings to be generated by the compile job. begin: @echo @echo $(MSG_BEGIN) end: @echo $(MSG_END) @echo # Display size of file. HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex ELFSIZE = $(SIZE) -A $(TARGET).elf AVRMEM = avr-mem.sh $(TARGET).elf $(MCU) sizebefore: @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ $(AVRMEM) 2>/dev/null; echo; fi sizeafter: @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ $(AVRMEM) 2>/dev/null; echo; fi # Display compiler version information. gccversion : @$(CC) --version # Program the device. program: $(TARGET).hex $(TARGET).eep $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) # Generate avr-gdb config/init file which does the following: # define the reset signal, load the target file, connect to target, and set # a breakpoint at main(). gdb-config: @$(REMOVE) $(GDBINIT_FILE) @echo define reset >> $(GDBINIT_FILE) @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) @echo end >> $(GDBINIT_FILE) @echo file $(TARGET).elf >> $(GDBINIT_FILE) @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE) 41 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 ifeq ($(DEBUG_BACKEND),simulavr) @echo load >> $(GDBINIT_FILE) endif @echo break main >> $(GDBINIT_FILE) debug: gdb-config $(TARGET).elf ifeq ($(DEBUG_BACKEND), avarice) @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) @$(WINSHELL) /c pause else @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ $(DEBUG_MFREQ) --port $(DEBUG_PORT) endif @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. COFFCONVERT=$(OBJCOPY) --debugging \ --change-section-address .data-0x800000 \ --change-section-address .bss-0x800000 \ --change-section-address .noinit-0x800000 \ --change-section-address .eeprom-0x810000 coff: $(TARGET).elf @echo @echo $(MSG_COFF) $(TARGET).cof $(COFFCONVERT) -O coff-avr $< $(TARGET).cof extcoff: $(TARGET).elf @echo @echo $(MSG_EXTENDED_COFF) $(TARGET).cof $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof # Create final output files (.hex, .eep) from ELF output file. %.hex: %.elf @echo @echo $(MSG_FLASH) $@ $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ %.eep: %.elf @echo @echo $(MSG_EEPROM) $@ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ # Create extended listing file from ELF output file. %.lss: %.elf @echo @echo $(MSG_EXTENDED_LISTING) $@ $(OBJDUMP) -h -S $< > $@ # Create a symbol table from ELF output file. %.sym: %.elf @echo @echo $(MSG_SYMBOL_TABLE) $@ $(NM) -n $< > $@ # Link: create ELF output file from object files. .SECONDARY : $(TARGET).elf .PRECIOUS : $(OBJ) %.elf: $(OBJ) @echo 42 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 @echo $(MSG_LINKING) $@ $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) # Compile: create object files from C source files. %.o : %.c @echo @echo $(MSG_COMPILING) $< $(CC) -c $(ALL_CFLAGS) $< -o $@ # Compile: create assembler files from C source files. %.s : %.c $(CC) -S $(ALL_CFLAGS) $< -o $@ # Assemble: create object files from assembler source files. %.o : %.S @echo @echo $(MSG_ASSEMBLING) $< $(CC) -c $(ALL_ASFLAGS) $< -o $@ # Create preprocessed source for use in sending a bug report. %.i : %.c $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ # Target: clean project. clean: begin clean_list end clean_list : @echo @echo $(MSG_CLEANING) $(REMOVE) $(TARGET).hex $(REMOVE) $(TARGET).eep $(REMOVE) $(TARGET).cof $(REMOVE) $(TARGET).elf $(REMOVE) $(TARGET).map $(REMOVE) $(TARGET).sym $(REMOVE) $(TARGET).lss $(REMOVE) $(OBJ) $(REMOVE) $(LST) $(REMOVE) $(SRC:.c=.s) $(REMOVE) $(SRC:.c=.d) $(REMOVE) .dep/* # Include the dependency files. -include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) # Listing of phony targets. .PHONY : all begin finish end sizebefore sizeafter gccversion \ build elf hex eep lss sym coff extcoff \ clean clean_list program debug gdb-config 1.2.2 USI_I2C_Port.c 1 2 3 4 5 6 7 8 9 10 /* * GccApplication3.c * * Created: 11/1/2012 2:32:46 PM * Author: Mary Hatfield */ #include <avr/interrupt.h> //#define F_CPU 8000000UL #include <util/delay.h> // Sets up the default speed for delay.h 43 11 #include <avr/io.h> 12 #include "USI_TWI_Master.h" 13 14 // LED and Button Ports - specific to ATtiny261 15 #define P_LED_1 PB4 // used for init & data signal (for Debug) 16 #define P_LED_2 PB5 // used for debug 17 #define P_LED_3 PB6 18 #define P_LED_4 PA7 19 20 //DAC ports 21 #define P_DAC_ZEROL PA0 22 #define P_DAC_MDI PA1 23 #define P_DAC_MC PA2 24 #define P_DAC_MS PA4 25 #define P_DAC_RST PB3 26 27 //Checking state 28 #define P_HV_EN PB6 29 #define P_HV_GOOD PA7 30 #define P_AIN PA6 31 #define P_AOUT PA5 32 33 //FPGA Ports 34 #define P_FPGA_58 PB7 35 //#define P_FPGA_76 PB2 36 #define P_FPGA_95 PB1 37 #define P_FPGA_17 PB0 38 #define PIN_FPGA PINB 39 40 #define CLK_PERIOD 200 41 #define SNOOZE 100 42 #define TSTBIT(REG, BIT) (REG & (1 << BIT)) 43 44 void blinkEm( uint8_t count, uint8_t led); 45 void shift_out(int addr, int data); 46 void ADCinit (void); 47 unsigned long Read_ADC(void); 48 int DCM_GO(void); 49 50 void main( void ) 51 { 52 enum{ 53 INIT, 54 PROGRAM, 55 WAIT_FOR_DCM, 56 UNMUTE_DAC, 57 CHECKING, 58 MUTE_DAC, 59 } state; 60 state = INIT; 61 62 /* Initialize LED blinkers, out/inputs */ 63 DDRB = _BV(P_LED_1) | _BV(P_LED_2) | _BV(P_HV_EN) | _BV(P_DAC_RST); 64 DDRA = _BV(P_HV_GOOD) | _BV(P_DAC_MDI) | _BV(P_DAC_MC) | _BV(P_DAC_MS) | _BV(P_AIN) | _BV (P_AOUT); 65 while(1){ 66 unsigned long result; 67 int i=0; 68 69 if (PIN_FPGA & _BV(P_FPGA_95)) //if DCM says go, turn off light 70 { 71 PORTB |= _BV(P_HV_EN); 72 } 73 else 74 { 75 PORTB &= ~_BV(P_HV_EN); 76 } 77 78 79 80 81 switch(state){ case INIT: USI_TWI_Master_Initialise(); PORTB |= _BV(P_DAC_RST); //reset, start fresh 44 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 PORTB &= ~_BV(P_DAC_RST); state = PROGRAM; break; case PROGRAM: shift_out (0x10, 0xFF); //write to MDI shift_out (0x11, 0xFF); shift_out(0x12, 0x21); //(21 MUTE on, 20 MUTE off) shift_out(0x13,0x08); //(08 HV low, 18 HV high) shift_out(0x14,0x11); shift_out(0x15,0x01); shift_out(0x96,0x00); shift_out(0x97,0x00); state = WAIT_FOR_DCM; break; case WAIT_FOR_DCM: i=DCM_GO(); if (i=0) { state=WAIT_FOR_DCM; } else { state=UNMUTE_DAC; } break; case UNMUTE_DAC: shift_out(0x12, 0x20); //UNMUTE shift_out(0x13,0x18); //HV EN HIGH- light LED_3 state = CHECKING; // blinkEm(4,P_LED_1); //debug break; case CHECKING: ADCinit(); //check Ain versus Aout, assign diff to int, check int to accepted value result = Read_ADC(); //if good, light LED_4 i=DCM_GO(); if (i=0) { state=CHECKING; } else { state=MUTE_DAC; } break; case MUTE_DAC: shift_out(0x12, 0x21); //MUTE shift_out(0x13,0x08); //HV EN LOW- unlight LED_3 PORTB |= _BV(P_FPGA_17); //flag FPGA _delay_ms(100); state = WAIT_FOR_DCM; break; default: state = INIT; break; } } return; } /*-----------------------------------------------------------------------** DCM_GO - function to see if DCM is ready ** ---------------------------------------------------------------------*/ int DCM_GO(void){ uint8_t but1; uint8_t but1a; uint8_t oldBut=0; int state=0; PORTB = _BV(P_FPGA_95); but1 = ~PIN_FPGA & _BV(P_FPGA_95); if (but1 != oldBut) // look at buttons, invert 45 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 { //_delay_ms(100); // 100ms @ 1MHz clock. but1a = ~PIN_FPGA & _BV(P_FPGA_95); // read again if (but1a == but1) // button has changed { oldBut = but1; if (oldBut > 0) // Switch is pressed { state=1; } } } else { state=0; } return state; } /*-----------------------------------------------------------------------** blinkEm - function to blink LED for count passed in ** Assumes that leds are all on the same port. 1MHz Clock rate. ** ---------------------------------------------------------------------*/ void blinkEm( uint8_t count, uint8_t led){ #if 0 uint8_t i; while (count > 0){ PORTB |= _BV(led); for (i=0;i<5;i++) { _delay_ms(400); } PORTB &= ~_BV(led); for (i=0;i<5;i++) { _delay_ms(400); } count--; } #endif } /*-----------------------------------------------------------------------** shift_out - function to pass DAC commands serially ** _delay_ms(CLK_PERIOD) where the CLK_PERIOD = 200 for now. ** 1MHz Clock rate. ** ---------------------------------------------------------------------*/ void shift_out(int addr, int data){ int i; PORTB &= ~_BV(P_DAC_MS); //set MS to allow writing to MDI //_delay_ms(200); for(i=7; i>=0; i--){ //clk = 0 PORTA &= ~_BV(P_DAC_MC); if ((addr>>i)&(0x01)) PORTA |= _BV(P_DAC_MDI); else PORTA &= ~_BV(P_DAC_MDI); _delay_us(20); //clk = 1; PORTA |= _BV(P_DAC_MC); _delay_us(20); } for(i=7; i>=0; i--){ //clk = 0 PORTA &= ~_BV(P_DAC_MC); if ((data>>i)&(0x01)) PORTA |= _BV(P_DAC_MDI); 46 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 else PORTA &= ~_BV(P_DAC_MDI); _delay_us(20); //clk = 1; PORTA |= _BV(P_DAC_MC); _delay_us(20); } PORTB |= _BV(P_DAC_MS); PORTA &= ~_BV(P_DAC_MDI); PORTA &= ~_BV(P_DAC_MC); //_delay_ms(200); //shut off MDI writing } /*-----------------------------------------------------------------------** ADCinit - function to initialize ADC ** set for differential comparison, ADC4 and ADC5 pin, ** multiplying diff by 20x, clk at 125kHz ** ---------------------------------------------------------------------*/ void ADCinit (void) { ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); ADMUX |= (0 << REFS1) | (0 << REFS0) | (1 << MUX4) | (1 << MUX2); ADCSRA |= (1 << ADEN); _delay_us(5); } /*-----------------------------------------------------------------------** Read_ADC - function to begin ADC conversions ** ** ---------------------------------------------------------------------*/ unsigned long Read_ADC(void) { uint16_t adc_rez=0; ADCSRA |= (1 << ADSC); // Start AD Conversions while ( TSTBIT(ADCSRA, ADSC)); adc_rez = ADCL+256*ADCH; return(adc_rez); } 1.2.3 USI_I2C_Master.c 1 #include <avr/interrupt.h> 2 //#define F_CPU 8000000UL // Sets up the default speed for delay.h 3 #include <util/delay.h> 4 #include <avr/io.h> 5 #include "USI_TWI_Master.h" 6 7 unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char ); 8 unsigned char USI_TWI_Master_Transfer( unsigned char ); 9 unsigned char USI_TWI_Master_Stop( void ); 10 unsigned char USI_TWI_Master_Start( void ); 11 12 union USI_TWI_state 13 { 14 unsigned char errorState; // Can reuse the TWI_state for error states since it will not be needed if there is an error. 15 struct 16 { 17 unsigned char addressMode : 1; 18 unsigned char masterWriteDataMode : 1; 19 unsigned char memReadMode : 1; 20 unsigned char unused : 5; 21 }; 22 } USI_TWI_state; 23 24 /*--------------------------------------------------------------25 USI TWI single master initialization function 26 ---------------------------------------------------------------*/ 27 void USI_TWI_Master_Initialise( void ) 47 28 { 29 PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released st ate. 30 PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released st ate. 31 32 DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output. 33 DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output. 34 35 USIDR = 0xFF; // Preload dataregister with "released level" data. 36 USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts. 37 (1<<USIWM1)|(0<<USIWM0)| // Set USI in Twowire mode. 38 (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counte r clock source 39 (0<<USITC); 40 USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags, 41 (0x0<<USICNT0); // and reset counter. 42 } 43 44 /*--------------------------------------------------------------45 Use this function to get hold of the error message from the last transmission 46 ---------------------------------------------------------------*/ 47 unsigned char USI_TWI_Get_State_Info( void ) 48 { 49 return ( USI_TWI_state.errorState ); // Return error state. 50 } 51 /*--------------------------------------------------------------52 USI Random (memory) Read function. This function sets up for call 53 to USI_TWI_Start_Transceiver_With_Data which does the work. 54 Doesn't matter if read/write bit is set or cleared, it'll be set 55 correctly in this function. 56 57 The msgSize is passed to USI_TWI_Start_Transceiver_With_Data. 58 59 Success or error code is returned. Error codes are defined in 60 USI_TWI_Master.h 61 ---------------------------------------------------------------*/ 62 unsigned char USI_TWI_Start_Random_Read( unsigned char *msg, unsigned char msgSize) 63 { 64 *(msg) &= ~(TRUE<<TWI_READ_BIT); // clear the read bit if it's set 65 USI_TWI_state.errorState = 0; 66 USI_TWI_state.memReadMode = TRUE; 67 68 return (USI_TWI_Start_Transceiver_With_Data( msg, msgSize)); 69 } 70 /*--------------------------------------------------------------71 USI Normal Read / Write Function 72 Transmit and receive function. LSB of first byte in buffer 73 indicates if a read or write cycles is performed. If set a read 74 operation is performed. 75 76 Function generates (Repeated) Start Condition, sends address and 77 R/W, Reads/Writes Data, and verifies/sends ACK. 78 79 Success or error code is returned. Error codes are defined in 80 USI_TWI_Master.h 81 ---------------------------------------------------------------*/ 82 unsigned char USI_TWI_Start_Read_Write( unsigned char *msg, unsigned char msgSize) 83 { 84 85 USI_TWI_state.errorState = 0; // Clears all mode bits also 86 87 return (USI_TWI_Start_Transceiver_With_Data( msg, msgSize)); 88 89 } 90 /*--------------------------------------------------------------91 USI Transmit and receive function. LSB of first byte in buffer 92 indicates if a read or write cycles is performed. If set a read 93 operation is performed. 94 95 Function generates (Repeated) Start Condition, sends address and 96 R/W, Reads/Writes Data, and verifies/sends ACK. 48 97 98 This function also handles Random Read function if the memReadMode 99 bit is set. In that case, the function will: 100 The address in memory will be the second 101 byte and is written *without* sending a STOP. 102 Then the Read bit is set (lsb of first byte), the byte count is 103 adjusted (if needed), and the function function starts over by sending 104 the slave address again and reading the data. 105 106 Success or error code is returned. Error codes are defined in 107 USI_TWI_Master.h 108 ---------------------------------------------------------------*/ 109 unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize) 110 { 111 unsigned char const tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and 112 (0x0<<USICNT0); // set U SI to shift 8 bits i.e. count 16 clock edges. 113 unsigned char const tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and 114 (0xE<<USICNT0); // set US I to shift 1 bit i.e. count 2 clock edges. 115 unsigned char *savedMsg; 116 unsigned char savedMsgSize; 117 118 //This clear must be done before calling this function so that memReadMode can be specified. 119 // USI_TWI_state.errorState = 0; // Clears all mode bits also 120 121 USI_TWI_state.addressMode = TRUE; // Always true for first byte 122 123 #ifdef PARAM_VERIFICATION 124 if(msg > (unsigned char*)RAMEND) // Test if address is outside SRAM space 125 { 126 USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND; 127 return (FALSE); 128 } 129 if(msgSize <= 1) // Test if the transmission buffer is empt y 130 { 131 USI_TWI_state.errorState = USI_TWI_NO_DATA; 132 return (FALSE); 133 } 134 #endif 135 136 #ifdef NOISE_TESTING // Test if any unexpected conditions have arrived prior to this execution. 137 if( USISR & (1<<USISIF) ) 138 { 139 USI_TWI_state.errorState = USI_TWI_UE_START_CON; 140 return (FALSE); 141 } 142 if( USISR & (1<<USIPF) ) 143 { 144 USI_TWI_state.errorState = USI_TWI_UE_STOP_CON; 145 return (FALSE); 146 } 147 if( USISR & (1<<USIDC) ) 148 { 149 USI_TWI_state.errorState = USI_TWI_UE_DATA_COL; 150 return (FALSE); 151 } 152 #endif 153 154 if ( !(*msg & (1<<TWI_READ_BIT)) ) // The LSB in the address byte determines if is a masterRead or masterWrite operation. 155 { 156 USI_TWI_state.masterWriteDataMode = TRUE; 157 } 158 159 // if (USI_TWI_state.memReadMode) 160 // { 161 savedMsg = msg; 162 savedMsgSize = msgSize; 49 163 // } 164 165 if ( !USI_TWI_Master_Start( )) 166 { 167 return (FALSE); // Send a START condition on the TWI bus. 168 } 169 170 /*Write address and Read/Write data */ 171 do 172 { 173 /* If masterWrite cycle (or inital address tranmission)*/ 174 if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode) 175 { 176 /* Write a byte */ 177 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 178 USIDR = *(msg++); // Setup data. 179 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 180 181 /* Clock and verify (N)ACK from slave */ 182 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 183 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 184 { 185 if ( USI_TWI_state.addressMode ) 186 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS; 187 else 188 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 189 return (FALSE); 190 } 191 192 if ((!USI_TWI_state.addressMode) && USI_TWI_state.memReadMode)// means memory start add ress has been written 193 { 194 msg = savedMsg; // start at slave address again 195 *(msg) |= (TRUE<<TWI_READ_BIT); // set the Read Bit on Slave address 196 USI_TWI_state.errorState = 0; 197 USI_TWI_state.addressMode = TRUE; // Now set up for the Read cycle 198 msgSize = savedMsgSize; // Set byte count correctly 199 // NOte that the length should be Slave adrs byte + # bytes to read + 1 (gets decreme nted below) 200 if ( !USI_TWI_Master_Start( )) 201 { 202 USI_TWI_state.errorState = USI_TWI_BAD_MEM_READ; 203 return (FALSE); // Send a START condition on the TWI bu s. 204 } 205 } 206 else 207 { 208 USI_TWI_state.addressMode = FALSE; // Only perform address transmission on ce. 209 } 210 } 211 /* Else masterRead cycle*/ 212 else 213 { 214 /* Read a data byte */ 215 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 216 *(msg++) = USI_TWI_Master_Transfer( tempUSISR_8bit ); 217 218 /* Prepare to generate ACK (or NACK in case of End Of Transmission) */ 219 if( msgSize == 1) // If transmission of last byte was perfor med. 220 { 221 USIDR = 0xFF; // Load NACK to confirm End Of Transmissio n. 222 } 223 else 224 { 225 USIDR = 0x00; // Load ACK. Set data register bit 7 (outp ut for SDA) low. 226 } 227 USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK. 228 } 50 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 }while( --msgSize) ; if (!USI_TWI_Master_Stop()) { return (FALSE); } // Until all data sent/received. // Send a STOP condition on the TWI bus. /* Transmission successfully completed*/ return (TRUE); } /*--------------------------------------------------------------Core function for shifting data in and out from the USI. Data to be sent has to be placed into the USIDR prior to calling this function. Data read, will be return'ed from the function. ---------------------------------------------------------------*/ unsigned char USI_TWI_Master_Transfer( unsigned char temp ) { USISR = temp; // Set USISR according to temp. // Prepare clocking. temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source. (1<<USITC); // Toggle Clock Port. do { _delay_us(T2_TWI); USICR = temp; // Generate positve SCL edge. while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high. _delay_us(T4_TWI); USICR = temp; // Generate negative SCL edge. }while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete. _delay_us(T2_TWI); temp = USIDR; USIDR = 0xFF; DDR_USI |= (1<<PIN_USI_SDA); // Read out data. // Release SDA. // Enable SDA as output. return temp; // Return the data from the USIDR } /*--------------------------------------------------------------Function for generating a TWI Start Condition. ---------------------------------------------------------------*/ unsigned char USI_TWI_Master_Start( void ) { /* Release SCL to ensure that (repeated) Start can be performed */ PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. while( !(PORT_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high. _delay_us(T2_TWI); /* Generate Start Condition */ PORT_USI &= ~(1<<PIN_USI_SDA); _delay_us(T4_TWI); PORT_USI &= ~(1<<PIN_USI_SCL); PORT_USI |= (1<<PIN_USI_SDA); // Force SDA LOW. // Pull SCL LOW. // Release SDA. #ifdef SIGNAL_VERIFY if( !(USISR & (1<<USISIF)) ) { USI_TWI_state.errorState = USI_TWI_MISSING_START_CON; return (FALSE); } #endif return (TRUE); } /*--------------------------------------------------------------Function for generating a TWI Stop Condition. Used to release the TWI bus. ---------------------------------------------------------------*/ unsigned char USI_TWI_Master_Stop( void ) { PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low. PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. 51 302 while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Wait for SCL to go high. 303 _delay_us(T4_TWI); 304 PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. 305 _delay_us(T2_TWI); 306 307 #ifdef SIGNAL_VERIFY 308 if( !(USISR & (1<<USIPF)) ) 309 { 310 USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON; 311 return (FALSE); 312 } 313 #endif 314 315 return (TRUE); 316 } 1.2.4 USI_TWI_Master_h 1 //********** Defines **********// 2 3 // Defines controlling timing limits - SCL <= 100KHz. 4 5 #define SYS_CLK 1000.0 // [kHz] Default for ATtiny2313 6 7 // For use with _delay_us() 8 #define T2_TWI 5 // >4,7us 9 #define T4_TWI 4 // >4,0us 10 11 // Defines error code generating 12 //#define PARAM_VERIFICATION 13 //#define NOISE_TESTING 14 #define SIGNAL_VERIFY // This should probably be on always. 15 16 /**************************************************************************** 17 Bit and byte definitions 18 ****************************************************************************/ 19 #define TWI_READ_BIT 0 // Bit position for R/W bit in "address byte". 20 #define TWI_ADR_BITS 1 // Bit position for LSB of the slave address bits in the init by te. 21 #define TWI_NACK_BIT 0 // Bit position for (N)ACK bit. 22 23 // Note these have been renumbered from the Atmel Apps Note. Most likely errors are now 24 // lowest numbers so they're easily recognized as LED flashes. 25 #define USI_TWI_NO_DATA 0x08 // Transmission buffer is empty 26 #define USI_TWI_DATA_OUT_OF_BOUND 0x09 // Transmission buffer is outside SRAM space 27 #define USI_TWI_UE_START_CON 0x07 // Unexpected Start Condition 28 #define USI_TWI_UE_STOP_CON 0x06 // Unexpected Stop Condition 29 #define USI_TWI_UE_DATA_COL 0x05 // Unexpected Data Collision (arbitration) 30 #define USI_TWI_NO_ACK_ON_DATA 0x02 // The slave did not acknowledge all data 31 #define USI_TWI_NO_ACK_ON_ADDRESS 0x01 // The slave did not acknowledge the address 32 #define USI_TWI_MISSING_START_CON 0x03 // Generated Start Condition not detected on bus 33 #define USI_TWI_MISSING_STOP_CON 0x04 // Generated Stop Condition not detected on bus 34 #define USI_TWI_BAD_MEM_READ 0x0A // Error during external memory read 35 36 // Device dependant defines - These for ATtiny2313. 37 38 #define DDR_USI DDRB 39 #define PORT_USI PORTB 40 #define PIN_USI PINB 41 #define PORT_USI_SDA PORTB5 42 #define PORT_USI_SCL PORTB7 43 #define PIN_USI_SDA PINB5 44 #define PIN_USI_SCL PINB7 45 46 // General defines 47 #define TRUE 1 48 #define FALSE 0 49 50 //********** Prototypes **********// 51 52 52 53 54 55 void USI_TWI_Master_Initialise( void ); unsigned char USI_TWI_Start_Random_Read( unsigned char * , unsigned char ); unsigned char USI_TWI_Start_Read_Write( unsigned char * , unsigned char ); unsigned char USI_TWI_Get_State_Info( void ); 1.3 UIM – Cross Platform GTK Client 1.3.1 complile.sh 1 #!/bin/sh 2 3 TARGNAME=team_spectrum 4 SRC_FILES="userIOusb.c dosa.c dcmusb.c ini.c uim_config.c" 5 FPGALIB=$HOME/Important_Files/RPi/libfpgalink-20120507 6 gcc -m64 -O3 -g -std=gnu99 \ 7 -I$FPGALIB -I$FPGALIB/hdl/common\ 8 -Wl,--relax,--gc-sections,-rpath,\$ORIGIN,-rpath-link,$FPGALIB/linux.x86_64/rel \ 9 -o $TARGNAME $SRC_FILES -L$FPGALIB/linux.x86_64/rel -lfpgalink -lerror \ 10 $(pkg-config --cflags gtk+-2.0 gmodule-2.0 --libs glib-2.0 gtkdatabox ) 11 #gcc $SRC_FILES $(pkg-config --cflags gtk+-2.0 gmodule-2.0 --libs glib-2.0) 12 #gcc -o team_spectrum $SRC_FILES $(pkg-config --cflags gtk+-2.0 gmodule-2.0 --libs glib2.0 gtkdatabox ) 13 echo "it's over" 1.3.2 dcm_compile.sh 1 #!/bin/sh 2 3 TARGNAME=dcmusb_test 4 SRC_FILES="dcmusb_unitTest.c dcmusb.c" 5 FPGALIB=$HOME/Important_Files/RPi/libfpgalink-20120507 6 gcc -m64 -O3 -g -std=c99 \ 7 -I$FPGALIB -I$FPGALIB/hdl/common\ 8 -Wl,--relax,--gc-sections,-rpath,\$ORIGIN,-rpath-link,$FPGALIB/linux.x86_64/rel \ 9 -o $TARGNAME $SRC_FILES -L$FPGALIB/linux.x86_64/rel -lfpgalink -lerror \ 10 $(pkg-config --cflags gtk+-2.0 gmodule-2.0 --libs glib-2.0 gtkdatabox ) 11 #gcc $SRC_FILES $(pkg-config --cflags gtk+-2.0 gmodule-2.0 --libs glib-2.0) 12 #gcc -o team_spectrum $SRC_FILES $(pkg-config --cflags gtk+-2.0 gmodule-2.0 --libs glib2.0 gtkdatabox ) 13 echo "it's over" 1.3.3 dcmusb.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include #include #include #include #include "dcmusb.h" <stdio.h> <stdint.h> <stdlib.h> "libfpgalink.h" #define #define TIMEOUT_MS 1000 BUFFER_SIZE 1024 uint8 *buffer; const char *error = NULL; bool isCommCapable; int fpga_init(void) { //fpgalink initialization function.required in order for proper communication to occur 53 17 flInitialise(); 18 19 //allocate proper amount of size for the data buffer 20 buffer = malloc(BUFFER_SIZE*sizeof(uint8)); 21 return 0; 22 } 23 24 int fpga_connect(const char *vp, struct FLContext **handle) 25 { 26 //return variable(rv) instantiation and boolean flag 27 int rv = 0,status; 28 bool flag,isNeroCapable; 29 char *xsvfFile = "commfpga_system.xsvf"; 30 31 //vendor and product ID for atlys 6. This ID is permanent and will thus never 32 //change unless we use a different fpga 33 const char * ivp = "1443:0007"; 34 35 //load standard cypress FX2 firmware 36 rv = flLoadStandardFirmware(ivp, vp, "D0234", &error); 37 38 //try opening the fpga communication channel 39 rv = flOpen(vp,handle,NULL); 40 41 //this is if the open function fails and the fpga is not ready yet 42 if(rv) 43 { 44 //run through a loop if a vendor and product ID is given(done by default) 45 if (ivp) 46 { 47 int count = 60; 48 49 //try loading the cypress fx2 firmware again 50 rv = flLoadStandardFirmware(ivp, vp, "D0234", &error); 51 52 //waits until device communicates that it is available (NEEDED) 53 //loops in the do/while loop until fpga communicates that it is ready to communic ate 54 do 55 { 56 fflush(stdout); 57 58 //flSleep is exactly like a traditional linux sleep command, waits for 100ms 59 flSleep(1000); 60 61 //tests to make sure the device is available 62 rv = flIsDeviceAvailable(vp, &flag, &error); 63 count--; 64 } while ( !flag && count ); 65 66 //if the system fails then print a failure statement to comand line 67 if ( !flag ) 68 { 69 fprintf(stderr, "FPGALink device did not renumerate properly as %s\n", vp); 70 } 71 72 //now open communication with fpga 73 rv = flOpen(vp, handle, &error); 74 } 75 isNeroCapable = flIsNeroCapable(*handle); 76 if ( xsvfFile ) { 77 //printf("Playing \"%s\" into the JTAG chain on FPGALink device %s...\n", xsvfFil e, vp); 78 if ( isNeroCapable ) { 79 status = flPlayXSVF(*handle, xsvfFile, &error); 80 rv = status; 81 //CHECK(18); 82 } 83 else { 84 fprintf(stderr, "XSVF play requested but device at %s does not support NeroJT AG\n", vp); 85 //FAIL(19); 86 rv = status; 54 87 } 88 } 89 } 90 return rv; 91 } 92 93 int fpga_disconnect(struct FLContext *handle) 94 { 95 //run function to close communication with fpga 96 printf("closing FPGA\n"); 97 flClose(handle); 98 return 0; 99 } 100 101 int fpga_wrReg8(struct FLContext *handle,int regNo, int val) 102 { 103 //load 8 bit version of value into data buffer 104 *buffer = (uint8)(0xff&val); 105 106 //initialize return value 107 int rv = 0; 108 109 //set up variable to a function that checks that the fpga is ready to communicate 110 isCommCapable = flIsCommCapable(handle); 111 if( isCommCapable ) 112 { 113 //run function to write 1 byte to fpga (handle is the struct to communicate with the fpga 114 //regNo is the register number, 1 is the amount of bytes, buffer is the data, and err or 115 //is the error number if there is one (0 is success)) 116 rv = flWriteChannel(handle,TIMEOUT_MS, (uint8)regNo, 1, buffer, &error); 117 } 118 else 119 //fpga is not ready to communicate 120 printf("could not send data to fpga"); 121 if(rv) 122 showFPGAerror(rv); 123 return rv; 124 } 125 126 int fpga_wrReg32(struct FLContext *handle,int regNoBase, int val) 127 { 128 int i,rv=0; 129 uint8 *temp_buff=buffer; 130 //guarentee endianess by individually loading the 32 bit value to the buffer byte by byte 131 buffer[0] = (uint8)(0xff&val); 132 buffer[1] = (uint8)(0xff&(val>>8)); 133 buffer[2] = (uint8)(0xff&(val>>16)); 134 buffer[3] = (uint8)(0xff&(val>>24)); 135 //printf("Buffer is: %c,%c,%c,%c",buffer[0],buffer[1],buffer[2],buffer[3]); 136 //set up variable to a function that checks that the fpga is ready to communicate 137 isCommCapable = flIsCommCapable(handle); 138 if( isCommCapable ) 139 { 140 //run function to write 1 byte to fpga (handle is the struct to communicate with the fpga 141 //regNoBase is the register number base register, 1 is the amount of bytes, buffer is the data, 142 //and error is the error number if there is one (0 is success)) 143 for(i=0;i<4;i++){ 144 rv = flWriteChannel(handle,TIMEOUT_MS, (uint8)regNoBase+i, 1, temp_buff++, &error ); 145 if(rv){ 146 showFPGAerror(rv); 147 return rv; 148 } 149 } 150 } 151 else 152 //fpga is not ready to communicate 153 printf("could not send data to fpga"); 154 return rv; 55 155 } 156 157 int fpga_rdReg8(struct FLContext *handle,int regNo, int *val) 158 { 159 int rv=0; 160 //set up variable to a function that checks that the fpga is ready to communicate 161 isCommCapable = flIsCommCapable(handle); 162 if( isCommCapable ) 163 { 164 //read from the register number into the buffer 165 rv = flReadChannel(handle, TIMEOUT_MS, (uint8)regNo, 1, buffer, &error); 166 } 167 else 168 printf("fpga not ready to communicate\n"); 169 170 //load the value in the buffer into the output val 171 *val = *(buffer); 172 if(rv) 173 showFPGAerror(rv); 174 return rv; 175 } 176 177 int fpga_rdReg32(struct FLContext *handle,int regNoBase,int *val) 178 { 179 int rv=0,i; 180 uint8 *temp_buff=buffer; 181 //set up variable to a function that checks that the fpga is ready to communicate 182 isCommCapable = flIsCommCapable(handle); 183 if( isCommCapable ) 184 { 185 //read from the register number into the buffer starting at regNoBase 186 *val=0; 187 for(i=0;i<4;i++){ 188 rv = flReadChannel(handle, TIMEOUT_MS, (uint8)regNoBase+i, 1, temp_buff++, &error ); 189 if(rv){ 190 showFPGAerror(rv); 191 return rv; 192 } 193 } 194 } 195 else 196 printf("fpga not ready to communicate\n"); 197 //load the values in the buffer in proper endianess into val 198 *val = *(buffer) | (*(buffer+1)<<8) | (*(buffer+2)<<16) | (*(buffer+3)<<24); 199 200 return rv; 201 } 202 203 int fpga_rdStream(struct FLContext *handle, uint32 timeout, uint8 chan, uint32 count, uint8 * buf) 204 { 205 int rv=0; 206 int i; 207 isCommCapable = flIsCommCapable(handle); 208 if( isCommCapable ) 209 { 210 //for(i=0;i<count;i++){ 211 rv = flReadChannel(handle, timeout, chan, count, buf,&error); 212 //printf("value: %c\n",*buf); 213 //} 214 } 215 else 216 printf("fpga not ready to communicate\n"); 217 if(rv) 218 showFPGAerror(rv); 219 return rv; 220 } 221 222 void showFPGAerror(int rv){ 223 switch(rv){ 224 case FL_SUCCESS: printf("libFPGAlink: The operation completed successfully. (%d)\n ",rv); 56 225 break; 226 case FL_ALLOC_ERR: printf("libFPGAlink: There was a memory allocation error.(%d)\n", rv); 227 break; 228 case FL_USB_ERR: printf("libFPGAlink: There was some USBrelated problem.(%d)\n",rv); 229 break; 230 case FL_PROTOCOL_ERR: printf("libFPGAlink: The device is probably not a valid \b FP GALink device.(%d)\n",rv); 231 break; 232 case FL_SYNC_ERR: printf("libFPGAlink: The library was unable to synchronise the de vice's bulk endpoints.(%d)\n",rv); 233 break; 234 case FL_FX2_ERR: printf("libFPGAlink: There was some problem talking to the FX2 ch ip.(%d)\n",rv); 235 break; 236 case FL_JTAG_ERR: printf("libFPGAlink: There was some problem with the NeroJTAG int erface.(%d)\n",rv); 237 break; 238 case FL_FILE_ERR: printf("libFPGAlink: There was a filerelated problem.(%d)\n",rv); 239 break; 240 case FL_WBUF_ERR: printf("libFPGAlink: There was some problem with the write buffer .(%d)\n",rv); 241 break; 242 case FL_BUF_INIT_ERR: printf("libFPGAlink: The CSVF buffer could not be allocated.( %d)\n",rv); 243 break; 244 case FL_BUF_APPEND_ERR: printf("libFPGAlink: The CSVF buffer could not be grown.( %d)\n",rv); 245 break; 246 case FL_BUF_LOAD_ERR: printf("libFPGAlink: The XSVF file could not be loaded.(%d)\n ",rv); 247 break; 248 case FL_UNSUPPORTED_CMD_ERR: printf("libFPGAlink: The XSVF file contains an unsupp orted command.(%d)\n",rv); 249 break; 250 case FL_UNSUPPORTED_DATA_ERR: printf("libFPGAlink: The XSVF file contains an unsupp orted XENDIR or XENDDR.(%d)\n",rv); 251 break; 252 case FL_UNSUPPORTED_SIZE_ERR: printf("libFPGAlink: The XSVF file requires more buff er space than is available.(%d)\n",rv); 253 break; 254 case FL_SVF_PARSE_ERR: printf("libFPGAlink: The SVF file was not parseable.(%d)\ n",rv); 255 break; 256 case FL_INTERNAL_ERR: printf("libFPGAlink: An internal error occurred. Please r eport it!(%d)\n",rv); 257 break; 258 default: printf("libFPGAlink: An undeclared error occurred:(%d)\n",rv); 259 } 260 } 1.3.4 dcmusb.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /* Team Spectrum UIM to DCM interface definition /* Kevin Nicotera and Jacob Dilles /* 9/7/2012 #include "libfpgalink.h" */ */ */ //call this first to initialize communication with the fpga int fpga_init(void); //connect to FPGA //pass pointer to pointer to flContext and fpga_connect will initialize the struct int fpga_connect(const char *vp, struct FLContext **handle); //disconnect from FPGA int fpga_disconnect(struct FLContext *handle); 57 16 //write 8 bits to DCM register number x 17 //val[ 7 downto 0] => REG(regNoBase); 18 int fpga_wrReg8(struct FLContext *handle,int regNo, int val); 19 20 //write 32 bits to DCM starting at register number regNoBase 21 //val[31 downto 24] => REG(regNoBase + 3); 22 //val[23 downto 16] => REG(regNoBase + 2); 23 //val[15 downto 8] => REG(regNoBase + 1); 24 //val[ 7 downto 0] => REG(regNoBase); 25 int fpga_wrReg32(struct FLContext *handle,int regNoBase, int val); 26 27 //read 8 bits from DCM register number x to UIM 28 //REG(regNoBase) => val[ 7 downto 0]; 29 int fpga_rdReg8(struct FLContext *handle,int regNo, int *val); 30 31 //read 32 bits from DCM to UIM starting at register number regNoBase 32 //REG(regNoBase + 3) => val[ 31 downto 24]; 33 //REG(regNoBase + 2) => val[ 23 downto 16]; 34 //REG(regNoBase + 1) => val[ 15 downto 8]; 35 //REG(regNoBase) => val[ 7 downto 0]; 36 int fpga_rdReg32(struct FLContext *handle,int regNoBase,int *val); 37 38 39 int fpga_rdStream(struct FLContext *handle, uint32 timeout, uint8 chan, uint32 count, uint8 *b uf); 40 41 void showFPGAerror(int rv); 1.3.5 dcmusb_unitTest.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 f) 34 35 36 37 38 39 40 #include "dcmusb.h" #include <stdio.h> #include "libfpgalink.h" #define SCAN_MIN_REG (0x32) #define SCAN_MAX_REG (0x36) #define SCAN_STEP_REG (0x40) #define SPS_REG (0x44) #define UI_CMD_REG (0x7E) #define FPGA_CMD_REG (0x7F) #define STREAM_REG (0x00) #define #define #define #define CMD_START (0x53) STATUS_IDLE (0x00) CMD_ABORT (0x00) BAD_PARAM (0x60) void debug(int step); int main(void) { struct FLContext *handle = NULL; const char *vp = "1443:0007"; char regValue; char buff[10000]; int i,num=1; printf("FPGALink device %s\n",vp); debug(0); fpga_init(); debug(1); fpga_connect(vp,&handle); debug(2); //printf("%ld\n",sizeof(int)); fpga_wrReg8(handle,SCAN_MIN_REG,num); //fpga_rdStream(struct FLContext *handle, uint32 timeout, uint8 chan, uint32 count, uint8 *bu for(num=0; num<1000; num++){ fpga_rdStream(handle,1000,STREAM_REG,10000,buff); for(i=0;i<10000;i++){ if(buff[i]){ printf("got some data: %d\n",buff[i]); } } 58 41 42 43 44 45 46 47 48 49 } debug(3); fpga_disconnect(handle); debug(4); } void debug(int step) { printf("at step %d\n",step); } 1.3.6 dosa.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ry; 19 20 21 22 23 24 25 26 27 28 29 30 ", 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include "support.h" #define DATA_LEN (8200) #define OVERVIEW_DATA_LEN (4000) #define OVERVIEW_SCAN_STEP (((1<<31)/OVERVIEW_DATA_LEN)*2) #define START_VALUE_DEF (0) #define STOP_VALUE_DEF (0xFFFFFF00) #define REFRESH_RATE_DEF (10)/*hertz*/ #define IPM_CLK_FREQ_DEF (25000000) #define GAIN_STAGE (7) //#define PRNTTEST #define FTDI_COMM (1) //#define NO_PERFORM uint32_t STOP_VALUE,START_VALUE,IPM_CLK_FREQ,REFRESH_RATE,SCAN_STEP; static int width,center; _scanStr s; int context, str_len, text_pos, interval=100, slow_interval=4000, context, entry_num=0, rota int settings_flag = 1, gain; const char* str2,*begin_entry = "0000000.000"; static const char gain_lookup[16] = {0x00,0x81,0x42,0xC3, 0x24,0xA5,0x66,0xE7, 0x18,0x99,0x5A,0xDB, 0x3C,0xBD,0x7E,0xFF}; const guint grlen = DATA_LEN-10; float x[DATA_LEN],y[DATA_LEN],ox[DATA_LEN],oy[DATA_LEN],ramp[DATA_LEN],low_marker[2] ,high_marker[2]; static float low_marker_height[]={0,ADC_MAX},high_marker_height[]={0,ADC_MAX}; static char* label_names[] = {"Run Mode","Window","Samples/FSR","Offset","Laser Wavelength", "Mirror Reflect.","Mirror Spacing","Min Voltage","Max Voltage "Gain","FSR","Finesse"}; char *volt_div_label = "Hz/Div: 0",*amp_div_label = "A/Div: 0", *hertz_rate_label = "Hz Rate: 0",pixel_diff_str,amp_diff_str,hz_diff_str; static char* setting_names[] = {"setting1","setting2","Save configuration","Save data"}; volatile unsigned int drawing; struct FLContext *handle = NULL; /******* This function is called by exit(int) *****/ void onExit (void) { int rv; do{ fpga_wrReg8(handle,GPIO_REG,HV_OFF); }while(!fpga_rdReg8(handle,GPIO_REG,&rv) || !rv); fpga_wrReg8(handle,UI_CMD_REG,CMD_ABORT);//stop the fpga from running fpga_disconnect(handle); printf ("Closing FPGA safely and exiting program\n"); // should call gtk_main_quit() here } int main( int argc, char **argv ) { /****************************************/ /* Local Variables to the main function */ /****************************************/ 59 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ****/ 91 */ 92 */ 93 / 94 ****/ 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ****/ 112 */ 113 s */ 114 */ 115 ****/ 116 117 118 119 int i; if(load_ini_config()){ //complain } /************************************************/ /* Initializations for GTK+ and the main window */ /************************************************/ gtk_init( &argc, &argv ); //Create Base Design: GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //create top level window gtk_widget_set_size_request (window, 1060, 600);//set size of window g_signal_connect (GTK_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);//allow user to close window gtk_window_set_title (GTK_WINDOW (window), "Team Spectrum: Digital Optical Spectrum Analyzer");//set title of window /****************************************************************/ /* Set Up Graphing Area of Main Window */ /* This section lays out the graphing are of the main window */ /* as specified in the design document */ /****************************************************************/ //Create split between graphing area and settings area GtkWidget *hpane1 = gtk_hpaned_new(); gtk_container_add (GTK_CONTAINER (window), hpane1); //Create vertical box area for both graphs GtkWidget *graph_vbox = gtk_vbox_new(FALSE,0); //pack with respect to beginning of hpane(leftmost) gtk_paned_add1(GTK_PANED(hpane1),graph_vbox); /**************************************************************************************** /* High Resolution Graph Settings /*This area is to set up the high resolution graph. This will allow someone /*to obtain a better visual of information of certain parts of the optical spectrum * /**************************************************************************************** //create databox for high resolution picture of selected spectrum gtk_databox_create_box_with_scrollbars_and_rulers ( &databox_highres, &databoxcontainer_highres, FALSE, FALSE, TRUE, TRUE); //settings for high res graph gtk_databox_set_total_limits (GTK_DATABOX(databox_highres),0, 250000, 300, 0); gtk_box_pack_start(GTK_BOX(graph_vbox), databoxcontainer_highres, 0, 0, 0 ); //force a minimum size for the graph gtk_widget_set_size_request(databoxcontainer_highres,700,450); //allow for zooming gtk_databox_set_enable_zoom (GTK_DATABOX(databox_highres), TRUE); //hopefully get a grid GtkDataboxGraph* high_res_gr = gtk_databox_grid_new (20, 40, &gridColor, 0); //set background color gtk_widget_modify_bg(databox_highres, GTK_STATE_NORMAL,&bgColor); /**************************************************************************************** /* /* /* Center Section for Volts/Div and other Information This will display information for the graphs including (hopefully) x and y coordinate and definitely will include Volts/Div as specified in design document /**************************************************************************************** //center area for selected data GtkWidget *hbox1 = gtk_hbox_new(FALSE,0); //gtk_paned_add2(GTK_PANED(hpane1),vbox2); gtk_box_pack_start(GTK_BOX(graph_vbox), hbox1, 0,0,0); 60 120 121 122 123 124 125 126 127 GtkWidget *lowerGraphDiv = gtk_label_new("Hz/Div: "); GtkWidget *upperGraphDiv = gtk_label_new("A/Div: "); GtkWidget *graphRate = gtk_label_new("Hz Rate: "); gtk_box_pack_start(GTK_BOX(hbox1),lowerGraphDiv,1,0,0); gtk_box_pack_start(GTK_BOX(hbox1),upperGraphDiv,1,0,0); gtk_box_pack_start(GTK_BOX(hbox1),graphRate,1,0,0); 128 /* 129 /* 130 /* 131 /**************************************************************************************** /**************************************************************************************** / Low Resolution Graph Settings * / This area is to set up the high resolution graph. This will allow * / the user to "see the big picture" of the optical spectrum * / / 132 //low resolution graph for big picture of spectrum 133 //gtk_box_pack_start(GTK_BOX(vbox1), lowres_window, 0, 0, 0 ); 134 gtk_databox_create_box_with_scrollbars_and_rulers ( 135 &databox_lowres, &databoxcontainer_lowres, 136 FALSE, FALSE, TRUE, TRUE); 137 //gtk_databox_set_total_limits (GTK_DATABOX(databox_lowres),0, 250000, 300, 0); 138 gtk_box_pack_start(GTK_BOX(graph_vbox), databoxcontainer_lowres, 0, 0, 0 ); 139 gtk_widget_set_size_request(databoxcontainer_lowres,700,115); 140 GtkDataboxGraph* low_res_gr = gtk_databox_grid_new (5, 40, &gridColor, 1); 141 gtk_widget_modify_bg(databox_lowres, GTK_STATE_NORMAL,&bgColor); 142 gtk_databox_graph_add (GTK_DATABOX (databox_lowres), low_res_gr); 143 144 /****************************************************************/ 145 /* Set Up Settings Area of Main Window */ 146 /* This section lays out the settings area of the main window */ 147 /* as specified in the design document */ 148 /****************************************************************/ 149 //Create vertical box area for settings 150 GtkWidget *vbox2 = gtk_vbox_new(FALSE,0); 151 //pack with respect to the end of the hpane(rightmost) 152 gtk_paned_add2(GTK_PANED(hpane1),vbox2); 153 154 //create settings panel with column of labels with text entries 155 GtkWidget *databuttons = gtk_vbutton_box_new(); 156 gtk_box_set_spacing(GTK_BOX(databuttons),10); 157 gtk_box_pack_start(GTK_BOX(vbox2), databuttons, 0, 0, 0 ); 158 159 //create labels with text entries 160 //for loop to create all the text entries and labels 161 for(i=0;i<9;i++){ 162 button_hbox[i] = gtk_hbox_new(FALSE,0); 163 gtk_container_add(GTK_CONTAINER(databuttons),button_hbox[i]); 164 button_label[i] = gtk_label_new(label_names[i]); 165 gtk_box_pack_start(GTK_BOX(button_hbox[i]), button_label[i], 1, 0, 1 ); 166 button_entry[i] = gtk_entry_new_with_max_length(MAX_ENTRY); 167 gtk_editable_set_editable(GTK_EDITABLE(button_entry[i]),TRUE); 168 gtk_entry_set_editable(GTK_ENTRY(button_entry[i]), TRUE); 169 gtk_editable_insert_text(GTK_EDITABLE(button_entry[i]),begin_entry,11,entry_pos); 170 gtk_widget_set_can_focus(button_entry[i],TRUE); 171 gtk_box_pack_start(GTK_BOX(button_hbox[i]), button_entry[i], 1, 0, 1 ); 172 } 173 174 /****************************************************************/ 175 /* Runtime Functions */ 176 /* This are is for functions that will be started at runtime */ 177 /* such as the graphing system and serial input system */ 178 /****************************************************************/ 179 //create signals for graphing functions 180 //Display contents and run program 181 gtk_widget_show_all (window); 182 /*#ifdef FTDIComm 183 //Serial Input stuff// 184 // Set up the shutdown stuff; 185 setupShutdown(); 186 187 fsm_enabled = TRUE; 61 188 //Begins the FSM taking in values from the user from hardware 189 190 // use defined value (OS specific) 191 //printf("about to enable the userIO\n"); 192 char* ftdi_name = FTDI_DEV; 193 GIOChannel *deviceChannel; 194 //deviceChannel = g_io_channel_unix_new(0); 195 //g_io_add_watch(deviceChannel, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL , &doBackgroundIOops, NULL); 196 // Open the file descripter 197 if( openFTDIfd(ftdi_name, &deviceChannel) != 0 ){ 198 printf("Could not open %s\n",ftdi_name); 199 terminate(1); 200 } 201 #endif*/ 202 //Initialize and setup FPGA communication 203 const char *vp = "1443:0007"; 204 fpga_init(); 205 fpga_connect(vp,&handle); 206 fpga_wrReg8(handle,GPIO_REG,HV_ON); 207 scanStr s = scan_init((1<<31)+(1<<29),1<<29,DATA_LEN); 208 g_timeout_add(1,&dcmFSM,s); 209 210 //g_signal_connect(G_OBJECT(graph_vbox),"graph_func",G_CALLBACK(graph_func),NULL); 211 gtk_main(); 212 return 0; 213 } 214 215 /****************************************************************/ 216 /* dcmFSM Function */ 217 /* inputs: fpga scan struct */ 218 /* outputs: TRUE or FALSE to continue running */ 219 /* Functions: finite state machine to take in new values */ 220 /* wait for the FPGA to finish or graph data */ 221 /****************************************************************/ 222 gint dcmFSM(gpointer s){ 223 int stat = 1; 224 static int count = 0; 225 if(fpga_rdReg8(handle,FPGA_CMD_REG,&stat)){ 226 printf("error reading fpga\n"); 227 return FALSE; 228 } 229 switch(state){ 230 case START_SCAN: 231 //scan_init(center,width,DATA_LEN); 232 start_scan(s); 233 state = WAIT_FOR_DATA; 234 break; 235 case WAIT_FOR_DATA: 236 count++; 237 if(stat == FIFO_WAIT){ 238 state = GRAPH; 239 } 240 break; 241 case GRAPH: 242 #ifdef PRNTTEST 243 printf("spins before status ok: %d\n",count); 244 #endif 245 count = 0; 246 graph_func(s); 247 #if 0 248 return FALSE; 249 #endif 250 state = START_SCAN; 251 break; 252 default: 253 state = START_SCAN; 254 } 255 return TRUE; 256 } 257 258 /****************************************************************/ 259 /* start_scan Function */ 62 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 /* inputs: fpga scan struct */ /* outputs: errors from writing to the FPGA */ /* Function: writes information to the FPGA to determine */ /* when to start,stop,step size,samples per step */ /****************************************************************/ int start_scan(scanStr s){ int rv = 0; rv = fpga_rdReg8(handle,FPGA_CMD_REG,&(s->status)); //rv = fpga_wrReg8(handle,GAIN_REG,0); /* Min value for the overview (0) */ rv = fpga_wrReg32(handle,START_REG,START_VALUE); /* Max value for the overview (max int value) */ rv = fpga_wrReg32(handle,STOP_REG,((uint32_t)STOP_VALUE)-(s->scan_step)); /* create reasonable step size to handle drawing */ rv = fpga_wrReg32(handle,OVERVIEW_STEP_REG,(s->over_per_step)-1);//scan_step for overview rv rv rv rv = = = = fpga_wrReg32(handle,SCAN_MIN_REG,s->scan_min);//scan_min fpga_wrReg32(handle,SCAN_MAX_REG,s->scan_max);//scan_max fpga_wrReg32(handle,SCAN_STEP_REG,s->scan_step);//samples per step fpga_wrReg32(handle,SPS_REG,(s->samples_per_step)-1);//scan_step rv = fpga_rdReg8(handle,FPGA_CMD_REG,&(s->status)); rv = fpga_wrReg8(handle,GAIN_REG,gain_lookup[gain]); rv = fpga_wrReg8(handle,UI_CMD_REG,CMD_START); rv = fpga_rdReg8(handle,FPGA_CMD_REG,&(s->status)); #ifdef PRNTTEST printf("Line 274 status=%d\n",s->status); #endif return rv; } /************************************************************************/ /* read_data Function */ /* inputs: buffer register, x array, y array */ /* outputs: return value of error(zero for no error) */ /* Function: reads either the overview buffer register or high */ /* resolution register for all of the values to graph */ /************************************************************************/ #define INVERSE_WORD ( (1.0) / (double)(1<<16) ) #define SCALE_ADC_Y(y) (float)(((double)(((uint32_t)(y))>>16))*INVERSE_WORD) int read_data(int reg,float *x,float *y,scanStr s) { int i,rv=0; static uint8_t buff[DATA_LEN*8 + 64]; fpga_rdStream(handle,FPGA_TIMEOUT,reg, DATA_LEN*8+8, buff); uint32_t * ibuf = (uint32_t*) buff; uint32_t xt, yt; uint32_t miny=1<<30,maxy=0, minx=1<<30,maxx=0; /* save the values as a float for graphing using gtkdatabox */ //if(reg == OVERVIEW_STREAM_REG){or for(i = 0; i < DATA_LEN; i++){ xt = ntohl((uint32_t) *(ibuf++)); yt = ntohl((uint32_t) *(ibuf++)); miny = yt < miny ? yt : miny; maxy = yt > maxy ? yt : maxy; minx = xt < minx ? xt : minx; maxx = xt > maxx ? xt : maxx; if( (yt&0xFFF) == 0xBAD) { y[rv] = SCALE_ADC_Y(yt); //y[rv] = (float)(yt&~(0xfff)); //ramp[rv] = (float)(xt); // find me a better home x[rv] = (float)xt; // scale factor eventually rv++; } } #ifdef PRNTTEST printf("X: %u - %u Y: %f - %f\n", minx, maxx,SCALE_ADC_Y(miny),SCALE_ADC_Y(maxy)); printf("finished for loop (got %d valid)\n",rv); #endif return rv; 63 333 } 334 335 /********************************************************************************/ 336 /* graph_func Function */ 337 /* inputs: fpga scan struct */ 338 /* outputs: gint(same as int) that is either TRUE or FALSE to */ 339 /* determine whether to continue drawing(TRUE) or not */ 340 /* (FALSE) */ 341 /* Function: takes values from the buffer registers and graphs */ 342 /* the values onto gtkdatabox graphs. After the first */ 343 /* draw, the graphs must be removed to not cause memory leaks */ 344 /********************************************************************************/ 345 gint graph_func(void *_s){ 346 int stat = 1,rv; 347 348 const guint line_size = 1; 349 static int marker_points = 2; 350 351 static int firstTime=1; 352 #ifndef NO_PERFORM 353 struct timeval start ,end; 354 long mtime, seconds, useconds; 355 gettimeofday(&start,NULL); 356 #endif 357 358 359 fpga_rdReg8(handle,FPGA_CMD_REG,&stat); 360 if(stat != FIFO_WAIT){ 361 return TRUE; 362 } 363 364 365 scanStr s = (scanStr) _s; 366 /* Set the markers to the user defined spot, specifically scan_min and scan_max */ 367 low_marker[0] = s->scan_min; 368 low_marker[1] = s->scan_min; 369 high_marker[0] = s->scan_max; 370 high_marker[1] = s->scan_max; 371 372 373 374 if(firstTime == 1){ 375 firstTime = 0; 376 377 378 } 379 else{ 380 //gtk_databox_graph_remove(GTK_DATABOX(databox_lowres),low_res_graph); 381 //gtk_databox_graph_remove(GTK_DATABOX(databox_lowres),lower_marker); 382 //gtk_databox_graph_remove(GTK_DATABOX(databox_lowres),upper_marker); 383 //gtk_databox_graph_remove(GTK_DATABOX(databox_lowres),low_res_ramp); 384 //gtk_databox_graph_remove(GTK_DATABOX(databox_highres),high_res_graph); 385 } 386 387 388 389 /* Get the values from the FPGA for the high res graph then graph it */ 390 gtk_databox_set_total_limits(GTK_DATABOX(databox_highres),s->scan_min,s>scan_max,ADC_MAX,0); 391 rv = read_data(STREAM_REG,x,y,s); 392 393 #ifdef PRNTTEST 394 printf("return value for STREAM_REG: %d\n",rv); 395 #endif 396 397 /* Get the values from the FPGA for the low res graph then graph it */ 398 /* and graph scan_min and scan_max as cursors on the low res graph */ 399 rv = read_data(OVERVIEW_STREAM_REG,ox,oy,s); 400 #ifdef PRNTTEST 401 printf("return value for OVERVIEW_STREAM_REG: %d\n",rv); 402 #endif 403 /* Add the graphs back onto the gtkdatabox container widget */ 404 high_res_graph = gtk_databox_lines_new(rv,x,y,&cyan,line_size); 64 405 high_res_grid = gtk_databox_grid_new (20, 40, &white, 0); 406 gtk_databox_graph_add (GTK_DATABOX (databox_highres), high_res_grid); 407 low_res_graph = gtk_databox_lines_new(rv,ox,oy,&cyan,line_size); 408 //low_res_ramp = gtk_databox_lines_new(grlen,ox,ramp,&red,line_size); 409 lower_marker = gtk_databox_lines_new(marker_points,low_marker,low_marker_height,&cyan ,line_size); 410 upper_marker = gtk_databox_lines_new(marker_points,high_marker,high_marker_height,&cy an,line_size); 411 gtk_databox_graph_add(GTK_DATABOX(databox_lowres),low_res_graph); 412 //gtk_databox_graph_add(GTK_DATABOX(databox_lowres),low_res_ramp); 413 gtk_databox_graph_add(GTK_DATABOX(databox_lowres),lower_marker); 414 gtk_databox_graph_add(GTK_DATABOX(databox_lowres),upper_marker); 415 gtk_databox_graph_add(GTK_DATABOX(databox_highres),high_res_graph); 416 gtk_databox_set_total_limits(GTK_DATABOX(databox_lowres),START_VALUE,STOP_VALUE,ADC_M AX,0); 417 //gtk_databox_auto_rescale(GTK_DATABOX(databox_lowres),0.005); 418 419 gtk_widget_queue_draw (GTK_WIDGET (databox_lowres)); 420 gtk_widget_queue_draw (GTK_WIDGET (databox_highres)); 421 #ifndef NO_PERFORM 422 gettimeofday(&end,NULL); 423 seconds = end.tv_sec - start.tv_sec; 424 useconds = end.tv_usec - start.tv_usec; 425 mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; 426 static int decount = 0; 427 printf("Graph Calc time: %ld milliseconds,%d\n",mtime,decount++); 428 #endif 429 drawing = 0; 430 fpga_wrReg8(handle,UI_CMD_REG,CMD_START); 431 return TRUE; 432 } 433 434 /********************************************************************************/ 435 /* button Functions */ 436 /* inputs: nothing */ 437 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 438 /* Function: These functions right now just toggle the leds on the buttons */ 439 /* with the exception being that pressed cursor will display */ 440 /* the settings window */ 441 /********************************************************************************/ 442 gint uim_pressed_home(void){ 443 uim_led_toggle(BTN_HOME); 444 return FALSE; 445 } 446 447 gint uim_pressed_measure(void){ 448 uim_led_toggle(BTN_MEASURE); 449 return FALSE; 450 } 451 452 //for right now this will be the settings button 453 gint uim_pressed_cursor(void){ 454 uim_led_toggle(BTN_CURSOR); 455 if(settings_flag == 1){ 456 settings(); 457 settings_flag = 1 - settings_flag; 458 context = 5; 459 } 460 else{ 461 printf("this should close the settings window\n"); 462 gtk_widget_destroy(settings_window); 463 settings_flag = 1 - settings_flag; 464 context = 0; 465 } 466 return FALSE; 467 } 468 469 gint uim_pressed_memory(void){ 470 uim_led_toggle(BTN_MEMORY); 471 return FALSE; 472 } 473 474 gint uim_pressed_power(void){ 65 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 uim_led_toggle(BTN_POWER); return FALSE; } /********************************************************************************/ /* rotary encoder button Functions */ /* inputs: nothing */ /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: These functions switch the context of the UIM-E finite state */ /* machine. They include toggles to simplify the mechanism */ /********************************************************************************/ gint uim_pressed_k0(void){ static int x = 0; /* If your in the Home State this will switch between the home state */ /* and the Field Select State */ if(context == 0){ x = 1-x; if(x == 1){ context = 1; } else{ context = 0; } } /* If your in the Field Select State this will switch between the home state */ /* and the Field Select State */ else if(context == 1){ x = 1-x; if(x ==1){ context = 1; } else{ context = 0; } } /* If your in the Edit Field State this will switch between the edit field state*/ /* and the Field Select State */ else if(context == 2){ gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); context = 1; } return FALSE; } gint uim_pressed_k1(void){ static int x = 0; /* This will save the modified value and return from the Edit Field State to*/ /* the Field Sele(2*width)/(ss*DATA_LEN)ct state */ if(context == 1){ x = 1-x; if(x == 1){ str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); entry_pos[entry_num] = 7; gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]); context = 2; } else if(x == 0){ context = 1; } } else if(context == 2){ context == 1; } return FALSE; } /************************************************************************************/ /* rotary encoder rotation Functions */ /* inputs: integer value(positive or negative) denoting */ /* denoting the number or ticks on the rotary encoder */ /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: These functions apply rotary movement to the text entries */ 66 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 /************************************************************************************/ gint uim_rotated_k0(int n) { rotary = 0; /* Run functions dependent on the state the UIM is in at the time */ if(context == 0){ //printf("in home context\n"); uim_state_home(n); } else if(context == 1){ uim_state_field_select(n); } else if(context == 2){ uim_state_edit_field(n); } else if(context == 5){ uim_settings_choice(n); } return FALSE; } gint uim_rotated_k1(int n){ rotary = 1; /* Run functions dependent on the state the UIM is in at the time*/ if(context == 0){ uim_state_home(n); } else if(context == 2){ uim_state_edit_field(n); } else if(context == 5){ uim_settings_choice(n); } return FALSE; } /************************************************************************************/ /* Number Pad Functions */ /* inputs: character that should be a ASCII number or * or # */ /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: This function will apply a number to the */ /* text entry that is selected */ /************************************************************************************/ gint uim_pressed_number(char num){ if(context == 0){ gain = num-'0'; printf("changing the gain level to %d (%x)\n",gain,gain_lookup[gain]); } if(context == 3){ /* This will add values to the text entry selected*/ char str[] = {num,0}; gtk_editable_insert_text(GTK_EDITABLE(button_entry[entry_num]),str,1,entry_pos); if(entry_pos[entry_num] < 11){ gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]++) ; 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 } else{ context = 1; } } else{ printf("this isn't implemented yet\n"); } return FALSE; } /* If the user presses star then the system will either change context */ /* or clear the text entry and change the context to manually change the value */ gint uim_pressed_star(void){ if(context == 1){ context = 3; str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),""); 67 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 ); 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 } else if(context == 3){ context = 1; } else{ printf("this function hasn't been implemented yet\n"); } return FALSE; } gint uim_pressed_pound(void){ if(context == 3){ /* Delete a value or save value and go back to field select state*/ if (entry_num >= 8){ entry_num = 8; gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); context = 1; } else{ gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]-} } else if(context == 2){ /* Save the value and go back to field select state */ gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); context = 1; } return FALSE; } /************************************************************************************/ /* UIM STATE HOME Function */ /* inputs: integer value that is positive or negative */ /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: Move the cursor on the graphs to obtain expansion and offset */ /************************************************************************************/ gint uim_state_home(int n){ /* Get two pixels values that are right next to each other then subtract them */ /* to get the distance of one pixel for scaling purposes */ //pixel1 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center); //pixel2 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center-1); //pixel_diff= pixel1 - pixel2; #undef MAX_WIDTH #define MAX_WIDTH ((STOP_VALUE_DEF-START_VALUE_DEF)/2) //static int64_t width=MAX_WIDTH/2,center=START_VALUE_DEF+MAX_WIDTH; int64_t pixel_diff = width/MIN_WIDTH; int64_t temp_width,temp_center; if(abs(n) > 8){ n *= 2; } n *= 2; if(rotary == 1){ width += pixel_diff*n; if(width+center > STOP_VALUE){ width = STOP_VALUE-center-1; } printf("The width+center is: %ld\n",width); if(center-width < 0){ width = center-1; } printf("The center-width is: %ld\n",width); if(width < MIN_WIDTH){ width = MIN_WIDTH; } printf("The smallest width is: %ld\n",width); if(!((2*width)/(SCAN_STEP*DATA_LEN))){ width = (SCAN_STEP*DATA_LEN)>>1; } } else if(rotary == 0){ center += pixel_diff*n; if(center < width){ 68 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 center = width + 1; } if(center > (STOP_VALUE-width)){ center = STOP_VALUE-width-1; } } //set the values on the middle section in between the graphs //pixel_diff2 = 5*pixel_diff; //amp1 = gtk_databox_pixel_to_value_y(GTK_DATABOX(databox_highres),0); //amp2 = gtk_databox_pixel_to_value_y(GTK_DATABOX(databox_highres),5); //sprintf(&pixel_diff_str,"Hz/Div: %f",pixel_diff2); //sprintf(&_diff_str,"Amp/Div: %f",amp_diff); //sprintf(&hz_diff_str,"Hz Rate: %f",pixel_diff); //gtk_label_set_text(GTK_LABEL(lowerGraphDiv),&pixel_diff_str); //gtk_label_set_text(GTK_LABEL(upperGraphDiv),&_diff_str); //gtk_label_set_text(GTK_LABEL(graphRate),&hz_diff_str); scan_init((int)center,(int)width,DATA_LEN); return FALSE; } /************************************************************************************/ /* UIM STATE FIELD SELECT Function */ /* inputs: integer value that is positive or negative */ /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: Rotate through the text entry fields next to the graphs */ /************************************************************************************/ gint uim_state_field_select(int n){ static int last = 0; /* make a text entry grab mouse focus manually since there will be no mouse */ if(n == last){ last = 0; if(n >= DIR_CW){ if(entry_num >= 9){ entry_num = 1; gtk_widget_grab_focus(button_entry[entry_num]); } else{ entry_num = entry_num + 1; gtk_widget_grab_focus(button_entry[entry_num]); } } else if(n <= DIR_CCW){ if(entry_num <= 1){ entry_num = 9; gtk_widget_grab_focus(button_entry[entry_num]); } else{ entry_num = entry_num - 1; gtk_widget_grab_focus(button_entry[entry_num]); } } } else{ //slow down the rotation so it is one text entry per click last = n; } return FALSE; } /************************************************************************************/ /* UIM STATE EDIT FIELD Function */ /* inputs: integer value that is positive or negative */ /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: add/subtract one on the text entry value on each rotary click */ /* wrapping the carry to the next significant bit and hold at */ /* MAX_VALUE(999999.999) and MIN_VALUE(000000.000) also change */ /* the position to start adding and subtracting */ /************************************************************************************/ gint uim_state_edit_field(int n){ static int last = 0; /* add/subtract rotary encoder is being used*/ 69 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 if(rotary == 1){ int i,j,store=-1,flag=0; char* str3 = gtk_editable_get_chars(GTK_EDITABLE(button_entry[entry_num]),0,11); i = entry_pos[entry_num]; if(n == last){ last = 0; /* Add to the value in the text entry with carry to next value*/ if(n >= DIR_CW){ do{ if(str3[i] == '.'){ str3[i] = '.'; i=i-n; flag = 1; } else{ str3[i]=str3[i]+n; if(str3[i] > '9'){ if(i == 0){ str3[i] = '9'; flag = 0; } else{ str3[i] = '0'; i=i-n; flag = 1; } } else{ flag = 0; } } }while(flag); } /* Subtract from the value in the text entry with carry */ else if(n <= DIR_CCW){ for(j=0;j<=i;j++){ if(str3[j] > '0'){ store = j; } } do{ if(str3[i] == '.'){ str3[i] = '.'; i--; flag = 1; } else if(store == -1){ str3[i] = '0'; flag = 0; } else if(store >= 0){ if(i == store){ str3[i]--; } else if(i > store){ str3[i] = '9'; } if(i != 0){ i--; flag = 1; } else{ flag = 0; } } }while(flag); } } else{ last = n; } /* set the text entry with the updated value and change the position if necessary */ gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str3); 70 837 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]); 838 } 839 /* change the starting position */ 840 else if(rotary == 0){ 841 if(n == last){ 842 if(n >= DIR_CW){ 843 if(entry_pos[entry_num] >= 10){ 844 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]=10); 845 } 846 else{ 847 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]++); 848 } 849 } 850 else if(n <= DIR_CCW){ 851 if(entry_pos[entry_num] < 1){ 852 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]=0); 853 } 854 else{ 855 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]--); 856 } 857 } 858 } 859 /* Wait for a click on the rotary encoder */ 860 else{ 861 last = n; 862 } 863 } 864 return FALSE; 865 } 866 867 /********************************************************************/ 868 /* Settings Window Function */ 869 /* inputs: nothing */ 870 /* outputs: nothing */ 871 /* Function: open a settings window for saving */ 872 /* values and other potential function */ 873 /********************************************************************/ 874 void settings(void){ 875 int i; 876 //Create Settings window 877 settings_window = gtk_window_new (GTK_WINDOW_POPUP); 878 gtk_widget_set_size_request (settings_window, 300, 200); 879 //g_signal_connect (GTK_OBJECT (settings_window), "destroy", 880 // G_CALLBACK (gtk_main_quit), NULL); 881 //set title of window 882 gtk_window_set_title (GTK_WINDOW (settings_window), 883 "Team Spectrum: DOSA Settings"); 884 885 GtkWidget *settingbuttons = gtk_vbutton_box_new(); 886 gtk_box_set_spacing(GTK_BOX(settingbuttons),4); 887 gtk_container_add(GTK_CONTAINER(settings_window), settingbuttons); 888 889 for(i=0;i<4;i++){ 890 setting_hbox[i] = gtk_hbox_new(FALSE,0); 891 gtk_container_add(GTK_CONTAINER(settingbuttons),setting_hbox[i]); 892 setting_button[i] = gtk_button_new_with_label(setting_names[i]); 893 gtk_widget_set_can_focus(setting_button[i],TRUE); 894 gtk_box_pack_start(GTK_BOX(setting_hbox[i]), setting_button[i], 1, 0, 1); 895 } 896 /* Connect asynchronous signals to buttons to asynchronously run settings functions */ 897 g_signal_new("save_config",G_TYPE_OBJECT,G_SIGNAL_RUN_FIRST,0,NULL,NULL, 898 NULL,G_TYPE_NONE,0); 899 g_signal_new("save_data",G_TYPE_OBJECT,G_SIGNAL_RUN_FIRST,0,NULL,NULL, 900 NULL,G_TYPE_NONE,0); 901 g_signal_connect(G_OBJECT(settings_window),"save_config",G_CALLBACK(cb_save_config),NULL) ; 902 g_signal_connect(G_OBJECT(settings_window),"save_data",G_CALLBACK(cb_save_data),NULL); 903 gtk_widget_show_all (settings_window); 904 } 71 905 906 /****************************************************************************************/ 907 /* Settings Window Callback Functions * / 908 /* inputs: nothing * / 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ /* Function: save the configuration values to a file (9 text entries on the right) */ /* also save data from the fpga to a different file */ /****************************************************************************************/ gint cb_save_config(void){ FILE *fp; int i; fp = fopen("DOSA_configuration","w");//write configuration if(fp != NULL){ for(i=0;i<9;i++){ char* str3 = gtk_editable_get_chars(GTK_EDITABLE(button_entry[entry_num]),0,11); fputs (str3,fp); } } fclose(fp); return FALSE; } gint cb_save_data(void){ FILE *fp; int i; return FALSE; } void uim_settings_choice(int n){ static int last = 0; /* make a text entry grab mouse focus manually since there will be no mouse */ if(last == 1){ last = 0; if(n == DIR_CW){ if(entry_num >= 4){ entry_num = 1; gtk_widget_grab_focus(button_entry[entry_num]); } else{ entry_num = entry_num + 1; gtk_widget_grab_focus(button_entry[entry_num]); } } else if(n == DIR_CCW){ if(entry_num <= 1){ entry_num = 4; gtk_widget_grab_focus(button_entry[entry_num]); } else{ entry_num = entry_num - 1; gtk_widget_grab_focus(button_entry[entry_num]); } } } else{ //slow down the rotation so it is one text entry per click last++; } } /****************************************************************/ /* scan_init Function */ /* inputs: center and width of desired high res graph */ /* and number of points to graph */ /* outputs: struct of necessary values to send to FPGA */ /* Function: determines samples per step, scan min, scan */ /* scan max, scan step, and number of points and */ /* saves to the scanStr struct */ /****************************************************************/ scanStr scan_init(uint32_t center,uint32_t width,int num_points){ assert(center > 0); 72 976 assert(width > 0); 977 assert(num_points > 0); 978 979 int sps = (2*width)/(SCAN_STEP*DATA_LEN); 980 int oss = (STOP_VALUE-START_VALUE)/(SCAN_STEP*DATA_LEN); 981 /* determine values using equations */ 982 s.status = 0; 983 s.scan_min=center-width; 984 s.scan_max=center+width; 985 s.samples_per_step = sps; 986 s.scan_step=SCAN_STEP; 987 s.over_per_step = oss; 988 s.count = DATA_LEN; //s.x_vals=x;s.y_vals=y; 989 #ifndef PRNTTEST 990 printf("status=%u\n num_points=%u\n scan_min=%u\n scan_max=%u\n sps=%u\n scan_step=%u\n o verview_per_step=%u\n center=%u\n width=%u\n",s.status,s.count,s.scan_min,s.scan_max,s.samples_pe r_step,s.scan_step,s.over_per_step,center,width); 991 #endif 992 assert(s.scan_max > s.scan_min); 993 assert(s.scan_step > 0); 994 995 return &s; 996 } 997 998 999 int load_ini_config(void){ 1000 st_configuration config; 1001 int rv; 1002 //TBI -Loadfrom ini 1003 STOP_VALUE = STOP_VALUE_DEF; 1004 START_VALUE =START_VALUE_DEF; 1005 IPM_CLK_FREQ =IPM_CLK_FREQ_DEF; 1006 REFRESH_RATE=REFRESH_RATE_DEF; 1007 // Calculate other static vals 1008 1009 if(!scanf_settings(&config)){ 1010 STOP_VALUE = (uint32_t)((config.stop_voltage)*(double)(config.som_steps_per_volt)); 1011 START_VALUE = (uint32_t)((config.start_voltage)*(double)(config.som_steps_per_volt)); 1012 IPM_CLK_FREQ = (uint32_t)(config.ipm_clk_freq); 1013 REFRESH_RATE = (uint32_t)(config.refresh_rate); 1014 #ifdef PRNTTEST 1015 printf("stop value: %f\nstart value: %f\noutput steps per volt: %u\n",config.stop_vol tage,config.start_voltage,config.som_steps_per_volt); 1016 #endif 1017 } 1018 SCAN_STEP= (STOP_VALUE-START_VALUE)/(IPM_CLK_FREQ/REFRESH_RATE); 1019 //gtk_editable_set_text(GTK_EDITABLE(button_entry[i]),begin_entry,11,entry_pos); 1020 #ifdef PRNTTEST 1021 printf(" start value %u\n stop value %u\n IPM Frequency %u\n Refresh Rate %u\n",START_VAL UE, STOP_VALUE, IPM_CLK_FREQ, REFRESH_RATE); 1022 printf("SS: %d\n",SCAN_STEP); 1023 #endif 1024 center = ((STOP_VALUE-START_VALUE)/2)+START_VALUE; 1025 width = ((STOP_VALUE-START_VALUE)/4); 1026 return 0; 1027 } 1.3.7 fpga.sh 1 2 3 4 5 6 7 8 9 #!/bin/sh TARGNAME=fpgalink_test FPGALIB=$HOME/Important_Files/RPi/libfpgalink-20120507 gcc -m64 -O3 -g -Wall -Wextra -Wundef -pedantic-errors -std=c99 -Wstrict-prototypes \ -Wno-missing-field-initializers -I$FPGALIB -I$FPGALIB/hdl/common\ -Wl,--relax,--gc-sections,-rpath,\$ORIGIN,-rpath-link,$FPGALIB/linux.x86_64/rel \ -o $TARGNAME dcmusb_unitTest.c dcmusb.c -L$FPGALIB/linux.x86_64/rel -lfpgalink -lerror echo "finished" 73 10 # gcc -m64 -O3 -Wall -Wextra -Wundef -pedantic-errors -std=c99 -Wstrict-prototypes -Wnomissing-field-initializers -I../.. -I../../../../common -Wl,--relax,--gc-sections,rpath,\$ORIGIN,-rpath-link,../../linux.x86_64/rel -o ../../linux.x86_64/rel/fpgalink *.c L../../linux.x86_64/rel –lfpgalink 1.3.8 fpgaComm.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 /* * Copyright (C) 2009-2012 Chris McClelland * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> #include <stdlib.h> #include <libfpgalink.h> #include "args.h" #define CHECK(x) \ if ( status != FL_SUCCESS ) { returnCode = x; fprintf(stderr, "%s\n", error); flFreeError(error); goto cleanup; } \ \ \ \ \ int main(int argc, const char *argv[]) { int returnCode; struct FLContext *handle = NULL; FLStatus status; const char *error = NULL; uint8 byte = 0x10; uint8 buf[256]; bool flag; bool isNeroCapable, isCommCapable; uint32 fileLen; uint8 *buffer = NULL; uint32 numDevices, scanChain[16], i; const char *vp = NULL, *ivp = NULL, *jtagPort = NULL, *xsvfFile = NULL, *dataFile = NULL; bool scan = false, usbPower = false; const char *const prog = argv[0]; //printf("FPGALink \"C\" Example Copyright (C) 2011 Chris McClelland\n\n"); argv++; argc--; while ( argc ) { if ( argv[0][0] != '-' ) { unexpected(prog, *argv); FAIL(1); } switch ( argv[0][1] ) { case 'v'://needed GET_ARG("v", vp, 2); break; case 'i'://don't need should be taken out GET_ARG("i", ivp, 3); break; case 'f': GET_ARG("f", dataFile, 6); break; 74 64 default: 65 invalid(prog, argv[0][1]); 66 FAIL(7); 67 } 68 argv++; 69 argc--; 70 } 71 if ( !vp ) { 72 missing(prog, "v <VID:PID>");//checks for a specified vendor id and product id 73 FAIL(8); 74 } 75 76 flInitialise();//initialize fpgalink 77 78 printf("Attempting to open connection to FPGALink device %s...\n", vp); 79 status = flOpen(vp, &handle, NULL);//open fpgalink 80 if ( status ) { 81 if ( ivp ) { 82 int count = 60; 83 printf("Loading firmware into %s...\n", ivp); 84 status = flLoadStandardFirmware(ivp, vp, jtagPort, &error); 85 CHECK(10); 86 87 printf("Awaiting renumeration"); 88 flSleep(1000); 89 do { 90 printf("."); 91 fflush(stdout); 92 flSleep(100); 93 status = flIsDeviceAvailable(vp, &flag, &error); 94 CHECK(11); 95 count--; 96 } while ( !flag && count ); 97 printf("\n"); 98 if ( !flag ) { 99 fprintf(stderr, "FPGALink device did not renumerate properly as %s\n", vp); 100 FAIL(12); 101 } 102 103 printf("Attempting to open connection to FPGLink device %s again...\n", vp); 104 status = flOpen(vp, &handle, &error); 105 CHECK(13); 106 } else { 107 fprintf(stderr, "Could not open FPGALink device at %s and no initial VID:PID was supplied\n", vp); 108 FAIL(14); 109 } 110 } 111 112 isNeroCapable = flIsNeroCapable(handle); 113 isCommCapable = flIsCommCapable(handle); 114 115 if ( dataFile && !isCommCapable ) { 116 fprintf(stderr, "Data file load requested but device at %s does not support CommFPGA\ n", vp); 117 FAIL(20); 118 } 119 120 if ( isCommCapable ) { 121 printf("Writing channel 0x01 to zero count...\n"); 122 byte = 0x01; 123 status = flWriteChannel(handle, 1000, 0x01, 1, &byte, &error); 124 CHECK(21); 125 126 if ( dataFile ) { 127 buffer = flLoadFile(dataFile, &fileLen); 128 if ( buffer ) { 129 uint16 checksum = 0x0000; 130 uint32 i; 131 for ( i = 0; i < fileLen; i++ ) { 132 checksum += buffer[i]; 133 } 134 printf( 75 135 "Writing %0.2f MiB (checksum 0x%04X) from %s to FPGALink device %s...\n", 136 (double)fileLen/(1024*1024), checksum, dataFile, vp); 137 status = flWriteChannel(handle, 30000, 0x00, fileLen, buffer, &error); 138 CHECK(22); 139 } else { 140 fprintf(stderr, "Unable to load file %s!\n", dataFile); 141 FAIL(23); 142 } 143 } 144 } 145 146 returnCode = 0; 147 148 cleanup: 149 flFreeFile(buffer); 150 flClose(handle); 151 return returnCode; 152 } 1.3.9 ini.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 /* inih -- simple .INI file parser inih is released under the New BSD license (see LICENSE.txt). Go to the project home page for more info: http://code.google.com/p/inih/ */ #include <stdio.h> #include <ctype.h> #include <string.h> #include "ini.h" #if !INI_USE_STACK #include <stdlib.h> #endif #define MAX_SECTION 50 #define MAX_NAME 50 /* Strip whitespace chars off end of given string, in place. Return s. */ static char* rstrip(char* s) { char* p = s + strlen(s); while (p > s && isspace(*--p)) *p = '\0'; return s; } /* Return pointer to first non-whitespace char in given string. */ static char* lskip(const char* s) { while (*s && isspace(*s)) s++; return (char*)s; } /* Return pointer to first char c or ';' comment in given string, or pointer to null at end of string if neither found. ';' must be prefixed by a whitespace character to register as a comment. */ static char* find_char_or_comment(const char* s, char c) { int was_whitespace = 0; while (*s && *s != c && !(was_whitespace && *s == ';')) { was_whitespace = isspace(*s); s++; 76 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 } return (char*)s; } /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ static char* strncpy0(char* dest, const char* src, size_t size) { strncpy(dest, src, size); dest[size - 1] = '\0'; return dest; } /* See documentation in header file. */ int ini_parse_file(FILE* file, int (*handler)(void*, const char*, const char*, const char*), void* user) { /* Uses a fair bit of stack (use heap instead if you need to) */ #if INI_USE_STACK char line[INI_MAX_LINE]; #else char* line; #endif char section[MAX_SECTION] = ""; char prev_name[MAX_NAME] = ""; char* start; char* end; char* name; char* value; int lineno = 0; int error = 0; #if !INI_USE_STACK line = (char*)malloc(INI_MAX_LINE); if (!line) { return -2; } #endif /* Scan through file line by line */ while (fgets(line, INI_MAX_LINE, file) != NULL) { lineno++; start = line; #if INI_ALLOW_BOM if (lineno == 1 && (unsigned char)start[0] == 0xEF && (unsigned char)start[1] == 0xBB && (unsigned char)start[2] == 0xBF) { start += 3; } #endif start = lskip(rstrip(start)); if (*start == ';' || *start == '#') { /* Per Python ConfigParser, allow '#' comments at start of line */ } #if INI_ALLOW_MULTILINE else if (*prev_name && *start && start > line) { /* Non-black line with leading whitespace, treat as continuation of previous name's value (as per Python ConfigParser). */ if (!handler(user, section, prev_name, start) && !error) error = lineno; } #endif else if (*start == '[') { /* A "[section]" line */ end = find_char_or_comment(start + 1, ']'); if (*end == ']') { *end = '\0'; strncpy0(section, start + 1, sizeof(section)); *prev_name = '\0'; 77 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 } else if (!error) { /* No ']' found on section line */ error = lineno; } } else if (*start && *start != ';') { /* Not a comment, must be a name[=:]value pair */ end = find_char_or_comment(start, '='); if (*end != '=') { end = find_char_or_comment(start, ':'); } if (*end == '=' || *end == ':') { *end = '\0'; name = rstrip(start); value = lskip(end + 1); end = find_char_or_comment(value, '\0'); if (*end == ';') *end = '\0'; rstrip(value); /* Valid name[=:]value pair found, call handler */ strncpy0(prev_name, name, sizeof(prev_name)); if (!handler(user, section, name, value) && !error) error = lineno; } else if (!error) { /* No '=' or ':' found on name[=:]value line */ error = lineno; } } } #if !INI_USE_STACK free(line); #endif return error; } /* See documentation in header file. */ int ini_parse(const char* filename, int (*handler)(void*, const char*, const char*, const char*), void* user) { FILE* file; int error; file = fopen(filename, "r"); if (!file) return -1; error = ini_parse_file(file, handler, user); fclose(file); return error; } 1.3.10 1 2 3 4 5 6 7 8 9 10 11 12 ini.h /* inih -- simple .INI file parser inih is released under the New BSD license (see LICENSE.txt). Go to the project home page for more info: http://code.google.com/p/inih/ */ #ifndef __INI_H__ #define __INI_H__ 78 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 /* Make this header file easier to include in C++ code */ #ifdef __cplusplus extern "C" { #endif #include <stdio.h> /* Parse given INI-style file. May have [section]s, name=value pairs (whitespace stripped), and comments starting with ';' (semicolon). Section is "" if name=value pair parsed before any section heading. name:value pairs are also supported as a concession to Python's ConfigParser. For each name=value pair parsed, call handler function with given user pointer as well as section, name, and value (data only valid for duration of handler call). Handler should return nonzero on success, zero on error. Returns 0 on success, line number of first error on parse error (doesn't stop on first error), -1 on file open error, or -2 on memory allocation error (only when INI_USE_STACK is zero). */ int ini_parse(const char* filename, int (*handler)(void* user, const char* section, const char* name, const char* value), void* user); /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't close the file when it's finished -- the caller must do that. */ int ini_parse_file(FILE* file, int (*handler)(void* user, const char* section, const char* name, const char* value), void* user); /* Nonzero to allow multi-line value parsing, in the style of Python's ConfigParser. If allowed, ini_parse() will call the handler with the same name for each subsequent line parsed. */ #ifndef INI_ALLOW_MULTILINE #define INI_ALLOW_MULTILINE 1 #endif /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of the file. See http://code.google.com/p/inih/issues/detail?id=21 */ #ifndef INI_ALLOW_BOM #define INI_ALLOW_BOM 1 #endif /* Nonzero to use stack, zero to use heap (malloc/free). */ #ifndef INI_USE_STACK #define INI_USE_STACK 1 #endif /* Maximum line length for any line in INI file. */ #ifndef INI_MAX_LINE #define INI_MAX_LINE 200 #endif #ifdef __cplusplus } #endif #endif /* __INI_H__ */ 1.3.11 1 2 3 4 5 6 7 8 #include #include #include #include #include #include #include #include support.h <sys/time.h> <stdio.h> <unistd.h> <gtk/gtk.h> <gdk/gdk.h> <glib.h> <gio/gio.h> <gtkdatabox.h> 79 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include <gtkdatabox_points.h> <gtkdatabox_ruler.h> <gtkdatabox_lines.h> <gtkdatabox_grid.h> <math.h> <cairo.h> <stdlib.h> <string.h> <stdint.h> <assert.h> <pthread.h> <netinet/in.h> "ini.h" "uim_config.h" "userIOusb.h" "dcmusb.h" #ifndef __SUPPORT_H__ #define __SUPPORT_H__ #define MAX_ENTRY (11) #define MAX_WIDTH (250000) #define MIN_WIDTH (400) #define ADC_MAX (1) //GDK colors GdkColor bgColor = { 0, 0, 0, 0 };//set background to black GdkColor gridColor = { 0, 65000, 65000, 65000 };//set gridlines to white GdkColor red = { 0, 65000, 0, 0};//set graph lines to red GdkColor cyan = {0, 0, 65000, 65000};//create cyan lines GdkColor white = { 0, 65000, 65000, 65000 };//set gridlines to white GtkWidget *button_hbox[9]; GtkWidget *button_label[9]; GtkWidget *button_entry[9]; GtkEditable *entry_editable[9]; GtkWidget GtkWidget GtkWidget GtkWidget *settings_window; *setting_hbox[4]; *setting_label[4]; *setting_button[4]; GtkWidget *lowerGraphDiv; GtkWidget *upperGraphDiv; GtkWidget *graphRate; //declare upper graph global so the entire program can gain access to information GtkWidget* databox_highres = 0; GtkWidget* databoxcontainer_highres = 0; GtkDataboxGraph *high_res_graph; GtkDataboxGraph* high_res_grid; //declare lower graph global so function can access everything GtkWidget* databox_lowres; GtkWidget* databoxcontainer_lowres; GtkDataboxGraph *low_res_graph; GtkDataboxGraph *lower_marker; GtkDataboxGraph *upper_marker; GtkDataboxGraph *low_res_grid; GtkDataboxGraph *low_res_ramp; int entry_pos[9]={1,1,1,1,1,1,1,1,1}; //scan range function //scan range defines #define SCAN_MIN_REG (32) #define SCAN_MAX_REG (36) #define SCAN_STEP_REG (40) #define SPS_REG (44) #define START_REG (48) #define STOP_REG (52) #define OVERVIEW_STEP_REG (56) #define UI_CMD_REG (0x7E) #define FPGA_CMD_REG (0x7F) #define STREAM_REG (1) #define OVERVIEW_STREAM_REG (2) 80 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 #define GAIN_REG (64) #define GPIO_REG (68) #define #define #define #define #define #define #define #define RUN_TIME_INT (1000) #define FPGA_TIMEOUT (100000000) #define MAX_POINTS (700) enum state_t{ START_SCAN, WAIT_FOR_DATA, GRAPH }state = START_SCAN; typedef struct { uint32_t status; uint32_t count; uint32_t scan_min; uint32_t scan_max; uint32_t samples_per_step; uint32_t over_per_step; uint32_t scan_step; int *x_vals; int *y_vals; }_scanStr; typedef _scanStr *scanStr; /*************************/ /* Function Prototypes */ /*************************/ void onExit(void); void settings(void); void request_redraw(void); gint graph_func(gpointer graph); gint start_scan(scanStr); gint cb_save_config(void); gint cb_save_data(void); scanStr scan_init(uint32_t center,uint32_t width, int num_points); int read_data(int reg,float *x,float *y,scanStr); gint dcmFSM(gpointer s); void uim_settings_choice(int n); int load_ini_config(void); #endif /* __SUPPORT_H__ */ 1.3.12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 CMD_START (0x53) STATUS_IDLE (0x00) CMD_ABORT (0x00) BAD_PARAM (0x60) FIFO_WAIT (0x56) HV_ON (1) HV_OFF (0) uim_config.c /** Settings IO Digital Optical Spectrum Analyzer /** Team Spectrum - George Mason University /** Jacob Dilles <[email protected]> 11 November 2012 **/ **/ **/ /* Standard Includes */ #include <stdio.h> /* FILE, printf, scanf, etc.. */ #include <math.h> /* NAN, log10, etc.. */ #include <errno.h> /* perror */ #include <stdint.h> /* uint32_t */ #include <string.h> /* strcmp */ #include <stdlib.h> /* atoi */ /* Project Includes */ #include "ini.h" #include "uim_config.h" 81 17 #define _f(x) ((double)x) /* force floating point */ 18 19 #define BOLD(x) "\033[1m" x "\033[0m" 20 #define RED(x) "\033[31m" x "\033[39m" 21 22 /* Internal functions */ 23 double f2si( double number, char * prefix ); 24 double si2f( const char* s ); 25 static int cfg_handler(void* user, const char* section, const char* name, const char* value); 26 27 #if _DEMO_INI_ 28 /* Demo */ 29 int main(int argc, char** argv) 30 { 31 st_configuration config; 32 33 int rv = scanf_settings(&config); 34 printf("Reading returned: %d\n", rv); 35 rv = printf_settings(&config); 36 printf("Writing returned: %d\n", rv); 37 return 0; 38 } 39 #endif 40 41 42 /* Read the settings from a specific file */ 43 int fscanf_settings(FILE * file, st_configuration* pcfg) 44 { 45 int errLine; 46 47 /* attempt to parse configuration file using the INI library */ 48 errLine = ini_parse_file(file, cfg_handler, pcfg); 49 50 if(errLine) printf("Settings file error on line: %d\n",errLine); 51 52 return errLine; 53 } 54 55 /* Call to set this file up */ 56 int scanf_settings(st_configuration* pcfg ) 57 { 58 int errLine; 59 60 /* attempt to parse configuration file using the INI library */ 61 errLine = ini_parse(SETTINGS_FILE_NAME, cfg_handler, pcfg); 62 63 /* No errors! */ 64 if(errLine == 0) 65 { 66 #if _DEBUG_INI_ 67 sout("Got settings OK"); 68 #endif 69 return 0; 70 } 71 72 if( errLine < 0) 73 { 74 fprintf(stderr, "Settings file '%s' not found, writing defaults...\n", SETTINGS_FILE_ NAME); 75 } 76 else 77 { 78 fprintf(stderr, BOLD(RED("WARNING: ")) RED("Settings file error: ") "%d:%s\n",errLine , SETTINGS_FILE_NAME); 79 } 80 81 return 1; 82 } 83 84 85 86 /* function that gets called by the ini.c */ 87 static int cfg_handler(void* user, const char* section, const char* name, 82 88 const char* value) 89 { 90 st_configuration* pcfg = (st_configuration*)user; 91 #define _SECTION(s) (strcmp(section, s) == 0) 92 #define _NAME(n) (strcmp(name, n) == 0) 93 #define _PARSEF(x) return (pcfg->x=si2f(value)) != NAN 94 #define _PARSES(x) (strncpy( (pcfg->x), value, sizeof( (pcfg->x) ))) 95 96 #if _DEBUG_INI_ 97 printf("Handeler Called! Section=%s Name=%s Value=%s\n", section, name, value); 98 #endif 99 100 if(_SECTION("config")){ 101 if(_NAME("version")) pcfg->version = atoi(value); 102 else return 0; 103 }else if(_SECTION("dcm")){ 104 /* no underscores */ 105 if(_NAME("stop voltage")) _PARSEF(stop_voltage); 106 else if(_NAME("start voltage")) _PARSEF(start_voltage); 107 else if(_NAME("ipm clock frequency")) _PARSEF(ipm_clk_freq); 108 else if(_NAME("refresh rate")) _PARSEF(refresh_rate); 109 else if(_NAME("free spectral range")) _PARSEF(fsr); 110 else if(_NAME("volts per fsr")) _PARSEF(volts_per_fsr); 111 else if(_NAME("output steps per volt")) pcfg->som_steps_per_volt=atoi(value); 112 /* not found */ 113 else return 0; 114 } else if(_SECTION("data")){ 115 /* no underscores */ 116 if(_NAME("output path")) _PARSES(output_path); 117 else if(_NAME("output type")) _PARSES(output_type); 118 /* with underscores */ 119 else if(_NAME("output_path")) _PARSES(output_path); 120 else if(_NAME("output_type")) _PARSES(output_type); 121 /* not found */ 122 else return 0; 123 } else { 124 return 0; 125 } 126 127 #undef _NAME 128 #undef _SECTION 129 #undef _PARSEF 130 #undef _PARSES 131 return 1; 132 } 133 134 /* Prints the settings to stdout */ 135 int printf_settings(st_configuration* pcfg) 136 { 137 return fprintf_settings(stdout, pcfg); 138 } 139 140 /* Prints the settings */ 141 int fprintf_settings(FILE * file, st_configuration* pcfg) 142 { 143 char prefix[2]={0,0}; 144 int rv = 0; 145 #define _SECTION(n) rv |= fprintf(file, "[%s]\n", n) 146 #define _PRINTFL(n, v, u) rv |= fprintf(file, "%s = %lf %s%s\n", n, f2si(pcfg>v,prefix), prefix, u) 147 #define _PRINTFS(k, v) rv |= fprintf(file, "%s = %s\n", k, pcfg->v) 148 #define _PRINTS(k, v) rv |= fprintf(file, "%s = %s\n", k, v) 149 #define _BR() rv |= fprintf(file, "\n") 150 _SECTION("config"); 151 _PRINTS("version", "1"); 152 _BR(); 153 /* 154 _SECTION("sfpi"); 155 _PRINTFL("free spectral range", free_spectral_range, "Hz"); 156 _PRINTFL("mirror reflectivity", mirror_reflectivity*100, "%" ); 157 _PRINTFL("mirror spacing", mirror_spacing, "m"); 158 _PRINTFL("displacement per volt", mirror_displacement_per_volt, "m"); 159 _PRINTFL("laser wavelength", laser_wavelength, "m"); 83 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 _PRINTFL("voltage min", voltage_min, "V"); _PRINTFL("voltage max", voltage_max, "V"); _PRINTFL("max scan frequency", scan_freq, "Hz"); _BR(); _SECTION("data"); _PRINTFS("output path", output_path); _PRINTFS("output type", output_type); _BR(); */ #undef #undef #undef #undef return _SECTION _PRINTFL _PRINTFS _PRINTS rv; } /* Scale a number for SI representation */ double f2si(double number, char * prefix) { const static char si_prefix[8 + 1 + 8] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 0, 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' }; int log1000; int minus; // Check for wacko conditions if( isnan(number) || isinf(number) || number == 0.0) { *prefix = 0; return number; } // Fix for log of negative number minus = number < 0.0; if(minus) number = -number; // Determine prefix based on power of 1000 log1000 = (int) floor( (log10(number) / 3) ); if(log1000 >= { number /= *prefix = } else { *prefix = } //log1000 -8 && log1000 <= 8) /* Prefixes only cover 1000^-8 .. 1000^8*/ (double) pow(1000.0, log1000); si_prefix[log1000+8]; /* number too big for metric prefix */ 0; if(minus) number = -number; // restore minus return number; } /* Parse a string to a double with support for SI prefixes on units */ double si2f(const char* s) { char prefix[5], c; double value, scale; int rv; /* parse the floating point number + 1-4 character extension*/ rv = sscanf(s, " %1$lf %2$5s", &value, prefix); 84 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 } #if _DEBUG_INI_ printf("si2f: rv=%d value=%lf prefix=%s\n", rv, value, prefix); #endif switch(rv) { case 0: return NAN; case 1: return value; case 2: c = prefix[0]; break; default: /* Unknown */ perror("Problem reading floating point string"); return NAN; } /* look up the si prefix (see http://en.wikipedia.org/wiki/Metric_prefix)*/ switch(c) { case 'Y': scale = _f(1.0e+24); break; case 'Z': scale = _f(1.0e+21); break; case 'E': scale = _f(1.0e+18); break; case 'P': scale = _f(1.0e+15); break; case 'T': scale = _f(1.0e+12); break; case 'G': scale = _f(1.0e+9); break; case 'M': scale = _f(1.0e+6); break; case 'k': scale = _f(1.0e+3); break; case 'h': scale = _f(1.0e+2); break; case 'd': scale = _f(1.0e-1); break; case 'c': scale = _f(1.0e-2); break; case 'm': scale = _f(1.0e-3); break; case 'u': scale = _f(1.0e-6); break; case 'n': scale = _f(1.0e-9); break; case 'p': scale = _f(1.0e-12); break; case 'f': scale = _f(1.0e-15); break; case 'a': scale = _f(1.0e-18); break; case 'z': scale = _f(1.0e-21); break; case 'y': scale = _f(1.0e-24); break; case '%': scale = _f(1.0e-2); break; /* not strictly si, but useful*/ default: scale = _f(1.0 ); break; /* unknown, ignore */ } /* scale by si unit */ value *= scale; return value; 1.3.13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 uim_config.h /** Settings IO Digital Optical Spectrum Analyzer /** Team Spectrum - George Mason University /** Jacob Dilles <[email protected]> 11 November 2012 **/ **/ **/ /* ; Team Spectrum DOSA Sample Configuration File ; Note, metric prefixes should be accepted, but the actual SI unit is not ; validated (so, for example, 1.5 mm is a valid frequency (0.0015 hz) [config] version = 1 ; Configuration Versioning ; Version 1 [sfpi] free spectral range = 1.5 GHz mirror reflectivity = 99.9999 % ; Free spectral range (FSR) of SPFI cavity ; Mirror reflectivity (either % or 0.999...) 85 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 mirror spacing = 15 mm displacement per volt = 4 mm laser wavelength = 785.80 nm voltage min = 15 V voltage max = 450 V max scan frequency = 10 Hz ; ; ; ; ; ; Mirror spacing SFPI Nominal wavelength, for auto-locking minimum allowable voltage for cavity maximum allowable voltage for cavity scan frequency limit [data] output path = /data output type = csv ; Output file extension and kind */ #ifndef __UIM_CONFIG_H #define __UIM_CONFIG_H /** --------- START INCLUDE FILE ------------- */ /* Define to 1 to enable print statements in the handler/parsers */ #define _DEBUG_INI_ (0) /* Define to 1 to enable demo of reading/writing INI */ #define _DEMO_INI_ (0) #define SETTINGS_FILE_NAME "uim_settings.txt" #define #define #define #define SOM_CODE_MIN SOM_CODE_MAX SOM_VOLTAGE_MIN SOM_VOLTAGE_MAX (4095.0) (2147483647.0) (4.0) (496.0) #define #define #define #define IPM_CODE_MIN IPM_CODE_MAX IPM_VOLTAGE_MIN IPM_VOLTAGE_MAX (2147483647.0) (0.0) (0.0) (3.0) #define #define #define #define VGA_CODE_MIN VGA_CODE_MAX VGA_GAIN_MIN VGA_GAIN_MAX (0.0) (15.0) (4000.0) (1258925.0) /* The struct to hold configuration data */ typedef struct { int version; float start_voltage; float stop_voltage; float ipm_clk_freq; float refresh_rate; int som_steps_per_volt; /* SFPI parameters */ double fsr; double mirror_reflectivity; double mirror_spacing; double volts_per_fsr; double laser_wavelength; /* Min/Max Limits */ double voltage_min; double voltage_max; /* Scanning params */ double scan_freq; /*File Output Stuff*/ char output_path[128]; char output_type[8]; } st_configuration; /* Read settings in. Non-zero return indicates error */ int scanf_settings( st_configuration* pcfg ); int fscanf_settings(FILE * file, st_configuration* pcfg); /* Debug print current settings to stdout */ 86 90 91 92 93 94 95 int printf_settings(st_configuration* pcfg); int fprintf_settings(FILE * file, st_configuration* pcfg); /** --------- END INCLUDE FILE ------------- */ #endif 1.3.14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 uim_functions.c #include "uim_functions.h" //declare upper graph global so the entire program can gain access to information GtkWidget* databox_highres = 0; GtkWidget* databoxcontainer_highres = 0; GtkDataboxGraph *high_res_graph; GtkDataboxGraph* high_res_grid; //declare lower graph global so function can access everything GtkWidget* databox_lowres; GtkWidget* databoxcontainer_lowres; GtkDataboxGraph *low_res_graph; GtkDataboxGraph *lower_marker; GtkDataboxGraph *upper_marker; GtkDataboxGraph *low_res_grid; GtkDataboxGraph *low_res_ramp; GtkWidget *button_hbox[9]; GtkWidget *button_label[9]; GtkWidget *button_entry[9]; GtkEditable *entry_editable[9]; const char* str2; char * pixel_diff_str,amp_diff_str,hz_diff_str; int context,entry_num=0,rotary; extern int entry_pos[9]={1,1,1,1,1,1,1,1,1}; float amp1,amp2,amp_diff,pixel1, pixel2,pixel_diff,pixel_diff2,width=50,center=50,temp_width,temp_center; gint uim_pressed_home(void){ uim_led_toggle(BTN_HOME); return FALSE; } gint uim_pressed_measure(void){ uim_led_toggle(BTN_MEASURE); return FALSE; } gint uim_pressed_cursor(void){ uim_led_toggle(BTN_CURSOR); settings(); return FALSE; } gint uim_pressed_memory(void){ uim_led_toggle(BTN_MEMORY); return FALSE; } gint uim_pressed_power(void){ uim_led_toggle(BTN_POWER); return FALSE; } // knobs x, y gint uim_pressed_k0(void){ static int x = 0; if(context == 0){ x = 1-x; if(x == 1){ context = 1; 87 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 } else{ context = 0; } } else if(context == 1){ x = 1-x; if(x ==1){ context = 1; } else{ context = 0; } } else if(context == 2){ gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); context = 1; } return FALSE; } gint uim_pressed_k1(void){ static int x = 0; if(context == 1){ x = 1-x; if(x == 1){ str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); entry_pos[entry_num] = 7; gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]); context = 2; } else if(x == 0){ context = 1; } } else if(context == 2){ context == 1; } return FALSE; } gint uim_rotated_k0(int n) { rotary = 0; if(context == 0){ //printf("in home context\n"); g_timeout_add(1,(GSourceFunc)(uim_state_home(n)),NULL); } else if(context == 1){ g_timeout_add(1,(GSourceFunc)(uim_state_field_select(n)),NULL); } else if(context == 2){ g_timeout_add(1,(GSourceFunc)(uim_state_edit_field(n)),NULL); } return FALSE; } // -1 = ccw, 1 = cw //dependent on context but should rotate arrows at top of graphs and go through text entries gint uim_rotated_k1(int n){ rotary = 1; if(context == 0){ g_timeout_add(1,(GSourceFunc)(uim_state_home(n)),NULL); } else if(context == 2){ g_timeout_add(1,(GSourceFunc)(uim_state_edit_field(n)),NULL); } return FALSE; } // keypad // num := 0..9 //initialize position array so cursor is in correct spot 88 135 136 137 138 139 140 141 ; 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 ); 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 gint uim_pressed_number(char num){ if(context = 3){ char str[] = {num,0}; gtk_editable_insert_text(GTK_EDITABLE(button_entry[entry_num]),str,1,entry_pos); //gtk_entry_append_text(GTK_ENTRY(button_entry[entry_num]),str); if(entry_pos[entry_num] < 11){ gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]++) } else{ context = 1; } } else{ printf("this isn't implemented yet\n"); } return FALSE; } gint uim_pressed_star(void){ if(context == 1){ context = 3; str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),""); } else if(context == 3){ context = 1; } else{ printf("this function hasn't been implemented yet\n"); } return FALSE; } gint uim_pressed_pound(void){ if(context == 3){ if (entry_num >= 8){ entry_num = 8; gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); context = 1; } else{ gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]-} } else if(context == 2){ gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); context = 1; } return FALSE; } gint uim_state_home(int n){ pixel1 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center); pixel2 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center-1); pixel_diff= pixel1 - pixel2; if(rotary == 1){ if(n == DIR_CW){ //clockwise = zoom in //use the difference in x-values displayed //on graph to create proper scaling temp_width = width - pixel_diff; if(temp_width < MIN_WIDTH){ width = width; } else if(center - temp_width < MIN_WIDTH){ width = width; } else if(center + temp_width > MAX_WIDTH){ width = width; } 89 206 else{ 207 width = temp_width; 208 } 209 //printf("the pix difference is: %f\n",pixel_diff); 210 } 211 else if(n == DIR_CCW){ 212 //counter clockwise = zoom out 213 //use the difference in x-values displayed 214 //on graph to create proper scaling 215 temp_width = width + pixel_diff; 216 if(temp_width > MAX_WIDTH){ 217 width = width; 218 } 219 else if(center + temp_width > MAX_WIDTH){ 220 width = width; 221 } 222 else if(center - temp_width < MIN_WIDTH){ 223 width = width; 224 } 225 else{ 226 width = temp_width; 227 } 228 } 229 } 230 else if(rotary == 0){ 231 if(n == DIR_CW){ 232 //clockwise = move the center right 233 temp_center = center + pixel_diff; 234 if(temp_center+width > MAX_WIDTH){ 235 center = center; 236 } 237 else{ 238 center = temp_center; 239 } 240 //printf("the pix difference is: %f\n",pixel_diff); 241 } 242 else if(n == DIR_CCW){ 243 //counter clockwise = move the center left 244 temp_center = center - pixel_diff; 245 if(temp_center - width < MIN_WIDTH){ 246 center = center; 247 } 248 else{ 249 center = temp_center; 250 } 251 } 252 } 253 254 pixel_diff2 = 5*pixel_diff; 255 amp1 = gtk_databox_pixel_to_value_y(GTK_DATABOX(databox_highres),0); 256 amp2 = gtk_databox_pixel_to_value_y(GTK_DATABOX(databox_highres),5); 257 amp_diff= 5*(amp1 - amp2); 258 259 sprintf(&pixel_diff_str,"Hz/Div: %f",pixel_diff2); 260 sprintf(&_diff_str,"Amp/Div: %f",amp_diff); 261 sprintf(&hz_diff_str,"Hz Rate: %f",pixel_diff); 262 //gtk_label_set_text(GTK_LABEL(lowerGraphDiv),&pixel_diff_str); 263 //gtk_label_set_text(GTK_LABEL(upperGraphDiv),&_diff_str); 264 //gtk_label_set_text(GTK_LABEL(graphRate),&hz_diff_str); 265 return FALSE; 266 } 267 268 gint uim_state_field_select(int n){ 269 static int last = 0; 270 if(n == last){ 271 last = 0; 272 if(n == DIR_CW){ 273 if(entry_num >= 9){ 274 entry_num = 1; 275 gtk_widget_grab_focus(button_entry[entry_num]); 276 } 277 else{ 278 entry_num = entry_num + 1; 90 279 gtk_widget_grab_focus(button_entry[entry_num]); 280 } 281 } 282 else if(n == DIR_CCW){ 283 if(entry_num <= 1){ 284 entry_num = 9; 285 gtk_widget_grab_focus(button_entry[entry_num]); 286 } 287 else{ 288 entry_num = entry_num - 1; 289 gtk_widget_grab_focus(button_entry[entry_num]); 290 } 291 } 292 } 293 else{ 294 last = n; 295 } 296 return FALSE; 297 } 298 299 gint uim_state_edit_field(int n){ 300 static int last = 0; 301 if(rotary == 1){ 302 int i,j,store=-1,flag=0; 303 char* str3 = gtk_editable_get_chars(GTK_EDITABLE(button_entry[entry_num]),0,11); 304 i = entry_pos[entry_num]; 305 if(n == last){ 306 last = 0; 307 if(n == DIR_CW){ 308 do{ 309 if(str3[i] == '.'){ 310 str3[i] = '.'; 311 i=i-n; 312 flag = 1; 313 } 314 else{ 315 str3[i]=str3[i]+n; 316 if(str3[i] > '9'){ 317 if(i == 0){ 318 str3[i] = '9'; 319 flag = 0; 320 } 321 else{ 322 str3[i] = '0'; 323 i=i-n; 324 flag = 1; 325 } 326 } 327 else{ 328 flag = 0; 329 } 330 } 331 }while(flag); 332 } 333 else if(n == DIR_CCW){ 334 for(j=0;j<=i;j++){ 335 if(str3[j] > '0'){ 336 store = j; 337 } 338 } 339 do{ 340 if(str3[i] == '.'){ 341 str3[i] = '.'; 342 i--; 343 flag = 1; 344 } 345 else if(store == -1){ 346 str3[i] = '0'; 347 flag = 0; 348 } 349 else if(store >= 0){ 350 if(i == store){ 351 str3[i]--; 91 352 } 353 else if(i > store){ 354 str3[i] = '9'; 355 } 356 if(i != 0){ 357 i--; 358 flag = 1; 359 } 360 else{ 361 flag = 0; 362 } 363 } 364 }while(flag); 365 } 366 } 367 else{ 368 last = n; 369 } 370 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str3); 371 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]); 372 } 373 else if(rotary == 0){ 374 if(n == last){ 375 if(n == DIR_CW){ 376 if(entry_pos[entry_num] >= 10){ 377 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]=10); 378 } 379 else{ 380 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]++); 381 } 382 } 383 else if(n == DIR_CCW){ 384 if(entry_pos[entry_num] < 1){ 385 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]=0); 386 } 387 else{ 388 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry _num]--); 389 } 390 } 391 } 392 else{ 393 last = n; 394 } 395 } 396 return FALSE; 397 } 1.4 uim_functions.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include #include #include #include #include #include #include #include #include #include #include #include #include <gtk/gtk.h> <glib.h> <gio/gio.h> <stdlib.h> <fcntl.h> <termios.h> <string.h> <errno.h> // errno <gtkdatabox.h> <gtkdatabox_points.h> <gtkdatabox_ruler.h> <gtkdatabox_lines.h> <gtkdatabox_grid.h> #define MAX_ENTRY 11 #define MAX_WIDTH 250000 #define MIN_WIDTH 700 92 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #define #define #define #define #define #define #define #define #define #define #define BTN_HOME 'A' BTN_MEASURE 'B' BTN_CURSOR 'C' BTN_MEMORY 'D' BTN_POWER 'P' BTN_K0 'X' BTN_K1 'Y' K0_CCW '<' K0_CW '>' K1_CCW '{' K1_CW '}' #define DIR_CW 1 // -1 = counter clockwise #define DIR_CCW -1 // -1 = counter clockwise // buttons A-D, P extern gint uim_pressed_home(void); extern gint uim_pressed_measure(void); extern gint uim_pressed_cursor(void); extern gint uim_pressed_memory(void); extern gint uim_pressed_power(void); // knobs x, extern gint extern gint extern gint extern gint y uim_pressed_k0(void); uim_pressed_k1(void); uim_rotated_k0(int n); // -1 = ccw, 1 = cw uim_rotated_k1(int n); // -1 = ccw, 1 = cw // keypad extern gint uim_pressed_number(char num); // num := 0..9 extern gint uim_pressed_star(void); extern gint uim_pressed_pound(void); extern extern extern extern gint gint gint gint uim_state_home(int n); uim_state_field_select(int n); uim_state_keypad_entry(int n); uim_state_edit_field(int n); 1.4.1 uim_settings.txt 1 ; Team Spectrum DOSA Configuration File 2 ; Note, metric prefixes should be accepted, but the actual SI unit is not 3 ; validated (so, for example, 1.5 mm is a valid frequency (0.0015 hz) 4 5 [config] ; Configuration Versioning 6 version = 1 ; Version 1 7 8 [dcm] 9 free spectral range = 1.5 GHz ; Free spectral range (FSR) of SPFI cavity 10 ;mirror reflectivity = 99.9998 % ; Mirror reflectivity (either % or 0.999...) 11 ;mirror spacing = 15 mm ; Mirror spacing 12 ;gain = 4 mm ; SFPI 13 ;laser wavelength = 785.80 nm ; Nominal wavelength, for auto-locking 14 start voltage = 15 V ; minimum allowable voltage for cavity 15 stop voltage = 450 V ; maximum allowable voltage for cavity 16 refresh rate = 10 Hz ; scan frequency limit 17 volts per fsr = 62.5 V ;volts per free spectral range 18 output steps per volt = 8418135 ;code points on DAC 19 ipm clock frequency = 25 MHz ;adc sample freq 20 21 [data] 22 output path = /data 23 output type = csv ; Output file extension 24 93 1.4.2 userIOusb.c 1 #include "userIOusb.h" 2 3 GIOChannel *deviceChannel; 4 //#define __USE_STD 5 //#define _DEBUG 6 7 void uim_rx(char c) 8 { 9 if(fsm_enabled) 10 { 11 if(FSMrunning == 1) 12 { 13 if(c >= '0' && c <= '9') 14 uim_pressed_number(c); // Handle numeric entry 15 else 16 { 17 switch (c){ 18 case BTN_HOME: 19 g_timeout_add(1,(GSourceFunc)(&uim_pressed_home),NULL); 20 break; 21 case BTN_MEASURE: 22 g_timeout_add(1,(GSourceFunc)(&uim_pressed_measure),NULL); 23 break; 24 case BTN_CURSOR: 25 g_timeout_add(1,(GSourceFunc)(&uim_pressed_cursor),NULL); 26 break; 27 case BTN_MEMORY: 28 g_timeout_add(1,(GSourceFunc)(&uim_pressed_memory),NULL); 29 break; 30 case BTN_POWER: 31 g_timeout_add(1,(GSourceFunc)(&uim_pressed_power),NULL); 32 break; 33 case BTN_K0: 34 g_timeout_add(1,(GSourceFunc)(&uim_pressed_k0),NULL); 35 break; 36 case BTN_K1: 37 g_timeout_add(1,(GSourceFunc)(&uim_pressed_k1),NULL); 38 break; 39 case '*': 40 g_timeout_add(1,(GSourceFunc)(&uim_pressed_star),NULL);//do for all c ases 41 break; 42 case '#': 43 g_timeout_add(1,(GSourceFunc)(&uim_pressed_pound),NULL); 44 break; 45 case K0_CCW: 46 uim_rotated_k0(DIR_CCW); // -1 = ccw, 1 = cw 47 break; 48 case K0_CW: 49 uim_rotated_k0(DIR_CW); // -1 = ccw, 1 = cw 50 break; 51 case K1_CCW: 52 uim_rotated_k1(DIR_CCW); // -1 = ccw, 1 = cw 53 break; 54 case K1_CW: 55 uim_rotated_k1(DIR_CW); // -1 = ccw, 1 = cw 56 break; 57 default: 58 // TODO RMDEBUG 59 printf("Unknown character returned '%c'\n",c); 60 break; 61 } 62 } 63 } 64 } 65 else 66 printf("RX logic disabled for '%c'\n", c); 67 //FSMrunning = 0; 68 //return TRUE; 94 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 } // Outputs int uim_output_str(char* str) { if(!ftdi_fd) { fprintf(stderr,"File not open??"); return FALSE; } return write(ftdi_fd, str, strlen(str)); } int uim_test_connected() { return ftdi_fd != 0; } /****** Helper to set up shutdown stuff ***********/ void setupShutdown(void) { // Set up the program to handle system signals gracefully // see http://www.cplusplus.com/reference/clibrary/csignal/signal/ void (*prev_fn)(int); prev_fn = signal(SIGINT, terminate); if (prev_fn==SIG_IGN) { signal (SIGINT,SIG_IGN); fprintf(stderr,"Could not register sigterm_handler!\n"); } // Add exit notifier (called on exit(n) ) atexit (onExit); } /******* Called on SIGINT (^c) after being registered by singal() ******/ void terminate( int parameter ) { // Attempt to close the serial port if(ftdi_fd == 0) // open() == 0 indicates it was never opened { // TODO RMDEBUG printf("FTDI device never opened...\n"); } else if(close(ftdi_fd) == 0) // close() == 0 indicates sucess { // TODO RMDEBUG printf("FTDI device descriptor closed.\n"); } else { fprintf(stderr,"FTDI device descriptor failed to close.\n"); } // Exit nicely exit(parameter); } /** * Configures a non-blocking 115200/8n1 FTDI connnection on the specified * filename. * * Returns 0 if the FTDI device was opened, otherwise -1 */ int openFTDIfd(char* filename,GIOChannel **deviceChannelP) { ////// Locals ////// 95 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 ; 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 int result; int tty_fd; struct termios tio; int nloop; int nread; // // // // // Result of last opperation File discriptor number from UNIX 'open' Struct modifying the paramaters of the serial term loops to wait for bootup bytes read from the stream #ifdef _DEBUG printf("openFTDIfd -> Called\n"); #endif /* Ensure that the file exists * see http://linux.die.net/man/2/access , #include <unistd.h> F_OK - validate that the file exists */ result = access(filename, F_OK); if( result != 0) { fprintf(stderr,"FTDI device %s does not exist.\n", filename); return 2; } /** Ensure read/write permissions. R_OK - ability to read W_OK - ability to write */ result = access(filename, R_OK | W_OK); if( result != 0) { fprintf(stderr,"FTDI device %s permission denied: %s\n", filename, strerror( errno )) return 3; } /** Open the terminal using UNIX IO * See http://rabbit.eng.miami.edu/info/functions/unixio.html * This function returns a file desriptor number, or 0 if the file could * not be opened. O_RDWR - read and write O_NONBLOCK - don't block reads O_NOCTTY - don't allow FTDI device to kill connection with ^C */ //tty_fd = open(FTDI_DEV, O_RDWR | O_NONBLOCK );//| O_NOCTTY); //add nonblocking IO tty_fd = open(FTDI_DEV, O_RDWR );//| O_NOCTTY); #ifdef _DEBUG printf("openFTDIfd -> FD#= %d\n", tty_fd); #endif if(tty_fd <= 0) { fprintf(stderr,"FTDI device %s can not be opened:%s\n", filename, strerror( errno )); return 4; } /** Zero out TIO struct * inc: string.h */ memset(&tio,0,sizeof(tio)); /** Configure the serial terminal * inc: termios.h * ref1: http://linux.die.net/man/3/tcsetattr * ref2: http://en.wikibooks.org/wiki/Serial_Programming/termios * ref3: http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html */ // Input mode: raw tio.c_iflag = 0; 96 214 // Output mode: raw 215 tio.c_oflag = 0; 216 217 // Local mode: raw 218 tio.c_lflag = 0; 219 220 // Control modes: [ref2][ref3] 221 // CS8 - 8n1 (8bit,no parity,1 stopbit) 222 // CREAD - enable reciever 223 // CLOCAL - ignore modem control lines 224 tio.c_cflag = CS8 | CREAD | CLOCAL; 225 226 /* So called "Non-Canonical Input Processing" [ref3] is controlled by VMIN 227 and VTIME: 228 If MIN > 0 and TIME = 0, MIN sets the number of characters to receive 229 before the read is satisfied. As TIME is zero, the timer is not used. 230 If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will be 231 satisfied if a single character is read, or TIME is exceeded 232 (t = TIME *0.1 s). If TIME is exceeded, no character will be returned. 233 If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. 234 The read will be satisfied if MIN characters are received, or the time 235 between two characters exceeds TIME. The timer is restarted every time 236 a character is received and only becomes active after the first 237 character has been received. 238 If MIN = 0 and TIME = 0, read will be satisfied immediately. 239 */ 240 tio.c_cc[VMIN] = 0; 241 tio.c_cc[VTIME] = 10; 242 243 // Set the baudrate to 115200 bits/second 244 cfsetospeed(&tio,B115200); // TX speed = 115200 baud 245 cfsetispeed(&tio,B115200); // RX speed = 115200 baud 246 247 // Apply attributes set above 248 // TCSANOW - do it imedialty [ref1] 249 result = tcsetattr(tty_fd,TCSANOW,&tio); 250 if( result != 0 ) { 251 fprintf(stderr,"FTDI device %s can not be configured.\n", filename); 252 terminate(5); 253 } 254 255 #ifdef _DEBUG 256 printf("openFTDIfd -> Configured (EAGIN=%d)\n", EAGAIN); 257 #endif 258 259 char* spam = "::\n"; // invalid combo for the SPIN fsm, returns an error 260 // wait for bootup 261 for(nloop = 0; nloop < PROPELLER_STARTUP_WAIT_SPINS; nloop++) 262 { 263 // 264 // Write out the invalid string (which will cause the prop to error) 265 // 266 //int write( int handle, void *buffer, int nbyte ); 267 result = write(tty_fd, spam, 3); 268 269 #ifdef _DEBUG 270 if(result < 0 ) 271 printf( "Spin loop write error (loop=%d): %d %s\n", nloop, errno, strerror( errno ) ); 272 else 273 printf("Waiting for feedback (loop=%d), wrote %d bytes\n", nloop, result); 274 #endif 275 276 // 277 // Sleep, give the system a chance to catch up 278 // 279 usleep(PROPELLER_STARTUP_WAIT_USEC); 280 281 // 282 // Try to read some bytes back, which would indicate that it started 283 // 284 //int read( int handle, void *buffer, int nbyte ); 285 nread = read(tty_fd, buff, 16); 97 286 287 #ifdef _DEBUG 288 if(nread < 0) 289 printf( "Spin loop read error (loop=%d): %d %s\n", nloop, errno, strerror( errno ) ); 290 else 291 printf("Got %d bytes of data (loop %d)\n", nread, nloop); 292 #endif 293 294 if(nread > 0){ 295 break; 296 } 297 298 } 299 300 // At this point, either we have read some bytes or timed out 301 // the former condition is indicated by a postive nread 302 if(nread > 0) 303 { 304 // as long as there is stuff in the buffer, drain 305 while(nread > 0) 306 { 307 // try to read again 308 nread = read(tty_fd, buff, 16); // drain the stream 309 #ifdef _DEBUG 310 if(nread < 0) 311 //perror( "Error draining data" ); 312 printf( "Drain loop read error: %d %s\n", errno, strerror( errno ) ); 313 else 314 printf("Drained %d bytes of data.\n", nread); 315 #endif 316 } 317 318 // Set the global varaible, and return 0 319 ftdi_fd = tty_fd; 320 #ifdef _DEBUG 321 printf("ftdi_fd=%d \n", (int)ftdi_fd); 322 #endif 323 deviceChannel= (*deviceChannelP) = g_io_channel_unix_new(fileno(fdopen(tty_fd,"rw+")) ); 324 325 pthread_t thread; 326 return pthread_create(&thread,NULL ,&doBackgroundIOopsLoop,NULL); 327 } 328 329 // No dice. Something went wrong 330 fprintf(stderr,"FTDI device %s timed out without a response.\n", filename); 331 332 // failure 333 return 5; 334 } 335 336 337 338 // keep track of state 339 int btn_state = 0; 340 341 int uim_led_set(char btn, int val){ 342 if(btn< 'A' || btn> 'Z') { 343 #ifdef _DEBUG 344 printf("You're an idiot %d\n",btn); 345 #endif 346 return 1; // not a valid button 347 } 348 349 // select correct bit of state 350 int mask = 1<<(btn - 'A'); 351 352 // command string x\0 353 char cmd[2] = " "; 354 355 if(val){ 356 // turn on 98 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 cmd[0] = btn; btn_state |= mask; } else { // A->a turn off cmd[0] = btn+0x20; btn_state &= ~mask; } return uim_output_str(cmd); } int uim_led_toggle(char btn){ if(btn< 'A' || btn> 'Z') { #ifdef _DEBUG printf("You're an idiot %d\n",btn); #endif return 1; // not a valid button } // select correct bit of state int mask = 1<<(btn - 'A'); // command string x\0 char cmd[2] = " "; if(mask & btn_state){ // already set, need to turn off cmd[0] = btn+0x20; } else { cmd[0] = btn; } uim_output_str(cmd); // toggle state variable btn_state ^= mask; return 0; } extern volatile unsigned int drawing; void *doBackgroundIOopsLoop(){ while(1){ //printf("the io loop\n"); if((doBackgroundIOops(deviceChannel,G_IO_IN,NULL))){ //if(counter >=3){ drawing = 2; //request_redraw(); //counter = 0; //} //else //counter++; } while(drawing){ //pthread_yield(); sched_yield(); //sleep(.01); } } } gboolean doBackgroundIOops(GIOChannel *deviceChannel,GIOCondition condition,gpointer data) { int nread; #ifdef __USE_STD int result; // Read from stdin result = scanf("%s",buff); if(result < 0) { perror("Error writing to stream"); 99 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 terminate(1); } else if(result > 0) { write(ftdi_fd, buff, (unsigned)strlen(buff)); #ifdef _DEBUG printf("%s\n", buff); #endif } #endif //nread = g_io_channel_read_chars(deviceChannel,buff,128,NULL,NULL); nread = read(ftdi_fd, buff, 128); if(nread < 0) { perror("Error reading stream"); terminate(1); } else if(nread > 0) { #ifdef __USE_STD buff[nread] = 0; printf("%s\n", buff); #else int i=0; printf("nread = %d\n",nread); for(i = 0; i < nread; i++){ FSMrunning = 1; //input = buff[i]; uim_rx(buff[i]); } FSMrunning = 0; return TRUE; #endif } return FALSE; } 1.4.3 userIOusb.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /* Kevin Nicotera */ /* 9/8/12 */ //includes //#include "uim_functions.h" #include <stdio.h> #include <gtk/gtk.h> #include <glib.h> #include <gio/gio.h> #include <stdlib.h> #include <fcntl.h> #include <termios.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <errno.h> // errno //defines #define FTDI_DEV "/dev/ttyUSB0" // UIM-E board #define PROPELLER_STARTUP_WAIT_USEC 1000*200 // 50ms #define PROPELLER_STARTUP_WAIT_SPINS 40 //2 seconds = 40 * 50ms #define _ECHO_I2C_VERSION ":4cXfe24?" #define #define #define #define #define #define BTN_HOME 'A' BTN_MEASURE 'B' BTN_CURSOR 'C' BTN_MEMORY 'D' BTN_POWER 'P' BTN_K0 'X' 100 33 #define BTN_K1 'Y' 34 #define K0_CCW '<' 35 #define K0_CW '>' 36 #define K1_CCW '{' 37 #define K1_CW '}' 38 39 #define DIR_CW 1 // -1 = counter clockwise 40 #define DIR_CCW -1 // -1 = counter clockwise 41 //****************** GLOBALS 42 int ftdi_fd; // fd of the tty port 43 int fsm_enabled; // enable/disable for FSM processing 44 45 char buff[256]; // buffer for exchanging info 46 //char* buffpos = buff; 47 /* 48 //This function will set appropriate settings to communicate with the front panel 49 void initFrontPanel(void); 50 51 //Takes in data from deviceChannel 52 //input/output channel (FTDI device/ttyUSB0) deviceChannel, condition to enter, data 53 gboolean handleSerialInput(GIOChannel *deviceChannel,GIOCondition condition,gpointer data); 54 55 //Send data to front panel 56 //input/output channel (FTDI device/ttyUSB0) deviceChannel, condition to enter, data 57 gboolean handleSerialOutput(GIOChannel *deviceChannel,GIOCondition condition,gpointer data); 58 */ 59 60 //**************** FUNCTION PROTOTYPES ***********************/// 61 int openFTDIfd(char* filename,GIOChannel **deviceChannel); 62 63 // These functions are exit helpers 64 void setupShutdown(void); 65 void terminate( int parameter ); 66 extern void onExit(void); 67 extern void request_redraw(void); 68 69 ///////////////////////// 70 // buttons A-D, P 71 gint uim_pressed_home(void); 72 gint uim_pressed_measure(void); 73 gint uim_pressed_cursor(void); 74 gint uim_pressed_memory(void); 75 gint uim_pressed_power(void); 76 77 // knobs x, y 78 gint uim_pressed_k0(void); 79 gint uim_pressed_k1(void); 80 gint uim_rotated_k0(int n); // -1 = ccw, 1 = cw 81 gint uim_rotated_k1(int n); // -1 = ccw, 1 = cw 82 83 // keypad 84 gint uim_pressed_number(char num); // num := 0..9 85 gint uim_pressed_star(void); 86 gint uim_pressed_pound(void); 87 88 gint uim_state_home(int n); 89 gint uim_state_field_select(int n); 90 gint uim_state_keypad_entry(int n); 91 gint uim_state_edit_field(int n); 92 93 // Front Panel Handler (internal) 94 gboolean doBackgroundIOops(GIOChannel *deviceChannel,GIOCondition condition,gpointer data); / / handler 95 void *doBackgroundIOopsLoop(); 96 void uim_rx(char c); 97 98 int FSMrunning; 99 char input; 100 // Outputs 101 int uim_output_str(char* str); 102 int uim_led_toggle(char btn); 103 // Tests 104 int uim_test_connected(); // Tests to see if the UIM is connected. TRUE=yes, FALSE = no 101 1.5 UIM-E – Propeller P8X32A Embedded Controller 1.5.1 Basic_I2C_Driver.spin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 '' '' '' '' Basic I2C Routines Version 1.1.1 - Jacob DIlles Written by Michael Green and copyright (©) 2007 Permission is given to use this in any program for the Parallax Propeller processor as long as this copyright notice is included. '' This is a minimal version of an I2C driver in SPIN. It assumes '' that the SDA pin is one higher than the SCL pin. It assumes that '' neither the SDA nor the SCL pins have pullups, so drives both. '' '' '' '' These routines are primarily intended for reading and writing EEPROMs. The low level I2C are provided for use with other devices, but the read/write byte routines assume a standard I2C serial EEPROM with a 16 bit device address register, paged writes, and acknowledge polling. '' '' '' '' '' '' '' '' '' '' '' All of these read/write routines accept an EEPROM address up to 19 bits (512K) even though the EEPROM addressing scheme normally allows for only 16 bits of addressing. The upper 3 bits are used as part of the device select code and these routines will take the upper 3 bits of the address and "or" it with the supplied device select code bits 3-1 which are used to select a particular EEPROM on an I2C bus. There are two schemes for selecting 64K "banks" in 128Kx8 EEPROMs. Atmel's 24LC1024 EEPROMs allow simple linear addressing up to 256Kx8 ($00000 to $3FFFF). Microchip's 24LC1025 allows for up to 512Kx8, but in two areas: $00000 to $3FFFF and $40000 to $7FFFF. Each EEPROM provides a 64K "bank" in each area. See the device datasheets for details. '' '' '' '' '' This will work with the boot EEPROM and does not require a pull-up resistor on the SCL line (but does on the SDA line ... about 4.7K to +3.3V). According to the Philips I2C specification, both pull-ups are required. Many devices will tolerate the absence of a pull-up on SCL. Some may tolerate the absence of a pull-up on SDA as well. '' '' '' '' Initialize may have to be called once at the beginning of your program. Sometimes an I2C device is left in an invalid state. This will reset the device to a known state so it will respond to the I2C start transition (sent out by the i2cStart routine). '' To read from or write to an EEPROM on pins 28/29 like the boot EEPROM: '' CON '' eepromAddress = $7000 '' VAR '' byte buffer[32] '' OBJ '' i2c : "Minimal_I2C_Driver" '' PRI readIt '' if i2c.ReadPage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32) '' abort ' an error occurred during the read '' PRI writeIt | startTime '' if i2c.WritePage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32) '' abort ' an error occured during the write '' startTime := cnt ' prepare to check for a timeout '' repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress) '' if cnt - startTime > clkfreq / 10 '' abort ' waited more than a 1/10 second for the write to finish '' Note that the read and write use something called paged reads/writes. '' This means that any read using ReadPage must fit entirely in one '' EEPROM if you have several attached to one set of pins. For writes, 102 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 '' '' '' '' '' '' '' '' any write using i2cWritePage must fit entirely within a page of the EEPROM. Usually these pages are either 32, 64, 128 or 256 bytes in size depending on the manufacturer and device type. 32 bytes is a good limit for the number of bytes to be written at a time if you don't know the specific page size (and the write must fit completely within a multiple of the page size). The WriteWait waits for the write operation to complete. Alternatively, you could wait for 5ms since currently produced EEPROMs will finish within that time. CON ACK NAK Xmit Recv BootPin EEPROM = = = = = = DAT scl sda 0 1 0 1 28 $A0 ' ' ' ' ' ' byte byte outa[SCL] := 1 dira[SCL] := 1 dira[SDA] := 0 repeat 9 outa[SCL] := 0 outa[SCL] := 1 if ina[SDA] quit ' An I2C device may be left in an ' invalid state and may need to be ' reinitialized. Drive SCL hig ' Set SDA as input ' Put out up to 9 clock pulses ' Repeat if SDA not driven high ' by the EEPROM ' SDA goes HIGH to LOW with SCL HIGH outa[SCL]~~ dira[SCL]~~ outa[SDA]~~ dira[SDA]~~ outa[SDA]~ outa[SCL]~ PUB Stop Acknowledge No Acknowledge Direction Transmit Direction Receive Boot EEPROM SCL Pin EEPROM Device Address 28 29 PUB Initialize(argSCL, argSDA) scl := argSCL sda := argSDA PUB Start I2C I2C I2C I2C I2C I2C ' Initially drive SCL HIGH ' Initially drive SDA HIGH ' Now drive SDA LOW ' Leave SCL LOW ' SDA goes LOW to HIGH with SCL High outa[SCL]~~ outa[SDA]~~ dira[SCL]~ dira[SDA]~ ' Drive SCL HIGH ' then SDA HIGH ' Now let them float ' If pullups present, they'll stay HIGH PUB Write(data) : ackbit '' Write i2c data. Data byte is output MSB first, SDA data line is valid '' only while the SCL line is HIGH. Data is always 8 bits (+ ACK/NAK). '' SDA is assumed LOW and SCL and SDA are both left in the LOW state. ackbit := 0 data <<= 24 repeat 8 outa[SDA] := (data <-= 1) & 1 outa[SCL]~~ outa[SCL]~ dira[SDA]~ outa[SCL]~~ ackbit := ina[SDA] outa[SCL]~ outa[SDA]~ dira[SDA]~~ ' Output data to SDA ' Toggle SCL from LOW to HIGH to LOW ' Set SDA to input for ACK/NAK ' Sample SDA when SCL is HIGH ' Leave SDA driven LOW PUB Read( ackbit): data '' Read in i2c data, Data byte is output MSB first, SDA data line is '' valid only while the SCL line is HIGH. SCL and SDA left in LOW state. data := 0 103 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 dira[SDA]~ repeat 8 outa[SCL]~~ data := (data << 1) | ina[SDA] outa[SCL]~ outa[SDA] := ackbit dira[SDA]~~ outa[SCL]~~ outa[SCL]~ outa[SDA]~ ' Make SDA an input ' Receive data from SDA ' Sample SDA when SCL is HIGH ' Output ACK/NAK to SDA ' Toggle SCL from LOW to HIGH to LOW ' Leave SDA driven LOW PUB ReadPage(devSel, addrReg, dataPtr, count) : ackbit '' Read in a block of i2c data. Device select code is devSel. Device starting '' address is addrReg. Data address is at dataPtr. Number of bytes is count. '' The device select code is modified using the upper 3 bits of the 19 bit addrReg. '' Return zero if no errors or the acknowledge bits if an error occurred. devSel |= addrReg >> 15 & %1110 Start ' Select the device & send address ackbit := Write(devSel | Xmit) ackbit := (ackbit << 1) | Write(addrReg >> 8 & $FF) ackbit := (ackbit << 1) | Write(addrReg & $FF) Start ' Reselect the device for reading ackbit := (ackbit << 1) | Write(devSel | Recv) repeat count - 1 byte[dataPtr++] := Read(ACK) byte[dataPtr++] := Read(NAK) Stop return ackbit PUB ReadByte(devSel, addrReg) : data '' Read in a single byte of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. if ReadPage(devSel, addrReg, @data, 1) return -1 PUB ReadWord(devSel, addrReg) : data '' Read in a single word of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. if ReadPage(devSel, addrReg, @data, 2) return -1 PUB ReadLong(devSel, addrReg) : data '' Read in a single long of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. '' Note that you can't distinguish between a return value of -1 and true error. if ReadPage(devSel, addrReg, @data, 4) return -1 PUB WritePage(devSel, addrReg, dataPtr, count) : ackbit '' Write out a block of i2c data. Device select code is devSel. Device starting '' address is addrReg. Data address is at dataPtr. Number of bytes is count. '' The device select code is modified using the upper 3 bits of the 19 bit addrReg. '' Most devices have a page size of at least 32 bytes, some as large as 256 bytes. '' Return zero if no errors or the acknowledge bits if an error occurred. If '' more than 31 bytes are transmitted, the sign bit is "sticky" and is the '' logical "or" of the acknowledge bits of any bytes past the 31st. devSel |= addrReg >> 15 & %1110 Start ' Select the device & send address ackbit := Write(devSel | Xmit) ackbit := (ackbit << 1) | Write(addrReg >> 8 & $FF) ackbit := (ackbit << 1) | Write(addrReg & $FF) repeat count ' Now send the data ackbit := ackbit << 1 | ackbit & $80000000 ' "Sticky" sign bit ackbit |= Write(byte[dataPtr++]) Stop return ackbit PUB WriteByte(devSel, addrReg, data) '' Write out a single byte of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the 104 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. if WritePage(devSel, addrReg, @data, 1) return true ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) waitcnt(400_000 + cnt) return false PUB WriteWord(devSel, addrReg, data) '' Write out a single word of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. '' Note that the word value may not span an EEPROM page boundary. if WritePage(devSel, addrReg, @data, 2) return true ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) waitcnt(400_000 + cnt) return false PUB WriteLong(devSel, addrReg, data) '' Write out a single long of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. '' Note that the long word value may not span an EEPROM page boundary. if WritePage(devSel, addrReg, @data, 4) return true ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) waitcnt(400_000 + cnt) return false PUB WriteWait(devSel, addrReg) : ackbit '' Wait for a previous write to complete. Device select code is devSel. Device '' starting address is addrReg. The device will not respond if it is busy. '' The device select code is modified using the upper 3 bits of the 18 bit addrReg. '' This returns zero if no error occurred or one if the device didn't respond. devSel |= addrReg >> 15 & %1110 Start ackbit := Write(devSel | Xmit) Stop return ackbit ' *************** JAMES'S Extra BITS ********************* PUB devicePresent(deviceAddress) : ackbit ' send the deviceAddress and listen for the ACK Start ackbit := Write(deviceAddress | 0) Stop if ackbit == ACK return true else return false PUB writeLocation(device_address, register, value) start write(device_address) write(register) write(value) stop PUB readLocation(device_address, register) : value start write(device_address | 0) write(register) start write(device_address | 1) value := read(NAK) stop return value '************************************* Jacob's extra bits PUB writeString(device_address, arrayPtr ) start 105 283 write(device_address) 284 repeat while byte[ arrayPtr] 285 write( byte[ arrayPtr++] ) 286 stop 287 288 PUB writeBytes(device_address, arrayPtr, n) 289 start 290 write(device_address) 291 repeat n 292 write( byte[arrayPtr++] ) 293 stop 294 295 PUB writeBytesRaw( arrayPtr, n) 296 start 297 repeat n 298 write( byte[arrayPtr++] ) 299 stop 300 301 PUB writeReadRaw( arrayPtr, n) : value | addr 302 addr := byte[arrayPtr] 303 start 304 repeat n 305 write( byte[arrayPtr++] ) 306 start 307 write(addr | 1) 308 value := read(NAK) 309 stop 310 return value 1.5.2 Front_Panel_Control_001.spin 1 { 2 Front Panel Control - UIM Embedded - Team Spectrum 3 4 George Mason University Senior Design Project 2012 5 6 File: Front Panel Controller 7 Author: Jacob Dilles <[email protected]> 8 Descrip: Top level file for managing the UIM-E devices 9 } 10 11 12 CON 13 _clkmode = xtal1 + pll16x ck mode * crystal frequency = 80 MHz 14 _xinfreq = 5_000_000 15 16 17 18 scl = 28 19 sda = 29 20 utx = 30 21 urx = 31 22 23 knob = 8 ' k1=8/9, k0=10/11 24 25 26 led = 17 27 28 29 ledp = 22 30 leda = 25 31 ledb = 24 32 ledc = 27 33 ledd = 26 34 35 sysrelay = 16 36 extint = 18 37 38 39 CR = $0D 'Standard clo 106 40 41 SHORT_DELAY = 45_000_000 42 43 OBJ 44 term : "PcFullDuplexSerial" 45 i2cObject : "basic_i2c_driver" 46 knobs : "Quadrature_Encoder" 47 lcd : "web4robot_lcd_001" 48 btns : "Front_Panel_Inputs_001" 49 VAR 50 byte i, temp 51 52 long delta 53 54 PUB Main 55 56 dira := 0 57 58 dira[leda] := 1 59 dira[ledb] := 1 60 dira[ledc] := 1 61 dira[ledd] := 1 62 dira[ledp] := 1 63 dira[led] := 1 64 dira[sysrelay] := 1 65 66 67 'term.str( string("Restart", 13) ) 68 outa[led] := 1 69 70 {Set up the Keypad object} 71 'kp.Init 72 btns.Init 73 74 {Set up the Rotary Encoder object 75 knobs.Start(knob, 2, 2, @rotarybuff) } 76 77 {Start up the i2c master} 78 i2cObject.Initialize(SCL, SDA) 79 80 {Start the LCD} 81 lcd.Start 82 'lcd.off 83 84 ' Define the logo 85 lcd.charmap(1, @LOGO1) 86 lcd.charmap(2, @LOGO2) 87 lcd.charmap(3, @LOGO3) 88 lcd.charmap(4, @LOGO4) 89 90 ' Write the logo 91 lcd.clear 92 lcd.str(String("Team Spectrum ",4,1,2,3,4)) 93 ' Write some text so there is something to read 94 ' while the RPi boots. 95 lcd.line(2) 96 lcd.str(String("DOSA is starting up ")) 97 98 'If no usb host is found, for some reason the USB FTDI chip 99 ' will reset the Propeller. So at least show a little animation 100 ' rather than flashing over and over 101 lcd.line(3) 102 lcd.str(String("Please standby ")) 103 waitcnt(clkfreq/2+cnt) 104 lcd.line(3) 105 lcd.str(String("Please standby. ")) 106 waitcnt(clkfreq/2+cnt) 107 lcd.line(3) 108 lcd.str(String("Please standby.. ")) 109 waitcnt(clkfreq/2+cnt) 110 term.start(urx, utx,0,115200) ' start the serial terminal here for smoother ani mation 111 lcd.line(3) 107 112 lcd.str(String("Please standby... ")) 113 waitcnt(clkfreq/2+cnt) 114 115 ' Start serial terminal 116 'term.start(urx, utx,0,115200) ' see above 117 118 ' Some more text, to show we have a valid serial link 119 lcd.line(3) 120 lcd.str(String("Reticulating Splines")) 121 waitcnt(SHORT_DELAY+cnt) 122 lcd.line(3) 123 lcd.str(String("Igniting Arc Reactor")) 124 waitcnt(SHORT_DELAY+cnt) 125 lcd.line(3) 126 lcd.str(String("Magnetizing Neutrons")) 127 waitcnt(SHORT_DELAY+cnt) 128 lcd.line(3) 129 lcd.str(String("Redimensioning Units")) 130 waitcnt(SHORT_DELAY+cnt) 131 lcd.line(3) 132 lcd.str(String("Cranking Up Past 11 ")) 133 waitcnt(SHORT_DELAY+cnt) 134 lcd.line(3) 135 lcd.str(@clearline) 136 137 {wait for first serial character} 138 i := 0 139 lcd.line(3) 140 temp := "." 141 repeat while term.rxtime(100) == -1 142 if i == 20 143 i := 0 144 lcd.line(3) 145 if temp == "." 146 temp := " " 147 else 148 temp := "." 149 else 150 i++ 151 lcd.out(temp) 152 term.tx(".") 153 154 lcd.line(2) 155 lcd.str(@clearline) 156 lcd.line(3) 157 lcd.str(@clearline) 158 159 {Main Infinate Loop} 160 repeat 161 btns.getChars(@msg) 162 term.str(@msg) 163 164 165 166 doFSM(term.rxcheck) 167 outa[led] := 1 ' blink the light to let us know it's alive 168 waitcnt(clkfreq/10+cnt) 169 doFSM(term.rxcheck) 170 outa[led] := 0 171 waitcnt(clkfreq/10+cnt) 172 173 174 PRI DoFSM(c) | hex 175 if c == -1 176 Return FALSE 177 178 179 { ' Remove me to enable debugging 180 term.hex(c,2) 181 term.tx(" ") 182 term.hex(k, 2) 183 term.tx(" ") 108 184 if (c => $20) AND (c =< $7F) 185 term.tx(c) 186 term.tx(CR) 187 } 188 case state 189 WAITING: 190 k := 0 191 case c 192 "p": outa[ledp] := 0 193 "P": outa[ledp] := 1 194 "a": outa[leda] := 0 195 "A": outa[leda] := 1 196 "b": outa[ledb] := 0 197 "B": outa[ledb] := 1 198 "c": outa[ledc] := 0 199 "C": outa[ledc] := 1 200 "d": outa[ledd] := 0 201 "D": outa[ledd] := 1 202 "s": outa[sysrelay]:= 0 203 "S": outa[sysrelay]:= 1 204 "l": lcd.Off 205 "L": lcd.On 206 "h": lcd.home 207 "0": lcd.line(0) 208 "1": lcd.line(1) 209 "2": lcd.line(2) 210 "3": lcd.line(3) 211 "k": lcd.clear 212 "u": lcd.underline(FALSE) 213 "U": lcd.underline(TRUE) 214 "j": lcd.blink(FALSE) 215 "J": lcd.blink(TRUE) 216 ":": state := ADDRESS0 217 "?": term.tx("!") 218 $27: doFSM($22) 219 $22: doFSM(":") 220 doFSM("4") 221 doFSM("C") 222 doFSM("'") 223 "T": lcd.str(String("Team Spectrum 224 ADDRESS0: 225 hex := hex2nib( c ) 226 if hex == -1 227 term.str(term.str(@badhex)) 228 term.dec(c) 229 state := WAITING 230 else 231 buff[k] := hex << 5 232 state := ADDRESS1 233 ADDRESS1: 234 hex := hex2nib( c ) 235 if hex == -1 236 term.str(@badhex) 237 term.dec(c) 238 state := WAITING 239 else 240 buff[k++] |= ((hex <<1) & $1E) 241 state := ADDRESS2 242 ADDRESS2: 243 'term.str(string(13,"+A3 ")) 244 'term.dec(buff[0]) 245 case c 246 "X": state := HIGHBITS 247 "x": state := HIGHBITS 248 $22: state := STRSEND 249 $27: state := STRSEND 250 OTHER: 251 state := waiting 252 term.str(@badhex) 253 term.dec(c) 254 HIGHBITS: 255 'term.str(string(13,"+HB ")) 256 case c ' echo to show we're alive ",4,1,2,3,4)) ' debug 109 257 CR: 258 if k > 0 259 ' Send here 260 i2cObject.writeBytesRaw(@buff, k) 261 'repeat c from 0 to k 262 'term.hex(buff[c], 2) 263 else 264 term.str(string("No data to send!",13)) 265 state := WAITING 266 "?": 267 c := i2cObject.writeReadRaw(@buff, k) 268 term.hex(c,2) 269 term.tx(CR) 270 state := WAITING 271 other: 272 hex := hex2nib( c ) 273 if hex == -1 274 term.str(@badhex) 275 term.dec(c) 276 state := WAITING 277 else 278 buff[k] := (hex <<4) ' upper 4 bits 279 state := LOWBITS ' Next state 280 LOWBITS: 281 hex := hex2nib(c) 282 if hex == -1 283 term.str(@badhex) 284 term.dec(c) 285 state := WAITING 286 else 287 buff[k++] |= (hex & $0F) 288 state:= HIGHBITS 289 STRSEND: 290 case c 291 ' Enter to send 292 CR: 293 i2cObject.writeBytesRaw(@buff, k) 294 state := WAITING 295 ' Backspace to delete 296 $08: 297 if k > 1 298 k-299 state := STRSEND 300 ' Escape to cancel 301 $1B: state := WAITING 302 ' Printable Characters 303 $20..$7F: 304 if k < 40 305 buff[k++] := c 306 else 307 term.str(string("Buffer Overflow - Input Canceled",13)) 308 state := WAITING 309 other: 310 term.str(string("Unprintable Character: ")) 311 term.tx(c) 312 term.tx(CR) 313 state:= WAITING 314 315 Return True 316 317 PRI hex2nib(c) 318 if c > "`" 319 c -= $20 320 Return lookdown(c : $30..$39, $41..$46 ) - 1 321 322 323 CON 324 WAITING = 0 325 ADDRESS0 = 1 326 ADDRESS1 = 2 327 ADDRESS2 = 3 328 LOWBITS = 4 329 HIGHBITS = 5 110 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 STRSEND = 6 SENDING = 7 DAT state k nan buff byte byte byte byte 0 1 $ff 0[64],0 DAT badhex clearline rotarybuff msg byte "Invalid Input",0 byte " ",0 long $12345678[8] byte " "[32] ,0 'Define some custom characters to 'form the Team Spectrum logo on LCD2 'Characters are 5 wide by 7 high 'So these bits:\ are unused ' ||| ' vvv LOGO1 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_01000 byte %000_01000 byte %000_01000 byte %000_01001 byte %000_10110 ' LOGO2 byte %000_00100 byte %000_00100 byte %000_00100 byte %000_00100 byte %000_00100 byte %000_01010 byte %000_01010 byte %000_10001 ' LOGO3 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_00010 byte %000_00010 byte %000_00010 byte %000_10010 byte %000_01101 ' LOGO4 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_00000 byte %000_11111 1.5.3 Front_Panel_Inputs_001.spin 1 {{ 2 Front Panel Inputs - UIM Embedded - Team Spectrum 3 George Mason University Senior Design Project 2012 4 5 File: Input Devices Controller 6 Author: Jacob Dilles <[email protected]> 7 Descrip: Handles a 4x4 keypad on inputs [7:0], 111 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 as well as monitoring the other buttons on the front panel Call INIT first, which will take 2 COGs. Then, call getChars, as often as you like. It will copy any pending input in the 64 byte buffer to your pointer. It is a valid string, ending in '0', to be sent to the computer Idea for keypad reader came from the 4x4KeypadReader v1.0 by Beau Schwabe (2007) However, his did not work with the hybrid button/matrix keypad, so I re-wrote it with active low logic and now it works fine. Also, since a cog must be dedicated to the rising edge detector, I have mashed monitoring the other buttons in here as well. So sorry if it is not an ideal OO model :/ }} CON NumControls = 18 BUF_PTR_MASK = $3F ' 64 byte tx buffer OBJ knobs : "Quadrature_Encoder" VAR long kpstack[128], delta byte i,j, bit PUB INIT cognew(EndlessLoop, @kpstack) {Set up the Rotary Encoder object} knobs.Start(8, 2, 2, @rotarybuff) PUB GetChars(loc) '' Get the current input string waiting to be sent to '' the computer (copy to buffer) repeat until j == i byte[loc++] := buff[j++] j &= BUF_PTR_MASK delta := knobs.ReadDelta(0) repeat while delta > 0 byte[loc++] := "<" delta -repeat while delta < 0 byte[loc++] := ">" delta ++ ' Read the bottom knob delta := knobs.ReadDelta(1) repeat while delta > 0 byte[loc++] := "{" delta -repeat while delta < 0 byte[loc++] := "}" delta ++ byte[loc++] := 0 PRI EndlessLoop '' Endless loop for a new COG repeat ReadRows ReadBtns CalcChange ' Read the row data from the keypad ' Read the additional buttons ' Rising edge detector 112 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 PRI ReadBtns '' This reads the buttons, so that the same rising edge detector can be '' used with the keypad keypad <<= 2 keypad |= ina[12..13] keypad <<= 1 keypad |= ina[23] PRI ReadRows '' Keypad read-rows routine keypad := 0 ReadRow(3) keypad <<= 4 ReadRow(2) keypad <<= 4 ReadRow(1) keypad <<= 4 ReadRow(0) 'Clear 4x4 'keypad' value 'Call routine to read entire ROW 'Shift 'keypad' value left by 4 'Call routine to read entire ROW 'Shift 'keypad' value left by 4 'Call routine to read entire ROW 'Shift 'keypad' value left by 4 'Call routine to read entire ROW PRI ReadRow(n) '' Keypad Read a Row routine. Uses '' having to use pullup resistors dira[0..7] ~ ' outa[0..7] ~ ' outa[0..7] ~~ ' ' dira[0..7] ~~ ' dira[0..7] ~ ' outa[n] := 0 ' dira[n] := 1 ' dira[n] := 0 ' keypad += ina[4..7] ' 0 1 2 3 the keepers on the IO pins to get around all pins input first discharge to low preset to high all output, set keepers high all input, keepers maintain last Clear one row Activate output on that row Deactivate, keeper maintains Add in result PRI CalcChange '' Simple rising edge detector st1 := st0 st0 := !keypad kpchange:= st0 & (st0 ^ st1) ' active low ' rising edge repeat bit from 0 to numcontrols if (kpchange & 1) == 1 PutChar( kplut[bit] ) kpchange >>= 1 buff[i] := 0 ' signal end of string PRI PutChar(c) '' Add a character to the buffer buff[i] := c i := (i+1) & BUF_PTR_MASK ' circular buffer DAT kplut byte buff byte keypad st1 st0 kpchange rotarybuff "PYX321A654B987C#0*D" " "[64],0 long 0 ' holds the keypad stuff long 0 long 0 long 0 long $12345678[4] 1.5.4 pcFullDuplexSerial.spin 1 ''************************************ 2 ''* Full-Duplex Serial Driver v1.1 * 3 ''* (C) 2006 Parallax, Inc. * 113 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 ''* * ''* * ''* * ''************************************ ''* * ''* now with 64 byte rx buffers * ''************************************ VAR long cog 'cog flag/id long long long long long long long long long rx_head rx_tail tx_head tx_tail rx_pin tx_pin rxtx_mode bit_ticks buffer_ptr '9 contiguous longs byte byte rx_buffer[64] tx_buffer[16] 'transmit and receive buffers PUB start(rxpin, txpin, mode, baudrate) : okay '' Start serial driver - starts a cog '' returns false if no cog available '' '' mode bit 0 = invert rx '' mode bit 1 = invert tx '' mode bit 2 = open-drain/source tx '' mode bit 3 = ignore tx echo on rx stop longfill(@rx_head, 0, 4) longmove(@rx_pin, @rxpin, 3) bit_ticks := clkfreq / baudrate buffer_ptr := @rx_buffer okay := cog := cognew(@entry, @rx_head) + 1 PUB stop '' Stop serial driver - frees a cog if cog cogstop(cog~ - 1) longfill(@rx_head, 0, 9) PUB getCogID : result return cog -1 PUB rxflush '' Flush receive buffer repeat while rxcheck => 0 PUB rxcheck : rxbyte '' Check if byte received (never waits) '' returns -1 if no byte received, $00..$FF if byte rxbyte-if rx_tail <> rx_head rxbyte := rx_buffer[rx_tail] rx_tail := (rx_tail + 1) & $3F PUB rxtime(ms) : rxbyte | t '' Wait ms milliseconds for a byte to be received '' returns -1 if no byte received, $00..$FF if byte t := cnt repeat until (rxbyte := rxcheck) => 0 or (cnt - t) / (clkfreq / 1000) > ms 114 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 PUB rx : rxbyte '' Receive byte (may wait for byte) '' returns $00..$FF repeat while (rxbyte := rxcheck) < 0 PUB tx(txbyte) '' Send byte (may wait for room in buffer) repeat until (tx_tail <> (tx_head + 1) & $F) tx_buffer[tx_head] := txbyte tx_head := (tx_head + 1) & $F if rxtx_mode & %1000 rx PUB str(stringptr) '' Send string repeat strsize(stringptr) tx(byte[stringptr++]) PUB dec(value) | i '' Print a decimal number if value < 0 -value tx("-") i := 1_000_000_000 repeat 10 if value => i tx(value / i + "0") value //= i result~~ elseif result or i == 1 tx("0") i /= 10 PUB hex(value, digits) '' Print a hexadecimal number value <<= (8 - digits) << 2 repeat digits tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F")) PUB bin(value, digits) '' Print a binary number value <<= 32 - digits repeat digits tx((value <-= 1) & 1 + "0") DAT '*********************************** '* Assembly language serial driver * '*********************************** org ' ' ' Entry ' entry mov add t1,par t1,#4 << 2 'get structure address 'skip past heads and tails rdlong mov shl t2,t1 rxmask,#1 rxmask,t2 'get rx_pin 115 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 urn 178 179 180 181 182 183 184 185 186 187 188 189 190 urn 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 add rdlong mov shl t1,#4 t2,t1 txmask,#1 txmask,t2 'get tx_pin add rdlong t1,#4 rxtxmode,t1 'get rxtx_mode add rdlong t1,#4 bitticks,t1 'get bit_ticks add rdlong mov 'add add t1,#4 rxbuff,t1 txbuff,rxbuff txbuff,#16 txbuff,#64 'get buffer_ptr test test or or rxtxmode,#%100 rxtxmode,#%010 outa,txmask dira,txmask mov txcode,#transmit 'initialize ping-pong multitasking jmpret rxcode,txcode 'run a chunk of transmit code, then ret test test jmp rxtxmode,#%001 rxmask,ina #receive mov mov shr add rxbits,#9 rxcnt,bitticks rxcnt,#1 rxcnt,cnt 'ready to receive byte :bit add rxcnt,bitticks 'ready next bit period :wait jmpret rxcode,txcode 'run a chuck of transmit code, then ret mov sub cmps jmp t1,rxcnt t1,cnt t1,#0 #:wait 'check if bit receive period done test rcr djnz rxmask,ina rxdata,#1 rxbits,#:bit shr and test xor rxdata,#32-9 rxdata,#$FF rxtxmode,#%001 rxdata,#$FF rdlong add wrbyte sub add 'and and wrlong t2,par 'save received byte and inc head t2,rxbuff rxdata,t2 t2,rxbuff t2,#1 t2,#$F t2,#$3F ' big buffers t2,par jmp #receive 'byte done, receive next byte jmpret txcode,rxcode 'run a chunk of receive code, then retu if_z_ne_c if_z ' ' ' Receive ' receive if_z_eq_c if_nc if_nz ' ' ' Transmit ' transmit ' big RX buffer wz wc wz wc 'init tx pin according to mode 'wait for start bit on rx pin wc wc 'receive bit on rx pin 'justify and trim received byte wz 'if rx inverted, invert byte 116 rn 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 rn 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 if_z :bit if_z_and_c if_z if_nz :wait if_nc mov add rdlong add rdlong cmp jmp t1,par t1,#2 << 2 t2,t1 t1,#1 << 2 t3,t1 t2,t3 #transmit add rdbyte sub add and wrlong t3,txbuff txdata,t3 t3,txbuff t3,#1 t3,#$0F t3,t1 'get byte and inc tail or shl or mov mov txdata,#$100 txdata,#2 txdata,#1 txbits,#11 txcnt,cnt 'ready byte to transmit test test xor shr muxc muxnc add rxtxmode,#%100 rxtxmode,#%010 txdata,#1 txdata,#1 outa,txmask dira,txmask txcnt,bitticks jmpret txcode,rxcode 'run a chunk of receive code, then retu mov sub cmps jmp t1,txcnt t1,cnt t1,#0 #:wait 'check if bit transmit period done djnz txbits,#:bit 'another bit to transmit? 'byte done, transmit next byte jmp #transmit ' ' ' Uninitialized data ' t1 t2 t3 res res res 1 1 1 rxtxmode bitticks res res 1 1 rxmask rxbuff rxdata rxbits rxcnt rxcode res res res res res res 1 1 1 1 1 1 txmask txbuff txdata txbits txcnt txcode res res res res res res 1 1 1 1 1 1 'check for head <> tail wz wz wc 'output bit on tx pin according to mode wc 'ready next cnt wc 1.5.5 Quadrature_Encoder.spin 1 {{ 2 ************************************* 117 3 * Quadrature Encoder v1.0 * 4 * Author: Jeff Martin * 5 * Copyright (c) 2005 Parallax, Inc. * 6 * See end of file for terms of use. * 7 ************************************* 8 }} 9 10 VAR 11 byte Cog 'Cog (ID+1) that is running Update 12 byte TotDelta 'Number of encoders needing deta value support. 13 long Pos 'Address of position buffer 14 15 16 PUB Start(StartPin, NumEnc, NumDelta, PosAddr): Pass 17 ''Record configuration, clear all encoder positions and launch a continuous encoderreading cog. 18 ''PARAMETERS: StartPin = (0..63) 1st pin of encoder 1. 2nd pin of encoder 1 is StartPin+1. 19 '' Additional pins for other encoders are contiguous starting with Star tPin+2 but MUST NOT cross port boundry (31). 20 '' NumEnc = Number of encoders (1..16) to monitor. 21 '' NumDelta = Number of encoders (0..16) needing delta value support (can be less than NumEnc). 22 '' PosAddr = Address of a buffer of longs where each encoder's position (and deta position, if any) is to be stored. 23 ''RETURNS: True if successful, False otherwise. 24 25 Pin := StartPin 26 TotEnc := NumEnc 27 TotDelta := NumDelta 28 Pos := PosAddr 29 Stop 30 longfill(Pos, 0, TotEnc+TotDelta) 31 Pass := (Cog := cognew(@Update, Pos) + 1) > 0 32 33 34 PUB Stop 35 ''Stop the encoder-reading cog, if there is one. 36 37 if Cog > 0 38 cogstop(Cog-1) 39 40 41 PUB ReadDelta(EncID): DeltaPos 42 ''Read delta position (relative position value since last time read) of EncID. 43 44 DeltaPos := 0 + -(EncID < TotDelta) * long[Pos][TotEnc+EncID] + (long[Pos][TotEnc+EncID] := long[Pos][EncID]) 45 46 47 48 '************************************ 49 '* Encoder Reading Assembly Routine * 50 '************************************ 51 52 DAT 53 'Read all encoders and update encoder positions in main memory. 54 'See "Theory of Operation," below, for operational explanation. 55 'Cycle Calculation Equation: 56 ' Terms: SU = :Sample to :Update. UTI = :UpdatePos through :IPos. MMW = Main Memory Wr ite. 57 ' AMMN = After MMW to :Next. NU = :Next to :UpdatePos. SH = Resync to Hub. NS = :Next to :Sample. 58 ' Equation: SU + UTI + MMW + (AMMN + NU + UTI + SH + MMW) * (TotEnc-1) + AMMN + NS 59 ' = 92 + 16 + 8 + ( 16 + 4 + 16 + 6 + 8 ) * (TotEnc-1) + 16 + 12 60 ' = 144 + 50*(TotEnc-1) 61 62 org 0 63 64 Update 65 test muxc Pin, #$20 :PinSrc, #%1 wc 'Test for upper or lower port 'Adjust :PinSrc instruction f 118 or proper port 66 mov IPosAddr, #IntPos osition values 67 movd :IClear, IPosAddr ter 68 mov Idx, TotEnc 69 :IClear mov 0, #0 70 add IPosAddr, #1 71 movd :IClear, IPosAddr 72 djnz Idx, #:IClear 73 74 mov St2, ina pins 75 shr St2, Pin 76 :Sample mov IPosAddr, #IntPos r addresses 77 movd :IPos+0, IPosAddr 78 movd :IPos+1, IPosAddr 79 mov MPosAddr, PAR 80 mov St1, St2 bit signed offsets (St1 = B1:A1) 81 mov T1, St2 1 = B1:A1 82 shl T1, #1 1 = A1:x 83 :PinSrc mov St2, inb t2 = B2:A2 left shifted by first encoder offset) 84 shr St2, Pin t2 = B2:A2) 85 xor St1, St2 B1^B2:A1^A2 86 xor T1, St2 A1^B2:x 87 and T1, BMask A1^B2:0 88 or T1, AMask A1^B2:1 89 mov T2, St1 B1^B2:A1^A2 90 and T2, AMask 0:A1^A2 91 and St1, BMask B1^B2:0 92 shr St1, #1 0:B1^B2 93 xor T2, St1 0:A1^A2^B1^B2 94 mov St1, T2 0:A1^B2^B1^A2 95 shl St1, #1 2^B1^A2:0 96 or St1, T2 2^B1^A2:A1^B2^B1^A2 97 and St1, T1 2&A1^B2:A1^B2^B1^A2 98 mov Idx, TotEnc 99 :UpdatePos ror St1, #2 31:30 100 mov Diff, St1 bit signed Diff 101 sar Diff, #30 102 :IPos add 0, Diff e 103 wrlong 0, MPosAddr emory 104 add IPosAddr, #1 ddresses 105 movd :IPos+0, IPosAddr 106 movd :IPos+1, IPosAddr 107 add MPosAddr, #4 108 :Next djnz Idx, #:UpdatePos 109 jmp #:Sample 110 'Clear all internal encoder p ' set starting internal poin ' ' ' for all encoders... clear internal memory increment pointer ' loop for each encoder 'Take first sample of encoder 'Reset encoder position buffe 'Calc 2' T ' T ' Sample encoders (S ' Adj for first encoder (S ' St1 = ' T1 = ' T1 = ' T1 = ' T2 = ' T2 = ' St1 = ' St1 = ' T2 = ' St1 = ' St1 = A1^B ' St1 = A1^B ' St1 = A1^B2^B1^A 'For all encoders... 'Rotate current bit pair into 'Convert 2-bit signed to 32'Add to encoder position valu 'Write new position to main m 'Increment encoder position a 'Loop for each encoder 'Loop forever 119 111 'Define Encoder Reading Cog's constants/variables 112 113 AMask long $55555555 'A bit mask 114 BMask long $AAAAAAAA 'B bit mask 115 MSB long $80000000 'MSB mask for current bit pai r 116 117 Pin long 0 'First pin connected to first encoder 118 TotEnc long 0 'Total number of encoders 119 120 Idx res 1 'Encoder index 121 St1 res 1 'Previous state 122 St2 res 1 'Current state 123 T1 res 1 'Temp 1 124 T2 res 1 'Temp 2 125 Diff res 1 'Difference, ie: -1, 0 or +1 126 IPosAddr res 1 'Address of current encoder p osition counter (Internal Memory) 127 MPosAddr res 1 'Address of current encoder p osition counter (Main Memory) 128 IntPos res 16 'Internal encoder position co unter buffer 129 130 131 132 {{ 133 ************************** 134 * FUNCTIONAL DESCRIPTION * 135 ************************** 136 137 Reads 1 to 16 two-bit gray-code quadrature encoders and provides 32bit absolute position values for each and optionally provides delta position support 138 (value since last read) for up to 16 encoders. See "Required Cycles and Maximum RPM" below f or speed boundary calculations. 139 140 Connect each encoder to two contiguous I/O pins (multiple encoders must be connected to a con tiguous block of pins). If delta position support is 141 required, those encoders must be at the start of the group, followed by any encoders not requ iring delta position support. 142 143 To use this object: 144 1) Create a position buffer (array of longs). The position buffer MUST contain NumEnc + Nu mDelta longs. The first NumEnc longs of the position buffer 145 will always contain readonly, absolute positions for the respective encoders. The remaining NumDelta longs of the positi on buffer will be "last 146 absolute read" storage for providing delta position support (if used) and should be igno red (use ReadDelta() method instead). 147 2) Call Start() passing in the starting pin number, number of encoders, number needing delt a support and the address of the position buffer. Start() will 148 configure and start an encoder reader in a separate cog; which runs continuously until S top is called. 149 3) Read position buffer (first NumEnc values) to obtain an absolute 32bit position value for each encoder. Each long (32-bit position counter) within 150 the position buffer is updated automatically by the encoder reader cog. 151 4) For any encoders requiring delta position support, call ReadDelta(); you must have first sized the position buffer and configured Start() appropriately 152 for this feature. 153 154 Example Code: 155 156 OBJ 157 Encoder : "Quadrature Encoder" 158 159 VAR 160 long Pos[3] 'Create buffer for two encoders (plus room for delta position support of 1st encoder) 161 162 PUB Init 163 Encoder.Start(8, 2, 1, @Pos) 'Start continuous twoencoder reader (encoders connected to pins 8 - 11) 164 120 165 PUB Main 166 repeat 167 <read Pos[0] or Pos[1] here> 'Read each encoder's absolute position 168 <variable> := Encoder.ReadDelta(0) 'Read 1st encoder's delta position (value since last read) 169 170 ________________________________ 171 REQUIRED CYCLES AND MAXIMUM RPM: 172 173 Encoder Reading Cog requires 144 + 50*(TotEnc1) cycles per sample. That is: 144 for 1 encoder, 194 for 2 encoders, 894 for 16 encoders. 174 175 Conservative Maximum RPM of Highest Resolution Encoder = XINFreq * PLLMultiplier / EncReaderC ogCycles / 2 / MaxEncPulsesPerRevolution * 60 176 177 Example 1: Using a 4 MHz crystal, 8x internal multiplier, 16 encoders where the highest resol ution encoders is 1024 pulses per revolution: 178 Max RPM = 4,000,000 * 8 / 894 / 2 / 1024 * 60 = 1,048 RPM 179 180 Example 2: Using same example above, but with only 2 encoders of 128 pulses per revolution: 181 Max RPM = 4,000,000 * 8 / 194 / 2 / 128 * 60 = 38,659 RPM 182 }} 183 184 185 { 186 ____________________ 187 THEORY OF OPERATION: 188 Column 1 of the following truth table illustrates 2bit, gray code quadrature encoder output (encoder pins A and B) and their possible transitions (a ssuming 189 we're sampling fast enough). A1 is the previous value of pin A, A2 is the current value of p in A, etc. '->' means 'transition to'. The four double-step 190 transition possibilities are not shown here because we won't ever see them if we're sampling fast enough and, secondly, it is impossible to tell direction 191 if a transition is missed anyway. 192 193 Column 2 shows each of the 2bit results of cross XOR'ing the bits in the previous and current values. Because of the encoder 's gray code output, when 194 there is an actual transition, A1^B2 (msb of column 2) yields the direction (0 = clockwise, 1 = counter-clockwise). When A1^B2 is paired with B1^A2, the 195 resulting 2bit value gives more transition detail (00 or 11 if no transition, 01 if clockwise, 10 if counter -clockwise). 196 197 Columns 3 and 4 show the results of further XORs and one AND operation. The result is a conv enient set of 2-bit signed values: 0 if no transition, +1 if 198 clockwise, and -1 and if counter-clockwise. 199 200 This object's Update routine performs the sampling (column 1) and logical operations (colum 3 ) of up to 16 2-bit pairs in one operation, then adds the 201 resulting offset (-1, 0 or +1) to each position counter, iteratively. 202 203 1 | 2 | 3 | 4 | 5 204 -------------|-------------|----------------------|----------------|----------205 | | A1^B2^B1^A2&(A1^B2): | 2-bit sign | 206 B1A1 -> B2A2 | A1^B2:B1^A2 | A1^B2^B1^A2 | extended value | Diagnosis 207 -------------|-------------|----------------------|----------------|----------208 00 -> 00 | 00 | 00 | +0 | No 209 01 -> 01 | 11 | 00 | +0 | Movement 210 11 -> 11 | 00 | 00 | +0 | 211 10 -> 10 | 11 | 00 | +0 | 212 -------------|-------------|----------------------|----------------|----------213 00 -> 01 | 01 | 01 | +1 | Clockwise 214 01 -> 11 | 01 | 01 | +1 | 215 11 -> 10 | 01 | 01 | +1 | 216 10 -> 00 | 01 | 01 | +1 | 217 -------------|-------------|----------------------|----------------|----------218 00 -> 10 | 10 | 11 | -1 | Counter219 10 -> 11 | 10 | 11 | -1 | Clockwise 220 11 -> 01 | 10 | 11 | -1 | 221 01 -> 00 | 10 | 11 | -1 | 222 } 121 223 224 {{ 225 ┌────────────────────────────────────────────────────────────────────────────── ────────────────────────────────────────────────┐ 226 │ TERMS OF USE: MIT License │ 227 ├────────────────────────────────────────────────────────────────────────────── ────────────────────────────────────────────────┤ 228 │Permission is hereby granted, free of charge, to any person obtaining a copy of this softwar e and associated documentation │ 229 │files (the "Software"), to deal in the Software without restriction, including without limit ation the rights to use, copy, │ 230 │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to p ermit persons to whom the Software│ 231 │is furnished to do so, subject to the following conditions: │ 232 │ │ 233 │The above copyright notice and this permission notice shall be included in all copies or sub stantial portions of the Software.│ 234 │ │ 235 │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDIN G BUT NOT LIMITED TO THE │ 236 │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO E VENT SHALL THE AUTHORS OR │ 237 │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ 238 │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ 239 └────────────────────────────────────────────────────────────────────────────── ────────────────────────────────────────────────┘ 240 }} 1.5.6 web4robot_lcd_001.spin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 '*********************************************** '** Controlls the web4robot I2C LCD '** Jacob Dilles <[email protected]> 6/8/2012 '** Version 1.00 '*********************************************** CON lcd2 = $4c << 1 | 0 ' 7 bit address ' Initial values LCD_BRIGHTNESS = 100 ' 0 - 250 LCD_CONTRAST = 80 ' 0 - 100 OBJ i2cObject : "basic_i2c_driver" VAR byte _contrast byte _brightness PUB Start '' set initial values _contrast := LCD_CONTRAST _brightness := LCD_BRIGHTNESS ' set initial state (on) clear on 'power on contrast(_contrast) PUB brightness(br) '' Set the brightness value 0-250 i2cObject.start i2cObject.write(lcd2) 122 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 i2cObject.write($fe) i2cObject.write($03) i2cObject.write(br) i2cObject.stop PUB contrast(cn) '' Set the contrast value 0 - 100 i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($04) i2cObject.write(cn) i2cObject.stop PUB pos(x, y) '' Set the cursor position. X = 0..19, Y = 0..3 i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($0C) i2cObject.write(x) i2cObject.write(y) i2cObject.stop PUB line(ln) '' Move to the start of the given line pos(0,ln) PUB home '' Move the cursor to the home position i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($0D) i2cObject.stop PUB off '' Turn the LCD off (does not affect backlight) i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($0B) i2cObject.stop brightness(0) PUB on '' Turn the LCD on i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($0A) i2cObject.stop brightness(_brightness) PUB underline(en) '' Turn on or off the cursor underline i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) if en i2cObject.write($0E) else i2cObject.write($0F) i2cObject.stop PUB left '' Move the cursor left one position i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($10) i2cObject.stop 123 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 PUB right '' Move the cursor right one position i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($11) i2cObject.stop PUB space i2cObject.start i2cObject.write(lcd2) i2cObject.write($20) i2cObject.stop PUB blink(en) '' Turn on or off the cursor blink i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) if en i2cObject.write($12) else i2cObject.write($13) i2cObject.stop PUB clear '' Move the cursor left one position i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($14) i2cObject.stop PUB charmap(charaddr, map) '' map a custom character '' charaddr = 0 .. 7, custom character '' map = a long (8 bytes) with character data i2cObject.start i2cObject.write(lcd2) i2cObject.write($fe) i2cObject.write($1A) i2cObject.write(charaddr) repeat 8 i2cObject.write( byte[map++] ) i2cObject.stop PUB out(b) '' write a single byte i2cObject.start i2cObject.write(lcd2) i2cObject.write(b) i2cObject.stop PUB str(stringloc) '' Write an ASC-II string: writeString(@stringloc) or writeString("hi there") i2cObject.writeString(lcd2, stringloc) PUB writeBytes(byteloc, n) i2cObject.writeBytes(lcd2, byteloc, n) PUB bin(value, nbits) bin2str(value, @msg, nbits) writeBytes(@msg, nbits) PUB hex(value, nchars) hex2str(value, @msg, nchars) writeBytes(@msg, nchars) PRI bin2str(val, strloc,n) '' Buffer a value as binary val <<= 32-n repeat n byte[strloc++]:=((val <-= 1) & 1 + "0") 124 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 pri hex2str(value, strloc, digits) '' Print a hexadecimal number value <<= (8 - digits) << 2 repeat digits byte[strloc++] := lookupz((value <-= 4) & $F : "0".."9", "A".."F") DAT '------------ LCD comand strings -----------lcd_clear byte $fe, $14, 0 lcd_pow_on byte $fe, $0A, 0 lcd_pow_off byte $fe, $0B, 0 lcd_home byte $fe, $0d, 0 ' ----------------- String Buffer msg byte "0",$00[64] ' stringbuff 1.6 IPM 1.6.1 IPM VGA Spice Simulation (With Parasitics) Version 4 SHEET 1 2692 1212 WIRE 160 -16 160 -32 WIRE 352 0 352 -16 WIRE -544 16 -544 -16 WIRE -496 16 -496 0 WIRE 256 80 256 64 WIRE 1568 80 1536 80 WIRE 1680 80 1680 -32 WIRE 1680 80 1632 80 WIRE -544 96 -544 80 WIRE -496 96 -496 80 WIRE -496 96 -544 96 WIRE 16 96 -16 96 WIRE 160 96 160 48 WIRE 160 96 16 96 WIRE 224 96 160 96 WIRE 1680 96 1680 80 WIRE -624 112 -752 112 WIRE -496 112 -496 96 WIRE -496 112 -544 112 WIRE -448 112 -496 112 WIRE 352 112 352 64 WIRE 352 112 288 112 WIRE 736 112 352 112 WIRE 1680 112 1680 96 WIRE 224 128 176 128 WIRE -752 160 -752 112 WIRE -720 160 -752 160 WIRE -496 160 -496 112 WIRE 256 160 256 144 WIRE -752 176 -752 160 WIRE 144 176 144 160 WIRE 560 176 560 160 WIRE 944 176 944 160 WIRE 1584 208 1520 208 WIRE 1680 208 1680 176 WIRE 1680 208 1648 208 WIRE 1680 224 1680 208 WIRE -496 256 -496 240 WIRE -496 256 -576 256 WIRE -432 256 -496 256 WIRE 16 256 16 96 WIRE 16 256 -32 256 WIRE 48 256 16 256 WIRE 144 256 144 240 WIRE 144 256 128 256 125 WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE 176 256 144 256 304 256 256 256 352 256 304 256 400 256 352 256 448 256 400 256 464 256 448 256 560 256 560 240 560 256 544 256 608 256 560 256 736 256 736 112 736 256 688 256 784 256 736 256 944 256 944 240 944 256 864 256 1024 256 944 256 1136 256 1104 256 1184 256 1136 256 -752 272 -752 240 -576 272 -576 256 -496 272 -496 256 944 272 944 256 304 288 304 256 352 288 352 256 400 288 400 256 1136 288 1136 256 144 320 144 256 176 320 144 320 256 320 256 256 256 320 240 320 1680 320 1680 304 -576 336 -576 320 16 336 16 256 -496 352 -496 336 448 352 448 256 464 352 448 352 560 352 560 256 560 352 528 352 -576 368 -576 336 352 368 352 352 400 368 400 352 -240 384 -272 384 -144 384 -176 384 1136 400 1136 368 1680 432 1680 400 1680 432 1664 432 1760 432 1680 432 1888 432 1840 432 -656 448 -736 448 -592 448 -656 448 -528 448 -592 448 -448 448 -528 448 -384 448 -448 448 -368 448 -384 448 1680 448 1680 432 16 464 -64 384 16 464 16 416 160 464 16 464 256 464 224 464 -736 480 -736 448 -656 496 -656 448 -384 496 -384 448 -288 496 -288 448 16 496 16 464 16 496 -288 496 -656 512 -656 496 -592 512 -592 448 -528 512 -528 448 -448 512 -448 448 16 512 16 496 1680 544 1680 528 -288 608 -288 592 16 608 16 592 16 608 -288 608 126 WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE WIRE -736 640 -736 560 -656 640 -656 576 -656 640 -736 640 -592 640 -592 576 -592 640 -656 640 -528 640 -528 576 -528 640 -592 640 -448 640 -448 576 -448 640 -528 640 -384 640 -384 608 -384 640 -448 640 -368 640 -384 640 -288 640 -288 608 1680 640 1680 624 1744 640 1680 640 1840 640 1808 640 -288 656 -288 640 16 656 16 608 80 656 80 592 80 656 16 656 160 656 80 656 256 656 224 656 1680 656 1680 640 1840 688 1840 640 1840 688 1792 688 1840 704 1840 688 16 720 16 656 -240 736 -272 736 -144 736 -176 736 -64 736 16 656 -736 752 -736 720 144 752 144 720 368 752 368 736 416 752 416 720 192 768 176 768 288 768 256 768 464 768 448 768 560 768 528 768 1680 768 1680 736 1728 768 1680 768 1792 768 1792 688 1680 816 1680 768 16 864 16 800 16 864 -16 864 48 864 16 864 144 864 144 816 144 864 128 864 176 864 176 768 176 864 144 864 192 864 176 864 288 864 288 768 288 864 272 864 336 864 336 816 336 864 288 864 368 864 368 816 368 864 336 864 416 864 416 816 416 864 368 864 448 864 448 768 448 864 416 864 464 864 448 864 560 864 560 768 560 864 544 864 624 864 560 864 736 864 736 816 736 864 704 864 784 864 736 864 944 864 944 848 944 864 864 864 1024 864 944 864 1136 864 1104 864 1216 864 1136 864 944 880 944 864 127 WIRE 560 896 560 864 WIRE 1136 896 1136 864 WIRE 944 960 944 944 WIRE 256 976 256 960 WIRE 560 976 560 960 WIRE 224 992 144 992 WIRE 336 1008 288 1008 WIRE 736 1008 736 864 WIRE 736 1008 336 1008 WIRE 1136 1008 1136 976 WIRE 16 1024 16 864 WIRE 16 1024 -16 1024 WIRE 192 1024 16 1024 WIRE 224 1024 192 1024 WIRE 16 1040 16 1024 WIRE 192 1040 192 1024 WIRE 336 1040 336 1008 WIRE 256 1072 256 1040 WIRE 192 1120 192 1104 WIRE 336 1120 336 1104 FLAG 256 160 vee FLAG 256 64 vcc FLAG 176 128 vcm1 FLAG 1680 -32 vcc FLAG 1184 256 op FLAG 304 368 0 FLAG 1664 432 0 FLAG 1680 816 vee FLAG 256 960 vee FLAG 256 1072 vcc FLAG 144 992 vcm2 FLAG 1216 864 on FLAG 336 736 0 FLAG -720 160 vcm FLAG 944 960 0 FLAG 944 160 0 FLAG 256 656 0 FLAG 256 464 0 FLAG 144 720 0 FLAG 144 160 0 FLAG 1840 704 0 FLAG 1536 80 0 FLAG 1520 208 0 FLAG -752 272 0 FLAG 368 736 0 FLAG 352 368 0 FLAG -432 256 vcm2 FLAG -448 112 vcm1 FLAG -496 352 0 FLAG -496 0 0 FLAG 192 1120 0 FLAG 336 1120 0 FLAG 352 -16 0 FLAG 560 160 0 FLAG 560 976 0 FLAG 160 -32 0 FLAG -576 368 0 FLAG -544 -16 0 FLAG 1136 1008 0 FLAG 1136 400 0 FLAG 1888 432 vcm FLAG -272 736 0 FLAG -272 384 0 FLAG 400 368 0 FLAG 416 720 0 FLAG -736 752 0 SYMBOL current -736 480 R0 WINDOW 123 -100 94 Left 2 WINDOW 39 0 0 Left 2 WINDOW 3 -251 36 Left 2 SYMATTR Value2 AC 1 SYMATTR Value SINE(0 10u 100k) SYMATTR InstName I1 128 SYMBOL res 272 240 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R1 SYMATTR Value 2.000k SYMBOL voltage 1680 304 R0 WINDOW 123 0 0 Left 2 WINDOW 39 24 124 Left 2 SYMATTR InstName V1 SYMATTR Value 2.5 SYMATTR SpiceLine Rser=5 SYMBOL res 560 240 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R2 SYMATTR Value 499 SYMBOL res 320 384 R180 WINDOW 0 36 76 Left 2 WINDOW 3 36 40 Left 2 SYMATTR InstName R3 SYMATTR Value {rs} SYMBOL voltage 1680 432 R0 WINDOW 123 0 0 Left 2 WINDOW 39 24 124 Left 2 SYMATTR InstName V2 SYMATTR Value 2.5 SYMATTR SpiceLine Rser=5 SYMBOL cap 336 288 R0 WINDOW 3 -27 112 Left 2 SYMATTR InstName C1 SYMATTR Value 90.3p SYMBOL cap 528 336 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C3 SYMATTR Value .5p SYMBOL res 288 880 M270 WINDOW 0 32 56 VTop 2 WINDOW 3 0 90 VBottom 2 SYMATTR InstName R5 SYMATTR Value 2.000k SYMBOL res 560 880 M270 WINDOW 0 32 56 VTop 2 WINDOW 3 0 56 VBottom 2 SYMATTR InstName R6 SYMATTR Value 499 SYMBOL res 352 720 M0 WINDOW 0 23 -12 Left 2 WINDOW 3 34 27 Left 2 SYMATTR InstName R7 SYMATTR Value {rs} SYMBOL res 1120 992 M180 WINDOW 0 36 76 Left 2 WINDOW 3 36 40 Left 2 SYMATTR InstName R8 SYMATTR Value 50 SYMBOL cap 352 816 M180 WINDOW 0 24 56 Left 2 WINDOW 3 -10 118 Left 2 SYMATTR InstName C4 SYMATTR Value 90.3p SYMBOL cap 256 784 M270 WINDOW 0 32 32 VTop 2 WINDOW 3 0 32 VBottom 2 SYMATTR InstName C5 SYMATTR Value .5p SYMBOL cap 528 784 M270 WINDOW 0 32 32 VTop 2 WINDOW 3 0 32 VBottom 2 SYMATTR InstName C6 SYMATTR Value .5p SYMBOL Opamps\\LT1886 256 48 R0 SYMATTR InstName U1 129 SYMBOL Opamps\\LT1886 256 1072 M180 SYMATTR InstName U2 SYMBOL cap -608 512 R0 SYMATTR InstName C7 SYMATTR Value 100p SYMBOL res 1856 416 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R10 SYMATTR Value 0.129 SYMBOL cap 928 176 R0 SYMATTR InstName C8 SYMATTR Value 1.44p SYMBOL cap 928 880 R0 SYMATTR InstName C9 SYMATTR Value 2.11p SYMBOL res -272 432 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R9 SYMATTR Value 2 SYMBOL ind 0 704 R0 SYMATTR InstName L1 SYMATTR Value 48n SYMBOL ind 0 320 R0 SYMATTR InstName L2 SYMATTR Value 48n SYMBOL ind 144 240 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L3 SYMATTR Value 15n SYMBOL ind 144 848 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L4 SYMATTR Value 25.85n SYMBOL ind -272 624 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L5 SYMATTR Value 0.48u SYMBOL cap -544 512 R0 SYMATTR InstName C12 SYMATTR Value 168p SYMBOL cap -464 512 R0 SYMATTR InstName C13 SYMATTR Value 60p SYMBOL cap 224 448 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C10 SYMATTR Value 2.69p SYMBOL cap 224 640 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C11 SYMATTR Value 2.69p SYMBOL cap 128 176 R0 WINDOW 3 -39 16 Left 2 SYMATTR InstName C14 SYMATTR Value .96p SYMBOL cap 128 752 R0 WINDOW 0 -49 18 Left 2 WINDOW 3 -43 60 Left 2 SYMATTR InstName C15 SYMATTR Value 1.2p SYMBOL ind 1664 528 R0 WINDOW 3 85 48 Left 2 SYMATTR Value 6.98n SYMATTR InstName L6 SYMBOL ind 1664 640 R0 SYMATTR InstName L7 130 SYMATTR Value 6.96n SYMBOL cap 1808 624 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C16 SYMATTR Value 2.2u SYMBOL cap 1792 752 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C18 SYMATTR Value 2.2u SYMBOL ind 1664 208 R0 WINDOW 0 -46 80 Left 2 SYMATTR InstName L8 SYMATTR Value 4.23n SYMBOL ind 1664 80 R0 SYMATTR InstName L9 SYMATTR Value 3.85n SYMBOL cap 1648 192 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C19 SYMATTR Value 2.2u SYMBOL cap 1632 64 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C21 SYMATTR Value 2.2u SYMBOL cap -768 176 R0 WINDOW 0 -56 66 Left 2 SYMATTR InstName C17 SYMATTR Value 1.2p SYMBOL ind -512 144 R0 SYMATTR InstName L10 SYMATTR Value 5.368n SYMBOL cap -512 272 R0 SYMATTR InstName C20 SYMATTR Value .385p SYMBOL cap -512 16 R0 SYMATTR InstName C23 SYMATTR Value .385p SYMBOL ind -528 96 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L11 SYMATTR Value 4.16n SYMBOL cap 176 1040 R0 WINDOW 3 -23 59 Left 2 SYMATTR Value .337p SYMATTR InstName C24 SYMBOL cap 320 1040 R0 SYMATTR InstName C26 SYMATTR Value .337p SYMBOL ind 720 848 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L12 SYMATTR Value 11.82n SYMBOL ind 704 240 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L13 SYMATTR Value 22.24n SYMBOL ind 880 848 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L14 SYMATTR Value 36.94n SYMBOL ind 880 240 R90 WINDOW 0 5 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName L15 SYMATTR Value 24.04n 131 SYMBOL cap 336 0 R0 SYMATTR InstName C27 SYMATTR Value .337p SYMBOL cap 544 176 R0 SYMATTR InstName C28 SYMATTR Value 1.34p SYMBOL cap 544 896 R0 SYMATTR InstName C29 SYMATTR Value .77p SYMBOL cap 144 -16 R0 SYMATTR InstName C30 SYMATTR Value .337p SYMBOL cap -592 272 R0 SYMATTR InstName C25 SYMATTR Value .337p SYMBOL cap -560 16 R0 WINDOW 0 -52 4 Left 2 SYMATTR InstName C31 SYMATTR Value .337p SYMBOL res 1120 848 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R11 SYMATTR Value 50 SYMBOL res 1120 384 M180 WINDOW 0 36 76 Left 2 WINDOW 3 36 40 Left 2 SYMATTR InstName R12 SYMATTR Value 50 SYMBOL res 1120 240 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R13 SYMATTR Value 50 SYMBOL res -672 480 R0 SYMATTR InstName R4 SYMATTR Value 100k SYMBOL res -48 720 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R15 SYMATTR Value {Rc} SYMBOL cap -176 720 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C32 SYMATTR Value {Cc} SYMBOL res -48 368 R90 WINDOW 0 0 56 VBottom 2 WINDOW 3 32 56 VTop 2 SYMATTR InstName R16 SYMATTR Value {Rc} SYMBOL cap -176 368 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C33 SYMATTR Value {Cc} SYMATTR SpiceLine Rser=10m Lser=10p SYMBOL cap 384 288 R0 SYMATTR InstName C2 SYMATTR Value {Ct} SYMBOL cap 400 752 R0 SYMATTR InstName C22 SYMATTR Value {Ct} SYMBOL cap 240 304 R90 WINDOW 0 0 32 VBottom 2 WINDOW 3 32 32 VTop 2 SYMATTR InstName C34 SYMATTR Value .5p SYMBOL res 64 496 R0 SYMATTR InstName R14 SYMATTR Value 100k SYMBOL cap -752 656 R0 132 SYMATTR InstName C35 SYMATTR Value 10n TEXT 960 -72 Left 2 !.tran 1m startup TEXT -472 -224 Left 2 ;.step param rs list 1e9 15999.998976 31.936128 15.984016 10.659560 7.996002 6.397441 5.331556 4.570123 3.999000 3.554766 3.199360 2.908562 2.666222 2.461160 2.285388 2.133049 TEXT -192 -48 Left 2 ;.param rs 5.39 TEXT -448 712 Left 2 ;rg-58 TEXT -584 688 Left 2 ;rg-58 TEXT -688 672 Left 2 ;pd TEXT -496 680 Left 2 ;con TEXT 1808 488 Left 2 ;header TEXT -568 176 Left 2 ;trace TEXT 624 192 Left 2 ;trace TEXT 616 920 Left 2 ;trace TEXT 280 32 Left 2 ;pad TEXT 856 208 Left 2 ;trace TEXT 864 896 Left 2 ;trace TEXT 104 0 Left 2 ;pad TEXT -632 304 Left 2 ;pad TEXT -640 768 Left 2 ;PULSE(0 10u 100n 10n 10n 20n) TEXT -200 -152 Left 2 !.param Rc 6.8 TEXT -192 -120 Left 2 !.param Cc 20n TEXT 160 -152 Left 2 ;.step param Cc list 10n 12n 14n 16n 18n 20n TEXT 176 -184 Left 2 ;.step param Rc list 8 10 12 14 16 18 TEXT 80 224 Left 2 ;trace TEXT 120 -120 Left 2 !.param Ct 1p TEXT 496 440 Left 2 ;Fix is to add 2x compensation RCs: Cc=20n and Rc=6.8 from inputs to ground TEXT 496 480 Left 2 ;This decreases frequency response, and moves the peak to around 200khz (vs 10 MHz) TEXT 512 512 Left 2 ;but should make us unconditionally stable TEXT -208 0 Left 2 !.param rs 15 133