Aharoni-Lab / Miniscope-DAQ-Cypress-firmware

DAQ firmware for V3 and V4 Miniscope platforms
15 stars 8 forks source link

change LED brightness #8

Open street-grease-coder opened 3 years ago

street-grease-coder commented 3 years ago

Hi, by default not all attributes seem to be available for modification in the windows driver - can e.g. the led (led0) be modified? It seems clear that this is possible from the software package, but I'm unsure how to interface the (unless I'm mistaken) I2C protocol, over which the LED communicates. I'm using LabView to enumerate and view the modifiable attributes, please let me know if that's an issue.

Do I have to modify/rebuild the firmware to be able to enumerate the attribute of the USB device? Or is there a *.dll file I could call?

Thanks a lot for your amazing work!

daharoni commented 3 years ago

Hi! Almost all commands that get sent from software to the Miniscope are done through a series of UVC commands. Probably the easiest place to start if to look at the VideoStreamOCV::sendCommands() function in videostreamocv.cpp of the Miniscope DAQ QT Software. Basically, we send up to 2 bytes on each of the Contrast, Gamma, and Sharpness UVC channels to the Miniscope DAQ. This data is then converted to I2C commands by the Miniscope DAQ Cypress firmware and set out to the Miniscope.

The actual data that is generated by the Miniscope Software to be sent over the UVC channels is mainly defined in the deviceConfigs/videoDevices.json file in the DAQ Software project.

TL:DR, we sort of hijack the UVC protocol to send generic I2C data of up to 6 bytes per communication. We are in the process of switching all USB communication over to a more general vender class USB protocol (and no longer us UVC) which would allow for more direct access to sending data/commands to and from the DAQ.

street-grease-coder commented 3 years ago

Very interesting, thank you very much for the timely and elaborate response! We will take a very close look at the UVC channel definition in the videoDevices.json and get back to you. Please correct me if I misunderstand: I think what we would want then is to basically send arbitrary I2C commands to a specified address over UVC channels to change the LED brightness. If there is currently no 2 byte UVC command that maps to 'set brightness of LED', then we cannot send the I2C command without recompile of firmware (and PR if that it's helpful at all). Is that more or less right?

street-grease-coder commented 3 years ago

Thanks again for your help. I think we understand it now, but are still failing to implement it likely because we have not figured out how to write the byte values to the UVC properties in Labview. Just to check whether our reading of the code is correct. According to the json file the LED has the address of 0x20 (0b00100000) reg0 0x01 and data0 0x00 (to turn off, we assume). According to the code below, we assume this is translated to 00 00 00 01 03 20 (empty empty data0 reg0 packet.length address). Thus this would be written as 00 00 to Sharpness, 00 01 to Gamma, and 03 20 to Contrast. Is this correct?

 if (packet.length() < 6){
            tempPacket = (quint64)packet[0]; // address
            tempPacket |= (((quint64)packet.length())&0xFF)<<8; // data length
            for (int j = 1; j < packet.length(); j++)
                tempPacket |= ((quint64)packet[j])<<(8*(j+1));
            qDebug() << "1-5: 0x" << QString::number(tempPacket,16);
//            cam->set(cv::CAP_PROP_GAMMA, tempPacket);
            success = camSetProperty(cam, cv::CAP_PROP_CONTRAST, (tempPacket & 0x00000000FFFF));
            success = camSetProperty(cam, cv::CAP_PROP_GAMMA, (tempPacket & 0x0000FFFF0000) >> 16) && success;
            success = camSetProperty(cam, cv::CAP_PROP_SHARPNESS, (tempPacket & 0xFFFF00000000) >> 32) && success;
            if (!success)
                qDebug() << "Send setting failed";
            sendCommandQueue.remove(key);
            sendCommandQueueOrder.removeFirst();