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:
Sebastián Mestre 2019-03-07 05:58:52 -03:00 committed by Chris Esposito
parent a144105b23
commit c149063452
5 changed files with 89 additions and 75 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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){

View File

@ -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);

View File

@ -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;