Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / lld / src / ut_lld_adc.c @ 7da800ab

History | View | Annotate | Download (6.333 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2019  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
#include <amiroos.h>
20
#include <ut_lld_adc.h>
21

    
22
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && (HAL_USE_ADC == TRUE))|| defined(__DOXYGEN__)
23

    
24
/******************************************************************************/
25
/* LOCAL DEFINITIONS                                                          */
26
/******************************************************************************/
27

    
28
/**
29
 * @brief   Event mask of the ADC analog watchdog event.
30
 */
31
#define _adcWdgEventmask                        EVENT_MASK(31)
32

    
33
/**
34
 * @brief   ADC analog watchdog threshold (9.0V).
35
 */
36
#define _adcWdgThreshold                        (uint16_t)(9.0f / 5.0f / 3.3f * ((1 << 12) - 1) + 0.5f)
37

    
38
/******************************************************************************/
39
/* EXPORTED VARIABLES                                                         */
40
/******************************************************************************/
41

    
42
/******************************************************************************/
43
/* LOCAL TYPES                                                                */
44
/******************************************************************************/
45

    
46
/******************************************************************************/
47
/* LOCAL VARIABLES                                                            */
48
/******************************************************************************/
49

    
50
/**
51
 * @brief   Pointer to the thread listening for an ADC analog watchdog event.
52
 */
53
static thread_t* _listener;
54

    
55
/******************************************************************************/
56
/* LOCAL FUNCTIONS                                                            */
57
/******************************************************************************/
58

    
59
/**
60
 * @brief   Helper function to convert ADC sample value to volts.
61
 *
62
 * @param[in] adc   ADC sample value.
63
 *
64
 * @return          Converted value in volts.
65
 */
66
static inline float _adc2volt(adcsample_t adc) {
67
  return (float)adc / ((1 << 12) - 1) * 3.3f * 5.0f;
68
}
69

    
70
/**
71
 * @brief   ADC analog watchdog callback function.
72
 *
73
 * @param[in] adcp  ADC driver.
74
 * @param[in] err   ADC error value.
75
 */
76
static void _adcAwdCb(ADCDriver* adcp, adcerror_t err)
77
{
78
  (void)adcp;
79

    
80
  if (err == ADC_ERR_WATCHDOG) {
81
    chSysLockFromISR();
82
    if (_listener != NULL) {
83
      chEvtSignalI(_listener, _adcWdgEventmask);
84
      _listener = NULL;
85
    }
86
    chSysUnlockFromISR();
87
  }
88

    
89
  return;
90
}
91

    
92
/******************************************************************************/
93
/* EXPORTED FUNCTIONS                                                         */
94
/******************************************************************************/
95

    
96
/**
97
 * @brief   ADC unit test function.
98
 *
99
 * @param[in] stream  Stream for input/output.
100
 * @param[in] ut      Unit test object.
101
 *
102
 * @return            Unit test result value.
103
 */
104
aos_utresult_t utAdcFunc(BaseSequentialStream* stream, aos_unittest_t* ut)
105
{
106
  aosDbgCheck(ut->data != NULL && ((ut_adcdata_t*)(ut->data))->driver != NULL && ((ut_adcdata_t*)(ut->data))->convgroup != NULL);
107

    
108
  // local variables
109
  aos_utresult_t result = {0, 0};
110
  adcsample_t buffer[1] = {0};
111
  bool wdgpassed = false;
112
  eventmask_t eventmask = 0;
113
  ADCConversionGroup conversionGroup = *(((ut_adcdata_t*)(ut->data))->convgroup);
114
  conversionGroup.circular = true;
115
  conversionGroup.end_cb = NULL;
116
  conversionGroup.end_cb = NULL;
117
  conversionGroup.htr = ADC_HTR_HT;
118
  conversionGroup.ltr = 0;
119

    
120
  chprintf(stream, "reading voltage for five seconds...\n");
121
  adcStartConversion(((ut_adcdata_t*)(ut->data))->driver, &conversionGroup, buffer, 1);
122
  for (uint8_t s = 0; s < 5; ++s) {
123
    aosThdSSleep(1);
124
    chprintf(stream, "\tVSYS = %fV\n", _adc2volt(buffer[0]));
125
  }
126
  adcStopConversion(((ut_adcdata_t*)(ut->data))->driver);
127
  if (buffer[0] != 0) {
128
    aosUtPassed(stream, &result);
129
  } else {
130
    aosUtFailed(stream, &result);
131
  }
132

    
133
  chprintf(stream, "detecting external power...\n");
134
  conversionGroup.error_cb = _adcAwdCb;
135
  conversionGroup.htr = _adcWdgThreshold;
136
  conversionGroup.ltr = _adcWdgThreshold;
137
  _listener = chThdGetSelfX();
138
  adcStartConversion(((ut_adcdata_t*)(ut->data))->driver, &conversionGroup, buffer, 1);
139
  eventmask = chEvtWaitOneTimeout(_adcWdgEventmask, chTimeS2I(5));
140
  if (eventmask == _adcWdgEventmask) {
141
    aosUtPassedMsg(stream, &result, "%fV %c 9V\n", _adc2volt(buffer[0]), (buffer[0] > _adcWdgThreshold) ? '>' : '<');
142
    wdgpassed = true;
143
  } else {
144
    adcStopConversion(((ut_adcdata_t*)(ut->data))->driver);
145
    aosUtFailed(stream, &result);
146
    wdgpassed = false;
147
  }
148

    
149
  if (wdgpassed) {
150
    for (uint8_t i = 0; i < 2; ++i) {
151
      if (buffer[0] > _adcWdgThreshold) {
152
        chprintf(stream, "Remove external power within ten seconds.\n");
153
        conversionGroup.htr = ADC_HTR_HT;
154
        conversionGroup.ltr = _adcWdgThreshold;
155
      } else {
156
        chprintf(stream, "Connect external power within ten seconds.\n");
157
        conversionGroup.htr = _adcWdgThreshold;
158
        conversionGroup.ltr = 0;
159
      }
160
      aosThdMSleep(100); // wait some time so the ADC wil trigger again immediately due to noise
161
      _listener = chThdGetSelfX();
162
      adcStartConversion(((ut_adcdata_t*)(ut->data))->driver, &conversionGroup, buffer, 1);
163
      eventmask = chEvtWaitOneTimeout(_adcWdgEventmask, chTimeS2I(10));
164
      if (eventmask == _adcWdgEventmask) {
165
        aosUtPassedMsg(stream, &result, "%fV %c 9V\n", _adc2volt(buffer[0]), (buffer[0] > _adcWdgThreshold) ? '>' : '<');
166
      } else {
167
        adcStopConversion(((ut_adcdata_t*)(ut->data))->driver);
168
        aosUtFailed(stream, &result);
169
        break;
170
      }
171
    }
172
  }
173

    
174
  return result;
175
}
176

    
177
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && (HAL_USE_ADC == TRUE) */