Skip to content

Commit e2605cb

Browse files
author
Daniel K. O. (dkosmari)
committed
Balance Board changes:
- Fixed LED not turning on (it only has LED 1.) - `wii_board_t` members renamed to be more readable. - Added battery and temperature fields. - Weights are adjusted from the current temperature. - The `.x`/`.y` members are now normalized between -1 and +1, and only set if 2 Kg or more is detected. - The `.y` member was negated, so positive means top/front. - `.total_weight` contains the sum of the 4 weights. - `.battery` goes from 0 (critical) to 4 (full charge.)
1 parent 77075c9 commit e2605cb

5 files changed

Lines changed: 126 additions & 78 deletions

File tree

gc/wiiuse/wiiuse.h

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -515,25 +515,39 @@ typedef struct guitar_hero_3_t {
515515
struct joystick_t js; /**< joystick calibration */
516516
} guitar_hero_3_t;
517517

518+
enum wii_board_sensor_id_t {
519+
WII_BOARD_SENSOR_ID_TOP_RIGHT,
520+
WII_BOARD_SENSOR_ID_BOT_RIGHT,
521+
WII_BOARD_SENSOR_ID_TOP_LEFT,
522+
WII_BOARD_SENSOR_ID_BOT_LEFT,
523+
WII_BOARD_NUM_SENSORS
524+
};
525+
526+
typedef struct wii_board_sensor_cal_t {
527+
short ref_0;
528+
short ref_17;
529+
short ref_34;
530+
} wii_board_sensor_cal_t;
531+
518532
/**
519533
* @struct wii_board_t
520534
* @brief Wii Balance Board expansion device.
521535
*/
522536
typedef struct wii_board_t {
523-
float tl; /* Interpolated */
524-
float tr;
525-
float bl;
526-
float br; /* End interp */
527-
short rtl; /* RAW */
528-
short rtr;
529-
short rbl;
530-
short rbr; /* /RAW */
531-
short ctl[3]; /* Calibration */
532-
short ctr[3];
533-
short cbl[3];
534-
short cbr[3]; /* /Calibration */
535-
float x;
536-
float y;
537+
/* RAW */
538+
short raw_sensor[WII_BOARD_NUM_SENSORS];
539+
ubyte raw_temp;
540+
ubyte raw_bat;
541+
/* Calibration */
542+
wii_board_sensor_cal_t cal_sensor[WII_BOARD_NUM_SENSORS];
543+
ubyte cal_temp;
544+
ubyte cal_bat; /**< always 0x69 */
545+
/* Calculated */
546+
float weight[WII_BOARD_NUM_SENSORS];
547+
float total_weight;
548+
float x; /**< normalized to [-1, +1], positive is right */
549+
float y; /**< normalized [-1, +1], positive is up */
550+
ubyte battery; /**< number of battery bars, from 0 to 4 */
537551
} wii_board_t;
538552

539553
typedef struct motion_plus_t

wiiuse/dynamics.c

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -225,49 +225,74 @@ void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) {
225225
}
226226
}
227227

228-
void calc_balanceboard_state(struct wii_board_t *wb)
228+
static float calc_balanceboard_weight(wii_board_t *wb, int idx)
229229
{
230-
/*
231-
Interpolate values
232-
Calculations borrowed from wiili.org - No names to mention sadly :( http://www.wiili.org/index.php/Wii_Balance_Board_PC_Drivers
233-
*/
234-
235-
if(wb->rtr<wb->ctr[1])
236-
{
237-
wb->tr = 17.0f*(f32)(wb->rtr-wb->ctr[0])/(f32)(wb->ctr[1]-wb->ctr[0]);
238-
}
230+
/*
231+
* Calculations borrowed from wiili.org - No names to mention sadly :(
232+
* http://www.wiili.org/index.php/Wii_Balance_Board_PC_Drivers
233+
*/
234+
short raw = wb->raw_sensor[idx];
235+
const wii_board_sensor_cal_t *cal = &wb->cal_sensor[idx];
236+
if (raw < cal->ref_17)
237+
return 17.0f * (raw - cal->ref_0 ) / (cal->ref_17 - cal->ref_0 );
239238
else
240-
{
241-
wb->tr = 17.0f*(f32)(wb->rtr-wb->ctr[1])/(f32)(wb->ctr[2]-wb->ctr[1]) + 17.0f;
242-
}
239+
return 17.0f * (raw - cal->ref_17) / (cal->ref_34 - cal->ref_17) + 17.0f;
240+
}
243241

244-
if(wb->rtl<wb->ctl[1])
245-
{
246-
wb->tl = 17.0f*(f32)(wb->rtl-wb->ctl[0])/(f32)(wb->ctl[1]-wb->ctl[0]);
247-
}
248-
else
249-
{
250-
wb->tl = 17.0f*(f32)(wb->rtl-wb->ctl[1])/(f32)(wb->ctl[2]-wb->ctl[1]) + 17.0f;
251-
}
242+
static float calc_balanceboard_temp_correct(float w, const wii_board_t* wb)
243+
{
244+
/* Temperature correction, based on https://wiibrew.org/wiki/Wii_Balance_Board */
245+
static const double a = 0.9990813732147217;
246+
static const double b = 0.007000000216066837;
247+
double c = 1.0 - b * (wb->raw_temp - wb->cal_temp) / 10.0;
248+
return a * w * c;
249+
}
252250

253-
if(wb->rbr<wb->cbr[1])
254-
{
255-
wb->br = 17.0f*(f32)(wb->rbr-wb->cbr[0])/(f32)(wb->cbr[1]-wb->cbr[0]);
256-
}
257-
else
258-
{
259-
wb->br = 17.0f*(f32)(wb->rbr-wb->cbr[1])/(f32)(wb->cbr[2]-wb->cbr[1]) + 17.0f;
260-
}
251+
static unsigned calc_balanceboard_battery_bars(const struct wii_board_t *wb)
252+
{
253+
if (wb->raw_bat >= 0x82)
254+
return 4;
255+
if (wb->raw_bat >= 0x7d)
256+
return 3;
257+
if (wb->raw_bat >= 0x78)
258+
return 2;
259+
if (wb->raw_bat >= wb->cal_bat)
260+
return 1;
261+
return 0;
262+
}
261263

262-
if(wb->rbl<wb->cbl[1])
263-
{
264-
wb->bl = 17.0f*(f32)(wb->rbl-wb->cbl[0])/(f32)(wb->cbl[1]-wb->cbl[0]);
264+
void calc_balanceboard_state(struct wii_board_t *wb)
265+
{
266+
/* Convert raw sensor data to Kg. */
267+
for (unsigned i = 0; i < WII_BOARD_NUM_SENSORS; ++i)
268+
wb->weight[i] = calc_balanceboard_weight(wb, i);
269+
270+
/* Apply temperature and zero correction. */
271+
for (unsigned i = 0; i < WII_BOARD_NUM_SENSORS; ++i)
272+
wb->weight[i] = calc_balanceboard_temp_correct(wb->weight[i], wb);
273+
274+
wb->total_weight = 0;
275+
for (unsigned i = 0; i < WII_BOARD_NUM_SENSORS; ++i)
276+
wb->total_weight += wb->weight[i];
277+
278+
/* Calculate x,y members only if there's at least 2 Kg on the board. */
279+
if (wb->total_weight >= 2.0f) {
280+
wb->x = ((wb->weight[WII_BOARD_SENSOR_ID_TOP_RIGHT] +
281+
wb->weight[WII_BOARD_SENSOR_ID_BOT_RIGHT])
282+
-
283+
(wb->weight[WII_BOARD_SENSOR_ID_TOP_LEFT] +
284+
wb->weight[WII_BOARD_SENSOR_ID_BOT_LEFT]))
285+
/ wb->total_weight;
286+
wb->y = ((wb->weight[WII_BOARD_SENSOR_ID_TOP_RIGHT] +
287+
wb->weight[WII_BOARD_SENSOR_ID_TOP_LEFT])
288+
-
289+
(wb->weight[WII_BOARD_SENSOR_ID_BOT_RIGHT] +
290+
wb->weight[WII_BOARD_SENSOR_ID_BOT_LEFT]))
291+
/ wb->total_weight;
292+
} else {
293+
wb->x = 0;
294+
wb->y = 0;
265295
}
266-
else
267-
{
268-
wb->bl = 17.0f*(f32)(wb->rbl-wb->cbl[1])/(f32)(wb->cbl[2]-wb->cbl[1]) + 17.0f;
269-
}
270296

271-
wb->x = ((wb->tr+wb->br) - (wb->tl+wb->bl))/2.0f;
272-
wb->y = ((wb->bl+wb->br) - (wb->tl+wb->tr))/2.0f;
297+
wb->battery = calc_balanceboard_battery_bars(wb);
273298
}

wiiuse/dynamics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ extern "C" {
4747
void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth);
4848
void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce);
4949
void calc_joystick_state(struct joystick_t* js, float x, float y);
50-
void calc_balanceboard_state(struct wii_board_t *wb);
5150
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type);
51+
void calc_balanceboard_state(struct wii_board_t *wb);
5252

5353
#ifdef __cplusplus
5454
}

wiiuse/wiiboard.c

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
#include "wiiboard.h"
4848
#include "io.h"
4949

50+
static u16 load_be_u16(u8* data)
51+
{
52+
return ((u16)(data[0] << 8)) | ((u16)data[1]);
53+
}
54+
5055
/**
5156
* @brief Handle the handshake data from the wiiboard.
5257
*
@@ -58,36 +63,40 @@
5863
*/
5964
int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, ubyte* data, uword len)
6065
{
61-
int offset = 0;
66+
unsigned offset = 0;
6267

63-
if (data[offset]==0xff) {
64-
if (data[offset+16]==0xff) {
68+
if (data[offset] == 0xff) {
69+
if (data[offset + 0x10] == 0xff) {
6570
WIIUSE_DEBUG("Wii Balance Board handshake appears invalid, trying again.");
6671
wiiuse_read_data(wm, data, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN, wiiuse_handshake_expansion);
6772
return 0;
6873
}
69-
offset += 16;
74+
offset += 0x10;
7075
}
7176

72-
wb->ctr[0] = (data[offset+4]<<8)|data[offset+5];
73-
wb->cbr[0] = (data[offset+6]<<8)|data[offset+7];
74-
wb->ctl[0] = (data[offset+8]<<8)|data[offset+9];
75-
wb->cbl[0] = (data[offset+10]<<8)|data[offset+11];
77+
78+
for (unsigned i = 0; i < WII_BOARD_NUM_SENSORS; ++i) {
79+
/* The reference values for 0 Kg */
80+
wb->cal_sensor[i].ref_0 = load_be_u16(data + offset + 0x04 + 2*i);
81+
/* The reference values for 17 Kg */
82+
wb->cal_sensor[i].ref_17 = load_be_u16(data + offset + 0x0c + 2*i);
83+
/* The reference values for 34 Kg */
84+
wb->cal_sensor[i].ref_34 = load_be_u16(data + offset + 0x14 + 2*i);
85+
}
7686

77-
wb->ctr[1] = (data[offset+12]<<8)|data[offset+13];
78-
wb->cbr[1] = (data[offset+14]<<8)|data[offset+15];
79-
wb->ctl[1] = (data[offset+16]<<8)|data[offset+17];
80-
wb->cbl[1] = (data[offset+18]<<8)|data[offset+19];
87+
/* The minimum battery value (always 0x6a). */
88+
wb->cal_bat = data[offset + 0x01];
8189

82-
wb->ctr[2] = (data[offset+20]<<8)|data[offset+21];
83-
wb->cbr[2] = (data[offset+22]<<8)|data[offset+23];
84-
wb->ctl[2] = (data[offset+24]<<8)|data[offset+25];
85-
wb->cbl[2] = (data[offset+26]<<8)|data[offset+27];
90+
/* The reference temperature. */
91+
wb->cal_temp = data[offset + 0x40];
8692

8793
/* handshake done */
8894
wm->event = WIIUSE_WII_BOARD_INSERTED;
8995
wm->exp.type = EXP_WII_BOARD;
9096

97+
/* Balance Board only has the first LED, so make sure it's on. */
98+
wiiuse_set_leds(wm, WIIMOTE_LED_1, NULL);
99+
91100
return 1;
92101
}
93102

@@ -110,9 +119,9 @@ void wii_board_disconnected(struct wii_board_t* wb)
110119
* @param msg The message specified in the event packet.
111120
*/
112121
void wii_board_event(struct wii_board_t* wb, ubyte* msg)
113-
{
114-
wb->rtr = (msg[0]<<8)|msg[1];
115-
wb->rbr = (msg[2]<<8)|msg[3];
116-
wb->rtl = (msg[4]<<8)|msg[5];
117-
wb->rbl = (msg[6]<<8)|msg[7];
122+
{
123+
for (unsigned i = 0; i < WII_BOARD_NUM_SENSORS; ++i)
124+
wb->raw_sensor[i] = load_be_u16(msg + 2*i);
125+
wb->raw_temp = msg[0x8];
126+
wb->raw_bat = msg[0xa];
118127
}

wiiuse/wpad.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -619,10 +619,10 @@ static u32 __wpad_read_expansion(struct wiimote_t *wm,WPADData *data, struct _wp
619619
break;
620620
case EXP_WII_BOARD:
621621
data->exp.wb = wm->exp.wb;
622-
STATE_CHECK(thresh->wb,wm->exp.wb.rtl,wm->lstate.exp.wb.rtl);
623-
STATE_CHECK(thresh->wb,wm->exp.wb.rtr,wm->lstate.exp.wb.rtr);
624-
STATE_CHECK(thresh->wb,wm->exp.wb.rbl,wm->lstate.exp.wb.rbl);
625-
STATE_CHECK(thresh->wb,wm->exp.wb.rbr,wm->lstate.exp.wb.rbr);
622+
for (unsigned i = 0; i < WII_BOARD_NUM_SENSORS; ++i)
623+
STATE_CHECK(thresh->wb,
624+
wm->exp.wb.raw_sensor[i],
625+
wm->lstate.exp.wb.raw_sensor[i]);
626626
break;
627627
case EXP_MOTION_PLUS:
628628
data->exp.mp = wm->exp.mp;

0 commit comments

Comments
 (0)