Implement the rest of the wiimote input reports.
This commit is contained in:
parent
10c2101e72
commit
0b4329e077
|
@ -63,7 +63,7 @@ union wm_buttons // also just called "core data"
|
|||
u8 down : 1;
|
||||
u8 up : 1;
|
||||
u8 plus : 1;
|
||||
u8 acc_x_lsb : 2; // LSB of accelerometer (10 bits in total)
|
||||
u8 acc_bits : 2;
|
||||
u8 unknown : 1;
|
||||
|
||||
u8 two : 1;
|
||||
|
@ -71,8 +71,7 @@ union wm_buttons // also just called "core data"
|
|||
u8 b : 1;
|
||||
u8 a : 1;
|
||||
u8 minus : 1;
|
||||
u8 acc_y_lsb : 1; // LSB of accelerometer (9 bits in total)
|
||||
u8 acc_z_lsb : 1; // LSB of accelerometer (9 bits in total)
|
||||
u8 acc_bits2 : 2;
|
||||
u8 home : 1;
|
||||
};
|
||||
};
|
||||
|
@ -109,6 +108,23 @@ struct wm_ir_extended
|
|||
};
|
||||
static_assert(sizeof(wm_ir_extended) == 3, "Wrong size");
|
||||
|
||||
// Nine bytes for one object
|
||||
// first 3 bytes are the same as extended
|
||||
struct wm_ir_full : wm_ir_extended
|
||||
{
|
||||
u8 xmin : 7;
|
||||
u8 : 1;
|
||||
u8 ymin : 7;
|
||||
u8 : 1;
|
||||
u8 xmax : 7;
|
||||
u8 : 1;
|
||||
u8 ymax : 7;
|
||||
u8 : 1;
|
||||
u8 zero;
|
||||
u8 intensity;
|
||||
};
|
||||
static_assert(sizeof(wm_ir_full) == 9, "Wrong size");
|
||||
|
||||
// Nunchuk
|
||||
union wm_nc_core
|
||||
{
|
||||
|
|
|
@ -46,10 +46,6 @@ void Wiimote::ReportMode(const wm_report_mode* const dr)
|
|||
WARN_LOG(WIIMOTE, "Game requested invalid report mode: 0x%02x", dr->mode);
|
||||
return;
|
||||
}
|
||||
else if (dr->mode > RT_REPORT_CORE_ACCEL_IR10_EXT6)
|
||||
{
|
||||
PanicAlert("Wiimote: Unsupported Reporting mode: 0x%02x", dr->mode);
|
||||
}
|
||||
|
||||
// TODO: A real wiimote sends a report immediately.
|
||||
// even on REPORT_CORE and continuous off when the buttons haven't changed.
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
#include <mutex>
|
||||
#include <numeric>
|
||||
|
||||
#include "Common/BitUtils.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Config/Config.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/BitUtils.h"
|
||||
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/Config/WiimoteInputSettings.h"
|
||||
|
@ -101,11 +101,16 @@ static const ReportFeatures reporting_mode_features[] = {
|
|||
{2, 0, 10, 9, 23},
|
||||
// 0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes
|
||||
{2, 3, 10, 6, 23},
|
||||
// UNSUPPORTED (but should be easy enough to implement):
|
||||
// Ugly padding members so 0x3d,3e,3f are properly placed in the array:
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
// 0x3d: 21 Extension Bytes
|
||||
{0, 0, 0, 21, 23},
|
||||
// 0x3e / 0x3f: Interleaved Core Buttons and Accelerometer with 36 IR bytes
|
||||
{0, 0, 0, 0, 23},
|
||||
{2, 1, 0, 18, 23},
|
||||
};
|
||||
|
||||
// Used for extension calibration data:
|
||||
|
@ -335,10 +340,10 @@ void Wiimote::Reset()
|
|||
memcpy(&m_motion_plus_logic.reg_data.ext_identifier, motion_plus_id, sizeof(motion_plus_id));
|
||||
|
||||
// calibration hackery
|
||||
static const u8 c1[16] = {0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c, 0xcf, 0xf0, 0x31, 0xad,
|
||||
0xc8, 0x0b, 0x5e, 0x39};
|
||||
static const u8 c2[16] = {0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51, 0x33, 0x60, 0xc9, 0xf5, 0x37, 0xc1,
|
||||
0x2d, 0xe9, 0x15, 0x8d};
|
||||
static const u8 c1[16] = {0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c,
|
||||
0xcf, 0xf0, 0x31, 0xad, 0xc8, 0x0b, 0x5e, 0x39};
|
||||
static const u8 c2[16] = {0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51, 0x33, 0x60,
|
||||
0xc9, 0xf5, 0x37, 0xc1, 0x2d, 0xe9, 0x15, 0x8d};
|
||||
|
||||
// std::copy(std::begin(c1), std::end(c1), m_motion_plus_logic.reg_data.calibration_data);
|
||||
// std::copy(std::begin(c2), std::end(c2), m_motion_plus_logic.reg_data.calibration_data + 0x10);
|
||||
|
@ -610,7 +615,8 @@ void Wiimote::GetButtonData(u8* const data)
|
|||
reinterpret_cast<wm_buttons*>(data)->hex |= m_status.buttons.hex;
|
||||
}
|
||||
|
||||
void Wiimote::GetAccelData(u8* const data)
|
||||
// Produces 10-bit precision values.
|
||||
void Wiimote::GetAccelData(s16* x, s16* y, s16* z)
|
||||
{
|
||||
const bool sideways_modifier_toggle = m_hotkeys->getSettingsModifier()[0];
|
||||
const bool upright_modifier_toggle = m_hotkeys->getSettingsModifier()[1];
|
||||
|
@ -661,26 +667,14 @@ void Wiimote::GetAccelData(u8* const data)
|
|||
EmulateDynamicShake(&m_accel, m_shake_dynamic_data, m_shake_dynamic, shake_config,
|
||||
m_shake_dynamic_step.data());
|
||||
|
||||
// TODO: kill these ugly looking offsets
|
||||
wm_accel& accel = *reinterpret_cast<wm_accel*>(data + 4);
|
||||
wm_buttons& core = *reinterpret_cast<wm_buttons*>(data + 2);
|
||||
|
||||
// We now use 2 bits more precision, so multiply by 4 before converting to int
|
||||
s16 x = (s16)(4 * (m_accel.x * ACCEL_RANGE + ACCEL_ZERO_G));
|
||||
s16 y = (s16)(4 * (m_accel.y * ACCEL_RANGE + ACCEL_ZERO_G));
|
||||
s16 z = (s16)(4 * (m_accel.z * ACCEL_RANGE + ACCEL_ZERO_G));
|
||||
*x = (s16)(4 * (m_accel.x * ACCEL_RANGE + ACCEL_ZERO_G));
|
||||
*y = (s16)(4 * (m_accel.y * ACCEL_RANGE + ACCEL_ZERO_G));
|
||||
*z = (s16)(4 * (m_accel.z * ACCEL_RANGE + ACCEL_ZERO_G));
|
||||
|
||||
x = MathUtil::Clamp<s16>(x, 0, 0x3ff);
|
||||
y = MathUtil::Clamp<s16>(y, 0, 0x3ff);
|
||||
z = MathUtil::Clamp<s16>(z, 0, 0x3ff);
|
||||
|
||||
accel.x = (x >> 2) & 0xFF;
|
||||
accel.y = (y >> 2) & 0xFF;
|
||||
accel.z = (z >> 2) & 0xFF;
|
||||
|
||||
core.acc_x_lsb = x & 0x3;
|
||||
core.acc_y_lsb = (y >> 1) & 0x1;
|
||||
core.acc_z_lsb = (z >> 1) & 0x1;
|
||||
*x = MathUtil::Clamp<s16>(*x, 0, 0x3ff);
|
||||
*y = MathUtil::Clamp<s16>(*y, 0, 0x3ff);
|
||||
*z = MathUtil::Clamp<s16>(*z, 0, 0x3ff);
|
||||
}
|
||||
|
||||
inline void LowPassFilter(double& var, double newval, double period)
|
||||
|
@ -694,9 +688,6 @@ inline void LowPassFilter(double& var, double newval, double period)
|
|||
|
||||
void Wiimote::UpdateIRData(bool use_accel)
|
||||
{
|
||||
// IR data is stored at offset 0x37
|
||||
u8* const data = m_camera_logic.reg_data.camera_data;
|
||||
|
||||
u16 x[4], y[4];
|
||||
memset(x, 0xFF, sizeof(x));
|
||||
|
||||
|
@ -781,15 +772,20 @@ void Wiimote::UpdateIRData(bool use_accel)
|
|||
y[i] = static_cast<u16>(lround((v[i].y + 1) / 2 * (camHeight - 1)));
|
||||
}
|
||||
|
||||
// IR data is read from offset 0x37 on real hardware
|
||||
u8* const data = m_camera_logic.reg_data.camera_data;
|
||||
// A maximum of 36 bytes.
|
||||
std::fill_n(data, sizeof(wm_ir_full) * 4, 0xff);
|
||||
|
||||
// Fill report with valid data when full handshake was done
|
||||
if (m_camera_logic.reg_data.data[0x30])
|
||||
{
|
||||
// ir mode
|
||||
switch (m_camera_logic.reg_data.mode)
|
||||
{
|
||||
// basic
|
||||
case 1:
|
||||
{
|
||||
memset(data, 0xFF, 10);
|
||||
wm_ir_basic* const irdata = reinterpret_cast<wm_ir_basic*>(data);
|
||||
for (unsigned int i = 0; i < 2; ++i)
|
||||
{
|
||||
|
@ -810,12 +806,11 @@ void Wiimote::UpdateIRData(bool use_accel)
|
|||
irdata[i].y2hi = y[i * 2 + 1] >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// extended
|
||||
case 3:
|
||||
{
|
||||
memset(data, 0xFF, 12);
|
||||
wm_ir_extended* const irdata = reinterpret_cast<wm_ir_extended*>(data);
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
if (x[i] < 1024 && y[i] < 768)
|
||||
|
@ -828,14 +823,39 @@ void Wiimote::UpdateIRData(bool use_accel)
|
|||
|
||||
irdata[i].size = 10;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// full
|
||||
case 5:
|
||||
PanicAlert("Full IR report");
|
||||
// UNSUPPORTED
|
||||
{
|
||||
wm_ir_full* const irdata = reinterpret_cast<wm_ir_full*>(data);
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
if (x[i] < 1024 && y[i] < 768)
|
||||
{
|
||||
irdata[i].x = static_cast<u8>(x[i]);
|
||||
irdata[i].xhi = x[i] >> 8;
|
||||
|
||||
irdata[i].y = static_cast<u8>(y[i]);
|
||||
irdata[i].yhi = y[i] >> 8;
|
||||
|
||||
irdata[i].size = 10;
|
||||
|
||||
// TODO: implement these sensibly:
|
||||
// TODO: do high bits of x/y min/max need to be set to zero?
|
||||
irdata[i].xmin = 0;
|
||||
irdata[i].ymin = 0;
|
||||
irdata[i].xmax = 0;
|
||||
irdata[i].ymax = 0;
|
||||
irdata[i].zero = 0;
|
||||
irdata[i].intensity = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARN_LOG(WIIMOTE, "Game is requesting IR data before setting IR mode.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wiimote::Update()
|
||||
|
@ -863,13 +883,21 @@ void Wiimote::Update()
|
|||
return;
|
||||
}
|
||||
|
||||
if (RT_REPORT_CORE == m_reporting_mode && !m_reporting_auto)
|
||||
{
|
||||
// TODO: we only need to send a report if the data changed when reporting_auto is disabled
|
||||
// probably only sensible to check this with RT_REPORT_CORE
|
||||
// and just always send a report with the other modes
|
||||
// return;
|
||||
}
|
||||
|
||||
const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - RT_REPORT_CORE];
|
||||
s8 rptf_size = rptf.total_size;
|
||||
if (Movie::IsPlayingInput() &&
|
||||
Movie::PlayWiimote(m_index, data, rptf, m_extension->active_extension, m_ext_logic.ext_key))
|
||||
{
|
||||
if (rptf.core_size)
|
||||
m_status.buttons = *reinterpret_cast<wm_buttons*>(data + 2);
|
||||
m_status.buttons = *reinterpret_cast<wm_buttons*>(data + rptf.GetCoreOffset());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -881,8 +909,7 @@ void Wiimote::Update()
|
|||
// hotkey/settings modifier
|
||||
m_hotkeys->GetState(); // data is later accessed in UpdateButtonsStatus and GetAccelData
|
||||
|
||||
// Data starts at byte 2 in the report
|
||||
u8* feature_ptr = data + 2;
|
||||
u8* feature_ptr = data + rptf.GetCoreOffset();
|
||||
|
||||
// core buttons
|
||||
if (rptf.core_size)
|
||||
|
@ -895,7 +922,38 @@ void Wiimote::Update()
|
|||
if (rptf.accel_size)
|
||||
{
|
||||
// TODO: GetAccelData has hardcoded payload offsets..
|
||||
GetAccelData(data);
|
||||
s16 x, y, z;
|
||||
GetAccelData(&x, &y, &z);
|
||||
|
||||
auto& core = *reinterpret_cast<wm_buttons*>(data + rptf.GetCoreOffset());
|
||||
|
||||
// Special cases for the interleaved reports:
|
||||
// only 8 bits of precision.
|
||||
if (RT_REPORT_INTERLEAVE1 == m_reporting_mode)
|
||||
{
|
||||
*feature_ptr = (x >> 2) & 0xff;
|
||||
core.acc_bits = (z >> 4) & 0b11;
|
||||
core.acc_bits2 = (z >> 6) & 0b11;
|
||||
}
|
||||
if (RT_REPORT_INTERLEAVE2 == m_reporting_mode)
|
||||
{
|
||||
*feature_ptr = (y >> 2) & 0xff;
|
||||
core.acc_bits = (z >> 0) & 0b11;
|
||||
core.acc_bits2 = (z >> 2) & 0b11;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& accel = *reinterpret_cast<wm_accel*>(feature_ptr);
|
||||
accel.x = (x >> 2) & 0xFF;
|
||||
accel.y = (y >> 2) & 0xFF;
|
||||
accel.z = (z >> 2) & 0xFF;
|
||||
|
||||
// Set the LSBs
|
||||
core.acc_bits = x & 0b11;
|
||||
core.acc_bits2 = (y >> 1) & 0x1;
|
||||
core.acc_bits2 |= ((z >> 1) & 0x1) << 1;
|
||||
}
|
||||
|
||||
feature_ptr += rptf.accel_size;
|
||||
}
|
||||
|
||||
|
@ -909,8 +967,16 @@ void Wiimote::Update()
|
|||
if (!m_status.ir)
|
||||
WARN_LOG(WIIMOTE, "Game is reading IR data without enabling IR logic first.");
|
||||
|
||||
m_i2c_bus.BusRead(IRCameraLogic::DEVICE_ADDR, offsetof(IRCameraLogic::RegData, camera_data),
|
||||
rptf.ir_size, feature_ptr);
|
||||
u8 camera_data_offset = offsetof(IRCameraLogic::RegData, camera_data);
|
||||
|
||||
if (RT_REPORT_INTERLEAVE2 == m_reporting_mode)
|
||||
{
|
||||
// Interleave2 reads the 2nd half of the "FULL" IR data
|
||||
camera_data_offset += sizeof(wm_ir_full) * 2;
|
||||
}
|
||||
|
||||
m_i2c_bus.BusRead(IRCameraLogic::DEVICE_ADDR, camera_data_offset, rptf.ir_size, feature_ptr);
|
||||
|
||||
feature_ptr += rptf.ir_size;
|
||||
}
|
||||
|
||||
|
@ -944,15 +1010,17 @@ void Wiimote::Update()
|
|||
Movie::CheckWiimoteStatus(m_index, data, rptf, m_extension->active_extension,
|
||||
m_ext_logic.ext_key);
|
||||
|
||||
// don't send a data report if auto reporting is off
|
||||
if (false == m_reporting_auto && data[1] >= RT_REPORT_CORE)
|
||||
return;
|
||||
|
||||
// send data report
|
||||
if (rptf_size)
|
||||
{
|
||||
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, data, rptf_size);
|
||||
}
|
||||
|
||||
// The interleaved reporting modes toggle back and forth:
|
||||
if (RT_REPORT_INTERLEAVE1 == m_reporting_mode)
|
||||
m_reporting_mode = RT_REPORT_INTERLEAVE2;
|
||||
else if (RT_REPORT_INTERLEAVE2 == m_reporting_mode)
|
||||
m_reporting_mode = RT_REPORT_INTERLEAVE1;
|
||||
}
|
||||
|
||||
void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size)
|
||||
|
@ -1213,9 +1281,9 @@ void Wiimote::MotionPlusLogic::Update()
|
|||
if (6 == i2c_bus.BusRead(ACTIVE_DEVICE_ADDR, 0x00, 6, data))
|
||||
{
|
||||
// Passthrough data modifications via wiibrew.org
|
||||
// Data passing through drops the least significant bit of the axes of the left (or only) joystick
|
||||
// Bit 0 of Byte 4 is overwritten [by the 'extension_connected' flag]
|
||||
// Bits 0 and 1 of Byte 5 are moved to bit 0 of Bytes 0 and 1, overwriting what was there before
|
||||
// Data passing through drops the least significant bit of the axes of the left (or only)
|
||||
// joystick Bit 0 of Byte 4 is overwritten [by the 'extension_connected' flag] Bits 0 and 1
|
||||
// of Byte 5 are moved to bit 0 of Bytes 0 and 1, overwriting what was there before
|
||||
SetBit(data[0], 0, Common::ExtractBit(data[5], 0));
|
||||
SetBit(data[1], 0, Common::ExtractBit(data[5], 1));
|
||||
|
||||
|
|
|
@ -269,6 +269,9 @@ public:
|
|||
// TODO: change int to u16 or something
|
||||
int BusRead(u8 slave_addr, u8 addr, int count, u8* data_out)
|
||||
{
|
||||
// TODO: the real bus seems to read in blocks of 8.
|
||||
// peripherals NACK after each 8 bytes.
|
||||
|
||||
// INFO_LOG(WIIMOTE, "i2c bus read: 0x%02x @ 0x%02x (%d)", slave_addr, addr, count);
|
||||
for (auto& slave : m_slaves)
|
||||
{
|
||||
|
@ -286,6 +289,7 @@ public:
|
|||
int BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in)
|
||||
{
|
||||
// TODO: write in blocks of 6 to simulate the real bus
|
||||
// sometimes it writes in blocks of 8, (speaker data)
|
||||
// this might trigger activation writes more accurately
|
||||
|
||||
// INFO_LOG(WIIMOTE, "i2c bus write: 0x%02x @ 0x%02x (%d)", slave_addr, addr, count);
|
||||
|
@ -389,7 +393,7 @@ protected:
|
|||
void UpdateButtonsStatus();
|
||||
|
||||
void GetButtonData(u8* data);
|
||||
void GetAccelData(u8* data);
|
||||
void GetAccelData(s16* x, s16* y, s16* z);
|
||||
void UpdateIRData(bool use_accel);
|
||||
|
||||
private:
|
||||
|
@ -399,6 +403,8 @@ private:
|
|||
|
||||
struct IRCameraLogic : public I2CSlave
|
||||
{
|
||||
// TODO: some of this memory is write-only and should return error 7.
|
||||
|
||||
struct RegData
|
||||
{
|
||||
// Contains sensitivity and other unknown data
|
||||
|
@ -501,6 +507,8 @@ private:
|
|||
static const u8 DATA_FORMAT_ADPCM = 0x00;
|
||||
static const u8 DATA_FORMAT_PCM = 0x40;
|
||||
|
||||
// TODO: It seems reading address 0x00 should always return 0xff.
|
||||
|
||||
struct
|
||||
{
|
||||
// Speaker reports result in a write of samples to addr 0x00 (which also plays sound)
|
||||
|
@ -746,6 +754,7 @@ private:
|
|||
DynamicData m_shake_dynamic_data;
|
||||
|
||||
// Wiimote accel data
|
||||
// TODO: can this member be eliminated?
|
||||
AccelData m_accel;
|
||||
|
||||
// Wiimote index, 0-3
|
||||
|
|
|
@ -688,8 +688,7 @@ static void SetWiiInputDisplayString(int remoteID, const u8* const data,
|
|||
std::memcpy(&dt, accelData, sizeof(dt));
|
||||
|
||||
display_str +=
|
||||
StringFromFormat(" ACC:%d,%d,%d", dt.x << 2 | buttons.acc_x_lsb,
|
||||
dt.y << 2 | buttons.acc_y_lsb << 1, dt.z << 2 | buttons.acc_z_lsb << 1);
|
||||
StringFromFormat(" ACC:%d,%d,%d (LSB not shown)", dt.x << 2, dt.y << 2, dt.z << 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -350,11 +350,12 @@ void WiiTASInputWindow::GetValues(u8* report_data, WiimoteEmu::ReportFeatures rp
|
|||
if (m_remote_orientation_box->isVisible() && accel_data && buttons_data)
|
||||
{
|
||||
wm_accel& accel = *reinterpret_cast<wm_accel*>(accel_data);
|
||||
wm_buttons& buttons = *reinterpret_cast<wm_buttons*>(buttons_data);
|
||||
//wm_buttons& buttons = *reinterpret_cast<wm_buttons*>(buttons_data);
|
||||
|
||||
u16 accel_x = (accel.x << 2) & (buttons.acc_x_lsb & 0b11);
|
||||
u16 accel_y = (accel.y << 2) & ((buttons.acc_y_lsb & 0b1) << 1);
|
||||
u16 accel_z = (accel.z << 2) & ((buttons.acc_z_lsb & 0b1) << 1);
|
||||
// TODO: lsb
|
||||
u16 accel_x = (accel.x << 2); // & (buttons.acc_x_lsb & 0b11);
|
||||
u16 accel_y = (accel.y << 2); // & ((buttons.acc_y_lsb & 0b1) << 1);
|
||||
u16 accel_z = (accel.z << 2); // &((buttons.acc_z_lsb & 0b1) << 1);
|
||||
|
||||
GetSpinBoxU16(m_remote_orientation_x_value, accel_x);
|
||||
GetSpinBoxU16(m_remote_orientation_y_value, accel_y);
|
||||
|
@ -364,9 +365,10 @@ void WiiTASInputWindow::GetValues(u8* report_data, WiimoteEmu::ReportFeatures rp
|
|||
accel.y = accel_y >> 2;
|
||||
accel.z = accel_z >> 2;
|
||||
|
||||
buttons.acc_x_lsb = accel_x & 0b11;
|
||||
buttons.acc_y_lsb = (accel_y >> 1) & 0b1;
|
||||
buttons.acc_z_lsb = (accel_z >> 1) & 0b1;
|
||||
// TODO: lsb
|
||||
//buttons.acc_x_lsb = accel_x & 0b11;
|
||||
//buttons.acc_y_lsb = (accel_y >> 1) & 0b1;
|
||||
//buttons.acc_z_lsb = (accel_z >> 1) & 0b1;
|
||||
}
|
||||
|
||||
if (m_ir_box->isVisible() && ir_data && !m_use_controller->isChecked())
|
||||
|
|
Loading…
Reference in New Issue