contiki/platform/mb851/dev/mems.c
Adam Dunkels a5046e83c7 Cleanup and refactoring of the STM32w port
This is a general cleanup of things like code style issues and code structure of the STM32w port to make it more like the rest of Contiki is structured.
2013-03-18 13:31:26 +01:00

349 lines
12 KiB
C

/**
* \addtogroup mb851-platform
*
* @{
*/
/******************** (C) COPYRIGHT 2009 STMicroelectronics ********************
* File Name : hal_led.c
* Author : MCD Application Team
* Version : V1.0
* Date : September 2009
* Description : Driver for leds management on STM32W108 MB851 board
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
#include PLATFORM_HEADER
#include "mems.h"
#include "timer.h"
/*--------------------------------------------------------------------------*/
#define TIMEOUT 20000
#define SUCCESS 1
#define FAIL 0
#define SEND_BYTE(data) do { SC2_DATA=(data); SC2_TWICTRL1 |= SC_TWISEND; \
} while(0)
#define WAIT_CMD_FIN() { \
struct timer t; \
timer_set(&t, CLOCK_SECOND/100); \
while((SC2_TWISTAT&SC_TWICMDFIN)!=SC_TWICMDFIN){ \
if(timer_expired(&t)){ \
return FAIL; \
} \
} \
}
#define WAIT_TX_FIN() { \
struct timer t; \
timer_set(&t, CLOCK_SECOND/100); \
while((SC2_TWISTAT&SC_TWITXFIN)!=SC_TWITXFIN){ \
if(timer_expired(&t)){ \
return FAIL; \
} \
} \
}
#define WAIT_RX_FIN() { \
struct timer t; \
timer_set(&t, CLOCK_SECOND/100); \
while((SC2_TWISTAT&SC_TWIRXFIN)!=SC_TWIRXFIN){ \
if(timer_expired(&t)){ \
return FAIL; \
} \
} \
}
/*--------------------------------------------------------------------------*/
static boolean fullscale_state;
static uint8_t i2c_mems_init(void);
static uint8_t i2c_send_frame(uint8_t address, uint8_t *p_buf, uint8_t len);
uint8_t i2c_write_reg(uint8_t slave_addr, uint8_t reg_addr,
uint8_t reg_value);
/* static uint8_t i2c_mems_read (mems_data_t *mems_data); */
/*--------------------------------------------------------------------------*/
/**
* \brief Init MEMS
* \return None
*/
uint8_t
mems_init(void)
{
uint8_t ret = 0;
/* GPIO assignments */
/* PA1: SC2SDA (Serial Data) */
/* PA2: SC2SCL (Serial Clock) */
/* -----SC2 I2C Master GPIO configuration */
TIM2_CCER &= 0xFFFFEEEE;
SC2_MODE = SC2_MODE_I2C;
GPIO_PACFGL &= 0xFFFFF00F;
GPIO_PACFGL |= 0x00000DD0;
SC2_RATELIN = 14; /* generates standard 100kbps or 400kbps */
SC2_RATEEXP = 1; /* 3 yields 100kbps; 1 yields 400kbps */
SC2_TWICTRL1 = 0; /* start from a clean state */
SC2_TWICTRL2 = 0; /* start from a clean state */
ret = i2c_mems_init();
fullscale_state = MEMS_LOW_RANGE;
/* Add later if really needed */
#ifdef ST_DBG
if(!ret)
I2C_DeInit(MEMS_I2C);
#endif
return ret;
}
/*--------------------------------------------------------------------------*/
/**
* \brief Returns the 3 mems acceleration values related to x,y,z axes
* \param mems_data pointer to mems_data_t that will be filled with the values
* \return None
*/
#if 0
uint8_t mems_get_value(mems_data_t *mems_data)
{
uint8_t i;
i = i2c_mems_read(mems_data);
return i;
}
#endif
/*--------------------------------------------------------------------------*/
/**
* \brief Send I2C frame
* \param address destination device address
* \param p_buf pointer to data buffer
* \param len length of data
* \retval 0 frame has not been successfully sent
* \retval 1 frame has been successfully sent
*/
static uint8_t
i2c_send_frame(uint8_t address, uint8_t *p_buf, uint8_t len)
{
uint8_t i, data;
SC2_TWICTRL1 |= SC_TWISTART; /* send start */
WAIT_CMD_FIN();
SEND_BYTE(address); /* send the address low byte */
WAIT_TX_FIN();
for(i = 0; i < len; i++) {
halInternalResetWatchDog();
data = *(p_buf + i);
SEND_BYTE(data);
WAIT_TX_FIN();
}
SC2_TWICTRL1 |= SC_TWISTOP;
WAIT_CMD_FIN();
return SUCCESS;
}
/*--------------------------------------------------------------------------*/
/**
* \brief Receive I2C frame
* \param address slave device address
* \param p_buf pointer to data buffer
* \param len length of data
* \retval 0 frame has not been successfully received
* \retval 1 frame has been successfully received
*/
static uint8_t
i2c_receive_frame(uint8_t slave_addr, uint8_t reg_addr, uint8_t *p_buf,
uint8_t len)
{
uint8_t i, addr = reg_addr;
if(len > 1) {
addr += REPETIR;
}
SC2_TWICTRL1 |= SC_TWISTART; /* send start */
WAIT_CMD_FIN();
SEND_BYTE(slave_addr | 0x00); /* send the address low byte */
WAIT_TX_FIN();
SEND_BYTE(addr);
WAIT_TX_FIN();
SC2_TWICTRL1 |= SC_TWISTART; /* send start */
WAIT_CMD_FIN();
SEND_BYTE(slave_addr | 0x01); /* send the address low byte */
WAIT_TX_FIN();
for(i = 0; i < len; i++) {
halInternalResetWatchDog();
if(i < (len - 1)) {
SC2_TWICTRL2 |= SC_TWIACK; /* ack on receipt of data */
} else {
SC2_TWICTRL2 &= ~SC_TWIACK; /* don't ack if last one */
}
SC2_TWICTRL1 |= SC_TWIRECV; /* set to receive */
WAIT_RX_FIN();
*(p_buf + i) = SC2_DATA; /* receive data */
}
SC2_TWICTRL1 |= SC_TWISTOP; /* send STOP */
WAIT_CMD_FIN();
return SUCCESS;
}
/*--------------------------------------------------------------------------*/
/**
* \brief write a register on the I2C target
* \param slave_addr slave device address
* \param reg_addr address of the register to be written
* \param reg_value value of the register to be written
* \retval 0 register has not been successfully written
* \retval 1 register has been successfully written
*/
uint8_t
i2c_write_reg(uint8_t slave_addr, uint8_t reg_addr, uint8_t reg_value)
{
uint8_t i2c_buffer[2];
i2c_buffer[0] = reg_addr;
i2c_buffer[1] = reg_value;
return i2c_send_frame(slave_addr, i2c_buffer, 2);
}
/*--------------------------------------------------------------------------*/
/**
* \brief read a register from the I2C target
* \param slave_addr slave device address
* \param reg_addr address of the register
* \param p_buf storage destination for the read data
* \retval 0 register has not been successfully read
* \retval 1 register has been successfully read
*/
uint8_t
i2c_read_reg(uint8_t slave_addr, uint8_t reg_addr, uint8_t *p_buf,
uint8_t len)
{
return i2c_receive_frame(slave_addr, reg_addr, p_buf, len);
}
/*--------------------------------------------------------------------------*/
/**
* \brief Init MEMS
* \return None
* \retval 0 the device has not been successfully initialized
* \retval 1 the device has been successfully initialized
*/
static uint8_t
i2c_mems_init(void)
{
uint8_t i = 0;
i += i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, STATUS_REG, 0x00); /* no flag */
i += i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, FF_WU_CFG, 0x00); /* all off */
i += i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, DD_CFG, 0x00); /* all off */
/* i += i2c_write_reg (KLIS3L02DQ_SLAVE_ADDR, CTRL_REG2, (1<<4) | (1<<1) | (1 << 0)); */
i += i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, CTRL_REG2, 0x00);
/* i += i2c_write_reg (KLIS3L02DQ_SLAVE_ADDR, CTRL_REG1, 0xC7); */
i += i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, CTRL_REG1, 0x87);
if(i != 5) {
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
/**
* \brief turn on the MEMS device
* \retval 0 the device has not been successfully set to normal mode
* \retval 1 the device has been successfully set to normal mode
*/
uint8_t
mems_on(void)
{
return i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, CTRL_REG1, 0xC7);
}
/*--------------------------------------------------------------------------*/
/**
* \brief turn off the MEMS device
* \retval 0 the device has not been successfully turned off
* \retval 1 the device has been successfully turned off
*/
uint8_t
mems_off(void)
{
return i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, CTRL_REG1, 0x87);
}
/*--------------------------------------------------------------------------*/
/**
* \brief set full-scale range of the device
* \param range HIGH for high scale selection, LOW for low range.
* \retval 0 the device has not been successfully set to full scale mode
* \retval 1 the device has been successfully set to full scale mode
*/
uint8_t
mems_set_fullscale(boolean range)
{
uint8_t i2c_buffer;
if (!i2c_read_reg(KLIS3L02DQ_SLAVE_ADDR, CTRL_REG1, &i2c_buffer, 1)) {
return 0;
}
if(range == MEMS_HIGH_RANGE) {
i2c_buffer |= 0x20;
} else {
i2c_buffer &= ~0x20;
}
if (!i2c_write_reg(KLIS3L02DQ_SLAVE_ADDR, CTRL_REG1, i2c_buffer)) {
return 0;
}
fullscale_state = range;
return 1;
}
/*--------------------------------------------------------------------------*/
/**
* \brief Get full-scale range of the device
* \retval HIGH high scale selection
* \retval LOW low range
*/
boolean
mems_get_fullscale(void)
{
return fullscale_state;
}
/*--------------------------------------------------------------------------*/
/**
* \brief Returns the 3 mems acceleration values related to x,y,z axes
* \param mems_data pointer to mems_data_t that will be filled with the values
* \retval 0 acceleration data has not been successfully read
* \retval 1 acceleration data has been successfully read
*/
#if 0
static uint8_t
i2c_mems_read(mems_data_t *mems_data)
{
uint8_t i, i2c_buffer[8];
i = i2c_read_reg (KLIS3L02DQ_SLAVE_ADDR, OUTX_L, i2c_buffer, 8);
mems_data->outx_h = i2c_buffer[0];
mems_data->outx_l = i2c_buffer[1];
mems_data->outy_h = i2c_buffer[2];
mems_data->outy_l = i2c_buffer[3];
mems_data->outz_h = i2c_buffer[4];
mems_data->outz_l = i2c_buffer[5];
return i;
}
#endif
/*--------------------------------------------------------------------------*/
/** @} */