Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add Support for the ADI Expander #245

Merged
merged 70 commits into from Sep 13, 2020
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
1fd691c
Create ext_adi.h
kunwarsahni01 Aug 14, 2020
d57786a
Created vdml_ext_adi.c and ext_adi.hpp
kunwarsahni01 Aug 14, 2020
1fd125a
Create vdml_ext_adi.cpp
kunwarsahni01 Aug 14, 2020
fd578fe
Add smart_port struct
kunwarsahni01 Aug 15, 2020
b8ef153
Remove Port Config Typedef
kunwarsahni01 Aug 15, 2020
cdd6483
Change smart_port variable
kunwarsahni01 Aug 15, 2020
9457cc7
Fixed adi_encoder_t ext_adi_encoder_init
kunwarsahni01 Aug 15, 2020
ae99033
Remove smart_port struct and add get_ports function
kunwarsahni01 Aug 16, 2020
bcf17fb
Implemented get_ports
kunwarsahni01 Aug 16, 2020
a461ede
Removing pointer
kunwarsahni01 Aug 16, 2020
5b9dae2
Working on implementation for get_ports()
kunwarsahni01 Aug 18, 2020
78bbc85
May have found proper solution to the issues with get_ports issue.
WillXuCodes Aug 26, 2020
7e23948
Changed params of gyro to directly reference smart points.
WillXuCodes Aug 26, 2020
6c89e26
(Unfinished) changed a few more params to be include both smart port and
WillXuCodes Aug 27, 2020
65043e1
Fixed get_ports macro scoping issue
WillXuCodes Aug 27, 2020
793157d
Fixed C api compiling errors, current state of cpp file is commented
WillXuCodes Aug 27, 2020
8dcc8d2
Merge pull request #243 from purduesigbots/develop
kunwarsahni01 Aug 29, 2020
b0b1a6a
Fixed warning with unused adi port var, and fixed the smart_ports to be
WillXuCodes Aug 29, 2020
cc06e2e
Revert "Fixed warning with unused adi port var, and fixed the smart_p…
WillXuCodes Aug 29, 2020
fcfc966
Made smart ports be - 1
kunwarsahni01 Aug 30, 2020
877df53
ext gyro fix (we were passing in the adi port instead of the gyro
WillXuCodes Aug 30, 2020
320f2fe
moved ext-adi #define functions into ext_adi.h, the c++ api is good for
mooreBrendan Aug 30, 2020
853428c
Change _port to uint32_t
kunwarsahni01 Aug 30, 2020
c265df5
Fix ultrasonic calls
kunwarsahni01 Aug 30, 2020
1f57bcb
fixed return_ports on ultrasonic_get, needs testing
mooreBrendan Aug 31, 2020
1b0cb14
Update Comments
kunwarsahni01 Sep 3, 2020
df7981b
made adi into wrapper for ext_adi
mooreBrendan Sep 4, 2020
bc9d9d2
Fix Ultrasonic C++ api
kunwarsahni01 Sep 4, 2020
4f59b3b
Combined external adi and internal adi, so it's all one api under the
WillXuCodes Sep 4, 2020
9fa3d95
Deleted old unused hpp/cpp files for the seperate cpp files.
WillXuCodes Sep 4, 2020
5286d03
merged c++ api works with encoders, sonars, buttons, motors, gyros
mooreBrendan Sep 5, 2020
414ca7e
code clean up
mooreBrendan Sep 5, 2020
7df1ce8
documentation clean up
mooreBrendan Sep 6, 2020
919f4ce
made ports in vdml_adi.c from int32_t to uint8_t
mooreBrendan Sep 6, 2020
2366756
removed unnecessary parenthesis
mooreBrendan Sep 6, 2020
6053a6b
fixed docs to accurately reflect function and not just "configure"
mooreBrendan Sep 6, 2020
3646819
reverted version
mooreBrendan Sep 6, 2020
0f68e42
Deleted redundant (For external adi port) comments in adi expander
WillXuCodes Sep 7, 2020
8d80a18
Update include/pros/adi.hpp
mooreBrendan Sep 7, 2020
12f0172
Update include/pros/adi.hpp
mooreBrendan Sep 7, 2020
93ca9ff
Alphabetized api header file, also deleted unnecessary empty lines on
WillXuCodes Sep 7, 2020
aedc307
Added spaces back to multiplyer = 1 to adi gyro default param.
WillXuCodes Sep 7, 2020
6487dc1
fixed ambiguous initializations
mooreBrendan Sep 8, 2020
1e83096
fixed typos in the documentation
mooreBrendan Sep 8, 2020
82af00d
Update src/devices/vdml_adi.cpp
mooreBrendan Sep 9, 2020
0c815d5
Formatting Fix
WillXuCodes Sep 10, 2020
c65d583
Comment Formatting Fix
WillXuCodes Sep 10, 2020
e8bf9d6
Param Formatting Fix
WillXuCodes Sep 10, 2020
4bf8135
Fix Param Formatting
WillXuCodes Sep 10, 2020
b30c154
Comment Fix
WillXuCodes Sep 10, 2020
6e27dda
Changed comment spelling error
WillXuCodes Sep 10, 2020
660e5cd
Update include/pros/adi.hpp
mooreBrendan Sep 11, 2020
b4db9e2
Update include/pros/ext_adi.h
mooreBrendan Sep 11, 2020
f89fdf1
Update src/devices/vdml_adi.cpp
mooreBrendan Sep 11, 2020
8d6ddbe
fixed documentation and formatting
mooreBrendan Sep 11, 2020
11668a1
Fixed formatting
WillXuCodes Sep 11, 2020
f2e2439
Fix Formatting
WillXuCodes Sep 11, 2020
997f116
revert version
WillXuCodes Sep 11, 2020
2ad6900
formatting fixes, documentation cleanup, fixed typos
mooreBrendan Sep 12, 2020
a39bfe4
removed constant function parameters, reset version string
mooreBrendan Sep 12, 2020
bc1695f
reversed the smart port and adi port
mooreBrendan Sep 12, 2020
8267034
removed empty ADIPort constructor
mooreBrendan Sep 12, 2020
066e1df
removed unnecessary type values
mooreBrendan Sep 12, 2020
5a38a5a
moved macros out of public, updated ENXIO warning
mooreBrendan Sep 12, 2020
766ad6b
added explicit to port_pair constructors
mooreBrendan Sep 12, 2020
0ac5b5a
Update include/pros/adi.hpp
mooreBrendan Sep 12, 2020
e980360
corrected encoder to gyro in comments
mooreBrendan Sep 12, 2020
ac9d6b4
fixed collum formating, reverted explicit
mooreBrendan Sep 12, 2020
8442742
Add External ADI Test
kunwarsahni01 Sep 13, 2020
8119101
Format Ext ADI Test
kunwarsahni01 Sep 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions include/api.h
Expand Up @@ -49,6 +49,7 @@

#include "pros/adi.h"
#include "pros/colors.h"
#include "pros/ext_adi.h"
#include "pros/imu.h"
#include "pros/llemu.h"
#include "pros/misc.h"
Expand Down
3 changes: 2 additions & 1 deletion include/pros/adi.h
Expand Up @@ -111,6 +111,7 @@ typedef enum adi_port_config_e {
#endif
#endif

#define INTERNAL_ADI_PORT 22
#define NUM_ADI_PORTS 8

#ifdef __cplusplus
Expand Down Expand Up @@ -327,7 +328,7 @@ int32_t adi_analog_read_calibrated_HR(uint8_t port);
* Gets the digital value (1 or 0) of a port configured as a digital input.
*
* If the port is configured as some other mode, the digital value which
* reflects the current state of the poprt is returned, which may or may not
* reflects the current state of the port is returned, which may or may not
* differ from the currently set value. The return value is undefined for ports
* configured as any mode other than a Digital Input.
*
Expand Down
215 changes: 177 additions & 38 deletions include/pros/adi.hpp
Expand Up @@ -23,6 +23,14 @@
#include <cstdint>

namespace pros {

/** type definition for the pair of smart port and adi port for the basic adi devices */
using ext_adi_port_pair_t = std::pair<std::uint8_t, std::uint8_t>;
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved

/** type definition for the triplet of smart port and two adi ports for the two wire adi devices*/
using ext_adi_port_tuple_t = std::tuple<std::uint8_t, std::uint8_t, std::uint8_t>;


class ADIPort {
public:
/**
Expand All @@ -32,12 +40,27 @@ class ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports
*
* \param port
* \param adi_port
* The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure
* \param type
* The configuration type for the port
*/
ADIPort(std::uint8_t port, adi_port_config_e_t type = E_ADI_TYPE_UNDEFINED);
ADIPort(std::uint8_t adi_port, adi_port_config_e_t type = E_ADI_TYPE_UNDEFINED);

/**
* Configures an ADI port on an adi expander to act as a given sensor type.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
* \param type
* The configuration type for the port
*/
ADIPort(ext_adi_port_pair_t port, adi_port_config_e_t type = E_ADI_TYPE_UNDEFINED);
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved

virtual ~ADIPort(void) = default;
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved

Expand Down Expand Up @@ -82,7 +105,8 @@ class ADIPort {

protected:
ADIPort(void);
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved
std::uint8_t _port;
std::uint8_t _adi_port;
std::uint8_t _smart_port;
};

class ADIAnalogIn : private ADIPort {
Expand All @@ -94,15 +118,29 @@ class ADIAnalogIn : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports
*
* \param port
* \param adi_port
* The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure
* \param type
* The configuration type for the port
*
* \return 1 if the operation was successful or PROS_ERR if the operation
* failed, setting errno.
*/
ADIAnalogIn(std::uint8_t port);
ADIAnalogIn(std::uint8_t adi_port);

/**
* Configures an ADI port on an adi expander to act as an Analog Input.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
*
* \return 1 if the operation was successful or PROS_ERR if the operation
* failed, setting errno.
*/
ADIAnalogIn(ext_adi_port_pair_t port);\

/**
* Calibrates the analog sensor on the specified port and returns the new
Expand Down Expand Up @@ -198,12 +236,23 @@ class ADIAnalogOut : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* \param adi_port
* The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure
* \param type
* The configuration type for the port
*/
ADIAnalogOut(std::uint8_t port);
ADIAnalogOut(std::uint8_t adi_port);

/**
* Configures an ADI port on an adi_expander to act as an Analog Output.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
*/
ADIAnalogOut(ext_adi_port_pair_t port);

/**
* Sets the value for the given ADI port.
Expand Down Expand Up @@ -233,12 +282,27 @@ class ADIDigitalOut : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* \param adi_port
* The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure
* \param type
* The configuration type for the port
* \param init_state
* The initial state for the port
*/
ADIDigitalOut(std::uint8_t port, bool init_state = LOW);
ADIDigitalOut(std::uint8_t adi_port, bool init_state = LOW);

/**
* Configures an ADI port on an adi_expander to act as a Digital Output.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
* \param init_state
* The initial state for the port
*/
ADIDigitalOut(ext_adi_port_pair_t port, bool init_state = LOW);

/**
* Sets the value for the given ADI port.
Expand Down Expand Up @@ -268,12 +332,23 @@ class ADIDigitalIn : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* \param adi_port
* The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure
* \param type
* The configuration type for the port
*/
ADIDigitalIn(std::uint8_t port);
ADIDigitalIn(std::uint8_t adi_port);

/**
* Configures an ADI port on an adi_expander to act as a Digital Input.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
*/
ADIDigitalIn(ext_adi_port_pair_t port);

/**
* Gets a rising-edge case for a digital button press.
Expand Down Expand Up @@ -318,13 +393,24 @@ class ADIMotor : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* \param adi_port
* The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure
* \param type
* The configuration type for the port
*/
ADIMotor(std::uint8_t port);
ADIMotor(std::uint8_t adi_port);

/**
* Configures an ADI port on an adi_expander to act as a Motor.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
*/
ADIMotor(ext_adi_port_pair_t port);

/**
* Stops the motor on the given port.
*
Expand Down Expand Up @@ -374,16 +460,31 @@ class ADIEncoder : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port_top
* The "top" wire from the encoder sensor with the removable cover side
* \param adi_port_top
* The tuple of the "top" wire from the encoder sensor with the removable cover side
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved
* UP
* \param port_bottom
* The "bottom" wire from the encoder sensor
* \param adi_port_bottom
* The "bottom" wire from the encoder sensor
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved
* \param reverse
* If "true", the sensor will count in the opposite direction
*/
ADIEncoder(std::uint8_t port_top, std::uint8_t port_bottom, bool reversed = false);

ADIEncoder(std::uint8_t adi_port_top, std::uint8_t adi_port_bottom, bool reversed = false);

/**
* Configures a set of ADI ports on an adi_expander to act as an Encoder.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* The tuple of the "top" wire from the encoder sensor with the removable cover side
* UP, the "bottom" wire from the encoder sensor, and the smart port number
* \param reverse
* If "true", the sensor will count in the opposite direction
*/
ADIEncoder(ext_adi_port_tuple_t port, bool reversed = false);

/**
* Sets the encoder value to zero.
*
Expand Down Expand Up @@ -416,8 +517,8 @@ class ADIEncoder : private ADIPort {

class ADIUltrasonic : private ADIPort {
public:
/**
* Configures a set of ADI ports to act as an Ultrasonic.
/**
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved
* Configures a set of ADI ports on an adi_expander to act as an Ultrasonic sensor.
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved
*
* This function uses the following values of errno when an error state is
* reached:
Expand All @@ -430,7 +531,21 @@ class ADIUltrasonic : private ADIPort {
* The port connected to the yellow INPUT cable. This should be in the
* next highest port following port_ping.
*/
ADIUltrasonic(std::uint8_t port_ping, std::uint8_t port_echo);
ADIUltrasonic(std::uint8_t adi_port_ping, std::uint8_t adi_port_echo);

/**
* Configures a set of ADI ports on an adi_expander to act as an Ultrasonic sensor.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports.
*
* \param port
* The tuple of the port connected to the orange OUTPUT cable (1, 3, 5, 7 or
* 'A', 'C', 'E', 'G'), the port connected to the yellow INPUT cable (the next
* highest port following port_ping), and the smart port number.
*/
ADIUltrasonic(ext_adi_port_tuple_t port);

/**
* Gets the current ultrasonic sensor value in centimeters.
Expand All @@ -446,15 +561,15 @@ class ADIUltrasonic : private ADIPort {
* \return The distance to the nearest object in m^-4 (10000 indicates 1
* meter), measured from the sensor's mounting points.
*/
using ADIPort::get_value;
std::int32_t get_value(void) const;
HotelCalifornia marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is an override, then mark it as such

Suggested change
std::int32_t get_value(void) const;
std::int32_t get_value(void) const override;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn’t work because in order for the override command to compile, the original function has to be labeled as virtual. If you label the original as virtual, than gyro::get_value also tries to override it ev,en though it has a different return type. So, I don’t think there is a way of doing this, without sacrificing uniformity in function names, and it only adds slight maintainability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Humm, this isn't really ideal. Since you have a virtual destructor, you already have the overhead of the vtable, so there is no good reason not to make the methods virtual. They should be virtual anyways, because if you have an ADIUltrasonic that is being treated as a ADIPort, you want it to properly dispatch to the derived method.
However, I see the problem with clashing with ADIGyro. Unfortunately, how it is right now is not ideal. The ADIGyro simply shadows and hides the derived method, which leads to problems with polymorphism and unexpected issues with the return type changing. I was worried it was going to lead to ambiguity, but at least this passes:

pros::ADIGyro g('A');
auto x = g.get_value();
static_assert(std::is_same_v<decltype(x), double>);

pros::ADIAnalogIn i('A');
auto j = i.get_value();
static_assert(std::is_same_v<decltype(j), std::int32_t>);

But you can see how it is not ideal to have the return type change, it could lead to unexpected conversions and narrowing.

What would be ideal is to have proper overriding and matching return type. I'm not sure how that would be done though, so I might have to agree with your conclusion.
Maybe have the base get_value override return integers and have a get_value_HR for the 10th precision, idk. If you and others don't think that's a good idea that's fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inheritence is private, so I don't think this is an issue.

BTW, my understanding is that most of the cost is in the function call. The vtable data structure has some size overhead, but that wouldn't be the part I worry about. If course, neither matter here.

};

class ADIGyro : private ADIPort {
public:
/**
* Initializes a gyroscope on the given port. If the given port has not
* previously been configured as a gyro, then this function starts a 1300ms
* calibration period.
* Initializes a gyroscope on the given port of an adi expander. If the given
mooreBrendan marked this conversation as resolved.
Show resolved Hide resolved
* port has not previously been configured as a gyro, then this function starts
* a 1300ms calibration period.
*
* It is highly recommended that an ADIGyro object be created in initialize()
* when the robot is stationary to ensure proper calibration. If an ADIGyro
Expand All @@ -466,13 +581,37 @@ class ADIGyro : private ADIPort {
* reached:
* ENXIO - The given value is not within the range of ADI Ports
*
* \param port
* \param adi_port
* The ADI port to initialize as a gyro (from 1-8, 'a'-'h', 'A'-'H')
* \param multiplier
* A scalar value that will be multiplied by the gyro heading value
* supplied by the ADI
*/
ADIGyro(std::uint8_t port, double multiplier = 1);
ADIGyro(std::uint8_t adi_port, double multiplier = 1);

/**
* Initializes a gyroscope on the given port of an adi expander. If the given
* port has not previously been configured as a gyro, then this function starts
* a 1300ms calibration period.
*
* It is highly recommended that an ADIGyro object be created in initialize()
* when the robot is stationary to ensure proper calibration. If an ADIGyro
* object is declared at the global scope, a hardcoded 1300ms delay at the
* beginning of initialize will be necessary to ensure that the gyro's
* returned values are correct at the beginning of autonomous/opcontrol.
*
* This function uses the following values of errno when an error state is
* reached:
* ENXIO - The given value is not within the range of ADI Ports
*
* \param port
* The pair of the ADI port number (from 1-8, 'a'-'h', 'A'-'H') and the
* smart port number (from 1-22) to configure
* \param multiplier
* A scalar value that will be multiplied by the gyro heading value
* supplied by the ADI
*/
ADIGyro(ext_adi_port_pair_t port, double multiplier = 1);

/**
* Gets the current gyro angle in tenths of a degree. Unless a multiplier is
Expand Down