Statistics
| Branch: | Tag: | Revision:

amiro-os / test / periphery-lld / VCNL4020_v1 / aos_test_VCNL4020.c @ 4e8e8462

History | View | Annotate | Download (12.768 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2020  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
#include <aos_test_VCNL4020.h>
21

    
22
#if (AMIROOS_CFG_TESTS_ENABLE == true) || defined(__DOXYGEN__)
23

    
24
/******************************************************************************/
25
/* LOCAL DEFINITIONS                                                          */
26
/******************************************************************************/
27

    
28
#define INTERRUPT_EVENT_ID            1
29

    
30
#define INTERRUPT_THRESHOLD           0x2000
31

    
32
/******************************************************************************/
33
/* EXPORTED VARIABLES                                                         */
34
/******************************************************************************/
35

    
36
/******************************************************************************/
37
/* LOCAL TYPES                                                                */
38
/******************************************************************************/
39

    
40
/******************************************************************************/
41
/* LOCAL VARIABLES                                                            */
42
/******************************************************************************/
43

    
44
/******************************************************************************/
45
/* LOCAL FUNCTIONS                                                            */
46
/******************************************************************************/
47

    
48
/******************************************************************************/
49
/* EXPORTED FUNCTIONS                                                         */
50
/******************************************************************************/
51

    
52
aos_testresult_t aosTestVcnl4020Func(BaseSequentialStream* stream, const aos_test_t* test)
53
{
54
  aosDbgCheck((test->data != NULL) &&
55
              (((aos_test_vcnl4020data_t*)(test->data))->vcnld != NULL) &&
56
              (((aos_test_vcnl4020data_t*)(test->data))->evtsource != NULL));
57

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

    
67
  aosTestResultInit(&result);
68

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

    
77
  chprintf(stream, "writing register...\n");
78
  status = vcnl4020_lld_writereg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_PROXRATE, VCNL4020_LLD_PROXRATEREG_250_HZ, ((aos_test_vcnl4020data_t*)(test->data))->timeout);
79
  status |= vcnl4020_lld_readreg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_PROXRATE, &reg_8[0], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
80
  status |= (reg_8[0] == VCNL4020_LLD_PROXRATEREG_250_HZ) ? 0x0000 : 0x0100;
81
  status |= vcnl4020_lld_writereg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_CMD, (VCNL4020_LLD_CMDREG_ALSEN | VCNL4020_LLD_CMDREG_PROXEN | VCNL4020_LLD_CMDREG_SELFTIMED), ((aos_test_vcnl4020data_t*)(test->data))->timeout);
82
  status |= vcnl4020_lld_readreg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_CMD, &reg_8[0], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
83
  status |= (reg_8[0] & (VCNL4020_LLD_CMDREG_ALSEN | VCNL4020_LLD_CMDREG_PROXEN | VCNL4020_LLD_CMDREG_SELFTIMED)) ? 0x0000 : 0x0200;
84
  if (status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) {
85
    aosTestPassed(stream, &result);
86
  } else {
87
    aosTestFailedMsg(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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[0], ((aos_test_vcnl4020data_t*)(test->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
    aosTestPassed(stream, &result);
100
  } else {
101
    aosTestFailedMsg(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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[1], ((aos_test_vcnl4020data_t*)(test->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
    aosTestPassed(stream, &result);
114
  } else {
115
    aosTestFailedMsg(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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[0], &reg_16[1], ((aos_test_vcnl4020data_t*)(test->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
    aosTestPassed(stream, &result);
128
  } else {
129
    aosTestFailedMsg(stream, &result, "0x%08X\n", status);
130
  }
131

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

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

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

    
156
  chprintf(stream, "writing low threshold register...\n");
157
  status = vcnl4020_lld_writelth(((aos_test_vcnl4020data_t*)(test->data))->vcnld, 0xFFFFu, ((aos_test_vcnl4020data_t*)(test->data))->timeout);
158
  status |= vcnl4020_lld_readlth(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[0], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
159
  if (status == APAL_STATUS_OK && reg_16[0] == 0xFFFFu) {
160
    aosTestPassed(stream, &result);
161
  } else {
162
    aosTestFailedMsg(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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, 0xFFFFu, ((aos_test_vcnl4020data_t*)(test->data))->timeout);
167
  status |= vcnl4020_lld_readhth(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[1], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
168
  if (status == APAL_STATUS_OK && reg_16[1] == 0xFFFFu) {
169
    aosTestPassed(stream, &result);
170
  } else {
171
    aosTestFailedMsg(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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, 0x5555u, 0xAAAAu, ((aos_test_vcnl4020data_t*)(test->data))->timeout);
176
  status |= vcnl4020_lld_readth(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[0], &reg_16[1], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
177
  if (status == APAL_STATUS_OK && reg_16[0] == 0x5555u && reg_16[1] == 0xAAAAu) {
178
    aosTestPassed(stream, &result);
179
  } else {
180
    aosTestFailedMsg(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(((aos_test_vcnl4020data_t*)(test->data))->evtsource, &event_listener, INTERRUPT_EVENT_ID);
186
  aosSysGetUptime(&tend);
187
  tend += 30 * MICROSECONDS_PER_SECOND;
188
  status = vcnl4020_lld_writeth(((aos_test_vcnl4020data_t*)(test->data))->vcnld, 0x0000, INTERRUPT_THRESHOLD, ((aos_test_vcnl4020data_t*)(test->data))->timeout);
189
  status |= vcnl4020_lld_writereg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_INTCTRL, VCNL4020_LLD_INTCTRLREG_THRES_EN, ((aos_test_vcnl4020data_t*)(test->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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, &reg_16[0], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
195
    status |= vcnl4020_lld_readreg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, &reg_8[2], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
196
    if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) &&
197
        eflags == ((aos_test_vcnl4020data_t*)(test->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 != ((aos_test_vcnl4020data_t*)(test->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 == ((aos_test_vcnl4020data_t*)(test->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 != ((aos_test_vcnl4020data_t*)(test->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(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, reg_8[2], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
226
    }
227
    aosSysGetUptime(&tcurrent);
228
  } while (tcurrent < tend);
229
  chEvtUnregister(((aos_test_vcnl4020data_t*)(test->data))->evtsource, &event_listener);
230
  status |= vcnl4020_lld_writereg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_INTCTRL, 0, ((aos_test_vcnl4020data_t*)(test->data))->timeout);
231
  status |= vcnl4020_lld_readreg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, &reg_8[2], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
232
  status |= vcnl4020_lld_writereg(((aos_test_vcnl4020data_t*)(test->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, reg_8[2], ((aos_test_vcnl4020data_t*)(test->data))->timeout);
233
  if (status == APAL_STATUS_SUCCESS || status == APAL_STATUS_WARNING) {
234
    aosTestPassed(stream, &result);
235
  } else {
236
    aosTestFailedMsg(stream, &result, "0x%08X\n", status);
237
  }
238

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

    
241
  return result;
242
}
243

    
244
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) */