Open FFBoard
Open source force feedback firmware
I2C.cpp
Go to the documentation of this file.
1/*
2 * I2C.cpp
3 *
4 * Created on: 10.03.2022
5 * Author: Yannick
6 */
7
8#include <I2C.h>
9#ifdef I2CBUS
11 .name = "I2C port",
12 .id = CLSID_I2CPORT,
13 .visibility = ClassVisibility::visible};
14
15
16
17//static bool operator==(const I2C_InitTypeDef& lhs, const I2C_InitTypeDef& rhs) {
18// return lhs.AddressingMode == rhs.AddressingMode
19// && lhs.ClockSpeed == rhs.ClockSpeed
20// && lhs.DualAddressMode == rhs.DualAddressMode
21// && lhs.DutyCycle == rhs.DutyCycle
22// && lhs.GeneralCallMode == rhs.GeneralCallMode
23// && lhs.NoStretchMode == rhs.NoStretchMode
24// && lhs.OwnAddress1 == rhs.OwnAddress1
25// && lhs.OwnAddress2 == rhs.OwnAddress2;
26//}
27
28//static bool operator==(const I2C_InitTypeDef& lhs, const I2C_InitTypeDef& rhs) {
29// return memcmp(&lhs,&rhs,sizeof(I2C_InitTypeDef)) == 0;
30//}
31//
32
33
34
35I2CPort::I2CPort(I2C_HandleTypeDef &hi2c,const I2CPortHardwareConfig& presets,uint8_t instance) : CommandHandler("i2c", CLSID_I2CPORT, instance), hi2c(hi2c),presets(presets) {
37#ifdef I2C_COMMANDS_DISABLED_IF_NOT_USED
38 this->setCommandsEnabled(false);
39#endif
41}
42
44
45}
46
48 if(this->getCommandHandlerInfo()->instance != 0){
49 return; // Only first instance can save
50 }
51 uint16_t data = (this->speedPreset & 0b11); // 2 bits reserved. 1 used
52 Flash_Write(ADR_I2CCONF1, data);
53}
54
56 if(this->getCommandHandlerInfo()->instance != 0){
57 return; // Only first instance can save
58 }
59 uint16_t data;
60 if(Flash_Read(ADR_I2CCONF1, &data)){
61 setSpeedPreset(data & 0b11);
62 }
63}
64
65void I2CPort::setSpeedPreset(uint8_t preset){
66
67 speedPreset = std::min<uint8_t>(preset,presets.presets.size());
69
70 if(portUsers)
72}
73
75 return speedPreset;
76}
77
80 registerCommand("speed", I2CPort_commands::speed, "I2C speed preset", CMDFLAG_GET|CMDFLAG_SET|CMDFLAG_INFOSTRING);
81}
82
83CommandStatus I2CPort::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
84
85 switch(static_cast<I2CPort_commands>(cmd.cmdId)){
86
88 if(cmd.type == CMDtype::get){
89 replies.emplace_back(this->speedPreset);
90 }else if(cmd.type == CMDtype::set && presets.canChangeSpeed){
92 }else if(cmd.type == CMDtype::info){
93 for(uint8_t i = 0; i<presets.presets.size();i++){
94 replies.emplace_back(std::string(presets.presets[i].name) + ":" + std::to_string(i));
95 }
96 }
97 break;
98
99 default:
101 }
102 return CommandStatus::OK;
103}
104
109 configurePort(&this->config);
111}
112
118 if(portUsers++ == 0){
119 this->config = hi2c.Init;
120 //configurePort(&this->config);
121 setSpeedPreset(speedPreset); // Load speed and activate
122#ifdef I2C_COMMANDS_DISABLED_IF_NOT_USED
123 this->setCommandsEnabled(true);
124#endif
125 }
126}
127
133 if(portUsers>0){
134 portUsers--;
135 }
136 if(device == currentDevice){
137 currentDevice = nullptr; // invalidate pointer if a transfer was in progress
139 }
140 if(portUsers == 0){
141
142 HAL_I2C_DeInit(&hi2c);
143#ifdef I2C_COMMANDS_DISABLED_IF_NOT_USED
144 this->setCommandsEnabled(false);
145#endif
146 }
147
148}
149
150void I2CPort::configurePort(I2C_InitTypeDef* config){
151 if(config == nullptr){
152 return; // No need to reconfigure
153 }
154 this->config = *config;
155 hi2c.Init = this->config;
156 HAL_I2C_Init(&hi2c);
157}
158
159bool I2CPort::transmitMaster(I2CDevice* device,const uint16_t addr,uint8_t* pData,const uint16_t size,const uint32_t timeout,bool shiftAddr){
160 currentDevice = device;
161 device->startI2CTransfer(this);
162 bool flag = HAL_I2C_Master_Transmit(&this->hi2c, shiftAddr ? addr << 1 : addr, pData, size, timeout) == HAL_OK;
163 device->endI2CTransfer(this);
164 return flag;
165}
166
167bool I2CPort::transmitMasterDMA(I2CDevice* device,const uint16_t addr,uint8_t* pData,const uint16_t size,bool shiftAddr){
168 currentDevice = device;
169 device->startI2CTransfer(this);
170 return HAL_I2C_Master_Transmit_DMA(&this->hi2c, shiftAddr ? addr << 1 : addr, pData, size) == HAL_OK;
171}
172
173bool I2CPort::transmitMasterIT(I2CDevice* device,const uint16_t addr,uint8_t* pData,const uint16_t size,bool shiftAddr){
174 currentDevice = device;
175 device->startI2CTransfer(this);
176 return HAL_I2C_Master_Transmit_IT(&this->hi2c, shiftAddr ? addr << 1 : addr, pData, size) == HAL_OK;
177}
178
179bool I2CPort::receiveMaster(I2CDevice* device,const uint16_t addr,uint8_t* pData,const uint16_t size,const uint32_t timeout,bool shiftAddr){
180 currentDevice = device;
181 device->startI2CTransfer(this);
182 bool flag = HAL_I2C_Master_Receive(&this->hi2c, shiftAddr ? addr << 1 : addr, pData, size, timeout) == HAL_OK;
183 device->endI2CTransfer(this);
184 return flag;
185}
186
187bool I2CPort::receiveMasterDMA(I2CDevice* device,const uint16_t addr,uint8_t* pData,const uint16_t size,bool shiftAddr){
188 currentDevice = device;
189 device->startI2CTransfer(this);
190 return HAL_I2C_Master_Receive_DMA(&this->hi2c, shiftAddr ? addr << 1 : addr, pData, size) == HAL_OK;
191}
192
193bool I2CPort::receiveMasterIT(I2CDevice* device,const uint16_t addr,uint8_t* pData,const uint16_t size,bool shiftAddr){
194 currentDevice = device;
195 device->startI2CTransfer(this);
196 return HAL_I2C_Master_Receive_IT(&this->hi2c, shiftAddr ? addr << 1 : addr, pData, size) == HAL_OK;
197}
198
199
200bool I2CPort::writeMem(I2CDevice* device,const uint16_t devAddr,const uint16_t memAddr,const uint16_t memAddSize,uint8_t* pData,const uint16_t size,const uint32_t timeout,bool shiftAddr){
201 currentDevice = device;
202 device->startI2CTransfer(this);
203 bool flag = HAL_I2C_Mem_Write(&this->hi2c, shiftAddr ? devAddr << 1 : devAddr, memAddr, memAddSize, pData, size, timeout) == HAL_OK;
204 device->endI2CTransfer(this);
205 return flag;
206}
207
208bool I2CPort::readMem(I2CDevice* device,const uint16_t devAddr,const uint16_t memAddr,const uint16_t memAddSize,uint8_t* pData,const uint16_t size,const uint32_t timeout,bool shiftAddr){
209 currentDevice = device;
210 device->startI2CTransfer(this);
211 bool flag = HAL_I2C_Mem_Read(&this->hi2c, shiftAddr ? devAddr << 1 : devAddr, memAddr, memAddSize, pData, size, timeout) == HAL_OK;
212 device->endI2CTransfer(this);
213 return flag;
214}
215
216bool I2CPort::readMemIT(I2CDevice* device,const uint16_t devAddr,const uint16_t memAddr,const uint16_t memAddSize,uint8_t* pData,const uint16_t size,bool shiftAddr){
217 currentDevice = device;
218 device->startI2CTransfer(this);
219 bool flag = HAL_I2C_Mem_Read_IT(&this->hi2c, shiftAddr ? devAddr << 1 : devAddr, memAddr, memAddSize, pData, size) == HAL_OK;
220 //device->endI2CTransfer(this);
221 return flag;
222}
223
224bool I2CPort::writeMemIT(I2CDevice* device,const uint16_t devAddr,const uint16_t memAddr,const uint16_t memAddSize,uint8_t* pData,const uint16_t size,bool shiftAddr){
225 currentDevice = device;
226 device->startI2CTransfer(this);
227 bool flag = HAL_I2C_Mem_Write_IT(&this->hi2c, shiftAddr ? devAddr << 1 : devAddr, memAddr, memAddSize, pData, size) == HAL_OK;
228 //device->endI2CTransfer(this);
229 return flag;
230}
231
232bool I2CPort::isDeviceReady(I2CDevice* device,const uint16_t devAddr,const uint32_t trials,uint32_t timeout,bool shiftAddr){
233 currentDevice = device;
234 device->startI2CTransfer(this);
235 bool flag = HAL_I2C_IsDeviceReady(&this->hi2c, shiftAddr ? devAddr << 1 : devAddr, trials,timeout) == HAL_OK;
236 device->endI2CTransfer(this);
237 return flag;
238}
239
240void I2CPort::I2cTxCplt(I2C_HandleTypeDef *hi2c){
241 if (currentDevice == nullptr) {
242 return;
243 }
244
245 if (hi2c->Instance != this->hi2c.Instance) {
246 return;
247 }
250
251 currentDevice = nullptr;
252}
253
254void I2CPort::I2cRxCplt(I2C_HandleTypeDef *hi2c){
255 if (currentDevice == nullptr) {
256 return;
257 }
258
259 if (hi2c->Instance != this->hi2c.Instance) {
260 return;
261 }
264
265 currentDevice = nullptr;
266}
267
268void I2CPort::I2cError(I2C_HandleTypeDef *hi2c){
269 if (currentDevice){
270 currentDevice->i2cError(this);
271 }else{
272 resetPort();
273 }
274}
275
277 return hi2c.State != HAL_I2C_STATE_READY;
278}
279
281 bool isIsr = inIsr();
282
283 if(isIsr){
284 BaseType_t taskWoken = 0;
285 this->semaphore.TakeFromISR(&taskWoken);
286 portYIELD_FROM_ISR(taskWoken);
287 }else{
288 this->semaphore.Take();
289 }
290 //isTakenFlag = true;
291}
292
294 bool isIsr = inIsr();
295 //isTakenFlag = false;
296 if(isIsr){
297 BaseType_t taskWoken = 0;
298 this->semaphore.GiveFromISR(&taskWoken);
299 portYIELD_FROM_ISR(taskWoken);
300 }else{
301 this->semaphore.Give();
302 }
303
304}
305
307
308}
310
311}
312
314 port->takeSemaphore();
315}
316
318 port->giveSemaphore();
319}
320
321
323
324}
326
327}
329 port->resetPort();
330}
331#endif
CommandStatus
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
virtual void setCommandsEnabled(bool enable)
virtual CmdHandlerInfo * getCommandHandlerInfo()
Definition: I2C.h:106
virtual void i2cError(I2CPort *port)
Definition: I2C.cpp:328
virtual void i2cTxCompleted(I2CPort *port)
Definition: I2C.cpp:322
virtual void i2cRxCompleted(I2CPort *port)
Definition: I2C.cpp:325
virtual void startI2CTransfer(I2CPort *port)
Definition: I2C.cpp:313
virtual ~I2CDevice()
Definition: I2C.cpp:309
I2CDevice()
Definition: I2C.cpp:306
virtual void endI2CTransfer(I2CPort *port)
Definition: I2C.cpp:317
const std::span< const I2CPortHardwareConfig_preset > presets
Definition: I2C.h:39
I2CPortHardwareConfig_preset getPreset(uint8_t idx) const
Definition: I2C.h:37
const bool canChangeSpeed
Definition: I2C.h:36
Definition: I2C.h:43
bool writeMemIT(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:224
uint8_t speedPreset
Definition: I2C.h:100
cpp_freertos::BinarySemaphore semaphore
Definition: I2C.h:95
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
Definition: I2C.cpp:83
void registerCommands()
Definition: I2C.cpp:78
const I2CPortHardwareConfig & presets
Definition: I2C.h:102
virtual ~I2CPort()
Definition: I2C.cpp:43
void I2cError(I2C_HandleTypeDef *hi2c)
Definition: I2C.cpp:268
void takeSemaphore()
Definition: I2C.cpp:280
bool isDeviceReady(I2CDevice *device, const uint16_t devAddr, const uint32_t trials, uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:232
I2C_HandleTypeDef & hi2c
Definition: I2C.h:97
bool transmitMasterDMA(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:167
void giveSemaphore()
Definition: I2C.cpp:293
bool receiveMasterIT(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:193
bool receiveMaster(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, const uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:179
void restoreFlash()
Definition: I2C.cpp:55
int32_t portUsers
Definition: I2C.h:99
bool transmitMaster(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, const uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:159
bool readMem(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, const uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:208
void freePort(I2CDevice *device)
Definition: I2C.cpp:132
bool readMemIT(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:216
I2CPort(I2C_HandleTypeDef &hi2c, const I2CPortHardwareConfig &presets, uint8_t instance=0)
Definition: I2C.cpp:35
I2C_InitTypeDef config
Definition: I2C.h:101
void saveFlash()
Definition: I2C.cpp:47
void I2cTxCplt(I2C_HandleTypeDef *hi2c)
Definition: I2C.cpp:240
void takePort(I2CDevice *device)
Definition: I2C.cpp:117
void I2cRxCplt(I2C_HandleTypeDef *hi2c)
Definition: I2C.cpp:254
static ClassIdentifier info
Definition: I2C.h:89
bool writeMem(I2CDevice *device, const uint16_t devAddr, const uint16_t memAddr, const uint16_t memAddSize, uint8_t *pData, const uint16_t size, const uint32_t timeout, bool shiftAddr=true)
Definition: I2C.cpp:200
void configurePort(I2C_InitTypeDef *config)
Definition: I2C.cpp:150
void resetPort()
Definition: I2C.cpp:108
void setSpeedPreset(uint8_t preset)
Definition: I2C.cpp:65
bool receiveMasterDMA(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:187
I2CDevice * currentDevice
Definition: I2C.h:98
bool transmitMasterIT(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:173
I2CPort_commands
Definition: I2C.h:44
uint8_t getSpeedPreset()
Definition: I2C.cpp:74
bool isTaken()
Definition: I2C.cpp:276
bool GiveFromISR(BaseType_t *pxHigherPriorityTaskWoken)
Definition: csemaphore.cpp:76
bool TakeFromISR(BaseType_t *pxHigherPriorityTaskWoken)
Definition: csemaphore.cpp:56
bool Take(TickType_t Timeout=portMAX_DELAY)
Definition: csemaphore.cpp:46
static bool inIsr()
Definition: cppmain.h:41
static struct @612 data
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
const char * name
uint32_t cmdId