mmvari/cradio.cpp
2013-07-05 15:09:45 -05:00

1452 lines
36 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//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
// <http://www.gnu.org/licenses/>.
//-----------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include <vcl.h>
#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;
}
}