Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / lld / src / ut_lld_adc.c @ f3ac1c96

History | View | Annotate | Download (6.38 KB)

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

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 <ut_lld_adc.h>
20
21
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && (HAL_USE_ADC == TRUE))|| defined(__DOXYGEN__)
22
23 f3ac1c96 Thomas Schöpping
/******************************************************************************/
24
/* LOCAL DEFINITIONS                                                          */
25
/******************************************************************************/
26 e545e620 Thomas Schöpping
#include <aos_debug.h>
27
#include <aos_thread.h>
28
#include <chprintf.h>
29
30
/**
31
 * @brief   Event mask of the ADC analog watchdog event.
32
 */
33
#define _adcWdgEventmask                        EVENT_MASK(31)
34
35
/**
36
 * @brief   ADC analog watchdog threshold (9.0V).
37
 */
38
#define _adcWdgThreshold                        (uint16_t)(9.0f / 5.0f / 3.3f * ((1 << 12) - 1) + 0.5f)
39
40 f3ac1c96 Thomas Schöpping
/******************************************************************************/
41
/* EXPORTED VARIABLES                                                         */
42
/******************************************************************************/
43
44
/******************************************************************************/
45
/* LOCAL TYPES                                                                */
46
/******************************************************************************/
47
48
/******************************************************************************/
49
/* LOCAL VARIABLES                                                            */
50
/******************************************************************************/
51
52 e545e620 Thomas Schöpping
/**
53
 * @brief   Pointer to the thread listening for an ADC analog watchdog event.
54
 */
55
static thread_t* _listener;
56
57 f3ac1c96 Thomas Schöpping
/******************************************************************************/
58
/* LOCAL FUNCTIONS                                                            */
59
/******************************************************************************/
60
61 e545e620 Thomas Schöpping
/**
62
 * @brief   Helper function to convert ADC sample value to volts.
63
 *
64
 * @param[in] adc   ADC sample value.
65
 *
66
 * @return          Converted value in volts.
67
 */
68
static inline float _adc2volt(adcsample_t adc) {
69
  return (float)adc / ((1 << 12) - 1) * 3.3f * 5.0f;
70
}
71
72
/**
73
 * @brief   ADC analog watchdog callback function.
74
 *
75
 * @param[in] adcp  ADC driver.
76
 * @param[in] err   ADC error value.
77
 */
78
static void _adcAwdCb(ADCDriver* adcp, adcerror_t err)
79
{
80
  (void)adcp;
81
82
  if (err == ADC_ERR_WATCHDOG) {
83
    chSysLockFromISR();
84
    if (_listener != NULL) {
85
      chEvtSignalI(_listener, _adcWdgEventmask);
86
      _listener = NULL;
87
    }
88
    chSysUnlockFromISR();
89
  }
90
91
  return;
92
}
93
94 f3ac1c96 Thomas Schöpping
/******************************************************************************/
95
/* EXPORTED FUNCTIONS                                                         */
96
/******************************************************************************/
97
98 e545e620 Thomas Schöpping
/**
99
 * @brief   ADC unit test function.
100
 *
101
 * @param[in] stream  Stream for input/output.
102
 * @param[in] ut      Unit test object.
103
 *
104
 * @return            Unit test result value.
105
 */
106
aos_utresult_t utAdcFunc(BaseSequentialStream* stream, aos_unittest_t* ut)
107
{
108
  aosDbgCheck(ut->data != NULL && ((ut_adcdata_t*)(ut->data))->driver != NULL && ((ut_adcdata_t*)(ut->data))->convgroup != NULL);
109
110
  // local variables
111
  aos_utresult_t result = {0, 0};
112
  adcsample_t buffer[1] = {0};
113
  bool wdgpassed = false;
114
  eventmask_t eventmask = 0;
115
  ADCConversionGroup conversionGroup = *(((ut_adcdata_t*)(ut->data))->convgroup);
116
  conversionGroup.circular = true;
117
  conversionGroup.end_cb = NULL;
118
  conversionGroup.end_cb = NULL;
119
  conversionGroup.htr = ADC_HTR_HT;
120
  conversionGroup.ltr = 0;
121
122
  chprintf(stream, "reading voltage for five seconds...\n");
123
  adcStartConversion(((ut_adcdata_t*)(ut->data))->driver, &conversionGroup, buffer, 1);
124
  for (uint8_t s = 0; s < 5; ++s) {
125
    aosThdSSleep(1);
126
    chprintf(stream, "\tVSYS = %fV\n", _adc2volt(buffer[0]));
127
  }
128
  adcStopConversion(((ut_adcdata_t*)(ut->data))->driver);
129
  if (buffer[0] != 0) {
130
    aosUtPassed(stream, &result);
131
  } else {
132
    aosUtFailed(stream, &result);
133
  }
134
135
  chprintf(stream, "detecting external power...\n");
136
  conversionGroup.error_cb = _adcAwdCb;
137
  conversionGroup.htr = _adcWdgThreshold;
138
  conversionGroup.ltr = _adcWdgThreshold;
139
  _listener = chThdGetSelfX();
140
  adcStartConversion(((ut_adcdata_t*)(ut->data))->driver, &conversionGroup, buffer, 1);
141 1e5f7648 Thomas Schöpping
  eventmask = chEvtWaitOneTimeout(_adcWdgEventmask, chTimeS2I(5));
142 e545e620 Thomas Schöpping
  if (eventmask == _adcWdgEventmask) {
143
    aosUtPassedMsg(stream, &result, "%fV %c 9V\n", _adc2volt(buffer[0]), (buffer[0] > _adcWdgThreshold) ? '>' : '<');
144
    wdgpassed = true;
145
  } else {
146
    adcStopConversion(((ut_adcdata_t*)(ut->data))->driver);
147
    aosUtFailed(stream, &result);
148
    wdgpassed = false;
149
  }
150
151
  if (wdgpassed) {
152
    for (uint8_t i = 0; i < 2; ++i) {
153
      if (buffer[0] > _adcWdgThreshold) {
154
        chprintf(stream, "Remove external power within ten seconds.\n");
155
        conversionGroup.htr = ADC_HTR_HT;
156
        conversionGroup.ltr = _adcWdgThreshold;
157
      } else {
158
        chprintf(stream, "Connect external power within ten seconds.\n");
159
        conversionGroup.htr = _adcWdgThreshold;
160
        conversionGroup.ltr = 0;
161
      }
162
      aosThdMSleep(100); // wait some time so the ADC wil trigger again immediately due to noise
163
      _listener = chThdGetSelfX();
164
      adcStartConversion(((ut_adcdata_t*)(ut->data))->driver, &conversionGroup, buffer, 1);
165 1e5f7648 Thomas Schöpping
      eventmask = chEvtWaitOneTimeout(_adcWdgEventmask, chTimeS2I(10));
166 e545e620 Thomas Schöpping
      if (eventmask == _adcWdgEventmask) {
167
        aosUtPassedMsg(stream, &result, "%fV %c 9V\n", _adc2volt(buffer[0]), (buffer[0] > _adcWdgThreshold) ? '>' : '<');
168
      } else {
169
        adcStopConversion(((ut_adcdata_t*)(ut->data))->driver);
170
        aosUtFailed(stream, &result);
171
        break;
172
      }
173
    }
174
  }
175
176
  return result;
177
}
178
179
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && (HAL_USE_ADC == TRUE) */