aboutsummaryrefslogtreecommitdiff
path: root/pw_digital_io_mcuxpresso/digital_io.cc
blob: bae7f60bf04cdd1284966474057fe7962b3ccda3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// 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 "pw_digital_io/digital_io.h"

#include <array>

#include "fsl_clock.h"
#include "fsl_gpio.h"
#include "fsl_reset.h"
#include "pw_assert/check.h"
#include "pw_digital_io_mcuxpresso/digital_io.h"
#include "pw_status/status.h"

namespace pw::digital_io {
namespace {

constexpr size_t kRt595ClockNum = 8;
constexpr size_t kRt595ResetNum = 8;

constexpr std::array<clock_ip_name_t, kRt595ClockNum> kGpioClocks = GPIO_CLOCKS;
constexpr std::array<reset_ip_name_t, kRt595ResetNum> kGpioResets = GPIO_RSTS_N;

}  // namespace

McuxpressoDigitalOut::McuxpressoDigitalOut(GPIO_Type* base,
                                           uint32_t port,
                                           uint32_t pin,
                                           pw::digital_io::State initial_state)
    : base_(base), port_(port), pin_(pin), initial_state_(initial_state) {
  PW_CHECK(base != nullptr);
  PW_CHECK(port < kGpioClocks.size());
  PW_CHECK(port < kGpioResets.size());
}

pw::Status McuxpressoDigitalOut::DoEnable(bool enable) {
  if (enable) {
    if (is_enabled()) {
      return pw::OkStatus();
    }

    CLOCK_EnableClock(kGpioClocks[port_]);
    RESET_ClearPeripheralReset(kGpioResets[port_]);

    gpio_pin_config_t config = {
        .pinDirection = kGPIO_DigitalOutput,
        .outputLogic = static_cast<uint8_t>(
            initial_state_ == pw::digital_io::State::kActive ? 1U : 0U),
    };
    GPIO_PinInit(base_, port_, pin_, &config);

  } else {
    // Set to input on disable.
    gpio_pin_config_t config = {
        .pinDirection = kGPIO_DigitalInput,
        .outputLogic = 0,
    };
    GPIO_PinInit(base_, port_, pin_, &config);

    // Can't disable clock as other users on same port may be active.
  }
  enabled_ = enable;
  return pw::OkStatus();
}

pw::Status McuxpressoDigitalOut::DoSetState(pw::digital_io::State state) {
  if (!is_enabled()) {
    return pw::Status::FailedPrecondition();
  }
  GPIO_PinWrite(
      base_, port_, pin_, state == pw::digital_io::State::kActive ? 1 : 0);
  return pw::OkStatus();
}

McuxpressoDigitalIn::McuxpressoDigitalIn(GPIO_Type* base,
                                         uint32_t port,
                                         uint32_t pin)
    : base_(base), port_(port), pin_(pin) {
  PW_CHECK(base != nullptr);
  PW_CHECK(port < kGpioClocks.size());
  PW_CHECK(port < kGpioResets.size());
}

pw::Status McuxpressoDigitalIn::DoEnable(bool enable) {
  if (!enable) {
    enabled_ = enable;
    // Can't disable clock as other users on same port may be active.
    return pw::OkStatus();
  }

  if (is_enabled()) {
    return pw::Status::FailedPrecondition();
  }

  CLOCK_EnableClock(kGpioClocks[port_]);
  RESET_ClearPeripheralReset(kGpioResets[port_]);

  gpio_pin_config_t config = {
      .pinDirection = kGPIO_DigitalInput,
      .outputLogic = 0,
  };
  GPIO_PinInit(base_, port_, pin_, &config);

  enabled_ = enable;
  return pw::OkStatus();
}

pw::Result<pw::digital_io::State> McuxpressoDigitalIn::DoGetState() {
  if (!is_enabled()) {
    return pw::Status::FailedPrecondition();
  }
  uint32_t value = GPIO_PinRead(base_, port_, pin_);
  return value == 1 ? pw::digital_io::State::kActive
                    : pw::digital_io::State::kInactive;
}

}  // namespace pw::digital_io