mmtty/cradio.cpp

1094 lines
26 KiB
C++
Raw Permalink Normal View History

//Copyright+LGPL
//-----------------------------------------------------------------------------------------------------------------------------------------------
// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba, Dave Bernstein
//-----------------------------------------------------------------------------------------------------------------------------------------------
// This file is part of MMTTY.
// MMTTY 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.
// MMTTY 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
CRADIOPARA RADIO;
void InitRADIOPara(void)
{
RADIO.change = 1;
strcpy(RADIO.StrPort, "NONE"); // <20>|<7C>[<5B>g<EFBFBD>̖<EFBFBD><CC96>O
RADIO.BaudRate = 4800; // <20>{<7B>[<5B><><EFBFBD>[<5B>g
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 = 5;
RADIO.PollOffset = 0;
RADIO.PollScan = 0;
}
void 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 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);
}
//---------------------------------------------------------------------------
// <20><><EFBFBD><EFBFBD>: VCL <20>I<EFBFBD>u<EFBFBD>W<EFBFBD>F<EFBFBD>N<EFBFBD>g<EFBFBD>̃<EFBFBD><CC83>\<5C>b<EFBFBD>h<EFBFBD>ƃv<C683><76><EFBFBD>p<EFBFBD>e<EFBFBD>B<EFBFBD><42><EFBFBD>g<EFBFBD>p<EFBFBD><70><EFBFBD><EFBFBD><EFBFBD>ɂ<EFBFBD>, Synchronize
// <20><><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\<5C>b<EFBFBD>h<EFBFBD>Ăяo<D18F><6F><EFBFBD>łȂ<C582><C882><EFBFBD><EFBFBD>΂Ȃ<CE82><C882>܂<EFBFBD><DC82><EFBFBD><EFBFBD>B<EFBFBD><42><EFBFBD>ɗ<EFBFBD><C997><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82>B
//
// Synchronize(UpdateCaption);
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, UpdateCaption <20>͎<EFBFBD><CD8E>̂悤<CC82>ɋL<C98B>q<EFBFBD>ł<EFBFBD><C582>܂<EFBFBD><DC82>B
//
// void __fastcall CCradio::UpdateCaption()
// {
// Form1->Caption = "<22>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD><68><EFBFBD><EFBFBD><E78F91><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>";
// }
//---------------------------------------------------------------------------
__fastcall CCradio::CCradio(bool CreateSuspended)
: TThread(CreateSuspended)
{
m_CreateON = FALSE; // <20>N<EFBFBD><4E><EFBFBD>G<EFBFBD>C<EFBFBD>g<EFBFBD>t<EFBFBD><74><EFBFBD>O
m_fHnd = NULL; // <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>n<EFBFBD><6E><EFBFBD>h<EFBFBD><68>
m_wHnd = NULL; // <20>e<EFBFBD>̃E<CC83>C<EFBFBD><43><EFBFBD>h<EFBFBD>E<EFBFBD>n<EFBFBD><6E><EFBFBD>h<EFBFBD><68>
m_uMsg = WM_USER;
m_ID = 0; // <20><><EFBFBD>b<EFBFBD>Z<EFBFBD>[<5B>W<EFBFBD>̂h<CC82>c<EFBFBD>ԍ<EFBFBD>
m_Command = 0; // <20>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>ւ̃R<CC83>}<7D><><EFBFBD>h
m_TxAbort = 0; // <20><><EFBFBD>M<EFBFBD><4D><EFBFBD>~<7E>t<EFBFBD><74><EFBFBD>O
m_txwp = m_txrp = m_txcnt = 0;
m_PSKGNRId = 0;
m_OpenGNR = 0;
m_PollCnt = 0;
m_rxcnt = 0;
m_FreqEvent = 0;
m_Freq[0] = 0;
m_MarkFreq = 2125;
m_ScanAddr = 0;
m_pRadio = NULL;
}
//---------------------------------------------------------------------------
void __fastcall CCradio::Execute()
{
//---- <20>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>̃R<CC83>[<5B>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɋL<C98B>q ----
// 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);
}
}
}
//---------------------------------------------------------------------------
/*#$%
==============================================================
<EFBFBD>ʐM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>[<EFBFBD>v<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>X<EFBFBD><EFBFBD><EFBFBD>b<EFBFBD>h<EFBFBD><EFBFBD><EFBFBD>A<EFBFBD>N<EFBFBD>e<EFBFBD>B<EFBFBD>u<EFBFBD>ɂ<EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
PortName : <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̖<EFBFBD><EFBFBD>O
pCP : COMMPARA<EFBFBD>̃|<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>^<EFBFBD>i<EFBFBD>k<EFBFBD><EFBFBD><EFBFBD>̎<EFBFBD><EFBFBD>̓f<EFBFBD>t<EFBFBD>H<EFBFBD><EFBFBD><EFBFBD>g<EFBFBD>ŏ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>j
pWnd : <EFBFBD><EFBFBD><EFBFBD>b<EFBFBD>Z<EFBFBD>[<EFBFBD>W<EFBFBD><EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD>̃E<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>h<EFBFBD>E<EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>X<EFBFBD>̃|<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>^<EFBFBD>i<EFBFBD>k<EFBFBD><EFBFBD><EFBFBD>̎<EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>ڰѳ<EFBFBD><EFBFBD><EFBFBD>޳<EFBFBD>j
nID : <EFBFBD>f<EFBFBD>[<EFBFBD>^<EFBFBD><EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD>̃<EFBFBD><EFBFBD>b<EFBFBD>Z<EFBFBD>[<EFBFBD>W<EFBFBD>h<EFBFBD>c
RBufSize : <EFBFBD><EFBFBD><EFBFBD>M<EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD>̃T<EFBFBD>C<EFBFBD>Y(default=2048)
TBufSize : <EFBFBD><EFBFBD><EFBFBD>M<EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD>̃T<EFBFBD>C<EFBFBD>Y(default=2048)
--------------------------------------------------------------
TRUE/FALSE
--------------------------------------------------------------
==============================================================
*/
BOOL CCradio::Open(CRADIOPARA *cp, HWND hwnd, UINT uMsg, UINT nID)
{
if( m_CreateON == TRUE ) Close();
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;
}
//AA6YQ 1.66 enable use of 2-digit com ports per http://support.microsoft.com/kb/115831/EN-US/
char *ComPort = new char[33];
StrCopy(ComPort,"\\\\.\\");
StrCat(ComPort,cp->StrPort);
m_fHnd = ::CreateFile(ComPort, 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(); // <20>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>̎<EFBFBD><CC8E>s
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; // <20><><EFBFBD>M<EFBFBD>֎~
m_dcb.fDtrControl = DTR_CONTROL_DISABLE; // <20><><EFBFBD>M<EFBFBD>֎~
}
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(); // <20>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>̎<EFBFBD><CC8E>s
return TRUE;
}
/*#$%
==============================================================
<EFBFBD>ʐM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>[<EFBFBD>Y<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
<EFBFBD>X<EFBFBD><EFBFBD><EFBFBD>b<EFBFBD>h<EFBFBD><EFBFBD><EFBFBD>I<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂ő҂<EFBFBD>
==============================================================
*/
void 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; // <20>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>I<EFBFBD><49><EFBFBD>R<EFBFBD>}<7D><><EFBFBD>h
Priority = tpNormal; //<2F>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>͒ʏ<CD92><CA8F>̗D<CC97><44><EFBFBD>x<EFBFBD>ł<EFBFBD><C582><EFBFBD>
WaitFor();
}
if( m_pRadio != NULL ){
delete m_pRadio;
m_pRadio = NULL;
}
else {
::CloseHandle(m_fHnd);
}
}
}
m_CreateON = FALSE;
m_TxAbort = TRUE;
}
void CCradio::ReqClose(void)
{
if( m_CreateON == TRUE ){
if( m_PSKGNRId ){
return;
}
else {
if( m_ID ){
m_Command = CRADIO_CLOSE; // <20>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>I<EFBFBD><49><EFBFBD>R<EFBFBD>}<7D><><EFBFBD>h
Priority = tpNormal; //<2F>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD>͒ʏ<CD92><CA8F>̗D<CC97><44><EFBFBD>x<EFBFBD>ł<EFBFBD><C582><EFBFBD>
}
}
}
}
void 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;
}
/*#$%
==============================================================
<EFBFBD><EFBFBD><EFBFBD>M<EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD><EFBFBD><EFBFBD>̊i<EFBFBD>[<EFBFBD>f<EFBFBD>[<EFBFBD>^<EFBFBD><EFBFBD><EFBFBD>𓾂<EFBFBD>
--------------------------------------------------------------
--------------------------------------------------------------
<EFBFBD>f<EFBFBD>[<EFBFBD>^<EFBFBD>̒<EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
==============================================================
*/
DWORD CCradio::RecvLen(void)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
::ClearCommError( m_fHnd, &dwErrorFlags, &ComStat );
return ComStat.cbInQue;
}
/*#$%
==============================================================
<EFBFBD><EFBFBD><EFBFBD>M<EFBFBD>r<EFBFBD>W<EFBFBD>[<EFBFBD><EFBFBD><EFBFBD>ǂ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ׂ<EFBFBD>
--------------------------------------------------------------
--------------------------------------------------------------
: <EFBFBD><EFBFBD><EFBFBD>M<EFBFBD>r<EFBFBD>W<EFBFBD>[<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
==============================================================
*/
int 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
}
/*#$%
==============================================================
<EFBFBD>ʐM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>[<EFBFBD>^<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD><EFBFBD>
--------------------------------------------------------------
p : <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD>̃|<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>^
len : <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD>̃T<EFBFBD>C<EFBFBD>Y
--------------------------------------------------------------
<EFBFBD><EFBFBD><EFBFBD>ۂɎ<EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y
--------------------------------------------------------------
==============================================================
*/
DWORD CCradio::Read(BYTE *p, DWORD len)
{
DWORD size=0;
if( m_CreateON == TRUE ){
::ReadFile( m_fHnd, p, len, &size, NULL );
}
return size;
}
/*#$%
==============================================================
<EFBFBD>ʐM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƀf<EFBFBD>[<EFBFBD>^<EFBFBD>𑗐M<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
==============================================================
*/
void 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++;
}
}
}
/*#$%
==============================================================
<EFBFBD>ʐM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƀf<EFBFBD>[<EFBFBD>^<EFBFBD>𑗐M<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
p : <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD>̃|<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>^
len : <EFBFBD><EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y
--------------------------------------------------------------
<EFBFBD><EFBFBD><EFBFBD>ۂɑ<EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y
--------------------------------------------------------------
==============================================================
*/
void 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);
}
}
}
/*#$%
==============================================================
<EFBFBD>ʐM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƀf<EFBFBD>[<EFBFBD>^<EFBFBD>𑗐M<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
--------------------------------------------------------------
p : <EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<EFBFBD>̃|<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>^
len : <EFBFBD><EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y
--------------------------------------------------------------
<EFBFBD><EFBFBD><EFBFBD>ۂɑ<EFBFBD><EFBFBD>M<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y
--------------------------------------------------------------
==============================================================
*/
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);
}
void 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 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());
}
}
}
//--------------------------------------------------------
// <20><><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>ω<EFBFBD><CF89><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD>ǂ<EFBFBD><C782><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ׂ<EFBFBD>
int 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;
}
//--------------------------------------------------------
// <20>^<5E>C<EFBFBD>}<7D>[<5B><><EFBFBD><EFBFBD>
void 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 = (5 + RADIO.PollInterval);
}
}
if( (!tx) && RADIO.PollType ){
if( !m_PollCnt ){
if( m_pRadio != NULL ) m_pRadio->Polling();
if( m_ScanAddr ){ // <20>A<EFBFBD>h<EFBFBD><68><EFBFBD>X<EFBFBD>X<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD>
m_PollCnt = 4;
if( m_ScanAddr <= 3 ){
m_ScanAddr++;
}
else {
RADIO.Cmdxx++;
if( RADIO.Cmdxx >= 0x80 ){
RADIO.Cmdxx = 0;
}
}
}
else {
m_PollCnt = (5 + RADIO.PollInterval);
}
if( interval ){
m_PollCnt = m_PollCnt * 100 / interval;
}
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. 1.70E AA6YQ
case RADIO_POLLFT9000:
case RADIO_POLLFT2000:
case RADIO_POLLFT950:
case RADIO_POLLFT450:
case RADIO_POLLFT991:
case RADIO_POLLFT891:
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--;
}
}
}
//--------------------------------------------------------
// <20><><EFBFBD>g<EFBFBD><67><EFBFBD>|<7C>[<5B><><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD>f<EFBFBD>[<5B>^<5E>̎<EFBFBD><CC8E>M
void CCradio::CatchPoll(BYTE c)
{
switch(RADIO.PollType){
case RADIO_POLLYAESUHF:
case RADIO_POLLFT1000D:
case RADIO_POLLFT920:
if( m_rxcnt < 5 ){
m_rxbuf[m_rxcnt] = c;
m_rxcnt++;
if( m_rxcnt == 5 ){
FreqYaesuHF();
}
}
break;
//1.66B AA6YQ
case RADIO_POLLFT9000:
case RADIO_POLLFT2000:
case RADIO_POLLFT950:
case RADIO_POLLFT450:
case RADIO_POLLFT891: //1.70H
case RADIO_POLLFT991: //1.70H
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_POLLYAESUVU:
if( m_rxcnt < 5 ){
m_rxbuf[m_rxcnt] = c;
m_rxcnt++;
if( m_rxcnt == 5 ){
FreqYaesuVU();
}
}
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; // <20>v<EFBFBD><76><EFBFBD>A<EFBFBD><41><EFBFBD>u<EFBFBD><75>
m_rxcnt++;
}
break;
case 1:
if( c != 0xfe ){
m_rxbuf[m_rxcnt] = c; // PC-Addr
m_rxcnt++;
}
break;
case 2:
if( (c == 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))) ){
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 >= 9 ){
FreqICOM();
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 != 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 ) 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 == 0x0f) ){
if( m_rxcnt >= 12 ) FreqJST245();
m_rxcnt = 0;
}
}
}
else {
m_rxcnt = 0;
}
break;
default:
break;
}
}
//----------------------------------------------------------
// <20><><EFBFBD>g<EFBFBD><67><EFBFBD>̍X<CC8D>V (freq=MHz)
//
void CCradio::UpdateFreq(double freq)
{
if( freq < 0.001 ) return;
switch(RADIO.PollOffset){
case 1:
freq -= m_MarkFreq/1000000.0;
break;
case 2:
freq += m_MarkFreq/1000000.0;
break;
default:
break;
}
char bf[32];
sprintf(bf, "%.3lf", freq);
if( strcmp(m_Freq, bf) ){
strcpy(m_Freq, bf);
m_FreqEvent = 1;
}
}
void 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);
}
void 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;
UpdateFreq( double(fq) / 1000.0 );
}
void CCradio::FreqICOM(void)
{
// 0 1 2 3 4 5 6 7 8 9
// fe e0 40 03 90 09 02 07 00 fd
// fe e0 40 03 90 09 02 07 fd
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);
}
void CCradio::FreqKenwood(void)
{
//0123456789012
//IF00021155000 +001000 0002000008 ;
//abcdefghijklmnopqrstuvwxyz1234567890 <----<2D>@<40><><EFBFBD>ʒu
//c - m <20><><EFBFBD>g<EFBFBD><67><EFBFBD>@21.155MHz
ULONG fq = 0;
m_rxbuf[13] = 0;
if( sscanf((LPCSTR)&m_rxbuf[2], "%lu", &fq) == 1 ){
if( fq ) UpdateFreq(double(fq)/1e6);
}
}
//AA6YQ 1.66B
//G3WYW Fix for FT-991 1.70B
void CCradio::FreqYaesu9K2K(void)
{
//000000000011111111112222222222
//012345678901234567890123456789
//IF000021155000+0000RTMVCTTS; <= FT991
//IF00021155000+0000RTMVCTTS; <= FT9K2K
//abcdefghijklmnopqrstuvwxyz1234567890 <----<2D>@Digit position
//f - m <20><><EFBFBD>g<EFBFBD><67> freq<65>@21.155MHz
ULONG fq = 0;
//G3WYW Feb 2016 am I a FT-991 or FT9K2K?
if (m_rxbuf[26] == ';')
{ //FT9K2K
m_rxbuf[13] = 0;
if( sscanf((LPCSTR)&m_rxbuf[5], "%lu", &fq) == 1 ){
if( fq ) UpdateFreq(double(fq)/1e6);
}
}
else //FT991
{
m_rxbuf[14] = 0;
if( sscanf((LPCSTR)&m_rxbuf[5], "%lu", &fq) == 1 ){
if( fq ) UpdateFreq(double(fq)/1e6);
}
}
}
void CCradio::FreqJST245(void)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12
//<2F>@<40>h<EFBFBD>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>h
//<2F>@<40>@<40>h<EFBFBD>F<EFBFBD>w<EFBFBD>b<EFBFBD>_<EFBFBD>[<5B>L<EFBFBD><4C>
//<2F>@<40>@<40><><EFBFBD>F<EFBFBD>g<EFBFBD>p<EFBFBD>A<EFBFBD><41><EFBFBD>e<EFBFBD>i<EFBFBD>P<EFBFBD><50><EFBFBD>i<EFBFBD>P<EFBFBD>`<60>R<EFBFBD>j
//<2F>@<40>@<40><><EFBFBD>F<EFBFBD>o<EFBFBD><6F><EFBFBD>h<EFBFBD><68><EFBFBD>P<EFBFBD><50><EFBFBD>i<EFBFBD>O<EFBFBD>`<60>Q<EFBFBD>j
//<2F>@<40>@<40><><EFBFBD>F<EFBFBD><46><EFBFBD>[<5B>h<EFBFBD>P<EFBFBD><50><EFBFBD>i<EFBFBD>O<EFBFBD>`<60>T<EFBFBD>j
//<2F>@<40>@<40><><EFBFBD>F<EFBFBD><46><EFBFBD><EFBFBD><EFBFBD>M<EFBFBD><4D><EFBFBD>g<EFBFBD><67><EFBFBD>W<EFBFBD><57><EFBFBD>i<EFBFBD>O<EFBFBD>O<EFBFBD>P<EFBFBD>O<EFBFBD>O<EFBFBD>O<EFBFBD>O<EFBFBD>O<EFBFBD>`<60>T<EFBFBD>R<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD>X<EFBFBD>W<EFBFBD>j
//<2F>@<40>@<40><><EFBFBD>F<EFBFBD>`<60>f<EFBFBD>b<EFBFBD>P<EFBFBD><50><EFBFBD>i<EFBFBD>O<EFBFBD>`<60>Q<EFBFBD>j
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);
}
}