Hey!
So this is my mIO.cpp:
//
// mIO.cpp
// mIO
//
// Created by Louis Frank on 2024-02-08.
// Based on the work of Philipp Schwedheln, Christopher Stawarz & Ralf Brockhausen
// Copyright 2024 DPZ. All rights reserved.
//
#include "mIO.hpp"
BEGIN_NAMESPACE_MW
const std::string mIO::SERIAL_PORT("serial_port");
const std::string mIO::RECONNECT_INTERVAL("reconnect_interval");
const std::string mIO::TAG("tag");
const std::string mIO::UPDATE_PERIOD("data_interval");
const std::string mIO::REWARDA("reward_a");
const std::string mIO::REWARDB("reward_b");
const std::string mIO::MANUALA("manual_a");
const std::string mIO::MANUALB("manual_b");
const std::string mIO::TOUCHXRAW("touch_x_raw");
const std::string mIO::TOUCHYRAW("touch_y_raw");
const std::string mIO::TOUCHZRAW("touch_z_raw");
const std::string mIO::TOUCHXCALIB("touch_x_calib"); // Not implemented and not needed with new firmware
const std::string mIO::TOUCHYCALIB("touch_y_calib"); // Not implemented and not needed with new firmware
const std::string mIO::BUTTONA("button_a");
const std::string mIO::BUTTONB("button_b");
const std::string mIO::BUTTONC("button_c");
const std::string mIO::BUTTOND("button_d");
const std::string mIO::LASERA("laser_a");
const std::string mIO::LASERB("laser_b");
const std::string mIO::SENDWORD("sendword");
const std::string mIO::JOYSTICKXRAW("joystick_x_raw");
const std::string mIO::JOYSTICKYRAW("joystick_y_raw");
const std::string mIO::JOYSTICKXCALIB("joystick_x_calib");
const std::string mIO::JOYSTICKYCALIB("joystick_y_calib");
const std::string mIO::JOYSTICKDIRECTION("joystick_direction");
const std::string mIO::JOYSTICKSTRENGTH("joystick_strength");
const std::string mIO::JOYSTICKBXRAW("joystick_b_x_raw");
const std::string mIO::JOYSTICKBYRAW("joystick_b_y_raw");
const std::string mIO::JOYSTICKBXCALIB("joystick_b_x_calib");
const std::string mIO::JOYSTICKBYCALIB("joystick_b_y_calib");
const std::string mIO::JOYSTICKBDIRECTION("joystick_b_direction");
const std::string mIO::JOYSTICKBSTRENGTH("joystick_b_strength");
const std::string mIO::JOYSTICKSAMPLINGRATE("joystick_samplingrate");
const std::string mIO::TTLINA("ttl_in_a");
const std::string mIO::TTLINB("ttl_in_b");
const std::string mIO::TTLOUT("ttl_out");
const std::string mIO::PHOTODIODEA("photodiode_a");
const std::string mIO::PHOTODIODEB("photodiode_b");
// Time the mIO need for one operationloop
const std::string mIO::LOOPTIME("looptime");
const std::string mIO::COLORBUTTONA("button_a_color");
const std::string mIO::COLORBUTTONB("button_b_color");
const std::string mIO::COLORJOYSTICK("joystick_color");
void mIO::describeComponent(ComponentInfo &info)
{
IODevice::describeComponent(info);
info.setSignature("iodevice/mio");
info.setDisplayName("mIO Plugin");
info.setDescription("mIO Plugin for all IO you can imagine...");
info.addParameter(SERIAL_PORT, false); // new
info.addParameter(RECONNECT_INTERVAL, "0"); // new
info.addParameter(UPDATE_PERIOD, true, "1ms");
info.addParameter(REWARDA, "0");
info.addParameter(REWARDB, "0");
info.addParameter(MANUALA, "0");
info.addParameter(MANUALB, "0");
info.addParameter(TOUCHXRAW, "0");
info.addParameter(TOUCHYRAW, "0");
info.addParameter(TOUCHZRAW, "0");
info.addParameter(TOUCHXCALIB, "0");
info.addParameter(TOUCHYCALIB, "0");
info.addParameter(BUTTONA, "0");
info.addParameter(BUTTONB, "0");
info.addParameter(BUTTONC, "0");
info.addParameter(BUTTOND, "0");
info.addParameter(LASERA, "0");
info.addParameter(LASERB, "0");
info.addParameter(SENDWORD, "0");
info.addParameter(JOYSTICKXRAW, "0");
info.addParameter(JOYSTICKYRAW, "0");
info.addParameter(JOYSTICKXCALIB, "0");
info.addParameter(JOYSTICKYCALIB, "0");
info.addParameter(JOYSTICKDIRECTION, "0");
info.addParameter(JOYSTICKSTRENGTH, "0");
info.addParameter(JOYSTICKBXRAW, "0");
info.addParameter(JOYSTICKBYRAW, "0");
info.addParameter(JOYSTICKBXCALIB, "0");
info.addParameter(JOYSTICKBYCALIB, "0");
info.addParameter(JOYSTICKBDIRECTION, "0");
info.addParameter(JOYSTICKBSTRENGTH, "0");
info.addParameter(JOYSTICKSAMPLINGRATE, "10");
info.addParameter(TTLINA, "0");
info.addParameter(TTLINB, "0");
info.addParameter(TTLOUT, "0");
info.addParameter(PHOTODIODEA, "0");
info.addParameter(PHOTODIODEB, "0");
info.addParameter(LOOPTIME, "0");
info.addParameter(COLORBUTTONA, "0.0,0.0,0.0");
info.addParameter(COLORBUTTONB, "0.0,0.0,0.0");
info.addParameter(COLORJOYSTICK, "0.0,0.0,0.0");
}
mIO::mIO(const ParameterValueMap ¶meters)
: IODevice(parameters),
serialPortPath(optionalVariableOrText(parameters[SERIAL_PORT])),
reconnectIntervalUS(parameters[RECONNECT_INTERVAL]),
clock(Clock::instance()),
running(false),
connected(false),
pump_1_timed_run(false),
pump_2_timed_run(false),
update_period(parameters[UPDATE_PERIOD]),
rewardA(parameters[REWARDA]),
rewardB(parameters[REWARDB]),
manualA(parameters[MANUALA]),
manualB(parameters[MANUALB]),
touchXraw(parameters[TOUCHXRAW]),
touchYraw(parameters[TOUCHYRAW]),
touchZraw(parameters[TOUCHZRAW]),
touchXcalib(parameters[TOUCHXCALIB]),
touchYcalib(parameters[TOUCHYCALIB]),
buttonA(parameters[BUTTONA]),
buttonB(parameters[BUTTONB]),
buttonC(parameters[BUTTONC]),
buttonD(parameters[BUTTOND]),
laserA(parameters[LASERA]),
laserB(parameters[LASERB]),
sendWord(parameters[SENDWORD]),
joystickXraw(parameters[JOYSTICKXRAW]),
joystickYraw(parameters[JOYSTICKYRAW]),
joystickXcalib(parameters[JOYSTICKXCALIB]),
joystickYcalib(parameters[JOYSTICKYCALIB]),
joystickDirection(parameters[JOYSTICKDIRECTION]),
joystickStrength(parameters[JOYSTICKSTRENGTH]),
joystickBXraw(parameters[JOYSTICKBXRAW]),
joystickBYraw(parameters[JOYSTICKBYRAW]),
joystickBXcalib(parameters[JOYSTICKBXCALIB]),
joystickBYcalib(parameters[JOYSTICKBYCALIB]),
joystickBDirection(parameters[JOYSTICKBDIRECTION]),
joystickBStrength(parameters[JOYSTICKBSTRENGTH]),
joystickSampleRate(parameters[JOYSTICKSAMPLINGRATE]),
ttlA(parameters[TTLINA]),
ttlB(parameters[TTLINB]),
ttlOut(parameters[TTLOUT]),
photoDiodeA(parameters[PHOTODIODEA]),
photoDiodeB(parameters[PHOTODIODEB]),
looptime(parameters[LOOPTIME]),
touchScreenMapper(point_type(-15.1858 + 2, 11.3894 - 2), // displayTopLeft
point_type(15.1858 - 2, 11.3894 - 2), // displayTopRight
point_type(-15.1858 + 2, -11.3894 + 2), // displayBottomLeft
point_type(15.1858 - 2, -11.3894 + 2), // displayBottomRight
point_type(252, 3760), // touchscreenTopLeft
point_type(3875, 3725), // touchscreenTopRight
point_type(245, 330), // touchscreenBottomLeft
point_type(3855, 340)), // touchscreenBottomRight
dcPumpCalculator(1., 1., 1.), // Seconds to reach max speed, Seconds to reach min speed, max speed ml per second
stepperPumpCalculator(1.), // ml per full rotation
joystick1Mapper({
{5, 505, 1005, 50}, // X: min, center, max raw values, deadzone
{5, 505, 1005, 50} // Y: min, center, max raw values, deadzone
}),
joystick2Mapper({
{5, 505, 1005, 50}, // X: min, center, max raw values, deadzone
{5, 505, 1005, 50} // Y: min, center, max raw values, deadzone
})
{
ParsedColorTrio colorButtonA(parameters[COLORBUTTONA]);
buttonA_colR = colorButtonA.getR();
buttonA_colG = colorButtonA.getG();
buttonA_colB = colorButtonA.getB();
ParsedColorTrio colorButtonB(parameters[COLORBUTTONB]);
buttonB_colR = colorButtonB.getR();
buttonB_colG = colorButtonB.getG();
buttonB_colB = colorButtonB.getB();
ParsedColorTrio colorJoystick(parameters[COLORJOYSTICK]);
joystick_colR = colorJoystick.getR();
joystick_colG = colorJoystick.getG();
joystick_colB = colorJoystick.getB();
}
mIO::~mIO()
{
if (receiveDataThread.joinable())
{
continueReceivingData.clear();
receiveDataThread.join();
}
if (mIO_Initialized)
{
if (schedule_node)
{
schedule_node->cancel();
schedule_node.reset();
}
}
delete proto_handler;
}
bool mIO::initialize()
{
if (serialPortPath)
{
path = serialPortPath->getValue().getString();
}
if (!serialPort.connect(path, baudRate))
{
return false;
}
connected = true;
proto_handler = new MioProtoV1(serialPort);
continueReceivingData.test_and_set();
receiveDataThread = std::thread([this]()
{ receiveData(); });
scheduler = Scheduler::instance();
schedule_node = scheduler->scheduleUS(
FILELINE, update_period, update_period, M_REPEAT_INDEFINITELY,
[this]()
{
update();
return nullptr;
},
M_DEFAULT_IODEVICE_PRIORITY, M_DEFAULT_IODEVICE_WARN_SLOP_US, M_DEFAULT_FAIL_SLOP_US,
M_MISSED_EXECUTION_DROP);
mprintf(M_IODEVICE_MESSAGE_DOMAIN, "mIO: loaded and started device %s", device_path.c_str());
mprintf(M_IODEVICE_MESSAGE_DOMAIN, "mIO: update_period %lld", update_period);
// TODO How can we permanently store variables?
double display_left = -15.1858;
double display_right = 15.1858;
double display_top = 11.3894;
double display_bottom = -11.3894;
// TODO Set calibration values
touchScreenMapper = TouchScreenMapper(point_type(display_left * 0.75, display_top * 0.75), // displayTopLeft
point_type(display_right * 0.75, display_top * 0.75), // displayTopRight
point_type(display_left * 0.75, display_bottom * 0.75), // displayBottomLeft
point_type(display_right * 0.75, display_bottom * 0.75), // displayBottomRight
point_type(475, 3629), // touchscreenTopLeft
point_type(3591, 3639), // touchscreenTopRight
point_type(488, 526), // touchscreenBottomLeft
point_type(3559, 544)); // touchscreenBottomRight
dcPumpCalculator = DCPumpCalculator(0., 0., 1.); // Seconds to reach max speed, Seconds to reach min speed, max speed ml per second
stepperPumpCalculator = StepperPumpCalculator(0.09175); // ml per full rotation (6 half pulses)
joystick1Mapper = JoystickMapper({
{5, 505, 1005, 65}, // X: min, center, max raw values, deadzone
{5, 505, 1005, 65} // Y: min, center, max raw values, deadzone
});
joystick2Mapper = JoystickMapper({
{5, 505, 1005, 65}, // X: min, center, max raw values, deadzone
{5, 505, 1005, 65} // Y: min, center, max raw values, deadzone
});
mIO_Initialized = true;
return mIO_Initialized;
}
bool mIO::startDeviceIO()
{
running = true;
return true;
}
bool mIO::stopDeviceIO()
{
running = false;
return true;
}
void mIO::update()
{
MWTime currentTime = clock->getCurrentTimeUS();
(void)currentTime;
if (!running)
{
return;
}
if (!connected)
{
return;
}
// Send
std::uint16_t pump_1_reward_half_pulses = 0;
if (rewardA->getValue().getFloat())
{
pump_1_timed_run.set(true, dcPumpCalculator.timeToRun_s(rewardA->getValue().getFloat()));
pump_1_reward_half_pulses = stepperPumpCalculator.rewardToHalfPulses(rewardA->getValue().getFloat());
merror(M_IODEVICE_MESSAGE_DOMAIN, "pump_1_timed_run %d", pump_1_timed_run);
merror(M_IODEVICE_MESSAGE_DOMAIN, "dcPumpCalculator.timeToRun_s %f", dcPumpCalculator.timeToRun_s(rewardA->getValue().getFloat()));
rewardA->setValue(0.0);
}
std::uint16_t pump_2_reward_half_pulses = 0;
if (rewardB->getValue().getFloat())
{
pump_2_timed_run.set(true, dcPumpCalculator.timeToRun_s(rewardB->getValue().getFloat()));
pump_2_reward_half_pulses = stepperPumpCalculator.rewardToHalfPulses(rewardB->getValue().getFloat());
merror(M_IODEVICE_MESSAGE_DOMAIN, "pump_2_timed_run %d", pump_2_timed_run);
merror(M_IODEVICE_MESSAGE_DOMAIN, "dcPumpCalculator.timeToRun_s %f", dcPumpCalculator.timeToRun_s(rewardB->getValue().getFloat()));
rewardB->setValue(0.0);
}
std::uint8_t digital_outs = 0;
proto_handler->writeFlag(digital_outs, MIO_PROTO_V1_DIGITAL_OUTS_REWARD_A_BIT_ID,
pump_1_timed_run.get());
proto_handler->writeFlag(digital_outs, MIO_PROTO_V1_DIGITAL_OUTS_REWARD_B_BIT_ID,
pump_2_timed_run.get());
proto_handler->writeFlag(digital_outs, MIO_PROTO_V1_DIGITAL_OUTS_REWARD_TTL_BIT_ID,
ttlOut->getValue().getBool());
if (laserA->getValue().getInteger() > (uint16_t)-1)
{
merror(M_IODEVICE_MESSAGE_DOMAIN, "mIO: conversion of laserA value to uint16 overflow. Result unknown!");
}
std::uint16_t analog_out_1 = (uint16_t)(laserA->getValue().getInteger());
if (laserB->getValue().getInteger() > (uint16_t)-1)
{
merror(M_IODEVICE_MESSAGE_DOMAIN, "mIO: conversion of laserB value to uint16 overflow. Result unknown!");
}
std::uint16_t analog_out_2 = (uint16_t)(laserB->getValue().getInteger());
if (sendWord->getValue().getInteger() > (uint16_t)-1)
{
merror(M_IODEVICE_MESSAGE_DOMAIN, "mIO: conversion of sendWord value to uint16 overflow. Result unknown!");
}
std::uint16_t idc = (uint16_t)(sendWord->getValue().getInteger());
mio_proto_v1_rgb rgb_button_A;
rgb_button_A.red = (uint8_t)(buttonA_colR->getValue().getFloat() * 255.0);
rgb_button_A.blue = (uint8_t)(buttonA_colB->getValue().getFloat() * 255.0);
rgb_button_A.green = (uint8_t)(buttonA_colG->getValue().getFloat() * 255.0);
mio_proto_v1_rgb rgb_button_B;
rgb_button_B.red = (uint8_t)(buttonB_colR->getValue().getFloat() * 255.0);
rgb_button_B.blue = (uint8_t)(buttonB_colB->getValue().getFloat() * 255.0);
rgb_button_B.green = (uint8_t)(buttonB_colG->getValue().getFloat() * 255.0);
mio_proto_v1_rgb rgb_joystick;
rgb_joystick.red = (uint8_t)(joystick_colR->getValue().getFloat() * 255.0);
rgb_joystick.blue = (uint8_t)(joystick_colB->getValue().getFloat() * 255.0);
rgb_joystick.green = (uint8_t)(joystick_colG->getValue().getFloat() * 255.0);
proto_handler->send(digital_outs, analog_out_1, analog_out_2, idc, rgb_button_A, rgb_button_B, rgb_joystick, pump_1_reward_half_pulses, pump_2_reward_half_pulses);
}
void mIO::receiveData()
{
while (continueReceivingData.test_and_set())
{
auto result = proto_handler->handleIncomingSerialCommunication();
if (result == MIO_PROTO_HANDLE_ERROR_SERIAL)
{
connected = false;
serialPort.disconnect();
if (!reconnect())
{
return;
}
}
// Recv message
MWTime currentTime = clock->getCurrentTimeUS();
if (!proto_handler->recvAvailable())
{
continue;
}
mio_proto_v1_data_protocol_from_mio buffer;
proto_handler->recv(&buffer);
// ==== DIGITAL_INS ====
if (manualA->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_1_BIT_ID))
manualA->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_1_BIT_ID),
currentTime);
if (manualB->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_2_BIT_ID))
manualB->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_2_BIT_ID),
currentTime);
if (ttlA->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_3_BIT_ID))
ttlA->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_3_BIT_ID),
currentTime);
if (ttlB->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_4_BIT_ID))
ttlB->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_D_IN_4_BIT_ID),
currentTime);
if (buttonA->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_1_BIT_ID))
buttonA->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_1_BIT_ID),
currentTime);
if (buttonB->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_2_BIT_ID))
buttonB->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_2_BIT_ID),
currentTime);
if (buttonC->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_3_BIT_ID))
buttonC->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_3_BIT_ID),
currentTime);
if (buttonD->getValue().getBool() != proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_4_BIT_ID))
buttonD->setValue(
proto_handler->readFlag(buffer.digital_ins, MIO_PROTO_V1_DIGITAL_INS_IO_TB_IN_4_BIT_ID),
currentTime);
// ==== TOUCHSCREEN ====
point_type touch_calibrated = touchScreenMapper.touchscreenToDisplay(
point_type(static_cast<double>(buffer.touchscreen_x), static_cast<double>(buffer.touchscreen_y)));
if (touchXraw->getValue().getInteger() != buffer.touchscreen_x)
{
touchXraw->setValue(buffer.touchscreen_x, currentTime);
touchXcalib->setValue(touch_calibrated.x(), currentTime);
}
if (touchYraw->getValue().getInteger() != buffer.touchscreen_y)
{
touchYraw->setValue(buffer.touchscreen_y, currentTime);
touchYcalib->setValue(touch_calibrated.y(), currentTime);
}
if (touchZraw->getValue().getInteger() != buffer.touchscreen_z)
{
touchZraw->setValue(buffer.touchscreen_z, currentTime);
}
// ==== JOYSTICK A ====
bool joystick_a_update_dir = false;
JoystickMapper::Axis joystick_a_axis_raw = {static_cast<double>(buffer.joystick_a_x), static_cast<double>(buffer.joystick_a_y)};
JoystickMapper::Axis joystick_a_axis = joystick1Mapper.mapAxis(joystick_a_axis_raw);
if (joystickXraw->getValue().getFloat() != joystick_a_axis_raw.x)
{
joystickXraw->setValue(joystick_a_axis_raw.x, currentTime);
joystickXcalib->setValue(joystick_a_axis.x, currentTime);
joystick_a_update_dir = true;
}
if (joystickYraw->getValue().getFloat() != joystick_a_axis_raw.y)
{
joystickYraw->setValue(joystick_a_axis_raw.y, currentTime);
joystickYcalib->setValue(joystick_a_axis.y, currentTime);
joystick_a_update_dir = true;
}
if (joystick_a_update_dir)
{
// TODO test JoystickMapper angle function
float joystick_a_dir = joystick1Mapper.angleAxis(joystick_a_axis); // Converting to degrees and shifting range to 0-360
joystickDirection->setValue(static_cast<int>(joystick_a_dir), currentTime);
}
// ==== JOYSTICK B ====
bool joystick_b_update_dir = false;
JoystickMapper::Axis joystick_b_axis_raw = {static_cast<double>(buffer.joystick_b_x), static_cast<double>(buffer.joystick_b_y)};
JoystickMapper::Axis joystick_b_axis = joystick1Mapper.mapAxis(joystick_b_axis_raw);
if (joystickBXraw->getValue().getInteger() != joystick_b_axis_raw.x)
{
joystickBXraw->setValue(joystick_b_axis_raw.x, currentTime);
joystickBXcalib->setValue(joystick_b_axis.x, currentTime);
joystickStrength->setValue(joystick1Mapper.distanceAxis({0, 0}, joystick_a_axis), currentTime);
joystick_b_update_dir = true;
}
if (joystickBYraw->getValue().getInteger() != joystick_b_axis_raw.y)
{
joystickBYraw->setValue(joystick_b_axis_raw.y, currentTime);
joystickBYcalib->setValue(joystick_b_axis.y, currentTime);
joystickBStrength->setValue(joystick2Mapper.distanceAxis({0, 0}, joystick_b_axis), currentTime);
joystick_b_update_dir = true;
}
if (joystick_b_update_dir)
{
// TODO test JoystickMapper angle function
float joystick_b_dir = joystick2Mapper.angleAxis(joystick_b_axis); // Converting to degrees and shifting range to 0-360
joystickBDirection->setValue(static_cast<int>(joystick_b_dir), currentTime);
}
if (photoDiodeA->getValue().getInteger() != buffer.analog_in_1)
{
photoDiodeA->setValue(buffer.analog_in_1, currentTime);
}
if (photoDiodeB->getValue().getInteger() != buffer.analog_in_2)
{
photoDiodeB->setValue(buffer.analog_in_2, currentTime);
}
// ==== LOOPTIME ====
looptime->setValue(static_cast<long>(buffer.mio_time), currentTime);
}
}
bool mIO::reconnect()
{
if (reconnectIntervalUS <= 0)
{
// User doesn't want us to attempt reconnection. Just abort.
merror(M_IODEVICE_MESSAGE_DOMAIN, "Disconnected from mIO");
return false;
}
merror(M_IODEVICE_MESSAGE_DOMAIN, "Disconnected from mIO; will try to reconnect in %g seconds",
double(reconnectIntervalUS) / 1e6);
while (true)
{
const auto waitStopTime = clock->getCurrentTimeUS() + reconnectIntervalUS;
// Perform an "active" wait, so that we can exit promptly if the experiment is unloaded
while (clock->getCurrentTimeUS() < waitStopTime)
{
if (!continueReceivingData.test_and_set())
{
return false;
}
clock->yield();
}
mprintf(M_IODEVICE_MESSAGE_DOMAIN, "Attempting to reconnect to mIO");
if (serialPort.connect(path, baudRate))
{
mprintf(M_IODEVICE_MESSAGE_DOMAIN, "Successfully reconnected to mIO");
connected = true;
break;
}
merror(M_IODEVICE_MESSAGE_DOMAIN, "Failed to reconnect to mIO; will try again in %g seconds",
double(reconnectIntervalUS) / 1e6);
}
return true;
}
END_NAMESPACE_MW
In line 255: // TODO How can we permanently store variables?
I would like a way to save the device-dependent calibration values for:
- touchScreenMapper
- dcPumpCalculator
- stepperPumpCalculator
- joystick1Mapper
- joystick2Mapper
somewhere, since they depend on the hardware and not the experiment, I think it would be best if they were experiment and protocol independent. I would like to be able to automatically/manually define a setting or calibration value file that I can read and write to for this purpose. They are unlikely to change during the lifetime of the hardware, or only if the touchscreen, pump, joystick or other components are replaced.