mirror of https://github.com/EspoTek/Labrador.git
490 lines
16 KiB
C++
490 lines
16 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
|
|
usbInit(0x03eb, 0xa000);
|
|
setDeviceMode(deviceMode);
|
|
newDig(digitalPinState);
|
|
usbIsoInit();
|
|
|
|
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){
|
|
int n;
|
|
bool success;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
|
|
success = OvlK_Init(&ovlPool, handle, MAX_OVERLAP, (KOVL_POOL_FLAG) 0);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "OvlK_Init failed with error code" << errorCode;
|
|
return 0;
|
|
}
|
|
success = UsbK_ResetPipe(handle, pipeID);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "UsbK_ResetPipe failed with error code" << errorCode;
|
|
return 0;
|
|
}
|
|
|
|
for(n=0;n<NUM_FUTURE_CTX;n++){
|
|
success = IsoK_Init(&isoCtx[n], ISO_PACKETS_PER_CTX, n*ISO_PACKETS_PER_CTX);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "IsoK_Init failed with error code" << errorCode;
|
|
qDebug() << "n =" << n;
|
|
return 0;
|
|
}
|
|
|
|
success = IsoK_SetPackets(isoCtx[n], ISO_PACKET_SIZE);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "IsoK_SetPackets failed with error code" << errorCode;
|
|
qDebug() << "n =" << n;
|
|
return 0;
|
|
}
|
|
|
|
success = OvlK_Acquire(&ovlkHandle[n], ovlPool);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "OvlK_Acquire failed with error code" << errorCode;
|
|
qDebug() << "n =" << n;
|
|
return 0;
|
|
}
|
|
|
|
success = UsbK_IsoReadPipe(handle, pipeID, dataBuffer[n], sizeof(dataBuffer[n]), (LPOVERLAPPED) ovlkHandle[n], isoCtx[n]);
|
|
}
|
|
qDebug() << "Iso Setup Successful";
|
|
return 1;
|
|
}
|
|
|
|
char *winUsbDriver::isoRead(){
|
|
unsigned char *returnBuffer;
|
|
|
|
bool success;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
unsigned int allocBytes = 0;
|
|
int n, i, j;
|
|
unsigned int returnBufferOffset = 8;
|
|
unsigned int dataBufferOffset;
|
|
|
|
//Calculate how much data needs to be allocated
|
|
for (n=0; n<NUM_FUTURE_CTX; n++){
|
|
if(OvlK_IsComplete(ovlkHandle[n])){
|
|
for(i=0;i<isoCtx[n]->NumberOfPackets;i++){
|
|
allocBytes +=isoCtx[n]->IsoPackets[i].Length;
|
|
}
|
|
}
|
|
}
|
|
//Allocate it (why am I allocating a new buffer every time?)
|
|
returnBuffer = (unsigned char *) malloc(allocBytes + 8); //Extra 8 bytes for the "header" that contains length of "packet" as unsigned int.
|
|
((unsigned int *) returnBuffer)[0] = allocBytes;
|
|
|
|
//Fill the memory with the relevant samples
|
|
//Note that this will return garbage if more than one isoCtx has completed.
|
|
//The above condition should only ever occur if the polling rate is slower than ISO_PACKETS_PER_CTX, though.
|
|
//(Or if some heinous external force stops the polling and gives it a long "temporary period"!!)
|
|
for (n=0; n<NUM_FUTURE_CTX; n++){
|
|
if(OvlK_IsComplete(ovlkHandle[n])){
|
|
//qDebug("Transfer %d is complete!!", n);
|
|
|
|
//Copy the iso packet
|
|
char currentString[8];
|
|
for(i=0;i<isoCtx[n]->NumberOfPackets;i++){
|
|
dataBufferOffset = isoCtx[n]->IsoPackets[i].Offset;
|
|
//memcpy(&returnBuffer[returnBufferOffset], &dataBuffer[n][dataBufferOffset], isoCtx[n]->IsoPackets[i].Length);
|
|
for(int j=0;j<isoCtx[n]->IsoPackets[i].Length;j++){
|
|
returnBuffer[returnBufferOffset+j] = dataBuffer[n][dataBufferOffset+j];
|
|
}
|
|
returnBufferOffset += isoCtx[n]->IsoPackets[i].Length;
|
|
}
|
|
}
|
|
|
|
|
|
//Setup next transfer
|
|
UINT oldStart = isoCtx[n]->StartFrame;
|
|
success = IsoK_ReUse(isoCtx[n]);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "IsoK_Init failed with error code" << errorCode;
|
|
qDebug() << "n =" << n;
|
|
return (char*) returnBuffer;
|
|
}
|
|
isoCtx[n]->StartFrame = oldStart + ISO_PACKETS_PER_CTX*NUM_FUTURE_CTX;
|
|
//qDebug() << oldStart;
|
|
//qDebug() << isoCtx[n]->StartFrame;
|
|
//qDebug() << handle;
|
|
|
|
success = OvlK_ReUse(ovlkHandle[n]);
|
|
if(!success){
|
|
errorCode = GetLastError();
|
|
qDebug() << "OvlK_ReUse failed with error code" << errorCode;
|
|
qDebug() << "n =" << n;
|
|
return (char*) returnBuffer;
|
|
}
|
|
success = UsbK_IsoReadPipe(handle, pipeID, dataBuffer[n], sizeof(dataBuffer[n]), (LPOVERLAPPED) ovlkHandle[n], isoCtx[n]);
|
|
}
|
|
//qDebug("%d bytes need to be allocated", allocBytes);
|
|
|
|
return (char*) returnBuffer;
|
|
}
|
|
|
|
winUsbDriver::~winUsbDriver(void){
|
|
qDebug() << "\n\nwinUsbDriver destructor ran!";
|
|
unsigned char success;
|
|
DWORD errorCode = ERROR_SUCCESS;
|
|
|
|
UsbK_Free(handle);
|
|
}
|
|
|
|
void winUsbDriver::setBufferPtr(bufferControl *newPtr){
|
|
bufferPtr = newPtr;
|
|
}
|
|
|
|
void winUsbDriver::setDeviceMode(int mode){
|
|
int oldMode = deviceMode;
|
|
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);
|
|
|
|
//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>106) || (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::avrDebug(void){
|
|
usbSendControl(0x40, 0xa0, 0, 0, 0, NULL);
|
|
}
|