COMMS Working Group
Hawaii
Alaska
Pacific
Mountain
Central
Eastern
Puerto Rico
UTC
Guam
 
Icom AH4 Auto-Tuner Protocol Emulator
for the
MFJ-994BRT Remote Auto-Tuner
 
 
 
Version 0.03
25 November 2022
 
 
Copyright © 2022 Raymond B Montagne All rights reserved.
 
Table of Contents
  1. License
  2. Overview
  3. Icom AH4 Auto-Tuner Protocol
  4. Icom IC-7610 AH4 Tuner Interface
  5. Fox Delta HFB3 HF Balanced Bridge
  6. Fox Delta HFB3 HF Balanced Bridge Calibration
  7. Arduino AH4 Protocol Emulator
  8. Arduino AH4 Protocol Emulator Construction
  9. Software Overview
  10. SourceCode
  11. Station Configuration
  12. MFJ-994BRT Inverted-L Installation
  13. Device Operation
  14. Testing & Evaluation
  15. Conclusions

A pdf version of this article can be downloaded by clicking HERE.

Chapter 1 - LICENSE

BSD-3 Clause License

Copyright © 2022 Raymond B Montagne All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Chapter 2 - MFJ-994BRT REMOTE TUNER AND ICOM AH4 AUTO TUNER EMULATOR

My station includes an Icom transceiver driving an Elecraft KPA-500 amplifier and an Elecraft KAT-500 auto-tuner. I recently installed an Inverted-L antenna that is located more than 200-feet from the radio installation. Using the KAT-500 auto-tuner to match the Inverted-L with over 200-feet of LMR-400 feed-line resulted in an inability to tune the antenna on a large number of frequencies.

Operationally, the main goal is to achieve a high-power Automatic Link Establishment, using ION2G, primarily supporting operation on NTIA channels that are outside of Part 97 frequency allocations.

My past experience with the Inverted-L demonstrated that when coupled with a remote auto-tuner, located at the base of the vertical segment of the antenna, there were no frequencies that the auto-tuner could not produce a proper impedance match. My prior experience was with an LDG RT-100 ATU, a 100-watt ATU that powers the ATU through the coaxial feed-line via a Bias-T. LDG had manufactured a higher power remote ATU, the RT-600 with a 600-watt rating. Unfortunately, the RT-600 ATU is no longer available.

The search for a remote ATU kept landing on MFJ. I have not been a big fan of MFJ products, but decided to give the MFJ-994BRT a go. Like the LDG RT-600, the MFJ-994BRT is rated for 600-watts power, and this provides some adequate headroom above the KPA-500 amplifier's 500-watt output.

No matter which remote ATU I chose, there are some significant differences between the Elecraft KAT-500 ATU and the available remote ATU offerings. Among these differences are the following critical features found in the Elecraft KAT-500 / KPA-500 configuration:

Lacking the above features that are inherent with the Elecraft configuration, using a remote auto-tuner reverts to a largely manual process that requires the following steps:

  1. Place the Elecraft KPA-500 into bypass mode.
  2. Set the transceiver power output level to a level appropriate for the auto-tuning process.
  3. Key the transceiver with a carrier or tone (I usually use the TUNE button in the FLDIGI application), and remain keyed while monitoring the transceiver VSWR until the VSWR stabilizes.
  4. Un-key the transceiver.
  5. Restore the transceiver power output setting to a level appropriate for driving the Elecraft KPA-500 amplifier.
  6. Restore the operating mode (if changed to accomplish step 3 above).

Comparing this to the KPA-500 / KAT-500 configuration required a single push of the TUNE button on the KAT-500 auto-tuner to achieve proper operation after changing frequency.

The increased operating complexity with the remote auto-tuner is undesirable. If using digital communications that are frequency agile, such as Automatic Link Establishment, the increased operational complexity is unacceptable.

What is needed is an emulation of the Icom AH4 auto-tuner protocol, with the addition of blocking the key-line to the KPA-500 amplifier during a tuning sequence, to restore an automated one-touch operation.


Chapter 3 - Icom AH4 Auto-Tuner Protocol

Icom AH4 Normal Tuning

The Icom AH4 protocol is implemented with two signals, START and KEY. A normal AH4 auto-tuning sequence occurs as follows:



  1. The START signal is driven from the transmitter and signals the auto-tuner that a request to tune is being made.
  2. The auto-tuner responds to the START signal by asserting a KEY signal back to the transceiver, causing the transceiver to key up with a carrier in a low-power state that will not result in damage to the auto-tuner.
  3. The transceiver responds to the KEY signal by negating the START signal and then waits for the KEY signal to be negated by the auto-tuner when the auto-tuning sequence has completed.
  4. When the auto-tuning sequence completes (usually due to resolving the tuning problem and achieivng a stable low VSWR), the auto-tuner negates the KEY signal.
  5. The transciever responds to the negated KEY signal by un-keying the transceiver before restoring the selected operating mode.

To emulate the AH4 protocol, a microcontroller is needed to model the state transitions that occur with the AH4 protocol signals, and an ability to determine when the VSWR has stabilized so that the KEY request to the transceiver can be terminated. An Arduino Pro Mini is used to implement the AH4 protocol state machine, and a Fox Delta FD-HFB3-1213 Balanced Bridge is interfaced to the Arudino to provide VSWR sensing.


NOTE: This project is emulating only the normal AH4 tuning protocol. Not supported are the AH4 protocols for placing the auto-tuner into BYPASS mode, or the AH4 protocol for indicating an auto-tuning error (ie. when no tuning solution was determined). There is no method of determing an auto-tuning error from the MFJ-994BRT remote auto-tuner, other than possibly an unacceptable VSWR. The non-remote version of the MFJ-994 does support a BYPASS mode, but with the control board buttons inside the case of the MFJ-994BRT remote tuner, placing the auto-tuner into BYPASS mode is only possible by removing the DC power to the remote tuner (which is best done with the power switch on the BIAS-T device).


Icom AH4 Normal Tuning - Failed Tuning




Icom AH4 Bypass Tuning




Chapter 4 - ICOM IC-7610 AH4 TUNER INTERFACE

The Icom IC-7610 AH4 Tuner Interface has a weak pull-down termination (R7025) on the START signal. The START signal has a strong pull-up that is located in the auto-tuner. If no auto-tuner is present, the weak pull-down on the START signal will result in a low being presented to the TCON signal and the IC-7610 will then determine that no external auto-tuner is attached during power-on boot. If the START signal is read as high during the power-up boot of the IC-7610, via the TCON signal, the IC-7610 determines that an external auto-tuner is attached.

The IC-7610 provides a strong pull-up termination (R7022) of the KEY signal, an input to the IC-7610. The auto-tuner should provide a weak pull-down of the KEY signal, and should have the ability to read the state of the KEY signal. If the KEY signal is read by the auto-tuner, and a low is detected while the auto-tuner is not driving the KEY signal low, the auto-tuner should determine that the IC-7610 is powered off, and should wait for the KEY signal and the START signal to go high prior to responding to any low assertion of the START signal.

The 1KΩ series resistors (R7024 & R7027) on each of the AH-4 Signals limit the current through the clamping diodes (D7022 & D7021) that prevent the I/O signals from exceeding the signal levels specified by the I/O logic devices.

The auto-tuner/emulator should provide a strong pull-up termination of the START signal. This is necessary to overcome the weak pull-down in the IC-7610 for both signal termination and so that the IC-7610 properly detects the presence of the tuner during power-on boot.

The auto-tuner/emulator should provide a weak pull-down termination of the KEY signal. This is necessary so that the KEY SENSE signal properly indicates when the IC-7610 is not powered on, and is used to gate accepting an assertion of the START signal to only occur when the IC-7610 is powewred-on.




Chapter 5 - FOX DELTA HFB3-1213 HF BALANCED BRIDGE

The Fox Delta FD-HFB3-1213 Balanced Bridge is available in kit form. The HFB-3 provides two adjustable outputs that represent a forward voltage and a reflected voltage. These outputs are adjustable and can be scaled to remain within the 0 to full-scale range of an analog to digital converter (ADC).

The following schematic depicts the Fox Delta HFB3 circuit. Note that this schematic corrects two errors on the schematic provided by Fox Delta, where the Forward and Reflected voltages were depicted as being routed off the top of the trim resistors. The corrected circuit has the Forward and Reflected voltages taken from the variable tap on the trim resistors. This error only appears on the schematic. The printed circuit board is implemented correctly.


Chapter 6 - FOX DELTA HFB3-1213 HF BALANCED BRIDGE CALIBRATION

Calibration of the Fox Delta HFB3-1213 HF Balanced Bridge should be performed before connecting the HFB3 to the Arduino Pro Mini. Note that the HFB3 is limited to transmitters operating at 100-watts or less.


The following steps can be used to calibrate the HFB3 to produce Forward output voltage that is compatible with the 5-volt Arduino Pro Mini:

  1. Connect transmit antenna port to RF-Input port on the HFB3.
  2. Connect a Dummy Load to the RF-Output port on the HFB3.
  3. Adjust the transmitter for 100-Watts output.
  4. Place the transmitter in CW mode.
  5. Key the transmitter.
  6. Adjust P1 so that the FWD signal on pin 3 of the D-SUB 9-pin connector is at 5.0000 volts.
  7. Un-key the transmitter.

The following steps can be used to calibrate the HFB3 to produce Reflected output voltage that is compatible with the 5-volt Arduino Pro Mini:

  1. Connect transmit antenna port to RF-Output port on the HFB3.
  2. Connect a Dummy Load to the RF-Input port on the HFB3.
  3. Adjust the transmitter for 100-Watts output.
  4. Place the transmitter in CW mode.
  5. Key the transmitter.
  6. Adjust P2 so that the REF signal on pin 4 of the D-SUB 9-pin connector is at 5.0000 volts.
  7. Un-key the transmitter.

Although not used in this project, the following steps can be used to calibrate the Frequency Sense output voltage:

  1. Connect transmit antenna port to RF-Input port on the HFB3.
  2. Connect a Dummy Load to the RF-Output port on the HFB3.
  3. Adjust the transmitter for the minimum output power level that the transmitter may be operated at.
  4. Place the transmitter in CW mode.
  5. Adjust P3 to its minimum value.
  6. Key the transmitter.
  7. Adjust P3 so that the Frequency Sense signal on pin 9 of the D-SUB 9-pin connector produces a square wave as observed on an oscillocope.
  8. Un-key the transmitter.
Chapter 7 - ARDUINO AH4 PROTOCOL EMULATOR

The AH4 Protocol Emulator includes the following features:

The Mode switch is used in a configuration that has another auto-tuner, such as an Elecraft KAT500, providing RF routing through antenna switches. In such a configuration, one antenna port/switch will route RF to the MFJ-994BRT Remote Tuner and the remaining ports/switches will route RF to other antennas. When the antenna port assigned to the MFJ-BRT994 Remote Tuner is selected, the KAT500 must be placed into BYPASS mode and the AH4 ATU Protocol Emulator MODE switch must be placed into MODE A / EMULATION. When another antenna port is selected, that does not route RF to the MFJ-994BRT, the AH4 ATU Protocol Emulator MODE switch must be placed into MODE B.



When in MODE B, the AH4 ATU Protocol Emulator will enable the amplifier keying and act as a repeater for the AH4 protocol (ie. AH4 START from the transceiver is forwarded to the KAT500, and AH4 KEY from the KAT500 is forwarded to the transceiver). The AH4 ATU Protocol Emulator TUNE button is disabled in MODE B.




Chapter 8 - ARDUINO AH4 PROTOCOL EMULATOR CONSTRUCTION







Chapter 9 - SOFTWARE OVERVIEW

The source code is written in the C programming language and can be compiled with the Arduino IDE. Source code tab-stops are based on a 4-character per tab-stop setting.

The source code implements a state machine that provides the AH4 protocol emulation. State machine execution is as follows:

  1. WAIT RADIO POWERUP

    This is the initial state. Should the KEY SENSE signal be sensed low when the KEY signal is not being driven by the AH4 Emulator, execution will return to this state under the assumption that the transceiver has been powered down.

    When the KEY SENSE signal indicates that the transceiver has powered up, the state machine will advance to the IDLE state.

  2. IDLE

    The IDLE state detects an assertion of the START signal to start the tuning process. If START is detected, this state will block the keying of the KPA-500 amplifier. A timer is then primed to produce the delay between START assertion and KEY assertion before advancing to the POST START DELAY state.

    Alternatively, a manual tuning sequence can be initiated by depressing the TUNE button. Like a START initiated tuning sequence, , this state will block the keying of the KPA-500 amplifier. A timer is then primed to produce the delay between START assertion and KEY assertion before advancing to the POST START DELAY state.

  3. POST START DELAY

    This state runs the delay timer to terminal count before advancing to the ASSERT KEY state.

  4. ASSERT KEY

    If the START signal remains asserted, or manual tuning was started via pressing the TUNE button, this state will assert the KEY signal. The timer is then primed to support a delay to allow the transceiver transmitter to key before checking for a tuning solution in the next state. The state is then advanced to the Wait For Transmit RF state.

    If the START signal is not asserted and the tuning was not started manually, the state advances to the Wait For Tune Button Release state.

  5. WAIT FOR TRANSMIT RF

    This state runs the timer down to terminal count while sampling RF to determine if the transmitter has keyed. If the transmitter RF is detected before the timer reaches terminal count, the state is advanced to the Wait For Stable VSWR state.

    If no transmitter RF is detected and the timer reaches terminal count, the state advances to the Negate Key state.

Supporting functions include:


Chapter 10 - SOURCE CODE

/*
	BSD-3 Clause License
	
    Copyright © 2022 Raymond B Montagne All rights reserved.
    
    Redistribution and use in source and binary forms, with or without modification, 
    are permitted provided that the following conditions are met:

	1.	Redistributions of source code must retain the above copyright notice, this 
		list of conditions and the following disclaimer.

	2.	Redistributions in binary form must reproduce the above copyright notice, 
		this list of conditions and the following disclaimer in the documentation 
		and/or other materials provided with the distribution.

	3.	Neither the name of the copyright holder nor the names of its contributors 
		may be used to endorse or promote products derived from this software without 
		specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
	IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
	POSSIBILITY OF SUCH DAMAGE.

    ____________________________________________________________________________________

    ICOM AH4 ATU PROTOCOL EMULATOR FOR MFJ-994BRT AUTO-TUNER
    
    This source code supports an Arduino Pro Mini interfaced to an Icom AH-4 Auto-Tuner 
    interface and a FoxDelta HFB3 VSWR bridge, and emulates the AH-4 auto-tuner 
    protocol to provide feed back to the transceiver regarding a request to KEY the 
    transmitter with a low power carrier and terminating that request when the VSWR 
    has stabilized.  It is assumed that a stabilized VSWR is the result of obtaining 
    a proper tuning solution, and that the auto-tuner has ceased the tuning process.
    
    It is possible that a stable VSWR is the result of not obtaining a match solution 
    and that no additional L/C combinations are available to test.
    
    During the auto-tuning sequence, the KEY line to a power amplifier is blocked 
    so that amplification is disabled during tuning, resulting in a power level that 
    is within the limits of the auto-tuner when performing the auto-tuning sequence.
    
    This project is being used with an MFJ-994BRT auto-tuner and Elecraft KPA-500 
    amplifier.
    
    Last edit:
    
    20 OCT 2022		Initial edit.
    
     7 NOV 2022		Added revision 2 support.
     
	23 NOV 2022		Added support for KEY_SENSE to detect whether the transceiver 
					has been powered-on.  The START IN signal is ignored if the 
					KEY SENSE indicates that the transceiver is not powered-on.  
					This is dependent on changing the strong pull-up resistor that 
					was originally installed on KEY IN to a weak pull-down resistor.
					
	25 NOV 2022		Fixed repeat mode.
*/
#define kBUILD_FOR_SERIAL_DEBUG				0				//	Set to 1 to serial debug

//  --------------------------------------------------------------------------------
//	PIN ASSIGNMENTS

const unsigned int	kPIN__AMP_ENABLE_H			=	2;
const unsigned int	kPIN__AH4_START_IN_H		=	3;
const unsigned int	kPIN__AH4_KEY_OUT_H			=	4;
const unsigned int	kPIN__TUNE_BUTTON_L			=	5;
const unsigned int	kPIN__MODE					=	6;
const unsigned int	kPIN__AH4_START_OUT_H		=	7;
const unsigned int	kPIN__AH4_KEY_IN_H			=	8;
const unsigned int	kPIN__AH4_KEY_SENSE_H		=	9;
const unsigned int	kPIN__VSWR_REVERSE			=	A0;
const unsigned int	kPIN__VSWR_FORWARD			=	A1;

//  --------------------------------------------------------------------------------
//	PIN LEVELS

const unsigned int	kAMP_ENABLE_ASSERTED		=	HIGH;
const unsigned int	kAMP_ENABLE_NEGATED			=	LOW;

const unsigned int	kAH4_START_IN_ASSERTED		=	HIGH;
const unsigned int	kAH4_START_IN_NEGATED		=	LOW;

const unsigned int	kKEY_OUT_ASSERTED			=	HIGH;
const unsigned int	kKEY_OUT_NEGATED			=	LOW;

const unsigned int	kTUNE_BUTTON_ASSERTED		=	LOW;
const unsigned int	kTUNE_BUTTON_NEGATED		=	HIGH;

const unsigned int	kMODE_A_SELECTED			=	HIGH;
const unsigned int	kMODE_B_SELECTED			=	LOW;

const unsigned int	kAH4_START_OUT_ASSERTED		=	HIGH;
const unsigned int	kAH4_START_OUT_NEGATED		=	LOW;

const unsigned int	kKEY_IN_ASSERTED			=	HIGH;
const unsigned int	kKEY_IN_NEGATED				=	LOW;

const unsigned int	kKEY_SENSE_ASSERTED			=	HIGH;
const unsigned int	kKEY_SENSE_NEGATED			=	LOW;

#define	kMODE_EMULATION							true
#define kMODE_REPEAT							false

//  --------------------------------------------------------------------------------
//	PIN INITIALIZATION

typedef struct {
    uint8_t		pin_address;
    uint8_t		pin_data_direction;
    uint8_t		pin_initial_state;
} PIN_INITIALIZATION_STRUCT;

const PIN_INITIALIZATION_STRUCT kPIN_INITIALIZATION_TABLE[] = {
	{	kPIN__AMP_ENABLE_H,		OUTPUT,		kAMP_ENABLE_ASSERTED	},
	{	kPIN__AH4_START_IN_H,	INPUT,		kAH4_START_IN_NEGATED	},
	{	kPIN__AH4_KEY_OUT_H,	OUTPUT,		kKEY_OUT_NEGATED		},
	{	kPIN__TUNE_BUTTON_L,	INPUT,		kTUNE_BUTTON_NEGATED	},
	{	kPIN__MODE,				INPUT,		kMODE_A_SELECTED		},
	{	kPIN__AH4_START_OUT_H,	OUTPUT,		kAH4_START_OUT_NEGATED	},
	{	kPIN__AH4_KEY_IN_H,		INPUT,		kKEY_IN_NEGATED			},
	{	kPIN__AH4_KEY_SENSE_H,	INPUT,		kKEY_SENSE_NEGATED		} };
	
const int kPIN_LOOP_COUNT = sizeof ( kPIN_INITIALIZATION_TABLE ) / sizeof ( PIN_INITIALIZATION_STRUCT );

//  --------------------------------------------------------------------------------
//	TIMER INITIALIZATION VALUES (IN MILLISECONDS)

const unsigned int	kAH4_START_250mSEC_DELAY				=	  250;
const unsigned int	kAH4_START_NEGATED_320mSEC_DELAY		=	  320;
const unsigned int	kAH4_MAX_TUNE_TIME						=	15000;
const unsigned int	kDEFAULT_SAMPLE_DELAY					=	   50;
const unsigned int	kRADIO_POWER_UP_DELAY					=	  100;

//  --------------------------------------------------------------------------------
//	VSWR BUFFER

const unsigned int	kVSWR_BUFFER_SIZE_BIT_WIDTH				=	3;
const unsigned int	kVSWR_BUFFER_SIZE						=	1 << kVSWR_BUFFER_SIZE_BIT_WIDTH;
const unsigned int	kVSWR_BUFFER_INDEX_MASK					=	( 1 << kVSWR_BUFFER_SIZE_BIT_WIDTH ) - 1;

//  --------------------------------------------------------------------------------
//	ADC & VSWR MEASUREMENTS

#define	kVSWR_SENSOR_FULL_SCALE_VOLTAGE			      5.0
#define kADC_RESOLUTION_BITS					     10
#define	kVSWR_ADC_RESOLUTION_BITS				   1023.0
#define kVSWR_ADC_VOLTS_PER_COUNT				( kVSWR_SENSOR_FULL_SCALE_VOLTAGE / kVSWR_ADC_RESOLUTION_BITS )
#define	kZERO_REFERENCE_OFFSET					( 10.0 * kVSWR_ADC_VOLTS_PER_COUNT )
#define kVSWR_STABILITY_TOLERANCE				     90.000
#define	kATU_MAX_VSWR_WHEN_TUNED				      2.000
#define	kINFINITE_VSWR							9999999.999
#define	kRF_SENSE_SAFETY_OFFSET					      0.100
#define	kRF_MAX_PERMISSIBLE_VSWR_RANGE			      0.250

//  --------------------------------------------------------------------------------
//	STATE MACHINE

enum {
	kSTATE__WAIT_RADIO_POWERUP = 0,
	kSTATE__IDLE,
	kSTATE__AH4_POST_START_DELAY,
	kSTATE__AH4_ASSERT_KEY,
	kSTATE__AH4_WAIT_XMIT_RF,
	kSTATE__AH4_WAIT_STABLE_VSWR,
	kSTATE__AH4_NEGATE_KEY,
	kSTATE__NEGATE_AMP_INHIBIT,
	kSTATE__WAIT_TUNE_BUTTON_RELEASE,
	kSTATE__NUM_STATES
} TUNING_STATES;

//  --------------------------------------------------------------------------------
//	GLOBALS

typedef struct {
	float				noXmitFwdRefLevel;
	float				noXmitRefRefLevel;
	float				vswrBuffer[kVSWR_BUFFER_SIZE];
	unsigned long int	masterTime;
	unsigned int		delayTimer;
	unsigned int		keyAssertTimer;
	boolean				previousTuneButtonState;
	boolean				vswrIsStable;
	boolean				previousMode;
	uint8_t				state;
	uint8_t				writePtr;
	uint8_t				readPtr;
	uint8_t				sampleDelayTimer;
#if kBUILD_FOR_SERIAL_DEBUG
	unsigned long int	tuningTimer;
	unsigned int		ah4StartInState		: 1;
	unsigned int		ah4KeyOutState		: 1;
	unsigned int		ah4StartOutState	: 1;
	unsigned int		ampEnableState		: 1;
	unsigned int		keyInState			: 1;
	unsigned int		keySenseState		: 1;
#endif
} GLOBALS;

GLOBALS	globals;

/*  --------------------------------------------------------------------------------
	       Vfwd + Vref
	VSWR = ------------
	       Vfwd - Vref
	       
	Result is rounded down to nearest tenth.  A negative result is converted to a 
	positive result of 9999999.0.  
*/

float	getVswrData ( void )
{
	float		vFwd = analogReadPinAndScale ( kPIN__VSWR_FORWARD );
	float		vRef = analogReadPinAndScale ( kPIN__VSWR_REVERSE );
	float		result = ( vFwd + vRef ) / ( vFwd - vRef );
	int			valX100 = result * 100;
	int			valX10 = result * 10;
	
	if ( 5 < valX100 % 10 ) { valX10 += 1; }
	result = (float)valX10 / 10.0;
	
	if ( 0.0 > result ) { result = kINFINITE_VSWR; }
	
	return result;
}

//  --------------------------------------------------------------------------------

float	analogReadPinAndScale ( int pin )
{
	return kVSWR_ADC_VOLTS_PER_COUNT * (float)analogRead ( pin );
}

//  --------------------------------------------------------------------------------

void pushVswrData ( float vswrData )
{
	globals.vswrBuffer[globals.writePtr++] = vswrData;
	
	if ( kVSWR_BUFFER_SIZE <= globals.writePtr )
	{
		for ( int index = 0; index < ( kVSWR_BUFFER_SIZE -1 ); index++ )
		{
			globals.vswrBuffer[index] = globals.vswrBuffer[index + 1];
		}
		globals.writePtr--;
	}
}

//  --------------------------------------------------------------------------------

uint8_t getNumberOfVswrMeasurements ( void )
{
	return globals.writePtr;
}

//  --------------------------------------------------------------------------------

boolean	checkIfVswrIsStable ( void )
{
	boolean			result = false;
	float			minVswr = kINFINITE_VSWR;
	float			maxVswr = 0.0;
	float			range = 0.0;
	float			minVswrPercentage = 0.0;
	float			average = 0.0;
	float			midPoint = 0.0;
	uint8_t			count = getNumberOfVswrMeasurements ();
	int				walkingBits = 0;
	
	if ( ( kVSWR_BUFFER_SIZE -1 ) == globals.writePtr )
	{
		for ( int index = 0; index < globals.writePtr; index++ )
		{
			if ( minVswr > globals.vswrBuffer[index] )
			{
				minVswr = globals.vswrBuffer[index];
			}
		
			if ( maxVswr < globals.vswrBuffer[index] )
			{
				maxVswr = globals.vswrBuffer[index];
			}
			
			average += globals.vswrBuffer[index];
		}
		
		average /= (float)( kVSWR_BUFFER_SIZE -1 );
		range = maxVswr - minVswr;
		midPoint = ( maxVswr + minVswr ) / 2.0;
		minVswrPercentage = ( ( minVswr / maxVswr ) * 100.0 );
		
		if ( kATU_MAX_VSWR_WHEN_TUNED >= maxVswr )
		{
			walkingBits |= ( 1 << 0 );
			if ( ( minVswr == maxVswr ) || ( ( minVswr < maxVswr ) && average <= midPoint ) )
			{
				walkingBits |= ( 1 << 1 );
				if ( kRF_MAX_PERMISSIBLE_VSWR_RANGE >= range )
				{
					walkingBits |= ( 1 << 2 );
					if ( kVSWR_STABILITY_TOLERANCE <= minVswrPercentage )
					{
						result = true;
					}
				}
			}
		}
				
#if kBUILD_FOR_SERIAL_DEBUG
		Serial.print ( "\tMIN: " );
		Serial.print ( minVswr );
		Serial.print ( "\tMAX: " );
		Serial.print ( maxVswr );
		Serial.print ( "\tMID: " );
		Serial.print ( midPoint );
		Serial.print ( "\tAVG: " );
		Serial.print ( average );
		Serial.print ( "\tRANGE: " );
		Serial.print ( range );
		Serial.print ( "\tPERCENT: " );
		Serial.print ( minVswrPercentage );
		Serial.print ( "\tSTABLE: " );
		Serial.print ( result ? "YES" : "NO" );
		Serial.print ( "\tSTATUS: " );
		Serial.print ( walkingBits, BIN );
		Serial.println ( "" );
#endif
	}

	return result;
}

//  --------------------------------------------------------------------------------

void setAh4TunerKeyOutState ( uint8_t ah4KeyOutState )
{
#if kBUILD_FOR_SERIAL_DEBUG
	if ( globals.ah4KeyOutState != ah4KeyOutState )
	{
		globals.ah4KeyOutState = ah4KeyOutState;
		Serial.print ( "KEY OUT:    " );
		Serial.println ( ah4KeyOutState ? "ASSERTED" : "NEGATED" );
	}
#endif
	digitalWrite ( kPIN__AH4_KEY_OUT_H, ah4KeyOutState );
}

//  --------------------------------------------------------------------------------

uint8_t readAh4TunerKeyOut ( void )
{
	return digitalRead ( kPIN__AH4_KEY_OUT_H );
}

//  --------------------------------------------------------------------------------

uint8_t readAh4TuneStartIn ( void )
{
	uint8_t result = digitalRead ( kPIN__AH4_START_IN_H );
#if kBUILD_FOR_SERIAL_DEBUG
	if ( result )
	{
		Serial.print ( "START IN:   " );
		Serial.println ( result ? "ASSERTED" : "NEGATED" );
	}
#endif
	return result;
}

//  --------------------------------------------------------------------------------

uint8_t readAh4TunerKeyIn ( void )
{
	uint8_t result = digitalRead ( kPIN__AH4_KEY_IN_H );
#if kBUILD_FOR_SERIAL_DEBUG
	if ( globals.keyInState != result )
	{
		globals.keyInState = result;
		Serial.print ( "KEY IN:  " );
		Serial.println ( result ? "ASSERTED" : "NEGATED" );
	}
#endif
	return result;
}

//  --------------------------------------------------------------------------------

uint8_t readAh4TunerKeySense ( void )
{
	boolean result = kKEY_SENSE_ASSERTED == digitalRead ( kPIN__AH4_KEY_SENSE_H );
#if kBUILD_FOR_SERIAL_DEBUG
	if ( globals.keySenseState != result )
	{
		globals.keySenseState = result;
		Serial.print ( "KEY SENSE:  " );
		Serial.println ( result ? "ASSERTED" : "NEGATED" );
	}
#endif
	return result;
}

//  --------------------------------------------------------------------------------

void setAmplifierEnableState ( uint8_t ampEnableState )
{
#if kBUILD_FOR_SERIAL_DEBUG
	if ( globals.ampEnableState != ampEnableState )
	{
		globals.ampEnableState = ampEnableState;
		Serial.print ( "AMP ENABLE: " );
		Serial.println ( ampEnableState ? "ENABLE" : "DISABLE" );
	}
#endif
	digitalWrite ( kPIN__AMP_ENABLE_H, ampEnableState );
}

//  --------------------------------------------------------------------------------

uint8_t readTuneButtonI ( void )
{
	return digitalRead ( kPIN__TUNE_BUTTON_L );
}

//  --------------------------------------------------------------------------------

boolean isInModeA ( void )
{
	return kMODE_A_SELECTED == digitalRead ( kPIN__MODE );
}

//  --------------------------------------------------------------------------------

void setAh4TunerStartOutState ( uint8_t ah4StartOutState )
{
#if kBUILD_FOR_SERIAL_DEBUG
	if ( globals.ah4StartOutState != ah4StartOutState )
	{
		globals.ah4StartOutState = ah4StartOutState;
		Serial.print ( "START OUT:  " );
		Serial.println ( ah4StartOutState ? "ASSERTED" : "NEGATED" );
	}
#endif
	digitalWrite ( kPIN__AH4_START_OUT_H, ah4StartOutState );
}
//  --------------------------------------------------------------------------------

boolean xmitRfDetected ( void )
{
	boolean		result = false;
	float		vFwd = analogReadPinAndScale ( kPIN__VSWR_FORWARD );
	float		vRef = analogReadPinAndScale ( kPIN__VSWR_REVERSE );
	
	if ( ( globals.noXmitFwdRefLevel + kRF_SENSE_SAFETY_OFFSET ) < vFwd ||
		 ( globals.noXmitRefRefLevel + kRF_SENSE_SAFETY_OFFSET ) < vRef )
	{
		result = true;
	}
	
#if kBUILD_FOR_SERIAL_DEBUG
	Serial.print ( "xmitRfDetected: " );
	Serial.println ( result ? "YES" : "NO" );
#endif
	return result;
}

//  --------------------------------------------------------------------------------

void stateMachine ( void )
{
	uint8_t		entryState = globals.state;
	
	switch ( globals.state )
	{
		case kSTATE__WAIT_RADIO_POWERUP:
		{
			if ( kKEY_SENSE_NEGATED == readAh4TunerKeySense () && kKEY_OUT_NEGATED == readAh4TunerKeyOut () )
			{
				if ( 0 != globals.delayTimer )
				{
					globals.delayTimer--;
				}
				
				if ( 0 == globals.delayTimer )
				{
					globals.state = kSTATE__IDLE;
				}
			}
			else
			{
				//	If the radio powers up and then powers down before the 
				//	stabilization delay has completed, reset the stabilization 
				//	timer so that the next power up is handled correctly.
				
				globals.delayTimer = kRADIO_POWER_UP_DELAY;
			}
		}
		break;
		
		case kSTATE__IDLE:
		{
			globals.writePtr = 0;
			globals.readPtr= 0;
#if kBUILD_FOR_SERIAL_DEBUG
			if ( 0 != globals.tuningTimer )
			{
				Serial.print ( "TUNING TIME: " );
				Serial.print ( globals.tuningTimer );
				Serial.println ( " mSec" );
				
				globals.tuningTimer = 0;
				
				Serial.println ( "TUNING TIME HAS BEEN RESET" );
			}
#endif
			
			globals.previousTuneButtonState = false;
			if ( kKEY_SENSE_ASSERTED == readAh4TunerKeySense () )
			{
				globals.state = kSTATE__WAIT_RADIO_POWERUP;
				globals.delayTimer = kRADIO_POWER_UP_DELAY;
			}
			else if ( kTUNE_BUTTON_ASSERTED == readTuneButtonI () && !globals.previousTuneButtonState )
			{
				globals.previousTuneButtonState = true;
				setAmplifierEnableState ( kAMP_ENABLE_NEGATED );
				globals.delayTimer = kAH4_START_250mSEC_DELAY;
				globals.state = kSTATE__AH4_POST_START_DELAY;
			}
			else if ( kAH4_START_IN_ASSERTED == readAh4TuneStartIn () )
			{
				setAmplifierEnableState ( kAMP_ENABLE_NEGATED );
				globals.delayTimer = kAH4_START_250mSEC_DELAY;
				globals.state = kSTATE__AH4_POST_START_DELAY;
			}
		}
		break;
		
		case kSTATE__AH4_POST_START_DELAY:
		{
#if kBUILD_FOR_SERIAL_DEBUG
			globals.tuningTimer++;
#endif
			if ( kKEY_SENSE_ASSERTED == readAh4TunerKeySense () )
			{
				globals.state = kSTATE__WAIT_RADIO_POWERUP;
				globals.delayTimer = kRADIO_POWER_UP_DELAY;
			}
			else
			{
				if ( 0 != globals.delayTimer )
				{
					globals.delayTimer--;
					if ( 0 == globals.delayTimer )
					{
						globals.state = kSTATE__AH4_ASSERT_KEY;
						globals.keyAssertTimer = kAH4_MAX_TUNE_TIME;
					}
				}
			}
		}
		break;
		
		case kSTATE__AH4_ASSERT_KEY:
		{
#if kBUILD_FOR_SERIAL_DEBUG
			globals.tuningTimer++;
#endif
			if ( kKEY_SENSE_ASSERTED == readAh4TunerKeySense () )
			{
				globals.state = kSTATE__WAIT_RADIO_POWERUP;
				globals.delayTimer = kRADIO_POWER_UP_DELAY;
			}
			else
			{
				if ( kAH4_START_IN_ASSERTED == readAh4TuneStartIn () || globals.previousTuneButtonState )
				{
					setAh4TunerKeyOutState ( kKEY_OUT_ASSERTED );
					globals.delayTimer = kAH4_START_NEGATED_320mSEC_DELAY;
					globals.state = kSTATE__AH4_WAIT_XMIT_RF;
				}
				else
				{
					setAmplifierEnableState ( kAMP_ENABLE_ASSERTED );
					globals.state = kSTATE__WAIT_TUNE_BUTTON_RELEASE;
				}
			}
		}
		break;
		
		case kSTATE__AH4_WAIT_XMIT_RF:
		{
#if kBUILD_FOR_SERIAL_DEBUG
			globals.tuningTimer++;
#endif
			if ( 0 != globals.keyAssertTimer )
			{
				globals.keyAssertTimer--;
			}
			
			if ( 0 == globals.keyAssertTimer )
			{
				globals.state = kSTATE__AH4_NEGATE_KEY;
			}
			else
			{
				if ( xmitRfDetected () )
				{
					globals.sampleDelayTimer = kDEFAULT_SAMPLE_DELAY;
					globals.state = kSTATE__AH4_WAIT_STABLE_VSWR;
				}
			}
		}
		break;
		
		case kSTATE__AH4_WAIT_STABLE_VSWR:
		{
#if kBUILD_FOR_SERIAL_DEBUG
			globals.tuningTimer++;
#endif
			globals.vswrIsStable = false;
			if ( 0 != globals.sampleDelayTimer )
			{
				globals.sampleDelayTimer--;
				if ( 0 == globals.sampleDelayTimer )
				{
					pushVswrData ( getVswrData () );
					globals.vswrIsStable = checkIfVswrIsStable ();
					globals.sampleDelayTimer = kDEFAULT_SAMPLE_DELAY;
				}
			}
			
			if ( globals.vswrIsStable )
			{
				globals.state = kSTATE__AH4_NEGATE_KEY;
			}
			else
			{
				if ( 0 != globals.keyAssertTimer )
				{
					globals.keyAssertTimer--;
				}
				
				if ( 0 == globals.keyAssertTimer )
				{
					globals.state = kSTATE__AH4_NEGATE_KEY;
				}
			}
		}
		break;
		
		case kSTATE__AH4_NEGATE_KEY:
		{
#if kBUILD_FOR_SERIAL_DEBUG
			globals.tuningTimer++;
#endif
			setAh4TunerKeyOutState ( kKEY_OUT_NEGATED );
			if ( globals.vswrIsStable )
			{
				globals.state = kSTATE__NEGATE_AMP_INHIBIT;
			}
			else
			{
				globals.state = kSTATE__WAIT_TUNE_BUTTON_RELEASE;
			}
		}
		break;
		
		case kSTATE__NEGATE_AMP_INHIBIT:
		{
#if kBUILD_FOR_SERIAL_DEBUG
			globals.tuningTimer++;
#endif
			setAmplifierEnableState ( kAMP_ENABLE_ASSERTED );
			globals.state = kSTATE__WAIT_TUNE_BUTTON_RELEASE;
		}
		break;
		
		case kSTATE__WAIT_TUNE_BUTTON_RELEASE:
		{
			if ( kTUNE_BUTTON_NEGATED == readTuneButtonI () )
			{
				if ( kKEY_SENSE_ASSERTED == readAh4TunerKeySense () )
				{
					globals.state = kSTATE__WAIT_RADIO_POWERUP;
				}
				else
				{
					globals.state = kSTATE__IDLE;
				}
				globals.delayTimer = kRADIO_POWER_UP_DELAY;
			}
		}
		break;
	}
	
#if kBUILD_FOR_SERIAL_DEBUG
	if ( entryState != globals.state )
	{
		Serial.print ( "± stateMachine entry: " );
		displayStatePosition ( entryState );
		Serial.print ( " , next: " );
		displayStatePosition ( globals.state );
		Serial.println ( "" );
	}
#endif
}

//  --------------------------------------------------------------------------------

#if kBUILD_FOR_SERIAL_DEBUG
void displayStatePosition ( int statePosition )
{
	switch ( statePosition )
	{
		case kSTATE__WAIT_RADIO_POWERUP:		Serial.print ( "WAIT_RADIO_POWERUP" );			break;
		case kSTATE__IDLE:						Serial.print ( "IDLE" );						break;
		case kSTATE__AH4_POST_START_DELAY:		Serial.print ( "AH4_POST_START_DELAY" );		break;
		case kSTATE__AH4_ASSERT_KEY:			Serial.print ( "AH4_ASSERT_KEY" );				break;
		case kSTATE__AH4_WAIT_XMIT_RF:			Serial.print ( "AH4_WAIT_XMIT_RF" );			break;
		case kSTATE__AH4_WAIT_STABLE_VSWR:		Serial.print ( "AH4_WAIT_STABLE_VSWR" );		break;
		case kSTATE__AH4_NEGATE_KEY:			Serial.print ( "AH4_NEGATE_KEY" );				break;
		case kSTATE__NEGATE_AMP_INHIBIT:		Serial.print ( "NEGATE_AMP_INHIBIT" );			break;
		case kSTATE__WAIT_TUNE_BUTTON_RELEASE:	Serial.print ( "WAIT_TUNE_BUTTON_RELEASE" );	break;
	}
}
#endif 

//  --------------------------------------------------------------------------------
//	Enforce a maximum tuning time when repeating

void	repeatAh4Protocol ( void )
{
	setAmplifierEnableState ( kAMP_ENABLE_ASSERTED );
	setAh4TunerStartOutState ( readAh4TuneStartIn () );
	setAh4TunerKeyOutState ( readAh4TunerKeyIn () );
}

//  --------------------------------------------------------------------------------

void setup ()
{
#if kBUILD_FOR_SERIAL_DEBUG
    Serial.begin ( 115200 );
    while ( !Serial ) {}
    Serial.println ( "Serial: 115200, 8N1" );
#endif 

	for ( int index = 0; index < kPIN_LOOP_COUNT; index++ )
	{
		pinMode ( kPIN_INITIALIZATION_TABLE[index].pin_address, 
				  kPIN_INITIALIZATION_TABLE[index].pin_data_direction );
				  
		if ( OUTPUT == kPIN_INITIALIZATION_TABLE[index].pin_data_direction )
		{
			digitalWrite ( kPIN_INITIALIZATION_TABLE[index].pin_address, 
						   kPIN_INITIALIZATION_TABLE[index].pin_initial_state );
		}
	}
	
	globals.previousMode = kMODE_EMULATION;
	globals.state = kSTATE__WAIT_RADIO_POWERUP;
	globals.delayTimer = kRADIO_POWER_UP_DELAY;
	globals.noXmitFwdRefLevel = analogReadPinAndScale ( kPIN__VSWR_FORWARD ) + kZERO_REFERENCE_OFFSET;
	globals.noXmitRefRefLevel = analogReadPinAndScale ( kPIN__VSWR_REVERSE ) + kZERO_REFERENCE_OFFSET;
	globals.previousTuneButtonState = readTuneButtonI ();
#if kBUILD_FOR_SERIAL_DEBUG
	globals.ah4KeyOutState = kKEY_OUT_NEGATED;
	globals.ah4StartOutState = kAH4_START_OUT_NEGATED;
	globals.ampEnableState = kAMP_ENABLE_ASSERTED;
	readAh4TuneStartIn ();
	readAh4TunerKeyIn ();
	readAh4TunerKeySense ();
	
	Serial.println ( "" );
	Serial.println ( "AH-4 EMULATOR INITIALIZED" );
	Serial.print ( "INITIAL globals.noXmitFwdRefLevel: " );
	Serial.println ( globals.noXmitFwdRefLevel );
	Serial.print ( "INITIAL globals.noXmitRefRefLevel: " );
	Serial.println ( globals.noXmitRefRefLevel );
	Serial.print ( "CURRENT MODE: " );
	Serial.println ( globals.previousMode ? "EMULATION" : "REPEATER" );
	Serial.print ( "INITIAL TUNE BUTTON STATE: " );
	Serial.println ( kTUNE_BUTTON_ASSERTED == globals.previousTuneButtonState ? "PRESSED" : "RELEASED" );
	Serial.print ( "STATE: " );
	displayStatePosition ( globals.state );
	Serial.println ( "" );
#endif 
}

//  --------------------------------------------------------------------------------

void loop ()
{
    unsigned long int	currentTime = millis ();
    boolean				requestedMode = isInModeA ();

    if ( globals.masterTime != currentTime )
    {
		globals.masterTime = currentTime;
		if ( globals.previousMode != requestedMode )
		{
			if ( kMODE_EMULATION == globals.previousMode )
			{
				//	When in EMULATION, a transition to REPEAT must wait 
				//	until the state machine has gone idle.
#if kBUILD_FOR_SERIAL_DEBUG
				Serial.println ( "REQUEST SWITCH TO REPEAT MODE" );
#endif 
				
				stateMachine ();
				if ( kSTATE__IDLE == globals.state )
				{
					globals.previousMode = requestedMode;
#if kBUILD_FOR_SERIAL_DEBUG
					Serial.println ( "COMPLETED SWITCH TO REPEAT MODE" );
#endif 
				}
			}
			else //	kMODE_REPEAT == globals.previoiusMode
			{
				//	When in REPEAT, a transition to MULATION must wait 
				//	until the AH4 protocol has gone idle.
#if kBUILD_FOR_SERIAL_DEBUG
				Serial.println ( "REQUEST SWITCH TO EMULATION MODE" );
#endif 
				
				repeatAh4Protocol ();
				if ( kAH4_START_IN_NEGATED == readAh4TuneStartIn () && kKEY_IN_NEGATED == readAh4TunerKeyIn () )
				{
					globals.previousMode = requestedMode;
#if kBUILD_FOR_SERIAL_DEBUG
					Serial.println ( "COMPLETED SWITCH TO EMULATION MODE" );
#endif 
				}
			}
		}
		else
		{
			if ( kMODE_EMULATION == globals.previousMode )
			{
				stateMachine ();
			}
			else
			{
				if ( kSTATE__IDLE == globals.state )
				{
					if ( kKEY_OUT_NEGATED == readAh4TunerKeyOut () && kKEY_SENSE_ASSERTED == readAh4TunerKeySense () )
					{
						globals.state = kSTATE__WAIT_RADIO_POWERUP;
						globals.delayTimer = kRADIO_POWER_UP_DELAY;
					}
					else
					{
						repeatAh4Protocol ();
					}
				}
				else
				{
					stateMachine ();					
				}
			}
		}
	}
}
				

Click here to download source code.


Chapter 11 - STATION CONFIGURATION

The following block diagram shows haw the station is configured where only AH4 Emulation is required (ie. no repeat operation). Note that the Fox Delta HFB3 HF Balanced Bridge is placed between the transmitter and the amplifier, where the power level will not exceed 100-watts. This placement of the Fox Delta HFB3 is between the transceiver and the amplifier. The amplifier is bypassed (inhibited) during the tuning process by blocking the routing of the transceiver SEND singal to the amplifier PTT signal. This results in the transmission of a low power carrier, resulting from the AH4 KEY line assertion to the transceiver, during the tuning cycle and prevents damage to the auto-tuner by avoiding the auto-tune process at power levels that exceed the limits of the auto-tuner during the tuning sequence.



Under normal operation, a transmitter output level of 23-watts produces 500-watts output from the Elecraft KPA-500 amplifier. When tuning, in response to assertion of the AH4 KEY signal, the transmitter output level is approximately 10-watts.



The following block diagram shows haw the station is configured where both AH4 Emulation and AH4 repeat operation are required. Note that the Fox Delta HFB3 HF In this configuration, the station configuration would have the MFJ-994BRT on one KAT500 antenna port and that antenna port must be operated in the BYPASS mode. Note that it is not possible to force a specified antenna port to always be in BYPASS mode with the KAT500 Utility, so this must be managed by the radio operator.





Chapter 12 - MFJ-994BRT INVERTED-L INSTALLATION

MFJ-994BRT Remote Auto-Tuner installed on tower stand-off with lightning arrestor and 4:1 balun. The total lenght of the stand-off arm is 4-feet, and is mounted approximately 6-feet above the ground to keep the installation above the normal snow depth. A ground rod is installed at the base of the tower.

An identical stand-off is mounted at the 56-foot level of the 60-foot tower.



Arial view of Inverted-L antenna layout. The end of the Inverted-L that is opposite to the feed point is tied off to a tree that is 124-feet from the tower. There are no trees inside of the "L". The vertical segment of wire is 50-feet and the sloping portion is 130-feet long, for a total wire length of 180-feet.




Tower, tower-stand-offs and Inverted-L antenna.





Chapter 13 - DEVICE OPERATION

The board supports two operating modes. In the first operating mode, MODE A / EMULATION, the AH4 ATU Emulator will provide handshanking with the AH4 protocol interface with the transceiver, using the Fox Delta HFB3-1213 HF Balance Bridge for VSWR measurement in support of the MFJ-994BRT Remote Tuner. In the second operating mode, MODE B / REPEAT, the AH4 ATU Emulator will repeat the AHR protocol signals between the transceiver and a secondary tuner that is attached to the AH4 ATU Emulator to enable the secondary tuner to provide antenna selection and antenna matching for antennas that are directly attached to the secondary tuner and are not connected through the MFJ-994BRT Remote Tuner.

NOTE: Switching from MODE A / EMULATION to MODE B / REPEAT will remove any amplifier lock-out. Switching back from MODE B / REPEAT to MODE A / EMULATION will not restore the amplifier lock-out until an auto-tune sequence is started.


Chapter 14 - TESTING & EVALUATION

This section provides an evaluation of the performance of the AH4 Protocol Emulator. An evaluation of the MFJ-994BRT Remote Auto-Tuner is not provided. In all cases, a tuning solution has previously been resolved and the tuning parameters have been stored in memory within the MFJ-994BRT Remote Auto-Tuner. This means that all applications of a tuning solution with the AH4 Protocol Emulator will draw tuning coefficients from memory, resulting in a very rapid tuning solution.


Chapter 15 - CONCLUSIONS

The goals of simplifying the auto-tuning and amplifier sequencing have been achieved when operating with the antenna selection routing RF to the MFJ-994BRT / Inverted-L antenna. For this configuration, operation is as simple as setting up the radio to auto-tune on key-down. After moving frequency, key the transceiver and wait for the auto-tune cycle to complete. After the auto-tune cycle has completed, normal operation is available.

The goals of simplifying the auto-tuning and amplifier sequencing where reliance on the KAT-500 auto-tuner antenna selection to route RF to other antenna ports on the KAT-500 have not been achieved. The inability of the KAT-500 to remember and apply the BYPASS mode, based on antenna selection, is the largest hurdle to be overcome. The only viable configuration where reliance on the KAT-500 auto-tuner antenna selection is necessary is where the other antenna ports (ie. ports other than the port supporting the MFJ-994BRT / Inverted-L) are able to operate in bypass mode with no KAT-500 tuning being required.

Although this project achieves all of the goals where operation is confined to the MFJ-994BRT / Inverted-L antenna, this project is not successful in achieving full frequency agility, at a high power level, across a multiple antenna configuration.

The configuration where this project succeeds is as follows:

missing successful_configuration.png
missing successful_configuration.png

The above configuration may simply omit the Emulate / Repeat switch.

This project is considered to be incomplete. A future modification will attempt to address the current issues by interfacing a serial port between the AH4 Emulator and the KAT500 to apply command control to (1) place the KAT500 in bypass when entering emulation mode, and (2) place the KAT500 in manual tuning mode when entering repeat mode. A breif low power transmission will be needed immediately after the transission of the mode switch and the sending of the command to allow the KAT500 to apply the frequency dependent antenna selection, followed by a full tuning cycle. Stay tuned...

73, Ray Montagne (W7CIA)