From 0c8c329686065ea6ec68dba851bc1d21f3e3b17b Mon Sep 17 00:00:00 2001 From: RoccoMarco Date: Mon, 12 Jan 2015 12:45:03 +0100 Subject: Added devices_lib --- os/various/devices_lib/l3gd20.c | 126 ++++++++ os/various/devices_lib/l3gd20.h | 248 ++++++++++++++++ os/various/devices_lib/lis3mdl.c | 154 ++++++++++ os/various/devices_lib/lis3mdl.h | 260 ++++++++++++++++ os/various/devices_lib/lsm303dlhc.c | 207 +++++++++++++ os/various/devices_lib/lsm303dlhc.h | 357 ++++++++++++++++++++++ os/various/devices_lib/lsm6ds0.c | 186 ++++++++++++ os/various/devices_lib/lsm6ds0.h | 485 ++++++++++++++++++++++++++++++ os/various/devices_lib/max7219.c | 95 ++++++ os/various/devices_lib/max7219.h | 187 ++++++++++++ os/various/devices_lib/nrf24l01.c | 441 +++++++++++++++++++++++++++ os/various/devices_lib/nrf24l01.h | 577 ++++++++++++++++++++++++++++++++++++ 12 files changed, 3323 insertions(+) create mode 100644 os/various/devices_lib/l3gd20.c create mode 100644 os/various/devices_lib/l3gd20.h create mode 100644 os/various/devices_lib/lis3mdl.c create mode 100644 os/various/devices_lib/lis3mdl.h create mode 100644 os/various/devices_lib/lsm303dlhc.c create mode 100644 os/various/devices_lib/lsm303dlhc.h create mode 100644 os/various/devices_lib/lsm6ds0.c create mode 100644 os/various/devices_lib/lsm6ds0.h create mode 100644 os/various/devices_lib/max7219.c create mode 100644 os/various/devices_lib/max7219.h create mode 100644 os/various/devices_lib/nrf24l01.c create mode 100644 os/various/devices_lib/nrf24l01.h (limited to 'os') diff --git a/os/various/devices_lib/l3gd20.c b/os/various/devices_lib/l3gd20.c new file mode 100644 index 0000000..2d93ee8 --- /dev/null +++ b/os/various/devices_lib/l3gd20.c @@ -0,0 +1,126 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use it. + */ + +/** + * @file l3gd20.c + * @brief L3GD20 MEMS interface module code. + * + * @addtogroup l3gd20 + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "play.h" +#include "l3gd20.h" + +#if (GYRO_USE_L3GD20) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Reads a generic register value. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] reg register number + * @return register value. + */ +uint8_t l3gd20ReadRegister(SPIDriver *spip, uint8_t reg) { + uint8_t txbuf[2] = {L3GD20_RW | reg, 0xFF}; + uint8_t rxbuf[2] = {0x00, 0x00}; + spiSelect(spip); + spiExchange(spip, 2, txbuf, rxbuf); + spiUnselect(spip); + return rxbuf[1]; +} + + +void l3gd20WriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value) { + + switch (reg) { + + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "lg3d20WriteRegister(), #1", "reserved register"); + case L3GD20_AD_WHO_AM_I: + case L3GD20_AD_OUT_TEMP : + case L3GD20_AD_STATUS_REG: + case L3GD20_AD_OUT_X_L: + case L3GD20_AD_OUT_X_H: + case L3GD20_AD_OUT_Y_L: + case L3GD20_AD_OUT_Y_H: + case L3GD20_AD_OUT_Z_L: + case L3GD20_AD_OUT_Z_H: + case L3GD20_AD_FIFO_SRC_REG: + case L3GD20_AD_INT1_SRC: + /* Read only registers cannot be written, the command is ignored.*/ + return; + case L3GD20_AD_CTRL_REG1: + case L3GD20_AD_CTRL_REG2: + case L3GD20_AD_CTRL_REG3: + case L3GD20_AD_CTRL_REG4: + case L3GD20_AD_CTRL_REG5: + case L3GD20_AD_REFERENCE: + case L3GD20_AD_FIFO_CTRL_REG: + case L3GD20_AD_INT1_CFG: + case L3GD20_AD_INT1_TSH_XH: + case L3GD20_AD_INT1_TSH_XL: + case L3GD20_AD_INT1_TSH_YH: + case L3GD20_AD_INT1_TSH_YL: + case L3GD20_AD_INT1_TSH_ZH: + case L3GD20_AD_INT1_TSH_ZL: + case L3GD20_AD_INT1_DURATION: + spiSelect(spip); + uint8_t txbuf[2] = {reg, value}; + spiSend(spip, 2, txbuf); + spiUnselect(spip); + } +} + +#endif /* (GYRO_USE_L3GD20) */ + +/** @} */ diff --git a/os/various/devices_lib/l3gd20.h b/os/various/devices_lib/l3gd20.h new file mode 100644 index 0000000..3fc58cb --- /dev/null +++ b/os/various/devices_lib/l3gd20.h @@ -0,0 +1,248 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file l3gd20.h + * @brief L3GD20 MEMS interface module header. + * + * @{ + */ + +#ifndef _L3GD20_H_ +#define _L3GD20_H_ + +#if (GYRO_USE_L3GD20) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#if (PLAY_USE_FLOAT) || defined(__DOXYGEN__) +#define L3GD20_SENS_250DPS ((float)131.072f) /*!< gyroscope sensitivity with 250 dps full scale [LSB/dps] */ +#define L3GD20_SENS_500DPS ((float)65.536f) /*!< gyroscope sensitivity with 500 dps full scale [LSB/dps] */ +#define L3GD20_SENS_2000DPS ((float)16.384f) /*!< gyroscope sensitivity with 2000 dps full scale [LSB/dps] */ +#endif /* PLAY_USE_FLOAT */ +/** + * @name L3GD20 register names + * @{ + */ +/******************************************************************************/ +/* */ +/* L3GD20 on board MEMS */ +/* */ +/******************************************************************************/ +/******************* Bit definition for SPI communication *******************/ +#define L3GD20_DI ((uint8_t)0xFF) /*!< DI[7:0] Data input */ +#define L3GD20_DI_0 ((uint8_t)0x01) /*!< bit 0 */ +#define L3GD20_DI_1 ((uint8_t)0x02) /*!< bit 1 */ +#define L3GD20_DI_2 ((uint8_t)0x04) /*!< bit 2 */ +#define L3GD20_DI_3 ((uint8_t)0x08) /*!< bit 3 */ +#define L3GD20_DI_4 ((uint8_t)0x10) /*!< bit 4 */ +#define L3GD20_DI_5 ((uint8_t)0x20) /*!< bit 5 */ +#define L3GD20_DI_6 ((uint8_t)0x40) /*!< bit 6 */ +#define L3GD20_DI_7 ((uint8_t)0x80) /*!< bit 7 */ + +#define L3GD20_AD ((uint8_t)0x3F) /*!< AD[5:0] Address Data */ +#define L3GD20_AD_0 ((uint8_t)0x01) /*!< bit 0 */ +#define L3GD20_AD_1 ((uint8_t)0x02) /*!< bit 1 */ +#define L3GD20_AD_2 ((uint8_t)0x04) /*!< bit 2 */ +#define L3GD20_AD_3 ((uint8_t)0x08) /*!< bit 3 */ +#define L3GD20_AD_4 ((uint8_t)0x10) /*!< bit 4 */ +#define L3GD20_AD_5 ((uint8_t)0x20) /*!< bit 5 */ + +#define L3GD20_MS ((uint8_t)0x40) /*!< Multiple read write */ +#define L3GD20_RW ((uint8_t)0x80) /*!< Read Write, 1 0 */ + +/****************** Bit definition for Registers Addresses *******************/ +#define L3GD20_AD_WHO_AM_I ((uint8_t)0x0F) /*!< WHO I AM */ +#define L3GD20_AD_CTRL_REG1 ((uint8_t)0x20) /*!< CONTROL REGISTER 1 */ +#define L3GD20_AD_CTRL_REG2 ((uint8_t)0x21) /*!< CONTROL REGISTER 2 */ +#define L3GD20_AD_CTRL_REG3 ((uint8_t)0x22) /*!< CONTROL REGISTER 3 */ +#define L3GD20_AD_CTRL_REG4 ((uint8_t)0x23) /*!< CONTROL REGISTER 4 */ +#define L3GD20_AD_CTRL_REG5 ((uint8_t)0x24) /*!< CONTROL REGISTER 5 */ +#define L3GD20_AD_REFERENCE ((uint8_t)0x25) /*!< REFERENCE/DATACAPTURE */ +#define L3GD20_AD_OUT_TEMP ((uint8_t)0x26) /*!< MEMS ONBOARD TEMP SENSOR */ +#define L3GD20_AD_STATUS_REG ((uint8_t)0x27) /*!< STATUS REGISTER */ +#define L3GD20_AD_OUT_X_L ((uint8_t)0x28) /*!< OUTPUT X-AXIS LOW */ +#define L3GD20_AD_OUT_X_H ((uint8_t)0x29) /*!< OUTPUT X-AXIS HIGH */ +#define L3GD20_AD_OUT_Y_L ((uint8_t)0x2A) /*!< OUTPUT Y-AXIS LOW */ +#define L3GD20_AD_OUT_Y_H ((uint8_t)0x2B) /*!< OUTPUT Y-AXIS HIGH */ +#define L3GD20_AD_OUT_Z_L ((uint8_t)0x2C) /*!< OUTPUT Z-AXIS LOW */ +#define L3GD20_AD_OUT_Z_H ((uint8_t)0x2D) /*!< OUTPUT Z-AXIS HIGH */ +#define L3GD20_AD_FIFO_CTRL_REG ((uint8_t)0x2E) /*!< FIFO CONTROL REGISTER */ +#define L3GD20_AD_FIFO_SRC_REG ((uint8_t)0x2F) /*!< FIFO SOURCE REGISTER */ +#define L3GD20_AD_INT1_CFG ((uint8_t)0x30) /*!< INTERRUPT1 CONFIG REGISTER */ +#define L3GD20_AD_INT1_SRC ((uint8_t)0x31) /*!< INTERRUPT1 SOURCE REGISTER */ +#define L3GD20_AD_INT1_TSH_XH ((uint8_t)0x32) /*!< INTERRUPT1 THRESHOLD X-AXIS HIGH */ +#define L3GD20_AD_INT1_TSH_XL ((uint8_t)0x33) /*!< INTERRUPT1 THRESHOLD X-AXIS LOW */ +#define L3GD20_AD_INT1_TSH_YH ((uint8_t)0x34) /*!< INTERRUPT1 THRESHOLD Y-AXIS HIGH */ +#define L3GD20_AD_INT1_TSH_YL ((uint8_t)0x35) /*!< INTERRUPT1 THRESHOLD Y-AXIS LOW */ +#define L3GD20_AD_INT1_TSH_ZH ((uint8_t)0x36) /*!< INTERRUPT1 THRESHOLD Z-AXIS HIGH */ +#define L3GD20_AD_INT1_TSH_ZL ((uint8_t)0x37) /*!< INTERRUPT1 THRESHOLD Z-AXIS LOW */ +#define L3GD20_AD_INT1_DURATION ((uint8_t)0x38) /*!< INTERRUPT1 DURATION */ + +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name Gyroscope data structures and types + * @{ + */ + +/** + * @brief Gyroscope Output Data Rate + */ +typedef enum { + L3GD20_ODR_95Hz_Fc_12_5 = 0x00, /*!< Output Data Rate = 95 Hz - LPF Cut-Off = 12.5 Hz */ + L3GD20_ODR_95Hz_Fc_25 = 0x10, /*!< Output Data Rate = 95 Hz - LPF Cut-Off = 25 Hz */ + L3GD20_ODR_190Hz_Fc_12_5 = 0x40, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 12.5 Hz */ + L3GD20_ODR_190Hz_Fc_25 = 0x50, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 25 Hz */ + L3GD20_ODR_190Hz_Fc_50 = 0x60, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 50 Hz */ + L3GD20_ODR_190Hz_Fc_70 = 0x70, /*!< Output Data Rate = 190 Hz - LPF Cut-Off = 70 Hz */ + L3GD20_ODR_380Hz_Fc_20 = 0x80, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 20 Hz */ + L3GD20_ODR_380Hz_Fc_25 = 0x90, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 25 Hz */ + L3GD20_ODR_380Hz_Fc_50 = 0xA0, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 50 Hz */ + L3GD20_ODR_380Hz_Fc_100 = 0xB0, /*!< Output Data Rate = 380 Hz - LPF Cut-Off = 100 Hz */ + L3GD20_ODR_760Hz_Fc_30 = 0xC0, /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 30 Hz */ + L3GD20_ODR_760Hz_Fc_35 = 0xD0, /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 35 Hz */ + L3GD20_ODR_760Hz_Fc_50 = 0xE0, /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 50 Hz */ + L3GD20_ODR_760Hz_Fc_100 = 0xF0 /*!< Output Data Rate = 760 Hz - LPF Cut-Off = 100 Hz */ +}L3GD20_ODR_t; + +/** + * @brief Gyroscope Power Mode + */ +typedef enum { + L3GD20_PM_POWER_DOWN = 0x00, /*!< Normal mode enabled */ + L3GD20_PM_SLEEP_NORMAL = 0x08 /*!< Low Power mode enabled */ +}L3GD20_PM_t; + +/** + * @brief Gyroscope Full Scale + */ +typedef enum { + L3GD20_FS_250DPS = 0x00, /*!< ±250 dps */ + L3GD20_FS_500DPS = 0x10, /*!< ±500 dps */ + L3GD20_FS_2000DPS = 0x20 /*!< ±200 dps */ +}L3GD20_FS_t; + +/** + * @brief Gyroscope Axes Enabling + */ +typedef enum { + L3GD20_AE_DISABLED = 0x00, /*!< All disabled */ + L3GD20_AE_X = 0x01, /*!< Only X */ + L3GD20_AE_Y = 0x02, /*!< Only Y */ + L3GD20_AE_XY = 0x03, /*!< X & Y */ + L3GD20_AE_Z = 0x04, /*!< Only Z */ + L3GD20_AE_XZ = 0x05, /*!< X & Z */ + L3GD20_AE_YZ = 0x06, /*!< Y & Z */ + L3GD20_AE_XYZ = 0x07 /*!< All enabled */ +}L3GD20_AE_t; + +/** + * @brief Gyroscope Block Data Update + */ +typedef enum { + L3GD20_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ + L3GD20_BDU_BLOCKED = 0x80 /*!< Single Update: output registers not updated until MSB and LSB reading */ +}L3GD20_BDU_t; + +/** + * @brief Gyroscope Endianness + */ +typedef enum { + L3GD20_End_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ + L3GD20_End_BIG = 0x40 /*!< Big Endian: data MSB @ lower address */ +}L3GD20_End_t; + + +/** + * @brief Gyroscope configuration structure. + */ +typedef struct { + /** + * @brief Gyroscope fullscale value. + */ + L3GD20_FS_t fullscale; + /** + * @brief Gyroscope power mode selection. + */ + L3GD20_PM_t powermode; + /** + * @brief Gyroscope output data rate selection. + */ + L3GD20_ODR_t outputdatarate; + /** + * @brief Gyroscope axes enabling. + */ + L3GD20_AE_t axesenabling; + /** + * @brief Gyroscope endianess. + */ + L3GD20_End_t endianess; + /** + * @brief Gyroscope block data update. + */ + L3GD20_BDU_t blockdataupdate; +} L3GD20_Config; +/** @} */ +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + uint8_t l3gd20ReadRegister(SPIDriver *spip, uint8_t reg); + void l3gd20WriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value); +#ifdef __cplusplus +} +#endif + +#endif /* GYRO_USE_L3GD20 */ +#endif /* _L3GD20_H_ */ + +/** @} */ + +/* + * TODO PLAY--> add i2c support, and Multiple reg read. + */ diff --git a/os/various/devices_lib/lis3mdl.c b/os/various/devices_lib/lis3mdl.c new file mode 100644 index 0000000..dba95c3 --- /dev/null +++ b/os/various/devices_lib/lis3mdl.c @@ -0,0 +1,154 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file lis3mdl.c + * @brief LIS3MDL MEMS interface module through I2C code. + * + * @addtogroup lis3mdl + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "play.h" +#include "lis3mdl.h" + +#if (COMP_USE_LIS3MDL) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Reads a generic sub-register value. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] message pointer to message + * @return register value. + */ +uint8_t lis3mdlReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + msg_t* message) { + + uint8_t txbuf, rxbuf[2]; +#if defined(STM32F103_MCUCONF) + txbuf = LSM303DLHC_SUB_MSB | sub; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, TIME_INFINITE); + } + return rxbuf[0]; +#else + txbuf = sub; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, TIME_INFINITE); + } + return rxbuf[0]; +#endif +} + +/** + * @brief Writes a value into a register. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] value the value to be written + * @param[out] message pointer to message + */ +void lis3mdlWriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + uint8_t value, msg_t* message) { + + uint8_t txbuf[2]; + uint8_t rxbuf; + switch (sub) { + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "lis3mdlWriteRegister(), #1", "reserved register"); + case LIS3MDL_SUB_WHO_AM_I: + case LIS3MDL_SUB_STATUS_REG: + case LIS3MDL_SUB_OUT_X_L: + case LIS3MDL_SUB_OUT_X_H: + case LIS3MDL_SUB_OUT_Y_L: + case LIS3MDL_SUB_OUT_Y_H: + case LIS3MDL_SUB_OUT_Z_L: + case LIS3MDL_SUB_OUT_Z_H: + case LIS3MDL_SUB_INT_SOURCE: + case LIS3MDL_SUB_INT_THS_L: + case LIS3MDL_SUB_INT_THS_H: + /* Read only registers cannot be written, the command is ignored.*/ + return; + case LIS3MDL_SUB_CTRL_REG1: + case LIS3MDL_SUB_CTRL_REG2: + case LIS3MDL_SUB_CTRL_REG3: + case LIS3MDL_SUB_CTRL_REG4: + case LIS3MDL_SUB_CTRL_REG5: + case LIS3MDL_SUB_INT_CFG: + txbuf[0] = sub; + txbuf[1] = value; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); + } + break; + } +} + +#endif /* COMP_USE_LIS3MDL */ +/** @} */ diff --git a/os/various/devices_lib/lis3mdl.h b/os/various/devices_lib/lis3mdl.h new file mode 100644 index 0000000..8ef37ef --- /dev/null +++ b/os/various/devices_lib/lis3mdl.h @@ -0,0 +1,260 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file lis3mdl.h + * @brief LIS3MDL MEMS interface module header. + * + * @{ + */ + +#ifndef _LIS3MDL_H_ +#define _LIS3MDL_H_ + +#if (COMP_USE_LIS3MDL) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#if (PLAY_USE_FLOAT) || defined(__DOXYGEN__) +#define LIS3MDL_COMP_SENS_4GA ((float)6842.0f) /*!< compass sensitivity with 4 GA full scale [LSB / Ga] */ +#define LIS3MDL_COMP_SENS_8GA ((float)3421.0f) /*!< compass sensitivity with 8 GA full scale [LSB / Ga] */ +#define LIS3MDL_COMP_SENS_12GA ((float)2281.0f) /*!< compass sensitivity with 12 GA full scale [LSB / Ga] */ +#define LIS3MDL_COMP_SENS_16GA ((float)1711.0f) /*!< compass sensitivity with 16 GA full scale [LSB / Ga] */ +#endif /* PLAY_USE_FLOAT */ +/** + * @name LIS3MDL register names + * @{ + */ +/******************************************************************************/ +/* */ +/* LIS3MDL on board MEMS */ +/* */ +/******************************************************************************/ +/***************** Bit definition for I2C/SPI communication *****************/ +#define LIS3MDL_SUB ((uint8_t)0x7F) /*!< SUB[6:0] Sub-registers address Mask */ +#define LIS3MDL_SUB_0 ((uint8_t)0x01) /*!< bit 0 */ +#define LIS3MDL_SUB_1 ((uint8_t)0x02) /*!< bit 1 */ +#define LIS3MDL_SUB_2 ((uint8_t)0x08) /*!< bit 3 */ +#define LIS3MDL_SUB_4 ((uint8_t)0x10) /*!< bit 4 */ +#define LIS3MDL_SUB_5 ((uint8_t)0x20) /*!< bit 5 */ +#define LIS3MDL_SUB_6 ((uint8_t)0x40) /*!< bit 6 */ + +#define LIS3MDL_SUB_MSB ((uint8_t)0x80) /*!< Multiple data read\write bit */ + +/**************** Bit definition SUB-Registers Addresses ********************/ +#define LIS3MDL_SUB_WHO_AM_I ((uint8_t)0x0F) /*!< CONTROL REGISTER 1 */ +#define LIS3MDL_SUB_CTRL_REG1 ((uint8_t)0x20) /*!< CONTROL REGISTER 1 */ +#define LIS3MDL_SUB_CTRL_REG2 ((uint8_t)0x21) /*!< CONTROL REGISTER 2 */ +#define LIS3MDL_SUB_CTRL_REG3 ((uint8_t)0x22) /*!< CONTROL REGISTER 3 */ +#define LIS3MDL_SUB_CTRL_REG4 ((uint8_t)0x23) /*!< CONTROL REGISTER 4 */ +#define LIS3MDL_SUB_CTRL_REG5 ((uint8_t)0x24) /*!< CONTROL REGISTER 5 */ +#define LIS3MDL_SUB_STATUS_REG ((uint8_t)0x27) /*!< STATUS REGISTER */ +#define LIS3MDL_SUB_OUT_X_L ((uint8_t)0x28) /*!< OUTPUT X-AXIS LOW */ +#define LIS3MDL_SUB_OUT_X_H ((uint8_t)0x29) /*!< OUTPUT X-AXIS HIGH */ +#define LIS3MDL_SUB_OUT_Y_L ((uint8_t)0x2A) /*!< OUTPUT Y-AXIS LOW */ +#define LIS3MDL_SUB_OUT_Y_H ((uint8_t)0x2B) /*!< OUTPUT Y-AXIS HIGH */ +#define LIS3MDL_SUB_OUT_Z_L ((uint8_t)0x2C) /*!< OUTPUT Z-AXIS LOW */ +#define LIS3MDL_SUB_OUT_Z_H ((uint8_t)0x2D) /*!< OUTPUT Z-AXIS HIGH */ +#define LIS3MDL_SUB_INT_CFG ((uint8_t)0x30) /*!< INTERRUPT1 CONFIG */ +#define LIS3MDL_SUB_INT_SOURCE ((uint8_t)0x31) /*!< INTERRUPT1 SOURCE */ +#define LIS3MDL_SUB_INT_THS_L ((uint8_t)0x32) /*!< INTERRUPT1 THRESHOLD */ +#define LIS3MDL_SUB_INT_THS_H ((uint8_t)0x33) /*!< INTERRUPT1 DURATION */ + +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name Compass data structures and types + * @{ + */ + +/** + * @brief Compass Slave Address + */ +typedef enum { + LIS3MDL_SAD_GND = 0x1C, /*!< COMPASS Slave Address when SA1 is to GND */ + LIS3MDL_SAD_VCC = 0x1E /*!< COMPASS Slave Address when SA1 is to VCC */ +}LIS3MDL_SAD_t; + +/** + * @brief Compass Operation Mode for X and Y axes + */ +typedef enum { + LIS3MDL_OMXY_LOW_POWER = 0x00, /*!< Operation Mode XY low power */ + LIS3MDL_OMXY_MEDIUM_PERFORMANCE = 0x20, /*!< Operation Mode XY medium performance */ + LIS3MDL_OMXY_HIGH_PERFORMANCE = 0x40, /*!< Operation Mode XY high performance */ + LIS3MDL_OMXY_ULTRA_PERFORMANCE = 0x60 /*!< Operation Mode XY ultra performance */ +}LIS3MDL_OMXY_t; + +/** + * @brief Compass Output Data Rate + */ +typedef enum { + LIS3MDL_ODR_0_625Hz = 0x00, /*!< Output Data Rate = 0.625 Hz */ + LIS3MDL_ODR_1_25Hz = 0x04, /*!< Output Data Rate = 1.25 Hz */ + LIS3MDL_ODR_2_5Hz = 0x08, /*!< Output Data Rate = 2.5 Hz */ + LIS3MDL_ODR_5Hz = 0x0C, /*!< Output Data Rate = 5 Hz */ + LIS3MDL_ODR_10Hz = 0x10, /*!< Output Data Rate = 10 Hz */ + LIS3MDL_ODR_20Hz = 0x14, /*!< Output Data Rate = 20 Hz */ + LIS3MDL_ODR_40Hz = 0x18, /*!< Output Data Rate = 40 Hz */ + LIS3MDL_ODR_80Hz = 0x1C /*!< Output Data Rate = 80 Hz */ +}LIS3MDL_ODR_t; + +/** + * @brief Compass Full Scale + */ +typedef enum { + LIS3MDL_FS_4GA = 0x00, /*!< ±4 Gauss */ + LIS3MDL_FS_8GA = 0x02, /*!< ±8 Gauss */ + LIS3MDL_FS_12GA = 0x04, /*!< ±12 Gauss */ + LIS3MDL_FS_16GA = 0x0C /*!< ±16 Gauss */ +}LIS3MDL_FS_t; + +/** + * @brief Compass Low Mode configuration + */ +typedef enum { + LIS3MDL_LOW_POWER_DISABLED = 0x00, /*!< Low Power mode disabled */ + LIS3MDL_LOW_POWER_ENABLED = 0x20 /*!< Low Power mode enabled */ +}LIS3MDL_PM_t; + +/** + * @brief Compass Mode + */ +typedef enum { + LIS3MDL_MD_CONTINOUS_CONVERSION = 0x00, /*!< Continous conversion mode */ + LIS3MDL_MD_SINGLE_CONVERSION = 0x01, /*!< Single conversion mode */ + LIS3MDL_MD_POWER_DOWN = 0x02 /*!< Power down mode */ +}LIS3MDL_MD_t; + + +/** + * @brief Compass Operation Mode for Z axis + */ +typedef enum { + LIS3MDL_OMZ_LOW_POWER = 0x00, /*!< Operation Mode Z low power */ + LIS3MDL_OMZ_MEDIUM_PERFORMANCE = 0x04, /*!< Operation Mode Z medium performance */ + LIS3MDL_OMZ_HIGH_PERFORMANCE = 0x08, /*!< Operation Mode Z high performance */ + LIS3MDL_OMZ_ULTRA_PERFORMANCE = 0x0C /*!< Operation Mode Z ultra performance */ +}LIS3MDL_OMZ_t; + +/** + * @brief Compass Endianness + */ +typedef enum { + LIS3MDL_End_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ + LIS3MDL_End_BIG = 0x02 /*!< Big Endian: data MSB @ lower address */ +}LIS3MDL_End_t; + +/** + * @brief Compass Block Data Update + */ +typedef enum { + LIS3MDL_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ + LIS3MDL_BDU_BLOCKED = 0x40 /*!< Single Update: output registers not updated until MSB and LSB reading */ +}LIS3MDL_BDU_t; + + + + +/** + * @brief Gyroscope configuration structure. + */ +typedef struct { + /** + * @brief Compass Slave Address + */ + LIS3MDL_SAD_t slaveaddress; + /** + * @brief Compass Operation Mode for X and Y axes + */ + LIS3MDL_OMXY_t opmodexy; + /** + * @brief Compass Output Data Rate + */ + LIS3MDL_ODR_t outputdatarate; + /** + * @brief Compass Full Scale + */ + LIS3MDL_FS_t fullscale; + /** + * @brief Compass Low Mode configuration + */ + LIS3MDL_PM_t lowpowermode; + /** + * @brief Compass Mode + */ + LIS3MDL_MD_t mode; + /** + * @brief Compass Operation Mode for Z axis + */ + LIS3MDL_OMZ_t opmodez; + /** + * @brief Compass Endianness + */ + LIS3MDL_End_t endianess; + /** + * @brief Compass Block Data Update + */ + LIS3MDL_BDU_t blockdataupdate; +} LIS3MDL_Config; +/** @} */ +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + uint8_t lis3mdlReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + msg_t* message); + void lis3mdlWriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + uint8_t value, msg_t* message); +#ifdef __cplusplus +} +#endif + +#endif /* COMP_USE_LIS3MDL */ +#endif /* _LIS3MDL_H_ */ + +/** @} */ diff --git a/os/various/devices_lib/lsm303dlhc.c b/os/various/devices_lib/lsm303dlhc.c new file mode 100644 index 0000000..7861255 --- /dev/null +++ b/os/various/devices_lib/lsm303dlhc.c @@ -0,0 +1,207 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file lsm303dlhc.c + * @brief LSM303DLHC MEMS interface module through I2C code. + * + * @addtogroup lsm303dlhc + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "play.h" +#include "lsm303dlhc.h" + +#if (ACCEL_USE_LSM303DLHC) || (COMP_USE_LSM303DLHC) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Reads a generic sub-register value. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] message pointer to message + * @return register value. + */ +uint8_t lsm303dlhcReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + msg_t* message) { + + uint8_t txbuf, rxbuf[2]; +#if defined(STM32F103_MCUCONF) + txbuf = LSM303DLHC_SUB_MSB | sub; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, TIME_INFINITE); + } + return rxbuf[0]; +#else + txbuf = sub; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, TIME_INFINITE); + } + return rxbuf[0]; +#endif + + +} + +/** + * @brief Writes a value into a register. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] value the value to be written + * @param[out] message pointer to message + */ +void lsm303dlhcWriteRegister(I2CDriver *i2cp,uint8_t sad, uint8_t sub, + uint8_t value, msg_t* message) { + + uint8_t txbuf[2]; + uint8_t rxbuf; + if(sad == LSM303DLHC_SAD_ACCEL){ + switch (sub) { + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "lsm303dlhcWriteRegister(), #1", "reserved register"); + case LSM303DLHC_SUB_ACC_STATUS_REG: + case LSM303DLHC_SUB_ACC_OUT_X_L: + case LSM303DLHC_SUB_ACC_OUT_X_H: + case LSM303DLHC_SUB_ACC_OUT_Y_L: + case LSM303DLHC_SUB_ACC_OUT_Y_H: + case LSM303DLHC_SUB_ACC_OUT_Z_L: + case LSM303DLHC_SUB_ACC_OUT_Z_H: + case LSM303DLHC_SUB_ACC_FIFO_SRC_REG: + case LSM303DLHC_SUB_ACC_INT1_SOURCE: + case LSM303DLHC_SUB_ACC_INT2_SOURCE: + case LSM303DLHC_SUB_ACC_CLICK_SRC: + /* Read only registers cannot be written, the command is ignored.*/ + return; + case LSM303DLHC_SUB_ACC_CTRL_REG1: + case LSM303DLHC_SUB_ACC_CTRL_REG2: + case LSM303DLHC_SUB_ACC_CTRL_REG3: + case LSM303DLHC_SUB_ACC_CTRL_REG4: + case LSM303DLHC_SUB_ACC_CTRL_REG5: + case LSM303DLHC_SUB_ACC_CTRL_REG6: + case LSM303DLHC_SUB_ACC_REFERENCE: + case LSM303DLHC_SUB_ACC_FIFO_CTRL_REG: + case LSM303DLHC_SUB_ACC_INT1_CFG: + case LSM303DLHC_SUB_ACC_INT1_THS: + case LSM303DLHC_SUB_ACC_INT1_DURATION: + case LSM303DLHC_SUB_ACC_INT2_CFG: + case LSM303DLHC_SUB_ACC_INT2_THS: + case LSM303DLHC_SUB_ACC_INT2_DURATION: + case LSM303DLHC_SUB_ACC_CLICK_CFG: + case LSM303DLHC_SUB_ACC_CLICK_THS: + case LSM303DLHC_SUB_ACC_TIME_LIMIT: + case LSM303DLHC_SUB_ACC_TIME_LATENCY: + case LSM303DLHC_SUB_ACC_TIME_WINDOW: + txbuf[0] = sub; + txbuf[1] = value; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); + } + break; + } + } + else if(sad == LSM303DLHC_SAD_COMPASS){ + switch (sub) { + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "lsm303dlhcWriteRegister(), #1", "reserved register"); + case LSM303DLHC_SUB_COMP_OUT_X_H: + case LSM303DLHC_SUB_COMP_OUT_X_L: + case LSM303DLHC_SUB_COMP_OUT_Z_H: + case LSM303DLHC_SUB_COMP_OUT_Z_L: + case LSM303DLHC_SUB_COMP_OUT_Y_H: + case LSM303DLHC_SUB_COMP_OUT_Y_L: + case LSM303DLHC_SUB_COMP_SR_REG: + case LSM303DLHC_SUB_COMP_IRA_REG: + case LSM303DLHC_SUB_COMP_IRB_REG: + case LSM303DLHC_SUB_COMP_IRC_REG: + case LSM303DLHC_SUB_COMP_TEMP_OUT_H: + case LSM303DLHC_SUB_COMP_TEMP_OUT_L: + /* Read only registers cannot be written, the command is ignored.*/ + return; + case LSM303DLHC_SUB_COMP_CRA_REG: + case LSM303DLHC_SUB_COMP_CRB_REG: + case LSM303DLHC_SUB_COMP_MR_REG: + txbuf[0] = sub; + txbuf[1] = value; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); + } + break; + } + } +} +#endif /* (ACCEL_USE_LSM303DLHC) || (COMP_USE_LSM303DLHC) */ +/** @} */ diff --git a/os/various/devices_lib/lsm303dlhc.h b/os/various/devices_lib/lsm303dlhc.h new file mode 100644 index 0000000..4ea788a --- /dev/null +++ b/os/various/devices_lib/lsm303dlhc.h @@ -0,0 +1,357 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file lsm303dlhc.h + * @brief LSM303DLHC MEMS interface module through I2C header. + * + * @addtogroup lsm303dlhc + * @{ + */ + +#ifndef _LSM303DLHC_H_ +#define _LSM303DLHC_H_ + +#if (ACCEL_USE_LSM303DLHC) || (COMP_USE_LSM303DLHC) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#if (PLAY_USE_FLOAT) || defined(__DOXYGEN__) +#define LSM303DLHC_ACC_SENS_2G ((float)1671.836f) /*!< Accelerometer sensitivity with 2 G full scale [LSB * s^2 / m] */ +#define LSM303DLHC_ACC_SENS_4G ((float)835.918f) /*!< Accelerometer sensitivity with 4 G full scale [LSB * s^2 / m] */ +#define LSM303DLHC_ACC_SENS_8G ((float)417.959f) /*!< Accelerometer sensitivity with 8 G full scale [LSB * s^2 / m] */ +#define LSM303DLHC_ACC_SENS_16G ((float)208.979f) /*!< Accelerometer sensitivity with 16 G full scale [LSB * s^2 / m] */ + +#define LSM303DLHC_COMP_SENS_XY_1_3GA ((float)1100.0f) /*!< Compass sensitivity with 1.3 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_XY_1_9GA ((float)855.0f) /*!< Compass sensitivity with 1.9 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_XY_2_5GA ((float)670.0f) /*!< Compass sensitivity with 2.5 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_XY_4_0GA ((float)450.0f) /*!< Compass sensitivity with 4.0 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_XY_4_7GA ((float)400.0f) /*!< Compass sensitivity with 4.7 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_XY_5_6GA ((float)330.0f) /*!< Compass sensitivity with 5.6 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_XY_8_1GA ((float)230.0f) /*!< Compass sensitivity with 8.1 GA full scale [LSB / Ga] */ + +#define LSM303DLHC_COMP_SENS_Z_1_3GA ((float)980.0f) /*!< Compass sensitivity with 1.3 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_Z_1_9GA ((float)765.0f) /*!< Compass sensitivity with 1.9 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_Z_2_5GA ((float)600.0f) /*!< Compass sensitivity with 2.5 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_Z_4_0GA ((float)400.0f) /*!< Compass sensitivity with 4.0 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_Z_4_7GA ((float)355.0f) /*!< Compass sensitivity with 4.7 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_Z_5_6GA ((float)295.0f) /*!< Compass sensitivity with 5.6 GA full scale [LSB / Ga] */ +#define LSM303DLHC_COMP_SENS_Z_8_1GA ((float)205.0f) /*!< Compass sensitivity with 8.1 GA full scale [LSB / Ga] */ +#endif /* PLAY_USE_FLOAT */ +/** + * @name LSM303DLHC register names + * @{ + */ +/******************************************************************************/ +/* */ +/* LSM303DLHC on board MEMS */ +/* */ +/******************************************************************************/ +/******************* Bit definition for I2C communication *******************/ +#define LSM303DLHC_SAD ((uint8_t)0x7F) /*!< SAD[6:0] Slave Address Mask */ +#define LSM303DLHC_SAD_ACCEL ((uint8_t)0x19) /*!< ACCELEROMETER Slave Address */ +#define LSM303DLHC_SAD_COMPASS ((uint8_t)0x1E) /*!< MAGNETOMETER Slave Address */ + +#define LSM303DLHC_SUB ((uint8_t)0x7F) /*!< SUB[6:0] Sub-registers address Mask */ +#define LSM303DLHC_SUB_0 ((uint8_t)0x01) /*!< bit 0 */ +#define LSM303DLHC_SUB_1 ((uint8_t)0x02) /*!< bit 1 */ +#define LSM303DLHC_SUB_2 ((uint8_t)0x08) /*!< bit 3 */ +#define LSM303DLHC_SUB_4 ((uint8_t)0x10) /*!< bit 4 */ +#define LSM303DLHC_SUB_5 ((uint8_t)0x20) /*!< bit 5 */ +#define LSM303DLHC_SUB_6 ((uint8_t)0x40) /*!< bit 6 */ + +#define LSM303DLHC_SUB_MSB ((uint8_t)0x80) /*!< Multiple data read\write bit */ + +/******** Bit definition for Accelerometer SUB-Registers Addresses **********/ +#define LSM303DLHC_SUB_ACC_CTRL_REG1 ((uint8_t)0x20) /*!< CONTROL REGISTER 1 FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CTRL_REG2 ((uint8_t)0x21) /*!< CONTROL REGISTER 2 FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CTRL_REG3 ((uint8_t)0x22) /*!< CONTROL REGISTER 3 FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CTRL_REG4 ((uint8_t)0x23) /*!< CONTROL REGISTER 4 FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CTRL_REG5 ((uint8_t)0x24) /*!< CONTROL REGISTER 5 FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CTRL_REG6 ((uint8_t)0x25) /*!< CONTROL REGISTER 6 FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_REFERENCE ((uint8_t)0x26) /*!< REFERENCE/DATACAPTURE FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_STATUS_REG ((uint8_t)0x27) /*!< STATUS REGISTER FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_OUT_X_L ((uint8_t)0x28) /*!< OUTPUT X-AXIS LOW FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_OUT_X_H ((uint8_t)0x29) /*!< OUTPUT X-AXIS HIGH FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_OUT_Y_L ((uint8_t)0x2A) /*!< OUTPUT Y-AXIS LOW FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_OUT_Y_H ((uint8_t)0x2B) /*!< OUTPUT Y-AXIS HIGH FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_OUT_Z_L ((uint8_t)0x2C) /*!< OUTPUT Z-AXIS LOW FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_OUT_Z_H ((uint8_t)0x2D) /*!< OUTPUT Z-AXIS HIGH FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_FIFO_CTRL_REG ((uint8_t)0x2E) /*!< FIFO CONTROL REGISTER FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_FIFO_SRC_REG ((uint8_t)0x2F) /*!< FIFO SOURCE REGISTER FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT1_CFG ((uint8_t)0x30) /*!< INTERRUPT1 CONFIG FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT1_SOURCE ((uint8_t)0x31) /*!< INTERRUPT1 SOURCE FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT1_THS ((uint8_t)0x32) /*!< INTERRUPT1 THRESHOLD FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT1_DURATION ((uint8_t)0x33) /*!< INTERRUPT1 DURATION FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT2_CFG ((uint8_t)0x34) /*!< INTERRUPT2 CONFIG FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT2_SOURCE ((uint8_t)0x35) /*!< INTERRUPT2 SOURCE FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT2_THS ((uint8_t)0x36) /*!< INTERRUPT2 THRESHOLD FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_INT2_DURATION ((uint8_t)0x37) /*!< INTERRUPT2 DURATION FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CLICK_CFG ((uint8_t)0x38) /*!< CLICK CONFIG FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CLICK_SRC ((uint8_t)0x39) /*!< CLICK SOURCE FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_CLICK_THS ((uint8_t)0x3A) /*!< CLICK THRESHOLD FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_TIME_LIMIT ((uint8_t)0x3B) /*!< TIME LIMIT FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_TIME_LATENCY ((uint8_t)0x3C) /*!< TIME LATENCY FOR ACCELEROMETER */ +#define LSM303DLHC_SUB_ACC_TIME_WINDOW ((uint8_t)0x3D) /*!< TIME WINDOW FOR ACCELEROMETER */ + +/********* Bit definition for Compass SUB-Registers Addresses **********/ +#define LSM303DLHC_SUB_COMP_CRA_REG ((uint8_t)0x00) /*!< CONTROL REGISTER A FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_CRB_REG ((uint8_t)0x01) /*!< CONTROL REGISTER B FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_MR_REG ((uint8_t)0x02) /*!< STATUS REGISTER FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_OUT_X_H ((uint8_t)0x03) /*!< OUTPUT X-AXIS HIGH FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_OUT_X_L ((uint8_t)0x04) /*!< OUTPUT X-AXIS LOW FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_OUT_Z_H ((uint8_t)0x05) /*!< OUTPUT Z-AXIS HIGH FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_OUT_Z_L ((uint8_t)0x06) /*!< OUTPUT Z-AXIS LOW FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_OUT_Y_H ((uint8_t)0x07) /*!< OUTPUT Y-AXIS HIGH FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_OUT_Y_L ((uint8_t)0x08) /*!< OUTPUT Y-AXIS LOW FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_SR_REG ((uint8_t)0x09) /*!< SR REGISTER FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_IRA_REG ((uint8_t)0x0A) /*!< IR A REGISTER FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_IRB_REG ((uint8_t)0x0B) /*!< IR B REGISTER FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_IRC_REG ((uint8_t)0x0C) /*!< IR C REGISTER FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_TEMP_OUT_H ((uint8_t)0x31) /*!< OUTPUT TEMP HIGH FOR MAGNETOMETER */ +#define LSM303DLHC_SUB_COMP_TEMP_OUT_L ((uint8_t)0x32) /*!< OUTPUT TEMP LOW FOR MAGNETOMETER */ + +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name Accelerometer data structures and types + * @{ + */ + +/** + * @brief Accelerometer Output Data Rate + */ +typedef enum +{ + LSM303DLHC_ACC_ODR_PD = 0x00, /*!< Power down */ + LSM303DLHC_ACC_ODR_1Hz = 0x10, /*!< Output Data Rate = 1 Hz */ + LSM303DLHC_ACC_ODR_10Hz = 0x20, /*!< Output Data Rate = 10 Hz */ + LSM303DLHC_ACC_ODR_25Hz = 0x30, /*!< Output Data Rate = 25 Hz */ + LSM303DLHC_ACC_ODR_50Hz = 0x40, /*!< Output Data Rate = 50 Hz */ + LSM303DLHC_ACC_ODR_100Hz = 0x50, /*!< Output Data Rate = 100 Hz */ + LSM303DLHC_ACC_ODR_200Hz = 0x60, /*!< Output Data Rate = 200 Hz */ + LSM303DLHC_ACC_ODR_400Hz = 0x70, /*!< Output Data Rate = 400 Hz */ + LSM303DLHC_ACC_ODR_1620Hz = 0x80, /*!< Output Data Rate = 1620 Hz Low Power mode only */ + LSM303DLHC_ACC_ODR_1344Hz = 0x90 /*!< Output Data Rate = 1344 Hz in Normal mode and 5376 Hz in Low Power Mode */ +}LSM303DLHC_ACC_ODR_t; + +/** + * @brief Accelerometer Power Mode + */ +typedef enum +{ + LSM303DLHC_ACC_PM_NORMAL = 0x00, /*!< Normal mode enabled */ + LSM303DLHC_ACC_PM_LOW_POWER = 0x08 /*!< Low Power mode enabled */ +}LSM303DLHC_ACC_PM_t; + +/** + * @brief Accelerometer Full Scale + */ +typedef enum +{ + LSM303DLHC_ACC_FS_2G = 0x00, /*!< ±2 g m/s^2 */ + LSM303DLHC_ACC_FS_4G = 0x10, /*!< ±4 g m/s^2 */ + LSM303DLHC_ACC_FS_8G = 0x20, /*!< ±8 g m/s^2 */ + LSM303DLHC_ACC_FS_16G = 0x30 /*!< ±16 g m/s^2 */ +}LSM303DLHC_ACC_FS_t; + +/** + * @brief Accelerometer Axes Enabling + */ +typedef enum{ + LSM303DLHC_ACC_AE_DISABLED = 0x00, /*!< Axes all disabled */ + LSM303DLHC_ACC_AE_X = 0x01, /*!< Only X-axis enabled */ + LSM303DLHC_ACC_AE_Y = 0x02, /*!< Only Y-axis enabled */ + LSM303DLHC_ACC_AE_XY = 0x03, /*!< X & Y axes enabled */ + LSM303DLHC_ACC_AE_Z = 0x04, /*!< Only Z-axis enabled */ + LSM303DLHC_ACC_AE_XZ = 0x05, /*!< X & Z axes enabled */ + LSM303DLHC_ACC_AE_YZ = 0x06, /*!< Y & Z axes enabled */ + LSM303DLHC_ACC_AE_XYZ = 0x07 /*!< All axes enabled */ +}LSM303DLHC_ACC_AE_t; + +/** + * @brief Accelerometer Block Data Update + */ +typedef enum +{ + LSM303DLHC_ACC_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ + LSM303DLHC_ACC_BDU_BLOCKED = 0x80 /*!< Single Update: output registers not updated until MSB and LSB reading */ +}LSM303DLHC_ACC_BDU_t; + +/** + * @brief Accelerometer Endianness + */ +typedef enum +{ + LSM303DLHC_ACC_End_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ + LSM303DLHC_ACC_End_BIG = 0x40 /*!< Big Endian: data MSB @ lower address */ +}LSM303DLHC_ACC_End_t; + +/** + * @brief Accelerometer High Resolution mode + */ +typedef enum +{ + LSM303DLHC_ACC_HR_Enabled = 0x08, /*!< High resolution output mode enabled */ + LSM303DLHC_ACC_HR_Disabled = 0x00 /*!< High resolution output mode disabled */ +}LSM303DLHC_ACC_HR_t; + +/** + * @brief Accelerometer configuration structure. + */ +typedef struct { + /** + * @brief Accelerometer fullscale value. + */ + LSM303DLHC_ACC_FS_t fullscale; + /** + * @brief Accelerometer power mode selection. + */ + LSM303DLHC_ACC_PM_t powermode; + /** + * @brief Accelerometer output data rate selection. + */ + LSM303DLHC_ACC_ODR_t outputdatarate; + /** + * @brief Accelerometer axes enabling. + */ + LSM303DLHC_ACC_AE_t axesenabling; + /** + * @brief Accelerometer block data update. + */ + LSM303DLHC_ACC_BDU_t blockdataupdate; + /** + * @brief Accelerometer block data update. + */ + LSM303DLHC_ACC_HR_t highresmode; +} LSM303DLHC_ACC_Config; +/** @} */ + + +/** + * @name Compass data types + * @{ + */ + +/** + * @brief Compass Output Data Rate + */ +typedef enum +{ + LSM303DLHC_COMP_ODR_0_75_Hz = 0x00, /*!< Output Data Rate = 0.75 Hz */ + LSM303DLHC_COMP_ODR_1_5_Hz = 0x04, /*!< Output Data Rate = 1.5 Hz */ + LSM303DLHC_COMP_ODR_3_0_Hz = 0x08, /*!< Output Data Rate = 3 Hz */ + LSM303DLHC_COMP_ODR_7_5_Hz = 0x0C, /*!< Output Data Rate = 7.5 Hz */ + LSM303DLHC_COMP_ODR_15_Hz = 0x10, /*!< Output Data Rate = 15 Hz */ + LSM303DLHC_COMP_ODR_30_Hz = 0x14, /*!< Output Data Rate = 30 Hz */ + LSM303DLHC_COMP_ODR_75_Hz = 0x18, /*!< Output Data Rate = 75 Hz */ + LSM303DLHC_COMP_ODR_220_Hz = 0x1C /*!< Output Data Rate = 220 Hz */ +}LSM303DLHC_COMP_ODR_t; + + +/** + * @brief Compass Full Scale + */ +typedef enum +{ + LSM303DLHC_COMP_FS_1_3_GA = 0x20, /*!< Full scale = ±1.3 Gauss */ + LSM303DLHC_COMP_FS_1_9_GA = 0x40, /*!< Full scale = ±1.9 Gauss */ + LSM303DLHC_COMP_FS_2_5_GA = 0x60, /*!< Full scale = ±2.5 Gauss */ + LSM303DLHC_COMP_FS_4_0_GA = 0x80, /*!< Full scale = ±4.0 Gauss */ + LSM303DLHC_COMP_FS_4_7_GA = 0xA0, /*!< Full scale = ±4.7 Gauss */ + LSM303DLHC_COMP_FS_5_6_GA = 0xC0, /*!< Full scale = ±5.6 Gauss */ + LSM303DLHC_COMP_FS_8_1_GA = 0xE0 /*!< Full scale = ±8.1 Gauss */ +}LSM303DLHC_COMP_FS_t; + + +/** + * @brief Compass Working Mode + */ +typedef enum +{ + LSM303DLHC_COMP_WM_CONTINUOS = 0x00, /*!< Continuous-Conversion Mode */ + LSM303DLHC_COMP_WM_BLOCKED = 0x01, /*!< Single-Conversion Mode */ + LSM303DLHC_COMP_WM_SLEEP = 0x02 /*!< Sleep Mode */ +}LSM303DLHC_COMP_WM_t; + +/** + * @brief Compass configuration structure. + */ +typedef struct { + /** + * @brief Compass fullscale value. + */ + LSM303DLHC_COMP_FS_t fullscale; + /** + * @brief Compass output data rate selection. + */ + LSM303DLHC_COMP_ODR_t outputdatarate; + /** + * @brief Compass working mode. + */ + LSM303DLHC_COMP_WM_t workingmode; +} LSM303DLHC_COMP_Config; +/** @} */ +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + uint8_t lsm303dlhcReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + msg_t* message); + void lsm303dlhcWriteRegister(I2CDriver *i2cp,uint8_t sad, uint8_t sub, + uint8_t value, msg_t* message); + +#ifdef __cplusplus +} +#endif +#endif /* (ACCEL_USE_LSM303DLHC) || (COMP_USE_LSM303DLHC) */ +#endif /* _LSM303DLHC_H_ */ +/** @} */ + +/* + * TODO PLAY--> add spi support, and Multiple reg read. + */ diff --git a/os/various/devices_lib/lsm6ds0.c b/os/various/devices_lib/lsm6ds0.c new file mode 100644 index 0000000..304b340 --- /dev/null +++ b/os/various/devices_lib/lsm6ds0.c @@ -0,0 +1,186 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file lsm6ds0.c + * @brief LSM6DS0 MEMS interface module through I2C code. + * + * @addtogroup lsm6ds0 + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "play.h" +#include "lsm6ds0.h" + +#if (ACCEL_USE_LSM6DS0) || (GYRO_USE_LSM6DS0) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Reads a generic sub-register value. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] message pointer to message + * @return register value. + */ +uint8_t lsm6ds0ReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + msg_t* message) { + + uint8_t txbuf, rxbuf[2]; +#if defined(STM32F103_MCUCONF) + txbuf = LSM303DLHC_SUB_MSB | sub; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 2, TIME_INFINITE); + } + return rxbuf[0]; +#else + txbuf = sub; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, 1, TIME_INFINITE); + } + return rxbuf[0]; +#endif +} + +/** + * @brief Writes a value into a register. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] value the value to be written + * @param[out] message pointer to message + */ +void lsm6ds0WriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + uint8_t value, msg_t* message) { + + uint8_t txbuf[2]; + uint8_t rxbuf; + switch (sub) { + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "lsm6ds0WriteRegister(), #1", "reserved register"); + case LSM6DS0_SUB_WHO_AM_I: + case LSM6DS0_SUB_INT_GEN_SRC_G: + case LSM6DS0_SUB_OUT_TEMP_L: + case LSM6DS0_SUB_OUT_TEMP_H: + case LSM6DS0_SUB_STATUS_REG1: + case LSM6DS0_SUB_OUT_X_L_G: + case LSM6DS0_SUB_OUT_X_H_G: + case LSM6DS0_SUB_OUT_Y_L_G: + case LSM6DS0_SUB_OUT_Y_H_G: + case LSM6DS0_SUB_OUT_Z_L_G: + case LSM6DS0_SUB_OUT_Z_H_G: + case LSM6DS0_SUB_INT_GEN_SRC_XL: + case LSM6DS0_SUB_STATUS_REG2: + case LSM6DS0_SUB_OUT_X_L_XL: + case LSM6DS0_SUB_OUT_X_H_XL: + case LSM6DS0_SUB_OUT_Y_L_XL: + case LSM6DS0_SUB_OUT_Y_H_XL: + case LSM6DS0_SUB_OUT_Z_L_XL: + case LSM6DS0_SUB_OUT_Z_H_XL: + case LSM6DS0_SUB_FIFO_SRC: + /* Read only registers cannot be written, the command is ignored.*/ + return; + case LSM6DS0_SUB_ACT_THS: + case LSM6DS0_SUB_ACT_DUR: + case LSM6DS0_SUB_INT_GEN_CFG_XL: + case LSM6DS0_SUB_INT_GEN_THS_X_XL: + case LSM6DS0_SUB_INT_GEN_THS_Y_XL: + case LSM6DS0_SUB_INT_GEN_THS_Z_XL: + case LSM6DS0_SUB_INT_GEN_DUR_XL: + case LSM6DS0_SUB_REFERENCE_G: + case LSM6DS0_SUB_INT_CTRL: + case LSM6DS0_SUB_CTRL_REG1_G: + case LSM6DS0_SUB_CTRL_REG2_G: + case LSM6DS0_SUB_CTRL_REG3_G: + case LSM6DS0_SUB_ORIENT_CFG_G: + case LSM6DS0_SUB_CTRL_REG4: + case LSM6DS0_SUB_CTRL_REG5_XL: + case LSM6DS0_SUB_CTRL_REG6_XL: + case LSM6DS0_SUB_CTRL_REG7_XL: + case LSM6DS0_SUB_CTRL_REG8: + case LSM6DS0_SUB_CTRL_REG9: + case LSM6DS0_SUB_CTRL_REG10: + case LSM6DS0_SUB_FIFO_CTRL: + case LSM6DS0_SUB_INT_GEN_CFG_G: + case LSM6DS0_SUB_INT_GEN_THS_XH_G: + case LSM6DS0_SUB_INT_GEN_THS_XL_G: + case LSM6DS0_SUB_INT_GEN_THS_YH_G: + case LSM6DS0_SUB_INT_GEN_THS_YL_G: + case LSM6DS0_SUB_INT_GEN_THS_ZH_G: + case LSM6DS0_SUB_INT_GEN_THS_ZL_G: + case LSM6DS0_SUB_INT_GEN_DUR_G: + txbuf[0] = sub; + txbuf[1] = value; + if(message != NULL){ + *message = i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, + TIME_INFINITE); + } + else{ + i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, &rxbuf, 0, TIME_INFINITE); + } + break; + } +} + +#endif /* (ACCEL_USE_LSM6DS0) || (GYRO_USE_LSM6DS0) */ +/** @} */ diff --git a/os/various/devices_lib/lsm6ds0.h b/os/various/devices_lib/lsm6ds0.h new file mode 100644 index 0000000..9f27e1b --- /dev/null +++ b/os/various/devices_lib/lsm6ds0.h @@ -0,0 +1,485 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file lsm6ds0.h + * @brief LSM6DS0 MEMS interface module header. + * + * @{ + */ + +#ifndef _LSM6DS0_H_ +#define _LSM6DS0_H_ + +#if (ACCEL_USE_LSM6DS0) || (GYRO_USE_LSM6DS0) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#if (PLAY_USE_FLOAT) || defined(__DOXYGEN__) +#define LSM6DS0_ACC_SENS_2G ((float)1671.095f) /*!< Accelerometer sensitivity with 2 G full scale [LSB * s^2 / m] */ +#define LSM6DS0_ACC_SENS_4G ((float)835.547f) /*!< Accelerometer sensitivity with 4 G full scale [LSB * s^2 / m] */ +#define LSM6DS0_ACC_SENS_8G ((float)417.774) /*!< Accelerometer sensitivity with 8 G full scale [LSB * s^2 / m] */ +#define LSM6DS0_ACC_SENS_16G ((float)139.258f) /*!< Accelerometer sensitivity with 16 G full scale [LSB * s^2 / m] */ + +#define LSM6DS0_GYRO_SENS_245DPS ((float)114.286f) /*!< Gyroscope sensitivity with 245 dps full scale [LSB * s / °] */ +#define LSM6DS0_GYRO_SENS_500DPS ((float)57.143f) /*!< Gyroscope sensitivity with 500 dps full scale [LSB * s / °] */ +#define LSM6DS0_GYRO_SENS_2000DPS ((float)14.286f) /*!< Gyroscope sensitivity with 2000 dps full scale [LSB * s / °] */ + +#endif /* PLAY_USE_FLOAT */ +/** + * @name LSM6DS0 register names + * @{ + */ +/******************************************************************************/ +/* */ +/* LSM6DS0 on board MEMS */ +/* */ +/******************************************************************************/ +/***************** Bit definition for I2C/SPI communication *****************/ +#define LSM6DS0_SUB ((uint8_t)0x7F) /*!< SUB[6:0] Sub-registers address Mask */ +#define LSM6DS0_SUB_0 ((uint8_t)0x01) /*!< bit 0 */ +#define LSM6DS0_SUB_1 ((uint8_t)0x02) /*!< bit 1 */ +#define LSM6DS0_SUB_2 ((uint8_t)0x08) /*!< bit 3 */ +#define LSM6DS0_SUB_4 ((uint8_t)0x10) /*!< bit 4 */ +#define LSM6DS0_SUB_5 ((uint8_t)0x20) /*!< bit 5 */ +#define LSM6DS0_SUB_6 ((uint8_t)0x40) /*!< bit 6 */ + +#define LSM6DS0_SUB_MSB ((uint8_t)0x80) /*!< Multiple data read\write bit */ + +/***************** Bit definition for Registers Addresses *******************/ +#define LSM6DS0_SUB_ACT_THS ((uint8_t)0x04) /*!< Activity threshold register */ +#define LSM6DS0_SUB_ACT_DUR ((uint8_t)0x05) /*!< Inactivity duration register */ +#define LSM6DS0_SUB_INT_GEN_CFG_XL ((uint8_t)0x06) /*!< Accelerometer interrupt generator configuration register */ +#define LSM6DS0_SUB_INT_GEN_THS_X_XL ((uint8_t)0x07) /*!< Accelerometer X-axis interrupt threshold register */ +#define LSM6DS0_SUB_INT_GEN_THS_Y_XL ((uint8_t)0x08) /*!< Accelerometer Y-axis interrupt threshold register */ +#define LSM6DS0_SUB_INT_GEN_THS_Z_XL ((uint8_t)0x09) /*!< Accelerometer Z-axis interrupt threshold register */ +#define LSM6DS0_SUB_INT_GEN_DUR_XL ((uint8_t)0x0A) /*!< Accelerometer interrupt duration register */ +#define LSM6DS0_SUB_REFERENCE_G ((uint8_t)0x0B) /*!< Gyroscope reference value register for digital high-pass filter */ +#define LSM6DS0_SUB_INT_CTRL ((uint8_t)0x0C) /*!< INT pin control register */ +#define LSM6DS0_SUB_WHO_AM_I ((uint8_t)0x0F) /*!< Who_AM_I register */ +#define LSM6DS0_SUB_CTRL_REG1_G ((uint8_t)0x10) /*!< Gyroscope control register 1 */ +#define LSM6DS0_SUB_CTRL_REG2_G ((uint8_t)0x11) /*!< Gyroscope control register 2 */ +#define LSM6DS0_SUB_CTRL_REG3_G ((uint8_t)0x12) /*!< Gyroscope control register 3 */ +#define LSM6DS0_SUB_ORIENT_CFG_G ((uint8_t)0x13) /*!< Gyroscope sign and orientation register */ +#define LSM6DS0_SUB_INT_GEN_SRC_G ((uint8_t)0x14) /*!< Gyroscope interrupt source register */ +#define LSM6DS0_SUB_OUT_TEMP_L ((uint8_t)0x15) /*!< Temperature data output low register */ +#define LSM6DS0_SUB_OUT_TEMP_H ((uint8_t)0x16) /*!< Temperature data output high register */ +#define LSM6DS0_SUB_STATUS_REG1 ((uint8_t)0x17) /*!< Status register 1 */ +#define LSM6DS0_SUB_OUT_X_L_G ((uint8_t)0x18) /*!< Gyroscope X-axis low output register */ +#define LSM6DS0_SUB_OUT_X_H_G ((uint8_t)0x19) /*!< Gyroscope X-axis high output register */ +#define LSM6DS0_SUB_OUT_Y_L_G ((uint8_t)0x1A) /*!< Gyroscope Y-axis low output register */ +#define LSM6DS0_SUB_OUT_Y_H_G ((uint8_t)0x1B) /*!< Gyroscope Y-axis high output register */ +#define LSM6DS0_SUB_OUT_Z_L_G ((uint8_t)0x1C) /*!< Gyroscope Z-axis low output register */ +#define LSM6DS0_SUB_OUT_Z_H_G ((uint8_t)0x1D) /*!< Gyroscope Z-axis high output register */ +#define LSM6DS0_SUB_CTRL_REG4 ((uint8_t)0x1E) /*!< Control register 4 */ +#define LSM6DS0_SUB_CTRL_REG5_XL ((uint8_t)0x1F) /*!< Accelerometer Control Register 5 */ +#define LSM6DS0_SUB_CTRL_REG6_XL ((uint8_t)0x20) /*!< Accelerometer Control Register 6 */ +#define LSM6DS0_SUB_CTRL_REG7_XL ((uint8_t)0x21) /*!< Accelerometer Control Register 7 */ +#define LSM6DS0_SUB_CTRL_REG8 ((uint8_t)0x22) /*!< Control register 8 */ +#define LSM6DS0_SUB_CTRL_REG9 ((uint8_t)0x23) /*!< Control register 9 */ +#define LSM6DS0_SUB_CTRL_REG10 ((uint8_t)0x24) /*!< Control register 10 */ +#define LSM6DS0_SUB_INT_GEN_SRC_XL ((uint8_t)0x26) /*!< Accelerometer interrupt source register */ +#define LSM6DS0_SUB_STATUS_REG2 ((uint8_t)0x27) /*!< Status register */ +#define LSM6DS0_SUB_OUT_X_L_XL ((uint8_t)0x28) /*!< Accelerometer X-axis low output register */ +#define LSM6DS0_SUB_OUT_X_H_XL ((uint8_t)0x29) /*!< Accelerometer X-axis high output register */ +#define LSM6DS0_SUB_OUT_Y_L_XL ((uint8_t)0x2A) /*!< Accelerometer Y-axis low output register */ +#define LSM6DS0_SUB_OUT_Y_H_XL ((uint8_t)0x2B) /*!< Accelerometer Y-axis high output register */ +#define LSM6DS0_SUB_OUT_Z_L_XL ((uint8_t)0x2C) /*!< Accelerometer Z-axis low output register */ +#define LSM6DS0_SUB_OUT_Z_H_XL ((uint8_t)0x2D) /*!< Accelerometer Z-axis high output register */ +#define LSM6DS0_SUB_FIFO_CTRL ((uint8_t)0x2E) /*!< FIFO control register */ +#define LSM6DS0_SUB_FIFO_SRC ((uint8_t)0x2F) /*!< FIFO status control register */ +#define LSM6DS0_SUB_INT_GEN_CFG_G ((uint8_t)0x30) /*!< Gyroscope interrupt generator configuration register */ +#define LSM6DS0_SUB_INT_GEN_THS_XH_G ((uint8_t)0x31) /*!< Gyroscope X-axis low interrupt generator threshold registers */ +#define LSM6DS0_SUB_INT_GEN_THS_XL_G ((uint8_t)0x32) /*!< Gyroscope X-axis high interrupt generator threshold registers */ +#define LSM6DS0_SUB_INT_GEN_THS_YH_G ((uint8_t)0x33) /*!< Gyroscope Y-axis low interrupt generator threshold registers */ +#define LSM6DS0_SUB_INT_GEN_THS_YL_G ((uint8_t)0x34) /*!< Gyroscope Y-axis high interrupt generator threshold registers */ +#define LSM6DS0_SUB_INT_GEN_THS_ZH_G ((uint8_t)0x35) /*!< Gyroscope Z-axis low interrupt generator threshold registers */ +#define LSM6DS0_SUB_INT_GEN_THS_ZL_G ((uint8_t)0x36) /*!< Gyroscope Z-axis high interrupt generator threshold registers */ +#define LSM6DS0_SUB_INT_GEN_DUR_G ((uint8_t)0x37) /*!< Gyroscope interrupt generator duration register */ + +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name Generic LSM6DS0 data structures and types + * @{ + */ + +/** + * @brief Accelerometer and Gyroscope Slave Address + */ +typedef enum { + LSM6DS0_SAD_GND = 0x6A, /*!< LSM6DS0 Slave Address when SA1 is to GND */ + LSM6DS0_SAD_VCC = 0x6B /*!< LSM6DS0 Slave Address when SA1 is to VCC */ +}LSM6DS0_SAD_t; + +/** + * @brief Accelerometer and Gyroscope Block Data Update + */ +typedef enum +{ + LSM6DS0_BDU_CONTINOUS = 0x00, /*!< Continuos Update */ + LSM6DS0_BDU_BLOCKED = 0x40 /*!< Single Update: output registers not updated until MSB and LSB reading */ +}LSM6DS0_BDU_t; + +/** + * @brief Accelerometer and Gyroscope Endianness + */ +typedef enum +{ + LSM6DS0_END_LITTLE = 0x00, /*!< Little Endian: data LSB @ lower address */ + LSM6DS0_END_BIG = 0x20 /*!< Big Endian: data MSB @ lower address */ +}LSM6DS0_END_t; +/** @} */ + +/** + * @name Accelerometer data structures and types + * @{ + */ + +/** + * @brief Accelerometer Decimation Mode + */ +typedef enum { + LSM6DS0_ACC_DEC_DISABLED = 0x00, /*!< NO decimation */ + LSM6DS0_ACC_DEC_X2 = 0x40, /*!< Decimation update every 2 sample */ + LSM6DS0_ACC_DEC_X4 = 0x80, /*!< Decimation update every 4 sample */ + LSM6DS0_ACC_DEC_X8 = 0xC0 /*!< Decimation update every 8 sample */ +}LSM6DS0_ACC_DEC_t; + +/** + * @brief Accelerometer Axes Enabling + */ +typedef enum{ + LSM6DS0_ACC_AE_DISABLED = 0x00, /*!< Axes all disabled */ + LSM6DS0_ACC_AE_X = 0x08, /*!< Only X-axis enabled */ + LSM6DS0_ACC_AE_Y = 0x10, /*!< Only Y-axis enabled */ + LSM6DS0_ACC_AE_XY = 0x18, /*!< X & Y axes enabled */ + LSM6DS0_ACC_AE_Z = 0x20, /*!< Only Z-axis enabled */ + LSM6DS0_ACC_AE_XZ = 0x28, /*!< X & Z axes enabled */ + LSM6DS0_ACC_AE_YZ = 0x30, /*!< Y & Z axes enabled */ + LSM6DS0_ACC_AE_XYZ = 0x38 /*!< All axes enabled */ +}LSM6DS0_ACC_AE_t; + +/** + * @brief Accelerometer Output Data Rate + */ +typedef enum { + LSM6DS0_ACC_ODR_PD = 0x00, /*!< Power down */ + LSM6DS0_ACC_ODR_10Hz = 0x20, /*!< Output Data Rate = 10 Hz */ + LSM6DS0_ACC_ODR_50Hz = 0x40, /*!< Output Data Rate = 50 Hz */ + LSM6DS0_ACC_ODR_119Hz = 0x60, /*!< Output Data Rate = 119 Hz */ + LSM6DS0_ACC_ODR_238Hz = 0x80, /*!< Output Data Rate = 238 Hz */ + LSM6DS0_ACC_ODR_476Hz = 0xA0, /*!< Output Data Rate = 476 Hz */ + LSM6DS0_ACC_ODR_952Hz = 0xC0 /*!< Output Data Rate = 952 Hz */ +}LSM6DS0_ACC_ODR_t; + +/** + * @brief Accelerometer Full Scale + */ +typedef enum { + LSM6DS0_ACC_FS_2G = 0x00, /*!< ±2 g m/s^2 */ + LSM6DS0_ACC_FS_4G = 0x10, /*!< ±4 g m/s^2 */ + LSM6DS0_ACC_FS_8G = 0x18, /*!< ±8 g m/s^2 */ + LSM6DS0_ACC_FS_16G = 0x08 /*!< ±16 g m/s^2 */ +}LSM6DS0_ACC_FS_t; + +/** + * @brief Accelerometer Antialiasing filter Bandwidth Selection + */ +typedef enum { + LSM6DS0_ACC_BW_408Hz = 0x00, /*!< AA filter bandwidth = 408 Hz */ + LSM6DS0_ACC_BW_211Hz = 0x01, /*!< AA filter bandwidth = 211 Hz */ + LSM6DS0_ACC_BW_105Hz = 0x02, /*!< AA filter bandwidth = 105 Hz */ + LSM6DS0_ACC_BW_50Hz = 0x03, /*!< AA filter bandwidth = 50 Hz */ + LSM6DS0_ACC_BW_ACCORDED = 0x04, /*!< AA filter bandwidth chosen by ODR selection */ +}LSM6DS0_ACC_BW_t; + +/** + * @brief Accelerometer High Resolution mode + */ +typedef enum +{ + LSM6DS0_ACC_HR_Disabled = 0x00, /*!< High resolution output mode disabled, FDS bypassed */ + LSM6DS0_ACC_HR_EN_9 = 0xC4, /*!< High resolution output mode enabled, LP cutoff = ODR/9, FDS enabled */ + LSM6DS0_ACC_HR_EN_50 = 0x84, /*!< High resolution output mode enabled, LP cutoff = ODR/50, FDS enabled */ + LSM6DS0_ACC_HR_EN_100 = 0xA4, /*!< High resolution output mode enabled, LP cutoff = ODR/100, FDS enabled */ + LSM6DS0_ACC_HR_EN_400 = 0xE4, /*!< High resolution output mode enabled, LP cutoff = ODR/400, FDS enabled */ +}LSM6DS0_ACC_HR_t; + +/** + * @brief HP filter for interrupt + */ +typedef enum +{ + LSM6DS0_ACC_HPIS1_BYPASSED = 0x00, /*!< High-pass filter bypassed */ + LSM6DS0_ACC_HPIS1_ENABLED = 0x01 /*!< High-pass filter enabled for accelerometer interrupt function on interrupt */ +}LSM6DS0_ACC_HPIS1_t; + +/** + * @brief Accelerometer configuration structure. + */ +typedef struct { + + /** + * @brief LSM6DS0 Slave Address + */ + LSM6DS0_SAD_t slaveaddress; + /** + * @brief Accelerometer Decimation Mode + */ + LSM6DS0_ACC_DEC_t decimation; + /** + * @brief Accelerometer Output Data Rate + */ + LSM6DS0_ACC_ODR_t outputdatarate; + /** + * @brief Accelerometer Antialiasing filter Bandwidth Selection + */ + LSM6DS0_ACC_BW_t bandwidth; + /** + * @brief Accelerometer Full Scale + */ + LSM6DS0_ACC_FS_t fullscale; + /** + * @brief Accelerometer Axes Enabling + */ + LSM6DS0_ACC_AE_t axesenabling; + /** + * @brief Accelerometer High Resolution mode + */ + LSM6DS0_ACC_HR_t highresmode; + /** + * @brief HP filter for interrupt + */ + LSM6DS0_ACC_HPIS1_t hpfirq; + /** + * @brief LSM6DS0 Endianness + */ + LSM6DS0_END_t endianess; + /** + * @brief LSM6DS0 Block Data Update + */ + LSM6DS0_BDU_t blockdataupdate; +} LSM6DS0_ACC_Config; +/** @} */ + +/** + * @name Gyroscope data structures and types + * @{ + */ + +/** + * @brief Gyroscope Output Data Rate + */ +typedef enum { + LSM6DS0_GYRO_ODR_PD = 0x00, /*!< Power down */ + LSM6DS0_GYRO_ODR_14_9Hz_CO_5Hz = 0x20, /*!< Output Data Rate = 14.9 Hz, CutOff = 5Hz */ + LSM6DS0_GYRO_ODR_59_5Hz_CO_16Hz = 0x40, /*!< Output Data Rate = 59.5 Hz, CutOff = 16Hz */ + LSM6DS0_GYRO_ODR_119Hz_CO_14Hz = 0x60, /*!< Output Data Rate = 119 Hz, CutOff = 14Hz */ + LSM6DS0_GYRO_ODR_119Hz_CO_31Hz = 0x61, /*!< Output Data Rate = 119 Hz, CutOff = 31Hz */ + LSM6DS0_GYRO_ODR_238Hz_CO_14Hz = 0x80, /*!< Output Data Rate = 238 Hz, CutOff = 14Hz */ + LSM6DS0_GYRO_ODR_238Hz_CO_29Hz = 0x81, /*!< Output Data Rate = 328 Hz, CutOff = 29Hz */ + LSM6DS0_GYRO_ODR_238Hz_CO_63Hz = 0x82, /*!< Output Data Rate = 238 Hz, CutOff = 63Hz */ + LSM6DS0_GYRO_ODR_238Hz_CO_78Hz = 0x83, /*!< Output Data Rate = 476 Hz, CutOff = 78Hz */ + LSM6DS0_GYRO_ODR_476Hz_CO_21Hz = 0xA0, /*!< Output Data Rate = 476 Hz, CutOff = 21Hz */ + LSM6DS0_GYRO_ODR_476Hz_CO_28Hz = 0xA1, /*!< Output Data Rate = 238 Hz, CutOff = 28Hz */ + LSM6DS0_GYRO_ODR_476Hz_CO_57Hz = 0xA2, /*!< Output Data Rate = 476 Hz, CutOff = 57Hz */ + LSM6DS0_GYRO_ODR_476Hz_CO_100Hz = 0xA3, /*!< Output Data Rate = 476 Hz, CutOff = 100Hz */ + LSM6DS0_GYRO_ODR_952Hz_CO_33Hz = 0xC0, /*!< Output Data Rate = 952 Hz, CutOff = 33Hz */ + LSM6DS0_GYRO_ODR_952Hz_CO_40Hz = 0xC1, /*!< Output Data Rate = 952 Hz, CutOff = 40Hz */ + LSM6DS0_GYRO_ODR_952Hz_CO_58Hz = 0xC2, /*!< Output Data Rate = 952 Hz, CutOff = 58Hz */ + LSM6DS0_GYRO_ODR_952Hz_CO_100Hz = 0xC3 /*!< Output Data Rate = 952 Hz, CutOff = 100Hz */ +}LSM6DS0_GYRO_ODR_t; + +/** + * @brief Gyroscope Full Scale + */ +typedef enum { + LSM6DS0_GYRO_FS_245DSP = 0x00, /*!< ±245 degrees per second */ + LSM6DS0_GYRO_FS_500DSP = 0x08, /*!< ±500 degrees per second */ + LSM6DS0_GYRO_FS_2000DSP = 0x18 /*!< ±2000 degrees per second */ +}LSM6DS0_GYRO_FS_t; + +/** + * @brief Gyroscope Output Selection + */ +typedef enum { + LSM6DS0_GYRO_OUT_SEL_BYPASS = 0x00, /*!< Output not filtered */ + LSM6DS0_GYRO_OUT_SEL_FILTERED = 0x01, /*!< Output filtered */ +}LSM6DS0_GYRO_OUT_SEL_t; + +/** + * @brief Gyroscope Interrupt Selection + */ +typedef enum { + LSM6DS0_GYRO_INT_SEL_BYPASS = 0x00, /*!< Interrupt generator signal not filtered */ + LSM6DS0_GYRO_INT_SEL_FILTERED = 0x08, /*!< Interrupt generator signal filtered */ +}LSM6DS0_GYRO_INT_SEL_t; + +/** + * @brief Gyroscope Low Power Mode + */ +typedef enum { + LSM6DS0_GYRO_LP_MODE_HIGH_PERFORMANCE = 0x00, /*!< High performance */ + LSM6DS0_GYRO_LP_MODE_LOW_POWER = 0x80, /*!< Low power */ +}LSM6DS0_GYRO_LP_MODE_t; + +/** + * @brief Gyroscope High Pass Filter Cutoff Selection + */ +typedef enum { + LSM6DS0_GYRO_HPCF_DISABLED = 0x00, /*!< HP filter disabled */ + LSM6DS0_GYRO_HPCF_0 = 0x40, /*!< Config 0 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_1 = 0x41, /*!< Config 1 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_2 = 0x42, /*!< Config 2 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_3 = 0x43, /*!< Config 3 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_4 = 0x44, /*!< Config 4 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_5 = 0x45, /*!< Config 5 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_6 = 0x46, /*!< Config 6 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_7 = 0x47, /*!< Config 7 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_8 = 0x48, /*!< Config 8 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_9 = 0x49, /*!< Config 9 refer to table 48 of DOcID025604 Rev 3 */ + LSM6DS0_GYRO_HPCF_10 = 0x4A /*!< Config 10 refer to table 48 of DOcID025604 Rev 3 */ +}LSM6DS0_GYRO_HPCF_t; + +/** + * @brief Gyroscope Axes Enabling + */ +typedef enum{ + LSM6DS0_GYRO_AE_DISABLED = 0x00, /*!< Axes all disabled */ + LSM6DS0_GYRO_AE_X = 0x08, /*!< Only X-axis enabled */ + LSM6DS0_GYRO_AE_Y = 0x10, /*!< Only Y-axis enabled */ + LSM6DS0_GYRO_AE_XY = 0x18, /*!< X & Y axes enabled */ + LSM6DS0_GYRO_AE_Z = 0x20, /*!< Only Z-axis enabled */ + LSM6DS0_GYRO_AE_XZ = 0x28, /*!< X & Z axes enabled */ + LSM6DS0_GYRO_AE_YZ = 0x30, /*!< Y & Z axes enabled */ + LSM6DS0_GYRO_AE_XYZ = 0x38 /*!< All axes enabled */ +}LSM6DS0_GYRO_AE_t; + +/** + * @brief Gyroscope Decimation Mode + */ +typedef enum { + LSM6DS0_GYRO_DEC_DISABLED = 0x00, /*!< NO decimation */ + LSM6DS0_GYRO_DEC_X2 = 0x40, /*!< Decimation update every 2 sample */ + LSM6DS0_GYRO_DEC_X4 = 0x80, /*!< Decimation update every 4 sample */ + LSM6DS0_GYRO_DEC_X8 = 0xC0 /*!< Decimation update every 8 sample */ +}LSM6DS0_GYRO_DEC_t; + +/** + * @brief Gyroscope Sleep Mode + */ +typedef enum { + LSM6DS0_GYRO_SLP_DISABLED = 0x00, /*!< Gyroscope sleep mode disabled */ + LSM6DS0_GYRO_SLP_ENABLED = 0x40 /*!< Gyroscope sleep mode enabled */ +}LSM6DS0_GYRO_SLP_t; +/** + * @brief Gyroscope configuration structure. + */ +typedef struct { + /** + * @brief LSM6DS0 Slave Address + */ + LSM6DS0_SAD_t slaveaddress; + /** + * @brief Gyroscope Output Data Rate + */ + LSM6DS0_GYRO_ODR_t outputdatarate; + /** + * @brief Gyroscope Full Scale + */ + LSM6DS0_GYRO_FS_t fullscale; + /** + * @brief Gyroscope Output Selection + */ + LSM6DS0_GYRO_OUT_SEL_t outputselect; + /** + * @brief Gyroscope Interrupt Selection + */ + LSM6DS0_GYRO_INT_SEL_t irqselect; + /** + * @brief Gyroscope Low Power Mode + */ + LSM6DS0_GYRO_LP_MODE_t lowpowermode; + /** + * @brief Gyroscope High Pass Filter Cutoff Selection + */ + LSM6DS0_GYRO_HPCF_t HPCfrequency; + /** + * @brief Gyroscope Axes Enabling + */ + LSM6DS0_GYRO_AE_t axesenabling; + /** + * @brief Gyroscope Decimation Mode + */ + LSM6DS0_GYRO_DEC_t decimation; + /** + * @brief LSM6DS0 Endianness + */ + LSM6DS0_END_t endianess; + /** + * @brief LSM6DS0 Block Data Update + */ + LSM6DS0_BDU_t blockdataupdate; +} LSM6DS0_GYRO_Config; +/** @} */ +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + uint8_t lsm6ds0ReadRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + msg_t* message); + void lsm6ds0WriteRegister(I2CDriver *i2cp, uint8_t sad, uint8_t sub, + uint8_t value, msg_t* message); +#ifdef __cplusplus +} +#endif + +#endif /* (ACCEL_USE_LSM6DS0) || (GYRO_USE_LSM6DS0) */ +#endif /* _LSM6DS0_H_ */ + +/** @} */ diff --git a/os/various/devices_lib/max7219.c b/os/various/devices_lib/max7219.c new file mode 100644 index 0000000..b15699e --- /dev/null +++ b/os/various/devices_lib/max7219.c @@ -0,0 +1,95 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use it. + */ + +/** + * @file max7219.c + * @brief MAX7219 display driver module code. + * + * @addtogroup max7219 + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "play.h" +#include "max7219.h" + +#if (PLAY_USE_MAX7219) || defined (__DOXYGEN__) +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Reads a generic register value. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] adr address number + * @param[in] data data value. + */ +void max7219WriteRegister(SPIDriver *spip, uint16_t adr, uint8_t data) { + + switch (adr) { + default: + return; + case MAX7219_AD_DIGIT_0: + case MAX7219_AD_DIGIT_1: + case MAX7219_AD_DIGIT_2: + case MAX7219_AD_DIGIT_3: + case MAX7219_AD_DIGIT_4: + case MAX7219_AD_DIGIT_5: + case MAX7219_AD_DIGIT_6: + case MAX7219_AD_DIGIT_7: + case MAX7219_AD_DECODE_MODE: + case MAX7219_AD_INTENSITY: + case MAX7219_AD_SCAN_LIMIT: + case MAX7219_AD_SHUTDOWN: + case MAX7219_AD_DISPLAY_TEST: + spiSelect(spip); + uint16_t txbuf = {adr | data}; + spiSend(spip, 1, &txbuf); + spiUnselect(spip); + } +} +#endif /* PLAY_USE_MAX7219 */ +/** @} */ diff --git a/os/various/devices_lib/max7219.h b/os/various/devices_lib/max7219.h new file mode 100644 index 0000000..80524be --- /dev/null +++ b/os/various/devices_lib/max7219.h @@ -0,0 +1,187 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file MAX7219.h + * @brief MAX7219 display driver module header. + * + * @{ + */ + +#ifndef _MAX7219_H_ +#define _MAX7219_H_ + +#if (PLAY_USE_MAX7219) || defined (__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name MAX7219 register names + * @{ + */ +/******************************************************************************/ +/* */ +/* MAX7219 display driver */ +/* */ +/******************************************************************************/ +/******************* Bit definition for SPI communication *******************/ +#define MAX7219_DI ((uint16_t)0x00FF) /*!< DI[7:0] Data input */ +#define MAX7219_DI_0 ((uint16_t)0x0001) /*!< bit 0 */ +#define MAX7219_DI_1 ((uint16_t)0x0002) /*!< bit 1 */ +#define MAX7219_DI_2 ((uint16_t)0x0004) /*!< bit 2 */ +#define MAX7219_DI_3 ((uint16_t)0x0008) /*!< bit 3 */ +#define MAX7219_DI_4 ((uint16_t)0x0010) /*!< bit 4 */ +#define MAX7219_DI_5 ((uint16_t)0x0020) /*!< bit 5 */ +#define MAX7219_DI_6 ((uint16_t)0x0040) /*!< bit 6 */ +#define MAX7219_DI_7 ((uint16_t)0x0080) /*!< bit 7 */ + +#define MAX7219_AD ((uint16_t)0x0F00) /*!< AD[11:8] Data input */ +#define MAX7219_AD_0 ((uint16_t)0x0100) /*!< bit 8 */ +#define MAX7219_AD_1 ((uint16_t)0x0200) /*!< bit 9 */ +#define MAX7219_AD_2 ((uint16_t)0x0400) /*!< bit 10 */ +#define MAX7219_AD_3 ((uint16_t)0x0800) /*!< bit 11 */ + +/****************** Bit definition for Registers Addresses *******************/ +#define MAX7219_AD_NOP ((uint16_t)0x0000) /*!< No operation */ +#define MAX7219_AD_DIGIT_0 ((uint16_t)0x0100) /*!< Digit 0 */ +#define MAX7219_AD_DIGIT_1 ((uint16_t)0x0200) /*!< Digit 1 */ +#define MAX7219_AD_DIGIT_2 ((uint16_t)0x0300) /*!< Digit 2 */ +#define MAX7219_AD_DIGIT_3 ((uint16_t)0x0400) /*!< Digit 3 */ +#define MAX7219_AD_DIGIT_4 ((uint16_t)0x0500) /*!< Digit 4 */ +#define MAX7219_AD_DIGIT_5 ((uint16_t)0x0600) /*!< Digit 5 */ +#define MAX7219_AD_DIGIT_6 ((uint16_t)0x0700) /*!< Digit 6 */ +#define MAX7219_AD_DIGIT_7 ((uint16_t)0x0800) /*!< Digit 7 */ +#define MAX7219_AD_DECODE_MODE ((uint16_t)0x0900) /*!< Decode mode */ +#define MAX7219_AD_INTENSITY ((uint16_t)0x0A00) /*!< Intensity */ +#define MAX7219_AD_SCAN_LIMIT ((uint16_t)0x0B00) /*!< Scan limit */ +#define MAX7219_AD_SHUTDOWN ((uint16_t)0x0C00) /*!< Shutdown */ +#define MAX7219_AD_DISPLAY_TEST ((uint16_t)0x0F00) /*!< Display test */ + +/*************** Bit definition for Registers Configuration *****************/ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !HAL_USE_SPI +#error "MAX7219 requires HAL_USE_SPI" +#endif +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name MAX7219 data structures and types + * @{ + * + */ + +/** + * @brief MAX7219 operation mode + */ +typedef enum { + MAX7219_OM_Shutdown = 0x00, /*!< Shutdown mode */ + MAX7219_OM_Normal = 0x01 /*!< Normal mode */ +} MAX7219_OM_t; + +/** + * @brief MAX7219 decoder mode + */ +typedef enum { + MAX7219_DM_No_decode = 0x00, /*!< No decode */ + MAX7219_DM_CodeB_0 = 0x01, /*!< Code B on Digit 0 */ + MAX7219_DM_CodeB_1 = 0x02, /*!< Code B on Digit 1 */ + MAX7219_DM_CodeB_2 = 0x04, /*!< Code B on Digit 2 */ + MAX7219_DM_CodeB_3 = 0x08, /*!< Code B on Digit 3 */ + MAX7219_DM_CodeB_4 = 0x10, /*!< Code B on Digit 4 */ + MAX7219_DM_CodeB_5 = 0x20, /*!< Code B on Digit 5 */ + MAX7219_DM_CodeB_6 = 0x40, /*!< Code B on Digit 6 */ + MAX7219_DM_CodeB_7 = 0x80 /*!< Code B on Digit 7 */ +} MAX7219_DM_t; + +/** + * @brief MAX7219 intensity mode + */ +typedef enum { + MAX7219_IM_1_32 = 0x00, /*!< 1/32 intensity */ + MAX7219_IM_3_32 = 0x01, /*!< 3/32 intensity */ + MAX7219_IM_5_32 = 0x02, /*!< 5/32 intensity */ + MAX7219_IM_7_32 = 0x03, /*!< 7/32 intensity */ + MAX7219_IM_9_32 = 0x04, /*!< 9/32 intensity */ + MAX7219_IM_11_32 = 0x05, /*!< 11/32 intensity */ + MAX7219_IM_13_32 = 0x06, /*!< 13/32 intensity */ + MAX7219_IM_15_32 = 0x07, /*!< 15/32 intensity */ + MAX7219_IM_17_32 = 0x08, /*!< 17/32 intensity */ + MAX7219_IM_19_32 = 0x09, /*!< 19/32 intensity */ + MAX7219_IM_21_32 = 0x0A, /*!< 21/32 intensity */ + MAX7219_IM_23_32 = 0x0B, /*!< 23/32 intensity */ + MAX7219_IM_25_32 = 0x0C, /*!< 25/32 intensity */ + MAX7219_IM_27_32 = 0x0D, /*!< 27/32 intensity */ + MAX7219_IM_29_32 = 0x0E, /*!< 29/32 intensity */ + MAX7219_IM_31_32 = 0x0F /*!< 31/32 intensity */ +} MAX7219_IM_t; + +/** + * @brief MAX7219 scan line mode + */ +typedef enum { + MAX7219_SL_0 = 0x00, /*!< Scanned digit 0 only */ + MAX7219_SL_1 = 0x01, /*!< Scanned digit 0 & 1 */ + MAX7219_SL_2 = 0x02, /*!< Scanned digit 0 - 2 */ + MAX7219_SL_3 = 0x03, /*!< Scanned digit 0 - 3 */ + MAX7219_SL_4 = 0x04, /*!< Scanned digit 0 - 4 */ + MAX7219_SL_5 = 0x05, /*!< Scanned digit 0 - 5 */ + MAX7219_SL_6 = 0x06, /*!< Scanned digit 0 - 6 */ + MAX7219_SL_7 = 0x07 /*!< Scanned digit 0 - 7 */ +} MAX7219_SL_t; +/** @} */ +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + void max7219WriteRegister(SPIDriver *spip, uint16_t adr, uint8_t data); +#ifdef __cplusplus +} +#endif +#endif /* PLAY_USE_MAX7219 */ +#endif /* _MAX7219_H_ */ + +/** @} */ + diff --git a/os/various/devices_lib/nrf24l01.c b/os/various/devices_lib/nrf24l01.c new file mode 100644 index 0000000..34d8bff --- /dev/null +++ b/os/various/devices_lib/nrf24l01.c @@ -0,0 +1,441 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use it. + */ + +/** + * @file nrf24l01.c + * @brief NRF24L01 interface module code. + * + * @addtogroup nrf24l01 + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "play.h" +#include "nrf24l01.h" + +#if (RF_USE_NRF24L01) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define ACTIVATE 0x73 +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Gets the status register value. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01GetStatus(SPIDriver *spip) { + uint8_t txbuf = NRF24L01_CMD_NOP; + uint8_t status; + spiSelect(spip); + spiExchange(spip, 1, &txbuf, &status); + spiUnselect(spip); + return status; +} + +/** + * @brief Reads a generic register value. + * + * @note Cannot be used to set addresses + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] reg register number + * @param[out] pvalue pointer to a data buffer + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01ReadRegister(SPIDriver *spip, uint8_t reg, + uint8_t* pvalue) { + uint8_t txbuf = (NRF24L01_CMD_READ | reg); + uint8_t status = 0xFF; + spiSelect(spip); + spiExchange(spip, 1, &txbuf, &status); + spiReceive(spip, 1, pvalue); + spiUnselect(spip); + return status; +} + +/** + * @brief Writes a generic register value. + * + * @note Cannot be used to set addresses + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] reg register number + * @param[in] value data value + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01WriteRegister(SPIDriver *spip, uint8_t reg, + uint8_t value) { + + uint8_t txbuf[2] = {(NRF24L01_CMD_WRITE | reg), value}; + uint8_t rxbuf[2] = {0xFF, 0xFF}; + switch (reg) { + + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "lg3d20WriteRegister(), #1", "reserved register"); + case NRF24L01_AD_OBSERVE_TX: + case NRF24L01_AD_CD: + case NRF24L01_AD_RX_ADDR_P0: + case NRF24L01_AD_RX_ADDR_P1: + case NRF24L01_AD_RX_ADDR_P2: + case NRF24L01_AD_RX_ADDR_P3: + case NRF24L01_AD_RX_ADDR_P4: + case NRF24L01_AD_RX_ADDR_P5: + case NRF24L01_AD_TX_ADDR: + /* Read only or addresses registers cannot be written, + * the command is ignored. + */ + return 0; + case NRF24L01_AD_CONFIG: + case NRF24L01_AD_EN_AA: + case NRF24L01_AD_EN_RXADDR: + case NRF24L01_AD_SETUP_AW: + case NRF24L01_AD_SETUP_RETR: + case NRF24L01_AD_RF_CH: + case NRF24L01_AD_RF_SETUP: + case NRF24L01_AD_STATUS: + case NRF24L01_AD_RX_PW_P0: + case NRF24L01_AD_RX_PW_P1: + case NRF24L01_AD_RX_PW_P2: + case NRF24L01_AD_RX_PW_P3: + case NRF24L01_AD_RX_PW_P4: + case NRF24L01_AD_RX_PW_P5: + case NRF24L01_AD_FIFO_STATUS: + case NRF24L01_AD_DYNPD: + case NRF24L01_AD_FEATURE: + spiSelect(spip); + spiExchange(spip, 2, txbuf, rxbuf); + spiUnselect(spip); + return rxbuf[0]; + } +} + + +/** + * @brief Writes an address. + * + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] reg register number + * @param[in] pvalue pointer to address value + * @param[in] addlen address len + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01WriteAddress(SPIDriver *spip, uint8_t reg, + uint8_t *pvalue, uint8_t addlen) { + + uint8_t txbuf[NRF24L01_MAX_ADD_LENGHT + 1]; + uint8_t rxbuf[NRF24L01_MAX_ADD_LENGHT + 1]; + unsigned i; + + if(addlen > NRF24L01_MAX_ADD_LENGHT) { + chDbgAssert(FALSE, "nrf24l01WriteAddress(), #1", "wrong address length"); + return 0; + } + txbuf[0] = (NRF24L01_CMD_WRITE | reg); + rxbuf[0] = 0xFF; + for(i = 1; i <= addlen; i++) { + txbuf[i] = *(pvalue + (i - 1)); + rxbuf[i] = 0xFF; + } + switch (reg) { + + default: + /* Reserved register must not be written, according to the datasheet + * this could permanently damage the device. + */ + chDbgAssert(FALSE, "nrf24l01WriteAddress(), #1", "reserved register"); + case NRF24L01_AD_OBSERVE_TX: + case NRF24L01_AD_CD: + case NRF24L01_AD_CONFIG: + case NRF24L01_AD_EN_AA: + case NRF24L01_AD_EN_RXADDR: + case NRF24L01_AD_SETUP_AW: + case NRF24L01_AD_SETUP_RETR: + case NRF24L01_AD_RF_CH: + case NRF24L01_AD_RF_SETUP: + case NRF24L01_AD_STATUS: + case NRF24L01_AD_RX_PW_P0: + case NRF24L01_AD_RX_PW_P1: + case NRF24L01_AD_RX_PW_P2: + case NRF24L01_AD_RX_PW_P3: + case NRF24L01_AD_RX_PW_P4: + case NRF24L01_AD_RX_PW_P5: + case NRF24L01_AD_FIFO_STATUS: + case NRF24L01_AD_DYNPD: + case NRF24L01_AD_FEATURE: + /* Not address registers cannot be written, the command is ignored.*/ + return 0; + case NRF24L01_AD_RX_ADDR_P0: + case NRF24L01_AD_RX_ADDR_P1: + case NRF24L01_AD_RX_ADDR_P2: + case NRF24L01_AD_RX_ADDR_P3: + case NRF24L01_AD_RX_ADDR_P4: + case NRF24L01_AD_RX_ADDR_P5: + case NRF24L01_AD_TX_ADDR: + spiSelect(spip); + spiExchange(spip, addlen + 1, txbuf, rxbuf); + spiUnselect(spip); + return rxbuf[0]; + } +} +/** + * @brief Reads RX payload from FIFO. + * + * @note Payload is deleted from FIFO after it is read. Used in RX mode. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] paylen payload length + * @param[in] rxbuf pointer to a buffer + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01GetRxPl(SPIDriver *spip, uint8_t paylen, + uint8_t* rxbuf) { + + uint8_t txbuf = NRF24L01_CMD_R_RX_PAYLOAD; + uint8_t status; + if(paylen > NRF24L01_MAX_PL_LENGHT) { + return 0; + } + spiSelect(spip); + spiExchange(spip, 1, &txbuf, &status); + spiReceive(spip, paylen, rxbuf); + spiUnselect(spip); + return status; +} + +/** + * @brief Writes TX payload on FIFO. + * + * @note Used in TX mode. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] paylen payload length + * @param[in] rxbuf pointer to a buffer + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01WriteTxPl(SPIDriver *spip, uint8_t paylen, + uint8_t* txbuf) { + + uint8_t cmd = NRF24L01_CMD_W_TX_PAYLOAD; + uint8_t status; + if(paylen > NRF24L01_MAX_PL_LENGHT) { + return 0; + } + spiSelect(spip); + spiExchange(spip, 1, &cmd, &status); + spiSend(spip, paylen, txbuf); + spiUnselect(spip); + return status; +} + +/** + * @brief Flush TX FIFO. + * + * @note Used in TX mode. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01FlushTx(SPIDriver *spip) { + + uint8_t txbuf = NRF24L01_CMD_FLUSH_TX; + uint8_t status; + spiSelect(spip); + spiExchange(spip, 1, &txbuf, &status); + spiUnselect(spip); + return status; +} + +/** + * @brief Flush RX FIFO. + * + * @note Used in RX mode. Should not be executed during transmission of + acknowledge, that is, acknowledge package will not be completed. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01FlushRx(SPIDriver *spip) { + + uint8_t txbuf = NRF24L01_CMD_FLUSH_RX; + uint8_t status; + spiSelect(spip); + spiExchange(spip, 1, &txbuf, &status); + spiUnselect(spip); + return status; +} + +#if NRF24L01_USE_FEATURE || defined(__DOXYGEN__) +/** + * @brief Activates the following features: + * R_RX_PL_WID -> (In order to enable DPL the EN_DPL bit in the + * FEATURE register must be set) + * W_ACK_PAYLOAD -> (In order to enable PL with ACK the EN_ACK_PAY + * bit in the FEATURE register must be set) + * W_TX_PAYLOAD_NOACK -> (In order to send a PL without ACK + * the EN_DYN_ACK it in the FEATURE register + * must be set) + * + * @note A new ACTIVATE command with the same data deactivates them again. + * This is executable in power down or stand by modes only. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01Activate(SPIDriver *spip) { + + uint8_t txbuf[2] = {NRF24L01_CMD_FLUSH_RX, ACTIVATE}; + uint8_t rxbuf[2]; + spiSelect(spip); + spiExchange(spip, 2, txbuf, rxbuf); + spiUnselect(spip); + return rxbuf[0]; +} + +/** + * @brief Reads RX payload lenght for the top R_RX_PAYLOAD + * in the RX FIFO when Dynamic Payload Length is activated. + * + * @note R_RX_PL_WID must be set and activated. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] ppaylen pointer to the payload length variable + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01ReadRxPlWid(SPIDriver *spip, uint8_t *ppaylen) { + + uint8_t txbuf[2] = {NRF24L01_CMD_R_RX_PL_WID, 0xFF}; + uint8_t rxbuf[2]; + spiSelect(spip); + spiExchange(spip, 2, txbuf, rxbuf); + spiUnselect(spip); + *ppaylen = rxbuf[1]; + return rxbuf[0]; +} + +/** + * @brief Writes TX payload associateted to ACK. + * + * @note Used in RX mode. Write Payload to be transmitted together with + * ACK packet on PIPE PPP. (PPP valid in the range from 000 to 101). + * @note EN_ACK_PAY must be set and activated. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] paylen payload length + * @param[in] rxbuf pointer to a buffer + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01WriteAckPl(SPIDriver *spip, uint8_t ppp, uint8_t paylen, + uint8_t* payload){ + + payload[0] = NRF24L01_CMD_W_ACK_PAYLOAD | NRF24L01_MAX_PPP; + uint8_t status; + if((paylen > NRF24L01_MAX_PL_LENGHT) || (ppp > NRF24L01_MAX_PPP)) { + return 0; + } + spiSelect(spip); + spiExchange(spip, 1, payload, &status); + spiSend(spip, paylen, payload); + spiUnselect(spip); + return status; +} + +/** + * @brief Writes next TX payload without ACK. + * + * @note Used in TX mode. + * @note EN_DYN_ACK must be set and activated. + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * @param[in] paylen payload length + * @param[in] rxbuf pointer to a buffer + * + * @return the status register value + */ +NRF24L01_status_t nrf24l01WriteTxPlNoAck(SPIDriver *spip, uint8_t paylen, + uint8_t* txbuf) { + + txbuf[0] = NRF24L01_CMD_W_TX_PAYLOAD_NOACK; + uint8_t status; + if(paylen > NRF24L01_MAX_PL_LENGHT) { + return 0; + } + spiSelect(spip); + spiExchange(spip, 1, txbuf, &status); + spiSend(spip, paylen, txbuf); + spiUnselect(spip); + return status; +} +#endif /* NRF24L01_USE_FEATURE */ +#endif /* RF_USE_NRF24L01 */ + +/** @} */ diff --git a/os/various/devices_lib/nrf24l01.h b/os/various/devices_lib/nrf24l01.h new file mode 100644 index 0000000..7112b9f --- /dev/null +++ b/os/various/devices_lib/nrf24l01.h @@ -0,0 +1,577 @@ +/* + Pretty LAYer for ChibiOS/RT - Copyright (C) 2014 Rocco Marco Guglielmi + + This file is part of PLAY for ChibiOS/RT. + + PLAY is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + PLAY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Special thanks to Giovanni Di Sirio for teachings, his moral support and + friendship. Note that some or every piece of this file could be part of + the ChibiOS project that is intellectual property of Giovanni Di Sirio. + Please refer to ChibiOS/RT license before use this file. + */ + +/** + * @file nrf24l01.h + * @brief NRF24L01 Radio frequency module interface module header. + * + * @{ + */ + +#ifndef _NRF24L01_H_ +#define _NRF24L01_H_ + +#include "playconf.h" + +#if (RF_USE_NRF24L01) || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define NRF24L01_MAX_ADD_LENGHT ((uint8_t) 5) +#define NRF24L01_MAX_PL_LENGHT ((uint8_t) 32) +#define NRF24L01_MAX_PPP ((uint8_t) 5) + +/** + * @brief Enables Advanced Features. + */ +#if !defined(NRF24L01_USE_FEATURE) || defined(__DOXYGEN__) +#define NRF24L01_USE_FEATURE TRUE +#endif + +/** + * @name NRF24L01 register names + * @{ + */ +/******************************************************************************/ +/* */ +/* NRF24L01 RF Transceiver */ +/* */ +/******************************************************************************/ +/****************** Bit definition for SPI communication ********************/ +#define NRF24L01_DI ((uint8_t)0xFF) /*!< DI[7:0] Data input */ +#define NRF24L01_DI_0 ((uint8_t)0x01) /*!< bit 0 */ +#define NRF24L01_DI_1 ((uint8_t)0x02) /*!< bit 1 */ +#define NRF24L01_DI_2 ((uint8_t)0x04) /*!< bit 2 */ +#define NRF24L01_DI_3 ((uint8_t)0x08) /*!< bit 3 */ +#define NRF24L01_DI_4 ((uint8_t)0x10) /*!< bit 4 */ +#define NRF24L01_DI_5 ((uint8_t)0x20) /*!< bit 5 */ +#define NRF24L01_DI_6 ((uint8_t)0x40) /*!< bit 6 */ +#define NRF24L01_DI_7 ((uint8_t)0x80) /*!< bit 7 */ + +#define NRF24L01_AD ((uint8_t)0x1F) /*!< AD[4:0] Address Data */ +#define NRF24L01_AD_0 ((uint8_t)0x01) /*!< bit 0 */ +#define NRF24L01_AD_1 ((uint8_t)0x02) /*!< bit 1 */ +#define NRF24L01_AD_2 ((uint8_t)0x04) /*!< bit 2 */ +#define NRF24L01_AD_3 ((uint8_t)0x08) /*!< bit 3 */ +#define NRF24L01_AD_4 ((uint8_t)0x10) /*!< bit 4 */ + +#define NRF24L01_CMD_READ ((uint8_t)0x00) /*!< Read command */ +#define NRF24L01_CMD_WRITE ((uint8_t)0x20) /*!< Write command */ +#define NRF24L01_CMD_R_RX_PAYLOAD ((uint8_t)0x61) /*!< Read RX-payload*/ +#define NRF24L01_CMD_W_TX_PAYLOAD ((uint8_t)0xA0) /*!< Write TX-payload */ +#define NRF24L01_CMD_FLUSH_TX ((uint8_t)0xE1) /*!< Flush TX FIFO */ +#define NRF24L01_CMD_FLUSH_RX ((uint8_t)0xE2) /*!< Flush RX FIFO */ +#define NRF24L01_CMD_REUSE_TX_PL ((uint8_t)0xE3) /*!< Used for a PTX device */ +#define NRF24L01_CMD_ACTIVATE ((uint8_t)0x50) /*!< Activate command */ +#define NRF24L01_CMD_R_RX_PL_WID ((uint8_t)0x60) /*!< Read RX-payload width */ +#define NRF24L01_CMD_W_ACK_PAYLOAD ((uint8_t)0xA8) /*!< Write Payload for ACK */ +#define NRF24L01_CMD_W_TX_PAYLOAD_NOACK ((uint8_t)0xB0) /*!< Disables AUTOACK*/ +#define NRF24L01_CMD_NOP ((uint8_t)0xFF) /*!< No Operation */ + +/****************** Bit definition for Registers Addresses *******************/ +#define NRF24L01_AD_CONFIG ((uint8_t)0x00) /*!< Configuration Register */ +#define NRF24L01_AD_EN_AA ((uint8_t)0x01) /*!< Enable ‘Auto Acknowledgment’ */ +#define NRF24L01_AD_EN_RXADDR ((uint8_t)0x02) /*!< Enabled RX Addresses */ +#define NRF24L01_AD_SETUP_AW ((uint8_t)0x03) /*!< Setup of Address Widths */ +#define NRF24L01_AD_SETUP_RETR ((uint8_t)0x04) /*!< Setup of Automatic Retransmission */ +#define NRF24L01_AD_RF_CH ((uint8_t)0x05) /*!< RF Channel */ +#define NRF24L01_AD_RF_SETUP ((uint8_t)0x06) /*!< RF Setup Register */ +#define NRF24L01_AD_STATUS ((uint8_t)0x07) /*!< Status Register */ +#define NRF24L01_AD_OBSERVE_TX ((uint8_t)0x08) /*!< Transmit observe register */ +#define NRF24L01_AD_CD ((uint8_t)0x09) /*!< CD */ +#define NRF24L01_AD_RX_ADDR_P0 ((uint8_t)0x0A) /*!< Receive address data pipe 0 */ +#define NRF24L01_AD_RX_ADDR_P1 ((uint8_t)0x0B) /*!< Receive address data pipe 1 */ +#define NRF24L01_AD_RX_ADDR_P2 ((uint8_t)0x0C) /*!< Receive address data pipe 2 */ +#define NRF24L01_AD_RX_ADDR_P3 ((uint8_t)0x0D) /*!< Receive address data pipe 3 */ +#define NRF24L01_AD_RX_ADDR_P4 ((uint8_t)0x0E) /*!< Receive address data pipe 4 */ +#define NRF24L01_AD_RX_ADDR_P5 ((uint8_t)0x0F) /*!< Receive address data pipe 5 */ +#define NRF24L01_AD_TX_ADDR ((uint8_t)0x10) /*!< Transmit address */ +#define NRF24L01_AD_RX_PW_P0 ((uint8_t)0x11) /*!< Number of bytes in RX payload in data pipe 0 */ +#define NRF24L01_AD_RX_PW_P1 ((uint8_t)0x12) /*!< Number of bytes in RX payload in data pipe 1 */ +#define NRF24L01_AD_RX_PW_P2 ((uint8_t)0x13) /*!< Number of bytes in RX payload in data pipe 2 */ +#define NRF24L01_AD_RX_PW_P3 ((uint8_t)0x14) /*!< Number of bytes in RX payload in data pipe 3 */ +#define NRF24L01_AD_RX_PW_P4 ((uint8_t)0x15) /*!< Number of bytes in RX payload in data pipe 4 */ +#define NRF24L01_AD_RX_PW_P5 ((uint8_t)0x16) /*!< Number of bytes in RX payload in data pipe 5 */ +#define NRF24L01_AD_FIFO_STATUS ((uint8_t)0x17) /*!< FIFO Status Register */ +#define NRF24L01_AD_DYNPD ((uint8_t)0x1C) /*!< Enable dynamic payload length */ +#define NRF24L01_AD_FEATURE ((uint8_t)0x1D) /*!< Feature Register */ + +/*************** Bit definition for Registers Configuration *****************/ +#define NRF24L01_DI_CONFIG ((uint8_t)0x7F) /*!< CONTROL REGISTER BIT MASK*/ +#define NRF24L01_DI_CONFIG_PRIM_RX ((uint8_t)0x01) /*!< RX/TX control - 1: PRX, 0: PTX */ +#define NRF24L01_DI_CONFIG_PWR_UP ((uint8_t)0x02) /*!< 1: POWER UP, 0:POWER DOWN */ +#define NRF24L01_DI_CONFIG_CRCO ((uint8_t)0x04) /*!< CRC encoding scheme - 1:two bytes, 0:one byte */ +#define NRF24L01_DI_CONFIG_EN_CRC ((uint8_t)0x08) /*!< Enable CRC. Forced high if one of the bits in the EN_AA is high */ +#define NRF24L01_DI_CONFIG_MASK_MAX_RT ((uint8_t)0x10) /*!< Mask interrupt caused by MAX_RT - 1: Interrupt disabled, 0: Interrupt reflected on IRQ pin */ +#define NRF24L01_DI_CONFIG_MASK_TX_DS ((uint8_t)0x20) /*!< Mask interrupt caused by TX_DS - 1: Interrupt disabled, 0: Interrupt reflected on IRQ pin */ +#define NRF24L01_DI_CONFIG_MASK_RX_DR ((uint8_t)0x40) /*!< Mask interrupt caused by RX_DR - 1: Interrupt disabled, 0: Interrupt reflected on IRQ pin */ + +#define NRF24L01_DI_EN_AA ((uint8_t)0x3F) /*!< ENABLE AUTO ACKNOLEDGMENT REGISTER BIT MASK */ +#define NRF24L01_DI_EN_AA_P0 ((uint8_t)0x01) /*!< Enable auto acknowledgement data pipe 0 */ +#define NRF24L01_DI_EN_AA_P1 ((uint8_t)0x02) /*!< Enable auto acknowledgement data pipe 1 */ +#define NRF24L01_DI_EN_AA_P2 ((uint8_t)0x04) /*!< Enable auto acknowledgement data pipe 2 */ +#define NRF24L01_DI_EN_AA_P3 ((uint8_t)0x08) /*!< Enable auto acknowledgement data pipe 3 */ +#define NRF24L01_DI_EN_AA_P4 ((uint8_t)0x10) /*!< Enable auto acknowledgement data pipe 4 */ +#define NRF24L01_DI_EN_AA_P5 ((uint8_t)0x20) /*!< Enable auto acknowledgement data pipe 5 */ + +#define NRF24L01_DI_EN_RXADDR ((uint8_t)0x3F) /*!< ENABLE RX ADDRESSES REGISTER BIT MASK */ +#define NRF24L01_DI_EN_RXADDR_P0 ((uint8_t)0x01) /*!< Enable data pipe 0 */ +#define NRF24L01_DI_EN_RXADDR_P1 ((uint8_t)0x02) /*!< Enable data pipe 1 */ +#define NRF24L01_DI_EN_RXADDR_P2 ((uint8_t)0x04) /*!< Enable data pipe 2 */ +#define NRF24L01_DI_EN_RXADDR_P3 ((uint8_t)0x08) /*!< Enable data pipe 3 */ +#define NRF24L01_DI_EN_RXADDR_P4 ((uint8_t)0x10) /*!< Enable data pipe 4 */ +#define NRF24L01_DI_EN_RXADDR_P5 ((uint8_t)0x20) /*!< Enable data pipe 5 */ + +#define NRF24L01_DI_SETUP_AW ((uint8_t)0x03) /*!< SETUP OF ADDRESSES WIDTHS REGISTER BIT MASK */ +#define NRF24L01_DI_SETUP_AW_0 ((uint8_t)0x01) /*!< Addressed widths bit 0 */ +#define NRF24L01_DI_SETUP_AW_1 ((uint8_t)0x02) /*!< Addressed widths bit 1 */ + +#define NRF24L01_DI_SETUP_RETR ((uint8_t)0xFF) /*!< SETUP OF AUTOMATIC RETRANSMISSION REGISTER BIT MASK */ +#define NRF24L01_DI_SETUP_RETR_ARC_0 ((uint8_t)0x01) /*!< Auto Retransmit Count bit 0 */ +#define NRF24L01_DI_SETUP_RETR_ARC_1 ((uint8_t)0x02) /*!< Auto Retransmit Count bit 1 */ +#define NRF24L01_DI_SETUP_RETR_ARC_2 ((uint8_t)0x04) /*!< Auto Retransmit Count bit 2 */ +#define NRF24L01_DI_SETUP_RETR_ARC_3 ((uint8_t)0x08) /*!< Auto Retransmit Count bit 3 */ +#define NRF24L01_DI_SETUP_RETR_ARD_0 ((uint8_t)0x10) /*!< Auto Retransmit Delay bit 0 */ +#define NRF24L01_DI_SETUP_RETR_ARD_1 ((uint8_t)0x20) /*!< Auto Retransmit Delay bit 1 */ +#define NRF24L01_DI_SETUP_RETR_ARD_2 ((uint8_t)0x40) /*!< Auto Retransmit Delay bit 2 */ +#define NRF24L01_DI_SETUP_RETR_ARD_3 ((uint8_t)0x80) /*!< Auto Retransmit Delay bit 3 */ + + +#define NRF24L01_DI_RF_CH ((uint8_t)0x7F) /*!< RF CHANNEL REGISTER BIT MASK */ +#define NRF24L01_DI_RF_CH_0 ((uint8_t)0x01) /*!< RF channel bit 0 */ +#define NRF24L01_DI_RF_CH_1 ((uint8_t)0x02) /*!< RF channel bit 1 */ +#define NRF24L01_DI_RF_CH_2 ((uint8_t)0x04) /*!< RF channel bit 2 */ +#define NRF24L01_DI_RF_CH_3 ((uint8_t)0x08) /*!< RF channel bit 3 */ +#define NRF24L01_DI_RF_CH_4 ((uint8_t)0x10) /*!< RF channel bit 4 */ +#define NRF24L01_DI_RF_CH_5 ((uint8_t)0x20) /*!< RF channel bit 5 */ +#define NRF24L01_DI_RF_CH_6 ((uint8_t)0x40) /*!< RF channel bit 6 */ + + +#define NRF24L01_DI_RF_SETUP ((uint8_t)0x1F) /*!< RF SETUP REGISTER BIT MASK */ +#define NRF24L01_DI_RF_SETUP_LNA_HCURR ((uint8_t)0x01) /*!< Setup LNA gain */ +#define NRF24L01_DI_RF_SETUP_RF_PWR_0 ((uint8_t)0x02) /*!< RF output power bit 0 */ +#define NRF24L01_DI_RF_SETUP_RF_PWR_1 ((uint8_t)0x04) /*!< RF output power bit 1 */ +#define NRF24L01_DI_RF_SETUP_RF_DR ((uint8_t)0x08) /*!< Air Data rate - 0: 1Mbps, 1: 2Mbps */ +#define NRF24L01_DI_RF_SETUP_PLL_LOCK ((uint8_t)0x10) /*!< Force PLL lock signal */ + +#define NRF24L01_DI_STATUS ((uint8_t)0x7F) /*!< STATUS REGISTER BIT MASK */ +#define NRF24L01_DI_STATUS_TX_FULL ((uint8_t)0x01) /*!< TX FIFO full flag - 0: Available locations, 1: Full */ +#define NRF24L01_DI_STATUS_RX_P_NO_0 ((uint8_t)0x02) /*!< RX payload number bit 0 */ +#define NRF24L01_DI_STATUS_RX_P_NO_1 ((uint8_t)0x04) /*!< RX payload number bit 1 */ +#define NRF24L01_DI_STATUS_RX_P_NO_2 ((uint8_t)0x08) /*!< RX payload number bit 2 */ +#define NRF24L01_DI_STATUS_MAX_RT ((uint8_t)0x10) /*!< Maximum number of TX retransmits interrupt */ +#define NRF24L01_DI_STATUS_TX_DS ((uint8_t)0x20) /*!< Data Sent TX FIFO interrupt */ +#define NRF24L01_DI_STATUS_RX_DR ((uint8_t)0x40) /*!< Data Ready RX FIFO interrupt */ + +#define NRF24L01_DI_OBSERVE_TX ((uint8_t)0xFF) /*!< TRANSMIT OBSERVE REGISTER BIT MASK */ +#define NRF24L01_DI_ARC_CNT_0 ((uint8_t)0x01) /*!< Count retransmitted packets bit 0 */ +#define NRF24L01_DI_ARC_CNT_1 ((uint8_t)0x02) /*!< Count retransmitted packets bit 1 */ +#define NRF24L01_DI_ARC_CNT_2 ((uint8_t)0x04) /*!< Count retransmitted packets bit 2 */ +#define NRF24L01_DI_ARC_CNT_3 ((uint8_t)0x08) /*!< Count retransmitted packets bit 3 */ +#define NRF24L01_DI_PLOS_CNT_0 ((uint8_t)0x10) /*!< Count lost packets bit 0 */ +#define NRF24L01_DI_PLOS_CNT_1 ((uint8_t)0x20) /*!< Count lost packets bit 1 */ +#define NRF24L01_DI_PLOS_CNT_2 ((uint8_t)0x40) /*!< Count lost packets bit 2 */ +#define NRF24L01_DI_PLOS_CNT_3 ((uint8_t)0x80) /*!< Count lost packets bit 3 */ + +#define NRF24L01_DI_CD ((uint8_t)0x01) /*!< REGISTER BIT MASK */ +#define NRF24L01_DI_CARRIER_DETECT ((uint8_t)0x01) /*!< Carrier detect */ + +#define NRF24L01_DI_RX_PW_P0 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 0 REGISTER BIT MASK */ +#define NRF24L01_DI_RX_PW_P0_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define NRF24L01_DI_RX_PW_P0_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define NRF24L01_DI_RX_PW_P0_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define NRF24L01_DI_RX_PW_P0_3 ((uint8_t)0x08) /*!< Bit 3 */ +#define NRF24L01_DI_RX_PW_P0_4 ((uint8_t)0x10) /*!< Bit 4 */ +#define NRF24L01_DI_RX_PW_P0_5 ((uint8_t)0x20) /*!< Bit 5 */ + +#define NRF24L01_DI_RX_PW_P1 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 1 REGISTER BIT MASK */ +#define NRF24L01_DI_RX_PW_P1_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define NRF24L01_DI_RX_PW_P1_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define NRF24L01_DI_RX_PW_P1_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define NRF24L01_DI_RX_PW_P1_3 ((uint8_t)0x08) /*!< Bit 3 */ +#define NRF24L01_DI_RX_PW_P1_4 ((uint8_t)0x10) /*!< Bit 4 */ +#define NRF24L01_DI_RX_PW_P1_5 ((uint8_t)0x20) /*!< Bit 5 */ + +#define NRF24L01_DI_RX_PW_P2 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 2 REGISTER BIT MASK */ +#define NRF24L01_DI_RX_PW_P2_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define NRF24L01_DI_RX_PW_P2_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define NRF24L01_DI_RX_PW_P2_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define NRF24L01_DI_RX_PW_P2_3 ((uint8_t)0x08) /*!< Bit 3 */ +#define NRF24L01_DI_RX_PW_P2_4 ((uint8_t)0x10) /*!< Bit 4 */ +#define NRF24L01_DI_RX_PW_P2_5 ((uint8_t)0x20) /*!< Bit 5 */ + +#define NRF24L01_DI_RX_PW_P3 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 3 REGISTER BIT MASK */ +#define NRF24L01_DI_RX_PW_P3_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define NRF24L01_DI_RX_PW_P3_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define NRF24L01_DI_RX_PW_P3_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define NRF24L01_DI_RX_PW_P3_3 ((uint8_t)0x08) /*!< Bit 3 */ +#define NRF24L01_DI_RX_PW_P3_4 ((uint8_t)0x10) /*!< Bit 4 */ +#define NRF24L01_DI_RX_PW_P3_5 ((uint8_t)0x20) /*!< Bit 5 */ + +#define NRF24L01_DI_RX_PW_P4 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 4 REGISTER BIT MASK */ +#define NRF24L01_DI_RX_PW_P4_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define NRF24L01_DI_RX_PW_P4_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define NRF24L01_DI_RX_PW_P4_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define NRF24L01_DI_RX_PW_P4_3 ((uint8_t)0x08) /*!< Bit 3 */ +#define NRF24L01_DI_RX_PW_P4_4 ((uint8_t)0x10) /*!< Bit 4 */ +#define NRF24L01_DI_RX_PW_P4_5 ((uint8_t)0x20) /*!< Bit 5 */ + +#define NRF24L01_DI_RX_PW_P5 ((uint8_t)0x3F) /*!< RX PAYLOAD WIDTH FOR PIPE 5 REGISTER BIT MASK */ +#define NRF24L01_DI_RX_PW_P5_0 ((uint8_t)0x01) /*!< Bit 0 */ +#define NRF24L01_DI_RX_PW_P5_1 ((uint8_t)0x02) /*!< Bit 1 */ +#define NRF24L01_DI_RX_PW_P5_2 ((uint8_t)0x04) /*!< Bit 2 */ +#define NRF24L01_DI_RX_PW_P5_3 ((uint8_t)0x08) /*!< Bit 3 */ +#define NRF24L01_DI_RX_PW_P5_4 ((uint8_t)0x10) /*!< Bit 4 */ +#define NRF24L01_DI_RX_PW_P5_5 ((uint8_t)0x20) /*!< Bit 5 */ + +#define NRF24L01_DI_FIFO_STATUS ((uint8_t)0x73) /*!< FIFO STATUS REGISTER BIT MASK*/ +#define NRF24L01_DI_FIFO_STATUS_RX_EMPTY ((uint8_t)0x01) /*!< RX FIFO empty flag - 0:Data in RX FIFO, 1:RX FIFO empty */ +#define NRF24L01_DI_FIFO_STATUS_RX_FULL ((uint8_t)0x02) /*!< RX FIFO full flag - 0:Available locations in RX FIFO, 1:RX FIFO empty */ +#define NRF24L01_DI_FIFO_STATUS_TX_EMPTY ((uint8_t)0x10) /*!< TX FIFO empty flag - 0:Data in TX FIFO, 1:TX FIFO empty */ +#define NRF24L01_DI_FIFO_STATUS_TX_FULL ((uint8_t)0x20) /*!< TX FIFO full flag - 0:Available locations in TX FIFO, 1:TX FIFO empty */ +#define NRF24L01_DI_FIFO_STATUS_TX_REUSE ((uint8_t)0x40) /*!< Reuse last transmitted data packet if set high */ + +#define NRF24L01_DI_DYNPD ((uint8_t)0x3F) /*!< ENABLE DYNAMIC PAYLOAD LENGHT REGISTER BIT MASK */ +#define NRF24L01_DI_DYNPD_DPL_P0 ((uint8_t)0x01) /*!< Enable dyn. payload length data pipe 0 */ +#define NRF24L01_DI_DYNPD_DPL_P1 ((uint8_t)0x02) /*!< Enable dyn. payload length data pipe 1 */ +#define NRF24L01_DI_DYNPD_DPL_P2 ((uint8_t)0x04) /*!< Enable dyn. payload length data pipe 2 */ +#define NRF24L01_DI_DYNPD_DPL_P3 ((uint8_t)0x08) /*!< Enable dyn. payload length data pipe 3 */ +#define NRF24L01_DI_DYNPD_DPL_P4 ((uint8_t)0x10) /*!< Enable dyn. payload length data pipe 4 */ +#define NRF24L01_DI_DYNPD_DPL_P5 ((uint8_t)0x20) /*!< Enable dyn. payload length data pipe 5 */ + +#define NRF24L01_DI_FEATURE ((uint8_t)0x07) /*!< FEATURE REGISTER REGISTER BIT MASK */ +#define NRF24L01_DI_FEATURE_EN_DYN_ACK ((uint8_t)0x01) /*!< Enables the W_TX_PAYLOAD_NOACK command */ +#define NRF24L01_DI_FEATURE_EN_ACK_PAY ((uint8_t)0x02) /*!< Enables Payload with ACK */ +#define NRF24L01_DI_FEATURE_EN_DPL ((uint8_t)0x04) /*!< Enables Dynamic Payload Length */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !(HAL_USE_SPI) +#error "RF_NRF24L01 requires HAL_USE_SPI." +#endif + +#if !(HAL_USE_EXT) +#error "RF_NRF24L01 requires HAL_USE_EXT." +#endif +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name RF Transceiver data structures and types + * @{ + */ + +/** + * @brief RF Transceiver RX/TX Address field width + */ +typedef enum { + + NRF24L01_AW_3_bytes = 0x01, /*!< 3 bytes width */ + NRF24L01_AW_4_bytes = 0x02, /*!< 4 bytes width */ + NRF24L01_AW_5_bytes = 0x03 /*!< 5 bytes width */ +} NRF24L01_AW_t; + +/** + * @brief RF Transceiver Auto Retransmit Delay + */ +typedef enum { + + NRF24L01_ARD_250us = 0x00, /*!< Wait 250us */ + NRF24L01_ARD_500us = 0x10, /*!< Wait 500us */ + NRF24L01_ARD_750us = 0x20, /*!< Wait 750us */ + NRF24L01_ARD_1000us = 0x30, /*!< Wait 1000us */ + NRF24L01_ARD_1250us = 0x40, /*!< Wait 1250us */ + NRF24L01_ARD_1500us = 0x50, /*!< Wait 1500us */ + NRF24L01_ARD_1750us = 0x60, /*!< Wait 1750us */ + NRF24L01_ARD_2000us = 0x70, /*!< Wait 2000us */ + NRF24L01_ARD_2250us = 0x80, /*!< Wait 2250us */ + NRF24L01_ARD_2500us = 0x90, /*!< Wait 2500us */ + NRF24L01_ARD_2750us = 0xA0, /*!< Wait 2750us */ + NRF24L01_ARD_3000us = 0xB0, /*!< Wait 3000us */ + NRF24L01_ARD_3250us = 0xC0, /*!< Wait 3250us */ + NRF24L01_ARD_3500us = 0xD0, /*!< Wait 3500us */ + NRF24L01_ARD_3750us = 0xE0, /*!< Wait 3750us */ + NRF24L01_ARD_4000us = 0xF0 /*!< Wait 4000us */ +} NRF24L01_ARD_t; + +/** + * @brief RF Transceiver Auto Retransmit Count + */ +typedef enum { + + NRF24L01_ARC_disabled = 0x00, /*!< Re-Transmit disabled */ + NRF24L01_ARC_1_time = 0x01, /*!< Up to 1 Re-Transmit on fail of AA */ + NRF24L01_ARC_2_times = 0x02, /*!< Up to 2 Re-Transmit on fail of AA */ + NRF24L01_ARC_3_times = 0x03, /*!< Up to 3 Re-Transmit on fail of AA */ + NRF24L01_ARC_4_times = 0x04, /*!< Up to 4 Re-Transmit on fail of AA */ + NRF24L01_ARC_5_times = 0x05, /*!< Up to 5 Re-Transmit on fail of AAs */ + NRF24L01_ARC_6_times = 0x06, /*!< Up to 6 Re-Transmit on fail of AA */ + NRF24L01_ARC_7_times = 0x07, /*!< Up to 7 Re-Transmit on fail of AA */ + NRF24L01_ARC_8_times = 0x08, /*!< Up to 8 Re-Transmit on fail of AA */ + NRF24L01_ARC_9_times = 0x09, /*!< Up to 9 Re-Transmit on fail of AA */ + NRF24L01_ARC_10_times = 0x0A, /*!< Up to 10 Re-Transmit on fail of AA */ + NRF24L01_ARC_11_times = 0x0B, /*!< Up to 11 Re-Transmit on fail of AA */ + NRF24L01_ARC_12_times = 0x0C, /*!< Up to 12 Re-Transmit on fail of AA */ + NRF24L01_ARC_13_times = 0x0D, /*!< Up to 13 Re-Transmit on fail of AA */ + NRF24L01_ARC_14_times = 0x0E, /*!< Up to 14 Re-Transmit on fail of AA */ + NRF24L01_ARC_15_times = 0x0F /*!< Up to 15 Re-Transmit on fail of AA */ +} NRF24L01_ARC_t; + + +/** + * @brief RF Transceiver configuration typedef. + * + * @detail This will select frequency channel beetween 2,4 GHz and 2,525 GHz + * @detail according to formula 2,4GHz + RF_CH[MHz]. This value must be included + * @detail between 0 and 125. + */ +typedef uint8_t NRF24L01_RF_CH_t; + +/** + * @brief RF Transceiver Air Data Rate + */ +typedef enum { + + NRF24L01_ADR_1Mbps = 0x00, /*!< Air data rate 1 Mbps */ + NRF24L01_ADR_2Mbps = 0x08 /*!< Air data rate 2 Mbps */ +} NRF24L01_ADR_t; + +/** + * @brief RF Transceiver Output Power + */ +typedef enum { + + NRF24L01_PWR_0dBm = 0x06, /*!< RF output power 0 dBm */ + NRF24L01_PWR_neg6dBm = 0x04, /*!< RF output power -6 dBm */ + NRF24L01_PWR_neg12dBm = 0x02, /*!< RF output power -12 dBm */ + NRF24L01_PWR_neg18dBm = 0x00 /*!< RF output power -18 dBm */ +} NRF24L01_PWR_t; + +/** + * @brief RF Transceiver Low Noise Amplifier + * + * @details Reduce current consumption in RX mode with 0.8 mA at cost of 1.5dB + * reduction in receiver sensitivity. + */ +typedef enum { + NRF24L01_LNA_enabled = 0x01, /*!< LNA_CURR enabled */ + NRF24L01_LNA_disabled = 0x00 /*!< LNA_CURR disabled */ +} NRF24L01_LNA_t; + +/** + * @brief RF Transceiver Backward Compatibility + * + * @details This type specifies if trasmission must be compatible to receive + * from an nRF2401/nRF2402/nRF24E1/nRF24E. + */ +typedef bool_t NRF24L01_bckwrdcmp_t; + +#if NRF24L01_USE_FEATURE || defined(__doxigen__) +/** + * @brief RF Transceiver Dynamic Payload enabler + * + * @details Enables Dynamic Payload Length + */ +typedef enum { + NRF24L01_DPL_enabled = 0x04, /*!< EN_DPL enabled */ + NRF24L01_DPL_disabled = 0x00 /*!< EN_DPL disabled */ +} NRF24L01_DPL_t; + +/** + * @brief RF Transceiver Dynamic Acknowledge with Payload enabler + * + * @details Enables Payload with ACK + */ +typedef enum { + NRF24L01_ACK_PAY_enabled = 0x02, /*!< EN_ACK_PAY enabled */ + NRF24L01_ACK_PAY_disabled = 0x00 /*!< EN_ACK_PAY disabled */ +} NRF24L01_ACK_PAY_t; + +/** + * @brief RF Transceiver Dynamic Acknowledge enabler + * + * @details Enables the W_TX_PAYLOAD_NOACK command + */ +typedef enum { + NRF24L01_DYN_ACK_enabled = 0x01, /*!< EN_DYN_ACK enabled */ + NRF24L01_DYN_ACK_disabled = 0x00 /*!< EN_DYN_ACK disabled */ +} NRF24L01_DYN_ACK_t; +#endif /* NRF24L01_USE_FEATURE */ + +/** + * @brief RF Transceiver configuration structure. + */ +typedef struct { + + /** + * @brief The chip enable line port. + */ + ioportid_t ceport; + /** + * @brief The chip enable line pad number. + */ + uint16_t cepad; + /** + * @brief The interrupt line port. + */ + ioportid_t irqport; + /** + * @brief The interrupt line pad number. + */ + uint16_t irqpad; + /** + * @brief Pointer to the SPI driver associated to this RF. + */ + SPIDriver *spip; + /** + * @brief Pointer to the SPI configuration . + */ + const SPIConfig *spicfg; + /** + * @brief Pointer to the EXT driver associated to this RF. + */ + EXTDriver *extp; + /** + * @brief EXT configuration. + */ + EXTConfig *extcfg; + /** + * @brief RF Transceiver auto retransmit count. + */ + NRF24L01_ARC_t auto_retr_count; + /** + * @brief RF Transceiver auto retransmit delay. + */ + NRF24L01_ARD_t auto_retr_delay; + /** + * @brief RF Transceiver address width. + */ + NRF24L01_AW_t address_width; + /** + * @brief RF Transceiver channel frequency. + */ + NRF24L01_RF_CH_t channel_freq; + /** + * @brief RF Transceiver air data rate. + */ + NRF24L01_ADR_t data_rate; + /** + * @brief RF Transceiver output power. + */ + NRF24L01_PWR_t out_pwr; + /** + * @brief RF Transceiver Low Noise Amplifier + */ + NRF24L01_LNA_t lna; +#if NRF24L01_USE_FEATURE || defined(__doxigen__) + /** + * @brief RF Transceiver Dynamic Payload enabler + */ + NRF24L01_DPL_t en_dpl; + + /** + * @brief RF Transceiver Dynamic Acknowledge with Payload enabler + */ + NRF24L01_ACK_PAY_t en_ack_pay; + + /** + * @brief RF Transceiver Dynamic Acknowledge enabler + */ + NRF24L01_DYN_ACK_t en_dyn_ack; +#endif /* NRF24L01_USE_FEATURE */ +} NRF24L01_Config; + +/** + * @brief RF Transceiver status register value. + */ +typedef uint8_t NRF24L01_status_t; +/** @} */ +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/** + * @brief Flushes FIFOs and resets all Status flags. + * + * @pre The SPI interface must be initialized and the driver started. + * + * @param[in] spip pointer to the SPI interface + * + * @return the status register value + */ +#define nrf24l01Reset(spip) { \ + \ + nrf24l01WriteRegister(spip, NRF24L01_AD_STATUS, \ + NRF24L01_DI_STATUS_MAX_RT | \ + NRF24L01_DI_STATUS_RX_DR | \ + NRF24L01_DI_STATUS_TX_DS); \ +} + +#ifdef __cplusplus +extern "C" { +#endif +NRF24L01_status_t nrf24l01GetStatus(SPIDriver *spip); +NRF24L01_status_t nrf24l01ReadRegister(SPIDriver *spip, uint8_t reg, + uint8_t* pvalue); +NRF24L01_status_t nrf24l01WriteRegister(SPIDriver *spip, uint8_t reg, + uint8_t value); +NRF24L01_status_t nrf24l01WriteAddress(SPIDriver *spip, uint8_t reg, + uint8_t *pvalue, uint8_t addlen); +NRF24L01_status_t nrf24l01GetRxPl(SPIDriver *spip, uint8_t paylen, + uint8_t* rxbuf); +NRF24L01_status_t nrf24l01WriteTxPl(SPIDriver *spip, uint8_t paylen, + uint8_t* txbuf); +NRF24L01_status_t nrf24l01FlushTx(SPIDriver *spip); +NRF24L01_status_t nrf24l01FlushRx(SPIDriver *spip); +#if NRF24L01_USE_FEATURE || defined(__DOXYGEN__) +NRF24L01_status_t nrf24l01Activate(SPIDriver *spip); +NRF24L01_status_t nrf24l01ReadRxPlWid(SPIDriver *spip, uint8_t* ppaylen); +NRF24L01_status_t nrf24l01WriteAckPl(SPIDriver *spip, uint8_t ppp, uint8_t paylen, + uint8_t* payload); +NRF24L01_status_t nrf24l01WriteTxPlNoAck(SPIDriver *spip, uint8_t paylen, + uint8_t* txbuf); +#endif /* NRF24L01_USE_FEATURE */ +#ifdef __cplusplus +} +#endif + +#endif /* RF_USE_NRF24L01 */ +#endif /* _NRF24L01_H_ */ + +/** @} */ -- cgit v1.2.3