• 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_mcuxpresso/pint.h"
16 
17 #include <array>
18 #include <cstdint>
19 
20 #include "fsl_pint.h"
21 #include "pw_function/function.h"
22 
23 namespace pw::digital_io {
24 namespace {
25 
26 using ::pw::digital_io::InterruptTrigger;
27 using ::pw::digital_io::State;
28 
29 // PINT API doesn't allow context on callback API, so store globally.
30 std::array<pw::digital_io::InterruptHandler,
31            FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS>
32     interrupt_handlers;
33 std::array<PINT_Type*, FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS> bases;
34 
PintCallback(pint_pin_int_t pin,uint32_t)35 void PintCallback(pint_pin_int_t pin, uint32_t) {
36   PW_CHECK(pin < interrupt_handlers.size());
37   State state = PINT_PinInterruptGetStatus(bases[pin], pin) == 1
38                     ? State::kActive
39                     : State::kInactive;
40   interrupt_handlers[pin](state);
41   SDK_ISR_EXIT_BARRIER;
42 }
43 
44 }  // namespace
45 
46 // McuxpressoPintController
47 
McuxpressoPintController(PINT_Type * base)48 McuxpressoPintController::McuxpressoPintController(PINT_Type* base)
49     : base_(base) {
50   PINT_Init(base_);
51 }
52 
~McuxpressoPintController()53 McuxpressoPintController::~McuxpressoPintController() { PINT_Deinit(base_); }
54 
Config(pint_pin_int_t pin,InterruptTrigger trigger,pw::digital_io::InterruptHandler && handler)55 pw::Status McuxpressoPintController::Config(
56     pint_pin_int_t pin,
57     InterruptTrigger trigger,
58     pw::digital_io::InterruptHandler&& handler) {
59   if (pin >= interrupt_handlers.size()) {
60     return pw::Status::InvalidArgument();
61   }
62   interrupt_handlers[pin] = std::move(handler);
63   bases[pin] = base_;
64   switch (trigger) {
65     case InterruptTrigger::kActivatingEdge:
66       PINT_PinInterruptConfig(
67           base_, pin, kPINT_PinIntEnableRiseEdge, PintCallback);
68       break;
69     case InterruptTrigger::kDeactivatingEdge:
70       PINT_PinInterruptConfig(
71           base_, pin, kPINT_PinIntEnableFallEdge, PintCallback);
72       break;
73     case InterruptTrigger::kBothEdges:
74       PINT_PinInterruptConfig(
75           base_, pin, kPINT_PinIntEnableBothEdges, PintCallback);
76       break;
77     default:
78       return pw::Status::InvalidArgument();
79   }
80   return pw::OkStatus();
81 }
82 
EnableHandler(pint_pin_int_t pin,bool enable)83 pw::Status McuxpressoPintController::EnableHandler(pint_pin_int_t pin,
84                                                    bool enable) {
85   if (enable) {
86     PINT_EnableCallbackByIndex(base_, pin);
87   } else {
88     PINT_DisableCallbackByIndex(base_, pin);
89   }
90   return pw::OkStatus();
91 }
92 
93 // McuxpressoPintInterrupt
94 
McuxpressoPintInterrupt(pw::sync::Borrowable<McuxpressoPintController> & controller,pint_pin_int_t pin)95 McuxpressoPintInterrupt::McuxpressoPintInterrupt(
96     pw::sync::Borrowable<McuxpressoPintController>& controller,
97     pint_pin_int_t pin)
98     : controller_(controller), pin_(pin) {}
99 
DoEnable(bool)100 pw::Status McuxpressoPintInterrupt::DoEnable(bool) {
101   // Can not enabled at individual line level. Only at controller level, which
102   // is always enabled.
103   return pw::OkStatus();
104 }
105 
DoSetInterruptHandler(pw::digital_io::InterruptTrigger trigger,pw::digital_io::InterruptHandler && handler)106 pw::Status McuxpressoPintInterrupt::DoSetInterruptHandler(
107     pw::digital_io::InterruptTrigger trigger,
108     pw::digital_io::InterruptHandler&& handler) {
109   return controller_.acquire()->Config(pin_, trigger, std::move(handler));
110 }
111 
DoEnableInterruptHandler(bool enable)112 pw::Status McuxpressoPintInterrupt::DoEnableInterruptHandler(bool enable) {
113   return controller_.acquire()->EnableHandler(pin_, enable);
114 }
115 
116 }  // namespace pw::digital_io
117