Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / lld / src / ut_lld_adc.c @ 9487b4cd

History | View | Annotate | Download (6.334 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

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

    
23
#include <ut_lld_adc.h>
24

    
25
/******************************************************************************/
26
/* LOCAL DEFINITIONS                                                          */
27
/******************************************************************************/
28

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

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

    
39
/******************************************************************************/
40
/* EXPORTED VARIABLES                                                         */
41
/******************************************************************************/
42

    
43
/******************************************************************************/
44
/* LOCAL TYPES                                                                */
45
/******************************************************************************/
46

    
47
/******************************************************************************/
48
/* LOCAL VARIABLES                                                            */
49
/******************************************************************************/
50

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

    
56
/******************************************************************************/
57
/* LOCAL FUNCTIONS                                                            */
58
/******************************************************************************/
59

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

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

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

    
90
  return;
91
}
92

    
93
/******************************************************************************/
94
/* EXPORTED FUNCTIONS                                                         */
95
/******************************************************************************/
96

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

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

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

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

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

    
175
  return result;
176
}
177

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