Skip to content

Commit

Permalink
add lock guard for read/write IO values
Browse files Browse the repository at this point in the history
  • Loading branch information
viordash committed Sep 12, 2024
1 parent 7a91615 commit 5139662
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 39 deletions.
41 changes: 22 additions & 19 deletions PLC_esp8266/main/LogicProgram/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ uint8_t Controller::var4 = LogicElement::MinValue;

Ladder *Controller::ladder = NULL;

Controller::io_values Controller::cached_io_values = {};
std::recursive_mutex Controller::lock_io_values_mutex;
ControllerIOValues Controller::cached_io_values = {};

void Controller::Start(EventGroupHandle_t gpio_events) {
Controller::gpio_events = gpio_events;
Expand Down Expand Up @@ -120,44 +121,46 @@ void Controller::RenderTask(void *parm) {
}

bool Controller::SampleIOValues() {
bool any_changes = false;
bool val_1bit;
uint16_t val_10bit;
uint8_t percent04;
ControllerIOValues io_values;

val_10bit = get_analog_value();
percent04 = val_10bit / 4;
any_changes |= Controller::cached_io_values.AI != percent04;
Controller::cached_io_values.AI = percent04;
io_values.AI = percent04;

val_1bit = get_digital_input_value();
percent04 = val_1bit ? LogicElement::MaxValue : LogicElement::MinValue;
any_changes |= Controller::cached_io_values.DI != percent04;
Controller::cached_io_values.DI = percent04;
io_values.DI = percent04;

val_1bit = get_digital_value(gpio_output::OUTPUT_0);
percent04 = val_1bit ? LogicElement::MaxValue : LogicElement::MinValue;
any_changes |= Controller::cached_io_values.O1 != percent04;
Controller::cached_io_values.O1 = percent04;
io_values.O1 = percent04;

val_1bit = get_digital_value(gpio_output::OUTPUT_1);
percent04 = val_1bit ? LogicElement::MaxValue : LogicElement::MinValue;
any_changes |= Controller::cached_io_values.O2 != percent04;
Controller::cached_io_values.O2 = percent04;
io_values.O2 = percent04;

any_changes |= Controller::cached_io_values.V1 != Controller::var1;
Controller::cached_io_values.V1 = Controller::var1;
io_values.V1 = Controller::var1;

any_changes |= Controller::cached_io_values.V2 != Controller::var2;
Controller::cached_io_values.V2 = Controller::var2;
io_values.V2 = Controller::var2;

any_changes |= Controller::cached_io_values.V3 != Controller::var3;
Controller::cached_io_values.V3 = Controller::var3;
io_values.V3 = Controller::var3;

any_changes |= Controller::cached_io_values.V4 != Controller::var4;
Controller::cached_io_values.V4 = Controller::var4;
io_values.V4 = Controller::var4;
{
std::lock_guard<std::recursive_mutex> lock(Controller::lock_io_values_mutex);
bool has_changes =
memcmp(&io_values, &Controller::cached_io_values, sizeof(io_values)) != 0;
Controller::cached_io_values = io_values;
return has_changes;
}
}

return any_changes;
ControllerIOValues &Controller::GetIOValues() {
std::lock_guard<std::recursive_mutex> lock(Controller::lock_io_values_mutex);
return Controller::cached_io_values;
}

uint8_t Controller::GetAIRelativeValue() {
Expand Down
26 changes: 14 additions & 12 deletions PLC_esp8266/main/LogicProgram/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ extern "C" {
#include <stdlib.h>
#include <string.h>

typedef struct {
uint8_t AI;
uint8_t DI;
uint8_t O1;
uint8_t O2;
uint8_t V1;
uint8_t V2;
uint8_t V3;
uint8_t V4;
} ControllerIOValues;

class Controller {
protected:
typedef struct {
uint8_t AI;
uint8_t DI;
uint8_t O1;
uint8_t O2;
uint8_t V1;
uint8_t V2;
uint8_t V3;
uint8_t V4;
} io_values;

static bool runned;
static EventGroupHandle_t gpio_events;
static EventGroupHandle_t events;
Expand All @@ -41,12 +41,14 @@ class Controller {
static uint8_t var4;
static Ladder *ladder;

static io_values cached_io_values;
static std::recursive_mutex lock_io_values_mutex;
static ControllerIOValues cached_io_values;

public:
static void Start(EventGroupHandle_t gpio_events);
static void Stop();
static bool SampleIOValues();
static ControllerIOValues &GetIOValues();

static void ProcessTask(void *parm);
static void RenderTask(void *parm);
Expand Down
18 changes: 10 additions & 8 deletions PLC_esp8266/main/LogicProgram/StatusBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,31 @@ IRAM_ATTR bool StatusBar::Render(uint8_t *fb) {
uint8_t separator_width = 1;
Point point = { 2, y };

res &= indicator_AI->Render(fb, &point, Controller::GetAIRelativeValue());
ControllerIOValues io_values = Controller::GetIOValues();

res &= indicator_AI->Render(fb, &point, io_values.AI);
point.x += separator_width;

res &= indicator_DI->Render(fb, &point, Controller::GetDIRelativeValue());
res &= indicator_DI->Render(fb, &point, io_values.DI);
point.x += separator_width;

res &= indicator_O1->Render(fb, &point, Controller::GetO1RelativeValue());
res &= indicator_O1->Render(fb, &point, io_values.O1);
point.x += separator_width;

res &= indicator_O2->Render(fb, &point, Controller::GetO2RelativeValue());
res &= indicator_O2->Render(fb, &point, io_values.O2);
point.x += separator_width;

res &= indicator_V1->Render(fb, &point, Controller::GetV1RelativeValue());
res &= indicator_V1->Render(fb, &point, io_values.V1);
point.x += separator_width;

res &= indicator_V2->Render(fb, &point, Controller::GetV2RelativeValue());
res &= indicator_V2->Render(fb, &point, io_values.V2);
point.x += separator_width;

res &= indicator_V3->Render(fb, &point, Controller::GetV3RelativeValue());
res &= indicator_V3->Render(fb, &point, io_values.V3);
point.x += separator_width;

separator_width = 0;
res &= indicator_V4->Render(fb, &point, Controller::GetV4RelativeValue());
res &= indicator_V4->Render(fb, &point, io_values.V4);
point.x += separator_width;

res &= draw_horz_line(fb, 0, y + MapIOIndicator::GetHeight(), DISPLAY_WIDTH);
Expand Down
38 changes: 38 additions & 0 deletions Tests_esp8266/src/logic_Controller_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,41 @@ TEST(LogicControllerTestsGroup, SampleIOValues_returns_status_of_value_change) {
CHECK_TRUE(Controller::SampleIOValues());
CHECK_FALSE(Controller::SampleIOValues());
}

TEST(LogicControllerTestsGroup, GetIOValues) {
mock("0").expectNCalls(1, "gpio_get_level").andReturnValue(0);
mock("2").expectNCalls(1, "gpio_get_level").andReturnValue(0);
mock("15").expectNCalls(1, "gpio_get_level").andReturnValue(0);

volatile uint16_t adc = 19 / 0.1;
mock()
.expectNCalls(1, "adc_read")
.withOutputParameterReturning("adc", (const void *)&adc, sizeof(adc));

Controller::SetV1RelativeValue(1);
Controller::SetV2RelativeValue(2);
Controller::SetV3RelativeValue(3);
Controller::SetV4RelativeValue(4);

ControllerIOValues io_values = Controller::GetIOValues();

CHECK_COMPARE(io_values.AI, !=, 19);
CHECK_COMPARE(io_values.DI, !=, LogicElement::MaxValue);
CHECK_COMPARE(io_values.O1, !=, LogicElement::MaxValue);
CHECK_COMPARE(io_values.O2, !=, LogicElement::MaxValue);
CHECK_COMPARE(io_values.V1, !=, 1);
CHECK_COMPARE(io_values.V2, !=, 2);
CHECK_COMPARE(io_values.V3, !=, 3);
CHECK_COMPARE(io_values.V4, !=, 4);
CHECK_TRUE(Controller::SampleIOValues());

io_values = Controller::GetIOValues();
CHECK_COMPARE(io_values.AI, ==, (uint8_t)(19 / 0.4));
CHECK_COMPARE(io_values.DI, ==, LogicElement::MaxValue);
CHECK_COMPARE(io_values.O1, ==, LogicElement::MaxValue);
CHECK_COMPARE(io_values.O2, ==, LogicElement::MaxValue);
CHECK_COMPARE(io_values.V1, ==, 1);
CHECK_COMPARE(io_values.V2, ==, 2);
CHECK_COMPARE(io_values.V3, ==, 3);
CHECK_COMPARE(io_values.V4, ==, 4);
}

0 comments on commit 5139662

Please sign in to comment.