For additional protection, the header is encoded using a [12,8] Hamming code, which can reliably correct single-bit errors and detect double-bit errors in every block of eight bits.
The IP packets transferred by Hamnet70 may contain long sequences of identical bytes (think of the zeros in the middle of IPv6 addresses), which make it hard to keep the system synchronized. To prevent the transmission of many identical symbols in a row, the data is whitened using a pseudo-random sequence.
Here, a 9-bit linear feedback shift register (LFSR) according to the CCITT specification is used to generate the pseudo-random sequence. The generator polynomial is stem:[x^9 + x^5 + 1]. The data is whitened by XORing data bytes with the _whitening key_ generated from the LFSR.
The whitening key is generated by taking the LSB of the LFSR state, and shifting it into an 8-bit register from the right. Then the LFSR is advanced and the process is repeated. Every 8 repetitions the contents of the 8-bit register are XORed with a data byte to calculate the whitened data.
To remove the whitening, the same procedure is applied to the whitened data at the receiver side. XORing with the same sequence results in the original data.
Whitening is only applied to the layer 2 packet data, but not the PHY header.
The first data symbol follows directly after the last symbol of the PHY header. The data is encoded and modulated using the scheme defined in the PHY header’s MODCOD field. The number of symbols resulting from the encoding and modulation process is stored in the PHY header as well.
. One or more packets as defined in <<phy_packet_format>>
. Ramp-down sequence
The ramp-up, ramp-down and idle sequences consist of alternating +1/-1 BPSK symbols.
During ramp-up, their amplitude stem:[A_u(k)] is scaled up across stem:[L_u] symbols, following the curve stem:[A_u(k) = sin(π/2 * k / L_u)]. Ramp-down follows a similar sinusoidal for stem:[L_d] symbols: stem:[A_d(k) = cos(π/2 * k / L_d)]. The purpose of these sequences is to avoid splatter while turning on and off the transmitted signal.
During the pre-packet idle sequence, the alternating BPSK symbols are continued with constant amplitude 1.0. This sequence may help synchronizers acquire the signal better (especially the gain and timing regulation can benefit), but is not needed if they are fast enough. If and how this part is used is still to be determined.
Each packet in a burst includes a preamble. Packets are directly concatenated, i.e. after the last data symbol follows the first preamble symbol.
This system uses Root Raised Cosine (RRC) filters with a roll-off factor of stem:[alpha=0.2]. Therefore the bandwidth is 1.2 times the symbol rate.
The filter is applied to the whole symbol sequence of the burst. The same filter must be applied at the receiver to minimize inter-symbol interference.
The Hamnet70 link layer is designed to ensure reliable communication between a central station (digipeater) and several clients, while making efficient use of the available airtime. To accomplish this, it uses several technologies, including variable-length addressing and automatic repetition of packets that could not be decoded.
Node addresses use the https://github.com/arngll/arnce-spec/blob/main/n6drc-arnce.md#introduction[HAM-64 address format]. This format allows to encode callsigns of up to 12 characters in a number of 16, 32, 48 or 64 bits. Additionally, it allows to replace the full version of an address with a temporary short address with only 16 bits that is used during a connection. Multicast and broadcast addresses are also specified.
=== Link Layer Header
Each layer 2 packet contains a header that identifies how the message should be interpreted. It is of variable length and composed as follows:
[cols="2,1,5", options="header"]
.Link layer header layout
|===
| Field | Length | Description
| Message type
| 3 bit
| The type of the message. See below for a list of values.
| TX request
| 1 bit
| After this message, the burst ends and the destination may transmit.
| Source address length
| 2 bit
| Length of the source address.
| Destination address length
| 2 bit
| Length of the destination address.
| TX sequence number
| 4 bit
| Sequence number of the currently transmitted packet.
| RX sequence number
| 4 bit
| Sequence number of the packet expected next.
| Source address
| 16, 32, 48 or 64 bit
| HAM-64 address identifying the sending station.
| Destination address length
| 16, 32, 48 or 64 bit
| HAM-64 address identifying the target station.
|===
The total Link Layer Header length is therefore at least 6 byte and at most 18 byte.
Lost packets are automatically repeated in Hamnet70. As the system is also designed for high throughput, it uses the Go-Back-N algorithm to handle this. The algorithm is described in this section.
Both the digipeater and the client send two sequence numbers with each packet.
The _TX sequence number_ is the number of the current packet. It uniquely identifies that packet at the time it is transmitted. The _TX sequence number_ is incremented (with overflow) with each new packet that is sent.
The _RX sequence number_ is the packet number the sending station expects to see next from the other side. It is incremented when a packet with this expected sequence number is decoded successfully. Received packets with other sequence numbers than the expected one must be dropped.
Example: The two stations A and B just connected and expect to see sequence number 0 from each other. Station A transmits a burst with three packets: P0, P1, P2. Station B decodes packet P0 and increases the expected number to 1. P1 is not decoded due to noise and therefore lost. P2 is again decoded, but is dropped because its sequence number is 2 and not the expected 1. In its transmission cycle, station B tells station A that it expects P1 next. Station A therefore _goes back to_ P1 in its transmission queue and starts transmitting all packets after P1 again.
As the sequence numbers in Hamnet70 have 4 bits, up to 15 packets can be transmitted in a burst before the numbers become ambiguous.
Due to the long possible bursts, this system can achieve high throughput if there is low packet loss. However, it can also become very slow if many packets are lost because all packets after the first error have to be repeated. Therefore it might be a good idea to adjust the burst length depending on the packet loss and send smaller bursts if only few packets go through.
Connection Management Frames control the Layer 2 connection between a client and the digipeater.
They are especially important for connect and disconnect procedures.
Connection Management Frames have at least one byte in the data field: the type of the management packet.
The following types are defined:
[cols="1,2,5", options="header"]
.Connection Management Types
|===
|Type Indicator
|Sent by
|Description
|`0x00`
|Digipeater
|Beacon
|`0x01`
|Client
|Connection Request
|`0x02`
|Digipeater
|Connection Parameters
|`0x03`
|Digipeater
|Connection Reset
|`0x04`
|Digipeater
|Disconnect Request
|`0x05`
|Client
|Disconnect
|===
===== Beacons
Beacons are sent periodically by the digipeater to show it’s presence to potential new clients.
The layer 2 header is filled as follows:
- Message Type: `001` (Connection Management)
- TX Request: `1`
- Source Address: the digipeater’s HAM-64 address
- Destination Address: the HAM-64 broadcast address
- TX sequence number: reserved, always 0
- RX sequence number: reserved, always 0
The message contains exactly 1 data byte: `0x00` to indicate that this is a Beacon packet.
A Beacon packet shall always be sent as the last or only packet in a burst.
After a Beacon is sent by the digipeater it listens for a short time for Connection Requests from new clients.
A new client that intends to connect shall send the Connection Request as soon as possible after the beacon transmission ends.
===== Connection Request
A Connection Request is sent by a client that intends to connect to a digipeater.
The layer 2 header is filled as follows:
- Message Type: `001` (Connection Management)
- TX Request: `1`
- Source Address: the new client’s HAM-64 address
- Destination Address: the digipeater’s HAM-64 address
- TX sequence number: reserved, always 0
- RX sequence number: reserved, always 0
The message contains exactly 1 data byte: `0x01` to indicate that this is a Connection Request packet.
A Connection Request is always a response to a Beacon packet.
It shall be the only packet in a burst.
When the digipeater receives a Connection Request it has two options for a response:
. Accept the connection by sending a Connection Parameters packet to the client in the next burst.
. Reject the connection by sending a Connection Reset packet to the client in the next burst.
===== Connection Parameters
The Connection Parameters packet has two functions: it indicates to a client that its Connection Request was accepted and tells it how to configure its network stack.
This is the first packet in the regular Go-back-N data flow.
The layer 2 header is filled as follows:
- Message Type: `001` (Connection Management)
- TX Request: `1`
- Source Address: the digipeater’s HAM-64 address
- Destination Address: the new client’s HAM-64 address
- TX sequence number: 0 (the first packet)
- RX sequence number: 0 (no packets received yet)
The type indicator is `0x02`.
After the type indicator follow one or more configuration blocks.
Each block consists of three data fields:
. Configuration Type: 1 byte
. Configuration Data Length: 1 byte
. Configuration data: variable number of bytes as indicated by Configuration Data Length
The following Configuration Types are defined:
[cols="1,1,5", options="header"]
.Configuration Types
|===
|Type Indicator
|Length
|Description
|`0x00`
|16 Byte
|IPv6 address
|`0x01`
|16 Byte
|IPv6 gateway
|`0x02`
|16 Byte
|IPv6 DNS server (may appear multiple times)
|`0x03` - `0x07`
|-
|_reserved_
|`0x08`
|4 Byte
|IPv4 address
|`0x09`
|4 Byte
|IPv4 gateway
|`0x0A`
|4 Byte
|IPv4 DNS server (may appear multiple times)
|`0x0B` - `0xFF`
|-
|_reserved_
|===
If the client receives an unknown Configuration Type the corresponding block shall be skipped.