PIC24 Support Libraries
esos_sensor.c
1 /*
2  * "Copyright (c) 2013 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 #include "esos_sensor.h"
31 #include <esos.h>
32 #include <stdlib.h>
33 
34 /**
35 * Waits until a sensor is available.
36 *
37 * \param e_senCh enumeration to select sensor channel
38 * \param e_senVRef enumeration to select sensor voltage reference
39 *
40 * \hideinitializer
41 */
42 ESOS_CHILD_TASK(_WAIT_ON_AVAILABLE_SENSOR, esos_sensor_ch_t e_senCh, esos_sensor_vref_t e_senVRef)
43 {
45 
46  // Wait for and then grab the ADC.
47  ESOS_TASK_WAIT_WHILE(__esos_IsSystemFlagSet(__ESOS_SYS_ADC_IS_BUSY));
48  __esos_SetSystemFlag(__ESOS_SYS_ADC_IS_BUSY);
49 
50  esos_sensor_config_hw(e_senCh, e_senVRef);
51 
52  ESOS_TASK_END();
53 }
54 
55 /**
56 * Waits until a sensor is read (quick version).
57 *
58 * \param pu16_data pointer to the location of the resulting data
59 *
60 * \hideinitializer
61 */
62 ESOS_CHILD_TASK(_WAIT_SENSOR_QUICK_READ, uint16_t* pu16_data)
63 {
65 
66  esos_sensor_initiate_hw();
68  *pu16_data = esos_sensor_getvalue_u16_hw();
69 
70  ESOS_TASK_END();
71 }
72 
73 /**
74 * Compares two data values
75 *
76 * \param pv_a pointer to the first value in comparison
77 * \param pv_b pointer to the second value in comparison
78 *
79 * \hideinitializer
80 */
81 int compareUint16(const void *pv_a, const void *pv_b)
82 {
83  return *((uint16_t*)pv_a) - *((uint16_t*)pv_b);
84 }
85 
86 /**
87 * Finds the median of a buffer of data
88 *
89 * \param pu16_buf pointer to the buffer
90 * \param u8_nelem number of elements in the buffer
91 *
92 * \hideinitializer
93 */
94 uint16_t medianOfBuffer(uint16_t *pu16_buf, uint8_t u8_nelem)
95 {
96  qsort(pu16_buf, u8_nelem, sizeof(uint16_t), compareUint16);
97 
98  // Always assumes buflen is even, and that the inputs are max 12 bit!
99  return (pu16_buf[u8_nelem / 2 - 1] + pu16_buf[u8_nelem / 2]) / 2;
100 }
101 
102 /**
103 * Finds the maximum value of a buffer of data
104 *
105 * \param pu16_buf pointer to the buffer
106 * \param u8_nelem number of elements in the buffer
107 *
108 * \hideinitializer
109 */
110 uint16_t maxOfBuffer(uint16_t *pu16_buf, uint8_t u8_nelem)
111 {
112  uint16_t max = 0;
113  uint8_t i = 0;
114 
115  for(;i<u8_nelem;i++){
116  if(max < pu16_buf[i]){
117  max = pu16_buf[i];
118  }
119  }
120  return max;
121 }
122 
123 /**
124 * Waits until a sensor is read (extended version).
125 *
126 * \param pu16_data pointer to the resultant data
127 * \param e_senProcess enumeration of type of processing to be completed
128 * \param e_senFMT enumeration of the format of the resultant data
129 *
130 * \hideinitializer
131 */
132 ESOS_CHILD_TASK(_WAIT_SENSOR_READ, uint16_t* pu16_data, uint8_t e_senProcess, esos_sensor_format_t e_senFMT)
133 {
134  ESOS_TASK_BEGIN();
135 
136  static uint8_t FMT_CONSTANT;
137  static uint8_t vRef;
138 
139  static uint16_t au16_dataArr[64] = {0};
140  static uint8_t arrayCount = 0;
141  uint16_t u16_oneShot = *pu16_data;
142  static uint32_t u32_algData;
143 
144  arrayCount = 0;
145  u32_algData = 0;
146  //Decompose e_senFMT to determine Vref and Format Constant
147  FMT_CONSTANT = e_senFMT & 0b11110000;
148  vRef = e_senFMT & 0b00001111;
149 
150  //2 Samples
151  if((e_senProcess & 0b00001111) == 1){
152  while(arrayCount < 2){
153  esos_sensor_initiate_hw();
155  au16_dataArr[arrayCount++] = esos_sensor_getvalue_u16_hw();
156  }
157  }
158  //4 Samples
159  else if((e_senProcess & 0b00001111) == 2){
160  while(arrayCount < 4){
161  esos_sensor_initiate_hw();
163  au16_dataArr[arrayCount++] = esos_sensor_getvalue_u16_hw();
164  }
165  }
166  //8 Samples
167  else if((e_senProcess & 0b00001111) == 3){
168  while(arrayCount < 8){
169  esos_sensor_initiate_hw();
171  au16_dataArr[arrayCount++] = esos_sensor_getvalue_u16_hw();
172  }
173  }
174  //16 Samples
175  else if((e_senProcess & 0b00001111) == 4){
176  while(arrayCount < 16){
177  esos_sensor_initiate_hw();
179  au16_dataArr[arrayCount++] = esos_sensor_getvalue_u16_hw();
180  }
181  }
182  //32 Samples
183  else if((e_senProcess & 0b00001111) == 5){
184  while(arrayCount < 32){
185  esos_sensor_initiate_hw();
187  au16_dataArr[arrayCount++] = esos_sensor_getvalue_u16_hw();
188  }
189  }
190  //64 Samples
191  else if((e_senProcess & 0b00001111) == 6){
192  while(arrayCount < 64){
193  esos_sensor_initiate_hw();
195  au16_dataArr[arrayCount++] = esos_sensor_getvalue_u16_hw();
196  }
197  }
198 
199  //Reset *pu16_data to zero since everything is now in the array
200  *pu16_data = 0;
201  arrayCount = 0; // resetting to zero before reusing in process algorithms.
202 
203 
204 
205  //Do Nothing
206  if(e_senProcess == ESOS_SENSOR_ONE_SHOT){
207  esos_sensor_initiate_hw();
209  *pu16_data = esos_sensor_getvalue_u16_hw();
210  }
211  //Average
212  else if(e_senProcess == ESOS_SENSOR_AVG2){
213  while(arrayCount < 2){
214  u32_algData += au16_dataArr[arrayCount];
215  arrayCount ++;
216  }
217  u32_algData = u32_algData/arrayCount;
218  *pu16_data = (uint16_t)u32_algData;
219  }
220  else if(e_senProcess == ESOS_SENSOR_AVG4){
221  while(arrayCount < 4){
222  u32_algData += au16_dataArr[arrayCount];
223  arrayCount ++;
224  }
225  u32_algData = u32_algData/arrayCount;
226  *pu16_data = (uint16_t)u32_algData;
227  }
228  else if(e_senProcess == ESOS_SENSOR_AVG8){
229  while(arrayCount < 8){
230  u32_algData += au16_dataArr[arrayCount];
231  arrayCount ++;
232  }
233  u32_algData = u32_algData/arrayCount;
234  *pu16_data = (uint16_t)u32_algData;
235  }
236  else if(e_senProcess == ESOS_SENSOR_AVG16){
237  while(arrayCount < 16){
238  u32_algData += au16_dataArr[arrayCount];
239  arrayCount ++;
240  }
241  u32_algData = u32_algData/arrayCount;
242  *pu16_data = (uint16_t)u32_algData;
243  }
244  else if(e_senProcess == ESOS_SENSOR_AVG32){
245  while(arrayCount < 32){
246  u32_algData += au16_dataArr[arrayCount];
247  arrayCount ++;
248  }
249  u32_algData = u32_algData/arrayCount;
250  *pu16_data = (uint16_t)u32_algData;
251  }
252  else if(e_senProcess == ESOS_SENSOR_AVG64){
253  while(arrayCount < 64){
254  u32_algData += au16_dataArr[arrayCount];
255  arrayCount ++;
256  }
257  u32_algData = u32_algData/arrayCount;
258  *pu16_data = (uint16_t)u32_algData;
259  }
260  //Minimum
261  else if(e_senProcess == ESOS_SENSOR_MIN2){
262  *pu16_data = MAX16BIT; // default to maximum 16 bit value.
263  while(arrayCount < 2){
264  if (au16_dataArr[arrayCount] < *pu16_data){
265  *pu16_data = au16_dataArr[arrayCount];
266  }
267  arrayCount ++;
268  }
269  }
270  else if(e_senProcess == ESOS_SENSOR_MIN4){
271  *pu16_data = MAX16BIT; // default to maximum 16 bit value.
272  while(arrayCount < 4){
273  if (au16_dataArr[arrayCount] < *pu16_data){
274  *pu16_data = au16_dataArr[arrayCount];
275  }
276  arrayCount ++;
277  }
278  }
279  else if(e_senProcess == ESOS_SENSOR_MIN8){
280  *pu16_data = MAX16BIT; // default to maximum 16 bit value.
281  while(arrayCount < 8){
282  if (au16_dataArr[arrayCount] < *pu16_data){
283  *pu16_data = au16_dataArr[arrayCount];
284  }
285  arrayCount ++;
286  }
287  }
288  else if(e_senProcess == ESOS_SENSOR_MIN16){
289  *pu16_data = MAX16BIT; // default to maximum 16 bit value.
290  while(arrayCount < 16){
291  if (au16_dataArr[arrayCount] < *pu16_data){
292  *pu16_data = au16_dataArr[arrayCount];
293  }
294  arrayCount ++;
295  }
296  }
297  else if(e_senProcess == ESOS_SENSOR_MIN32){
298  *pu16_data = MAX16BIT; // default to maximum 16 bit value.
299  while(arrayCount < 32){
300  if (au16_dataArr[arrayCount] < *pu16_data){
301  *pu16_data = au16_dataArr[arrayCount];
302  }
303  arrayCount ++;
304  }
305  }
306  else if(e_senProcess == ESOS_SENSOR_MIN64){
307  *pu16_data = MAX16BIT; // default to maximum 16 bit value.
308  while(arrayCount < 64){
309  if (au16_dataArr[arrayCount] < *pu16_data){
310  *pu16_data = au16_dataArr[arrayCount];
311  }
312  arrayCount ++;
313  }
314  }
315  //Maximum
316  else if(e_senProcess == ESOS_SENSOR_MAX2){
317  *pu16_data = maxOfBuffer(au16_dataArr, 2);
318  }
319  else if(e_senProcess == ESOS_SENSOR_MAX4){
320  *pu16_data = maxOfBuffer(au16_dataArr, 4);
321  }
322  else if(e_senProcess == ESOS_SENSOR_MAX8){
323  *pu16_data = maxOfBuffer(au16_dataArr, 8);
324  }
325  else if(e_senProcess == ESOS_SENSOR_MAX16){
326  *pu16_data = maxOfBuffer(au16_dataArr, 16);
327  }
328  else if(e_senProcess == ESOS_SENSOR_MAX32){
329  *pu16_data = maxOfBuffer(au16_dataArr, 32);
330  }
331  else if(e_senProcess == ESOS_SENSOR_MAX64){
332  *pu16_data = maxOfBuffer(au16_dataArr, 64);
333  }
334  //Median
335  else if(e_senProcess == ESOS_SENSOR_MEDIAN2){
336  *pu16_data = medianOfBuffer(au16_dataArr, 2);
337  }
338  else if(e_senProcess == ESOS_SENSOR_MEDIAN4){
339  *pu16_data = medianOfBuffer(au16_dataArr, 4);
340  }
341  else if(e_senProcess == ESOS_SENSOR_MEDIAN8){
342  *pu16_data = medianOfBuffer(au16_dataArr, 8);
343  }
344  else if(e_senProcess == ESOS_SENSOR_MEDIAN16){
345  *pu16_data = medianOfBuffer(au16_dataArr, 16);
346  }
347  else if(e_senProcess == ESOS_SENSOR_MEDIAN32){
348  *pu16_data = medianOfBuffer(au16_dataArr, 32);
349  }
350  else if(e_senProcess == ESOS_SENSOR_MEDIAN64){
351  *pu16_data = medianOfBuffer(au16_dataArr, 64);
352  }
353  else{}
354 
355  //Export as Voltage
356  if(FMT_CONSTANT & ESOS_SENSOR_FORMAT_VOLTAGE){
357  const uint32_t u32_maxDeciMilliVolts =
358  vRef == ESOS_SENSOR_VREF_1V0 ? 10000
359  : vRef == ESOS_SENSOR_VREF_1V024 ? 10240
360  : vRef == ESOS_SENSOR_VREF_2V0 ? 20000
361  : vRef == ESOS_SENSOR_VREF_2V048 ? 20480
362  : vRef == ESOS_SENSOR_VREF_3V0 ? 30000
363  : vRef == ESOS_SENSOR_VREF_3V3 ? 33000
364  : vRef == ESOS_SENSOR_VREF_4V0 ? 40000
365  : vRef == ESOS_SENSOR_VREF_4V096 ? 40960
366  : vRef == ESOS_SENSOR_VREF_5V0 ? 50000
367  : 0;
368  const uint32_t u32_divDeciMillivolts = (uint32_t)(*u16_data) * u32_maxDeciMilliVolts;
369  const uint32_t u32_DeciMillivolts = u32_divDeciMillivolts / 4096;
370  *pu16_data = (uint16_t)u32_DeciMillivolts;
371  }
372 
373  //Export as Percent
374  else if(FMT_CONSTANT & ESOS_SENSOR_FORMAT_PERCENT) {
375  *pu16_data = (uint32_t)(*u16_data) * 100 / 4096;
376  }
377 
378 
379  ESOS_TASK_END();
380 }
381 
382 /**
383 * Waits until a sensor is closed.
384 *
385 * \hideinitializer
386 */
388 {
390  // Release the flag
391  __esos_ClearSystemFlag(__ESOS_SYS_ADC_IS_BUSY);
392 
393  return TRUE;
394 }
BOOL
Definition: all_generic.h:402
esos_sensor_vref_t
Definition: esos_sensor.h:74
#define ESOS_TASK_END()
Definition: esos_task.h:272
#define ESOS_TASK_WAIT_WHILE(cond)
Definition: esos_task.h:364
void esos_sensor_config_hw(esos_sensor_ch_t, esos_sensor_vref_t)
uint16_t esos_sensor_getvalue_u16_hw(void)
#define ESOS_TASK_BEGIN()
Definition: esos_task.h:260
BOOL esos_sensor_is_converting_hw(void)
esos_sensor_ch_t
Definition: esos_sensor.h:52
esos_sensor_format_t
Definition: esos_sensor.h:120
ESOS_CHILD_TASK(_WAIT_ON_AVAILABLE_SENSOR, esos_sensor_ch_t e_senCh, esos_sensor_vref_t e_senVRef)
Definition: esos_sensor.c:42
unsigned char uint8_t
An abbreviation for an 8-bit unsigned integer.
Definition: dataXferImpl.h:194
void esos_sensor_release_hw(void)
BOOL ESOS_SENSOR_CLOSE(void)
Definition: esos_sensor.c:387