apps/php-5.2.1/ext/elphel/elphel_php.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : elphel_php.c
00003 *! DESCRIPTION: Implementation of elphel extension module for PHP
00004 *! Copyright (C) 2002-2007 Elphel, Inc.
00005 *! -----------------------------------------------------------------------------**
00006 *!  This program is free software: you can redistribute it and/or modify
00007 *!  it under the terms of the GNU General Public License as published by
00008 *!  the Free Software Foundation, either version 3 of the License, or
00009 *!  (at your option) any later version.
00010 *!
00011 *!  This program is distributed in the hope that it will be useful,
00012 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *!  GNU General Public License for more details.
00015 *!
00016 *!  You should have received a copy of the GNU General Public License
00017 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 *! -----------------------------------------------------------------------------**
00019 *!  $Log: elphel_php.c,v $
00020 *!  Revision 1.21  2008/05/02 15:12:09  elphel
00021 *!  minor comment edit
00022 *!
00023 *!  Revision 1.20  2008/05/01 01:32:04  elphel
00024 *!  support for the frame number - combining hardware frame counter used by i2c (3-bit) and software one
00025 *!
00026 *!  Revision 1.19  2008/04/25 21:31:35  elphel
00027 *!  Added Exif_Photo_ExposureTime to be returned by elphel_get_exif_elphel()
00028 *!
00029 *!  Revision 1.18  2008/04/24 18:16:40  elphel
00030 *!  New function to retrieve circbuf structure (frame pointers and Exif pointers)
00031 *!
00032 *!  Revision 1.17  2008/04/22 22:14:08  elphel
00033 *!  Added functions related to Exif data
00034 *!
00035 *!  Revision 1.16  2008/04/20 06:49:04  elphel
00036 *!  Added histogram related functions
00037 *!
00038 *!  Revision 1.15  2008/04/17 22:36:07  elphel
00039 *!  Bug fix, new function added - elphel_is_compressor_idle()
00040 *!
00041 *!  Revision 1.14  2008/03/20 22:25:09  elphel
00042 *!  elphel_trigger - programming synchronization parameters
00043 *!
00044 *!  Revision 1.13  2008/03/15 23:04:21  elphel
00045 *!  added FPGA registers R/W
00046 *!
00047 *!  Revision 1.12  2008/01/27 06:23:17  elphel
00048 *!  New function - elphel_wait_frame (wait fro the next frame to be compressed)
00049 *!
00050 *!  Revision 1.11  2008/01/12 06:53:23  elphel
00051 *!  7.1.7.2 - added elphel_autoexposure_get() function to elphel php extension
00052 *!
00053 *!  Revision 1.10  2008/01/11 07:47:44  elphel
00054 *!  added elphel_autoexposure_set() function
00055 *!
00056 *!  Revision 1.9  2008/01/10 02:43:37  elphel
00057 *!  Added balance of 2 greens in Bayer mosaic
00058 *!
00059 *!  Revision 1.8  2008/01/09 10:22:02  elphel
00060 *!  Implemented elphel_white_balance() function
00061 *!
00062 *!  Revision 1.7  2007/12/14 22:38:53  elphel
00063 *!  cleaned up after fixing cache bug
00064 *!
00065 *!  Revision 1.6  2007/12/06 19:05:33  elphel
00066 *!  2 new functions - arbitrary compressor command (elphel_compressor_cmd) and elphel_compressor_reset
00067 *!
00068 *!  Revision 1.5  2007/12/05 23:41:04  elphel
00069 *!  Fixing minor in bugs in the sensor reset code
00070 *!
00071 *!  Revision 1.4  2007/12/05 22:01:19  elphel
00072 *!  added handling etrax fs mmap cach problem when communicating between PHP extension and the driver
00073 *!
00074 *!  Revision 1.3  2007/12/04 06:41:11  elphel
00075 *!  Implementation of 2 additional functions:    elphel_get_P_arr, elphel_set_P_arr
00076 *!
00077 */
00078 
00079 #ifdef HAVE_CONFIG_H
00080 #include "config.h"
00081 #endif
00082 
00083 #include <sys/mman.h>           /* mmap */
00084 #include <sys/ioctl.h>
00085 #include <fcntl.h>     /* (O_RDWR) */
00086 #include <asm/byteorder.h>
00087 #include <errno.h>
00088 
00089 #include "php.h"
00090 #include "php_ini.h"  /* for php.ini processing */
00091 #include "elphel_php.h"
00093 
00094 
00095 ZEND_DECLARE_MODULE_GLOBALS(elphel)
00096 static function_entry elphel_functions[] = {
00097     PHP_FE(elph_hello, NULL)
00098     PHP_FE(elphel_get_P_value, NULL)
00099     PHP_FE(elphel_set_P_value, NULL)
00100     PHP_FE(elphel_get_P_arr, NULL)
00101     PHP_FE(elphel_get_P_warr, NULL)
00102     PHP_FE(elphel_set_P_arr, NULL)
00103     PHP_FE(elphel_get_state, NULL)
00104     PHP_FE(elphel_program_sensor, NULL)
00105     PHP_FE(elphel_compressor_cmd, NULL)
00106     PHP_FE(elphel_compressor_reset, NULL)
00107     PHP_FE(elphel_compressor_run, NULL)
00108     PHP_FE(elphel_compressor_stop, NULL)
00109     PHP_FE(elphel_compressor_frame, NULL)
00110     PHP_FE(elphel_is_compressor_idle, NULL)
00111     PHP_FE(elphel_reset_sensor, NULL)
00112     PHP_FE(elphel_set_fpga_time, NULL)
00113     PHP_FE(elphel_get_fpga_time, NULL)
00114     PHP_FE(elphel_white_balance, NULL)
00115     PHP_FE(elphel_autoexposure_set, NULL)
00116     PHP_FE(elphel_autoexposure_get, NULL)
00117     PHP_FE(elphel_wait_frame, NULL)
00118     PHP_FE(elphel_fpga_read, NULL)
00119     PHP_FE(elphel_fpga_write, NULL)
00120     PHP_FE(elphel_trigger, NULL)
00121     PHP_FE(elphel_flush_cache, NULL)
00122     PHP_FE(elphel_gamma, NULL)
00123     PHP_FE(elphel_histogram, NULL)
00124     PHP_FE(elphel_get_gamma, NULL)
00125     PHP_FE(elphel_get_histogram, NULL)
00126     PHP_FE(elphel_get_exif_field, NULL)
00127     PHP_FE(elphel_set_exif_field, NULL)
00128     PHP_FE(elphel_get_exif_elphel, NULL)
00129     PHP_FE(elphel_update_exif, NULL)
00130     PHP_FE(elphel_get_circbuf_pointers, NULL)
00131     {NULL, NULL, NULL}
00132 };
00133 
00134 zend_module_entry elphel_module_entry = {
00135 #if ZEND_MODULE_API_NO >= 20010901
00136     STANDARD_MODULE_HEADER,
00137 #endif
00138     PHP_ELPHEL_EXTNAME,
00139     elphel_functions,
00140     PHP_MINIT(elphel),
00141     PHP_MSHUTDOWN(elphel),
00142     PHP_RINIT(elphel),
00143     NULL,
00144     PHP_MINFO(elphel),
00145 #if ZEND_MODULE_API_NO >= 20010901
00146     PHP_ELPHEL_VERSION,
00147 #endif
00148     STANDARD_MODULE_PROPERTIES
00149 };
00150 
00151 #ifdef COMPILE_DL_ELPHEL
00152 ZEND_GET_MODULE(elphel)
00153 #endif
00154 
00155 
00156 PHP_INI_BEGIN()
00158 PHP_INI_END()
00159 
00160 
00162 static void init_sens() {
00163   if ((((long *) ELPHEL_G(imageParamsR)) [P_SENSOR])==0)  lseek((int) ELPHEL_G( fd_sens), LSEEK_INIT_SENSOR , SEEK_END );
00164 }
00165 
00166 PHP_FUNCTION(elphel_flush_cache)
00167 {
00168   lseek((int)ELPHEL_G(fd_sens),LSEEK_FLUSH_CACHE, SEEK_END);
00169   RETURN_NULL();
00170 }
00171 
00172 long createExifDirectory (int rebuild) { 
00173      int indx;
00174      long numfields=0;
00175      struct exif_dir_table_t dir_table_entry;
00177      int exif_this_size=lseek((int) ELPHEL_G(fd_exifdir),1,SEEK_END); // at the beginning of page 1 - position == page length
00178 
00179      if ((ELPHEL_G(exif_size) == exif_this_size) && !rebuild) return 0; // no need to rebuild
00180      ELPHEL_G(exif_size) = exif_this_size;
00181 
00182      for (indx=0; indx<ExifKmlNumber; indx++) ELPHEL_G(exif_dir)[indx].ltag=0;
00183      while (read((int) ELPHEL_G(fd_exifdir), &dir_table_entry, sizeof(dir_table_entry))>0) {
00184        switch (dir_table_entry.ltag) {
00185          case Exif_Image_ImageDescription:      indx= Exif_Image_ImageDescription_Index; break;
00186          case Exif_Image_FrameNumber:           indx= Exif_Image_FrameNumber_Index; break;
00187          case Exif_Photo_DateTimeOriginal:      indx= Exif_Photo_DateTimeOriginal_Index; break;
00188          case Exif_Photo_SubSecTimeOriginal:    indx= Exif_Photo_SubSecTimeOriginal_Index; break;
00189          case Exif_Photo_ExposureTime:          indx= Exif_Photo_ExposureTime_Index; break;
00190          case Exif_GPSInfo_GPSLatitudeRef:      indx= Exif_GPSInfo_GPSLatitudeRef_Index; break;
00191          case Exif_GPSInfo_GPSLatitude:         indx= Exif_GPSInfo_GPSLatitude_Index ; break;
00192          case Exif_GPSInfo_GPSLongitudeRef:     indx= Exif_GPSInfo_GPSLongitudeRef_Index ; break;
00193          case Exif_GPSInfo_GPSLongitude:        indx= Exif_GPSInfo_GPSLongitude_Index; break;
00194          case Exif_GPSInfo_GPSAltitudeRef:      indx= Exif_GPSInfo_GPSAltitudeRef_Index; break;
00195          case Exif_GPSInfo_GPSAltitude:         indx= Exif_GPSInfo_GPSAltitude_Index; break;
00196          case Exif_GPSInfo_GPSTimeStamp:        indx= Exif_GPSInfo_GPSTimeStamp_Index; break;
00197          case Exif_GPSInfo_GPSDateStamp:        indx= Exif_GPSInfo_GPSDateStamp_Index; break;
00198          case Exif_GPSInfo_GPSMeasureMode:      indx= Exif_GPSInfo_GPSMeasureMode_Index; break;
00199          case Exif_GPSInfo_CompassDirectionRef: indx= Exif_GPSInfo_CompassDirectionRef_Index; break;
00200          case Exif_GPSInfo_CompassDirection:    indx= Exif_GPSInfo_CompassDirection_Index; break;
00201          case Exif_GPSInfo_CompassPitchRef:     indx= Exif_GPSInfo_CompassPitchRef_Index; break;
00202          case Exif_GPSInfo_CompassPitch:        indx= Exif_GPSInfo_CompassPitch_Index; break;
00203          case Exif_GPSInfo_CompassRollRef:      indx= Exif_GPSInfo_CompassRollRef_Index; break;
00204          case Exif_GPSInfo_CompassRoll:         indx= Exif_GPSInfo_CompassRoll_Index; break;
00205          default: indx=-1;
00206        }
00207        if (indx>=0) {
00208            memcpy(&(ELPHEL_G(exif_dir)[indx]),&dir_table_entry,sizeof(dir_table_entry));
00209            numfields++;
00210        }
00211      }
00212   return numfields;
00213 }
00214 
00215 
00216 //  add_assoc_long(return_value, key, ((long *) ELPHEL_G(imageParamsR))[ Z_LVAL(const_value)]);
00217 
00218 
00219 PHP_FUNCTION(elphel_get_circbuf_pointers) {
00220     char * ccam_dma_buf_char= (char *) ELPHEL_G( ccam_dma_buf);
00221     long second=0;
00222     long p,frameParamPointer;
00223     long buff_size=lseek(ELPHEL_G( fd_circ),0,SEEK_END); //size of circbuf
00224 
00225     zval *image_pointers;
00226     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &second) == FAILURE) {
00227         RETURN_NULL();
00228     }
00229     p=lseek((int) ELPHEL_G( fd_circ), second? CIRCLSEEK_SCND: CIRCLSEEK_FIRST, SEEK_END );
00230     if (p<0) RETURN_NULL();
00231     array_init(return_value);
00232     while (p>=0) {
00233       frameParamPointer=p-32;
00234       if (frameParamPointer<0) frameParamPointer+=buff_size;
00235       ALLOC_INIT_ZVAL(image_pointers);
00236       array_init(image_pointers);
00237       add_assoc_long(image_pointers, "circbuf_pointer", p);
00238       add_assoc_long(image_pointers, "exif_pointer", ((struct frame_params_t *) &ccam_dma_buf_char[frameParamPointer])->meta_index);
00239       add_next_index_zval(return_value, image_pointers);
00241       p=lseek((int) ELPHEL_G( fd_circ), CIRCLSEEK_NEXT, SEEK_END );
00242       p=lseek((int) ELPHEL_G( fd_circ), CIRCLSEEK_READY, SEEK_END );
00243 
00244     }
00245 }
00246 
00247 
00248 #define saferead255(f,d,l) read(f,d,((l)<256)?(l):255)
00249 PHP_FUNCTION(elphel_get_exif_elphel)
00250 {
00251     long rational3[6];
00252     long exif_page_start;
00253     char *key;
00254     long indx;
00255     char val[256];
00256     long exif_page=0;
00257     int hours=0, minutes=0;
00258     double seconds=0.0;
00259     double  longitude=0.0, latitude=0.0,  altitude=0.0,  heading=0.0,  roll=0.0, pitch=0.0, exposure=0.0;
00260     val[255]='\0';
00261     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &exif_page) == FAILURE) {
00262         RETURN_NULL();
00263     }
00264 
00265     createExifDirectory(0); 
00266     if (exif_page) exif_page_start=lseek ((int) ELPHEL_G(fd_exif), exif_page, SEEK_END); 
00267     else           exif_page_start=lseek ((int) ELPHEL_G(fd_exif), 0, SEEK_SET); 
00268     if (exif_page_start<0) RETURN_NULL(); //exif_page may be out of range
00269     array_init(return_value);
00270 
00271 
00273 
00274      if (ELPHEL_G(exif_dir)[Exif_Image_ImageDescription_Index].ltag==Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template
00275        lseek (ELPHEL_G(fd_exif),
00276               exif_page_start+ELPHEL_G(exif_dir)[Exif_Image_ImageDescription_Index].dst,
00277               SEEK_SET);
00278        saferead255(ELPHEL_G(fd_exif), val, ELPHEL_G(exif_dir)[Exif_Image_ImageDescription_Index].len);
00279        add_assoc_string(return_value, "ImageDescription", val,  1);
00280      }
00282      if (ELPHEL_G(exif_dir)[Exif_Image_FrameNumber_Index].ltag==Exif_Image_FrameNumber) { // Exif_Image_FrameNumber_Index is present in template
00283        lseek (ELPHEL_G(fd_exif),
00284               exif_page_start+ELPHEL_G(exif_dir)[Exif_Image_FrameNumber_Index].dst,
00285               SEEK_SET);
00286        read(ELPHEL_G(fd_exif), rational3, 4);
00287        sprintf (val,"%ld", (long) __cpu_to_be32( rational3[0]));
00288        add_assoc_string(return_value, "FrameNumber", val,  1);
00289      }
00290 
00292      if (ELPHEL_G(exif_dir)[Exif_Photo_DateTimeOriginal_Index].ltag==Exif_Photo_DateTimeOriginal) {
00293        lseek (ELPHEL_G(fd_exif),
00294               exif_page_start+ELPHEL_G(exif_dir)[Exif_Photo_DateTimeOriginal_Index].dst,
00295               SEEK_SET);
00296        read(ELPHEL_G(fd_exif), val, 19);
00297        val[19]='\0';
00298        if (ELPHEL_G(exif_dir)[Exif_Photo_SubSecTimeOriginal_Index].ltag==Exif_Photo_SubSecTimeOriginal) {
00299          val[19]='.';
00300          lseek (ELPHEL_G(fd_exif),
00301                 exif_page_start+ELPHEL_G(exif_dir)[Exif_Photo_SubSecTimeOriginal_Index].dst,
00302                 SEEK_SET);
00303          read(ELPHEL_G(fd_exif), &val[20], 7);
00304          val[27]='\0';
00305        }
00306        add_assoc_string(return_value, "DateTimeOriginal", val,  1);
00307      }
00308 
00310      if (ELPHEL_G(exif_dir)[Exif_Photo_ExposureTime_Index].ltag==Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template
00311        lseek (ELPHEL_G(fd_exif),
00312               exif_page_start+ELPHEL_G(exif_dir)[Exif_Photo_ExposureTime_Index].dst,
00313               SEEK_SET);
00314        read(ELPHEL_G(fd_exif), rational3, 8);
00315        exposure=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
00316        sprintf (val,"%f",exposure);
00317        add_assoc_string(return_value, "ExposureTime", val,  1);
00318      }
00319 
00320 
00322      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSMeasureMode_Index].ltag==Exif_GPSInfo_GPSMeasureMode) {
00323        lseek (ELPHEL_G(fd_exif),
00324               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSMeasureMode_Index].dst,
00325               SEEK_SET);
00326        read(ELPHEL_G(fd_exif), val, 1);
00327        add_assoc_stringl(return_value, "GPSMeasureMode", val, 1,  1);
00328      }
00329 
00331      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSDateStamp_Index].ltag==Exif_GPSInfo_GPSDateStamp) {
00332        lseek (ELPHEL_G(fd_exif),
00333               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSDateStamp_Index].dst,
00334               SEEK_SET);
00335        read(ELPHEL_G(fd_exif), val, 10);
00336        val[10]='\0';
00337        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSTimeStamp_Index].ltag==Exif_GPSInfo_GPSTimeStamp) {
00338          lseek (ELPHEL_G(fd_exif),
00339                 exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSTimeStamp_Index].dst,
00340                 SEEK_SET);
00341          read(ELPHEL_G(fd_exif), rational3, 24);
00342          hours=   __cpu_to_be32( rational3[0]);
00343          minutes= __cpu_to_be32( rational3[2]);
00344          seconds= (1.0*(__cpu_to_be32( rational3[4])+1))/__cpu_to_be32( rational3[5]); 
00345          sprintf (&val[10]," %02d:%02d:%05.2f",hours,minutes,seconds);
00346        }
00347        add_assoc_string(return_value, "GPSDateTime", val,  1);
00348      }
00349 
00352      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitude_Index].ltag==Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
00353        lseek (ELPHEL_G(fd_exif),
00354               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitude_Index].dst,
00355               SEEK_SET);
00356        read(ELPHEL_G(fd_exif), rational3, 24);
00357        longitude=__cpu_to_be32( rational3[0])/(1.0*__cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2])/(60.0*__cpu_to_be32( rational3[3]));
00358        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitudeRef_Index].ltag==Exif_GPSInfo_GPSLongitudeRef) {
00359          lseek (ELPHEL_G(fd_exif),
00360             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitudeRef_Index].dst,
00361             SEEK_SET);
00362          read(ELPHEL_G(fd_exif), val, 1);
00363          if (val[0]!= 'E') longitude=-longitude;
00364        }
00365        sprintf (val,"%f",longitude);
00366        add_assoc_string(return_value, "GPSLongitude", val,  1);
00367      }
00369      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitude_Index].ltag==Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
00370        lseek (ELPHEL_G(fd_exif),
00371               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitude_Index].dst,
00372               SEEK_SET);
00373        read(ELPHEL_G(fd_exif), rational3, 24);
00374        latitude=__cpu_to_be32( rational3[0])/(1.0*__cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2])/(60.0*__cpu_to_be32( rational3[3]));
00375        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitudeRef_Index].ltag==Exif_GPSInfo_GPSLatitudeRef) {
00376          lseek (ELPHEL_G(fd_exif),
00377             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitudeRef_Index].dst,
00378             SEEK_SET);
00379          read(ELPHEL_G(fd_exif), val, 1);
00380          if (val[0] != 'N') latitude=-latitude;
00381         }
00382        sprintf (val,"%f",latitude);
00383        add_assoc_string(return_value, "GPSLatitude", val,  1);
00384      }
00386      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitude_Index].ltag==Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
00387        lseek (ELPHEL_G(fd_exif),
00388               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitude_Index].dst,
00389               SEEK_SET);
00390        read(ELPHEL_G(fd_exif), rational3, 8);
00391        altitude=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
00392 
00393        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitudeRef_Index].ltag==Exif_GPSInfo_GPSAltitudeRef) {
00394          lseek (ELPHEL_G(fd_exif),
00395             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitudeRef_Index].dst,
00396             SEEK_SET);
00397          read(ELPHEL_G(fd_exif), val, 1);
00398          if (val[0] != '\0') altitude=-altitude;
00399         }
00400        sprintf (val,"%f",altitude);
00401        add_assoc_string(return_value, "GPSAltitude", val,  1);
00402      }
00404      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassDirection_Index].ltag==Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
00405        lseek (ELPHEL_G(fd_exif),
00406               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassDirection_Index].dst,
00407               SEEK_SET);
00408        read(ELPHEL_G(fd_exif), rational3, 8);
00409        heading=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
00410        sprintf (val,"%f",heading);
00411        add_assoc_string(return_value, "CompassDirection", val,  1);
00412      }
00415      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRoll_Index].ltag==Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
00416        lseek (ELPHEL_G(fd_exif),
00417               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRoll_Index].dst,
00418               SEEK_SET);
00419        read(ELPHEL_G(fd_exif), rational3, 8);
00420        roll=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
00421 
00422        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRollRef_Index].ltag==Exif_GPSInfo_CompassRollRef) {
00423          lseek (ELPHEL_G(fd_exif),
00424             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRollRef_Index].dst,
00425             SEEK_SET);
00426          read(ELPHEL_G(fd_exif), val, 1);
00427          if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll=-roll;
00428         }
00429        sprintf (val,"%f",roll);
00430        add_assoc_string(return_value, "CompassRoll", val,  1);
00431      }
00432 
00434      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitch_Index].ltag==Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
00435        lseek (ELPHEL_G(fd_exif),
00436               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitch_Index].dst,
00437               SEEK_SET);
00438        read(ELPHEL_G(fd_exif), rational3, 8);
00439        pitch=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
00440 
00441        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitchRef_Index].ltag==Exif_GPSInfo_CompassPitchRef) {
00442          lseek (ELPHEL_G(fd_exif),
00443             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitchRef_Index].dst,
00444             SEEK_SET);
00445          read(ELPHEL_G(fd_exif), val, 1);
00446          if (val[0] != EXIF_COMPASS_PITCH_ASCII[0]) pitch=-pitch;
00447         }
00448        sprintf (val,"%f",pitch);
00449        add_assoc_string(return_value, "CompassPitch", val,  1);
00450      }
00451 
00452 }
00453 
00454 
00455 PHP_FUNCTION(elphel_update_exif) {
00456     RETURN_LONG(createExifDirectory(1)); // force rebuild
00457 }
00458 
00459 
00460 PHP_FUNCTION(elphel_get_exif_field)
00461 {
00462     long exif_page=0;
00463     long ltag;
00464     struct exif_dir_table_t dir_table_entry;
00465     char * rslt;
00466     int found=0;
00467 
00468     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &ltag, &exif_page) == FAILURE) {
00469         RETURN_NULL();
00470     }
00471 // find the ltag in the directory (may need to scan all the directory)
00472     lseek ((int) ELPHEL_G(fd_exifdir), 0, SEEK_SET);
00473     while (read((int) ELPHEL_G(fd_exifdir), &dir_table_entry, sizeof(dir_table_entry))>0) {
00474       if (dir_table_entry.ltag==ltag) {
00475         found=1;
00476         break;
00477       }
00478     }
00479     if (!found) RETURN_NULL();
00480 //    lseek (fd_exifdir, 0, SEEK_SET);
00481     if (exif_page) found= lseek ((int) ELPHEL_G(fd_exif), exif_page, SEEK_END); 
00482     else           found= lseek ((int) ELPHEL_G(fd_exif), 0, SEEK_SET); 
00483     if (found<0) RETURN_NULL(); //exif_page may be out of range
00484 
00485     lseek ((int) ELPHEL_G(fd_exif), dir_table_entry.dst, SEEK_CUR);
00486     rslt=emalloc(dir_table_entry.len);
00487     read((int) ELPHEL_G(fd_exif), rslt, dir_table_entry.len);
00488     RETURN_STRINGL(rslt,dir_table_entry.len,0);
00489 }
00490 
00491 
00492 
00493 PHP_FUNCTION(elphel_set_exif_field)
00494 {
00495     
00496     long ltag;
00497     struct exif_dir_table_t dir_table_entry;
00498     char * value;
00499     int value_length;
00500     int found=0;
00501     
00502     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &ltag, &value,&value_length) == FAILURE) {
00503         RETURN_NULL();
00504     }
00505 // find the ltag in the directory (may need to scan all the directory)
00506     lseek ((int) ELPHEL_G(fd_exifdir), 0, SEEK_SET);
00507     while (read((int) ELPHEL_G(fd_exifdir), &dir_table_entry, sizeof(dir_table_entry))>0) {
00508       if (dir_table_entry.ltag==ltag) {
00509         found=1;
00510         break;
00511       }
00512     }
00513     if (!found) RETURN_NULL();
00514     lseek ((int) ELPHEL_G(fd_exifmeta), dir_table_entry.src, SEEK_SET);
00515     if (value_length>dir_table_entry.len) value_length = dir_table_entry.len;
00517 // php_printf ("value=%s, value_length=%d\n",value, value_length);
00518     long rslt=write(ELPHEL_G(fd_exifmeta), value, value_length);
00519     if (rslt<0) rslt =-errno;
00520     RETURN_LONG(rslt);
00521 }
00522 
00523 
00525 PHP_FUNCTION(elph_hello)
00526 {
00528     DEFINE_P_NAMES(pname_arr);
00529     int i;
00530 //    init_sens(); // to see w/o sensor initialization
00531     array_init(return_value);
00532     for (i=0;i< (sizeof(pname_arr)/sizeof(pname_arr[0])); i++) {
00533 //      add_assoc_long(return_value, pname_arr[i].name, pname_arr[i].value);
00534       add_assoc_long(return_value, pname_arr[i].name, ((long *) ELPHEL_G(imageParamsR))[pname_arr[i].value]);
00535     }
00536 }
00538 PHP_FUNCTION(elphel_wait_frame)
00539 {
00540     lseek((int) ELPHEL_G( fd_circ), CIRCLSEEK_TOWP, SEEK_END );
00541     lseek((int) ELPHEL_G( fd_circ), CIRCLSEEK_WAIT, SEEK_END );
00542     RETURN_NULL();
00543 }
00544 
00546 PHP_FUNCTION(elphel_autoexposure_set)
00547 {
00548     lseek((int) ELPHEL_G( fd_sens), LSEEK_AUTOEXP_SET, SEEK_END );
00549     RETURN_NULL();
00550 } 
00551 
00553 PHP_FUNCTION(elphel_autoexposure_get)
00554 {
00555     lseek((int) ELPHEL_G( fd_sens), LSEEK_AUTOEXP_GET, SEEK_END );
00556     RETURN_NULL();
00557 } 
00558 
00559 
00560 #define HIST_LEN  256 * 4 * 4
00561 #define GAMMA_LEN 256 * 4 * 2
00562 //  memcpy (hists, ELPHEL_G(hist_gamma_mmap), HIST_LEN);
00563 //  memcpy (gammas,ELPHEL_G(hist_gamma_mmap) + HIST_LEN, GAMMA_LEN);
00564 //histogram values are 18-bit onex, gamma - unsigned short 0..0xffff
00565 
00566 PHP_FUNCTION(elphel_get_histogram)
00567 {
00568     long addr;
00569 
00570     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
00571         RETURN_NULL();
00572     }
00573     if ((addr > 1023) || (addr <0)) {
00574         RETURN_NULL();
00575     }
00576     RETURN_LONG(  ((long *) ELPHEL_G(hist_gamma_mmap))[addr]);
00577 } 
00578 PHP_FUNCTION(elphel_get_gamma)
00579 {
00580     long addr;
00581 
00582     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
00583         RETURN_NULL();
00584     }
00585     if ((addr > 1023) || (addr <0)) {
00586         RETURN_NULL();
00587     }
00588     RETURN_LONG(  ((unsigned short *) ELPHEL_G(hist_gamma_mmap))[addr+(HIST_LEN>>1)]);
00589 } 
00590 
00591 
00596 PHP_FUNCTION(elphel_gamma)
00597 {
00598   unsigned short gamma[256];
00599     long   channel;
00600     double indat,outdat;
00601     int indx;
00602     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &channel, &indat ) == FAILURE) {
00603         RETURN_LONG (-1);
00604     }
00605     if ((channel <0) || (channel > 3)) RETURN_LONG (-1); 
00606 
00607 
00608     memcpy (gamma,ELPHEL_G(hist_gamma_mmap) + HIST_LEN + ((GAMMA_LEN>>2)*channel), (GAMMA_LEN>>2)); // one color only
00609     indat*=255.0;
00610     indx=indat;
00611     if      (indx < 0)   outdat=0.0;
00612     else if (indx >=255) outdat=1.0;
00613     else     outdat=(gamma[indx]+ (gamma[indx+1]-gamma[indx])*(indat-indx))*(1.0/65535);
00614     RETURN_DOUBLE (outdat);
00615 }
00616 
00617 PHP_FUNCTION(elphel_histogram)
00618 {
00619   unsigned long histogram[256];
00620     long   channel;
00621     double indat,outdat;
00622     int i,d;
00623     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &channel, &indat ) == FAILURE) {
00624         RETURN_LONG (-1);
00625     }
00626     if ((channel <0) || (channel > 3)) RETURN_LONG (-1); 
00627 
00628     memcpy (histogram,ELPHEL_G(hist_gamma_mmap) + ((HIST_LEN>>2)*channel), (HIST_LEN>>2)); // one color only
00629     if (indat <= 0.0) outdat=0.0;
00630     else if (indat>=1.0) outdat=1.0;
00631     else {
00632       for (i=1;i<256;i++) histogram[i]+=histogram[i-1];
00633       indat*=histogram[255];
00634       d=indat;
00635       for (i=0; histogram[i] <= d; i++);
00636       if (i==0) outdat= ((1.0/255.0)*d)/histogram[0];
00637       else      outdat= (1.0/255.0)*((i-1)+ (1.0*(d-histogram[i-1])/(histogram[i]-histogram[i-1])));
00638     }
00639     RETURN_DOUBLE (outdat);
00640 }
00641 
00650 //#define HISTDBG y
00651 //#define HIST_LEN      256 * 4 * 4
00652 //#define GAMMA_LEN     256 * 4 * 2
00653 int calcWhiteBalance(int thrsh,   // threshold (0..255) for the "brightest color"
00654                      int min_pixels, // minimal number of pixels above threshold for the brightest color (threshold will be lowered to satisfy min_pixels)
00655                      double diffGains[3], 
00656                      long use_green2
00657                      ){
00658   double colPercentiles[4];
00659   int hists[1024];
00660   unsigned short gammas[1024];
00661 //  int retr=10000;
00662   int sum[4];
00663   int indx[4];
00664   int i,j,k,smax;
00665   int percFound=0;
00667   memcpy (hists, ELPHEL_G(hist_gamma_mmap), HIST_LEN);
00668   memcpy (gammas,ELPHEL_G(hist_gamma_mmap) + HIST_LEN, GAMMA_LEN);
00669 
00670 #ifdef HISTDBG
00671   php_printf ("thrsh=%d, min_pixels=%d\n",thrsh, min_pixels);
00672   for (k=0; k<4; k++) {
00673     php_printf ("k=%d\n",k);
00674     for (j=0; j<256; j+=16) {
00675       php_printf ( "%03x: ",j);
00676       for (i=j; i<j+16; i++) {
00677         php_printf ( " %08x: ",hists[256*k+i]);
00678       }
00679       php_printf ("\n");
00680     }
00681   }
00682 
00683   for (k=0; k<4; k++) {
00684     php_printf ("k=%d\n",k);
00685     for (j=0; j<256; j+=16) {
00686       php_printf ( "%03x: ",j);
00687       for (i=j; i<j+16; i++) {
00688         php_printf ( " %04x: ", (int) gammas[256*k+i]);
00689       }
00690       php_printf ("\n");
00691     }
00692   }
00693 #endif
00694 
00695 
00696   for (j=0;j<4;j++) {sum[j]=0;indx[j]=-1;colPercentiles[j]=-1.0;}
00697   for (i=255;i>=thrsh;i--) for (j=0;j<4;j++)   sum[j]+=hists[i+ (j<<8)];
00698 #ifdef HISTDBG
00699  php_printf ("sum[0]=%d,  sum[1]=%d,  sum[2]=%d,  sum[3]=%d\n", sum[0], sum[1], sum[2], sum[3]);
00700 #endif
00701   smax = sum[0];
00702   for (j=1;j<4;j++) if (sum[j]>smax) smax=sum[j];
00703   if (smax<min_pixels) {
00704     for (i=thrsh-1;(i>0) && (smax<min_pixels); i--) { 
00705       for (j=0;j<4;j++)   sum[j]+=hists[i+ (j<<8)];
00706       for (j=0;j<4;j++) {
00707          if (((j!=2) || use_green2) && (sum[j]>smax)) {smax=sum[j];k=j;thrsh=i;}
00708       }
00709     }
00710   }
00711 #ifdef HISTDBG
00712   php_printf ("thrsh=%d\n",thrsh);
00713   php_printf ("smax=%d, sum[0]=%d, sum[1]=%d, sum[2]=%d, sum[3]=%d\n",smax, sum[0], sum[1], sum[2], sum[3]);
00714 #endif
00715 
00716   if(smax < min_pixels) return -2; 
00717   i=0;
00718   smax=0;
00719   for (j=0;j<4;j++) if (((j!=2) || use_green2) && (sum[j]>smax)) {smax=sum[j];i=j;}
00720   indx[i]=thrsh; //colPercentiles[i]=thrsh;
00721   percFound |= (1<<i);
00722   for (i=thrsh-1;(i>0) && (percFound != 0xf); i--) { 
00723     for (j=0;j<4;j++)  if (((j!=2) || use_green2) && !(percFound & (1 <<j))) {
00724       sum[j] += hists[i+ (j<<8)];
00725       if (sum[j]>=smax) {
00726         percFound |= (1<<j);
00727         indx[j]=i;
00728       }
00729     }
00730   }
00731 #ifdef HISTDBG
00732   php_printf ("sum[0]=%d,  sum[1]=%d,  sum[2]=%d,  sum[3]=%d\n", sum[0], sum[1], sum[2], sum[3]);
00733   php_printf ("indx[0]=%d, indx[1]=%d, indx[2]=%d, indx[3]=%d\n", indx[0], indx[1], indx[2], indx[3]);
00734 #endif
00735   if (!use_green2) percFound |= 0x4; // as if found
00736 
00737   if(percFound != 0xf) return -3; 
00738   for (j=0;j<4;j++) if ((j!=2) || use_green2) {
00739     if (sum[j]==smax) colPercentiles[j]=indx[j];
00740     else colPercentiles[j]= indx[j]+(1.0*(sum[j]-smax))/hists[indx[j]+ (j<<8)];
00741   }
00743 //TODO: use all 16 bits of gamma? Or actual 10-bit table?
00744   k=0; // to make gcc happy
00745   for (j=0;j<4;j++) if ((j!=2) || use_green2) {
00746     for (i=255;(i>=0) && ((k=((gammas[i+(j<<8)]>>8) & 0xff)) > indx[j]);i--);
00747     colPercentiles[j]=i+ (colPercentiles[j]-k)/ ( ((gammas[i+1+(j<<8)]>>8) & 0xff) -k);
00748   }
00749 
00750 //  diffGains[0]=(colPercentiles[1]+colPercentiles[2])/2.0/colPercentiles[0];
00751 //  diffGains[1]=(colPercentiles[1]+colPercentiles[2])/2.0/colPercentiles[3];
00752 
00753   diffGains[0]=colPercentiles[1]/colPercentiles[0];
00754   diffGains[1]=colPercentiles[1]/colPercentiles[3];
00755   if ((j!=2) || use_green2) diffGains[2]=colPercentiles[1]/colPercentiles[2];
00756 
00757 #ifdef HISTDBG
00758   for (k=0; k<4; k++)  php_printf ("colPercentiles[%d]=%f\n",k,colPercentiles[k]);
00759   for (k=0; k<3; k++)  php_printf ("diffGains[%d]=%f\n",k,diffGains[k]);
00760 #endif
00761   return 0; 
00762 }
00769 PHP_FUNCTION(elphel_white_balance)
00770 {
00771     double thrsh=   0.98;
00772     double minfrac =0.01;
00773     double rscale=  1.0;
00774     double bscale=  1.0;
00775     double corr_factor=1.0; // correct less than calculated (to smooth scene variations)
00776     int ithrsh, minpix;
00777     double wbDiffGains[3]; 
00778     long   corr_green=0;
00779     int rslt=-1;
00780     int d,s;
00781     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ddddl", &thrsh, &minfrac, &rscale, &bscale, &corr_factor, &corr_green) == FAILURE) {
00782         RETURN_LONG (-1);
00783     }
00784     ithrsh=(255*thrsh)+0.5;
00785     minpix=  ((long *) ELPHEL_G(imageParamsR))[P_ACTUAL_WIDTH] *
00786              ((long *) ELPHEL_G(imageParamsR))[P_ACTUAL_HEIGHT] *
00787              minfrac; 
00788     rslt = calcWhiteBalance( ithrsh, 
00789                              minpix, 
00790                              wbDiffGains,
00791                              corr_green);
00792     if (rslt)  RETURN_LONG (rslt) ; 
00793 
00794     wbDiffGains[0]*=rscale;
00795     wbDiffGains[1]*=bscale;
00798     ((long *) ELPHEL_G(imageParamsR))[P_RSCALE+P_NUMBER]=256.0*wbDiffGains[0];
00799     ((long *) ELPHEL_G(imageParamsR))[P_BSCALE+P_NUMBER]=256.0*wbDiffGains[1];
00800     if (corr_green) ((long *) ELPHEL_G(imageParamsR))[P_GSCALE+P_NUMBER]=256.0*wbDiffGains[2]; // always full - anyway small
00801     if (corr_factor < 1.0) {
00802      d=((long *) ELPHEL_G(imageParamsR))[P_RSCALE+P_NUMBER]-((long *) ELPHEL_G(imageParamsR))[P_RSCALE];
00803      s=1;
00804      if (d<0) {d=-d;s=-s;};
00805      if (d) {
00806        d *= corr_factor;
00807        if (d<1) d=1;
00808        ((long *) ELPHEL_G(imageParamsR))[P_RSCALE+P_NUMBER]=((long *) ELPHEL_G(imageParamsR))[P_RSCALE]+s*d;
00809      }
00810      d=((long *) ELPHEL_G(imageParamsR))[P_BSCALE+P_NUMBER]-((long *) ELPHEL_G(imageParamsR))[P_BSCALE];
00811      s=1;
00812      if (d<0) {d=-d;s=-s;};
00813      if (d) {
00814        d *= corr_factor;
00815        if (d<1) d=1;
00816        ((long *) ELPHEL_G(imageParamsR))[P_BSCALE+P_NUMBER]=((long *) ELPHEL_G(imageParamsR))[P_BSCALE]+s*d;
00817      }
00818     }
00819     RETURN_LONG (0);
00820 }
00821 
00822 
00823 
00828 PHP_FUNCTION(elphel_get_P_arr)
00829 {
00830     char full_constant_name[256];
00831     zval *arr, **data;
00832     HashTable *arr_hash;
00833     HashPosition pointer;
00834     char *key;
00835     int   key_len;
00836     long index;
00837     zval const_value;
00838     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
00839         RETURN_NULL();
00840     }
00841     init_sens();
00842     array_init(return_value);
00843     arr_hash = Z_ARRVAL_P(arr);
00844     for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
00845         zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;
00846         zend_hash_move_forward_ex(arr_hash, &pointer)) {
00847         if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) {
00848            sprintf (full_constant_name,"ELPHEL_%s",key);
00849            if (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC)) {
00850               add_assoc_long(return_value, key, ((long *) ELPHEL_G(imageParamsR))[ Z_LVAL(const_value)]);
00851               zval_dtor(&const_value);
00852            }
00853         }
00854     }
00855 }
00857 PHP_FUNCTION(elphel_get_P_warr)
00858 {
00859     char full_constant_name[256];
00860     zval *arr, **data;
00861     HashTable *arr_hash;
00862     HashPosition pointer;
00863     char *key;
00864     int   key_len;
00865     long index;
00866     zval const_value;
00867     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
00868         RETURN_NULL();
00869     }
00870     init_sens();
00871     array_init(return_value);
00872     arr_hash = Z_ARRVAL_P(arr);
00873     for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
00874         zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;
00875         zend_hash_move_forward_ex(arr_hash, &pointer)) {
00876         if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) {
00877            sprintf (full_constant_name,"ELPHEL_%s",key);
00878            if (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC)) {
00879               add_assoc_long(return_value, key, ((long *) ELPHEL_G(imageParamsR))[P_NUMBER + Z_LVAL(const_value)]);
00880               zval_dtor(&const_value);
00881            }
00882         }
00883     }
00884 }
00885 
00886 
00891 PHP_FUNCTION(elphel_set_P_arr)
00892 {
00893     char full_constant_name[256];
00894     zval *arr, **data;
00895     HashTable *arr_hash;
00896     HashPosition pointer;
00897     char *key;
00898     int   key_len;
00899     long index;
00900     zval const_value;
00901     int num_written=0;
00902     int reg_addr, reg_data;
00903     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
00904         RETURN_LONG(num_written);
00905     }
00906     init_sens();
00907     arr_hash = Z_ARRVAL_P(arr);
00908     for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
00909         zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;
00910         zend_hash_move_forward_ex(arr_hash, &pointer)) {
00911         if ((zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) &&
00912            (Z_TYPE_PP(data) == IS_LONG)) {
00913            reg_data=Z_LVAL_PP(data);
00914            sprintf (full_constant_name,"ELPHEL_%s",key);
00915            if (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC)) {
00916               reg_addr=Z_LVAL(const_value);
00917               zval_dtor(&const_value);
00918               if ((reg_addr>=0) && (reg_addr<P_NUMBER)) {
00919                 ((long *) ELPHEL_G(imageParamsR))[reg_addr+P_NUMBER]=reg_data;
00920                 num_written++;
00921               }
00922            }
00923         }
00924     }
00925     RETURN_LONG(num_written);
00926 }
00927 
00929 PHP_FUNCTION(elphel_fpga_read)
00930 {
00931     long addr,data,res;
00932     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
00933         RETURN_NULL();
00934     }
00935     int fd=open("/dev/fpgaio", O_RDONLY);
00936     if (fd<0) {
00937       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/fpgaio");
00938       return ;
00939     }
00940     lseek (fd, addr,SEEK_SET) ; 
00941     res=read(fd,&data,4);
00942     close (fd);
00943     if (res<4) {
00944       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not read file %s","/dev/fpgaio");
00945       return ;
00946     }
00947     RETURN_LONG(data);
00948 }
00949 
00950 PHP_FUNCTION(elphel_fpga_write)
00951 {
00952     long addr,data,res;
00953     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &addr,&data) == FAILURE) {
00954         RETURN_NULL();
00955     }
00956     int fd=open("/dev/fpgaio", O_RDWR);
00957     if (fd<0) {
00958       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/fpgaio");
00959       return ;
00960     }
00961     lseek (fd, addr,SEEK_SET) ; 
00962     res=write(fd,&data,4);
00963     close (fd);
00964     if (res<4) {
00965       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not write to file %s","/dev/fpgaio");
00966       return ;
00967     }
00968     RETURN_NULL();
00969 }
00970 
00971 
00972 
00975 PHP_FUNCTION(elphel_get_P_value)
00976 {
00977     long addr;
00978 
00979     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
00980         RETURN_NULL();
00981     }
00982     if ((addr<0) ||(addr>= (P_NUMBER * 4))) {
00983         RETURN_NULL();
00984     }
00985     init_sens();
00986     RETURN_LONG(  ((long *) ELPHEL_G(imageParamsR))[addr]);
00987 } 
00989 PHP_FUNCTION(elphel_set_P_value)
00990 {
00991     long addr;
00992     long data;
00993 
00994     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &addr,&data) == FAILURE) {
00995         RETURN_NULL();
00996     }
00997     if ((addr<0) ||(addr>= (P_NUMBER * 2))) {
00998         RETURN_NULL();
00999     }
01000     if (addr>=P_NUMBER) addr-=P_NUMBER;
01001     else                addr+=P_NUMBER;
01002     init_sens();
01003     ((long *) ELPHEL_G(imageParamsR))[addr]=data;
01004     RETURN_NULL();
01005 } 
01006 
01008 PHP_FUNCTION(elphel_get_state)
01009 {
01010     RETURN_LONG(lseek((int) ELPHEL_G( fd_sens), LSEEK_CAMSEQSTATE, SEEK_END ));
01011 } 
01012 
01014 PHP_FUNCTION(elphel_program_sensor)
01015 {
01016     long nonstop;
01017 
01018     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &nonstop) == FAILURE) {
01019         RETURN_NULL();
01020     }
01021     init_sens();
01022     if (nonstop) lseek((int) ELPHEL_G( fd_sens), PROGRAM_SENSOR_1, SEEK_END );
01023     else         lseek((int) ELPHEL_G( fd_sens), PROGRAM_SENSOR_0, SEEK_END );
01024     RETURN_NULL();
01025 } 
01026 
01028 PHP_FUNCTION(elphel_compressor_cmd)
01029 {
01030     long cmd;
01031     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &cmd) == FAILURE) {
01032         RETURN_NULL();
01033     }
01034     lseek((int) ELPHEL_G( fd_sens), cmd, SEEK_END );
01035     RETURN_NULL();
01036 } 
01038 PHP_FUNCTION(elphel_compressor_reset)
01039 {
01040     lseek((int) ELPHEL_G( fd_sens), JPEG_CMD_RESET0, SEEK_END );
01041     RETURN_NULL();
01042 } 
01043 
01045 PHP_FUNCTION(elphel_compressor_run)
01046 {
01047     lseek((int) ELPHEL_G( fd_sens), JPEG_CMD_START, SEEK_END );
01048     RETURN_NULL();
01049 } 
01050 
01052 
01053 PHP_FUNCTION(elphel_compressor_stop)
01054 {
01055     lseek((int) ELPHEL_G( fd_sens), JPEG_CMD_JUST_STOP, SEEK_END );
01056     RETURN_NULL();
01057 } 
01059 PHP_FUNCTION(elphel_compressor_frame)
01060 {
01061     lseek((int) ELPHEL_G( fd_sens), JPEG_CMD_ACQUIRE, SEEK_END );
01062     RETURN_NULL();
01063 } 
01064 
01066 PHP_FUNCTION(elphel_is_compressor_idle)
01067 {
01068   int state= lseek((int) ELPHEL_G( fd_sens), LSEEK_CAMSEQSTATE, SEEK_END );
01069   if      (state == 7) {RETURN_LONG (((((long *) ELPHEL_G(imageParamsR)) [P_COMPRESSOR_CMD])==0)?1:0);} 
01070   else if (state >  7) {RETURN_LONG (0);}
01071   else                 {RETURN_LONG (1);}
01072 }
01073 
01075 PHP_FUNCTION(elphel_reset_sensor) {
01076   lseek((int) ELPHEL_G( fd_sens), JPEG_CMD_RESET, SEEK_END );      
01077   lseek((int) ELPHEL_G( fd_sens), LSEEK_RESET_SENSOR , SEEK_END ); 
01078   init_sens();                                                     
01079   RETURN_NULL();
01080 }
01081 
01085 PHP_FUNCTION(elphel_set_fpga_time) {
01086   double dtime;
01087   long ltime_sec,ltime_usec;
01088   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dtime) == FAILURE) {
01089         RETURN_NULL();
01090   }
01091   ltime_sec=dtime;
01092   ltime_usec=(dtime-ltime_sec)*1000000;
01093   ((long *) ELPHEL_G(imageParamsR)) [P_SECONDS+P_NUMBER] =      ltime_sec;
01094   ((long *) ELPHEL_G(imageParamsR)) [P_MICROSECONDS+P_NUMBER] = ltime_usec;
01095   lseek((int) ELPHEL_G( fd_sens), LSEEK_SET_FPGA_TIME, SEEK_END );
01096   dtime=ltime_usec;
01097   dtime=ltime_sec+0.000001*dtime;
01098   RETURN_DOUBLE(dtime);
01099 }
01100 
01102 PHP_FUNCTION(elphel_get_fpga_time) {
01103   double dtime;
01104   long ltime_sec,ltime_usec;
01105   lseek((int) ELPHEL_G( fd_sens), LSEEK_GET_FPGA_TIME, SEEK_END );
01106   dtime=((long *) ELPHEL_G(imageParamsR)) [P_MICROSECONDS];
01107   dtime=(((long *) ELPHEL_G(imageParamsR)) [P_SECONDS]) + 0.000001*dtime;
01108   RETURN_DOUBLE(dtime);
01109 }
01110 
01112 PHP_FUNCTION(elphel_trigger)
01113 {
01114     lseek((int) ELPHEL_G( fd_sens),  LSEEK_TRIGGER_PGM, SEEK_END );
01115     RETURN_NULL();
01116 } 
01117 
01118 
01119 static void php_elphel_init_globals(zend_elphel_globals *elphel_globals)
01120 {
01122     elphel_globals->imageParamsR = NULL;
01123     elphel_globals->fd_sens= open("/dev/sensorpars", O_RDWR);
01124     if (elphel_globals->fd_sens <0) {
01125       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/sensorpars");
01126       return ;
01127     }
01129     elphel_globals->imageParamsR = (unsigned long *) mmap(0, P_NUMBER*4 *4 , PROT_READ | PROT_WRITE, MAP_SHARED, elphel_globals->fd_sens, 0);
01130     if((int)elphel_globals->imageParamsR == -1) {
01131       elphel_globals->imageParamsR=NULL;
01132 //     php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error in mmap");
01133 //     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in mmap");
01134       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap /dev/sensorpars");
01135       close (elphel_globals->fd_sens);
01136       elphel_globals->fd_sens = -1;
01137       return ;
01138     }
01140     elphel_globals->ccam_dma_buf = NULL;
01141     elphel_globals->fd_circ= open("/dev/circbuf", O_RDWR);
01142     if (elphel_globals->fd_circ <0) {
01143       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/circbuf");
01144       return ;
01145     }
01146     elphel_globals->ccam_dma_buf_len=lseek(elphel_globals->fd_circ,0,SEEK_END); //size of circbuf
01147 
01149     elphel_globals->ccam_dma_buf = (unsigned long *) mmap(0, elphel_globals->ccam_dma_buf_len , PROT_READ | PROT_WRITE, MAP_SHARED, elphel_globals->fd_circ, 0);
01150     if((int)elphel_globals->ccam_dma_buf == -1) {
01151       elphel_globals->ccam_dma_buf=NULL;
01152       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap /dev/circbuf");
01153       close (elphel_globals->fd_circ);
01154       elphel_globals->fd_circ = -1;
01155       return ;
01156     }
01157 
01158 
01159 //hist_gamma_mmap
01160 //  while ( (((autoexp_fd = open(AUTOEXP_DEV_NAME, O_RDONLY)))<0) && (retr>0)) retr--; // maybe now not needed after this file can be opened for reading multiple times
01162     elphel_globals->hist_gamma_mmap = NULL;
01163     elphel_globals->fd_autoexp = open(AUTOEXP_DEV_NAME, O_RDONLY);
01164     if (elphel_globals->fd_autoexp <0) {
01165       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",AUTOEXP_DEV_NAME);
01166       return ;
01167     }
01168     elphel_globals->hist_gamma_mmap = (void *) mmap(NULL, TABLES_LEN, PROT_READ, MAP_FIXED | MAP_SHARED, elphel_globals->fd_autoexp, 0);
01169     if(elphel_globals->hist_gamma_mmap == MAP_FAILED) {
01170       elphel_globals->hist_gamma_mmap=NULL;
01171       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap %s",AUTOEXP_DEV_NAME);
01172       close (elphel_globals->fd_autoexp);
01173       elphel_globals->fd_autoexp = -1;
01174       return ;
01175     }
01176     elphel_globals->fd_exif = open(EXIF_DEV_NAME, O_RDONLY);
01177     if (elphel_globals->fd_exif <0) {
01178       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",EXIF_DEV_NAME);
01179       return ;
01180     }
01181     elphel_globals->fd_exifdir = open(EXIFDIR_DEV_NAME, O_RDONLY);
01182     if (elphel_globals->fd_exifdir <0) {
01183       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",EXIFDIR_DEV_NAME);
01184       return ;
01185     }
01186     elphel_globals->fd_exifmeta = open(EXIFMETA_DEV_NAME, O_RDWR);
01187     if (elphel_globals->fd_exifmeta <0) {
01188       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",EXIFMETA_DEV_NAME);
01189       return ;
01190     }
01191     elphel_globals->exif_size=0;
01192 //    php_printf ("ccam_dma_buf=0x%lx\n",                   (long)  elphel_globals->ccam_dma_buf );
01193 //    php_printf ("imageParamsR=0x%lx\n",                   (long)  elphel_globals->imageParamsR );
01194 //    php_printf ("elphel_globals->hist_gamma_mmap=0x%lx\n",(long)  elphel_globals->hist_gamma_mmap ); ///NOTE: Why does it print 0 here???
01195 
01196 }
01197 
01198 PHP_RINIT_FUNCTION(elphel)
01199 {
01200 // session initialization may be here
01201 
01202     return SUCCESS;
01203 }
01204 
01205 PHP_MINIT_FUNCTION(elphel)
01206 {
01207     ZEND_INIT_MODULE_GLOBALS(elphel, php_elphel_init_globals, NULL);
01208 
01209     DEFINE_P_NAMES(pname_arr);
01210     int i;
01211     char full_constant_name[256];
01213     REGISTER_INI_ENTRIES(); // not used yet
01214     for (i=0;i< (sizeof(pname_arr)/sizeof(pname_arr[0])); i++) {
01215       sprintf (full_constant_name,"ELPHEL_%s",pname_arr[i].name);
01216       zend_register_long_constant(full_constant_name, strlen(full_constant_name)+1, pname_arr[i].value, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
01217     }
01218     return SUCCESS;
01219 
01220 }
01221 
01222 PHP_MSHUTDOWN_FUNCTION(elphel)
01223 {
01224     UNREGISTER_INI_ENTRIES();
01225     if (ELPHEL_G(imageParamsR)) ; //unmap?
01226     if (ELPHEL_G(fd_sens)>=0) close (ELPHEL_G(fd_sens));
01227     if (ELPHEL_G(ccam_dma_buf)) ; //unmap?
01228     if (ELPHEL_G(fd_circ)>=0) close (ELPHEL_G(fd_circ));
01229     if (ELPHEL_G(hist_gamma_mmap)) ; //unmap?
01230     if (ELPHEL_G(fd_autoexp)>=0) close (ELPHEL_G(fd_autoexp));
01231     if (ELPHEL_G(fd_exif)>=0) close (ELPHEL_G(fd_exif));
01232     if (ELPHEL_G(fd_exifdir)>=0) close (ELPHEL_G(fd_exifdir));
01233     if (ELPHEL_G(fd_exifmeta)>=0) close (ELPHEL_G(fd_exifmeta));
01234     return SUCCESS;
01235 }
01236 
01237 PHP_MINFO_FUNCTION(elphel)
01238 {
01239         php_info_print_table_start();
01240         php_info_print_table_row(2, "Elphel support", "Enabled");
01241         php_info_print_table_row(2, "Elphel API Version", PHP_ELPHEL_VERSION);
01242         php_info_print_table_end();
01243 }
01244 

Generated on Thu Aug 7 16:18:59 2008 for elphel by  doxygen 1.5.1