From d736f6d58cdb29d1750a8f5a7da551189940f733 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Sun, 11 Aug 2024 08:17:02 -0700 Subject: [PATCH 1/7] Add padding support to icf.warp_byte_size --- chirp/drivers/icf.py | 10 ++++++++-- tests/unit/test_icf.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/chirp/drivers/icf.py b/chirp/drivers/icf.py index c0acbd668..843204dfe 100644 --- a/chirp/drivers/icf.py +++ b/chirp/drivers/icf.py @@ -1034,7 +1034,7 @@ def get_bank_model(self): return None -def warp_byte_size(inbytes, obw=8, ibw=8): +def warp_byte_size(inbytes, obw=8, ibw=8, iskip=0, opad=0): """Convert between "byte sizes". This will pack N-bit characters into a sequence of 8-bit bytes, @@ -1042,17 +1042,23 @@ def warp_byte_size(inbytes, obw=8, ibw=8): ibw (input bit width) is the width of the storage obw (output bit width) is the width of the characters to extract + iskip is the number of input padding bits to skip + opad is the number of output zero padding bits to add ibw=8,obw=7 will pull seven-bit characters from a sequence of bytes ibw=7,obw=8 will pack seven-bit characters into a sequence of bytes """ if isinstance(inbytes, str): inbytes = [ord(x) for x in inbytes] - outbit = 0 + outbit = opad tmp = 0 stripmask = 1 << (ibw - 1) for byte in inbytes: inbit = 0 + while iskip: + byte = (byte << 1) & 0xFF + inbit += 1 + iskip -= 1 for i in range(0, max(obw, ibw - inbit)): if inbit == ibw: # Move to next char diff --git a/tests/unit/test_icf.py b/tests/unit/test_icf.py index 08bd74d04..cc30ee23b 100644 --- a/tests/unit/test_icf.py +++ b/tests/unit/test_icf.py @@ -159,3 +159,32 @@ def test_pack(self): f = icf.IcfFrame(icf.ADDR_PC, icf.ADDR_RADIO, icf.CMD_CLONE_ID) f.payload = b'\x01\x02' self.assertEqual(b'\xfe\xfe\xee\xef\xe0\x01\x02\xfd', f.pack()) + + +class TestICFUtil(unittest.TestCase): + def test_warp_byte_size(self): + # 4-bit chars to 8-bit bytes + input = bytes([0x12, 0x34]) + output = bytes(icf.warp_byte_size(input, obw=4)) + self.assertEqual(b'\x01\x02\x03\x04', output) + + def test_warp_byte_size_skip(self): + # 4-bit chars to 8-bit bytes with 4 bits of padding ignored + input = bytes([0x12, 0x34]) + output = bytes(icf.warp_byte_size(input, obw=4, iskip=4)) + self.assertEqual(b'\x02\x03\x04', output) + + def test_warp_byte_size_pad(self): + # 8-bit bytes to 4-bit chars, with 4 bits of padding added + input = bytes([2, 3, 4]) + output = bytes(icf.warp_byte_size(input, ibw=4, opad=4)) + self.assertEqual(b'\x02\x34', output) + + def test_warp_byte_size_symmetric_padded(self): + # Make sure we can go from 8->4-> with padding and get back what we + # put in + ref = bytes([1, 2, 3, 4, 5, 6]) + stored = bytes(icf.warp_byte_size(bytes(ref), ibw=6, opad=4)) + self.assertEqual(5, len(bytes(stored))) + self.assertEqual(ref, + bytes(icf.warp_byte_size(stored, obw=6, iskip=4))) From 74fb706be1f01d9a4e207fe49d0aa35f7af500e8 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 12 Aug 2024 15:01:16 -0700 Subject: [PATCH 2/7] thd8: Fix ham model RX-bands The TD-H8 Ham variant never got the proper _rxbands list which it needs to allow users to put in the full range of receive-only frequencies. Fixes #11473 --- chirp/drivers/tdh8.py | 9 +++++++++ tests/unit/test_chirp_common.py | 1 + 2 files changed, 10 insertions(+) diff --git a/chirp/drivers/tdh8.py b/chirp/drivers/tdh8.py index c2adf7cce..4afa5139b 100644 --- a/chirp/drivers/tdh8.py +++ b/chirp/drivers/tdh8.py @@ -2465,8 +2465,17 @@ class TDH8_HAM(TDH8): MODEL = "TD-H8-HAM" ident_mode = b'P31185\xff\xff' _ham = True + _rxbands = [(136000000, 143999000), (149000001, 174000000), + (400000000, 419999000), (451000001, 521000000)] _txbands = [(144000000, 149000000), (420000000, 451000000)] + def check_set_memory_immutable_policy(self, existing, new): + # Immutable duplex handling is done in set_memory, so no need + # to ever obsess over it here. + if 'duplex' in existing.immutable: + existing.immutable.remove('duplex') + super().check_set_memory_immutable_policy(existing, new) + @directory.register @directory.detected_by(TDH8) diff --git a/tests/unit/test_chirp_common.py b/tests/unit/test_chirp_common.py index c0dd4ecd4..60f068d36 100644 --- a/tests/unit/test_chirp_common.py +++ b/tests/unit/test_chirp_common.py @@ -769,6 +769,7 @@ class TestOverrideRules(base.BaseTest): 'Baofeng_5RM', 'Baofeng_K5-Plus', 'Radtel_RT-730', + 'TIDRADIO_TD-H8-HAM', ] def _test_radio_override_immutable_policy(self, rclass): From 85896b6ccd172d6a4ac5f669e4ea614caf3d3060 Mon Sep 17 00:00:00 2001 From: Jim Unroe Date: Mon, 12 Aug 2024 15:30:26 -0700 Subject: [PATCH 3/7] btech: Handle out-of-range reset time setting Fixes #11461 --- chirp/drivers/btech.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/chirp/drivers/btech.py b/chirp/drivers/btech.py index d40017538..f5a384881 100644 --- a/chirp/drivers/btech.py +++ b/chirp/drivers/btech.py @@ -2548,12 +2548,16 @@ def apply_dmtf_listvalue(setting, obj): val])) dtmf_dec_settings.append(line) else: + if _mem.dtmf_settings.resettime > 0x4F: + val = 0x4F + else: + val = _mem.dtmf_settings.resettime line = RadioSetting( "dtmf_settings.resettime", "Reset time", RadioSettingValueList(LIST_5TONE_RESET, LIST_5TONE_RESET[ - _mem.dtmf_settings.resettime])) + val])) dtmf_dec_settings.append(line) if _mem.dtmf_settings.delayproctime > 0x27: From 87bdc660a3453b1911da021761b492b5cab5ec1f Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 12 Aug 2024 15:41:36 -0700 Subject: [PATCH 4/7] Add Radioddity DB50 model alias Fixes #11472 --- chirp/share/model_alias_map.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chirp/share/model_alias_map.yaml b/chirp/share/model_alias_map.yaml index 2b1bdd2a0..cde22e1d9 100644 --- a/chirp/share/model_alias_map.yaml +++ b/chirp/share/model_alias_map.yaml @@ -227,6 +227,8 @@ R&L Electronics: Radioddity: - alt: Radioddity UV-5G model: UV-5X +- alt: AnyTone 5888UV + model: DB50 Radtel: - alt: Retevis RT22 model: RT-10 From 6069ec4436b86ca435c162c2ba41db2d6342b24c Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 12 Aug 2024 17:11:07 -0700 Subject: [PATCH 5/7] uv17Pro: Note the A/B selection byte Fixes #11452 --- chirp/drivers/baofeng_uv17Pro.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chirp/drivers/baofeng_uv17Pro.py b/chirp/drivers/baofeng_uv17Pro.py index 99e7af1ed..c2cdf78c7 100644 --- a/chirp/drivers/baofeng_uv17Pro.py +++ b/chirp/drivers/baofeng_uv17Pro.py @@ -361,7 +361,7 @@ class UV17Pro(bfc.BaofengCommonHT): u8 rpttailclear; u8 rpttaildet; u8 roger; - u8 unknown2; + u8 a_or_b_selected; // a=0, b=1 u8 fmenable; u8 chbworkmode:4, chaworkmode:4; From 3a14a5943f330b5d434cde8f3b08b744191e391f Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 12 Aug 2024 18:29:50 -0700 Subject: [PATCH 6/7] tdh3: Fix VFO power level settings Same treatment as the memory channels, but for the VFOs. Fixes #11471 --- chirp/drivers/tdh8.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/chirp/drivers/tdh8.py b/chirp/drivers/tdh8.py index 4afa5139b..1d44e9159 100644 --- a/chirp/drivers/tdh8.py +++ b/chirp/drivers/tdh8.py @@ -741,14 +741,12 @@ # AB CHANNEL A_OFFSET = ["Off", "-", "+"] -A_TX_POWER = ["Low", "Mid", "High"] A_BAND = ["Wide", "Narrow"] A_BUSYLOCK = ["Off", "On"] A_SPEC_QTDQT = ["Off", "On"] A_WORKMODE = ["VFO", "VFO+CH", "CH Mode"] B_OFFSET = ["Off", "-", "+"] -B_TX_POWER = ["Low", "Mid", "High"] B_BAND = ["Wide", "Narrow"] B_BUSYLOCK = ["Off", "On"] B_SPEC_QTDQT = ["Off", "On"] @@ -1719,9 +1717,15 @@ def _filter(name): A_OFFSET, A_OFFSET[_vfoa.offset])) abblock.append(rs) + try: + self._tx_power[_vfoa.lowpower] + cur_a_power = _vfoa.lowpower + except IndexError: + cur_a_power = 0 rs = RadioSetting("lowpower", "A TX Power", RadioSettingValueList( - A_TX_POWER, A_TX_POWER[_vfoa.lowpower])) + [str(x) for x in self._tx_power], + str(self._tx_power[cur_a_power]))) abblock.append(rs) rs = RadioSetting("wide", "A Band", @@ -1781,9 +1785,15 @@ def _filter(name): B_OFFSET, B_OFFSET[_vfob.offsetb])) abblock.append(rs) + try: + self._tx_power[_vfob.lowpowerb] + cur_b_power = _vfob.lowpowerb + except IndexError: + cur_b_power = 0 rs = RadioSetting("lowpowerb", "B TX Power", RadioSettingValueList( - B_TX_POWER, B_TX_POWER[_vfob.lowpowerb])) + [str(x) for x in self._tx_power], + str(self._tx_power[cur_b_power]))) abblock.append(rs) rs = RadioSetting("wideb", "B Band", From 78d7f1f9575d5d4ddc6bdfbb1c9a87b585ad8db9 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Tue, 13 Aug 2024 14:45:12 -0700 Subject: [PATCH 7/7] ga510v2: Fix power level handling The GA510v2 has two bits for a three-level power value, unlike the UV-17 it inherits from. This splits the channel def apart to fix that. Fixes #11475 --- chirp/drivers/baofeng_uv17.py | 6 ++++-- chirp/drivers/ga510.py | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/chirp/drivers/baofeng_uv17.py b/chirp/drivers/baofeng_uv17.py index 09b7da0ec..52cd3219a 100644 --- a/chirp/drivers/baofeng_uv17.py +++ b/chirp/drivers/baofeng_uv17.py @@ -196,7 +196,7 @@ class UV17(baofeng_uv17Pro.UV17Pro): LIST_MODE = ["Name", "Frequency"] CHANNELS = 999 - MEM_DEFS = """ + CHANNEL_DEF = """ struct channel { lbcd rxfreq[4]; lbcd txfreq[4]; @@ -215,6 +215,8 @@ class UV17(baofeng_uv17Pro.UV17Pro): scan:1; u8 unknown4; }; + """ + MEM_DEFS = """ struct channelname { char name[11]; }; @@ -320,7 +322,7 @@ class UV17(baofeng_uv17Pro.UV17Pro): struct ani ani; """ - MEM_FORMAT = MEM_DEFS + MEM_LAYOUT + MEM_FORMAT = CHANNEL_DEF + MEM_DEFS + MEM_LAYOUT def _make_frame(self, cmd, addr, length, data=""): """Pack the info in the header format""" diff --git a/chirp/drivers/ga510.py b/chirp/drivers/ga510.py index 13d426e8f..1642a9011 100644 --- a/chirp/drivers/ga510.py +++ b/chirp/drivers/ga510.py @@ -1141,6 +1141,26 @@ class RadioddityGA510v2(baofeng_uv17.UV17): LIST_MODE = ["Name", "Frequency"] CHANNELS = 128 + CHANNEL_DEF = """ + struct channel { + lbcd rxfreq[4]; + lbcd txfreq[4]; + u8 unused1; + ul16 rxtone; + ul16 txtone; + u8 unknown1:1, + bcl:1, + pttid:2, + unknown2:1, + wide:1, + lowpower:2; + u8 scode:4, + unknown3:3, + scan:1; + u8 unknown4; + }; + """ + MEM_LAYOUT = """ #seekto 0x1000; struct settings settings; @@ -1157,6 +1177,6 @@ class RadioddityGA510v2(baofeng_uv17.UV17): #seekto 0x400B; struct channelname names1[128]; """ - MEM_FORMAT = baofeng_uv17.UV17.MEM_DEFS + MEM_LAYOUT + MEM_FORMAT = CHANNEL_DEF + baofeng_uv17.UV17.MEM_DEFS + MEM_LAYOUT _has_workmode_support = False