Compare commits

..

19 Commits

Author SHA1 Message Date
cde747439f upm: v1.0.2
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
2016-12-08 15:47:13 -08:00
dfc7a710d4 firmata: extended data types on pins to allow subplatform usage
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
2016-12-08 15:10:36 -08:00
130cb822e4 rf22: Initial implementation for RFM22B radios, C++ only & bindings
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
2016-12-07 14:38:56 -08:00
c057fa6708 travis.yml: use different swig ppa for Travis CI builds
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
2016-12-06 19:33:00 -08:00
c6ad8cb5ee utilities: use a better method for detecting zephyr kernel version
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-12-05 15:04:34 -07:00
024b43dfa3 utilities: fix new Zephyr k_timer based implementation
- Fixed the Zephyr kernel version checks to check for 0.1.6 rather
  than 1.6.0.
- fixed the k_timer implementation to actually work.  None of these
  were being called correctly.
- due to the fact that the k_timer API only has a 1ms resolution,
  re-implement upm_delay_us() (on 0.1.6 version of zephyr) as a busy
  loop using a upm_clock_t.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-12-05 13:41:19 -07:00
6667646d32 mb704x: Initial implementation; C; FTI; C++ wraps C
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-12-02 16:44:43 -07:00
e1e9067744 groups.md: Add MaxBotix manufacturer
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-12-02 16:44:43 -07:00
c4656bf8ba utilities: add Zephyr 1.6 k_timer support (pulled from zupm)
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-12-02 16:44:43 -07:00
232089f400 cmake: Check for JAVA in top-level CMakeLists.txt
Moved require for Java/JNI/mraajava to top-level CMakeLists.txt
which will fail early if these are NOT found (vs failing in
the src-level CMakeLists.txt

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-29 15:14:32 -08:00
09144e712b cmake: Consolidated BUILDJAVAEXAMPLES and BUILDEXAMPLES
The java examples will now build if BUILDSWIGJAVA=on and
BUILDEXAMPLES=on.  This is similar to the C/C++ examples.

    * Replaced BUILDJAVAEXAMPLES w/BUILDEXAMPLES
    * Updated docs
    * Updated travis-ci

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-29 12:25:25 -08:00
2d94c2ed90 travis-ci: Turn on FTI source compiling in travis-ci
* Build FTI source w/travis

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-29 11:49:52 -08:00
91652a2da5 button: fix so that button intr C example is built
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-11-29 12:02:26 -07:00
929244b27a ims: Fixed IMS java example
* Fixed a compile issue for the JAVA example
    * Added C header to swig java/js interface files

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-29 09:56:57 -08:00
9a4f0cae0c ims: Added FTI and java example
* Added compiling FTI for IMS
    * Updated JAVA example, added to CMakeLists.txt

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-29 08:51:45 -08:00
402de082d3 ecezo: make sure to mraa_init() in ecezo_uart_init()
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-11-28 18:23:18 -07:00
ad275e1d41 ecezo: initial implementation; C, C++; FTI + examples
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-11-28 17:45:23 -07:00
d4559878df cmake: Removed -dirty from VERSION if git_describe fails
* Removed -dirty
    * Also removed redundant set(PACK_PACKAGE_VERSION ...
      since the first gets overwritten by the second

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-22 15:03:14 -08:00
971cb4ab51 ims: Initial turnin of I2C Moisture Sensor
* Added C library
    * Added CXX library
    * Added C/CXX/java/js/python examples

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-11-21 14:57:15 -08:00
97 changed files with 5885 additions and 64 deletions

View File

@ -15,7 +15,7 @@ compiler:
- clang - clang
- gcc - gcc
install: install:
- sudo add-apt-repository --yes ppa:fenics-packages/fenics-dev/swig - sudo add-apt-repository --yes ppa:rosmo/swig3.0.7
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -y --force-yes -qq swig3.0 git - sudo apt-get install -y --force-yes -qq swig3.0 git
- sudo ln -s /usr/bin/swig3.0 /usr/bin/swig - sudo ln -s /usr/bin/swig3.0 /usr/bin/swig
@ -36,7 +36,7 @@ script:
- sudo make install - sudo make install
- sudo ldconfig - sudo ldconfig
# Build/install UPM # Build/install UPM
- cd $UPM_ROOT && mkdir $UPM_BUILD && cd $_ && cmake -DNODE_ROOT_DIR:PATH="${NODE_ROOT_DIR}" -DBUILDSWIGJAVA=$BUILDJAVA -DBUILDEXAMPLES=ON -DBUILDJAVAEXAMPLES=$BUILDJAVA -DBUILDTESTS=ON .. && sudo make install && sudo ldconfig && ctest --output-on-failure -E examplenames_js - cd $UPM_ROOT && mkdir $UPM_BUILD && cd $_ && cmake -DNODE_ROOT_DIR:PATH="${NODE_ROOT_DIR}" -DBUILDSWIGJAVA=$BUILDJAVA -DBUILDEXAMPLES=ON -DBUILDTESTS=ON -DBUILDFTI=ON .. && sudo make install && sudo ldconfig && ctest --output-on-failure -E examplenames_js
addons: addons:
apt: apt:
sources: sources:

View File

@ -8,8 +8,7 @@ option (BUILDFTI "Build Funtion Table Interface (FTI) in C sensor libraries" OFF
option (BUILDSWIGPYTHON "Build swig python modules" ON) option (BUILDSWIGPYTHON "Build swig python modules" ON)
option (BUILDSWIGNODE "Build swig node modules" ON) option (BUILDSWIGNODE "Build swig node modules" ON)
option (BUILDSWIGJAVA "Build swig java modules" OFF) option (BUILDSWIGJAVA "Build swig java modules" OFF)
option (BUILDEXAMPLES "Build C/C++ example binaries" OFF) option (BUILDEXAMPLES "Build C/C++/JAVA examples" OFF)
option (BUILDJAVAEXAMPLES "Build java example jars" OFF)
option (IPK "Generate IPK using CPack" OFF) option (IPK "Generate IPK using CPack" OFF)
option (RPM "Generate RPM using CPack" OFF) option (RPM "Generate RPM using CPack" OFF)
option (NPM "Generate NPM/GYP tarballs" OFF) option (NPM "Generate NPM/GYP tarballs" OFF)
@ -139,6 +138,13 @@ if (BUILDSWIGNODE)
find_package (Node REQUIRED) find_package (Node REQUIRED)
endif (BUILDSWIGNODE) endif (BUILDSWIGNODE)
# Find JAVA/JNI
if (BUILDSWIGJAVA)
find_package (Java REQUIRED)
find_package (JNI REQUIRED)
pkg_check_modules (MRAAJAVA REQUIRED mraajava>=0.8.0)
endif (BUILDSWIGJAVA)
# Find swig if any wrapper is enabled # Find swig if any wrapper is enabled
if (BUILDSWIGPYTHON OR BUILDSWIGNODE OR BUILDSWIGJAVA) if (BUILDSWIGPYTHON OR BUILDSWIGNODE OR BUILDSWIGJAVA)
find_package (SWIG 3.0.5 REQUIRED) find_package (SWIG 3.0.5 REQUIRED)
@ -187,7 +193,7 @@ include (GetGitRevisionDescription)
git_describe (VERSION "--tags") git_describe (VERSION "--tags")
# If git_describe fails, use a dirty version # If git_describe fails, use a dirty version
if (${VERSION} MATCHES -NOTFOUND) if (${VERSION} MATCHES -NOTFOUND)
set (VERSION "v1.0.1-dirty") set (VERSION "v1.0.2")
message (WARNING "Failed to retrieve UPM version with 'git describe' (using " message (WARNING "Failed to retrieve UPM version with 'git describe' (using "
"${VERSION}). Check that git is installed and this is a valid git repo.") "${VERSION}). Check that git is installed and this is a valid git repo.")
endif () endif ()
@ -381,7 +387,6 @@ endif()
if (RPM) if (RPM)
message (STATUS "RPM packaging enabled for ${DETECTED_ARCH}") message (STATUS "RPM packaging enabled for ${DETECTED_ARCH}")
set(CPACK_PACKAGE_VERSION ${VERSION})
set(CPACK_GENERATOR "RPM") set(CPACK_GENERATOR "RPM")
set(CPACK_PACKAGE_NAME "upm") set(CPACK_PACKAGE_NAME "upm")
set(upm_PACKAGE_ON_TAG ".") set(upm_PACKAGE_ON_TAG ".")
@ -418,7 +423,8 @@ if(BUILDEXAMPLES)
endif(BUILDCPP) endif(BUILDCPP)
endif() endif()
if(BUILDJAVAEXAMPLES) # Build java examples
if(BUILDSWIGJAVA AND BUILDEXAMPLES)
add_subdirectory (examples/java) add_subdirectory (examples/java)
endif() endif()

View File

@ -80,14 +80,10 @@ Building documentation
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
-DBUILDDOC=ON -DBUILDDOC=ON
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
Build C++ example binaries Build C/C++/JAVA examples
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
-DBUILDEXAMPLES=ON -DBUILDEXAMPLES=ON
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
Build Java examples
~~~~~~~~~~~~~
-DBUILDJAVAEXAMPLES=ON
~~~~~~~~~~~~~
If you intend to turn on all the options and build everything at once If you intend to turn on all the options and build everything at once
(C++, Java, Node, Python and Documentation) you will have to edit the (C++, Java, Node, Python and Documentation) you will have to edit the

View File

@ -4,6 +4,15 @@ Changelog {#changelog}
Here's a list summarizing some of the key undergoing changes to our library Here's a list summarizing some of the key undergoing changes to our library
from earlier versions: from earlier versions:
### v1.0.2
* Minor cmake changes for Java builds and Java examples are now toggled with
the same BUILDEXAMPLES cmake switch
* Made some improvements in the utilities class for our C drivers
* Fixed issue with some drivers not being usable on subplatforms due to pin
numbers using uint8 type
* New sensors: ims, ecezo, mb704x, rf22
### v1.0.1 ### v1.0.1
* Warnings as errors enabled for C/CXX (fixed warnings from -Wall and others) * Warnings as errors enabled for C/CXX (fixed warnings from -Wall and others)

BIN
docs/images/ims.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
docs/images/rf22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

View File

@ -24,6 +24,7 @@ hcsr04.cxx HCSR04Sample.java hcsr04.js hcsr04.py
hm11.cxx HM11Sample.java hm11.js hm11.py hm11.cxx HM11Sample.java hm11.js hm11.py
hmc5883l.cxx Hmc5883lSample.java hmc5883l.js hmc5883l.py hmc5883l.cxx Hmc5883lSample.java hmc5883l.js hmc5883l.py
htu21d.cxx HTU21DSample.java htu21d.js htu21d.py htu21d.cxx HTU21DSample.java htu21d.js htu21d.py
ims.cxx IMS_Example.java ims.js ims.py
itg3200.cxx Itg3200Sample.java itg3200.js itg3200.py itg3200.cxx Itg3200Sample.java itg3200.js itg3200.py
jhd1313m1-lcd.cxx Jhd1313m1_lcdSample.java jhd1313m1-lcd.js jhd1313m1-lcd.py jhd1313m1-lcd.cxx Jhd1313m1_lcdSample.java jhd1313m1-lcd.js jhd1313m1-lcd.py
joystick12.cxx Joystick12Sample.java joystick12.js joystick12.py joystick12.cxx Joystick12Sample.java joystick12.js joystick12.py

View File

@ -322,6 +322,11 @@ add_example (dfrorp)
add_example (dfrec) add_example (dfrec)
add_example (sht1x) add_example (sht1x)
add_example (ms5803) add_example (ms5803)
add_example (ims)
add_example (ecezo)
add_example (mb704x)
add_example (rf22-server)
add_example (rf22-client)
# These are special cases where you specify example binary, source file and module(s) # These are special cases where you specify example binary, source file and module(s)
include_directories (${PROJECT_SOURCE_DIR}/src) include_directories (${PROJECT_SOURCE_DIR}/src)

81
examples/c++/ecezo.cxx Normal file
View File

@ -0,0 +1,81 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <signal.h>
#include <upm_utilities.h>
#include <ecezo.hpp>
using namespace std;
using namespace upm;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a ECEZO sensor on uart 0 at 9600 baud.
upm::ECEZO *sensor = new upm::ECEZO(0, 9600, false);
// For I2C, assuming the device is configured for address 0x64 on
// I2C bus 0, you could use something like:
//
// upm::ECEZO *sensor = new upm::ECEZO(0, 0x64, true);
while (shouldRun)
{
// this will take about 1 second to complete
sensor->update();
cout << "EC "
<< sensor->getEC()
<< " uS/cm, TDS "
<< sensor->getTDS()
<< " mg/L, Salinity "
<< sensor->getSalinity()
<< " PSS-78, SG "
<< sensor->getSG()
<< endl;
upm_delay(5);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

69
examples/c++/ims.cxx Normal file
View File

@ -0,0 +1,69 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "ims.hpp"
using namespace upm;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a IMS instance using i2c bus 0 and default address
upm::IMS sensor(0);
while (shouldRun)
{
std::cout << "Version: "
<< sensor.get_version()
<< " light: "
<< sensor.get_light()
<< " moisture: "
<< sensor.get_moisture()
<< " temp: "
<< sensor.get_temperature()
<< " C"
<< std::endl;
sleep(1);
}
//! [Interesting]
std::cout << "Exiting..." << std::endl;
return 0;
}

70
examples/c++/mb704x.cxx Normal file
View File

@ -0,0 +1,70 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <signal.h>
#include <upm_utilities.h>
#include <mb704x.hpp>
using namespace std;
using namespace upm;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a MB704X sensor using default parameters (bus 0,
// address 112)
upm::MB704X *sensor = new upm::MB704X();
while (shouldRun)
{
cout << "Range: "
<< sensor->getRange()
<< " cm"
<< endl;
upm_delay_ms(500);
}
cout << "Exiting..." << endl;
delete sensor;
//! [Interesting]
return 0;
}

View File

@ -0,0 +1,72 @@
/*
* Author: Kiveisha Yevgeniy
* Copyright (c) 2015-2016 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 <iostream>
#include <signal.h>
#include "rf22.hpp"
bool amWorking = true;
void
sig_handler (int signo) {
if (signo == SIGINT) {
amWorking = false;
}
}
//! [Interesting]
int
main (int argc, char ** argv) {
// SPI bus 0, CS pin 10, INTR pin 2
upm::RF22* rf22 = new upm::RF22 (0, 10, 2);
if (!rf22->init()) {
std::cout << "RF22 init failed" << std::endl;
return 0x1;
}
uint8_t data[] = "Hello World!";
uint8_t buf[RF22_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
signal (SIGINT, sig_handler);
while (amWorking) {
std::cout << "Sending to rf22_server" << std::endl;
// Send a message to rf22_server
rf22->send(data, sizeof(data));
rf22->waitPacketSent();
// Now wait for a reply
rf22->waitAvailableTimeout(1000000);
if (rf22->recv(buf, &len)) {
std::cout << "got response: " << (char*)buf << std::endl;
} else {
std::cout << "!!! NO RESPONSE !!!" << std::endl;
}
}
std::cout << "Exit 'rfm22-client'" << std::endl;
return 0;
}
//! [Interesting]

View File

@ -0,0 +1,73 @@
/*
* Author: Kiveisha Yevgeniy
* Copyright (c) 2015-2016 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 <iostream>
#include <signal.h>
#include "rf22.hpp"
bool amWorking = true;
void
sig_handler (int signo) {
if (signo == SIGINT) {
amWorking = false;
}
}
//! [Interesting]
int
main (int argc, char ** argv) {
// SPI bus 0, CS pin 10, INTR pin 2
upm::RF22* rf22 = new upm::RF22 (0, 10, 2);
if (!rf22->init()) {
std::cout << "RF22 init failed" << std::endl;
return 0x1;
}
uint8_t buf[RF22_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
signal (SIGINT, sig_handler);
while (amWorking) {
// rf22->waitAvailable();
rf22->waitAvailableTimeout (500);
// Should be a message for us now
if (rf22->recv(buf, &len)) {
std::cout << "got request: " << (char*)buf << std::endl;
// Send a reply
uint8_t data[] = "And hello back to you";
rf22->send(data, sizeof(data));
rf22->waitPacketSent();
} else {
// Do whatever you need.
}
}
delete rf22;
std::cout << "Exit 'rfm22-server'" << std::endl;
return 0;
}
//! [Interesting]

View File

@ -23,7 +23,7 @@ macro(add_custom_example example_bin example_src example_module_list)
set(found_all_modules FALSE) set(found_all_modules FALSE)
endif() endif()
if (MODULE_LIST) if (MODULE_LIST)
list(FIND MODULE_LIST ${module}-c index) list(FIND MODULE_LIST ${module} index)
if (${index} EQUAL -1) if (${index} EQUAL -1)
set(found_all_modules FALSE) set(found_all_modules FALSE)
endif() endif()
@ -136,9 +136,11 @@ add_example (ppd42ns)
add_example (guvas12d) add_example (guvas12d)
add_example (otp538u) add_example (otp538u)
add_example (button) add_example (button)
add_example (button_intr)
add_example (my9221) add_example (my9221)
add_example (ms5803) add_example (ms5803)
add_example (ims)
add_example (ecezo)
add_example (mb704x)
# Custom examples # Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)
@ -146,3 +148,4 @@ add_custom_example (lcm1602-i2c-example-c lcm1602-i2c.c lcm1602)
add_custom_example (lcm1602-parallel-example-c lcm1602-parallel.c lcm1602) add_custom_example (lcm1602-parallel-example-c lcm1602-parallel.c lcm1602)
add_custom_example (rpr220-intr-example-c rpr220-intr.c rpr220) add_custom_example (rpr220-intr-example-c rpr220-intr.c rpr220)
add_custom_example (md-stepper-example-c md-stepper.c md) add_custom_example (md-stepper-example-c md-stepper.c md)
add_custom_example (button_intr-example-c button_intr.c button)

85
examples/c/ecezo.c Normal file
View File

@ -0,0 +1,85 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <signal.h>
#include <upm_utilities.h>
#include <ecezo.h>
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a ECEZO sensor on uart 0 at 9600 baud.
ecezo_context sensor = ecezo_uart_init(0, 9600);
// For I2C, assuming the device is configured for address 0x64 on
// I2C bus 0, you could use something like:
//
// ecezo_context sensor = ecezo_i2c_init(0, 0x64);
if (!sensor)
{
printf("ecezo_init() failed.\n");
return 1;
}
while (shouldRun)
{
// this will take about 1 second to complete
if (ecezo_update(sensor))
{
printf("ecezo_update() failed\n");
}
else
{
printf("EC %f uS/cm, TDS %f mg/L, Salinity %f PSS-78, SG %f\n",
ecezo_get_ec(sensor),
ecezo_get_tds(sensor),
ecezo_get_salinity(sensor),
ecezo_get_sg(sensor));
}
upm_delay(5);
}
//! [Interesting]
printf("Exiting\n");
ecezo_close(sensor);
return 0;
}

75
examples/c/ims.c Normal file
View File

@ -0,0 +1,75 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* Copyright (c) 2016 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 <unistd.h>
#include <stdio.h>
#include <signal.h>
#include "ims.h"
#include "upm_utilities.h"
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
ims_context* sensor = ims_init(0, IMS_ADDRESS_DEFAULT);
if (!sensor)
{
printf("ims_init() failed\n");
return 1;
}
// Every second, sample the sensor outputs
while (shouldRun)
{
uint16_t version, light, moisture, temp;
if (ims_get_version(sensor, &version) == UPM_SUCCESS &&
ims_get_light(sensor, &light) == UPM_SUCCESS &&
ims_get_moisture(sensor, &moisture) == UPM_SUCCESS &&
ims_get_temperature(sensor, &temp) == UPM_SUCCESS)
printf("Version: %d light: 0x%04x moisture: 0x%04x temp: %3.2f C\n",
version, light, moisture, temp/10.0);
else
break;
upm_delay(1);
}
//! [Interesting]
printf("Exiting\n");
ims_close(sensor);
return 0;
}

77
examples/c/mb704x.c Normal file
View File

@ -0,0 +1,77 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <signal.h>
#include <upm_utilities.h>
#include <mb704x.h>
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a MB704X sensor on i2c bus 0, address 112.
mb704x_context sensor = mb704x_init(0, 112);
if (!sensor)
{
printf("mb704x_init() failed.\n");
return 1;
}
while (shouldRun)
{
// this will take about 1 second to complete
int range = mb704x_get_range(sensor);
if (range < 0)
{
printf("Error getting range.\n");
}
else
{
printf("Range: %d cm\n", range);
}
upm_delay_ms(500);
}
printf("Exiting\n");
mb704x_close(sensor);
//! [Interesting]
return 0;
}

View File

@ -157,6 +157,9 @@ add_example(DFRORP_Example dfrorp)
add_example(DFREC_Example dfrec) add_example(DFREC_Example dfrec)
add_example(SHT1X_Example sht1x) add_example(SHT1X_Example sht1x)
add_example(MS5803_Example ms5803) add_example(MS5803_Example ms5803)
add_example(ECEZO_Example ecezo)
add_example(IMS_Example ims)
add_example(MB704X_Example mb704x)
add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd) add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd)
add_example_with_path(Jhd1313m1Sample lcd i2clcd) add_example_with_path(Jhd1313m1Sample lcd i2clcd)

View File

@ -0,0 +1,60 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 upm_ecezo.ECEZO;
public class ECEZO_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a ECEZO sensor on uart 0 at 9600 baud.
ECEZO sensor = new ECEZO(0, 9600, false);
// For I2C, assuming the device is configured for address 0x64 on
// I2C bus 0, you could use something like:
//
// ECEZO sensor = new ECEZO(0, 0x64, true);
while (true)
{
// update our values from the sensor
sensor.update();
System.out.println("EC "
+ sensor.getEC()
+ " uS/cm, TDS "
+ sensor.getTDS()
+ " mg/L, Salinity "
+ sensor.getSalinity()
+ " PSS-78, SG "
+ sensor.getSG());
Thread.sleep(5000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,53 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* Copyright (c) 2016 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 upm_ims.IMS;
public class IMS_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a IMS instance using bus 0 and default i2c address
IMS sensor = new IMS((short)0);
while (true)
{
System.out.println("Version: "
+ sensor.get_version()
+ " light: "
+ sensor.get_light()
+ " moisture: "
+ sensor.get_moisture()
+ " temp: "
+ sensor.get_temperature()
+ " C");
Thread.sleep(1000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,48 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 upm_mb704x.MB704X;
public class MB704X_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a MB704X sensor using default parameters (bus 0,
// address 112)
MB704X sensor = new MB704X();
while (true)
{
System.out.println("Range: "
+ sensor.getRange()
+ " cm");
Thread.sleep(500);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,59 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 sensorObj = require('jsupm_ecezo');
// Instantiate a ECEZO sensor on uart 0 at 9600 baud.
var sensor = new sensorObj.ECEZO(0, 9600, false);
// For I2C, assuming the device is configured for address 0x64 on
// I2C bus 0, you could use something like:
//
// var sensor = new sensorObj.ECEZO(0, 0x64, true);
setInterval(function()
{
// update our values from the sensor
sensor.update();
console.log("EC "
+ sensor.getEC()
+ " uS/cm, TDS "
+ sensor.getTDS()
+ " mg/L, Salinity "
+ sensor.getSalinity()
+ " PSS-78, SG "
+ sensor.getSG());
}, 5000);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,51 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* Copyright (c) 2016 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 sensorObj = require('jsupm_ims');
// Instantiate a IMS instance using bus 0 and default i2c address
var sensor = new sensorObj.IMS(0);
setInterval(function()
{
console.log("Version: "
+ sensor.get_version()
+ " light: "
+ sensor.get_light()
+ " moisture: "
+ sensor.get_moisture()
+ " temp: "
+ sensor.get_temperature().toFixed(2)
+ " C");
}, 1000);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,47 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 sensorObj = require('jsupm_mb704x');
// Instantiate a MB704X sensor using default parameters (bus 0,
// address 112)
var sensor = new sensorObj.MB704X();
setInterval(function()
{
console.log("Range: "
+ sensor.getRange()
+ " cm");
}, 500);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

66
examples/python/ecezo.py Executable file
View File

@ -0,0 +1,66 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
from __future__ import print_function
import time, sys, signal, atexit
from upm import pyupm_ecezo as sensorObj
def main():
# Instantiate a ECEZO sensor on uart 0 at 9600 baud.
sensor = sensorObj.ECEZO(0, 9600, False);
# For I2C, assuming the device is configured for address 0x64 on
# I2C bus 0, you could use something like:
#
# sensor = sensorObj.ECEZO(0, 0x64, True);
## Exit handlers ##
# This function stops python from printing a stacktrace when you
# hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit
def exitHandler():
print("Exiting")
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
while (1):
sensor.update()
print("EC "
+ str(sensor.getEC())
+ " uS/cm, TDS "
+ str(sensor.getTDS())
+ " mg/L, Salinity "
+ str(sensor.getSalinity())
+ " PSS-78, SG "
+ str(sensor.getSG()));
time.sleep(5)
if __name__ == '__main__':
main()

44
examples/python/ims.py Executable file
View File

@ -0,0 +1,44 @@
#!/usr/bin/python
# Author: Noel Eck <noel.eck@intel.com>
# Copyright (c) 2016 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.
from __future__ import print_function
import time, sys, signal, atexit
from upm import pyupm_ims
def main():
# Create an instance of the I2C Moisture Sensor
# I2C bus 0, default address = 0x20
ims = pyupm_ims.IMS(0)
print ('I2C moisture sensor example...')
while (1):
try:
print ('Version: %d light: 0x%04x moisture: 0x%04x temp: %3.2f C' \
% (ims.get_version(), ims.get_light(), ims.get_moisture(),
ims.get_temperature()))
time.sleep(1)
except KeyboardInterrupt:
break
if __name__ == '__main__':
main()

56
examples/python/mb704x.py Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
from __future__ import print_function
import time, sys, signal, atexit
from upm import pyupm_mb704x as sensorObj
def main():
# Instantiate a MB704X sensor using default parameters (bus 0,
# address 112)
sensor = sensorObj.MB704X();
## Exit handlers ##
# This function stops python from printing a stacktrace when you
# hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit
def exitHandler():
print("Exiting")
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
while (1):
print("Range: "
+ str(sensor.getRange())
+ " cm")
time.sleep(.5)
if __name__ == '__main__':
main()

View File

@ -221,9 +221,6 @@ endmacro(upm_swig_node)
macro(upm_swig_java) macro(upm_swig_java)
# Skip if the libname is in the blacklist # Skip if the libname is in the blacklist
if (NOT ";${JAVASWIG_BLACKLIST};" MATCHES ";${libname};") if (NOT ";${JAVASWIG_BLACKLIST};" MATCHES ";${libname};")
FIND_PACKAGE (JNI REQUIRED)
pkg_check_modules (MRAAJAVA REQUIRED mraajava>=0.8.0)
include_directories ( include_directories (
${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}
${JAVA_INCLUDE_PATH2} ${JAVA_INCLUDE_PATH2}

9
src/ecezo/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
upm_mixed_module_init (NAME ecezo
DESCRIPTION "EC EZO Atlas Scientific EC circuit"
C_HDR ecezo.h ecezo_defs.h
C_SRC ecezo.c
CPP_HDR ecezo.hpp
CPP_SRC ecezo.cxx
FTI_SRC ecezo_fti.c
CPP_WRAPS_C
REQUIRES mraa)

674
src/ecezo/ecezo.c Normal file
View File

@ -0,0 +1,674 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <upm_utilities.h>
#include "ecezo.h"
// "Typical" command completion delay in ms
#define CMD_DELAY (350)
// uncomment for dubugging
//#define ECEZO_DEBUG (1)
// I2C read helper
static int readBytes(const ecezo_context dev, uint8_t *buffer, int len)
{
assert(dev != NULL);
assert(dev->i2c != NULL);
bool done = false;
int rv;
int retries = 10;
while (!done && (retries-- > 0))
{
if ((rv = mraa_i2c_read(dev->i2c, buffer, len)) < 0)
{
printf("%s: mraa_i2c_read(code) failed.\n", __FUNCTION__);
return rv;
}
#if defined(ECEZO_DEBUG)
printf("CODE: %02x\n", buffer[0]);
#endif
if (buffer[0] == 0xff || buffer[0] == 0x02)
{
// no data available, or error
return -1;
}
else if (buffer[0] == 0x01)
{
// data is ready
done = true;
// now we need to move the data one byte down so the rest
// of this driver can work as-is.
memmove(buffer, (buffer + 1), len - 1);
}
else
{
// buffer[0] 0xfe - data is pending. wait and loop again.
upm_delay_ms(CMD_DELAY);
}
}
if (retries <= 0)
{
printf("%s: timed out waiting for correct response.\n", __FUNCTION__);
return -1;
}
#if defined(ECEZO_DEBUG)
printf("%s: Got %d bytes\n", __FUNCTION__, rv);
for (int i=0; i<rv; i++)
{
printf("%02x (%c) ", buffer[i],
isprint(buffer[i]) ? buffer[i] : '@');
}
printf("\n");
#endif // ECEZO_DEBUG
return rv;
}
static upm_result_t generic_init(const ecezo_context dev)
{
assert(dev != NULL);
// do some generic initialization
bool error = false;
// turn off response (*OK) codes (UART only)
if (dev->uart)
{
if (ecezo_send_command(dev, "Response,0", NULL, 0) < 0)
error = true;
}
// turn off continuous sampling
if (ecezo_set_continuous(dev, false))
error = true;
// make sure all parameters are enabled
if (ecezo_send_command(dev, "O,EC,1", NULL, 0) < 0)
error = true;
if (ecezo_send_command(dev, "O,TDS,1", NULL, 0) < 0)
error = true;
if (ecezo_send_command(dev, "O,S,1", NULL, 0) < 0)
error = true;
if (ecezo_send_command(dev, "O,SG,1", NULL, 0) < 0)
error = true;
if (error)
return UPM_ERROR_OPERATION_FAILED;
else
return UPM_SUCCESS;
}
static upm_result_t decode_report(const ecezo_context dev, char *data)
{
assert(dev != NULL);
char *startptr = data;
char *endptr = NULL;
float val;
// the format of the data string should be: ec,tds,s,sg
// ec
val = strtof(startptr, &endptr);
if (startptr == endptr)
{
// error
return UPM_ERROR_OPERATION_FAILED;
}
dev->ec = val;
startptr = endptr + 1;
// tds
val = strtof(startptr, &endptr);
// error
if (startptr == endptr)
return UPM_ERROR_OPERATION_FAILED;
dev->tds = val;
startptr = endptr + 1;
// salinity
val = strtof(startptr, &endptr);
// error
if (startptr == endptr)
return UPM_ERROR_OPERATION_FAILED;
dev->salinity = val;
startptr = endptr + 1;
// sg
val = strtof(startptr, &endptr);
if (startptr == endptr)
return UPM_ERROR_OPERATION_FAILED;
dev->sg = val;
return UPM_SUCCESS;
}
static bool ecezo_data_available(const ecezo_context dev, unsigned int millis)
{
assert(dev != NULL);
// i2c, we don't support this
if (dev->i2c)
{
return false;
}
// uart
if (mraa_uart_data_available(dev->uart, millis))
return true;
else
return false;
}
// uart init
ecezo_context ecezo_uart_init(unsigned int uart, unsigned int baudrate)
{
// make sure MRAA is initialized
int mraa_rv;
if ((mraa_rv = mraa_init()) != MRAA_SUCCESS)
{
printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv);
return NULL;
}
ecezo_context dev =
(ecezo_context)malloc(sizeof(struct _ecezo_context));
if (!dev)
return NULL;
// zero out context
memset((void *)dev, 0, sizeof(struct _ecezo_context));
// initialize the MRAA contexts
// uart, default should be 8N1
if (!(dev->uart = mraa_uart_init(uart)))
{
printf("%s: mraa_uart_init() failed.\n", __FUNCTION__);
ecezo_close(dev);
return NULL;
}
if (mraa_uart_set_baudrate(dev->uart, baudrate))
{
printf("%s: mraa_uart_set_baudrate() failed.\n", __FUNCTION__);
ecezo_close(dev);
return NULL;
}
mraa_uart_set_flowcontrol(dev->uart, false, false);
if (generic_init(dev))
{
printf("%s: generic_init() failed.\n", __FUNCTION__);
ecezo_close(dev);
return NULL;
}
return dev;
}
// i2c ublox init
ecezo_context ecezo_i2c_init(unsigned int bus, uint8_t addr)
{
// make sure MRAA is initialized
int mraa_rv;
if ((mraa_rv = mraa_init()) != MRAA_SUCCESS)
{
printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv);
return NULL;
}
ecezo_context dev =
(ecezo_context)malloc(sizeof(struct _ecezo_context));
if (!dev)
return NULL;
// zero out context
memset((void *)dev, 0, sizeof(struct _ecezo_context));
// initialize the MRAA contexts
if (!(dev->i2c = mraa_i2c_init(bus)))
{
printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__);
ecezo_close(dev);
return NULL;
}
if (mraa_i2c_address(dev->i2c, addr))
{
printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__);
ecezo_close(dev);
return NULL;
}
if (generic_init(dev))
{
printf("%s: generic_init() failed.\n", __FUNCTION__);
ecezo_close(dev);
return NULL;
}
return dev;
}
void ecezo_close(ecezo_context dev)
{
assert(dev != NULL);
if (dev->uart)
mraa_uart_stop(dev->uart);
if (dev->i2c)
mraa_i2c_stop(dev->i2c);
free(dev);
}
upm_result_t ecezo_set_continuous(const ecezo_context dev, bool enable)
{
int rv;
if (enable)
rv = ecezo_send_command(dev, "C,1", NULL, 0);
else
rv = ecezo_send_command(dev, "C,0", NULL, 0);
return ((rv < 0) ? UPM_ERROR_OPERATION_FAILED : UPM_SUCCESS);
}
upm_result_t ecezo_set_temperature(const ecezo_context dev, float temp)
{
char buffer[ECEZO_MAX_BUFFER_LEN];
snprintf(buffer, ECEZO_MAX_BUFFER_LEN, "T,%f", temp);
int rv = ecezo_send_command(dev, buffer, NULL, 0);
return ((rv < 0) ? UPM_ERROR_OPERATION_FAILED : UPM_SUCCESS);
}
upm_result_t ecezo_set_led(const ecezo_context dev, bool enable)
{
int rv;
if (enable)
rv = ecezo_send_command(dev, "L,1", NULL, 0);
else
rv = ecezo_send_command(dev, "L,0", NULL, 0);
return ((rv < 0) ? UPM_ERROR_OPERATION_FAILED : UPM_SUCCESS);
}
upm_result_t ecezo_set_k_value(const ecezo_context dev, float k)
{
char buffer[ECEZO_MAX_BUFFER_LEN];
// the K value must be between 0.1 and 10.0
if (k < 0.1 || k > 10.0)
{
printf("%s: K value must be between 0.1 and 10.0\n", __FUNCTION__);
return UPM_ERROR_OUT_OF_RANGE;
}
snprintf(buffer, ECEZO_MAX_BUFFER_LEN, "K,%f", k);
int rv = ecezo_send_command(dev, buffer, NULL, 0);
return ((rv < 0) ? UPM_ERROR_OPERATION_FAILED : UPM_SUCCESS);
}
upm_result_t ecezo_set_sleep(const ecezo_context dev, bool enable)
{
int rv = 0;
if (enable)
rv = ecezo_send_command(dev, "SLEEP", NULL, 0);
else
{
// "WAKE" isn't a real command, but should wake the device up.
// We ignore the return value, as it will likely be an error
// anyway.
ecezo_send_command(dev, "WAKE", NULL, 0);
}
return ((rv < 0) ? UPM_ERROR_OPERATION_FAILED : UPM_SUCCESS);
}
int ecezo_read(const ecezo_context dev, char *buffer, size_t len)
{
assert(dev != NULL);
upm_delay_ms(CMD_DELAY); // delay CMD_DELAY ms to make sure cmd completed
// i2c
if (dev->i2c)
{
return readBytes(dev, (uint8_t *)buffer, len);
}
else
{
// UART
int bytesRead = 0;
while(bytesRead < len)
{
// we read one byte at a time, exiting when either len is
// reached, or a '\r' is found indicating the end of a
// sentence. Most commands (except 'R') require a minimum
// of 300ms to execute, so we wait up to CMD_DELAY ms after all
// data (if any) is read.
if (ecezo_data_available(dev, CMD_DELAY))
{
int br = mraa_uart_read(dev->uart, &buffer[bytesRead], 1);
if (br <= 0)
return br;
if (buffer[bytesRead] == '\r')
{
// if we found a CR, replace it with a 0 byte
buffer[bytesRead++] = 0;
return bytesRead;
}
bytesRead++;
}
else
{
// timed out - ok with responses disabled
return 0;
}
}
}
// anything else is an error
return -1;
}
upm_result_t ecezo_write(const ecezo_context dev, char *buffer, size_t len)
{
assert(dev != NULL);
if (dev->uart)
{
if (mraa_uart_write(dev->uart, buffer, len) != len)
{
printf("%s: mraa_uart_write() failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
}
else
{
// I2C
if (mraa_i2c_write(dev->i2c, (uint8_t *)buffer, len))
{
printf("%s: mraa_i2c_write() failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
}
return UPM_SUCCESS;
}
int ecezo_send_command(const ecezo_context dev, char *cmd, char *buffer,
int len)
{
assert(dev != NULL);
if (!cmd)
return -1;
// Our local buffer in case one isn't supplied
char localBuffer[ECEZO_MAX_BUFFER_LEN];
// our read buffer ptr
char *readBuffer = NULL;
if (!buffer || !len)
{
readBuffer = localBuffer;
len = ECEZO_MAX_BUFFER_LEN;
}
else
{
readBuffer = buffer;
}
#if defined(ECEZO_DEBUG)
printf("Command: %s\n", cmd);
#endif // ECEZO_DEBUG
// our write buffer
char writeBuffer[ECEZO_MAX_BUFFER_LEN];
strncpy(writeBuffer, cmd, ECEZO_MAX_BUFFER_LEN);
writeBuffer[ECEZO_MAX_BUFFER_LEN - 1] = 0;
int writelen = strlen(writeBuffer);
if (dev->uart)
{
if (strlen(writeBuffer) >= ECEZO_MAX_BUFFER_LEN - 2)
{
// too big. Should never happen in real life.
printf("%s: cmd writeBuffer too big.\n", __FUNCTION__);
return -1;
}
strcat(writeBuffer, "\r");
}
// for the uart this will now include the added CR, for I2C, this
// will now include the already existing \0 terminator.
writelen++;
// Let the games begin...
int retries = 10;
while (retries-- > 0)
{
if (ecezo_write(dev, writeBuffer, writelen))
{
printf("%s: ecezo_write() failed\n", __FUNCTION__);
return -1;
}
// we wait up to CMD_DELAY ms for an error response, which should be
// more than enough time. No response is also ok, since we
// disable the "*OK" response in the init.
memset((void *)readBuffer, 0, len);
int bytesRead = 0;
if ((bytesRead = ecezo_read(dev, readBuffer, len)) < 0)
{
return -1;
}
// for I2C, we are done at this point
if (dev->i2c)
break;
// for UART, we need some more checks
if (bytesRead && strstr(readBuffer, "*ER"))
{
// need to retry the command
#if defined(ECEZO_DEBUG)
printf("%s: *ER DETECTED, retry\n", __FUNCTION__);
#endif // ECEZO_DEBUG
continue;
}
else if (bytesRead && strchr(readBuffer, '*'))
{
// Some other diagnostic code, output it.
#if defined(ECEZO_DEBUG)
printf("%s: * diagnostic code detected (%s), retry\n",
__FUNCTION__, buffer);
#endif // ECEZO_DEBUG
continue;
}
else
{
// we are done here
#if defined(ECEZO_DEBUG)
printf("%s: bytesRead = %d\n", __FUNCTION__, bytesRead);
#endif // ECEZO_DEBUG
break;
}
}
if (retries <= 0)
{
printf("%s: read timed out and/or and retries exhausted\n",
__FUNCTION__);
return 0;
}
return len;
}
upm_result_t ecezo_update(const ecezo_context dev)
{
assert(dev != NULL);
// first we send a 'R' command to get a reading (takes a minimum
// of 1 second), then we parse out the string values into the
// context variables.
char buffer[ECEZO_MAX_BUFFER_LEN];
// first issue the report command
int rv = ecezo_send_command(dev, "R", buffer, ECEZO_MAX_BUFFER_LEN);
if (rv == 0)
{
printf("%s: timed out waiting for data\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
else if (rv < 0)
{
printf("%s: error retrieving data\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
// decode
if (decode_report(dev, buffer))
{
printf("%s: decode_report() failed\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
return UPM_SUCCESS;
}
float ecezo_get_ec(const ecezo_context dev)
{
assert(dev != NULL);
return dev->ec;
}
float ecezo_get_tds(const ecezo_context dev)
{
assert(dev != NULL);
return dev->tds;
}
float ecezo_get_salinity(const ecezo_context dev)
{
assert(dev != NULL);
return dev->salinity;
}
float ecezo_get_sg(const ecezo_context dev)
{
assert(dev != NULL);
return dev->sg;
}
upm_result_t ecezo_calibrate(const ecezo_context dev, ECEZO_CALIBRATION_T cal,
float ec)
{
assert(dev != NULL);
char cmdBuffer[ECEZO_MAX_BUFFER_LEN];
switch(cal)
{
case ECEZO_CALIBRATE_CLEAR:
snprintf(cmdBuffer, ECEZO_MAX_BUFFER_LEN, "cal,clear");
break;
case ECEZO_CALIBRATE_DRY:
snprintf(cmdBuffer, ECEZO_MAX_BUFFER_LEN, "cal,dry");
break;
case ECEZO_CALIBRATE_ONE:
snprintf(cmdBuffer, ECEZO_MAX_BUFFER_LEN, "cal,one,%f", ec);
break;
case ECEZO_CALIBRATE_LOW:
snprintf(cmdBuffer, ECEZO_MAX_BUFFER_LEN, "cal,low,%f", ec);
break;
case ECEZO_CALIBRATE_HIGH:
snprintf(cmdBuffer, ECEZO_MAX_BUFFER_LEN, "cal,high,%f", ec);
break;
default:
// should be able to happen
printf("%s: invalid cal parameter\n", __FUNCTION__);
return UPM_ERROR_INVALID_PARAMETER;
}
return ecezo_send_command(dev, cmdBuffer, NULL, 0);
}

146
src/ecezo/ecezo.cxx Normal file
View File

@ -0,0 +1,146 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <iostream>
#include <stdexcept>
#include "ecezo.hpp"
using namespace upm;
using namespace std;
ECEZO::ECEZO(unsigned int bus, unsigned int addrBaud, bool isI2C) :
m_ecezo(nullptr)
{
if (isI2C)
m_ecezo = ecezo_i2c_init(bus, addrBaud);
else
m_ecezo = ecezo_uart_init(bus, addrBaud);
if (!m_ecezo)
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_*_init() failed");
}
ECEZO::~ECEZO()
{
ecezo_close(m_ecezo);
}
void ECEZO::update()
{
if (ecezo_update(m_ecezo))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_update() failed");
}
void ECEZO::setTemperature(float temp)
{
if (ecezo_set_temperature(m_ecezo, temp))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_set_temperature() failed");
}
void ECEZO::setKValue(float k)
{
if (ecezo_set_k_value(m_ecezo, k))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_set_k_value() failed");
}
void ECEZO::setSleep(bool enable)
{
if (ecezo_set_sleep(m_ecezo, enable))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_set_sleep() failed");
}
float ECEZO::getEC()
{
return ecezo_get_ec(m_ecezo);
}
float ECEZO::getTDS()
{
return ecezo_get_tds(m_ecezo);
}
float ECEZO::getSalinity()
{
return ecezo_get_salinity(m_ecezo);
}
float ECEZO::getSG()
{
return ecezo_get_sg(m_ecezo);
}
void ECEZO::calibrate(ECEZO_CALIBRATION_T cal, float ec)
{
if (ecezo_calibrate(m_ecezo, cal, ec))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_calibrate() failed");
}
void ECEZO::setContinuous(bool enable)
{
if (ecezo_set_continuous(m_ecezo, enable))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_set_continuous() failed");
}
string ECEZO::sendCommand(string cmd)
{
char buffer[ECEZO_MAX_BUFFER_LEN];
int rv;
if ((rv = ecezo_send_command(m_ecezo, (char *)cmd.c_str(),
buffer, ECEZO_MAX_BUFFER_LEN)) < 0)
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_send_command() failed");
return string(buffer, rv);
}
string ECEZO::read()
{
char buffer[ECEZO_MAX_BUFFER_LEN];
int rv;
if ((rv = ecezo_read(m_ecezo, buffer, ECEZO_MAX_BUFFER_LEN)) < 0)
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_read() failed");
return string(buffer, rv);
}
void ECEZO::write(std::string data)
{
if (ecezo_write(m_ecezo, (char*)data.data(),
data.size()))
throw std::runtime_error(string(__FUNCTION__)
+ ": ecezo_write() failed");
}

267
src/ecezo/ecezo.h Normal file
View File

@ -0,0 +1,267 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <stdint.h>
#include <upm.h>
#include <mraa/uart.h>
#include <mraa/i2c.h>
#include <mraa/gpio.h>
#include "ecezo_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file ecezo.h
* @library ecezo
* @brief C API for the EC-EZO EC Sensor
*
* @include ecezo.c
*/
/**
* Device context
*/
typedef struct _ecezo_context {
mraa_uart_context uart;
mraa_i2c_context i2c;
// our values
float ec; // electrical conductivity
float tds; // total dissolved solids
float salinity;
float sg; // specific gravity
} *ecezo_context;
/**
* ECEZO Initializer for UART operation
*
* @param uart Specify which uart to use.
* @param baudrate Specify the baudrate to use. The device defaults
* to 9600 baud, though the datasheet implies the default is 38400.
* @return an initialized device context on success, NULL on error.
*/
ecezo_context ecezo_uart_init(unsigned int uart, unsigned int baudrate);
/**
* ECEZO Initializer for I2C operation
*
* @param bus Specify which the I2C bus to use.
* @param addr Specify the I2C address to use. This is
* configurable on the device, so there is no default.
* @return an initialized device context on success, NULL on error.
*/
ecezo_context ecezo_i2c_init(unsigned int bus, uint8_t addr);
/**
* ECEZO sensor close function
*/
void ecezo_close(ecezo_context dev);
/**
* Query the device for a reading, parse the response, and store
* the read values into the device context. This function must be
* called prior to calling any function that returns the data,
* like ecezo_get_ec().
*
* @param dev Device context
* @return UPM result
*/
upm_result_t ecezo_update(const ecezo_context dev);
/**
* For accurate readings, the temperature of the liquid being
* measured should be known. This function allows you to specify
* the liquid's temperature (in Celsius) so that proper
* compensation can take place. How you measure this temperature
* is up to you. By default, the device will assume a temperature
* of 25C.
*
* @param dev Device context
* @param temp The temperature of the liquid being measured
* @return UPM result
*/
upm_result_t ecezo_set_temperature(const ecezo_context dev, float temp);
/**
* Set the K value of the probe being used. By default, this is
* 1.0. Valid values are between 0.1 and 10.0.
*
* @param dev Device context
* @param k The K value of the probe
* @return UPM result
*/
upm_result_t ecezo_set_k_value(const ecezo_context dev, float k);
/**
* Enable or disable Sleep mode.
*
* @param dev Device context
* @param enable True to enable sleep mode, false to wake up
* @return UPM result
*/
upm_result_t ecezo_set_sleep(const ecezo_context dev, bool enable);
/**
* Retrieve the last measured Electrical Conductivity (EC) value
* in microsiemens. ecezo_update() must have been called before
* calling this function.
*
* @param dev Device context
* @return EC value in microsiemens
*/
float ecezo_get_ec(const ecezo_context dev);
/**
* Retrieve the last measured Total Dissolved solids (TDS) value.
* ecezo_update() must have been called before calling this
* function.
*
* @param dev Device context
* @return TDS value
*/
float ecezo_get_tds(const ecezo_context dev);
/**
* Retrieve the last measured Salinity value. ecezo_update() must
* have been called before calling this function.
*
* @param dev Device context
* @return Salinity value
*/
float ecezo_get_salinity(const ecezo_context dev);
/**
* Retrieve the last measured Specific Gravity (SG) value.
* ecezo_update() must have been called before calling this
* function.
*
* @param dev Device context
* @return SG value
*/
float ecezo_get_sg(const ecezo_context dev);
/**
* Specify calibration data for calibrating the device. See the
* datasheet for details on how calibration is performed. This
* function provides a mechanism for clearing out, and setting
* calibration data.
*
* A simple one point calibration might work as follows:
*
* 1. CLEAR the calibration data
* 2. with a dry probe, set the DRY point.
* 3. with the probe immersed in a standardized solution, set the
* ONE parameter to the solution's known EC value in microsiemens.
*
* A two point calibration might work as follows:
*
* 1. CLEAR the calibration data
* 2. with a dry probe, set the DRY point.
* 3. with the probe immersed in the lowest EC standardized
* solution, set the LOW parameter to the solution's known EC
* value in microsiemens.
* 4. with the probe immersed in the highest EC standardized
* solution, set the HIGH parameter to the solution's known EC
* value in microsiemens.
*
* @param dev Device context
* @param cal One of the ECEZO_CALIBRATION_T values
* @param ec The EC value of the calibration fluid. This
* parameter is ignored when cal is either ECEZO_CALIBRATE_CLEAR
* or ECEZO_CALIBRATE_DRY.
* @return UPM result
*/
upm_result_t ecezo_calibrate(const ecezo_context dev,
ECEZO_CALIBRATION_T cal,
float ec);
/**
* Enable or disable "continuous" operation. In continuous
* operation, the device will sample and emit readings every
* second. The driver disables this mode by default. If you wish
* to use continuous mode, you will be responsible for reading and
* parsing the returned data yourself.
*
* The functionality of this driver depends on continuous mode
* being disabled. When disabled, the driver will manually
* request a reading when desired via ecezo_update().
*
* @param dev Device context
* @param enable true to enable continuous mode, false to disable.
* @return UPM result
*/
upm_result_t ecezo_set_continuous(const ecezo_context dev, bool enable);
/**
* Directly send a command to the device and optionally get a
* response. This is a low level function and should not be
* called unless you know what you are doing.
*
* @param dev Device context
* @param cmd command to send to the device. See the datasheet
* for valid commands.
* @param buffer Optional buffer in which to return any data.
* NULL if you are not interested in any returned data.
* @param len Length of the buffer, or 0 if you are not interested
* in returned data
* @return Number of characters read back, 0 if a timeout or no
* data, -1 if an error
*/
int ecezo_send_command(const ecezo_context dev, char *cmd,
char *buffer, int len);
/**
* Read character data from the device. This is a low level
* function and should not be called unless you know what you are
* doing.
*
* @param dev sensor context
* @param buffer The character buffer to read data into.
* @param len The maximum size of the buffer
* @return The number of bytes successfully read, or -1 on error
*/
int ecezo_read(const ecezo_context dev, char *buffer, size_t len);
/**
* Write character data to the device. This is a low level
* function and should not be called unless you know what you are
* doing.
*
* @param dev sensor context
* @param buffer The character buffer containing data to write.
* @param len The number of bytes to write.
* @return The number of bytes successfully written, or -1 on error.
*/
upm_result_t ecezo_write(const ecezo_context dev, char *buffer, size_t len);
#ifdef __cplusplus
}
#endif

238
src/ecezo/ecezo.hpp Normal file
View File

@ -0,0 +1,238 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include "ecezo.h"
namespace upm {
/**
* @brief API for the EC-EZO EC Sensor
* @defgroup ecezo libupm-ecezo
* @ingroup uart i2c liquid
*/
/**
* @library ecezo
* @sensor ecezo
* @comname EC-EZO EC Sensor
* @type liquid
* @man sparkfun
* @con uart i2c
* @web https://www.sparkfun.com/products/12908
*
* @brief API for the EC-EZO EC Sensor
*
* This driver was tested with the Atlas Scientific Electrical
* Conductivity kit.
*
* This device can operate in either UART or I2C modes.
*
* @snippet ecezo.cxx Interesting
*/
class ECEZO {
public:
/**
* ECEZO object constructor. This can use either UART
* (default) or I2C communications. For UART, specify the
* uart number as the bus parameter, the baudrate as the
* addrBaud parameter, and false for the isI2C parameter.
*
* For I2C, specify the bus parameter, the I2C address as the
* addrBaud parameter, and true for the isI2C parameter.
*
* @param bus Specify which uart or I2C bus to use
* @param addrBaud Specify the baudrate if using UART, or the
* I2C address of the device if using I2C.
* @param isI2C true if using I2C, false if using a UART
*/
ECEZO(unsigned int bus=0, unsigned int addrBaud=9600,
bool isI2C=false);
/**
* ECEZO object destructor
*/
~ECEZO();
/**
* Query the device for a reading, parse the response, and store
* the read values into the device context. This function must be
* called prior to calling any function that returns the data,
* like getEC().
*/
void update();
/**
* For accurate readings, the temperature of the liquid being
* measured should be known. This function allows you to specify
* the liquid's temperature (in Celsius) so that proper
* compensation can take place. How you measure this temperature
* is up to you. By default, the device will assume a temperature
* of 25C.
*
* @param temp The temperature of the liquid being measured
* @return UPM result
*/
void setTemperature(float temp);
/**
* Set the K value of the probe being used. By default, this is
* 1.0. Valid values are between 0.1 and 10.0.
*
* @param k The K value of the probe
*/
void setKValue(float k);
/**
* Enable or disable Sleep mode.
*
* @param enable True to enable sleep mode, false to wake up
*/
void setSleep(bool enable);
/**
* Retrieve the last measured Electrical Conductivity (EC)
* value in microsiemens. update() must have been called
* before calling this function.
*
* @return EC value in microsiemens
*/
float getEC();
/**
* Retrieve the last measured Total Dissolved solids (TDS) value.
* update() must have been called before calling this
* function.
*
* @return TDS value
*/
float getTDS();
/**
* Retrieve the last measured Salinity value. update() must
* have been called before calling this function.
*
* @return Salinity value
*/
float getSalinity();
/**
* Retrieve the last measured Specific Gravity (SG) value.
* update() must have been called before calling this
* function.
*
* @return SG value
*/
float getSG();
/**
* Specify calibration data for calibrating the device. See the
* datasheet for details on how calibration is performed. This
* function provides a mechanism for clearing out, and setting
* calibration data.
*
* A simple one point calibration might work as follows:
*
* 1. CLEAR the calibration data
* 2. with a dry probe, set the DRY point.
* 3. with the probe immersed in a standardized solution, set the
* ONE parameter to the solution's known EC value in microsiemens.
*
* A two point calibration might work as follows:
*
* 1. CLEAR the calibration data
* 2. with a dry probe, set the DRY point.
* 3. with the probe immersed in the lowest EC standardized
* solution, set the LOW parameter to the solution's known EC
* value in microsiemens.
* 4. with the probe immersed in the highest EC standardized
* solution, set the HIGH parameter to the solution's known EC
* value in microsiemens.
*
* @param cal One of the ECEZO_CALIBRATION_T values
* @param ec The EC value of the calibration fluid. This
* parameter is ignored when cal is either ECEZO_CALIBRATE_CLEAR
* or ECEZO_CALIBRATE_DRY.
*/
void calibrate(ECEZO_CALIBRATION_T cal, float ec);
protected:
// ecezo device context
ecezo_context m_ecezo;
/**
* Enable or disable "continuous" operation. In continuous
* operation, the device will sample and emit readings every
* second. The driver disables this mode by default. If you wish
* to use continuous mode, you will be responsible for reading and
* parsing the returned data yourself.
*
* The functionality of this driver depends on continuous mode
* being disabled. When disabled, the driver will manually
* request a reading when desired via ecezo_update().
*
* @param enable true to enable continuous mode, false to disable.
*/
void setContinuous(bool enable);
/**
* Directly send a command to the device and optionally get a
* response. This is a low level function and should not be
* called unless you know what you are doing.
*
* @param cmd a String containing the command to send to the
* device. See the datasheet for valid commands.
* @return The string response, if any
*/
std::string sendCommand(std::string cmd);
/**
* Read character data from the device. This is a low level
* function and should not be called unless you know what you are
* doing.
*
* @return A string containing the data read back, if any
*/
std::string read();
/**
* Write character data to the device. This is a low level
* function and should not be called unless you know what you are
* doing.
*
* @param data The string containing data to write.
*/
void write(std::string data);
private:
};
}

45
src/ecezo/ecezo_defs.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// our maximum buffer size
#define ECEZO_MAX_BUFFER_LEN (64)
// calibration commands
typedef enum {
ECEZO_CALIBRATE_CLEAR = 0, // clear calibration
ECEZO_CALIBRATE_DRY, // cal dry point
ECEZO_CALIBRATE_ONE, // single point cal EC value
ECEZO_CALIBRATE_LOW, // 2-point cal, LOW EC value
ECEZO_CALIBRATE_HIGH // 2-point cal, HIGH EC value
} ECEZO_CALIBRATION_T;
#ifdef __cplusplus
}
#endif

88
src/ecezo/ecezo_fti.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 "ecezo.h"
#include "upm_fti.h"
/**
* This file implements the Function Table Interface (FTI) for this sensor
*/
const char upm_ecezo_name[] = "ECEZO";
const char upm_ecezo_description[] = "EC-EZO EC sensor";
const upm_protocol_t upm_ecezo_protocol[] = {UPM_UART, UPM_I2C};
const upm_sensor_t upm_ecezo_category[] = {UPM_EC};
// forward declarations
const void* upm_ecezo_get_ft(upm_sensor_t sensor_type);
void* upm_ecezo_init_name();
void upm_ecezo_close(void *dev);
upm_result_t upm_ecezo_get_value(const void *dev, float *value);
static const upm_sensor_ft ft =
{
.upm_sensor_init_name = &upm_ecezo_init_name,
.upm_sensor_close = &upm_ecezo_close,
};
static const upm_ec_ft ecft =
{
.upm_ec_get_value = upm_ecezo_get_value
};
const void* upm_ecezo_get_ft(upm_sensor_t sensor_type)
{
switch(sensor_type)
{
case UPM_SENSOR:
return &ft;
case UPM_EC:
return &ecft;
default:
return NULL;
}
}
void* upm_ecezo_init_name()
{
return NULL;
}
void upm_ecezo_close(void *dev)
{
ecezo_close((ecezo_context)dev);
}
upm_result_t upm_ecezo_get_value(const void *dev, float *value)
{
upm_result_t rv;
if ((rv = ecezo_update((ecezo_context)dev)))
return rv;
*value = ecezo_get_ec((ecezo_context)dev);
return UPM_SUCCESS;
}

22
src/ecezo/javaupm_ecezo.i Normal file
View File

@ -0,0 +1,22 @@
%module javaupm_ecezo
%include "../upm.i"
%include "std_string.i"
%include "stdint.i"
%include "typemaps.i"
%include "ecezo_defs.h"
%include "ecezo.hpp"
%{
#include "ecezo.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_ecezo");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

9
src/ecezo/jsupm_ecezo.i Normal file
View File

@ -0,0 +1,9 @@
%module jsupm_ecezo
%include "../upm.i"
%include "std_string.i"
%include "ecezo_defs.h"
%include "ecezo.hpp"
%{
#include "ecezo.hpp"
%}

13
src/ecezo/pyupm_ecezo.i Normal file
View File

@ -0,0 +1,13 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_ecezo
%include "../upm.i"
%include "std_string.i"
%feature("autodoc", "3");
%include "ecezo_defs.h"
%include "ecezo.hpp"
%{
#include "ecezo.hpp"
%}

View File

@ -32,7 +32,7 @@
using namespace upm; using namespace upm;
ECS1030::ECS1030 (uint8_t pinNumber) { ECS1030::ECS1030 (int pinNumber) {
m_dataPinCtx = mraa_aio_init(pinNumber); m_dataPinCtx = mraa_aio_init(pinNumber);
if (m_dataPinCtx == NULL) { if (m_dataPinCtx == NULL) {
throw std::invalid_argument(std::string(__FUNCTION__) + throw std::invalid_argument(std::string(__FUNCTION__) +

View File

@ -83,7 +83,7 @@ class ECS1030 {
* *
* @param pinNumber Number of the data pin * @param pinNumber Number of the data pin
*/ */
ECS1030 (uint8_t pinNumber); ECS1030 (int pinNumber);
/** /**
* ECS1030 object destructor; basically, it closes the GPIO. * ECS1030 object destructor; basically, it closes the GPIO.

View File

@ -315,9 +315,14 @@ and is not meant to be installed anywhere.
@brief Honeywell @brief Honeywell
@defgroup maxim Maxim Integrated @defgroup sparkfun Sparkfun
@ingroup byman @ingroup byman
@brief Maxim Integrated @brief Sparkfun
@defgroup maxbotix MaxBotixs
@ingroup byman
@brief MaxBotixs
@defgroup meas Measurement Specialties @defgroup meas Measurement Specialties

View File

@ -33,7 +33,7 @@
using namespace upm; using namespace upm;
GroveUltraSonic::GroveUltraSonic (uint8_t pin) { GroveUltraSonic::GroveUltraSonic (int pin) {
m_name = "GroveUltraSonic"; m_name = "GroveUltraSonic";
mraa_init(); mraa_init();

View File

@ -69,7 +69,7 @@ class GroveUltraSonic {
* *
* @param pin pin for triggering the sensor for distance and for receiving pulse response * @param pin pin for triggering the sensor for distance and for receiving pulse response
*/ */
GroveUltraSonic (uint8_t pin); GroveUltraSonic (int pin);
/** /**
* GroveUltraSonic object destructor. * GroveUltraSonic object destructor.

View File

@ -38,7 +38,7 @@
using namespace upm; using namespace upm;
HCSR04::HCSR04 (uint8_t triggerPin, uint8_t echoPin) { HCSR04::HCSR04 (int triggerPin, int echoPin) {
m_name = "HCSR04"; m_name = "HCSR04";
m_triggerPinCtx = mraa_gpio_init (triggerPin); m_triggerPinCtx = mraa_gpio_init (triggerPin);

View File

@ -65,7 +65,7 @@ class HCSR04 {
* @param fptr Function pointer to handle rising-edge and * @param fptr Function pointer to handle rising-edge and
* falling-edge interrupts * falling-edge interrupts
*/ */
HCSR04 (uint8_t triggerPin, uint8_t echoPin); HCSR04 (int triggerPin, int echoPin);
/** /**
* HCSR04 object destructor * HCSR04 object destructor
*/ */

View File

@ -30,7 +30,7 @@
using namespace upm; using namespace upm;
using namespace std; using namespace std;
HX711::HX711(uint8_t data, uint8_t sck, uint8_t gain) { HX711::HX711(int data, int sck, uint8_t gain) {
mraa_result_t error = MRAA_SUCCESS; mraa_result_t error = MRAA_SUCCESS;
this->m_dataPinCtx = mraa_gpio_init(data); this->m_dataPinCtx = mraa_gpio_init(data);

View File

@ -63,7 +63,7 @@ namespace upm {
* @param gain Defines the gain factor * @param gain Defines the gain factor
* Valid values are 128 or 64 for channel A; channel B works with a 32-gain factor only * Valid values are 128 or 64 for channel A; channel B works with a 32-gain factor only
*/ */
HX711(uint8_t data, uint8_t sck, uint8_t gain = 128); HX711(int data, int sck, uint8_t gain = 128);
/** /**
* HX711 destructor * HX711 destructor

View File

@ -37,7 +37,7 @@
using namespace upm; using namespace upm;
ILI9341::ILI9341(uint8_t csLCD, uint8_t csSD, uint8_t dc, uint8_t rst) : ILI9341::ILI9341(int csLCD, int csSD, int dc, int rst) :
GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT), m_csLCDPinCtx(csLCD), GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT), m_csLCDPinCtx(csLCD),
m_csSDPinCtx(csSD), m_dcPinCtx(dc), m_rstPinCtx(rst), m_spi(0) { m_csSDPinCtx(csSD), m_dcPinCtx(dc), m_rstPinCtx(rst), m_spi(0) {

View File

@ -159,7 +159,7 @@ namespace upm {
* @param dc Data/command pin * @param dc Data/command pin
* @param rst Reset pin * @param rst Reset pin
*/ */
ILI9341(uint8_t csLCD, uint8_t csSD, uint8_t dc, uint8_t rst); ILI9341(int csLCD, int csSD, int dc, int rst);
/** /**
* Returns the name of the component * Returns the name of the component

9
src/ims/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
upm_mixed_module_init (NAME ims
DESCRIPTION "Catnip Electronics I2C moisture sensor"
C_HDR ims.h
C_SRC ims.c
CPP_HDR ims.hpp
CPP_SRC ims.cxx
FTI_SRC ims_fti.c
CPP_WRAPS_C
REQUIRES mraa)

207
src/ims/ims.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* 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 <stdlib.h>
#include <syslog.h>
#include "ims.h"
ims_context* ims_init(int16_t i2c_bus, int16_t i2c_address)
{
/* Allocate space for the sensor structure */
ims_context* dev = (ims_context*) malloc(sizeof(ims_context));
if(dev == NULL)
{
syslog(LOG_CRIT, "%s: malloc() failed\n", __FUNCTION__);
goto ims_init_fail;
}
/* Initilize mraa */
mraa_result_t result = mraa_init();
if (result != MRAA_SUCCESS)
{
syslog(LOG_ERR, "%s: mraa_init() failed (%d)\n", __FUNCTION__, result);
goto ims_init_fail;
}
/* Init i2c */
dev->_i2c_context = mraa_i2c_init(i2c_bus);
if(dev->_i2c_context == NULL)
{
syslog(LOG_ERR, "%s: mraa_i2c_init() failed\n", __FUNCTION__);
goto ims_init_fail;
}
/* Set the i2c slave address for this device */
if (mraa_i2c_address(dev->_i2c_context, i2c_address) != MRAA_SUCCESS)
{
syslog(LOG_ERR, "%s: mraa_i2c_address() failed\n", __FUNCTION__);
goto ims_init_fail;
}
/* This device must run at 100kHz */
if (mraa_i2c_frequency(dev->_i2c_context, MRAA_I2C_STD))
{
syslog(LOG_ERR, "%s: mraa_i2c_frequency() failed\n", __FUNCTION__);
goto ims_init_fail;
}
return dev;
/* Handle all failing cases here */
ims_init_fail:
/* Free structure memory if allocated */
if (dev != NULL)
free(dev);
return NULL;
}
void ims_close(ims_context* dev)
{
if (dev == NULL) return;
/* Cleanup the I2C context */
mraa_i2c_stop(dev->_i2c_context);
free(dev);
}
upm_result_t ims_read(const ims_context* dev, IMS_RD_COMMAND cmd, uint16_t* rd_data)
{
int32_t val = 0;
uint8_t readbuf[2] = {0, 0};
switch (cmd)
{
/* One byte reads */
case IMS_GET_ADDRESS:
case IMS_GET_VERSION:
case IMS_GET_BUSY:
val = mraa_i2c_read_bytes_data(dev->_i2c_context, cmd, readbuf, 1);
*rd_data = readbuf[0];
break;
/* Two byte reads */
case IMS_GET_CAPACITANCE:
case IMS_GET_LIGHT:
case IMS_GET_TEMPERATURE:
val = mraa_i2c_read_bytes_data(dev->_i2c_context, cmd, readbuf, 2);
*rd_data = readbuf[1];
*rd_data += ((uint16_t)readbuf[0] << 8) & 0xFF00;
break;
default:
syslog(LOG_ERR, "%s: Invalid read command: 0x%02x\n", __FUNCTION__, cmd);
return UPM_ERROR_INVALID_PARAMETER;
}
/* val will be < 0 on failing case */
if (val < 0)
{
syslog(LOG_ERR, "%s: mraa_i2c_read_byte/word_data() failed\n", __FUNCTION__);
return UPM_ERROR_NO_DATA;
}
return UPM_SUCCESS;
}
upm_result_t ims_write(const ims_context* dev, IMS_WR_COMMAND cmd, uint8_t wr_data)
{
mraa_result_t mr;
switch (cmd)
{
/* One byte write */
case IMS_SET_ADDRESS:
mr = mraa_i2c_write_byte_data(dev->_i2c_context, wr_data, cmd);
break;
/* Zero byte write */
case IMS_MEASURE_LIGHT:
case IMS_RESET:
case IMS_SLEEP:
mr = mraa_i2c_write(dev->_i2c_context, (const uint8_t *)&cmd, 1);
break;
default:
syslog(LOG_ERR, "%s: Invalid read command: 0x%02x\n", __FUNCTION__, cmd);
return UPM_ERROR_INVALID_PARAMETER;
}
if (mr != MRAA_SUCCESS) return UPM_ERROR_OPERATION_FAILED;
return UPM_SUCCESS;
}
upm_result_t ims_get_version(const ims_context* dev, uint16_t* rd_data)
{
return ims_read(dev, IMS_GET_VERSION, rd_data);
}
upm_result_t ims_get_moisture(const ims_context* dev, uint16_t* rd_data)
{
return ims_read(dev, IMS_GET_CAPACITANCE, rd_data);
}
upm_result_t ims_get_light(const ims_context* dev, uint16_t* rd_data)
{
/* Initiate a light measurement */
upm_result_t res = ims_write(dev, IMS_MEASURE_LIGHT, 0);
if (res != UPM_SUCCESS) return res;
/* Technical data for the ISM specifies a 3 second wait. Check the BUSY
* command every 100 ms for 3 seconds. The sensor will return quickly in
* bright light and much slower in less light. */
int retry = 30;
*rd_data = 1;
while ((retry-- > 0) && (*rd_data != 0))
{
// Always delay at least 100 ms
upm_delay_ms(100);
res = ims_read(dev, IMS_GET_BUSY, rd_data);
if (res != UPM_SUCCESS) return res;
}
/* If the sensor is STILL not ready, go ahead and perform the read.
* From testing, this appears to happen only in complete darkness,
* at which point the sensor get light read returns 0xffff anyway.*/
return ims_read(dev, IMS_GET_LIGHT, rd_data);
}
upm_result_t ims_get_temperature(const ims_context* dev, uint16_t* rd_data)
{
return ims_read(dev, IMS_GET_TEMPERATURE, rd_data);
}
upm_result_t ims_reset(const ims_context* dev)
{
return ims_write(dev, IMS_RESET, 0);
}
upm_result_t ims_reset_i2c_address(const ims_context* dev, uint8_t address_new)
{
upm_result_t res = ims_write(dev, IMS_SET_ADDRESS, address_new);
if (res != UPM_SUCCESS) return res;
return ims_reset(dev);
}
upm_result_t ims_sleep(const ims_context* dev)
{
return ims_write(dev, IMS_SLEEP, 0);
}

110
src/ims/ims.cxx Normal file
View File

@ -0,0 +1,110 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* 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 <stdexcept>
#include "ims.hpp"
using namespace upm;
IMS::IMS(int16_t i2c_bus, int16_t i2c_address) :
_dev(ims_init(i2c_bus, i2c_address))
{
if (_dev == NULL)
throw std::runtime_error(std::string(__FUNCTION__) +
": failed to initialize sensor, check syslog");
}
uint16_t IMS::get_version()
{
uint16_t retval;
if (ims_get_version(_dev, &retval) != UPM_SUCCESS)
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_get_version command failed");
return retval;
}
uint16_t IMS::get_moisture()
{
uint16_t retval;
if (ims_get_moisture(_dev, &retval) != UPM_SUCCESS)
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_get_moisture command failed");
return retval;
}
uint16_t IMS::get_light()
{
uint16_t retval;
if (ims_get_light(_dev, &retval) != UPM_SUCCESS)
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_get_light command failed");
return retval;
}
float IMS::get_temperature()
{
uint16_t retval;
if (ims_get_temperature(_dev, &retval) != UPM_SUCCESS)
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_get_temperature command failed");
return static_cast<float>(retval)/10.0;
}
void IMS::reset_i2c_address(uint8_t address_new)
{
if (ims_reset_i2c_address(_dev, address_new) != UPM_SUCCESS)
throw std::runtime_error(std::string(__FUNCTION__) +
": reset_i2c_address command failed");
}
void IMS::reset()
{
if ( ims_write(_dev, IMS_RESET, 1) != UPM_SUCCESS )
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_write command failed");
}
uint16_t IMS::read(IMS_RD_COMMAND cmd)
{
uint16_t retval;
if (ims_read(_dev, cmd, &retval) != UPM_SUCCESS)
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_read command failed");
return retval;
}
void IMS::write(IMS_WR_COMMAND cmd, uint8_t value)
{
if ( ims_write(_dev, cmd, value) != UPM_SUCCESS )
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_write command failed");
}
void IMS::sleep()
{
if ( ims_sleep(_dev) != UPM_SUCCESS )
throw std::runtime_error(std::string(__FUNCTION__) +
": ims_sleep command failed");
}

178
src/ims/ims.h Normal file
View File

@ -0,0 +1,178 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* 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.
*/
#pragma once
#include <errno.h>
#include <stdint.h>
#include "mraa/i2c.h"
#include "upm.h"
#ifdef __cplusplus
extern "C" {
#endif
#define IMS_ADDRESS_DEFAULT 0x20
/* @brief Moisture sensor I2C READ commands */
typedef enum _IMS_RD_COMMAND {
/* Read capacitance (moisture) register */
IMS_GET_CAPACITANCE = 0x00, /* (r) 2 */
/* Read I2C address register */
IMS_GET_ADDRESS = 0x02, /* (r) 1 */
/* Read light register (requires write to IMS_MEASURE_LIGHT) */
IMS_GET_LIGHT = 0x04, /* (r) 2 */
/* Read temperature register */
IMS_GET_TEMPERATURE = 0x05, /* (r) 2 */
/* Read version register */
IMS_GET_VERSION = 0x07, /* (r) 1 */
/* Read busy register (0 = ready, 1 = sampling) */
IMS_GET_BUSY = 0x09, /* (r) 1 */
} IMS_RD_COMMAND;
/* @brief Moisture sensor I2C WRITE commands */
typedef enum {
/* Write I2C address register (latched w/IMS_RESET) */
IMS_SET_ADDRESS = 0x01, /* (w) 1 */
/* Initiate light measurement */
IMS_MEASURE_LIGHT = 0x03, /* (w) 0 */
/* Reset device */
IMS_RESET = 0x06, /* (w) 0 */
/* Sleep microcontroller, wake on any I2C request */
IMS_SLEEP = 0x08, /* (w) 0 */
} IMS_WR_COMMAND;
/**
* @file ims.h
* @library ims
* @brief C API for the Catnip Electronics I2C moisture sensor. This sensor
* must run at 100 kHz.
*
* @include ims.c
*/
/**
* device context
*/
typedef struct {
/* mraa i2c context */
mraa_i2c_context _i2c_context;
} ims_context;
/**
* Initialize sensor
* @param i2c_bus Target I2C bus
* @param i2c_address Target I2C address (default is 0x20)
* @return sensor context pointer
*/
ims_context* ims_init(int16_t i2c_bus, int16_t i2c_address);
/**
* Sensor close method.
* Cleans up any memory held by this device
* @param sensor context pointer
*/
void ims_close(ims_context* dev);
/**
* Read I2C Moisture Sensor registers
* @param dev Sensor context pointer
* @param cmd Read command
* @param rd_data Data returned from sensor (1 or 2 bytes depending on cmd)
* @return Function result code
*/
upm_result_t ims_read(const ims_context* dev, IMS_RD_COMMAND cmd, uint16_t* rd_data);
/**
* Write I2C Moisture Sensor registers
* @param dev Sensor context pointer
* @param cmd Write command
* @param wr_data Target data to write (only used for IMS_SET_ADDRESS)
* @return Function result code
*/
upm_result_t ims_write(const ims_context* dev, IMS_WR_COMMAND cmd, uint8_t wr_data);
/**
* Get sensor version
* @param dev Sensor context pointer
* @param rd_data Sensor version
* @return Function result code
*/
upm_result_t ims_get_version(const ims_context* dev, uint16_t* rd_data);
/**
* Get moisture reading from sensor
* @param dev Sensor context pointer
* @param rd_data Unitless, relative capacitance value (used to determine moisture)
* @return Function result code
*/
upm_result_t ims_get_moisture(const ims_context* dev, uint16_t* rd_data);
/**
* Get light reading from LED on device. The technical data for the I2C
* moisture sensor specifies a 3 second wait. Loop for 3 seconds checking
* the GET_BUSY register. IF the sensor is NOT ready after 3 seconds,
* assume there is NO light and return a max uint16_t (dark) value.
* @param dev Sensor context pointer
* @param rd_data Unitless, relative value for brightness
* dark (0xFFFF) ---> light (0x0000)
* @return Function result code
*/
upm_result_t ims_get_light(const ims_context* dev, uint16_t* rd_data);
/**
* Get temperature reading from device
* @param dev Sensor context pointer
* @param rd_data Temperature in degrees Celsius * 10
* ie, 256 = 25.6 C
* @return Function result code
*/
upm_result_t ims_get_temperature(const ims_context* dev, uint16_t* rd_data);
/**
* Reset sensor
* @param dev Sensor context pointer
* @return Function result code
*/
upm_result_t ims_reset(const ims_context* dev);
/**
* Set I2C address AND reset sensor
* @param dev Sensor context pointer
* @param address_new New I2C for device
* @return Function result code
*/
upm_result_t ims_reset_i2c_address(const ims_context* dev, uint8_t address_new);
/**
* Put device into low-power mode. Device wakes on any I2C command.
* @param dev Sensor context pointer
* @return Function result code
*/
upm_result_t ims_sleep(const ims_context* dev);
#ifdef __cplusplus
}
#endif

148
src/ims/ims.hpp Normal file
View File

@ -0,0 +1,148 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* 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.
*/
#pragma once
#include "mraa/i2c.h"
#include "ims.h"
namespace upm {
/**
* @brief Catnip Electronics I2C moisture sensor
* @defgroup ims libupm-ims
* @ingroup catnip i2c liquid light temp
*/
/**
* @library ims
* @sensor ims
* @comname Catnip Electronics I2C moisture sensor
* @type liquid light temp
* @man catnip
* @web https://www.tindie.com/products/miceuz/i2c-soil-moisture-sensor/
* @con i2c
*
* @brief API for the Catnip Electronics I2C moisture sensor
*
* I2C sensor which can be used to read:
* moisture
* light
* temperature
*
* This sensor must run at 100 kHz
*
* @image html ims.png
* @snippet ims.cxx Interesting
*/
class IMS {
public:
/**
* I2C Moisture Sensor constructor
*
* Initialize I2C Moisture Sensor
* @param i2c_bus Target I2C bus
* @param i2c_address Target I2C address (default is 0x20)
* @return sensor context pointer
* @throws std::runtime_error if sensor initializate fails
*/
IMS(int16_t i2c_bus, int16_t i2c_address = IMS_ADDRESS_DEFAULT);
/**
* IMS destructor
*/
virtual ~IMS() {};
/**
* Write I2C Moisture Sensor registers
* @param cmd Write command
* @param wr_data Target data to write (only used for IMS_SET_ADDRESS)
* @throws std::runtime_error if I2C write command fails
*/
void write(IMS_WR_COMMAND cmd, uint8_t wr_data);
/**
* Read I2C Moisture Sensor registers
* @param cmd Read command
* @return Data returned from sensor (1 or 2 bytes depending on CMD)
* @throws std::runtime_error if I2C read command fails
*/
uint16_t read(IMS_RD_COMMAND cmd);
/**
* Get sensor version
* @return Sensor version
* @throws std::runtime_error if I2C read command fails
*/
uint16_t get_version();
/**
* Get moisture reading from sensor
* @return Unitless, relative capacitance value (moisture)
* @throws std::runtime_error if I2C read command fails
*/
uint16_t get_moisture();
/**
* Get light reading from LED on device. The technical data for the I2C
* moisture sensor specifies a 3 second wait. Loop for 3 seconds
* checking the GET_BUSY register. IF the sensor is NOT ready after 3
* seconds, assume there is NO light and return a max uint16_t (dark)
* value.
* @return rd_data Unitless, relative value for brightness
* dark (0xFFFF) ---> light (0x0000)
* @throws std::runtime_error if I2C write/read command fails
*/
uint16_t get_light();
/**
* Get temperature reading from device
* @return rd_data Temperature in degrees Celsius
* @throws std::runtime_error if I2C read command fails
*/
float get_temperature();
/**
* Reset sensor
* @throws std::runtime_error if I2C write command fails
*/
void reset();
/**
* Set I2C address AND reset sensor
* @param address_new New I2C for device
* @throws std::runtime_error if I2C write command fails
*/
void reset_i2c_address(uint8_t address_new);
/**
* Put device into low-power mode. Device wakes on any I2C command.
* @throws std::runtime_error if I2C write command fails
*/
void sleep();
private:
/* device context struct */
ims_context* _dev;
};
}

146
src/ims/ims_fti.c Normal file
View File

@ -0,0 +1,146 @@
/*
* Author: Noel Eck <noel.eck@intel.com>
* 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 <string.h>
#include <stdlib.h>
#include "ims.h"
#include "upm_fti.h"
#include "fti/upm_sensor.h"
/**
* This file implements the Function Table Interface (FTI) for this sensor
*/
const char upm_ims_name[] = "IMS";
const char upm_ims_description[] = "Catnip Electronics I2C moisture sensor";
const upm_protocol_t upm_ims_protocol[] = {UPM_I2C};
const upm_sensor_t upm_ims_category[] = {UPM_LIGHT, UPM_TEMPERATURE, UPM_MOISTURE};
// forward declarations
const void* upm_ims_get_ft(upm_sensor_t sensor_type);
void* upm_ims_init_str(const char* protocol, const char* params);
void upm_ims_close(void* dev);
const upm_sensor_descriptor_t upm_ims_get_descriptor();
upm_result_t upm_ims_get_light(const void* dev, float *value);
upm_result_t upm_ims_get_temperature(void* dev, float *value, upm_temperature_u unit);
upm_result_t upm_ims_get_moisture(void* dev, int *value);
/* This sensor implementes 2 function tables */
/* 1. Generic base function table */
static const upm_sensor_ft ft_gen =
{
.upm_sensor_init_name = &upm_ims_init_str,
.upm_sensor_close = &upm_ims_close,
.upm_sensor_get_descriptor = &upm_ims_get_descriptor
};
/* 2. Light function table */
static const upm_light_ft ft_light =
{
.upm_light_set_offset = NULL,
.upm_light_set_scale = NULL,
.upm_light_get_value = &upm_ims_get_light
};
/* 3. Light function table */
static const upm_temperature_ft ft_temperature =
{
.upm_temperature_set_offset = NULL,
.upm_temperature_set_scale = NULL,
.upm_temperature_get_value = &upm_ims_get_temperature
};
/* 4. Light function table */
static const upm_moisture_ft ft_moisture =
{
.upm_moisture_sensor_get_moisture = &upm_ims_get_moisture
};
const void* upm_ims_get_ft(upm_sensor_t sensor_type)
{
switch(sensor_type)
{
case UPM_SENSOR:
return &ft_gen;
case UPM_LIGHT:
return &ft_light;
case UPM_TEMPERATURE:
return &ft_temperature;
case UPM_MOISTURE:
return &ft_moisture;
default:
return NULL;
}
}
void* upm_ims_init_str(const char* protocol, const char* params)
{
fprintf(stderr,
"String initialization - not implemented, using i2c bus 0, addr: 0x20: %s\n", __FILENAME__);
return ims_init(0, 0x20);
}
void upm_ims_close(void* dev)
{
ims_close(dev);
}
const upm_sensor_descriptor_t upm_ims_get_descriptor()
{
/* Fill in the descriptor */
upm_sensor_descriptor_t usd;
usd.name = upm_ims_name;
usd.description = upm_ims_description;
usd.protocol_size = 1;
usd.protocol = upm_ims_protocol;
usd.category_size = 3;
usd.category = upm_ims_category;
return usd;
}
upm_result_t upm_ims_get_light(const void* dev, float *value)
{
uint16_t data;
upm_result_t result = ims_get_light((ims_context*)dev, &data);
*value = data;
return result;
}
upm_result_t upm_ims_get_temperature(void* dev, float *value, upm_temperature_u unit)
{
uint16_t data;
upm_result_t result = ims_get_temperature((ims_context*)dev, &data);
*value = data;
return result;
}
upm_result_t upm_ims_get_moisture(void* dev, int *value)
{
uint16_t data;
upm_result_t result = ims_get_moisture((ims_context*)dev, &data);
*value = data;
return result;
}

20
src/ims/javaupm_ims.i Normal file
View File

@ -0,0 +1,20 @@
%module javaupm_ims
%include "../upm.i"
%{
#include "ims.hpp"
%}
%include "ims.h"
%include "ims.hpp"
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_ims");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

9
src/ims/jsupm_ims.i Normal file
View File

@ -0,0 +1,9 @@
%module jsupm_ims
%include "../upm.i"
%{
#include "ims.hpp"
%}
%include "ims.h"
%include "ims.hpp"

13
src/ims/pyupm_ims.i Normal file
View File

@ -0,0 +1,13 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_ims
%include "../upm.i"
%feature("autodoc", "3");
%{
#include "ims.hpp"
%}
%include "ims.h"
%include "ims.hpp"

View File

@ -100,8 +100,8 @@ Lcm1602::Lcm1602(int bus_in, int addr_in, bool isExpander,
home(); home();
} }
Lcm1602::Lcm1602(uint8_t rs, uint8_t enable, uint8_t d0, Lcm1602::Lcm1602(int rs, int enable, int d0,
uint8_t d1, uint8_t d2, uint8_t d3, int d1, int d2, int d3,
uint8_t numColumns, uint8_t numRows) : uint8_t numColumns, uint8_t numRows) :
m_numColumns(numColumns), m_numRows(numRows), m_numColumns(numColumns), m_numRows(numRows),
m_i2c_lcd_control(0), m_i2c_lcd_control(0),

View File

@ -97,8 +97,8 @@ class Lcm1602 : public LCD
* @param numColumns Number of columns the display has. Default 16. * @param numColumns Number of columns the display has. Default 16.
* @param numRows Number of rows the display has. Default 2. * @param numRows Number of rows the display has. Default 2.
*/ */
Lcm1602(uint8_t rs, uint8_t enable, Lcm1602(int rs, int enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, int d0, int d1, int d2, int d3,
uint8_t numColumns = 16, uint8_t numRows = 2); uint8_t numColumns = 16, uint8_t numRows = 2);
/** /**

View File

@ -29,9 +29,9 @@
using namespace upm; using namespace upm;
SAINSMARTKS::SAINSMARTKS(uint8_t rs, uint8_t enable, SAINSMARTKS::SAINSMARTKS(int rs, int enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, int d0, int d1, int d2, int d3,
uint8_t keypad) int keypad)
: Lcm1602(rs, enable, d0, d1, d2, d3), : Lcm1602(rs, enable, d0, d1, d2, d3),
m_aioKeypad(keypad) m_aioKeypad(keypad)
{ {

View File

@ -69,9 +69,9 @@ namespace upm
* @param d3 data 3 pin * @param d3 data 3 pin
* @param keypad analog pin of the keypad * @param keypad analog pin of the keypad
*/ */
SAINSMARTKS(uint8_t rs=8, uint8_t enable=9, SAINSMARTKS(int rs=8, int enable=9,
uint8_t d0=4, uint8_t d1=5, uint8_t d2=6, uint8_t d3=7, int d0=4, int d1=5, int d2=6, int d3=7,
uint8_t keypad=0); int keypad=0);
/** /**
* SAINSMARTKS destructor * SAINSMARTKS destructor
*/ */

View File

@ -49,8 +49,8 @@ Lcm1602::Lcm1602(int bus_in, int addr_in, bool isExpander,
": lcm1602_i2c_init failed"); ": lcm1602_i2c_init failed");
} }
Lcm1602::Lcm1602(uint8_t rs, uint8_t enable, uint8_t d0, Lcm1602::Lcm1602(int rs, int enable, int d0,
uint8_t d1, uint8_t d2, uint8_t d3, int d1, int d2, int d3,
uint8_t numColumns, uint8_t numRows) : uint8_t numColumns, uint8_t numRows) :
m_lcm1602(lcm1602_gpio_init(rs, enable, d0, d1, d2, d3, numColumns, m_lcm1602(lcm1602_gpio_init(rs, enable, d0, d1, d2, d3, numColumns,
numRows)) numRows))

View File

@ -99,8 +99,8 @@ namespace upm
* @param numColumns Number of columns the display has. Default 16. * @param numColumns Number of columns the display has. Default 16.
* @param numRows Number of rows the display has. Default 2. * @param numRows Number of rows the display has. Default 2.
*/ */
Lcm1602(uint8_t rs, uint8_t enable, Lcm1602(int rs, int enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, int d0, int d1, int d2, int d3,
uint8_t numColumns = 16, uint8_t numRows = 2); uint8_t numColumns = 16, uint8_t numRows = 2);
/** /**

View File

@ -32,7 +32,7 @@
using namespace upm; using namespace upm;
LPD8806::LPD8806 (uint16_t pixelCount, uint8_t csn) :m_spi(0), m_csnPinCtx(csn) { LPD8806::LPD8806 (uint16_t pixelCount, int csn) :m_spi(0), m_csnPinCtx(csn) {
mraa::Result error = mraa::SUCCESS; mraa::Result error = mraa::SUCCESS;
m_name = "LPD8806"; m_name = "LPD8806";

View File

@ -65,7 +65,7 @@ class LPD8806 {
* @param pixelCount Number of pixels in the strip * @param pixelCount Number of pixels in the strip
* @param csn Chip select pin * @param csn Chip select pin
*/ */
LPD8806 (uint16_t pixelCount, uint8_t csn); LPD8806 (uint16_t pixelCount, int csn);
/** /**
* LPD8806 object destructor; basically, it frees the allocated * LPD8806 object destructor; basically, it frees the allocated

View File

@ -0,0 +1,9 @@
upm_mixed_module_init (NAME mb704x
DESCRIPTION "MB7040/7047 I2C MaxSonar WR Ultrasonic Ranger"
C_HDR mb704x.h
C_SRC mb704x.c
CPP_HDR mb704x.hpp
CPP_SRC mb704x.cxx
FTI_SRC mb704x_fti.c
CPP_WRAPS_C
REQUIRES mraa)

View File

@ -0,0 +1,21 @@
%module javaupm_mb704x
%include "../upm.i"
%include "std_string.i"
%include "stdint.i"
%include "typemaps.i"
%include "mb704x.hpp"
%{
#include "mb704x.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_mb704x");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

View File

@ -0,0 +1,8 @@
%module jsupm_mb704x
%include "../upm.i"
%include "std_string.i"
%include "mb704x.hpp"
%{
#include "mb704x.hpp"
%}

115
src/mb704x/mb704x.c Normal file
View File

@ -0,0 +1,115 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <upm_utilities.h>
#include "mb704x.h"
// The delay to wait (in ms) for a ranging command to complete before
// requesting the range data.
#define MB704X_RANGE_DELAY (100)
// range command
#define MB704X_CMD_RANGE (81)
mb704x_context mb704x_init(unsigned int bus, int addr)
{
// make sure MRAA is initialized
int mraa_rv;
if ((mraa_rv = mraa_init()) != MRAA_SUCCESS)
{
printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv);
return NULL;
}
mb704x_context dev =
(mb704x_context)malloc(sizeof(struct _mb704x_context));
if (!dev)
return NULL;
// zero out context
memset((void *)dev, 0, sizeof(struct _mb704x_context));
// initialize the MRAA contexts
if (!(dev->i2c = mraa_i2c_init(bus)))
{
printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__);
mb704x_close(dev);
return NULL;
}
if (mraa_i2c_address(dev->i2c, (uint8_t)addr))
{
printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__);
mb704x_close(dev);
return NULL;
}
// max power up delay
upm_delay_ms(135);
return dev;
}
void mb704x_close(mb704x_context dev)
{
assert(dev != NULL);
if (dev->i2c)
mraa_i2c_stop(dev->i2c);
free(dev);
}
int mb704x_get_range(const mb704x_context dev)
{
assert(dev != NULL);
// first, send the range command.
uint8_t cmd = MB704X_CMD_RANGE;
if (mraa_i2c_write(dev->i2c, &cmd, 1))
{
printf("%s: mraa_i2c_write() failed.\n", __FUNCTION__);
return -1;
}
// delay for measurement
upm_delay_ms(MB704X_RANGE_DELAY);
// At this point, we should be able to do our read of the data
uint8_t buffer[2];
if (mraa_i2c_read(dev->i2c, buffer, 2) != 2)
{
printf("%s: mraa_i2c_read() failed.\n", __FUNCTION__);
return -1;
}
return ((buffer[0] << 8) | buffer[1]);
}

49
src/mb704x/mb704x.cxx Normal file
View File

@ -0,0 +1,49 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <iostream>
#include <stdexcept>
#include "mb704x.hpp"
using namespace upm;
using namespace std;
MB704X::MB704X(unsigned int bus, unsigned int addr) :
m_mb704x(mb704x_init(bus, addr))
{
if (!m_mb704x)
throw std::runtime_error(string(__FUNCTION__)
+ ": mb704x_*_init() failed");
}
MB704X::~MB704X()
{
mb704x_close(m_mb704x);
}
int MB704X::getRange()
{
return mb704x_get_range(m_mb704x);
}

78
src/mb704x/mb704x.h Normal file
View File

@ -0,0 +1,78 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <stdint.h>
#include <upm.h>
#include <mraa/i2c.h>
#include <mraa/gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file mb704x.h
* @library mb704x
* @brief C API for the MB704x MaxSonar-WR Ultrasonic Ranger
*
* @include mb704x.c
*/
/**
* Device context
*/
typedef struct _mb704x_context {
mraa_i2c_context i2c;
} *mb704x_context;
/**
* MB704X Initializer
*
* @param bus Specify which the I2C bus to use.
* @param addr Specify the I2C address to use. The default is 112.
* @return an initialized device context on success, NULL on error.
*/
mb704x_context mb704x_init(unsigned int bus, int addr);
/**
* MB704X sensor close function
*/
void mb704x_close(mb704x_context dev);
/**
* Query the device for a range reading. The range will be
* reported in centimeters (cm).
*
* @param dev Device context
* @return Measured range, -1 on error. The range is reported in
* centimeters (cm).
*/
int mb704x_get_range(const mb704x_context dev);
#ifdef __cplusplus
}
#endif

94
src/mb704x/mb704x.hpp Normal file
View File

@ -0,0 +1,94 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include "mb704x.h"
namespace upm {
/**
* @brief API for the MB704x MaxSonar-WR Ultrasonic Ranger
* @defgroup mb704x libupm-mb704x
* @ingroup i2c sound
*/
/**
* @library mb704x
* @sensor mb704x
* @comname MB704x MaxSonar-WR Ultrasonic Ranger
* @altname MB7040 MB7047 MB7247
* @type sound
* @man maxbotix
* @con i2c
* @web http://www.maxbotix.com/Ultrasonic_Sensors/I2C_Distance_Sensors.htm
*
* @brief API for the MB704x MaxSonar-WR Ultrasonic Ranger
*
* This driver was tested with the MB704x MaxSonar-WR Ultrasonic
* Ranger using the long distance, weather resistant horn.
* Depending on your sensor type and horn, tanges from 20cm to
* 750cm are possible.
*
* @snippet mb704x.cxx Interesting
*/
class MB704X {
public:
/**
* Initialize a device context.
*
* @param bus Specify which the I2C bus to use. The default is 0.
* @param addr Specify the I2C address to use. The default is 112.
*/
MB704X(unsigned int bus=0, unsigned int addr=112);
/**
* MB704X object destructor
*/
~MB704X();
/**
* Query the device for a range reading. The range will be
* reported in centimeters (cm).
*
* @param dev Device context
* @return Measured range, -1 on error. The range is reported in
* centimeters (cm).
*/
int getRange();
protected:
// mb704x device context
mb704x_context m_mb704x;
private:
};
}

113
src/mb704x/mb704x_fti.c Normal file
View File

@ -0,0 +1,113 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 "mb704x.h"
#include "upm_fti.h"
/**
* This file implements the Function Table Interface (FTI) for this sensor
*/
const char upm_mb704x_name[] = "MB704X";
const char upm_mb704x_description[] = "MB704x MaxSonar-WR Ultrasonic Ranger";
const upm_protocol_t upm_mb704x_protocol[] = {UPM_I2C};
const upm_sensor_t upm_mb704x_category[] = {UPM_DISTANCE};
// forward declarations
const void* upm_mb704x_get_ft(upm_sensor_t sensor_type);
void* upm_mb704x_init_name();
void upm_mb704x_close(void *dev);
upm_result_t upm_mb704x_get_distance(void *dev, float *value,
upm_distance_u unit);
const upm_sensor_descriptor_t upm_es08a_get_descriptor()
{
upm_sensor_descriptor_t usd;
usd.name = upm_mb704x_name;
usd.description = upm_mb704x_description;
usd.protocol_size = 1;
usd.protocol = upm_mb704x_protocol;
usd.category_size = 1;
usd.category = upm_mb704x_category;
return usd;
}
static const upm_sensor_ft ft =
{
.upm_sensor_init_name = &upm_mb704x_init_name,
.upm_sensor_close = &upm_mb704x_close,
};
static const upm_distance_ft dft =
{
.upm_distance_get_value = upm_mb704x_get_distance
};
const void* upm_mb704x_get_ft(upm_sensor_t sensor_type)
{
switch(sensor_type)
{
case UPM_SENSOR:
return &ft;
case UPM_DISTANCE:
return &dft;
default:
return NULL;
}
}
void *upm_mb704x_init_name()
{
return NULL;
}
void upm_mb704x_close(void *dev)
{
mb704x_close((mb704x_context)dev);
}
upm_result_t upm_mb704x_get_distance(void *dev, float *value,
upm_distance_u unit)
{
int rv;
if ((rv = mb704x_get_range((mb704x_context)dev)) < 0)
return UPM_ERROR_OPERATION_FAILED;
switch(unit)
{
case CENTIMETER:
*value = (float)rv;
case INCH:
*value = ((float)rv * 0.393701);
default:
return UPM_ERROR_INVALID_PARAMETER;
}
return UPM_SUCCESS;
}

12
src/mb704x/pyupm_mb704x.i Normal file
View File

@ -0,0 +1,12 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_mb704x
%include "../upm.i"
%include "std_string.i"
%feature("autodoc", "3");
%include "mb704x.hpp"
%{
#include "mb704x.hpp"
%}

View File

@ -44,7 +44,7 @@
using namespace upm; using namespace upm;
using namespace std; using namespace std;
GroveCircularLED::GroveCircularLED (uint8_t dataPin, uint8_t clockPin) GroveCircularLED::GroveCircularLED (int dataPin, int clockPin)
: MY9221(dataPin, clockPin, 2) : MY9221(dataPin, clockPin, 2)
{ {
// auto refresh by default // auto refresh by default

View File

@ -67,7 +67,7 @@ namespace upm {
* @param dataPin Data pin * @param dataPin Data pin
* @param clockPin Clock pin * @param clockPin Clock pin
*/ */
GroveCircularLED(uint8_t dataPin, uint8_t clockPin); GroveCircularLED(int dataPin, int clockPin);
/** /**
* GroveCircularLED destructor * GroveCircularLED destructor

View File

@ -44,7 +44,7 @@
using namespace upm; using namespace upm;
using namespace std; using namespace std;
GroveLEDBar::GroveLEDBar (uint8_t dataPin, uint8_t clockPin, int instances) GroveLEDBar::GroveLEDBar (int dataPin, int clockPin, int instances)
: MY9221(dataPin, clockPin, instances) : MY9221(dataPin, clockPin, instances)
{ {
// auto refresh by default // auto refresh by default

View File

@ -73,7 +73,7 @@ namespace upm {
* @param clockPin Clock pin * @param clockPin Clock pin
* @param instances Number of daisy-chained Grove LED Bars, default 1 * @param instances Number of daisy-chained Grove LED Bars, default 1
*/ */
GroveLEDBar(uint8_t dataPin, uint8_t clockPin, int instances=1); GroveLEDBar(int dataPin, int clockPin, int instances=1);
/** /**
* GroveLEDBar destructor * GroveLEDBar destructor

View File

@ -44,7 +44,7 @@
using namespace upm; using namespace upm;
using namespace std; using namespace std;
MY9221::MY9221 (uint8_t dataPin, uint8_t clockPin, int instances) : MY9221::MY9221 (int dataPin, int clockPin, int instances) :
m_my9221(my9221_init(dataPin, clockPin, instances)) m_my9221(my9221_init(dataPin, clockPin, instances))
{ {
if (!m_my9221) if (!m_my9221)

View File

@ -54,7 +54,7 @@ namespace upm {
* @param clockPin Clock pin * @param clockPin Clock pin
* @param instances Number of daisy-chained my9221s, default 1 * @param instances Number of daisy-chained my9221s, default 1
*/ */
MY9221(uint8_t dataPin, uint8_t clockPin, int instances=1); MY9221(int dataPin, int clockPin, int instances=1);
/** /**
* MY9221 destructor * MY9221 destructor

View File

@ -34,14 +34,14 @@
using namespace upm; using namespace upm;
NRF24L01::NRF24L01 (uint8_t cs, uint8_t ce) NRF24L01::NRF24L01 (int cs, int ce)
:m_spi(0), m_csnPinCtx(cs), m_cePinCtx(ce) :m_spi(0), m_csnPinCtx(cs), m_cePinCtx(ce)
{ {
init (cs, ce); init (cs, ce);
} }
void void
NRF24L01::init (uint8_t chip_select, uint8_t chip_enable) { NRF24L01::init (int chip_select, int chip_enable) {
mraa::Result error = mraa::SUCCESS; mraa::Result error = mraa::SUCCESS;
m_csn = chip_select; m_csn = chip_select;

View File

@ -192,7 +192,7 @@ class NRF24L01 {
* *
* @param cs Chip select pin * @param cs Chip select pin
*/ */
NRF24L01 (uint8_t cs, uint8_t ce); NRF24L01 (int cs, int ce);
/** /**
* Returns the name of the component * Returns the name of the component
@ -208,7 +208,7 @@ class NRF24L01 {
* @param chipSelect Sets up the chip select pin * @param chipSelect Sets up the chip select pin
* @param chipEnable Sets up the chip enable pin * @param chipEnable Sets up the chip enable pin
*/ */
void init (uint8_t chipSelect, uint8_t chipEnable); void init (int chipSelect, int chipEnable);
/** /**
* Configures the NRF24L01 transceiver * Configures the NRF24L01 transceiver

5
src/rf22/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
set (libname "rf22")
set (libdescription "HopeRF RFM22B ISM Band Radio Module")
set (module_src ${libname}.cxx)
set (module_hpp ${libname}.hpp)
upm_module_init()

24
src/rf22/javaupm_rf22.i Normal file
View File

@ -0,0 +1,24 @@
%module(directors="1") javaupm_rf22
%include "../upm.i"
%include "arrays_java.i"
%include "typemaps.i"
%apply uint8_t *INOUT { uint8_t* len };
%apply signed char[] {uint8_t*};
%{
#include "rf22.hpp"
%}
%include "rf22.hpp"
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_rf22");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

9
src/rf22/jsupm_rf22.i Normal file
View File

@ -0,0 +1,9 @@
%module jsupm_rf22
%include "../upm.i"
%include "../carrays_uint8_t.i"
%{
#include "rf22.hpp"
%}
%include "rf22.hpp"

12
src/rf22/pyupm_rf22.i Normal file
View File

@ -0,0 +1,12 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_rf22
%include "../upm.i"
%include "../carrays_uint8_t.i"
%feature("autodoc", "3");
%include "rf22.hpp"
%{
#include "rf22.hpp"
%}

766
src/rf22/rf22.cxx Normal file
View File

@ -0,0 +1,766 @@
/*
* Author: Kiveisha Yevgeniy
* Copyright (c) 2015-2016 Intel Corporation
*
* Author: Mike McCauley
* Copyright (c) 2011 Mike McCauley
*
* 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 <cstring>
#include <cmath>
#include <sys/time.h>
#include <rf22.hpp>
using namespace upm;
// These are indexed by the values of ModemConfigChoice
// Canned modem configurations generated with
// http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
// Stored in flash (program) memory to save SRAM
static const RF22::ModemConfig MODEM_CONFIG_TABLE[] =
{
{ 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier
{ 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5
// All the following enable FIFO with reg 71
// 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72
// FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
{ 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5
{ 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x3a }, // 2.4, 36
{ 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x22, 0x48 }, // 4.8, 45
{ 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x22, 0x48 }, // 9.6, 45
{ 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x22, 0x0f }, // 19.2, 9.6
{ 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x22, 0x1f }, // 38.4, 19.6
{ 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x22, 0x2e }, // 57.6. 28.8
{ 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x22, 0xc8 }, // 125, 125
// GFSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
// These differ from FSK only in register 71, for the modulation type
{ 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x23, 0x08 }, // 2, 5
{ 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x23, 0x3a }, // 2.4, 36
{ 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x23, 0x48 }, // 4.8, 45
{ 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x23, 0x48 }, // 9.6, 45
{ 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x23, 0x0f }, // 19.2, 9.6
{ 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x23, 0x1f }, // 38.4, 19.6
{ 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x23, 0x2e }, // 57.6. 28.8
{ 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x23, 0xc8 }, // 125, 125
// OOK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
{ 0x51, 0x03, 0x68, 0x00, 0x3a, 0x93, 0x01, 0x3d, 0x2c, 0x11, 0x28, 0x80, 0x60, 0x09, 0xd5, 0x2c, 0x21, 0x08 }, // 1.2, 75
{ 0xc8, 0x03, 0x39, 0x20, 0x68, 0xdc, 0x00, 0x6b, 0x2a, 0x08, 0x2a, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x21, 0x08 }, // 2.4, 335
{ 0xc8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x29, 0x04, 0x29, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x21, 0x08 }, // 4.8, 335
{ 0xb8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x82, 0x29, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x21, 0x08 }, // 9.6, 335
{ 0xa8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x41, 0x29, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x21, 0x08 }, // 19.2, 335
{ 0x98, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x20, 0x29, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x21, 0x08 }, // 38.4, 335
{ 0x98, 0x03, 0x96, 0x00, 0xda, 0x74, 0x00, 0xdc, 0x28, 0x1f, 0x29, 0x80, 0x60, 0x0a, 0x3d, 0x0c, 0x21, 0x08 }, // 40, 335
};
RF22::RF22(int spiBus, int slaveSelectPin, int interruptPin)
{
_idleMode = RF22_XTON; // Default idle state is READY mode
_mode = RF22_MODE_IDLE; // We start up in idle mode
_rxGood = 0;
_rxBad = 0;
_txGood = 0;
//Initialize the SPI bus and pins, MRAA will log any failures here
// start the SPI library:
// Note the RF22 wants mode 0, MSB first and default to 1 Mbps
_spi = mraa_spi_init(spiBus);
mraa_spi_mode (_spi, MRAA_SPI_MODE0);
mraa_spi_lsbmode(_spi, 0);
mraa_spi_frequency(_spi, 1000000); // 1Mhz
_cs = mraa_gpio_init(slaveSelectPin);
mraa_gpio_dir(_cs, MRAA_GPIO_OUT);
_irq = mraa_gpio_init(interruptPin);
mraa_gpio_dir(_irq, MRAA_GPIO_IN);
mraa_gpio_isr(_irq, MRAA_GPIO_EDGE_FALLING, &isr, (void*)this);
}
RF22::~RF22()
{
mraa_spi_stop(_spi);
mraa_gpio_close(_cs);
mraa_gpio_close(_irq);
}
uint8_t RF22::init()
{
// Wait for RF22 POR (up to 16msec)
usleep (16);
// Initialise the slave select pin
mraa_gpio_write(_cs, 0x1);
usleep (100);
// Software reset the device
reset();
// Get the device type and check it
// This also tests whether we are really connected to a device
_deviceType = spiRead(RF22_REG_00_DEVICE_TYPE);
if ( _deviceType != RF22_DEVICE_TYPE_RX_TRX
&& _deviceType != RF22_DEVICE_TYPE_TX)
return 0;
clearTxBuf();
clearRxBuf();
// Most of these are the POR default
spiWrite(RF22_REG_7D_TX_FIFO_CONTROL2, RF22_TXFFAEM_THRESHOLD);
spiWrite(RF22_REG_7E_RX_FIFO_CONTROL, RF22_RXFFAFULL_THRESHOLD);
spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_ENPACRX | RF22_ENPACTX | RF22_ENCRC | RF22_CRC_CRC_16_IBM);
// Configure the message headers
// Here we set up the standard packet format for use by the RF22 library
// 8 nibbles preamble
// 2 SYNC words 2d, d4
// Header length 4 (to, from, id, flags)
// 1 octet of data length (0 to 255)
// 0 to 255 octets data
// 2 CRC octets as CRC16(IBM), computed on the header, length and data
// On reception the to address is check for validity against RF22_REG_3F_CHECK_HEADER3
// or the broadcast address of 0xff
// If no changes are made after this, the transmitted
// to address will be 0xff, the from address will be 0xff
// and all such messages will be accepted. This permits the out-of the box
// RF22 config to act as an unaddresed, unreliable datagram service
spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_HEADER3 | RF22_HDCH_HEADER3);
spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_4 | RF22_SYNCLEN_2);
setPreambleLength(8);
uint8_t syncwords[] = { 0x2d, 0xd4 };
setSyncWords(syncwords, sizeof(syncwords));
setPromiscuous(0);
// Check the TO header against RF22_DEFAULT_NODE_ADDRESS
spiWrite(RF22_REG_3F_CHECK_HEADER3, RF22_DEFAULT_NODE_ADDRESS);
// Set the default transmit header values
setHeaderTo(RF22_DEFAULT_NODE_ADDRESS);
setHeaderFrom(RF22_DEFAULT_NODE_ADDRESS);
setHeaderId(0);
setHeaderFlags(0);
// Ensure the antenna can be switched automatically according to transmit and receive
// This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit
// This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive
spiWrite (RF22_REG_0B_GPIO_CONFIGURATION0, 0x12) ; // TX state
spiWrite (RF22_REG_0C_GPIO_CONFIGURATION1, 0x15) ; // RX state
// Enable interrupts
spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR);
spiWrite(RF22_REG_06_INTERRUPT_ENABLE2, RF22_ENPREAVAL);
// Set some defaults. An innocuous ISM frequency, and reasonable pull-in
setFrequency(434.0, 0.05);
// setFrequency(900.0);
// Some slow, reliable default speed and modulation
setModemConfig(FSK_Rb2_4Fd36);
// setModemConfig(FSK_Rb125Fd125);
// Minimum power
setTxPower(RF22_TXPOW_8DBM);
// setTxPower(RF22_TXPOW_17DBM);
return 1;
}
// C++ level interrupt handler for this instance
void RF22::handleInterrupt()
{
uint8_t _lastInterruptFlags[2];
// Read the interrupt flags which clears the interrupt
spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2);
if (_lastInterruptFlags[0] & RF22_IFFERROR)
{
resetFifos(); // Clears the interrupt
if (_mode == RF22_MODE_TX)
restartTransmit();
else if (_mode == RF22_MODE_RX)
clearRxBuf();
}
// Caution, any delay here may cause a FF underflow or overflow
if (_lastInterruptFlags[0] & RF22_ITXFFAEM)
{
// See if more data has to be loaded into the Tx FIFO
sendNextFragment();
}
if (_lastInterruptFlags[0] & RF22_IRXFFAFULL)
{
// Caution, any delay here may cause a FF overflow
// Read some data from the Rx FIFO
readNextFragment();
}
if (_lastInterruptFlags[0] & RF22_IEXT)
{
// This is not enabled by the base code, but users may want to enable it
handleExternalInterrupt();
}
if (_lastInterruptFlags[1] & RF22_IWUT)
{
// This is not enabled by the base code, but users may want to enable it
handleWakeupTimerInterrupt();
}
if (_lastInterruptFlags[0] & RF22_IPKSENT)
{
_txGood++;
// Transmission does not automatically clear the tx buffer.
// Could retransmit if we wanted
// RF22 transitions automatically to Idle
_mode = RF22_MODE_IDLE;
}
if (_lastInterruptFlags[0] & RF22_IPKVALID)
{
uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH);
// May have already read one or more fragments
// Get any remaining unread octets, based on the expected length
// First make sure we dont overflow the buffer in the case of a stupid length
// or partial bad receives
if ( len > RF22_MAX_MESSAGE_LEN
|| len < _bufLen)
{
_rxBad++;
_mode = RF22_MODE_IDLE;
clearRxBuf();
return; // Hmmm receiver buffer overflow.
}
spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen);
_rxGood++;
_bufLen = len;
_mode = RF22_MODE_IDLE;
_rxBufValid = true;
}
if (_lastInterruptFlags[0] & RF22_ICRCERROR)
{
_rxBad++;
clearRxBuf();
resetRxFifo();
_mode = RF22_MODE_IDLE;
setModeRx(); // Keep trying
}
if (_lastInterruptFlags[1] & RF22_IPREAVAL)
{
_lastRssi = spiRead(RF22_REG_26_RSSI);
clearRxBuf();
}
}
void RF22::isr(void* args)
{
RF22* This = (RF22*)(args);
This->handleInterrupt();
}
void RF22::reset()
{
spiWrite(RF22_REG_07_OPERATING_MODE1, RF22_SWRES);
// Wait for it to settle
usleep(100); // SWReset time is nominally 100usec
}
uint8_t RF22::spiRead(uint8_t reg)
{
uint8_t data;
spiBurstRead (reg, &data, 1);
return data;
}
void RF22::spiWrite(uint8_t reg, uint8_t val)
{
spiBurstWrite (reg, &val, 1);
}
void RF22::spiBurstRead(uint8_t reg, uint8_t* dest, uint8_t len)
{
uint8_t *request;
uint8_t *response;
request = (uint8_t *) malloc(sizeof(uint8_t) * (len + 1));
response = (uint8_t *) malloc(sizeof(uint8_t) * (len + 1));
memset(request, 0x00, len + 1);
memset(response, 0x00, len + 1);
request[0] = reg & ~RF22_SPI_WRITE_MASK;
memcpy (&request[1], dest, len);
mraa_gpio_write(_cs, 0x1);
mraa_gpio_write(_cs, 0x0);
usleep(100);
mraa_spi_transfer_buf(_spi, request, response, len + 1);
usleep(100);
mraa_gpio_write(_cs, 0x1);
memcpy (dest, &response[1], len);
free (request);
free (response);
}
void RF22::spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len)
{
uint8_t *request;
uint8_t *response;
request = (uint8_t *) malloc(sizeof(uint8_t) * (len + 1));
response = (uint8_t *) malloc(sizeof(uint8_t) * (len + 1));
memset(request, 0x00, len + 1);
memset(response, 0x00, len + 1);
request[0] = reg | RF22_SPI_WRITE_MASK;
memcpy (&request[1], src, len);
mraa_gpio_write(_cs, 0x1);
mraa_gpio_write(_cs, 0x0);
usleep(100);
mraa_spi_transfer_buf(_spi, request, response, len + 1);
usleep(100);
mraa_gpio_write(_cs, 0x1);
free (request);
free (response);
}
uint8_t RF22::statusRead()
{
return spiRead(RF22_REG_02_DEVICE_STATUS);
}
uint8_t RF22::adcRead(uint8_t adcsel,
uint8_t adcref ,
uint8_t adcgain,
uint8_t adcoffs)
{
uint8_t configuration = adcsel | adcref | (adcgain & RF22_ADCGAIN);
spiWrite(RF22_REG_0F_ADC_CONFIGURATION, configuration | RF22_ADCSTART);
spiWrite(RF22_REG_10_ADC_SENSOR_AMP_OFFSET, adcoffs);
// Conversion time is nominally 305usec
// Wait for the DONE bit
while (!(spiRead(RF22_REG_0F_ADC_CONFIGURATION) & RF22_ADCDONE))
;
// Return the value
return spiRead(RF22_REG_11_ADC_VALUE);
}
uint8_t RF22::temperatureRead(uint8_t tsrange, uint8_t tvoffs)
{
spiWrite(RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION, tsrange | RF22_ENTSOFFS);
spiWrite(RF22_REG_13_TEMPERATURE_VALUE_OFFSET, tvoffs);
return adcRead(RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RF22_ADCREF_BANDGAP_VOLTAGE);
}
uint16_t RF22::wutRead()
{
uint8_t buf[2];
spiBurstRead(RF22_REG_17_WAKEUP_TIMER_VALUE1, buf, 2);
return ((uint16_t)buf[0] << 8) | buf[1]; // Dont rely on byte order
}
// RFM-22 doc appears to be wrong: WUT for wtm = 10000, r, = 0, d = 0 is about 1 sec
void RF22::setWutPeriod(uint16_t wtm, uint8_t wtr, uint8_t wtd)
{
uint8_t period[3];
period[0] = ((wtr & 0xf) << 2) | (wtd & 0x3);
period[1] = wtm >> 8;
period[2] = wtm & 0xff;
spiBurstWrite(RF22_REG_14_WAKEUP_TIMER_PERIOD1, period, sizeof(period));
}
// Returns true if center + (fhch * fhs) is within limits
// Caution, different versions of the RF22 support different max freq
// so YMMV
uint8_t RF22::setFrequency(float center, float afcPullInRange)
{
uint8_t fbsel = RF22_SBSEL;
uint8_t afclimiter;
if (center < 240.0 || center > 960.0) // 930.0 for early silicon
return false;
if (center >= 480.0)
{
if (afcPullInRange < 0.0 || afcPullInRange > 0.318750)
return false;
center /= 2;
fbsel |= RF22_HBSEL;
afclimiter = afcPullInRange * 1000000.0 / 1250.0;
}
else
{
if (afcPullInRange < 0.0 || afcPullInRange > 0.159375)
return false;
afclimiter = afcPullInRange * 1000000.0 / 625.0;
}
center /= 10.0;
float integerPart = floor(center);
float fractionalPart = center - integerPart;
uint8_t fb = (uint8_t)integerPart - 24; // Range 0 to 23
fbsel |= fb;
uint16_t fc = fractionalPart * 64000;
spiWrite(RF22_REG_73_FREQUENCY_OFFSET1, 0); // REVISIT
spiWrite(RF22_REG_74_FREQUENCY_OFFSET2, 0);
spiWrite(RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel);
spiWrite(RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8);
spiWrite(RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff);
spiWrite(RF22_REG_2A_AFC_LIMITER, afclimiter);
return !(statusRead() & RF22_FREQERR);
}
// Step size in 10kHz increments
// Returns true if centre + (fhch * fhs) is within limits
uint8_t RF22::setFHStepSize(uint8_t fhs)
{
spiWrite(RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE, fhs);
return !(statusRead() & RF22_FREQERR);
}
// Adds fhch * fhs to centre frequency
// Returns true if centre + (fhch * fhs) is within limits
uint8_t RF22::setFHChannel(uint8_t fhch)
{
spiWrite(RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT, fhch);
return !(statusRead() & RF22_FREQERR);
}
uint8_t RF22::rssiRead()
{
return spiRead(RF22_REG_26_RSSI);
}
uint8_t RF22::ezmacStatusRead()
{
return spiRead(RF22_REG_31_EZMAC_STATUS);
}
void RF22::setMode(uint8_t mode)
{
spiWrite(RF22_REG_07_OPERATING_MODE1, mode);
}
void RF22::setModeIdle()
{
if (_mode != RF22_MODE_IDLE)
{
setMode(_idleMode);
_mode = RF22_MODE_IDLE;
}
}
void RF22::setModeRx()
{
if (_mode != RF22_MODE_RX)
{
setMode(_idleMode | RF22_RXON);
_mode = RF22_MODE_RX;
}
}
void RF22::setModeTx()
{
if (_mode != RF22_MODE_TX)
{
setMode(_idleMode | RF22_TXON);
_mode = RF22_MODE_TX;
// Hmmm, if you dont clear the RX FIFO here, then it appears that going
// to transmit mode in the middle of a receive can corrupt the
// RX FIFO
resetRxFifo();
clearRxBuf();
}
}
uint8_t RF22::mode()
{
return _mode;
}
void RF22::setTxPower(uint8_t power)
{
spiWrite(RF22_REG_6D_TX_POWER, power);
}
// Sets registers from a canned modem configuration structure
void RF22::setModemRegisters(const ModemConfig* config)
{
spiWrite(RF22_REG_1C_IF_FILTER_BANDWIDTH, config->reg_1c);
spiWrite(RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE, config->reg_1f);
spiBurstWrite(RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE, &config->reg_20, 6);
spiBurstWrite(RF22_REG_2C_OOK_COUNTER_VALUE_1, &config->reg_2c, 3);
spiWrite(RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING, config->reg_58);
spiWrite(RF22_REG_69_AGC_OVERRIDE1, config->reg_69);
spiBurstWrite(RF22_REG_6E_TX_DATA_RATE1, &config->reg_6e, 5);
}
// Set one of the canned FSK Modem configs
// Returns true if its a valid choice
uint8_t RF22::setModemConfig(ModemConfigChoice index)
{
if (index > (sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
return false;
RF22::ModemConfig cfg;
// memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RF22::ModemConfig)); // !!!!!!!!!!!!!!!!!!! MIGHT CAUSE ISSUES
memcpy(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RF22::ModemConfig));
setModemRegisters(&cfg);
return true;
}
// REVISIT: top bit is in Header Control 2 0x33
void RF22::setPreambleLength(uint8_t nibbles)
{
spiWrite(RF22_REG_34_PREAMBLE_LENGTH, nibbles);
}
// Caution doesnt set sync word len in Header Control 2 0x33
void RF22::setSyncWords(const uint8_t* syncWords, uint8_t len)
{
spiBurstWrite(RF22_REG_36_SYNC_WORD3, syncWords, len);
}
void RF22::clearRxBuf()
{
_bufLen = 0;
_rxBufValid = false;
}
uint8_t RF22::available()
{
if (!_rxBufValid)
setModeRx(); // Make sure we are receiving
return _rxBufValid;
}
// Blocks until a valid message is received
void RF22::waitAvailable()
{
while (!available())
;
}
// Blocks until a valid message is received or timeout expires
// Return true if there is a message available
bool RF22::waitAvailableTimeout(unsigned long timeout)
{
unsigned long endtime = getTimestamp() + timeout;
unsigned long currenttime = getTimestamp();
while (currenttime < endtime) {
currenttime = getTimestamp();
if (available()) {
return true;
}
}
return false;
}
void RF22::waitPacketSent()
{
while (_mode == RF22_MODE_TX)
; // Wait for any previous transmit to finish
}
// Diagnostic help
void RF22::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len)
{
}
uint8_t RF22::recv(uint8_t* buf, uint8_t* len)
{
if (!available())
return false;
if (*len > _bufLen)
*len = _bufLen;
memcpy(buf, _buf, *len);
clearRxBuf();
return true;
}
void RF22::clearTxBuf()
{
_bufLen = 0;
_txBufSentIndex = 0;
}
void RF22::startTransmit()
{
sendNextFragment(); // Actually the first fragment
spiWrite(RF22_REG_3E_PACKET_LENGTH, _bufLen); // Total length that will be sent
setModeTx(); // Start the transmitter, turns off the receiver
}
// Restart the transmission of a packet that had a problem
void RF22::restartTransmit()
{
_mode = RF22_MODE_IDLE;
_txBufSentIndex = 0;
startTransmit();
}
uint8_t RF22::send(const uint8_t* data, uint8_t len)
{
waitPacketSent();
if (!fillTxBuf(data, len))
return false;
startTransmit();
return true;
}
uint8_t RF22::fillTxBuf(const uint8_t* data, uint8_t len)
{
clearTxBuf();
if (!len)
return false;
return appendTxBuf(data, len);
}
uint8_t RF22::appendTxBuf(const uint8_t* data, uint8_t len)
{
if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN)
return false;
memcpy(_buf + _bufLen, data, len);
_bufLen += len;
return true;
}
// Assumption: there is currently <= RF22_TXFFAEM_THRESHOLD bytes in the Tx FIFO
void RF22::sendNextFragment()
{
if (_txBufSentIndex < _bufLen)
{
// Some left to send?
uint8_t len = _bufLen - _txBufSentIndex;
// But dont send too much
if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1))
len = (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1);
spiBurstWrite(RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len);
_txBufSentIndex += len;
}
}
// Assumption: there are at least RF22_RXFFAFULL_THRESHOLD in the RX FIFO
// That means it should only be called after a RXFFAFULL interrupt
void RF22::readNextFragment()
{
if (((uint16_t)_bufLen + RF22_RXFFAFULL_THRESHOLD) > RF22_MAX_MESSAGE_LEN)
return; // Hmmm receiver overflow. Should never occur
// Read the RF22_RXFFAFULL_THRESHOLD octets that should be there
spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RF22_RXFFAFULL_THRESHOLD);
_bufLen += RF22_RXFFAFULL_THRESHOLD;
}
// Clear the FIFOs
void RF22::resetFifos()
{
spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRRX | RF22_FFCLRTX);
spiWrite(RF22_REG_08_OPERATING_MODE2, 0);
}
// Clear the Rx FIFO
void RF22::resetRxFifo()
{
spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRRX);
spiWrite(RF22_REG_08_OPERATING_MODE2, 0);
}
// CLear the TX FIFO
void RF22::resetTxFifo()
{
spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRTX);
spiWrite(RF22_REG_08_OPERATING_MODE2, 0);
}
// Default implmentation does nothing. Override if you wish
void RF22::handleExternalInterrupt()
{
}
// Default implmentation does nothing. Override if you wish
void RF22::handleWakeupTimerInterrupt()
{
}
void RF22::setHeaderTo(uint8_t to)
{
spiWrite(RF22_REG_3A_TRANSMIT_HEADER3, to);
}
void RF22::setHeaderFrom(uint8_t from)
{
spiWrite(RF22_REG_3B_TRANSMIT_HEADER2, from);
}
void RF22::setHeaderId(uint8_t id)
{
spiWrite(RF22_REG_3C_TRANSMIT_HEADER1, id);
}
void RF22::setHeaderFlags(uint8_t flags)
{
spiWrite(RF22_REG_3D_TRANSMIT_HEADER0, flags);
}
uint8_t RF22::headerTo()
{
return spiRead(RF22_REG_47_RECEIVED_HEADER3);
}
uint8_t RF22::headerFrom()
{
return spiRead(RF22_REG_48_RECEIVED_HEADER2);
}
uint8_t RF22::headerId()
{
return spiRead(RF22_REG_49_RECEIVED_HEADER1);
}
uint8_t RF22::headerFlags()
{
return spiRead(RF22_REG_4A_RECEIVED_HEADER0);
}
uint8_t RF22::lastRssi()
{
return _lastRssi;
}
void RF22::setPromiscuous(uint8_t promiscuous)
{
spiWrite(RF22_REG_43_HEADER_ENABLE3, promiscuous ? 0x00 : 0xff);
}
uint64_t
RF22::getTimestamp () {
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)(1000000 * tv.tv_sec + tv.tv_usec);
}

987
src/rf22/rf22.hpp Normal file
View File

@ -0,0 +1,987 @@
/*
* Author: Kiveisha Yevgeniy
* Copyright (c) 2015-2016 Intel Corporation
*
* Author: Mike McCauley
* Copyright (c) 2011 Mike McCauley
*
* 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 <stdint.h>
#include <mraa.h>
// This is the bit in the SPI address that marks it as a write
#define RF22_SPI_WRITE_MASK 0x80
// This is the maximum message length that can be supported by this library. Limited by
// the single message length octet in the header.
// Yes, 255 is correct even though the FIFO size in the RF22 is only
// 64 octets. We use interrupts to refill the Tx FIFO during transmission and to empty the
// Rx FIFO during reception
// Can be pre-defined to a smaller size (to save SRAM) prior to including this header
#ifndef RF22_MAX_MESSAGE_LEN
//#define RF22_MAX_MESSAGE_LEN 255
#define RF22_MAX_MESSAGE_LEN 50
#endif
// Max number of octets the RF22 Rx and Tx FIFOs can hold
#define RF22_FIFO_SIZE 64
// Keep track of the mode the RF22 is in
#define RF22_MODE_IDLE 0
#define RF22_MODE_RX 1
#define RF22_MODE_TX 2
// These values we set for FIFO thresholds are actually the same as the POR values
#define RF22_TXFFAEM_THRESHOLD 4
#define RF22_RXFFAFULL_THRESHOLD 55
// This is the default node address,
#define RF22_DEFAULT_NODE_ADDRESS 0
// This address in the TO address signifies a broadcast
#define RF22_BROADCAST_ADDRESS 0xff
// Number of registers to be passed to setModemConfig()
#define RF22_NUM_MODEM_CONFIG_REGS 18
// Register names
#define RF22_REG_00_DEVICE_TYPE 0x00
#define RF22_REG_01_VERSION_CODE 0x01
#define RF22_REG_02_DEVICE_STATUS 0x02
#define RF22_REG_03_INTERRUPT_STATUS1 0x03
#define RF22_REG_04_INTERRUPT_STATUS2 0x04
#define RF22_REG_05_INTERRUPT_ENABLE1 0x05
#define RF22_REG_06_INTERRUPT_ENABLE2 0x06
#define RF22_REG_07_OPERATING_MODE1 0x07
#define RF22_REG_08_OPERATING_MODE2 0x08
#define RF22_REG_09_OSCILLATOR_LOAD_CAPACITANCE 0x09
#define RF22_REG_0A_UC_OUTPUT_CLOCK 0x0a
#define RF22_REG_0B_GPIO_CONFIGURATION0 0x0b
#define RF22_REG_0C_GPIO_CONFIGURATION1 0x0c
#define RF22_REG_0D_GPIO_CONFIGURATION2 0x0d
#define RF22_REG_0E_IO_PORT_CONFIGURATION 0x0e
#define RF22_REG_0F_ADC_CONFIGURATION 0x0f
#define RF22_REG_10_ADC_SENSOR_AMP_OFFSET 0x10
#define RF22_REG_11_ADC_VALUE 0x11
#define RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION 0x12
#define RF22_REG_13_TEMPERATURE_VALUE_OFFSET 0x13
#define RF22_REG_14_WAKEUP_TIMER_PERIOD1 0x14
#define RF22_REG_15_WAKEUP_TIMER_PERIOD2 0x15
#define RF22_REG_16_WAKEUP_TIMER_PERIOD3 0x16
#define RF22_REG_17_WAKEUP_TIMER_VALUE1 0x17
#define RF22_REG_18_WAKEUP_TIMER_VALUE2 0x18
#define RF22_REG_19_LDC_MODE_DURATION 0x19
#define RF22_REG_1A_LOW_BATTERY_DETECTOR_THRESHOLD 0x1a
#define RF22_REG_1B_BATTERY_VOLTAGE_LEVEL 0x1b
#define RF22_REG_1C_IF_FILTER_BANDWIDTH 0x1c
#define RF22_REG_1D_AFC_LOOP_GEARSHIFT_OVERRIDE 0x1d
#define RF22_REG_1E_AFC_TIMING_CONTROL 0x1e
#define RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE 0x1f
#define RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE 0x20
#define RF22_REG_21_CLOCK_RECOVERY_OFFSET2 0x21
#define RF22_REG_22_CLOCK_RECOVERY_OFFSET1 0x22
#define RF22_REG_23_CLOCK_RECOVERY_OFFSET0 0x23
#define RF22_REG_24_CLOCK_RECOVERY_TIMING_LOOP_GAIN1 0x24
#define RF22_REG_25_CLOCK_RECOVERY_TIMING_LOOP_GAIN0 0x25
#define RF22_REG_26_RSSI 0x26
#define RF22_REG_27_RSSI_THRESHOLD 0x27
#define RF22_REG_28_ANTENNA_DIVERSITY1 0x28
#define RF22_REG_29_ANTENNA_DIVERSITY2 0x29
#define RF22_REG_2A_AFC_LIMITER 0x2a
#define RF22_REG_2B_AFC_CORRECTION_READ 0x2b
#define RF22_REG_2C_OOK_COUNTER_VALUE_1 0x2c
#define RF22_REG_2D_OOK_COUNTER_VALUE_2 0x2d
#define RF22_REG_2E_SLICER_PEAK_HOLD 0x2e
#define RF22_REG_30_DATA_ACCESS_CONTROL 0x30
#define RF22_REG_31_EZMAC_STATUS 0x31
#define RF22_REG_32_HEADER_CONTROL1 0x32
#define RF22_REG_33_HEADER_CONTROL2 0x33
#define RF22_REG_34_PREAMBLE_LENGTH 0x34
#define RF22_REG_35_PREAMBLE_DETECTION_CONTROL1 0x35
#define RF22_REG_36_SYNC_WORD3 0x36
#define RF22_REG_37_SYNC_WORD2 0x37
#define RF22_REG_38_SYNC_WORD1 0x38
#define RF22_REG_39_SYNC_WORD0 0x39
#define RF22_REG_3A_TRANSMIT_HEADER3 0x3a
#define RF22_REG_3B_TRANSMIT_HEADER2 0x3b
#define RF22_REG_3C_TRANSMIT_HEADER1 0x3c
#define RF22_REG_3D_TRANSMIT_HEADER0 0x3d
#define RF22_REG_3E_PACKET_LENGTH 0x3e
#define RF22_REG_3F_CHECK_HEADER3 0x3f
#define RF22_REG_40_CHECK_HEADER2 0x40
#define RF22_REG_41_CHECK_HEADER1 0x41
#define RF22_REG_42_CHECK_HEADER0 0x42
#define RF22_REG_43_HEADER_ENABLE3 0x43
#define RF22_REG_44_HEADER_ENABLE2 0x44
#define RF22_REG_45_HEADER_ENABLE1 0x45
#define RF22_REG_46_HEADER_ENABLE0 0x46
#define RF22_REG_47_RECEIVED_HEADER3 0x47
#define RF22_REG_48_RECEIVED_HEADER2 0x48
#define RF22_REG_49_RECEIVED_HEADER1 0x49
#define RF22_REG_4A_RECEIVED_HEADER0 0x4a
#define RF22_REG_4B_RECEIVED_PACKET_LENGTH 0x4b
#define RF22_REG_50_ANALOG_TEST_BUS_SELECT 0x50
#define RF22_REG_51_DIGITAL_TEST_BUS_SELECT 0x51
#define RF22_REG_52_TX_RAMP_CONTROL 0x52
#define RF22_REG_53_PLL_TUNE_TIME 0x53
#define RF22_REG_55_CALIBRATION_CONTROL 0x55
#define RF22_REG_56_MODEM_TEST 0x56
#define RF22_REG_57_CHARGE_PUMP_TEST 0x57
#define RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING 0x58
#define RF22_REG_59_DIVIDER_CURRENT_TRIMMING 0x59
#define RF22_REG_5A_VCO_CURRENT_TRIMMING 0x5a
#define RF22_REG_5B_VCO_CALIBRATION 0x5b
#define RF22_REG_5C_SYNTHESIZER_TEST 0x5c
#define RF22_REG_5D_BLOCK_ENABLE_OVERRIDE1 0x5d
#define RF22_REG_5E_BLOCK_ENABLE_OVERRIDE2 0x5e
#define RF22_REG_5F_BLOCK_ENABLE_OVERRIDE3 0x5f
#define RF22_REG_60_CHANNEL_FILTER_COEFFICIENT_ADDRESS 0x60
#define RF22_REG_61_CHANNEL_FILTER_COEFFICIENT_VALUE 0x61
#define RF22_REG_62_CRYSTAL_OSCILLATOR_POR_CONTROL 0x62
#define RF22_REG_63_RC_OSCILLATOR_COARSE_CALIBRATION 0x63
#define RF22_REG_64_RC_OSCILLATOR_FINE_CALIBRATION 0x64
#define RF22_REG_65_LDO_CONTROL_OVERRIDE 0x65
#define RF22_REG_66_LDO_LEVEL_SETTINGS 0x66
#define RF22_REG_67_DELTA_SIGMA_ADC_TUNING1 0x67
#define RF22_REG_68_DELTA_SIGMA_ADC_TUNING2 0x68
#define RF22_REG_69_AGC_OVERRIDE1 0x69
#define RF22_REG_6A_AGC_OVERRIDE2 0x6a
#define RF22_REG_6B_GFSK_FIR_FILTER_COEFFICIENT_ADDRESS 0x6b
#define RF22_REG_6C_GFSK_FIR_FILTER_COEFFICIENT_VALUE 0x6c
#define RF22_REG_6D_TX_POWER 0x6d
#define RF22_REG_6E_TX_DATA_RATE1 0x6e
#define RF22_REG_6F_TX_DATA_RATE0 0x6f
#define RF22_REG_70_MODULATION_CONTROL1 0x70
#define RF22_REG_71_MODULATION_CONTROL2 0x71
#define RF22_REG_72_FREQUENCY_DEVIATION 0x72
#define RF22_REG_73_FREQUENCY_OFFSET1 0x73
#define RF22_REG_74_FREQUENCY_OFFSET2 0x74
#define RF22_REG_75_FREQUENCY_BAND_SELECT 0x75
#define RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1 0x76
#define RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0 0x77
#define RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT 0x79
#define RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE 0x7a
#define RF22_REG_7C_TX_FIFO_CONTROL1 0x7c
#define RF22_REG_7D_TX_FIFO_CONTROL2 0x7d
#define RF22_REG_7E_RX_FIFO_CONTROL 0x7e
#define RF22_REG_7F_FIFO_ACCESS 0x7f
// These register masks etc are named wherever possible
// corresponding to the bit and field names in the RF-22 Manual
// RF22_REG_00_DEVICE_TYPE 0x00
#define RF22_DEVICE_TYPE_RX_TRX 0x08
#define RF22_DEVICE_TYPE_TX 0x07
// RF22_REG_02_DEVICE_STATUS 0x02
#define RF22_FFOVL 0x80
#define RF22_FFUNFL 0x40
#define RF22_RXFFEM 0x20
#define RF22_HEADERR 0x10
#define RF22_FREQERR 0x08
#define RF22_LOCKDET 0x04
#define RF22_CPS 0x03
#define RF22_CPS_IDLE 0x00
#define RF22_CPS_RX 0x01
#define RF22_CPS_TX 0x10
// RF22_REG_03_INTERRUPT_STATUS1 0x03
#define RF22_IFFERROR 0x80
#define RF22_ITXFFAFULL 0x40
#define RF22_ITXFFAEM 0x20
#define RF22_IRXFFAFULL 0x10
#define RF22_IEXT 0x08
#define RF22_IPKSENT 0x04
#define RF22_IPKVALID 0x02
#define RF22_ICRCERROR 0x01
// RF22_REG_04_INTERRUPT_STATUS2 0x04
#define RF22_ISWDET 0x80
#define RF22_IPREAVAL 0x40
#define RF22_IPREAINVAL 0x20
#define RF22_IRSSI 0x10
#define RF22_IWUT 0x08
#define RF22_ILBD 0x04
#define RF22_ICHIPRDY 0x02
#define RF22_IPOR 0x01
// RF22_REG_05_INTERRUPT_ENABLE1 0x05
#define RF22_ENFFERR 0x80
#define RF22_ENTXFFAFULL 0x40
#define RF22_ENTXFFAEM 0x20
#define RF22_ENRXFFAFULL 0x10
#define RF22_ENEXT 0x08
#define RF22_ENPKSENT 0x04
#define RF22_ENPKVALID 0x02
#define RF22_ENCRCERROR 0x01
// RF22_REG_06_INTERRUPT_ENABLE2 0x06
#define RF22_ENSWDET 0x80
#define RF22_ENPREAVAL 0x40
#define RF22_ENPREAINVAL 0x20
#define RF22_ENRSSI 0x10
#define RF22_ENWUT 0x08
#define RF22_ENLBDI 0x04
#define RF22_ENCHIPRDY 0x02
#define RF22_ENPOR 0x01
// RF22_REG_07_OPERATING_MODE 0x07
#define RF22_SWRES 0x80
#define RF22_ENLBD 0x40
#define RF22_ENWT 0x20
#define RF22_X32KSEL 0x10
#define RF22_TXON 0x08
#define RF22_RXON 0x04
#define RF22_PLLON 0x02
#define RF22_XTON 0x01
// RF22_REG_08_OPERATING_MODE2 0x08
#define RF22_ANTDIV 0xc0
#define RF22_RXMPK 0x10
#define RF22_AUTOTX 0x08
#define RF22_ENLDM 0x04
#define RF22_FFCLRRX 0x02
#define RF22_FFCLRTX 0x01
// RF22_REG_0F_ADC_CONFIGURATION 0x0f
#define RF22_ADCSTART 0x80
#define RF22_ADCDONE 0x80
#define RF22_ADCSEL 0x70
#define RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR 0x00
#define RF22_ADCSEL_GPIO0_SINGLE_ENDED 0x10
#define RF22_ADCSEL_GPIO1_SINGLE_ENDED 0x20
#define RF22_ADCSEL_GPIO2_SINGLE_ENDED 0x30
#define RF22_ADCSEL_GPIO0_GPIO1_DIFFERENTIAL 0x40
#define RF22_ADCSEL_GPIO1_GPIO2_DIFFERENTIAL 0x50
#define RF22_ADCSEL_GPIO0_GPIO2_DIFFERENTIAL 0x60
#define RF22_ADCSEL_GND 0x70
#define RF22_ADCREF 0x0c
#define RF22_ADCREF_BANDGAP_VOLTAGE 0x00
#define RF22_ADCREF_VDD_ON_3 0x08
#define RF22_ADCREF_VDD_ON_2 0x0c
#define RF22_ADCGAIN 0x03
// RF22_REG_10_ADC_SENSOR_AMP_OFFSET 0x10
#define RF22_ADCOFFS 0x0f
// RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION 0x12
#define RF22_TSRANGE 0xc0
#define RF22_TSRANGE_M64_64C 0x00
#define RF22_TSRANGE_M64_192C 0x40
#define RF22_TSRANGE_0_128C 0x80
#define RF22_TSRANGE_M40_216F 0xc0
#define RF22_ENTSOFFS 0x20
#define RF22_ENTSTRIM 0x10
#define RF22_TSTRIM 0x0f
// RF22_REG_14_WAKEUP_TIMER_PERIOD1 0x14
#define RF22_WTR 0x3c
#define RF22_WTD 0x03
// RF22_REG_1D_AFC_LOOP_GEARSHIFT_OVERRIDE 0x1d
#define RF22_AFBCD 0x80
#define RF22_ENAFC 0x40
#define RF22_AFCGEARH 0x38
#define RF22_AFCGEARL 0x07
// RF22_REG_1E_AFC_TIMING_CONTROL 0x1e
#define RF22_SWAIT_TIMER 0xc0
#define RF22_SHWAIT 0x38
#define RF22_ANWAIT 0x07
// RF22_REG_30_DATA_ACCESS_CONTROL 0x30
#define RF22_ENPACRX 0x80
#define RF22_MSBFRST 0x00
#define RF22_LSBFRST 0x40
#define RF22_CRCHDRS 0x00
#define RF22_CRCDONLY 0x20
#define RF22_ENPACTX 0x08
#define RF22_ENCRC 0x04
#define RF22_CRC 0x03
#define RF22_CRC_CCITT 0x00
#define RF22_CRC_CRC_16_IBM 0x01
#define RF22_CRC_IEC_16 0x02
#define RF22_CRC_BIACHEVA 0x03
// RF22_REG_32_HEADER_CONTROL1 0x32
#define RF22_BCEN 0xf0
#define RF22_BCEN_NONE 0x00
#define RF22_BCEN_HEADER0 0x10
#define RF22_BCEN_HEADER1 0x20
#define RF22_BCEN_HEADER2 0x40
#define RF22_BCEN_HEADER3 0x80
#define RF22_HDCH 0x0f
#define RF22_HDCH_NONE 0x00
#define RF22_HDCH_HEADER0 0x01
#define RF22_HDCH_HEADER1 0x02
#define RF22_HDCH_HEADER2 0x04
#define RF22_HDCH_HEADER3 0x08
// RF22_REG_33_HEADER_CONTROL2 0x33
#define RF22_HDLEN 0x70
#define RF22_HDLEN_0 0x00
#define RF22_HDLEN_1 0x10
#define RF22_HDLEN_2 0x20
#define RF22_HDLEN_3 0x30
#define RF22_HDLEN_4 0x40
#define RF22_VARPKLEN 0x00
#define RF22_FIXPKLEN 0x08
#define RF22_SYNCLEN 0x06
#define RF22_SYNCLEN_1 0x00
#define RF22_SYNCLEN_2 0x02
#define RF22_SYNCLEN_3 0x04
#define RF22_SYNCLEN_4 0x06
#define RF22_PREALEN8 0x01
// RF22_REG_6D_TX_POWER 0x6d
#define RF22_TXPOW 0x07
#define RF22_TXPOW_4X31 0x08 // Not used in RFM22B
#define RF22_TXPOW_1DBM 0x00
#define RF22_TXPOW_2DBM 0x01
#define RF22_TXPOW_5DBM 0x02
#define RF22_TXPOW_8DBM 0x03
#define RF22_TXPOW_11DBM 0x04
#define RF22_TXPOW_14DBM 0x05
#define RF22_TXPOW_17DBM 0x06
#define RF22_TXPOW_20DBM 0x07
// IN RFM23B
#define RF22_TXPOW_LNA_SW 0x08
// RF22_REG_71_MODULATION_CONTROL2 0x71
#define RF22_TRCLK 0xc0
#define RF22_TRCLK_NONE 0x00
#define RF22_TRCLK_GPIO 0x40
#define RF22_TRCLK_SDO 0x80
#define RF22_TRCLK_NIRQ 0xc0
#define RF22_DTMOD 0x30
#define RF22_DTMOD_DIRECT_GPIO 0x00
#define RF22_DTMOD_DIRECT_SDI 0x10
#define RF22_DTMOD_FIFO 0x20
#define RF22_DTMOD_PN9 0x30
#define RF22_ENINV 0x08
#define RF22_FD8 0x04
#define RF22_MODTYP 0x30
#define RF22_MODTYP_UNMODULATED 0x00
#define RF22_MODTYP_OOK 0x01
#define RF22_MODTYP_FSK 0x02
#define RF22_MODTYP_GFSK 0x03
// RF22_REG_75_FREQUENCY_BAND_SELECT 0x75
#define RF22_SBSEL 0x40
#define RF22_HBSEL 0x20
#define RF22_FB 0x1f
// Define this to include Serial printing in diagnostic routines
#define RF22_HAVE_SERIAL
namespace upm {
/**
* @brief RF22 Wireless Transceiver library
* @defgroup rf22 libupm-rf22
* @ingroup sparkfun spi wifi
*/
/**
* @library rf22
* @sensor rf22
* @comname RF22 Transceiver
* @altname RFM22B
* @type wifi
* @man sparkfun
* @web https://www.sparkfun.com/products/12030
* @con spi
*
* @brief API for the RF22 Transceiver Module
*
* This base class provides basic functions for sending and receiving unaddressable,
* unreliable datagrams of arbitrary length to 255 octets per packet.
*
* Subclasses may use this class to implement reliable, addressed datagrams and streams,
* mesh routers, repeaters, translators etc.
*
* On transmission, the TO and FROM addresses default to 0x00, unless changed by a subclass.
* On reception the TO addressed is checked against the node address (defaults to 0x00) or the
* broadcast address (which is 0xff). The ID and FLAGS are set to 0, and not checked by this class.
* This permits use of the this base RF22 class as an unaddressable, unreliable datagram service.
* Subclasses are expected to change this behavior to add node address, ids, retransmission etc.
*
* Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
* modulation scheme.
*
* @image html rf22.jpg
* <br><em>RF22 Sensor image provided by SparkFun* under
* <a href=https://creativecommons.org/licenses/by-nc-sa/3.0/>
* CC BY-NC-SA-3.0</a>.</em>
*
* @snippet rf22-server.cxx Interesting
* @snippet rf22-client.cxx Interesting
*/
class RF22
{
public:
/**
* @brief Defines register values for a set of modem configuration registers
*
* Defines register values for a set of modem configuration registers
* that can be passed to setModemConfig()
* if none of the choices in ModemConfigChoice suit your need
* setModemConfig() writes the register values to the appropriate RF22 registers
* to set the desired modulation type, data rate and deviation/bandwidth.
* Suitable values for these registers can be computed using the register calculator at
* http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
*/
typedef struct
{
uint8_t reg_1c; ///< Value for register RF22_REG_1C_IF_FILTER_BANDWIDTH
uint8_t reg_1f; ///< Value for register RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE
uint8_t reg_20; ///< Value for register RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE
uint8_t reg_21; ///< Value for register RF22_REG_21_CLOCK_RECOVERY_OFFSET2
uint8_t reg_22; ///< Value for register RF22_REG_22_CLOCK_RECOVERY_OFFSET1
uint8_t reg_23; ///< Value for register RF22_REG_23_CLOCK_RECOVERY_OFFSET0
uint8_t reg_24; ///< Value for register RF22_REG_24_CLOCK_RECOVERY_TIMING_LOOP_GAIN1
uint8_t reg_25; ///< Value for register RF22_REG_25_CLOCK_RECOVERY_TIMING_LOOP_GAIN0
uint8_t reg_2c; ///< Value for register RF22_REG_2C_OOK_COUNTER_VALUE_1
uint8_t reg_2d; ///< Value for register RF22_REG_2D_OOK_COUNTER_VALUE_2
uint8_t reg_2e; ///< Value for register RF22_REG_2E_SLICER_PEAK_HOLD
uint8_t reg_58; ///< Value for register RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING
uint8_t reg_69; ///< Value for register RF22_REG_69_AGC_OVERRIDE1
uint8_t reg_6e; ///< Value for register RF22_REG_6E_TX_DATA_RATE1
uint8_t reg_6f; ///< Value for register RF22_REG_6F_TX_DATA_RATE0
uint8_t reg_70; ///< Value for register RF22_REG_70_MODULATION_CONTROL1
uint8_t reg_71; ///< Value for register RF22_REG_71_MODULATION_CONTROL2
uint8_t reg_72; ///< Value for register RF22_REG_72_FREQUENCY_DEVIATION
} ModemConfig;
/**
* Choices for setModemConfig() for a selected subset of common modulation types,
* and data rates. If you need another configuration, use the register calculator.
* and call setModemRegisters() with your desired settings
* These are indexes into _modemConfig
*/
typedef enum
{
UnmodulatedCarrier = 0, ///< Unmodulated carrier for testing
FSK_PN9_Rb2Fd5, ///< FSK, No Manchester, Rb = 2kbs, Fd = 5kHz, PN9 random modulation for testing
FSK_Rb2Fd5, ///< FSK, No Manchester, Rb = 2kbs, Fd = 5kHz
FSK_Rb2_4Fd36, ///< FSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz
FSK_Rb4_8Fd45, ///< FSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz
FSK_Rb9_6Fd45, ///< FSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz
FSK_Rb19_2Fd9_6, ///< FSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz
FSK_Rb38_4Fd19_6, ///< FSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz
FSK_Rb57_6Fd28_8, ///< FSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz
FSK_Rb125Fd125, ///< FSK, No Manchester, Rb = 125kbs, Fd = 125kHz
GFSK_Rb2Fd5, ///< GFSK, No Manchester, Rb = 2kbs, Fd = 5kHz
GFSK_Rb2_4Fd36, ///< GFSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz
GFSK_Rb4_8Fd45, ///< GFSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz
GFSK_Rb9_6Fd45, ///< GFSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz
GFSK_Rb19_2Fd9_6, ///< GFSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz
GFSK_Rb38_4Fd19_6, ///< GFSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz
GFSK_Rb57_6Fd28_8, ///< GFSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz
GFSK_Rb125Fd125, ///< GFSK, No Manchester, Rb = 125kbs, Fd = 125kHz
OOK_Rb1_2Bw75, ///< OOK, No Manchester, Rb = 1.2kbs, Rx Bandwidth = 75kHz
OOK_Rb2_4Bw335, ///< OOK, No Manchester, Rb = 2.4kbs, Rx Bandwidth = 335kHz
OOK_Rb4_8Bw335, ///< OOK, No Manchester, Rb = 4.8kbs, Rx Bandwidth = 335kHz
OOK_Rb9_6Bw335, ///< OOK, No Manchester, Rb = 9.6kbs, Rx Bandwidth = 335kHz
OOK_Rb19_2Bw335, ///< OOK, No Manchester, Rb = 19.2kbs, Rx Bandwidth = 335kHz
OOK_Rb38_4Bw335, ///< OOK, No Manchester, Rb = 38.4kbs, Rx Bandwidth = 335kHz
OOK_Rb40Bw335 ///< OOK, No Manchester, Rb = 40kbs, Rx Bandwidth = 335kHz
} ModemConfigChoice;
/**
* Constructor. You can have multiple instances, but each instance must have its own
* interrupt and slave select pin. After constructing, you must call init() to initialize the interface
* and the radio module
* @param[in] spiBus Pointer to the SPI interface object to use. Default 0 or the standard Arduino hardware
* SPI interface
* @param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
* accessing it. Default is 10 or the normal SS pin for Arduino
* @param[in] interruptPin The interrupt pin number to use. Default is 2
*/
RF22(int spiBus = 0, int slaveSelectPin = 10, int interruptPin = 2);
/**
* Destructor.
*/
virtual ~RF22();
/**
* Initializes this instance and the radio module connected to it.
* The following steps are taken:
* - Software reset the RF22 module
* - Checks the connected RF22 module is either a RF22_DEVICE_TYPE_RX_TRX or a RF22_DEVICE_TYPE_TX
* - Configures the RF22 module
* - Sets the frequency to 434.0 MHz
* - Sets the modem data rate to FSK_Rb2_4Fd36
* @return true if everything was successful
*/
uint8_t init();
/**
* Issues a software reset to the
* RF22 module. Blocks for 1ms to ensure the reset is complete.
*/
void reset();
/**
* Reads a single register from the RF22
* @param[in] reg Register number, one of RF22_REG_*
* @return The value of the register
*/
uint8_t spiRead(uint8_t reg);
/**
* Writes a single byte to the RF22
* @param[in] reg Register number, one of RF22_REG_*
* @param[in] val The value to write
*/
void spiWrite(uint8_t reg, uint8_t val);
/**
* Reads a number of consecutive registers from the RF22 using burst read mode
* @param[in] reg Register number of the first register, one of RF22_REG_*
* @param[in] dest Array to write the register values to. Must be at least len bytes
* @param[in] len Number of bytes to read
*/
void spiBurstRead(uint8_t reg, uint8_t* dest, uint8_t len);
/**
* Write a number of consecutive registers using burst write mode
* @param[in] reg Register number of the first register, one of RF22_REG_*
* @param[in] src Array of new register values to write. Must be at least len bytes
* @param[in] len Number of bytes to write
*/
void spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len);
/**
* Reads and returns the device status register RF22_REG_02_DEVICE_STATUS
* @return The value of the device status register
*/
uint8_t statusRead();
/**
* Reads a value from the on-chip analog-digital converter
* @param[in] adcsel Selects the ADC input to measure. One of RF22_ADCSEL_*. Defaults to the
* internal temperature sensor
* @param[in] adcref Specifies the reference voltage to use. One of RF22_ADCREF_*.
* Defaults to the internal bandgap voltage.
* @param[in] adcgain Amplifier gain selection.
* @param[in] adcoffs Amplifier offset (0 to 15).
* @return The analog value. 0 to 255.
*/
uint8_t adcRead(uint8_t adcsel = RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR,
uint8_t adcref = RF22_ADCREF_BANDGAP_VOLTAGE,
uint8_t adcgain = 0,
uint8_t adcoffs = 0);
/**
* Reads the on-chip temperature sensor
* @param[in] tsrange Specifies the temperature range to use. One of RF22_TSRANGE_*
* @param[in] tvoffs Specifies the temperature value offset. This is actually signed value
* added to the measured temperature value
* @return The measured temperature.
*/
uint8_t temperatureRead(uint8_t tsrange = RF22_TSRANGE_M64_64C, uint8_t tvoffs = 0);
/**
* Reads the wakeup timer value in registers RF22_REG_17_WAKEUP_TIMER_VALUE1
* and RF22_REG_18_WAKEUP_TIMER_VALUE2
* @return The wakeup timer value
*/
uint16_t wutRead();
/**
* Sets the wakeup timer period registers RF22_REG_14_WAKEUP_TIMER_PERIOD1,
* RF22_REG_15_WAKEUP_TIMER_PERIOD2 and RF22_R<EG_16_WAKEUP_TIMER_PERIOD3
* @param[in] wtm Wakeup timer mantissa value
* @param[in] wtr Wakeup timer exponent R value
* @param[in] wtd Wakeup timer exponent D value
*/
void setWutPeriod(uint16_t wtm, uint8_t wtr = 0, uint8_t wtd = 0);
/**
* Sets the transmitter and receiver center frequency
* @param[in] center Frequency in MHz. 240.0 to 960.0. Caution, some versions of RF22 and derivatives
* implemented more restricted frequency ranges.
* @param[in] afcPullInRange Sets the AF Pull In Range in MHz. Defaults to 0.05MHz (50kHz). Range is 0.0 to 0.159375
* for frequencies 240.0 to 480MHz, and 0.0 to 0.318750MHz for frequencies 480.0 to 960MHz,
* @return true if the selected frequency center + (fhch * fhs) is within range and the afcPullInRange is within range
*/
uint8_t setFrequency(float center, float afcPullInRange = 0.05);
/**
* Sets the frequency hopping step size.
* @param[in] fhs Frequency Hopping step size in 10kHz increments
* @return true if center + (fhch * fhs) is within limits
*/
uint8_t setFHStepSize(uint8_t fhs);
/**
* Sets the frequency hopping channel. Adds fhch * fhs to center frequency
* @param[in] fhch The channel number
* @return true if the selected frequency center + (fhch * fhs) is within range
*/
uint8_t setFHChannel(uint8_t fhch);
/**
* Reads and returns the current RSSI value from register RF22_REG_26_RSSI. If you want to find the RSSI
* of the last received message, use lastRssi() instead.
* @return The current RSSI value
*/
uint8_t rssiRead();
/**
* Reads and returns the current EZMAC value from register RF22_REG_31_EZMAC_STATUS
* @return The current EZMAC value
*/
uint8_t ezmacStatusRead();
/**
* Sets the parameters for the RF22 Idle mode in register RF22_REG_07_OPERATING_MODE.
* Idle mode is the mode the RF22 will be in when not transmitting or receiving. The default idle mode
* is RF22_XTON i.e. READY mode.
* @param[in] mode Mask of mode bits, using RF22_SWRES, RF22_ENLBD, RF22_ENWT,
* RF22_X32KSEL, RF22_PLLON, RF22_XTON.
*/
void setMode(uint8_t mode);
/**
* If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
* disables them.
*/
void setModeIdle();
/**
* If current mode is Tx or Idle, changes it to Rx.
* Starts the receiver in the RF22.
*/
void setModeRx();
/**
* If current mode is Rx or Idle, changes it to Rx.
* Starts the transmitter in the RF22.
*/
void setModeTx();
/**
* Returns the operating mode of the library.
* @return the current mode, one of RF22_MODE_*
*/
uint8_t mode();
/**
* Sets the transmitter power output level in register RF22_REG_6D_TX_POWER.
* Be a good neighbor and set the lowest power level you need.
* After init(), the power will be set to RF22_TXPOW_8DBM.
* Caution: In some countries you may only select RF22_TXPOW_17DBM if you
* are also using frequency hopping.
* @param[in] power Transmitter power level, one of RF22_TXPOW_*
*/
void setTxPower(uint8_t power);
/**
* Sets all the registered required to configure the data modem in the RF22, including the data rate,
* bandwidths etc. You can use this to configure the modem with custom configurations if none of the
* canned configurations in ModemConfigChoice suit you.
* @param[in] config A ModemConfig structure containing values for the modem configuration registers.
*/
void setModemRegisters(const ModemConfig* config);
/**
* Select one of the predefined modem configurations. If you need a modem configuration not provided
* here, use setModemRegisters() with your own ModemConfig.
* @param[in] index The configuration choice.
* @return true if index is a valid choice.
*/
uint8_t setModemConfig(ModemConfigChoice index);
/**
* Starts the receiver and checks whether a received message is available.
* This can be called multiple times in a timeout loop
* @return true if a complete, valid message has been received and is able to be retrieved by
* recv()
*/
uint8_t available();
/**
* Starts the receiver and blocks until a valid received
* message is available.
*/
void waitAvailable();
/**
* Starts the receiver and blocks until a received message is available or a timeout
* @param[in] timeout Maximum time to wait in milliseconds.
* @return true if a message is available
*/
bool waitAvailableTimeout(unsigned long timeout);
/**
* Turns the receiver on if it not already on.
* If there is a valid message available, copy it to buf and return true
* else return false.
* If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
* You should be sure to call this function frequently enough to not miss any messages
* It is recommended that you call it in your main loop.
* @param[in] buf Location to copy the received message
* @param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
* @return true if a valid message was copied to buf
*/
uint8_t recv(uint8_t* buf, uint8_t* len);
/**
* Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
* Then loads a message into the transmitter and starts the transmitter. Note that a message length
* of 0 is NOT permitted.
* @param[in] data Array of data to be sent
* @param[in] len Number of bytes of data to send (> 0)
* @return true if the message length was valid and it was correctly queued for transmit
*/
uint8_t send(const uint8_t* data, uint8_t len);
/**
* Blocks until the RF22 is not in mode RF22_MODE_TX (i.e. until the RF22 is not transmitting).
* This effectively waits until any previous transmit packet is finished being transmitted.
*/
void waitPacketSent();
/**
* Tells the receiver to accept messages with any TO address, not just messages
* addressed to this node or the broadcast address
* @param[in] promiscuous true if you wish to receive messages with any TO address
*/
void setPromiscuous(uint8_t promiscuous);
/**
* Returns the TO header of the last received message
* @return The TO header
*/
uint8_t headerTo();
/**
* Returns the FROM header of the last received message
* @return The FROM header
*/
uint8_t headerFrom();
/**
* Returns the ID header of the last received message
* @return The ID header
*/
uint8_t headerId();
/**
* Returns the FLAGS header of the last received message
* @return The FLAGS header
*/
uint8_t headerFlags();
/**
* Returns the RSSI (Receiver Signal Strength Indicator)
* of the last received message. This measurement is taken when
* the preamble has been received. It is a (non-linear) measure of the received signal strength.
* @return The RSSI
*/
uint8_t lastRssi();
/**
* Prints a data buffer in HEX.
* For diagnostic use
* @param[in] prompt string to preface the print
* @param[in] buf Location of the buffer to print
* @param[in] len Length of the buffer in octets.
*/
static void printBuffer(const char* prompt, const uint8_t* buf, uint8_t len);
/**
* Sets the length of the preamble
* in 4-bit nibbles.
* Caution: this should be set to the same
* value on all nodes in your network. Default is 8.
* Sets the message preamble length in RF22_REG_34_PREAMBLE_LENGTH
* @param[in] nibbles Preamble length in nibbles of 4 bits each.
*/
void setPreambleLength(uint8_t nibbles);
/**
* Sets the sync words for transmit and receive in registers RF22_REG_36_SYNC_WORD3
* to RF22_REG_39_SYNC_WORD0
* Caution: this should be set to the same
* value on all nodes in your network. Default is { 0x2d, 0xd4 }
* @param[in] syncWords Array of sync words
* @param[in] len Number of sync words to set
*/
void setSyncWords(const uint8_t* syncWords, uint8_t len);
protected:
/**
* This is a low level function to handle the interrupts for one instance of RF22.
* Called automatically when interrupt pin goes low, should not need to be called by user.
*/
void handleInterrupt();
/**
* Clears the receiver buffer.
* Internal use only
*/
void clearRxBuf();
/**
* Clears the transmitter buffer
* Internal use only
*/
void clearTxBuf();
/**
* Fills the transmitter buffer with the data of a message to be sent
* @param[in] data Array of data bytes to be sent (1 to 255)
* @param[in] len Number of data bytes in data (> 0)
* @return true if the message length is valid
*/
uint8_t fillTxBuf(const uint8_t* data, uint8_t len);
/**
* Appends the transmitter buffer with the data of a message to be sent
* @param[in] data Array of data bytes to be sent (0 to 255)
* @param[in] len Number of data bytes in data
* @return false if the resulting message would exceed RF22_MAX_MESSAGE_LEN, else true
*/
uint8_t appendTxBuf(const uint8_t* data, uint8_t len);
/**
* Internal function to load the next fragment of
* the current message into the transmitter FIFO
* Internal use only
*/
void sendNextFragment();
/**
* Function to copy the next fragment from
* the receiver FIFO into the receiver buffer
*/
void readNextFragment();
/**
* Clears the RF22 Rx and Tx FIFOs
* Internal use only
*/
void resetFifos();
/**
* Clears the RF22 Rx FIFO
* Internal use only
*/
void resetRxFifo();
/**
* Clears the RF22 Tx FIFO
* Internal use only
*/
void resetTxFifo();
/**
* This function will be called by handleInterrupt() if an RF22 external interrupt occurs.
* This can only happen if external interrupts are enabled in the RF22
* (which they are not by default).
* Subclasses may override this function to get control when an RF22 external interrupt occurs.
*/
virtual void handleExternalInterrupt();
/**
* This function will be called by handleInterrupt() if an RF22 wakeup timer interrupt occurs.
* This can only happen if wakeup timer interrupts are enabled in the RF22
* (which they are not by default).
* Subclasses may override this function to get control when an RF22 wakeup timer interrupt occurs.
*/
virtual void handleWakeupTimerInterrupt();
/**
* Sets the TO header to be sent in all subsequent messages
* @param[in] to The new TO header value
*/
void setHeaderTo(uint8_t to);
/**
* Sets the FROM header to be sent in all subsequent messages
* @param[in] from The new FROM header value
*/
void setHeaderFrom(uint8_t from);
/**
* Sets the ID header to be sent in all subsequent messages
* @param[in] id The new ID header value
*/
void setHeaderId(uint8_t id);
/**
* Sets the FLAGS header to be sent in all subsequent messages
* @param[in] flags The new FLAGS header value
*/
void setHeaderFlags(uint8_t flags);
/**
* Start the transmission of the contents
* of the Tx buffer
*/
void startTransmit();
/**
* ReStart the transmission of the contents
* of the Tx buffer after a transmission failure
*/
void restartTransmit();
uint64_t getTimestamp ();
private:
/**
* Static interrupt handler wrapper
*/
static void isr(void* args);
mraa_spi_context _spi;
mraa_gpio_context _cs;
mraa_gpio_context _irq;
volatile uint8_t _mode; // One of RF22_MODE_*
uint8_t _idleMode;
uint8_t _deviceType;
// These volatile members may get changed in the interrupt service routine
volatile uint8_t _bufLen;
uint8_t _buf[RF22_MAX_MESSAGE_LEN];
volatile uint8_t _rxBufValid;
volatile uint8_t _txBufSentIndex;
volatile uint16_t _rxBad;
volatile uint16_t _rxGood;
volatile uint16_t _txGood;
volatile uint8_t _lastRssi;
};
}

View File

@ -35,7 +35,7 @@
using namespace upm; using namespace upm;
using namespace std; using namespace std;
SSD1351::SSD1351 (uint8_t oc, uint8_t dc, uint8_t rst) : SSD1351::SSD1351 (int oc, int dc, int rst) :
GFX(SSD1351WIDTH, SSD1351HEIGHT), GFX(SSD1351WIDTH, SSD1351HEIGHT),
m_spi(0), m_oc(oc), m_dc(dc), m_rst(rst) { m_spi(0), m_oc(oc), m_dc(dc), m_rst(rst) {

View File

@ -112,7 +112,7 @@ class SSD1351 : public GFX{
* @param dc Data/command pin * @param dc Data/command pin
* @param rst Reset pin * @param rst Reset pin
*/ */
SSD1351 (uint8_t oc, uint8_t dc, uint8_t rst); SSD1351 (int oc, int dc, int rst);
/** /**
* SSD1351 object destructor * SSD1351 object destructor

View File

@ -34,7 +34,7 @@
using namespace upm; using namespace upm;
ST7735::ST7735 (uint8_t csLCD, uint8_t cSD, uint8_t rs, uint8_t rst) ST7735::ST7735 (int csLCD, int cSD, int rs, int rst)
: GFX (160, 128, m_map, font), m_spi(0), m_csLCDPinCtx(csLCD), m_cSDPinCtx(cSD), : GFX (160, 128, m_map, font), m_spi(0), m_csLCDPinCtx(csLCD), m_cSDPinCtx(cSD),
m_rSTPinCtx(rst), m_rSPinCtx(rs) { m_rSTPinCtx(rst), m_rSPinCtx(rs) {

View File

@ -527,7 +527,7 @@ class ST7735 : public GFX {
* @param rs Data/command pin * @param rs Data/command pin
* @param rst Reset pin * @param rst Reset pin
*/ */
ST7735 (uint8_t csLCD, uint8_t cSD, uint8_t rs, uint8_t rst); ST7735 (int csLCD, int cSD, int rs, int rst);
/** /**
* Returns the name of the component * Returns the name of the component

View File

@ -33,7 +33,7 @@
using namespace upm; using namespace upm;
UltraSonic::UltraSonic (uint8_t pin) { UltraSonic::UltraSonic (int pin) {
m_name = "UltraSonic"; m_name = "UltraSonic";
mraa_init(); mraa_init();

View File

@ -67,7 +67,7 @@ class UltraSonic {
* *
* @param pin pin for triggering the sensor for distance and for receiving pulse response * @param pin pin for triggering the sensor for distance and for receiving pulse response
*/ */
UltraSonic (uint8_t pin); UltraSonic (int pin);
/** /**
* UltraSonic object destructor. * UltraSonic object destructor.

View File

@ -26,39 +26,94 @@
#include <upm_platform.h> #include <upm_platform.h>
#include <upm_utilities.h> #include <upm_utilities.h>
void upm_delay(int time){ void upm_delay(int time)
{
if (time <= 0)
time = 1;
#if defined(UPM_PLATFORM_LINUX) #if defined(UPM_PLATFORM_LINUX)
sleep(time); sleep(time);
#elif defined(UPM_PLATFORM_ZEPHYR) #elif defined(UPM_PLATFORM_ZEPHYR)
# if KERNEL_VERSION_MAJOR == 1 && KERNEL_VERSION_MINOR >= 6
struct k_timer timer;
k_timer_init(&timer, NULL, NULL);
k_timer_start(&timer, time * 1000, 0);
k_timer_status_sync(&timer);
# else
struct nano_timer timer; struct nano_timer timer;
void *timer_data[1]; void *timer_data[1];
nano_timer_init(&timer, timer_data); nano_timer_init(&timer, timer_data);
nano_timer_start(&timer, SECONDS(time) + 1); nano_timer_start(&timer, SECONDS(time) + 1);
nano_timer_test(&timer, TICKS_UNLIMITED); nano_timer_test(&timer, TICKS_UNLIMITED);
# endif
#endif #endif
} }
void upm_delay_ms(int time){ void upm_delay_ms(int time)
{
if (time <= 0)
time = 1;
#if defined(UPM_PLATFORM_LINUX) #if defined(UPM_PLATFORM_LINUX)
usleep(1000 * time); usleep(1000 * time);
#elif defined(UPM_PLATFORM_ZEPHYR) #elif defined(UPM_PLATFORM_ZEPHYR)
# if KERNEL_VERSION_MAJOR == 1 && KERNEL_VERSION_MINOR >= 6
struct k_timer timer;
k_timer_init(&timer, NULL, NULL);
k_timer_start(&timer, time, 0);
k_timer_status_sync(&timer);
# else
struct nano_timer timer; struct nano_timer timer;
void *timer_data[1]; void *timer_data[1];
nano_timer_init(&timer, timer_data); nano_timer_init(&timer, timer_data);
nano_timer_start(&timer, MSEC(time) + 1); nano_timer_start(&timer, MSEC(time) + 1);
nano_timer_test(&timer, TICKS_UNLIMITED); nano_timer_test(&timer, TICKS_UNLIMITED);
# endif
#endif #endif
} }
void upm_delay_us(int time){ void upm_delay_us(int time)
{
if (time <= 0)
time = 1;
#if defined(UPM_PLATFORM_LINUX) #if defined(UPM_PLATFORM_LINUX)
usleep(time); usleep(time);
#elif defined(UPM_PLATFORM_ZEPHYR) #elif defined(UPM_PLATFORM_ZEPHYR)
# if KERNEL_VERSION_MAJOR == 1 && KERNEL_VERSION_MINOR >= 6
// we will use a upm_clock to do microsecond timings here as k_timer has
// only a millisecond resolution. So we init a clock and spin.
upm_clock_t timer;
upm_clock_init(&timer);
while (upm_elapsed_us(&timer) < time)
; // spin
# else
struct nano_timer timer; struct nano_timer timer;
void *timer_data[1]; void *timer_data[1];
nano_timer_init(&timer, timer_data); nano_timer_init(&timer, timer_data);
nano_timer_start(&timer, USEC(time) + 1); nano_timer_start(&timer, USEC(time) + 1);
nano_timer_test(&timer, TICKS_UNLIMITED); nano_timer_test(&timer, TICKS_UNLIMITED);
# endif
#endif #endif
} }

View File

@ -45,6 +45,8 @@ typedef struct timeval upm_clock_t;
#include <zephyr.h> #include <zephyr.h>
#include <device.h> #include <device.h>
#include <sys_clock.h> #include <sys_clock.h>
#include <version.h>
#include <kernel_version.h>
#if defined(CONFIG_STDOUT_CONSOLE) #if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h> #include <stdio.h>