Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
mux
Date:
Fri Dec 09 05:32:12 2011 +0000
Commit message:
4D uCAM driver

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
ucam.cpp Show annotated file Show diff for this revision Revisions of this file
ucam.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 796c01948235 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Dec 09 05:32:12 2011 +0000
@@ -0,0 +1,66 @@
+#include "mbed.h"
+#include "ucam.h"
+#define BUFFER_LENGTH 4096
+
+Serial firefly(p28, p27);
+Serial debug(USBTX, USBRX);
+
+DigitalOut firefly_led(LED1);
+UCam ucam(p13, p14, LED2, 1228800);  // tx, rx, led, baud
+
+uint16_t len;
+uint8_t ubuf[BUFFER_LENGTH];
+uint8_t take_snapshot  =0;
+
+void firefly_isr()
+{
+    while(firefly.readable())
+        firefly.getc();
+    take_snapshot = 1;
+}
+
+int main()
+{
+    debug.puts("initiating firefly...\r\n");
+    firefly.baud(921600);     
+    firefly.attach(firefly_isr);
+    firefly_led = 1;
+    
+    debug.puts("initiating ucam...\r\n");
+        
+    if (ucam.connect() == 0){
+        debug.puts("connection to ucam established\r\n");
+    } else {
+        debug.puts("connection to ucam failed\r\n");
+        return -1;
+    }
+
+
+    if (ucam.start_video(COLOR_JPEG, JPEG_160x128, JPEG_160x128) != 0) {
+            debug.printf("failed to start video\r\n");
+            return -1;
+    }
+
+    Timer t;
+    uint16_t i;    
+    
+    while (1) {   
+    
+        t.reset();
+        
+        if (take_snapshot 
+                && ucam.next_frame(ubuf, &len) == 0) {
+
+            firefly.putc(((char*)&len)[0]); //size lsb
+            firefly.putc(((char*)&len)[1]); //size msb
+ 
+            for(i=0; i < len; i++){
+                firefly.putc(ubuf[i]);
+            }
+            
+            take_snapshot = 0;    
+            debug.printf("frame %f \r\n", t.read());
+        }
+        wait_ms(10);
+    }    
+}
\ No newline at end of file
diff -r 000000000000 -r 796c01948235 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Dec 09 05:32:12 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da
diff -r 000000000000 -r 796c01948235 ucam.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ucam.cpp	Fri Dec 09 05:32:12 2011 +0000
@@ -0,0 +1,365 @@
+#include "ucam.h"
+/*commands*/
+#define CMD_ACK         0x0E
+#define CMD_SYNC        0x0D
+#define CMD_INITIAL     0x01
+#define CMD_SNAPSHOT    0x05
+#define CMD_PICTURE     0x04
+#define CMD_DATA        0x0A
+#define CMD_BAUDRATE    0x07
+#define MAX_SYNC        60
+#define PACKET_LENGTH   506
+#define BUFFER_SIZE     8129
+#define DEBUG_WARN      0x01
+#define DEBUG_INFO      0x02
+#define DEBUG_COMS      0x04
+#define DEBUG_LEVEL     0xff
+
+#if DEBUG_LEVEL
+    extern Serial debug;
+#endif
+
+struct ucam_command{
+    union{
+        struct{
+            uint8_t buf[6];
+        };
+        struct{
+            uint8_t pre;
+            uint8_t id;            
+            uint8_t p1;
+            uint8_t p2;
+            uint8_t p3;
+            uint8_t p4;
+        };
+    };
+};
+
+struct{
+    uint16_t ss; 
+    uint16_t se;
+    uint8_t sz[BUFFER_SIZE];
+}fbuf;
+  
+uint8_t pbuf[PACKET_LENGTH * 2];
+
+inline void buf_put_char(uint8_t ch)
+{  
+   register uint16_t se = fbuf.se;
+   register uint16_t idx = (se + 1) % BUFFER_SIZE;
+    
+   if (idx != fbuf.ss) {
+       fbuf.sz[se] = ch;
+       fbuf.se = idx;    
+   }
+   
+   ///*buffer is full*/
+   //#if (DEBUG_LEVEL & DEBUG_WARN)
+   //   debug.printf("warning buffer full\n");
+   //#endif
+}
+
+uint8_t buf_get_char()
+{
+   uint16_t ch = fbuf.ss % BUFFER_SIZE;
+   
+   while( ch == fbuf.se){
+      /*buffer is empty*/
+        wait_ms(1);
+   }
+      
+   ch = fbuf.sz[fbuf.ss];
+   fbuf.ss = (fbuf.ss + 1) % BUFFER_SIZE;
+   return ch;
+}
+
+UCam::UCam(PinName tx_pin, PinName rx_pin, PinName led_pin, uint32_t baudrate):
+led(led_pin)
+{
+    ucam = new Serial(p13, p14);
+    ucam->baud(115200);
+    ucam->attach(this, &UCam::uart_isr);
+    fbuf.ss = 0;
+    fbuf.se = 0;
+}
+
+uint16_t buf_size()
+{
+    return fbuf.se - fbuf.ss;
+}
+
+UCam::~UCam()
+{
+    led = 0;
+    delete ucam;
+}
+
+void UCam::uart_isr(void)
+{
+    register uint16_t i;
+    register uint16_t size = 0;
+    register uint8_t *buf = pbuf;
+           
+    do{
+        buf[size++] = ucam->getc();
+    }while (ucam->readable());        
+    
+    for (i=0; i<size; i++)  
+        buf_put_char(buf[i]);
+}
+
+int8_t UCam::connect()
+{      
+    struct ucam_command cmd;
+    
+    /*reset state machine*/
+    //send_cmd(0x08, 0x01, 0x00, 0x00, 0x00);
+    //wait(1.0);
+
+    /*full reset*/    
+ //   send_cmd(0x08, 0x00, 0x00, 0x00, 0xff);
+   // wait(1.0);
+
+    int8_t state=0;
+#if (DEBUG_LEVEL & DEBUG_INFO)
+        debug.puts("syncing...\n");
+#endif
+            
+    for (int i = 0; i < MAX_SYNC; i++) {
+        switch(state){
+            case 0: /*sync and recv ACK*/
+                if (send_cmd(CMD_SYNC) == 0)
+                    ++state;
+                break;
+            
+            case 1:/*recv SYNC*/
+                if (recv_cmd(&cmd) == 0 && cmd.id == CMD_SYNC)
+                    ++state;
+                break;                
+            
+            case 2:/*send ACK SYNC*/
+                if (send_cmd(CMD_ACK, CMD_SYNC, 0x00, 0x00, 0x00, 0x01) == 0)
+                    ++state; 
+                break;
+                
+            case 3:
+                led = 1; 
+                send_cmd(CMD_BAUDRATE, 0x00, 0x04, 0x00, 0x00);
+                ucam->baud(737280);
+                return 0;
+        }        
+        wait(0.100);              
+    }
+    
+    return -1;
+}
+
+int8_t UCam::send_cmd(uint8_t id, uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4, uint8_t noack)
+{
+    struct ucam_command cmd;
+
+    ucam->putc(0xAA);
+    ucam->putc(id);
+    ucam->putc(p1);
+    ucam->putc(p2);
+    ucam->putc(p3);
+    ucam->putc(p4);           
+
+#if (DEBUG_LEVEL & DEBUG_COMS)
+    debug.printf("> aa %02x %02x %02x %02x %02x\n", 
+                    id, p1, p2, p3, p4);
+#endif/*enable_debug*/
+                     
+    if (noack)
+        return 0;
+    
+    /*recv ACK*/    
+    if (recv_cmd(&cmd) == 0 && cmd.id == CMD_ACK && cmd.p1 == id)
+        return 0;
+
+    return -1;
+}
+
+int8_t UCam::recv_cmd(struct ucam_command *cmd)
+{ 
+    for (int8_t i = 0; i < sizeof(struct ucam_command); i++) {            
+        cmd->buf[i] = buf_get_char();
+    }    
+
+#if (DEBUG_LEVEL & DEBUG_COMS)
+    debug.printf("< %02x %02x %02x %02x %02x %02x\n", 
+                    cmd->pre, cmd->id, cmd->p1,
+                    cmd->p2, cmd->p3, cmd->p4);
+#endif/*enable_debug*/
+ 
+    if (cmd->pre != 0xAA)
+        goto error;          
+
+    return 0; 
+error:
+    return -1;   
+}
+
+int8_t UCam::snapshot(uint8_t *buf, uint16_t *len, uint8_t color_space, uint8_t raw_size, uint8_t jpeg_size)
+{ 
+    struct ucam_command cmd;
+    
+    if (send_cmd(CMD_INITIAL, 0x00, color_space, raw_size, jpeg_size) != 0)
+        return -1;
+
+    if (send_cmd(0x06, 0x08, 0x00, 0x02, 0x00) != 0) //set packet size to 512
+        return -2;       
+     
+    if (send_cmd(CMD_SNAPSHOT, 0x00, 0x00, 0x00, 0x00) != 0)
+        return -3;
+       
+    if (send_cmd(CMD_PICTURE, 0x01, 0x00, 0x00, 0x00) != 0)
+        return -4;
+
+    if (recv_cmd(&cmd) != 0 || cmd.id != CMD_DATA)
+        return -5;            
+          
+    uint8_t id = 0;
+    uint8_t byte;
+    uint8_t blocks;
+
+    uint32_t size = 0, i = 0;    
+    
+    size = (size | cmd.p4) << 16;
+    size = (size | cmd.p3) << 8;    
+    size = (size | cmd.p2);
+    
+    blocks = size / PACKET_LENGTH;
+    if (size % PACKET_LENGTH)
+        ++blocks;
+        
+#if (DEBUG_LEVEL & DEBUG_INFO)
+    debug.printf("image %d %d\n", size, blocks);
+#endif/*enable_debug*/
+    
+    *len = size;
+    while (blocks--) {
+        if (send_cmd(CMD_ACK, 0x00, 0x00, id++, 0x00, true) != 0)
+            return -6;
+
+        buf_get_char();  //id lsb
+        buf_get_char();  //id msb
+        
+        size=0;
+        byte = buf_get_char(); //size lsb
+        size |= buf_get_char(); //size msb
+        size = (size << 8) | byte;
+        
+        if (size == 0 || size > PACKET_LENGTH)
+            return -7;
+                
+        for (i = 0; i<size; i++) {
+            *buf++ = buf_get_char(); 
+        }
+        buf_get_char(); //checksum lsb
+        buf_get_char(); //checksum msb                      
+    }        
+            
+    /*ack frame*/
+    send_cmd(CMD_ACK, 0x00, 0x00, 0xF0, 0xF0, 0x01);
+    return 0;
+}
+
+int8_t UCam::start_video(uint8_t color_space, uint8_t raw_size, uint8_t jpeg_size)
+{   
+    if (send_cmd(CMD_INITIAL, 0x00, color_space, raw_size, jpeg_size) != 0)
+        return -1;
+
+    if (send_cmd(0x06, 0x08, 0x00, 0x02, 0x00) != 0) //set packet size to 512
+        return -2;       
+         
+    return 0;
+}
+
+int8_t UCam::next_frame(uint8_t *buf, uint16_t *len)
+{   
+    uint8_t id = 0;
+    uint8_t byte;
+    uint8_t blocks;
+    uint32_t size = 0, i = 0;    
+    
+    struct ucam_command cmd;
+    
+    wait_ms(10); /* don't know why*/
+    
+    if (send_cmd(CMD_PICTURE, 0x05, 0x00, 0x00, 0x00) != 0)
+        goto error;
+               
+    if (recv_cmd(&cmd) != 0 || cmd.id != CMD_DATA)
+        goto error;           
+          
+    
+    size = (size | cmd.p4) << 16;
+    size = (size | cmd.p3) << 8;    
+    size = (size | cmd.p2);
+    
+    blocks = size / PACKET_LENGTH;
+    if (size % PACKET_LENGTH)
+        ++blocks;
+        
+    #if (DEBUG_LEVEL & DEBUG_WARN)
+        debug.printf("image %d %d\n", size, blocks);
+    #endif/*enable_debug*/
+    
+    *len = size;
+    while (blocks--) {
+        if (send_cmd(CMD_ACK, 0x00, 0x00, id++, 0x00, true) != 0)
+            goto error;
+        
+        size = 0;
+        byte = buf_get_char(); //id lsb
+        size |= buf_get_char(); //id msb
+        size = (size << 8) | byte;               
+            
+        #if (DEBUG_LEVEL & DEBUG_INFO)
+            debug.printf("block id %d ", size);
+        #endif
+        
+        size=0;
+        byte = buf_get_char(); //size lsb
+        size |= buf_get_char(); //size msb
+        size = (size << 8) | byte;
+
+        #if (DEBUG_LEVEL & DEBUG_INFO)
+            debug.printf("block size %d\n", size);
+        #endif
+        
+        if (size > PACKET_LENGTH || size > buf_size()) {
+            #if (DEBUG_LEVEL & DEBUG_INFO)
+                debug.printf("warning: invalid size %d\n", size);
+            #endif
+            goto error;
+        }
+                
+        if (blocks == 0 && size == PACKET_LENGTH) { /*ucam bug*/
+            #if (DEBUG_LEVEL & DEBUG_WARN)
+                debug.printf("warning: soft reset\n");
+            #endif
+            /*soft reset*/
+            wait(1.0);
+            send_cmd(0x08, 0x01, 0x00, 0x00, 0xFF);
+            
+            /*ack frame*/
+            send_cmd(CMD_ACK, 0x00, 0x00, 0xF0, 0xF0, 0x01);
+            goto error;
+        }
+                                      
+        for (i = 0; i<size; i++) {
+            *buf++ = buf_get_char();  
+        }
+        
+        buf_get_char(); //checksum lsb
+        buf_get_char(); //checksum msb                      
+    }        
+            
+    /*ack frame*/
+    send_cmd(CMD_ACK, 0x00, 0x00, 0xF0, 0xF0, 0x01);    
+    return 0;
+error:
+    return -1;
+}
\ No newline at end of file
diff -r 000000000000 -r 796c01948235 ucam.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ucam.h	Fri Dec 09 05:32:12 2011 +0000
@@ -0,0 +1,45 @@
+#ifndef __UCAM__H__
+#define __UCAM__H__
+#include <mbed.h>
+/*color space*/
+#define COLOR_YUV_2     0x01
+#define COLOR_YUV_4     0x02
+#define COLOR_YUV_8     0x03
+#define COLOR_RGB_332   0x04
+#define COLOR_RGB_444   0x05
+#define COLOR_RGB_565   0x06
+#define COLOR_JPEG      0x07
+/*raw resolution*/
+#define RAW_80x60       0x01
+#define RAW_160x120     0x03
+#define RAW_320x240     0x05
+#define RAW_640x480     0x07
+#define RAW_128x128     0x09
+#define RAW_128x96      0x0B
+/*jpeg resolution*/
+#define JPEG_80x64      0x01
+#define JPEG_160x128    0x03
+#define JPEG_320x240    0x05
+#define JPEG_640x480    0x07
+struct ucam_command;
+
+class UCam{
+    public:
+        Serial *ucam;
+        DigitalOut led;
+        
+    public:        
+        UCam(PinName tx_pin, PinName rx_pin, PinName led_pin, uint32_t baudrate);
+        ~UCam();
+        int8_t connect();
+        int8_t snapshot(uint8_t *buf, uint16_t *len, uint8_t colorspace, uint8_t raw_size, uint8_t jpeg_size);
+        int8_t start_video(uint8_t colorspace, uint8_t raw_size, uint8_t jpeg_size);
+        int8_t next_frame(uint8_t *buf, uint16_t *len);
+        int8_t end_video();
+        
+    private:
+        void uart_isr();
+        int8_t send_cmd(uint8_t cmd, uint8_t p1=0, uint8_t p2=0, uint8_t p3=0, uint8_t p4=0, uint8_t noack=0);
+        int8_t recv_cmd(struct ucam_command *cmd);
+};
+#endif/*#define __UCAM_H__*/
\ No newline at end of file