Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / periphery-lld / src / ut_alld_AT42QT1050_v1.c @ 265dae32

History | View | Annotate | Download (18.2 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_AT42QT1050_v1.h>
21

    
22
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_AT42QT1050) && (AMIROLLD_CFG_AT42QT1050 == 1)) || defined(__DOXYGEN__)
23
/******************************************************************************/
24
/* LOCAL DEFINITIONS                                                          */
25
/******************************************************************************/
26

    
27
#define INTERRUPT_EVENT_ID            1
28

    
29
/******************************************************************************/
30
/* EXPORTED VARIABLES                                                         */
31
/******************************************************************************/
32

    
33
/******************************************************************************/
34
/* LOCAL TYPES                                                                */
35
/******************************************************************************/
36

    
37
/******************************************************************************/
38
/* LOCAL VARIABLES                                                            */
39
/******************************************************************************/
40

    
41
/******************************************************************************/
42
/* LOCAL FUNCTIONS                                                            */
43
/******************************************************************************/
44

    
45
void print_settings(apalExitStatus_t* status, BaseSequentialStream* stream, aos_unittest_t* ut) {
46
    chprintf(stream, "settings...\n");
47

    
48
    uint8_t test8;
49
    at42qt1050_lld_register_t txbuf;
50
    *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_LOWPOWERMODE, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
51
    chprintf(stream, "\tmeasurement inverval %d ms\n", test8*8);
52

    
53
    *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_MAXONDURATION, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
54
    chprintf(stream, "\tMax on duration %d ms\n", test8*160);
55

    
56
    *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_FINFOUTMAXCALGUARD, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
57
    chprintf(stream, "\tFast In %d, Fast Out, %d MaxCal %d\n\tGuard channel ",
58
             test8 & AT42QT1050_LLD_FINFOUTMAXCALGUARD_FI,     //enter fast mode whenever an unfiltered signal value is detected
59
             test8 & AT42QT1050_LLD_FINFOUTMAXCALGUARD_FO,     //DI of 4 (global setting for all keys)
60
             test8 & AT42QT1050_LLD_FINFOUTMAXCALGUARD_MAXCAL);//recalibrate ALL KEYS after a Max On Duration timeout vs. individually
61

    
62
    //guard channel (which gets priority filtering)
63
    if((test8 & AT42QT1050_LLD_FINFOUTMAXCALGUARD_GUARD) > AT42QT1050_LLD_NUM_KEYS-1)
64
        chprintf(stream, "off");
65
    else
66
        chprintf(stream, " %d", test8 & AT42QT1050_LLD_FINFOUTMAXCALGUARD_GUARD);
67

    
68
    chprintf(stream, "\n\n\tkey\tgroup\tintegr.\tdelay\tthresh.\tpulse\tscale\n");
69
    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
70
        chprintf(stream, "\t%d\t", key);
71
        txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_INTEGRATOR_AKS_0, key);
72
        *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
73
        if(!((at42qt1050_lld_detectionintegratoraksreg_t)test8).aks)
74
            chprintf(stream, "none\t");
75
        else
76
            chprintf(stream, "%d\t", ((at42qt1050_lld_detectionintegratoraksreg_t)test8).aks);
77

    
78
        if(!((at42qt1050_lld_detectionintegratoraksreg_t)test8).detection_integrator)
79
            chprintf(stream, "off");
80
        else
81
            chprintf(stream, "%d", ((at42qt1050_lld_detectionintegratoraksreg_t)test8).detection_integrator);
82

    
83
        txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_CHARGESHAREDELAY_0, key);
84
        *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
85
        chprintf(stream, "\t+%d", test8);
86

    
87
        txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0, key);
88
        *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
89
        chprintf(stream, "\t%d", test8);
90

    
91
        txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_PULSE_SCALE_0, key);
92
        *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &test8, ((ut_at42qt1050data_t*)ut->data)->timeout);
93
        chprintf(stream, "\t%d\t%d\n", ((at42qt1050_lld_pulsescalereg_t)test8).pulse, ((at42qt1050_lld_pulsescalereg_t)test8).scale);
94
    }
95

    
96
}
97

    
98
void show_live(const uint8_t first_key, apalExitStatus_t* status,
99
               BaseSequentialStream* stream, aos_unittest_t* ut) {
100

    
101
    apalDbgAssert(first_key<5);
102

    
103
    event_listener_t event_listener;
104
    aos_timestamp_t tcurrent, tend ,tdemo_end;
105

    
106
    //stop demo after 15 seconds
107
    aosSysGetUptime(&tcurrent);
108
    tdemo_end = tcurrent + 15*MICROSECONDS_PER_SECOND;
109

    
110
    uint8_t keyStatus, detectionStatus;
111
    uint16_t signal, reference;
112
    uint8_t threshold[AT42QT1050_LLD_NUM_KEYS];
113

    
114
    chprintf(stream, "key, count, ref, signal, [threshold], \033[31mtouch\n\033[0m");
115

    
116
    //get thresholds
117
    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
118
        const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0, key);
119
        *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &threshold[key], ((ut_at42qt1050data_t*)ut->data)->timeout);
120
    }
121
    chEvtRegister(((ut_at42qt1050data_t*)ut->data)->evtsource, &event_listener, INTERRUPT_EVENT_ID);
122
    while(true) {
123
        aosSysGetUptime(&tcurrent);
124

    
125
        for (uint8_t key = first_key; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
126

    
127
            //highlight touched key
128
            *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_KEYSTATUS, &keyStatus, ((ut_at42qt1050data_t*)ut->data)->timeout);
129
            if((key == 0 && keyStatus&AT42QT1050_LLD_KEYSTATUS_KEY0)
130
                    || (key == 1 && keyStatus&AT42QT1050_LLD_KEYSTATUS_KEY1)
131
                    || (key == 2 && keyStatus&AT42QT1050_LLD_KEYSTATUS_KEY2)
132
                    || (key == 3 && keyStatus&AT42QT1050_LLD_KEYSTATUS_KEY3)
133
                    || (key == 4 && keyStatus&AT42QT1050_LLD_KEYSTATUS_KEY4))
134
                chprintf(stream, "\033[31m"); //red
135
            else
136
                chprintf(stream, "\033[0m"); //black
137

    
138
            *status |= at42qt1050_lld_read_keyssignal(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, key, &signal, ((ut_at42qt1050data_t*)ut->data)->timeout);
139
            *status |= at42qt1050_lld_read_referencedata(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, key, &reference, ((ut_at42qt1050data_t*)ut->data)->timeout);
140

    
141
            const uint16_t dist = (signal<reference?0:signal-reference);
142
            chprintf(stream, "\033[Kkey %d, %d\t0x%04X 0x%04X [", key, dist, reference, signal);
143
            uint16_t stars=0;
144
            for(; stars < dist; stars++) {
145
                chprintf(stream, "0");
146
                if(stars > 40) {           //max_stars = 40
147
                    chprintf(stream, "+"); //more than max_stars
148
                    break;
149
                }
150
            }
151
            for(; stars < threshold[key]; stars++)
152
                chprintf(stream, " ");
153
            if(stars == threshold[key])
154
                chprintf(stream, "]");
155
            chprintf(stream, "\n\033[0m");
156
        }
157

    
158
        //wait 1/3 second for a touch event
159
        tend = tcurrent + (MICROSECONDS_PER_SECOND/3);
160
        const eventmask_t emask = chEvtWaitOneTimeout(EVENT_MASK(INTERRUPT_EVENT_ID), chTimeUS2I(tend));
161
        const eventflags_t eflags = chEvtGetAndClearFlags(&event_listener);
162
        if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) && eflags == ((ut_at42qt1050data_t*)ut->data)->evtflags) {
163
            // interrupt detected
164
            chprintf(stream, "interrupt ");
165
        } // else: timeout
166

    
167
        *status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_DETECTIONSTATUS, &detectionStatus, ((ut_at42qt1050data_t*)ut->data)->timeout);
168
        if(detectionStatus & AT42QT1050_LLD_DETECTIONSTATUS_TOUCH)
169
            chprintf(stream, "touch ");
170
        if(detectionStatus & AT42QT1050_LLD_DETECTIONSTATUS_OVERFLOW)
171
            chprintf(stream, "overflow ");
172
        if(detectionStatus & AT42QT1050_LLD_DETECTIONSTATUS_CALIBRATE)
173
            chprintf(stream, "calibrate");
174
        chprintf(stream, "\033[K");
175

    
176
        if(tcurrent > tdemo_end)
177
            break;
178

    
179
        chprintf(stream, "\033[%dF", 5-first_key); //cursor up
180
    }
181
    chEvtUnregister(((ut_at42qt1050data_t*)ut->data)->evtsource, &event_listener);
182
}
183

    
184
/******************************************************************************/
185
/* EXPORTED FUNCTIONS                                                         */
186
/******************************************************************************/
187

    
188
aos_utresult_t utAlldAt42qt1050Func(BaseSequentialStream* stream, aos_unittest_t* ut)
189
{
190
    aosDbgCheck(ut->data != NULL && ((ut_at42qt1050data_t*)ut->data)->at42qt1050d != NULL);
191

    
192
    // local variables
193
    aos_utresult_t result = {0, 0};
194
    apalExitStatus_t status;
195
    uint8_t test_8;
196
    bool error;
197

    
198
    chprintf(stream, "read register...\n");
199
    error = false;
200
    status = at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_CHIPID, &test_8, ((ut_at42qt1050data_t*)ut->data)->timeout);
201
    chprintf(stream, "\t\tchip ID: 0x%02X\n", test_8);
202
    if (test_8 != AT42QT1050_LLD_CHIPID)
203
        error = true;
204
    status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_FIRMWAREVERSION, &test_8, ((ut_at42qt1050data_t*)ut->data)->timeout);
205
    chprintf(stream, "\t\tfirmware version: %u.%u (0x%02X)\n", ((at42qt1050_lld_firmwarereg_t)test_8).major, ((at42qt1050_lld_firmwarereg_t)test_8).minor, test_8);
206
    if (status == APAL_STATUS_SUCCESS && !error) {
207
        aosUtPassed(stream, &result);
208
    } else {
209
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
210
    }
211

    
212
    chprintf(stream, "write and readback threshold data...\n");
213
    status = APAL_STATUS_OK;
214
    const uint8_t threshold_test = 0x40;
215
    error = false;
216
    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
217
        const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0, key);
218
        status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, threshold_test , ((ut_at42qt1050data_t*)ut->data)->timeout);
219
        status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &test_8, ((ut_at42qt1050data_t*)ut->data)->timeout);
220
        if(test_8 != threshold_test)
221
            error = true;
222
    }
223
    if (status == APAL_STATUS_SUCCESS  &&  !error) {
224
        aosUtPassedMsg(stream, &result, "Set thresholds successfull to 0x%04X\n", threshold_test);
225
    } else {
226
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
227
    }
228

    
229
    chprintf(stream, "guarding...\nincrease charge_delay0\ndisable multitouch\n");
230

    
231
    //channel 0 is to big to be charged in the default cycle
232
    status = at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_CHARGESHAREDELAY_0, 128 , ((ut_at42qt1050data_t*)ut->data)->timeout);
233

    
234
    //set all channel to group 1 -> only 1 simultaneous touch in group = single touch
235
    at42qt1050_lld_detectionintegratoraksreg_t detectionintegrator;
236
    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
237
        const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_INTEGRATOR_AKS_0, key);
238
        detectionintegrator.aks = 1;                  //on touch per group-id simultaneous
239
        detectionintegrator.detection_integrator = 4; //4 times > threshold => touchevent
240
        status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, detectionintegrator.raw, ((ut_at42qt1050data_t*)ut->data)->timeout);
241
    }
242
    if (status == APAL_STATUS_SUCCESS) {
243
        aosUtPassed(stream, &result);
244
    } else {
245
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
246
    }
247

    
248
    chprintf(stream, "reset device...\n");
249
    status = at42qt1050_lld_reset(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, ((ut_at42qt1050data_t*)ut->data)->timeout, true);
250
    if (status == APAL_STATUS_SUCCESS) {
251
        aosUtPassed(stream, &result);
252
    } else {
253
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
254
    }
255

    
256
    chprintf(stream, "read threshold data again...\n");
257
    status = APAL_STATUS_OK;
258
    const uint8_t threshold_default = 20;
259
    error = false;
260
    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
261
        const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0, key);
262
        status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, &test_8, ((ut_at42qt1050data_t*)ut->data)->timeout);
263
        if(test_8 != threshold_default)
264
            error = true;
265
    }
266

    
267
    if (status == APAL_STATUS_SUCCESS && !error) {
268
        aosUtPassedMsg(stream, &result, "threshold 0x%04X = default\n", threshold_default);
269
    } else {
270
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
271
    }
272

    
273
    chprintf(stream, "demo of default configuration:\n");
274
    status = APAL_STATUS_OK;
275
    show_live(0, &status, stream, ut);
276
    if (status == APAL_STATUS_SUCCESS) {
277
        aosUtPassed(stream, &result);
278
    } else {
279
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
280
    }
281

    
282
    status = APAL_STATUS_OK;
283
    chprintf(stream, "write configuration...\npuls + scale + threshold 8\n");
284
    at42qt1050_lld_pulsescalereg_t pulse_scale;
285
    //values stored as exponent of 2
286
    pulse_scale.pulse = 0; // accumulate #pulses -> increase resolution & time to acquire
287
    pulse_scale.scale = 0; // scale = average factor n: NewAvg = (NewData/n) + [OldAvg*(n-1/n)] -> decrease noise
288
    status  = at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_0, pulse_scale.raw , ((ut_at42qt1050data_t*)ut->data)->timeout);
289
    pulse_scale.pulse = 1;
290
    status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_3, pulse_scale.raw , ((ut_at42qt1050data_t*)ut->data)->timeout);
291

    
292
    pulse_scale.pulse = 4;
293
    status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_1, pulse_scale.raw , ((ut_at42qt1050data_t*)ut->data)->timeout);
294
    status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_2, pulse_scale.raw , ((ut_at42qt1050data_t*)ut->data)->timeout);
295

    
296
    status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_4, pulse_scale.raw , ((ut_at42qt1050data_t*)ut->data)->timeout);
297

    
298
    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
299
        const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0, key);
300
        status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, txbuf, 8, ((ut_at42qt1050data_t*)ut->data)->timeout);
301
    }
302
    chprintf(stream, "disable guard key\n");
303
    status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_INTEGRATOR_AKS_0, 0 , ((ut_at42qt1050data_t*)ut->data)->timeout); //disable key
304
    status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_FINFOUTMAXCALGUARD, 8 , ((ut_at42qt1050data_t*)ut->data)->timeout); //disable feature
305

    
306
    chprintf(stream, "calibrate...\n");
307
    status = at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_RESET_CALIBRATE, AT42QT1050_LLD_RESETCALIBRATE_CALIBRATE, ((ut_at42qt1050data_t*)ut->data)->timeout);
308

    
309

    
310

    
311
    //wait for calibration to complete
312
    error = true;
313
    for(uint8_t i=0; i<0xFF; i++) {
314
        usleep(10);
315
        status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_DETECTIONSTATUS, &test_8, ((ut_at42qt1050data_t*)ut->data)->timeout);
316
        if(!(test_8 & AT42QT1050_LLD_DETECTIONSTATUS_CALIBRATE)) {
317
            error = false;
318
            break;
319
        }
320
    }
321
    if (status == APAL_STATUS_SUCCESS) {
322
        aosUtPassed(stream, &result);
323
    } else {
324
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
325
    }
326
    chprintf(stream, "demo of custom configuration:\n");
327
    status = APAL_STATUS_OK;
328
    show_live(1, &status, stream, ut);
329
    if (status == APAL_STATUS_SUCCESS) {
330
        aosUtPassed(stream, &result);
331
    } else {
332
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
333
    }
334

    
335
    status = APAL_STATUS_OK;
336
    print_settings(&status, stream, ut);
337
    if (status == APAL_STATUS_SUCCESS) {
338
        aosUtPassed(stream, &result);
339
    } else {
340
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
341
    }
342

    
343
    chprintf(stream, "shutdown touch\n");
344
    test_8 = 0; //Power down
345
    status = at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_LOWPOWERMODE, test_8, ((ut_at42qt1050data_t*)ut->data)->timeout);
346
    if (status == APAL_STATUS_SUCCESS) {
347
        aosUtPassed(stream, &result);
348
    } else {
349
        aosUtFailedMsg(stream, &result, "0x%08X\n", status);
350
    }
351

    
352
    aosUtInfoMsg(stream,"driver object memory footprint: %u bytes\n", sizeof(AT42QT1050Driver));
353

    
354
    return result;
355
}
356

    
357
#endif