MARMEX-VB : "Mary Camera module" library

Dependents:   MARMEX_VB_test MARMEX_VB_Hello

MARMEX-VB (MARY-VB) camera module library for mbed. (This module may be available in Japan only.)

Kown problem / 既知の問題

The read data may have contouring. In this case, it may require reset or changing order of data reading. The order change API is available as "read_order_change()" function.
カメラから読み出したデータに擬似輪郭が発生することがあります.この問題にはシステム全体のリセットを行うか,または読み出し順の変更を行うことで対処して下さい.読み出し順の変更はAPIの"read_order_change()"関数を使うことができます.

Revision:
5:84e6c89a9a6d
Parent:
4:8ef31b67c0ab
--- a/MARMEX_VB.cpp	Thu Jun 19 12:21:43 2014 +0000
+++ b/MARMEX_VB.cpp	Fri Jun 20 09:05:19 2014 +0000
@@ -1,8 +1,8 @@
 /** MARMEX_VB Camera control library
  *
  *  @class   MARMEX_VB
- *  @version 0.4
- *  @date    19-Jun-2014
+ *  @version 0.5
+ *  @date    20-Jun-2014
  *
  *  Released under the Apache License, Version 2.0 : http://mbed.org/handbook/Apache-Licence
  *
@@ -14,6 +14,51 @@
 
 #define     SPI_FREQUENCY                   (12 * 1000 * 1000)
 
+/*  
+ *  Followings are 3 types of line read routines.
+ *  Choose one of next 3 methods for reading camera data trough SPI interface
+ *
+ *  Type0: "LINE_READ_OPT" is define as "NO_OPTIMIZATION"
+ *      Most basic loop to explain how the MCU reading the line data.
+ *      But this routine is slow, because the loop does 1 byte read
+ *      with ChipSelect signal assertion/deassertion by DigitalOut
+ *
+ *  Type1: "LINE_READ_OPT" is define as "LOOP_UNROLL"
+ *      Faster. And keeping compatibility on mbed-SDK.
+ *      Data reading speed improvement has been done in two ways.
+ *          * The ChipSelect signal is kept asserted for whole line data transfer.
+ *            because the MARMEX-VB module does not need deassertion at each end of byte transfer.
+ *          * Loop unrolled. minimized loop overhead
+ *
+ *  Type2: "LINE_READ_OPT" is define as "USING_SSP_FIFO"
+ *      Fastest but no compatibility with mbed-SDK.
+ *      The optimization has been done to use FIFO of SSP block.
+ *      This code makes data transfer efficiency maximum.
+ *      However, since this optimization is done in very low level (by register accessing),
+ *      it works on some MCU's only (test has been done on LPC1768, LPC11U24 and LPC11U35).
+ *
+ *      And user need to care about which SSP block is used. For instance, if the SPI pins
+ *      of p5, p6 and p7 are used, those are connected to SSP1 in LPC1768. In case of
+ *      LPC11U24 and LPC11U35, those pins are routed to SSP0.
+ *      These settings should be done manually
+ */
+ 
+//#define   LINE_READ_OPT   NO_OPTIMIZATION
+#define     LINE_READ_OPT   LOOP_UNROLL
+//#define   LINE_READ_OPT   USING_SSP_FIFO
+
+
+/*  Setting for "LINE_READ_OPT == USING_SSP_FIFO"
+ *      Choose one line from next 3 lines when the FIFO option is taken
+ */
+
+#define     SSP_AUTO_SELECTION  //  for demo setup on "MAPLE mini type-B (MARM03-BASE)" baseboard (slot2) with a MARMEX_OB module (on slot1)
+//#define   SSP_USE_SSP0
+//#define   SSP_USE_SSP1
+
+
+
+
 MARMEX_VB::MARMEX_VB(
     PinName SPI_mosi,
     PinName SPI_miso,
@@ -227,30 +272,11 @@
 extern int read_order_change;
 
 void MARMEX_VB::read_a_line( short *p, int line_number, int x_offset, int n_of_pixels )
-{
-#if 0
-
-    char    tmp;
-
-    if ( line_number < 0 )
-        return;
-
-    //  set camera module's buffer address
-    set_address( line_number * get_horizontal_size() * BYTE_PER_PIXEL + x_offset * BYTE_PER_PIXEL );
-
-    //  put a read command, first return byte should be ignored
-    read_register( CAMERA_DATA_REGISTER );
-
-    for( int x = 0; x < n_of_pixels; x++ ) {
-        //  perform 2 bytes read. a pixel data is in RGB565 format (16bits)
-        tmp     = read_register( CAMERA_DATA_REGISTER );                //  read lower byte
-        *p++    = (read_register( CAMERA_DATA_REGISTER ) << 8) | tmp;   //  read upper byte
-    }
-
-#else
-
-
-    short    tmp;
+{    
+    //  OPTION REFERENCE NUMBER (DO NOT EDIT)
+    #define NO_OPTIMIZATION 0
+    #define LOOP_UNROLL     1
+    #define USING_SSP_FIFO  2
 
     if ( line_number < 0 )
         return;
@@ -262,7 +288,23 @@
     read_register( CAMERA_DATA_REGISTER );
 
 
+/*
+ *  Type0: "LINE_READ_OPT" is define as "NO_OPTIMIZATION"
+ *      Most basic loop to explain how the MCU reading the line data.
+ *      But this routine is slow, because the loop does 1 byte read
+ *      with ChipSelect signal assertion/deassertion by DigitalOut
+ */
+#if ( LINE_READ_OPT == NO_OPTIMIZATION )
+
+    short    tmp;
+
     if ( _read_order_change ) {
+        for( int x = 0; x < n_of_pixels; x++ ) {
+            //  perform 2 bytes read. a pixel data is in RGB565 format (16bits)
+            tmp     = read_register( CAMERA_DATA_REGISTER );                //  read lower byte
+            *p++    = (read_register( CAMERA_DATA_REGISTER ) << 8) | tmp;   //  read upper byte
+        }
+    } else {
 
         read_register( CAMERA_DATA_REGISTER );
 
@@ -271,91 +313,131 @@
             tmp     = read_register( CAMERA_DATA_REGISTER ) << 8;                //  read lower byte
             *p++    = (read_register( CAMERA_DATA_REGISTER ) << 0) | tmp;   //  read upper byte
         }
+    }
+#endif  //  ( LINE_READ_OPT == NO_OPTIMIZATION )
 
-    } else {
 
-#define OPTIMIZE_KEEP_ASSERTING_CS_DURING_LINE_DATA_TRANSFER
-#ifdef  OPTIMIZE_KEEP_ASSERTING_CS_DURING_LINE_DATA_TRANSFER
-        //  optimized by IO register access and loop unroll
+/*
+ *  Type1: "LINE_READ_OPT" is define as "LOOP_UNROLL"
+ *      Faster. And keeping compatibility on mbed-SDK.
+ *      Data reading speed improvement has been done in two ways.
+ *          * The ChipSelect signal is kept asserted for whole line data transfer.
+ *            because the MARMEX-VB module does not need deassertion at each end of byte transfer.
+ *          * Loop unrolled. minimized loop overhead
+ */
+#if ( LINE_READ_OPT == LOOP_UNROLL )
+
+    char    reg = COMMAND_READ | CAMERA_DATA_REGISTER | COMMAND_ADDR_INCREMENT;
+
+    if ( _read_order_change ) {
+
         _cs = 0;
-
-        char    reg = COMMAND_READ | CAMERA_DATA_REGISTER | COMMAND_ADDR_INCREMENT;
-
+    
         for( int x = 0; x < n_of_pixels; x += 8 ) {
             //  perform 2 bytes read. a pixel data is in RGB565 format (16bits)
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
-
-            *p  = _spi.write( reg );
-            *p++  |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
+            *p      = _spi.write( reg );
+            *p++   |= _spi.write( reg ) << 8;
+    
         }
         _cs = 1;
-#else
-        for( int x = 0; x < n_of_pixels; x++ ) {
+
+    } else {
+        
+        read_register( CAMERA_DATA_REGISTER );
+
+        _cs = 0;
+    
+        for( int x = 0; x < n_of_pixels; x += 8 ) {
             //  perform 2 bytes read. a pixel data is in RGB565 format (16bits)
-            tmp     = read_register( CAMERA_DATA_REGISTER );                //  read lower byte
-            *p++    = (read_register( CAMERA_DATA_REGISTER ) << 8) | tmp;   //  read upper byte
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
+            *p      = _spi.write( reg ) << 8;
+            *p++   |= _spi.write( reg );
+    
         }
-#endif
+        _cs = 1;
     }
-
-#endif
-}
-
-
+#endif  //  ( LINE_READ_OPT == LOOP_UNROLL )
 
 
-void MARMEX_VB::read_a_line_SPI_FIFO_READ( short *p, int line_number, int x_offset, int n_of_pixels )
-{
-#define FIFO_DEPTH  4
+/*
+ *  Type2: "LINE_READ_OPT" is define as "USING_SSP_FIFO"
+ *      Fastest but no compatibility with mbed-SDK.
+ *      The optimization has been done to use FIFO of SSP block.
+ *      This code makes data transfer efficiency maximum.
+ *      However, since this optimization is done in very low level (by register accessing),
+ *      it works on some MCU's only (test has been done on LPC1768, LPC11U24 and LPC11U35).
+ *
+ *      And user need to care about which SSP block is used. For instance, if the SPI pins
+ *      of p5, p6 and p7 are used, those are connected to SSP1 in LPC1768. In case of
+ *      LPC11U24 and LPC11U35, those pins are routed to SSP0.
+ *      These settings should be done manually
+ */
+#if ( LINE_READ_OPT == USING_SSP_FIFO )
 
-#ifdef  TARGET_MBED_LPC1768
-#define SPI_PORT_SELECTOR   LPC_SSP1
-#endif
-
-#ifdef  TARGET_LPC11U35_501
-#define SPI_PORT_SELECTOR   LPC_SSP0
-#endif
+    #define FIFO_DEPTH  4
 
-#ifdef  TARGET_LPC11U24_401
-#define SPI_PORT_SELECTOR   LPC_SSP0
-#endif
-
-    char                reg = COMMAND_READ | CAMERA_DATA_REGISTER | COMMAND_ADDR_INCREMENT;
-    int                 n;
+    #if defined( SSP_AUTO_SELECTION )
+        #if defined( TARGET_MBED_LPC1768 )
+            #define SPI_PORT_SELECTOR   LPC_SSP1
+        #elif defined( TARGET_LPC11U35_501 ) || defined( TARGET_LPC11U24_401 )
+            #define SPI_PORT_SELECTOR   LPC_SSP0
+        #endif
+    #elif defined( SSP_USE_SSP0 )
+        #define SPI_PORT_SELECTOR   LPC_SSP0
+    #elif defined( SSP_USE_SSP1 )
+        #define SPI_PORT_SELECTOR   LPC_SSP1
+    #else
+        #error when using FIFO option for the optimization, choose one of definition from SSP_AUTO_SELECTION, SSP_USE_SSP0 or SSP_USE_SSP1
+    #endif   //  #if defined( SSP_AUTO_SELECTION )
 
-    if ( line_number < 0 )
-        return;
-
-    //  set camera module's buffer address
-    set_address( line_number * get_horizontal_size() * BYTE_PER_PIXEL + x_offset * BYTE_PER_PIXEL );
-
-    //  put a read command, first return byte should be ignored
-    read_register( CAMERA_DATA_REGISTER );
-
-
-    //  optimized by SPI-FIFO access
+    char    reg = COMMAND_READ | CAMERA_DATA_REGISTER | COMMAND_ADDR_INCREMENT;
+    int     n;
 
     if ( _read_order_change ) {
+        
         _cs = 0;
 
         for(n = FIFO_DEPTH; n > 0; n--) {
@@ -378,7 +460,9 @@
         } while(n < (n_of_pixels << 1));
 
         _cs = 1;
+        
     } else {
+        
         read_register( CAMERA_DATA_REGISTER );
 
         _cs = 0;
@@ -404,6 +488,8 @@
 
         _cs = 1;
     }
+
+#endif  //  ( LINE_READ_OPT == USING_SSP_FIFO )
 }
 
 void MARMEX_VB::open_transfer( void )