/* MSHV Part from RigControl
 * Copyright 2015 Hrisimir Hristov, LZ2HV
 * (Edited by Harper Innes, VK1TTY - to remove Gendered Language and Replace with Non-Gendered language)  NOTE:May be used under the terms of the GNU General Public License (GPL)
 */
#include "icom.h"
#include "icom_def.h"
#include "../hvutils.h"
//#include <QtGui>

#define PR		    0xfe
#define C_CTL_PTT	0x1c		/* Control Transmit On/Off, Sc */
#define FI		    0xfd		/* End of message code */
#define CTRLID		0xe0		/* Controllers's default address */

////////////////////////////////////////////////////////new read com
#define COL		    0xfc		/* CI-V bus collision detected */
#define C_SET_FREQ	0x05		/* Set frequency data(1) */
#define C_RD_FREQ	0x03		/* Read display frequency */
#define C_SET_MODE	0x06		/* Set mode data, Sc */
#define C_RD_MODE	0x04		/* Read display mode */
#define MAXFRAMELEN 56
//#define CIV_731_MODE 1          /*priv->civ_731_mode ? 4:5*  -> 0=1HZ 1=10Hz   */
////////////////////////////////////////////////////////end new read com

#define S_PTT		0x00
#define S_ANT_TUN	0x01	/* Auto tuner 0=OFF, 1 = ON, 2=Start Tuning */

#define S_LSB	    0x00    /* Set to LSB */
#define S_USB	    0x01	/* Set to USB */
#define S_R7000_SSB	0x05	/* Set to SSB on R-7000 */

static const unsigned char icom_addr_list[ICOM_COUNT] =
    {
        /*IC-7000*/0x70,
        /*IC-7100*/0x88,
        /*IC-7200*/0x76,
        /*IC-7300*/0x94,
        /*IC-705*/0xa4,
        /*IC-756*/0x50,
        /*IC-756PRO*/0x5c,
        /*IC-756PROII*/0x64,
        /*IC-756PROIII*/0x6e,
        /*IC-706*/0x48,
        /*IC-706MkII*/0x4e,
        /*IC-706MkIIG*/0x58,
        /*IC-9100*/0x7c,
        /*IC-9700*/0xa2,
        /*IC-7800*/0x6a,
        /*IC-785x*/0x8e,
        /*IC-7700*/0x74,
        /*IC-7600*/0x7a,
        /*IC-7610*/0x98,
        /*IC-7410*/0x80,
        /*IC-1275*/0x18,
        /*IC-970*/0x2e,
        /*IC-910*/0x60,
        /*IC-821H*/0x4c,
        /*IC-820H*/0x42,
        /*IC-781*/0x26,
        /*IC-775*/0x46,
        /*IC-765*/0x2c,
        /*IC-761*/0x1e,
        /*IC-751*/0x1c,
        /*IC-746*/0x56,
        /*IC-746PRO*/0x66,
        /*IC-738*/0x44,
        /*IC-737*/0x3c,
        /*IC-736*/0x40,
        /*IC-735*/0x04,
        /*IC-728*/0x38,
        /*IC-726*/0x30,
        /*IC-725*/0x28,
        /*IC-718*/0x5e,
        /*IC-707*/0x3e,
        /*IC-703*/0x68,
        /*IC-475*/0x14,
        /*IC-471*/0x22,
        /*IC-275*/0x10,
        /*IC-275*/0x20,
        /*IC-92D*/0x20,// niama kod
        /*IC-78*/0x62,
        /*IC-R10*/0x52,
        /*IC-R20*/0x6c,
        /*IC-R71*/0x1a,
        /*IC-R72*/0x32,
        /*IC-R75*/0x5a,
        /*IC-R7000*/0x08,
        /*ICR-8500*/0x4a,
        /*IC-R7100*/0x34,
        /*IC-R9000*/0x2a,
        /*IC-R9500*/0x72,
        /*IC-RX7*/0x78,
        /*IC ID-1*/0x01,
        /*ID-5100*/0x8c,       
        /*Xiegu G90*/0x70,
        /*Xiegu X108G*/0x70,
        /*Xiegu X5105*/0x70,
        /*Xiegu X6100*/0x70,
    };
Icom::Icom(int ModelID,QWidget *parent)
        : QWidget(parent)
{
    s_ModelID = ModelID;
    s_model_addr = icom_addr_list[s_ModelID];
	s_rig_name = rigs_icom[s_ModelID].name;
    s_CmdID = -1;
    s_read_array.clear();
}
Icom::~Icom()
{
    //qDebug()<<"Delete"<<rigs_icom[s_ModelID].name;
}
/*#include <unistd.h>
struct icom_cmd_init
{
    int c_init;
    unsigned char init0[3][5];
};
static const icom_cmd_init init_0[ICOM_COUNT] =
    {
        {2,{{0x1a,0x05,0x00,0x92,0x00},{0x1a,0x05,0x00,0x79,0x00},{0}}},//IC-7000
        {2,{{0x1a,0x05,0x00,0x95,0x00},{0x1a,0x05,0x00,0x32,0x00},{0}}},//IC-7100
        {2,{{0x1a,0x03,0x48,0x00,0x00},{0x1a,0x03,0x37,0x00,0x00},{0}}},//IC-7200  FEFE76E0.1A0348.00.FD   FEFE76E0.1A0337.00.FD
        {3,{{0x1a,0x05,0x00,0x75,0x01},{0x1a,0x05,0x00,0x71,0x00},{0x1a,0x05,0x00,0x53,0x00}}},//IC-7300
        {3,{{0x1a,0x05,0x01,0x32,0x01},{0x1a,0x05,0x01,0x31,0x00},{0x1a,0x05,0x00,0x70,0x00}}},//IC-705
        {0,{{0},{0},{0}}},//IC-756
        {0,{{0},{0},{0}}},//IC-756PRO
        {2,{{0x1a,0x05,0x42,0x00,0x00},{0x1a,0x05,0x43,0x00,0x00},{0}}},//IC-756PROII FEFE64E0.1A0542.00.FD FEFE64E0.1A0543.00.FD
        {0,{{0},{0},{0}}},//IC-756PROIII
        {0,{{0},{0},{0}}},//IC-706
        {0,{{0},{0},{0}}},//IC-706MkII
        {0,{{0},{0},{0}}},//IC-706MkIIG
        {2,{{0x1a,0x05,0x00,0x58,0x00},{0x1a,0x05,0x00,0x40,0x00},{0}}},//IC-9100
        {3,{{0x1a,0x05,0x01,0x30,0x01},{0x1a,0x05,0x01,0x27,0x00},{0x1a,0x05,0x00,0x67,0x00}}},//IC-9700
        {3,{{0x1a,0x05,0x01,0x01,0x00},{0x1a,0x05,0x01,0x02,0x00},{0x1a,0x05,0x00,0x97,0x00}}},//IC-7800
        {3,{{0x1a,0x05,0x01,0x58,0x01},{0x1a,0x05,0x01,0x55,0x00},{0x1a,0x05,0x01,0x40,0x00}}},//IC-785x
        {3,{{0x1a,0x05,0x00,0x95,0x00},{0x1a,0x05,0x00,0x96,0x00},{0x1a,0x05,0x00,0x91,0x00}}},//IC-7700
        {3,{{0x1a,0x05,0x00,0x97,0x00},{0x1a,0x05,0x00,0x98,0x00},{0x1a,0x05,0x00,0x89,0x00}}},//IC-7600
        {3,{{0x1a,0x05,0x01,0x16,0x01},{0x1a,0x05,0x01,0x12,0x00},{0x1a,0x05,0x00,0x62,0x00}}},//IC-7610
        {2,{{0x1a,0x05,0x00,0x40,0x00},{0x1a,0x05,0x00,0x33,0x00},{0}}},//IC-7410
        {0,{{0},{0},{0}}},//IC-1275
        {0,{{0},{0},{0}}},//IC-970
        {0,{{0},{0},{0}}},//IC-910
        {0,{{0},{0},{0}}},//IC-821H
        {0,{{0},{0},{0}}},//IC-820H
        {0,{{0},{0},{0}}},//IC-781
        {0,{{0},{0},{0}}},//IC-775
        {0,{{0},{0},{0}}},//IC-765
        {0,{{0},{0},{0}}},//IC-761
        {0,{{0},{0},{0}}},//IC-751
        {0,{{0},{0},{0}}},//IC-746
        {2,{{0x1a,0x05,0x36,0x00,0x00},{0x1a,0x05,0x37,0x00,0x00},{0}}},//IC-746PRO FEFE66E0.1A0536.00.FD   FEFE66E0.1A0537.00.FD
        {0,{{0},{0},{0}}},//IC-738
        {0,{{0},{0},{0}}},//IC-737
        {0,{{0},{0},{0}}},//IC-736
        {0,{{0},{0},{0}}},//IC-735
        {0,{{0},{0},{0}}},//IC-728
        {0,{{0},{0},{0}}},//IC-726
        {0,{{0},{0},{0}}},//IC-725
        {0,{{0},{0},{0}}},//IC-718
        {0,{{0},{0},{0}}},//IC-707
        {0,{{0},{0},{0}}},//IC-703
        {0,{{0},{0},{0}}},//IC-475
        {0,{{0},{0},{0}}},//IC-471
        {0,{{0},{0},{0}}},//IC-275
        {0,{{0},{0},{0}}},//IC-275
        {0,{{0},{0},{0}}},//IC-92D
        {0,{{0},{0},{0}}},//IC-78
        {0,{{0},{0},{0}}},//IC-R10
        {0,{{0},{0},{0}}},//IC-R20
        {0,{{0},{0},{0}}},//IC-R71
        {0,{{0},{0},{0}}},//IC-R72
        {0,{{0},{0},{0}}},//IC-R75
        {0,{{0},{0},{0}}},//IC-R7000
        {0,{{0},{0},{0}}},//ICR-8500
        {0,{{0},{0},{0}}},//IC-R7100
        {0,{{0},{0},{0}}},//IC-R9000
        {0,{{0},{0},{0}}},//IC-R9500
        {0,{{0},{0},{0}}},//IC-RX7
        {0,{{0},{0},{0}}},//IC ID-1
        {0,{{0},{0},{0}}} //ID-5100
    };
void Icom::SetOnOffCatCommand(bool f, int model_id, int fact_id)
{
    if (model_id!=s_ModelID || fact_id!=ICOM_ID)
        return;

    if (f && init_0[s_ModelID].c_init>0)
    {
    	int c_cmd = 5;
    	if (s_rig_name=="IC-7200" || s_rig_name=="IC-746PRO" || s_rig_name=="IC-756PROII") c_cmd = 4;
        unsigned char cmd[6];
        for (int i = 0; i<init_0[s_ModelID].c_init; ++i)
        {
            for (int j = 0; j<c_cmd; ++j) cmd[j]=init_0[s_ModelID].init0[i][j];
            make_cmd_all(cmd,c_cmd);
            //qDebug()<<"Icom CAT ON="<<QString("%1").arg(cmd[0], 0, 16)
            //<<QString("%1").arg(cmd[1], 0, 16)
            //<<QString("%1").arg(cmd[2], 0, 16)
            //<<QString("%1").arg(cmd[3], 0, 16)
            //<<QString("%1").arg(cmd[4], 0, 16);
            if (i<init_0[s_ModelID].c_init-1) usleep(150000);
        }
    }
    //else if (!f)
    //{
    //qDebug()<<"Icom CAT OFF SetOnOffCatCommand========================"<<f;
    //}
}*/
void Icom::SetCmd(CmdID i,ptt_t ptt,QString str)
{
    s_CmdID = -1;
    switch (i)
    {
    case GET_SETT:
        emit EmitRigSet(rigs_icom[s_ModelID]);
        break;
    case SET_PTT:
        set_ptt(ptt);
        break;
    case SET_FREQ:
        set_freq(str.toLongLong());
        break;
    case GET_FREQ:
        s_CmdID = GET_FREQ;
        get_freq();
        break;
    case SET_MODE:
        set_mode(str);
        break;
    case GET_MODE:
        s_CmdID = GET_MODE;
        get_mode();
        break;
    }
}
void Icom::make_cmd_all(unsigned char *comand_subcomand,int count_c)
{
    unsigned char cmd_all[128];
    int count = 0;
    cmd_all[0]=PR;
    count++;
    cmd_all[count]=PR;
    count++;
    cmd_all[count]=s_model_addr;
    count++;
    cmd_all[count]=CTRLID;
    count++;

    for (int i = 0; i<count_c; i++)
    {
        cmd_all[count]=comand_subcomand[i];
        count++;
    }

    cmd_all[count]=FI;
    count++; //qDebug()<<"CMD Count"<<count;    
    emit EmitWriteCmd((char *)cmd_all,count);
}
void Icom::set_ptt(ptt_t ptt)
{
    unsigned char cmd[3];

    if (ptt==RIG_PTT_ON)
    {
        cmd[0] = C_CTL_PTT;
        cmd[1] = S_PTT;
        cmd[2] = 1;
    }
    else
    {
        cmd[0] = C_CTL_PTT;
        cmd[1] = S_PTT;
        cmd[2] = 0;
    }
    make_cmd_all(cmd,3);
}
void Icom::set_freq(unsigned long long freq)
{
    unsigned char freqbuf[MAXFRAMELEN];//, ackbuf[MAXFRAMELEN];
    unsigned char cmd[MAXFRAMELEN+5];
    int freq_len = 5;
    int count_cmd = 0;
    //freq_len = 1 ? 4:5;  qDebug()<<"freq_len="<<freq_len;
    //QString mod731 = rigs_icom[s_ModelID].name;
    if (s_rig_name=="IC-735" || s_rig_name=="IC-820H" || s_rig_name=="IC-821H")
        freq_len = 4;

    to_bcd_(freqbuf, freq, freq_len*2);

    cmd[count_cmd] = C_SET_FREQ;
    count_cmd++;
    //cmd[count_cmd] = -1;         count_cmd++;
    //cmd[count_cmd] =  0;         count_cmd++;

    for (int i = 0; i<freq_len; i++)
    {
        cmd[count_cmd]=freqbuf[i];
        count_cmd++;
        //qDebug()<<freq<<"freqbuf="<<i<<(unsigned char)freqbuf[i];
    }
    make_cmd_all(cmd,count_cmd);
}
void Icom::set_mode(QString str)
{
    //#define S_USB	    0x01		/* Set to USB */
    //#define S_R7000_SSB	0x05	/* Set to SSB on R-7000 */
    //C_SET_MODE
    unsigned char mode = S_LSB;
    unsigned char bpmode = 0x01;  //0x01 <- slaga lentata na nai 6iroka 0x00<-ni6to ne prawi
    if (str=="USB")
    {
        if (s_rig_name=="IC-R7000")
        {
            mode = S_R7000_SSB;
            bpmode = 0x00;
        }
        else
        {
            mode = S_USB;
        }
    }
    else if (str=="LSB")
    {
        mode = S_LSB;
    }
    else
        return;

    unsigned char cmd[3];
    cmd[0] = C_SET_MODE;
    cmd[1] = mode;
    cmd[2] = bpmode;
    make_cmd_all(cmd,3);
}
void Icom::get_freq()
{
    unsigned char cmd[MAXFRAMELEN];
    cmd[0] = C_RD_FREQ;
    make_cmd_all(cmd,1);
}
void Icom::get_mode()
{
    unsigned char cmd[MAXFRAMELEN];
    cmd[0] = C_RD_MODE;
    make_cmd_all(cmd,1);
}
void Icom::SetReadyRead(QByteArray ar,int size)
{
    for (int i = 0; i < size; i++)
    {
        if (ar[i]==(char)FI)//FI=0xfd end of word EOM
        {
            //qDebug()<<"ICOM READ ALL COMMAND="<<(QString(s_read_array.toHex()))<<s_read_array.size();
            int size = s_read_array.size();
            //rejekt small array
            if (size < 5)
            {                
                s_read_array.clear();//qDebug()<<"NO INAF SIZE";
                return;
            }
            //rejekt no icom in network
            if (s_read_array[0]!=(char)PR || s_read_array[1]!=(char)PR)
            {                
                s_read_array.clear();//qDebug()<<"NO ICOM IN NETWORK";
                return;
            }
            //rejekt no my correspondent in network or my full duplex signal
            if (s_read_array[2]!=(char)CTRLID || s_read_array[3]!=(char)s_model_addr)
            {
                //qDebug()<<"NO MAY CORRESPONDENT OR FULL DUPLEX SIGNAL"<<size<<s_CmdID;
                s_read_array.clear();
                //2.55 may be no end, try to end,  may be echo is ON
                continue;
            }
            if (s_CmdID==GET_FREQ && s_read_array[4]==(char)C_RD_FREQ)//my qestion for freq and freq filter
            {
                if (size==10 || size==9)//bez fd=fi (size==10 || size==9)
                {
                    unsigned char fbsd[10];
                    int cfbsd = 0;
                    for (int j=5; j < size; j++)//2.12
                    {
                        fbsd[cfbsd]=(unsigned char)s_read_array[j];
                        cfbsd++;
                    }
                    unsigned long long f = from_bcd_(fbsd, cfbsd*2);
                    emit EmitReadedInfo(GET_FREQ,QString("%1").arg(f));
                    s_CmdID = -1;//I Find my answer no need more
                }
            }
            if (s_CmdID==GET_MODE && s_read_array[4]==(char)C_RD_MODE)//my qestion for mode and mode filter
            {
                if (size==7)//bez fd=fi
                {
                    unsigned char mod = (unsigned char)s_read_array[5];
                    QString smode = "WRONG_MODE";
                    if 		(mod==0x00) smode = "LSB"; //LSB=0x00
                    else if (mod==0x01) smode = "USB"; //USB=0x01 
                    else if (mod==0x02) smode = "AM";  //AM =0x02 
                    else if (mod==0x03) smode = "CWL";//CW-L=0x03  
                    else if (mod==0x04) smode = "DIGL";//DIGL=0x04  
                    else if (mod==0x05) smode = "FM";  //FM =0x05 
                    else if (mod==0x07) smode = "CWU";//CW-U=0x07                  
                    else if (mod==0x08) smode = "DIGU";//DATA-USB=0x08                        

                    emit EmitReadedInfo(GET_MODE,smode);
                    s_CmdID = -1;//I Find my answer no need more
                }
            }
            s_read_array.clear();
        }
        else if (ar[i]==(char)COL)//COL=0xfc collision detected
        {
            s_read_array.clear();//qDebug()<<"COLYSION READ";
            s_CmdID = -1;//see you in nex poll           
            return;
        }
        else
            s_read_array.append(ar[i]);
    }
    if (s_read_array.size()>512) s_read_array.clear(); //2.55 protection  max>256 something is wrong
}

