MARMEX-VB : "Mary Camera module" library
Dependents: MARMEX_VB_test MARMEX_VB_Hello
MARMEX_VB.cpp
00001 /** MARMEX_VB Camera control library 00002 * 00003 * @class MARMEX_VB 00004 * @version 0.5 00005 * @date 20-Jun-2014 00006 * 00007 * Released under the Apache License, Version 2.0 : http://mbed.org/handbook/Apache-Licence 00008 * 00009 * MARMEX_VB Camera control library for mbed 00010 */ 00011 00012 #include "mbed.h" 00013 #include "MARMEX_VB.h" 00014 00015 #define SPI_FREQUENCY (12 * 1000 * 1000) 00016 00017 /* 00018 * Followings are 3 types of line read routines. 00019 * Choose one of next 3 methods for reading camera data trough SPI interface 00020 * 00021 * Type0: "LINE_READ_OPT" is define as "NO_OPTIMIZATION" 00022 * Most basic loop to explain how the MCU reading the line data. 00023 * But this routine is slow, because the loop does 1 byte read 00024 * with ChipSelect signal assertion/deassertion by DigitalOut 00025 * 00026 * Type1: "LINE_READ_OPT" is define as "LOOP_UNROLL" 00027 * Faster. And keeping compatibility on mbed-SDK. 00028 * Data reading speed improvement has been done in two ways. 00029 * * The ChipSelect signal is kept asserted for whole line data transfer. 00030 * because the MARMEX-VB module does not need deassertion at each end of byte transfer. 00031 * * Loop unrolled. minimized loop overhead 00032 * 00033 * Type2: "LINE_READ_OPT" is define as "USING_SSP_FIFO" 00034 * Fastest but no compatibility with mbed-SDK. 00035 * The optimization has been done to use FIFO of SSP block. 00036 * This code makes data transfer efficiency maximum. 00037 * However, since this optimization is done in very low level (by register accessing), 00038 * it works on some MCU's only (test has been done on LPC1768, LPC11U24 and LPC11U35). 00039 * 00040 * And user need to care about which SSP block is used. For instance, if the SPI pins 00041 * of p5, p6 and p7 are used, those are connected to SSP1 in LPC1768. In case of 00042 * LPC11U24 and LPC11U35, those pins are routed to SSP0. 00043 * These settings should be done manually 00044 */ 00045 00046 //#define LINE_READ_OPT NO_OPTIMIZATION 00047 #define LINE_READ_OPT LOOP_UNROLL 00048 //#define LINE_READ_OPT USING_SSP_FIFO 00049 00050 00051 /* Setting for "LINE_READ_OPT == USING_SSP_FIFO" 00052 * Choose one line from next 3 lines when the FIFO option is taken 00053 */ 00054 00055 #define SSP_AUTO_SELECTION // for demo setup on "MAPLE mini type-B (MARM03-BASE)" baseboard (slot2) with a MARMEX_OB module (on slot1) 00056 //#define SSP_USE_SSP0 00057 //#define SSP_USE_SSP1 00058 00059 00060 00061 00062 MARMEX_VB::MARMEX_VB( 00063 PinName SPI_mosi, 00064 PinName SPI_miso, 00065 PinName SPI_sck, 00066 PinName SPI_cs, 00067 PinName cam_reset, 00068 PinName I2C_sda, 00069 PinName I2C_scl 00070 ) : 00071 _spi( SPI_mosi, SPI_miso, SPI_sck ), 00072 _cs( SPI_cs ), 00073 _reset( cam_reset ), 00074 _i2c( I2C_sda, I2C_scl ) 00075 { 00076 #ifdef IGNORE_INITIALIZATION_ERROR 00077 init(); 00078 #else 00079 if ( 0 != init() ) 00080 error( "camera initialization failed." ); 00081 #endif 00082 } 00083 00084 00085 #define CAM_I2C_ADDR 0x42 00086 00087 #define COMMAND_WRITE 0x00 00088 #define COMMAND_READ 0x80 00089 #define COMMAND_ADDR_INCREMENT 0x20 00090 00091 #define MEMORY_ADDR_LOW__REGISTER 0x0 00092 #define MEMORY_ADDR_MID__REGISTER 0x1 00093 #define MEMORY_ADDR_HIGH_REGISTER 0x2 00094 #define CAMERA_DATA_REGISTER 0x8 00095 #define CONTROL_DATA_REGISTER 0x3 00096 #define STATUS_REGISTER 0x4 00097 00098 #define CONTROL__PAUSE_BUFFER_UPDATE 0x01 00099 #define CONTROL__RESUME_BUFFER_UPDATE 0x00 00100 00101 00102 int MARMEX_VB::init( CameraResolution res ) 00103 { 00104 #define PARAM_NUM 99 00105 #define RES_CHANGE_PARAM_NUM 12 00106 #define RESET_PULSE_WIDTH 100 // mili-seconds 00107 #define RESET_RECOVERY_TIME 100 // mili-seconds 00108 #define COMMAND_INTERVAL 20 // mili-seconds 00109 00110 char camera_register_setting[ PARAM_NUM ][ 2 ] = { 00111 { 0x01, 0x40 }, { 0x02, 0x60 }, { 0x03, 0x02 }, { 0x0C, 0x0C }, 00112 { 0x0E, 0x61 }, { 0x0F, 0x4B }, { 0x11, 0x80 }, { 0x12, 0x04 }, 00113 { 0x15, 0x00 }, { 0x16, 0x02 }, { 0x17, 0x39 }, { 0x18, 0x03 }, 00114 { 0x19, 0x03 }, { 0x1A, 0x7B }, { 0x1E, 0x37 }, { 0x21, 0x02 }, 00115 { 0x22, 0x91 }, { 0x29, 0x07 }, { 0x32, 0x80 }, { 0x33, 0x0B }, 00116 { 0x34, 0x11 }, { 0x35, 0x0B }, { 0x37, 0x1D }, { 0x38, 0x71 }, 00117 { 0x39, 0x2A }, { 0x3B, 0x12 }, { 0x3C, 0x78 }, { 0x3D, 0xC3 }, 00118 { 0x3E, 0x11 }, { 0x3F, 0x00 }, { 0x40, 0xD0 }, { 0x41, 0x08 }, 00119 { 0x41, 0x38 }, { 0x43, 0x0A }, { 0x44, 0xF0 }, { 0x45, 0x34 }, 00120 { 0x46, 0x58 }, { 0x47, 0x28 }, { 0x48, 0x3A }, { 0x4B, 0x09 }, 00121 { 0x4C, 0x00 }, { 0x4D, 0x40 }, { 0x4E, 0x20 }, { 0x4F, 0x80 }, 00122 { 0x50, 0x80 }, { 0x51, 0x00 }, { 0x52, 0x22 }, { 0x53, 0x5E }, 00123 { 0x54, 0x80 }, { 0x56, 0x40 }, { 0x58, 0x9E }, { 0x59, 0x88 }, 00124 { 0x5A, 0x88 }, { 0x5B, 0x44 }, { 0x5C, 0x67 }, { 0x5D, 0x49 }, 00125 { 0x5E, 0x0E }, { 0x69, 0x00 }, { 0x6A, 0x40 }, { 0x6B, 0x0A }, 00126 { 0x6C, 0x0A }, { 0x6D, 0x55 }, { 0x6E, 0x11 }, { 0x6F, 0x9F }, 00127 { 0x70, 0x3A }, { 0x71, 0x35 }, { 0x72, 0x11 }, { 0x73, 0xF1 }, 00128 { 0x74, 0x10 }, { 0x75, 0x05 }, { 0x76, 0xE1 }, { 0x77, 0x01 }, 00129 { 0x78, 0x04 }, { 0x79, 0x01 }, { 0x8D, 0x4F }, { 0x8E, 0x00 }, 00130 { 0x8F, 0x00 }, { 0x90, 0x00 }, { 0x91, 0x00 }, { 0x96, 0x00 }, 00131 { 0x96, 0x00 }, { 0x97, 0x30 }, { 0x98, 0x20 }, { 0x99, 0x30 }, 00132 { 0x9A, 0x00 }, { 0x9A, 0x84 }, { 0x9B, 0x29 }, { 0x9C, 0x03 }, 00133 { 0x9D, 0x4C }, { 0x9E, 0x3F }, { 0xA2, 0x52 }, { 0xA4, 0x88 }, 00134 { 0xB0, 0x84 }, { 0xB1, 0x0C }, { 0xB2, 0x0E }, { 0xB3, 0x82 }, 00135 { 0xB8, 0x0A }, { 0xC8, 0xF0 }, { 0xC9, 0x60 }, 00136 }; 00137 const char res_change_param[ 5 ][ RES_CHANGE_PARAM_NUM ] = { 00138 { 0x17, 0x18, 0x32, 0x19, 0x1a, 0x03, 0x0c, 0x3e, 0x71, 0x72, 0x73, 0xa2 }, // register addr 00139 { 0x39, 0x03, 0x80, 0x03, 0x7b, 0x02, 0x0c, 0x11, 0x35, 0x11, 0xf1, 0x52 }, // QSIF 00140 { 0x13, 0x01, 0xb6, 0x02, 0x7a, 0x0a, 0x00, 0x00, 0x35, 0x11, 0xf0, 0x02 }, // VGA 00141 { 0x16, 0x04, 0x80, 0x02, 0x7a, 0x0a, 0x04, 0x19, 0x35, 0x11, 0xf1, 0x02 }, // QVGA 00142 { 0x16, 0x04, 0xa4, 0x02, 0x7a, 0x0a, 0x04, 0x1a, 0x35, 0x22, 0xf2, 0x02 }, // QQVGA 00143 }; 00144 const char camera_reset_command[] = { 0x12, 0x80 }; 00145 00146 _read_order_change = 0; 00147 00148 // SPI settings 00149 00150 00151 _cs = 1; // set ChipSelect signal HIGH 00152 _spi.format( 8 ); // camera SPI : 8bits/transfer 00153 _spi.frequency( SPI_FREQUENCY ); // SPI frequency setting 00154 _i2c.frequency( 400 * 1000 ); 00155 00156 // reset 00157 00158 _reset = 0; 00159 wait_ms( RESET_PULSE_WIDTH ); // assert RESET signal 00160 _reset = 1; 00161 wait_ms( RESET_RECOVERY_TIME ); // deassert RESET signal 00162 00163 if ( 0 != (_error_state = _i2c.write( CAM_I2C_ADDR, camera_reset_command, 2 )) ) 00164 return _error_state; // return non-zero if I2C access failed 00165 00166 wait_ms( 100 ); // reset (via I2C) recovery time 00167 00168 _horizontal_size = QCIF_PIXEL_PER_LINE; 00169 _vertical_size = QCIF_LINE_PER_FRAME; 00170 00171 #ifdef UNIFIED_RESOLUTION_CHANGE 00172 if ( QCIF != res ) { 00173 for ( int i = 0; i < RES_CHANGE_PARAM_NUM; i++ ) { 00174 for ( int j = 0; j < PARAM_NUM; j++ ) { 00175 if ( camera_register_setting[ j ][ 0 ] == res_change_param[ 0 ][ i ] ) { 00176 camera_register_setting[ j ][ 1 ] = res_change_param[ res ][ i ]; 00177 } 00178 } 00179 } 00180 } 00181 00182 switch ( res ) { 00183 case QCIF: 00184 _horizontal_size = QCIF_PIXEL_PER_LINE; 00185 _vertical_size = QCIF_LINE_PER_FRAME; 00186 break; 00187 case VGA: 00188 _horizontal_size = VGA_PIXEL_PER_LINE; 00189 _vertical_size = VGA_LINE_PER_FRAME; 00190 break; 00191 case QVGA: 00192 _horizontal_size = VGA_PIXEL_PER_LINE / 2; 00193 _vertical_size = VGA_LINE_PER_FRAME / 2; 00194 break; 00195 case QQVGA: 00196 _horizontal_size = VGA_PIXEL_PER_LINE / 4; 00197 _vertical_size = VGA_LINE_PER_FRAME / 4; 00198 break; 00199 } 00200 #endif 00201 00202 00203 for ( int i = 0; i < PARAM_NUM; i++ ) { 00204 if ( 0 != (_error_state = _i2c.write( CAM_I2C_ADDR, camera_register_setting[ i ], 2 )) ) 00205 break; 00206 00207 wait_ms( COMMAND_INTERVAL ); // camera register writing requires this interval 00208 } 00209 00210 #ifndef UNIFIED_RESOLUTION_CHANGE 00211 if ( QCIF != res ) { 00212 char d[ 2 ]; 00213 for ( int i = 0; i < RES_CHANGE_PARAM_NUM; i++ ) { 00214 d[ 0 ] = res_change_param[ 0 ][ i ]; 00215 d[ 1 ] = res_change_param[ res ][ i ]; 00216 00217 if ( 0 != (_error_state = _i2c.write( CAM_I2C_ADDR, d, 2 )) ) 00218 break; 00219 00220 wait_ms( COMMAND_INTERVAL ); // camera register writing requires this interval 00221 } 00222 } 00223 00224 switch ( res ) { 00225 case QCIF: 00226 _horizontal_size = QCIF_PIXEL_PER_LINE; 00227 _vertical_size = QCIF_LINE_PER_FRAME; 00228 break; 00229 case VGA: 00230 _horizontal_size = VGA_PIXEL_PER_LINE; 00231 _vertical_size = VGA_LINE_PER_FRAME; 00232 break; 00233 case QVGA: 00234 _horizontal_size = VGA_PIXEL_PER_LINE / 2; 00235 _vertical_size = VGA_LINE_PER_FRAME / 2; 00236 break; 00237 case QQVGA: 00238 _horizontal_size = VGA_PIXEL_PER_LINE / 4; 00239 _vertical_size = VGA_LINE_PER_FRAME / 4; 00240 break; 00241 } 00242 #endif 00243 00244 return _error_state; // return non-zero if I2C access failed 00245 } 00246 00247 void MARMEX_VB::colorbar( SwitchState sw ) 00248 { 00249 char s[ 2 ]; 00250 00251 s[ 0 ] = 0x12; 00252 s[ 1 ] = sw ? 0x06 : 0x04; 00253 00254 _error_state = _i2c.write( CAM_I2C_ADDR, s, 2 ); 00255 } 00256 00257 int MARMEX_VB::get_horizontal_size( void ) 00258 { 00259 return _horizontal_size; // return last state of I2C access 00260 } 00261 00262 int MARMEX_VB::get_vertical_size( void ) 00263 { 00264 return _vertical_size; // return last state of I2C access 00265 } 00266 00267 int MARMEX_VB::ready( void ) 00268 { 00269 return _error_state; // return last state of I2C access 00270 } 00271 00272 extern int read_order_change; 00273 00274 void MARMEX_VB::read_a_line( short *p, int line_number, int x_offset, int n_of_pixels ) 00275 { 00276 // OPTION REFERENCE NUMBER (DO NOT EDIT) 00277 #define NO_OPTIMIZATION 0 00278 #define LOOP_UNROLL 1 00279 #define USING_SSP_FIFO 2 00280 00281 if ( line_number < 0 ) 00282 return; 00283 00284 // set camera module's buffer address 00285 set_address( line_number * get_horizontal_size() * BYTE_PER_PIXEL + x_offset * BYTE_PER_PIXEL ); 00286 00287 // put a read command, first return byte should be ignored 00288 read_register( CAMERA_DATA_REGISTER ); 00289 00290 00291 /* 00292 * Type0: "LINE_READ_OPT" is define as "NO_OPTIMIZATION" 00293 * Most basic loop to explain how the MCU reading the line data. 00294 * But this routine is slow, because the loop does 1 byte read 00295 * with ChipSelect signal assertion/deassertion by DigitalOut 00296 */ 00297 #if ( LINE_READ_OPT == NO_OPTIMIZATION ) 00298 00299 short tmp; 00300 00301 if ( _read_order_change ) { 00302 for( int x = 0; x < n_of_pixels; x++ ) { 00303 // perform 2 bytes read. a pixel data is in RGB565 format (16bits) 00304 tmp = read_register( CAMERA_DATA_REGISTER ); // read lower byte 00305 *p++ = (read_register( CAMERA_DATA_REGISTER ) << 8) | tmp; // read upper byte 00306 } 00307 } else { 00308 00309 read_register( CAMERA_DATA_REGISTER ); 00310 00311 for( int x = 0; x < n_of_pixels; x++ ) { 00312 // perform 2 bytes read. a pixel data is in RGB565 format (16bits) 00313 tmp = read_register( CAMERA_DATA_REGISTER ) << 8; // read lower byte 00314 *p++ = (read_register( CAMERA_DATA_REGISTER ) << 0) | tmp; // read upper byte 00315 } 00316 } 00317 #endif // ( LINE_READ_OPT == NO_OPTIMIZATION ) 00318 00319 00320 /* 00321 * Type1: "LINE_READ_OPT" is define as "LOOP_UNROLL" 00322 * Faster. And keeping compatibility on mbed-SDK. 00323 * Data reading speed improvement has been done in two ways. 00324 * * The ChipSelect signal is kept asserted for whole line data transfer. 00325 * because the MARMEX-VB module does not need deassertion at each end of byte transfer. 00326 * * Loop unrolled. minimized loop overhead 00327 */ 00328 #if ( LINE_READ_OPT == LOOP_UNROLL ) 00329 00330 char reg = COMMAND_READ | CAMERA_DATA_REGISTER | COMMAND_ADDR_INCREMENT; 00331 00332 if ( _read_order_change ) { 00333 00334 _cs = 0; 00335 00336 for( int x = 0; x < n_of_pixels; x += 8 ) { 00337 // perform 2 bytes read. a pixel data is in RGB565 format (16bits) 00338 00339 *p = _spi.write( reg ); 00340 *p++ |= _spi.write( reg ) << 8; 00341 00342 *p = _spi.write( reg ); 00343 *p++ |= _spi.write( reg ) << 8; 00344 00345 *p = _spi.write( reg ); 00346 *p++ |= _spi.write( reg ) << 8; 00347 00348 *p = _spi.write( reg ); 00349 *p++ |= _spi.write( reg ) << 8; 00350 00351 *p = _spi.write( reg ); 00352 *p++ |= _spi.write( reg ) << 8; 00353 00354 *p = _spi.write( reg ); 00355 *p++ |= _spi.write( reg ) << 8; 00356 00357 *p = _spi.write( reg ); 00358 *p++ |= _spi.write( reg ) << 8; 00359 00360 *p = _spi.write( reg ); 00361 *p++ |= _spi.write( reg ) << 8; 00362 00363 } 00364 _cs = 1; 00365 00366 } else { 00367 00368 read_register( CAMERA_DATA_REGISTER ); 00369 00370 _cs = 0; 00371 00372 for( int x = 0; x < n_of_pixels; x += 8 ) { 00373 // perform 2 bytes read. a pixel data is in RGB565 format (16bits) 00374 00375 *p = _spi.write( reg ) << 8; 00376 *p++ |= _spi.write( reg ); 00377 00378 *p = _spi.write( reg ) << 8; 00379 *p++ |= _spi.write( reg ); 00380 00381 *p = _spi.write( reg ) << 8; 00382 *p++ |= _spi.write( reg ); 00383 00384 *p = _spi.write( reg ) << 8; 00385 *p++ |= _spi.write( reg ); 00386 00387 *p = _spi.write( reg ) << 8; 00388 *p++ |= _spi.write( reg ); 00389 00390 *p = _spi.write( reg ) << 8; 00391 *p++ |= _spi.write( reg ); 00392 00393 *p = _spi.write( reg ) << 8; 00394 *p++ |= _spi.write( reg ); 00395 00396 *p = _spi.write( reg ) << 8; 00397 *p++ |= _spi.write( reg ); 00398 00399 } 00400 _cs = 1; 00401 } 00402 #endif // ( LINE_READ_OPT == LOOP_UNROLL ) 00403 00404 00405 /* 00406 * Type2: "LINE_READ_OPT" is define as "USING_SSP_FIFO" 00407 * Fastest but no compatibility with mbed-SDK. 00408 * The optimization has been done to use FIFO of SSP block. 00409 * This code makes data transfer efficiency maximum. 00410 * However, since this optimization is done in very low level (by register accessing), 00411 * it works on some MCU's only (test has been done on LPC1768, LPC11U24 and LPC11U35). 00412 * 00413 * And user need to care about which SSP block is used. For instance, if the SPI pins 00414 * of p5, p6 and p7 are used, those are connected to SSP1 in LPC1768. In case of 00415 * LPC11U24 and LPC11U35, those pins are routed to SSP0. 00416 * These settings should be done manually 00417 */ 00418 #if ( LINE_READ_OPT == USING_SSP_FIFO ) 00419 00420 #define FIFO_DEPTH 4 00421 00422 #if defined( SSP_AUTO_SELECTION ) 00423 #if defined( TARGET_MBED_LPC1768 ) 00424 #define SPI_PORT_SELECTOR LPC_SSP1 00425 #elif defined( TARGET_LPC11U35_501 ) || defined( TARGET_LPC11U24_401 ) 00426 #define SPI_PORT_SELECTOR LPC_SSP0 00427 #endif 00428 #elif defined( SSP_USE_SSP0 ) 00429 #define SPI_PORT_SELECTOR LPC_SSP0 00430 #elif defined( SSP_USE_SSP1 ) 00431 #define SPI_PORT_SELECTOR LPC_SSP1 00432 #else 00433 #error when using FIFO option for the optimization, choose one of definition from SSP_AUTO_SELECTION, SSP_USE_SSP0 or SSP_USE_SSP1 00434 #endif // #if defined( SSP_AUTO_SELECTION ) 00435 00436 char reg = COMMAND_READ | CAMERA_DATA_REGISTER | COMMAND_ADDR_INCREMENT; 00437 int n; 00438 00439 if ( _read_order_change ) { 00440 00441 _cs = 0; 00442 00443 for(n = FIFO_DEPTH; n > 0; n--) { 00444 SPI_PORT_SELECTOR->DR = reg; 00445 } 00446 00447 do { 00448 while (!(SPI_PORT_SELECTOR->SR & 0x4)); 00449 *p = (SPI_PORT_SELECTOR->DR & 0xFF); 00450 00451 if (n++ < (n_of_pixels << 1) - FIFO_DEPTH) 00452 SPI_PORT_SELECTOR->DR = reg; 00453 00454 while (!(SPI_PORT_SELECTOR->SR & 0x4)); 00455 *p++ |= (SPI_PORT_SELECTOR->DR << 8); 00456 00457 if (n++ < (n_of_pixels << 1) - FIFO_DEPTH) 00458 SPI_PORT_SELECTOR->DR = reg; 00459 00460 } while(n < (n_of_pixels << 1)); 00461 00462 _cs = 1; 00463 00464 } else { 00465 00466 read_register( CAMERA_DATA_REGISTER ); 00467 00468 _cs = 0; 00469 00470 for(n = FIFO_DEPTH; n > 0; n--) { 00471 SPI_PORT_SELECTOR->DR = reg; 00472 } 00473 00474 do { 00475 while (!(SPI_PORT_SELECTOR->SR & 0x4)); 00476 *p = (SPI_PORT_SELECTOR->DR << 8); 00477 00478 if (n++ < (n_of_pixels << 1) - FIFO_DEPTH) 00479 SPI_PORT_SELECTOR->DR = reg; 00480 00481 while (!(SPI_PORT_SELECTOR->SR & 0x4)); 00482 *p++ |= (SPI_PORT_SELECTOR->DR & 0xFF); 00483 00484 if (n++ < (n_of_pixels << 1) - FIFO_DEPTH) 00485 SPI_PORT_SELECTOR->DR = reg; 00486 00487 } while(n < (n_of_pixels << 1)); 00488 00489 _cs = 1; 00490 } 00491 00492 #endif // ( LINE_READ_OPT == USING_SSP_FIFO ) 00493 } 00494 00495 void MARMEX_VB::open_transfer( void ) 00496 { 00497 // send command to pause the camera buffer update 00498 write_register( CONTROL_DATA_REGISTER, CONTROL__PAUSE_BUFFER_UPDATE ); 00499 00500 // read status register (first return byte should be ignored) 00501 read_register( STATUS_REGISTER ); 00502 00503 // wait until the status register become 0x51(ready to transfer data) 00504 while ( 0x51 != read_register( STATUS_REGISTER ) ) 00505 ; 00506 } 00507 00508 void MARMEX_VB::close_transfer( void ) 00509 { 00510 // send command to resume the camera buffer update 00511 write_register( CONTROL_DATA_REGISTER, CONTROL__RESUME_BUFFER_UPDATE ); 00512 00513 // read status register (first return byte should be ignored) 00514 read_register( STATUS_REGISTER ); 00515 00516 // wait until the status register become 0x50(camera updating the buffer) 00517 while ( 0x50 != read_register( STATUS_REGISTER ) ) 00518 ; 00519 } 00520 00521 int MARMEX_VB::read_order_change( void ) 00522 { 00523 return ( _read_order_change = !_read_order_change ); 00524 } 00525 00526 void MARMEX_VB::set_address( int address ) 00527 { 00528 // set memory address (3 bytes) 00529 00530 write_register( MEMORY_ADDR_LOW__REGISTER, (address >> 0) & 0xFF ); 00531 write_register( MEMORY_ADDR_MID__REGISTER, (address >> 8) & 0xFF ); 00532 write_register( MEMORY_ADDR_HIGH_REGISTER, (address >> 16) & 0xFF ); 00533 } 00534 00535 void MARMEX_VB::write_register( char reg, char value ) 00536 { 00537 // camera register write 00538 00539 send_spi( COMMAND_WRITE | reg ); // send command and register number 00540 send_spi( value ); // send register value 00541 } 00542 00543 int MARMEX_VB::read_register( char reg ) 00544 { 00545 // camera register read 00546 // returning current data in SPI buffer (data returned by previous command) 00547 00548 return ( send_spi( COMMAND_READ | reg | ((reg == CAMERA_DATA_REGISTER) ? COMMAND_ADDR_INCREMENT : 0x00) ) ); 00549 } 00550 00551 int MARMEX_VB::send_spi( char data ) 00552 { 00553 int tmp; 00554 00555 // SPI access 00556 _cs = 0; 00557 tmp = _spi.write( data ); 00558 _cs = 1; 00559 00560 return ( tmp ); 00561 }
Generated on Wed Jul 13 2022 17:47:09 by 1.7.2