Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / periphery-lld / src / ut_alld_vcnl4020.c @ f3ac1c96

History | View | Annotate | Download (12.398 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 <ut_alld_vcnl4020.h>
20

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

    
23
/******************************************************************************/
24
/* LOCAL DEFINITIONS                                                          */
25
/******************************************************************************/
26
#include <aos_debug.h>
27
#include <chprintf.h>
28
#include <aos_thread.h>
29
#include <alld_vcnl4020.h>
30
#include <amiroos.h>
31

    
32
#define INTERRUPT_EVENT_ID            1
33

    
34
#define INTERRUPT_THRESHOLD           0x2000
35

    
36
/******************************************************************************/
37
/* EXPORTED VARIABLES                                                         */
38
/******************************************************************************/
39

    
40
/******************************************************************************/
41
/* LOCAL TYPES                                                                */
42
/******************************************************************************/
43

    
44
/******************************************************************************/
45
/* LOCAL VARIABLES                                                            */
46
/******************************************************************************/
47

    
48
/******************************************************************************/
49
/* LOCAL FUNCTIONS                                                            */
50
/******************************************************************************/
51

    
52
/******************************************************************************/
53
/* EXPORTED FUNCTIONS                                                         */
54
/******************************************************************************/
55

    
56
aos_utresult_t utAlldVcnl4020Func(BaseSequentialStream* stream, aos_unittest_t* ut)
57
{
58
  aosDbgCheck((ut->data != NULL) &&
59
              (((ut_vcnl4020data_t*)(ut->data))->vcnld != NULL) &&
60
              (((ut_vcnl4020data_t*)(ut->data))->evtsource != NULL));
61

    
62
  // local variables
63
  aos_utresult_t result = {0, 0};
64
  uint32_t status;
65
  uint8_t reg_buf[4];
66
  uint8_t* reg_8 = (uint8_t*)(reg_buf);
67
  uint16_t* reg_16 = (uint16_t*)(reg_buf);
68
  event_listener_t event_listener;
69
  aos_timestamp_t tcurrent, tend;
70

    
71
  chprintf(stream, "reading register...\n");
72
  status = vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_IDREV, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
73
  if ((status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) && reg_8[0] == 0x21u) {
74
    aosUtPassed(stream, &result);
75
  } else {
76
    aosUtFailedMsg(stream, &result, "0x%08X; 0x%08X\n", status, reg_8[0]);
77
  }
78

    
79
  chprintf(stream, "writing register...\n");
80
  status = vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_PROXRATE, VCNL4020_LLD_PROXRATEREG_250_HZ, ((ut_vcnl4020data_t*)(ut->data))->timeout);
81
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_PROXRATE, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
82
  status |= (reg_8[0] == VCNL4020_LLD_PROXRATEREG_250_HZ) ? 0x0000 : 0x0100;
83
  status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_CMD, (VCNL4020_LLD_CMDREG_ALSEN | VCNL4020_LLD_CMDREG_PROXEN | VCNL4020_LLD_CMDREG_SELFTIMED), ((ut_vcnl4020data_t*)(ut->data))->timeout);
84
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_CMD, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
85
  status |= (reg_8[0] & (VCNL4020_LLD_CMDREG_ALSEN | VCNL4020_LLD_CMDREG_PROXEN | VCNL4020_LLD_CMDREG_SELFTIMED)) ? 0x0000 : 0x0200;
86

    
87
  if (status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) {
88
    aosUtPassed(stream, &result);
89
  } else {
90
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%02X\n", status, reg_8[0]);
91
  }
92

    
93
  chprintf(stream, "reading ambient light for ten seconds...\n");
94
  status = APAL_STATUS_OK;
95
  for (uint8_t i = 0; i < 10; ++i) {
96
    aosThdSSleep(1);
97
    status |= vcnl4020_lld_readals(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
98
    chprintf(stream, "\t\tambient light: 0x%04X\n", reg_16[0]);
99
  }
100
  status |= (reg_16[0] == 0x0000) ? 0x10 : 0x00;
101
  if (status == APAL_STATUS_OK) {
102
    aosUtPassed(stream, &result);
103
  } else {
104
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
105
  }
106

    
107
  chprintf(stream, "reading proximity for ten seconds...\n");
108
  status = APAL_STATUS_OK;
109
  for (uint8_t i = 0; i < 10; ++i) {
110
    aosThdSSleep(1);
111
    status |= vcnl4020_lld_readprox(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
112
    chprintf(stream, "\t\tproximity: 0x%04X\n", reg_16[1]);
113
  }
114
  status |= (reg_16[1] == 0x0000) ? 0x10 : 0x00;
115
  if (status == APAL_STATUS_OK) {
116
    aosUtPassed(stream, &result);
117
  } else {
118
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
119
  }
120

    
121
  chprintf(stream, "reading ambient light and proximity for ten seconds...\n");
122
  status = APAL_STATUS_OK;
123
  for (uint8_t i = 0; i < 10; ++i) {
124
    aosThdSSleep(1);
125
    status |= vcnl4020_lld_readalsandprox(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
126
    chprintf(stream, "\t\tambient light: 0x%04X\tproximity: 0x%04X\n", reg_16[0], reg_16[1]);
127
  }
128
  status |= (reg_16[0] == 0x0000 || reg_16[1] == 0x0000) ? 0x10 : 0x00;
129
  if (status == APAL_STATUS_OK) {
130
    aosUtPassed(stream, &result);
131
  } else {
132
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
133
  }
134

    
135
  chprintf(stream, "reading low threshold register...\n");
136
  status = vcnl4020_lld_readlth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
137
  if (status == APAL_STATUS_OK) {
138
    aosUtPassed(stream, &result);
139
  } else {
140
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
141
  }
142

    
143
  chprintf(stream, "reading high threshold register...\n");
144
  status = vcnl4020_lld_readhth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
145
  if (status == APAL_STATUS_OK) {
146
    aosUtPassedMsg(stream, &result, "0x%04X\n", reg_16[1]);
147
  } else {
148
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
149
  }
150

    
151
  chprintf(stream, "reading both threshold registers...\n");
152
  status = vcnl4020_lld_readth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
153
  if (status == APAL_STATUS_OK) {
154
    aosUtPassedMsg(stream, &result, "low: 0x%04X; high: 0x%04X\n", reg_16[0], reg_16[1]);
155
  } else {
156
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
157
  }
158

    
159
  chprintf(stream, "writing low threshold register...\n");
160
  status = vcnl4020_lld_writelth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0xFFFFu, ((ut_vcnl4020data_t*)(ut->data))->timeout);
161
  status |= vcnl4020_lld_readlth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
162
  if (status == APAL_STATUS_OK && reg_16[0] == 0xFFFFu) {
163
    aosUtPassed(stream, &result);
164
  } else {
165
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%04X\n", status, reg_16[0]);
166
  }
167

    
168
  chprintf(stream, "writing high threshold register...\n");
169
  status = vcnl4020_lld_writehth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0xFFFFu, ((ut_vcnl4020data_t*)(ut->data))->timeout);
170
  status |= vcnl4020_lld_readhth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
171
  if (status == APAL_STATUS_OK && reg_16[1] == 0xFFFFu) {
172
    aosUtPassed(stream, &result);
173
  } else {
174
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%04X\n", status, reg_16[1]);
175
  }
176

    
177
  chprintf(stream, "writing both threshold registers...\n");
178
  status = vcnl4020_lld_writeth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0x5555u, 0xAAAAu, ((ut_vcnl4020data_t*)(ut->data))->timeout);
179
  status |= vcnl4020_lld_readth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
180
  if (status == APAL_STATUS_OK && reg_16[0] == 0x5555u && reg_16[1] == 0xAAAAu) {
181
    aosUtPassed(stream, &result);
182
  } else {
183
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%04X, 0x%04X\n", status, reg_16[0], reg_16[1]);
184
  }
185

    
186
  chprintf(stream, "test interrupts...\n");
187
  chprintf(stream, "(thresholds are 0x%04X and 0x%04X)\n", 0, INTERRUPT_THRESHOLD);
188
  chEvtRegister(((ut_vcnl4020data_t*)(ut->data))->evtsource, &event_listener, INTERRUPT_EVENT_ID);
189
  aosSysGetUptime(&tend);
190
  tend += 30 * MICROSECONDS_PER_SECOND;
191
  status = vcnl4020_lld_writeth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0x0000, INTERRUPT_THRESHOLD, ((ut_vcnl4020data_t*)(ut->data))->timeout);
192
  status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTCTRL, VCNL4020_LLD_INTCTRLREG_THRES_EN, ((ut_vcnl4020data_t*)(ut->data))->timeout);
193
  do {
194
    // read proximity data, interrupt event information and interrupt status
195
    const eventmask_t emask = chEvtWaitOneTimeout(EVENT_MASK(INTERRUPT_EVENT_ID), chTimeUS2I(10*MICROSECONDS_PER_MILLISECOND));
196
    const eventflags_t eflags = chEvtGetAndClearFlags(&event_listener);
197
    status |= vcnl4020_lld_readprox(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
198
    status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, &reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
199
    if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) &&
200
        eflags == ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
201
        reg_8[2] == VCNL4020_LLD_INTSTATUSREG_THHIGH) {
202
      // true positive (correct case)
203
      chprintf(stream, "\t\tinterrupt detected: prox = 0x%04X\n", reg_16[0]);
204
      aosThdMSleep(100);
205
    }
206
    else if (emask != EVENT_MASK(INTERRUPT_EVENT_ID) &&
207
             eflags != ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
208
             reg_8[2] != VCNL4020_LLD_INTSTATUSREG_THHIGH) {
209
      // true negative (correct case)
210
      // do nothing, just keep on looping
211
    }
212
    else if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) &&
213
             eflags == ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
214
             reg_8[2] != 0 ) {
215
      // false positive
216
      status |= 0x1000;
217
      chprintf(stream, "\t\tfalse positive: intstatus = 0x%02X; prox = 0x%04X\n", reg_8[2], reg_16[0]);
218
    }
219
    else if (emask != EVENT_MASK(INTERRUPT_EVENT_ID) &&
220
             eflags != ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
221
             reg_8[2] == 0) {
222
      // false negative
223
      status |= 0x2000;
224
      chprintf(stream, "\t\tfalse negative: intstatus = 0x%02X; prox = 0x%04X\n", reg_8[2], reg_16[0]);
225
    } // any other events are just ignored
226
    // reset interrupt status
227
    if (reg_8[2] != 0) {
228
      status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
229
    }
230
    aosSysGetUptime(&tcurrent);
231
  } while (tcurrent < tend);
232
  chEvtUnregister(((ut_vcnl4020data_t*)(ut->data))->evtsource, &event_listener);
233
  status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTCTRL, 0, ((ut_vcnl4020data_t*)(ut->data))->timeout);
234
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, &reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
235
  status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
236
  if (status == APAL_STATUS_SUCCESS || status == APAL_STATUS_WARNING) {
237
    aosUtPassed(stream, &result);
238
  } else {
239
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
240
  }
241

    
242
  aosUtInfoMsg(stream, "driver object memory footprint: %u bytes\n", sizeof(VCNL4020Driver));
243

    
244
  return result;
245
}
246

    
247
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_VCNL4020) */