AppleScripting cocoaModem 2.0
Kok Chen, W7AY [w7ay (at)
arrl.net]
Last updated: January 14, 2009
Index
Introduction
cocoaModem does not pretend to be a digital interface for
everybody; when there are multiple methods to get something
done, cocoaModem will often implement only a single method.
cocoaModem also does not provide sophisticated contest nor
logging facilities. I have tried to build decent
demodulators for cocoaModem, but the area of user
interfaces is neither a forte nor an interest of mine.
In an attempt to allow others to configure cocoaModem to
their specific needs, I’d made cocoaModem’s
source code completely free to non-commercial users.
However, this still limits the audience of people to
programmers who know how to get around in Cocoa.
For the non-programmer, I have added AppleScript support.
This allows a wider set of people to create extensions for
cocoaModem. It allows cocoaModem to inter-operate and share
data with new, or with existing applications, including
those that are written for other frameworks, such as Carbon
or REALbasic.
As an example, whenever cocoaModem wishes to transmit, it
simply generates the needed waveform and cocoaModem sends
the audio signal to the output device. It assumes that the
presence of that audio signal will trigger a VOX mechanism,
which in turn will key the transmitter. This is the
simplest and most plug-and-play means to connect a
Macintosh to an SSB transceiver, and is the only
“push-to-talk” mechanism provided natively by
cocoaModem. AppleScripts that are associated with the
Transmit button are used to implement other
push-to-talk schemes.
Sending AppleScript Messages to
Other Applications
cocoaModem can be set up so that certain activities (e.g.,
pressing the Transmit button in the interactive
interface, or pressing the Log button in the QSO
strip) can cause user-defined AppleScript scripts files to
be executed. This is the mechanism which allows the buttons
to be user configurable.
Figure 1 shows the AppleScript tab in the cocoaModem
Preferences panel (select Preferences inside the
cocoaModem 2.0 menu in the menu bar, or use the
Command-comma keyboard shortcut).
Figure 1 -
AppleScript Preferences
The User Defined PTT
scripts are described in the PTT section of the manual. The QSO
Log script is executed when the Log button
in the control strip is depressed.
Each text field in this preference panel points to the path
of a script file (QSO Log) or to a folder that contains the
script files (User Defined PTT). The Browse button
for each text field allows you to use a standard file
dialog to find and select the file or folder to use. If a
text field is empty, no script will be executed for that
action.
These script files are read, compiled and cached as
NSAppleScript objects when cocoaModem initializes. They are
recompiled and re-cached whenever the name of the
Applescript file is changed.
QSO Log
The QSO Info bar (see cocoaModem User’s manual) of
the interactive interface has a Log button which is usually
disabled and gray out. This button becomes enabled when the
Log button is linked to a script file through the
AppleScript preference described above. The Log button
executes this script when it is pushed. The script can for
example fetch certain data from cocoaModem and send those
to a second scriptable program.
Receiving AppleScript Messages
from Other Applications
Figure 2 below shows cocoaModem’s AppleScript class
hierarchy.
Figure 2 -
cocoaModem AppleScript Hierarchy
As usual, cocoaModem 2.0 is
reached from an application tell block. The
following is an example script. The rest of this section
looks at each class in more detail.
set properties of receiver to { mark:2295.0, space:2125.0 }
set properties of transmitter to { mark:2125.0, space:2295.0 }
select rtty modem
select contest interface
cocoaModem Interfaces
The cocoaModem interface can be either an interactive interface or a contest interface.
(Note: these two interfaces are the same ones as presented in the Interface menu in the main cocoaModem menu bar.)
The cocoaModem interface that is shown on the desktop is selected by one of the following:
select contest interface
Interface Window Color
The background color of a non-textured window can be changed by
The three numbers represent respectively the red, green and blue components in RGB Color Space. 0 is the minimum value and 65535 (16-bit unsigned integer) is the maximum value.
Modems
The two interfaces (interactive and contest interfaces) share a set of modems, and the modems can be the RTTY, the dual RTTY, the wideband RTTY, the PSK, the Hellschreiber, the CW or the MFSK modem. Each modem is controlled by addressing them through their parent interfaces.
Modem interfaces are known by their names (in the cocoaModem main window's tabs), e.g. rtty modem, wideband rtty modem, dual rtty modem, psk modem, hellschreiber modem, cw modem or mfsk modem . You can select them for example by:
or
The currently selected modem interface can be found by
modemName returns a text string that is one of
“wideband rtty modem”
“dual rtty modem”
“psk modem”
“hellschreiber modem”
“cw modem”
“mfsk modem”
Transceivers
Each modem contains pairs of transmit and receive modules in the form of a transceiver. The RTTY modem has one transceiver, and the Dual RTTY, wideband RTTY, PSK and CW modems have two transceivers each.
Each transceiver is further partitioned into a transmitter and a receiver module, which we will see later.
Each transceiver has a transmit state, a modulation mode and an enable state to turn it on (receiver active) or off (receiver inactive).
You can query the transceiver that is currently active with the selectedTransceiver property, e.g.,
selectedTransceiver returns 1 if the Xcvr 1 or Main transceiver is chosen, and selectedTransceiver returns 2 if Xcvr 2 or Sub transceiver is chosen. For modem interfaces that only have a single transceiver, selectedTransceiver returns 1 always.
Modulation Mode
With the PSK modem, the specific modulation mode of a transceiver can be selected to BPSK31, QPSK31, BPSK63, QPSK63, BPSK125 and QPSK125. For example
The above an also be written as:
With Hellschreiber, you can select Feld, FM105 and FM245 as the modulation modes, e.g.,
With MFSK, you can at present only select MFSK16 as the modulation mode, e.g.,
The modulation property is not presently used in the RTTY or CW modems.
Transceiver Enable
When enabled, a transceiver will demodulate and decode the incoming data to its receiver’s text stream. An enabled transceiver is also capable of being set into the transmitting state.
Setting enable to true is equivalent to setting the state of the modem to “active” in the modem’s receive config panel.
The enable state can be read back using
Note: since the two transceivers of the PSK modem share the same A/D converter, you can set the enable state of the PSK modem using either transceiver 1 or transceiver 2. The two channels of the Dual RTTY, wideband RTTY and CW modems have separate A/D converters and each transceiver can be independently enabled or disabled.
Transmit State
The state of a transceiver can either be receive or transmit.
Care should be taken to ensure that only one transceiver of one modem is in the transmit state, otherwise the output tones will be mixed and sent to the radio as separate PSK signals!
Note: for the PSK, CW, Hellschreiber and MFSK modems, the center frequency has to be selected (either by clicking on the waterfall or by sending the set frequency AppleScript to the modem) before the modem will switch to the transmit state. The frequencies of both the receiver and transmitter modules have to be set even though the transmission is only done through the transmitter.
Flush
If the modem is in the transmit state, any text characters in the transmitter module that has not yet started will be flushed away with the flush command. If the modem is not transmitting, all text in the transmitter module that is waiting to be sent out is discarded.
Likewise, text in the receiver module’s buffer can be flushed. This causes subsequent get text requests to return empty strings until new text has been decoded by the demodulator.
Receiver and Transmitter Modules
Each transceiver consists of a receiver and a transmitter, each with a set of properties. For example, the following script will set the offset frequency of the receiver module of the psk transceiver:
The above script can also be written as:
Frequency Property of Module
frequency is a floating point value.
In an RTTY modem, this property is the same as mark, and specifies the Mark frequency of the AFSK signal.
In a PSK modem, this parameter specifies the frequency of the audio carrier tone of the PSK signal. Note that the PSK modem returns a -1.0 if the frequency has not been set.
Setting the property of a PSK receiver module to zero will deselect the particular channel (similar to a shift-click on the waterfall). However, even if the receiver is deselected, transmission is possible as long as a legitimate tone is sent to the transmit module.
Note that in PSK mode, the frequency property will be different from the frequency shown on the waterfall scale unless the Dial Readout in the PSK config panel has been set to Upper Side Band with 0 offset.
Mark and Space Frequencies
mark and space are floating point values which specify the Mark and Space frequencies of an RTTY signal.
These properties are not used by non-RTTY modems.
With an LSB transceiver, with standard amateur RTTY conventions, the space frequency of a standard RTTY signal is 170 Hz higher than the mark frequency.
set space to 2295.0
Baud Rate
baud is a floating point value which specifies the baud rate an RTTY signal.
This property is not used by non-RTTY modems.
The conventional amateur RTTY baud rate is 45.45 baud (usually just called “45 baud”), determined by the 22 millisecond bit timing of the Baudot characters.
Even though it is rare to see anything other than 45 baud operation in the amateur bands, there have been occasions where hams have been known to use other baud rates. P5/4L4FN had operated for a period at 50 baud, and there used to be a high speed RTTY contest conducted at 75 baud.
The mark frequency, space frequency and the baud rate can be set with a single set properties command:
Invert
invert is an integer value (0 or 1) which specifies the inverted state of an RTTY tone pair.
This property is not used by non-RTTY modems.
Under standard amateur RTTY conventions, the space frequency an LSB transceiver is 170 Hz higher than the mark frequency. Inverting the signal will reverse the relative position of the tone pairs.
set invert of receiver to 1
Break-in
breakin is an integer value (0 or 1) which specifies if semi-break in is selected
This property is only currently used in the CW interface and it only applies to the transmit module.
To get the break-in state of the CW interface,
To set the break-in state of the CW interface
If the AppleScript breakin property is asserted, anything sent to the module's stream will cause the PTT to assert and the character(s) in the stream to be immediately transmitted.
Stream
Each module of a modem is associated with a text string called the stream.
Text is added by cocoaModem to the receiver modules’ streams as they are demodulated and decoded. The AppleScript client periodically polls the stream for new characters. An empty string is returned if there are no new received characters.
Since RTTY is sent at 6 characters per second, when polled at a slower rate than 6 per second, the returned RTTY modem’s stream can contain more than one character.
Each text string is a portion of a 256 character circular buffer. If the module is not polled often enough, the buffer can wrap around, causing text to be lost.
To transmit text, the client adds characters to the transmitter module of a transceiver by setting the stream string:
For example, the following AppleScript can be used to transmit a quick CQ message over RTTY:
set stream of transmitter to “\nCQ CQ\n”
set state to receive
When the transceiver is in the transmit state, the string will be immediately sent to the transmit stream. Otherwise, it will be buffered and will be sent the next time the modem is placed in the transmit state.
Text that has been sent to the modulator can be read back by performing a get on the transmit text stream. This functions as an echo of characters as they are being transmitted.
As mentioned earlier, any text left in the transmit buffer can be flushed using the flush transmitter command.
The set stream AppleScript works with Hellschreiber, but you cannot read any stream from the receive module since Feld Hell and FM Hell are facsimile modes -- there is no decoded text stream to read back.
Replay (click buffer)
cocoaModem's PSK, wideband RTTY and wideband CW interfaces come with "click buffers." These are buffers which stores up to 20 seconds of wideband audio. Input from the sound card are written into the click buffer and data are read by the demodulators from the buffer. Two pointers determine where data is written into and where data is read from, acting in a ring buffer manner -- the ring's size accommodating about 20 seconds worth of audio.
As long as the consumer and producer pointers of the ring buffer are not identical, data is handed to the demodulators at about 8 times real-time rate.
The replay AppleScript allows the client to move the consumer pointer so that up to 20 seconds of "old" audio is replayed into the demodulator.
cocoaModem will treat the replay AppleScript as a no-op if it is sent to a modem that does not support a click buffer. A transmit module will also treat the replay AppleScript as a no-op.
The replay property, a floating point, will be truncated to 20 seconds if a larger value is sent to it. Values that are negative, or are smaller than 0.1 second are replaced by 0.1 second.
Spectrum
An AppleScript client can draw its own waterfall or panadaptor display by fetching the spectrum from the receive module of the wideband RTTY and PSK interfaces.
Please note for the present, only the spectrum of "transceiver 1" of the RTTY interface is available. The two PSK transceivers share a common waterfall, which can be obtain from "transceiver 1" of the PSK interface.
The following script can be used to fetch a spectrum:
This script returns a zero length string if an updated spectrum is not yet available. Otherwise, it returns a string of 1024 bytes. Each non-zero byte is treated as an unsigned 8-bit number.
The 1024 numbers represent FFT bins with a resolution of 2.692 Hz per bin. The 0-th byte contains the value of the DC bin and the 1023-rd byte contains the value of the FFT bin that is centered at approximately 2756 Hz (i.e., at 11025/4 Hz).
To compress the spectral height into a single unsigned byte, the values are encoded as the square root of the power (i.e., the fourth root of voltage) in each FFT bin.
The amplitude of each FFT bin is encoded with pow( v, 0.25 )*5.52. A full scale signal (when a narrow carrier causes the yellow bar in cocoaModem's VU meter to light up) is encoded into the value 200, a signal that is -30 dB from full scale is encoded as the value 35, etc. A clipped signal can exceed the nominal full scale signal and reach a value of about 234.
The waterfall in cocoaModem updates approximately every 371 milliseconds. While a new spectrum is not yet available, cocoaModem will respond to the get spectrum request by returning a string of length zero.
To help the client avoid needless polling, the next spectrum script returns an integer which gives an estimate of the number milliseconds before the next FFT spectrum becomes avalable.
If next spectrum returns zero, another spectrum is immediately available to be fetched.
next spectrum returns a conservative estimate; 2.5 milliseconds is added to the scheduled time an FFT is next taken by cocoaModem. However, system latencies can cause next spectrum to return an estimate that is still too small. Because of this, get spectrum should always be checked to see if the length of the returned string is zero. If a string of length zero is returned by get spectrum, a new spectrum is not yet available and next spectrum should then be called again, followed by a delay it specifies. The next get spectrum should again be called only after this delay.
When cocoaModem is placed in transmit mode, no new spectrum will be returned until cocoaModem returns to the receive mode. In the transmit mode, next spectrum will always return the maximum delay (approx 374 msec). The algorithm given above will still work while cocoaModem is transmitting since it simply causes the client to re-poll cocoaModem every 374 milliseconds. When cocoaModem is later switched back to receive mode, the spectrum stream will automatically resume.
Windows and Panels
Some windows and panels in cocoaModem can be controlled through AppleScripts.
The main window (including the Lite window) can be made visible or invisible by setting the application's window state to true or false, respectively.
The main window position can also be read and set by addressing the window position property.
set window position to {15,200}
The position consists of two integers, representing the x and y locations of the bottom left corner of the window.
The Config panel of any modem can be brought up by sending open config panel to the modem.
In addition, the RTTY modem of the Lite interface has two auxiliary windows that can be displayed or hidden and their positions can also be read back or set.
set show controls to false
set spectrum position to { 500,100 }
set show spectrum to false
Setting show controls and show spectrum to true or false makes the controls window or spectrum window visible or invisible. The controls window is the one with the crossed ellipse indicator, and the spectrum window is the one with the spectrum of the input device (similar to the spectrum in the config panel).
Like the main window, the position consists of two integers, representing the x and y locations of the bottom left corner of the window.
version and scriptVersion
scriptVersion returns an integer. The current script version is 3.
version is a string (e.g., "0.90") that is the current version of cocoaModem 2.0. The version AppleScript is available from scriptVersion 3 onwards.
Watchdog Timer
There is a watchdog timer in cocoaModem that unkeys the transmitter when the duration exceeds a a limit. To prevent the watchdog time from firing, the timer can be reset periodically (once every 30 seconds is sufficient) using the reset watchdog AppleScript .
QSO Info
The qso (QSO Info subclass) property of the application accesses the callsign and operator name text strings in cocoaModem’s QSO Info bar. Examples of its usage is
Note that when a property is inside of a set of nested tell blocks, you can concatenate the classes by using one or more of directives and write the above more concisely as
Similarly, the operator name field can be accessed using
Contest Interface
The band menu in cocoaModem’s read and set through an AppleScript. This allows an external rig control software to change the band menu.
set band of contest to 15
cocoaModem Suite Dictionary
The cocoaModem 2.0 AppleScript suite is defined in the file cocoaModem 2.0.sdef. The classes defined in the suite are application, interface, modem, module and QSO.
Commands
Classes
rtty / dual rtty / wideband rtty / psk / hellschreiber / cw / mfsk modem
scriptVersion
version
modulation bpsk31 / qpsk31 / bpsk63 / qpsk63 / bpsk125 | qpsk125 | mfsk16
state transmit / receive
flush module
module transmitter / receiver
mark float
space float
baud float
invert int
breakin int
stream text
operator name text
Deprecated AppleScripts
The global AppleScript properties that were available in cocoaModem 1.15 are now deprecated.
In some future version of cocoaModem, these AppleScripts will no longer be accepted. It is being kept for the time being for users to transition to the new AppleScripts. The deprecated AppleScripts and their new equivalents are shown below.
use instead: select rtty modem
use instead: set modulation of transceiver 1 of psk modem to bpsk31
use instead: get frequency of receiver of transceiver 1 of psk modem
use instead: get frequency of transmitter of transceiver 1 of psk mode
use instead: get frequency of receiver of transceiver 2 of psk modem
use instead: get frequency of transmitter of transceiver 2 of psk modem
use instead: get callsign of qso
use instead: get operator name of qso
Index