Appendix C - Code Listing

133
1 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 UIME – 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

Transcript of Appendix C - Code Listing

Page 1: Appendix C - Code Listing

  1  

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  

 

Page 2: Appendix C - Code Listing

  2  

1.1 DCM – Spartan 6 FPGA: HDL Code

1.1.1 adg714s3w.vhdl

1 ---------------------------------------------------------------------------- 2 -- Company: Team Spectrum 3 -- Engineer: Jacob Dilles 4 -- 5 -- Create Date: 13:02:12 11/21/2012 6 -- Design Name: ADG714 Serial Protocol Adapter 7 ---------------------------------------------------------------------------- 8 library IEEE; 9 use IEEE.STD_LOGIC_1164.ALL; 10 11 entity adg714s3w is 12 Port ( clk : in STD_LOGIC; 13 reset : in STD_LOGIC; 14 reg_data : in STD_LOGIC_VECTOR (7 downto 0); 15 adg_sclk : out STD_LOGIC; 16 adg_sync : out STD_LOGIC; 17 adg_dout : out STD_LOGIC; 18 adg_reset : out STD_LOGIC); 19 end adg714s3w; 20 21 architecture Behavioral of adg714s3w is 22 -- signal holds the last data to check for a change 23 signal last_reg_data : STD_LOGIC_VECTOR (7 downto 0); 24 25 -- triggers latch and reset of different flag 26 signal latch_reg_data : STD_LOGIC; 27 28 signal last_is_different : STD_LOGIC; 29 signal shifting, shifting_done : STD_LOGIC; 30 -- internal signals 31 signal adg_reset_flag : STD_LOGIC; 32 33 constant sreg_shift_ctl : STD_LOGIC_VECTOR(0 to 63) := 34 X"000000000000FFFF"; 35 constant sclk_shift_reg : STD_LOGIC_VECTOR(0 to 63) := 36 X"AAAAAAAAAAAAAAAA";-- X"AAAA" & "10 10 10 10 10 10 10 10" & X"AAAA"; 37 constant sync_shift_reg : STD_LOGIC_VECTOR(0 to 63) := 38 X"FFFF0000FFFFFFFF";-- X"FFFF" & "00 00 00 00 00 00 00 00" & X"FFFF"; 39 signal dout_shift_reg : STD_LOGIC_VECTOR(0 to 63); 40 -- X"0000" & d7 d6 d5 d4 d3 d2 d1 d0 & X"0000"; 41 42 alias d : STD_LOGIC_VECTOR(7 downto 0) is reg_data; 43 44 -- counters 45 constant RESET_NCOUNTS : INTEGER := 7 ;--2**15 - 1; 46 47 48 signal shift_reg_cnt : INTEGER RANGE 0 to 63; 49 50 begin 51 52 mux_proc: process(clk) is 53 begin 54 if rising_edge(clk) then 55 shifting_done <= sreg_shift_ctl(shift_reg_cnt); 56 adg_sync <= sync_shift_reg(shift_reg_cnt); 57 adg_dout <= dout_shift_reg(shift_reg_cnt); 58 adg_sclk <= sclk_shift_reg(shift_reg_cnt); 59 adg_reset <= adg_reset_flag; 60 end if; 61 end process; 62 63 64 -- The actual shifted out data 65 shift_reg_proc: process(clk, reset) is 66 begin 67 if rising_edge(clk) then

Page 3: Appendix C - Code Listing

  3  

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;

Page 4: Appendix C - Code Listing

  4  

141 adg_reset_flag <= '0'; -- active low 142 end if; 143 end if; 144 end if; 145 end process reset_proc; 146 147 148 149 -- 150 -- Monitor the register for change 151 -- 152 change_flag: process (clk, reset) is 153 begin 154 if rising_edge(clk) then 155 if reset = '1' then 156 last_reg_data <= (others => '0'); 157 last_is_different <= '0'; 158 else 159 -- change value 160 last_reg_data <= reg_data; 161 162 if last_reg_data = reg_data then 163 last_is_different <= '0'; 164 else 165 last_is_different <= '1'; 166 end if; 167 end if; 168 end if; 169 end process change_flag; 170 171 end Behavioral;

1.1.2 clockmanager.vhdl

1 -- file: Clockmanager.vhd 2 -- 3 -- (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved. 4 -- 5 -- This file contains confidential and proprietary information 6 -- of Xilinx, Inc. and is protected under U.S. and 7 -- international copyright and other intellectual property 8 -- laws. 9 -- 10 -- DISCLAIMER 11 -- This disclaimer is not a license and does not grant any 12 -- rights to the materials distributed herewith. Except as 13 -- otherwise provided in a valid license issued to you by 14 -- Xilinx, and to the maximum extent permitted by applicable 15 -- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 -- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 -- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 -- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 -- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 -- (2) Xilinx shall not be liable (whether in contract or tort, 21 -- including negligence, or under any other theory of 22 -- liability) for any loss or damage of any kind or nature 23 -- related to, arising under or in connection with these 24 -- materials, including for any direct, or any indirect, 25 -- special, incidental, or consequential loss or damage 26 -- (including loss of data, profits, goodwill, or any type of 27 -- loss or damage suffered as a result of any action brought 28 -- by a third party) even if such damage or loss was 29 -- reasonably foreseeable or Xilinx had been advised of the 30 -- possibility of the same. 31 -- 32 -- CRITICAL APPLICATIONS 33 -- Xilinx products are not designed or intended to be fail- 34 -- safe, or for use in any application requiring fail-safe 35 -- performance, such as life-support or safety devices or

Page 5: Appendix C - Code Listing

  5  

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,{component_name=Clockmanager,use_phase_alignment=false,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,feedback_source=FDBK_AUTO,primtype_sel=PLL_BASE,num_out_clk=3,clkin1_period=10.0,clkin2_period=10.0,use_power_down=false,use_reset=true,use_locked=true,use_inclk_stopped=false,use_status=false,use_freeze=false,use_clk_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

Page 6: Appendix C - Code Listing

  6  

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);

Page 7: Appendix C - Code Listing

  7  

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 (active-low) when reading from FX2 29 fx2GotData_in : in std_logic; -- asserted (active-high) when FX2 has data for us 30 fx2Write_out : out std_logic; -- asserted (active-low) when writing to FX2 31 fx2GotRoom_in : in std_logic; -- asserted (active-high) when FX2 has room for more data from us 32 fx2PktEnd_out : out std_logic; -- asserted (active-low) 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 therefore 47 -- of the opposite sense to the host's read and write. So host reads are fulfilled in the S_WRITE state, and 48 -- vice-versa. Apologies for the confusion.

Page 8: Appendix C - Code Listing

  8  

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;

Page 9: Appendix C - Code Listing

  9  

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

Page 10: Appendix C - Code Listing

  10  

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 library IEEE; 2 use IEEE.STD_LOGIC_1164.ALL; 3 use IEEE.STD_LOGIC_UNSIGNED.ALL; 4 5 entity dac_count is 6 PORT( 7 scan_pos : in STD_LOGIC_VECTOR(31 downto 0); 8 dac_clk : in STD_LOGIC; 9 dac_out : out STD_LOGIC; 10 wrld_clk : out STD_LOGIC 11 ); 12 end dac_count; 13 14 architecture Behavioral of dac_count is 15 16 signal count : STD_LOGIC_VECTOR(4 downto 0); 17 signal shft_reg : STD_LOGIC_VECTOR(31 downto 0); 18 19 begin 20 21 PROCESS(dac_clk) 22 begin 23 if(rising_edge(dac_clk))then 24 dac_out <= shft_reg(conv_integer(count)); 25 count <= count + 1; 26 if(count = "00000")then 27 shft_reg <= x"00" & scan_pos(31 downto 8); 28 end if; 29 end if; 30 end process; 31 wrld_clk <= count(4); 32 33 end Behavioral; 34

Page 11: Appendix C - Code Listing

  11  

1.1.5 emulator.vhdl

1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 5 entity analog_interface is 6 port ( 7 dac_clk : in std_logic; 8 adc_clk : in std_logic; 9 -- data signals 10 dac_data: in std_logic_vector(23 downto 0); -- 24 bit from DCM 11 adc_data: out std_logic_vector(15 downto 0); -- 16 bit to DCM 12 -- status signals 13 control: in std_logic_vector(7 downto 0); -- control register (TBD) 14 status : out std_logic_vector(7 downto 0) -- status register (TBD) 15 ); 16 end entity; 17 18 architecture black_box_emulator of analog_interface is 19 20 21 type bram_rom is array(natural range <>) of std_logic_vector(15 downto 0); 22 23 24 -- this should fit in 4x 16x1K BRAMs (i.e. in the S3E-100) 25 constant EMULATOR_DATA : bram_rom(0 to 4095) := ( 26 X"0000", X"0131", X"0126", X"0086", X"0089", X"0412", X"05f1", X"0135", 27 X"02b8", X"03a0", X"0305", X"029a", X"0411", X"02f1", X"0533", X"0292", 28 X"041b", X"0334", X"0023", X"04ac", X"0078", X"0284", X"0213", X"0466", 29 X"0504", X"00a4", X"02b4", X"02f0", X"0382", X"0123", X"0373", X"01f2", 30 X"038b", X"056d", X"01f1", X"0391", X"0208", X"03c8", X"0236", X"0256", 31 X"0196", X"0408", X"01a5", X"02c4", X"0365", X"0319", X"0392", X"02b7", 32 X"010c", X"01ec", X"05da", X"05fd", X"0130", X"0174", X"03bd", X"040a", 33 X"02a3", X"048c", X"02b1", X"019d", X"059f", X"035d", X"0186", X"0208", 34 X"028e", X"0414", X"01a8", X"0050", X"0497", X"035e", X"0263", X"0041", 35 X"01c1", X"048e", X"0248", X"006e", X"021f", X"01f1", X"037a", X"009a", 36 X"0352", X"02e2", X"0322", X"004d", X"02f9", X"048a", X"004b", X"029b", 37 X"0374", X"00f8", X"0380", X"04ac", X"0227", X"04c2", X"05e1", X"01c1", 38 X"0487", X"016c", X"03dd", X"01af", X"04e3", X"03c8", X"00c7", X"01d8", 39 X"04a6", X"0387", X"00a8", X"01c4", X"0171", X"0309", X"05df", X"0267", 40 X"00ef", X"024d", X"002e", X"0252", X"01c9", X"059a", X"035e", X"0279", 41 X"0203", X"027e", X"0287", X"0394", X"0405", X"0277", X"0377", X"03f7", 42 X"0295", X"02e9", X"0262", X"0510", X"00c9", X"0138", X"012e", X"02d6", 43 X"0548", X"0260", X"036b", X"055b", X"0013", X"0164", X"01f9", X"035d", 44 X"0599", X"04eb", X"028b", X"00c4", X"01a8", X"03b1", X"0285", X"01be", 45 X"021c", X"023a", X"00f4", X"05ae", X"0233", X"0323", X"0073", X"03ad", 46 X"022c", X"012d", X"0679", X"0170", X"04df", X"0385", X"02e2", X"02c1", 47 X"01fe", X"03b6", X"0335", X"0046", X"02ca", X"02f3", X"0145", X"004e", 48 X"042d", X"00c3", X"028a", X"02e7", X"03c8", X"025f", X"0207", X"0213", 49 X"03fa", X"0566", X"0071", X"02e9", X"0501", X"02bb", X"0210", X"0381", 50 X"025a", X"004d", X"0352", X"0362", X"01b6", X"0316", X"000b", X"0250", 51 X"062c", X"0213", X"040e", X"0546", X"02ae", X"0332", X"0295", X"008b", 52 X"00bb", X"02e4", X"0269", X"02a6", X"03e2", X"0006", X"00b2", X"0285", 53 X"02a4", X"03b3", X"039b", X"0357", X"02b3", X"01bb", X"01a6", X"0097", 54 X"01ee", X"025e", X"0085", X"0169", X"01c0", X"0690", X"034e", X"00dc", 55 X"02df", X"0143", X"02e3", X"0475", X"01bd", X"0351", X"0165", X"0507", 56 X"0226", X"0119", X"00f9", X"03b3", X"013f", X"03a0", X"03c0", X"0407", 57 X"0480", X"05ad", X"012f", X"01bf", X"0412", X"0021", X"04e9", X"02c9", 58 X"0292", X"0083", X"05aa", X"02a2", X"02da", X"028f", X"0373", X"0020", 59 X"020f", X"02b3", X"03ba", X"01da", X"0293", X"03cb", X"0016", X"035b", 60 X"00d4", X"0468", X"027e", X"0110", X"024a", X"0398", X"022c", X"03c0", 61 X"03dd", X"0198", X"0456", X"0397", X"00cf", X"0270", X"0310", X"023d", 62 X"0317", X"0162", X"0317", X"000f", X"00fb", X"0147", X"0016", X"0224", 63 X"0472", X"00b1", X"02c8", X"02ec", X"0292", X"027b", X"0495", X"02c0", 64 X"0093", X"04bd", X"02f1", X"01dd", X"0111", X"0203", X"02d7", X"03d3", 65 X"0264", X"0408", X"016f", X"05c8", X"0267", X"02ba", X"020a", X"0521", 66 X"033f", X"02d8", X"037a", X"03c3", X"028c", X"0095", X"02a8", X"0227", 67 X"02ad", X"021f", X"039d", X"050e", X"00c8", X"01fe", X"04b0", X"03eb", 68 X"04f1", X"021a", X"03be", X"028a", X"0622", X"0066", X"0234", X"034d",

Page 12: Appendix C - Code Listing

  12  

69 X"02ee", X"028d", X"0141", X"0265", X"0108", X"0414", X"03fb", X"0326", 70 X"0083", X"0377", X"04b0", X"001b", X"00e7", X"003e", X"02ab", X"033a", 71 X"04d0", X"0423", X"03d8", X"0307", X"01f5", X"0126", X"02c5", X"0533", 72 X"037d", X"0323", X"03b5", X"00f6", X"037a", X"009e", X"0500", X"035d", 73 X"0358", X"0315", X"0353", X"01f8", X"04c1", X"008f", X"0094", X"010c", 74 X"03ab", X"03f7", X"0015", X"018c", X"0369", X"03d0", X"02cb", X"02c2", 75 X"01d9", X"023c", X"0431", X"04ea", X"0196", X"0250", X"03d0", X"05a5", 76 X"0227", X"0264", X"038c", X"030d", X"012d", X"02f1", X"02ed", X"021e", 77 X"0107", X"0284", X"0309", X"0205", X"0291", X"01ec", X"00a8", X"01b8", 78 X"03c7", X"022e", X"02f5", X"035d", X"002b", X"0332", X"04b7", X"02ec", 79 X"0452", X"01a6", X"029a", X"04e7", X"023b", X"033d", X"0215", X"02e5", 80 X"03a2", X"0244", X"0271", X"0442", X"00ba", X"02c3", X"01c7", X"069f", 81 X"0361", X"01e3", X"02b5", X"02dc", X"03dc", X"02f5", X"0262", X"0278", 82 X"01a8", X"00fd", X"0182", X"04fa", X"0279", X"0264", X"023a", X"0529", 83 X"02fa", X"0415", X"03d4", X"01d5", X"0550", X"02f9", X"0375", X"06db", 84 X"038a", X"0226", X"0340", X"01ba", X"044f", X"04ef", X"0374", X"047a", 85 X"053f", X"024f", X"0395", X"024a", X"03be", X"021b", X"00a0", X"0430", 86 X"0410", X"01b6", X"01f9", X"0292", X"022e", X"0214", X"016b", X"0584", 87 X"04f9", X"02bb", X"01be", X"0009", X"049c", X"02f6", X"005f", X"0287", 88 X"05d6", X"020d", X"0048", X"037b", X"027c", X"01a9", X"02c5", X"0129", 89 X"05b5", X"0023", X"0660", X"0236", X"02b1", X"03e1", X"028d", X"0312", 90 X"0367", X"04d3", X"041e", X"006c", X"040b", X"00d6", X"0300", X"0031", 91 X"02f3", X"00ed", X"024a", X"04ff", X"0151", X"0371", X"0368", X"0371", 92 X"01fb", X"01f9", X"0215", X"031f", X"0258", X"03df", X"01e0", X"0484", 93 X"040f", X"04a2", X"00a5", X"0394", X"01ab", X"01a6", X"0418", X"0145", 94 X"020e", X"0116", X"018a", X"030c", X"04fc", X"0060", X"03aa", X"0372", 95 X"0263", X"027a", X"00f8", X"049b", X"03c0", X"0012", X"04da", X"027e", 96 X"01ba", X"02e1", X"03af", X"0161", X"04da", X"0476", X"0364", X"01bd", 97 X"0459", X"020f", X"05e1", X"01e9", X"038a", X"03f9", X"02d7", X"025f", 98 X"04cc", X"02db", X"02d1", X"035b", X"017a", X"03ed", X"018a", X"0556", 99 X"0039", X"0455", X"04f1", X"0449", X"032d", X"039a", X"034a", X"04b6", 100 X"03b0", X"0236", X"046c", X"052f", X"0514", X"0159", X"031c", X"040d", 101 X"00b6", X"0140", X"01bc", X"03af", X"0328", X"02a1", X"01f4", X"013b", 102 X"032b", X"0396", X"01a3", X"0266", X"00fb", X"023b", X"01f8", X"0362", 103 X"0430", X"0404", X"036e", X"033d", X"047e", X"04e9", X"06ba", X"0365", 104 X"0796", X"006a", X"053b", X"02e8", X"02cd", X"02de", X"02bb", X"05d0", 105 X"02f3", X"0306", X"0384", X"01ae", X"025b", X"05e1", X"03cd", X"0486", 106 X"0144", X"03d9", X"05bb", X"02f8", X"0435", X"06b2", X"0368", X"042b", 107 X"0270", X"080b", X"0439", X"0553", X"04cc", X"0702", X"04f1", X"0779", 108 X"0480", X"08f1", X"0447", X"05ce", X"0774", X"0a47", X"09a4", X"08f9", 109 X"0a49", X"0b52", X"0b42", X"0b2d", X"0e10", X"0fcf", X"1150", X"1437", 110 X"15f0", X"1a9e", X"214c", X"24ec", X"305e", X"3e0f", X"4ff5", X"6d8c", 111 X"8e3e", X"afdf", X"c0cb", X"b78b", X"9c10", X"770f", X"581f", X"457e", 112 X"3421", X"2b2e", X"2020", X"1d4a", X"17f0", X"13c9", X"12c7", X"0e6a", 113 X"0e40", X"0c59", X"0b95", X"0cf3", X"086e", X"071f", X"0abf", X"0619", 114 X"05d7", X"054f", X"058a", X"047c", X"04d9", X"0954", X"06a2", X"04ea", 115 X"053a", X"04ce", X"05a6", X"0724", X"0333", X"049b", X"04cf", X"01c5", 116 X"054f", X"05cc", X"029d", X"0280", X"045f", X"0262", X"03fe", X"02e3", 117 X"02f5", X"0634", X"04e3", X"017a", X"00d1", X"020d", X"0088", X"0157", 118 X"0419", X"03ea", X"002c", X"049b", X"01a3", X"03f3", X"05b3", X"0201", 119 X"054d", X"040d", X"0135", X"028e", X"0243", X"05a4", X"0310", X"0027", 120 X"02f6", X"0342", X"0463", X"02e3", X"0673", X"06a0", X"03c0", X"0416", 121 X"0247", X"03e1", X"052f", X"00d5", X"006b", X"038f", X"04a7", X"040a", 122 X"01d0", X"034a", X"02df", X"0344", X"00c5", X"038d", X"0236", X"0341", 123 X"0338", X"050d", X"026f", X"0043", X"0377", X"01da", X"0532", X"03a0", 124 X"0109", X"0114", X"0232", X"021b", X"03fe", X"0428", X"02b0", X"0210", 125 X"01e6", X"011c", X"00f9", X"0341", X"0166", X"0040", X"046a", X"021f", 126 X"0426", X"04a9", X"0160", X"045d", X"0030", X"02b6", X"01d4", X"016e", 127 X"04f0", X"036d", X"05c6", X"05e8", X"02bc", X"00dd", X"020d", X"01e3", 128 X"0572", X"01e9", X"033f", X"0360", X"0228", X"00df", X"0056", X"05dc", 129 X"01e1", X"00d3", X"021a", X"0146", X"049f", X"009a", X"0390", X"00c6", 130 X"03f8", X"0216", X"0127", X"008f", X"033f", X"0231", X"023c", X"0301", 131 X"02b1", X"01a2", X"03f6", X"019f", X"02c7", X"070f", X"04e7", X"034b", 132 X"0568", X"0290", X"01bd", X"006c", X"0022", X"0134", X"0527", X"02d3", 133 X"0262", X"02bd", X"00aa", X"03da", X"017a", X"0323", X"0376", X"0121", 134 X"0071", X"040f", X"02de", X"0240", X"0212", X"06ed", X"02ba", X"0056", 135 X"02b8", X"007a", X"03bd", X"0367", X"01ff", X"008e", X"03b9", X"0322", 136 X"043c", X"0491", X"044b", X"0224", X"03bb", X"0124", X"00b3", X"019e", 137 X"0448", X"03a2", X"026f", X"0114", X"03c2", X"01d8", X"0261", X"004b", 138 X"00f7", X"0414", X"017b", X"0006", X"02cb", X"02be", X"0074", X"0649", 139 X"012b", X"0296", X"007c", X"0392", X"005d", X"02a7", X"04a8", X"01ca", 140 X"0154", X"049b", X"03b8", X"0483", X"044c", X"04e4", X"035c", X"023d", 141 X"040e", X"019a", X"00bd", X"030a", X"014f", X"0164", X"03af", X"031e",

Page 13: Appendix C - Code Listing

  13  

142 X"032d", X"01a4", X"04d6", X"0186", X"0305", X"00ef", X"02c6", X"0158", 143 X"005c", X"00b0", X"0425", X"0034", X"0308", X"0291", X"00e0", X"0001", 144 X"03ac", X"0210", X"0026", X"031d", X"0026", X"0373", X"0334", X"039a", 145 X"0324", X"0366", X"0228", X"022f", X"017f", X"03d0", X"01b1", X"0506", 146 X"0218", X"0121", X"0379", X"01ec", X"0569", X"01c2", X"0153", X"038e", 147 X"01b7", X"0484", X"0315", X"0217", X"0035", X"03f0", X"0034", X"0377", 148 X"02b8", X"01ec", X"01da", X"0181", X"0103", X"02fc", X"02d6", X"00b9", 149 X"0371", X"00b6", X"0450", X"0197", X"0230", X"049a", X"034a", X"0272", 150 X"0183", X"061b", X"003d", X"0531", X"0079", X"0130", X"0117", X"049a", 151 X"0075", X"026f", X"03f3", X"01de", X"051f", X"00d2", X"02a5", X"0494", 152 X"03b2", X"02fe", X"00f9", X"0525", X"0409", X"0435", X"02f8", X"04fd", 153 X"043f", X"0383", X"0277", X"0458", X"0231", X"006e", X"004e", X"0467", 154 X"0318", X"05e2", X"0370", X"04b0", X"0364", X"00e2", X"01d4", X"034d", 155 X"01a9", X"00db", X"036a", X"0577", X"022c", X"03e7", X"0150", X"0228", 156 X"0382", X"0101", X"0045", X"03d3", X"0293", X"0315", X"0321", X"057b", 157 X"00cd", X"0303", X"0303", X"029e", X"02b2", X"01be", X"05d9", X"047d", 158 X"0290", X"025d", X"02a0", X"0343", X"0289", X"0150", X"01e2", X"005e", 159 X"01e8", X"03cf", X"0325", X"01bb", X"006f", X"03ec", X"04c1", X"0223", 160 X"01ec", X"03ca", X"0493", X"0431", X"0383", X"00cb", X"05af", X"0456", 161 X"01a7", X"0289", X"01ec", X"0163", X"01cd", X"00f2", X"03ba", X"03a6", 162 X"00df", X"06b4", X"0213", X"0256", X"039b", X"03aa", X"01f6", X"0600", 163 X"013b", X"042e", X"00c3", X"020f", X"059b", X"0342", X"020d", X"01aa", 164 X"001f", X"02cc", X"001f", X"0236", X"02d1", X"03c1", X"0478", X"0468", 165 X"0431", X"0253", X"02fe", X"015f", X"0404", X"0342", X"00fb", X"012c", 166 X"0193", X"055e", X"0151", X"00f6", X"0217", X"06fe", X"03f6", X"00fa", 167 X"0022", X"01f6", X"0271", X"00fc", X"04a1", X"040a", X"041e", X"00be", 168 X"0262", X"00a6", X"030d", X"03d0", X"007b", X"058d", X"01db", X"0313", 169 X"0425", X"0316", X"05fd", X"02cd", X"0239", X"03f0", X"01b0", X"010a", 170 X"028b", X"022a", X"02b7", X"0145", X"0558", X"0247", X"0416", X"01ad", 171 X"0475", X"0354", X"0095", X"0306", X"0371", X"049c", X"0176", X"0052", 172 X"01d2", X"0345", X"0272", X"03c8", X"0272", X"02a1", X"025a", X"005d", 173 X"032d", X"0459", X"038d", X"012c", X"00ee", X"005d", X"027c", X"01c0", 174 X"0403", X"015a", X"0424", X"01d8", X"0238", X"052e", X"043d", X"02e0", 175 X"0088", X"0296", X"0306", X"03a9", X"0017", X"02d5", X"031a", X"03b8", 176 X"02b5", X"0311", X"00ad", X"034c", X"03f5", X"0400", X"053f", X"01e9", 177 X"07b0", X"0473", X"0030", X"0321", X"0152", X"03b4", X"00b3", X"02e9", 178 X"01b5", X"02b5", X"009b", X"0141", X"0140", X"01f0", X"0118", X"0270", 179 X"01da", X"01a2", X"0267", X"03d9", X"0383", X"01ca", X"0358", X"02a3", 180 X"02e8", X"022d", X"051b", X"01e4", X"031f", X"01d6", X"0421", X"02cb", 181 X"0371", X"0363", X"028c", X"02f9", X"02b0", X"0437", X"005c", X"0324", 182 X"0116", X"006c", X"01d7", X"0310", X"01bc", X"02fe", X"02b8", X"02bd", 183 X"005a", X"01a6", X"03f1", X"031d", X"031c", X"0103", X"0230", X"0287", 184 X"0322", X"005c", X"03a0", X"01b1", X"0306", X"0250", X"03c0", X"055c", 185 X"0199", X"00ed", X"0252", X"0351", X"0177", X"00b8", X"0545", X"008d", 186 X"0228", X"00eb", X"05f4", X"020d", X"036d", X"00ac", X"03a9", X"021d", 187 X"026f", X"01ee", X"01b6", X"01b0", X"0206", X"0265", X"02f5", X"03a1", 188 X"02ab", X"02d8", X"0009", X"01c3", X"0186", X"02cf", X"00c9", X"01c8", 189 X"0579", X"04e6", X"04ba", X"001b", X"05bb", X"02b5", X"01e5", X"02bc", 190 X"0210", X"0008", X"02f8", X"0555", X"00e0", X"05a6", X"02ba", X"0054", 191 X"0082", X"023d", X"038a", X"017b", X"0226", X"01e7", X"05e3", X"0318", 192 X"0153", X"009b", X"02e1", X"0567", X"01f5", X"0264", X"00b2", X"01d5", 193 X"0367", X"0303", X"0340", X"026e", X"063b", X"03b5", X"03dc", X"04c3", 194 X"01e4", X"0219", X"0119", X"0508", X"02ba", X"03a7", X"0031", X"01d0", 195 X"030b", X"017a", X"05e2", X"01fe", X"0220", X"02b3", X"0023", X"014b", 196 X"0296", X"0009", X"04ca", X"0384", X"020e", X"0377", X"0209", X"00d3", 197 X"035f", X"01d3", X"0569", X"02f5", X"009d", X"0356", X"0218", X"0473", 198 X"03bd", X"01d7", X"0690", X"0181", X"015d", X"019a", X"0234", X"0418", 199 X"03b0", X"0075", X"0528", X"0331", X"0081", X"0302", X"01e5", X"0444", 200 X"0429", X"02c0", X"04c2", X"0290", X"0307", X"02ce", X"0403", X"021e", 201 X"02cb", X"041f", X"01cd", X"0146", X"04e4", X"026c", X"031a", X"03d3", 202 X"039e", X"008f", X"01bf", X"01f1", X"04e9", X"019e", X"0425", X"0243", 203 X"0442", X"0376", X"00cd", X"039c", X"01aa", X"0654", X"00f8", X"0160", 204 X"01a2", X"0485", X"01cf", X"03e9", X"00d0", X"0473", X"0299", X"0005", 205 X"04c2", X"0213", X"0172", X"02d8", X"0367", X"02dd", X"01ac", X"0322", 206 X"01c4", X"037c", X"043a", X"0565", X"032c", X"02fe", X"0369", X"0245", 207 X"02a1", X"043c", X"04b0", X"0657", X"03b5", X"049a", X"038c", X"0399", 208 X"01a7", X"01b9", X"021f", X"034e", X"031d", X"010c", X"028d", X"025f", 209 X"04c4", X"043f", X"0249", X"0184", X"0293", X"0303", X"0216", X"0041", 210 X"0553", X"0569", X"00b8", X"0228", X"030c", X"0030", X"044b", X"03e4", 211 X"03cf", X"021e", X"01a6", X"040b", X"02dd", X"0350", X"033c", X"0444", 212 X"0662", X"041c", X"031d", X"0491", X"0611", X"0352", X"001a", X"0161", 213 X"05b3", X"0574", X"02fb", X"015b", X"01f9", X"01ba", X"05d1", X"0297", 214 X"005f", X"00ed", X"0493", X"03e8", X"0108", X"0293", X"0258", X"0366",

Page 14: Appendix C - Code Listing

  14  

215 X"04c5", X"01b1", X"03a1", X"02f8", X"033f", X"037f", X"0337", X"0391", 216 X"053f", X"03f5", X"0119", X"0296", X"0369", X"0350", X"018f", X"04c5", 217 X"02b9", X"046a", X"058b", X"0432", X"05ce", X"0284", X"075c", X"055e", 218 X"0272", X"03cb", X"02fb", X"047f", X"0133", X"0215", X"0317", X"0341", 219 X"0529", X"0223", X"049d", X"0442", X"0774", X"02c9", X"0294", X"03f6", 220 X"053f", X"06a8", X"0550", X"02a0", X"0537", X"029e", X"05f8", X"0324", 221 X"0030", X"04f8", X"03e3", X"060a", X"0722", X"05b8", X"04a2", X"0546", 222 X"0635", X"0546", X"0771", X"0a91", X"0bc9", X"0694", X"083a", X"08e6", 223 X"0bed", X"0aaa", X"0cbc", X"0e62", X"1281", X"1308", X"18a2", X"19cb", 224 X"1db5", X"2422", X"2d54", X"3b52", X"4d81", X"6652", X"8523", X"a9ce", 225 X"bc74", X"bf2b", X"a400", X"7d38", X"5f9d", X"468e", X"366a", X"2ed3", 226 X"263d", X"1e78", X"18b5", X"121b", X"12e0", X"0fdd", X"0f50", X"0b2a", 227 X"0a6f", X"0b27", X"0aa4", X"0951", X"0891", X"081b", X"07a9", X"0826", 228 X"094c", X"083b", X"0695", X"0639", X"0317", X"05b4", X"06ea", X"085e", 229 X"0678", X"0500", X"042b", X"04e7", X"0491", X"02e7", X"0429", X"053a", 230 X"020b", X"0360", X"019a", X"04c5", X"04ca", X"03c4", X"0266", X"05e2", 231 X"0383", X"0500", X"03ad", X"025e", X"0608", X"04af", X"03fe", X"0191", 232 X"05ed", X"04f1", X"053e", X"03b7", X"0516", X"01fa", X"01f5", X"0358", 233 X"0345", X"0451", X"0326", X"02d2", X"029b", X"0516", X"0542", X"0262", 234 X"0318", X"0390", X"0128", X"0244", X"04f8", X"012c", X"036e", X"0184", 235 X"0195", X"026b", X"021a", X"02bf", X"02e8", X"0252", X"040e", X"0500", 236 X"0300", X"0067", X"0504", X"030f", X"0530", X"047e", X"0261", X"0392", 237 X"04b8", X"03e9", X"02c8", X"02bb", X"02ca", X"02ef", X"02aa", X"00c8", 238 X"0186", X"0151", X"05d4", X"045d", X"0533", X"029f", X"0564", X"0383", 239 X"0323", X"034b", X"0432", X"04df", X"0194", X"0409", X"01c4", X"0115", 240 X"01f6", X"027b", X"0447", X"0297", X"016d", X"0086", X"0093", X"0209", 241 X"03ee", X"0326", X"00dd", X"018e", X"0441", X"0194", X"03b7", X"0162", 242 X"031b", X"03a4", X"04a0", X"00d0", X"040d", X"0237", X"0540", X"032a", 243 X"030e", X"0194", X"055b", X"02bd", X"05cf", X"03dc", X"052e", X"02a0", 244 X"00ec", X"022e", X"0129", X"01e0", X"03d2", X"0423", X"0215", X"0225", 245 X"031e", X"038e", X"03ab", X"0203", X"05ed", X"03fe", X"01a6", X"017b", 246 X"0119", X"03cb", X"03db", X"01f9", X"02de", X"010f", X"01bf", X"0692", 247 X"0237", X"017b", X"017d", X"01bf", X"0279", X"0496", X"016d", X"03a5", 248 X"01bb", X"0694", X"0280", X"01d1", X"02d8", X"02f3", X"0128", X"0089", 249 X"0463", X"0516", X"0318", X"026a", X"0216", X"0529", X"04fb", X"02f1", 250 X"02b1", X"025a", X"01c4", X"0543", X"0233", X"043e", X"01b4", X"041b", 251 X"0093", X"020f", X"03da", X"01f5", X"01ec", X"0327", X"042e", X"0391", 252 X"0210", X"015c", X"0237", X"04e6", X"030a", X"01a9", X"0239", X"0500", 253 X"02ac", X"0265", X"0270", X"01f9", X"0224", X"0079", X"0148", X"03a7", 254 X"04c6", X"002d", X"01c2", X"01bb", X"005d", X"00c8", X"02c9", X"003e", 255 X"00e1", X"03b9", X"02f1", X"0245", X"03e1", X"043f", X"054f", X"038b", 256 X"00e3", X"025b", X"037c", X"02e1", X"02b8", X"0439", X"0272", X"0219", 257 X"03ea", X"04dc", X"01b9", X"025f", X"01b1", X"05ee", X"0336", X"0158", 258 X"03b0", X"00c9", X"01ee", X"03d6", X"00d8", X"014c", X"00b9", X"0519", 259 X"0129", X"023e", X"0495", X"0118", X"02bd", X"0232", X"0072", X"0153", 260 X"0336", X"01de", X"015e", X"01fc", X"0349", X"03e0", X"0079", X"0481", 261 X"01c6", X"0061", X"0113", X"0208", X"02f3", X"03ba", X"036b", X"04e8", 262 X"0470", X"0192", X"0117", X"01d8", X"02af", X"0276", X"0266", X"04ab", 263 X"01b7", X"00ef", X"038c", X"036b", X"02f6", X"0496", X"0489", X"0536", 264 X"01ad", X"0337", X"03b3", X"041e", X"0406", X"02c0", X"0737", X"064d", 265 X"0321", X"0188", X"0244", X"03b2", X"03f8", X"02a5", X"0539", X"00d0", 266 X"04a7", X"03b8", X"02cc", X"03d3", X"04b3", X"02d9", X"0259", X"0284", 267 X"0236", X"0047", X"0143", X"021f", X"035c", X"02a6", X"031a", X"0228", 268 X"0050", X"0407", X"02a6", X"0263", X"0217", X"046a", X"0374", X"0400", 269 X"020c", X"0486", X"0234", X"023f", X"006b", X"03e1", X"008e", X"0310", 270 X"02e7", X"036d", X"00e1", X"01f1", X"0131", X"0155", X"009d", X"0103", 271 X"035a", X"031e", X"0187", X"026b", X"0338", X"02c7", X"0382", X"047e", 272 X"02b0", X"02e0", X"023e", X"014e", X"01fe", X"032a", X"0187", X"030e", 273 X"02cd", X"009e", X"00a7", X"044b", X"0373", X"0325", X"02b5", X"0397", 274 X"00da", X"025d", X"03e2", X"04fb", X"0407", X"03e9", X"024b", X"0618", 275 X"01d2", X"043b", X"011f", X"035d", X"024d", X"0445", X"0508", X"03ae", 276 X"016f", X"038e", X"05cf", X"0301", X"01d5", X"02cd", X"01ac", X"0430", 277 X"0694", X"036d", X"03ca", X"0201", X"06e4", X"01e0", X"039b", X"01ad", 278 X"033f", X"026b", X"028d", X"005c", X"00a1", X"02ec", X"0063", X"00aa", 279 X"00f0", X"0417", X"0009", X"04b9", X"018f", X"0446", X"02ef", X"02ce", 280 X"0334", X"0190", X"04cc", X"02be", X"0122", X"0079", X"04d7", X"01ee", 281 X"00cc", X"04cd", X"05ac", X"03af", X"0233", X"0104", X"0342", X"0343", 282 X"0112", X"0083", X"0258", X"0216", X"0263", X"0164", X"02b1", X"01d1", 283 X"02d6", X"03e4", X"0082", X"041d", X"0176", X"03f9", X"02ac", X"05a9", 284 X"037c", X"0311", X"011e", X"01f2", X"04a3", X"0534", X"023f", X"01bf", 285 X"002c", X"04af", X"03b1", X"00a1", X"03da", X"036a", X"0574", X"0082", 286 X"0170", X"0294", X"03bb", X"0215", X"0322", X"00fc", X"05a5", X"05fd", 287 X"01d3", X"0270", X"026a", X"03af", X"0110", X"04cc", X"0401", X"020c",

Page 15: Appendix C - Code Listing

  15  

288 X"0154", X"01e5", X"0167", X"0467", X"040c", X"0741", X"03a0", X"02eb", 289 X"030b", X"0079", X"04f9", X"03c5", X"0311", X"0416", X"01e4", X"0456", 290 X"0367", X"01f7", X"04d1", X"03eb", X"02de", X"00c1", X"0299", X"03b1", 291 X"05f8", X"03c5", X"03c7", X"04d9", X"0429", X"01ff", X"0360", X"04c6", 292 X"03db", X"0252", X"0386", X"0193", X"0234", X"0406", X"019d", X"01a8", 293 X"020d", X"01e4", X"02a1", X"031f", X"03e0", X"0216", X"03b8", X"03d5", 294 X"0238", X"0517", X"046a", X"00f0", X"0159", X"04ba", X"03ff", X"046a", 295 X"01fa", X"000d", X"0019", X"01ea", X"0329", X"03e1", X"02ec", X"045b", 296 X"0522", X"0494", X"0372", X"03ab", X"02e8", X"0630", X"02dd", X"05ca", 297 X"02a9", X"04ab", X"025b", X"022c", X"0519", X"01eb", X"0267", X"024f", 298 X"0228", X"058a", X"00a0", X"031e", X"01aa", X"0774", X"014c", X"0499", 299 X"0103", X"02eb", X"02ff", X"03e6", X"04f2", X"00b7", X"022a", X"0588", 300 X"00e3", X"0281", X"04f7", X"01e6", X"0350", X"0404", X"0038", X"0243", 301 X"02f7", X"02a3", X"03eb", X"04b8", X"03e2", X"031d", X"02eb", X"0226", 302 X"0152", X"0077", X"036b", X"03d0", X"044a", X"0248", X"01dc", X"0128", 303 X"0167", X"04c5", X"010b", X"0206", X"0394", X"04d8", X"01d1", X"0445", 304 X"01cc", X"04a3", X"00f7", X"01bb", X"04d6", X"001e", X"05e2", X"0149", 305 X"02bc", X"01f7", X"03c2", X"0026", X"025e", X"034b", X"039c", X"0035", 306 X"03fb", X"0272", X"038a", X"02c7", X"030e", X"0115", X"025b", X"0397", 307 X"0329", X"0027", X"0326", X"032c", X"0410", X"01c4", X"03b6", X"02ef", 308 X"012e", X"025a", X"009c", X"02b2", X"03f6", X"016a", X"018f", X"02d6", 309 X"027c", X"04e2", X"011a", X"00bc", X"0329", X"00e4", X"03be", X"0439", 310 X"039e", X"014e", X"071d", X"02de", X"0546", X"0291", X"02ab", X"0168", 311 X"0493", X"03b9", X"03b2", X"02ee", X"032e", X"035b", X"012f", X"0459", 312 X"0153", X"0399", X"0201", X"01a2", X"03c2", X"0436", X"04be", X"0408", 313 X"035c", X"0389", X"00da", X"0029", X"0244", X"03b4", X"0419", X"025b", 314 X"0223", X"02d3", X"0353", X"0529", X"01c9", X"019a", X"02ce", X"0082", 315 X"031d", X"02e3", X"0303", X"03d2", X"0252", X"02a6", X"0300", X"009f", 316 X"027e", X"037e", X"011a", X"0471", X"004f", X"0163", X"028c", X"01fc", 317 X"03d6", X"018d", X"047b", X"0154", X"04c5", X"00e6", X"040e", X"02b4", 318 X"007f", X"033c", X"0420", X"028d", X"000a", X"029e", X"0342", X"00e0", 319 X"004f", X"075b", X"01ef", X"02a7", X"018b", X"03af", X"046c", X"026f", 320 X"002f", X"0016", X"02e5", X"00ec", X"022a", X"02ae", X"019e", X"040f", 321 X"00d7", X"0466", X"027f", X"0401", X"053a", X"032b", X"008b", X"026d", 322 X"02bf", X"0212", X"00bd", X"03d4", X"02a8", X"0289", X"016e", X"042e", 323 X"034b", X"03d8", X"02d9", X"0302", X"0379", X"0364", X"0262", X"054b", 324 X"04dc", X"0406", X"0399", X"02bb", X"0192", X"05fa", X"032b", X"02ad", 325 X"04d4", X"04fc", X"033b", X"033b", X"02b5", X"0062", X"016a", X"0280", 326 X"02bc", X"054d", X"00cc", X"0317", X"01d5", X"02d1", X"0070", X"04c5", 327 X"038f", X"0351", X"0279", X"0250", X"0511", X"01fa", X"01ad", X"0481", 328 X"04b2", X"0405", X"03bf", X"019c", X"050f", X"028f", X"059a", X"01b4", 329 X"021e", X"0230", X"02bb", X"02e3", X"042e", X"03dc", X"027e", X"019a", 330 X"02b5", X"08fe", X"01ce", X"0299", X"0602", X"03d4", X"04f0", X"02c9", 331 X"0181", X"0482", X"022b", X"05bc", X"0240", X"02f7", X"0284", X"03da", 332 X"05e1", X"04a9", X"0769", X"0350", X"03da", X"04db", X"0262", X"02f0", 333 X"04f6", X"02d9", X"0228", X"042b", X"030c", X"0367", X"0460", X"055b", 334 X"031e", X"0833", X"06ee", X"04a2", X"05ad", X"0698", X"0281", X"0781", 335 X"0608", X"04d3", X"06d5", X"05bf", X"066a", X"068f", X"086c", X"0a70", 336 X"0597", X"0654", X"0803", X"06f2", X"0b13", X"099a", X"0c23", X"0c2a", 337 X"0d9e", X"0d17", X"0fbd", X"1326", X"15ac", X"179d", X"1da6", X"2395", 338 X"2aab", X"34f8", X"48c7", X"6374", X"7e55", X"a224", X"bd43", X"c187", 339 X"a9bd", X"85ad", X"65ef", X"494e", X"3d90", X"2e4a", X"269e", X"1db4", 340 X"1b33", X"1797", X"12a2", X"11a8", X"0df3", X"0cb8", X"0d44", X"0b5c", 341 X"08f2", X"04e7", X"0d4f", X"063a", X"060d", X"0582", X"074b", X"0a13", 342 X"0435", X"025d", X"060f", X"06d7", X"0547", X"0507", X"016f", X"039b", 343 X"040e", X"053d", X"0245", X"038f", X"0305", X"039b", X"052b", X"01df", 344 X"047e", X"0105", X"0279", X"0655", X"0334", X"0456", X"05cb", X"05c5", 345 X"0606", X"040a", X"02c3", X"03b7", X"001c", X"027c", X"0358", X"01d4", 346 X"0380", X"05d7", X"059f", X"0185", X"0543", X"0277", X"03e7", X"0380", 347 X"05df", X"02cc", X"02af", X"0435", X"036c", X"0347", X"02eb", X"00c8", 348 X"02a9", X"0200", X"02b4", X"0332", X"01ec", X"01d1", X"02fc", X"0361", 349 X"03d1", X"03e9", X"021a", X"0154", X"04c8", X"01a2", X"004a", X"042a", 350 X"050e", X"021b", X"0195", X"0501", X"02bd", X"0330", X"00c2", X"02e5", 351 X"01dd", X"01cd", X"078c", X"02d2", X"0232", X"03df", X"03e9", X"00fb", 352 X"01d5", X"059b", X"02aa", X"007a", X"050c", X"02f7", X"031a", X"01fe", 353 X"0402", X"047e", X"0350", X"01c0", X"03ef", X"038d", X"00b3", X"038b", 354 X"0640", X"02fa", X"02d8", X"0226", X"02a6", X"0211", X"0359", X"0214", 355 X"0227", X"03e7", X"03de", X"05b4", X"016f", X"00a7", X"0282", X"00eb", 356 X"0265", X"0193", X"034c", X"02ad", X"0086", X"01ea", X"0457", X"03dc", 357 X"0184", X"00f8", X"028e", X"030a", X"037a", X"02c5", X"01f8", X"01e1", 358 X"025d", X"02ce", X"0403", X"01ce", X"0498", X"02bd", X"0116", X"00eb", 359 X"030b", X"0219", X"02b0", X"0210", X"0238", X"01d3", X"031e", X"0394", 360 X"0312", X"0396", X"01e7", X"0318", X"0118", X"0359", X"029a", X"03ef",

Page 16: Appendix C - Code Listing

  16  

361 X"0497", X"0195", X"04be", X"03b8", X"0175", X"0253", X"00f7", X"01bd", 362 X"0316", X"0334", X"02e6", X"009b", X"0405", X"03fb", X"001a", X"041f", 363 X"0076", X"03f0", X"0212", X"00a6", X"016e", X"003d", X"0264", X"0288", 364 X"0505", X"0314", X"05d1", X"05f9", X"0276", X"005b", X"00f2", X"013e", 365 X"046c", X"00ca", X"039c", X"0363", X"04a2", X"046c", X"0325", X"0354", 366 X"00dc", X"02c7", X"0440", X"0389", X"02b0", X"0387", X"02e2", X"021a", 367 X"033c", X"01ed", X"029c", X"0297", X"02bc", X"005a", X"0201", X"0041", 368 X"01e7", X"021f", X"02ba", X"01be", X"0410", X"0557", X"02a5", X"0563", 369 X"043a", X"048c", X"0117", X"0412", X"0489", X"00ee", X"03da", X"02c8", 370 X"02da", X"0100", X"024c", X"01c0", X"014e", X"0343", X"0010", X"0411", 371 X"0520", X"061f", X"045c", X"02d8", X"0494", X"04f9", X"033b", X"01ac", 372 X"0246", X"02a9", X"03e8", X"0409", X"05cf", X"02bf", X"04f6", X"0269", 373 X"01e4", X"01aa", X"012c", X"03a8", X"03d0", X"0282", X"00da", X"05a4", 374 X"00e4", X"0324", X"019f", X"0230", X"0003", X"007a", X"020f", X"0308", 375 X"021f", X"0162", X"031d", X"023d", X"02b6", X"04b2", X"022c", X"0636", 376 X"03af", X"0293", X"0160", X"0354", X"048f", X"05ee", X"029e", X"0574", 377 X"0204", X"0491", X"0164", X"0261", X"0054", X"04a6", X"03de", X"02e4", 378 X"02d1", X"0225", X"0237", X"049c", X"0350", X"0469", X"02d8", X"0215", 379 X"02b1", X"026e", X"05bf", X"03da", X"0075", X"00b5", X"0392", X"015e", 380 X"0254", X"0478", X"027d", X"045f", X"02eb", X"03fb", X"0205", X"01f0", 381 X"01c0", X"0255", X"04c8", X"0390", X"0263", X"0221", X"03a6", X"038c", 382 X"0367", X"02e6", X"035f", X"012f", X"0323", X"0597", X"00a0", X"0138", 383 X"02c7", X"00b6", X"00ca", X"0420", X"04ef", X"0336", X"0328", X"01d5", 384 X"027c", X"035d", X"0020", X"0269", X"0250", X"038a", X"0182", X"0340", 385 X"00dc", X"03fa", X"03bf", X"0015", X"0265", X"0011", X"07c9", X"00bb", 386 X"026a", X"0472", X"0200", X"012b", X"0126", X"0388", X"0051", X"030d", 387 X"01b1", X"0503", X"0110", X"0166", X"01e6", X"0461", X"0310", X"029e", 388 X"00d3", X"0165", X"01e2", X"03dc", X"0207", X"01c3", X"0281", X"02c1", 389 X"004a", X"0319", X"00a8", X"04c1", X"0240", X"01d9", X"03f0", X"01cb", 390 X"01bf", X"03b5", X"007a", X"03d8", X"0255", X"009b", X"0002", X"021e", 391 X"0042", X"01cc", X"0144", X"0710", X"0282", X"0527", X"047a", X"0067", 392 X"030b", X"0572", X"0289", X"0068", X"0656", X"004d", X"02a2", X"0256", 393 X"0399", X"0197", X"057d", X"0357", X"02aa", X"017a", X"0435", X"03e5", 394 X"0389", X"0127", X"0299", X"043b", X"035c", X"0209", X"0307", X"0156", 395 X"00b7", X"03e5", X"0413", X"01e5", X"05cf", X"0770", X"02e4", X"02c7", 396 X"0373", X"032b", X"03c0", X"02bc", X"015f", X"005a", X"0000", X"03ab", 397 X"049f", X"0693", X"0348", X"0110", X"03e0", X"0131", X"050a", X"0377", 398 X"01d9", X"0331", X"05c1", X"03c1", X"0219", X"03ca", X"0163", X"02a5", 399 X"027e", X"02c0", X"06a8", X"0152", X"0214", X"01bc", X"030d", X"02a1", 400 X"03b4", X"0410", X"0549", X"0303", X"00ee", X"0392", X"0326", X"02b5", 401 X"00eb", X"007d", X"01de", X"01b7", X"028f", X"0450", X"0134", X"022b", 402 X"00f5", X"0277", X"047b", X"0412", X"0388", X"01d4", X"041a", X"0233", 403 X"0181", X"0081", X"0327", X"01c7", X"0091", X"02ff", X"0259", X"0290", 404 X"040b", X"0102", X"0394", X"0230", X"0271", X"02d6", X"02d2", X"00e2", 405 X"0268", X"052b", X"02ad", X"0194", X"02fc", X"011c", X"0493", X"007c", 406 X"03f2", X"01d3", X"04b8", X"034a", X"0234", X"02cd", X"00f8", X"028e", 407 X"00d6", X"0446", X"0035", X"0438", X"0276", X"0180", X"0363", X"021c", 408 X"00ab", X"0435", X"02ac", X"0135", X"0400", X"0087", X"03c3", X"03a7", 409 X"0464", X"00fc", X"01e9", X"0346", X"0213", X"0244", X"0070", X"067b", 410 X"0706", X"0181", X"026e", X"0074", X"04fe", X"002d", X"000e", X"0378", 411 X"00f7", X"0102", X"00e8", X"03a9", X"01d4", X"0238", X"0316", X"01f9", 412 X"03c9", X"02be", X"0346", X"03a3", X"0253", X"030d", X"039a", X"0200", 413 X"026d", X"0455", X"026a", X"03b5", X"0010", X"0474", X"0307", X"047d", 414 X"0259", X"01bf", X"02d6", X"0329", X"0138", X"0226", X"01d6", X"0384", 415 X"01a8", X"0164", X"01ed", X"02f2", X"0278", X"017b", X"0266", X"0266", 416 X"0331", X"00e4", X"0303", X"0310", X"0487", X"03c3", X"0071", X"03c0", 417 X"01bc", X"040b", X"0430", X"0253", X"0411", X"01be", X"02db", X"0296", 418 X"04e2", X"024f", X"0390", X"00bb", X"00db", X"017a", X"05d6", X"0420", 419 X"02e7", X"03c1", X"01d8", X"02cb", X"0096", X"0371", X"03ee", X"02ac", 420 X"03a1", X"02eb", X"0168", X"034a", X"0472", X"022e", X"047d", X"0151", 421 X"00e4", X"000b", X"001e", X"0027", X"03e3", X"03a0", X"0561", X"0231", 422 X"046b", X"0332", X"0424", X"013d", X"023d", X"03fa", X"03f2", X"05e3", 423 X"02df", X"0606", X"03b2", X"0282", X"02ad", X"04e5", X"0241", X"0383", 424 X"03aa", X"058a", X"032e", X"027f", X"0284", X"0152", X"0271", X"05de", 425 X"037f", X"00c5", X"03d6", X"03a8", X"021a", X"0022", X"0577", X"0468", 426 X"016a", X"0395", X"034b", X"01f4", X"01e8", X"02e7", X"0197", X"041f", 427 X"04c6", X"00ae", X"027f", X"012e", X"022d", X"038e", X"0458", X"031b", 428 X"039b", X"0338", X"0228", X"01d2", X"0416", X"04a9", X"01dd", X"0380", 429 X"0453", X"0179", X"02fd", X"00c8", X"01f3", X"0418", X"03a3", X"00ca", 430 X"022e", X"0475", X"00b8", X"0257", X"0138", X"03fc", X"02c9", X"04b7", 431 X"053d", X"01f8", X"03a9", X"01be", X"0260", X"0327", X"044b", X"0366", 432 X"0074", X"02c9", X"01d6", X"019c", X"03fd", X"0340", X"02ef", X"0103", 433 X"0302", X"01b1", X"038e", X"057f", X"0280", X"01ac", X"0339", X"01ea",

Page 17: Appendix C - Code Listing

  17  

434 X"0420", X"0424", X"0084", X"036f", X"026d", X"0274", X"028d", X"058a", 435 X"0391", X"02c8", X"02af", X"015b", X"019f", X"009c", X"01dd", X"0338", 436 X"03b5", X"021e", X"0277", X"021d", X"0184", X"006b", X"02d3", X"01d5", 437 X"048c", X"053d", X"02b5", X"04fe", X"03c6", X"04b8", X"01df", X"05a8", 438 X"0249", X"00ab", X"0239", X"00ae", X"00cc", X"029a", X"01dc", X"0440", 439 X"040d", X"0101", X"0234", X"039a", X"04ee", X"062b", X"0199", X"02d5", 440 X"0461", X"0361", X"039a", X"039a", X"022b", X"012f", X"03b4", X"02d4", 441 X"02ce", X"02e6", X"01ab", X"0176", X"05d0", X"01a7", X"023e", X"043f", 442 X"00c0", X"00fe", X"030e", X"0007", X"0292", X"04bb", X"01bb", X"069d", 443 X"0335", X"0450", X"011f", X"0266", X"0452", X"021e", X"026a", X"030e", 444 X"025a", X"02e5", X"020d", X"00fc", X"059c", X"0352", X"022b", X"03ca", 445 X"0514", X"0367", X"0432", X"0367", X"0416", X"050a", X"0326", X"0326", 446 X"05f5", X"0470", X"04bd", X"0346", X"0036", X"0309", X"0381", X"07d2", 447 X"0547", X"0244", X"01d7", X"078d", X"01cd", X"0577", X"04fd", X"02b8", 448 X"03a0", X"0605", X"0560", X"0448", X"06c0", X"0567", X"0297", X"052e", 449 X"045d", X"0a55", X"0637", X"0821", X"0654", X"0bb6", X"0899", X"050b", 450 X"0b00", X"09d9", X"09e1", X"0a26", X"08fc", X"0b64", X"0aba", X"0e64", 451 X"0fc7", X"14aa", X"1683", X"19c6", X"1e77", X"21e6", X"270d", X"34ff", 452 X"4630", X"5b63", X"7638", X"9ab7", X"b64a", X"c547", X"ae41", X"8dfa", 453 X"6c6f", X"52c1", X"3d41", X"31d2", X"28dd", X"21a2", X"19a0", X"190f", 454 X"12f7", X"110a", X"107b", X"0e88", X"0b8f", X"0a52", X"09ce", X"09f2", 455 X"079e", X"096a", X"08a8", X"07ae", X"085a", X"069b", X"094c", X"0724", 456 X"060b", X"048d", X"04c8", X"06b5", X"05cb", X"0519", X"06fa", X"040b", 457 X"0589", X"0671", X"0551", X"0352", X"0478", X"030b", X"04f4", X"0660", 458 X"04af", X"0145", X"0430", X"0688", X"04b7", X"07fa", X"0300", X"034a", 459 X"0451", X"0372", X"03fb", X"0292", X"00dc", X"0319", X"0130", X"045e", 460 X"057f", X"035c", X"0458", X"0336", X"037f", X"02cd", X"024b", X"0582", 461 X"04d5", X"0353", X"007d", X"058f", X"00f3", X"03f8", X"03e9", X"048c", 462 X"037c", X"0313", X"03c6", X"0278", X"0026", X"03f7", X"0367", X"02a5", 463 X"0486", X"012e", X"028f", X"0019", X"002e", X"0010", X"02e7", X"0177", 464 X"02f4", X"029b", X"0302", X"036c", X"0411", X"0213", X"066f", X"02a7", 465 X"0255", X"03cb", X"02fa", X"03e5", X"0371", X"02c8", X"0573", X"03d5", 466 X"035d", X"038c", X"045d", X"03a6", X"0219", X"03f5", X"0438", X"0501", 467 X"02f6", X"030e", X"0450", X"0011", X"03d3", X"03b2", X"03ee", X"016d", 468 X"0306", X"006b", X"01e2", X"022c", X"03e2", X"01c3", X"02ea", X"01db", 469 X"01a7", X"0520", X"0522", X"029b", X"00d7", X"013e", X"00b3", X"0192", 470 X"044c", X"01fc", X"0103", X"0342", X"04e8", X"0444", X"055b", X"00a1", 471 X"02a9", X"01ae", X"021a", X"0094", X"00a6", X"0158", X"022a", X"03cd", 472 X"04ce", X"0213", X"0276", X"02a1", X"01d7", X"0364", X"0285", X"0192", 473 X"0417", X"01bd", X"02cf", X"033e", X"01d3", X"043d", X"0262", X"02a7", 474 X"0411", X"01dd", X"013e", X"04c9", X"03b2", X"0026", X"0515", X"037a", 475 X"029c", X"03a3", X"005f", X"0063", X"045e", X"0160", X"0527", X"031a", 476 X"028f", X"0528", X"02cf", X"0260", X"02a5", X"00fd", X"03c9", X"00d0", 477 X"0334", X"044a", X"0319", X"032a", X"03c2", X"0425", X"01b1", X"01d5", 478 X"0176", X"0238", X"019d", X"033a", X"01c5", X"0197", X"0231", X"038c", 479 X"03bd", X"0337", X"05c2", X"03fc", X"0317", X"047b", X"01f7", X"0266", 480 X"02ad", X"04e9", X"03dd", X"0221", X"0278", X"00f4", X"0164", X"0448", 481 X"019a", X"0267", X"0237", X"0243", X"0165", X"03eb", X"033b", X"01d2", 482 X"0382", X"0543", X"0194", X"041f", X"03ac", X"0503", X"0097", X"028a", 483 X"01a6", X"03a5", X"031b", X"01f9", X"006d", X"0387", X"02ba", X"0416", 484 X"004a", X"0194", X"037a", X"023b", X"0577", X"0341", X"009e", X"021a", 485 X"0615", X"02dd", X"01fb", X"020b", X"00b6", X"04ea", X"02d0", X"0249", 486 X"00fd", X"0016", X"0139", X"0038", X"031c", X"03fd", X"026e", X"03af", 487 X"05a7", X"00c8", X"0135", X"0513", X"0236", X"0392", X"024f", X"03b0", 488 X"00da", X"044b", X"0139", X"016a", X"0301", X"010c", X"01bf", X"04e8", 489 X"001d", X"00b5", X"0064", X"0195", X"02a4", X"0129", X"00bc", X"021f", 490 X"0373", X"0355", X"020d", X"0426", X"037e", X"03ad", X"0407", X"0106", 491 X"0525", X"0323", X"0135", X"02b7", X"04d9", X"0087", X"029a", X"03fe", 492 X"0350", X"005c", X"00dd", X"04de", X"01b9", X"044a", X"02a2", X"03ac", 493 X"00cc", X"05ad", X"0143", X"00c7", X"0453", X"03cf", X"03a3", X"017a", 494 X"0258", X"03ab", X"0044", X"0354", X"0236", X"02a6", X"037d", X"0502", 495 X"0429", X"02a4", X"02a0", X"0189", X"0099", X"01fd", X"04cb", X"022a", 496 X"03a2", X"00b1", X"0489", X"02db", X"0071", X"01d6", X"01da", X"04ce", 497 X"05fb", X"056b", X"008b", X"00a6", X"0329", X"0508", X"0094", X"0594", 498 X"02a9", X"043d", X"0153", X"0021", X"0036", X"04f0", X"036b", X"0080", 499 X"0146", X"0131", X"04c0", X"0097", X"009e", X"0113", X"0061", X"045c", 500 X"02ff", X"03a2", X"0245", X"0151", X"023d", X"0276", X"0241", X"0798", 501 X"01e7", X"03ba", X"01b7", X"01d6", X"01fd", X"0144", X"037f", X"028d", 502 X"00d7", X"01b8", X"040a", X"029f", X"0648", X"0022", X"00bc", X"0249", 503 X"022d", X"030f", X"0442", X"014d", X"020e", X"011a", X"0209", X"0285", 504 X"012c", X"024b", X"01e5", X"0225", X"0352", X"038e", X"026a", X"0250", 505 X"04b4", X"005f", X"031f", X"02c8", X"0460", X"0187", X"0403", X"012f", 506 X"03c2", X"02c0", X"036d", X"0559", X"0446", X"003e", X"0381", X"0368",

Page 18: Appendix C - Code Listing

  18  

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;

Page 19: Appendix C - Code Listing

  19  

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

Page 20: Appendix C - Code Listing

  20  

62 63 --heavy_math: process(clk) is 64 --begin 65 -- if rising_edge(clk) then 66 scan_diff <= scan_max - scan_min; 67 check_nsamp1 <= ((scan_max - scan_min)*smp_step) ; 68 check_nsamp2 <= (MAXMEM*scan_step); 69 -- end if; 70 --end process; 71 72 --process for moore based output 73 mealy_fsm:process(clk,reset) 74 begin 75 if(reset = '1')then 76 cur_state <= ST_WAIT; 77 elsif(rising_edge(clk))then 78 cmd_reg_reset <= '0'; 79 sample_en <= '0'; 80 CASE cur_state IS 81 82 --wait until UIM has asked for values 83 WHEN ST_WAIT => 84 sample_en <= '0'; --don't write values from the FIFO 85 t_scan_pos <=x"00000000"; 86 if(cmd = SCAN_BEGIN) then 87 next_state <= ST_INIT; 88 else 89 next_state <= cur_state; 90 end if; 91 92 --load values into registers 93 WHEN ST_INIT => 94 --fpga_ready <= '1'; --write values to FIFO 95 next_state <= ST_CHK; 96 97 --check for correct parameters 98 WHEN ST_CHK => 99 100 --if(ipm_fifo_empty = '1')then --is FIFO empty? 101 --next_state <= ST_FIFO_WAIT; 102 if(scan_min >= scan_max) then -- failing here? 103 next_state <= ST_ERR_PAR; 104 elsif(scan_step > scan_diff) then -- failing here? 105 next_state <= ST_ERR_PAR; 106 --elsif ( check_nsamp1 < check_nsamp2 )then 107 -- next_state <= ST_ERR_MEM; 108 else 109 next_state <= ST_PRESCAN; 110 end if; 111 112 --scan the minimum 113 WHEN ST_PRESCAN => 114 --fpga_ready <= '1'; --start writing values to FIFO 115 t_scan_pos <= scan_min; 116 next_state <= ST_SCAN; 117 track_sps <= (others=>'0'); 118 119 --full scanning function 120 WHEN ST_SCAN => 121 if(cmd = SCAN_ABORT_CMD) then 122 next_state <= ST_ERR_SCAN; 123 else 124 sample_en <= '1'; --begin writing values from FIFO 125 if (track_sps >= smp_step) then 126 track_sps <= (others=>'0'); 127 t_scan_pos <= t_scan_pos + scan_step; 128 else 129 track_sps <= track_sps + x"00000001"; -- increment to SPS value 130 end if; 131 132 if(t_scan_pos > scan_max) then 133 --sample_en <= '0'; 134 next_state <= ST_FIFO_WAIT;

Page 21: Appendix C - Code Listing

  21  

135 else 136 --sample_en <= '0'; 137 next_state <= cur_state; 138 end if; 139 end if; 140 141 --Wait until FIFO has finished being read 142 WHEN ST_FIFO_WAIT => 143 if(ipm_fifo_empty = '1') then 144 cmd_reg_reset <= '1'; 145 next_state <= ST_WAIT; 146 else 147 next_state <= cur_state; 148 end if; 149 150 --invalid scan input state 151 WHEN ST_ERR_PAR => 152 if(cmd = x"00") then 153 next_state <= ST_WAIT; 154 else 155 next_state <= cur_state; --I think this is wrong (infinite loop) 156 end if; 157 158 --no memory available 159 WHEN ST_ERR_MEM => 160 if(cmd = ERR_NOMEM) then 161 next_state <= ST_WAIT; 162 else 163 next_state <= cur_state; 164 end if; 165 166 --Something went wrong with the scanning 167 WHEN ST_ERR_SCAN => 168 if(cmd = ERR_FAULTSCAN) then 169 next_state <= ST_WAIT; 170 else 171 next_state <= cur_state; 172 end if; 173 END CASE; 174 cur_state <= next_state; 175 end if; 176 END process; 177 178 scan_pos <= t_scan_pos; 179 status <= state_to_status(cur_state); 180 181 end Behavioral; 182

1.1.7 FSM2.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 FSM2 is 15 PORT( 16 clk : in STD_LOGIC; 17 reset : in STD_LOGIC; 18 ipm_fifo_empty : in STD_LOGIC;

Page 22: Appendix C - Code Listing

  22  

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');

Page 23: Appendix C - Code Listing

  23  

88 track_sps <= (others=>'0'); 89 track_oss <= (others=>'0'); 90 91 if(cmd = SCAN_BEGIN) then 92 next_state <= ST_INIT; 93 else 94 next_state <= ST_WAIT; 95 end if; 96 97 --load values into registers 98 WHEN ST_INIT => 99 t_scan_pos <= (others=>'0'); 100 track_sps <= (others=>'0'); 101 track_oss <= (others=>'0'); 102 103 next_state <= ST_CHK; 104 105 --check for correct parameters 106 WHEN ST_CHK => 107 t_scan_pos <= (others=>'0'); 108 track_sps <= (others=>'0'); 109 track_oss <= (others=>'0'); 110 --if(ipm_fifo_empty = '1')then --is FIFO empty? 111 --next_state <= ST_FIFO_WAIT; 112 --if(scan_min >= scan_max) then -- failing here? 113 -- next_state <= ST_ERR_PAR; 114 --elsif(scan_step > scan_diff) then -- failing here? 115 -- next_state <= ST_ERR_PAR; 116 --elsif ( check_nsamp1 < check_nsamp2 )then 117 -- next_state <= ST_ERR_MEM; 118 --else 119 next_state <= ST_PRESCAN; 120 --end if; 121 122 --scan the minimum 123 WHEN ST_PRESCAN => 124 t_scan_pos <= scan_start; 125 next_state <= ST_SCAN; 126 127 track_sps <= (others=>'0'); 128 track_oss <= (others=>'0'); 129 130 --full scanning function 131 WHEN ST_SCAN => 132 --som_status <= '0'; 133 134 t_scan_pos <= t_scan_pos + scan_step; 135 136 if(t_sample_en='1')then 137 track_sps <= (others=>'0'); 138 else 139 track_sps <= track_sps + 1; 140 end if; 141 142 if(t_overview_en ='1')then 143 track_oss <= (others=>'0'); 144 else 145 track_oss <= track_oss + 1; 146 end if; 147 148 if(cmd = SCAN_ABORT_CMD) then 149 next_state <= ST_ERR_SCAN; 150 elsif (t_scan_pos > scan_stop) then 151 next_state <= ST_FIFO_WAIT; 152 else 153 next_state <= ST_SCAN; 154 end if; 155 156 --Wait until FIFO has finished being read 157 WHEN ST_FIFO_WAIT => 158 t_scan_pos <= (others=>'0'); 159 track_sps <= (others=>'0'); 160 track_oss <= (others=>'0');

Page 24: Appendix C - Code Listing

  24  

161 if(ipm_fifo_empty = '1') then 162 cmd_reg_reset <= '1'; 163 next_state <= ST_WAIT; 164 else 165 next_state <= ST_FIFO_WAIT; 166 end if; 167 168 --invalid scan input state 169 WHEN ST_ERR_PAR => 170 t_scan_pos <= (others=>'0'); 171 track_sps <= (others=>'0'); 172 track_oss <= (others=>'0'); 173 if(cmd = x"00") then 174 next_state <= ST_WAIT; 175 else 176 next_state <= ST_ERR_PAR; 177 end if; 178 179 --no memory available 180 WHEN ST_ERR_MEM => 181 t_scan_pos <= (others=>'0'); 182 track_sps <= (others=>'0'); 183 track_oss <= (others=>'0'); 184 if(cmd = ERR_NOMEM) then 185 next_state <= ST_WAIT; 186 else 187 next_state <= ST_ERR_MEM; 188 end if; 189 190 --Something went wrong with the scanning 191 WHEN ST_ERR_SCAN => 192 t_scan_pos <= (others=>'0'); 193 track_sps <= (others=>'0'); 194 track_oss <= (others=>'0'); 195 if(cmd = ERR_FAULTSCAN) then 196 next_state <= ST_WAIT; 197 else 198 next_state <= ST_ERR_SCAN; 199 end if; 200 END CASE; 201 -- cur_state <= next_state; 202 end if; 203 END process; 204 205 t_sample_en <= '1' when ((t_scan_pos > scan_min) AND 206 (t_scan_pos < scan_max) AND 207 (cur_state = ST_SCAN) AND 208 (track_sps >= smp_step)) 209 else '0'; 210 t_overview_en <= '1' when ((t_scan_pos > scan_start) AND 211 (t_scan_pos < scan_stop) AND 212 (cur_state = ST_SCAN) AND 213 (track_oss >= overview_scan_step)) 214 else '0'; 215 sample_en <= t_sample_en; 216 overview_en <= t_overview_en; 217 scan_pos <= t_scan_pos; 218 status <= state_to_status(cur_state); 219 220 end Behavioral; 221

1.1.8 ipm_fifo.vhdl

1 -------------------------------------------------------------------------------- 2 -- This file is owned and controlled by Xilinx and must be used solely -- 3 -- for design, simulation, implementation and creation of design files -- 4 -- limited to Xilinx devices or technologies. Use with non-Xilinx -- 5 -- devices or technologies is expressly prohibited and immediately -- 6 -- terminates your license. --

Page 25: Appendix C - Code Listing

  25  

7 -- -- 8 -- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" SOLELY -- 9 -- FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY -- 10 -- PROVIDING THIS DESIGN, CODE, OR INFORMATION AS ONE POSSIBLE -- 11 -- IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, XILINX IS -- 12 -- MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE FROM ANY -- 13 -- CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING ANY -- 14 -- RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY -- 15 -- DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE -- 16 -- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR -- 17 -- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF -- 18 -- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -- 19 -- PARTICULAR PURPOSE. -- 20 -- -- 21 -- Xilinx products are not intended for use in life support appliances, -- 22 -- devices, or systems. Use in such applications are expressly -- 23 -- prohibited. -- 24 -- -- 25 -- (c) Copyright 1995-2012 Xilinx, Inc. -- 26 -- All rights reserved. -- 27 -------------------------------------------------------------------------------- 28 -------------------------------------------------------------------------------- 29 -- You must compile the wrapper file IPM_FIFO.vhd when simulating 30 -- the core, IPM_FIFO. When compiling the wrapper file, be sure to 31 -- reference the XilinxCoreLib VHDL simulation library. For detailed 32 -- instructions, please refer to the "CORE Generator Help". 33 34 -- The synthesis directives "translate_off/translate_on" specified 35 -- below are supported by Xilinx, Mentor Graphics and Synplicity 36 -- synthesis tools. Ensure they are correct for your synthesis tool(s). 37 38 LIBRARY ieee; 39 USE ieee.std_logic_1164.ALL; 40 -- synthesis translate_off 41 LIBRARY XilinxCoreLib; 42 -- synthesis translate_on 43 ENTITY IPM_FIFO IS 44 PORT ( 45 rst : IN STD_LOGIC; 46 wr_clk : IN STD_LOGIC; 47 rd_clk : IN STD_LOGIC; 48 din : IN STD_LOGIC_VECTOR(63 DOWNTO 0); 49 wr_en : IN STD_LOGIC; 50 rd_en : IN STD_LOGIC; 51 dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); 52 full : OUT STD_LOGIC; 53 overflow : OUT STD_LOGIC; 54 empty : OUT STD_LOGIC; 55 rd_data_count : OUT STD_LOGIC_VECTOR(10 DOWNTO 0) 56 ); 57 END IPM_FIFO; 58 59 ARCHITECTURE IPM_FIFO_a OF IPM_FIFO IS 60 -- synthesis translate_off 61 COMPONENT wrapped_IPM_FIFO 62 PORT ( 63 rst : IN STD_LOGIC; 64 wr_clk : IN STD_LOGIC; 65 rd_clk : IN STD_LOGIC; 66 din : IN STD_LOGIC_VECTOR(63 DOWNTO 0); 67 wr_en : IN STD_LOGIC; 68 rd_en : IN STD_LOGIC; 69 dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); 70 full : OUT STD_LOGIC; 71 overflow : OUT STD_LOGIC; 72 empty : OUT STD_LOGIC; 73 rd_data_count : OUT STD_LOGIC_VECTOR(10 DOWNTO 0) 74 ); 75 END COMPONENT; 76 77 -- Configuration specification 78 FOR ALL : wrapped_IPM_FIFO USE ENTITY XilinxCoreLib.fifo_generator_v8_3(behavioral) 79 GENERIC MAP (

Page 26: Appendix C - Code Listing

  26  

80 c_add_ngc_constraint => 0, 81 c_application_type_axis => 0, 82 c_application_type_rach => 0, 83 c_application_type_rdch => 0, 84 c_application_type_wach => 0, 85 c_application_type_wdch => 0, 86 c_application_type_wrch => 0, 87 c_axi_addr_width => 32, 88 c_axi_aruser_width => 1, 89 c_axi_awuser_width => 1, 90 c_axi_buser_width => 1, 91 c_axi_data_width => 64, 92 c_axi_id_width => 4, 93 c_axi_ruser_width => 1, 94 c_axi_type => 0, 95 c_axi_wuser_width => 1, 96 c_axis_tdata_width => 64, 97 c_axis_tdest_width => 4, 98 c_axis_tid_width => 8, 99 c_axis_tkeep_width => 4, 100 c_axis_tstrb_width => 4, 101 c_axis_tuser_width => 4, 102 c_axis_type => 0, 103 c_common_clock => 0, 104 c_count_type => 0, 105 c_data_count_width => 13, 106 c_default_value => "BlankString", 107 c_din_width => 64, 108 c_din_width_axis => 1, 109 c_din_width_rach => 32, 110 c_din_width_rdch => 64, 111 c_din_width_wach => 32, 112 c_din_width_wdch => 64, 113 c_din_width_wrch => 2, 114 c_dout_rst_val => "0", 115 c_dout_width => 8, 116 c_enable_rlocs => 0, 117 c_enable_rst_sync => 1, 118 c_error_injection_type => 0, 119 c_error_injection_type_axis => 0, 120 c_error_injection_type_rach => 0, 121 c_error_injection_type_rdch => 0, 122 c_error_injection_type_wach => 0, 123 c_error_injection_type_wdch => 0, 124 c_error_injection_type_wrch => 0, 125 c_family => "spartan6", 126 c_full_flags_rst_val => 1, 127 c_has_almost_empty => 0, 128 c_has_almost_full => 0, 129 c_has_axi_aruser => 0, 130 c_has_axi_awuser => 0, 131 c_has_axi_buser => 0, 132 c_has_axi_rd_channel => 0, 133 c_has_axi_ruser => 0, 134 c_has_axi_wr_channel => 0, 135 c_has_axi_wuser => 0, 136 c_has_axis_tdata => 0, 137 c_has_axis_tdest => 0, 138 c_has_axis_tid => 0, 139 c_has_axis_tkeep => 0, 140 c_has_axis_tlast => 0, 141 c_has_axis_tready => 1, 142 c_has_axis_tstrb => 0, 143 c_has_axis_tuser => 0, 144 c_has_backup => 0, 145 c_has_data_count => 0, 146 c_has_data_counts_axis => 0, 147 c_has_data_counts_rach => 0, 148 c_has_data_counts_rdch => 0, 149 c_has_data_counts_wach => 0, 150 c_has_data_counts_wdch => 0, 151 c_has_data_counts_wrch => 0, 152 c_has_int_clk => 0,

Page 27: Appendix C - Code Listing

  27  

153 c_has_master_ce => 0, 154 c_has_meminit_file => 0, 155 c_has_overflow => 1, 156 c_has_prog_flags_axis => 0, 157 c_has_prog_flags_rach => 0, 158 c_has_prog_flags_rdch => 0, 159 c_has_prog_flags_wach => 0, 160 c_has_prog_flags_wdch => 0, 161 c_has_prog_flags_wrch => 0, 162 c_has_rd_data_count => 1, 163 c_has_rd_rst => 0, 164 c_has_rst => 1, 165 c_has_slave_ce => 0, 166 c_has_srst => 0, 167 c_has_underflow => 0, 168 c_has_valid => 0, 169 c_has_wr_ack => 0, 170 c_has_wr_data_count => 0, 171 c_has_wr_rst => 0, 172 c_implementation_type => 2, 173 c_implementation_type_axis => 1, 174 c_implementation_type_rach => 1, 175 c_implementation_type_rdch => 1, 176 c_implementation_type_wach => 1, 177 c_implementation_type_wdch => 1, 178 c_implementation_type_wrch => 1, 179 c_init_wr_pntr_val => 0, 180 c_interface_type => 0, 181 c_memory_type => 1, 182 c_mif_file_name => "BlankString", 183 c_msgon_val => 1, 184 c_optimization_mode => 0, 185 c_overflow_low => 0, 186 c_preload_latency => 0, 187 c_preload_regs => 1, 188 c_prim_fifo_type => "8kx4", 189 c_prog_empty_thresh_assert_val => 4, 190 c_prog_empty_thresh_assert_val_axis => 1022, 191 c_prog_empty_thresh_assert_val_rach => 1022, 192 c_prog_empty_thresh_assert_val_rdch => 1022, 193 c_prog_empty_thresh_assert_val_wach => 1022, 194 c_prog_empty_thresh_assert_val_wdch => 1022, 195 c_prog_empty_thresh_assert_val_wrch => 1022, 196 c_prog_empty_thresh_negate_val => 5, 197 c_prog_empty_type => 0, 198 c_prog_empty_type_axis => 5, 199 c_prog_empty_type_rach => 5, 200 c_prog_empty_type_rdch => 5, 201 c_prog_empty_type_wach => 5, 202 c_prog_empty_type_wdch => 5, 203 c_prog_empty_type_wrch => 5, 204 c_prog_full_thresh_assert_val => 8189, 205 c_prog_full_thresh_assert_val_axis => 1023, 206 c_prog_full_thresh_assert_val_rach => 1023, 207 c_prog_full_thresh_assert_val_rdch => 1023, 208 c_prog_full_thresh_assert_val_wach => 1023, 209 c_prog_full_thresh_assert_val_wdch => 1023, 210 c_prog_full_thresh_assert_val_wrch => 1023, 211 c_prog_full_thresh_negate_val => 8188, 212 c_prog_full_type => 0, 213 c_prog_full_type_axis => 5, 214 c_prog_full_type_rach => 5, 215 c_prog_full_type_rdch => 5, 216 c_prog_full_type_wach => 5, 217 c_prog_full_type_wdch => 5, 218 c_prog_full_type_wrch => 5, 219 c_rach_type => 0, 220 c_rd_data_count_width => 11, 221 c_rd_depth => 65536, 222 c_rd_freq => 1, 223 c_rd_pntr_width => 16, 224 c_rdch_type => 0, 225 c_reg_slice_mode_axis => 0,

Page 28: Appendix C - Code Listing

  28  

226 c_reg_slice_mode_rach => 0, 227 c_reg_slice_mode_rdch => 0, 228 c_reg_slice_mode_wach => 0, 229 c_reg_slice_mode_wdch => 0, 230 c_reg_slice_mode_wrch => 0, 231 c_underflow_low => 0, 232 c_use_common_overflow => 0, 233 c_use_common_underflow => 0, 234 c_use_default_settings => 0, 235 c_use_dout_rst => 1, 236 c_use_ecc => 0, 237 c_use_ecc_axis => 0, 238 c_use_ecc_rach => 0, 239 c_use_ecc_rdch => 0, 240 c_use_ecc_wach => 0, 241 c_use_ecc_wdch => 0, 242 c_use_ecc_wrch => 0, 243 c_use_embedded_reg => 0, 244 c_use_fifo16_flags => 0, 245 c_use_fwft_data_count => 1, 246 c_valid_low => 0, 247 c_wach_type => 0, 248 c_wdch_type => 0, 249 c_wr_ack_low => 0, 250 c_wr_data_count_width => 14, 251 c_wr_depth => 8192, 252 c_wr_depth_axis => 1024, 253 c_wr_depth_rach => 16, 254 c_wr_depth_rdch => 1024, 255 c_wr_depth_wach => 16, 256 c_wr_depth_wdch => 1024, 257 c_wr_depth_wrch => 16, 258 c_wr_freq => 1, 259 c_wr_pntr_width => 13, 260 c_wr_pntr_width_axis => 10, 261 c_wr_pntr_width_rach => 4, 262 c_wr_pntr_width_rdch => 10, 263 c_wr_pntr_width_wach => 4, 264 c_wr_pntr_width_wdch => 10, 265 c_wr_pntr_width_wrch => 4, 266 c_wr_response_latency => 1, 267 c_wrch_type => 0 268 ); 269 -- synthesis translate_on 270 BEGIN 271 -- synthesis translate_off 272 U0 : wrapped_IPM_FIFO 273 PORT MAP ( 274 rst => rst, 275 wr_clk => wr_clk, 276 rd_clk => rd_clk, 277 din => din, 278 wr_en => wr_en, 279 rd_en => rd_en, 280 dout => dout, 281 full => full, 282 overflow => overflow, 283 empty => empty, 284 rd_data_count => rd_data_count 285 ); 286 -- synthesis translate_on 287 288 END IPM_FIFO_a;

Page 29: Appendix C - Code Listing

  29  

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 "fx2Data_io<0>" LOC="A2" | IOSTANDARD=LVTTL; # PB0/FD0 NET "fx2Data_io<1>" LOC="D6" | IOSTANDARD=LVTTL; # PB1/FD1 NET "fx2Data_io<2>" LOC="C6" | IOSTANDARD=LVTTL; # PB2/FD2 NET "fx2Data_io<3>" LOC="B3" | IOSTANDARD=LVTTL; # PB3/FD3 NET "fx2Data_io<4>" LOC="A3" | IOSTANDARD=LVTTL; # PB4/FD4 NET "fx2Data_io<5>" LOC="B4" | IOSTANDARD=LVTTL; # PB5/FD5 NET "fx2Data_io<6>" LOC="A4" | IOSTANDARD=LVTTL; # PB6/FD6 NET "fx2Data_io<7>" LOC="C5" | IOSTANDARD=LVTTL; # PB7/FD7 NET "fx2Read_out" LOC="F13" | IOSTANDARD=LVTTL; # RDY0/SLRD NET "fx2OE_out" LOC="A15" | IOSTANDARD=LVTTL; # PA2/SLOE NET "fx2GotData_in" LOC="C15" | IOSTANDARD=LVTTL; # CTL2/FLAGC NET "fx2Write_out" LOC="E13" | IOSTANDARD=LVTTL; # RDY1/SLWR NET "fx2GotRoom_in" LOC="A9" | IOSTANDARD=LVTTL; # CTL1/FLAGB NET "fx2PktEnd_out" LOC="C4" | IOSTANDARD=LVTTL; # 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 "sw_in<0>" LOC="A10" | IOSTANDARD=LVTTL; # SW0 NET "sw_in<1>" LOC="D14" | IOSTANDARD=LVTTL; # SW1 NET "sw_in<2>" LOC="C14" | IOSTANDARD=LVTTL; # SW2 NET "sw_in<3>" LOC="P15" | IOSTANDARD=LVTTL; # SW3 NET "sw_in<4>" LOC="P12" | IOSTANDARD=LVTTL; # SW4 NET "sw_in<5>" LOC="R5" | IOSTANDARD=LVTTL; # SW5 NET "sw_in<6>" LOC="T5" | IOSTANDARD=LVTTL; # SW6 NET "sw_in<7>" LOC="E4" | IOSTANDARD=LVTTL; # SW7

Page 30: Appendix C - Code Listing

  30  

#=============================================================================== #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 = "T3" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L62N_D6, Sch name = JA-D0_N NET "som_data<1>" LOC = "R3" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L62P_D5, Sch name = JA-D0_P NET "som_data<2>" LOC = "P6" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L64N_D9, Sch name = JA-D2_N NET "som_data<3>" LOC = "N5" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L64P_D8, Sch name = JA-D2_P NET "som_data<4>" LOC = "V9" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L32N_GCLK28, Sch name = JA-CLK_N NET "som_data<5>" LOC = "T9" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L32P_GCLK29, Sch name = JA-CLK_P NET "som_data<6>" LOC = "V4" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L63N, Sch name = JA-D1_N NET "som_data<7>" LOC = "T4" | IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L63P, Sch name = JA-D1_P 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 VHCDI FPGA UCF #0 BB1-14 25 IO14-P U8 NET "IPM_Data<0>" LOC = "U8"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L41P, Sch name = EXP-IO14_P #1 BB1-13 23 IO13-P M8 NET "IPM_Data<1>" LOC = "M8"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L40P, Sch name = EXP-IO13_P #2 BB2-28 59 IO14-N V8 NET "IPM_Data<2>" LOC = "V8"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L41N_VREF, Sch name = EXP-IO14_N #3 BB2-27 57 IO13-N N8 NET "IPM_Data<3>" LOC = "N8"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L40N, Sch name = EXP-IO13_N #4 BB2-26 56 IO12-N T8 NET "IPM_Data<4>" LOC = "T8"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L31N_GCLK30_D15, Sch name = EXP-IO12_N #5 BB2-25 54 IO11-N V10 NET "IPM_Data<5>" LOC = "V10"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L30N_GCLK0_USERCCLK, Sch name = EXP-IO11_N #6 BB2-24 49 IO10-N T10

Page 31: Appendix C - Code Listing

  31  

NET "IPM_Data<6>" LOC = "T10"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L29N_GCLK2, Sch name = EXP-IO10_N #7 BB2-23 47 IO9-N V11 NET "IPM_Data<7>" LOC = "V11"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L23N, Sch name = EXP-IO9_N #8 BB2-22 46 IO8-N N9 NET "IPM_Data<8>" LOC = "N9"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L22N, Sch name = EXP-IO8_N #9 BB2-21 44 IO7-N P11 NET "IPM_Data<9>" LOC = "P11"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L20N, Sch name = EXP-IO7_N #10 BB2-20 43 IO6-N V12 NET "IPM_Data<10>" LOC = "V12"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L19N, Sch name = EXP-IO6_N #11 BB2-19 41 IO5-N T11 NET "IPM_Data<11>" LOC = "T11"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L16N_VREF, Sch name = EXP-IO5_N #12 BB2-18 40 IO4-N N11 NET "IPM_Data<12>" LOC = "N11"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L15N, Sch name = EXP-IO4_N #13 BB2-17 38 IO3-N V13 NET "IPM_Data<13>" LOC = "V13"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L14N_D12, Sch name = EXP-IO3_N #14 BB2-16 37 IO2-N V15 NET "IPM_Data<14>" LOC = "V15"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = *IO_L5N, Sch name = EXP-IO2_N #15 BB2-15 35 IO1-N V16 NET "IPM_Data<15>" LOC = "V16"| IOSTANDARD=LVTTL; # Bank = 2, Pin name = IO_L2N_CMPMOSI, Sch name = EXP-IO1_N #=============================================================================== # 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;

Page 32: Appendix C - Code Listing

  32  

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 (active-low) when reading from FX2 28 fx2OE_out : out std_logic; -- asserted (active-low) to tell FX2 to drive bus 29 fx2GotData_in : in std_logic; -- asserted (active-high) when FX2 has data for us 30 31 -- When EP8IN selected: 32 fx2Write_out : out std_logic; -- asserted (active-low) when writing to FX2 33 fx2GotRoom_in : in std_logic; -- asserted (active-high) when FX2 has room for more data from us 34 fx2PktEnd_out : out std_logic; -- asserted (active-low) 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

Page 33: Appendix C - Code Listing

  33  

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 downto 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

Page 34: Appendix C - Code Listing

  34  

142 t_IPM_data <= sum(18 downto 3); 143 end block fakefir; 144 145 gain_stage: entity work.adg714s3w 146 port map( 147 clk => bclk, 148 reset => rst_high, 149 reg_data => reg(vga_gain_reg), 150 adg_sclk => adg_sclk, 151 adg_sync => adg_sync, 152 adg_dout => adg_dout, 153 adg_reset => adg_reset 154 ); 155 156 --filter_FIR: entity work.IPM_filt 157 --port map( 158 -- clk => IPM_clk_in, 159 -- rfd => open, 160 -- rdy => open, 161 -- din => IPM_data, 162 -- dout => t_IPM_data 163 --); 164 -- som_start <= t_som_start; 165 -- SOM_bclk <= bclk; 166 --fake values to test 167 -- test_blockram: entity work.analog_interface 168 -- port map( 169 -- dac_clk => bclk, 170 -- adc_clk => IPM_clko, 171 -- dac_data => scan_posit(31 downto 8), 172 -- adc_data => t_IPM_data, 173 -- control => x"00", 174 -- status => open 175 -- ); 176 --SOM Instantiation 177 -- som_inst : entity work.dac_count 178 -- port map( 179 -- scan_pos => scan_posit, 180 -- dac_clk => bclk, 181 -- dac_out => som_data, 182 -- wrld_clk => SOM_wclk 183 -- ); 184 --CLOCK GENERATOR GOES HERE 185 clk_mngr_inst: entity work.clockmanager 186 port map( 187 --CLOCK INPUT 188 CLK_IN1 => clk, 189 --CLOCK OUTPUTS 190 sys_clk => sys_clko, 191 IPM_clk => IPM_clko, 192 SOM_clk => bclk, 193 --Status/Control signals 194 RESET_Clk => rst_high, 195 LOCKED_clk => clk_lck 196 ); 197 198 --IPM FIFO DECLARATION GOES HERE 199 ipm_fifo : entity work.IPM_FIFO 200 PORT MAP ( 201 rst => rst_high, 202 --wr_clk => IPM_clk_in, 203 wr_clk => IPM_clk_in, 204 rd_clk => fx2Clk_in, 205 din => ipm_fifo_in, 206 wr_en => get_sample, 207 rd_en => data_stream_enable, 208 dout => ipm_fifo_out, 209 full => open, --needs work 210 overflow => open, --needs work 211 empty => ipm_fifo_empty, 212 rd_data_count => rd_data_count 213 ); 214

Page 35: Appendix C - Code Listing

  35  

215 ipm_fifo_overview: entity work.IPM_FIFO 216 port map( 217 rst => rst_high, 218 --wr_clk => IPM_clk_in, 219 wr_clk => IPM_clk_in, 220 rd_clk => fx2Clk_in, 221 din => ipm_fifo_in, 222 wr_en => get_overview_sample, 223 rd_en => data_stream_enable_overview, 224 dout => ipm_fifo_out_overview, 225 full => open, --needs work 226 overflow => open, --needs work 227 empty => ipm_fifo_empty_overview, 228 rd_data_count => rd_data_count_overview 229 ); 230 231 som_data <= scan_posit(31 downto 24); 232 ipm_fifo_in <= scan_posit(31 downto 0) & t_IPM_data(15 downto 0) & x"0BAD"; 233 data_stream_enable <= (f2hReady) when chanAddr = "0000001" else '0'; 234 data_stream_enable_overview <= (f2hReady) when chanAddr = "0000010" else '0'; 235 --Generator for 128 registers and for the code for registers to take in new data 236 237 decodeGen: FOR I IN 2 TO 126 GENERATE 238 blk1: block is 239 signal reset_reg : std_logic; 240 begin 241 cmd_rst_gen:if i = 126 generate 242 reset_reg <= cmd_rst or rst_high ; 243 end generate; 244 everything_else: if i < 126 generate 245 reset_reg <= rst_high ; 246 end generate; 247 248 reg_next(i) <= h2fdata when i = CONV_INTEGER(chanAddr) else reg(i); 249 -- Infer registers 250 process(reset_reg, fx2Clk_in, h2fValid) 251 begin 252 if reset_reg='1' then 253 reg(i) <= x"00"; 254 elsif ( rising_edge(fx2Clk_in) ) and h2fValid = '1' then 255 reg(i) <= reg_next(i); 256 end if; 257 end process; 258 end block; 259 END GENERATE; 260 261 t_ipm_fifo_empty <= ipm_fifo_empty AND ipm_fifo_empty_overview; 262 263 --FINITE STATE MACHINE GOES HERE 264 sys_FSM: entity work.FSM2 265 port map( 266 clk => IPM_clk_in, 267 --ipm_clk => IPM_clk_in, 268 reset => rst_high, 269 ipm_fifo_empty => t_ipm_fifo_empty, 270 cmd => reg(uim_cmd_reg), 271 scan_min => t_scan_min, 272 scan_max => t_scan_max, 273 scan_step => t_scan_step, 274 smp_step => t_sps, 275 scan_start => t_scan_start, 276 scan_stop => t_scan_stop, 277 overview_scan_step => t_overview_scan, 278 scan_pos => scan_posit, 279 status => reg(fsm_status), 280 sample_en => get_sample, 281 overview_en => get_overview_sample, 282 -- som_status => open, --t_som_start, 283 cmd_reg_reset => cmd_rst 284 ); 285 286 t_scan_min <= (reg(minval_min_addr +3) 287 & reg(minval_min_addr +2)

Page 36: Appendix C - Code Listing

  36  

288 & reg(minval_min_addr +1) 289 & reg(minval_min_addr +0)); 290 291 t_scan_max <= (reg(maxval_min_addr +3) 292 & reg(maxval_min_addr +2) 293 & reg(maxval_min_addr +1) 294 & reg(maxval_min_addr +0)); 295 296 t_scan_step <= (reg(increment_min_addr +3) 297 & reg(increment_min_addr +2) 298 & reg(increment_min_addr +1) 299 & reg(increment_min_addr +0)); 300 301 t_sps <= (reg(sps_min_addr +3) 302 & reg(sps_min_addr +2) 303 & reg(sps_min_addr +1) 304 & reg(sps_min_addr +0)); 305 306 t_scan_start<= (reg(scanstart_min_addr +3) 307 & reg(scanstart_min_addr +2) 308 & reg(scanstart_min_addr +1) 309 & reg(scanstart_min_addr +0)); 310 311 t_scan_stop<= (reg(scanstop_min_addr +3) 312 & reg(scanstop_min_addr +2) 313 & reg(scanstop_min_addr +1) 314 & reg(scanstop_min_addr +0)); 315 316 t_overview_scan<=(reg(overview_min_addr +3) 317 & reg(overview_min_addr +2) 318 & reg(overview_min_addr +1) 319 & reg(overview_min_addr +0)); 320 321 WITH chanAddr SELECT 322 f2hdata <= ipm_fifo_out when "0000001", 323 ipm_fifo_out_overview when "0000010", 324 reg(fsm_status) when "1111111", 325 reg(CONV_INTEGER(chanAddr)) when others; 326 327 328 329 led_out <= reg(CONV_INTEGER(sw_in(6 downto 0))) when sw_in(7) = '1' 330 else scan_posit(31 downto 24) when sw_in = "00000001" 331 --"0000001" & t_som_start when sw_in(7) = '1' 332 else rd_data_count(10 downto 3); 333 334 h2fReady <= '1'; 335 f2hValid <= '1'; 336 337 338 339 -- CommFPGA module 340 fx2Read_out <= fx2Read; 341 fx2OE_out <= fx2Read; 342 fx2Addr_out(1) <= '1'; -- Use EP6OUT/EP8IN, not EP2OUT/EP4IN. 343 comm_fpga : entity work.comm_fpga 344 port map( 345 -- FX2 interface 346 fx2Clk_in => fx2Clk_in, 347 fx2FifoSel_out => fx2Addr_out(0), 348 fx2Data_io => fx2Data_io, 349 fx2Read_out => fx2Read, 350 fx2GotData_in => fx2GotData_in, 351 fx2Write_out => fx2Write_out, 352 fx2GotRoom_in => fx2GotRoom_in, 353 fx2PktEnd_out => fx2PktEnd_out, 354 355 -- Channel read/write interface 356 chanAddr_out => chanAddr, 357 h2fData_out => h2fData, 358 h2fValid_out => h2fValid, 359 h2fReady_in => h2fReady, 360 f2hData_in => f2hData,

Page 37: Appendix C - Code Listing

  37  

361 f2hValid_in => f2hValid, 362 f2hReady_out => f2hReady 363 ); 364 365 end behavioral; 366 367 368

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

Page 38: Appendix C - Code Listing

  38  

55 56 57 # List any extra directories to look for include files here. 58 # Each directory must be seperated by a space. 59 # Use forward slashes for directory separators. 60 # For a directory that has spaces, enclose it in quotes. 61 EXTRAINCDIRS = 62 63 64 # Compiler flag to set the C Standard level. 65 # c89 = "ANSI" C 66 # gnu89 = c89 plus GCC extensions 67 # c99 = ISO C99 standard (not yet fully implemented) 68 # gnu99 = c99 plus GCC extensions 69 CSTANDARD = -std=gnu99 70 71 72 # Place -D or -U options here 73 #CDEFS = -DF_CPU=$(F_CPU)UL 74 75 76 # Place -I options here 77 CINCS = 78 79 80 81 #---------------- Compiler Options ---------------- 82 # -g*: generate debugging information 83 # -O*: optimization level 84 # -f...: tuning, see GCC manual and avr-libc documentation 85 # -Wall...: warning level 86 # -Wa,...: tell GCC to pass this to the assembler. 87 # -adhlns...: create assembler listing 88 CFLAGS = -g$(DEBUG) 89 CFLAGS += $(CDEFS) $(CINCS) 90 CFLAGS += -O$(OPT) 91 CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums 92 CFLAGS += -Wall -Wstrict-prototypes 93 CFLAGS += -Wa,-adhlns=$(<:.c=.lst) 94 CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) 95 CFLAGS += $(CSTANDARD) 96 97 98 #---------------- Assembler Options ---------------- 99 # -Wa,...: tell GCC to pass this to the assembler. 100 # -ahlms: create listing 101 # -gstabs: have the assembler create line number information; note that 102 # for use in COFF files, additional information about filenames 103 # and function names needs to be present in the assembler source 104 # files -- see avr-libc docs [FIXME: not yet described there] 105 ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 106 107 108 #---------------- Library Options ---------------- 109 # Minimalistic printf version 110 PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min 111 112 # Floating point printf version (requires MATH_LIB = -lm below) 113 PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt 114 115 # If this is left blank, then it will use the Standard printf version. 116 PRINTF_LIB = 117 #PRINTF_LIB = $(PRINTF_LIB_MIN) 118 #PRINTF_LIB = $(PRINTF_LIB_FLOAT) 119 120 121 # Minimalistic scanf version 122 SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min 123 124 # Floating point + %[ scanf version (requires MATH_LIB = -lm below) 125 SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt 126 127 # If this is left blank, then it will use the Standard scanf version.

Page 39: Appendix C - Code Listing

  39  

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 ----------------

Page 40: Appendix C - Code Listing

  40  

200 201 # For simulavr only - target MCU frequency. 202 DEBUG_MFREQ = $(F_CPU) 203 204 # Set the DEBUG_UI to either gdb or insight. 205 # DEBUG_UI = gdb 206 DEBUG_UI = insight 207 208 # Set the debugging back-end to either avarice, simulavr. 209 DEBUG_BACKEND = avarice 210 #DEBUG_BACKEND = simulavr 211 212 # GDB Init Filename. 213 GDBINIT_FILE = __avr_gdbinit 214 215 # When using avarice settings for the JTAG 216 JTAG_DEV = /dev/com1 217 218 # Debugging port used to communicate between GDB / avarice / simulavr. 219 DEBUG_PORT = 4242 220 221 # Debugging host used to communicate between GDB / avarice / simulavr, normally 222 # just set to localhost unless doing some sort of crazy debugging when 223 # avarice is running on a different computer. 224 DEBUG_HOST = localhost 225 226 227 228 #============================================================================ 229 230 231 # Define programs and commands. 232 SHELL = sh 233 CC = avr-gcc 234 OBJCOPY = avr-objcopy 235 OBJDUMP = avr-objdump 236 SIZE = avr-size 237 NM = avr-nm 238 AVRDUDE = avrdude 239 REMOVE = rm -f 240 COPY = cp 241 WINSHELL = cmd 242 243 244 # Define Messages 245 # English 246 MSG_ERRORS_NONE = Errors: none 247 MSG_BEGIN = -------- begin -------- 248 MSG_END = -------- end -------- 249 MSG_SIZE_BEFORE = Size before: 250 MSG_SIZE_AFTER = Size after: 251 MSG_COFF = Converting to AVR COFF: 252 MSG_EXTENDED_COFF = Converting to AVR Extended COFF: 253 MSG_FLASH = Creating load file for Flash: 254 MSG_EEPROM = Creating load file for EEPROM: 255 MSG_EXTENDED_LISTING = Creating Extended Listing: 256 MSG_SYMBOL_TABLE = Creating Symbol Table: 257 MSG_LINKING = Linking: 258 MSG_COMPILING = Compiling: 259 MSG_ASSEMBLING = Assembling: 260 MSG_CLEANING = Cleaning project: 261 262 263 264 265 # Define all object files. 266 OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) 267 268 # Define all listing files. 269 LST = $(SRC:.c=.lst) $(ASRC:.S=.lst) 270 271 272 # Compiler flags to generate dependency files.

Page 41: Appendix C - Code Listing

  41  

273 GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d 274 275 276 # Combine all necessary flags and optional flags. 277 # Add target processor to flags. 278 ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) 279 ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) 280 281 282 283 284 285 # Default target. 286 all: begin gccversion sizebefore build sizeafter end 287 288 build: elf hex eep lss sym 289 290 elf: $(TARGET).elf 291 hex: $(TARGET).hex 292 eep: $(TARGET).eep 293 lss: $(TARGET).lss 294 sym: $(TARGET).sym 295 296 297 298 # Eye candy. 299 # AVR Studio 3.x does not check make's exit code but relies on 300 # the following magic strings to be generated by the compile job. 301 begin: 302 @echo 303 @echo $(MSG_BEGIN) 304 305 end: 306 @echo $(MSG_END) 307 @echo 308 309 310 # Display size of file. 311 HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex 312 ELFSIZE = $(SIZE) -A $(TARGET).elf 313 AVRMEM = avr-mem.sh $(TARGET).elf $(MCU) 314 315 sizebefore: 316 @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ 317 $(AVRMEM) 2>/dev/null; echo; fi 318 319 sizeafter: 320 @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ 321 $(AVRMEM) 2>/dev/null; echo; fi 322 323 324 325 # Display compiler version information. 326 gccversion : 327 @$(CC) --version 328 329 330 331 # Program the device. 332 program: $(TARGET).hex $(TARGET).eep 333 $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) 334 335 336 # Generate avr-gdb config/init file which does the following: 337 # define the reset signal, load the target file, connect to target, and set 338 # a breakpoint at main(). 339 gdb-config: 340 @$(REMOVE) $(GDBINIT_FILE) 341 @echo define reset >> $(GDBINIT_FILE) 342 @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) 343 @echo end >> $(GDBINIT_FILE) 344 @echo file $(TARGET).elf >> $(GDBINIT_FILE) 345 @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)

Page 42: Appendix C - Code Listing

  42  

346 ifeq ($(DEBUG_BACKEND),simulavr) 347 @echo load >> $(GDBINIT_FILE) 348 endif 349 @echo break main >> $(GDBINIT_FILE) 350 351 debug: gdb-config $(TARGET).elf 352 ifeq ($(DEBUG_BACKEND), avarice) 353 @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. 354 @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ 355 $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) 356 @$(WINSHELL) /c pause 357 358 else 359 @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ 360 $(DEBUG_MFREQ) --port $(DEBUG_PORT) 361 endif 362 @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) 363 364 365 366 367 # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. 368 COFFCONVERT=$(OBJCOPY) --debugging \ 369 --change-section-address .data-0x800000 \ 370 --change-section-address .bss-0x800000 \ 371 --change-section-address .noinit-0x800000 \ 372 --change-section-address .eeprom-0x810000 373 374 375 coff: $(TARGET).elf 376 @echo 377 @echo $(MSG_COFF) $(TARGET).cof 378 $(COFFCONVERT) -O coff-avr $< $(TARGET).cof 379 380 381 extcoff: $(TARGET).elf 382 @echo 383 @echo $(MSG_EXTENDED_COFF) $(TARGET).cof 384 $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof 385 386 387 388 # Create final output files (.hex, .eep) from ELF output file. 389 %.hex: %.elf 390 @echo 391 @echo $(MSG_FLASH) $@ 392 $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ 393 394 %.eep: %.elf 395 @echo 396 @echo $(MSG_EEPROM) $@ 397 -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ 398 --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ 399 400 # Create extended listing file from ELF output file. 401 %.lss: %.elf 402 @echo 403 @echo $(MSG_EXTENDED_LISTING) $@ 404 $(OBJDUMP) -h -S $< > $@ 405 406 # Create a symbol table from ELF output file. 407 %.sym: %.elf 408 @echo 409 @echo $(MSG_SYMBOL_TABLE) $@ 410 $(NM) -n $< > $@ 411 412 413 414 # Link: create ELF output file from object files. 415 .SECONDARY : $(TARGET).elf 416 .PRECIOUS : $(OBJ) 417 %.elf: $(OBJ) 418 @echo

Page 43: Appendix C - Code Listing

  43  

419 @echo $(MSG_LINKING) $@ 420 $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) 421 422 423 # Compile: create object files from C source files. 424 %.o : %.c 425 @echo 426 @echo $(MSG_COMPILING) $< 427 $(CC) -c $(ALL_CFLAGS) $< -o $@ 428 429 430 # Compile: create assembler files from C source files. 431 %.s : %.c 432 $(CC) -S $(ALL_CFLAGS) $< -o $@ 433 434 435 # Assemble: create object files from assembler source files. 436 %.o : %.S 437 @echo 438 @echo $(MSG_ASSEMBLING) $< 439 $(CC) -c $(ALL_ASFLAGS) $< -o $@ 440 441 # Create preprocessed source for use in sending a bug report. 442 %.i : %.c 443 $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 444 445 446 # Target: clean project. 447 clean: begin clean_list end 448 449 clean_list : 450 @echo 451 @echo $(MSG_CLEANING) 452 $(REMOVE) $(TARGET).hex 453 $(REMOVE) $(TARGET).eep 454 $(REMOVE) $(TARGET).cof 455 $(REMOVE) $(TARGET).elf 456 $(REMOVE) $(TARGET).map 457 $(REMOVE) $(TARGET).sym 458 $(REMOVE) $(TARGET).lss 459 $(REMOVE) $(OBJ) 460 $(REMOVE) $(LST) 461 $(REMOVE) $(SRC:.c=.s) 462 $(REMOVE) $(SRC:.c=.d) 463 $(REMOVE) .dep/* 464 465 466 467 # Include the dependency files. 468 -include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) 469 470 471 # Listing of phony targets. 472 .PHONY : all begin finish end sizebefore sizeafter gccversion \ 473 build elf hex eep lss sym coff extcoff \ 474 clean clean_list program debug gdb-config 475

1.2.2 USI_I2C_Port.c

1 /* 2 * GccApplication3.c 3 * 4 * Created: 11/1/2012 2:32:46 PM 5 * Author: Mary Hatfield 6 */ 7 8 #include <avr/interrupt.h> 9 //#define F_CPU 8000000UL // Sets up the default speed for delay.h 10 #include <util/delay.h>

Page 44: Appendix C - Code Listing

  44  

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 switch(state){ 79 case INIT: 80 USI_TWI_Master_Initialise(); 81 PORTB |= _BV(P_DAC_RST); //reset, start fresh

Page 45: Appendix C - Code Listing

  45  

82 PORTB &= ~_BV(P_DAC_RST); 83 state = PROGRAM; 84 break; 85 case PROGRAM: 86 shift_out (0x10, 0xFF); //write to MDI 87 shift_out (0x11, 0xFF); 88 shift_out(0x12, 0x21); //(21 MUTE on, 20 MUTE off) 89 shift_out(0x13,0x08); //(08 HV low, 18 HV high) 90 shift_out(0x14,0x11); 91 shift_out(0x15,0x01); 92 shift_out(0x96,0x00); 93 shift_out(0x97,0x00); 94 state = WAIT_FOR_DCM; 95 break; 96 case WAIT_FOR_DCM: 97 i=DCM_GO(); 98 if (i=0) 99 { 100 state=WAIT_FOR_DCM; 101 } 102 else 103 { 104 state=UNMUTE_DAC; 105 } 106 break; 107 case UNMUTE_DAC: 108 shift_out(0x12, 0x20); //UNMUTE 109 shift_out(0x13,0x18); //HV EN HIGH- light LED_3 110 state = CHECKING; 111 // blinkEm(4,P_LED_1); //debug 112 break; 113 case CHECKING: 114 ADCinit(); 115 //check Ain versus Aout, assign diff to int, check int to accepted value 116 result = Read_ADC(); //if good, light LED_4 117 i=DCM_GO(); 118 if (i=0) 119 { 120 state=CHECKING; 121 } 122 else 123 { 124 state=MUTE_DAC; 125 } 126 break; 127 case MUTE_DAC: 128 shift_out(0x12, 0x21); //MUTE 129 shift_out(0x13,0x08); //HV EN LOW- unlight LED_3 130 PORTB |= _BV(P_FPGA_17); //flag FPGA 131 _delay_ms(100); 132 state = WAIT_FOR_DCM; 133 break; 134 default: 135 state = INIT; 136 break; 137 } 138 } 139 return; 140 } 141 142 /*------------------------------------------------------------------------ 143 ** DCM_GO - function to see if DCM is ready 144 ** ---------------------------------------------------------------------*/ 145 int DCM_GO(void){ 146 147 uint8_t but1; 148 uint8_t but1a; 149 uint8_t oldBut=0; 150 int state=0; 151 152 PORTB = _BV(P_FPGA_95); 153 but1 = ~PIN_FPGA & _BV(P_FPGA_95); // look at buttons, invert 154 if (but1 != oldBut)

Page 46: Appendix C - Code Listing

  46  

155 { 156 //_delay_ms(100); // 100ms @ 1MHz clock. 157 but1a = ~PIN_FPGA & _BV(P_FPGA_95); // read again 158 if (but1a == but1) // button has changed 159 { 160 oldBut = but1; 161 if (oldBut > 0) // Switch is pressed 162 { 163 state=1; 164 } 165 } 166 } 167 else 168 { 169 state=0; 170 } 171 return state; 172 } 173 174 175 /*------------------------------------------------------------------------ 176 ** blinkEm - function to blink LED for count passed in 177 ** Assumes that leds are all on the same port. 1MHz Clock rate. 178 ** ---------------------------------------------------------------------*/ 179 void blinkEm( uint8_t count, uint8_t led){ 180 #if 0 181 uint8_t i; 182 while (count > 0){ 183 PORTB |= _BV(led); 184 for (i=0;i<5;i++) 185 { 186 _delay_ms(400); 187 } 188 PORTB &= ~_BV(led); 189 for (i=0;i<5;i++) 190 { 191 _delay_ms(400); 192 } 193 count--; 194 195 } 196 #endif 197 } 198 199 /*------------------------------------------------------------------------ 200 ** shift_out - function to pass DAC commands serially 201 ** _delay_ms(CLK_PERIOD) where the CLK_PERIOD = 200 for now. 202 ** 1MHz Clock rate. 203 ** ---------------------------------------------------------------------*/ 204 void shift_out(int addr, int data){ 205 int i; 206 PORTB &= ~_BV(P_DAC_MS); //set MS to allow writing to MDI 207 //_delay_ms(200); 208 209 for(i=7; i>=0; i--){ 210 211 //clk = 0 212 PORTA &= ~_BV(P_DAC_MC); 213 if ((addr>>i)&(0x01)) 214 PORTA |= _BV(P_DAC_MDI); 215 else 216 PORTA &= ~_BV(P_DAC_MDI); 217 _delay_us(20); 218 //clk = 1; 219 PORTA |= _BV(P_DAC_MC); 220 _delay_us(20); 221 } 222 223 for(i=7; i>=0; i--){ 224 //clk = 0 225 PORTA &= ~_BV(P_DAC_MC); 226 if ((data>>i)&(0x01)) 227 PORTA |= _BV(P_DAC_MDI);

Page 47: Appendix C - Code Listing

  47  

228 else 229 PORTA &= ~_BV(P_DAC_MDI); 230 _delay_us(20); 231 232 //clk = 1; 233 PORTA |= _BV(P_DAC_MC); 234 235 _delay_us(20); 236 } 237 238 PORTB |= _BV(P_DAC_MS); //shut off MDI writing 239 PORTA &= ~_BV(P_DAC_MDI); 240 PORTA &= ~_BV(P_DAC_MC); 241 //_delay_ms(200); 242 } 243 /*------------------------------------------------------------------------ 244 ** ADCinit - function to initialize ADC 245 ** set for differential comparison, ADC4 and ADC5 pin, 246 ** multiplying diff by 20x, clk at 125kHz 247 ** ---------------------------------------------------------------------*/ 248 void ADCinit (void) { 249 ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); 250 ADMUX |= (0 << REFS1) | (0 << REFS0) | (1 << MUX4) | (1 << MUX2); 251 ADCSRA |= (1 << ADEN); 252 _delay_us(5); 253 } 254 /*------------------------------------------------------------------------ 255 ** Read_ADC - function to begin ADC conversions 256 ** 257 ** ---------------------------------------------------------------------*/ 258 unsigned long Read_ADC(void) { 259 uint16_t adc_rez=0; 260 ADCSRA |= (1 << ADSC); // Start AD Conversions 261 while ( TSTBIT(ADCSRA, ADSC)); 262 adc_rez = ADCL+256*ADCH; 263 return(adc_rez); 264 } 265 266

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 )

Page 48: Appendix C - Code Listing

  48  

28 { 29 PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state. 30 PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state. 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 Two-wire mode. 38 (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter 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.

Page 49: Appendix C - Code Listing

  49  

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 USI 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 USI 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 empty 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;

Page 50: Appendix C - Code Listing

  50  

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 address 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 decremented 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 bus. 204 } 205 } 206 else 207 { 208 USI_TWI_state.addressMode = FALSE; // Only perform address transmission once. 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 performed. 220 { 221 USIDR = 0xFF; // Load NACK to confirm End Of Transmission. 222 } 223 else 224 { 225 USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low. 226 } 227 USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK. 228 }

Page 51: Appendix C - Code Listing

  51  

229 }while( --msgSize) ; // Until all data sent/received. 230 231 if (!USI_TWI_Master_Stop()) 232 { 233 return (FALSE); // Send a STOP condition on the TWI bus. 234 } 235 236 /* Transmission successfully completed*/ 237 return (TRUE); 238 } 239 240 /*--------------------------------------------------------------- 241 Core function for shifting data in and out from the USI. 242 Data to be sent has to be placed into the USIDR prior to calling 243 this function. Data read, will be return'ed from the function. 244 ---------------------------------------------------------------*/ 245 unsigned char USI_TWI_Master_Transfer( unsigned char temp ) 246 { 247 USISR = temp; // Set USISR according to temp. 248 // Prepare clocking. 249 temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled 250 (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. 251 (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source. 252 (1<<USITC); // Toggle Clock Port. 253 do 254 { 255 _delay_us(T2_TWI); 256 USICR = temp; // Generate positve SCL edge. 257 while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high. 258 _delay_us(T4_TWI); 259 USICR = temp; // Generate negative SCL edge. 260 }while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete. 261 262 _delay_us(T2_TWI); 263 temp = USIDR; // Read out data. 264 USIDR = 0xFF; // Release SDA. 265 DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output. 266 267 return temp; // Return the data from the USIDR 268 } 269 /*--------------------------------------------------------------- 270 Function for generating a TWI Start Condition. 271 ---------------------------------------------------------------*/ 272 unsigned char USI_TWI_Master_Start( void ) 273 { 274 /* Release SCL to ensure that (repeated) Start can be performed */ 275 PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. 276 while( !(PORT_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high. 277 _delay_us(T2_TWI); 278 279 /* Generate Start Condition */ 280 PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW. 281 _delay_us(T4_TWI); 282 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 283 PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. 284 285 #ifdef SIGNAL_VERIFY 286 if( !(USISR & (1<<USISIF)) ) 287 { 288 USI_TWI_state.errorState = USI_TWI_MISSING_START_CON; 289 return (FALSE); 290 } 291 #endif 292 return (TRUE); 293 } 294 /*--------------------------------------------------------------- 295 Function for generating a TWI Stop Condition. Used to release 296 the TWI bus. 297 ---------------------------------------------------------------*/ 298 unsigned char USI_TWI_Master_Stop( void ) 299 { 300 PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low. 301 PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.

Page 52: Appendix C - Code Listing

  52  

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 byte. 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

Page 53: Appendix C - Code Listing

  53  

52 void USI_TWI_Master_Initialise( void ); 53 unsigned char USI_TWI_Start_Random_Read( unsigned char * , unsigned char ); 54 unsigned char USI_TWI_Start_Read_Write( unsigned char * , unsigned char ); 55 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 glib-2.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 glib-2.0 gtkdatabox ) 13 echo "it's over"

1.3.3 dcmusb.c

1 #include "dcmusb.h" 2 #include <stdio.h> 3 #include <stdint.h> 4 #include <stdlib.h> 5 #include "libfpgalink.h" 6 7 #define TIMEOUT_MS 1000 8 #define BUFFER_SIZE 1024 9 10 uint8 *buffer; 11 const char *error = NULL; 12 bool isCommCapable; 13 14 int fpga_init(void) 15 { 16 //fpgalink initialization function.required in order for proper communication to occur

Page 54: Appendix C - Code Listing

  54  

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 communicate 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", xsvfFile, 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 NeroJTAG\n", vp); 85 //FAIL(19); 86 rv = status;

Page 55: Appendix C - Code Listing

  55  

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 error 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;

Page 56: Appendix C - Code Listing

  56  

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);

Page 57: Appendix C - Code Listing

  57  

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 USB-related problem.(%d)\n",rv); 229 break; 230 case FL_PROTOCOL_ERR: printf("libFPGAlink: The device is probably not a valid \b FPGALink device.(%d)\n",rv); 231 break; 232 case FL_SYNC_ERR: printf("libFPGAlink: The library was unable to synchronise the device's bulk endpoints.(%d)\n",rv); 233 break; 234 case FL_FX2_ERR: printf("libFPGAlink: There was some problem talking to the FX2 chip.(%d)\n",rv); 235 break; 236 case FL_JTAG_ERR: printf("libFPGAlink: There was some problem with the NeroJTAG interface.(%d)\n",rv); 237 break; 238 case FL_FILE_ERR: printf("libFPGAlink: There was a file-related 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 unsupported command.(%d)\n",rv); 249 break; 250 case FL_UNSUPPORTED_DATA_ERR: printf("libFPGAlink: The XSVF file contains an unsupported XENDIR or XENDDR.(%d)\n",rv); 251 break; 252 case FL_UNSUPPORTED_SIZE_ERR: printf("libFPGAlink: The XSVF file requires more buffer 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 report 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 /* Team Spectrum UIM to DCM interface definition */ 2 /* Kevin Nicotera and Jacob Dilles */ 3 /* 9/7/2012 */ 4 #include "libfpgalink.h" 5 6 //call this first to initialize communication with the fpga 7 int fpga_init(void); 8 9 //connect to FPGA 10 //pass pointer to pointer to flContext and fpga_connect will initialize the struct 11 int fpga_connect(const char *vp, struct FLContext **handle); 12 13 //disconnect from FPGA 14 int fpga_disconnect(struct FLContext *handle); 15

Page 58: Appendix C - Code Listing

  58  

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 *buf); 40 41 void showFPGAerror(int rv);

1.3.5 dcmusb_unitTest.c

1 #include "dcmusb.h" 2 #include <stdio.h> 3 #include "libfpgalink.h" 4 #define SCAN_MIN_REG (0x32) 5 #define SCAN_MAX_REG (0x36) 6 #define SCAN_STEP_REG (0x40) 7 #define SPS_REG (0x44) 8 #define UI_CMD_REG (0x7E) 9 #define FPGA_CMD_REG (0x7F) 10 #define STREAM_REG (0x00) 11 12 #define CMD_START (0x53) 13 #define STATUS_IDLE (0x00) 14 #define CMD_ABORT (0x00) 15 #define BAD_PARAM (0x60) 16 17 void debug(int step); 18 int main(void) 19 { 20 struct FLContext *handle = NULL; 21 const char *vp = "1443:0007"; 22 char regValue; 23 char buff[10000]; 24 int i,num=1; 25 printf("FPGALink device %s\n",vp); 26 debug(0); 27 fpga_init(); 28 debug(1); 29 fpga_connect(vp,&handle); 30 debug(2); 31 //printf("%ld\n",sizeof(int)); 32 fpga_wrReg8(handle,SCAN_MIN_REG,num); 33 //fpga_rdStream(struct FLContext *handle, uint32 timeout, uint8 chan, uint32 count, uint8 *buf) 34 for(num=0; num<1000; num++){ 35 fpga_rdStream(handle,1000,STREAM_REG,10000,buff); 36 for(i=0;i<10000;i++){ 37 if(buff[i]){ 38 printf("got some data: %d\n",buff[i]); 39 } 40 }

Page 59: Appendix C - Code Listing

  59  

41 } 42 debug(3); 43 fpga_disconnect(handle); 44 debug(4); 45 } 46 void debug(int step) 47 { 48 printf("at step %d\n",step); 49 }  

1.3.6 dosa.c

1 #include "support.h" 2 #define DATA_LEN (8200) 3 #define OVERVIEW_DATA_LEN (4000) 4 #define OVERVIEW_SCAN_STEP (((1<<31)/OVERVIEW_DATA_LEN)*2) 5 #define START_VALUE_DEF (0) 6 #define STOP_VALUE_DEF (0xFFFFFF00) 7 #define REFRESH_RATE_DEF (10)/*hertz*/ 8 #define IPM_CLK_FREQ_DEF (25000000) 9 #define GAIN_STAGE (7) 10 //#define PRNTTEST 11 #define FTDI_COMM (1) 12 //#define NO_PERFORM 13 14 15 uint32_t STOP_VALUE,START_VALUE,IPM_CLK_FREQ,REFRESH_RATE,SCAN_STEP; 16 static int width,center; 17 _scanStr s; 18 int context, str_len, text_pos, interval=100, slow_interval=4000, context, entry_num=0, rotary; 19 int settings_flag = 1, gain; 20 const char* str2,*begin_entry = "0000000.000"; 21 static const char gain_lookup[16] = {0x00,0x81,0x42,0xC3, 22 0x24,0xA5,0x66,0xE7, 23 0x18,0x99,0x5A,0xDB, 24 0x3C,0xBD,0x7E,0xFF}; 25 const guint grlen = DATA_LEN-10; 26 float x[DATA_LEN],y[DATA_LEN],ox[DATA_LEN],oy[DATA_LEN],ramp[DATA_LEN],low_marker[2] 27 ,high_marker[2]; 28 static float low_marker_height[]={0,ADC_MAX},high_marker_height[]={0,ADC_MAX}; 29 static char* label_names[] = {"Run Mode","Window","Samples/FSR","Offset","Laser Wavelength", 30 "Mirror Reflect.","Mirror Spacing","Min Voltage","Max Voltage", 31 "Gain","FSR","Finesse"}; 32 char *volt_div_label = "Hz/Div: 0",*amp_div_label = "A/Div: 0", 33 *hertz_rate_label = "Hz Rate: 0",pixel_diff_str,amp_diff_str,hz_diff_str; 34 35 static char* setting_names[] = {"setting1","setting2","Save configuration","Save data"}; 36 volatile unsigned int drawing; 37 struct FLContext *handle = NULL; 38 39 /******* This function is called by exit(int) *****/ 40 void onExit (void) 41 { 42 int rv; 43 do{ 44 fpga_wrReg8(handle,GPIO_REG,HV_OFF); 45 }while(!fpga_rdReg8(handle,GPIO_REG,&rv) || !rv); 46 fpga_wrReg8(handle,UI_CMD_REG,CMD_ABORT);//stop the fpga from running 47 fpga_disconnect(handle); 48 printf ("Closing FPGA safely and exiting program\n"); 49 // should call gtk_main_quit() here 50 } 51 52 int main( int argc, char **argv ) 53 { 54 /****************************************/ 55 /* Local Variables to the main function */ 56 /****************************************/

Page 60: Appendix C - Code Listing

  60  

57 int i; 58 59 if(load_ini_config()){ 60 //complain 61 } 62 63 /************************************************/ 64 /* Initializations for GTK+ and the main window */ 65 /************************************************/ 66 gtk_init( &argc, &argv ); 67 //Create Base Design: 68 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //create top level window 69 gtk_widget_set_size_request (window, 1060, 600);//set size of window 70 g_signal_connect (GTK_OBJECT (window), "destroy", 71 G_CALLBACK (gtk_main_quit), NULL);//allow user to close window 72 gtk_window_set_title (GTK_WINDOW (window), 73 "Team Spectrum: Digital Optical Spectrum Analyzer");//set title of window 74 75 /****************************************************************/ 76 /* Set Up Graphing Area of Main Window */ 77 /* This section lays out the graphing are of the main window */ 78 /* as specified in the design document */ 79 /****************************************************************/ 80 //Create split between graphing area and settings area 81 GtkWidget *hpane1 = gtk_hpaned_new(); 82 gtk_container_add (GTK_CONTAINER (window), hpane1); 83 84 //Create vertical box area for both graphs 85 GtkWidget *graph_vbox = gtk_vbox_new(FALSE,0); 86 87 //pack with respect to beginning of hpane(leftmost) 88 gtk_paned_add1(GTK_PANED(hpane1),graph_vbox); 89 90 /********************************************************************************************/ 91 /* High Resolution Graph Settings */ 92 /*This area is to set up the high resolution graph. This will allow someone */ 93 /*to obtain a better visual of information of certain parts of the optical spectrum */ 94 /********************************************************************************************/ 95 //create databox for high resolution picture of selected spectrum 96 gtk_databox_create_box_with_scrollbars_and_rulers ( 97 &databox_highres, &databoxcontainer_highres, 98 FALSE, FALSE, TRUE, TRUE); 99 //settings for high res graph 100 gtk_databox_set_total_limits (GTK_DATABOX(databox_highres),0, 250000, 300, 0); 101 gtk_box_pack_start(GTK_BOX(graph_vbox), databoxcontainer_highres, 0, 0, 0 ); 102 //force a minimum size for the graph 103 gtk_widget_set_size_request(databoxcontainer_highres,700,450); 104 //allow for zooming 105 gtk_databox_set_enable_zoom (GTK_DATABOX(databox_highres), TRUE); 106 //hopefully get a grid 107 GtkDataboxGraph* high_res_gr = gtk_databox_grid_new (20, 40, &gridColor, 0); 108 //set background color 109 gtk_widget_modify_bg(databox_highres, GTK_STATE_NORMAL,&bgColor); 110 111 /********************************************************************************************/ 112 /* Center Section for Volts/Div and other Information */ 113 /* This will display information for the graphs including (hopefully) x and y coordinates */ 114 /* and definitely will include Volts/Div as specified in design document */ 115 /********************************************************************************************/ 116 //center area for selected data 117 GtkWidget *hbox1 = gtk_hbox_new(FALSE,0); 118 //gtk_paned_add2(GTK_PANED(hpane1),vbox2); 119 gtk_box_pack_start(GTK_BOX(graph_vbox), hbox1, 0,0,0);

Page 61: Appendix C - Code Listing

  61  

120 GtkWidget *lowerGraphDiv = gtk_label_new("Hz/Div: "); 121 GtkWidget *upperGraphDiv = gtk_label_new("A/Div: "); 122 GtkWidget *graphRate = gtk_label_new("Hz Rate: "); 123 gtk_box_pack_start(GTK_BOX(hbox1),lowerGraphDiv,1,0,0); 124 gtk_box_pack_start(GTK_BOX(hbox1),upperGraphDiv,1,0,0); 125 gtk_box_pack_start(GTK_BOX(hbox1),graphRate,1,0,0); 126 127 /****************************************************************************************/ 128 /* Low Resolution Graph Settings */ 129 /* This area is to set up the high resolution graph. This will allow */ 130 /* the user to "see the big picture" of the optical spectrum */ 131 /****************************************************************************************/ 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;

Page 62: Appendix C - Code Listing

  62  

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

Page 63: Appendix C - Code Listing

  63  

260 /* inputs: fpga scan struct */ 261 /* outputs: errors from writing to the FPGA */ 262 /* Function: writes information to the FPGA to determine */ 263 /* when to start,stop,step size,samples per step */ 264 /****************************************************************/ 265 int start_scan(scanStr s){ 266 int rv = 0; 267 rv = fpga_rdReg8(handle,FPGA_CMD_REG,&(s->status)); 268 //rv = fpga_wrReg8(handle,GAIN_REG,0); 269 /* Min value for the overview (0) */ 270 rv = fpga_wrReg32(handle,START_REG,START_VALUE); 271 /* Max value for the overview (max int value) */ 272 rv = fpga_wrReg32(handle,STOP_REG,((uint32_t)STOP_VALUE)-(s->scan_step)); 273 /* create reasonable step size to handle drawing */ 274 rv = fpga_wrReg32(handle,OVERVIEW_STEP_REG,(s->over_per_step)-1);//scan_step for overview 275 276 rv = fpga_wrReg32(handle,SCAN_MIN_REG,s->scan_min);//scan_min 277 rv = fpga_wrReg32(handle,SCAN_MAX_REG,s->scan_max);//scan_max 278 rv = fpga_wrReg32(handle,SCAN_STEP_REG,s->scan_step);//samples per step 279 rv = fpga_wrReg32(handle,SPS_REG,(s->samples_per_step)-1);//scan_step 280 281 rv = fpga_rdReg8(handle,FPGA_CMD_REG,&(s->status)); 282 rv = fpga_wrReg8(handle,GAIN_REG,gain_lookup[gain]); 283 rv = fpga_wrReg8(handle,UI_CMD_REG,CMD_START); 284 rv = fpga_rdReg8(handle,FPGA_CMD_REG,&(s->status)); 285 #ifdef PRNTTEST 286 printf("Line 274 status=%d\n",s->status); 287 #endif 288 return rv; 289 } 290 291 /************************************************************************/ 292 /* read_data Function */ 293 /* inputs: buffer register, x array, y array */ 294 /* outputs: return value of error(zero for no error) */ 295 /* Function: reads either the overview buffer register or high */ 296 /* resolution register for all of the values to graph */ 297 /************************************************************************/ 298 #define INVERSE_WORD ( (1.0) / (double)(1<<16) ) 299 #define SCALE_ADC_Y(y) (float)(((double)(((uint32_t)(y))>>16))*INVERSE_WORD) 300 int read_data(int reg,float *x,float *y,scanStr s) 301 { 302 int i,rv=0; 303 static uint8_t buff[DATA_LEN*8 + 64]; 304 fpga_rdStream(handle,FPGA_TIMEOUT,reg, DATA_LEN*8+8, buff); 305 uint32_t * ibuf = (uint32_t*) buff; 306 uint32_t xt, yt; 307 uint32_t miny=1<<30,maxy=0, minx=1<<30,maxx=0; 308 /* save the values as a float for graphing using gtkdatabox */ 309 //if(reg == OVERVIEW_STREAM_REG){or 310 for(i = 0; i < DATA_LEN; i++){ 311 xt = ntohl((uint32_t) *(ibuf++)); 312 yt = ntohl((uint32_t) *(ibuf++)); 313 miny = yt < miny ? yt : miny; 314 maxy = yt > maxy ? yt : maxy; 315 minx = xt < minx ? xt : minx; 316 maxx = xt > maxx ? xt : maxx; 317 318 if( (yt&0xFFF) == 0xBAD) 319 { 320 y[rv] = SCALE_ADC_Y(yt); 321 //y[rv] = (float)(yt&~(0xfff)); 322 //ramp[rv] = (float)(xt); // find me a better home 323 x[rv] = (float)xt; // scale factor eventually 324 rv++; 325 } 326 } 327 328 #ifdef PRNTTEST 329 printf("X: %u - %u Y: %f - %f\n", minx, maxx,SCALE_ADC_Y(miny),SCALE_ADC_Y(maxy)); 330 printf("finished for loop (got %d valid)\n",rv); 331 #endif 332 return rv;

Page 64: Appendix C - Code Listing

  64  

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);

Page 65: Appendix C - Code Listing

  65  

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,&cyan,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_MAX,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){

Page 66: Appendix C - Code Listing

  66  

475 uim_led_toggle(BTN_POWER); 476 return FALSE; 477 } 478 479 /********************************************************************************/ 480 /* rotary encoder button Functions */ 481 /* inputs: nothing */ 482 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 483 /* Function: These functions switch the context of the UIM-E finite state */ 484 /* machine. They include toggles to simplify the mechanism */ 485 /********************************************************************************/ 486 gint uim_pressed_k0(void){ 487 static int x = 0; 488 /* If your in the Home State this will switch between the home state */ 489 /* and the Field Select State */ 490 if(context == 0){ 491 x = 1-x; 492 if(x == 1){ 493 context = 1; 494 } 495 else{ 496 context = 0; 497 } 498 } 499 /* If your in the Field Select State this will switch between the home state */ 500 /* and the Field Select State */ 501 else if(context == 1){ 502 x = 1-x; 503 if(x ==1){ 504 context = 1; 505 } 506 else{ 507 context = 0; 508 } 509 } 510 /* If your in the Edit Field State this will switch between the edit field state*/ 511 /* and the Field Select State */ 512 else if(context == 2){ 513 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); 514 context = 1; 515 } 516 return FALSE; 517 } 518 519 gint uim_pressed_k1(void){ 520 static int x = 0; 521 /* This will save the modified value and return from the Edit Field State to*/ 522 /* the Field Sele(2*width)/(ss*DATA_LEN)ct state */ 523 if(context == 1){ 524 x = 1-x; 525 if(x == 1){ 526 str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); 527 entry_pos[entry_num] = 7; 528 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]); 529 context = 2; 530 } 531 else if(x == 0){ 532 context = 1; 533 } 534 } 535 else if(context == 2){ 536 context == 1; 537 } 538 return FALSE; 539 } 540 541 /************************************************************************************/ 542 /* rotary encoder rotation Functions */ 543 /* inputs: integer value(positive or negative) denoting */ 544 /* denoting the number or ticks on the rotary encoder */ 545 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 546 /* Function: These functions apply rotary movement to the text entries */

Page 67: Appendix C - Code Listing

  67  

547 /************************************************************************************/ 548 gint uim_rotated_k0(int n) 549 { 550 rotary = 0; 551 /* Run functions dependent on the state the UIM is in at the time */ 552 if(context == 0){ 553 //printf("in home context\n"); 554 uim_state_home(n); 555 } 556 else if(context == 1){ 557 uim_state_field_select(n); 558 } 559 else if(context == 2){ 560 uim_state_edit_field(n); 561 } 562 else if(context == 5){ 563 uim_settings_choice(n); 564 } 565 return FALSE; 566 } 567 568 gint uim_rotated_k1(int n){ 569 rotary = 1; 570 /* Run functions dependent on the state the UIM is in at the time*/ 571 if(context == 0){ 572 uim_state_home(n); 573 } 574 else if(context == 2){ 575 uim_state_edit_field(n); 576 } 577 else if(context == 5){ 578 uim_settings_choice(n); 579 } 580 return FALSE; 581 } 582 583 /************************************************************************************/ 584 /* Number Pad Functions */ 585 /* inputs: character that should be a ASCII number or * or # */ 586 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 587 /* Function: This function will apply a number to the */ 588 /* text entry that is selected */ 589 /************************************************************************************/ 590 gint uim_pressed_number(char num){ 591 if(context == 0){ 592 gain = num-'0'; 593 printf("changing the gain level to %d (%x)\n",gain,gain_lookup[gain]); 594 } 595 if(context == 3){ 596 /* This will add values to the text entry selected*/ 597 char str[] = {num,0}; 598 gtk_editable_insert_text(GTK_EDITABLE(button_entry[entry_num]),str,1,entry_pos); 599 if(entry_pos[entry_num] < 11){ 600 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]++); 601 } 602 else{ 603 context = 1; 604 } 605 } 606 else{ 607 printf("this isn't implemented yet\n"); 608 } 609 return FALSE; 610 } 611 612 /* If the user presses star then the system will either change context */ 613 /* or clear the text entry and change the context to manually change the value */ 614 gint uim_pressed_star(void){ 615 if(context == 1){ 616 context = 3; 617 str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); 618 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),"");

Page 68: Appendix C - Code Listing

  68  

619 } 620 else if(context == 3){ 621 context = 1; 622 } 623 else{ 624 printf("this function hasn't been implemented yet\n"); 625 } 626 return FALSE; 627 } 628 629 gint uim_pressed_pound(void){ 630 if(context == 3){ 631 /* Delete a value or save value and go back to field select state*/ 632 if (entry_num >= 8){ 633 entry_num = 8; 634 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); 635 context = 1; 636 } else{ 637 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]--); 638 } 639 } 640 else if(context == 2){ 641 /* Save the value and go back to field select state */ 642 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); 643 context = 1; 644 } 645 return FALSE; 646 } 647 648 /************************************************************************************/ 649 /* UIM STATE HOME Function */ 650 /* inputs: integer value that is positive or negative */ 651 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 652 /* Function: Move the cursor on the graphs to obtain expansion and offset */ 653 /************************************************************************************/ 654 gint uim_state_home(int n){ 655 /* Get two pixels values that are right next to each other then subtract them */ 656 /* to get the distance of one pixel for scaling purposes */ 657 //pixel1 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center); 658 //pixel2 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center-1); 659 //pixel_diff= pixel1 - pixel2; 660 #undef MAX_WIDTH 661 #define MAX_WIDTH ((STOP_VALUE_DEF-START_VALUE_DEF)/2) 662 //static int64_t width=MAX_WIDTH/2,center=START_VALUE_DEF+MAX_WIDTH; 663 664 int64_t pixel_diff = width/MIN_WIDTH; 665 int64_t temp_width,temp_center; 666 if(abs(n) > 8){ 667 n *= 2; 668 } 669 n *= 2; 670 if(rotary == 1){ 671 width += pixel_diff*n; 672 if(width+center > STOP_VALUE){ 673 width = STOP_VALUE-center-1; 674 } 675 printf("The width+center is: %ld\n",width); 676 if(center-width < 0){ 677 width = center-1; 678 } 679 printf("The center-width is: %ld\n",width); 680 if(width < MIN_WIDTH){ 681 width = MIN_WIDTH; 682 } 683 printf("The smallest width is: %ld\n",width); 684 if(!((2*width)/(SCAN_STEP*DATA_LEN))){ 685 width = (SCAN_STEP*DATA_LEN)>>1; 686 } 687 } 688 else if(rotary == 0){ 689 center += pixel_diff*n; 690 if(center < width){

Page 69: Appendix C - Code Listing

  69  

691 center = width + 1; 692 } 693 if(center > (STOP_VALUE-width)){ 694 center = STOP_VALUE-width-1; 695 } 696 } 697 698 //set the values on the middle section in between the graphs 699 //pixel_diff2 = 5*pixel_diff; 700 //amp1 = gtk_databox_pixel_to_value_y(GTK_DATABOX(databox_highres),0); 701 //amp2 = gtk_databox_pixel_to_value_y(GTK_DATABOX(databox_highres),5); 702 703 //sprintf(&pixel_diff_str,"Hz/Div: %f",pixel_diff2); 704 //sprintf(&amp_diff_str,"Amp/Div: %f",amp_diff); 705 //sprintf(&hz_diff_str,"Hz Rate: %f",pixel_diff); 706 //gtk_label_set_text(GTK_LABEL(lowerGraphDiv),&pixel_diff_str); 707 //gtk_label_set_text(GTK_LABEL(upperGraphDiv),&amp_diff_str); 708 //gtk_label_set_text(GTK_LABEL(graphRate),&hz_diff_str); 709 scan_init((int)center,(int)width,DATA_LEN); 710 return FALSE; 711 } 712 713 /************************************************************************************/ 714 /* UIM STATE FIELD SELECT Function */ 715 /* inputs: integer value that is positive or negative */ 716 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 717 /* Function: Rotate through the text entry fields next to the graphs */ 718 /************************************************************************************/ 719 gint uim_state_field_select(int n){ 720 static int last = 0; 721 /* make a text entry grab mouse focus manually since there will be no mouse */ 722 if(n == last){ 723 last = 0; 724 if(n >= DIR_CW){ 725 if(entry_num >= 9){ 726 entry_num = 1; 727 gtk_widget_grab_focus(button_entry[entry_num]); 728 } 729 else{ 730 entry_num = entry_num + 1; 731 gtk_widget_grab_focus(button_entry[entry_num]); 732 } 733 } 734 else if(n <= DIR_CCW){ 735 if(entry_num <= 1){ 736 entry_num = 9; 737 gtk_widget_grab_focus(button_entry[entry_num]); 738 } 739 else{ 740 entry_num = entry_num - 1; 741 gtk_widget_grab_focus(button_entry[entry_num]); 742 } 743 } 744 } 745 else{ 746 //slow down the rotation so it is one text entry per click 747 last = n; 748 } 749 return FALSE; 750 } 751 752 /************************************************************************************/ 753 /* UIM STATE EDIT FIELD Function */ 754 /* inputs: integer value that is positive or negative */ 755 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 756 /* Function: add/subtract one on the text entry value on each rotary click */ 757 /* wrapping the carry to the next significant bit and hold at */ 758 /* MAX_VALUE(999999.999) and MIN_VALUE(000000.000) also change */ 759 /* the position to start adding and subtracting */ 760 /************************************************************************************/ 761 gint uim_state_edit_field(int n){ 762 static int last = 0; 763 /* add/subtract rotary encoder is being used*/

Page 70: Appendix C - Code Listing

  70  

764 if(rotary == 1){ 765 int i,j,store=-1,flag=0; 766 char* str3 = gtk_editable_get_chars(GTK_EDITABLE(button_entry[entry_num]),0,11); 767 i = entry_pos[entry_num]; 768 if(n == last){ 769 last = 0; 770 /* Add to the value in the text entry with carry to next value*/ 771 if(n >= DIR_CW){ 772 do{ 773 if(str3[i] == '.'){ 774 str3[i] = '.'; 775 i=i-n; 776 flag = 1; 777 } 778 else{ 779 str3[i]=str3[i]+n; 780 if(str3[i] > '9'){ 781 if(i == 0){ 782 str3[i] = '9'; 783 flag = 0; 784 } 785 else{ 786 str3[i] = '0'; 787 i=i-n; 788 flag = 1; 789 } 790 } 791 else{ 792 flag = 0; 793 } 794 } 795 }while(flag); 796 } 797 /* Subtract from the value in the text entry with carry */ 798 else if(n <= DIR_CCW){ 799 for(j=0;j<=i;j++){ 800 if(str3[j] > '0'){ 801 store = j; 802 } 803 } 804 do{ 805 if(str3[i] == '.'){ 806 str3[i] = '.'; 807 i--; 808 flag = 1; 809 } 810 else if(store == -1){ 811 str3[i] = '0'; 812 flag = 0; 813 } 814 else if(store >= 0){ 815 if(i == store){ 816 str3[i]--; 817 } 818 else if(i > store){ 819 str3[i] = '9'; 820 } 821 if(i != 0){ 822 i--; 823 flag = 1; 824 } 825 else{ 826 flag = 0; 827 } 828 } 829 }while(flag); 830 } 831 } 832 else{ 833 last = n; 834 } 835 /* set the text entry with the updated value and change the position if necessary */ 836 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str3);

Page 71: Appendix C - Code Listing

  71  

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 }

Page 72: Appendix C - Code Listing

  72  

905 906 /****************************************************************************************/ 907 /* Settings Window Callback Functions */ 908 /* inputs: nothing */ 909 /* outputs: gint (either TRUE OR FALSE though always will be FALSE) */ 910 /* Function: save the configuration values to a file (9 text entries on the right) */ 911 /* also save data from the fpga to a different file */ 912 /****************************************************************************************/ 913 gint cb_save_config(void){ 914 FILE *fp; 915 int i; 916 fp = fopen("DOSA_configuration","w");//write configuration 917 if(fp != NULL){ 918 for(i=0;i<9;i++){ 919 char* str3 = gtk_editable_get_chars(GTK_EDITABLE(button_entry[entry_num]),0,11); 920 fputs (str3,fp); 921 } 922 } 923 fclose(fp); 924 return FALSE; 925 } 926 927 gint cb_save_data(void){ 928 FILE *fp; 929 int i; 930 return FALSE; 931 } 932 933 void uim_settings_choice(int n){ 934 static int last = 0; 935 /* make a text entry grab mouse focus manually since there will be no mouse */ 936 if(last == 1){ 937 last = 0; 938 if(n == DIR_CW){ 939 if(entry_num >= 4){ 940 entry_num = 1; 941 gtk_widget_grab_focus(button_entry[entry_num]); 942 } 943 else{ 944 entry_num = entry_num + 1; 945 gtk_widget_grab_focus(button_entry[entry_num]); 946 } 947 } 948 else if(n == DIR_CCW){ 949 if(entry_num <= 1){ 950 entry_num = 4; 951 gtk_widget_grab_focus(button_entry[entry_num]); 952 } 953 else{ 954 entry_num = entry_num - 1; 955 gtk_widget_grab_focus(button_entry[entry_num]); 956 } 957 } 958 } 959 else{ 960 //slow down the rotation so it is one text entry per click 961 last++; 962 } 963 } 964 965 /****************************************************************/ 966 /* scan_init Function */ 967 /* inputs: center and width of desired high res graph */ 968 /* and number of points to graph */ 969 /* outputs: struct of necessary values to send to FPGA */ 970 /* Function: determines samples per step, scan min, scan */ 971 /* scan max, scan step, and number of points and */ 972 /* saves to the scanStr struct */ 973 /****************************************************************/ 974 scanStr scan_init(uint32_t center,uint32_t width,int num_points){ 975 assert(center > 0);

Page 73: Appendix C - Code Listing

  73  

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 overview_per_step=%u\n center=%u\n width=%u\n",s.status,s.count,s.scan_min,s.scan_max,s.samples_per_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_voltage,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_VALUE, 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 #!/bin/sh 2 TARGNAME=fpgalink_test 3 FPGALIB=$HOME/Important_Files/RPi/libfpgalink-20120507 4 gcc -m64 -O3 -g -Wall -Wextra -Wundef -pedantic-errors -std=c99 -Wstrict-prototypes \ 5 -Wno-missing-field-initializers -I$FPGALIB -I$FPGALIB/hdl/common\ 6 -Wl,--relax,--gc-sections,-rpath,\$ORIGIN,-rpath-link,$FPGALIB/linux.x86_64/rel \ 7 -o $TARGNAME dcmusb_unitTest.c dcmusb.c -L$FPGALIB/linux.x86_64/rel -lfpgalink -lerror 8 echo "finished" 9

Page 74: Appendix C - Code Listing

  74  

10 # gcc -m64 -O3 -Wall -Wextra -Wundef -pedantic-errors -std=c99 -Wstrict-prototypes -Wno-missing-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 * 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 #include <stdio.h> 18 #include <stdlib.h> 19 #include <libfpgalink.h> 20 #include "args.h" 21 22 #define CHECK(x) \ 23 if ( status != FL_SUCCESS ) { \ 24 returnCode = x; \ 25 fprintf(stderr, "%s\n", error); \ 26 flFreeError(error); \ 27 goto cleanup; \ 28 } 29 30 int main(int argc, const char *argv[]) { 31 int returnCode; 32 struct FLContext *handle = NULL; 33 FLStatus status; 34 const char *error = NULL; 35 uint8 byte = 0x10; 36 uint8 buf[256]; 37 bool flag; 38 bool isNeroCapable, isCommCapable; 39 uint32 fileLen; 40 uint8 *buffer = NULL; 41 uint32 numDevices, scanChain[16], i; 42 const char *vp = NULL, *ivp = NULL, *jtagPort = NULL, *xsvfFile = NULL, *dataFile = NULL; 43 bool scan = false, usbPower = false; 44 const char *const prog = argv[0]; 45 46 //printf("FPGALink \"C\" Example Copyright (C) 2011 Chris McClelland\n\n"); 47 argv++; 48 argc--; 49 while ( argc ) { 50 if ( argv[0][0] != '-' ) { 51 unexpected(prog, *argv); 52 FAIL(1); 53 } 54 switch ( argv[0][1] ) { 55 case 'v'://needed 56 GET_ARG("v", vp, 2); 57 break; 58 case 'i'://don't need should be taken out 59 GET_ARG("i", ivp, 3); 60 break; 61 case 'f': 62 GET_ARG("f", dataFile, 6); 63 break;

Page 75: Appendix C - Code Listing

  75  

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(

Page 76: Appendix C - Code Listing

  76  

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 /* inih -- simple .INI file parser 2 3 inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 home page for more info: 5 6 http://code.google.com/p/inih/ 7 8 */ 9 10 #include <stdio.h> 11 #include <ctype.h> 12 #include <string.h> 13 14 #include "ini.h" 15 16 #if !INI_USE_STACK 17 #include <stdlib.h> 18 #endif 19 20 #define MAX_SECTION 50 21 #define MAX_NAME 50 22 23 /* Strip whitespace chars off end of given string, in place. Return s. */ 24 static char* rstrip(char* s) 25 { 26 char* p = s + strlen(s); 27 while (p > s && isspace(*--p)) 28 *p = '\0'; 29 return s; 30 } 31 32 /* Return pointer to first non-whitespace char in given string. */ 33 static char* lskip(const char* s) 34 { 35 while (*s && isspace(*s)) 36 s++; 37 return (char*)s; 38 } 39 40 /* Return pointer to first char c or ';' comment in given string, or pointer to 41 null at end of string if neither found. ';' must be prefixed by a whitespace 42 character to register as a comment. */ 43 static char* find_char_or_comment(const char* s, char c) 44 { 45 int was_whitespace = 0; 46 while (*s && *s != c && !(was_whitespace && *s == ';')) { 47 was_whitespace = isspace(*s); 48 s++;

Page 77: Appendix C - Code Listing

  77  

49 } 50 return (char*)s; 51 } 52 53 /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 54 static char* strncpy0(char* dest, const char* src, size_t size) 55 { 56 strncpy(dest, src, size); 57 dest[size - 1] = '\0'; 58 return dest; 59 } 60 61 /* See documentation in header file. */ 62 int ini_parse_file(FILE* file, 63 int (*handler)(void*, const char*, const char*, 64 const char*), 65 void* user) 66 { 67 /* Uses a fair bit of stack (use heap instead if you need to) */ 68 #if INI_USE_STACK 69 char line[INI_MAX_LINE]; 70 #else 71 char* line; 72 #endif 73 char section[MAX_SECTION] = ""; 74 char prev_name[MAX_NAME] = ""; 75 76 char* start; 77 char* end; 78 char* name; 79 char* value; 80 int lineno = 0; 81 int error = 0; 82 83 #if !INI_USE_STACK 84 line = (char*)malloc(INI_MAX_LINE); 85 if (!line) { 86 return -2; 87 } 88 #endif 89 90 /* Scan through file line by line */ 91 while (fgets(line, INI_MAX_LINE, file) != NULL) { 92 lineno++; 93 94 start = line; 95 #if INI_ALLOW_BOM 96 if (lineno == 1 && (unsigned char)start[0] == 0xEF && 97 (unsigned char)start[1] == 0xBB && 98 (unsigned char)start[2] == 0xBF) { 99 start += 3; 100 } 101 #endif 102 start = lskip(rstrip(start)); 103 104 if (*start == ';' || *start == '#') { 105 /* Per Python ConfigParser, allow '#' comments at start of line */ 106 } 107 #if INI_ALLOW_MULTILINE 108 else if (*prev_name && *start && start > line) { 109 /* Non-black line with leading whitespace, treat as continuation 110 of previous name's value (as per Python ConfigParser). */ 111 if (!handler(user, section, prev_name, start) && !error) 112 error = lineno; 113 } 114 #endif 115 else if (*start == '[') { 116 /* A "[section]" line */ 117 end = find_char_or_comment(start + 1, ']'); 118 if (*end == ']') { 119 *end = '\0'; 120 strncpy0(section, start + 1, sizeof(section)); 121 *prev_name = '\0';

Page 78: Appendix C - Code Listing

  78  

122 } 123 else if (!error) { 124 /* No ']' found on section line */ 125 error = lineno; 126 } 127 } 128 else if (*start && *start != ';') { 129 /* Not a comment, must be a name[=:]value pair */ 130 end = find_char_or_comment(start, '='); 131 if (*end != '=') { 132 end = find_char_or_comment(start, ':'); 133 } 134 if (*end == '=' || *end == ':') { 135 *end = '\0'; 136 name = rstrip(start); 137 value = lskip(end + 1); 138 end = find_char_or_comment(value, '\0'); 139 if (*end == ';') 140 *end = '\0'; 141 rstrip(value); 142 143 /* Valid name[=:]value pair found, call handler */ 144 strncpy0(prev_name, name, sizeof(prev_name)); 145 if (!handler(user, section, name, value) && !error) 146 error = lineno; 147 } 148 else if (!error) { 149 /* No '=' or ':' found on name[=:]value line */ 150 error = lineno; 151 } 152 } 153 } 154 155 #if !INI_USE_STACK 156 free(line); 157 #endif 158 159 return error; 160 } 161 162 /* See documentation in header file. */ 163 int ini_parse(const char* filename, 164 int (*handler)(void*, const char*, const char*, const char*), 165 void* user) 166 { 167 FILE* file; 168 int error; 169 170 file = fopen(filename, "r"); 171 if (!file) 172 return -1; 173 error = ini_parse_file(file, handler, user); 174 fclose(file); 175 return error; 176 }

1.3.10 ini.h

1 /* inih -- simple .INI file parser 2 3 inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 home page for more info: 5 6 http://code.google.com/p/inih/ 7 8 */ 9 10 #ifndef __INI_H__ 11 #define __INI_H__ 12

Page 79: Appendix C - Code Listing

  79  

13 /* Make this header file easier to include in C++ code */ 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 #include <stdio.h> 19 20 /* Parse given INI-style file. May have [section]s, name=value pairs 21 (whitespace stripped), and comments starting with ';' (semicolon). Section 22 is "" if name=value pair parsed before any section heading. name:value 23 pairs are also supported as a concession to Python's ConfigParser. 24 25 For each name=value pair parsed, call handler function with given user 26 pointer as well as section, name, and value (data only valid for duration 27 of handler call). Handler should return nonzero on success, zero on error. 28 29 Returns 0 on success, line number of first error on parse error (doesn't 30 stop on first error), -1 on file open error, or -2 on memory allocation 31 error (only when INI_USE_STACK is zero). 32 */ 33 int ini_parse(const char* filename, 34 int (*handler)(void* user, const char* section, 35 const char* name, const char* value), 36 void* user); 37 38 /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 39 close the file when it's finished -- the caller must do that. */ 40 int ini_parse_file(FILE* file, 41 int (*handler)(void* user, const char* section, 42 const char* name, const char* value), 43 void* user); 44 45 /* Nonzero to allow multi-line value parsing, in the style of Python's 46 ConfigParser. If allowed, ini_parse() will call the handler with the same 47 name for each subsequent line parsed. */ 48 #ifndef INI_ALLOW_MULTILINE 49 #define INI_ALLOW_MULTILINE 1 50 #endif 51 52 /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 53 the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 54 #ifndef INI_ALLOW_BOM 55 #define INI_ALLOW_BOM 1 56 #endif 57 58 /* Nonzero to use stack, zero to use heap (malloc/free). */ 59 #ifndef INI_USE_STACK 60 #define INI_USE_STACK 1 61 #endif 62 63 /* Maximum line length for any line in INI file. */ 64 #ifndef INI_MAX_LINE 65 #define INI_MAX_LINE 200 66 #endif 67 68 #ifdef __cplusplus 69 } 70 #endif 71 72 #endif /* __INI_H__ */

1.3.11 support.h

1 #include <sys/time.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <gtk/gtk.h> 5 #include <gdk/gdk.h> 6 #include <glib.h> 7 #include <gio/gio.h> 8 #include <gtkdatabox.h>

Page 80: Appendix C - Code Listing

  80  

9 #include <gtkdatabox_points.h> 10 #include <gtkdatabox_ruler.h> 11 #include <gtkdatabox_lines.h> 12 #include <gtkdatabox_grid.h> 13 #include <math.h> 14 #include <cairo.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <stdint.h> 18 #include <assert.h> 19 #include <pthread.h> 20 #include <netinet/in.h> 21 #include "ini.h" 22 #include "uim_config.h" 23 #include "userIOusb.h" 24 #include "dcmusb.h" 25 26 #ifndef __SUPPORT_H__ 27 #define __SUPPORT_H__ 28 29 #define MAX_ENTRY (11) 30 #define MAX_WIDTH (250000) 31 #define MIN_WIDTH (400) 32 #define ADC_MAX (1) 33 //GDK colors 34 GdkColor bgColor = { 0, 0, 0, 0 };//set background to black 35 GdkColor gridColor = { 0, 65000, 65000, 65000 };//set gridlines to white 36 GdkColor red = { 0, 65000, 0, 0};//set graph lines to red 37 GdkColor cyan = {0, 0, 65000, 65000};//create cyan lines 38 GdkColor white = { 0, 65000, 65000, 65000 };//set gridlines to white 39 40 GtkWidget *button_hbox[9]; 41 GtkWidget *button_label[9]; 42 GtkWidget *button_entry[9]; 43 GtkEditable *entry_editable[9]; 44 45 GtkWidget *settings_window; 46 GtkWidget *setting_hbox[4]; 47 GtkWidget *setting_label[4]; 48 GtkWidget *setting_button[4]; 49 50 GtkWidget *lowerGraphDiv; 51 GtkWidget *upperGraphDiv; 52 GtkWidget *graphRate; 53 //declare upper graph global so the entire program can gain access to information 54 GtkWidget* databox_highres = 0; 55 GtkWidget* databoxcontainer_highres = 0; 56 GtkDataboxGraph *high_res_graph; 57 GtkDataboxGraph* high_res_grid; 58 59 //declare lower graph global so function can access everything 60 GtkWidget* databox_lowres; 61 GtkWidget* databoxcontainer_lowres; 62 GtkDataboxGraph *low_res_graph; 63 GtkDataboxGraph *lower_marker; 64 GtkDataboxGraph *upper_marker; 65 GtkDataboxGraph *low_res_grid; 66 GtkDataboxGraph *low_res_ramp; 67 68 int entry_pos[9]={1,1,1,1,1,1,1,1,1}; 69 //scan range function 70 //scan range defines 71 #define SCAN_MIN_REG (32) 72 #define SCAN_MAX_REG (36) 73 #define SCAN_STEP_REG (40) 74 #define SPS_REG (44) 75 #define START_REG (48) 76 #define STOP_REG (52) 77 #define OVERVIEW_STEP_REG (56) 78 #define UI_CMD_REG (0x7E) 79 #define FPGA_CMD_REG (0x7F) 80 #define STREAM_REG (1) 81 #define OVERVIEW_STREAM_REG (2)

Page 81: Appendix C - Code Listing

  81  

82 #define GAIN_REG (64) 83 #define GPIO_REG (68) 84 85 #define CMD_START (0x53) 86 #define STATUS_IDLE (0x00) 87 #define CMD_ABORT (0x00) 88 #define BAD_PARAM (0x60) 89 #define FIFO_WAIT (0x56) 90 #define HV_ON (1) 91 #define HV_OFF (0) 92 93 #define RUN_TIME_INT (1000) 94 #define FPGA_TIMEOUT (100000000) 95 #define MAX_POINTS (700) 96 97 98 enum state_t{ 99 START_SCAN, 100 WAIT_FOR_DATA, 101 GRAPH 102 }state = START_SCAN; 103 104 typedef struct { 105 uint32_t status; 106 uint32_t count; 107 uint32_t scan_min; 108 uint32_t scan_max; 109 uint32_t samples_per_step; 110 uint32_t over_per_step; 111 uint32_t scan_step; 112 int *x_vals; 113 int *y_vals; 114 }_scanStr; 115 typedef _scanStr *scanStr; 116 117 /*************************/ 118 /* Function Prototypes */ 119 /*************************/ 120 void onExit(void); 121 void settings(void); 122 void request_redraw(void); 123 gint graph_func(gpointer graph); 124 gint start_scan(scanStr); 125 gint cb_save_config(void); 126 gint cb_save_data(void); 127 scanStr scan_init(uint32_t center,uint32_t width, int num_points); 128 int read_data(int reg,float *x,float *y,scanStr); 129 gint dcmFSM(gpointer s); 130 void uim_settings_choice(int n); 131 int load_ini_config(void); 132 #endif /* __SUPPORT_H__ */  

1.3.12 uim_config.c

1 /** Settings IO Digital Optical Spectrum Analyzer **/ 2 /** Team Spectrum - George Mason University **/ 3 /** Jacob Dilles <[email protected]> 11 November 2012 **/ 4 5 /* Standard Includes */ 6 #include <stdio.h> /* FILE, printf, scanf, etc.. */ 7 #include <math.h> /* NAN, log10, etc.. */ 8 #include <errno.h> /* perror */ 9 #include <stdint.h> /* uint32_t */ 10 #include <string.h> /* strcmp */ 11 #include <stdlib.h> /* atoi */ 12 13 /* Project Includes */ 14 #include "ini.h" 15 #include "uim_config.h" 16

Page 82: Appendix C - Code Listing

  82  

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,

Page 83: Appendix C - Code Listing

  83  

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");

Page 84: Appendix C - Code Listing

  84  

160 _PRINTFL("voltage min", voltage_min, "V"); 161 _PRINTFL("voltage max", voltage_max, "V"); 162 _PRINTFL("max scan frequency", scan_freq, "Hz"); 163 _BR(); 164 165 _SECTION("data"); 166 _PRINTFS("output path", output_path); 167 _PRINTFS("output type", output_type); 168 _BR(); 169 */ 170 #undef _SECTION 171 #undef _PRINTFL 172 #undef _PRINTFS 173 #undef _PRINTS 174 return rv; 175 } 176 177 178 /* Scale a number for SI representation */ 179 double f2si(double number, char * prefix) 180 { 181 const static char si_prefix[8 + 1 + 8] = 182 { 183 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 184 0, 185 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' 186 }; 187 188 189 int log1000; 190 int minus; 191 192 // Check for wacko conditions 193 if( isnan(number) || isinf(number) || number == 0.0) 194 { 195 *prefix = 0; 196 return number; 197 } 198 199 // Fix for log of negative number 200 minus = number < 0.0; 201 if(minus) number = -number; 202 203 // Determine prefix based on power of 1000 204 log1000 = (int) floor( (log10(number) / 3) ); //log1000 205 206 207 if(log1000 >= -8 && log1000 <= 8) /* Prefixes only cover 1000^-8 .. 1000^8*/ 208 { 209 number /= (double) pow(1000.0, log1000); 210 *prefix = si_prefix[log1000+8]; 211 } 212 else /* number too big for metric prefix */ 213 { 214 *prefix = 0; 215 } 216 217 if(minus) number = -number; // restore minus 218 219 return number; 220 } 221 222 223 /* Parse a string to a double with support for SI prefixes on units */ 224 double si2f(const char* s) 225 { 226 char prefix[5], c; 227 double value, scale; 228 int rv; 229 230 /* parse the floating point number + 1-4 character extension*/ 231 rv = sscanf(s, " %1$lf %2$5s", &value, prefix); 232

Page 85: Appendix C - Code Listing

  85  

233 #if _DEBUG_INI_ 234 printf("si2f: rv=%d value=%lf prefix=%s\n", rv, value, prefix); 235 #endif 236 237 switch(rv) 238 { 239 case 0: 240 return NAN; 241 case 1: 242 return value; 243 case 2: 244 c = prefix[0]; 245 break; 246 default: 247 /* Unknown */ 248 perror("Problem reading floating point string"); 249 return NAN; 250 } 251 252 /* look up the si prefix (see http://en.wikipedia.org/wiki/Metric_prefix)*/ 253 switch(c) 254 { 255 case 'Y': scale = _f(1.0e+24); break; 256 case 'Z': scale = _f(1.0e+21); break; 257 case 'E': scale = _f(1.0e+18); break; 258 case 'P': scale = _f(1.0e+15); break; 259 case 'T': scale = _f(1.0e+12); break; 260 case 'G': scale = _f(1.0e+9); break; 261 case 'M': scale = _f(1.0e+6); break; 262 case 'k': scale = _f(1.0e+3); break; 263 case 'h': scale = _f(1.0e+2); break; 264 case 'd': scale = _f(1.0e-1); break; 265 case 'c': scale = _f(1.0e-2); break; 266 case 'm': scale = _f(1.0e-3); break; 267 case 'u': scale = _f(1.0e-6); break; 268 case 'n': scale = _f(1.0e-9); break; 269 case 'p': scale = _f(1.0e-12); break; 270 case 'f': scale = _f(1.0e-15); break; 271 case 'a': scale = _f(1.0e-18); break; 272 case 'z': scale = _f(1.0e-21); break; 273 case 'y': scale = _f(1.0e-24); break; 274 case '%': scale = _f(1.0e-2); break; /* not strictly si, but useful*/ 275 default: scale = _f(1.0 ); break; /* unknown, ignore */ 276 } 277 278 /* scale by si unit */ 279 value *= scale; 280 281 return value; 282 }  

1.3.13 uim_config.h

1 /** Settings IO Digital Optical Spectrum Analyzer **/ 2 /** Team Spectrum - George Mason University **/ 3 /** Jacob Dilles <[email protected]> 11 November 2012 **/ 4 5 6 /* 7 ; Team Spectrum DOSA Sample Configuration File 8 ; Note, metric prefixes should be accepted, but the actual SI unit is not 9 ; validated (so, for example, 1.5 mm is a valid frequency (0.0015 hz) 10 11 [config] ; Configuration Versioning 12 version = 1 ; Version 1 13 14 [sfpi] 15 free spectral range = 1.5 GHz ; Free spectral range (FSR) of SPFI cavity 16 mirror reflectivity = 99.9999 % ; Mirror reflectivity (either % or 0.999...)

Page 86: Appendix C - Code Listing

  86  

17 mirror spacing = 15 mm ; Mirror spacing 18 displacement per volt = 4 mm ; SFPI 19 laser wavelength = 785.80 nm ; Nominal wavelength, for auto-locking 20 voltage min = 15 V ; minimum allowable voltage for cavity 21 voltage max = 450 V ; maximum allowable voltage for cavity 22 max scan frequency = 10 Hz ; scan frequency limit 23 24 [data] 25 output path = /data 26 output type = csv ; Output file extension and kind 27 28 */ 29 30 #ifndef __UIM_CONFIG_H 31 #define __UIM_CONFIG_H 32 /** --------- START INCLUDE FILE ------------- */ 33 34 /* Define to 1 to enable print statements in the handler/parsers */ 35 #define _DEBUG_INI_ (0) 36 37 /* Define to 1 to enable demo of reading/writing INI */ 38 #define _DEMO_INI_ (0) 39 40 #define SETTINGS_FILE_NAME "uim_settings.txt" 41 42 #define SOM_CODE_MIN (4095.0) 43 #define SOM_CODE_MAX (2147483647.0) 44 #define SOM_VOLTAGE_MIN (4.0) 45 #define SOM_VOLTAGE_MAX (496.0) 46 47 #define IPM_CODE_MIN (2147483647.0) 48 #define IPM_CODE_MAX (0.0) 49 #define IPM_VOLTAGE_MIN (0.0) 50 #define IPM_VOLTAGE_MAX (3.0) 51 52 #define VGA_CODE_MIN (0.0) 53 #define VGA_CODE_MAX (15.0) 54 #define VGA_GAIN_MIN (4000.0) 55 #define VGA_GAIN_MAX (1258925.0) 56 57 /* The struct to hold configuration data */ 58 typedef struct { 59 int version; 60 float start_voltage; 61 float stop_voltage; 62 float ipm_clk_freq; 63 float refresh_rate; 64 int som_steps_per_volt; 65 /* SFPI parameters */ 66 double fsr; 67 double mirror_reflectivity; 68 double mirror_spacing; 69 double volts_per_fsr; 70 double laser_wavelength; 71 72 /* Min/Max Limits */ 73 double voltage_min; 74 double voltage_max; 75 76 /* Scanning params */ 77 double scan_freq; 78 79 /*File Output Stuff*/ 80 char output_path[128]; 81 char output_type[8]; 82 83 } st_configuration; 84 85 /* Read settings in. Non-zero return indicates error */ 86 int scanf_settings( st_configuration* pcfg ); 87 int fscanf_settings(FILE * file, st_configuration* pcfg); 88 89 /* Debug print current settings to stdout */

Page 87: Appendix C - Code Listing

  87  

90 int printf_settings(st_configuration* pcfg); 91 int fprintf_settings(FILE * file, st_configuration* pcfg); 92 93 94 /** --------- END INCLUDE FILE ------------- */ 95 #endif

1.3.14 uim_functions.c

1 #include "uim_functions.h" 2 //declare upper graph global so the entire program can gain access to information 3 GtkWidget* databox_highres = 0; 4 GtkWidget* databoxcontainer_highres = 0; 5 GtkDataboxGraph *high_res_graph; 6 GtkDataboxGraph* high_res_grid; 7 8 //declare lower graph global so function can access everything 9 GtkWidget* databox_lowres; 10 GtkWidget* databoxcontainer_lowres; 11 GtkDataboxGraph *low_res_graph; 12 GtkDataboxGraph *lower_marker; 13 GtkDataboxGraph *upper_marker; 14 GtkDataboxGraph *low_res_grid; 15 GtkDataboxGraph *low_res_ramp; 16 17 GtkWidget *button_hbox[9]; 18 GtkWidget *button_label[9]; 19 GtkWidget *button_entry[9]; 20 GtkEditable *entry_editable[9]; 21 22 const char* str2; 23 char * pixel_diff_str,amp_diff_str,hz_diff_str; 24 int context,entry_num=0,rotary; 25 extern int entry_pos[9]={1,1,1,1,1,1,1,1,1}; 26 float amp1,amp2,amp_diff,pixel1, 27 pixel2,pixel_diff,pixel_diff2,width=50,center=50,temp_width,temp_center; 28 29 gint uim_pressed_home(void){ 30 uim_led_toggle(BTN_HOME); 31 return FALSE; 32 } 33 34 gint uim_pressed_measure(void){ 35 uim_led_toggle(BTN_MEASURE); 36 return FALSE; 37 } 38 39 gint uim_pressed_cursor(void){ 40 uim_led_toggle(BTN_CURSOR); 41 settings(); 42 return FALSE; 43 } 44 45 gint uim_pressed_memory(void){ 46 uim_led_toggle(BTN_MEMORY); 47 return FALSE; 48 } 49 50 gint uim_pressed_power(void){ 51 uim_led_toggle(BTN_POWER); 52 return FALSE; 53 } 54 55 // knobs x, y 56 gint uim_pressed_k0(void){ 57 static int x = 0; 58 if(context == 0){ 59 x = 1-x; 60 if(x == 1){ 61 context = 1;

Page 88: Appendix C - Code Listing

  88  

62 } 63 else{ 64 context = 0; 65 } 66 } 67 else if(context == 1){ 68 x = 1-x; 69 if(x ==1){ 70 context = 1; 71 } 72 else{ 73 context = 0; 74 } 75 } 76 else if(context == 2){ 77 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); 78 context = 1; 79 } 80 return FALSE; 81 } 82 83 gint uim_pressed_k1(void){ 84 static int x = 0; 85 if(context == 1){ 86 x = 1-x; 87 if(x == 1){ 88 str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); 89 entry_pos[entry_num] = 7; 90 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]); 91 context = 2; 92 } 93 else if(x == 0){ 94 context = 1; 95 } 96 } 97 else if(context == 2){ 98 context == 1; 99 } 100 return FALSE; 101 } 102 103 gint uim_rotated_k0(int n) 104 { 105 rotary = 0; 106 if(context == 0){ 107 //printf("in home context\n"); 108 g_timeout_add(1,(GSourceFunc)(uim_state_home(n)),NULL); 109 } 110 else if(context == 1){ 111 g_timeout_add(1,(GSourceFunc)(uim_state_field_select(n)),NULL); 112 } 113 else if(context == 2){ 114 g_timeout_add(1,(GSourceFunc)(uim_state_edit_field(n)),NULL); 115 } 116 return FALSE; 117 } // -1 = ccw, 1 = cw 118 119 //dependent on context but should rotate arrows at top of graphs and go through text entries 120 gint uim_rotated_k1(int n){ 121 rotary = 1; 122 if(context == 0){ 123 g_timeout_add(1,(GSourceFunc)(uim_state_home(n)),NULL); 124 } 125 else if(context == 2){ 126 g_timeout_add(1,(GSourceFunc)(uim_state_edit_field(n)),NULL); 127 } 128 return FALSE; 129 } 130 131 // keypad 132 // num := 0..9 133 //initialize position array so cursor is in correct spot 134

Page 89: Appendix C - Code Listing

  89  

135 gint uim_pressed_number(char num){ 136 if(context = 3){ 137 char str[] = {num,0}; 138 gtk_editable_insert_text(GTK_EDITABLE(button_entry[entry_num]),str,1,entry_pos); 139 //gtk_entry_append_text(GTK_ENTRY(button_entry[entry_num]),str); 140 if(entry_pos[entry_num] < 11){ 141 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]++); 142 } 143 else{ 144 context = 1; 145 } 146 } 147 else{ 148 printf("this isn't implemented yet\n"); 149 } 150 return FALSE; 151 } 152 153 gint uim_pressed_star(void){ 154 if(context == 1){ 155 context = 3; 156 str2 = gtk_entry_get_text(GTK_ENTRY(button_entry[entry_num])); 157 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),""); 158 } 159 else if(context == 3){ 160 context = 1; 161 } 162 else{ 163 printf("this function hasn't been implemented yet\n"); 164 } 165 return FALSE; 166 } 167 168 gint uim_pressed_pound(void){ 169 if(context == 3){ 170 if (entry_num >= 8){ 171 entry_num = 8; 172 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); 173 context = 1; 174 } else{ 175 gtk_entry_set_position(GTK_ENTRY(button_entry[entry_num]),entry_pos[entry_num]--); 176 } 177 } 178 else if(context == 2){ 179 gtk_entry_set_text(GTK_ENTRY(button_entry[entry_num]),str2); 180 context = 1; 181 } 182 return FALSE; 183 } 184 185 gint uim_state_home(int n){ 186 pixel1 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center); 187 pixel2 = gtk_databox_pixel_to_value_x(GTK_DATABOX(databox_lowres),center-1); 188 pixel_diff= pixel1 - pixel2; 189 190 191 if(rotary == 1){ 192 if(n == DIR_CW){ 193 //clockwise = zoom in 194 //use the difference in x-values displayed 195 //on graph to create proper scaling 196 temp_width = width - pixel_diff; 197 if(temp_width < MIN_WIDTH){ 198 width = width; 199 } 200 else if(center - temp_width < MIN_WIDTH){ 201 width = width; 202 } 203 else if(center + temp_width > MAX_WIDTH){ 204 width = width; 205 }

Page 90: Appendix C - Code Listing

  90  

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(&amp_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),&amp_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;

Page 91: Appendix C - Code Listing

  91  

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]--;

Page 92: Appendix C - Code Listing

  92  

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 #include <gtk/gtk.h> 2 #include <glib.h> 3 #include <gio/gio.h> 4 #include <stdlib.h> 5 #include <fcntl.h> 6 #include <termios.h> 7 #include <string.h> 8 #include <errno.h> // errno 9 #include <gtkdatabox.h> 10 #include <gtkdatabox_points.h> 11 #include <gtkdatabox_ruler.h> 12 #include <gtkdatabox_lines.h> 13 #include <gtkdatabox_grid.h> 14 15 #define MAX_ENTRY 11 16 #define MAX_WIDTH 250000 17 #define MIN_WIDTH 700

Page 93: Appendix C - Code Listing

  93  

18 19 #define BTN_HOME 'A' 20 #define BTN_MEASURE 'B' 21 #define BTN_CURSOR 'C' 22 #define BTN_MEMORY 'D' 23 #define BTN_POWER 'P' 24 #define BTN_K0 'X' 25 #define BTN_K1 'Y' 26 #define K0_CCW '<' 27 #define K0_CW '>' 28 #define K1_CCW '{' 29 #define K1_CW '}' 30 31 #define DIR_CW 1 // -1 = counter clockwise 32 #define DIR_CCW -1 // -1 = counter clockwise 33 34 // buttons A-D, P 35 extern gint uim_pressed_home(void); 36 extern gint uim_pressed_measure(void); 37 extern gint uim_pressed_cursor(void); 38 extern gint uim_pressed_memory(void); 39 extern gint uim_pressed_power(void); 40 41 // knobs x, y 42 extern gint uim_pressed_k0(void); 43 extern gint uim_pressed_k1(void); 44 extern gint uim_rotated_k0(int n); // -1 = ccw, 1 = cw 45 extern gint uim_rotated_k1(int n); // -1 = ccw, 1 = cw 46 47 // keypad 48 extern gint uim_pressed_number(char num); // num := 0..9 49 extern gint uim_pressed_star(void); 50 extern gint uim_pressed_pound(void); 51 52 extern gint uim_state_home(int n); 53 extern gint uim_state_field_select(int n); 54 extern gint uim_state_keypad_entry(int n); 55 extern gint 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

Page 94: Appendix C - Code Listing

  94  

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 cases 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;

Page 95: Appendix C - Code Listing

  95  

69 } 70 71 // Outputs 72 int uim_output_str(char* str) 73 { 74 if(!ftdi_fd) 75 { 76 fprintf(stderr,"File not open??"); 77 return FALSE; 78 } 79 return write(ftdi_fd, str, strlen(str)); 80 } 81 82 83 int uim_test_connected() 84 { 85 return ftdi_fd != 0; 86 } 87 88 89 /****** Helper to set up shutdown stuff ***********/ 90 void setupShutdown(void) 91 { 92 // Set up the program to handle system signals gracefully 93 // see http://www.cplusplus.com/reference/clibrary/csignal/signal/ 94 void (*prev_fn)(int); 95 prev_fn = signal(SIGINT, terminate); 96 if (prev_fn==SIG_IGN) 97 { 98 signal (SIGINT,SIG_IGN); 99 fprintf(stderr,"Could not register sigterm_handler!\n"); 100 } 101 102 // Add exit notifier (called on exit(n) ) 103 atexit (onExit); 104 105 } 106 107 /******* Called on SIGINT (^c) after being registered by singal() ******/ 108 void terminate( int parameter ) 109 { 110 // Attempt to close the serial port 111 if(ftdi_fd == 0) // open() == 0 indicates it was never opened 112 { 113 // TODO RMDEBUG 114 printf("FTDI device never opened...\n"); 115 } 116 else if(close(ftdi_fd) == 0) // close() == 0 indicates sucess 117 { 118 // TODO RMDEBUG 119 printf("FTDI device descriptor closed.\n"); 120 } 121 else 122 { 123 fprintf(stderr,"FTDI device descriptor failed to close.\n"); 124 } 125 126 127 // Exit nicely 128 exit(parameter); 129 } 130 131 132 133 /** 134 * Configures a non-blocking 115200/8n1 FTDI connnection on the specified 135 * filename. 136 * 137 * Returns 0 if the FTDI device was opened, otherwise -1 138 */ 139 int openFTDIfd(char* filename,GIOChannel **deviceChannelP) 140 { 141 ////// Locals //////

Page 96: Appendix C - Code Listing

  96  

142 int result; // Result of last opperation 143 int tty_fd; // File discriptor number from UNIX 'open' 144 struct termios tio; // Struct modifying the paramaters of the serial term 145 int nloop; // loops to wait for bootup 146 int nread; // bytes read from the stream 147 148 #ifdef _DEBUG 149 printf("openFTDIfd -> Called\n"); 150 #endif 151 152 /* 153 Ensure that the file exists 154 * see http://linux.die.net/man/2/access , #include <unistd.h> 155 F_OK - validate that the file exists 156 */ 157 result = access(filename, F_OK); 158 if( result != 0) 159 { 160 fprintf(stderr,"FTDI device %s does not exist.\n", filename); 161 return 2; 162 } 163 164 /** 165 Ensure read/write permissions. 166 R_OK - ability to read 167 W_OK - ability to write 168 */ 169 result = access(filename, R_OK | W_OK); 170 if( result != 0) { 171 fprintf(stderr,"FTDI device %s permission denied: %s\n", filename, strerror( errno )); 172 return 3; 173 } 174 /** 175 Open the terminal using UNIX IO 176 * See http://rabbit.eng.miami.edu/info/functions/unixio.html 177 * This function returns a file desriptor number, or 0 if the file could 178 * not be opened. 179 O_RDWR - read and write 180 O_NONBLOCK - don't block reads 181 O_NOCTTY - don't allow FTDI device to kill connection with ^C 182 */ 183 //tty_fd = open(FTDI_DEV, O_RDWR | O_NONBLOCK );//| O_NOCTTY); //add nonblocking IO 184 tty_fd = open(FTDI_DEV, O_RDWR );//| O_NOCTTY); 185 186 #ifdef _DEBUG 187 printf("openFTDIfd -> FD#= %d\n", tty_fd); 188 #endif 189 190 if(tty_fd <= 0) { 191 fprintf(stderr,"FTDI device %s can not be opened:%s\n", filename, strerror( errno )); 192 return 4; 193 } 194 195 196 /** 197 Zero out TIO struct 198 * inc: string.h 199 */ 200 memset(&tio,0,sizeof(tio)); 201 202 203 /** 204 Configure the serial terminal 205 * inc: termios.h 206 * ref1: http://linux.die.net/man/3/tcsetattr 207 * ref2: http://en.wikibooks.org/wiki/Serial_Programming/termios 208 * ref3: http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html 209 */ 210 211 // Input mode: raw 212 tio.c_iflag = 0; 213

Page 97: Appendix C - Code Listing

  97  

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);

Page 98: Appendix C - Code Listing

  98  

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

Page 99: Appendix C - Code Listing

  99  

357 cmd[0] = btn; 358 btn_state |= mask; 359 } else { 360 // A->a turn off 361 cmd[0] = btn+0x20; 362 btn_state &= ~mask; 363 } 364 365 return uim_output_str(cmd); 366 } 367 368 369 370 int uim_led_toggle(char btn){ 371 if(btn< 'A' || btn> 'Z') { 372 #ifdef _DEBUG 373 printf("You're an idiot %d\n",btn); 374 #endif 375 return 1; // not a valid button 376 } 377 378 // select correct bit of state 379 int mask = 1<<(btn - 'A'); 380 381 // command string x\0 382 char cmd[2] = " "; 383 384 if(mask & btn_state){ 385 // already set, need to turn off 386 cmd[0] = btn+0x20; 387 } else { 388 cmd[0] = btn; 389 } 390 391 uim_output_str(cmd); 392 393 // toggle state variable 394 btn_state ^= mask; 395 396 return 0; 397 } 398 extern volatile unsigned int drawing; 399 400 void *doBackgroundIOopsLoop(){ 401 while(1){ 402 //printf("the io loop\n"); 403 if((doBackgroundIOops(deviceChannel,G_IO_IN,NULL))){ 404 //if(counter >=3){ 405 drawing = 2; 406 //request_redraw(); 407 //counter = 0; 408 //} 409 //else 410 //counter++; 411 } 412 while(drawing){ 413 //pthread_yield(); 414 sched_yield(); 415 //sleep(.01); 416 } 417 } 418 } 419 420 gboolean doBackgroundIOops(GIOChannel *deviceChannel,GIOCondition condition,gpointer data) 421 { 422 int nread; 423 #ifdef __USE_STD 424 int result; 425 // Read from stdin 426 result = scanf("%s",buff); 427 if(result < 0) 428 { 429 perror("Error writing to stream");

Page 100: Appendix C - Code Listing

  100  

430 terminate(1); 431 } else if(result > 0) 432 { 433 write(ftdi_fd, buff, (unsigned)strlen(buff)); 434 #ifdef _DEBUG 435 printf("%s\n", buff); 436 #endif 437 } 438 #endif 439 //nread = g_io_channel_read_chars(deviceChannel,buff,128,NULL,NULL); 440 nread = read(ftdi_fd, buff, 128); 441 if(nread < 0) 442 { 443 perror("Error reading stream"); 444 terminate(1); 445 } 446 else if(nread > 0) 447 { 448 #ifdef __USE_STD 449 buff[nread] = 0; 450 printf("%s\n", buff); 451 #else 452 int i=0; 453 printf("nread = %d\n",nread); 454 for(i = 0; i < nread; i++){ 455 FSMrunning = 1; 456 //input = buff[i]; 457 uim_rx(buff[i]); 458 459 } 460 FSMrunning = 0; 461 return TRUE; 462 #endif 463 } 464 return FALSE; 465 }

1.4.3 userIOusb.h

1 /* Kevin Nicotera */ 2 /* 9/8/12 */ 3 4 //includes 5 //#include "uim_functions.h" 6 #include <stdio.h> 7 #include <gtk/gtk.h> 8 #include <glib.h> 9 #include <gio/gio.h> 10 #include <stdlib.h> 11 #include <fcntl.h> 12 #include <termios.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <pthread.h> 16 #include <errno.h> // errno 17 18 19 //defines 20 #define FTDI_DEV "/dev/ttyUSB0" // UIM-E board 21 #define PROPELLER_STARTUP_WAIT_USEC 1000*200 // 50ms 22 #define PROPELLER_STARTUP_WAIT_SPINS 40 //2 seconds = 40 * 50ms 23 24 25 #define _ECHO_I2C_VERSION ":4cXfe24?" 26 27 #define BTN_HOME 'A' 28 #define BTN_MEASURE 'B' 29 #define BTN_CURSOR 'C' 30 #define BTN_MEMORY 'D' 31 #define BTN_POWER 'P' 32 #define BTN_K0 'X'

Page 101: Appendix C - Code Listing

  101  

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

Page 102: Appendix C - Code Listing

  102  

1.5 UIM-E – Propeller P8X32A Embedded Controller

1.5.1 Basic_I2C_Driver.spin

1 '' Basic I2C Routines Version 1.1.1 - Jacob DIlles 2 '' Written by Michael Green and copyright (©) 2007 3 '' Permission is given to use this in any program for the Parallax 4 '' Propeller processor as long as this copyright notice is included. 5 6 '' This is a minimal version of an I2C driver in SPIN. It assumes 7 '' that the SDA pin is one higher than the SCL pin. It assumes that 8 '' neither the SDA nor the SCL pins have pullups, so drives both. 9 10 '' These routines are primarily intended for reading and writing EEPROMs. 11 '' The low level I2C are provided for use with other devices, but the 12 '' read/write byte routines assume a standard I2C serial EEPROM with a 13 '' 16 bit device address register, paged writes, and acknowledge polling. 14 15 '' All of these read/write routines accept an EEPROM address up to 19 16 '' bits (512K) even though the EEPROM addressing scheme normally allows 17 '' for only 16 bits of addressing. The upper 3 bits are used as part of 18 '' the device select code and these routines will take the upper 3 bits 19 '' of the address and "or" it with the supplied device select code bits 20 '' 3-1 which are used to select a particular EEPROM on an I2C bus. There 21 '' are two schemes for selecting 64K "banks" in 128Kx8 EEPROMs. Atmel's 22 '' 24LC1024 EEPROMs allow simple linear addressing up to 256Kx8 ($00000 23 '' to $3FFFF). Microchip's 24LC1025 allows for up to 512Kx8, but in two 24 '' areas: $00000 to $3FFFF and $40000 to $7FFFF. Each EEPROM provides 25 '' a 64K "bank" in each area. See the device datasheets for details. 26 27 '' This will work with the boot EEPROM and does not require a pull-up 28 '' resistor on the SCL line (but does on the SDA line ... about 4.7K to 29 '' +3.3V). According to the Philips I2C specification, both pull-ups 30 '' are required. Many devices will tolerate the absence of a pull-up 31 '' on SCL. Some may tolerate the absence of a pull-up on SDA as well. 32 33 '' Initialize may have to be called once at the beginning of your 34 '' program. Sometimes an I2C device is left in an invalid state. This 35 '' will reset the device to a known state so it will respond to the I2C 36 '' start transition (sent out by the i2cStart routine). 37 38 '' To read from or write to an EEPROM on pins 28/29 like the boot EEPROM: 39 40 '' CON 41 '' eepromAddress = $7000 42 43 '' VAR 44 '' byte buffer[32] 45 46 '' OBJ 47 '' i2c : "Minimal_I2C_Driver" 48 49 '' PRI readIt 50 '' if i2c.ReadPage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32) 51 '' abort ' an error occurred during the read 52 53 '' PRI writeIt | startTime 54 '' if i2c.WritePage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32) 55 '' abort ' an error occured during the write 56 '' startTime := cnt ' prepare to check for a timeout 57 '' repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress) 58 '' if cnt - startTime > clkfreq / 10 59 '' abort ' waited more than a 1/10 second for the write to finish 60 61 '' Note that the read and write use something called paged reads/writes. 62 '' This means that any read using ReadPage must fit entirely in one 63 '' EEPROM if you have several attached to one set of pins. For writes,

Page 103: Appendix C - Code Listing

  103  

64 '' any write using i2cWritePage must fit entirely within a page of the 65 '' EEPROM. Usually these pages are either 32, 64, 128 or 256 bytes in 66 '' size depending on the manufacturer and device type. 32 bytes is a 67 '' good limit for the number of bytes to be written at a time if you 68 '' don't know the specific page size (and the write must fit completely 69 '' within a multiple of the page size). The WriteWait waits for the 70 '' write operation to complete. Alternatively, you could wait for 5ms 71 '' since currently produced EEPROMs will finish within that time. 72 73 CON 74 ACK = 0 ' I2C Acknowledge 75 NAK = 1 ' I2C No Acknowledge 76 Xmit = 0 ' I2C Direction Transmit 77 Recv = 1 ' I2C Direction Receive 78 BootPin = 28 ' I2C Boot EEPROM SCL Pin 79 EEPROM = $A0 ' I2C EEPROM Device Address 80 81 DAT 82 scl byte 28 83 sda byte 29 84 85 PUB Initialize(argSCL, argSDA) ' An I2C device may be left in an 86 scl := argSCL ' invalid state and may need to be 87 sda := argSDA ' reinitialized. Drive SCL hig 88 89 outa[SCL] := 1 90 dira[SCL] := 1 91 dira[SDA] := 0 ' Set SDA as input 92 repeat 9 93 outa[SCL] := 0 ' Put out up to 9 clock pulses 94 outa[SCL] := 1 95 if ina[SDA] ' Repeat if SDA not driven high 96 quit ' by the EEPROM 97 98 PUB Start ' SDA goes HIGH to LOW with SCL HIGH 99 100 outa[SCL]~~ ' Initially drive SCL HIGH 101 dira[SCL]~~ 102 outa[SDA]~~ ' Initially drive SDA HIGH 103 dira[SDA]~~ 104 outa[SDA]~ ' Now drive SDA LOW 105 outa[SCL]~ ' Leave SCL LOW 106 107 PUB Stop ' SDA goes LOW to HIGH with SCL High 108 109 outa[SCL]~~ ' Drive SCL HIGH 110 outa[SDA]~~ ' then SDA HIGH 111 dira[SCL]~ ' Now let them float 112 dira[SDA]~ ' If pullups present, they'll stay HIGH 113 114 PUB Write(data) : ackbit 115 '' Write i2c data. Data byte is output MSB first, SDA data line is valid 116 '' only while the SCL line is HIGH. Data is always 8 bits (+ ACK/NAK). 117 '' SDA is assumed LOW and SCL and SDA are both left in the LOW state. 118 119 ackbit := 0 120 data <<= 24 121 repeat 8 ' Output data to SDA 122 outa[SDA] := (data <-= 1) & 1 123 outa[SCL]~~ ' Toggle SCL from LOW to HIGH to LOW 124 outa[SCL]~ 125 dira[SDA]~ ' Set SDA to input for ACK/NAK 126 outa[SCL]~~ 127 ackbit := ina[SDA] ' Sample SDA when SCL is HIGH 128 outa[SCL]~ 129 outa[SDA]~ ' Leave SDA driven LOW 130 dira[SDA]~~ 131 132 PUB Read( ackbit): data 133 '' Read in i2c data, Data byte is output MSB first, SDA data line is 134 '' valid only while the SCL line is HIGH. SCL and SDA left in LOW state. 135 136 data := 0

Page 104: Appendix C - Code Listing

  104  

137 dira[SDA]~ ' Make SDA an input 138 repeat 8 ' Receive data from SDA 139 outa[SCL]~~ ' Sample SDA when SCL is HIGH 140 data := (data << 1) | ina[SDA] 141 outa[SCL]~ 142 outa[SDA] := ackbit ' Output ACK/NAK to SDA 143 dira[SDA]~~ 144 outa[SCL]~~ ' Toggle SCL from LOW to HIGH to LOW 145 outa[SCL]~ 146 outa[SDA]~ ' Leave SDA driven LOW 147 148 PUB ReadPage(devSel, addrReg, dataPtr, count) : ackbit 149 '' Read in a block of i2c data. Device select code is devSel. Device starting 150 '' address is addrReg. Data address is at dataPtr. Number of bytes is count. 151 '' The device select code is modified using the upper 3 bits of the 19 bit addrReg. 152 '' Return zero if no errors or the acknowledge bits if an error occurred. 153 devSel |= addrReg >> 15 & %1110 154 Start ' Select the device & send address 155 ackbit := Write(devSel | Xmit) 156 ackbit := (ackbit << 1) | Write(addrReg >> 8 & $FF) 157 ackbit := (ackbit << 1) | Write(addrReg & $FF) 158 Start ' Reselect the device for reading 159 ackbit := (ackbit << 1) | Write(devSel | Recv) 160 repeat count - 1 161 byte[dataPtr++] := Read(ACK) 162 byte[dataPtr++] := Read(NAK) 163 Stop 164 return ackbit 165 166 PUB ReadByte(devSel, addrReg) : data 167 '' Read in a single byte of i2c data. Device select code is devSel. Device 168 '' starting address is addrReg. The device select code is modified using the 169 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. 170 if ReadPage(devSel, addrReg, @data, 1) 171 return -1 172 173 PUB ReadWord(devSel, addrReg) : data 174 '' Read in a single word of i2c data. Device select code is devSel. Device 175 '' starting address is addrReg. The device select code is modified using the 176 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. 177 if ReadPage(devSel, addrReg, @data, 2) 178 return -1 179 180 PUB ReadLong(devSel, addrReg) : data 181 '' Read in a single long of i2c data. Device select code is devSel. Device 182 '' starting address is addrReg. The device select code is modified using the 183 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. 184 '' Note that you can't distinguish between a return value of -1 and true error. 185 if ReadPage(devSel, addrReg, @data, 4) 186 return -1 187 188 PUB WritePage(devSel, addrReg, dataPtr, count) : ackbit 189 '' Write out a block of i2c data. Device select code is devSel. Device starting 190 '' address is addrReg. Data address is at dataPtr. Number of bytes is count. 191 '' The device select code is modified using the upper 3 bits of the 19 bit addrReg. 192 '' Most devices have a page size of at least 32 bytes, some as large as 256 bytes. 193 '' Return zero if no errors or the acknowledge bits if an error occurred. If 194 '' more than 31 bytes are transmitted, the sign bit is "sticky" and is the 195 '' logical "or" of the acknowledge bits of any bytes past the 31st. 196 devSel |= addrReg >> 15 & %1110 197 Start ' Select the device & send address 198 ackbit := Write(devSel | Xmit) 199 ackbit := (ackbit << 1) | Write(addrReg >> 8 & $FF) 200 ackbit := (ackbit << 1) | Write(addrReg & $FF) 201 repeat count ' Now send the data 202 ackbit := ackbit << 1 | ackbit & $80000000 ' "Sticky" sign bit 203 ackbit |= Write(byte[dataPtr++]) 204 Stop 205 return ackbit 206 207 PUB WriteByte(devSel, addrReg, data) 208 '' Write out a single byte of i2c data. Device select code is devSel. Device 209 '' starting address is addrReg. The device select code is modified using the

Page 105: Appendix C - Code Listing

  105  

210 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. 211 if WritePage(devSel, addrReg, @data, 1) 212 return true 213 ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) 214 waitcnt(400_000 + cnt) 215 return false 216 217 PUB WriteWord(devSel, addrReg, data) 218 '' Write out a single word of i2c data. Device select code is devSel. Device 219 '' starting address is addrReg. The device select code is modified using the 220 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. 221 '' Note that the word value may not span an EEPROM page boundary. 222 if WritePage(devSel, addrReg, @data, 2) 223 return true 224 ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) 225 waitcnt(400_000 + cnt) 226 return false 227 228 PUB WriteLong(devSel, addrReg, data) 229 '' Write out a single long of i2c data. Device select code is devSel. Device 230 '' starting address is addrReg. The device select code is modified using the 231 '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. 232 '' Note that the long word value may not span an EEPROM page boundary. 233 if WritePage(devSel, addrReg, @data, 4) 234 return true 235 ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) 236 waitcnt(400_000 + cnt) 237 return false 238 239 PUB WriteWait(devSel, addrReg) : ackbit 240 '' Wait for a previous write to complete. Device select code is devSel. Device 241 '' starting address is addrReg. The device will not respond if it is busy. 242 '' The device select code is modified using the upper 3 bits of the 18 bit addrReg. 243 '' This returns zero if no error occurred or one if the device didn't respond. 244 devSel |= addrReg >> 15 & %1110 245 Start 246 ackbit := Write(devSel | Xmit) 247 Stop 248 return ackbit 249 250 251 ' *************** JAMES'S Extra BITS ********************* 252 253 PUB devicePresent(deviceAddress) : ackbit 254 ' send the deviceAddress and listen for the ACK 255 Start 256 ackbit := Write(deviceAddress | 0) 257 Stop 258 if ackbit == ACK 259 return true 260 else 261 return false 262 263 PUB writeLocation(device_address, register, value) 264 start 265 write(device_address) 266 write(register) 267 write(value) 268 stop 269 270 PUB readLocation(device_address, register) : value 271 start 272 write(device_address | 0) 273 write(register) 274 start 275 write(device_address | 1) 276 value := read(NAK) 277 stop 278 return value 279 280 '************************************* Jacob's extra bits 281 PUB writeString(device_address, arrayPtr ) 282 start

Page 106: Appendix C - Code Listing

  106  

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 'Standard clock 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

Page 107: Appendix C - Code Listing

  107  

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 animation 111 lcd.line(3)

Page 108: Appendix C - Code Listing

  108  

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(" ")

Page 109: Appendix C - Code Listing

  109  

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("!") ' echo to show we're alive 218 $27: doFSM($22) 219 $22: doFSM(":") 220 doFSM("4") 221 doFSM("C") 222 doFSM("'") 223 "T": lcd.str(String("Team Spectrum ",4,1,2,3,4)) 224 ADDRESS0: 225 hex := hex2nib( c ) 226 if hex == -1 227 term.str(term.str(@badhex)) ' debug 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

Page 110: Appendix C - Code Listing

  110  

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

Page 111: Appendix C - Code Listing

  111  

330 STRSEND = 6 331 SENDING = 7 332 333 DAT 334 state byte 0 335 k byte 1 336 nan byte $ff 337 buff byte 0[64],0 338 339 340 DAT 341 342 badhex byte "Invalid Input",0 343 clearline byte " ",0 344 345 346 rotarybuff long $12345678[8] 347 msg byte " "[32] ,0 348 349 'Define some custom characters to 350 'form the Team Spectrum logo on LCD2 351 'Characters are 5 wide by 7 high 352 'So these bits:\ are unused 353 ' ||| 354 ' vvv 355 LOGO1 byte %000_00000 356 byte %000_00000 357 byte %000_00000 358 byte %000_01000 359 byte %000_01000 360 byte %000_01000 361 byte %000_01001 362 byte %000_10110 363 ' 364 LOGO2 byte %000_00100 365 byte %000_00100 366 byte %000_00100 367 byte %000_00100 368 byte %000_00100 369 byte %000_01010 370 byte %000_01010 371 byte %000_10001 372 ' 373 LOGO3 byte %000_00000 374 byte %000_00000 375 byte %000_00000 376 byte %000_00010 377 byte %000_00010 378 byte %000_00010 379 byte %000_10010 380 byte %000_01101 381 ' 382 LOGO4 byte %000_00000 383 byte %000_00000 384 byte %000_00000 385 byte %000_00000 386 byte %000_00000 387 byte %000_00000 388 byte %000_00000 389 byte %000_11111 390  

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],

Page 112: Appendix C - Code Listing

  112  

8 as well as monitoring the other buttons 9 on the front panel 10 11 12 13 Call INIT first, which will take 2 COGs. 14 15 Then, call getChars, as often as you like. It will copy 16 any pending input in the 64 byte buffer to your pointer. 17 It is a valid string, ending in '0', to be sent to the 18 computer 19 20 21 Idea for keypad reader came from the 22 4x4KeypadReader v1.0 by Beau Schwabe (2007) 23 However, his did not work with the hybrid 24 button/matrix keypad, so I re-wrote it with active 25 low logic and now it works fine. 26 27 Also, since a cog must be dedicated to the rising 28 edge detector, I have mashed monitoring the other 29 buttons in here as well. So sorry if it is not an 30 ideal OO model :/ 31 }} 32 33 CON 34 NumControls = 18 35 BUF_PTR_MASK = $3F ' 64 byte tx buffer 36 37 OBJ 38 knobs : "Quadrature_Encoder" 39 VAR 40 long kpstack[128], delta 41 byte i,j, bit 42 43 44 PUB INIT 45 cognew(EndlessLoop, @kpstack) 46 {Set up the Rotary Encoder object} 47 knobs.Start(8, 2, 2, @rotarybuff) 48 49 PUB GetChars(loc) 50 '' Get the current input string waiting to be sent to 51 '' the computer (copy to buffer) 52 repeat until j == i 53 byte[loc++] := buff[j++] 54 j &= BUF_PTR_MASK 55 56 delta := knobs.ReadDelta(0) 57 repeat while delta > 0 58 byte[loc++] := "<" 59 delta -- 60 repeat while delta < 0 61 byte[loc++] := ">" 62 delta ++ 63 64 ' Read the bottom knob 65 delta := knobs.ReadDelta(1) 66 repeat while delta > 0 67 byte[loc++] := "{" 68 delta -- 69 repeat while delta < 0 70 byte[loc++] := "}" 71 delta ++ 72 73 byte[loc++] := 0 74 75 PRI EndlessLoop 76 '' Endless loop for a new COG 77 repeat 78 ReadRows ' Read the row data from the keypad 79 ReadBtns ' Read the additional buttons 80 CalcChange ' Rising edge detector

Page 113: Appendix C - Code Listing

  113  

81 82 PRI ReadBtns 83 '' This reads the buttons, so that the same rising edge detector can be 84 '' used with the keypad 85 keypad <<= 2 86 keypad |= ina[12..13] 87 keypad <<= 1 88 keypad |= ina[23] 89 90 PRI ReadRows 91 '' Keypad read-rows routine 92 keypad := 0 'Clear 4x4 'keypad' value 93 ReadRow(3) 'Call routine to read entire ROW 0 94 keypad <<= 4 'Shift 'keypad' value left by 4 95 ReadRow(2) 'Call routine to read entire ROW 1 96 keypad <<= 4 'Shift 'keypad' value left by 4 97 ReadRow(1) 'Call routine to read entire ROW 2 98 keypad <<= 4 'Shift 'keypad' value left by 4 99 ReadRow(0) 'Call routine to read entire ROW 3 100 101 PRI ReadRow(n) 102 '' Keypad Read a Row routine. Uses the keepers on the IO pins to get around 103 '' having to use pullup resistors 104 dira[0..7] ~ ' all pins input 105 outa[0..7] ~ ' first discharge to low 106 outa[0..7] ~~ ' ' preset to high 107 dira[0..7] ~~ ' all output, set keepers high 108 dira[0..7] ~ ' all input, keepers maintain last 109 outa[n] := 0 ' Clear one row 110 dira[n] := 1 ' Activate output on that row 111 dira[n] := 0 ' Deactivate, keeper maintains 112 keypad += ina[4..7] ' Add in result 113 114 115 PRI CalcChange 116 '' Simple rising edge detector 117 st1 := st0 118 st0 := !keypad ' active low 119 kpchange:= st0 & (st0 ^ st1) ' rising edge 120 121 repeat bit from 0 to numcontrols 122 if (kpchange & 1) == 1 123 PutChar( kplut[bit] ) 124 kpchange >>= 1 125 126 127 128 buff[i] := 0 ' signal end of string 129 130 PRI PutChar(c) 131 '' Add a character to the buffer 132 buff[i] := c 133 i := (i+1) & BUF_PTR_MASK ' circular buffer 134 135 136 DAT 137 kplut byte "PYX321A654B987C#0*D" 138 139 buff byte " "[64],0 140 141 keypad long 0 ' holds the keypad stuff 142 st1 long 0 143 st0 long 0 144 kpchange long 0 145 rotarybuff long $12345678[4]  

1.5.4 pcFullDuplexSerial.spin

1 ''************************************ 2 ''* Full-Duplex Serial Driver v1.1 * 3 ''* (C) 2006 Parallax, Inc. *

Page 114: Appendix C - Code Listing

  114  

4 ''* * 5 ''* * 6 ''* * 7 ''************************************ 8 ''* * 9 ''* now with 64 byte rx buffers * 10 ''************************************ 11 12 13 VAR 14 15 long cog 'cog flag/id 16 17 long rx_head '9 contiguous longs 18 long rx_tail 19 long tx_head 20 long tx_tail 21 long rx_pin 22 long tx_pin 23 long rxtx_mode 24 long bit_ticks 25 long buffer_ptr 26 27 byte rx_buffer[64] 'transmit and receive buffers 28 byte tx_buffer[16] 29 30 31 PUB start(rxpin, txpin, mode, baudrate) : okay 32 '' Start serial driver - starts a cog 33 '' returns false if no cog available 34 '' 35 '' mode bit 0 = invert rx 36 '' mode bit 1 = invert tx 37 '' mode bit 2 = open-drain/source tx 38 '' mode bit 3 = ignore tx echo on rx 39 40 stop 41 longfill(@rx_head, 0, 4) 42 longmove(@rx_pin, @rxpin, 3) 43 bit_ticks := clkfreq / baudrate 44 buffer_ptr := @rx_buffer 45 okay := cog := cognew(@entry, @rx_head) + 1 46 47 48 PUB stop 49 '' Stop serial driver - frees a cog 50 if cog 51 cogstop(cog~ - 1) 52 longfill(@rx_head, 0, 9) 53 54 PUB getCogID : result 55 return cog -1 56 57 PUB rxflush 58 '' Flush receive buffer 59 repeat while rxcheck => 0 60 61 62 PUB rxcheck : rxbyte 63 '' Check if byte received (never waits) 64 '' returns -1 if no byte received, $00..$FF if byte 65 rxbyte-- 66 if rx_tail <> rx_head 67 rxbyte := rx_buffer[rx_tail] 68 rx_tail := (rx_tail + 1) & $3F 69 70 71 PUB rxtime(ms) : rxbyte | t 72 '' Wait ms milliseconds for a byte to be received 73 '' returns -1 if no byte received, $00..$FF if byte 74 t := cnt 75 repeat until (rxbyte := rxcheck) => 0 or (cnt - t) / (clkfreq / 1000) > ms 76

Page 115: Appendix C - Code Listing

  115  

77 78 PUB rx : rxbyte 79 '' Receive byte (may wait for byte) 80 '' returns $00..$FF 81 repeat while (rxbyte := rxcheck) < 0 82 83 84 PUB tx(txbyte) 85 '' Send byte (may wait for room in buffer) 86 repeat until (tx_tail <> (tx_head + 1) & $F) 87 tx_buffer[tx_head] := txbyte 88 tx_head := (tx_head + 1) & $F 89 90 if rxtx_mode & %1000 91 rx 92 93 94 PUB str(stringptr) 95 '' Send string 96 repeat strsize(stringptr) 97 tx(byte[stringptr++]) 98 99 100 PUB dec(value) | i 101 '' Print a decimal number 102 if value < 0 103 -value 104 tx("-") 105 106 i := 1_000_000_000 107 108 repeat 10 109 if value => i 110 tx(value / i + "0") 111 value //= i 112 result~~ 113 elseif result or i == 1 114 tx("0") 115 i /= 10 116 117 118 PUB hex(value, digits) 119 '' Print a hexadecimal number 120 value <<= (8 - digits) << 2 121 repeat digits 122 tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F")) 123 124 125 PUB bin(value, digits) 126 '' Print a binary number 127 value <<= 32 - digits 128 repeat digits 129 tx((value <-= 1) & 1 + "0") 130 131 132 DAT 133 134 '*********************************** 135 '* Assembly language serial driver * 136 '*********************************** 137 138 org 139 ' 140 ' 141 ' Entry 142 ' 143 entry mov t1,par 'get structure address 144 add t1,#4 << 2 'skip past heads and tails 145 146 rdlong t2,t1 'get rx_pin 147 mov rxmask,#1 148 shl rxmask,t2 149

Page 116: Appendix C - Code Listing

  116  

150 add t1,#4 'get tx_pin 151 rdlong t2,t1 152 mov txmask,#1 153 shl txmask,t2 154 155 add t1,#4 'get rxtx_mode 156 rdlong rxtxmode,t1 157 158 add t1,#4 'get bit_ticks 159 rdlong bitticks,t1 160 161 add t1,#4 'get buffer_ptr 162 rdlong rxbuff,t1 163 mov txbuff,rxbuff 164 'add txbuff,#16 165 add txbuff,#64 ' big RX buffer 166 167 test rxtxmode,#%100 wz 'init tx pin according to mode 168 test rxtxmode,#%010 wc 169 if_z_ne_c or outa,txmask 170 if_z or dira,txmask 171 172 mov txcode,#transmit 'initialize ping-pong multitasking 173 ' 174 ' 175 ' Receive 176 ' 177 receive jmpret rxcode,txcode 'run a chunk of transmit code, then return 178 179 test rxtxmode,#%001 wz 'wait for start bit on rx pin 180 test rxmask,ina wc 181 if_z_eq_c jmp #receive 182 183 mov rxbits,#9 'ready to receive byte 184 mov rxcnt,bitticks 185 shr rxcnt,#1 186 add rxcnt,cnt 187 188 :bit add rxcnt,bitticks 'ready next bit period 189 190 :wait jmpret rxcode,txcode 'run a chuck of transmit code, then return 191 192 mov t1,rxcnt 'check if bit receive period done 193 sub t1,cnt 194 cmps t1,#0 wc 195 if_nc jmp #:wait 196 197 test rxmask,ina wc 'receive bit on rx pin 198 rcr rxdata,#1 199 djnz rxbits,#:bit 200 201 shr rxdata,#32-9 'justify and trim received byte 202 and rxdata,#$FF 203 test rxtxmode,#%001 wz 'if rx inverted, invert byte 204 if_nz xor rxdata,#$FF 205 206 rdlong t2,par 'save received byte and inc head 207 add t2,rxbuff 208 wrbyte rxdata,t2 209 sub t2,rxbuff 210 add t2,#1 211 'and t2,#$F 212 and t2,#$3F ' big buffers 213 wrlong t2,par 214 215 jmp #receive 'byte done, receive next byte 216 ' 217 ' 218 ' Transmit 219 ' 220 transmit jmpret txcode,rxcode 'run a chunk of receive code, then retu

Page 117: Appendix C - Code Listing

  117  

rn 221 222 mov t1,par 'check for head <> tail 223 add t1,#2 << 2 224 rdlong t2,t1 225 add t1,#1 << 2 226 rdlong t3,t1 227 cmp t2,t3 wz 228 if_z jmp #transmit 229 230 add t3,txbuff 'get byte and inc tail 231 rdbyte txdata,t3 232 sub t3,txbuff 233 add t3,#1 234 and t3,#$0F 235 wrlong t3,t1 236 237 or txdata,#$100 'ready byte to transmit 238 shl txdata,#2 239 or txdata,#1 240 mov txbits,#11 241 mov txcnt,cnt 242 243 :bit test rxtxmode,#%100 wz 'output bit on tx pin according to mode 244 test rxtxmode,#%010 wc 245 if_z_and_c xor txdata,#1 246 shr txdata,#1 wc 247 if_z muxc outa,txmask 248 if_nz muxnc dira,txmask 249 add txcnt,bitticks 'ready next cnt 250 251 :wait jmpret txcode,rxcode 'run a chunk of receive code, then return 252 253 mov t1,txcnt 'check if bit transmit period done 254 sub t1,cnt 255 cmps t1,#0 wc 256 if_nc jmp #:wait 257 258 djnz txbits,#:bit 'another bit to transmit? 259 260 jmp #transmit 'byte done, transmit next byte 261 ' 262 ' 263 ' Uninitialized data 264 ' 265 t1 res 1 266 t2 res 1 267 t3 res 1 268 269 rxtxmode res 1 270 bitticks res 1 271 272 rxmask res 1 273 rxbuff res 1 274 rxdata res 1 275 rxbits res 1 276 rxcnt res 1 277 rxcode res 1 278 279 txmask res 1 280 txbuff res 1 281 txdata res 1 282 txbits res 1 283 txcnt res 1 284 txcode res 1  

1.5.5 Quadrature_Encoder.spin

1 {{ 2 *************************************

Page 118: Appendix C - Code Listing

  118  

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 encoder-reading 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 StartPin+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 Write. 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 test Pin, #$20 wc 'Test for upper or lower port 65 muxc :PinSrc, #%1 'Adjust :PinSrc instruction f

Page 119: Appendix C - Code Listing

  119  

or proper port 66 mov IPosAddr, #IntPos 'Clear all internal encoder position values 67 movd :IClear, IPosAddr ' set starting internal pointer 68 mov Idx, TotEnc ' for all encoders... 69 :IClear mov 0, #0 ' clear internal memory 70 add IPosAddr, #1 ' increment pointer 71 movd :IClear, IPosAddr 72 djnz Idx, #:IClear ' loop for each encoder 73 74 mov St2, ina 'Take first sample of encoder pins 75 shr St2, Pin 76 :Sample mov IPosAddr, #IntPos 'Reset encoder position buffer addresses 77 movd :IPos+0, IPosAddr 78 movd :IPos+1, IPosAddr 79 mov MPosAddr, PAR 80 mov St1, St2 'Calc 2-bit signed offsets (St1 = B1:A1) 81 mov T1, St2 ' T1 = B1:A1 82 shl T1, #1 ' T1 = A1:x 83 :PinSrc mov St2, inb ' Sample encoders (St2 = B2:A2 left shifted by first encoder offset) 84 shr St2, Pin ' Adj for first encoder (St2 = B2:A2) 85 xor St1, St2 ' St1 = B1^B2:A1^A2 86 xor T1, St2 ' T1 = A1^B2:x 87 and T1, BMask ' T1 = A1^B2:0 88 or T1, AMask ' T1 = A1^B2:1 89 mov T2, St1 ' T2 = B1^B2:A1^A2 90 and T2, AMask ' T2 = 0:A1^A2 91 and St1, BMask ' St1 = B1^B2:0 92 shr St1, #1 ' St1 = 0:B1^B2 93 xor T2, St1 ' T2 = 0:A1^A2^B1^B2 94 mov St1, T2 ' St1 = 0:A1^B2^B1^A2 95 shl St1, #1 ' St1 = A1^B2^B1^A2:0 96 or St1, T2 ' St1 = A1^B2^B1^A2:A1^B2^B1^A2 97 and St1, T1 ' St1 = A1^B2^B1^A2&A1^B2:A1^B2^B1^A2 98 mov Idx, TotEnc 'For all encoders... 99 :UpdatePos ror St1, #2 'Rotate current bit pair into 31:30 100 mov Diff, St1 'Convert 2-bit signed to 32-bit signed Diff 101 sar Diff, #30 102 :IPos add 0, Diff 'Add to encoder position value 103 wrlong 0, MPosAddr 'Write new position to main memory 104 add IPosAddr, #1 'Increment encoder position addresses 105 movd :IPos+0, IPosAddr 106 movd :IPos+1, IPosAddr 107 add MPosAddr, #4 108 :Next djnz Idx, #:UpdatePos 'Loop for each encoder 109 jmp #:Sample 'Loop forever 110

Page 120: Appendix C - Code Listing

  120  

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 pair 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 position counter (Internal Memory) 127 MPosAddr res 1 'Address of current encoder position counter (Main Memory) 128 IntPos res 16 'Internal encoder position counter buffer 129 130 131 132 {{ 133 ************************** 134 * FUNCTIONAL DESCRIPTION * 135 ************************** 136 137 Reads 1 to 16 two-bit gray-code quadrature encoders and provides 32-bit 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 for speed boundary calculations. 139 140 Connect each encoder to two contiguous I/O pins (multiple encoders must be connected to a contiguous 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 requiring delta position support. 142 143 To use this object: 144 1) Create a position buffer (array of longs). The position buffer MUST contain NumEnc + NumDelta longs. The first NumEnc longs of the position buffer 145 will always contain read-only, absolute positions for the respective encoders. The remaining NumDelta longs of the position buffer will be "last 146 absolute read" storage for providing delta position support (if used) and should be ignored (use ReadDelta() method instead). 147 2) Call Start() passing in the starting pin number, number of encoders, number needing delta 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 Stop is called. 149 3) Read position buffer (first NumEnc values) to obtain an absolute 32-bit 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 two-encoder reader (encoders connected to pins 8 - 11) 164

Page 121: Appendix C - Code Listing

  121  

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*(TotEnc-1) 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 / EncReaderCogCycles / 2 / MaxEncPulsesPerRevolution * 60 176 177 Example 1: Using a 4 MHz crystal, 8x internal multiplier, 16 encoders where the highest resolution 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 2-bit, gray code quadrature encoder output (encoder pins A and B) and their possible transitions (assuming 189 we're sampling fast enough). A1 is the previous value of pin A, A2 is the current value of pin 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 2-bit 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 2-bit 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 convenient 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 | Counter- 219 10 -> 11 | 10 | 11 | -1 | Clockwise 220 11 -> 01 | 10 | 11 | -1 | 221 01 -> 00 | 10 | 11 | -1 | 222 }

Page 122: Appendix C - Code Listing

  122  

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 software and associated documentation │ 229 │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ 230 │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 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 substantial portions of the Software.│ 234 │ │ 235 │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ 236 │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 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 '** Controlls the web4robot I2C LCD 3 '** Jacob Dilles <[email protected]> 6/8/2012 4 '** Version 1.00 5 '*********************************************** 6 7 CON 8 lcd2 = $4c << 1 | 0 ' 7 bit address 9 10 ' Initial values 11 LCD_BRIGHTNESS = 100 ' 0 - 250 12 LCD_CONTRAST = 80 ' 0 - 100 13 OBJ 14 i2cObject : "basic_i2c_driver" 15 16 VAR 17 byte _contrast 18 byte _brightness 19 20 PUB Start 21 '' set initial values 22 _contrast := LCD_CONTRAST 23 _brightness := LCD_BRIGHTNESS 24 25 ' set initial state (on) 26 clear 27 on 'power on 28 contrast(_contrast) 29 30 PUB brightness(br) 31 '' Set the brightness value 0-250 32 i2cObject.start 33 i2cObject.write(lcd2)

Page 123: Appendix C - Code Listing

  123  

34 i2cObject.write($fe) 35 i2cObject.write($03) 36 i2cObject.write(br) 37 i2cObject.stop 38 39 PUB contrast(cn) 40 '' Set the contrast value 0 - 100 41 i2cObject.start 42 i2cObject.write(lcd2) 43 i2cObject.write($fe) 44 i2cObject.write($04) 45 i2cObject.write(cn) 46 i2cObject.stop 47 48 PUB pos(x, y) 49 '' Set the cursor position. X = 0..19, Y = 0..3 50 i2cObject.start 51 i2cObject.write(lcd2) 52 i2cObject.write($fe) 53 i2cObject.write($0C) 54 i2cObject.write(x) 55 i2cObject.write(y) 56 i2cObject.stop 57 58 PUB line(ln) 59 '' Move to the start of the given line 60 pos(0,ln) 61 62 PUB home 63 '' Move the cursor to the home position 64 i2cObject.start 65 i2cObject.write(lcd2) 66 i2cObject.write($fe) 67 i2cObject.write($0D) 68 i2cObject.stop 69 70 PUB off 71 '' Turn the LCD off (does not affect backlight) 72 i2cObject.start 73 i2cObject.write(lcd2) 74 i2cObject.write($fe) 75 i2cObject.write($0B) 76 i2cObject.stop 77 brightness(0) 78 79 PUB on 80 '' Turn the LCD on 81 i2cObject.start 82 i2cObject.write(lcd2) 83 i2cObject.write($fe) 84 i2cObject.write($0A) 85 i2cObject.stop 86 brightness(_brightness) 87 88 PUB underline(en) 89 '' Turn on or off the cursor underline 90 i2cObject.start 91 i2cObject.write(lcd2) 92 i2cObject.write($fe) 93 if en 94 i2cObject.write($0E) 95 else 96 i2cObject.write($0F) 97 i2cObject.stop 98 99 PUB left 100 '' Move the cursor left one position 101 i2cObject.start 102 i2cObject.write(lcd2) 103 i2cObject.write($fe) 104 i2cObject.write($10) 105 i2cObject.stop 106

Page 124: Appendix C - Code Listing

  124  

107 PUB right 108 '' Move the cursor right one position 109 i2cObject.start 110 i2cObject.write(lcd2) 111 i2cObject.write($fe) 112 i2cObject.write($11) 113 i2cObject.stop 114 115 PUB space 116 i2cObject.start 117 i2cObject.write(lcd2) 118 i2cObject.write($20) 119 i2cObject.stop 120 121 PUB blink(en) 122 '' Turn on or off the cursor blink 123 i2cObject.start 124 i2cObject.write(lcd2) 125 i2cObject.write($fe) 126 if en 127 i2cObject.write($12) 128 else 129 i2cObject.write($13) 130 i2cObject.stop 131 132 PUB clear 133 '' Move the cursor left one position 134 i2cObject.start 135 i2cObject.write(lcd2) 136 i2cObject.write($fe) 137 i2cObject.write($14) 138 i2cObject.stop 139 140 PUB charmap(charaddr, map) 141 '' map a custom character 142 '' charaddr = 0 .. 7, custom character 143 '' map = a long (8 bytes) with character data 144 i2cObject.start 145 i2cObject.write(lcd2) 146 i2cObject.write($fe) 147 i2cObject.write($1A) 148 i2cObject.write(charaddr) 149 repeat 8 150 i2cObject.write( byte[map++] ) 151 i2cObject.stop 152 153 PUB out(b) 154 '' write a single byte 155 i2cObject.start 156 i2cObject.write(lcd2) 157 i2cObject.write(b) 158 i2cObject.stop 159 160 PUB str(stringloc) 161 '' Write an ASC-II string: writeString(@stringloc) or writeString("hi there") 162 i2cObject.writeString(lcd2, stringloc) 163 164 PUB writeBytes(byteloc, n) 165 i2cObject.writeBytes(lcd2, byteloc, n) 166 167 PUB bin(value, nbits) 168 bin2str(value, @msg, nbits) 169 writeBytes(@msg, nbits) 170 171 PUB hex(value, nchars) 172 hex2str(value, @msg, nchars) 173 writeBytes(@msg, nchars) 174 175 PRI bin2str(val, strloc,n) 176 '' Buffer a value as binary 177 val <<= 32-n 178 repeat n 179 byte[strloc++]:=((val <-= 1) & 1 + "0")

Page 125: Appendix C - Code Listing

  125  

180 181 pri hex2str(value, strloc, digits) 182 '' Print a hexadecimal number 183 value <<= (8 - digits) << 2 184 repeat digits 185 byte[strloc++] := lookupz((value <-= 4) & $F : "0".."9", "A".."F") 186 187 DAT 188 '------------ LCD comand strings ------------ 189 lcd_clear byte $fe, $14, 0 190 lcd_pow_on byte $fe, $0A, 0 191 lcd_pow_off byte $fe, $0B, 0 192 lcd_home byte $fe, $0d, 0 193 194 195 ' ----------------- String Buffer 196 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

Page 126: Appendix C - Code Listing

  126  

WIRE 176 256 144 256 WIRE 304 256 256 256 WIRE 352 256 304 256 WIRE 400 256 352 256 WIRE 448 256 400 256 WIRE 464 256 448 256 WIRE 560 256 560 240 WIRE 560 256 544 256 WIRE 608 256 560 256 WIRE 736 256 736 112 WIRE 736 256 688 256 WIRE 784 256 736 256 WIRE 944 256 944 240 WIRE 944 256 864 256 WIRE 1024 256 944 256 WIRE 1136 256 1104 256 WIRE 1184 256 1136 256 WIRE -752 272 -752 240 WIRE -576 272 -576 256 WIRE -496 272 -496 256 WIRE 944 272 944 256 WIRE 304 288 304 256 WIRE 352 288 352 256 WIRE 400 288 400 256 WIRE 1136 288 1136 256 WIRE 144 320 144 256 WIRE 176 320 144 320 WIRE 256 320 256 256 WIRE 256 320 240 320 WIRE 1680 320 1680 304 WIRE -576 336 -576 320 WIRE 16 336 16 256 WIRE -496 352 -496 336 WIRE 448 352 448 256 WIRE 464 352 448 352 WIRE 560 352 560 256 WIRE 560 352 528 352 WIRE -576 368 -576 336 WIRE 352 368 352 352 WIRE 400 368 400 352 WIRE -240 384 -272 384 WIRE -144 384 -176 384 WIRE 1136 400 1136 368 WIRE 1680 432 1680 400 WIRE 1680 432 1664 432 WIRE 1760 432 1680 432 WIRE 1888 432 1840 432 WIRE -656 448 -736 448 WIRE -592 448 -656 448 WIRE -528 448 -592 448 WIRE -448 448 -528 448 WIRE -384 448 -448 448 WIRE -368 448 -384 448 WIRE 1680 448 1680 432 WIRE 16 464 -64 384 WIRE 16 464 16 416 WIRE 160 464 16 464 WIRE 256 464 224 464 WIRE -736 480 -736 448 WIRE -656 496 -656 448 WIRE -384 496 -384 448 WIRE -288 496 -288 448 WIRE 16 496 16 464 WIRE 16 496 -288 496 WIRE -656 512 -656 496 WIRE -592 512 -592 448 WIRE -528 512 -528 448 WIRE -448 512 -448 448 WIRE 16 512 16 496 WIRE 1680 544 1680 528 WIRE -288 608 -288 592 WIRE 16 608 16 592 WIRE 16 608 -288 608

Page 127: Appendix C - Code Listing

  127  

WIRE -736 640 -736 560 WIRE -656 640 -656 576 WIRE -656 640 -736 640 WIRE -592 640 -592 576 WIRE -592 640 -656 640 WIRE -528 640 -528 576 WIRE -528 640 -592 640 WIRE -448 640 -448 576 WIRE -448 640 -528 640 WIRE -384 640 -384 608 WIRE -384 640 -448 640 WIRE -368 640 -384 640 WIRE -288 640 -288 608 WIRE 1680 640 1680 624 WIRE 1744 640 1680 640 WIRE 1840 640 1808 640 WIRE -288 656 -288 640 WIRE 16 656 16 608 WIRE 80 656 80 592 WIRE 80 656 16 656 WIRE 160 656 80 656 WIRE 256 656 224 656 WIRE 1680 656 1680 640 WIRE 1840 688 1840 640 WIRE 1840 688 1792 688 WIRE 1840 704 1840 688 WIRE 16 720 16 656 WIRE -240 736 -272 736 WIRE -144 736 -176 736 WIRE -64 736 16 656 WIRE -736 752 -736 720 WIRE 144 752 144 720 WIRE 368 752 368 736 WIRE 416 752 416 720 WIRE 192 768 176 768 WIRE 288 768 256 768 WIRE 464 768 448 768 WIRE 560 768 528 768 WIRE 1680 768 1680 736 WIRE 1728 768 1680 768 WIRE 1792 768 1792 688 WIRE 1680 816 1680 768 WIRE 16 864 16 800 WIRE 16 864 -16 864 WIRE 48 864 16 864 WIRE 144 864 144 816 WIRE 144 864 128 864 WIRE 176 864 176 768 WIRE 176 864 144 864 WIRE 192 864 176 864 WIRE 288 864 288 768 WIRE 288 864 272 864 WIRE 336 864 336 816 WIRE 336 864 288 864 WIRE 368 864 368 816 WIRE 368 864 336 864 WIRE 416 864 416 816 WIRE 416 864 368 864 WIRE 448 864 448 768 WIRE 448 864 416 864 WIRE 464 864 448 864 WIRE 560 864 560 768 WIRE 560 864 544 864 WIRE 624 864 560 864 WIRE 736 864 736 816 WIRE 736 864 704 864 WIRE 784 864 736 864 WIRE 944 864 944 848 WIRE 944 864 864 864 WIRE 1024 864 944 864 WIRE 1136 864 1104 864 WIRE 1216 864 1136 864 WIRE 944 880 944 864

Page 128: Appendix C - Code Listing

  128  

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

Page 129: Appendix C - Code Listing

  129  

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

Page 130: Appendix C - Code Listing

  130  

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

Page 131: Appendix C - Code Listing

  131  

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

Page 132: Appendix C - Code Listing

  132  

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

Page 133: Appendix C - Code Listing

  133  

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