-
Notifications
You must be signed in to change notification settings - Fork 8
/
i2sdev_AK4534.c
executable file
·138 lines (107 loc) · 2.92 KB
/
i2sdev_AK4534.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
//(c) uARM project https://github.com/uARM-Palm/uARM [email protected]
#include "i2sdev_AK4534.h"
#include <string.h>
#include <stdlib.h>
#include "util.h"
struct AK4534 {
struct SocGpio *gpio;
//regs
uint8_t regs[16]; //last two forced to zero
//i2c state machine state
struct {
uint8_t inTransaction : 1;
uint8_t addrSeen : 1;
uint8_t ourAddr : 1;
uint8_t isRead : 1;
uint8_t regAddrSeen : 1;
uint8_t reg;
} i2c;
};
static bool ak4534prvDoRegWrite(struct AK4534 *ak, uint8_t reg, uint8_t val)
{
//fprintf(stderr, "AK4534: writing 0x%02x -> [0x%02x]\n", val, reg);
if (reg < sizeof(ak->regs) / sizeof(*ak->regs)) {
ak->regs[reg] = val;
return true;
}
fprintf(stderr, "UNKNOWN REG WRITTEN 0x%02x -> [0x%02x]\n", val, reg);
return false;
}
static uint8_t ak4534prvDoRegRead(struct AK4534 *ak, uint8_t reg)
{
//fprintf(stderr, "AK4534: reading [0x%02x]\n", reg);
if (reg < sizeof(ak->regs) / sizeof(*ak->regs))
return ak->regs[reg];
fprintf(stderr, "UNKNOWN REG READ: 0x%02x\n", reg);
return 0;
}
static uint_fast8_t ak4534prvI2cHandler(void *userData, enum ActionI2C stimulus, uint_fast8_t value)
{
struct AK4534 *ak = (struct AK4534*)userData;
switch (stimulus) {
case i2cStart:
ak->i2c.inTransaction = 1;
ak->i2c.regAddrSeen = 0;
//fallthrough
case i2cRestart:
ak->i2c.addrSeen = 0;
ak->i2c.ourAddr = 0;
return 0;
case i2cStop:
ak->i2c.inTransaction = 0;
return 0;
case i2cTx:
if (!ak->i2c.inTransaction)
return 0;
if (!ak->i2c.addrSeen) {
ak->i2c.addrSeen = 1;
if ((value >> 1) != 0x10)
return 0;
ak->i2c.ourAddr = 1;
ak->i2c.isRead = value & 1;
return 1;
}
if (!ak->i2c.ourAddr)
return 0;
if (ak->i2c.isRead) {
fprintf(stderr, "unexpected write in read mode\n");
return 0;
}
//write to us
if (!ak->i2c.regAddrSeen) {
ak->i2c.regAddrSeen = 1;
ak->i2c.reg = value;
return 1;
}
//write to a reg
return ak4534prvDoRegWrite(ak, ak->i2c.reg++, value) ? 1 : 0;
case i2cRx:
if (!ak->i2c.inTransaction || !ak->i2c.addrSeen || !ak->i2c.ourAddr)
return 0;
if (!ak->i2c.isRead) {
fprintf(stderr, "unexpected read in write mode\n");
return 0;
}
return ak4534prvDoRegRead(ak, ak->i2c.reg++);
default:
return 0;
}
}
struct AK4534* ak4534Init(struct SocI2c *i2c, struct SocI2s *i2s, struct SocGpio *gpio)
{
struct AK4534 *ak = (struct AK4534*)malloc(sizeof(*ak));
if (!ak)
ERR("cannot alloc AK4534");
memset(ak, 0, sizeof (*ak));
ak->regs[1] = 0x80;
ak->regs[3] = 0x03;
ak->regs[4] = 0x02;
ak->regs[6] = 0x11;
ak->regs[7] = 0x01;
ak->regs[9] = 0x40;
ak->regs[10] = 0x36;
ak->regs[11] = 0x10;
if (!socI2cDeviceAdd(i2c, ak4534prvI2cHandler, ak))
ERR("cannot add TSC2101 to I2C\n");
return ak;
}