Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (4.947 KB)

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