first add of anytone778 notes
[wikirepo] / projects / anytone778uv_serial / index.mdwn
diff --git a/projects/anytone778uv_serial/index.mdwn b/projects/anytone778uv_serial/index.mdwn
new file mode 100644 (file)
index 0000000..24dc811
--- /dev/null
@@ -0,0 +1,407 @@
+# AT778UV Driver\r
+\r
+This is the notes I made reverse engineering the serial commuication between\r
+the vendor software and the AnyTone 778UV radio.  Driver support in chirp as\r
+of build #872 on 20200521\r
+\r
+## TODO\r
+how to capture with wireshark and dissect\r
+\r
+## programming flow\r
+\r
+n.b. tx and rx connected together in the serial adaptor - the host sees everything it sends\r
+on rx, that's not shown here\r
+\r
+## Memory map \r
+\r
+       +------+---------------------------+\r
+       | addr | Contents                  |\r
+       +------+---------------------------+\r
+       | 0000 | Memory 0 - bytes  0 - 15  |\r
+       | 0010 | Memory 0 - bytes 16 - 32  |\r
+       +------+---------------------------+\r
+       | 0020 | Memory 1                  |\r
+       | 0030 |                           |\r
+       +------+---------------------------+\r
+       | ...  |         ...               |\r
+       +------+---------------------------+\r
+       | 18e0 | Memory 199                |\r
+       | 18f0 | 0x18e0/32 = 199           |\r
+       +------+---------------------------+\r
+       | 1900 | VF01                      |\r
+       | ...  | just another memory       |\r
+       |      | don't set name - it       |\r
+       | 1910 | overwrites freq disp.     |\r
+       +------+---------------------------+\r
+       | 1920 | VF02                      |\r
+       | ...  | just another memory       |\r
+       |      | don't set name - it       |\r
+       | 1930 | overwrites freq disp.     |\r
+       +------+---------------------------+\r
+       | 1940 | bit field of mem occupied |\r
+       | 1950 |                           |\r
+       +------+---------------------------+\r
+       | 1960 | bit field of scan add     |\r
+       | 1970 |                           |\r
+       +------+---------------------------+\r
+       | 1980 | switch on message is here |\r
+       |      | bytes  0-6                |\r
+       +------+---------------------------+\r
+       | 1990 | this block is all 0xff    |\r
+       | ...  | from the factory          |\r
+       | 1ac0 |                           |\r
+       +------+---------------------------+\r
+       | 1ad0 | unknown                   |\r
+       | ...  | there's some stuff here   |\r
+       | 1c70 | but don't know what it is |\r
+       +------+---------------------------+\r
+       | 1c80 | unknown                   |\r
+       | ...  | there's some stuff here   |\r
+       | 1c60 | but don't know what it is |\r
+       +------+---------------------------+\r
+       | 1c70 | this block is all 0x00    |\r
+       | ...  | from the factory          |\r
+       | 30d0 |                           |\r
+       +------+---------------------------+\r
+       | 30e0 | unknown                   |\r
+       | ...  | there's some stuff here   |\r
+       | 3270 | but don't know what it is |\r
+       +------+---------------------------+\r
+       | 3280 | TRF                       |\r
+       | 3290 | just another memory       |\r
+       +------+---------------------------+\r
+       | 320a | Don't know what's here,   |\r
+       |      | and the vendor s/w doesn't|\r
+       | 3b00 | read it. Here be dragons? |\r
+       +------+---------------------------+\r
+       | 3b10 | Don't know what this is   |\r
+       | ...  | vendor s/w reads it before|\r
+       |      | writing memories.  Looks  |\r
+       | 3b20 | like maybe a bitfield.    |\r
+       +------+---------------------------+\r
+\r
+Spot addresses:\r
+\r
+       +--------+--------+---------------------------------------+\r
+       |  Addr  | Length | Description                           |\r
+       +--------+--------+---------------------------------------+\r
+    | 0x320b |    1   | Active VFO 00=A, 01=B                 |\r
+       +--------+--------+---------------------------------------+\r
+    | 0x326d |    1   | Band Settings - see band limits table |\r
+       +--------+--------+---------------------------------------+\r
+    | 0x3260 |    1   | Current channel VF0 A                 |\r
+       +--------+--------+---------------------------------------+\r
+       | 0x3267 |    1   | current scan channel                  |\r
+       +--------+--------+---------------------------------------+\r
+       | 0x3268 |    1   |  bit 3 set for scan active            |\r
+       +--------+--------+---------------------------------------+\r
+\r
+\r
+## Messages and Flow\r
+\r
+### Enter Programming Mode and Identify\r
+\r
+     host                         radio\r
+       |                            |\r
+          +------Program-------------->|   Host will send PROGRAM three times\r
+          |                            |   before giving up.\r
+          |<-----QX\x06----------------+\r
+          |                            |\r
+       +------\x02----------------->|  Check radio version\r
+          |                            |\r
+          |<-----..AT778UV.V200.....---+  Model and version\r
+          |                            |\r
+\r
+The identify message has the following format: \r
+\r
+       +-------+--------+---------+----------------------+\r
+       | Start | Length | Name    | Desc                 |\r
+       | Byte  | Byte   |         |                      |\r
+       +-------+--------+---------+----------------------+\r
+       | 0x00  |    1   | Header  | Always 'I' 0x49      |\r
+       +-------+--------+---------+----------------------+\r
+       | 0x01  |    7   | Model   | C-string, model name |\r
+       +-------+--------+---------+----------------------+\r
+       | 0x08  |    1   | Band    | Always 0x00-0x02     |\r
+       +-------+--------+---------+----------------------+\r
+       | 0x09  |    6   | Version | C-string, version    |\r
+       +-------+--------+---------+----------------------+\r
+\r
+Band settings limit the transmit/receive frequency ranges\r
+\r
+       +------+---------------------------------+\r
+       | Band |       Band Limits [Hz]          |\r
+       +------+----------------+----------------+\r
+       | Byte |       VHF      |       UHF      |\r
+       +------+----------------+----------------+\r
+       | 0x00 | (144e6, 148e6) | (430e6, 440e6) |\r
+       | 0x01 | (134e6, 174e6) | (400e6, 490e6) |\r
+       | 0x02 | (144e6, 146e6) | (430e6, 440e6) |\r
+       +------+----------------+----------------+\r
+\r
+\r
+Known radio models and versions:\r
+\r
+       +---------+------------+--------------+----------------+\r
+       | Vendor  | Model Name | Model String | Version String |\r
+       +---------+------------+--------------+----------------+\r
+       | AnyTone |   778UV    | AT778UV      | V200           |\r
+       | Retevis |    RT95    | RT95         | V100           |\r
+       | CRT     | Micron UV  | MICRON       | V100           |\r
+       | Midland | DBR2500    | DBR2500      | V100           |\r
+       +---------+------------+--------------+----------------+\r
+\r
+Model and version can also be found in the first few bytes of a save file from\r
+the vendor software.\r
+\r
+### Exit Programming Mode\r
+\r
+     host                         radio\r
+       |                            |\r
+          +------END------------------>|\r
+          |                            |\r
+          |<-----\x06------------------+\r
+          |                            |\r
+\r
+### Programming Flow - Read Device Memory\r
+\r
+     host                         radio\r
+       |                            |\r
+        +--------------------------------+\r
+        | Enter programming mode         |\r
+        | and identify                   |\r
+        +--------------------------------+\r
+          |                            |\r
+          +----Read 0x0000 16 bytes--->| Request the first half of memory 0\r
+          |                            |\r
+          |<---Write 0x0000 16 bytes---+ First half of memory 0\r
+          |                            |\r
+          +----Read 0x0010 16 bytes--->| Request the second half of memory 0\r
+          |                            |\r
+          |<---Write 0x0010 16 bytes---+ Second half of memory 0\r
+          |                            |\r
+                                   ...               Repeat for addresses 0x20-0x3aff\r
+          |                            |\r
+          +----Read 0x3b00 16 bytes--->| Read last address in memory map\r
+          |                            |\r
+          |<---Write 0x0000 16 bytes---+ \r
+       |                            |\r
+        +--------------------------------+\r
+        |  Exit programming mode         |\r
+        |                                |\r
+        +--------------------------------+\r
+          |                            |\r
+\r
+### Programming Flow - Write Device Memory\r
+\r
+     host                         radio\r
+       |                            |\r
+        +--------------------------------+\r
+        | Enter programming mode         |\r
+        | and identify                   |\r
+        +--------------------------------+\r
+          |                            |\r
+          +----Read 0x3b10 16 bytes--->|\r
+          |                            |\r
+          |<---Write 0x3b10 16 bytes---+  Data is 02ffffff 00000000 00000000 00000000\r
+          |                            |  but I don't know what it means yet.\r
+          |                            |  Also note that it's off the bottom of\r
+          |                            |  the memory map. XXX 32 bytes\r
+          |                            |\r
+          |                            |\r
+          +---Write 0x0000 16 bytes--->| Write the first half of memory 0\r
+          |                            |\r
+          |<----------\x06-------------+ Ack\r
+          |                            |\r
+          +---Write 0x0010 16 bytes--->| Write the second half of memory 0\r
+          |                            |\r
+          |<----------\x06-------------+ Ack\r
+          |                            |\r
+                                   ...               Repeat for addresses 0x20-0x3aff\r
+          |                            |\r
+          +----Write 0x3b00 16 bytes-->| Write last address in memory map\r
+          |                            |\r
+          |<----------\x06-------------+ Ack\r
+       |                            |\r
+        +--------------------------------+\r
+        |  Exit programming mode         |\r
+        |                                |\r
+        +--------------------------------+\r
+          |                            |\r
+\r
+Note however, that it's not necessary to read or write the whole memory, the\r
+radio seems to support arbitary length reads at any address; and definitely\r
+supports partial writes of radio memories - e.g. writing only memory 0.\r
+\r
+Also note, that per-memory scan status, and a memory occupied flag, are stored\r
+in bit fields and may also need to be updated (see addresses 0x1940 and 0x1960\r
+in the memory map).  These bitfields are indexed by the memory index 0-199\r
+starting with the bitfield address.  E.g. memory zero is at bit 7 of byte 0;\r
+memory 10 at bit 3 of byte 1 etc.\r
+\r
+\r
+### Read and Write Messages\r
+There's a really simple format to the messages sent and received by the radio\r
+in program mode, there are two message types: read and write.  If the PC sends\r
+a read then it's a request with no data, the radio responds with a write\r
+message of the requested data.  If the PC sends a write message then it\r
+includes the data, and the radio sends only an ACK, 0x06 in reply.  If, for\r
+example, the checksum of a write message is wrong the radio can reply with\r
+0x0a - NACK.\r
+\r
+Message fields:\r
+\r
++-------+-------------------------------------+\r
+| Start | Length | Content                    | \r
+| Byte  | Bytes  |                            | \r
++-------+--------+----------------------------+\r
+| 0x00  |    1   | Message Type:              |\r
+|       |        | * 0x57 ('W') Write message |\r
+|       |        | * 0x52 ('R') Read message  |\r
++-------+--------+----------------------------+\r
+| 0x01  |    2   | Memory Read/Write Address  |\r
++-------+--------+----------------------------+\r
+| 0x03  |    1   | Data Length (Bytes)        |\r
+|       |        | typically (always?) 0x10   |\r
++-------+--------+----------------------------+\r
+| 0x04  | Length | Data Bytes to read/write   |\r
++-------+--------+----------------------------+\r
+| -0x02 |    1   | [checksum](##Checksum)     |\r
+|       |        | over bytes 0x01 to -0x03   |\r
++-------+--------+----------------------------+\r
+| -0x01 |    1   | End of message, always     |\r
+|       |        | 0x06                       |\r
++-------+--------+----------------------------+\r
+\r
+Message format, and a typical message writing the first 16 bytes of memory 49.\r
+This is also the format of the response from the radio if the host requests to\r
+read memory 49.\r
+\r
++------+---------+--------+-------------------------------------+----------+-----+\r
+| Type | Address | Length | Data                                | Checksum | EoM |\r
++------+---------+--------+-------------------------------------+----------+-----+\r
+|   57 |    0620 |    10  | 14500000 00100000 00010004 33001100 |    f3    | 06  |\r
++------+---------+--------+-------------------------------------+----------+-----+\r
+\r
+Message format, and a typical message from the host asking to read the first 16 bytes of memory 49.\r
+\r
++------+---------+--------+----------+-----+\r
+| Type | Address | Length | Checksum | EoM |\r
++------+---------+--------+----------+-----+\r
+|   52 |    0620 |    10  |    f3    | 06  |\r
++------+---------+--------+----------+-----+\r
+\r
+## Memory Format\r
+\r
++------+---+--------------+----------------------------+\r
+| 0x00 | 4 | frequency    | big endian bcd             |\r
+|      |   |              | frequency 10s of Hz        |\r
++------+---+--------------+----------------------------+\r
+| 0x04 | 4 | offset       | big endian bcd             |\r
+|      |   |              | frequency 10s of Hz        |\r
++------+---+--------------+----------------------------+\r
+| 0x08 | 1 | unknown1     | default 00                 |\r
++------+---+--------------+----------------------------+\r
+| 0x09 | 1 |              | OR of tx power and split   |\r
+|      |   | tx power     | tx power high : 00001000   |\r
+|      |   |              | tx power med  : 00000100   |\r
+|      |   | and          | tx power low  : 00000000   |\r
+|      |   |              |                            |\r
+|      |   | split        | split +ve : 00000001       |\r
+|      |   |              | split -ve : 00000010       |\r
+|      |   | flags1       | no split : 00000000        |\r
+|      |   |              |                            |\r
+|      |   |              | talk around: 0x80          |\r
+|      |   |              | scramble : 0x40            |\r
++------+---+--------------+----------------------------+\r
+| 0x0a | 1 | chan spacing | bit:                       |\r
+|      |   |              |   7 -                      |\r
+|      |   | and          |   6                        |\r
+|      |   |              |   5                        |\r
+|      |   | params       |   4                        |\r
+|      |   |              |   3 - channel width 3,2    |\r
+|      |   | flags 2      |   2 - 10=25kHz,01=20kHz,   |\r
+|      |   |              |       00=12.5kHz           | \r
+|      |   |              |   1 - reverse              |\r
+|      |   |              |   0 - tx off               |\r
++------+---+--------------+----------------------------+\r
+| 0x0b | 1 | ctcss enable | bit:                       |\r
+|      |   |              |   3 - dcs dec enable       |\r
+|      |   |              |   2 - ctcss dec enable     |\r
+|      |   | flags3       |   1 - dcs enc enable       |\r
+|      |   |              |   0 - ctcss enc enable     |\r
++------+---+--------------+----------------------------+\r
+| 0x0c | 1 |ctcss dec tone| ctcss enumeration          |\r
++------+---+--------------+----------------------------+\r
+| 0x0d | 1 |ctcss enc tone| ctcss enumeration          |\r
++------+---+--------------+----------------------------+\r
+| 0x0e | 1 | dcs dec code | =int(tone, 8) bits 7:0     |\r
++------+---+--------------+----------------------------+\r
+| 0x0f | 1 | unknown3     | default 0x00               |\r
+|      |   |              |   1 - DCS dec invert en    |\r
+|      |   |              |   0 - DCS dec code bit 8   |\r
++------+---+--------------+----------------------------+\r
+| 0x10 | 1 | dcs enc code | =int(tone, 8) bits 7:0     |\r
++------+---+--------------+----------------------------+\r
+| 0x11 | 1 | unknown5     | default 0x00               |\r
+|      |   |              |   1 - DCS enc invert en    |\r
+|      |   |              |   0 - DCS enc code bit 8   |\r
++------+---+--------------+----------------------------+\r
+| 0x12 | 1 | params       | bit                        |\r
+|      |   |              | 1,0 - busy chn lockout     |\r
+|      |   |              |       10 = 'busy'          |\r
+|      |   | flags4       |       01 = 'repeater'      |\r
+|      |   |              |       00 = 'off'           |\r
++------+---+--------------+----------------------------+\r
+| 0x13 | 1 | unknown6     | default 0x00               |\r
++------+---+--------------+----------------------------+\r
+| 0x14 | 1 | params       | bit                        |\r
+|      |   | flags5       |   0 - ctcss squelch enable |\r
++------+---+--------------+----------------------------+\r
+| 0x15 | 1 | unknown7     | default 0x00               |\r
++------+---+--------------+----------------------------+\r
+| 0x16 | 1 | unknown8     | default 0x00               |\r
++------+---+--------------+----------------------------+\r
+| 0x17 | 1 | unknown9     | default 0x00               |\r
++------+---+--------------+----------------------------+\r
+| 0x18 | 1 | unknown10    | default 0x00               |\r
++------+---+--------------+----------------------------+\r
+| 0x19 | 5 | name string  |                            |\r
++------+---+--------------+----------------------------+\r
+| 0x1e | 1 | custom ctcss | custom ctcss value as      |\r
+|      |   | low byte     |  Hz * 10, litte endian     |\r
++------+---+--------------+ e.g. 0xae08 = 222.2Hz      |\r
+| 0x1f | 1 | custom ctcss | see 'define' value in      |\r
+|      |   | high byte    | ctcss enumeration          |\r
+|      |   |              |                            |\r
++------+---+--------------+----------------------------+\r
+\r
+## ctcss enumeration:\r
++------+-----------++------+------------++------+-----------++------+------------+\r
+| Val  | Tone [Hz] || Val  | Tone [Hz]  || Val  | Tone [Hz] || Val  | Tone [Hz]  |\r
++------+-----------++------+------------++------+-----------++------+------------+\r
+| 0x00 | 62.5      || 0x0d | 100.0      || 0x1a | 156.7     || 0x27 | 196.6      |\r
+| 0x01 | 67.0      || 0x0e | 103.5      || 0x1b | 159.8     || 0x28 | 199.5      |\r
+| 0x02 | 69.3      || 0x0f | 107.2      || 0x1c | 162.2     || 0x29 | 203.5      |\r
+| 0x03 | 71.9      || 0x10 | 110.9      || 0x1d | 165.5     || 0x2a | 206.5      |\r
+| 0x04 | 74.4      || 0x11 | 114.8      || 0x1e | 167.9     || 0x2b | 210.7      |\r
+| 0x05 | 77.0      || 0x12 | 118.8      || 0x1f | 171.3     || 0x2c | 218.1      |\r
+| 0x06 | 79.7      || 0x13 | 123.0      || 0x20 | 173.8     || 0x2d | 225.7      |\r
+| 0x07 | 82.5      || 0x14 | 127.3      || 0x21 | 177.3     || 0x2e | 229.1      |\r
+| 0x08 | 85.4      || 0x15 | 131.8      || 0x22 | 179.9     || 0x2f | 233.6      |\r
+| 0x09 | 88.5      || 0x16 | 136.5      || 0x23 | 183.5     || 0x30 | 241.8      |\r
+| 0x0a | 91.5      || 0x17 | 141.3      || 0x24 | 186.2     || 0x31 | 250.3      |\r
+| 0x0b | 94.8      || 0x18 | 146.2      || 0x25 | 189.9     || 0x32 | 254.1      |\r
+| 0x0c | 97.4      || 0x19 | 151.4      || 0x26 | 192.8     || 0x33 | define     |\r
++------+-----------++------+------------++------+-----------++------+------------+\r
+\r
+## Checksum\r
+```python\r
+def checksum(message_bytes):\r
+       mask = 0xFF\r
+       checksum = 0\r
+       for b in message_bytes:\r
+               checksum = (checksum + b) & mask\r
+       return checksum\r
+```\r
+vim: set ft=markdown :\r