Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (12.364 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) && defined(AMIROLLD_CFG_VCNL4020) && (AMIROLLD_CFG_VCNL4020 == 1)) || defined(__DOXYGEN__)
22

    
23
#include <ut_alld_VCNL4020_v1.h>
24

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

    
29
#define INTERRUPT_EVENT_ID            1
30

    
31
#define INTERRUPT_THRESHOLD           0x2000
32

    
33
/******************************************************************************/
34
/* EXPORTED VARIABLES                                                         */
35
/******************************************************************************/
36

    
37
/******************************************************************************/
38
/* LOCAL TYPES                                                                */
39
/******************************************************************************/
40

    
41
/******************************************************************************/
42
/* LOCAL VARIABLES                                                            */
43
/******************************************************************************/
44

    
45
/******************************************************************************/
46
/* LOCAL FUNCTIONS                                                            */
47
/******************************************************************************/
48

    
49
/******************************************************************************/
50
/* EXPORTED FUNCTIONS                                                         */
51
/******************************************************************************/
52

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

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

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

    
76
  chprintf(stream, "writing register...\n");
77
  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);
78
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_PROXRATE, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
79
  status |= (reg_8[0] == VCNL4020_LLD_PROXRATEREG_250_HZ) ? 0x0000 : 0x0100;
80
  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);
81
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_CMD, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
82
  status |= (reg_8[0] & (VCNL4020_LLD_CMDREG_ALSEN | VCNL4020_LLD_CMDREG_PROXEN | VCNL4020_LLD_CMDREG_SELFTIMED)) ? 0x0000 : 0x0200;
83

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

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

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

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

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

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

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

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

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

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

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

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

    
241
  return result;
242
}
243

    
244
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_VCNL4020) && (AMIROLLD_CFG_VCNL4020 == 1) */
245