2017-10-21 06:11:49 +01:00
|
|
|
#include "functiongencontrol.h"
|
|
|
|
#include "platformspecific.h"
|
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
namespace functionGen {
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
ChannelData const& SingleChannelController::getData() const {
|
|
|
|
return m_data;
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
void SingleChannelController::waveformName(QString newName)
|
2019-03-04 09:02:19 +00:00
|
|
|
{
|
2017-10-21 06:11:49 +01:00
|
|
|
qDebug() << "newName = " << newName;
|
|
|
|
newName.append(".tlw");
|
|
|
|
|
2019-03-07 08:58:52 +00:00
|
|
|
int length;
|
|
|
|
|
2017-10-21 06:11:49 +01:00
|
|
|
#ifdef PLATFORM_ANDROID
|
|
|
|
QString waveformFilePath("assets:/waveforms/");
|
|
|
|
waveformFilePath.append(newName);
|
|
|
|
|
|
|
|
QFile fptr(waveformFilePath);
|
|
|
|
bool success = fptr.open(QIODevice::ReadOnly);
|
|
|
|
|
|
|
|
QByteArray line;
|
|
|
|
char lengthString[16];
|
|
|
|
char divisibilityString[16];
|
|
|
|
|
|
|
|
line = fptr.readLine();
|
|
|
|
strcpy(lengthString, line.data());
|
2019-03-07 08:58:52 +00:00
|
|
|
sscanf(lengthString, "%d", &length);
|
2017-10-21 06:11:49 +01:00
|
|
|
qDebug() << "lengthString" << lengthString;
|
|
|
|
|
|
|
|
line = fptr.readLine();
|
|
|
|
strcpy(divisibilityString, line.data());
|
2019-03-25 23:12:08 +00:00
|
|
|
sscanf(divisibilityString, "%d", &m_data.divisibility);
|
2017-10-21 06:11:49 +01:00
|
|
|
qDebug() << "divisibilityString" << divisibilityString;
|
|
|
|
|
2019-03-07 08:58:52 +00:00
|
|
|
qDebug() << "Length = " << length;
|
2019-03-25 23:12:08 +00:00
|
|
|
qDebug() << "Divisibility = " << m_data.divisibility;
|
2017-10-21 06:11:49 +01:00
|
|
|
|
|
|
|
QByteArray remainingData = fptr.readAll();
|
|
|
|
char *dataString = remainingData.data();
|
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
m_data.samples.resize(length);
|
2017-10-21 06:11:49 +01:00
|
|
|
|
|
|
|
int dummy;
|
|
|
|
char *dataStringCurrent = dataString;
|
2019-03-07 08:58:52 +00:00
|
|
|
for (int i = 0; i < length; i++)
|
2019-03-04 09:02:19 +00:00
|
|
|
{
|
2017-10-21 06:11:49 +01:00
|
|
|
sscanf(dataStringCurrent, "%d", &dummy);
|
|
|
|
dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1;
|
2019-03-25 23:12:08 +00:00
|
|
|
m_data.samples[i] = static_cast<uint8_t>(dummy);
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
2019-03-04 09:02:19 +00:00
|
|
|
|
2017-10-21 06:11:49 +01:00
|
|
|
#else
|
|
|
|
|
2019-03-04 09:02:19 +00:00
|
|
|
QByteArray filePath = QCoreApplication::applicationDirPath()
|
2019-03-07 08:58:52 +00:00
|
|
|
.append("/waveforms/").append(newName).toLocal8Bit();
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-04 09:02:19 +00:00
|
|
|
qDebug() << "opening" << filePath;
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-04 09:02:19 +00:00
|
|
|
FILE *fptr = fopen(filePath.constData(), "r");
|
|
|
|
if (fptr == NULL)
|
|
|
|
qFatal("%s could not be opened!", filePath.constData());
|
|
|
|
|
|
|
|
char lengthString[16];
|
2017-10-21 06:11:49 +01:00
|
|
|
fgets(lengthString, 5, fptr);
|
2019-03-07 08:58:52 +00:00
|
|
|
sscanf(lengthString, "%d", &length);
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-04 09:02:19 +00:00
|
|
|
char divisibilityString[16];
|
2017-10-21 06:11:49 +01:00
|
|
|
//Bit of bullshit to deal with CRLF line endings on Mac.
|
2019-03-04 09:02:19 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
fgets(divisibilityString, 5, fptr);
|
|
|
|
}
|
|
|
|
while ((divisibilityString[0] == '\r') || (divisibilityString[0] == '\n'));
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
sscanf(divisibilityString, "%d", &m_data.divisibility);
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-07 08:58:52 +00:00
|
|
|
qDebug() << "Length = " << length;
|
2019-03-25 23:12:08 +00:00
|
|
|
qDebug() << "Divisibility = " << m_data.divisibility;
|
2017-10-21 06:11:49 +01:00
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
m_data.samples.resize(length);
|
2019-03-04 09:02:19 +00:00
|
|
|
|
2019-03-07 08:58:52 +00:00
|
|
|
char *dataString = (char *) malloc(length*5+1);
|
|
|
|
fgets(dataString, length*5+1, fptr);
|
2017-10-21 06:11:49 +01:00
|
|
|
|
|
|
|
int dummy;
|
|
|
|
char *dataStringCurrent = dataString;
|
2019-03-07 08:58:52 +00:00
|
|
|
for (int i = 0; i < length; i++)
|
2019-03-04 09:02:19 +00:00
|
|
|
{
|
2017-10-21 06:11:49 +01:00
|
|
|
sscanf(dataStringCurrent, "%d", &dummy);
|
|
|
|
dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1;
|
2019-03-25 23:12:08 +00:00
|
|
|
m_data.samples[i] = static_cast<uint8_t>(dummy);
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
free(dataString);
|
|
|
|
fclose(fptr);
|
|
|
|
#endif
|
2019-03-04 09:02:19 +00:00
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
double newMaxFreq = DAC_SPS / (length >> (m_data.divisibility - 1));
|
2019-03-07 09:00:40 +00:00
|
|
|
double newMinFreq = double(CLOCK_FREQ) / 1024.0 / 65535.0 / static_cast<double>(length);
|
2019-03-04 09:02:19 +00:00
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
setMaxFreq(newMaxFreq);
|
|
|
|
setMinFreq(newMinFreq);
|
|
|
|
|
|
|
|
notifyUpdate(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SingleChannelController::freqUpdate(double newFreq)
|
|
|
|
{
|
|
|
|
qDebug() << "newFreq = " << newFreq;
|
|
|
|
m_data.freq = newFreq;
|
|
|
|
notifyUpdate(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SingleChannelController::amplitudeUpdate(double newAmplitude)
|
|
|
|
{
|
|
|
|
qDebug() << "newAmplitude = " << newAmplitude;
|
|
|
|
m_data.amplitude = newAmplitude;
|
|
|
|
notifyUpdate(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SingleChannelController::offsetUpdate(double newOffset)
|
|
|
|
{
|
|
|
|
qDebug() << "newOffset = " << newOffset;
|
|
|
|
m_data.offset = newOffset;
|
|
|
|
notifyUpdate(this);
|
|
|
|
}
|
|
|
|
|
2019-03-04 09:02:19 +00:00
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
DualChannelController::DualChannelController(QWidget *parent) : QLabel(parent)
|
|
|
|
{
|
|
|
|
// A bunch of plumbing to forward the SingleChannelController's signals
|
|
|
|
|
|
|
|
SingleChannelController* controller1 = getChannelController(ChannelID::CH1);
|
|
|
|
SingleChannelController* controller2 = getChannelController(ChannelID::CH2);
|
|
|
|
|
|
|
|
connect(controller1, &SingleChannelController::notifyUpdate,
|
|
|
|
this, [=](SingleChannelController* ptr){ this->functionGenToUpdate(ChannelID::CH1, ptr); });
|
|
|
|
|
|
|
|
connect(controller1, &SingleChannelController::setMaxFreq,
|
|
|
|
this, &DualChannelController::setMaxFreq_CH1);
|
|
|
|
|
|
|
|
connect(controller1, &SingleChannelController::setMinFreq,
|
|
|
|
this, &DualChannelController::setMinFreq_CH1);
|
|
|
|
|
|
|
|
|
|
|
|
connect(controller2, &SingleChannelController::notifyUpdate,
|
|
|
|
this, [=](SingleChannelController* ptr){ this->functionGenToUpdate(ChannelID::CH2, ptr); });
|
|
|
|
|
|
|
|
connect(controller1, &SingleChannelController::setMaxFreq,
|
|
|
|
this, &DualChannelController::setMaxFreq_CH2);
|
|
|
|
|
|
|
|
connect(controller1, &SingleChannelController::setMinFreq,
|
|
|
|
this, &DualChannelController::setMinFreq_CH2);
|
|
|
|
|
|
|
|
this->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SingleChannelController* DualChannelController::getChannelController(ChannelID channelID)
|
|
|
|
{
|
|
|
|
return &m_channels[(int)channelID];
|
|
|
|
}
|
|
|
|
|
|
|
|
// The rest of this file is just plumbing to forward slot calls to SingleChannelController's
|
|
|
|
// Hopefuly it can be mostly removed eventually
|
|
|
|
void DualChannelController::waveformName(ChannelID channelID, QString newName)
|
|
|
|
{
|
|
|
|
getChannelController(channelID)->waveformName(newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::freqUpdate(ChannelID channelID, double newFreq)
|
|
|
|
{
|
|
|
|
getChannelController(channelID)->freqUpdate(newFreq);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::amplitudeUpdate(ChannelID channelID, double newAmplitude)
|
|
|
|
{
|
|
|
|
getChannelController(channelID)->amplitudeUpdate(newAmplitude);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::offsetUpdate(ChannelID channelID, double newOffset)
|
|
|
|
{
|
|
|
|
getChannelController(channelID)->offsetUpdate(newOffset);
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
|
|
|
|
void DualChannelController::waveformName_CH1(QString newName)
|
|
|
|
{
|
|
|
|
waveformName(ChannelID::CH1, newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::freqUpdate_CH1(double newFreq)
|
|
|
|
{
|
|
|
|
freqUpdate(ChannelID::CH1, newFreq);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::amplitudeUpdate_CH1(double newAmplitude)
|
2019-03-04 09:02:19 +00:00
|
|
|
{
|
2019-03-25 23:12:08 +00:00
|
|
|
amplitudeUpdate(ChannelID::CH1, newAmplitude);
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
void DualChannelController::offsetUpdate_CH1(double newOffset)
|
2019-03-04 09:02:19 +00:00
|
|
|
{
|
2019-03-25 23:12:08 +00:00
|
|
|
offsetUpdate(ChannelID::CH1, newOffset);
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-25 23:12:08 +00:00
|
|
|
|
|
|
|
void DualChannelController::waveformName_CH2(QString newName)
|
2019-03-04 09:02:19 +00:00
|
|
|
{
|
2019-03-25 23:12:08 +00:00
|
|
|
waveformName(ChannelID::CH2, newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::freqUpdate_CH2(double newFreq)
|
|
|
|
{
|
|
|
|
freqUpdate(ChannelID::CH2, newFreq);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::amplitudeUpdate_CH2(double newAmplitude)
|
|
|
|
{
|
|
|
|
amplitudeUpdate(ChannelID::CH2, newAmplitude);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DualChannelController::offsetUpdate_CH2(double newOffset)
|
|
|
|
{
|
|
|
|
offsetUpdate(ChannelID::CH2, newOffset);
|
|
|
|
}
|
|
|
|
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
2019-03-04 09:02:19 +00:00
|
|
|
|