Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11 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_alld_vcnl4020.h>
20
21
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_VCNL4020)) || defined(__DOXYGEN__)
22
23
#include <aos_debug.h>
24
#include <chprintf.h>
25
#include <aos_thread.h>
26
#include <alld_vcnl4020.h>
27
#include <amiroos.h>
28
29
#define INTERRUPT_EVENT_ID            1
30
31
#define INTERRUPT_THRESHOLD           0x2000
32
33
aos_utresult_t utAlldVcnl4020Func(BaseSequentialStream* stream, aos_unittest_t* ut)
34
{
35
  aosDbgCheck((ut->data != NULL) &&
36
              (((ut_vcnl4020data_t*)(ut->data))->vcnld != NULL) &&
37
              (((ut_vcnl4020data_t*)(ut->data))->evtsource != NULL));
38
39
  // local variables
40
  aos_utresult_t result = {0, 0};
41
  uint32_t status;
42
  uint8_t reg_buf[4];
43
  uint8_t* reg_8 = (uint8_t*)(reg_buf);
44
  uint16_t* reg_16 = (uint16_t*)(reg_buf);
45
  event_listener_t event_listener;
46
  aos_timestamp_t tcurrent, tend;
47
48
  chprintf(stream, "reading register...\n");
49
  status = vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_IDREV, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
50
  if ((status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) && reg_8[0] == 0x21u) {
51
    aosUtPassed(stream, &result);
52
  } else {
53
    aosUtFailedMsg(stream, &result, "0x%08X; 0x%08X\n", status, reg_8[0]);
54
  }
55
56
  chprintf(stream, "writing register...\n");
57
  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);
58
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_PROXRATE, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
59
  status |= (reg_8[0] == VCNL4020_LLD_PROXRATEREG_250_HZ) ? 0x0000 : 0x0100;
60
  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);
61
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_CMD, &reg_8[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
62
  status |= (reg_8[0] & (VCNL4020_LLD_CMDREG_ALSEN | VCNL4020_LLD_CMDREG_PROXEN | VCNL4020_LLD_CMDREG_SELFTIMED)) ? 0x0000 : 0x0200;
63
64
  if (status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) {
65
    aosUtPassed(stream, &result);
66
  } else {
67
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%02X\n", status, reg_8[0]);
68
  }
69
70
  chprintf(stream, "reading ambient light for ten seconds...\n");
71
  status = APAL_STATUS_OK;
72
  for (uint8_t i = 0; i < 10; ++i) {
73
    aosThdSSleep(1);
74
    status |= vcnl4020_lld_readals(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
75
    chprintf(stream, "\t\tambient light: 0x%04X\n", reg_16[0]);
76
  }
77
  status |= (reg_16[0] == 0x0000) ? 0x10 : 0x00;
78
  if (status == APAL_STATUS_OK) {
79
    aosUtPassed(stream, &result);
80
  } else {
81
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
82
  }
83
84
  chprintf(stream, "reading proximity for ten seconds...\n");
85
  status = APAL_STATUS_OK;
86
  for (uint8_t i = 0; i < 10; ++i) {
87
    aosThdSSleep(1);
88
    status |= vcnl4020_lld_readprox(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
89
    chprintf(stream, "\t\tproximity: 0x%04X\n", reg_16[1]);
90
  }
91
  status |= (reg_16[1] == 0x0000) ? 0x10 : 0x00;
92
  if (status == APAL_STATUS_OK) {
93
    aosUtPassed(stream, &result);
94
  } else {
95
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
96
  }
97
98
  chprintf(stream, "reading ambient light and proximity for ten seconds...\n");
99
  status = APAL_STATUS_OK;
100
  for (uint8_t i = 0; i < 10; ++i) {
101
    aosThdSSleep(1);
102
    status |= vcnl4020_lld_readalsandprox(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
103
    chprintf(stream, "\t\tambient light: 0x%04X\tproximity: 0x%04X\n", reg_16[0], reg_16[1]);
104
  }
105
  status |= (reg_16[0] == 0x0000 || reg_16[1] == 0x0000) ? 0x10 : 0x00;
106
  if (status == APAL_STATUS_OK) {
107
    aosUtPassed(stream, &result);
108
  } else {
109
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
110
  }
111
112
  chprintf(stream, "reading low threshold register...\n");
113
  status = vcnl4020_lld_readlth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
114
  if (status == APAL_STATUS_OK) {
115
    aosUtPassed(stream, &result);
116
  } else {
117
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
118
  }
119
120
  chprintf(stream, "reading high threshold register...\n");
121
  status = vcnl4020_lld_readhth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
122
  if (status == APAL_STATUS_OK) {
123
    aosUtPassedMsg(stream, &result, "0x%04X\n", reg_16[1]);
124
  } else {
125
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
126
  }
127
128
  chprintf(stream, "reading both threshold registers...\n");
129
  status = vcnl4020_lld_readth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
130
  if (status == APAL_STATUS_OK) {
131
    aosUtPassedMsg(stream, &result, "low: 0x%04X; high: 0x%04X\n", reg_16[0], reg_16[1]);
132
  } else {
133
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
134
  }
135
136
  chprintf(stream, "writing low threshold register...\n");
137
  status = vcnl4020_lld_writelth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0xFFFFu, ((ut_vcnl4020data_t*)(ut->data))->timeout);
138
  status |= vcnl4020_lld_readlth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
139
  if (status == APAL_STATUS_OK && reg_16[0] == 0xFFFFu) {
140
    aosUtPassed(stream, &result);
141
  } else {
142
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%04X\n", status, reg_16[0]);
143
  }
144
145
  chprintf(stream, "writing high threshold register...\n");
146
  status = vcnl4020_lld_writehth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0xFFFFu, ((ut_vcnl4020data_t*)(ut->data))->timeout);
147
  status |= vcnl4020_lld_readhth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
148
  if (status == APAL_STATUS_OK && reg_16[1] == 0xFFFFu) {
149
    aosUtPassed(stream, &result);
150
  } else {
151
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%04X\n", status, reg_16[1]);
152
  }
153
154
  chprintf(stream, "writing both threshold registers...\n");
155
  status = vcnl4020_lld_writeth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0x5555u, 0xAAAAu, ((ut_vcnl4020data_t*)(ut->data))->timeout);
156
  status |= vcnl4020_lld_readth(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], &reg_16[1], ((ut_vcnl4020data_t*)(ut->data))->timeout);
157
  if (status == APAL_STATUS_OK && reg_16[0] == 0x5555u && reg_16[1] == 0xAAAAu) {
158
    aosUtPassed(stream, &result);
159
  } else {
160
    aosUtFailedMsg(stream, &result, "0x%08X, 0x%04X, 0x%04X\n", status, reg_16[0], reg_16[1]);
161
  }
162
163
  chprintf(stream, "test interrupts...\n");
164
  chprintf(stream, "(thresholds are 0x%04X and 0x%04X)\n", 0, INTERRUPT_THRESHOLD);
165
  chEvtRegister(((ut_vcnl4020data_t*)(ut->data))->evtsource, &event_listener, INTERRUPT_EVENT_ID);
166
  aosSysGetUptime(&tend);
167
  tend += 30 * MICROSECONDS_PER_SECOND;
168
  status = vcnl4020_lld_writeth(((ut_vcnl4020data_t*)(ut->data))->vcnld, 0x0000, INTERRUPT_THRESHOLD, ((ut_vcnl4020data_t*)(ut->data))->timeout);
169
  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);
170
  do {
171
    // read proximity data, interrupt event information and interrupt status
172
    const eventmask_t emask = chEvtWaitOneTimeout(EVENT_MASK(INTERRUPT_EVENT_ID), LL_US2ST(10*MICROSECONDS_PER_MILLISECOND));
173
    const eventflags_t eflags = chEvtGetAndClearFlags(&event_listener);
174
    status |= vcnl4020_lld_readprox(((ut_vcnl4020data_t*)(ut->data))->vcnld, &reg_16[0], ((ut_vcnl4020data_t*)(ut->data))->timeout);
175
    status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, &reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
176
    if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) &&
177
        eflags == ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
178
        reg_8[2] == VCNL4020_LLD_INTSTATUSREG_THHIGH) {
179
      // true positive (correct case)
180
      chprintf(stream, "\t\tinterrupt detected: prox = 0x%04X\n", reg_16[0]);
181
      aosThdMSleep(100);
182
    }
183
    else if (emask != EVENT_MASK(INTERRUPT_EVENT_ID) &&
184
             eflags != ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
185
             reg_8[2] != VCNL4020_LLD_INTSTATUSREG_THHIGH) {
186
      // true negative (correct case)
187
      // do nothing, just keep on looping
188
    }
189
    else if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) &&
190
             eflags == ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
191
             reg_8[2] != 0 ) {
192
      // false positive
193
      status |= 0x1000;
194
      chprintf(stream, "\t\tfalse positive: intstatus = 0x%02X; prox = 0x%04X\n", reg_8[2], reg_16[0]);
195
    }
196
    else if (emask != EVENT_MASK(INTERRUPT_EVENT_ID) &&
197
             eflags != ((ut_vcnl4020data_t*)(ut->data))->evtflags &&
198
             reg_8[2] == 0) {
199
      // false negative
200
      status |= 0x2000;
201
      chprintf(stream, "\t\tfalse negative: intstatus = 0x%02X; prox = 0x%04X\n", reg_8[2], reg_16[0]);
202
    } // any other events are just ignored
203
    // reset interrupt status
204
    if (reg_8[2] != 0) {
205
      status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
206
    }
207
    aosSysGetUptime(&tcurrent);
208
  } while (tcurrent < tend);
209
  chEvtUnregister(((ut_vcnl4020data_t*)(ut->data))->evtsource, &event_listener);
210
  status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTCTRL, 0, ((ut_vcnl4020data_t*)(ut->data))->timeout);
211
  status |= vcnl4020_lld_readreg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, &reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
212
  status |= vcnl4020_lld_writereg(((ut_vcnl4020data_t*)(ut->data))->vcnld, VCNL4020_LLD_REGADDR_INTSTATUS, reg_8[2], ((ut_vcnl4020data_t*)(ut->data))->timeout);
213
  if (status == APAL_STATUS_SUCCESS || status == APAL_STATUS_WARNING) {
214
    aosUtPassed(stream, &result);
215
  } else {
216
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
217
  }
218
219
  aosUtInfoMsg(stream, "driver object memory footprint: %u bytes\n", sizeof(VCNL4020Driver));
220
221
  return result;
222
}
223
224
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_VCNL4020) */
225