diff --git a/.gitignore b/.gitignore index ad865f3..842d69a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,3 @@ -*.o -cpp/bin/* -cpp/lib/* -cpp/obj/* -js/bin/* -*.TMP -/js/node_modules -/js/bin -/vala/bin /autogen/node_modules /autogen/npm-debug.log *.orig diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index b8d0c54..0000000 --- a/.gitmodules +++ /dev/null @@ -1,7 +0,0 @@ -[submodule "js"] - path = js - url = https://github.com/wasabifan/ev3dev-lang-js -[submodule "python"] - path = python - url = https://github.com/rhempel/ev3dev-lang-python - branch = master diff --git a/README.md b/README.md index 9950ec9..476aa54 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ -ev3dev language bindings +ev3dev-lang language bindings ======================== -This repository provides several language bindings for the sensor, motor, and other functionality in the [ev3dev](http://www.ev3dev.org) Linux distribution for the LEGO MINDSTORMS EV3 hardware. +This repository stores the utilities and metadata information for the ev3dev-lang family of libraries. These libraries are easy-to-use interfaces for the APIs that are available on [ev3dev-based](http://www.ev3dev.org) devices. -We currently have libraries for the following languages here: -- C++ -- Node.JS -- Python +We support multiple libraries for various programming languages using a centralized "specification" which we keep updated as kernel changes are made. We don't have the actual library code here (see below) -- instead we use this repo to facilitate the maintenance of our bindings. -Each binding complies with our universal language binding specification, which also serves as high-level documentation for our wrappers. +We currently support libraries for the following languages: +- [C++](https://github.com/ddemidov/ev3dev-lang-cpp) +- [Node.js](https://github.com/wasabifan/ev3dev-lang-js) +- [Python](https://github.com/rhempel/ev3dev-lang-python) + +Each binding is written based on our central spec, so each has a uniform interface which is kept close to the ev3dev API surface while still encouraging language-specific enhancements. diff --git a/autogen/README.md b/autogen/README.md index d0b585e..3a3aa8e 100644 --- a/autogen/README.md +++ b/autogen/README.md @@ -9,14 +9,14 @@ To help us maintain our language bindings, we have written a script to automatic - If you have not yet done so yet, run `npm install` to install the dependencies for auto-generation ### Running from the command line -If you run the script without any parameters, it will auto-generate all language groups: +If you run the script without any parameters, it will look for an `autogen-config.json` file in your current working directory. The autogen-config file specifies the locations to look for templates and source files. ``` -$ node autogen.js +$ node path/to/autogen.js ``` -If you would like to only process a single group (as defined in `autogen-list.json`), you can provide the name of the group as a command-line parameter: +If you want to specify a config file manually, you can include use a full file path for the target JSON config file. ``` -$ node autogen.js docs +$ node path/to/autogen.js other/path/to/config.json ``` ## How it works diff --git a/autogen/autogen-list.json b/autogen/autogen-list.json deleted file mode 100644 index 2352083..0000000 --- a/autogen/autogen-list.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "cpp": { - "files": [ - "cpp/ev3dev.h", - "cpp/ev3dev.cpp", - "cpp/ev3dev-lang-test.cpp", - "cpp/ev3dev-lang-demo.cpp" - ], - "templateDir": "cpp/templates/" - }, - "python": { - "files": [ - "python/ev3dev/core.py", - "python/ev3dev/ev3.py", - "python/ev3dev/brickpi.py", - "python/spec_version.py" - ], - "templateDir": "python/templates/" - }, - "js": { - "files": [ - "js/extras.ts", - "js/motors.ts", - "js/sensors.ts", - "js/index.ts" - ], - "templateDir": "js/templates/" - }, - "docs": { - "files": [ - "wrapper-specification.md" - ], - "templateDir": "autogen/templates/" - } -} diff --git a/autogen/autogen.js b/autogen/autogen.js index 6df7141..743dd78 100644 --- a/autogen/autogen.js +++ b/autogen/autogen.js @@ -17,12 +17,12 @@ liquidEngine.registerFilters(config.extraLiquidFilters); //Load the spec data and list of files to process var specData = JSON.parse(fs.readFileSync(path.resolve(__dirname, "spec.json"))); -var groupsToProcess = getGroupsToProcess(); +var targetInfo = getTargetFileInfo(); -if (groupsToProcess.length > 0) - console.log("Queuing " + groupsToProcess.length + " file groups..."); -else - console.log("Warning: No matching file groups found!"); +if(!targetInfo) { + console.error("No valid config file found! Either specify a path to a '" + config.defaultConfigFileName + "' or 'cd' into a directory that has one."); + process.exit(1); +} var clearTemplatedSections = false; if (argv.x || argv.clear) @@ -30,39 +30,51 @@ if (argv.x || argv.clear) //Call the process function on each specified file, and log the result -for (var groupIndex = 0; groupIndex < groupsToProcess.length; groupIndex++) { - for (var fileIndex = 0; fileIndex < groupsToProcess[groupIndex].files.length; fileIndex++) { - var filePath = groupsToProcess[groupIndex].files[fileIndex]; - var templateDir = path.resolve(__dirname, '..', groupsToProcess[groupIndex].templateDir);; - - var autogenContext = { - filePath: filePath, - templateDir: templateDir, - specData: specData, - liquidEngine: liquidEngine, - clearTemplatedSections: clearTemplatedSections - } +for (var fileIndex = 0; fileIndex < targetInfo.files.length; fileIndex++) { + var filePath = targetInfo.files[fileIndex]; - core.bootstrapFileProcessor(autogenContext, function (filename, err) { - if (err) - console.log("Error processing file \"" + filename + "\": " + err); - else - console.log("Completed processing file \"" + filename + "\""); - }); + var autogenContext = { + filePath: filePath, + templateDir: targetInfo.templateDir, + specData: specData, + liquidEngine: liquidEngine, + clearTemplatedSections: clearTemplatedSections } -} -function getGroupsToProcess() { - //Load the list of files to process - var groupDefinitions = JSON.parse(fs.readFileSync(path.resolve(__dirname, "autogen-list.json")).toString()); - - var groupsToProcess = []; + core.bootstrapFileProcessor(autogenContext, function (filename, err) { + if (err) + console.log("Error processing file \"" + filename + "\": " + err); + else + console.log("Completed processing file \"" + filename + "\""); + }); +} - //Only queue the files from the group that was specified - for (var groupName in groupDefinitions) { - if (argv._.indexOf(groupName) != -1) - groupsToProcess.push(groupDefinitions[groupName]); - } +function getTargetFileInfo() { + var pathCandidates = argv._.concat(process.cwd()); + + var configFilePath = pathCandidates.map(function(possiblePath) { + var stat = fs.statSync(possiblePath); + + if(stat.isFile()) + return path.resolve(possiblePath); + else if (stat.isDirectory()) + return path.resolve(possiblePath, config.defaultConfigFileName); + else + return null; + + }).filter(function(configPath) { + return !!configPath && fs.existsSync(configPath); + })[0]; + + if(!configFilePath) + return null; + + var loadedTargetFileInfo = JSON.parse(fs.readFileSync(configFilePath).toString()); - return groupsToProcess; + return { + templateDir: path.resolve(path.dirname(configFilePath), loadedTargetFileInfo.templateDir), + files: loadedTargetFileInfo.files.map(function(configRelativePath) { + return path.resolve(path.dirname(configFilePath), configRelativePath); + }) + }; } diff --git a/autogen/config.js b/autogen/config.js index ba7c64d..c02c219 100644 --- a/autogen/config.js +++ b/autogen/config.js @@ -1,5 +1,7 @@ var utils = require('./utils.js'); +exports.defaultConfigFileName = 'autogen-config.json'; + var cStyleAutogenStart = /\/\/\s*~autogen *(.+)/; var cStyleAutogenEnd = "//~autogen"; diff --git a/autogen/templates/autogen-header.liquid b/autogen/templates/autogen-header.liquid deleted file mode 100644 index 58305fb..0000000 --- a/autogen/templates/autogen-header.liquid +++ /dev/null @@ -1,7 +0,0 @@ -{% case commentStyle %}{% - when 'lua' %} --{% - when 'xml' %}' }} diff --git a/cpp/Makefile b/cpp/Makefile deleted file mode 100644 index 69c8891..0000000 --- a/cpp/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -EV3DEV_PLATFORM=EV3 - -CXX = $(CROSS_COMPILE)g++ -AR = $(CROSS_COMPILE)ar -RANLIB = $(CROSS_COMPILE)ranlib - -CFLAGS=-O2 -march=armv5 -CCFLAGS=-std=c++11 -D_GLIBCXX_USE_NANOSLEEP -DEV3DEV_PLATFORM_$(EV3DEV_PLATFORM) -DEPS=ev3dev.h -LIBS=-Llib -lev3dev -lstdc++ -lm - -obj/%.o: %.cpp $(DEPS) - mkdir -p $(@D) - $(CXX) -c -o $@ $< $(CFLAGS) $(CCFLAGS) - -lib/libev3dev.a: obj/ev3dev.o - mkdir -p $(@D) - $(AR) rc $@ $^ && $(RANLIB) $@ - -bin/ev3dev-lang-test: lib/libev3dev.a obj/ev3dev-lang-test.o - mkdir -p $(@D) - $(CXX) -o $@ $^ $(CFLAGS) $(CCFLAGS) $(LIBS) - -bin/ev3dev-lang-demo: lib/libev3dev.a obj/ev3dev-lang-demo.o - mkdir -p $(@D) - $(CXX) -o $@ $^ $(CFLAGS) $(CCFLAGS) $(LIBS) -lpthread - -bin/remote_control-test: lib/libev3dev.a obj/remote_control-test.o - mkdir -p $(@D) - $(CXX) -o $@ $^ $(CFLAGS) $(CCFLAGS) $(LIBS) - -bin/drive-test: lib/libev3dev.a obj/drive-test.o - mkdir -p $(@D) - $(CXX) -o $@ $^ $(CFLAGS) $(CCFLAGS) $(LIBS) -lpthread - -bin/button-test: lib/libev3dev.a obj/button-test.o - mkdir -p $(@D) - $(CXX) -o $@ $^ $(CFLAGS) $(CCFLAGS) $(LIBS) - -bin/sound-test: lib/libev3dev.a obj/sound-test.o - mkdir -p $(@D) - $(CXX) -o $@ $^ $(CFLAGS) $(CCFLAGS) $(LIBS) - -.PHONY: all clean - -clean: - rm -f obj/* lib/* bin/* *~ - -all: \ - lib/libev3dev.a \ - bin/ev3dev-lang-test \ - bin/ev3dev-lang-demo \ - bin/remote_control-test \ - bin/drive-test \ - bin/button-test diff --git a/cpp/README.md b/cpp/README.md deleted file mode 100644 index d29efbe..0000000 --- a/cpp/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Compiling - -* EV3: -``` -make -``` - -* BrickPi: -``` -make EV3DEV_PLATFORM=BRICKPI -``` - -You have several options for compiling. - -## Cross-compiling - -You can use a cross-compiling toolchain to create ARM compatible code. Note: You need a Linux toolchain, -not a "bare-metal" toolchain. If it does not have "linux" in the name, it probably won't work. - -Pros: Fastest option. Works on Windows and Mac without a virtual machine. - -Cons: Only includes standard libraries - no Debian `-dev` packages. - -### Windows - -[MentorGraphics toolchain](http://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-gnueabi/arm-2014.05-29-arm-none-linux-gnueabi.exe) (formerly known as CodeSourcery). - -### Mac - -[Carlson-Minot toolchain](http://www.carlson-minot.com/available-arm-gnu-linux-g-lite-builds-for-mac-os-x/mac-os-x-arm-gnu-linux-g-lite-201405-29-toolchain) - - -## Brickstrap - -Brickstrap uses QEMU to create a virtual environment (not exactly a virtual machine) that can run the same ARM -compatible code on a different type of computer. - -Pros: Faster than running on the EV3 itself. Can install all Debian `-dev` packages using `apt-get`. - -Cons: Slower than cross-compiler. Requires Linux (Ubuntu). - -See [this page](https://github.com/ev3dev/ev3dev/wiki/Using-brickstrap-to-cross-compile-and-debug) for instructions. - - -## On the Brick - -It is possible to compile programs on the EV3 brick itself. - -Pros: Easy to setup. - -Cons: Really slow. - -Just run `sudo apt-get install build-essential` on the EV3 and you will have everything your need. diff --git a/cpp/button-test.cpp b/cpp/button-test.cpp deleted file mode 100644 index 5ba552f..0000000 --- a/cpp/button-test.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -#include "ev3dev.h" - -using namespace std; -using namespace ev3dev; - -int -main () -{ - bool up = false, down = false, left = false, right = false, enter = false, - escape = false; - - while (escape == 0) - { - up = button::up.pressed (); - down = button::down.pressed (); - left = button::left.pressed (); - right = button::right.pressed (); - enter = button::enter.pressed (); - escape = button::back.pressed (); - - printf ("up:%d down:%d left:%d right:%d enter:%d esc:%d\n", up, down, - left, right, enter, escape); - usleep (100000); - } -} diff --git a/cpp/drive-test.cpp b/cpp/drive-test.cpp deleted file mode 100644 index c23656c..0000000 --- a/cpp/drive-test.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2014 - Franz Detro - * - * Some real world test program for motor control - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "ev3dev.h" - -#include -#include -#include -#include - -#ifndef NO_LINUX_HEADERS -#include -#include -#include -#define KEY_RELEASE 0 -#define KEY_PRESS 1 -#define KEY_REPEAT 2 -#endif - -using namespace std; -using namespace ev3dev; - -class control -{ -public: - control(); - ~control(); - - void drive(int speed, int time=0); - void turn(int direction); - void stop(); - void reset(); - - bool initialized() const; - - void terminate_on_key(); - void panic_if_touched(); - - void remote_loop(); - void drive_autonomously(); - - void terminate() { _terminate = true; } - -protected: - large_motor _motor_left; - large_motor _motor_right; - infrared_sensor _sensor_ir; - touch_sensor _sensor_touch; - - enum state - { - state_idle, - state_driving, - state_turning - }; - - state _state; - bool _terminate; -}; - -control::control() : - _motor_left(OUTPUT_B), - _motor_right(OUTPUT_C), - _state(state_idle), - _terminate(false) -{ -} - -control::~control() -{ - reset(); -} - -void control::drive(int speed, int time) -{ - _motor_left.set_duty_cycle_sp(-speed); - - _motor_right.set_duty_cycle_sp(-speed); - - _state = state_driving; - - if (time > 0) - { - _motor_left .set_time_sp(time).run_timed(); - _motor_right.set_time_sp(time).run_timed(); - - while (_motor_left.state().count("running") || _motor_right.state().count("running")) - this_thread::sleep_for(chrono::milliseconds(10)); - - _state = state_idle; - } - else - { - _motor_left.run_forever(); - _motor_right.run_forever(); - } -} - -void control::turn(int direction) -{ - if (_state != state_idle) - stop(); - - if (direction == 0) - return; - - _state = state_turning; - - _motor_left. set_position_sp( direction).set_duty_cycle_sp(50).run_to_rel_pos(); - _motor_right.set_position_sp(-direction).set_duty_cycle_sp(50).run_to_rel_pos(); - - while (_motor_left.state().count("running") || _motor_right.state().count("running")) - this_thread::sleep_for(chrono::milliseconds(10)); - - _state = state_idle; -} - -void control::stop() -{ - _motor_left .stop(); - _motor_right.stop(); - - _state = state_idle; -} - -void control::reset() -{ - if (_motor_left.connected()) - _motor_left.reset(); - - if (_motor_right.connected()) - _motor_right.reset(); - - _state = state_idle; -} - -bool control::initialized() const -{ - return (_motor_left .connected() && - _motor_right.connected() && - _sensor_ir .connected()); -} - -void control::terminate_on_key() -{ - #ifndef NO_LINUX_HEADERS - thread t([&] () { - int fd = open("/dev/input/by-path/platform-gpio-keys.0-event", O_RDONLY); - if (fd < 0) - { - cout << "Couldn't open platform-gpio-keys device!" << endl; - return; - } - - input_event ev; - while (true) - { - size_t rb = read(fd, &ev, sizeof(ev)); - - if (rb < sizeof(input_event)) - continue; - - if ((ev.type == EV_KEY) /*&& (ev.value == KEY_PRESS)*/) - { - terminate(); - return; - } - } - }); - t.detach(); - #endif -} - -void control::panic_if_touched() -{ - if (!_sensor_touch.connected()) - { - cout << "no touch sensor found!" << endl; - return; - } - - thread t([&] () { - while (!_terminate) { - if (_sensor_touch.value()) - { - terminate(); - reset(); - break; - } - this_thread::sleep_for(chrono::milliseconds(100)); - } - }); - t.detach(); -} - -void control::remote_loop() -{ - remote_control r(_sensor_ir); - - if (!r.connected()) - { - cout << "no infrared sensor found!" << endl; - return; - } - - const int speed = 70; - const int ninety_degrees = 260; - - r.on_red_up = [&] (bool state) - { - if (state) - { - if (_state == state_idle) - drive(speed); - } - else - stop(); - }; - - r.on_red_down = [&] (bool state) - { - if (state) - { - if (_state == state_idle) - drive(-speed); - } - else - stop(); - }; - - r.on_blue_up = [&] (bool state) - { - if (state) - { - if (_state == state_idle) - turn(-ninety_degrees); - } - }; - - r.on_blue_down = [&] (bool state) - { - if (state) - { - if (_state == state_idle) - turn(ninety_degrees); - } - }; - - r.on_beacon = [&] (bool state) - { - if (state) - terminate(); - }; - - while (!_terminate) - { - if (!r.process()) - { - this_thread::sleep_for(chrono::milliseconds(10)); - } - } - - reset(); -} - -void control::drive_autonomously() -{ - if (!_sensor_ir.connected()) - { - cout << "no infrared sensor found!" << endl; - return; - } - - _sensor_ir.set_mode(infrared_sensor::mode_ir_prox); - - while (!_terminate) - { - int distance = _sensor_ir.value(); - if (distance <= 0) - { - // panic - terminate(); - reset(); - break; - } - else if (distance >= 20) - { - if (_state != state_driving) - drive(75); - this_thread::sleep_for(chrono::milliseconds(10)); - } - else - { - stop(); - - int direction = 100; - int start_distance = distance; - - while (distance <= 40) - { - turn(direction); - - distance = _sensor_ir.value(); - if (distance < start_distance) - { - if (direction < 0) - { - drive(-70, 1000); - } - else - { - direction = -200; - } - } - } - } - } -} - -int main() -{ - control c; - - if (c.initialized()) - { - c.terminate_on_key(); // we terminate if a button is pressed - c.panic_if_touched(); // we panic if the touch sensor is triggered - - // change mode to 1 to get IR remote mode - int mode = 2; - if (mode == 1) - { - cout << "ensure that channel 1 is selected on your remote control." << endl << endl - << "upper red button - forward" << endl - << "lower red button - backward" << endl - << "upper blue button - left" << endl - << "lower blue button - right" << endl - << "middle button - exit" << endl << endl; - - c.remote_loop(); - } - else if (mode == 2) - { - cout << "touch the sensor or press a button to stop." << endl << endl; - - c.drive_autonomously(); - } - } - else - { - cout << "you need to connect an infrared sensor and large motors to ports B and C!" << endl; - return 1; - } - - return 0; -} diff --git a/cpp/ev3dev-lang-demo.cpp b/cpp/ev3dev-lang-demo.cpp deleted file mode 100644 index 2323446..0000000 --- a/cpp/ev3dev-lang-demo.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/* - * demo program for the ev3dev C++ binding - * - * Copyright (c) 2014 - Franz Detro - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "ev3dev.h" - -#include -#include -#include -#include - -using namespace std; -using namespace ev3dev; - -std::ostream& operator<<(std::ostream &os, const std::set &ss) { - os << "[ "; - for(const auto &s : ss) os << s << " "; - return os << "]"; -} - - -void print_values(sensor &s) -{ - auto dp = s.decimals(); - unsigned m = s.num_values(); - for (unsigned i=0; i> c; - - switch (c) - { - case 's': - { - cout << "available modes are "; - const mode_set &m = s.modes(); - for (mode_set::const_iterator it = m.begin(); it!=m.end(); ++it) - { - cout << *it << " "; - } - cout << endl; - } - break; - case 'c': - { - string mode; - cout << endl << "new mode: "; cin >> mode; cout << endl; - s.set_mode(mode); - } - break; - case 'v': - cout << endl << "value is "; print_values(s); cout << endl; - break; - case 'm': - { - bool bStop = false; - thread t([&] () { - char cc; cin >> cc; - bStop = true; - }); - - int value, lastValue = -99999; - while (!bStop) - { - value = s.value(); - if (value != lastValue) - { - lastValue = value; - print_values(s); - cout << endl; - } - this_thread::sleep_for(chrono::milliseconds(100)); - } - t.join(); - } - break; - } - } - while (c != 'b'); -} - -void sensor_menu() -{ - sensor arrSensors[4] { - { INPUT_1 }, - { INPUT_2 }, - { INPUT_3 }, - { INPUT_4 } - }; - - char c = 0; - do - { - cout << endl - << "*** sensor menu ***" << endl - << endl; - - for (unsigned i=0; i<4; ++i) - { - sensor &s = arrSensors[i]; - if (s.connected()) - { - cout << "(" << i+1 << ") " << s.type_name() << " (device " << s.driver_name() - << ", port " << s.address() << ", mode " << s.mode() << ")" << endl; - } - } - cout << endl; - cout << "(b)ack" << endl; - cout << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case '1': - case '2': - case '3': - case '4': - sensor_action(arrSensors[c-'1']); - break; - } - } - while (c != 'b'); -} - -void motor_action(motor &dev) -{ - char c = 0; - int new_value = 0; - std::string answer; - bool running = false; - - do - { - cout << endl - << "*** " << dev.driver_name() << " motor (" << dev.address() << ") actions ***" << endl - << endl - << "(i)nfo" << endl - << "(c)ommand" << endl - << "st(o)p command [" << dev.stop_command() << "]" << endl - << "speed r(e)gulation [" << dev.speed_regulation_enabled() << "]" << endl; - - if (dev.speed_regulation_enabled()==dev.speed_regulation_on) - cout << "speed (s)etpoint (" << dev.speed_sp() << ")" << endl; - else - cout << "duty cycle (s)etpoint (" << dev.duty_cycle_sp() << ")" << endl; - - cout << "(p)osition setpoint (" << dev.position_sp() << ")" << endl - << "ramp (u)p setpoint (" << dev.ramp_up_sp() << ")" << endl - << "ramp (d)own setpoint (" << dev.ramp_down_sp() << ")" << endl - << "(t)ime setpoint (" << dev.time_sp() << ")" << endl - << endl - << "(0) reset position" << endl - << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 'i': - cout << endl; -//~autogen generic_report_status classes.motor>currentClass - - cout << " Commands: "; - try { cout << dev.commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Count Per Rot: "; - try { cout << dev.count_per_rot() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Driver Name: "; - try { cout << dev.driver_name() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Duty Cycle: "; - try { cout << dev.duty_cycle() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Duty Cycle SP: "; - try { cout << dev.duty_cycle_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Encoder Polarity: "; - try { cout << dev.encoder_polarity() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Polarity: "; - try { cout << dev.polarity() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Address: "; - try { cout << dev.address() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position: "; - try { cout << dev.position() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position P: "; - try { cout << dev.position_p() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position I: "; - try { cout << dev.position_i() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position D: "; - try { cout << dev.position_d() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position SP: "; - try { cout << dev.position_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed: "; - try { cout << dev.speed() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed SP: "; - try { cout << dev.speed_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Ramp Up SP: "; - try { cout << dev.ramp_up_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Ramp Down SP: "; - try { cout << dev.ramp_down_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation Enabled: "; - try { cout << dev.speed_regulation_enabled() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation P: "; - try { cout << dev.speed_regulation_p() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation I: "; - try { cout << dev.speed_regulation_i() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation D: "; - try { cout << dev.speed_regulation_d() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " State: "; - try { cout << dev.state() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Stop Command: "; - try { cout << dev.stop_command() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Stop Commands: "; - try { cout << dev.stop_commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Time SP: "; - try { cout << dev.time_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - - -//~autogen - cout << endl; - break; - case 'c': - cout << "command " << dev.commands() << ": "; - cin >> answer; dev.set_command(answer); cout << endl; - break; - case 'o': - cout << "stop command " << dev.stop_commands() << ": "; - cin >> answer; dev.set_stop_command(answer); cout << endl; - break; - case 'e': - cout << "speed regulation (off, on): "; - cin >> answer; dev.set_speed_regulation_enabled(answer); cout << endl; - break; - case 's': - if (dev.speed_regulation_enabled()==dev.speed_regulation_on) - { - cout << "speed: "; cin >> new_value; dev.set_speed_sp(new_value); cout << endl; - } - else - { - cout << "duty cycle: "; cin >> new_value; dev.set_duty_cycle_sp(new_value); cout << endl; - } - break; - case 'p': - cout << "position: "; cin >> new_value; dev.set_position_sp(new_value); cout << endl; - break; - case 'u': - cout << "ramp up: "; cin >> new_value; dev.set_ramp_up_sp(new_value); cout << endl; - break; - case 'd': - cout << "ramp down: "; cin >> new_value; dev.set_ramp_down_sp(new_value); cout << endl; - break; - case 't': - cout << "time: "; cin >> new_value; dev.set_time_sp(new_value); cout << endl; - break; - case '0': - dev.set_position(0); - break; - } - } - while (c != 'b'); -} - -void motor_action(dc_motor &m) -{ - char c = 0; - int new_value = 0; - std::string new_mode; - - do - { - cout << endl - << "*** dc motor (" << m.address() << ") actions ***" << endl - << endl - << "(d)uty cycle sp(" << m.duty_cycle_sp() << ")" << endl - << "(r)amp down sp (" << m.ramp_down_sp() << ")" << endl - << "ramp (u)p sp (" << m.ramp_up_sp() << ")" << endl - << "p(o)larity [" << m.polarity() << "]" << endl; - cout << endl << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 'c': - cout << "command " << m.commands() << ": "; - cin >> new_mode; m.set_command(new_mode); cout << endl; - break; - case 'o': - cout << "polarity (normal, inverted): "; - cin >> new_mode; m.set_polarity(new_mode); cout << endl; - break; - case 'd': - cout << "duty cycle sp: "; cin >> new_value; m.set_duty_cycle_sp(new_value); cout << endl; - break; - case 'r': - cout << "ramp down sp: "; cin >> new_value; m.set_ramp_down_sp(new_value); cout << endl; - break; - case 'u': - cout << "ramp up sp: "; cin >> new_value; m.set_ramp_up_sp(new_value); cout << endl; - break; - } - } - while (c != 'b'); -} - -void motor_action(servo_motor &m) -{ - char c = 0; - int new_value = 0; - std::string new_mode; - - do - { - cout << endl - << "*** servo motor (" << m.address() << ") actions ***" << endl - << endl - << "(c)ommand" << endl - << "(p)osition_sp (" << m.position_sp() << ")" << endl - << "(r)ate_sp (" << m.rate_sp() << ")" << endl - << "mi(n) pulse sp (" << m.min_pulse_sp() << ")" << endl - << "mi(d) pulse sp (" << m.mid_pulse_sp() << ")" << endl - << "ma(x) pulse sp (" << m.max_pulse_sp() << ")" << endl - << "p(o)larity [" << m.polarity() << "]" << endl; - cout << endl << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 'c': - cout << "command (run, float): "; - cin >> new_mode; m.set_command(new_mode); cout << endl; - break; - case 'p': - cout << "position sp: "; cin >> new_value; m.set_position_sp(new_value); cout << endl; - break; - case 'o': - cout << "polarity (normal, inverted): "; - cin >> new_mode; m.set_polarity(new_mode); cout << endl; - break; - case 'r': - cout << "rate sp: "; cin >> new_value; m.set_rate_sp(new_value); cout << endl; - break; - case 'n': - cout << "min pulse sp: "; cin >> new_value; m.set_min_pulse_sp(new_value); cout << endl; - break; - case 'd': - cout << "mid pulse sp: "; cin >> new_value; m.set_mid_pulse_sp(new_value); cout << endl; - break; - case 'x': - cout << "max pulse sp: "; cin >> new_value; m.set_max_pulse_sp(new_value); cout << endl; - break; - } - } - while (c != 'b'); -} - -void motor_menu() -{ - motor arrMotors[4] = { - { OUTPUT_A }, - { OUTPUT_B }, - { OUTPUT_C }, - { OUTPUT_D } - }; - dc_motor arrDCMotors[4] = { - { OUTPUT_A }, - { OUTPUT_B }, - { OUTPUT_C }, - { OUTPUT_D } - }; - servo_motor arrServoMotors[4] = { - { OUTPUT_A }, - { OUTPUT_B }, - { OUTPUT_C }, - { OUTPUT_D } - }; - - char c = 0; - do - { - cout << endl - << "*** motor menu ***" << endl - << endl; - - for (unsigned i=0; i<4; ++i) - { - motor &m = arrMotors[i]; - if (m.connected()) - { - cout << "(" << 1+i << ") " << m.driver_name() << " motor on port " << m.address() << endl; - } - else if (arrDCMotors[i].connected()) - { - cout << "(" << 1+i << ") dc motor on port " << arrDCMotors[i].address() << endl; - } - else if (arrServoMotors[i].connected()) - { - cout << "(" << 1+i << ") servo motor on port " << arrServoMotors[i].address() << endl; - } - } - cout << endl; - cout << "(b)ack" << endl; - cout << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case '1': - case '2': - case '3': - case '4': - if (arrMotors[c-'1'].connected()) - motor_action(arrMotors[c-'1']); - else if (arrMotors[c-'1'].connected()) - motor_action(arrDCMotors[c-'1']); - else if (arrServoMotors[c-'1'].connected()) - motor_action(arrServoMotors[c-'1']); - break; - } - } - while (c != 'b'); -} - -void led_action(const char *name, led &l) -{ - int interval = 500; - char c = 0; - do - { - cout << endl - << "*** " << name << " actions ***" << endl - << endl - << "(0) off" << endl - << "(1) on" << endl - << "(f)lash" << endl - << "(i)nterval" << endl - << "(t)rigger" << endl - << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case '0': - l.off(); - break; - case '1': - l.on(); - break; - case 'f': - l.flash(200, 200); - break; - case 'i': - cout << "interval: "; cin >> interval; cout << endl; - l.set_delay_on(interval); l.set_delay_off(interval); - break; - case 't': - { - cout << "available triggers are " << endl; - mode_type t = l.trigger(); - mode_set s = l.triggers(); - for (mode_set::const_iterator it = s.begin(); it!=s.end(); ++it) - { - if (*it == t) - cout << "[" << *it << "] "; - else - cout << *it << " "; - } - cout << endl << endl << "choice: "; - - cin >> t; - if (!t.empty()) - l.set_trigger(t); - } - break; - } - } - while (c != 'b'); -} - -void led_menu() -{ - led arrPortLEDs[4] { - { "ev3::outA" }, { "ev3::outB" }, { "ev3::outC" }, { "ev3::outD" } }; - - char c = 0; - do - { - cout << endl - << "*** led menu ***" << endl - << endl - << "(1) green:left" << endl - << "(2) green:right" << endl - << "(3) red:left" << endl - << "(4) red:right" << endl; - - for (unsigned i=0; i<4; ++i) - { - if (arrPortLEDs[i].connected()) - { - cout << "(" << 5+i << ") out" << static_cast('A'+i) << endl; - } - } - - cout << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case '1': - led_action("green:left", led::green_left); - break; - case '2': - led_action("green:right", led::green_right); - break; - case '3': - led_action("red:left", led::red_left); - break; - case '4': - led_action("red:right", led::red_right); - break; - case '5': - led_action("outA", arrPortLEDs[0]); - break; - case '6': - led_action("outB", arrPortLEDs[1]); - break; - case '7': - led_action("outC", arrPortLEDs[2]); - break; - case '8': - led_action("outD", arrPortLEDs[3]); - break; - } - } - while (c != 'b'); -} - -void button_menu() -{ - char c = 0; - do - { - cout << endl - << "*** button menu ***" << endl - << endl - << "(1) back" << endl - << "(2) left" << endl - << "(3) right" << endl - << "(4) up" << endl - << "(5) down" << endl - << "(6) enter" << endl - << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case '1': - cout << endl << "back button is " << (button::back.pressed() ? "down" : "up") << endl; - break; - case '2': - cout << endl << "left button is " << (button::left.pressed() ? "down" : "up") << endl; - break; - case '3': - cout << endl << "right button is " << (button::right.pressed() ? "down" : "up") << endl; - break; - case '4': - cout << endl << "up button is " << (button::up.pressed() ? "down" : "up") << endl; - break; - case '5': - cout << endl << "down button is " << (button::down.pressed() ? "down" : "up") << endl; - break; - case '6': - cout << endl << "enter button is " << (button::enter.pressed() ? "down" : "up") << endl; - break; - } - } - while (c != 'b'); -} - -void sound_menu() -{ - unsigned frequency = 440; // 440 Hz - unsigned duration = 1000; // 1 sec - char c = 0; - do - { - cout << endl - << "*** sound menu ***" << endl - << endl - << "b(e)ep" << endl - << "(t)one" << endl - << "tone (d)uration" << endl - << "(p)lay" << endl - << "(s)peak" << endl - << "(v)olume" << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 'e': - sound::beep(); - break; - case 't': - cout << "frequency: "; cin >> frequency; cout << endl; - sound::tone(frequency, duration); - break; - case 'd': - cout << "duration: "; cin >> duration; cout << endl; - sound::tone(frequency, duration); - break; - case 'p': - { - std::string fname; - cout << "soundfile: "; cin >> fname; cout << endl; - sound::play(fname, true); - } - break; - case 's': - { - std::string text; - cout << "text: "; getline(cin, text); getline(cin, text); cout << endl; - sound::speak(text, true); - } - break; - } - } - while (c != 'b'); -} - -void battery_menu() -{ - char c = 0; - do - { - cout << endl - << "*** battery menu ***" << endl - << endl - << "(v)oltage" << endl - << "(c)urrent" << endl - << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 'v': - cout << endl << "voltage is " << power_supply::battery.measured_volts() << " Volt" << endl << endl; - break; - case 'c': - cout << endl << "current is " << power_supply::battery.measured_amps() << " A" << endl << endl; - break; - } - } - while (c != 'b'); -} - -void lcd_menu() -{ - lcd l; - - if (!l.available()) - { - cout << endl - << "###error: lcd not available ###" << endl; - return; - } - - char c = 0; - do - { - cout << endl - << "*** lcd menu ***" << endl - << endl - << "(i)nfo" << endl - << "(f)ill" << endl - << "(c)lear" << endl - << endl - << "(b)ack" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 'i': - cout << endl - << "Resolution is " << l.resolution_x() << " x " << l.resolution_y() - << ", " << l.bits_per_pixel() << " bit(s) per pixel" << endl - << "Frame buffer size is " << l.frame_buffer_size() << " byte, " - << "line length is " << l.line_length() << " byte" << endl; - case 'f': - l.fill(0xFF); - break; - case 'c': - l.fill(0); - break; - } - } - while (c != 'b'); -} - -void main_menu() -{ - char c = 0; - do - { - cout << endl - << "*** main menu ***" << endl - << endl - << "(s)ensors" << endl - << "(m)otors" << endl - << "(l)eds" << endl - << "(b)uttons" << endl - << "s(o)und" << endl - << "b(a)ttery" << endl - << "l(c)d" << endl - << "(q)uit" << endl - << endl - << "Choice: "; - cin >> c; - - switch (c) - { - case 's': - sensor_menu(); - break; - case 'm': - motor_menu(); - break; - case 'l': - led_menu(); - break; - case 'b': - button_menu(); - break; - case 'o': - sound_menu(); - break; - case 'a': - battery_menu(); - break; - case 'c': - lcd_menu(); - break; - } - } - while (c != 'q'); -} - -int main() -{ - main_menu(); - - return 0; -} diff --git a/cpp/ev3dev-lang-test.cpp b/cpp/ev3dev-lang-test.cpp deleted file mode 100644 index bf50af0..0000000 --- a/cpp/ev3dev-lang-test.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - * test program for the ev3dev C++ binding - * - * Copyright (c) 2014 - Franz Detro - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -//----------------------------------------------------------------------------- -//~autogen autogen-header - -// Sections of the following code were auto-generated based on spec v0.9.3-pre, rev 2. - -//~autogen -//----------------------------------------------------------------------------- - -#include "ev3dev.h" - -#include -#include -#include -#include - -using namespace std; -using namespace ev3dev; - - -std::ostream& operator<<(std::ostream &os, const std::set &ss) { - os << "[ "; - for(const auto &s : ss) os << s << " "; - return os << "]"; -} - -template -void test_sensor(const char *name) -{ - S dev; - if (dev.connected()) - { - cout << endl - << "Found " << name << " sensor" << endl - << " Current properties are:" << endl; -//~autogen generic_report_status classes.sensor>currentClass - - cout << " Commands: "; - try { cout << dev.commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Decimals: "; - try { cout << dev.decimals() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Driver Name: "; - try { cout << dev.driver_name() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Mode: "; - try { cout << dev.mode() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Modes: "; - try { cout << dev.modes() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Num Values: "; - try { cout << dev.num_values() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Address: "; - try { cout << dev.address() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Units: "; - try { cout << dev.units() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - - -//~autogen - cout << endl; - } - else - cout << "No " << name << " sensor found" << endl; -} - -template -void test_motor(const char *name) -{ - M dev; - if (dev.connected()) - { - cout << endl - << "Found " << name << " motor" << endl - << " Current properties are:" << endl; -//~autogen generic_report_status classes.motor>currentClass - - cout << " Commands: "; - try { cout << dev.commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Count Per Rot: "; - try { cout << dev.count_per_rot() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Driver Name: "; - try { cout << dev.driver_name() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Duty Cycle: "; - try { cout << dev.duty_cycle() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Duty Cycle SP: "; - try { cout << dev.duty_cycle_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Encoder Polarity: "; - try { cout << dev.encoder_polarity() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Polarity: "; - try { cout << dev.polarity() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Address: "; - try { cout << dev.address() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position: "; - try { cout << dev.position() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position P: "; - try { cout << dev.position_p() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position I: "; - try { cout << dev.position_i() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position D: "; - try { cout << dev.position_d() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position SP: "; - try { cout << dev.position_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed: "; - try { cout << dev.speed() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed SP: "; - try { cout << dev.speed_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Ramp Up SP: "; - try { cout << dev.ramp_up_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Ramp Down SP: "; - try { cout << dev.ramp_down_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation Enabled: "; - try { cout << dev.speed_regulation_enabled() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation P: "; - try { cout << dev.speed_regulation_p() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation I: "; - try { cout << dev.speed_regulation_i() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Speed Regulation D: "; - try { cout << dev.speed_regulation_d() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " State: "; - try { cout << dev.state() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Stop Command: "; - try { cout << dev.stop_command() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Stop Commands: "; - try { cout << dev.stop_commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Time SP: "; - try { cout << dev.time_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - - -//~autogen - cout << endl; - } - else - cout << "No " << name << " motor found" << endl; -} - -void test_dc_motor() -{ - dc_motor dev; - if (dev.connected()) - { - cout << endl - << "Found dc motor" << endl - << " Current properties are:" << endl; -//~autogen generic_report_status classes.dcMotor>currentClass - - cout << " Commands: "; - try { cout << dev.commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Driver Name: "; - try { cout << dev.driver_name() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Duty Cycle: "; - try { cout << dev.duty_cycle() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Duty Cycle SP: "; - try { cout << dev.duty_cycle_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Polarity: "; - try { cout << dev.polarity() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Address: "; - try { cout << dev.address() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Ramp Down SP: "; - try { cout << dev.ramp_down_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Ramp Up SP: "; - try { cout << dev.ramp_up_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " State: "; - try { cout << dev.state() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Stop Commands: "; - try { cout << dev.stop_commands() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Time SP: "; - try { cout << dev.time_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - - -//~autogen - cout << endl; - } - else - cout << "No dc motor found" << endl; -} - -void test_servo_motor() -{ - servo_motor dev; - if (dev.connected()) - { - cout << endl - << "Found servo motor" << endl - << " Current properties are:" << endl; -//~autogen generic_report_status classes.servoMotor>currentClass - - cout << " Driver Name: "; - try { cout << dev.driver_name() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Max Pulse SP: "; - try { cout << dev.max_pulse_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Mid Pulse SP: "; - try { cout << dev.mid_pulse_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Min Pulse SP: "; - try { cout << dev.min_pulse_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Polarity: "; - try { cout << dev.polarity() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Address: "; - try { cout << dev.address() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Position SP: "; - try { cout << dev.position_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " Rate SP: "; - try { cout << dev.rate_sp() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - cout << " State: "; - try { cout << dev.state() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; } - - -//~autogen - cout << endl; - } - else - cout << "No servo motor found" << endl; -} - -int main() -{ - - test_sensor("touch"); - test_sensor("color"); - test_sensor("ultrasonic"); - test_sensor("gyro"); - test_sensor("infrared"); - test_sensor("i2c"); - - cout << endl; - - test_motor("medium"); - test_motor("large"); - - test_dc_motor(); - test_servo_motor(); - - const vector outPortLEDs { - "ev3::outA", - "ev3::outB", - "ev3::outC", - "ev3::outD" - }; - for (auto const &portName : outPortLEDs) - { - led l { portName }; - if (l.connected()) - { - cout << "Brightness of " << portName << " led is " << l.brightness() << endl; - cout << "Trigger of " << portName << " led is " << l.trigger() << endl << endl; - } - } - - cout << "Brightness of left green led is " << led::green_left.brightness() << endl; - cout << "Trigger of right red led is " << led::red_right.trigger() << endl << endl; - - cout << "Beeping..." << endl << endl; sound::beep(); - - cout << "Battery voltage is " << power_supply::battery.measured_volts() << " V" << endl; - cout << "Battery current is " << power_supply::battery.measured_amps() << " A" << endl; - - cout << endl; - - return 0; -} diff --git a/cpp/ev3dev.cpp b/cpp/ev3dev.cpp deleted file mode 100644 index 834c57c..0000000 --- a/cpp/ev3dev.cpp +++ /dev/null @@ -1,1319 +0,0 @@ -/* - * C++ API to the sensors, motors, buttons, LEDs and battery of the ev3dev - * Linux kernel for the LEGO Mindstorms EV3 hardware - * - * Copyright (c) 2014 - Franz Detro - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Modification: - * Add new button for ev3dev Release 02.00.00 (ev3dev-jessie-2014-07-12) - Christophe Chaudelet - * - */ - -//----------------------------------------------------------------------------- -//~autogen autogen-header - -// Sections of the following code were auto-generated based on spec v0.9.3-pre, rev 2. - -//~autogen -//----------------------------------------------------------------------------- - -#include "ev3dev.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifndef SYS_ROOT -#define SYS_ROOT "/sys" -#endif - -#ifndef FSTREAM_CACHE_SIZE -#define FSTREAM_CACHE_SIZE 16 -#endif - -#ifndef NO_LINUX_HEADERS -#include -#include -#else -#define KEY_CNT 8 -#endif -static const int bits_per_long = sizeof(long) * 8; - -//----------------------------------------------------------------------------- - -namespace ev3dev { - -namespace { - -// This class implements a small LRU cache. It assumes the number of elements -// is small, and so uses a simple linear search. -template -class lru_cache -{ -private: - // typedef st::pair item; - // std::pair seems to be missing necessary move constructors :( - struct item - { - K first; - V second; - - item(const K &k) : first(k) {} - item(item &&m) : first(std::move(m.first)), second(std::move(m.second)) {} - }; - -public: - lru_cache(size_t size = 3) : _size(size) - { - } - - V &operator[] (const K &k) - { - iterator i = find(k); - if (i != _items.end()) - { - // Found the key, bring the item to the front. - _items.splice(_items.begin(), _items, i); - } else { - // If the cache is full, remove oldest items to make room. - while (_items.size() + 1 > _size) - { - _items.pop_back(); - } - // Insert a new default constructed value for this new key. - _items.emplace_front(k); - } - // The new item is the most recently used. - return _items.front().second; - } - - void clear() - { - _items.clear(); - } - -private: - typedef typename std::list::iterator iterator; - - iterator find(const K &k) - { - return std::find_if(_items.begin(), _items.end(), - [&](const item &i) { return i.first == k; }); - } - - size_t _size; - std::list _items; -}; - -// A global cache of files. -lru_cache ifstream_cache(FSTREAM_CACHE_SIZE); -lru_cache ofstream_cache(FSTREAM_CACHE_SIZE); -std::mutex ofstream_cache_lock; -std::mutex ifstream_cache_lock; - -//----------------------------------------------------------------------------- - -std::ofstream &ofstream_open(const std::string &path) -{ - std::lock_guard lock(ofstream_cache_lock); - std::ofstream &file = ofstream_cache[path]; - if (!file.is_open()) - { - // Don't buffer writes to avoid latency. Also saves a bit of memory. - file.rdbuf()->pubsetbuf(NULL, 0); - file.open(path); - } - else - { - // Clear the error bits in case something happened. - file.clear(); - } - return file; -} - -std::ifstream &ifstream_open(const std::string &path) -{ - std::lock_guard lock(ifstream_cache_lock); - std::ifstream &file = ifstream_cache[path]; - if (!file.is_open()) - { - file.open(path); - } - else - { - // Clear the flags bits in case something happened (like reaching EOF). - file.clear(); - file.seekg(0, std::ios::beg); - } - return file; -} - -} // namespace - -//----------------------------------------------------------------------------- - -bool device::connect( - const std::string &dir, - const std::string &pattern, - const std::map> &match - ) noexcept -{ - using namespace std; - - const size_t pattern_length = pattern.length(); - - struct dirent *dp; - DIR *dfd; - - if ((dfd = opendir(dir.c_str())) != nullptr) - { - while ((dp = readdir(dfd)) != nullptr) - { - if (strncmp(dp->d_name, pattern.c_str(), pattern_length)==0) - { - try - { - _path = dir + dp->d_name + '/'; - - bool bMatch = true; - for (auto &m : match) - { - const auto &attribute = m.first; - const auto &matches = m.second; - const auto strValue = get_attr_string(attribute); - - if (!matches.empty() && !matches.begin()->empty() && - (matches.find(strValue) == matches.end())) - { - bMatch = false; - break; - } - } - - if (bMatch) { - closedir(dfd); - return true; - } - } - catch (...) { } - - _path.clear(); - } - } - - closedir(dfd); - } - - return false; -} - -//----------------------------------------------------------------------------- - -int device::device_index() const -{ - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - if (_device_index < 0) - { - unsigned f = 1; - _device_index = 0; - for (auto it=_path.rbegin(); it!=_path.rend(); ++it) - { - if ((*it < '0') || (*it > '9')) - break; - - _device_index += (*it -'0') * f; - f *= 10; - } - } - - return _device_index; -} - -//----------------------------------------------------------------------------- - -int device::get_attr_int(const std::string &name) const { - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - for(int attempt = 0; attempt < 2; ++attempt) { - ifstream &is = ifstream_open(_path + name); - if (is.is_open()) - { - int result = 0; - try { - is >> result; - return result; - } catch(...) { - // This could mean the sysfs attribute was recreated and the - // corresponding file handle got stale. Lets close the file and try - // again (once): - if (attempt != 0) throw; - - is.close(); - is.clear(); - } - } else { - throw system_error(make_error_code(errc::no_such_device), _path+name); - } - } -} - -//----------------------------------------------------------------------------- - -void device::set_attr_int(const std::string &name, int value) { - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - for(int attempt = 0; attempt < 2; ++attempt) { - ofstream &os = ofstream_open(_path + name); - if (os.is_open()) - { - if (os << value) return; - - // An error could mean that sysfs attribute was recreated and the cached - // file handle is stale. Lets close the file and try again (once): - if (attempt == 0 && errno == ENODEV) { - os.close(); - os.clear(); - } else { - throw system_error(std::error_code(errno, std::system_category())); - } - } else { - throw system_error(make_error_code(errc::no_such_device), _path + name); - } - } -} - -//----------------------------------------------------------------------------- - -std::string device::get_attr_string(const std::string &name) const -{ - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - ifstream &is = ifstream_open(_path + name); - if (is.is_open()) - { - string result; - is >> result; - return result; - } - - throw system_error(make_error_code(errc::no_such_device), _path+name); -} - -//----------------------------------------------------------------------------- - -void device::set_attr_string(const std::string &name, const std::string &value) -{ - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - ofstream &os = ofstream_open(_path + name); - if (os.is_open()) - { - if (!(os << value)) throw system_error(std::error_code(errno, std::system_category())); - return; - } - - throw system_error(make_error_code(errc::no_such_device), _path+name); -} - -//----------------------------------------------------------------------------- - -std::string device::get_attr_line(const std::string &name) const -{ - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - ifstream &is = ifstream_open(_path + name); - if (is.is_open()) - { - string result; - getline(is, result); - return result; - } - - throw system_error(make_error_code(errc::no_such_device), _path+name); -} - -//----------------------------------------------------------------------------- - -mode_set device::get_attr_set(const std::string &name, - std::string *pCur) const -{ - using namespace std; - - string s = get_attr_line(name); - - mode_set result; - size_t pos, last_pos = 0; - string t; - do { - pos = s.find(' ', last_pos); - - if (pos != string::npos) - { - t = s.substr(last_pos, pos-last_pos); - last_pos = pos+1; - } - else - t = s.substr(last_pos); - - if (!t.empty()) - { - if (*t.begin()=='[') - { - t = t.substr(1, t.length()-2); - if (pCur) - *pCur = t; - } - result.insert(t); - } - } while (pos!=string::npos); - - return result; -} - -//----------------------------------------------------------------------------- - -std::string device::get_attr_from_set(const std::string &name) const -{ - using namespace std; - - string s = get_attr_line(name); - - size_t pos, last_pos = 0; - string t; - do { - pos = s.find(' ', last_pos); - - if (pos != string::npos) - { - t = s.substr(last_pos, pos-last_pos); - last_pos = pos+1; - } - else - t = s.substr(last_pos); - - if (!t.empty()) - { - if (*t.begin()=='[') - { - return t.substr(1, t.length()-2); - } - } - } while (pos!=string::npos); - - return { "none" }; -} - -//----------------------------------------------------------------------------- - -const sensor::sensor_type sensor::ev3_touch { "lego-ev3-touch" }; -const sensor::sensor_type sensor::ev3_color { "lego-ev3-color" }; -const sensor::sensor_type sensor::ev3_ultrasonic { "lego-ev3-us" }; -const sensor::sensor_type sensor::ev3_gyro { "lego-ev3-gyro" }; -const sensor::sensor_type sensor::ev3_infrared { "lego-ev3-ir" }; - -const sensor::sensor_type sensor::nxt_touch { "lego-nxt-touch" }; -const sensor::sensor_type sensor::nxt_light { "lego-nxt-light" }; -const sensor::sensor_type sensor::nxt_sound { "lego-nxt-sound" }; -const sensor::sensor_type sensor::nxt_ultrasonic { "lego-nxt-us" }; -const sensor::sensor_type sensor::nxt_i2c_sensor { "nxt-i2c-sensor" }; -const sensor::sensor_type sensor::nxt_analog { "nxt-analog" }; - -//----------------------------------------------------------------------------- - -sensor::sensor(address_type address) -{ - connect({{ "address", { address }}}); -} - -//----------------------------------------------------------------------------- - -sensor::sensor(address_type address, const std::set &types) -{ - connect({{ "address", { address }}, - { "driver_name", types }}); -} - -//----------------------------------------------------------------------------- - -bool sensor::connect(const std::map> &match) noexcept -{ - static const std::string _strClassDir { SYS_ROOT "/class/lego-sensor/" }; - static const std::string _strPattern { "sensor" }; - - try - { - if (device::connect(_strClassDir, _strPattern, match)) - { - return true; - } - } - catch (...) { } - - _path.clear(); - - return false; -} - -//----------------------------------------------------------------------------- - -std::string sensor::type_name() const -{ - auto type = driver_name(); - if (type.empty()) - { - static const std::string s(""); - return s; - } - - static const std::map lookup_table { - { ev3_touch, "EV3 touch" }, - { ev3_color, "EV3 color" }, - { ev3_ultrasonic, "EV3 ultrasonic" }, - { ev3_gyro, "EV3 gyro" }, - { ev3_infrared, "EV3 infrared" }, - { nxt_touch, "NXT touch" }, - { nxt_light, "NXT light" }, - { nxt_sound, "NXT sound" }, - { nxt_ultrasonic, "NXT ultrasonic" }, - { nxt_i2c_sensor, "I2C sensor" }, - }; - - auto s = lookup_table.find(type); - if (s != lookup_table.end()) - return s->second; - - return type; -} - -//----------------------------------------------------------------------------- - -int sensor::value(unsigned index) const -{ - if (static_cast(index) >= num_values()) - throw std::invalid_argument("index"); - - char svalue[7] = "value0"; - svalue[5] += index; - - return get_attr_int(svalue); -} - -//----------------------------------------------------------------------------- - -float sensor::float_value(unsigned index) const -{ - return value(index) * powf(10, -decimals()); -} - -//----------------------------------------------------------------------------- -const std::vector& sensor::bin_data() const -{ - using namespace std; - - if (_path.empty()) - throw system_error(make_error_code(errc::function_not_supported), "no device connected"); - - if (_bin_data.empty()) { - static const map lookup_table { - {"u8", 1}, - {"s8", 1}, - {"u16", 2}, - {"s16", 2}, - {"s16_be", 2}, - {"s32", 4}, - {"float", 4} - }; - - int value_size = 1; - - auto s = lookup_table.find(bin_data_format()); - if (s != lookup_table.end()) - value_size = s->second; - - _bin_data.resize(num_values() * value_size); - } - - const string fname = _path + "bin_data"; - ifstream &is = ifstream_open(fname); - if (is.is_open()) - { - is.read(_bin_data.data(), _bin_data.size()); - return _bin_data; - } - - throw system_error(make_error_code(errc::no_such_device), fname); -} - -//----------------------------------------------------------------------------- - -i2c_sensor::i2c_sensor(address_type address) : - sensor(address, { nxt_i2c_sensor }) -{ -} - -//----------------------------------------------------------------------------- - -touch_sensor::touch_sensor(address_type address) : - sensor(address, { ev3_touch, nxt_touch }) -{ -} - -//----------------------------------------------------------------------------- - -//~autogen generic-define-property-value specialSensorTypes.colorSensor>currentClass - -const std::string color_sensor::mode_col_reflect{ "COL-REFLECT" }; -const std::string color_sensor::mode_col_ambient{ "COL-AMBIENT" }; -const std::string color_sensor::mode_col_color{ "COL-COLOR" }; -const std::string color_sensor::mode_ref_raw{ "REF-RAW" }; -const std::string color_sensor::mode_rgb_raw{ "RGB-RAW" }; - -//~autogen - -color_sensor::color_sensor(address_type address) : - sensor(address, { ev3_color }) -{ -} - -//----------------------------------------------------------------------------- - -//~autogen generic-define-property-value specialSensorTypes.ultrasonicSensor>currentClass - -const std::string ultrasonic_sensor::mode_us_dist_cm{ "US-DIST-CM" }; -const std::string ultrasonic_sensor::mode_us_dist_in{ "US-DIST-IN" }; -const std::string ultrasonic_sensor::mode_us_listen{ "US-LISTEN" }; -const std::string ultrasonic_sensor::mode_us_si_cm{ "US-SI-CM" }; -const std::string ultrasonic_sensor::mode_us_si_in{ "US-SI-IN" }; - -//~autogen - -ultrasonic_sensor::ultrasonic_sensor(address_type address) : - sensor(address, { ev3_ultrasonic, nxt_ultrasonic }) -{ -} - -//----------------------------------------------------------------------------- - -//~autogen generic-define-property-value specialSensorTypes.gyroSensor>currentClass - -const std::string gyro_sensor::mode_gyro_ang{ "GYRO-ANG" }; -const std::string gyro_sensor::mode_gyro_rate{ "GYRO-RATE" }; -const std::string gyro_sensor::mode_gyro_fas{ "GYRO-FAS" }; -const std::string gyro_sensor::mode_gyro_g_a{ "GYRO-G&A" }; -const std::string gyro_sensor::mode_gyro_cal{ "GYRO-CAL" }; - -//~autogen - -gyro_sensor::gyro_sensor(address_type address) : - sensor(address, { ev3_gyro }) -{ -} - -//----------------------------------------------------------------------------- - -//~autogen generic-define-property-value specialSensorTypes.infraredSensor>currentClass - -const std::string infrared_sensor::mode_ir_prox{ "IR-PROX" }; -const std::string infrared_sensor::mode_ir_seek{ "IR-SEEK" }; -const std::string infrared_sensor::mode_ir_remote{ "IR-REMOTE" }; -const std::string infrared_sensor::mode_ir_rem_a{ "IR-REM-A" }; -const std::string infrared_sensor::mode_ir_cal{ "IR-CAL" }; - -//~autogen - -infrared_sensor::infrared_sensor(address_type address) : - sensor(address, { ev3_infrared }) -{ -} - -//----------------------------------------------------------------------------- - -//~autogen generic-define-property-value specialSensorTypes.soundSensor>currentClass - -const std::string sound_sensor::mode_db{ "DB" }; -const std::string sound_sensor::mode_dba{ "DBA" }; - -//~autogen - -sound_sensor::sound_sensor(address_type address) : - sensor(address, { nxt_sound, nxt_analog }) -{ - if (connected() && driver_name() == nxt_analog) { - lego_port port(address); - - if (port.connected()) { - port.set_set_device(nxt_sound); - - if (port.status() != nxt_sound) { - // Failed to load lego-nxt-sound friver. Wrong port? - _path.clear(); - } - } else { - _path.clear(); - } - } -} - -//----------------------------------------------------------------------------- - -//~autogen generic-define-property-value specialSensorTypes.lightSensor>currentClass - -const std::string light_sensor::mode_reflect{ "REFLECT" }; -const std::string light_sensor::mode_ambient{ "AMBIENT" }; - -//~autogen - -light_sensor::light_sensor(address_type address) : - sensor(address, { nxt_light }) -{ -} - -//----------------------------------------------------------------------------- - -const motor::motor_type motor::motor_large { "lego-ev3-l-motor" }; -const motor::motor_type motor::motor_medium { "lego-ev3-m-motor" }; - -//~autogen generic-define-property-value classes.motor>currentClass - -const std::string motor::command_run_forever{ "run-forever" }; -const std::string motor::command_run_to_abs_pos{ "run-to-abs-pos" }; -const std::string motor::command_run_to_rel_pos{ "run-to-rel-pos" }; -const std::string motor::command_run_timed{ "run-timed" }; -const std::string motor::command_run_direct{ "run-direct" }; -const std::string motor::command_stop{ "stop" }; -const std::string motor::command_reset{ "reset" }; -const std::string motor::encoder_polarity_normal{ "normal" }; -const std::string motor::encoder_polarity_inversed{ "inversed" }; -const std::string motor::polarity_normal{ "normal" }; -const std::string motor::polarity_inversed{ "inversed" }; -const std::string motor::speed_regulation_on{ "on" }; -const std::string motor::speed_regulation_off{ "off" }; -const std::string motor::stop_command_coast{ "coast" }; -const std::string motor::stop_command_brake{ "brake" }; -const std::string motor::stop_command_hold{ "hold" }; - -//~autogen - -//----------------------------------------------------------------------------- - -motor::motor(address_type address) -{ - connect({{ "address", { address } }}); -} - -//----------------------------------------------------------------------------- - -motor::motor(address_type address, const motor_type &t) -{ - connect({{ "address", { address } }, { "driver_name", { t }}}); -} - -//----------------------------------------------------------------------------- - -bool motor::connect(const std::map> &match) noexcept -{ - static const std::string _strClassDir { SYS_ROOT "/class/tacho-motor/" }; - static const std::string _strPattern { "motor" }; - - try - { - return device::connect(_strClassDir, _strPattern, match); - } - catch (...) { } - - _path.clear(); - - return false; -} - -//----------------------------------------------------------------------------- - -medium_motor::medium_motor(address_type address) : motor(address, motor_medium) -{ -} - -//----------------------------------------------------------------------------- - -large_motor::large_motor(address_type address) : motor(address, motor_large) -{ -} - -//----------------------------------------------------------------------------- - -dc_motor::dc_motor(address_type address) -{ - static const std::string _strClassDir { SYS_ROOT "/class/dc-motor/" }; - static const std::string _strPattern { "motor" }; - - connect(_strClassDir, _strPattern, {{ "address", { address }}}); -} - -//~autogen generic-define-property-value classes.dcMotor>currentClass - -const std::string dc_motor::command_run_forever{ "run-forever" }; -const std::string dc_motor::command_run_timed{ "run-timed" }; -const std::string dc_motor::command_run_direct{ "run-direct" }; -const std::string dc_motor::command_stop{ "stop" }; -const std::string dc_motor::polarity_normal{ "normal" }; -const std::string dc_motor::polarity_inversed{ "inversed" }; -const std::string dc_motor::stop_command_coast{ "coast" }; -const std::string dc_motor::stop_command_brake{ "brake" }; - -//~autogen - -//----------------------------------------------------------------------------- - -servo_motor::servo_motor(address_type address) -{ - static const std::string _strClassDir { SYS_ROOT "/class/servo-motor/" }; - static const std::string _strPattern { "motor" }; - - connect(_strClassDir, _strPattern, {{ "address", { address }}}); -} - -//~autogen generic-define-property-value classes.servoMotor>currentClass - -const std::string servo_motor::command_run{ "run" }; -const std::string servo_motor::command_float{ "float" }; -const std::string servo_motor::polarity_normal{ "normal" }; -const std::string servo_motor::polarity_inversed{ "inversed" }; - -//~autogen - -//----------------------------------------------------------------------------- - -led::led(std::string name) -{ - static const std::string _strClassDir { SYS_ROOT "/class/leds/" }; - connect(_strClassDir, name, std::map>()); -} - -//----------------------------------------------------------------------------- - -void led::flash(unsigned on_ms, unsigned off_ms) -{ - static const mode_type timer("timer"); - set_trigger(timer); - if (on_ms) - { - // A workaround for ev3dev/ev3dev#225. - // It takes some time for delay_{on,off} sysfs attributes to appear after - // led trigger has been set to "timer". - for (int i = 0; ; ++i) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - try { - set_delay_on (on_ms ); - set_delay_off(off_ms); - break; - } catch(...) { - if (i >= 5) throw; - } - } - } -} - -//----------------------------------------------------------------------------- - -#ifdef EV3DEV_PLATFORM_BRICKPI -//~autogen leds-define platforms.brickpi.led>currentClass - -led led::blue_led1{"brickpi1:blue:ev3dev"}; -led led::blue_led2{"brickpi2:blue:ev3dev"}; - -std::vector led::led1{ &led::blue_led1 }; -std::vector led::led2{ &led::blue_led2 }; - -std::vector led::blue{ static_cast(1) }; - -//----------------------------------------------------------------------------- -void led::all_off() { - - blue_led1.off(); - blue_led2.off(); - -} - -//~autogen -#else -//~autogen leds-define platforms.ev3.led>currentClass - -led led::red_left{"ev3:left:red:ev3dev"}; -led led::red_right{"ev3:right:red:ev3dev"}; -led led::green_left{"ev3:left:green:ev3dev"}; -led led::green_right{"ev3:right:green:ev3dev"}; - -std::vector led::left{ &led::red_left, &led::green_left }; -std::vector led::right{ &led::red_right, &led::green_right }; - -std::vector led::red{ static_cast(1), static_cast(0) }; -std::vector led::green{ static_cast(0), static_cast(1) }; -std::vector led::amber{ static_cast(1), static_cast(1) }; -std::vector led::orange{ static_cast(1), static_cast(0.5) }; -std::vector led::yellow{ static_cast(0.5), static_cast(1) }; - -//----------------------------------------------------------------------------- -void led::all_off() { - - red_left.off(); - red_right.off(); - green_left.off(); - green_right.off(); - -} - -//~autogen -#endif - -//----------------------------------------------------------------------------- - -void led::set_color(const std::vector &group, const std::vector &color) { - const size_t n = std::min(group.size(), color.size()); - for(size_t i = 0; i < n; ++i) - group[i]->set_brightness_pct(color[i]); -} - -//----------------------------------------------------------------------------- - -power_supply power_supply::battery { "" }; - -//----------------------------------------------------------------------------- - -power_supply::power_supply(std::string name) -{ - static const std::string _strClassDir { SYS_ROOT "/class/power_supply/" }; - - if (name.empty()) - name = "legoev3-battery"; - - connect(_strClassDir, name, std::map>()); -} - -//----------------------------------------------------------------------------- - -button::file_descriptor::file_descriptor(const char *path, int flags) - : _fd(open(path, flags)) -{} - -button::file_descriptor::~file_descriptor() -{ - if (_fd != -1) close(_fd); -} - -//----------------------------------------------------------------------------- - -button::button(int bit) - : _bit(bit), - _buf((KEY_CNT + bits_per_long - 1) / bits_per_long), - _fd( new file_descriptor("/dev/input/by-path/platform-gpio-keys.0-event", O_RDONLY) ) -{ } - -//----------------------------------------------------------------------------- - -bool button::pressed() const -{ -#ifndef NO_LINUX_HEADERS - if (ioctl(*_fd, EVIOCGKEY(_buf.size()), _buf.data()) < 0) - { - // handle error - } -#endif - // bit in bytes is 1 when released and 0 when pressed - return !(_buf[_bit / bits_per_long] & 1 << (_bit % bits_per_long)); -} - -//----------------------------------------------------------------------------- - -bool button::process() -{ - bool new_state = pressed(); - - if (new_state != _state) { - _state = new_state; - if (onclick) onclick(new_state); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -#ifndef NO_LINUX_HEADERS -button button::back (KEY_BACKSPACE); -button button::left (KEY_LEFT); -button button::right(KEY_RIGHT); -button button::up (KEY_UP); -button button::down (KEY_DOWN); -button button::enter(KEY_ENTER); -#endif - -//----------------------------------------------------------------------------- - -bool button::process_all() { - std::array changed = { - back. process(), - left. process(), - right.process(), - up. process(), - down. process(), - enter.process() - }; - return std::any_of(changed.begin(), changed.end(), [](bool c){ return c; }); -} - -//----------------------------------------------------------------------------- - -void sound::beep(const std::string &args, bool bSynchronous) -{ - std::ostringstream cmd; - cmd << "/usr/bin/beep " << args; - if (!bSynchronous) cmd << " &"; - std::system(cmd.str().c_str()); -} - -//----------------------------------------------------------------------------- - -void sound::tone( - const std::vector< std::vector > &sequence, - bool bSynchronous - ) -{ - std::ostringstream args; - bool first = true; - - for(auto v : sequence) { - if (first) { - first = false; - } else { - args << " -n"; - } - - if (v.size() > 0) { - args << " -f " << v[0]; - } else { - continue; - } - - if (v.size() > 1) { - args << " -l " << v[1]; - } else { - continue; - } - - if (v.size() > 2) { - args << " -D " << v[2]; - } else { - continue; - } - } - - beep(args.str(), bSynchronous); -} - -//----------------------------------------------------------------------------- - -void sound::tone(float frequency, float ms, bool bSynchronous) { - tone({{frequency, ms, 0.0f}}, bSynchronous); -} - -//----------------------------------------------------------------------------- - -void sound::play(const std::string &soundfile, bool bSynchronous) -{ - std::ostringstream cmd; - cmd << "/usr/bin/aplay -q " << soundfile; - - if (!bSynchronous) cmd << " &"; - - std::system(cmd.str().c_str()); -} - -//----------------------------------------------------------------------------- - -void sound::speak(const std::string &text, bool bSynchronous) -{ - std::ostringstream cmd; - - cmd << "/usr/bin/espeak -a 200 --stdout \"" << text << "\"" - << " | /usr/bin/aplay -q"; - - if (!bSynchronous) cmd << " &"; - - std::system(cmd.str().c_str()); -} - -//----------------------------------------------------------------------------- - -lcd::lcd() : - _fb(nullptr), - _fbsize(0), - _llength(0), - _xres(0), - _yres(0), - _bpp(0) -{ - init(); -} - -//----------------------------------------------------------------------------- - -lcd::~lcd() -{ - deinit(); -} - -//----------------------------------------------------------------------------- - -void lcd::fill(unsigned char pixel) -{ - if (_fb && _fbsize) - { - memset(_fb, pixel, _fbsize); - } -} - -//----------------------------------------------------------------------------- - -void lcd::init() -{ - using namespace std; - - #ifdef _LINUX_FB_H - int fbf = open("/dev/fb0", O_RDWR); - if (fbf < 0) - return; - - fb_fix_screeninfo i; - if (ioctl(fbf, FBIOGET_FSCREENINFO, &i) < 0) - return; - - _fbsize = i.smem_len; - _llength = i.line_length; - - _fb = (unsigned char*)mmap(NULL, _fbsize, PROT_READ|PROT_WRITE, MAP_SHARED, fbf, 0); - if (_fb == nullptr) - return; - - fb_var_screeninfo v; - - if (ioctl(fbf, FBIOGET_VSCREENINFO, &v) < 0) - return; - - _xres = v.xres; - _yres = v.yres; - _bpp = v.bits_per_pixel; - #endif -} - -//----------------------------------------------------------------------------- - -void lcd::deinit() -{ - if (_fb) - { - munmap(_fb, 0); - } - - _fbsize = 0; -} - -//----------------------------------------------------------------------------- - -remote_control::remote_control(unsigned channel) : - _sensor(new infrared_sensor), - _owns_sensor(true) -{ - if ((channel >= 1) && (channel <=4)) - _channel = channel-1; - - if (_sensor->connected()) - _sensor->set_mode(infrared_sensor::mode_ir_remote); -} - -//----------------------------------------------------------------------------- - -remote_control::remote_control(infrared_sensor &ir, unsigned channel) : - _sensor(&ir), - _owns_sensor(false) -{ - if ((channel >= 1) && (channel <=4)) - _channel = channel-1; - - if (_sensor->connected()) - _sensor->set_mode(infrared_sensor::mode_ir_remote); -} - -//----------------------------------------------------------------------------- - -remote_control::~remote_control() -{ - if (_owns_sensor) - delete _sensor; -} - -//----------------------------------------------------------------------------- - -bool remote_control::process() -{ - int value = _sensor->value(_channel); - if (value != _value) - { - on_value_changed(value); - _value = value; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -void remote_control::on_value_changed(int value) -{ - int new_state = 0; - - switch (value) - { - case 1: - new_state = red_up; - break; - case 2: - new_state = red_down; - break; - case 3: - new_state = blue_up; - break; - case 4: - new_state = blue_down; - break; - case 5: - new_state = red_up | blue_up; - break; - case 6: - new_state = red_up | blue_down; - break; - case 7: - new_state = red_down | blue_up; - break; - case 8: - new_state = red_down | blue_down; - break; - case 9: - new_state = beacon; - break; - case 10: - new_state = red_up | red_down; - break; - case 11: - new_state = blue_up | blue_down; - break; - } - - if (((new_state & red_up) != (_state & red_up)) && - static_cast(on_red_up)) - on_red_up(new_state & red_up); - - if (((new_state & red_down) != (_state & red_down)) && - static_cast(on_red_down)) - on_red_down(new_state & red_down); - - if (((new_state & blue_up) != (_state & blue_up)) && - static_cast(on_blue_up)) - on_blue_up(new_state & blue_up); - - if (((new_state & blue_down) != (_state & blue_down)) && - static_cast(on_blue_down)) - on_blue_down(new_state & blue_down); - - if (((new_state & beacon) != (_state & beacon)) && - static_cast(on_beacon)) - on_beacon(new_state & beacon); - - if ((new_state != _state) && - static_cast(on_state_change)) - on_state_change(new_state); - - _state = new_state; -} - -//----------------------------------------------------------------------------- - -lego_port::lego_port(address_type address) -{ - connect({{ "address", { address } }}); -} - -//----------------------------------------------------------------------------- - -bool lego_port::connect(const std::map> &match) noexcept -{ - static const std::string _strClassDir { SYS_ROOT "/class/lego-port/" }; - static const std::string _strPattern { "port" }; - - try - { - return device::connect(_strClassDir, _strPattern, match); - } - catch (...) { } - - _path.clear(); - - return false; -} - -//----------------------------------------------------------------------------- - -} // namespace ev3dev - -// vim: sw=2 diff --git a/cpp/ev3dev.h b/cpp/ev3dev.h deleted file mode 100644 index ed3ff2c..0000000 --- a/cpp/ev3dev.h +++ /dev/null @@ -1,1741 +0,0 @@ -/* - * C++ API to the sensors, motors, buttons, LEDs and battery of the ev3dev - * Linux kernel for the LEGO Mindstorms EV3 hardware - * - * Copyright (c) 2014 - Franz Detro - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Modification: - * Add new button management for ev3dev Release 02.00.00 (ev3dev-jessie-2014-07-12) - Christophe Chaudelet - * - */ - -#pragma once - -//----------------------------------------------------------------------------- -//~autogen autogen-header - -// Sections of the following code were auto-generated based on spec v0.9.3-pre, rev 2. - -//~autogen -//----------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include - -//----------------------------------------------------------------------------- - -namespace ev3dev { - -//----------------------------------------------------------------------------- - -typedef std::string device_type; -typedef std::string mode_type; -typedef std::set mode_set; -typedef std::string address_type; - -//----------------------------------------------------------------------------- - -const address_type INPUT_AUTO; //!< Automatic input selection -const address_type OUTPUT_AUTO; //!< Automatic output selection - -#ifdef EV3DEV_PLATFORM_BRICKPI -const address_type INPUT_1 { "ttyAMA0:in1" }; //!< Sensor port 1 -const address_type INPUT_2 { "ttyAMA0:in2" }; //!< Sensor port 2 -const address_type INPUT_3 { "ttyAMA0:in3" }; //!< Sensor port 3 -const address_type INPUT_4 { "ttyAMA0:in4" }; //!< Sensor port 4 - -const address_type OUTPUT_A { "ttyAMA0:outA" }; //!< Motor port A -const address_type OUTPUT_B { "ttyAMA0:outB" }; //!< Motor port B -const address_type OUTPUT_C { "ttyAMA0:outC" }; //!< Motor port C -const address_type OUTPUT_D { "ttyAMA0:outD" }; //!< Motor port D -#else -const address_type INPUT_1 { "in1" }; //!< Sensor port 1 -const address_type INPUT_2 { "in2" }; //!< Sensor port 2 -const address_type INPUT_3 { "in3" }; //!< Sensor port 3 -const address_type INPUT_4 { "in4" }; //!< Sensor port 4 - -const address_type OUTPUT_A { "outA" }; //!< Motor port A -const address_type OUTPUT_B { "outB" }; //!< Motor port B -const address_type OUTPUT_C { "outC" }; //!< Motor port C -const address_type OUTPUT_D { "outD" }; //!< Motor port D -#endif - -//----------------------------------------------------------------------------- - -// Generic device class. -class device -{ -public: - bool connect(const std::string &dir, - const std::string &pattern, - const std::map> &match) noexcept; - - inline bool connected() const { return !_path.empty(); } - - int device_index() const; - - int get_attr_int (const std::string &name) const; - void set_attr_int (const std::string &name, - int value); - std::string get_attr_string(const std::string &name) const; - void set_attr_string(const std::string &name, - const std::string &value); - - std::string get_attr_line (const std::string &name) const; - mode_set get_attr_set (const std::string &name, - std::string *pCur = nullptr) const; - - std::string get_attr_from_set(const std::string &name) const; - -protected: - std::string _path; - mutable int _device_index = -1; -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.sensor>currentClass - -// The sensor class provides a uniform interface for using most of the -// sensors available for the EV3. The various underlying device drivers will -// create a `lego-sensor` device for interacting with the sensors. -// -// Sensors are primarily controlled by setting the `mode` and monitored by -// reading the `value` attributes. Values can be converted to floating point -// if needed by `value` / 10.0 ^ `decimals`. -// -// Since the name of the `sensor` device node does not correspond to the port -// that a sensor is plugged in to, you must look at the `address` attribute if -// you need to know which port a sensor is plugged in to. However, if you don't -// have more than one sensor of each type, you can just look for a matching -// `driver_name`. Then it will not matter which port a sensor is plugged in to - your -// program will still work. - -//~autogen -class sensor : protected device -{ -public: - typedef device_type sensor_type; - - static const sensor_type ev3_touch; - static const sensor_type ev3_color; - static const sensor_type ev3_ultrasonic; - static const sensor_type ev3_gyro; - static const sensor_type ev3_infrared; - - static const sensor_type nxt_touch; - static const sensor_type nxt_light; - static const sensor_type nxt_sound; - static const sensor_type nxt_ultrasonic; - static const sensor_type nxt_i2c_sensor; - static const sensor_type nxt_analog; - - sensor(address_type); - sensor(address_type, const std::set&); - - using device::connected; - using device::device_index; - - // Returns the value or values measured by the sensor. Check `num_values` to - // see how many values there are. Values with index >= num_values will return - // an error. The values are fixed point numbers, so check `decimals` to see - // if you need to divide to get the actual value. - int value(unsigned index=0) const; - - // The value converted to float using `decimals`. - float float_value(unsigned index=0) const; - - // Human-readable name of the connected sensor. - std::string type_name() const; - - // Bin Data Format: read-only - // Returns the format of the values in `bin_data` for the current mode. - // Possible values are: - // - // - `u8`: Unsigned 8-bit integer (byte) - // - `s8`: Signed 8-bit integer (sbyte) - // - `u16`: Unsigned 16-bit integer (ushort) - // - `s16`: Signed 16-bit integer (short) - // - `s16_be`: Signed 16-bit integer, big endian - // - `s32`: Signed 32-bit integer (int) - // - `float`: IEEE 754 32-bit floating point (float) - std::string bin_data_format() const { return get_attr_string("bin_data_format"); }; - - // Bin Data: read-only - // Returns the unscaled raw values in the `value` attributes as raw byte - // array. Use `bin_data_format`, `num_values` and the individual sensor - // documentation to determine how to interpret the data. - const std::vector& bin_data() const; - - // Bin Data: read-only - // Writes the unscaled raw values in the `value` attributes into the - // user-provided struct/buffer. Use `bin_data_format`, `num_values` and the - // individual sensor documentation to determine how to interpret the data. - template - void bin_data(T *buf) const { - bin_data(); // fills _bin_data - std::copy_n(_bin_data.data(), _bin_data.size(), static_cast(buf)); - } - -//~autogen generic-get-set classes.sensor>currentClass - - // Command: write-only - // Sends a command to the sensor. - auto set_command(std::string v) -> decltype(*this) { - set_attr_string("command", v); - return *this; - } - - // Commands: read-only - // Returns a list of the valid commands for the sensor. - // Returns -EOPNOTSUPP if no commands are supported. - mode_set commands() const { return get_attr_set("commands"); } - - // Decimals: read-only - // Returns the number of decimal places for the values in the `value` - // attributes of the current mode. - int decimals() const { return get_attr_int("decimals"); } - - // Driver Name: read-only - // Returns the name of the sensor device/driver. See the list of [supported - // sensors] for a complete list of drivers. - std::string driver_name() const { return get_attr_string("driver_name"); } - - // Mode: read/write - // Returns the current mode. Writing one of the values returned by `modes` - // sets the sensor to that mode. - std::string mode() const { return get_attr_string("mode"); } - auto set_mode(std::string v) -> decltype(*this) { - set_attr_string("mode", v); - return *this; - } - - // Modes: read-only - // Returns a list of the valid modes for the sensor. - mode_set modes() const { return get_attr_set("modes"); } - - // Num Values: read-only - // Returns the number of `value` attributes that will return a valid value - // for the current mode. - int num_values() const { return get_attr_int("num_values"); } - - // Address: read-only - // Returns the name of the port that the sensor is connected to, e.g. `ev3:in1`. - // I2C sensors also include the I2C address (decimal), e.g. `ev3:in1:i2c8`. - std::string address() const { return get_attr_string("address"); } - - // Units: read-only - // Returns the units of the measured value for the current mode. May return - // empty string - std::string units() const { return get_attr_string("units"); } - - -//~autogen - -protected: - sensor() {} - - bool connect(const std::map>&) noexcept; - - mutable std::vector _bin_data; -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.i2cSensor>currentClass - -// A generic interface to control I2C-type EV3 sensors. - -//~autogen -class i2c_sensor : public sensor -{ -public: - i2c_sensor(address_type address = INPUT_AUTO); - -//~autogen generic-get-set classes.i2cSensor>currentClass - - // FW Version: read-only - // Returns the firmware version of the sensor if available. Currently only - // I2C/NXT sensors support this. - std::string fw_version() const { return get_attr_string("fw_version"); } - - // Poll MS: read/write - // Returns the polling period of the sensor in milliseconds. Writing sets the - // polling period. Setting to 0 disables polling. Minimum value is hard - // coded as 50 msec. Returns -EOPNOTSUPP if changing polling is not supported. - // Currently only I2C/NXT sensors support changing the polling period. - int poll_ms() const { return get_attr_int("poll_ms"); } - auto set_poll_ms(int v) -> decltype(*this) { - set_attr_int("poll_ms", v); - return *this; - } - - -//~autogen -}; - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.touchSensor>currentClass - -// Touch Sensor -class touch_sensor : public sensor -{ -public: - touch_sensor(address_type address = INPUT_AUTO); - - // Button state - static const std::string mode_touch; - - - // A boolean indicating whether the current touch sensor is being - // pressed. - bool is_pressed() { - set_mode(mode_touch); - return value(0); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.colorSensor>currentClass - -// LEGO EV3 color sensor. -class color_sensor : public sensor -{ -public: - color_sensor(address_type address = INPUT_AUTO); - - // Reflected light. Red LED on. - static const std::string mode_col_reflect; - - // Ambient light. Red LEDs off. - static const std::string mode_col_ambient; - - // Color. All LEDs rapidly cycling, appears white. - static const std::string mode_col_color; - - // Raw reflected. Red LED on - static const std::string mode_ref_raw; - - // Raw Color Components. All LEDs rapidly cycling, appears white. - static const std::string mode_rgb_raw; - - - // Reflected light intensity as a percentage. Light on sensor is red. - int reflected_light_intensity() { - set_mode(mode_col_reflect); - return value(0); - } - - // Ambient light intensity. Light on sensor is dimly lit blue. - int ambient_light_intensity() { - set_mode(mode_col_ambient); - return value(0); - } - - // Color detected by the sensor, categorized by overall value. - // - 0: No color - // - 1: Black - // - 2: Blue - // - 3: Green - // - 4: Yellow - // - 5: Red - // - 6: White - // - 7: Brown - int color() { - set_mode(mode_col_color); - return value(0); - } - - // Red component of the detected color, in the range 0-1020. - int red() { - set_mode(mode_rgb_raw); - return value(0); - } - - // Green component of the detected color, in the range 0-1020. - int green() { - set_mode(mode_rgb_raw); - return value(1); - } - - // Blue component of the detected color, in the range 0-1020. - int blue() { - set_mode(mode_rgb_raw); - return value(2); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.ultrasonicSensor>currentClass - -// LEGO EV3 ultrasonic sensor. -class ultrasonic_sensor : public sensor -{ -public: - ultrasonic_sensor(address_type address = INPUT_AUTO); - - // Continuous measurement in centimeters. - static const std::string mode_us_dist_cm; - - // Continuous measurement in inches. - static const std::string mode_us_dist_in; - - // Listen. - static const std::string mode_us_listen; - - // Single measurement in centimeters. - static const std::string mode_us_si_cm; - - // Single measurement in inches. - static const std::string mode_us_si_in; - - - // Measurement of the distance detected by the sensor, - // in centimeters. - float distance_centimeters() { - set_mode(mode_us_dist_cm); - return float_value(0); - } - - // Measurement of the distance detected by the sensor, - // in inches. - float distance_inches() { - set_mode(mode_us_dist_in); - return float_value(0); - } - - // Value indicating whether another ultrasonic sensor could - // be heard nearby. - bool other_sensor_present() { - set_mode(mode_us_listen); - return value(0); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.gyroSensor>currentClass - -// LEGO EV3 gyro sensor. -class gyro_sensor : public sensor -{ -public: - gyro_sensor(address_type address = INPUT_AUTO); - - // Angle - static const std::string mode_gyro_ang; - - // Rotational speed - static const std::string mode_gyro_rate; - - // Raw sensor value - static const std::string mode_gyro_fas; - - // Angle and rotational speed - static const std::string mode_gyro_g_a; - - // Calibration ??? - static const std::string mode_gyro_cal; - - - // The number of degrees that the sensor has been rotated - // since it was put into this mode. - int angle() { - set_mode(mode_gyro_ang); - return value(0); - } - - // The rate at which the sensor is rotating, in degrees/second. - int rate() { - set_mode(mode_gyro_rate); - return value(0); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.infraredSensor>currentClass - -// LEGO EV3 infrared sensor. -class infrared_sensor : public sensor -{ -public: - infrared_sensor(address_type address = INPUT_AUTO); - - // Proximity - static const std::string mode_ir_prox; - - // IR Seeker - static const std::string mode_ir_seek; - - // IR Remote Control - static const std::string mode_ir_remote; - - // IR Remote Control. State of the buttons is coded in binary - static const std::string mode_ir_rem_a; - - // Calibration ??? - static const std::string mode_ir_cal; - - - // A measurement of the distance between the sensor and the remote, - // as a percentage. 100% is approximately 70cm/27in. - int proximity() { - set_mode(mode_ir_prox); - return value(0); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.soundSensor>currentClass - -// LEGO NXT Sound Sensor -class sound_sensor : public sensor -{ -public: - sound_sensor(address_type address = INPUT_AUTO); - - // Sound pressure level. Flat weighting - static const std::string mode_db; - - // Sound pressure level. A weighting - static const std::string mode_dba; - - - // A measurement of the measured sound pressure level, as a - // percent. Uses a flat weighting. - float sound_pressure() { - set_mode(mode_db); - return float_value(0); - } - - // A measurement of the measured sound pressure level, as a - // percent. Uses A-weighting, which focuses on levels up to 55 dB. - float sound_pressure_low() { - set_mode(mode_dba); - return float_value(0); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen special-sensor-declaration specialSensorTypes.lightSensor>currentClass - -// LEGO NXT Light Sensor -class light_sensor : public sensor -{ -public: - light_sensor(address_type address = INPUT_AUTO); - - // Reflected light. LED on - static const std::string mode_reflect; - - // Ambient light. LED off - static const std::string mode_ambient; - - - // A measurement of the reflected light intensity, as a percentage. - float reflected_light_intensity() { - set_mode(mode_reflect); - return float_value(0); - } - - // A measurement of the ambient light intensity, as a percentage. - float ambient_light_intensity() { - set_mode(mode_ambient); - return float_value(0); - } - -}; - -//~autogen - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.motor>currentClass - -// The motor class provides a uniform interface for using motors with -// positional and directional feedback such as the EV3 and NXT motors. -// This feedback allows for precise control of the motors. This is the -// most common type of motor, so we just call it `motor`. - -//~autogen -class motor : protected device -{ -public: - typedef device_type motor_type; - - motor(address_type); - motor(address_type, const motor_type&); - - static const motor_type motor_large; - static const motor_type motor_medium; - - using device::connected; - using device::device_index; - -//~autogen generic-declare-property-value classes.motor>currentClass - - // Run the motor until another command is sent. - static const std::string command_run_forever; - - // Run to an absolute position specified by `position_sp` and then - // stop using the command specified in `stop_command`. - static const std::string command_run_to_abs_pos; - - // Run to a position relative to the current `position` value. - // The new position will be current `position` + `position_sp`. - // When the new position is reached, the motor will stop using - // the command specified by `stop_command`. - static const std::string command_run_to_rel_pos; - - // Run the motor for the amount of time specified in `time_sp` - // and then stop the motor using the command specified by `stop_command`. - static const std::string command_run_timed; - - // Run the motor at the duty cycle specified by `duty_cycle_sp`. - // Unlike other run commands, changing `duty_cycle_sp` while running *will* - // take effect immediately. - static const std::string command_run_direct; - - // Stop any of the run commands before they are complete using the - // command specified by `stop_command`. - static const std::string command_stop; - - // Reset all of the motor parameter attributes to their default value. - // This will also have the effect of stopping the motor. - static const std::string command_reset; - - // Sets the normal polarity of the rotary encoder. - static const std::string encoder_polarity_normal; - - // Sets the inversed polarity of the rotary encoder. - static const std::string encoder_polarity_inversed; - - // With `normal` polarity, a positive duty cycle will - // cause the motor to rotate clockwise. - static const std::string polarity_normal; - - // With `inversed` polarity, a positive duty cycle will - // cause the motor to rotate counter-clockwise. - static const std::string polarity_inversed; - - // The motor controller will vary the power supplied to the motor - // to try to maintain the speed specified in `speed_sp`. - static const std::string speed_regulation_on; - - // The motor controller will use the power specified in `duty_cycle_sp`. - static const std::string speed_regulation_off; - - // Power will be removed from the motor and it will freely coast to a stop. - static const std::string stop_command_coast; - - // Power will be removed from the motor and a passive electrical load will - // be placed on the motor. This is usually done by shorting the motor terminals - // together. This load will absorb the energy from the rotation of the motors and - // cause the motor to stop more quickly than coasting. - static const std::string stop_command_brake; - - // Does not remove power from the motor. Instead it actively try to hold the motor - // at the current position. If an external force tries to turn the motor, the motor - // will ``push back`` to maintain its position. - static const std::string stop_command_hold; - - -//~autogen - -//~autogen generic-get-set classes.motor>currentClass - - // Command: write-only - // Sends a command to the motor controller. See `commands` for a list of - // possible values. - auto set_command(std::string v) -> decltype(*this) { - set_attr_string("command", v); - return *this; - } - - // Commands: read-only - // Returns a list of commands that are supported by the motor - // controller. Possible values are `run-forever`, `run-to-abs-pos`, `run-to-rel-pos`, - // `run-timed`, `run-direct`, `stop` and `reset`. Not all commands may be supported. - // - // - `run-forever` will cause the motor to run until another command is sent. - // - `run-to-abs-pos` will run to an absolute position specified by `position_sp` - // and then stop using the command specified in `stop_command`. - // - `run-to-rel-pos` will run to a position relative to the current `position` value. - // The new position will be current `position` + `position_sp`. When the new - // position is reached, the motor will stop using the command specified by `stop_command`. - // - `run-timed` will run the motor for the amount of time specified in `time_sp` - // and then stop the motor using the command specified by `stop_command`. - // - `run-direct` will run the motor at the duty cycle specified by `duty_cycle_sp`. - // Unlike other run commands, changing `duty_cycle_sp` while running *will* - // take effect immediately. - // - `stop` will stop any of the run commands before they are complete using the - // command specified by `stop_command`. - // - `reset` will reset all of the motor parameter attributes to their default value. - // This will also have the effect of stopping the motor. - mode_set commands() const { return get_attr_set("commands"); } - - // Count Per Rot: read-only - // Returns the number of tacho counts in one rotation of the motor. Tacho counts - // are used by the position and speed attributes, so you can use this value - // to convert rotations or degrees to tacho counts. In the case of linear - // actuators, the units here will be counts per centimeter. - int count_per_rot() const { return get_attr_int("count_per_rot"); } - - // Driver Name: read-only - // Returns the name of the driver that provides this tacho motor device. - std::string driver_name() const { return get_attr_string("driver_name"); } - - // Duty Cycle: read-only - // Returns the current duty cycle of the motor. Units are percent. Values - // are -100 to 100. - int duty_cycle() const { return get_attr_int("duty_cycle"); } - - // Duty Cycle SP: read/write - // Writing sets the duty cycle setpoint. Reading returns the current value. - // Units are in percent. Valid values are -100 to 100. A negative value causes - // the motor to rotate in reverse. This value is only used when `speed_regulation` - // is off. - int duty_cycle_sp() const { return get_attr_int("duty_cycle_sp"); } - auto set_duty_cycle_sp(int v) -> decltype(*this) { - set_attr_int("duty_cycle_sp", v); - return *this; - } - - // Encoder Polarity: read/write - // Sets the polarity of the rotary encoder. This is an advanced feature to all - // use of motors that send inversed encoder signals to the EV3. This should - // be set correctly by the driver of a device. It You only need to change this - // value if you are using a unsupported device. Valid values are `normal` and - // `inversed`. - std::string encoder_polarity() const { return get_attr_string("encoder_polarity"); } - auto set_encoder_polarity(std::string v) -> decltype(*this) { - set_attr_string("encoder_polarity", v); - return *this; - } - - // Polarity: read/write - // Sets the polarity of the motor. With `normal` polarity, a positive duty - // cycle will cause the motor to rotate clockwise. With `inversed` polarity, - // a positive duty cycle will cause the motor to rotate counter-clockwise. - // Valid values are `normal` and `inversed`. - std::string polarity() const { return get_attr_string("polarity"); } - auto set_polarity(std::string v) -> decltype(*this) { - set_attr_string("polarity", v); - return *this; - } - - // Address: read-only - // Returns the name of the port that this motor is connected to. - std::string address() const { return get_attr_string("address"); } - - // Position: read/write - // Returns the current position of the motor in pulses of the rotary - // encoder. When the motor rotates clockwise, the position will increase. - // Likewise, rotating counter-clockwise causes the position to decrease. - // Writing will set the position to that value. - int position() const { return get_attr_int("position"); } - auto set_position(int v) -> decltype(*this) { - set_attr_int("position", v); - return *this; - } - - // Position P: read/write - // The proportional constant for the position PID. - int position_p() const { return get_attr_int("hold_pid/Kp"); } - auto set_position_p(int v) -> decltype(*this) { - set_attr_int("hold_pid/Kp", v); - return *this; - } - - // Position I: read/write - // The integral constant for the position PID. - int position_i() const { return get_attr_int("hold_pid/Ki"); } - auto set_position_i(int v) -> decltype(*this) { - set_attr_int("hold_pid/Ki", v); - return *this; - } - - // Position D: read/write - // The derivative constant for the position PID. - int position_d() const { return get_attr_int("hold_pid/Kd"); } - auto set_position_d(int v) -> decltype(*this) { - set_attr_int("hold_pid/Kd", v); - return *this; - } - - // Position SP: read/write - // Writing specifies the target position for the `run-to-abs-pos` and `run-to-rel-pos` - // commands. Reading returns the current value. Units are in tacho counts. You - // can use the value returned by `counts_per_rot` to convert tacho counts to/from - // rotations or degrees. - int position_sp() const { return get_attr_int("position_sp"); } - auto set_position_sp(int v) -> decltype(*this) { - set_attr_int("position_sp", v); - return *this; - } - - // Speed: read-only - // Returns the current motor speed in tacho counts per second. Not, this is - // not necessarily degrees (although it is for LEGO motors). Use the `count_per_rot` - // attribute to convert this value to RPM or deg/sec. - int speed() const { return get_attr_int("speed"); } - - // Speed SP: read/write - // Writing sets the target speed in tacho counts per second used when `speed_regulation` - // is on. Reading returns the current value. Use the `count_per_rot` attribute - // to convert RPM or deg/sec to tacho counts per second. - int speed_sp() const { return get_attr_int("speed_sp"); } - auto set_speed_sp(int v) -> decltype(*this) { - set_attr_int("speed_sp", v); - return *this; - } - - // Ramp Up SP: read/write - // Writing sets the ramp up setpoint. Reading returns the current value. Units - // are in milliseconds. When set to a value > 0, the motor will ramp the power - // sent to the motor from 0 to 100% duty cycle over the span of this setpoint - // when starting the motor. If the maximum duty cycle is limited by `duty_cycle_sp` - // or speed regulation, the actual ramp time duration will be less than the setpoint. - int ramp_up_sp() const { return get_attr_int("ramp_up_sp"); } - auto set_ramp_up_sp(int v) -> decltype(*this) { - set_attr_int("ramp_up_sp", v); - return *this; - } - - // Ramp Down SP: read/write - // Writing sets the ramp down setpoint. Reading returns the current value. Units - // are in milliseconds. When set to a value > 0, the motor will ramp the power - // sent to the motor from 100% duty cycle down to 0 over the span of this setpoint - // when stopping the motor. If the starting duty cycle is less than 100%, the - // ramp time duration will be less than the full span of the setpoint. - int ramp_down_sp() const { return get_attr_int("ramp_down_sp"); } - auto set_ramp_down_sp(int v) -> decltype(*this) { - set_attr_int("ramp_down_sp", v); - return *this; - } - - // Speed Regulation Enabled: read/write - // Turns speed regulation on or off. If speed regulation is on, the motor - // controller will vary the power supplied to the motor to try to maintain the - // speed specified in `speed_sp`. If speed regulation is off, the controller - // will use the power specified in `duty_cycle_sp`. Valid values are `on` and - // `off`. - std::string speed_regulation_enabled() const { return get_attr_string("speed_regulation"); } - auto set_speed_regulation_enabled(std::string v) -> decltype(*this) { - set_attr_string("speed_regulation", v); - return *this; - } - - // Speed Regulation P: read/write - // The proportional constant for the speed regulation PID. - int speed_regulation_p() const { return get_attr_int("speed_pid/Kp"); } - auto set_speed_regulation_p(int v) -> decltype(*this) { - set_attr_int("speed_pid/Kp", v); - return *this; - } - - // Speed Regulation I: read/write - // The integral constant for the speed regulation PID. - int speed_regulation_i() const { return get_attr_int("speed_pid/Ki"); } - auto set_speed_regulation_i(int v) -> decltype(*this) { - set_attr_int("speed_pid/Ki", v); - return *this; - } - - // Speed Regulation D: read/write - // The derivative constant for the speed regulation PID. - int speed_regulation_d() const { return get_attr_int("speed_pid/Kd"); } - auto set_speed_regulation_d(int v) -> decltype(*this) { - set_attr_int("speed_pid/Kd", v); - return *this; - } - - // State: read-only - // Reading returns a list of state flags. Possible flags are - // `running`, `ramping` `holding` and `stalled`. - mode_set state() const { return get_attr_set("state"); } - - // Stop Command: read/write - // Reading returns the current stop command. Writing sets the stop command. - // The value determines the motors behavior when `command` is set to `stop`. - // Also, it determines the motors behavior when a run command completes. See - // `stop_commands` for a list of possible values. - std::string stop_command() const { return get_attr_string("stop_command"); } - auto set_stop_command(std::string v) -> decltype(*this) { - set_attr_string("stop_command", v); - return *this; - } - - // Stop Commands: read-only - // Returns a list of stop modes supported by the motor controller. - // Possible values are `coast`, `brake` and `hold`. `coast` means that power will - // be removed from the motor and it will freely coast to a stop. `brake` means - // that power will be removed from the motor and a passive electrical load will - // be placed on the motor. This is usually done by shorting the motor terminals - // together. This load will absorb the energy from the rotation of the motors and - // cause the motor to stop more quickly than coasting. `hold` does not remove - // power from the motor. Instead it actively try to hold the motor at the current - // position. If an external force tries to turn the motor, the motor will 'push - // back' to maintain its position. - mode_set stop_commands() const { return get_attr_set("stop_commands"); } - - // Time SP: read/write - // Writing specifies the amount of time the motor will run when using the - // `run-timed` command. Reading returns the current value. Units are in - // milliseconds. - int time_sp() const { return get_attr_int("time_sp"); } - auto set_time_sp(int v) -> decltype(*this) { - set_attr_int("time_sp", v); - return *this; - } - - -//~autogen - -//~autogen motor_commands classes.motor>currentClass - - // Run the motor until another command is sent. - void run_forever() { set_command("run-forever"); } - - // Run to an absolute position specified by `position_sp` and then - // stop using the command specified in `stop_command`. - void run_to_abs_pos() { set_command("run-to-abs-pos"); } - - // Run to a position relative to the current `position` value. - // The new position will be current `position` + `position_sp`. - // When the new position is reached, the motor will stop using - // the command specified by `stop_command`. - void run_to_rel_pos() { set_command("run-to-rel-pos"); } - - // Run the motor for the amount of time specified in `time_sp` - // and then stop the motor using the command specified by `stop_command`. - void run_timed() { set_command("run-timed"); } - - // Run the motor at the duty cycle specified by `duty_cycle_sp`. - // Unlike other run commands, changing `duty_cycle_sp` while running *will* - // take effect immediately. - void run_direct() { set_command("run-direct"); } - - // Stop any of the run commands before they are complete using the - // command specified by `stop_command`. - void stop() { set_command("stop"); } - - // Reset all of the motor parameter attributes to their default value. - // This will also have the effect of stopping the motor. - void reset() { set_command("reset"); } - - -//~autogen - -protected: - motor() {} - - bool connect(const std::map>&) noexcept; -}; - -//----------------------------------------------------------------------------- - -// EV3 medium motor -class medium_motor : public motor -{ -public: - medium_motor(address_type address = OUTPUT_AUTO); -}; - -//----------------------------------------------------------------------------- - -// EV3 large motor -class large_motor : public motor -{ -public: - large_motor(address_type address = OUTPUT_AUTO); -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.dcMotor>currentClass - -// The DC motor class provides a uniform interface for using regular DC motors -// with no fancy controls or feedback. This includes LEGO MINDSTORMS RCX motors -// and LEGO Power Functions motors. - -//~autogen -class dc_motor : protected device -{ -public: - dc_motor(address_type address = OUTPUT_AUTO); - - using device::connected; - using device::device_index; - -//~autogen generic-declare-property-value classes.dcMotor>currentClass - - // Run the motor until another command is sent. - static const std::string command_run_forever; - - // Run the motor for the amount of time specified in `time_sp` - // and then stop the motor using the command specified by `stop_command`. - static const std::string command_run_timed; - - // Run the motor at the duty cycle specified by `duty_cycle_sp`. - // Unlike other run commands, changing `duty_cycle_sp` while running *will* - // take effect immediately. - static const std::string command_run_direct; - - // Stop any of the run commands before they are complete using the - // command specified by `stop_command`. - static const std::string command_stop; - - // With `normal` polarity, a positive duty cycle will - // cause the motor to rotate clockwise. - static const std::string polarity_normal; - - // With `inversed` polarity, a positive duty cycle will - // cause the motor to rotate counter-clockwise. - static const std::string polarity_inversed; - - // Power will be removed from the motor and it will freely coast to a stop. - static const std::string stop_command_coast; - - // Power will be removed from the motor and a passive electrical load will - // be placed on the motor. This is usually done by shorting the motor terminals - // together. This load will absorb the energy from the rotation of the motors and - // cause the motor to stop more quickly than coasting. - static const std::string stop_command_brake; - - -//~autogen - -//~autogen generic-get-set classes.dcMotor>currentClass - - // Command: write-only - // Sets the command for the motor. Possible values are `run-forever`, `run-timed` and - // `stop`. Not all commands may be supported, so be sure to check the contents - // of the `commands` attribute. - auto set_command(std::string v) -> decltype(*this) { - set_attr_string("command", v); - return *this; - } - - // Commands: read-only - // Returns a list of commands supported by the motor - // controller. - mode_set commands() const { return get_attr_set("commands"); } - - // Driver Name: read-only - // Returns the name of the motor driver that loaded this device. See the list - // of [supported devices] for a list of drivers. - std::string driver_name() const { return get_attr_string("driver_name"); } - - // Duty Cycle: read-only - // Shows the current duty cycle of the PWM signal sent to the motor. Values - // are -100 to 100 (-100% to 100%). - int duty_cycle() const { return get_attr_int("duty_cycle"); } - - // Duty Cycle SP: read/write - // Writing sets the duty cycle setpoint of the PWM signal sent to the motor. - // Valid values are -100 to 100 (-100% to 100%). Reading returns the current - // setpoint. - int duty_cycle_sp() const { return get_attr_int("duty_cycle_sp"); } - auto set_duty_cycle_sp(int v) -> decltype(*this) { - set_attr_int("duty_cycle_sp", v); - return *this; - } - - // Polarity: read/write - // Sets the polarity of the motor. Valid values are `normal` and `inversed`. - std::string polarity() const { return get_attr_string("polarity"); } - auto set_polarity(std::string v) -> decltype(*this) { - set_attr_string("polarity", v); - return *this; - } - - // Address: read-only - // Returns the name of the port that this motor is connected to. - std::string address() const { return get_attr_string("address"); } - - // Ramp Down SP: read/write - // Sets the time in milliseconds that it take the motor to ramp down from 100% - // to 0%. Valid values are 0 to 10000 (10 seconds). Default is 0. - int ramp_down_sp() const { return get_attr_int("ramp_down_sp"); } - auto set_ramp_down_sp(int v) -> decltype(*this) { - set_attr_int("ramp_down_sp", v); - return *this; - } - - // Ramp Up SP: read/write - // Sets the time in milliseconds that it take the motor to up ramp from 0% to - // 100%. Valid values are 0 to 10000 (10 seconds). Default is 0. - int ramp_up_sp() const { return get_attr_int("ramp_up_sp"); } - auto set_ramp_up_sp(int v) -> decltype(*this) { - set_attr_int("ramp_up_sp", v); - return *this; - } - - // State: read-only - // Gets a list of flags indicating the motor status. Possible - // flags are `running` and `ramping`. `running` indicates that the motor is - // powered. `ramping` indicates that the motor has not yet reached the - // `duty_cycle_sp`. - mode_set state() const { return get_attr_set("state"); } - - // Stop Command: write-only - // Sets the stop command that will be used when the motor stops. Read - // `stop_commands` to get the list of valid values. - auto set_stop_command(std::string v) -> decltype(*this) { - set_attr_string("stop_command", v); - return *this; - } - - // Stop Commands: read-only - // Gets a list of stop commands. Valid values are `coast` - // and `brake`. - mode_set stop_commands() const { return get_attr_set("stop_commands"); } - - // Time SP: read/write - // Writing specifies the amount of time the motor will run when using the - // `run-timed` command. Reading returns the current value. Units are in - // milliseconds. - int time_sp() const { return get_attr_int("time_sp"); } - auto set_time_sp(int v) -> decltype(*this) { - set_attr_int("time_sp", v); - return *this; - } - - -//~autogen - -//~autogen motor_commands classes.dcMotor>currentClass - - // Run the motor until another command is sent. - void run_forever() { set_command("run-forever"); } - - // Run the motor for the amount of time specified in `time_sp` - // and then stop the motor using the command specified by `stop_command`. - void run_timed() { set_command("run-timed"); } - - // Run the motor at the duty cycle specified by `duty_cycle_sp`. - // Unlike other run commands, changing `duty_cycle_sp` while running *will* - // take effect immediately. - void run_direct() { set_command("run-direct"); } - - // Stop any of the run commands before they are complete using the - // command specified by `stop_command`. - void stop() { set_command("stop"); } - - -//~autogen - -protected: - std::string _port_name; -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.servoMotor>currentClass - -// The servo motor class provides a uniform interface for using hobby type -// servo motors. - -//~autogen -class servo_motor : protected device -{ -public: - servo_motor(address_type address = OUTPUT_AUTO); - - using device::connected; - using device::device_index; - -//~autogen generic-declare-property-value classes.servoMotor>currentClass - - // Drive servo to the position set in the `position_sp` attribute. - static const std::string command_run; - - // Remove power from the motor. - static const std::string command_float; - - // With `normal` polarity, a positive duty cycle will - // cause the motor to rotate clockwise. - static const std::string polarity_normal; - - // With `inversed` polarity, a positive duty cycle will - // cause the motor to rotate counter-clockwise. - static const std::string polarity_inversed; - - -//~autogen - -//~autogen generic-get-set classes.servoMotor>currentClass - - // Command: write-only - // Sets the command for the servo. Valid values are `run` and `float`. Setting - // to `run` will cause the servo to be driven to the position_sp set in the - // `position_sp` attribute. Setting to `float` will remove power from the motor. - auto set_command(std::string v) -> decltype(*this) { - set_attr_string("command", v); - return *this; - } - - // Driver Name: read-only - // Returns the name of the motor driver that loaded this device. See the list - // of [supported devices] for a list of drivers. - std::string driver_name() const { return get_attr_string("driver_name"); } - - // Max Pulse SP: read/write - // Used to set the pulse size in milliseconds for the signal that tells the - // servo to drive to the maximum (clockwise) position_sp. Default value is 2400. - // Valid values are 2300 to 2700. You must write to the position_sp attribute for - // changes to this attribute to take effect. - int max_pulse_sp() const { return get_attr_int("max_pulse_sp"); } - auto set_max_pulse_sp(int v) -> decltype(*this) { - set_attr_int("max_pulse_sp", v); - return *this; - } - - // Mid Pulse SP: read/write - // Used to set the pulse size in milliseconds for the signal that tells the - // servo to drive to the mid position_sp. Default value is 1500. Valid - // values are 1300 to 1700. For example, on a 180 degree servo, this would be - // 90 degrees. On continuous rotation servo, this is the 'neutral' position_sp - // where the motor does not turn. You must write to the position_sp attribute for - // changes to this attribute to take effect. - int mid_pulse_sp() const { return get_attr_int("mid_pulse_sp"); } - auto set_mid_pulse_sp(int v) -> decltype(*this) { - set_attr_int("mid_pulse_sp", v); - return *this; - } - - // Min Pulse SP: read/write - // Used to set the pulse size in milliseconds for the signal that tells the - // servo to drive to the miniumum (counter-clockwise) position_sp. Default value - // is 600. Valid values are 300 to 700. You must write to the position_sp - // attribute for changes to this attribute to take effect. - int min_pulse_sp() const { return get_attr_int("min_pulse_sp"); } - auto set_min_pulse_sp(int v) -> decltype(*this) { - set_attr_int("min_pulse_sp", v); - return *this; - } - - // Polarity: read/write - // Sets the polarity of the servo. Valid values are `normal` and `inversed`. - // Setting the value to `inversed` will cause the position_sp value to be - // inversed. i.e `-100` will correspond to `max_pulse_sp`, and `100` will - // correspond to `min_pulse_sp`. - std::string polarity() const { return get_attr_string("polarity"); } - auto set_polarity(std::string v) -> decltype(*this) { - set_attr_string("polarity", v); - return *this; - } - - // Address: read-only - // Returns the name of the port that this motor is connected to. - std::string address() const { return get_attr_string("address"); } - - // Position SP: read/write - // Reading returns the current position_sp of the servo. Writing instructs the - // servo to move to the specified position_sp. Units are percent. Valid values - // are -100 to 100 (-100% to 100%) where `-100` corresponds to `min_pulse_sp`, - // `0` corresponds to `mid_pulse_sp` and `100` corresponds to `max_pulse_sp`. - int position_sp() const { return get_attr_int("position_sp"); } - auto set_position_sp(int v) -> decltype(*this) { - set_attr_int("position_sp", v); - return *this; - } - - // Rate SP: read/write - // Sets the rate_sp at which the servo travels from 0 to 100.0% (half of the full - // range of the servo). Units are in milliseconds. Example: Setting the rate_sp - // to 1000 means that it will take a 180 degree servo 2 second to move from 0 - // to 180 degrees. Note: Some servo controllers may not support this in which - // case reading and writing will fail with `-EOPNOTSUPP`. In continuous rotation - // servos, this value will affect the rate_sp at which the speed ramps up or down. - int rate_sp() const { return get_attr_int("rate_sp"); } - auto set_rate_sp(int v) -> decltype(*this) { - set_attr_int("rate_sp", v); - return *this; - } - - // State: read-only - // Returns a list of flags indicating the state of the servo. - // Possible values are: - // * `running`: Indicates that the motor is powered. - mode_set state() const { return get_attr_set("state"); } - - -//~autogen - -//~autogen motor_commands classes.servoMotor>currentClass - - // Drive servo to the position set in the `position_sp` attribute. - void run() { set_command("run"); } - - // Remove power from the motor. - void float_() { set_command("float"); } - - -//~autogen -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.led>currentClass - -// Any device controlled by the generic LED driver. -// See https://www.kernel.org/doc/Documentation/leds/leds-class.txt -// for more details. - -//~autogen -class led : protected device -{ -public: - led(std::string name); - - using device::connected; - -//~autogen generic-get-set classes.led>currentClass - - // Max Brightness: read-only - // Returns the maximum allowable brightness value. - int max_brightness() const { return get_attr_int("max_brightness"); } - - // Brightness: read/write - // Sets the brightness level. Possible values are from 0 to `max_brightness`. - int brightness() const { return get_attr_int("brightness"); } - auto set_brightness(int v) -> decltype(*this) { - set_attr_int("brightness", v); - return *this; - } - - // Triggers: read-only - // Returns a list of available triggers. - mode_set triggers() const { return get_attr_set("trigger"); } - - // Trigger: read/write - // Sets the led trigger. A trigger - // is a kernel based source of led events. Triggers can either be simple or - // complex. A simple trigger isn't configurable and is designed to slot into - // existing subsystems with minimal additional code. Examples are the `ide-disk` and - // `nand-disk` triggers. - // - // Complex triggers whilst available to all LEDs have LED specific - // parameters and work on a per LED basis. The `timer` trigger is an example. - // The `timer` trigger will periodically change the LED brightness between - // 0 and the current brightness setting. The `on` and `off` time can - // be specified via `delay_{on,off}` attributes in milliseconds. - // You can change the brightness value of a LED independently of the timer - // trigger. However, if you set the brightness value to 0 it will - // also disable the `timer` trigger. - std::string trigger() const { return get_attr_from_set("trigger"); } - auto set_trigger(std::string v) -> decltype(*this) { - set_attr_string("trigger", v); - return *this; - } - - // Delay On: read/write - // The `timer` trigger will periodically change the LED brightness between - // 0 and the current brightness setting. The `on` time can - // be specified via `delay_on` attribute in milliseconds. - int delay_on() const { return get_attr_int("delay_on"); } - auto set_delay_on(int v) -> decltype(*this) { - set_attr_int("delay_on", v); - return *this; - } - - // Delay Off: read/write - // The `timer` trigger will periodically change the LED brightness between - // 0 and the current brightness setting. The `off` time can - // be specified via `delay_off` attribute in milliseconds. - int delay_off() const { return get_attr_int("delay_off"); } - auto set_delay_off(int v) -> decltype(*this) { - set_attr_int("delay_off", v); - return *this; - } - - -//~autogen - - // Gets the LED's brightness as a percentage (0-1) of the maximum. - float brightness_pct() const { - return static_cast(brightness()) / max_brightness(); - } - - // Sets the LED's brightness as a percentage (0-1) of the maximum. - auto set_brightness_pct(float v) -> decltype(*this) { - return set_brightness(v * max_brightness()); - } - - // Turns the led on by setting its brightness to the maximum level. - void on() { set_brightness(max_brightness()); } - - // Turns the led off. - void off() { set_brightness(0); } - - // Enables timer trigger and sets delay_on and delay_off attributes to the - // provided values (in milliseconds). - void flash(unsigned on_ms, unsigned off_ms); - -#ifdef EV3DEV_PLATFORM_BRICKPI -//~autogen leds-declare platforms.brickpi.led>currentClass - - static led blue_led1; - static led blue_led2; - - static std::vector led1; - static std::vector led2; - - static std::vector blue; - -//~autogen -#else -//~autogen leds-declare platforms.ev3.led>currentClass - - static led red_left; - static led red_right; - static led green_left; - static led green_right; - - static std::vector left; - static std::vector right; - - static std::vector red; - static std::vector green; - static std::vector amber; - static std::vector orange; - static std::vector yellow; - -//~autogen -#endif - - // Assigns to each led in `group` corresponding brightness percentage from `color`. - static void set_color(const std::vector &group, const std::vector &color); - - static void all_off(); - -protected: - int _max_brightness = 0; -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.powerSupply>currentClass - -// A generic interface to read data from the system's power_supply class. -// Uses the built-in legoev3-battery if none is specified. - -//~autogen -class power_supply : protected device -{ -public: - power_supply(std::string name); - - using device::connected; - -//~autogen generic-get-set classes.powerSupply>currentClass - - // Measured Current: read-only - // The measured current that the battery is supplying (in microamps) - int measured_current() const { return get_attr_int("current_now"); } - - // Measured Voltage: read-only - // The measured voltage that the battery is supplying (in microvolts) - int measured_voltage() const { return get_attr_int("voltage_now"); } - - // Max Voltage: read-only - int max_voltage() const { return get_attr_int("voltage_max_design"); } - - // Min Voltage: read-only - int min_voltage() const { return get_attr_int("voltage_min_design"); } - - // Technology: read-only - std::string technology() const { return get_attr_string("technology"); } - - // Type: read-only - std::string type() const { return get_attr_string("type"); } - - -//~autogen - - float measured_amps() const { return measured_current() / 1000000.f; } - float measured_volts() const { return measured_voltage() / 1000000.f; } - - static power_supply battery; -}; - -//----------------------------------------------------------------------------- - -// EV3 buttons -class button -{ -public: - button(int bit); - - // Check if the button is pressed. - bool pressed() const; - - // Gets called whenever the button state changes. - // The user has to call the process() function to check for state change. - std::function onclick; - - // Check if the button state has changed, - // call onclick function in case it has. - // Returns true if the state has changed since the last call. - bool process(); - - static button back; - static button left; - static button right; - static button up; - static button down; - static button enter; - - // Call process() for each of the EV3 buttons. - // Returns true if any of the states have changed since the last call. - static bool process_all(); - -private: - int _bit; - bool _state = false; - std::vector _buf; - - struct file_descriptor { - int _fd; - - file_descriptor(const char *path, int flags); - ~file_descriptor(); - operator int() { return _fd; } - }; - - std::shared_ptr _fd; -}; - -//----------------------------------------------------------------------------- - -// EV3 Sound -class sound -{ -public: - static void beep(const std::string &args = "", bool bSynchronous = false); - static void tone(float frequency, float ms, bool bSynchronous = false); - static void tone(const std::vector< std::vector > &sequence, bool bSynchronous = false); - static void play(const std::string &soundfile, bool bSynchronous = false); - static void speak(const std::string &text, bool bSynchronous = false); -}; - -//----------------------------------------------------------------------------- - -// EV3 LCD -class lcd -{ -public: - lcd(); - ~lcd(); - - bool available() const { return _fb != nullptr; } - - uint32_t resolution_x() const { return _xres; } - uint32_t resolution_y() const { return _yres; } - uint32_t bits_per_pixel() const { return _bpp; } - - uint32_t frame_buffer_size() const { return _fbsize; } - uint32_t line_length() const { return _llength; } - - unsigned char *frame_buffer() { return _fb; } - - void fill(unsigned char pixel); - -protected: - void init(); - void deinit(); - -private: - unsigned char *_fb; - uint32_t _fbsize; - uint32_t _llength; - uint32_t _xres; - uint32_t _yres; - uint32_t _bpp; -}; - -//----------------------------------------------------------------------------- - -// EV3 remote control -class remote_control -{ -public: - remote_control(unsigned channel = 1); - remote_control(infrared_sensor&, unsigned channel = 1); - virtual ~remote_control(); - - inline bool connected() const { return _sensor->connected(); } - inline unsigned channel() const { return _channel+1; } - - bool process(); - - std::function on_red_up; - std::function on_red_down; - std::function on_blue_up; - std::function on_blue_down; - std::function on_beacon; - std::function on_state_change; - - enum buttons - { - red_up = (1 << 0), - red_down = (1 << 1), - blue_up = (1 << 2), - blue_down = (1 << 3), - beacon = (1 << 4), - }; - -protected: - virtual void on_value_changed(int value); - - infrared_sensor *_sensor = nullptr; - bool _owns_sensor = false; - unsigned _channel = 0; - int _value = 0; - int _state = 0; -}; - -//----------------------------------------------------------------------------- - -//~autogen generic-class-description classes.legoPort>currentClass - -// The `lego-port` class provides an interface for working with input and -// output ports that are compatible with LEGO MINDSTORMS RCX/NXT/EV3, LEGO -// WeDo and LEGO Power Functions sensors and motors. Supported devices include -// the LEGO MINDSTORMS EV3 Intelligent Brick, the LEGO WeDo USB hub and -// various sensor multiplexers from 3rd party manufacturers. -// -// Some types of ports may have multiple modes of operation. For example, the -// input ports on the EV3 brick can communicate with sensors using UART, I2C -// or analog validate signals - but not all at the same time. Therefore there -// are multiple modes available to connect to the different types of sensors. -// -// In most cases, ports are able to automatically detect what type of sensor -// or motor is connected. In some cases though, this must be manually specified -// using the `mode` and `set_device` attributes. The `mode` attribute affects -// how the port communicates with the connected device. For example the input -// ports on the EV3 brick can communicate using UART, I2C or analog voltages, -// but not all at the same time, so the mode must be set to the one that is -// appropriate for the connected sensor. The `set_device` attribute is used to -// specify the exact type of sensor that is connected. Note: the mode must be -// correctly set before setting the sensor type. -// -// Ports can be found at `/sys/class/lego-port/port` where `` is -// incremented each time a new port is registered. Note: The number is not -// related to the actual port at all - use the `address` attribute to find -// a specific port. - -//~autogen -class lego_port : protected device -{ -public: - lego_port(address_type); - - using device::connected; - using device::device_index; - -//~autogen generic-get-set classes.legoPort>currentClass - - // Driver Name: read-only - // Returns the name of the driver that loaded this device. You can find the - // complete list of drivers in the [list of port drivers]. - std::string driver_name() const { return get_attr_string("driver_name"); } - - // Modes: read-only - // Returns a list of the available modes of the port. - mode_set modes() const { return get_attr_set("modes"); } - - // Mode: read/write - // Reading returns the currently selected mode. Writing sets the mode. - // Generally speaking when the mode changes any sensor or motor devices - // associated with the port will be removed new ones loaded, however this - // this will depend on the individual driver implementing this class. - std::string mode() const { return get_attr_string("mode"); } - auto set_mode(std::string v) -> decltype(*this) { - set_attr_string("mode", v); - return *this; - } - - // Address: read-only - // Returns the name of the port. See individual driver documentation for - // the name that will be returned. - std::string address() const { return get_attr_string("address"); } - - // Set Device: write-only - // For modes that support it, writing the name of a driver will cause a new - // device to be registered for that driver and attached to this port. For - // example, since NXT/Analog sensors cannot be auto-detected, you must use - // this attribute to load the correct driver. Returns -EOPNOTSUPP if setting a - // device is not supported. - auto set_set_device(std::string v) -> decltype(*this) { - set_attr_string("set_device", v); - return *this; - } - - // Status: read-only - // In most cases, reading status will return the same value as `mode`. In - // cases where there is an `auto` mode additional values may be returned, - // such as `no-device` or `error`. See individual port driver documentation - // for the full list of possible values. - std::string status() const { return get_attr_string("status"); } - - -//~autogen - -protected: - lego_port() {} - - bool connect(const std::map>&) noexcept; -}; - -//----------------------------------------------------------------------------- - -} // namespace ev3dev - -// vim: sw=2 diff --git a/cpp/remote_control-test.cpp b/cpp/remote_control-test.cpp deleted file mode 100644 index b14675d..0000000 --- a/cpp/remote_control-test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * test program for the ev3dev C++ remote_control class - * - * Copyright (c) 2014 - Franz Detro - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "ev3dev.h" - -#include - - -using namespace std; -using namespace ev3dev; - -void print_button(const char *name, bool state) -{ - cout << name << " " << (state ? "pressed" : "released") << endl; -} - -int main() -{ - remote_control r; - - if (!r.connected()) - { - cout << "no infrared sensor found!" << endl; - return 1; - } - - r.on_red_down = bind(print_button, "red down", placeholders::_1); - r.on_red_up = bind(print_button, "red up", placeholders::_1); - r.on_blue_down = bind(print_button, "blue down", placeholders::_1); - r.on_blue_up = bind(print_button, "blue up", placeholders::_1); - - bool stop = false; - r.on_beacon = [&] (bool state) { if (state) stop = true; }; - - cout << "ensure that channel 1 is selected," << endl - << "press middle (beacon) button to exit!" << endl << endl; - - while (!stop) - r.process(); - - return 0; -} diff --git a/cpp/sound-test.cpp b/cpp/sound-test.cpp deleted file mode 100644 index 40b99ca..0000000 --- a/cpp/sound-test.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "ev3dev.h" - -using namespace ev3dev; - -int main() { - sound::speak("Hello, I am Robot!", true); - sound::tone({ - {392, 350, 100}, {392, 350, 100}, {392, 350, 100}, {311.1, 250, 100}, - {466.2, 25, 100}, {392, 350, 100}, {311.1, 250, 100}, {466.2, 25, 100}, - {392, 700, 100}, {587.32, 350, 100}, {587.32, 350, 100}, - {587.32, 350, 100}, {622.26, 250, 100}, {466.2, 25, 100}, - {369.99, 350, 100}, {311.1, 250, 100}, {466.2, 25, 100}, {392, 700, 100}, - {784, 350, 100}, {392, 250, 100}, {392, 25, 100}, {784, 350, 100}, - {739.98, 250, 100}, {698.46, 25, 100}, {659.26, 25, 100}, - {622.26, 25, 100}, {659.26, 50, 400}, {415.3, 25, 200}, {554.36, 350, 100}, - {523.25, 250, 100}, {493.88, 25, 100}, {466.16, 25, 100}, {440, 25, 100}, - {466.16, 50, 400}, {311.13, 25, 200}, {369.99, 350, 100}, - {311.13, 250, 100}, {392, 25, 100}, {466.16, 350, 100}, {392, 250, 100}, - {466.16, 25, 100}, {587.32, 700, 100}, {784, 350, 100}, {392, 250, 100}, - {392, 25, 100}, {784, 350, 100}, {739.98, 250, 100}, {698.46, 25, 100}, - {659.26, 25, 100}, {622.26, 25, 100}, {659.26, 50, 400}, {415.3, 25, 200}, - {554.36, 350, 100}, {523.25, 250, 100}, {493.88, 25, 100}, - {466.16, 25, 100}, {440, 25, 100}, {466.16, 50, 400}, {311.13, 25, 200}, - {392, 350, 100}, {311.13, 250, 100}, {466.16, 25, 100}, - {392.00, 300, 150}, {311.13, 250, 100}, {466.16, 25, 100}, {392, 700} - }, - true - ); -} diff --git a/cpp/templates/autogen-header.liquid b/cpp/templates/autogen-header.liquid deleted file mode 100644 index ff071fb..0000000 --- a/cpp/templates/autogen-header.liquid +++ /dev/null @@ -1,2 +0,0 @@ - -// Sections of the following code were auto-generated based on spec v{{ meta.version }}{% if meta.specRevision %}, rev {{meta.specRevision}}{% endif %}. diff --git a/cpp/templates/generic-class-description.liquid b/cpp/templates/generic-class-description.liquid deleted file mode 100644 index 8b0ccf2..0000000 --- a/cpp/templates/generic-class-description.liquid +++ /dev/null @@ -1,3 +0,0 @@ -{% for line in currentClass.description %} -// {{ line }}{% -endfor %} diff --git a/cpp/templates/generic-declare-property-value.liquid b/cpp/templates/generic-declare-property-value.liquid deleted file mode 100644 index 5df0545..0000000 --- a/cpp/templates/generic-declare-property-value.liquid +++ /dev/null @@ -1,10 +0,0 @@ -{% for prop in currentClass.propertyValues %}{% - assign prefix = prop.propertyName | downcase | underscore_spaces %}{% - for value in prop.values %}{% - for line in value.description %} - // {{ line }}{% - endfor %}{% - assign cppName = value.name | downcase | underscore_non_wc %} - static const std::string {{ prefix }}_{{cppName}}; -{% endfor %}{% -endfor %} diff --git a/cpp/templates/generic-define-property-value.liquid b/cpp/templates/generic-define-property-value.liquid deleted file mode 100644 index 9b7d344..0000000 --- a/cpp/templates/generic-define-property-value.liquid +++ /dev/null @@ -1,8 +0,0 @@ -{% for prop in currentClass.propertyValues %}{% - assign className = currentClass.friendlyName | downcase | underscore_spaces %}{% - assign prefix = prop.propertyName | downcase | underscore_spaces %}{% - for value in prop.values %}{% - assign cppName = value.name | downcase | underscore_non_wc %} -const std::string {{className}}::{{ prefix }}_{{cppName}}{ "{{ value.name }}" };{% - endfor %}{% -endfor %} diff --git a/cpp/templates/generic-get-set.liquid b/cpp/templates/generic-get-set.liquid deleted file mode 100644 index c8313de..0000000 --- a/cpp/templates/generic-get-set.liquid +++ /dev/null @@ -1,35 +0,0 @@ -{% for prop in currentClass.systemProperties %} - // {{ prop.name }}:{% - if prop.readAccess %}{% - if prop.writeAccess %} read/write{% - else %} read-only{% - endif %}{% - else %} write-only{% - endif %}{% - for line in prop.description %} - // {{ line }}{% - endfor %}{% - assign cppName = prop.name | downcase | underscore_spaces %}{% - assign type = prop.type %}{% - assign getter = prop.type %}{% - assign setter = prop.type %}{% - if prop.type == 'string' %}{% - assign type = 'std::string' %}{% - elsif prop.type == 'string array' %}{% - assign type = 'mode_set' %}{% - assign getter = 'set' %}{% - elsif prop.type == 'string selector' %}{% - assign type = 'std::string' %}{% - assign getter = 'from_set' %}{% - assign setter = 'string' %}{% - endif %}{% - if prop.readAccess == true %} - {{ type }} {{ cppName }}() const { return get_attr_{{ getter }}("{{ prop.systemName }}"); }{% - endif %}{% - if prop.writeAccess == true %} - auto set_{{ cppName }}({{ type }} v) -> decltype(*this) { - set_attr_{{ setter }}("{{ prop.systemName }}", v); - return *this; - }{% - endif %} -{%endfor %} diff --git a/cpp/templates/generic_report_status.liquid b/cpp/templates/generic_report_status.liquid deleted file mode 100644 index 29cc39f..0000000 --- a/cpp/templates/generic_report_status.liquid +++ /dev/null @@ -1,9 +0,0 @@ -{% for prop in currentClass.systemProperties %}{% - assign cppName = prop.name | downcase | underscore_spaces %}{% - if prop.readAccess == true %} - cout << " {{ prop.name }}: "; - try { cout << dev.{{ cppName }}() << endl; } - catch(...) { cout << "[" << strerror(errno) << "]" << endl; }{% - endif %}{% -endfor %} - diff --git a/cpp/templates/leds-declare.liquid b/cpp/templates/leds-declare.liquid deleted file mode 100644 index eb58286..0000000 --- a/cpp/templates/leds-declare.liquid +++ /dev/null @@ -1,12 +0,0 @@ -{% for instance in currentClass.instances %}{% - assign instanceName = instance.name | downcase | underscore_spaces %} - static led {{instanceName}};{% -endfor %} -{% for group in currentClass.groups %}{% - assign groupName = group.name | downcase | underscore_spaces %} - static std::vector {{ groupName }};{% -endfor %} -{% for color in currentClass.colors %}{% - assign colorName = color.name | downcase | underscore_spaces %} - static std::vector {{ colorName }};{% -endfor %} diff --git a/cpp/templates/leds-define.liquid b/cpp/templates/leds-define.liquid deleted file mode 100644 index 39d5b3f..0000000 --- a/cpp/templates/leds-define.liquid +++ /dev/null @@ -1,31 +0,0 @@ -{% for instance in currentClass.instances %}{% - assign instanceName = instance.name | downcase | underscore_spaces %} -led led::{{instanceName}}{"{{instance.systemName}}"};{% -endfor %} -{% for group in currentClass.groups %}{% - assign groupName = group.name | downcase | underscore_spaces %}{% - assign ledNames = '' %}{% - for name in group.entries %}{% - capture ledNames %}{{ ledNames }}&led::{{ name | downcase | underscore_spaces }}{% unless forloop.last %}, {% endunless %}{% - endcapture %}{% - endfor %} -std::vector led::{{ groupName }}{ {{ ledNames }} };{% -endfor %} -{% for color in currentClass.colors %}{% - assign colorName = color.name | downcase | underscore_spaces %}{% - assign mixValues = '' %}{% - for value in color.value %}{% - capture mixValues %}{{ mixValues }}static_cast({{ value }}){% unless forloop.last %}, {% endunless %}{% - endcapture %}{% - endfor %} -std::vector led::{{ colorName }}{ {{ mixValues }} };{% -endfor %} - -//----------------------------------------------------------------------------- -void led::all_off() { -{% for instance in currentClass.instances %}{% - assign instanceName = instance.name | downcase | underscore_spaces %} - {{instanceName}}.off();{% -endfor %} - -} diff --git a/cpp/templates/motor_commands.liquid b/cpp/templates/motor_commands.liquid deleted file mode 100644 index a57d446..0000000 --- a/cpp/templates/motor_commands.liquid +++ /dev/null @@ -1,15 +0,0 @@ -{% for prop in currentClass.propertyValues %}{% - if prop.propertyName == 'Command' %}{% - assign className = currentClass.friendlyName | downcase | underscore_spaces %}{% - for value in prop.values %}{% - assign commandName = value.name | downcase | underscore_non_wc %}{% - if commandName == 'float' %}{% - assign commandName = 'float_' %}{% - endif %}{% - for line in value.description %} - // {{ line }}{% - endfor%} - void {{ commandName }}() { set_command("{{ value.name }}"); } -{% endfor %}{% - endif %}{% -endfor %} diff --git a/cpp/templates/special-sensor-declaration.liquid b/cpp/templates/special-sensor-declaration.liquid deleted file mode 100644 index 549d294..0000000 --- a/cpp/templates/special-sensor-declaration.liquid +++ /dev/null @@ -1,40 +0,0 @@ -{% -assign className = currentClass.friendlyName | downcase | underscore_spaces %}{% -assign parentName = currentClass.inheritance | downcase | underscore_spaces %}{% -for line in currentClass.description %} -// {{ line }}{% -endfor %} -class {{ className }} : public {{ parentName }} -{ -public: - {{className}}(address_type address = INPUT_AUTO); -{% for prop in currentClass.propertyValues %}{% - assign prefix = prop.propertyName | downcase | underscore_spaces %}{% - for value in prop.values %}{% - for line in value.description %} - // {{ line }}{% - endfor %}{% - assign cppName = value.name | downcase | underscore_non_wc %} - static const std::string {{ prefix }}_{{cppName}}; -{% endfor %}{% -endfor %} -{% for mapping in currentClass.sensorValueMappings %}{% - assign name = mapping.name | downcase | underscore_spaces %}{% - assign mode = mapping.requiredMode | downcase | underscore_non_wc %}{% - assign value_index = mapping.sourceValue %}{% - assign type = mapping.type %}{% - assign reader = 'value' %}{% - if type == 'float' %}{% - assign reader = 'float_value' %}{% - elsif type == 'boolean' %}{% - assign type = 'bool' %}{% - endif %}{% - for line in mapping.description %} - // {{ line }}{% - endfor %} - {{ type }} {{ name }}() { - set_mode(mode_{{ mode }}); - return {{ reader }}({{ value_index }}); - } -{% endfor %} -}; diff --git a/exec-autogen.js b/exec-autogen.js new file mode 100755 index 0000000..df12e6c --- /dev/null +++ b/exec-autogen.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node + +// 'require'-ing the autogen entry point will execute it +require('./autogen/autogen.js'); diff --git a/js b/js deleted file mode 160000 index 9925a1c..0000000 --- a/js +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9925a1cd90e3c147876772a0b53085d625bf5e6c diff --git a/python b/python deleted file mode 160000 index 75b3225..0000000 --- a/python +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 75b3225216bb0126323eef1800b4dd58417bd570