forked from payne92/bare-metal-arm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaccel.c
executable file
·138 lines (108 loc) · 3.41 KB
/
accel.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// accel.c -- Accelerometer support
//
// Copyright (c) 2012-2013 Andrew Payne <[email protected]>
//
// Based on demo example from Freescale
#include <freedom.h>
#include "common.h"
#define MMA8451_I2C_ADDRESS (0x1d<<1)
#define I2C_READ 1
#define I2C_WRITE 0
#define I2C0_B I2C0_BASE_PTR
// ---------------------------------------------------------------------------
// I2C bus control functions
//
inline void i2c_set_tx(I2C_MemMapPtr p) {p->C1 |= I2C_C1_TX_MASK;}
inline void i2c_set_rx(I2C_MemMapPtr p) {p->C1 &= ~I2C_C1_TX_MASK;}
inline void i2c_set_slave(I2C_MemMapPtr p) {p->C1 &= ~I2C_C1_MST_MASK;}
inline void i2c_set_master(I2C_MemMapPtr p) {p->C1 |= I2C_C1_MST_MASK;}
inline void i2c_give_nack(I2C_MemMapPtr p) {p->C1 |= I2C_C1_TXAK_MASK;}
inline void i2c_give_ack(I2C_MemMapPtr p) {p->C1 &= ~I2C_C1_TXAK_MASK;}
inline void i2c_repeated_start(I2C_MemMapPtr p){p->C1 |= I2C_C1_RSTA_MASK;}
inline uint8_t i2c_read(I2C_MemMapPtr p) {return p->D;}
inline void i2c_start(I2C_MemMapPtr p)
{
i2c_set_master(p);
i2c_set_tx(p);
}
inline void i2c_stop(I2C_MemMapPtr p)
{
i2c_set_slave(p);
i2c_set_rx(p);
}
inline void i2c_wait(I2C_MemMapPtr p)
{
// Spin wait for the interrupt flag to be set
while((p->S & I2C_S_IICIF_MASK) == 0)
;
p->S |= I2C_S_IICIF_MASK; // Clear flag
}
inline int i2c_write(I2C_MemMapPtr p, uint8_t data)
{
// Send data, wait, and return ACK status
p->D = data;
i2c_wait(p);
return ((p->S & I2C_S_RXAK_MASK) == 0);
}
inline void i2c_init(I2C_MemMapPtr p)
{
// Enable clocks
SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;
SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK;
// Configure GPIO for I2C
PORTE_PCR24 = PORT_PCR_MUX(5);
PORTE_PCR25 = PORT_PCR_MUX(5);
p->F = 0x14; // Baudrate settings: ICR=0x14, MULT=0
p->C1 = I2C_C1_IICEN_MASK; // Enable: IICEN=1
}
// ---------------------------------------------------------------------------
// MMA8451 control functions
//
// this delay is very important, it may cause w-r operation failure.
static void pause(void)
{
int n;
for(n=0; n<40; n++)
asm("nop");
}
uint8_t mma8451_read(uint8_t addr)
{
pause();
i2c_start(I2C0_B);
i2c_write(I2C0_B, MMA8451_I2C_ADDRESS | I2C_WRITE);
i2c_write(I2C0_B, addr);
i2c_repeated_start(I2C0_B);
i2c_write(I2C0_B, MMA8451_I2C_ADDRESS | I2C_READ);
i2c_set_rx(I2C0_B);
i2c_give_nack(I2C0_B);
i2c_read(I2C0_B);
i2c_wait(I2C0_B);
i2c_stop(I2C0_B);
return i2c_read(I2C0_B);
}
void mma8451_write(uint8_t addr, uint8_t data)
{
pause();
i2c_start(I2C0_B);
i2c_write(I2C0_B, MMA8451_I2C_ADDRESS | I2C_WRITE);
i2c_write(I2C0_B, addr);
i2c_write(I2C0_B, data);
i2c_stop(I2C0_B);
}
#define CTRL_REG1 (0x2a)
void accel_init(void)
{
uint8_t tmp;
i2c_init(I2C0_B);
tmp = mma8451_read(CTRL_REG1);
mma8451_write(CTRL_REG1, tmp | 0x01); // ACTIVE = 1
}
// Read a signed 14-bit value from (reg, reg+1)
int16_t _read_reg14(int reg)
{
return (int16_t)((mma8451_read(reg) << 8) | mma8451_read(reg+1)) >> 2;
}
// Read acceleration values for each axis
int16_t accel_x(void) {return _read_reg14(0x01);}
int16_t accel_y(void) {return _read_reg14(0x03);}
int16_t accel_z(void) {return _read_reg14(0x05);}