34 #ifndef INCLUDE_SI114X_CALIBRATIONCODE
41 #define INCLUDE_SI114X_CALIBRATIONCODE 1
46 #ifndef INCLUDE_SI114X_COMPRESS_CODE
54 #define INCLUDE_SI114X_COMPRESS_CODE 1
58 #define LOOP_TIMEOUT_MS 200
69 while(count < LOOP_TIMEOUT_MS)
72 if(retval == 1)
break;
73 if(retval < 0)
return retval;
137 static int16_t _sendCmd(HANDLE
si114x_handle, uint8_t command)
149 while(count < LOOP_TIMEOUT_MS)
151 if((retval=_waitUntilSleep(si114x_handle)) != 0)
return retval;
153 if(command==0)
break;
156 if(retval==response)
break;
157 else if(retval<0)
return retval;
158 else response = retval;
168 while(count < LOOP_TIMEOUT_MS)
170 if(command==0)
break;
173 if(retval != response)
break;
174 else if(retval<0)
return retval;
192 return _sendCmd(si114x_handle,0x00);
207 return _sendCmd(si114x_handle,0x05);
222 return _sendCmd(si114x_handle,0x06);
237 return _sendCmd(si114x_handle,0x07);
252 return _sendCmd(si114x_handle,0x0F);
271 uint8_t cmd = 0x80 + (address & 0x1F);
273 retval=_sendCmd(si114x_handle, cmd);
274 if( retval != 0 )
return retval;
304 int16_t response_stored;
307 if((retval = _waitUntilSleep(si114x_handle))!=0)
return retval;
312 buffer[1]= 0xA0 + (address & 0x1F);
314 retval=
Si114xBlockWrite(si114x_handle, REG_PARAM_WR, 2, ( uint8_t* ) buffer);
315 if(retval != 0)
return retval;
319 while(response == response_stored )
322 if (response == response_stored)
339 static int16_t _PsAlsPause (HANDLE si114x_handle)
341 return _sendCmd(si114x_handle,0x0B);
357 uint8_t countA, countB;
367 while(retval != 0x01)
377 while(countA < LOOP_TIMEOUT_MS)
381 while(countB < LOOP_TIMEOUT_MS)
398 _PsAlsPause(si114x_handle);
402 while(countB < LOOP_TIMEOUT_MS)
423 #if( INCLUDE_SI114X_COMPRESS_CODE == 1 )
561 uint8_t exponent = 0;
569 if( input < 8 )
return 0;
582 exponent = (input & 0xF0 ) >> 4;
583 output = 0x10 | (input & 0x0F);
586 if( exponent >= 4 )
return ( output << (exponent-4) );
587 return( output >> (4-exponent) );
648 uint32_t exponent = 0;
649 uint32_t significand = 0;
661 if(input == 0x0000)
return 0x00;
662 if(input == 0x0001)
return 0x08;
687 significand = ( input << (4 - exponent) ) ;
688 return ( (exponent << 4) | (significand & 0xF));
702 significand = input >> (exponent - 5);
723 if(significand & 0x0040)
731 return ( (exponent << 4) | ( (significand >> 1) & 0xF ) );
733 #endif // INCLUDE_SI114X_COMPRESS_CODE
744 #define FLT_TO_FX20(x) ((int32_t)((x*1048576)+.5))
745 #define FX20_ONE FLT_TO_FX20( 1.000000)
746 #define FX20_BAD_VALUE 0xffffffff
749 #if(INCLUDE_SI114X_CALIBRATIONCODE == 1)
754 #define SIRPD_ADCHI_IRLED (collect(buffer, 0x23, 0x22, 0))
755 #define SIRPD_ADCLO_IRLED (collect(buffer, 0x22, 0x25, 1))
756 #define SIRPD_ADCLO_WHLED (collect(buffer, 0x24, 0x26, 0))
757 #define VISPD_ADCHI_WHLED (collect(buffer, 0x26, 0x27, 1))
758 #define VISPD_ADCLO_WHLED (collect(buffer, 0x28, 0x29, 0))
759 #define LIRPD_ADCHI_IRLED (collect(buffer, 0x29, 0x2a, 1))
760 #define LED_DRV65 (collect(buffer, 0x2b, 0x2c, 0))
764 #ifdef SI114x_CAL_DEBUG
765 #include "Si114x_cal_debug.c"
767 #define DEBUG_PRINT_OUTPUT
768 #define DEBUG_PRINT_OUTPUT_2
796 FLT_TO_FX20( 4.021290),
797 FLT_TO_FX20(57.528500),
798 FLT_TO_FX20( 2.690010),
799 FLT_TO_FX20( 0.042903),
800 FLT_TO_FX20( 0.633435),
801 FLT_TO_FX20(23.902900),
802 FLT_TO_FX20(56.889300),
803 {0x7B, 0x6B, 0x01, 0x00}
806 FLT_TO_FX20( 2.325484),
807 FLT_TO_FX20(33.541500),
808 FLT_TO_FX20( 1.693750),
809 FLT_TO_FX20( 0.026775),
810 FLT_TO_FX20( 0.398443),
811 FLT_TO_FX20(12.190900),
812 FLT_TO_FX20(56.558200),
813 {0xdb, 0x8f, 0x01, 0x00}
823 static uint32_t decode(uint32_t input)
825 int32_t exponent, exponent_bias9;
828 if(input==0)
return 0.0;
830 exponent_bias9 = (input & 0x0f00) >> 8;
831 exponent = exponent_bias9 - 9;
833 mantissa = input & 0x00ff;
837 mantissa = mantissa << (12+exponent);
850 static uint32_t collect(uint8_t* buffer,
856 uint8_t msb_ind = msb_addr - 0x22;
857 uint8_t lsb_ind = lsb_addr - 0x22;
861 value = buffer[msb_ind]<<4;
862 value += buffer[lsb_ind]>>4;
866 value = buffer[msb_ind]<<8;
867 value += buffer[lsb_ind];
871 if( ( value == 0x0fff )
872 || ( value == 0x0000 ) )
return FX20_BAD_VALUE;
873 else return decode( value );
884 static void shift_left(uint32_t* value_p, int8_t shift)
887 *value_p = *value_p<<shift ;
889 *value_p = *value_p>>(-shift) ;
895 #define ALIGN_RIGHT -1
902 static int8_t align( uint32_t* value_p, int8_t direction )
904 int8_t local_shift, shift ;
908 if( value_p == NULL )
return 0;
909 if( *value_p == 0 )
return 0;
932 if(*value_p & mask )
break;
934 shift_left( value_p, local_shift );
946 #define FORCE_ROUND_16 1
959 static void fx20_round
971 uint32_t mask1 = 0xffff8000;
972 uint32_t mask2 = 0xffff0000;
973 uint32_t lsb = 0x00008000;
977 uint32_t mask1 = ((2<<(round))-1)<<(31-(round));
978 uint32_t mask2 = ((2<<(round-1))-1)<<(31-(round-1));
979 uint32_t lsb = mask1-mask2;
982 shift = align( value_p, ALIGN_LEFT );
983 if( ( (*value_p)&mask1 ) == mask1 )
985 *value_p = 0x80000000;
994 shift_left( value_p, -shift );
1014 static uint32_t fx20_divide(
struct operand_t* operand_p )
1016 int8_t numerator_sh=0, denominator_sh=0;
1018 uint32_t* numerator_p;
1019 uint32_t* denominator_p;
1021 if( operand_p == NULL )
return FX20_BAD_VALUE;
1023 numerator_p = &operand_p->
op1;
1024 denominator_p = &operand_p->
op2;
1026 if( (*numerator_p == FX20_BAD_VALUE)
1027 || (*denominator_p == FX20_BAD_VALUE)
1028 || (*denominator_p == 0 ) )
return FX20_BAD_VALUE;
1030 fx20_round ( numerator_p );
1031 fx20_round ( denominator_p );
1032 numerator_sh = align ( numerator_p, ALIGN_LEFT );
1033 denominator_sh = align ( denominator_p, ALIGN_RIGHT );
1035 result = *numerator_p / ( (uint16_t)(*denominator_p) );
1036 shift_left( &result , 20-numerator_sh-denominator_sh );
1047 static uint32_t fx20_multiply(
struct operand_t* operand_p )
1050 int8_t val1_sh, val2_sh;
1054 if( operand_p == NULL )
return FX20_BAD_VALUE;
1056 val1_p = &(operand_p->
op1);
1057 val2_p = &(operand_p->
op2);
1059 fx20_round( val1_p );
1060 fx20_round( val2_p );
1062 val1_sh = align( val1_p, ALIGN_RIGHT );
1063 val2_sh = align( val2_p, ALIGN_RIGHT );
1066 result = (uint32_t)( ( (uint32_t)(*val1_p) ) * ( (uint32_t)(*val2_p) ) );
1067 shift_left( &result, -20+val1_sh+val2_sh );
1081 static int16_t find_cal_index( uint8_t* buffer )
1087 index = ( int16_t )( buffer[12] + ( (uint16_t)( buffer[13] ) << 8 ) );
1100 index = -(4+index) ;
1103 size =
sizeof(
calref)/
sizeof(calref[0]);
1121 static uint32_t vispd_correction(uint8_t* buffer)
1126 int16_t index = find_cal_index( buffer );
1128 if( index < 0 ) result = FX20_ONE;
1131 op.op2 = VISPD_ADCLO_WHLED;
1132 result = fx20_divide( &op );
1134 if( result == FX20_BAD_VALUE ) result = FX20_ONE;
1145 static uint32_t irpd_correction(uint8_t* buffer)
1149 int16_t index = find_cal_index( buffer );
1151 if( index < 0 ) result = FX20_ONE;
1155 op.op2 = SIRPD_ADCLO_IRLED;
1156 result = fx20_divide( &op );
1158 if( result == FX20_BAD_VALUE ) result = FX20_ONE;
1171 static uint32_t adcrange_ratio(uint8_t* buffer)
1176 op.
op1 = SIRPD_ADCLO_IRLED ; op.op2 = SIRPD_ADCHI_IRLED ;
1177 result = fx20_divide( &op );
1179 if( result == FX20_BAD_VALUE ) result = FLT_TO_FX20( 14.5 );
1191 static uint32_t irsize_ratio(uint8_t* buffer)
1196 op.
op1 = LIRPD_ADCHI_IRLED ; op.op2 = SIRPD_ADCHI_IRLED ;
1198 result = fx20_divide( &op );
1200 if( result == FX20_BAD_VALUE ) result = FLT_TO_FX20( 6.0 );
1212 static uint32_t ledi_ratio(uint8_t* buffer)
1219 index = find_cal_index( buffer );
1221 if( index < 0 ) result = FX20_ONE;
1226 result = fx20_divide( &op );
1228 if( result == FX20_BAD_VALUE ) result = FX20_ONE;
1241 static int16_t si114x_get_cal_index( HANDLE si114x_handle, uint8_t* buffer )
1246 if( ( si114x_handle == NULL ) || ( buffer == NULL ) )
1253 if( retval != 0 )
return -1;
1261 }
while( response != 0 );
1265 _waitUntilSleep(si114x_handle);
1267 if( retval != 0 )
return -1;
1269 retval =
Si114xBlockRead( si114x_handle, REG_PS1_DATA0, 2, &(buffer[12]) );
1270 if( retval != 0 )
return -1;
1338 if( si114x_handle == NULL ) { retval = -4;
goto error_exit; }
1340 if( si114x_cal == NULL ) { retval = -4;
goto error_exit; }
1349 retval =
Si114xBlockRead( si114x_handle, REG_ALS_VIS_DATA0, 12, buffer );
1350 if( retval != 0 ) { retval = -2;
goto error_exit; }
1352 for( i=0; i<12; i++)
1354 if( buffer[i] != 0 ) { retval = -1;
goto error_exit; }
1365 if( retval != 0 ) { retval = -2;
goto error_exit; }
1373 }
while( response != 0 );
1377 _waitUntilSleep(si114x_handle);
1379 if( retval != 0 ) { retval = -2;
goto error_exit; }
1386 if( response == 0x80 )
1396 else if( response & 0xfff0 )
1406 }
while( response != 1 );
1409 retval =
Si114xBlockRead( si114x_handle, REG_ALS_VIS_DATA0, 12, buffer );
1410 if( retval != 0 ) { retval = -2;
goto error_exit; }
1414 retval=si114x_get_cal_index( si114x_handle, buffer );
1418 retval = -2;
goto error_exit;
1425 si114x_cal->
ucoef_p = calref[find_cal_index(buffer)].
ucoef;
1428 DEBUG_PRINT_OUTPUT_2;
1471 uint8_t* input_ucoef,
1476 uint32_t vc=FX20_ONE, ic=FX20_ONE, long_temp;
1478 uint8_t* ref_ucoef = si114x_cal->
ucoef_p;
1479 uint8_t out_ucoef[4];
1481 if( input_ucoef != NULL ) ref_ucoef = input_ucoef;
1483 if( ref_ucoef == NULL )
return -1 ;
1489 case 0x32:
case 0x45:
case 0x46:
case 0x47: temp = 1;
break;
1490 default: temp = 0;
break;
1492 if( !temp )
return -1;
1500 op.
op1 = ref_ucoef[0] + ((ref_ucoef[1])<<8);
1502 long_temp = fx20_multiply( &op );
1503 out_ucoef[0] = (long_temp & 0x00ff);
1504 out_ucoef[1] = (long_temp & 0xff00)>>8;
1506 op.
op1 = ref_ucoef[2] + (ref_ucoef[3]<<8);
1508 long_temp = fx20_multiply( &op );
1509 out_ucoef[2] = (long_temp & 0x00ff);
1510 out_ucoef[3] = (long_temp & 0xff00)>>8;
1518 #else // INCLUDE_SI114X_CALIBRATION_CODE
1532 uint8_t* input_ucoef,
1536 uint8_t code ucoef[4] = { 0x7B, 0x6B, 0x01, 0x00 } ;
1542 #endif // INCLUDE_SI114X_CALIBRATION_CODE
SI114X_CAL_S Data Structure.
void delay_10ms()
Implements 10ms delay.
#define FORCE_ROUND_16
This compile switch used only to experiment with various rounding precisions. The flexibility has a s...
int16_t Si114xPsForce(HANDLE si114x_handle)
Sends a PSFORCE command to the Si113x/4x.
int16_t Si114xNop(HANDLE si114x_handle)
Sends a NOP command to the Si113x/4x.
uint32_t lirpd_adchi_irled
Si114x function prototypes, structure and bit definitions.
uint16_t Uncompress(uint8_t input)
Converts an 8-bit compressed value to 16-bit.
uint32_t vispd_correction
int16_t Si114xParamSet(HANDLE si114x_handle, uint8_t address, uint8_t value)
Writes a byte to an Si113x/4x Parameter.
uint8_t Compress(uint16_t input)
Converts a 16-bit value to 8-bit value.
int16_t Si114xBlockWrite(HANDLE si114x_handle, uint8_t address, uint8_t length, uint8_t *values)
Writes block of Si114x registers.
Structure Definition for calref array.
int16_t Si114xWriteToRegister(HANDLE si114x_handle, uint8_t address, uint8_t data)
Writes to Si114x Register.
int16_t si114x_set_ucoef(HANDLE si114x_handle, uint8_t *input_ucoef, SI114X_CAL_S *si114x_cal)
Initializes the Si113x/46/47/48 UCOEF Registers.
int16_t Si114xAlsForce(HANDLE si114x_handle)
Sends an ALSFORCE command to the Si113x/4x.
int16_t Si114xParamRead(HANDLE si114x_handle, uint8_t address)
Reads a Parameter from the Si113x/4x.
void delay_1ms()
Implements 1ms delay.
struct cal_ref_t calref[2]
Factory Calibration Reference Values.
int16_t Si114xPsAlsForce(HANDLE si114x_handle)
Sends a PSALSFORCE command to the Si113x/4x.
uint32_t vispd_adclo_whled
int16_t Si114xReadFromRegister(HANDLE si114x_handle, uint8_t address)
Reads from Si114x register.
uint32_t sirpd_adchi_irled
int16_t Si114xBlockRead(HANDLE si114x_handle, uint8_t address, uint8_t length, uint8_t *values)
Reads block of Si114x registers.
int16_t si114x_get_calibration(HANDLE si114x_handle, SI114X_CAL_S *si114x_cal, uint8_t security)
Populates the SI114X_CAL_S structure.
The fx20_divide and fx20_multiply uses this structure to pass values into it.
static void * si114x_handle
Si114x PGM toolkit functions uses a void* to pass hardware parameters through to the lower level i2c ...
int16_t Si114xPsAlsAuto(HANDLE si114x_handle)
Sends a PSALSAUTO command to the Si113x/4x.
uint32_t sirpd_adclo_irled
int16_t Si114xPauseAll(HANDLE si114x_handle)
Pauses autonomous measurements.
uint32_t sirpd_adclo_whled
int16_t Si114xReset(HANDLE si114x_handle)
Resets the Si113x/4x, clears any interrupts and initializes the HW_KEY register.
uint32_t vispd_adchi_whled