si114x_sys_out.c

00001 /**************************************************************************/
00014 #include <stdio.h>
00015 #include "i2cspm.h"
00016 #include "em_i2c.h"
00017 #include "em_gpio.h"
00018 #include "string.h"
00019 #include "em_usb.h"
00020 #include "rtcdriver.h"
00021 #include "em_gpio.h"
00022 #include "si114x_functions.h"
00023 #include "si114x_sys_out.h"
00024 #include "si114xhrm.h"
00025 
00026 #ifdef USB_DEBUG
00027     #include "usb_debug.h"
00028 #endif
00029 
00030 /*  I2C port configuration */
00031 static Si114xPortConfig_t _handle;
00032 /*  Flag to indicate USB debug is enabled  */
00033 static bool     usbDebugEnable;
00034 /*  interrupt sequence counter  */
00035 static uint16_t irqSequence = 0;
00036 /*  interrupt queue size in bytes  */
00037 #define IRQ_QUEUE_SIZE  270
00038 /*  interrupt queue data */
00039 static u8 IrqQueue[IRQ_QUEUE_SIZE];
00040 /*  interrupt queue current get index  */
00041 static u16 irqQueueGetIndex = 0;
00042 /*  interrupt queue current put index  */
00043 static u16 irqQueuePutIndex = 0;
00044 
00045 /*  Non-exported Function Prototypes  */
00046 static s16 Si114x_i2c_smbus_write_byte_data(HANDLE si114x_handle, u8 address, u8 data, bool block);
00047 static s16 Si114x_i2c_smbus_read_byte_data(HANDLE si114x_handle, u8 address, u8 *data, bool block);
00048 static s16 Si114x_i2c_smbus_write_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8 const* values, bool block);
00049 static s16 Si114x_i2c_smbus_read_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8* values, bool block);
00050 static s16 Si114xIrqQueue_Put(SI114X_IRQ_SAMPLE *samples);
00051 
00052 /**************************************************************************/
00055 int si114xSetupDebug(HANDLE si114x_handle, void *si114x_debug)
00056 {
00057   int *enable_usb_debug = (int *)si114x_debug;
00058   (void) si114x_handle;
00059   if(*enable_usb_debug == 1)
00060     usbDebugEnable = true;
00061   else if(*enable_usb_debug == 0)
00062     usbDebugEnable = false;
00063 
00064   return SI114xHRM_SUCCESS;
00065 }
00066 
00067 /**************************************************************************/
00070 int si114xOutputDebugMessage(HANDLE si114x_handle, char *message)
00071 {
00072   uint16_t i;
00073   uint8_t message_buffer[((99)+3)&~3] __attribute__ ((aligned(4)));
00074   uint8_t *Message_Buffer[1] = {message_buffer};
00075   (void) si114x_handle;
00076   message_buffer[0] = 0x10;
00077   for(i=0; i<strlen(message); i++)
00078     message_buffer[i+1] = (uint8_t)message[i];
00079   message_buffer[strlen(message)+1] = 0x10;
00080   message_buffer[strlen(message)+2] = 0x0D;
00081 #ifdef USB_DEBUG
00082   USBD_Write(CDC_EP_DATA_IN, (void*) Message_Buffer[0], strlen(message)+3, NULL);
00083 #endif
00084   return SI114xHRM_SUCCESS;
00085 }
00086 
00087 /**************************************************************************/
00090 int16_t Si114xWriteToRegister(HANDLE si114x_handle, uint8_t address, uint8_t data)
00091 {
00092   return Si114x_i2c_smbus_write_byte_data(si114x_handle, address, data, true);
00093 }
00094 
00095 /**************************************************************************/
00098 int16_t Si114xReadFromRegister(HANDLE si114x_handle, uint8_t address)
00099 {
00100   u8 data;
00101   Si114x_i2c_smbus_read_byte_data(si114x_handle, address, &data, true);
00102   return data;
00103 }
00104 
00105 /**************************************************************************/
00108 int16_t Si114xBlockWrite(HANDLE si114x_handle,
00109                      uint8_t address, uint8_t length, uint8_t *values)
00110 {
00111   return Si114x_i2c_smbus_write_i2c_block_data(si114x_handle,
00112                                                address,
00113                                                length,
00114                                                values,
00115                                                true);
00116 }
00117 
00118 /**************************************************************************/
00121 int16_t Si114xBlockRead(HANDLE si114x_handle,
00122                     uint8_t address, uint8_t length, uint8_t *values)
00123 {
00124     return Si114x_i2c_smbus_read_i2c_block_data(si114x_handle,
00125                            address,    length,     values, true);
00126 }
00127 
00128 /**************************************************************************/
00131 void DisableSi114xInterrupt ()
00132 {
00133 
00134     GPIO_IntDisable(1<<_handle.irqPin);
00135 }
00136 
00137 /**************************************************************************/
00140 void EnableSi114xInterrupt ()
00141 {
00142     if (GPIO_PinInGet(_handle.irqPort, _handle.irqPin) == 0)
00143         GPIO_IntSet(1<<_handle.irqPin);
00144     GPIO_IntEnable(1<<_handle.irqPin);
00145 }
00146 
00147 /**************************************************************************/
00150 s16 Si114xProcessIrq(HANDLE si114x_handle, u16 timestamp)
00151 {
00152   u8 data_buffer[13];
00153   s16 error;
00154   SI114X_IRQ_SAMPLE sample;
00155   irqSequence++;
00156   Si114x_i2c_smbus_read_i2c_block_data(si114x_handle, 0x21, 13, data_buffer, false);        // Grab all data registers
00157   Si114x_i2c_smbus_write_byte_data(si114x_handle, 0x21, data_buffer[0], false);      // Clear interrupts
00158 
00159   sample.sequence = irqSequence;       // sequence number
00160   sample.timestamp = timestamp;      // 16-bit Timestamp to record
00161   sample.pad= 0;
00162   sample.irqstat = data_buffer[0];        // 8-bit irq status
00163   sample.vis = (((u16)(data_buffer[2]) << 8) & 0xff00) | data_buffer[1];            // VIS
00164   sample.ir = (((u16)(data_buffer[4]) << 8) & 0xff00) | data_buffer[3];             // IR
00165   sample.ps1 = (((u16)(data_buffer[6]) << 8) & 0xff00) | data_buffer[5];            // PS1
00166   sample.ps2 = (((u16)(data_buffer[8]) << 8) & 0xff00) | data_buffer[7];            // PS2
00167   sample.ps3 = (((u16)(data_buffer[10]) << 8) & 0xff00) | data_buffer[9];            // PS3
00168   sample.aux = (((u16)(data_buffer[12]) << 8) & 0xff00) | data_buffer[11];;            // AUX
00169 
00170   error = Si114xIrqQueue_Put(&sample);
00171   return error;
00172 }
00173 
00174 
00175 /**************************************************************************/
00178 s16 Si114xIrqQueueNumentries(HANDLE si114x_handle)
00179 {
00180   (void) si114x_handle;
00181   u16 runnerIndex = irqQueueGetIndex;
00182   s16 count=0;
00183   while (runnerIndex != irqQueuePutIndex)
00184   {
00185     runnerIndex++;
00186     count++;
00187     if(runnerIndex == IRQ_QUEUE_SIZE)
00188       runnerIndex = 0;
00189   }
00190   return (count/sizeof(SI114X_IRQ_SAMPLE));
00191 
00192 }
00193 
00194 /**************************************************************************/
00197 s16 Si114xIrqQueue_Get(HANDLE si114x_handle, SI114X_IRQ_SAMPLE *samples)
00198 {
00199   (void) si114x_handle;
00200   int16_t error = 0;
00201   uint16_t i;
00202   int8_t *data = (int8_t *)samples;
00203   DisableSi114xInterrupt ();
00204   if (irqQueueGetIndex == irqQueuePutIndex)
00205     error = -1;
00206   else
00207   {
00208     for(i=0; i<sizeof(SI114X_IRQ_SAMPLE); i++)
00209     {
00210       data[i] = IrqQueue[irqQueueGetIndex];
00211       irqQueueGetIndex++;
00212       if(irqQueueGetIndex == IRQ_QUEUE_SIZE)
00213         irqQueueGetIndex = 0;
00214 
00215     }
00216 
00217   }
00218   EnableSi114xInterrupt();
00219 #ifdef USB_DEBUG
00220   if (usbDebugEnable == 1)                                    // Dump data to USB if usb_debug is enabled
00221     USBDebug_ProcessUSBOutput(data);
00222 #endif // si114xHRM_USB_DEBUG
00223   return error;
00224 }
00225 
00226 /**************************************************************************/
00229 static s16 Si114xIrqQueue_Put(SI114X_IRQ_SAMPLE *samples)
00230 {
00231   uint16_t i;
00232   u8 *data = (u8 *)samples;
00233   for(i=0; i<sizeof(SI114X_IRQ_SAMPLE); i++)
00234   {
00235     IrqQueue[irqQueuePutIndex] = data[i];
00236     irqQueuePutIndex++;
00237     if(irqQueuePutIndex == IRQ_QUEUE_SIZE)
00238       irqQueuePutIndex = 0;
00239   }
00240   if (irqQueueGetIndex == irqQueuePutIndex)
00241   {
00242     irqQueueGetIndex += sizeof(SI114X_IRQ_SAMPLE);          // if we have wrapped around then we must delete one sample
00243     return -1; //indicate to caller something bad happened
00244   }
00245   return 0;
00246 }
00247 
00248 /**************************************************************************/
00251 s16 Si114xIrqQueue_Clear(HANDLE si114x_handle)
00252 {
00253   (void) si114x_handle;
00254   irqQueueGetIndex = 0;
00255   irqQueuePutIndex = 0;
00256   return 0;
00257 }
00258 
00259 /**************************************************************************/
00262 s16 Si114xInit(void *port, int options, HANDLE *si114x_handle)
00263 {
00264   s16 error = 0;
00265   u8 data;
00266 
00267   (void) options;
00268 
00269   *si114x_handle = (HANDLE)&_handle;
00270   _handle.i2cPort = ((Si114xPortConfig_t*)port)->i2cPort;
00271   _handle.i2cAddress = ((Si114xPortConfig_t*)port)->i2cAddress << 1;
00272   _handle.irqPort = ((Si114xPortConfig_t*)port)->irqPort;
00273   _handle.irqPin = ((Si114xPortConfig_t*)port)->irqPin;
00274 
00275   data = Si114xReadFromRegister(*si114x_handle, REG_PART_ID);
00276 
00277   if ((_handle.i2cAddress == (0x60 << 1)) && (data != 0x46) && (data != 0x47))
00278     error = -1;
00279   if ((_handle.i2cAddress == (0x5A << 1)) && (data != 0x43))
00280     error = -1;
00281 
00282   Si114xIrqQueue_Clear(*si114x_handle);
00283 
00284   return error;
00285 }
00286 
00287 /**************************************************************************/
00290 s16 Si114xClose(HANDLE si114x_handle)
00291 {
00292   (void) si114x_handle;
00293   _handle.i2cAddress = 0xff;
00294   return 0;
00295 }
00296 
00297 /**************************************************************************/
00300 s16 Si114xSysReset(HANDLE si114x_handle)
00301 {
00302   (void) si114x_handle;
00303   return 0;
00304 }
00305 
00306 /**************************************************************************/
00309 void delay_10ms(void)
00310 {
00311   RTCDRV_Delay(10);
00312   return;
00313 }
00314 
00315 /**************************************************************************/
00318 void delay_1ms(void)
00319 {
00320   RTCDRV_Delay(1);
00321   return;
00322 }
00323 
00324 
00325 /**************************************************************************/
00328 static s16 Si114x_i2c_smbus_write_byte_data(HANDLE si114x_handle, u8 address, u8 data, bool block)
00329 {
00330   I2C_TransferSeq_TypeDef    seq;
00331   I2C_TransferReturn_TypeDef ret;
00332   Si114xPortConfig_t* handle;
00333   uint8_t i2c_write_data[2];
00334   uint8_t i2c_read_data[1];
00335 
00336   if (block)
00337     DisableSi114xInterrupt();
00338   seq.addr  = _handle.i2cAddress;
00339   seq.flags = I2C_FLAG_WRITE;
00340   /* Select register and data to write */
00341   i2c_write_data[0] = address;
00342   i2c_write_data[1] = data;
00343   seq.buf[0].data = i2c_write_data;
00344   seq.buf[0].len  = 2;
00345   seq.buf[1].data = i2c_read_data;
00346   seq.buf[1].len  = 0;
00347 
00348   handle = (Si114xPortConfig_t *)si114x_handle;
00349 
00350   ret = I2CSPM_Transfer(handle->i2cPort, &seq);
00351 
00352   if (block)
00353     EnableSi114xInterrupt();
00354   if (ret != i2cTransferDone)
00355   {
00356     return (s16)ret;
00357   }
00358   return (s16)0;
00359 }
00360 
00361 /**************************************************************************/
00364 static s16 Si114x_i2c_smbus_read_byte_data(HANDLE si114x_handle, u8 address, u8 *data, bool block)
00365 {
00366   //  si114x_handle is not used in the EFM32.   We use a global instead
00367   I2C_TransferSeq_TypeDef    seq;
00368   I2C_TransferReturn_TypeDef ret;
00369   uint8_t i2c_write_data[1];
00370   Si114xPortConfig_t* i2cDrvHandle;
00371 
00372   if (block)
00373     DisableSi114xInterrupt ();
00374   seq.addr  = _handle.i2cAddress;
00375   seq.flags = I2C_FLAG_WRITE_READ;
00376   /* Select register to start reading from */
00377   i2c_write_data[0] = address;
00378   seq.buf[0].data = i2c_write_data;
00379   seq.buf[0].len  = 1;
00380   /* Select length of data to be read */
00381   seq.buf[1].data = data;
00382   seq.buf[1].len  = 1;
00383 
00384   i2cDrvHandle = (Si114xPortConfig_t *)si114x_handle;
00385 
00386   ret = I2CSPM_Transfer(i2cDrvHandle->i2cPort, &seq);
00387 
00388   if (block)
00389     EnableSi114xInterrupt();
00390   if (ret != i2cTransferDone)
00391   {
00392     *data = 0xff;
00393     return((int) ret);
00394   }
00395   return((int) 1);
00396 }
00397 
00398 /**************************************************************************/
00401 static s16 Si114x_i2c_smbus_write_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8 const* data, bool block)
00402 {
00403   I2C_TransferSeq_TypeDef    seq;
00404   I2C_TransferReturn_TypeDef ret;
00405   uint8_t i2c_write_data[10];
00406   uint8_t i2c_read_data[1];
00407   Si114xPortConfig_t* handle;
00408   int i;
00409 
00410   if (block)
00411     DisableSi114xInterrupt ();
00412   seq.addr  = _handle.i2cAddress;
00413   seq.flags = I2C_FLAG_WRITE;
00414   /* Select register to start writing to*/
00415   i2c_write_data[0] = address;
00416   for (i=0; i<length;i++)
00417   {
00418     i2c_write_data[i+1] = data[i];
00419   }
00420   seq.buf[0].data = i2c_write_data;
00421   seq.buf[0].len  = 1+length;
00422   seq.buf[1].data = i2c_read_data;
00423   seq.buf[1].len  = 0;
00424 
00425   handle = (Si114xPortConfig_t *)si114x_handle;
00426 
00427   ret = I2CSPM_Transfer(handle->i2cPort, &seq);
00428 
00429   if (block)
00430     EnableSi114xInterrupt ();
00431   if (ret != i2cTransferDone)
00432   {
00433     return((int) ret);
00434   }
00435 
00436   return((int) 0);
00437 }
00438 
00439 /**************************************************************************/
00442 static s16 Si114x_i2c_smbus_read_i2c_block_data(HANDLE si114x_handle, u8 address, u8 length, u8* data, bool block)
00443 {
00444   I2C_TransferSeq_TypeDef    seq;
00445   I2C_TransferReturn_TypeDef ret;
00446   uint8_t i2c_write_data[1];
00447   Si114xPortConfig_t* handle;
00448 
00449   seq.addr  = _handle.i2cAddress;
00450   seq.flags = I2C_FLAG_WRITE_READ;
00451   if (block)
00452     DisableSi114xInterrupt ();
00453   /* Select register to start reading from */
00454   i2c_write_data[0] = address;
00455   seq.buf[0].data = i2c_write_data;
00456   seq.buf[0].len  = 1;
00457 
00458   /* Select length of data to be read */
00459   seq.buf[1].data = data;
00460   seq.buf[1].len  = length;
00461 
00462   handle = (Si114xPortConfig_t *)si114x_handle;
00463 
00464   ret = I2CSPM_Transfer(handle->i2cPort, &seq);
00465 
00466   if (block)
00467     EnableSi114xInterrupt ();
00468   if (ret != i2cTransferDone)
00469   {
00470     return((int) ret);
00471   }
00472 
00473   return((int) 0);
00474 }
00475 
00476 int si114xFindEvb(char *port_description, char *last_port, int num_ports_found)
00477 {
00478     (void) port_description;
00479     (void) last_port;
00480     (void) num_ports_found;
00481     return 0;
00482 }
00483