mirror of https://github.com/EspoTek/Labrador.git
513 lines
15 KiB
C++
513 lines
15 KiB
C++
#include "winusbdriver.h"
|
|
|
|
winUsbDriver::winUsbDriver(QWidget *parent) : QLabel(parent)
|
|
{
|
|
qDebug() << "Making USB Driver invisible!!";
|
|
this->hide();
|
|
//Load stack so that reset signal can be sent
|
|
firstConnect = usbInit(0x03eb, 0xa000);
|
|
if(firstConnect){
|
|
setDeviceMode(deviceMode);
|
|
usbSendControl(0x40, 0xa7, 0, 0, 0, NULL);
|
|
//Stack will reinitialise TIMER_PERIOD seconds later, after first failed iso request
|
|
}
|
|
|
|
psuTimer = new QTimer();
|
|
psuTimer->setTimerType(Qt::PreciseTimer);
|
|
psuTimer->start(PSU_PERIOD);
|
|
connect(psuTimer, SIGNAL(timeout()), this, SLOT(psuTick()));
|
|
}
|
|
|
|
unsigned char winUsbDriver::usbInit(ULONG VIDin, ULONG PIDin){
|
|
unsigned char success;
|
|
|
|
//qDebug() << "usbInit() entered";
|
|
if (!LstK_Init(&deviceList, (KLST_FLAG) 0)) {
|
|
qDebug("Error initializing device list");
|
|
return 0;
|
|
} //else qDebug() << "Device List initialised!";
|
|
|
|
LstK_Count(deviceList, &deviceCount);
|
|
if (!deviceCount) {
|
|
qDebug("Device list empty");
|
|
LstK_Free(deviceList); // If LstK_Init returns TRUE, the list must be freed.
|
|
return 0;
|
|
} //else qDebug() << "Device Count initialised!";
|
|
|
|
//qDebug("Looking for device VID = %04X, PID = %04X\n", VIDin, PIDin);
|
|
|
|
LstK_FindByVidPid(deviceList, VIDin, PIDin, &deviceInfo);
|
|
LstK_Free(deviceList);
|
|
if (deviceInfo){
|
|
/*qDebug("Using %04X:%04X (%s): %s - %s\n",
|
|
deviceInfo->Common.Vid,
|
|
deviceInfo->Common.Pid,
|
|
deviceInfo->Common.InstanceID,
|
|
deviceInfo->DeviceDesc,
|
|
deviceInfo->Mfg);
|
|
Causes exceptions in debug mode!!!!*/
|
|
}
|
|
else {
|
|
qDebug("Could not find device VID = %04X, PID = %04X", VIDin, PIDin);
|
|
return 0;
|
|
}
|
|
|
|
success = UsbK_Init(&handle, deviceInfo);
|
|
if (!success){
|
|
ec = GetLastError();
|
|
qDebug("UsbK_Init failed. ErrorCode: %08Xh", ec);
|
|
} else qDebug("Device opened successfully!");
|
|
|
|
return success;
|
|
}
|
|
|
|
void winUsbDriver::usbSendControl(int RequestType, int Request, int Value, int Index, int Length, unsigned char *LDATA){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//IF YOU'RE SEEING AN ERROR, CHECK THAT REQUESTTYPE AND REQUEST ARE FORMATTED AS HEX
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
WINUSB_SETUP_PACKET setupPacket;
|
|
unsigned char controlSuccess;
|
|
UINT bytesTransferred = 0;
|
|
unsigned char *controlBuffer;
|
|
|
|
if (handle==NULL){
|
|
qDebug("Null handle error in usbSendControl");
|
|
return;
|
|
}
|
|
setupPacket.RequestType = (UCHAR) RequestType;
|
|
setupPacket.Request = (UCHAR) Request;
|
|
setupPacket.Value = (USHORT) Value;
|
|
setupPacket.Index = (USHORT) Index;
|
|
setupPacket.Length = (USHORT) Length;
|
|
|
|
//qDebug("RequestType = %x, Request = %x, Value = %u, Index = %u, Length = %u", setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, setupPacket.Length);
|
|
|
|
if (LDATA==NULL){
|
|
controlBuffer = (unsigned char *) malloc(256);
|
|
}
|
|
else controlBuffer = LDATA;
|
|
|
|
//qDebug() << controlBuffer;
|
|
//qDebug() << handle;
|
|
|
|
//qDebug("SENDING CONTROL PACKET\n");
|
|
controlSuccess = UsbK_ControlTransfer(handle, setupPacket, controlBuffer, setupPacket.Length, &bytesTransferred, NULL);
|
|
if (controlSuccess) {
|
|
qDebug("%d BYTES TRANSFERRED", bytesTransferred);
|
|
}
|
|
else qDebug("usbSendControl failed");
|
|
|
|
if(LDATA == NULL){
|
|
free(controlBuffer);
|
|
}
|
|
}
|
|
|
|
void winUsbDriver::setPsu(double voltage){
|
|
|
|
qDebug() << "New voltage =" << voltage;
|
|
currentPsuVoltage = voltage;
|
|
//if(deviceMode > 6) qFatal("setPsu is not configured for mode 7!!!");
|
|
double vinp = voltage/11;
|
|
double vinn = 0;
|
|
//double vref = 1.65;
|
|
double gainPsu = 1;
|
|
|
|
dutyPsu = (int) ((vinp - vinn)/vref * gainPsu * PSU_ADC_TOP);
|
|
|
|
qDebug() << "Going to send value " << dutyPsu;
|
|
}
|
|
|
|
void winUsbDriver::setFunctionGen(int channel, functionGenControl *fGenControl){
|
|
////////////////////////////
|
|
////NO RESIZING (YET)!!!////
|
|
////////////////////////////
|
|
|
|
//////////////////////////////////////
|
|
//// CH1 is AUX!! CH2 is "MAIN"!!////
|
|
//////////////////////////////////////
|
|
|
|
int length, maxLength, numDivides, maxDivides;
|
|
double freq, amplitude, offset;
|
|
unsigned char *samples;
|
|
|
|
//For recalling on crash.
|
|
fGenChannel = channel;
|
|
if (channel == 0) fGenPtr_CH1 = fGenControl;
|
|
else fGenPtr_CH2 = fGenControl;
|
|
|
|
//Reading in data
|
|
if (channel == 0){
|
|
length = fGenControl->length_CH1;
|
|
freq = fGenControl->freq_CH1;
|
|
amplitude = fGenControl->amplitude_CH1;
|
|
offset = fGenControl->offset_CH1;
|
|
samples = (unsigned char *) malloc(length);
|
|
memcpy(samples, fGenControl->samples_CH1, (unsigned int) length);
|
|
numDivides = fGenControl->divisibility_CH1;
|
|
}
|
|
else if(channel == 1){
|
|
length = fGenControl->length_CH2;
|
|
freq = fGenControl->freq_CH2;
|
|
amplitude = fGenControl->amplitude_CH2;
|
|
offset = fGenControl->offset_CH2;
|
|
samples = (unsigned char *) malloc(length);
|
|
memcpy(samples, fGenControl->samples_CH2, (unsigned int) length);
|
|
numDivides = fGenControl->divisibility_CH2;
|
|
}
|
|
|
|
//Triple mode
|
|
if ((amplitude+offset) > FGEN_LIMIT){
|
|
amplitude = amplitude / 3;
|
|
offset = offset / 3;
|
|
fGenTriple |= ((unsigned char) !channel + 1);
|
|
}
|
|
else fGenTriple &= ((unsigned char) (254 - !channel));
|
|
|
|
//qDebug() << "fGenTriple = " << fGenTriple << "fGenControl = " << fGenControl << "length = " << length << "freq = " << freq << "amplitude = " << amplitude << "offset = " << offset << "samples = " << samples;
|
|
|
|
//Waveform scaling in V
|
|
double tempDouble;
|
|
amplitude = (amplitude * 255) / FGEN_LIMIT;
|
|
offset = (offset * 255) / FGEN_LIMIT;
|
|
if (offset<FGEN_OFFSET){
|
|
if (amplitude>5)
|
|
amplitude -= FGEN_OFFSET;
|
|
else
|
|
amplitude = 0;
|
|
offset = FGEN_OFFSET;
|
|
}
|
|
|
|
#ifdef INVERT_TRIPLE
|
|
unsigned char fGenTemp = 0;
|
|
fGenTemp |= (fGenTriple & 0x01)<<1;
|
|
fGenTemp |= (fGenTriple & 0x02)>>1;
|
|
usbSendControl(0x40, 0xa4, fGenTemp, 0, 0, NULL);
|
|
#else
|
|
usbSendControl(0x40, 0xa4, fGenTriple, 0, 0, NULL);
|
|
#endif
|
|
|
|
//Applying amplitude and offset to all samples.
|
|
for (int i=0;i<length;i++){
|
|
tempDouble = (double) samples[i];
|
|
tempDouble *= amplitude;
|
|
tempDouble /= 255;
|
|
tempDouble += offset;
|
|
samples[i] = (unsigned char) tempDouble;
|
|
}
|
|
|
|
|
|
//Need to increase size of wave if its freq too high, or too low!
|
|
maxDivides = numDivides;
|
|
bool loop_entered = false;
|
|
unsigned char *tempSamples = (unsigned char *) malloc(0);
|
|
|
|
while(length * freq > DAC_SPS){
|
|
loop_entered = true;
|
|
numDivides--;
|
|
if (numDivides==0){
|
|
qDebug("numDivides = 0 - in T-stretching of winUsbDriver:: setFunctionGen");
|
|
}
|
|
|
|
int shiftTemp = (maxDivides - numDivides);
|
|
length = length >> 1;
|
|
|
|
free(tempSamples);
|
|
tempSamples = (unsigned char *) malloc(length);
|
|
for (int i=0; i<length;i++){
|
|
tempSamples[i] = samples[i<<shiftTemp];
|
|
}
|
|
}
|
|
if(loop_entered){
|
|
samples = tempSamples;
|
|
}
|
|
|
|
//Scaling in t here:
|
|
// Something something maxLength something
|
|
|
|
//Timer Setup
|
|
int validClockDivs[7] = {1, 2, 4, 8, 64, 256, 1024};
|
|
|
|
int clkSetting;
|
|
for(clkSetting = 0; clkSetting<7; clkSetting++){
|
|
if ( (CLOCK_FREQ / (length * validClockDivs[clkSetting] * freq)) < 65535 )
|
|
break;
|
|
}
|
|
int timerPeriod = CLOCK_FREQ / (length * freq * validClockDivs[clkSetting]);
|
|
|
|
clkSetting++; // Change from [0:n] to [1:n]
|
|
|
|
if(deviceMode == 5){
|
|
qDebug("DEVICE IS IN MODE 5");
|
|
}
|
|
|
|
//qDebug() << "First three samples:" << samples[0] << samples[1] << samples[2];
|
|
|
|
if(channel){
|
|
usbSendControl(0x40, 0xa1, timerPeriod, clkSetting, length, samples);
|
|
}
|
|
else usbSendControl(0x40, 0xa2, timerPeriod, clkSetting, length, samples);
|
|
free(tempSamples);
|
|
return;
|
|
}
|
|
|
|
void winUsbDriver::xmegaBreak(void){
|
|
usbSendControl(0x40, 0xa0, 0, 0, 0, NULL);
|
|
}
|
|
|
|
void winUsbDriver::newDig(int digState){
|
|
qDebug() << "newDig";
|
|
digitalPinState = digState;
|
|
usbSendControl(0x40, 0xa6, digState, 0, 0, NULL);
|
|
}
|
|
|
|
unsigned char winUsbDriver::usbIsoInit(void){
|
|
unsigned char success;
|
|
unsigned int transferred;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
|
|
success = StmK_Init(
|
|
&stm_handle,
|
|
handle,
|
|
pipeID,
|
|
MAX_TRANSFER_SIZE,
|
|
MAX_PENDING_TRANSFERS,
|
|
MAX_PENDING_IO,
|
|
NULL,
|
|
KSTM_FLAG_NONE);
|
|
if (!success){
|
|
errorCode = GetLastError();
|
|
qDebug("StmK_Init failed. ErrorCode: %08Xh\n", errorCode);
|
|
return 0;
|
|
}
|
|
|
|
success = StmK_Start(stm_handle);
|
|
if (!success){
|
|
errorCode = GetLastError();
|
|
qDebug("StmK_Start failed. ErrorCode: %08Xh\n", errorCode);
|
|
return 0;
|
|
}
|
|
|
|
qDebug("[Start Stream] successful!\n");
|
|
return 1;
|
|
}
|
|
|
|
char *winUsbDriver::isoRead(int numSamples){
|
|
unsigned char *returnBuffer;
|
|
unsigned char success;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
|
|
returnBuffer = (unsigned char *) malloc(numSamples + 8); //8-byte header contains (unsigned long) length
|
|
|
|
success = StmK_Read(stm_handle, returnBuffer+8, 0, numSamples, (PUINT) returnBuffer);
|
|
//qDebug("%d bytes copied, out of a possible %d\n", *((PUINT)returnBuffer), numSamples);
|
|
if (!success) {
|
|
errorCode = GetLastError();
|
|
qDebug("StmkK_Read failed. ErrorCode: %08Xh\n", errorCode);
|
|
reinitialise(0);
|
|
free(returnBuffer);
|
|
return (char*) malloc(numSamples + 8);
|
|
//printf("No more items = %08Xh\n", ERROR_NO_MORE_ITEMS);
|
|
}
|
|
|
|
return (char*) returnBuffer;
|
|
}
|
|
|
|
winUsbDriver::~winUsbDriver(void){
|
|
qDebug() << "\n\nwinUsbDriver destructor ran!";
|
|
unsigned char success;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
|
|
success = StmK_Stop(stm_handle, 0);
|
|
if (!success)
|
|
{
|
|
errorCode = GetLastError();
|
|
qDebug("StmK_Stop failed. ErrorCode: %08Xh\n", errorCode);
|
|
}
|
|
qDebug("[Stop Stream] successful!\n");
|
|
|
|
success = StmK_Free(stm_handle);
|
|
if (!success)
|
|
{
|
|
errorCode = GetLastError();
|
|
qDebug("StmK_Free failed. ErrorCode: %08Xh\n", errorCode);
|
|
}
|
|
|
|
UsbK_Free(handle);
|
|
}
|
|
|
|
void winUsbDriver::setBufferPtr(bufferControl *newPtr){
|
|
bufferPtr = newPtr;
|
|
}
|
|
|
|
void winUsbDriver::setDeviceMode(int mode){
|
|
int oldMode = deviceMode;
|
|
deviceMode = mode;
|
|
usbSendControl(0x40, 0xa5, mode, gainMask, 0, NULL);
|
|
|
|
if (fGenPtr_CH1!=NULL) setFunctionGen(0, fGenPtr_CH1);
|
|
if (fGenPtr_CH2!=NULL) setFunctionGen(1, fGenPtr_CH2);
|
|
|
|
//switch on new deviceMode!!
|
|
switch(deviceMode){
|
|
case 0:
|
|
if(oldMode > 2) sendClearBuffer(1,0,0);
|
|
setVisible_CH2(0);
|
|
checkXY(0);
|
|
break;
|
|
case 1:
|
|
if(oldMode > 2) sendClearBuffer(1,0,0);
|
|
sendClearBuffer(0,1,0);
|
|
setVisible_CH2(1);
|
|
checkXY(0);
|
|
break;
|
|
case 2:
|
|
if(oldMode > 2) sendClearBuffer(1,0,0);
|
|
sendClearBuffer(0,1,0);
|
|
setVisible_CH2(1);
|
|
break;
|
|
case 3:
|
|
if(oldMode != 4) sendClearBuffer(1,0,0);
|
|
sendClearBuffer(0,1,0);
|
|
setVisible_CH2(0);
|
|
checkXY(0);
|
|
break;
|
|
case 4:
|
|
if(oldMode != 3) sendClearBuffer(1,0,0);
|
|
sendClearBuffer(0,1,0);
|
|
setVisible_CH2(1);
|
|
checkXY(0);
|
|
break;
|
|
case 5:
|
|
setVisible_CH2(0);
|
|
checkXY(0);
|
|
break;
|
|
case 6:
|
|
sendClearBuffer(0,0,1);
|
|
setVisible_CH2(0);
|
|
checkXY(0);
|
|
break;
|
|
case 7:
|
|
sendClearBuffer(1,0,0);
|
|
enableMMTimer();
|
|
checkXY(0);
|
|
break;
|
|
default:
|
|
qFatal("Error in winUsbDriver::setDeviceMode. Invalid device mode.");
|
|
}
|
|
|
|
}
|
|
|
|
void winUsbDriver::psuTick(){
|
|
if(dutyTemp == dutyPsu) return;
|
|
|
|
if (dutyTemp > dutyPsu){
|
|
if((dutyTemp - dutyPsu)> PSU_STEP){
|
|
dutyTemp -= PSU_STEP;
|
|
} else dutyTemp = dutyPsu;
|
|
}
|
|
|
|
if (dutyTemp < dutyPsu){
|
|
if((dutyPsu - dutyTemp)> PSU_STEP){
|
|
dutyTemp += PSU_STEP;
|
|
} else dutyTemp = dutyPsu;
|
|
}
|
|
|
|
if ((dutyTemp>113) || (dutyTemp<21)){
|
|
qDebug("PSU DUTY CYCLE TOO LARGE (could underflow on SOF)!!! ABORTING!!!");
|
|
}
|
|
usbSendControl(0x40, 0xa3, dutyTemp, 0, 0, NULL);
|
|
}
|
|
|
|
void winUsbDriver::setGain(double newGain){
|
|
if (newGain == scopeGain) return; //No update!
|
|
gainBuffers(scopeGain/newGain);
|
|
scopeGain = newGain;
|
|
if (newGain == 0.5){
|
|
gainMask = 7<<2 | 7<<10;
|
|
}
|
|
else gainMask = (unsigned short)(log2(newGain))<<2 | (unsigned short)(log2(newGain))<<10;
|
|
qDebug("newGain = %f", newGain);
|
|
qDebug("gainMask = %d", gainMask);
|
|
usbSendControl(0x40, 0xa5, deviceMode, gainMask, 0, NULL);
|
|
}
|
|
|
|
void winUsbDriver::reinitialise(bool forceAttempt){
|
|
|
|
/*if (!firstConnect){
|
|
firstConnect = usbInit(0x03eb, 0xa000);
|
|
setDeviceMode(deviceMode);
|
|
usbIsoInit();
|
|
//Reset!!
|
|
usbSendControl(0x40, 0xa7, 0, 0, 0, NULL);
|
|
//Stack will reinitialise TIMER_PERIOD seconds later, after first failed iso request
|
|
return;
|
|
}*/
|
|
|
|
if (!forceAttempt){
|
|
if(recoveryInProcess == true) {
|
|
//qDebug() << "Cancelling reinitialise()";
|
|
return;
|
|
}
|
|
}
|
|
|
|
//qDebug() << "reinitialise() entered";
|
|
|
|
//if(forceAttempt) qFatal("Forcing attempt");
|
|
|
|
disableWindow(0);
|
|
|
|
recoveryInProcess = true;
|
|
|
|
unsigned char success;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
|
|
success = UsbK_Free(handle);
|
|
if (!success){
|
|
errorCode = GetLastError();
|
|
qDebug("UsbK_Free (reinit) failed. ErrorCode: %08Xh\n", errorCode);
|
|
}
|
|
//else qDebug() << "Handle freed successfully!";
|
|
|
|
if(forceAttempt){
|
|
StmK_Free(stm_handle);
|
|
stm_handle = NULL;
|
|
}
|
|
UsbK_ResetDevice(handle);
|
|
unsigned char initSuccess = usbInit(0x03eb, 0xa000);
|
|
//qDebug() << "usbInit(0x03eb, 0xa000) returned" << initSuccess;
|
|
|
|
if (!initSuccess){
|
|
recoverySuccess = 0;
|
|
return;
|
|
}
|
|
|
|
setDeviceMode(deviceMode);
|
|
//qDebug() << "setDeviceMode(deviceMode) returned" << deviceSuccess;
|
|
if (fGenPtr_CH1 != NULL) {
|
|
//qDebug() << "setFunctionGen(0, fGenPtr_CH1)";
|
|
setFunctionGen(0, fGenPtr_CH1);
|
|
}
|
|
if (fGenPtr_CH2 != NULL){
|
|
//qDebug() << "setFunctionGen(1, fGenPtr_CH2)";
|
|
setFunctionGen(1, fGenPtr_CH2);
|
|
}
|
|
newDig(digitalPinState);
|
|
|
|
|
|
unsigned char isoInitSuccess = usbIsoInit();
|
|
//qDebug() << "usbIsoInit() returned" << isoInitSuccess;
|
|
|
|
recoverySuccess = initSuccess && isoInitSuccess;
|
|
|
|
if(recoverySuccess){
|
|
//qDebug() << "reinitialise() completed successfully";
|
|
}
|
|
//else qDebug() << "reinitialise() completed with errors";
|
|
}
|
|
|
|
void winUsbDriver::avrDebug(void){
|
|
usbSendControl(0x40, 0xa0, 0, 0, 0, NULL);
|
|
}
|