From 075233c09051bfce58b6ecc81455725737516839 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Tue, 31 Dec 2024 10:20:02 -0800 Subject: [PATCH] rt21: Fix DTCS decoding when stored in hex Apparently this radio has a bit for whether or not the DTCS code is stored in hex or octal. CHIRP was only supporting octal format, but radios with codes stored in hex were found in the wild and we, of course, fail to decode those. Fixes #11749 --- chirp/drivers/retevis_rt21.py | 41 +++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/chirp/drivers/retevis_rt21.py b/chirp/drivers/retevis_rt21.py index b060eea0..a6637fc0 100644 --- a/chirp/drivers/retevis_rt21.py +++ b/chirp/drivers/retevis_rt21.py @@ -767,6 +767,8 @@ class RT21Radio(chirp_common.CloneModeRadio): _skipflags = True _reserved = False _mask = 0x2000 # bit mask to identify DTCS tone decoding is used + _dcs_octal = 0x0800 # bit mask to identify DTCS stored in octal + _dcs_inverse = 0x8000 # bit mask to identify inverted DTCS codes _gmrs = _frs = _pmr = False _echo = False @@ -839,9 +841,29 @@ def get_raw_memory(self, number): return repr(self._memobj.memory[number - 1]) def _get_tone(self, _mem, mem): + # 0xA662 = 662R = 1010 0... + # 0xA9DC = 734R = 1010 1... + # 0x29D3 = 723N - 0010 1... + def _get_dcs(val): - code = int("%03o" % (val & 0x07FF)) - pol = (val & 0x8000) and "R" or "N" + # 0x0800 means code is stored in hex instead of ocal (?!) + if val & self._dcs_octal: + code = int("%03o" % (val & 0x07FF)) + else: + try: + code = int("%03x" % (val & 0x07FF)) + if code not in chirp_common.DTCS_CODES: + raise ValueError('DCS code assumed to be wrong') + except ValueError: + # Memories may have been stored as octal but without the + # proper bit flag in the past, so if we see something + # recorded as "should be hex" but interpretation as hex + # yields an invalid code, assume it's actually octal and + # parse it as such. + LOG.warning('Trying DCS conversion of 0x%04x as octal ' + 'for compatibility', val) + code = int("%03o" % (val & 0x07FF)) + pol = (val & self._dcs_inverse) and "R" or "N" return code, pol tpol = False @@ -1129,9 +1151,10 @@ def get_memory(self, number): def _set_tone(self, mem, _mem): def _set_dcs(code, pol): - val = int("%i" % code, 8) + self._mask + val = int("%i" % code, 8) if pol == "R": - val += 0x8000 + val |= self._dcs_inverse + val |= self._mask | self._dcs_octal return val rx_mode = tx_mode = None @@ -1919,7 +1942,6 @@ class RB26Radio(RT21Radio): _ack_1st_block = False _skipflags = True _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _gmrs = True _ranges = [ @@ -1956,7 +1978,6 @@ class RT76Radio(RT21Radio): _ack_1st_block = False _skipflags = False _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _gmrs = True _ranges = [ @@ -2038,7 +2059,6 @@ class RB23Radio(RT21Radio): _ack_1st_block = False _skipflags = True _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _gmrs = True _ranges = [ @@ -2071,7 +2091,6 @@ class RT19Radio(RT21Radio): _ack_1st_block = False _skipflags = False _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _frs = True _ranges = [ @@ -2100,7 +2119,6 @@ class RT619Radio(RT19Radio): 0x100, # memory start _upper # number of freqhops ) - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _frs = False _pmr = True @@ -2128,7 +2146,6 @@ class AR63Radio(RT21Radio): _ack_1st_block = False _skipflags = True _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _gmrs = False _ranges = [ @@ -2162,7 +2179,6 @@ class RT40BRadio(RT21Radio): _ack_1st_block = False _skipflags = True _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _gmrs = True _echo = True @@ -2194,7 +2210,6 @@ class RB28BRadio(RT21Radio): _ack_1st_block = False _skipflags = False _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _frs = True _ranges = [ @@ -2218,7 +2233,6 @@ class RB628BRadio(RB28BRadio): _magic = b"PHOGR\x09\xB2" _fingerprint = [b"P32073" + b"\x02\xFF", ] _upper = 16 - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _frs = False _pmr = True @@ -2243,7 +2257,6 @@ class RT86Radio(RT21Radio): _ack_1st_block = False _skipflags = True _reserved = True - _mask = 0x2800 # bit mask to identify DTCS tone decoding is used _ranges = [ (0x0000, 0x01A0),