This section of the document describes how an application interfaces to the µH Router using the UDP interface. If you are only interested in using the router, please go directly to the
Set Up page.


UDP Interface

The UDP interface uses the bidirectional User Datagram Protocol to communicate.

Once µH Router is launched, it opens a number of UDP ports that the client can use to communicate with each of the keyer's function.

When the client has finished using the router, it can terminate the router, or just leave µH Router running.


Launching the µH Router

There are multiple ways to launch µH Router. With Cocoa, you can send a -launchApplication: message to the AppKit's NSWorkspace class. With Carbon, you can launch an application by calling LSOpenApplication in Launch Services. Finally, you can use AppleScript to launch the router from an AppleScript Studio program or a Carbon or Cocoa application.


Master UDP Ports on the µH Router

The µH Router opens four UDP ports when it is launched. The master port is at 60744. The other ports are used by up to three keyers (microKeyer, CW Keyer and digiKeyer) and have the next three consecutive port numbers.

Although they are not dynamically created, you won't directly use the three ports that are associated with the keyers. You request those port numbers from the master port. They are mentioned here in case you need to open a network Firewall for the UDP packets to pass through.

The master port corresponds to the number ( ( 0x8000 | ' mH' ) & 0xffff ).

The following are single byte datagrams that you can send to the router's master port:

#define ROUTERFUNCTION   0x80
#define OPENMICROKEYER   ( ROUTERFUNCTION + 0x01 )     // get a port to the microKEYER router
#define OPENCWKEYER      ( ROUTERFUNCTION + 0x02 )     // get a port to the CW KEYER router
#define OPENDIGIKEYER    ( ROUTERFUNCTION + 0x03 )     // get a port to the DIGI KEYER router
#define QUITIFNOKEYER    ( ROUTERFUNCTION + 0x1f )     // quit if there are no keyers
#define QUITIFNOTINUSE   ( ROUTERFUNCTION + 0x1e )     // quit if not connected
#define QUITALWAYS       ( ROUTERFUNCTION + 0x1d )     // quit
#define WATCHDOG         ( 0x08 )


(Notice that, except for the additional WATCHDOG item, these have the same values as the commands sent to the FIFO's master port that is described in the Interface section. The watchdog function is described later here.)


Obtaining UDP Ports to a Keyer

To obtain a port for communicating with a keyer, you send a single byte datagram with OPENMICROKEYER or the OPENDIGIKEYER or the OPENCWKEYER byte to the master port. The µH Router will send back a three byte datagram. The following is an example of obtaining the UDP port of the microKeyer.


  unsigned char buffer[4] ;

  buffer[0] = OPENMICROKEYER ;
  sendto( mySocket, command, 1, 0, (struct sockaddr*)udpServerAddress, sizeof( struct sockaddr ) ) ;

  int port = 0 ;
  if ( recv( mySocket, buffer, 4, 0 ) == 3 ) && ( buffer[0] & 0xff ) == OPENMICROKEYER ) {
    port = buffer[1]*256 + buffer[2] ;
  }

The first byte of the reply datagram contains OPENMICROKEYER or OPENDIGIKEYER or OPENCWKEYER. The next two bytes contain the big endian port number for the keyer's UDP port. The two bytes will be zero if µH Router could not find an attached (hardware) keyer.

There is no need to "close" a connection. The router will remove any UDP client that has been inactive for more than 60 seconds. A client stays connected by sending keyer commands, and it can ask to stay connected by periodically sending a watchdog datagram. A watchdog packet can be considered to be a no-op operation that only updates timers in the router. The watchdog packet is described in greater detail here.

Note: µH Router should return port 60745 for the microKeyer if it exists, 60746 for the CW Keyer if it exists, and port 60746 for the digiKeyer if it exists. However, you should use the number that is returned in the datagram in case there is a change in the future.


Communicating with Keyer Functions

Each microHAM keyer has multiple functions, and each of these functions can be accessed by prefixing a datagram with a PREFIX byte:

#define RADIO_PREFIX   ( KEYERFUNCTION + 0x02 ) // RADIO function
#define CONTROL_PREFIX ( KEYERFUNCTION + 0x03 ) // CONTROL function
#define PTT_PREFIX     ( KEYERFUNCTION + 0x04 ) // PTT flag bit
#define CW_PREFIX      ( KEYERFUNCTION + 0x05 ) // serial CW flag bit
#define RTS_PREFIX     ( KEYERFUNCTION + 0x06 ) // RTS flag bit
#define FSK_PREFIX     ( KEYERFUNCTION + 0x07 ) // FSK serial port
#define WINKEY_PREFIX  ( KEYERFUNCTION + 0x08 ) // WinKey port
#define FLAGS_PREFIX   ( KEYERFUNCTION + 0x09 ) // FLAG bits
#define WINDOW_PREFIX  ( KEYERFUNCTION + 0x0b ) // response window


Whenever µH Router gets a response from a function (e.g., FSK) in the keyer, it checks all connected UDP clients to see if the client has sent a command to that function within a response time. A UDP client is "connected" if it has used one of the OPEN operations described above. If a client has sent a command, µH Router will pass the keyer's response to the client.

Please note that a UDP client can still receive a response that it did not initiate; for example when a different client has sent a keyer command to the same function within the same response window. However, this mechanism should reduce the number of datagrams that the client has to discard.

There are two exceptions to this.

The first exception is that in addition to responding to FLAGS requests, a FLAGS response will also be returned to clients that have made PTT, CW, RTS or FSK requests within the response window. This is because PTT, CW, RTS ad FSK can all cause a FLAGS response. E.g., the FSK buffer empty state is sent back from a microHAM keyer through the FLAGS channel, not the FSK channel.

The second exception is when the WRITEONLY flag is merged with the PREFIX byte (e.g., PTT _PREFIX | WRITEONLY ). In this case, a response window will not be opened.


RADIO Port

Datagrams that are sent to a keyer's RADIO port should have a RADIO_PREFIX byte prepended to the control data.

Datagrams that are sent back through the UDP keyer port will also begin with a RADIO_PREFIX byte. As in the FIFO case, µH Router aggregates single byte responses from the keyer's RADIO port into a buffer. An entire buffer is sent to the client only when an "aggregate timeout" has exceeded. The client should be prepared to see multiple byte RADIO datagrams.

Please note that you do not use ioctl to set the serial port parameters (bits, parity, baud rate) of the radio port. Instead, you set the radio's serial parameter by using SET RADIO CHANNEL command the Control Port. Please refer to the microHAM Keyer Protocol document for the details.


CONTROL Port

Datagrams that are sent to a keyer's CONTROL port should have a CONTROL_PREFIX byte prepended to the RADIO data.

Datagrams that are sent back through the UDP keyer port will start witjh a RADIO_PREFIX byte.

In addition to the 8 bit data bytes in a CONTROL stream, the microHAM keyers require that the first and the last byte of a control command string be specially tagged. The way the µH Router handles this is to require that you send each complete command string using a single UDP sendto() call. The router will then tag the first and the last byte of that string properly. These tagged bytes are the ones that are shown in bold in the microHAM Keyer Protocol document.

A response from a keyer's CONTROL port will likewise be buffered so that all the bytes of a CONTROL stream are sent in a single datagram back to the client.

The Control port of a microHAM keyer is used to set parameters in the keyer. This includes setting the serial port parameters (number of data and stop bits, parity and baud rate) of the RADIO and FSK channels, settings various parameters such as FSK polarity, setting up the WinKey memory, obtaining version number of the keyer, setting up the bootloader for downloading new firmware, etc.


PTT Port

If you send a non-zero byte that is not an ASCII '0' to this port, the keyer will engage the PTT of the attached receiver (as long as the keyer is set up to connect this command to the physical PTT line - see STORE SETTINGS command in the microHAM Keyer Protocol document).

Whenever the PTT state changes, the PTT changes are reported back as a bit within the FLAGS channel of the keyer. µH Router will send the FLAGS bytes back to the client.

Please be prepared to ignore any FLAGS state changes that you did not initiate since they can be caused by other applications or even other physical sources (e.g., from a foot switch).

Data is sent from UDP to the PTT port if the datagram starts with the PTT_PREFIX byte. Responses from the keyer are sent to the client as datagrams whose initial byte contains the FLAGS_PREFIX.


Serial CW Port

Like the PTT port, this port asserts or deasserts a "serial CW" keying line. If the keyer is set up to obey the signal, writing a non-zero character to this port will assert the keying line from the keyer to the radio. With the current firmware from microHAM, the Keyer Mode has to be set to CW for serial CW and WinKey to function.

Data is sent from UDP to the serial CW port if the datagram starts with the CW_PREFIX byte. Responses from the keyer are sent to the client as datagrams whose initial byte contains the FLAGS_PREFIX.



RTS Port

This is yet another port that controls a flag bit on the Keyer and appears on the RTS pin of the serial port from the keyer to the radio.

Data is sent from UDP to the RTS port if the datagram starts with the RTS_PREFIX byte. Responses from the keyer are sent to the client as datagrams whose initial byte contains the FLAGS_PREFIX.



WinKey Port

This is the port that is connected to the WinKey chip on a microKEYER and a CW KEYER (note: the DIGI KEYER lacks this chip).

The data that you send to this port is documented in K1EL's WinKey document. You can command the WinKey chip to send Morse characters, change dash/dot weighting, CW speed, join two characters into a Prosign, etc.

Data is sent from UDP to the WinKey port if the datagram starts with the WINKEY_PREFIX byte. Responses from the keyer are sent to the client as datagrams whose initial byte contains the WINKEY_PREFIX.



FSK Port

This port allows you to send Baudot data to an FSK buffer in the keyer, to be sent out as an FSK keying line. The baud rate and other parameters are set up by sending the SET FSK CHANNEL command to the CONTROL port. Characters sent to the FSK Port will key the FSK line of the radio.

(NOTE: the FSK ports in the microHAM devices do not work at the nominal Amateur RTTY data rate of 45.45 baud -- you will have to configure it to use 45.0 baud. While this is not ideal with demodulators that are tuned for 22 msec bit periods, there should be no noticeable difference in performance except when the SNR is very poor.)

Data is sent from UDP to the FSK port if the datagram starts with the FSK_PREFIX byte. Changes in the empty state of the FSK buffer in the keyer is reported back as a bit in the FLAGS channel. Because of that, µH Router will send FLAGS changes to a client that is actively using the FSK port as datagrams whose initial byte contains FLAGS_PREFIX. Currently, the microHAM keyers do not send any response back in the FSK port.


Write-only Datagrams

The keyer functions (PTT, WinKey, FSK, etc) can be sent in Write-only mode if you are not interested in responses from the keyer. To send a command and not receive a response, merge the WRITEONLY flag to the PREFIX byte (e.g., PTT_PREFIX|WRITEONLY). The WRITEONLY flag is defined as:

#define WRITEONLY   0x80


Timeouts and response windows

The router will stop communicating with a client if it does not see any datagrams from the client in 60 seconds.

To keep the router alive when there is no new data to send to the keyer, the client can send a single byte WATCHDOG datagram to either the router's master UDP port, or one of the keyer's UDP port.

#define WATCHDOG       ( 0x08 )

If the WATCHDOG packet is sent to the master UDP port, the router will update all the keyers which the client is using. If it is sent to a keyer's UDP port, it only extend the timeout for the client's connection to the keyer.

The router has a mechanism to keep responses from the keyer that are not initiated by a client down to a minimum. This is done by establishing a response window for each keyer function. If a keyer response arrives outside of a window after a keyer command was sent by the client, the router will assume that the response belongs to a different client. The default window is 1 second.

For example, if a response to a CONTROL command arrives from the keyer later than 1 second after a CONTROL command arrives from the client, the response will not be passed back to the client.

The client can change the response window from the default 1 second by issuing a datagram that has the WINDOW_PREFIX as the first byte.

#define WINDOW_PREFIX   ( KEYERFUNCTION + 0x0b ) // response window

A response window datagram consists of 3 bytes, starting with the WINDOW_PREFIX byte. It is followed by a byte that specifies the function, such as RADIO_PREFIX. The third byte encodes the response window duration.

If the duration (last) byte contains 0, the response window will be set to the default (1 second) value. If it contains 255, the response time will be consider indefinite (actually hundreds of days). For any other value, the response time is set to n/16 of a second, where n is between 1 and 254.

The FLAGS, PTT, serial CW and RTS "ports" share the same response window parameter.


Terminating the µH Router

There are three different ways that you can use to terminate the µH Routerby sending a single byte datagram to the µH Router's master port.

#define QUITALWAYS       ( ROUTERFUNCTION + 0x1d )     // quit
#define QUITIFNOKEYER    ( ROUTERFUNCTION + 0x1f )     // quit if there are no keyers
#define QUITIFNOTINUSE   ( ROUTERFUNCTION + 0x1e )     // quit if not connected

The first way is the unconditional quit message that you can send to the router's master port. It is not advisable to use this command if the router can potentially be shared and be in use by another application., for example:

  command[0] = QUITALWAYS ;
  sendto( mySocket, command, 1, 0, (struct sockaddr*)udpServerAddress, sizeof( struct sockaddr ) ) ;

When the µH Router receives the QUITALWAYS command, it waits one second and then quits.

The µH Router also supports a quitIfNoKeyer command. When the µH Router wakes up, it looks to find any serial port that is associated with a microHAM device. It it does not find any keyer and if it receives a subsequent quitIfNoKeyer command, the µH Router will terminate itself.

  command[0] = QUITIFNOKEYER ;
  sendto( mySocket, command, 1, 0, (struct sockaddr*)udpServerAddress, sizeof( struct sockaddr ) ) ;

Instead of launching the µH Router and then asking it to quit, the application can also check to see if any microHAM devices exist before launching the router. microHAM devices have serial ports with names that start with "usbserial-MK"(microKEYER), "usbserial-DK"(DIGI KEYER) or "usbserial-CK"(CW KEYER).

Another conditional termination script is the quitIfNotInUse command. This command will cause the µH Router to terminate if there are no connections made to it from an application. You can safely send the quitIfNotInUse command to the µH Router just before your application terminates. This will remove the router from the dock if no other application is using the router. E.g.,

  command[0] = QUITIFNOTINUSE ;
  sendto( mySocket, command, 1, 0, (struct sockaddr*)udpServerAddress, sizeof( struct sockaddr ) ) ;