Dependencies:   mbed

Committer:
mux
Date:
Fri Dec 09 05:32:12 2011 +0000
Revision:
0:796c01948235
4D uCAM driver

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mux 0:796c01948235 1 #include "ucam.h"
mux 0:796c01948235 2 /*commands*/
mux 0:796c01948235 3 #define CMD_ACK 0x0E
mux 0:796c01948235 4 #define CMD_SYNC 0x0D
mux 0:796c01948235 5 #define CMD_INITIAL 0x01
mux 0:796c01948235 6 #define CMD_SNAPSHOT 0x05
mux 0:796c01948235 7 #define CMD_PICTURE 0x04
mux 0:796c01948235 8 #define CMD_DATA 0x0A
mux 0:796c01948235 9 #define CMD_BAUDRATE 0x07
mux 0:796c01948235 10 #define MAX_SYNC 60
mux 0:796c01948235 11 #define PACKET_LENGTH 506
mux 0:796c01948235 12 #define BUFFER_SIZE 8129
mux 0:796c01948235 13 #define DEBUG_WARN 0x01
mux 0:796c01948235 14 #define DEBUG_INFO 0x02
mux 0:796c01948235 15 #define DEBUG_COMS 0x04
mux 0:796c01948235 16 #define DEBUG_LEVEL 0xff
mux 0:796c01948235 17
mux 0:796c01948235 18 #if DEBUG_LEVEL
mux 0:796c01948235 19 extern Serial debug;
mux 0:796c01948235 20 #endif
mux 0:796c01948235 21
mux 0:796c01948235 22 struct ucam_command{
mux 0:796c01948235 23 union{
mux 0:796c01948235 24 struct{
mux 0:796c01948235 25 uint8_t buf[6];
mux 0:796c01948235 26 };
mux 0:796c01948235 27 struct{
mux 0:796c01948235 28 uint8_t pre;
mux 0:796c01948235 29 uint8_t id;
mux 0:796c01948235 30 uint8_t p1;
mux 0:796c01948235 31 uint8_t p2;
mux 0:796c01948235 32 uint8_t p3;
mux 0:796c01948235 33 uint8_t p4;
mux 0:796c01948235 34 };
mux 0:796c01948235 35 };
mux 0:796c01948235 36 };
mux 0:796c01948235 37
mux 0:796c01948235 38 struct{
mux 0:796c01948235 39 uint16_t ss;
mux 0:796c01948235 40 uint16_t se;
mux 0:796c01948235 41 uint8_t sz[BUFFER_SIZE];
mux 0:796c01948235 42 }fbuf;
mux 0:796c01948235 43
mux 0:796c01948235 44 uint8_t pbuf[PACKET_LENGTH * 2];
mux 0:796c01948235 45
mux 0:796c01948235 46 inline void buf_put_char(uint8_t ch)
mux 0:796c01948235 47 {
mux 0:796c01948235 48 register uint16_t se = fbuf.se;
mux 0:796c01948235 49 register uint16_t idx = (se + 1) % BUFFER_SIZE;
mux 0:796c01948235 50
mux 0:796c01948235 51 if (idx != fbuf.ss) {
mux 0:796c01948235 52 fbuf.sz[se] = ch;
mux 0:796c01948235 53 fbuf.se = idx;
mux 0:796c01948235 54 }
mux 0:796c01948235 55
mux 0:796c01948235 56 ///*buffer is full*/
mux 0:796c01948235 57 //#if (DEBUG_LEVEL & DEBUG_WARN)
mux 0:796c01948235 58 // debug.printf("warning buffer full\n");
mux 0:796c01948235 59 //#endif
mux 0:796c01948235 60 }
mux 0:796c01948235 61
mux 0:796c01948235 62 uint8_t buf_get_char()
mux 0:796c01948235 63 {
mux 0:796c01948235 64 uint16_t ch = fbuf.ss % BUFFER_SIZE;
mux 0:796c01948235 65
mux 0:796c01948235 66 while( ch == fbuf.se){
mux 0:796c01948235 67 /*buffer is empty*/
mux 0:796c01948235 68 wait_ms(1);
mux 0:796c01948235 69 }
mux 0:796c01948235 70
mux 0:796c01948235 71 ch = fbuf.sz[fbuf.ss];
mux 0:796c01948235 72 fbuf.ss = (fbuf.ss + 1) % BUFFER_SIZE;
mux 0:796c01948235 73 return ch;
mux 0:796c01948235 74 }
mux 0:796c01948235 75
mux 0:796c01948235 76 UCam::UCam(PinName tx_pin, PinName rx_pin, PinName led_pin, uint32_t baudrate):
mux 0:796c01948235 77 led(led_pin)
mux 0:796c01948235 78 {
mux 0:796c01948235 79 ucam = new Serial(p13, p14);
mux 0:796c01948235 80 ucam->baud(115200);
mux 0:796c01948235 81 ucam->attach(this, &UCam::uart_isr);
mux 0:796c01948235 82 fbuf.ss = 0;
mux 0:796c01948235 83 fbuf.se = 0;
mux 0:796c01948235 84 }
mux 0:796c01948235 85
mux 0:796c01948235 86 uint16_t buf_size()
mux 0:796c01948235 87 {
mux 0:796c01948235 88 return fbuf.se - fbuf.ss;
mux 0:796c01948235 89 }
mux 0:796c01948235 90
mux 0:796c01948235 91 UCam::~UCam()
mux 0:796c01948235 92 {
mux 0:796c01948235 93 led = 0;
mux 0:796c01948235 94 delete ucam;
mux 0:796c01948235 95 }
mux 0:796c01948235 96
mux 0:796c01948235 97 void UCam::uart_isr(void)
mux 0:796c01948235 98 {
mux 0:796c01948235 99 register uint16_t i;
mux 0:796c01948235 100 register uint16_t size = 0;
mux 0:796c01948235 101 register uint8_t *buf = pbuf;
mux 0:796c01948235 102
mux 0:796c01948235 103 do{
mux 0:796c01948235 104 buf[size++] = ucam->getc();
mux 0:796c01948235 105 }while (ucam->readable());
mux 0:796c01948235 106
mux 0:796c01948235 107 for (i=0; i<size; i++)
mux 0:796c01948235 108 buf_put_char(buf[i]);
mux 0:796c01948235 109 }
mux 0:796c01948235 110
mux 0:796c01948235 111 int8_t UCam::connect()
mux 0:796c01948235 112 {
mux 0:796c01948235 113 struct ucam_command cmd;
mux 0:796c01948235 114
mux 0:796c01948235 115 /*reset state machine*/
mux 0:796c01948235 116 //send_cmd(0x08, 0x01, 0x00, 0x00, 0x00);
mux 0:796c01948235 117 //wait(1.0);
mux 0:796c01948235 118
mux 0:796c01948235 119 /*full reset*/
mux 0:796c01948235 120 // send_cmd(0x08, 0x00, 0x00, 0x00, 0xff);
mux 0:796c01948235 121 // wait(1.0);
mux 0:796c01948235 122
mux 0:796c01948235 123 int8_t state=0;
mux 0:796c01948235 124 #if (DEBUG_LEVEL & DEBUG_INFO)
mux 0:796c01948235 125 debug.puts("syncing...\n");
mux 0:796c01948235 126 #endif
mux 0:796c01948235 127
mux 0:796c01948235 128 for (int i = 0; i < MAX_SYNC; i++) {
mux 0:796c01948235 129 switch(state){
mux 0:796c01948235 130 case 0: /*sync and recv ACK*/
mux 0:796c01948235 131 if (send_cmd(CMD_SYNC) == 0)
mux 0:796c01948235 132 ++state;
mux 0:796c01948235 133 break;
mux 0:796c01948235 134
mux 0:796c01948235 135 case 1:/*recv SYNC*/
mux 0:796c01948235 136 if (recv_cmd(&cmd) == 0 && cmd.id == CMD_SYNC)
mux 0:796c01948235 137 ++state;
mux 0:796c01948235 138 break;
mux 0:796c01948235 139
mux 0:796c01948235 140 case 2:/*send ACK SYNC*/
mux 0:796c01948235 141 if (send_cmd(CMD_ACK, CMD_SYNC, 0x00, 0x00, 0x00, 0x01) == 0)
mux 0:796c01948235 142 ++state;
mux 0:796c01948235 143 break;
mux 0:796c01948235 144
mux 0:796c01948235 145 case 3:
mux 0:796c01948235 146 led = 1;
mux 0:796c01948235 147 send_cmd(CMD_BAUDRATE, 0x00, 0x04, 0x00, 0x00);
mux 0:796c01948235 148 ucam->baud(737280);
mux 0:796c01948235 149 return 0;
mux 0:796c01948235 150 }
mux 0:796c01948235 151 wait(0.100);
mux 0:796c01948235 152 }
mux 0:796c01948235 153
mux 0:796c01948235 154 return -1;
mux 0:796c01948235 155 }
mux 0:796c01948235 156
mux 0:796c01948235 157 int8_t UCam::send_cmd(uint8_t id, uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4, uint8_t noack)
mux 0:796c01948235 158 {
mux 0:796c01948235 159 struct ucam_command cmd;
mux 0:796c01948235 160
mux 0:796c01948235 161 ucam->putc(0xAA);
mux 0:796c01948235 162 ucam->putc(id);
mux 0:796c01948235 163 ucam->putc(p1);
mux 0:796c01948235 164 ucam->putc(p2);
mux 0:796c01948235 165 ucam->putc(p3);
mux 0:796c01948235 166 ucam->putc(p4);
mux 0:796c01948235 167
mux 0:796c01948235 168 #if (DEBUG_LEVEL & DEBUG_COMS)
mux 0:796c01948235 169 debug.printf("> aa %02x %02x %02x %02x %02x\n",
mux 0:796c01948235 170 id, p1, p2, p3, p4);
mux 0:796c01948235 171 #endif/*enable_debug*/
mux 0:796c01948235 172
mux 0:796c01948235 173 if (noack)
mux 0:796c01948235 174 return 0;
mux 0:796c01948235 175
mux 0:796c01948235 176 /*recv ACK*/
mux 0:796c01948235 177 if (recv_cmd(&cmd) == 0 && cmd.id == CMD_ACK && cmd.p1 == id)
mux 0:796c01948235 178 return 0;
mux 0:796c01948235 179
mux 0:796c01948235 180 return -1;
mux 0:796c01948235 181 }
mux 0:796c01948235 182
mux 0:796c01948235 183 int8_t UCam::recv_cmd(struct ucam_command *cmd)
mux 0:796c01948235 184 {
mux 0:796c01948235 185 for (int8_t i = 0; i < sizeof(struct ucam_command); i++) {
mux 0:796c01948235 186 cmd->buf[i] = buf_get_char();
mux 0:796c01948235 187 }
mux 0:796c01948235 188
mux 0:796c01948235 189 #if (DEBUG_LEVEL & DEBUG_COMS)
mux 0:796c01948235 190 debug.printf("< %02x %02x %02x %02x %02x %02x\n",
mux 0:796c01948235 191 cmd->pre, cmd->id, cmd->p1,
mux 0:796c01948235 192 cmd->p2, cmd->p3, cmd->p4);
mux 0:796c01948235 193 #endif/*enable_debug*/
mux 0:796c01948235 194
mux 0:796c01948235 195 if (cmd->pre != 0xAA)
mux 0:796c01948235 196 goto error;
mux 0:796c01948235 197
mux 0:796c01948235 198 return 0;
mux 0:796c01948235 199 error:
mux 0:796c01948235 200 return -1;
mux 0:796c01948235 201 }
mux 0:796c01948235 202
mux 0:796c01948235 203 int8_t UCam::snapshot(uint8_t *buf, uint16_t *len, uint8_t color_space, uint8_t raw_size, uint8_t jpeg_size)
mux 0:796c01948235 204 {
mux 0:796c01948235 205 struct ucam_command cmd;
mux 0:796c01948235 206
mux 0:796c01948235 207 if (send_cmd(CMD_INITIAL, 0x00, color_space, raw_size, jpeg_size) != 0)
mux 0:796c01948235 208 return -1;
mux 0:796c01948235 209
mux 0:796c01948235 210 if (send_cmd(0x06, 0x08, 0x00, 0x02, 0x00) != 0) //set packet size to 512
mux 0:796c01948235 211 return -2;
mux 0:796c01948235 212
mux 0:796c01948235 213 if (send_cmd(CMD_SNAPSHOT, 0x00, 0x00, 0x00, 0x00) != 0)
mux 0:796c01948235 214 return -3;
mux 0:796c01948235 215
mux 0:796c01948235 216 if (send_cmd(CMD_PICTURE, 0x01, 0x00, 0x00, 0x00) != 0)
mux 0:796c01948235 217 return -4;
mux 0:796c01948235 218
mux 0:796c01948235 219 if (recv_cmd(&cmd) != 0 || cmd.id != CMD_DATA)
mux 0:796c01948235 220 return -5;
mux 0:796c01948235 221
mux 0:796c01948235 222 uint8_t id = 0;
mux 0:796c01948235 223 uint8_t byte;
mux 0:796c01948235 224 uint8_t blocks;
mux 0:796c01948235 225
mux 0:796c01948235 226 uint32_t size = 0, i = 0;
mux 0:796c01948235 227
mux 0:796c01948235 228 size = (size | cmd.p4) << 16;
mux 0:796c01948235 229 size = (size | cmd.p3) << 8;
mux 0:796c01948235 230 size = (size | cmd.p2);
mux 0:796c01948235 231
mux 0:796c01948235 232 blocks = size / PACKET_LENGTH;
mux 0:796c01948235 233 if (size % PACKET_LENGTH)
mux 0:796c01948235 234 ++blocks;
mux 0:796c01948235 235
mux 0:796c01948235 236 #if (DEBUG_LEVEL & DEBUG_INFO)
mux 0:796c01948235 237 debug.printf("image %d %d\n", size, blocks);
mux 0:796c01948235 238 #endif/*enable_debug*/
mux 0:796c01948235 239
mux 0:796c01948235 240 *len = size;
mux 0:796c01948235 241 while (blocks--) {
mux 0:796c01948235 242 if (send_cmd(CMD_ACK, 0x00, 0x00, id++, 0x00, true) != 0)
mux 0:796c01948235 243 return -6;
mux 0:796c01948235 244
mux 0:796c01948235 245 buf_get_char(); //id lsb
mux 0:796c01948235 246 buf_get_char(); //id msb
mux 0:796c01948235 247
mux 0:796c01948235 248 size=0;
mux 0:796c01948235 249 byte = buf_get_char(); //size lsb
mux 0:796c01948235 250 size |= buf_get_char(); //size msb
mux 0:796c01948235 251 size = (size << 8) | byte;
mux 0:796c01948235 252
mux 0:796c01948235 253 if (size == 0 || size > PACKET_LENGTH)
mux 0:796c01948235 254 return -7;
mux 0:796c01948235 255
mux 0:796c01948235 256 for (i = 0; i<size; i++) {
mux 0:796c01948235 257 *buf++ = buf_get_char();
mux 0:796c01948235 258 }
mux 0:796c01948235 259 buf_get_char(); //checksum lsb
mux 0:796c01948235 260 buf_get_char(); //checksum msb
mux 0:796c01948235 261 }
mux 0:796c01948235 262
mux 0:796c01948235 263 /*ack frame*/
mux 0:796c01948235 264 send_cmd(CMD_ACK, 0x00, 0x00, 0xF0, 0xF0, 0x01);
mux 0:796c01948235 265 return 0;
mux 0:796c01948235 266 }
mux 0:796c01948235 267
mux 0:796c01948235 268 int8_t UCam::start_video(uint8_t color_space, uint8_t raw_size, uint8_t jpeg_size)
mux 0:796c01948235 269 {
mux 0:796c01948235 270 if (send_cmd(CMD_INITIAL, 0x00, color_space, raw_size, jpeg_size) != 0)
mux 0:796c01948235 271 return -1;
mux 0:796c01948235 272
mux 0:796c01948235 273 if (send_cmd(0x06, 0x08, 0x00, 0x02, 0x00) != 0) //set packet size to 512
mux 0:796c01948235 274 return -2;
mux 0:796c01948235 275
mux 0:796c01948235 276 return 0;
mux 0:796c01948235 277 }
mux 0:796c01948235 278
mux 0:796c01948235 279 int8_t UCam::next_frame(uint8_t *buf, uint16_t *len)
mux 0:796c01948235 280 {
mux 0:796c01948235 281 uint8_t id = 0;
mux 0:796c01948235 282 uint8_t byte;
mux 0:796c01948235 283 uint8_t blocks;
mux 0:796c01948235 284 uint32_t size = 0, i = 0;
mux 0:796c01948235 285
mux 0:796c01948235 286 struct ucam_command cmd;
mux 0:796c01948235 287
mux 0:796c01948235 288 wait_ms(10); /* don't know why*/
mux 0:796c01948235 289
mux 0:796c01948235 290 if (send_cmd(CMD_PICTURE, 0x05, 0x00, 0x00, 0x00) != 0)
mux 0:796c01948235 291 goto error;
mux 0:796c01948235 292
mux 0:796c01948235 293 if (recv_cmd(&cmd) != 0 || cmd.id != CMD_DATA)
mux 0:796c01948235 294 goto error;
mux 0:796c01948235 295
mux 0:796c01948235 296
mux 0:796c01948235 297 size = (size | cmd.p4) << 16;
mux 0:796c01948235 298 size = (size | cmd.p3) << 8;
mux 0:796c01948235 299 size = (size | cmd.p2);
mux 0:796c01948235 300
mux 0:796c01948235 301 blocks = size / PACKET_LENGTH;
mux 0:796c01948235 302 if (size % PACKET_LENGTH)
mux 0:796c01948235 303 ++blocks;
mux 0:796c01948235 304
mux 0:796c01948235 305 #if (DEBUG_LEVEL & DEBUG_WARN)
mux 0:796c01948235 306 debug.printf("image %d %d\n", size, blocks);
mux 0:796c01948235 307 #endif/*enable_debug*/
mux 0:796c01948235 308
mux 0:796c01948235 309 *len = size;
mux 0:796c01948235 310 while (blocks--) {
mux 0:796c01948235 311 if (send_cmd(CMD_ACK, 0x00, 0x00, id++, 0x00, true) != 0)
mux 0:796c01948235 312 goto error;
mux 0:796c01948235 313
mux 0:796c01948235 314 size = 0;
mux 0:796c01948235 315 byte = buf_get_char(); //id lsb
mux 0:796c01948235 316 size |= buf_get_char(); //id msb
mux 0:796c01948235 317 size = (size << 8) | byte;
mux 0:796c01948235 318
mux 0:796c01948235 319 #if (DEBUG_LEVEL & DEBUG_INFO)
mux 0:796c01948235 320 debug.printf("block id %d ", size);
mux 0:796c01948235 321 #endif
mux 0:796c01948235 322
mux 0:796c01948235 323 size=0;
mux 0:796c01948235 324 byte = buf_get_char(); //size lsb
mux 0:796c01948235 325 size |= buf_get_char(); //size msb
mux 0:796c01948235 326 size = (size << 8) | byte;
mux 0:796c01948235 327
mux 0:796c01948235 328 #if (DEBUG_LEVEL & DEBUG_INFO)
mux 0:796c01948235 329 debug.printf("block size %d\n", size);
mux 0:796c01948235 330 #endif
mux 0:796c01948235 331
mux 0:796c01948235 332 if (size > PACKET_LENGTH || size > buf_size()) {
mux 0:796c01948235 333 #if (DEBUG_LEVEL & DEBUG_INFO)
mux 0:796c01948235 334 debug.printf("warning: invalid size %d\n", size);
mux 0:796c01948235 335 #endif
mux 0:796c01948235 336 goto error;
mux 0:796c01948235 337 }
mux 0:796c01948235 338
mux 0:796c01948235 339 if (blocks == 0 && size == PACKET_LENGTH) { /*ucam bug*/
mux 0:796c01948235 340 #if (DEBUG_LEVEL & DEBUG_WARN)
mux 0:796c01948235 341 debug.printf("warning: soft reset\n");
mux 0:796c01948235 342 #endif
mux 0:796c01948235 343 /*soft reset*/
mux 0:796c01948235 344 wait(1.0);
mux 0:796c01948235 345 send_cmd(0x08, 0x01, 0x00, 0x00, 0xFF);
mux 0:796c01948235 346
mux 0:796c01948235 347 /*ack frame*/
mux 0:796c01948235 348 send_cmd(CMD_ACK, 0x00, 0x00, 0xF0, 0xF0, 0x01);
mux 0:796c01948235 349 goto error;
mux 0:796c01948235 350 }
mux 0:796c01948235 351
mux 0:796c01948235 352 for (i = 0; i<size; i++) {
mux 0:796c01948235 353 *buf++ = buf_get_char();
mux 0:796c01948235 354 }
mux 0:796c01948235 355
mux 0:796c01948235 356 buf_get_char(); //checksum lsb
mux 0:796c01948235 357 buf_get_char(); //checksum msb
mux 0:796c01948235 358 }
mux 0:796c01948235 359
mux 0:796c01948235 360 /*ack frame*/
mux 0:796c01948235 361 send_cmd(CMD_ACK, 0x00, 0x00, 0xF0, 0xF0, 0x01);
mux 0:796c01948235 362 return 0;
mux 0:796c01948235 363 error:
mux 0:796c01948235 364 return -1;
mux 0:796c01948235 365 }