mbed serial interface for the OV528 camera (uCAM TTL 120 from 4D systems).
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.
Above is a saved jpeg image from the camera at 480x640 resolution
Camera and TFT screen setup
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 } }
Diff: uCAM_TTL120.cpp
- 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(); + } +}