summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <>2008-09-16 15:40:46 +0000
committererdgeist <>2008-09-16 15:40:46 +0000
commit8d957f068792b4ee55f807930c975699c29922a2 (patch)
tree4a960cbe6c05797175a7c8b518f93e4459bafd1d
KickoffHEADmaster
-rw-r--r--Makefile5
-rw-r--r--display.c63
-rw-r--r--display.h6
-rw-r--r--gm.h5
-rw-r--r--heuristics.c111
-rw-r--r--heuristics.h13
-rw-r--r--locate.c91
-rw-r--r--locate.h9
-rw-r--r--main.c172
-rw-r--r--vubars.c148
-rw-r--r--vubars.h6
11 files changed, 629 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bf43616
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
1main: main.c locate.c display.c vubars.c locate.h gm.h display.h vubars.h heuristics.c
2 gcc -O2 -o main main.c locate.c display.c vubars.c heuristics.c -l cwiid -lm -lSDL -lSDL_gfx
3
4clean:
5 rm main
diff --git a/display.c b/display.c
new file mode 100644
index 0000000..a4ac62b
--- /dev/null
+++ b/display.c
@@ -0,0 +1,63 @@
1#include <SDL/SDL.h>
2#include <SDL/SDL_gfxPrimitives.h>
3
4#include "display.h"
5
6static SDL_Surface *screen;
7static int g_width, g_height;
8
9void display_init( int width, int height) {
10 g_width = width;
11 g_height = height;
12
13 if (SDL_Init (SDL_INIT_EVERYTHING) == -1) {
14 fprintf( stderr, "Can't initialize SDL.\n" );
15 exit (1);
16 }
17
18 screen = SDL_SetVideoMode ( width, height, 24, SDL_SWSURFACE | SDL_DOUBLEBUF );
19 if( !screen ) {
20 fprintf( stderr, "Can't set video mode.\n" );
21 exit( 1 );
22 }
23
24 memset( screen->pixels, 0, width * height * 3 );
25 SDL_WM_SetCaption ( "GodMachine", "GodMachine" );
26
27}
28
29void display_clear( ) {
30// rectangleColor( screen, 0, 0, g_width, g_height, 0 );
31
32 memset( screen->pixels, 0, g_width * g_height * 3 );
33 vlineColor( screen, g_width / 2, 0, g_height, 0xffffffff );
34 hlineColor( screen, 0, g_width, g_height / 2, 0xffffffff );
35}
36
37void display_circle( int wii_id, int x, int y, int w ) {
38 int xoff = ( wii_id & 1 ) * g_width / 2;
39 int yoff = ( wii_id >> 1 ) * g_height / 2;
40
41 filledCircleColor(screen, x + xoff, y + yoff, w, 0xffffffff );
42
43}
44
45void display_line( int wii_id, int x0, int y0, int x1, int y1 ) {
46 int xoff = ( wii_id & 1 ) * g_width / 2;
47 int yoff = ( wii_id >> 1 ) * g_height / 2;
48
49 aalineColor( screen, x0 + xoff, y0 + yoff, x1 + xoff, y1 + yoff, 0xffffffff );
50
51}
52
53void display_rectangle( int wii_id, int x, int y, int w, int h ) {
54 int xoff = ( wii_id & 1 ) * g_width / 2;
55 int yoff = ( wii_id >> 1 ) * g_height / 2;
56
57 boxColor( screen, x + xoff, y + yoff, x + xoff + w, y + yoff + h, 0xffffffff );
58
59}
60
61void display_redraw() {
62 SDL_Flip( screen );
63}
diff --git a/display.h b/display.h
new file mode 100644
index 0000000..2b2464f
--- /dev/null
+++ b/display.h
@@ -0,0 +1,6 @@
1void display_init( int width, int height);
2void display_redraw( );
3
4void display_clear( );
5void display_line( int wii_id, int x0, int y0, int x1, int y1 );
6void display_circle( int wii_id, int x, int y, int w );
diff --git a/gm.h b/gm.h
new file mode 100644
index 0000000..95b54f3
--- /dev/null
+++ b/gm.h
@@ -0,0 +1,5 @@
1typedef struct {
2 double x; double y;
3} wii_pt;
4
5#define WII_COUNT 4
diff --git a/heuristics.c b/heuristics.c
new file mode 100644
index 0000000..429a612
--- /dev/null
+++ b/heuristics.c
@@ -0,0 +1,111 @@
1#include <stdio.h>
2
3#include "vubars.h"
4
5static void heuristics_getGesture( int const amount, int const off, int const * const values,
6 int *dxl, int *dyl, int *dxr, int *dyr );
7
8int heuristics_getEnergy( int const amount, int const * const values ) {
9 int energy = 0;
10 int i;
11
12 for( i = 0; i < amount-1; ++i )
13 energy += values[i]*values[i+1];
14
15 return energy;
16}
17
18// Gets the two longest consecutive gestures found
19// in frames. -1 in off[ab] means no gesture found
20
21// Here what counts: the bigger abs(dx[ab]), the longer the gesture
22// the bigger dy[ab]/dx[ab], the slower the gesture
23void heuristics_getGestures( int const amount, int const * const values,
24 int *offa, int *dxa, int *dya, int *dda,
25 int *offb, int *dxb, int *dyb, int *ddb )
26{
27 int i, l = 0;
28 int dxl [ amount ], dyl [ amount ], dxr [ amount ], dyr [ amount ];
29
30 // Get the longest gestures for each point - both into left and rite
31 for( i=0; i<amount; ++i )
32 heuristics_getGesture( amount, i, values, dxl + i, dyl + i, dxr + i, dyr + i );
33
34 // "Sort" gesture by length
35 *offa = *dxa = *dya = 0;
36 for( i=0; i<amount; ++i ) {
37 if( dxr[ i ] > *dxa ) { *offa = i; *dxa = dxr[ i ]; *dya = dyr[ i ]; *dda = 1; }
38 if( dxl[ i ] > *dxa ) { *offa = i; *dxa = dxl[ i ]; *dya = dyl[ i ]; *dda =-1; }
39 }
40
41 // If no gesture found at all, invalidate off
42 // and return... second run wouldnt suddenly find a gesture
43 if( *dxa == 0 ) { *offa = *offb = -1; return; }
44
45 // Now clear the best result - this will find us the second best result
46 i = *offa;
47 if( *dda == 1 ) {
48 for( i=*offa; i < *offa + dxr[ *offa ]; ++i )
49 dxr[ i ] = 0;
50 } else {
51 for( i=*offa; i > *offa - dxl[ *offa ]; --i )
52 dxl[ i ] = 0;
53 }
54
55 // "Sort" remaining gestures by length
56 *offb = *dxb = *dyb = 0;
57 for( i=0; i<amount; ++i ) {
58 if( dxr[ i ] > *dxb ) { *offb = i; *dxb = dxr[ i ]; *dyb = dyr[ i ]; *ddb = 1;}
59 if( dxl[ i ] > *dxb ) { *offb = i; *dxb = -dxl[ i ]; *dyb = dyl[ i ]; *ddb =-1;}
60 }
61
62 // If no secondary gesture found, invalidate off
63 if( *dxb == 0 ) *offb = -1;
64}
65
66static void heuristics_getGesture( int const amount, int const off, int const * const values,
67 int * const dxl, int * const dyl, int * const dxr, int * const dyr )
68{
69 int i;
70
71 // Initialize as "nothing happened"
72 *dxl = *dxr = *dyl = *dyr = 0;
73
74 // if this didn't peak in last frame, we're not starting
75 // a gesture here.
76 if( values[off] != VU_PEAK ) return;
77
78 if( off > 0 ) *dyl = values[off]-values[off-1];
79 if( off < amount-1 ) *dyr = values[off]-values[off+1];
80
81 if( !*dyl && !*dyr ) return;
82
83 // Depending on where this peaks seems to have come from,
84 // chose direction where to follow it
85 // try to collect enough monotonic samples and calculate a
86 // slope. Since our sample peaks, all others cant be larger
87 if( (*dyl) && (*dyl < *dyr) ) {
88 (*dxl)++;
89 for( i=off-1; i>=0; --i ) {
90 int dy = values[i+1] - values[i];
91
92 // If it scrolled out of scope, ignore it
93 if( !values[i] || dy < 0 ) break;
94
95 (*dxl)++;
96 (*dyl) += dy;
97 }
98 } else {
99 (*dxr)++;
100 // Do the same when going right
101 for( i=off+1; i<amount; ++i ) {
102 int dy = values[i-1] - values[i];
103
104 // If it scrolled out of scope, ignore it
105 if( !values[i] || dy < 0 ) break;
106
107 (*dxr)++;
108 (*dyr) += dy;
109 }
110 }
111}
diff --git a/heuristics.h b/heuristics.h
new file mode 100644
index 0000000..a01d1f7
--- /dev/null
+++ b/heuristics.h
@@ -0,0 +1,13 @@
1// Gets the two longest consecutive gestures found
2// in frames. -1 in off[ab] means no gesture found
3
4// Here what counts: the bigger abs(dx[ab]), the longer the gesture
5// the bigger dy[ab]/dx[ab], the slower the gesture
6void heuristics_getGestures( int const amount, int const * const values,
7 int *offa, int *dxa, int *dya, int *dda,
8 int *offb, int *dxb, int *dyb, int *ddb );
9
10// Calculate an "energy" level contained in vu bars.
11// to soften spikes, we correlate neighbouring bars
12int heuristics_getEnergy( int const amount, int const * const values );
13
diff --git a/locate.c b/locate.c
new file mode 100644
index 0000000..1d3ec72
--- /dev/null
+++ b/locate.c
@@ -0,0 +1,91 @@
1#include <math.h>
2#include <stdio.h>
3
4#include "gm.h"
5
6static wii_pt bounds[2][4];
7static int g_calibrated[4];
8
9double get_dist( wii_pt *p1, wii_pt *p2 ) {
10 double d = (p1->x - p2->x)*(p1->x - p2->x) +
11 (p1->y - p2->y)*(p1->y - p2->y);
12 return sqrt(d);
13}
14
15/* This call stores information about the expected
16 rectangle for each wii
17*/
18void wii_calibrate( int wii_id, wii_pt *coords ) {
19 double max_dist = 0.0;
20 int pt1 = 0, pt2 = 0, i, j;
21
22 /* Points with maximal distance span a rectangle */
23 for( i=0; i<4; ++i )
24 for( j=1; j<4; ++j ) {
25 double dist = get_dist( coords+i, coords+j );
26 if( dist > max_dist ) {
27 pt1 = i; pt2 = j;
28 max_dist = dist;
29 }
30 }
31
32 if( coords[pt1].x > coords[pt2].x ) {
33 bounds[0][wii_id] = coords[pt1];
34 bounds[1][wii_id] = coords[pt2];
35 } else {
36 bounds[1][wii_id] = coords[pt1];
37 bounds[0][wii_id] = coords[pt2];
38 }
39
40 g_calibrated[wii_id] = 1;
41}
42
43int wii_point_to_led( int wii_id, wii_pt *coords ) {
44 // Ick nenn die immer so.
45 const double x0 = bounds[0][wii_id].x;
46 const double y0 = bounds[0][wii_id].y;
47 const double x1 = bounds[1][wii_id].x;
48 const double y1 = bounds[1][wii_id].y;
49 const double xp = coords->x;
50 const double yp = coords->y;
51
52//printf( "%lf:%lf ", xp, yp );
53
54 // Where m is slope of orthogonal line
55 // And n is square of diagonal of bounding box
56 double m = (x1-x0)*(xp-x0)+(y1-y0)*(yp-y0);
57 double n = (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);
58
59 // To find out distance of coord to our base line
60 double q = (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);
61
62//printf( "%lf %lf %lf\n", m, n, q );
63
64 double offs_on_line = m/n;
65 double dist_to_line = q/n;
66
67 // If wii is not calibrated, we cannot detect point
68 if( !g_calibrated[wii_id] )
69 return -1;
70
71 // Point is too far away to be considered a match
72 if( ( dist_to_line > 0.1 ) || ( dist_to_line < -0.1 ) ) {
73// puts( "too far " );
74 return -1;
75 }
76
77// printf( "%1.3lf\n", offs_on_line );
78
79 // Check, which segment our line hits
80 if( ( offs_on_line > (-1.0/6.0) ) && ( offs_on_line <= (1.0/6.0) ) )
81 return 0;
82 if( ( offs_on_line > ( 1.0/6.0) ) && ( offs_on_line <= (3.0/6.0) ) )
83 return 1;
84 if( ( offs_on_line > ( 3.0/6.0) ) && ( offs_on_line <= (5.0/6.0) ) )
85 return 2;
86 if( ( offs_on_line > ( 5.0/6.0) ) && ( offs_on_line <= (7.0/6.0) ) )
87 return 3;
88
89 // No match!
90 return -1;
91}
diff --git a/locate.h b/locate.h
new file mode 100644
index 0000000..0b72f72
--- /dev/null
+++ b/locate.h
@@ -0,0 +1,9 @@
1#ifndef _WII_LOCATE_H_
2#define _WII_LOCATE_H_
3
4#include "gm.h"
5
6void wii_calibrate( int wii_id, wii_pt *coords );
7int wii_point_to_led( int wii_id, wii_pt *coords );
8
9#endif
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..e645b48
--- /dev/null
+++ b/main.c
@@ -0,0 +1,172 @@
1#include <stdarg.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <signal.h>
5#include <time.h>
6
7#include <cwiid.h>
8#include "gm.h"
9#include "display.h"
10
11/* Our wii's bluetooth and wii handles */
12static bdaddr_t g_bdaddr[4];
13static cwiid_wiimote_t *g_wiimotes[4];
14static int g_num_controls = 0;
15static int g_samples_received = 0;
16static uint32_t g_starttime;
17
18static volatile int g_redraw_lock = 0;
19
20static const int g_width = 400, g_height = 300;
21
22cwiid_mesg_callback_t cwiid_callback;
23cwiid_err_t err;
24void err(cwiid_wiimote_t *wiimote, const char *s, va_list ap)
25{
26 if (wiimote) printf("%d:", cwiid_get_id(wiimote)); else printf("-1:");
27 vprintf(s, ap);
28 printf("\n");
29}
30
31int main( int argc, char **argv ) {
32 int LEDs[4] = { CWIID_LED1_ON, CWIID_LED1_ON | CWIID_LED2_ON,
33 CWIID_LED1_ON | CWIID_LED2_ON | CWIID_LED3_ON,
34 CWIID_LED1_ON | CWIID_LED2_ON | CWIID_LED3_ON | CWIID_LED4_ON };
35 int i;
36 struct timeval now;
37
38 signal( SIGINT, exit );
39 display_init( g_width, g_height);
40
41 cwiid_set_err(err);
42
43 /* If no bdaddrs given on command line, just connect to
44 first visible wii */
45 if( argc <= 1 ) {
46 char bt_out[64];
47 g_bdaddr[0] = *BDADDR_ANY;
48
49 while( !(g_wiimotes[g_num_controls] = cwiid_open( &g_bdaddr[0], 0 )))
50 fprintf( stderr, "Unable to connect to wiimote\n" );
51
52 ba2str( &g_bdaddr[0], bt_out );
53 fprintf( stderr, "Connected to wiimote %i (BT-Addr: %s)\n", i, bt_out );
54 g_num_controls++;
55 }
56
57 /* ... else try to reach every single wii */
58 for( i=0; i<argc-1; ++i ) {
59 str2ba(argv[i+1], &g_bdaddr[i]);
60
61 while( !(g_wiimotes[g_num_controls] = cwiid_open( &g_bdaddr[i], 0 )))
62 fprintf( stderr, "Unable to connect to wiimote %i (BT-Addr: %s)\n", i, argv[i+1] );
63
64 g_num_controls++;
65 fprintf( stderr, "Connected to wiimote %i (BT-Addr: %s)\n", i, argv[i+1] );
66 }
67
68 for( i=0; i<g_num_controls; ++i ) {
69 if (cwiid_set_mesg_callback(g_wiimotes[i], cwiid_callback)) {
70 fprintf(stderr, "Unable to set message callback\n");
71 return -1;
72 }
73
74 /* Set report mode to IR */
75 cwiid_set_rpt_mode(g_wiimotes[i], CWIID_RPT_IR);
76
77 /* Enable call back */
78 cwiid_enable(g_wiimotes[i], CWIID_FLAG_MESG_IFC);
79
80 /* Reflect number in leds */
81 cwiid_set_led(g_wiimotes[i], LEDs[i]);
82 }
83
84 gettimeofday(&now, (struct timezone *)NULL);
85 g_starttime = now.tv_sec * 1000 + now.tv_usec / 1000; /* in ms */
86
87 /* Spin and let call back do all the work */
88 while( 1 ) {
89 if( ! (++i & 0xffff ) ) {
90 int wii_id, led;
91 while( g_redraw_lock );
92
93 for( wii_id=0; wii_id<4; ++wii_id )
94 for( led = 0; led<4; ++led )
95 display_rectangle( wii_id, led * g_width / 16, 0, g_width / 16, vubars_getinfo(wii_id, led)/2 );
96
97 display_redraw();
98 usleep( 1000 );
99 vubars_reduce();
100 display_rectangle( 2, g_width/2-10, 0, 20, -vubars_getweather()/2 );
101 display_rectangle( 2, g_width/2-15, -128, 30, 1 );
102 display_rectangle( 2, g_width/2-15, -64, 30, 1 );
103 }
104 }
105
106 return 0;
107}
108
109void cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count,
110 union cwiid_mesg mesg[], struct timespec *timestamp)
111{
112 int i, j, k, wii_id, ledmask;
113 int valid_sources;
114 struct timeval now;
115 uint32_t runtime;
116 wii_pt coords[4];
117
118 gettimeofday(&now, (struct timezone *)NULL);
119 runtime = now.tv_sec * 1000 + now.tv_usec / 1000 - g_starttime; /* in ms */
120
121 for( i=0; i<g_num_controls; ++i ) {
122 if( wiimote == g_wiimotes[i] )
123 wii_id = i;
124 }
125 g_redraw_lock = 1;
126 display_clear();
127 g_samples_received++;
128 for (i=0; i < mesg_count; i++) {
129 switch (mesg[i].type) {
130
131 case CWIID_MESG_IR:
132// printf("IR Report (%i): ", wii_id );
133// printf("(%ld Hz) ", ( g_samples_received * 1000 ) / runtime );
134
135 valid_sources = 0;
136 for (j = 0; j < CWIID_IR_SRC_COUNT; j++) {
137 if (mesg[i].ir_mesg.src[j].valid) {
138 coords[valid_sources].x = (double)mesg[i].ir_mesg.src[j].pos[CWIID_X];
139 coords[valid_sources].y = (double)mesg[i].ir_mesg.src[j].pos[CWIID_Y];
140
141 display_circle( wii_id, coords[valid_sources].x / 5.0, coords[valid_sources].y / 5.0, 6 );
142 valid_sources++;
143// printf("(%d,%d) ", mesg[i].ir_mesg.src[j].pos[CWIID_X],
144// mesg[i].ir_mesg.src[j].pos[CWIID_Y]);
145 }
146 }
147
148 if (!valid_sources) {
149// printf("no sources detected");
150 }
151
152 if( valid_sources == 4 ) {
153 wii_calibrate( wii_id, coords );
154 }
155
156 ledmask = 0;
157 for( j=0; j<valid_sources; ++j ) {
158 int led = wii_point_to_led( wii_id, coords+j );
159 ledmask |= 1<<led;
160 }
161 for( j=0; j<4; ++j ) {
162 vubars_peak( wii_id, j, ( ledmask >> j ) & 1 );
163 }
164
165 break;
166 default:
167 break;
168 }
169 }
170 g_redraw_lock = 0;
171}
172
diff --git a/vubars.c b/vubars.c
new file mode 100644
index 0000000..8fcf081
--- /dev/null
+++ b/vubars.c
@@ -0,0 +1,148 @@
1#include <stdio.h>
2#include <math.h>
3
4#include "gm.h"
5#include "vubars.h"
6#include "heuristics.h"
7
8// This is our current idea of how we want to influence the weather
9// 128 means: do nothing at all
10//
11// We want to default to softening the weather, so our value always
12// flows back towards 100
13static double vu_value_main = 100.0;
14static double vu_value_softening = 0.0;
15static double vu_value_activating = 0.0;
16
17static int wii_last[WII_COUNT * 4];
18static int wii_bars[WII_COUNT * 4];
19
20int vubars_peak( int wii_id, int led, int is_on ) {
21 if( is_on ) {
22 wii_last[wii_id*4+led] = 0;
23 } else {
24 if( ++wii_last[wii_id*4+led] == 1 )
25 wii_bars[wii_id*4+led] = VU_PEAK;
26 }
27}
28
29int vubars_getinfo( int wii_id, int led ) {
30 return wii_bars[wii_id*4+led];
31}
32
33int vubars_getweather( ) {
34 return (int)vu_value_main;
35}
36
37static int GESTURE_A_dd = 0;
38static int GESTURE_A_dx = 0;
39static int GESTURE_A_dy = 0;
40
41static int GESTURE_A_off = 0;
42static int GESTURE_A_ttl = 0;
43
44static int GESTURE_B_dd = 0;
45static int GESTURE_B_dx = 0;
46static int GESTURE_B_dy = 0;
47
48static int GESTURE_B_off = 0;
49static int GESTURE_B_ttl = 0;
50
51static void match_gesture( int off, int dx, int dy, int dd ) {
52 if( ( GESTURE_A_dd == dd ) && ( GESTURE_A_off == off + dd ) ) {
53 printf( "...continued A\n" );
54
55 GESTURE_A_off = off;
56 GESTURE_A_dx = dx;
57 GESTURE_A_dy = dy;
58 GESTURE_A_ttl = VU_PEAK;
59
60 } else if ( ( GESTURE_B_dd == dd ) && ( GESTURE_B_off == off + dd ) ) {
61 printf( "...continued B\n" );
62
63 GESTURE_B_off = off;
64 GESTURE_B_dx = dx;
65 GESTURE_B_dy = dy;
66 GESTURE_B_ttl = VU_PEAK;
67
68 } else {
69 printf( "\n" );
70
71 if( GESTURE_B_ttl >= GESTURE_A_ttl ) {
72 GESTURE_A_off = off;
73 GESTURE_A_dd = dd;
74 GESTURE_A_dx = dx;
75 GESTURE_A_dy = dy;
76 GESTURE_A_ttl = VU_PEAK;
77 } else {
78 GESTURE_B_off = off;
79 GESTURE_B_dd = dd;
80 GESTURE_B_dx = dx;
81 GESTURE_B_dy = dy;
82 GESTURE_B_ttl = VU_PEAK;
83 }
84 }
85}
86
87void vubars_reduce() {
88 int i;
89 double diff;
90
91 // First do some heuristics voodoo
92 int offa, offb, dxa, dxb, dya, dyb, dda, ddb;
93
94 heuristics_getGestures( 16, wii_bars, &offa, &dxa, &dya, &dda, &offb, &dxb, &dyb, &ddb );
95
96 if( ( offa != -1 ) && ( dxa > 2 ) ) {
97 printf( "1mary gesture detected: offset: % 2d direction: %s len: % 2d speed: %lf",
98 offa, dda < 0 ? "left" : "rite", dxa, (double)dya / (double)dxa );
99 match_gesture( offa, dxa, dya, dda );
100 }
101
102
103 if( ( offb != -1 ) && ( dxb > 2 ) ) {
104 printf( "2ndry gesture detected: offset: % 2d direction: %s len: % 2d speed: %lf\n",
105 offb, ddb < 0 ? "left" : "rite", dxb, (double)dyb / (double)dxb );
106 match_gesture( offb, dxb, dyb, ddb );
107 }
108
109 // Have two gestures living at one
110 if( GESTURE_A_ttl && GESTURE_B_ttl ) {
111 if( GESTURE_A_dd == GESTURE_B_dd ) {
112// printf( "Two gestures pointing into the same direction.\n" );
113 } else {
114 // The more interesting case: hands move into opposite directions
115 if( GESTURE_A_dd == -1 ) {
116 if ( GESTURE_A_off < GESTURE_B_off )
117 printf( "Slower! (Case 1)\n" );
118 else
119 printf( "Faster! (Case 2)\n" );
120 } else {
121 if ( GESTURE_A_off < GESTURE_B_off )
122 printf( "Faster! (Case 3)\n" );
123 else
124 printf( "Slower! (Case 4)\n" );
125 }
126 }
127 }
128
129 // Now try to modify the weather by using values from our vu-bars
130 diff = (double)heuristics_getEnergy( 16, wii_bars );
131 vu_value_main += diff / 40000.0;
132
133 diff = vu_value_main - 100.0;
134 if( diff<0 ) diff = -diff;
135 diff = sqrt( diff );
136
137 if( vu_value_main > 100.0 ) diff = -diff;
138
139 vu_value_main += diff;
140
141 for( i=0; i<WII_COUNT*4; ++i )
142 if( wii_bars[i] )
143 wii_bars[i]-=VU_STEP;
144
145 if( GESTURE_A_ttl ) GESTURE_A_ttl -= VU_STEP;
146 if( GESTURE_B_ttl ) GESTURE_B_ttl -= VU_STEP;
147
148}
diff --git a/vubars.h b/vubars.h
new file mode 100644
index 0000000..8cca6b8
--- /dev/null
+++ b/vubars.h
@@ -0,0 +1,6 @@
1static unsigned long const VU_STEP = 10;
2static unsigned long const VU_PEAK = 400;
3
4int vubars_peak( int wii_id, int led, int is_on );
5void vubars_reduce();
6int vubars_getweather();