mmtty/ClockAdj.cpp
2013-07-05 15:00:12 -05:00

450 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

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 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 "ClockAdj.h"
#include "Main.h"
//---------------------------------------------------------------------
#pragma resource "*.dfm"
//TClockAdjDlg *ClockAdjDlg;
static int s_Gain = 0x0108;
//---------------------------------------------------------------------
__fastcall TClockAdjDlg::TClockAdjDlg(TComponent* AOwner)
: TForm(AOwner)
{
FormStyle = ((TForm *)AOwner)->FormStyle;
pBitmap = new Graphics::TBitmap();
pBitmap->Width = PaintBox->Width;
pBitmap->Height = PaintBox->Height;
// pBitmap->Palette = MmttyWd->UsrPal;
switch(SampType){
case 0:
UpDown->Max = 11599;
UpDown->Min = 10000;
break;
case 1:
UpDown->Max = 9999;
UpDown->Min = 7000;
break;
case 2:
UpDown->Max = 6999;
UpDown->Min = 5000;
break;
case 3:
UpDown->Max = 12500;
UpDown->Min = 11600;
break;
}
TRect rc;
int XL = 0;
int XR = pBitmap->Width - 1;
int YT = 0;
int YB = pBitmap->Height - 1;
rc.Left = XL;
rc.Right = XR;
rc.Top = YT;
rc.Bottom = YB+1;
TCanvas *cp = pBitmap->Canvas;
cp->Brush->Color = clBlack;
cp->FillRect(rc);
m_CursorX = XR - 20;
pDem = NULL;
pTick = NULL;
Font->Name = ((TForm *)AOwner)->Font->Name;
Font->Charset = ((TForm *)AOwner)->Font->Charset;
cp->Font->Name = ((TForm *)AOwner)->Font->Name;
cp->Font->Charset = ((TForm *)AOwner)->Font->Charset;
cp->Font->Color = clWhite;
cp->Font->Size = 10;
int FH = cp->TextHeight("A");
int Y = 5;
if( Font->Charset != SHIFTJIS_CHARSET ){
Caption = "Calibrating the Sound Card with a Time Standard Broadcast Station";
// "Adjust Sampling Frequency using an off-air time signal";
// Caption = "Adjust Sampling freq. (Recive WWV tick sound on Mark freq.)";
CancelBtn->Caption = "Cancel";
cp->TextOut(10, Y, "1.Tune your radio to WWV or another 1-second tick standard. Set the radio display"); Y+=FH;
cp->TextOut(10, Y, " to the carrier frequency."); Y+=FH;
cp->TextOut(10, Y, "2.Wait for about three minutes. If you are using 11025 Hz. calibration, you should"); Y+=FH;
cp->TextOut(10, Y, " see two lines of marks (vertical or slanted), corresponding to the 1-second tick"); Y+=FH;
cp->TextOut(10, Y, " sound bursts transmitted by the time-standard broadcast station. You will see only"); Y+=FH;
cp->TextOut(10, Y, " one line with 8000 Hz. or 6000 Hz."); Y+=FH;
cp->TextOut(10, Y, "3.Right-click to move the vertical green line to the tick line. This allows you to"); Y+=FH;
cp->TextOut(10, Y, " compare the tick line to vertical."); Y+=FH;
cp->TextOut(10, Y, "4.Left-click a low tick burst mark (bottom one if possible), and move the cursor to"); Y+=FH;
cp->TextOut(10, Y, " the top of the line. You will see a yellow line on the display."); Y+=FH;
cp->TextOut(10, Y, "5.Overlay the yellow line with the tick mark line, and left-click a high burst mark"); Y+=FH;
cp->TextOut(10, Y, " (top one if possible)."); Y+=FH;
cp->TextOut(10, Y, "6.This will automatically put the correct clock frequency in the adjust window."); Y+=FH;
cp->TextOut(10, Y, "7.Click OK to leave the setup display and to memorize the new value."); Y+=FH;
cp->TextOut(10, Y, "8.Restart MMTTY for the new clock value to take effect.");
#if 0
cp->TextOut(10, 10, "1.Receive WWV in AM or SSB mode. Tune the radio to the carrier frequency.");
cp->TextOut(10, 30, "2.Let this adjustment display run for a few minutes, and look for one or two");
cp->TextOut(10, 50, " almost-vertical lines of dots. If you do not see this, wait for up to ten minutes.");
cp->TextOut(10, 70, "3.If your sound card clock is far out of adjustment, the lines will be very slanted.");
cp->TextOut(10, 90, "4.Click the 1st point on the slanted line.");
cp->TextOut(10,110, "5.And then click the 2nd point on the same line. The value of clock will be revised");
cp->TextOut(10,130, " automatically. If there is distance of 1st point and 2nd point, precision is better.");
cp->TextOut(10,160, "If the first degree of slant is very big, please repeat once again, because an error");
cp->TextOut(10,180, "remains a little.");
cp->TextOut(10,200, "WWV - 2.5, 5, 10MHz // GBR - 60KHz // RWM - 4.996, 9.996, 14.996MHz");
cp->TextOut(10,240, "Left click - Start adjustment");
cp->TextOut(10,260, "Right click - Move vertical cursor");
#endif
}
else {
cp->TextOut(10, Y, "1.JJY<4A><59>AM<41>܂<EFBFBD><DC82><EFBFBD>SSB<53>Ŏ<EFBFBD><C58E>M<EFBFBD><4D><EFBFBD>A<EFBFBD><41><EFBFBD>̉<EFBFBD><CC89>ʂ̉<CA82><CC89>ɂ<EFBFBD><C982><EFBFBD>Mark<72><6B>1000Hz<48>܂<EFBFBD><DC82><EFBFBD>"); Y+=FH;
cp->TextOut(10, Y, " 1600Hz<48><7A><EFBFBD>ݒ肵<DD92>܂<EFBFBD>."); Y+=FH;
cp->TextOut(10, Y, "2.SSB<53>̏ꍇ<CC8F>͂P<CD82>b<EFBFBD>`<60>b<EFBFBD>N<EFBFBD><4E><EFBFBD><EFBFBD>Mark<72>ɏd<C98F>Ȃ<EFBFBD><C882><EFBFBD>Ɏ<EFBFBD><C98E>M<EFBFBD><4D><EFBFBD>g<EFBFBD><67><EFBFBD>𒲐<EFBFBD><F092B290><EFBFBD><EFBFBD>܂<EFBFBD>."); Y+=FH;
cp->TextOut(10, Y, "3.<2E><><EFBFBD>΂炭<CE82><E782AD><EFBFBD>M<EFBFBD><4D><EFBFBD>ďc<C48F>܂<EFBFBD><DC82>͎΂߃<CE82><DF83>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>\<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂<EFBFBD><EFBFBD>҂<EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD>i<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>j."); Y+=FH;
cp->TextOut(10, Y, "4.<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̏ꍇ<CC8F>̓N<CD83><4E><EFBFBD>b<EFBFBD>N<EFBFBD>l<EFBFBD>͐<EFBFBD><CD90>m<EFBFBD>ł<EFBFBD><C582>B<EFBFBD>΂߂ɂȂ<C982><C882>Ă<EFBFBD><C482><EFBFBD><EFBFBD><EFBFBD>́A"); Y+=FH;
cp->TextOut(10, Y, " <20><><EFBFBD>̎΂ߐ<CE82><DF90>̍ŏ<CC8D><C58F>̒[<5B>_<EFBFBD><5F><EFBFBD>N<EFBFBD><4E><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>܂<EFBFBD>."); Y+=FH;
cp->TextOut(10, Y, "5.<2E>X<EFBFBD>ɓ<EFBFBD><C993><EFBFBD><EFBFBD>΂ߐ<CE82><DF90>̔<EFBFBD><CC94>Α<EFBFBD><CE91>̒[<5B>_<EFBFBD><5F><EFBFBD>N<EFBFBD><4E><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD><EFBFBD><EFBFBD>ƃN<C683><4E><EFBFBD>b<EFBFBD>N<EFBFBD>l<EFBFBD><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD><49>"); Y+=FH;
cp->TextOut(10, Y, " <20>ݒ肳<DD92><E882B3><EFBFBD>܂<EFBFBD>.<2E>i2<69>_<EFBFBD>Ԃ̋<D482><CC8B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ق<EFBFBD><D982><EFBFBD><EFBFBD><EFBFBD><EFBFBD>m<EFBFBD>ł<EFBFBD><C582>j"); Y+=FH;
cp->TextOut(10, Y, "<EFBFBD>X<EFBFBD>΂<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɑ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD><EFBFBD>L<EFBFBD>̎葱<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>x<EFBFBD>J<EFBFBD><EFBFBD><EFBFBD>Ԃ<EFBFBD><EFBFBD>ĉ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."); Y+=FH+FH;
cp->TextOut(10, Y, "JJY<EFBFBD>̑<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɁAJMH,JMG<4D>Ȃǂ<C882>FAX<41><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0.5<EFBFBD>b<EFBFBD><EFBFBD><EFBFBD>̃f<EFBFBD>b<EFBFBD>h<EFBFBD>Z<EFBFBD>N<EFBFBD>^<5E>𗘗p<F0979897><70><EFBFBD>Ă<EFBFBD>"); Y+=FH;
cp->TextOut(10, Y, "OK<EFBFBD>̂悤<EFBFBD>ł<EFBFBD>."); Y+=FH;
cp->TextOut(10, Y, "<EFBFBD><EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>b<EFBFBD>N - <20><><EFBFBD><EFBFBD><EFBFBD>̊J<CC8A>n"); Y+=FH;
cp->TextOut(10, Y, "<EFBFBD>E<EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>b<EFBFBD>N - <20><><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD>[<5B>\<EFBFBD><EFBFBD><EFBFBD>ړ<EFBFBD>");
}
m_agcMax = 8192;
m_agcMin = 0;
m_agcSumMax = 8192 * AGCAVG;
m_Point = 0;
// SBHelp->Visible = !JanHelp.IsEmpty();
SBHelp->Visible = FALSE;
}
//---------------------------------------------------------------------
__fastcall TClockAdjDlg::~TClockAdjDlg()
{
pDem = NULL;
pTick = NULL;
pBitmap->Palette = NULL;
delete pBitmap;
pBitmap = NULL;
}
//---------------------------------------------------------------------------
// <20><><EFBFBD>݂̘_<CC98><5F><EFBFBD>p<EFBFBD><70><EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD>Ԃ<EFBFBD><D482>iTControl::GetPalette<74>̃I<CC83>[<5B>o<EFBFBD><6F><EFBFBD>C<EFBFBD>h<EFBFBD>֐<EFBFBD><D690>j
HPALETTE __fastcall TClockAdjDlg::GetPalette(void)
{
pBitmap->Palette = MmttyWd->UsrPal;
return MmttyWd->UsrPal;
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::UpdateTB(void)
{
TBGAIN->Enabled = !SBAGC->Down;
LG->Font->Color = SBAGC->Down ? clGrayText : clBlack;
}
//---------------------------------------------------------------------
void __fastcall TClockAdjDlg::UpdatePPM(void)
{
int d = ((UpDown->Position - SampBase) * 1000000.0 / SampBase) + 0.5;
char bf[64];
sprintf(bf, "%d ppm", d);
LPPM->Caption = bf;
}
//---------------------------------------------------------------------
int __fastcall TClockAdjDlg::Execute(TSound *p, double &Samp)
{
pSound = p;
pDem = &p->FSKDEM;
pTick = &pDem->Tick;
pTick->m_Samp = int(Samp);
InitColorTable(clBlack, clWhite);
MmttyWd->ReqPaletteChange();
if( (Samp > UpDown->Max) || (Samp < UpDown->Max) ){
Samp = SampFreq;
}
EditClock->Text = int(Samp);
UpDown->Position = SHORT(Samp);
pDem->Tick.Init();
pDem->m_Tick = 1;
m_DisEvent++;
double SaveMarkFreq = pDem->GetMarkFreq();
double SaveSpaceFreq = pDem->GetSpaceFreq();
int SaveAFC = sys.m_AFC;
int SaveBPF = pSound->m_bpf;
int SaveType = pSound->FSKDEM.m_type;
pSound->m_bpf = 0;
sys.m_AFC = 0;
if( SaveType == 2 ) pSound->FSKDEM.m_type = 0;
UDMark->Position = 1000;
pDem->SetMarkFreq(1000.0);
pDem->SetSpaceFreq(1200.0);
TBGAIN->Position = s_Gain & 0x00ff;
SBAGC->Down = s_Gain & 0xff00 ? 1 : 0;
UpdateTB();
m_DisEvent--;
UpdatePPM();
int r = ShowModal();
InitColorTable(sys.m_ColorLow, sys.m_ColorHigh);
s_Gain = (s_Gain & 0x00ff) | (SBAGC->Down ? 0x0100 : 0);
pDem->m_Tick = 0;
pDem->SetMarkFreq(SaveMarkFreq);
pDem->SetSpaceFreq(SaveSpaceFreq);
sys.m_AFC = SaveAFC;
pSound->m_bpf = SaveBPF;
pSound->FSKDEM.m_type = SaveType;
MmttyWd->ReqPaletteChange();
if( r == IDOK ){
Samp = UpDown->Position;
return TRUE;
}
else {
return FALSE;
}
}
//---------------------------------------------------------------------
void __fastcall TClockAdjDlg::TimerTimer(TObject *Sender)
{
if( pBitmap == NULL ) return;
if( pDem == NULL ) return;
if( pTick == NULL ) return;
int *p = pTick->GetData();
if( p == NULL ) return;
TCanvas *tp = pBitmap->Canvas;
TRect rc;
int XL = 0;
int XR = pBitmap->Width - 1;
int YT = 0;
int YB = pBitmap->Height - 1;
rc.Left = XL;
rc.Right = XR;
rc.Top = YT;
rc.Bottom = YB+1;
TRect src(rc);
src.Bottom--;
rc.Top++;
tp->CopyRect(rc, tp, src);
int mx = -MAXINT;
int mi = MAXINT;
int x, xx, d;
double k1 = 16384.0/double(m_agcMax - m_agcMin);
double k2;
if( SBAGC->Down ){
k2 = 128.0 / 16384.0;
}
else {
k2 = (128.0 * (s_Gain & 0x00ff)) / (4096 * 16);
}
for( x = 0; x < XR; x++){
xx = (x * pTick->m_Samp)/pBitmap->Width;
d = p[xx];
if( mx < d ) mx = d;
if( mi > d ) mi = d;
if( SBAGC->Down ){
d -= m_agcMin;
if( m_agcMax > 0 ) d = double(d) * k1;
}
d = double(d) * k2;
if( d >= 128 ) d = 127;
if( d <= 0 ) d = 0;
tp->Pixels[x][0] = TColor(ColorTable[127-d] | sys.d_PaletteMask);
}
m_agcSumMax -= m_agcMax;
m_agcSumMax += mx;
if( m_agcSumMax < (4096*AGCAVG) ) m_agcSumMax = (4096*AGCAVG);
m_agcMax = m_agcSumMax / AGCAVG;
m_agcMin = mi;
if( m_agcMin > 2048 ) m_agcMin = 2048;
m_PointY++;
PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap);
PaintCursor();
#if 0
PaintBox->Canvas->Font->Color = clWhite;
char bf[128];
sprintf(bf, "curMax:%d", mx);
PaintBox->Canvas->TextOut( 500, 200, bf );
sprintf(bf, "agcMax:%d", m_agcMax);
PaintBox->Canvas->TextOut( 500, 220, bf );
sprintf(bf, "agcMin:%d", m_agcMin);
PaintBox->Canvas->TextOut( 500, 240, bf );
sprintf(bf, "SumMax:%d", m_agcSumMax);
PaintBox->Canvas->TextOut( 500, 260, bf );
#endif
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::DrawMessage(LPCSTR p)
{
int xr = PaintBox->Canvas->TextWidth(p);
int xl = (PaintBox->Width - xr)/2;
xr += xl;
int FH = PaintBox->Canvas->TextHeight(p);
int VC = PaintBox->Height - FH;
PaintBox->Canvas->Pen->Color = clWhite;
PaintBox->Canvas->Brush->Color = clBlack;
PaintBox->Canvas->RoundRect(xl-10, VC-FH, xr+10, VC+FH, 10, 10);
PaintBox->Canvas->Font->Color = clWhite;
PaintBox->Canvas->TextOut(xl, VC-FH/2, p);
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::PaintCursor(void)
{
PaintBox->Canvas->Pen->Color = clLime;
PaintBox->Canvas->Pen->Style = psDot;
PaintBox->Canvas->MoveTo(m_CursorX, 0);
int rop = ::SetROP2(PaintBox->Canvas->Handle, R2_MASKPENNOT);
PaintBox->Canvas->LineTo(m_CursorX, pBitmap->Height - 1);
::SetROP2((HDC)PaintBox->Canvas, rop);
if( m_Point ){
PaintBox->Canvas->Pen->Color = clYellow;
PaintBox->Canvas->Pen->Style = psSolid;
PaintBox->Canvas->MoveTo(m_PointX, m_PointY);
::SetROP2(PaintBox->Canvas->Handle, R2_MASKPENNOT);
PaintBox->Canvas->LineTo(m_PointX2, m_PointY2);
::SetROP2((HDC)PaintBox->Canvas, rop);
char bf[256];
if( Font->Charset != SHIFTJIS_CHARSET ){
sprintf( bf, "OK : Left button, Cancel : Right button Clock=%.1lf", GetPointSamp());
}
else {
sprintf( bf, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> : <20><><EFBFBD>{<7B>^<5E><>, <20><><EFBFBD>~ : <20>E<EFBFBD>{<7B>^<5E><> Clock=%.1lf", GetPointSamp());
}
DrawMessage(bf);
if( PaintBox->Cursor != crCross ) PaintBox->Cursor = crCross;
}
else {
if( PaintBox->Cursor != crDefault ) PaintBox->Cursor = crDefault;
}
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::UpDownClick(TObject *Sender, TUDBtnType Button)
{
if( pTick == NULL ) return;
pTick->m_Samp = UpDown->Position;
UpdatePPM();
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::PaintBoxPaint(TObject *Sender)
{
PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap);
PaintCursor();
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::PaintBoxMouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if( Button == mbLeft ){
if( m_Point ){
m_Point = 0;
if( m_PointY2 != m_PointY ){
int newc = int(GetPointSamp() + 0.5);
pTick->m_Samp = newc;
UpDown->Position = SHORT(newc);
ModalResult = mrOk;
}
}
else {
m_PointX2 = m_PointX = X;
m_PointY2 = m_PointY = Y;
m_Point = 1;
}
}
else if( m_Point ){
m_Point = 0;
}
else {
m_CursorX = X;
}
PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap);
PaintCursor();
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::MarkFreqChange(TObject *Sender)
{
if( m_DisEvent ) return;
int dd;
if( sscanf(AnsiString(MarkFreq->Text).c_str(), "%lu", &dd ) == 1){ //JA7UDE 0428
if( (dd >= 300) && (dd <= 2700) ){
m_DisEvent++;
UDMark->Position = SHORT(dd);
pDem->SetMarkFreq(dd);
pDem->SetSpaceFreq(dd + 200);
m_DisEvent--;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::TBGAINChange(TObject *Sender)
{
s_Gain = (s_Gain & 0xff00) | TBGAIN->Position;
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::UDMarkClick(TObject *Sender, TUDBtnType Button)
{
if( m_DisEvent ) return;
pDem->SetMarkFreq(UDMark->Position);
pDem->SetSpaceFreq(UDMark->Position + 200);
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::SBAGCClick(TObject *Sender)
{
UpdateTB();
}
//---------------------------------------------------------------------------
double __fastcall TClockAdjDlg::GetPointSamp(void)
{
if( m_PointY == m_PointY2 ) return pTick->m_Samp;
double d = (m_PointX2 - m_PointX);
d = d * pTick->m_Samp / pBitmap->Width;
d /= (m_PointY - m_PointY2);
d += pTick->m_Samp;
return d;
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::PaintBoxMouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
if( m_Point ){
m_PointX2 = X;
m_PointY2 = Y;
PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap);
PaintCursor();
}
}
//---------------------------------------------------------------------------
void __fastcall TClockAdjDlg::SBHelpClick(TObject *Sender)
{
#if 1
ShowHtmlHelp();
#else
ShowHelp(25);
#endif
}
//---------------------------------------------------------------------------