From f7114aad22dc01234a39d1eef805006a97d67d69 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 26 Aug 2024 11:46:03 +0200 Subject: [PATCH 01/40] Command interface buffer size changes --- Firmware/FFBoard/Inc/CmdParser.h | 2 ++ Firmware/FFBoard/Inc/CommandInterface.h | 4 ++-- Firmware/FFBoard/Src/CmdParser.cpp | 8 ++++---- Firmware/FFBoard/Src/CommandInterface.cpp | 2 +- .../FFBoard/UserExtensions/Src/FFBoardMain.cpp | 2 +- .../UserExtensions/Src/usb_descriptors.cpp | 15 +++++++-------- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Firmware/FFBoard/Inc/CmdParser.h b/Firmware/FFBoard/Inc/CmdParser.h index 48094d3c5..be3221884 100644 --- a/Firmware/FFBoard/Inc/CmdParser.h +++ b/Firmware/FFBoard/Inc/CmdParser.h @@ -17,7 +17,9 @@ #include "CommandHandler.h" #include "ringbufferwrapper.h" +#ifndef CMDPARSER_MAX_VALID_CAPACITY #define CMDPARSER_MAX_VALID_CAPACITY 2048 +#endif class CommandHandler; class CommandInterface; diff --git a/Firmware/FFBoard/Inc/CommandInterface.h b/Firmware/FFBoard/Inc/CommandInterface.h index d99ec7b92..b70a57da6 100644 --- a/Firmware/FFBoard/Inc/CommandInterface.h +++ b/Firmware/FFBoard/Inc/CommandInterface.h @@ -60,7 +60,7 @@ class StringCommandInterface : public CommandInterface{ CmdParser parser; // String parser }; - +#define CDC_CMD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 4096 : 1024) //receives bytes from mainclass. calls its own parser instance, calls global parser thread, passes replies back to cdc port. class CDC_CommandInterface : public StringCommandInterface,public cpp_freertos::Thread{ public: @@ -83,7 +83,7 @@ class CDC_CommandInterface : public StringCommandInterface,public cpp_freertos:: bool nextFormat = false; std::string sendBuffer; uint32_t bufferLength = 0; - const uint32_t maxSendBuffer = 1024; // Max buffered command size before sending immediately + const uint32_t maxSendBuffer = CDC_CMD_BUFFER_SIZE; // Max buffered command size before sending immediately }; diff --git a/Firmware/FFBoard/Src/CmdParser.cpp b/Firmware/FFBoard/Src/CmdParser.cpp index 73640b9fd..bd61b1206 100644 --- a/Firmware/FFBoard/Src/CmdParser.cpp +++ b/Firmware/FFBoard/Src/CmdParser.cpp @@ -155,8 +155,8 @@ bool CmdParser::parse(std::vector& commands){ // Check if conversion is even possible bool validPqm = (pqm != std::string::npos && (std::isdigit(word[pqm+1]) || (std::isdigit(word[pqm+2]) && (word[pqm+1] == '-' || word[pqm+1] == '+')) || ( std::isxdigit(word[pqm+2]) && word[pqm+1] == 'x'))); bool validPeq = (peq != std::string::npos && (std::isdigit(word[peq+1]) || (std::isdigit(word[peq+2]) && (word[peq+1] == '-' || word[peq+1] == '+')) || ( std::isxdigit(word[peq+2]) && word[peq+1] == 'x'))); - - if(validPqm && validPeq && peq < pqm && (abs(pqm - peq) > 1)){ // =? + int32_t pqm_peq_dist = (pqm - peq); + if(validPqm && validPeq && peq < pqm && (abs(pqm_peq_dist) > 1)){ // =? // Dual int64_t val; int64_t val2; @@ -167,9 +167,9 @@ bool CmdParser::parse(std::vector& commands){ } if(word[peq+1] == 'x'){ - val = (int64_t)std::strtoll(word.substr(peq+2, pqm-peq).c_str(),0,16); + val = (int64_t)std::strtoll(word.substr(peq+2, pqm_peq_dist).c_str(),0,16); }else{ - val = (int64_t)std::strtoll(word.substr(peq+1, pqm-peq).c_str(),0,10); + val = (int64_t)std::strtoll(word.substr(peq+1, pqm_peq_dist).c_str(),0,10); } cmdstring = word.substr(cmd_start, peq-cmd_start); diff --git a/Firmware/FFBoard/Src/CommandInterface.cpp b/Firmware/FFBoard/Src/CommandInterface.cpp index 9aa004c91..0427cd0d0 100644 --- a/Firmware/FFBoard/Src/CommandInterface.cpp +++ b/Firmware/FFBoard/Src/CommandInterface.cpp @@ -240,7 +240,7 @@ void StringCommandInterface::generateReplyFromCmd(std::string& replyPart,const P */ -CDC_CommandInterface::CDC_CommandInterface() : StringCommandInterface(1024), Thread("CDCCMD", 512, 37) { +CDC_CommandInterface::CDC_CommandInterface() : StringCommandInterface(CDC_CMD_BUFFER_SIZE), Thread("CDCCMD", 512, 37) { parser.setClearBufferTimeout(parserTimeout); this->Start(); } diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBoardMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBoardMain.cpp index da0b8da10..83c42dd0e 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBoardMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBoardMain.cpp @@ -14,7 +14,7 @@ ClassIdentifier FFBoardMain::info ={.name = "Basic (Failsafe)" ,.id=0}; -char FFBoardMain::cdcbuf[64]; +char FFBoardMain::cdcbuf[(TUD_OPT_HIGH_SPEED ? 512 : 64)]; diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp b/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp index 442758d04..ff31cf8ba 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp @@ -7,7 +7,6 @@ #include "tusb.h" #include "usb_descriptors.h" #include "usbd.h" -#include "stm32f4xx_hal.h" #include "main.h" #include "usb_hid_ffb_desc.h" @@ -51,7 +50,7 @@ const uint8_t usb_cdc_conf[] = TUD_CONFIG_DESCRIPTOR(1, 2, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), }; // Composite CDC and HID @@ -62,7 +61,7 @@ const uint8_t usb_cdc_hid_conf_1axis[] = TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), // HID Descriptor. EP 83 and 2 TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_1FFB_REPORT_DESC_SIZE, 0x83, 0x02, 64, HID_BINTERVAL), @@ -77,10 +76,10 @@ const uint8_t usb_cdc_hid_conf_2axis[] = TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), // HID Descriptor. EP 83 and 2 - TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_2FFB_REPORT_DESC_SIZE, 0x83, 0x02, 64, HID_BINTERVAL), + TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_2FFB_REPORT_DESC_SIZE, 0x83, 0x02,64, HID_BINTERVAL), }; #endif @@ -92,10 +91,10 @@ const uint8_t usb_cdc_hid_conf_gamepad[] = TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), // HID Descriptor. EP 83 and 2 - TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_GAMEPAD_REPORT_DESC_SIZE, 0x83, 0x02, 64, HID_BINTERVAL), + TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_GAMEPAD_REPORT_DESC_SIZE, 0x83, 0x02, (TUD_OPT_HIGH_SPEED ? 512 : 64), HID_BINTERVAL), }; #endif @@ -105,7 +104,7 @@ uint8_t const usb_cdc_midi_conf[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, 4, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MIDI_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), // Interface number, string index, EP Out & EP In address, EP size TUD_MIDI_DESCRIPTOR(2, 6, 0x02, 0x83, 64) }; From b33edde1e03d0bb60091f684842579392dbe0205 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Thu, 28 Sep 2023 13:38:47 +0200 Subject: [PATCH 02/40] SPI allow speed range --- Firmware/FFBoard/Inc/SPI.h | 3 ++- Firmware/FFBoard/Src/SPI.cpp | 4 ++-- Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Firmware/FFBoard/Inc/SPI.h b/Firmware/FFBoard/Inc/SPI.h index b1a063f79..0f6afedfe 100644 --- a/Firmware/FFBoard/Inc/SPI.h +++ b/Firmware/FFBoard/Inc/SPI.h @@ -14,6 +14,7 @@ #include "SpiHandler.h" #include "semaphore.hpp" +#include struct SPIConfig { SPIConfig(OutputPin cs,bool cspol = true) @@ -77,7 +78,7 @@ class SPIPort: public SpiHandler { bool hasFreePins(); uint32_t getBaseClk(); - std::pair getClosestPrescaler(float clock); + std::pair getClosestPrescaler(float clock,float min = 0, float max = INFINITY); SPI_HandleTypeDef* getPortHandle(); diff --git a/Firmware/FFBoard/Src/SPI.cpp b/Firmware/FFBoard/Src/SPI.cpp index 37185ea27..206ab2693 100644 --- a/Firmware/FFBoard/Src/SPI.cpp +++ b/Firmware/FFBoard/Src/SPI.cpp @@ -288,7 +288,7 @@ void SPIPort::SpiError(SPI_HandleTypeDef *hspi) { * Calculates the closest possible clock achievable with the current base clock and prescalers * Returns a pair of {prescaler,actual_clock} */ -std::pair SPIPort::getClosestPrescaler(float clock){ +std::pair SPIPort::getClosestPrescaler(float clock,float min,float max){ std::vector> distances; #if defined(SPI_BAUDRATEPRESCALER_2) distances.push_back({SPI_BAUDRATEPRESCALER_2,(baseclk/2.0)}); @@ -318,7 +318,7 @@ std::pair SPIPort::getClosestPrescaler(float clock){ std::pair bestVal = distances[0]; float bestDist = INFINITY; for(auto& val : distances){ - if(std::abs(clock-val.second) < bestDist){ + if(std::abs(clock-val.second) < bestDist && (val.second > min && val.second < max)){ bestDist = abs(clock-val.second); bestVal = val; } diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index 3b331632a..14b482e09 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -59,7 +59,7 @@ TMC4671::TMC4671(SPIPort& spiport,OutputPin cspin,uint8_t address) : spiConfig.peripheral.CLKPolarity = SPI_POLARITY_HIGH; spiConfig.peripheral.CLKPhase = SPI_PHASE_2EDGE; spiConfig.peripheral.NSS = SPI_NSS_SOFT; - spiConfig.peripheral.BaudRatePrescaler = spiPort.getClosestPrescaler(10e6).first; // 10MHz + spiConfig.peripheral.BaudRatePrescaler = spiPort.getClosestPrescaler(8e6,0,10e6).first; // 8 target, 10MHz max spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_MSB; spiConfig.peripheral.TIMode = SPI_TIMODE_DISABLE; spiConfig.peripheral.CRCCalculation = SPI_CRCCALCULATION_DISABLE; @@ -261,7 +261,7 @@ bool TMC4671::initialize(){ */ pulseClipLed(); - this->spiConfig.peripheral.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; + this->spiConfig.peripheral.BaudRatePrescaler = spiPort.getClosestPrescaler(1e6).first; // 1MHz target spiPort.configurePort(&this->spiConfig.peripheral); ES_TMCdetected = true; } @@ -3222,7 +3222,7 @@ void TMC4671::setUpExtEncTimer(){ // Setup timer this->externalEncoderTimer = &TIM_TMC; this->externalEncoderTimer->Instance->ARR = 200; // 200 = 5khz = 5 tmc cycles, 250 = 4khz, 240 = 6 tmc cycles - this->externalEncoderTimer->Instance->PSC = (SystemCoreClock / 2000000)+1; // timer running at half clock speed. 1µs ticks + this->externalEncoderTimer->Instance->PSC = ((TIM_TMC_BCLK)/1000000) +1; // 1µs ticks this->externalEncoderTimer->Instance->CR1 = 1; HAL_TIM_Base_Start_IT(this->externalEncoderTimer); #endif From fd7c1b3c923605d002917b653932ea23ae856e6d Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Sat, 21 Oct 2023 10:41:41 +0200 Subject: [PATCH 03/40] Task delay in i2c eeprom --- Firmware/FFBoard/Src/flash_helpers.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Firmware/FFBoard/Src/flash_helpers.cpp b/Firmware/FFBoard/Src/flash_helpers.cpp index cc8256ec0..4b0c2d051 100644 --- a/Firmware/FFBoard/Src/flash_helpers.cpp +++ b/Firmware/FFBoard/Src/flash_helpers.cpp @@ -121,7 +121,7 @@ bool Flash_Write(uint16_t adr,uint16_t dat){ bool res = false; while(curAdr < adr+dataLength){ while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){ - HAL_Delay(1); + vTaskDelay(1); } uint16_t wLen = std::min(dataLength,I2C_EEPROM_PAGEWRITE_SIZE - (adr % I2C_EEPROM_PAGEWRITE_SIZE)); @@ -147,7 +147,8 @@ bool Flash_Read(uint16_t adr,uint16_t *buf, bool checkempty){ adr *= sizeof(*buf)/I2C_EEPROM_DATA_SIZE; assert(adr < I2C_EEPROM_SIZE); while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){ - HAL_Delay(1); +// HAL_Delay(1); + vTaskDelay(1); } bool res = HAL_I2C_Mem_Read(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, I2C_EEPROM_OFS+adr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, 2, I2C_EEPROM_TIMEOUT) == HAL_OK; @@ -180,7 +181,7 @@ bool Flash_Format(){ flag = false; }else{ while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){ - HAL_Delay(1); + vTaskDelay(1); } } } From a6aa0e198da81f9b5329ec3a9baf4997b9b2d24f Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 23 Oct 2023 18:18:19 +0200 Subject: [PATCH 04/40] Dynamic biss-c speed presets --- Firmware/FFBoard/UserExtensions/Src/EncoderBissC.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/EncoderBissC.cpp b/Firmware/FFBoard/UserExtensions/Src/EncoderBissC.cpp index 218e3e03a..5f36b13b1 100644 --- a/Firmware/FFBoard/UserExtensions/Src/EncoderBissC.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/EncoderBissC.cpp @@ -101,16 +101,16 @@ void EncoderBissC::configSPI() { uint32_t prescale; switch (spiSpeed) { case 1 : - prescale = SPI_BAUDRATEPRESCALER_64; + prescale = spiPort.getClosestPrescaler(600000).first; break; case 2 : - prescale = SPI_BAUDRATEPRESCALER_32; + prescale = spiPort.getClosestPrescaler(1300000).first; break; case 3 : - prescale = SPI_BAUDRATEPRESCALER_16; + prescale = spiPort.getClosestPrescaler(2600000).first; break; default : - prescale = SPI_BAUDRATEPRESCALER_16; + prescale = spiPort.getClosestPrescaler(2600000).first; break; } From 7b994440be4522cdb520be0d686a7f2551e3fed2 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Fri, 8 Dec 2023 18:38:25 +0100 Subject: [PATCH 05/40] Add force erase flag for debugging --- Firmware/FFBoard/Src/cppmain.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Firmware/FFBoard/Src/cppmain.cpp b/Firmware/FFBoard/Src/cppmain.cpp index aa0f9a76d..cc760ff07 100644 --- a/Firmware/FFBoard/Src/cppmain.cpp +++ b/Firmware/FFBoard/Src/cppmain.cpp @@ -15,6 +15,7 @@ extern IWDG_HandleTypeDef hiwdg; // Watchdog bool running = true; bool mainclassChosen = false; +volatile bool forceErase = false; uint16_t main_id = 0; @@ -46,6 +47,10 @@ void cppmain() { Error_Handler(); } + if(forceErase){ + Flash_Format(); + } + // // Check if flash is initialized // uint16_t lastVersion = 0; // if(!Flash_Read(ADR_SW_VERSION, &lastVersion)){ // Version never written From ca8468fa14e850cdd2d97a9cf1320286bdd5ef4c Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 23 Jan 2024 19:45:35 +0100 Subject: [PATCH 06/40] Set initial spi device config to actual current port config --- Firmware/FFBoard/Src/SPI.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/FFBoard/Src/SPI.cpp b/Firmware/FFBoard/Src/SPI.cpp index 206ab2693..937cae4a8 100644 --- a/Firmware/FFBoard/Src/SPI.cpp +++ b/Firmware/FFBoard/Src/SPI.cpp @@ -328,9 +328,11 @@ std::pair SPIPort::getClosestPrescaler(float clock,float min,flo SPIDevice::SPIDevice(SPIPort& port,SPIConfig& spiConfig) : spiPort{port},spiConfig{spiConfig}{ spiPort.reserveCsPin(spiConfig.cs); + this->spiConfig.peripheral = port.getPortHandle()->Init; } SPIDevice::SPIDevice(SPIPort& port,OutputPin csPin) : spiPort{port},spiConfig{csPin}{ this->spiConfig.cs = csPin; + this->spiConfig.peripheral = port.getPortHandle()->Init; spiPort.reserveCsPin(spiConfig.cs); } SPIDevice::~SPIDevice() { From 67fb5fd829edc04291e3f75b1ec3b90311e762e4 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 30 Jan 2024 13:47:41 +0100 Subject: [PATCH 07/40] Add analog encoder cal skip option --- Firmware/FFBoard/UserExtensions/Inc/TMC4671.h | 3 ++- .../FFBoard/UserExtensions/Src/TMC4671.cpp | 26 +++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h index dd19e51fb..6afbd9114 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h +++ b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h @@ -97,6 +97,7 @@ struct TMC4671HardwareTypeConf{ uint8_t bbm = 20; float fluxDissipationScaler = 0.5; bool allowFluxDissipationDeactivation = true; + bool analogEncoderSkipCal = false; // Todo restrict allowed motor and encoder types }; @@ -237,7 +238,7 @@ struct TMC4671AENCConf{ int16_t AENC0_scale = 256; uint16_t AENC1_offset = 0x7fff; int16_t AENC1_scale = 256; - uint16_t AENC2_offset = 20000; + uint16_t AENC2_offset = 0x7fff; int16_t AENC2_scale = 256; int16_t nMask = 0; // 0x3c & 0xffff0000 diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index 14b482e09..8d9afb32d 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -651,7 +651,9 @@ void TMC4671::calibrateEncoder(){ // Report changes CommandHandler::broadcastCommandReply(CommandReply(abnconf.npol ? 1 : 0), (uint32_t)TMC4671_commands::encpol, CMDtype::get); }else if(conf.motconf.enctype == EncoderType_TMC::sincos || conf.motconf.enctype == EncoderType_TMC::uvw){ - calibrateAenc(); + if(!conf.hwconf.analogEncoderSkipCal){ + calibrateAenc(); + } }else if(conf.motconf.enctype == EncoderType_TMC::ext){ estimateExtEnc(); } @@ -1447,7 +1449,9 @@ void TMC4671::encoderInit(){ setPosSel(PosSelection::PhiM_aenc); // Mechanical Angle setVelSel(VelSelection::PhiM_aenc); // Mechanical Angle (RPM) //setup_AENC(aencconf); - calibrateAenc(); + if(!conf.hwconf.analogEncoderSkipCal){ + calibrateAenc(); + } } // find index @@ -2707,7 +2711,8 @@ void TMC4671::setHwType(TMC_HW_Ver type){ .brakeLimHigh = 50900, .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 50 // DMTH8003SPS need longer deadtime + .bbm = 50, // DMTH8003SPS need longer deadtime + .analogEncoderSkipCal = false }; this->conf.hwconf = newHwConf; break; @@ -2727,7 +2732,8 @@ void TMC4671::setHwType(TMC_HW_Ver type){ .brakeLimHigh = 50900, .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 40 + .bbm = 40, + .analogEncoderSkipCal = false }; this->conf.hwconf = newHwConf; break; @@ -2748,7 +2754,8 @@ void TMC4671::setHwType(TMC_HW_Ver type){ .brakeLimHigh = 50900, .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20 + .bbm = 20, + .analogEncoderSkipCal = false }; this->conf.hwconf = newHwConf; break; @@ -2769,7 +2776,8 @@ void TMC4671::setHwType(TMC_HW_Ver type){ .brakeLimHigh = 50900, .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20 + .bbm = 20, + .analogEncoderSkipCal = false }; this->conf.hwconf = newHwConf; break; @@ -2790,7 +2798,8 @@ void TMC4671::setHwType(TMC_HW_Ver type){ .brakeLimHigh = 50900, .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20 + .bbm = 20, + .analogEncoderSkipCal = false }; this->conf.hwconf = newHwConf; // Activates around 60V as last resort failsave. Check offsets from tmc leakage. ~ 1.426V @@ -2813,7 +2822,8 @@ void TMC4671::setHwType(TMC_HW_Ver type){ .brakeLimHigh = 52800, .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20 + .bbm = 20, + .analogEncoderSkipCal = false }; this->conf.hwconf = newHwConf; From f940e34ddb0c8aebcda4d46a8236bdebfc658b34 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Wed, 7 Feb 2024 17:37:28 +0100 Subject: [PATCH 08/40] .gitignore added Debug --- Firmware/.gitignore | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Firmware/.gitignore b/Firmware/.gitignore index 1757ea432..f6faee73a 100644 --- a/Firmware/.gitignore +++ b/Firmware/.gitignore @@ -1,4 +1,4 @@ -/*Debug/ +**/Debug/ **/Release/ **/.settings/ *.launch @@ -7,5 +7,4 @@ .mxproject fixlang /build/ -/OpenFFBoard/ -/*Targets/F407VG/*.cfg +/OpenFFBoard/ \ No newline at end of file From 4dd799e2608aaaeb166c60c481ac07c3ab2d294e Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 20 Feb 2024 17:18:29 +0100 Subject: [PATCH 09/40] TMC4671 restructured hw conf constants --- Firmware/FFBoard/UserExtensions/Inc/TMC4671.h | 112 +++++--- .../FFBoard/UserExtensions/Src/TMC4671.cpp | 245 +++++------------- .../UserExtensions/Src/TMC4671_configs.cpp | 117 +++++++++ 3 files changed, 268 insertions(+), 206 deletions(-) create mode 100644 Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp diff --git a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h index 6afbd9114..fb5563b33 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h +++ b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h @@ -21,7 +21,7 @@ #include "ExtiHandler.h" #include "SPI.h" #include "TimerHandler.h" - +#include #include "semaphore.hpp" #include #include "cpp_target_config.h" @@ -38,6 +38,20 @@ extern SPI_HandleTypeDef HSPIDRV; extern TIM_HandleTypeDef TIM_TMC; #endif +#ifndef TMC4671_DEFAULT_CURRENT_SCALER +#define TMC4671_DEFAULT_CURRENT_SCALER 0 +#endif +#ifndef TMC4671_DEFAULT_CLOCKFREQ +#define TMC4671_DEFAULT_CLOCKFREQ 25e6 +#endif +#ifndef TMC4671_DEFAULT_BBM +#define TMC4671_DEFAULT_BBM 20 +#endif +#ifndef TMC4671_DEFAULT_ANALOGENC_SKIPCAL +#define TMC4671_DEFAULT_ANALOGENC_SKIPCAL 0 +#endif + + enum class TMC_ControlState : uint32_t {uninitialized,waitPower,Shutdown,Running,EncoderInit,EncoderFinished,HardError,OverTemp,IndexSearch,FullCalibration,ExternalEncoderInit,Pidautotune}; enum class TMC_PwmMode : uint8_t {off = 0,HSlow_LShigh = 1, HShigh_LSlow = 2, res2 = 3, res3 = 4, PWM_LS = 5, PWM_HS = 6, PWM_FOC = 7}; @@ -46,7 +60,7 @@ enum class TMC_StartupType{NONE,coldStart,warmStart}; enum class TMC_GpioMode{DebugSpi,DSAdcClkOut,DSAdcClkIn,Aout_Bin,Ain_Bout,Aout_Bout,Ain_Bin}; -enum class MotorType : uint8_t {NONE=0,DC=1,STEPPER=2,BLDC=3,ERR}; +enum class MotorType : uint8_t {NONE=0,DC=1,STEPPER=2,BLDC=3}; enum class PhiE : uint8_t {ext=1,openloop=2,abn=3,hall=5,aenc=6,aencE=7,NONE,extEncoder}; enum class MotionMode : uint8_t {stop=0,torque=1,velocity=2,position=3,prbsflux=4,prbstorque=5,prbsvelocity=6,uqudext=8,encminimove=9,NONE}; enum class FFMode : uint8_t {none=0,velocity=1,torque=2}; @@ -54,18 +68,8 @@ enum class PosSelection : uint8_t {PhiE=0, PhiE_ext=1, PhiE_openloop=2, PhiE_abn enum class VelSelection : uint8_t {PhiE=0, PhiE_ext=1, PhiE_openloop=2, PhiE_abn=3, res1=4, PhiE_hal=5, PhiE_aenc=6, PhiA_aenc=7, res2=8, PhiM_abn=9, PhiM_abn2=10, PhiM_aenc=11, PhiM_hal=12}; enum class EncoderType_TMC : uint8_t {NONE=0,abn=1,sincos=2,uvw=3,hall=4,ext=5}; // max 7 -// Hardware versions for identifying different types. 31 versions valid +//// Hardware versions for identifying different types. 31 versions valid enum class TMC_HW_Ver : uint8_t {NONE=0,v1_0,v1_2,v1_2_2,v1_2_2_LEM20,v1_2_2_100mv,v1_3_66mv}; -// Selectable version names to be listed in commands -const std::vector> tmcHwVersionNames{ - std::make_pair(TMC_HW_Ver::NONE,"Undefined"), // Do not select. Default but disables some safety features - std::make_pair(TMC_HW_Ver::v1_0,"v1.0 AD8417"), - std::make_pair(TMC_HW_Ver::v1_2,"v1.2 AD8417"), - std::make_pair(TMC_HW_Ver::v1_2_2,"v1.2.2 LEM GO 10 (80mV/A)"), - std::make_pair(TMC_HW_Ver::v1_2_2_LEM20,"v1.2.2 LEM GO 20 (40mV/A)"), - std::make_pair(TMC_HW_Ver::v1_2_2_100mv,"v1.2/3 100mV/A"), - std::make_pair(TMC_HW_Ver::v1_3_66mv,"v1.3 ACS724 30A (66mV/A)") -}; struct TMC4671MotConf{ MotorType motor_type = MotorType::NONE; //saved @@ -81,24 +85,70 @@ struct TMC4671MotConf{ * Settings that depend on the hardware version */ struct TMC4671HardwareTypeConf{ - TMC_HW_Ver hwVersion = TMC_HW_Ver::NONE; + const char* name="CUSTOM"; + uint8_t hwVersion = 0; int adcOffset = 0; - float thermistor_R2 = 1500; - float thermistor_R = 22000; - float thermistor_Beta = 4300; - bool temperatureEnabled = false; // Enables temperature readings - float temp_limit = 90; - float currentScaler = 2.5 / (0x7fff * 60.0 * 0.0015); // Converts from adc counts to current in Amps - uint16_t brakeLimLow = 50700; - uint16_t brakeLimHigh = 50900; + + struct ThermistorSettings{ + float thermistor_R2 = 1500; + float thermistor_R = 22000; + float thermistor_Beta = 4300; + float temp_limit = 90; + bool temperatureEnabled = false; // Enables temperature readings + }; + ThermistorSettings thermistorSettings; + + + float currentScaler = TMC4671_DEFAULT_CURRENT_SCALER; // Converts from adc counts to current in Amps + uint16_t brakeLimLow = 0; + uint16_t brakeLimHigh = 0; float vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5); float vSenseMult = VOLTAGE_MULT_DEFAULT; - float clockfreq = 25e6; - uint8_t bbm = 20; + float clockfreq = TMC4671_DEFAULT_CLOCKFREQ; + uint8_t bbm = TMC4671_DEFAULT_BBM; float fluxDissipationScaler = 0.5; - bool allowFluxDissipationDeactivation = true; - bool analogEncoderSkipCal = false; - // Todo restrict allowed motor and encoder types + + /** + * Flags which features are enabled in this hardware type + */ + struct SupportedModes_s { + uint32_t mot_none: 1 = 1, + mot_dc : 1 = 1, + mot_bldc: 1 = 1, + mot_stepper:1 = 1, + + enc_none:1 = 1, + enc_abn:1 = 1, + enc_sincos:1 = 1, + enc_uvw:1 = 1, + enc_hall:1 = 1, + enc_ext:1 = 1, + + analog_enc_skip_cal:1 = TMC4671_DEFAULT_ANALOGENC_SKIPCAL, + + allowFluxDissipationDeactivation:1 = 1; + }; + SupportedModes_s flags; + bool isEncSupported(EncoderType_TMC type){ + switch(type){ + case EncoderType_TMC::NONE: return flags.enc_none; + case EncoderType_TMC::abn: return flags.enc_abn; + case EncoderType_TMC::ext: return flags.enc_ext; + case EncoderType_TMC::sincos: return flags.enc_sincos; + case EncoderType_TMC::hall: return flags.enc_hall; + case EncoderType_TMC::uvw: return flags.enc_uvw; + default: return false; + } + } + bool isMotSupported(MotorType type){ + switch(type){ + case MotorType::NONE: return flags.mot_none; + case MotorType::DC: return flags.mot_dc; + case MotorType::STEPPER: return flags.mot_stepper; + case MotorType::BLDC: return flags.mot_bldc; + default: return false; + } + } }; @@ -158,7 +208,6 @@ struct TMC4671MainConfig{ uint16_t adc_I1_offset = 33415; uint16_t adc_I0_scale = 256; uint16_t adc_I1_scale = 256; - bool canChangeHwType = true; // Allows changing the hardware version by commands bool encoderReversed = false; bool combineEncoder = false; bool invertForce = false; @@ -347,7 +396,7 @@ friend class TMCDebugBridge; TMC4671(SPIPort& spiport,OutputPin cspin,uint8_t address=1); - void setHwType(TMC_HW_Ver type); + void setHwType(uint8_t type); void setAddress(uint8_t address); @@ -571,6 +620,8 @@ friend class TMCDebugBridge; TMC4671* tmc; }; + static std::span tmc4671_hw_configs; // Can override in external target file + private: OutputPin enablePin = OutputPin(*DRV_ENABLE_GPIO_Port,DRV_ENABLE_Pin); const Error indexNotHitError = Error(ErrorCode::encoderIndexMissed,ErrorType::critical,"Encoder index missed"); @@ -601,6 +652,7 @@ friend class TMCDebugBridge; bool fullCalibrationInProgress = false; bool phiErestored = false; bool encHallRestored = false; + bool canChangeHwType = true; // Allows changing the hardware version by commands //int32_t phiEOffsetRestored = 0; //-0x8000 to 0x7fff uint8_t calibrationFailCount = 2; @@ -636,6 +688,8 @@ friend class TMCDebugBridge; void errorCallback(const Error &error, bool cleared); bool pidAutoTune(); + void replyHardwareVersions(const std::span& versions,std::vector& replies); + uint32_t initTime = 0; bool manualEncAlign = false; bool spiActive = false; // Flag for tx interrupt that the transfer was started by this instance diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index 8d9afb32d..f59aa92b0 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -9,7 +9,6 @@ #ifdef TMC4671DRIVER #include "ledEffects.h" #include "voltagesense.h" -//#include "stm32f4xx_hal_spi.h" #include #include #include "ErrorHandler.h" @@ -46,6 +45,7 @@ ClassIdentifier TMC4671::info = { }; + TMC4671::TMC4671(SPIPort& spiport,OutputPin cspin,uint8_t address) : CommandHandler("tmc", CLSID_MOT_TMC0,address-1), SPIDevice{motor_spi,cspin},Thread("TMC", TMC_THREAD_MEM, TMC_THREAD_PRIO) { @@ -347,7 +347,7 @@ bool TMC4671::initialize(){ * Not calibrated perfectly! */ float TMC4671::getTemp(){ - if(!this->conf.hwconf.temperatureEnabled){ + if(!this->conf.hwconf.thermistorSettings.temperatureEnabled){ return 0; } TMC4671HardwareTypeConf* hwconf = &conf.hwconf; @@ -358,10 +358,10 @@ float TMC4671::getTemp(){ if(adcval <= 0){ return 0.0; } - float r = hwconf->thermistor_R2 * (((float)43252 / (float)adcval)); //43252 equivalent ADC count if it was 3.3V and not 2.5V + float r = hwconf->thermistorSettings.thermistor_R2 * (((float)43252 / (float)adcval)); //43252 equivalent ADC count if it was 3.3V and not 2.5V // Beta - r = (1.0 / 298.15) + log(r / hwconf->thermistor_R) / hwconf->thermistor_Beta; + r = (1.0 / 298.15) + log(r / hwconf->thermistorSettings.thermistor_R) / hwconf->thermistorSettings.thermistor_Beta; r = 1.0 / r; r -= 273.15; return r; @@ -549,9 +549,9 @@ void TMC4671::Run(){ } // Temperature sense - if(conf.hwconf.temperatureEnabled){ + if(conf.hwconf.thermistorSettings.temperatureEnabled){ float temp = getTemp(); - if(temp > conf.hwconf.temp_limit){ + if(temp > conf.hwconf.thermistorSettings.temp_limit){ changeState(TMC_ControlState::OverTemp); pulseErrLed(); } @@ -651,7 +651,7 @@ void TMC4671::calibrateEncoder(){ // Report changes CommandHandler::broadcastCommandReply(CommandReply(abnconf.npol ? 1 : 0), (uint32_t)TMC4671_commands::encpol, CMDtype::get); }else if(conf.motconf.enctype == EncoderType_TMC::sincos || conf.motconf.enctype == EncoderType_TMC::uvw){ - if(!conf.hwconf.analogEncoderSkipCal){ + if(!conf.hwconf.flags.analog_enc_skip_cal){ calibrateAenc(); } }else if(conf.motconf.enctype == EncoderType_TMC::ext){ @@ -1364,8 +1364,8 @@ bool TMC4671::calibrateAdcOffset(uint16_t time){ uint32_t measurements_idle = 0; uint64_t totalA=0; uint64_t totalB=0; - bool allowTemp = conf.hwconf.temperatureEnabled; - conf.hwconf.temperatureEnabled = false; // Temp check interrupts adc + bool allowTemp = conf.hwconf.thermistorSettings.temperatureEnabled; + conf.hwconf.thermistorSettings.temperatureEnabled = false; // Temp check interrupts adc writeReg(0x03, 0); // Read raw adc PhiE lastphie = getPhiEtype(); MotionMode lastmode = getMotionMode(); @@ -1404,7 +1404,7 @@ bool TMC4671::calibrateAdcOffset(uint16_t time){ // setPwm(TMC_PwmMode::off); //Disable pwm // this->changeState(TMC_ControlState::HardError); adcCalibrated = false; - conf.hwconf.temperatureEnabled = allowTemp; + conf.hwconf.thermistorSettings.temperatureEnabled = allowTemp; return false; // An adc or shunt amp is likely broken. do not proceed. } conf.adc_I0_offset = offsetAidle; @@ -1415,7 +1415,7 @@ bool TMC4671::calibrateAdcOffset(uint16_t time){ setPhiEtype(lastphie); setMotionMode(lastmode,true); adcCalibrated = true; - conf.hwconf.temperatureEnabled = allowTemp; + conf.hwconf.thermistorSettings.temperatureEnabled = allowTemp; return true; } @@ -1449,7 +1449,7 @@ void TMC4671::encoderInit(){ setPosSel(PosSelection::PhiM_aenc); // Mechanical Angle setVelSel(VelSelection::PhiM_aenc); // Mechanical Angle (RPM) //setup_AENC(aencconf); - if(!conf.hwconf.analogEncoderSkipCal){ + if(!conf.hwconf.flags.analog_enc_skip_cal){ calibrateAenc(); } } @@ -1516,9 +1516,10 @@ void TMC4671::encoderInit(){ */ void TMC4671::setEncoderType(EncoderType_TMC type){ // If no external timer is set external encoder is not valid - if((!externalEncoderTimer || !externalEncoderAllowed()) && type == EncoderType_TMC::ext){ + if( !conf.hwconf.isEncSupported(type) || ((!externalEncoderTimer || !externalEncoderAllowed()) && type == EncoderType_TMC::ext)){ type = EncoderType_TMC::NONE; } + this->conf.motconf.enctype = type; this->statusMask.flags.AENC_N = 0; this->statusMask.flags.ENC_N = 0; @@ -2011,14 +2012,19 @@ bool TMC4671::externalEncoderAllowed(){ #ifndef TIM_TMC return false; #else - return allowExternalEncoder; + return allowExternalEncoder && conf.hwconf.flags.enc_ext; #endif } void TMC4671::setMotorType(MotorType motor,uint16_t poles){ + + if(!conf.hwconf.isMotSupported(motor)){ + motor = MotorType::NONE; + } if(motor == MotorType::DC){ poles = 1; } + conf.motconf.motor_type = motor; conf.motconf.pole_pairs = poles; uint32_t mtype = poles | ( ((uint8_t)motor&0xff) << 16); @@ -2686,167 +2692,47 @@ void TMC4671::restoreEncHallMisc(uint16_t val){ this->hallconf.interpolation = (val>>9) & 0x01; this->curPids.sequentialPI = (val>>10) & 0x01; - setHwType((TMC_HW_Ver)((val >> 11) & 0x1F)); + setHwType((uint8_t)((val >> 11) & 0x1F)); } + + /** * Sets some constants and features depending on the hardware version of the driver */ -void TMC4671::setHwType(TMC_HW_Ver type){ - //TMC4671HardwareTypeConf newHwConf; - switch(type){ - case TMC_HW_Ver::v1_3_66mv: - { - TMC4671HardwareTypeConf newHwConf = { - .hwVersion = TMC_HW_Ver::v1_3_66mv, - .adcOffset = 0, - .thermistor_R2 = 1500, - .thermistor_R = 10000, - .thermistor_Beta = 4300, - .temperatureEnabled = true, - .temp_limit = 90, - .currentScaler = 2.5 / (0x7fff * 0.066), // sensor 66mV/A - .brakeLimLow = 50700, - .brakeLimHigh = 50900, - .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), - .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 50, // DMTH8003SPS need longer deadtime - .analogEncoderSkipCal = false - }; - this->conf.hwconf = newHwConf; - break; - } - case TMC_HW_Ver::v1_2_2_100mv: - { - TMC4671HardwareTypeConf newHwConf = { - .hwVersion = TMC_HW_Ver::v1_2_2_100mv, - .adcOffset = 0, - .thermistor_R2 = 1500, - .thermistor_R = 10000, - .thermistor_Beta = 4300, - .temperatureEnabled = true, - .temp_limit = 90, - .currentScaler = 2.5 / (0x7fff * 0.1), // w. TMCS1100A2 sensor 100mV/A - .brakeLimLow = 50700, - .brakeLimHigh = 50900, - .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), - .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 40, - .analogEncoderSkipCal = false - }; - this->conf.hwconf = newHwConf; - break; - } - case TMC_HW_Ver::v1_2_2_LEM20: - { - // TODO possibly lower PWM limit because of lower valid sensor range - TMC4671HardwareTypeConf newHwConf = { - .hwVersion = TMC_HW_Ver::v1_2_2, - .adcOffset = 0, - .thermistor_R2 = 1500, - .thermistor_R = 10000, - .thermistor_Beta = 4300, - .temperatureEnabled = true, - .temp_limit = 90, - .currentScaler = 2.5 / (0x7fff * 0.04), // w. LEM 20 sensor 40mV/A - .brakeLimLow = 50700, - .brakeLimHigh = 50900, - .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), - .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20, - .analogEncoderSkipCal = false - }; - this->conf.hwconf = newHwConf; - break; - } - case TMC_HW_Ver::v1_2_2: - { - // TODO possibly lower PWM limit because of lower valid sensor range - TMC4671HardwareTypeConf newHwConf = { - .hwVersion = TMC_HW_Ver::v1_2_2, - .adcOffset = 0, - .thermistor_R2 = 1500, - .thermistor_R = 10000, - .thermistor_Beta = 4300, - .temperatureEnabled = true, - .temp_limit = 90, - .currentScaler = 2.5 / (0x7fff * 0.08), // w. LEM 10 sensor 80mV/A - .brakeLimLow = 50700, - .brakeLimHigh = 50900, - .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), - .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20, - .analogEncoderSkipCal = false - }; - this->conf.hwconf = newHwConf; - break; - } - - case TMC_HW_Ver::v1_2: - { - TMC4671HardwareTypeConf newHwConf = { - .hwVersion = TMC_HW_Ver::v1_2, - .adcOffset = 1000, - .thermistor_R2 = 1500, - .thermistor_R = 22000, - .thermistor_Beta = 4300, - .temperatureEnabled = true, - .temp_limit = 90, - .currentScaler = 2.5 / (0x7fff * 60.0 * 0.0015), // w. 60x 1.5mOhm sensor - .brakeLimLow = 50700, - .brakeLimHigh = 50900, - .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), - .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20, - .analogEncoderSkipCal = false - }; - this->conf.hwconf = newHwConf; - // Activates around 60V as last resort failsave. Check offsets from tmc leakage. ~ 1.426V - break; - } - - - case TMC_HW_Ver::v1_0: - { - TMC4671HardwareTypeConf newHwConf = { - .hwVersion = TMC_HW_Ver::v1_0, - .adcOffset = 1000, - .thermistor_R2 = 0, - .thermistor_R = 0, - .thermistor_Beta = 0, - .temperatureEnabled = false, - .temp_limit = 90, - .currentScaler = 2.5 / (0x7fff * 60.0 * 0.0015), // w. 60x 1.5mOhm sensor - .brakeLimLow = 52400, - .brakeLimHigh = 52800, - .vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5), - .vSenseMult = VOLTAGE_MULT_DEFAULT, - .bbm = 20, - .analogEncoderSkipCal = false - }; - this->conf.hwconf = newHwConf; - - break; +void TMC4671::setHwType(uint8_t type){ + // If only one config is valid use this regardless of requested type + if(TMC4671::tmc4671_hw_configs.size() == 1){ + this->conf.hwconf = TMC4671::tmc4671_hw_configs[0]; + }else{ // Search for config matching requested type + for(const TMC4671HardwareTypeConf& newConf : TMC4671::tmc4671_hw_configs){ + if(type == newConf.hwVersion){ + this->conf.hwconf = newConf; + break; + } + } } - case TMC_HW_Ver::NONE: - { - default: - TMC4671HardwareTypeConf newHwConf; - newHwConf.temperatureEnabled = false; - newHwConf.hwVersion = TMC_HW_Ver::NONE; - newHwConf.currentScaler = 0; - this->conf.hwconf = newHwConf; - setBrakeLimits(0,0); // Disables internal brake resistor activation. DANGER! - break; - } - } setVSenseMult(this->conf.hwconf.vSenseMult); // Update vsense multiplier //setupBrakePin(vdiffAct, vdiffDeact, vMax); // TODO if required setBrakeLimits(this->conf.hwconf.brakeLimLow,this->conf.hwconf.brakeLimHigh); setBBM(this->conf.hwconf.bbm,this->conf.hwconf.bbm); + // Force changing motor and encoder types to prevent invalid types being selected if new hw type does not support them + setMotorType(this->conf.motconf.motor_type, this->conf.motconf.pole_pairs); + setEncoderType(this->conf.motconf.enctype); +} +/** + * Appends a formatted reply with currently available hardware version configs + */ +void TMC4671::replyHardwareVersions(const std::span& versions,std::vector& replies){ +// uint8_t idx = 0; + for(const TMC4671HardwareTypeConf& c : versions){ + if(this->canChangeHwType || c.hwVersion == this->conf.hwconf.hwVersion){ + replies.emplace_back( std::to_string((uint8_t)c.hwVersion) + ":" + c.name,(uint8_t)c.hwVersion); + } + } } void TMC4671::registerCommands(){ @@ -2933,10 +2819,16 @@ CommandStatus TMC4671::command(const ParsedCommand& cmd,std::vectorconf.motconf.motor_type); - }else if(cmd.type == CMDtype::set && (uint8_t)cmd.type < (uint8_t)MotorType::ERR){ + }else if(cmd.type == CMDtype::set && (uint8_t)cmd.type <= (uint8_t)MotorType::BLDC){ this->setMotorType((MotorType)cmd.val, this->conf.motconf.pole_pairs); }else{ - replies.emplace_back("NONE=0,DC=1,2Ph Stepper=2,3Ph BLDC=3"); + std::string rplstr = ""; + TMC4671HardwareTypeConf::SupportedModes_s* confflags = &conf.hwconf.flags; + if(confflags->mot_none) rplstr += "NONE=0,"; + if(confflags->mot_dc) rplstr += "DC=1,"; + if(confflags->mot_stepper) rplstr += "Stepper 2Ph=2,"; + if(confflags->mot_bldc) rplstr += "BLDC 3Ph=3"; + replies.emplace_back(rplstr); } break; @@ -2946,11 +2838,15 @@ CommandStatus TMC4671::command(const ParsedCommand& cmd,std::vectorsetEncoderType((EncoderType_TMC)cmd.val); }else{ - if(externalEncoderAllowed()) - replies.emplace_back("NONE=0,ABN=1,SinCos=2,Analog UVW=3,Hall=4,External=5"); - else - replies.emplace_back("NONE=0,ABN=1,SinCos=2,Analog UVW=3,Hall=4"); - + std::string rplstr = ""; + TMC4671HardwareTypeConf::SupportedModes_s* confflags = &conf.hwconf.flags; + if(confflags->enc_none) rplstr += "NONE=0,"; + if(confflags->enc_abn) rplstr += "ABN=1,"; + if(confflags->enc_sincos) rplstr += "SinCos=2,"; + if(confflags->enc_uvw) rplstr += "UVW=3,"; + if(confflags->enc_hall) rplstr += "HALL=4,"; + if(confflags->enc_ext && externalEncoderAllowed()) rplstr += "External=5"; + replies.emplace_back(rplstr); } break; @@ -2958,16 +2854,11 @@ CommandStatus TMC4671::command(const ParsedCommand& cmd,std::vector({conf1_3,conf1_2_2,conf1_2,conf1_0}); +std::span TMC4671::tmc4671_hw_configs = tmc4671_hw_configs_array; +#endif + +// Only a single config with default settings. Some defaults can be overridden by defines +#ifdef TMC4671_CUSTOM_DEFAULT_HWCONF +const TMC4671HardwareTypeConf defaultconf; +const auto tmc4671_hw_configs_array = std::to_array({defaultconf}); +std::span TMC4671::tmc4671_hw_configs = tmc4671_hw_configs_array; + +#endif From 6fbe1a510c1be06dd79bfb2918ff7feb7f967364 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Thu, 22 Feb 2024 12:05:40 +0100 Subject: [PATCH 10/40] TMC allow autotuning I term definition --- Firmware/FFBoard/UserExtensions/Inc/TMC4671.h | 4 ++++ Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h index fb5563b33..425f76ae3 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h +++ b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h @@ -50,6 +50,10 @@ extern TIM_HandleTypeDef TIM_TMC; #ifndef TMC4671_DEFAULT_ANALOGENC_SKIPCAL #define TMC4671_DEFAULT_ANALOGENC_SKIPCAL 0 #endif +#ifndef TMC4671_ITUNE_CUTOFF +#define TMC4671_ITUNE_CUTOFF 0.04 +#endif + enum class TMC_ControlState : uint32_t {uninitialized,waitPower,Shutdown,Running,EncoderInit,EncoderFinished,HardError,OverTemp,IndexSearch,FullCalibration,ExternalEncoderInit,Pidautotune}; diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index f59aa92b0..38ef00d46 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -726,7 +726,7 @@ bool TMC4671::pidAutoTune(){ flux = getActualFlux(); } - if(peakflux > (targetflux + ( targetflux * 0.03))) // Overshoot target by 3% + if(peakflux > (targetflux + ( targetflux * TMC4671_ITUNE_CUTOFF))) // Overshoot target by 4% default { fluxI -= step_i; // Revert last step break; From ed6567666e55c1e7883a2ac25ab8dc2ecefef98a Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Thu, 22 Feb 2024 12:06:23 +0100 Subject: [PATCH 11/40] Commandhandler split register command template and prepared overriding Saves memory on smaller template function --- Firmware/FFBoard/Inc/CommandHandler.h | 27 ++++++++++++------- Firmware/FFBoard/Src/CommandHandler.cpp | 36 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/Firmware/FFBoard/Inc/CommandHandler.h b/Firmware/FFBoard/Inc/CommandHandler.h index 0a5cb92a7..71c005a53 100644 --- a/Firmware/FFBoard/Inc/CommandHandler.h +++ b/Firmware/FFBoard/Inc/CommandHandler.h @@ -13,7 +13,7 @@ #include "mutex.hpp" #include "ClassIDs.h" #include - +#include #define CMDFLAG_GET 0x01 #define CMDFLAG_SET 0x02 @@ -22,6 +22,7 @@ #define CMDFLAG_SETADR 0x20 #define CMDFLAG_HIDDEN 0x40 #define CMDFLAG_DEBUG 0x80 +#define CMDFLAG_EXTOVERRIDE 0x80000000 #define CMDFLAG_STR_ONLY 0x100 #define CMDFLAG_HID_ONLY 0x200 // Command not available for string based parsers @@ -50,8 +51,8 @@ class CmdHandlerCommanddef {}; const char* cmd = nullptr; const char* helpstring = nullptr; - const uint32_t cmdId; - const uint32_t flags; + uint32_t cmdId; + uint32_t flags; }; struct CmdHandlerInfo @@ -260,17 +261,22 @@ class CommandHandler { */ template void registerCommand(const char* cmd,const ID cmdid,const char* help=nullptr,uint32_t flags = 0){ - for(CmdHandlerCommanddef& cmdDef : registeredCommands){ - if(cmdDef.cmdId == static_cast(cmdid)) - return; //already present - } + registerCommand_INT(cmd, static_cast(cmdid), help, flags); + } - this->registeredCommands.emplace_back(cmd, help,static_cast(cmdid),flags); - this->registeredCommands.shrink_to_fit(); + + virtual void postCmdhandlerInit(){}; // Can implement in external file to override command flags + template + /** + * Can override command flags to make it read only + */ + void overrideCommandFlags(const ID cmdid,uint32_t flagmask = 0){ + overrideCommandFlags_INT(static_cast(cmdid), flagmask); } + protected: void setInstance(uint8_t instance); bool commandsEnabled = true; @@ -287,6 +293,9 @@ class CommandHandler { CmdHandlerInfo cmdHandlerInfo; + void registerCommand_INT(const char* cmd,const uint32_t cmdid,const char* help=nullptr,uint32_t flags = 0); + void overrideCommandFlags_INT(const uint32_t cmdid,uint32_t flagmask = CMDFLAG_GET | CMDFLAG_GETADR); + }; #endif /* COMMANDHANDLER_H_ */ diff --git a/Firmware/FFBoard/Src/CommandHandler.cpp b/Firmware/FFBoard/Src/CommandHandler.cpp index 1c488a832..95cf4d823 100644 --- a/Firmware/FFBoard/Src/CommandHandler.cpp +++ b/Firmware/FFBoard/Src/CommandHandler.cpp @@ -523,3 +523,39 @@ void CommandHandler::removeCommandHandler(){ removeCallbackHandler(getCommandHandlers(), this); //cmdHandlerListMutex.Unlock(); } + +/** + * Registers a new command. Called by registerCommand template + */ +void CommandHandler::registerCommand_INT(const char* cmd,const uint32_t cmdid,const char* help,uint32_t flags){ + for(auto it = registeredCommands.begin();it!=registeredCommands.end();++it){ + CmdHandlerCommanddef& cmdDef = *it; + if(cmdDef.cmdId == cmdid){ + if(cmdDef.flags & CMDFLAG_EXTOVERRIDE){ + // Override dummy present. Only update other data if not present and honor flag mask + flags &= flags | CMDFLAG_EXTOVERRIDE; + registeredCommands.erase(it); // Remove old dummy + break; + }else{ + return; //already present + } + } + } + + this->registeredCommands.emplace_back(cmd, help,cmdid,flags); + this->registeredCommands.shrink_to_fit(); +} + +/** + * Adds an override dummy or changes flags of a command. Called by template. TODO untested + */ +void CommandHandler::overrideCommandFlags_INT(const uint32_t cmdid,uint32_t flagmask){ + for(CmdHandlerCommanddef& cmdDef : registeredCommands){ + if(cmdDef.cmdId == static_cast(cmdid)){ + cmdDef.flags &= flagmask; + cmdDef.flags |= CMDFLAG_EXTOVERRIDE; + return; //already present + } + } + this->registeredCommands.emplace_back(nullptr, nullptr,cmdid,flagmask); // Dummy +} From 5febed31c7119233a5529c806b6cc38dab8599e3 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 26 Feb 2024 16:46:00 +0100 Subject: [PATCH 12/40] Make FFB capable axes optionally report 32b gamepad values --- Firmware/FFBoard/Inc/AxesManager.h | 2 -- Firmware/FFBoard/Inc/Axis.h | 2 +- Firmware/FFBoard/Inc/EffectsCalculator.h | 2 +- Firmware/FFBoard/Inc/ffb_defs.h | 17 +++++++++-- Firmware/FFBoard/Src/Axis.cpp | 26 +++++++++-------- Firmware/FFBoard/Src/EffectsCalculator.cpp | 6 ++-- .../UserExtensions/Inc/usb_hid_ffb_desc.h | 28 ++++++++++++++++++- .../FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 4 +++ .../UserExtensions/Src/usb_hid_1ffb_desc.c | 13 +++++++++ .../UserExtensions/Src/usb_hid_2ffb_desc.c | 13 +++++++++ .../UserExtensions/Src/usb_hid_gamepad.c | 13 +++++++++ 11 files changed, 104 insertions(+), 22 deletions(-) diff --git a/Firmware/FFBoard/Inc/AxesManager.h b/Firmware/FFBoard/Inc/AxesManager.h index f1b9e3762..46527d225 100644 --- a/Firmware/FFBoard/Inc/AxesManager.h +++ b/Firmware/FFBoard/Inc/AxesManager.h @@ -49,8 +49,6 @@ class AxesManager private: volatile Control_t* control; - volatile bool *p_usb_disabled; - volatile bool *p_emergency; std::shared_ptr effects_calc; uint16_t axis_count = 0; std::vector> axes; diff --git a/Firmware/FFBoard/Inc/Axis.h b/Firmware/FFBoard/Inc/Axis.h index 05e87fdc9..0fdfcb7bc 100644 --- a/Firmware/FFBoard/Inc/Axis.h +++ b/Firmware/FFBoard/Inc/Axis.h @@ -71,7 +71,7 @@ struct AxisConfig struct metric_t { float accel = 0; // in deg/s² float speed = 0; // in deg/s - int32_t pos = 0; // scaled position as 16b int -0x7fff to 0x7fff + int32_t pos_scaled_16b = 0; // scaled position as 16b int -0x7fff to 0x7fff matching FFB ranges float pos_f = 0; // scaled position as float. -1 to 1 range float posDegrees = 0; // Position in degrees. Not scaled to selected range int32_t torque = 0; // total of effect + endstop torque diff --git a/Firmware/FFBoard/Inc/EffectsCalculator.h b/Firmware/FFBoard/Inc/EffectsCalculator.h index e065c0335..3728f6cca 100644 --- a/Firmware/FFBoard/Inc/EffectsCalculator.h +++ b/Firmware/FFBoard/Inc/EffectsCalculator.h @@ -84,7 +84,7 @@ class EffectsCalculator: public PersistentStorage, uint8_t getGain(); void logEffectType(uint8_t type,bool remove = false); //void setDirectionEnableMask(uint8_t mask); - void calcStatsEffectType(uint8_t type, int16_t force,uint8_t axis); + void calcStatsEffectType(uint8_t type, int32_t force,uint8_t axis); void logEffectState(uint8_t type,uint8_t state); void resetLoggedActiveEffects(bool reinit); diff --git a/Firmware/FFBoard/Inc/ffb_defs.h b/Firmware/FFBoard/Inc/ffb_defs.h index e78b1e6fd..c5596b073 100644 --- a/Firmware/FFBoard/Inc/ffb_defs.h +++ b/Firmware/FFBoard/Inc/ffb_defs.h @@ -96,15 +96,25 @@ // Only include these for cpp #ifdef __cplusplus -// HID gamepad report - struct __attribute__((__packed__)) reportHID_t { uint8_t id = 1; uint64_t buttons = 0; +#if defined(HIDAXISRES_32B) && MAX_AXIS >= 1 + int32_t X = 0; +#else int16_t X = 0; +#endif +#if defined(HIDAXISRES_32B) && MAX_AXIS >= 2 + int32_t Y = 0; +#else int16_t Y = 0; +#endif +#if defined(HIDAXISRES_32B) && MAX_AXIS >= 3 + int32_t Z = 0; +#else int16_t Z = 0; +#endif int16_t RX = 0; int16_t RY = 0; int16_t RZ = 0; @@ -115,7 +125,8 @@ struct __attribute__((__packed__)) reportHID_t { /* * Helper function to access analog axes in packed HID report struct */ -inline void setHidReportAxis(reportHID_t *report, uint8_t idx, int16_t val){ +inline void setHidReportAxis(reportHID_t *report, uint8_t idx, uint32_t val){ + switch(idx){ case 0: report->X = val; diff --git a/Firmware/FFBoard/Src/Axis.cpp b/Firmware/FFBoard/Src/Axis.cpp index 2a61616b4..f3855525e 100644 --- a/Firmware/FFBoard/Src/Axis.cpp +++ b/Firmware/FFBoard/Src/Axis.cpp @@ -553,17 +553,21 @@ metric_t* Axis::getMetrics() { } /** - * Returns position as 16b int scaled to gamepad range + * Returns position as int scaled to gamepad range */ int32_t Axis::getLastScaledEnc() { - return clip(metric.current.pos,-0x7fff,0x7fff); +#if defined(HIDAXISRES_32B) + return clip(metric.current.pos_f * 0x7fffffff,-0x7fffffff,0x7fffffff); // Calc from float pos +#else + return clip(metric.current.pos_scaled_16b,-0x7fff,0x7fff); +#endif } /** * Changes intensity of idle spring when FFB is off */ int32_t Axis::updateIdleSpringForce() { - return clip((int32_t)(-metric.current.pos*idlespringscale),-idlespringclip,idlespringclip); + return clip((int32_t)(-metric.current.pos_scaled_16b*idlespringscale),-idlespringclip,idlespringclip); } /* @@ -638,7 +642,7 @@ void Axis::setFxRatio(uint8_t val) { void Axis::resetMetrics(float new_pos= 0) { // pos is degrees metric.current = metric_t(); metric.current.posDegrees = new_pos; - std::tie(metric.current.pos,metric.current.pos_f) = scaleEncValue(new_pos, degreesOfRotation); + std::tie(metric.current.pos_scaled_16b,metric.current.pos_f) = scaleEncValue(new_pos, degreesOfRotation); metric.previous = metric_t(); // Reset filters speedFilter.calcBiquad(); @@ -653,7 +657,7 @@ void Axis::updateMetrics(float new_pos) { // pos is degrees metric.previous = metric.current; metric.current.posDegrees = new_pos; - std::tie(metric.current.pos,metric.current.pos_f) = scaleEncValue(new_pos, degreesOfRotation); + std::tie(metric.current.pos_scaled_16b,metric.current.pos_f) = scaleEncValue(new_pos, degreesOfRotation); // compute speed and accel from raw instant speed normalized @@ -692,7 +696,7 @@ float Axis::getTorqueScaler(){ } -int32_t Axis::getTorque() { return metric.current.torque; } +int32_t Axis::getTorque() { return metric.previous.torque; } bool Axis::isInverted() { return invertAxis; @@ -702,7 +706,7 @@ bool Axis::isInverted() { * Calculate soft endstop effect */ int16_t Axis::updateEndstop(){ - int8_t clipdir = cliptest(metric.current.pos, -0x7fff, 0x7fff); + int8_t clipdir = cliptest(metric.current.pos_scaled_16b, -0x7fff, 0x7fff); if(clipdir == 0){ return 0; } @@ -975,16 +979,16 @@ CommandStatus Axis::command(const ParsedCommand& cmd,std::vector& break; case Axis_commands::curpos: - replies.emplace_back(this->metric.current.pos); + replies.emplace_back(this->metric.previous.pos_scaled_16b); break; case Axis_commands::curtorque: - replies.emplace_back(this->metric.current.torque); + replies.emplace_back(getTorque()); break; case Axis_commands::curspd: - replies.emplace_back(this->metric.current.speed); + replies.emplace_back(this->metric.previous.speed); break; case Axis_commands::curaccel: - replies.emplace_back(this->metric.current.accel); + replies.emplace_back(this->metric.previous.accel); break; case Axis_commands::reductionScaler: diff --git a/Firmware/FFBoard/Src/EffectsCalculator.cpp b/Firmware/FFBoard/Src/EffectsCalculator.cpp index 688afb25f..a75d745c1 100644 --- a/Firmware/FFBoard/Src/EffectsCalculator.cpp +++ b/Firmware/FFBoard/Src/EffectsCalculator.cpp @@ -313,7 +313,7 @@ int32_t EffectsCalculator::calcComponentForce(FFB_Effect *effect, int32_t forceV case FFB_EFFECT_SPRING: { - float pos = metrics->pos; + float pos = metrics->pos_scaled_16b; result_torque -= calcConditionEffectForce(effect, pos, gain.spring, con_idx, scaler.spring, angle_ratio); break; } @@ -669,12 +669,12 @@ void EffectsCalculator::logEffectState(uint8_t type,uint8_t state){ } -void EffectsCalculator::calcStatsEffectType(uint8_t type, int16_t force,uint8_t axis){ +void EffectsCalculator::calcStatsEffectType(uint8_t type, int32_t force,uint8_t axis){ if(axis >= MAX_AXIS) return; if(type > 0 && type < 13) { uint8_t arrayLocation = type - 1; - effects_stats[arrayLocation].current[axis] = clip(effects_stats[arrayLocation].current[axis] + force, -0x7fff, 0x7fff); + effects_stats[arrayLocation].current[axis] = clip(effects_stats[arrayLocation].current[axis] + force, -0x7fff, 0x7fff); effects_stats[arrayLocation].max[axis] = std::max(effects_stats[arrayLocation].max[axis], (int16_t)abs(force)); } } diff --git a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h index d6067effe..ea9aee670 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h +++ b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h @@ -9,18 +9,44 @@ #define USB_INC_USB_HID_FFB_DESC_H_ #include "constants.h" +#if defined(HIDAXISRES_32B) +#define HIDDESC_32B_ENTRY(count) /* LOGICAL_MINIMUM (-7FFFFFFF)*/\ + 0x17, 0x01, 0x00, 0x00, 0x80, \ + /* LOGICAL_MAXIMUM (7FFFFFFF)*/\ + 0x27, 0xff, 0xff, 0xff, 0x7f,\ + /* REPORT_SIZE (16)*/\ + 0x75, 0x20,\ + /* REPORT_COUNT */\ + 0x95, count,\ +/* INPUT (Data,Var,Abs)*/\ + 0x81, 0x02, +#define HIDDESC_32B_ENTRY_SIZE 12 // 12 bytes extra for additional 16b definition 2B count +#endif +#if defined(HIDAXISRES_32B) +#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 + 16 +#else #define USB_HID_1FFB_REPORT_DESC_SIZE 1196 +#endif #ifdef AXIS1_FFB_HID_DESC extern const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE]; #endif -#define USB_HID_2FFB_REPORT_DESC_SIZE 1215//1213 +#if defined(HIDAXISRES_32B) +#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 + 16 +#else +#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 +#endif + #ifdef AXIS2_FFB_HID_DESC extern const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE]; #endif +#if defined(HIDAXISRES_32B) +#define USB_HID_GAMEPAD_REPORT_DESC_SIZE 176 + 16 +#else #define USB_HID_GAMEPAD_REPORT_DESC_SIZE 176 +#endif #ifdef FFB_HID_DESC_GAMEPAD extern const uint8_t hid_gamepad_desc[USB_HID_GAMEPAD_REPORT_DESC_SIZE]; #endif diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 3fd91228c..0ef76ac3f 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -175,8 +175,12 @@ void FFBHIDMain::send_report(){ for(int32_t val : *axes){ if(count >= analogAxisCount) break; +#ifdef HIDAXISRES_32B + if(count <= MAX_AXIS) val = val << 16; // Shift up 16 bit to fill 32b value. Primary axis is 32b +#endif setHidReportAxis(&reportHID,count++,val); } + // sourcesSem.Give(); // Fill rest for(;count Date: Mon, 4 Mar 2024 16:10:13 +0100 Subject: [PATCH 13/40] Allow changing FFB update rates Forwards new samplerate to filters. Needs presets, non timer handling, better FX samplerate resolutions --- Firmware/FFBoard/Inc/AxesManager.h | 2 + Firmware/FFBoard/Inc/Axis.h | 5 +- Firmware/FFBoard/Inc/EffectsCalculator.h | 9 +- Firmware/FFBoard/Inc/HidFFB.h | 1 + Firmware/FFBoard/Inc/SerialFFB.h | 1 + Firmware/FFBoard/Src/AxesManager.cpp | 24 +++-- Firmware/FFBoard/Src/Axis.cpp | 24 +++-- Firmware/FFBoard/Src/EffectsCalculator.cpp | 25 ++++-- Firmware/FFBoard/Src/Filters.cpp | 2 + Firmware/FFBoard/Src/HidFFB.cpp | 4 + Firmware/FFBoard/Src/SerialFFB.cpp | 4 + .../FFBoard/UserExtensions/Inc/FFBHIDMain.h | 34 +++++++- .../FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 87 ++++++++++++++++--- 13 files changed, 178 insertions(+), 44 deletions(-) diff --git a/Firmware/FFBoard/Inc/AxesManager.h b/Firmware/FFBoard/Inc/AxesManager.h index 46527d225..fb361e127 100644 --- a/Firmware/FFBoard/Inc/AxesManager.h +++ b/Firmware/FFBoard/Inc/AxesManager.h @@ -47,6 +47,8 @@ class AxesManager void emergencyStop(bool reset); void resetPosZero(); + void updateSamplerate(float newSamplerate); + private: volatile Control_t* control; std::shared_ptr effects_calc; diff --git a/Firmware/FFBoard/Inc/Axis.h b/Firmware/FFBoard/Inc/Axis.h index 0fdfcb7bc..5b044c187 100644 --- a/Firmware/FFBoard/Inc/Axis.h +++ b/Firmware/FFBoard/Inc/Axis.h @@ -171,6 +171,9 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle bool updateTorque(int32_t* totalTorque); + void updateSamplerate(float newSamplerate); + void updateFilters(uint8_t profileId); + void setGearRatio(uint8_t numerator,uint8_t denominator); static const std::vector> axis1_drivers; @@ -259,7 +262,7 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle const biquad_constant_t filterFrictionCst = {50, 20}; const biquad_constant_t filterInertiaCst = {20, 20}; uint8_t filterProfileId = 1; // Default medium (1) as this is the most common encoder resolution and users can go lower or higher if required. - const float filter_f = 1000; // 1khz + float filter_f = 1000; // 1khz default. should be set at runtime once the actual rate is known const int32_t intFxClip = 20000; uint8_t damperIntensity = 30; diff --git a/Firmware/FFBoard/Inc/EffectsCalculator.h b/Firmware/FFBoard/Inc/EffectsCalculator.h index 3728f6cca..feff5f0a0 100644 --- a/Firmware/FFBoard/Inc/EffectsCalculator.h +++ b/Firmware/FFBoard/Inc/EffectsCalculator.h @@ -100,6 +100,8 @@ class EffectsCalculator: public PersistentStorage, // Thread impl void Run(); + void updateSamplerate(float newSamplerate); // Must be called if update rate is changed to update filters and effects + protected: @@ -108,7 +110,7 @@ class EffectsCalculator: public PersistentStorage, // Filters effect_biquad_t filter[2]; // 0 is the default profile and the custom for CFFilter, CUSTOM_PROFILE_ID is the custom slot uint8_t filterProfileId = 0; - const uint32_t calcfrequency = 1000; // HID frequency 1khz + uint32_t calcfrequency = 1000; // HID frequency 1khz const float qfloatScaler = 0.01; // Rescale factor for conditional effect to boost or decrease the intensity @@ -150,10 +152,11 @@ class EffectsControlItf{ virtual void set_gain(uint8_t gain) = 0; virtual void cfUpdateEvent(); virtual void fxUpdateEvent(); + virtual void updateSamplerate(float newSamplerate) = 0; // Should be called when update loop rate is changed private: - FastMovingAverage fxPeriodAvg{20}; - FastMovingAverage cfUpdatePeriodAvg{20}; + FastMovingAverage fxPeriodAvg{5}; + FastMovingAverage cfUpdatePeriodAvg{5}; uint32_t lastFxUpdate = 0; uint32_t lastCfUpdate = 0; diff --git a/Firmware/FFBoard/Inc/HidFFB.h b/Firmware/FFBoard/Inc/HidFFB.h index 28ddc6707..7dae12394 100644 --- a/Firmware/FFBoard/Inc/HidFFB.h +++ b/Firmware/FFBoard/Inc/HidFFB.h @@ -39,6 +39,7 @@ class HidFFB: public UsbHidHandler, public EffectsControlItf { void sendStatusReport(uint8_t effect); void setDirectionEnableMask(uint8_t mask); + void updateSamplerate(float newSamplerate); private: // HID diff --git a/Firmware/FFBoard/Inc/SerialFFB.h b/Firmware/FFBoard/Inc/SerialFFB.h index e16cfc1a7..9ec6e26be 100644 --- a/Firmware/FFBoard/Inc/SerialFFB.h +++ b/Firmware/FFBoard/Inc/SerialFFB.h @@ -37,6 +37,7 @@ class SerialFFB : public CommandHandler, public EffectsControlItf{ void setMagnitude(uint8_t idx,int16_t magnitude); void setEffectState(uint8_t id, bool state); + void updateSamplerate(float newSamplerate); private: static ClassIdentifier info; diff --git a/Firmware/FFBoard/Src/AxesManager.cpp b/Firmware/FFBoard/Src/AxesManager.cpp index dd1edd726..c2855fe11 100644 --- a/Firmware/FFBoard/Src/AxesManager.cpp +++ b/Firmware/FFBoard/Src/AxesManager.cpp @@ -102,19 +102,25 @@ bool AxesManager::setAxisCount(int8_t count) { } void AxesManager::usbSuspend() { - for (auto &axis : axes) { - axis->usbSuspend(); - } + for (auto &axis : axes) { + axis->usbSuspend(); + } } void AxesManager::usbResume() { - for (auto &axis : axes) { - axis->usbResume(); - } + for (auto &axis : axes) { + axis->usbResume(); + } } void AxesManager::resetPosZero() { - for (auto &axis : axes) { - axis->setPos(0); - } + for (auto &axis : axes) { + axis->setPos(0); + } +} + +void AxesManager::updateSamplerate(float newSamplerate){ + for (auto &axis : axes) { + axis->updateSamplerate(newSamplerate); + } } diff --git a/Firmware/FFBoard/Src/Axis.cpp b/Firmware/FFBoard/Src/Axis.cpp index f3855525e..cc9c717bc 100644 --- a/Firmware/FFBoard/Src/Axis.cpp +++ b/Firmware/FFBoard/Src/Axis.cpp @@ -661,9 +661,9 @@ void Axis::updateMetrics(float new_pos) { // pos is degrees // compute speed and accel from raw instant speed normalized - float currentSpeed = (new_pos - metric.previous.posDegrees) * 1000.0; // deg/s + float currentSpeed = (new_pos - metric.previous.posDegrees) * this->filter_f; // deg/s metric.current.speed = speedFilter.process(currentSpeed); - metric.current.accel = accelFilter.process((currentSpeed - _lastSpeed))* 1000.0; // deg/s/s + metric.current.accel = accelFilter.process((currentSpeed - _lastSpeed))* this->filter_f; // deg/s/s _lastSpeed = currentSpeed; } @@ -796,6 +796,20 @@ bool Axis::updateTorque(int32_t* totalTorque) { return (torqueChanged); } +void Axis::updateSamplerate(float newSamplerate){ + this->filter_f = newSamplerate; + this->updateFilters(this->filterProfileId); // Recalculate filters +} + +void Axis::updateFilters(uint8_t profileId){ + this->filterProfileId = profileId; + speedFilter.setFc(filterSpeedCst[this->filterProfileId].freq / filter_f); + speedFilter.setQ(filterSpeedCst[this->filterProfileId].q / 100.0); + accelFilter.setFc(filterAccelCst[this->filterProfileId].freq / filter_f); + accelFilter.setQ(filterAccelCst[this->filterProfileId].q / 100.0); + damperFilter.setFc(filterDamperCst.freq/filter_f); +} + /** * Starts fading in force from start to 1 over fadeTime */ @@ -1007,11 +1021,7 @@ CommandStatus Axis::command(const ParsedCommand& cmd,std::vector& else if (cmd.type == CMDtype::set) { uint32_t value = clip(cmd.val, 0, filterSpeedCst.size()-1); - this->filterProfileId = value; - speedFilter.setFc(filterSpeedCst[this->filterProfileId].freq / filter_f); - speedFilter.setQ(filterSpeedCst[this->filterProfileId].q / 100.0); - accelFilter.setFc(filterAccelCst[this->filterProfileId].freq / filter_f); - accelFilter.setQ(filterAccelCst[this->filterProfileId].q / 100.0); + this->updateFilters(value); } break; case Axis_commands::filterSpeed: diff --git a/Firmware/FFBoard/Src/EffectsCalculator.cpp b/Firmware/FFBoard/Src/EffectsCalculator.cpp index a75d745c1..6c8947919 100644 --- a/Firmware/FFBoard/Src/EffectsCalculator.cpp +++ b/Firmware/FFBoard/Src/EffectsCalculator.cpp @@ -74,6 +74,15 @@ void EffectsCalculator::setActive(bool active) setClipLed(active); } +void EffectsCalculator::updateSamplerate(float newSamplerate){ + this->calcfrequency = newSamplerate; + for(FFB_Effect &effect : this->effects){ + if(effect.filter[0]){ // Update filters if effect has filters + setFilters(&effect); + } + } +} + /* If the metric is less than CP Offset - Dead Band, then the resulting force is given by the following formula: @@ -1001,12 +1010,12 @@ int32_t EffectsCalculator::find_free_effect(uint8_t type){ */ uint32_t EffectsControlItf::getRate(){ float periodAvg = fxPeriodAvg.getAverage(); - if((HAL_GetTick() - lastFxUpdate) > 1000 || periodAvg == 0){ + if((micros() - lastFxUpdate) > 1000000 || periodAvg == 0){ // Reset average fxPeriodAvg.clear(); return 0; }else{ - return (1000.0/periodAvg); + return (1000000.0/periodAvg); } } @@ -1015,22 +1024,22 @@ uint32_t EffectsControlItf::getRate(){ */ uint32_t EffectsControlItf::getConstantForceRate(){ float periodAvg = cfUpdatePeriodAvg.getAverage(); - if((HAL_GetTick() - lastCfUpdate) > 1000 || periodAvg == 0){ + if((micros() - lastCfUpdate) > 1000000 || periodAvg == 0){ // Reset average cfUpdatePeriodAvg.clear(); return 0; }else{ - return (1000.0/periodAvg); + return (1000000.0/periodAvg); } } void EffectsControlItf::cfUpdateEvent(){ - cfUpdatePeriodAvg.addValue((uint32_t)(HAL_GetTick() - lastCfUpdate)); - lastCfUpdate = HAL_GetTick(); + cfUpdatePeriodAvg.addValue((uint32_t)(micros() - lastCfUpdate)); + lastCfUpdate = micros(); } void EffectsControlItf::fxUpdateEvent(){ - fxPeriodAvg.addValue((uint32_t)(HAL_GetTick() - lastFxUpdate)); - lastFxUpdate = HAL_GetTick(); + fxPeriodAvg.addValue((uint32_t)(micros() - lastFxUpdate)); + lastFxUpdate = micros(); } diff --git a/Firmware/FFBoard/Src/Filters.cpp b/Firmware/FFBoard/Src/Filters.cpp index a62074783..a9c59330a 100644 --- a/Firmware/FFBoard/Src/Filters.cpp +++ b/Firmware/FFBoard/Src/Filters.cpp @@ -3,6 +3,8 @@ * * Created on: Feb 13, 2020 * Author: Yannick + * + * Based on http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/ */ #include "Filters.h" diff --git a/Firmware/FFBoard/Src/HidFFB.cpp b/Firmware/FFBoard/Src/HidFFB.cpp index 21835fef3..5b12a41f7 100644 --- a/Firmware/FFBoard/Src/HidFFB.cpp +++ b/Firmware/FFBoard/Src/HidFFB.cpp @@ -39,6 +39,10 @@ void HidFFB::setDirectionEnableMask(uint8_t mask){ this->directionEnableMask = mask; } +void HidFFB::updateSamplerate(float newSamplerate){ + effects_calc->updateSamplerate(newSamplerate); +} + bool HidFFB::getFfbActive(){ return this->ffb_active; diff --git a/Firmware/FFBoard/Src/SerialFFB.cpp b/Firmware/FFBoard/Src/SerialFFB.cpp index a439850d4..6e00d25d0 100644 --- a/Firmware/FFBoard/Src/SerialFFB.cpp +++ b/Firmware/FFBoard/Src/SerialFFB.cpp @@ -121,6 +121,10 @@ void SerialFFB::setEffectState(uint8_t id, bool state){ effects[id].state = state ? 1 : 0; } +void SerialFFB::updateSamplerate(float newSamplerate){ + effects_calc->updateSamplerate(newSamplerate); +} + CommandStatus SerialFFB::command(const ParsedCommand& cmd,std::vector& replies){ CommandStatus status = CommandStatus::OK; EffectsControlItf::fxUpdateEvent(); diff --git a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h index 72855f793..b383b95d7 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h +++ b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h @@ -33,7 +33,11 @@ #include "SelectableInputs.h" #include "thread.hpp" -class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentStorage,ExtiHandler,public UsbHidHandler, ErrorHandler, SelectableInputs{ +class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentStorage,ExtiHandler,public UsbHidHandler, ErrorHandler, SelectableInputs +#ifdef TIM_FFB +, TimerHandler // Adds timer handler +#endif +{ enum class FFBWheel_commands : uint32_t{ ffbactive,axes,btntypes,lsbtn,addbtn,aintypes,lsain,addain,hidrate,hidsendspd,estop,cfrate }; @@ -74,6 +78,11 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto void errorCallback(const Error &error, bool cleared); void systick(); +#ifdef TIM_FFB + void timerElapsed(TIM_HandleTypeDef* htim); +#endif + + float getCurFFBFreq(); protected: std::shared_ptr ffb; @@ -91,9 +100,28 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto * Warning: Report rate initialized by bInterval is overridden by saved speed preset at startup! */ void setReportRate(uint8_t rateidx); - uint8_t usb_report_rate = HID_BINTERVAL; //1 = 1000hz, 2 = 500hz, 3 = 333hz 4 = 250hz, 5 = 200hz 6 = 166hz, 8 = 125hz etc... + uint8_t usb_report_rate = HID_BINTERVAL; //for FS USB 1 = 1000hz, 2 = 500hz, 3 = 333hz 4 = 250hz, 5 = 200hz 6 = 166hz, 8 = 125hz etc... uint8_t usb_report_rate_idx = 0; - const uint8_t usb_report_rates[4] = {1,2,4,8}; // Maps stored hid speed to report rates +#ifndef TIM_FFB + uint8_t ffb_rate_divider = 0; +#endif + + + struct FFB_update_rates{ + struct FFB_update_rate_divider{ + uint8_t basediv; + uint8_t hiddiv; + }; +#if TUD_OPT_HIGH_SPEED // divider pair + uint32_t basefreq = 8000; + std::array dividers = {{{1,1},{2,1},{4,1},{8,1},{16,1},{32,1},{64,1}}}; // 8khz to 125hz +#else + uint32_t basefreq = 1000; + std::array dividers = {{{1,1},{2,1},{4,1},{8,1}}}; // 8 entries max. 1khz to 125hz +#endif + }; + //const uint8_t usb_report_rates[4] = {1,2,4,8}; // Maps stored hid speed to report rates + const static FFB_update_rates ffbrates; std::string usb_report_rates_names(); diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 0ef76ac3f..28ac4e58f 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -14,6 +14,14 @@ #include "cmsis_os.h" extern osThreadId_t defaultTaskHandle; +#ifdef TIM_FFB +extern TIM_HandleTypeDef TIM_FFB; +#endif + +#ifndef OVERRIDE_FFBRATES +const FFBHIDMain::FFB_update_rates FFBHIDMain::ffbrates; // Default rates +#endif + ////////////////////////////////////////////// @@ -76,7 +84,7 @@ void FFBHIDMain::saveFlash(){ Flash_Write(ADR_FFBWHEEL_ANALOGCONF,this->ainsources); uint8_t conf1 = 0; - conf1 |= usb_report_rate_idx & 0x3; + conf1 |= usb_report_rate_idx & 0x7; Flash_Write(ADR_FFBWHEEL_CONF1,conf1); } @@ -90,9 +98,16 @@ void FFBHIDMain::Run(){ // control.emergency = true; // Immediately enter emergency state but without notifying other classes yet lastEstop = HAL_GetTick(); } +#endif +#ifdef TIM_FFB + HAL_TIM_Base_Start_IT(&TIM_FFB); // Start generating updates #endif while(true){ +#ifndef TIM_FFB Delay(1); +#else + WaitForNotification(); +#endif updateControl(); } } @@ -203,37 +218,74 @@ void FFBHIDMain::send_report(){ } +/** + * Returns current FFB update loop frequency in Hz + */ +float FFBHIDMain::getCurFFBFreq(){ + return ffbrates.basefreq/((uint32_t)ffbrates.dividers[usb_report_rate_idx].basediv); +} + /** * Changes the hid report rate based on the index for usb_report_rates */ void FFBHIDMain::setReportRate(uint8_t rateidx){ - rateidx = clip(rateidx, 0,sizeof(usb_report_rates)); + uint32_t usbrate_base = TUD_OPT_HIGH_SPEED ? 8000 : 1000; + if(tud_connected()){ // Get either actual rate or max supported rate if not connected + usbrate_base = tud_speed_get() == TUSB_SPEED_HIGH ? 8000 : 1000; // Only FS and HS supported + } + + rateidx = clip(rateidx, 0,ffbrates.dividers.size()); usb_report_rate_idx = rateidx; - usb_report_rate = usb_report_rates[rateidx]*HID_BINTERVAL; + + + // Either limit using rate counter or HW timer if present. +#ifdef TIM_FFB + TIM_FFB.Instance->ARR = ((1000000*(uint32_t)ffbrates.dividers[rateidx].basediv)/ffbrates.basefreq); // Assumes 1µs timer steps +#else + ffb_rate_divider = ffbrates.dividers[rateidx].basediv; +#endif + usb_report_rate = ffbrates.dividers[rateidx].hiddiv*HID_BINTERVAL; + // Divide report rate down if above actual usb rate + while(((ffbrates.basefreq / (uint32_t)ffbrates.dividers[rateidx].basediv) / usb_report_rate) > usbrate_base){ + usb_report_rate++; + } + + // Pass updated rate to other classes to update filters + float newRate = getCurFFBFreq(); + if(ffb) + ffb->updateSamplerate(newRate); + if(axes_manager) + axes_manager->updateSamplerate(newRate); } /** * Generates the speed strings to display to the user */ std::string FFBHIDMain::usb_report_rates_names() { - std::string s = ""; - for(uint8_t i = 0 ; i < sizeof(usb_report_rates);i++){ - s += std::to_string(1000/(HID_BINTERVAL*usb_report_rates[i])) + "Hz:"+std::to_string(i); - if(i < sizeof(usb_report_rates)-1) - s += ","; + std::string s = ""; + uint32_t usbrate_base = TUD_OPT_HIGH_SPEED ? 8000 : 1000; + if(tud_connected()){ // Get either actual rate or max supported rate if not connected + usbrate_base = tud_speed_get() == TUSB_SPEED_HIGH ? 8000 : 1000; // Only FS and HS supported + } + for(uint8_t i = 0 ; i < ffbrates.dividers.size();i++){ + uint32_t updatefreq = ffbrates.basefreq/((uint32_t)ffbrates.dividers[i].basediv); + uint32_t hidrate = (HID_BINTERVAL*ffbrates.dividers[i].hiddiv); + while((updatefreq/hidrate) > usbrate_base){ // Fall back if usb rate is still higher than supported + hidrate++; } - return s; + uint32_t hidfreq = updatefreq/hidrate; + s += "FFB "+std::to_string(updatefreq) + "Hz\nUSB " + std::to_string(hidfreq) + "Hz:"+std::to_string(i); + if(i < ffbrates.dividers.size()-1) + s += ","; } + return s; +} void FFBHIDMain::emergencyStop(bool reset){ control.emergency = !reset; axes_manager->emergencyStop(reset); } -//void FFBHIDMain::timerElapsed(TIM_HandleTypeDef* htim){ -// -//} - /** * USB unplugged @@ -257,6 +309,7 @@ void FFBHIDMain::usbResume(){ control.emergency = false; } #endif + setReportRate(this->usb_report_rate_idx); control.usb_disabled = false; axes_manager->usbResume(); } @@ -305,3 +358,11 @@ void FFBHIDMain::errorCallback(const Error &error, bool cleared){ } } +#ifdef TIM_FFB +void FFBHIDMain::timerElapsed(TIM_HandleTypeDef* htim){ + if(htim == &TIM_FFB){ + NotifyFromISR(); + } +} +#endif + From c2f784e0e2b01bcca7b2c4612a6835a797ec7946 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Wed, 6 Mar 2024 11:57:37 +0100 Subject: [PATCH 14/40] Added tasklist --- Firmware/FFBoard/Inc/SystemCommands.h | 2 +- Firmware/FFBoard/Src/SystemCommands.cpp | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Firmware/FFBoard/Inc/SystemCommands.h b/Firmware/FFBoard/Inc/SystemCommands.h index 46ef39695..ec6118529 100644 --- a/Firmware/FFBoard/Inc/SystemCommands.h +++ b/Firmware/FFBoard/Inc/SystemCommands.h @@ -11,7 +11,7 @@ #include "CommandHandler.h" enum class FFBoardMain_commands : uint32_t{ - help=0,save=1,reboot=2,dfu=3,swver=4,hwtype=5,lsmain,main,lsactive,format,errors,errorsclr,flashdump,flashraw,vint,vext,mallinfo,heapfree,taskstats,debug,devid,uid,temp,otp,signature + help=0,save=1,reboot=2,dfu=3,swver=4,hwtype=5,lsmain,main,lsactive,format,errors,errorsclr,flashdump,flashraw,vint,vext,mallinfo,heapfree,taskstats,debug,devid,uid,temp,otp,signature,tasklist }; class SystemCommands : public CommandHandler { diff --git a/Firmware/FFBoard/Src/SystemCommands.cpp b/Firmware/FFBoard/Src/SystemCommands.cpp index c42b0918a..9874be82f 100644 --- a/Firmware/FFBoard/Src/SystemCommands.cpp +++ b/Firmware/FFBoard/Src/SystemCommands.cpp @@ -61,7 +61,7 @@ void SystemCommands::registerCommands(){ CommandHandler::registerCommand("errors", FFBoardMain_commands::errors, "Read error states",CMDFLAG_GET); CommandHandler::registerCommand("errorsclr", FFBoardMain_commands::errorsclr, "Reset errors",CMDFLAG_GET); CommandHandler::registerCommand("heapfree", FFBoardMain_commands::heapfree, "Memory info",CMDFLAG_GET); -#if configUSE_STATS_FORMATTING_FUNCTIONS> 0 +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) CommandHandler::registerCommand("taskstats", FFBoardMain_commands::taskstats, "Task stats",CMDFLAG_GET); #endif CommandHandler::registerCommand("format", FFBoardMain_commands::format, "set format=1 to erase all stored values",CMDFLAG_SET); @@ -77,6 +77,9 @@ void SystemCommands::registerCommands(){ #if defined(SIGNATURE) CommandHandler::registerCommand("signature", FFBoardMain_commands::signature, "Chip signature in OTP. setadr to write data. set=1 to lock",CMDFLAG_GETADR | CMDFLAG_SETADR | CMDFLAG_GET | CMDFLAG_INFOSTRING); #endif +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + CommandHandler::registerCommand("tasklist", FFBoardMain_commands::tasklist, "Task list",CMDFLAG_GET); +#endif } // Choose lower optimize level because the compiler likes to blow up this function @@ -218,7 +221,7 @@ CommandStatus SystemCommands::internalCommand(const ParsedCommand& cmd,std::vect } - case FFBoardMain_commands::mallinfo: // UNUSED since freertos + case FFBoardMain_commands::mallinfo: { CommandReply reply; struct mallinfo info = mallinfo(); @@ -238,14 +241,23 @@ CommandStatus SystemCommands::internalCommand(const ParsedCommand& cmd,std::vect replies.emplace_back(xPortGetFreeHeapSize(),xPortGetMinimumEverFreeHeapSize()); break; } -#if configUSE_STATS_FORMATTING_FUNCTIONS>0 +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) case FFBoardMain_commands::taskstats: { - char repl[800]; + char repl[uxTaskGetNumberOfTasks()*64]; vTaskGetRunTimeStats(repl); replies.emplace_back("\n"+std::string(repl)); break; } +#endif +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + case FFBoardMain_commands::tasklist: + { + char repl[uxTaskGetNumberOfTasks()*64]; + vTaskList(repl); + replies.emplace_back("\n"+std::string(repl)); + break; + } #endif case FFBoardMain_commands::lsactive: { From 862b383b7cf2fb2df6328da67a0bd67f2830d805 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Wed, 6 Mar 2024 15:07:38 +0100 Subject: [PATCH 15/40] Periodic effect sampling using microsecond counter --- Firmware/FFBoard/Src/EffectsCalculator.cpp | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Firmware/FFBoard/Src/EffectsCalculator.cpp b/Firmware/FFBoard/Src/EffectsCalculator.cpp index 6c8947919..5684fd975 100644 --- a/Firmware/FFBoard/Src/EffectsCalculator.cpp +++ b/Firmware/FFBoard/Src/EffectsCalculator.cpp @@ -188,15 +188,15 @@ int32_t EffectsCalculator::calcNonConditionEffectForce(FFB_Effect *effect) { case FFB_EFFECT_RAMP: { - uint32_t elapsed_time = HAL_GetTick() - effect->startTime; + float elapsed_time = (micros()/1000.0) - (float)effect->startTime; int32_t duration = effect->duration; - force_vector = (int32_t)effect->startLevel + ((int32_t)elapsed_time * (effect->endLevel - effect->startLevel)) / duration; + force_vector = (int32_t)effect->startLevel + (elapsed_time * (effect->endLevel - effect->startLevel)) / duration; break; } case FFB_EFFECT_SQUARE: { - uint32_t elapsed_time = HAL_GetTick() - effect->startTime; + uint32_t elapsed_time = HAL_GetTick() - effect->startTime; // Square is ms aligned int32_t force = ((elapsed_time + effect->phase) % ((uint32_t)effect->period + 2)) < (uint32_t)(effect->period + 2) / 2 ? -magnitude : magnitude; force_vector = force + effect->offset; break; @@ -206,16 +206,16 @@ int32_t EffectsCalculator::calcNonConditionEffectForce(FFB_Effect *effect) { { int32_t force = 0; int32_t offset = effect->offset; - uint32_t elapsed_time = HAL_GetTick() - effect->startTime; + float elapsed_time = micros() - ((float)effect->startTime*1000.0); uint32_t phase = effect->phase; uint32_t period = effect->period; float periodF = period; int32_t maxMagnitude = offset + magnitude; int32_t minMagnitude = offset - magnitude; - uint32_t phasetime = (phase * period) / 35999; - uint32_t timeTemp = elapsed_time + phasetime; - float remainder = timeTemp % period; + float phasetime = (phase * period) / 35999.0; + uint32_t timeTemp = elapsed_time + (phasetime*1000); // timetemp in µs + float remainder = (timeTemp % (period*1000)) / 1000; float slope = ((maxMagnitude - minMagnitude) * 2) / periodF; if (remainder > (periodF / 2)) force = slope * (periodF - remainder); @@ -229,16 +229,16 @@ int32_t EffectsCalculator::calcNonConditionEffectForce(FFB_Effect *effect) { case FFB_EFFECT_SAWTOOTHUP: { float offset = effect->offset; - uint32_t elapsed_time = HAL_GetTick() - effect->startTime; + float elapsed_time = micros() - ((float)effect->startTime*1000.0); uint32_t phase = effect->phase; uint32_t period = effect->period; float periodF = effect->period; float maxMagnitude = offset + magnitude; float minMagnitude = offset - magnitude; - int32_t phasetime = (phase * period) / 35999; - uint32_t timeTemp = elapsed_time + phasetime; - float remainder = timeTemp % period; + float phasetime = (phase * period) / 35999.0; + uint32_t timeTemp = elapsed_time + (phasetime*1000); // timetemp in µs + float remainder = (timeTemp % (period*1000)) / 1000; float slope = (maxMagnitude - minMagnitude) / periodF; force_vector = (int32_t)(minMagnitude + slope * (period - remainder)); break; @@ -247,16 +247,16 @@ int32_t EffectsCalculator::calcNonConditionEffectForce(FFB_Effect *effect) { case FFB_EFFECT_SAWTOOTHDOWN: { float offset = effect->offset; - uint32_t elapsed_time = HAL_GetTick() - effect->startTime; + float elapsed_time = micros() - ((float)effect->startTime*1000.0); float phase = effect->phase; uint32_t period = effect->period; float periodF = effect->period; float maxMagnitude = offset + magnitude; float minMagnitude = offset - magnitude; - int32_t phasetime = (phase * period) / 35999; - uint32_t timeTemp = elapsed_time + phasetime; - float remainder = timeTemp % period; + float phasetime = (phase * period) / 35999.0; + uint32_t timeTemp = elapsed_time + (phasetime*1000); // timetemp in µs + float remainder = (timeTemp % (period*1000)) / 1000; float slope = (maxMagnitude - minMagnitude) / periodF; force_vector = (int32_t)(minMagnitude + slope * (remainder)); // reverse time break; @@ -264,7 +264,7 @@ int32_t EffectsCalculator::calcNonConditionEffectForce(FFB_Effect *effect) { case FFB_EFFECT_SINE: { - float t = HAL_GetTick() - effect->startTime; + float t = (micros()/1000.0) - (float)effect->startTime; float freq = 1.0f / (float)(std::max(effect->period, 2)); float phase = (float)effect->phase / (float)35999; //degrees float sine = sinf(2.0 * M_PI * (t * freq + phase)) * magnitude; From ffde94f1673ea2a480f35b53b5c30f7898a136e1 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Wed, 6 Mar 2024 15:22:03 +0100 Subject: [PATCH 16/40] Corrected tmc hw config defines --- Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp index 8dfd8c4c0..1062d05f6 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp @@ -4,10 +4,12 @@ * Created on: Feb 20, 2024 * Author: Yannick */ + #include "TMC4671.h" #include "constants.h" +#include "span" -#ifndef TMC4671_OVERRIDE_HWCONFS +#if !defined(TMC4671_OVERRIDE_HWCONFS) && defined(TMC4671DRIVER) // Default configs for officially supported hardware From b4497d537306bb0cf2d36d68fcebd480d6d03532 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 12 Mar 2024 15:34:35 +0100 Subject: [PATCH 17/40] TMC4671 corrected brake pin settings. Must be 0xffff to keep pin off. --- Firmware/FFBoard/UserExtensions/Inc/TMC4671.h | 4 ++-- Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h index 425f76ae3..e418f4377 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h +++ b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h @@ -104,8 +104,8 @@ struct TMC4671HardwareTypeConf{ float currentScaler = TMC4671_DEFAULT_CURRENT_SCALER; // Converts from adc counts to current in Amps - uint16_t brakeLimLow = 0; - uint16_t brakeLimHigh = 0; + uint16_t brakeLimLow = 0xffff; + uint16_t brakeLimHigh = 0xffff; float vmScaler = (2.5 / 0x7fff) * ((1.5+71.5)/1.5); float vSenseMult = VOLTAGE_MULT_DEFAULT; float clockfreq = TMC4671_DEFAULT_CLOCKFREQ; diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index 38ef00d46..5dc16bf74 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -180,6 +180,9 @@ void TMC4671::restoreFlash(){ if(Flash_Read(flashAddrs.encA, &miscval)){ restoreEncHallMisc(miscval); encHallRestored = true; + }else{ + // set first hwconf if we can't restore + this->setHwType(TMC4671::tmc4671_hw_configs[0].hwVersion); } uint16_t filterval; if(Flash_Read(flashAddrs.torqueFilter, &filterval)){ @@ -2060,7 +2063,11 @@ void TMC4671::setFluxTorque(int16_t flux, int16_t torque){ if(curMotionMode != MotionMode::torque && !emergency){ setMotionMode(MotionMode::torque,true); } +#ifdef TMC4671_TORQUE_USE_ASYNC + writeRegAsync(0x64, (flux & 0xffff) | (torque << 16)); +#else writeReg(0x64, (flux & 0xffff) | (torque << 16)); +#endif } void TMC4671::setFluxTorqueFF(int16_t flux, int16_t torque){ @@ -2272,7 +2279,7 @@ void TMC4671::setTorqueFilter(TMC4671Biquad_conf& conf){ /** * Sets the raw brake resistor limits. * Centered at 0x7fff - * Set both 0 to deactivate + * Set both 0xffff to deactivate */ void TMC4671::setBrakeLimits(uint16_t low,uint16_t high){ uint32_t val = low | (high << 16); From b9aeefebbbabac63f7b11e7e23a487da0d7997a5 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 19 Mar 2024 12:20:39 +0100 Subject: [PATCH 18/40] Removed micros timer from canbridge --- Firmware/FFBoard/UserExtensions/Src/CanBridge.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/CanBridge.cpp b/Firmware/FFBoard/UserExtensions/Src/CanBridge.cpp index 9708e8908..5b013463c 100644 --- a/Firmware/FFBoard/UserExtensions/Src/CanBridge.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/CanBridge.cpp @@ -12,8 +12,6 @@ #include "ledEffects.h" #include "cdc_device.h" -extern TIM_TypeDef TIM_MICROS; - ClassIdentifier CanBridge::info = { .name = "CAN Bridge (GVRET)" , .id=CLSID_MAIN_CAN, @@ -63,9 +61,9 @@ void CanBridge::sendMessage(uint32_t id, uint64_t msg,uint8_t len = 8,bool rtr = txHeader.id = id; txHeader.length = len; txHeader.rtr = rtr; - if(id & 1 << 31){ + if(id & 0x80000000){ txHeader.extId = true; - id &= 0x7FFFFFFF; + txHeader.id &= 0x7FFFFFFF; }else{ txHeader.extId = false; } @@ -102,10 +100,9 @@ void CanBridge::update(){ CAN_msg_header_rx rxHeader = msg.header; uint32_t time = rxHeader.timestamp; uint32_t id = rxHeader.id; -// if(rxHeader.ExtId != 0){ -// id = rxHeader.ExtId; -// id |= 0x80000000; -// } + if(rxHeader.extId){ + id |= 0x80000000; + } std::vector reply = { 0xF1,0,(char)(time & 0xff), (char)((time >> 8) & 0xff), (char)((time >> 16) & 0xff), (char)((time >> 24) & 0xff), (char)(id & 0xff), (char)((id >> 8) & 0xff), (char)((id >> 16) & 0xff), (char)((id >> 24) & 0xff), From 2e368c3ef122e1574b4fc280e0966131661a310a Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 19 Mar 2024 12:23:50 +0100 Subject: [PATCH 19/40] Default ffb rate option --- Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h index b383b95d7..d3e4fa6a0 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h +++ b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h @@ -101,9 +101,9 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto */ void setReportRate(uint8_t rateidx); uint8_t usb_report_rate = HID_BINTERVAL; //for FS USB 1 = 1000hz, 2 = 500hz, 3 = 333hz 4 = 250hz, 5 = 200hz 6 = 166hz, 8 = 125hz etc... - uint8_t usb_report_rate_idx = 0; + uint8_t usb_report_rate_idx = ffbrates.defaultmode; #ifndef TIM_FFB - uint8_t ffb_rate_divider = 0; + uint8_t ffb_rate_divider = 0; // TODO support ffb without timers again #endif @@ -112,15 +112,17 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto uint8_t basediv; uint8_t hiddiv; }; + #if TUD_OPT_HIGH_SPEED // divider pair + const uint8_t defaultmode = 3; uint32_t basefreq = 8000; std::array dividers = {{{1,1},{2,1},{4,1},{8,1},{16,1},{32,1},{64,1}}}; // 8khz to 125hz #else + const uint8_t defaultmode = 0; uint32_t basefreq = 1000; std::array dividers = {{{1,1},{2,1},{4,1},{8,1}}}; // 8 entries max. 1khz to 125hz #endif }; - //const uint8_t usb_report_rates[4] = {1,2,4,8}; // Maps stored hid speed to report rates const static FFB_update_rates ffbrates; std::string usb_report_rates_names(); From 8a4683fa86a7598358525d49020e36a7f72cca71 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 2 Apr 2024 12:14:43 +0200 Subject: [PATCH 20/40] Axis always returns a 32b value. mainclass does the scaling in 16b mode. --- Firmware/FFBoard/Src/Axis.cpp | 4 ---- Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Firmware/FFBoard/Src/Axis.cpp b/Firmware/FFBoard/Src/Axis.cpp index cc9c717bc..400421dee 100644 --- a/Firmware/FFBoard/Src/Axis.cpp +++ b/Firmware/FFBoard/Src/Axis.cpp @@ -556,11 +556,7 @@ metric_t* Axis::getMetrics() { * Returns position as int scaled to gamepad range */ int32_t Axis::getLastScaledEnc() { -#if defined(HIDAXISRES_32B) return clip(metric.current.pos_f * 0x7fffffff,-0x7fffffff,0x7fffffff); // Calc from float pos -#else - return clip(metric.current.pos_scaled_16b,-0x7fff,0x7fff); -#endif } /** diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 28ac4e58f..fe957e2a1 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -182,6 +182,9 @@ void FFBHIDMain::send_report(){ std::vector* axes = axes_manager->getAxisValues(); uint8_t count = 0; for(auto val : *axes){ +#if !defined(HIDAXISRES_32B) + val = val >> 16; // Scale to 16b +#endif setHidReportAxis(&reportHID,count++,val); } From 29ddbd3d6b795e1c33427fe249645ad24a9da4db Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 2 Apr 2024 12:15:13 +0200 Subject: [PATCH 21/40] Prepared usb descriptor splitting. # Conflicts: # Firmware/FFBoard/UserExtensions/Inc/usb_descriptors.h # Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp --- .../FFBoard/UserExtensions/Inc/FFBHIDMain.h | 4 +- .../UserExtensions/Inc/usb_descriptors.h | 14 +- .../UserExtensions/Inc/usb_hid_ffb_desc.h | 754 +++++++++- .../FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 15 +- .../UserExtensions/Src/usb_descriptors.cpp | 48 +- .../UserExtensions/Src/usb_hid_1ffb_desc.c | 697 +++------ .../UserExtensions/Src/usb_hid_2ffb_desc.c | 1283 +++++++++-------- .../UserExtensions/Src/usb_hid_gamepad.c | 131 +- 8 files changed, 1627 insertions(+), 1319 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h index d3e4fa6a0..bdb0bd200 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h +++ b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h @@ -43,7 +43,7 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto }; public: - FFBHIDMain(uint8_t axisCount); + FFBHIDMain(uint8_t axisCount,bool hidAxis32b = false); virtual ~FFBHIDMain(); void setFFBEffectsCalc(std::shared_ptr ffb,std::shared_ptr effects_calc); @@ -125,6 +125,8 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto }; const static FFB_update_rates ffbrates; + const bool hidAxis32b; + std::string usb_report_rates_names(); uint8_t report_rate_cnt = 0; diff --git a/Firmware/FFBoard/UserExtensions/Inc/usb_descriptors.h b/Firmware/FFBoard/UserExtensions/Inc/usb_descriptors.h index b4d6d8ee8..ef8507300 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/usb_descriptors.h +++ b/Firmware/FFBoard/UserExtensions/Inc/usb_descriptors.h @@ -24,6 +24,16 @@ typedef struct usb_string_desc const std::vector interfaces; } usb_string_desc_t; +/* + * Base combined usb config descriptor for HID and CDC composite device + */ +#define USB_CONF_DESC_HID_CDC(HIDREPSIZE,EPSIZE) \ + /* Config number, interface count, string index, total length, attribute, power in mA*/\ + TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP | TUSB_DESC_CONFIG_ATT_SELF_POWERED, 100),\ + /* 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.*/\ + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, EPSIZE),\ + /* HID Descriptor. EP 83 and 2*/\ + TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, HIDREPSIZE, 0x83, 0x02,EPSIZE, HID_BINTERVAL) /* * Device descriptors @@ -42,7 +52,9 @@ extern const uint8_t usb_cdc_hid_conf_1axis[]; #ifdef AXIS2_FFB_HID_DESC extern const uint8_t usb_cdc_hid_conf_2axis[]; #endif - +#ifdef AXIS2_FFB_HID_DESC_32B +extern const uint8_t usb_cdc_hid_conf_2axis_32b[]; +#endif #ifdef FFB_HID_DESC_GAMEPAD extern const uint8_t usb_cdc_hid_conf_gamepad[]; #endif diff --git a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h index ea9aee670..61b3fccfd 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h +++ b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h @@ -8,8 +8,28 @@ #ifndef USB_INC_USB_HID_FFB_DESC_H_ #define USB_INC_USB_HID_FFB_DESC_H_ #include "constants.h" +#include "hid.h" -#if defined(HIDAXISRES_32B) +//#if defined(HIDAXISRES_32B) +//#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 + 16 +//#else +//#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 +//#endif +//#ifdef AXIS1_FFB_HID_DESC +//extern const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE]; +//#endif + +//#if defined(HIDAXISRES_32B) +//#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 + 16 +//#else +//#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 +//#endif + + + + + +// HID descriptor building blocks #define HIDDESC_32B_ENTRY(count) /* LOGICAL_MINIMUM (-7FFFFFFF)*/\ 0x17, 0x01, 0x00, 0x00, 0x80, \ /* LOGICAL_MAXIMUM (7FFFFFFF)*/\ @@ -21,34 +41,738 @@ /* INPUT (Data,Var,Abs)*/\ 0x81, 0x02, #define HIDDESC_32B_ENTRY_SIZE 12 // 12 bytes extra for additional 16b definition 2B count -#endif -#if defined(HIDAXISRES_32B) -#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 + 16 + +#define HIDDESC_GAMEPAD_16B \ + 0xa1, 0x00, /* COLLECTION (Physical)*/\ + 0x85, 0x01, /* REPORT_ID (1)*/\ + 0x05, 0x09, /* USAGE_PAGE (Button)*/\ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1)*/\ + 0x29, 0x40, /* USAGE_MAXIMUM (Button 64)*/\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0)*/\ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1)*/\ + 0x95, 0x40, /* REPORT_COUNT (64)*/\ + 0x75, 0x01, /* REPORT_SIZE (1)*/\ + 0x81, 0x02, /* INPUT (Data,Var,Abs)*/\ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/\ + 0x09, HID_USAGE_DESKTOP_X, /* USAGE (X)*/\ + 0x09, HID_USAGE_DESKTOP_Y, /* USAGE (Y)*/\ + 0x09, HID_USAGE_DESKTOP_Z, /* USAGE (Z)*/\ + 0x09, HID_USAGE_DESKTOP_RX, /* USAGE (Rx)*/\ + 0x09, HID_USAGE_DESKTOP_RY, /* USAGE (Ry)*/\ + 0x09, HID_USAGE_DESKTOP_RZ, /* USAGE (Rz)*/\ + 0x09, HID_USAGE_DESKTOP_DIAL, /* USAGE (Dial)*/\ + 0x09, HID_USAGE_DESKTOP_SLIDER, /* USAGE (Slider)*/\ + 0x16, 0x01, 0x80, /* LOGICAL_MINIMUM (-32767)*/\ + 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767)*/\ + 0x75, 0x10, /* REPORT_SIZE (16)*/\ + 0x95, 0x08, /* REPORT_COUNT (8)*/\ + 0x81, 0x02, /* INPUT (Data,Var,Abs)*/\ + 0xc0 +#define HIDDESC_GAMEPAD_16B_SIZE 51 + +// Define workaround because we can't have conditionals in macros +#if MAX_AXIS == 1 +#define HIDDESC_GPENTRY_32B_1 0x09, HID_USAGE_DESKTOP_X, /* USAGE (X)*/\ + HIDDESC_32B_ENTRY(0x01) #else -#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 +#define HIDDESC_GPENTRY_32B_1 0x09, HID_USAGE_DESKTOP_X, /* USAGE (X)*/ #endif -#ifdef AXIS1_FFB_HID_DESC -extern const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE]; +#if MAX_AXIS == 2 +#define HIDDESC_GPENTRY_32B_2 0x09, HID_USAGE_DESKTOP_Y, /* USAGE (Y)*/\ + HIDDESC_32B_ENTRY(0x02) +#else +#define HIDDESC_GPENTRY_32B_2 0x09, HID_USAGE_DESKTOP_Y, /* USAGE (Y)*/ #endif - -#if defined(HIDAXISRES_32B) -#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 + 16 +#if MAX_AXIS == 3 +#define HIDDESC_GPENTRY_32B_3 0x09, HID_USAGE_DESKTOP_Z, /* USAGE (Z)*/\ + HIDDESC_32B_ENTRY(0x02) #else -#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 +#define HIDDESC_GPENTRY_32B_3 0x09, HID_USAGE_DESKTOP_Z, /* USAGE (Z)*/ #endif +#define HIDDESC_GAMEPAD_32B \ + 0xa1, 0x00, /* COLLECTION (Physical)*/\ + 0x85, 0x01, /* REPORT_ID (1)*/\ + 0x05, 0x09, /* USAGE_PAGE (Button)*/\ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1)*/\ + 0x29, 0x40, /* USAGE_MAXIMUM (Button 64)*/\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0)*/\ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1)*/\ + 0x95, 0x40, /* REPORT_COUNT (64)*/\ + 0x75, 0x01, /* REPORT_SIZE (1)*/\ + 0x81, 0x02, /* INPUT (Data,Var,Abs)*/\ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/\ + HIDDESC_GPENTRY_32B_1 \ + HIDDESC_GPENTRY_32B_2 \ + HIDDESC_GPENTRY_32B_3 \ + 0x09, HID_USAGE_DESKTOP_RX, /* USAGE (Rx)*/\ + 0x09, HID_USAGE_DESKTOP_RY, /* USAGE (Ry)*/\ + 0x09, HID_USAGE_DESKTOP_RZ, /* USAGE (Rz)*/\ + 0x09, HID_USAGE_DESKTOP_DIAL, /* USAGE (Dial)*/\ + 0x09, HID_USAGE_DESKTOP_SLIDER, /* USAGE (Slider)*/\ + 0x16, 0x01, 0x80, /* LOGICAL_MINIMUM (-32767)*/\ + 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767)*/\ + 0x75, 0x10, /* REPORT_SIZE (16)*/\ + 0x95, 0x08-MAX_AXIS, /* REPORT_COUNT (8-32baxes)*/\ + 0x81, 0x02, /* INPUT (Data,Var,Abs)*/\ + 0xc0 +#define HIDDESC_GAMEPAD_32B_SIZE HIDDESC_GAMEPAD_16B_SIZE + HIDDESC_32B_ENTRY_SIZE +// Control reports for HID command interface +#define HIDDESC_CTRL_REP(DIR) /* INPUT or OUTPUT*/\ + 0x85,HID_ID_HIDCMD, /* Report ID*/\ + 0x09, 0x01, /* USAGE (Vendor)*/\ + 0x15, 0x00, /* LOGICAL_MINIMUM (0)*/\ + 0x26, 0x04, 0x00, /* Logical Maximum 4*/\ + 0x75, 0x08, /* REPORT_SIZE (8)*/\ + 0x95, 0x01, /* REPORT_COUNT (1)*/\ + HID_##DIR(1), /* INPUT (Data,Var,Abs)*/\ + \ + 0x09, 0x02, /* USAGE (Vendor) class address*/\ + 0x75, 0x10, /* REPORT_SIZE (16)*/\ + 0x95, 0x01, /* REPORT_COUNT (1)*/\ + HID_##DIR(1), /* INPUT (Data,Var,Abs)*/\ + \ + 0x09, 0x03, /* USAGE (Vendor) class instance*/\ + 0x75, 0x08, /* REPORT_SIZE (8)*/\ + 0x95, 0x01, /* REPORT_COUNT (1)*/\ + HID_##DIR(1), /* INPUT (Data,Var,Abs)*/\ + \ + 0x09, 0x04, /* USAGE (Vendor) cmd*/\ + 0x75, 0x20, /* REPORT_SIZE (32)*/\ + 0x95, 0x01, /* REPORT_COUNT (1)*/\ + HID_##DIR(1), /* INPUT (Data,Var,Abs)*/\ + \ + 0x09, 0x05, /* USAGE (Vendor)*/\ + 0x75, 0x40, /* REPORT_SIZE (64) value*/\ + 0x95, 0x01, /* REPORT_COUNT (1)*/\ + HID_##DIR(1), /* INPUT (Data,Var,Abs)*/\ + \ + 0x09, 0x06, /* USAGE (Vendor) address*/\ + 0x75, 0x40, /* REPORT_SIZE (64)*/\ + 0x95, 0x01, /* REPORT_COUNT (1)*/\ + HID_##DIR(1) /* INPUT (Data,Var,Abs)*/ +#define HIDDESC_CTRL_REPORTS \ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor)*/\ + 0x09, 0x00, /* USAGE (Vendor)*/\ + 0xA1, 0x01, /* Collection (Application)*/\ + HIDDESC_CTRL_REP(OUTPUT),\ + HIDDESC_CTRL_REP(INPUT),\ + 0xc0 /* END_COLLECTION*/ +#define HIDDESC_CTRL_REPORTS_SIZE 118 + +#define HIDDESC_FFB_STATEREP \ + 0x05,0x0F, /* Usage Page Physical Interface*/ \ + 0x09,0x92, /* Usage PID State report*/\ + 0xA1,0x02, /* Collection Datalink (logical)*/\ + 0x85,HID_ID_STATE+FFB_ID_OFFSET, /* Report ID 2*/\ +/* 0x09,0x22, Usage Effect Block Index*/\ +/* 0x15,0x01, Logical Minimum 1*/\ +/* 0x25,MAX_EFFECTS, Logical Maximum 28h (40d)*/\ +/* 0x35,0x01, Physical Minimum 1*/\ +/* 0x45,MAX_EFFECTS, Physical Maximum 28h (40d)*/\ +/* 0x75,0x08, Report Size 8*/\ +/* 0x95,0x01, Report Count 1*/\ +/* 0x81,0x02, Input (Variable)*/\ + 0x09,0x9F, /* Usage Device is Pause*/\ + 0x09,0xA0, /* Usage Actuators Enabled*/\ + 0x09,0xA4, /* Usage Safety Switch*/\ + 0x09,0xA6, /* Usage Actuator Power*/\ + 0x09,0x94, /* Usage Effect Playing*/\ + /* 0x15,0x00, Logical Minimum 0*/\ + /* 0x25,0x01, Logical Maximum 1*/\ + /* 0x35,0x00, Physical Minimum 0*/\ + /* 0x45,0x01, Physical Maximum 1*/\ + /* 0x75,0x01, Report Size 1*/\ + /* 0x95,0x01, Report Count 1*/\ + /* 0x81,0x02, Input (Variable)*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x25,0x01, /* Logical Maximum 1*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x45,0x01, /* Physical Maximum 1*/\ + 0x75,0x01, /* Report Size 1*/\ + 0x95,0x05, /* Report Count 4*/\ + 0x81,0x02, /* Input (Variable)*/\ + 0x95,0x03, /* Report Count 3*/\ + 0x81,0x03, /* Input (Constant, Variable)*/\ + 0xC0 // End Collection +#define HIDDESC_FFB_STATEREP_SIZE 37 + +/* +Output +Collection Datalink: +Usage Set Effect Report + +ID:1 +Effect Block Index: 8bit + +subcollection Effect Type +12 effect types, 8bit each + +*/ +#define HIDDESC_FFB_SETEFREP \ + 0x09,0x21, /* Usage Set Effect Report*/\ + 0xA1,0x02, /* Collection Datalink (Logical)*/\ + 0x85,HID_ID_EFFREP+FFB_ID_OFFSET, /* Report ID 1*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x25, /* Usage Effect Type*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x09, HID_USAGE_CONST, /* Usage ET Constant Force*/\ + 0x09, HID_USAGE_RAMP, /* Usage ET Ramp*/\ + 0x09, HID_USAGE_SQUR, /* Usage ET Square*/\ + 0x09, HID_USAGE_SINE, /* Usage ET Sine*/\ + 0x09, HID_USAGE_TRNG, /* Usage ET Triangle*/\ + 0x09, HID_USAGE_STUP, /* Usage ET Sawtooth Up*/\ + 0x09, HID_USAGE_STDN, /* Usage ET Sawtooth Down*/\ + 0x09, HID_USAGE_SPRNG, /* Usage ET Spring*/\ + 0x09, HID_USAGE_DMPR, /* Usage ET Damper*/\ + 0x09, HID_USAGE_INRT, /* Usage ET Inertia*/\ + 0x09, HID_USAGE_FRIC, /* Usage ET Friction*/\ + /* 0x09, 0x28, // Usage ET Custom Force Data*/\ + 0x25,0x0B, /* Logical Maximum Bh (11d)*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,0x0B, /* Physical Maximum Bh (11d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x00, /* Output*/\ + 0xC0 , /* End Collection*/\ + 0x09,0x50, /* Usage Duration*/\ + 0x09,0x54, /* Usage Trigger Repeat Interval*/\ + 0x09,0x51, /* Usage Sample Period*/\ + 0x09,0xA7, /* Usage Start Delay*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x26,0xFF,0x7F, /* Logical Maximum 7FFFh (32767d)*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x46,0xFF,0x7F, /* Physical Maximum 7FFFh (32767d)*/\ + 0x66,0x03,0x10, /* Unit 1003h (4099d)*/\ + 0x55,0xFD, /* Unit Exponent FDh (253d)*/\ + 0x75,0x10, /* Report Size 10h (16d)*/\ + 0x95,0x04, /* Report Count 4*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x55,0x00, /* Unit Exponent 0*/\ + 0x66,0x00,0x00, /* Unit 0*/\ + 0x09,0x52, /* Usage Gain*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x26,0xFF,0x00, /* Logical Maximum FFh (255d) // TODO scaling?*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x46,0x10,0x27, /* Physical Maximum 2710h (10000d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x53, /* Usage Trigger Button*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,0x08, /* Logical Maximum 8*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,0x08, /* Physical Maximum 8*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02 // Output (Variable) +#define HIDDESC_FFB_SETEFREP_SIZE 131 + +#define HIDDESC_FFB_SETENVREP \ + /* Envelope Report Definition*/\ + 0x09,0x5A, /* Usage Set Envelope Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_ENVREP+FFB_ID_OFFSET, /* Report ID 2*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x5B, /* Usage Attack Level*/\ + 0x09,0x5D, /* Usage Fade Level*/\ + 0x16,0x00,0x00, /* Logical Minimum 0*/\ + 0x26,0xFF,0x7F, /* Logical Maximum 7FFFh (32767d)*/\ + 0x36,0x00,0x00, /* Physical Minimum 0*/\ + 0x46,0xFF,0x7F, /* Physical Maximum 7FFFh (32767d)*/\ + 0x75,0x10, /* Report Size 16*/\ + 0x95,0x02, /* Report Count 2*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09, 0x5C, /* Usage Attack Time*/\ + 0x09, 0x5E, /* Usage Fade Time*/\ + 0x66, 0x03, 0x10, /* Unit 1003h (English Linear, Seconds)*/\ + 0x55, 0xFD, /* Unit Exponent FDh (X10^-3 ==> Milisecond)*/\ + 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum FFFFFFFFh (4294967295)*/\ + 0x47, 0xFF, 0x7F, 0x00, 0x00, /* Physical Maximum FFFFFFFFh (4294967295)*/\ + 0x75, 0x20, /* Report Size 20h (32d)*/\ + 0x91, 0x02, /* Output (Variable)*/\ + 0x45, 0x00, /* Physical Maximum 0*/\ + 0x66,0x00,0x00, /* Unit 0*/\ + 0x55,0x00, /* Unit Exponent 0*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_SETENVREP_SIZE 75 + +// Contains axis dependant parts. not used +#define HIDDESC_FFB_SETCONDREP \ + 0x09,0x5F, /* Usage Set Condition Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_CONDREP+FFB_ID_OFFSET, /* Report ID 3*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x23, /* Usage Parameter Block Offset*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x25,0x03, /* Logical Maximum 3*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x45,0x03, /* Physical Maximum 3*/\ + 0x75,0x04, /* Report Size 4*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x58, /* Usage Type Specific Block Off...*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x0B,0x01,0x00,0x0A,0x00, /* Usage Ordinals: Instance 1*/\ + 0x0B,0x02,0x00,0x0A,0x00, /* Usage Ordinals: Instance 2*/\ + 0x75,0x02, /* Report Size 2*/\ + 0x95,0x02, /* Report Count 2*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 , /* End Collection*/\ + 0x16,0x00, 0x80, /* Logical Minimum 7FFFh (-32767d)*/\ + 0x26,0xff, 0x7f, /* Logical Maximum 7FFFh (32767d)*/\ + 0x36,0x00, 0x80, /* Physical Minimum 7FFFh (-32767d)*/\ + 0x46,0xff, 0x7f, /* Physical Maximum 7FFFh (32767d)*/\ +\ + 0x09,0x60, /* Usage CP Offset*/\ + 0x75,0x10, /* Report Size 16*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x36,0x00, 0x80, /* Physical Minimum (-32768)*/\ + 0x46,0xff, 0x7f, /* Physical Maximum (32767)*/\ + 0x09,0x61, /* Usage Positive Coefficient*/\ + 0x09,0x62, /* Usage Negative Coefficient*/\ + 0x95,0x02, /* Report Count 2*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x16,0x00,0x00, /* Logical Minimum 0*/\ + 0x26,0xff, 0x7f, /* Logical Maximum (32767)*/\ + 0x36,0x00,0x00, /* Physical Minimum 0*/\ + 0x46,0xff, 0x7f, /* Physical Maximum (32767)*/\ + 0x09,0x63, /* Usage Positive Saturation*/\ + 0x09,0x64, /* Usage Negative Saturation*/\ + 0x75,0x10, /* Report Size 16*/\ + 0x95,0x02, /* Report Count 2*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x65, /* Usage Dead Band*/\ + 0x46,0xff, 0x7f, /* Physical Maximum (32767)*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_SETCONDREP_SIZE 125 + +#define HIDDESC_FFB_SETPERIODICREP \ + 0x09,0x6E, /* Usage Set Periodic Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_PRIDREP+FFB_ID_OFFSET, /* Report ID 4*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x70, /* Usage Magnitude*/\ + 0x16,0x00,0x00, /* Logical Minimum 0*/\ + 0x26,0xff, 0x7f, /* Logical Maximum 7FFFh (32767d)*/\ + 0x36,0x00,0x00, /* Physical Minimum 0*/\ + 0x26,0xff, 0x7f, /* Logical Maximum 7FFFh (32767d)*/\ + 0x75,0x10, /* Report Size 16*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09, 0x6F, /* Usage Offset*/\ + 0x16,0x00, 0x80, /* Logical Minimum 7FFFh (-32767d)*/\ + 0x26,0xff, 0x7f, /* Logical Maximum 7FFFh (32767d)*/\ + 0x36,0x00, 0x80, /* Physical Minimum 7FFFh (-32767d)*/\ + 0x46,0xff, 0x7f, /* Physical Maximum 7FFFh (32767d)*/\ + 0x95, 0x01, /* Report Count 1*/\ + 0x75, 0x10, /* Report Size 16*/\ + 0x91, 0x02, /* Output (Variable)*/\ + 0x09, 0x71, /* Usage Phase*/\ + 0x66, 0x14, 0x00, /* Unit 14h (Eng Rotation, Degrees)*/\ + 0x55, 0xFE, /* Unit Exponent FEh (X10^-2)*/\ + 0x15, 0x00, /* Logical Minimum 0*/\ + 0x27, 0x9F, 0x8C, 0x00, 0x00, /* Logical Maximum 8C9Fh (35999d)*/\ + 0x35, 0x00, /* Physical Minimum 0*/\ + 0x47, 0x9F, 0x8C, 0x00, 0x00, /* Physical Maximum 8C9Fh (35999d)*/\ + 0x75, 0x10, /* Report Size 16*/\ + 0x95, 0x01, /* Report Count 1*/\ + 0x91, 0x02, /* Output (Variable)*/\ + 0x09, 0x72, /* Usage Period*/\ + 0x15, 0x01, /* Logical Minimum 1*/\ + 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum 7FFFh (32K)*/\ + 0x35, 0x01, /* Physical Minimum 1*/\ + 0x47, 0xFF, 0x7F, 0x00, 0x00, /* Physical Maximum 7FFFh (32K)*/\ + 0x66, 0x03, 0x10, /* Unit 1003h (English Linear, Seconds)*/\ + 0x55, 0xFD, /* Unit Exponent FDh (X10^-3 ==> Millisecond)*/\ + 0x75, 0x20, /* Report Size 20h (32)*/\ + 0x95, 0x01, /* Report Count 1*/\ + 0x91, 0x02, /* Output (Variable)*/\ + 0x66, 0x00, 0x00, /* Unit 0*/\ + 0x55,0x00, /* Unit Exponent 0*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_SETPERIODICREP_SIZE 122 + +#define HIDDESC_FFB_SETCFREP \ + 0x09,0x73, /* Usage Set Constant Force Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_CONSTREP+FFB_ID_OFFSET, /* Report ID 5*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x70, /* Usage Magnitude*/\ + 0x16,0x01, 0x80, /* Logical Minimum -7FFFh (-32767d)*/\ + 0x26,0xff, 0x7f, /* Logical Maximum 7FFFh (32767d)*/\ + 0x36,0x01, 0x80, /* Physical Minimum -7FFFh (-32767d)*/\ + 0x46,0xff, 0x7f, /* Physical Maximum 7FFFh (32767d)*/\ + 0x75, 0x10, /* Report Size 10h (16d)*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_SETCFREP_SIZE 43 + +#define HIDDESC_FFB_SETRAMPREP \ + 0x09,0x74, /* Usage Set Ramp Force Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_RAMPREP+FFB_ID_OFFSET, /* Report ID 6*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x75, /* Usage Ramp Start*/\ + 0x09,0x76, /* Usage Ramp End*/\ + 0x16,0x00, 0x80, /* Logical Minimum 7FFFh (-32767d)*/\ + 0x26,0xff, 0x7f, /* Logical Maximum 7FFFh (32767d)*/\ + 0x36,0x00, 0x80, /* Physical Minimum 7FFFh (-32767d)*/\ + 0x46,0xff, 0x7f, /* Physical Maximum 7FFFh (32767d)*/\ + 0x75,0x10, /* Report Size 16*/\ + 0x95,0x02, /* Report Count 2*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_SETRAMPREP_SIZE 45 +// not to be used yet +#define HIDDESC_FFB_CUSTOMFORCEREP \ +/* 0x09,0x68, // Usage Custom Force Data Report*/\ +/* 0xA1,0x02, // Collection Datalink*/\ +/* 0x85,HID_ID_CSTMREP+FFB_ID_OFFSET, // Report ID 7*/\ +/* 0x09,0x22, // Usage Effect Block Index*/\ +/* 0x15,0x01, // Logical Minimum 1*/\ +/* 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d)*/\ +/* 0x35,0x01, // Physical Minimum 1*/\ +/* 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d)*/\ +/* 0x75,0x08, // Report Size 8*/\ +/* 0x95,0x01, // Report Count 1*/\ +/* 0x91,0x02, // Output (Variable)*/\ +/* 0x09,0x6C, // Usage Custom Force Data Offset*/\ +/* 0x15,0x00, // Logical Minimum 0*/\ +/* 0x26,0x10,0x27, // Logical Maximum 2710h (10000d)*/\ +/* 0x35,0x00, // Physical Minimum 0*/\ +/* 0x46,0x10,0x27, // Physical Maximum 2710h (10000d)*/\ +/* 0x75,0x10, // Report Size 10h (16d)*/\ +/* 0x95,0x01, // Report Count 1*/\ +/* 0x91,0x02, // Output (Variable)*/\ +/* 0x09,0x69, // Usage Custom Force Data*/\ +/* 0x15,0x81, // Logical Minimum 81h (-127d)*/\ +/* 0x25,0x7F, // Logical Maximum 7Fh (127d)*/\ +/* 0x35,0x00, // Physical Minimum 0*/\ +/* 0x46,0xFF,0x00, // Physical Maximum FFh (255d)*/\ +/* 0x75,0x08, // Report Size 8*/\ +/* 0x95,0x0C, // Report Count Ch (12d)*/\ +/* 0x92,0x02,0x01, // Output (Variable, Buffered)*/\ +/* 0xC0 , // End Collection*/\ +/* 0x09,0x66, // Usage Download Force Sample*/\ +/* 0xA1,0x02, // Collection Datalink*/\ +/* 0x85,HID_ID_SMPLREP+FFB_ID_OFFSET, // Report ID 8*/\ +/* 0x05,0x01, // Usage Page Generic Desktop*/\ +/* 0x09,0x30, // Usage X*/\ +/* 0x09,0x31, // Usage Y*/\ +/* 0x15,0x81, // Logical Minimum 81h (-127d)*/\ +/* 0x25,0x7F, // Logical Maximum 7Fh (127d)*/\ +/* 0x35,0x00, // Physical Minimum 0*/\ +/* 0x46,0xFF,0x00, // Physical Maximum FFh (255d)*/\ +/* 0x75,0x08, // Report Size 8*/\ +/* 0x95,0x02, // Report Count 2*/\ +/* 0x91,0x02, // Output (Variable)*/\ +/* 0xC0 , // End Collection*/ +#define HIDDESC_FFB_EFOPREP \ + 0x05,0x0F, /* Usage Page Physical Interface*/\ + 0x09,0x77, /* Usage Effect Operation Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_EFOPREP+FFB_ID_OFFSET, /* Report ID Ah (10d)*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0x09,0x78, /* Usage Effect Operation*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x09,0x79, /* Usage Op Effect Start*/\ + 0x09,0x7A, /* Usage Op Effect Start Solo*/\ + 0x09,0x7B, /* Usage Op Effect Stop*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,0x03, /* Logical Maximum 3*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x00, /* Output*/\ + 0xC0 , /* End Collection*/\ + 0x09,0x7C, /* Usage Loop Count*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x26,0xFF,0x00, /* Logical Maximum FFh (255d)*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x46,0xFF,0x00, /* Physical Maximum FFh (255d)*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_EFOPREP_SIZE 60 +#define HIDDESC_FFB_BLOCKFREEREP \ + 0x09,0x90, /* Usage PID Block Free Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_BLKFRREP+FFB_ID_OFFSET, /* Report ID Bh (11d)*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_BLOCKFREEREP_SIZE 23 +#define HIDDESC_FFB_DEVCTRLREP \ + 0x09,0x95, /* Usage PID Device Control (0x96?)*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_CTRLREP+FFB_ID_OFFSET, /* Report ID Ch (12d)*/\ + 0x09,0x96, /* Usage PID Device Control (0x96?)*/\ + 0xA1,0x02, /* Collection Datalink*/\ +\ + 0x09,0x97, /* Usage DC Enable Actuators*/\ + 0x09,0x98, /* Usage DC Disable Actuators*/\ + 0x09,0x99, /* Usage DC Stop All Effects*/\ + 0x09,0x9A, /* Usage DC Device Reset*/\ + 0x09,0x9B, /* Usage DC Device Pause*/\ + 0x09,0x9C, /* Usage DC Device Continue*/\ +\ +\ +\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,0x06, /* Logical Maximum 6*/\ + 0x75,0x01, /* Report Size 1*/\ + 0x95,0x08, /* Report Count 8*/\ + 0x91,0x02, /* Output*/\ +\ + 0xC0 , /* End Collection*/\ + 0xC0 , /* End Collection*/\ + 0x09,0x7D, /* Usage Device Gain Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_GAINREP+FFB_ID_OFFSET, /* Report ID Dh (13d)*/\ + 0x09,0x7E, /* Usage Device Gain*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x26,0xFF,0x00, /* Logical Maximum FFh (255d)*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x46,0x10,0x27, /* Physical Maximum 2710h (10000d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x91,0x02, /* Output (Variable)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_DEVCTRLREP_SIZE 59 +// Do not use yet +#define HIDDESC_FFB_SETCUSTFORCEREP \ +/* 0x09,0x6B, // Usage Set Custom Force Report*/\ +/* 0xA1,0x02, // Collection Datalink*/\ +/* 0x85,HID_ID_SETCREP+FFB_ID_OFFSET, // Report ID Eh (14d)*/\ +/* 0x09,0x22, // Usage Effect Block Index*/\ +/* 0x15,0x01, // Logical Minimum 1*/\ +/* 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d)*/\ +/* 0x35,0x01, // Physical Minimum 1*/\ +/* 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d)*/\ +/* 0x75,0x08, // Report Size 8*/\ +/* 0x95,0x01, // Report Count 1*/\ +/* 0x91,0x02, // Output (Variable)*/\ +/* 0x09,0x6D, // Usage Sample Count*/\ +/* 0x15,0x00, // Logical Minimum 0*/\ +/* 0x26,0xFF,0x00, // Logical Maximum FFh (255d)*/\ +/* 0x35,0x00, // Physical Minimum 0*/\ +/* 0x46,0xFF,0x00, // Physical Maximum FFh (255d)*/\ +/* 0x75,0x08, // Report Size 8*/\ +/* 0x95,0x01, // Report Count 1*/\ +/* 0x91,0x02, // Output (Variable)*/\ +/* 0x09,0x51, // Usage Sample Period*/\ +/* 0x66,0x03,0x10, // Unit 1003h (4099d)*/\ +/* 0x55,0xFD, // Unit Exponent FDh (253d)*/\ +/* 0x15,0x00, // Logical Minimum 0*/\ +/* 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d)*/\ +/* 0x35,0x00, // Physical Minimum 0*/\ +/* 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d)*/\ +/* 0x75,0x10, // Report Size 10h (16d)*/\ +/* 0x95,0x01, // Report Count 1*/\ +/* 0x91,0x02, // Output (Variable)*/\ +/* 0x55,0x00, // Unit Exponent 0*/\ +/* 0x66,0x00,0x00, // Unit 0*/\ +/* 0xC0 // End Collection*/ +#define HIDDESC_FFB_NEWEFREP \ + 0x09,0xAB, /* Usage Create New Effect Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_NEWEFREP+FFB_ID_OFFSET, /* Report ID 1*/\ + 0x09,0x25, /* Usage Effect Type*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x09, HID_USAGE_CONST, /* Usage ET Constant Force*/\ + 0x09, HID_USAGE_RAMP, /* Usage ET Ramp*/\ + 0x09, HID_USAGE_SQUR, /* Usage ET Square*/\ + 0x09, HID_USAGE_SINE, /* Usage ET Sine*/\ + 0x09, HID_USAGE_TRNG, /* Usage ET Triangle*/\ + 0x09, HID_USAGE_STUP, /* Usage ET Sawtooth Up*/\ + 0x09, HID_USAGE_STDN, /* Usage ET Sawtooth Down*/\ + 0x09, HID_USAGE_SPRNG, /* Usage ET Spring*/\ + 0x09, HID_USAGE_DMPR, /* Usage ET Damper*/\ + 0x09, HID_USAGE_INRT, /* Usage ET Inertia*/\ + 0x09, HID_USAGE_FRIC, /* Usage ET Friction*/\ +/* 0x09, 0x28, // Usage ET Custom Force Data*/\ + 0x25,0x0B, /* Logical Maximum Ch (11d)*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,0x0B, /* Physical Maximum Ch (11d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x00, /* Feature*/\ + 0xC0 , /* End Collection*/\ + 0x05,0x01, /* Usage Page Generic Desktop*/\ + 0x09,0x3B, /* Usage Reserved (Byte count)*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x26,0xFF,0x01, /* Logical Maximum 1FFh (511d)*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x46,0xFF,0x01, /* Physical Maximum 1FFh (511d)*/\ + 0x75,0x0A, /* Report Size Ah (10d)*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x02, /* Feature (Variable)*/\ + 0x75,0x06, /* Report Size 6*/\ + 0xB1,0x01, /* Feature (Constant)*/\ + 0xC0 /* End Collection*/ +#define HIDDESC_FFB_NEWEFREP_SIZE 72 + +#define HIDDESC_FFB_BLOCKLOADREP \ + 0x05,0x0F, /* Usage Page Physical Interface*/\ + 0x09,0x89, /* Usage Block Load Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_BLKLDREP+FFB_ID_OFFSET, /* Report ID 0x12*/\ + 0x09,0x22, /* Usage Effect Block Index*/\ + 0x25,MAX_EFFECTS, /* Logical Maximum 28h (40d)*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,MAX_EFFECTS, /* Physical Maximum 28h (40d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x02, /* Feature (Variable)*/\ + 0x09,0x8B, /* Usage Block Load Status*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x09,0x8C, /* Usage Block Load Success*/\ + 0x09,0x8D, /* Usage Block Load Full*/\ + 0x09,0x8E, /* Usage Block Load Error*/\ + 0x15,0x01, /* Logical Minimum 1*/\ + 0x25,0x03, /* Logical Maximum 3*/\ + 0x35,0x01, /* Physical Minimum 1*/\ + 0x45,0x03, /* Physical Maximum 3*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x00, /* Feature*/\ + 0xC0 , /* End Collection*/\ + 0x09,0xAC, /* Usage Pool available*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x27,0xFF,0xFF,0x00,0x00, /* Logical Maximum FFFFh (65535d)*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x47,0xFF,0xFF,0x00,0x00, /* Physical Maximum FFFFh (65535d)*/\ + 0x75,0x10, /* Report Size 10h (16d)*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x00, /* Feature*/\ + 0xC0 // End Collection +#define HIDDESC_FFB_BLOCKLOADREP_SIZE 72 + +#define HIDDESC_FFB_POOLREP \ + 0x09,0x7F, /* Usage PID Pool Report*/\ + 0xA1,0x02, /* Collection Datalink*/\ + 0x85,HID_ID_POOLREP+FFB_ID_OFFSET, /* Report ID 0x13*/\ + 0x09,0x80, /* Usage RAM Pool size*/\ + 0x75,0x10, /* Report Size 10h (16d)*/\ + 0x95,0x01, /* Report Count 1*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x27,0xFF,0xFF,0x00,0x00, /* Logical Maximum FFFFh (65535d)*/\ + 0x47,0xFF,0xFF,0x00,0x00, /* Physical Maximum FFFFh (65535d)*/\ + 0xB1,0x02, /* Feature (Variable)*/\ + 0x09,0x83, /* Usage Simultaneous Effects Max*/\ + 0x26,0xFF,0x00, /* Logical Maximum FFh (255d)*/\ + 0x46,0xFF,0x00, /* Physical Maximum FFh (255d)*/\ + 0x75,0x08, /* Report Size 8*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x02, /* Feature (Variable)*/\ + 0x09,0xA9, /* Usage Device Managed Pool*/\ + 0x09,0xAA, /* Usage Shared Parameter Blocks*/\ + 0x75,0x01, /* Report Size 1*/\ + 0x95,0x02, /* Report Count 2*/\ + 0x15,0x00, /* Logical Minimum 0*/\ + 0x25,0x01, /* Logical Maximum 1*/\ + 0x35,0x00, /* Physical Minimum 0*/\ + 0x45,0x01, /* Physical Maximum 1*/\ + 0xB1,0x02, /* Feature (Variable)*/\ + 0x75,0x06, /* Report Size 6*/\ + 0x95,0x01, /* Report Count 1*/\ + 0xB1,0x03, /* Feature (Constant, Variable)*/\ + 0xC0 // End Collection +#define HIDDESC_FFB_POOLREP_SIZE 67 + +#define HIDDESC_FFB_DESCSIZE HIDDESC_FFB_STATEREP_SIZE + HIDDESC_FFB_POOLREP_SIZE + HIDDESC_FFB_BLOCKLOADREP_SIZE + HIDDESC_FFB_NEWEFREP_SIZE + HIDDESC_FFB_DEVCTRLREP_SIZE + HIDDESC_FFB_BLOCKFREEREP_SIZE + HIDDESC_FFB_EFOPREP_SIZE + HIDDESC_FFB_SETEFREP_SIZE + HIDDESC_FFB_SETRAMPREP_SIZE + HIDDESC_FFB_SETCFREP_SIZE + HIDDESC_FFB_SETPERIODICREP_SIZE + HIDDESC_FFB_SETENVREP_SIZE + + #ifdef AXIS2_FFB_HID_DESC +#define USB_HID_2FFB_REPORT_DESC_SIZE HIDDESC_GAMEPAD_16B_SIZE + HIDDESC_CTRL_REPORTS_SIZE + HIDDESC_FFB_DESCSIZE + 7 + 108 + 125 extern const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE]; #endif +#ifdef AXIS2_FFB_HID_DESC_32B +#define USB_HID_2FFB_REPORT_DESC_32B_SIZE HIDDESC_GAMEPAD_32B_SIZE + HIDDESC_CTRL_REPORTS_SIZE + HIDDESC_FFB_DESCSIZE + 7 + 108 + 125 +extern const uint8_t hid_2ffb_desc_32b[USB_HID_2FFB_REPORT_DESC_32B_SIZE]; +#endif -#if defined(HIDAXISRES_32B) -#define USB_HID_GAMEPAD_REPORT_DESC_SIZE 176 + 16 -#else -#define USB_HID_GAMEPAD_REPORT_DESC_SIZE 176 +#ifdef AXIS1_FFB_HID_DESC +#define USB_HID_1FFB_REPORT_DESC_SIZE HIDDESC_GAMEPAD_16B_SIZE + HIDDESC_CTRL_REPORTS_SIZE + HIDDESC_FFB_DESCSIZE + 7 + 94 + 120 +extern const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE]; +#endif +#ifdef AXIS1_FFB_HID_DESC_32B +#define USB_HID_1FFB_REPORT_DESC_SIZE HIDDESC_GAMEPAD_32B_SIZE + HIDDESC_CTRL_REPORTS_SIZE + HIDDESC_FFB_DESCSIZE + 7 + 94 + 120 +extern const uint8_t hid_1ffb_desc_32b[USB_HID_1FFB_REPORT_DESC_32B_SIZE]; #endif + + #ifdef FFB_HID_DESC_GAMEPAD +#define USB_HID_GAMEPAD_REPORT_DESC_SIZE HIDDESC_GAMEPAD_16B_SIZE + HIDDESC_CTRL_REPORTS_SIZE + 7 extern const uint8_t hid_gamepad_desc[USB_HID_GAMEPAD_REPORT_DESC_SIZE]; #endif +#ifdef FFB_HID_DESC_GAMEPAD_32B +#define USB_HID_GAMEPAD_REPORT_DESC_32B_SIZE HIDDESC_GAMEPAD_32B_SIZE + HIDDESC_CTRL_REPORTS_SIZE + 7 +extern const uint8_t hid_gamepad_desc_32b[USB_HID_GAMEPAD_REPORT_DESC_32B_SIZE]; +#endif + #endif /* USB_INC_USB_HID_FFB_DESC_H_ */ diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index fe957e2a1..c50cb9e5f 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -28,10 +28,10 @@ const FFBHIDMain::FFB_update_rates FFBHIDMain::ffbrates; // Default rates /** * setFFBEffectsCalc must be called in constructor of derived class to finish the setup */ -FFBHIDMain::FFBHIDMain(uint8_t axisCount) : +FFBHIDMain::FFBHIDMain(uint8_t axisCount,bool hidAxis32b) : Thread("FFBMAIN", 256, 30), SelectableInputs(ButtonSource::all_buttonsources,AnalogSource::all_analogsources), - axisCount(axisCount) + axisCount(axisCount),hidAxis32b(hidAxis32b) { restoreFlashDelayed(); // Load parameters @@ -182,9 +182,9 @@ void FFBHIDMain::send_report(){ std::vector* axes = axes_manager->getAxisValues(); uint8_t count = 0; for(auto val : *axes){ -#if !defined(HIDAXISRES_32B) - val = val >> 16; // Scale to 16b -#endif + if(!hidAxis32b){ + val = val >> 16; // Scale to 16b + } setHidReportAxis(&reportHID,count++,val); } @@ -193,9 +193,8 @@ void FFBHIDMain::send_report(){ for(int32_t val : *axes){ if(count >= analogAxisCount) break; -#ifdef HIDAXISRES_32B - if(count <= MAX_AXIS) val = val << 16; // Shift up 16 bit to fill 32b value. Primary axis is 32b -#endif + if(count <= MAX_AXIS && hidAxis32b) + val = val << 16; // Shift up 16 bit to fill 32b value. Primary axis is 32b setHidReportAxis(&reportHID,count++,val); } diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp b/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp index ff31cf8ba..0b692e60c 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp @@ -47,64 +47,38 @@ const tusb_desc_device_t usb_devdesc_ffboard_composite = const uint8_t usb_cdc_conf[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, 2, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CONFIG_DESCRIPTOR(1, 2, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP | TUSB_DESC_CONFIG_ATT_SELF_POWERED, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), }; + // Composite CDC and HID #ifdef AXIS1_FFB_HID_DESC -const uint8_t usb_cdc_hid_conf_1axis[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - - // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), - - // HID Descriptor. EP 83 and 2 - TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_1FFB_REPORT_DESC_SIZE, 0x83, 0x02, 64, HID_BINTERVAL), -}; + const uint8_t usb_cdc_hid_conf_1axis[] ={USB_CONF_DESC_HID_CDC(USB_HID_1FFB_REPORT_DESC_SIZE,64)}; #endif // Composite CDC and HID #ifdef AXIS2_FFB_HID_DESC -const uint8_t usb_cdc_hid_conf_2axis[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - - // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), - - // HID Descriptor. EP 83 and 2 - TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_2FFB_REPORT_DESC_SIZE, 0x83, 0x02,64, HID_BINTERVAL), -}; + const uint8_t usb_cdc_hid_conf_2axis[] ={USB_CONF_DESC_HID_CDC(USB_HID_2FFB_REPORT_DESC_SIZE,64)}; +#endif +#ifdef AXIS1_FFB_HID_DESC_32B + const uint8_t usb_cdc_hid_conf_2axis_32b[] ={USB_CONF_DESC_HID_CDC(USB_HID_2FFB_REPORT_DESC_32B_SIZE,64)}; #endif // Composite CDC and HID #ifdef FFB_HID_DESC_GAMEPAD -const uint8_t usb_cdc_hid_conf_gamepad[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, 3, 0, (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - - // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), - - // HID Descriptor. EP 83 and 2 - TUD_HID_INOUT_DESCRIPTOR(2, 5, HID_ITF_PROTOCOL_NONE, USB_HID_GAMEPAD_REPORT_DESC_SIZE, 0x83, 0x02, (TUD_OPT_HIGH_SPEED ? 512 : 64), HID_BINTERVAL), -}; + const uint8_t usb_cdc_hid_conf_gamepad[] ={USB_CONF_DESC_HID_CDC(USB_HID_GAMEPAD_REPORT_DESC_SIZE,64)}; #endif // Composite CDC and MIDI uint8_t const usb_cdc_midi_conf[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, 4, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MIDI_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CONFIG_DESCRIPTOR(1, 4, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MIDI_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP | TUSB_DESC_CONFIG_ATT_SELF_POWERED, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, (TUD_OPT_HIGH_SPEED ? 512 : 64)), + TUD_CDC_DESCRIPTOR(0, 4, 0x82, 8, 0x01, 0x81, 64), // Interface number, string index, EP Out & EP In address, EP size TUD_MIDI_DESCRIPTOR(2, 6, 0x02, 0x83, 64) }; diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_hid_1ffb_desc.c b/Firmware/FFBoard/UserExtensions/Src/usb_hid_1ffb_desc.c index c8432e410..afbc27caa 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_hid_1ffb_desc.c +++ b/Firmware/FFBoard/UserExtensions/Src/usb_hid_1ffb_desc.c @@ -13,244 +13,17 @@ __ALIGN_BEGIN const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE] __ALIGN_END = { - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0xa1, 0x00, // COLLECTION (Physical) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x40, // USAGE_MAXIMUM (Button 64) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x40, // REPORT_COUNT (64) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, HID_USAGE_X, // USAGE (X) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 1 - HIDDESC_32B_ENTRY(0x01) -#endif - 0x09, HID_USAGE_Y, // USAGE (Y) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 2 - HIDDESC_32B_ENTRY(0x02) -#endif - 0x09, HID_USAGE_Z, // USAGE (Z) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 3 - HIDDESC_32B_ENTRY(0x03) -#endif - 0x09, HID_USAGE_RX, // USAGE (Rx) - 0x09, HID_USAGE_RY, // USAGE (Ry) - 0x09, HID_USAGE_RZ, // USAGE (Rz) - 0x09, HID_USAGE_SL1, // USAGE (Dial) - 0x09, HID_USAGE_SL0, // USAGE (Slider) - 0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767) - 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) -#if defined(HIDAXISRES_32B) - 0x95, 0x08-MAX_AXIS, // REPORT_COUNT (8- amount of 32b axes) -#else - 0x95, 0x08, // REPORT_COUNT (8) -#endif - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - - - // Control reports - 0x06, 0x00, 0xFF, // USAGE_PAGE (Vendor) - 0x09, 0x00, // USAGE (Vendor) - 0xA1, 0x01, // Collection (Application) - - 0x85,HID_ID_HIDCMD, // Report ID - 0x09, 0x01, // USAGE (Vendor) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0x04, 0x00, // Logical Maximum 4 - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x02, // USAGE (Vendor) class address - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x03, // USAGE (Vendor) class instance - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x04, // USAGE (Vendor) cmd - 0x75, 0x20, // REPORT_SIZE (32) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x05, // USAGE (Vendor) - 0x75, 0x40, // REPORT_SIZE (64) value - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x06, // USAGE (Vendor) address - 0x75, 0x40, // REPORT_SIZE (64) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x85,HID_ID_HIDCMD, // Report ID - 0x09, 0x01, // USAGE (Vendor) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0x04, 0x00, // Logical Maximum 4 - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x02, // USAGE (Vendor) class address - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x03, // USAGE (Vendor) class instance - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x04, // USAGE (Vendor) cmd - 0x75, 0x20, // REPORT_SIZE (32) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x05, // USAGE (Vendor) - 0x75, 0x40, // REPORT_SIZE (64) value - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x06, // USAGE (Vendor) address - 0x75, 0x40, // REPORT_SIZE (64) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - - - 0xc0, // END_COLLECTION - - - // BEGIN PID effects - 0x05,0x0F, // Usage Page Physical Interface - 0x09,0x92, // Usage PID State report - 0xA1,0x02, // Collection Datalink (logical) - 0x85,HID_ID_STATE+FFB_ID_OFFSET, // Report ID 2 - -// 0x09,0x22, // Usage Effect Block Index -// 0x15,0x01, // Logical Minimum 1 -// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) -// 0x35,0x01, // Physical Minimum 1 -// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) -// 0x75,0x08, // Report Size 8 -// 0x95,0x01, // Report Count 1 -// 0x81,0x02, // Input (Variable) - - - - 0x09,0x9F, // Usage Device is Pause - 0x09,0xA0, // Usage Actuators Enabled - 0x09,0xA4, // Usage Safety Switch - 0x09,0xA6, // Usage Actuator Power - - 0x09,0x94, // Usage Effect Playing - /* - 0x15,0x00, // Logical Minimum 0 - 0x25,0x01, // Logical Maximum 1 - 0x35,0x00, // Physical Minimum 0 - 0x45,0x01, // Physical Maximum 1 - 0x75,0x01, // Report Size 1 - 0x95,0x01, // Report Count 1 - 0x81,0x02, // Input (Variable)*/ //14 + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ + 0x09, 0x04, /* USAGE (Joystick)*/ + 0xa1, 0x01, /* COLLECTION (Application)*/ + HIDDESC_GAMEPAD_16B, - 0x15,0x00, // Logical Minimum 0 - 0x25,0x01, // Logical Maximum 1 - 0x35,0x00, // Physical Minimum 0 - 0x45,0x01, // Physical Maximum 1 - 0x75,0x01, // Report Size 1 - 0x95,0x05, // Report Count 4 - 0x81,0x02, // Input (Variable) - 0x95,0x03, // Report Count 3 - 0x81,0x03, // Input (Constant, Variable) - 0xC0 , // End Collection + HIDDESC_CTRL_REPORTS, // HID command report support - /* - Output - Collection Datalink: - Usage Set Effect Report - ID:1 - Effect Block Index: 8bit - - subcollection Effect Type - 12 effect types, 8bit each + HIDDESC_FFB_STATEREP, - */ - 0x09,0x21, // Usage Set Effect Report - 0xA1,0x02, // Collection Datalink (Logical) - 0x85,HID_ID_EFFREP+FFB_ID_OFFSET, // Report ID 1 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x25, // Usage Effect Type - 0xA1,0x02, // Collection Datalink - 0x09, HID_USAGE_CONST, // Usage ET Constant Force - 0x09, HID_USAGE_RAMP, // Usage ET Ramp - 0x09, HID_USAGE_SQUR, // Usage ET Square - 0x09, HID_USAGE_SINE, // Usage ET Sine - 0x09, HID_USAGE_TRNG, // Usage ET Triangle - 0x09, HID_USAGE_STUP, // Usage ET Sawtooth Up - 0x09, HID_USAGE_STDN, // Usage ET Sawtooth Down - 0x09, HID_USAGE_SPRNG, // Usage ET Spring - 0x09, HID_USAGE_DMPR, // Usage ET Damper - 0x09, HID_USAGE_INRT, // Usage ET Inertia - 0x09, HID_USAGE_FRIC, // Usage ET Friction - // 0x09, 0x28, // Usage ET Custom Force Data - 0x25,0x0B, // Logical Maximum Bh (11d) - 0x15,0x01, // Logical Minimum 1 - 0x35,0x01, // Physical Minimum 1 - 0x45,0x0B, // Physical Maximum Bh (11d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x00, // Output - 0xC0 , // End Collection - 0x09,0x50, // Usage Duration - 0x09,0x54, // Usage Trigger Repeat Interval - 0x09,0x51, // Usage Sample Period - 0x09,0xA7, // Usage Start Delay - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) - 0x66,0x03,0x10, // Unit 1003h (4099d) - 0x55,0xFD, // Unit Exponent FDh (253d) - 0x75,0x10, // Report Size 10h (16d) - 0x95,0x04, // Report Count 4 - 0x91,0x02, // Output (Variable) - 0x55,0x00, // Unit Exponent 0 - 0x66,0x00,0x00, // Unit 0 - 0x09,0x52, // Usage Gain - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) // TODO scaling? - 0x35,0x00, // Physical Minimum 0 - 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x53, // Usage Trigger Button - 0x15,0x01, // Logical Minimum 1 - 0x25,0x08, // Logical Maximum 8 - 0x35,0x01, // Physical Minimum 1 - 0x45,0x08, // Physical Maximum 8 - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) + HIDDESC_FFB_SETEFREP, 0x09,0x55, // Usage Axes Enable TODO multi axis 0xA1,0x02, // Collection Datalink @@ -302,39 +75,8 @@ __ALIGN_BEGIN const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE] __ALIGN 0xC0, // END_COLLECTION 0xC0, // END_COLLECTION - // Envelope Report Definition - 0x09,0x5A, // Usage Set Envelope Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_ENVREP+FFB_ID_OFFSET, // Report ID 2 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x5B, // Usage Attack Level - 0x09,0x5D, // Usage Fade Level - 0x16,0x00,0x00, // Logical Minimum 0 - 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) - 0x36,0x00,0x00, // Physical Minimum 0 - 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) - 0x75,0x10, // Report Size 16 - 0x95,0x02, // Report Count 2 - 0x91,0x02, // Output (Variable) - 0x09, 0x5C, // Usage Attack Time - 0x09, 0x5E, // Usage Fade Time - 0x66, 0x03, 0x10, // Unit 1003h (English Linear, Seconds) - 0x55, 0xFD, // Unit Exponent FDh (X10^-3 ==> Milisecond) - 0x27, 0xFF, 0x7F, 0x00, 0x00, // Logical Maximum FFFFFFFFh (4294967295) - 0x47, 0xFF, 0x7F, 0x00, 0x00, // Physical Maximum FFFFFFFFh (4294967295) - 0x75, 0x20, // Report Size 20h (32d) - 0x91, 0x02, // Output (Variable) - 0x45, 0x00, // Physical Maximum 0 - 0x66,0x00,0x00, // Unit 0 - 0x55,0x00, // Unit Exponent 0 - 0xC0 , // End Collection + HIDDESC_FFB_SETENVREP, + 0x09,0x5F, // Usage Set Condition Report 0xA1,0x02, // Collection Datalink 0x85,HID_ID_CONDREP+FFB_ID_OFFSET, // Report ID 3 @@ -391,97 +133,12 @@ __ALIGN_BEGIN const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE] __ALIGN 0x95,0x01, // Report Count 1 0x91,0x02, // Output (Variable) 0xC0 , // End Collection - 0x09,0x6E, // Usage Set Periodic Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_PRIDREP+FFB_ID_OFFSET, // Report ID 4 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x70, // Usage Magnitude - 0x16,0x00,0x00, // Logical Minimum 0 - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00,0x00, // Physical Minimum 0 - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x75,0x10, // Report Size 16 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09, 0x6F, // Usage Offset - 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) - 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) - 0x95, 0x01, // Report Count 1 - 0x75, 0x10, // Report Size 16 - 0x91, 0x02, // Output (Variable) - 0x09, 0x71, // Usage Phase - 0x66, 0x14, 0x00, // Unit 14h (Eng Rotation, Degrees) - 0x55, 0xFE, // Unit Exponent FEh (X10^-2) - 0x15, 0x00, // Logical Minimum 0 - 0x27, 0x9F, 0x8C, 0x00, 0x00, // Logical Maximum 8C9Fh (35999d) - 0x35, 0x00, // Physical Minimum 0 - 0x47, 0x9F, 0x8C, 0x00, 0x00, // Physical Maximum 8C9Fh (35999d) - 0x75, 0x10, // Report Size 16 - 0x95, 0x01, // Report Count 1 - 0x91, 0x02, // Output (Variable) - 0x09, 0x72, // Usage Period - 0x15, 0x01, // Logical Minimum 1 - 0x27, 0xFF, 0x7F, 0x00, 0x00, // Logical Maximum 7FFFh (32K) - 0x35, 0x01, // Physical Minimum 1 - 0x47, 0xFF, 0x7F, 0x00, 0x00, // Physical Maximum 7FFFh (32K) - 0x66, 0x03, 0x10, // Unit 1003h (English Linear, Seconds) - 0x55, 0xFD, // Unit Exponent FDh (X10^-3 ==> Milisecond) - 0x75, 0x20, // Report Size 20h (32) - 0x95, 0x01, // Report Count 1 - 0x91, 0x02, // Output (Variable) - 0x66, 0x00, 0x00, // Unit 0 - 0x55,0x00, // Unit Exponent 0 - 0xC0 , // End Collection - 0x09,0x73, // Usage Set Constant Force Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_CONSTREP+FFB_ID_OFFSET, // Report ID 5 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x70, // Usage Magnitude - 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) - 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) - 0x75, 0x10, // Report Size 10h (16d) - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - 0x09,0x74, // Usage Set Ramp Force Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_RAMPREP+FFB_ID_OFFSET, // Report ID 6 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x75, // Usage Ramp Start - 0x09,0x76, // Usage Ramp End - 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) - 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) - 0x75,0x10, // Report Size 16 - 0x95,0x02, // Report Count 2 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection + + HIDDESC_FFB_SETPERIODICREP, + + HIDDESC_FFB_SETCFREP, + + HIDDESC_FFB_SETRAMPREP, // 0x09,0x68, // Usage Custom Force Data Report @@ -527,84 +184,10 @@ __ALIGN_BEGIN const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE] __ALIGN // 0x91,0x02, // Output (Variable) // 0xC0 , // End Collection - 0x05,0x0F, // Usage Page Physical Interface - 0x09,0x77, // Usage Effect Operation Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_EFOPREP+FFB_ID_OFFSET, // Report ID Ah (10d) - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x78, // Usage Effect Operation - 0xA1,0x02, // Collection Datalink - 0x09,0x79, // Usage Op Effect Start - 0x09,0x7A, // Usage Op Effect Start Solo - 0x09,0x7B, // Usage Op Effect Stop - 0x15,0x01, // Logical Minimum 1 - 0x25,0x03, // Logical Maximum 3 - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x00, // Output - 0xC0 , // End Collection - 0x09,0x7C, // Usage Loop Count - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0xFF,0x00, // Physical Maximum FFh (255d) - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - 0x09,0x90, // Usage PID Block Free Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_BLKFRREP+FFB_ID_OFFSET, // Report ID Bh (11d) - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - - 0x09,0x95, // Usage PID Device Control (0x96?) - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_CTRLREP+FFB_ID_OFFSET, // Report ID Ch (12d) - 0x09,0x96, // Usage PID Device Control (0x96?) - 0xA1,0x02, // Collection Datalink - - 0x09,0x97, // Usage DC Enable Actuators - 0x09,0x98, // Usage DC Disable Actuators - 0x09,0x99, // Usage DC Stop All Effects - 0x09,0x9A, // Usage DC Device Reset - 0x09,0x9B, // Usage DC Device Pause - 0x09,0x9C, // Usage DC Device Continue + HIDDESC_FFB_EFOPREP, + HIDDESC_FFB_BLOCKFREEREP, - - - 0x15,0x01, // Logical Minimum 1 - 0x25,0x06, // Logical Maximum 6 - 0x75,0x01, // Report Size 1 - 0x95,0x08, // Report Count 8 - 0x91,0x02, // Output - - 0xC0 , // End Collection - 0xC0 , // End Collection - 0x09,0x7D, // Usage Device Gain Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_GAINREP+FFB_ID_OFFSET, // Report ID Dh (13d) - 0x09,0x7E, // Usage Device Gain - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection + HIDDESC_FFB_DEVCTRLREP, // 0x09,0x6B, // Usage Set Custom Force Report // 0xA1,0x02, // Collection Datalink // 0x85,HID_ID_SETCREP+FFB_ID_OFFSET, // Report ID Eh (14d) @@ -637,110 +220,168 @@ __ALIGN_BEGIN const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE] __ALIGN // 0x55,0x00, // Unit Exponent 0 // 0x66,0x00,0x00, // Unit 0 // 0xC0 , // End Collection - 0x09,0xAB, // Usage Create New Effect Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_NEWEFREP+FFB_ID_OFFSET, // Report ID 1 - 0x09,0x25, // Usage Effect Type + HIDDESC_FFB_NEWEFREP, + HIDDESC_FFB_BLOCKLOADREP, + + HIDDESC_FFB_POOLREP, + + 0xC0 /* END_COLLECTION */ +}; +#endif + +#ifdef AXIS1_FFB_HID_DESC_32B +__ALIGN_BEGIN const uint8_t hid_1ffb_desc_32b[USB_HID_1FFB_REPORT_DESC_32B_SIZE] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ + 0x09, 0x04, /* USAGE (Joystick)*/ + 0xa1, 0x01, /* COLLECTION (Application)*/ + HIDDESC_GAMEPAD_32B, + + HIDDESC_CTRL_REPORTS, // HID command report support + + HIDDESC_FFB_STATEREP, + /* + Output + Collection Datalink: + Usage Set Effect Report + + ID:1 + Effect Block Index: 8bit + + subcollection Effect Type + 12 effect types, 8bit each + + */ + HIDDESC_FFB_SETEFREP, + + 0x09,0x55, // Usage Axes Enable TODO multi axis + 0xA1,0x02, // Collection Datalink + 0x05,0x01, // Usage Page Generic Desktop + 0x09,0x30, // Usage X + //0x09,0x31, // Usage Y + 0x15,0x00, // Logical Minimum 0 + 0x25,0x00, // Logical Maximum 0 + 0x75,0x01, // Report Size 1 + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0xC0 , // End Collection + 0x05,0x0F, // Usage Page Physical Interface + 0x09,0x56, // Usage Direction Enable + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0x95,0x06, // Report Count 6 + 0x91,0x03, // Output (Constant, Variable) + + 0x09,0x57, // Usage Direction 0xA1,0x02, // Collection Datalink - 0x09, HID_USAGE_CONST, // Usage ET Constant Force - 0x09, HID_USAGE_RAMP, // Usage ET Ramp - 0x09, HID_USAGE_SQUR, // Usage ET Square - 0x09, HID_USAGE_SINE, // Usage ET Sine - 0x09, HID_USAGE_TRNG, // Usage ET Triangle - 0x09, HID_USAGE_STUP, // Usage ET Sawtooth Up - 0x09, HID_USAGE_STDN, // Usage ET Sawtooth Down - 0x09, HID_USAGE_SPRNG, // Usage ET Spring - 0x09, HID_USAGE_DMPR, // Usage ET Damper - 0x09, HID_USAGE_INRT, // Usage ET Inertia - 0x09, HID_USAGE_FRIC, // Usage ET Friction -// 0x09, 0x28, // Usage ET Custom Force Data - 0x25,0x0B, // Logical Maximum Ch (11d) + 0x0B,0x01,0x00,0x0A,0x00, // Usage Ordinals: Instance 1 +// 0x0B,0x02,0x00,0x0A,0x00, // Usage Ordinals: Instance 2 + 0x66,0x14,0x00, // Unit 14h (20d) +// 0x55,0xFE, // Unit Exponent FEh (254d) +// 0x15,0x00, // Logical Minimum 0 +// 0x26,0xFF,0x00, // Logical Maximum FFh (255d) + 0x15,0x00, // Logical Minimum 0 + 0x27,0xA0,0x8C,0x00,0x00, // Logical Maximum 8CA0h (36000d) + 0x35,0x00, // Physical Minimum 0 + 0x47,0xA0,0x8C,0x00,0x00, // Physical Maximum 8CA0h (36000d) + 0x66,0x00,0x00, // Unit 0 + 0x75,0x10, // Report Size 16 + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0x55,0x00, // Unit Exponent 0 + 0x66,0x00,0x00, // Unit 0 + 0xC0, // End Collection + + 0x05, 0x0F, // USAGE_PAGE (Physical Interface) + 0x09, 0x58, // USAGE (Type Specific Block Offset) + 0xA1, 0x02, // COLLECTION (Logical) + 0x0B, 0x01, 0x00, 0x0A, 0x00, //USAGE (Ordinals:Instance 1 + //0x0B, 0x02, 0x00, 0x0A, 0x00, //USAGE (Ordinals:Instance 2) + 0x26, 0xFD, 0x7F, // LOGICAL_MAXIMUM (32765) ; 32K RAM or ROM max. + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x01, // REPORT_COUNT (1) + 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0xC0, // END_COLLECTION + 0xC0, // END_COLLECTION + + HIDDESC_FFB_SETENVREP, + + 0x09,0x5F, // Usage Set Condition Report + 0xA1,0x02, // Collection Datalink + 0x85,HID_ID_CONDREP+FFB_ID_OFFSET, // Report ID 3 + 0x09,0x22, // Usage Effect Block Index 0x15,0x01, // Logical Minimum 1 + 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) 0x35,0x01, // Physical Minimum 1 - 0x45,0x0B, // Physical Maximum Ch (11d) + 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) 0x75,0x08, // Report Size 8 0x95,0x01, // Report Count 1 - 0xB1,0x00, // Feature - 0xC0 , // End Collection - 0x05,0x01, // Usage Page Generic Desktop - 0x09,0x3B, // Usage Reserved (Byte count) - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x01, // Logical Maximum 1FFh (511d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0xFF,0x01, // Physical Maximum 1FFh (511d) - 0x75,0x0A, // Report Size Ah (10d) - 0x95,0x01, // Report Count 1 - 0xB1,0x02, // Feature (Variable) - 0x75,0x06, // Report Size 6 - 0xB1,0x01, // Feature (Constant) - 0xC0 , // End Collection - 0x05,0x0F, // Usage Page Physical Interface - 0x09,0x89, // Usage Block Load Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_BLKLDREP+FFB_ID_OFFSET, // Report ID 0x12 - 0x09,0x22, // Usage Effect Block Index - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x15,0x01, // Logical Minimum 1 - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0xB1,0x02, // Feature (Variable) - 0x09,0x8B, // Usage Block Load Status - 0xA1,0x02, // Collection Datalink - 0x09,0x8C, // Usage Block Load Success - 0x09,0x8D, // Usage Block Load Full - 0x09,0x8E, // Usage Block Load Error - 0x15,0x01, // Logical Minimum 1 + 0x91,0x02, // Output (Variable) + 0x09,0x23, // Usage Parameter Block Offset + 0x15,0x00, // Logical Minimum 0 0x25,0x03, // Logical Maximum 3 - 0x35,0x01, // Physical Minimum 1 + 0x35,0x00, // Physical Minimum 0 0x45,0x03, // Physical Maximum 3 - 0x75,0x08, // Report Size 8 + 0x75,0x06, // Report Size 6 0x95,0x01, // Report Count 1 - 0xB1,0x00, // Feature - 0xC0 , // End Collection - 0x09,0xAC, // Usage Pool available - 0x15,0x00, // Logical Minimum 0 - 0x27,0xFF,0xFF,0x00,0x00, // Logical Maximum FFFFh (65535d) - 0x35,0x00, // Physical Minimum 0 - 0x47,0xFF,0xFF,0x00,0x00, // Physical Maximum FFFFh (65535d) - 0x75,0x10, // Report Size 10h (16d) - 0x95,0x01, // Report Count 1 - 0xB1,0x00, // Feature + 0x91,0x02, // Output (Variable) + 0x09,0x58, // Usage Type Specific Block Off... + 0xA1,0x02, // Collection Datalink + 0x0B,0x01,0x00,0x0A,0x00, // Usage Ordinals: Instance 1 +// 0x0B,0x02,0x00,0x0A,0x00, // Usage Ordinals: Instance 2 + 0x75,0x02, // Report Size 2 + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0xC0 , // End Collection + 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) + 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) + 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) + 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) + + 0x09,0x60, // Usage CP Offset + 0x75,0x10, // Report Size 16 + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0x36,0x00, 0x80, // Physical Minimum (-32768) + 0x46,0xff, 0x7f, // Physical Maximum (32767) + 0x09,0x61, // Usage Positive Coefficient + 0x09,0x62, // Usage Negative Coefficient + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0x16,0x00,0x00, // Logical Minimum 0 + 0x26,0xff, 0x7f, // Logical Maximum (32767) + 0x36,0x00,0x00, // Physical Minimum 0 + 0x46,0xff, 0x7f, // Physical Maximum (32767) + 0x09,0x63, // Usage Positive Saturation + 0x09,0x64, // Usage Negative Saturation + 0x75,0x10, // Report Size 16 + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0x09,0x65, // Usage Dead Band + 0x46,0xff, 0x7f, // Physical Maximum (32767) + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) 0xC0 , // End Collection - 0x09,0x7F, // Usage PID Pool Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_POOLREP+FFB_ID_OFFSET, // Report ID 0x13 - 0x09,0x80, // Usage RAM Pool size - 0x75,0x10, // Report Size 10h (16d) - 0x95,0x01, // Report Count 1 - 0x15,0x00, // Logical Minimum 0 - 0x35,0x00, // Physical Minimum 0 - 0x27,0xFF,0xFF,0x00,0x00, // Logical Maximum FFFFh (65535d) - 0x47,0xFF,0xFF,0x00,0x00, // Physical Maximum FFFFh (65535d) - 0xB1,0x02, // Feature (Variable) - 0x09,0x83, // Usage Simultaneous Effects Max - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) - 0x46,0xFF,0x00, // Physical Maximum FFh (255d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0xB1,0x02, // Feature (Variable) - 0x09,0xA9, // Usage Device Managed Pool - 0x09,0xAA, // Usage Shared Parameter Blocks - 0x75,0x01, // Report Size 1 - 0x95,0x02, // Report Count 2 - 0x15,0x00, // Logical Minimum 0 - 0x25,0x01, // Logical Maximum 1 - 0x35,0x00, // Physical Minimum 0 - 0x45,0x01, // Physical Maximum 1 - 0xB1,0x02, // Feature (Variable) - 0x75,0x06, // Report Size 6 - 0x95,0x01, // Report Count 1 - 0xB1,0x03, // Feature (Constant, Variable) - 0xC0, // End Collection + HIDDESC_FFB_SETPERIODICREP, + + HIDDESC_FFB_SETCFREP, + + HIDDESC_FFB_SETRAMPREP, + + HIDDESC_FFB_EFOPREP, + + HIDDESC_FFB_BLOCKFREEREP, + + HIDDESC_FFB_DEVCTRLREP, + + HIDDESC_FFB_NEWEFREP, + + HIDDESC_FFB_BLOCKLOADREP, + + HIDDESC_FFB_POOLREP, 0xC0 /* END_COLLECTION */ }; - #endif + diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c b/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c index 427dba6c7..386e5a1aa 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c +++ b/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c @@ -12,223 +12,95 @@ #ifdef AXIS2_FFB_HID_DESC __ALIGN_BEGIN const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE] __ALIGN_END = { - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0xa1, 0x00, // COLLECTION (Physical) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x40, // USAGE_MAXIMUM (Button 64) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x40, // REPORT_COUNT (64) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, HID_USAGE_X, // USAGE (X) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 1 - HIDDESC_32B_ENTRY(0x01) -#endif - 0x09, HID_USAGE_Y, // USAGE (Y) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 2 - HIDDESC_32B_ENTRY(0x02) -#endif - 0x09, HID_USAGE_Z, // USAGE (Z) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 3 - HIDDESC_32B_ENTRY(0x03) -#endif - 0x09, HID_USAGE_RX, // USAGE (Rx) - 0x09, HID_USAGE_RY, // USAGE (Ry) - 0x09, HID_USAGE_RZ, // USAGE (Rz) - 0x09, HID_USAGE_SL1, // USAGE (Dial) - 0x09, HID_USAGE_SL0, // USAGE (Slider) - 0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767) - 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) -#if defined(HIDAXISRES_32B) - 0x95, 0x08-MAX_AXIS, // REPORT_COUNT (8- amount of 32b axes) -#else - 0x95, 0x08, // REPORT_COUNT (8) -#endif - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - - - // Control reports - 0x06, 0x00, 0xFF, // USAGE_PAGE (Vendor) - 0x09, 0x00, // USAGE (Vendor) - 0xA1, 0x01, // Collection (Application) -// 0x85,HID_ID_CUSTOMCMD, // Report ID -// 0x09, 0x01, // USAGE (Vendor) type -// 0x15, 0x00, // LOGICAL_MINIMUM (0) -// 0x26, 0x04, 0x00, // Logical Maximum 4 -// 0x75, 0x08, // REPORT_SIZE (8) -// 0x95, 0x01, // REPORT_COUNT (1) -// 0xb1, 0x02, // FEATURE (Data,Var,Abs) -// -// 0x09, 0x02, // USAGE (Vendor) cmd -// 0x09, 0x03, // USAGE (Vendor) addr -// 0x75, 0x20, // REPORT_SIZE (32) -// 0x95, 0x02, // REPORT_COUNT (2) -// 0xb1, 0x02, // FEATURE (Data,Var,Abs) -// -// 0x09, 0x04, // USAGE (Vendor) data -// 0x75, 0x40, // REPORT_SIZE (64) -// 0x95, 0x01, // REPORT_COUNT (1) -// 0xb1, 0x02, // FEATURE (Data,Var,Abs) -// -// 0x85,HID_ID_CUSTOMCMD, // Report ID -// 0x09, 0x01, // USAGE (Vendor) -// 0x15, 0x00, // LOGICAL_MINIMUM (0) -// 0x26, 0x04, 0x00, // Logical Maximum 4 -// 0x75, 0x08, // REPORT_SIZE (8) -// 0x95, 0x01, // REPORT_COUNT (1) -// 0x91, 0x02, // OUTPUT (Data,Var,Abs) -// -// 0x09, 0x02, // USAGE (Vendor) -// 0x09, 0x03, // USAGE (Vendor) -// 0x75, 0x20, // REPORT_SIZE (32) -// 0x95, 0x02, // REPORT_COUNT (2) -// 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ + 0x09, 0x04, /* USAGE (Joystick)*/ + 0xa1, 0x01, /* COLLECTION (Application)*/ + HIDDESC_GAMEPAD_16B, +// 0x05, 0x01, // USAGE_PAGE (Generic Desktop) +// 0x09, 0x04, // USAGE (Joystick) +// 0xa1, 0x01, // COLLECTION (Application) +// 0xa1, 0x00, // COLLECTION (Physical) +// 0x85, 0x01, // REPORT_ID (1) +// 0x05, 0x09, // USAGE_PAGE (Button) +// 0x19, 0x01, // USAGE_MINIMUM (Button 1) +// 0x29, 0x40, // USAGE_MAXIMUM (Button 64) +// 0x15, 0x00, // LOGICAL_MINIMUM (0) +// 0x25, 0x01, // LOGICAL_MAXIMUM (1) +// 0x95, 0x40, // REPORT_COUNT (64) +// 0x75, 0x01, // REPORT_SIZE (1) +// 0x81, 0x02, // INPUT (Data,Var,Abs) +// 0x05, 0x01, // USAGE_PAGE (Generic Desktop) +// 0x09, HID_USAGE_DESKTOP_X, // USAGE (X) +//#if defined(HIDAXISRES_32B) && MAX_AXIS == 1 +// HIDDESC_32B_ENTRY(0x01) +//#endif +// 0x09, HID_USAGE_DESKTOP_Y, // USAGE (Y) +//#if defined(HIDAXISRES_32B) && MAX_AXIS == 2 +// HIDDESC_32B_ENTRY(0x02) +//#endif +// 0x09, HID_USAGE_DESKTOP_Z, // USAGE (Z) +//#if defined(HIDAXISRES_32B) && MAX_AXIS == 3 +// HIDDESC_32B_ENTRY(0x03) +//#endif +// 0x09, HID_USAGE_DESKTOP_RX, // USAGE (Rx) +// 0x09, HID_USAGE_DESKTOP_RY, // USAGE (Ry) +// 0x09, HID_USAGE_DESKTOP_RZ, // USAGE (Rz) +// 0x09, HID_USAGE_DESKTOP_DIAL, // USAGE (Dial) +// 0x09, HID_USAGE_DESKTOP_SLIDER, // USAGE (Slider) +// 0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767) +// 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) +// 0x75, 0x10, // REPORT_SIZE (16) +//#if defined(HIDAXISRES_32B) +// 0x95, 0x08-MAX_AXIS, // REPORT_COUNT (8- amount of 32b axes) +//#else +// 0x95, 0x08, // REPORT_COUNT (8) +//#endif +// 0x81, 0x02, // INPUT (Data,Var,Abs) +// 0xc0, // END_COLLECTION + + HIDDESC_CTRL_REPORTS, // HID command report support + + // BEGIN PID effects +// 0x05,0x0F, // Usage Page Physical Interface +// 0x09,0x92, // Usage PID State report +// 0xA1,0x02, // Collection Datalink (logical) +// 0x85,HID_ID_STATE+FFB_ID_OFFSET, // Report ID 2 // -// 0x09, 0x04, // USAGE (Vendor) -// 0x75, 0x40, // REPORT_SIZE (64) -// 0x95, 0x01, // REPORT_COUNT (1) -// 0x91, 0x02, // OUTPUT (Data,Var,Abs) +//// 0x09,0x22, // Usage Effect Block Index +//// 0x15,0x01, // Logical Minimum 1 +//// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +//// 0x35,0x01, // Physical Minimum 1 +//// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +//// 0x75,0x08, // Report Size 8 +//// 0x95,0x01, // Report Count 1 +//// 0x81,0x02, // Input (Variable) // -// 0x85,HID_ID_CUSTOMCMD, // Report ID -// 0x09, 0x01, // USAGE (Vendor) -// 0x15, 0x00, // LOGICAL_MINIMUM (0) -// 0x26, 0x04, 0x00, // Logical Maximum 4 -// 0x75, 0x08, // REPORT_SIZE (8) -// 0x95, 0x01, // REPORT_COUNT (1) -// 0x81, 0x02, // INPUT (Data,Var,Abs) +// 0x09,0x9F, // Usage Device is Pause +// 0x09,0xA0, // Usage Actuators Enabled +// 0x09,0xA4, // Usage Safety Switch +// 0x09,0xA6, // Usage Actuator Power // -// 0x09, 0x02, // USAGE (Vendor) -// 0x09, 0x03, // USAGE (Vendor) -// 0x75, 0x20, // REPORT_SIZE (32) -// 0x95, 0x02, // REPORT_COUNT (2) -// 0x81, 0x02, // INPUT (Data,Var,Abs) +// 0x09,0x94, // Usage Effect Playing +// /* +// 0x15,0x00, // Logical Minimum 0 +// 0x25,0x01, // Logical Maximum 1 +// 0x35,0x00, // Physical Minimum 0 +// 0x45,0x01, // Physical Maximum 1 +// 0x75,0x01, // Report Size 1 +// 0x95,0x01, // Report Count 1 +// 0x81,0x02, // Input (Variable)*/ //14 // -// 0x09, 0x04, // USAGE (Vendor) -// 0x75, 0x40, // REPORT_SIZE (64) -// 0x95, 0x01, // REPORT_COUNT (1) -// 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x85,HID_ID_HIDCMD, // Report ID - 0x09, 0x01, // USAGE (Vendor) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0x04, 0x00, // Logical Maximum 4 - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x02, // USAGE (Vendor) class address - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x03, // USAGE (Vendor) class instance - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x04, // USAGE (Vendor) cmd - 0x75, 0x20, // REPORT_SIZE (32) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x05, // USAGE (Vendor) - 0x75, 0x40, // REPORT_SIZE (64) value - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x06, // USAGE (Vendor) address - 0x75, 0x40, // REPORT_SIZE (64) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x85,HID_ID_HIDCMD, // Report ID - 0x09, 0x01, // USAGE (Vendor) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0x04, 0x00, // Logical Maximum 4 - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x02, // USAGE (Vendor) class address - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x03, // USAGE (Vendor) class instance - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x04, // USAGE (Vendor) cmd - 0x75, 0x20, // REPORT_SIZE (32) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x05, // USAGE (Vendor) - 0x75, 0x40, // REPORT_SIZE (64) value - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x06, // USAGE (Vendor) address - 0x75, 0x40, // REPORT_SIZE (64) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - - - 0xc0, // END_COLLECTION - - - // BEGIN PID effects - 0x05,0x0F, // Usage Page Physical Interface - 0x09,0x92, // Usage PID State report - 0xA1,0x02, // Collection Datalink (logical) - 0x85,HID_ID_STATE+FFB_ID_OFFSET, // Report ID 2 - -// 0x09,0x22, // Usage Effect Block Index -// 0x15,0x01, // Logical Minimum 1 -// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) -// 0x35,0x01, // Physical Minimum 1 -// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) -// 0x75,0x08, // Report Size 8 -// 0x95,0x01, // Report Count 1 +// 0x15,0x00, // Logical Minimum 0 +// 0x25,0x01, // Logical Maximum 1 +// 0x35,0x00, // Physical Minimum 0 +// 0x45,0x01, // Physical Maximum 1 +// 0x75,0x01, // Report Size 1 +// 0x95,0x05, // Report Count 4 // 0x81,0x02, // Input (Variable) - - - - 0x09,0x9F, // Usage Device is Pause - 0x09,0xA0, // Usage Actuators Enabled - 0x09,0xA4, // Usage Safety Switch - 0x09,0xA6, // Usage Actuator Power - - 0x09,0x94, // Usage Effect Playing - /* - 0x15,0x00, // Logical Minimum 0 - 0x25,0x01, // Logical Maximum 1 - 0x35,0x00, // Physical Minimum 0 - 0x45,0x01, // Physical Maximum 1 - 0x75,0x01, // Report Size 1 - 0x95,0x01, // Report Count 1 - 0x81,0x02, // Input (Variable)*/ //14 - - 0x15,0x00, // Logical Minimum 0 - 0x25,0x01, // Logical Maximum 1 - 0x35,0x00, // Physical Minimum 0 - 0x45,0x01, // Physical Maximum 1 - 0x75,0x01, // Report Size 1 - 0x95,0x05, // Report Count 4 - 0x81,0x02, // Input (Variable) - 0x95,0x03, // Report Count 3 - 0x81,0x03, // Input (Constant, Variable) - 0xC0 , // End Collection - +// 0x95,0x03, // Report Count 3 +// 0x81,0x03, // Input (Constant, Variable) +// 0xC0 , // End Collection + HIDDESC_FFB_STATEREP, /* Output Collection Datalink: @@ -241,71 +113,72 @@ __ALIGN_BEGIN const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE] __ALIGN 12 effect types, 8bit each */ - 0x09,0x21, // Usage Set Effect Report - 0xA1,0x02, // Collection Datalink (Logical) - 0x85,HID_ID_EFFREP+FFB_ID_OFFSET, // Report ID 1 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x25, // Usage Effect Type - 0xA1,0x02, // Collection Datalink - 0x09, HID_USAGE_CONST, // Usage ET Constant Force - 0x09, HID_USAGE_RAMP, // Usage ET Ramp - 0x09, HID_USAGE_SQUR, // Usage ET Square - 0x09, HID_USAGE_SINE, // Usage ET Sine - 0x09, HID_USAGE_TRNG, // Usage ET Triangle - 0x09, HID_USAGE_STUP, // Usage ET Sawtooth Up - 0x09, HID_USAGE_STDN, // Usage ET Sawtooth Down - 0x09, HID_USAGE_SPRNG, // Usage ET Spring - 0x09, HID_USAGE_DMPR, // Usage ET Damper - 0x09, HID_USAGE_INRT, // Usage ET Inertia - 0x09, HID_USAGE_FRIC, // Usage ET Friction - // 0x09, 0x28, // Usage ET Custom Force Data - 0x25,0x0B, // Logical Maximum Bh (11d) - 0x15,0x01, // Logical Minimum 1 - 0x35,0x01, // Physical Minimum 1 - 0x45,0x0B, // Physical Maximum Bh (11d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x00, // Output - 0xC0 , // End Collection - 0x09,0x50, // Usage Duration - 0x09,0x54, // Usage Trigger Repeat Interval - 0x09,0x51, // Usage Sample Period - 0x09,0xA7, // Usage Start Delay - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) - 0x66,0x03,0x10, // Unit 1003h (4099d) - 0x55,0xFD, // Unit Exponent FDh (253d) - 0x75,0x10, // Report Size 10h (16d) - 0x95,0x04, // Report Count 4 - 0x91,0x02, // Output (Variable) - 0x55,0x00, // Unit Exponent 0 - 0x66,0x00,0x00, // Unit 0 - 0x09,0x52, // Usage Gain - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) // TODO scaling? - 0x35,0x00, // Physical Minimum 0 - 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x53, // Usage Trigger Button - 0x15,0x01, // Logical Minimum 1 - 0x25,0x08, // Logical Maximum 8 - 0x35,0x01, // Physical Minimum 1 - 0x45,0x08, // Physical Maximum 8 - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - + HIDDESC_FFB_SETEFREP, +// 0x09,0x21, // Usage Set Effect Report +// 0xA1,0x02, // Collection Datalink (Logical) +// 0x85,HID_ID_EFFREP+FFB_ID_OFFSET, // Report ID 1 +// 0x09,0x22, // Usage Effect Block Index +// 0x15,0x01, // Logical Minimum 1 +// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +// 0x35,0x01, // Physical Minimum 1 +// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0x09,0x25, // Usage Effect Type +// 0xA1,0x02, // Collection Datalink +// 0x09, HID_USAGE_CONST, // Usage ET Constant Force +// 0x09, HID_USAGE_RAMP, // Usage ET Ramp +// 0x09, HID_USAGE_SQUR, // Usage ET Square +// 0x09, HID_USAGE_SINE, // Usage ET Sine +// 0x09, HID_USAGE_TRNG, // Usage ET Triangle +// 0x09, HID_USAGE_STUP, // Usage ET Sawtooth Up +// 0x09, HID_USAGE_STDN, // Usage ET Sawtooth Down +// 0x09, HID_USAGE_SPRNG, // Usage ET Spring +// 0x09, HID_USAGE_DMPR, // Usage ET Damper +// 0x09, HID_USAGE_INRT, // Usage ET Inertia +// 0x09, HID_USAGE_FRIC, // Usage ET Friction +// // 0x09, 0x28, // Usage ET Custom Force Data +// 0x25,0x0B, // Logical Maximum Bh (11d) +// 0x15,0x01, // Logical Minimum 1 +// 0x35,0x01, // Physical Minimum 1 +// 0x45,0x0B, // Physical Maximum Bh (11d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x00, // Output +// 0xC0 , // End Collection +// 0x09,0x50, // Usage Duration +// 0x09,0x54, // Usage Trigger Repeat Interval +// 0x09,0x51, // Usage Sample Period +// 0x09,0xA7, // Usage Start Delay +// 0x15,0x00, // Logical Minimum 0 +// 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) +// 0x35,0x00, // Physical Minimum 0 +// 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) +// 0x66,0x03,0x10, // Unit 1003h (4099d) +// 0x55,0xFD, // Unit Exponent FDh (253d) +// 0x75,0x10, // Report Size 10h (16d) +// 0x95,0x04, // Report Count 4 +// 0x91,0x02, // Output (Variable) +// 0x55,0x00, // Unit Exponent 0 +// 0x66,0x00,0x00, // Unit 0 +// 0x09,0x52, // Usage Gain +// 0x15,0x00, // Logical Minimum 0 +// 0x26,0xFF,0x00, // Logical Maximum FFh (255d) // TODO scaling? +// 0x35,0x00, // Physical Minimum 0 +// 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0x09,0x53, // Usage Trigger Button +// 0x15,0x01, // Logical Minimum 1 +// 0x25,0x08, // Logical Maximum 8 +// 0x35,0x01, // Physical Minimum 1 +// 0x45,0x08, // Physical Maximum 8 +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// Len 108 bytes following 0x09,0x55, // Usage Axes Enable TODO multi axis 0xA1,0x02, // Collection Datalink 0x05,0x01, // Usage Page Generic Desktop @@ -357,39 +230,44 @@ __ALIGN_BEGIN const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE] __ALIGN 0xC0, // END_COLLECTION 0xC0, // END_COLLECTION - // Envelope Report Definition - 0x09,0x5A, // Usage Set Envelope Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_ENVREP+FFB_ID_OFFSET, // Report ID 2 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x5B, // Usage Attack Level - 0x09,0x5D, // Usage Fade Level - 0x16,0x00,0x00, // Logical Minimum 0 - 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) - 0x36,0x00,0x00, // Physical Minimum 0 - 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) - 0x75,0x10, // Report Size 16 - 0x95,0x02, // Report Count 2 - 0x91,0x02, // Output (Variable) - 0x09, 0x5C, // Usage Attack Time - 0x09, 0x5E, // Usage Fade Time - 0x66, 0x03, 0x10, // Unit 1003h (English Linear, Seconds) - 0x55, 0xFD, // Unit Exponent FDh (X10^-3 ==> Milisecond) - 0x27, 0xFF, 0x7F, 0x00, 0x00, // Logical Maximum FFFFFFFFh (4294967295) - 0x47, 0xFF, 0x7F, 0x00, 0x00, // Physical Maximum FFFFFFFFh (4294967295) - 0x75, 0x20, // Report Size 20h (32d) - 0x91, 0x02, // Output (Variable) - 0x45, 0x00, // Physical Maximum 0 - 0x66,0x00,0x00, // Unit 0 - 0x55,0x00, // Unit Exponent 0 - 0xC0 , // End Collection + HIDDESC_FFB_SETENVREP, +// // Envelope Report Definition +// 0x09,0x5A, // Usage Set Envelope Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_ENVREP+FFB_ID_OFFSET, // Report ID 2 +// 0x09,0x22, // Usage Effect Block Index +// 0x15,0x01, // Logical Minimum 1 +// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +// 0x35,0x01, // Physical Minimum 1 +// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0x09,0x5B, // Usage Attack Level +// 0x09,0x5D, // Usage Fade Level +// 0x16,0x00,0x00, // Logical Minimum 0 +// 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) +// 0x36,0x00,0x00, // Physical Minimum 0 +// 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) +// 0x75,0x10, // Report Size 16 +// 0x95,0x02, // Report Count 2 +// 0x91,0x02, // Output (Variable) +// 0x09, 0x5C, // Usage Attack Time +// 0x09, 0x5E, // Usage Fade Time +// 0x66, 0x03, 0x10, // Unit 1003h (English Linear, Seconds) +// 0x55, 0xFD, // Unit Exponent FDh (X10^-3 ==> Milisecond) +// 0x27, 0xFF, 0x7F, 0x00, 0x00, // Logical Maximum FFFFFFFFh (4294967295) +// 0x47, 0xFF, 0x7F, 0x00, 0x00, // Physical Maximum FFFFFFFFh (4294967295) +// 0x75, 0x20, // Report Size 20h (32d) +// 0x91, 0x02, // Output (Variable) +// 0x45, 0x00, // Physical Maximum 0 +// 0x66,0x00,0x00, // Unit 0 +// 0x55,0x00, // Unit Exponent 0 +// 0xC0 , // End Collection +// HIDDESC_FFB_SETCONDREP, + + // Condition report depends on ffb axis count + // 125 bytes following 0x09,0x5F, // Usage Set Condition Report 0xA1,0x02, // Collection Datalink 0x85,HID_ID_CONDREP+FFB_ID_OFFSET, // Report ID 3 @@ -446,102 +324,62 @@ __ALIGN_BEGIN const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE] __ALIGN 0x95,0x01, // Report Count 1 0x91,0x02, // Output (Variable) 0xC0 , // End Collection - 0x09,0x6E, // Usage Set Periodic Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_PRIDREP+FFB_ID_OFFSET, // Report ID 4 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x70, // Usage Magnitude - 0x16,0x00,0x00, // Logical Minimum 0 - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00,0x00, // Physical Minimum 0 - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x75,0x10, // Report Size 16 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09, 0x6F, // Usage Offset - 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) - 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) - 0x95, 0x01, // Report Count 1 - 0x75, 0x10, // Report Size 16 - 0x91, 0x02, // Output (Variable) - 0x09, 0x71, // Usage Phase - 0x66, 0x14, 0x00, // Unit 14h (Eng Rotation, Degrees) - 0x55, 0xFE, // Unit Exponent FEh (X10^-2) - 0x15, 0x00, // Logical Minimum 0 - 0x27, 0x9F, 0x8C, 0x00, 0x00, // Logical Maximum 8C9Fh (35999d) - 0x35, 0x00, // Physical Minimum 0 - 0x47, 0x9F, 0x8C, 0x00, 0x00, // Physical Maximum 8C9Fh (35999d) - 0x75, 0x10, // Report Size 16 - 0x95, 0x01, // Report Count 1 - 0x91, 0x02, // Output (Variable) - 0x09, 0x72, // Usage Period - 0x15, 0x01, // Logical Minimum 1 - 0x27, 0xFF, 0x7F, 0x00, 0x00, // Logical Maximum 7FFFh (32K) - 0x35, 0x01, // Physical Minimum 1 - 0x47, 0xFF, 0x7F, 0x00, 0x00, // Physical Maximum 7FFFh (32K) - 0x66, 0x03, 0x10, // Unit 1003h (English Linear, Seconds) - 0x55, 0xFD, // Unit Exponent FDh (X10^-3 ==> Milisecond) - 0x75, 0x20, // Report Size 20h (32) - 0x95, 0x01, // Report Count 1 - 0x91, 0x02, // Output (Variable) - 0x66, 0x00, 0x00, // Unit 0 - 0x55,0x00, // Unit Exponent 0 - 0xC0 , // End Collection - 0x09,0x73, // Usage Set Constant Force Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_CONSTREP+FFB_ID_OFFSET, // Report ID 5 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x70, // Usage Magnitude - 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) - 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) - 0x75, 0x10, // Report Size 10h (16d) - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - 0x09,0x74, // Usage Set Ramp Force Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_RAMPREP+FFB_ID_OFFSET, // Report ID 6 - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x75, // Usage Ramp Start - 0x09,0x76, // Usage Ramp End - 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) - 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) - 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) - 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) - 0x75,0x10, // Report Size 16 - 0x95,0x02, // Report Count 2 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - -// 0x09,0x68, // Usage Custom Force Data Report + HIDDESC_FFB_SETPERIODICREP, +// 0x09,0x6E, // Usage Set Periodic Report // 0xA1,0x02, // Collection Datalink -// 0x85,HID_ID_CSTMREP+FFB_ID_OFFSET, // Report ID 7 +// 0x85,HID_ID_PRIDREP+FFB_ID_OFFSET, // Report ID 4 +// 0x09,0x22, // Usage Effect Block Index +// 0x15,0x01, // Logical Minimum 1 +// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +// 0x35,0x01, // Physical Minimum 1 +// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0x09,0x70, // Usage Magnitude +// 0x16,0x00,0x00, // Logical Minimum 0 +// 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) +// 0x36,0x00,0x00, // Physical Minimum 0 +// 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) +// 0x75,0x10, // Report Size 16 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0x09, 0x6F, // Usage Offset +// 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) +// 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) +// 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) +// 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) +// 0x95, 0x01, // Report Count 1 +// 0x75, 0x10, // Report Size 16 +// 0x91, 0x02, // Output (Variable) +// 0x09, 0x71, // Usage Phase +// 0x66, 0x14, 0x00, // Unit 14h (Eng Rotation, Degrees) +// 0x55, 0xFE, // Unit Exponent FEh (X10^-2) +// 0x15, 0x00, // Logical Minimum 0 +// 0x27, 0x9F, 0x8C, 0x00, 0x00, // Logical Maximum 8C9Fh (35999d) +// 0x35, 0x00, // Physical Minimum 0 +// 0x47, 0x9F, 0x8C, 0x00, 0x00, // Physical Maximum 8C9Fh (35999d) +// 0x75, 0x10, // Report Size 16 +// 0x95, 0x01, // Report Count 1 +// 0x91, 0x02, // Output (Variable) +// 0x09, 0x72, // Usage Period +// 0x15, 0x01, // Logical Minimum 1 +// 0x27, 0xFF, 0x7F, 0x00, 0x00, // Logical Maximum 7FFFh (32K) +// 0x35, 0x01, // Physical Minimum 1 +// 0x47, 0xFF, 0x7F, 0x00, 0x00, // Physical Maximum 7FFFh (32K) +// 0x66, 0x03, 0x10, // Unit 1003h (English Linear, Seconds) +// 0x55, 0xFD, // Unit Exponent FDh (X10^-3 ==> Milisecond) +// 0x75, 0x20, // Report Size 20h (32) +// 0x95, 0x01, // Report Count 1 +// 0x91, 0x02, // Output (Variable) +// 0x66, 0x00, 0x00, // Unit 0 +// 0x55,0x00, // Unit Exponent 0 +// 0xC0 , // End Collection + HIDDESC_FFB_SETCFREP, +// 0x09,0x73, // Usage Set Constant Force Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_CONSTREP+FFB_ID_OFFSET, // Report ID 5 // 0x09,0x22, // Usage Effect Block Index // 0x15,0x01, // Logical Minimum 1 // 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) @@ -550,119 +388,19 @@ __ALIGN_BEGIN const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE] __ALIGN // 0x75,0x08, // Report Size 8 // 0x95,0x01, // Report Count 1 // 0x91,0x02, // Output (Variable) -// 0x09,0x6C, // Usage Custom Force Data Offset -// 0x15,0x00, // Logical Minimum 0 -// 0x26,0x10,0x27, // Logical Maximum 2710h (10000d) -// 0x35,0x00, // Physical Minimum 0 -// 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) -// 0x75,0x10, // Report Size 10h (16d) +// 0x09,0x70, // Usage Magnitude +// 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) +// 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) +// 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) +// 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) +// 0x75, 0x10, // Report Size 10h (16d) // 0x95,0x01, // Report Count 1 // 0x91,0x02, // Output (Variable) -// 0x09,0x69, // Usage Custom Force Data -// 0x15,0x81, // Logical Minimum 81h (-127d) -// 0x25,0x7F, // Logical Maximum 7Fh (127d) -// 0x35,0x00, // Physical Minimum 0 -// 0x46,0xFF,0x00, // Physical Maximum FFh (255d) -// 0x75,0x08, // Report Size 8 -// 0x95,0x0C, // Report Count Ch (12d) -// 0x92,0x02,0x01, // Output (Variable, Buffered) // 0xC0 , // End Collection -// 0x09,0x66, // Usage Download Force Sample + HIDDESC_FFB_SETRAMPREP, +// 0x09,0x74, // Usage Set Ramp Force Report // 0xA1,0x02, // Collection Datalink -// 0x85,HID_ID_SMPLREP+FFB_ID_OFFSET, // Report ID 8 -// 0x05,0x01, // Usage Page Generic Desktop -// 0x09,0x30, // Usage X -// 0x09,0x31, // Usage Y -// 0x15,0x81, // Logical Minimum 81h (-127d) -// 0x25,0x7F, // Logical Maximum 7Fh (127d) -// 0x35,0x00, // Physical Minimum 0 -// 0x46,0xFF,0x00, // Physical Maximum FFh (255d) -// 0x75,0x08, // Report Size 8 -// 0x95,0x02, // Report Count 2 -// 0x91,0x02, // Output (Variable) -// 0xC0 , // End Collection - - 0x05,0x0F, // Usage Page Physical Interface - 0x09,0x77, // Usage Effect Operation Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_EFOPREP+FFB_ID_OFFSET, // Report ID Ah (10d) - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0x09,0x78, // Usage Effect Operation - 0xA1,0x02, // Collection Datalink - 0x09,0x79, // Usage Op Effect Start - 0x09,0x7A, // Usage Op Effect Start Solo - 0x09,0x7B, // Usage Op Effect Stop - 0x15,0x01, // Logical Minimum 1 - 0x25,0x03, // Logical Maximum 3 - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x00, // Output - 0xC0 , // End Collection - 0x09,0x7C, // Usage Loop Count - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0xFF,0x00, // Physical Maximum FFh (255d) - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - 0x09,0x90, // Usage PID Block Free Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_BLKFRREP+FFB_ID_OFFSET, // Report ID Bh (11d) - 0x09,0x22, // Usage Effect Block Index - 0x15,0x01, // Logical Minimum 1 - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection - - 0x09,0x95, // Usage PID Device Control (0x96?) - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_CTRLREP+FFB_ID_OFFSET, // Report ID Ch (12d) - 0x09,0x96, // Usage PID Device Control (0x96?) - 0xA1,0x02, // Collection Datalink - - 0x09,0x97, // Usage DC Enable Actuators - 0x09,0x98, // Usage DC Disable Actuators - 0x09,0x99, // Usage DC Stop All Effects - 0x09,0x9A, // Usage DC Device Reset - 0x09,0x9B, // Usage DC Device Pause - 0x09,0x9C, // Usage DC Device Continue - - - - 0x15,0x01, // Logical Minimum 1 - 0x25,0x06, // Logical Maximum 6 - 0x75,0x01, // Report Size 1 - 0x95,0x08, // Report Count 8 - 0x91,0x02, // Output - - 0xC0 , // End Collection - 0xC0 , // End Collection - 0x09,0x7D, // Usage Device Gain Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_GAINREP+FFB_ID_OFFSET, // Report ID Dh (13d) - 0x09,0x7E, // Usage Device Gain - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0x91,0x02, // Output (Variable) - 0xC0 , // End Collection -// 0x09,0x6B, // Usage Set Custom Force Report -// 0xA1,0x02, // Collection Datalink -// 0x85,HID_ID_SETCREP+FFB_ID_OFFSET, // Report ID Eh (14d) +// 0x85,HID_ID_RAMPREP+FFB_ID_OFFSET, // Report ID 6 // 0x09,0x22, // Usage Effect Block Index // 0x15,0x01, // Logical Minimum 1 // 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) @@ -671,131 +409,442 @@ __ALIGN_BEGIN const uint8_t hid_2ffb_desc[USB_HID_2FFB_REPORT_DESC_SIZE] __ALIGN // 0x75,0x08, // Report Size 8 // 0x95,0x01, // Report Count 1 // 0x91,0x02, // Output (Variable) -// 0x09,0x6D, // Usage Sample Count +// 0x09,0x75, // Usage Ramp Start +// 0x09,0x76, // Usage Ramp End +// 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) +// 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) +// 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) +// 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) +// 0x75,0x10, // Report Size 16 +// 0x95,0x02, // Report Count 2 +// 0x91,0x02, // Output (Variable) +// 0xC0 , // End Collection +// +// +//// 0x09,0x68, // Usage Custom Force Data Report +//// 0xA1,0x02, // Collection Datalink +//// 0x85,HID_ID_CSTMREP+FFB_ID_OFFSET, // Report ID 7 +//// 0x09,0x22, // Usage Effect Block Index +//// 0x15,0x01, // Logical Minimum 1 +//// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +//// 0x35,0x01, // Physical Minimum 1 +//// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +//// 0x75,0x08, // Report Size 8 +//// 0x95,0x01, // Report Count 1 +//// 0x91,0x02, // Output (Variable) +//// 0x09,0x6C, // Usage Custom Force Data Offset +//// 0x15,0x00, // Logical Minimum 0 +//// 0x26,0x10,0x27, // Logical Maximum 2710h (10000d) +//// 0x35,0x00, // Physical Minimum 0 +//// 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) +//// 0x75,0x10, // Report Size 10h (16d) +//// 0x95,0x01, // Report Count 1 +//// 0x91,0x02, // Output (Variable) +//// 0x09,0x69, // Usage Custom Force Data +//// 0x15,0x81, // Logical Minimum 81h (-127d) +//// 0x25,0x7F, // Logical Maximum 7Fh (127d) +//// 0x35,0x00, // Physical Minimum 0 +//// 0x46,0xFF,0x00, // Physical Maximum FFh (255d) +//// 0x75,0x08, // Report Size 8 +//// 0x95,0x0C, // Report Count Ch (12d) +//// 0x92,0x02,0x01, // Output (Variable, Buffered) +//// 0xC0 , // End Collection +//// 0x09,0x66, // Usage Download Force Sample +//// 0xA1,0x02, // Collection Datalink +//// 0x85,HID_ID_SMPLREP+FFB_ID_OFFSET, // Report ID 8 +//// 0x05,0x01, // Usage Page Generic Desktop +//// 0x09,0x30, // Usage X +//// 0x09,0x31, // Usage Y +//// 0x15,0x81, // Logical Minimum 81h (-127d) +//// 0x25,0x7F, // Logical Maximum 7Fh (127d) +//// 0x35,0x00, // Physical Minimum 0 +//// 0x46,0xFF,0x00, // Physical Maximum FFh (255d) +//// 0x75,0x08, // Report Size 8 +//// 0x95,0x02, // Report Count 2 +//// 0x91,0x02, // Output (Variable) +//// 0xC0 , // End Collection + HIDDESC_FFB_EFOPREP, +// 0x05,0x0F, // Usage Page Physical Interface +// 0x09,0x77, // Usage Effect Operation Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_EFOPREP+FFB_ID_OFFSET, // Report ID Ah (10d) +// 0x09,0x22, // Usage Effect Block Index +// 0x15,0x01, // Logical Minimum 1 +// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +// 0x35,0x01, // Physical Minimum 1 +// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0x09,0x78, // Usage Effect Operation +// 0xA1,0x02, // Collection Datalink +// 0x09,0x79, // Usage Op Effect Start +// 0x09,0x7A, // Usage Op Effect Start Solo +// 0x09,0x7B, // Usage Op Effect Stop +// 0x15,0x01, // Logical Minimum 1 +// 0x25,0x03, // Logical Maximum 3 +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x00, // Output +// 0xC0 , // End Collection +// 0x09,0x7C, // Usage Loop Count // 0x15,0x00, // Logical Minimum 0 // 0x26,0xFF,0x00, // Logical Maximum FFh (255d) // 0x35,0x00, // Physical Minimum 0 // 0x46,0xFF,0x00, // Physical Maximum FFh (255d) -// 0x75,0x08, // Report Size 8 -// 0x95,0x01, // Report Count 1 // 0x91,0x02, // Output (Variable) -// 0x09,0x51, // Usage Sample Period -// 0x66,0x03,0x10, // Unit 1003h (4099d) -// 0x55,0xFD, // Unit Exponent FDh (253d) +// 0xC0 , // End Collection + HIDDESC_FFB_BLOCKFREEREP, +// 0x09,0x90, // Usage PID Block Free Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_BLKFRREP+FFB_ID_OFFSET, // Report ID Bh (11d) +// 0x09,0x22, // Usage Effect Block Index +// 0x15,0x01, // Logical Minimum 1 +// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +// 0x35,0x01, // Physical Minimum 1 +// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0x91,0x02, // Output (Variable) +// 0xC0 , // End Collection + HIDDESC_FFB_DEVCTRLREP, +// 0x09,0x95, // Usage PID Device Control (0x96?) +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_CTRLREP+FFB_ID_OFFSET, // Report ID Ch (12d) +// 0x09,0x96, // Usage PID Device Control (0x96?) +// 0xA1,0x02, // Collection Datalink +// +// 0x09,0x97, // Usage DC Enable Actuators +// 0x09,0x98, // Usage DC Disable Actuators +// 0x09,0x99, // Usage DC Stop All Effects +// 0x09,0x9A, // Usage DC Device Reset +// 0x09,0x9B, // Usage DC Device Pause +// 0x09,0x9C, // Usage DC Device Continue +// +// +// +// 0x15,0x01, // Logical Minimum 1 +// 0x25,0x06, // Logical Maximum 6 +// 0x75,0x01, // Report Size 1 +// 0x95,0x08, // Report Count 8 +// 0x91,0x02, // Output +// +// 0xC0 , // End Collection +// 0xC0 , // End Collection +// 0x09,0x7D, // Usage Device Gain Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_GAINREP+FFB_ID_OFFSET, // Report ID Dh (13d) +// 0x09,0x7E, // Usage Device Gain // 0x15,0x00, // Logical Minimum 0 -// 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) +// 0x26,0xFF,0x00, // Logical Maximum FFh (255d) // 0x35,0x00, // Physical Minimum 0 -// 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) -// 0x75,0x10, // Report Size 10h (16d) +// 0x46,0x10,0x27, // Physical Maximum 2710h (10000d) +// 0x75,0x08, // Report Size 8 // 0x95,0x01, // Report Count 1 // 0x91,0x02, // Output (Variable) -// 0x55,0x00, // Unit Exponent 0 -// 0x66,0x00,0x00, // Unit 0 +// 0xC0 , // End Collection + +//// 0x09,0x6B, // Usage Set Custom Force Report +//// 0xA1,0x02, // Collection Datalink +//// 0x85,HID_ID_SETCREP+FFB_ID_OFFSET, // Report ID Eh (14d) +//// 0x09,0x22, // Usage Effect Block Index +//// 0x15,0x01, // Logical Minimum 1 +//// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +//// 0x35,0x01, // Physical Minimum 1 +//// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +//// 0x75,0x08, // Report Size 8 +//// 0x95,0x01, // Report Count 1 +//// 0x91,0x02, // Output (Variable) +//// 0x09,0x6D, // Usage Sample Count +//// 0x15,0x00, // Logical Minimum 0 +//// 0x26,0xFF,0x00, // Logical Maximum FFh (255d) +//// 0x35,0x00, // Physical Minimum 0 +//// 0x46,0xFF,0x00, // Physical Maximum FFh (255d) +//// 0x75,0x08, // Report Size 8 +//// 0x95,0x01, // Report Count 1 +//// 0x91,0x02, // Output (Variable) +//// 0x09,0x51, // Usage Sample Period +//// 0x66,0x03,0x10, // Unit 1003h (4099d) +//// 0x55,0xFD, // Unit Exponent FDh (253d) +//// 0x15,0x00, // Logical Minimum 0 +//// 0x26,0xFF,0x7F, // Logical Maximum 7FFFh (32767d) +//// 0x35,0x00, // Physical Minimum 0 +//// 0x46,0xFF,0x7F, // Physical Maximum 7FFFh (32767d) +//// 0x75,0x10, // Report Size 10h (16d) +//// 0x95,0x01, // Report Count 1 +//// 0x91,0x02, // Output (Variable) +//// 0x55,0x00, // Unit Exponent 0 +//// 0x66,0x00,0x00, // Unit 0 +//// 0xC0 , // End Collection + HIDDESC_FFB_NEWEFREP, +// 0x09,0xAB, // Usage Create New Effect Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_NEWEFREP+FFB_ID_OFFSET, // Report ID 1 +// 0x09,0x25, // Usage Effect Type +// 0xA1,0x02, // Collection Datalink +// 0x09, HID_USAGE_CONST, // Usage ET Constant Force +// 0x09, HID_USAGE_RAMP, // Usage ET Ramp +// 0x09, HID_USAGE_SQUR, // Usage ET Square +// 0x09, HID_USAGE_SINE, // Usage ET Sine +// 0x09, HID_USAGE_TRNG, // Usage ET Triangle +// 0x09, HID_USAGE_STUP, // Usage ET Sawtooth Up +// 0x09, HID_USAGE_STDN, // Usage ET Sawtooth Down +// 0x09, HID_USAGE_SPRNG, // Usage ET Spring +// 0x09, HID_USAGE_DMPR, // Usage ET Damper +// 0x09, HID_USAGE_INRT, // Usage ET Inertia +// 0x09, HID_USAGE_FRIC, // Usage ET Friction +//// 0x09, 0x28, // Usage ET Custom Force Data +// 0x25,0x0B, // Logical Maximum Ch (11d) +// 0x15,0x01, // Logical Minimum 1 +// 0x35,0x01, // Physical Minimum 1 +// 0x45,0x0B, // Physical Maximum Ch (11d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0xB1,0x00, // Feature +// 0xC0 , // End Collection +// 0x05,0x01, // Usage Page Generic Desktop +// 0x09,0x3B, // Usage Reserved (Byte count) +// 0x15,0x00, // Logical Minimum 0 +// 0x26,0xFF,0x01, // Logical Maximum 1FFh (511d) +// 0x35,0x00, // Physical Minimum 0 +// 0x46,0xFF,0x01, // Physical Maximum 1FFh (511d) +// 0x75,0x0A, // Report Size Ah (10d) +// 0x95,0x01, // Report Count 1 +// 0xB1,0x02, // Feature (Variable) +// 0x75,0x06, // Report Size 6 +// 0xB1,0x01, // Feature (Constant) // 0xC0 , // End Collection - 0x09,0xAB, // Usage Create New Effect Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_NEWEFREP+FFB_ID_OFFSET, // Report ID 1 - 0x09,0x25, // Usage Effect Type +// 0x05,0x0F, // Usage Page Physical Interface + HIDDESC_FFB_BLOCKLOADREP, +// 0x09,0x89, // Usage Block Load Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_BLKLDREP+FFB_ID_OFFSET, // Report ID 0x12 +// 0x09,0x22, // Usage Effect Block Index +// 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) +// 0x15,0x01, // Logical Minimum 1 +// 0x35,0x01, // Physical Minimum 1 +// 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0xB1,0x02, // Feature (Variable) +// 0x09,0x8B, // Usage Block Load Status +// 0xA1,0x02, // Collection Datalink +// 0x09,0x8C, // Usage Block Load Success +// 0x09,0x8D, // Usage Block Load Full +// 0x09,0x8E, // Usage Block Load Error +// 0x15,0x01, // Logical Minimum 1 +// 0x25,0x03, // Logical Maximum 3 +// 0x35,0x01, // Physical Minimum 1 +// 0x45,0x03, // Physical Maximum 3 +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0xB1,0x00, // Feature +// 0xC0 , // End Collection +// 0x09,0xAC, // Usage Pool available +// 0x15,0x00, // Logical Minimum 0 +// 0x27,0xFF,0xFF,0x00,0x00, // Logical Maximum FFFFh (65535d) +// 0x35,0x00, // Physical Minimum 0 +// 0x47,0xFF,0xFF,0x00,0x00, // Physical Maximum FFFFh (65535d) +// 0x75,0x10, // Report Size 10h (16d) +// 0x95,0x01, // Report Count 1 +// 0xB1,0x00, // Feature +// 0xC0 , // End Collection + HIDDESC_FFB_POOLREP, +// 0x09,0x7F, // Usage PID Pool Report +// 0xA1,0x02, // Collection Datalink +// 0x85,HID_ID_POOLREP+FFB_ID_OFFSET, // Report ID 0x13 +// 0x09,0x80, // Usage RAM Pool size +// 0x75,0x10, // Report Size 10h (16d) +// 0x95,0x01, // Report Count 1 +// 0x15,0x00, // Logical Minimum 0 +// 0x35,0x00, // Physical Minimum 0 +// 0x27,0xFF,0xFF,0x00,0x00, // Logical Maximum FFFFh (65535d) +// 0x47,0xFF,0xFF,0x00,0x00, // Physical Maximum FFFFh (65535d) +// 0xB1,0x02, // Feature (Variable) +// 0x09,0x83, // Usage Simultaneous Effects Max +// 0x26,0xFF,0x00, // Logical Maximum FFh (255d) +// 0x46,0xFF,0x00, // Physical Maximum FFh (255d) +// 0x75,0x08, // Report Size 8 +// 0x95,0x01, // Report Count 1 +// 0xB1,0x02, // Feature (Variable) +// 0x09,0xA9, // Usage Device Managed Pool +// 0x09,0xAA, // Usage Shared Parameter Blocks +// 0x75,0x01, // Report Size 1 +// 0x95,0x02, // Report Count 2 +// 0x15,0x00, // Logical Minimum 0 +// 0x25,0x01, // Logical Maximum 1 +// 0x35,0x00, // Physical Minimum 0 +// 0x45,0x01, // Physical Maximum 1 +// 0xB1,0x02, // Feature (Variable) +// 0x75,0x06, // Report Size 6 +// 0x95,0x01, // Report Count 1 +// 0xB1,0x03, // Feature (Constant, Variable) +// 0xC0, // End Collection + + 0xC0 /* END_COLLECTION */ +}; +#endif + +#ifdef AXIS2_FFB_HID_DESC_32B +__ALIGN_BEGIN const uint8_t hid_2ffb_desc_32b[USB_HID_2FFB_REPORT_DESC_32B_SIZE] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ + 0x09, 0x04, /* USAGE (Joystick)*/ + 0xa1, 0x01, /* COLLECTION (Application)*/ + HIDDESC_GAMEPAD_32B, + + HIDDESC_CTRL_REPORTS, // HID command report support + + HIDDESC_FFB_STATEREP, + /* + Output + Collection Datalink: + Usage Set Effect Report + + ID:1 + Effect Block Index: 8bit + + subcollection Effect Type + 12 effect types, 8bit each + + */ + HIDDESC_FFB_SETEFREP, + +// Len 108 bytes following + 0x09,0x55, // Usage Axes Enable TODO multi axis + 0xA1,0x02, // Collection Datalink + 0x05,0x01, // Usage Page Generic Desktop + 0x09,0x30, // Usage X + 0x09,0x31, // Usage Y + 0x15,0x00, // Logical Minimum 0 + 0x25,0x01, // Logical Maximum 1 + 0x75,0x01, // Report Size 1 + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0xC0 , // End Collection + 0x05,0x0F, // Usage Page Physical Interface + 0x09,0x56, // Usage Direction Enable + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0x95,0x05, // Report Count 5 + 0x91,0x03, // Output (Constant, Variable) + + 0x09,0x57, // Usage Direction 0xA1,0x02, // Collection Datalink - 0x09, HID_USAGE_CONST, // Usage ET Constant Force - 0x09, HID_USAGE_RAMP, // Usage ET Ramp - 0x09, HID_USAGE_SQUR, // Usage ET Square - 0x09, HID_USAGE_SINE, // Usage ET Sine - 0x09, HID_USAGE_TRNG, // Usage ET Triangle - 0x09, HID_USAGE_STUP, // Usage ET Sawtooth Up - 0x09, HID_USAGE_STDN, // Usage ET Sawtooth Down - 0x09, HID_USAGE_SPRNG, // Usage ET Spring - 0x09, HID_USAGE_DMPR, // Usage ET Damper - 0x09, HID_USAGE_INRT, // Usage ET Inertia - 0x09, HID_USAGE_FRIC, // Usage ET Friction -// 0x09, 0x28, // Usage ET Custom Force Data - 0x25,0x0B, // Logical Maximum Ch (11d) + 0x0B,0x01,0x00,0x0A,0x00, // Usage Ordinals: Instance 1 + 0x0B,0x02,0x00,0x0A,0x00, // Usage Ordinals: Instance 2 + 0x66,0x14,0x00, // Unit 14h (20d) Angular position + 0x55,0xFE, // Unit Exponent FEh (254d) +// 0x15,0x00, // Logical Minimum 0 +// 0x26,0xFF,0x00, // Logical Maximum FFh (255d) + 0x15,0x00, // Logical Minimum 0 + 0x27,0xA0,0x8C,0x00,0x00, // Logical Maximum 8CA0h (36000d) + 0x35,0x00, // Physical Minimum 0 + 0x47,0xA0,0x8C,0x00,0x00, // Physical Maximum 8CA0h (36000d) + 0x66,0x00,0x00, // Unit 0 + 0x75,0x10, // Report Size 16 +// 0x95,0x01, // Report Count 1 + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0x55,0x00, // Unit Exponent 0 + 0x66,0x00,0x00, // Unit 0 + 0xC0, // End Collection + + 0x05, 0x0F, // USAGE_PAGE (Physical Interface) + 0x09, 0x58, // USAGE (Type Specific Block Offset) + 0xA1, 0x02, // COLLECTION (Logical) + 0x0B, 0x01, 0x00, 0x0A, 0x00, //USAGE (Ordinals:Instance 1 + 0x0B, 0x02, 0x00, 0x0A, 0x00, //USAGE (Ordinals:Instance 2) + 0x26, 0xFD, 0x7F, // LOGICAL_MAXIMUM (32765) ; 32K RAM or ROM max. + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x02, // REPORT_COUNT (2) + 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0xC0, // END_COLLECTION + 0xC0, // END_COLLECTION + + HIDDESC_FFB_SETENVREP, + +// HIDDESC_FFB_SETCONDREP, + + // Condition report depends on ffb axis count + // 125 bytes following + 0x09,0x5F, // Usage Set Condition Report + 0xA1,0x02, // Collection Datalink + 0x85,HID_ID_CONDREP+FFB_ID_OFFSET, // Report ID 3 + 0x09,0x22, // Usage Effect Block Index 0x15,0x01, // Logical Minimum 1 + 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) 0x35,0x01, // Physical Minimum 1 - 0x45,0x0B, // Physical Maximum Ch (11d) + 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) 0x75,0x08, // Report Size 8 0x95,0x01, // Report Count 1 - 0xB1,0x00, // Feature - 0xC0 , // End Collection - 0x05,0x01, // Usage Page Generic Desktop - 0x09,0x3B, // Usage Reserved (Byte count) - 0x15,0x00, // Logical Minimum 0 - 0x26,0xFF,0x01, // Logical Maximum 1FFh (511d) - 0x35,0x00, // Physical Minimum 0 - 0x46,0xFF,0x01, // Physical Maximum 1FFh (511d) - 0x75,0x0A, // Report Size Ah (10d) - 0x95,0x01, // Report Count 1 - 0xB1,0x02, // Feature (Variable) - 0x75,0x06, // Report Size 6 - 0xB1,0x01, // Feature (Constant) - 0xC0 , // End Collection - 0x05,0x0F, // Usage Page Physical Interface - 0x09,0x89, // Usage Block Load Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_BLKLDREP+FFB_ID_OFFSET, // Report ID 0x12 - 0x09,0x22, // Usage Effect Block Index - 0x25,MAX_EFFECTS, // Logical Maximum 28h (40d) - 0x15,0x01, // Logical Minimum 1 - 0x35,0x01, // Physical Minimum 1 - 0x45,MAX_EFFECTS, // Physical Maximum 28h (40d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0xB1,0x02, // Feature (Variable) - 0x09,0x8B, // Usage Block Load Status - 0xA1,0x02, // Collection Datalink - 0x09,0x8C, // Usage Block Load Success - 0x09,0x8D, // Usage Block Load Full - 0x09,0x8E, // Usage Block Load Error - 0x15,0x01, // Logical Minimum 1 + 0x91,0x02, // Output (Variable) + 0x09,0x23, // Usage Parameter Block Offset + 0x15,0x00, // Logical Minimum 0 0x25,0x03, // Logical Maximum 3 - 0x35,0x01, // Physical Minimum 1 + 0x35,0x00, // Physical Minimum 0 0x45,0x03, // Physical Maximum 3 - 0x75,0x08, // Report Size 8 + 0x75,0x04, // Report Size 4 0x95,0x01, // Report Count 1 - 0xB1,0x00, // Feature - 0xC0 , // End Collection - 0x09,0xAC, // Usage Pool available - 0x15,0x00, // Logical Minimum 0 - 0x27,0xFF,0xFF,0x00,0x00, // Logical Maximum FFFFh (65535d) - 0x35,0x00, // Physical Minimum 0 - 0x47,0xFF,0xFF,0x00,0x00, // Physical Maximum FFFFh (65535d) - 0x75,0x10, // Report Size 10h (16d) - 0x95,0x01, // Report Count 1 - 0xB1,0x00, // Feature + 0x91,0x02, // Output (Variable) + 0x09,0x58, // Usage Type Specific Block Off... + 0xA1,0x02, // Collection Datalink + 0x0B,0x01,0x00,0x0A,0x00, // Usage Ordinals: Instance 1 + 0x0B,0x02,0x00,0x0A,0x00, // Usage Ordinals: Instance 2 + 0x75,0x02, // Report Size 2 + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0xC0 , // End Collection + 0x16,0x00, 0x80, // Logical Minimum 7FFFh (-32767d) + 0x26,0xff, 0x7f, // Logical Maximum 7FFFh (32767d) + 0x36,0x00, 0x80, // Physical Minimum 7FFFh (-32767d) + 0x46,0xff, 0x7f, // Physical Maximum 7FFFh (32767d) + + 0x09,0x60, // Usage CP Offset + 0x75,0x10, // Report Size 16 + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) + 0x36,0x00, 0x80, // Physical Minimum (-32768) + 0x46,0xff, 0x7f, // Physical Maximum (32767) + 0x09,0x61, // Usage Positive Coefficient + 0x09,0x62, // Usage Negative Coefficient + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0x16,0x00,0x00, // Logical Minimum 0 + 0x26,0xff, 0x7f, // Logical Maximum (32767) + 0x36,0x00,0x00, // Physical Minimum 0 + 0x46,0xff, 0x7f, // Physical Maximum (32767) + 0x09,0x63, // Usage Positive Saturation + 0x09,0x64, // Usage Negative Saturation + 0x75,0x10, // Report Size 16 + 0x95,0x02, // Report Count 2 + 0x91,0x02, // Output (Variable) + 0x09,0x65, // Usage Dead Band + 0x46,0xff, 0x7f, // Physical Maximum (32767) + 0x95,0x01, // Report Count 1 + 0x91,0x02, // Output (Variable) 0xC0 , // End Collection - 0x09,0x7F, // Usage PID Pool Report - 0xA1,0x02, // Collection Datalink - 0x85,HID_ID_POOLREP+FFB_ID_OFFSET, // Report ID 0x13 - 0x09,0x80, // Usage RAM Pool size - 0x75,0x10, // Report Size 10h (16d) - 0x95,0x01, // Report Count 1 - 0x15,0x00, // Logical Minimum 0 - 0x35,0x00, // Physical Minimum 0 - 0x27,0xFF,0xFF,0x00,0x00, // Logical Maximum FFFFh (65535d) - 0x47,0xFF,0xFF,0x00,0x00, // Physical Maximum FFFFh (65535d) - 0xB1,0x02, // Feature (Variable) - 0x09,0x83, // Usage Simultaneous Effects Max - 0x26,0xFF,0x00, // Logical Maximum FFh (255d) - 0x46,0xFF,0x00, // Physical Maximum FFh (255d) - 0x75,0x08, // Report Size 8 - 0x95,0x01, // Report Count 1 - 0xB1,0x02, // Feature (Variable) - 0x09,0xA9, // Usage Device Managed Pool - 0x09,0xAA, // Usage Shared Parameter Blocks - 0x75,0x01, // Report Size 1 - 0x95,0x02, // Report Count 2 - 0x15,0x00, // Logical Minimum 0 - 0x25,0x01, // Logical Maximum 1 - 0x35,0x00, // Physical Minimum 0 - 0x45,0x01, // Physical Maximum 1 - 0xB1,0x02, // Feature (Variable) - 0x75,0x06, // Report Size 6 - 0x95,0x01, // Report Count 1 - 0xB1,0x03, // Feature (Constant, Variable) - 0xC0, // End Collection + HIDDESC_FFB_SETPERIODICREP, + + HIDDESC_FFB_SETCFREP, + + HIDDESC_FFB_SETRAMPREP, + + HIDDESC_FFB_EFOPREP, + + HIDDESC_FFB_BLOCKFREEREP, + + HIDDESC_FFB_DEVCTRLREP, + + HIDDESC_FFB_NEWEFREP, + + HIDDESC_FFB_BLOCKLOADREP, + + HIDDESC_FFB_POOLREP, 0xC0 /* END_COLLECTION */ }; - #endif + + diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_hid_gamepad.c b/Firmware/FFBoard/UserExtensions/Src/usb_hid_gamepad.c index 6f9364491..bc56f3781 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_hid_gamepad.c +++ b/Firmware/FFBoard/UserExtensions/Src/usb_hid_gamepad.c @@ -16,124 +16,31 @@ */ __ALIGN_BEGIN const uint8_t hid_gamepad_desc[USB_HID_GAMEPAD_REPORT_DESC_SIZE] __ALIGN_END = { - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0xa1, 0x00, // COLLECTION (Physical) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x40, // USAGE_MAXIMUM (Button 64) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x40, // REPORT_COUNT (64) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, HID_USAGE_X, // USAGE (X) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 1 - HIDDESC_32B_ENTRY(0x01) -#endif - 0x09, HID_USAGE_Y, // USAGE (Y) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 2 - HIDDESC_32B_ENTRY(0x02) -#endif - 0x09, HID_USAGE_Z, // USAGE (Z) -#if defined(HIDAXISRES_32B) && MAX_AXIS == 3 - HIDDESC_32B_ENTRY(0x03) -#endif - 0x09, HID_USAGE_RX, // USAGE (Rx) - 0x09, HID_USAGE_RY, // USAGE (Ry) - 0x09, HID_USAGE_RZ, // USAGE (Rz) - 0x09, HID_USAGE_SL1, // USAGE (Dial) - 0x09, HID_USAGE_SL0, // USAGE (Slider) - 0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767) - 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) -#if defined(HIDAXISRES_32B) - 0x95, 0x08-MAX_AXIS, // REPORT_COUNT (8- amount of 32b axes) -#else - 0x95, 0x08, // REPORT_COUNT (8) -#endif - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - - - // Control reports - 0x06, 0x00, 0xFF, // USAGE_PAGE (Vendor) - 0x09, 0x00, // USAGE (Vendor) - 0xA1, 0x01, // Collection (Application) - - 0x85,HID_ID_HIDCMD, // Report ID - 0x09, 0x01, // USAGE (Vendor) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0x04, 0x00, // Logical Maximum 4 - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x02, // USAGE (Vendor) class address - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x03, // USAGE (Vendor) class instance - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x04, // USAGE (Vendor) cmd - 0x75, 0x20, // REPORT_SIZE (32) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x05, // USAGE (Vendor) - 0x75, 0x40, // REPORT_SIZE (64) value - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - - 0x09, 0x06, // USAGE (Vendor) address - 0x75, 0x40, // REPORT_SIZE (64) - 0x95, 0x01, // REPORT_COUNT (1) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ + 0x09, 0x04, /* USAGE (Joystick)*/ + 0xa1, 0x01, /* COLLECTION (Application)*/ + HIDDESC_GAMEPAD_16B, - 0x85,HID_ID_HIDCMD, // Report ID - 0x09, 0x01, // USAGE (Vendor) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0x04, 0x00, // Logical Maximum 4 - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) + HIDDESC_CTRL_REPORTS, // HID command report support - 0x09, 0x02, // USAGE (Vendor) class address - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x03, // USAGE (Vendor) class instance - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x04, // USAGE (Vendor) cmd - 0x75, 0x20, // REPORT_SIZE (32) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x05, // USAGE (Vendor) - 0x75, 0x40, // REPORT_SIZE (64) value - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - - 0x09, 0x06, // USAGE (Vendor) address - 0x75, 0x40, // REPORT_SIZE (64) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xC0 /* END_COLLECTION */ +}; +#endif +#ifdef FFB_HID_DESC_GAMEPAD_32B - 0xc0, // END_COLLECTION +/** + * USB HID descriptor containing a gamepad definition and the vendor defined reports but no PID FFB + */ +__ALIGN_BEGIN const uint8_t hid_gamepad_desc_32b[USB_HID_GAMEPAD_REPORT_DESC_32B_SIZE] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ + 0x09, 0x04, /* USAGE (Joystick)*/ + 0xa1, 0x01, /* COLLECTION (Application)*/ + HIDDESC_GAMEPAD_32B, + HIDDESC_CTRL_REPORTS, // HID command report support 0xC0 /* END_COLLECTION */ }; From 2b474517fcec98d4f8c82669713dce2d8f6d5a27 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Thu, 4 Apr 2024 15:31:10 +0200 Subject: [PATCH 22/40] Split HID gamepad report buffer into helper class --- Firmware/FFBoard/Inc/ffb_defs.h | 108 +++++++++++------- .../FFBoard/UserExtensions/Inc/FFBHIDMain.h | 7 +- .../FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 39 ++++--- 3 files changed, 96 insertions(+), 58 deletions(-) diff --git a/Firmware/FFBoard/Inc/ffb_defs.h b/Firmware/FFBoard/Inc/ffb_defs.h index c5596b073..f6f0a8eef 100644 --- a/Firmware/FFBoard/Inc/ffb_defs.h +++ b/Firmware/FFBoard/Inc/ffb_defs.h @@ -97,21 +97,22 @@ #ifdef __cplusplus +template struct __attribute__((__packed__)) reportHID_t { uint8_t id = 1; uint64_t buttons = 0; -#if defined(HIDAXISRES_32B) && MAX_AXIS >= 1 - int32_t X = 0; +#if MAX_AXIS >= 1 + dtypeaxis X = 0; #else int16_t X = 0; #endif -#if defined(HIDAXISRES_32B) && MAX_AXIS >= 2 - int32_t Y = 0; +#if MAX_AXIS >= 2 + dtypeaxis Y = 0; #else int16_t Y = 0; #endif -#if defined(HIDAXISRES_32B) && MAX_AXIS >= 3 - int32_t Z = 0; +#if MAX_AXIS >= 3 + dtypeaxis Z = 0; #else int16_t Z = 0; #endif @@ -121,41 +122,70 @@ struct __attribute__((__packed__)) reportHID_t { int16_t Dial = 0; int16_t Slider = 0; }; - -/* - * Helper function to access analog axes in packed HID report struct +/** + * Helper class for double buffered HID gamepad reports to allow use of different datatypes for main axes + * Double buffer allows testing if data has changed before sending */ -inline void setHidReportAxis(reportHID_t *report, uint8_t idx, uint32_t val){ - - switch(idx){ - case 0: - report->X = val; - break; - case 1: - report->Y = val; - break; - case 2: - report->Z = val; - break; - case 3: - report->RX = val; - break; - case 4: - report->RY = val; - break; - case 5: - report->RZ = val; - break; - case 6: - report->Dial = val; - break; - case 7: - report->Slider = val; - break; - default: - return; +class HID_GamepadReport_base{ +public: + virtual void setHidReportAxis(uint8_t idx, uint32_t val) = 0; + virtual uint8_t* getBuffer() = 0; + virtual uint32_t getLength() = 0; + virtual uint64_t getButtons() = 0; + virtual void setButtons(uint64_t btn) = 0; //! Must use setter to prevent unaligned access + virtual bool changed() = 0; + virtual void swap() = 0; +}; + +template +class HID_GamepadReport : public HID_GamepadReport_base{ +private: + reportHID_t report1; + reportHID_t report2; + reportHID_t* report = &report1; + +public: + uint64_t getButtons() override {return report->buttons;} + void setButtons(uint64_t btn) override {report->buttons = btn;} + + void setHidReportAxis(uint8_t idx, uint32_t val) override { + switch(idx){ + case 0: + report->X = val; + break; + case 1: + report->Y = val; + break; + case 2: + report->Z = val; + break; + case 3: + report->RX = val; + break; + case 4: + report->RY = val; + break; + case 5: + report->RZ = val; + break; + case 6: + report->Dial = val; + break; + case 7: + report->Slider = val; + break; + default: + return; + } } -} + bool changed() override {return memcmp(&report1,&report2,sizeof(reportHID_t)) != 0;} + void swap() override {report = (report == &report1 ? &report2 : &report1);} // Swaps report buffers + + uint32_t getLength() override {return sizeof(reportHID_t);} + uint8_t* getBuffer() override {return reinterpret_cast(this->report);} + +}; + typedef struct { diff --git a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h index bdb0bd200..736b6c81b 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h +++ b/Firmware/FFBoard/UserExtensions/Inc/FFBHIDMain.h @@ -103,7 +103,8 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto uint8_t usb_report_rate = HID_BINTERVAL; //for FS USB 1 = 1000hz, 2 = 500hz, 3 = 333hz 4 = 250hz, 5 = 200hz 6 = 166hz, 8 = 125hz etc... uint8_t usb_report_rate_idx = ffbrates.defaultmode; #ifndef TIM_FFB - uint8_t ffb_rate_divider = 0; // TODO support ffb without timers again + uint8_t ffb_rate_divider = 0; + uint8_t ffb_rate_counter = 0; #endif @@ -137,8 +138,8 @@ class FFBHIDMain: public FFBoardMain, public cpp_freertos::Thread, PersistentSto std::vector> btns; std::vector> analog_inputs; - reportHID_t reportHID; - reportHID_t lastReportHID; + std::unique_ptr reportHID; + uint8_t reportSendCounter = 0; const uint8_t analogAxisCount = 8; diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index c50cb9e5f..90e8dcec8 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -33,7 +33,13 @@ FFBHIDMain::FFBHIDMain(uint8_t axisCount,bool hidAxis32b) : SelectableInputs(ButtonSource::all_buttonsources,AnalogSource::all_analogsources), axisCount(axisCount),hidAxis32b(hidAxis32b) { - + if(hidAxis32b){ + reportHID = std::make_unique>(); + }else{ + reportHID = std::make_unique>(); + } +// reportHID((hidAxis32b ? HID_GamepadReport() : HID_GamepadReport())), +// lastReportHID((hidAxis32b ? HID_GamepadReport() : HID_GamepadReport())), restoreFlashDelayed(); // Load parameters registerCommands(); @@ -104,7 +110,10 @@ void FFBHIDMain::Run(){ #endif while(true){ #ifndef TIM_FFB - Delay(1); + while(ffb_rate_counter++ < ffb_rate_divider){ + Delay(1); + } + ffb_rate_counter = 0; #else WaitForNotification(); #endif @@ -169,12 +178,11 @@ void FFBHIDMain::send_report(){ // if(!sourcesSem.Take(10)){ // return; // } - // Read buttons - reportHID.buttons = 0; // Reset buttons + // Read buttons uint64_t b = 0; SelectableInputs::getButtonValues(b); - reportHID.buttons = b; + reportHID->setButtons(b); // Encoder //axes_manager->addAxesToReport(analogAxesReport, &count); @@ -185,7 +193,8 @@ void FFBHIDMain::send_report(){ if(!hidAxis32b){ val = val >> 16; // Scale to 16b } - setHidReportAxis(&reportHID,count++,val); + //setHidReportAxis(&reportHID,count++,val); + reportHID->setHidReportAxis(count++, val); } // Fill remaining values with analog inputs @@ -193,29 +202,27 @@ void FFBHIDMain::send_report(){ for(int32_t val : *axes){ if(count >= analogAxisCount) break; - if(count <= MAX_AXIS && hidAxis32b) + if((count <= MAX_AXIS) && hidAxis32b) val = val << 16; // Shift up 16 bit to fill 32b value. Primary axis is 32b - setHidReportAxis(&reportHID,count++,val); + reportHID->setHidReportAxis(count++, val); } // sourcesSem.Give(); // Fill rest for(;countsetHidReportAxis(count, 0); } /* * Only send a new report if actually changed since last time or timeout and hid is ready */ - if( (reportSendCounter > 100/usb_report_rate || (memcmp(&lastReportHID,&reportHID,sizeof(reportHID_t)) != 0) )) + if( (reportSendCounter > 100/usb_report_rate || reportHID->changed()) ) { - - - tud_hid_report(0, reinterpret_cast(&reportHID), sizeof(reportHID_t)); - lastReportHID = reportHID; - reportSendCounter = 0; - + tud_hid_report(0, reportHID->getBuffer(), reportHID->getLength()); + reportHID->swap(); // Report has changed and was sent. Swap buffers. + reportSendCounter = 0; } } From 3c02223c23199bcb6a315b59b27a8f372a73e567 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 8 Apr 2024 11:49:35 +0200 Subject: [PATCH 23/40] Cleanup --- .../UserExtensions/Inc/usb_hid_ffb_desc.h | 22 +++++-------------- .../UserExtensions/Src/TMC4671_configs.cpp | 4 +--- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h index 61b3fccfd..9257ceaf6 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h +++ b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h @@ -10,22 +10,10 @@ #include "constants.h" #include "hid.h" -//#if defined(HIDAXISRES_32B) -//#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 + 16 -//#else -//#define USB_HID_1FFB_REPORT_DESC_SIZE 1196 -//#endif -//#ifdef AXIS1_FFB_HID_DESC -//extern const uint8_t hid_1ffb_desc[USB_HID_1FFB_REPORT_DESC_SIZE]; -//#endif - -//#if defined(HIDAXISRES_32B) -//#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 + 16 -//#else -//#define USB_HID_2FFB_REPORT_DESC_SIZE 1215 -//#endif - - +/** \defgroup HID Descriptors + * \details Contains definitions of different HID descriptor parts * + * @{ + */ @@ -774,5 +762,5 @@ extern const uint8_t hid_gamepad_desc[USB_HID_GAMEPAD_REPORT_DESC_SIZE]; extern const uint8_t hid_gamepad_desc_32b[USB_HID_GAMEPAD_REPORT_DESC_32B_SIZE]; #endif - +/** @}*/ #endif /* USB_INC_USB_HID_FFB_DESC_H_ */ diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp index 1062d05f6..1d5cb0d0d 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671_configs.cpp @@ -71,7 +71,7 @@ const TMC4671HardwareTypeConf conf1_2_2 = { .bbm = 20, }; const TMC4671HardwareTypeConf conf1_3 = { - .name = "v1.2.2 ACS724 (66mV/A)", + .name = "v1.3 ACS724 (66mV/A)", .hwVersion = (uint8_t)TMC_HW_Ver::v1_3_66mv, .adcOffset = 0, .thermistorSettings = { @@ -101,8 +101,6 @@ const TMC4671HardwareTypeConf conf1_3 = { .enc_hall = 1, .enc_ext = 1, - .analog_enc_skip_cal = 0, - .allowFluxDissipationDeactivation = 1 } }; From bca95eb09dd0c205dc7c9fd44eda416ac5e96773 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 16 Apr 2024 14:35:14 +0200 Subject: [PATCH 24/40] I2C eeprom using port class. Requires port definition and id >=1 --- Firmware/FFBoard/Inc/cpp_target_config.h | 4 ++++ Firmware/FFBoard/Src/I2C.cpp | 18 ----------------- Firmware/FFBoard/Src/flash_helpers.cpp | 25 +++++++++++++++--------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/Firmware/FFBoard/Inc/cpp_target_config.h b/Firmware/FFBoard/Inc/cpp_target_config.h index fcf4f7ed6..20b898825 100644 --- a/Firmware/FFBoard/Inc/cpp_target_config.h +++ b/Firmware/FFBoard/Inc/cpp_target_config.h @@ -47,4 +47,8 @@ extern const OutputPin debugpin; extern const OutputPin gpMotor; #endif +#if defined(I2C_PORT_EEPROM) +extern I2CPort i2cport_int; +#endif + #endif diff --git a/Firmware/FFBoard/Src/I2C.cpp b/Firmware/FFBoard/Src/I2C.cpp index decbe4192..33470ab8a 100644 --- a/Firmware/FFBoard/Src/I2C.cpp +++ b/Firmware/FFBoard/Src/I2C.cpp @@ -14,24 +14,6 @@ ClassIdentifier I2CPort::info = { -//static bool operator==(const I2C_InitTypeDef& lhs, const I2C_InitTypeDef& rhs) { -// return lhs.AddressingMode == rhs.AddressingMode -// && lhs.ClockSpeed == rhs.ClockSpeed -// && lhs.DualAddressMode == rhs.DualAddressMode -// && lhs.DutyCycle == rhs.DutyCycle -// && lhs.GeneralCallMode == rhs.GeneralCallMode -// && lhs.NoStretchMode == rhs.NoStretchMode -// && lhs.OwnAddress1 == rhs.OwnAddress1 -// && lhs.OwnAddress2 == rhs.OwnAddress2; -//} - -//static bool operator==(const I2C_InitTypeDef& lhs, const I2C_InitTypeDef& rhs) { -// return memcmp(&lhs,&rhs,sizeof(I2C_InitTypeDef)) == 0; -//} -// - - - I2CPort::I2CPort(I2C_HandleTypeDef &hi2c,const I2CPortHardwareConfig& presets,uint8_t instance) : CommandHandler("i2c", CLSID_I2CPORT, instance), hi2c(hi2c),presets(presets) { restoreFlashDelayed(); #ifdef I2C_COMMANDS_DISABLED_IF_NOT_USED diff --git a/Firmware/FFBoard/Src/flash_helpers.cpp b/Firmware/FFBoard/Src/flash_helpers.cpp index 4b0c2d051..1008df97d 100644 --- a/Firmware/FFBoard/Src/flash_helpers.cpp +++ b/Firmware/FFBoard/Src/flash_helpers.cpp @@ -107,7 +107,10 @@ bool Flash_ReadWriteDefault(uint16_t adr,uint16_t *buf,uint16_t def){ uint8_t i2cBufferEeprom[sizeof(uint16_t)] = {0}; #include "string.h" // Memcpy #include "cassert" - +#include +#include "I2C.h" +I2CDevice i2cdeveeprom; +extern I2CPort i2cport_int; bool Flash_Write(uint16_t adr,uint16_t dat){ uint16_t dataLength = sizeof(dat); @@ -120,12 +123,14 @@ bool Flash_Write(uint16_t adr,uint16_t dat){ // Do segmented writes bool res = false; while(curAdr < adr+dataLength){ - while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){ +// i2cport_int.isDeviceReady(i2cdeveeprom, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT,false) + while(!i2cport_int.isDeviceReady(&i2cdeveeprom, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT,false)){ vTaskDelay(1); } uint16_t wLen = std::min(dataLength,I2C_EEPROM_PAGEWRITE_SIZE - (adr % I2C_EEPROM_PAGEWRITE_SIZE)); - res = HAL_I2C_Mem_Write(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, curAdr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, wLen,I2C_EEPROM_TIMEOUT) == HAL_OK; + res = i2cport_int.writeMem(&i2cdeveeprom, I2C_EEPROM_ADR, curAdr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, wLen, I2C_EEPROM_TIMEOUT, false); + //res = HAL_I2C_Mem_Write(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, curAdr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, wLen,I2C_EEPROM_TIMEOUT) == HAL_OK; curAdr+=wLen; if(!res){ break; @@ -146,11 +151,12 @@ bool Flash_ReadWriteDefault(uint16_t adr,uint16_t *buf,uint16_t def){ bool Flash_Read(uint16_t adr,uint16_t *buf, bool checkempty){ adr *= sizeof(*buf)/I2C_EEPROM_DATA_SIZE; assert(adr < I2C_EEPROM_SIZE); - while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){ -// HAL_Delay(1); + while(!i2cport_int.isDeviceReady(&i2cdeveeprom, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT,false)){ vTaskDelay(1); } - bool res = HAL_I2C_Mem_Read(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, I2C_EEPROM_OFS+adr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, 2, I2C_EEPROM_TIMEOUT) == HAL_OK; + + //bool res = HAL_I2C_Mem_Read(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, I2C_EEPROM_OFS+adr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, 2, I2C_EEPROM_TIMEOUT) == HAL_OK; + bool res = i2cport_int.readMem(&i2cdeveeprom, I2C_EEPROM_ADR, I2C_EEPROM_OFS+adr, I2C_EEPROM_ADR_SIZE, i2cBufferEeprom, 2, I2C_EEPROM_TIMEOUT, false); if(checkempty){ bool empty = true; @@ -176,11 +182,12 @@ bool Flash_Format(){ eraseBuf.fill(I2C_EEPROM_ERASED); for(uint32_t i=I2C_EEPROM_OFS;i(I2C_EEPROM_PAGEWRITE_SIZE,I2C_EEPROM_SIZE-i),I2C_EEPROM_TIMEOUT) == HAL_OK; + //bool res = HAL_I2C_Mem_Write(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, I2C_EEPROM_OFS+i, I2C_EEPROM_ADR_SIZE, eraseBuf.data(), std::min(I2C_EEPROM_PAGEWRITE_SIZE,I2C_EEPROM_SIZE-i),I2C_EEPROM_TIMEOUT) == HAL_OK; + bool res = i2cport_int.writeMem(&i2cdeveeprom, I2C_EEPROM_ADR, I2C_EEPROM_OFS+i, I2C_EEPROM_ADR_SIZE, eraseBuf.data(), std::min(I2C_EEPROM_PAGEWRITE_SIZE,I2C_EEPROM_SIZE-i), I2C_EEPROM_TIMEOUT, false); if(!res){ flag = false; }else{ - while(!HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT) == HAL_OK){ + while(!i2cport_int.isDeviceReady(&i2cdeveeprom, I2C_EEPROM_ADR, 100, I2C_EEPROM_TIMEOUT,false)){ vTaskDelay(1); } } @@ -188,7 +195,7 @@ bool Flash_Format(){ return flag; } bool Flash_Init(){ - return HAL_I2C_IsDeviceReady(&I2C_PORT_EEPROM, I2C_EEPROM_ADR, 10, I2C_EEPROM_TIMEOUT) == HAL_OK; + return i2cport_int.isDeviceReady(&i2cdeveeprom, I2C_EEPROM_ADR, 50, I2C_EEPROM_TIMEOUT,false); } #else From e67f11fcf7f77d4d9f111ba89677e799924f684c Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 23 Apr 2024 14:12:52 +0200 Subject: [PATCH 25/40] TMC check if motor is set before encoder init --- Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index 5dc16bf74..d60c37c2f 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -580,12 +580,12 @@ void TMC4671::Run(){ break; case TMC_ControlState::EncoderInit: - if(powerInitialized && hasPower()) + if(powerInitialized && hasPower() && conf.motconf.motor_type != MotorType::NONE) encoderInit(); break; case TMC_ControlState::ExternalEncoderInit: - if(powerInitialized && hasPower() && drvEncoder != nullptr) + if(powerInitialized && hasPower() && drvEncoder != nullptr && conf.motconf.motor_type != MotorType::NONE) encoderInit(); break; @@ -1170,8 +1170,8 @@ int16_t TMC4671::getPhiE_Enc(){ * Steps the motor a few times to check if the encoder follows correctly */ bool TMC4671::checkEncoder(){ - if(this->conf.motconf.motor_type != MotorType::STEPPER && this->conf.motconf.motor_type != MotorType::BLDC && - conf.motconf.enctype != EncoderType_TMC::uvw && conf.motconf.enctype != EncoderType_TMC::sincos && conf.motconf.enctype != EncoderType_TMC::abn && conf.motconf.enctype != EncoderType_TMC::ext) + if((this->conf.motconf.motor_type != MotorType::STEPPER && this->conf.motconf.motor_type != MotorType::BLDC) || ( + conf.motconf.enctype != EncoderType_TMC::uvw && conf.motconf.enctype != EncoderType_TMC::sincos && conf.motconf.enctype != EncoderType_TMC::abn && conf.motconf.enctype != EncoderType_TMC::ext)) { // If not stepper or bldc return return true; } From 9843a8fffa2154c7cd00ef03442e616f3e0176dd Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 29 Apr 2024 18:11:20 +0200 Subject: [PATCH 26/40] FFBWheel supporting variable range in 32b desc mode --- Firmware/FFBoard/Inc/constants.h | 8 ++++++ .../FFBoard/UserExtensions/Inc/FFBWheel.h | 6 ++++ .../UserExtensions/Inc/usb_hid_ffb_desc.h | 22 +++++++++++---- .../FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 4 ++- .../FFBoard/UserExtensions/Src/FFBWheel.cpp | 28 +++++++++++++------ .../UserExtensions/Src/usb_descriptors.cpp | 10 ++++++- .../UserExtensions/Src/usb_hid_2ffb_desc.c | 2 +- 7 files changed, 63 insertions(+), 17 deletions(-) diff --git a/Firmware/FFBoard/Inc/constants.h b/Firmware/FFBoard/Inc/constants.h index e18918af6..04b6f8b7f 100644 --- a/Firmware/FFBoard/Inc/constants.h +++ b/Firmware/FFBoard/Inc/constants.h @@ -31,11 +31,19 @@ static const uint8_t SW_VERSION_INT[3] = {1,16,6}; // Version as array. 8 bit ea #ifdef FFBWHEEL #ifdef FFBWHEEL_USE_1AXIS_DESC +#ifdef HIDAXISRES_USE_32B_DESC +#define AXIS1_FFB_HID_DESC_32B +#else #define AXIS1_FFB_HID_DESC +#endif +#else +#ifdef HIDAXISRES_USE_32B_DESC +#define AXIS2_FFB_HID_DESC_32B #else #define AXIS2_FFB_HID_DESC #endif #endif +#endif #ifdef FFBJOYSTICK #define AXIS2_FFB_HID_DESC diff --git a/Firmware/FFBoard/UserExtensions/Inc/FFBWheel.h b/Firmware/FFBoard/UserExtensions/Inc/FFBWheel.h index 0f7be1be1..274e93cc0 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/FFBWheel.h +++ b/Firmware/FFBoard/UserExtensions/Inc/FFBWheel.h @@ -12,6 +12,12 @@ #include "FFBHIDMain.h" +#ifdef HIDAXISRES_USE_32B_DESC +#define FFBWHEEL_32B_MODE true +#else +#define FFBWHEEL_32B_MODE false +#endif + class FFBWheel : public FFBHIDMain { public: FFBWheel(); diff --git a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h index 9257ceaf6..242536eba 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h +++ b/Firmware/FFBoard/UserExtensions/Inc/usb_hid_ffb_desc.h @@ -15,20 +15,26 @@ * @{ */ - +#if defined(HIDAXISRES_32B_BITS) && HIDAXISRES_32B_BITS > 2 && HIDAXISRES_32B_BITS < 32 +// 7FFFFFFF for 32 +#define HIDAXISRES_32B_MAXS (1 << (HIDAXISRES_32B_BITS-1))-1 +#else +#define HIDAXISRES_32B_MAXS 0x7FFFFFFF +#define HIDAXISRES_32B_BITS 32 +#endif // HID descriptor building blocks #define HIDDESC_32B_ENTRY(count) /* LOGICAL_MINIMUM (-7FFFFFFF)*/\ - 0x17, 0x01, 0x00, 0x00, 0x80, \ + HID_LOGICAL_MIN_N(-HIDAXISRES_32B_MAXS,3), /*0x17, 0x01, 0x00, 0x00, 0x80,*/\ /* LOGICAL_MAXIMUM (7FFFFFFF)*/\ - 0x27, 0xff, 0xff, 0xff, 0x7f,\ - /* REPORT_SIZE (16)*/\ + HID_LOGICAL_MAX_N(HIDAXISRES_32B_MAXS,3), /* 0x27, 0xff, 0xff, 0xff, 0x7f, */ \ + /* REPORT_SIZE (32)*/\ 0x75, 0x20,\ /* REPORT_COUNT */\ 0x95, count,\ /* INPUT (Data,Var,Abs)*/\ 0x81, 0x02, -#define HIDDESC_32B_ENTRY_SIZE 12 // 12 bytes extra for additional 16b definition 2B count +#define HIDDESC_32B_ENTRY_SIZE 16 // 16 bytes more for range definition #define HIDDESC_GAMEPAD_16B \ @@ -74,7 +80,7 @@ #endif #if MAX_AXIS == 3 #define HIDDESC_GPENTRY_32B_3 0x09, HID_USAGE_DESKTOP_Z, /* USAGE (Z)*/\ - HIDDESC_32B_ENTRY(0x02) + HIDDESC_32B_ENTRY(0x03) #else #define HIDDESC_GPENTRY_32B_3 0x09, HID_USAGE_DESKTOP_Z, /* USAGE (Z)*/ #endif @@ -762,5 +768,9 @@ extern const uint8_t hid_gamepad_desc[USB_HID_GAMEPAD_REPORT_DESC_SIZE]; extern const uint8_t hid_gamepad_desc_32b[USB_HID_GAMEPAD_REPORT_DESC_32B_SIZE]; #endif +#ifdef HIDAXISRES_USE_32B_DESC + +#endif + /** @}*/ #endif /* USB_INC_USB_HID_FFB_DESC_H_ */ diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 90e8dcec8..2eea7683d 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -192,6 +192,8 @@ void FFBHIDMain::send_report(){ for(auto val : *axes){ if(!hidAxis32b){ val = val >> 16; // Scale to 16b + }else{ + val = val >> (32-HIDAXISRES_32B_BITS); // Scale if less than 32b } //setHidReportAxis(&reportHID,count++,val); reportHID->setHidReportAxis(count++, val); @@ -203,7 +205,7 @@ void FFBHIDMain::send_report(){ if(count >= analogAxisCount) break; if((count <= MAX_AXIS) && hidAxis32b) - val = val << 16; // Shift up 16 bit to fill 32b value. Primary axis is 32b + val = val << (HIDAXISRES_32B_BITS-16); // Shift up 16 bit to fill 32b value. Primary axis is 32b reportHID->setHidReportAxis(count++, val); } diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBWheel.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBWheel.cpp index b77f5c37d..1e94dd4cc 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBWheel.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBWheel.cpp @@ -24,7 +24,7 @@ const ClassIdentifier FFBWheel::getInfo(){ FFBWheel::FFBWheel() : - FFBHIDMain(1) + FFBHIDMain(1,FFBWHEEL_32B_MODE) { FFBHIDMain::setFFBEffectsCalc(ffb, effects_calc); } @@ -34,17 +34,29 @@ FFBWheel::~FFBWheel() { } - void FFBWheel::usbInit(){ +#ifdef HIDAXISRES_USE_32B_DESC #ifdef FFBWHEEL_USE_1AXIS_DESC - this->usbdev = std::make_unique(&usb_devdesc_ffboard_composite,usb_cdc_hid_conf_1axis,&usb_ffboard_strings_default); - FFBHIDMain::UsbHidHandler::setHidDesc(hid_1ffb_desc); - static_cast(ffb.get())->setDirectionEnableMask(0x02); +const uint8_t* usbconf = usb_cdc_hid_conf_1axis_32b; +const uint8_t* ffbdesc = hid_1ffb_desc_32b; #else - this->usbdev = std::make_unique(&usb_devdesc_ffboard_composite,usb_cdc_hid_conf_2axis,&usb_ffboard_strings_default); - FFBHIDMain::UsbHidHandler::setHidDesc(hid_2ffb_desc); - static_cast(ffb.get())->setDirectionEnableMask(0x04); +const uint8_t* ffbdesc = hid_2ffb_desc_32b; +const uint8_t* usbconf = usb_cdc_hid_conf_2axis_32b; +#endif +#else // ELSE 32B +#ifdef FFBWHEEL_USE_1AXIS_DESC +const uint8_t* usbconf = usb_cdc_hid_conf_1axis; +const uint8_t* ffbdesc = hid_1ffb_desc; +#else +const uint8_t* ffbdesc = hid_2ffb_desc; +const uint8_t* usbconf = usb_cdc_hid_conf_2axis; #endif +#endif + + this->usbdev = std::make_unique(&usb_devdesc_ffboard_composite,usbconf,&usb_ffboard_strings_default); + + FFBHIDMain::UsbHidHandler::setHidDesc(ffbdesc); + static_cast(ffb.get())->setDirectionEnableMask(0x04); usbdev->registerUsb(); } diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp b/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp index 0b692e60c..d199462e9 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/usb_descriptors.cpp @@ -59,11 +59,19 @@ const uint8_t usb_cdc_conf[] = const uint8_t usb_cdc_hid_conf_1axis[] ={USB_CONF_DESC_HID_CDC(USB_HID_1FFB_REPORT_DESC_SIZE,64)}; #endif +#ifdef AXIS1_FFB_HID_DESC_32B + const uint8_t usb_cdc_hid_conf_1axis_32b[] ={USB_CONF_DESC_HID_CDC(USB_HID_1FFB_REPORT_DESC_32B_SIZE,64)}; +#if TUD_OPT_HIGH_SPEED + const uint8_t usb_cdc_hid_conf_1axis_32b_hs[] ={USB_CONF_DESC_HID_CDC(USB_HID_1FFB_REPORT_DESC_32B_SIZE,512)}; +#endif +#endif + // Composite CDC and HID #ifdef AXIS2_FFB_HID_DESC const uint8_t usb_cdc_hid_conf_2axis[] ={USB_CONF_DESC_HID_CDC(USB_HID_2FFB_REPORT_DESC_SIZE,64)}; #endif -#ifdef AXIS1_FFB_HID_DESC_32B + +#ifdef AXIS2_FFB_HID_DESC_32B const uint8_t usb_cdc_hid_conf_2axis_32b[] ={USB_CONF_DESC_HID_CDC(USB_HID_2FFB_REPORT_DESC_32B_SIZE,64)}; #endif diff --git a/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c b/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c index 386e5a1aa..6083e7e52 100644 --- a/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c +++ b/Firmware/FFBoard/UserExtensions/Src/usb_hid_2ffb_desc.c @@ -691,7 +691,7 @@ __ALIGN_BEGIN const uint8_t hid_2ffb_desc_32b[USB_HID_2FFB_REPORT_DESC_32B_SIZE] 0x05, 0x01, /* USAGE_PAGE (Generic Desktop)*/ 0x09, 0x04, /* USAGE (Joystick)*/ 0xa1, 0x01, /* COLLECTION (Application)*/ - HIDDESC_GAMEPAD_32B, + HIDDESC_GAMEPAD_32B, HIDDESC_CTRL_REPORTS, // HID command report support From d396f62c106bbe0d9f55380c9860680ffb47e624 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 29 Apr 2024 18:13:53 +0200 Subject: [PATCH 27/40] HID command interface using reference in loop --- Firmware/FFBoard/Src/HidCommandInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/FFBoard/Src/HidCommandInterface.cpp b/Firmware/FFBoard/Src/HidCommandInterface.cpp index 9a73a4268..418c3a032 100644 --- a/Firmware/FFBoard/Src/HidCommandInterface.cpp +++ b/Firmware/FFBoard/Src/HidCommandInterface.cpp @@ -99,7 +99,7 @@ void HID_CommandInterface::sendReplies(const std::vector& results } - for(const CommandReply reply : replies){ + for(const CommandReply& reply : replies){ if(reply.type == CommandReplyType::STRING){ continue; // Ignore string only replies } From da0b4391c008b824c59db35f93c472cab0907bbe Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Fri, 3 May 2024 10:56:02 +0200 Subject: [PATCH 28/40] Fixed first 16b axis being scaled incorrectly --- Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 2eea7683d..428967168 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -204,7 +204,7 @@ void FFBHIDMain::send_report(){ for(int32_t val : *axes){ if(count >= analogAxisCount) break; - if((count <= MAX_AXIS) && hidAxis32b) + if((count < MAX_AXIS) && hidAxis32b) val = val << (HIDAXISRES_32B_BITS-16); // Shift up 16 bit to fill 32b value. Primary axis is 32b reportHID->setHidReportAxis(count++, val); } From f616395b4b036c171d5bba0ff090d91c2ca6d804 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Fri, 14 Jun 2024 11:13:10 +0200 Subject: [PATCH 29/40] Axis updates friction and inertia filters on samplerate change --- Firmware/FFBoard/Src/Axis.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/FFBoard/Src/Axis.cpp b/Firmware/FFBoard/Src/Axis.cpp index 400421dee..41f487b28 100644 --- a/Firmware/FFBoard/Src/Axis.cpp +++ b/Firmware/FFBoard/Src/Axis.cpp @@ -804,6 +804,8 @@ void Axis::updateFilters(uint8_t profileId){ accelFilter.setFc(filterAccelCst[this->filterProfileId].freq / filter_f); accelFilter.setQ(filterAccelCst[this->filterProfileId].q / 100.0); damperFilter.setFc(filterDamperCst.freq/filter_f); + inertiaFilter.setFc(filterInertiaCst.freq/filter_f); + frictionFilter.setFc(filterFrictionCst.freq/filter_f); } /** From 1cda177fc1b949679e748a1eee2783defb3959e8 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 26 Aug 2024 10:39:49 +0200 Subject: [PATCH 30/40] Allow overriding flash defaults. Requires >CPP20 --- Firmware/FFBoard/Inc/flash_helpers.h | 4 ++++ Firmware/FFBoard/Src/SystemCommands.cpp | 1 + Firmware/FFBoard/Src/cppmain.cpp | 3 +++ Firmware/FFBoard/Src/flash_helpers.cpp | 20 ++++++++++++++++++++ 4 files changed, 28 insertions(+) diff --git a/Firmware/FFBoard/Inc/flash_helpers.h b/Firmware/FFBoard/Inc/flash_helpers.h index a409a48fe..68961e711 100644 --- a/Firmware/FFBoard/Inc/flash_helpers.h +++ b/Firmware/FFBoard/Inc/flash_helpers.h @@ -23,6 +23,7 @@ extern "C" { #include #include +#include bool Flash_Init(); bool Flash_Write(uint16_t adr,uint16_t dat); // Writes or updates only if changed or missing @@ -58,4 +59,7 @@ inline std::tuple unpack(uint16_t v) { #endif +extern const std::span> flash_factory_defaults; // address,value pair +void Flash_Write_Defaults(); + #endif /* FLASH_HELPERS_H_ */ diff --git a/Firmware/FFBoard/Src/SystemCommands.cpp b/Firmware/FFBoard/Src/SystemCommands.cpp index 9874be82f..853f46ec6 100644 --- a/Firmware/FFBoard/Src/SystemCommands.cpp +++ b/Firmware/FFBoard/Src/SystemCommands.cpp @@ -279,6 +279,7 @@ CommandStatus SystemCommands::internalCommand(const ParsedCommand& cmd,std::vect if(cmd.type == CMDtype::set && cmd.val==1){ if(Flash_Format()){ + Flash_Write_Defaults(); // Restore default values if present flag = CommandStatus::OK; }else{ flag = CommandStatus::ERR; diff --git a/Firmware/FFBoard/Src/cppmain.cpp b/Firmware/FFBoard/Src/cppmain.cpp index cc760ff07..412b75efb 100644 --- a/Firmware/FFBoard/Src/cppmain.cpp +++ b/Firmware/FFBoard/Src/cppmain.cpp @@ -49,6 +49,7 @@ void cppmain() { if(forceErase){ Flash_Format(); + Flash_Write_Defaults(); } // // Check if flash is initialized @@ -64,11 +65,13 @@ void cppmain() { // Check if flash is initialized uint16_t lastFlashVersion = 0; if(!Flash_Read(ADR_FLASH_VERSION, &lastFlashVersion)){ // Version never written + Flash_Write_Defaults(); Flash_Write(ADR_FLASH_VERSION, FLASH_VERSION); } Flash_Read(ADR_FLASH_VERSION,&lastFlashVersion); if(lastFlashVersion != FLASH_VERSION){ Flash_Format(); // Major version changed or could not write initial value. force a format + Flash_Write_Defaults(); Flash_Write(ADR_FLASH_VERSION, FLASH_VERSION); } diff --git a/Firmware/FFBoard/Src/flash_helpers.cpp b/Firmware/FFBoard/Src/flash_helpers.cpp index 1008df97d..75e0f61e0 100644 --- a/Firmware/FFBoard/Src/flash_helpers.cpp +++ b/Firmware/FFBoard/Src/flash_helpers.cpp @@ -8,6 +8,7 @@ #include "eeprom_addresses.h" #include #include "mutex.hpp" +#include cpp_freertos::MutexStandard flashMutex; // Flash helpers @@ -291,3 +292,22 @@ __weak bool OTP_Read(uint16_t adroffset,uint64_t* dat){ } #endif + +#ifndef FLASH_FACTORY_DEFAULTS_OVERRIDE + /** + * To define factory defaults create a span/array in a core folder defined for example as + * const auto flash_defaults = std::to_array>({ {ADR_CURRENT_CONFIG,1} }); // ADR,VALUE pairs + * const std::span> flash_factory_defaults = flash_defaults; + */ +const std::array,0> empty_flash_defaults; // Empty +const std::span> flash_factory_defaults = empty_flash_defaults; +#endif + +/** + * Writes factory default values to flash. Does nothing if no defaults are defined + */ +void Flash_Write_Defaults(){ + for(const std::pair &kv : flash_factory_defaults){ + Flash_Write(kv.first, kv.second); // Try to write values + } +} \ No newline at end of file From 15ae944deec2213ceccf1baa0305500070da29bf Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Mon, 10 Feb 2025 10:47:25 +0100 Subject: [PATCH 31/40] Wait at least 1ms if no TIM_FFB defined --- Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 428967168..344ec0044 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -110,7 +110,7 @@ void FFBHIDMain::Run(){ #endif while(true){ #ifndef TIM_FFB - while(ffb_rate_counter++ < ffb_rate_divider){ + while(ffb_rate_counter++ <= ffb_rate_divider){ Delay(1); } ffb_rate_counter = 0; From ce15222c80aa0fed0bfcb93da2b9de1d7710654c Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Wed, 26 Feb 2025 17:20:10 +0100 Subject: [PATCH 32/40] TMC4671 fix ext encoder timer not starting --- Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index d60c37c2f..5f7757826 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -1856,7 +1856,9 @@ Encoder* TMC4671::getEncoder(){ void TMC4671::setEncoder(std::shared_ptr& encoder){ MotorDriver::drvEncoder = encoder; if(conf.motconf.enctype == EncoderType_TMC::ext && externalEncoderTimer){ - // TODO Calibrate and align external encoder + if(!extEncUpdater){ // If updater has not been set up because the encoder mode was changed before the external encoder passed force it now + setUpExtEncTimer(); + } changeState(TMC_ControlState::ExternalEncoderInit); } } From 6026b4c45fe8574357ca069e059331a0c65ec628 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Wed, 26 Feb 2025 17:21:55 +0100 Subject: [PATCH 33/40] TMC4671 make ext enc timer ARR a define --- Firmware/FFBoard/UserExtensions/Inc/TMC4671.h | 4 +++- Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h index e418f4377..8d5cc8cbd 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h +++ b/Firmware/FFBoard/UserExtensions/Inc/TMC4671.h @@ -53,7 +53,9 @@ extern TIM_HandleTypeDef TIM_TMC; #ifndef TMC4671_ITUNE_CUTOFF #define TMC4671_ITUNE_CUTOFF 0.04 #endif - +#ifndef TIM_TMC_ARR +#define TIM_TMC_ARR 200 +#endif enum class TMC_ControlState : uint32_t {uninitialized,waitPower,Shutdown,Running,EncoderInit,EncoderFinished,HardError,OverTemp,IndexSearch,FullCalibration,ExternalEncoderInit,Pidautotune}; diff --git a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp index 5f7757826..8e996cba1 100644 --- a/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/TMC4671.cpp @@ -3131,7 +3131,7 @@ void TMC4671::setUpExtEncTimer(){ extEncUpdater = std::make_unique(this); // Setup timer this->externalEncoderTimer = &TIM_TMC; - this->externalEncoderTimer->Instance->ARR = 200; // 200 = 5khz = 5 tmc cycles, 250 = 4khz, 240 = 6 tmc cycles + this->externalEncoderTimer->Instance->ARR = TIM_TMC_ARR; // 200 = 5khz = 5 tmc cycles, 250 = 4khz, 240 = 6 tmc cycles this->externalEncoderTimer->Instance->PSC = ((TIM_TMC_BCLK)/1000000) +1; // 1µs ticks this->externalEncoderTimer->Instance->CR1 = 1; HAL_TIM_Base_Start_IT(this->externalEncoderTimer); From c1dc72cd81b3d352328c71444cb15a328d4835ff Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Sat, 10 Jan 2026 15:05:55 +0100 Subject: [PATCH 34/40] Fixed timerless FFB updating waiting 1ms too long --- Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp index 344ec0044..428967168 100644 --- a/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/FFBHIDMain.cpp @@ -110,7 +110,7 @@ void FFBHIDMain::Run(){ #endif while(true){ #ifndef TIM_FFB - while(ffb_rate_counter++ <= ffb_rate_divider){ + while(ffb_rate_counter++ < ffb_rate_divider){ Delay(1); } ffb_rate_counter = 0; From af7885f6018f05f0e36b39ff8ee50c3f38c7cc59 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Sat, 10 Jan 2026 15:22:04 +0100 Subject: [PATCH 35/40] Enabled TIM_FFB for F407VG target --- Firmware/Targets/F407VG/Core/Inc/target_constants.h | 1 + Firmware/Targets/F407VG/Core/Src/main.c | 2 +- Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc | 5 +++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Firmware/Targets/F407VG/Core/Inc/target_constants.h b/Firmware/Targets/F407VG/Core/Inc/target_constants.h index 860f27682..6409a522b 100644 --- a/Firmware/Targets/F407VG/Core/Inc/target_constants.h +++ b/Firmware/Targets/F407VG/Core/Inc/target_constants.h @@ -69,6 +69,7 @@ #define TIM_USER htim9 // Timer with full core clock speed available for the mainclass #define TIM_TMC htim6 // Timer running at half clock speed #define TIM_TMC_BCLK SystemCoreClock / 2 +#define TIM_FFB htim13 extern UART_HandleTypeDef huart1; #define UART_PORT_EXT huart1 // main uart port diff --git a/Firmware/Targets/F407VG/Core/Src/main.c b/Firmware/Targets/F407VG/Core/Src/main.c index b2316a867..a23a8c8ee 100644 --- a/Firmware/Targets/F407VG/Core/Src/main.c +++ b/Firmware/Targets/F407VG/Core/Src/main.c @@ -1200,7 +1200,7 @@ static void MX_TIM13_Init(void) /* USER CODE END TIM13_Init 1 */ htim13.Instance = TIM13; - htim13.Init.Prescaler = 167; + htim13.Init.Prescaler = 84-1; htim13.Init.CounterMode = TIM_COUNTERMODE_UP; htim13.Init.Period = 100; htim13.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; diff --git a/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc b/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc index d97d47989..e9aab43bb 100644 --- a/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc +++ b/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc @@ -721,6 +721,7 @@ PH1-OSC_OUT.Signal=RCC_OSC_OUT PinOutPanel.RotationAngle=-180 ProjectManager.AskForMigrate=true ProjectManager.BackupPrevious=false +ProjectManager.CompilerLinker=GCC ProjectManager.CompilerOptimize=6 ProjectManager.ComputerToolchain=false ProjectManager.CoupleFile=false @@ -733,7 +734,7 @@ ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x400 ProjectManager.KeepUserCode=true -ProjectManager.LastFirmware=false +ProjectManager.LastFirmware=true ProjectManager.LibraryCopy=1 ProjectManager.MainLocation=Core/Src ProjectManager.MultiThreaded=true @@ -873,7 +874,7 @@ TIM1.TIM_MasterOutputTrigger=TIM_TRGO_RESET TIM1.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_DISABLE TIM13.IPParameters=Prescaler,Period TIM13.Period=100 -TIM13.Prescaler=167 +TIM13.Prescaler=84-1 TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE TIM2.ClockDivision=TIM_CLOCKDIVISION_DIV1 TIM2.CounterMode=TIM_COUNTERMODE_UP From 8d494852d8fcf75b8ce30f06be78747da102afe7 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Thu, 15 Jan 2026 12:18:59 +0100 Subject: [PATCH 36/40] Enable freertos task formatting for F407VG --- Firmware/Targets/F407VG/.cproject | 24 +++++++++++++++++-- .../.settings/stm32cubeide.project.prefs | 6 ++--- .../Targets/F407VG/Core/Inc/FreeRTOSConfig.h | 12 ++++++++++ Firmware/Targets/F407VG/Core/Src/freertos.c | 15 ++++++++++++ .../F407VG/Core/ThreadSafe/newlib_lock_glue.c | 2 +- .../F407VG/Core/ThreadSafe/stm32_lock.h | 2 +- .../Targets/F407VG/OpenFFBoard_F407VG.ioc | 4 ++-- 7 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Firmware/Targets/F407VG/.cproject b/Firmware/Targets/F407VG/.cproject index f645a46aa..81af2569f 100644 --- a/Firmware/Targets/F407VG/.cproject +++ b/Firmware/Targets/F407VG/.cproject @@ -25,7 +25,7 @@ + @@ -241,7 +251,7 @@ + diff --git a/Firmware/Targets/F407VG/.settings/stm32cubeide.project.prefs b/Firmware/Targets/F407VG/.settings/stm32cubeide.project.prefs index be0603234..405ce1e69 100644 --- a/Firmware/Targets/F407VG/.settings/stm32cubeide.project.prefs +++ b/Firmware/Targets/F407VG/.settings/stm32cubeide.project.prefs @@ -1,4 +1,4 @@ -2F62501ED4689FB349E356AB974DBE57=E2380525C25FCA23F64F38676B957D9B -8DF89ED150041C4CBC7CB9A9CAA90856=E2380525C25FCA23F64F38676B957D9B -DC22A860405A8BF2F2C095E5B6529F12=609A53BFF0492F10C829ECAB4963903C +2F62501ED4689FB349E356AB974DBE57=2E846C232C86F8091E1D1C41786923FD +8DF89ED150041C4CBC7CB9A9CAA90856=2E846C232C86F8091E1D1C41786923FD +DC22A860405A8BF2F2C095E5B6529F12=948244613B091C43745821314F11043C eclipse.preferences.version=1 diff --git a/Firmware/Targets/F407VG/Core/Inc/FreeRTOSConfig.h b/Firmware/Targets/F407VG/Core/Inc/FreeRTOSConfig.h index df33746ef..3d718b1e3 100644 --- a/Firmware/Targets/F407VG/Core/Inc/FreeRTOSConfig.h +++ b/Firmware/Targets/F407VG/Core/Inc/FreeRTOSConfig.h @@ -51,6 +51,10 @@ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include extern uint32_t SystemCoreClock; +/* USER CODE BEGIN 0 */ + extern void configureTimerForRunTimeStats(void); + extern unsigned long getRunTimeCounterValue(void); +/* USER CODE END 0 */ #endif #ifndef CMSIS_device_header #define CMSIS_device_header "stm32f4xx.h" @@ -70,7 +74,9 @@ #define configMINIMAL_STACK_SIZE ((uint16_t)64) #define configTOTAL_HEAP_SIZE ((size_t)0xffff) #define configMAX_TASK_NAME_LEN ( 16 ) +#define configGENERATE_RUN_TIME_STATS 1 #define configUSE_TRACE_FACILITY 1 +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 #define configUSE_16_BIT_TICKS 0 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 @@ -169,6 +175,12 @@ standard names. */ #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0 +/* USER CODE BEGIN 2 */ +/* Definitions needed when configGENERATE_RUN_TIME_STATS is on */ +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats +#define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue +/* USER CODE END 2 */ + /* USER CODE BEGIN Defines */ #define CPP_FREERTOS_NO_EXCEPTIONS // For freertos cpp addons #define configAPPLICATION_ALLOCATED_HEAP 1 // ucHeap allocated in freertos.c diff --git a/Firmware/Targets/F407VG/Core/Src/freertos.c b/Firmware/Targets/F407VG/Core/Src/freertos.c index 6eadca3d4..6f24b2c27 100644 --- a/Firmware/Targets/F407VG/Core/Src/freertos.c +++ b/Firmware/Targets/F407VG/Core/Src/freertos.c @@ -55,10 +55,25 @@ uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; // rtos heap // __attribute__((section /* USER CODE END FunctionPrototypes */ /* Hook prototypes */ +void configureTimerForRunTimeStats(void); +unsigned long getRunTimeCounterValue(void); void vApplicationIdleHook(void); void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName); void vApplicationMallocFailedHook(void); +/* USER CODE BEGIN 1 */ +/* Functions needed when configGENERATE_RUN_TIME_STATS is on */ +__weak void configureTimerForRunTimeStats(void) +{ + +} + +__weak unsigned long getRunTimeCounterValue(void) +{ +return 0; +} +/* USER CODE END 1 */ + /* USER CODE BEGIN 2 */ void vApplicationIdleHook( void ) { diff --git a/Firmware/Targets/F407VG/Core/ThreadSafe/newlib_lock_glue.c b/Firmware/Targets/F407VG/Core/ThreadSafe/newlib_lock_glue.c index 8d956e401..4ed4b9ba0 100644 --- a/Firmware/Targets/F407VG/Core/ThreadSafe/newlib_lock_glue.c +++ b/Firmware/Targets/F407VG/Core/ThreadSafe/newlib_lock_glue.c @@ -19,7 +19,7 @@ ****************************************************************************** * @attention * - * Copyright (c) 2023 STMicroelectronics. + * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file diff --git a/Firmware/Targets/F407VG/Core/ThreadSafe/stm32_lock.h b/Firmware/Targets/F407VG/Core/ThreadSafe/stm32_lock.h index 372c5ded9..b661efdda 100644 --- a/Firmware/Targets/F407VG/Core/ThreadSafe/stm32_lock.h +++ b/Firmware/Targets/F407VG/Core/ThreadSafe/stm32_lock.h @@ -48,7 +48,7 @@ ****************************************************************************** * @attention * - * Copyright (c) 2023 STMicroelectronics. + * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file diff --git a/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc b/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc index e9aab43bb..8857b1e93 100644 --- a/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc +++ b/Firmware/Targets/F407VG/OpenFFBoard_F407VG.ioc @@ -176,7 +176,7 @@ FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configTOTAL_HEAP_SIZE,FootprintOK FREERTOS.Tasks01=defaultTask,16,512,StartDefaultTask,As weak,NULL,Dynamic,NULL,NULL FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2 FREERTOS.configENABLE_FPU=1 -FREERTOS.configGENERATE_RUN_TIME_STATS=0 +FREERTOS.configGENERATE_RUN_TIME_STATS=1 FREERTOS.configMINIMAL_STACK_SIZE=64 FREERTOS.configRECORD_STACK_HIGH_ADDRESS=1 FREERTOS.configTIMER_TASK_STACK_DEPTH=128 @@ -184,7 +184,7 @@ FREERTOS.configTOTAL_HEAP_SIZE=0xffff FREERTOS.configUSE_IDLE_HOOK=1 FREERTOS.configUSE_MALLOC_FAILED_HOOK=1 FREERTOS.configUSE_NEWLIB_REENTRANT=1 -FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=0 +FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1 FREERTOS.configUSE_TRACE_FACILITY=1 File.Version=6 GPIO.groupedBy=Show All From 0d9c851594870745d7e8878b14c1c9b8ef44e379 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Thu, 15 Jan 2026 12:19:33 +0100 Subject: [PATCH 37/40] Write task info directly into string buffer --- Firmware/FFBoard/Src/SystemCommands.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Firmware/FFBoard/Src/SystemCommands.cpp b/Firmware/FFBoard/Src/SystemCommands.cpp index 853f46ec6..49b50ebd0 100644 --- a/Firmware/FFBoard/Src/SystemCommands.cpp +++ b/Firmware/FFBoard/Src/SystemCommands.cpp @@ -244,18 +244,22 @@ CommandStatus SystemCommands::internalCommand(const ParsedCommand& cmd,std::vect #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) case FFBoardMain_commands::taskstats: { - char repl[uxTaskGetNumberOfTasks()*64]; - vTaskGetRunTimeStats(repl); - replies.emplace_back("\n"+std::string(repl)); + std::string repl; + repl.resize(uxTaskGetNumberOfTasks()*64,'\0'); + vTaskGetRunTimeStats(repl.data()); + repl.resize(repl.find_first_of('\0')); // Cut + replies.emplace_back("\n"+(repl)); break; } #endif #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) case FFBoardMain_commands::tasklist: { - char repl[uxTaskGetNumberOfTasks()*64]; - vTaskList(repl); - replies.emplace_back("\n"+std::string(repl)); + std::string repl; + repl.resize(uxTaskGetNumberOfTasks()*64,'\0'); + vTaskList(repl.data()); + repl.resize(repl.find_first_of('\0')); // Cut + replies.emplace_back("\n"+(repl)); break; } #endif From 4aaecc54af8ddf4d5adc1c61e2dc3a6cacefc080 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 16 Jan 2026 09:58:57 +0100 Subject: [PATCH 38/40] Fix SPI_Buttons constructor procedure (#164) Fix SPI_Buttons constructor procedure --- .../FFBoard/UserExtensions/Src/SPIButtons.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp b/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp index f4a0512a6..a82e0d710 100644 --- a/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp @@ -51,13 +51,6 @@ SPI_Buttons::SPI_Buttons(uint16_t configuration_address, uint16_t configuration_ this->configuration_address_2 = configuration_address_2; restoreFlash(); - this->spiConfig.peripheral.BaudRatePrescaler = speedPresets[this->conf.spi_speed]; - this->spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_LSB; - this->spiConfig.peripheral.CLKPhase = SPI_PHASE_1EDGE; - this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_LOW; - - initSPI(); - registerCommands(); this->setCommandsEnabled(true); ready = true; @@ -109,18 +102,17 @@ void SPI_Buttons::setConfig(ButtonSourceConfig config){ if(conf.mode == SPI_BtnMode::TM){ this->spiConfig.cspol = true; this->conf.cutRight = true; - this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_LOW; + this->spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_LSB; this->spiConfig.peripheral.CLKPhase = SPI_PHASE_1EDGE; - + this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_LOW; }else if(conf.mode == SPI_BtnMode::PISOSR){ this->spiConfig.cspol = false; this->conf.cutRight = false; + this->spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_LSB; this->spiConfig.peripheral.CLKPhase = SPI_PHASE_2EDGE; this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_HIGH; // its actually shifting on the rising edge but 165 will have the first output set even before clocking. First clock cycle is actually second bit so we sample at the falling edge and skip the first bit with that. } -// spiPort.takeSemaphore(); -// spiPort.configurePort(&this->spiConfig.peripheral); -// spiPort.giveSemaphore(); + this->spiConfig.peripheral.BaudRatePrescaler = speedPresets[this->conf.spi_speed]; initSPI(); if(config.numButtons == 64){ // Special case mask = 0xffffffffffffffff; From cf7dd4dbf76f9b0e62126eecde4207311a7bd134 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Sun, 18 Jan 2026 20:08:33 +0100 Subject: [PATCH 39/40] Version bump 1.16.7 --- Firmware/FFBoard/Inc/constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/FFBoard/Inc/constants.h b/Firmware/FFBoard/Inc/constants.h index 04b6f8b7f..ac1f0fede 100644 --- a/Firmware/FFBoard/Inc/constants.h +++ b/Firmware/FFBoard/Inc/constants.h @@ -8,7 +8,7 @@ * For more settings see target_constants.h in a target specific folder */ -static const uint8_t SW_VERSION_INT[3] = {1,16,6}; // Version as array. 8 bit each! +static const uint8_t SW_VERSION_INT[3] = {1,16,7}; // Version as array. 8 bit each! #ifndef MAX_AXIS #define MAX_AXIS 2 // ONLY USE 2 for now else screws HID Reports #endif From 45b62e76777cf75c5837075cba6c983dea55fc50 Mon Sep 17 00:00:00 2001 From: Lucas Jansson Date: Wed, 5 Nov 2025 12:53:47 +0100 Subject: [PATCH 40/40] Add RP2040 SPI_Buttons mode --- Firmware/FFBoard/UserExtensions/Inc/SPIButtons.h | 2 +- Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Firmware/FFBoard/UserExtensions/Inc/SPIButtons.h b/Firmware/FFBoard/UserExtensions/Inc/SPIButtons.h index 9f8f061df..9e9fdf57a 100644 --- a/Firmware/FFBoard/UserExtensions/Inc/SPIButtons.h +++ b/Firmware/FFBoard/UserExtensions/Inc/SPIButtons.h @@ -19,7 +19,7 @@ // Set this to 64, 128 or 256 to slow down SPI if unstable. #define SPIBUTTONS_SPEED SPI_BAUDRATEPRESCALER_32 -enum class SPI_BtnMode : uint8_t {TM=0,PISOSR=1}; +enum class SPI_BtnMode : uint8_t {TM=0,PISOSR=1,RP2040=2}; struct ButtonSourceConfig{ diff --git a/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp b/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp index a82e0d710..7aa092ef4 100644 --- a/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp +++ b/Firmware/FFBoard/UserExtensions/Src/SPIButtons.cpp @@ -15,7 +15,7 @@ static ButtonSourceConfig decodeIntToConf(uint16_t config, uint16_t config_int_2); static std::tuple encodeConfToInt(ButtonSourceConfig* c); -const std::vector SPI_Buttons::mode_names = {"Thrustmaster/HEF4021BT","74xx165"}; +const std::vector SPI_Buttons::mode_names = {"Thrustmaster/HEF4021BT","74xx165","RP2040"}; const std::vector SPI_Buttons::speed_names = {"Fast","Medium","Slow"}; ClassIdentifier SPI_Buttons_1::info = { @@ -111,6 +111,12 @@ void SPI_Buttons::setConfig(ButtonSourceConfig config){ this->spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_LSB; this->spiConfig.peripheral.CLKPhase = SPI_PHASE_2EDGE; this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_HIGH; // its actually shifting on the rising edge but 165 will have the first output set even before clocking. First clock cycle is actually second bit so we sample at the falling edge and skip the first bit with that. + }else if(conf.mode == SPI_BtnMode::RP2040){ + this->conf.cutRight = false; + this->spiConfig.cspol = true; + this->spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_MSB; + this->spiConfig.peripheral.CLKPhase = SPI_PHASE_1EDGE; + this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_LOW; } this->spiConfig.peripheral.BaudRatePrescaler = speedPresets[this->conf.spi_speed]; initSPI();