blob: 943a1aa06054d1b331485ef52606076e82298b66 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include "hal/Interrupts.h"
6
7#include <memory>
8
9#include <wpi/SafeThread.h>
10
11#include "DigitalInternal.h"
12#include "HALInitializer.h"
Austin Schuh1e69f942020-11-14 15:06:14 -080013#include "HALInternal.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080014#include "PortsInternal.h"
15#include "hal/ChipObject.h"
16#include "hal/Errors.h"
Austin Schuh1e69f942020-11-14 15:06:14 -080017#include "hal/HALBase.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080018#include "hal/handles/HandlesInternal.h"
19#include "hal/handles/LimitedHandleResource.h"
20
21using namespace hal;
22
23namespace {
Brian Silverman8fce7482020-01-05 13:18:21 -080024
25struct Interrupt {
26 std::unique_ptr<tInterrupt> anInterrupt;
27 std::unique_ptr<tInterruptManager> manager;
Brian Silverman8fce7482020-01-05 13:18:21 -080028};
29
30} // namespace
31
Brian Silverman8fce7482020-01-05 13:18:21 -080032static LimitedHandleResource<HAL_InterruptHandle, Interrupt, kNumInterrupts,
33 HAL_HandleEnum::Interrupt>* interruptHandles;
34
Austin Schuh812d0d12021-11-04 20:16:48 -070035namespace hal::init {
Austin Schuh1e69f942020-11-14 15:06:14 -080036void InitializeInterrupts() {
Brian Silverman8fce7482020-01-05 13:18:21 -080037 static LimitedHandleResource<HAL_InterruptHandle, Interrupt, kNumInterrupts,
38 HAL_HandleEnum::Interrupt>
39 iH;
40 interruptHandles = &iH;
41}
Austin Schuh812d0d12021-11-04 20:16:48 -070042} // namespace hal::init
Brian Silverman8fce7482020-01-05 13:18:21 -080043
44extern "C" {
45
Austin Schuh812d0d12021-11-04 20:16:48 -070046HAL_InterruptHandle HAL_InitializeInterrupts(int32_t* status) {
Brian Silverman8fce7482020-01-05 13:18:21 -080047 hal::init::CheckInit();
48 HAL_InterruptHandle handle = interruptHandles->Allocate();
49 if (handle == HAL_kInvalidHandle) {
50 *status = NO_AVAILABLE_RESOURCES;
51 return HAL_kInvalidHandle;
52 }
53 auto anInterrupt = interruptHandles->Get(handle);
54 uint32_t interruptIndex = static_cast<uint32_t>(getHandleIndex(handle));
55 // Expects the calling leaf class to allocate an interrupt index.
56 anInterrupt->anInterrupt.reset(tInterrupt::create(interruptIndex, status));
57 anInterrupt->anInterrupt->writeConfig_WaitForAck(false, status);
58 anInterrupt->manager = std::make_unique<tInterruptManager>(
Austin Schuh812d0d12021-11-04 20:16:48 -070059 (1u << interruptIndex) | (1u << (interruptIndex + 8u)), true, status);
Brian Silverman8fce7482020-01-05 13:18:21 -080060 return handle;
61}
62
Austin Schuh812d0d12021-11-04 20:16:48 -070063void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle) {
Brian Silverman8fce7482020-01-05 13:18:21 -080064 auto anInterrupt = interruptHandles->Get(interruptHandle);
65 interruptHandles->Free(interruptHandle);
66 if (anInterrupt == nullptr) {
Austin Schuh812d0d12021-11-04 20:16:48 -070067 return;
Brian Silverman8fce7482020-01-05 13:18:21 -080068 }
Brian Silverman8fce7482020-01-05 13:18:21 -080069}
70
71int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle,
72 double timeout, HAL_Bool ignorePrevious,
73 int32_t* status) {
74 uint32_t result;
75 auto anInterrupt = interruptHandles->Get(interruptHandle);
76 if (anInterrupt == nullptr) {
77 *status = HAL_HANDLE_ERROR;
78 return 0;
79 }
80
81 result = anInterrupt->manager->watch(static_cast<int32_t>(timeout * 1e3),
82 ignorePrevious, status);
83
84 // Don't report a timeout as an error - the return code is enough to tell
85 // that a timeout happened.
86 if (*status == -NiFpga_Status_IrqTimeout) {
87 *status = NiFpga_Status_Success;
88 }
89
90 return result;
91}
92
Brian Silverman8fce7482020-01-05 13:18:21 -080093int64_t HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle,
94 int32_t* status) {
95 auto anInterrupt = interruptHandles->Get(interruptHandle);
96 if (anInterrupt == nullptr) {
97 *status = HAL_HANDLE_ERROR;
98 return 0;
99 }
100 uint32_t timestamp = anInterrupt->anInterrupt->readRisingTimeStamp(status);
101 return timestamp;
102}
103
104int64_t HAL_ReadInterruptFallingTimestamp(HAL_InterruptHandle interruptHandle,
105 int32_t* status) {
106 auto anInterrupt = interruptHandles->Get(interruptHandle);
107 if (anInterrupt == nullptr) {
108 *status = HAL_HANDLE_ERROR;
109 return 0;
110 }
111 uint32_t timestamp = anInterrupt->anInterrupt->readFallingTimeStamp(status);
112 return timestamp;
113}
114
115void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle,
116 HAL_Handle digitalSourceHandle,
117 HAL_AnalogTriggerType analogTriggerType,
118 int32_t* status) {
119 auto anInterrupt = interruptHandles->Get(interruptHandle);
120 if (anInterrupt == nullptr) {
121 *status = HAL_HANDLE_ERROR;
122 return;
123 }
124 anInterrupt->anInterrupt->writeConfig_WaitForAck(false, status);
125 bool routingAnalogTrigger = false;
126 uint8_t routingChannel = 0;
127 uint8_t routingModule = 0;
128 bool success =
129 remapDigitalSource(digitalSourceHandle, analogTriggerType, routingChannel,
130 routingModule, routingAnalogTrigger);
131 if (!success) {
132 *status = HAL_HANDLE_ERROR;
133 return;
134 }
135 anInterrupt->anInterrupt->writeConfig_Source_AnalogTrigger(
136 routingAnalogTrigger, status);
137 anInterrupt->anInterrupt->writeConfig_Source_Channel(routingChannel, status);
138 anInterrupt->anInterrupt->writeConfig_Source_Module(routingModule, status);
139}
140
Brian Silverman8fce7482020-01-05 13:18:21 -0800141void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle,
142 HAL_Bool risingEdge, HAL_Bool fallingEdge,
143 int32_t* status) {
144 auto anInterrupt = interruptHandles->Get(interruptHandle);
145 if (anInterrupt == nullptr) {
146 *status = HAL_HANDLE_ERROR;
147 return;
148 }
149 anInterrupt->anInterrupt->writeConfig_RisingEdge(risingEdge, status);
150 anInterrupt->anInterrupt->writeConfig_FallingEdge(fallingEdge, status);
151}
152
Austin Schuh1e69f942020-11-14 15:06:14 -0800153void HAL_ReleaseWaitingInterrupt(HAL_InterruptHandle interruptHandle,
154 int32_t* status) {
155 auto anInterrupt = interruptHandles->Get(interruptHandle);
156 if (anInterrupt == nullptr) {
157 *status = HAL_HANDLE_ERROR;
158 return;
159 }
160
161 uint32_t interruptIndex =
162 static_cast<uint32_t>(getHandleIndex(interruptHandle));
163
164 hal::ReleaseFPGAInterrupt(interruptIndex);
165 hal::ReleaseFPGAInterrupt(interruptIndex + 8);
166}
167
Brian Silverman8fce7482020-01-05 13:18:21 -0800168} // extern "C"