mirror of
https://github.com/EEVengers/ThunderScope.git
synced 2025-04-22 17:43:44 +00:00
Merge pull request #194 from EEVengers/FPGA_DSP_PIPE_HOOKUP
Fpga dsp pipe hookup
This commit is contained in:
commit
1b57c317ee
Software/waveview/scope_link
@ -22,7 +22,7 @@
|
||||
#define USER_DEVICE_PATH "user"
|
||||
#define C2H_0_DEVICE_PATH "c2h_0"
|
||||
|
||||
#define DATAMOVER_REG_OUT 0x00000 // bit 0: halt, bit 1: reset
|
||||
#define DATAMOVER_REG_OUT 0x00000 // bit 0: !halt, bit 1: !reset
|
||||
#define DATAMOVER_TRANSFER_COUNTER 0x00008 // A 32 bit value, low 16 is transfer counter, bit 31 error bit
|
||||
#define BOARD_REG_OUT 0x10000 // A 32 bit value, bit 0:3: attenuation, bit 4:7: dc_cpl, bit 8: acq_en, bit 9: clk_oe, bit 10: fe_en, 21bits unused
|
||||
#define BOARD_REG_IN 0x10008 // unused for now
|
||||
@ -43,19 +43,55 @@
|
||||
#define CLOCK_GEN_I2C_ADDRESS_READ 0b10110001 //IF WE COULD
|
||||
|
||||
enum ScopeCommand {
|
||||
board_enable,
|
||||
adc_enable,
|
||||
adc_rest,
|
||||
adc_power_down,
|
||||
adc_active,
|
||||
adc_cgain_cfg,
|
||||
adc_btc_mode,
|
||||
adc_chnum_clkdiv_init,
|
||||
clk_enable,
|
||||
init_board,
|
||||
adc_enable_ramp_test,
|
||||
dataMover_enable,
|
||||
dataMover_halt,
|
||||
dataMover_disable,
|
||||
test_write
|
||||
enable_channel,
|
||||
disable_channel,
|
||||
ac_couple,
|
||||
dc_couple,
|
||||
voltage_divison_set,
|
||||
voltage_offset_set,
|
||||
bandwidth_set,
|
||||
test_write,
|
||||
test_adc_data
|
||||
};
|
||||
|
||||
struct VoltageDivSetParam {
|
||||
int ch_num;
|
||||
int voltage_div;
|
||||
};
|
||||
|
||||
struct VoltageOffsetParam {
|
||||
int ch_num;
|
||||
double voltage;
|
||||
};
|
||||
|
||||
struct BandwidthSetParam {
|
||||
int ch_num;
|
||||
int bw;
|
||||
};
|
||||
|
||||
struct BoardState {
|
||||
//general front end en
|
||||
bool board_en;
|
||||
//adc values
|
||||
bool adc_en;
|
||||
uint8_t num_ch_on;
|
||||
bool ch_is_on[4];
|
||||
uint8_t adc_chnum_clkdiv [4];
|
||||
uint8_t adc_in_sel_12[4];
|
||||
uint8_t adc_in_sel_34[4];
|
||||
//pga's
|
||||
uint8_t pga[4][4];
|
||||
//dac
|
||||
uint8_t dac[4][5];
|
||||
//clock values
|
||||
bool clk_en;
|
||||
//Board Register Values
|
||||
uint32_t board_reg_out; // A 32 bit value, bit 0:3: attenuation, bit 4:7: dc_cpl, bit 8: acq_en, bit 9: clk_oe, bit 10: fe_en, 21bits unused
|
||||
uint32_t datamover_reg_out; // bit 0: !halt, bit 1: !reset, bit 4:6: channel
|
||||
};
|
||||
|
||||
class PCIeLink {
|
||||
@ -85,7 +121,6 @@ private:
|
||||
|
||||
char user_device[20] = USER_DEVICE_PATH; //write/read registers
|
||||
char c2h_0_device[20] = C2H_0_DEVICE_PATH; //read memory
|
||||
uint8_t dataMoverReg[1] = {0x00};
|
||||
HANDLE user_handle;
|
||||
char user_connection_string[261] = "";
|
||||
HANDLE c2h_0_handle;
|
||||
@ -93,6 +128,9 @@ private:
|
||||
LARGE_INTEGER freq; //used for perforamnce testing
|
||||
int64_t last_chunk_read;
|
||||
|
||||
//current state
|
||||
BoardState currentBoardState;
|
||||
|
||||
std::atomic<bool> _run;
|
||||
std::atomic<bool> _pause;
|
||||
std::thread PCIeReadThread;
|
||||
@ -106,9 +144,23 @@ private:
|
||||
|
||||
void _Read(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToRead);
|
||||
void _Write(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToWrite);
|
||||
void _Write32(HANDLE hPCIE, long long address, uint32_t val);
|
||||
void _FIFO_WRITE(HANDLE hPCIE, uint8_t* data, uint8_t bytesToWrite);
|
||||
void _Job();
|
||||
|
||||
|
||||
//scope control stuff
|
||||
int _ch_on(int ch_num);
|
||||
int _ch_off(int ch_num);
|
||||
int _dc_cpl(int ch_num);
|
||||
int _ac_cpl(int ch_num);
|
||||
int _vdiv_set(int ch_num, int vdiv);
|
||||
int _voffset_set(int ch_num, double voffset);
|
||||
int _bw_set(int ch_num, int bw);
|
||||
int _adc_ch_cfg();
|
||||
void _adc_power_down();
|
||||
void _adc_active();
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
void setMathSign(bool newSign);
|
||||
void getData();
|
||||
void setFileName(int8_t newFile);
|
||||
void hardWareCommand(int command, int channel, int val1, double val2);
|
||||
void testADCData();
|
||||
|
||||
private:
|
||||
// external queue
|
||||
|
@ -222,17 +222,7 @@ boost::lockfree::queue<buffer*, boost::lockfree::fixed_sized<false>> testerDataQ
|
||||
void runPCIeTest() {
|
||||
|
||||
controller* troller = new controller(&testerDataQueue);
|
||||
troller->controllerUnPause();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
/*FILE* fp = fopen("TestData.txt","w");
|
||||
for(int i = 0; i < (1 << 23); i+= 8) {
|
||||
fprintf(fp,"%X,%X,%X,%X,%X,%X,%X,%X\n",
|
||||
buff[i],buff[i + 1],buff[i + 2],buff[i + 3],buff[i + 4],buff[i + 5],buff[i + 6],buff[i + 7]);
|
||||
}
|
||||
fclose(fp); */
|
||||
|
||||
|
||||
troller->setWindowSize(1000);
|
||||
troller->testADCData();
|
||||
delete troller;
|
||||
}
|
@ -174,9 +174,7 @@ void PCIeLink::Read(uint8_t* buff) {
|
||||
}
|
||||
|
||||
void PCIeLink::InitBoard() {
|
||||
Write(board_enable,nullptr);
|
||||
Write(clk_enable,nullptr);
|
||||
Write(adc_enable,nullptr);
|
||||
Write(init_board,nullptr);
|
||||
Write(dataMover_enable,nullptr);
|
||||
}
|
||||
|
||||
@ -204,18 +202,84 @@ void PCIeLink::Stop() {
|
||||
*************************************************************/
|
||||
void PCIeLink::Write(ScopeCommand command, void* val) {
|
||||
switch(command) {
|
||||
case board_enable:
|
||||
case init_board:
|
||||
INFO << "Enabling Board";
|
||||
{
|
||||
uint8_t en[] = {0x00, 0x00};
|
||||
_Read(user_handle,BOARD_REG_OUT,en,2);
|
||||
en[1] |= 0x01; //acq->on fe->off
|
||||
_Write(user_handle,BOARD_REG_OUT,en,2);
|
||||
currentBoardState.board_reg_out |= 0x0100; //acq->on fe->off
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
break;
|
||||
case adc_enable:
|
||||
|
||||
INFO << "Enabling PLL";
|
||||
{
|
||||
uint16_t config_clk_gen[] = {
|
||||
0x0010, 0x010B, 0x0233, 0x08B0,
|
||||
0x0901, 0x1000, 0x1180, 0x1501,
|
||||
0x1600, 0x1705, 0x1900, 0x1A32,
|
||||
0x1B00, 0x1C00, 0x1D00, 0x1E00,
|
||||
0x1F00, 0x2001, 0x210C, 0x2228,
|
||||
0x2303, 0x2408, 0x2500, 0x2600,
|
||||
0x2700, 0x2F00, 0x3000, 0x3110,
|
||||
0x3200, 0x3300, 0x3400, 0x3500,
|
||||
0x3800, 0x4802 }; //correct bytes to configure the clock gen
|
||||
|
||||
//write to the clock generator
|
||||
for(int i = 0; i < 34; i++) {
|
||||
uint8_t data[] = {I2C_BYTE_PLL, CLOCK_GEN_I2C_ADDRESS_WRITE, (uint8_t)((config_clk_gen[i] & 0xFF00) >> 8),(uint8_t)(config_clk_gen[i] & 0xFF)};
|
||||
//printf("DataPacket: %X %X %X %X\n",data[0],data[1],data[2],data[3]);
|
||||
_FIFO_WRITE(user_handle,data,4);
|
||||
}
|
||||
|
||||
currentBoardState.board_reg_out |= 0x0200;
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
}
|
||||
|
||||
INFO << "Enabling ADC";
|
||||
{
|
||||
//Reset ADC
|
||||
uint8_t resetADC[] = {0xFD,0x00,0x00,0x01};
|
||||
_FIFO_WRITE(user_handle,resetADC,4);
|
||||
//Power Down ADC
|
||||
_adc_power_down();
|
||||
//Set Channel and Clock Div
|
||||
uint8_t setChannelClock[] = {0xFD,0x31,0x00,0x01};
|
||||
_FIFO_WRITE(user_handle,setChannelClock,4);
|
||||
//invert channels
|
||||
uint8_t channel_invert[] = {0xFD,0x24,0x00,0x7F};
|
||||
_FIFO_WRITE(user_handle,channel_invert,4);
|
||||
|
||||
_ch_on(0);
|
||||
//twos compliment mode TURN OFF
|
||||
uint8_t setTwosComp[] = {0xFD,0x46,0x00,0x00};
|
||||
_FIFO_WRITE(user_handle,setTwosComp,4);
|
||||
//Course Gain On
|
||||
uint8_t course_gain_on[] = {0xFD,0x33,0x00,0x00};
|
||||
_FIFO_WRITE(user_handle,course_gain_on,4);
|
||||
//Course Gain 4-CH set
|
||||
uint8_t course_gain4[] = {0xFD,0x2A,0x99,0x99};
|
||||
_FIFO_WRITE(user_handle,course_gain4,4);
|
||||
//Course Gain 1-CH & 2-CH set
|
||||
uint8_t course_gain12[] = {0xFD,0x2B,0x09,0x99};
|
||||
_FIFO_WRITE(user_handle,course_gain12,4);
|
||||
//Set adc into active mode
|
||||
_adc_active();
|
||||
}
|
||||
|
||||
INFO << "Enabling the front end";
|
||||
{
|
||||
currentBoardState.board_reg_out |= 0x0400; //fe->on
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
//enable the pga
|
||||
for(int i = 0; i < 4; i++) {
|
||||
_FIFO_WRITE(user_handle,currentBoardState.pga[i],sizeof(currentBoardState.pga[i]));
|
||||
_FIFO_WRITE(user_handle,currentBoardState.dac[i],sizeof(currentBoardState.dac[i]));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case adc_enable_ramp_test:
|
||||
INFO << "Enabling ADC RAMP MODE";
|
||||
{
|
||||
//Reset ADC
|
||||
uint8_t resetADC[] = {0xFD,0x00,0x00,0x01};
|
||||
@ -244,31 +308,53 @@ void PCIeLink::Write(ScopeCommand command, void* val) {
|
||||
_FIFO_WRITE(user_handle,adcActiveMode,4);
|
||||
}
|
||||
break;
|
||||
case clk_enable:
|
||||
INFO << "Enabling PLL";
|
||||
case dataMover_enable:
|
||||
INFO << "Enabling DataMover";
|
||||
{
|
||||
uint16_t config_clk_gen[] = {
|
||||
0x0010, 0x010B, 0x0233, 0x08B0,
|
||||
0x0901, 0x1000, 0x1180, 0x1501,
|
||||
0x1600, 0x1705, 0x1900, 0x1A32,
|
||||
0x1B00, 0x1C00, 0x1D00, 0x1E00,
|
||||
0x1F00, 0x2001, 0x210C, 0x2228,
|
||||
0x2303, 0x2408, 0x2500, 0x2600,
|
||||
0x2700, 0x2F00, 0x3000, 0x3110,
|
||||
0x3200, 0x3300, 0x3400, 0x3500,
|
||||
0x3800, 0x4802 }; //correct bytes to configure the clock gen
|
||||
|
||||
//write to the clock generator
|
||||
for(int i = 0; i < 34; i++) {
|
||||
uint8_t data[] = {I2C_BYTE_PLL, CLOCK_GEN_I2C_ADDRESS_WRITE, (uint8_t)((config_clk_gen[i] & 0xFF00) >> 8),(uint8_t)(config_clk_gen[i] & 0xFF)};
|
||||
//printf("DataPacket: %X %X %X %X\n",data[0],data[1],data[2],data[3]);
|
||||
_FIFO_WRITE(user_handle,data,4);
|
||||
}
|
||||
|
||||
uint8_t en[] = {0x00, 0x00};
|
||||
_Read(user_handle,BOARD_REG_OUT,en,2);
|
||||
en[1] |= 0x02; //clk->on
|
||||
_Write(user_handle,BOARD_REG_OUT,en,2);
|
||||
currentBoardState.datamover_reg_out |= 0x03;
|
||||
_Write32(user_handle,DATAMOVER_REG_OUT,currentBoardState.datamover_reg_out);
|
||||
}
|
||||
break;
|
||||
case dataMover_disable:
|
||||
INFO << "Disabling DataMover";
|
||||
{
|
||||
currentBoardState.datamover_reg_out &= ~(0x01);
|
||||
_Write32(user_handle,DATAMOVER_REG_OUT,currentBoardState.datamover_reg_out);
|
||||
currentBoardState.datamover_reg_out &= ~(0x02);
|
||||
_Write32(user_handle,DATAMOVER_REG_OUT,currentBoardState.datamover_reg_out);
|
||||
}
|
||||
break;
|
||||
case enable_channel:
|
||||
_ch_on(*((int*)val));
|
||||
break;
|
||||
case disable_channel:
|
||||
_ch_off(*((int*)val));
|
||||
break;
|
||||
case ac_couple:
|
||||
_ac_cpl(*((int*)val));
|
||||
break;
|
||||
case dc_couple:
|
||||
_dc_cpl(*((int*)val));
|
||||
break;
|
||||
case voltage_divison_set:
|
||||
{
|
||||
VoltageDivSetParam* param = (VoltageDivSetParam*)val;
|
||||
DEBUG << "Setting Channel " << param->ch_num << " Voltage Division To " << param->voltage_div;
|
||||
_vdiv_set(param->ch_num,param->voltage_div);
|
||||
}
|
||||
break;
|
||||
case voltage_offset_set:
|
||||
{
|
||||
VoltageOffsetParam* param = (VoltageOffsetParam*)val;
|
||||
DEBUG << "Setting Channel " << param->ch_num << " DC Voltage Offset To " << param->voltage << "mV";
|
||||
_voffset_set(param->ch_num,param->voltage);
|
||||
}
|
||||
break;
|
||||
case bandwidth_set:
|
||||
{
|
||||
BandwidthSetParam* param = (BandwidthSetParam*)val;
|
||||
DEBUG << "Setting Channel " << param->ch_num << " Bandwidth To: " << param->bw;
|
||||
_bw_set(param->ch_num,param->bw);
|
||||
}
|
||||
break;
|
||||
case test_write:
|
||||
@ -293,20 +379,48 @@ void PCIeLink::Write(ScopeCommand command, void* val) {
|
||||
printf("After writting 0 again, the read value is: %d\n",rxBuff[0]);
|
||||
}
|
||||
break;
|
||||
case dataMover_enable:
|
||||
INFO << "Enabling DataMover";
|
||||
case test_adc_data:
|
||||
{
|
||||
dataMoverReg[0] |= 0x03;
|
||||
_Write(user_handle,DATAMOVER_REG_OUT,dataMoverReg,1);
|
||||
}
|
||||
break;
|
||||
case dataMover_disable:
|
||||
INFO << "Disabling DataMover";
|
||||
{
|
||||
dataMoverReg[0] &= ~(0x01);
|
||||
_Write(user_handle,DATAMOVER_REG_OUT,dataMoverReg,1);
|
||||
dataMoverReg[0] &= ~(0x02);
|
||||
_Write(user_handle,DATAMOVER_REG_OUT,dataMoverReg,1);
|
||||
int num_buffers = 4;
|
||||
uint8_t* preBuff = (uint8_t*)malloc(BUFFER_SIZE * sizeof(uint8_t));
|
||||
int8_t **buffers = (int8_t**)malloc(num_buffers * sizeof(int8_t*));
|
||||
for(int i = 0; i < num_buffers; i++) {
|
||||
buffers[i] = (int8_t*)malloc(BUFFER_SIZE * sizeof(int8_t));
|
||||
}
|
||||
|
||||
for(int i = 0; i < num_buffers; i++) {
|
||||
Read(preBuff);
|
||||
for(int q = 0; q < BUFFER_SIZE; q++) {
|
||||
if(preBuff[i] & 0x80) {
|
||||
//postive
|
||||
buffers[i][q] = (int)(preBuff[q] & 0x7F);
|
||||
} else {
|
||||
//negative
|
||||
buffers[i][q] = (-128 + ((int)(preBuff[q] & 0x7F)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < num_buffers; i++) {
|
||||
char name[100];
|
||||
sprintf(name,"ADC_DATA_FILE%d.csv",i);
|
||||
FILE* file = fopen(name,"w");
|
||||
for(int q = 0; q < BUFFER_SIZE;) {
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d,",buffers[i][q++]);
|
||||
fprintf(file,"%d\n",buffers[i][q++]);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < num_buffers; i++) {
|
||||
free(buffers[i]);
|
||||
}
|
||||
free(buffers);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -399,7 +513,34 @@ void PCIeLink::_Write(HANDLE hPCIE, int64_t address, uint8_t* buff, int bytesToW
|
||||
}
|
||||
}
|
||||
|
||||
void PCIeLink::_Write32(HANDLE hPCIE, long long address, uint32_t val) {
|
||||
if(hPCIE == INVALID_HANDLE_VALUE) {
|
||||
ERROR << "INVALID HANDLE PASSED INTO PCIeLink::_Write(): " << hPCIE;
|
||||
return;
|
||||
}
|
||||
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = address;
|
||||
// set file pointer to offset of target address within PCIe BAR
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hPCIE, offset, NULL, FILE_BEGIN)) {
|
||||
ERROR << "Error setting file pointer for PCIeLink::_Write(), win32 error code: " << GetLastError();
|
||||
}
|
||||
|
||||
// write from buffer to device
|
||||
DWORD bytesWritten;
|
||||
uint8_t bytes[4];
|
||||
bytes[3] = (uint8_t)( (val & 0xFF000000) >> 24);
|
||||
bytes[2] = (uint8_t)( (val & 0x00FF0000) >> 16);
|
||||
bytes[1] = (uint8_t)( (val & 0x0000FF00) >> 8);
|
||||
bytes[0] = (uint8_t)( (val & 0x000000FF));
|
||||
if (!WriteFile(hPCIE, bytes, 4, &bytesWritten, NULL)) {
|
||||
ERROR << "_Write() failed with Win32 error code: " << GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
void PCIeLink::_Job() {
|
||||
|
||||
uint8_t* preBuff = (uint8_t*)malloc(sizeof(uint8_t) * BUFFER_SIZE);
|
||||
while(_run.load()) {
|
||||
while(_pause.load()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
@ -409,36 +550,111 @@ void PCIeLink::_Job() {
|
||||
buff = bufferAllocator.allocate(1);
|
||||
bufferAllocator.construct(buff);
|
||||
//read from the PCIeLink
|
||||
Read((uint8_t*)buff->data);
|
||||
Read(preBuff);
|
||||
for(int i = 0; i < BUFFER_SIZE; i++) {
|
||||
if(preBuff[i] & 0x80) {
|
||||
//postive
|
||||
buff->data[i] = (int)(preBuff[i] & 0x7F);
|
||||
} else {
|
||||
//negative
|
||||
buff->data[i] = (-128 + ((int)(preBuff[i] & 0x7F)));
|
||||
}
|
||||
}
|
||||
//push to queue
|
||||
outputQueue->push(buff);
|
||||
}
|
||||
free(preBuff);
|
||||
}
|
||||
|
||||
PCIeLink::PCIeLink(boost::lockfree::queue<buffer*, boost::lockfree::fixed_sized<false>> *outputQueue) {
|
||||
user_handle = INVALID_HANDLE_VALUE;
|
||||
c2h_0_handle = INVALID_HANDLE_VALUE;
|
||||
dataMoverReg[0] = 0x00;
|
||||
last_chunk_read = -1;
|
||||
_run = true;
|
||||
_pause = true;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
this->outputQueue = outputQueue;
|
||||
//keep the read thread alive but paused
|
||||
_run = true;
|
||||
_pause = true;
|
||||
//init board state vairable
|
||||
currentBoardState.board_en = false;
|
||||
currentBoardState.adc_en = false;
|
||||
currentBoardState.clk_en = false;
|
||||
currentBoardState.num_ch_on = 0;
|
||||
|
||||
//adc stuff
|
||||
currentBoardState.adc_chnum_clkdiv[0] = 0xFD;
|
||||
currentBoardState.adc_chnum_clkdiv[1] = 0x31;
|
||||
currentBoardState.adc_chnum_clkdiv[2] = 0x00;
|
||||
currentBoardState.adc_chnum_clkdiv[3] = 0x01;
|
||||
|
||||
currentBoardState.adc_in_sel_12[0] = 0xFD;
|
||||
currentBoardState.adc_in_sel_12[1] = 0x3A;
|
||||
currentBoardState.adc_in_sel_12[2] = 0x10;
|
||||
currentBoardState.adc_in_sel_12[3] = 0x10;
|
||||
|
||||
currentBoardState.adc_in_sel_34[0] = 0xFD;
|
||||
currentBoardState.adc_in_sel_34[1] = 0x3B;
|
||||
currentBoardState.adc_in_sel_34[2] = 0x10;
|
||||
currentBoardState.adc_in_sel_34[3] = 0x10;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
currentBoardState.ch_is_on[i] = 0;
|
||||
//init dac state
|
||||
currentBoardState.dac[i][0] = 0xFF;
|
||||
currentBoardState.dac[i][1] = 0xC2;
|
||||
currentBoardState.dac[i][3] = 0x08;
|
||||
currentBoardState.dac[i][4] = 0x00;
|
||||
//init pga state
|
||||
currentBoardState.pga[i][1] = 0x00;
|
||||
currentBoardState.pga[i][2] = 0x04;
|
||||
currentBoardState.pga[i][3] = 0x0A;
|
||||
}
|
||||
//init pga state address
|
||||
currentBoardState.pga[0][0] = 0xFB;
|
||||
currentBoardState.pga[1][0] = 0xFA;
|
||||
currentBoardState.pga[2][0] = 0xF9;
|
||||
currentBoardState.pga[3][0] = 0xF8;
|
||||
|
||||
currentBoardState.dac[0][2] = 0x40;
|
||||
currentBoardState.dac[1][2] = 0x42;
|
||||
currentBoardState.dac[2][2] = 0x44;
|
||||
currentBoardState.dac[3][2] = 0x46;
|
||||
|
||||
//init register values
|
||||
currentBoardState.datamover_reg_out = 0x00;
|
||||
currentBoardState.board_reg_out = 0xFF; // FOR FUCKS SAKE CHANGE THIS!
|
||||
|
||||
//connect to the board and start the adc + read thread
|
||||
Connect();
|
||||
InitBoard();
|
||||
PCIeReadThread = std::thread(&PCIeLink::_Job, this);
|
||||
}
|
||||
|
||||
PCIeLink::~PCIeLink() {
|
||||
if(user_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(user_handle);
|
||||
if(c2h_0_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(c2h_0_handle);
|
||||
|
||||
//turn off the adc
|
||||
INFO << "Powering down adc";
|
||||
_adc_power_down();
|
||||
//disable the front end and board power
|
||||
INFO << "Turning Off Power To Front End";
|
||||
currentBoardState.board_reg_out = 0;
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
|
||||
_pause.store(false);
|
||||
_run.store(true);
|
||||
_run.store(false);
|
||||
|
||||
DEBUG << "Waiting to join PCIeReadThread";
|
||||
PCIeReadThread.join();
|
||||
DEBUG << "Joined PCIeReadThread";
|
||||
|
||||
if(user_handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(user_handle);
|
||||
user_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if(c2h_0_handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(c2h_0_handle);
|
||||
c2h_0_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
void PCIeLink::ClockTick1() {
|
||||
@ -466,11 +682,224 @@ double PCIeLink::GetTimeDelta() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************ SCOPE CONTROL STUFF ***********************************************/
|
||||
|
||||
int PCIeLink::_ch_on(int ch_num){
|
||||
|
||||
if (currentBoardState.ch_is_on[ch_num])
|
||||
return 0; //Channel already on
|
||||
|
||||
currentBoardState.num_ch_on++;
|
||||
currentBoardState.ch_is_on[ch_num] = true;
|
||||
_adc_ch_cfg();
|
||||
|
||||
_FIFO_WRITE(user_handle,currentBoardState.dac[ch_num],sizeof(currentBoardState.dac[ch_num]));
|
||||
_FIFO_WRITE(user_handle,currentBoardState.pga[ch_num],sizeof(currentBoardState.pga[ch_num]));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PCIeLink::_ch_off(int ch_num){
|
||||
|
||||
if (!currentBoardState.ch_is_on[ch_num])
|
||||
return 0; //Channel already off
|
||||
|
||||
currentBoardState.num_ch_on--;
|
||||
currentBoardState.ch_is_on[ch_num] = false;
|
||||
_adc_ch_cfg();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PCIeLink::_dc_cpl(int ch_num){
|
||||
if (ch_num == 0)
|
||||
currentBoardState.board_reg_out |= (1 << 4);
|
||||
else if (ch_num == 1)
|
||||
currentBoardState.board_reg_out |= (1 << 5);
|
||||
else if (ch_num == 2)
|
||||
currentBoardState.board_reg_out |= (1 << 6);
|
||||
else if (ch_num == 3)
|
||||
currentBoardState.board_reg_out |= (1 << 7);
|
||||
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PCIeLink::_ac_cpl(int ch_num){
|
||||
if (ch_num == 0)
|
||||
currentBoardState.board_reg_out &= ~(1 << 4);
|
||||
else if (ch_num == 1)
|
||||
currentBoardState.board_reg_out &= ~(1 << 5);
|
||||
else if (ch_num == 2)
|
||||
currentBoardState.board_reg_out &= ~(1 << 6);
|
||||
else if (ch_num == 3)
|
||||
currentBoardState.board_reg_out &= ~(1 << 7);
|
||||
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//expect vdiv in millivolts
|
||||
int PCIeLink::_vdiv_set(int ch_num, int vdiv){
|
||||
|
||||
if (vdiv <= 100){ //Attenuator relay on for higher v/divs
|
||||
if (ch_num == 0)
|
||||
currentBoardState.board_reg_out |= (1 << 0);
|
||||
else if (ch_num == 1)
|
||||
currentBoardState.board_reg_out |= (1 << 1);
|
||||
else if (ch_num == 2)
|
||||
currentBoardState.board_reg_out |= (1 << 2);
|
||||
else if (ch_num == 3)
|
||||
currentBoardState.board_reg_out |= (1 << 3);
|
||||
}
|
||||
else{ //Attenuator relay off for lower v/divs
|
||||
if (ch_num == 0)
|
||||
currentBoardState.board_reg_out &= ~(1 << 0);
|
||||
else if (ch_num == 1)
|
||||
currentBoardState.board_reg_out &= ~(1 << 1);
|
||||
else if (ch_num == 2)
|
||||
currentBoardState.board_reg_out &= ~(1 << 2);
|
||||
else if (ch_num == 3)
|
||||
currentBoardState.board_reg_out &= ~(1 << 3);
|
||||
}
|
||||
|
||||
if (vdiv == 10000 || vdiv == 100){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x0A;
|
||||
}
|
||||
else if (vdiv == 5000 || vdiv == 50){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x07;
|
||||
}
|
||||
else if (vdiv == 2000 || vdiv == 20){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x03;
|
||||
}
|
||||
else if (vdiv == 1000 || vdiv == 10){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x1A;
|
||||
}
|
||||
else if (vdiv == 500 || vdiv == 5){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x17;
|
||||
}
|
||||
else if (vdiv == 200 || vdiv == 2){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x13;
|
||||
}
|
||||
else if (vdiv == 1){
|
||||
currentBoardState.pga[ch_num][3] &= 0xE0;
|
||||
currentBoardState.pga[ch_num][3] |= 0x10;
|
||||
}
|
||||
|
||||
_Write32(user_handle,BOARD_REG_OUT,currentBoardState.board_reg_out);
|
||||
_FIFO_WRITE(user_handle,currentBoardState.pga[ch_num],sizeof(currentBoardState.pga[ch_num]));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PCIeLink::_voffset_set(int ch_num, double voffset){
|
||||
unsigned int dac_value = (unsigned int)round((voffset + 0.5) * 4095);
|
||||
|
||||
currentBoardState.dac[ch_num][4] = (unsigned char)(0xFF & dac_value);
|
||||
currentBoardState.dac[ch_num][3] = (unsigned char)(0x0F & (dac_value >> 8));
|
||||
|
||||
_FIFO_WRITE(user_handle,currentBoardState.dac[ch_num],sizeof(currentBoardState.dac[ch_num]));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PCIeLink::_bw_set(int ch_num, int bw){
|
||||
if (bw == 20){
|
||||
currentBoardState.pga[ch_num][3] &= 0x1F;
|
||||
currentBoardState.pga[ch_num][3] |= 0x40;
|
||||
}
|
||||
else if (bw == 100){
|
||||
currentBoardState.pga[ch_num][3] &= 0x1F;
|
||||
currentBoardState.pga[ch_num][3] |= 0x80;
|
||||
}
|
||||
else if (bw == 200){
|
||||
currentBoardState.pga[ch_num][3] &= 0x1F;
|
||||
currentBoardState.pga[ch_num][3] |= 0xC0;
|
||||
}
|
||||
else if (bw == 350){
|
||||
currentBoardState.pga[ch_num][3] &= 0x1F;
|
||||
}
|
||||
|
||||
_FIFO_WRITE(user_handle,currentBoardState.pga[ch_num],sizeof(currentBoardState.pga[ch_num]));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PCIeLink::_adc_ch_cfg(){
|
||||
unsigned char cmd_temp [4];
|
||||
int i;
|
||||
|
||||
if (currentBoardState.num_ch_on == 0){
|
||||
return 1;
|
||||
}
|
||||
else if (currentBoardState.num_ch_on == 1) {
|
||||
currentBoardState.adc_chnum_clkdiv[3] = 0x01;
|
||||
currentBoardState.adc_chnum_clkdiv[2] = 0x00;
|
||||
|
||||
for (i=0; !currentBoardState.ch_is_on[i]; i++); //Find channel that is on
|
||||
|
||||
currentBoardState.adc_in_sel_12[3] = (2 << i); //Set all 4 ADCs to sample that channel
|
||||
currentBoardState.adc_in_sel_12[2] = (2 << i);
|
||||
currentBoardState.adc_in_sel_34[3] = (2 << i);
|
||||
currentBoardState.adc_in_sel_34[2] = (2 << i);
|
||||
currentBoardState.datamover_reg_out &= ~(0xF0);
|
||||
} else if (currentBoardState.num_ch_on == 2){
|
||||
currentBoardState.adc_chnum_clkdiv[3] = 0x02;
|
||||
currentBoardState.adc_chnum_clkdiv[2] = 0x01;
|
||||
|
||||
for (i=0; !currentBoardState.ch_is_on[i]; i++); //Find first on channel
|
||||
|
||||
currentBoardState.adc_in_sel_12[3] = (2 << i); //Set 2 ADCs to sample first channel
|
||||
currentBoardState.adc_in_sel_12[2] = (2 << i);
|
||||
|
||||
for (; !currentBoardState.ch_is_on[i]; i++); //Find second on channel
|
||||
|
||||
currentBoardState.adc_in_sel_34[3] = (2 << i); //Set 2 ADCs to sample second channel
|
||||
currentBoardState.adc_in_sel_34[2] = (2 << i);
|
||||
|
||||
currentBoardState.datamover_reg_out &= ~(0xF0);
|
||||
currentBoardState.datamover_reg_out |= 0x10;
|
||||
} else {
|
||||
currentBoardState.adc_chnum_clkdiv[3] = 0x04;
|
||||
currentBoardState.adc_chnum_clkdiv[2] = 0x02;
|
||||
currentBoardState.adc_in_sel_12[3] = (2 << 0); //Set each ADC to sample one channel
|
||||
currentBoardState.adc_in_sel_12[2] = (2 << 1);
|
||||
currentBoardState.adc_in_sel_34[3] = (2 << 2);
|
||||
currentBoardState.adc_in_sel_34[2] = (2 << 3);
|
||||
currentBoardState.datamover_reg_out &= ~(0xF0);
|
||||
currentBoardState.datamover_reg_out |= 0x30;
|
||||
}
|
||||
|
||||
|
||||
_adc_power_down();
|
||||
|
||||
_FIFO_WRITE(user_handle,currentBoardState.adc_chnum_clkdiv,sizeof(currentBoardState.adc_chnum_clkdiv));
|
||||
|
||||
_adc_active();
|
||||
|
||||
_FIFO_WRITE(user_handle,currentBoardState.adc_in_sel_12,sizeof(currentBoardState.adc_in_sel_12));
|
||||
_FIFO_WRITE(user_handle,currentBoardState.adc_in_sel_34,sizeof(currentBoardState.adc_in_sel_34));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PCIeLink::_adc_power_down() {
|
||||
uint8_t power_down_bytes[4] = {0xFD,0x0F,0x02,0x00};
|
||||
_FIFO_WRITE(user_handle,power_down_bytes,sizeof(power_down_bytes));
|
||||
}
|
||||
|
||||
void PCIeLink::_adc_active() {
|
||||
uint8_t adc_active_bytes[4] = {0xFD,0x0F,0x00,0x00};
|
||||
_FIFO_WRITE(user_handle,adc_active_bytes,sizeof(adc_active_bytes));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -436,8 +436,8 @@ int Bridge::InitTxBridge() {
|
||||
// pipe already exists...
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1,
|
||||
4096 * 16,
|
||||
4096 * 16,
|
||||
4096 * 4096 * 16,
|
||||
4096 * 4096 * 16,
|
||||
NMPWAIT_USE_DEFAULT_WAIT,
|
||||
NULL);
|
||||
|
||||
@ -503,8 +503,8 @@ int Bridge::InitRxBridge() {
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE |
|
||||
PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1,
|
||||
4096 * 16,
|
||||
4096 * 16,
|
||||
4096 * 4096 * 16,
|
||||
4096 * 4096 * 16,
|
||||
NMPWAIT_USE_DEFAULT_WAIT,
|
||||
NULL);
|
||||
|
||||
|
@ -69,6 +69,7 @@ controller::~controller()
|
||||
delete processorThread;
|
||||
delete postProcessorThread;
|
||||
delete bridgeThread;
|
||||
delete pcieLinkThread;
|
||||
|
||||
DEBUG << "Controller Destroyed";
|
||||
}
|
||||
@ -408,7 +409,7 @@ void controller::controllerLoop()
|
||||
}
|
||||
|
||||
//Sleep, but don't oversleep
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(250));
|
||||
}
|
||||
}
|
||||
|
||||
@ -815,3 +816,69 @@ void controller::setFileName(int8_t newFile)
|
||||
free(inputFile);
|
||||
inputFile = filename;
|
||||
}
|
||||
|
||||
void controller::hardWareCommand(int command, int channel, int val1, double val2) {
|
||||
ScopeCommand cmd = static_cast<ScopeCommand>(command);
|
||||
|
||||
switch(cmd) {
|
||||
case init_board:
|
||||
|
||||
break;
|
||||
case adc_enable_ramp_test:
|
||||
|
||||
break;
|
||||
case dataMover_enable:
|
||||
|
||||
break;
|
||||
case dataMover_disable:
|
||||
|
||||
break;
|
||||
case test_write:
|
||||
|
||||
break;
|
||||
case enable_channel:
|
||||
pcieLinkThread->Write(cmd,(void*)&channel);
|
||||
break;
|
||||
case disable_channel:
|
||||
pcieLinkThread->Write(cmd,(void*)&channel);
|
||||
break;
|
||||
case ac_couple:
|
||||
pcieLinkThread->Write(cmd,(void*)&channel);
|
||||
break;
|
||||
case dc_couple:
|
||||
pcieLinkThread->Write(cmd,(void*)&channel);
|
||||
break;
|
||||
case voltage_divison_set:
|
||||
{
|
||||
VoltageDivSetParam param;
|
||||
param.ch_num = channel;
|
||||
param.voltage_div = val1;
|
||||
pcieLinkThread->Write(cmd,(void*)¶m);
|
||||
}
|
||||
break;
|
||||
case voltage_offset_set:
|
||||
{
|
||||
VoltageOffsetParam param;
|
||||
param.ch_num = channel;
|
||||
param.voltage = val2;
|
||||
pcieLinkThread->Write(cmd,(void*)¶m);
|
||||
}
|
||||
break;
|
||||
case bandwidth_set:
|
||||
{
|
||||
BandwidthSetParam param;
|
||||
param.ch_num = channel;
|
||||
param.bw = val1;
|
||||
pcieLinkThread->Write(cmd,(void*)¶m);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void controller::testADCData() {
|
||||
pcieLinkThread->Write(test_adc_data,nullptr);
|
||||
}
|
@ -407,6 +407,9 @@ void runCli() {
|
||||
|
||||
parseThings = parseCli(line);
|
||||
}
|
||||
|
||||
if(controllerThread != NULL)
|
||||
delete controllerThread;
|
||||
}
|
||||
int main(int argc, char** args)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user