Skip to content
This repository was archived by the owner on May 3, 2026. It is now read-only.

Commit b510600

Browse files
committed
further restructuring of port mutexes
1 parent d68bb2a commit b510600

7 files changed

Lines changed: 140 additions & 155 deletions

File tree

include/pros/devices/adi_expander.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class AdiExpander {
1616
*
1717
* @param port the smart port the ADI expander is connected to
1818
*/
19-
consteval AdiExpander(SmartPort& port)
19+
constexpr AdiExpander(SmartPort port)
2020
: port_a(port, 'A'),
2121
port_b(port, 'B'),
2222
port_c(port, 'C'),
@@ -39,6 +39,6 @@ class AdiExpander {
3939
// users may use port_invalid as a placeholder or temporary port
4040
AdiPort port_invalid;
4141

42-
SmartPort& smart_port;
42+
SmartPort smart_port;
4343
};
4444
}; // namespace zest

include/pros/devices/battery.hpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,41 @@
11
#pragma once
22

3-
#include "common/result.hpp"
4-
53
namespace zest {
64

75
class Battery {
86
public:
9-
static Result<double, UnknownError> get_capacity();
10-
static Result<double, UnknownError> get_current();
11-
static Result<double, UnknownError> get_temperature();
12-
static Result<double, UnknownError> get_voltage();
7+
/**
8+
* @brief Get the remaining capacity of the robot battery
9+
*
10+
* TODO: document how the returned value should be interpreted (e.g 0-1 or 0-100)
11+
*
12+
* @return double
13+
*/
14+
static double get_capacity();
15+
/**
16+
* @brief Get the current drawn from the robot battery
17+
*
18+
* TODO: document how the returned value should be interpreted (e.g amps or milliamps)
19+
*
20+
* @return double
21+
*/
22+
static double get_current();
23+
/**
24+
* @brief Get the temperature of the robot battery
25+
*
26+
* TODO: document how the returned value should be interpreted (e.g celsius or fahrenheit)
27+
*
28+
* @return double
29+
*/
30+
static double get_temperature();
31+
/**
32+
* @brief Get the voltage of the robot battery
33+
*
34+
* TODO: document how the returned value should be interpreted (e.g celsius or fahrenheit)
35+
*
36+
* @return double
37+
*/
38+
static double get_voltage();
1339
};
1440

1541
} // namespace zest

include/pros/devices/brain.hpp

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "pros/devices/adi_expander.hpp"
4+
#include "pros/rtos.hpp"
45

56
namespace zest {
67
/**
@@ -9,42 +10,65 @@ namespace zest {
910
*/
1011
class Brain {
1112
public:
12-
// port collections
13-
// there are 21 physical smart ports, 11 virtual smart ports, and 1 reserved virtual smart port
14-
// for invalid ports. Totals 33.
15-
static constinit std::array<SmartPort, 33> ports;
16-
1713
// physical smart ports
18-
// these references are simply a QoL feature
19-
static constinit SmartPort& port_1;
20-
static constinit SmartPort& port_2;
21-
static constinit SmartPort& port_3;
22-
static constinit SmartPort& port_4;
23-
static constinit SmartPort& port_5;
24-
static constinit SmartPort& port_6;
25-
static constinit SmartPort& port_7;
26-
static constinit SmartPort& port_8;
27-
static constinit SmartPort& port_9;
28-
static constinit SmartPort& port_10;
29-
static constinit SmartPort& port_11;
30-
static constinit SmartPort& port_12;
31-
static constinit SmartPort& port_13;
32-
static constinit SmartPort& port_14;
33-
static constinit SmartPort& port_15;
34-
static constinit SmartPort& port_16;
35-
static constinit SmartPort& port_17;
36-
static constinit SmartPort& port_18;
37-
static constinit SmartPort& port_19;
38-
static constinit SmartPort& port_20;
39-
static constinit SmartPort& port_21;
14+
static constexpr SmartPort PORT_1 = SmartPort(1);
15+
static constexpr SmartPort PORT_2 = SmartPort(2);
16+
static constexpr SmartPort PORT_3 = SmartPort(3);
17+
static constexpr SmartPort PORT_4 = SmartPort(4);
18+
static constexpr SmartPort PORT_5 = SmartPort(5);
19+
static constexpr SmartPort PORT_6 = SmartPort(6);
20+
static constexpr SmartPort PORT_7 = SmartPort(7);
21+
static constexpr SmartPort PORT_8 = SmartPort(8);
22+
static constexpr SmartPort PORT_9 = SmartPort(9);
23+
static constexpr SmartPort PORT_10 = SmartPort(10);
24+
static constexpr SmartPort PORT_11 = SmartPort(11);
25+
static constexpr SmartPort PORT_12 = SmartPort(12);
26+
static constexpr SmartPort PORT_13 = SmartPort(13);
27+
static constexpr SmartPort PORT_14 = SmartPort(14);
28+
static constexpr SmartPort PORT_15 = SmartPort(15);
29+
static constexpr SmartPort PORT_16 = SmartPort(16);
30+
static constexpr SmartPort PORT_17 = SmartPort(17);
31+
static constexpr SmartPort PORT_18 = SmartPort(18);
32+
static constexpr SmartPort PORT_19 = SmartPort(19);
33+
static constexpr SmartPort PORT_20 = SmartPort(20);
34+
static constexpr SmartPort PORT_21 = SmartPort(21);
4035

4136
// virtual smart ports
42-
static constinit SmartPort& integrated_adi_port;
43-
static constinit SmartPort& battery_port;
37+
static constexpr SmartPort INTEGRATED_ADI_PORT = SmartPort(22);
38+
static constexpr SmartPort BATTERY_PORT = SmartPort(25);
4439
// users may use port_invalid as a placeholder or temporary port
45-
static constinit SmartPort& invalid_port;
40+
static constexpr SmartPort INVALID_PORT = SmartPort(33);
4641

4742
// all adi ports on the brain
48-
static constinit AdiExpander adi;
43+
static constexpr AdiExpander adi = AdiExpander(INTEGRATED_ADI_PORT);
44+
45+
// TODO: conditionally declare functions below, to prevent users accidentally calling them
46+
// TODO: replace lock_all and unlock_all with a single function that returns an std::scoped_lock
47+
48+
/**
49+
* @brief Get the mutex of a smart port
50+
*
51+
* @warning this function should not be used by typical users
52+
*
53+
* @param smart_port the smart port to get the mutex of
54+
* @return pros::RecursiveMutex&
55+
*/
56+
static pros::RecursiveMutex& get_smart_port_mutex(SmartPort smart_port);
57+
58+
/**
59+
* @brief lock all smart port mutexes
60+
*
61+
* uses std::lock to prevent deadlocks
62+
*/
63+
static void smart_port_mutex_lock_all();
64+
65+
/**
66+
* @brief unlock all smart port mutexes
67+
*
68+
*/
69+
static void smart_port_mutex_unlock_all();
70+
71+
private:
72+
static constinit std::array<pros::RecursiveMutex, 33> m_mutexes;
4973
};
5074
}; // namespace zest

include/pros/devices/port.hpp

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#pragma once
22

3-
#include "pros/rtos.hpp"
4-
53
#include <cstdint>
64

75
namespace zest {
@@ -37,11 +35,6 @@ class SmartPort {
3735
return m_number - 1;
3836
}
3937

40-
// users should always use a reference to a SmartPort
41-
SmartPort(SmartPort& other) = delete;
42-
43-
pros::RecursiveMutex mutex;
44-
4538
private:
4639
/**
4740
* @brief construct a Smart Port from an index
@@ -65,15 +58,12 @@ class AdiPort {
6558

6659
public:
6760
/**
68-
* @brief Get the ADI Port as a char
69-
*
70-
* @note the returned char will be uppercase
61+
* @brief Get the ADI Port as an uppercase letter
7162
*
7263
* @return constexpr char
7364
*/
74-
constexpr char as_char() const {
75-
// convert index to an uppercase letter
76-
return m_index + 'A';
65+
constexpr char as_letter() const {
66+
return m_letter;
7767
}
7868

7969
/**
@@ -82,13 +72,13 @@ class AdiPort {
8272
* @return constexpr uint8_t
8373
*/
8474
constexpr uint8_t as_index() const {
85-
return m_index;
75+
return m_letter - 'A';
8676
}
8777

8878
// users should always use a reference to an AdiPort
8979
AdiPort(AdiPort& other) = delete;
9080

91-
SmartPort& host_port;
81+
SmartPort host_port;
9282

9383
private:
9484
/**
@@ -98,10 +88,11 @@ class AdiPort {
9888
* @param port must be uppercase, 'A' - 'H'
9989
* @return constexpr AdiPort
10090
*/
101-
constexpr AdiPort(SmartPort& host_port, char port)
91+
constexpr AdiPort(SmartPort host_port, char port)
10292
: host_port(host_port),
103-
m_index(port - 'A') {}
93+
m_letter(port) {}
10494

105-
uint8_t m_index;
95+
char m_letter;
10696
};
97+
10798
} // namespace zest

src/devices/battery.cpp

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,23 @@
66
#include <mutex>
77

88
namespace zest {
9-
10-
static Brain brain;
11-
12-
Result<double, UnknownError> Battery::get_capacity() {
13-
std::lock_guard lock(brain.battery_port.mutex);
14-
if (auto res = vexBatteryCapacityGet(); res == std::numeric_limits<typeof(res)>::max()) {
15-
return UnknownError("An unknown error has occurred");
16-
} else {
17-
return res;
18-
}
9+
double Battery::get_capacity() {
10+
std::lock_guard lock(Brain::get_smart_port_mutex(Brain::BATTERY_PORT));
11+
return vexBatteryCapacityGet();
1912
}
2013

21-
Result<double, UnknownError> Battery::get_current() {
22-
std::lock_guard lock(brain.battery_port.mutex);
23-
if (auto res = vexBatteryCurrentGet(); res == std::numeric_limits<typeof(res)>::max()) {
24-
return UnknownError("An unknown error has occurred");
25-
} else {
26-
return res;
27-
}
14+
double Battery::get_current() {
15+
std::lock_guard lock(Brain::get_smart_port_mutex(Brain::BATTERY_PORT));
16+
return vexBatteryCurrentGet();
2817
}
2918

30-
Result<double, UnknownError> Battery::get_temperature() {
31-
std::lock_guard lock(brain.battery_port.mutex);
32-
if (auto res = vexBatteryTemperatureGet(); res == std::numeric_limits<typeof(res)>::max()) {
33-
return UnknownError("An unknown error has occurred");
34-
} else {
35-
return res;
36-
}
19+
double Battery::get_temperature() {
20+
std::lock_guard lock(Brain::get_smart_port_mutex(Brain::BATTERY_PORT));
21+
return vexBatteryTemperatureGet();
3722
}
3823

39-
Result<double, UnknownError> Battery::get_voltage() {
40-
std::lock_guard lock(brain.battery_port.mutex);
41-
if (auto res = vexBatteryVoltageGet(); res == std::numeric_limits<typeof(res)>::max()) {
42-
return UnknownError("An unknown error has occurred");
43-
} else {
44-
return res;
45-
}
24+
double Battery::get_voltage() {
25+
std::lock_guard lock(Brain::get_smart_port_mutex(Brain::BATTERY_PORT));
26+
return vexBatteryVoltageGet();
4627
}
4728
} // namespace zest

src/devices/brain.cpp

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,35 @@
11
#include "pros/devices/brain.hpp"
22

3+
#include <mutex>
4+
35
namespace zest {
4-
// collection of smart ports
5-
constinit std::array<SmartPort, 33> Brain::ports = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
6-
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
7-
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33};
86

9-
// physical smart ports
10-
constinit SmartPort& Brain::port_1 = ports.at(0);
11-
constinit SmartPort& Brain::port_2 = ports.at(1);
12-
constinit SmartPort& Brain::port_3 = ports.at(2);
13-
constinit SmartPort& Brain::port_4 = ports.at(3);
14-
constinit SmartPort& Brain::port_5 = ports.at(4);
15-
constinit SmartPort& Brain::port_6 = ports.at(5);
16-
constinit SmartPort& Brain::port_7 = ports.at(6);
17-
constinit SmartPort& Brain::port_8 = ports.at(7);
18-
constinit SmartPort& Brain::port_9 = ports.at(8);
19-
constinit SmartPort& Brain::port_10 = ports.at(9);
20-
constinit SmartPort& Brain::port_11 = ports.at(10);
21-
constinit SmartPort& Brain::port_12 = ports.at(11);
22-
constinit SmartPort& Brain::port_13 = ports.at(12);
23-
constinit SmartPort& Brain::port_14 = ports.at(13);
24-
constinit SmartPort& Brain::port_15 = ports.at(14);
25-
constinit SmartPort& Brain::port_16 = ports.at(15);
26-
constinit SmartPort& Brain::port_17 = ports.at(16);
27-
constinit SmartPort& Brain::port_18 = ports.at(17);
28-
constinit SmartPort& Brain::port_19 = ports.at(18);
29-
constinit SmartPort& Brain::port_20 = ports.at(19);
30-
constinit SmartPort& Brain::port_21 = ports.at(20);
7+
pros::RecursiveMutex& Brain::get_smart_port_mutex(SmartPort smart_port) {
8+
// If the port is invalid, return the invalid port mutex.
9+
// Otherwise, return the respective mutex
10+
if (smart_port.as_number() > 32) {
11+
return m_mutexes.at(Brain::INVALID_PORT.as_index());
12+
} else {
13+
return m_mutexes.at(smart_port.as_index());
14+
}
15+
}
16+
17+
void Brain::smart_port_mutex_lock_all() {
18+
std::apply([&](auto&... args) {
19+
std::lock(args...);
20+
}, Brain::m_mutexes);
21+
}
22+
23+
void Brain::smart_port_mutex_unlock_all() {
24+
for (auto& mutex : Brain::m_mutexes) {
25+
mutex.unlock();
26+
}
27+
}
3128

32-
// virtual smart ports
33-
constinit SmartPort& Brain::integrated_adi_port = ports.at(21);
34-
constinit SmartPort& Brain::battery_port = ports.at(24);
35-
constinit SmartPort& Brain::invalid_port = ports.at(32);
29+
// The VEX SDK has 32 virtual smart ports.
30+
// 21 of these ports represent physical smart ports,
31+
// the rest represent things like the battery, the controller, etc.
32+
// This array has 33 mutexes. The extra mutex is used for invalid ports.
33+
constinit std::array<pros::RecursiveMutex, 33> Brain::m_mutexes;
3634

37-
// adi ports integrated in the brain
38-
constinit AdiExpander Brain::adi = AdiExpander(integrated_adi_port);
3935
} // namespace zest

0 commit comments

Comments
 (0)