Restore ft990.c and move FT990UNI to it's own file

https://github.com/Hamlib/Hamlib/issues/1050
pull/1077/head
Mike Black W9MDB 2022-06-28 09:21:04 -05:00
rodzic 2f4bca95f7
commit 5711257279
5 zmienionych plików z 4091 dodań i 388 usunięć

Wyświetl plik

@ -3,7 +3,7 @@
## Yeasu radios that use the legacy CAT commands
YAESUSRC = ft100.c ft100.h ft747.c ft747.h ft817.c ft817.h ft847.c ft847.h \
ft890.c ft890.h ft900.c ft900.h ft920.c ft920.h ft1000mp.c ft1000mp.h \
ft857.c ft857.h ft897.c ft897.h ft990.c ft990.h frg8800.c ft757gx.c \
ft857.c ft857.h ft897.c ft897.h ft990.c ft990.h ft990v12.c ft990v12.h frg8800.c ft757gx.c \
ft757gx.h ft600.h ft600.c ft736.c frg100.c frg100.h frg9600.c ft1000d.c \
ft1000d.h vr5000.c ft767gx.c ft767gx.h ft840.c ft840.h ft980.c ft980.h \
vx1700.c vx1700.h ftdx10.h

Wyświetl plik

@ -24,19 +24,13 @@
*
*/
/* THIS FILE WAS MODIFIED IN DECEMBER 2016 TO REMOVE ANY REFERENCE TO THE FT-1000/D. SEPARATE ft1000d.c and .h FILES
* WERE CREATED TO HANDLE FT-1000/D COMMANDS AND PROVIDE THE FULL RANGE OF FUNCTIONS AVAILABLE ON THE FT-1000/D
* TO MAXIMISE COMPATIBILITY WITH RIGCTL.
* G0OAN
*/
/* MODIFIED VERSION for FT-990 with ROM v1.2 : June 2022
* The standard version was written for FT-990 with ROM v1.3 and as the CAT spec was different to ROM v1.2 CAT
* would not work with the older ROM. This version enables ROM v1.2 to work although it is necessary to accept
* that frequent polling functionality is not feasible with this older ROM. With ROM v1.2 polling fetches 1492
* bytes which at 4800 Baud takes about 3.8 seconds during which the FT-990 has a CAT blackout. The longest poll
* interval available in WSJT-X is 99 seconds.
* Collaboration between M0EZP David Brewerton and K1MMI Edmund Hajjar
*/
#include <hamlib/config.h>
@ -160,68 +154,65 @@ static int ft990_send_dial_freq(RIG *rig, unsigned char ci, freq_t freq);
static int ft990_send_rit_freq(RIG *rig, unsigned char ci, shortfreq_t rit);
static const yaesu_cmd_set_t ncmd[] =
{ /* ci */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 00 00 Split (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x01 } }, /* 01 01 Split (On) */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x02 } }, /* 02 02 Recall Memory */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x03 } }, /* 03 03 Memory Operations */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x04 } }, /* 04 04 Lock (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x04 } }, /* 05 05 Lock (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x05 } }, /* 06 06 Select VFO (A) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x05 } }, /* 07 07 Select VFO (B) */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x06 } }, /* 08 08 Copy Memory Data to VFO A */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x07 } }, /* 09 09 OP Freq Up 0.1MHz */
{ 1, { 0x00, 0x00, 0x01, 0x00, 0x07 } }, /* 10 0a OP Freq Up 1MHz */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x08 } }, /* 11 0b OP Freq Down 0.1MHz */
{ 1, { 0x00, 0x00, 0x01, 0x00, 0x08 } }, /* 12 0c OP Freq Down 1MHz */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x09 } }, /* 13 0d RX Clarifier (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x09 } }, /* 14 0e RX Clarifier (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x80, 0x09 } }, /* 15 0f TX Clarifier (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x81, 0x09 } }, /* 16 10 TX Clarifier (ON) */
{ 1, { 0x00, 0x00, 0x00, 0xff, 0x09 } }, /* 17 11 Clear Clarifier Offset */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x09 } }, /* 18 12 Clarifier */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x0a } }, /* 19 13 Set Op Freq */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x0c } }, /* 20 14 OP Mode Set LSB */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x0c } }, /* 21 15 OP Mode Set USB */
{ 1, { 0x00, 0x00, 0x00, 0x02, 0x0c } }, /* 22 16 OP Mode Set CW 2.4KHz */
{ 1, { 0x00, 0x00, 0x00, 0x03, 0x0c } }, /* 23 17 OP Mode Set CW 500Hz */
{ 1, { 0x00, 0x00, 0x00, 0x04, 0x0c } }, /* 24 18 OP Mode Set AM 6KHz */
{ 1, { 0x00, 0x00, 0x00, 0x05, 0x0c } }, /* 25 19 OP Mode Set AM 2.4KHz */
{ 1, { 0x00, 0x00, 0x00, 0x06, 0x0c } }, /* 26 1a OP Mode Set FM */
{ 1, { 0x00, 0x00, 0x00, 0x08, 0x0c } }, /* 27 1b OP Mode Set RTTY LSB */
{ 1, { 0x00, 0x00, 0x00, 0x09, 0x0c } }, /* 28 1c OP Mode Set RTTY USB */
{ 1, { 0x00, 0x00, 0x00, 0x0a, 0x0c } }, /* 29 1d OP Mode Set PKT LSB */
{ 1, { 0x00, 0x00, 0x00, 0x0b, 0x0c } }, /* 30 1e OP Mode Set PKT FM */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x0e } }, /* 31 1f Pacing */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x0f } }, /* 32 20 PTT (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x0f } }, /* 33 21 PTT (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x10 } }, /* 34 22 Update All Data (1492 bytes) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x10 } }, /* 35 23 Update Memory Ch Number M0EZP: 2ndByte was 0x01 */
{ 1, { 0x00, 0x00, 0x00, 0x02, 0x10 } }, /* 36 24 Update Op Data M0EZP: 2ndByte was 0x02 */
{ 1, { 0x00, 0x00, 0x00, 0x03, 0x10 } }, /* 37 25 Update VFO Data M0EZP: 2ndByte was 0x03 */
{ 0, { 0x00, 0x00, 0x00, 0x04, 0x10 } }, /* 38 26 Update Memory Ch Data M0EZP: 2ndByte was 0x04 */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x81 } }, /* 39 27 Tuner (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x81 } }, /* 40 28 Tuner (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x82 } }, /* 41 29 Tuner (Start) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x84 } }, /* 42 2a Repeater Mode (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x84 } }, /* 43 2b Repeater Mode (Minus) */
{ 1, { 0x00, 0x00, 0x00, 0x02, 0x84 } }, /* 44 2c Repeater Mode (Plus) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x85 } }, /* 45 2d Copy displayed VFO (A=B || B=A) */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x8C } }, /* 46 2e Select Bandwidth */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x8E } }, /* 47 2f Step Operating Frequency Up */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x8E } }, /* 48 30 Step Operating Frequency Down */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0xf7 } }, /* 49 31 Read Meter */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0xf8 } }, /* 50 32 DIM Level */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0xf9 } }, /* 51 33 Set Offset for Repeater Shift */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0xfa } }, /* 52 34 Read Status Flags */
{
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* Split (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x01 } }, /* Split (On) */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x02 } }, /* Recall Memory */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x03 } }, /* Memory Operations */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x04 } }, /* Lock (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x04 } }, /* Lock (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x05 } }, /* Select VFO (A) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x05 } }, /* Select VFO (B) */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x06 } }, /* Copy Memory Data to VFO A */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x07 } }, /* OP Freq Up 0.1MHz */
{ 1, { 0x00, 0x00, 0x01, 0x00, 0x07 } }, /* OP Freq Up 1MHz */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x08 } }, /* OP Freq Down 0.1MHz */
{ 1, { 0x00, 0x00, 0x01, 0x00, 0x08 } }, /* OP Freq Down 1MHz */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x09 } }, /* RX Clarifier (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x09 } }, /* RX Clarifier (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x80, 0x09 } }, /* TX Clarifier (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x81, 0x09 } }, /* TX Clarifier (ON) */
{ 1, { 0x00, 0x00, 0x00, 0xff, 0x09 } }, /* Clear Clarifier Offset */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x09 } }, /* Clarifier */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x0a } }, /* Set Op Freq */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x0c } }, /* OP Mode Set LSB */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x0c } }, /* OP Mode Set USB */
{ 1, { 0x00, 0x00, 0x00, 0x02, 0x0c } }, /* OP Mode Set CW 2.4KHz */
{ 1, { 0x00, 0x00, 0x00, 0x03, 0x0c } }, /* OP Mode Set CW 500Hz */
{ 1, { 0x00, 0x00, 0x00, 0x04, 0x0c } }, /* OP Mode Set AM 6KHz */
{ 1, { 0x00, 0x00, 0x00, 0x05, 0x0c } }, /* OP Mode Set AM 2.4KHz */
{ 1, { 0x00, 0x00, 0x00, 0x06, 0x0c } }, /* OP Mode Set FM */
{ 1, { 0x00, 0x00, 0x00, 0x08, 0x0c } }, /* OP Mode Set RTTY LSB */
{ 1, { 0x00, 0x00, 0x00, 0x09, 0x0c } }, /* OP Mode Set RTTY USB */
{ 1, { 0x00, 0x00, 0x00, 0x0a, 0x0c } }, /* OP Mode Set PKT LSB */
{ 1, { 0x00, 0x00, 0x00, 0x0b, 0x0c } }, /* OP Mode Set PKT FM */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x0e } }, /* Pacing */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x0f } }, /* PTT (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x0f } }, /* PTT (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x10 } }, /* Update All Data (1508 bytes) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x10 } }, /* Update Memory Ch Number */
{ 1, { 0x00, 0x00, 0x00, 0x02, 0x10 } }, /* Update Op Data */
{ 1, { 0x00, 0x00, 0x00, 0x03, 0x10 } }, /* Update VFO Data */
{ 0, { 0x00, 0x00, 0x00, 0x04, 0x10 } }, /* Update Memory Ch Data */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x81 } }, /* Tuner (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x81 } }, /* Tuner (ON) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x82 } }, /* Tuner (Start) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x84 } }, /* Repeater Mode (OFF) */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x84 } }, /* Repeater Mode (Minus) */
{ 1, { 0x00, 0x00, 0x00, 0x02, 0x84 } }, /* Repeater Mode (Plus) */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x85 } }, /* Copy displayed VFO (A=B || B=A) */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0x8C } }, /* Select Bandwidth */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0x8E } }, /* Step Operating Frequency Up */
{ 1, { 0x00, 0x00, 0x00, 0x01, 0x8E } }, /* Step Operating Frequency Down */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0xf7 } }, /* Read Meter */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0xf8 } }, /* DIM Level */
{ 0, { 0x00, 0x00, 0x00, 0x00, 0xf9 } }, /* Set Offset for Repeater Shift */
{ 1, { 0x00, 0x00, 0x00, 0x00, 0xfa } }, /* Read Status Flags */
};
/*
* Private data
*/
// M0EZP: status 0=uni first call, 1=uni after first call
int ft990uni_get_freq_state = 0;
struct ft990_priv_data
{
unsigned char pacing; /* pacing value */
@ -379,144 +370,6 @@ const struct rig_caps ft990_caps =
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
// Old FT990 ROM has to read all 1492 to get frequency
// So for this model we just use the cache to read freq
const struct rig_caps ft990uni_caps =
{
RIG_MODEL(RIG_MODEL_FT990UNI),
.model_name = "FT-990 Old Rom",
.mfg_name = "Yaesu",
.version = "20220628.0",
.copyright = "LGPL",
.status = RIG_STATUS_STABLE,
.rig_type = RIG_TYPE_TRANSCEIVER,
.ptt_type = RIG_PTT_RIG,
.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 = FT990_WRITE_DELAY,
.post_write_delay = FT990_POST_WRITE_DELAY,
.timeout = 2000,
.retry = 0,
.has_get_func = RIG_FUNC_LOCK | RIG_FUNC_TUNER | RIG_FUNC_MON,
.has_set_func = RIG_FUNC_LOCK | RIG_FUNC_TUNER,
.has_get_level = RIG_LEVEL_STRENGTH | RIG_LEVEL_SWR | RIG_LEVEL_ALC | \
RIG_LEVEL_RFPOWER | RIG_LEVEL_COMP,
.has_set_level = RIG_LEVEL_BAND_SELECT,
.has_get_parm = RIG_PARM_NONE,
.has_set_parm = RIG_PARM_BACKLIGHT,
.ctcss_list = NULL,
.dcs_list = NULL,
.preamp = { RIG_DBLST_END, },
.attenuator = { RIG_DBLST_END, },
.max_rit = Hz(9999),
.max_xit = Hz(9999),
.max_ifshift = Hz(1200),
.vfo_ops = RIG_OP_CPY | RIG_OP_FROM_VFO | RIG_OP_TO_VFO |
RIG_OP_UP | RIG_OP_DOWN | RIG_OP_TUNE | RIG_OP_TOGGLE,
.targetable_vfo = RIG_TARGETABLE_ALL,
.transceive = RIG_TRN_OFF, /* Yaesus have to be polled, sigh */
.bank_qty = 0,
.chan_desc_sz = 0,
.chan_list = {
{1, 90, RIG_MTYPE_MEM, FT990_MEM_CAP},
RIG_CHAN_END,
},
.rx_range_list1 = {
{kHz(100), MHz(30), FT990_ALL_RX_MODES, -1, -1, FT990_VFO_ALL, FT990_ANTS}, /* General coverage + ham */
RIG_FRNG_END,
},
.tx_range_list1 = {
FRQ_RNG_HF(1, FT990_OTHER_TX_MODES, W(5), W(100), FT990_VFO_ALL, FT990_ANTS),
FRQ_RNG_HF(1, FT990_AM_TX_MODES, W(2), W(25), FT990_VFO_ALL, FT990_ANTS), /* AM class */
RIG_FRNG_END,
},
.rx_range_list2 = {
{kHz(100), MHz(30), FT990_ALL_RX_MODES, -1, -1, FT990_VFO_ALL, FT990_ANTS},
RIG_FRNG_END,
},
.tx_range_list2 = {
FRQ_RNG_HF(2, FT990_OTHER_TX_MODES, W(5), W(100), FT990_VFO_ALL, FT990_ANTS),
FRQ_RNG_HF(2, FT990_AM_TX_MODES, W(2), W(25), FT990_VFO_ALL, FT990_ANTS), /* AM class */
RIG_FRNG_END,
},
.tuning_steps = {
{FT990_SSB_CW_RX_MODES, Hz(10)}, /* Normal */
{FT990_SSB_CW_RX_MODES, Hz(100)}, /* Fast */
{FT990_AM_RX_MODES, Hz(100)}, /* Normal */
{FT990_AM_RX_MODES, kHz(1)}, /* Fast */
{FT990_FM_RX_MODES, Hz(100)}, /* Normal */
{FT990_FM_RX_MODES, kHz(1)}, /* Fast */
{FT990_RTTY_RX_MODES, Hz(10)}, /* Normal */
{FT990_RTTY_RX_MODES, Hz(100)}, /* Fast */
RIG_TS_END,
},
/* mode/filter list, .remember = order matters! */
.filters = {
{RIG_MODE_SSB, RIG_FLT_ANY}, /* Enable all filters for SSB */
{RIG_MODE_CW, RIG_FLT_ANY}, /* Enable all filters for CW */
{RIG_MODE_RTTY, RIG_FLT_ANY}, /* Enable all filters for RTTY */
{RIG_MODE_RTTYR, RIG_FLT_ANY}, /* Enable all filters for Reverse RTTY */
{RIG_MODE_PKTLSB, RIG_FLT_ANY}, /* Enable all filters for Packet Radio LSB */
{RIG_MODE_AM, kHz(6)}, /* normal AM filter */
{RIG_MODE_AM, kHz(2.4)}, /* narrow AM filter */
{RIG_MODE_FM, kHz(8)}, /* FM standard filter */
{RIG_MODE_PKTFM, kHz(8)}, /* FM standard filter for Packet Radio FM */
RIG_FLT_END,
},
.priv = NULL, /* private data FIXME: */
.rig_init = ft990_init,
.rig_cleanup = ft990_cleanup,
.rig_open = ft990_open, /* port opened */
.rig_close = ft990_close, /* port closed */
.set_freq = ft990_set_freq,
.get_freq = ft990_get_freq,
.set_mode = ft990_set_mode,
.get_mode = ft990_get_mode,
.set_vfo = ft990_set_vfo,
.get_vfo = ft990_get_vfo,
.set_ptt = ft990_set_ptt,
.get_ptt = ft990_get_ptt,
.set_rptr_shift = ft990_set_rptr_shift,
.get_rptr_shift = ft990_get_rptr_shift,
.set_rptr_offs = ft990_set_rptr_offs,
.set_split_vfo = ft990_set_split_vfo,
.get_split_vfo = ft990_get_split_vfo,
.set_rit = ft990_set_rit,
.get_rit = ft990_get_rit,
.set_xit = ft990_set_xit,
.get_xit = ft990_get_xit,
.set_func = ft990_set_func,
.get_func = ft990_get_func,
.set_parm = ft990_set_parm,
.get_level = ft990_get_level,
.set_mem = ft990_set_mem,
.get_mem = ft990_get_mem,
.vfo_op = ft990_vfo_op,
.set_channel = ft990_set_channel,
.get_channel = ft990_get_channel,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
/*
* ************************************
@ -618,9 +471,7 @@ int ft990_open(RIG *rig)
}
// Get current rig settings and status
// err = ft990_get_update_data(rig, FT990_NATIVE_UPDATE_OP_DATA, 0);
// M0EZP read flags instead of update
err = ft990_get_update_data(rig, FT990_NATIVE_READ_FLAGS, 0);
err = ft990_get_update_data(rig, FT990_NATIVE_UPDATE_OP_DATA, 0);
if (err != RIG_OK)
{
@ -756,78 +607,69 @@ int ft990_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
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: ft990uni_get_freq_state = 0x%02x\n", __func__, ft990uni_get_freq_state);
if (ft990uni_get_freq_state < 2) {
// M0EZP: UNI first call needs UPDATE_ALL
ft990uni_get_freq_state = ft990uni_get_freq_state + 1;
if (!rig)
{
return -RIG_EINVAL;
}
if (!rig)
{
return -RIG_EINVAL;
}
priv = (struct ft990_priv_data *)rig->state.priv;
if (vfo == RIG_VFO_CURR)
{
vfo = priv->current_vfo;
rig_debug(RIG_DEBUG_TRACE, "%s: priv->current.vfo = 0x%02x\n",
priv = (struct ft990_priv_data *)rig->state.priv;
if (vfo == RIG_VFO_CURR)
{
vfo = priv->current_vfo;
rig_debug(RIG_DEBUG_TRACE, "%s: priv->current.vfo = 0x%02x\n",
__func__, vfo);
}
}
switch (vfo)
{
case RIG_VFO_A:
case RIG_VFO_VFO:
p = priv->update_data.vfoa.basefreq;
ci = FT990_NATIVE_UPDATE_VFO_DATA;
break;
switch (vfo)
{
case RIG_VFO_A:
case RIG_VFO_VFO:
p = priv->update_data.vfoa.basefreq;
ci = FT990_NATIVE_UPDATE_VFO_DATA;
break;
case RIG_VFO_B:
p = priv->update_data.vfob.basefreq;
ci = FT990_NATIVE_UPDATE_VFO_DATA;
break;
case RIG_VFO_B:
p = priv->update_data.vfob.basefreq;
ci = FT990_NATIVE_UPDATE_VFO_DATA;
break;
case RIG_VFO_MEM:
case RIG_VFO_MAIN:
p = priv->update_data.current_front.basefreq;
ci = FT990_NATIVE_UPDATE_OP_DATA;
break;
case RIG_VFO_MEM:
case RIG_VFO_MAIN:
p = priv->update_data.current_front.basefreq;
ci = FT990_NATIVE_UPDATE_OP_DATA;
break;
default:
return -RIG_EINVAL;
}
ci = FT990_NATIVE_UPDATE_ALL_DATA; /* M0EZP: inserted to override CI */
err = ft990_get_update_data(rig, ci, 0);
default:
return -RIG_EINVAL;
}
if (err != RIG_OK)
{
return err;
}
// Get update data structure to obtain get frequency
err = ft990_get_update_data(rig, ci, 0);
/* big endian integer */
f = ((((p[0] << 8) + p[1]) << 8) + p[2]) * 10;
if (err != RIG_OK)
{
return err;
}
rig_debug(RIG_DEBUG_TRACE, "%s: p0=0x%02x p1=0x%02x p2=0x%02x\n",
/* big endian integer */
f = ((((p[0] << 8) + p[1]) << 8) + p[2]) * 10;
rig_debug(RIG_DEBUG_TRACE, "%s: p0=0x%02x p1=0x%02x p2=0x%02x\n",
__func__, p[0], p[1], p[2]);
rig_debug(RIG_DEBUG_TRACE,
rig_debug(RIG_DEBUG_TRACE,
"%s: freq = %"PRIfreq" Hz for vfo 0x%02x\n", __func__, f, vfo);
// Frequency sanity check
if (f < 100000 || f > 30000000)
{
return -RIG_EINVAL;
}
// Frequency sanity check
if (f < 100000 || f > 30000000)
{
return -RIG_EINVAL;
}
*freq = f;
*freq = f;
return RIG_OK;
} else {
// M0EZP: Uni use cache
// *freq = vfo == RIG_VFO_A ? rig->state.cache.freqMainA : rig->state.cache.freqMainB;
return (RIG_OK);
}
return RIG_OK;
}
/*
@ -2461,6 +2303,7 @@ int ft990_set_vfo(RIG *rig, vfo_t vfo)
int ft990_get_vfo(RIG *rig, vfo_t *vfo)
{
struct ft990_priv_data *priv;
int err;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
@ -2471,14 +2314,13 @@ int ft990_get_vfo(RIG *rig, vfo_t *vfo)
priv = (struct ft990_priv_data *)rig->state.priv;
/* Get flags for VFO status
err = ft990_get_update_data(rig, FT990_NATIVE_READ_FLAGS, 0);
/* Get flags for VFO status */
err = ft990_get_update_data(rig, FT990_NATIVE_READ_FLAGS, 0);
if (err != RIG_OK)
{
return err;
}
*/
if (priv->update_data.flag2 & FT990_SF_MEM ||
priv->update_data.flag2 & FT990_SF_MTUNE)
@ -3168,7 +3010,7 @@ int ft990_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
if (chan->split & RIG_SPLIT_ON)
{
// Get data for the transmit VFO
p = (ft990_op_data_t *) &priv->update_data.current_front; /* M0EZP: was current_rear */
p = (ft990_op_data_t *) &priv->update_data.current_rear;
/* FT1000D
@ -3387,7 +3229,7 @@ int ft990_get_update_data(RIG *rig, unsigned char ci, unsigned short ch)
int n;
int err;
int rl;
unsigned char temp[FT990_STATUS_FLAGS_LENGTH];
unsigned char temp[5];
unsigned char *p;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
@ -3399,119 +3241,73 @@ int ft990_get_update_data(RIG *rig, unsigned char ci, unsigned short ch)
return -RIG_EINVAL;
}
n = 0; // K1MMI: Initialise as the only time n will be updated is for the FT990_NATIVE_ALL_DATA AND FT990_READ_FLAGS
priv = (struct ft990_priv_data *)rig->state.priv;
if (ci == FT990_NATIVE_UPDATE_MEM_CHNL_DATA)
// P4 = 0x01 to 0x5a for channel 1 - 90
{
err = ft990_send_dynamic_cmd(rig, ci, 4, 0, 0, ch);
}
else
{
err = ft990_send_static_cmd(rig, ci);
}
if (err != RIG_OK)
{
return err;
}
switch (ci)
{
case FT990_NATIVE_UPDATE_ALL_DATA:
case FT990_NATIVE_UPDATE_MEM_CHNL:
case FT990_NATIVE_UPDATE_OP_DATA:
case FT990_NATIVE_UPDATE_VFO_DATA:
case FT990_NATIVE_UPDATE_MEM_CHNL_DATA:
if (ft990uni_get_freq_state < 2) {
//
if (ci == FT990_NATIVE_UPDATE_MEM_CHNL_DATA)
// P4 = 0x01 to 0x5a for channel 1 - 90
{
/* err = ft990_send_dynamic_cmd(rig, ci, 4, 0, 0, ch);
M0EZP: dont send command, rely on the assignment from memory below*/
} else {
// err = RIG_OK; K1MMI
err = ft990_send_static_cmd(rig, ci); // K1MMI: only send for ALL DATA 1492 bytes or READ FLAGS 5 bytes
}
if (err != RIG_OK)
{
return err;
}
switch (ci)
{
case FT990_NATIVE_UPDATE_ALL_DATA:
rl = FT990_ALL_DATA_LENGTH; // K1MMI: prepare to receive 1492 bytes back
p = (unsigned char *)&priv->update_data; // K1MMI: This seems like 1492 will be saved here
n = read_block(&rig->state.rigport, p, rl); /* M0EZP: copied here from below */
return RIG_OK;
break;
case FT990_NATIVE_UPDATE_MEM_CHNL:
// we already have the channelnumber in the previously saved 1492 bytes
p = (unsigned char *) &priv->update_data.channelnumber;
rl = FT990_MEM_CHNL_LENGTH; // 1
break;
case FT990_NATIVE_UPDATE_OP_DATA:
// we already have the current OP and VFOA in the 1492 bytes
p = (unsigned char *) &priv->update_data.current_front;
rl = FT990_OP_DATA_LENGTH; // 32
break;
case FT990_NATIVE_UPDATE_VFO_DATA:
// we already have the VFOA and VFOB in the 1492 bytes
p = (unsigned char *) &priv->update_data.vfoa;
rl = FT990_VFO_DATA_LENGTH; // 32
break;
case FT990_NATIVE_UPDATE_MEM_CHNL_DATA:
// we already have the 16 structure for the memory channel number
p = (unsigned char *) &priv->update_data.channel[ch];
rl = FT990_MEM_CHNL_DATA_LENGTH; // 16
break;
default:
// M0EZP: shouldn't be here!
rig_debug(RIG_DEBUG_TRACE, "%s: Default clause ci 0x%02x\n", __func__, ci); // M0EZP
return -RIG_EINVAL;
}
ft990uni_get_freq_state = ft990uni_get_freq_state + 1;
if (n < 0)
{
return n; /* die returning read_block error */
}
rig_debug(RIG_DEBUG_TRACE, "%s: read %i bytes\n", __func__, n);
memcpy(&priv->update_data, p, FT990_ALL_DATA_LENGTH);
return RIG_OK;
} else {
return RIG_OK;
}
case FT990_NATIVE_READ_FLAGS:
rig_debug(RIG_DEBUG_TRACE, "%s: passed ci 0x%02x\n", __func__, ci);
err = ft990_send_static_cmd(rig, ci); // K1MMI: only send for ALL DATA 1492 bytes
if (err != RIG_OK)
{
return err;
}
p = (unsigned char *)&priv->update_data;
rl = FT990_STATUS_FLAGS_LENGTH; // 5
n = read_block(&rig->state.rigport, (unsigned char*)&temp, rl); /* M0EZP: copied here from below */
if (n < 0)
{
return n; /* die returning read_block error */
}
rig_debug(RIG_DEBUG_TRACE, "%s: read %i bytes\n", __func__, n);
memcpy(&priv->update_data, p, FT990_STATUS_FLAGS_LENGTH - 2); /* just overwrite first 3 bytes */
return RIG_OK;
break;
default:
// M0EZP: shouldn't be here!
rig_debug(RIG_DEBUG_TRACE, "%s: Default clause ci 0x%02x\n", __func__, ci); // M0EZP
return -RIG_EINVAL;
}
{
case FT990_NATIVE_UPDATE_ALL_DATA:
return RIG_OK;
break;
case FT990_NATIVE_UPDATE_MEM_CHNL:
p = (unsigned char *) &priv->update_data.channelnumber;
rl = FT990_MEM_CHNL_LENGTH;
break;
case FT990_NATIVE_UPDATE_OP_DATA:
p = (unsigned char *) &priv->update_data.current_front;
rl = FT990_OP_DATA_LENGTH;
break;
case FT990_NATIVE_UPDATE_VFO_DATA:
p = (unsigned char *) &priv->update_data.vfoa;
rl = FT990_VFO_DATA_LENGTH;
break;
case FT990_NATIVE_UPDATE_MEM_CHNL_DATA:
p = (unsigned char *) &priv->update_data.channel[ch];
rl = FT990_MEM_CHNL_DATA_LENGTH;
break;
case FT990_NATIVE_READ_FLAGS:
p = temp;
rl = FT990_STATUS_FLAGS_LENGTH;
break;
default:
return -RIG_EINVAL;
}
n = read_block(&rig->state.rigport, p, rl);
if (n < 0)
{
return n; /* die returning read_block error */
}
rig_debug(RIG_DEBUG_TRACE, "%s: read %i bytes\n", __func__, n);
if (ci == FT990_NATIVE_READ_FLAGS)
{
memcpy(&priv->update_data, p, FT990_STATUS_FLAGS_LENGTH - 2);
}
return RIG_OK;
}
/*

Wyświetl plik

@ -22,14 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/* MODIFIED VERSION for FT-990 with ROM v1.2 : June 2022
* The standard version was written for FT-990 with ROM v1.3 and as the CAT spec was different to ROM v1.2 CAT
* would not work with the older ROM. This version enables ROM v1.2 to work although it is necessary to accept
* that frequent polling functionality is not feasible with this older ROM. With ROM v1.2 polling fetches 1492
* bytes which at 4800 Baud takes about 3.8 seconds during which the FT-990 has a CAT blackout. The longest poll
* interval available in WSJT-X is 99 seconds.
* Collaboration between M0EZP David Brewerton and K1MMI Edmund Hajjar
*/
#ifndef _FT990_H
#define _FT990_H 1
@ -64,7 +57,7 @@
/* Returned data length in bytes */
#define FT990_ALL_DATA_LENGTH 1492 /* 0x10 P1 = 00 return size */
#define FT990_ALL_DATA_LENGTH 1508 /* 0x10 P1 = 00 return size */
#define FT990_MEM_CHNL_LENGTH 1 /* 0x10 P1 = 01 return size */
#define FT990_OP_DATA_LENGTH 32 /* 0x10 P1 = 02 return size */
#define FT990_VFO_DATA_LENGTH 32 /* 0x10 P1 = 03 return size -- A & B returned */
@ -297,7 +290,7 @@ typedef struct _ft990_update_data_t {
unsigned char flag3;
unsigned char channelnumber;
ft990_op_data_t current_front;
/* ft990_op_data_t current_rear; M0EZP: field not valid for FT990 ROM v1.2 */
ft990_op_data_t current_rear;
ft990_op_data_t vfoa;
ft990_op_data_t vfob;
ft990_op_data_t channel[90];

3602
rigs/yaesu/ft990v12.c 100755

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,312 @@
/*
* hamlib - (C) Stephane Fillod 2002, 2003 (fillods at users.sourceforge.net)
*
* ft990.h - (C) Berndt Josef Wulf (wulf at ping.net.au)
*
* 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
*
*/
/* MODIFIED VERSION for FT-990 with ROM v1.2 : June 2022
* The standard version was written for FT-990 with ROM v1.3 and as the CAT spec was different to ROM v1.2 CAT
* would not work with the older ROM. This version enables ROM v1.2 to work although it is necessary to accept
* that frequent polling functionality is not feasible with this older ROM. With ROM v1.2 polling fetches 1492
* bytes which at 4800 Baud takes about 3.8 seconds during which the FT-990 has a CAT blackout. The longest poll
* interval available in WSJT-X is 99 seconds.
* Collaboration between M0EZP David Brewerton and K1MMI Edmund Hajjar
*/
#ifndef _FT990_H
#define _FT990_H 1
// Global Definitions
#define TRUE 1
#define FALSE 0
#define ON TRUE
#define OFF FALSE
/* RX caps */
#define FT990_ALL_RX_MODES (RIG_MODE_LSB|RIG_MODE_USB|RIG_MODE_CW|RIG_MODE_AM|RIG_MODE_FM|RIG_MODE_RTTY|RIG_MODE_RTTYR|RIG_MODE_PKTFM|RIG_MODE_PKTLSB)
#define FT990_SSB_CW_RX_MODES (RIG_MODE_CW|RIG_MODE_USB|RIG_MODE_LSB|RIG_MODE_PKTLSB)
#define FT990_RTTY_RX_MODES (RIG_MODE_RTTY|RIG_MODE_RTTYR)
#define FT990_AM_RX_MODES (RIG_MODE_AM)
#define FT990_FM_RX_MODES (RIG_MODE_FM|RIG_MODE_PKTFM)
/* TX caps */
#define FT990_OTHER_TX_MODES (RIG_MODE_CW|RIG_MODE_USB|RIG_MODE_LSB|RIG_MODE_RTTY|RIG_MODE_RTTYR|RIG_MODE_FM|RIG_MODE_PKTFM|RIG_MODE_PKTLSB) /* 100 W class */
#define FT990_AM_TX_MODES (RIG_MODE_AM ) /* set 25W max */
#define FT990_FUNC_ALL (RIG_FUNC_FAGC|RIG_FUNC_NB|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_TONE|RIG_FUNC_TSQL|RIG_FUNC_SBKIN|RIG_FUNC_FBKIN|RIG_FUNC_LOCK|RIG_FUNC_TUNER) /* fix */
/* Other features */
#define FT990_VFO_ALL (RIG_VFO_A|RIG_VFO_B)
#define FT990_ANTS 0
#define FT990_VFO_OPS (RIG_OP_TO_VFO|RIG_OP_FROM_VFO|RIG_OP_CPY|RIG_OP_UP|RIG_OP_DOWN)
/* Returned data length in bytes */
#define FT990_ALL_DATA_LENGTH 1492 /* 0x10 P1 = 00 return size */
#define FT990_MEM_CHNL_LENGTH 1 /* 0x10 P1 = 01 return size */
#define FT990_OP_DATA_LENGTH 32 /* 0x10 P1 = 02 return size */
#define FT990_VFO_DATA_LENGTH 32 /* 0x10 P1 = 03 return size -- A & B returned */
#define FT990_MEM_CHNL_DATA_LENGTH 16 /* 0x10 P1 = 04, P4 = 0x00-0x59 return size */
#define FT990_READ_METER_LENGTH 5 /* 0xf7 return size */
#define FT990_STATUS_FLAGS_LENGTH 5 /* 0xfa return size */
/* BCD coded frequency length */
#define FT990_BCD_DIAL 8
#define FT990_BCD_RIT 3
#define FT990_BCD_RPTR_OFFSET 6
/* Timing values in mS */
#define FT990_PACING_INTERVAL 5
#define FT990_PACING_DEFAULT_VALUE 0
#define FT990_WRITE_DELAY 50
/* Delay sequential fast writes */
#define FT990_POST_WRITE_DELAY 5
/* Rough safe value for default timeout */
#define FT990_DEFAULT_READ_TIMEOUT FT990_ALL_DATA_LENGTH * ( 5 + (FT990_PACING_INTERVAL * FT990_PACING_DEFAULT_VALUE))
/*
* The definitions below are copied from the kft990
* project and are hereby made available to the
* hamlib project. [BJW]
*/
// OpCode Declarations
#define FT990_CMD_SPLIT 0x01
#define FT990_CMD_RECALLMEM 0x02
#define FT990_CMD_VFO2MEM 0x03
#define FT990_CMD_LOCK 0x04
#define FT990_CMD_SELVFOAB 0x05
#define FT990_CMD_MEM2VFO 0x06
#define FT990_CMD_UP 0x07
#define FT990_CMD_DOWN 0x08
#define FT990_CMD_CLARIFIER 0x09
#define FT990_CMD_SETVFOA 0x0a
#define FT990_CMD_SELOPMODE 0x0c
#define FT990_CMD_PACING 0x0e
#define FT990_CMD_PTT 0x0f
#define FT990_CMD_UPDATE 0x10
#define FT990_CMD_TUNER 0x81
#define FT990_CMD_START 0x82
#define FT990_CMD_RPT 0x84
#define FT990_CMD_VFOA2B 0x85
#define FT990_CMD_BW 0x8c
#define FT990_CMD_MEMSCANSKIP 0x8d
#define FT990_CMD_STEPVFO 0x8e
#define FT990_CMD_RDMETER 0xf7
#define FT990_CMD_DIMLEVEL 0xf8
#define FT990_CMD_RPTROFFSET 0xf9
#define FT990_CMD_RDFLAGS 0xfa
// Bandwidth Filter
#define FT990_BW_F2400 0x00
#define FT990_BW_F2000 0x01
#define FT990_BW_F500 0x02
#define FT990_BW_F250 0x03
#define FT990_BW_F6000 0x04
#define FT990_BW_FMPKTRTTY 0x80
// Operating Mode Status
#define FT990_MODE_LSB 0x00
#define FT990_MODE_USB 0x01
#define FT990_MODE_CW 0x02
#define FT990_MODE_AM 0x03
#define FT990_MODE_FM 0x04
#define FT990_MODE_RTTY 0x05
#define FT990_MODE_PKT 0x06
// Operation Mode Selection
#define FT990_OP_MODE_LSB 0x00
#define FT990_OP_MODE_USB 0x01
#define FT990_OP_MODE_CW2400 0x02
#define FT990_OP_MODE_CW500 0x03
#define FT990_OP_MODE_AM6000 0x04
#define FT990_OP_MODE_AM2400 0x05
#define FT990_OP_MODE_FM 0x06
#define FT990_OP_MODE_RTTYLSB 0x08
#define FT990_OP_MODE_RTTYUSB 0x09
#define FT990_OP_MODE_PKTLSB 0x0a
#define FT990_OP_MODE_PKTFM 0x0b
// Clarifier Operation
#define FT990_CLAR_TX_EN 0x01
#define FT990_CLAR_RX_EN 0x02
#define FT990_CLAR_RX_OFF 0x00
#define FT990_CLAR_RX_ON 0x01
#define FT990_CLAR_TX_OFF 0x80
#define FT990_CLAR_TX_ON 0x81
#define FT990_CLAR_CLEAR 0xff
#define FT990_CLAR_TUNE_UP 0x00
#define FT990_CLAR_TUNE_DOWN 0xff
// Repeater Shift Enable
#define FT990_RPT_POS_EN 0x04
#define FT990_RPT_NEG_EN 0x08
#define FT990_RPT_MASK 0x0C
// Status Flag 1 Masks
#define FT990_SF_SPLIT 0x01
#define FT990_SF_VFOB 0x02
#define FT990_SF_FAST 0x04
#define FT990_SF_CAT 0x08
#define FT990_SF_TUNING 0x10
#define FT990_SF_KEY_ENTRY 0x20
#define FT990_SF_MEM_EMPTY 0x40
#define FT990_SF_XMIT 0x80
// Status Flag 2 Masks
#define FT990_SF_MEM_SCAN_PAUSE 0x01
#define FT990_SF_MEM_CHECK 0x02
#define FT990_SF_MEM_SCAN 0x04
#define FT990_SF_LOCKED 0x08
#define FT990_SF_MTUNE 0x10
#define FT990_SF_VFO 0x20
#define FT990_SF_MEM 0x40
#define FT990_SF_GEN 0x80
// Status Flag 3 Masks
#define FT990_SF_PTT 0x01
#define FT990_SF_TX_INHIBIT 0x02
#define FT990_SF_KEY_TIMER 0x04
#define FT990_SF_MEM_TIMER 0x08
#define FT990_SF_PTT_INHIBIT 0x10
#define FT990_SF_XMIT_MON 0x20
#define FT990_SF_TUNER_ON 0x40
#define FT990_SF_SIDETONE 0x80
#define FT990_EMPTY_MEM 0x80
#define FT990_AMFILTER2400 0x80
// Flags Byte 1
typedef struct _ft990_flags1_t {
unsigned split: 1;
unsigned vfob: 1;
unsigned fast: 1;
unsigned cat: 1;
unsigned tuning: 1;
unsigned keyentry: 1;
unsigned memempty: 1;
unsigned xmit: 1;
} ft990_flags1_t;
// Flags Byte 2
typedef struct _ft990_flags2_t {
unsigned memscanpause:1;
unsigned memcheck: 1;
unsigned memscan: 1;
unsigned locked: 1;
unsigned mtune: 1;
unsigned vfo: 1;
unsigned mem: 1;
unsigned gen: 1;
} ft990_flags2_t;
// Flags Byte 3
typedef struct _ft990_status3_t {
unsigned ptt: 1;
unsigned txinhibit: 1;
unsigned keytimer: 1;
unsigned memtimer: 1;
unsigned pttinhibit: 1;
unsigned xmitmon: 1;
unsigned tuneron: 1;
unsigned sidetone: 1;
} ft990_flags3_t;
typedef union _ft990_flags1_u {
ft990_flags1_t bits;
unsigned char byte;
} ft990_flags1_u;
typedef union _ft990_flags2_u {
ft990_flags2_t bits;
unsigned char byte;
} ft990_flags2_u;
typedef union _ft990_flags3_u {
ft990_flags3_t bits;
unsigned char byte;
} ft990_flags3_u;
typedef struct _ft990_status_data_t {
ft990_flags1_u flags1;
ft990_flags2_u flags2;
ft990_flags3_u flags3;
unsigned char id1;
unsigned char id2;
} ft990_status_data_t;
typedef struct _ft990_meter_data_t {
unsigned char mdata1;
unsigned char mdata2;
unsigned char mdata3;
unsigned char mdata4;
unsigned char id1;
} ft990_meter_data_t;
typedef struct _ft990_op_data_t {
unsigned char bpf;
unsigned char basefreq[3];
unsigned char status;
unsigned char coffset[2];
unsigned char mode;
unsigned char filter;
unsigned char lastssbfilter;
unsigned char lastcwfilter;
unsigned char lastrttyfilter;
unsigned char lastpktfilter;
unsigned char lastclariferstate;
unsigned char skipscanamfilter;
unsigned char amfm100;
} ft990_op_data_t;
// Update Data Structure
typedef struct _ft990_update_data_t {
unsigned char flag1;
unsigned char flag2;
unsigned char flag3;
unsigned char channelnumber;
ft990_op_data_t current_front;
/* ft990_op_data_t current_rear; M0EZP: field not valid for FT990 ROM v1.2 */
ft990_op_data_t vfoa;
ft990_op_data_t vfob;
ft990_op_data_t channel[90];
} ft990_update_data_t;
// Command Structure
typedef struct _ft990_command_t {
unsigned char data[4];
unsigned char opcode;
} ft990_command_t;
#endif /* _FT990_H */