| | 1 | /* |
|---|
| | 2 | * Copyright 2006 Anthony Rowe and Adam Goode |
|---|
| | 3 | * |
|---|
| | 4 | * This file is part of cc3. |
|---|
| | 5 | * |
|---|
| | 6 | * cc3 is free software; you can redistribute it and/or modify |
|---|
| | 7 | * it under the terms of the GNU General Public License as published by |
|---|
| | 8 | * the Free Software Foundation; either version 2 of the License, or |
|---|
| | 9 | * (at your option) any later version. |
|---|
| | 10 | * |
|---|
| | 11 | * cc3 is distributed in the hope that it will be useful, |
|---|
| | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| | 14 | * GNU General Public License for more details. |
|---|
| | 15 | * |
|---|
| | 16 | * You should have received a copy of the GNU General Public License |
|---|
| | 17 | * along with cc3; if not, write to the Free Software |
|---|
| | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| | 19 | */ |
|---|
| | 20 | |
|---|
| | 21 | |
|---|
| | 22 | /****************************************************************************** |
|---|
| | 23 | * |
|---|
| | 24 | * Initial CMUcam3 (cc3) data types and functions. |
|---|
| | 25 | * |
|---|
| | 26 | *****************************************************************************/ |
|---|
| | 27 | #include <stdbool.h> |
|---|
| | 28 | #include <stdlib.h> |
|---|
| | 29 | |
|---|
| | 30 | #include "cc3.h" |
|---|
| | 31 | #include "cc3_pin_defines.h" |
|---|
| | 32 | #include "cc3_hal.h" |
|---|
| | 33 | #include "serial.h" |
|---|
| | 34 | #include "devices.h" |
|---|
| | 35 | |
|---|
| | 36 | |
|---|
| | 37 | // Globals used by CMUCam functions |
|---|
| | 38 | cc3_pixel_t cc3_g_current_pixel; // global that gets updated with pixbuf calls |
|---|
| | 39 | cc3_frame_t cc3_g_current_frame; // global that keeps clip, stride |
|---|
| | 40 | |
|---|
| | 41 | |
|---|
| | 42 | static inline void _cc3_seek_left (void); |
|---|
| | 43 | static inline void _cc3_seek_top (void); |
|---|
| | 44 | |
|---|
| | 45 | static inline void _cc3_pixbuf_skip_pixels (uint32_t size); |
|---|
| | 46 | |
|---|
| | 47 | static inline uint8_t _cc3_pixbuf_read_subpixel (void); |
|---|
| | 48 | |
|---|
| | 49 | static inline void _cc3_pixbuf_read_pixel (uint8_t * pixel, |
|---|
| | 50 | uint8_t * saved, |
|---|
| | 51 | uint8_t off0, |
|---|
| | 52 | uint8_t off1, uint8_t off2); |
|---|
| | 53 | |
|---|
| | 54 | static inline void _cc3_pixbuf_skip_subpixel (void); |
|---|
| | 55 | |
|---|
| | 56 | |
|---|
| | 57 | // Move to the next byte in the FIFO |
|---|
| | 58 | static inline void _cc3_fifo_read_inc (void); |
|---|
| | 59 | |
|---|
| | 60 | static uint8_t _cc3_second_green; |
|---|
| | 61 | static bool _cc3_second_green_valid; |
|---|
| | 62 | |
|---|
| | 63 | static void _cc3_update_frame_bounds (cc3_frame_t *); |
|---|
| | 64 | |
|---|
| | 65 | void cc3_pixbuf_load () |
|---|
| | 66 | { |
|---|
| | 67 | // uint32_t start_time; |
|---|
| | 68 | FILE *fp; |
|---|
| | 69 | char filename[40]; |
|---|
| | 70 | int x,i,val,tmp,r,g,b,r2,b2,g2,t; |
|---|
| | 71 | char c; |
|---|
| | 72 | static int img_cnt=0; |
|---|
| | 73 | |
|---|
| | 74 | printf( "cc3_pixbuf_loaded()\n" ); |
|---|
| | 75 | if(_cc3_g_current_camera_state.colorspace==CC3_YCRCB) |
|---|
| | 76 | { |
|---|
| | 77 | printf( "Virtual Cam Achtung! Das YCrCb Colorspace ist Verboten...\n" ); |
|---|
| | 78 | exit(0); |
|---|
| | 79 | } |
|---|
| | 80 | if(_cc3_g_current_camera_state.resolution ==CC3_LOW_RES ) |
|---|
| | 81 | sprintf(filename, "../virtual_cam/low_res/IMG%.5d.PPM", img_cnt); |
|---|
| | 82 | else |
|---|
| | 83 | sprintf(filename, "../virtual_cam/high_res/IMG%.5d.PPM", img_cnt); |
|---|
| | 84 | img_cnt++; |
|---|
| | 85 | fp=fopen(filename,"r" ); |
|---|
| | 86 | if(fp==NULL ) |
|---|
| | 87 | { |
|---|
| | 88 | printf( "Virtual Camera Error: No more test images...\n" ); |
|---|
| | 89 | printf( "Last tried img: %s\n",filename ); |
|---|
| | 90 | exit(0); |
|---|
| | 91 | } |
|---|
| | 92 | |
|---|
| | 93 | // skip first 3 rows of ppm |
|---|
| | 94 | for(i=0; i<3; i++ ) |
|---|
| | 95 | { |
|---|
| | 96 | do { |
|---|
| | 97 | c=fgetc(fp); |
|---|
| | 98 | }while(c!='\n' ); |
|---|
| | 99 | } |
|---|
| | 100 | |
|---|
| | 101 | i=0; |
|---|
| | 102 | do{ |
|---|
| | 103 | val=fscanf( fp, "%d", &r ); if(val==EOF) break; |
|---|
| | 104 | val=fscanf( fp, "%d", &g ); if(val==EOF) break; |
|---|
| | 105 | val=fscanf( fp, "%d", &b ); if(val==EOF) break; |
|---|
| | 106 | val=fscanf( fp, "%d", &r2 ); if(val==EOF) break; |
|---|
| | 107 | val=fscanf( fp, "%d", &g2 ); if(val==EOF) break; |
|---|
| | 108 | val=fscanf( fp, "%d", &b2 ); if(val==EOF) break; |
|---|
| | 109 | //printf( "%d %d %d %d %d %d ",r,g,b,r2,g2,b2 ); |
|---|
| | 110 | // Load up the FIFO in the most natural way... |
|---|
| | 111 | virtual_fifo[i++]=g; |
|---|
| | 112 | virtual_fifo[i++]=r; |
|---|
| | 113 | virtual_fifo[i++]=g2; |
|---|
| | 114 | virtual_fifo[i++]=b; |
|---|
| | 115 | } while(val!=EOF); |
|---|
| | 116 | |
|---|
| | 117 | printf( "FIFO Loaded %d bytes\n", i); |
|---|
| | 118 | virtual_fifo_index=0; |
|---|
| | 119 | cc3_g_current_frame.y_loc = 0; |
|---|
| | 120 | |
|---|
| | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | void _cc3_fifo_read_inc (void) |
|---|
| | 124 | { |
|---|
| | 125 | //printf( "cc3_fifo_read_inc\n" ); |
|---|
| | 126 | virtual_fifo_index++; |
|---|
| | 127 | } |
|---|
| | 128 | |
|---|
| | 129 | void _cc3_pixbuf_skip_pixels (uint32_t size) |
|---|
| | 130 | { |
|---|
| | 131 | uint32_t i; |
|---|
| | 132 | |
|---|
| | 133 | for (i = 0; i < size; i++) { |
|---|
| | 134 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 135 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 136 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 137 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 138 | } |
|---|
| | 139 | } |
|---|
| | 140 | |
|---|
| | 141 | |
|---|
| | 142 | void _cc3_seek_top () |
|---|
| | 143 | { |
|---|
| | 144 | if (cc3_g_current_frame.y_loc < cc3_g_current_frame.y0) { |
|---|
| | 145 | _cc3_pixbuf_skip_pixels (cc3_g_current_frame.raw_width / 2 |
|---|
| | 146 | * cc3_g_current_frame.y0); |
|---|
| | 147 | |
|---|
| | 148 | cc3_g_current_frame.y_loc = cc3_g_current_frame.y0; |
|---|
| | 149 | } |
|---|
| | 150 | } |
|---|
| | 151 | |
|---|
| | 152 | |
|---|
| | 153 | void _cc3_seek_left () |
|---|
| | 154 | { |
|---|
| | 155 | _cc3_pixbuf_skip_pixels (cc3_g_current_frame.x0 / 2); |
|---|
| | 156 | } |
|---|
| | 157 | |
|---|
| | 158 | uint8_t _cc3_pixbuf_read_subpixel (void) |
|---|
| | 159 | { |
|---|
| | 160 | //uint8_t result = REG (GPIO_IOPIN) >> 24; |
|---|
| | 161 | uint8_t result; |
|---|
| | 162 | result=virtual_fifo[virtual_fifo_index]; |
|---|
| | 163 | _cc3_fifo_read_inc (); |
|---|
| | 164 | return result; |
|---|
| | 165 | } |
|---|
| | 166 | |
|---|
| | 167 | void _cc3_pixbuf_skip_subpixel (void) |
|---|
| | 168 | { |
|---|
| | 169 | _cc3_fifo_read_inc (); |
|---|
| | 170 | } |
|---|
| | 171 | |
|---|
| | 172 | void _cc3_pixbuf_read_pixel (uint8_t * pixel, |
|---|
| | 173 | uint8_t * saved, |
|---|
| | 174 | uint8_t off0, uint8_t off1, uint8_t off2) |
|---|
| | 175 | { |
|---|
| | 176 | if (cc3_g_current_frame.x_step == 1) { |
|---|
| | 177 | if (_cc3_second_green_valid) { |
|---|
| | 178 | // use the second green |
|---|
| | 179 | _cc3_second_green_valid = false; |
|---|
| | 180 | *(pixel + off0) = *(saved + off0); |
|---|
| | 181 | *(pixel + off1) = _cc3_second_green; |
|---|
| | 182 | *(pixel + off2) = *(saved + off2); |
|---|
| | 183 | |
|---|
| | 184 | return; |
|---|
| | 185 | } |
|---|
| | 186 | |
|---|
| | 187 | // otherwise, load a new thing |
|---|
| | 188 | *(pixel + off1) = _cc3_pixbuf_read_subpixel (); // G |
|---|
| | 189 | *(pixel + off0) = _cc3_pixbuf_read_subpixel (); // R |
|---|
| | 190 | _cc3_second_green = _cc3_pixbuf_read_subpixel (); // G |
|---|
| | 191 | *(pixel + off2) = _cc3_pixbuf_read_subpixel (); // B |
|---|
| | 192 | |
|---|
| | 193 | _cc3_second_green_valid = true; |
|---|
| | 194 | } else { |
|---|
| | 195 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 196 | *(pixel + off0) = _cc3_pixbuf_read_subpixel (); |
|---|
| | 197 | *(pixel + off1) = _cc3_pixbuf_read_subpixel (); |
|---|
| | 198 | *(pixel + off2) = _cc3_pixbuf_read_subpixel (); |
|---|
| | 199 | } |
|---|
| | 200 | } |
|---|
| | 201 | |
|---|
| | 202 | /** |
|---|
| | 203 | * cc3_pixbuf_rewind(): |
|---|
| | 204 | * Rewinds the fifo. |
|---|
| | 205 | * Calling this and then changing parameters such as the |
|---|
| | 206 | * region of interest, channel of interest, virtual frame, and |
|---|
| | 207 | * subsampling will allow rapid reprocessing of a new frame. |
|---|
| | 208 | */ |
|---|
| | 209 | void cc3_pixbuf_rewind () |
|---|
| | 210 | { |
|---|
| | 211 | printf( "Fifo rewind!\n" ); |
|---|
| | 212 | virtual_fifo_index=0; |
|---|
| | 213 | _cc3_second_green_valid = false; |
|---|
| | 214 | cc3_g_current_frame.y_loc = 0; |
|---|
| | 215 | } |
|---|
| | 216 | |
|---|
| | 217 | |
|---|
| | 218 | void cc3_clr_led (uint8_t select) |
|---|
| | 219 | { |
|---|
| | 220 | switch (select) { |
|---|
| | 221 | case 0: |
|---|
| | 222 | printf( "led 0 off\n" ); |
|---|
| | 223 | break; |
|---|
| | 224 | case 1: |
|---|
| | 225 | printf( "led 1 off\n" ); |
|---|
| | 226 | break; |
|---|
| | 227 | case 2: |
|---|
| | 228 | printf( "led 2 off\n" ); |
|---|
| | 229 | break; |
|---|
| | 230 | } |
|---|
| | 231 | |
|---|
| | 232 | } |
|---|
| | 233 | |
|---|
| | 234 | |
|---|
| | 235 | void cc3_set_led (uint8_t select) |
|---|
| | 236 | { |
|---|
| | 237 | |
|---|
| | 238 | switch (select) { |
|---|
| | 239 | case 0: |
|---|
| | 240 | printf( "led 0 on\n" ); |
|---|
| | 241 | break; |
|---|
| | 242 | case 1: |
|---|
| | 243 | printf( "led 1 on\n" ); |
|---|
| | 244 | break; |
|---|
| | 245 | case 2: |
|---|
| | 246 | printf( "led 2 on\n" ); |
|---|
| | 247 | break; |
|---|
| | 248 | } |
|---|
| | 249 | } |
|---|
| | 250 | |
|---|
| | 251 | |
|---|
| | 252 | uint8_t *cc3_malloc_rows (uint32_t rows) |
|---|
| | 253 | { |
|---|
| | 254 | int channels = cc3_g_current_frame.channels; |
|---|
| | 255 | int width = cc3_g_current_frame.width; |
|---|
| | 256 | |
|---|
| | 257 | return (uint8_t *) malloc (width * channels * rows); |
|---|
| | 258 | } |
|---|
| | 259 | |
|---|
| | 260 | |
|---|
| | 261 | /** |
|---|
| | 262 | * cc3_pixbuf_read_rows(): |
|---|
| | 263 | * Using the cc3_frame_t reads rows taking into account the virtual window and subsampling. |
|---|
| | 264 | * This function copies a specified number of rows from the camera FIFO into a block |
|---|
| | 265 | * of cc3_pixel_t memory. |
|---|
| | 266 | * This should be the lowest level call that the user directly interacts with. |
|---|
| | 267 | * Returns number of rows read. (May be zero if error.) |
|---|
| | 268 | */ |
|---|
| | 269 | int cc3_pixbuf_read_rows (void * mem, uint32_t rows) |
|---|
| | 270 | { |
|---|
| | 271 | |
|---|
| | 272 | int16_t j; |
|---|
| | 273 | uint16_t r; |
|---|
| | 274 | |
|---|
| | 275 | uint8_t off0, off1, off2; |
|---|
| | 276 | |
|---|
| | 277 | int width = cc3_g_current_frame.width; |
|---|
| | 278 | |
|---|
| | 279 | unsigned int row_limit = (cc3_g_current_frame.y1 - cc3_g_current_frame.y_loc) |
|---|
| | 280 | / cc3_g_current_frame.y_step; |
|---|
| | 281 | |
|---|
| | 282 | if (row_limit < rows) { |
|---|
| | 283 | rows = row_limit; |
|---|
| | 284 | } |
|---|
| | 285 | |
|---|
| | 286 | if (_cc3_g_current_camera_state.colorspace == CC3_RGB) { |
|---|
| | 287 | off0 = 0; |
|---|
| | 288 | off1 = 1; |
|---|
| | 289 | off2 = 2; |
|---|
| | 290 | } |
|---|
| | 291 | else if (_cc3_g_current_camera_state.colorspace == CC3_YCRCB) { |
|---|
| | 292 | off0 = 1; |
|---|
| | 293 | off1 = 0; |
|---|
| | 294 | off2 = 2; |
|---|
| | 295 | } |
|---|
| | 296 | else { |
|---|
| | 297 | off0 = 0; |
|---|
| | 298 | off1 = 1; |
|---|
| | 299 | off2 = 2; |
|---|
| | 300 | } |
|---|
| | 301 | |
|---|
| | 302 | // First read into frame |
|---|
| | 303 | _cc3_seek_top (); |
|---|
| | 304 | |
|---|
| | 305 | for (r = 0; r < rows; r++) { |
|---|
| | 306 | int x = cc3_g_current_frame.x0; |
|---|
| | 307 | |
|---|
| | 308 | // First read into line |
|---|
| | 309 | _cc3_seek_left (); |
|---|
| | 310 | |
|---|
| | 311 | switch (cc3_g_current_frame.coi) { |
|---|
| | 312 | case CC3_ALL: |
|---|
| | 313 | _cc3_second_green_valid = false; |
|---|
| | 314 | for (j = 0; j < width; j++) { |
|---|
| | 315 | uint8_t *p = ((uint8_t *) mem) + |
|---|
| | 316 | (r * width + j * 3); |
|---|
| | 317 | _cc3_pixbuf_read_pixel (p, p - 3, off0, off1, off2); |
|---|
| | 318 | |
|---|
| | 319 | // advance by x_step |
|---|
| | 320 | x += cc3_g_current_frame.x_step; |
|---|
| | 321 | _cc3_pixbuf_skip_pixels ((cc3_g_current_frame.x_step - 1) / 2); |
|---|
| | 322 | } |
|---|
| | 323 | |
|---|
| | 324 | break; |
|---|
| | 325 | |
|---|
| | 326 | case CC3_RED: |
|---|
| | 327 | for (j = 0; j < width; j++) { |
|---|
| | 328 | uint8_t *p = ((uint8_t *) mem) + (r * width + j); |
|---|
| | 329 | |
|---|
| | 330 | if ((j & 0x1) == 0 || cc3_g_current_frame.x_step > 1) { |
|---|
| | 331 | // read |
|---|
| | 332 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 333 | *p = _cc3_pixbuf_read_subpixel (); |
|---|
| | 334 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 335 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 336 | } else { |
|---|
| | 337 | *p = *(p - 1); |
|---|
| | 338 | } |
|---|
| | 339 | |
|---|
| | 340 | x += cc3_g_current_frame.x_step; |
|---|
| | 341 | _cc3_pixbuf_skip_pixels ((cc3_g_current_frame.x_step - 1) / 2); |
|---|
| | 342 | } |
|---|
| | 343 | break; |
|---|
| | 344 | |
|---|
| | 345 | case CC3_GREEN: |
|---|
| | 346 | for (j = 0; j < width; j++) { |
|---|
| | 347 | uint8_t *p = ((uint8_t *) mem) + (r * width + j); |
|---|
| | 348 | |
|---|
| | 349 | if ((j & 0x1) == 0 || cc3_g_current_frame.x_step > 1) { |
|---|
| | 350 | // read |
|---|
| | 351 | *p = _cc3_pixbuf_read_subpixel (); |
|---|
| | 352 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 353 | _cc3_second_green = _cc3_pixbuf_read_subpixel (); |
|---|
| | 354 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 355 | } else { |
|---|
| | 356 | *p = _cc3_second_green; |
|---|
| | 357 | } |
|---|
| | 358 | |
|---|
| | 359 | x += cc3_g_current_frame.x_step; |
|---|
| | 360 | _cc3_pixbuf_skip_pixels ((cc3_g_current_frame.x_step - 1) / 2); |
|---|
| | 361 | } |
|---|
| | 362 | break; |
|---|
| | 363 | |
|---|
| | 364 | case CC3_BLUE: |
|---|
| | 365 | for (j = 0; j < width; j++) { |
|---|
| | 366 | uint8_t *p = ((uint8_t *) mem) + (r * width + j); |
|---|
| | 367 | |
|---|
| | 368 | if ((j & 0x1) == 0 || cc3_g_current_frame.x_step > 1) { |
|---|
| | 369 | // read |
|---|
| | 370 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 371 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 372 | _cc3_pixbuf_skip_subpixel (); |
|---|
| | 373 | *p = _cc3_pixbuf_read_subpixel (); |
|---|
| | 374 | } else { |
|---|
| | 375 | *p = *(p - 1); |
|---|
| | 376 | } |
|---|
| | 377 | |
|---|
| | 378 | x += cc3_g_current_frame.x_step; |
|---|
| | 379 | _cc3_pixbuf_skip_pixels ((cc3_g_current_frame.x_step - 1) / 2); |
|---|
| | 380 | } |
|---|
| | 381 | break; |
|---|
| | 382 | } |
|---|
| | 383 | _cc3_pixbuf_skip_pixels ((cc3_g_current_frame.raw_width - x) / 2); |
|---|
| | 384 | |
|---|
| | 385 | |
|---|
| | 386 | // advance by y_step |
|---|
| | 387 | _cc3_pixbuf_skip_pixels ((cc3_g_current_frame.y_step - 1) * cc3_g_current_frame.raw_width / 2); |
|---|
| | 388 | cc3_g_current_frame.y_loc += cc3_g_current_frame.y_step; |
|---|
| | 389 | } |
|---|
| | 390 | return rows; |
|---|
| | 391 | } |
|---|
| | 392 | |
|---|
| | 393 | /** |
|---|
| | 394 | * cc3_wait_ms(): |
|---|
| | 395 | * |
|---|
| | 396 | */ |
|---|
| | 397 | void cc3_wait_ms (uint32_t delay) |
|---|
| | 398 | { |
|---|
| | 399 | uint32_t start; |
|---|
| | 400 | //start = cc3_timer (); |
|---|
| | 401 | //while (cc3_timer () < (start + delay)); |
|---|
| | 402 | printf( "cc3_wait_ms not implemented!\n" ); |
|---|
| | 403 | } |
|---|
| | 404 | |
|---|
| | 405 | |
|---|
| | 406 | /** |
|---|
| | 407 | * cc3_timer(): |
|---|
| | 408 | * |
|---|
| | 409 | * This function returns the time since startup in ms as a uint32 |
|---|
| | 410 | */ |
|---|
| | 411 | uint32_t cc3_timer () |
|---|
| | 412 | { |
|---|
| | 413 | //return (REG (TIMER0_TC)); // REG in milliseconds |
|---|
| | 414 | printf( "cc3_timer not implemented!\n" ); |
|---|
| | 415 | return 0; |
|---|
| | 416 | } |
|---|
| | 417 | |
|---|
| | 418 | /** |
|---|
| | 419 | * cc3_pixbuf_set_roi(): |
|---|
| | 420 | * Sets the region of interest in cc3_frame_t for virtual windowing. |
|---|
| | 421 | * This function changes the way data is read from the FIFO. |
|---|
| | 422 | * Returns 1 upon success and 0 on an out of bounds failure. |
|---|
| | 423 | */ |
|---|
| | 424 | int cc3_pixbuf_set_roi (int16_t x0, int16_t y0, int16_t x1, int16_t y1) |
|---|
| | 425 | { |
|---|
| | 426 | int w = cc3_g_current_frame.raw_width; |
|---|
| | 427 | int h = cc3_g_current_frame.raw_height; |
|---|
| | 428 | |
|---|
| | 429 | // constrain |
|---|
| | 430 | if (x0 < 0) { |
|---|
| | 431 | x0 = 0; |
|---|
| | 432 | } |
|---|
| | 433 | if ((x0 & 0x1) == 1) { |
|---|
| | 434 | x0++; // x0 must be even! |
|---|
| | 435 | } |
|---|
| | 436 | if (y0 < 0) { |
|---|
| | 437 | y0 = 0; |
|---|
| | 438 | } |
|---|
| | 439 | if (x0 > w) { |
|---|
| | 440 | x0 = w; |
|---|
| | 441 | } |
|---|
| | 442 | if (y0 > h) { |
|---|
| | 443 | y0 = h; |
|---|
| | 444 | } |
|---|
| | 445 | |
|---|
| | 446 | if (x1 < 0) { |
|---|
| | 447 | x1 = 0; |
|---|
| | 448 | } |
|---|
| | 449 | if (y1 < 0) { |
|---|
| | 450 | y1 = 0; |
|---|
| | 451 | } |
|---|
| | 452 | if (x1 > w) { |
|---|
| | 453 | x1 = w; |
|---|
| | 454 | } |
|---|
| | 455 | if (y1 > h) { |
|---|
| | 456 | y1 = h; |
|---|
| | 457 | } |
|---|
| | 458 | |
|---|
| | 459 | // check bounds |
|---|
| | 460 | if (x0 >= x1 || y0 >= y1) { |
|---|
| | 461 | return 0; |
|---|
| | 462 | } |
|---|
| | 463 | |
|---|
| | 464 | // set if ok |
|---|
| | 465 | cc3_g_current_frame.x0 = x0; |
|---|
| | 466 | cc3_g_current_frame.y0 = y0; |
|---|
| | 467 | cc3_g_current_frame.x1 = x1; |
|---|
| | 468 | cc3_g_current_frame.y1 = y1; |
|---|
| | 469 | |
|---|
| | 470 | _cc3_update_frame_bounds (&cc3_g_current_frame); |
|---|
| | 471 | |
|---|
| | 472 | return 1; |
|---|
| | 473 | } |
|---|
| | 474 | |
|---|
| | 475 | /** |
|---|
| | 476 | * cc3_pixbuf_set_subsample(): |
|---|
| | 477 | * Sets the subsampling step and mode in cc3_frame_t. |
|---|
| | 478 | * This function changes the way data is read from the FIFO. |
|---|
| | 479 | */ |
|---|
| | 480 | int cc3_pixbuf_set_subsample (cc3_subsample_mode_t mode, uint8_t x_step, |
|---|
| | 481 | uint8_t y_step) |
|---|
| | 482 | { |
|---|
| | 483 | int result = 1; |
|---|
| | 484 | |
|---|
| | 485 | if (x_step == 0) { |
|---|
| | 486 | x_step = 1; |
|---|
| | 487 | result = 0; |
|---|
| | 488 | } |
|---|
| | 489 | if (y_step == 0) { |
|---|
| | 490 | y_step = 1; |
|---|
| | 491 | result = 0; |
|---|
| | 492 | } |
|---|
| | 493 | |
|---|
| | 494 | // only allow even subsampling (or 1) for x |
|---|
| | 495 | if (x_step != 1 && x_step % 2 != 0) { |
|---|
| | 496 | x_step++; |
|---|
| | 497 | result = 0; |
|---|
| | 498 | } |
|---|
| | 499 | |
|---|
| | 500 | cc3_g_current_frame.x_step = x_step; |
|---|
| | 501 | cc3_g_current_frame.y_step = y_step; |
|---|
| | 502 | //cc3_g_current_frame.x0 = 0; |
|---|
| | 503 | //cc3_g_current_frame.y0 = 0; |
|---|
| | 504 | //cc3_g_current_frame.x1 = cc3_g_current_frame.raw_width; |
|---|
| | 505 | //cc3_g_current_frame.y1 = cc3_g_current_frame.raw_height; |
|---|
| | 506 | cc3_g_current_frame.subsample_mode = mode; |
|---|
| | 507 | |
|---|
| | 508 | _cc3_update_frame_bounds (&cc3_g_current_frame); |
|---|
| | 509 | |
|---|
| | 510 | return result; |
|---|
| | 511 | } |
|---|
| | 512 | |
|---|
| | 513 | /** |
|---|
| | 514 | * cc3_pixbuf_set_coi(): |
|---|
| | 515 | * Sets the channel of interest 1 or all. |
|---|
| | 516 | * This function changes the way data is read from the FIFO. |
|---|
| | 517 | * Returns 1 upon success and 0 on failure. |
|---|
| | 518 | */ |
|---|
| | 519 | int cc3_pixbuf_set_coi (cc3_channel_t chan) |
|---|
| | 520 | { |
|---|
| | 521 | if (chan > 4) |
|---|
| | 522 | return 0; // Sanity check on bounds |
|---|
| | 523 | cc3_g_current_frame.coi = chan; |
|---|
| | 524 | |
|---|
| | 525 | cc3_g_current_frame.channels = (chan == CC3_ALL ? 3 : 1); |
|---|
| | 526 | |
|---|
| | 527 | return 1; |
|---|
| | 528 | } |
|---|
| | 529 | |
|---|
| | 530 | |
|---|
| | 531 | |
|---|
| | 532 | /** |
|---|
| | 533 | * cc3_camera_init(): |
|---|
| | 534 | * First Enable Camera & FIFO Power, next Reset Camera, then call cc3_set functions for default state |
|---|
| | 535 | * |
|---|
| | 536 | * Return: |
|---|
| | 537 | * 1 successfully got acks back |
|---|
| | 538 | * 0 failure (probably due to hardware?) |
|---|
| | 539 | */ |
|---|
| | 540 | int cc3_camera_init () |
|---|
| | 541 | { |
|---|
| | 542 | _cc3_camera_reset (); |
|---|
| | 543 | _cc3_fifo_reset (); |
|---|
| | 544 | |
|---|
| | 545 | _cc3_g_current_camera_state.camera_type = _CC3_OV6620; // XXX add autodetect code |
|---|
| | 546 | _cc3_g_current_camera_state.clock_divider = 0; |
|---|
| | 547 | _cc3_g_current_camera_state.brightness = -1; |
|---|
| | 548 | _cc3_g_current_camera_state.contrast = -1; |
|---|
| | 549 | _cc3_g_current_camera_state.auto_exposure = true; |
|---|
| | 550 | _cc3_g_current_camera_state.auto_white_balance = false; |
|---|
| | 551 | _cc3_g_current_camera_state.colorspace = CC3_RGB; |
|---|
| | 552 | _cc3_set_register_state (); |
|---|
| | 553 | |
|---|
| | 554 | cc3_frame_default (); |
|---|
| | 555 | printf( "cc3_camera_init()\n" ); |
|---|
| | 556 | return 1; |
|---|
| | 557 | } |
|---|
| | 558 | |
|---|
| | 559 | void cc3_frame_default () |
|---|
| | 560 | { |
|---|
| | 561 | cc3_g_current_frame.x_step = 1; |
|---|
| | 562 | cc3_g_current_frame.y_step = 1; |
|---|
| | 563 | cc3_g_current_frame.x0 = 0; |
|---|
| | 564 | cc3_g_current_frame.y0 = 0; |
|---|
| | 565 | cc3_g_current_frame.x1 = cc3_g_current_frame.raw_width; |
|---|
| | 566 | cc3_g_current_frame.y1 = cc3_g_current_frame.raw_height; |
|---|
| | 567 | cc3_g_current_frame.y_loc = 0; |
|---|
| | 568 | cc3_g_current_frame.subsample_mode = CC3_NEAREST; |
|---|
| | 569 | |
|---|
| | 570 | cc3_pixbuf_set_coi(CC3_ALL); |
|---|
| | 571 | |
|---|
| | 572 | _cc3_update_frame_bounds (&cc3_g_current_frame); |
|---|
| | 573 | } |
|---|
| | 574 | |
|---|
| | 575 | /** |
|---|
| | 576 | * cc3_camera_kill(): |
|---|
| | 577 | * Turn camera power off |
|---|
| | 578 | * Turn fifo power off (may "cause picture to evaporate") |
|---|
| | 579 | */ |
|---|
| | 580 | void cc3_camera_kill () |
|---|
| | 581 | { |
|---|
| | 582 | // XXX I need to be implemented |
|---|
| | 583 | |
|---|
| | 584 | } |
|---|
| | 585 | |
|---|
| | 586 | |
|---|
| | 587 | void |
|---|
| | 588 | cc3_system_setup (void) |
|---|
| | 589 | { |
|---|
| | 590 | printf( "cc3_system_setup()\n" ); |
|---|
| | 591 | } |
|---|
| | 592 | |
|---|
| | 593 | |
|---|
| | 594 | static void _cc3_set_cam_ddr_i2c_idle (void) |
|---|
| | 595 | { |
|---|
| | 596 | //REG (GPIO_IODIR) = _CC3_I2C_PORT_DDR_IDLE; |
|---|
| | 597 | //_cc3_delay_i2c (); |
|---|
| | 598 | } |
|---|
| | 599 | |
|---|
| | 600 | static void _cc3_set_cam_ddr_i2c_write (void) |
|---|
| | 601 | { |
|---|
| | 602 | //REG (GPIO_IODIR) = _CC3_I2C_PORT_DDR_WRITE; |
|---|
| | 603 | //_cc3_delay_i2c (); |
|---|
| | 604 | } |
|---|
| | 605 | |
|---|
| | 606 | |
|---|
| | 607 | static void _cc3_set_cam_ddr (volatile unsigned long val) |
|---|
| | 608 | { |
|---|
| | 609 | //DDR(I2C_PORT,val); |
|---|
| | 610 | //REG (GPIO_IODIR) = val; |
|---|
| | 611 | //_cc3_delay_i2c (); |
|---|
| | 612 | } |
|---|
| | 613 | |
|---|
| | 614 | |
|---|
| | 615 | |
|---|
| | 616 | static unsigned int _cc3_i2c_send (unsigned int num, unsigned int *buffer) |
|---|
| | 617 | { |
|---|
| | 618 | |
|---|
| | 619 | return 1; |
|---|
| | 620 | } |
|---|
| | 621 | |
|---|
| | 622 | /** |
|---|
| | 623 | * cc3_set_raw_register(): |
|---|
| | 624 | * This will take an address and a value from the OmniVision manual |
|---|
| | 625 | * and set it on the camera. This should be used for advanced low level |
|---|
| | 626 | * manipulation of the camera modes. Currently, this will not set the |
|---|
| | 627 | * corresponding cc3 internal data structure that keeps record of the camera |
|---|
| | 628 | * mode. Use with CAUTION. |
|---|
| | 629 | * |
|---|
| | 630 | * For basic manipulation of camera parameters see other cc3_set_xxxx functions. |
|---|
| | 631 | */ |
|---|
| | 632 | int cc3_set_raw_register (uint8_t address, uint8_t value) |
|---|
| | 633 | { |
|---|
| | 634 | unsigned int data[3]; |
|---|
| | 635 | int to; |
|---|
| | 636 | data[0] = _cc3_g_current_camera_state.camera_type; |
|---|
| | 637 | data[1] = address; |
|---|
| | 638 | data[2] = value; |
|---|
| | 639 | to = 0; |
|---|
| | 640 | while (_cc3_i2c_send (3, data)) { |
|---|
| | 641 | to++; |
|---|
| | 642 | if (to > 3) |
|---|
| | 643 | return 0; |
|---|
| | 644 | } |
|---|
| | 645 | _cc3_delay_us_4 (1); |
|---|
| | 646 | return 1; |
|---|
| | 647 | } |
|---|
| | 648 | |
|---|
| | 649 | |
|---|
| | 650 | /** |
|---|
| | 651 | * Sets the resolution, also updates cc3_g_current_frame width and height |
|---|
| | 652 | * Takes enum CC3_LOW_RES and CC3_HIGH_RES. |
|---|
| | 653 | * WARNING: Clears ROI, COI, sampling mode etc! |
|---|
| | 654 | */ |
|---|
| | 655 | int cc3_set_resolution (cc3_camera_resolution_t cam_res) |
|---|
| | 656 | { |
|---|
| | 657 | _cc3_g_current_camera_state.resolution = cam_res; |
|---|
| | 658 | _cc3_set_register_state (); // XXX Don't reset all of them, this is just quick and dirty... |
|---|
| | 659 | cc3_frame_default (); |
|---|
| | 660 | |
|---|
| | 661 | return 1; |
|---|
| | 662 | } |
|---|
| | 663 | |
|---|
| | 664 | void _cc3_update_frame_bounds (cc3_frame_t *f) |
|---|
| | 665 | { |
|---|
| | 666 | f->width = (f->x1 - f->x0) / f->x_step; |
|---|
| | 667 | f->height = (f->y1 - f->y0) / f->y_step; |
|---|
| | 668 | } |
|---|
| | 669 | |
|---|
| | 670 | /** |
|---|
| | 671 | * This sets the hardware colorspace that comes out of the camera. |
|---|
| | 672 | * You can choose between CC3_RGB or CC3_YCRCB. In RGB mode, then |
|---|
| | 673 | * address pixels with CC3_RED, CC3_GREEN, CC3_BLUE, and CC3_GREEN2 |
|---|
| | 674 | * in YCrCb mode, use CC3_CR, CC3_Y, CC3_CB, CC3_Y2 when indexing |
|---|
| | 675 | * the pixel array. |
|---|
| | 676 | */ |
|---|
| | 677 | int cc3_set_colorspace (cc3_colorspace_t colorspace) |
|---|
| | 678 | { |
|---|
| | 679 | _cc3_g_current_camera_state.colorspace = colorspace; |
|---|
| | 680 | _cc3_set_register_state (); |
|---|
| | 681 | return 1; |
|---|
| | 682 | } |
|---|
| | 683 | |
|---|
| | 684 | |
|---|
| | 685 | int cc3_set_framerate_divider (uint8_t rate_divider) |
|---|
| | 686 | { |
|---|
| | 687 | _cc3_g_current_camera_state.clock_divider = rate_divider; |
|---|
| | 688 | _cc3_set_register_state (); // XXX Don't reset all of them, this is just quick and dirty... |
|---|
| | 689 | return 1; |
|---|
| | 690 | } |
|---|
| | 691 | |
|---|
| | 692 | int cc3_set_auto_exposure (bool exp) |
|---|
| | 693 | { |
|---|
| | 694 | _cc3_g_current_camera_state.auto_exposure = exp; |
|---|
| | 695 | _cc3_set_register_state (); // XXX Don't reset all of them, this is just quick and dirty... |
|---|
| | 696 | return 1; |
|---|
| | 697 | } |
|---|
| | 698 | |
|---|
| | 699 | int cc3_set_auto_white_balance (bool awb) |
|---|
| | 700 | { |
|---|
| | 701 | _cc3_g_current_camera_state.auto_white_balance = awb; |
|---|
| | 702 | _cc3_set_register_state (); // XXX Don't reset all of them, this is just quick and dirty... |
|---|
| | 703 | return 1; |
|---|
| | 704 | } |
|---|
| | 705 | |
|---|
| | 706 | int cc3_set_brightness (uint8_t level) |
|---|
| | 707 | { |
|---|
| | 708 | _cc3_g_current_camera_state.brightness = level; |
|---|
| | 709 | _cc3_set_register_state (); // XXX Don't reset all of them, this is just quick and dirty... |
|---|
| | 710 | return 1; |
|---|
| | 711 | } |
|---|
| | 712 | |
|---|
| | 713 | int cc3_set_contrast (uint8_t level) |
|---|
| | 714 | { |
|---|
| | 715 | _cc3_g_current_camera_state.contrast = level; |
|---|
| | 716 | _cc3_set_register_state (); // XXX Don't reset all of them, this is just quick and dirty... |
|---|
| | 717 | return 1; |
|---|
| | 718 | } |
|---|
| | 719 | |
|---|
| | 720 | |
|---|
| | 721 | bool cc3_read_button (void) |
|---|
| | 722 | { |
|---|
| | 723 | return 1; |
|---|
| | 724 | } |
|---|