Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_zssc3123.c
1 #include <bc_zssc3123.h>
2 #include <bc_timer.h>
3 #include <bc_log.h>
4 
5 static uint8_t _bc_zssc3123_get_response(bc_zssc3123_t *self);
6 static void _bc_zssc3123_task(void *param);
7 
8 bool bc_zssc3123_init(bc_zssc3123_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
9 {
10  memset(self, 0, sizeof(*self));
11 
12  self->_i2c_channel = i2c_channel;
13  self->_i2c_address = i2c_address;
14 
15  bc_timer_init();
16 
17  bc_i2c_init(self->_i2c_channel, BC_I2C_SPEED_400_KHZ);
18 
19  self->_update_interval = BC_TICK_INFINITY;
20 
21  self->_data_fetch_delay = 100;
22 
23  self->_task_id = bc_scheduler_register(_bc_zssc3123_task, self, BC_TICK_INFINITY);
24 
25  return true;
26 }
27 
29 {
30  bc_i2c_deinit(self->_i2c_channel);
31 
32  bc_scheduler_unregister(self->_task_id);
33 
34  return true;
35 }
36 
38 {
39  self->_data_fetch_delay = interval;
40 }
41 
42 void bc_zssc3123_set_event_handler(bc_zssc3123_t *self, void (*event_handler)(bc_zssc3123_t *, bc_zssc3123_event_t, void *), void *event_param)
43 {
44  self->_event_handler = event_handler;
45  self->_event_param = event_param;
46 }
47 
49 {
50  self->_update_interval = interval;
51 
52  if (self->_update_interval == BC_TICK_INFINITY)
53  {
54  if (!self->_measurement_active)
55  {
57  }
58  }
59  else
60  {
61  bc_zssc3123_measure(self);
62  }
63 }
64 
66 {
67  if (self->_measurement_active)
68  {
69  return false;
70  }
71 
72  self->_measurement_active = true;
73 
74  bc_scheduler_plan_now(self->_task_id);
75 
76  return true;
77 }
78 
79 bool bc_zssc3123_get_raw_cap_data(bc_zssc3123_t *self, uint16_t *raw)
80 {
81  if (!self->_valid)
82  {
83  return false;
84  }
85 
86  *raw = self->_raw;
87 
88  return true;
89 }
90 
92 {
93  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0xA0, 0x0000))
94  {
95  return false;
96  }
97 
98  return (_bc_zssc3123_get_response(self) >> 6) == 2;
99 }
100 
102 {
103  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x80, 0x0000))
104  {
105  return false;
106  }
107 
108  return true;
109 }
110 
111 bool bc_zssc3123_eeprom_read(bc_zssc3123_t *self, uint8_t adr, uint16_t *word)
112 {
113  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, adr, 0x0000))
114  {
115  return false;
116  }
117 
118  bc_timer_start();
119 
120  bc_timer_delay(90);
121 
122  bc_timer_stop();
123 
124  uint8_t buffer[3];
125 
126  bc_i2c_transfer_t transfer;
127 
128  transfer.device_address = self->_i2c_address;
129 
130  transfer.buffer = buffer;
131 
132  transfer.length = sizeof(buffer);
133 
134  if (!bc_i2c_read(self->_i2c_channel, &transfer))
135  {
136  return false;
137 
138  }
139 
140  if ((buffer[0] & 0x03) != 1)
141  {
142  return false;
143  }
144 
145  *word = ((uint16_t) buffer[1]) << 8 | buffer[2];
146 
147  return true;
148 }
149 
150 bool bc_zssc3123_eeprom_write(bc_zssc3123_t *self, uint8_t address, uint16_t word)
151 {
152  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x40 + address, word))
153  {
154  return false;
155  }
156 
157  bc_timer_start();
158 
159  bc_timer_delay(12000);
160 
161  bc_timer_stop();
162 
163  return (_bc_zssc3123_get_response(self) & 0x03) == 1;
164 }
165 
167 {
168  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0xa2, 0x0000))
169  {
170  return false;
171  }
172 
173  if (!bc_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0xf0, 0x0021))
174  {
175  return false;
176  }
177 
178  return true;
179 }
180 
181 static uint8_t _bc_zssc3123_get_response(bc_zssc3123_t *self)
182 {
183  bc_i2c_transfer_t transfer;
184 
185  uint8_t data;
186 
187  transfer.device_address = self->_i2c_address;
188 
189  transfer.buffer = &data;
190 
191  transfer.length = 1;
192 
193  if (!bc_i2c_read(self->_i2c_channel, &transfer))
194  {
195  return 0xff;
196  }
197  else
198  {
199  return data;
200  }
201 }
202 
203 static bool _bc_zssc3123_data_fetch(bc_zssc3123_t *self)
204 {
205  bc_i2c_transfer_t transfer;
206 
207  uint8_t buffer[2];
208 
209  transfer.device_address = self->_i2c_address;
210 
211  transfer.buffer = buffer;
212 
213  transfer.length = sizeof(buffer);
214 
215  if (!bc_i2c_read(self->_i2c_channel, &transfer))
216  {
217  return false;
218  }
219 
220  if ((buffer[0] & 0xc0) == 0)
221  {
222  self->_valid = true;
223 
224  self->_raw = (uint16_t) (buffer[0] & 0x3f) << 8 | buffer[1];
225  }
226 
227  return true;
228 }
229 
230 static bool _bc_zssc3123_measurement_request(bc_zssc3123_t *self)
231 {
232  bc_i2c_transfer_t transfer;
233 
234  uint8_t buffer[1] = { self->_i2c_address << 1 };
235 
236  transfer.device_address = self->_i2c_address;
237 
238  transfer.buffer = buffer;
239 
240  transfer.length = sizeof(buffer);
241 
242  if (!bc_i2c_write(self->_i2c_channel, &transfer))
243  {
244  return false;
245  }
246 
247  return true;
248 }
249 
250 static void _bc_zssc3123_task(void *param)
251 {
252  bc_zssc3123_t *self = param;
253 
254 start:
255 
256  switch (self->_state)
257  {
258  case BC_ZSSC3123_STATE_ERROR:
259  {
260  self->_valid = false;
261 
262  self->_measurement_active = false;
263 
264  if (self->_event_handler != NULL)
265  {
266  self->_event_handler(self, BC_ZSSC3123_EVENT_ERROR, self->_event_param);
267  }
268 
269  self->_state = BC_ZSSC3123_STATE_INITIALIZE;
270 
271  bc_scheduler_plan_current_absolute(self->_next_update_start);
272 
273  return;
274  }
275  case BC_ZSSC3123_STATE_INITIALIZE:
276  {
277  self->_next_update_start = bc_tick_get() + self->_update_interval;
278 
279  if (!_bc_zssc3123_data_fetch(self))
280  {
281  self->_state = BC_ZSSC3123_STATE_ERROR;
282 
283  goto start;
284  }
285 
286  self->_state = BC_ZSSC3123_STATE_MEASURE;
287 
289 
290  return;
291  }
292  case BC_ZSSC3123_STATE_MEASURE:
293  {
294  self->_next_update_start = bc_tick_get() + self->_update_interval;
295 
296  self->_measurement_active = true;
297 
298  self->_valid = false;
299 
300  if (!_bc_zssc3123_measurement_request(self))
301  {
302  self->_state = BC_ZSSC3123_STATE_ERROR;
303 
304  goto start;
305  }
306 
307  self->_state = BC_ZSSC3123_STATE_READ;
308 
309  bc_scheduler_plan_current_from_now(self->_data_fetch_delay);
310 
311  return;
312  }
313  case BC_ZSSC3123_STATE_READ:
314  {
315  if (!_bc_zssc3123_data_fetch(self))
316  {
317  self->_state = BC_ZSSC3123_STATE_ERROR;
318 
319  goto start;
320  }
321 
322  self->_measurement_active = false;
323 
324  self->_state = BC_ZSSC3123_STATE_MEASURE;
325 
326  bc_scheduler_plan_current_absolute(self->_next_update_start);
327 
328  if (self->_event_handler != NULL)
329  {
330  self->_event_handler(self, BC_ZSSC3123_EVENT_UPDATE, self->_event_param);
331  }
332 
333  return;
334  }
335  default:
336  {
337  self->_state = BC_ZSSC3123_STATE_ERROR;
338 
339  goto start;
340  }
341  }
342 }
I2C transfer parameters.
Definition: bc_i2c.h:42
void bc_zssc3123_set_update_interval(bc_zssc3123_t *self, bc_tick_t interval)
Set scan interval.
Definition: bc_zssc3123.c:48
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
bool bc_i2c_memory_write_16b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t data)
Memory write 2 bytes to I2C channel.
Definition: bc_i2c.c:414
bool bc_zssc3123_unlock_eeprom(bc_zssc3123_t *self)
Unlock eerpom, work only with command mode.
Definition: bc_zssc3123.c:166
bool bc_zssc3123_start_cm(bc_zssc3123_t *self)
Start Command Mode.
Definition: bc_zssc3123.c:91
I2C communication speed is 400 kHz.
Definition: bc_i2c.h:36
bool bc_zssc3123_measure(bc_zssc3123_t *self)
Start measurement manually.
Definition: bc_zssc3123.c:65
void bc_scheduler_plan_absolute(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to absolute tick.
Definition: bc_scheduler.c:124
bool bc_zssc3123_deinit(bc_zssc3123_t *self)
Deitialize ZSSC3123.
Definition: bc_zssc3123.c:28
bool bc_zssc3123_get_raw_cap_data(bc_zssc3123_t *self, uint16_t *raw)
Get capacitance data as raw value.
Definition: bc_zssc3123.c:79
void bc_timer_start(void)
Start timer.
Definition: bc_timer.c:24
uint8_t device_address
7-bit I2C device address
Definition: bc_i2c.h:45
bool bc_zssc3123_init(bc_zssc3123_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize ZSSC3123.
Definition: bc_zssc3123.c:8
bool bc_i2c_read(bc_i2c_channel_t channel, const bc_i2c_transfer_t *transfer)
Read from I2C channel.
Definition: bc_i2c.c:283
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
void bc_scheduler_plan_now(bc_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
Definition: bc_scheduler.c:119
void bc_timer_delay(uint16_t microseconds)
Relative delay.
Definition: bc_timer.c:40
struct bc_zssc3123_t bc_zssc3123_t
ZSSC3123 instance.
Definition: bc_zssc3123.h:25
void bc_scheduler_plan_current_absolute(bc_tick_t tick)
Schedule current task to absolute tick.
Definition: bc_scheduler.c:144
void bc_i2c_init(bc_i2c_channel_t channel, bc_i2c_speed_t speed)
Initialize I2C channel.
Definition: bc_i2c.c:54
void bc_i2c_deinit(bc_i2c_channel_t channel)
Deitialize I2C channel.
Definition: bc_i2c.c:139
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
void * buffer
Pointer to buffer which is being written or read.
Definition: bc_i2c.h:48
void bc_timer_stop(void)
Stop timer.
Definition: bc_timer.c:55
bool bc_i2c_write(bc_i2c_channel_t channel, const bc_i2c_transfer_t *transfer)
Write to I2C channel.
Definition: bc_i2c.c:237
void bc_zssc3123_set_data_fetch_delay(bc_zssc3123_t *self, bc_tick_t interval)
Set data fetch delay.
Definition: bc_zssc3123.c:37
void bc_zssc3123_set_event_handler(bc_zssc3123_t *self, void(*event_handler)(bc_zssc3123_t *, bc_zssc3123_event_t, void *), void *event_param)
Set callback function.
Definition: bc_zssc3123.c:42
bool bc_zssc3123_end_cm(bc_zssc3123_t *self)
Ends Command Mode.
Definition: bc_zssc3123.c:101
bc_i2c_channel_t
I2C channels.
Definition: bc_i2c.h:15
bool bc_zssc3123_eeprom_read(bc_zssc3123_t *self, uint8_t adr, uint16_t *word)
Write to eeprom, work only with command mode.
Definition: bc_zssc3123.c:111
size_t length
Length of buffer which is being written or read.
Definition: bc_i2c.h:51
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bool bc_zssc3123_eeprom_write(bc_zssc3123_t *self, uint8_t address, uint16_t word)
Read from eeprm, work only with command mode.
Definition: bc_zssc3123.c:150
void bc_timer_init(void)
Initialize timer.
Definition: bc_timer.c:18
bc_zssc3123_event_t
Callback events.
Definition: bc_zssc3123.h:13
void bc_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
Definition: bc_scheduler.c:139
void bc_scheduler_unregister(bc_scheduler_task_id_t task_id)
Unregister specified task.
Definition: bc_scheduler.c:80