Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (12.363 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
#include <ut_alld_VCNL4020_v1.h>
21

    
22
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_VCNL4020) && (AMIROLLD_CFG_VCNL4020 == 1)) || 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_utresult_t utAlldVcnl4020Func(BaseSequentialStream* stream, aos_unittest_t* ut)
53
{
54
  aosDbgCheck((ut->data != NULL) &&
55
              (((ut_vcnl4020data_t*)(ut->data))->vcnld != NULL) &&
56
              (((ut_vcnl4020data_t*)(ut->data))->evtsource != NULL));
57

    
58
  // local variables
59
  aos_utresult_t result = {0, 0};
60
  uint32_t status;
61
  uint8_t reg_buf[4];
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
  chprintf(stream, "reading register...\n");
68
  status = vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_IDREV, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
69
  if ((status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) && reg_8[0] == 0x21u) {
70
    aosUtPassed(stream, &result);
71
  } else {
72
    aosUtFailedMsg(stream, &result, "0x%08X; 0x%08X\n", status, reg_8[0]);
73
  }
74

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

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

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

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

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

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

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

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

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

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

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

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

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

    
240
  return result;
241
}
242

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