priyom.org

DPRK-ARQ Protocol

North Korean diplomatic communications utilize a proprietary ARQ modem of unknown name, unofficially known as DPRK-ARQ. Depending on which stations on the diplomatic network are involved, the modem can be observed to operate in three different regional variants:

  • the Moscow variant, used for links between an embassy and the Moscow hub (modem ID: 0xA5)
  • the Pyongyang variant, used for links between an embassy and the Pyongyang hub (modem ID: 0xD3)
  • the relay variant, used for links involving neither Moscow nor Pyongyang hubs

The Moscow and relay variants differ only by some command codes, and slightly quicker-paced bursts for the relay variant; whereas the Pyongyang variant differs majorly from them in flow control and ARQ sequencing. Due to lack of data, understanding of some implementation details of the Pyongyang variant is still tentative.

Waveform

The modem is based on BFSK bursts transmitted in lower sideband mode. There are two possible waveforms: 600Bd/600Hz as the default, and 1200Bd/600Hz as an option. The nominal center frequency is 1500 Hz, although it is frequently slightly modified by the operators for unknown reasons. When demodulated in LSB, the upper frequency is space (0), and the lower frequency is mark (1).

The bursts are packets of synchronous data whose structure follow a similar pattern in 600Bd and 1200Bd modes, the 1200Bd waveform basically extending the 600Bd one with double the elements:

1200Bd only 600Bd and 1200Bd 1200Bd only
1010101010 10101010101 B53C6161 D5AFDBA 61616161 9327A3A 61616161 9327A3A 61616161 9327A3A
Bit reversals,
up to 11 bits
Bit reversals,
up to 11 bits
32-bit data
section 1
28-bit
checksum
32-bit data
section 2
28-bit
checksum
32-bit data
section 3
28-bit
checksum
32-bit data
section 4
28-bit
checksum

Whether in 600Bd or 1200Bd mode, the packet bursts have the same approximate duration, between 200 and 218 ms. These packets are paced and sent every 540 ms for the Moscow and Pyongyang variants; the relay variant instead uses a shorter, variable frame duration between 500 and 540 ms. Links operate between station pairs, each station synchronized to transmit between the frame gap of the other one.

Packet structure

The data sections are simply joined together to form a packet: the length of a packet is 8 bytes in 600Bd mode, or 16 bytes in 1200Bd mode. The checksumming mechanism is not well understood, although collisions are easy to observe, and the second and further checksum sections seem to depend on at least the first one. Packet data follows this generic structure:

Peer station
modem ID
Packet type /
ARQ sequencing
Payload 1200Bd extra payload
B5 3C 61 61 61 61 61 61 61 61 61 61 61 61 61 61

The first byte is the modem ID of the peer station on the link - the destination of the packet rather than their source. Known modem IDs, some identified with and located to given embassies, are listed here.

The second byte of each packet indicates the packet type, and is modulated by ARQ sequencing information used to manage packet retransmission. This modem uses stop-and-wait ARQ, realized in this case by treating new packets from the other station as acknowledgements, and repeats as non-acknowledgements.

ARQ sequencing

The ARQ sequencing method used is a major difference between the Moscow/relay and Pyongyang variants.

The Moscow and relay variants split the packet type byte into two 4-bit sections, which may take only 0, 3, C, or F as valid values. There are six pairs of valid request-response packet type bytes, corresponding to three packet categories. The modem alternates between the two variants for consecutive packets of the same kind. The 3_ variant follows C_, and vice versa.

Category Request Response
Commands CF FC
3F F3
Chat/idle
traffic
C0 0C
30 03
Data
traffic
CC 3C
33 C3

The Pyongyang variant splits the packet type byte into four 2-bit sections, the outer two being the packet type, and the inner two being ARQ counters:

Pyongyang variant
00 01 10 00
First 2 bits of
packet type
ARQ ack.
counter
ARQ seq.
counter
Last 2 bits of
packet type

The two counters may take 00, 01, 10, 11 as values, in that order; the initial state of both is 00. The sequence counter increments with each new (not retransmitted) packet. The other counter is an acknowledgement counter. Correct reception of a packet from the peer station is acknowledged by sending a new packet with both acknowledgement and sequence counters incremented. Non-acknowledgement is indicated by sending a new packet with an increased sequence counter, but unmodified acknowledgement counter, which causes the other station to repeat its last packet.

Packet types

The packet type is indicated by the bits of the second byte that are not used for ARQ sequencing. In the following table, "_" is used to denote bits used for ARQ.

Packet
type
Moscow / relay variants Pyongyang variant Payload
type
Bit field Possible values Bit field Possible values
Traffic modes
Data ________ 33 / CC, C3 / 3C 00____11 03 / 17 / 2B / 3F, ... Byte stream
Chat ____0000 C0 / 30 00____10 02 / 16 / 2A / 3E, ... Byte stream
Idle 0000____ 0C / 03 00____00 00 / 14 / 28 / 3C, ... Filler
Commands
Command ____1111 CF / 3F 01____11 43 / 57 / 6B / 7F, ... Parameters
Command ACK 1111____ FC / F3   Filler
CQ   00____01 01 / 15 / 29 / 3D, ... Parameters (custom)
CQ ACK 01____01 41 / 55 / 69 / 7D, ... Parameters

Traffic mode packets are sent continuously while a station is in the corresponding mode. Individual command packets are used to switch between modes and set up the link and transmission. All packet types will be described in detail later below.

Transmission overview

A typical simple, trouble-free DPRK-ARQ link follows this basic structure:

  1. CQ stage and link establishment
  2. Default chat/idle phase
  3. Data transmission in full duplex
  4. Reverting to a chat/idle phase with sign-off operator chatter
  5. Shutting down the link

Here is a transcript of a representative sample transmission where the Moscow hub (0xA5) is calling the embassy with modem ID 0xB3:

B3 CF 01 14 75 00 00 00   [A5 command: CQ 14750kHz]
                          [B3 off]
B3 CF 01 14 75 00 00 00   [A5 command: CQ 14750kHz]   [Retransmit]
                          [B3 off]
B3 CF 01 14 75 00 00 00   [A5 command: CQ 14750kHz]   [Retransmit]
                          [B3 off]
B3 CF 01 14 75 00 00 00   [A5 command: CQ 14750kHz]   [Retransmit]
A5 FC 04 04 A5 FC 05 05   [B3 command: CQ ACK]
B3 CF 01 14 75 00 00 00   [A5 command: CQ 14750kHz]   [Retransmit]
A5 FC 04 04 A5 FC 05 05   [B3 command: CQ ACK]        [Retransmit]
B3 CF 01 14 75 00 00 00   [A5 command: CQ 14750kHz]   [Retransmit]
A5 FC 04 04 A5 FC 05 05   [B3 command: CQ ACK]        [Retransmit]
B3 3F 03 00 00 00 00 00   [A5 command: chat mode]
A5 F3 0C 0C A5 F3 0D 0D   [B3 command: chat mode ACK]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]       [Retransmit]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]   [Retransmit]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]
B3 CF 06 0C 97 00 00 00   [A5 command: data mode, TX ID "0C97", position 0]
A5 3F 07 60 00 00 00 00   [B3 command: data mode response, QRU]
B3 C3 30 03 6B 05 00 00   [A5 data]
A5 3C 60 61 61 61 61 61   [B3 data: end-of-data marker]
B3 33 11 02 00 00 DF 00   [A5 data]
A5 C3 61 61 61 61 61 61   [B3 data: padding]
B3 CC 00 00 19 00 01 11   [A5 data]
A5 3C 61 61 61 61 61 61   [B3 data: padding]
B3 33 41 01 2C 01 4B 00   [A5 data]
A5 C3 61 61 61 61 61 61   [B3 data: padding]
B3 CC 00 00 00 31 77 14   [A5 data]
A5 3C 61 61 61 61 61 61   [B3 data: padding]
B3 33 83 52 54 44 48 70   [A5 data]
A5 3C 61 61 61 61 61 61   [B3 data: padding]   [Retransmit]
B3 33 83 52 54 44 48 70   [A5 data]            [Retransmit]
A5 C3 61 61 61 61 61 61   [B3 data: padding]
B3 CC 35 81 78 74 65 62   [A5 data]
A5 3C 61 61 61 61 61 61   [B3 data: padding]
[Skipping data transmission...]
B3 33 07 40 83 66 38 00   [A5 data]
A5 C3 61 61 61 61 61 61   [B3 data: padding]
B3 CC 14 14 54 53 56 12   [A5 data]
A5 3C 61 61 61 61 61 61   [B3 data: padding]
B3 33 29 10 C8 18 58 1A   [A5 data]
A5 C3 61 61 61 61 61 61   [B3 data: padding]
B3 CC 50 3D 60 61 61 61   [A5 data: end-of-data marker]
A5 3C 61 61 61 61 61 61   [B3 data: padding]
B3 33 61 61 61 61 61 61   [A5 data: padding]
A5 C3 61 61 61 61 61 61   [B3 data: padding]
B3 CC 61 61 61 61 61 61   [A5 data: padding]
A5 CF 08 00 00 00 00 00   [B3 command: end of data]
B3 3F 03 00 00 00 00 00   [A5 command: chat mode]
A5 F3 0C 0C A5 F3 0D 0D   [B3 command: chat mode ACK]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]
[Skipping empty chat/idling...]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]       [Retransmit]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]   [Retransmit]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 72 74 20 6F 6B 20   [A5 chat: "rt ok "]
A5 03 00 00 A5 03 01 01   [B3 idle]
B3 C0 73 6B 00 00 00 00   [A5 chat: "sk"]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]
[Skipping empty chat/idling...]
B3 C0 00 00 00 00 00 00   [A5 chat: ""]
A5 0C 00 00 A5 0C 01 01   [B3 idle]
B3 30 00 00 00 00 00 00   [A5 chat: ""]
A5 03 00 00 A5 03 01 01   [B3 idle]
B3 CF 02 00 00 00 00 00   [A5 command: idle mode]
A5 3F 03 00 00 00 00 00   [B3 command: chat mode]
B3 F3 0C 0C B3 F3 0D 0D   [A5 command: chat mode ACK]
A5 C0 00 00 00 00 00 00   [B3 chat: ""]
B3 0C 00 00 B3 0C 01 01   [A5 idle]
A5 30 00 00 00 00 00 00   [B3 chat: ""]
B3 03 00 00 B3 03 01 01   [A5 idle]
A5 C0 00 00 00 00 00 00   [B3 chat: ""]
B3 0C 00 00 B3 0C 01 01   [A5 idle]
A5 30 33 20 72 74 20 6F   [B3 chat: "3 rt o"]
B3 03 00 00 B3 03 01 01   [A5 idle]
A5 C0 6B 20 73 6B 00 00   [B3 chat: "k sk"]
B3 0C 00 00 B3 0C 01 01   [A5 idle]
A5 30 00 00 00 00 00 00   [B3 chat: ""]
B3 03 00 00 B3 03 01 01   [A5 idle]
A5 C0 00 00 00 00 00 00   [B3 chat: ""]
[Skipping empty chat/idling...]
B3 0C 00 00 B3 0C 01 01   [A5 idle]
A5 30 00 00 00 00 00 00   [B3 chat: ""]
B3 03 00 00 B3 03 01 01   [A5 idle]
A5 30 00 00 00 00 00 00   [B3 chat: ""]
00 00 00 00 00 00 00 00   [A5 shutdown]
A5 30 00 00 00 00 00 00   [B3 chat: ""]   [Retransmit]
                          [A5 off]
A5 30 00 00 00 00 00 00   [B3 chat: ""]   [Retransmit]
                          [A5 off]
A5 30 00 00 00 00 00 00   [B3 chat: ""]   [Retransmit]
                          [A5 off]
A5 30 00 00 00 00 00 00   [B3 chat: ""]   [Retransmit]
                          [A5 off]
                          [B3 off]

In all the various packet examples in the descriptions below, the packet type / ARQ byte shown is only one among two or more possible values when taking ARQ sequencing into account.

Byte stream payload

Transmission data and operator chatter each take the form of byte streams, which are sent segment by segment inside traffic packets. The payload of a data or chat packet is a segment of the corresponding byte stream: 6 bytes in 600Bd mode, or 14 bytes in 1200Bd mode. If, when sending a packet, not enough data is available from the byte stream to fill the whole payload, a shorter segment containing whatever data is available is included, followed by padding.

Peer
station
Type
/ ARQ
Byte stream segment 1200Bd extra byte stream
CE CC 30 01 9B 01 00 00 9B 00 00 00 B6 01 00 00

Parameter payload

Many command packets use the following format to carry a command in their payload. The third byte of the packet is a command code, which may be followed by corresponding command parameters. The rest of the payload after the parameters is padded with 0x00 bytes. Often, the command has no parameters, so the parameters section is simply filled with 0x00. In 1200Bd mode, the extra payload is always padded with 0x00 bytes.

Peer
station
Type
/ ARQ
Code Parameters 1200Bd padding
AA CF 01 11 77 70 00 00 00 00 00 00 00 00 00 00

Filler payload

Some other packets that don't need to carry much information follow a particular filler structure. As in parameter payloads, the third byte is a command code; it is repeated in the 4th byte. This first segment of the packet is then repeated: the first 2, header bytes appear again, identical, then the command code appears again for 2 bytes, its value either identical too (relay variant of the protocol) or incremented by 1 (Moscow and Pyongyang variants). In 1200Bd mode, this pattern also follows in the rest of the packet.

Peer
station
Type
/ ARQ
Code Filler 1200Bd filler
Code
repeat
Header
repeat
Code
variant
Moscow / Pyongyang variants
A5 FC 04 04 A5 FC 05 05 A5 FC 06 06 A5 FC 07 07
Relay variant
D2 FC 21 21 D2 FC 21 21 D2 FC 21 21 D2 FC 21 21

Data packets

Peer
station
Type
/ ARQ
TX data segment 1200Bd extra data
CE CC 30 01 9B 01 00 00 9B 00 00 00 B6 01 00 00

Data packets contain segments of the main transmission data. When the transmission contains actual traffic, the transmission data byte stream follows a structured message format. The data stream is then ended by one 0x60 byte acting as an end-of-data marker. When there is no traffic, the data stream is reduced to the single 0x60 end-of-data byte. In either case, the end-of-data marker is followed by whatever necessary amount of padding bytes: 0x61 bytes for the Moscow and relay variants, 0x00 bytes for the Pyongyang variant. When there is no traffic or after finishing transmitting messages, the Moscow and relay variants go on and keep sending data packets filled with 0x61 padding bytes, until leaving data mode (the Pyongyang variant automatically switches to idle after sending the last data segment, containing the 0x60 end-of-data marker).

Chat packets

Peer
station
Type
/ ARQ
Chat text segment 1200Bd extra text
CE C0 31 72 74 20 6F 6B 20 73 6B 00 00 00 00 00

Chat packets contain text messages sent live from one station operator to the other. The text is encoded using the North Korean KPS 9566 character encoding. 0x00 bytes are used as padding: when text segments do not fill the whole payload, they are followed by 0x00 padding; when the station is in chat mode but there is no message text available to send (the operator has not typed in anything yet, or everything he typed was already transmitted), chat packets full of 0x00 padding are sent.

Message text contains no CR or LF new line characters; "//" is sometimes used as a separator instead. Furthermore, typos and inconsistencies in following message conventions suggest that chat messages are hand-typed by operators, using an IME to enter Korean, and pressing the enter key on the keyboard to send out messages. Routine uses of chat packets include QRU, QRT and sign-off chatter, as well as coordination of modem settings such as power, sensitivity and 600Bd/1200Bd mode toggling. Chat is also occasionally used for scheduling later links, or discussion of any operational issue, which sometimes reveals interesting insights on DPRK-ARQ operations.

Idle packets

Idle packets are traffic packets simply containing filler payload with the command code 0x00. The Moscow and relay variants send these when in idle mode, while the other station is in chat mode. The Pyongyang variant sends these when the station does not have something else to send, for example after finishing sending all the messages in the transmission.

Peer
station
Type
/ ARQ
Code Filler 1200Bd filler
Moscow / Pyongyang variants
A5 0C 00 00 A5 0C 01 01 A5 0C 02 02 A5 0C 03 03
Relay variant
D2 0C 00 00 D2 0C 00 00 D2 0C 00 00 D2 0C 00 00

Command packets

Command packets each contain one command, mainly identified by the command code in the third byte. Command ACK packets correspond to a matching command: in the relay variant, they share the same command code, while in the Moscow variant, the command ACK apparently uses the command code value from its corresponding command, shifted by two bits to the left.

There are many different commands, and each protocol variant uses its own, different set of command codes for them.

Command Packet
type
Example packet Payload
type
Peer
station
Type
/ ARQ
Code Payload 1200Bd padding / filler
Moscow variant
CQ Command AA CF 01 11 77 70 00 00 00 00 00 00 00 00 00 00 Parameters
CQ ACK Command ACK A5 FC 04 04 A5 FC 05 05 A5 FC 06 06 A5 FC 07 07 Filler
Idle mode Command A5 CF 02 00 00 00 00 00 00 00 00 00 00 00 00 00 Empty parameters
Chat mode Command AA CF 03 00 00 00 00 00 00 00 00 00 00 00 00 00 Empty parameters
Chat mode ACK Command ACK A5 FC 0C 0C A5 FC 0D 0D A5 FC 0E 0E A5 FC 0F 0F Filler
Data mode Command AA CF 06 60 00 00 00 00 00 00 00 00 00 00 00 00 Parameters
Data mode response Command A5 CF 07 60 00 00 00 00 00 00 00 00 00 00 00 00 Parameters
End of data Command A5 CF 08 00 00 00 00 00 00 00 00 00 00 00 00 00 Empty parameters
Relay variant
CQ Command D2 CF 21 16 08 50 00 00 00 00 00 00 00 00 00 00 Parameters
CQ ACK Command ACK CE FC 21 21 CE FC 21 21 CE FC 21 21 CE FC 21 21 Filler
Idle mode Command D2 CF 41 00 00 00 00 00 00 00 00 00 00 00 00 00 Empty parameters
Chat mode Command D2 CF 47 00 00 00 00 00 00 00 00 00 00 00 00 00 Empty parameters
Chat mode ACK Command ACK CE FC 47 47 CE FC 47 47 CE FC 47 47 CE FC 47 47 Filler
Data mode Command D2 CF 72 60 00 00 00 00 00 00 00 00 00 00 00 00 Parameters
Data mode response Command CE CF 74 60 00 00 00 00 00 00 00 00 00 00 00 00 Parameters
End of data Command D2 CF 74 00 00 00 00 00 00 00 00 00 00 00 00 00 Empty parameters
Pyongyang variant
CQ Custom C8 01 16 31 80 00 00 00 00 00 00 00 00 00 00 00 Parameters (custom)
CQ ACK Custom D3 41 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 Parameters
Data init 1 Command C8 43 01 01 2C E2 08 00 00 00 00 00 00 00 00 00 Parameters (unknown)
Data init 2 Command C8 43 02 00 00 00 00 00 00 00 00 00 00 00 00 00 Parameters (unknown)
Data start 3 Command C8 43 03 5B F7 00 00 00 00 00 00 00 00 00 00 00 Parameters
Data start 4 Command C8 43 04 98 2F 00 00 00 00 00 00 00 00 00 00 00 Parameters

CQ command parameters

This type of parameters appears in CQ commands of Moscow (code 0x01) and relay (code 0x21) variants. The QSX frequency, on which the peer station is expected to reply, is encoded using basic packed binary-coded decimal, 4 bits per digit (hexadecimal A..F is never used). Frequencies lower than 10 MHz are encoded with a leading zero. The QSX frequency is intended for LSB mode.

Peer
station
Type
/ ARQ
Code QSX
frequency
Padding 1200Bd padding Decode
D2 CF 21 16 08 5 0 00 00 00 00 00 00 00 00 00 00 16085 kHz LSB
A4 CF 01 09 75 5 0 00 00 00 00 00 00 00 00 00 00 9755 kHz LSB

The Pyongyang variant uses a custom packet type for CQ commands, without command code, but using the same encoding for the QSX frequency:

Peer
station
Type
/ ARQ
QSX
frequency
Padding 1200Bd padding Decode
C8 01 16 31 8 0 00 00 00 00 00 00 00 00 00 00 00 16318 kHz LSB

The Pyongyang variant also uses a custom packet type for CQ ACK, which contains as a parameter the modem ID of the station replying to the CQ:

Peer
station
Type
/ ARQ
Code Source
station
Padding 1200Bd padding
D3 41 00 C8 00 00 00 00 00 00 00 00 00 00 00 00

Data mode command parameters

This type of parameters appears in data mode and data mode response commands of Moscow (codes 0x06 and 0x07) and relay (codes 0x72 and 0x74) variants, as well as in data start 3 and 4 commands of the Pyongyang variant (codes 0x03 and 0x04). They contain information about the data stream going to be transmitted.

Peer
station
Type
/ ARQ
Code Transmission
ID
Position Padding 1200Bd padding Decode
AA CF 06 78 4A 00 00 00 00 00 00 00 00 00 00 00 Starting TX "784A"
D2 CF 72 60 00 00 00 00 00 00 00 00 00 00 00 00 Starting QRU TX
C8 43 03 5B F7 4A 01 00 00 00 00 00 00 00 00 00 Resuming TX "5BF7" from 330 bytes
A4 CF 06 60 00 CE 01 00 00 00 00 00 00 00 00 00 Resuming QRU TX from 462 bytes

The transmission ID is a random-looking binary value. In the Pyongyang variant, it also appears in the transmission header at the beginning, inside of the data stream. It identifies that data payload: it remains the same in every data mode command resuming the same data stream on a given side of the link, however each station on the link uses a different transmission ID. When there is no traffic and the transmission is reduced to the single 0x60 end-of-data marker, it is identified by transmission ID "60 00".

The position field is a little-endian number of bytes which represents the point in the data stream from which the transmission is starting or resumed. It is 0 when the transmission is starting; when resumed, the value in the field is lower than the actual resuming position, by a small offset (apparently 6 bytes). If data mode is resumed after one side already reached the end of the stream, the further padding bytes are still counted towards the position field.

Flow control

Flow control is an area where the Pyongyang variant of the protocol departs majorly from the Moscow and relay variants. The Moscow and relay variants are based on traffic modes, flow state and command packets to manage it and transition between them - the Pyongyang variant is radically different.

In the Moscow and relay variants, when the link is established, each station is in a given traffic mode: data, chat or idle. While in a mode, stations send only traffic packets of the corresponding type, continuously; or command packets to transition out of that mode. Both stations enter, leave and are in data mode at the same time, exchanging transmission data contents in at the same time in full duplex. Chat and idle modes are always paired: when one station is in chat mode - and may send text messages to the other one, the other station is always in idle mode, listening without replying. The only reasons a station enters idle mode is either as a response to the other station entering chat mode, or when switching from chat to idle mode to hand off chat mode to the other station so it can reply. Either station can interrupt data mode at any time and switch the link to chat/idle mode. Chat/idle mode is also used as a default state after the link is established and before the data transmission is started; and also after the data transmission is ended, to exchange sign-off chatter before shutting down the link.

The mode transitions are codified in the protocol, and some commands always receive a given other command as a reply from the other station.

Command Destination mode Customary response
CQ - CQ ACK
CQ ACK - Chat mode
Idle mode Idle Chat mode
Chat mode Chat Chat mode ACK
Chat mode ACK Idle -
Data mode Data Data mode response
Data mode response Data -
End of data - Chat mode

For example, the sequence of commands CQ - CQ ACK - chat mode - chat mode ACK is always followed, going back and forth between the two stations, when establishing the link; and the sequence end of data - chat mode - chat mode ACK always followed after the data transmission is finished on both sides.

The Pyongyang variant is drastically different from this. There is no notion of mode or state, and most commands used to transition between them by other variants are inexistant in this one. Chat and idle are not paired, and each station can send chat packets at any time without interrupting the data transmission. Stations simply send idle packets whenever they are not sending something else: after the link is established and before data transmission starts, and also after the transmission reached the end of the data stream - at this point, contrary to the other variants, a station isn't bound to data mode having to send packets filled with 0x61 padding bytes while the other station is still transmitting data: instead it automatically switches to idle right away, without any command packet.

The most flow control in the Pyongyang variant is a sequence of commands when starting the data transmission. This sequence is believed to involve data init 1 or 2 commands (codes 0x01 or 0x02), followed by one of data start 3 or 4 commands (code 0x03 or 0x04). The station then starts sending data packets (if there is no traffic, it sends a single packet containing the 0x60 end-of-data marker). After reaching the end of the data stream (if any) and sending the last data segment, containing the 0x60 end-of-data marker, the station sends no further padding data packets and starts sending idle packets right away.

Link establishment

The link is first established when the calling station starts sending CQ commands for the other station, on a scheduled time and frequency. The other station, once it's up, ready, listening for and receiving the CQ commands, replies with CQ ACK packets. Once the calling station receives these packets back, the link is established. If propagation conditions are poor, this may take several attempts on different frequencies.

Conversely, when properly shutting down a link, one station sends as its last packet a special, invalid burst starting with the normal reversal bits, but containing only 0 bits, as many as a normal packet would; and then powers down. The other station on the link doesn't automatically power down, it usually keeps sending a few packets before being turned off.

When one station has lost reception of the other one, because link quality degraded too badly or the other station stopped transmitting, it omits sending every sixth packet, causing a noticeable skip in the signal bursts. This presumably serves as a feedback signal to the unhearable station. This condition may get reversed and cleared by itself if signal quality and reception are restored - the station then stops skipping packets; it also often happens in the context of switching link frequencies.

Contrary to power and sensitivity modem settings, which can be adjusted on the fly, toggling between 600Bd and 1200Bd or changing link frequencies (due to poor or degrading propagation conditions for example) require restarting the link: the calling station sends a shutdown burst and powers down, then after a few seconds restarts from the CQ stage, indicating a new QSX frequency, or transmitting from a different frequency, or using the other baud rate.

See also the conventions page for more information around the protocol concerning link establishment, frequencies and modem settings.