Open FFBoard
Open source force feedback firmware
PCF8574.cpp
Go to the documentation of this file.
1/*
2 * PCF8574.cpp
3 *
4 * Created on: 10.03.2022
5 * Author: Yannick
6 */
7
8
9#include "PCF8574.h"
10#include "math.h"
11#ifdef I2C_PORT
12PCF8574::PCF8574(I2CPort &port) : port(port) {
13
14 port.takePort(this);
15}
16
18 port.freePort(this);
19}
20
21//void PCF8574::configurePort(bool fastMode){
22// config.ClockSpeed = fastMode ? 400000 : 100000;
23// config.DutyCycle = I2C_DUTYCYCLE_2;
24// config.OwnAddress1 = 0;
25// config.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
26// config.DualAddressMode = I2C_DUALADDRESS_DISABLE;
27// config.OwnAddress2 = 0;
28// config.GeneralCallMode = I2C_GENERALCALL_DISABLE;
29// config.NoStretchMode = I2C_NOSTRETCH_ENABLE;
30// port.configurePort(&config);
31//}
32
33uint8_t PCF8574::readByte(const uint8_t devAddr){
34 uint8_t data = 0;
35 port.receiveMaster(this,devAddr, &data, 1, 250);
36 return data;
37}
38
39void PCF8574::readByteIT(const uint8_t devAddr,uint8_t* data){
40 port.receiveMasterIT(this,devAddr, data, 1);
41}
42
43void PCF8574::writeByteIT(const uint8_t devAddr,uint8_t* data){
44 port.transmitMasterIT(this,devAddr, data, 1);
45}
46
47void PCF8574::writeByte(const uint8_t devAddr,uint8_t data){
49 port.transmitMaster(this,devAddr , &lastWriteData, 1, 250);
50}
51
52//void PCF8574::startI2CTransfer(I2CPort* port){
53// transferActive = true;
54//}
55//
56//void PCF8574::endI2CTransfer(I2CPort* port){
57// transferActive = false;
58//}
59
60
61#ifdef PCF8574BUTTONS
63 .name = "I2C PCF8574" ,
64 .id=CLSID_BTN_PCF,
65 };
67 return info;
68}
69
70
71PCF8574Buttons::PCF8574Buttons() : PCF8574(i2cport) , CommandHandler("pcfbtn", CLSID_BTN_PCF, 0), Thread("pcfbtn", 64, 20) {
74 registerCommand("btnnum", PCF8574Buttons_commands::btnnum, "Amount of buttons",CMDFLAG_GET | CMDFLAG_SET);
75 registerCommand("invert", PCF8574Buttons_commands::invert, "Invert buttons",CMDFLAG_GET | CMDFLAG_SET);
76 registerCommand("speed", PCF8574Buttons_commands::speed, "400kb/s mode",CMDFLAG_GET | CMDFLAG_SET);
78
79 this->Start();
80}
81
83
84}
85
86// Handles starting next transfer for >1 byte transfers
88 while(true){
90 if(lastByte+1 < this->numBytes){
91 // Next transfer
92 lastData = 0;
93 readByteIT(0x20+ ++lastByte, &lastData);
94 }else{
95 lastByte = 0;
96 readingData = false; // Done
98 }
99 }
100}
101
102// i2c complete interrupt signals thread to start next transfer
104 if(port != &this->port || !readingData){
105 return;
106 }
107 lastSuccess = HAL_GetTick();
108 currentButtons |= (uint64_t)lastData << (lastByte*8);
110
111}
112
114 uint16_t conf1 = (btnnum-1) & 0x3F;
115 conf1 |= (invert & 0x1) << 6;
116 //conf1 |= (fastmode & 0x1) << 7;
117 Flash_Write(ADR_PCFBTN_CONF1, conf1);
118}
119
121 uint16_t conf1;
122 if(Flash_Read(ADR_PCFBTN_CONF1, &conf1)){
123 setBtnNum((conf1 & 0x3F) +1);
124 invert = (conf1 >> 6) & 0x1;
125 //fastmode = (conf1 >> 7) & 0x1;
126 }
127}
128
129
131 readingData = false;
132 port->resetPort();
133 lastSuccess = HAL_GetTick();
134}
135
136uint8_t PCF8574Buttons::readButtons(uint64_t* buf){
137
138 if(invert){
139 *buf = ~lastButtons;
140 }else{
141 *buf = lastButtons;
142 }
143 *buf &= mask;
144
145
146 // Update
147 if(HAL_GetTick()-lastSuccess > timeout && readingData){
148 readingData = false;
149 port.resetPort();
150 lastSuccess = HAL_GetTick();
151 }
152 if(!port.isTaken() && !readingData){
153 readingData = true;
154 //lastButtons = 0;
155 currentButtons = 0;
156 lastByte = 0;
157 readByteIT(0x20, &lastData); // Read first address
158 }
159 return btnnum;
160}
161
162
164 // Amount of readable buttons
165 return btnnum;
166}
167
174 num = clip<uint8_t,uint8_t>(num, 1, 64); // up to 8 PCF8574 can be chained resulting in 64 buttons
175 this->btnnum = num;
176 this->numBytes = 1+((num-1)/8);
177
178 if(num == 64){ // Special case
179 mask = 0xffffffffffffffff;
180 }else{
181 mask = (uint64_t)pow<uint64_t>(2,num)-(uint64_t)1; // Must be done completely in 64 bit!
182 }
183 port.resetPort();
184}
185
186CommandStatus PCF8574Buttons::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
187
188 switch(static_cast<PCF8574Buttons_commands>(cmd.cmdId)){
189
191 if(cmd.type == CMDtype::get){
192 replies.emplace_back(this->btnnum);
193 }else if(cmd.type == CMDtype::set){
194 setBtnNum(cmd.val);
195 }
196 break;
198 return handleGetSet(cmd, replies, this->invert);
199 break;
200
202 if(cmd.type == CMDtype::get){
203 replies.emplace_back(this->port.getSpeedPreset());
204 }else if(cmd.type == CMDtype::set){
206 }
207 break;
208
209
210 default:
212 }
213 return CommandStatus::OK;
214}
215#endif
216#endif //i2c
CommandStatus
uint16_t btnnum
Definition: ButtonSource.h:38
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
Definition: I2C.h:43
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
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
void freePort(I2CDevice *device)
Definition: I2C.cpp:132
void takePort(I2CDevice *device)
Definition: I2C.cpp:117
void resetPort()
Definition: I2C.cpp:108
void setSpeedPreset(uint8_t preset)
Definition: I2C.cpp:65
bool transmitMasterIT(I2CDevice *device, const uint16_t addr, uint8_t *pData, const uint16_t size, bool shiftAddr=true)
Definition: I2C.cpp:173
uint8_t getSpeedPreset()
Definition: I2C.cpp:74
bool isTaken()
Definition: I2C.cpp:276
uint8_t numBytes
Definition: PCF8574.h:84
void i2cError(I2CPort *port)
Definition: PCF8574.cpp:130
void Run()
Definition: PCF8574.cpp:87
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies) override
Definition: PCF8574.cpp:186
uint64_t mask
Definition: PCF8574.h:85
PCF8574Buttons_commands
Definition: PCF8574.h:55
void setBtnNum(uint8_t num)
Definition: PCF8574.cpp:173
virtual const ClassIdentifier getInfo()
Definition: PCF8574.cpp:66
bool invert
Definition: PCF8574.h:83
uint8_t lastData
Definition: PCF8574.h:90
static ClassIdentifier info
Definition: PCF8574.h:73
uint8_t lastByte
Definition: PCF8574.h:89
void saveFlash()
Definition: PCF8574.cpp:113
uint64_t lastButtons
Definition: PCF8574.h:86
uint8_t readButtons(uint64_t *buf)
Definition: PCF8574.cpp:136
const uint32_t timeout
Definition: PCF8574.h:93
virtual ~PCF8574Buttons()
Definition: PCF8574.cpp:82
uint64_t currentButtons
Definition: PCF8574.h:87
void restoreFlash()
Definition: PCF8574.cpp:120
uint16_t getBtnNum()
Definition: PCF8574.cpp:163
volatile bool readingData
Definition: PCF8574.h:94
uint32_t lastSuccess
Definition: PCF8574.h:92
void i2cRxCompleted(I2CPort *port)
Definition: PCF8574.cpp:103
void readByteIT(const uint8_t devAddr, uint8_t *data)
Definition: PCF8574.cpp:39
PCF8574(I2CPort &port)
Definition: PCF8574.cpp:12
virtual ~PCF8574()
Definition: PCF8574.cpp:17
void writeByteIT(const uint8_t devAddr, uint8_t *data)
Definition: PCF8574.cpp:43
uint8_t readByte(const uint8_t devAddr)
Definition: PCF8574.cpp:33
uint8_t lastWriteData
Definition: PCF8574.h:46
void writeByte(const uint8_t devAddr, uint8_t data)
Definition: PCF8574.cpp:47
I2CPort & port
Definition: PCF8574.h:42
uint32_t WaitForNotification(TickType_t Timeout=portMAX_DELAY)
Definition: thread.hpp:246
I2CPort i2cport
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