teensy LC and 3.1/3.2 project not compiling on 4.0 board

djbordie

New member
Any takers on this one?
i am 97% newb on this.

TeensyDuino version
https://github.com/dchote/fanatecWheelUSB#readme

teensyloader hex version
https://github.com/darknao/btClubSportWheel


trying to get an LC 3.1/3.2 to work on a 4.0 board.
The LC and 3 series are hard to find in Canada, assumed (wrongly) that the code would simply work on a 4.0 board.

Thank you for your help

ERRORS
Code:
Arduino: 1.8.19 (Windows 10), TD: 1.57, Board: "Teensy 4.0, Fanatec CSW, 24 MHz, Smallest Code, US English"





















C:\Users\uvpc\Downloads\arduino-1.8.19\arduino-builder -dump-prefs -logger=machine -hardware C:\Users\uvpc\Downloads\arduino-1.8.19\hardware -tools C:\Users\uvpc\Downloads\arduino-1.8.19\tools-builder -tools C:\Users\uvpc\Downloads\arduino-1.8.19\hardware\tools\avr -built-in-libraries C:\Users\uvpc\Downloads\arduino-1.8.19\libraries -libraries C:\Users\uvpc\Documents\Arduino\libraries -fqbn=teensy:avr:teensy40:usb=fanatec,speed=24,opt=osstd,keys=en-us -ide-version=10819 -build-path C:\Users\uvpc\AppData\Local\Temp\arduino_build_597513 -warnings=none -build-cache C:\Users\uvpc\AppData\Local\Temp\arduino_cache_584247 -verbose C:\Users\uvpc\Downloads\fanatecWheelUSB-master\fanatecWheelUSB\fanatecWheelUSB.ino

C:\Users\uvpc\Downloads\arduino-1.8.19\arduino-builder -compile -logger=machine -hardware C:\Users\uvpc\Downloads\arduino-1.8.19\hardware -tools C:\Users\uvpc\Downloads\arduino-1.8.19\tools-builder -tools C:\Users\uvpc\Downloads\arduino-1.8.19\hardware\tools\avr -built-in-libraries C:\Users\uvpc\Downloads\arduino-1.8.19\libraries -libraries C:\Users\uvpc\Documents\Arduino\libraries -fqbn=teensy:avr:teensy40:usb=fanatec,speed=24,opt=osstd,keys=en-us -ide-version=10819 -build-path C:\Users\uvpc\AppData\Local\Temp\arduino_build_597513 -warnings=none -build-cache C:\Users\uvpc\AppData\Local\Temp\arduino_cache_584247 -verbose C:\Users\uvpc\Downloads\fanatecWheelUSB-master\fanatecWheelUSB\fanatecWheelUSB.ino

Using board 'teensy40' from platform in folder: C:\Users\uvpc\Downloads\arduino-1.8.19\hardware\teensy\avr

Using core 'teensy4' from platform in folder: C:\Users\uvpc\Downloads\arduino-1.8.19\hardware\teensy\avr

Detecting libraries used...

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatecWheelUSB.ino.cpp" -o nul

Alternatives for SPI.h: [SPI@1.0]

ResolveLibrary(SPI.h)

  -> candidates: [SPI@1.0]

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatecWheelUSB.ino.cpp" -o nul

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\debouncer.cpp" -o nul

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatec.cpp" -o nul

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatec_joystick.c" -o nul

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI\\SPI.cpp" -o nul

Generating function prototypes...

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatecWheelUSB.ino.cpp" -o "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\preproc\\ctags_target_for_gcc_minus_e.cpp"

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\preproc\\ctags_target_for_gcc_minus_e.cpp"

Compiling sketch...

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/precompile_helper" "C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr/cores/teensy4" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513" "C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -x c++-header -Os --specs=nano.specs -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr/cores/teensy4" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513/pch/Arduino.h" -o "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513/pch/Arduino.h.gch"

"C:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-gcc" -c -Os --specs=nano.specs -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10819 -DARDUINO_TEENSY40 -DF_CPU=24000000 -DFANATEC_CSW -DLAYOUT_US_ENGLISH "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Users\\uvpc\\Downloads\\arduino-1.8.19\\hardware\\teensy\\avr\\libraries\\SPI" "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatec_joystick.c" -o "C:\\Users\\uvpc\\AppData\\Local\\Temp\\arduino_build_597513\\sketch\\fanatec_joystick.c.o"

fanatec_joystick.c: In function 'fanatec_joystick_send':

fanatec_joystick.c:74: error: unknown type name 'usb_packet_t'

   usb_packet_t *tx_packet;

   ^

fanatec_joystick.c:79: error: 'usb_configuration' undeclared (first use in this function)

     if (!usb_configuration) {

          ^

C:\Users\uvpc\Downloads\fanatecWheelUSB-master\fanatecWheelUSB\fanatec_joystick.c:79:10: note: each undeclared identifier is reported only once for each function it appears in

fanatec_joystick.c:84: warning: implicit declaration of function 'usb_tx_packet_count' 

     if (usb_tx_packet_count(JOYSTICK_ENDPOINT) < TX_PACKET_LIMIT) {

         ^

fanatec_joystick.c:84: error: 'JOYSTICK_ENDPOINT' undeclared (first use in this function)

     if (usb_tx_packet_count(JOYSTICK_ENDPOINT) < TX_PACKET_LIMIT) {

                             ^

fanatec_joystick.c:85: warning: implicit declaration of function 'usb_malloc' 

       tx_packet = usb_malloc();

                   ^

fanatec_joystick.c:85: warning: assignment makes pointer from integer without a cast 

       tx_packet = usb_malloc();

                 ^

fanatec_joystick.c:99: error: request for member 'buf' in something not a structure or union

   memcpy(tx_packet->buf, fanatec_joystick_data, JOYSTICK_SIZE);

                   ^

fanatec_joystick.c:99: error: 'JOYSTICK_SIZE' undeclared (first use in this function)

   memcpy(tx_packet->buf, fanatec_joystick_data, JOYSTICK_SIZE);

                                                 ^

fanatec_joystick.c:100: error: request for member 'len' in something not a structure or union

   tx_packet->len = JOYSTICK_SIZE;

            ^

fanatec_joystick.c:102: warning: implicit declaration of function 'usb_tx' 

   usb_tx(JOYSTICK_ENDPOINT, tx_packet);

   ^

fanatec_joystick.c: In function 'fanatec_lights_recv':

fanatec_joystick.c:109: error: unknown type name 'usb_packet_t'

   usb_packet_t *rx_packet;

   ^

fanatec_joystick.c:113: error: 'usb_configuration' undeclared (first use in this function)

     if (!usb_configuration) {

          ^

fanatec_joystick.c:117: warning: implicit declaration of function 'usb_rx' 

     rx_packet = usb_rx(LIGHTS_ENDPOINT);

                 ^

fanatec_joystick.c:117: error: 'LIGHTS_ENDPOINT' undeclared (first use in this function)

     rx_packet = usb_rx(LIGHTS_ENDPOINT);

                        ^

fanatec_joystick.c:125: error: request for member 'buf' in something not a structure or union

   memcpy(buffer, rx_packet->buf, LIGHTS_SIZE);

                           ^

fanatec_joystick.c:125: error: 'LIGHTS_SIZE' undeclared (first use in this function)

   memcpy(buffer, rx_packet->buf, LIGHTS_SIZE);

                                  ^

fanatec_joystick.c:126: warning: implicit declaration of function 'usb_free' 

   usb_free(rx_packet);

   ^

fanatec_joystick.c: In function 'fanatec_lights_available':

fanatec_joystick.c:135: error: 'usb_configuration' undeclared (first use in this function)

   if (!usb_configuration) {

        ^

fanatec_joystick.c:139: warning: implicit declaration of function 'usb_rx_byte_count' 

   count = usb_rx_byte_count(LIGHTS_ENDPOINT);

           ^

fanatec_joystick.c:139: error: 'LIGHTS_ENDPOINT' undeclared (first use in this function)

   count = usb_rx_byte_count(LIGHTS_ENDPOINT);

                             ^

fanatec_joystick.c: In function 'fanatec_lights_recv':

fanatec_joystick.c:129: warning: control reaches end of non-void function 

 }

 ^

Using library SPI at version 1.0 in folder: C:\Users\uvpc\Downloads\arduino-1.8.19\hardware\teensy\avr\libraries\SPI 

unknown type name 'usb_packet_t'
 
Last edited:
I thought the link would have sufficed, as per the forum rule?

please see source code here;

seems to be missing Wprogram.h, maybe something in the teensy3 vs 4 libraries?

Code:
/*
 *
 * Project: https://github.com/dchote/fanatecWheelUSB
 * Author: Daniel Chote
 *
 * Copyright (C) 2015 darknao
 * https://github.com/darknao/btClubSportWheel
 *
 * This file is part of btClubSportWheel.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "WProgram.h"
#include "Arduino.h"

#include "fanatec_joystick.h"

#include "fanatec.h"
#include "debouncer.h"


#define MAX_SPEED 5000


uint8_t hid_data[35];
uint32_t max_delay = 150000; // overhead if below 120ms
// 400 is too short with fanaleds

bool in_changed;

void hid_output(uint8_t link_id, uint16_t data_length, const uint8_t *data);

void setup();
void loop();

void idle();
void init_wheel();

/* Wheel inputs */
void whClear();
void whButton(uint8_t button, bool val);
void whStick(unsigned int x, unsigned int y);
void whDoubleAxis(unsigned int x, unsigned int y);
void whDoubleClutch(unsigned int x, unsigned int y);
void whHat(int8_t val, bool is_csl);
void whSetId(unsigned int val);

csw_in_t csw_in;
csw_out_t csw_out;

csl_in_t csl_in;
csl_out_t csl_out;

mcl_in_t mcl_in;
mcl_out_t mcl_out;


bool bt_connected;
bool got_hid;
bool show_fwvers;
uint32_t timing;
uint32_t timing_bt;
uint32_t disp_timout;
uint32_t usb_time;

uint8_t hid_pck[7];

debouncer *btDebncer = new debouncer[89];
debouncer hatDebncer = debouncer();

byte rotary_debounce = 0;
int8_t rotary_value = 0;
uint8_t main_link_id = 1;
uint8_t clutch_max = 0xFF;


void setup() {
  fsetup();

  // debounce timer for hat switch
  hatDebncer.interval(50);
  
  // debounce timer for rotary encoder
  btDebncer[17].interval(30);
  btDebncer[18].interval(30);

  fJoystick.useManualSend(true);
  
  whClear();

  // prebuild output packet
  memset(csw_out.raw, 0, sizeof(csw_out_t));
  memset(csl_out.raw, 0, sizeof(csl_out_t));
  memset(mcl_out.raw, 0, sizeof(mcl_out_t));
  
  csw_out.header = 0xa5;
  mcl_out.header = 0xa5;
  csw_out.id = 0x00;
  got_hid = false;

  // debug
  #ifdef HAS_DEBUG
    Serial.begin(115200);
    Serial.println("MCU Ready");
    
    for (int i = 0; i < 100; ++i) {
      delay(100);
      Serial.print(".");
      /* code */
    }

    Serial.println("check for active connection...");
  #endif

  timing = micros();
  timing_bt = millis();
  usb_time = micros();
}



void loop() {
  // Fetching HID packet
  uint16_t hid_size;
  hid_size = fJoystick.recv(&hid_pck, 0);
  if (hid_size > 0) {
    hid_output(1, hid_size, hid_pck);
  } 
  
  switch(detectWheelType()) {
    case CSW_WHEEL:
      // csw stuff
      // Read Fanatec Packet
      
      //csw_out.raw[9] = 0x0F; // xbox light
      transferCswData(&csw_out, &csw_in, sizeof(csw_out.raw));
      init_wheel();
      
      #ifdef HAS_DEBUG
         Serial.print("CSW_IN:");
         for (int i=0; i<sizeof(csw_in.raw); i++) {
            Serial.print(csw_in.raw[i], HEX);
            Serial.print(":");
          }
          Serial.println();
      #endif
      
      // Wheel ID
      whSetId(csw_in.id);
      
      // Left stick
      whStick(csw_in.axisX, csw_in.axisY);
      
      // All buttons
      whButton(1, csw_in.buttons[0] & 0x80); // first top right
      whButton(2, csw_in.buttons[0] & 0x40); // middle right
      whButton(3, csw_in.buttons[0] & 0x20); // second top right
      whButton(4, csw_in.buttons[0] & 0x10); // bottom right
      whButton(5, csw_in.buttons[1] & 0x80); // third center
      whButton(6, csw_in.buttons[1] & 0x40); // first center
      whButton(7, csw_in.buttons[1] & 0x20); // middle left
      whButton(9, csw_in.buttons[1] & 0x04); // bottom left
      whButton(11, csw_in.buttons[2] & 0x08); // second center
      whButton(12, csw_in.buttons[2] & 0x04); // stick button
      
      // paddles shitfer
      whButton(15, csw_in.buttons[1] & 0x08); // left
      whButton(16, csw_in.buttons[1] & 0x01); // right
      
      rotary_value = csw_in.encoder;
      
      if (csw_in.id != CSLMCLGT3) {
        whButton(8, csw_in.buttons[1] & 0x10); // first top left
        whButton(10, csw_in.buttons[1] & 0x02); // second top left
        whButton(13, csw_in.buttons[2] & 0x02); // hat button
        whButton(14, csw_in.buttons[2] & 0x20); // display button
        
        whButton(17, rotary_value == -1); // left
        whButton(18, rotary_value == 1); // right
      }
      
      if (csw_in.id == UNIHUB || csw_in.id == XBOXHUB) {
        // Uni Hub extra buttons
        // BUT_5 array (optional 3 buttons)
        whButton(19, csw_in.btnHub[0] & 0x08);
        whButton(20, csw_in.btnHub[0] & 0x10);
        whButton(21, csw_in.btnHub[0] & 0x20);
        
        // Playstation buttons
        whButton(22, csw_in.btnPS[0] & 0x01);
        whButton(23, csw_in.btnPS[0] & 0x02);
        whButton(24, csw_in.btnPS[0] & 0x04);
        whButton(25, csw_in.btnPS[0] & 0x08);
        whButton(26, csw_in.btnPS[0] & 0x10);
        whButton(27, csw_in.btnPS[0] & 0x20);
        whButton(28, csw_in.btnPS[0] & 0x40);
        whButton(29, csw_in.btnPS[0] & 0x80);
        
        whButton(30, csw_in.btnPS[1] & 0x01);
        whButton(31, csw_in.btnPS[1] & 0x02);
        whButton(32, csw_in.btnPS[1] & 0x04);
        whButton(33, csw_in.btnPS[1] & 0x08);
        whButton(34, csw_in.btnPS[1] & 0x10);
        whButton(35, csw_in.btnPS[1] & 0x20);
        whButton(36, csw_in.btnPS[1] & 0x40);
        whButton(37, csw_in.btnPS[1] & 0x80);
      }
      
      if (csw_in.id == XBOXHUB) {
        // Xbox Hub has 1 extra button
        whButton(38, csw_in.btnHub[1] & 0x08);
      }
      
      whHat(csw_in.buttons[0] & 0x0f, false);
      
      if (csw_in.id == CSLMCLGT3) {
        whButton(8, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x10)); // switch left up
        whButton(19, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x10)); // switch left down
        whButton(10, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x10)); // switch right up
        whButton(20, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x10)); // switch right down
        
        whButton(33, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x20)); // switch left up
        whButton(34, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x20)); // switch left down
        whButton(35, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x20)); // switch right up
        whButton(36, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x20)); // switch right down
        
        whButton(37, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x30)); // switch left up
        whButton(38, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x30)); // switch left down
        whButton(39, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x30)); // switch right up
        whButton(40, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x30)); // switch right down
        
        whButton(41, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x40)); // switch left up
        whButton(42, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x40)); // switch left down
        whButton(43, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x40)); // switch right up
        whButton(44, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x40)); // switch right down
        
        whButton(45, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x50)); // switch left up
        whButton(46, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x50)); // switch left down
        whButton(47, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x50)); // switch right up
        whButton(48, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x50)); // switch right down
        
        whButton(49, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x60)); // switch left up
        whButton(50, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x60)); // switch left down
        whButton(51, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x60)); // switch right up
        whButton(52, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x60)); // switch right down
        
        whButton(53, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x70)); // switch left up
        whButton(54, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x70)); // switch left down
        whButton(55, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x70)); // switch right up
        whButton(56, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x70)); // switch right down
        
        whButton(57, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x80)); // switch left up
        whButton(58, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x80)); // switch left down
        whButton(59, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x80)); // switch right up
        whButton(60, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x80)); // switch right down
        
        whButton(61, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0x90)); // switch left up
        whButton(62, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0x90)); // switch left down
        whButton(63, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0x90)); // switch right up
        whButton(64, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0x90)); // switch right down
        
        whButton(65, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0xA0)); // switch left up
        whButton(66, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0xA0)); // switch left down
        whButton(67, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0xA0)); // switch right up
        whButton(68, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0xA0)); // switch right down
        
        whButton(69, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0xB0)); // switch left up
        whButton(70, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0xB0)); // switch left down
        whButton(71, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0xB0)); // switch right up
        whButton(72, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0xB0)); // switch right down
        
        whButton(73, (csw_in.buttons[1] & 0x10) && ((csw_in.garbage[3] & 0xF0) == 0xC0)); // switch left up
        whButton(74, (csw_in.buttons[2] & 0x80) && ((csw_in.garbage[3] & 0xF0) == 0xC0)); // switch left down
        whButton(75, (csw_in.buttons[1] & 0x02) && ((csw_in.garbage[3] & 0xF0) == 0xC0)); // switch right up
        whButton(76, (csw_in.buttons[2] & 0x40) && ((csw_in.garbage[3] & 0xF0) == 0xC0)); // switch right down
        
        whButton(14, csw_in.buttons[2] & 0x02); // xbox
        
        if ((csw_in.garbage[2] & 0x0F) == 0x02 && !csw_in.axisX) { // left clutch fully pressed
          clutch_max = constrain(clutch_max + rotary_value, 0, 0xFF);
        } else {
          whButton(17, rotary_value <= -1); // left
          whButton(18, rotary_value >= 1); // right
        }
        
        // clutch paddle
        switch (csw_in.garbage[2] & 0x0F) {
          case 0x01:
            // bite point
            whDoubleClutch(~csw_in.axisX, ~csw_in.axisY);
            break;
          case 0x02:
            // bite point advanced
            whDoubleClutch(map(~csw_in.axisX & 0xFF,0,0xFF,0,clutch_max) , ~csw_in.axisY&0xff);
            break;
          default:
            whDoubleAxis(~csw_in.axisX, ~csw_in.axisY);
        }
        
        //whButton(11, mcl_in.buttons[2] & 0x20); // display button
        
        whButton(21, ((csw_in.garbage[3] & 0x0f) == 0x01) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(22, ((csw_in.garbage[3] & 0x0f) == 0x02) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(23, ((csw_in.garbage[3] & 0x0f) == 0x03) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(24, ((csw_in.garbage[3] & 0x0f) == 0x04) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(25, ((csw_in.garbage[3] & 0x0f) == 0x05) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(26, ((csw_in.garbage[3] & 0x0f) == 0x06) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(27, ((csw_in.garbage[3] & 0x0f) == 0x07) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(28, ((csw_in.garbage[3] & 0x0f) == 0x08) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(29, ((csw_in.garbage[3] & 0x0f) == 0x09) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(30, ((csw_in.garbage[3] & 0x0f) == 0x0A) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(31, ((csw_in.garbage[3] & 0x0f) == 0x0B) && !((csw_in.buttons[2] & 0x20) == 0x20));
        whButton(32, ((csw_in.garbage[3] & 0x0f) == 0x0C) && !((csw_in.buttons[2] & 0x20) == 0x20));
        
        whStick(0, 0);
      }
      break;
    case CSL_WHEEL:
      // csl stuff
      transferCslData(&csl_out, &csl_in, sizeof(csl_out.raw), 0x00);
      whSetId(CSLP1XBOX);
      
      init_wheel();
      
      // fJoystick / 1st disp
      csl_out.disp = csw7segToCsl(csw_out.disp[0]);
      transferCslData(&csl_out, &csl_in, sizeof(csl_out.raw), 0x41);
      
      whHat(csl_in.buttons & 0x1E, true);
      whButton(13, csl_in.buttons & 0x01); // hat button
      
      // Right Line / 2st disp
      csl_out.disp = csw7segToCsl(csw_out.disp[1]);
      transferCslData(&csl_out, &csl_in, sizeof(csl_out.raw), 0x02);
      
      whButton(11, csl_in.buttons & 0x01); // wrench
      whButton(5, csl_in.buttons & 0x04); // RT
      whButton(14, csl_in.buttons & 0x08); // xbox
      whButton(6, csl_in.buttons & 0x10); // RSB
      
      // Left cluster / 3st disp
      csl_out.disp = csw7segToCsl(csw_out.disp[2]);
      transferCslData(&csl_out, &csl_in, sizeof(csl_out.raw), 0x44);
      
      whButton(15, csl_in.buttons & 0x01); // left paddle
      whButton(9, csl_in.buttons & 0x02); // lines
      whButton(10, csl_in.buttons & 0x04); // squares
      whButton(8, csl_in.buttons & 0x08); // LSB
      whButton(7, csl_in.buttons & 0x10); // LT
      
      // Right cluster / RGB Led
      csl_out.disp = cswLedsToCsl(csw_out.leds);
      transferCslData(&csl_out, &csl_in, sizeof(csl_out.raw), 0x08);
      
      whButton(16, csl_in.buttons & 0x01); // right paddle
      whButton(1, csl_in.buttons & 0x02); // B
      whButton(2, csl_in.buttons & 0x04); // A
      whButton(3, csl_in.buttons & 0x08); // Y
      whButton(4, csl_in.buttons & 0x10); // X
      
      whStick(0, 0);
      
      break;
    case MCL_WHEEL:
      // McLaren GT3
      transferMclData(&mcl_out, &mcl_in, sizeof(mcl_out.raw));
      
      init_wheel();
      
      // Wheel ID
      whSetId(mcl_in.id);
      
      whHat(mcl_in.buttons[0] & 0x0f, false);
      
      // All buttons
      whButton(1, mcl_in.buttons[0] & 0x80); // Y
      whButton(2, mcl_in.buttons[0] & 0x40); // B
      whButton(3, mcl_in.buttons[0] & 0x20); // X
      whButton(4, mcl_in.buttons[0] & 0x10); // A
      whButton(5, mcl_in.buttons[1] & 0x80); // P
      whButton(6, mcl_in.buttons[1] & 0x40); // N
      whButton(7, mcl_in.buttons[1] & 0x20); // LSB
      
      whButton(9, mcl_in.buttons[1] & 0x04); // RSB
      
      whButton(8, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x10)); // switch left up
      whButton(19, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x10)); // switch left down
      whButton(10, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x10)); // switch right up
      whButton(20, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x10)); // switch right down
      
      whButton(33, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x20)); // switch left up
      whButton(34, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x20)); // switch left down
      whButton(35, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x20)); // switch right up
      whButton(36, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x20)); // switch right down
      
      whButton(37, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x30)); // switch left up
      whButton(38, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x30)); // switch left down
      whButton(39, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x30)); // switch right up
      whButton(40, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x30)); // switch right down
      
      whButton(41, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x40)); // switch left up
      whButton(42, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x40)); // switch left down
      whButton(43, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x40)); // switch right up
      whButton(44, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x40)); // switch right down
      
      whButton(45, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x50)); // switch left up
      whButton(46, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x50)); // switch left down
      whButton(47, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x50)); // switch right up
      whButton(48, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x50)); // switch right down
      
      whButton(49, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x60)); // switch left up
      whButton(50, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x60)); // switch left down
      whButton(51, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x60)); // switch right up
      whButton(52, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x60)); // switch right down
      
      whButton(53, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x70)); // switch left up
      whButton(54, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x70)); // switch left down
      whButton(55, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x70)); // switch right up
      whButton(56, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x70)); // switch right down
      
      whButton(57, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x80)); // switch left up
      whButton(58, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x80)); // switch left down
      whButton(59, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x80)); // switch right up
      whButton(60, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x80)); // switch right down
      
      whButton(61, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0x90)); // switch left up
      whButton(62, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0x90)); // switch left down
      whButton(63, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0x90)); // switch right up
      whButton(64, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0x90)); // switch right down
      
      whButton(65, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0xA0)); // switch left up
      whButton(66, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0xA0)); // switch left down
      whButton(67, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0xA0)); // switch right up
      whButton(68, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0xA0)); // switch right down
      
      whButton(69, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0xB0)); // switch left up
      whButton(70, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0xB0)); // switch left down
      whButton(71, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0xB0)); // switch right up
      whButton(72, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0xB0)); // switch right down
      
      whButton(73, (mcl_in.buttons[1] & 0x10) && ((mcl_in.garbage[3] & 0xF0) == 0xC0)); // switch left up
      whButton(74, (mcl_in.buttons[2] & 0x80) && ((mcl_in.garbage[3] & 0xF0) == 0xC0)); // switch left down
      whButton(75, (mcl_in.buttons[1] & 0x02) && ((mcl_in.garbage[3] & 0xF0) == 0xC0)); // switch right up
      whButton(76, (mcl_in.buttons[2] & 0x40) && ((mcl_in.garbage[3] & 0xF0) == 0xC0)); // switch right down
      
      whButton(12, mcl_in.buttons[2] & 0x04); // hat button
      whButton(14, mcl_in.buttons[2] & 0x02); // xbox
      
      // paddles shitfer
      whButton(15, mcl_in.buttons[1] & 0x08); // left
      whButton(16, mcl_in.buttons[1] & 0x01); // right
      
      rotary_value = mcl_in.encoder;
      
      if ((mcl_in.garbage[2] & 0x0F) == 0x02 && !mcl_in.axisX) { // left clutch fully pressed
        clutch_max = constrain(clutch_max + rotary_value, 0, 0xFF);
      } else {
        whButton(17, rotary_value <= -1); // left
        whButton(18, rotary_value >= 1); // right
      }
      
      // clutch paddle
      switch (mcl_in.garbage[2] & 0x0F) {
        case 0x01:
          // bite point
          whDoubleClutch(~mcl_in.axisX, ~mcl_in.axisY);
          break;
        case 0x02:
          // bite point advanced
          whDoubleClutch(map(~mcl_in.axisX & 0xFF,0,0xFF,0,clutch_max) , ~mcl_in.axisY&0xff);
          break;
        default:
          whDoubleAxis(~mcl_in.axisX, ~mcl_in.axisY);
      }
      
      //whButton(11, mcl_in.buttons[2] & 0x20); // display button
      
      whButton(21, ((mcl_in.garbage[3] & 0x0f) == 0x01) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(22, ((mcl_in.garbage[3] & 0x0f) == 0x02) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(23, ((mcl_in.garbage[3] & 0x0f) == 0x03) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(24, ((mcl_in.garbage[3] & 0x0f) == 0x04) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(25, ((mcl_in.garbage[3] & 0x0f) == 0x05) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(26, ((mcl_in.garbage[3] & 0x0f) == 0x06) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(27, ((mcl_in.garbage[3] & 0x0f) == 0x07) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(28, ((mcl_in.garbage[3] & 0x0f) == 0x08) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(29, ((mcl_in.garbage[3] & 0x0f) == 0x09) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(30, ((mcl_in.garbage[3] & 0x0f) == 0x0A) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(31, ((mcl_in.garbage[3] & 0x0f) == 0x0B) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      whButton(32, ((mcl_in.garbage[3] & 0x0f) == 0x0C) && !((mcl_in.buttons[2] & 0x20) == 0x20));
      
      whStick(0, 0);
      
      #ifdef HAS_DEBUG
        Serial.print("MCL_IN:");
        for (int i=0; i<sizeof(mcl_in.raw); i++) {
          Serial.print(mcl_in.raw[i], HEX);
          Serial.print(":");
        }
        Serial.println();
      #endif

      break;
    default:
      // no wheel  ?
      whClear();
      delay(10);
  }

  // Send HID report (all inputs)
  uint32_t now = micros();
  if (now >= usb_time) {
    uint32_t delta_t = now - usb_time;
    
    #ifdef HAS_DEBUG
      Serial.println(String("usb loop time : ") + delta_t);
    #endif

    if (delta_t >= MAX_SPEED) {
      // delayMicroseconds(MAX_SPEED - delta_t);
      #ifdef HAS_DEBUG
          Serial.println(String("usb loop time pre send: ") + (micros() - usb_time));
      #endif
          
      fJoystick.send_now();
      
      #ifdef HAS_DEBUG
          Serial.println(String("usb loop time post send: ") + (micros() - usb_time));
      #endif
      
      usb_time = micros();
    } else {
      #ifdef HAS_DEBUG
          Serial.println(String("skipping report"));
      #endif
    }
  }  
  
  // timing = micros() - timing;
  // if(timing > 550)  Serial.println(String("timing: ") + timing);
  // some delay
  idle();
}

void whButton(uint8_t button, bool val) {
  val = btDebncer[button].get(val);
  
  fJoystick.button(button, val);
}

void whStick(unsigned int x, unsigned int y) {
  x = 255 - (x + 127);
  y = y + 127;
  
  fJoystick.X(x);
  fJoystick.Y(y);
}

void whDoubleAxis(unsigned int x, unsigned int y) {
  fJoystick.clutch1(x);
  fJoystick.clutch2(y);
}

void whDoubleClutch(unsigned int x, unsigned int y) {
  if(y > x) x = y;
  
  fJoystick.clutch1(x);
  fJoystick.clutch2(0);
}

void whHat(int8_t val, bool is_csl) {
  val = hatDebncer.get(val);
  
  if (is_csl) { // CSL
    switch (val) {
      case 4: val=0;break;
      case 2: val=2;break;
      case 8: val=4;break;
      case 16: val=6;break;
      default: val=0xFF;
    }
  } else { // CSW
    switch (val) {
      case 1: val=0;break;
      case 2: val=6;break;
      case 4: val=2;break;
      case 8: val=4;break;
      default: val=0xFF;
    }
  }
  
  fJoystick.hat(val);
}

void whSetId(unsigned int val) {
  csw_out.id = val & 0xFF;
  
  fJoystick.setWheel(val);
}

void whClear(){
  whSetId(NO_RIM);
  
  whStick(0, 0);
  whHat(0, false);
  whDoubleAxis(0x00, 0x00);
  
  for (int i = 1; i <= 37; ++i) {
    whButton(i, 0);
  }
  
  clutch_max = 0xFF;
  show_fwvers = true;
  disp_timout = 0;
}

void hid_output(uint8_t link_id, uint16_t data_length, const uint8_t *data) {
  if (data[2] == 0x01 && data[3] == 0x02) {
    // 7 seg
    if (!show_fwvers) {
      if (detectWheelType() == MCL_WHEEL) {
        mcl_out.raw[1] = 0x11;
        mcl_out.raw[2] = csw7segToAscii(data[4] & 0xff);
        mcl_out.raw[3] = csw7segToAscii(data[5] & 0xff);
        mcl_out.raw[4] = csw7segToAscii(data[6] & 0xff);

        #ifdef HAS_DEBUG
          Serial.print(String("HID display: " ));
          Serial.print(data[4], HEX);
          Serial.print(":");
          Serial.print(data[5], HEX);
          Serial.print(":");
          Serial.print(data[6], HEX);
          Serial.println();
        #endif
      } else {
        if (csw_in.id == CSLMCLGT3) {
          csw_out.raw[1] = 0x11;
          csw_out.raw[2] = csw7segToAscii(data[4] & 0xff);
          csw_out.raw[3] = csw7segToAscii(data[5] & 0xff);
          csw_out.raw[4] = csw7segToAscii(data[6] & 0xff);
        } else {
          csw_out.disp[0] = (data[4] & 0xff);
          csw_out.disp[1] = (data[5] & 0xff);
          csw_out.disp[2] = (data[6] & 0xff);
        }
        
        #ifdef HAS_DEBUG
          Serial.println(String("HID display: " )+ csw_out.disp[0]+":"+csw_out.disp[1]+":"+csw_out.disp[2]);
        #endif
      }
    }
  } else if(data[2] == 0x01 && data[3] == 0x03) {
    // rumbles
    if (csw_out.id != UNIHUB && csw_in.id != CSLMCLGT3) {
      csw_out.rumble[0] = (data[4] & 0xff);
      csw_out.rumble[1] = (data[5] & 0xff);
    }
    
    #ifdef HAS_DEBUG
      Serial.println(String("HID rumbles: " )+ csw_out.rumble[0]+":"+csw_out.rumble[1]);
    #endif
  } else if(data[2] == 0x08) {
    // Rev Lights
    if (csw_out.id != UNIHUB && csw_in.id != CSLMCLGT3){
      csw_out.leds = (data[3] & 0xff) << 8 | (data[4] & 0xff);
      // ftx_pck[5] = (hid_pck[4] & 0xff);
      // ftx_pck[6] = (hid_pck[3] & 0xff);
    }
    
    #ifdef HAS_DEBUG
      Serial.println(String("HID leds   : " )+ csw_out.leds);
    #endif
  } else if(data[1] == 0x14) {
      // ??
  } else {
    #ifdef HAS_DEBUG
      Serial.print(String("[!] HID Unknown from " )+ link_id + " (size:" + data_length + ") : ");
      
      for (int i=0; i<data_length; i++) {
        Serial.print(data[i], HEX);
        Serial.print(":");
      }
      Serial.println();
    #endif
    
  }
  
  timing_bt = millis();
}


void init_wheel() {
  if (show_fwvers) {
    if (disp_timout == 0) {
      // start showing fw vers
      if (detectWheelType() == MCL_WHEEL) {
        String fw_vers = String(mcl_in.fwvers);
        
        mcl_out.raw[1] = 0x11;
        // Erase all
        mcl_out.raw[2] = 0x0A;
        mcl_out.raw[3] = 0x0A;
        mcl_out.raw[4] = 0x0A;
        //
        mcl_out.raw[2] = fw_vers.charAt(0);
        
        if (fw_vers.length()>1) {
          mcl_out.raw[3] = fw_vers.charAt(1);
        }
          
        if (fw_vers.length()>2) {
          mcl_out.raw[4] = fw_vers.charAt(2);
        }
      } else {
        String fw_vers = String(csw_in.fwvers);
        
        if (csw_in.id == CSLMCLGT3) {
          csw_out.raw[1] = 0x11;
          // Erase all
          csw_out.raw[2] = 0x0A;
          csw_out.raw[3] = 0x0A;
          csw_out.raw[4] = 0x0A;
          //
          csw_out.raw[2] = fw_vers.charAt(0);
          
          if (fw_vers.length()>1) {
            csw_out.raw[3] = fw_vers.charAt(1);
          }
          
          if (fw_vers.length()>2) {
            csw_out.raw[4] = fw_vers.charAt(2);
          }
        } else {
          // TODO: AsciiTo7seg conversion
          csw_out.disp[0] = 0x00;
          csw_out.disp[1] = 0x00;
          csw_out.disp[2] = 0x00;
        }
      }
      
      disp_timout = millis();
    } else if(millis() - disp_timout >= 4000) {
      // stop
      show_fwvers = false;
      
      mcl_out.raw[1] = 0x11;
      mcl_out.raw[2] = 0x0A;
      mcl_out.raw[3] = 0x0A;
      mcl_out.raw[4] = 0x0A;
      mcl_out.raw[9] = 0x00;
      
      if (csw_in.id == CSLMCLGT3) {
        csw_out.raw[1] = 0x11;
        csw_out.raw[2] = 0x0A;
        csw_out.raw[3] = 0x0A;
        csw_out.raw[4] = 0x0A;
      }
    }
  } else {
    // xbox light
    //    mcl_out.raw[1] = 0x00;
    //    mcl_out.raw[9] = 0x0F;
  }

}

void idle() {
  delay(1);
}
 
That probably isn't your whole program. I can see from the error message you also have a file "fanatec_joystick.c".

From the errors, my guess is someone created that file by copying portions of the USB code from the core library meant for Teensy 3.x & LC.
 
sounds correct, i have other files as well yes.
Do you want me to paste each in here? or would it be easier to check the github link?

here is fanatec_joystic.c the problem file
Code:
/*
 *
 * Project: https://github.com/dchote/fanatecWheelUSB
 * Author: Daniel Chote
 *
 * Modified from the Teensyduino Core Library and pulling in darknao's changes
 * http://www.pjrc.com/teensy/
 * Copyright (c) 2013 PJRC.COM, LLC.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * 1. The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * 2. If the Software is incorporated into a build system that allows
 * selection among a list of target devices, then similar target
 * devices manufactured by PJRC.COM must be included in the list of
 * target devices and selectable in the same manner.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */


#include "usb_dev.h"
#include "fanatec_joystick.h"
#include "core_pins.h" // for yield()
#include "HardwareSerial.h"
#include <string.h> // for memcpy()

uint8_t fanatec_joystick_data[32];

// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
#define TX_PACKET_LIMIT 3

static uint8_t transmit_previous_timeout = 0;

// When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 30

#if F_CPU == 168000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1100)
#elif F_CPU == 144000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 932)
#elif F_CPU == 120000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 764)
#elif F_CPU == 96000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
#elif F_CPU == 72000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512)
#elif F_CPU == 48000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
#elif F_CPU == 24000000
  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
#endif



int fanatec_joystick_send(void)
{
  uint32_t wait_count = 0;
  usb_packet_t *tx_packet;

  //serial_print("send");
  //serial_print("\n");
  while (1) {
    if (!usb_configuration) {
      //serial_print("error1\n");
      return -1;
    }
  
    if (usb_tx_packet_count(JOYSTICK_ENDPOINT) < TX_PACKET_LIMIT) {
      tx_packet = usb_malloc();
      if (tx_packet) break;
    }
    
    if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
      transmit_previous_timeout = 1;
      //serial_print("error2\n");
      return -1;
    }
    yield();
  }
  
  transmit_previous_timeout = 0;
  
  memcpy(tx_packet->buf, fanatec_joystick_data, JOYSTICK_SIZE);
  tx_packet->len = JOYSTICK_SIZE;
  
  usb_tx(JOYSTICK_ENDPOINT, tx_packet);
  //serial_print("ok\n");
  return 0;
}

int fanatec_lights_recv(void *buffer, uint32_t timeout) 
{
  usb_packet_t *rx_packet;
  uint32_t begin = millis();

  while (1) {
    if (!usb_configuration) {
      return -1;
    } 
  
    rx_packet = usb_rx(LIGHTS_ENDPOINT);
    
    if (rx_packet) break;
    if (millis() - begin > timeout || !timeout) return 0;
    
    yield();
  }

  memcpy(buffer, rx_packet->buf, LIGHTS_SIZE);
  usb_free(rx_packet);

  return LIGHTS_SIZE;
}

int fanatec_lights_available(void)
{
  uint32_t count;
  
  if (!usb_configuration) {
    return 0;
  } 
  
  count = usb_rx_byte_count(LIGHTS_ENDPOINT);
  
  return count;
}
 
Back
Top