EFM32 Gecko Software Documentation  efm32g-doc-5.1.2
si114x_sys_out.c
1 /**************************************************************************/
14 #include <stdio.h>
15 #include "i2cspm.h"
16 #include "em_i2c.h"
17 #include "em_gpio.h"
18 #include "string.h"
19 #include "em_usb.h"
20 #include "rtcdriver.h"
21 #include "em_gpio.h"
22 #include "si114x_functions.h"
23 #include "si114x_sys_out.h"
24 #include "si114xhrm.h"
25 
26 #ifdef USB_DEBUG
27  #include "usb_debug.h"
28 #endif
29 
30 /* I2C port configuration */
31 static Si114xPortConfig_t _handle;
32 /* Flag to indicate USB debug is enabled */
33 static bool usbDebugEnable;
34 /* interrupt sequence counter */
35 static uint16_t irqSequence = 0;
36 /* interrupt queue size in bytes */
37 #define IRQ_QUEUE_SIZE 270
38 /* interrupt queue data */
39 static u8 IrqQueue[IRQ_QUEUE_SIZE];
40 /* interrupt queue current get index */
41 static u16 irqQueueGetIndex = 0;
42 /* interrupt queue current put index */
43 static u16 irqQueuePutIndex = 0;
44 
45 /* Non-exported Function Prototypes */
46 static s16 Si114x_i2c_smbus_write_byte_data(HANDLE si114x_handle, u8 address, u8 data, bool block);
47 static s16 Si114x_i2c_smbus_read_byte_data(HANDLE si114x_handle, u8 address, u8 *data, bool block);
48 static s16 Si114x_i2c_smbus_write_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8 const* values, bool block);
49 static s16 Si114x_i2c_smbus_read_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8* values, bool block);
50 static s16 Si114xIrqQueue_Put(SI114X_IRQ_SAMPLE *samples);
51 
52 /**************************************************************************/
55 int si114xSetupDebug(HANDLE si114x_handle, void *si114x_debug)
56 {
57  int *enable_usb_debug = (int *)si114x_debug;
58  (void) si114x_handle;
59  if(*enable_usb_debug == 1)
60  usbDebugEnable = true;
61  else if(*enable_usb_debug == 0)
62  usbDebugEnable = false;
63 
64  return SI114xHRM_SUCCESS;
65 }
66 
67 /**************************************************************************/
70 int si114xOutputDebugMessage(HANDLE si114x_handle, char *message)
71 {
72  uint16_t i;
73  uint8_t message_buffer[((99)+3)&~3] SL_ATTRIBUTE_ALIGN(4);
74  uint8_t *Message_Buffer[1] = {message_buffer};
75  (void) si114x_handle;
76  message_buffer[0] = 0x10;
77  for(i=0; i<strlen(message); i++)
78  message_buffer[i+1] = (uint8_t)message[i];
79  message_buffer[strlen(message)+1] = 0x10;
80  message_buffer[strlen(message)+2] = 0x0D;
81 #ifdef USB_DEBUG
82  USBD_Write(CDC_EP_DATA_IN, (void*) Message_Buffer[0], strlen(message)+3, NULL);
83 #endif
84  return SI114xHRM_SUCCESS;
85 }
86 
87 /**************************************************************************/
90 int16_t Si114xWriteToRegister(HANDLE si114x_handle, uint8_t address, uint8_t data)
91 {
92  return Si114x_i2c_smbus_write_byte_data(si114x_handle, address, data, true);
93 }
94 
95 /**************************************************************************/
98 int16_t Si114xReadFromRegister(HANDLE si114x_handle, uint8_t address)
99 {
100  u8 data;
101  Si114x_i2c_smbus_read_byte_data(si114x_handle, address, &data, true);
102  return data;
103 }
104 
105 /**************************************************************************/
108 int16_t Si114xBlockWrite(HANDLE si114x_handle,
109  uint8_t address, uint8_t length, uint8_t *values)
110 {
111  return Si114x_i2c_smbus_write_i2c_block_data(si114x_handle,
112  address,
113  length,
114  values,
115  true);
116 }
117 
118 /**************************************************************************/
121 int16_t Si114xBlockRead(HANDLE si114x_handle,
122  uint8_t address, uint8_t length, uint8_t *values)
123 {
124  return Si114x_i2c_smbus_read_i2c_block_data(si114x_handle,
125  address, length, values, true);
126 }
127 
128 /**************************************************************************/
131 void DisableSi114xInterrupt ()
132 {
133 
134  GPIO_IntDisable(1<<_handle.irqPin);
135 }
136 
137 /**************************************************************************/
140 void EnableSi114xInterrupt ()
141 {
142  if (GPIO_PinInGet(_handle.irqPort, _handle.irqPin) == 0)
143  GPIO_IntSet(1<<_handle.irqPin);
144  GPIO_IntEnable(1<<_handle.irqPin);
145 }
146 
147 /**************************************************************************/
150 s16 Si114xProcessIrq(HANDLE si114x_handle, u16 timestamp)
151 {
152  u8 data_buffer[13];
153  s16 error;
154  SI114X_IRQ_SAMPLE sample;
155  irqSequence++;
156  Si114x_i2c_smbus_read_i2c_block_data(si114x_handle, 0x21, 13, data_buffer, false); // Grab all data registers
157  Si114x_i2c_smbus_write_byte_data(si114x_handle, 0x21, data_buffer[0], false); // Clear interrupts
158 
159  sample.sequence = irqSequence; // sequence number
160  sample.timestamp = timestamp; // 16-bit Timestamp to record
161  sample.pad= 0;
162  sample.irqstat = data_buffer[0]; // 8-bit irq status
163  sample.vis = (((u16)(data_buffer[2]) << 8) & 0xff00) | data_buffer[1]; // VIS
164  sample.ir = (((u16)(data_buffer[4]) << 8) & 0xff00) | data_buffer[3]; // IR
165  sample.ps1 = (((u16)(data_buffer[6]) << 8) & 0xff00) | data_buffer[5]; // PS1
166  sample.ps2 = (((u16)(data_buffer[8]) << 8) & 0xff00) | data_buffer[7]; // PS2
167  sample.ps3 = (((u16)(data_buffer[10]) << 8) & 0xff00) | data_buffer[9]; // PS3
168  sample.aux = (((u16)(data_buffer[12]) << 8) & 0xff00) | data_buffer[11];; // AUX
169 
170  error = Si114xIrqQueue_Put(&sample);
171  return error;
172 }
173 
174 
175 /**************************************************************************/
178 s16 Si114xIrqQueueNumentries(HANDLE si114x_handle)
179 {
180  (void) si114x_handle;
181  u16 runnerIndex = irqQueueGetIndex;
182  s16 count=0;
183  while (runnerIndex != irqQueuePutIndex)
184  {
185  runnerIndex++;
186  count++;
187  if(runnerIndex == IRQ_QUEUE_SIZE)
188  runnerIndex = 0;
189  }
190  return (count/sizeof(SI114X_IRQ_SAMPLE));
191 
192 }
193 
194 /**************************************************************************/
197 s16 Si114xIrqQueue_Get(HANDLE si114x_handle, SI114X_IRQ_SAMPLE *samples)
198 {
199  (void) si114x_handle;
200  int16_t error = 0;
201  uint16_t i;
202  int8_t *data = (int8_t *)samples;
203  DisableSi114xInterrupt ();
204  if (irqQueueGetIndex == irqQueuePutIndex)
205  error = -1;
206  else
207  {
208  for(i=0; i<sizeof(SI114X_IRQ_SAMPLE); i++)
209  {
210  data[i] = IrqQueue[irqQueueGetIndex];
211  irqQueueGetIndex++;
212  if(irqQueueGetIndex == IRQ_QUEUE_SIZE)
213  irqQueueGetIndex = 0;
214 
215  }
216 
217  }
218  EnableSi114xInterrupt();
219 #ifdef USB_DEBUG
220  if (usbDebugEnable == 1) // Dump data to USB if usb_debug is enabled
221  USBDebug_ProcessUSBOutput(data);
222 #endif // si114xHRM_USB_DEBUG
223  return error;
224 }
225 
226 /**************************************************************************/
229 static s16 Si114xIrqQueue_Put(SI114X_IRQ_SAMPLE *samples)
230 {
231  uint16_t i;
232  u8 *data = (u8 *)samples;
233  for(i=0; i<sizeof(SI114X_IRQ_SAMPLE); i++)
234  {
235  IrqQueue[irqQueuePutIndex] = data[i];
236  irqQueuePutIndex++;
237  if(irqQueuePutIndex == IRQ_QUEUE_SIZE)
238  irqQueuePutIndex = 0;
239  }
240  if (irqQueueGetIndex == irqQueuePutIndex)
241  {
242  irqQueueGetIndex += sizeof(SI114X_IRQ_SAMPLE); // if we have wrapped around then we must delete one sample
243  return -1; //indicate to caller something bad happened
244  }
245  return 0;
246 }
247 
248 /**************************************************************************/
251 s16 Si114xIrqQueue_Clear(HANDLE si114x_handle)
252 {
253  (void) si114x_handle;
254  irqQueueGetIndex = 0;
255  irqQueuePutIndex = 0;
256  return 0;
257 }
258 
259 /**************************************************************************/
262 s16 Si114xInit(void *port, int options, HANDLE *si114x_handle)
263 {
264  s16 error = 0;
265  u8 data;
266 
267  (void) options;
268 
269  *si114x_handle = (HANDLE)&_handle;
270  _handle.i2cPort = ((Si114xPortConfig_t*)port)->i2cPort;
271  _handle.i2cAddress = ((Si114xPortConfig_t*)port)->i2cAddress << 1;
272  _handle.irqPort = ((Si114xPortConfig_t*)port)->irqPort;
273  _handle.irqPin = ((Si114xPortConfig_t*)port)->irqPin;
274 
275  data = Si114xReadFromRegister(*si114x_handle, REG_PART_ID);
276 
277  if ((_handle.i2cAddress == (0x60 << 1)) && (data != 0x46) && (data != 0x47))
278  error = -1;
279  if ((_handle.i2cAddress == (0x5A << 1)) && (data != 0x43))
280  error = -1;
281 
282  Si114xIrqQueue_Clear(*si114x_handle);
283 
284  return error;
285 }
286 
287 /**************************************************************************/
290 s16 Si114xClose(HANDLE si114x_handle)
291 {
292  (void) si114x_handle;
293  _handle.i2cAddress = 0xff;
294  return 0;
295 }
296 
297 /**************************************************************************/
300 s16 Si114xSysReset(HANDLE si114x_handle)
301 {
302  (void) si114x_handle;
303  return 0;
304 }
305 
306 /**************************************************************************/
309 void delay_10ms(void)
310 {
311  RTCDRV_Delay(10);
312  return;
313 }
314 
315 /**************************************************************************/
318 void delay_1ms(void)
319 {
320  RTCDRV_Delay(1);
321  return;
322 }
323 
324 
325 /**************************************************************************/
328 static s16 Si114x_i2c_smbus_write_byte_data(HANDLE si114x_handle, u8 address, u8 data, bool block)
329 {
332  Si114xPortConfig_t* handle;
333  uint8_t i2c_write_data[2];
334  uint8_t i2c_read_data[1];
335 
336  if (block)
337  DisableSi114xInterrupt();
338  seq.addr = _handle.i2cAddress;
339  seq.flags = I2C_FLAG_WRITE;
340  /* Select register and data to write */
341  i2c_write_data[0] = address;
342  i2c_write_data[1] = data;
343  seq.buf[0].data = i2c_write_data;
344  seq.buf[0].len = 2;
345  seq.buf[1].data = i2c_read_data;
346  seq.buf[1].len = 0;
347 
348  handle = (Si114xPortConfig_t *)si114x_handle;
349 
350  ret = I2CSPM_Transfer(handle->i2cPort, &seq);
351 
352  if (block)
353  EnableSi114xInterrupt();
354  if (ret != i2cTransferDone)
355  {
356  return (s16)ret;
357  }
358  return (s16)0;
359 }
360 
361 /**************************************************************************/
364 static s16 Si114x_i2c_smbus_read_byte_data(HANDLE si114x_handle, u8 address, u8 *data, bool block)
365 {
366  // si114x_handle is not used in the EFM32. We use a global instead
369  uint8_t i2c_write_data[1];
370  Si114xPortConfig_t* i2cDrvHandle;
371 
372  if (block)
373  DisableSi114xInterrupt ();
374  seq.addr = _handle.i2cAddress;
376  /* Select register to start reading from */
377  i2c_write_data[0] = address;
378  seq.buf[0].data = i2c_write_data;
379  seq.buf[0].len = 1;
380  /* Select length of data to be read */
381  seq.buf[1].data = data;
382  seq.buf[1].len = 1;
383 
384  i2cDrvHandle = (Si114xPortConfig_t *)si114x_handle;
385 
386  ret = I2CSPM_Transfer(i2cDrvHandle->i2cPort, &seq);
387 
388  if (block)
389  EnableSi114xInterrupt();
390  if (ret != i2cTransferDone)
391  {
392  *data = 0xff;
393  return((int) ret);
394  }
395  return((int) 1);
396 }
397 
398 /**************************************************************************/
401 static s16 Si114x_i2c_smbus_write_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8 const* data, bool block)
402 {
405  uint8_t i2c_write_data[10];
406  uint8_t i2c_read_data[1];
407  Si114xPortConfig_t* handle;
408  int i;
409 
410  if (block)
411  DisableSi114xInterrupt ();
412  seq.addr = _handle.i2cAddress;
413  seq.flags = I2C_FLAG_WRITE;
414  /* Select register to start writing to*/
415  i2c_write_data[0] = address;
416  for (i=0; i<length;i++)
417  {
418  i2c_write_data[i+1] = data[i];
419  }
420  seq.buf[0].data = i2c_write_data;
421  seq.buf[0].len = 1+length;
422  seq.buf[1].data = i2c_read_data;
423  seq.buf[1].len = 0;
424 
425  handle = (Si114xPortConfig_t *)si114x_handle;
426 
427  ret = I2CSPM_Transfer(handle->i2cPort, &seq);
428 
429  if (block)
430  EnableSi114xInterrupt ();
431  if (ret != i2cTransferDone)
432  {
433  return((int) ret);
434  }
435 
436  return((int) 0);
437 }
438 
439 /**************************************************************************/
442 static s16 Si114x_i2c_smbus_read_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8* data, bool block)
443 {
446  uint8_t i2c_write_data[1];
447  Si114xPortConfig_t* handle;
448 
449  seq.addr = _handle.i2cAddress;
451  if (block)
452  DisableSi114xInterrupt ();
453  /* Select register to start reading from */
454  i2c_write_data[0] = address;
455  seq.buf[0].data = i2c_write_data;
456  seq.buf[0].len = 1;
457 
458  /* Select length of data to be read */
459  seq.buf[1].data = data;
460  seq.buf[1].len = length;
461 
462  handle = (Si114xPortConfig_t *)si114x_handle;
463 
464  ret = I2CSPM_Transfer(handle->i2cPort, &seq);
465 
466  if (block)
467  EnableSi114xInterrupt ();
468  if (ret != i2cTransferDone)
469  {
470  return((int) ret);
471  }
472 
473  return((int) 0);
474 }
475 
476 int si114xFindEvb(char *port_description, char *last_port, int num_ports_found)
477 {
478  (void) port_description;
479  (void) last_port;
480  (void) num_ports_found;
481  return 0;
482 }
483 
void delay_10ms(void)
10ms delay required by Si114x reset sequence.
Si114x Sample Data Structure.
Definition: si114x_types.h:90
I2C_TransferReturn_TypeDef I2CSPM_Transfer(I2C_TypeDef *i2c, I2C_TransferSeq_TypeDef *seq)
Perform I2C transfer.
Definition: i2cspm.c:124
Si114x function prototypes, structure and bit definitions.
unsigned short int u16
Definition: bmp280.h:283
I2C_TypeDef * i2cPort
int16_t Si114xBlockWrite(HANDLE si114x_handle, uint8_t address, uint8_t length, uint8_t *values)
block write to si114x
#define I2C_FLAG_WRITE
Indicate plain write sequence: S+ADDR(W)+DATA0+P.
Definition: em_i2c.h:124
RTCDRV timer API definition.
I2C_TransferReturn_TypeDef
Definition: em_i2c.h:179
int16_t Si114xWriteToRegister(HANDLE si114x_handle, uint8_t address, uint8_t data)
Write to Si114x register.
__STATIC_INLINE void GPIO_IntDisable(uint32_t flags)
Disable one or more GPIO interrupts.
Definition: em_gpio.h:686
__STATIC_INLINE void GPIO_IntEnable(uint32_t flags)
Enable one or more GPIO interrupts.
Definition: em_gpio.h:703
signed short int s16
Definition: bmp280.h:277
void delay_1ms(void)
1ms delay required by Si114x polling sequence.
General Purpose IO (GPIO) peripheral API.
I2C simple poll-based master mode driver for the DK/STK.
unsigned char u8
Definition: bmp280.h:282
Ecode_t RTCDRV_Delay(uint32_t ms)
Millisecond delay function.
Definition: rtcdriver.c:270
#define SL_ATTRIBUTE_ALIGN(X)
GCC style macro for aligning a variable.
Definition: em_common.h:160
Implementation specific functions for HRM code.
__STATIC_INLINE void GPIO_IntSet(uint32_t flags)
Set one or more pending GPIO interrupts from SW.
Definition: em_gpio.h:754
struct I2C_TransferSeq_TypeDef::@0 buf[2]
int16_t Si114xReadFromRegister(HANDLE si114x_handle, uint8_t address)
Read from Si114x register.
Master mode transfer message structure used to define a complete I2C transfer sequence (from start to...
Definition: em_i2c.h:252
int16_t Si114xBlockRead(HANDLE si114x_handle, uint8_t address, uint8_t length, uint8_t *values)
Block read from Si114x.
static void * si114x_handle
Si114x PGM toolkit functions uses a void* to pass hardware parameters through to the lower level i2c ...
uint16_t timestamp
Definition: si114x_types.h:93
#define I2C_FLAG_WRITE_READ
Indicate combined write/read sequence: S+ADDR(W)+DATA0+Sr+ADDR(R)+DATA1+P.
Definition: em_i2c.h:148
Inter-intergrated circuit (I2C) peripheral API.
__STATIC_INLINE unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
Read the pad value for a single pin in a GPIO port.
Definition: em_gpio.h:781
uint16_t addr
Address to use after (repeated) start.
Definition: em_i2c.h:262
GPIO_Port_TypeDef irqPort