Cleric-K / vJoySerialFeeder

Feed Virtual Joystick driver with data from a serial port
GNU General Public License v3.0
252 stars 55 forks source link

IBUS failure to read with Native USB (U-series) Arduino variants (Leonardo and similar) #45

Closed Hyratel closed 2 years ago

Hyratel commented 3 years ago

I just tested the following boards:

Failed: Arduino Leonardo (32u4) Failed: Chinaclone Pro Micro (32u4) Success: Arduino Uno (328p with 16u2-based serial bridge) Success: Arduino Duemilanovae (328p with FTDI Serial Bridge Chip) Success: Cypress PSoC (4200-family with Cypress Cy7C Serial Bridge Chip) (<- this one was an adventure: I had to re-implement the IBUS protocol library because it's only C not C++)

All devices showed the same output via serial monitor @ 115200 baud

the test code for Arduino:

#include <ibus.h>

const int NUM_CHANNELS = 3;

IBus ibus(NUM_CHANNELS);

const int16_t axisX = A0;
const int16_t axisY = A1;
const int numAxs = 2;
const int numBtn = 4;
const int numHat = 1;

const int sampavgsize = 10;
int16_t axisXsens[sampavgsize];
int16_t axisYsens[sampavgsize];
int16_t axisXsensAvg;
int16_t axisYsensAvg;

int btnTrg = 4;
int btnThm = 2;
int btnLft = 5;
int btnRgt = 3;

// hat switch direct buttons
int btnNorth = 6, btnEast = 7, btnSouth = 8, btnWest = 9;

int btnsPin[numBtn] = {btnTrg, btnThm, btnLft, btnRgt};
int btns[numBtn];
int hatPin[4] = {btnNorth, btnEast, btnSouth, btnWest};

int lastButtonState[4] = {0, 0, 0, 0};

void setup() {
  // put your setup code here, to run once:
  //digitalWrite(btnTrg, LOW);
  for (int i = 0; i < 4; i++)
    pinMode(btnsPin[i], INPUT_PULLUP);
  for (int i = 0; i < 4; i++)
    pinMode(hatPin[i], INPUT_PULLUP);

  pinMode(axisX, INPUT);
  pinMode(axisY, INPUT);
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  uint16_t currentButtonState = 0x00;

  do {
    int axisXsensSum = 0;
    int axisYsensSum = 0;

    for (int i = 0; i < sampavgsize; i++)
    {
      axisXsens[i] = analogRead(axisX);
      axisYsens[i] = analogRead(axisY);
    }
    for (int j = 0; j < sampavgsize; j++)
    {
      axisXsensSum += axisXsens[j];
      axisYsensSum += axisYsens[j];
    }
    axisXsensAvg = axisXsensSum / sampavgsize;
    axisYsensAvg = axisYsensSum / sampavgsize;
  } while (0);

  //  Serial.print(axisHsens);
  //  Serial.print("\t");

  for (int index = 0; index < 4; index++)
  {
    if ( !digitalRead(btnsPin[index]))
      currentButtonState |= 0x01 << index + 4; // buttons to second nibble, hat to first/low nibble
  }

  // currentButtonState &= 0xFFF0; //clear low nibble(redundant)
  for (int hatTest = 0; hatTest < 4; hatTest++)
  {
    if (!digitalRead(hatPin[hatTest]))
      currentButtonState |= 0x01 << hatTest;

  }
  ibus.begin();
  ibus.write((uint16_t)(1023 - axisXsensAvg));
  ibus.write((uint16_t)(1023 - axisYsensAvg));
  ibus.write(currentButtonState);
  ibus.end();
}
Cleric-K commented 3 years ago

I have no clue at this point. Think I have a pro micro lying around so I'll try to replicate at first opportunity.

Hyratel commented 3 years ago

my best guess is there's a timing issue causing the UART stream to get segmented so VSJF only gets half a frame before forgetting what it was doing so it's only seeing invalid partial frames? it's Weird, especially because the Uno with its 16u2 chip works fine