pw_digital_io_mcuxpresso: Pass correct pin state for interrupt handler

Also allow enable on enabled pin to be a no-op to align with current
digital_io reccomendations.

Add a test that builds when the rt595 sample sdk is enabled to ensure
this code is built in CI. If no tests are present in a conditionally
compiled module then pigweed CI won't compile it.

Change-Id: I472044989421c30e6a11bb39f208e6f0d5df136b
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/151131
Reviewed-by: Anton Markov <amarkov@google.com>
Commit-Queue: Austin Foxley <afoxley@google.com>
diff --git a/pw_digital_io_mcuxpresso/BUILD.bazel b/pw_digital_io_mcuxpresso/BUILD.bazel
index 7de0177..e377c16 100644
--- a/pw_digital_io_mcuxpresso/BUILD.bazel
+++ b/pw_digital_io_mcuxpresso/BUILD.bazel
@@ -15,6 +15,7 @@
 load(
     "//pw_build:pigweed.bzl",
     "pw_cc_library",
+    "pw_cc_test",
 )
 
 package(default_visibility = ["//visibility:public"])
@@ -41,3 +42,12 @@
         "//pw_preprocessor",
     ],
 )
+
+pw_cc_test(
+    name = "mimxrt595_test",
+    srcs = ["mimxrt595_test.cc"],
+    target_compatible_with = [
+        "//pw_build/constraints/board:mimxrt595_evk",
+    ],
+    deps = [":pw_digital_io_mcuxpresso"],
+)
diff --git a/pw_digital_io_mcuxpresso/BUILD.gn b/pw_digital_io_mcuxpresso/BUILD.gn
index 37a4384..6a244f0 100644
--- a/pw_digital_io_mcuxpresso/BUILD.gn
+++ b/pw_digital_io_mcuxpresso/BUILD.gn
@@ -17,6 +17,7 @@
 import("$dir_pw_build/target_types.gni")
 import("$dir_pw_docgen/docs.gni")
 import("$dir_pw_third_party/mcuxpresso/mcuxpresso.gni")
+import("$dir_pw_toolchain/generate_toolchain.gni")
 import("$dir_pw_unit_test/test.gni")
 
 config("default_config") {
@@ -47,7 +48,21 @@
   }
 }
 
+pw_test("mimxrt595_test") {
+  enable_if =
+      pw_third_party_mcuxpresso_SDK == "//targets/mimxrt595_evk:sample_sdk" &&
+      (pw_toolchain_SCOPE.name == "mimxrt595_evk_debug" ||
+       pw_toolchain_SCOPE.name == "mimxrt595_evk_size_optimized" ||
+       pw_toolchain_SCOPE.name == "mimxrt595_evk_speed_optimized")
+  sources = [ "mimxrt595_test.cc" ]
+  deps = [
+    ":pw_digital_io_mcuxpresso",
+    "//targets/mimxrt595_evk:sample_sdk",
+  ]
+}
+
 pw_test_group("tests") {
+  tests = [ ":mimxrt595_test" ]
 }
 
 pw_doc_group("docs") {
diff --git a/pw_digital_io_mcuxpresso/digital_io.cc b/pw_digital_io_mcuxpresso/digital_io.cc
index 4971935..bae7f60 100644
--- a/pw_digital_io_mcuxpresso/digital_io.cc
+++ b/pw_digital_io_mcuxpresso/digital_io.cc
@@ -20,7 +20,7 @@
 #include "fsl_gpio.h"
 #include "fsl_reset.h"
 #include "pw_assert/check.h"
-#include "pw_digital_io_mcuxpresso/digital_io_mcuxpresso.h"
+#include "pw_digital_io_mcuxpresso/digital_io.h"
 #include "pw_status/status.h"
 
 namespace pw::digital_io {
@@ -47,7 +47,7 @@
 pw::Status McuxpressoDigitalOut::DoEnable(bool enable) {
   if (enable) {
     if (is_enabled()) {
-      return pw::Status::FailedPrecondition();
+      return pw::OkStatus();
     }
 
     CLOCK_EnableClock(kGpioClocks[port_]);
diff --git a/pw_digital_io_mcuxpresso/docs.rst b/pw_digital_io_mcuxpresso/docs.rst
index 63eef01..d8bdabf 100644
--- a/pw_digital_io_mcuxpresso/docs.rst
+++ b/pw_digital_io_mcuxpresso/docs.rst
@@ -8,7 +8,7 @@
 
 Setup
 =====
-Use of this module requires setting up the MCUXpresso SDK for use with pigweed. Follow
+Use of this module requires setting up the MCUXpresso SDK for use with Pigweed. Follow
 the steps in :ref:`module-pw_build_mcuxpresso` to create a ``pw_source_set`` for an
 MCUXpresso SDK. Include the GPIO and PINT driver components in this SDK definition.
 
@@ -42,8 +42,8 @@
 
    deps = [ dir_pw_digital_io_mcuxpresso ]
 
-Use
-===
+Examples
+========
 Use ``pw::digital_io::McuxpressoDigitalIn`` and ``pw::digital_io::McuxpressoDigitalOut``
 classes to control GPIO pins.
 
diff --git a/pw_digital_io_mcuxpresso/interrupt_controller.cc b/pw_digital_io_mcuxpresso/interrupt_controller.cc
index 77d064b..4b84022 100644
--- a/pw_digital_io_mcuxpresso/interrupt_controller.cc
+++ b/pw_digital_io_mcuxpresso/interrupt_controller.cc
@@ -29,13 +29,18 @@
 using ::pw::digital_io::InterruptTrigger;
 using ::pw::digital_io::State;
 
+// PINT API doesn't allow context on callback API, so store globally.
 std::array<pw::digital_io::InterruptHandler,
            FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS>
     interrupt_handlers;
+std::array<PINT_Type*, FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS> bases;
 
 void PintCallback(pint_pin_int_t pin, uint32_t) {
   PW_CHECK(pin < interrupt_handlers.size());
-  interrupt_handlers[pin](State::kActive);
+  State state = PINT_PinInterruptGetStatus(bases[pin], pin) == 1
+                    ? State::kActive
+                    : State::kInactive;
+  interrupt_handlers[pin](state);
   SDK_ISR_EXIT_BARRIER;
 }
 
@@ -58,6 +63,7 @@
     return pw::Status::InvalidArgument();
   }
   interrupt_handlers[pin] = std::move(handler);
+  bases[pin] = base_;
   switch (trigger) {
     case InterruptTrigger::kActivatingEdge:
       PINT_PinInterruptConfig(
diff --git a/pw_digital_io_mcuxpresso/mimxrt595_test.cc b/pw_digital_io_mcuxpresso/mimxrt595_test.cc
new file mode 100644
index 0000000..4f81d14
--- /dev/null
+++ b/pw_digital_io_mcuxpresso/mimxrt595_test.cc
@@ -0,0 +1,39 @@
+// Copyright 2023 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 <cstdint>
+
+#include "gtest/gtest.h"
+#include "pw_digital_io/digital_io.h"
+#include "pw_digital_io_mcuxpresso/digital_io.h"
+#include "pw_status/status.h"
+
+namespace pw::digital_io {
+namespace {
+
+constexpr uint32_t kPort = 0;
+constexpr uint32_t kPin = 8;
+
+TEST(DigitalIoTest, SetOk) {
+  McuxpressoDigitalOut out(GPIO, kPort, kPin, pw::digital_io::State::kActive);
+  EXPECT_TRUE(out.SetState(pw::digital_io::State::kInactive).ok());
+}
+
+TEST(DigitalIoTest, GetOk) {
+  McuxpressoDigitalIn in(GPIO, kPort, kPin);
+  EXPECT_TRUE(in.GetState().ok());
+}
+
+}  // namespace
+}  // namespace pw::digital_io
\ No newline at end of file