UoS³ Flight Computer Firmware
 All Data Structures Files Functions Groups Pages
i2ctest.c
1 
2 // i2c IMU functionality test
3 //
4 // Suzanna Lucarotti (c) 11/8/2017
5 //
6 // for use with the UoS3 Cubesat
7 //
8 // derived from blinky and Ti's i2c examples and MPU9205 datasheets
9 
10 
11 #include "../firmware.h"
12 
13 #include "inc/hw_i2c.h"
14 #include "inc/hw_memmap.h"
15 #include "inc/hw_types.h"
16 
17 #include "driverlib/gpio.h"
18 #include "driverlib/i2c.h"
19 #include "driverlib/pin_map.h"
20 #include "driverlib/sysctl.h"
21 
22 #include <stdlib.h>
23 #include <stdarg.h>
24 
25 #define DEBUG_SERIAL UART_CAMERA // this is the serial port debug messages will come through (UART_CAMERA or UART_GNSS)
26 #define GPS_SERIAL UART_GNSS
27 #define CAM_SERIAL UART_CAMERA
28 
29 #define DEBUG_SERIAL GPS_SERIAL
30 
31  // the useful hardware constants (only used here so not moved away as yet)
32 
33 #define SLAVE_ADDRESS 0x68 // this is the MPU-9250A i2c address %1011000
34 
35 // MPU 9250 registers
36 
37 #define MPU_CONFIG 26
38 #define MPU_GYRO_CONFIG 27
39 #define MPU_ACCEL_CONFIG 28
40 #define MPU_ACCEL_XOUT 59
41 #define MPU_ACCEL_YOUT 61
42 #define MPU_ACCEL_ZOUT 63
43 #define MPU_TEMP_OUT 65
44 #define MPU_GYRO_XOUT 67
45 #define MPU_GYRO_YOUT 69
46 #define MPU_GYRO_ZOUT 71
47 #define MPU_WHO_AM_I 117
48 #define MPU_INT_BYPASS_ENABLE 55
49 
50 
51 // Wrappers for printing to serial port - always to the one specified as output, placed here close to code for clarity
52 
53 #define STRING_BUFFER_LENGTH 20 // rough hack for testing
54 
55 static char string_buffer[STRING_BUFFER_LENGTH];
56 static char string_buffer2[STRING_BUFFER_LENGTH];
57 
58 static void UART_putnum(unsigned int serialport,signed long x)
59  {
60  itoa(abs(x),string_buffer,16); // 16 for hex, 10 for decimal
61  unsigned int len=strlen(string_buffer);
62  unsigned int targetlen=6-len;
63  strcpy(string_buffer2,"+00000");
64  strcpy(string_buffer2+targetlen,string_buffer);
65  if (x<0) string_buffer2[0]='-';
66  UART_puts(serialport,string_buffer2);
67 }
68 
69 static void UART_putstr(unsigned int serialport, char *s1,signed long x, char *s2)
70  {
71  if (s1!=NULL) UART_puts(serialport,s1);
72  UART_putnum(serialport,x);
73  if (s2!=NULL) UART_puts(serialport,s2);
74  }
75 
76 #define DISP3(x,y,z) UART_putstr(DEBUG_SERIAL,x,y,z); // x and z are strings, y is a number shown as signed base10 16bit
77 #define DISP2(y,z) UART_putstr(DEBUG_SERIAL,NULL,y,z);
78 #define DISP1(x) UART_puts(DEBUG_SERIAL,x);
79 
81  // the actual main code
83 
84 int main(void)
85 {
86  InitI2C2(); // initialise correct interface on processor
87 
88  Board_init(); // start the board
89  WDT_kick(); // kick the watchdog
90 
91  UART_init(DEBUG_SERIAL, 9600); DISP1("\n\n\r I2C Satellite I2C IMU test.\n")
92 
93  // start the console, print bootup message (below)
94 
95  #define MAG_PASS_THROUGH_I2C_ADDR 12
96 
97  #define MAG_HXL 3
98  #define MAG_HYL 5
99  #define MAG_HZL 7 // offsets in magnetometer, note little endian, so need to be read opposite way round
100  #define MAG_CNTL1 10 // Magnetometer control register
101  #define MAG_STA1 2 // read only gives flags at 1 for DRDY and 2 for DOR (data ready and overload), used in read cycle
102 
103 // enable magnetometer to appear separately I2C by commanding MPU chip
104 
105  char i2cstring[3]; // static buffer for i2c calls here
106  i2cstring[0]=MPU_INT_BYPASS_ENABLE; // int pin /bypass enable configuration
107  char i2cstatus=I2CReceive(SLAVE_ADDRESS,MPU_INT_BYPASS_ENABLE);
108  i2cstring[1]=i2cstatus | MPU_INT_BYPASS_ENABLE; // flag bypass on
109  i2cstring[3]=0; // null terminated string
110  I2CSendString(SLAVE_ADDRESS, i2cstring); // turn on bypass to Magnetometer so visible on I2C
111 
112 // setup magnetometer
113 
114  i2cstring[0]=MAG_CNTL1;
115  i2cstring[2]=0;
116  i2cstring[1]=0; // set mode to zero before changing mode
117  I2CSendString(MAG_PASS_THROUGH_I2C_ADDR, i2cstring); // set Magnetometer to safe mode before mode change
118  i2cstring[1]=1 | 0; // continuous (16hz) mode with 14bit range
119  I2CSendString(MAG_PASS_THROUGH_I2C_ADDR, i2cstring); // set Magnetometer to continuous shot mode with 16bit range, single shot needs updating and has delay
120 
121  char mag_id=I2CReceive(MAG_PASS_THROUGH_I2C_ADDR,0); // magnetometer ID (hopefully)
122 
123 DISP3("\r I2Cstatus old: ",i2cstatus,"\n")
124 DISP3("\r I2Cstatus new (After enabling passthrough for Magnetometer): ",I2CReceive(SLAVE_ADDRESS,55),"\n")
125 DISP3("\r Magnetometer ID (test, should equal 72 if found): ",mag_id,"\n")
126 
127 signed short acc_x,acc_y,acc_z,gyr_x,gyr_y,gyr_z,mag_x,mag_y,mag_z,temp;
128 
129 unsigned int wdt_start=20; // loops before kick, not too long or too short or hardware will reset
130 
131 // some macros to simplify repeated I2c calls - deliberately kept near where used
132 #define MPUGET(x) I2CReceive16(SLAVE_ADDRESS,x); // wrapper for I2C call to MPU
133 #define MAGGET(x) I2CReceive16r(MAG_PASS_THROUGH_I2C_ADDR, x); // wrapper for I2C call to Magnetometer
134 
135  while(1) // infinite loop
136  {
137 
138  for (unsigned int wdt_kicker=wdt_start;wdt_kicker>0;wdt_kicker--) // repeat this to kick wdt at correct time.
139  {
140  acc_x=MPUGET(MPU_ACCEL_XOUT) acc_y=MPUGET( MPU_ACCEL_YOUT) acc_z=MPUGET(MPU_ACCEL_ZOUT)
141  gyr_x=MPUGET(MPU_GYRO_XOUT) gyr_y=MPUGET(MPU_GYRO_YOUT) gyr_z=MPUGET(MPU_GYRO_ZOUT)
142  temp=MPUGET(MPU_TEMP_OUT)
143 
144  // magnetometer should be in power down mode with data ready, if not wait for it
145  while ((I2CReceive(MAG_PASS_THROUGH_I2C_ADDR,MAG_STA1)&1)!=1) {}
146  mag_x=MAGGET(MAG_HXL) mag_y=MAGGET(MAG_HYL) mag_z=MAGGET(MAG_HZL)
147 
148  I2CSendString(MAG_PASS_THROUGH_I2C_ADDR, i2cstring); // prepare magnetometer for next call (delay, so give lead in
149 
150  DISP3("\r A:(",acc_x,",") DISP2(acc_y,",") DISP2(acc_z,") ")
151  DISP3("G:(",gyr_x,",") DISP2(gyr_y,",") DISP2(gyr_z,") ")
152  DISP3("Temp:(",temp,")")
153  DISP3(" M:(",mag_x,",") DISP2(mag_y,",") DISP2(mag_z,") ")
154  }
155  WDT_kick();
156  }
157 }
158 
159 
void UART_init(uint8_t uart_num, uint32_t baudrate)
Definition: uart.c:78
int main(void)
Runs all module tests.
Definition: test.c:19
void UART_puts(uint8_t uart_num, char *str)
Definition: uart.c:129
void Board_init(void)
Definition: board.c:13
void WDT_kick(void)
Definition: wdt.c:19