aboutsummaryrefslogtreecommitdiff
path: root/chirp/drivers/ft818.py
diff options
context:
space:
mode:
Diffstat (limited to 'chirp/drivers/ft818.py')
-rwxr-xr-xchirp/drivers/ft818.py342
1 files changed, 342 insertions, 0 deletions
diff --git a/chirp/drivers/ft818.py b/chirp/drivers/ft818.py
new file mode 100755
index 0000000..c7a0a32
--- /dev/null
+++ b/chirp/drivers/ft818.py
@@ -0,0 +1,342 @@
+#
+# Copyright 2012 Filippi Marco <iz3gme.marco@gmail.com>
+# Copyright 2018 Vinny Stipo <v@xpctech.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""FT818 management module"""
+
+from chirp.drivers import ft817
+from chirp import chirp_common, errors, directory
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+ RadioSettingValueInteger, RadioSettingValueList, \
+ RadioSettingValueBoolean, RadioSettingValueString, \
+ RadioSettings
+import os
+import logging
+from textwrap import dedent
+from chirp.util import safe_charset_string
+
+LOG = logging.getLogger(__name__)
+
+
+@directory.register
+class FT818Radio(ft817.FT817Radio):
+
+ """Yaesu FT-818"""
+ BAUD_RATE = 9600
+ MODEL = "FT-818"
+ _model = ""
+ _memsize = 6573
+ _block_lengths = [2, 40, 208, 208, 208, 208, 198, 53, 130, 118, 130]
+
+ MEM_FORMAT = """
+ struct mem_struct {
+ u8 tag_on_off:1,
+ tag_default:1,
+ unknown1:3,
+ mode:3;
+ u8 duplex:2,
+ is_duplex:1,
+ is_cwdig_narrow:1,
+ is_fm_narrow:1,
+ freq_range:3;
+ u8 skip:1,
+ unknown2:1,
+ ipo:1,
+ att:1,
+ unknown3:4;
+ u8 ssb_step:2,
+ am_step:3,
+ fm_step:3;
+ u8 unknown4:6,
+ tmode:2;
+ u8 unknown5:2,
+ tx_mode:3,
+ tx_freq_range:3;
+ u8 unknown6:1,
+ unknown_toneflag:1,
+ tone:6;
+ u8 unknown7:1,
+ dcs:7;
+ ul16 rit;
+ u32 freq;
+ u32 offset;
+ u8 name[8];
+ };
+
+ #seekto 0x4;
+ struct {
+ u8 fst:1,
+ lock:1,
+ nb:1,
+ pbt:1,
+ unknownb:1,
+ dsp:1,
+ agc:2;
+ u8 vox:1,
+ vlt:1,
+ bk:1,
+ kyr:1,
+ unknown5:1,
+ cw_paddle:1,
+ pwr_meter_mode:2;
+ u8 vfob_band_select:4,
+ vfoa_band_select:4;
+ u8 unknowna;
+ u8 backlight:2,
+ color:2,
+ contrast:4;
+ u8 beep_freq:1,
+ beep_volume:7;
+ u8 arts_beep:2,
+ main_step:1,
+ cw_id:1,
+ scope:1,
+ pkt_rate:1,
+ resume_scan:2;
+ u8 op_filter:2,
+ lock_mode:2,
+ cw_pitch:4;
+ u8 sql_rf_gain:1,
+ ars_144:1,
+ ars_430:1,
+ cw_weight:5;
+ u8 cw_delay;
+ u8 unknown8:1,
+ sidetone:7;
+ u8 batt_chg:2,
+ cw_speed:6;
+ u8 disable_amfm_dial:1,
+ vox_gain:7;
+ u8 cat_rate:2,
+ emergency:1,
+ vox_delay:5;
+ u8 dig_mode:3,
+ mem_group:1,
+ unknown9:1,
+ apo_time:3;
+ u8 dcs_inv:2,
+ unknown10:1,
+ tot_time:5;
+ u8 mic_scan:1,
+ ssb_mic:7;
+ u8 mic_key:1,
+ am_mic:7;
+ u8 unknown11:1,
+ fm_mic:7;
+ u8 unknown12:1,
+ dig_mic:7;
+ u8 extended_menu:1,
+ pkt_mic:7;
+ u8 unknown14:1,
+ pkt9600_mic:7;
+ il16 dig_shift;
+ il16 dig_disp;
+ i8 r_lsb_car;
+ i8 r_usb_car;
+ i8 t_lsb_car;
+ i8 t_usb_car;
+ u8 unknown15:2,
+ menu_item:6;
+ u8 unknown16:4,
+ menu_sel:4;
+ u16 unknown17;
+ u8 art:1,
+ scn_mode:2,
+ dw:1,
+ pri:1,
+ unknown18:1,
+ tx_power:2;
+ u8 spl:1,
+ unknown:1,
+ uhf_antenna:1,
+ vhf_antenna:1,
+ air_antenna:1,
+ bc_antenna:1,
+ sixm_antenna:1,
+ hf_antenna:1;
+ } settings;
+
+ #seekto 0x2A;
+ struct mem_struct vfoa[16];
+ struct mem_struct vfob[16];
+ struct mem_struct home[4];
+ struct mem_struct qmb;
+ struct mem_struct mtqmb;
+ struct mem_struct mtune;
+
+ #seekto 0x431;
+ u8 visible[25];
+ u8 pmsvisible;
+
+ #seekto 0x44B;
+ u8 filled[25];
+ u8 pmsfilled;
+
+ #seekto 0x465;
+ struct mem_struct memory[200];
+ struct mem_struct pms[2];
+
+ #seekto 0x1903;
+ u8 callsign[7];
+
+ #seekto 0x19AD;
+ struct mem_struct sixtymeterchannels[5];
+ """
+
+ SPECIAL_MEMORIES = {
+ "VFOa-1.8M": -37,
+ "VFOa-3.5M": -36,
+ "VFOa-5M": -35,
+ "VFOa-7M": -34,
+ "VFOa-10M": -33,
+ "VFOa-14M": -32,
+ "VFOa-18M": -31,
+ "VFOa-21M": -30,
+ "VFOa-24M": -29,
+ "VFOa-28M": -28,
+ "VFOa-50M": -27,
+ "VFOa-FM": -26,
+ "VFOa-AIR": -25,
+ "VFOa-144": -24,
+ "VFOa-430": -23,
+ "VFOa-HF": -22,
+ "VFOb-1.8M": -21,
+ "VFOb-3.5M": -20,
+ "VFOb-5M": -19,
+ "VFOb-7M": -18,
+ "VFOb-10M": -17,
+ "VFOb-14M": -16,
+ "VFOb-18M": -15,
+ "VFOb-21M": -14,
+ "VFOb-24M": -13,
+ "VFOb-28M": -12,
+ "VFOb-50M": -11,
+ "VFOb-FM": -10,
+ "VFOb-AIR": -9,
+ "VFOb-144": -8,
+ "VFOb-430": -7,
+ "VFOb-HF": -6,
+ "HOME HF": -5,
+ "HOME 50M": -4,
+ "HOME 144": -3,
+ "HOME 430": -2,
+ "QMB": -1,
+ }
+ FIRST_VFOB_INDEX = -6
+ LAST_VFOB_INDEX = -21
+ FIRST_VFOA_INDEX = -22
+ LAST_VFOA_INDEX = -37
+
+ SPECIAL_PMS = {
+ "PMS-L": -39,
+ "PMS-U": -38,
+ }
+ LAST_PMS_INDEX = -39
+
+ SPECIAL_MEMORIES.update(SPECIAL_PMS)
+
+ SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
+ SPECIAL_MEMORIES.keys()))
+
+
+@directory.register
+class FT818NDUSRadio(FT818Radio):
+
+ """Yaesu FT-818ND (US version)"""
+ MODEL = "FT-818ND (US)"
+
+ _model = ""
+ _US_model = True
+ _memsize = 6703
+
+ _block_lengths = [2, 40, 208, 208, 208, 208, 198, 53, 130, 118, 130, 130]
+
+ SPECIAL_60M = {
+ "M-601": -44,
+ "M-602": -43,
+ "M-603": -42,
+ "M-604": -41,
+ "M-605": -40,
+ }
+ LAST_SPECIAL60M_INDEX = -44
+
+ SPECIAL_MEMORIES = dict(FT818Radio.SPECIAL_MEMORIES)
+ SPECIAL_MEMORIES.update(SPECIAL_60M)
+
+ SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
+ SPECIAL_MEMORIES.keys()))
+
+ def _get_special_60m(self, number):
+ mem = chirp_common.Memory()
+ mem.number = self.SPECIAL_60M[number]
+ mem.extd_number = number
+
+ _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
+ mem.number]
+
+ mem = self._get_memory(mem, _mem)
+
+ mem.immutable = ["number", "rtone", "ctone",
+ "extd_number", "name", "dtcs", "tmode", "cross_mode",
+ "dtcs_polarity", "power", "duplex", "offset",
+ "comment", "empty"]
+
+ return mem
+
+ def _set_special_60m(self, mem):
+ if mem.empty:
+ # can't delete 60M memories!
+ raise Exception("Sorry, 60M memory can't be deleted")
+
+ cur_mem = self._get_special_60m(self.SPECIAL_MEMORIES_REV[mem.number])
+
+ for key in cur_mem.immutable:
+ if cur_mem.__dict__[key] != mem.__dict__[key]:
+ raise errors.RadioError("Editing field `%s' " % key +
+ "is not supported on M-60x channels")
+
+ if mem.mode not in ["USB", "LSB", "CW", "CWR", "NCW", "NCWR", "DIG"]:
+ raise errors.RadioError("Mode {mode} is not valid "
+ "in 60m channels".format(mode=mem.mode))
+ _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
+ mem.number]
+ self._set_memory(mem, _mem)
+
+ def get_memory(self, number):
+ if number in self.SPECIAL_60M.keys():
+ return self._get_special_60m(number)
+ elif number < 0 and \
+ self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_60M.keys():
+ # I can't stop delete operation from loosing extd_number but
+ # I know how to get it back
+ return self._get_special_60m(self.SPECIAL_MEMORIES_REV[number])
+ else:
+ return FT818Radio.get_memory(self, number)
+
+ def set_memory(self, memory):
+ if memory.number in self.SPECIAL_60M.values():
+ return self._set_special_60m(memory)
+ else:
+ return FT818Radio.set_memory(self, memory)
+
+ def get_settings(self):
+ top = FT818Radio.get_settings(self)
+ basic = top[0]
+ rs = RadioSetting("emergency", "Emergency",
+ RadioSettingValueBoolean(
+ self._memobj.settings.emergency))
+ basic.append(rs)
+ return top