#include "device_d001.h" #include "../adlink.h" device_d001::device_d001(QObject *parent) : gtl::hw::device(parent), _is_full_restarting(true) { _count_ai = 4; set_ai(); _device->set_name("d001"); } device_d001::~device_d001() { stop(); } QString device_d001::type() const { return "d001"; } bool device_d001::start(QString id, qreal rate) { emit status_changed(INIT_IN_PROGRESS); _ids.clear(); _modules.clear(); _id = id; std::vector ids; QStringList str_ids = id.split(','); for(int i = 0; i < str_ids.size(); i++) { bool is_ok; int int_id = str_ids[i].toInt(&is_ok); if(is_ok) ids.push_back(int_id); } _ids_current.clear(); std::copy(ids.begin(), ids.end(), std::back_inserter(_ids_current)); U8 sn_test[] = ADLINK_SN_FIXED; for (int i = 0; i < ids.size(); i++) { I16 err = UD_Register_Card(USB_2405, ids[i]); _ids.insert(std::pair(i, err)); if (err >= 0 && err < MAX_USB_DEVICE) { U8 sn[16]; UD_Serial_Number_Read(err, sn); if (memcmp(sn_test, sn, sizeof(sn)) == 0) _modules.push_back(err); else err = MAX_USB_DEVICE + 1; } } ULONG access_cnt; I16 err; for (std::map::iterator iter_ids = _ids.begin(); iter_ids != _ids.end(); iter_ids++) { if (iter_ids->second < 0 || iter_ids->second >= MAX_USB_DEVICE) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(iter_ids->first + 1), tr("Error starting module")); } //emit error("init hardware #" + QString::number(iter_ids->first + 1), "UD_Register_Card error. code: " + QString::number(iter_ids->second)); } _buffer.resize(_modules.size()); _buffer_read.resize(_modules.size()); _count_ai = (int)_modules.size()*4; _rate = rate; set_ai(); QJsonArray array_config = _config.toArray(); for(int i = 0; i < qMin(array_config.size(), count_ai()); i++) { ai(i)->blockSignals(true); ai(i)->set_iepe(array_config[i].toObject().value("iepe").toBool()); ai(i)->set_coupling(array_config[i].toObject().value("ac").toBool()); ai(i)->blockSignals(false); } if (_is_full_restarting) emit channels_changed(); if (_modules.empty()) return false; for (int i = 0; i < _modules.size(); i++) { err = UD_AI_AsyncClear(_modules[i], &access_cnt); err = UD_GPTC_Control(_modules[i], 0, IntENABLE, 0); } for (int i = 0; i < _modules.size(); i++) { err = UD_AI_2405_Chan_Config(_modules[i], get_channel_config(i * 4 + 0), get_channel_config(i * 4 + 1), get_channel_config(i * 4 + 2), get_channel_config(i * 4 + 3)); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition", "UD_AI_2405_Chan_Config error. code: " + QString::number(err)); break; } err = UD_AI_AsyncDblBufferMode(_modules[i], 1); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition", "UD_AI_AsyncDblBufferMode error. code: " + QString::number(err)); break; } U16 trig_ctrl; U16 conv_src; if (_modules.size() == 1) { conv_src = P2405_AI_CONVSRC_INT; trig_ctrl = P2405_AI_TRGSRC_SOFT; } else { conv_src = P2405_AI_CONVSRC_EXT; if (i == _modules.size() - 1) { err = UD_DIO_2405_Config(_modules[i], P2405_PULSE_OUTPUT, P2405_DIGITAL_INPUT); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition. module: " + QString::number(_modules[i]), "UD_DIO_2405_Config error. code: " + QString::number(err)); break; } err = UD_GPTC_Clear(_modules[i], 0); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition. module: " + QString::number(_modules[i]), "UD_GPTC_Clear error. code: " + QString::number(err)); break; } err = UD_GPTC_Setup(_modules[i], 0, ContGatedPulseGenPWM, 0, GPTC_OUTPUT_HACTIVE, qRound(40e+6 / rate), 0, 0); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition. module: " + QString::number(_modules[i]), "UD_GPTC_Setup error. code: " + QString::number(err)); break; } //err = UD_GPTC_Control(_modules[i], 0, IntENABLE, 0); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition. module: " + QString::number(_modules[i]), "UD_GPTC_Control error. code: " + QString::number(err)); break; } trig_ctrl = P2405_AI_TRGSRC_SOFT; } else { err = UD_DIO_2405_Config(_modules[i], P2405_DIGITAL_INPUT, P2405_DIGITAL_INPUT); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition. module: " + QString::number(_modules[i]), "UD_DIO_2405_Config error. code: " + QString::number(err)); break; } trig_ctrl = P2405_AI_TRGSRC_DTRIG; } } err = UD_AI_2405_Trig_Config(_modules[i], conv_src, P2405_AI_TRGMOD_POST, trig_ctrl, 0, 0, 0, 0); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition", "UD_AI_2405_Trig_Config error. code: " + QString::number(err)); break; } int samples = rate/10; samples = qRound(samples / 128.0) * 128; U32 size_available = 0; err = UD_AI_InitialMemoryAllocated(_modules[i], &size_available); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); // emit error("start acquisition", "UD_AI_InitialMemoryAllocated error. code: " + QString::number(err)); break; } int factor_size = 2; size_available *= 1024; int size = samples * sizeof(I32) * 4 * factor_size; if (size > size_available) { samples = size_available / sizeof(I32) / factor_size / channels(); samples = qRound(samples / 128.0) * 128; if (samples * sizeof(I32)*4 > size_available) samples--; } _buffer[i].resize(samples * 4 * factor_size); F64 rate_actual = 0; UD_AI_DDS_ActualRate_Get(_modules[i], rate, &rate_actual); //emit set_timing(_settings->rate(), samples); U16 gains[] = { AD_B_10_V, AD_B_10_V, AD_B_10_V, AD_B_10_V }; U16 ch[4] = { 0, 1, 2, 3 }; err = UD_AI_ContReadMultiChannels(_modules[i], 4, ch, gains, (U16*)&_buffer[i][0], (_buffer[i].size() * 1), _rate, ASYNCH_OP); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); //emit error("start acquisition", "UD_AI_ContReadMultiChannels error. code: " + QString::number(err)); break; } if (i == _modules.size() - 1 && _modules.size() != 1) { err = UD_GPTC_Control(_modules[i], 0, IntENABLE, 1); if (err != NoError_) { emit status_changed(INIT_FAILED); emit error(tr("Init") + QString("d001 ") + " #" + QString::number(i + 1), tr("Error starting module")); // emit error("start acquisition. module: " + QString::number(_modules[i]), "UD_GPTC_Control error. code: " + QString::number(err)); break; } } } _device->set_name(QString("d001") + "[" + id + "]"); _device->set_id(_id); _device->set_rate(rate); QThread::start(QThread::HighestPriority); emit status_changed(OK); return true; } bool device_d001::stop() { if (isRunning()) { ULONG access_cnt; I16 err; bool res = true; for (int i = 0; i < _modules.size(); i++) { err = UD_AI_AsyncClear(_modules[i], &access_cnt); res &= err == NoError_; } wait(); // return res; } ULONG access_cnt; I16 err; for (int i = 0; i < _modules.size(); i++) { err = UD_AI_AsyncClear(_modules[i], &access_cnt); //err = UD_GPTC_Control(_modules[i], 0, IntENABLE, 0); err = UD_GPTC_Clear(_modules[i], 0); err = UD_DIO_2405_Config(_modules[i], P2405_DIGITAL_INPUT, P2405_DIGITAL_INPUT); err = UD_Release_Card(_modules[i]); } return true; } void device_d001::set_config(const QJsonValue &config) { gtl::hw::device::set_config(config); if(isRunning()) restart(); } void device_d001::run() { qDebug() << "device started"; BOOLEAN HalfReady; BOOLEAN fstop; I16 err; while (true) { bool is_stop = true; for (int i = 0; i < _modules.size(); i++) { _buffer_read[i].resize(_buffer[i].size() / 2); do { err = UD_AI_AsyncDblBufferHalfReady(_modules[i], &HalfReady, &fstop); if (err != NoError_) { emit status_changed(FAILED); QString title_err = "acquisition. module: " + QString::number(_modules[i]); QString msg_err = QString("UD_AI_AsyncDblBufferHalfReady error. code: ") + QString::number(err); emit error(title_err, msg_err); qDebug() << title_err << msg_err; return; } err = UD_AI_AsyncDblBufferTransfer32(_modules[i], &_buffer_read[i][0]); if (err != NoError_) { emit status_changed(FAILED); QString title_err = "acquisition. module: " + QString::number(_modules[i]); QString msg_err = QString("UD_AI_AsyncDblBufferTransfer32 error. code: ") + QString::number(err); emit error(title_err, msg_err); qDebug() << title_err << msg_err; break; } } while (!HalfReady && !fstop); // qDebug() << "read half buffer"; is_stop &= (bool)fstop; } if (is_stop) break; send_data(); } emit status_changed(IDLE); } void device_d001::send_data() { _buffer_send.clear(); int samples = _buffer_read[0].size() / 4; for (int i = 0; i < samples; i++) { for (int j = 0; j < _buffer_read.size(); j++) { for (int k = 0; k < 4; k++) { F64 voltage; UD_AI_VoltScale32(_modules[j], AD_B_10_V, 0, _buffer_read[j][i*4 + k], &voltage); if (voltage > 10) voltage = 10; else if (voltage < -10) voltage = -10; _buffer_send.push_back(voltage); } } } set_ai_data(&_buffer_send[0], (int)_buffer_send.size()); // qDebug() << "send data"; emit received_data(); } U16 device_d001::get_channel_config(int channel) { U16 iepe = (ai(channel)->is_iepe() ? P2405_AI_EnableIEPE : P2405_AI_DisableIEPE); U16 coupling = (ai(channel)->is_iepe() ? P2405_AI_Coupling_AC : (ai(channel)->is_coupling() ? P2405_AI_Coupling_AC : P2405_AI_Coupling_None)); return iepe | coupling | P2405_AI_Differential; } void device_d001::ai_iepe_changed() { restart(); } void device_d001::ai_coupling_changed() { restart(); }