FSUDAQ/ClassDigitizer.cpp
2022-10-06 15:49:08 -04:00

905 lines
42 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ClassDigitizer.h"
Digitizer::Digitizer(){
Initalization();
}
Digitizer::Digitizer(int boardID, int portID, bool program, bool verbose){
Initalization();
OpenDigitizer(boardID, portID, program, verbose);
}
Digitizer::~Digitizer(){
delete data;
delete settingFile;
CloseDigitizer();
}
void Digitizer::Initalization(){
portID = -1;
boardID = -1;
handle = -1;
NChannel = 0;
ADCbits = 1;
DPPType = 0;
DPPTypeStr = "";
ADCFullSize = 0;
ch2ns = 0;
BoardInfo = {};
VMEBaseAddress = 0;
LinkType = CAEN_DGTZ_USB; /// default USB
IOlev = CAEN_DGTZ_IOLevel_NIM; ///default NIM
AcqMode = CAEN_DGTZ_DPP_ACQ_MODE_List; ///default list mode
channelMask = 0xFFFF;
data = new Data();
isSettingFilledinMemeory = false;
settingFileName = "";
settingFileExist = false;
settingFile = NULL;
ret = -1;
isConnected = false;
AcqRun = false;
}
void Digitizer::Reset(){
ret = CAEN_DGTZ_Reset(handle);
if( ret != 0 ) ErrorMsg(__func__);
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::SoftwareClear_W, 1);
if( ret != 0 ) ErrorMsg("Reset-SoftwareClear_W");
}
void Digitizer::PrintBoard(){
printf("Connected to Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link");
printf("Sampling rate : %.0f MHz = %.1f ns \n", 1000/ch2ns, ch2ns);
printf("Number of Channels : %d = 0x%X\n", NChannel, channelMask);
printf("SerialNumber :\e[1m\e[33m %d\e[0m\n", BoardInfo.SerialNumber);
printf("DPPType : %d (%s)\n", DPPType, DPPTypeStr.c_str());
printf("ADC bit is \e[33m%d\e[0m, %d = 0x%X\n", ADCbits, ADCFullSize, ADCFullSize);
printf("ROC FPGA Release is %s\n", BoardInfo.ROC_FirmwareRel);
printf("AMC FPGA Release is %s\n", BoardInfo.AMC_FirmwareRel);
}
int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose){
this->boardID = boardID;
this->portID = portID;
/***************************************************/
/** Open the digitizer and read board information */
/***************************************************/
if( verbose) printf("============= Opening Digitizer at Board %d, Port %d \n", boardID, portID);
///-------- try USB first
LinkType = CAEN_DGTZ_USB; /// Link Type
ret = (int) CAEN_DGTZ_OpenDigitizer(LinkType, boardID, 0, VMEBaseAddress, &handle);
if (ret != 0){ ///---------- try Optical link
LinkType = CAEN_DGTZ_OpticalLink ;
ret = (int) CAEN_DGTZ_OpenDigitizer(LinkType, portID, boardID, VMEBaseAddress, &handle);
}
if (ret != 0) {
if( verbose) printf("Can't open digitizer\n");
return -1;
}else{
///----- Getting Board Info
ret = (int) CAEN_DGTZ_GetInfo(handle, &BoardInfo);
if (ret != 0) {
if( verbose) printf("Can't read board info\n");
}else{
isConnected = true;
NChannel = BoardInfo.Channels;
channelMask = pow(2, NChannel)-1;
switch(BoardInfo.Model){
case CAEN_DGTZ_V1730: ch2ns = 2.0; break; ///ns -> 500 MSamples/s
case CAEN_DGTZ_V1725: ch2ns = 4.0; break; ///ns -> 250 MSamples/s
}
data->ch2ns = ch2ns;
ADCbits = BoardInfo.ADC_NBits;
ADCFullSize = (unsigned int)( pow(2, ADCbits) -1 );
//SetBoardID(BoardInfo.SerialNumber);
}
}
///====================== Check DPP firmware revision
sscanf(BoardInfo.AMC_FirmwareRel, "%d", &DPPType);
data->DPPType = DPPType;
switch (DPPType){
case V1724_DPP_PHA_CODE: DPPTypeStr = "DPP-PHA x724"; break; /// 0x80
case V1720_DPP_CI_CODE : DPPTypeStr = "DPP-CI x720"; break; /// 0x82
case V1720_DPP_PSD_CODE: DPPTypeStr = "DPP-PSD x720"; break; /// 0x83
case V1751_DPP_PSD_CODE: DPPTypeStr = "DPP-PSD x751"; break; /// 0x84
case V1751_DPP_ZLE_CODE: DPPTypeStr = "DPP-ZLE x751"; break; /// 0x85
case V1743_DPP_CI_CODE: DPPTypeStr = "DPP-PSD x743"; break; /// 0x86
case V1740_DPP_QDC_CODE: DPPTypeStr = "DPP-QDC x740"; break; /// 0x87
case V1730_DPP_PSD_CODE: DPPTypeStr = "DPP-PSD x730"; break; /// 0x88
case V1730_DPP_PHA_CODE: DPPTypeStr = "DPP-PHA x730"; break; /// 0x8B
case V1730_DPP_ZLE_CODE: DPPTypeStr = "DPP-ZLE x730"; break; /// 0x8C
case V1730_DPP_DAW_CODE: DPPTypeStr = "DPP-DAW x730"; break; /// 0x8D
}
if ( verbose ){
PrintBoard();
if (DPPType < 0x80 ) {
printf("This digitizer does not have DPP-PHA firmware\n");
}else {
printf("\t==== This digitizer has a DPP firmware!\n");
printf("\e[32m\t %s \e[0m", DPPTypeStr.c_str());
}
}
///======================= Check virtual probe
int probes[MAX_SUPPORTED_PROBES];
int numProbes;
ret = CAEN_DGTZ_GetDPP_SupportedVirtualProbes(handle, 1, probes, &numProbes);
if( verbose ){
printf("\t==== supported virtual probe (number of Probe : %d)\n", numProbes);
for( int i = 0 ; i < numProbes; i++){
switch (probes[i]){
case 0: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Input\n"); break;
case 1: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Delta\n"); break;
case 2: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Delta2\n"); break;
case 3: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Trapezoid\n"); break;
case 4: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_TrapezoidReduced\n"); break;
case 5: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Baseline\n"); break;
case 6: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Threshold\n"); break;
case 7: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_CFD\n"); break;
case 8: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_SmoothedInput\n"); break;
case 9: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_None\n"); break;
case 10: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGWin\n"); break;
case 11: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Armed\n"); break;
case 12: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PkRun\n"); break;
case 13: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Peaking\n"); break;
case 14: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_CoincWin\n"); break;
case 15: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BLHoldoff\n"); break;
case 16: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGHoldoff\n"); break;
case 17: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGVal\n"); break;
case 18: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_ACQVeto\n"); break;
case 19: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BFMVeto\n"); break;
case 20: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_ExtTRG\n"); break;
case 21: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_OverThr\n"); break;
case 22: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGOut\n"); break;
case 23: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Coincidence \n"); break;
case 24: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PileUp \n"); break;
case 25: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Gate \n"); break;
case 26: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_GateShort \n"); break;
case 27: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Trigger \n"); break;
case 28: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_None \n"); break;
case 29: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BLFreeze \n"); break;
case 30: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Busy \n"); break;
case 31: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PrgVeto \n"); break;
}
}
}
ErrorMsg("end of OpenDigitizer");
if( isConnected && program) {
ProgramBoard();
}
if( isConnected ) FillAllSettings();
return ret;
}
int Digitizer::CloseDigitizer(){
if( !isConnected ) return 0;
isConnected = false;
printf("-------- Closing Digtizer Board : %d Port : %d \n", boardID, portID);
printf(" Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link");
ret = CAEN_DGTZ_SWStopAcquisition(handle);
ret |= CAEN_DGTZ_CloseDigitizer(handle);
return ret;
}
void Digitizer::ErrorMsg(string header){
switch (ret){
///case CAEN_DGTZ_Success : /** 0 */ printf("%s | Operation completed successfully.\n", header.c_str()); break;
case CAEN_DGTZ_CommError : /** -1 */ printf("%s | Communication Error.\n", header.c_str()); break;
case CAEN_DGTZ_GenericError : /** -2 */ printf("%s | Unspecified error.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidParam : /** -3 */ printf("%s | Invalid parameter.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidLinkType : /** -4 */ printf("%s | Invalid Link Type.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidHandle : /** -5 */ printf("%s | Invalid device handler.\n", header.c_str()); break;
case CAEN_DGTZ_MaxDevicesError : /** -6 */ printf("%s | Maximum number of devices exceeded.\n", header.c_str()); break;
case CAEN_DGTZ_BadBoardType : /** -7 */ printf("%s | Operation not allowed on this type of board.\n", header.c_str()); break;
case CAEN_DGTZ_BadInterruptLev : /** -8 */ printf("%s | The interrupt level is not allowed.\n", header.c_str()); break;
case CAEN_DGTZ_BadEventNumber : /** -9 */ printf("%s | The event number is bad.\n", header.c_str()); break;
case CAEN_DGTZ_ReadDeviceRegisterFail : /** -10 */ printf("%s | Unable to read the registry.\n", header.c_str()); break;
case CAEN_DGTZ_WriteDeviceRegisterFail : /** -11 */ printf("%s | Unable to write the registry.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidChannelNumber : /** -13 */ printf("%s | The channel number is invalid.\n", header.c_str()); break;
case CAEN_DGTZ_ChannelBusy : /** -14 */ printf("%s | The channel is busy.\n", header.c_str()); break;
case CAEN_DGTZ_FPIOModeInvalid : /** -15 */ printf("%s | Invalid FPIO mode.\n", header.c_str()); break;
case CAEN_DGTZ_WrongAcqMode : /** -16 */ printf("%s | Wrong Acquistion mode.\n", header.c_str()); break;
case CAEN_DGTZ_FunctionNotAllowed : /** -17 */ printf("%s | This function is not allowed on this module.\n", header.c_str()); break;
case CAEN_DGTZ_Timeout : /** -18 */ printf("%s | Communication Timeout.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidBuffer : /** -19 */ printf("%s | The buffer is invalid.\n", header.c_str()); break;
case CAEN_DGTZ_EventNotFound : /** -20 */ printf("%s | The event is not found.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidEvent : /** -21 */ printf("%s | The event is invalid.\n", header.c_str()); break;
case CAEN_DGTZ_OutOfMemory : /** -22 */ printf("%s | Out of memory.\n", header.c_str()); break;
case CAEN_DGTZ_CalibrationError : /** -23 */ printf("%s | Unable to calibrate the board.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerNotFound : /** -24 */ printf("%s | Unbale to open the digitizer.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerAlreadyOpen : /** -25 */ printf("%s | The digitizer is already open.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerNotReady : /** -26 */ printf("%s | The digitizer is not ready.\n", header.c_str()); break;
case CAEN_DGTZ_InterruptNotConfigured : /** -27 */ printf("%s | The digitizer has no IRQ configured.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerMemoryCorrupted: /** -28 */ printf("%s | The digitizer flash memory is corrupted.\n", header.c_str()); break;
case CAEN_DGTZ_DPPFirmwareNotSupported : /** -29 */ printf("%s | The digitier DPP firmware is not supported in this lib version.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidLicense : /** -30 */ printf("%s | Invalid firmware licence.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidDigitizerStatus : /** -31 */ printf("%s | The digitizer is found in a corrupted status.\n", header.c_str()); break;
case CAEN_DGTZ_UnsupportedTrace : /** -32 */ printf("%s | The given trace is not supported.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidProbe : /** -33 */ printf("%s | The given probe is not supported.\n", header.c_str()); break;
case CAEN_DGTZ_UnsupportedBaseAddress : /** -34 */ printf("%s | The base address is not supported.\n", header.c_str()); break;
case CAEN_DGTZ_NotYetImplemented : /** -99 */ printf("%s | The function is not yet implemented.\n", header.c_str()); break;
}
}
int Digitizer::ProgramBoard(){
printf("----- program Board\n");
ret = CAEN_DGTZ_Reset(handle);
if (ret) {
printf("ERROR: can't reset the digitizer.\n");
return -1;
}
/// Board Configuration without PHA or PSD fireware
///bx0000 0000 0000 0000 0000 0000 0001 0000 =
/// | | +- (1) trigger overlap not allowed
/// | +- (3) test pattern disable
/// + (6) Self-trigger polarity, 1 = negative, 0 = Positive
ret = CAEN_DGTZ_WriteRegister(handle, (uint32_t) Register::BoardConfiguration , 0x000E0114); /// Channel Control Reg (indiv trg, seq readout) ??
/// Set the I/O level (CAEN_DGTZ_IOLevel_NIM or CAEN_DGTZ_IOLevel_TTL)
ret |= CAEN_DGTZ_SetIOLevel(handle, IOlev);
/// Set the enabled channels
ret |= CAEN_DGTZ_SetChannelEnableMask(handle, channelMask);
/// Set the number of samples for each waveform
SetRecordLength(2000); /// ns
/// Set Extras 2 to enable, this override Accusition mode, focring list mode
ret |= CAEN_DGTZ_WriteRegister(handle, Register::BoardConfiguration , 0x00E8114 );
/// Set the digitizer acquisition mode (CAEN_DGTZ_SW_CONTROLLED or CAEN_DGTZ_S_IN_CONTROLLED)
ret |= CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command
ret |= CAEN_DGTZ_SetDPPAcquisitionMode(handle, AcqMode, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime);
/** Set the digitizer's behaviour when an external trigger arrives:
CAEN_DGTZ_TRGMODE_DISABLED: do nothing
CAEN_DGTZ_TRGMODE_EXTOUT_ONLY: generate the Trigger Output signal
CAEN_DGTZ_TRGMODE_ACQ_ONLY = generate acquisition trigger
CAEN_DGTZ_TRGMODE_ACQ_AND_EXTOUT = generate both Trigger Output and acquisition trigger
see CAENDigitizer user manual, chapter "Trigger configuration" for details */
//TODO set bit
ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY);
ret |= CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled);
/// Set how many events to accumulate in the board memory before being available for readout
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::NumberEventsPerAggregate_G + 0x7000, 100);
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::AggregateOrganization, 0);
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::MaxAggregatePerBlockTransfer, 50);
ErrorMsg(__func__);
return ret;
}
//========================================================= ACQ control
void Digitizer::StartACQ(){
if ( AcqRun ) return;
ret = CAEN_DGTZ_SWStartAcquisition(handle);
if( ret != 0 ) {
ErrorMsg("Start ACQ");
return;
}
printf("\e[1m\e[33m======= Acquisition Started for Board %d\e[0m\n", boardID);
AcqRun = true;
}
void Digitizer::StopACQ(){
if( !AcqRun ) return;
int ret = CAEN_DGTZ_SWStopAcquisition(handle);
ret |= CAEN_DGTZ_ClearData(handle);
if( ret != 0 ) ErrorMsg("something wrong when try to stop ACQ and clear buffer");
printf("\n\e[1m\e[33m====== Acquisition STOPPED for Board %d\e[0m\n", boardID);
AcqRun = false;
}
unsigned int Digitizer::CalByteForBuffer(){
//TODO
unsigned int numAggBLT = ReadRegister(Register::DPP::MaxAggregatePerBlockTransfer);
/// Channel Mask
/// is takeing waveForm
/// Record Length
return 0;
}
void Digitizer::ReadData(){
if( !isConnected ) return;
if( data->buffer == NULL ) {
printf("need allocate memory for readout buffer\n");
return;
}
ret = CAEN_DGTZ_ReadData(handle, CAEN_DGTZ_SLAVE_TERMINATED_READOUT_MBLT, data->buffer, &(data->nByte));
//uint32_t EventSize = ReadRegister(Register::DPP::EventSize); // Is it as same as data->nByte?
//printf("Read Buffer size %d byte, Event Size : %d byte \n", data->nByte, EventSize);
if (ret || data->nByte == 0) {
ErrorMsg(__func__);
return;
}
}
//===========================================================
void Digitizer::WriteRegister(uint32_t registerAddress, uint32_t value, int ch ){
if( !isConnected ) return;
///printf("0x%X, 0x%X=%u, ch:%d\n", registerAddress, value, value, ch);
if( registerAddress == 0x8180){
if( ch < 0 ){
for( int i = 0; i < NChannel/2; i++){
ret = CAEN_DGTZ_WriteRegister(handle, registerAddress + 4*i, value);
ReadRegister(registerAddress, i);
}
}else{
ret = CAEN_DGTZ_WriteRegister(handle, registerAddress + 4*(ch/2), value);
ReadRegister(registerAddress, ch);
}
}else if( registerAddress < 0x8000){
if( ch < 0 ) {
ret = CAEN_DGTZ_WriteRegister(handle, registerAddress + 0x7000, value);
for( int i = 0; i < NChannel; i++) ReadRegister(registerAddress, i);
}else{
ret = CAEN_DGTZ_WriteRegister(handle, registerAddress + (ch<<8), value);
ReadRegister(registerAddress, ch);
}
}else{
ret = CAEN_DGTZ_WriteRegister(handle, registerAddress, value);
ReadRegister(registerAddress);
}
/// for grouped address
if( registerAddress == Register::DPP::RecordLength_G ||
registerAddress == Register::DPP::NumberEventsPerAggregate_G ||
registerAddress == Register::DPP::PHA::DPPAlgorithmControl2_G ||
registerAddress == Register::DPP::PSD::DPPAlgorithmControl2_G ||
registerAddress == Register::DPP::TriggerValidationMask_G
){
ReadRegister(registerAddress, ch + (ch%2 == 1 ? -1 : +1));
}
ErrorMsg("WriteRegister:" + std::to_string(registerAddress));
}
uint32_t Digitizer::ReadRegister(uint32_t registerAddress, int ch, string str ){
if( !isConnected ) return 0;
uint32_t actualAddress = registerAddress ;
if( registerAddress == 0x8180 ){
if( ch < 0 ) ch = 0;
actualAddress = registerAddress + 4*(ch/2);
}
if( registerAddress < 0x8000) {
if( ch >= 0 ) actualAddress = registerAddress + (ch << 8);
}
uint32_t data[1];
ret = CAEN_DGTZ_ReadRegister(handle, actualAddress, data);
if( ret == 0 ) SaveSettingToFile(registerAddress, data[0], ch);
ErrorMsg("ReadRegister:" + std::to_string(registerAddress));
if( str != "" ) printf("%s : 0x%04X(0x%04X) is 0x%08X \n", str.c_str(), actualAddress, registerAddress, data[0]);
return data[0];
}
void Digitizer::SetChannelMask(uint32_t mask){
if( !isConnected ) return;
channelMask = mask;
ret |= CAEN_DGTZ_SetChannelEnableMask(handle, channelMask);
SaveSettingToFile(Register::DPP::ChannelEnableMask, mask);
ErrorMsg(__func__);
}
void Digitizer::SetRecordLength(unsigned int ns, int ch){
WriteRegister( Register::DPP::RecordLength_G, ns / ch2ns / 8 , ch);
if( ch >= 0 ) WriteRegister( Register::DPP::RecordLength_G, ns / ch2ns / 8 , ch + int(pow(-1, ch)));
ErrorMsg(__func__);
}
void Digitizer::SetAggregateOrganization(unsigned int bit){
WriteRegister(Register::DPP::AggregateOrganization, bit & 0x7);
ErrorMsg(__func__);
}
void Digitizer::SetEventAggregation(unsigned int numEvent, int ch){
WriteRegister( Register::DPP::NumberEventsPerAggregate_G,numEvent, ch);
if( ch >= 0 ) WriteRegister( Register::DPP::NumberEventsPerAggregate_G,numEvent, ch + int(pow(-1, ch)));
ErrorMsg(__func__);
}
void Digitizer::SetMaxAggregatePerBlockTransfer(unsigned int numEvent){
WriteRegister( Register::DPP::MaxAggregatePerBlockTransfer,numEvent);
ErrorMsg(__func__);
}
void Digitizer::SetACQControl(uint32_t bit){
WriteRegister( Register::DPP::AcquisitionControl, bit);
ErrorMsg(__func__);
}
void Digitizer::SetGlobalTriggerMask(uint32_t bit){
WriteRegister( Register::DPP::GlobalTriggerMask, bit);
ErrorMsg(__func__);
}
void Digitizer::SetFrontPanelTRGOUTMask(uint32_t bit){
WriteRegister( Register::DPP::FrontPanelTRGOUTEnableMask, bit);
ErrorMsg(__func__);
}
void Digitizer::SetFrontPanelIOControl(uint32_t bit){
WriteRegister( Register::DPP::FrontPanelIOControl, bit);
ErrorMsg(__func__);
}
void Digitizer::SetTriggerValidationMask(uint32_t bit){
WriteRegister( Register::DPP::TriggerValidationMask_G, bit);
ErrorMsg(__func__);
}
void Digitizer::SetInputDynamicRange(unsigned int TwoVol_0_or_halfVol_1, int ch){ WriteRegister( Register::DPP::InputDynamicRange, TwoVol_0_or_halfVol_1, ch); ErrorMsg(__func__);}
void Digitizer::SetPreTriggerSample(unsigned int nSample, int ch) { WriteRegister( Register::DPP::PreTrigger, nSample / 4, ch); ErrorMsg(__func__);}
void Digitizer::SetPreTriggerDuration(unsigned int ns, int ch) { WriteRegister( Register::DPP::PreTrigger, ns / ch2ns / 4, ch); ErrorMsg(__func__);}
void Digitizer::SetDCOffset(float offsetPrecentage, int ch) { WriteRegister( Register::DPP::ChannelDCOffset, uint( 0xFFFF * (1.0-offsetPrecentage)), ch ); ErrorMsg(__func__);}
void Digitizer::SetVetoWidth(uint32_t bit, int ch) { WriteRegister( Register::DPP::VetoWidth, bit, ch); ErrorMsg(__func__);}
void Digitizer::SetTriggerPolarity(bool RiseingIsZero, int ch ){
if( !isConnected ) return;
if ( DPPType >= 128 ) return; /// do thing for DPP firmware
if( ch < 0 ) {
ret = 0;
for (int i = 0; i < NChannel; i++){
ret |= CAEN_DGTZ_SetTriggerPolarity(handle, i, CAEN_DGTZ_TriggerPolarity_t(RiseingIsZero));
}
}else{
ret = CAEN_DGTZ_SetTriggerPolarity(handle, ch, CAEN_DGTZ_TriggerPolarity_t(RiseingIsZero));
}
if( ret != 0 ) ErrorMsg(__func__);
}
//============================== DPP-Alpgorthm Control
void Digitizer::SetDPPAlgorithmControl(uint32_t bit, int ch){
///============= DPP algorithm control is 32 bit
/// [ 0: 5] Trapazoid Rescaling. the trapazoid ADC is 48 bit. it need to bit-shift before the 0x3FFF (14 bit filter)
/// [ 8: 9] Decimation. 00 = disable, 01 = 2 samples, 10 = 4 samples, 11 = 8 sample
/// [10:11] Decimation Gain. This gain apply to the Trapazoid Rescaling and fine gain
/// [12:13] Peak Mean. sample for averaging the trapezoid height calculation. 00 = 1 sample, 01 = 4 samples, 10 = 16 sample, 11 = 64 sample
/// [16] pulse polarity. 0 = positve, 1 = negative
/// [18:19] Trigger mode. 00 = normal, 01 = coincident, 10 = reserved. 11 = anti coincident
/// [20:22] number of samples for the baseline average calculation. 000 = baseline disable (energy not subtraced with baseline)
/// 001 = 16 samples
/// 010 = 64 samples
/// 011 = 256 samples
/// 100 = 1024 samples
/// 101 = 4096 samples
/// 110 = 16384 samples
/// 111 = resertved.
/// [24] Disable self trigger. 0 = selftrigger used to acquire and propagated to the trigger logic;
/// 1 = selftrigger only propagated to the trigger logic.
/// [26] Enable Roll-Over flag. see manual 0 = disable, 1 = enable
/// [27] Enable pile-up flag.
///============= PHA - DPP algorithm control 2 is 32 bit
/// [ 0: 1] Local Shaped Trigger mode. see manual
/// [ 2] Enable Local Shaped Trigger
/// [ 4: 5] Local Trigger Validation mode, see manual
/// [ 6] Enable Local Trigger Validation
/// [ 8:10] Extra 2 word option. 000 = [0:15] baseline *4 [16:31] extended time stamp
/// 001 = reserved
/// 010 = [0:15] fine time stamp [16:31] extended time stamp
/// 011 = reserved
/// 100 = [0:15] total tigger counter [16:31] Lost trigger counter
/// 101 = [0:15] event after the zero crosiing [16:31] event before zero crossing
/// 110, 111 = reserved.
/// [14:15] source of veto. 00 = disable, 01 veto is common to all channels, 10 = veto for coupled channels, 11 = veto comes from negative saturation
/// [16:17] Select the step for the trigger counter rate flag. see manual
/// [18] baseline calculation is active also when the acquisition is not running. 0 = disbale, 1 = enable
/// [19] Tag correlated events. see manual 0 = disbale, 1 = enable
/// [29] Enable the optimization of the Baseline Restorer to avoid tails in the energy peaks. 0 = disbale, 1 = enable
WriteRegister( Register::DPP::DPPAlgorithmControl, bit, ch);
if( ret != 0 ) ErrorMsg(__func__);
}
unsigned int Digitizer::ReadBits(uint32_t address, unsigned int bitLength, unsigned int bitSmallestPos, int ch ){
int tempCh = ch;
if (ch < 0 && address < 0x8000 ) tempCh = 0; /// take ch-0
uint32_t bit = ReadRegister(address, tempCh);
bit = (bit >> bitSmallestPos ) & uint(pow(2, bitLength)-1);
return bit;
}
void Digitizer::SetBits(uint32_t address, unsigned int bitValue, unsigned int bitLength, unsigned int bitSmallestPos, int ch){
///printf("address : 0x%X, value : 0x%X, len : %d, pos : %d, ch : %d \n", address, bitValue, bitLength, bitSmallestPos, ch);
uint32_t bit ;
uint32_t bitmask = (uint(pow(2, bitLength)-1) << bitSmallestPos);
int tempCh = ch;
if (ch < 0 && address < 0x8000 ) tempCh = 0; /// take ch-0
bit = ReadRegister(address, tempCh);
///printf("bit : 0x%X, bitmask : 0x%X \n", bit, bitmask);
bit = (bit & ~bitmask) | (bitValue << bitSmallestPos);
///printf("bit : 0x%X, ch : %d \n", bit, ch);
WriteRegister(address, bit, ch);
if( ret != 0 ) ErrorMsg(__func__);
}
int Digitizer::GetChTemperature(int ch){
if( !isConnected ) return -404;
if( BoardInfo.Model != CAEN_DGTZ_V1730 &&
BoardInfo.Model != CAEN_DGTZ_V1725 &&
BoardInfo.Model != CAEN_DGTZ_V1751 ) return -404;
uint32_t * temp;
ret |= CAEN_DGTZ_ReadTemperature(handle, ch, temp);
if( ret != 0 ) ErrorMsg(__func__);
return temp[0];
}
uint32_t Digitizer::PrintRegister(uint32_t address, std::string msg){
if( !isConnected ) return 0 ;
printf("\e[33m----------------------------------------------------\n");
printf("------------ %s = 0x%X \n", msg.c_str(), address);
printf("----------------------------------------------------\e[0m\n");
uint32_t * value = new uint32_t[1];
CAEN_DGTZ_ReadRegister(handle, address, value);
printf(" %*s 32 28 24 20 16 12 8 4 0\n", (int) msg.length(), "");
printf(" %*s | | | | | | | | |\n", (int) msg.length(), "");
printf(" %*s", (int) msg.length(), "");
cout << " : 0b" << bitset<32>(value[0]) << endl;
printf(" %*s : 0x%X\n", (int) msg.length(), msg.c_str(), value[0]);
return value[0];
}
void Digitizer::PrintACQStatue(){
if( !isConnected ) return;
unsigned int status = ReadRegister(Register::DPP::AcquisitionStatus_R);
printf("=================== Print ACQ status \n");
printf(" 32 28 24 20 16 12 8 4 0\n");
printf(" | | | | | | | | |\n");
cout <<" 0b" << bitset<32>(status) << endl;
printf(" Acq state (0x%1X): %s \n", (status >> 2) & 0x1, ((status >> 2) & 0x1) == 0? "stopped" : "running");
printf(" Event Ready (0x%1X): %s \n", (status >> 3) & 0x1, ((status >> 3) & 0x1) == 0? "no event in buffer" : "event in buffer");
printf(" Event Full (0x%1X): %s \n", (status >> 4) & 0x1, ((status >> 4) & 0x1) == 0? "not full" : "full");
printf(" Clock source (0x%1X): %s \n", (status >> 5) & 0x1, ((status >> 5) & 0x1) == 0? "internal" : "external");
printf(" Board ready (0x%1X): %s \n", (status >> 8) & 0x1, ((status >> 8) & 0x1) == 0? "not ready" : "ready");
printf(" Ch shutDown (0x%1X): %s \n", (status >> 19) & 0x1, ((status >> 19) & 0x1) == 0? "Channels are on" : "channels are shutdown");
printf(" TRG-IN 0x%1X \n", (status >> 16) & 0x1);
printf(" Ch temp state 0x%04X \n", (status >> 20) & 0xF);
}
//=====================================================
int Digitizer::ProgramPHABoard(){
ret = CAEN_DGTZ_Reset(handle);
printf("======== program board PHA\n");
ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::RecordLength_G + 0x7000, 250);
ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardConfiguration, 0x0F8115);
//TODO change to write register
ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command
ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM);
ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY);
ret = CAEN_DGTZ_SetChannelEnableMask(handle, 0xFFFF);
//ret = CAEN_DGTZ_SetNumEventsPerAggregate(handle, 0);
ret = CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled);
if( ret != 0 ) { printf("==== set board error.\n"); return 0;}
printf("======== program Channels PHA\n");
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::DecayTime + 0x7000 , 5000 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TrapezoidFlatTop + 0x7000 , 0x62 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TrapezoidRiseTime + 0x7000 , 6 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::PeakingTime + 0x7000 , 6 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::RCCR2SmoothingFactor + 0x7000 , 4 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::InputRiseTime + 0x7000 , 6 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TriggerThreshold + 0x7000 , 1000 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::PeakHoldOff + 0x7000 , 0x3E );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TriggerHoldOffWidth + 0x7000 , 0x3E );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::RiseTimeValidationWindow + 0x7000 , 0x0 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::ChannelDCOffset + 0x7000 , 0xEEEE );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PreTrigger + 0x7000 , 124 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::InputDynamicRange + 0x7000 , 0x0 );
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::NumberEventsPerAggregate_G + 0x7000, 100);
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::AggregateOrganization, 0);
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::MaxAggregatePerBlockTransfer, 40);
ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::DPPAlgorithmControl + 0x7000, 0xe30200f);
if( ret != 0 ) { printf("==== set channels error.\n"); return 0;}
printf("End of program board and channels\n");
isSettingFilledinMemeory = false;
FillAllSettings();
return ret;
}
//========================================== setting file IO
unsigned short Digitizer::CalSettingIndex(uint32_t registerAddress, int ch){
unsigned short index;
uint32_t newAddress;
if( registerAddress == 0x8180){
///if( ch%2 ==1 ) return 0xFFFF;
newAddress = registerAddress + 4*(ch/2);
index = (newAddress & 0x0FFF) / 4;
}else if( registerAddress < 0x8000){
if( ch < 0 ) ch = 0;
newAddress = registerAddress + (ch << 8);
index = newAddress / 4;
}else{
newAddress = registerAddress;
index = (newAddress & 0x0FFF) / 4;
}
//printf("---------address : 0x%04X = %5d = index : %6.1f (%d)\n", newAddress, newAddress, (newAddress & 0x0FFF) / 4., index);
return index;
}
void Digitizer::FillSetting(uint32_t registerAddress, int ch){
unsigned short index = CalSettingIndex(registerAddress, ch);
if( index > SETTINGSIZE ) return;
//if( setting[index] != 0 ) printf("##############################\n");
setting[index] = ReadRegister(registerAddress, ch);
}
void Digitizer::SetSettingToMemory(uint32_t registerAddress, unsigned int value, int ch ){
unsigned short index = CalSettingIndex(registerAddress, ch);
if( index > SETTINGSIZE ) return;
setting[index] = value;
}
unsigned int Digitizer::GetSettingFromMemory(uint32_t registerAddress, int ch ){
unsigned short index = CalSettingIndex(registerAddress, ch);
if( index > SETTINGSIZE ) return 0xFFFF;
return setting[index] ;
}
void Digitizer::FillAllSettings(){
/// for 1 digitizer, 16 channels, needs 0x10XX to 0x1FXX
/// Board setting is 0x8000 --> 0x0000
/// Saved date YYYYMMDDHH --> 0x0004
/// Global Trigger Mask 0x810C --> 0x010C
/// Channel mask 0x8120 --> 0x0120
/// ROM Board version 0xF030 --> 0x0030
/// Board Form factor 0xF034 --> 0x0034
/// Board ID Byte 1 0xF038 --> 0x0038
/// Board ID Byte 0 0xF03C --> 0x003C
/// Board Serial Num Byte1 0xF080 --> 0x0080
/// Board Serial Num Byte0 0xF084 --> 0x0084 /// serial number = byte0 << 8 + byte1
/// ROC fireware version is 0x8124 --> 0x0124
/// Board Info is 0x8140 --> 0x0140
/// -------------------------------------
/// for 1 channel is 0x2000 = 8192 byte should be enough for all setting for 1 board
if( isSettingFilledinMemeory) return;
for( int ch = 0; ch < NChannel; ch ++){
FillSetting(Register::DPP::RecordLength_G , ch); /// 0x1020; /// R/W
FillSetting(Register::DPP::InputDynamicRange , ch); /// 0x1028; /// R/W
FillSetting(Register::DPP::NumberEventsPerAggregate_G , ch); /// 0x1034; /// R/W
FillSetting(Register::DPP::PreTrigger , ch); /// 0x1038; /// R/W
FillSetting(Register::DPP::DPPAlgorithmControl , ch); /// 0x1080; /// R/W
FillSetting(Register::DPP::ChannelStatus_R , ch); /// 0x1088; /// R
FillSetting(Register::DPP::AMCFirmwareRevision_R , ch); /// 0x108C; /// R
FillSetting(Register::DPP::ChannelDCOffset , ch); /// 0x1098; /// R/W
FillSetting(Register::DPP::ChannelADCTemperature_R , ch); /// 0x10A8; /// R
FillSetting(Register::DPP::VetoWidth , ch); /// 0x10D4; /// R/W
if( DPPType == V1730_DPP_PHA_CODE ){
FillSetting(Register::DPP::PHA::ChannelStopAcquisition , ch); /// 0x1040; /// R/W not sure
FillSetting(Register::DPP::PHA::RCCR2SmoothingFactor , ch); /// 0x1054; /// R/W Trigger Filter smoothing, triggerSmoothingFactor
FillSetting(Register::DPP::PHA::InputRiseTime , ch); /// 0x1058; /// R/W OK
FillSetting(Register::DPP::PHA::TrapezoidRiseTime , ch); /// 0x105C; /// R/W OK
FillSetting(Register::DPP::PHA::TrapezoidFlatTop , ch); /// 0x1060; /// R/W OK
FillSetting(Register::DPP::PHA::PeakingTime , ch); /// 0x1064; /// R/W OK
FillSetting(Register::DPP::PHA::DecayTime , ch); /// 0x1068; /// R/W OK
FillSetting(Register::DPP::PHA::TriggerThreshold , ch); /// 0x106C; /// R/W OK
FillSetting(Register::DPP::PHA::RiseTimeValidationWindow, ch); /// 0x1070; /// R/W OK
FillSetting(Register::DPP::PHA::TriggerHoldOffWidth , ch); /// 0x1074; /// R/W OK
FillSetting(Register::DPP::PHA::PeakHoldOff , ch); /// 0x1078; /// R/W OK
FillSetting(Register::DPP::PHA::ShapedTriggerWidth , ch); /// 0x1084; /// R/W not sure
FillSetting(Register::DPP::PHA::DPPAlgorithmControl2_G , ch); /// 0x10A0; /// R/W OK
FillSetting(Register::DPP::PHA::FineGain , ch); /// 0x10C4; /// R/W OK
}
if( DPPType == V1730_DPP_PSD_CODE ){
FillSetting(Register::DPP::PSD::CFDSetting , ch); /// 0x103C; /// R/W
FillSetting(Register::DPP::PSD::ChargeZeroSuppressionThreshold, ch); /// 0x1044; /// R/W
FillSetting(Register::DPP::PSD::ShortGateWidth , ch); /// 0x1054; /// R/W
FillSetting(Register::DPP::PSD::LongGateWidth , ch); /// 0x1058; /// R/W
FillSetting(Register::DPP::PSD::GateOffset , ch); /// 0x105C; /// R/W
FillSetting(Register::DPP::PSD::TriggerThreshold , ch); /// 0x1060; /// R/W
FillSetting(Register::DPP::PSD::FixedBaseline , ch); /// 0x1064; /// R/W
FillSetting(Register::DPP::PSD::TriggerLatency , ch); /// 0x106C; /// R/W
FillSetting(Register::DPP::PSD::ShapedTriggerWidth , ch); /// 0x1070; /// R/W
FillSetting(Register::DPP::PSD::TriggerHoldOffWidth , ch); /// 0x1074; /// R/W
FillSetting(Register::DPP::PSD::ThresholdForPSDCut , ch); /// 0x1078; /// R/W
FillSetting(Register::DPP::PSD::PurGapThreshold , ch); /// 0x107C; /// R/W
FillSetting(Register::DPP::PSD::DPPAlgorithmControl2_G , ch); /// 0x1084; /// R/W
FillSetting(Register::DPP::PSD::EarlyBaselineFreeze , ch); /// 0x10D8; /// R/W
}
FillSetting(Register::DPP::TriggerValidationMask_G, ch); /// 0x8180; /// R/W, 0x8180 + 4n
}
FillSetting(Register::DPP::BoardConfiguration ); /// 0x8000; /// R/W
FillSetting(Register::DPP::AggregateOrganization ); /// 0x800C; /// R/W
FillSetting(Register::DPP::AcquisitionControl ); /// 0x8100; /// R/W
FillSetting(Register::DPP::AcquisitionStatus_R ); /// 0x8104; /// R
FillSetting(Register::DPP::GlobalTriggerMask ); /// 0x810C; /// R/W
FillSetting(Register::DPP::FrontPanelTRGOUTEnableMask ); /// 0x8110; /// R/W
FillSetting(Register::DPP::LVDSIOData ); /// 0x8118; /// R/W
FillSetting(Register::DPP::FrontPanelIOControl ); /// 0x811C; /// R/W
FillSetting(Register::DPP::ChannelEnableMask ); /// 0x8120; /// R/W
FillSetting(Register::DPP::ROCFPGAFirmwareRevision_R ); /// 0x8124; /// R
FillSetting(Register::DPP::EventStored_R ); /// 0x812C; /// R
FillSetting(Register::DPP::VoltageLevelModeConfig ); /// 0x8138; /// R/W
FillSetting(Register::DPP::BoardInfo_R ); /// 0x8140; /// R /// [0:7] 0x0E = 725, 0x0B = 730, [8:15] 0x01 = 640 kSample, 0x08 = 5.12 MSample, [16:23] channel number
FillSetting(Register::DPP::AnalogMonitorMode ); /// 0x8144; /// R/W
FillSetting(Register::DPP::EventSize_R ); /// 0x814C; /// R
FillSetting(Register::DPP::TimeBombDowncounter_R ); /// 0x8158; /// R
FillSetting(Register::DPP::FanSpeedControl ); /// 0x8168; /// R/W
FillSetting(Register::DPP::RunStartStopDelay ); /// 0x8170; /// R/W
FillSetting(Register::DPP::BoardFailureStatus_R ); /// 0x8178; /// R
FillSetting(Register::DPP::DisableExternalTrigger ); /// 0x817C; /// R/W
FillSetting(Register::DPP::FrontPanelLVDSIONewFeatures ); /// 0x81A0; /// R/W
FillSetting(Register::DPP::BufferOccupancyGain ); /// 0x81B4; /// R/W
FillSetting(Register::DPP::ExtendedVetoDelay ); /// 0x81C4; /// R/W
FillSetting(Register::DPP::ReadoutControl ); /// 0xEF00; /// R/W
FillSetting(Register::DPP::ReadoutStatus_R ); /// 0xEF04; /// R
FillSetting(Register::DPP::BoardID ); /// 0xEF08; /// R/W /// Geo address on VME crate
FillSetting(Register::DPP::MCSTBaseAddressAndControl ); /// 0xEF0C; /// R/W
FillSetting(Register::DPP::RelocationAddress ); /// 0xEF10; /// R/W
FillSetting(Register::DPP::InterruptStatusID ); /// 0xEF14; /// R/W
FillSetting(Register::DPP::InterruptEventNumber ); /// 0xEF18; /// R/W
FillSetting(Register::DPP::MaxAggregatePerBlockTransfer); /// 0xEF1C; /// R/W
FillSetting(Register::DPP::Scratch ); /// 0xEF20; /// R/W
isSettingFilledinMemeory = true;
}
void Digitizer::PrintSettingFromMemory(){
for( int i = 0; i < SETTINGSIZE; i++) printf("%4d | 0x%04X |0x%08X = %u \n", i, i*4, setting[i], setting[i]);
}
void Digitizer::OpenSettingBinary(string fileName){
settingFile = NULL;
this->settingFileName = fileName;
settingFile = fopen(fileName.c_str(), "r+");
if( settingFile == NULL ){
printf("cannot open file %s. \n", fileName.c_str());
CreateAndSaveSettingToFile(fileName);
}else{
settingFileExist = true;
printf("setting file already exist.\n");
}
}
void Digitizer::CreateAndSaveSettingToFile(string fileName){
settingFileName = fileName;
settingFile = fopen(settingFileName.c_str(), "w+");
if( isSettingFilledinMemeory == false) FillAllSettings();
fwrite(setting, SETTINGSIZE * sizeof(unsigned int), 1, settingFile);
fseek(settingFile, 0L, SEEK_END);
unsigned int inFileSize = ftell(settingFile);
printf("Created file : %s. file size : %d Byte\n", settingFileName.c_str(), inFileSize);
fclose (settingFile);
settingFileExist = true;
}
void Digitizer::LoadSettingBinary(string fileName){
settingFileName = fileName;
settingFile = fopen(settingFileName.c_str(), "r");
if( settingFile == NULL ) {
printf(" %s does not exist.\n", fileName.c_str());
settingFileExist = false;
return;
}else{
settingFileExist = true;
size_t dummy = fread( setting, SETTINGSIZE * sizeof(unsigned int), 1, settingFile);
}
}
unsigned int Digitizer::ReadSettingFromFile(uint32_t registerAddress, int ch){
if ( !settingFileExist ) return -1;
unsigned short index = CalSettingIndex(registerAddress, ch);
settingFile = fopen (settingFileName.c_str(),"r");
///fseek( settingFile, address, SEEK_SET);
fseek( settingFile, index * 4, SEEK_SET);
///printf(" at pos %lu Byte = index(%lu)\n", ftell(settingFile), ftell(settingFile)/4);
unsigned int lala[1];
size_t dummy = fread( lala, sizeof(unsigned int), 1, settingFile);
///printf(" data at pos %lu(%lu) : %X = %d\n", ftell(settingFile) - sizeof(unsigned int), (ftell(settingFile) - sizeof(unsigned int))/4, lala[0], lala[0]);
fclose (settingFile);
return lala[0];
}
void Digitizer::SaveSettingToFile(uint32_t registerAddress, unsigned int value, int ch){
if ( !settingFileExist ) return ;
unsigned short index = CalSettingIndex(registerAddress, ch);
setting[index] = value;
settingFile = fopen (settingFileName.c_str(),"r+");
///fseek( settingFile, address, SEEK_SET);
fseek( settingFile, index * 4, SEEK_SET);
unsigned int jaja[1] = {value};
size_t dummy = fwrite( jaja, sizeof(unsigned int), 1, settingFile);
///printf("fwrite ret : %d, 0x%0X, 0x%0X, %d, 0x%X = %d\n", (int)dummy, registerAddress, index*4, index, jaja[0], jaja[0]);
fclose (settingFile);
}