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
                }
             }

uCAM_TTL120.cpp

Committer:
jebradshaw
Date:
2014-11-17
Revision:
0:fcc0eaeeb35c
Child:
2:f80257456c6e

File content as of revision 0:fcc0eaeeb35c:

// 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();   
    }
}