ELAD AMS33 hacked for Remote Control

The ELAD AMS-33 is a 3x3 matrix antenna switch. The button on the front panel let you choose one of the 7 possible combinations. The actual combinations are displayed via a LED matrix.

After opening the box, the interior is well made. Near the processor is a 10 pole connector marked J11. My first assumption, it is a ISP programming port was wrong. It killed my ISP-programmer output. Further test showed that it is a JTAG port. Luckily, I was able to use my old DRAGON board with the actual version of ATMEL Studio after a short automatic firmware update. The reading and programming of the original software worked reliably. Thanks to ELAD not protecting the chip against reprogramming. Of course, the chip can be replaced with an new, unprotected one.

I used BASCOM for the new software. The first difficulty was finding the exact port connections of the relays, the LEDs, and the button. I desoldered all the relais to have a clear view on the PCB wiring. The original software has a special behavior. After switching, it turns of the controllers clock to avoid injecting noise into the receiver. A press on the button wake up the controller again.

For an external operation of the device I can use the UART interface available in many of ATMEL controllers. It is also available on the multipole post connector J1 including 5V power and ground.

The protocol for setting the antenna matrix is very rudimentary. Sending # followed by the desired switching position number and a final CR sets the desired IN/OUT configuration. The controller is now also awakened when data is received at the serial interface. Unfortunately, the first characters are lost. An unused sent character from the protocol (like space CHR(h20)) is sufficient to wake up the controller. After 200 ms, send the real control sequence.

After a voltage loss, the inputs are connected to the same outputs. (1=>1 / 2=>2 / 3=>3)

pictures

ams33-schema-pdf.jpg mod-1.jpg mod-2.jpg mod-3.jpg mod-4.jpg mod-5.jpg mod-6.jpg mod-7.jpg mod-8.jpg

downloads

Schema PDF
Software ZIP

update

Dezember 2017: Connecting my RigExpert 230-Zoom to the Switch showed infinite SWR on the antenna which has a SWR on the 5W transceiver of 1:1.3. The result was the relais cannot handle such small current efficiently. If you knock the relais while transmitting 5W you will see changes in SWR as well.

AMS33.bas

'*********************************************
'* HF switch box AMS-33 from ELAD
'* modified firmware for remote control
'* using RS232 terminal => USB converter
'* HB9FZG 2016
'*
'* Connection matrix
'* Pos0 = I1=x I2=x I3=x
'* Pos1 = In1=Out1 In2=Out2 In3=Out3
'* Pos2 = In1=Out1 In2=Out3 In3=Out2
'* Pos3 = In1=Out2 In2=Out1 In3=Out3
'* Pos4 = In1=Out2 In2=Out3 In3=Out1
'* Pos5 = In1=Out3 In2=Out1 In3=Out2
'* Pos6 = In1=Out3 In2=Out2 In3=Out1
'*
'*********************************************

$regfile = "m169pdef.dat"
$crystal = 8000000
$hwstack = 16
$swstack = 32
$framesize = 32
$baud = 9600

CONFIG SUBMODE = NEW

CONST true = 1
CONST false = 0
CONST LEDPWR_ein = 0
CONST LEDPWR_aus = 1
CONST BUTTON_pressed = 0
CONST BUTTON_released = 1
CONST CMDnil = 0
CONST CMDstarted = 1
CONST CMDreceived = 2
CONST SleepDelay = 5
CONST POSnil = 255

LED_O1_I1 Alias PortA.3
LED_O1_I2 Alias PORTC.6
LED_O1_I3 Alias PORTC.7

LED_O2_I1 Alias PORTE.4
LED_O2_I2 Alias PORTE.3
LED_O2_I3 Alias PORTE.2

LED_O3_I1 Alias PORTE.7
LED_O3_I2 Alias PORTE.6
LED_O3_I3 Alias PORTE.5

BUTTON Alias PIND.1
LEDPWR Alias PORTB.1

K1 Alias PORTD.5
K2 Alias PORTC.0
K3 Alias PORTD.7
K4 Alias PORTD.2
K5 Alias PORTD.6
K6 Alias PORTC.4
K7 Alias PORTC.1
K8 Alias PORTC.3
K9 Alias PORTD.3
K10 Alias PORTD.4
K11 Alias PORTC.2
K12 Alias PORTC.5

DDRA = &b00001000
DDRB = &b00000010
DDRC = &b11111111
DDRD = &b11111100
DDRE = &b11111100

DIM Event10ms As Boolean
DIM Event100ms As Boolean
DIM Event1s As Boolean
DIM EventCntr As Integer
DIM Position_Curr As Integer
DIM E_Position_Curr as Eram Integer
DIM Position_New As Integer
DIM i As Integer
DIM x As Integer
DIM d as Byte
DIM cmdValue as Byte
DIM cmdState as Byte
DIM cmdLock as Integer
DIM Button_cntr as Integer
DIM Sleep_cntr as Integer

$include system.inc
$include relaispos.inc

'Init Timer0 (10ms cycle)
CONFIG TIMER0 = TIMER , PRESCALE = 1024
START TIMER0
ON OVF0 isrTimer0_Overflow
ENABLE OVF0

Config COM1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "COM1:" For BINARY As #1
On URXC isrRX_DataReceived
Enable URXC

Config Int0 = LOW LEVEL
On Int0 isrINT0 NoSave

'Config PCINT0
Pcmsk0 = &B00000001
On PCINT0 isrPCINT0

ENABLE Interrupts
LEDPWR = LEDPWR_ein
cmdState = CMDnil
Position_Curr = POSnil
Position_New = E_Position_Curr
Sleep_cntr = SleepDelay

Do
  If Position_New <> Position_Curr Then
    ' Open all connections
    Call SetNoConnection
    Waitms 100
    Call SetConfig(Position_New)
    Position_Curr = Position_New
    Sleep_cntr = SleepDelay
  End If

  If Event10ms = true then
    Event10ms = false
    If cmdLock > 0 Then DECR cmdLock
    If Button = BUTTON_pressed Then
      INCR Button_cntr
    Else
      Select Case Button_cntr
        Case 10 to 50
          If Position_New < 6 Then
            INCR Position_New
          Else
            Position_New = 0
          End If
          Button_cntr = 0
        Case Is > 100
          ' do nothing now
            Button_cntr = 0
      End Select
    End If
  End If

  If Event100ms = true then
    Event100ms = false
  End If

  If Event1s = true then
    Event1s = false
    If Sleep_cntr > 0 Then
      DECR Sleep_cntr
    End If
  End If

  If Sleep_cntr = 0 Then
    Call goSleep
  End If
Loop

'ISRs

isrINT0:
  DISABLE INT0
  Sleep_cntr = SleepDelay
RETURN

isrPCINT0:
  Sleep_cntr = SleepDelay
RETURN

isrTimer0_Overflow:
  'set 10ms interval
  TIMER0 = 178
  Event10ms = true
  'Toggle LEDPWR
  Incr EventCntr
  Select Case EventCntr
    Case 10
      Event100ms = true
    Case 20
      Event100ms = true
    Case 30
      Event100ms = true
    Case 40
      Event100ms = true
    Case 50
      Event100ms = true
    Case 60
      Event100ms = true
    Case 70
      Event100ms = true
    Case 80
      Event100ms = true
    Case 90
      Event100ms = true
    Case 100
      EventCntr = 0
      Event1s = true
  End Select
RETURN

'COM1 data received
isrRX_DataReceived:
  d = UDR
  'Toggle LEDPWR
  Select Case d
    Case 35                                                 ' # Command Start received
      cmdState = CMDstarted

    Case 48 to 54                                           ' "0" - "6" = valid relais map positions received
      if cmdState = CMDstarted then
        cmdValue = d - 48                                   'shift the ascii gap
        cmdState = CMDreceived
      end if

    Case 13                                                 ' CR Command End received
      if cmdState = CMDreceived then
        if cmdLock = 0 then
          cmdLock = 100                                     ' set 1 second lock time
          Position_New = cmdValue
        end if
      end if
      cmdState = CMDnil

    Case 10
      'do nothing, just ignore the LF character

    Case else                                               ' invalid command payload
      cmdState = CMDnil

  End Select
RETURN

relaispos.inc

'***********************************
'* Connection matrix
'* Pos0 = I1=x I2=x I3=x
'* Pos1 = In1=Out1 In2=Out2 In3=Out3 (default = powerless Relais)
'* Pos2 = In1=Out1 In2=Out3 In3=Out2
'* Pos3 = In1=Out2 In2=Out1 In3=Out3
'* Pos4 = In1=Out2 In2=Out3 In3=Out1
'* Pos5 = In1=Out3 In2=Out1 In3=Out2
'* Pos6 = In1=Out3 In2=Out2 In3=Out1
'*
'* In1 => Out1 = K4, K1 = off
'* In1 => Out2 = K2, K4, K6
'* In1 => Out3 = K3, K4
'*
'* In2 => Out1 = K1, K5, K9
'* In2 => Out2 = K9, K11, K7, K2 = off
'* In2 => Out3 = K8, K11
'*
'* In3 => Out1 = K1, K5
'* In3 => Out2 = K7, K12
'* In3 => Out3 = K10, K12, K8, K3 = off
'*
'***********************************

Sub SetRelais(ByVal n As Integer , ByVal p As Integer)
  Select Case n
    Case 1
      K1 = p
    Case 2
      K2 = p
    Case 3
      K3 = p
    Case 4
      K4 = p
    Case 5
      K5 = p
    Case 6
      K6 = p
    Case 7
      K7 = p
    Case 8
      K8 = p
    Case 9
      K9 = p
    Case 10
      K10 = p
    Case 11
      K11 = p
    Case 12
      K12 = p
  End Select
End Sub

Sub SetConfig(ByVal n As Integer)
  Select Case n
    Case 0
      Call SetNoConnection

    Case 1
      Call SetIn1Out1
      Call SetIn2Out2
      Call SetIn3Out3

    Case 2
      Call SetIn1Out2
      Call SetIn2Out1
      Call SetIn3Out3

    Case 3
      Call SetIn1Out3
      Call SetIn2Out2
      Call SetIn3Out1

    Case 4
      Call SetIn1Out1
      Call SetIn2Out3
      Call SetIn3Out2

    Case 5
      Call SetIn1Out2
      Call SetIn2Out3
      Call SetIn3Out1

    Case 6
      Call SetIn1Out3
      Call SetIn2Out1
      Call SetIn3Out2

  End Select
End Sub

Sub SetIn1Out1
  Call SetRelais(1 , 0)
  Call SetRelais(4 , 0)
  LED_O1_I1 = true
End Sub

Sub SetIn1Out2
  Call SetRelais(2 , 1)
  Call SetRelais(4 , 1)
  Call SetRelais(6 , 1)
  LED_O2_I1 = true
End Sub

Sub SetIn1Out3
  Call SetRelais(3 , 1)
  Call SetRelais(4 , 1)
  LED_O3_I1 = true
End Sub

Sub SetIn2Out1
  Call SetRelais(1 , 1)
  Call SetRelais(5 , 1)
  Call SetRelais(9 , 1)
  LED_O1_I2 = true
End Sub

Sub SetIn2Out2
  Call SetRelais(2 , 0)
  Call SetRelais(7 , 0)
  Call SetRelais(9 , 0)
  Call SetRelais(11 , 0)
  LED_O2_I2 = true
End Sub

Sub SetIn2Out3
  Call SetRelais(3 , 0)
  Call SetRelais(8 , 1)
  Call SetRelais(9 , 0)
  Call SetRelais(11 , 1)
  LED_O3_I2 = true
End Sub

Sub SetIn3Out1
  Call SetRelais(1 , 1)
  Call SetRelais(10 , 1)
  LED_O1_I3 = true
End Sub

Sub SetIn3Out2
  Call SetRelais(2 , 0)
  Call SetRelais(7 , 1)
  Call SetRelais(10 , 0)
  Call SetRelais(12 , 1)
  LED_O2_I3 = true
End Sub

Sub SetIn3Out3
  Call SetRelais(3 , 0)
  Call SetRelais(8 , 0)
  Call SetRelais(10 , 0)
  Call SetRelais(12 , 0)
  LED_O3_I3 = true
End Sub

Sub SetNoConnection
  'No connections
  Call SetRelais(3 , 0)
  Call SetRelais(4 , 0)
  Call SetRelais(5 , 0)
  Call SetRelais(6 , 0)
  Call SetRelais(7 , 0)
  Call SetRelais(9 , 0)
  Call SetRelais(10 , 0)
  Call SetRelais(11 , 0)
  Call SetRelais(12 , 0)
  Call SetRelais(1 , 1)
  Call SetRelais(2 , 1)
  Call SetRelais(8 , 1)

  LED_O1_I1 = false
  LED_O1_I2 = false
  LED_O1_I3 = false

  LED_O2_I1 = false
  LED_O2_I2 = false
  LED_O2_I3 = false

  LED_O3_I1 = false
  LED_O3_I2 = false
  LED_O3_I3 = false
End Sub

system.inc

Sub goSleep
  LEDPWR = LEDPWR_aus
  E_Position_Curr = Position_Curr
  ENABLE INT0
  ENABLE PCINT0
  CONFIG POWERMODE = POWERDOWN
  Waitms 200
  LEDPWR = LEDPWR_ein
End Sub