static void caerInputEDVSExit(caerModuleData moduleData) { // Remove listener, which can reference invalid memory in userData. sshsNodeRemoveAttributeListener(moduleData->moduleNode, moduleData, &logLevelListener); sshsNode biasNode = sshsGetRelativeNode(moduleData->moduleNode, "bias/"); sshsNodeRemoveAttributeListener(biasNode, moduleData, &biasConfigListener); sshsNode dvsNode = sshsGetRelativeNode(moduleData->moduleNode, "dvs/"); sshsNodeRemoveAttributeListener(dvsNode, moduleData, &dvsConfigListener); sshsNode serialNode = sshsGetRelativeNode(moduleData->moduleNode, "serial/"); sshsNodeRemoveAttributeListener(serialNode, moduleData, &serialConfigListener); sshsNode sysNode = sshsGetRelativeNode(moduleData->moduleNode, "system/"); sshsNodeRemoveAttributeListener(sysNode, moduleData, &systemConfigListener); caerDeviceDataStop(moduleData->moduleState); caerDeviceClose((caerDeviceHandle *) &moduleData->moduleState); // Clear sourceInfo node. sshsNode sourceInfoNode = sshsGetRelativeNode(moduleData->moduleNode, "sourceInfo/"); sshsNodeRemoveAllAttributes(sourceInfoNode); if (sshsNodeGetBool(moduleData->moduleNode, "autoRestart")) { // Prime input module again so that it will try to restart if new devices detected. sshsNodePutBool(moduleData->moduleNode, "running", true); } }
static void caerVisualizerEventHandlerInput(caerVisualizerPublicState state, const sf::Event &event) { // This only works with an input module. const std::string moduleLibrary = sshsNodeGetStdString(state->eventSourceConfigNode, "moduleLibrary"); if (!boost::algorithm::starts_with(moduleLibrary, "caer_input_")) { return; } // PAUSE. if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Space) { bool pause = sshsNodeGetBool(state->eventSourceConfigNode, "pause"); sshsNodePutBool(state->eventSourceConfigNode, "pause", !pause); } // SLOW DOWN. else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::S) { int timeSlice = sshsNodeGetInt(state->eventSourceConfigNode, "PacketContainerInterval"); sshsNodePutInt(state->eventSourceConfigNode, "PacketContainerInterval", timeSlice / 2); } // SPEED UP. else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::F) { int timeSlice = sshsNodeGetInt(state->eventSourceConfigNode, "PacketContainerInterval"); sshsNodePutInt(state->eventSourceConfigNode, "PacketContainerInterval", timeSlice * 2); } }
static void caerInputDVS128Exit(caerModuleData moduleData) { caerDeviceDataStop(moduleData->moduleState); caerDeviceClose((caerDeviceHandle *) &moduleData->moduleState); if (sshsNodeGetBool(moduleData->moduleNode, "Auto-Restart")) { // Prime input module again so that it will try to restart if new devices detected. sshsNodePutBool(moduleData->moduleNode, "shutdown", false); } }
caerModuleData caerModuleInitialize(uint16_t moduleID, const char *moduleShortName, sshsNode mainloopNode) { // Generate short module name with ID, reused in all error messages and later code. size_t nameLength = (size_t) snprintf(NULL, 0, "%" PRIu16 "-%s", moduleID, moduleShortName); char nameString[nameLength + 1]; snprintf(nameString, nameLength + 1, "%" PRIu16 "-%s", moduleID, moduleShortName); // Allocate memory for the module. caerModuleData moduleData = calloc(1, sizeof(struct caer_module_data)); if (moduleData == NULL) { caerLog(CAER_LOG_ALERT, nameString, "Failed to allocate memory for module. Error: %d.", errno); thrd_exit(EXIT_FAILURE); } // Set module ID for later identification (hash-table key). moduleData->moduleID = moduleID; // Put module into startup state. moduleData->moduleStatus = STOPPED; atomic_store_explicit(&moduleData->running, true, memory_order_relaxed); // Determine SSHS module node. Use short name for better human recognition. char sshsString[nameLength + 2]; strncpy(sshsString, nameString, nameLength); sshsString[nameLength] = '/'; sshsString[nameLength + 1] = '\0'; // Initialize configuration, shutdown hooks. moduleData->moduleNode = sshsGetRelativeNode(mainloopNode, sshsString); if (moduleData->moduleNode == NULL) { caerLog(CAER_LOG_ALERT, nameString, "Failed to allocate configuration node for module."); thrd_exit(EXIT_FAILURE); } sshsNodePutBool(moduleData->moduleNode, "shutdown", false); // Always reset to false. sshsNodeAddAttributeListener(moduleData->moduleNode, moduleData, &caerModuleShutdownListener); // Setup default full log string name. moduleData->moduleSubSystemString = malloc(nameLength + 1); if (moduleData->moduleSubSystemString == NULL) { caerLog(CAER_LOG_ALERT, nameString, "Failed to allocate subsystem string for module."); thrd_exit(EXIT_FAILURE); } strncpy(moduleData->moduleSubSystemString, nameString, nameLength); moduleData->moduleSubSystemString[nameLength] = '\0'; atomic_thread_fence(memory_order_release); return (moduleData); }
static bool caerInputDVS128Init(caerModuleData moduleData) { caerLog(CAER_LOG_DEBUG, moduleData->moduleSubSystemString, "Initializing module ..."); // USB port/bus/SN settings/restrictions. // These can be used to force connection to one specific device at startup. sshsNodePutShortIfAbsent(moduleData->moduleNode, "BusNumber", 0); sshsNodePutShortIfAbsent(moduleData->moduleNode, "DevAddress", 0); sshsNodePutStringIfAbsent(moduleData->moduleNode, "SerialNumber", ""); // Add auto-restart setting. sshsNodePutBoolIfAbsent(moduleData->moduleNode, "Auto-Restart", true); // Start data acquisition, and correctly notify mainloop of new data and module of exceptional // shutdown cases (device pulled, ...). char *serialNumber = sshsNodeGetString(moduleData->moduleNode, "SerialNumber"); moduleData->moduleState = caerDeviceOpen(moduleData->moduleID, CAER_DEVICE_DVS128, U8T(sshsNodeGetShort(moduleData->moduleNode, "BusNumber")), U8T(sshsNodeGetShort(moduleData->moduleNode, "DevAddress")), serialNumber); free(serialNumber); if (moduleData->moduleState == NULL) { // Failed to open device. return (false); } // Put global source information into SSHS. struct caer_dvs128_info devInfo = caerDVS128InfoGet(moduleData->moduleState); sshsNode sourceInfoNode = sshsGetRelativeNode(moduleData->moduleNode, "sourceInfo/"); sshsNodePutShort(sourceInfoNode, "logicVersion", devInfo.logicVersion); sshsNodePutBool(sourceInfoNode, "deviceIsMaster", devInfo.deviceIsMaster); sshsNodePutShort(sourceInfoNode, "dvsSizeX", devInfo.dvsSizeX); sshsNodePutShort(sourceInfoNode, "dvsSizeY", devInfo.dvsSizeY); // Put source information for "virtual" APS frame that can be used to display and debug filter information. sshsNodePutShort(sourceInfoNode, "apsSizeX", devInfo.dvsSizeX); sshsNodePutShort(sourceInfoNode, "apsSizeY", devInfo.dvsSizeY); caerModuleSetSubSystemString(moduleData, devInfo.deviceString); // Ensure good defaults for data acquisition settings. // No blocking behavior due to mainloop notification, and no auto-start of // all producers to ensure cAER settings are respected. caerDeviceConfigSet(moduleData->moduleState, CAER_HOST_CONFIG_DATAEXCHANGE, CAER_HOST_CONFIG_DATAEXCHANGE_BLOCKING, false); caerDeviceConfigSet(moduleData->moduleState, CAER_HOST_CONFIG_DATAEXCHANGE, CAER_HOST_CONFIG_DATAEXCHANGE_START_PRODUCERS, false); caerDeviceConfigSet(moduleData->moduleState, CAER_HOST_CONFIG_DATAEXCHANGE, CAER_HOST_CONFIG_DATAEXCHANGE_STOP_PRODUCERS, true); // Create default settings and send them to the device. createDefaultConfiguration(moduleData); sendDefaultConfiguration(moduleData); // Start data acquisition. bool ret = caerDeviceDataStart(moduleData->moduleState, &mainloopDataNotifyIncrease, &mainloopDataNotifyDecrease, caerMainloopGetReference(), &moduleShutdownNotify, moduleData->moduleNode); if (!ret) { // Failed to start data acquisition, close device and exit. caerDeviceClose((caerDeviceHandle *) &moduleData->moduleState); return (false); } return (true); }
static void moduleShutdownNotify(void *p) { sshsNode moduleNode = p; // Ensure parent also shuts down (on disconnected device for example). sshsNodePutBool(moduleNode, "shutdown", true); }
static void caerInputDAVISExit(caerModuleData moduleData) { // Device related configuration has its own sub-node. struct caer_davis_info devInfo = caerDavisInfoGet(moduleData->moduleState); sshsNode deviceConfigNode = sshsGetRelativeNode(moduleData->moduleNode, chipIDToName(devInfo.chipID, true)); // Remove listener, which can reference invalid memory in userData. sshsNodeRemoveAttributeListener(moduleData->moduleNode, moduleData, &logLevelListener); sshsNode chipNode = sshsGetRelativeNode(deviceConfigNode, "chip/"); sshsNodeRemoveAttributeListener(chipNode, moduleData, &chipConfigListener); sshsNode muxNode = sshsGetRelativeNode(deviceConfigNode, "multiplexer/"); sshsNodeRemoveAttributeListener(muxNode, moduleData, &muxConfigListener); sshsNode dvsNode = sshsGetRelativeNode(deviceConfigNode, "dvs/"); sshsNodeRemoveAttributeListener(dvsNode, moduleData, &dvsConfigListener); sshsNode apsNode = sshsGetRelativeNode(deviceConfigNode, "aps/"); sshsNodeRemoveAttributeListener(apsNode, moduleData, &apsConfigListener); sshsNode imuNode = sshsGetRelativeNode(deviceConfigNode, "imu/"); sshsNodeRemoveAttributeListener(imuNode, moduleData, &imuConfigListener); sshsNode extNode = sshsGetRelativeNode(deviceConfigNode, "externalInput/"); sshsNodeRemoveAttributeListener(extNode, moduleData, &extInputConfigListener); sshsNode usbNode = sshsGetRelativeNode(deviceConfigNode, "usb/"); sshsNodeRemoveAttributeListener(usbNode, moduleData, &usbConfigListener); sshsNode sysNode = sshsGetRelativeNode(moduleData->moduleNode, "system/"); sshsNodeRemoveAttributeListener(sysNode, moduleData, &systemConfigListener); sshsNode biasNode = sshsGetRelativeNode(deviceConfigNode, "bias/"); size_t biasNodesLength = 0; sshsNode *biasNodes = sshsNodeGetChildren(biasNode, &biasNodesLength); if (biasNodes != NULL) { for (size_t i = 0; i < biasNodesLength; i++) { // Remove listener for this particular bias. sshsNodeRemoveAttributeListener(biasNodes[i], moduleData, &biasConfigListener); } free(biasNodes); } // Ensure Exposure value is coherent with libcaer. sshsAttributeUpdaterRemoveAllForNode(apsNode); sshsNodePutAttribute( apsNode, "Exposure", SSHS_INT, apsExposureUpdater(moduleData->moduleState, "Exposure", SSHS_INT)); // Remove statistics updaters. sshsNode statNode = sshsGetRelativeNode(deviceConfigNode, "statistics/"); sshsAttributeUpdaterRemoveAllForNode(statNode); caerDeviceDataStop(moduleData->moduleState); caerDeviceClose((caerDeviceHandle *) &moduleData->moduleState); // Clear sourceInfo node. sshsNode sourceInfoNode = sshsGetRelativeNode(moduleData->moduleNode, "sourceInfo/"); sshsNodeRemoveAllAttributes(sourceInfoNode); if (sshsNodeGetBool(moduleData->moduleNode, "autoRestart")) { // Prime input module again so that it will try to restart if new devices detected. sshsNodePutBool(moduleData->moduleNode, "running", true); } }