Open FFBoard
Open source force feedback firmware
ffb_defs.h
Go to the documentation of this file.
1/*
2 * ffb_defs.h
3 *
4 * Created on: Feb 9, 2020
5 * Author: Yannick
6 */
7
8#ifndef FFB_DEFS_H_
9#define FFB_DEFS_H_
10
11#include "cppmain.h"
12#include "Filters.h"
13#include "constants.h" // For #define MAX_AXIS
14#define FFB_ID_OFFSET 0x00
15#define MAX_EFFECTS 40
16
17// HID Descriptor definitions - Axes
18#define HID_USAGE_X 0x30
19#define HID_USAGE_Y 0x31
20#define HID_USAGE_Z 0x32
21#define HID_USAGE_RX 0x33
22#define HID_USAGE_RY 0x34
23#define HID_USAGE_RZ 0x35
24#define HID_USAGE_SL0 0x36
25#define HID_USAGE_SL1 0x37
26#define HID_USAGE_WHL 0x38
27#define HID_USAGE_POV 0x39
28
29// HID Descriptor definitions - FFB Effects
30#define HID_USAGE_CONST 0x26 // Usage ET Constant Force
31#define HID_USAGE_RAMP 0x27 // Usage ET Ramp
32#define HID_USAGE_SQUR 0x30 // Usage ET Square
33#define HID_USAGE_SINE 0x31 // Usage ET Sine
34#define HID_USAGE_TRNG 0x32 // Usage ET Triangle
35#define HID_USAGE_STUP 0x33 // Usage ET Sawtooth Up
36#define HID_USAGE_STDN 0x34 // Usage ET Sawtooth Down
37#define HID_USAGE_SPRNG 0x40 // Usage ET Spring
38#define HID_USAGE_DMPR 0x41 // Usage ET Damper
39#define HID_USAGE_INRT 0x42 // Usage ET Inertia
40#define HID_USAGE_FRIC 0x43 // Usage ET Friction
41
42
43// HID Descriptor definitions - FFB Report IDs
44#define HID_ID_STATE 0x02 // Usage PID State report
45
46#define HID_ID_EFFREP 0x01 // Usage Set Effect Report
47#define HID_ID_ENVREP 0x02 // Usage Set Envelope Report
48#define HID_ID_CONDREP 0x03 // Usage Set Condition Report
49#define HID_ID_PRIDREP 0x04 // Usage Set Periodic Report
50#define HID_ID_CONSTREP 0x05 // Usage Set Constant Force Report
51#define HID_ID_RAMPREP 0x06 // Usage Set Ramp Force Report
52#define HID_ID_CSTMREP 0x07 // Usage Custom Force Data Report
53#define HID_ID_SMPLREP 0x08 // Usage Download Force Sample
54#define HID_ID_EFOPREP 0x0A // Usage Effect Operation Report
55#define HID_ID_BLKFRREP 0x0B // Usage PID Block Free Report
56#define HID_ID_CTRLREP 0x0C // Usage PID Device Control
57#define HID_ID_GAINREP 0x0D // Usage Device Gain Report
58#define HID_ID_SETCREP 0x0E // Usage Set Custom Force Report
59// Features
60#define HID_ID_NEWEFREP 0x11 // Usage Create New Effect Report
61#define HID_ID_BLKLDREP 0x12 // Usage Block Load Report
62#define HID_ID_POOLREP 0x13 // Usage PID Pool Report
63
64// Control
65#define HID_ID_CUSTOMCMD 0xAF // Custom cmd (old. reserved)
66#define HID_ID_HIDCMD 0xA1 // HID cmd
67#define HID_ID_STRCMD 0xAC // HID cmd as string. reserved
68//#define HID_ID_CUSTOMCMD_IN 0xA2 // Custom cmd in. reserved
69//#define HID_ID_CUSTOMCMD_OUT 0xA1 // Custom cmd out. reserved
70
71
72#define FFB_EFFECT_NONE 0x00
73#define FFB_EFFECT_CONSTANT 0x01
74#define FFB_EFFECT_RAMP 0x02
75#define FFB_EFFECT_SQUARE 0x03
76#define FFB_EFFECT_SINE 0x04
77#define FFB_EFFECT_TRIANGLE 0x05
78#define FFB_EFFECT_SAWTOOTHUP 0x06
79#define FFB_EFFECT_SAWTOOTHDOWN 0x07
80#define FFB_EFFECT_SPRING 0x08
81#define FFB_EFFECT_DAMPER 0x09
82#define FFB_EFFECT_INERTIA 0x0A
83#define FFB_EFFECT_FRICTION 0x0B
84#define FFB_EFFECT_CUSTOM 0x0C
85
86#define HID_ACTUATOR_POWER 0x08
87#define HID_SAFETY_SWITCH 0x04
88#define HID_ENABLE_ACTUATORS 0x02
89#define HID_EFFECT_PAUSE 0x01
90#define HID_ENABLE_ACTUATORS_MASK 0xFD
91#define HID_EFFECT_PLAYING 0x10
92
93#define HID_DIRECTION_ENABLE 0x04
94#define FFB_EFFECT_DURATION_INFINITE 0xffff
95
96// Only include these for cpp
97#ifdef __cplusplus
98
99// HID gamepad report
100
101
102struct __attribute__((__packed__)) reportHID_t {
103 uint8_t id = 1;
104 uint64_t buttons = 0;
105 int16_t X = 0;
106 int16_t Y = 0;
107 int16_t Z = 0;
108 int16_t RX = 0;
109 int16_t RY = 0;
110 int16_t RZ = 0;
111 int16_t Dial = 0;
112 int16_t Slider = 0;
113};
114
115/*
116 * Helper function to access analog axes in packed HID report struct
117 */
118inline void setHidReportAxis(reportHID_t *report, uint8_t idx, int16_t val){
119 switch(idx){
120 case 0:
121 report->X = val;
122 break;
123 case 1:
124 report->Y = val;
125 break;
126 case 2:
127 report->Z = val;
128 break;
129 case 3:
130 report->RX = val;
131 break;
132 case 4:
133 report->RY = val;
134 break;
135 case 5:
136 report->RZ = val;
137 break;
138 case 6:
139 report->Dial = val;
140 break;
141 case 7:
142 report->Slider = val;
143 break;
144 default:
145 return;
146 }
147}
148
149typedef struct
150{
151 const uint8_t reportId = HID_ID_STATE+FFB_ID_OFFSET;
152 //uint8_t effectBlockIndex = 1; //EffectId
153 uint8_t status = (HID_ACTUATOR_POWER) | (HID_ENABLE_ACTUATORS); // Bits: 0=Device Paused,1=Actuators Enabled,2=Safety Switch,3=Actuator Power, 4=Effect Playing
154
155} __attribute__((packed)) reportFFB_status_t;
156
157
158
159typedef struct
160 {
161 uint8_t reportId = 1;
162 uint8_t effectBlockIndex = 0; // 1..max_effects
163 uint8_t effectType = 0;
164 uint16_t duration = 0; // 0..32767 ms
165 uint16_t triggerRepeatInterval = 0; // 0..32767 ms
166 uint16_t samplePeriod = 0; // 0..32767 ms
167 uint16_t startDelay = 0; // 0..32767 ms
168 uint8_t gain = 255; // 0..255 scaler
169 uint8_t triggerButton = 0; // button ID. unused
170 uint8_t enableAxis = 0; // bits: 0=X, 1=Y, 2=DirectionEnable
171 uint16_t directionX = 0; // angle (0=0 .. 36000=360deg)
172 uint16_t directionY = 0; // angle (0=0 .. 36000=360deg) TODO axes are last bytes in struct if fewer axes are used. use different report if this is not enough anymore!
173//#if MAX_AXIS == 3
174// uint8_t directionZ = 0; // angle (0=0 .. 255=360deg)
175//#endif
176 // uint16_t typeSpecificBlockOffsetX = 0; // Needed?
177 // uint16_t typeSpecificBlockOffsetY = 0;
178// uint16_t startDelay; // 0..32767 ms
179} __attribute__((packed)) FFB_SetEffect_t;
180
181typedef struct
182 {
183 uint8_t reportId;
184 uint8_t effectBlockIndex; // 1..max_effects
185 uint8_t parameterBlockOffset; // bits: 0..3=parameterBlockOffset, 4..5=instance1, 6..7=instance2
186 int16_t cpOffset; // Center
187 int16_t positiveCoefficient; // Scaler for positive range
189 uint16_t positiveSaturation; // Clipping point for positive range
191 uint16_t deadBand;
192} __attribute__((packed)) FFB_SetCondition_Data_t;
193
194
195typedef struct
196 {
197 //uint8_t reportId; // ID removed by tinyusb
198 uint8_t effectType; // Effect type ID
199 uint16_t byteCount; // Size of custom effects
200} __attribute__((packed)) FFB_CreateNewEffect_Feature_Data_t;
201
202// Feature GET report
203typedef struct
204 {
205 //uint8_t reportId = HID_ID_BLKLDREP; // No report ID for tinyusb feature GET
206 uint8_t effectBlockIndex; // 1..max_effects
207 uint8_t loadStatus; // 1=Success,2=Full,3=Error
209} __attribute__((packed)) FFB_BlockLoad_Feature_Data_t;
210
211typedef struct
212 {
213 //uint8_t reportId = HID_ID_POOLREP; // No report ID for tinyusb feature GET
214 uint16_t ramPoolSize = MAX_EFFECTS;
215 uint8_t maxSimultaneousEffects = MAX_EFFECTS;
216 uint8_t memoryManagement = 1; // 0=DeviceManagedPool (0/1), 1=SharedParameterBlocks (0/1)
217} __attribute__((packed)) FFB_PIDPool_Feature_Data_t;
218
219
220typedef struct
221 {
222 uint8_t reportId;
223 uint8_t effectBlockIndex;
224 uint16_t magnitude;
225 int16_t offset;
226 uint16_t phase; // degrees
227 uint32_t period; // 0..32767 ms
228} __attribute__((packed)) FFB_SetPeriodic_Data_t;
229
230typedef struct
231{
232 uint8_t reportId;
233 uint8_t effectBlockIndex;
234 uint16_t attackLevel;
235 uint16_t fadeLevel;
236 uint32_t attackTime;
237 uint32_t fadeTime;
238} __attribute__((packed)) FFB_SetEnvelope_Data_t;
239
240typedef struct
241{
242 uint8_t reportId;
243 uint8_t effectBlockIndex;
244 uint16_t startLevel;
245 uint16_t endLevel;
246} __attribute__((packed)) FFB_SetRamp_Data_t;
247
248typedef struct
249{
250 int16_t cpOffset = 0; // Center point
251 int16_t positiveCoefficient = 0;
252 int16_t negativeCoefficient = 0;
253 uint16_t positiveSaturation = 0;
254 uint16_t negativeSaturation = 0;
255 uint16_t deadBand = 0;
256
257 bool isActive(){ // Condition is active if either coefficient is not zero
258 return (positiveCoefficient != 0 && positiveSaturation != 0) || (negativeCoefficient != 0 && negativeSaturation != 0);
259 }
261
262typedef struct
263{
264 uint8_t reportId;
265 uint8_t effectBlockIndex;
266 uint8_t state;
267 uint8_t loopCount;
268} __attribute__((packed)) FFB_EffOp_Data_t;
269
270// Internal struct for storing effects
271typedef struct
272{
273 volatile uint8_t state = 0;
274 uint8_t type = FFB_EFFECT_NONE; // Type
275 int16_t offset = 0; // Center point
276 uint8_t gain = 255; // Scaler. often unused
277 int16_t magnitude = 0; // High res intensity of effect
278 int16_t startLevel = 0; // Ramp effect
279 int16_t endLevel = 0; // Ramp effect
280 float axisMagnitudes[MAX_AXIS] = {0}; // 0=0,100%=1
281
282 FFB_Effect_Condition conditions[MAX_AXIS];
283 int16_t phase = 0;
284 uint16_t period = 0;
285 uint32_t duration = FFB_EFFECT_DURATION_INFINITE; // Duration in ms
286 uint16_t attackLevel = 0, fadeLevel = 0; // Envelope effect
287 uint32_t attackTime = 0, fadeTime = 0; // Envelope effect
288
289 std::unique_ptr<Biquad> filter[MAX_AXIS] = { nullptr }; // Optional filter
290 uint16_t startDelay = 0;
291 uint32_t startTime = 0; // Elapsed time in ms before effect starts
292 uint16_t samplePeriod = 0;
293 bool useEnvelope = false;
294 bool useSingleCondition = true;
295} FFB_Effect;
296
297
298
299// --------------- Effects------------------------
300typedef struct
301 {
302 uint8_t reportId;
303 uint8_t effectBlockIndex; // 1..max_effects
304 int16_t magnitude; // High res intensity
305} __attribute__((packed)) FFB_SetConstantForce_Data_t;
306
307#endif //c++
308
309#endif /* FFB_DEFS_H_ */
void setHidReportAxis(reportHID_t *report, uint8_t idx, int16_t val)
Definition: ffb_defs.h:118
struct __attribute__((__packed__)) reportHID_t
Definition: ffb_defs.h:102
int16_t positiveCoefficient
Definition: ffb_defs.h:187
uint8_t parameterBlockOffset
Definition: ffb_defs.h:185
uint16_t startLevel
Definition: ffb_defs.h:244
uint32_t fadeTime
Definition: ffb_defs.h:237
uint16_t negativeSaturation
Definition: ffb_defs.h:190
uint16_t ramPoolAvailable
Definition: ffb_defs.h:208
uint16_t magnitude
Definition: ffb_defs.h:224
uint16_t phase
Definition: ffb_defs.h:226
uint32_t attackTime
Definition: ffb_defs.h:236
int16_t offset
Definition: ffb_defs.h:225
int16_t magnitude
Definition: ffb_defs.h:304
uint8_t loopCount
Definition: ffb_defs.h:267
uint8_t loadStatus
Definition: ffb_defs.h:207
uint8_t state
Definition: ffb_defs.h:266
uint16_t fadeLevel
Definition: ffb_defs.h:235
int16_t negativeCoefficient
Definition: ffb_defs.h:188
uint16_t endLevel
Definition: ffb_defs.h:245
int16_t cpOffset
Definition: ffb_defs.h:186
uint16_t deadBand
Definition: ffb_defs.h:191
uint16_t positiveSaturation
Definition: ffb_defs.h:189
uint16_t attackLevel
Definition: ffb_defs.h:234
uint16_t byteCount
Definition: ffb_defs.h:199
uint32_t period
Definition: ffb_defs.h:227