Firmware SDK
twr_cy8cmbr3102.c
1 #include <twr_cy8cmbr3102.h>
2 
3 #define _TWR_CY8CMBR3102_START_INTERVAL 1500
4 #define _TWR_CY8CMBR3102_SCAN_INTERVAL 100
5 #define _TWR_CY8CMBR3102_SCAN_INTERVAL_IS_TOUCH 1000
6 
7 static const uint8_t _twr_cy8cmbr3102_default_setting[] = {
8  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9  0x00, 0x00, 0x00, 0x00, 0x32, 0x7F, 0x00, 0x00,
10  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
12  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80,
13  0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,
14  0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00,
15  0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16  0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17  0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x54,
18  0x00, 0x37, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x00,
19  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x0E
24 };
25 
26 static void _twr_cy8cmbr3102_task(void *param);
27 
28 bool twr_cy8cmbr3102_init(twr_cy8cmbr3102_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
29 {
30  memset(self, 0, sizeof(*self));
31 
32  self->_i2c_channel = i2c_channel;
33  self->_i2c_address = i2c_address;
34 
35  twr_i2c_init(self->_i2c_channel, TWR_I2C_SPEED_400_KHZ);
36 
37  self->_scan_interval = _TWR_CY8CMBR3102_SCAN_INTERVAL;
38 
39  self->_task_id_task = twr_scheduler_register(_twr_cy8cmbr3102_task, self, _TWR_CY8CMBR3102_START_INTERVAL);
40 
41  return true;
42 }
43 
44 void twr_cy8cmbr3102_set_event_handler(twr_cy8cmbr3102_t *self, void (*event_handler)(twr_cy8cmbr3102_t *, twr_cy8cmbr3102_event_t, void *), void *event_param)
45 {
46  self->_event_handler = event_handler;
47  self->_event_param = event_param;
48 }
49 
51 {
52  self->_scan_interval = scan_interval;
53 
54  twr_scheduler_plan_absolute(self->_task_id_task, _TWR_CY8CMBR3102_START_INTERVAL < twr_tick_get() ? _TWR_CY8CMBR3102_START_INTERVAL: 0);
55 }
56 
58 {
59  return twr_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0xba, &value);
60 }
61 
62 bool twr_cy8cmbr3102_is_touch(twr_cy8cmbr3102_t *self, bool *is_touch)
63 {
64  uint8_t prox_stat = 0;
65 
66  if (!twr_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0xae, &prox_stat))
67  {
68  return false;
69  }
70 
71  *is_touch = (prox_stat & 0x01) != 0;
72 
73  return true;
74 }
75 
76 
77 static void _twr_cy8cmbr3102_task(void *param)
78 {
79  twr_cy8cmbr3102_t *self = param;
80 
81  start:
82 
83  switch (self->_state)
84  {
85  case TWR_CY8CMBR3102_STATE_ERROR:
86  {
87  if (self->_event_handler != NULL)
88  {
89  self->_event_handler(self, TWR_CY8CMBR3102_EVENT_ERROR, self->_event_param);
90  }
91 
92  self->_state = TWR_CY8CMBR3102_STATE_INITIALIZE;
93 
94  twr_scheduler_plan_current_from_now(self->_scan_interval);
95 
96  return;
97  }
98  case TWR_CY8CMBR3102_STATE_INITIALIZE:
99  {
100  twr_i2c_memory_transfer_t transfer;
101  transfer.device_address = self->_i2c_address;
102  transfer.memory_address = 0x00;
103  transfer.buffer = (uint8_t *)_twr_cy8cmbr3102_default_setting;
104  transfer.length = sizeof(_twr_cy8cmbr3102_default_setting);
105 
106  if (!twr_i2c_memory_write(self->_i2c_channel, &transfer))
107  {
108  if (self->_error_cnt++ < 2)
109  {
111 
112  return;
113  }
114 
115  self->_error_cnt = 0;
116 
117  self->_state = TWR_CY8CMBR3102_STATE_ERROR;
118 
119  goto start;
120  }
121 
122  self->_state = TWR_CY8CMBR3102_STATE_CALC_CONFIG_CRC;
123 
125 
126  return;
127  }
128  case TWR_CY8CMBR3102_STATE_CALC_CONFIG_CRC:
129  {
130  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x86, 0x02))
131  {
132  self->_state = TWR_CY8CMBR3102_STATE_ERROR;
133 
134  goto start;
135  }
136 
137  self->_state = TWR_CY8CMBR3102_STATE_SELF_RESET;
138 
140 
141  return;
142  }
143  case TWR_CY8CMBR3102_STATE_SELF_RESET:
144  {
145  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x86, 0xff))
146  {
147  self->_state = TWR_CY8CMBR3102_STATE_ERROR;
148  goto start;
149  }
150 
151  self->_state = TWR_CY8CMBR3102_STATE_READ;
152 
154 
155  return;
156  }
157  case TWR_CY8CMBR3102_STATE_READ:
158  {
159  bool is_touch;
160 
161  if (!twr_cy8cmbr3102_is_touch(self, &is_touch))
162  {
163  if (self->_error_cnt++ < 2)
164  {
166 
167  return;
168  }
169 
170  self->_error_cnt = 0;
171 
172  self->_state = TWR_CY8CMBR3102_STATE_ERROR;
173 
174  goto start;
175  }
176 
177  if (is_touch)
178  {
179  if (self->_event_handler != NULL)
180  {
181  self->_event_handler(self, TWR_CY8CMBR3102_EVENT_TOUCH, self->_event_param);
182  }
183 
184  twr_scheduler_plan_current_from_now(_TWR_CY8CMBR3102_SCAN_INTERVAL_IS_TOUCH);
185 
186  return;
187  }
188 
189  twr_scheduler_plan_current_from_now(self->_scan_interval);
190 
191  return;
192  }
193  default:
194  {
195  self->_state = TWR_CY8CMBR3102_STATE_ERROR;
196 
197  goto start;
198  }
199  }
200 }
201 
twr_cy8cmbr3102_event_t
Callback events.
bool twr_cy8cmbr3102_is_touch(twr_cy8cmbr3102_t *self, bool *is_touch)
Is touch.
bool twr_cy8cmbr3102_get_proximity(twr_cy8cmbr3102_t *self, uint16_t value)
Get proximity (Capacitive sensor difference count signal.)
void twr_cy8cmbr3102_set_scan_interval(twr_cy8cmbr3102_t *self, twr_tick_t scan_interval)
Set scan interval.
void twr_cy8cmbr3102_set_event_handler(twr_cy8cmbr3102_t *self, void(*event_handler)(twr_cy8cmbr3102_t *, twr_cy8cmbr3102_event_t, void *), void *event_param)
Set callback function.
bool twr_cy8cmbr3102_init(twr_cy8cmbr3102_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize CY8CMBR3102.
struct twr_cy8cmbr3102_t twr_cy8cmbr3102_t
TCA9534A instance.
@ TWR_CY8CMBR3102_EVENT_TOUCH
Update event.
@ TWR_CY8CMBR3102_EVENT_ERROR
Error event.
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
Definition: twr_i2c.c:57
bool twr_i2c_memory_write(twr_i2c_channel_t channel, const twr_i2c_memory_transfer_t *transfer)
Memory write to I2C channel.
Definition: twr_i2c.c:333
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: twr_i2c.c:408
bool twr_i2c_memory_read_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t *data)
Memory read 2 bytes from I2C channel.
Definition: twr_i2c.c:449
bool twr_i2c_memory_read_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: twr_i2c.c:437
twr_i2c_channel_t
I2C channels.
Definition: twr_i2c.h:16
@ TWR_I2C_SPEED_400_KHZ
I2C communication speed is 400 kHz.
Definition: twr_i2c.h:36
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
I2C memory transfer parameters.
Definition: twr_i2c.h:58
uint32_t memory_address
8-bit I2C memory address (it can be extended to 16-bit format if OR-ed with TWR_I2C_MEMORY_ADDRESS_16...
Definition: twr_i2c.h:63
uint8_t device_address
7-bit I2C device address
Definition: twr_i2c.h:60
size_t length
Length of buffer which is being written or read.
Definition: twr_i2c.h:69
void * buffer
Pointer to buffer which is being written or read.
Definition: twr_i2c.h:66