= Digital Voice Modem

== Technical Note
=== Modem Protocol

Document Identifier: TN.1001

Author: Bryan Biedenkapp, N2PLL

Editors: Bryan Biedenkapp, N2PLL

Contributors: N/A

Abstract: Describes high-level concepts and procedures for the Modem Protocol.

Status: Draft

== 1. Introduction
This document describes, in high-level, the general concepts and procedures for the Modem Protocol used by DVM projects.

== 2. Technical Note

=== 2.1 Definitions
* DVM: Digital Voice Modem

=== 2.2 General Concept
The DVM Modem Protocol defines a common and standard communications protocol between a host application and a dedicated modem hardware device (usually based around a STM32F446 or similar).

The core purpose of the protocol is to provide a common serial communications between the host application and the dedicated modem hardware.

=== 2.3 Modem Packet Framing
The modem protocol implements a very simplistic framing mechanism for transmitting data between the host and modem (and vice versa).

[cols="2,1,3"]
|===
|Frame Type |Opcode |Description

|Short
|$FE
|This frame type is used for transporting packets of 254 bytes or less in length.

|Long
|$FD
|This frame type is used for transporting packets greater than 254 bytes in length.
|=== 

[discrete]
==== Modem Packet - Short Frame
[listing]
    Byte 0               1               2               3
    Bit  7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        | Frame Type  | Length          | Opcode        | ...           |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        | <Variable Length Data>                                        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2 bytes (not including data length)

[discrete]
==== Modem Packet - Long Frame
[listing]
    Byte 0               1               2               3
    Bit  7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        | Frame Type  | Length                          | Opcode        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        | <Variable Length Data>                                        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    3 bytes (not including data length)

It is important to note the Length parameter of the packet buffer should be the length of the *entire* packet not just the payload.

==== 2.3.1 Modem Opcodes
The opcode defines which operation/command being transmitted.

[cols="2,1,3"]
|===
|Function Name |Opcode |Description

|Get Version
|$00
|This function is used for retrieving the firmware version from the modem.

|Get Status
|$01
|This function is used for retrieving the current status from the modem.

|Set Configuration
|$02
|This function is used for setting configuration parameters to the modem.

|Set Mode
|$03
|This function is used for setting the operational mode parameter to the modem.

|Set Symbol Level Adjustment
|$04
|This function is used for setting the symbol level adjustment parameters to the modem.

|Set Rx Level Adjustment
|$05
|This function is used for setting the receive level adjustment parameter to the modem.

|Set RF Parameters
|$06
|This function is used for setting the RF parameters to the modem. (Hotspot Only)

|Calibration Data
|$08
|This function is used for setting calibration data to the modem when operating in a calibration mode.

|RSSI Data
|$08
|This function is used for receiving RSSI data from the modem.

|Send CW ID
|$0A
|This function is used to cause the modem to emit a CWID burst of morse code.

|Set FIFO Buffers
|$0F
|This function is used for setting the internal FIFO ringbuffer sizes on the modem.

|DMR Slot 1 Data
|$18
|This function is used for sending/receiving DMR Slot 1 protocol data to/from the modem.

|DMR Slot 1 Lost
|$19
|This function is used for signalling loss of synchronization for DMR Slot 1 protocol data.

|DMR Slot 2 Data
|$1A
|This function is used for sending/receiving DMR Slot 2 protocol data to/from the modem.

|DMR Slot 2 Lost
|$1B
|This function is used for signalling loss of synchronization for DMR Slot 2 protocol data.

|DMR Short LC
|$1C
|This function is used for sending/receiving DMR Short LC protocol data to/from the modem.

|DMR Start
|$1D
|This function is used for providing transmitter control and starting the DMR data stream.

|DMR Abort
|$1E
|

|DMR CACH AT Control
|$1F
|This function is used for setting the DMR CACH AT bit on or off.

|DMR Slot 1 Clear
|$20
|This function is used for commanding the modem to clear the DMR Slot 1 FIFO buffers.

|DMR Slot 2 Clear
|$21
|This function is used for commanding the modem to clear the DMR Slot 2 FIFO buffers.

|Project 25 Data
|$31
|This function is used for sending/receiving Project 25 protocol data to/from the modem.

|Project 25 Lost
|$32
|This function is used for signalling loss of synchronization for Project 25 protocol data.

|Project 25 Clear
|$33
|This function is used for commanding the modem to clear the Project 25 FIFO buffers.

|NXDN Data
|$41
|This function is used for sending/receiving NXDN protocol data to/from the modem.

|NXDN Lost
|$42
|This function is used for signalling loss of synchronization for NXDN protocol data.

|NXDN Clear
|$43
|This function is used for commanding the modem to clear the NXDN FIFO buffers.

|Ack
|$70
|This function is used for acknowledging a command.

|Nack
|$7F
|This function is used for negative acknowledgment of a command.

|Flash Read
|$E0
|This function is used for reading 256 bytes of data from the flash storage partition of the modem. (Only on supported hardware.)

|Flash Write
|$E1
|This function is used for writing 256 bytes of data to the flash storage partition of the modem. (Only on supported hardware.)

|Reboot MCU
|$EA
|This function is used for triggering a reboot of the modem MCU.

|Debug 1
|$F1
|This function is used for receiving debug data from the modem. (1 byte)

|Debug 2
|$F2
|This function is used for receiving debug data from the modem. (2 byte)

|Debug 3
|$F3
|This function is used for receiving debug data from the modem. (3 byte)

|Debug 4
|$F4
|This function is used for receiving debug data from the modem. (4 byte)

|Debug 5
|$F5
|This function is used for receiving debug data from the modem. (5 byte)

|=== 

==== 2.3.2 Modem Operational States
The operational state defines which mode/state the modem is currently in.

[cols="2,1,3"]
|===
|State Name |State |Description

|IDLE
|0
|This is the default state for a modem, the modem is not in any active mode in this state.

|DMR
|1
|When in this mode the modem is actively Rx/Tx DMR protocol data.

|Project 25
|2
|When in this mode the modem is actively Rx/Tx Project 25 protocol data.

|NXDN
|3
|When in this mode the modem is actively Rx/Tx NXDN protocol data.

|CW
|10
|When in this mode the modem is actively Tx CWID morse data.

|Project 25 Calibration 1K
|92
|

|DMR DMO Calibration 1K
|93
|

|DMR Calibration 1K
|94
|

|DMR Low Frequency Calibration
|95
|

|RSSI Calibration
|96
|

|Project 25 Calibration
|97
|

|DMR Calibration
|98
|

|NXDN Calibration
|99
|
|=== 

==== 2.3.3 Negative Acknowledgement Reasons
This table defines the reasons a negative acknowledgement may be sent.

[cols="2,1,3"]
|===
|Reason Name |Reason Code |Description

|OK
|0
|

|NAK
|1
|General Failure.

|Illegal Length
|2
|Packet received was of an illegal length, and was discarded by the modem.

|Invalid Request
|4
|Packet received was an invalid request, and was discarded by the modem.

|Ringbuffer Full
|8
|Sent when a command attempts to write to a FIFO buffer that is full.

|Invalid FDMA Preamble
|10
|Sent by the Set Configuration command typically, to indicate the FDMA preamble value was out of range.

|Invalid Mode
|11
|Sent by either Set Configuration or Set Mode command to indicate a mode was specified that is invalid.

|Invalid DMR Color Code
|12
|Sent by the Set Configuration command typically, if the DMR color code is out of range.

|Invalid DMR Slot
|13
|Sent by the modem to indicate the DMR slot value was out of range.

|Invalid DMR Start
|14
|

|Invalid DMR Rx Delay
|15
|Sent by the modem to indicate the DMR Rx Delay value was out of range.

|Invalid P25 Correlation Count
|16
|Sent by the modem to indicate the P25 Correlation Count value was out of range.

|No Internal Flash
|20
|Sent by the modem when the hardware does not support the Flash Read or Flash Write operations.

|Flash Erase Failed
|21
|Sent by the modem when the configuration partition of the flash was unable to be erased.

|Flash Write Failed
|22
|Sent by the modem when the configuration partition of the flash was unable to be written.

|Flash Write Too Big
|23
|Sent by the modem when the data sent to be written to the configuration partition of the flash was too large to be written.

|DMR Disabled
|63
|Sent by the modem to indicate DMR operations are disabled.

|P25 Disabled
|64
|Sent by the modem to indicate P25 operations are disabled.

|NXDN Disabled
|65
|Sent by the modem to indicate NXDN operations are disabled.

|=== 

=== 2.4 General Opcode Specifications

==== 2.4.1 Get Version
This opcode is utilized to retreive the hardcoded (at compile time) version string from the firmware.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|3
|Length

|Get Version Opcode
|1
|
|=== 

Upon reception, the modem shall transmit in response:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|3
|Length

|Get Version Opcode
|1
|$00

|Protocol Version
|1
|

|CPU Type
|1
|

|CPU UDID
|16
|Universal Device Identifier

|Baked Firmware Version String
|83
|
|=== 

==== 2.4.2 Get Status
This opcode is utilized to retreive the various interesting operational runtime values from the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|3
|Length

|Get Status Opcode
|1
|$01
|=== 

Upon reception, the modem shall transmit in response:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|3
|Length

|Get Status Opcode
|1
|$01

|Protocol Enablement Flags
|1
|This byte contains flags that indicate which digital protocol is enabled on the modem.

|Modem State
|1
|Current operational state.

|Operation Flags
|1
|This byte contains various operation flags.

|Reserved
|1
|

|DMR Slot 1 FIFO Space
|1
|This byte contains the FIFO space available in DMR frames.

|DMR Slot 2 FIFO Space
|1
|This byte contains the FIFO space available in DMR frames.

|Reserved
|1
|

|Project 25 FIFO Space
|1
|This byte contains the FIFO space available in P25 LDU frames.

|NXDN FIFO Space
|1
|This byte contains the FIFO space available in NXDN frames.

|=== 

==== 2.4.3 Set Configuration
This opcode is utilized to set the general configuration of the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|24
|Length

|Set Configuration Opcode
|1
|$02

|Flags 1 Byte
|1
|This flags byte represents various states (see below).

|Flags 2 Byte
|1
|This flags byte represents various states (see below).

|FDMA Preamble Length
|1
|

|Initial Mode
|1
|This sets the initial mode of the modem, the mode can be changed with Set Mode at any time.

|Rx Level
|1
|

|CW ID Tx Level
|1
|

|DMR Color Code
|1
|

|DMR Rx Delay
|1
|

|P25 NAC
|2
|

|DMR Tx Level
|1
|

|P25 Correlation Count
|1
|

|P25 Tx Level
|1
|

|Tx DC Offset
|1
|

|Rx DC Offset
|1
|

|NXDN Tx Level
|1
|

|Rx Coarse Softpot Setting
|1
|This currently only applies to DVMV1 modems.

|Rx Fine Softpot Setting
|1
|This currently only applies to DVMV1 modems.

|Tx Coarse Softpot Setting
|1
|This currently only applies to DVMV1 modems.

|Tx Fine Softpot Setting
|1
|This currently only applies to DVMV1 modems.

|RSSI Coarse Softpot Setting
|1
|This currently only applies to DVMV1 modems.

|RSSI Fine Softpot Setting
|1
|This currently only applies to DVMV1 modems.
|=== 

[discrete]
==== Flags 1 Byte
[cols="2,1,2"]
|===
|Name |Flag Bit |Description

|Rx Invert
|$01
|

|Tx Invert
|$02
|

|PTT Invert
|$04
|

|Modem Debug
|$10
|

|Simplex Operation
|$80
|
|=== 

[discrete]
==== Flags 2 Byte
[cols="2,1,2"]
|===
|Name |Flag Bit |Description

|DC Blocker
|$01
|

|COS Lockout
|$04
|

|DMR Enabled
|$02
|

|P25 Enabled
|$08
|

|NXDN Enabled
|$10
|
|=== 

Upon reception, the modem shall perform whatever operations necessary to transition to the requested mode and transmit a ACK or NACK in response.

If the operation fails the modem shall:
* Respond with a NACK and the "Illegal Length" if packet from the host is improperly sized.
* Respond with a NACK and the "Invalid FDMA Preamble" if the FDMA preamble parameter is out of range.
* Respond with a NACK and the "Invalid DMR Color Code" if the DMR color code is out of range.
* Respond with a NACK and the "Invalid DMR Rx Delay" if the DMR receive delay is out of range.
* Respond with a NACK and the "Invalid P25 Correlation Count" if the P25 correlation count is out of range.

==== 2.4.4 Set Mode
This opcode is utilized to set the operational mode of the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|4
|Length

|Set Mode Opcode
|1
|$03

|Operational Mode
|1
|$00
|=== 

Upon reception, the modem shall perform whatever operations necessary to transition to the requested mode and transmit a ACK or NACK in response.

==== 2.4.5 Set Symbol Level Adjustment
This opcode is utilized to set the symbol level adjustments on the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|9
|Length

|Set Symbol Level Adjustment Opcode
|1
|$04

|DMR +3/-3 Symbol Level Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|DMR +1/-1 Symbol Level Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|P25 +3/-3 Symbol Level Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|P25 +1/-1 Symbol Level Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|NXDN +3/-3 Symbol Level Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|NXDN +1/-1 Symbol Level Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.
|=== 

Upon reception, the modem shall perform whatever operations necessary to set the Rx level and transmit a ACK or NACK in response.

If the operation fails the modem shall:
* Respond with a NACK and the "Illegal Length" if packet from the host is improperly sized.
* Respond with a NACK and the "Invalid Request" if parameters are out of range.

==== 2.4.6 Set Rx Level Adjustment
This opcode is utilized to set the Rx level on the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|4
|Length

|Set Rx Level Opcode
|1
|$05

|Rx Level
|1
|
|=== 

Upon reception, the modem shall perform whatever operations necessary to set the Rx level and transmit a ACK or NACK in response.

If the operation fails the modem shall:
* Respond with a NACK and the "Illegal Length" if packet from the host is improperly sized.

==== 2.4.7 Set RF Parameters (Hotspot Only)
This opcode is utilized to set the RF parameters for a hotspot modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|18 or 22
|Length of 18 does not set AFC parameters, length of 22 sets AFC parameters.

|Set RF Parameters Opcode
|1
|$06

|Rx Frequency (in Hz)
|4
|

|Tx Frequency (in Hz)
|4
|

|Tx Power (value from 0 to 255)
|1
|

|DMR Discriminator Bandwidth Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|P25 Discriminator Bandwidth Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|DMR Post Demodulation Bandwidth Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|P25 Post Demodulation Bandwidth Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|AFC Gain Mode
|1
|This represents the AFC gain mode: 0 = Auto, 1 = Auto (Linear), 2 = Low, 3 = High.

|NXDN Discriminator Bandwidth Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|NXDN Post Demodulation Bandwidth Adjustment
|1
|This is a unsigned value of 0 to 255 representing an adjustment of -128 to 128.

|AFC Enable, KI and KP
|1
|This value represents whether or not AFC is enabled ($80 bit), the AFC KI (lower 4 bits), the AFC KP (upper 4 bits).

|AFC Range
|1
|

|=== 

Upon reception, the modem shall perform whatever operations necessary to set the RF parameters and transmit a ACK or NACK in response.

If the operation fails the modem shall:
* Respond with a NACK and the "Illegal Length" if packet from the host is improperly sized.
* Respond with a NACK and the "Invalid Request" if parameters are out of range.

==== 2.4.8 Calibration Data
*TODO TODO TODO*

==== 2.4.9 RSSI Data
*TODO TODO TODO*

==== 2.4.10 Send CWID
This opcode is utilized to transmit a CW ID morse message from the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|4 or More
|Length, the length is typically 3 + the length of the CWID to send.

|Send CWID Opcode
|1
|$0A

|...
|...
|...

|CWID Letters
|1
|

|...
|...
|...
|=== 

Upon reception, the modem shall perform whatever operations necessary to transmit a CWID with the given letters and transmit a ACK or NACK in response.

If the operation fails the modem shall:
* Respond with a NACK and the "Illegal Length" if packet from the host is improperly sized.

==== 2.4.11 Set FIFO Buffers
This opcode is utilized to set the size of the FIFO buffers on the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|6
|Length

|Set FIFO Buffers Opcode
|1
|$0F

|DMR Buffer Size
|2
|This is a unsigned 16-bit value representing the FIFO buffer size.

|P25 Buffer Size
|2
|This is a unsigned 16-bit value representing the FIFO buffer size.

|NXDN Buffer Size
|2
|This is a unsigned 16-bit value representing the FIFO buffer size.
|=== 

Upon reception, the modem shall perform whatever operations necessary to resize the FIFO buffers and transmit a ACK or NACK in response.

If the operation fails the modem shall:
* Respond with a NACK and the "Illegal Length" if packet from the host is improperly sized.
* Respond with a NACK and the "Invalid Mode" if buffers are attempted to be resized while not in an IDLE state.

==== 2.4.12 Acknowledgement
This opcode is utilized by the modem to notify the host of a positive acknowledgement of a command.

The modem shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|4
|Length

|Ack Opcode
|1
|$70

|Opcode Being Acknowledged
|1
|$00
|=== 

==== 2.4.13 Negative Acknowledgement
This opcode is utilized by the modem to notify the host of a negative acknowledgement of a command.

The modem shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|5
|Length

|Nack Opcode
|1
|$7F

|Opcode Being Acknowledged
|1
|$00

|NACK Reason Code
|1
|$00
|=== 

==== 2.4.14 Flash Read
This opcode is utilized to read data from the modem's configuration partition on the flash.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|3
|Length

|Flash Read Opcode
|1
|$E0
|=== 

The modem shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|249
|Length

|Flash Read Opcode
|1
|$E0

|Variable Length Data
|249
|...
|=== 

==== 2.4.15 Flash Write
This opcode is utilized to write data from the modem's configuration partition on the flash.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|254
|Length

|Flash Write Opcode
|1
|$E1

|Flash Data
|<Variable>
|...
|=== 

Upon reception, the modem shall perform whatever operations necessary to write data to the flash and transmit a ACK or NACK in response.

If the flash operation fails the modem shall:
* Respond with a NACK and the "Flash Write Too Big" if more then 254 bytes are attempted to be written.
* Respond with a NACK and the "Flash Write Failed" if a write error occurs.

==== 2.4.16 Reset MCU
This opcode is utilized to reboot the MCU of the modem.

The host shall transmit:
[cols="2,1,2"]
|===
|Name |Length (bytes) |Description

|Short Frame Start
|1
|Short Frame Start

|Length
|3
|Length

|Reset MCU Opcode
|1
|$EA
|=== 

Upon reception of this opcode the modem should immediately issue a MCU restart. No response back from the modem shall be expected.

=== 2.5 DMR Opcode Specifications

==== 2.5.1 Slot 1 Data
*TODO TODO TODO*

==== 2.5.2 Slot 2 Lost
*TODO TODO TODO*

==== 2.5.3 Slot 2 Data
*TODO TODO TODO*

==== 2.5.4 Slot 2 Lost
*TODO TODO TODO*

==== 2.5.5 Short LC
*TODO TODO TODO*

==== 2.5.6 Start
*TODO TODO TODO*

==== 2.5.7 Abort
*TODO TODO TODO*

==== 2.5.8 CACH AT Control
*TODO TODO TODO*

==== 2.5.9 Slot 1 Clear
*TODO TODO TODO*

==== 2.5.10 Slot 2 Clear
*TODO TODO TODO*

=== 2.6 P25 Opcode Specifications

==== 2.6.1 Data
*TODO TODO TODO*

==== 2.6.2 Lost
*TODO TODO TODO*

==== 2.6.3 Clear
*TODO TODO TODO*

=== 2.7 NXDN Opcode Specifications

==== 2.7.1 Data
*TODO TODO TODO*

==== 2.7.2 Lost
*TODO TODO TODO*

==== 2.7.3 Clear
*TODO TODO TODO*
