-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathi2c_workaround.h
119 lines (103 loc) · 4.33 KB
/
i2c_workaround.h
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
/*
As of the date of releasing this code, there is (seemingly) a bug in the FZ i2c library code
It is described here: https://github.com/flipperdevices/flipperzero-firmware/issues/1670
This is a short-term workaround so I can keep developing while we get to the bottom of the issue
FYI. *something* in the following code is the fix
void furi_hal_i2c_acquire (FuriHalI2cBusHandle* handle)
{
// 1. Disable the power/backlight (it uses i2c)
furi_hal_power_insomnia_enter();
// 2. Lock bus access
handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
// 3. Ensuree that no active handle set
furi_check(handle->bus->current_handle == NULL);
// 4. Set current handle
handle->bus->current_handle = handle;
// 5. Activate bus
handle->bus->callback(handle->bus, FuriHalI2cBusEventActivate);
// 6. Activate handle
handle->callback(handle, FuriHalI2cBusHandleEventActivate);
}
void furi_hal_i2c_release (FuriHalI2cBusHandle* handle)
{
// Ensure that current handle is our handle
furi_check(handle->bus->current_handle == handle);
// 6. Deactivate handle
handle->callback(handle, FuriHalI2cBusHandleEventDeactivate);
// 5. Deactivate bus
handle->bus->callback(handle->bus, FuriHalI2cBusEventDeactivate);
// 3,4. Reset current handle
handle->bus->current_handle = NULL;
// 2. Unlock bus
handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock);
// 1. Re-enable the power system
furi_hal_power_insomnia_exit();
}
*/
#ifndef I2C_WORKAROUND_H_
#define I2C_WORKAROUND_H_
#include <furi_hal.h>
#define ENABLE_WORKAROUND 1
#if ENABLE_WORKAROUND == 1
//+============================================================================ ========================================
static inline
bool furi_hal_Wi2c_is_device_ready (FuriHalI2cBusHandle* const bus, const uint8_t addr, const uint32_t tmo)
{
furi_hal_i2c_acquire(bus);
bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo);
furi_hal_i2c_release(bus);
return rv;
}
//+============================================================================
static inline
bool furi_hal_Wi2c_tx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
const void* buf, const size_t len, const uint32_t tmo )
{
furi_hal_i2c_acquire(bus);
bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo);
furi_hal_i2c_release(bus);
return rv;
}
//+============================================================================
static inline
bool furi_hal_Wi2c_rx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
void* buf, const size_t len, const uint32_t tmo )
{
furi_hal_i2c_acquire(bus);
bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo);
furi_hal_i2c_release(bus);
return rv;
}
//+============================================================================
static inline
bool furi_hal_Wi2c_trx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
const void* tx, const size_t txlen,
void* rx, const size_t rxlen, const uint32_t tmo )
{
bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo);
if (rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo);
return rv;
}
//----------------------------------------------------------------------------- ----------------------------------------
# define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__)
# define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__)
# define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__)
# define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__)
#endif //ENABLE_WORKAROUND
//+============================================================================ ========================================
// Some devices take a moment to respond to read requests
// The puts a delay between the address being set and the data being read
//
static inline
bool furi_hal_i2c_trxd ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
const void* tx, const size_t txlen,
void* rx, const size_t rxlen, const uint32_t tmo, const uint32_t us )
{
bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo);
if (rv) {
furi_delay_us(us);
rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo);
}
return rv;
}
#endif //I2C_WORKAROUND_H_