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