Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
mpu60x0_spi.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 Gautier Hattenberger
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
30
31void mpu60x0_spi_init(struct Mpu60x0_Spi *mpu, struct spi_periph *spi_p, uint8_t slave_idx)
32{
33 /* set spi_peripheral */
34 mpu->spi_p = spi_p;
35
36 /* configure spi transaction */
41 mpu->spi_trans.cdiv = SPIDiv64;
42
44 mpu->spi_trans.slave_idx = slave_idx;
45 mpu->spi_trans.output_length = 2;
48 mpu->spi_trans.after_cb = NULL;
49 mpu->spi_trans.input_buf = &(mpu->rx_buf[0]);
50 mpu->spi_trans.output_buf = &(mpu->tx_buf[0]);
51
52 /* set inital status: Success or Done */
54
55 /* set default MPU60X0 config options */
57
58 mpu->data_available = false;
59 mpu->config.initialized = false;
61
63}
64
65
67{
68 struct Mpu60x0_Spi *mpu_spi = (struct Mpu60x0_Spi *)(mpu);
70 mpu_spi->spi_trans.input_length = 0;
71 mpu_spi->tx_buf[0] = _reg;
72 mpu_spi->tx_buf[1] = _val;
73 spi_submit(mpu_spi->spi_p, &(mpu_spi->spi_trans));
74}
75
76// Configuration function called once before normal use
78{
80
81 // First check if we found the chip (succesfull WHO_AM_I response)
82 if (mpu->spi_trans.status == SPITransSuccess &&
83 (mpu->rx_buf[1] == MPU60X0_WHOAMI_REPLY ||
84 mpu->rx_buf[1] == ICM20600_WHOAMI_REPLY ||
85 mpu->rx_buf[1] == ICM20608_WHOAMI_REPLY ||
86 mpu->rx_buf[1] == ICM20602_WHOAMI_REPLY ||
87 mpu->rx_buf[1] == ICM20689_WHOAMI_REPLY ||
88 mpu->rx_buf[1] == MPU6500_WHOAMI_REPLY)) {
89
90 if (mpu->rx_buf[1] == MPU60X0_WHOAMI_REPLY || mpu->rx_buf[1] == MPU6500_WHOAMI_REPLY) {
91 mpu->config.type = MPU60X0;
92 } else if (mpu->rx_buf[1] == ICM20600_WHOAMI_REPLY) {
93 mpu->config.type = ICM20600;
94 } else if (mpu->rx_buf[1] == ICM20608_WHOAMI_REPLY) {
95 mpu->config.type = ICM20608;
96 } else if (mpu->rx_buf[1] == ICM20602_WHOAMI_REPLY) {
97 mpu->config.type = ICM20602;
98 } else if (mpu->rx_buf[1] == ICM20689_WHOAMI_REPLY) {
99 mpu->config.type = ICM20689;
100 }
101
102 mpu->config.init_status++;
104 mpu60x0_send_config(mpu60x0_spi_write_to_reg, (void *)mpu, &(mpu->config));
105 }
106 // Send WHO_AM_I to check if chip is there
107 else if (mpu->spi_trans.status != SPITransRunning && mpu->spi_trans.status != SPITransPending) {
108 mpu->spi_trans.output_length = 1;
109 mpu->spi_trans.input_length = 2;
111 spi_submit(mpu->spi_p, &(mpu->spi_trans));
112 }
113 }
114}
115
117{
118 if (mpu->config.initialized && mpu->spi_trans.status == SPITransDone) {
119 mpu->spi_trans.output_length = 1;
120 mpu->spi_trans.input_length = 1 + mpu->config.nb_bytes;
121 /* set read bit and multiple byte bit, then address */
123 spi_submit(mpu->spi_p, &(mpu->spi_trans));
124 }
125}
126
127#define Int16FromBuf(_buf,_idx) ((int16_t)((_buf[_idx]<<8) | _buf[_idx+1]))
128
130{
131 if (mpu->config.initialized) {
132 if (mpu->spi_trans.status == SPITransFailed) {
134 } else if (mpu->spi_trans.status == SPITransSuccess) {
135 // Successfull reading
136 if (bit_is_set(mpu->rx_buf[1], 0)) {
137 // new data
138 mpu->data_accel.vect.x = Int16FromBuf(mpu->rx_buf, 2);
139 mpu->data_accel.vect.y = Int16FromBuf(mpu->rx_buf, 4);
140 mpu->data_accel.vect.z = Int16FromBuf(mpu->rx_buf, 6);
141 mpu->data_rates.rates.p = Int16FromBuf(mpu->rx_buf, 10);
142 mpu->data_rates.rates.q = Int16FromBuf(mpu->rx_buf, 12);
143 mpu->data_rates.rates.r = Int16FromBuf(mpu->rx_buf, 14);
144
146 switch(mpu->config.type) {
147 case ICM20600:
148 case ICM20602:
149 case ICM20608:
150 mpu->temp = (float)temp_raw / 326.8f + 25.0f;
151 break;
152 case ICM20689:
153 mpu->temp = (float)temp_raw * 0.003f + 25.0f;
154 break;
155 default:
156 mpu->temp = (float)temp_raw / 340.0f + 36.53f;
157 break;
158 }
159
160 // if we are reading slaves, copy the ext_sens_data
161 if (mpu->config.nb_slaves > 0) {
162 /* the buffer is volatile, since filled from ISR
163 * but we know it's ok to use it here so we silence the warning
164 */
165#pragma GCC diagnostic push
166#pragma GCC diagnostic ignored "-Wcast-qual"
167 memcpy(mpu->data_ext, (uint8_t *) & (mpu->rx_buf[16]), mpu->config.nb_bytes - 15);
168#pragma GCC diagnostic pop
169 }
170
171 mpu->data_available = true;
172 }
174 }
175 } else if (mpu->config.init_status != MPU60X0_CONF_UNINIT) { // Configuring but not yet initialized
176 switch (mpu->spi_trans.status) {
177 case SPITransFailed:
178 mpu->config.init_status--; // Retry config (TODO max retry)
179 /* Falls through. */
180 case SPITransSuccess:
181 case SPITransDone:
182 mpu60x0_send_config(mpu60x0_spi_write_to_reg, (void *)mpu, &(mpu->config));
183 if (mpu->config.initialized) {
184 mpu->spi_trans.status = SPITransDone;
185 }
186 break;
187 default:
188 break;
189 }
190 }
191}
192
195{
196 struct Mpu60x0_Spi *mpu_spi = (struct Mpu60x0_Spi *)(mpu);
197
198 if (mpu_spi->slave_init_status == MPU60X0_SPI_CONF_UNINIT) {
200 }
201
202 switch (mpu_spi->slave_init_status) {
204 /* configure MPU I2C master clock and stop/start between slave reads */
205 mpu_set(mpu, MPU60X0_REG_I2C_MST_CTRL, ((1 << 4) | mpu_spi->config.i2c_mst_clk));
206 mpu_spi->slave_init_status++;
207 break;
209 /* Set I2C slaves delayed sample rate */
210 mpu_set(mpu, MPU60X0_REG_I2C_MST_DELAY, mpu_spi->config.i2c_mst_delay);
211 mpu_spi->slave_init_status++;
212 break;
214 /* enable internal I2C master and disable primary I2C interface */
216 (1 << MPU60X0_I2C_MST_EN)));
217 mpu_spi->slave_init_status++;
218 break;
220 /* configure each slave until all nb_slaves are done */
221 if (mpu_spi->config.nb_slave_init < mpu_spi->config.nb_slaves && mpu_spi->config.nb_slave_init < MPU60X0_I2C_NB_SLAVES) {
222 // proceed to next slave if configure for current one returns true
223 if (mpu_spi->config.slaves[mpu_spi->config.nb_slave_init].configure(mpu_set, mpu)) {
224 mpu_spi->config.nb_slave_init++;
225 }
226 }
227 else {
228 /* all slave devies configured, continue MPU side configuration of I2C slave stuff */
229 mpu_spi->slave_init_status++;
230 }
231 break;
233 return true;
234 default:
235 break;
236 }
237 return false;
238}
enum SPIClockPolarity cpol
clock polarity control
Definition spi.h:155
enum SPIClockPhase cpha
clock phase control
Definition spi.h:156
enum SPISlaveSelect select
slave selection behavior
Definition spi.h:154
SPICallback before_cb
NULL or function called before the transaction.
Definition spi.h:160
SPICallback after_cb
NULL or function called after the transaction.
Definition spi.h:161
enum SPIDataSizeSelect dss
data transfer word size
Definition spi.h:157
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition spi.h:150
uint16_t input_length
number of data words to read
Definition spi.h:151
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition spi.h:159
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition spi.h:149
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition spi.h:153
enum SPIBitOrder bitorder
MSB/LSB order.
Definition spi.h:158
uint16_t output_length
number of data words to write
Definition spi.h:152
enum SPITransactionStatus status
Definition spi.h:162
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition spi_arch.c:533
@ SPICphaEdge2
CPHA = 1.
Definition spi.h:75
@ SPITransFailed
Definition spi.h:100
@ SPITransSuccess
Definition spi.h:99
@ SPITransRunning
Definition spi.h:98
@ SPITransPending
Definition spi.h:97
@ SPITransDone
Definition spi.h:101
@ SPICpolIdleHigh
CPOL = 1.
Definition spi.h:84
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:63
@ SPIMSBFirst
Definition spi.h:112
@ SPIDiv64
Definition spi.h:125
@ SPIDss8bit
Definition spi.h:90
SPI peripheral structure.
Definition spi.h:174
uint16_t foo
Definition main_demo5.c:58
void mpu60x0_set_default_config(struct Mpu60x0Config *c)
Definition mpu60x0.c:67
void mpu60x0_send_config(Mpu60x0ConfigSet mpu_set, void *mpu, struct Mpu60x0Config *config)
Configuration sequence called once before normal use.
Definition mpu60x0.c:89
#define MPU60X0_I2C_NB_SLAVES
Definition mpu60x0.h:53
bool initialized
config done flag
Definition mpu60x0.h:149
uint8_t nb_bytes
number of bytes to read starting with MPU60X0_REG_INT_STATUS
Definition mpu60x0.h:147
@ ICM20602
Definition mpu60x0.h:108
@ ICM20689
Definition mpu60x0.h:109
@ ICM20600
Definition mpu60x0.h:106
@ MPU60X0
Definition mpu60x0.h:105
@ ICM20608
Definition mpu60x0.h:107
uint8_t nb_slaves
number of used I2C slaves
Definition mpu60x0.h:156
enum Mpu60x0Type type
The type of sensor (MPU60x0, ICM20608, ...)
Definition mpu60x0.h:139
enum Mpu60x0ConfStatus init_status
init status
Definition mpu60x0.h:148
@ MPU60X0_CONF_UNINIT
Definition mpu60x0.h:113
void(* Mpu60x0ConfigSet)(void *mpu, uint8_t _reg, uint8_t _val)
Configuration function prototype.
Definition mpu60x0.h:129
#define MPU60X0_REG_USER_CTRL
#define MPU6500_WHOAMI_REPLY
#define MPU60X0_WHOAMI_REPLY
#define ICM20600_WHOAMI_REPLY
#define MPU60X0_REG_WHO_AM_I
#define MPU60X0_REG_INT_STATUS
#define ICM20689_WHOAMI_REPLY
#define MPU60X0_SPI_READ
#define MPU60X0_I2C_IF_DIS
#define ICM20602_WHOAMI_REPLY
#define MPU60X0_REG_I2C_MST_CTRL
#define ICM20608_WHOAMI_REPLY
#define MPU60X0_I2C_MST_EN
#define MPU60X0_REG_I2C_MST_DELAY
void mpu60x0_spi_read(struct Mpu60x0_Spi *mpu)
void mpu60x0_spi_event(struct Mpu60x0_Spi *mpu)
void mpu60x0_spi_init(struct Mpu60x0_Spi *mpu, struct spi_periph *spi_p, uint8_t slave_idx)
Definition mpu60x0_spi.c:31
void mpu60x0_spi_start_configure(struct Mpu60x0_Spi *mpu)
Definition mpu60x0_spi.c:77
#define Int16FromBuf(_buf, _idx)
bool mpu60x0_configure_i2c_slaves(Mpu60x0ConfigSet mpu_set, void *mpu)
configure the registered I2C slaves
static void mpu60x0_spi_write_to_reg(void *mpu, uint8_t _reg, uint8_t _val)
Definition mpu60x0_spi.c:66
Driver for the MPU-60X0 using SPI.
volatile bool data_available
data ready flag
Definition mpu60x0_spi.h:56
uint8_t data_ext[MPU60X0_BUFFER_EXT_LEN]
Definition mpu60x0_spi.h:66
struct Mpu60x0Config config
Definition mpu60x0_spi.h:67
struct spi_transaction spi_trans
Definition mpu60x0_spi.h:53
float temp
temperature in degrees Celcius
Definition mpu60x0_spi.h:65
volatile uint8_t tx_buf[2]
Definition mpu60x0_spi.h:54
union Mpu60x0_Spi::@344 data_rates
enum Mpu60x0SpiSlaveInitStatus slave_init_status
Definition mpu60x0_spi.h:68
struct spi_periph * spi_p
Definition mpu60x0_spi.h:52
@ MPU60X0_SPI_CONF_SLAVES_CONFIGURE
Definition mpu60x0_spi.h:47
@ MPU60X0_SPI_CONF_UNINIT
Definition mpu60x0_spi.h:43
@ MPU60X0_SPI_CONF_I2C_MST_CLK
Definition mpu60x0_spi.h:44
@ MPU60X0_SPI_CONF_DONE
Definition mpu60x0_spi.h:48
@ MPU60X0_SPI_CONF_I2C_MST_DELAY
Definition mpu60x0_spi.h:45
@ MPU60X0_SPI_CONF_I2C_MST_EN
Definition mpu60x0_spi.h:46
volatile uint8_t rx_buf[MPU60X0_BUFFER_LEN]
Definition mpu60x0_spi.h:55
#define MPU60X0_BUFFER_LEN
Definition mpu60x0_spi.h:39
union Mpu60x0_Spi::@343 data_accel
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.