📄 cc3.c
字号:
/* * Copyright 2006-2007 Anthony Rowe and Adam Goode * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//****************************************************************************** * * Initial CMUcam3 (cc3) data types and functions. * *****************************************************************************/#include <stdbool.h>#include <stdlib.h>#include "cc3.h"#include "cc3_pin_defines.h"#include "cc3_hal.h"#include "serial.h"#include "devices.h"#include "interrupt.h"// Globals used by CMUCam functionscc3_pixel_t cc3_g_current_pixel; // global that gets updated with pixbuf callscc3_frame_t cc3_g_pixbuf_frame; // global that keeps clip, stridestatic _cc3_camera_state_t _cc3_g_current_camera_state;static inline void _cc3_seek_left (void);static inline void _cc3_seek_top (void);static inline void _cc3_pixbuf_skip_pixels (uint32_t size);static inline uint8_t _cc3_pixbuf_read_subpixel (void);static inline void _cc3_pixbuf_read_pixel (uint8_t * pixel, uint8_t * saved, uint8_t off0, uint8_t off1, uint8_t off2);static inline void _cc3_pixbuf_skip_subpixel (void);// Move to the next byte in the FIFOstatic inline void _cc3_fifo_read_inc (void);static uint8_t _cc3_second_green;static bool _cc3_second_green_valid;static void _cc3_update_frame_bounds (cc3_frame_t *);static bool _cc3_set_register_state (void);void cc3_pixbuf_load (){ // uint32_t start_time; unsigned int i; if (REG (GPIO_IOPIN) & _CC3_CAM_POWER_DOWN) { return; } //REG(GPIO_IOCLR)=CAM_IE; //while(frame_done!=1); // cc3_pixbuf_rewind(); _cc3_pixbuf_write_rewind (); while (!(REG (GPIO_IOPIN) & _CC3_CAM_VSYNC)); //while(CAM_VSYNC); while (REG (GPIO_IOPIN) & _CC3_CAM_VSYNC); //while(!CAM_VSYNC); REG (GPIO_IOSET) = _CC3_BUF_WEE; // wait for vsync to finish while (!(REG (GPIO_IOPIN) & _CC3_CAM_VSYNC)); //while(CAM_VSYNC); enable_ext_interrupt (); // Delay to wait for the image buffer to fill up before you start reading it for (i = 0; i < 3; i++) { while (!(REG (GPIO_IOPIN) & _CC3_CAM_HREF)); while (REG (GPIO_IOPIN) & _CC3_CAM_HREF); } cc3_pixbuf_rewind(); cc3_g_pixbuf_frame.y_loc = 0; //while (REG (GPIO_IOPIN) & _CC3_CAM_VSYNC); //REG (GPIO_IOCLR) = _CC3_BUF_WEE;// delay();// REG(GPIO_IOCLR)=_CC3_BUF_WEE; //BUF_WEE=0return 1;}void _cc3_fifo_read_inc (void){ REG (GPIO_IOSET) = _CC3_BUF_RCK; REG (GPIO_IOCLR) = _CC3_BUF_RCK;}void _cc3_pixbuf_skip_pixels (uint32_t size){ uint32_t i; for (i = 0; i < size; i++) { _cc3_pixbuf_skip_subpixel (); _cc3_pixbuf_skip_subpixel (); _cc3_pixbuf_skip_subpixel (); _cc3_pixbuf_skip_subpixel (); }}void _cc3_seek_top (){ if (cc3_g_pixbuf_frame.y_loc < cc3_g_pixbuf_frame.y0) { _cc3_pixbuf_skip_pixels (cc3_g_pixbuf_frame.raw_width / 2 * cc3_g_pixbuf_frame.y0); cc3_g_pixbuf_frame.y_loc = cc3_g_pixbuf_frame.y0; }}void _cc3_seek_left (){ _cc3_pixbuf_skip_pixels (cc3_g_pixbuf_frame.x0 / 2);}uint8_t _cc3_pixbuf_read_subpixel (void){ uint8_t result = REG (GPIO_IOPIN) >> 24; _cc3_fifo_read_inc (); return result;}void _cc3_pixbuf_skip_subpixel (void){ _cc3_fifo_read_inc ();}void _cc3_pixbuf_read_pixel (uint8_t * pixel, uint8_t * saved, uint8_t off0, uint8_t off1, uint8_t off2){ if (cc3_g_pixbuf_frame.x_step == 1) { if (_cc3_second_green_valid) { // use the second green _cc3_second_green_valid = false; *(pixel + off0) = *(saved + off0); *(pixel + off1) = _cc3_second_green; *(pixel + off2) = *(saved + off2); return; } // otherwise, load a new thing *(pixel + off1) = _cc3_pixbuf_read_subpixel (); // G *(pixel + off0) = _cc3_pixbuf_read_subpixel (); // R _cc3_second_green = _cc3_pixbuf_read_subpixel (); // G *(pixel + off2) = _cc3_pixbuf_read_subpixel (); // B _cc3_second_green_valid = true; } else { _cc3_pixbuf_skip_subpixel (); *(pixel + off0) = _cc3_pixbuf_read_subpixel (); *(pixel + off1) = _cc3_pixbuf_read_subpixel (); *(pixel + off2) = _cc3_pixbuf_read_subpixel (); }}/** * cc3_pixbuf_rewind(): * Rewinds the fifo. * Calling this and then changing parameters such as the * region of interest, channel of interest, virtual frame, and * subsampling will allow rapid reprocessing of a new frame. */void cc3_pixbuf_rewind (){ REG (GPIO_IOCLR) = _CC3_BUF_RRST; REG (GPIO_IOCLR) = _CC3_BUF_RCK; REG (GPIO_IOSET) = _CC3_BUF_RCK; REG (GPIO_IOCLR) = _CC3_BUF_RCK; REG (GPIO_IOSET) = _CC3_BUF_RRST; // skip first line because it is blue _cc3_pixbuf_skip_pixels (cc3_g_pixbuf_frame.raw_width / 2); //_cc3_pixbuf_skip_pixels (cc3_g_pixbuf_frame.raw_width / 2); _cc3_second_green_valid = false; cc3_g_pixbuf_frame.y_loc = 0;}void cc3_led_set_state (uint8_t select, bool state){ if (state) { switch (select) { case 0: REG (GPIO_IOSET) = _CC3_LED_0; break; case 1: REG (GPIO_IOSET) = _CC3_LED_1; break; case 2: REG (GPIO_IOSET) = _CC3_LED_2; break; } } else { switch (select) { case 0: REG (GPIO_IOCLR) = _CC3_LED_0; break; case 1: REG (GPIO_IOCLR) = _CC3_LED_1; break; case 2: REG (GPIO_IOCLR) = _CC3_LED_2; break; } }}uint8_t *cc3_malloc_rows (uint32_t rows){ int channels = cc3_g_pixbuf_frame.channels; int width = cc3_g_pixbuf_frame.width; return (uint8_t *) malloc (width * channels * rows);}/** * cc3_pixbuf_read_rows(): * Using the cc3_frame_t reads rows taking into account the virtual window and subsampling. * This function copies a specified number of rows from the camera FIFO into a block * of cc3_pixel_t memory. * This should be the lowest level call that the user directly interacts with. * Returns number of rows read. (May be zero if error.) */int cc3_pixbuf_read_rows (void * mem, uint32_t rows){ int16_t j; uint16_t r; uint8_t off0, off1, off2; int width = cc3_g_pixbuf_frame.width; unsigned int row_limit = (cc3_g_pixbuf_frame.y1 - cc3_g_pixbuf_frame.y_loc) / cc3_g_pixbuf_frame.y_step; if (row_limit < rows) { rows = row_limit; } if (_cc3_g_current_camera_state.colorspace == CC3_COLORSPACE_RGB) { off0 = 0; off1 = 1; off2 = 2; } else if (_cc3_g_current_camera_state.colorspace == CC3_COLORSPACE_YCRCB) { off0 = 1; off1 = 0; off2 = 2; } else { off0 = 0; off1 = 1; off2 = 2; } // First read into frame _cc3_seek_top (); for (r = 0; r < rows; r++) { int x = cc3_g_pixbuf_frame.x0; // First read into line _cc3_seek_left (); switch (cc3_g_pixbuf_frame.coi) { case CC3_CHANNEL_ALL: _cc3_second_green_valid = false; for (j = 0; j < width; j++) { uint8_t *p = ((uint8_t *) mem) + (r * width + j * 3); _cc3_pixbuf_read_pixel (p, p - 3, off0, off1, off2); // advance by x_step x += cc3_g_pixbuf_frame.x_step; _cc3_pixbuf_skip_pixels ((cc3_g_pixbuf_frame.x_step - 1) / 2); } break; case CC3_CHANNEL_RED: for (j = 0; j < width; j++) { uint8_t *p = ((uint8_t *) mem) + (r * width + j); if ((j & 0x1) == 0 || cc3_g_pixbuf_frame.x_step > 1) { // read _cc3_pixbuf_skip_subpixel (); *p = _cc3_pixbuf_read_subpixel (); _cc3_pixbuf_skip_subpixel (); _cc3_pixbuf_skip_subpixel (); } else { *p = *(p - 1); } x += cc3_g_pixbuf_frame.x_step; _cc3_pixbuf_skip_pixels ((cc3_g_pixbuf_frame.x_step - 1) / 2); } break; case CC3_CHANNEL_GREEN: for (j = 0; j < width; j++) { uint8_t *p = ((uint8_t *) mem) + (r * width + j); if ((j & 0x1) == 0 || cc3_g_pixbuf_frame.x_step > 1) { // read *p = _cc3_pixbuf_read_subpixel (); _cc3_pixbuf_skip_subpixel (); _cc3_second_green = _cc3_pixbuf_read_subpixel (); _cc3_pixbuf_skip_subpixel (); } else { *p = _cc3_second_green; } x += cc3_g_pixbuf_frame.x_step; _cc3_pixbuf_skip_pixels ((cc3_g_pixbuf_frame.x_step - 1) / 2); } break; case CC3_CHANNEL_BLUE: for (j = 0; j < width; j++) { uint8_t *p = ((uint8_t *) mem) + (r * width + j); if ((j & 0x1) == 0 || cc3_g_pixbuf_frame.x_step > 1) { // read _cc3_pixbuf_skip_subpixel (); _cc3_pixbuf_skip_subpixel (); _cc3_pixbuf_skip_subpixel (); *p = _cc3_pixbuf_read_subpixel (); } else { *p = *(p - 1); } x += cc3_g_pixbuf_frame.x_step; _cc3_pixbuf_skip_pixels ((cc3_g_pixbuf_frame.x_step - 1) / 2); } break; } _cc3_pixbuf_skip_pixels ((cc3_g_pixbuf_frame.raw_width - x) / 2); // advance by y_step _cc3_pixbuf_skip_pixels ((cc3_g_pixbuf_frame.y_step - 1) * cc3_g_pixbuf_frame.raw_width / 2); cc3_g_pixbuf_frame.y_loc += cc3_g_pixbuf_frame.y_step; } return rows;}/** * cc3_wait_ms(): * */void cc3_timer_wait_ms (uint32_t delay){ uint32_t start; start = cc3_timer_get_current_ms (); while (cc3_timer_get_current_ms () < (start + delay));}uint32_t cc3_timer_get_current_ms (){ return (REG (TIMER0_TC)); // REG in milliseconds}/** * cc3_pixbuf_frame_set_roi(): * Sets the region of interest in cc3_frame_t for virtual windowing. * This function changes the way data is read from the FIFO. */bool cc3_pixbuf_frame_set_roi (int16_t x0, int16_t y0, int16_t x1, int16_t y1){ int w = cc3_g_pixbuf_frame.raw_width; int h = cc3_g_pixbuf_frame.raw_height; // constrain if (x0 < 0) { x0 = 0; } if ((x0 & 0x1) == 1) { x0++; // x0 must be even! } if (y0 < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -