Open FFBoard
Open source force feedback firmware
FFBHIDMain.cpp
Go to the documentation of this file.
1/*
2 * FFBWheel.cpp
3 *
4 * Created on: 31.01.2020
5 * Author: Yannick / Lidders
6 */
7
8#include <FFBHIDMain.h>
9#include "voltagesense.h"
10#include "hid_device.h"
11#include "tusb.h"
12#include "usb_hid_ffb_desc.h"
13
14#include "cmsis_os.h"
15extern osThreadId_t defaultTaskHandle;
16
18
19
23FFBHIDMain::FFBHIDMain(uint8_t axisCount) :
24 Thread("FFBMAIN", 256, 30),
25 SelectableInputs(ButtonSource::all_buttonsources,AnalogSource::all_analogsources),
26 axisCount(axisCount)
27{
28
29 restoreFlashDelayed(); // Load parameters
31
32}
33
39void FFBHIDMain::setFFBEffectsCalc(std::shared_ptr<EffectsControlItf> ffb,std::shared_ptr<EffectsCalculator> effects_calc){
40 this->ffb = ffb;
41 this->effects_calc = effects_calc;
42 axes_manager = std::make_unique<AxesManager>(&control,effects_calc);
43 axes_manager->setAxisCount(axisCount);
44 this->Start();
45}
46
47
50}
51
56
57 Flash_Read(ADR_FFBWHEEL_BUTTONCONF, &this->btnsources);
59
60 Flash_Read(ADR_FFBWHEEL_ANALOGCONF, &this->ainsources);
62
63 uint16_t conf1 = 0;
64 if(Flash_Read(ADR_FFBWHEEL_CONF1,&conf1)){
65 uint8_t rateidx = conf1 & 0x3;
66 setReportRate(rateidx);
67 }
68
69}
74
75 Flash_Write(ADR_FFBWHEEL_BUTTONCONF,this->btnsources);
76 Flash_Write(ADR_FFBWHEEL_ANALOGCONF,this->ainsources);
77
78 uint8_t conf1 = 0;
79 conf1 |= usb_report_rate_idx & 0x3;
80 Flash_Write(ADR_FFBWHEEL_CONF1,conf1);
81}
82
83
84
86#ifdef E_STOP_Pin
87 bool estopState = HAL_GPIO_ReadPin(E_STOP_GPIO_Port, E_STOP_Pin) == GPIO_PIN_RESET;
88 if(estopState){ // Estop pressed at startup
89 emergencyStop(!estopState);
90// control.emergency = true; // Immediately enter emergency state but without notifying other classes yet
91 lastEstop = HAL_GetTick();
92 }
93#endif
94 while(true){
95 Delay(1);
97 }
98}
99
105 //logSerial("request update disabled");
108
109 }
111 //logSerial("Update disabled");
112 return;
113 }
114
116 control.resetEncoder = false;
117 axes_manager->resetPosZero();
118 }
119
120 //debugpin.set();
121 axes_manager->update();
122
124 report_rate_cnt = 0;
125 this->send_report();
126 }
127 if(!control.emergency){
128 axes_manager->updateTorque();
129
130 }else{
131 pulseClipLed();
132 }
133 //debugpin.reset();
134}
135
136
138 return this->ffb->getRate();
139}
140
142 return this->ffb->getFfbActive();
143}
144
149 // Check if HID command interface wants to send something and allow that if we did not skip too many reports
150 if(!tud_hid_n_ready(0) || ((reportSendCounter++ < usb_report_rate*2) && this->hidCommands->waitingToSend())){
151 return;
152 }
153 //Try semaphore
154// if(!sourcesSem.Take(10)){
155// return;
156// }
157 // Read buttons
158 reportHID.buttons = 0; // Reset buttons
159
160 uint64_t b = 0;
162 reportHID.buttons = b;
163
164 // Encoder
165 //axes_manager->addAxesToReport(analogAxesReport, &count);
166
167 std::vector<int32_t>* axes = axes_manager->getAxisValues();
168 uint8_t count = 0;
169 for(auto val : *axes){
170 setHidReportAxis(&reportHID,count++,val);
171 }
172
173 // Fill remaining values with analog inputs
175 for(int32_t val : *axes){
176 if(count >= analogAxisCount)
177 break;
178 setHidReportAxis(&reportHID,count++,val);
179 }
180// sourcesSem.Give();
181 // Fill rest
182 for(;count<analogAxisCount; count++){
183 setHidReportAxis(&reportHID,count,0);
184 }
185
186
187 /*
188 * Only send a new report if actually changed since last time or timeout and hid is ready
189 */
190 if( (reportSendCounter > 100/usb_report_rate || (memcmp(&lastReportHID,&reportHID,sizeof(reportHID_t)) != 0) ))
191 {
192
193
194 tud_hid_report(0, reinterpret_cast<uint8_t*>(&reportHID), sizeof(reportHID_t));
197
198 }
199
200}
201
205void FFBHIDMain::setReportRate(uint8_t rateidx){
206 rateidx = clip<uint8_t,uint8_t>(rateidx, 0,sizeof(usb_report_rates));
207 usb_report_rate_idx = rateidx;
208 usb_report_rate = usb_report_rates[rateidx]*HID_BINTERVAL;
209}
210
215 std::string s = "";
216 for(uint8_t i = 0 ; i < sizeof(usb_report_rates);i++){
217 s += std::to_string(1000/(HID_BINTERVAL*usb_report_rates[i])) + "Hz:"+std::to_string(i);
218 if(i < sizeof(usb_report_rates)-1)
219 s += ",";
220 }
221 return s;
222 }
223
225 control.emergency = !reset;
226 axes_manager->emergencyStop(reset);
227}
228
229//void FFBHIDMain::timerElapsed(TIM_HandleTypeDef* htim){
230//
231//}
232
233
240 return;
241 control.usb_disabled = true;
242 ffb->stop_FFB();
243 ffb->reset_ffb(); // Delete all effects
244 axes_manager->usbSuspend();
245}
246
251#ifdef E_STOP_Pin
252 if(control.emergency && HAL_GPIO_ReadPin(E_STOP_GPIO_Port, E_STOP_Pin) != GPIO_PIN_RESET){ // Reconnected after emergency stop
253 control.emergency = false;
254 }
255#endif
256 control.usb_disabled = false;
257 axes_manager->usbResume();
258}
259
260
261// External interrupt pins
262void FFBHIDMain::exti(uint16_t GPIO_Pin){
263 if(GPIO_Pin == BUTTON_A_Pin){
264 // Button down?
265 if(HAL_GPIO_ReadPin(BUTTON_A_GPIO_Port, BUTTON_A_Pin)){
266 this->control.resetEncoder = true;
267 }
268 }
269#ifdef E_STOP_Pin
270 if(GPIO_Pin == E_STOP_Pin){ // Emergency stop. low active
271// if(HAL_GPIO_ReadPin(E_STOP_GPIO_Port, E_STOP_Pin) == GPIO_PIN_RESET){
272 bool estopPinState = HAL_GPIO_ReadPin(E_STOP_GPIO_Port, E_STOP_Pin) == GPIO_PIN_RESET;
273 if(HAL_GetTick()-lastEstop > 1000 && estopPinState != this->control.emergency){ // Long debounce
274 lastEstop = HAL_GetTick();
275 if(estopPinState){
276 emergencyStop(false);
277 }else if(allowEstopReset){
278 emergencyStop(true);
279 }
280
281 }
282// }
283 }
284#endif
285}
286
287/*
288 * Error handling
289 */
290void FFBHIDMain::errorCallback(const Error &error, bool cleared){
291 if(error.type == ErrorType::critical){
292 if(!cleared){
293 this->emergencyStop(true);
294 }
295 }
296 if(error.code == ErrorCode::emergencyStop){
297 this->emergencyStop(cleared); // Clear Estop
298 }
299 if(!cleared){
300 pulseErrLed();
301 }
302}
303
osThreadId_t defaultTaskHandle
ErrorCode code
Definition: ErrorHandler.h:65
ErrorType type
Definition: ErrorHandler.h:66
std::shared_ptr< EffectsControlItf > ffb
Definition: FFBHIDMain.h:79
uint32_t getRate()
Definition: FFBHIDMain.cpp:137
void setReportRate(uint8_t rateidx)
Definition: FFBHIDMain.cpp:205
void Run()
Definition: FFBHIDMain.cpp:85
void usbResume()
Definition: FFBHIDMain.cpp:250
void usbSuspend()
Definition: FFBHIDMain.cpp:238
std::string usb_report_rates_names()
Definition: FFBHIDMain.cpp:214
void exti(uint16_t GPIO_Pin)
Definition: FFBHIDMain.cpp:262
volatile Control_t control
Definition: FFBHIDMain.h:84
uint8_t usb_report_rate
Definition: FFBHIDMain.h:94
void restoreFlash()
Definition: FFBHIDMain.cpp:55
uint8_t axisCount
Definition: FFBHIDMain.h:81
reportHID_t lastReportHID
Definition: FFBHIDMain.h:109
void saveFlash()
Definition: FFBHIDMain.cpp:73
volatile uint32_t lastEstop
Definition: FFBHIDMain.h:118
uint8_t usb_report_rate_idx
Definition: FFBHIDMain.h:95
std::unique_ptr< AxesManager > axes_manager
Definition: FFBHIDMain.h:102
const bool allowEstopReset
Definition: FFBHIDMain.h:86
void setFFBEffectsCalc(std::shared_ptr< EffectsControlItf > ffb, std::shared_ptr< EffectsCalculator > effects_calc)
Definition: FFBHIDMain.cpp:39
bool getFfbActive()
Definition: FFBHIDMain.cpp:141
const uint8_t analogAxisCount
Definition: FFBHIDMain.h:112
reportHID_t reportHID
Definition: FFBHIDMain.h:108
FFBHIDMain(uint8_t axisCount)
Definition: FFBHIDMain.cpp:23
virtual ~FFBHIDMain()
Definition: FFBHIDMain.cpp:48
void send_report()
Definition: FFBHIDMain.cpp:148
std::shared_ptr< EffectsCalculator > effects_calc
Definition: FFBHIDMain.h:80
uint8_t report_rate_cnt
Definition: FFBHIDMain.h:100
void updateControl()
Definition: FFBHIDMain.cpp:103
void errorCallback(const Error &error, bool cleared)
Definition: FFBHIDMain.cpp:290
void emergencyStop(bool reset)
Definition: FFBHIDMain.cpp:224
const uint8_t usb_report_rates[4]
Definition: FFBHIDMain.h:96
std::unique_ptr< HID_CommandInterface > hidCommands
Definition: FFBHIDMain.h:114
uint8_t reportSendCounter
Definition: FFBHIDMain.h:110
virtual void setAinTypes(uint16_t aintypes)
virtual void setBtnTypes(uint16_t btntypes)
virtual std::vector< int32_t > * getAnalogValues()
virtual void clearBtnTypes()
virtual uint8_t getButtonValues(uint64_t &values)
void Delay(const TickType_t Delay)
Definition: thread.hpp:352
void setHidReportAxis(reportHID_t *report, uint8_t idx, int16_t val)
Definition: ffb_defs.h:118
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
bool tud_hid_n_ready(uint8_t instance)
Definition: hid_device.c:104
static TU_ATTR_ALWAYS_INLINE bool tud_hid_report(uint8_t report_id, void const *report, uint16_t len)
Definition: hid_device.h:97
void pulseClipLed()
Definition: ledEffects.cpp:49
void pulseErrLed()
Definition: ledEffects.cpp:44
bool update_disabled
Definition: Axis.h:41
bool usb_disabled
Definition: Axis.h:40
bool emergency
Definition: Axis.h:39
bool request_update_disabled
Definition: Axis.h:42
bool resetEncoder
Definition: Axis.h:45