Working version. ADXL355 data saved to microSD.

adxl355.cpp

Committer:
DUR
Date:
2017-09-29
Revision:
0:e2579e8d9b13

File content as of revision 0:e2579e8d9b13:

/**
  ******************************************************************************
  * @file    adxl355.cpp         
  * @author  DUR
  * @version V1.0.0  
  * @date    01-Aug-2017
  * @brief   Library for adxl355 interface.
  *
  * @par Manual Reference Names:
  *  1. "Low Noise, Low Drift, Low Power, 3-Axis MEMS Accelerometers
  *      ADXL354/ADXL355"
  *      9/2016—Revision 0: Initial Version  
  *
  * @par Document History:
  * 
  * Version: 1.0.0 (01/08/2017)
  * ----------------------------------------------------------------------------
  * Author: DUR
  * First release.
  * ----------------------------------------------------------------------------
  *
@verbatim
================================================================================
                 ##### How to use this file #####
================================================================================
Questa libreria è stata redatta per poter gestire ad alto livello il sensore di  
accelerazione ad uscita digitale a 20 bit della Analog Devices ADXL355, dotato
di un bus SPI/I2C per la comunicazione, insieme ad un pin per la segnalazione di 
nuovi dati pronti e ben 2 pin di interrupt che sono configurabili per scattare a 
seguito di ben precisi eventi interni.
Perché si possa utilizzare questa libreria su di una qualunque piattaforma 
hardware, la seguente funzione dovrà poi essere associata a quella di basso 
livello:
    (+) uint16_t adxl355_spi_transfer(uint8_t * rbuffer, uint32_t rlen)
        < trasferimento su bus SPI >;
Nella presente versione della libreria, sono state fatte le seguenti scelte 
progettuali:
    (+) è stato scelto di utilizzare il bus SPI piuttosto che il bus I2C per la 
        comunicazione da e verso l'host;
    (+) è stato scelto l'utilizzo della sincronizzazione interna (EXT_SYNC = 0x00).
L'accelerometro viene configurato dall'utente, per mezzo di una struttura dati 
adxl355_handler, con la quale è possibile definire un setting di parametri 
applicativi in base alle differenti esigenze. Nel suo utilizzo è importante tenere
a mente le seguenti osservzioni:
    (i) dopo avere lanciato il comando di reset software (adxl355_sw_reset) il 
        sensore deve essere nuovamente inizializzato (adxl355_init);
    (i) per effettuare il self test, il sensore deve già essere in modalità di 
        acquisizione; il camando adxl355_self_test(true) dovrà essere lanciato 
        più volte perché ad ogni invocazione del metodo viene appicata una 
        specifica accelerazione all'interno, e quella che si andrà a rilevare
        sarà proprio la differenza tra i valori in g rilevati tra due invocazioni
        successive, e che dovrà rispettare i valori imposti dal datasheet.
@endverbatim

  ******************************************************************************
@attention
<h2><center>&copy; COPYRIGHT(c) 2014 TD Group</center></h2>

The information contained herein is property of TD Group S.p.A.

Licensees are granted free, non-transferable use of the information. NO
WARRANTY of ANY KIND is provided. This heading must NOT be removed from
the file.
  ******************************************************************************
  */

#define ADXL355_VERSION  1
#define ADXL355_REVISION 0
#define ADXL355_PATCH    0  
    
    
/* Includes ------------------------------------------------------------------*/

/** @brief   Add ONLY the header of THIS source file and not others.
 */

#include "adxl355.h"

/** @addtogroup FILE_FUNCTIONS
  * @{
  */



/* Private function prototypes -----------------------------------------------*/
/* Ricava da una maschera di bit, la posizione del primo bit della maschera stessa */
static uint8_t  adxl355_get_bit_position(uint8_t gbp_mask);
/* Setting dei parametri */
static uint16_t adxl355_set_parameter(uint8_t sp_reg, uint8_t sp_mask_data, uint8_t sp_data);
/* Lettura valore accelerazione lungo asse X, Y e Z */
static uint16_t adxl355_read_acc_value(adxl355_handler *adxl_acc);
/* Lettura valore di temperatura */
static uint16_t adxl355_read_temp_value(adxl355_handler *adxl_temp);


/* Private variables ---------------------------------------------------------*/
/* Definisce in ogni momento quali misure sono attive */
static adxl355_measure_enabled adxl_measure_on;


/* Exported variables --------------------------------------------------------*/


/* Private functions ---------------------------------------------------------*/

/** @defgroup Group1 Private_Functions      
 *  @brief    Function used only in this file and NOT visible to the rest of the 
 *            code. 
 *  @{
 */


/**
  *  @brief   Ricava da una maschera di bit, la posizione del primo bit della maschera 
  *           stessa.
  *  @note    No one.
  *  @param   gbp_mask           maschera di bit
  *  @retval  uint8_t            posizione del primo bit nella maschera
  *  @todo    Nothing.
  *  @warning No one.
  */  
static uint8_t adxl355_get_bit_position(uint8_t gbp_mask)
{
    uint8_t gbp_index;
    
    for(gbp_index = 0; gbp_index < 8; gbp_index++)
    {
        if(((gbp_mask>>gbp_index) & 0x01) != 0)
        {
            break;
        }else{}
    }
    
    return gbp_index;
}


/**
  *  @brief   Funzione per la scrittura di un parametro su di un registro dell'accelerometro.
  *  @note    No one.
  *  @param   sp_reg             indirizzo del registro da settare
  *  @param   sp_mask_data       posizione del/i bit da settare sotto forma di maschera
  *  @param   sp_data            valore del/i bit da settare
  *  @retval  uint16_t           errore restituito dal metodo (se 0, tutto ok)
  *  @todo    Nothing.
  *  @warning No one.
  */ 
static uint16_t adxl355_set_parameter(uint8_t sp_reg, uint8_t sp_mask_data, uint8_t sp_data)
{
    uint16_t adxl_sp_error = 0u;
    uint8_t  adxl_sp_data[2];       
    
    /* Lettura del registro */  
    adxl_sp_data[0] = (uint8_t)((sp_reg << 1) | ADXL355_READ_BYTE_MASK);
    adxl_sp_data[1] = 0x00;
    if(adxl355_spi_transfer((uint8_t*)&adxl_sp_data, 2) == 0)
    {
        adxl_sp_data[0]  = (uint8_t)((sp_reg << 1) & ADXL355_WRITE_BYTE_MASK);      
        adxl_sp_data[1] &= (uint8_t)~sp_mask_data;
        adxl_sp_data[1] |= (uint8_t)(sp_data << (adxl355_get_bit_position(sp_mask_data)));
        /* Scrittura del nuovo valore */
        if(adxl355_spi_transfer((uint8_t*)&adxl_sp_data, 2) == 0)
        {}
        else
        {
            adxl_sp_error = (uint16_t)__LINE__;//ERRORE SCRITTURA REGISTRO
        }   
    }
    else
    {
        adxl_sp_error = (uint16_t)__LINE__;//ERRORE LETTURA REGISTRO
    }
    
    return adxl_sp_error;
}


/**
  *  @brief   Funzione di lettura del dato grezzo di accelerazione lungo gli assi 
  *           X, Y e Z dell'accelerometro.
  *  @note    No one.
  *  @param   adxl_acc      puntatore all'handler dell'accelerometro 
  *  @retval  uint16_t      errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */ 
static uint16_t adxl355_read_acc_value(adxl355_handler *adxl_acc)
{
    uint16_t adxl_read_acc_error = 0u;
    uint8_t  adxl_read_acc_data[10];
    /* Azzeramento buffer dati SPI */
    memset(adxl_read_acc_data, 0x00, 10);
    adxl_read_acc_data[0u] = (uint8_t)((ADXL355_XDATA3<<1) | ADXL355_READ_BYTE_MASK);
    
    if(adxl355_spi_transfer((uint8_t*)&adxl_read_acc_data, 10) == 0)
    {
        adxl_acc->raw_acc_x_value = 0u;
        adxl_acc->raw_acc_x_value = (adxl_read_acc_data[1]<<16u) | (adxl_read_acc_data[2]<<8u) | (adxl_read_acc_data[3]);
        adxl_acc->raw_acc_x_value = (adxl_acc->raw_acc_x_value>>4u) & ADXL355_20_BIT_MASK;
        
        adxl_acc->raw_acc_y_value = 0u;
        adxl_acc->raw_acc_y_value = (adxl_read_acc_data[4]<<16u) | (adxl_read_acc_data[5]<<8u) | (adxl_read_acc_data[6]);
        adxl_acc->raw_acc_y_value = (adxl_acc->raw_acc_y_value>>4u) & ADXL355_20_BIT_MASK;      
        
        adxl_acc->raw_acc_z_value = 0u;
        adxl_acc->raw_acc_z_value = (adxl_read_acc_data[7]<<16u) | (adxl_read_acc_data[8]<<8u) | (adxl_read_acc_data[9]);
        adxl_acc->raw_acc_z_value = (adxl_acc->raw_acc_z_value>>4u) & ADXL355_20_BIT_MASK;      
    }
    else
    {
        adxl_read_acc_error = (uint16_t)__LINE__;//ERRORE LETTURA DATI ACCELERAZIONE
    }
        
    return adxl_read_acc_error;
}



/**
  *  @brief   Funzione di lettura del dato grezzo di temperatura fornito dall'accelerometro.
  *  @note    No one.
  *  @param   adxl_temp      puntatore all'handler dell'accelerometro 
  *  @retval  uint16_t      errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */ 
static uint16_t adxl355_read_temp_value(adxl355_handler *adxl_temp)
{
    uint16_t adxl_read_temp_error = 0u;
    uint8_t  adxl_read_temp_data[3];
    /* Azzeramento buffer dati SPI */
    memset(adxl_read_temp_data, 0x00, 3);
    adxl_read_temp_data[0u] = (uint8_t)((ADXL355_TEMP2<<1) | ADXL355_READ_BYTE_MASK);
    
    if(adxl355_spi_transfer((uint8_t*)&adxl_read_temp_data, 3) == 0)
    {
        adxl_temp->raw_temp_value = 0u;
        adxl_temp->raw_temp_value = (adxl_read_temp_data[1]<<8u) | adxl_read_temp_data[2];
        adxl_temp->raw_temp_value &=  ADXL355_12_BIT_MASK;      
    }
    else
    {
        adxl_read_temp_error = (uint16_t)__LINE__;//ERRORE LETTURA DATI ACCELERAZIONE
    }
        
    return adxl_read_temp_error;    
}
    
    




/**
  * @}
  */

  
/* Exported functions --------------------------------------------------------*/

/** @defgroup Group2 Exported_Functions      
 *  @brief    Functions used in this file and also visible to the rest of the 
 *            code.
 *  @{
 */  
  

  
/**
*  @brief   Funzione che restituisce i parametri identificativi del driver.
*  @note    No one.
*  @param   adxl355_driver_version    puntatore all'identificatore di versione del driver 
*  @param   adxl355_driver_revision   puntatore all'identificatore di revisione del driver 
*  @param   adxl355_driver_patch      puntatore all'identificatore di patch del driver 
*  @retval  No one.
*  @todo    No one.
*  @warning No one.
*/ 
void adxl355_driver_info(uint8_t * adxl355_driver_version, uint8_t * adxl355_driver_revision, uint8_t * adxl355_driver_patch)
{
    *adxl355_driver_version  = ADXL355_VERSION;
    *adxl355_driver_revision = ADXL355_REVISION;
    *adxl355_driver_patch    = ADXL355_PATCH;   
}

 
/**
*  @brief   Funzione che restituisce l'ID dell'accelerometro.
*  @note    No one.
*  @param   adxl355_device_id    puntatore all'identificatore del device 
*  @retval  uint16_t             errore restituito dal metodo (se 0, tutto ok)
*  @todo    No one.
*  @warning No one.
*/ 
uint16_t adxl355_who_am_i(uint8_t * adxl355_device_id)
{
    uint16_t adxl_whoami_error = 0u;
    uint8_t  adxl_whoami_data[2];       
    
    /* Lettura del registro */  
    adxl_whoami_data[0] = (uint8_t)((ADXL355_PARTID << 1) | ADXL355_READ_BYTE_MASK);
    adxl_whoami_data[1] = 0x00;
    if(adxl355_spi_transfer((uint8_t*)&adxl_whoami_data, 2) == 0)   
    {
        *adxl355_device_id = adxl_whoami_data[1];
    }
    else
    {
        adxl_whoami_error = (uint16_t)__LINE__;//ERRORE LETTURA ID
    }
    
    return adxl_whoami_error;
}   
  
  
/**
  *  @brief   Funzione di inizializzazione dell'accelerometro.
  *  @note    No one.
  *  @param   adxl_init_handler      puntatore all'handler dell'accelerometro 
  *  @retval  uint16_t               errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */ 
uint16_t adxl355_init(adxl355_handler *adxl_init_handler)
{
    uint16_t adxl_init_error = 0u;
    uint8_t  adxl_init_state = 0u;  
    
    switch(adxl_init_state)
    {       
        case 0:/* Configurazione range di misura */
            if(0u == adxl355_set_parameter(ADXL355_RANGE, ADXL355_RANGE_MASK, (uint8_t)adxl_init_handler->measure_range))
            {}
            else
            {
                adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING RANGE DI MISURA
                break;
            }           
                
                
        case 1:/* Configurazione output data rate */
            if(0u == adxl355_set_parameter(ADXL355_FILTER, ADXL355_ODR_MASK, (uint8_t)adxl_init_handler->out_data_rate))
            {}
            else
            {
                adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING OUTPUT DATA RATE
                break;
            }               
                
                
        case 2:/* Configurazione polarità interrupt */
            if((adxl_init_handler->int1_pin == NULL) && 
               (adxl_init_handler->int2_pin == NULL)){}//Se i pin non sono configurati, è inutile configurare la polarità degli interrupt
            else
            {
                if(0u == adxl355_set_parameter(ADXL355_RANGE, ADXL355_ODR_MASK, (adxl_init_handler->int_config.int_act_low==true) ? 0:1))
                {}
                else
                {
                    adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING POLARITA' INTERRUPT
                    break;
                }
            }           
                
        
        case 3:/* Configurazione interrupt 1 */
            if(adxl_init_handler->int1_pin == NULL){}//Se il pin non è configurato, è inutile configurare il relativo interrupt
            else        
            {
                if(0u == adxl355_set_parameter(ADXL355_INT_MAP, ADXL355_INT_1_MASK, (uint8_t)adxl_init_handler->int_config.int1_evt))
                {}
                else
                {
                    adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING EVENTO ASSOCIATO AD INTERRUPT 1
                    break;
                }                                   
            }
            
    
        case 4:/* Configurazione interrupt 2 */
            if(adxl_init_handler->int2_pin == NULL){}//Se il pin non è configurato, è inutile configurare il relativo interrupt
            else        
            {
                if(0u == adxl355_set_parameter(ADXL355_INT_MAP, ADXL355_INT_2_MASK, (uint8_t)adxl_init_handler->int_config.int2_evt))
                {}
                else
                {
                    adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING EVENTO ASSOCIATO AD INTERRUPT 2
                    break;
                }                                   
            }               
            
        
        case 5:/* Stop di tutte le possibili misure */
            if(0u == adxl355_start_acquisition(adxl355_none))
            {}
            else
            {
                adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING STOP MISURE
                break;
            }   
            

        case 6:/* Self-test disabilitato */
            if(0u == adxl355_self_test(false))
            {}
            else
            {
                adxl_init_error = (uint16_t)__LINE__;//ERRORE DISABILITAZIONE SELF-TEST
                break;
            }           
        
            
        default:        
            break;      
    }
                                
    return adxl_init_error; 
}



/**
  *  @brief   Funzione di start/stop delle acquisizioni.
  *  @note    No one.
  *  @param   adxl_start      misura/e da avviare 
  *  @retval  uint16_t        errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */
uint16_t adxl355_start_acquisition(adxl355_measure_enabled adxl_start)
{
    uint16_t adxl_start_error = 0u; 
    uint8_t  adxl_start_data;   
        
    switch(adxl_start)
    {
        case 0://Solo accelerazione
            adxl_start_data = 0x02;
            break;  

        case 1://Entrambe le misure (accelerazione e temperatura)
            adxl_start_data = 0x00;
            break;  

        case 2://Nessuna misura (mette in standby il sensore)
            adxl_start_data = 0x03;
            break;          
        
        default:
            break;      
    }
    
    if(0u == adxl355_set_parameter(ADXL355_POWER_CTL, ADXL355_MEAS_MASK, adxl_start_data))
    {
        adxl_measure_on = adxl_start;       
    }
    else
    {
        adxl_start_error = (uint16_t)__LINE__;//ERRORE SETTING RANGE DI MISURA      
    }   
        
    return adxl_start_error;
}



/**
  *  @brief   Funzione per la lettura del/i dato/i acquisito/i.
  *  @note    No one.
  *  @param   adxl_data_handler      puntatore all'handler dell'accelerometro 
  *  @retval  uint16_t               errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */
uint16_t adxl355_get_data(adxl355_handler *adxl_data_handler)  
{
    uint16_t adxl_data_error = 0u;      
    
    if((adxl_measure_on == adxl355_acc) || (adxl_measure_on == adxl355_both))
    {   /* Lettura accelerazione */
        if(adxl355_read_acc_value(adxl_data_handler) == 0u)
        {
            if(adxl_measure_on == adxl355_both)
            {   /* Lettura temperatura */
                if(adxl355_read_temp_value(adxl_data_handler) == 0u)
                {}
                else 
                {
                    adxl_data_error = (uint16_t)__LINE__;//ERRORE LETTURA MISURA TEMPERATURA 
                }               
            }
            else{}
            
        }
        else
        {
            adxl_data_error = (uint16_t)__LINE__;//ERRORE LETTURA MISURA ACCELERAZIONE 
        }
    }else{}

    return adxl_data_error;
}



/**
  *  @brief   Funzione che restituisce il valore grezzo di accelerazione lungo l'asse X.
  *  @note    No one.
  *  @param   adxl_xdata_handler     puntatore all'handler dell'accelerometro 
  *  @retval  uint32_t               valore grezzo accelerazione
  *  @todo    No one.
  *  @warning No one.
  */
uint32_t adxl355_raw_x_acc(adxl355_handler *adxl_xdata_handler)
{
    return adxl_xdata_handler->raw_acc_x_value;
}



/**
  *  @brief   Funzione che restituisce il valore grezzo di accelerazione lungo l'asse Y.
  *  @note    No one.
  *  @param   adxl_ydata_handler     puntatore all'handler dell'accelerometro 
  *  @retval  uint32_t               valore grezzo accelerazione
  *  @todo    No one.
  *  @warning No one.
  */
uint32_t adxl355_raw_y_acc(adxl355_handler *adxl_ydata_handler)
{
    return adxl_ydata_handler->raw_acc_y_value;
}



/**
  *  @brief   Funzione che restituisce il valore grezzo di accelerazione lungo l'asse Z.
  *  @note    No one.
  *  @param   adxl_zdata_handler     puntatore all'handler dell'accelerometro 
  *  @retval  uint32_t               valore grezzo accelerazione
  *  @todo    No one.
  *  @warning No one.
  */
uint32_t adxl355_raw_z_acc(adxl355_handler *adxl_zdata_handler)
{
    return adxl_zdata_handler->raw_acc_z_value;
}



/**
  *  @brief   Funzione che restituisce il valore grezzo di temperatura.
  *  @note    No one.
  *  @param   adxl_tdata_handler     puntatore all'handler dell'accelerometro 
  *  @retval  uint16_t               valore grezzo temperatura
  *  @todo    No one.
  *  @warning No one.
  */
uint16_t adxl355_raw_temp(adxl355_handler *adxl_tdata_handler)
{
    return adxl_tdata_handler->raw_temp_value;
}



/**
  *  @brief   Funzione per il reset sw.
  *  @note    No one.
  *  @param   No one.
  *  @retval  uint16_t               errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */
uint16_t adxl355_sw_reset(void)
{
    uint16_t adxl_swres_error = 0u;
    uint8_t  adxl_swres_data[2];        
    
    /* Lettura del registro */  
    adxl_swres_data[0] = (uint8_t)((ADXL355_RESET << 1) & ADXL355_WRITE_BYTE_MASK);
    adxl_swres_data[1] = ADXL355_RESET_CODE;
    if(adxl355_spi_transfer((uint8_t*)&adxl_swres_data, 2) == 0)    
    {}
    else
    {
        adxl_swres_error = (uint16_t)__LINE__;//ERRORE RESET ACCELEROMETRO
    }
    
    return adxl_swres_error;
}



/**
  *  @brief   Funzione per il self-test.
  *  @note    Questo metodo va utilizzato lanciandolo ponendo a true adxl_start
  *           ad acquisizione in corso; in questa modalità il metodo va lanciato 
  *           diverse volte in modo che si possa registrare la variazione di 
  *           accelerazione sui 3 assi che deve essere, secondo datasheet:
  *           [X]: 0.3g
  *           [Y]: 0.3g
  *           [Z]: 1.5g
  *           In modalità self-test, il sensore non registra alcuna accelerazione 
  *           esterna; ponendo a false adxl_start, il sensore termina il self-test 
  *           e ritorna in modalità normale di funzionamento.
  *  @param   adxl_start          booleano per avviare/fermare il self test
  *  @retval  uint16_t            errore restituito dal metodo (se 0, tutto ok)
  *  @todo    No one.
  *  @warning No one.
  */
uint16_t adxl355_self_test(bool adxl_start)
{
    uint16_t adxl_st_error = 0u;
    static uint8_t adxl_st2_val = 0u;
    
    if(adxl_start == true)
    {           
        adxl_measure_on = adxl355_acc;
        if(0u == adxl355_set_parameter(ADXL355_SELF_TEST, ADXL355_SELF_TEST_MASK, (adxl_st2_val<<1)|ADXL355_SELF_TEST_ENABLE ))
        {
            if(adxl_st2_val == 0u) adxl_st2_val = 1u;
            else adxl_st2_val = 0u;
        }
        else    
        {
            adxl_st_error = (uint16_t)__LINE__;//ERRORE AVVIO SELF-TEST     
        }
    }
    else
    {
        if(0u == adxl355_set_parameter(ADXL355_SELF_TEST, ADXL355_SELF_TEST_MASK, ADXL355_SELF_TEST_DISABLE))
        {
            adxl_st2_val = 0u;
        }
        else    
        {
            adxl_st_error = (uint16_t)__LINE__;//ERRORE STOP SELF-TEST      
        }       
    }
        
    return adxl_st_error;
}



/**
  * @}
  */



 /**
  * @}
  */ 
  
/************************ (C) COPYRIGHT TD Group *****END OF FILE**************/