summaryrefslogtreecommitdiff
path: root/firmware/export/mpr121.h
blob: 96b83ecc9046c1b439a218b5840f79b8acf52460 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2012 Amaury Pouly
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

/** Driver for the Freescale MPR121 Capacitive Proximity Sensor */
#include "system.h"

#define ELECTRODE_COUNT 12
#define ELE_GPIO_FIRST  4
#define ELE_GPIO_LAST   11

/* gpio config (encoding: [0]=en,[1]=dir,[2]=ctl[1],[3]=ctl[0]) */
#define ELE_GPIO_DISABLE        0
#define ELE_GPIO_INPUT          1
#define ELE_GPIO_INPUT_PULLDOWN 9 /* input with pull-down */
#define ELE_GPIO_INPUT_PULLUP   13 /* input with pull-up */
#define ELE_GPIO_OUTPUT         3
#define ELE_GPIO_OUTPUT_OPEN     11 /* open drain low-side */
#define ELE_GPIO_OUTPUT_OPEN_LED 15 /* open drain high-side (led driver) */

/* internal use */
#define ELE_GPIO_EN(val)    ((val) & 1)
#define ELE_GPIO_DIR(val)   (((val) >> 1) & 1)
#define ELE_GPIO_CTL0(val)  (((val) >> 3) & 1)
#define ELE_GPIO_CTL1(val)  (((val) >> 1) & 1)

struct mpr121_electrode_config_t
{
    uint8_t bv; /* baseline value */
    uint8_t tth; /* touch threshold */
    uint8_t rth; /* release threshold */
    uint8_t cdc; /* charge current (optional if auto-conf) */
    uint8_t cdt; /* charge time (optional if auto-conf) */
    int gpio; /* gpio config */
};

struct mpr121_baseline_filter_config_t
{
    uint8_t mhd; /* max half delta (except for touched) */
    uint8_t nhd; /* noise half delta */
    uint8_t ncl; /* noise count limit */
    uint8_t fdl; /* filter delay count limit */
};

struct mpr121_baseline_filters_config_t
{
    struct mpr121_baseline_filter_config_t rising;
    struct mpr121_baseline_filter_config_t falling;
    struct mpr121_baseline_filter_config_t touched;
};

struct mpr121_debounce_config_t
{
    uint8_t dt; /* debounce count for touch */
    uint8_t dr; /* debounce count for release */
};

/* first filter iterations */
#define FFI_6_SAMPLES   0
#define FFI_10_SAMPLES  1
#define FFI_18_SAMPLES  2
#define FFI_34_SAMPLES  3
/* charge discharge current */
#define CDC_DISABLE     0
#define CDC_uA(ua)      (ua)
/* charge discharge time */
#define CDT_DISABLE     0
#define CDT_log_us(lus) (lus) /* actual value = 2^{us-2} µs */
/* second filter iterations */
#define SFI_4_SAMPLES   0
#define SFI_6_SAMPLES   1
#define SFI_10_SAMPLES  2
#define SFI_18_SAMPLES  3
/* Eletrode sample interval */
#define ESI_log_ms(lms) (lms) /* actual value = 2^{lms} ms */

struct mpr121_global_config_t
{
    uint8_t ffi; /* first filter iterations */
    uint8_t cdc; /* global charge discharge current */
    uint8_t cdt; /* global charge discharge time */
    uint8_t sfi; /* second first iterations */
    uint8_t esi; /* electrode sample interval */
};

#define RETRY_NEVER     0
#define RETRY_2_TIMES   1
#define RETRY_4_TIMES   2
#define RETRY_8_TIMES   3

struct mpr121_auto_config_t
{
    bool en; /* auto-conf enable */
    bool ren; /* auto-reconf enable */
    uint8_t retry; /* retry count */
    bool scts; /* skip charge time search */
    uint8_t usl; /* upper-side limit */
    uint8_t lsl; /* lower-side limit */
    uint8_t tl; /* target level */
    bool acfie; /* auto-conf fail interrupt en */
    bool arfie; /* auto-reconf fail interrupt en */
    bool oorie; /* out of range interrupt en */
};

/* electrode mode */
#define ELE_DISABLE     0
#define ELE_EN0_x(x)    ((x) + 1)
/* eleprox mode */
#define ELEPROX_DISABLE 0
#define ELEPROX_EN0_1   1
#define ELEPROX_EN0_3   2
#define ELEPROX_EN0_11  3
/* calibration lock */
#define CL_SLOW_TRACK   0
#define CL_DISABLE      1
#define CL_TRACK        2
#define CL_FAST_TRACK   3

struct mpr121_config_t
{
    struct mpr121_electrode_config_t ele[ELECTRODE_COUNT];
    struct mpr121_electrode_config_t eleprox;
    struct
    {
        struct mpr121_baseline_filters_config_t ele;
        struct mpr121_baseline_filters_config_t eleprox;
    }filters;
    struct mpr121_debounce_config_t debounce;
    struct mpr121_global_config_t global;
    struct mpr121_auto_config_t autoconf;
    uint8_t ele_en; /* eletroce mode */
    uint8_t eleprox_en; /* proximity mode */
    uint8_t cal_lock; /* calibration lock */
};

/* gpio value */
#define ELE_GPIO_CLR    0
#define ELE_GPIO_SET    1
#define ELE_GPIO_TOG    2
/* pwm value */
#define ELE_PWM_DISABLE 0
#define ELE_PWM_DUTY(x) (x)
#define ELE_PWM_MIN_DUTY    1
#define ELE_PWM_MAX_DUTY    15

int mpr121_init(int dev_i2c_addr);
int mpr121_soft_reset(void);
int mpr121_set_config(struct mpr121_config_t *conf);
/* gpios are only implemented for electrode>=4 */
int mpr121_set_gpio_output(int ele, int gpio_val);
int mpr121_set_gpio_pwm(int ele, int pwm);
/* get electrode status (bitmap) */
int mpr121_get_touch_status(unsigned *status);