// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flrig.
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include "yaesu/FT890.h"
const char FT890name_[] = "FT-890";
static std::vectorFT890modes_;
static const char *vFT890modes_[] = {
"LSB", "USB", "CW", "CW-N", "AM", "AM-N", "FM", "FM-N"};
static const int FT890_mode_val[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
static const char FT890_mode_type[] = { 'L', 'U', 'U', 'U', 'U' };
static std::vectorFT890widths_;
static const char *vFT890widths_[] = { "wide", "narr"};
static const int FT890_bw_val[] =
{ 0, 1 };
RIG_FT890::RIG_FT890() {
name_ = FT890name_;
modes_ = FT890modes_;
bandwidths_ = FT890widths_;
bw_vals_ = FT890_bw_val;
serial_baudrate = BR4800;
stopbits = 2;
serial_retries = 2;
serial_write_delay = 5;
serial_post_write_delay = 50;
serial_timeout = 50;
serial_rtscts = false;
serial_rtsplus = false;
serial_dtrplus = true;
serial_catptt = true;
serial_rtsptt = false;
serial_dtrptt = false;
afreq = bfreq = A.freq = B.freq = 14070000ULL;
amode = bmode = A.imode = B.imode = 1;
aBW = bBW = A.iBW = B.iBW = 0;
precision = 10;
has_getvfoAorB =
has_split =
has_smeter =
has_power_out =
has_get_info =
has_ptt_control =
has_mode_control = true;
precision = 10;
ndigits = 7;
}
void RIG_FT890::init_cmd()
{
cmd = "00000";
for (size_t i = 0; i < 5; i++) cmd[i] = 0;
}
void RIG_FT890::initialize()
{
VECTOR (FT890modes_, vFT890modes_);
VECTOR (FT890widths_, vFT890widths_);
modes_ = FT890modes_;
bandwidths_ = FT890widths_;
bw_vals_ = FT890_bw_val;
}
void RIG_FT890::selectA()
{
init_cmd();
cmd[4] = 0x05;
sendCommand(cmd);
showresp(WARN, HEX, "select A", cmd, replystr);
inuse = onA;
}
void RIG_FT890::selectB()
{
init_cmd();
cmd[3] = 0x01;
cmd[4] = 0x05;
sendCommand(cmd);
showresp(WARN, HEX, "select B", cmd, replystr);
inuse = onB;
}
void RIG_FT890::set_split(bool val)
{
split = val;
init_cmd();
cmd[3] = val ? 0x01 : 0x00;
cmd[4] = 0x01;
sendCommand(cmd);
if (val)
showresp(INFO, HEX, "set split ON", cmd, replystr);
else
showresp(INFO, HEX, "set split OFF", cmd, replystr);
}
bool RIG_FT890::check()
{
init_cmd();
cmd[3] = 0x03;
cmd[4] = 0x10;
int ret = waitN(18, 100, "check", HEX);
if (ret >= 18) return true;
return false;
}
// 18 byte return values
/*
VFO A is 5000.00 MHz on FLRIG
VFO B is .740.00 MHz on the rig
Radio is set to 5.000.00 MHz, the same as FLRIG.
05:37:41.733 : read_smeter()
05:37:41.733 : WriteBuffer: 00 00 00 00 F7
05:37:41.783 : ReadBuffer [0.032000 msec]: 36 36 36 36 F7
05:37:42.203 : read_vfo()
05:37:42.203 : WriteBuffer: 00 00 00 03 10
05:37:42.260 : ReadBuffer [6.529000 msec]: 08 07 A1 20 00 00 03 04 04 01 01 21 10 00 00 03 04 85
05:37:42.260 : vfoA active get vfo A
05:37:42.260 : read_mode vfoA active
05:37:42.260 : read: 0
05:37:42.661 : read_smeter()
05:37:42.661 : WriteBuffer: 00 00 00 00 F7
05:37:42.711 : ReadBuffer [0.033000 msec]: 3C 3C 3C 3C F7
05:37:43.131 : read_vfo()
05:37:43.131 : WriteBuffer: 00 00 00 03 10
05:37:43.188 : ReadBuffer [6.500000 msec]: 08 07 A1 20 00 00 03 04 04 01 01 21 10 00 00 03 04 85
05:37:43.188 : vfoA active get vfo A
05:37:43.189 : read_mode vfoA active
05:37:43.189 : read: 0
05:37:43.589 : read_smeter()
05:37:43.589 : WriteBuffer: 00 00 00 00 F7
05:37:43.640 : ReadBuffer [0.019000 msec]: 3C 3C 3C 3C F7
------------------------------------
VFO A is 5000.00 MHz on FLRIG
VFO B is 2961.92 on FLRIG, .740.00 MHz on the rig.
Radio is set to 5.001.00 MHz, different from FLRIG.
05:50:47.284 : read_vfo()
05:50:47.285 : WriteBuffer: 00 00 00 03 10
05:50:47.340 : ReadBuffer [5.437000 msec]: 08 07 A1 84 00 00 03 04 04 01 01 21 10 00 00 03 04 85
05:50:47.340 : vfoA active get vfo A
05:50:47.341 : read_mode vfoA active
05:50:47.341 : read: 0
05:50:47.741 : read_smeter()
05:50:47.741 : WriteBuffer: 00 00 00 00 F7
05:50:47.791 : ReadBuffer [0.067000 msec]: 42 42 42 42 F7
05:50:48.211 : read_vfo()
05:50:48.211 : WriteBuffer: 00 00 00 03 10
05:50:48.268 : ReadBuffer [6.509000 msec]: 08 07 A1 84 00 00 03 04 04 01 01 21 10 00 00 03 04 85
05:50:48.268 : vfoA active get vfo A
05:50:48.268 : read_mode vfoA active
05:50:48.268 : read: 0
05:50:48.669 : read_smeter()
05:50:48.669 : WriteBuffer: 00 00 00 00 F7
05:50:48.719 : ReadBuffer [0.035000 msec]: 3F 3F 3F 3F F7
05:50:49.139 : read_vfo()
05:50:49.139 : WriteBuffer: 00 00 00 03 10
05:50:49.196 : ReadBuffer [6.537000 msec]: 08 07 A1 84 00 00 03 04 04 01 01 21 10 00 00 03 04 85
05:50:49.196 : vfoA active get vfo A
05:50:49.197 : read_mode vfoA active
05:50:49.197 : read: 0
05:50:49.597 : read_smeter()
05:50:49.597 : WriteBuffer: 00 00 00 00 F7
05:50:49.648 : ReadBuffer [0.037000 msec]: 3E 3E 3E 3E F7
*/
static bool testing = false;
bool RIG_FT890::get_info()
{
init_cmd();
cmd[3] = 0x03;
cmd[4] = 0x10;
size_t ret;
if (testing) {
replystr.clear();
// vfo A
replystr += '\x08'; replystr += '\x07'; replystr += '\xA1'; replystr += '\x20';
replystr += '\x00'; replystr += '\x00'; replystr += '\x01'; replystr += '\x04';
replystr += '\x04';
// vfo B
// replystr += '\x01'; replystr += '\x01'; replystr += '\x21'; replystr += '\x10';
replystr += '\x08'; replystr += '\x07'; replystr += '\xA1'; replystr += '\x20';
replystr += '\x00'; replystr += '\x00'; replystr += '\x03'; replystr += '\x04';
replystr += '\x85';
ret = replystr.length();
} else {
ret = waitN(18, 100, "get info", HEX);
}
if (ret == 18) {
A.iBW = (replystr[0] & 1);
A.freq = 10 * ((((replystr[1] & 0xFF) * 256 +
(replystr[2] & 0xFF) ) * 256 +
(replystr[3] & 0xFF) ) );
switch (replystr[6] & 0x07) {
case 0: A.imode = ((replystr[6] & 0x40) == 0x40) ? 1 : 0; break;
case 1: A.imode = ((replystr[6] & 0x40) == 0x40) ? 3 : 2; break;
case 2: A.imode = ((replystr[6] & 0x80) == 0x80) ? 5 : 4; break;
case 3: A.imode = ((replystr[6] & 0x80) == 0x80) ? 7 : 6; break;
default: A.imode = 0;
}
std::cout << "Info: " << str2hex(replystr.c_str(), replystr.length()) << std::endl;
std::cout << " A: " << A.freq << ", " << vFT890modes_[A.imode] << std::endl;
B.iBW = (replystr[9] & 1);
B.freq = 10 * ((((replystr[10] & 0xFF) * 256 +
(replystr[11] & 0xFF) ) * 256 +
(replystr[12] & 0xFF) ) );
switch (replystr[15] & 0x07) {
case 0: B.imode = ((replystr[15] & 0x40) == 0x40) ? 1 : 0; break;
case 1: B.imode = ((replystr[15] & 0x40) == 0x40) ? 3 : 2; break;
case 2: B.imode = ((replystr[15] & 0x80) == 0x80) ? 5 : 4; break;
case 3: B.imode = ((replystr[15] & 0x80) == 0x80) ? 7 : 6; break;
default: B.imode = 0;
}
std::cout << " B: " << B.freq << ", " << vFT890modes_[B.imode] << std::endl;
} else {
std::cout << "failed to read VFO status bytes (18)" << std::endl;
return false;
}
// read flag bytes
if (testing) {
replystr.clear();
replystr += '\x04'; replystr += '\xFF'; replystr += '\x80'; replystr += '\xFF';
replystr += '\xFF';
ret = replystr.length();
} else {
init_cmd();
cmd[4] = 0xFA;
ret = waitN(5, 100, "get info", HEX);
}
ptt_ = false;
split = false;
inuse = onA;
if (ret == 5) {
if ( (replystr[0] & 0x04) == 0x04 ) split = true;
if ( (replystr[0] & 0x40) == 0x40 ) inuse = onB;
if ( (replystr[2] & 0x80) == 0x80 ) ptt_ = true;
std::cout << "Flag Bytes " << str2hex(replystr.c_str(), replystr.length()) << std::endl;
std::cout << " Split: " << (split ? "ON" : "OFF") <<
" Active vfo: " << (inuse ? "B" : "A") <<
" PTT: " << (ptt_ ? "ON" : "OFF") << std::endl << std::endl;
} else {
std::cout << "failed to read flag bytes (5)" << std::endl << std::endl;
return false;
}
return true;
}
unsigned long long RIG_FT890::get_vfoA ()
{
return A.freq;
}
void RIG_FT890::set_vfoA (unsigned long long freq)
{
A.freq = freq;
freq /=10; // 890 does not support 1 Hz resolution
cmd = to_bcd_be(freq, 8);
cmd += 0x0A;
sendCommand(cmd);
showresp(WARN, HEX, "set vfo A", cmd, replystr);
}
int RIG_FT890::get_modeA()
{
return A.imode;
}
void RIG_FT890::set_modeA(int val)
{
A.imode = val;
init_cmd();
cmd[3] = FT890_mode_val[val];
cmd[4] = 0x0C;
sendCommand(cmd);
showresp(WARN, HEX, "set mode A", cmd, replystr);
}
unsigned long long RIG_FT890::get_vfoB()
{
return B.freq;
}
void RIG_FT890::set_vfoB(unsigned long long freq)
{
B.freq = freq;
freq /=10; // 890 does not support 1 Hz resolution
cmd = to_bcd_be(freq, 8);
cmd += 0x8A;
sendCommand(cmd);
showresp(WARN, HEX, "set vfo B", cmd, replystr);
}
void RIG_FT890::set_modeB(int val)
{
B.imode = val;
init_cmd();
cmd[3] = FT890_mode_val[val] | 0x80;
cmd[4] = 0x0C;
sendCommand(cmd);
showresp(WARN, HEX, "set mode B", cmd, replystr);
}
int RIG_FT890::get_modeB()
{
return B.imode;
}
// Tranceiver PTT on/off
void RIG_FT890::set_PTT_control(int val)
{
init_cmd();
if (val) cmd[3] = 1;
else cmd[3] = 0;
cmd[4] = 0x0F;
sendCommand(cmd, 0);
LOG_INFO("%s", str2hex(cmd.c_str(), 5));
ptt_ = val;
}
int RIG_FT890::get_PTT() {
return ptt_;
}
int RIG_FT890::get_smeter()
{
init_cmd();
cmd[4] = 0xF7;
int ret = waitN(5, 100, "get smeter", HEX);
if (ret < 5) return 0;
int sval = (unsigned char)(replystr[ret - 2] & 0xFF);
sval = round(sval * 100.0 / 240.0);
return sval;
}
int RIG_FT890::get_power_out()
{
init_cmd();
cmd[4] = 0xF7;
size_t ret;
if (testing) {
replystr[0] = 120; replystr[1] = 60; replystr[2] = 60; replystr[3] = 60;
replystr[4] = 0xF7;
ret = replystr.length();
} else {
ret = waitN(5, 100, "get pwr out", HEX);
}
if (ret < 5) return 0;
int sval = (unsigned char)(replystr[ret - 5]);
sval = round(sval * 100.0 / 240.0);
return sval;
}