Jariullah Safi пре 4 месеци
родитељ
комит
44d4871642
1 измењених фајлова са 15 додато и 7 уклоњено
  1. 15 7
      OpenPuck/mode_switch_pro.cpp

+ 15 - 7
OpenPuck/mode_switch_pro.cpp

@@ -113,16 +113,24 @@ static void switchProBuild(uint8_t out[63]){
   memset(out,0,63);
   jcInputPrefix(out);
   // Gyro slot order follows hid-nintendo: raw+6 = ROLL, raw+8 = PITCH, raw+10 = YAW. Steam-validated source
-  // routing: roll<-gy, pitch<--gx (inverted), yaw<-gz.
+  // routing (a proper rotation, det +1): SwitchX<-+gy, SwitchY<--gx, SwitchZ<-+gz.
+  //
+  // CRITICAL: the accel MUST use the SAME signed permutation as the gyro. Steam reads the gyro raw and ignores
+  // this, but the Switch console FUSES accel (gravity) with gyro to anchor absolute orientation -- and if the
+  // accel frame has the opposite handedness, the fusion's gravity-correction term points the wrong way and the
+  // attitude estimate latches into a rotated solution (the intermittent ~45deg axis-mixing, per-unit roll bias,
+  // and "only a replug clears it" behaviour). So accel Y must be -ax to match the gyro's -gx pitch axis; with
+  // that, accel is also det +1 and resting gravity lands cleanly on Switch Z (the up axis).
   int16_t gpitch=(int16_t)(-(int16_t)g_in.gx);
+  int16_t aY=(int16_t)(-(int16_t)g_in.ax);
   for(int k=0;k<3;k++){
     int o=12+k*12;
-    out[o+0]=g_in.ay&0xFF;  out[o+1]=g_in.ay>>8;    // accel X <- g_in.ay
-    out[o+2]=g_in.ax&0xFF;  out[o+3]=g_in.ax>>8;    // accel Y <- g_in.ax
-    out[o+4]=g_in.az&0xFF;  out[o+5]=g_in.az>>8;    // accel Z
-    out[o+6]=g_in.gy&0xFF;  out[o+7]=g_in.gy>>8;       // gyro ROLL  <- g_in.gy
-    out[o+8]=gpitch&0xFF;   out[o+9]=(gpitch>>8)&0xFF;  // gyro PITCH <- -g_in.gx (inverted vs Switch frame)
-    out[o+10]=g_in.gz&0xFF; out[o+11]=g_in.gz>>8;      // gyro YAW   <- g_in.gz
+    out[o+0]=g_in.ay&0xFF;  out[o+1]=g_in.ay>>8;       // accel X (Switch) <- +g_in.ay   (matches gyro +gy)
+    out[o+2]=aY&0xFF;       out[o+3]=(aY>>8)&0xFF;      // accel Y (Switch) <- -g_in.ax   (matches gyro -gx)
+    out[o+4]=g_in.az&0xFF;  out[o+5]=g_in.az>>8;        // accel Z (Switch) <- +g_in.az   (matches gyro +gz)
+    out[o+6]=g_in.gy&0xFF;  out[o+7]=g_in.gy>>8;        // gyro ROLL  <- +g_in.gy
+    out[o+8]=gpitch&0xFF;   out[o+9]=(gpitch>>8)&0xFF;  // gyro PITCH <- -g_in.gx
+    out[o+10]=g_in.gz&0xFF; out[o+11]=g_in.gz>>8;       // gyro YAW   <- +g_in.gz
   }
 }
 // --- Canonical factory SPI dumps the host reads for calibration. Neutral IMU + centered sticks so a fresh