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-26
Revision:
3:85db6ea8c0a4
Parent:
2:f80257456c6e

File content as of revision 3:85db6ea8c0a4:

// 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){        
    Timer t_Frame;
    int i=0;        
    int timeoutState=0;
    t_Frame.start();
    
    while(timeoutState != 3  && (i < numchars)){
        switch(timeoutState){
            case 0:
                while(_cam.readable()){ //if characters are in buffer, read them
                    str[i++] = _cam.getc();
                    if(i == numchars){
                        timeoutState = 3;
                        break;   
                    }
                }
                //if no characters in buffer, initiate timeout
                timeoutState = 1;
                break;
            case 1:
                timeout = t_Frame.read() + timeout;    //current time plus timeout time
                timeoutState = 2;
//                                              pc.printf("Timeout initiated %f\r\n", timeout);
                break;
            case 2:
                if(_cam.readable()){ //check buffer while timeout is running
                    str[i++] = _cam.getc();
                    if(i == numchars){
                        timeoutState = 3;
                    }
                    else{
                        timeoutState = 0;
                    }
                    break;
                }
                if(t_Frame.read() >= timeout) //if timeout has elapsed, exit the while loop with state 3
                    timeoutState = 3;
                break;
            default:
                timeoutState = 0;
        }//switch timeoutState                             
    }//while timeoutState != 2
    return i;   //return number of bytes read
}

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(int command)
{
    char ser_read[7];
    int i;

    for(i=0;i<7;i++)         //clear the string
        ser_read[i] = 0;

    wait(.1);

    //read serial buffer and wait for ACK (0xAA0E0DXX0000)
    uCAM_read(ser_read, 6, .5);
    if((ser_read[0] == 0xAA) &&
        (ser_read[1] == 0x0E)){
        if((command & 0xff) == ser_read[2])
            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, .1);
      
      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=0x00-raw

   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, .02); //.01
   
   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(.010);
            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(.02);
            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(.01);

    if(uCAM_GetACK(uCAM_SNAPSHOT))
        return 1;
    else
        return 0;
}

int uCAM_TTL120::uCAM_send_GET_PICTURE_80x60_16COL_RAW(FILE *fp)
{
    char ser_read[7];
    unsigned long pic_bytes;
    unsigned int i, j, k;
    unsigned int serbytes_read;
    unsigned int pixel_col;

    pic_bytes = 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);

   if(uCAM_GetACK(uCAM_GET_PICTURE))     //returned get pic
  {
   //read serial C buffer and wait for ACK (0xAA0E0DXX0000)
      char c=uCAM_read(ser_read, 6, .1);

     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++;
                 fputc(((picture[k] >> 8) & 0xff), fp);     //write pixel high byte to file 
                 fputc(picture[k] & 0xff, fp);                 //write low byte
//               printf("%d ", pixel_col);
//               TFT.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 -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
   wait(.05);
   
   if(uCAM_GetACK(uCAM_SET_BAUD_RATE)){
        printf("Baud rate sucessfully changed");
    }
    else{
        printf("Baud rate NOT sucessfully changed");
    }
   
   _cam.baud(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(FILE *fp)
{
    uCAM_send_INITIAL_80x60_16RAW();
    wait(.1);
    uCAM_send_SNAPSHOT();
    wait(.1);
    uCAM_send_GET_PICTURE_80x60_16COL_RAW(fp);
}

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

int uCAM_TTL120::uCAM_get_jpeg(FILE *fp){
    
    char ser_read[7];
    unsigned long pic_bytes;
    
    uCAM_FlushBuffer();
    uCAM_Command_Send(uCAM_INITIAL,0x00,0x07,0x07,0x07); // JPEG,640 x 480,JPEG
    //cam.uCAM_Command_Send(uCAM_INITIAL,0x00,0x07,0x07,0x03); // JPEG,160 x 120,JPEG    
    wait(.05);
        
    if(uCAM_GetACK(uCAM_INITIAL)){     //INITIAL ACK
        printf("ACK received on uCAM_INITIAL\r\n");
    }
    else{
       printf("Did not receive ACK on uCAM_INITIAL\r\n");
    }
                
    uCAM_FlushBuffer();         
    uCAM_Command_Send(uCAM_SET_PACKAGE_SIZE,0x08,0x00,0x02,0x00); //512 bytes

    wait(.05);
            
    if(uCAM_GetACK(uCAM_SET_PACKAGE_SIZE)){     //SET PACKAGE SIZE ACK
        printf("ACK received on uCAM_SET_PACKAGE_SIZE\r\n");
    }
    else{
        printf("Did not receive ACK on SET PACKAGE SIZE\r\n");
    }        
            
    uCAM_FlushBuffer();     
    uCAM_Command_Send(uCAM_SNAPSHOT,0x00,0x00,0x00,0x00); //JPEG

    if(uCAM_GetACK(uCAM_SNAPSHOT)){     //uCAM_SNAPSHOT ACK
        printf("ACK received on uCAM_SNAPSHOT\r\n");
    }
    else{
        printf("Did not receive ACK on uCAM_SNAPSHOT\r\n");
    }

    pic_bytes = 0;
    
    uCAM_FlushBuffer();
    uCAM_Command_Send(uCAM_GET_PICTURE,0x01,0x00,0x00,0x00); // p1=0x01-Snapshot picture
    wait(.1);

    if(uCAM_GetACK(uCAM_GET_PICTURE))     //returned get pic
    {
        //read serial buffer and wait for ACK (0xAA0E0DXX0000)
        uCAM_read(ser_read, 6, 1);

        if((ser_read[0] == 0xAA) &&   //first 2 bytes indicate it was a DATA packet
            (ser_read[1] == 0x0A) &&
            (ser_read[2] == 0x01))      //DATA from snapshot ACK
        {
            pic_bytes = (unsigned long)ser_read[3];
            pic_bytes += (unsigned long)ser_read[4] << 8;
            pic_bytes += (unsigned long)ser_read[5] << 16;

            int packID=0;
            char packID_l, packID_h;
                    
 //           pc.printf("\r\n");
            int numPackages = pic_bytes / (512 - 6);
                     
            while(numPackages>=0){
                packID_h = (packID >> 8) & 0xff;
                packID_l = packID & 0xff;
                        
                uCAM_FlushBuffer();
                uCAM_Command_Send(uCAM_ACK, 0x00, 0x00, packID_l, packID_h);    
                        
                char ID_ret[2];
                uCAM_read(ID_ret, 2, .2);
                
                char dataSize[2];
                uCAM_read(dataSize, 2, .2);
                
                char imageData[506];    //512 - 6
                int imageDataSize = ((dataSize[1] & 0xff) << 8) + (dataSize[0] & 0xff);                        
                
                //uCAM_read(imageData, imageDataSize, .2);
                for(int i=0;i<imageDataSize;i++)
                    imageData[i] = _cam.getc();
                
                char verifyCode[2];
                uCAM_read(verifyCode, 2, .2);

                int vCodeCheck=0;
                vCodeCheck += ID_ret[0];
                vCodeCheck += ID_ret[1];
                vCodeCheck += dataSize[0];
                vCodeCheck += dataSize[1];
                
                for(int i=0;i<imageDataSize;i++)
                    vCodeCheck += imageData[i];

                if((verifyCode[0] & 0xff) == (vCodeCheck & 0xff)){                            
                    //pc.printf("\r\nPack ID = %d\r\n", packID);//debugging
                    for(int j=0;j<imageDataSize;j++){   //write image data to file pointer
                        fputc(imageData[j], fp);
                        //pc.printf("%2X ", imageData[j]);
                    }                                                                   
                    packID++;
                    numPackages--;
                }
                else{
                    printf("\r\nBad Data in transfer. ReTransfer\r\n");
                    return -2;
                }
            }
           uCAM_Command_Send(uCAM_ACK, 0x00, 0x00, 0xf0, 0xf0);
           return 0; //return 0 on success
        }
    }//data packet
    return -1;
}  //function