mirror of https://github.com/EspoTek/Labrador.git
Functiongencontrol refactor - part 2 (#69)
* use an enum instead of int to identify function generator channels * Use local 8 bit encoding instead of utf8 for file paths * use static_cast instead of function-style casts * remove length member from channelData struct. use reference captures on some lambdas
This commit is contained in:
parent
a144105b23
commit
c149063452
|
@ -9,53 +9,60 @@ functionGenControl::functionGenControl(QWidget *parent) : QLabel(parent)
|
|||
|
||||
void functionGenControl::waveformName_CH1(QString newName)
|
||||
{
|
||||
waveformName(newName, 0);
|
||||
waveformName(ChannelID::CH1, newName);
|
||||
}
|
||||
|
||||
void functionGenControl::freqUpdate_CH1(double newFreq)
|
||||
{
|
||||
freqUpdate(newFreq, 0);
|
||||
freqUpdate(ChannelID::CH1, newFreq);
|
||||
}
|
||||
|
||||
void functionGenControl::amplitudeUpdate_CH1(double newAmplitude)
|
||||
{
|
||||
amplitudeUpdate(newAmplitude, 0);
|
||||
amplitudeUpdate(ChannelID::CH1, newAmplitude);
|
||||
}
|
||||
|
||||
void functionGenControl::offsetUpdate_CH1(double newOffset)
|
||||
{
|
||||
offsetUpdate(newOffset, 0);
|
||||
offsetUpdate(ChannelID::CH1, newOffset);
|
||||
}
|
||||
|
||||
|
||||
void functionGenControl::waveformName_CH2(QString newName)
|
||||
{
|
||||
waveformName(newName, 1);
|
||||
waveformName(ChannelID::CH2, newName);
|
||||
}
|
||||
|
||||
void functionGenControl::freqUpdate_CH2(double newFreq)
|
||||
{
|
||||
freqUpdate(newFreq, 1);
|
||||
freqUpdate(ChannelID::CH2, newFreq);
|
||||
}
|
||||
|
||||
void functionGenControl::amplitudeUpdate_CH2(double newAmplitude)
|
||||
{
|
||||
amplitudeUpdate(newAmplitude, 1);
|
||||
amplitudeUpdate(ChannelID::CH2, newAmplitude);
|
||||
}
|
||||
|
||||
void functionGenControl::offsetUpdate_CH2(double newOffset)
|
||||
{
|
||||
offsetUpdate(newOffset, 1);
|
||||
offsetUpdate(ChannelID::CH2, newOffset);
|
||||
}
|
||||
|
||||
|
||||
void functionGenControl::waveformName(QString newName, int channelID)
|
||||
functionGenControl::ChannelData& functionGenControl::getChannelData(ChannelID channelID)
|
||||
{
|
||||
ChannelData& channel = channels[channelID];
|
||||
return channels[static_cast<int>(channelID)];
|
||||
}
|
||||
|
||||
void functionGenControl::waveformName(ChannelID channelID, QString newName)
|
||||
{
|
||||
ChannelData& channel = getChannelData(channelID);
|
||||
|
||||
qDebug() << "newName = " << newName;
|
||||
newName.append(".tlw");
|
||||
|
||||
int length;
|
||||
|
||||
#ifdef PLATFORM_ANDROID
|
||||
QString waveformFilePath("assets:/waveforms/");
|
||||
waveformFilePath.append(newName);
|
||||
|
@ -69,7 +76,7 @@ void functionGenControl::waveformName(QString newName, int channelID)
|
|||
|
||||
line = fptr.readLine();
|
||||
strcpy(lengthString, line.data());
|
||||
sscanf(lengthString, "%d", &channel.length);
|
||||
sscanf(lengthString, "%d", &length);
|
||||
qDebug() << "lengthString" << lengthString;
|
||||
|
||||
line = fptr.readLine();
|
||||
|
@ -77,27 +84,27 @@ void functionGenControl::waveformName(QString newName, int channelID)
|
|||
sscanf(divisibilityString, "%d", &channel.divisibility);
|
||||
qDebug() << "divisibilityString" << divisibilityString;
|
||||
|
||||
qDebug() << "Length = " << channel.length;
|
||||
qDebug() << "Length = " << length;
|
||||
qDebug() << "Divisibility = " << channel.divisibility;
|
||||
|
||||
QByteArray remainingData = fptr.readAll();
|
||||
char *dataString = remainingData.data();
|
||||
|
||||
channel.samples.resize(channel.length);
|
||||
channel.samples.resize(length);
|
||||
|
||||
int dummy;
|
||||
char *dataStringCurrent = dataString;
|
||||
for (int i = 0; i < channel.length; i++)
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
sscanf(dataStringCurrent, "%d", &dummy);
|
||||
dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1;
|
||||
channel.samples[i] = uint8_t(dummy);
|
||||
channel.samples[i] = static_cast<uint8_t>(dummy);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
QByteArray filePath = QCoreApplication::applicationDirPath()
|
||||
.append("/waveforms/").append(newName).toUtf8();
|
||||
.append("/waveforms/").append(newName).toLocal8Bit();
|
||||
|
||||
qDebug() << "opening" << filePath;
|
||||
|
||||
|
@ -107,7 +114,7 @@ void functionGenControl::waveformName(QString newName, int channelID)
|
|||
|
||||
char lengthString[16];
|
||||
fgets(lengthString, 5, fptr);
|
||||
sscanf(lengthString, "%d", &channel.length);
|
||||
sscanf(lengthString, "%d", &length);
|
||||
|
||||
char divisibilityString[16];
|
||||
//Bit of bullshit to deal with CRLF line endings on Mac.
|
||||
|
@ -119,67 +126,68 @@ void functionGenControl::waveformName(QString newName, int channelID)
|
|||
|
||||
sscanf(divisibilityString, "%d", &channel.divisibility);
|
||||
|
||||
qDebug() << "Length = " << channel.length;
|
||||
qDebug() << "Length = " << length;
|
||||
qDebug() << "Divisibility = " << channel.divisibility;
|
||||
|
||||
channel.samples.resize(channel.length);
|
||||
channel.samples.resize(length);
|
||||
|
||||
char *dataString = (char *) malloc(channel.length*5+1);
|
||||
fgets(dataString, channel.length*5+1, fptr);
|
||||
char *dataString = (char *) malloc(length*5+1);
|
||||
fgets(dataString, length*5+1, fptr);
|
||||
|
||||
int dummy;
|
||||
char *dataStringCurrent = dataString;
|
||||
for (int i = 0; i < channel.length; i++)
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
sscanf(dataStringCurrent, "%d", &dummy);
|
||||
dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1;
|
||||
channel.samples[i] = uint8_t(dummy);
|
||||
channel.samples[i] = static_cast<uint8_t>(dummy);
|
||||
}
|
||||
|
||||
free(dataString);
|
||||
fclose(fptr);
|
||||
#endif
|
||||
|
||||
double newMaxFreq = DAC_SPS / (channel.length >> (channel.divisibility - 1));
|
||||
double newMinFreq = double(CLOCK_FREQ) / 1024.0 / 65535.0 / channel.length;
|
||||
double newMaxFreq = DAC_SPS / (length >> (channel.divisibility - 1));
|
||||
double newMinFreq = double(CLOCK_FREQ) / 1024.0 / 65535.0 / length;
|
||||
|
||||
// NOTE: Not very clean... Not sure what to do about it.
|
||||
// I guess the "right thing" would be to have a Channel QObject class with its
|
||||
// own signals and slots, or have a single setMaxFreq signal with channelID as
|
||||
// an argument. Either solution would require changes in other places in the
|
||||
// codebase so this will have to do for now.
|
||||
if (channelID == 0)
|
||||
switch (channelID)
|
||||
{
|
||||
setMaxFreq_CH1(newMaxFreq);
|
||||
setMinFreq_CH1(newMinFreq);
|
||||
}
|
||||
else
|
||||
{
|
||||
setMaxFreq_CH2(newMaxFreq);
|
||||
setMinFreq_CH2(newMinFreq);
|
||||
case ChannelID::CH1:
|
||||
setMaxFreq_CH1(newMaxFreq);
|
||||
setMinFreq_CH1(newMinFreq);
|
||||
break;
|
||||
case ChannelID::CH2:
|
||||
setMaxFreq_CH2(newMaxFreq);
|
||||
setMinFreq_CH2(newMinFreq);
|
||||
break;
|
||||
}
|
||||
|
||||
functionGenToUpdate(channelID, this);
|
||||
}
|
||||
|
||||
void functionGenControl::freqUpdate(double newFreq, int channelID)
|
||||
void functionGenControl::freqUpdate(ChannelID channelID, double newFreq)
|
||||
{
|
||||
qDebug() << "newFreq" << channelID << " = " << newFreq;
|
||||
channels[channelID].freq = newFreq;
|
||||
qDebug() << "newFreq" << int(channelID) << " = " << newFreq;
|
||||
getChannelData(channelID).freq = newFreq;
|
||||
functionGenToUpdate(channelID, this);
|
||||
}
|
||||
|
||||
void functionGenControl::amplitudeUpdate(double newAmplitude, int channelID)
|
||||
void functionGenControl::amplitudeUpdate(ChannelID channelID, double newAmplitude)
|
||||
{
|
||||
qDebug() << "newAmplitude" << channelID << " = " << newAmplitude;
|
||||
channels[channelID].amplitude = newAmplitude;
|
||||
qDebug() << "newAmplitude" << int(channelID) << " = " << newAmplitude;
|
||||
getChannelData(channelID).amplitude = newAmplitude;
|
||||
functionGenToUpdate(channelID, this);
|
||||
}
|
||||
|
||||
void functionGenControl::offsetUpdate(double newOffset, int channelID)
|
||||
void functionGenControl::offsetUpdate(ChannelID channelID, double newOffset)
|
||||
{
|
||||
qDebug() << "newOffset" << channelID << " = " << newOffset;
|
||||
channels[channelID].offset = newOffset;
|
||||
qDebug() << "newOffset" << int(channelID) << " = " << newOffset;
|
||||
getChannelData(channelID).offset = newOffset;
|
||||
functionGenToUpdate(channelID, this);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,37 +17,42 @@ class functionGenControl : public QLabel
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
struct ChannelData
|
||||
{
|
||||
std::vector<uint8_t> samples;
|
||||
// TODO: get rid of length member. samples:std::vector already has this information
|
||||
int length;
|
||||
int divisibility;
|
||||
double freq = 1000.0;
|
||||
double amplitude = 0.0;
|
||||
double offset = 0.0;
|
||||
};
|
||||
|
||||
enum class ChannelID
|
||||
{
|
||||
CH1 = 0,
|
||||
CH2 = 1
|
||||
};
|
||||
|
||||
explicit functionGenControl(QWidget *parent = 0);
|
||||
|
||||
ChannelData channels[2];
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
// NOTE: An enum instead of a plain int would probably be better here
|
||||
void waveformName(QString newName, int channelID);
|
||||
void freqUpdate(double newFreq, int channelID);
|
||||
void amplitudeUpdate(double newAmplitude, int channelID);
|
||||
void offsetUpdate(double newOffset, int channelID);
|
||||
ChannelData& getChannelData(ChannelID channelID);
|
||||
|
||||
signals:
|
||||
void functionGenToUpdate(int channel, functionGenControl *fGenControl);
|
||||
void functionGenToUpdate(ChannelID channel, functionGenControl *fGenControl);
|
||||
void setMaxFreq_CH1(double maxFreq);
|
||||
void setMinFreq_CH1(double minFreq);
|
||||
void setMaxFreq_CH2(double maxFreq);
|
||||
void setMinFreq_CH2(double minFreq);
|
||||
|
||||
public slots:
|
||||
void waveformName(ChannelID channelId, QString newName);
|
||||
void freqUpdate(ChannelID channelId, double newFreq);
|
||||
void amplitudeUpdate(ChannelID channelId, double newAmplitude);
|
||||
void offsetUpdate(ChannelID channelId, double newOffset);
|
||||
|
||||
void waveformName_CH1(QString newName);
|
||||
void freqUpdate_CH1(double newFreq);
|
||||
void amplitudeUpdate_CH1(double newAmplitude);
|
||||
|
|
|
@ -75,8 +75,9 @@ void genericUsbDriver::setPsu(double voltage){
|
|||
qDebug() << "Going to send value " << dutyPsu;
|
||||
}
|
||||
|
||||
void genericUsbDriver::setFunctionGen(int channelID, functionGenControl *fGenControl)
|
||||
void genericUsbDriver::setFunctionGen(functionGenControl::ChannelID channelID, functionGenControl *fGenControl)
|
||||
{
|
||||
using ChannelID = functionGenControl::ChannelID;
|
||||
////////////////////////////
|
||||
////NO RESIZING (YET)!!!////
|
||||
////////////////////////////
|
||||
|
@ -86,24 +87,24 @@ void genericUsbDriver::setFunctionGen(int channelID, functionGenControl *fGenCon
|
|||
//////////////////////////////////////
|
||||
|
||||
//For recalling on crash.
|
||||
if (channelID == 0)
|
||||
if (channelID == ChannelID::CH1)
|
||||
fGenPtr_CH1 = fGenControl;
|
||||
else
|
||||
fGenPtr_CH2 = fGenControl;
|
||||
|
||||
//Reading in data
|
||||
functionGenControl::ChannelData channelData = fGenControl->channels[channelID];
|
||||
functionGenControl::ChannelData channelData = fGenControl->getChannelData(channelID);
|
||||
|
||||
//Triple mode
|
||||
if ((channelData.amplitude + channelData.offset) > FGEN_LIMIT)
|
||||
{
|
||||
channelData.amplitude /= 3.0;
|
||||
channelData.offset /= 3.0;
|
||||
fGenTriple |= uint8_t(!channelID + 1);
|
||||
fGenTriple |= static_cast<uint8_t>(!static_cast<uint8_t>(channelID) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fGenTriple &= uint8_t(254 - !channelID);
|
||||
fGenTriple &= static_cast<uint8_t>(254 - !static_cast<uint8_t>(channelID));
|
||||
}
|
||||
|
||||
//Waveform scaling in V
|
||||
|
@ -127,7 +128,7 @@ void genericUsbDriver::setFunctionGen(int channelID, functionGenControl *fGenCon
|
|||
usbSendControl(0x40, 0xa4, fGenTriple, 0, 0, NULL);
|
||||
#endif
|
||||
|
||||
auto applyAmplitudeAndOffset = [=](unsigned char sample) -> unsigned char
|
||||
auto applyAmplitudeAndOffset = [&](unsigned char sample) -> unsigned char
|
||||
{
|
||||
return sample / 255.0 * channelData.amplitude + channelData.offset;
|
||||
};
|
||||
|
@ -139,19 +140,20 @@ void genericUsbDriver::setFunctionGen(int channelID, functionGenControl *fGenCon
|
|||
//Need to increase size of wave if its freq too high, or too low!
|
||||
{
|
||||
int shift = 0;
|
||||
int newLength = channelData.samples.size();
|
||||
|
||||
while ((channelData.length >> shift) * channelData.freq > DAC_SPS)
|
||||
while ((newLength >> shift) * channelData.freq > DAC_SPS)
|
||||
shift++;
|
||||
|
||||
if (shift != 0)
|
||||
{
|
||||
channelData.divisibility -= shift;
|
||||
channelData.length >>= shift;
|
||||
newLength >>= shift;
|
||||
|
||||
for (int i = 0; i < channelData.length; ++i)
|
||||
for (int i = 0; i < newLength; ++i)
|
||||
channelData.samples[i] = channelData.samples[i << shift];
|
||||
|
||||
channelData.samples.resize(channelData.length);
|
||||
channelData.samples.resize(newLength);
|
||||
channelData.samples.shrink_to_fit();
|
||||
|
||||
if (channelData.divisibility <= 0)
|
||||
|
@ -161,9 +163,9 @@ void genericUsbDriver::setFunctionGen(int channelID, functionGenControl *fGenCon
|
|||
|
||||
// Timer Setup
|
||||
int validClockDivs[7] = {1, 2, 4, 8, 64, 256, 1024};
|
||||
auto period = [=](int division) -> int
|
||||
auto period = [&](int division) -> int
|
||||
{
|
||||
return CLOCK_FREQ / (division * channelData.length * channelData.freq);
|
||||
return CLOCK_FREQ / (division * channelData.samples.size() * channelData.freq);
|
||||
};
|
||||
|
||||
int* clkSettingIt = std::find_if(std::begin(validClockDivs), std::end(validClockDivs),
|
||||
|
@ -178,11 +180,10 @@ void genericUsbDriver::setFunctionGen(int channelID, functionGenControl *fGenCon
|
|||
qDebug("DEVICE IS IN MODE 5");
|
||||
|
||||
|
||||
|
||||
if (channelID)
|
||||
usbSendControl(0x40, 0xa1, timerPeriod, clkSetting, channelData.length, channelData.samples.data());
|
||||
if (channelID == ChannelID::CH2)
|
||||
usbSendControl(0x40, 0xa1, timerPeriod, clkSetting, channelData.samples.size(), channelData.samples.data());
|
||||
else
|
||||
usbSendControl(0x40, 0xa2, timerPeriod, clkSetting, channelData.length, channelData.samples.data());
|
||||
usbSendControl(0x40, 0xa2, timerPeriod, clkSetting, channelData.samples.size(), channelData.samples.data());
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -204,8 +205,8 @@ void genericUsbDriver::setDeviceMode(int mode){
|
|||
deviceMode = mode;
|
||||
usbSendControl(0x40, 0xa5, (mode == 5 ? 0 : mode), gainMask, 0, NULL);
|
||||
|
||||
if (fGenPtr_CH1!=NULL) setFunctionGen(0, fGenPtr_CH1);
|
||||
if (fGenPtr_CH2!=NULL) setFunctionGen(1, fGenPtr_CH2);
|
||||
if (fGenPtr_CH1 != NULL) setFunctionGen(functionGenControl::ChannelID::CH1, fGenPtr_CH1);
|
||||
if (fGenPtr_CH2 != NULL) setFunctionGen(functionGenControl::ChannelID::CH2, fGenPtr_CH2);
|
||||
|
||||
//switch on new deviceMode!!
|
||||
switch(deviceMode){
|
||||
|
|
|
@ -115,7 +115,7 @@ signals:
|
|||
void calibrateMe(void);
|
||||
public slots:
|
||||
void setPsu(double voltage);
|
||||
void setFunctionGen(int channel, functionGenControl *fGenControl);
|
||||
void setFunctionGen(functionGenControl::ChannelID channel, functionGenControl *fGenControl);
|
||||
void setDeviceMode(int mode);
|
||||
void newDig(int digState);
|
||||
void psuTick(void);
|
||||
|
|
|
@ -127,7 +127,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
connect(ui->debugButton1, SIGNAL(clicked()), ui->controller_iso->driver, SLOT(avrDebug()));
|
||||
connect(ui->psuSlider, SIGNAL(voltageChanged(double)), ui->controller_iso->driver, SLOT(setPsu(double)));
|
||||
connect(ui->controller_iso, SIGNAL(setGain(double)), ui->controller_iso->driver, SLOT(setGain(double)));
|
||||
connect(ui->controller_fg, SIGNAL(functionGenToUpdate(int,functionGenControl*)), ui->controller_iso->driver, SLOT(setFunctionGen(int,functionGenControl*)));
|
||||
connect(ui->controller_fg, &functionGenControl::functionGenToUpdate, ui->controller_iso->driver, &genericUsbDriver::setFunctionGen);
|
||||
connect(ui->bufferDisplay, SIGNAL(modeChange(int)), ui->controller_iso->driver, SLOT(setDeviceMode(int)));
|
||||
connect(ui->bufferDisplay, SIGNAL(updateDig(int)), ui->controller_iso->driver, SLOT(newDig(int)));
|
||||
|
||||
|
@ -1334,7 +1334,7 @@ void MainWindow::reinitUsbStage2(void){
|
|||
connect(ui->debugButton3, SIGNAL(clicked()), ui->controller_iso->driver, SLOT(bootloaderJump()));
|
||||
connect(ui->psuSlider, SIGNAL(voltageChanged(double)), ui->controller_iso->driver, SLOT(setPsu(double)));
|
||||
connect(ui->controller_iso, SIGNAL(setGain(double)), ui->controller_iso->driver, SLOT(setGain(double)));
|
||||
connect(ui->controller_fg, SIGNAL(functionGenToUpdate(int,functionGenControl*)), ui->controller_iso->driver, SLOT(setFunctionGen(int,functionGenControl*)));
|
||||
connect(ui->controller_fg, &functionGenControl::functionGenToUpdate, ui->controller_iso->driver, &genericUsbDriver::setFunctionGen);
|
||||
connect(ui->bufferDisplay, SIGNAL(modeChange(int)), ui->controller_iso->driver, SLOT(setDeviceMode(int)));
|
||||
connect(ui->bufferDisplay, SIGNAL(updateDig(int)), ui->controller_iso->driver, SLOT(newDig(int)));
|
||||
|
||||
|
@ -1368,8 +1368,8 @@ void MainWindow::resetUsbState(void){
|
|||
ui->psuSlider->poke();
|
||||
//ui->controller_iso->driver->newDig(digitalPinState);
|
||||
ui->bufferDisplay->poke();
|
||||
ui->controller_iso->driver->setFunctionGen(0,ui->controller_fg);
|
||||
ui->controller_iso->driver->setFunctionGen(1,ui->controller_fg);
|
||||
ui->controller_iso->driver->setFunctionGen(functionGenControl::ChannelID::CH1, ui->controller_fg);
|
||||
ui->controller_iso->driver->setFunctionGen(functionGenControl::ChannelID::CH2, ui->controller_fg);
|
||||
|
||||
ui->controller_iso->clearBuffers(1,1,1);
|
||||
ui->controller_iso->doNotTouchGraph = false;
|
||||
|
|
Loading…
Reference in New Issue