1 /*
2  * Copyright (c) 2023-2024, 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 #include <stdint.h>
34 #include <string.h>
35 
36 #include <ti/devices/DeviceFamily.h>
37 
38 #include <ti/drivers/rcl/RCL.h>
39 #include <ti/drivers/rcl/commands/adc_noise.h>
40 
41 #include <ti/drivers/Power.h>
42 
43 #include DeviceFamily_constructPath(inc/hw_lrfddbell.h)
44 #include DeviceFamily_constructPath(inc/pbe_common_ram_regs.h)
45 
46 extern const LRF_Config LRF_configAdcNoise;
47 
48 /* Place necessary RCL structs in BUFRAM to avoid using static SYSRAM. This saves 148 B */
49 /* Note that we need to skip the part of the BUFRAM used by common RAM variables, as they
50   may be written by the RCL */
51 #define PBE_COMMON_RAM_REGISTER_END_OFFSET     32UL
52 /* We know that the PBE_COMMON_RAM_FIFOCMDADD register is used by the LRF setup, so at least make sure that this is covered */
53 #if (PBE_COMMON_RAM_FIFOCMDADD_ADR >= (BUF_RAM_BASE_ADDR + PBE_COMMON_RAM_REGISTER_END_OFFSET))
54 #error "BUFRAM memory used by ADC noise wrapper overlaps initialized RAM variable"
55 #endif
56 
57 #define RCL_CLIENT_ADDR     (BUF_RAM_BASE_ADDR + PBE_COMMON_RAM_REGISTER_END_OFFSET)
58 #define RCL_ADC_NOISE_CMD_ADDR   (RCL_CLIENT_ADDR + sizeof(RCL_Client))
59 #define CALLBACK_ADDR       (RCL_ADC_NOISE_CMD_ADDR + sizeof(RCL_CmdAdcNoiseGet))
60 
61 #define RCL_CLIENT_PTR      ((RCL_Client*)RCL_CLIENT_ADDR)
62 #define RCL_ADC_NOISE_CMD_PTR    ((RCL_CmdAdcNoiseGet*)RCL_ADC_NOISE_CMD_ADDR)
63 #define CALLBACK_PTR        ((applicationCallback_t*)CALLBACK_ADDR)
64 
65 #define STATUS_SUCCESS 0
66 #define STATUS_ERROR -1
67 #define RCL_STATUS_TO_WRAPPER_STATUS(x) ((x) == RCL_CommandStatus_Finished ? STATUS_SUCCESS : STATUS_ERROR)
68 
69 /* Callback function type */
70 typedef void (*applicationCallback_t)(uint32_t* buffer, uint32_t numWords, int_fast16_t status);
71 
72 /******************************************************************************
73  * Internal callback function
74  ******************************************************************************/
adcNoiseCallback(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEvents)75 static void adcNoiseCallback(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEvents)
76 {
77     RCL_CmdAdcNoiseGet *adcCmd = (RCL_CmdAdcNoiseGet *)cmd;
78 
79     applicationCallback_t callback = *CALLBACK_PTR;
80 
81     callback(adcCmd->output, adcCmd->numWords, RCL_STATUS_TO_WRAPPER_STATUS(cmd->status));
82 
83     /* Close the RCL client */
84     RCL_close(cmd->runtime.client);
85 
86     /* This must come after closing because command and client structs are in BUFRAM */
87     Power_releaseDependency(PowerLPF3_PERIPH_LRFD_BUFRAM);
88 
89     /* Release power constraint to allow standby */
90     hal_power_release_constraint();
91 }
92 
93 /******************************************************************************
94  * Public API
95  ******************************************************************************/
96 
97 
98 /*
99  *  ======== RCL_AdcNoise_get_samples_blocking ========
100  */
RCL_AdcNoise_get_samples_blocking(uint32_t * buffer,uint32_t numWords)101 int_fast16_t RCL_AdcNoise_get_samples_blocking(uint32_t* buffer, uint32_t numWords)
102 {
103     RCL_CommandStatus status;
104     RCL_CmdAdcNoiseGet *adcNoiseCmd = RCL_ADC_NOISE_CMD_PTR;
105 
106     /* Turn on BUFRAM before calling RCL_open, since the RCL_client resides in BUFRAM */
107     Power_setDependency(PowerLPF3_PERIPH_LRFD_BUFRAM);
108 
109     /* Prevent the system from going to standby because BUFRAM doesn't have retention */
110     hal_power_set_constraint();
111 
112     RCL_init();
113 
114     /* Open client and provide settings */
115     RCL_Handle h = RCL_open(RCL_CLIENT_PTR, &LRF_configAdcNoise);
116 
117     *adcNoiseCmd = RCL_CmdAdcNoiseGet_Default();
118 
119     /* Set number of sample words */
120     adcNoiseCmd->numWords = numWords;
121     adcNoiseCmd->output = buffer;
122 
123     /* Submit the command */
124     status = RCL_Command_submit(h, adcNoiseCmd);
125 
126     if (status <= RCL_CommandStatus_Finished)
127     {
128         /* Wait for the command to finish. The thread will yield and other threads can run. */
129         status = RCL_Command_pend(adcNoiseCmd);
130     }
131 
132     /* Close the RCL client */
133     RCL_close(h);
134 
135     /* This must come after closing because command and client structs are in BUFRAM */
136     Power_releaseDependency(PowerLPF3_PERIPH_LRFD_BUFRAM);
137 
138     /* Release power constraint to allow standby */
139     hal_power_release_constraint();
140 
141     return RCL_STATUS_TO_WRAPPER_STATUS(status);
142 }
143 
144 /*
145  *  ======== RCL_AdcNoise_get_samples_callback ========
146  *
147  *  NOTE: This function must be called from a task context, with interrupts enabled
148  */
RCL_AdcNoise_get_samples_callback(uint32_t * buffer,uint32_t numWords,applicationCallback_t callback)149 int_fast16_t RCL_AdcNoise_get_samples_callback(uint32_t* buffer, uint32_t numWords, applicationCallback_t callback)
150 {
151     RCL_CommandStatus status;
152     RCL_CmdAdcNoiseGet *adcNoiseCmd = RCL_ADC_NOISE_CMD_PTR;
153 
154     /* Turn on BUFRAM before calling RCL_open, since the RCL_client resides in BUFRAM */
155     Power_setDependency(PowerLPF3_PERIPH_LRFD_BUFRAM);
156 
157     /* Prevent the system from going to standby because BUFRAM doesn't have retention */
158     hal_power_set_constraint();
159 
160     RCL_init();
161 
162     /* Open client and provide settings */
163     RCL_Handle h = RCL_open(RCL_CLIENT_PTR, &LRF_configAdcNoise);
164 
165     *adcNoiseCmd = RCL_CmdAdcNoiseGet_Default();
166 
167     /* Set number of sample words */
168     adcNoiseCmd->numWords = numWords;
169     adcNoiseCmd->output = buffer;
170 
171     /* Set callback function to be run at the end of the command */
172     adcNoiseCmd->common.runtime.callback = adcNoiseCallback;
173 
174     *CALLBACK_PTR = callback;
175 
176     /* Run callback at the end of the command only */
177     adcNoiseCmd->common.runtime.rclCallbackMask.value = RCL_EventLastCmdDone.value;
178 
179     /* Submit the command */
180     status = RCL_Command_submit(h, adcNoiseCmd);
181 
182     return RCL_STATUS_TO_WRAPPER_STATUS(status);
183 }
184