forked from uARM-Palm/uARM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathi2cdev_AN32502A.c
executable file
·119 lines (92 loc) · 2.42 KB
/
i2cdev_AN32502A.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
//(c) uARM project https://github.com/uARM-Palm/uARM [email protected]
#include "i2cdev_AN32502A.h"
#include <string.h>
#include <stdlib.h>
#include "util.h"
struct An32502A {
uint8_t inTransaction : 1;
uint8_t addrSeen : 1;
uint8_t ourAddr : 1;
uint8_t isRead : 1;
uint8_t regAddrSeen : 1;
uint8_t reg;
};
static bool an32502aPrvDoRegWrite(struct An32502A *an, uint8_t reg, uint8_t val)
{
fprintf(stderr, "AN: writing 0x%02x -> 0x%02x\n", val, reg);
if (reg > 2)
return false;
//value not needed for emulated system
return true;
}
static uint8_t an32502aPrvDoRegRead(struct An32502A *an, uint8_t reg)
{
fprintf(stderr, "AN32502A does not support register reading\n");
return 0;
}
static uint_fast8_t an32502aPrvI2cHandler(void *userData, enum ActionI2C stimulus, uint_fast8_t value)
{
struct An32502A *an = (struct An32502A*)userData;
switch (stimulus) {
case i2cStart:
an->inTransaction = 1;
an->regAddrSeen = 0;
//fallthrough
case i2cRestart:
an->addrSeen = 0;
an->ourAddr = 0;
return 0;
case i2cStop:
an->inTransaction = 0;
return 0;
case i2cTx:
if (!an->inTransaction)
return 0;
if (!an->addrSeen) {
an->addrSeen = 1;
if ((value >> 1) != 0x73)
return 0;
an->ourAddr = 1;
an->isRead = value & 1;
return 1;
}
if (!an->ourAddr)
return 0;
if (an->isRead) {
fprintf(stderr, "unexpected write in read mode\n");
return 0;
}
//write to us
if (!an->regAddrSeen) {
an->regAddrSeen = 1;
an->reg = value;
return 1;
}
//write to a reg
return an32502aPrvDoRegWrite(an, an->reg++, value) ? 1 : 0;
case i2cRx:
if (!an->inTransaction || !an->addrSeen || !an->ourAddr)
return 0;
if (!an->isRead) {
fprintf(stderr, "unexpected read in write mode\n");
return 0;
}
if (!an->regAddrSeen) {
fprintf(stderr, "unexpected read before register specified\n");
return 0;
}
return an32502aPrvDoRegRead(an, an->reg++);
default:
return 0;
}
}
struct An32502A* an32502aInit(struct SocI2c* i2c)
{
struct An32502A *an = (struct An32502A*)malloc(sizeof(*an));
if (!an)
ERR("cannot alloc AN32502A");
memset(an, 0, sizeof (*an));
if (!socI2cDeviceAdd(i2c, an32502aPrvI2cHandler, an))
ERR("cannot add AN32502A to I2C\n");
return an;
}