• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_digital_io/digital_io.h"
16 
17 #include <array>
18 
19 #include "fsl_clock.h"
20 #include "fsl_gpio.h"
21 #include "fsl_reset.h"
22 #include "pw_assert/check.h"
23 #include "pw_digital_io_mcuxpresso/digital_io.h"
24 #include "pw_status/status.h"
25 
26 namespace pw::digital_io {
27 namespace {
28 
29 constexpr std::array kGpioClocks = GPIO_CLOCKS;
30 constexpr std::array kGpioResets = GPIO_RSTS_N;
31 
32 }  // namespace
33 
McuxpressoDigitalOut(GPIO_Type * base,uint32_t port,uint32_t pin,pw::digital_io::State initial_state)34 McuxpressoDigitalOut::McuxpressoDigitalOut(GPIO_Type* base,
35                                            uint32_t port,
36                                            uint32_t pin,
37                                            pw::digital_io::State initial_state)
38     : base_(base), port_(port), pin_(pin), initial_state_(initial_state) {
39   PW_CHECK(base != nullptr);
40   PW_CHECK(port < kGpioClocks.size());
41   PW_CHECK(port < kGpioResets.size());
42 }
43 
DoEnable(bool enable)44 pw::Status McuxpressoDigitalOut::DoEnable(bool enable) {
45   if (enable) {
46     if (is_enabled()) {
47       return pw::OkStatus();
48     }
49 
50     CLOCK_EnableClock(kGpioClocks[port_]);
51     RESET_ClearPeripheralReset(kGpioResets[port_]);
52 
53     gpio_pin_config_t config = {
54         .pinDirection = kGPIO_DigitalOutput,
55         .outputLogic = static_cast<uint8_t>(
56             initial_state_ == pw::digital_io::State::kActive ? 1U : 0U),
57     };
58     GPIO_PinInit(base_, port_, pin_, &config);
59 
60   } else {
61     // Set to input on disable.
62     gpio_pin_config_t config = {
63         .pinDirection = kGPIO_DigitalInput,
64         .outputLogic = 0,
65     };
66     GPIO_PinInit(base_, port_, pin_, &config);
67 
68     // Can't disable clock as other users on same port may be active.
69   }
70   enabled_ = enable;
71   return pw::OkStatus();
72 }
73 
DoSetState(pw::digital_io::State state)74 pw::Status McuxpressoDigitalOut::DoSetState(pw::digital_io::State state) {
75   if (!is_enabled()) {
76     return pw::Status::FailedPrecondition();
77   }
78   GPIO_PinWrite(
79       base_, port_, pin_, state == pw::digital_io::State::kActive ? 1 : 0);
80   return pw::OkStatus();
81 }
82 
McuxpressoDigitalIn(GPIO_Type * base,uint32_t port,uint32_t pin)83 McuxpressoDigitalIn::McuxpressoDigitalIn(GPIO_Type* base,
84                                          uint32_t port,
85                                          uint32_t pin)
86     : base_(base), port_(port), pin_(pin) {
87   PW_CHECK(base != nullptr);
88   PW_CHECK(port < kGpioClocks.size());
89   PW_CHECK(port < kGpioResets.size());
90 }
91 
DoEnable(bool enable)92 pw::Status McuxpressoDigitalIn::DoEnable(bool enable) {
93   if (!enable) {
94     enabled_ = enable;
95     // Can't disable clock as other users on same port may be active.
96     return pw::OkStatus();
97   }
98 
99   if (is_enabled()) {
100     return pw::Status::FailedPrecondition();
101   }
102 
103   CLOCK_EnableClock(kGpioClocks[port_]);
104   RESET_ClearPeripheralReset(kGpioResets[port_]);
105 
106   gpio_pin_config_t config = {
107       .pinDirection = kGPIO_DigitalInput,
108       .outputLogic = 0,
109   };
110   GPIO_PinInit(base_, port_, pin_, &config);
111 
112   enabled_ = enable;
113   return pw::OkStatus();
114 }
115 
DoGetState()116 pw::Result<pw::digital_io::State> McuxpressoDigitalIn::DoGetState() {
117   if (!is_enabled()) {
118     return pw::Status::FailedPrecondition();
119   }
120   uint32_t value = GPIO_PinRead(base_, port_, pin_);
121   return value == 1 ? pw::digital_io::State::kActive
122                     : pw::digital_io::State::kInactive;
123 }
124 
125 }  // namespace pw::digital_io
126