blob: ede3ed58bb52d8e34dc0e806fc658e289ed5abb9 [file] [log] [blame]
// Copyright 2025 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_digital_io/digital_io.h"
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_emul.h>
#include "pw_digital_io_zephyr/digital_io.h"
#include "pw_unit_test/framework.h"
namespace pw::digital_io {
namespace {
constexpr const struct gpio_dt_spec kZephyrGpio = {
.port = DEVICE_DT_GET(DT_NODELABEL(gpio0)),
.pin = 0,
.dt_flags = 0,
};
TEST(DigitalIoTest, ReadDigitalIn) {
ZephyrDigitalIn gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
auto state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kActive);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kInactive);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, ReadDigitalInInterrupt) {
ZephyrDigitalInInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
auto state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kActive);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kInactive);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, TriggerDigitalInInterrupt) {
int trigger_count = 0;
ZephyrDigitalInInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetInterruptHandler(
InterruptTrigger::kBothEdges,
[&trigger_count](State sampled_state) {
if (trigger_count == 0 && sampled_state == State::kActive) {
trigger_count++;
} else if (trigger_count == 1 &&
sampled_state == State::kInactive) {
trigger_count++;
}
}),
pw::OkStatus());
ASSERT_EQ(gpio.EnableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 2);
trigger_count = 0;
ASSERT_EQ(gpio.DisableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 0);
ASSERT_EQ(gpio.ClearInterruptHandler(), pw::OkStatus());
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, ReadDigitalInOut) {
ZephyrDigitalInOut gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
auto state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kActive);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kInactive);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, WriteDigitalInOut) {
ZephyrDigitalInOut gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetStateActive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 1);
ASSERT_EQ(gpio.SetStateInactive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 0);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, ReadDigitalInOutInterrupt) {
ZephyrDigitalInOutInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
auto state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kActive);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
state = gpio.GetState();
ASSERT_EQ(state.status(), pw::OkStatus());
ASSERT_EQ(state.value(), State::kInactive);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, WriteDigitalInOutInterrupt) {
ZephyrDigitalInOutInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetStateActive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 1);
ASSERT_EQ(gpio.SetStateInactive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 0);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, TriggerDigitalInOutInterrupt) {
int trigger_count = 0;
ZephyrDigitalInOutInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetInterruptHandler(
InterruptTrigger::kBothEdges,
[&trigger_count](State sampled_state) {
if (trigger_count == 0 && sampled_state == State::kActive) {
trigger_count++;
} else if (trigger_count == 1 &&
sampled_state == State::kInactive) {
trigger_count++;
}
}),
pw::OkStatus());
ASSERT_EQ(gpio.EnableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 2);
trigger_count = 0;
ASSERT_EQ(gpio.DisableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 0);
ASSERT_EQ(gpio.ClearInterruptHandler(), pw::OkStatus());
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, TriggerDigitalInterrupt) {
int trigger_count = 0;
ZephyrDigitalInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetInterruptHandler(
InterruptTrigger::kBothEdges,
[&trigger_count](State sampled_state) {
if (trigger_count == 0 && sampled_state == State::kActive) {
trigger_count++;
} else if (trigger_count == 1 &&
sampled_state == State::kInactive) {
trigger_count++;
}
}),
pw::OkStatus());
ASSERT_EQ(gpio.EnableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 2);
trigger_count = 0;
ASSERT_EQ(gpio.DisableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 0);
ASSERT_EQ(gpio.ClearInterruptHandler(), pw::OkStatus());
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, WriteDigitalOut) {
ZephyrDigitalOut gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetStateActive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 1);
ASSERT_EQ(gpio.SetStateInactive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 0);
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
TEST(DigitalIoTest, WriteDigitalOutInterrupt) {
ZephyrDigitalOutInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetStateActive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 1);
ASSERT_EQ(gpio.SetStateInactive(), pw::OkStatus());
ASSERT_EQ(gpio_emul_output_get(kZephyrGpio.port, kZephyrGpio.pin), 0);
}
TEST(DigitalIoTest, TriggerDigitalOutInterrupt) {
int trigger_count = 0;
ZephyrDigitalOutInterrupt gpio(kZephyrGpio);
ASSERT_EQ(gpio.Enable(), pw::OkStatus());
ASSERT_EQ(gpio.SetInterruptHandler(
InterruptTrigger::kBothEdges,
[&trigger_count](State sampled_state) {
if (trigger_count == 0 && sampled_state == State::kActive) {
trigger_count++;
} else if (trigger_count == 1 &&
sampled_state == State::kInactive) {
trigger_count++;
}
}),
pw::OkStatus());
ASSERT_EQ(gpio.EnableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 2);
trigger_count = 0;
ASSERT_EQ(gpio.DisableInterruptHandler(), pw::OkStatus());
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 1);
gpio_emul_input_set(kZephyrGpio.port, kZephyrGpio.pin, 0);
ASSERT_EQ(trigger_count, 0);
ASSERT_EQ(gpio.ClearInterruptHandler(), pw::OkStatus());
ASSERT_EQ(gpio.Disable(), pw::OkStatus());
}
} // namespace
} // namespace pw::digital_io