From the very first Elphel camera (Model 303) camera driver maintained data array that was accessible by the applications through IOCTL calls. Total number of elements (32-bit data words) was 64 (limited by address bits designated for that purpose in IOCTL command map, the indexes are defined in the c313a.h(names starting with P_ ). Most (but not all) of the elements are represented in two arrays - imageParamsW and imageParamsR, first (W for "write") having the data passed by the applications through IOCTL (example from the ccam.c - described in Ccam.cgi. The next line passes compression quality received as part of the GET request to the driver:
1852 if ((vp=paramValue(gparams, "iq"))) ioctl(devfd, _CCCMD(CCAM_WPARS , P_QUALITY), strtol (vp,&cp,10));
The second array - imageParamsR (R for "read") holds the current value that driver uses. In most cases driver tries to make this value as close as possible to the one specified by application, if the application passed the invalid value driver will use the corrected one. Next line returns the current image width used by the driver (currently it is always a multiple of 16):
1136 ImageWidth = ioctl(data_fd, _CCCMD( CCAM_RPARS , P_ACTUAL_WIDTH ), 0);
Some elements are read only (like P_SENSOR that returns the type of the sensor used in the camera), others (P_UPDATE) initiate actions when written to.
These arrays and parameter definitions were changing with the new camera models, new sensors features that became available, new additions to the FPGA code. Address space of just 64 locations was too small and we have to eliminate older parameters and combine several in a single 32-bit word.
Read/write/lseek vs. ioctl
When the model 353 started to support PHP it became important to have those camera driver parameters to be accessible from the PHP programs. And with the desire to increase the address space we expanded imageParamsR and imageParamsW arrays to 1024 elements (4096 bytes) each and now they can be read/written as form/to a character device (/dev/sensorpars). Both arrays are combined together into a single 8192 byte file where the first 4096 (1024 of 32-bit words) correspond to the imageParamsR, and the second - to imageParamsW, but writing to the first half (to imageParamsR) effectively writes to the corresponding element of imageParamsW (that is 4096 bytes after), so writing to the byte 4 is the same as writing to the byte 4+4096=4100.
Using senspars.php to access driver parameters
There is a simple PHP script that demonstrates access to the camera driver parameters from the PHP code. If the URL is opened without any parameters:
It just lists the command options:
- cmd=list - show all registers
- cmd=read&addr=ra - read register ra
- cmd=write&addr=ra&data=rd - write rd to register ra
Right now it is the very early state of the code, the numeric values of registers have to be (manually) looked up in c313a.h, the result of the read operations is just HTML code (TODO: XML data), write operations return empty page.
But it already works. Here is an example of changing the JPEG compression quality to 100% (no quantization loss):
1. looking into c313a.h
315 #define P_QUALITY 54 // JPEG IMAGE QUALITY
2. making access to the following URL:
http://<camera_ip>:81/senspars.php?cmd=write&addr=54&data=100 -(opens empty page)
That data will be actually written to location 1024+54, at 54 there still be the current parameter value (in this example - 70%)
http://<camera_ip>:81/senspars.php?cmd=read&addr=54 will show: 54(0x36):70(0x46)
http://<camera_ip>:81/senspars.php?cmd=read&addr=1078 will immediately get the new value: 1078(0x436):100(0x64)
3. JPEG quality value controls compressor, not the sensor (or sensor-related part of the FPGA), it is processed when the compressor is programmed. To apply it you may start (or re-start) the compressor with the command
That will apply the change and if you try again
http://<camera_ip>:81/senspars.php?cmd=read&addr=54 - it will show the new value: 54(0x36):100(0x64)
When you change parameter that applies to the sensor (like, for example, gain of read color component):
299 #define P_GAINR 46 /* R channel gain (mono gain) 8.8 0x100 - 1.0 */ http://<camera_ip>:81/senspars.php?cmd=write&addr=46&data=0x100 -0x100 (256) means gain of 1.0
you will need to write a special register (P_UPDATE) with value "1" - apply the changes without interrupting acquisition or compression of the images (value "3" will restart the sensor and/or compressor). For some parameters (like changing image size) the restarting of the image acquisition/compression is required else it will most likely result in corrupted image
http://<camera_ip>:81/senspars.php?cmd=write&addr=0&data=1 - after that the read command http://<camera_ip>:81/senspars.php?cmd=read&addr=46 - it will show the new value: 46(0x2e):256(0x100)