diff --git a/deviceConfigs/behaviorCams.json b/deviceConfigs/behaviorCams.json index 284a046..2e18a3d 100644 --- a/deviceConfigs/behaviorCams.json +++ b/deviceConfigs/behaviorCams.json @@ -15,14 +15,15 @@ "frameRate": "adjustable", "width": 1024, "height": 768, + "pixelClock": 96, "headOrientation": false, "isColor": false, "controlSettings": { "gain": { - "displaySpinBoxValues":["Low", "Medium", "High"], - "displayTextValues": [1, 4, 8], - "outputValues":[8,32,96], - "startValue": "Low", + "displaySpinBoxValues":["1X", "8X", "16X", "32X"], + "displayTextValues": [1, 8, 16,32], + "outputValues":[8,96,2144,6240], + "startValue": "1X", "sendCommand": [ { "protocol": "I2C", @@ -36,10 +37,10 @@ ] }, "frameRate": { - "displaySpinBoxValues":["10FPS", "30FPS", "45FPS"], - "displayTextValues": [10, 30, 45], - "outputValues":[2048,1536,1024], - "startValue": "45FPS", + "displaySpinBoxValues":["10FPS", "40FPS", "50FPS"], + "displayTextValues": [10, 40, 50], + "outputValues":[2048,1536,766], + "startValue": "50FPS", "sendCommand": [ { "protocol": "I2C", @@ -51,9 +52,9 @@ "data1": "valueL" } ] - }, - "led0": { - "startValue": 0, + }, + "led0": { + "startValue": 20, "min": 0, "max": 100, "stepSize": 1, @@ -71,7 +72,17 @@ ] } }, - "initialize": [ + + "initialize": [ + { + "description": "Make sure DES has SER ADDR", + "protocol": "I2C", + "addressW": "0xC0", + "regLength": "1", + "reg0": "0x07", + "dataLength": "1", + "data0": "0xB0" + }, { "description": "Speed up i2c bus timer to 50us max", "protocol": "I2C", @@ -90,15 +101,6 @@ "dataLength": "1", "data0": "0b00001010" }, - { - "description": "Make sure DES has SER ADDR", - "protocol": "I2C", - "addressW": "0x07", - "regLength": "1", - "reg0": "0x07", - "dataLength": "1", - "data0": "0xB0" - }, { "description": "Speed up I2c bus timer to 50u Max", "protocol": "I2C", @@ -126,9 +128,9 @@ "dataLength": "2", "device0": "MT9P031", "data0": "0xBA", - "device1": "Digital LED Driver", + "device1": "Digital LED Driver", "data1": "0x6C" - + }, { "description": "sets sudo allowable i2c addresses to send through serializer", @@ -139,11 +141,31 @@ "dataLength": "2", "device0": "MT9P031", "data0": "0xBA", - "device1": "Digital LED Driver", + "device1": "Digital LED Driver", "data1": "0x6C" - - }, - { + }, + { + "description": "1535 Rows", + "protocol": "I2C", + "addressW": "0xBA", + "regLength": "1", + "reg0": "0x03", + "dataLength": "2", + "data0": "0b00000101", + "data1": "0b11111111" + }, + { + "description": "2047 Colums", + "protocol": "I2C", + "addressW": "0xBA", + "regLength": "1", + "reg0": "0x04", + "dataLength": "2", + "data0": "0b00000111", + "data1": "0b11111111" + }, + + { "description": "2x subsamp and binning 1", "protocol": "I2C", "addressW": "0xBA", @@ -173,6 +195,16 @@ "data0": "0x00", "data1": "0b01100000" }, + { + "description": "Set R0X03E to 0X00C0 when Sensor Gain>4", + "protocol": "I2C", + "addressW": "0xBA", + "regLength": "1", + "reg0": "0x3E", + "dataLength": "2", + "data0": "0x00", + "data1": "0xC0" + }, { "description": "Change shutter width", "protocol": "I2C", @@ -180,9 +212,9 @@ "regLength": "1", "reg0": "0x09", "dataLength": "2", - "data0": "0b00000100", - "data1": "0x00" - }, + "data0": "0b00000010", + "data1": "0b11111111" + }, { "description": "LED Driver LM3509", "protocol": "I2C", @@ -193,6 +225,7 @@ "data0": "0b11010111" } - ] + + ] } } diff --git a/deviceConfigs/miniscopes.json b/deviceConfigs/miniscopes.json index 68b2faf..07498bf 100644 --- a/deviceConfigs/miniscopes.json +++ b/deviceConfigs/miniscopes.json @@ -5,6 +5,7 @@ "frameRate": "adjustable", "width": 608, "height": 608, + "pixelClock": 16.6, "headOrientation": true, "isColor": false, "controlSettings": { @@ -53,7 +54,7 @@ "max": 100, "stepSize": 1, "displayValueScale": -2.55, - "displayValueOffset": -255, + "displayValueOffset": 0, "sendCommand": [ { "protocol": "I2C", @@ -217,6 +218,7 @@ "frameRate": "adjustable", "width": 608, "height": 608, + "pixelClock": 16.6, "headOrientation": false, "isColor": false, "controlSettings": { @@ -398,6 +400,7 @@ "frameRate": "adjustable", "width": 752, "height": 480, + "pixelClock": 26, "headOrientation": false, "isColor": false, "controlSettings": { @@ -560,20 +563,21 @@ } ] }, - "Siminiscope_Bin2x": { + "Siminiscope_1024X768": { "qmlFile": "qrc:/Miniscope_V4_BNO.qml", "sensor": "MT9P031", "frameRate": "adjustable", - "width": 1296, - "height": 972, - "headOrientation": true, + "width": 1024, + "height": 768, + "pixelClock": 96, + "headOrientation": false, "isColor": false, "controlSettings": { "gain": { - "displaySpinBoxValues":["Low", "Medium", "High"], - "displayTextValues": [1, 4, 8], - "outputValues":[8,32,96], - "startValue": "Low", + "displaySpinBoxValues":["1X", "8X", "16X", "32X"], + "displayTextValues": [1, 8, 16,32], + "outputValues":[8,96,2144,6240], + "startValue": "1X", "sendCommand": [ { "protocol": "I2C", @@ -587,10 +591,10 @@ ] }, "frameRate": { - "displaySpinBoxValues":["10FPS", "15FPS", "20FPS"], - "displayTextValues": [10, 15, 20], - "outputValues":[2048,1536,1024], - "startValue": "20FPS", + "displaySpinBoxValues":["10FPS", "40FPS", "50FPS"], + "displayTextValues": [10, 40, 50], + "outputValues":[2048,1536,766], + "startValue": "40FPS", "sendCommand": [ { "protocol": "I2C", @@ -603,72 +607,53 @@ } ] }, - "led0": { - "startValue": 0, + "led0": { + "startValue": 20, "min": 0, "max": 100, "stepSize": 1, - "displayValueScale": -2.55, - "displayValueOffset": -255, - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b01011000", - "regLength": "1", - "reg0": "0x00", - "dataLength": "2", - "data0": "value", - "data1": "value" - } - ] - }, - "ewl": { - "startValue": 0, - "min": -127, - "max": 127, - "stepSize": 1, - "displayValueScale": 1, - "displayValueOffset": -127, + "displayValueScale": 0.31, + "displayValueOffset": 0, "sendCommand": [ { "protocol": "I2C", - "addressW": "0b11101110", + "addressW": "0x6C", "regLength": "1", - "reg0": "0x08", - "dataLength": "2", - "data0": "value", - "data1": "0x02" + "reg0": "0b10100000", + "dataLength": "1", + "data0": "value" } ] } }, - "initialize": [ + + "initialize": [ { - "description": "Speed up i2c bus timer to 50us max", + "description": "Make sure DES has SER ADDR", "protocol": "I2C", "addressW": "0xC0", "regLength": "1", - "reg0": "0x22", + "reg0": "0x07", "dataLength": "1", - "data0": "0b00000010" + "data0": "0xB0" }, { - "description": "Decrease BCC timeout, units in 2ms XX", + "description": "Speed up i2c bus timer to 50us max", "protocol": "I2C", "addressW": "0xC0", "regLength": "1", - "reg0": "0x20", + "reg0": "0x22", "dataLength": "1", - "data0": "0b00001010" + "data0": "0b00000010" }, { - "description": "Make sure DES has SER ADDR", + "description": "Decrease BCC timeout, units in 2ms XX", "protocol": "I2C", "addressW": "0xC0", "regLength": "1", - "reg0": "0x07", + "reg0": "0x20", "dataLength": "1", - "data0": "0xB0" + "data0": "0b00001010" }, { "description": "Speed up I2c bus timer to 50u Max", @@ -694,15 +679,12 @@ "addressW": "0xC0", "regLength": "1", "reg0": "0x08", - "dataLength": "4", + "dataLength": "2", "device0": "MT9P031", "data0": "0xBA", - "device1": "EWL Driver", - "data1": "0b11101110", - "device2": "Digital Pot", - "data2": "0b10100000", - "device3": "BNO", - "data3": "0b01010000" + "device1": "Digital LED Driver", + "data1": "0x6C" + }, { "description": "sets sudo allowable i2c addresses to send through serializer", @@ -710,52 +692,33 @@ "addressW": "0xC0", "regLength": "1", "reg0": "0x10", - "dataLength": "4", + "dataLength": "2", "device0": "MT9P031", "data0": "0xBA", - "device1": "EWL Driver", - "data1": "0b11101110", - "device2": "Digital Pot Sudo", - "data2": "0b01011000", - "device3": "BNO", - "data3": "0b01010000" + "device1": "Digital LED Driver", + "data1": "0x6C" }, - { - "description": "Remap BNO axes, and sign", + { + "description": "1535 Rows", "protocol": "I2C", - "addressW": "0b01010000", + "addressW": "0xBA", "regLength": "1", - "reg0": "0x41", + "reg0": "0x03", "dataLength": "2", - "data0": "0b00001001", - "data1": "0b00000101" - }, - { - "description": "Set BNO operation mode to NDOF", - "protocol": "I2C", - "addressW": "0b01010000", - "regLength": "1", - "reg0": "0x3D", - "dataLength": "1", - "data0": "0b00001100" - }, - { - "description": "Enable BNO streaming in DAQ", - "protocol": "I2C", - "addressW": "0xFE", - "regLength": "1", - "reg0": "0x00", - "dataLength": "0" - }, - { - "description": "Enable EWL Driver", + "data0": "0b00000101", + "data1": "0b11111111" + }, + { + "description": "2047 Colums", "protocol": "I2C", - "addressW": "0b11101110", + "addressW": "0xBA", "regLength": "1", - "reg0": "0x03", - "dataLength": "1", - "data0": "0x03" - }, + "reg0": "0x04", + "dataLength": "2", + "data0": "0b00000111", + "data1": "0b11111111" + }, + { "description": "2x subsamp and binning 1", "protocol": "I2C", @@ -786,6 +749,16 @@ "data0": "0x00", "data1": "0b01100000" }, + { + "description": "Set R0X03E to 0X00C0 when Sensor Gain>4", + "protocol": "I2C", + "addressW": "0xBA", + "regLength": "1", + "reg0": "0x3E", + "dataLength": "2", + "data0": "0x00", + "data1": "0xC0" + }, { "description": "Change shutter width", "protocol": "I2C", @@ -793,414 +766,20 @@ "regLength": "1", "reg0": "0x09", "dataLength": "2", - "data0": "0b00000100", - "data1": "0x00" - } - - ] - }, - "Miniscope_V4_2C": { - "qmlFile": "qrc:/Miniscope_V4_BNO.qml", - "sensor": "PYTHON480", - "frameRate": "adjustable", - "width": 608, - "height": 608, - "headOrientation": true, - "isColor": false, - "controlSettings": { - "gain": { - "displaySpinBoxValues":["Low", "Medium", "High"], - "displayTextValues": [1, 2, 3.5], - "outputValues":[225,228,36], - "startValue": "Low", - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b00100000", - "regLength": "1", - "reg0": "0x05", - "dataLength": "4", - "data0": "0x00", - "data1": "0xCC", - "data2": "valueH", - "data3": "valueL" - } - ] - }, - "frameRate": { - "displaySpinBoxValues":["10FPS", "15FPS", "20FPS", "25FPS", "30FPS"], - "displayTextValues": [10, 15, 20, 25, 30], - "outputValues":[10000,6667,5000, 4000, 3300], - "startValue": "20FPS", - "sendCommand": [ - - { - "protocol": "I2C", - "addressW": "0b00100000", - "regLength": "1", - "reg0": "0x05", - "dataLength": "4", - "data0": "0x00", - "data1": "0xC9", - "data2": "valueH", - "data3": "valueL" - } - ] - }, - "led0": { - "startValue": 0, - "min": 0, - "max": 100, - "stepSize": 1, - "displayValueScale": -2.55, - "displayValueOffset": -255, - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b00100000", - "regLength": "1", - "reg0": "0x01", - "dataLength": "1", - "data0": "value" - }, - { - "protocol": "I2C", - "addressW": "0b01011000", - "regLength": "1", - "reg0": "0x01", - "dataLength": "1", - "data0": "value" - } - ] - }, - "led1": { - "startValue": 0, - "min": 0, - "max": 100, - "stepSize": 1, - "displayValueScale": -2.55, - "displayValueOffset": -255, - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b00100000", - "regLength": "1", - "reg0": "0x02", - "dataLength": "1", - "data0": "value" - }, - { - "protocol": "I2C", - "addressW": "0b01011000", - "regLength": "1", - "reg0": "0x00", - "dataLength": "1", - "data0": "value" - } - ] - }, - "ewl": { - "startValue": 0, - "min": -127, - "max": 127, - "stepSize": 1, - "displayValueScale": 1, - "displayValueOffset": -127, - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b11101110", - "regLength": "1", - "reg0": "0x08", - "dataLength": "2", - "data0": "value", - "data1": "0x02" - } - ] - } - }, - "initialize": [ - { - "description": "Speed up i2c bus timer to 50us max", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x22", - "dataLength": "1", - "data0": "0b00000010" - }, - { - "description": "Decrease BCC timeout, units in 2ms XX", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x20", - "dataLength": "1", - "data0": "0b00001010" - }, - { - "description": "Make sure DES has SER ADDR", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x07", - "dataLength": "1", - "data0": "0xB0" - }, - { - "description": "Speed up I2c bus timer to 50u Max", - "protocol": "I2C", - "addressW": "0xB0", - "regLength": "1", - "reg0": "0x0F", - "dataLength": "1", - "data0": "0b00000010" - }, - { - "description": "Decrease BCC timeout, units in 2ms", - "protocol": "I2C", - "addressW": "0xB0", - "regLength": "1", - "reg0": "0x1E", - "dataLength": "1", - "data0": "0b00001010" - }, - { - "description": "sets allowable i2c addresses to send through serializer", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x08", - "dataLength": "4", - "device0": "MCU", - "data0": "0b00100000", - "device1": "EWL Driver", - "data1": "0b11101110", - "device2": "Digital Pot", - "data2": "0b10100000", - "device3": "BNO", - "data3": "0b01010000" - }, - { - "description": "sets sudo allowable i2c addresses to send through serializer", + "data0": "0b00000010", + "data1": "0b11111111" + }, + { + "description": "LED Driver LM3509", "protocol": "I2C", - "addressW": "0xC0", + "addressW": "0x6C", "regLength": "1", "reg0": "0x10", - "dataLength": "4", - "device0": "MCU", - "data0": "0b00100000", - "device1": "EWL Driver", - "data1": "0b11101110", - "device2": "Digital Pot Sudo", - "data2": "0b01011000", - "device3": "BNO", - "data3": "0b01010000" - }, - { - "description": "Remap BNO axes, and sign", - "protocol": "I2C", - "addressW": "0b01010000", - "regLength": "1", - "reg0": "0x41", - "dataLength": "2", - "data0": "0b00001001", - "data1": "0b00000101" - }, - { - "description": "Set BNO operation mode to NDOF", - "protocol": "I2C", - "addressW": "0b01010000", - "regLength": "1", - "reg0": "0x3D", - "dataLength": "1", - "data0": "0b00001100" - }, - { - "description": "Enable BNO streaming in DAQ", - "protocol": "I2C", - "addressW": "0xFE", - "regLength": "1", - "reg0": "0x01", - "dataLength": "0" - }, - { - "description": "Enable EWL Driver", - "protocol": "I2C", - "addressW": "0b11101110", - "regLength": "1", - "reg0": "0x03", "dataLength": "1", - "data0": "0x03" - } + "data0": "0b11010111" + + } - ] - }, - "MiniLFM": { - "qmlFile": "qrc:/Miniscope_V4_BNO.qml", - "sensor": "MT9P031", - "frameRate": "adjustable", - "width": 2592, - "height": 1944, - "headOrientation": false, - "isColor": false, - "controlSettings": { - "gain": { - "displaySpinBoxValues":["Low", "Medium", "High"], - "displayTextValues": [1, 4, 8], - "outputValues":[8,32,96], - "startValue": "Low", - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0xBA", - "regLength": "1", - "reg0": "0x35", - "dataLength": "2", - "data0": "valueH", - "data1": "valueL" - } - ] - }, - "frameRate": { - "displaySpinBoxValues":["10FPS", "15FPS", "20FPS"], - "displayTextValues": [10, 15, 20], - "outputValues":[2048,1536,1024], - "startValue": "20FPS", - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0xBA", - "regLength": "1", - "reg0": "0x09", - "dataLength": "2", - "data0": "valueH", - "data1": "valueL" - } - ] - }, - "led0": { - "startValue": 0, - "min": 0, - "max": 100, - "stepSize": 1, - "displayValueScale": -2.55, - "displayValueOffset": -255, - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b01011000", - "regLength": "1", - "reg0": "0x00", - "dataLength": "2", - "data0": "value", - "data1": "value" - } - ] - }, - "ewl": { - "startValue": 0, - "min": -127, - "max": 127, - "stepSize": 1, - "displayValueScale": 1, - "displayValueOffset": -127, - "sendCommand": [ - { - "protocol": "I2C", - "addressW": "0b11101110", - "regLength": "1", - "reg0": "0x08", - "dataLength": "2", - "data0": "value", - "data1": "0x02" - } - ] - } - }, - "initialize": [ - { - "description": "Speed up i2c bus timer to 50us max", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x22", - "dataLength": "1", - "data0": "0b00000010" - }, - { - "description": "Decrease BCC timeout, units in 2ms XX", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x20", - "dataLength": "1", - "data0": "0b00001010" - }, - { - "description": "Make sure DES has SER ADDR", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x07", - "dataLength": "1", - "data0": "0xB0" - }, - { - "description": "Speed up I2c bus timer to 50u Max", - "protocol": "I2C", - "addressW": "0xB0", - "regLength": "1", - "reg0": "0x0F", - "dataLength": "1", - "data0": "0b00000010" - }, - { - "description": "Decrease BCC timeout, units in 2ms", - "protocol": "I2C", - "addressW": "0xB0", - "regLength": "1", - "reg0": "0x1E", - "dataLength": "1", - "data0": "0b00001010" - }, - { - "description": "sets allowable i2c addresses to send through serializer", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x08", - "dataLength": "3", - "device0": "MT9P031", - "data0": "0xBA", - "device1": "EWL Driver", - "data1": "0b11101110", - "device2": "Digital Pot", - "data2": "0b10100000" - }, - { - "description": "sets sudo allowable i2c addresses to send through serializer", - "protocol": "I2C", - "addressW": "0xC0", - "regLength": "1", - "reg0": "0x10", - "dataLength": "3", - "device0": "MT9P031", - "data0": "0xBA", - "device1": "EWL Driver", - "data1": "0b11101110", - "device2": "Digital Pot Sudo", - "data2": "0b01011000" - }, - { - "description": "Enable EWL Driver", - "protocol": "I2C", - "addressW": "0b11101110", - "regLength": "1", - "reg0": "0x03", - "dataLength": "1", - "data0": "0x03" - } - ] + ] } -} +} \ No newline at end of file diff --git a/source/Miniscope-DAQ-QT-Software.pro b/source/Miniscope-DAQ-QT-Software.pro index 19bfa0d..93cef83 100644 --- a/source/Miniscope-DAQ-QT-Software.pro +++ b/source/Miniscope-DAQ-QT-Software.pro @@ -54,13 +54,19 @@ DISTFILES += win32 { # Path to your openCV .lib file(s) LIBS += -LC:/opencv-4.4.0/build/lib/Release -lopencv_world440 -## LIBS += -LC:/opencv-4.4.0/build/lib/Debug -lopencv_world440d + +# LIBS += -LC:/opencv-4.4.0/build/lib/Debug -lopencv_world440d # Path to openCV header files INCLUDEPATH += C:/opencv-4.4.0/build/install/include # Do we need DEPENDPATH ???? # #DEPENDPATH += + + # For libusb + LIBS += -LC:/libusb-1.0.23/MS64/dll/ -llibusb-1.0 + INCLUDEPATH += C:/libusb-1.0.23/include/libusb-1.0 + } else { CONFIG += link_pkgconfig PKGCONFIG += opencv4 diff --git a/source/Miniscope_V4_BNO.qml b/source/Miniscope_V4_BNO.qml index bad9fe6..4139579 100644 --- a/source/Miniscope_V4_BNO.qml +++ b/source/Miniscope_V4_BNO.qml @@ -106,8 +106,6 @@ Item { droppedFrameCount.text = "Dropped Frames: " + videoDisplay.droppedFrameCount; } } - - } Text{ diff --git a/source/backend.cpp b/source/backend.cpp index 8e274ac..058db6a 100644 --- a/source/backend.cpp +++ b/source/backend.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,8 @@ #include "datasaver.h" #include "behaviortracker.h" +#include + //#define DEBUG backEnd::backEnd(QObject *parent) : @@ -59,6 +62,101 @@ backEnd::backEnd(QObject *parent) : dataSaver = new DataSaver(); + // ---- LIBUSB TEST ---- +// libusb_device **devs; +// int r; +// ssize_t cnt; + +// r = libusb_init(NULL); +// if (r < 0) +// qDebug() << "Problem 1 "; +// else { +// cnt = libusb_get_device_list(NULL, &devs); +// if (cnt < 0){ +// libusb_exit(NULL); +// qDebug() << "Problem 2"; +// } +// else { +// // ----------- +// libusb_device *dev; +// int i = 0, j = 0; +// uint8_t path[8]; + +// while ((dev = devs[i++]) != NULL) { +// struct libusb_device_descriptor desc; +// struct libusb_config_descriptor **configDesc; +// const struct libusb_endpoint_descriptor *epdesc; +// const struct libusb_interface_descriptor *interdesc; +// int r = libusb_get_device_descriptor(dev, &desc); +// if (r < 0) { +// qDebug() << "failed to get device descriptor"; +// } +// else { + +// qDebug() << desc.idVendor << ":" << desc.idProduct << "bus" << libusb_get_bus_number(dev) << "device" << libusb_get_device_address(dev); + +// r = libusb_get_port_numbers(dev, path, sizeof(path)); +// if (r > 0) { +// qDebug() <<"path:" << path[0]; +// for (j = 1; j < r; j++) +// qDebug() << " more paths:" << path[j]; +// } + + + + +// libusb_device_handle *d_h = NULL; +// r = libusb_open(dev,&d_h); +// if ( r == 0) { +// unsigned char name[200]; +// r = libusb_get_string_descriptor_ascii(d_h,desc.iProduct,name,200); +// if ( r > 0) { +// qDebug() << "name" << QString::fromUtf8((char *)name, r); +// } +// // libusb_set_configuration(d_h,0); +// // r = libusb_get_active_config_descriptor(dev,configDesc); +// // if (r < 0) +// // qDebug() << "Config Desc failed:" << r; +// // else { +// // qDebug() << "Number of alt settings:" << configDesc[0]->interface->num_altsetting; +// // interdesc = configDesc[0]->interface->altsetting; + +// // qDebug() << "Number of endpoints: "<< interdesc->bNumEndpoints; +// // for(int k=0; k<(int)interdesc->bNumEndpoints; k++) { +// // epdesc = &interdesc->endpoint[k]; +// // qDebug()<<"Descriptor Type: "<<(int)epdesc->bDescriptorType; +// // qDebug()<<"EP Address: "<<(int)epdesc->bEndpointAddress; +// // } +// // } +// // // } +// // libusb_free_config_descriptor(configDesc[0]); + +// libusb_claim_interface(d_h,2); +// uint8_t data[5] = {0,1,2,3,4}; +// uint8_t inData[1024]; +// int actualLength; +// qDebug() << "Sending" << data[0] << data[1] << data[2] << data[3] << data[4]; +// r = libusb_bulk_transfer(d_h,0x04|LIBUSB_ENDPOINT_OUT,data,5,NULL,1000); +// if (r != 0) +// qDebug() << "Issue sending bulk transfer to device:" << r; +// else { +// libusb_bulk_transfer(d_h,0x04|LIBUSB_ENDPOINT_IN ,inData,1024,&actualLength,1000); +// qDebug() << "Receiving" << inData[0] << inData[1] << inData[2] << inData[3] << inData[4] << "inLength:" << actualLength; +// } +// libusb_close(d_h); +// } +// else { +// qDebug() << "Open Fail:" << r; +// } +// } +// } +// // --------------- + +// libusb_free_device_list(devs, 1); +// libusb_exit(NULL); +// } +// } + testCodecSupport(); QString tempStr; diff --git a/source/behaviorCam.qml b/source/behaviorCam.qml index ba7c482..dee6f8d 100644 --- a/source/behaviorCam.qml +++ b/source/behaviorCam.qml @@ -230,6 +230,25 @@ Item { } } + Text{ + id: droppedFrameCount + objectName: "droppedFrameCount" + Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + text: "--" + font.pointSize: 10 + font.family: "Arial" + Layout.column: 0 + Layout.row: 1 + Timer{ + interval: 100 + repeat: true + running: true + onTriggered: { + droppedFrameCount.text = "Dropped Frames: " + videoDisplay.droppedFrameCount; + } + } + } + Text{ id: acqFPS objectName: "acqFPS" @@ -346,6 +365,23 @@ Item { visible: false } + VideoSpinBoxControl{ + id: frameRate + objectName: "frameRate" + iconPath: "img/icon/fps.png" + visible: false + } + VideoSpinBoxControl{ + id: gain + objectName: "gain" + iconPath: "img/icon/gain.png" + visible: false + } + + ToolSeparator { + id: toolSeparator + } + VideoSliderControl{ id: alpha objectName: "alpha" @@ -375,6 +411,14 @@ Item { target: led0 onValueChangedSignal: vidPropChangedSignal(led0.objectName, displayValue, i2cValue, i2cValue2) } + Connections{ + target: gain + onValueChangedSignal: vidPropChangedSignal(gain.objectName, displayValue, i2cValue, i2cValue2) + } + Connections{ + target: frameRate + onValueChangedSignal: vidPropChangedSignal(frameRate.objectName, displayValue, i2cValue, i2cValue2) + } Connections{ target: alpha onValueChangedSignal: vidPropChangedSignal(alpha.objectName, displayValue, i2cValue, i2cValue2) diff --git a/source/behaviorcam.cpp b/source/behaviorcam.cpp index 378f109..c91c61b 100644 --- a/source/behaviorcam.cpp +++ b/source/behaviorcam.cpp @@ -23,7 +23,7 @@ BehaviorCam::BehaviorCam(QObject *parent, QJsonObject ucBehavCam) : vidDisplay(nullptr), m_previousDisplayFrameNum(0), m_acqFrameNum(new QAtomicInt(0)), -// m_daqFrameNum(new QAtomicInt(0)), + m_daqFrameNum(new QAtomicInt(0)), m_streamHeadOrientationState(false), m_camCalibWindowOpen(false), m_camCalibRunning(false), @@ -31,12 +31,22 @@ BehaviorCam::BehaviorCam(QObject *parent, QJsonObject ucBehavCam) : { m_ucBehavCam = ucBehavCam; // hold user config for this Miniscope + parseUserConfigBehavCam(); getBehavCamConfig(m_ucBehavCam["deviceType"].toString()); // holds specific Miniscope configuration + // TODO: Handle cases where there is more than webcams and MiniCAMs + if (m_ucBehavCam["deviceType"].toString() == "WebCam") { + isMiniCAM = false; + m_daqFrameNum = nullptr; + } + else { + isMiniCAM = true; + } + // Checks to make sure user config and miniscope device type are supporting BNO streaming - m_streamHeadOrientationState = m_ucBehavCam["streamHeadOrientation"].toBool(false) && m_cBehavCam["headOrientation"].toBool(false); + m_streamHeadOrientationState = false; // Thread safe buffer stuff @@ -46,7 +56,7 @@ BehaviorCam::BehaviorCam(QObject *parent, QJsonObject ucBehavCam) : // ------------------------- // Setup OpenCV camera stream - behavCamStream = new VideoStreamOCV(nullptr, m_cBehavCam["width"].toInt(), m_cBehavCam["height"].toInt()); + behavCamStream = new VideoStreamOCV(nullptr, m_cBehavCam["width"].toInt(-1), m_cBehavCam["height"].toInt(-1), m_cBehavCam["pixelClock"].toDouble(-1)); behavCamStream->setDeviceName(m_deviceName); behavCamStream->setHeadOrientationConfig(false, false); // don't allow head orientation streaming for behavior cameras @@ -64,7 +74,7 @@ BehaviorCam::BehaviorCam(QObject *parent, QJsonObject ucBehavCam) : freeFrames, usedFrames, m_acqFrameNum, - nullptr); + m_daqFrameNum); // ----------------- @@ -82,15 +92,21 @@ BehaviorCam::BehaviorCam(QObject *parent, QJsonObject ucBehavCam) : // Pass send message signal through QObject::connect(behavCamStream, &VideoStreamOCV::sendMessage, this, &BehaviorCam::sendMessage); + // Handle request for reinitialization of commands + QObject::connect(behavCamStream, &VideoStreamOCV::requestInitCommands, this, &BehaviorCam::handleInitCommandsRequest); + // Pass new Frame available through to parent - QObject::connect(behavCamStream, &VideoStreamOCV::newFrameAvailable, this, &BehaviorCam::newFrameAvailable); +// QObject::connect(behavCamStream, &VideoStreamOCV::newFrameAvailable, this, &BehaviorCam::newFrameAvailable); // ---------------------------------------------- connectSnS(); - // sendInitCommands(); + if (isMiniCAM) + sendInitCommands(); videoStreamThread->start(); + + QThread::msleep(500); } } @@ -107,7 +123,8 @@ void BehaviorCam::createView() // TODO: Check deviceType and log correct qml file // const QUrl url("qrc:/" + m_deviceType + ".qml"); - const QUrl url("qrc:/behaviorCam.qml"); + const QUrl url(m_cBehavCam["qmlFile"].toString("qrc:/behaviorCam.qml")); +// const QUrl url("qrc:/behaviorCam.qml"); view = new NewQuickView(url); view->setWidth(m_cBehavCam["width"].toInt() * m_ucBehavCam["windowScale"].toDouble(1)); view->setHeight(m_cBehavCam["height"].toInt() * m_ucBehavCam["windowScale"].toDouble(1)); @@ -129,7 +146,7 @@ void BehaviorCam::createView() vidDisplay->setWindowScaleValue(m_ucBehavCam["windowScale"].toDouble(1)); // Turn on or off saturation display - if (m_ucBehavCam["showSaturation"].toBool(true)) + if (m_ucBehavCam["showSaturation"].toBool(false)) vidDisplay->setShowSaturation(1); else vidDisplay->setShowSaturation(0); @@ -140,8 +157,10 @@ void BehaviorCam::createView() this, SLOT( handlePropChangedSignal(QString, double, double, double) )); // Open OpenCV properties dialog for behav cam - QObject::connect(rootObject, SIGNAL( camPropsClicked() ), this, SLOT( handleCamPropsClicked())); - QObject::connect(this, SIGNAL( openCamPropsDialog()), behavCamStream, SLOT( openCamPropsDialog())); + if (!isMiniCAM) { + QObject::connect(rootObject, SIGNAL( camPropsClicked() ), this, SLOT( handleCamPropsClicked())); + QObject::connect(this, SIGNAL( openCamPropsDialog()), behavCamStream, SLOT( openCamPropsDialog())); + } // Set ROI Stuff QObject::connect(rootObject, SIGNAL( setRoiClicked() ), this, SLOT( handleSetRoiClicked())); @@ -175,8 +194,8 @@ void BehaviorCam::createView() } void BehaviorCam::connectSnS(){ - -// QObject::connect(this, SIGNAL( setPropertyI2C(long, QVector) ), behavCamStream, SLOT( setPropertyI2C(long, QVector) )); + if (isMiniCAM) + QObject::connect(this, SIGNAL( setPropertyI2C(long, QVector) ), behavCamStream, SLOT( setPropertyI2C(long, QVector) )); } @@ -198,45 +217,52 @@ void BehaviorCam::parseUserConfigBehavCam() { } } -QString BehaviorCam::getCompressionType() +void BehaviorCam::sendInitCommands() { - return m_compressionType; -} + // Sends out the commands in the miniscope json config file under Initialize + QVector packet; + long preambleKey; + int tempValue; -//void BehaviorCam::sendInitCommands() -//{ -// // Sends out the commands in the miniscope json config file under Initialize -// QVector packet; -// long preambleKey; -// int tempValue; - -// QVector> sendCommands = parseSendCommand(m_cBehavCam["initialize"].toArray()); -// QMap command; - -// for (int i = 0; i < sendCommands.length(); i++) { -// // Loop through send commands -// command = sendCommands[i]; -// packet.clear(); -// if (command["protocol"] == PROTOCOL_I2C) { -// packet.append(command["addressW"]); -// for (int j = 0; j < command["regLength"]; j++) { -// packet.append(command["reg" + QString::number(j)]); -// } -// for (int j = 0; j < command["dataLength"]; j++) { -// tempValue = command["data" + QString::number(j)]; -// packet.append(tempValue); -// } + QVector> sendCommands = parseSendCommand(m_cBehavCam["initialize"].toArray()); + QMap command; + + for (int i = 0; i < sendCommands.length(); i++) { + // Loop through send commands + command = sendCommands[i]; + packet.clear(); + if (command["protocol"] == PROTOCOL_I2C) { + preambleKey = 0; + + packet.append(command["addressW"]); + preambleKey = (preambleKey<<8) | packet.last(); + + for (int j = 0; j < command["regLength"]; j++) { + packet.append(command["reg" + QString::number(j)]); + preambleKey = (preambleKey<<8) | packet.last(); + } + for (int j = 0; j < command["dataLength"]; j++) { + tempValue = command["data" + QString::number(j)]; + packet.append(tempValue); + preambleKey = (preambleKey<<8) | packet.last(); + } +// qDebug() << packet; // preambleKey = 0; // for (int k = 0; k < (command["regLength"]+1); k++) // preambleKey |= (packet[k]&0xFF)<<(8*k); -// emit setPropertyI2C(preambleKey, packet); -// } -// else { -// qDebug() << command["protocol"] << " initialize protocol not yet supported"; -// } + emit setPropertyI2C(preambleKey, packet); + } + else { + qDebug() << command["protocol"] << " initialize protocol not yet supported"; + } -// } -//} + } +} + +QString BehaviorCam::getCompressionType() +{ + return m_compressionType; +} void BehaviorCam::getBehavCamConfig(QString deviceType) { QString jsonFile; @@ -271,15 +297,19 @@ void BehaviorCam::configureBehavCamControls() { // qDebug() << controlItem; values = controlSettings[controlName[i]].toObject(); - if (m_ucBehavCam.contains(controlName[i])) // sets starting value if it is defined in user config - values["startValue"] = m_ucBehavCam[controlName[i]].toDouble(); + if (m_ucBehavCam.contains(controlName[i])) {// sets starting value if it is defined in user config + if (m_ucBehavCam[controlName[i]].isDouble()) + values["startValue"] = m_ucBehavCam[controlName[i]].toDouble(); + if (m_ucBehavCam[controlName[i]].isString()) + values["startValue"] = m_ucBehavCam[controlName[i]].toString(); + } keys = values.keys(); if (controlItem) { controlItem->setVisible(true); for (int j = 0; j < keys.size(); j++) { // Set min, max, startValue, and stepSize in order found in 'format' if (keys[j] == "sendCommand") { -// m_controlSendCommand[controlName[i]] = parseSendCommand(values["sendCommand"].toArray()); + m_controlSendCommand[controlName[i]] = parseSendCommand(values["sendCommand"].toArray()); } else { if (values[keys[j]].isArray()) { @@ -295,6 +325,9 @@ void BehaviorCam::configureBehavCamControls() { } else if (values[keys[j]].isString()) { controlItem->setProperty(keys[j].toLatin1().data(), values[keys[j]].toString()); + if (keys[j] == "startValue") + // sends signal on initial setup of controls + emit onPropertyChanged(m_deviceName, controlName[i], values["startValue"].toVariant()); } else { controlItem->setProperty(keys[j].toLatin1().data(), values[keys[j]].toDouble()); @@ -312,75 +345,83 @@ void BehaviorCam::configureBehavCamControls() { } } -//QVector> BehaviorCam::parseSendCommand(QJsonArray sendCommand) -//{ -// // Creates a QMap for handing future I2C/SPI slider value send commands -// QVector> output; -// QMap commandStructure; -// QJsonObject jObj; -// QStringList keys; - -// for (int i = 0; i < sendCommand.size(); i++) { -// jObj = sendCommand[i].toObject(); -// keys = jObj.keys(); - -// for (int j = 0; j < keys.size(); j++) { -// // -1 = controlValue, -2 = error -// if (jObj[keys[j]].isString()) -// commandStructure[keys[j]] = processString2Int(jObj[keys[j]].toString()); -// else if (jObj[keys[j]].isDouble()) -// commandStructure[keys[j]] = jObj[keys[j]].toInt(); -// } -// output.append(commandStructure); -// } -// return output; -//} - -//int BehaviorCam::processString2Int(QString s) -//{ -// // Should return a uint8 type of value (0 to 255) -// bool ok = false; -// int value; -// int size = s.size(); -// if (size == 0) { -// qDebug() << "No data in string to convert to int"; -// value = SEND_COMMAND_ERROR; -// ok = false; -// } -// else if (s.left(2) == "0x"){ -// // HEX -// value = s.right(size-2).toUInt(&ok, 16); -// } -// else if (s.left(2) == "0b"){ -// // Binary -// value = s.right(size-2).toUInt(&ok, 2); -// } -// else { -// value = s.toUInt(&ok, 10); -//// qDebug() << "String is " << s; -// if (ok == false) { -// // This is then a string -// if (s == "I2C") -// value = PROTOCOL_I2C; -// else if (s == "SPI") -// value = PROTOCOL_SPI; -// else if (s == "valueH") -// value = SEND_COMMAND_VALUE_H; -// else if (s == "valueL") -// value = SEND_COMMAND_VALUE_L; -// else if (s == "value") -// value = SEND_COMMAND_VALUE; -// else -// value = SEND_COMMAND_ERROR; -// ok = true; -// } -// } - -// if (ok == true) -// return value; -// else -// return SEND_COMMAND_ERROR; -//} +QVector> BehaviorCam::parseSendCommand(QJsonArray sendCommand) +{ + // Creates a QMap for handing future I2C/SPI slider value send commands + QVector> output; + QMap commandStructure; + QJsonObject jObj; + QStringList keys; + + for (int i = 0; i < sendCommand.size(); i++) { + jObj = sendCommand[i].toObject(); + keys = jObj.keys(); + + for (int j = 0; j < keys.size(); j++) { + // -1 = controlValue, -2 = error + if (jObj[keys[j]].isString()) + commandStructure[keys[j]] = processString2Int(jObj[keys[j]].toString()); + else if (jObj[keys[j]].isDouble()) + commandStructure[keys[j]] = jObj[keys[j]].toInt(); + } + output.append(commandStructure); + } + return output; +} + +int BehaviorCam::processString2Int(QString s) +{ + // Should return a uint8 type of value (0 to 255) + bool ok = false; + int value; + int size = s.size(); + if (size == 0) { + qDebug() << "No data in string to convert to int"; + value = SEND_COMMAND_ERROR; + ok = false; + } + else if (s.left(2) == "0x"){ + // HEX + value = s.right(size-2).toUInt(&ok, 16); + } + else if (s.left(2) == "0b"){ + // Binary + value = s.right(size-2).toUInt(&ok, 2); + } + else { + value = s.toUInt(&ok, 10); +// qDebug() << "String is " << s; + if (ok == false) { + // This is then a string + if (s == "I2C") + value = PROTOCOL_I2C; + else if (s == "SPI") + value = PROTOCOL_SPI; + else if (s == "valueH24") + value = SEND_COMMAND_VALUE_H24; + else if (s == "valueH16") + value = SEND_COMMAND_VALUE_H16; + else if (s == "valueH") + value = SEND_COMMAND_VALUE_H; + else if (s == "valueL") + value = SEND_COMMAND_VALUE_L; + else if (s == "value") + value = SEND_COMMAND_VALUE; + else if (s == "value2H") + value = SEND_COMMAND_VALUE2_H; + else if (s == "value2L") + value = SEND_COMMAND_VALUE2_L; + else + value = SEND_COMMAND_ERROR; + ok = true; + } + } + + if (ok == true) + return value; + else + return SEND_COMMAND_ERROR; +} void BehaviorCam::testSlot(QString type, double value) { @@ -403,11 +444,17 @@ void BehaviorCam::sendNewFrame(){ } else tempFrame2 = QImage(frameBuffer[f].data, frameBuffer[f].cols, frameBuffer[f].rows, frameBuffer[f].step, QImage::Format_RGB888); + vidDisplay->setDisplayFrame(tempFrame2.copy()); vidDisplay->setBufferUsed(usedFrames->available()); if (f > 0) // This is just a quick cheat so I don't have to wrap around for (f-1) vidDisplay->setAcqFPS(timeStampBuffer[f] - timeStampBuffer[f-1]); // TODO: consider changing name as this is now interframeinterval + + if (isMiniCAM) + vidDisplay->setDroppedFrameCount(*m_daqFrameNum - *m_acqFrameNum); + else + vidDisplay->setDroppedFrameCount(-1); } } @@ -433,46 +480,60 @@ void BehaviorCam::handlePropChangedSignal(QString type, double displayValue, dou // TODO: maybe add a check to make sure property successfully updates before signallng it has changed // qDebug() << "Sending updated prop signal to backend"; - emit onPropertyChanged(m_deviceName, type, QVariant(displayValue)); + + emit onPropertyChanged(m_deviceName, type, QVariant(displayValue)); // This sends the change to the datasaver + // TODO: Handle int values greater than 8 bits -// for (int i = 0; i < m_controlSendCommand[type].length(); i++) { -// sendCommand = m_controlSendCommand[type][i]; -// packet.clear(); -// if (sendCommand["protocol"] == PROTOCOL_I2C) { -// preambleKey = 0; - -// packet.append(sendCommand["addressW"]); -// preambleKey = (preambleKey<<8) | packet.last(); - -// for (int j = 0; j < sendCommand["regLength"]; j++) { -// packet.append(sendCommand["reg" + QString::number(j)]); -// preambleKey = (preambleKey<<8) | packet.last(); -// } -// for (int j = 0; j < sendCommand["dataLength"]; j++) { -// tempValue = sendCommand["data" + QString::number(j)]; -// // TODO: Handle value1 through value3 -// if (tempValue == SEND_COMMAND_VALUE_H) { -// packet.append(((quint16)round(i2cValue))>>8); -// } -// else if (tempValue == SEND_COMMAND_VALUE_L) { -// packet.append((quint8)round(i2cValue)); -// } -// else { -// packet.append(tempValue); -// preambleKey = (preambleKey<<8) | packet.last(); -// } -// } -// // qDebug() << packet; - -//// for (int k = 0; k < (sendCommand["regLength"]+1); k++) -//// preambleKey |= (packet[k]&0xFF)<<(8*k); -// emit setPropertyI2C(preambleKey, packet); -// } -// else { -// qDebug() << sendCommand["protocol"] << " protocol for " << type << " not yet supported"; -// } -// } + for (int i = 0; i < m_controlSendCommand[type].length(); i++) { + sendCommand = m_controlSendCommand[type][i]; + packet.clear(); + if (sendCommand["protocol"] == PROTOCOL_I2C) { + preambleKey = 0; + + packet.append(sendCommand["addressW"]); + preambleKey = (preambleKey<<8) | packet.last(); + + for (int j = 0; j < sendCommand["regLength"]; j++) { + packet.append(sendCommand["reg" + QString::number(j)]); + preambleKey = (preambleKey<<8) | packet.last(); + } + for (int j = 0; j < sendCommand["dataLength"]; j++) { + tempValue = sendCommand["data" + QString::number(j)]; + // TODO: Handle value1 through value3 + if (tempValue == SEND_COMMAND_VALUE_H24) { + packet.append((static_cast(round(i2cValue))>>24)&0xFF); + } + else if (tempValue == SEND_COMMAND_VALUE_H16) { + packet.append((static_cast(round(i2cValue))>>16)&0xFF); + } + else if (tempValue == SEND_COMMAND_VALUE_H) { + packet.append((static_cast(round(i2cValue))>>8)&0xFF); + } + else if (tempValue == SEND_COMMAND_VALUE_L) { + packet.append(static_cast(round(i2cValue))&0xFF); + } + else if (tempValue == SEND_COMMAND_VALUE2_H) { + packet.append((static_cast(round(i2cValue2))>>8)&0xFF); + } + else if (tempValue == SEND_COMMAND_VALUE2_L) { + packet.append(static_cast(round(i2cValue2))&0xFF); + } + else { + packet.append(tempValue); + preambleKey = (preambleKey<<8) | packet.last(); + } + } + // qDebug() << packet; + +// for (int k = 0; k < (sendCommand["regLength"]+1); k++) +// preambleKey |= (packet[k]&0xFF)<<(8*k); + emit setPropertyI2C(preambleKey, packet); + } + else { + qDebug() << sendCommand["protocol"] << " protocol for " << type << " not yet supported"; + } + } } } @@ -550,3 +611,9 @@ void BehaviorCam::handleNewROI(int leftEdge, int topEdge, int width, int height) // TODO: enable ROI button } + +void BehaviorCam::handleInitCommandsRequest() +{ + qDebug() << "Reinitializing device."; + sendInitCommands(); +} diff --git a/source/behaviorcam.h b/source/behaviorcam.h index 4ea9c53..3a35cea 100644 --- a/source/behaviorcam.h +++ b/source/behaviorcam.h @@ -18,6 +18,17 @@ #include "newquickview.h" #include +#define PROTOCOL_I2C -2 +#define PROTOCOL_SPI -3 +#define SEND_COMMAND_VALUE_H -5 +#define SEND_COMMAND_VALUE_L -6 +#define SEND_COMMAND_VALUE -6 +#define SEND_COMMAND_VALUE_H16 -7 +#define SEND_COMMAND_VALUE_H24 -8 +#define SEND_COMMAND_VALUE2_H -9 +#define SEND_COMMAND_VALUE2_L -10 +#define SEND_COMMAND_ERROR -20 + #define FRAME_BUFFER_SIZE 128 class BehaviorCam : public QObject @@ -28,6 +39,7 @@ class BehaviorCam : public QObject void createView(); void connectSnS(); void parseUserConfigBehavCam(); + void sendInitCommands(); QString getCompressionType(); // void sendInitCommands(); cv::Mat* getFrameBufferPointer(){return frameBuffer;} @@ -44,7 +56,7 @@ class BehaviorCam : public QObject signals: // TODO: setup signals to configure camera in thread -// void setPropertyI2C(long preambleKey, QVector packet); + void setPropertyI2C(long preambleKey, QVector packet); void onPropertyChanged(QString devieName, QString propName, QVariant propValue); void sendMessage(QString msg); void takeScreenShot(QString type); @@ -57,6 +69,7 @@ public slots: void handlePropChangedSignal(QString type, double displayValue, double i2cValue, double i2cValue2); void handleTakeScreenShotSignal(); void close(); + void handleInitCommandsRequest(); void handleCamPropsClicked() { emit openCamPropsDialog();} void handleSetRoiClicked(); @@ -72,7 +85,7 @@ public slots: private: void getBehavCamConfig(QString deviceType); void configureBehavCamControls(); -// QVector> parseSendCommand(QJsonArray sendCommand); + QVector> parseSendCommand(QJsonArray sendCommand); int processString2Int(QString s); int m_camConnected; @@ -89,7 +102,7 @@ public slots: QTimer *timer; int m_previousDisplayFrameNum; QAtomicInt *m_acqFrameNum; -// QAtomicInt *m_daqFrameNum; + QAtomicInt *m_daqFrameNum; // QAtomicInt *m_DAQTimeStamp; @@ -101,7 +114,7 @@ public slots: QJsonObject m_cBehavCam; // Consider renaming to not confuse with ucMiniscopes -// QMap>> m_controlSendCommand; + QMap>> m_controlSendCommand; // QMap m_sendCommand; bool m_streamHeadOrientationState; @@ -114,6 +127,9 @@ public slots: // ROI bool m_roiIsDefined; int m_roiBoundingBox[4]; // left, top, width, height + + // Handle MiniCAM stuff + bool isMiniCAM; }; #endif // BEHAVIORCAM_H diff --git a/source/main.cpp b/source/main.cpp index 245b80c..1aa5289 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -9,7 +9,7 @@ #include "backend.h" -#define VERSION_NUMBER "0.171" +#define VERSION_NUMBER "0.200" // TODO: have exit button close everything // For Window's deployment diff --git a/source/miniscope.cpp b/source/miniscope.cpp index 09953e4..1644f4e 100644 --- a/source/miniscope.cpp +++ b/source/miniscope.cpp @@ -34,7 +34,6 @@ Miniscope::Miniscope(QObject *parent, QJsonObject ucMiniscope) : { m_ucMiniscope = ucMiniscope; // hold user config for this Miniscope -// qDebug() << m_ucMiniscope["deviceType"].toString(); parseUserConfigMiniscope(); getMiniscopeConfig(m_ucMiniscope["deviceType"].toString()); // holds specific Miniscope configuration @@ -62,7 +61,7 @@ Miniscope::Miniscope(QObject *parent, QJsonObject ucMiniscope) : // ------------------------- // Setup OpenCV camera stream - miniscopeStream = new VideoStreamOCV(nullptr, m_cMiniscopes["width"].toInt(-1), m_cMiniscopes["height"].toInt(-1)); + miniscopeStream = new VideoStreamOCV(nullptr, m_cMiniscopes["width"].toInt(-1), m_cMiniscopes["height"].toInt(-1), m_cMiniscopes["pixelClock"].toDouble(-1)); miniscopeStream->setDeviceName(m_deviceName); miniscopeStream->setHeadOrientationConfig(m_headOrientationStreamState, m_headOrientationFilterState); @@ -99,6 +98,9 @@ Miniscope::Miniscope(QObject *parent, QJsonObject ucMiniscope) : // Pass send message signal through QObject::connect(miniscopeStream, &VideoStreamOCV::sendMessage, this, &Miniscope::sendMessage); + // Handle request for reinitialization of commands + QObject::connect(miniscopeStream, &VideoStreamOCV::requestInitCommands, this, &Miniscope::handleInitCommandsRequest); + // Handle external triggering passthrough QObject::connect(this, &Miniscope::setExtTriggerTrackingState, miniscopeStream, &VideoStreamOCV::setExtTriggerTrackingState); QObject::connect(miniscopeStream, &VideoStreamOCV::extTriggered, this, &Miniscope::extTriggered); @@ -166,9 +168,10 @@ void Miniscope::createView() configureMiniscopeControls(); vidDisplay = rootObject->findChild("vD"); vidDisplay->setMaxBuffer(FRAME_BUFFER_SIZE); + vidDisplay->setWindowScaleValue(m_ucMiniscope["windowScale"].toDouble(1)); // Turn on or off show saturation display - if (m_ucMiniscope["showSaturation"].toBool(true)) + if (m_ucMiniscope["showSaturation"].toBool(false)) vidDisplay->setShowSaturation(1); else vidDisplay->setShowSaturation(0); @@ -332,12 +335,14 @@ void Miniscope::configureMiniscopeControls() { } else { // remaining option is value is a double controlItem->setProperty(keys[j].toLatin1().data(), values[keys[j]].toDouble()); - if (keys[j] == "startValue") + if (keys[j] == "startValue") { if (controlName[i] == "led0") { // This is used to hold initial (and last known) LED value for toggling LED on and off using remote trigger m_lastLED0Value = values["startValue"].toDouble(); } // sends signal on initial setup of controls emit onPropertyChanged(m_deviceName, controlName[i], values["startValue"].toVariant()); + + } } } } @@ -472,6 +477,8 @@ void Miniscope::sendNewFrame(){ if (m_displatState == "Raw") { +// vidDisplay->setDisplayFrame(tempFrame2.copy()); + // TODO: Check to see if we can get rid of .copy() here vidDisplay->setDisplayFrame(tempFrame2.copy()); } else if (m_displatState == "dFF") { @@ -660,6 +667,12 @@ void Miniscope::handleRecordStop() } } +void Miniscope::handleInitCommandsRequest() +{ + qDebug() << "Reinitializing device."; + sendInitCommands(); +} + void Miniscope::close() { diff --git a/source/miniscope.h b/source/miniscope.h index 940e838..164db3a 100644 --- a/source/miniscope.h +++ b/source/miniscope.h @@ -77,6 +77,7 @@ public slots: void handleSetExtTriggerTrackingState(bool state); void handleRecordStart(); // Currently used to toggle LED on and off void handleRecordStop(); // Currently used to toggle LED on and off + void handleInitCommandsRequest(); void close(); private: diff --git a/source/videodisplay.cpp b/source/videodisplay.cpp index 3e1605f..3eb876e 100644 --- a/source/videodisplay.cpp +++ b/source/videodisplay.cpp @@ -35,9 +35,15 @@ void VideoDisplay::setT(qreal t) window()->update(); } void VideoDisplay::setDisplayFrame(QImage frame) { - m_displayFrame2 = frame; - if (m_renderer) - m_renderer->setDisplayFrame(m_displayFrame2.copy()); +// m_displayFrame2 = frame; + // Checking to see if there is already a new frame waiting has solved a + // consistent source of crash. + // This crash was due to the texture data of the next frame in the queue to be displayed + // changing before it is moved to GPU memory I think. + if (m_renderer && !m_renderer->m_newFrame) + m_renderer->setDisplayFrame(frame); +// else +// qDebug() << "New frame available before last frame was displayed"; } void VideoDisplay::setShowSaturation(double value) @@ -228,10 +234,11 @@ void VideoDisplayRenderer::paint() if (m_newFrame) { // qDebug() << "Set new texture QImage"; - m_newFrame = false; + m_texture->destroy(); m_texture->create(); - m_texture->setData(m_displayFrame.copy()); + m_texture->setData(m_displayFrame); + m_newFrame = false; } } diff --git a/source/videodisplay.h b/source/videodisplay.h index 32ce179..d025da7 100644 --- a/source/videodisplay.h +++ b/source/videodisplay.h @@ -28,13 +28,16 @@ class VideoDisplayRenderer : public QObject, protected QOpenGLFunctions ~VideoDisplayRenderer(); void setT(qreal t) { m_t = t; } - void setDisplayFrame(QImage frame) { m_displayFrame = frame; m_newFrame = true;} + void setDisplayFrame(QImage frame) {m_displayFrame = frame.copy(); m_newFrame = true;} void setViewportSize(const QSize &size) { m_viewportSize = size; } void setWindow(QQuickWindow *window) { m_window = window; } void setAlpha(double a) {m_alpha = a;} void setBeta(double b) {m_beta = b;} void setShowSaturation(double value) {m_showStaturation = value; } + + bool m_newFrame; + signals: void requestNewFrame(); @@ -48,7 +51,7 @@ public slots: QOpenGLShaderProgram *m_program; QOpenGLTexture *m_texture; QQuickWindow *m_window; - bool m_newFrame; + double m_alpha; double m_beta; @@ -67,7 +70,7 @@ class VideoDisplay : public QQuickItem Q_PROPERTY(int bufferUsed READ bufferUsed WRITE setBufferUsed NOTIFY bufferUsedChanged) Q_PROPERTY(int maxBuffer READ maxBuffer WRITE setMaxBuffer NOTIFY maxBufferChanged) Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) - Q_PROPERTY(QImage displayFrame READ displayFrame WRITE setDisplayFrame NOTIFY displayFrameChanged) +// Q_PROPERTY(QImage displayFrame READ displayFrame WRITE setDisplayFrame NOTIFY displayFrameChanged) // For visualizing ROI Q_PROPERTY(QList ROI READ ROI WRITE setROI NOTIFY roiChanged) @@ -85,8 +88,7 @@ class VideoDisplay : public QQuickItem int bufferUsed() const { return m_bufferUsed; } int droppedFrameCount() const {return m_droppedFrameCount; } - QImage displayFrame() { return m_displayFrame2; } -// QImage displayFrame() {return m_displayFrame;} +// QImage displayFrame() { return m_displayFrame2; } void setT(qreal t); void setAcqFPS(double acqFPS) { m_acqFPS = acqFPS; acqFPSChanged();} void setROI(QList roi); @@ -125,7 +127,7 @@ private slots: int m_bufferUsed; int m_maxBuffer; int m_droppedFrameCount; - QImage m_displayFrame2; +// QImage m_displayFrame2; VideoDisplayRenderer *m_renderer; double m_showSaturation; diff --git a/source/videostreamocv.cpp b/source/videostreamocv.cpp index 0aa8d85..28f1f64 100644 --- a/source/videostreamocv.cpp +++ b/source/videostreamocv.cpp @@ -13,7 +13,7 @@ #include #include -VideoStreamOCV::VideoStreamOCV(QObject *parent, int width, int height) : +VideoStreamOCV::VideoStreamOCV(QObject *parent, int width, int height, double pixelClock) : QObject(parent), m_deviceName(""), m_stopStreaming(false), @@ -23,6 +23,7 @@ VideoStreamOCV::VideoStreamOCV(QObject *parent, int width, int height) : m_trackExtTrigger(false), m_expectedWidth(width), m_expectedHeight(height), + m_pixelClock(pixelClock), m_connectionType("") { @@ -62,9 +63,55 @@ int VideoStreamOCV::connect2Camera(int cameraID) { m_connectionType = "OTHER"; } } + // We need to make sure the MODE of the SERDES is correct + // This needs to be done before any other commands are sent over SERDES + // Currently this is for the 913/914 TI SERES + // TODO: Probably should move this somewhere else + QVector packet; + if (m_pixelClock > 0 && connectionState != 0) { + if (m_pixelClock <= 50) { + // Set to 12bit low frequency in this case + + // DES + packet.append(0xC0); // I2C Address + packet.append(0x1F); // reg + packet.append(0b00010000); // data + setPropertyI2C(0,packet); + + // SER + packet.clear(); + packet.append(0xB0); // I2C Address + packet.append(0x05); // reg + packet.append(0b00100000); // data + setPropertyI2C(1,packet); + } + else { + // Set to 10bit high frequency in this case + + // DES + packet.clear(); + packet.append(0xC0); // I2C Address + packet.append(0x1F); // reg + packet.append(0b00010001); // data + setPropertyI2C(0,packet); + + // SER + packet.clear(); + packet.append(0xB0); // I2C Address + packet.append(0x05); // reg + packet.append(0b00100001); // data + setPropertyI2C(1,packet); + + } + sendCommands(); + QThread::msleep(500); + + } + if (connectionState != 0) { cam->set(cv::CAP_PROP_FRAME_WIDTH, m_expectedWidth); cam->set(cv::CAP_PROP_FRAME_HEIGHT, m_expectedHeight); + QThread::msleep(500); } // qDebug() << "Camera capture backend is" << QString::fromStdString (cam->getBackendName()); return connectionState; @@ -344,6 +391,8 @@ void VideoStreamOCV::sendCommands() } else { //TODO: Handle packets longer than 6 bytes + sendCommandQueue.remove(key); + sendCommandQueueOrder.removeFirst(); } } @@ -352,13 +401,99 @@ void VideoStreamOCV::sendCommands() bool VideoStreamOCV::attemptReconnect() { + // TODO: handle quitting nicely when stuck in this loop + QVector packet; if (m_connectionType == "DSHOW") { - if (cam->open(m_cameraID, cv::CAP_DSHOW)) + if (cam->open(m_cameraID, cv::CAP_DSHOW)) { + + if (m_pixelClock <= 50) { + // Set to 12bit low frequency in this case + + // DES + packet.append(0xC0); // I2C Address + packet.append(0x1F); // reg + packet.append(0b00010000); // data + setPropertyI2C(0,packet); + + // SER + packet.clear(); + packet.append(0xB0); // I2C Address + packet.append(0x05); // reg + packet.append(0b00100000); // data + setPropertyI2C(1,packet); + } + else { + // Set to 10bit high frequency in this case + + // DES +// packet.clear(); + packet.append(0xC0); // I2C Address + packet.append(0x1F); // reg + packet.append(0b00010001); // data + setPropertyI2C(0,packet); + + // SER + packet.clear(); + packet.append(0xB0); // I2C Address + packet.append(0x05); // reg + packet.append(0b00100001); // data + setPropertyI2C(1,packet); + + } + sendCommands(); + QThread::msleep(500); + + cam->set(cv::CAP_PROP_FRAME_WIDTH, m_expectedWidth); + cam->set(cv::CAP_PROP_FRAME_HEIGHT, m_expectedHeight); + QThread::msleep(500); + requestInitCommands(); return true; + } } else if (m_connectionType == "OTHER") { - if (cam->open(m_cameraID)) + if (cam->open(m_cameraID)) { + if (m_pixelClock <= 50) { + // Set to 12bit low frequency in this case + + // DES + packet.append(0xC0); // I2C Address + packet.append(0x1F); // reg + packet.append(0b00010000); // data + setPropertyI2C(0,packet); + + // SER + packet.clear(); + packet.append(0xB0); // I2C Address + packet.append(0x05); // reg + packet.append(0b00100000); // data + setPropertyI2C(1,packet); + } + else { + // Set to 10bit high frequency in this case + + // DES +// packet.clear(); + packet.append(0xC0); // I2C Address + packet.append(0x1F); // reg + packet.append(0b00010001); // data + setPropertyI2C(0,packet); + + // SER + packet.clear(); + packet.append(0xB0); // I2C Address + packet.append(0x05); // reg + packet.append(0b00100001); // data + setPropertyI2C(1,packet); + + } + sendCommands(); + QThread::msleep(500); + cam->set(cv::CAP_PROP_FRAME_WIDTH, m_expectedWidth); + cam->set(cv::CAP_PROP_FRAME_HEIGHT, m_expectedHeight); + QThread::msleep(500); + requestInitCommands(); return true; + } } return false; } diff --git a/source/videostreamocv.h b/source/videostreamocv.h index dc97a36..36cc574 100644 --- a/source/videostreamocv.h +++ b/source/videostreamocv.h @@ -18,7 +18,7 @@ class VideoStreamOCV : public QObject { Q_OBJECT public: - explicit VideoStreamOCV(QObject *parent = nullptr, int width = 0, int height = 0); + explicit VideoStreamOCV(QObject *parent = nullptr, int width = 0, int height = 0, double pixelClock = 0); ~VideoStreamOCV(); // void setCameraID(int cameraID); void setBufferParameters(cv::Mat *frameBuf, qint64 *tsBuf, float *bnoBuf, @@ -33,6 +33,7 @@ class VideoStreamOCV : public QObject void sendMessage(QString msg); void newFrameAvailable(QString name, int frameNum); void extTriggered(bool triggerState); + void requestInitCommands(); public slots: void startStream(); @@ -71,6 +72,7 @@ public slots: int m_expectedWidth; int m_expectedHeight; + double m_pixelClock; QString m_connectionType; diff --git a/userConfigs/UserConfigExample_Dual_MiniCAM.json b/userConfigs/UserConfigExample_Dual_MiniCAM.json new file mode 100644 index 0000000..94dc4cd --- /dev/null +++ b/userConfigs/UserConfigExample_Dual_MiniCAM.json @@ -0,0 +1,69 @@ +{ + "researcherName": "Dr_Miniscope", + "dataDirectory": "C:/Users/DBAharoni/Documents/Data", + "directoryStructure": [ + "researcherName", + "experimentName", + "animalName", + "date", + "time" + ], + "animalName": "testMouse", + "experimentName": "Linear Track Test", + "recordLengthinSeconds": 600, + "experiment_Not_Implemented": { + "type": "linearTrack", + "units": "cm", + "trackLength": 200 + }, + "behaviorTracker_Not_Implemented": { + "type": "HSV", + "hue": [0, 1], + "saturation": [0, 1], + "value": [0, 1] + }, + "devices": { + "cameras": [ + { + "deviceName": "MiniCAM0", + "deviceType": "Minicam-Mono-XGA", + "deviceID": 1, + "showSaturation": true, + "ROI": { + "notes": "This defines the bounding box of the portion of the video that is saved to disk", + "leftEdge": 10, + "topEdge": 20, + "width": 300, + "height": 200 + }, + "cameraCalibrationFileLocation": "", + "compressionOptions": ["MJPG","MJ2C","XVID","FFV1"], + "compression": "MJPG", + "framesPerFile": 1000, + "windowScale": 0.75, + "windowX": 800, + "windowY": 600 + }, + { + "deviceName": "MiniCAM1", + "deviceType": "Minicam-Mono-XGA", + "deviceID": 2, + "showSaturation": true, + "ROI": { + "notes": "This defines the bounding box of the portion of the video that is saved to disk", + "leftEdge": 10, + "topEdge": 20, + "width": 300, + "height": 200 + }, + "cameraCalibrationFileLocation": "", + "compressionOptions": ["MJPG","MJ2C","XVID","FFV1"], + "compression": "MJPG", + "framesPerFile": 1000, + "windowScale": 0.75, + "windowX": 800, + "windowY": 600 + } + ] + } +} diff --git a/userConfigs/UserConfigExample_Dual_MiniCAM_PLUS_V4.json b/userConfigs/UserConfigExample_Dual_MiniCAM_PLUS_V4.json new file mode 100644 index 0000000..1eee2bf --- /dev/null +++ b/userConfigs/UserConfigExample_Dual_MiniCAM_PLUS_V4.json @@ -0,0 +1,93 @@ +{ + "researcherName": "Dr_Miniscope", + "dataDirectory": "C:/Users/dbaha/Documents/Data", + "directoryStructure": [ + "researcherName", + "experimentName", + "animalName", + "date", + "time" + ], + "animalName": "testMouse", + "experimentName": "Linear Track Test", + "recordLengthinSeconds": 600, + "experiment_Not_Implemented": { + "type": "linearTrack", + "units": "cm", + "trackLength": 200 + }, + "behaviorTracker_Not_Implemented": { + "type": "HSV", + "hue": [0, 1], + "saturation": [0, 1], + "value": [0, 1] + }, + "devices": { + "cameras": [ + { + "deviceName": "MiniCAM0", + "deviceType": "Minicam-Mono-XGA", + "deviceID": 1, + "showSaturation": true, + "ROI": { + "notes": "This defines the bounding box of the portion of the video that is saved to disk", + "leftEdge": 10, + "topEdge": 20, + "width": 300, + "height": 200 + }, + "cameraCalibrationFileLocation": "", + "compressionOptions": ["MJPG","MJ2C","XVID","FFV1"], + "compression": "MJPG", + "framesPerFile": 1000, + "windowScale": 0.5, + "windowX": 800, + "windowY": 600 + }, + { + "deviceName": "MiniCAM1", + "deviceType": "Minicam-Mono-XGA", + "deviceID": 2, + "showSaturation": true, + "ROI": { + "notes": "This defines the bounding box of the portion of the video that is saved to disk", + "leftEdge": 10, + "topEdge": 20, + "width": 300, + "height": 200 + }, + "cameraCalibrationFileLocation": "", + "compressionOptions": ["MJPG","MJ2C","XVID","FFV1"], + "compression": "MJPG", + "framesPerFile": 1000, + "windowScale": 0.5, + "windowX": 800, + "windowY": 600 + } + ], + "miniscopes": [ + { + "deviceName": "Miniscope", + "deviceType": "Miniscope_V4_BNO", + "imageRegistration": "Off", + "headOrientation": { + "enable": true, + "filterBadData": true + }, + "streamHeadOrientation_OLD": true, + "deviceID": 3, + "showSaturation": true, + "compressionOptions": ["MJPG","MJ2C","XVID","FFV1"], + "compression": "FFV1", + "framesPerFile": 1000, + "windowScale": 0.75, + "windowX": 800, + "windowY": 100, + "gain": "Low", + "ewl": 50, + "led0": 10, + "frameRate": "30FPS" + } + ] + } +} diff --git a/userConfigs/UserConfigExample_MiniCAM.json b/userConfigs/UserConfigExample_MiniCAM.json new file mode 100644 index 0000000..3b6bb1e --- /dev/null +++ b/userConfigs/UserConfigExample_MiniCAM.json @@ -0,0 +1,49 @@ +{ + "researcherName": "Dr_Miniscope", + "dataDirectory": "C:/Users/DBAharoni/Documents/Data", + "directoryStructure": [ + "researcherName", + "experimentName", + "animalName", + "date", + "time" + ], + "animalName": "testMouse", + "experimentName": "Linear Track Test", + "recordLengthinSeconds": 600, + "experiment_Not_Implemented": { + "type": "linearTrack", + "units": "cm", + "trackLength": 200 + }, + "behaviorTracker_Not_Implemented": { + "type": "HSV", + "hue": [0, 1], + "saturation": [0, 1], + "value": [0, 1] + }, + "devices": { + "cameras": [ + { + "deviceName": "MiniCAM0", + "deviceType": "Minicam-Mono-XGA", + "deviceID": 2, + "showSaturation": true, + "ROI": { + "notes": "This defines the bounding box of the portion of the video that is saved to disk", + "leftEdge": 10, + "topEdge": 20, + "width": 300, + "height": 200 + }, + "cameraCalibrationFileLocation": "", + "compressionOptions": ["MJPG","MJ2C","XVID","FFV1"], + "compression": "FFV1", + "framesPerFile": 1000, + "windowScale": 0.75, + "windowX": 800, + "windowY": 600 + } + ] + } +} diff --git a/userConfigs/UserConfigExample_BehavCam.json b/userConfigs/UserConfigExample_WebCam.json similarity index 100% rename from userConfigs/UserConfigExample_BehavCam.json rename to userConfigs/UserConfigExample_WebCam.json