static void sendDefaultConfiguration(caerModuleData moduleData) { // Send cAER configuration to libcaer and device. biasConfigSend(sshsGetRelativeNode(moduleData->moduleNode, "bias/"), moduleData); systemConfigSend(sshsGetRelativeNode(moduleData->moduleNode, "system/"), moduleData); usbConfigSend(sshsGetRelativeNode(moduleData->moduleNode, "usb/"), moduleData); dvsConfigSend(sshsGetRelativeNode(moduleData->moduleNode, "dvs/"), moduleData); }
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 caerInputEDVSConfigInit(sshsNode moduleNode) { // Serial port settings. sshsNodeCreateString( moduleNode, "serialPort", "/dev/ttyUSB0", 0, 128, SSHS_FLAGS_NORMAL, "Serial port to connect to."); sshsNodeCreateInt(moduleNode, "baudRate", CAER_HOST_CONFIG_SERIAL_BAUD_RATE_12M, 0, 20000000, SSHS_FLAGS_NORMAL, "Baud-rate for serial port."); // Add auto-restart setting. sshsNodeCreateBool( moduleNode, "autoRestart", true, SSHS_FLAGS_NORMAL, "Automatically restart module after shutdown."); // Set default biases, from EDVSFast.xml settings. sshsNode biasNode = sshsGetRelativeNode(moduleNode, "bias/"); sshsNodeCreateInt(biasNode, "cas", 1992, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "Photoreceptor cascode."); sshsNodeCreateInt( biasNode, "injGnd", 1108364, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "Differentiator switch level."); sshsNodeCreateInt(biasNode, "reqPd", 16777215, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "AER request pull-down."); sshsNodeCreateInt( biasNode, "puX", 8159221, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "2nd dimension AER static pull-up."); sshsNodeCreateInt( biasNode, "diffOff", 132, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "OFF threshold - lower to raise threshold."); sshsNodeCreateInt(biasNode, "req", 309590, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "OFF request inverter bias."); sshsNodeCreateInt(biasNode, "refr", 969, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "Refractory period."); sshsNodeCreateInt( biasNode, "puY", 16777215, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "1st dimension AER static pull-up."); sshsNodeCreateInt(biasNode, "diffOn", 209996, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "ON threshold - higher to raise threshold."); sshsNodeCreateInt(biasNode, "diff", 13125, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "Differentiator."); sshsNodeCreateInt(biasNode, "foll", 271, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "Source follower buffer between photoreceptor and differentiator."); sshsNodeCreateInt(biasNode, "pr", 217, 0, (0x01 << 24) - 1, SSHS_FLAGS_NORMAL, "Photoreceptor."); // DVS settings. sshsNode dvsNode = sshsGetRelativeNode(moduleNode, "dvs/"); sshsNodeCreateBool(dvsNode, "Run", true, SSHS_FLAGS_NORMAL, "Run DVS to get polarity events."); sshsNodeCreateBool(dvsNode, "TimestampReset", false, SSHS_FLAGS_NOTIFY_ONLY, "Reset timestamps to zero."); // Serial communication buffer settings. sshsNode serialNode = sshsGetRelativeNode(moduleNode, "serial/"); sshsNodeCreateInt(serialNode, "ReadSize", 1024, 128, 32768, SSHS_FLAGS_NORMAL, "Size in bytes of data buffer for serial port read operations."); sshsNode sysNode = sshsGetRelativeNode(moduleNode, "system/"); // Packet settings (size (in events) and time interval (in µs)). sshsNodeCreateInt(sysNode, "PacketContainerMaxPacketSize", 0, 0, 10 * 1024 * 1024, SSHS_FLAGS_NORMAL, "Maximum packet size in events, when any packet reaches this size, the EventPacketContainer is sent for " "processing."); sshsNodeCreateInt(sysNode, "PacketContainerInterval", 10000, 1, 120 * 1000 * 1000, SSHS_FLAGS_NORMAL, "Time interval in µs, each sent EventPacketContainer will span this interval."); // Ring-buffer setting (only changes value on module init/shutdown cycles). sshsNodeCreateInt(sysNode, "DataExchangeBufferSize", 64, 8, 1024, SSHS_FLAGS_NORMAL, "Size of EventPacketContainer queue, used for transfers between data acquisition thread and mainloop."); }
static void createDefaultConfiguration(caerModuleData moduleData) { // First, always create all needed setting nodes, set their default values // and add their listeners. // Set default biases, from DVS128Fast.xml settings. sshsNode biasNode = sshsGetRelativeNode(moduleData->moduleNode, "bias/"); sshsNodePutIntIfAbsent(biasNode, "cas", 1992); sshsNodePutIntIfAbsent(biasNode, "injGnd", 1108364); sshsNodePutIntIfAbsent(biasNode, "reqPd", 16777215); sshsNodePutIntIfAbsent(biasNode, "puX", 8159221); sshsNodePutIntIfAbsent(biasNode, "diffOff", 132); sshsNodePutIntIfAbsent(biasNode, "req", 309590); sshsNodePutIntIfAbsent(biasNode, "refr", 969); sshsNodePutIntIfAbsent(biasNode, "puY", 16777215); sshsNodePutIntIfAbsent(biasNode, "diffOn", 209996); sshsNodePutIntIfAbsent(biasNode, "diff", 13125); sshsNodePutIntIfAbsent(biasNode, "foll", 271); sshsNodePutIntIfAbsent(biasNode, "pr", 217); sshsNodeAddAttributeListener(biasNode, moduleData, &biasConfigListener); // DVS settings. sshsNode dvsNode = sshsGetRelativeNode(moduleData->moduleNode, "dvs/"); sshsNodePutBoolIfAbsent(dvsNode, "Run", true); sshsNodePutBoolIfAbsent(dvsNode, "TimestampReset", false); sshsNodePutBoolIfAbsent(dvsNode, "ArrayReset", false); sshsNodeAddAttributeListener(dvsNode, moduleData, &dvsConfigListener); // USB buffer settings. sshsNode usbNode = sshsGetRelativeNode(moduleData->moduleNode, "usb/"); sshsNodePutIntIfAbsent(usbNode, "BufferNumber", 8); sshsNodePutIntIfAbsent(usbNode, "BufferSize", 4096); sshsNodeAddAttributeListener(usbNode, moduleData, &usbConfigListener); sshsNode sysNode = sshsGetRelativeNode(moduleData->moduleNode, "system/"); // Packet settings (size (in events) and time interval (in µs)). sshsNodePutIntIfAbsent(sysNode, "PacketContainerMaxSize", 4096 + 128); sshsNodePutIntIfAbsent(sysNode, "PacketContainerMaxInterval", 5000); sshsNodePutIntIfAbsent(sysNode, "PolarityPacketMaxSize", 4096); sshsNodePutIntIfAbsent(sysNode, "PolarityPacketMaxInterval", 5000); sshsNodePutIntIfAbsent(sysNode, "SpecialPacketMaxSize", 128); sshsNodePutIntIfAbsent(sysNode, "SpecialPacketMaxInterval", 1000); // Ring-buffer setting (only changes value on module init/shutdown cycles). sshsNodePutIntIfAbsent(sysNode, "DataExchangeBufferSize", 64); sshsNodeAddAttributeListener(sysNode, moduleData, &systemConfigListener); }
static void sendDefaultConfiguration(caerModuleData moduleData, struct caer_davis_info *devInfo) { // Device related configuration has its own sub-node. sshsNode deviceConfigNode = sshsGetRelativeNode(moduleData->moduleNode, chipIDToName(devInfo->chipID, true)); // Send cAER configuration to libcaer and device. biasConfigSend(sshsGetRelativeNode(deviceConfigNode, "bias/"), moduleData, devInfo); chipConfigSend(sshsGetRelativeNode(deviceConfigNode, "chip/"), moduleData, devInfo); systemConfigSend(sshsGetRelativeNode(moduleData->moduleNode, "system/"), moduleData); usbConfigSend(sshsGetRelativeNode(deviceConfigNode, "usb/"), moduleData); muxConfigSend(sshsGetRelativeNode(deviceConfigNode, "multiplexer/"), moduleData); dvsConfigSend(sshsGetRelativeNode(deviceConfigNode, "dvs/"), moduleData, devInfo); apsConfigSend(sshsGetRelativeNode(deviceConfigNode, "aps/"), moduleData, devInfo); imuConfigSend(sshsGetRelativeNode(deviceConfigNode, "imu/"), moduleData, devInfo); extInputConfigSend(sshsGetRelativeNode(deviceConfigNode, "externalInput/"), moduleData, devInfo); }
static void createDefaultUSBConfiguration(caerModuleData moduleData, const char *nodePrefix) { // Device related configuration has its own sub-node. sshsNode deviceConfigNode = sshsGetRelativeNode(moduleData->moduleNode, nodePrefix); // Subsystem 9: FX2/3 USB Configuration and USB buffer settings. sshsNode usbNode = sshsGetRelativeNode(deviceConfigNode, "usb/"); sshsNodeCreateBool( usbNode, "Run", true, SSHS_FLAGS_NORMAL, "Enable the USB state machine (FPGA to USB data exchange)."); sshsNodeCreateInt(usbNode, "EarlyPacketDelay", 8, 1, 8000, SSHS_FLAGS_NORMAL, "Send early USB packets if this timeout is reached (in 125µs time-slices)."); sshsNodeCreateInt(usbNode, "BufferNumber", 8, 2, 128, SSHS_FLAGS_NORMAL, "Number of USB transfers."); sshsNodeCreateInt( usbNode, "BufferSize", 8192, 512, 32768, SSHS_FLAGS_NORMAL, "Size in bytes of data buffers for USB transfers."); }
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 void caerVisualizerEventHandlerNeuronMonitor(caerVisualizerPublicState state, const sf::Event &event) { // This only works with actual hardware. const std::string moduleLibrary = sshsNodeGetStdString(state->eventSourceConfigNode, "moduleLibrary"); if (moduleLibrary != "caer_dynapse") { return; } // On release of left click. if (event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Button::Left) { float positionX = (float) event.mouseButton.x; float positionY = (float) event.mouseButton.y; // Adjust coordinates according to zoom factor. float currentZoomFactor = state->renderZoomFactor.load(); if (currentZoomFactor > 1.0f) { positionX = floorf(positionX / currentZoomFactor); positionY = floorf(positionY / currentZoomFactor); } else if (currentZoomFactor < 1.0f) { positionX = floorf(positionX * currentZoomFactor); positionY = floorf(positionY * currentZoomFactor); } // Transform into chip ID, core ID and neuron ID. const struct caer_spike_event val = caerDynapseSpikeEventFromXY(U16T(positionX), U16T(positionY)); uint8_t chipId = caerSpikeEventGetChipID(&val); uint8_t coreId = caerSpikeEventGetSourceCoreID(&val); uint32_t neuronId = caerSpikeEventGetNeuronID(&val); // Set value via SSHS. sshsNode neuronMonitorNode = sshsGetRelativeNode(state->eventSourceConfigNode, "NeuronMonitor/"); char monitorKey[] = "Ux_Cy"; monitorKey[1] = (char) (48 + chipId); monitorKey[4] = (char) (48 + coreId); sshsNodePutInt(neuronMonitorNode, monitorKey, I32T(neuronId)); caerLog(CAER_LOG_NOTICE, "Visualizer", "Monitoring neuron - chip ID: %d, core ID: %d, neuron ID: %d.", chipId, coreId, neuronId); } }
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 bool caerInputEDVSInit(caerModuleData moduleData) { caerModuleLog(moduleData, CAER_LOG_DEBUG, "Initializing module ..."); // Start data acquisition, and correctly notify mainloop of new data and module of exceptional // shutdown cases (device pulled, ...). char *serialPortName = sshsNodeGetString(moduleData->moduleNode, "serialPort"); moduleData->moduleState = caerDeviceOpenSerial(U16T(moduleData->moduleID), CAER_DEVICE_EDVS, serialPortName, U32T(sshsNodeGetInt(moduleData->moduleNode, "baudRate"))); free(serialPortName); if (moduleData->moduleState == NULL) { // Failed to open device. return (false); } // Initialize per-device log-level to module log-level. caerDeviceConfigSet(moduleData->moduleState, CAER_HOST_CONFIG_LOG, CAER_HOST_CONFIG_LOG_LEVEL, atomic_load(&moduleData->moduleLogLevel)); // Put global source information into SSHS. struct caer_edvs_info devInfo = caerEDVSInfoGet(moduleData->moduleState); sshsNode sourceInfoNode = sshsGetRelativeNode(moduleData->moduleNode, "sourceInfo/"); sshsNodeCreateBool(sourceInfoNode, "deviceIsMaster", devInfo.deviceIsMaster, SSHS_FLAGS_READ_ONLY | SSHS_FLAGS_NO_EXPORT, "Timestamp synchronization support: device master status."); sshsNodeCreateInt(sourceInfoNode, "polaritySizeX", devInfo.dvsSizeX, devInfo.dvsSizeX, devInfo.dvsSizeX, SSHS_FLAGS_READ_ONLY | SSHS_FLAGS_NO_EXPORT, "Polarity events width."); sshsNodeCreateInt(sourceInfoNode, "polaritySizeY", devInfo.dvsSizeY, devInfo.dvsSizeY, devInfo.dvsSizeY, SSHS_FLAGS_READ_ONLY | SSHS_FLAGS_NO_EXPORT, "Polarity events height."); // Put source information for generic visualization, to be used to display and debug filter information. sshsNodeCreateInt(sourceInfoNode, "dataSizeX", devInfo.dvsSizeX, devInfo.dvsSizeX, devInfo.dvsSizeX, SSHS_FLAGS_READ_ONLY | SSHS_FLAGS_NO_EXPORT, "Data width."); sshsNodeCreateInt(sourceInfoNode, "dataSizeY", devInfo.dvsSizeY, devInfo.dvsSizeY, devInfo.dvsSizeY, SSHS_FLAGS_READ_ONLY | SSHS_FLAGS_NO_EXPORT, "Data height."); // Generate source string for output modules. size_t sourceStringLength = (size_t) snprintf(NULL, 0, "#Source %" PRIu16 ": eDVS4337\r\n", moduleData->moduleID); char sourceString[sourceStringLength + 1]; snprintf(sourceString, sourceStringLength + 1, "#Source %" PRIu16 ": eDVS4337\r\n", moduleData->moduleID); sourceString[sourceStringLength] = '\0'; sshsNodeCreateString(sourceInfoNode, "sourceString", sourceString, sourceStringLength, sourceStringLength, SSHS_FLAGS_READ_ONLY | SSHS_FLAGS_NO_EXPORT, "Device source information."); // 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. sendDefaultConfiguration(moduleData); // Start data acquisition. bool ret = caerDeviceDataStart(moduleData->moduleState, &caerMainloopDataNotifyIncrease, &caerMainloopDataNotifyDecrease, NULL, &moduleShutdownNotify, moduleData->moduleNode); if (!ret) { // Failed to start data acquisition, close device and exit. caerDeviceClose((caerDeviceHandle *) &moduleData->moduleState); return (false); } // Add config listeners last, to avoid having them dangling if Init doesn't succeed. sshsNode biasNode = sshsGetRelativeNode(moduleData->moduleNode, "bias/"); sshsNodeAddAttributeListener(biasNode, moduleData, &biasConfigListener); sshsNode dvsNode = sshsGetRelativeNode(moduleData->moduleNode, "dvs/"); sshsNodeAddAttributeListener(dvsNode, moduleData, &dvsConfigListener); sshsNode serialNode = sshsGetRelativeNode(moduleData->moduleNode, "serial/"); sshsNodeAddAttributeListener(serialNode, moduleData, &serialConfigListener); sshsNode sysNode = sshsGetRelativeNode(moduleData->moduleNode, "system/"); sshsNodeAddAttributeListener(sysNode, moduleData, &systemConfigListener); sshsNodeAddAttributeListener(moduleData->moduleNode, moduleData, &logLevelListener); return (true); }
static bool caerInputDAVISInit(caerModuleData moduleData) { caerModuleLog(moduleData, CAER_LOG_DEBUG, "Initializing module ..."); // 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(U16T(moduleData->moduleID), CAER_DEVICE_DAVIS, U8T(sshsNodeGetInt(moduleData->moduleNode, "busNumber")), U8T(sshsNodeGetInt(moduleData->moduleNode, "devAddress")), serialNumber); free(serialNumber); if (moduleData->moduleState == NULL) { // Failed to open device. return (false); } struct caer_davis_info devInfo = caerDavisInfoGet(moduleData->moduleState); caerInputDAVISCommonInit(moduleData, &devInfo); // Generate sub-system string for module. char *prevAdditionStart = strchr(moduleData->moduleSubSystemString, '['); if (prevAdditionStart != NULL) { *prevAdditionStart = '\0'; } size_t subSystemStringLength = (size_t) snprintf(NULL, 0, "%s[SN %s, %" PRIu8 ":%" PRIu8 "]", moduleData->moduleSubSystemString, devInfo.deviceSerialNumber, devInfo.deviceUSBBusNumber, devInfo.deviceUSBDeviceAddress); char subSystemString[subSystemStringLength + 1]; snprintf(subSystemString, subSystemStringLength + 1, "%s[SN %s, %" PRIu8 ":%" PRIu8 "]", moduleData->moduleSubSystemString, devInfo.deviceSerialNumber, devInfo.deviceUSBBusNumber, devInfo.deviceUSBDeviceAddress); subSystemString[subSystemStringLength] = '\0'; caerModuleSetSubSystemString(moduleData, subSystemString); // Create default settings and send them to the device. createDefaultBiasConfiguration(moduleData, chipIDToName(devInfo.chipID, true), devInfo.chipID); createDefaultLogicConfiguration(moduleData, chipIDToName(devInfo.chipID, true), &devInfo); createDefaultUSBConfiguration(moduleData, chipIDToName(devInfo.chipID, true)); sendDefaultConfiguration(moduleData, &devInfo); // Start data acquisition. bool ret = caerDeviceDataStart(moduleData->moduleState, &caerMainloopDataNotifyIncrease, &caerMainloopDataNotifyDecrease, NULL, &moduleShutdownNotify, moduleData->moduleNode); if (!ret) { // Failed to start data acquisition, close device and exit. caerDeviceClose((caerDeviceHandle *) &moduleData->moduleState); return (false); } // Device related configuration has its own sub-node. sshsNode deviceConfigNode = sshsGetRelativeNode(moduleData->moduleNode, chipIDToName(devInfo.chipID, true)); // Add config listeners last, to avoid having them dangling if Init doesn't succeed. sshsNode chipNode = sshsGetRelativeNode(deviceConfigNode, "chip/"); sshsNodeAddAttributeListener(chipNode, moduleData, &chipConfigListener); sshsNode muxNode = sshsGetRelativeNode(deviceConfigNode, "multiplexer/"); sshsNodeAddAttributeListener(muxNode, moduleData, &muxConfigListener); sshsNode dvsNode = sshsGetRelativeNode(deviceConfigNode, "dvs/"); sshsNodeAddAttributeListener(dvsNode, moduleData, &dvsConfigListener); sshsNode apsNode = sshsGetRelativeNode(deviceConfigNode, "aps/"); sshsNodeAddAttributeListener(apsNode, moduleData, &apsConfigListener); sshsNode imuNode = sshsGetRelativeNode(deviceConfigNode, "imu/"); sshsNodeAddAttributeListener(imuNode, moduleData, &imuConfigListener); sshsNode extNode = sshsGetRelativeNode(deviceConfigNode, "externalInput/"); sshsNodeAddAttributeListener(extNode, moduleData, &extInputConfigListener); sshsNode usbNode = sshsGetRelativeNode(deviceConfigNode, "usb/"); sshsNodeAddAttributeListener(usbNode, moduleData, &usbConfigListener); sshsNode sysNode = sshsGetRelativeNode(moduleData->moduleNode, "system/"); sshsNodeAddAttributeListener(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++) { // Add listener for this particular bias. sshsNodeAddAttributeListener(biasNodes[i], moduleData, &biasConfigListener); } free(biasNodes); } sshsNodeAddAttributeListener(moduleData->moduleNode, moduleData, &logLevelListener); return (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); } }