diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 92245fba..e3f8bc3e 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -203,6 +203,7 @@ add_example (ht9170) add_example (h3lis331dl) add_example (ad8232) add_example (grovescam) +add_example (scam) add_example (m24lr64e) add_example (rgbringcoder) add_example (hp20x) diff --git a/examples/c++/scam.cxx b/examples/c++/scam.cxx new file mode 100644 index 00000000..a7afc73a --- /dev/null +++ b/examples/c++/scam.cxx @@ -0,0 +1,77 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include "scam.hpp" + +using namespace std; +using namespace upm; + +int main (int argc, char **argv) +{ +//! [Interesting] + + // Instantiate a Serial Camera on UART 0 + upm::SCAM* camera = new upm::SCAM(0); + + // make sure port is initialized properly. 115200 baud is the default. + if (!camera->setupTty()) + { + cerr << "Failed to setup tty port parameters" << endl; + return 1; + } + + if (camera->init()) + cout << "Initialized..." << endl; + else + cout << "init() failed" << endl; + + if (camera->preCapture()) + cout << "preCapture succeeded..." << endl; + else + cout << "preCapture failed." << endl; + + if (camera->doCapture()) + cout << "doCapture succeeded..." << endl; + else + cout << "doCapture failed." << endl; + + cout << "Image size is " << camera->getImageSize() << " bytes" << endl; + + if (camera->getImageSize() > 0) + { + cout << "Storing image.jpg..." << endl; + if (camera->storeImage("image.jpg")) + cout << "storeImage succeeded..." << endl; + else + cout << "storeImage failed." << endl; + } +//! [Interesting] + + delete camera; + return 0; +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index a3e0a84c..7395a5c3 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -49,6 +49,7 @@ add_example(GroveQTouch at42qt1070) add_example(RelaySample relay) add_example(RotarySample rotary) add_example(GROVESCAMSample grovescam) +add_example(SCAMSample scam) add_example(SlideSample slide) add_example(SpeakerSample speaker) add_example(TemperatureSample temperature) diff --git a/examples/java/SCAMSample.java b/examples/java/SCAMSample.java new file mode 100644 index 00000000..55078770 --- /dev/null +++ b/examples/java/SCAMSample.java @@ -0,0 +1,66 @@ +/* + * Author: Stefan Andritoiu + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +//NOT TESTED!!! +public class SCAMSample { + + public static void main(String[] args) throws InterruptedException { + // ! [Interesting] + // Instantiate a Serial Camera on UART 0 + upm_scam.SCAM camera = new upm_scam.SCAM(0); + + // make sure port is initialized properly. 115200 baud is the default. + if (!camera.setupTty()) { + System.err.println("Failed to setup tty port parameters"); + System.exit(-1); + } + + if (camera.init()) + System.out.println("Initialized..."); + else + System.out.println("Initialization failed"); + + if (camera.preCapture()) + System.out.println("preCapture succeeded..."); + else + System.out.println("preCapture failed."); + + if (camera.doCapture()) + System.out.println("doCapture succeeded..."); + else + System.out.println("doCapture failed."); + + if (camera.getImageSize() > 0) { + System.out.println("Storing image.jpg..."); + + if (camera.storeImage("image.jpg")) + System.out.println("storeImage succeeded..."); + else + System.out.println("storeImage failed."); + + } + // ! [Interesting] + } + +} diff --git a/examples/javascript/scam.js b/examples/javascript/scam.js new file mode 100644 index 00000000..a3664f5c --- /dev/null +++ b/examples/javascript/scam.js @@ -0,0 +1,69 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +var cameraObj = require('jsupm_scam'); + +// Instantiate a Serial Camera on UART 0 +var camera = new cameraObj.SCAM(0); + +// make sure port is initialized properly. 115200 baud is the default. +if (!camera.setupTty()) +{ + console.log("Failed to setup tty port parameters"); + process.exit(1); +} + +if (camera.init()) + console.log("Initialized..."); +else + console.log("init() failed"); + +if (camera.preCapture()) + console.log("preCapture succeeded..."); +else + console.log("preCapture failed."); + +if (camera.doCapture()) + console.log("doCapture succeeded..."); +else + console.log("doCapture failed."); + +console.log("Image size is " + camera.getImageSize() + " bytes"); + +if (camera.getImageSize() > 0) +{ + console.log("Storing image.jpg..."); + if (camera.storeImage("image.jpg")) + console.log("storeImage succeeded..."); + else + console.log("storeImage failed."); +} + + +camera = null; +cameraObj.cleanUp(); +cameraObj = null; +console.log("Exiting."); +process.exit(0); + diff --git a/examples/python/scam.py b/examples/python/scam.py new file mode 100644 index 00000000..fcbfc56b --- /dev/null +++ b/examples/python/scam.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# +# Author: Jon Trulson +# Copyright (c) 2015 Intel Corporation. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import sys +import pyupm_scam as upmscam + +# Instantiate a Serial Camera on UART 0 +camera = upmscam.SCAM(0) + +# make sure port is initialized properly. 115200 baud is the default. +if (not camera.setupTty()): + print "Failed to setup tty port parameters" + sys.exit(1) + +if (camera.init()): + print "Initialized..." +else: + print "init() failed" + +if (camera.preCapture()): + print "preCapture succeeded..." +else: + print "preCapture failed." + +if (camera.doCapture()): + print "doCapture succeeded..." +else: + print "doCapture failed." + +print "Image size is", camera.getImageSize(), "bytes" + +if (camera.getImageSize() > 0): + print "Storing image.jpg..." + if (camera.storeImage("image.jpg")): + print "storeImage succeeded..." + else: + print "storeImage failed." + +print "Exiting." +sys.exit(0) diff --git a/src/scam/CMakeLists.txt b/src/scam/CMakeLists.txt new file mode 100644 index 00000000..9d9fdee5 --- /dev/null +++ b/src/scam/CMakeLists.txt @@ -0,0 +1,5 @@ +upm_mixed_module_init (NAME scam + DESCRIPTION "UPM scam sensor module" + CPP_HDR scam.hpp + CPP_SRC scam.cxx + REQUIRES mraa) diff --git a/src/scam/javaupm_grovescam.i b/src/scam/javaupm_grovescam.i new file mode 100644 index 00000000..f061fddf --- /dev/null +++ b/src/scam/javaupm_grovescam.i @@ -0,0 +1,20 @@ +%module javaupm_scam +%include "../upm.i" +%include "../java_buffer.i" + +%{ + #include "scam.hpp" +%} + +%include "scam.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_scam"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/scam/jsupm_grovescam.i b/src/scam/jsupm_grovescam.i new file mode 100644 index 00000000..7a633b86 --- /dev/null +++ b/src/scam/jsupm_grovescam.i @@ -0,0 +1,8 @@ +%module jsupm_scam +%include "../upm.i" + +%{ + #include "scam.hpp" +%} + +%include "scam.hpp" diff --git a/src/scam/pyupm_grovescam.i b/src/scam/pyupm_grovescam.i new file mode 100644 index 00000000..b2747d4d --- /dev/null +++ b/src/scam/pyupm_grovescam.i @@ -0,0 +1,11 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_scam +%include "../upm.i" + +%feature("autodoc", "3"); + +%{ + #include "scam.hpp" +%} +%include "scam.hpp" diff --git a/src/scam/scam.cxx b/src/scam/scam.cxx new file mode 100644 index 00000000..83bfcccc --- /dev/null +++ b/src/scam/scam.cxx @@ -0,0 +1,490 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Thanks to Seeed Studio for a working arduino sketch + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "scam.hpp" + +using namespace upm; +using namespace std; + +static const int maxRetries = 100; + +SCAM::SCAM(int uart, uint8_t camAddr) +{ + m_ttyFd = -1; + + // save our shifted camera address, we'll need it a lot + m_camAddr = (camAddr << 5); + + m_picTotalLen = 0; + + if ( !(m_uart = mraa_uart_init(uart)) ) + { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_uart_init() failed"); + return; + } + + // This requires a recent MRAA (1/2015) + const char *devPath = mraa_uart_get_dev_path(m_uart); + + if (!devPath) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_uart_get_dev_path() failed"); + return; + } + + // now open the tty + if ( (m_ttyFd = open(devPath, O_RDWR)) == -1) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": open of " + + string(devPath) + " failed:" + + string(strerror(errno))); + return; + } +} + +SCAM::~SCAM() +{ + if (m_ttyFd != -1) + close(m_ttyFd); +} + +bool SCAM::dataAvailable(unsigned int millis) +{ + if (m_ttyFd == -1) + return false; + + struct timeval timeout; + + if (millis == 0) + { + // no waiting + timeout.tv_sec = 0; + timeout.tv_usec = 0; + } + else + { + timeout.tv_sec = millis / 1000; + timeout.tv_usec = (millis % 1000) * 1000; + } + + int nfds; + fd_set readfds; + + FD_ZERO(&readfds); + + FD_SET(m_ttyFd, &readfds); + + if (select(m_ttyFd + 1, &readfds, NULL, NULL, &timeout) > 0) + return true; // data is ready + else + return false; +} + +int SCAM::readData(uint8_t *buffer, int len) +{ + if (m_ttyFd == -1) + return(-1); + + int rv = read(m_ttyFd, (char *)buffer, len); + + if (rv < 0) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": read() failed: " + + string(strerror(errno))); + return rv; + } + + return rv; +} + +int SCAM::writeData(uint8_t *buffer, int len) +{ + if (m_ttyFd == -1) + return(-1); + + // first, flush any pending but unread input + + tcflush(m_ttyFd, TCIFLUSH); + + int rv = write(m_ttyFd, (char *)buffer, len); + + if (rv < 0) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": write() failed: " + + string(strerror(errno))); + return rv; + } + + tcdrain(m_ttyFd); + + return rv; +} + +bool SCAM::setupTty(speed_t baud) +{ + if (m_ttyFd == -1) + return(false); + + struct termios termio; + + // get current modes + tcgetattr(m_ttyFd, &termio); + + // setup for a 'raw' mode. 81N, no echo or special character + // handling, such as flow control. + cfmakeraw(&termio); + + // set our baud rates + cfsetispeed(&termio, baud); + cfsetospeed(&termio, baud); + + // make it so + if (tcsetattr(m_ttyFd, TCSAFLUSH, &termio) < 0) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": tcsetattr() failed: " + + string(strerror(errno))); + return false; + } + + return true; +} + +void SCAM::drainInput() +{ + uint8_t ch; + + while (dataAvailable(0)) + readData(&ch, 1); +} + +bool SCAM::init() +{ + const unsigned int pktLen = 6; + uint8_t cmd[pktLen] = {0xaa, static_cast(0x0d|m_camAddr), 0x00, + 0x00, 0x00, 0x00}; + uint8_t resp[pktLen]; + int retries = 0; + + while (true) + { + if (retries++ > maxRetries) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": maximum retries exceeded"); + return false; + } + + writeData(cmd, pktLen); + + if (!dataAvailable(500)) + continue; + + if (readData(resp, pktLen) != pktLen) + continue; + + if (resp[0] == 0xaa + && resp[1] == (0x0e | m_camAddr) + && resp[2] == 0x0d + && resp[4] == 0 + && resp[5] == 0) + { + if (readData(resp, pktLen) != pktLen) + continue; + else + { + if (resp[0] == 0xaa + && resp[1] == (0x0d | m_camAddr) + && resp[2] == 0 + && resp[3] == 0 + && resp[4] == 0 + && resp[5] == 0) + break; + } + } + } + + cmd[1] = 0x0e | m_camAddr; + cmd[2] = 0x0d; + writeData(cmd, pktLen); + + return true; +} + +bool SCAM::preCapture(PIC_FORMATS_T fmt) +{ + const unsigned int pktLen = 6; + uint8_t cmd[pktLen] = { 0xaa, static_cast(0x01 | m_camAddr), 0x00, + 0x07, 0x00, static_cast(fmt) }; + uint8_t resp[pktLen]; + int retries = 0; + + while (true) + { + if (retries++ > maxRetries) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": maximum retries exceeded"); + return false; + } + + drainInput(); + + writeData(cmd, pktLen); + + if (!dataAvailable(100)) + continue; + + if (readData(resp, pktLen) != pktLen) + continue; + + if (resp[0] == 0xaa + && resp[1] == (0x0e | m_camAddr) + && resp[2] == 0x01 + && resp[4] == 0 + && resp[5] == 0) break; + } + + return true; +} + +bool SCAM::doCapture() +{ + const unsigned int pktLen = 6; + uint8_t cmd[pktLen] = { 0xaa, static_cast(0x06 | m_camAddr), 0x08, + static_cast(MAX_PKT_LEN & 0xff), + static_cast((MAX_PKT_LEN >> 8)) & 0xff, 0}; + uint8_t resp[pktLen]; + int retries = 0; + + m_picTotalLen = 0; + + while (true) + { + if (retries++ > maxRetries) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": maximum retries exceeded"); + return false; + } + + drainInput(); + writeData(cmd, pktLen); + usleep(100000); + + if (!dataAvailable(100)) + continue; + + if (readData(resp, pktLen) != pktLen) + continue; + + if (resp[0] == 0xaa + && resp[1] == (0x0e | m_camAddr) + && resp[2] == 0x06 + && resp[4] == 0 + && resp[5] == 0) + break; + } + + cmd[1] = 0x05 | m_camAddr; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + cmd[5] = 0; + + retries = 0; + while (true) + { + if (retries++ > maxRetries) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": maximum retries exceeded"); + return false; + } + + drainInput(); + writeData(cmd, pktLen); + if (readData(resp, pktLen) != pktLen) + continue; + + if (resp[0] == 0xaa + && resp[1] == (0x0e | m_camAddr) + && resp[2] == 0x05 + && resp[4] == 0 + && resp[5] == 0) + break; + } + + cmd[1] = 0x04 | m_camAddr; + cmd[2] = 0x01; + + retries = 0; + while (true) + { + if (retries++ > maxRetries) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": maximum retries exceeded"); + return false; + } + + drainInput(); + writeData(cmd, 6); + + if (readData(resp, pktLen) != pktLen) + continue; + + if (resp[0] == 0xaa + && resp[1] == (0x0e | m_camAddr) + && resp[2] == 0x04 + && resp[4] == 0 + && resp[5] == 0) + { + if (!dataAvailable(1000)) + continue; + + if (readData(resp, pktLen) != pktLen) + continue; + + if (resp[0] == 0xaa + && resp[1] == (0x0a | m_camAddr) + && resp[2] == 0x01) + { + m_picTotalLen = (resp[3]) | (resp[4] << 8) | (resp[5] << 16); + break; + } + } + } + + return true; +} + +bool SCAM::storeImage(const char *fname) +{ + if (!fname) + { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": filename is NULL"); + return false; + } + + if (!m_picTotalLen) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": Picture length is zero, you need to capture first."); + + return false; + } + + FILE *file = fopen(fname, "wb"); + + if (!file) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": fopen() failed: " + + string(strerror(errno))); + return false; + } + + /// let the games begin... + const unsigned int pktLen = 6; + unsigned int pktCnt = (m_picTotalLen) / (MAX_PKT_LEN - 6); + if ((m_picTotalLen % (MAX_PKT_LEN-6)) != 0) + pktCnt += 1; + + uint8_t cmd[pktLen] = { 0xaa, static_cast(0x0e | m_camAddr), 0x00, + 0x00, 0x00, 0x00 }; + uint8_t pkt[MAX_PKT_LEN]; + int retries = 0; + + for (unsigned int i = 0; i < pktCnt; i++) + { + cmd[4] = i & 0xff; + cmd[5] = (i >> 8) & 0xff; + + retries = 0; + + retry: + + usleep(10000); + + drainInput(); + writeData(cmd, pktLen); + + if (!dataAvailable(1000)) + { + if (retries++ > maxRetries) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": timeout, maximum retries exceeded"); + return false; + } + goto retry; + } + + uint16_t cnt = readData(pkt, MAX_PKT_LEN); + + unsigned char sum = 0; + for (int y = 0; y < cnt - 2; y++) + { + sum += pkt[y]; + } + if (sum != pkt[cnt-2]) + { + if (retries++ <= maxRetries) + goto retry; + else + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": cksum error, maximum retries exceeded"); + return false; + } + } + + fwrite((const uint8_t *)&pkt[4], cnt - 6, 1, file); + } + + cmd[4] = 0xf0; + cmd[5] = 0xf0; + writeData(cmd, pktLen); + + fclose(file); + + // reset the pic length to 0 for another run. + m_picTotalLen = 0; + + return true; +} diff --git a/src/scam/scam.hpp b/src/scam/scam.hpp new file mode 100644 index 00000000..929c0145 --- /dev/null +++ b/src/scam/scam.hpp @@ -0,0 +1,194 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Thanks to Seeed Studio for a working arduino sketch + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SCAM_DEFAULT_UART 0 + +#define SCAM_DEFAULT_CAMERA_ADDR 0 + +namespace upm { + /** + * @brief Serial Camera library + * @defgroup scam libupm-scam + * @ingroup seeed uart other + */ + + /** + * @library scam + * @sensor scam + * @comname Serial Camera + * @type other + * @man seeed + * @con uart + * @web http://www.seeedstudio.com/wiki/Grove_-_Serial_Camera_Kit + * + * @brief API for the Serial Camera + * + * The driver was tested with the Serial Camera. There is + * no protocol documentation currently available, so this module + * was developed based completely on the Seeed Studio* Arduino* + * sketch. + * + * It is connected via a UART at 115,200 baud. + * + * @image html scam.jpg + * @snippet scam.cxx Interesting + */ + + class SCAM { + public: + + static const unsigned int MAX_PKT_LEN = 128; + + typedef enum { + FORMAT_VGA = 7, // 640x480 + FORMAT_CIF = 5, // 352×288 + FORMAT_OCIF = 3 // ??? (maybe they meant QCIF?) + } PIC_FORMATS_T; + + /** + * Serial Camera constructor + * + * @param uart Default UART to use (0 or 1) + * @param camAddr 3-bit address identifier of the camera; default is 0 + */ + SCAM(int uart, uint8_t camAddr=SCAM_DEFAULT_CAMERA_ADDR); + + /** + * SCAM destructor + */ + ~SCAM(); + + /** + * Checks to see if there is data available for reading + * + * @param millis Number of milliseconds to wait; 0 means no waiting. + * @return True if there is data available for reading + */ + bool dataAvailable(unsigned int millis); + + /** + * Reads any available data into a user-supplied buffer. Note: the + * call blocks until data is available to be read. Use + * dataAvailable() to determine whether there is data available + * beforehand, to avoid blocking. + * + * @param buffer Buffer to hold the data read + * @param len Length of the buffer + * @return Number of bytes read + */ + int readData(uint8_t *buffer, int len); + + /** + * Writes the data in the buffer to the device + * + * @param buffer Buffer to hold the data read + * @param len Length of the buffer + * @return Number of bytes written + */ + int writeData(uint8_t *buffer, int len); + + /** + * Sets up proper tty I/O modes and the baud rate. For this device, the default + * baud rate is 9,600 (B9600). + * + * @param baud Desired baud rate + * @return True if successful + */ + bool setupTty(speed_t baud=B115200); + + /** + * Reads serial input and discards until no more characters are available + * + */ + void drainInput(); + + /** + * Initializes the camera + * + */ + bool init(); + + /** + * Tells the camera to prepare for a capture + * + * @param fmt One of the PIC_FORMATS_T values + */ + bool preCapture(PIC_FORMATS_T fmt=FORMAT_VGA); + + /** + * Starts the capture + * + * @return True if successful + */ + bool doCapture(); + + /** + * Stores the captured image in a file + * + * @param fname Name of the file to write + * @return True if successful + */ + bool storeImage(const char *fname); + + /** + * Returns the picture length. Note: this is only valid after + * doCapture() has run successfully. + * + * @return Image length + */ + int getImageSize() { return m_picTotalLen; }; + + protected: + int ttyFd() { return m_ttyFd; }; + + private: + mraa_uart_context m_uart; + int m_ttyFd; + + uint8_t m_camAddr; + int m_picTotalLen; + }; +} + +