mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 01:55:48 -05:00
ATV Demod: include in build tree
This commit is contained in:
parent
763d486514
commit
2e93f68e39
@ -10,7 +10,7 @@ add_subdirectory(udpsrc)
|
||||
add_subdirectory(demodwfm)
|
||||
add_subdirectory(chanalyzer)
|
||||
add_subdirectory(chanalyzerng)
|
||||
#add_subdirectory(demodatv)
|
||||
add_subdirectory(demodatv)
|
||||
|
||||
if(LIBDSDCC_FOUND AND LIBMBE_FOUND)
|
||||
add_subdirectory(demoddsd)
|
||||
|
49
plugins/channelrx/demodatv/CMakeLists.txt
Normal file
49
plugins/channelrx/demodatv/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
project(atv)
|
||||
|
||||
set(atv_SOURCES
|
||||
atvdemod.cpp
|
||||
atvdemodgui.cpp
|
||||
atvdemodplugin.cpp
|
||||
atvscreen.cpp
|
||||
glshaderarray.cpp
|
||||
)
|
||||
|
||||
set(atv_HEADERS
|
||||
atvdemod.h
|
||||
atvdemodgui.h
|
||||
atvdemodplugin.h
|
||||
atvscreen.h
|
||||
glshaderarray.h
|
||||
)
|
||||
|
||||
set(atv_FORMS
|
||||
atvdemodgui.ui
|
||||
)
|
||||
|
||||
include_directories(
|
||||
.
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
#include(${QT_USE_FILE})
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
add_definitions(-DQT_PLUGIN)
|
||||
add_definitions(-DQT_SHARED)
|
||||
|
||||
#qt5_wrap_cpp(nfm_HEADERS_MOC ${nfm_HEADERS})
|
||||
qt5_wrap_ui(atv_FORMS_HEADERS ${atv_FORMS})
|
||||
|
||||
add_library(demodatv SHARED
|
||||
${atv_SOURCES}
|
||||
${atv_HEADERS_MOC}
|
||||
${atv_FORMS_HEADERS}
|
||||
)
|
||||
|
||||
target_link_libraries(demodatv
|
||||
${QT_LIBRARIES}
|
||||
sdrbase
|
||||
)
|
||||
|
||||
qt5_use_modules(demodatv Core Widgets)
|
||||
|
||||
install(TARGETS demodatv DESTINATION lib/plugins/channelrx)
|
586
plugins/channelrx/demodatv/atvdemod.cpp
Normal file
586
plugins/channelrx/demodatv/atvdemod.cpp
Normal file
@ -0,0 +1,586 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "atvdemod.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(ATVDemod::MsgConfigureATVDemod, Message)
|
||||
|
||||
ATVDemod::ATVDemod() :
|
||||
m_objSettingsMutex(QMutex::NonRecursive),
|
||||
m_objRegisteredATVScreen(NULL),
|
||||
m_intImageIndex(0),
|
||||
m_intColIndex(0),
|
||||
m_intRowIndex(0),
|
||||
m_intSynchroPoints(0),
|
||||
m_blnSynchroDetected(false),
|
||||
m_blnVerticalSynchroDetected(false),
|
||||
m_fltLevelSynchroTop(0.0),
|
||||
m_fltLevelSynchroBlack(1.0),
|
||||
m_enmModulation(ATV_FM1),
|
||||
m_intRowsLimit(0),
|
||||
m_blnImageDetecting(false),
|
||||
m_fltEffMin(2000000000.0f),
|
||||
m_fltEffMax(-2000000000.0f),
|
||||
m_fltAmpMin(-2000000000.0f),
|
||||
m_fltAmpMax(2000000000.0f),
|
||||
m_fltAmpDelta(1.0),
|
||||
m_fltAmpLineAverage(0.0f)
|
||||
{
|
||||
setObjectName("ATVDemod");
|
||||
|
||||
//*************** ATV PARAMETERS ***************
|
||||
m_intNumberSamplePerLine=0;
|
||||
m_intSynchroPoints=0;
|
||||
m_intNumberOfLines=0;
|
||||
m_blnInitialized=false;
|
||||
m_intNumberOfRowsToDisplay=0;
|
||||
|
||||
memset((void*)m_fltBufferI,0,6*sizeof(float));
|
||||
memset((void*)m_fltBufferQ,0,6*sizeof(float));
|
||||
|
||||
}
|
||||
|
||||
ATVDemod::~ATVDemod()
|
||||
{
|
||||
}
|
||||
|
||||
bool ATVDemod::SetATVScreen(ATVScreen *objScreen)
|
||||
{
|
||||
m_objRegisteredATVScreen = objScreen;
|
||||
}
|
||||
|
||||
void ATVDemod::configure(MessageQueue* objMessageQueue, int intLineDurationUs, int intTopDurationUs, int intFramePerS, int intPercentOfRowsToDisplay, float fltVoltLevelSynchroTop, float fltVoltLevelSynchroBlack, ATVModulation enmModulation, bool blnHSync, bool blnVSync)
|
||||
{
|
||||
Message* msgCmd = MsgConfigureATVDemod::create(intLineDurationUs, intTopDurationUs, intFramePerS, intPercentOfRowsToDisplay, fltVoltLevelSynchroTop, fltVoltLevelSynchroBlack, enmModulation,blnHSync,blnVSync);
|
||||
objMessageQueue->push(msgCmd);
|
||||
}
|
||||
|
||||
void ATVDemod::InitATVParameters(int intMsps, int intLineDurationUs, int intTopDurationUs, int intFramePerS, int intPercentOfRowsToDisplay, float fltVoltLevelSynchroTop, float fltVoltLevelSynchroBlack, ATVModulation enmModulation, bool blnHSync, bool blnVSync)
|
||||
{
|
||||
float fltSecondToUs = 1000000.0f;
|
||||
float fltSampling=(float) intMsps;
|
||||
float fltLineTimeUs=((float) intLineDurationUs)/10.0f;
|
||||
float fltLineSynchroTop=(float) intTopDurationUs;
|
||||
float fltImagesPerSeconds=(float) intFramePerS;
|
||||
int intNumberSamplePerLine;
|
||||
int intNumberOfLines;
|
||||
bool blnNewOpenGLScreen=false;
|
||||
|
||||
m_blnInitialized=false;
|
||||
|
||||
m_objSettingsMutex.lock();
|
||||
|
||||
|
||||
if(m_objRegisteredATVScreen==NULL)
|
||||
{
|
||||
m_intNumberSamplePerLine=0;
|
||||
m_intNumberSamplePerTop=0;
|
||||
m_intNumberOfLines=0;
|
||||
|
||||
m_fltLevelSynchroTop=0.0;
|
||||
m_fltLevelSynchroBlack=1.0;
|
||||
|
||||
m_blnInitialized=false;
|
||||
m_objSettingsMutex.unlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_fltLevelSynchroTop = fltVoltLevelSynchroTop;
|
||||
m_fltLevelSynchroBlack = fltVoltLevelSynchroBlack;
|
||||
|
||||
intNumberSamplePerLine=(int)((fltLineTimeUs*fltSampling)/fltSecondToUs);
|
||||
intNumberOfLines=(int)((fltSecondToUs/fltImagesPerSeconds)/round(fltLineTimeUs));
|
||||
|
||||
if((intNumberSamplePerLine!=m_intNumberSamplePerLine)
|
||||
|| (intNumberOfLines!=m_intNumberOfLines))
|
||||
{
|
||||
blnNewOpenGLScreen=true;
|
||||
}
|
||||
|
||||
m_intNumberSamplePerLine= intNumberSamplePerLine;
|
||||
m_intNumberSamplePerTop=(int)((fltLineSynchroTop*fltSampling)/fltSecondToUs);
|
||||
m_intNumberOfLines = intNumberOfLines;
|
||||
m_intNumberOfRowsToDisplay = (int)((((float)intPercentOfRowsToDisplay)*fltLineTimeUs*fltSampling)/(fltSecondToUs*100.0f));
|
||||
m_intRowsLimit = m_intNumberOfLines-1;
|
||||
m_intImageIndex = 0;
|
||||
|
||||
m_enmModulation = enmModulation;
|
||||
|
||||
m_intColIndex=0;
|
||||
m_intRowIndex=0;
|
||||
m_intRowsLimit=0;
|
||||
|
||||
if(blnNewOpenGLScreen)
|
||||
{
|
||||
m_objRegisteredATVScreen->resizeATVScreen(m_intNumberSamplePerLine,m_intNumberOfLines);
|
||||
}
|
||||
|
||||
|
||||
//Mise à jour de la config
|
||||
m_objRunning.m_enmModulation = m_enmModulation;
|
||||
m_objRunning.m_fltVoltLevelSynchroBlack = m_fltLevelSynchroBlack;
|
||||
m_objRunning.m_fltVoltLevelSynchroTop = m_fltLevelSynchroTop;
|
||||
m_objRunning.m_intFramePerS = intFramePerS;
|
||||
m_objRunning.m_intLineDurationUs = intLineDurationUs;
|
||||
m_objRunning.m_intTopDurationUs = intTopDurationUs;
|
||||
m_objRunning.m_intMsps = intMsps;
|
||||
m_objRunning.m_intPercentOfRowsToDisplay = intPercentOfRowsToDisplay;
|
||||
m_objRunning.m_blnHSync = blnHSync;
|
||||
m_objRunning.m_blnVSync = blnVSync;
|
||||
|
||||
qDebug() << "ATV Settings "
|
||||
<< " - Msps: " << intMsps
|
||||
<< " - Line us: " << intLineDurationUs
|
||||
<< " - Top us: " << intTopDurationUs
|
||||
<< " - Frame/s: " << intFramePerS
|
||||
<< " <=> "
|
||||
<< " - Samples per Line: " << m_intNumberSamplePerLine
|
||||
<< " - Samples per Top: " << m_intNumberSamplePerTop
|
||||
<< " - Lines per Frame: " << m_intNumberOfLines
|
||||
<< " - Rows to Display: " << m_intNumberOfRowsToDisplay
|
||||
<< " - Modulation: " << ((m_enmModulation==ATV_AM)?"AM" : "FM");
|
||||
|
||||
m_objSettingsMutex.unlock();
|
||||
|
||||
m_blnInitialized=true;
|
||||
|
||||
}
|
||||
|
||||
void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
|
||||
{
|
||||
float fltDivSynchroBlack=1.0f-m_fltLevelSynchroBlack;
|
||||
float fltI;
|
||||
float fltQ;
|
||||
float fltNormI;
|
||||
float fltNormQ;
|
||||
|
||||
float fltNorm=0.00f;
|
||||
float fltVal;
|
||||
int intVal;
|
||||
|
||||
qint16 * ptrBufferToRelease=NULL;
|
||||
|
||||
bool blnComputeImage=false;
|
||||
|
||||
int intSynchroTimeSamples= (3*m_intNumberSamplePerLine)/4;
|
||||
float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples)*m_fltLevelSynchroBlack;
|
||||
|
||||
//********** Let's rock and roll buddy ! **********
|
||||
|
||||
m_objSettingsMutex.lock();
|
||||
|
||||
|
||||
//********** Accessing ATV Screen context **********
|
||||
|
||||
if(m_intImageIndex==0)
|
||||
{
|
||||
if(m_intNumberOfLines%2==1)
|
||||
{
|
||||
m_intRowsLimit = m_intNumberOfLines;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_intRowsLimit = m_intNumberOfLines-2;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTENDED_DIRECT_SAMPLE
|
||||
|
||||
qint16 * ptrBuffer;
|
||||
qint32 intLen;
|
||||
|
||||
//********** Reading direct samples **********
|
||||
|
||||
SampleVector::const_iterator it = begin;
|
||||
intLen = it->intLen;
|
||||
ptrBuffer = it->ptrBuffer;
|
||||
ptrBufferToRelease = ptrBuffer;
|
||||
++it;
|
||||
|
||||
for(qint32 intInd=0; intInd<intLen-1; intInd +=2)
|
||||
{
|
||||
|
||||
fltI= ((qint32) (*ptrBuffer)) << 4;
|
||||
ptrBuffer ++;
|
||||
fltQ= ((qint32) (*ptrBuffer)) << 4;
|
||||
ptrBuffer ++;
|
||||
#else
|
||||
|
||||
for (SampleVector::const_iterator it = begin; it != end; ++it /* ++it **/)
|
||||
{
|
||||
|
||||
fltI = it->real();
|
||||
fltQ = it->imag();
|
||||
#endif
|
||||
|
||||
|
||||
//********** demodulation **********
|
||||
|
||||
fltNorm = sqrt(fltI*fltI + fltQ*fltQ);
|
||||
|
||||
if(m_enmModulation!=ATV_AM)
|
||||
{
|
||||
//Amplitude FM
|
||||
|
||||
fltNormI= fltI/fltNorm;
|
||||
fltNormQ= fltQ/fltNorm;
|
||||
|
||||
//-2 > 2 : 0 -> 1 volt
|
||||
//0->0.3 synchro 0.3->1 image
|
||||
|
||||
if(m_enmModulation==ATV_FM1)
|
||||
{
|
||||
//YDiff Cd
|
||||
fltVal = m_fltBufferI[0]*(fltNormQ - m_fltBufferQ[1]);
|
||||
fltVal -= m_fltBufferQ[0]*(fltNormI - m_fltBufferI[1]);
|
||||
|
||||
fltVal += 2.0f;
|
||||
fltVal /=4.0f;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//YDiff Folded
|
||||
fltVal = m_fltBufferI[2]*((m_fltBufferQ[5]-fltNormQ)/16.0f + m_fltBufferQ[1] - m_fltBufferQ[3]);
|
||||
fltVal -= m_fltBufferQ[2]*((m_fltBufferI[5]-fltNormI)/16.0f + m_fltBufferI[1] - m_fltBufferI[3]);
|
||||
|
||||
fltVal += 2.125f;
|
||||
fltVal /=4.25f;
|
||||
|
||||
m_fltBufferI[5]=m_fltBufferI[4];
|
||||
m_fltBufferQ[5]=m_fltBufferQ[4];
|
||||
|
||||
m_fltBufferI[4]=m_fltBufferI[3];
|
||||
m_fltBufferQ[4]=m_fltBufferQ[3];
|
||||
|
||||
m_fltBufferI[3]=m_fltBufferI[2];
|
||||
m_fltBufferQ[3]=m_fltBufferQ[2];
|
||||
|
||||
m_fltBufferI[2]=m_fltBufferI[1];
|
||||
m_fltBufferQ[2]=m_fltBufferQ[1];
|
||||
}
|
||||
|
||||
m_fltBufferI[1]=m_fltBufferI[0];
|
||||
m_fltBufferQ[1]=m_fltBufferQ[0];
|
||||
|
||||
m_fltBufferI[0]=fltNormI;
|
||||
m_fltBufferQ[0]=fltNormQ;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Amplitude AM
|
||||
fltVal = fltNorm;
|
||||
|
||||
//********** Mini and Maxi Amplitude tracking **********
|
||||
|
||||
if(fltVal<m_fltEffMin)
|
||||
{
|
||||
m_fltEffMin=fltVal;
|
||||
}
|
||||
|
||||
if(fltVal>m_fltEffMax)
|
||||
{
|
||||
m_fltEffMax=fltVal;
|
||||
}
|
||||
|
||||
//Normalisation
|
||||
fltVal -= m_fltAmpMin;
|
||||
fltVal /=m_fltAmpDelta;
|
||||
}
|
||||
|
||||
m_fltAmpLineAverage += fltVal;
|
||||
|
||||
//********** gray level **********
|
||||
//-0.3 -> 0.7
|
||||
intVal = (int) 255.0*(fltVal-m_fltLevelSynchroBlack)/fltDivSynchroBlack;
|
||||
|
||||
//0 -> 255
|
||||
if(intVal<0)
|
||||
{
|
||||
intVal=0;
|
||||
}
|
||||
else if(intVal>255)
|
||||
{
|
||||
intVal=255;
|
||||
}
|
||||
|
||||
//********** Filling pixels **********
|
||||
|
||||
blnComputeImage=m_blnInitialized;
|
||||
|
||||
if(m_blnInitialized==true)
|
||||
{
|
||||
blnComputeImage=(m_objRunning.m_intPercentOfRowsToDisplay!=50);
|
||||
if(!blnComputeImage)
|
||||
{
|
||||
blnComputeImage=((m_intImageIndex/2)%2==0);
|
||||
}
|
||||
}
|
||||
|
||||
if(blnComputeImage)
|
||||
{
|
||||
m_objRegisteredATVScreen->setDataColor(m_intColIndex,intVal, intVal, intVal);
|
||||
}
|
||||
|
||||
m_intColIndex++;
|
||||
|
||||
//////////////////////
|
||||
|
||||
m_blnSynchroDetected=false;
|
||||
if((m_objRunning.m_blnHSync) && (m_intRowIndex>1))
|
||||
{
|
||||
//********** Line Synchro 0-0-0 -> 0.3-0.3 0.3 **********
|
||||
if(m_blnImageDetecting==false)
|
||||
{
|
||||
//Floor Detection 0
|
||||
if(fltVal<=m_fltLevelSynchroTop)
|
||||
{
|
||||
m_intSynchroPoints ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_intSynchroPoints=0;
|
||||
}
|
||||
|
||||
if(m_intSynchroPoints>=m_intNumberSamplePerTop)
|
||||
{
|
||||
m_blnSynchroDetected=true;
|
||||
m_blnImageDetecting=true;
|
||||
m_intSynchroPoints=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Image detection Sub Black 0.3
|
||||
if(fltVal>=m_fltLevelSynchroBlack)
|
||||
{
|
||||
m_intSynchroPoints ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_intSynchroPoints=0;
|
||||
}
|
||||
|
||||
if(m_intSynchroPoints>=m_intNumberSamplePerTop)
|
||||
{
|
||||
m_blnSynchroDetected=false;
|
||||
m_blnImageDetecting=false;
|
||||
m_intSynchroPoints=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//********** Rendering if necessary **********
|
||||
|
||||
// Vertical Synchro : 3/4 a line necessary
|
||||
if(!m_blnVerticalSynchroDetected && m_objRunning.m_blnVSync)
|
||||
{
|
||||
if(m_intColIndex>=intSynchroTimeSamples)
|
||||
{
|
||||
if(m_fltAmpLineAverage<=fltSynchroTrameLevel) //(m_fltLevelSynchroBlack*(float)(m_intColIndex-((m_intNumberSamplePerLine*12)/64)))) //75
|
||||
{
|
||||
m_blnVerticalSynchroDetected=true;
|
||||
|
||||
m_intRowIndex=m_intImageIndex%2;
|
||||
|
||||
if(blnComputeImage)
|
||||
{
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Horizontal Synchro
|
||||
if((m_intColIndex>=m_intNumberSamplePerLine)
|
||||
|| (m_blnSynchroDetected==true))
|
||||
{
|
||||
m_blnSynchroDetected=false;
|
||||
m_blnImageDetecting=true;
|
||||
|
||||
//New line + Interleaving
|
||||
m_intRowIndex ++;
|
||||
m_intRowIndex ++;
|
||||
m_intColIndex=0;
|
||||
|
||||
if(m_intRowIndex<m_intNumberOfLines)
|
||||
{
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
|
||||
}
|
||||
|
||||
m_fltAmpLineAverage=0.0f;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
||||
if(m_intRowIndex>=m_intRowsLimit)
|
||||
{
|
||||
|
||||
m_blnVerticalSynchroDetected=false;
|
||||
|
||||
m_fltAmpLineAverage=0.0f;
|
||||
|
||||
//Interleave Odd/Even images
|
||||
m_intRowIndex=m_intImageIndex%2;
|
||||
m_intColIndex=0;
|
||||
|
||||
if(blnComputeImage)
|
||||
{
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
|
||||
}
|
||||
|
||||
//Rendering when odd image processed
|
||||
if(m_intImageIndex%2==1)
|
||||
{
|
||||
//interleave
|
||||
if(blnComputeImage)
|
||||
{
|
||||
m_objRegisteredATVScreen->renderImage(NULL);
|
||||
}
|
||||
|
||||
m_intRowsLimit = m_intNumberOfLines-1;
|
||||
|
||||
if(m_objRunning.m_enmModulation==ATV_AM)
|
||||
{
|
||||
m_fltAmpMin=m_fltEffMin;
|
||||
m_fltAmpMax=m_fltEffMax;
|
||||
m_fltAmpDelta=m_fltEffMax-m_fltEffMin;
|
||||
|
||||
if(m_fltAmpDelta<=0.0)
|
||||
{
|
||||
m_fltAmpDelta=1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_intNumberOfLines%2==1)
|
||||
{
|
||||
m_intRowsLimit = m_intNumberOfLines;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_intRowsLimit = m_intNumberOfLines-2;
|
||||
}
|
||||
}
|
||||
|
||||
m_intImageIndex ++;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
}
|
||||
|
||||
if(ptrBufferToRelease!=NULL)
|
||||
{
|
||||
delete ptrBufferToRelease;
|
||||
}
|
||||
|
||||
m_objSettingsMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
void ATVDemod::start()
|
||||
{
|
||||
//m_objTimer.start();
|
||||
}
|
||||
|
||||
void ATVDemod::stop()
|
||||
{
|
||||
}
|
||||
|
||||
bool ATVDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
qDebug() << "ATVDemod::handleMessage";
|
||||
|
||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
|
||||
if(m_objRunning.m_intMsps!=objNotif.getSampleRate())
|
||||
{
|
||||
m_objRunning.m_intMsps = objNotif.getSampleRate();
|
||||
ApplySettings();
|
||||
}
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgChannelizerNotification:"
|
||||
<< " m_intMsps: " << m_objRunning.m_intMsps;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureATVDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureATVDemod& objCfg = (MsgConfigureATVDemod&) cmd;
|
||||
|
||||
if((objCfg.m_objMsgConfig.m_enmModulation != m_objRunning.m_enmModulation)
|
||||
|| (objCfg.m_objMsgConfig.m_fltVoltLevelSynchroBlack != m_objRunning.m_fltVoltLevelSynchroBlack)
|
||||
|| (objCfg.m_objMsgConfig.m_fltVoltLevelSynchroTop != m_objRunning.m_fltVoltLevelSynchroTop)
|
||||
|| (objCfg.m_objMsgConfig.m_intFramePerS != m_objRunning.m_intFramePerS)
|
||||
|| (objCfg.m_objMsgConfig.m_intLineDurationUs != m_objRunning.m_intLineDurationUs)
|
||||
|| (objCfg.m_objMsgConfig.m_intPercentOfRowsToDisplay != m_objRunning.m_intPercentOfRowsToDisplay)
|
||||
|| (objCfg.m_objMsgConfig.m_intTopDurationUs != m_objRunning.m_intTopDurationUs)
|
||||
|| (objCfg.m_objMsgConfig.m_blnHSync != m_objRunning.m_blnHSync)
|
||||
|| (objCfg.m_objMsgConfig.m_blnVSync != m_objRunning.m_blnVSync))
|
||||
{
|
||||
m_objRunning.m_enmModulation = objCfg.m_objMsgConfig.m_enmModulation;
|
||||
m_objRunning.m_fltVoltLevelSynchroBlack = objCfg.m_objMsgConfig.m_fltVoltLevelSynchroBlack;
|
||||
m_objRunning.m_fltVoltLevelSynchroTop = objCfg.m_objMsgConfig.m_fltVoltLevelSynchroTop;
|
||||
m_objRunning.m_intFramePerS = objCfg.m_objMsgConfig.m_intFramePerS;
|
||||
m_objRunning.m_intLineDurationUs = objCfg.m_objMsgConfig.m_intLineDurationUs;
|
||||
m_objRunning.m_intPercentOfRowsToDisplay = objCfg.m_objMsgConfig.m_intPercentOfRowsToDisplay;
|
||||
m_objRunning.m_intTopDurationUs = objCfg.m_objMsgConfig.m_intTopDurationUs;
|
||||
m_objRunning.m_blnHSync = objCfg.m_objMsgConfig.m_blnHSync;
|
||||
m_objRunning.m_blnVSync = objCfg.m_objMsgConfig.m_blnVSync;
|
||||
|
||||
ApplySettings();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ATVDemod::ApplySettings()
|
||||
{
|
||||
|
||||
if(m_objRunning.m_intMsps==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
InitATVParameters(m_objRunning.m_intMsps,m_objRunning.m_intLineDurationUs,m_objRunning.m_intTopDurationUs,m_objRunning.m_intFramePerS,m_objRunning.m_intPercentOfRowsToDisplay,m_objRunning.m_fltVoltLevelSynchroTop,m_objRunning.m_fltVoltLevelSynchroBlack,m_objRunning.m_enmModulation,m_objRunning.m_blnHSync, m_objRunning.m_blnVSync);
|
||||
}
|
||||
|
||||
int ATVDemod::GetSampleRate()
|
||||
{
|
||||
return m_objRunning.m_intMsps;
|
||||
}
|
168
plugins/channelrx/demodatv/atvdemod.h
Normal file
168
plugins/channelrx/demodatv/atvdemod.h
Normal file
@ -0,0 +1,168 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_ATVDEMOD_H
|
||||
#define INCLUDE_ATVDEMOD_H
|
||||
|
||||
#include <dsp/basebandsamplesink.h>
|
||||
#include <dsp/devicesamplesource.h>
|
||||
#include <dsp/dspcommands.h>
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include <QMutex>
|
||||
#include <QElapsedTimer>
|
||||
#include <vector>
|
||||
#include "dsp/nco.h"
|
||||
#include "dsp/interpolator.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "dsp/agc.h"
|
||||
#include "audio/audiofifo.h"
|
||||
#include "util/message.h"
|
||||
#include "atvscreen.h"
|
||||
|
||||
|
||||
enum ATVModulation { ATV_AM, ATV_FM1 , ATV_FM2 };
|
||||
|
||||
struct ATVConfig
|
||||
{
|
||||
int m_intMsps;
|
||||
int m_intLineDurationUs;
|
||||
int m_intTopDurationUs;
|
||||
int m_intFramePerS;
|
||||
int m_intPercentOfRowsToDisplay;
|
||||
float m_fltVoltLevelSynchroTop;
|
||||
float m_fltVoltLevelSynchroBlack;
|
||||
ATVModulation m_enmModulation;
|
||||
bool m_blnHSync;
|
||||
bool m_blnVSync;
|
||||
|
||||
ATVConfig() :
|
||||
m_intMsps(0),
|
||||
m_intLineDurationUs(0),
|
||||
m_intTopDurationUs(0),
|
||||
m_intFramePerS(0),
|
||||
m_intPercentOfRowsToDisplay(0),
|
||||
m_fltVoltLevelSynchroTop(0),
|
||||
m_fltVoltLevelSynchroBlack(0),
|
||||
m_enmModulation(ATV_FM1),
|
||||
m_blnHSync(false),
|
||||
m_blnVSync(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ATVDemod : public BasebandSampleSink
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ATVDemod();
|
||||
~ATVDemod();
|
||||
|
||||
void configure(MessageQueue* objMessageQueue, int intLineDurationUs, int intTopDurationUs, int intFramePerS, int intPercentOfRowsToDisplay, float fltVoltLevelSynchroTop, float fltVoltLevelSynchroBlack, ATVModulation enmModulation, bool blnHSync, bool blnVSync);
|
||||
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
bool SetATVScreen(ATVScreen *objScreen);
|
||||
void InitATVParameters(int intMsps, int intLineDurationUs, int intTopDurationUs, int intFramePerS, int intPercentOfRowsToDisplay, float fltVoltLevelSynchroTop, float fltVoltLevelSynchroBlack, ATVModulation enmModulation, bool blnHSync, bool blnVSync);
|
||||
int GetSampleRate();
|
||||
|
||||
private:
|
||||
|
||||
//*************** ATV PARAMETERS ***************
|
||||
ATVScreen * m_objRegisteredATVScreen;
|
||||
|
||||
int m_intNumberSamplePerLine;
|
||||
int m_intNumberSamplePerTop;
|
||||
int m_intNumberOfLines;
|
||||
bool m_blnInitialized;
|
||||
int m_intNumberOfRowsToDisplay;
|
||||
|
||||
float m_fltLevelSynchroTop;
|
||||
float m_fltLevelSynchroBlack;
|
||||
|
||||
ATVModulation m_enmModulation;
|
||||
|
||||
//*************** PROCESSING ***************
|
||||
|
||||
int m_intImageIndex;
|
||||
int m_intRowsLimit;
|
||||
int m_intSynchroPoints;
|
||||
|
||||
bool m_blnSynchroDetected;
|
||||
bool m_blnImageDetecting;
|
||||
bool m_blnVerticalSynchroDetected;
|
||||
|
||||
float m_fltAmpLineAverage;
|
||||
|
||||
float m_fltEffMin;
|
||||
float m_fltEffMax;
|
||||
|
||||
float m_fltAmpMin;
|
||||
float m_fltAmpMax;
|
||||
float m_fltAmpDelta;
|
||||
|
||||
float m_fltBufferI[6];
|
||||
float m_fltBufferQ[6];
|
||||
|
||||
int m_intColIndex;
|
||||
int m_intRowIndex;
|
||||
|
||||
//QElapsedTimer m_objTimer;
|
||||
private:
|
||||
|
||||
class MsgConfigureATVDemod : public Message
|
||||
{
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
static MsgConfigureATVDemod* create(int intLineDurationUs, int intTopDurationUs, int intFramePerS, int intPercentOfRowsToDisplay, float fltVoltLevelSynchroTop, float fltVoltLevelSynchroBlack, ATVModulation enmModulation, bool blnHSync, bool blnVSync)
|
||||
{
|
||||
return new MsgConfigureATVDemod(intLineDurationUs, intTopDurationUs, intFramePerS, intPercentOfRowsToDisplay, fltVoltLevelSynchroTop, fltVoltLevelSynchroBlack, enmModulation, blnHSync, blnVSync);
|
||||
}
|
||||
|
||||
ATVConfig m_objMsgConfig;
|
||||
|
||||
private:
|
||||
MsgConfigureATVDemod(int intLineDurationUs, int intTopDurationUs, int intFramePerS, int intPercentOfRowsToDisplay, float fltVoltLevelSynchroTop, float fltVoltLevelSynchroBlack, ATVModulation enmModulation, bool blnHSync, bool blnVSync) :
|
||||
Message()
|
||||
{
|
||||
m_objMsgConfig.m_enmModulation = enmModulation;
|
||||
m_objMsgConfig.m_fltVoltLevelSynchroBlack = fltVoltLevelSynchroBlack;
|
||||
m_objMsgConfig.m_fltVoltLevelSynchroTop = fltVoltLevelSynchroTop;
|
||||
m_objMsgConfig.m_intFramePerS = intFramePerS;
|
||||
m_objMsgConfig.m_intLineDurationUs = intLineDurationUs;
|
||||
m_objMsgConfig.m_intTopDurationUs = intTopDurationUs;
|
||||
m_objMsgConfig.m_intPercentOfRowsToDisplay = intPercentOfRowsToDisplay;
|
||||
m_objMsgConfig.m_blnHSync = blnHSync;
|
||||
m_objMsgConfig.m_blnVSync = blnVSync;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ATVConfig m_objRunning;
|
||||
|
||||
QMutex m_objSettingsMutex;
|
||||
|
||||
void ApplySettings();
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ATVDEMOD_H
|
337
plugins/channelrx/demodatv/atvdemodgui.cpp
Normal file
337
plugins/channelrx/demodatv/atvdemodgui.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "atvdemodgui.h"
|
||||
|
||||
#include "device/devicesourceapi.h"
|
||||
#include "dsp/downchannelizer.h"
|
||||
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include "ui_atvdemodgui.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "util/db.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "atvdemod.h"
|
||||
|
||||
const QString ATVDemodGUI::m_strChannelID = "sdrangel.channel.demodatv";
|
||||
|
||||
ATVDemodGUI* ATVDemodGUI::create(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI)
|
||||
{
|
||||
ATVDemodGUI* gui = new ATVDemodGUI(objPluginAPI, objDeviceAPI);
|
||||
return gui;
|
||||
}
|
||||
|
||||
void ATVDemodGUI::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void ATVDemodGUI::setName(const QString& strName)
|
||||
{
|
||||
setObjectName(strName);
|
||||
}
|
||||
|
||||
QString ATVDemodGUI::getName() const
|
||||
{
|
||||
return objectName();
|
||||
}
|
||||
|
||||
qint64 ATVDemodGUI::getCenterFrequency() const
|
||||
{
|
||||
return m_objChannelMarker.getCenterFrequency();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::setCenterFrequency(qint64 intCenterFrequency)
|
||||
{
|
||||
m_objChannelMarker.setCenterFrequency(intCenterFrequency);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::resetToDefaults()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
//ui->rfBW->setValue(50);
|
||||
|
||||
blockApplySettings(false);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
QByteArray ATVDemodGUI::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
|
||||
//s.writeS32(2, ui->rfBW->value());
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool ATVDemodGUI::deserialize(const QByteArray& arrData)
|
||||
{
|
||||
SimpleDeserializer d(arrData);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
|
||||
blockApplySettings(true);
|
||||
m_objChannelMarker.blockSignals(true);
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_objChannelMarker.setCenterFrequency(tmp);
|
||||
//d.readS32(2, &tmp, 4);
|
||||
//ui->rfBW->setValue(tmp);
|
||||
|
||||
if(d.readU32(7, &u32tmp))
|
||||
{
|
||||
m_objChannelMarker.setColor(u32tmp);
|
||||
}
|
||||
|
||||
blockApplySettings(false);
|
||||
m_objChannelMarker.blockSignals(false);
|
||||
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ATVDemodGUI::handleMessage(const Message& objMessage)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ATVDemodGUI::viewChanged()
|
||||
{
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
{
|
||||
}
|
||||
|
||||
void ATVDemodGUI::onMenuDoubleClicked()
|
||||
{
|
||||
if(!m_blnBasicSettingsShown)
|
||||
{
|
||||
m_blnBasicSettingsShown = true;
|
||||
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(&m_objChannelMarker, this);
|
||||
bcsw->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI, QWidget* objParent) :
|
||||
RollupWidget(objParent),
|
||||
ui(new Ui::ATVDemodGUI),
|
||||
m_objPluginAPI(objPluginAPI),
|
||||
m_objDeviceAPI(objDeviceAPI),
|
||||
m_objChannelMarker(this),
|
||||
m_blnBasicSettingsShown(false),
|
||||
m_blnDoApplySettings(true)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_objATVDemod = new ATVDemod();
|
||||
m_objATVDemod->SetATVScreen(ui->screenTV);
|
||||
|
||||
m_objChannelizer = new DownChannelizer(m_objATVDemod);
|
||||
m_objThreadedChannelizer = new ThreadedBasebandSampleSink(m_objChannelizer, this);
|
||||
m_objDeviceAPI->addThreadedSink(m_objThreadedChannelizer);
|
||||
|
||||
//m_objPluginAPI->addThreadedSink(m_objThreadedChannelizer);
|
||||
//connect(&m_objPluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
||||
|
||||
m_objChannelMarker.setColor(Qt::white);
|
||||
m_objChannelMarker.setBandwidth(6000000);
|
||||
|
||||
m_objChannelMarker.setCenterFrequency(0);
|
||||
m_objChannelMarker.setVisible(true);
|
||||
|
||||
//connect(&m_objchannelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
|
||||
m_objDeviceAPI->registerChannelInstance(m_strChannelID, this);
|
||||
m_objDeviceAPI->addChannelMarker(&m_objChannelMarker);
|
||||
m_objDeviceAPI->addRollupWidget(this);
|
||||
|
||||
ui->screenTV->connectTimer(m_objPluginAPI->getMainWindow()->getMasterTimer());
|
||||
|
||||
//********** ATV Default values **********
|
||||
ui->horizontalSlider->setValue(100);
|
||||
ui->horizontalSlider_2->setValue(310);
|
||||
ui->horizontalSlider_3->setValue(640);
|
||||
ui->horizontalSlider_4->setValue(3);
|
||||
ui->comboBox_2->setCurrentIndex(0);
|
||||
ui->comboBox->setCurrentIndex(0);
|
||||
ui->checkBox->setChecked(true);
|
||||
ui->checkBox_2->setChecked(true);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
||||
ATVDemodGUI::~ATVDemodGUI()
|
||||
{
|
||||
m_objDeviceAPI->removeChannelInstance(this);
|
||||
m_objDeviceAPI->removeThreadedSink(m_objThreadedChannelizer);
|
||||
delete m_objThreadedChannelizer;
|
||||
delete m_objChannelizer;
|
||||
delete m_objATVDemod;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ATVDemodGUI::blockApplySettings(bool blnBlock)
|
||||
{
|
||||
m_blnDoApplySettings = !blnBlock;
|
||||
}
|
||||
|
||||
void ATVDemodGUI::applySettings()
|
||||
{
|
||||
ATVModulation enmSelectedModulation;
|
||||
|
||||
if (m_blnDoApplySettings)
|
||||
{
|
||||
setTitleColor(m_objChannelMarker.getColor());
|
||||
|
||||
m_objChannelizer->configure(m_objChannelizer->getInputMessageQueue(), m_objATVDemod->GetSampleRate(), m_objChannelMarker.getCenterFrequency());
|
||||
|
||||
switch(ui->comboBox_2->currentIndex())
|
||||
{
|
||||
case 0:
|
||||
enmSelectedModulation=ATV_FM1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
enmSelectedModulation=ATV_FM2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
enmSelectedModulation=ATV_AM;
|
||||
break;
|
||||
|
||||
default:
|
||||
enmSelectedModulation=ATV_FM1;
|
||||
break;
|
||||
}
|
||||
|
||||
m_objATVDemod->configure(m_objATVDemod->getInputMessageQueue(),
|
||||
ui->horizontalSlider_3->value(),
|
||||
ui->horizontalSlider_4->value(),
|
||||
(ui->comboBox->currentIndex()==0)?25:30,
|
||||
(ui->checkBox_3->checkState()==Qt::Checked)?50:100,
|
||||
((float)(ui->horizontalSlider->value()))/1000.0f,
|
||||
((float)(ui->horizontalSlider_2->value()))/1000.0f,
|
||||
enmSelectedModulation,
|
||||
ui->checkBox->isChecked(),
|
||||
ui->checkBox_2->isChecked());
|
||||
|
||||
m_objChannelMarker.setBandwidth(m_objATVDemod->GetSampleRate());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ATVDemodGUI::leaveEvent(QEvent*)
|
||||
{
|
||||
blockApplySettings(true);
|
||||
m_objChannelMarker.setHighlighted(false);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void ATVDemodGUI::enterEvent(QEvent*)
|
||||
{
|
||||
blockApplySettings(true);
|
||||
m_objChannelMarker.setHighlighted(true);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void ATVDemodGUI::tick()
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
void ATVDemodGUI::on_horizontalSlider_valueChanged(int value)
|
||||
{
|
||||
applySettings();
|
||||
ui->label_2->setText(QString("%1 mV").arg(value));
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_horizontalSlider_2_valueChanged(int value)
|
||||
{
|
||||
applySettings();
|
||||
ui->label_4->setText(QString("%1 mV").arg(value));
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_horizontalSlider_3_valueChanged(int value)
|
||||
{
|
||||
ui->label_6->setText(QString("%1 uS").arg(((float)value)/10.0f));
|
||||
applySettings();
|
||||
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_horizontalSlider_4_valueChanged(int value)
|
||||
{
|
||||
ui->label_8->setText(QString("%1 uS").arg(value));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_checkBox_clicked()
|
||||
{
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_checkBox_2_clicked()
|
||||
{
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_checkBox_3_clicked()
|
||||
{
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_comboBox_currentIndexChanged(int index)
|
||||
{
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_comboBox_2_currentIndexChanged(int index)
|
||||
{
|
||||
applySettings();
|
||||
}
|
96
plugins/channelrx/demodatv/atvdemodgui.h
Normal file
96
plugins/channelrx/demodatv/atvdemodgui.h
Normal file
@ -0,0 +1,96 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_ATVDEMODGUI_H
|
||||
#define INCLUDE_ATVDEMODGUI_H
|
||||
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "plugin/plugingui.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceSourceAPI;
|
||||
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
class ATVDemod;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ATVDemodGUI;
|
||||
}
|
||||
|
||||
class ATVDemodGUI : public RollupWidget, public PluginGUI
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static ATVDemodGUI* create(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI);
|
||||
void destroy();
|
||||
|
||||
void setName(const QString& strName);
|
||||
QString getName() const;
|
||||
virtual qint64 getCenterFrequency() const;
|
||||
virtual void setCenterFrequency(qint64 intCenterFrequency);
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& arrData);
|
||||
|
||||
virtual bool handleMessage(const Message& objMessage);
|
||||
|
||||
static const QString m_strChannelID;
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDoubleClicked();
|
||||
void tick();
|
||||
void on_horizontalSlider_valueChanged(int value);
|
||||
void on_horizontalSlider_2_valueChanged(int value);
|
||||
void on_horizontalSlider_3_valueChanged(int value);
|
||||
void on_horizontalSlider_4_valueChanged(int value);
|
||||
void on_checkBox_clicked();
|
||||
void on_checkBox_2_clicked();
|
||||
void on_checkBox_3_clicked();
|
||||
void on_comboBox_currentIndexChanged(int index);
|
||||
void on_comboBox_2_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::ATVDemodGUI* ui;
|
||||
PluginAPI* m_objPluginAPI;
|
||||
DeviceSourceAPI* m_objDeviceAPI;
|
||||
ChannelMarker m_objChannelMarker;
|
||||
ThreadedBasebandSampleSink* m_objThreadedChannelizer;
|
||||
DownChannelizer* m_objChannelizer;
|
||||
ATVDemod* m_objATVDemod;
|
||||
|
||||
bool m_blnBasicSettingsShown;
|
||||
bool m_blnDoApplySettings;
|
||||
|
||||
explicit ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI, QWidget* objParent = NULL);
|
||||
virtual ~ATVDemodGUI();
|
||||
|
||||
void blockApplySettings(bool blnBlock);
|
||||
void applySettings();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ATVDEMODGUI_H
|
419
plugins/channelrx/demodatv/atvdemodgui.ui
Normal file
419
plugins/channelrx/demodatv/atvdemodgui.ui
Normal file
@ -0,0 +1,419 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ATVDemodGUI</class>
|
||||
<widget class="RollupWidget" name="ATVDemodGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>450</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ATV Demodulator</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>481</width>
|
||||
<height>361</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="signalLevelLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ATVScreen" name="screenTV" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>460</width>
|
||||
<height>345</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>460</width>
|
||||
<height>345</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>380</y>
|
||||
<width>481</width>
|
||||
<height>105</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>461</width>
|
||||
<height>105</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>ATV Settings</string>
|
||||
</property>
|
||||
<widget class="QSlider" name="horizontalSlider_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>310</x>
|
||||
<y>60</y>
|
||||
<width>101</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>140</x>
|
||||
<y>30</y>
|
||||
<width>72</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="25">25 Fps</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="30">30 Fps</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QSlider" name="horizontalSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>60</y>
|
||||
<width>101</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>250</x>
|
||||
<y>30</y>
|
||||
<width>61</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>HSync</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="checkBox_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>340</x>
|
||||
<y>30</y>
|
||||
<width>61</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VSync</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>60</y>
|
||||
<width>41</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Synch</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>60</y>
|
||||
<width>51</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="right">mV</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>250</x>
|
||||
<y>60</y>
|
||||
<width>61</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Black Lvl</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>420</x>
|
||||
<y>60</y>
|
||||
<width>51</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="right">mV</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="checkBox_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>420</x>
|
||||
<y>30</y>
|
||||
<width>51</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Half</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>80</y>
|
||||
<width>31</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Line</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="horizontalSlider_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>80</y>
|
||||
<width>101</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>80</y>
|
||||
<width>51</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="right">uS</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>250</x>
|
||||
<y>80</y>
|
||||
<width>31</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Top</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="horizontalSlider_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>310</x>
|
||||
<y>80</y>
|
||||
<width>101</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>420</x>
|
||||
<y>80</y>
|
||||
<width>51</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="right">uS</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>72</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FM 1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FM 2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AM</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RollupWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ATVScreen</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>atvscreen.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
72
plugins/channelrx/demodatv/atvdemodplugin.cpp
Normal file
72
plugins/channelrx/demodatv/atvdemodplugin.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <QtPlugin>
|
||||
#include <QAction>
|
||||
#include "plugin/pluginapi.h"
|
||||
|
||||
#include "atvdemodgui.h"
|
||||
#include "atvdemodplugin.h"
|
||||
|
||||
const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor =
|
||||
{
|
||||
QString("ATV Demodulator"),
|
||||
QString("3.2.0"),
|
||||
QString("(c) F4HKW for F4EXB / SDRAngel"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
QString("https://github.com/f4exb/sdrangel")
|
||||
};
|
||||
|
||||
ATVDemodPlugin::ATVDemodPlugin(QObject* ptrParent) :
|
||||
QObject(ptrParent),
|
||||
m_ptrPluginAPI(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const PluginDescriptor& ATVDemodPlugin::getPluginDescriptor() const
|
||||
{
|
||||
return m_ptrPluginDescriptor;
|
||||
}
|
||||
|
||||
void ATVDemodPlugin::initPlugin(PluginAPI* ptrPluginAPI)
|
||||
{
|
||||
m_ptrPluginAPI = ptrPluginAPI;
|
||||
|
||||
// register ATV demodulator
|
||||
m_ptrPluginAPI->registerRxChannel(ATVDemodGUI::m_strChannelID, this);
|
||||
}
|
||||
|
||||
PluginGUI* ATVDemodPlugin::createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI)
|
||||
{
|
||||
if(strChannelName == ATVDemodGUI::m_strChannelID)
|
||||
{
|
||||
ATVDemodGUI* ptrGui = ATVDemodGUI::create(m_ptrPluginAPI, ptrDeviceAPI);
|
||||
return ptrGui;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ATVDemodPlugin::createInstanceDemodATV(DeviceSourceAPI *ptrDeviceAPI)
|
||||
{
|
||||
ATVDemodGUI::create(m_ptrPluginAPI, ptrDeviceAPI);
|
||||
}
|
49
plugins/channelrx/demodatv/atvdemodplugin.h
Normal file
49
plugins/channelrx/demodatv/atvdemodplugin.h
Normal file
@ -0,0 +1,49 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_ATVPLUGIN_H
|
||||
#define INCLUDE_ATVPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include "plugin/plugininterface.h"
|
||||
|
||||
class DeviceSourceAPI;
|
||||
|
||||
class ATVDemodPlugin : public QObject, PluginInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(PluginInterface)
|
||||
Q_PLUGIN_METADATA(IID "sdrangel.channel.demodatv")
|
||||
|
||||
public:
|
||||
explicit ATVDemodPlugin(QObject* ptrParent = NULL);
|
||||
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* ptrPluginAPI);
|
||||
|
||||
PluginGUI* createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_ptrPluginDescriptor;
|
||||
|
||||
PluginAPI* m_ptrPluginAPI;
|
||||
|
||||
private slots:
|
||||
void createInstanceDemodATV(DeviceSourceAPI *ptrDeviceAPI);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ATVPLUGIN_H
|
205
plugins/channelrx/demodatv/atvscreen.cpp
Normal file
205
plugins/channelrx/demodatv/atvscreen.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// OpenGL interface modernization. //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QSurface>
|
||||
#include "atvscreen.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QDebug>
|
||||
|
||||
ATVScreen::ATVScreen(QWidget* parent) :
|
||||
QGLWidget(parent),
|
||||
m_objMutex(QMutex::NonRecursive)
|
||||
{
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
//connect(&m_objTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
//m_objTimer.start(50);
|
||||
|
||||
m_chrLastData=NULL;
|
||||
m_blnDataChanged=false;
|
||||
m_blnGLContextInitialized=false;
|
||||
|
||||
m_intAskedCols=0;
|
||||
m_intAskedRows=0;
|
||||
|
||||
}
|
||||
|
||||
ATVScreen::~ATVScreen()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
QRgb* ATVScreen::getRowBuffer(int intRow)
|
||||
{
|
||||
if(m_blnGLContextInitialized==false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_objGLShaderArray.GetRowBuffer(intRow);
|
||||
}
|
||||
|
||||
void ATVScreen::renderImage(unsigned char * objData)
|
||||
{
|
||||
m_chrLastData=objData;
|
||||
update();
|
||||
}
|
||||
|
||||
void ATVScreen::resetImage()
|
||||
{
|
||||
m_objGLShaderArray.ResetPixels();
|
||||
}
|
||||
|
||||
void ATVScreen::resizeATVScreen(int intCols, int intRows)
|
||||
{
|
||||
m_intAskedCols=intCols;
|
||||
m_intAskedRows=intRows;
|
||||
}
|
||||
|
||||
void ATVScreen::initializeGL()
|
||||
{
|
||||
m_objMutex.lock();
|
||||
|
||||
QOpenGLContext *objGlCurrentContext = QOpenGLContext::currentContext();
|
||||
|
||||
if (objGlCurrentContext)
|
||||
{
|
||||
if (QOpenGLContext::currentContext()->isValid())
|
||||
{
|
||||
qDebug() << "ATVScreen::initializeGL: context:"
|
||||
<< " major: " << (QOpenGLContext::currentContext()->format()).majorVersion()
|
||||
<< " minor: " << (QOpenGLContext::currentContext()->format()).minorVersion()
|
||||
<< " ES: " << (QOpenGLContext::currentContext()->isOpenGLES() ? "yes" : "no");
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ATVScreen::initializeGL: current context is invalid";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "ATVScreen::initializeGL: no current context";
|
||||
return;
|
||||
}
|
||||
|
||||
QSurface *objSurface = objGlCurrentContext->surface();
|
||||
|
||||
if (objSurface == NULL)
|
||||
{
|
||||
qCritical() << "ATVScreen::initializeGL: no surface attached";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (objSurface->surfaceType() != QSurface::OpenGLSurface)
|
||||
{
|
||||
qCritical() << "ATVScreen::initializeGL: surface is not an OpenGLSurface: " << objSurface->surfaceType() << " cannot use an OpenGL context";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ATVScreen::initializeGL: OpenGL surface:" << " class: " << (objSurface->surfaceClass() == QSurface::Window ? "Window" : "Offscreen");
|
||||
}
|
||||
}
|
||||
|
||||
connect(objGlCurrentContext, &QOpenGLContext::aboutToBeDestroyed, this, &ATVScreen::cleanup); // TODO: when migrating to QOpenGLWidget
|
||||
|
||||
//Par défaut
|
||||
m_intAskedCols = ATV_COLS;
|
||||
m_intAskedRows = ATV_ROWS;
|
||||
|
||||
m_blnGLContextInitialized=true;
|
||||
|
||||
m_objMutex.unlock();
|
||||
}
|
||||
|
||||
void ATVScreen::resizeGL(int intWidth, int intHeight)
|
||||
{
|
||||
QOpenGLFunctions *ptrF = QOpenGLContext::currentContext()->functions();
|
||||
ptrF->glViewport(0, 0, intWidth, intHeight);
|
||||
m_blnConfigChanged = true;
|
||||
}
|
||||
|
||||
void ATVScreen::paintGL()
|
||||
{
|
||||
m_objMutex.lock();
|
||||
|
||||
if(m_blnGLContextInitialized)
|
||||
{
|
||||
if((m_intAskedCols!=0) && (m_intAskedRows!=0))
|
||||
{
|
||||
m_objGLShaderArray.InitializeGL(m_intAskedCols, m_intAskedRows);
|
||||
m_intAskedCols=0;
|
||||
m_intAskedRows=0;
|
||||
}
|
||||
|
||||
m_objGLShaderArray.RenderPixels(m_chrLastData);
|
||||
}
|
||||
|
||||
m_objMutex.unlock();
|
||||
}
|
||||
|
||||
void ATVScreen::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ATVScreen::tick()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ATVScreen::connectTimer(const QTimer& objTimer)
|
||||
{
|
||||
/*
|
||||
qDebug() << "ATVScreen::connectTimer";
|
||||
disconnect(&m_objTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
connect(&objTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
m_objTimer.stop();
|
||||
*/
|
||||
}
|
||||
|
||||
void ATVScreen::cleanup()
|
||||
{
|
||||
if(m_blnGLContextInitialized)
|
||||
{
|
||||
m_objGLShaderArray.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ATVScreen::selectRow(int intLine)
|
||||
{
|
||||
if(m_blnGLContextInitialized)
|
||||
{
|
||||
return m_objGLShaderArray.SelectRow(intLine);
|
||||
}
|
||||
}
|
||||
|
||||
bool ATVScreen::setDataColor(int intCol,int intRed, int intGreen, int intBlue)
|
||||
{
|
||||
if(m_blnGLContextInitialized)
|
||||
{
|
||||
return m_objGLShaderArray.SetDataColor(intCol, qRgb(intRed, intGreen, intBlue));
|
||||
}
|
||||
}
|
98
plugins/channelrx/demodatv/atvscreen.h
Normal file
98
plugins/channelrx/demodatv/atvscreen.h
Normal file
@ -0,0 +1,98 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// OpenGL interface modernization. //
|
||||
// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_ATVSCREEN_H
|
||||
#define INCLUDE_ATVSCREEN_H
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QPen>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
#include <QFont>
|
||||
#include <QMatrix4x4>
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "dsp/scopevis.h"
|
||||
#include "gui/scaleengine.h"
|
||||
#include "glshaderarray.h"
|
||||
#include "gui/glshadertextured.h"
|
||||
#include "util/export.h"
|
||||
#include "util/bitfieldindex.h"
|
||||
|
||||
|
||||
class ScopeVis;
|
||||
class QPainter;
|
||||
|
||||
|
||||
|
||||
class SDRANGEL_API ATVScreen: public QGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ATVScreen(QWidget* parent = NULL);
|
||||
~ATVScreen();
|
||||
|
||||
void resizeATVScreen(int intCols, int intRows);
|
||||
void renderImage(unsigned char * objData);
|
||||
QRgb* getRowBuffer(int intRow);
|
||||
void resetImage();
|
||||
|
||||
bool selectRow(int intLine);
|
||||
bool setDataColor(int intCol,int intRed, int intGreen, int intBlue);
|
||||
|
||||
void connectTimer(const QTimer& timer);
|
||||
|
||||
//Valeurs par défaut
|
||||
static const int ATV_COLS=192;
|
||||
static const int ATV_ROWS=625;
|
||||
|
||||
signals:
|
||||
void traceSizeChanged(int);
|
||||
void sampleRateChanged(int);
|
||||
|
||||
private:
|
||||
bool m_blnGLContextInitialized;
|
||||
int m_intAskedCols;
|
||||
int m_intAskedRows;
|
||||
|
||||
|
||||
// state
|
||||
QTimer m_objTimer;
|
||||
QMutex m_objMutex;
|
||||
bool m_blnDataChanged;
|
||||
bool m_blnConfigChanged;
|
||||
|
||||
GLShaderArray m_objGLShaderArray;
|
||||
|
||||
void initializeGL();
|
||||
void resizeGL(int width, int height);
|
||||
void paintGL();
|
||||
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
|
||||
unsigned char *m_chrLastData;
|
||||
|
||||
protected slots:
|
||||
void cleanup();
|
||||
void tick();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ATVSCREEN_H
|
41
plugins/channelrx/demodatv/demodatv.pro
Normal file
41
plugins/channelrx/demodatv/demodatv.pro
Normal file
@ -0,0 +1,41 @@
|
||||
#--------------------------------------------------------
|
||||
#
|
||||
# Pro file for Android and Windows builds with Qt Creator
|
||||
#
|
||||
#--------------------------------------------------------
|
||||
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin
|
||||
|
||||
QT += core gui widgets multimedia
|
||||
|
||||
TARGET = demodam
|
||||
|
||||
DEFINES += USE_SSE2=1
|
||||
QMAKE_CXXFLAGS += -msse2
|
||||
DEFINES += USE_SSE4_1=1
|
||||
QMAKE_CXXFLAGS += -msse4.1
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
INCLUDEPATH += ../../../sdrbase
|
||||
|
||||
CONFIG(Release):build_subdir = release
|
||||
CONFIG(Debug):build_subdir = debug
|
||||
|
||||
SOURCES += atvdemod.cpp\
|
||||
atvdemodgui.cpp\
|
||||
atvdemodplugin.cpp\
|
||||
atvscreen.cpp\
|
||||
glshaderarray.cpp
|
||||
|
||||
HEADERS += atvdemod.h\
|
||||
atvdemodgui.h\
|
||||
atvdemodplugin.h\
|
||||
atvscreen.h\
|
||||
glshaderarray.h
|
||||
|
||||
FORMS += atvdemodgui.ui
|
||||
|
||||
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
|
||||
|
||||
RESOURCES = ../../../sdrbase/resources/res.qrc
|
303
plugins/channelrx/demodatv/glshaderarray.cpp
Normal file
303
plugins/channelrx/demodatv/glshaderarray.cpp
Normal file
@ -0,0 +1,303 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "glshaderarray.h"
|
||||
|
||||
const QString GLShaderArray::m_strVertexShaderSourceArray = QString(
|
||||
"uniform highp mat4 uMatrix;\n"
|
||||
"attribute highp vec4 vertex;\n"
|
||||
"attribute highp vec2 texCoord;\n"
|
||||
"varying mediump vec2 texCoordVar;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = uMatrix * vertex;\n"
|
||||
" texCoordVar = texCoord;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
const QString GLShaderArray::m_strFragmentShaderSourceColored = QString(
|
||||
"uniform lowp sampler2D uTexture;\n"
|
||||
"varying mediump vec2 texCoordVar;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = texture2D(uTexture, texCoordVar);\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
GLShaderArray::GLShaderArray()
|
||||
{
|
||||
m_objProgram=NULL;
|
||||
m_objImage = NULL;
|
||||
m_objTexture = NULL;
|
||||
m_intCols=0;
|
||||
m_intRows=0;
|
||||
m_blnInitialized=false;
|
||||
m_objCurrentRow=NULL;
|
||||
}
|
||||
|
||||
GLShaderArray::~GLShaderArray()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void GLShaderArray::InitializeGL(int intCols, int intRows)
|
||||
{
|
||||
QMatrix4x4 objQMatrix;
|
||||
|
||||
m_blnInitialized=false;
|
||||
|
||||
m_intCols=0;
|
||||
m_intRows=0;
|
||||
|
||||
m_objCurrentRow=NULL;
|
||||
|
||||
if(m_objProgram==NULL)
|
||||
{
|
||||
m_objProgram = new QOpenGLShaderProgram();
|
||||
|
||||
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, m_strVertexShaderSourceArray))
|
||||
{
|
||||
qDebug() << "GLShaderArray::initializeGL: error in vertex shader: " << m_objProgram->log();
|
||||
}
|
||||
|
||||
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, m_strFragmentShaderSourceColored))
|
||||
{
|
||||
qDebug() << "GLShaderArray::initializeGL: error in fragment shader: " << m_objProgram->log();
|
||||
}
|
||||
|
||||
m_objProgram->bindAttributeLocation("vertex", 0);
|
||||
|
||||
if (!m_objProgram->link())
|
||||
{
|
||||
qDebug() << "GLShaderArray::initializeGL: error linking shader: " << m_objProgram->log();
|
||||
}
|
||||
|
||||
m_objProgram->bind();
|
||||
m_objProgram->setUniformValue(m_objMatrixLoc, objQMatrix);
|
||||
m_objProgram->setUniformValue(m_objTextureLoc, 0);
|
||||
m_objProgram->release();
|
||||
}
|
||||
|
||||
m_objMatrixLoc = m_objProgram->uniformLocation("uMatrix");
|
||||
m_objTextureLoc = m_objProgram->uniformLocation("uTexture");
|
||||
m_objColorLoc = m_objProgram->uniformLocation("uColour");
|
||||
|
||||
if(m_objTexture!=NULL)
|
||||
{
|
||||
delete m_objTexture;
|
||||
m_objTexture=NULL;
|
||||
}
|
||||
|
||||
//Image container
|
||||
m_objImage = new QImage(intCols,intRows,QImage::Format_RGBA8888);
|
||||
m_objImage->fill(QColor(0,0,0));
|
||||
|
||||
m_objTexture = new QOpenGLTexture(*m_objImage);
|
||||
m_objTexture->setMinificationFilter(QOpenGLTexture::Linear);
|
||||
m_objTexture->setMagnificationFilter(QOpenGLTexture::Linear);
|
||||
m_objTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||
|
||||
m_intCols = intCols;
|
||||
m_intRows = intRows;
|
||||
|
||||
m_blnInitialized=true;
|
||||
|
||||
}
|
||||
|
||||
QRgb * GLShaderArray::GetRowBuffer(int intRow)
|
||||
{
|
||||
if(m_blnInitialized==false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(m_objImage==NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(intRow>m_intRows)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (QRgb *)m_objImage->scanLine(intRow);
|
||||
}
|
||||
|
||||
|
||||
void GLShaderArray::RenderPixels(unsigned char *chrData)
|
||||
{
|
||||
QOpenGLFunctions *ptrF;
|
||||
int intI;
|
||||
int intJ;
|
||||
int intNbVertices=4;
|
||||
|
||||
QMatrix4x4 objQMatrix;
|
||||
|
||||
GLfloat arrVertices[] =
|
||||
{
|
||||
-1.0f, -1.0f,
|
||||
-1.0f, 1.0f,
|
||||
1.0f, 1.0f,
|
||||
1.0f, -1.0f
|
||||
};
|
||||
|
||||
GLfloat arrTextureCoords[] =
|
||||
{
|
||||
0.0f, 1.0f,
|
||||
0.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
1.0f, 1.0f
|
||||
};
|
||||
|
||||
QRgb *ptrLine;
|
||||
int intVal;
|
||||
|
||||
if(m_blnInitialized==false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_objImage==NULL)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
if(chrData!=NULL)
|
||||
{
|
||||
for(intJ=0; intJ<m_intRows; intJ++)
|
||||
{
|
||||
ptrLine = (QRgb *)m_objImage->scanLine(intJ);
|
||||
|
||||
for(intI=0; intI<m_intCols; intI ++)
|
||||
{
|
||||
|
||||
intVal = (int)(*chrData);
|
||||
*ptrLine = qRgb(intVal,intVal,intVal);
|
||||
ptrLine ++;
|
||||
|
||||
chrData ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Affichage
|
||||
ptrF = QOpenGLContext::currentContext()->functions();
|
||||
|
||||
m_objProgram->bind();
|
||||
|
||||
m_objProgram->setUniformValue(m_objMatrixLoc, objQMatrix);
|
||||
m_objProgram->setUniformValue(m_objTextureLoc, 0);
|
||||
|
||||
m_objTexture->bind();
|
||||
|
||||
ptrF->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_intCols, m_intRows, GL_RGBA, GL_UNSIGNED_BYTE, m_objImage->bits());
|
||||
|
||||
ptrF->glEnableVertexAttribArray(0); // vertex
|
||||
ptrF->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, arrVertices);
|
||||
|
||||
ptrF->glEnableVertexAttribArray(1); // texture coordinates
|
||||
ptrF->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, arrTextureCoords);
|
||||
|
||||
ptrF->glDrawArrays(GL_POLYGON, 0, intNbVertices);
|
||||
|
||||
//cleanup
|
||||
ptrF->glDisableVertexAttribArray(0);
|
||||
ptrF->glDisableVertexAttribArray(1);
|
||||
|
||||
//*********************//
|
||||
|
||||
m_objTexture->release();
|
||||
m_objProgram->release();
|
||||
}
|
||||
|
||||
void GLShaderArray::ResetPixels()
|
||||
{
|
||||
if(m_objImage!=NULL)
|
||||
{
|
||||
m_objImage->fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
void GLShaderArray::Cleanup()
|
||||
{
|
||||
m_blnInitialized=false;
|
||||
|
||||
m_intCols=0;
|
||||
m_intRows=0;
|
||||
|
||||
m_objCurrentRow=NULL;
|
||||
|
||||
if (m_objProgram)
|
||||
{
|
||||
delete m_objProgram;
|
||||
m_objProgram = NULL;
|
||||
}
|
||||
|
||||
if(m_objTexture!=NULL)
|
||||
{
|
||||
delete m_objTexture;
|
||||
m_objTexture=NULL;
|
||||
}
|
||||
|
||||
if (m_objImage!=NULL)
|
||||
{
|
||||
delete m_objImage;
|
||||
m_objImage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool GLShaderArray::SelectRow(int intLine)
|
||||
{
|
||||
bool blnRslt=false;
|
||||
|
||||
if(m_blnInitialized)
|
||||
{
|
||||
if((intLine<m_intRows)
|
||||
&&(intLine>=0))
|
||||
{
|
||||
m_objCurrentRow=(QRgb *)m_objImage->scanLine(intLine);
|
||||
blnRslt=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_objCurrentRow=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return blnRslt;
|
||||
}
|
||||
|
||||
bool GLShaderArray::SetDataColor(int intCol,QRgb objColor)
|
||||
{
|
||||
bool blnRslt=false;
|
||||
|
||||
if(m_blnInitialized)
|
||||
{
|
||||
if((intCol<m_intCols)
|
||||
&&(intCol>=0)
|
||||
&&(m_objCurrentRow!=NULL))
|
||||
{
|
||||
m_objCurrentRow[intCol]=objColor;
|
||||
blnRslt=true;
|
||||
}
|
||||
}
|
||||
|
||||
return blnRslt;
|
||||
|
||||
}
|
||||
|
||||
|
76
plugins/channelrx/demodatv/glshaderarray.h
Normal file
76
plugins/channelrx/demodatv/glshaderarray.h
Normal file
@ -0,0 +1,76 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 F4HKW //
|
||||
// for F4EXB / SDRAngel //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// //
|
||||
// This program 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 General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_GUI_GLSHADERARRAY_H_
|
||||
#define INCLUDE_GUI_GLSHADERARRAY_H_
|
||||
|
||||
#include <QString>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLFunctions_2_0>
|
||||
#include <QOpenGLFunctions_2_1>
|
||||
#include <QOpenGLFunctions_3_0>
|
||||
#include <QOpenGLTexture>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLContext>
|
||||
#include <QMatrix4x4>
|
||||
#include <QVector4D>
|
||||
#include <QDebug>
|
||||
#include <QColor>
|
||||
#include <math.h>
|
||||
|
||||
class QOpenGLShaderProgram;
|
||||
class QMatrix4x4;
|
||||
class QVector4D;
|
||||
|
||||
class GLShaderArray
|
||||
{
|
||||
public:
|
||||
GLShaderArray();
|
||||
~GLShaderArray();
|
||||
|
||||
void InitializeGL(int intCols, int intRows);
|
||||
void ResizeContainer(int intCols, int intRows);
|
||||
void Cleanup();
|
||||
QRgb *GetRowBuffer(int intRow);
|
||||
void RenderPixels(unsigned char *chrData);
|
||||
void ResetPixels();
|
||||
|
||||
bool SelectRow(int intLine);
|
||||
bool SetDataColor(int intCol,QRgb objColor);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
QOpenGLShaderProgram *m_objProgram;
|
||||
int m_objMatrixLoc;
|
||||
int m_objTextureLoc;
|
||||
int m_objColorLoc;
|
||||
static const QString m_strVertexShaderSourceArray;
|
||||
static const QString m_strFragmentShaderSourceColored;
|
||||
|
||||
QImage *m_objImage=NULL;
|
||||
QOpenGLTexture *m_objTexture=NULL;
|
||||
|
||||
int m_intCols;
|
||||
int m_intRows;
|
||||
|
||||
QRgb * m_objCurrentRow;
|
||||
|
||||
bool m_blnInitialized;
|
||||
};
|
||||
|
||||
#endif /* INCLUDE_GUI_GLSHADERARRAY_H_ */
|
43
plugins/channelrx/demodatv/readme.md
Normal file
43
plugins/channelrx/demodatv/readme.md
Normal file
@ -0,0 +1,43 @@
|
||||
<h1>ATV demodulator plugin</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
This plugin can be used to view ATV.
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
![ATV Demodulator plugin GUI](../../../doc/img/ATVemod_plugin.png)
|
||||
|
||||
<h3>1: Frequency shift from center frequency of reception direction</h3>
|
||||
|
||||
The "+/-" button on the left side of the dial toggles between positive and negative shift.
|
||||
|
||||
<h3>2: Frequency shift from center frequency of reception value</h3>
|
||||
|
||||
Use the wheels to adjust the frequency shift in Hz from the center frequency of reception. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position.
|
||||
|
||||
<h3>3: Channel power</h3>
|
||||
|
||||
Average total power in dB relative to a +/- 1.0 amplitude signal received in the pass band.
|
||||
|
||||
<h3>4: Audio mute</h3>
|
||||
|
||||
Use this button to toggle audio mute for this channel. The button will light up in green if the squelch is open. This helps identifying which channels are active in a multi-channel configuration.
|
||||
|
||||
<h3>5: Level meter in dB</h3>
|
||||
|
||||
- top bar (green): average value
|
||||
- bottom bar (blue green): instantaneous peak value
|
||||
- tip vertical bar (bright green): peak hold value
|
||||
|
||||
<h3>6: RF bandwidth</h3>
|
||||
|
||||
This is the bandwidth in kHz of the channel signal before demodulation. It can be set continuously in 1 kHz steps from 1 to 40 kHz.
|
||||
|
||||
<h3>7: Volume</h3>
|
||||
|
||||
This is the volume of the audio signal from 0.0 (mute) to 10.0 (maximum). It can be varied continuously in 0.1 steps using the dial button.
|
||||
|
||||
<h3>8: Squelch threshold</h3>
|
||||
|
||||
This is the squelch threshold in dB. The average total power received in the signal bandwidth before demodulation is compared to this value and the squelch input is open above this value. It can be varied continuously in 0.1 dB steps from 0.0 to -100.0 dB using the dial button.
|
Loading…
Reference in New Issue
Block a user