[chirp_devel] Fwd: [PATCH 4 of 4] [RT76] Retevis RT76

Jim Unroe
Sat Apr 3 18:05:11 PDT 2021


Note: image files were attached to their respective patches.

Jim KC9HI

---------- Forwarded message ---------
From: Jim Unroe <kc9hi at comcast.net>
Date: Sat, Apr 3, 2021 at 8:59 PM
Subject: [PATCH 4 of 4] [RT76] Retevis RT76
To: <Rock.Unroe at gmail.com>


# HG changeset patch
# User Jim Unroe <rock.unroe at gmail.com>
# Date 1617488266 14400
#      Sat Apr 03 18:17:46 2021 -0400
# Node ID 35ce102f7e2d432b0ba6a30b580904ad816c846e
# Parent  c11f6ae9ccfd9b306db3b5f1e7fe166364a822b0
[RT76] Retevis RT76

This patch adds support for the Retevis RT76.

Related to #8959

diff -r c11f6ae9ccfd -r 35ce102f7e2d chirp/drivers/retevis_rt21.py
--- a/chirp/drivers/retevis_rt21.py     Sat Apr 03 18:13:37 2021 -0400
+++ b/chirp/drivers/retevis_rt21.py     Sat Apr 03 18:17:46 2021 -0400
@@ -197,6 +197,48 @@
 } settings3;
 """

+MEM_FORMAT_RT76 = """
+#seekto 0x0000;
+struct {
+  lbcd rxfreq[4];      // RX Frequency           0-3
+  lbcd txfreq[4];      // TX Frequency           4-7
+  ul16 rx_tone;        // PL/DPL Decode          8-9
+  ul16 tx_tone;        // PL/DPL Encode          A-B
+  u8 compander:1,      // Compander              C
+     unknown1:1,       //
+     highpower:1,      // Power Level
+     wide:1,           // Bandwidth
+     unknown2:4;       //
+  u8 reserved[3];      // Reserved               D-F
+} memory[30];
+
+#seekto 0x002D;
+struct {
+  u8 unknown_1:1,      //                        002D
+     chnumberd:1,      // Channel Number Disable
+     gain:1,           // MIC Gain                                 ---
+     savem:1,          // Battery Save Mode                        ---
+     save:1,           // Battery Save                             ---
+     beep:1,           // Beep                                     ---
+     voice:2;          // Voice Prompts                            ---
+  u8 squelch;          // Squelch                002E              ---
+  u8 tot;              // Time-out Timer         002F              ---
+  u8 channel_4[13];    //                        0030-003C
+  u8 unused:7,         //                        003D
+     vox:1;            // Vox                                      ---
+  u8 voxl;             // Vox Level              003E              ---
+  u8 voxd;             // Vox Delay              003F              ---
+  u8 channel_5[13];    //                        0040-004C
+  u8 unknown_4;        //                        004D
+  u8 unknown_5[2];     //                        004E-004F
+  u8 channel_6[13];    //                        0050-005C
+  u8 chnumber;         // Channel Number         005D              ---
+  u8 unknown_7[2];     //                        005E-005F
+  u8 channel_7[13];    //                        0060-006C
+  u8 warn;             //                        006D              ---
+} settings;
+"""
+
 CMD_ACK = "\x06"

 ALARM_LIST = ["Local Alarm", "Remote Alarm"]
@@ -211,6 +253,7 @@
 TOTALERT_LIST = ["Off"] + ["%s seconds" % x for x in range(1, 11)]
 VOICE_LIST = ["Off", "Chinese", "English"]
 VOICE_LIST2 = ["Off", "English"]
+VOICE_LIST3 = VOICE_LIST2 + ["Chinese"]
 VOX_LIST = ["OFF"] + ["%s" % x for x in range(1, 17)]
 VOXD_LIST = ["0.5", "1.0", "1.5", "2.0", "2.5", "3.0"]
 VOXL_LIST = ["OFF"] + ["%s" % x for x in range(1, 9)]
@@ -232,6 +275,7 @@
     "totalert": TOTALERT_LIST,
     "voice": VOICE_LIST,
     "voice": VOICE_LIST2,
+    "voice": VOICE_LIST3,
     "vox": VOX_LIST,
     "voxd": VOXD_LIST,
     "voxl": VOXL_LIST,
@@ -253,7 +297,7 @@
     exito = False
     for i in range(0, 5):
         serial.write(radio._magic)
-        if radio.MODEL == "RB26":
+        if radio.MODEL == "RB26" or radio.MODEL == "RT76":
             serial.read(1)
         ack = serial.read(1)

@@ -387,7 +431,7 @@
         status.cur = addr + radio.BLOCK_SIZE
         radio.status_fn(status)

-        if radio.MODEL == "RB26":
+        if radio.MODEL == "RB26" or radio.MODEL == "RT76":
             block = _rb26_read_block(radio, addr, radio.BLOCK_SIZE)
         else:
             block = _read_block(radio, addr, radio.BLOCK_SIZE)
@@ -633,7 +677,7 @@
             LOG.debug("Initializing empty memory")
             if self.MODEL == "RB17A":
                 _mem.set_raw("\x00" * 13 + "\x04\xFF\xFF")
-            if self.MODEL == "RB26":
+            if self.MODEL == "RB26" or self.MODEL == "RT76":
                 _mem.set_raw("\x00" * 13 + _rsvd)
             else:
                 _mem.set_raw("\x00" * 13 + "\x30\x8F\xF8")
@@ -651,8 +695,9 @@

         mem.power = self.POWER_LEVELS[_mem.highpower]

-        mem.skip = "" if (_skp & bitpos) else "S"
-        LOG.debug("mem.skip %s" % mem.skip)
+        if self.MODEL != "RT76":
+            mem.skip = "" if (_skp & bitpos) else "S"
+            LOG.debug("mem.skip %s" % mem.skip)

         mem.extra = RadioSettingGroup("Extra", "extra")

@@ -671,10 +716,11 @@
                 rset = RadioSetting("cdcss", "Cdcss Mode", rs)
                 mem.extra.append(rset)

-        if self.MODEL == "RB26":
-            rs = RadioSettingValueBoolean(_mem.bcl)
-            rset = RadioSetting("bcl", "Busy Channel Lockout", rs)
-            mem.extra.append(rset)
+        if self.MODEL == "RB26" or self.MODEL == "RT76":
+            if self.MODEL == "RB26":
+                rs = RadioSettingValueBoolean(_mem.bcl)
+                rset = RadioSetting("bcl", "Busy Channel Lockout", rs)
+                mem.extra.append(rset)

             rs = RadioSettingValueBoolean(_mem.compander)
             rset = RadioSetting("compander", "Compander", rs)
@@ -749,7 +795,7 @@
         if mem.empty:
             if self.MODEL == "RB17A":
                 _mem.set_raw("\xFF" * 12 + "\x00\x00\xFF\xFF")
-            elif self.MODEL == "RB26":
+            elif self.MODEL == "RB26" or self.MODEL == "RT76":
                 _mem.set_raw("\xFF" * 13 + _rsvd)
             else:
                 _mem.set_raw("\xFF" * (_mem.size() / 8))
@@ -773,7 +819,7 @@

         if self.MODEL == "RB17A":
             _mem.set_raw("\x00" * 13 + "\x00\xFF\xFF")
-        elif self.MODEL == "RB26":
+        elif self.MODEL == "RB26" or self.MODEL == "RT76":
             _mem.set_raw("\x00" * 13 + _rsvd)
         else:
             _mem.set_raw("\x00" * 13 + "\x30\x8F\xF8")
@@ -798,11 +844,12 @@

         _mem.highpower = mem.power == self.POWER_LEVELS[1]

-        if mem.skip != "S":
-            _skp |= bitpos
-        else:
-            _skp &= ~bitpos
-        LOG.debug("_skp %s" % _skp)
+        if self.MODEL != "RT76":
+            if mem.skip != "S":
+                _skp |= bitpos
+            else:
+                _skp &= ~bitpos
+            LOG.debug("_skp %s" % _skp)

         for setting in mem.extra:
             if setting.get_name() == "scramble_type":
@@ -894,9 +941,10 @@
                 rset.set_apply_callback(apply_topkey_listvalue, _keys.topkey)
                 basic.append(rset)

-        if self.MODEL == "RB26":
-            _settings2 = self._memobj.settings2
-            _settings3 = self._memobj.settings3
+        if self.MODEL == "RB26" or self.MODEL == "RT76":
+            if self.MODEL == "RB26":
+                _settings2 = self._memobj.settings2
+                _settings3 = self._memobj.settings3

             rs = RadioSettingValueInteger(0, 9, _settings.squelch)
             rset = RadioSetting("squelch", "Squelch Level", rs)
@@ -907,14 +955,21 @@
             rset = RadioSetting("tot", "Time-out timer", rs)
             basic.append(rset)

-            rs = RadioSettingValueList(VOICE_LIST2,
-                                       VOICE_LIST2[_settings.voice])
-            rset = RadioSetting("voice", "Voice Annumciation", rs)
-            basic.append(rset)
+            if self.MODEL == "RT76":
+                rs = RadioSettingValueList(VOICE_LIST3,
+                                           VOICE_LIST3[_settings.voice])
+                rset = RadioSetting("voice", "Voice Annumciation", rs)
+                basic.append(rset)

-            rs = RadioSettingValueBoolean(not _settings.chnumberd)
-            rset = RadioSetting("chnumberd", "Channel Number Enable", rs)
-            basic.append(rset)
+            if self.MODEL == "RB26":
+                rs = RadioSettingValueList(VOICE_LIST2,
+                                           VOICE_LIST2[_settings.voice])
+                rset = RadioSetting("voice", "Voice Annumciation", rs)
+                basic.append(rset)
+
+                rs = RadioSettingValueBoolean(not _settings.chnumberd)
+                rset = RadioSetting("chnumberd", "Channel Number Enable", rs)
+                basic.append(rset)

             rs = RadioSettingValueBoolean(_settings.save)
             rset = RadioSetting("save", "Battery Save", rs)
@@ -924,9 +979,10 @@
             rset = RadioSetting("beep", "Beep", rs)
             basic.append(rset)

-            rs = RadioSettingValueBoolean(not _settings.tail)
-            rset = RadioSetting("tail", "QT/DQT Tail", rs)
-            basic.append(rset)
+            if self.MODEL == "RB26":
+                rs = RadioSettingValueBoolean(not _settings.tail)
+                rset = RadioSetting("tail", "QT/DQT Tail", rs)
+                basic.append(rset)

             rs = RadioSettingValueList(SAVE_LIST, SAVE_LIST[_settings.savem])
             rset = RadioSetting("savem", "Battery Save Mode", rs)
@@ -940,29 +996,53 @@
             rset = RadioSetting("warn", "Warn Mode", rs)
             basic.append(rset)

-            rs = RadioSettingValueBoolean(_settings3.vox)
-            rset = RadioSetting("settings3.vox", "Vox Function", rs)
-            basic.append(rset)
+            if self.MODEL == "RB26":
+                rs = RadioSettingValueBoolean(_settings3.vox)
+                rset = RadioSetting("settings3.vox", "Vox Function", rs)
+                basic.append(rset)
+
+                rs = RadioSettingValueList(VOXL_LIST,
+                                           VOXL_LIST[_settings3.voxl])
+                rset = RadioSetting("settings3.voxl", "Vox Level", rs)
+                basic.append(rset)

-            rs = RadioSettingValueList(VOXL_LIST, VOXL_LIST[_settings3.voxl])
-            rset = RadioSetting("settings3.voxl", "Vox Level", rs)
-            basic.append(rset)
+                rs = RadioSettingValueList(VOXD_LIST,
+                                           VOXD_LIST[_settings3.voxd])
+                rset = RadioSetting("settings3.voxd", "Vox Delay", rs)
+                basic.append(rset)

-            rs = RadioSettingValueList(VOXD_LIST, VOXD_LIST[_settings3.voxd])
-            rset = RadioSetting("settings3.voxd", "Vox Delay", rs)
-            basic.append(rset)
+                rs = RadioSettingValueList(PFKEY_LIST,
+                                           PFKEY_LIST[_settings.pf1])
+                rset = RadioSetting("pf1", "PF1 Key Set", rs)
+                basic.append(rset)

-            rs = RadioSettingValueList(PFKEY_LIST, PFKEY_LIST[_settings.pf1])
-            rset = RadioSetting("pf1", "PF1 Key Set", rs)
-            basic.append(rset)
+                rs = RadioSettingValueList(PFKEY_LIST,
+                                           PFKEY_LIST[_settings.pf2])
+                rset = RadioSetting("pf2", "PF2 Key Set", rs)
+                basic.append(rset)
+
+                rs = RadioSettingValueInteger(1, 30, _settings2.chnumber + 1)
+                rset = RadioSetting("settings2.chnumber", "Channel Number", rs)
+                basic.append(rset)
+
+            if self.MODEL == "RT76":
+                rs = RadioSettingValueBoolean(_settings.vox)
+                rset = RadioSetting("vox", "Vox Function", rs)
+                basic.append(rset)

-            rs = RadioSettingValueList(PFKEY_LIST, PFKEY_LIST[_settings.pf2])
-            rset = RadioSetting("pf2", "PF2 Key Set", rs)
-            basic.append(rset)
+                rs = RadioSettingValueList(VOXL_LIST,
+                                           VOXL_LIST[_settings.voxl])
+                rset = RadioSetting("voxl", "Vox Level", rs)
+                basic.append(rset)

-            rs = RadioSettingValueInteger(1, 30, _settings2.chnumber + 1)
-            rset = RadioSetting("settings2.chnumber", "Channel Number", rs)
-            basic.append(rset)
+                rs = RadioSettingValueList(VOXD_LIST,
+                                           VOXD_LIST[_settings.voxd])
+                rset = RadioSetting("voxd", "Vox Delay", rs)
+                basic.append(rset)
+
+                rs = RadioSettingValueInteger(1, 30, _settings.chnumber + 1)
+                rset = RadioSetting("chnumber", "Channel Number", rs)
+                basic.append(rset)

         return top

@@ -1059,6 +1139,34 @@
     def process_mmap(self):
         self._memobj = bitwise.parse(MEM_FORMAT_RB26, self._mmap)

+
+ at directory.register
+class RT76Radio(RT21Radio):
+    """RETEVIS RT76"""
+    VENDOR = "Retevis"
+    MODEL = "RT76"
+    BAUD_RATE = 9600
+    BLOCK_SIZE = 0x20
+    BLOCK_SIZE_UP = 0x10
+
+    POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=0.50),
+                    chirp_common.PowerLevel("High", watts=5.00)]
+
+    _magic = "PHOGR\x14\xD4"
+    _fingerprint = "P32073" + "\x02\xFF"
+    _upper = 30
+    _skipflags = False
+    _reserved = True
+    _gmrs = True
+
+    _ranges = [
+               (0x0000, 0x01E0),
+              ]
+    _memsize = 0x01E0
+
+    def process_mmap(self):
+        self._memobj = bitwise.parse(MEM_FORMAT_RT76, self._mmap)
+
     @classmethod
     def match_model(cls, filedata, filename):
         if cls.MODEL == "RT21":
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Retevis_RT76.img
Type: application/octet-stream
Size: 645 bytes
Desc: not available
Url : http://intrepid.danplanet.com/pipermail/chirp_devel/attachments/20210403/7959ff03/attachment-0001.img 


More information about the chirp_devel mailing list