Skip to content

Commit 25b3efd

Browse files
committed
Move ownership of inputs to the service
1 parent b4acb55 commit 25b3efd

File tree

10 files changed

+90
-59
lines changed

10 files changed

+90
-59
lines changed

src/drivers/input/gpio_input_driver.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ namespace xbot::driver::input {
1111

1212
bool GpioInputDriver::OnInputConfigValue(lwjson_stream_parser_t* jsp, const char* key, lwjson_stream_type_t type,
1313
Input& input) {
14-
auto& gpio_input = static_cast<GpioInput&>(input);
1514
if (strcmp(key, "line") == 0) {
1615
JsonExpectType(STRING);
17-
gpio_input.line = GetIoLineByName(jsp->data.str.buff);
18-
if (gpio_input.line == PAL_NOLINE) {
16+
input.gpio.line = GetIoLineByName(jsp->data.str.buff);
17+
if (input.gpio.line == PAL_NOLINE) {
1918
ULOG_ERROR("Unknown GPIO line \"%s\"", jsp->data.str.buff);
2019
return false;
2120
}
@@ -41,23 +40,23 @@ static void LineCallback(void*) {
4140
}
4241

4342
bool GpioInputDriver::OnStart() {
44-
for (const auto& input : inputs_) {
45-
palSetLineMode(input.line, PAL_MODE_INPUT);
46-
palSetLineCallback(input.line, LineCallback, nullptr);
47-
palEnableLineEvent(input.line, PAL_EVENT_MODE_BOTH_EDGES);
43+
for (const auto& input : Inputs()) {
44+
palSetLineMode(input.gpio.line, PAL_MODE_INPUT);
45+
palSetLineCallback(input.gpio.line, LineCallback, nullptr);
46+
palEnableLineEvent(input.gpio.line, PAL_EVENT_MODE_BOTH_EDGES);
4847
}
4948
return true;
5049
}
5150

5251
void GpioInputDriver::OnStop() {
53-
for (const auto& input : inputs_) {
54-
palDisableLineEvent(input.line);
52+
for (const auto& input : Inputs()) {
53+
palDisableLineEvent(input.gpio.line);
5554
}
5655
}
5756

5857
void GpioInputDriver::tick() {
59-
for (auto& input : inputs_) {
60-
input.Update(palReadLine(input.line) == PAL_HIGH);
58+
for (auto& input : Inputs()) {
59+
input.Update(palReadLine(input.gpio.line) == PAL_HIGH);
6160
}
6261
}
6362

src/drivers/input/gpio_input_driver.hpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,13 @@ class GpioInputDriver : public InputDriver {
1212
using InputDriver::InputDriver;
1313

1414
public:
15-
Input& AddInput() override {
16-
return inputs_.emplace_back();
17-
}
18-
void ClearInputs() override {
19-
inputs_.clear();
20-
}
2115
bool OnInputConfigValue(lwjson_stream_parser_t* jsp, const char* key, lwjson_stream_type_t type,
2216
Input& input) override;
2317
bool OnStart() override;
2418
void OnStop() override;
2519
void tick();
2620

2721
private:
28-
struct GpioInput : public Input {
29-
ioline_t line = PAL_NOLINE;
30-
};
31-
32-
etl::vector<GpioInput, 4> inputs_;
33-
3422
ServiceSchedule tick_schedule_{input_service, 1'000'000,
3523
XBOT_FUNCTION_FOR_METHOD(GpioInputDriver, &GpioInputDriver::tick, this)};
3624
};

src/drivers/input/input_driver.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,20 @@ bool Input::Update(bool new_active) {
2222
return false;
2323
}
2424

25+
void InputDriver::AddInput(Input* input) {
26+
if (inputs_head_ == nullptr) {
27+
inputs_head_ = input;
28+
} else {
29+
Input* current = inputs_head_;
30+
while (current->next_for_driver_ != nullptr) {
31+
current = current->next_for_driver_;
32+
}
33+
current->next_for_driver_ = input;
34+
}
35+
}
36+
37+
void InputDriver::ClearInputs() {
38+
inputs_head_ = nullptr;
39+
}
40+
2541
} // namespace xbot::driver::input

src/drivers/input/input_driver.hpp

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <etl/atomic.h>
55
#include <etl/string.h>
6+
#include <hal.h>
67
#include <lwjson/lwjson.h>
78

89
#include <xbot-service/portable/system.hpp>
@@ -17,6 +18,16 @@ struct Input {
1718
uint16_t emergency_reason = 0;
1819
uint16_t emergency_delay_ms = 0;
1920

21+
union {
22+
struct {
23+
ioline_t line;
24+
} gpio;
25+
26+
struct {
27+
uint8_t bit;
28+
} worx;
29+
};
30+
2031
// State
2132
bool IsActive() const {
2233
return active;
@@ -31,20 +42,59 @@ struct Input {
3142
private:
3243
etl::atomic<bool> active = false;
3344
uint32_t active_since = 0;
45+
Input* next_for_driver_ = nullptr;
46+
47+
friend class InputDriver;
48+
friend struct InputIterable;
49+
};
50+
51+
struct InputIterable {
52+
Input* head;
53+
54+
struct Iterator {
55+
Input* ptr;
56+
57+
Input& operator*() const {
58+
return *ptr;
59+
}
60+
61+
Iterator& operator++() {
62+
ptr = ptr->next_for_driver_;
63+
return *this;
64+
}
65+
66+
bool operator!=(const Iterator& other) const {
67+
return ptr != other.ptr;
68+
}
69+
};
70+
71+
Iterator begin() const {
72+
return Iterator{head};
73+
}
74+
75+
Iterator end() const {
76+
return Iterator{nullptr};
77+
}
3478
};
3579

3680
class InputDriver {
3781
public:
3882
virtual ~InputDriver() = default;
3983
explicit InputDriver() = default;
40-
virtual Input& AddInput() = 0;
41-
virtual void ClearInputs() = 0;
84+
void AddInput(Input* input);
85+
void ClearInputs();
4286
virtual bool OnInputConfigValue(lwjson_stream_parser_t* jsp, const char* key, lwjson_stream_type_t type,
4387
Input& input) = 0;
4488
virtual bool OnStart() {
4589
return true;
4690
};
4791
virtual void OnStop(){};
92+
93+
protected:
94+
Input* inputs_head_ = nullptr;
95+
InputIterable Inputs() {
96+
return InputIterable{inputs_head_};
97+
}
4898
};
4999
} // namespace xbot::driver::input
50100

src/drivers/input/simulated_input_driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ bool SimulatedInputDriver::OnInputConfigValue(lwjson_stream_parser_t* jsp, const
1818
}
1919

2020
void SimulatedInputDriver::SetActiveInputs(uint64_t active_inputs_mask) {
21-
for (auto& input : inputs_) {
21+
for (auto& input : Inputs()) {
2222
input.Update(IS_BIT_SET(active_inputs_mask, input.idx));
2323
}
2424
}

src/drivers/input/simulated_input_driver.hpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,9 @@ class SimulatedInputDriver : public InputDriver {
1010
using InputDriver::InputDriver;
1111

1212
public:
13-
Input& AddInput() override {
14-
return inputs_.emplace_back();
15-
}
16-
void ClearInputs() override {
17-
inputs_.clear();
18-
}
1913
bool OnInputConfigValue(lwjson_stream_parser_t* jsp, const char* key, lwjson_stream_type_t type,
2014
Input& input) override;
2115
void SetActiveInputs(uint64_t active_inputs_mask);
22-
23-
private:
24-
etl::vector<Input, 64> inputs_;
2516
};
2617
} // namespace xbot::driver::input
2718

src/drivers/input/worx_input_driver.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ static const etl::flat_map<etl::string<13>, uint8_t, 8> INPUT_BITS = {
2727

2828
bool WorxInputDriver::OnInputConfigValue(lwjson_stream_parser_t* jsp, const char* key, lwjson_stream_type_t type,
2929
Input& input) {
30-
auto& worx_input = static_cast<WorxInput&>(input);
3130
if (strcmp(key, "id") == 0) {
3231
JsonExpectType(STRING);
3332
decltype(INPUT_BITS)::key_type input_id{jsp->data.str.buff};
@@ -36,7 +35,7 @@ bool WorxInputDriver::OnInputConfigValue(lwjson_stream_parser_t* jsp, const char
3635
ULOG_ERROR("Unknown Worx input ID \"%s\"", input_id.c_str());
3736
return false;
3837
}
39-
worx_input.bit = bit_it->second;
38+
input.worx.bit = bit_it->second;
4039
return true;
4140
}
4241
ULOG_ERROR("Unknown attribute \"%s\"", key);
@@ -52,8 +51,8 @@ bool WorxInputDriver::OnStart() {
5251
void WorxInputDriver::tick() {
5352
KeypadResponse keypad{};
5453
if (ReadKeypad(keypad)) {
55-
for (auto& input : inputs_) {
56-
input.Update(IS_BIT_SET(keypad.keys_and_halls, input.bit));
54+
for (auto& input : Inputs()) {
55+
input.Update(IS_BIT_SET(keypad.keys_and_halls, input.worx.bit));
5756
}
5857
}
5958
}

src/drivers/input/worx_input_driver.hpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ class WorxInputDriver : public InputDriver {
1313
using InputDriver::InputDriver;
1414

1515
public:
16-
Input& AddInput() override {
17-
return inputs_.emplace_back();
18-
}
19-
void ClearInputs() override {
20-
inputs_.clear();
21-
}
2216
bool OnInputConfigValue(lwjson_stream_parser_t* jsp, const char* key, lwjson_stream_type_t type,
2317
Input& input) override;
2418
bool OnStart() override;
@@ -33,14 +27,8 @@ class WorxInputDriver : public InputDriver {
3327
};
3428
#pragma pack(pop)
3529

36-
struct WorxInput : public Input {
37-
uint8_t bit = 0;
38-
};
39-
4030
I2CDriver* i2c_driver_ = nullptr;
4131

42-
etl::vector<WorxInput, 16> inputs_;
43-
4432
bool ReadKeypad(KeypadResponse& response) const;
4533

4634
void tick();

src/services/input_service/input_service.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ bool InputService::InputConfigsJsonCallback(lwjson_stream_parser_t* jsp, lwjson_
6868
ULOG_ERROR("Too many inputs (max. %d)", all_inputs_.max_size());
6969
return false;
7070
}
71-
data->current_input = &data->driver->AddInput();
71+
data->current_input = &all_inputs_.emplace_back();
7272
data->current_input->idx = data->next_idx++;
73+
data->driver->AddInput(data->current_input);
7374
} else {
7475
// TODO: Give driver a chance to check completeness of the input?
75-
all_inputs_.push_back(data->current_input);
7676
data->current_input = nullptr;
7777
}
7878
break;
@@ -166,8 +166,8 @@ uint32_t InputService::OnLoop(uint32_t, uint32_t) {
166166
void InputService::SendStatus() {
167167
uint64_t active_inputs_mask = 0;
168168
for (auto& input : all_inputs_) {
169-
if (input->IsActive()) {
170-
active_inputs_mask |= 1 << input->idx;
169+
if (input.IsActive()) {
170+
active_inputs_mask |= 1 << input.idx;
171171
}
172172
}
173173

@@ -214,9 +214,9 @@ etl::pair<uint16_t, uint32_t> InputService::GetEmergencyReasons(uint32_t now) {
214214
uint32_t block_time = UINT32_MAX;
215215
for (const auto& input : all_inputs_) {
216216
// TODO: What if the input was triggered so briefly that we couldn't observe it?
217-
if (input->emergency_reason == 0 || !input->IsActive()) continue;
218-
if (TimeoutReached(input->ActiveDuration(now), input->emergency_delay_ms * 1'000, block_time)) {
219-
reasons |= input->emergency_reason;
217+
if (input.emergency_reason == 0 || !input.IsActive()) continue;
218+
if (TimeoutReached(input.ActiveDuration(now), input.emergency_delay_ms * 1'000, block_time)) {
219+
reasons |= input.emergency_reason;
220220
}
221221
}
222222

src/services/input_service/input_service.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class InputService : public InputServiceBase {
4141
etl::flat_map<etl::string<10>, InputDriver*, 3> drivers_;
4242

4343
// Must not have more than 64 inputs due to the size of various bitmasks.
44-
etl::vector<Input*, 30> all_inputs_;
44+
etl::vector<Input, 30> all_inputs_;
4545

4646
etl::atomic<uint8_t> num_active_lift_{0};
4747
Input lift_input_;

0 commit comments

Comments
 (0)