-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpi2c.c
106 lines (90 loc) · 2.73 KB
/
pi2c.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
/**
* I2C wrapper for ChibiOS due to a bug: I2C blocking when I2C transfer suffered timeout
* @see https://github.com/psas/stm32/commit/32ec8c97a1e5bf605bd5d41a89fc60b60e136af2
*/
#include "ch.h"
#include "hal.h"
#include "pi2c.h"
#define I2C_DRIVER (&I2CD1)
static uint8_t error;
const I2CConfig _i2cfg = {
OPMODE_I2C,
50000,
STD_DUTY_CYCLE,
};
//seriously, do not try to use 200khz I2C, it causes the camera to stop working
//static const I2CConfig _i2cfg = {
// OPMODE_I2C,
// 200000,
// FAST_DUTY_CYCLE_2,
//};
static bool I2C_transmit(uint8_t addr, uint8_t *txbuf, uint32_t txbytes, uint8_t *rxbuf, uint32_t rxbytes, sysinterval_t timeout) {
i2cAcquireBus(I2C_DRIVER);
i2cStart(I2C_DRIVER, &_i2cfg);
msg_t i2c_status = i2cMasterTransmitTimeout(I2C_DRIVER, addr, txbuf, txbytes, rxbuf, rxbytes, timeout);
i2cStop(I2C_DRIVER);
i2cReleaseBus(I2C_DRIVER);
if(i2c_status == MSG_TIMEOUT) { // Restart I2C at timeout
chprintf((BaseSequentialStream *)&SD1,"I2C > TIMEOUT (ADDR 0x%02x)\r\n", addr);
error = 0x1;
} else if(i2c_status == MSG_RESET) {
chprintf((BaseSequentialStream *)&SD1,"I2C > RESET (ADDR 0x%02x)\r\n", addr);
error = 0x0;
} else {
error = 0x0;
}
return i2c_status == MSG_OK;
}
void I2C_Lock(void) {
i2cAcquireBus(I2C_DRIVER);
}
void I2C_Unlock(void) {
i2cReleaseBus(I2C_DRIVER);
}
bool I2C_write8(uint8_t address, uint8_t reg, uint8_t value)
{
uint8_t txbuf[] = {reg, value};
return I2C_transmit(address, txbuf, 2, NULL, 0, TIME_MS2I(100));
}
bool I2C_writeN(uint8_t address, uint8_t *txbuf, uint32_t length)
{
return I2C_transmit(address, txbuf, length, NULL, 0, TIME_MS2I(100));
}
bool I2C_read8(uint8_t address, uint8_t reg, uint8_t *val)
{
uint8_t txbuf[] = {reg};
uint8_t rxbuf[1];
bool ret = I2C_transmit(address, txbuf, 1, rxbuf, 1, TIME_MS2I(100));
*val = rxbuf[0];
return ret;
}
bool I2C_read16(uint8_t address, uint8_t reg, uint16_t *val)
{
uint8_t txbuf[] = {reg};
uint8_t rxbuf[2];
bool ret = I2C_transmit(address, txbuf, 1, rxbuf, 2, TIME_MS2I(100));
*val = (rxbuf[0] << 8) | rxbuf[1];
return ret;
}
bool I2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val) {
bool ret = I2C_read16(address, reg, val);
*val = (*val >> 8) | (*val << 8);
return ret;
}
bool I2C_read8_16bitreg(uint8_t address, uint16_t reg, uint8_t *val) // 16bit register (for OV5640)
{
uint8_t txbuf[] = {reg >> 8, reg & 0xFF};
uint8_t rxbuf[1];
bool ret = I2C_transmit(address, txbuf, 2, rxbuf, 1, TIME_MS2I(100));
*val = rxbuf[0];
return ret;
}
bool I2C_write8_16bitreg(uint8_t address, uint16_t reg, uint8_t value) // 16bit register (for OV5640)
{
uint8_t txbuf[] = {reg >> 8, reg & 0xFF, value};
return I2C_transmit(address, txbuf, 3, NULL, 0, TIME_MS2I(100));
}
uint8_t I2C_hasError(void)
{
return error;
}