CameraC328
Dependents: CameraC328_TestProgram CameraC328_Thresholding Camera_TestProgram_2015 Camera_TestProgram_2015 ... more
Diff: CameraC328.cpp
- Revision:
- 3:6d3150d4396a
- Parent:
- 2:6a72fcad5c0a
- Child:
- 4:ad06342d4b84
--- a/CameraC328.cpp Mon Jun 28 13:57:15 2010 +0000 +++ b/CameraC328.cpp Tue Jun 29 11:45:53 2010 +0000 @@ -1,65 +1,178 @@ +/** + * C328-7640 device driver class + * Reference documents: C328-7640 User Manual v3.0 2004.8.19 + * + * Version 0.0.1 + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * shinta.main.jp@gmail.com + * http://shinta.main.jp/ + */ + #include "CameraC328.h" -Serial debout(USBTX, USBRX); - -#if 0 -#define SENDFUNC sendBytesWithDebugOutput -#define RECVFUNC recvBytesWithDebugOutput -#else #define SENDFUNC sendBytes #define RECVFUNC recvBytes -#endif +#define WAITFUNC waitRecv -CameraC328::CameraC328(PinName tx, PinName rx) : serial(tx, rx), syncdone(false) { - serial.baud(BAUD); +CameraC328::CameraC328(PinName tx, PinName rx, Baud baud) : serial(tx, rx) { + serial.baud((int)baud); } CameraC328::~CameraC328() { } CameraC328::ErrorNumber CameraC328::sync() { - char send[COMMAND_LENGTH]; - char recv[COMMAND_LENGTH]; - send[0] = 0xAA; - send[1] = 0x0D; - send[2] = 0; - send[3] = 0; - send[4] = 0; - send[5] = 0; for (int i = 0; i < SYNCMAX; i++) { - if (SENDFUNC(send, sizeof(send))) { - if (RECVFUNC(recv, sizeof(recv))) { - if ((0xAA == recv[0]) && (0x0E == recv[1])) { - if (RECVFUNC(recv, sizeof(recv))) { - if ((0xAA == recv[0]) && (0x0D == recv[1])) { - send[0] = 0xAA; - send[1] = 0x0E; - send[2] = 0x0D; - send[3] = 0x00; - send[4] = 0x00; - send[5] = 0x00; - if (SENDFUNC(send, sizeof(send))) { - syncdone = true; - /* - * After synchronization, the camera needs a little time for AEC and AGC to be stable. - * Users should wait for 1-2 seconds before capturing the first picture. - */ - wait(1); - return NoError; - } - } + if (NoError == sendSync()) { + if (NoError == recvAckOrNck()) { + if (NoError == recvSync()) { + if (NoError == sendAck(0x0D, 0x00)) { + /* + * After synchronization, the camera needs a little time for AEC and AGC to be stable. + * Users should wait for 1-2 seconds before capturing the first picture. + */ + wait(2); + return NoError; } } } } - wait(0.200); + wait_ms(50); } return UnexpectedReply; } CameraC328::ErrorNumber CameraC328::init(ColorType ct, RawResolution rr, JpegResolution jr) { + ErrorNumber en; + + en = sendInitial(ct, rr, jr); + if (NoError != en) { + return en; + } + WAITFUNC(); + en = recvAckOrNck(); + if (NoError != en) { + return en; + } + + return (ErrorNumber)NoError; +} + +/** + * Get uncompressed snapshot picture (uncompressed snapshot picture) + * + * @param func Pointer to a callback function. + * @return Status of the error. + */ +CameraC328::ErrorNumber CameraC328::getUncompressedSnapshotPicture(void(*func)(size_t done, size_t total, char c)) { + ErrorNumber en; + + en = sendSnapshot(UncompressedPicture, 0); + if (NoError != en) { + return en; + } + WAITFUNC(); + en = recvAckOrNck(); + if (NoError != en) { + return en; + } + + en = sendGetPicture(SnapshotPicture); + if (NoError != en) { + return en; + } + WAITFUNC(); + en = recvAckOrNck(); + if (NoError != en) { + return en; + } + + /* + * image data + */ + DataType dt; + uint32_t length = 0; + WAITFUNC(); + en = recvData(&dt, &length); + if (NoError != en) { + return en; + } + size_t imgcnt = 0; + for (int i = 0; i < (int)length; i++) { + char c; + WAITFUNC(); + if (!RECVFUNC(&c, 1)) { + return (ErrorNumber)UnexpectedReply; + } + imgcnt++; + func(imgcnt, length, c); + } + + /* + * ACK + */ + en = sendAck(0x0A, 0x00); + if (NoError != en) { + return en; + } + + return (ErrorNumber)NoError; +} + +/** + * Get uncompressed snapshot picture (uncompressed snapshot picture) + * + * @param func Pointer to a callback function. + * @return Status of the error. + */ +CameraC328::ErrorNumber CameraC328::getUncompressedPreviewPicture(void(*func)(size_t done, size_t total, char c)) { + ErrorNumber en; + + en = sendGetPicture(PreviewPicture); + if (NoError != en) { + return en; + } + WAITFUNC(); + en = recvAckOrNck(); + if (NoError != en) { + return en; + } + + /* + * image data + */ + DataType dt; + uint32_t length = 0; + WAITFUNC(); + en = recvData(&dt, &length); + if (NoError != en) { + return en; + } + size_t imgcnt = 0; + for (int i = 0; i < (int)length; i++) { + char c; + WAITFUNC(); + if (!RECVFUNC(&c, 1)) { + return (ErrorNumber)UnexpectedReply; + } + imgcnt++; + func(imgcnt, length, c); + } + + /* + * ACK + */ + en = sendAck(0x0A, 0x00); + if (NoError != en) { + return en; + } + + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::sendInitial(ColorType ct, RawResolution rr, JpegResolution jr) { char send[COMMAND_LENGTH]; - char recv[COMMAND_LENGTH]; send[0] = 0xAA; send[1] = 0x01; @@ -71,36 +184,15 @@ if (!SENDFUNC(send, sizeof(send))) { return (ErrorNumber)SendRegisterTimeout; } - - wait(0.2); - if (!RECVFUNC(recv, sizeof(recv))) { - return (ErrorNumber)UnexpectedReply; - } - - if ((0xAA != recv[0]) || (0x0E != recv[1])) { - return (ErrorNumber)recv[4]; - } - return (ErrorNumber)NoError; } -/* - * Get snapshot picture (uncompressed snapshot picture) - * - * @param func Pointer to a callback function. - * @return Status of the error. - */ -CameraC328::ErrorNumber CameraC328::getJpegSnapshotPicture(void(*func)(size_t done, size_t total, char c)) { - +CameraC328::ErrorNumber CameraC328::sendGetPicture(PictureType pt) { char send[COMMAND_LENGTH]; - char recv[COMMAND_LENGTH]; - /* - * Snapshot (uncompressed picture) - */ send[0] = 0xAA; - send[1] = 0x05; - send[2] = (char)UncompressedPicture; + send[1] = 0x04; + send[2] = (char)pt; send[3] = 0x00; send[4] = 0x00; send[5] = 0x00; @@ -108,20 +200,105 @@ if (!SENDFUNC(send, sizeof(send))) { return (ErrorNumber)SendRegisterTimeout; } - if (!RECVFUNC(recv, sizeof(recv))) { - return (ErrorNumber)UnexpectedReply; + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::sendSnapshot(SnapshotType st, uint16_t skipFrames) { + char send[COMMAND_LENGTH]; + send[0] = 0xAA; + send[1] = 0x05; + send[2] = (char)st; + send[3] = (skipFrames >> 0) & 0xff; + send[4] = (skipFrames >> 8) & 0xff; + send[5] = 0x00; + + if (!SENDFUNC(send, sizeof(send))) { + return (ErrorNumber)SendRegisterTimeout; + } + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::sendSetPackageSize(uint16_t packageSize) { + char send[COMMAND_LENGTH]; + send[0] = 0xAA; + send[1] = 0x06; + send[2] = 0x08; + send[3] = (packageSize >> 0) & 0xff; + send[4] = (packageSize >> 8) & 0xff; + send[5] = 0x00; + + if (!SENDFUNC(send, sizeof(send))) { + return (ErrorNumber)SendRegisterTimeout; } - if ((0xAA != recv[0]) || (0x0E != recv[1])) { - return (ErrorNumber)recv[4]; + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::sendSetBaudrate(Baud baud) { + char send[COMMAND_LENGTH]; + + static struct baud_list { + Baud baud; + uint8_t div1st; + uint8_t div2nd; + } baudtable [] = { + { Baud7200, 0xff, 0x01 }, + { Baud9600, 0xbf, 0x01 }, + { Baud14400, 0x7f, 0x01 }, + { Baud19200, 0x5f, 0x01 }, + { Baud28800, 0x3f, 0x01 }, + { Baud38400, 0x2f, 0x01 }, + { Baud57600, 0x1f, 0x01 }, + { Baud115200, 0x0f, 0x01 } + }; + + uint8_t div1st = 0x00, div2nd = 0x00; + struct baud_list *p = &baudtable[0]; + for (int i = 0; i < sizeof(baudtable) / sizeof(baudtable[0]); i++) { + if (p->baud == baud) { + div1st = p->div1st; + div2nd = p->div2nd; + } + p++; } + send[0] = 0xAA; + send[1] = 0x07; + send[2] = div1st; + send[3] = div2nd; + send[4] = 0x00; + send[5] = 0x00; + + if (!SENDFUNC(send, sizeof(send))) { + return (ErrorNumber)SendRegisterTimeout; + } + + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::sendReset(ResetType rt, bool specialReset) { + char send[COMMAND_LENGTH]; + send[0] = 0xAA; + send[1] = 0x08; + send[2] = (int)rt; + send[3] = 0x00; + send[4] = 0x00; + send[5] = specialReset ? 0xff : 0x00; /* - * Get picture (snapshot picture) + * Special reset : If the parameter is 0xFF, the command is a special Reset command and the firmware responds to it immediately. */ + if (!SENDFUNC(send, sizeof(send))) { + return (ErrorNumber)SendRegisterTimeout; + } + + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::sendPowerOff() { + char send[COMMAND_LENGTH]; send[0] = 0xAA; - send[1] = 0x04; - send[2] = (char)SnapshotPicture; + send[1] = 0x09; + send[2] = 0x00; send[3] = 0x00; send[4] = 0x00; send[5] = 0x00; @@ -129,52 +306,88 @@ if (!SENDFUNC(send, sizeof(send))) { return (ErrorNumber)SendRegisterTimeout; } - if (!RECVFUNC(recv, sizeof(recv))) { - return (ErrorNumber)UnexpectedReply; - } - if ((0xAA != recv[0]) || (0x0E != recv[1])) { - return (ErrorNumber)recv[4]; - } - /* - * image data - */ - while (!serial.readable()) { - } + return (ErrorNumber)NoError; +} + +CameraC328::ErrorNumber CameraC328::recvData(DataType *dt, uint32_t *length) { + char recv[COMMAND_LENGTH]; if (!RECVFUNC(recv, sizeof(recv))) { return (ErrorNumber)UnexpectedReply; } if ((0xAA != recv[0]) || (0x0A != recv[1])) { - return (ErrorNumber)recv[4]; + return (ErrorNumber)UnexpectedReply; } - size_t imgsiz = (recv[5] << 16) | (recv[4] << 8) | (recv[3] << 0); - size_t imgcnt = 0; - for (int i = 0; i < (int)imgsiz; i++) { - char c; - if (!RECVFUNC(&c, 1)) { - return (ErrorNumber)UnexpectedReply; - } - imgcnt++; - func(imgcnt, imgsiz, c); - } + *dt = (DataType)recv[2]; + *length = (recv[5] << 16) | (recv[4] << 8) | (recv[3] << 0); + return (ErrorNumber)NoError; +} - /* - * ACK - */ +CameraC328::ErrorNumber CameraC328::sendSync() { + char send[COMMAND_LENGTH]; send[0] = 0xAA; - send[1] = 0x0E; - send[2] = 0x0A; + send[1] = 0x0D; + send[2] = 0x00; send[3] = 0x00; send[4] = 0x00; send[5] = 0x00; if (!SENDFUNC(send, sizeof(send))) { return (ErrorNumber)SendRegisterTimeout; } + return (ErrorNumber)NoError; +} +CameraC328::ErrorNumber CameraC328::recvSync() { + char recv[COMMAND_LENGTH]; + if (!RECVFUNC(recv, sizeof(recv))) { + return (ErrorNumber)UnexpectedReply; + } + if ((0xAA != recv[0]) || (0x0D != recv[1])) { + return (ErrorNumber)UnexpectedReply; + } return (ErrorNumber)NoError; } /** + * Send ACK. + * + * @param commandId The command with that ID is acknowledged by this command. + * @param packageId For acknowledging Data command, these two bytes represent the requested package ID. While for acknowledging other commands, these two bytes are set to 00h. + */ +CameraC328::ErrorNumber CameraC328::sendAck(uint8_t commandId, uint16_t packageId) { + char send[COMMAND_LENGTH]; + send[0] = 0xAA; + send[1] = 0x0E; + send[2] = commandId; + send[3] = 0x00; // ACK counter is not used. + send[4] = (packageId >> 0) & 0xff; + send[5] = (packageId >> 8) & 0xff; + if (!SENDFUNC(send, sizeof(send))) { + return (ErrorNumber)SendRegisterTimeout; + } + return (ErrorNumber)NoError; +} + +/** + * Receive ACK or NCK. + * + * @return Error number. + */ +CameraC328::ErrorNumber CameraC328::recvAckOrNck() { + char recv[COMMAND_LENGTH]; + if (!RECVFUNC(recv, sizeof(recv))) { + return (ErrorNumber)UnexpectedReply; + } + if ((0xAA == recv[0]) && (0x0E == recv[1])) { + return (ErrorNumber)NoError; + } + if ((0xAA == recv[0]) && (0x0F == recv[1])) { + return (ErrorNumber)recv[4]; + } + return (ErrorNumber)UnexpectedReply; +} + +/** * Send bytes to camera module. * * @param buf Pointer to the data buffer. @@ -182,13 +395,13 @@ * * @return True if the data sended. */ -bool CameraC328::sendBytes(char *buf, size_t len) { +bool CameraC328::sendBytes(char *buf, size_t len, int timeout_us) { for (uint32_t i = 0; i < (uint32_t)len; i++) { int cnt = 0; while (!serial.writeable()) { - wait(0.000001); + wait_us(1); cnt++; - if (TIMEOUT_US < cnt) { + if (timeout_us < cnt) { return false; } } @@ -198,56 +411,6 @@ } /** - * Send bytes to camera module. - * - * @param buf Pointer to the data buffer. - * @param len Length of the data buffer. - * - * @return True if the data sended. - */ -bool CameraC328::sendBytesWithDebugOutput(char *buf, size_t len) { - debout.printf("SEND : "); - for (uint32_t i = 0; i < (uint32_t)len; i++) { - int cnt = 0; - while (!serial.writeable()) { - wait(0.000001); - cnt++; - if (TIMEOUT_US < cnt) { - debout.printf(" [Timed out]\n"); - return false; - } - } - serial.putc(buf[i]); - debout.printf(" %02X", buf[i]); - } - debout.printf(" [OK]\n"); - return true; -} - -/** - * Receive bytes from camera module. - * - * @param buf Pointer to the data buffer. - * @param len Length of the data buffer. - * - * @return True if the data received. - */ -bool CameraC328::recvBytes(char *buf, size_t len) { - for (uint32_t i = 0; i < (uint32_t)len; i++) { - int cnt = 0; - while (!serial.readable()) { - wait(0.000001); - cnt++; - if (TIMEOUT_US < cnt) { - return false; - } - } - buf[i] = serial.getc(); - } - return true; -} - -/** * Receive bytes from camera module. * * @param buf Pointer to the data buffer. @@ -255,21 +418,28 @@ * * @return True if the data received. */ -bool CameraC328::recvBytesWithDebugOutput(char *buf, size_t len) { - debout.printf("RECV : "); +bool CameraC328::recvBytes(char *buf, size_t len, int timeout_us) { for (uint32_t i = 0; i < (uint32_t)len; i++) { int cnt = 0; while (!serial.readable()) { - wait(0.000001); + wait_us(1); cnt++; - if (TIMEOUT_US < cnt) { - debout.printf(" [Timed out]\n"); + if (timeout_us < cnt) { return false; } } buf[i] = serial.getc(); - debout.printf(" %02X", buf[i]); } - debout.printf(" [OK]\n"); return true; } + +/** + * Wait received. + * + * @return True if the data received. + */ +bool CameraC328::waitRecv() { + while (!serial.readable()) { + } + return true; +} \ No newline at end of file