1 /*
2 * Copyright (c) 2020-2023, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef ti_drivers_RCL_Command_h__include
34 #define ti_drivers_RCL_Command_h__include
35
36 #include <stdint.h>
37 #include <stdbool.h>
38
39 #include <ti/drivers/rcl/RCL_Types.h>
40 #include <ti/drivers/rcl/RCL_Event.h>
41 #include <ti/drivers/rcl/LRF.h>
42
43 /**
44 * @brief Command handler function type
45 */
46 typedef RCL_Events (*RCL_CommandHandler)(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEvents);
47
48 /**
49 * @brief Callback function type
50 */
51 typedef void (*RCL_Callback)(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEvents);
52
53 /**
54 * @brief Command runtime structure
55 *
56 * Holds information on running the command
57 */
58 struct RCL_CommandRuntime_s {
59 RCL_CommandHandler handler; /*!< Command handler to use for this command */
60 RCL_Client *client; /*!< Client */
61 LRF_Events lrfCallbackMask; /*!< Callbacks enabled for events directly from LRF */
62 RCL_Events rclCallbackMask; /*!< Callbacks enabled for events generated in RCL */
63 RCL_Callback callback; /*!< Callback function */
64 };
65
66 /**
67 * @brief Command timing structure
68 *
69 * Holds information on the timing of the command
70 */
71 struct RCL_CommandTiming_s {
72 uint32_t absStartTime; /*!< Unless timing is Schedule_Now: Start time of the command on SYSTIM (0.25 us steps) */
73 uint32_t relMinTime; /*!< For scheduler: Minimum time command must be allowed to run (0.25 us steps). Not supported in this version. */
74 int32_t relGracefulStopTime; /*!< Time to initiate graceful stop of command. If negative: Relative to hardStopTime, otherwise relative to startTime (0.25 us steps). 0: Not used */
75 uint32_t relHardStopTime; /*!< Time to stop the command as soon as possible; relative to start time (0.25 us steps). 0: Not used. */
76 };
77
78 /**
79 * @brief Command status
80 *
81 * Gives information on the command, and if finished, how it finished.
82 */
83 typedef enum RCL_CommandStatus_e {
84 RCL_CommandStatus_Idle = 0, /*!< Command is not yet run. This state is mandatory when submitting. */
85 RCL_CommandStatus_Queued, /*!< Command is queued, but pending end of previous command */
86 RCL_CommandStatus_Scheduled, /*!< Command is scheduled, pending start time. */
87 RCL_CommandStatus_Active, /*!< Command is currently running. */
88 RCL_CommandStatus_Suspended, /*!< Command is suspended and will resume once the othe running commands have finished */
89 RCL_CommandStatus_Deferred, /*!< Command is deferred. */
90 RCL_CommandStatus_Finished = 0x10, /*!< Command has finished normally */
91 RCL_CommandStatus_ChannelIdle, /*!< Channel assessment has finished with channel idle */
92 RCL_CommandStatus_ChannelBusy, /*!< Channel assessment has finished with channel busy */
93 RCL_CommandStatus_RxTimeout, /*!< Command timed out waiting for sync */
94 RCL_CommandStatus_NoSync, /*!< Command timed out waiting for a returned packet from peer device */
95 RCL_CommandStatus_RxErr, /*!< Command ended due to errors with the received packet (e.g, CRC errors) */
96 RCL_CommandStatus_RejectedStart, /*!< Command was rejected start due to scheduling parameters */
97 RCL_CommandStatus_UnexpectedMdrRx, /*!< Command ended because an MDR packet was received when we have MDR disabled */
98 RCL_CommandStatus_DescheduledApi = 0x31, /*!< Command was descheduled before starting running in the radio because stop API was called */
99 RCL_CommandStatus_DescheduledScheduling, /*!< Command was descheduled before starting running in the radio due to scheduling of another command */
100 RCL_CommandStatus_GracefulStopTimeout = 0x34, /*!< Command ended because graceful stop time was reached */
101 RCL_CommandStatus_GracefulStopApi, /*!< Command ended because stop API was called with RCL_StopType_Graceful argument */
102 RCL_CommandStatus_GracefulStopScheduling, /*!< Command ended due to scheduling where interrupting command had RCL_ConflictPolicy_Polite */
103 RCL_CommandStatus_HardStopTimeout = 0x38, /*!< Command ended because hard stop time was reached */
104 RCL_CommandStatus_HardStopApi, /*!< Command ended because stop API was called with RCL_StopType_Hard argument */
105 RCL_CommandStatus_HardStopScheduling, /*!< Command ended due to scheduling where interrupting command had RCL_ConflictPolicy_AlwaysInterrupt */
106 RCL_CommandStatus_Connect = 0x40, /*!< Command has finished and a connection may be established (BLE5 advertiser and initiator) */
107 RCL_CommandStatus_MaxNak, /*!< Command ended because more subsequent NAKs than supported were received (BLE5) */
108 RCL_CommandStatus_MaxAuxWaitTimeExceeded, /*!< Command ended because the wait time for a new packet following an AuxPtr was exceeded (BLE5 scanner and initiator) */
109 RCL_CommandStatus_Error = 0x80, /*!< Command ended with unknown error */
110 RCL_CommandStatus_Error_Setup, /*!< Command ended because of an error in the setup */
111 RCL_CommandStatus_Error_Param, /*!< Command ended because of an error with a parameter */
112 RCL_CommandStatus_Error_MissingTxBuffer, /*!< Command ended because no TX buffer was available when required */
113 RCL_CommandStatus_Error_TxBufferCorruption, /*!< Command ended because of errors in TX buffer structure */
114 RCL_CommandStatus_Error_RxBufferCorruption, /*!< Command ended because of errors in RX buffer structure */
115 RCL_CommandStatus_Error_StartTooLate, /*!< Command ended because start time was in the past */
116 RCL_CommandStatus_Error_TxFifo, /*!< Command ended because of underflow of TX FIFO */
117 RCL_CommandStatus_Error_RxFifo, /*!< Command ended because of unsupported overflow of RX FIFO (no buffer to store packets) */
118 RCL_CommandStatus_Error_Synth, /*!< Command ended because of synth programming error */
119 RCL_CommandStatus_Error_UnknownOp, /*!< Command ended because radio did not recognize command; probably wrong image for given command */
120 RCL_CommandStatus_Error_AlreadySubmitted, /*!< Command is already submitted and planned or running and can't be submitted again without calling stop first */
121 RCL_CommandStatus_Error_CommandQueueFull /*!< Command was not submitted because there is no space in the pending commands queue */
122 } RCL_CommandStatus;
123
124 /**
125 * Helper macros to compare command status
126 */
127 #define RCL_CommandStatus_isAnyStop(x) (((x) >= RCL_CommandStatus_DescheduledApi) && ((x) <= RCL_CommandStatus_HardStopScheduling))
128 #define RCL_CommandStatus_isAnyDescheduled(x) (((x) >= RCL_CommandStatus_DescheduledApi) && ((x) <= RCL_CommandStatus_DescheduledScheduling))
129 #define RCL_CommandStatus_isAnyGracefulStop(x) (((x) >= RCL_CommandStatus_GracefulStopTimeout) && ((x) <= RCL_CommandStatus_GracefulStopScheduling))
130 #define RCL_CommandStatus_isAnyHardStop(x) (((x) >= RCL_CommandStatus_HardStopTimeout) && ((x) <= RCL_CommandStatus_HardStopScheduling))
131 #define RCL_CommandStatus_isAnyTimeoutStop(x) (((x) == RCL_CommandStatus_GracefulStopTimeout) || ((x) == RCL_CommandStatus_HardStopTimeout))
132 #define RCL_CommandStatus_isAnyApiStop(x) (((x) == RCL_CommandStatus_DescheduledApi) || ((x) == RCL_CommandStatus_GracefulStopApi) || ((x) == RCL_CommandStatus_HardStopApi))
133 #define RCL_CommandStatus_isAnySchedulingStop(x) (((x) == RCL_CommandStatus_DescheduledScheduling) || ((x) == RCL_CommandStatus_GracefulStopScheduling) || ((x) == RCL_CommandStatus_HardStopScheduling))
134
135 /**
136 * @brief Stop types
137 *
138 * Type of stop to perform
139 */
140 typedef enum {
141 RCL_StopType_None = 0, /*!< No stop requested */
142 RCL_StopType_DescheduleOnly, /*!< Stop a command that is queued or pending start, but do not stop it from running */
143 RCL_StopType_Graceful, /*!< Stop the command gracefully, that is finish a packet or transaction in progress before ending */
144 RCL_StopType_Hard, /*!< Stop the command as soon as possible */
145 } RCL_StopType;
146
147 /**
148 * @brief Schedule type
149 *
150 * The type of scheduling used for a command
151 */
152 typedef enum {
153 RCL_Schedule_Now = 0, /*!< Schedule the command to start as soon as possible */
154 RCL_Schedule_AbsTime = 1, /*!< Schedule command to start at a given time; give error if delays occur */
155 } RCL_ScheduleType;
156
157 /**
158 * @brief Conflict resolution policy
159 *
160 * How will this command interact with an already running and overlapping command
161 */
162 typedef enum {
163 RCL_ConflictPolicy_AlwaysInterrupt = 0, /*!< Always stop a running command if necessary to run this command */
164 RCL_ConflictPolicy_Polite = 1, /*!< Stop a running command unless it is communicating, i.e. transmitting or is actively receiving */
165 RCL_ConflictPolicy_NeverInterrupt = 2, /*!< Never stop an ongoing command */
166 } RCL_ConflictPolicy;
167
168 /**
169 * @brief General command
170 *
171 * Fields common for all commands
172 */
173 struct RCL_Command_s {
174 uint16_t cmdId; /*!< Command ID */
175 uint16_t phyFeatures; /*!< PHY feature selector; use 0 if only one PHY */
176 RCL_ScheduleType scheduling : 8; /*!< Scheduling type */
177 RCL_CommandStatus status : 8; /*!< Status of command */
178 RCL_ConflictPolicy conflictPolicy : 8; /*!< Conflict resolution policy */
179 bool allowDelay; /*!< Start may be delayed */
180 RCL_CommandRuntime runtime; /*!< Runtime information */
181 RCL_CommandTiming timing; /*!< Timing information */
182 };
183
184 #define RCL_Command_Default(_id, _handler) \
185 { \
186 .cmdId = _id, \
187 .phyFeatures = 0, \
188 .scheduling = RCL_Schedule_Now, \
189 .status = RCL_CommandStatus_Idle, \
190 .conflictPolicy = RCL_ConflictPolicy_AlwaysInterrupt, \
191 .allowDelay = false, \
192 .runtime = { \
193 .handler = _handler, \
194 }, \
195 .timing = { \
196 .absStartTime = 0, \
197 .relGracefulStopTime = 0, \
198 .relHardStopTime = 0, \
199 }, \
200 }
201 #define RCL_Command_DefaultRuntime(_id, _handler) (RCL_Command) RCL_Command_Default(_id, _handler)
202
203 /**
204 * @brief Type for TX power
205 *
206 * The wanted TX power to program; the RCL will select the highest available power smaller than or
207 * equal to the requested setting.
208 *
209 * Special settings:
210 * %LRF_TxPower_Use_Min: Use minimum available TX power
211 * %LRF_TxPower_Use_Max: Use maximum available TX power
212 * %LRF_TxPower_Use_Raw: Use a raw TX power register setting given with %RCL_Command_setRawTxPower()
213 * %LRF_TxPower_None: Do not write TX power
214 */
215 typedef LRF_TxPowerTable_Index RCL_Command_TxPower;
216
217 /**
218 * @brief Set raw TX power
219 *
220 * Set the TX power to be written directly into the TX power register applicable to the chip.
221 * The setting only applies to commands where the TX power is set to %LRF_TxPower_Use_Raw
222 */
RCL_Command_setRawTxPower(uint32_t registerSetting,uint32_t temperatureCoefficient)223 static inline void RCL_Command_setRawTxPower(uint32_t registerSetting, uint32_t temperatureCoefficient)
224 {
225 LRF_setRawTxPower(registerSetting, temperatureCoefficient);
226 }
227
228 #endif /* ti_drivers_RCL_Command_h__include */
229