Library to communicate with LDC1614

Dependencies:   SHTx

Dependents:   Inductive_Sensor_3

Fork of LDC1101 by Bob Giesberts

Revision:
29:41815fd13822
Parent:
28:76a2fc42f888
Child:
30:95c53d244f91
--- a/LDC1614.cpp	Tue Aug 23 08:25:40 2016 +0000
+++ b/LDC1614.cpp	Wed Aug 24 07:42:49 2016 +0000
@@ -21,9 +21,9 @@
 */
 
 #include "LDC1614.h"
-
+#include "mbed_debug.h"
 
-LDC1614::LDC1614(PinName sda, PinName scl, PinName sd, float f_CLKIN, int channels, float capacitor) : _i2c(sda, scl), _shutdown_pin(sd)
+LDC1614::LDC1614(PinName sda, PinName scl, PinName sd, PinName os, float f_CLKIN, int channels, float capacitor) : _i2c(sda, scl), _shutdown_pin(sd), _oscillator(os)
 {
     // settings
     _channels = channels;   // number of sensors
@@ -35,12 +35,10 @@
     _SettleCount = 50;      // CHx_SETTLECOUNT = t_settle * f_REFx/16 = 50 (p.12)
     _DriveCurrent = 31;     // max???
        
+    // start communication
     _i2c.frequency(400000); // 400 kHz (p.6)
     
-    // Turn the LDC1614 on (exit shutdown)
-    _shutdown_pin.write(0);
-    wait_us(100);
-    
+    // Initilialize the LDC1614
     init();
 }
 
@@ -68,6 +66,9 @@
     ** CHx_FREF_DIVIDER =     1       (16.0 MHz)    
     ************************************/
     
+    // Configuring setup, set LDC in configuration modus
+    sleep();
+    
     for(int i = 0; i < _channels; i++)
     {
         // set Reference Count to highest resolution
@@ -91,7 +92,7 @@
     
     // mux_config    
     set( MUX_CONFIG, AUTOSCAN_EN,    _channels > 1 );
-    set( MUX_CONFIG, RR_SEQUENCE,    max(0, _channels - 2) );
+    set( MUX_CONFIG, RR_SEQUENCE,    ( ( _channels - 2 > 0 ) ? _channels - 2 : 0 ) );
     set( MUX_CONFIG, DEGLITCH,       DEGLITCH_10M );
     
     // override Rp and use own Drive Current to reduce power consumption
@@ -113,17 +114,26 @@
     {
         case LDC_MODE_ACTIVE:
         case LDC_MODE_SLEEP:
+        
+            // turn on oscillator
+            _oscillator.write( 1 );
+            wait_ms(3); // datasheet oscillator says 3 ms max
+            
+            // turn on LDC
             _shutdown_pin.write( 0 );
-            set( CONFIG, SLEEP_MODE_EN, LDC_MODE_ACTIVE );
+            set( CONFIG, SLEEP_MODE_EN, mode );
+            wait_us(400); // Wait 16384 f_INT clock cycles (0.377 ms) (p.16)
             break;
         
         case LDC_MODE_SHUTDOWN:
             _shutdown_pin.write( 1 );
+            _oscillator.write( 0 );
             break;
     }
 }
-void LDC1614::sleep( void )  { func_mode( LDC_MODE_SLEEP );  }
-void LDC1614::wakeup( void ) { func_mode( LDC_MODE_ACTIVE ); }
+void LDC1614::sleep( void )    { func_mode( LDC_MODE_SLEEP );    }
+void LDC1614::wakeup( void )   { func_mode( LDC_MODE_ACTIVE );   }
+void LDC1614::shutdown( void ) { func_mode( LDC_MODE_SHUTDOWN ); }
 
 void LDC1614::setReferenceCount( uint8_t channel, uint16_t rcount )
 {
@@ -145,14 +155,15 @@
 void LDC1614::setDivider( uint8_t channel, uint8_t divIN, uint8_t divREF )
 {
     // make sure the values fit
-    _dividerIN  = min(max(divIN,  1), 15);  // 4 bit
-    _dividerREF = min(max(divREF, 1), 255); // 8 bit    
+    _dividerIN  = (( divIN <  15) ? (( divIN > 1) ? divIN  : 1) :  15 ); // 4 bit
+    _dividerIN  = ((divREF < 255) ? ((divREF > 1) ? divREF : 1) : 255 ); // 8 bit
     writeI2Cregister( CLOCK_DIVIDERS_CH0 + channel, uint16_t ((_dividerIN << 12) + _dividerREF) );
 } 
 
 void LDC1614::setDriveCurrent( uint8_t channel, uint8_t idrive )
 {   
-    _DriveCurrent = min( idrive, 31 ); // 5-bit (b1 1111)
+    _DriveCurrent = ((idrive < 31) ? idrive : 31 ); // 5-bit (b1 1111)
+    
     // todo: read initial idrive [10:6]
 
     writeI2Cregister(DRIVE_CURRENT_CH0 + channel, uint16_t (_DriveCurrent<<10) );
@@ -172,6 +183,22 @@
     regchange( addr, setting, value, mask );
 }
 
+uint8_t LDC1614::get( ADDR addr, SETTING setting, uint8_t mask )
+{
+    if ( addr == MUX_CONFIG )
+    {
+        switch (setting){
+            case AUTOSCAN_EN: mask = 1; break;  // 1
+            case RR_SEQUENCE: mask = 3; break;  // 11
+            case DEGLITCH:    mask = 7; break;  // 111
+        }    
+    }
+    
+    uint16_t data[1]; 
+    readI2C( data, addr ); 
+    return ( data[0]>>setting ) & mask;    
+}
+
 
 
 
@@ -185,7 +212,16 @@
     readI2C( status, STATUS );  
     return status[0];
 }
-bool LDC1614::is_ready( void )            { return ( get_status() & 0x0080 ); }
+bool LDC1614::is_ready( uint8_t status )
+{
+    if( status == 17 ) { status = get_status(); }
+    return ( status>>DRDY ) & 1;
+}
+bool LDC1614::is_error( uint8_t status )
+{
+    if( status == 17 ) { status = get_status(); }
+    return ((( status>>ERR_ZC) & 6) == 0);
+}
 
 
 uint16_t LDC1614::get_Rcount( uint8_t channel )
@@ -199,11 +235,18 @@
 {
     uint16_t data[2];
     readI2C(data, DATA_MSB_CH0 + channel, 2);
+    
+    if( ((data[0]>>CHx_ERR_UR) & 1) == 1 ) { debug( "Under-range Error" ); }
+    if( ((data[0]>>CHx_ERR_OR) & 1) == 1 ) { debug( "Over-range Error" ); }
+    if( ((data[0]>>CHx_ERR_WD) & 1) == 1 ) { debug( "Watchdog Timeout Error" ); }
+    if( ((data[0]>>CHx_ERR_AE) & 1) == 1 ) { debug( "Amplitude Error" ); }
+    
     return ( (data[0] & 0x0fff)<<16) | data[1]; // MSB + LSB
 }
 
 
 
+/* REGISTER FUNCTIONS (READ / WRITE)  */
 
 
 void LDC1614::readI2C( uint16_t *data, uint8_t address, uint8_t length )
@@ -247,7 +290,6 @@
 float LDC1614::get_fsensor( uint32_t LData )
 {    
     _fsensor = _dividerIN * (_fCLKIN/_dividerREF) * ((LData / 268435456) + (_Offset / 65536)); // (p.14)
-       
     return _fsensor;
 }