From 14cc93e3524ee3f23d246abc28665f66c8bf064d Mon Sep 17 00:00:00 2001 From: N8TW Date: Sat, 6 Feb 2021 16:55:05 -0500 Subject: [PATCH] Added Features: targetable VFO Other: added debug statements, foundation-work for new featues, "modernized" a bit (but still needs additional effort). --- rigs/yaesu/ft980.c | 1195 +++++++++++++++++++++++++++++--------------- rigs/yaesu/ft980.h | 460 +++++++++++++++++ 2 files changed, 1263 insertions(+), 392 deletions(-) create mode 100644 rigs/yaesu/ft980.h diff --git a/rigs/yaesu/ft980.c b/rigs/yaesu/ft980.c index 072e58e22..1d3a741df 100644 --- a/rigs/yaesu/ft980.c +++ b/rigs/yaesu/ft980.c @@ -2,6 +2,8 @@ * ft980.c - (C) Stephane Fillod 2004-2010 * (C) Wolfgang Buesser 2010 * + * (C) Mathew Breton 2021 + * * This shared library provides an API for communicating * via serial interface to an FT-980 using the "CAT" interface * @@ -22,6 +24,66 @@ * */ + +/* +* FT-980 Hamlib API functions considered to be Stable: +* sadly, none yet +* +* Functions considered to be Beta: +* init * cleanup +* set_freq * get_freq +* set_mode * get_mode +* set_mem * get_mem +* open * close +* +* Functions considered to be Alpha: +* set_vfo * get_vfo +* +* Functions not yet implemented +* get_xit * set_xit +* set_func * get_func +* get_ptt * set_ptt +* get_dcd +* set_rptr_shift * get_rptr_shift +* set_rptr_offs * get_rptr_offs +* set_split_freq * get_split_freq +* set_split_mode * get_split_mode +* set_split_freq_mode * get_split_freq_mode +* set_split_vfo * get_split_vfo +* set_ts * get_ts +* vfo_op +* +* Functions the radio does not support: see readme.ft980 for more details +* power2mW * mW2power +* newcat_get_ant * newcat_set_ant +* set_dcs_code * get_dcs_code +* set_tone * get_tone +* set_ctcss_tone * get_ctcss_tone +* set_dcs_sql * get_dcs_sql +* set_tone_sql * get_tone_sql +* set_ctcss_sql * get_ctcss_sql +* set_powerstat * get_powerstat +* set_ant * get_ant +* send_dtmf * recv_dtmf +* send_morse * stop_morse +* wait_morse * send_voice_mem +* set_trn * get_trn +* set_channel * get_channel +* set_bank * scan +* set_parm * get_parm +* get_info +* reset +* set_vfo_opt +* decode_event +* +* No idea yet what these do +* set_chan_all_cb +* get_chan_all_cb +* set_conf +* get_conf +*/ + + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -29,68 +91,14 @@ #include #include /* String function definitions */ #include /* UNIX standard function definitions */ +#include /* for timeofday call */ #include "hamlib/rig.h" #include "serial.h" #include "misc.h" #include "bandplan.h" #include "yaesu.h" - -#define FT980_MODES (RIG_MODE_LSB|RIG_MODE_USB|RIG_MODE_CW|RIG_MODE_AM|RIG_MODE_RTTY|RIG_MODE_FM) - -#define FT980_ANTS (RIG_ANT_1) - -/* TODO: RIG_VFO_HAM|RIG_VFO_GEN ? */ -#define FT980_VFOS (RIG_VFO_MAIN) - -/* TODO: RIG_OP_TO_VFO|RIG_OP_FROM_VFO|RIG_OP_BAND_UP|RIG_OP_BAND_DOWN */ -#define FT980_VFO_OPS (RIG_OP_NONE) - -typedef struct _ft980_memory_t -{ - unsigned char mem_16[4]; unsigned char vfo_16; unsigned char mode_16; - unsigned char mem_15[4]; unsigned char vfo_15; unsigned char mode_15; - unsigned char mem_14[4]; unsigned char vfo_14; unsigned char mode_14; - unsigned char mem_13[4]; unsigned char vfo_13; unsigned char mode_13; - unsigned char mem_12[4]; unsigned char vfo_12; unsigned char mode_12; - unsigned char mem_11[4]; unsigned char vfo_11; unsigned char mode_11; - unsigned char mem_10[4]; unsigned char vfo_10; unsigned char mode_10; - unsigned char mem_9[4]; unsigned char vfo_9; unsigned char mode_9; - unsigned char mem_8[4]; unsigned char vfo_8; unsigned char mode_8; - unsigned char mem_7[4]; unsigned char vfo_7; unsigned char mode_7; - unsigned char mem_6[4]; unsigned char vfo_6; unsigned char mode_6; - unsigned char mem_5[4]; unsigned char vfo_5; unsigned char mode_5; - unsigned char mem_4[4]; unsigned char vfo_4; unsigned char mode_4; - unsigned char mem_3[4]; unsigned char vfo_3; unsigned char mode_3; - unsigned char mem_2[4]; unsigned char vfo_2; unsigned char mode_2; - unsigned char mem_1[4]; unsigned char vfo_1; unsigned char mode_1; - unsigned char CLAR[4]; - unsigned char GEN[4]; unsigned char HAM[4]; unsigned char vfo; - unsigned char mode; - unsigned char ff_1[4]; - unsigned char ff_2[4]; - unsigned char vfo_mem; - unsigned char mode_mem; - unsigned char LDB; - unsigned char EXT_CTL; - unsigned char IF_SHIFT; - unsigned char SPLIT_CODE; - unsigned char FSK_SHIFT; - unsigned char IF_WIDTH; - unsigned char MEM_SHIFT; - unsigned char CLAR_FLAG; - unsigned char TAB_FLAG; - unsigned char SELECT_SW; - unsigned char OFFSET_SW; - unsigned char MODE_SW; - unsigned char MEM_CH_SW; - unsigned char LOW_TAB[4]; - unsigned char UP_TAB[4]; - unsigned char VFO_STATUS; - unsigned char OP_MODE; - unsigned char OP_FREQ[4]; - unsigned char STATUS_FLAG; -} _ft980_memory_t; +#include "ft980.h" /* * Private data @@ -98,176 +106,38 @@ typedef struct _ft980_memory_t struct ft980_priv_data { _ft980_memory_t update_data; /* returned data */ + vfo_t current_vfo; /* active VFO from last cmd */ struct timeval status_tv; /* update_data caching */ }; -#define UPDATE_DATA_OFS(p, o) (((unsigned char*)((p)+1))-(o)) - -static const char cmd_OK[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x0B}; -static const char cmd_ON_OFF[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x00}; - -/* Private helper function prototypes */ - - +/************************************************************************************* + * Private Prototype Declarations + */ static int ft980_transaction(RIG *rig, const unsigned char *cmd, unsigned char *data, int expected_len); static int ft980_get_status_data(RIG *rig); -static int ft980_open(RIG *rig); -static int ft980_close(RIG *rig); - -static int ft980_set_freq(RIG *rig, vfo_t vfo, freq_t freq); -static int ft980_get_freq(RIG *rig, vfo_t vfo, freq_t *freq); -static int ft980_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width); -static int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width); - -static int ft980_set_mem(RIG *rig, vfo_t vfo, int ch); -static int ft980_get_mem(RIG *rig, vfo_t vfo, int *ch); - -#if 0 -static int ft980_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, - vfo_t tx_vfo); -static int ft980_set_split_freq(RIG *rig, vfo_t vfo, freq_t freq); -static int ft980_set_split_mode(RIG *rig, vfo_t vfo, rmode_t mode, - pbwidth_t width); - -static int ft980_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val); -static int ft980_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t shift); -static int ft980_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs); -#endif - -/* - * ft980 rigs capabilities. - */ -#define FT980_MEM_CAP { \ - .freq = 1, \ - .mode = 1, \ - .width = 1, \ -} - -#define FT980_CACHE_TIMEOUT 500 /* ms */ - -/* - * ft980 rigs capabilities. - * - * Protocol is documented in FT 980 Technical Supplement, page 13. - * - * TODO: - */ - -const struct rig_caps ft980_caps = -{ - RIG_MODEL(RIG_MODEL_FT980), - .model_name = "FT-980", - .mfg_name = "Yaesu", - .version = "20200114.0", - .copyright = "LGPL", - .status = RIG_STATUS_ALPHA, - .rig_type = RIG_TYPE_TRANSCEIVER, - .ptt_type = RIG_PTT_SERIAL_RTS, - .dcd_type = RIG_DCD_NONE, - .port_type = RIG_PORT_SERIAL, - .serial_rate_min = 4800, - .serial_rate_max = 4800, - .serial_data_bits = 8, - .serial_stop_bits = 2, - .serial_parity = RIG_PARITY_NONE, - .serial_handshake = RIG_HANDSHAKE_NONE, - .write_delay = 80, - .post_write_delay = 0, - .timeout = 2000, - .retry = 3, - .has_get_func = RIG_FUNC_NONE, - .has_set_func = RIG_FUNC_NONE, - .has_get_level = RIG_LEVEL_NONE, - .has_set_level = RIG_LEVEL_NONE, - .has_get_parm = RIG_PARM_NONE, - .has_set_parm = RIG_PARM_NONE, - .vfo_ops = FT980_VFO_OPS, - .preamp = { RIG_DBLST_END, }, - .attenuator = { RIG_DBLST_END, }, - .max_rit = Hz(10000), - .max_xit = Hz(10000), - .max_ifshift = Hz(1500), - .targetable_vfo = RIG_TARGETABLE_NONE, - .transceive = RIG_TRN_OFF, - .bank_qty = 0, - .chan_desc_sz = 0, - - .chan_list = { - {1, 16, RIG_MTYPE_MEM, FT980_MEM_CAP}, - }, - - .rx_range_list1 = { - {kHz(150), MHz(30) - 100, FT980_MODES, -1, -1, FT980_VFOS, FT980_ANTS}, - RIG_FRNG_END, - }, - - .tx_range_list1 = { - FRQ_RNG_HF(1, RIG_MODE_SSB | RIG_MODE_CW, W(5), W(100), FT980_VFOS, FT980_ANTS), - FRQ_RNG_HF(1, RIG_MODE_FM | RIG_MODE_RTTY, W(2), W(50), FT980_VFOS, FT980_ANTS), - FRQ_RNG_HF(1, RIG_MODE_AM, W(2), W(25), FT980_VFOS, FT980_ANTS), - RIG_FRNG_END, - }, - - .rx_range_list2 = { - {kHz(150), MHz(30) - 100, FT980_MODES, -1, -1, FT980_VFOS, FT980_ANTS}, - RIG_FRNG_END, - }, - - .tx_range_list2 = { - FRQ_RNG_HF(2, RIG_MODE_SSB | RIG_MODE_CW, W(5), W(100), FT980_VFOS, FT980_ANTS), - FRQ_RNG_HF(2, RIG_MODE_FM | RIG_MODE_RTTY, W(2), W(50), FT980_VFOS, FT980_ANTS), - FRQ_RNG_HF(2, RIG_MODE_AM, W(2), W(25), FT980_VFOS, FT980_ANTS), - RIG_FRNG_END, - }, - - .tuning_steps = { - {FT980_MODES, Hz(10)}, - {FT980_MODES, kHz(5)}, - {FT980_MODES, kHz(500)}, - RIG_TS_END, - }, - - /* mode/filter list, remember: order matters! */ - .filters = { - {RIG_MODE_SSB | RIG_MODE_CW | RIG_MODE_RTTY, kHz(2.5)}, - {RIG_MODE_CW, Hz(300)}, - {RIG_MODE_FM, kHz(12)}, - {RIG_MODE_AM, kHz(5)}, - {RIG_MODE_AM, kHz(3)}, - - RIG_FLT_END, - }, - - .rig_open = ft980_open, - .rig_close = ft980_close, - - .set_freq = ft980_set_freq, - .get_freq = ft980_get_freq, - .set_mode = ft980_set_mode, - .get_mode = ft980_get_mode, - - .set_mem = ft980_set_mem, - .get_mem = ft980_get_mem, - -#ifdef XXREMOVEDXX - .get_level = ft980_get_level, - .set_level = ft980_set_level, - - .set_split_vfo = ft980_set_split_vfo, - .set_split_freq = ft980_set_split_freq, - .set_split_mode = ft980_set_split_mode, - - .set_rptr_shift = ft980_set_rptr_shift, - .set_rptr_offs = ft980_set_rptr_offs, -#endif -}; - +/* Dump routines are for debug purposes */ +static void dump_freq(unsigned char *data); +static void dump_vfo(unsigned char data); +static void dump_mode(unsigned char data); +static void dump_switch(unsigned char data); +static void dump_if_shift(unsigned char data); +static void dump_rptr_split_code(unsigned char data); +static void dump_fsk_shift(unsigned char data); +static void dump_if_width(unsigned char data); +static void dump_mem_shift_flag(unsigned char data); +static void dump_clar_flag(unsigned char data); +static void dump_tab_flag(unsigned char data); +static void dump_freq_select_sws(unsigned char data); +static void dump_mode_sw(unsigned char data); +static void dump_mem_ch_sw(unsigned char data); +static void dump_status_flag_bits(unsigned char data); +static void dump_memory(_ft980_memory_t *memory); static void dump_freq(unsigned char *data) { - rig_debug(RIG_DEBUG_VERBOSE, "%02x%02x%02x%02x ", data[3], data[2], data[1], + rig_debug(RIG_DEBUG_TRACE, "%02x%02x%02x%02x ", data[3], data[2], data[1], data[0]); } @@ -275,32 +145,51 @@ static void dump_vfo(unsigned char data) { switch ((unsigned int)data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "GEN"); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "GEN"); + break; - case 128: rig_debug(RIG_DEBUG_VERBOSE, "%s", "HAM"); break; + case 128: + rig_debug(RIG_DEBUG_TRACE, "%s", "HAM"); + break; } } - static void dump_mode(unsigned char data) { switch ((unsigned int)data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", " LSB\n"); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", " LSB\n"); + break; - case 1: rig_debug(RIG_DEBUG_VERBOSE, "%s", " USB\n"); break; + case 1: + rig_debug(RIG_DEBUG_TRACE, "%s", " USB\n"); + break; - case 2: rig_debug(RIG_DEBUG_VERBOSE, "%s", " CW-W\n"); break; + case 2: + rig_debug(RIG_DEBUG_TRACE, "%s", " CW-W\n"); + break; - case 3: rig_debug(RIG_DEBUG_VERBOSE, "%s", " CW-N\n"); break; + case 3: + rig_debug(RIG_DEBUG_TRACE, "%s", " CW-N\n"); + break; - case 4: rig_debug(RIG_DEBUG_VERBOSE, "%s", " AM-W\n"); break; + case 4: + rig_debug(RIG_DEBUG_TRACE, "%s", " AM-W\n"); + break; - case 5: rig_debug(RIG_DEBUG_VERBOSE, "%s", " AM-N\n"); break; + case 5: + rig_debug(RIG_DEBUG_TRACE, "%s", " AM-N\n"); + break; - case 6: rig_debug(RIG_DEBUG_VERBOSE, "%s", " FSK\n"); break; + case 6: + rig_debug(RIG_DEBUG_TRACE, "%s", " FSK\n"); + break; - case 7: rig_debug(RIG_DEBUG_VERBOSE, "%s", " FM\n"); break; + case 7: + rig_debug(RIG_DEBUG_TRACE, "%s", " FM\n"); + break; } } @@ -308,324 +197,369 @@ static void dump_switch(unsigned char data) { switch ((unsigned int)data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "OFF"); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "OFF"); + break; - case 1: rig_debug(RIG_DEBUG_VERBOSE, "%s", "ON "); break; + case 1: + rig_debug(RIG_DEBUG_TRACE, "%s", "ON "); + break; } } -static void dump_IF_SHIFT(unsigned char data) +static void dump_if_shift(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "IF_SHIFT :\%d\n", data - 15); + rig_debug(RIG_DEBUG_TRACE, "if_shift :\%d\n", data - 15); } -static void dump_SPLIT_CODE(unsigned char data) +static void dump_rptr_split_code(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "SPLIT_CODE :\%02x\n", data); + rig_debug(RIG_DEBUG_TRACE, "rptr_split_code :\%02x\n", data); } -static void dump_FSK_SHIFT(unsigned char data) +static void dump_fsk_shift(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "FSK_SHIFT :\%02x\n", data); + rig_debug(RIG_DEBUG_TRACE, "fsk_shift :\%02x\n", data); } -static void dump_IF_WIDTH(unsigned char data) +static void dump_if_width(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "IF_WIDTH :\%d\n", data); + rig_debug(RIG_DEBUG_TRACE, "if_width :\%d\n", data); } -static void dump_MEM_SHIFT(unsigned char data) +static void dump_mem_shift_flag(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "MEM_SHIFT :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_shift_flag :"); switch ((unsigned int)data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "OFF\n"); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "OFF\n"); + break; - case 16: rig_debug(RIG_DEBUG_VERBOSE, "%s", "ON\n"); break; + case 16: + rig_debug(RIG_DEBUG_TRACE, "%s", "ON\n"); + break; } } -static void dump_CLAR_FLAG(unsigned char data) + +static void dump_clar_flag(unsigned char data) { unsigned char RX_CLAR = data & 0x20; unsigned char TX_CLAR = data & 0x40; - rig_debug(RIG_DEBUG_VERBOSE, "%s", "CLAR_SHIFT RX/TX:"); + rig_debug(RIG_DEBUG_TRACE, "%s", "CLAR_SHIFT RX/TX:"); switch ((unsigned int)RX_CLAR) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "OFF "); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "OFF "); + break; - case 0x20: rig_debug(RIG_DEBUG_VERBOSE, "%s", "ON "); break; + case 0x20: + rig_debug(RIG_DEBUG_TRACE, "%s", "ON "); + break; } switch ((unsigned int)TX_CLAR) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", " OFF "); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", " OFF "); + break; - case 0x40: rig_debug(RIG_DEBUG_VERBOSE, "%s", " ON "); break; + case 0x40: + rig_debug(RIG_DEBUG_TRACE, "%s", " ON "); + break; } - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); } -static void dump_TAB_FLAG(unsigned char data) +static void dump_tab_flag(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "TAB FLAG :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "TAB FLAG :"); switch (data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "OFF\n"); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "OFF\n"); + break; - case 0x80: rig_debug(RIG_DEBUG_VERBOSE, "%s", "ON\n"); break; + case 0x80: + rig_debug(RIG_DEBUG_TRACE, "%s", "ON\n"); + break; } } -static void dump_SELECT_SW(unsigned char data) +static void dump_freq_select_sws(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "SELECT_SW :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "freq_select_sws :"); switch ((unsigned int)data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "VFO "); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "VFO "); + break; - case 1: rig_debug(RIG_DEBUG_VERBOSE, "%s", "MR "); break; + case 1: + rig_debug(RIG_DEBUG_TRACE, "%s", "MR "); + break; - case 2: rig_debug(RIG_DEBUG_VERBOSE, "%s", "RX_M"); break; + case 2: + rig_debug(RIG_DEBUG_TRACE, "%s", "RX_M"); + break; - case 3: rig_debug(RIG_DEBUG_VERBOSE, "%s", "RX_V"); break; + case 3: + rig_debug(RIG_DEBUG_TRACE, "%s", "RX_V"); + break; } - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); } -static void dump_MODE_SW(unsigned char data) +static void dump_mode_sw(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "MODE_SW :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mode_sw :"); switch ((unsigned int)data) { - case 0: rig_debug(RIG_DEBUG_VERBOSE, "%s", "LSB "); break; + case 0: + rig_debug(RIG_DEBUG_TRACE, "%s", "LSB "); + break; - case 1: rig_debug(RIG_DEBUG_VERBOSE, "%s", "USB "); break; + case 1: + rig_debug(RIG_DEBUG_TRACE, "%s", "USB "); + break; - case 2: rig_debug(RIG_DEBUG_VERBOSE, "%s", "CW-W"); break; + case 2: + rig_debug(RIG_DEBUG_TRACE, "%s", "CW-W"); + break; - case 3: rig_debug(RIG_DEBUG_VERBOSE, "%s", "CW-N"); break; + case 3: + rig_debug(RIG_DEBUG_TRACE, "%s", "CW-N"); + break; - case 4: rig_debug(RIG_DEBUG_VERBOSE, "%s", "AM-W"); break; + case 4: + rig_debug(RIG_DEBUG_TRACE, "%s", "AM-W"); + break; - case 5: rig_debug(RIG_DEBUG_VERBOSE, "%s", "AM-N"); break; + case 5: + rig_debug(RIG_DEBUG_TRACE, "%s", "AM-N"); + break; - case 6: rig_debug(RIG_DEBUG_VERBOSE, "%s", "FSK"); break; + case 6: + rig_debug(RIG_DEBUG_TRACE, "%s", "FSK"); + break; - case 7: rig_debug(RIG_DEBUG_VERBOSE, "%s", "FM"); break; + case 7: + rig_debug(RIG_DEBUG_TRACE, "%s", "FM"); + break; } - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); } -static void dump_MEM_CH_SW(unsigned char data) +static void dump_mem_ch_sw(unsigned char data) { - rig_debug(RIG_DEBUG_VERBOSE, "MEM_CH_SW :%d\n", data + 1); + rig_debug(RIG_DEBUG_TRACE, "mem_ch_sw :%d\n", data + 1); } -static void dump_STATUS_FLAG(unsigned char data) +static void dump_status_flag_bits(unsigned char data) { unsigned char TX = data & 0x01; unsigned char SPLIT = data & 0x08; unsigned char VFO = data & 0x20; unsigned char CLAR = data & 0x40; - rig_debug(RIG_DEBUG_VERBOSE, "%s", "STATUS_FLAG :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "status_flag_bits :"); if (TX) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "TX "); + rig_debug(RIG_DEBUG_TRACE, "%s", "TX "); } else { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "RX "); + rig_debug(RIG_DEBUG_TRACE, "%s", "RX "); } if (SPLIT) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "SPLIT "); + rig_debug(RIG_DEBUG_TRACE, "%s", "SPLIT "); } else { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "SIMPLEX "); + rig_debug(RIG_DEBUG_TRACE, "%s", "SIMPLEX "); } if (VFO) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "VFO "); + rig_debug(RIG_DEBUG_TRACE, "%s", "VFO "); } else { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "MEMORY "); + rig_debug(RIG_DEBUG_TRACE, "%s", "MEMORY "); } if (CLAR) { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "CLAR_ON "); + rig_debug(RIG_DEBUG_TRACE, "%s", "CLAR_ON "); } else { - rig_debug(RIG_DEBUG_VERBOSE, "%s", "CLAR_OFF"); + rig_debug(RIG_DEBUG_TRACE, "%s", "CLAR_OFF"); } - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); } static void dump_memory(_ft980_memory_t *memory) { - if (!rig_need_debug(RIG_DEBUG_VERBOSE)) + if (!rig_need_debug(RIG_DEBUG_TRACE)) { return; } - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_1 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_1 :"); dump_freq(memory->mem_1); dump_vfo(memory->vfo_1); dump_mode(memory->mode_1); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_2 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_2 :"); dump_freq(memory->mem_2); dump_vfo(memory->vfo_2); dump_mode(memory->mode_2); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_3 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_3 :"); dump_freq(memory->mem_3); dump_vfo(memory->vfo_3); dump_mode(memory->mode_3); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_4 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_4 :"); dump_freq(memory->mem_4); dump_vfo(memory->vfo_4); dump_mode(memory->mode_4); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_5 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_5 :"); dump_freq(memory->mem_5); dump_vfo(memory->vfo_5); dump_mode(memory->mode_5); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_6 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_6 :"); dump_freq(memory->mem_6); dump_vfo(memory->vfo_6); dump_mode(memory->mode_6); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_7 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_7 :"); dump_freq(memory->mem_7); dump_vfo(memory->vfo_7); dump_mode(memory->mode_7); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_8 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_8 :"); dump_freq(memory->mem_8); dump_vfo(memory->vfo_8); dump_mode(memory->mode_8); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_9 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_9 :"); dump_freq(memory->mem_9); dump_vfo(memory->vfo_9); dump_mode(memory->mode_9); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_10 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_10 :"); dump_freq(memory->mem_10); dump_vfo(memory->vfo_10); dump_mode(memory->mode_10); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_11 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_11 :"); dump_freq(memory->mem_11); dump_vfo(memory->vfo_11); dump_mode(memory->mode_11); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_12 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_12 :"); dump_freq(memory->mem_12); dump_vfo(memory->vfo_12); dump_mode(memory->mode_12); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_13 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_13 :"); dump_freq(memory->mem_13); dump_vfo(memory->vfo_13); dump_mode(memory->mode_13); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_14 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_14 :"); dump_freq(memory->mem_14); dump_vfo(memory->vfo_14); dump_mode(memory->mode_14); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_15 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_15 :"); dump_freq(memory->mem_15); dump_vfo(memory->vfo_15); dump_mode(memory->mode_15); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "mem_16 :"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_16 :"); dump_freq(memory->mem_16); dump_vfo(memory->vfo_16); dump_mode(memory->mode_16); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "GEN :"); - dump_freq(memory->GEN); + rig_debug(RIG_DEBUG_TRACE, "%s", "gen_vfo_freq :"); + dump_freq(memory->gen_vfo_freq); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\nHAM :"); - dump_freq(memory->HAM); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n "); + rig_debug(RIG_DEBUG_TRACE, "%s", "\nHAM :"); + dump_freq(memory->ham_vfo_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n "); dump_vfo(memory->vfo); dump_mode(memory->mode); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "CLAR :"); - dump_freq(memory->CLAR); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "clar_freq :"); + dump_freq(memory->clar_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "f_1 :"); - dump_freq(memory->ff_1); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_shift_freq :"); + dump_freq(memory->mem_shift_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "f_2 :"); - dump_freq(memory->ff_2); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "mem_clar_freq :"); + dump_freq(memory->mem_clar_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - rig_debug(RIG_DEBUG_VERBOSE, "%s", " "); + rig_debug(RIG_DEBUG_TRACE, "%s", " "); dump_vfo(memory->vfo); dump_mode(memory->mode); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "LDB :"); - dump_switch(memory->LDB); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "ldb_flag :"); + dump_switch(memory->ldb_flag); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "EXT_CTL :"); - dump_switch(memory->EXT_CTL); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "ext_ctl_flag :"); + dump_switch(memory->ext_ctl_flag); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - dump_IF_SHIFT(memory->IF_SHIFT); - dump_SPLIT_CODE(memory->SPLIT_CODE); - dump_FSK_SHIFT(memory->FSK_SHIFT); - dump_IF_WIDTH(memory->IF_WIDTH); - dump_MEM_SHIFT(memory->MEM_SHIFT); - dump_CLAR_FLAG(memory->CLAR_FLAG); - dump_TAB_FLAG(memory->TAB_FLAG); - dump_SELECT_SW(memory->SELECT_SW); + dump_if_shift(memory->if_shift); + dump_rptr_split_code(memory->rptr_split_code); + dump_fsk_shift(memory->fsk_shift); + dump_if_width(memory->if_width); + dump_mem_shift_flag(memory->mem_shift_flag); + dump_clar_flag(memory->clar_flag); + dump_tab_flag(memory->tab_flag); + dump_freq_select_sws(memory->freq_select_sws); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "OFFSET_SW :"); - dump_switch(memory->OFFSET_SW); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "offset_sw :"); + dump_switch(memory->offset_sw); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - dump_MODE_SW(memory->MODE_SW); - dump_MEM_CH_SW(memory->MEM_CH_SW); + dump_mode_sw(memory->mode_sw); + dump_mem_ch_sw(memory->mem_ch_sw); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "LOW_TAB :"); - dump_freq(memory->LOW_TAB); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "lower_tab_freq :"); + dump_freq(memory->lower_tab_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "UP_TAB :"); - dump_freq(memory->UP_TAB); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "upper_tab_freq :"); + dump_freq(memory->upper_tab_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - rig_debug(RIG_DEBUG_VERBOSE, "%s", " "); - dump_vfo(memory->VFO_STATUS); - dump_mode(memory->OP_MODE); + rig_debug(RIG_DEBUG_TRACE, "%s", " "); + dump_vfo(memory->op_vfo); + dump_mode(memory->op_mode); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "OP_FREQ :"); - dump_freq(memory->OP_FREQ); - rig_debug(RIG_DEBUG_VERBOSE, "%s", "\n"); + rig_debug(RIG_DEBUG_TRACE, "%s", "op_freq :"); + dump_freq(memory->op_freq); + rig_debug(RIG_DEBUG_TRACE, "%s", "\n"); - dump_STATUS_FLAG(memory->STATUS_FLAG); + dump_status_flag_bits(memory->status_flag_bits); } @@ -635,6 +569,8 @@ int ft980_transaction(RIG *rig, const unsigned char *cmd, unsigned char *data, int retval; char echo_back[YAESU_CMD_LENGTH]; + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + rig_flush(&rig->state.rigport); retval = write_block(&rig->state.rigport, (const char *)cmd, YAESU_CMD_LENGTH); @@ -684,12 +620,14 @@ int ft980_get_status_data(RIG *rig) struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; int retval; + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + if (!rig_check_cache_timeout(&priv->status_tv, FT980_CACHE_TIMEOUT)) { return RIG_OK; } - retval = ft980_transaction(rig, cmd, (unsigned char *)&priv->update_data, 148); + retval = ft980_transaction(rig, cmd, (unsigned char *)&priv->update_data, FT980_ALL_STATUS_LENGTH); if (retval != RIG_OK) { @@ -704,20 +642,33 @@ int ft980_get_status_data(RIG *rig) return retval; } - -/* - * ft980_open routine +/**************************************************************************** + * rig_init* + * + * Initialize memory & rig private data structure + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Nothing special here * */ -int ft980_open(RIG *rig) +int ft980_init(RIG *rig) { - unsigned char echo_back[YAESU_CMD_LENGTH]; struct ft980_priv_data *priv; - int retry_count1 = 0; - rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); - rig->state.priv = calloc(1, sizeof(struct ft980_priv_data)); + if (!rig) + { + return -RIG_EINVAL; + } + + rig->state.priv = (struct ft980_priv_data *) calloc(1, + sizeof(struct ft980_priv_data)); if (!rig->state.priv) { @@ -728,6 +679,71 @@ int ft980_open(RIG *rig) memset(priv, 0, sizeof(struct ft980_priv_data)); + // Initialize operating vfo mode to current VFO + priv->current_vfo = RIG_VFO_MAIN; + + return RIG_OK; +} + +/**************************************************************************** + * rig_cleanup* + * + * Release memory in rig private data structure for a clean exit + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Nothing special here + * + */ +int ft980_cleanup(RIG *rig) +{ + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rig) + { + return -RIG_EINVAL; + } + + if (rig->state.priv) + { + free(rig->state.priv); + } + + rig->state.priv = NULL; + + return RIG_OK; +} + +/**************************************************************************** + * rig_open* + * + * Initialize memory & rig private data structure + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Should be able to optimize + * ToDo: add check so we don't get stuck in EXT CTRL toggle trap/loop + * + */ +int ft980_open(RIG *rig) +{ + unsigned char echo_back[YAESU_CMD_LENGTH]; + struct ft980_priv_data *priv; + int retry_count1 = 0; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + priv = (struct ft980_priv_data *)rig->state.priv; + /* send Ext Cntl ON: Activate CAT */ do { @@ -743,20 +759,35 @@ int ft980_open(RIG *rig) while (retval != 5 && retry_count2++ < rig->state.rigport.retry); write_block(&rig->state.rigport, (char *) cmd_OK, YAESU_CMD_LENGTH); - retval = read_block(&rig->state.rigport, (char *) &priv->update_data, 148); + retval = read_block(&rig->state.rigport, (char *) &priv->update_data, FT980_ALL_STATUS_LENGTH); } - while (!priv->update_data.EXT_CTL && retry_count1++ < rig->state.rigport.retry); + while (!priv->update_data.ext_ctl_flag && retry_count1++ < rig->state.rigport.retry); return RIG_OK; } +/**************************************************************************** + * rig_close* + * + * Send command to toggle out of EXT CTRL mode + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Nothing special here + * Could be optimized. + * + */ int ft980_close(RIG *rig) { unsigned char echo_back[YAESU_CMD_LENGTH]; struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; int retry_count1 = 0; - rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); do { @@ -772,35 +803,113 @@ int ft980_close(RIG *rig) while (retval != 5 && retry_count2++ < rig->state.rigport.retry); write_block(&rig->state.rigport, (char *) cmd_OK, YAESU_CMD_LENGTH); - retval = read_block(&rig->state.rigport, (char *) &priv->update_data, 148); + retval = read_block(&rig->state.rigport, (char *) &priv->update_data, FT980_ALL_STATUS_LENGTH); } - while (priv->update_data.EXT_CTL && retry_count1++ < rig->state.rigport.retry); + while (priv->update_data.ext_ctl_flag && retry_count1++ < rig->state.rigport.retry); - free(priv); return RIG_OK; } - +/* + * Only the current VFO frequency can be set + * Other Hamlib backends (ex FT-990) switch VFO, change freq, then exit + * They do not return to the original VFO. + * We will stick with this convention for now. + * + * ToDo: Check return data to verify frequency was set correctly + */ +/* + * rig_set_freq* + * + * Set frequency for a given VFO + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo | input | currVFO, VFOA, VFOB, MEM + * freq | input | 100000 - 30000000 + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Passing currVFO to vfo will use the currently selected VFO + * obtained from the priv->current_vfo data structure. + * In all other cases the passed vfo is selected if it differs + * from the currently selected VFO. + * + * Issues: an error will occur with the 4.0 rig.c set_cache_freq routine when + * targeting VFO_MEM. + */ int ft980_set_freq(RIG *rig, vfo_t vfo, freq_t freq) { unsigned char cmd[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x08}; struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s: called\n", __func__); + rig_debug(RIG_DEBUG_TRACE, " %s: passed vfo = 0x%02x\n", __func__, vfo); + rig_debug(RIG_DEBUG_TRACE, " %s: passed freq = %lf Hz\n", __func__, freq); + + // Set to selected VFO + if (vfo == RIG_VFO_CURR) + { + vfo = priv->current_vfo; + rig_debug(RIG_DEBUG_TRACE, " %s: priv->current.vfo = 0x%02x\n", + __func__, vfo); + } + else + { + if (vfo != priv->current_vfo) + { + err = ft980_set_vfo(rig, vfo); + + if (err != RIG_OK) + { + return err; + } + } + } /* store bcd format in cmd (MSB) */ to_bcd(cmd, freq / 10, 8); + /* why is this done ? */ rig_force_cache_timeout(&priv->status_tv); /* Frequency set */ return ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, 5), 5); } +/* + * We can get HAM, GEN, Memory Shift (?), "Operating" + * What is memory "Shift"? + */ +/* + * rig_get_freq* + * + * Get frequency for a given VFO + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo | input | currVFO, Main, VFO, VFOA, VFOB, MEM + * freq * | output | 100000 - 30000000 + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Passing currVFO to vfo will use the currently selected VFO + * obtained from the priv->current_vfo data structure. + * In all other cases the passed vfo is selected if it differs + * from the currently selected VFO. + */ int ft980_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) { struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; int retval; freq_t f; + rig_debug(RIG_DEBUG_VERBOSE, "%s: called\n", __func__); + rig_debug(RIG_DEBUG_TRACE, " %s: passed vfo = 0x%02x\n", __func__, vfo); + /* Frequency get */ retval = ft980_get_status_data(rig); @@ -809,45 +918,122 @@ int ft980_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) return retval; } - f = from_bcd(priv->update_data.OP_FREQ, 8); + switch (vfo) + { + case RIG_VFO_CURR: + f = from_bcd(priv->update_data.op_freq, 8); + break; + + case RIG_VFO_MAIN: + f = from_bcd(priv->update_data.ham_vfo_freq, 8); + break; + + case RIG_VFO_SUB: + f = from_bcd(priv->update_data.gen_vfo_freq, 8); + break; + + case RIG_VFO_MEM: + f = from_bcd(priv->update_data.mem_shift_freq, 8); + break; + + default: + return -RIG_EINVAL; + } + + rig_debug(RIG_DEBUG_TRACE, + "%s: Selected Memory Freq = %lf\n", __func__, f*10); *freq = f * 10; /* return displayed frequency */ return RIG_OK; } - -#define MD_LSB 0x10 -#define MD_USB 0x11 -#define MD_CW 0x12 -#define MD_CWN 0x13 -#define MD_AM 0x14 -#define MD_AMN 0x15 -#define MD_RTTY 0x16 -#define MD_FM 0x17 - +/* + * Only the current VFO mode can be set + * Other Hamlib backends (ex FT-990) switch VFO, change mode, then exit + * They do not return to the original VFO. + * We will stick with this convention for now. + * + * ToDo: Check return data to verify mode was set correctly + */ +/* + * rig_set_mode* + * + * Set mode for a given VFO + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo | input | currVFO, Main, Sub, MEM + * mode | input | byte + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Passing currVFO to vfo will use the currently selected VFO + * obtained from the priv->current_vfo data structure. + * In all other cases the passed vfo is selected if it differs + * from the currently selected VFO. + */ int ft980_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) { unsigned char cmd[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x0A}; struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; unsigned char md; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s: called\n", __func__); + rig_debug(RIG_DEBUG_TRACE, " %s: passed vfo = 0x%02x\n", __func__, vfo); + rig_debug(RIG_DEBUG_TRACE, " %s: passed mode = %s\n", __func__, rig_strrmode(mode)); + rig_debug(RIG_DEBUG_TRACE, " %s: passed width = %ld Hz\n", __func__, width); + + // Set to selected VFO + if (vfo == RIG_VFO_CURR) + { + vfo = priv->current_vfo; + rig_debug(RIG_DEBUG_TRACE, "%s: priv->current.vfo = 0x%02x\n", + __func__, vfo); + } + else + { + if (vfo != priv->current_vfo) + { + err = ft980_set_vfo(rig, vfo); + + if (err != RIG_OK) + { + return err; + } + } + } /* * translate mode from generic to ft980 specific */ switch (mode) { - case RIG_MODE_CW : md = MD_CW; break; + case RIG_MODE_CW : + md = FT980_CMD0A_MD_CW; + break; - case RIG_MODE_USB: md = MD_USB; break; + case RIG_MODE_USB: + md = FT980_CMD0A_MD_USB; + break; - case RIG_MODE_LSB: md = MD_LSB; break; + case RIG_MODE_LSB: + md = FT980_CMD0A_MD_LSB; + break; - case RIG_MODE_FM: md = MD_FM; break; + case RIG_MODE_FM: + md = FT980_CMD0A_MD_FM; + break; - case RIG_MODE_AM: md = MD_AM; break; + case RIG_MODE_AM: + md = FT980_CMD0A_MD_AM; + break; - case RIG_MODE_RTTY: md = MD_RTTY; break; + case RIG_MODE_RTTY: + md = FT980_CMD0A_MD_RTTY; + break; default: return -RIG_EINVAL; /* sorry, wrong MODE */ @@ -859,25 +1045,49 @@ int ft980_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) { switch (md) { - case MD_CW: md = MD_CWN; break; + case FT980_CMD0A_MD_CW: + md = FT980_CMD0A_MD_CWN; + break; - case MD_AM: md = MD_AMN; break; + case FT980_CMD0A_MD_AM: + md = FT980_CMD0A_MD_AMN; + break; } } cmd[3] = md; + /* Might be deprecated in Hamlib 4.1 */ rig_force_cache_timeout(&priv->status_tv); /* Mode set */ - return ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, 22), 22); + return ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, FT980_OTHER_STATUS_LENGTH), FT980_OTHER_STATUS_LENGTH); } /* * rig_get_mode * * get mode eg AM, CW etc + * ??? What is the difference between byte 6 (operating mode vfo_op + * and byte 30 (selected VFO mode) ??? + */ +/* + * rig_get_mode* * + * Get frequency for a given VFO + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo | input | currVFO, Main, VFO, VFOA, VFOB, MEM + * mode * | output | byte + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Passing currVFO to vfo will use the currently selected VFO + * obtained from the priv->current_vfo data structure. + * In all other cases the passed vfo is selected if it differs + * from the currently selected VFO. */ int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) { @@ -885,6 +1095,9 @@ int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; int retval, norm; + rig_debug(RIG_DEBUG_VERBOSE, "%s: called\n", __func__); + rig_debug(RIG_DEBUG_TRACE, " %s: passed vfo = 0x%02x\n", __func__, vfo); + retval = ft980_get_status_data(rig); if (retval != RIG_OK) @@ -892,9 +1105,36 @@ int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) return retval; } - my_mode = priv->update_data.OP_MODE; + switch (vfo) + { + case RIG_VFO_CURR: + my_mode = priv->update_data.op_mode; - rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__); + rig_debug(RIG_DEBUG_TRACE, + " %s: Current VFO Mode = 0x%02x\n", __func__, my_mode); + + break; + + case RIG_VFO_MAIN: + case RIG_VFO_SUB: + + /* This is a point of confusion: what exactly is byte 30? */ + + my_mode = priv->update_data.mode; + rig_debug(RIG_DEBUG_TRACE, + " %s: HAM/GEN VFO Mode = 0x%02x\n", __func__, my_mode); + break; + + case RIG_VFO_MEM: + my_mode = priv->update_data.mem_mode; + + rig_debug(RIG_DEBUG_TRACE, + " %s: MEM VFO Mode = 0x%02x\n", __func__, my_mode); + break; + + default: + return -RIG_EVFO; + } /* * translate mode from ft980 to generic. @@ -944,6 +1184,8 @@ int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) default: return -RIG_EPROTO; /* Oops! file bug report */ } + rig_debug(RIG_DEBUG_TRACE, " %s: Hamlib mode = %s\n", __func__, + rig_strrmode(*mode)); if (norm) { @@ -953,10 +1195,7 @@ int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) { *width = rig_passband_narrow(rig, *mode); } - - rig_debug(RIG_DEBUG_TRACE, "%s: set mode = %s\n", __func__, - rig_strrmode(*mode)); - rig_debug(RIG_DEBUG_TRACE, "%s: set width = %d Hz\n", __func__, (int)*width); + rig_debug(RIG_DEBUG_TRACE, " %s: Filter width = %d Hz\n", __func__, (int)*width); return RIG_OK; } @@ -968,7 +1207,6 @@ int ft980_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo) #if 0 // deprecated as was ignored before now unsigned char cmd[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x8e}; - /* * this can be misleading as Yaesu call it "Full duplex" * or "sat mode", and split Yaesu terms is repeater shift. @@ -995,6 +1233,8 @@ int ft980_set_mem(RIG *rig, vfo_t vfo, int ch) unsigned char cmd[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x0A }; struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + if (ch > 16 || ch < 1) { return -RIG_EINVAL; @@ -1002,14 +1242,32 @@ int ft980_set_mem(RIG *rig, vfo_t vfo, int ch) cmd[3] = ch - 1; - return ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, 22), 22); + return ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, FT980_OTHER_STATUS_LENGTH), FT980_OTHER_STATUS_LENGTH); } +/**************************************************************************** + * rig_get_mem + * + * Get the number of the currently selected memory + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo | input | Not applicable for FT-980 + * ch | output | pointer to channel integer to be returned + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: returns currently selected memory channel regardlessof front + * panel knob selection (can be different when CAT is enabled). + */ int ft980_get_mem(RIG *rig, vfo_t vfo, int *ch) { struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; int retval; + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + retval = ft980_get_status_data(rig); if (retval != RIG_OK) @@ -1017,7 +1275,160 @@ int ft980_get_mem(RIG *rig, vfo_t vfo, int *ch) return retval; } - *ch = priv->update_data.MEM_CH_SW + 1; + *ch = priv->update_data.mem_ch_sw + 1; + + return RIG_OK; +} + +/**************************************************************************** + * rig_set_vfo* + * + * Set operational VFO + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo | input | currVFO, VFO_MAIN, VFOB/GEN, MEM + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: Passing currVFO to vfo will essentially "no op" + * In all other cases the passed vfo is selected if it differs + * from the currently selected VFO. + */ +/* VFO_CURR: Whatever is shown in op_freq/op_mode */ +/* VFO_MAIN: Mode = VFO, VFO = MAIN */ +/* VFO_SUB: Mode = VFO, VFO = GEN */ +/* VFO_MEM: Mode = Memory, VFO = don't care */ +int ft980_set_vfo(RIG *rig, vfo_t vfo) +{ + unsigned char cmd[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x0A }; + struct ft980_priv_data *priv; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rig) + { + return -RIG_EARG; + } + + rig_debug(RIG_DEBUG_TRACE, "%s: passed vfo = %s\n", __func__, rig_strvfo(vfo)); + + priv = (struct ft980_priv_data *)rig->state.priv; + + switch (vfo) + { + case RIG_VFO_CURR: + rig_debug(RIG_DEBUG_TRACE, + "%s: priv->current_vfo = 0x%02x\n", __func__, priv->current_vfo); + return RIG_OK; + break; + + case RIG_VFO_MAIN: + cmd[3] = FT980_CMD0A_VFO_SEL_HAM; + rig_debug(RIG_DEBUG_TRACE, "%s: set VFO GEN/HAM = 0x%02x\n", + __func__, cmd[3]); + err = ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, FT980_OTHER_STATUS_LENGTH), FT980_OTHER_STATUS_LENGTH); + if (err != RIG_OK) + { + return err; + } + cmd[3] = FT980_CMD0A_FREQ_SEL_VFO; + break; + + case RIG_VFO_SUB: + cmd[3] = FT980_CMD0A_VFO_SEL_GEN; + rig_debug(RIG_DEBUG_TRACE, "%s: set VFO GEN/HAM = 0x%02x\n", + __func__, cmd[3]); + err = ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, FT980_OTHER_STATUS_LENGTH), FT980_OTHER_STATUS_LENGTH); + if (err != RIG_OK) + { + return err; + } + cmd[3] = FT980_CMD0A_FREQ_SEL_VFO; + break; + + case RIG_VFO_MEM: + cmd[3] = FT980_CMD0A_FREQ_SEL_MR; + break; + + default: + return -RIG_EVFO; + } + + rig_debug(RIG_DEBUG_TRACE, "%s: set VFO Status = %s\n", + __func__, rig_strvfo(vfo)); + + return ft980_transaction(rig, cmd, UPDATE_DATA_OFS(&priv->update_data, FT980_OTHER_STATUS_LENGTH), FT980_OTHER_STATUS_LENGTH); +} + +/**************************************************************************** + * rig_get_vfo* + * + * Get operational VFO + * + * Parameter | Type | Accepted/Expected Values + * ------------------------------------------------------------------------- + * RIG * | input | pointer to private data + * vfo * | output | currVFO, VFO_MAIN, VFOB/GEN, MEM + * ------------------------------------------------------------------------- + * Returns RIG_OK on success or an error code on failure + * + * Comments: + * VFO_MAIN: If (Status = VFO && VFO = MAIN) || (Status = RXV && VFO = MAIN) + * VFO_SUB: If (Status = VFO && VFO = GEN) || (Status = RXV && VFO = GEN) + * VFO_MEM: If *Status = Memory) || (Status = RXM) + * + * If operating in split (RXM, RXV) then get_vfo returns the receive vfo + */ +int ft980_get_vfo(RIG *rig, vfo_t *vfo) +{ + int err; + struct ft980_priv_data *priv = (struct ft980_priv_data *)rig->state.priv; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + if (!rig) + { + return -RIG_EARG; + } + + /* Get flags for VFO status */ + err = ft980_get_status_data(rig); + if (err != RIG_OK) + { + return err; + } + + rig_debug(RIG_DEBUG_TRACE, + "%s: status_flag_bits = 0x%02x\n", __func__, + priv->update_data.status_flag_bits); + rig_debug(RIG_DEBUG_TRACE, + "%s: op_vfo = %s\n", __func__, + rig_strvfo(priv->update_data.op_vfo)); + + /* Decode the VFO Setting and VFO States */ + if (!(priv->update_data.status_flag_bits & FT_980_STATUSFLAG_VFO_MASK)) + { + priv->current_vfo = RIG_VFO_MEM; + } + else if (priv->update_data.op_vfo == FT980_VFO_HAM_SEL) + { + priv->current_vfo = RIG_VFO_MAIN; + } + else if (priv->update_data.op_vfo == FT980_VFO_GEN_SEL) + { + priv->current_vfo = RIG_VFO_SUB; + } + else + { + return -RIG_EVFO; + } + + rig_debug(RIG_DEBUG_TRACE, + "%s: stat_vfo = %s\n", __func__, rig_strvfo(priv->current_vfo)); + + *vfo = priv->current_vfo; return RIG_OK; } diff --git a/rigs/yaesu/ft980.h b/rigs/yaesu/ft980.h new file mode 100644 index 000000000..3cc931976 --- /dev/null +++ b/rigs/yaesu/ft980.h @@ -0,0 +1,460 @@ +/* + * hamlib - (C) Stephane Fillod 2002, 2003 (fillods at users.sourceforge.net) + * + * ft980.h - (C) Mat Breton, 2020 + * + * This shared library provides an API for communicating + * via serial interface to an FT-990 using the "CAT" interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* This file is a bit of a hack at the moment, containing both public and private declarations + * ToDo: Fix this point later, but temporarily necessary to sort stuff out right now + */ + +#ifndef _FT980_H +#define _FT980_H 1 + +/* Lets make the Linters Happy - remove later*/ +#ifndef _RIG_H +#include "hamlib/rig.h" +#endif + +#ifndef _YAESU_H +#include "yaesu.h" +#endif + +#ifndef _BANDPLAN_H +#include "bandplan.h" +#endif +/* End of Happy Linter Section */ + +/************************************************************************************* + * Semi-Public prototypes: need to be placed before the caps construct + * HAMLIB API implementation + */ +static int ft980_init(RIG *rig); +static int ft980_cleanup(RIG *rig); +static int ft980_open(RIG *rig); +static int ft980_close(RIG *rig); + +static int ft980_set_freq(RIG *rig, vfo_t vfo, freq_t freq); +static int ft980_get_freq(RIG *rig, vfo_t vfo, freq_t *freq); +static int ft980_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width); +static int ft980_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width); + +static int ft980_set_mem(RIG *rig, vfo_t vfo, int ch); +static int ft980_get_mem(RIG *rig, vfo_t vfo, int *ch); + +static int ft980_set_vfo(RIG *rig, vfo_t vfo); +static int ft980_get_vfo(RIG *rig, vfo_t *vfo); + +#if 0 +static int ft980_set_rit(RIG *rig, vfo_t vfo, shortfreq_t rit); +static int ft980_get_rit(RIG *rig, vfo_t vfo, shortfreq_t *rit); + +static int ft980_set_xit(RIG *rig, vfo_t vfo, shortfreq_t xit); +static int ft980_get_xit(RIG *rig, vfo_t vfo, shortfreq_t *xit); + +static int ft980_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, + vfo_t tx_vfo); +static int ft980_set_split_freq(RIG *rig, vfo_t vfo, freq_t freq); +static int ft980_set_split_mode(RIG *rig, vfo_t vfo, rmode_t mode, + pbwidth_t width); + +static int ft980_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t shift); +static int ft980_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs); +#endif + + +/************************************************************************************* + * Constants (enums and defines, w/ a couple typedefs thrown in) + */ + +/* Handy constants */ +#ifndef TRUE +#define TRUE 1 +#endif +#define ON TRUE +#ifndef FALSE +#define FALSE 0 +#endif +#define OFF FALSE + +/* FT-980 Status Return Message Lengths */ +#define FT980_ALL_STATUS_LENGTH 148 +#define FT980_OTHER_STATUS_LENGTH 22 +#define FT980_RPTRSPLT_STATUS_LENGTH 6 +#define FT980_UPDN_STATUS_LENGTH 5 +#define FT980_ONEBYTE_STATUS_LENGTH 1 + +/* FT-980 Timing Constants (for caps structure)*/ +/* Serial write timing values, in mS */ +#define FT980_WRITE_DELAY 80 +/* Delay sequential fast writes */ +#define FT980_POST_WRITE_DELAY 5 +/* Serial write timing values, in mS */ +#define FT980_PACING_INTERVAL 5 +/* The following may be deprecated into rig.c cache with 4.1 release*/ +#define FT980_CACHE_TIMEOUT 500 +/* Rough safe value for default read timeout = # bytes x (xmit speed + pacing_interval) x safety factor +#define FT980_DEFAULT_READ_TIMEOUT FT980_ALL_DATA_LENGTH * ( 1.7 + FT980_PACING_INTERVAL) * 6 +*/ +#define FT980_DEFAULT_READ_TIMEOUT 2000 + +/* FT-980 Configuration Constants (for caps structure)*/ +#define FT980_MODES (RIG_MODE_LSB|RIG_MODE_USB|RIG_MODE_CW|RIG_MODE_AM|RIG_MODE_RTTY|RIG_MODE_FM) +#define FT980_ANTS (RIG_ANT_1) + +/* */ +#define FT980_VFOS (RIG_VFO_CURR|RIG_VFO_MAIN|RIG_VFO_SUB|RIG_VFO_MEM) + +/* TODO: RIG_OP_TO_VFO|RIG_OP_FROM_VFO|RIG_OP_BAND_UP|RIG_OP_BAND_DOWN */ +#define FT980_VFO_OPS (RIG_OP_NONE) +/* TODO: RIG_OP_TO_VFO|RIG_OP_FROM_VFO|RIG_OP_BAND_UP|RIG_OP_BAND_DOWN +#define FT890_VFO_OPS (RIG_OP_TO_VFO|RIG_OP_FROM_VFO|RIG_OP_CPY|RIG_OP_UP|RIG_OP_DOWN) +*/ + +/* + * ft980 rigs capabilities. + * + * Protocol is documented in FT 980 Technical Supplement, page 13. + * + */ +#define FT980_MEM_CAP { \ + .freq = 1, \ + .mode = 1, \ + .width = 1, \ + } + +const struct rig_caps ft980_caps = +{ + RIG_MODEL(RIG_MODEL_FT980), + .model_name = "FT-980", + .mfg_name = "Yaesu", + .version = "20200114.0", + .copyright = "LGPL", + .status = RIG_STATUS_ALPHA, + .rig_type = RIG_TYPE_TRANSCEIVER, + .ptt_type = RIG_PTT_SERIAL_RTS, + .dcd_type = RIG_DCD_NONE, + .port_type = RIG_PORT_SERIAL, + .serial_rate_min = 4800, + .serial_rate_max = 4800, + .serial_data_bits = 8, + .serial_stop_bits = 2, + .serial_parity = RIG_PARITY_NONE, + .serial_handshake = RIG_HANDSHAKE_NONE, + .write_delay = FT980_WRITE_DELAY, + .post_write_delay = FT980_POST_WRITE_DELAY, + .timeout = FT980_DEFAULT_READ_TIMEOUT, + .retry = 3, + .has_get_func = RIG_FUNC_NONE, + .has_set_func = RIG_FUNC_NONE, + .has_get_level = RIG_LEVEL_NONE, + .has_set_level = RIG_LEVEL_NONE, + .has_get_parm = RIG_PARM_NONE, + .has_set_parm = RIG_PARM_NONE, + .vfo_ops = FT980_VFO_OPS, + .preamp = { RIG_DBLST_END, }, + .attenuator = { RIG_DBLST_END, }, + .max_rit = Hz(10000), + .max_xit = Hz(10000), + .max_ifshift = Hz(1500), + .targetable_vfo = RIG_TARGETABLE_FREQ | RIG_TARGETABLE_MODE, + .transceive = RIG_TRN_OFF, + .bank_qty = 0, + .chan_desc_sz = 0, + + .chan_list = { + {1, 16, RIG_MTYPE_MEM, FT980_MEM_CAP}, + }, + + .rx_range_list1 = { + {kHz(150), MHz(30) - 100, FT980_MODES, -1, -1, FT980_VFOS, FT980_ANTS}, + RIG_FRNG_END, + }, + + .tx_range_list1 = { + FRQ_RNG_HF(1, RIG_MODE_SSB | RIG_MODE_CW, W(5), W(100), FT980_VFOS, FT980_ANTS), + FRQ_RNG_HF(1, RIG_MODE_FM | RIG_MODE_RTTY, W(2), W(50), FT980_VFOS, FT980_ANTS), + FRQ_RNG_HF(1, RIG_MODE_AM, W(2), W(25), FT980_VFOS, FT980_ANTS), + RIG_FRNG_END, + }, + + .rx_range_list2 = { + {kHz(150), MHz(30) - 100, FT980_MODES, -1, -1, FT980_VFOS, FT980_ANTS}, + RIG_FRNG_END, + }, + + .tx_range_list2 = { + FRQ_RNG_HF(2, RIG_MODE_SSB | RIG_MODE_CW, W(5), W(100), FT980_VFOS, FT980_ANTS), + FRQ_RNG_HF(2, RIG_MODE_FM | RIG_MODE_RTTY, W(2), W(50), FT980_VFOS, FT980_ANTS), + FRQ_RNG_HF(2, RIG_MODE_AM, W(2), W(25), FT980_VFOS, FT980_ANTS), + RIG_FRNG_END, + }, + + .tuning_steps = { + {FT980_MODES, Hz(10)}, + {FT980_MODES, kHz(5)}, + {FT980_MODES, kHz(500)}, + RIG_TS_END, + }, + + /* mode/filter list, remember: order matters! */ + .filters = { + {RIG_MODE_SSB | RIG_MODE_CW | RIG_MODE_RTTY, kHz(2.5)}, + {RIG_MODE_CW, Hz(300)}, + {RIG_MODE_FM, kHz(12)}, + {RIG_MODE_AM, kHz(5)}, + {RIG_MODE_AM, kHz(3)}, + + RIG_FLT_END, + }, + + .rig_init = ft980_init, + .rig_cleanup = ft980_cleanup, + + .rig_open = ft980_open, + .rig_close = ft980_close, + + .set_freq = ft980_set_freq, + .get_freq = ft980_get_freq, + .set_mode = ft980_set_mode, + .get_mode = ft980_get_mode, + + .set_mem = ft980_set_mem, + .get_mem = ft980_get_mem, + + .get_vfo = ft980_get_vfo, + .set_vfo = ft980_set_vfo, + +#ifdef XXREMOVEDXX + .set_split_vfo = ft980_set_split_vfo, + .set_split_freq = ft980_set_split_freq, + .set_split_mode = ft980_set_split_mode, + + .set_rptr_shift = ft980_set_rptr_shift, + .set_rptr_offs = ft980_set_rptr_offs, +#endif +}; + +/* FT-980 Status Return Lengths (for memory structure)*/ +#define FT980_ALL_STATUS_LENGTH 148 +#define FT980_OTHER_STATUS_LENGTH 22 +#define FT980_RPTRSPLT_STATUS_LENGTH 6 +#define FT980_UPDN_STATUS_LENGTH 5 +#define FT980_ONEBYTE_STATUS_LENGTH 1 + +/* Do not change the order of the memory structure */ +typedef struct _ft980_memory_t +{ + unsigned char mem_16[4]; + unsigned char vfo_16; + unsigned char mode_16; + unsigned char mem_15[4]; + unsigned char vfo_15; + unsigned char mode_15; + unsigned char mem_14[4]; + unsigned char vfo_14; + unsigned char mode_14; + unsigned char mem_13[4]; + unsigned char vfo_13; + unsigned char mode_13; + unsigned char mem_12[4]; + unsigned char vfo_12; + unsigned char mode_12; + unsigned char mem_11[4]; + unsigned char vfo_11; + unsigned char mode_11; + unsigned char mem_10[4]; + unsigned char vfo_10; + unsigned char mode_10; + unsigned char mem_9[4]; + unsigned char vfo_9; + unsigned char mode_9; + unsigned char mem_8[4]; + unsigned char vfo_8; + unsigned char mode_8; + unsigned char mem_7[4]; + unsigned char vfo_7; + unsigned char mode_7; + unsigned char mem_6[4]; + unsigned char vfo_6; + unsigned char mode_6; + unsigned char mem_5[4]; + unsigned char vfo_5; + unsigned char mode_5; + unsigned char mem_4[4]; + unsigned char vfo_4; + unsigned char mode_4; + unsigned char mem_3[4]; + unsigned char vfo_3; + unsigned char mode_3; + unsigned char mem_2[4]; + unsigned char vfo_2; + unsigned char mode_2; + unsigned char mem_1[4]; + unsigned char vfo_1; + unsigned char mode_1; + unsigned char clar_freq[4]; + unsigned char gen_vfo_freq[4]; + unsigned char ham_vfo_freq[4]; + unsigned char vfo; /* ??? */ + unsigned char mode; /* ??? */ + unsigned char mem_shift_freq[4]; + unsigned char mem_clar_freq[4]; + unsigned char mem_vfo; + unsigned char mem_mode; + unsigned char ldb_flag; + unsigned char ext_ctl_flag; + unsigned char if_shift; + unsigned char rptr_split_code; + unsigned char fsk_shift; + unsigned char if_width; + unsigned char mem_shift_flag; + unsigned char clar_flag; + unsigned char tab_flag; + unsigned char freq_select_sws; + unsigned char offset_sw; + unsigned char mode_sw; + unsigned char mem_ch_sw; + unsigned char lower_tab_freq[4]; + unsigned char upper_tab_freq[4]; + unsigned char op_vfo; + unsigned char op_mode; + unsigned char op_freq[4]; + unsigned char status_flag_bits; +} _ft980_memory_t; + +/* + * Start of Return Status Code Defines + * These are the memory decode define (for the _ft980_memory_structure) + */ + +/* status_flag_bits: STATUS FLAG BYTE BIT decode MASKS */ +#define FT_980_STATUSFLAG_TXRX_MASK 0x01 +#define FT_980_STATUSFLAG_SPLIT_MASK 0x08 +#define FT_980_STATUSFLAG_VFO_MASK 0x20 +#define FT_980_STATUSFLAG_UPDN_MASK 0X30 +#define FT_980_STATUSFLAG_CLAR_MASK 0x40 + +/* op_vfo: VFO decode: Main, Gen, and 3 unsused AUX */ +#define FT980_VFO_HAM_SEL 0x80 +#define FT980_VFO_GEN_SEL 0x00 +#define FT980_VFO_AUX1_SEL 0x81 +#define FT980_VFO_AUX2_SEL 0x82 +#define FT980_VFO_AUX3_SEL 0x83 + +/* freq_select_sws: Frequency source decode, either a VFO, Mem, or Split */ +#define FT980_FREQ_SRC_SW_VFO 0x00 +#define FT980_FREQ_SRC_SW_MR 0x01 +#define FT980_FREQ_SRC_SW_RXM 0x02 +#define FT980_FREQ_SRC_SW_RXV 0x03 + +/* Clarifier Active Decode Masks */ +#define FT980_CLAR_RX_FLAG 0x20 +#define FT980_CLAR_TX_FLAG 0x40 + +/* FSK Shift Decode */ +#define FT980_FSK_SHIFT_INT 0x00 +#define FT980_FSK_SHIFT_425 0x40 +#define FT980_FSK_SHIFT_850 0x80 +#define FT980_FSK_SHIFT_170 0xC0 + +/* Repeater Split Codes */ +/* TBD: Is this table even needed */ + +/* + * Start of Command Code Defines + */ +static const char cmd_OK[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x0B}; +static const char cmd_ON_OFF[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* Opcodes 00 to 0B */ +enum ft980_native_cmd_e { + FT980_CMD_TOGGLE_EXT_CNTL = 0x00, + FT980_CMD_ALL_STATUS_CHECK = 0x01, + FT980_CMD_UP_10HZ = 0x02, + FT980_CMD_DN_10HZ = 0x03, + FT980_CMD_IF_WIDTH = 0x04, + FT980_CMD_IF_SHIFT = 0x05, + FT980_CMD_FSK_FREQ = 0x06, + FT980_CMD_RPTR_SPLIT_CODE = 0x07, + FT980_CMD_FREQ = 0x08, + FT980_CMD_LDB_SET = 0x09, + FT980_CMD_USER_PROG = 0x0A, + FT980_CMD0A_OK_SIGNAL = 0x0B +}; + +/* OpCode command 0x0A byte 3 sub-codes */ +/* The first 16 subcodes 00-0F are to command the memory channel */ + +// Operating Mode Status +enum ft980_native_cmd0A_e { + FT980_CMD0A_MD_LSB = 0x10, + FT980_CMD0A_MD_USB = 0x11, + FT980_CMD0A_MD_CW = 0x12, + FT980_CMD0A_MD_CWN = 0x13, + FT980_CMD0A_MD_AM = 0x14, + FT980_CMD0A_MD_AMN = 0x15, + FT980_CMD0A_MD_RTTY = 0x16, + FT980_CMD0A_MD_FM = 0x17, + + FT980_CMD0A_SHOW_OFFSET = 0x1B, + + /* Frequency Source Select */ + FT980_CMD0A_FREQ_SEL_RXM = 0x1C, + FT980_CMD0A_FREQ_SEL_RXV = 0x1D, + FT980_CMD0A_FREQ_SEL_MR = 0x1E, + FT980_CMD0A_FREQ_SEL_VFO = 0x1F, + + /* VFO Select; Question ... how do you set AUX1,2,3? */ + FT980_CMD0A_VFO_SEL_GEN = 0x21, + FT980_CMD0A_VFO_SEL_HAM = 0x22, + + /* Set Tab to Current Operating Frequency */ + FT980_CMD0A_SET_UPPER_TAB = 0x23, + FT980_CMD0A_SET_LOWER_TAB = 0x24, + FT980_CMD0A_TOGGLE_TABS = 0x25, + + /* Clarifier Commands */ + FT980_CMD0A_TOGGLE_TX_CLAR = 0x26, + FT980_CMD0A_TOGGLE_RX_CLAR = 0x27, + + /* Memory Commands */ + FT980_CMD0A_MEM_SHIFT = 0x28, + FT980_CMD0A_MEM_WRITE = 0x29, + + /* More Frequency Skips */ + FT980_CMD0A_UP_100Hz = 0x18, + FT980_CMD0A_DN_100Hz = 0x20, + FT980_CMD0A_UP_5KHz = 0x2C, + FT980_CMD0A_DN_5KHz = 0x2B, + FT980_CMD0A_BANDUP = 0x2F, + FT980_CMD0A_BANDOWN = 0x2D + + /* Missing 0A Sub-op-codes: 19,1A,2A,2E, after 2F */ +}; +/* End of OpCode command 0x0A byte 3 sub-codes */ + +/************************************************************************************* + * Macro Definitions + */ +#define UPDATE_DATA_OFS(p, o) (((unsigned char*)((p)+1))-(o)) + +#endif /* _FT980_H */