mbed serial interface for the OV528 camera (uCAM TTL 120 from 4D systems).

Dependencies:   MODSERIAL

Dependents:   mbed_uCAM_TTL120_20141118

Library for interfacing the mbed to the OV528 jpeg engine camera from Omnivision. I tested this program using the uCAM TTL 120 from 4D systems, now obsolete.

/media/uploads/jebradshaw/pic0003.jpg

Above is a saved jpeg image from the camera at 480x640 resolution

/media/uploads/jebradshaw/fullsizerender.jpg

Camera and TFT screen setup

/media/uploads/jebradshaw/tft_closeup_60x80.jpg

Closeup of the TFT screen displaying a 60x80 pixel 16 bit color bitmap image. The RGB (565) pixel colors were reversed when read from the camera relative to the TFT screen so a bit mask and shift had to be applied when displaying the pixel color.

bit mask and shift

         int k=12;
         for(int i=0;i<60;i++){
                for(int j=0;j<80;j++){                    
                    //returned 16-bit color is 565(RGB)
                     pixel_col = (imageData[k] << 8);
                     k++;                       
                     pixel_col += imageData[k];
                     k++;
//                 fputc(((picture[k] >> 8) & 0xff), fp);     //write pixel high byte to file 
//                 fputc(picture[k] & 0xff, fp);                 //write low byte
                                        
                //swap R and B bits in returned pixel for TFT display
                int TFT_pix_col = 0;
                TFT_pix_col += (pixel_col & 0x001f) << 11;
                TFT_pix_col += (pixel_col & 0xf800) >> 11;
                TFT_pix_col += (pixel_col & 0x07e0);
                                        
                 TFT.pixel(j, i, TFT_pix_col);  //Do something with the pixel
                }
             }
Revision:
0:fcc0eaeeb35c
Child:
2:f80257456c6e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uCAM_TTL120.cpp	Mon Nov 17 21:03:43 2014 +0000
@@ -0,0 +1,563 @@
+// Library for uCAM-TTL120 from Saelig
+
+#include "uCAM_TTL120.h"
+#define __DEBUG
+
+//----------------- uCAM Functions ------------------------------
+
+uCAM_TTL120::uCAM_TTL120(PinName tx, PinName rx) : _cam(tx, rx) {
+    _cam.baud(115200); //Initial baud rate
+    timerCam = new Timer();
+    
+    timerCam->start();    
+}
+
+/*
+int uCAM_TTL120::uCAM_read(char *str, int numchars, float timeout){
+    int i = 0;
+    
+        float t_stop = timerCam->read()+timeout;
+    
+    while(i < numchars){
+        if(_cam.readable()){
+            str[i] = _cam.getc();
+            i++;                
+        }
+                if(timerCam->read() > t_stop)
+                    return i;
+    }
+    
+    return i;
+}
+*/
+
+int uCAM_TTL120::uCAM_read(char *str, int numchars, float timeout){
+    int i = 0;
+    float t_start = timerCam->read();
+    
+    while((timerCam->read() < (t_start + timeout)) && (i < numchars)){
+        if(_cam.readable()){
+            str[i] = _cam.getc();
+            i++;                
+        }    
+    }
+    if(timerCam->read() >= (t_start + timeout)){
+        return -1;    
+    }
+    if(i >= numchars){
+        return -2;   
+    }
+    
+    return i;
+}
+
+void uCAM_TTL120::uCAM_Command_Send(int command,char p1,char p2,char p3,char p4)
+{
+    _cam.putc((char)(command >> 8) & 0xff);
+    _cam.putc((char)(command & 0xff));
+    _cam.putc(p1);
+    _cam.putc(p2);
+    _cam.putc(p3);
+    _cam.putc(p4);
+}
+
+int uCAM_TTL120::uCAM_GetACK(void)
+{
+    char ser_read[7];
+   int i;
+
+   for(i=0;i<7;i++)         //clear the string
+        ser_read[i] = 0;
+
+    wait(.2);
+
+      //read serial buffer and wait for ACK (0xAA0E0DXX0000)
+      uCAM_read(ser_read, 6, .1);
+      if((ser_read[0] == 0xAA) &&
+        (ser_read[1] == 0x0E))
+      {
+            return 1;
+      }
+      else
+        return 0;
+}
+
+int uCAM_TTL120::uCAM_Connect(void)
+{
+    char ser_read[20];
+   int i, retries;
+
+   for(i=0;i<20;i++)            //clear the string
+        ser_read[i] = 0;
+   retries=0;
+
+   while(retries < 60)
+   {
+        uCAM_FlushBuffer();
+         
+       //Transmit SYNC command
+        uCAM_Command_Send(uCAM_SYNC,0x00,0x00,0x00,0x00);
+
+        wait(.2);
+
+      //read serial buffer and wait for ACK (0xAA0E0DXX0000)
+      uCAM_read(ser_read, 6, .01);
+      
+      if((ser_read[0] == 0xAA) &&
+        (ser_read[1] == 0x0E) &&
+        (ser_read[2] == 0x0D) &&  //skip ser_read[3]
+         (ser_read[4] == 0x00))
+        {
+        //after receiving ACK, wait for SYNC (0xAA0D00000000)
+            uCAM_read(ser_read, 6, 100);
+          if((ser_read[0] == 0xAA) &&
+             (ser_read[1] == 0x0D) &&
+             (ser_read[2] == 0x00) &&
+             (ser_read[3] == 0x00) &&
+             (ser_read[4] == 0x00) &&
+             (ser_read[5] == 0x00))
+          {
+             //Transmit ACK command
+            uCAM_Command_Send(uCAM_ACK,0x0D,0x00,0x00,0x00);
+
+            printf("\r\n uCAM 120 Initialized\r\nDelaying 2 seconds for AGC and AEC \r\n circuits to stabilise before image capture.");
+            wait(.5);       //2 second delay before capturing first image
+            printf(".");
+            wait(.5);
+            printf(".");
+            wait(.5);
+            printf(".");
+            wait(.5);
+            printf(".\r\nFinished\r\n");
+
+            return 1;           //Camera connection successful
+          }
+      }
+      retries++;
+    }
+   if(retries == 60)
+        return 0;
+        
+    return -1;
+}
+
+int uCAM_TTL120::uCAM_send_INITIAL_80x60_16RAW(void)
+{
+    char ser_read[7];
+   int i;
+
+   uCAM_Command_Send(uCAM_INITIAL,0x00,0x06,0x01,0x00); // p2=0x06-16 bit color(RAW,565(RGB))
+                                                        // p3=0x01-80 x 60 bit resolution                                                            // p4=0x01-JPEG res 80 x 64
+    wait(.02);
+
+   for(i=0;i<7;i++)         //clear the string
+        ser_read[i] = 0;
+
+   //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+   uCAM_read(ser_read, 6, 100);
+   
+   if((ser_read[0] == 0xAA) &&
+      (ser_read[1] == 0x0E) &&
+      (ser_read[2] == 0x01)){
+      return 1;
+   }
+   else
+      return 0;
+}
+
+int uCAM_TTL120::uCAM_send_INITIAL_80x60_2RAW(void)
+{
+    char ser_read[7];
+    int i;
+    uCAM_Command_Send(uCAM_INITIAL,0x00,0x01,0x01,0x00);  // p2=0x01-2 bit GRAY (RAW)
+                                                                            // p3=0x01-80 x 60 bit resolution
+                                                            // p4=0x01-JPEG res 80 x 64
+    wait(.02);
+
+   for(i=0;i<7;i++)         //clear the string
+        ser_read[i] = 0;
+
+      //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+      uCAM_read(ser_read, 6, .1);
+      
+      if((ser_read[0] == 0xAA) &&
+        (ser_read[1] == 0x0E) &&
+         (ser_read[2] == 0x01))
+      {
+        wait(.050);
+            return 1;
+      }
+      else
+        return 0;
+}
+
+int uCAM_TTL120::uCAM_send_INITIAL_128x128_4RAW(void)
+{
+    char ser_read[7];
+    int i;
+    uCAM_Command_Send(uCAM_INITIAL,0x00,0x02,0x09,0x00);  // p2=0x02-4 bit GRAY (RAW)
+                                                                            // p3=0x09- 128x128 bit resolution
+                                                            // p4=0x01-JPEG res 80 x 64
+    wait(.02);
+
+   for(i=0;i<7;i++)         //clear the string
+        ser_read[i] = 0;
+
+      //read serial buffer and wait for ACK (0xAA0E0DXX0000)
+      uCAM_read(ser_read, 6, 100);
+      
+      if((ser_read[0] == 0xAA) &&
+        (ser_read[1] == 0x0E) &&
+         (ser_read[2] == 0x01))
+      {
+        wait(.05);
+            return 1;
+      }
+      else
+        return 0;
+}
+int uCAM_TTL120::uCAM_send_SNAPSHOT(void)
+{
+      uCAM_Command_Send(uCAM_SNAPSHOT,0x01,0x00,0x00,0x00); // p1=0x01-Uncompressed Image
+                                                                            // p2 and p3 = 0, current frame
+        wait(.05);
+
+        if(uCAM_GetACK())
+        return 1;
+      else
+            return 0;
+}
+
+int uCAM_TTL120::uCAM_send_GET_PICTURE_80x60_16COL_RAW(void)
+{
+    char ser_read[7];
+    char c;
+    unsigned long pic_bytes;
+    unsigned int i, j, k;
+    unsigned int serbytes_read;
+        unsigned int pixel_col;
+
+    pic_bytes = 0;
+    c=0;
+    serbytes_read = 0;
+    
+    for(i=0;i<100;i++)
+        picture[i] = 0;
+
+    while(_cam.readable()){     //flush the buffer
+        char c = _cam.getc();   
+    }
+
+    uCAM_Command_Send(uCAM_GET_PICTURE,0x01,0x00,0x00,0x00); // p1=0x01-Snapshot picture
+    wait(.3);
+
+      //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+    c=uCAM_read(ser_read, 6, 1);
+    wait(.3);
+
+   if(c==6) //received 6 bytes back
+   {
+       if((ser_read[0] == 0xAA) &&  //first 2 bytes indicate it was a DATA packet
+          (ser_read[1] == 0x0E) &&
+         (ser_read[2] == 0x04))     //returned get pic
+      {
+       //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+          c=uCAM_read(ser_read, 6, 1);
+
+          if(c==6) //received 6 bytes back
+          {
+             if((ser_read[0] == 0xAA) &&   //first 2 bytes indicate it was a DATA packet
+                (ser_read[1] == 0x0A))
+             {
+                pic_bytes = (unsigned long)ser_read[3];
+                pic_bytes += (unsigned long)ser_read[4] << 8;
+                pic_bytes += (unsigned long)ser_read[5] << 16;
+
+                serbytes_read = uCAM_read(picture, pic_bytes, .200);
+
+               if(serbytes_read == pic_bytes)
+               {
+                   k=0;
+                   for(i=0;i<60;i++)
+                   {
+                      for(j=0;j<80;j++)
+                      {
+                         pixel_col = picture[k];
+                         k++;
+//                         printf("%d ", pixel_col);
+//                         uLCD144_Put_Pixel(j, i, pixel_col);  //Do something with the pixel
+                      }
+                   }
+
+                   uCAM_Command_Send(uCAM_ACK, 0x0A, 0x00, 0x01, 0x00);
+
+                   return pic_bytes;
+               }
+               else
+                                    return -4;
+             }
+             else
+                return -3;
+          }
+      }
+      else
+        return -2;
+   }
+     return -1;
+}
+
+int uCAM_TTL120::uCAM_send_GET_PICTURE_80x60_2GRAY_RAW(void)
+{
+    char ser_read[7];
+    char c;
+    unsigned long pic_bytes;
+    unsigned int pixel_col;
+    unsigned int i, j, k;
+    int m;
+    unsigned int serbytes_read;
+    int temp;
+    
+    pic_bytes = 0;
+    c=0;
+    serbytes_read = 0;
+    
+    for(i=0;i<100;i++)
+    picture[i] = 0;
+    
+    while(_cam.readable()){     //flush the buffer
+        char c = _cam.getc();   
+    }
+    
+    uCAM_Command_Send(uCAM_GET_PICTURE,0x01,0x00,0x00,0x00); // p1=0x01-Snapshot picture
+    wait(.3);
+
+      //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+    c=uCAM_read(ser_read, 6, 1);
+    wait(.2);
+
+   if(c==6) //received 6 bytes back
+   {
+       if((ser_read[0] == 0xAA) &&  //first 2 bytes indicate it was a DATA packet
+          (ser_read[1] == 0x0E) &&
+         (ser_read[2] == 0x04))     //returned get pic
+      {
+       //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+          c=uCAM_read(ser_read, 6, 1);
+
+          if(c==6) //received 6 bytes back
+          {
+             if((ser_read[0] == 0xAA) &&   //first 2 bytes indicate it was a DATA packet
+                (ser_read[1] == 0x0A))
+             {
+                pic_bytes = (unsigned long)ser_read[3];
+                pic_bytes += (unsigned long)ser_read[4] << 8;
+                pic_bytes += (unsigned long)ser_read[5] << 16;
+
+                serbytes_read = uCAM_read(picture, pic_bytes, 200);
+
+               if(serbytes_read == pic_bytes)
+               {
+                   k=0;
+                   for(i=0;i<60;i++)
+                   {
+                      for(j=0;j<80;)
+                      {
+                        temp = picture[k];
+                        for(m=14;m>=0;m-=2)
+                        {
+                            pixel_col = (temp >> m) & 0x03;
+                            switch(pixel_col)
+                           {
+                                case 0:
+ //                               uLCD144_Put_Pixel(j, i, 0x0000);    //0x0000
+                                 break;
+                              case 1:
+ //                                uLCD144_Put_Pixel(j, i, 0x0180); //0x39e7
+                                 break;
+                              case 2:
+ //                                uLCD144_Put_Pixel(j, i, 0xc209); //0x7bef
+                                 break;
+                              case 3:
+//                                 uLCD144_Put_Pixel(j, i, 0xFFFF); //0xFFFF
+                                 break;
+                              default:
+ //                                 uLCD144_Put_Pixel(j, i, 0x0000);
+                                break;
+                           }
+                           j++;
+                        }
+                         k++;
+                      }
+                   }
+
+                   uCAM_Command_Send(uCAM_ACK, 0x0A, 0x00, 0x01, 0x00);
+
+                   return pic_bytes;
+               }
+               else
+                                    return -4;
+             }
+             else
+                return -3;
+          }
+      }
+      else
+        return -2;
+   }
+     return -1;
+}
+
+int uCAM_TTL120::uCAM_send_GET_PICTURE_128x128_4GRAY_RAW(void)
+{
+    char ser_read[7];
+   char c;
+   unsigned long pic_bytes;
+   unsigned int pixel_col;
+   unsigned int i, j, k;  
+   unsigned int serbytes_read;
+   int temp;
+
+   pic_bytes = 0;
+   c=0;
+   serbytes_read = 0;
+
+    for(i=0;i<100;i++)
+        picture[i] = 0;
+
+    while(_cam.readable()){     //flush the buffer
+        char c = _cam.getc();   
+    }
+
+   uCAM_Command_Send(uCAM_GET_PICTURE,0x01,0x00,0x00,0x00); // p1=0x01-Snapshot picture
+        wait(.3);
+
+      //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+   c=uCAM_read(ser_read, 6, 1);
+        wait(.2);
+
+   if(c==6) //received 6 bytes back
+   {
+       if((ser_read[0] == 0xAA) &&  //first 2 bytes indicate it was a DATA packet
+          (ser_read[1] == 0x0E) &&
+         (ser_read[2] == 0x04))     //returned get pic
+      {
+       //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
+          c=uCAM_read(ser_read, 6, 1);
+
+          if(c==6) //received 6 bytes back
+          {
+             if((ser_read[0] == 0xAA) &&   //first 2 bytes indicate it was a DATA packet
+                (ser_read[1] == 0x0A))
+             {
+                pic_bytes = (unsigned long)ser_read[3];
+                pic_bytes += (unsigned long)ser_read[4] << 8;
+                pic_bytes += (unsigned long)ser_read[5] << 16;
+
+                serbytes_read = uCAM_read(picture, pic_bytes, .2);
+
+               if(serbytes_read == pic_bytes)
+               {
+                   k=0;
+                   for(i=0;i<128;i++)
+                   {
+                      for(j=0;j<128;)
+                      {
+                        temp = picture[k];
+                        pixel_col = (temp >> 12) & 0x000F;
+                        pixel_col |= ((temp >> 12) & 0x000F) << 6;
+                        pixel_col |= ((temp >> 12) & 0x000F) << 11;
+ //                       uLCD144_Put_Pixel(j, i, pixel_col);
+                        printf("%c", pixel_col);
+                        j++;
+
+                        pixel_col = (temp >> 8) & 0x000F;
+                        pixel_col |= ((temp >> 8) & 0x000F) << 6;
+                        pixel_col |= ((temp >> 8) & 0x000F) << 11;
+ //                       uLCD144_Put_Pixel(j, i, pixel_col);
+                        printf("%c", pixel_col);
+                        j++;
+
+                        pixel_col = (temp >> 4) & 0x000F;
+                        pixel_col |= ((temp >> 4) & 0x000F) << 6;
+                        pixel_col |= ((temp >> 4) & 0x000F) << 11;
+//                        uLCD144_Put_Pixel(j, i, pixel_col);
+                        printf("%c", pixel_col);
+                        j++;
+
+                                pixel_col = temp & 0x000F;
+                        pixel_col |= (temp & 0x000F) << 6;
+                        pixel_col |= (temp & 0x000F) << 11;
+//                        uLCD144_Put_Pixel(j, i, pixel_col);
+                        printf("%c", pixel_col);
+                        j++;
+
+                        k++;
+                      }
+                   }
+
+                   uCAM_Command_Send(uCAM_ACK, 0x0A, 0x00, 0x01, 0x00);
+
+                   return pic_bytes;
+               }
+               else
+                return -4;
+             }
+             else
+                return -3;
+          }
+      }
+      else
+        return -2;
+   }
+     return -1;
+}
+
+void uCAM_TTL120::uCAM_set_baud(void)
+{
+   /*uCAM_Command_Send(uCAM_SET_BAUD_RATE,0x03,0x00,0x00,0x00);   // set baud to
+   serCopen(921600);*/
+   uCAM_Command_Send(uCAM_SET_BAUD_RATE,0x02,0x00,0x00,0x00);   // set baud to
+   _cam.baud(1228800);
+}
+
+void uCAM_TTL120::uCAM_TakePic_RAW_16COLOR_80x60(void)
+{
+    uCAM_send_INITIAL_80x60_16RAW();
+    wait(.1);
+    uCAM_send_SNAPSHOT();
+    wait(.1);
+    uCAM_send_GET_PICTURE_80x60_16COL_RAW();
+}
+
+void uCAM_TTL120::uCAM_TakePic_RAW_2GRAY_80x60(void)
+{
+    uCAM_send_INITIAL_80x60_2RAW();
+    wait(.1);
+    uCAM_send_SNAPSHOT();
+    wait(.1);
+
+    while(uCAM_send_GET_PICTURE_80x60_2GRAY_RAW() < 0){
+        wait(.1);
+        uCAM_send_SNAPSHOT();
+        wait(.2);
+    }
+}
+
+void uCAM_TTL120::uCAM_TakePic_RAW_4GRAY_128x128(void)
+{
+    uCAM_send_INITIAL_128x128_4RAW();
+    wait(.100);
+    uCAM_send_SNAPSHOT();
+    wait(.100);
+    while(uCAM_send_GET_PICTURE_128x128_4GRAY_RAW() < 0){
+        wait(.100);
+        uCAM_send_SNAPSHOT();
+        wait(.200);
+    }
+}
+
+void uCAM_TTL120::uCAM_FlushBuffer(void){
+    while(_cam.readable()){     //flush the buffer
+        char c = _cam.getc();   
+    }
+}