/** * \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 /*--------------------------------------------------------------------------*/ /** @} */