# HG changeset patch # User Richard Cochran ag6qr@sonic.net # Date 1426564842 25200 # Mon Mar 16 21:00:42 2015 -0700 # Node ID 5c8ac5597f34af143915667c51ed5882e97e30f7 # Parent b15013e7ded2bfb5147128388ad0765ed017b6de [ft2900] Support cross tones (#2433) This patch adds support for cross tones to the FT2900/FT1900 driver. It allows all combinations of CTCSS and DTCS for transmit and receive, including using one CTCSS tone for sending, and a different CTCSS tone for receiving. This also includes a minor change to memedit.py, to support the proper column hiding/unhiding for TSQL-R. The TSQL-R is "reverse tone squelch", and has the same data, and thus the same columns shown/hidden, as in ordinary TSQL. But on TSQL-R, the radio behavior is different. Squelch is broken only if the tone does NOT match the stored tone.
diff -r b15013e7ded2 -r 5c8ac5597f34 chirp/drivers/ft2900.py --- a/chirp/drivers/ft2900.py Sat Mar 14 17:13:02 2015 -0700 +++ b/chirp/drivers/ft2900.py Mon Mar 16 21:00:42 2015 -0700 @@ -205,17 +205,19 @@ tmode:3; u8 name[6]; bbcd offset[3]; - u8 tone; + u8 ctone; + u8 rx_dtcs; + u8 unknown5; + u8 rtone; u8 dtcs; - u8 unknown5; - u8 tone2; - u8 dtcs2; } memory[200];
"""
MODES = ["FM", "NFM"] -TMODES = ["", "Tone", "TSQL", "DTCS", "TSQL-R"] +TMODES = ["", "Tone", "TSQL", "DTCS", "TSQL-R", "Cross"] +CROSS_MODES = ["DTCS->", "Tone->DTCS", "DTCS->Tone", + "Tone->Tone", "DTCS->DTCS"] DUPLEX = ["", "-", "+", "split"] POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=75), chirp_common.PowerLevel("Low3", watts=30), @@ -275,13 +277,16 @@ rf.memory_bounds = (0, 199)
rf.can_odd_split = True - rf.has_ctone = False + rf.has_ctone = True + rf.has_rx_dtcs = True + rf.has_cross = True rf.has_dtcs_polarity = False rf.has_bank = False
rf.valid_tuning_steps = STEPS rf.valid_modes = MODES rf.valid_tmodes = TMODES + rf.valid_cross_modes = CROSS_MODES rf.valid_bands = [(136000000, 174000000)] rf.valid_power_levels = POWER_LEVELS rf.valid_duplexes = DUPLEX @@ -348,9 +353,30 @@
mem.offset = chirp_common.fix_rounded_step(int(_mem.offset) * 1000) mem.duplex = DUPLEX[_mem.duplex] - mem.tmode = TMODES[_mem.tmode] - mem.rtone = chirp_common.TONES[_mem.tone] + if _mem.tmode < TMODES.index("Cross"): + mem.tmode = TMODES[_mem.tmode] + mem.cross_mode = CROSS_MODES[0] + else: + mem.tmode = "Cross" + mem.cross_mode = CROSS_MODES[_mem.tmode - TMODES.index("Cross")] + mem.rtone = chirp_common.TONES[_mem.rtone] + mem.ctone = chirp_common.TONES[_mem.ctone] + + # check for unequal ctone/rtone in TSQL mode. map it as a + # cross tone mode + if mem.rtone != mem.ctone and mem.tmode == "TSQL": + mem.tmode = "Cross" + mem.cross_mode = "Tone->Tone" + mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs] + mem.rx_dtcs = chirp_common.DTCS_CODES[_mem.rx_dtcs] + + # check for unequal dtcs/rx_dtcs in DTCS mode. map it as a + # cross tone mode + if mem.dtcs != mem.rx_dtcs and mem.tmode == "DTCS": + mem.tmode = "Cross" + mem.cross_mode = "DTCS->DTCS" + if (int(_mem.name[0]) & 0x80) != 0: mem.name = _decode_name(_mem.name)
@@ -386,11 +412,40 @@ _mem.freq = mem.freq / 1000 _mem.offset = mem.offset / 1000 _mem.duplex = DUPLEX.index(mem.duplex) - _mem.tmode = TMODES.index(mem.tmode) - _mem.tone = chirp_common.TONES.index(mem.rtone) - _mem.tone2 = chirp_common.TONES.index(mem.rtone) - _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) - _mem.dtcs2 = chirp_common.DTCS_CODES.index(mem.dtcs) + if mem.tmode != "Cross": + _mem.tmode = TMODES.index(mem.tmode) + # for the non-cross modes, use ONE tone for both send + # and receive but figure out where to get it from. + if mem.tmode == "TSQL" or mem.tmode == "TSQL-R": + _mem.rtone = chirp_common.TONES.index(mem.ctone) + _mem.ctone = chirp_common.TONES.index(mem.ctone) + else: + _mem.rtone = chirp_common.TONES.index(mem.rtone) + _mem.ctone = chirp_common.TONES.index(mem.rtone) + + # and one tone for dtcs, but this is always the sending one + _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) + _mem.rx_dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) + + else: + _mem.rtone = chirp_common.TONES.index(mem.rtone) + _mem.ctone = chirp_common.TONES.index(mem.ctone) + _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) + _mem.rx_dtcs = chirp_common.DTCS_CODES.index(mem.rx_dtcs) + if mem.cross_mode == "Tone->Tone": + # tone->tone cross mode is treated as + # TSQL, but with separate tones for + # send and receive + _mem.tmode = TMODES.index("TSQL") + elif mem.cross_mode == "DTCS->DTCS": + # DTCS->DTCS cross mode is treated as + # DTCS, but with separate codes for + # send and receive + _mem.tmode = TMODES.index("DTCS") + else: + _mem.tmode = TMODES.index("Cross") + \ + CROSS_MODES.index(mem.cross_mode) + _mem.isnarrow = MODES.index(mem.mode) _mem.step = STEPS.index(mem.tuning_step) _flag["%s_pskip" % nibble] = mem.skip == "P" diff -r b15013e7ded2 -r 5c8ac5597f34 chirp/ui/memedit.py --- a/chirp/ui/memedit.py Sat Mar 14 17:13:02 2015 -0700 +++ b/chirp/ui/memedit.py Mon Mar 16 21:00:42 2015 -0700 @@ -289,7 +289,7 @@ self.col(_("DTCS Rx Code")), self.col(_("DTCS Pol")), self.col(_("Cross Mode"))] - elif tmode == "TSQL": + elif tmode == "TSQL" or tmode == "TSQL-R": if self._features.has_ctone: hide += [self.col(_("Tone"))]
@@ -297,7 +297,7 @@ self.col(_("DTCS Rx Code")), self.col(_("DTCS Pol")), self.col(_("Cross Mode"))] - elif tmode == "DTCS": + elif tmode == "DTCS" or tmode == "DTCS-R": hide += [self.col(_("Tone")), self.col(_("ToneSql")), self.col(_("Cross Mode")),