F06 is based on a proprietary synchronous BFSK mode. Its standard configuration is speed of 200 bd, shift of 1000 Hz, space (0) frequency at -500 Hz, and mark (1) frequency at +500 Hz. The binary fields of its protocol use big-endian bit and byte orders.
All the data of the BFSK transmission is split and packed into consecutive ordered 288-bit blocks of the following fixed structure: (hexadecimal/binary representations)
|Sync sequence||Block index with ECC||Interleaved payload with ECC|
|11-bit raw block index||5-bit ECC data||Interleaved 144-bit raw payload with CRC||Interleaved 96-bit ECC data|
The payload is composed of 4 pieces, each separately encoded with ECC and containing 36 bits of raw original data followed by 24 bits of corresponding ECC data (the ECC algorithm is not known). These 4 pieces are interleaved together (a common FEC practice), 4 bits at a time, in the following manner:
|Raw original data, 36 bits/piece||ECC data, 24 bits/piece|
The deinterleaved 144-bit payload then actually contains, at the end, a 16-bit CRC of the previous 128-bit data. The CRC algorithm is the standard CRC-16-CCITT. This can be used to check and reject corrupted block payloads.
|Deinterleaved 144-bit payload with CRC|
|128-bit block payload||16-bit CRC|
There are two types of block, and the interpretation of the payload of a block depends on its type.
The blocks with indices divisible by 16, including zero (#0, #16, #32, #48, #64, #80, ...) are metadata blocks. They are sent at regular intervals through the broadcast and report information on the numbers of blocks and messages contained in the broadcast, and the position where, in which block, to find the start of each message. The 128-bit metadata payload is spread out over eight 16-bit groups, as follows:
|Block and message counts||Position of message 1||Position of message 2||Position of message 3||Positions of messages 4, 5 and 6...||Position of message 7|
|11-bit block count||5-bit message count||11-bit start block index||5 bits, unused, always 0||11-bit start block index||5 bits, unused, always 0||11-bit start block index||5 bits, unused, always 0||11-bit start block index||5 bits, unused, always 0|
For example, this broadcast contains 67 blocks, on which 2 messages are mapped: the first message starts with block #1, and the second message starts with block #22.
This provides for up to seven messages in a broadcast. Most of the time there is only one or maybe two messages in the broadcast, and the remaining, unused message fields are simply set to 0. A block is never shared between two messages; messages always start with the beginning of a block. In practice, the position of the first message always equals 1. The block count includes block #0.
Message blocks are blocks whose indices, unlike metadata blocks, are not divisible by 16. Each of them is part of one of the possibly several messages in the broadcast. A message can use one of two known encodings for the payload of its blocks:
- Raw binary - the 128 bits or 16 bytes of the payload are simply taken as they are and put together to form a binary message, left to further interpretation. This is used for usual test transmissions, and for rare broadcasts such as F06a.
- A custom encoding used for normal messages based on typical 5-figure groups, mapping binary to decimal digits. 10-bit pieces of the payload are mapped to 3 digits each. A 10-bit value can range from 0 to 1023 (210-1), and is mapped to a 3-digit string ranging from 000 to 999, with simplicity, efficiency and very little wasted entropy. 4-digit 10-bit values from 1000 to 1023 are believed to be invalid, and should not be encountered during decoding. The first 120 bits of the 128-bit payload are encoded through these 10-bit pieces. The remaining 8 bits at the end are divided into two 4-bit pieces. In a similar way, a 4-bit value can range from 0 to 15 (24-1), and is mapped to a single digit from 0 to 9, while values from 10 to 15 are unused.
|Bits 1-10||Bits 11-20||Bits 21-30||Bits 31-40||...||Bits 101-110||Bits 111-120||Bits 121-124||Bits 125-128|
The decoded payload yields 12 successive 3-digit strings, and 2 extra digits at the end, for a total of 38 digits per block. These digits can be used to reconstitute 5-figure groups only after being all put together from the different blocks into the whole message, as 5-figure group boundaries are not aligned with block boundaries, and a 5-figure group is often split across two successive blocks.
A separator block contains the normal 32-bit synchronization constant 0x7d12b0e6 followed by 256 zero bits. It is not a valid block, and trying to decode it will result in a block #0 with an incorrect payload CRC, which should be rejected as corrupted. Although its purpose may seem intuitive, it is not known which actual technical constraints, if any, it is supposed to satisfy.
The broadcasts consist of all the blocks in index order, followed by a separator block, repeated over and over for 6 to 8 minutes. Decoding a message comes down to the following steps:
- Decoding a metadata block to know the number of message blocks to recover and map each message with an ordered list of message block. Any metadata block whose integrity was verified will do.
- Decoding message blocks to obtain a copy, whose integrity was verified, of the payload of each message block. They don't have to be received or processed in order, and can be taken from any repeated portion of the broadcast; corrupted or already-received blocks can be ignored, until all blocks were decoded.
- For each message in the broadcast, checking the payload of its first block to determine the payload encoding of this message. (In practice, no instance has been observed of multiple messages using different payload encoding methods inside a single broadcast.)
- Decoding the payload of every block part of each message. Each payload must be decoded separately, block by block, not as a whole.
- Putting the decoded payloads back together, in block index order, to reconstitute the messages.