Facebook
From pio, 6 Years ago, written in C++.
Embed
Download Paste or View Raw
Hits: 347
  1. /*
  2.  * C++ API to the sensors, motors, buttons, LEDs and battery of the ev3dev
  3.  * Linux kernel for the LEGO Mindstorms EV3 hardware
  4.  *
  5.  * Copyright (c) 2014 - Franz Detro
  6.  *
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  21.  *
  22.  * Modification:
  23.  *  Add new button management for ev3dev Release 02.00.00 (ev3dev-jessie-2014-07-12) - Christophe Chaudelet
  24.  *
  25.  */
  26.  
  27. #pragma once
  28.  
  29. //-----------------------------------------------------------------------------
  30. //~autogen autogen-header
  31.  
  32. // Sections of the following code were auto-generated based on spec v1.2.0.
  33.  
  34. //~autogen
  35. //-----------------------------------------------------------------------------
  36.  
  37. #include <map>
  38. #include <set>
  39. #include <string>
  40. #include <tuple>
  41. #include <vector>
  42. #include <algorithm>
  43. #include <functional>
  44. #include <memory>
  45.  
  46. //-----------------------------------------------------------------------------
  47.  
  48. namespace ev3dev {
  49.  
  50. //-----------------------------------------------------------------------------
  51.  
  52. typedef std::string         device_type;
  53. typedef std::string         mode_type;
  54. typedef std::set<mode_type> mode_set;
  55. typedef std::string         address_type;
  56.  
  57. //-----------------------------------------------------------------------------
  58.  
  59. const address_type INPUT_AUTO;  //!< Automatic input selection
  60. const address_type OUTPUT_AUTO; //!< Automatic output selection
  61.  
  62. #if defined(EV3DEV_PLATFORM_BRICKPI)
  63. constexpr char INPUT_1[]  = "ttyAMA0:in1";  //!< Sensor port 1
  64. constexpr char INPUT_2[]  = "ttyAMA0:in2";  //!< Sensor port 2
  65. constexpr char INPUT_3[]  = "ttyAMA0:in3";  //!< Sensor port 3
  66. constexpr char INPUT_4[]  = "ttyAMA0:in4";  //!< Sensor port 4
  67.  
  68. constexpr char OUTPUT_A[] = "ttyAMA0:outA"; //!< Motor port A
  69. constexpr char OUTPUT_B[] = "ttyAMA0:outB"; //!< Motor port B
  70. constexpr char OUTPUT_C[] = "ttyAMA0:outC"; //!< Motor port C
  71. constexpr char OUTPUT_D[] = "ttyAMA0:outD"; //!< Motor port D
  72. #elif defined(EV3DEV_PLATFORM_PISTORMS)
  73. constexpr char INPUT_1[]  = "pistorms:BAS1"; //!< Sensor port 1
  74. constexpr char INPUT_2[]  = "pistorms:BAS2"; //!< Sensor port 2
  75. constexpr char INPUT_3[]  = "pistorms:BBS1"; //!< Sensor port 3
  76. constexpr char INPUT_4[]  = "pistorms:BBS2"; //!< Sensor port 4
  77.  
  78. constexpr char OUTPUT_A[] = "pistorms:BAM1"; //!< Motor port A
  79. constexpr char OUTPUT_B[] = "pistorms:BAM2"; //!< Motor port B
  80. constexpr char OUTPUT_C[] = "pistorms:BBM1"; //!< Motor port C
  81. constexpr char OUTPUT_D[] = "pistorms:BBM2"; //!< Motor port D
  82. #else // assume EV3DEV_PLATFORM_EV3
  83. constexpr char INPUT_1[]  = "ev3-ports:in1";  //!< Sensor port 1
  84. constexpr char INPUT_2[]  = "ev3-ports:in2";  //!< Sensor port 2
  85. constexpr char INPUT_3[]  = "ev3-ports:in3";  //!< Sensor port 3
  86. constexpr char INPUT_4[]  = "ev3-ports:in4";  //!< Sensor port 4
  87.  
  88. //constexpr char OUTPUT_A[] = "ev3-ports:outA"; //!< Motor port A
  89. //constexpr char OUTPUT_B[] = "ev3-ports:outB"; //!< Motor port B
  90. //constexpr char OUTPUT_C[] = "ev3-ports:outC"; //!< Motor port C
  91. //constexpr char OUTPUT_D[] = "ev3-ports:outD"; //!< Motor port D
  92.  
  93. // piopio
  94. constexpr char OUTPUT_A[] = "outA"; //!< Motor port A
  95. constexpr char OUTPUT_B[] = "outB"; //!< Motor port B
  96. constexpr char OUTPUT_C[] = "outC"; //!< Motor port C
  97. constexpr char OUTPUT_D[] = "outD"; //!< Motor port D
  98. #endif
  99.  
  100. //-----------------------------------------------------------------------------
  101.  
  102. // Generic device class.
  103. class device
  104. {
  105. public:
  106.   bool connect(const std::string &dir,
  107.                const std::string &pattern,
  108.                const std::map<std::string, std::set<std::string>> &match) noexcept;
  109.  
  110.   inline bool connected() const { return !_path.empty(); }
  111.  
  112.   int         device_index() const;
  113.  
  114.   int         get_attr_int   (const std::string &name) const;
  115.   void        set_attr_int   (const std::string &name,
  116.                               int value);
  117.   std::string get_attr_string(const std::string &name) const;
  118.   void        set_attr_string(const std::string &name,
  119.                               const std::string &value);
  120.  
  121.   std::string get_attr_line  (const std::string &name) const;
  122.   mode_set    get_attr_set   (const std::string &name,
  123.                               std::string *pCur = nullptr) const;
  124.  
  125.   std::string get_attr_from_set(const std::string &name) const;
  126.  
  127. protected:
  128.   std::string _path;
  129.   mutable int _device_index = -1;
  130. };
  131.  
  132. //-----------------------------------------------------------------------------
  133.  
  134. //~autogen generic-class-description classes.sensor>currentClass
  135.  
  136. // The sensor class provides a uniform interface for using most of the
  137. // sensors available for the EV3. The various underlying device drivers will
  138. // create a `lego-sensor` device for interacting with the sensors.
  139. //
  140. // Sensors are primarily controlled by setting the `mode` and monitored by
  141. // reading the `value<N>` attributes. Values can be converted to floating point
  142. // if needed by `value<N>` / 10.0 ^ `decimals`.
  143. //
  144. // Since the name of the `sensor<N>` device node does not correspond to the port
  145. // that a sensor is plugged in to, you must look at the `address` attribute if
  146. // you need to know which port a sensor is plugged in to. However, if you don't
  147. // have more than one sensor of each type, you can just look for a matching
  148. // `driver_name`. Then it will not matter which port a sensor is plugged in to - your
  149. // program will still work.
  150.  
  151. //~autogen
  152. class sensor : protected device
  153. {
  154. public:
  155.   typedef device_type sensor_type;
  156.  
  157.   static constexpr char ev3_touch[]      = "lego-ev3-touch";
  158.   static constexpr char ev3_color[]      = "lego-ev3-color";
  159.   static constexpr char ev3_ultrasonic[] = "lego-ev3-us";
  160.   static constexpr char ev3_gyro[]       = "lego-ev3-gyro";
  161.   static constexpr char ev3_infrared[]   = "lego-ev3-ir";
  162.  
  163.   static constexpr char nxt_touch[]      = "lego-nxt-touch";
  164.   static constexpr char nxt_light[]      = "lego-nxt-light";
  165.   static constexpr char nxt_sound[]      = "lego-nxt-sound";
  166.   static constexpr char nxt_ultrasonic[] = "lego-nxt-us";
  167.   static constexpr char nxt_i2c_sensor[] = "nxt-i2c-sensor";
  168.   static constexpr char nxt_analog[]     = "nxt-analog";
  169.  
  170.   sensor(address_type);
  171.   sensor(address_type, const std::set<sensor_type>&);
  172.  
  173.   using device::connected;
  174.   using device::device_index;
  175.  
  176.   // Returns the value or values measured by the sensor. Check `num_values` to
  177.   // see how many values there are. Values with index >= num_values will return
  178.   // an error. The values are fixed point numbers, so check `decimals` to see
  179.   // if you need to divide to get the actual value.
  180.   int   value(unsigned index=0) const;
  181.  
  182.   // The value converted to float using `decimals`.
  183.   float float_value(unsigned index=0) const;
  184.  
  185.   // Human-readable name of the connected sensor.
  186.   std::string type_name() const;
  187.  
  188.   // Bin Data Format: read-only
  189.   // Returns the format of the values in `bin_data` for the current mode.
  190.   // Possible values are:
  191.   //
  192.   //    - `u8`: Unsigned 8-bit integer (byte)
  193.   //    - `s8`: Signed 8-bit integer (sbyte)
  194.   //    - `u16`: Unsigned 16-bit integer (ushort)
  195.   //    - `s16`: Signed 16-bit integer (short)
  196.   //    - `s16_be`: Signed 16-bit integer, big endian
  197.   //    - `s32`: Signed 32-bit integer (int)
  198.   //    - `float`: IEEE 754 32-bit floating point (float)
  199.   std::string bin_data_format() const { return get_attr_string("bin_data_format"); };
  200.  
  201.   // Bin Data: read-only
  202.   // Returns the unscaled raw values in the `value<N>` attributes as raw byte
  203.   // array. Use `bin_data_format`, `num_values` and the individual sensor
  204.   // documentation to determine how to interpret the data.
  205.   const std::vector<char>& bin_data() const;
  206.  
  207.   // Bin Data: read-only
  208.   // Writes the unscaled raw values in the `value<N>` attributes into the
  209.   // user-provided struct/buffer.  Use `bin_data_format`, `num_values` and the
  210.   // individual sensor documentation to determine how to interpret the data.
  211.   template <class T>
  212.   void bin_data(T *buf) const {
  213.       bin_data(); // fills _bin_data
  214.       std::copy_n(_bin_data.data(), _bin_data.size(), reinterpret_cast<char*>(buf));
  215.   }
  216.  
  217. //~autogen generic-get-set classes.sensor>currentClass
  218.  
  219.   // Address: read-only
  220.   // Returns the name of the port that the sensor is connected to, e.g. `ev3:in1`.
  221.   // I2C sensors also include the I2C address (decimal), e.g. `ev3:in1:i2c8`.
  222.   std::string address() const { return get_attr_string("address"); }
  223.  
  224.   // Command: write-only
  225.   // Sends a command to the sensor.
  226.   auto set_command(std::string v) -> decltype(*this) {
  227.     set_attr_string("command", v);
  228.     return *this;
  229.   }
  230.  
  231.   // Commands: read-only
  232.   // Returns a list of the valid commands for the sensor.
  233.   // Returns -EOPNOTSUPP if no commands are supported.
  234.   mode_set commands() const { return get_attr_set("commands"); }
  235.  
  236.   // Decimals: read-only
  237.   // Returns the number of decimal places for the values in the `value<N>`
  238.   // attributes of the current mode.
  239.   int decimals() const { return get_attr_int("decimals"); }
  240.  
  241.   // Driver Name: read-only
  242.   // Returns the name of the sensor device/driver. See the list of [supported
  243.   // sensors] for a complete list of drivers.
  244.   std::string driver_name() const { return get_attr_string("driver_name"); }
  245.  
  246.   // Mode: read/write
  247.   // Returns the current mode. Writing one of the values returned by `modes`
  248.   // sets the sensor to that mode.
  249.   std::string mode() const { return get_attr_string("mode"); }
  250.   auto set_mode(std::string v) -> decltype(*this) {
  251.     set_attr_string("mode", v);
  252.     return *this;
  253.   }
  254.  
  255.   // Modes: read-only
  256.   // Returns a list of the valid modes for the sensor.
  257.   mode_set modes() const { return get_attr_set("modes"); }
  258.  
  259.   // Num Values: read-only
  260.   // Returns the number of `value<N>` attributes that will return a valid value
  261.   // for the current mode.
  262.   int num_values() const { return get_attr_int("num_values"); }
  263.  
  264.   // Units: read-only
  265.   // Returns the units of the measured value for the current mode. May return
  266.   // empty string
  267.   std::string units() const { return get_attr_string("units"); }
  268.  
  269.  
  270. //~autogen
  271.  
  272. protected:
  273.   sensor() {}
  274.  
  275.   bool connect(const std::map<std::string, std::set<std::string>>&) noexcept;
  276.  
  277.   mutable std::vector<char> _bin_data;
  278. };
  279.  
  280. //-----------------------------------------------------------------------------
  281.  
  282. //~autogen generic-class-description classes.i2cSensor>currentClass
  283.  
  284. // A generic interface to control I2C-type EV3 sensors.
  285.  
  286. //~autogen
  287. class i2c_sensor : public sensor
  288. {
  289. public:
  290.   i2c_sensor(
  291.       address_type address = INPUT_AUTO,
  292.       const std::set<sensor_type> &types = {}
  293.       );
  294.  
  295. //~autogen generic-get-set classes.i2cSensor>currentClass
  296.  
  297.   // FW Version: read-only
  298.   // Returns the firmware version of the sensor if available. Currently only
  299.   // I2C/NXT sensors support this.
  300.   std::string fw_version() const { return get_attr_string("fw_version"); }
  301.  
  302.   // Poll MS: read/write
  303.   // Returns the polling period of the sensor in milliseconds. Writing sets the
  304.   // polling period. Setting to 0 disables polling. Minimum value is hard
  305.   // coded as 50 msec. Returns -EOPNOTSUPP if changing polling is not supported.
  306.   // Currently only I2C/NXT sensors support changing the polling period.
  307.   int poll_ms() const { return get_attr_int("poll_ms"); }
  308.   auto set_poll_ms(int v) -> decltype(*this) {
  309.     set_attr_int("poll_ms", v);
  310.     return *this;
  311.   }
  312.  
  313.  
  314. //~autogen
  315. };
  316.  
  317. //-----------------------------------------------------------------------------
  318.  
  319. //~autogen special-sensor-declaration specialSensorTypes.touchSensor>currentClass
  320.  
  321. // Touch Sensor
  322. class touch_sensor : public sensor
  323. {
  324. public:
  325.   touch_sensor(address_type address = INPUT_AUTO);
  326.  
  327.   // Button state
  328.   static constexpr char mode_touch[] = "TOUCH";
  329.  
  330.  
  331.   // A boolean indicating whether the current touch sensor is being
  332.   // pressed.
  333.   bool is_pressed(bool do_set_mode = true) {
  334.     if (do_set_mode) set_mode(mode_touch);
  335.     return value(0);
  336.   }
  337.  
  338. };
  339.  
  340. //~autogen
  341.  
  342. //-----------------------------------------------------------------------------
  343.  
  344. //~autogen special-sensor-declaration specialSensorTypes.colorSensor>currentClass
  345.  
  346. // LEGO EV3 color sensor.
  347. class color_sensor : public sensor
  348. {
  349. public:
  350.   color_sensor(address_type address = INPUT_AUTO);
  351.  
  352.   // Reflected light. Red LED on.
  353.   static constexpr char mode_col_reflect[] = "COL-REFLECT";
  354.  
  355.   // Ambient light. Red LEDs off.
  356.   static constexpr char mode_col_ambient[] = "COL-AMBIENT";
  357.  
  358.   // Color. All LEDs rapidly cycling, appears white.
  359.   static constexpr char mode_col_color[] = "COL-COLOR";
  360.  
  361.   // Raw reflected. Red LED on
  362.   static constexpr char mode_ref_raw[] = "REF-RAW";
  363.  
  364.   // Raw Color Components. All LEDs rapidly cycling, appears white.
  365.   static constexpr char mode_rgb_raw[] = "RGB-RAW";
  366.  
  367.   // No color.
  368.   static constexpr char color_nocolor[] = "NoColor";
  369.  
  370.   // Black color.
  371.   static constexpr char color_black[] = "Black";
  372.  
  373.   // Blue color.
  374.   static constexpr char color_blue[] = "Blue";
  375.  
  376.   // Green color.
  377.   static constexpr char color_green[] = "Green";
  378.  
  379.   // Yellow color.
  380.   static constexpr char color_yellow[] = "Yellow";
  381.  
  382.   // Red color.
  383.   static constexpr char color_red[] = "Red";
  384.  
  385.   // White color.
  386.   static constexpr char color_white[] = "White";
  387.  
  388.   // Brown color.
  389.   static constexpr char color_brown[] = "Brown";
  390.  
  391.  
  392.   // Reflected light intensity as a percentage. Light on sensor is red.
  393.   int reflected_light_intensity(bool do_set_mode = true) {
  394.     if (do_set_mode) set_mode(mode_col_reflect);
  395.     return value(0);
  396.   }
  397.  
  398.   // Ambient light intensity. Light on sensor is dimly lit blue.
  399.   int ambient_light_intensity(bool do_set_mode = true) {
  400.     if (do_set_mode) set_mode(mode_col_ambient);
  401.     return value(0);
  402.   }
  403.  
  404.   // Color detected by the sensor, categorized by overall value.
  405.   //   - 0: No color
  406.   //   - 1: Black
  407.   //   - 2: Blue
  408.   //   - 3: Green
  409.   //   - 4: Yellow
  410.   //   - 5: Red
  411.   //   - 6: White
  412.   //   - 7: Brown
  413.   int color(bool do_set_mode = true) {
  414.     if (do_set_mode) set_mode(mode_col_color);
  415.     return value(0);
  416.   }
  417.  
  418.   // Red, green, and blue components of the detected color, in the range 0-1020.
  419.   std::tuple<int, int, int> raw(bool do_set_mode = true) {
  420.     if (do_set_mode) set_mode(mode_rgb_raw);
  421.     return std::make_tuple( value(0), value(1), value(2) );
  422.   }
  423.  
  424.   // Red component of the detected color, in the range 0-1020.
  425.   int red(bool do_set_mode = true) {
  426.     if (do_set_mode) set_mode(mode_rgb_raw);
  427.     return value(0);
  428.   }
  429.  
  430.   // Green component of the detected color, in the range 0-1020.
  431.   int green(bool do_set_mode = true) {
  432.     if (do_set_mode) set_mode(mode_rgb_raw);
  433.     return value(1);
  434.   }
  435.  
  436.   // Blue component of the detected color, in the range 0-1020.
  437.   int blue(bool do_set_mode = true) {
  438.     if (do_set_mode) set_mode(mode_rgb_raw);
  439.     return value(2);
  440.   }
  441.  
  442. };
  443.  
  444. //~autogen
  445.  
  446. //-----------------------------------------------------------------------------
  447.  
  448. //~autogen special-sensor-declaration specialSensorTypes.ultrasonicSensor>currentClass
  449.  
  450. // LEGO EV3 ultrasonic sensor.
  451. class ultrasonic_sensor : public sensor
  452. {
  453. public:
  454.   ultrasonic_sensor(address_type address = INPUT_AUTO);
  455.  
  456.   ultrasonic_sensor(address_type address, const std::set<sensor_type>& sensorTypes);
  457.  
  458.   // Continuous measurement in centimeters.
  459.   static constexpr char mode_us_dist_cm[] = "US-DIST-CM";
  460.  
  461.   // Continuous measurement in inches.
  462.   static constexpr char mode_us_dist_in[] = "US-DIST-IN";
  463.  
  464.   // Listen.
  465.   static constexpr char mode_us_listen[] = "US-LISTEN";
  466.  
  467.   // Single measurement in centimeters.
  468.   static constexpr char mode_us_si_cm[] = "US-SI-CM";
  469.  
  470.   // Single measurement in inches.
  471.   static constexpr char mode_us_si_in[] = "US-SI-IN";
  472.  
  473.  
  474.   // Measurement of the distance detected by the sensor,
  475.   // in centimeters.
  476.   float distance_centimeters(bool do_set_mode = true) {
  477.     if (do_set_mode) set_mode(mode_us_dist_cm);
  478.     return float_value(0);
  479.   }
  480.  
  481.   // Measurement of the distance detected by the sensor,
  482.   // in inches.
  483.   float distance_inches(bool do_set_mode = true) {
  484.     if (do_set_mode) set_mode(mode_us_dist_in);
  485.     return float_value(0);
  486.   }
  487.  
  488.   // Value indicating whether another ultrasonic sensor could
  489.   // be heard nearby.
  490.   bool other_sensor_present(bool do_set_mode = true) {
  491.     if (do_set_mode) set_mode(mode_us_listen);
  492.     return value(0);
  493.   }
  494.  
  495. };
  496.  
  497. //~autogen
  498.  
  499. //-----------------------------------------------------------------------------
  500.  
  501. //~autogen special-sensor-declaration specialSensorTypes.gyroSensor>currentClass
  502.  
  503. // LEGO EV3 gyro sensor.
  504. class gyro_sensor : public sensor
  505. {
  506. public:
  507.   gyro_sensor(address_type address = INPUT_AUTO);
  508.  
  509.   // Angle
  510.   static constexpr char mode_gyro_ang[] = "GYRO-ANG";
  511.  
  512.   // Rotational speed
  513.   static constexpr char mode_gyro_rate[] = "GYRO-RATE";
  514.  
  515.   // Raw sensor value
  516.   static constexpr char mode_gyro_fas[] = "GYRO-FAS";
  517.  
  518.   // Angle and rotational speed
  519.   static constexpr char mode_gyro_g_a[] = "GYRO-G&A";
  520.  
  521.   // Calibration ???
  522.   static constexpr char mode_gyro_cal[] = "GYRO-CAL";
  523.  
  524.  
  525.   // The number of degrees that the sensor has been rotated
  526.   // since it was put into this mode.
  527.   int angle(bool do_set_mode = true) {
  528.     if (do_set_mode) set_mode(mode_gyro_ang);
  529.     return value(0);
  530.   }
  531.  
  532.   // The rate at which the sensor is rotating, in degrees/second.
  533.   int rate(bool do_set_mode = true) {
  534.     if (do_set_mode) set_mode(mode_gyro_rate);
  535.     return value(0);
  536.   }
  537.  
  538.   // Angle (degrees) and Rotational Speed (degrees/second).
  539.   std::tuple<int, int> rate_and_angle(bool do_set_mode = true) {
  540.     if (do_set_mode) set_mode(mode_gyro_g_a);
  541.     return std::make_tuple( value(0), value(1) );
  542.   }
  543.  
  544. };
  545.  
  546. //~autogen
  547.  
  548. //-----------------------------------------------------------------------------
  549.  
  550. //~autogen special-sensor-declaration specialSensorTypes.infraredSensor>currentClass
  551.  
  552. // LEGO EV3 infrared sensor.
  553. class infrared_sensor : public sensor
  554. {
  555. public:
  556.   infrared_sensor(address_type address = INPUT_AUTO);
  557.  
  558.   // Proximity
  559.   static constexpr char mode_ir_prox[] = "IR-PROX";
  560.  
  561.   // IR Seeker
  562.   static constexpr char mode_ir_seek[] = "IR-SEEK";
  563.  
  564.   // IR Remote Control
  565.   static constexpr char mode_ir_remote[] = "IR-REMOTE";
  566.  
  567.   // IR Remote Control. State of the buttons is coded in binary
  568.   static constexpr char mode_ir_rem_a[] = "IR-REM-A";
  569.  
  570.   // Calibration ???
  571.   static constexpr char mode_ir_cal[] = "IR-CAL";
  572.  
  573.  
  574.   // A measurement of the distance between the sensor and the remote,
  575.   // as a percentage. 100% is approximately 70cm/27in.
  576.   int proximity(bool do_set_mode = true) {
  577.     if (do_set_mode) set_mode(mode_ir_prox);
  578.     return value(0);
  579.   }
  580.  
  581. };
  582.  
  583. //~autogen
  584.  
  585. //-----------------------------------------------------------------------------
  586.  
  587. //~autogen special-sensor-declaration specialSensorTypes.soundSensor>currentClass
  588.  
  589. // LEGO NXT Sound Sensor
  590. class sound_sensor : public sensor
  591. {
  592. public:
  593.   sound_sensor(address_type address = INPUT_AUTO);
  594.  
  595.   // Sound pressure level. Flat weighting
  596.   static constexpr char mode_db[] = "DB";
  597.  
  598.   // Sound pressure level. A weighting
  599.   static constexpr char mode_dba[] = "DBA";
  600.  
  601.  
  602.   // A measurement of the measured sound pressure level, as a
  603.   // percent. Uses a flat weighting.
  604.   float sound_pressure(bool do_set_mode = true) {
  605.     if (do_set_mode) set_mode(mode_db);
  606.     return float_value(0);
  607.   }
  608.  
  609.   // A measurement of the measured sound pressure level, as a
  610.   // percent. Uses A-weighting, which focuses on levels up to 55 dB.
  611.   float sound_pressure_low(bool do_set_mode = true) {
  612.     if (do_set_mode) set_mode(mode_dba);
  613.     return float_value(0);
  614.   }
  615.  
  616. };
  617.  
  618. //~autogen
  619.  
  620. //-----------------------------------------------------------------------------
  621.  
  622. //~autogen special-sensor-declaration specialSensorTypes.lightSensor>currentClass
  623.  
  624. // LEGO NXT Light Sensor
  625. class light_sensor : public sensor
  626. {
  627. public:
  628.   light_sensor(address_type address = INPUT_AUTO);
  629.  
  630.   // Reflected light. LED on
  631.   static constexpr char mode_reflect[] = "REFLECT";
  632.  
  633.   // Ambient light. LED off
  634.   static constexpr char mode_ambient[] = "AMBIENT";
  635.  
  636.  
  637.   // A measurement of the reflected light intensity, as a percentage.
  638.   float reflected_light_intensity(bool do_set_mode = true) {
  639.     if (do_set_mode) set_mode(mode_reflect);
  640.     return float_value(0);
  641.   }
  642.  
  643.   // A measurement of the ambient light intensity, as a percentage.
  644.   float ambient_light_intensity(bool do_set_mode = true) {
  645.     if (do_set_mode) set_mode(mode_ambient);
  646.     return float_value(0);
  647.   }
  648.  
  649. };
  650.  
  651. //~autogen
  652.  
  653. //-----------------------------------------------------------------------------
  654.  
  655. //~autogen generic-class-description classes.motor>currentClass
  656.  
  657. // The motor class provides a uniform interface for using motors with
  658. // positional and directional feedback such as the EV3 and NXT motors.
  659. // This feedback allows for precise control of the motors. This is the
  660. // most common type of motor, so we just call it `motor`.
  661. //
  662. // The way to configure a motor is to set the '_sp' attributes when
  663. // calling a command or before. Only in 'run_direct' mode attribute
  664. // changes are processed immediately, in the other modes they only
  665. // take place when a new command is issued.
  666.  
  667. //~autogen
  668. class motor : protected device
  669. {
  670. public:
  671.   typedef device_type motor_type;
  672.  
  673.   motor(address_type);
  674.   motor(address_type, const motor_type&);
  675.  
  676.   static constexpr char motor_large[]  = "lego-ev3-l-motor";
  677.   static constexpr char motor_medium[] = "lego-ev3-m-motor";
  678.  
  679.   using device::connected;
  680.   using device::device_index;
  681.  
  682. //~autogen generic-declare-property-value classes.motor>currentClass
  683.  
  684.   // Run the motor until another command is sent.
  685.   static constexpr char command_run_forever[] = "run-forever";
  686.  
  687.   // Run to an absolute position specified by `position_sp` and then
  688.   // stop using the action specified in `stop_action`.
  689.   static constexpr char command_run_to_abs_pos[] = "run-to-abs-pos";
  690.  
  691.   // Run to a position relative to the current `position` value.
  692.   // The new position will be current `position` + `position_sp`.
  693.   // When the new position is reached, the motor will stop using
  694.   // the action specified by `stop_action`.
  695.   static constexpr char command_run_to_rel_pos[] = "run-to-rel-pos";
  696.  
  697.   // Run the motor for the amount of time specified in `time_sp`
  698.   // and then stop the motor using the action specified by `stop_action`.
  699.   static constexpr char command_run_timed[] = "run-timed";
  700.  
  701.   // Run the motor at the duty cycle specified by `duty_cycle_sp`.
  702.   // Unlike other run commands, changing `duty_cycle_sp` while running *will*
  703.   // take effect immediately.
  704.   static constexpr char command_run_direct[] = "run-direct";
  705.  
  706.   // Stop any of the run commands before they are complete using the
  707.   // action specified by `stop_action`.
  708.   static constexpr char command_stop[] = "stop";
  709.  
  710.   // Reset all of the motor parameter attributes to their default value.
  711.   // This will also have the effect of stopping the motor.
  712.   static constexpr char command_reset[] = "reset";
  713.  
  714.   // Sets the normal polarity of the rotary encoder.
  715.   static constexpr char encoder_polarity_normal[] = "normal";
  716.  
  717.   // Sets the inversed polarity of the rotary encoder.
  718.   static constexpr char encoder_polarity_inversed[] = "inversed";
  719.  
  720.   // With `normal` polarity, a positive duty cycle will
  721.   // cause the motor to rotate clockwise.
  722.   static constexpr char polarity_normal[] = "normal";
  723.  
  724.   // With `inversed` polarity, a positive duty cycle will
  725.   // cause the motor to rotate counter-clockwise.
  726.   static constexpr char polarity_inversed[] = "inversed";
  727.  
  728.   // Power is being sent to the motor.
  729.   static constexpr char state_running[] = "running";
  730.  
  731.   // The motor is ramping up or down and has not yet reached a constant output level.
  732.   static constexpr char state_ramping[] = "ramping";
  733.  
  734.   // The motor is not turning, but rather attempting to hold a fixed position.
  735.   static constexpr char state_holding[] = "holding";
  736.  
  737.   // The motor is turning, but cannot reach its `speed_sp`.
  738.   static constexpr char state_overloaded[] = "overloaded";
  739.  
  740.   // The motor is not turning when it should be.
  741.   static constexpr char state_stalled[] = "stalled";
  742.  
  743.   // Power will be removed from the motor and it will freely coast to a stop.
  744.   static constexpr char stop_action_coast[] = "coast";
  745.  
  746.   // Power will be removed from the motor and a passive electrical load will
  747.   // be placed on the motor. This is usually done by shorting the motor terminals
  748.   // together. This load will absorb the energy from the rotation of the motors and
  749.   // cause the motor to stop more quickly than coasting.
  750.   static constexpr char stop_action_brake[] = "brake";
  751.  
  752.   // Does not remove power from the motor. Instead it actively try to hold the motor
  753.   // at the current position. If an external force tries to turn the motor, the motor
  754.   // will `push back` to maintain its position.
  755.   static constexpr char stop_action_hold[] = "hold";
  756.  
  757.  
  758. //~autogen
  759.  
  760. //~autogen generic-get-set classes.motor>currentClass
  761.  
  762.   // Address: read-only
  763.   // Returns the name of the port that this motor is connected to.
  764.   std::string address() const { return get_attr_string("address"); }
  765.  
  766.   // Command: write-only
  767.   // Sends a command to the motor controller. See `commands` for a list of
  768.   // possible values.
  769.   auto set_command(std::string v) -> decltype(*this) {
  770.     set_attr_string("command", v);
  771.     return *this;
  772.   }
  773.  
  774.   // Commands: read-only
  775.   // Returns a list of commands that are supported by the motor
  776.   // controller. Possible values are `run-forever`, `run-to-abs-pos`, `run-to-rel-pos`,
  777.   // `run-timed`, `run-direct`, `stop` and `reset`. Not all commands may be supported.
  778.   //
  779.   // - `run-forever` will cause the motor to run until another command is sent.
  780.   // - `run-to-abs-pos` will run to an absolute position specified by `position_sp`
  781.   //   and then stop using the action specified in `stop_action`.
  782.   // - `run-to-rel-pos` will run to a position relative to the current `position` value.
  783.   //   The new position will be current `position` + `position_sp`. When the new
  784.   //   position is reached, the motor will stop using the action specified by `stop_action`.
  785.   // - `run-timed` will run the motor for the amount of time specified in `time_sp`
  786.   //   and then stop the motor using the action specified by `stop_action`.
  787.   // - `run-direct` will run the motor at the duty cycle specified by `duty_cycle_sp`.
  788.   //   Unlike other run commands, changing `duty_cycle_sp` while running *will*
  789.   //   take effect immediately.
  790.   // - `stop` will stop any of the run commands before they are complete using the
  791.   //   action specified by `stop_action`.
  792.   // - `reset` will reset all of the motor parameter attributes to their default value.
  793.   //   This will also have the effect of stopping the motor.
  794.   mode_set commands() const { return get_attr_set("commands"); }
  795.  
  796.   // Count Per Rot: read-only
  797.   // Returns the number of tacho counts in one rotation of the motor. Tacho counts
  798.   // are used by the position and speed attributes, so you can use this value
  799.   // to convert rotations or degrees to tacho counts. (rotation motors only)
  800.   int count_per_rot() const { return get_attr_int("count_per_rot"); }
  801.  
  802.   // Count Per M: read-only
  803.   // Returns the number of tacho counts in one meter of travel of the motor. Tacho
  804.   // counts are used by the position and speed attributes, so you can use this
  805.   // value to convert from distance to tacho counts. (linear motors only)
  806.   int count_per_m() const { return get_attr_int("count_per_m"); }
  807.  
  808.   // Driver Name: read-only
  809.   // Returns the name of the driver that provides this tacho motor device.
  810.   std::string driver_name() const { return get_attr_string("driver_name"); }
  811.  
  812.   // Duty Cycle: read-only
  813.   // Returns the current duty cycle of the motor. Units are percent. Values
  814.   // are -100 to 100.
  815.   int duty_cycle() const { return get_attr_int("duty_cycle"); }
  816.  
  817.   // Duty Cycle SP: read/write
  818.   // Writing sets the duty cycle setpoint. Reading returns the current value.
  819.   // Units are in percent. Valid values are -100 to 100. A negative value causes
  820.   // the motor to rotate in reverse.
  821.   int duty_cycle_sp() const { return get_attr_int("duty_cycle_sp"); }
  822.   auto set_duty_cycle_sp(int v) -> decltype(*this) {
  823.     set_attr_int("duty_cycle_sp", v);
  824.     return *this;
  825.   }
  826.  
  827.   // Full Travel Count: read-only
  828.   // Returns the number of tacho counts in the full travel of the motor. When
  829.   // combined with the `count_per_m` atribute, you can use this value to
  830.   // calculate the maximum travel distance of the motor. (linear motors only)
  831.   int full_travel_count() const { return get_attr_int("full_travel_count"); }
  832.  
  833.   // Polarity: read/write
  834.   // Sets the polarity of the motor. With `normal` polarity, a positive duty
  835.   // cycle will cause the motor to rotate clockwise. With `inversed` polarity,
  836.   // a positive duty cycle will cause the motor to rotate counter-clockwise.
  837.   // Valid values are `normal` and `inversed`.
  838.   std::string polarity() const { return get_attr_string("polarity"); }
  839.   auto set_polarity(std::string v) -> decltype(*this) {
  840.     set_attr_string("polarity", v);
  841.     return *this;
  842.   }
  843.  
  844.   // Position: read/write
  845.   // Returns the current position of the motor in pulses of the rotary
  846.   // encoder. When the motor rotates clockwise, the position will increase.
  847.   // Likewise, rotating counter-clockwise causes the position to decrease.
  848.   // Writing will set the position to that value.
  849.   int position() const { return get_attr_int("position"); }
  850.   auto set_position(int v) -> decltype(*this) {
  851.     set_attr_int("position", v);
  852.     return *this;
  853.   }
  854.  
  855.   // Position P: read/write
  856.   // The proportional constant for the position PID.
  857.   int position_p() const { return get_attr_int("hold_pid/Kp"); }
  858.   auto set_position_p(int v) -> decltype(*this) {
  859.     set_attr_int("hold_pid/Kp", v);
  860.     return *this;
  861.   }
  862.  
  863.   // Position I: read/write
  864.   // The integral constant for the position PID.
  865.   int position_i() const { return get_attr_int("hold_pid/Ki"); }
  866.   auto set_position_i(int v) -> decltype(*this) {
  867.     set_attr_int("hold_pid/Ki", v);
  868.     return *this;
  869.   }
  870.  
  871.   // Position D: read/write
  872.   // The derivative constant for the position PID.
  873.   int position_d() const { return get_attr_int("hold_pid/Kd"); }
  874.   auto set_position_d(int v) -> decltype(*this) {
  875.     set_attr_int("hold_pid/Kd", v);
  876.     return *this;
  877.   }
  878.  
  879.   // Position SP: read/write
  880.   // Writing specifies the target position for the `run-to-abs-pos` and `run-to-rel-pos`
  881.   // commands. Reading returns the current value. Units are in tacho counts. You
  882.   // can use the value returned by `counts_per_rot` to convert tacho counts to/from
  883.   // rotations or degrees.
  884.   int position_sp() const { return get_attr_int("position_sp"); }
  885.   auto set_position_sp(int v) -> decltype(*this) {
  886.     set_attr_int("position_sp", v);
  887.     return *this;
  888.   }
  889.  
  890.   // Max Speed: read-only
  891.   // Returns the maximum value that is accepted by the `speed_sp` attribute. This
  892.   // may be slightly different than the maximum speed that a particular motor can
  893.   // reach - it's the maximum theoretical speed.
  894.   int max_speed() const { return get_attr_int("max_speed"); }
  895.  
  896.   // Speed: read-only
  897.   // Returns the current motor speed in tacho counts per second. Note, this is
  898.   // not necessarily degrees (although it is for LEGO motors). Use the `count_per_rot`
  899.   // attribute to convert this value to RPM or deg/sec.
  900.   int speed() const { return get_attr_int("speed"); }
  901.  
  902.   // Speed SP: read/write
  903.   // Writing sets the target speed in tacho counts per second used for all `run-*`
  904.   // commands except `run-direct`. Reading returns the current value. A negative
  905.   // value causes the motor to rotate in reverse with the exception of `run-to-*-pos`
  906.   // commands where the sign is ignored. Use the `count_per_rot` attribute to convert
  907.   // RPM or deg/sec to tacho counts per second. Use the `count_per_m` attribute to
  908.   // convert m/s to tacho counts per second.
  909.   int speed_sp() const { return get_attr_int("speed_sp"); }
  910.   auto set_speed_sp(int v) -> decltype(*this) {
  911.     set_attr_int("speed_sp", v);
  912.     return *this;
  913.   }
  914.  
  915.   // Ramp Up SP: read/write
  916.   // Writing sets the ramp up setpoint. Reading returns the current value. Units
  917.   // are in milliseconds and must be positive. When set to a non-zero value, the
  918.   // motor speed will increase from 0 to 100% of `max_speed` over the span of this
  919.   // setpoint. The actual ramp time is the ratio of the difference between the
  920.   // `speed_sp` and the current `speed` and max_speed multiplied by `ramp_up_sp`.
  921.   int ramp_up_sp() const { return get_attr_int("ramp_up_sp"); }
  922.   auto set_ramp_up_sp(int v) -> decltype(*this) {
  923.     set_attr_int("ramp_up_sp", v);
  924.     return *this;
  925.   }
  926.  
  927.   // Ramp Down SP: read/write
  928.   // Writing sets the ramp down setpoint. Reading returns the current value. Units
  929.   // are in milliseconds and must be positive. When set to a non-zero value, the
  930.   // motor speed will decrease from 0 to 100% of `max_speed` over the span of this
  931.   // setpoint. The actual ramp time is the ratio of the difference between the
  932.   // `speed_sp` and the current `speed` and max_speed multiplied by `ramp_down_sp`.
  933.   int ramp_down_sp() const { return get_attr_int("ramp_down_sp"); }
  934.   auto set_ramp_down_sp(int v) -> decltype(*this) {
  935.     set_attr_int("ramp_down_sp", v);
  936.     return *this;
  937.   }
  938.  
  939.   // Speed P: read/write
  940.   // The proportional constant for the speed regulation PID.
  941.   int speed_p() const { return get_attr_int("speed_pid/Kp"); }
  942.   auto set_speed_p(int v) -> decltype(*this) {
  943.     set_attr_int("speed_pid/Kp", v);
  944.     return *this;
  945.   }
  946.  
  947.   // Speed I: read/write
  948.   // The integral constant for the speed regulation PID.
  949.   int speed_i() const { return get_attr_int("speed_pid/Ki"); }
  950.   auto set_speed_i(int v) -> decltype(*this) {
  951.     set_attr_int("speed_pid/Ki", v);
  952.     return *this;
  953.   }
  954.  
  955.   // Speed D: read/write
  956.   // The derivative constant for the speed regulation PID.
  957.   int speed_d() const { return get_attr_int("speed_pid/Kd"); }
  958.   auto set_speed_d(int v) -> decltype(*this) {
  959.     set_attr_int("speed_pid/Kd", v);
  960.     return *this;
  961.   }
  962.  
  963.   // State: read-only
  964.   // Reading returns a list of state flags. Possible flags are
  965.   // `running`, `ramping`, `holding`, `overloaded` and `stalled`.
  966.   mode_set state() const { return get_attr_set("state"); }
  967.  
  968.   // Stop Action: read/write
  969.   // Reading returns the current stop action. Writing sets the stop action.
  970.   // The value determines the motors behavior when `command` is set to `stop`.
  971.   // Also, it determines the motors behavior when a run command completes. See
  972.   // `stop_actions` for a list of possible values.
  973.   std::string stop_action() const { return get_attr_string("stop_action"); }
  974.   auto set_stop_action(std::string v) -> decltype(*this) {
  975.     set_attr_string("stop_action", v);
  976.     return *this;
  977.   }
  978.  
  979.   // Stop Actions: read-only
  980.   // Returns a list of stop actions supported by the motor controller.
  981.   // Possible values are `coast`, `brake` and `hold`. `coast` means that power will
  982.   // be removed from the motor and it will freely coast to a stop. `brake` means
  983.   // that power will be removed from the motor and a passive electrical load will
  984.   // be placed on the motor. This is usually done by shorting the motor terminals
  985.   // together. This load will absorb the energy from the rotation of the motors and
  986.   // cause the motor to stop more quickly than coasting. `hold` does not remove
  987.   // power from the motor. Instead it actively tries to hold the motor at the current
  988.   // position. If an external force tries to turn the motor, the motor will 'push
  989.   // back' to maintain its position.
  990.   mode_set stop_actions() const { return get_attr_set("stop_actions"); }
  991.  
  992.   // Time SP: read/write
  993.   // Writing specifies the amount of time the motor will run when using the
  994.   // `run-timed` command. Reading returns the current value. Units are in
  995.   // milliseconds.
  996.   int time_sp() const { return get_attr_int("time_sp"); }
  997.   auto set_time_sp(int v) -> decltype(*this) {
  998.     set_attr_int("time_sp", v);
  999.     return *this;
  1000.   }
  1001.  
  1002.  
  1003. //~autogen
  1004.  
  1005. //~autogen motor_commands classes.motor>currentClass
  1006.  
  1007.     // Run the motor until another command is sent.
  1008.     void run_forever() { set_command("run-forever"); }
  1009.  
  1010.     // Run to an absolute position specified by `position_sp` and then
  1011.     // stop using the action specified in `stop_action`.
  1012.     void run_to_abs_pos() { set_command("run-to-abs-pos"); }
  1013.  
  1014.     // Run to a position relative to the current `position` value.
  1015.     // The new position will be current `position` + `position_sp`.
  1016.     // When the new position is reached, the motor will stop using
  1017.     // the action specified by `stop_action`.
  1018.     void run_to_rel_pos() { set_command("run-to-rel-pos"); }
  1019.  
  1020.     // Run the motor for the amount of time specified in `time_sp`
  1021.     // and then stop the motor using the action specified by `stop_action`.
  1022.     void run_timed() { set_command("run-timed"); }
  1023.  
  1024.     // Run the motor at the duty cycle specified by `duty_cycle_sp`.
  1025.     // Unlike other run commands, changing `duty_cycle_sp` while running *will*
  1026.     // take effect immediately.
  1027.     void run_direct() { set_command("run-direct"); }
  1028.  
  1029.     // Stop any of the run commands before they are complete using the
  1030.     // action specified by `stop_action`.
  1031.     void stop() { set_command("stop"); }
  1032.  
  1033.     // Reset all of the motor parameter attributes to their default value.
  1034.     // This will also have the effect of stopping the motor.
  1035.     void reset() { set_command("reset"); }
  1036.  
  1037.  
  1038. //~autogen
  1039.  
  1040. protected:
  1041.   motor() {}
  1042.  
  1043.   bool connect(const std::map<std::string, std::set<std::string>>&) noexcept;
  1044. };
  1045.  
  1046. //-----------------------------------------------------------------------------
  1047.  
  1048. // EV3 medium motor
  1049. class medium_motor : public motor
  1050. {
  1051. public:
  1052.   medium_motor(address_type address = OUTPUT_AUTO);
  1053. };
  1054.  
  1055. //-----------------------------------------------------------------------------
  1056.  
  1057. // EV3 large motor
  1058. class large_motor : public motor
  1059. {
  1060. public:
  1061.   large_motor(address_type address = OUTPUT_AUTO);
  1062. };
  1063.  
  1064. //-----------------------------------------------------------------------------
  1065.  
  1066. //~autogen generic-class-description classes.dcMotor>currentClass
  1067.  
  1068. // The DC motor class provides a uniform interface for using regular DC motors
  1069. // with no fancy controls or feedback. This includes LEGO MINDSTORMS RCX motors
  1070. // and LEGO Power Functions motors.
  1071.  
  1072. //~autogen
  1073. class dc_motor : protected device
  1074. {
  1075. public:
  1076.   dc_motor(address_type address = OUTPUT_AUTO);
  1077.  
  1078.   using device::connected;
  1079.   using device::device_index;
  1080.  
  1081. //~autogen generic-declare-property-value classes.dcMotor>currentClass
  1082.  
  1083.   // Run the motor until another command is sent.
  1084.   static constexpr char command_run_forever[] = "run-forever";
  1085.  
  1086.   // Run the motor for the amount of time specified in `time_sp`
  1087.   // and then stop the motor using the action specified by `stop_action`.
  1088.   static constexpr char command_run_timed[] = "run-timed";
  1089.  
  1090.   // Run the motor at the duty cycle specified by `duty_cycle_sp`.
  1091.   // Unlike other run commands, changing `duty_cycle_sp` while running *will*
  1092.   // take effect immediately.
  1093.   static constexpr char command_run_direct[] = "run-direct";
  1094.  
  1095.   // Stop any of the run commands before they are complete using the
  1096.   // action specified by `stop_action`.
  1097.   static constexpr char command_stop[] = "stop";
  1098.  
  1099.   // With `normal` polarity, a positive duty cycle will
  1100.   // cause the motor to rotate clockwise.
  1101.   static constexpr char polarity_normal[] = "normal";
  1102.  
  1103.   // With `inversed` polarity, a positive duty cycle will
  1104.   // cause the motor to rotate counter-clockwise.
  1105.   static constexpr char polarity_inversed[] = "inversed";
  1106.  
  1107.   // Power will be removed from the motor and it will freely coast to a stop.
  1108.   static constexpr char stop_action_coast[] = "coast";
  1109.  
  1110.   // Power will be removed from the motor and a passive electrical load will
  1111.   // be placed on the motor. This is usually done by shorting the motor terminals
  1112.   // together. This load will absorb the energy from the rotation of the motors and
  1113.   // cause the motor to stop more quickly than coasting.
  1114.   static constexpr char stop_action_brake[] = "brake";
  1115.  
  1116.  
  1117. //~autogen
  1118.  
  1119. //~autogen generic-get-set classes.dcMotor>currentClass
  1120.  
  1121.   // Address: read-only
  1122.   // Returns the name of the port that this motor is connected to.
  1123.   std::string address() const { return get_attr_string("address"); }
  1124.  
  1125.   // Command: write-only
  1126.   // Sets the command for the motor. Possible values are `run-forever`, `run-timed` and
  1127.   // `stop`. Not all commands may be supported, so be sure to check the contents
  1128.   // of the `commands` attribute.
  1129.   auto set_command(std::string v) -> decltype(*this) {
  1130.     set_attr_string("command", v);
  1131.     return *this;
  1132.   }
  1133.  
  1134.   // Commands: read-only
  1135.   // Returns a list of commands supported by the motor
  1136.   // controller.
  1137.   mode_set commands() const { return get_attr_set("commands"); }
  1138.  
  1139.   // Driver Name: read-only
  1140.   // Returns the name of the motor driver that loaded this device. See the list
  1141.   // of [supported devices] for a list of drivers.
  1142.   std::string driver_name() const { return get_attr_string("driver_name"); }
  1143.  
  1144.   // Duty Cycle: read-only
  1145.   // Shows the current duty cycle of the PWM signal sent to the motor. Values
  1146.   // are -100 to 100 (-100% to 100%).
  1147.   int duty_cycle() const { return get_attr_int("duty_cycle"); }
  1148.  
  1149.   // Duty Cycle SP: read/write
  1150.   // Writing sets the duty cycle setpoint of the PWM signal sent to the motor.
  1151.   // Valid values are -100 to 100 (-100% to 100%). Reading returns the current
  1152.   // setpoint.
  1153.   int duty_cycle_sp() const { return get_attr_int("duty_cycle_sp"); }
  1154.   auto set_duty_cycle_sp(int v) -> decltype(*this) {
  1155.     set_attr_int("duty_cycle_sp", v);
  1156.     return *this;
  1157.   }
  1158.  
  1159.   // Polarity: read/write
  1160.   // Sets the polarity of the motor. Valid values are `normal` and `inversed`.
  1161.   std::string polarity() const { return get_attr_string("polarity"); }
  1162.   auto set_polarity(std::string v) -> decltype(*this) {
  1163.     set_attr_string("polarity", v);
  1164.     return *this;
  1165.   }
  1166.  
  1167.   // Ramp Down SP: read/write
  1168.   // Sets the time in milliseconds that it take the motor to ramp down from 100%
  1169.   // to 0%. Valid values are 0 to 10000 (10 seconds). Default is 0.
  1170.   int ramp_down_sp() const { return get_attr_int("ramp_down_sp"); }
  1171.   auto set_ramp_down_sp(int v) -> decltype(*this) {
  1172.     set_attr_int("ramp_down_sp", v);
  1173.     return *this;
  1174.   }
  1175.  
  1176.   // Ramp Up SP: read/write
  1177.   // Sets the time in milliseconds that it take the motor to up ramp from 0% to
  1178.   // 100%. Valid values are 0 to 10000 (10 seconds). Default is 0.
  1179.   int ramp_up_sp() const { return get_attr_int("ramp_up_sp"); }
  1180.   auto set_ramp_up_sp(int v) -> decltype(*this) {
  1181.     set_attr_int("ramp_up_sp", v);
  1182.     return *this;
  1183.   }
  1184.  
  1185.   // State: read-only
  1186.   // Gets a list of flags indicating the motor status. Possible
  1187.   // flags are `running` and `ramping`. `running` indicates that the motor is
  1188.   // powered. `ramping` indicates that the motor has not yet reached the
  1189.   // `duty_cycle_sp`.
  1190.   mode_set state() const { return get_attr_set("state"); }
  1191.  
  1192.   // Stop Action: write-only
  1193.   // Sets the stop action that will be used when the motor stops. Read
  1194.   // `stop_actions` to get the list of valid values.
  1195.   auto set_stop_action(std::string v) -> decltype(*this) {
  1196.     set_attr_string("stop_action", v);
  1197.     return *this;
  1198.   }
  1199.  
  1200.   // Stop Actions: read-only
  1201.   // Gets a list of stop actions. Valid values are `coast`
  1202.   // and `brake`.
  1203.   mode_set stop_actions() const { return get_attr_set("stop_actions"); }
  1204.  
  1205.   // Time SP: read/write
  1206.   // Writing specifies the amount of time the motor will run when using the
  1207.   // `run-timed` command. Reading returns the current value. Units are in
  1208.   // milliseconds.
  1209.   int time_sp() const { return get_attr_int("time_sp"); }
  1210.   auto set_time_sp(int v) -> decltype(*this) {
  1211.     set_attr_int("time_sp", v);
  1212.     return *this;
  1213.   }
  1214.  
  1215.  
  1216. //~autogen
  1217.  
  1218. //~autogen motor_commands classes.dcMotor>currentClass
  1219.  
  1220.     // Run the motor until another command is sent.
  1221.     void run_forever() { set_command("run-forever"); }
  1222.  
  1223.     // Run the motor for the amount of time specified in `time_sp`
  1224.     // and then stop the motor using the action specified by `stop_action`.
  1225.     void run_timed() { set_command("run-timed"); }
  1226.  
  1227.     // Run the motor at the duty cycle specified by `duty_cycle_sp`.
  1228.     // Unlike other run commands, changing `duty_cycle_sp` while running *will*
  1229.     // take effect immediately.
  1230.     void run_direct() { set_command("run-direct"); }
  1231.  
  1232.     // Stop any of the run commands before they are complete using the
  1233.     // action specified by `stop_action`.
  1234.     void stop() { set_command("stop"); }
  1235.  
  1236.  
  1237. //~autogen
  1238.  
  1239. protected:
  1240.   std::string _port_name;
  1241. };
  1242.  
  1243. //-----------------------------------------------------------------------------
  1244.  
  1245. //~autogen generic-class-description classes.servoMotor>currentClass
  1246.  
  1247. // The servo motor class provides a uniform interface for using hobby type
  1248. // servo motors.
  1249.  
  1250. //~autogen
  1251. class servo_motor : protected device
  1252. {
  1253. public:
  1254.   servo_motor(address_type address = OUTPUT_AUTO);
  1255.  
  1256.   using device::connected;
  1257.   using device::device_index;
  1258.  
  1259. //~autogen generic-declare-property-value classes.servoMotor>currentClass
  1260.  
  1261.   // Drive servo to the position set in the `position_sp` attribute.
  1262.   static constexpr char command_run[] = "run";
  1263.  
  1264.   // Remove power from the motor.
  1265.   static constexpr char command_float[] = "float";
  1266.  
  1267.   // With `normal` polarity, a positive duty cycle will
  1268.   // cause the motor to rotate clockwise.
  1269.   static constexpr char polarity_normal[] = "normal";
  1270.  
  1271.   // With `inversed` polarity, a positive duty cycle will
  1272.   // cause the motor to rotate counter-clockwise.
  1273.   static constexpr char polarity_inversed[] = "inversed";
  1274.  
  1275.  
  1276. //~autogen
  1277.  
  1278. //~autogen generic-get-set classes.servoMotor>currentClass
  1279.  
  1280.   // Address: read-only
  1281.   // Returns the name of the port that this motor is connected to.
  1282.   std::string address() const { return get_attr_string("address"); }
  1283.  
  1284.   // Command: write-only
  1285.   // Sets the command for the servo. Valid values are `run` and `float`. Setting
  1286.   // to `run` will cause the servo to be driven to the position_sp set in the
  1287.   // `position_sp` attribute. Setting to `float` will remove power from the motor.
  1288.   auto set_command(std::string v) -> decltype(*this) {
  1289.     set_attr_string("command", v);
  1290.     return *this;
  1291.   }
  1292.  
  1293.   // Driver Name: read-only
  1294.   // Returns the name of the motor driver that loaded this device. See the list
  1295.   // of [supported devices] for a list of drivers.
  1296.   std::string driver_name() const { return get_attr_string("driver_name"); }
  1297.  
  1298.   // Max Pulse SP: read/write
  1299.   // Used to set the pulse size in milliseconds for the signal that tells the
  1300.   // servo to drive to the maximum (clockwise) position_sp. Default value is 2400.
  1301.   // Valid values are 2300 to 2700. You must write to the position_sp attribute for
  1302.   // changes to this attribute to take effect.
  1303.   int max_pulse_sp() const { return get_attr_int("max_pulse_sp"); }
  1304.   auto set_max_pulse_sp(int v) -> decltype(*this) {
  1305.     set_attr_int("max_pulse_sp", v);
  1306.     return *this;
  1307.   }
  1308.  
  1309.   // Mid Pulse SP: read/write
  1310.   // Used to set the pulse size in milliseconds for the signal that tells the
  1311.   // servo to drive to the mid position_sp. Default value is 1500. Valid
  1312.   // values are 1300 to 1700. For example, on a 180 degree servo, this would be
  1313.   // 90 degrees. On continuous rotation servo, this is the 'neutral' position_sp
  1314.   // where the motor does not turn. You must write to the position_sp attribute for
  1315.   // changes to this attribute to take effect.
  1316.   int mid_pulse_sp() const { return get_attr_int("mid_pulse_sp"); }
  1317.   auto set_mid_pulse_sp(int v) -> decltype(*this) {
  1318.     set_attr_int("mid_pulse_sp", v);
  1319.     return *this;
  1320.   }
  1321.  
  1322.   // Min Pulse SP: read/write
  1323.   // Used to set the pulse size in milliseconds for the signal that tells the
  1324.   // servo to drive to the miniumum (counter-clockwise) position_sp. Default value
  1325.   // is 600. Valid values are 300 to 700. You must write to the position_sp
  1326.   // attribute for changes to this attribute to take effect.
  1327.   int min_pulse_sp() const { return get_attr_int("min_pulse_sp"); }
  1328.   auto set_min_pulse_sp(int v) -> decltype(*this) {
  1329.     set_attr_int("min_pulse_sp", v);
  1330.     return *this;
  1331.   }
  1332.  
  1333.   // Polarity: read/write
  1334.   // Sets the polarity of the servo. Valid values are `normal` and `inversed`.
  1335.   // Setting the value to `inversed` will cause the position_sp value to be
  1336.   // inversed. i.e `-100` will correspond to `max_pulse_sp`, and `100` will
  1337.   // correspond to `min_pulse_sp`.
  1338.   std::string polarity() const { return get_attr_string("polarity"); }
  1339.   auto set_polarity(std::string v) -> decltype(*this) {
  1340.     set_attr_string("polarity", v);
  1341.     return *this;
  1342.   }
  1343.  
  1344.   // Position SP: read/write
  1345.   // Reading returns the current position_sp of the servo. Writing instructs the
  1346.   // servo to move to the specified position_sp. Units are percent. Valid values
  1347.   // are -100 to 100 (-100% to 100%) where `-100` corresponds to `min_pulse_sp`,
  1348.   // `0` corresponds to `mid_pulse_sp` and `100` corresponds to `max_pulse_sp`.
  1349.   int position_sp() const { return get_attr_int("position_sp"); }
  1350.   auto set_position_sp(int v) -> decltype(*this) {
  1351.     set_attr_int("position_sp", v);
  1352.     return *this;
  1353.   }
  1354.  
  1355.   // Rate SP: read/write
  1356.   // Sets the rate_sp at which the servo travels from 0 to 100.0% (half of the full
  1357.   // range of the servo). Units are in milliseconds. Example: Setting the rate_sp
  1358.   // to 1000 means that it will take a 180 degree servo 2 second to move from 0
  1359.   // to 180 degrees. Note: Some servo controllers may not support this in which
  1360.   // case reading and writing will fail with `-EOPNOTSUPP`. In continuous rotation
  1361.   // servos, this value will affect the rate_sp at which the speed ramps up or down.
  1362.   int rate_sp() const { return get_attr_int("rate_sp"); }
  1363.   auto set_rate_sp(int v) -> decltype(*this) {
  1364.     set_attr_int("rate_sp", v);
  1365.     return *this;
  1366.   }
  1367.  
  1368.   // State: read-only
  1369.   // Returns a list of flags indicating the state of the servo.
  1370.   // Possible values are:
  1371.   // * `running`: Indicates that the motor is powered.
  1372.   mode_set state() const { return get_attr_set("state"); }
  1373.  
  1374.  
  1375. //~autogen
  1376.  
  1377. //~autogen motor_commands classes.servoMotor>currentClass
  1378.  
  1379.     // Drive servo to the position set in the `position_sp` attribute.
  1380.     void run() { set_command("run"); }
  1381.  
  1382.     // Remove power from the motor.
  1383.     void float_() { set_command("float"); }
  1384.  
  1385.  
  1386. //~autogen
  1387. };
  1388.  
  1389. //-----------------------------------------------------------------------------
  1390.  
  1391. //~autogen generic-class-description classes.led>currentClass
  1392.  
  1393. // Any device controlled by the generic LED driver.
  1394. // See https://www.kernel.org/doc/Documentation/leds/leds-class.txt
  1395. // for more details.
  1396.  
  1397. //~autogen
  1398. class led : protected device
  1399. {
  1400. public:
  1401.   led(std::string name);
  1402.  
  1403.   using device::connected;
  1404.  
  1405. //~autogen generic-get-set classes.led>currentClass
  1406.  
  1407.   // Max Brightness: read-only
  1408.   // Returns the maximum allowable brightness value.
  1409.   int max_brightness() const { return get_attr_int("max_brightness"); }
  1410.  
  1411.   // Brightness: read/write
  1412.   // Sets the brightness level. Possible values are from 0 to `max_brightness`.
  1413.   int brightness() const { return get_attr_int("brightness"); }
  1414.   auto set_brightness(int v) -> decltype(*this) {
  1415.     set_attr_int("brightness", v);
  1416.     return *this;
  1417.   }
  1418.  
  1419.   // Triggers: read-only
  1420.   // Returns a list of available triggers.
  1421.   mode_set triggers() const { return get_attr_set("trigger"); }
  1422.  
  1423.   // Trigger: read/write
  1424.   // Sets the led trigger. A trigger
  1425.   // is a kernel based source of led events. Triggers can either be simple or
  1426.   // complex. A simple trigger isn't configurable and is designed to slot into
  1427.   // existing subsystems with minimal additional code. Examples are the `ide-disk` and
  1428.   // `nand-disk` triggers.
  1429.   //
  1430.   // Complex triggers whilst available to all LEDs have LED specific
  1431.   // parameters and work on a per LED basis. The `timer` trigger is an example.
  1432.   // The `timer` trigger will periodically change the LED brightness between
  1433.   // 0 and the current brightness setting. The `on` and `off` time can
  1434.   // be specified via `delay_{on,off}` attributes in milliseconds.
  1435.   // You can change the brightness value of a LED independently of the timer
  1436.   // trigger. However, if you set the brightness value to 0 it will
  1437.   // also disable the `timer` trigger.
  1438.   std::string trigger() const { return get_attr_from_set("trigger"); }
  1439.   auto set_trigger(std::string v) -> decltype(*this) {
  1440.     set_attr_string("trigger", v);
  1441.     return *this;
  1442.   }
  1443.  
  1444.   // Delay On: read/write
  1445.   // The `timer` trigger will periodically change the LED brightness between
  1446.   // 0 and the current brightness setting. The `on` time can
  1447.   // be specified via `delay_on` attribute in milliseconds.
  1448.   int delay_on() const { return get_attr_int("delay_on"); }
  1449.   auto set_delay_on(int v) -> decltype(*this) {
  1450.     set_attr_int("delay_on", v);
  1451.     return *this;
  1452.   }
  1453.  
  1454.   // Delay Off: read/write
  1455.   // The `timer` trigger will periodically change the LED brightness between
  1456.   // 0 and the current brightness setting. The `off` time can
  1457.   // be specified via `delay_off` attribute in milliseconds.
  1458.   int delay_off() const { return get_attr_int("delay_off"); }
  1459.   auto set_delay_off(int v) -> decltype(*this) {
  1460.     set_attr_int("delay_off", v);
  1461.     return *this;
  1462.   }
  1463.  
  1464.  
  1465. //~autogen
  1466.  
  1467.   // Gets the LED's brightness as a percentage (0-1) of the maximum.
  1468.   float brightness_pct() const {
  1469.     return static_cast<float>(brightness()) / max_brightness();
  1470.   }
  1471.  
  1472.   // Sets the LED's brightness as a percentage (0-1) of the maximum.
  1473.   auto set_brightness_pct(float v) -> decltype(*this) {
  1474.     return set_brightness(v * max_brightness());
  1475.   }
  1476.  
  1477.   // Turns the led on by setting its brightness to the maximum level.
  1478.   void on()  { set_brightness(max_brightness()); }
  1479.  
  1480.   // Turns the led off.
  1481.   void off() { set_brightness(0); }
  1482.  
  1483.   // Enables timer trigger and sets delay_on and delay_off attributes to the
  1484.   // provided values (in milliseconds).
  1485.   void flash(unsigned on_ms, unsigned off_ms);
  1486.  
  1487. #if defined(EV3DEV_PLATFORM_BRICKPI)
  1488. //~autogen leds-declare platforms.brickpi.led>currentClass
  1489.  
  1490.     static led blue_led1;
  1491.     static led blue_led2;
  1492.  
  1493.     static std::vector<led*> led1;
  1494.     static std::vector<led*> led2;
  1495.  
  1496.     static std::vector<float> black;
  1497.     static std::vector<float> blue;
  1498.  
  1499. //~autogen
  1500. #elif defined(EV3DEV_PLATFORM_PISTORMS)
  1501. //~autogen leds-declare platforms.pistorms.led>currentClass
  1502.  
  1503.     static led red_left;
  1504.     static led red_right;
  1505.     static led green_left;
  1506.     static led green_right;
  1507.     static led blue_left;
  1508.     static led blue_right;
  1509.  
  1510.     static std::vector<led*> left;
  1511.     static std::vector<led*> right;
  1512.  
  1513.     static std::vector<float> black;
  1514.     static std::vector<float> red;
  1515.     static std::vector<float> green;
  1516.     static std::vector<float> blue;
  1517.     static std::vector<float> yellow;
  1518.     static std::vector<float> purple;
  1519.     static std::vector<float> cyan;
  1520.     static std::vector<float> white;
  1521.     static std::vector<float> orange;
  1522.  
  1523. //~autogen
  1524. #else
  1525. //~autogen leds-declare platforms.ev3.led>currentClass
  1526.  
  1527.     static led red_left;
  1528.     static led red_right;
  1529.     static led green_left;
  1530.     static led green_right;
  1531.  
  1532.     static std::vector<led*> left;
  1533.     static std::vector<led*> right;
  1534.  
  1535.     static std::vector<float> black;
  1536.     static std::vector<float> red;
  1537.     static std::vector<float> green;
  1538.     static std::vector<float> amber;
  1539.     static std::vector<float> orange;
  1540.     static std::vector<float> yellow;
  1541.  
  1542. //~autogen
  1543. #endif
  1544.  
  1545.   // Assigns to each led in `group` corresponding brightness percentage from `color`.
  1546.   static void set_color(const std::vector<led*> &group, const std::vector<float> &color);
  1547.  
  1548.   static void all_off();
  1549.  
  1550. protected:
  1551.   int _max_brightness = 0;
  1552. };
  1553.  
  1554. //-----------------------------------------------------------------------------
  1555.  
  1556. //~autogen generic-class-description classes.powerSupply>currentClass
  1557.  
  1558. // A generic interface to read data from the system's power_supply class.
  1559. // Uses the built-in legoev3-battery if none is specified.
  1560.  
  1561. //~autogen
  1562. class power_supply : protected device
  1563. {
  1564. public:
  1565.   power_supply(std::string name);
  1566.  
  1567.   using device::connected;
  1568.  
  1569. //~autogen generic-get-set classes.powerSupply>currentClass
  1570.  
  1571.   // Measured Current: read-only
  1572.   // The measured current that the battery is supplying (in microamps)
  1573.   int measured_current() const { return get_attr_int("current_now"); }
  1574.  
  1575.   // Measured Voltage: read-only
  1576.   // The measured voltage that the battery is supplying (in microvolts)
  1577.   int measured_voltage() const { return get_attr_int("voltage_now"); }
  1578.  
  1579.   // Max Voltage: read-only
  1580.   int max_voltage() const { return get_attr_int("voltage_max_design"); }
  1581.  
  1582.   // Min Voltage: read-only
  1583.   int min_voltage() const { return get_attr_int("voltage_min_design"); }
  1584.  
  1585.   // Technology: read-only
  1586.   std::string technology() const { return get_attr_string("technology"); }
  1587.  
  1588.   // Type: read-only
  1589.   std::string type() const { return get_attr_string("type"); }
  1590.  
  1591.  
  1592. //~autogen
  1593.  
  1594.   float measured_amps()       const { return measured_current() / 1000000.f; }
  1595.   float measured_volts()      const { return measured_voltage() / 1000000.f; }
  1596.  
  1597.   static power_supply battery;
  1598. };
  1599.  
  1600. //-----------------------------------------------------------------------------
  1601.  
  1602. // EV3 buttons
  1603. class button
  1604. {
  1605. public:
  1606.   button(int bit);
  1607.  
  1608.   // Check if the button is pressed.
  1609.   bool pressed() const;
  1610.  
  1611.   // Gets called whenever the button state changes.
  1612.   // The user has to call the process() function to check for state change.
  1613.   std::function<void(bool)> onclick;
  1614.  
  1615.   // Check if the button state has changed,
  1616.   // call onclick function in case it has.
  1617.   // Returns true if the state has changed since the last call.
  1618.   bool process();
  1619.  
  1620.   static button back;
  1621.   static button left;
  1622.   static button right;
  1623.   static button up;
  1624.   static button down;
  1625.   static button enter;
  1626.  
  1627.   // Call process() for each of the EV3 buttons.
  1628.   // Returns true if any of the states have changed since the last call.
  1629.   static bool process_all();
  1630.  
  1631. private:
  1632.   int _bit;
  1633.   bool _state = false;
  1634.   std::vector<unsigned long> _buf;
  1635.  
  1636.   struct file_descriptor {
  1637.     int _fd;
  1638.  
  1639.     file_descriptor(const char *path, int flags);
  1640.     ~file_descriptor();
  1641.     operator int() { return _fd; }
  1642.   };
  1643.  
  1644.   std::shared_ptr<file_descriptor> _fd;
  1645. };
  1646.  
  1647. //-----------------------------------------------------------------------------
  1648.  
  1649. // EV3 Sound
  1650. class sound
  1651. {
  1652. public:
  1653.   static void beep(const std::string &args = "", bool bSynchronous = false);
  1654.   static void tone(float frequency, float ms, bool bSynchronous = false);
  1655.   static void tone(const std::vector< std::vector<float> > &sequence, bool bSynchronous = false);
  1656.   static void play(const std::string &soundfile, bool bSynchronous = false);
  1657.   static void speak(const std::string &text, bool bSynchronous = false);
  1658. };
  1659.  
  1660. //-----------------------------------------------------------------------------
  1661.  
  1662. // EV3 LCD
  1663. class lcd
  1664. {
  1665. public:
  1666.   lcd();
  1667.   ~lcd();
  1668.  
  1669.   bool available() const { return _fb != nullptr; }
  1670.  
  1671.   uint32_t resolution_x()   const { return _xres; }
  1672.   uint32_t resolution_y()   const { return _yres; }
  1673.   uint32_t bits_per_pixel() const { return _bpp; }
  1674.  
  1675.   uint32_t frame_buffer_size() const { return _fbsize; }
  1676.   uint32_t line_length()       const { return _llength; }
  1677.  
  1678.   unsigned char *frame_buffer() { return _fb; }
  1679.  
  1680.   void fill(unsigned char pixel);
  1681.  
  1682. protected:
  1683.   void init();
  1684.   void deinit();
  1685.  
  1686. private:
  1687.   unsigned char *_fb;
  1688.   uint32_t _fbsize;
  1689.   uint32_t _llength;
  1690.   uint32_t _xres;
  1691.   uint32_t _yres;
  1692.   uint32_t _bpp;
  1693. };
  1694.  
  1695. //-----------------------------------------------------------------------------
  1696.  
  1697. // EV3 remote control
  1698. class remote_control
  1699. {
  1700. public:
  1701.   remote_control(unsigned channel = 1);
  1702.   remote_control(infrared_sensor&, unsigned channel = 1);
  1703.   virtual ~remote_control();
  1704.  
  1705.   inline bool   connected() const { return _sensor->connected(); }
  1706.   inline unsigned channel() const { return _channel+1; }
  1707.  
  1708.   bool process();
  1709.  
  1710.   std::function<void (bool)> on_red_up;
  1711.   std::function<void (bool)> on_red_down;
  1712.   std::function<void (bool)> on_blue_up;
  1713.   std::function<void (bool)> on_blue_down;
  1714.   std::function<void (bool)> on_beacon;
  1715.   std::function<void (int)>  on_state_change;
  1716.  
  1717.   enum buttons
  1718.   {
  1719.     red_up    = (1 << 0),
  1720.     red_down  = (1 << 1),
  1721.     blue_up   = (1 << 2),
  1722.     blue_down = (1 << 3),
  1723.     beacon    = (1 << 4),
  1724.   };
  1725.  
  1726. protected:
  1727.   virtual void on_value_changed(int value);
  1728.  
  1729.   infrared_sensor *_sensor = nullptr;
  1730.   bool             _owns_sensor = false;
  1731.   unsigned         _channel = 0;
  1732.   int              _value = 0;
  1733.   int              _state = 0;
  1734. };
  1735.  
  1736. //-----------------------------------------------------------------------------
  1737.  
  1738. //~autogen generic-class-description classes.legoPort>currentClass
  1739.  
  1740. // The `lego-port` class provides an interface for working with input and
  1741. // output ports that are compatible with LEGO MINDSTORMS RCX/NXT/EV3, LEGO
  1742. // WeDo and LEGO Power Functions sensors and motors. Supported devices include
  1743. // the LEGO MINDSTORMS EV3 Intelligent Brick, the LEGO WeDo USB hub and
  1744. // various sensor multiplexers from 3rd party manufacturers.
  1745. //
  1746. // Some types of ports may have multiple modes of operation. For example, the
  1747. // input ports on the EV3 brick can communicate with sensors using UART, I2C
  1748. // or analog validate signals - but not all at the same time. Therefore there
  1749. // are multiple modes available to connect to the different types of sensors.
  1750. //
  1751. // In most cases, ports are able to automatically detect what type of sensor
  1752. // or motor is connected. In some cases though, this must be manually specified
  1753. // using the `mode` and `set_device` attributes. The `mode` attribute affects
  1754. // how the port communicates with the connected device. For example the input
  1755. // ports on the EV3 brick can communicate using UART, I2C or analog voltages,
  1756. // but not all at the same time, so the mode must be set to the one that is
  1757. // appropriate for the connected sensor. The `set_device` attribute is used to
  1758. // specify the exact type of sensor that is connected. Note: the mode must be
  1759. // correctly set before setting the sensor type.
  1760. //
  1761. // Ports can be found at `/sys/class/lego-port/port<N>` where `<N>` is
  1762. // incremented each time a new port is registered. Note: The number is not
  1763. // related to the actual port at all - use the `address` attribute to find
  1764. // a specific port.
  1765.  
  1766. //~autogen
  1767. class lego_port : protected device
  1768. {
  1769. public:
  1770.   lego_port(address_type);
  1771.  
  1772.   using device::connected;
  1773.   using device::device_index;
  1774.  
  1775. //~autogen generic-get-set classes.legoPort>currentClass
  1776.  
  1777.   // Address: read-only
  1778.   // Returns the name of the port. See individual driver documentation for
  1779.   // the name that will be returned.
  1780.   std::string address() const { return get_attr_string("address"); }
  1781.  
  1782.   // Driver Name: read-only
  1783.   // Returns the name of the driver that loaded this device. You can find the
  1784.   // complete list of drivers in the [list of port drivers].
  1785.   std::string driver_name() const { return get_attr_string("driver_name"); }
  1786.  
  1787.   // Modes: read-only
  1788.   // Returns a list of the available modes of the port.
  1789.   mode_set modes() const { return get_attr_set("modes"); }
  1790.  
  1791.   // Mode: read/write
  1792.   // Reading returns the currently selected mode. Writing sets the mode.
  1793.   // Generally speaking when the mode changes any sensor or motor devices
  1794.   // associated with the port will be removed new ones loaded, however this
  1795.   // this will depend on the individual driver implementing this class.
  1796.   std::string mode() const { return get_attr_string("mode"); }
  1797.   auto set_mode(std::string v) -> decltype(*this) {
  1798.     set_attr_string("mode", v);
  1799.     return *this;
  1800.   }
  1801.  
  1802.   // Set Device: write-only
  1803.   // For modes that support it, writing the name of a driver will cause a new
  1804.   // device to be registered for that driver and attached to this port. For
  1805.   // example, since NXT/Analog sensors cannot be auto-detected, you must use
  1806.   // this attribute to load the correct driver. Returns -EOPNOTSUPP if setting a
  1807.   // device is not supported.
  1808.   auto set_set_device(std::string v) -> decltype(*this) {
  1809.     set_attr_string("set_device", v);
  1810.     return *this;
  1811.   }
  1812.  
  1813.   // Status: read-only
  1814.   // In most cases, reading status will return the same value as `mode`. In
  1815.   // cases where there is an `auto` mode additional values may be returned,
  1816.   // such as `no-device` or `error`. See individual port driver documentation
  1817.   // for the full list of possible values.
  1818.   std::string status() const { return get_attr_string("status"); }
  1819.  
  1820.  
  1821. //~autogen
  1822.  
  1823. protected:
  1824.   lego_port() {}
  1825.  
  1826.   bool connect(const std::map<std::string, std::set<std::string>>&) noexcept;
  1827. };
  1828.  
  1829. //-----------------------------------------------------------------------------
  1830.  
  1831. } // namespace ev3dev
  1832.  
  1833. // vim: sw=2