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