//Copyright+LGPL
//-----------------------------------------------------------------------------------------------------------------------------------------------
// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba
//-----------------------------------------------------------------------------------------------------------------------------------------------
// This file is part of MMVARI.
// MMVARI 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 3 of the License, or (at your option) any later version.
// MMVARI 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 MMTTY. If not, see
// .
//-----------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Cradio.h"
#include "ComLib.h"
#define WAITSTAT 0
const LPCSTR g_tRadioMode[]={
"LSB", "USB", "CW", "AM", "FM", "RTTY", "PACKET", "UNKNOWN"
};
CRADIOPARA RADIO;
void __fastcall InitRADIOPara(void)
{
RADIO.change = 1;
strcpy(RADIO.StrPort, "NONE"); // ポートの名前
RADIO.BaudRate = 4800; // ボーレート
RADIO.BitLen = 1; // 0-7Bit, 1-8Bit
RADIO.Stop = 1; // 0-1Bit, 1-2Bit
RADIO.Parity = 0; // 0-PN, 1-PE, 2-PO
RADIO.flwXON = 0; // Xon/Xoff ON
RADIO.flwCTS = 0; // CTS-RTS ON
RADIO.usePTT = 0;
RADIO.Cmdxx = 0;
RADIO.CmdInit = "";
RADIO.CmdRx = "\\$000000000F";
RADIO.CmdTx = "\\$000000010F\\w10";
RADIO.ByteWait = 0;
RADIO.cmdGNR = "";
RADIO.openGNR = 0;
RADIO.PollType = 0;
RADIO.PollInterval = 8;
RADIO.PollOffset = 3;
RADIO.PollScan = 0;
}
void __fastcall LoadRADIOSetup(TMemIniFile *pIniFile)
{
AnsiString as = RADIO.StrPort;
as = pIniFile->ReadString("RADIO", "PortName", as);
StrCopy(RADIO.StrPort, as.c_str(), 31);
RADIO.BaudRate = pIniFile->ReadInteger("RADIO", "BaudRate", RADIO.BaudRate);
RADIO.BitLen = pIniFile->ReadInteger("RADIO", "BitLen", RADIO.BitLen);
RADIO.Stop = pIniFile->ReadInteger("RADIO", "Stop", RADIO.Stop);
RADIO.Parity = pIniFile->ReadInteger("RADIO", "Parity", RADIO.Parity);
RADIO.flwXON = pIniFile->ReadInteger("RADIO", "flwXON", RADIO.flwXON);
RADIO.flwCTS = pIniFile->ReadInteger("RADIO", "flwCTS", RADIO.flwCTS);
RADIO.usePTT = pIniFile->ReadInteger("RADIO", "usePTT", RADIO.usePTT);
RADIO.ByteWait = pIniFile->ReadInteger("RADIO", "ByteWait", RADIO.ByteWait);
RADIO.Cmdxx = pIniFile->ReadInteger("RADIO", "Cmdxx", RADIO.Cmdxx);
RADIO.CmdInit = pIniFile->ReadString("RADIO", "CmdInit", RADIO.CmdInit);
RADIO.CmdRx = pIniFile->ReadString("RADIO", "CmdRx", RADIO.CmdRx);
RADIO.CmdTx = pIniFile->ReadString("RADIO", "CmdTx", RADIO.CmdTx);
RADIO.cmdGNR = pIniFile->ReadString("RADIO", "FileGNR", RADIO.cmdGNR);
RADIO.openGNR = pIniFile->ReadInteger("RADIO", "OpenGNR", RADIO.openGNR);
RADIO.PollType = pIniFile->ReadInteger("RADIO", "PollType", RADIO.PollType);
RADIO.PollInterval = pIniFile->ReadInteger("RADIO", "PollInterval", RADIO.PollInterval);
RADIO.PollOffset = pIniFile->ReadInteger("RADIO", "PollOffset", RADIO.PollOffset);
}
void __fastcall SaveRADIOSetup(TMemIniFile *pIniFile)
{
pIniFile->WriteString("RADIO", "PortName", RADIO.StrPort);
pIniFile->WriteInteger("RADIO", "BaudRate", RADIO.BaudRate);
pIniFile->WriteInteger("RADIO", "BitLen", RADIO.BitLen);
pIniFile->WriteInteger("RADIO", "Stop", RADIO.Stop);
pIniFile->WriteInteger("RADIO", "Parity", RADIO.Parity);
pIniFile->WriteInteger("RADIO", "flwXON", RADIO.flwXON);
pIniFile->WriteInteger("RADIO", "flwCTS", RADIO.flwCTS);
pIniFile->WriteInteger("RADIO", "usePTT", RADIO.usePTT);
pIniFile->WriteInteger("RADIO", "ByteWait", RADIO.ByteWait);
pIniFile->WriteInteger("RADIO", "Cmdxx", RADIO.Cmdxx);
pIniFile->WriteString("RADIO", "CmdInit", RADIO.CmdInit);
pIniFile->WriteString("RADIO", "CmdRx", RADIO.CmdRx);
pIniFile->WriteString("RADIO", "CmdTx", RADIO.CmdTx);
pIniFile->WriteString("RADIO", "FileGNR", RADIO.cmdGNR);
pIniFile->WriteInteger("RADIO", "OpenGNR", RADIO.openGNR);
pIniFile->WriteInteger("RADIO", "PollType", RADIO.PollType);
pIniFile->WriteInteger("RADIO", "PollInterval", RADIO.PollInterval);
pIniFile->WriteInteger("RADIO", "PollOffset", RADIO.PollOffset);
}
//---------------------------------------------------------------------------
// 注意: VCL オブジェクトのメソッドとプロパティを使用するには, Synchronize
// を使ったメソッド呼び出しでなければなりません。次に例を示します。
//
// Synchronize(UpdateCaption);
//
// ここで, UpdateCaption は次のように記述できます。
//
// void __fastcall CCradio::UpdateCaption()
// {
// Form1->Caption = "スレッドから書き換えました";
// }
//---------------------------------------------------------------------------
__fastcall CCradio::CCradio(bool CreateSuspended)
: TThread(CreateSuspended)
{
m_RigHz = m_FreqHz = 0;
if( RADIO.PollOffset < 3 ){
m_LSB = RADIO.PollOffset;
}
else {
m_LSB = 1;
}
m_RigMode = rmUNKNOWN;
m_CreateON = FALSE; // クリエイトフラグ
m_fHnd = NULL; // ファイルハンドル
m_wHnd = NULL; // 親のウインドウハンドル
m_uMsg = WM_USER;
m_ID = 0; // メッセージのID番号
m_Command = 0; // スレッドへのコマンド
m_TxAbort = 0; // 送信中止フラグ
m_txwp = m_txrp = m_txcnt = 0;
m_PSKGNRId = 0;
m_OpenGNR = 0;
m_PollCnt = 0;
m_PollCntHalf = -1;
m_PollInhibit = 0;
m_rxcnt = 0;
m_FreqEvent = 0;
m_Freq[0] = 0;
m_ScanAddr = 0;
m_pRadio = NULL;
m_CarrierFreq = 0;
}
//---------------------------------------------------------------------------
void __fastcall CCradio::Execute()
{
//---- スレッドのコードをここに記述 ----
// Priority = tpLower;
while(1){
if( Terminated == TRUE ){
return;
}
if( m_Command == CRADIO_CLOSE ){
m_Command = 0;
return;
}
if( m_CreateON == TRUE ){
if( m_txcnt ){
if( m_pRadio != NULL ){
if( !(m_pRadio->GetStatus() & mmrpstatusTXBUSY) ){
m_pRadio->PutChar(m_txbuf[m_txrp]);
m_txrp++;
if( m_txrp >= RADIO_TXBUFSIZE ){
m_txrp = 0;
}
m_txcnt--;
}
}
else if( !TxBusy() ){
DWORD size=0;
::WriteFile( m_fHnd, &m_txbuf[m_txrp], 1, &size, NULL );
if( size ){
m_txrp++;
if( m_txrp >= RADIO_TXBUFSIZE ){
m_txrp = 0;
}
m_txcnt--;
}
if( RADIO.ByteWait ) ::Sleep(RADIO.ByteWait);
}
::Sleep(1);
}
else if( m_pRadio != NULL ){
if( m_pRadio->GetStatus() & mmrpstatusFREQ ){
long fq = m_pRadio->GetFreq();
if( fq ) UpdateFreq(double(fq)/1e4);
}
while(m_pRadio->GetStatus() & mmrpstatusRX){
CatchPoll(m_pRadio->GetChar());
}
::Sleep(10);
}
else {
BYTE dmy[256];
while(1){
int len = RecvLen();
if( !len ) break;
if( len >= sizeof(dmy) ) len = sizeof(dmy);
Read(dmy, len);
if( RADIO.PollType ){
BYTE *p = dmy;
for( ; len; p++, len-- ){
CatchPoll(*p);
}
}
}
::Sleep(10);
}
}
else {
::Sleep(10);
}
}
}
//---------------------------------------------------------------------------
/*#$%
==============================================================
通信回線をオープンしスレッドをアクティブにする
--------------------------------------------------------------
PortName : 回線の名前
pCP : COMMPARAのポインタ(ヌルの時はデフォルトで初期化)
pWnd : メッセージ送信先のウインドウクラスのポインタ(ヌルの時はメインフレームウインドウ)
nID : データ受信時のメッセージID
RBufSize : 受信バッファのサイズ(default=2048)
TBufSize : 送信バッファのサイズ(default=2048)
--------------------------------------------------------------
TRUE/FALSE
--------------------------------------------------------------
==============================================================
*/
BOOL __fastcall CCradio::Open(CRADIOPARA *cp, HWND hwnd, UINT uMsg, UINT nID)
{
if( m_CreateON == TRUE ) Close();
m_RigHz = m_FreqHz = 0;
m_TxAbort = FALSE;
m_PSKGNRId = 0;
m_OpenGNR = 0;
if( !strcmpi(cp->StrPort, "PSKGNR") || !strcmpi(cp->StrPort, "WD5GNR") || !strcmpi(cp->StrPort, "LOGGER")){
m_PSKGNRId = ::RegisterWindowMessage("PSKGNRFUNC");
m_CreateON = TRUE;
if( RADIO.openGNR && (!RADIO.cmdGNR.IsEmpty()) && (strcmpi(cp->StrPort, "LOGGER")) ){
if( FindWindow("ThunderRT6Main", NULL) == NULL ){
::WinExec(RADIO.cmdGNR.c_str(), SW_HIDE);
m_OpenGNR = 1;
}
}
return m_CreateON;
}
m_fHnd = ::CreateFile(cp->StrPort, GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if( m_fHnd == INVALID_HANDLE_VALUE ){
AnsiString as = "\\\\.\\";
as += cp->StrPort;
m_fHnd = ::CreateFile(as.c_str(), GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
}
m_wHnd = hwnd;
m_uMsg = uMsg;
m_ID = nID;
if( m_fHnd == INVALID_HANDLE_VALUE ) goto _mmr;
// setup device buffers
if( ::SetupComm( m_fHnd, DWORD(RADIO_COMBUFSIZE), DWORD(RADIO_COMBUFSIZE) ) == FALSE ){
::CloseHandle(m_fHnd);
_mmr:;
m_pRadio = new CMMRadio(hwnd, uMsg);
if( m_pRadio->Open(cp->StrPort) ){
m_CreateON = TRUE;
Priority = tpLower;
Resume(); // スレッドの実行
return TRUE;
}
else {
delete m_pRadio;
m_pRadio = NULL;
return FALSE;
}
}
// purge any information in the buffer
::PurgeComm( m_fHnd, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
// set up for overlapped I/O
COMMTIMEOUTS TimeOut;
TimeOut.ReadIntervalTimeout = 0xffffffff;
TimeOut.ReadTotalTimeoutMultiplier = 0;
TimeOut.ReadTotalTimeoutConstant = 0;
TimeOut.WriteTotalTimeoutMultiplier = 0;
TimeOut.WriteTotalTimeoutConstant = 20000;
// TimeOut.WriteTotalTimeoutConstant = 1;
if( !::SetCommTimeouts( m_fHnd, &TimeOut ) ){
::CloseHandle( m_fHnd );
return FALSE;
}
::GetCommState( m_fHnd, &m_dcb );
m_dcb.BaudRate = cp->BaudRate;
m_dcb.fBinary = TRUE;
m_dcb.ByteSize = USHORT(cp->BitLen ? 8 : 7);
const UCHAR _tp[]={NOPARITY, EVENPARITY, ODDPARITY};
m_dcb.Parity = _tp[cp->Parity];
const UCHAR _ts[]={ONESTOPBIT,TWOSTOPBITS};
m_dcb.StopBits = _ts[cp->Stop];
if( cp->usePTT ){
m_dcb.fRtsControl = RTS_CONTROL_DISABLE; // 送信禁止
m_dcb.fDtrControl = DTR_CONTROL_DISABLE; // 送信禁止
}
else {
m_dcb.fRtsControl = RTS_CONTROL_ENABLE;
}
m_dcb.fOutxCtsFlow = (cp->flwCTS && !cp->usePTT) ? TRUE : FALSE;
m_dcb.fInX = m_dcb.fOutX = cp->flwXON ? TRUE : FALSE;
m_dcb.XonChar = 0x11;
m_dcb.XoffChar = 0x13;
m_dcb.fParity = FALSE;
m_dcb.EvtChar = 0x0d; // dummy setting
// m_dcb.fTXContinueOnXoff = TRUE;
m_dcb.XonLim = USHORT(RADIO_COMBUFSIZE/4); // 1/4 of RBufSize
m_dcb.XoffLim = USHORT(RADIO_COMBUFSIZE*3/4); // 3/4 of RBufSize
m_dcb.DCBlength = sizeof( DCB );
if( !::SetCommState( m_fHnd, &m_dcb ) ){
::CloseHandle( m_fHnd );
return FALSE;
}
// get any early notifications
if( !::SetCommMask( m_fHnd, EV_RXFLAG ) ){
::CloseHandle(m_fHnd);
return FALSE;
}
m_CreateON = TRUE;
Priority = tpLower;
Resume(); // スレッドの実行
return TRUE;
}
/*#$%
==============================================================
通信回線をクローズする
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
スレッドが終了するまで待つ
==============================================================
*/
void __fastcall CCradio::Close(void)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ){
if( (m_OpenGNR || RADIO.change) && RADIO.openGNR ) ::SendMessage(HWND_BROADCAST, m_PSKGNRId, 1 , 0);
m_PSKGNRId = 0;
}
else {
if( m_ID ){
m_Command = CRADIO_CLOSE; // スレッド終了コマンド
Priority = tpNormal; //スレッドは通常の優先度である
WaitFor();
}
if( m_pRadio != NULL ){
delete m_pRadio;
m_pRadio = NULL;
}
else {
::CloseHandle(m_fHnd);
}
}
}
m_CreateON = FALSE;
m_TxAbort = TRUE;
}
void __fastcall CCradio::ReqClose(void)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ){
return;
}
else {
if( m_ID ){
m_Command = CRADIO_CLOSE; // スレッド終了コマンド
Priority = tpNormal; //スレッドは通常の優先度である
}
}
}
}
void __fastcall CCradio::WaitClose(void)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ){
if( (m_OpenGNR || RADIO.change) && RADIO.openGNR ) ::SendMessage(HWND_BROADCAST, m_PSKGNRId, 1 , 0);
m_PSKGNRId = 0;
}
else {
if( m_ID && m_Command ){
WaitFor();
}
if( m_pRadio != NULL ){
delete m_pRadio;
m_pRadio = NULL;
}
else {
::CloseHandle(m_fHnd);
}
}
m_CreateON = FALSE;
}
m_TxAbort = TRUE;
}
/*#$%
==============================================================
受信バッファ内の格納データ長を得る
--------------------------------------------------------------
--------------------------------------------------------------
データの長さ
--------------------------------------------------------------
==============================================================
*/
DWORD __fastcall CCradio::RecvLen(void)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
::ClearCommError( m_fHnd, &dwErrorFlags, &ComStat );
return ComStat.cbInQue;
}
/*#$%
==============================================================
送信ビジーかどうか調べる
--------------------------------------------------------------
--------------------------------------------------------------
: 送信ビジー状態
--------------------------------------------------------------
==============================================================
*/
int __fastcall CCradio::TxBusy(void)
{
#if 0
COMSTAT ComStat;
DWORD dwErrorFlags;
if( m_TxAbort ) return FALSE;
ClearCommError( m_fHnd, &dwErrorFlags, &ComStat );
int f = ComStat.fRlsdHold;
if( f ) return TRUE;
if( m_dcb.fOutxCtsFlow ){
f |= ComStat.fCtsHold;
}
if( m_dcb.fOutX ){
f |= ComStat.fXoffHold;
}
return f ? TRUE : FALSE;
#else
COMSTAT ComStat;
DWORD dwErrorFlags;
::ClearCommError( m_fHnd, &dwErrorFlags, &ComStat );
return ComStat.cbOutQue;
#endif
}
/*#$%
==============================================================
通信回線からデータを取り出す
--------------------------------------------------------------
p : バッファのポインタ
len : バッファのサイズ
--------------------------------------------------------------
実際に受信したサイズ
--------------------------------------------------------------
==============================================================
*/
DWORD __fastcall CCradio::Read(BYTE *p, DWORD len)
{
DWORD size=0;
if( m_CreateON == TRUE ){
::ReadFile( m_fHnd, p, len, &size, NULL );
}
return size;
}
/*#$%
==============================================================
通信回線にデータを送信する
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
==============================================================
*/
void __fastcall CCradio::PutChar(char c)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ) return;
if( m_txcnt < RADIO_TXBUFSIZE ){
m_txbuf[m_txwp] = c;
m_txwp++;
if( m_txwp >= RADIO_TXBUFSIZE ) m_txwp = 0;
m_txcnt++;
}
}
}
/*#$%
==============================================================
通信回線にデータを送信する
--------------------------------------------------------------
p : バッファのポインタ
len : 送信するサイズ
--------------------------------------------------------------
実際に送信したサイズ
--------------------------------------------------------------
==============================================================
*/
void __fastcall CCradio::Write(void *s, DWORD len)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ) return;
char *p;
for( p = (char *)s; len; len--, p++ ){
PutChar(*p);
}
}
}
/*#$%
==============================================================
通信回線にデータを送信する
--------------------------------------------------------------
p : バッファのポインタ
len : 送信するサイズ
--------------------------------------------------------------
実際に送信したサイズ
--------------------------------------------------------------
==============================================================
*/
void CCradio::OutStr(LPCSTR fmt, ...)
{
va_list pp;
char bf[1024];
va_start(pp, fmt);
vsprintf( bf, fmt, pp );
va_end(pp);
Write(bf, strlen(bf));
}
void CCradio::OutLine(LPCSTR fmt, ...)
{
va_list pp;
char bf[1024];
va_start(pp, fmt);
vsprintf( bf, fmt, pp );
va_end(pp);
Write(bf, strlen(bf));
char r[] = "\r"; //JA7UDE 0428
Write(r, 1); //JA7UDE 0428
}
void __fastcall CCradio::SendCommand(LPCSTR p)
{
int c;
int f;
for(f = 0; *p; p++){
if( *p == '\\' ){
f = 0;
p++;
switch(*p){
case '$':
f = 1;
continue;
case 'x':
case 'X':
p++;
if( *p == 'x' ){
c = RADIO.Cmdxx;
}
else {
c = htoin(p, 2);
}
p++;
break;
case 'r':
c = CR;
break;
case 'n':
c = LF;
break;
case 'w':
p++;
c = atoin(p, 2);
if( (c < 0) || (c >= 100) ) c = 100;
if( c ) ::Sleep(c * 10);
p++;
continue;
case '\\':
c = '\\';
break;
case 'c': // comment
return;
}
}
else if( f ){
p = SkipSpace(p);
if( *p == 'x' ){
c = RADIO.Cmdxx;
}
else {
c = htoin(p, 2);
}
p++;
}
else {
c = *p;
}
PutChar(BYTE(c));
}
}
void __fastcall CCradio::SetPTT(int sw)
{
if( m_PSKGNRId ){
::SendMessage(HWND_BROADCAST, m_PSKGNRId, 0 , sw ? 1 : 0);
if( sw ) ::Sleep(50);
}
else {
if( sw ){
if( m_pRadio != NULL ){
m_pRadio->SetPTT(sw);
}
else if( RADIO.usePTT ){
::EscapeCommFunction(m_fHnd, SETRTS);
::EscapeCommFunction(m_fHnd, SETDTR);
}
SendCommand(RADIO.CmdTx.c_str());
}
else {
if( m_pRadio != NULL ){
m_pRadio->SetPTT(sw);
}
else if( RADIO.usePTT ){
::EscapeCommFunction(m_fHnd, CLRRTS);
::EscapeCommFunction(m_fHnd, CLRDTR);
}
SendCommand(RADIO.CmdRx.c_str());
}
}
}
//--------------------------------------------------------
// 周波数が変化しているかどうか調べる
int __fastcall CCradio::IsFreqChange(LPCSTR pFreq)
{
if( RADIO.PollType ){
if( m_FreqEvent ) return 1;
if( m_Freq[0] ){
if( strcmp(m_Freq, pFreq) ) return 1;
}
}
return 0;
}
//--------------------------------------------------------
void __fastcall CCradio::WaitICOM(int interval)
{
if( interval ){
switch(RADIO.PollType){
case RADIO_POLLICOM:
case RADIO_POLLOMNIVI:
m_PollInhibit = 500 / interval;
::Sleep(100);
break;
}
}
}
//--------------------------------------------------------
// タイマー処理
void __fastcall CCradio::Timer(int tx, int interval)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ) return;
if( m_pRadio != NULL ){
if( m_pRadio->GetStatus() & mmrpstatusDEFCMD ){
LPCSTR p;
switch(m_pRadio->GetDefCommand()){
case 1:
p = RADIO.CmdTx.c_str();
break;
case 2:
p = RADIO.CmdRx.c_str();
break;
default:
p = RADIO.CmdInit.c_str();
break;
}
SendCommand(p);
m_PollCnt = (2 + RADIO.PollInterval);
if( interval ){
m_PollCnt = m_PollCnt * 100 / interval;
if( !m_PollCnt ) m_PollCnt++;
}
}
}
if( (!tx) && RADIO.PollType && (!m_PollInhibit) ){
if( (m_PollCnt == m_PollCntHalf) && (RADIO.PollOffset == 3) ){
switch(RADIO.PollType){
case RADIO_POLLICOM:
case RADIO_POLLOMNIVI:
if( !m_ScanAddr ){
m_rxcnt = 0;
SendCommand("\\$FEFExxE004FD");
}
break;
case RADIO_POLLICOMN:
case RADIO_POLLOMNIVIN:
if( (m_RigMode == rmUNKNOWN) && !m_ScanAddr ){
m_rxcnt = 0;
SendCommand("\\$FEFExxE004FD");
}
break;
}
}
if( !m_PollCnt ){
if( m_pRadio != NULL ) m_pRadio->Polling();
if( m_ScanAddr ){ // アドレススキャン
m_PollCnt = 4;
if( m_ScanAddr <= 3 ){
m_ScanAddr++;
}
else {
RADIO.Cmdxx++;
if( RADIO.Cmdxx >= 0x80 ){
RADIO.Cmdxx = 0;
}
}
}
else {
m_PollCnt = (2 + RADIO.PollInterval);
}
if( interval ){
m_PollCnt = m_PollCnt * 100 / interval;
m_PollCntHalf = m_PollCnt / 2;
if( !m_PollCnt ) m_PollCnt++;
}
switch(RADIO.PollType){
case RADIO_POLLYAESUHF:
case RADIO_POLLFT1000D:
case RADIO_POLLFT920:
m_rxcnt = 0;
SendCommand("\\$0000000210");
break;
case RADIO_POLLYAESUVU:
m_rxcnt = 0;
SendCommand("\\$0000000003");
break;
//1.66B AA6YQ
case RADIO_POLLFT9000:
case RADIO_POLLFT2000:
case RADIO_POLLFT950:
case RADIO_POLLFT450:
m_rxcnt = 0;
SendCommand("IF;");
break;
case RADIO_POLLICOM:
case RADIO_POLLOMNIVI:
m_rxcnt = 0;
SendCommand("\\$FEFExxE003FD");
break;
case RADIO_POLLICOMN:
case RADIO_POLLOMNIVIN:
if( !m_Freq[0] || m_ScanAddr ){
m_rxcnt = 0;
SendCommand("\\$FEFExxE003FD");
}
break;
case RADIO_POLLKENWOOD:
m_rxcnt = 0;
SendCommand("IF;");
break;
case RADIO_POLLKENWOODN:
if( !m_Freq[0] ){
m_rxcnt = 0;
SendCommand("AI1;");
}
break;
case RADIO_POLLJST245:
m_rxcnt = 0;
SendCommand("I\r\n");
break;
case RADIO_POLLJST245N:
if( !m_Freq[0] ){
m_rxcnt = 0;
SendCommand("I1\r\nL\r\n");
}
break;
default:
break;
}
}
m_PollCnt--;
}
if( m_PollInhibit ) m_PollInhibit--;
}
}
//--------------------------------------------------------
// 周波数ポーリングデータの受信
void __fastcall CCradio::CatchPoll(BYTE c)
{
switch(RADIO.PollType){
case RADIO_POLLYAESUHF:
case RADIO_POLLFT1000D:
case RADIO_POLLFT920:
if( m_rxcnt < 8 ){
m_rxbuf[m_rxcnt] = c;
m_rxcnt++;
if( m_rxcnt == 8 ){
FreqYaesuHF();
}
}
break;
case RADIO_POLLYAESUVU:
if( m_rxcnt < 5 ){
m_rxbuf[m_rxcnt] = c;
m_rxcnt++;
if( m_rxcnt == 5 ){
FreqYaesuVU();
}
}
break;
//1.66B AA6YQ
case RADIO_POLLFT9000:
case RADIO_POLLFT2000:
case RADIO_POLLFT950:
case RADIO_POLLFT450:
if( m_rxcnt < sizeof(m_rxbuf) ){
if( (c != 0x0d) && (c != 0x0f) ){
if( (c != ' ') || m_rxcnt ){
m_rxbuf[m_rxcnt] = c; // Data
m_rxcnt++;
if( c == ';' ){
if( (m_rxbuf[0] == 'I') && (m_rxbuf[1]=='F') ){
if( m_rxcnt >= 13 ) FreqYaesu9K2K();
}
m_rxcnt = 0;
}
}
}
}
else {
m_rxcnt = 0;
}
break;
case RADIO_POLLICOM:
case RADIO_POLLICOMN:
case RADIO_POLLOMNIVI:
case RADIO_POLLOMNIVIN:
switch(m_rxcnt){
case 0:
if( c == 0xfe ){
m_rxbuf[m_rxcnt] = c; // プリアンブル
m_rxcnt++;
}
break;
case 1:
if( c != 0xfe ){
if( (c >= 0x80) || (!m_ScanAddr&&(c == 0x00)&&((RADIO.PollType == RADIO_POLLICOMN)||(RADIO.PollType == RADIO_POLLOMNIVIN))) ){
m_rxbuf[m_rxcnt] = c; // PC-Addr
m_rxcnt++;
}
else {
m_rxcnt = 0;
}
}
// if( (c != 0xfe) && (c >= 0x80) ){
// m_rxbuf[m_rxcnt] = c; // PC-Addr
// m_rxcnt++;
// }
break;
case 2:
if( (c == RADIO.Cmdxx) || (!RADIO.Cmdxx) ||
(m_ScanAddr && c) ){
m_rxbuf[m_rxcnt] = c; // Radio-Addr
m_rxcnt++;
}
else {
m_rxcnt = 0;
}
break;
case 3:
// if( (c == 0x03) || ((c == 0x00)&&((RADIO.PollType == RADIO_POLLICOMN)||(RADIO.PollType == RADIO_POLLOMNIVIN))) ){
if( (c == 0x03) || (c == 0x04) ){
m_rxbuf[m_rxcnt] = c; // Respons-command
m_rxcnt++;
}
else if( ((c == 0x00)||(c == 0x01)) && ((RADIO.PollType == RADIO_POLLICOMN)||(RADIO.PollType == RADIO_POLLOMNIVIN)) ){
m_rxbuf[m_rxcnt] = c; // Respons-command
m_rxcnt++;
}
else {
m_rxcnt = 0;
}
break;
default:
if( m_rxcnt < sizeof(m_rxbuf) ){
m_rxbuf[m_rxcnt] = c; // Data
m_rxcnt++;
if( c == 0xfd ){
if( m_rxcnt >= 5 ){
FreqICOM();
// if( (m_ScanAddr && m_rxbuf[2]) || (!RADIO.Cmdxx) ){
if( (m_ScanAddr && m_rxbuf[2]) ){
RADIO.Cmdxx = m_rxbuf[2];
RADIO.PollScan = 0;
m_ScanAddr = 0;
}
}
m_rxcnt = 0;
}
}
else {
m_rxcnt = 0;
}
break;
}
break;
case RADIO_POLLKENWOOD:
case RADIO_POLLKENWOODN:
if( m_rxcnt < sizeof(m_rxbuf) ){
if( (c != 0x0d) && (c != 0x0a) ){
if( (c != ' ') || m_rxcnt ){
m_rxbuf[m_rxcnt] = c; // Data
m_rxcnt++;
if( c == ';' ){
if( (m_rxbuf[0] == 'I') && (m_rxbuf[1]=='F') ){
if( m_rxcnt >= 13 ) FreqKenwood();
}
m_rxcnt = 0;
}
}
}
}
else {
m_rxcnt = 0;
}
break;
case RADIO_POLLJST245:
case RADIO_POLLJST245N:
if( m_rxcnt < sizeof(m_rxbuf) ){
if( (c == 'I') || m_rxcnt ){
m_rxbuf[m_rxcnt] = c; // Data
m_rxcnt++;
if( (c == 0x0d) || (c == 0x0a) ){
if( m_rxcnt >= 12 ) FreqJST245();
m_rxcnt = 0;
}
}
}
else {
m_rxcnt = 0;
}
break;
default:
break;
}
}
//----------------------------------------------------------
void __fastcall CCradio::SetCarrierFreq(int fq)
{
int offset = fq - m_CarrierFreq;
m_CarrierFreq = fq;
if( m_FreqHz ){
if( RADIO.PollOffset < 3 ) m_LSB = RADIO.PollOffset;
switch(m_LSB){
case 1:
case 3:
m_FreqHz -= offset;
break;
default:
m_FreqHz += offset;
break;
}
}
}
//----------------------------------------------------------
BOOL __fastcall CCradio::IsRigLSB(void)
{
return m_LSB == 1;
}
//----------------------------------------------------------
// モードの更新
//
void __fastcall CCradio::SetInternalRigMode(LPCSTR pMode)
{
int mode = 0;
int oldmode = m_RigMode;
m_RigMode = FindStringTable(g_tRadioMode, pMode, AN(g_tRadioMode));
if( m_RigMode < 0 ) m_RigMode = rmUNKNOWN;
switch(m_RigMode){
case rmLSB:
case rmRTTY:
case rmPACKET:
mode = 1;
break;
case rmUSB:
mode = 2;
break;
}
m_LSB = mode;
if( mode ){
if( RADIO.PollOffset < 3 ) RADIO.PollOffset = mode;
if( oldmode != m_RigMode ){
CalcRigFreq(m_RigHz*1.0e-6);
}
}
}
//----------------------------------------------------------
// 周波数の更新 (freq=MHz)
//
double __fastcall CCradio::CalcRigFreq(double freq)
{
m_RigHz = (freq * 1.0e6) + 0.5;
switch(m_LSB){
case 1: // LSB
freq -= m_CarrierFreq/1000000.0;
break;
case 2: // USB
freq += m_CarrierFreq/1000000.0;
break;
case 3: // CW-LSB
freq -= (m_CarrierFreq-700)/1000000.0;
break;
case 4: // CW-USB
freq += (m_CarrierFreq-700)/1000000.0;
break;
default:
break;
}
m_FreqHz = (freq * 1.0e6) + 0.5;
return freq;
}
//----------------------------------------------------------
// 周波数の更新 (freq=MHz)
//
void __fastcall CCradio::UpdateFreq(double freq)
{
if( freq < 0.001 ) return;
if( RADIO.PollOffset < 3 ) m_LSB = RADIO.PollOffset;
#if 1
freq = CalcRigFreq(freq);
#else
m_RigHz = (freq * 1.0e6) + 0.5;
switch(m_LSB){
case 1: // LSB
freq -= m_CarrierFreq/1000000.0;
break;
case 2: // USB
freq += m_CarrierFreq/1000000.0;
break;
case 3: // CW-LSB
freq -= (m_CarrierFreq-700)/1000000.0;
break;
case 4: // CW-USB
freq += (m_CarrierFreq-700)/1000000.0;
break;
default:
break;
}
m_FreqHz = (freq * 1.0e6) + 0.5;
#endif
char bf[32];
sprintf(bf, "%.3lf", freq);
if( strcmp(m_Freq, bf) ){
strcpy(m_Freq, bf);
m_FreqEvent = 1;
}
}
void __fastcall CCradio::FreqYaesuHF(void)
{
ULONG fq;
fq = m_rxbuf[1];
fq = fq << 8;
fq |= m_rxbuf[2];
fq = fq << 8;
fq |= m_rxbuf[3];
fq = fq << 8;
fq |= m_rxbuf[4];
double f;
switch(RADIO.PollType){
case RADIO_POLLFT1000D: // FT1000D
f = 25600000.0;
break;
case RADIO_POLLFT920: // FT920
f = 1000000.0;
break;
default: // FT1000MP
f = 1600000.0;
break;
}
UpdateFreq(double(fq)/f);
if( RADIO.PollOffset < 3 ) return;
switch(m_rxbuf[7]){
case 0: // LSB
m_LSB = 1;
m_RigMode = rmLSB;
break;
case 1: // USB
m_LSB = 2;
m_RigMode = rmUSB;
break;
case 2: // CW
m_LSB = 0;
m_RigMode = rmCW;
break;
case 3: // AM
m_LSB = 0;
m_RigMode = rmAM;
break;
case 4: // FM
m_LSB = 0;
m_RigMode = rmFM;
break;
case 5: // RTTY
m_LSB = 1;
m_RigMode = rmRTTY;
break;
case 6: // PACKET
m_LSB = 1;
m_RigMode = rmPACKET;
break;
default: // Other
m_LSB = 0;
m_RigMode = rmUNKNOWN;
break;
}
}
void __fastcall CCradio::FreqYaesuVU(void)
{
ULONG fq;
fq = m_rxbuf[0] >> 4;
fq *= 10;
fq += m_rxbuf[0] & 0x0f;
fq *= 10;
fq += m_rxbuf[1] >> 4;
fq *= 10;
fq += m_rxbuf[1] & 0x0f;
fq *= 10;
fq += m_rxbuf[2] >> 4;
fq *= 10;
fq += m_rxbuf[2] & 0x0f;
fq *= 10;
fq += m_rxbuf[3] >> 4;
fq *= 10;
fq += m_rxbuf[3] & 0x0f;
UpdateFreq( double(fq) / 100000.0 );
if( RADIO.PollOffset < 3 ) return;
switch(m_rxbuf[4]){
case 0x00: // LSB
m_LSB = 1;
m_RigMode = rmLSB;
break;
case 0x01: // USB
m_LSB = 2;
m_RigMode = rmUSB;
break;
case 0x03: // CW-LSB
case 0x83:
m_LSB = 3;
m_RigMode = rmCW;
break;
case 0x02: // CW-USB
case 0x82:
m_LSB = 4;
m_RigMode = rmCW;
break;
case 0x04: // AM
case 0x84:
m_LSB = 0;
m_RigMode = rmAM;
break;
case 0x08: // FM
case 0x88:
m_LSB = 0;
m_RigMode = rmFM;
break;
default: // Other
m_LSB = 0;
m_RigMode = rmUNKNOWN;
break;
}
}
//AA6YQ 1.66B
void __fastcall CCradio::FreqYaesu9K2K(void)
{
//0 1 2 3
//01234567890123456789012345678901234567890
//IF00021155000 +001000 0002000008 ;
//abcdefghijklmnopqrstuvwxyz1234567890 <---- 桁位置
//c - m 周波数 21.155000MHz
//x 0 = RIT off 1 = RIT on
//z 0 = XIT off 1 = XIT on
//12 M.CH
//4 モード 1=LSB 2=USB 3=CW 4=FM 5=AM 6=RTTY
//567 000=RX:A TX:A 001=RX:A TX=B 100=RX:B TX:B 101=RX:B TX=A
ULONG fq = 0;
m_rxbuf[13] = 0;
if( sscanf((LPCSTR)&m_rxbuf[5], "%lu", &fq) == 1 ){
if( fq ) UpdateFreq(double(fq)/1e6);
}
if( RADIO.PollOffset < 3 ) return;
switch(m_rxbuf[29]){
case '1': // LSB
m_LSB = 1;
m_RigMode = rmLSB;
break;
case '2': // USB
m_LSB = 2;
m_RigMode = rmUSB;
break;
case '3': // CW
m_LSB = 0;
m_RigMode = rmCW;
break;
case '4': // FM
m_LSB = 0;
m_RigMode = rmFM;
break;
case '5': // AM
m_LSB = 0;
m_RigMode = rmAM;
break;
case '6': // RTTY
m_LSB = 1;
m_RigMode = rmRTTY;
break;
default: // Other
m_LSB = 0;
m_RigMode = rmUNKNOWN;
break;
}
}
void __fastcall CCradio::FreqICOM(void)
{
// 0 1 2 3 4 5 6 7 8 9
// fe e0 40 03 90 09 02 07 00 fd 0007020990
// fe e0 40 03 90 09 02 07 fd 07020990
// fe e0 40 04 xx fd
if( (m_rxbuf[3] == 0x03) || (m_rxbuf[3] == 0x00) ){ // Freq
ULONG fq = 0;
if( m_rxbuf[8] != 0xfd ){
fq = (m_rxbuf[8] >> 4);
fq *= 10;
fq += (m_rxbuf[8] & 0x0f);
}
fq *= 10;
fq += m_rxbuf[7] >> 4;
fq *= 10;
fq += m_rxbuf[7] & 0x0f;
fq *= 10;
fq += m_rxbuf[6] >> 4;
fq *= 10;
fq += m_rxbuf[6] & 0x0f;
fq *= 10;
fq += m_rxbuf[5] >> 4;
fq *= 10;
fq += m_rxbuf[5] & 0x0f;
fq *= 10;
fq += m_rxbuf[4] >> 4;
fq *= 10;
fq += m_rxbuf[4] & 0x0f;
UpdateFreq(double(fq)/1e6);
}
else if( (m_rxbuf[3] == 0x04) || (m_rxbuf[3] == 0x01) ){ // Mode
if( RADIO.PollOffset < 3 ) return;
int oldmode = m_RigMode;
switch(m_rxbuf[4]){
case 0x00: // LSB
m_LSB = 1;
m_RigMode = rmLSB;
break;
case 0x01: // USB
m_LSB = 2;
m_RigMode = rmUSB;
break;
case 0x02: // AM
m_LSB = 0;
m_RigMode = rmAM;
break;
case 0x03: // CW
m_LSB = 0;
m_RigMode = rmCW;
break;
case 0x04: // RTTY
m_LSB = 1;
m_RigMode = rmRTTY;
break;
case 0x05: // FM
m_LSB = 0;
m_RigMode = rmFM;
break;
default: // Other
m_LSB = 0;
m_RigMode = rmUNKNOWN;
break;
}
if( oldmode != m_RigMode ){
CalcRigFreq(m_RigHz*1.0e-6);
}
}
}
void __fastcall CCradio::FreqKenwood(void)
{
//0 1 2 3
//01234567890123456789012345678901234567890
//IF00021155000 +001000 0002000008 ;
//abcdefghijklmnopqrstuvwxyz1234567890 <---- 桁位置
//c - m 周波数 21.155000MHz
//x 0 = RIT off 1 = RIT on
//z 0 = XIT off 1 = XIT on
//12 M.CH
//4 モード 1=LSB 2=USB 3=CW 4=FM 5=AM 6=RTTY
//567 000=RX:A TX:A 001=RX:A TX=B 100=RX:B TX:B 101=RX:B TX=A
ULONG fq = 0;
m_rxbuf[13] = 0;
if( sscanf((LPCSTR)&m_rxbuf[2], "%lu", &fq) == 1 ){
if( fq ) UpdateFreq(double(fq)/1e6);
}
if( RADIO.PollOffset < 3 ) return;
switch(m_rxbuf[29]){
case '1': // LSB
m_LSB = 1;
m_RigMode = rmLSB;
break;
case '2': // USB
m_LSB = 2;
m_RigMode = rmUSB;
break;
case '3': // CW
m_LSB = 0;
m_RigMode = rmCW;
break;
case '4': // FM
m_LSB = 0;
m_RigMode = rmFM;
break;
case '5': // AM
m_LSB = 0;
m_RigMode = rmAM;
break;
case '6': // RTTY
m_LSB = 1;
m_RigMode = rmRTTY;
break;
default: // Other
m_LSB = 0;
m_RigMode = rmUNKNOWN;
break;
}
}
void __fastcall CCradio::FreqJST245(void)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12
// ”Iabdffffffffg”
// I:ヘッダー記号
// a:使用アンテナ1桁(1〜3)
// b:バンド幅1桁(0〜2)
// d:モード1桁(0〜5)
// f:送受信周波数8桁(00100000〜53999998)
// g:AGC1桁(0〜2)
ULONG fq = 0;
m_rxbuf[12] = 0;
LPCSTR p = (LPCSTR)&m_rxbuf[4];
for( ; *p; p++ ) if( !isdigit(*p) ) return;
if( sscanf((LPCSTR)&m_rxbuf[4], "%lu", &fq) == 1 ){
if( fq ) UpdateFreq(double(fq)/1e6);
}
if( RADIO.PollOffset < 3 ) return;
//char JST_Mode[] = {"F1","A1","USB","LSB","A3", "F3"};
switch(m_rxbuf[3]){
case '0': // RTTY
m_LSB = 1;
m_RigMode = rmRTTY;
break;
case '1': // CW
m_LSB = 0;
m_RigMode = rmCW;
break;
case '2': // USB
m_LSB = 2;
m_RigMode = rmUSB;
break;
case '3': // LSB
m_LSB = 1;
m_RigMode = rmLSB;
break;
case '4': // AM
m_LSB = 0;
m_RigMode = rmAM;
break;
case '5': // FM
m_LSB = 0;
m_RigMode = rmFM;
break;
default:
m_LSB = 0;
m_RigMode = rmUNKNOWN;
break;
}
}