Index: firmware/FTM/ftu_control/FTM_ftu_control.vhd
===================================================================
--- firmware/FTM/ftu_control/FTM_ftu_control.vhd	(revision 10929)
+++ firmware/FTM/ftu_control/FTM_ftu_control.vhd	(revision 11485)
@@ -56,17 +56,20 @@
     tx_d_3 : out STD_LOGIC;
 
-    -- commands from FTM main control
-    new_config : in std_logic;
-    ping_all   : in std_logic;
-    read_rates : in std_logic;
-
-    -- answers to FTM main control
-    read_rates_started : out std_logic := '0';
-    read_rates_done    : out std_logic := '0';
-    new_config_started : out std_logic := '0';
-    new_config_done    : out std_logic := '0';
-    ping_all_started   : out std_logic := '0';
-    ping_all_done      : out std_logic := '0';
-
+    -- commands from FTM central control
+    new_config        : in std_logic;
+    ping_all          : in std_logic;
+    read_rates        : in std_logic;
+    config_single_FTU : in std_logic;
+    
+    -- answers to FTM central control
+    read_rates_started        : out std_logic := '0';
+    read_rates_done           : out std_logic := '0';
+    new_config_started        : out std_logic := '0';
+    new_config_done           : out std_logic := '0';
+    ping_all_started          : out std_logic := '0';
+    ping_all_done             : out std_logic := '0';
+    config_single_FTU_started : out std_logic := '0';
+    config_single_FTU_done    : out std_logic := '0';
+    
     -- active FTU lists
     ftu_active_cr0 : in std_logic_vector (15 downto 0);
@@ -75,4 +78,7 @@
     ftu_active_cr3 : in std_logic_vector (15 downto 0);
 
+    -- parameter for config single FTU command
+    config_single_FTU_param : in std_logic_vector (15 DOWNTO 0);
+    
     --error message interface to ethernet control
     ftu_error_calls      : out std_logic_vector (15 DOWNTO 0) := (others => '0');
@@ -123,7 +129,9 @@
   
   -- FTU configuration data, read out from static RAM (board by board)
-  signal FTU_dac_array_RAM_sig    : FTU_dac_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'));
-  signal FTU_enable_array_RAM_sig : FTU_enable_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'));
-  signal FTU_prescaling_RAM_sig   : std_logic_vector(15 downto 0) := (others => '0');
+  signal FTU_dac_array_RAM_sig      : FTU_dac_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'));
+  signal FTU_dac_array_RAM_sig_2    : FTU_dac_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'));
+  signal FTU_enable_array_RAM_sig   : FTU_enable_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'));
+  signal FTU_enable_array_RAM_sig_2 : FTU_enable_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'));
+  signal FTU_prescaling_RAM_sig     : std_logic_vector(15 downto 0) := (others => '0');
   
   -- signals for receiver of FTU communication
@@ -216,5 +224,7 @@
   signal FTU_cnt             : integer range 0 to NO_OF_FTUS_PER_CRATE := 0;
   signal FTU_register_cnt    : integer range 0 to (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) := 0;
+  signal FTU_register_cnt_2  : integer range 0 to (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG) := 0;
   signal FTU_command_cnt     : integer range 0 to 3 := 0;
+  signal FTU_command_cnt_2   : integer range 0 to 2 := 0;
   signal frame_cnt           : integer range 0 to (FTU_RS485_BLOCK_WIDTH / 8) := 0;
   signal FTU_list_reg_cnt    : integer range 0 to NO_OF_FTU_LIST_REG := 0;
@@ -229,4 +239,8 @@
   signal FTU_cnt_offset_sig   : integer range 0 to (NO_OF_DD_RAM_REG * NO_OF_FTUS_PER_CRATE) := 0;
   signal crate_cnt_offset_sig : integer range 0 to (NO_OF_CRATES * NO_OF_FTUS_PER_CRATE * NO_OF_DD_RAM_REG) := 0;
+
+  --Crate and Slot number for config_single_FTU command
+  signal single_FTU_crate_sig : integer range 0 to 7 := 0;
+  signal single_FTU_slot_sig  : integer range 0 to 15 := 0;
   
   component FTM_ftu_rs485_interface
@@ -306,5 +320,9 @@
                                            TRANSMIT_CONFIG_1, TRANSMIT_CONFIG_2, TRANSMIT_CONFIG_3,
                                            PING_1, PING_2, PING_3, PING_END_1, PING_END_2, PING_END_3,
-                                           FTU_LIST_1, FTU_LIST_2, FTU_LIST_3);
+                                           FTU_LIST_1, FTU_LIST_2, FTU_LIST_3,
+                                           GET_FTU_PAR, READ_CONFIG_SINGLE_FTU,
+                                           READ_CONFIG_SINGLE_FTU_1, READ_CONFIG_SINGLE_FTU_2, READ_CONFIG_SINGLE_FTU_3,
+                                           TRANSMIT_CONFIG_SINGLE_FTU_1, TRANSMIT_CONFIG_SINGLE_FTU_2, TRANSMIT_CONFIG_SINGLE_FTU_3,
+                                           TRANSMIT_CONFIG_SINGLE_FTU, CONFIG_SINGLE_FTU_END);
   signal FTM_ftu_rs485_control_State : FTM_ftu_rs485_control_StateType;
   signal after_error_State : FTM_ftu_rs485_control_StateType;
@@ -446,26 +464,37 @@
           --read_rates_done <= '0';
           if (new_config = '1') then
-            new_config_done <= '0';--
+            new_config_done <= '0';
             new_config_started <= '1';
             ping_all_started   <= '0';
             read_rates_started <= '0';
+            config_single_FTU_started <= '0';
             FTM_ftu_rs485_control_State <= ACTIVE_LIST;
           elsif (new_config = '0' and  ping_all = '1') then
-            ping_all_done   <= '0';--
+            ping_all_done   <= '0';
             new_config_started <= '0';
             ping_all_started   <= '1';
             read_rates_started <= '0';
+            config_single_FTU_started <= '0';
             rec_reset_sig <= '1';
             FTM_ftu_rs485_control_State <= PING;
           elsif (new_config = '0' and  ping_all = '0' and read_rates = '1') then
-            read_rates_done <= '0';--
+            read_rates_done <= '0';
             new_config_started <= '0';
             ping_all_started   <= '0';
             read_rates_started <= '1';
+            config_single_FTU_started <= '0';
             FTM_ftu_rs485_control_State <= RATES;
-          else
+          elsif (new_config = '0' and  ping_all = '0' and read_rates = '0' and config_single_FTU = '1') then
+            config_single_FTU_done <= '0';
             new_config_started <= '0';
             ping_all_started   <= '0';
             read_rates_started <= '0';
+            config_single_FTU_started <= '1';
+            FTM_ftu_rs485_control_State <= GET_FTU_PAR;
+          else
+            new_config_started <= '0';
+            ping_all_started   <= '0';
+            read_rates_started <= '0';
+            config_single_FTU_started <= '0';
             FTM_ftu_rs485_control_State <= IDLE;
           end if;
@@ -477,4 +506,9 @@
           active_FTU_array_sig(3) <= ftu_active_cr3;
           FTM_ftu_rs485_control_State <= READ_CONFIG;
+
+        when GET_FTU_PAR =>  -- copy FTU parameter (crate and slot) from input
+          single_FTU_crate_sig <= conv_integer(unsigned(config_single_FTU_param( 2 downto 0)));
+          single_FTU_slot_sig  <= conv_integer(unsigned(config_single_FTU_param(11 downto 8)));
+          FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU;
           
 --        when ACTIVE_LIST =>  -- loop over 4 crates to get active FTU list
@@ -536,4 +570,19 @@
           end if;
 
+        when READ_CONFIG_SINGLE_FTU =>  -- read configuration of one FTU
+          sel_crate_sig <= conv_std_logic_vector(single_FTU_crate_sig, 3);
+          if (FTU_register_cnt_2 < (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG)) then
+            FTU_register_cnt_2 <= FTU_register_cnt_2 + 1;
+            FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU_1;
+          else
+            FTU_register_cnt_2 <= 0;
+            if (active_FTU_array_sig(single_FTU_crate_sig)(single_FTU_slot_sig) = '1') then
+              rec_reset_sig <= '1';
+              FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU;
+            else
+              FTM_ftu_rs485_control_State <= CONFIG_SINGLE_FTU_END;
+            end if;
+          end if;
+            
         when READ_CONFIG_1 =>
           if (static_RAM_busy = '0') then
@@ -545,10 +594,25 @@
             FTM_ftu_rs485_control_State <= READ_CONFIG_2;
           end if;
-            
+
+        when READ_CONFIG_SINGLE_FTU_1 =>
+          if (static_RAM_busy = '0') then
+            read_static_RAM <= '1';
+            addr_static_RAM <= conv_std_logic_vector(STATIC_RAM_CFG_FTU_OFFSET +
+                                                     single_FTU_crate_sig * NO_OF_FTUS_PER_CRATE * (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) +
+                                                     single_FTU_slot_sig * (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) +
+                                                     (FTU_register_cnt_2 - 1), STATIC_RAM_ADDR_WIDTH);
+            FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU_2;
+          end if;
+          
         when READ_CONFIG_2 =>
           if (static_RAM_started = '1') then
             FTM_ftu_rs485_control_State <= READ_CONFIG_3;
           end if;
-            
+
+        when READ_CONFIG_SINGLE_FTU_2 =>
+          if (static_RAM_started = '1') then
+            FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU_3;
+          end if;
+          
         when READ_CONFIG_3 =>
           if (static_RAM_ready = '1') then
@@ -562,4 +626,15 @@
             read_static_RAM <= '0';
             FTM_ftu_rs485_control_State <= READ_CONFIG;
+          end if;
+
+        when READ_CONFIG_SINGLE_FTU_3 =>
+          if (static_RAM_ready = '1') then
+            if ((FTU_register_cnt_2 - 1) < NO_OF_FTU_ENABLE_REG) then
+              FTU_enable_array_RAM_sig_2(FTU_register_cnt_2 - 1) <= data_static_RAM;
+            elsif ((FTU_register_cnt_2 - 1) < (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG)) then
+              FTU_dac_array_RAM_sig_2((FTU_register_cnt_2 - 1) - NO_OF_FTU_ENABLE_REG) <= data_static_RAM;
+            end if;
+            read_static_RAM <= '0';
+            FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU;
           end if;
           
@@ -621,4 +696,47 @@
             FTM_ftu_rs485_control_State <= READ_CONFIG;
           end if;
+
+        when TRANSMIT_CONFIG_SINGLE_FTU =>  -- send configuration to one FTU
+          rec_reset_sig <= '0';
+          if (FTU_command_cnt_2 = 0) then  -- DACs
+            FTU_command_cnt_2 <= FTU_command_cnt_2 + 1;
+            enable_crc_from_FSM_sig <= '1';
+            crc_data_from_FSM_sig <= "00000000"
+                                     & "00000000" & "00000000" & "00000000" & "00000000" & "00000000"
+                                     & "00000000" & "00000000" & "00000000" & "00000000" & "00000000"
+                                     & "00000000"
+                                     & FTU_dac_array_RAM_sig_2(4)(15 downto 8) & FTU_dac_array_RAM_sig_2(4)(7 downto 0)
+                                     & FTU_dac_array_RAM_sig_2(3)(15 downto 8) & FTU_dac_array_RAM_sig_2(3)(7 downto 0)
+                                     & FTU_dac_array_RAM_sig_2(2)(15 downto 8) & FTU_dac_array_RAM_sig_2(2)(7 downto 0)
+                                     & FTU_dac_array_RAM_sig_2(1)(15 downto 8) & FTU_dac_array_RAM_sig_2(1)(7 downto 0)
+                                     & FTU_dac_array_RAM_sig_2(0)(15 downto 8) & FTU_dac_array_RAM_sig_2(0)(7 downto 0)
+                                     & "00000000" & FIRMWARE_ID & FTM_ADDRESS
+                                     & "00" & conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2)
+                                     & FTU_RS485_START_DELIM;
+            FTU_brd_add_sig <= conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2);
+            FTU_command_sig <= "00000000";
+            FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_1;
+          elsif (FTU_command_cnt_2 = 1) then  -- enables
+            FTU_command_cnt_2 <= FTU_command_cnt_2 + 1;
+            enable_crc_from_FSM_sig <= '1';
+            crc_data_from_FSM_sig <= "00000000"
+                                     & "00000000" & "00000000" & "00000000" & "00000000" & "00000000"
+                                     & "00000000" & "00000000" & "00000000" & "00000000" & "00000000"
+                                     & "00000000" & "00000000" & "00000000"
+                                     & FTU_enable_array_RAM_sig_2(3)(15 downto 8) & FTU_enable_array_RAM_sig_2(3)(7 downto 0)
+                                     & FTU_enable_array_RAM_sig_2(2)(15 downto 8) & FTU_enable_array_RAM_sig_2(2)(7 downto 0)
+                                     & FTU_enable_array_RAM_sig_2(1)(15 downto 8) & FTU_enable_array_RAM_sig_2(1)(7 downto 0)
+                                     & FTU_enable_array_RAM_sig_2(0)(15 downto 8) & FTU_enable_array_RAM_sig_2(0)(7 downto 0)
+                                     & "00000011" & FIRMWARE_ID & FTM_ADDRESS
+                                     & "00" & conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2)
+                                     & FTU_RS485_START_DELIM;
+            FTU_brd_add_sig <= conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2);
+            FTU_command_sig <= "00000011";
+            FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_1;
+          else
+            FTU_command_cnt_2 <= 0;
+            enable_crc_from_FSM_sig <= '0';
+            FTM_ftu_rs485_control_State <= CONFIG_SINGLE_FTU_END;
+          end if;
             
         when TRANSMIT_CONFIG_1 =>  -- wait one cycle for CRC calculation
@@ -626,5 +744,10 @@
           crc_data_from_FSM_sig_cp <= crc_data_from_FSM_sig;
           FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2;
-          
+
+        when TRANSMIT_CONFIG_SINGLE_FTU_1 =>  -- wait one cycle for CRC calculation
+          enable_crc_from_FSM_sig <= '0';
+          crc_data_from_FSM_sig_cp <= crc_data_from_FSM_sig;
+          FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_2;
+            
         when TRANSMIT_CONFIG_2 =>  -- transmit byte by byte
           if (tx_busy_sig = '0') then
@@ -650,4 +773,28 @@
             FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2;
           end if;
+
+        when TRANSMIT_CONFIG_SINGLE_FTU_2 =>  -- transmit byte by byte
+          if (tx_busy_sig = '0') then
+            if (frame_cnt < 27) then
+              frame_cnt <= frame_cnt + 1;
+              tx_data_sig <= crc_data_from_FSM_sig (7 downto 0);
+              crc_data_from_FSM_sig <= "00000000" & crc_data_from_FSM_sig ((FTU_RS485_BLOCK_WIDTH - 9) downto 8);
+              tx_start_sig <= '1';
+              FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_2;
+            elsif (frame_cnt = 27) then
+              frame_cnt <= frame_cnt + 1;
+              ftu_error_data <= crc_sig & crc_data_from_FSM_sig_cp;
+              tx_data_sig <= crc_sig;
+              tx_start_sig <= '1';
+              FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_2;
+            else
+              frame_cnt <= 0;
+              reset_crc_from_FSM_sig <= '1';
+              FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_3;
+            end if;            
+          else
+            tx_start_sig <= '0';
+            FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_2;
+          end if;
           
         when TRANSMIT_CONFIG_3 =>  -- wait for FTU answer
@@ -687,4 +834,40 @@
           end if;
 
+          when TRANSMIT_CONFIG_SINGLE_FTU_3 =>  -- wait for FTU answer
+          reset_crc_from_FSM_sig <= '0';
+          if (FTU_answer_ok_sig = '1') then
+            timeout_cnt <= 0;
+            retry_cnt <= 0;
+            sel_crc_input_source_sig <= '0';
+            if (retry_cnt = 0) then  -- no errors 
+              FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU;
+            else  -- send error message and move to next command;
+              ftu_error_calls <= conv_std_logic_vector((retry_cnt + 1), 16);
+              after_error_State <= TRANSMIT_CONFIG_SINGLE_FTU;
+              FTM_ftu_rs485_control_State <= SEND_ERROR_1;
+            end if;
+          else
+            if (timeout_cnt < FTU_RS485_TIMEOUT) then
+              timeout_cnt <= timeout_cnt + 1;
+              sel_crc_input_source_sig <= '1';
+              FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_3;
+            else
+              timeout_cnt <= 0;
+              sel_crc_input_source_sig <= '0';
+              rec_reset_sig <= '1';
+              if (retry_cnt < FTU_RS485_NO_OF_RETRY) then
+                retry_cnt <= retry_cnt + 1;
+                FTU_command_cnt_2 <= FTU_command_cnt_2 - 1;  -- try this command again
+                FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU;
+              else
+                retry_cnt <= 0;
+                FTU_command_cnt_2 <= FTU_command_cnt_2;  -- send error message and move to next command
+                ftu_error_calls <= (others => '0');
+                after_error_State <= TRANSMIT_CONFIG_SINGLE_FTU;
+                FTM_ftu_rs485_control_State <= SEND_ERROR_1;
+              end if;
+            end if;
+          end if;
+          
         when SEND_ERROR_1 =>  -- send an error message
           ftu_error_send <= '1';
@@ -698,4 +881,10 @@
             FTM_ftu_rs485_control_State <= after_error_state;
           end if;
+
+        when CONFIG_SINGLE_FTU_END =>
+          config_single_FTU_started <= '0';
+          config_single_FTU_done <= '1';
+          sel_crate_sig <= "111";
+          FTM_ftu_rs485_control_State <= IDLE;
           
         when PING =>  -- ping all FTUs
