Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/wiimote/src/external/wiicpp/wiic/ir.c @ 10905

Last change on this file since 10905 was 9780, checked in by georgr, 11 years ago

WiiCpp library successfully (?) added - won't work without libbluetooth-dev

  • Property svn:executable set to *
File size: 16.7 KB
Line 
1/*
2 *    ir.c
3 *
4 *        This file is part of WiiC, written by:
5 *              Gabriele Randelli
6 *              Email: randelli@dis.uniroma1.it
7 *
8 *    Copyright 2010
9 *             
10 *        This file is based on Wiiuse, written By:
11 *              Michael Laforest        < para >
12 *              Email: < thepara (--AT--) g m a i l [--DOT--] com >
13 *
14 *        Copyright 2006-2007
15 *
16 *    This program is free software; you can redistribute it and/or modify
17 *    it under the terms of the GNU General Public License as published by
18 *    the Free Software Foundation; either version 3 of the License, or
19 *    (at your option) any later version.
20 *
21 *    This program is distributed in the hope that it will be useful,
22 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
23 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 *    GNU General Public License for more details.
25 *
26 *    You should have received a copy of the GNU General Public License
27 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 *
29 *        $Header$
30 */
31
32/**
33 *      @file
34 *      @brief Handles IR data.
35 */
36
37#include <stdio.h>
38#include <math.h>
39#include <unistd.h>
40
41#include "definitions.h"
42#include "wiic_internal.h"
43#include "ir.h"
44
45static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2);
46static void interpret_ir_data(struct wiimote_t* wm);
47static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang);
48static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y);
49static void reorder_ir_dots(struct ir_dot_t* dot);
50static float ir_distance(struct ir_dot_t* dot);
51static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y);
52static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy);
53
54
55/**
56 *      @brief  Set if the wiimote should track IR targets.
57 *
58 *      @param wm               Pointer to a wiimote_t structure.
59 *      @param status   1 to enable, 0 to disable.
60 */
61void wiic_set_ir(struct wiimote_t* wm, int status) {
62        byte buf;
63        char* block1 = NULL;
64        char* block2 = NULL;
65        int ir_level;
66
67        if (!wm)
68                return;
69
70        /*
71         *      Wait for the handshake to finish first.
72         *      When it handshake finishes and sees that
73         *      IR is enabled, it will call this function
74         *      again to actually enable IR.
75         */
76        if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
77                WIIC_DEBUG("Tried to enable IR, will wait until handshake finishes.");
78                WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
79                return;
80        }
81
82        /*
83         *      Check to make sure a sensitivity setting is selected.
84         */
85        ir_level = get_ir_sens(wm, &block1, &block2);
86        if (!ir_level) {
87                WIIC_ERROR("No IR sensitivity setting selected.");
88                return;
89        }
90
91        if (status) {
92                /* if already enabled then stop */
93                if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
94                        return;
95                WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
96        } else {
97                /* if already disabled then stop */
98                if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
99                        return;
100                WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
101        }
102
103        /* set camera 1 and 2 */
104        buf = (status ? 0x04 : 0x00);
105        wiic_send(wm, WM_CMD_IR, &buf, 1);
106        wiic_send(wm, WM_CMD_IR_2, &buf, 1);
107
108        if (!status) {
109                WIIC_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
110                wiic_set_report_type(wm);
111                return;
112        }
113
114        /* enable IR, set sensitivity */
115        buf = 0x08;
116        wiic_write_data(wm, WM_REG_IR, &buf, 1);
117
118        /* wait for the wiimote to catch up */
119        usleep(50000);
120
121        /* write sensitivity blocks */
122        wiic_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
123        wiic_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
124
125        /* set the IR mode */
126        if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
127                buf = WM_IR_TYPE_BASIC;
128        else
129                buf = WM_IR_TYPE_EXTENDED;
130        wiic_write_data(wm, WM_REG_IR_MODENUM, &buf, 1);
131
132        usleep(50000);
133
134        /* set the wiimote report type */
135        wiic_set_report_type(wm);
136
137        WIIC_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level);
138}
139
140
141/**
142 *      @brief  Get the IR sensitivity settings.
143 *
144 *      @param wm               Pointer to a wiimote_t structure.
145 *      @param block1   [out] Pointer to where block1 will be set.
146 *      @param block2   [out] Pointer to where block2 will be set.
147 *
148 *      @return Returns the sensitivity level.
149 */
150static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
151        if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
152                *block1 = WM_IR_BLOCK1_LEVEL1;
153                *block2 = WM_IR_BLOCK2_LEVEL1;
154                return 1;
155        } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
156                *block1 = WM_IR_BLOCK1_LEVEL2;
157                *block2 = WM_IR_BLOCK2_LEVEL2;
158                return 2;
159        } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
160                *block1 = WM_IR_BLOCK1_LEVEL3;
161                *block2 = WM_IR_BLOCK2_LEVEL3;
162                return 3;
163        } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
164                *block1 = WM_IR_BLOCK1_LEVEL4;
165                *block2 = WM_IR_BLOCK2_LEVEL4;
166                return 4;
167        } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
168                *block1 = WM_IR_BLOCK1_LEVEL5;
169                *block2 = WM_IR_BLOCK2_LEVEL5;
170                return 5;
171        }
172
173        *block1 = NULL;
174        *block2 = NULL;
175        return 0;
176}
177
178
179/**
180 *      @brief  Set the virtual screen resolution for IR tracking.
181 *
182 *      @param wm               Pointer to a wiimote_t structure.
183 *      @param x       Screen resolution width.
184 * @param y                     Screen resolution height.
185 */
186void wiic_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
187        if (!wm)        return;
188
189        wm->ir.vres[0] = (x-1);
190        wm->ir.vres[1] = (y-1);
191}
192
193
194/**
195 *      @brief  Set the XY position for the IR cursor.
196 *
197 *      @param wm               Pointer to a wiimote_t structure.
198 * @param pos           The position of the IR emitter (WIIC_IR_ABOVE or WIIC_IR_BELOW)
199 */
200void wiic_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
201        if (!wm)        return;
202
203        wm->ir.pos = pos;
204
205        switch (pos) {
206
207                case WIIC_IR_ABOVE:
208                        wm->ir.offset[0] = 0;
209
210                        if (wm->ir.aspect == WIIC_ASPECT_16_9)
211                                wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
212                        else if (wm->ir.aspect == WIIC_ASPECT_4_3)
213                                wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
214
215                        return;
216
217                case WIIC_IR_BELOW:
218                        wm->ir.offset[0] = 0;
219
220                        if (wm->ir.aspect == WIIC_ASPECT_16_9)
221                                wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 100;
222                        else if (wm->ir.aspect == WIIC_ASPECT_4_3)
223                                wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 70;
224
225                        return;
226
227                default:
228                        return;
229        };
230}
231
232
233/**
234 *      @brief  Set the aspect ratio of the TV/monitor.
235 *
236 *      @param wm               Pointer to a wiimote_t structure.
237 *      @param aspect   Either WIIC_ASPECT_16_9 or WIIC_ASPECT_4_3
238 */
239void wiic_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
240        if (!wm)        return;
241
242        wm->ir.aspect = aspect;
243
244        if (aspect == WIIC_ASPECT_4_3) {
245                wm->ir.vres[0] = WM_ASPECT_4_3_X;
246                wm->ir.vres[1] = WM_ASPECT_4_3_Y;
247        } else {
248                wm->ir.vres[0] = WM_ASPECT_16_9_X;
249                wm->ir.vres[1] = WM_ASPECT_16_9_Y;
250        }
251
252        /* reset the position offsets */
253        wiic_set_ir_position(wm, wm->ir.pos);
254}
255
256
257/**
258 *      @brief  Set the IR sensitivity.
259 *
260 *      @param wm               Pointer to a wiimote_t structure.
261 *      @param level    1-5, same as Wii system sensitivity setting.
262 *
263 *      If the level is < 1, then level will be set to 1.
264 *      If the level is > 5, then level will be set to 5.
265 */
266void wiic_set_ir_sensitivity(struct wiimote_t* wm, int level) {
267        char* block1 = NULL;
268        char* block2 = NULL;
269
270        if (!wm)        return;
271
272        if (level > 5)          level = 5;
273        if (level < 1)          level = 1;
274
275        WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
276                                                                WIIMOTE_STATE_IR_SENS_LVL2 |
277                                                                WIIMOTE_STATE_IR_SENS_LVL3 |
278                                                                WIIMOTE_STATE_IR_SENS_LVL4 |
279                                                                WIIMOTE_STATE_IR_SENS_LVL5));
280
281        switch (level) {
282                case 1:
283                        WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
284                        break;
285                case 2:
286                        WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
287                        break;
288                case 3:
289                        WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
290                        break;
291                case 4:
292                        WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
293                        break;
294                case 5:
295                        WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
296                        break;
297                default:
298                        return;
299        }
300
301        /* set the new sensitivity */
302        get_ir_sens(wm, &block1, &block2);
303
304        wiic_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
305        wiic_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
306
307        WIIC_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
308}
309
310
311/**
312 *      @brief Calculate the data from the IR spots.  Basic IR mode.
313 *
314 *      @param wm               Pointer to a wiimote_t structure.
315 *      @param data             Data returned by the wiimote for the IR spots.
316 */
317void calculate_basic_ir(struct wiimote_t* wm, byte* data) {
318        struct ir_dot_t* dot = wm->ir.dot;
319        int i;
320
321        dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
322        dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
323
324        dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
325        dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
326
327        dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
328        dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
329
330        dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
331        dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
332
333        /* set each IR spot to visible if spot is in range */
334        for (i = 0; i < 4; ++i) {
335                if (dot[i].ry == 1023)
336                        dot[i].visible = 0;
337                else {
338                        dot[i].visible = 1;
339                        dot[i].size = 0;                /* since we don't know the size, set it as 0 */
340                }
341        }
342
343        interpret_ir_data(wm);
344}
345
346
347/**
348 *      @brief Calculate the data from the IR spots.  Extended IR mode.
349 *
350 *      @param wm               Pointer to a wiimote_t structure.
351 *      @param data             Data returned by the wiimote for the IR spots.
352 */
353void calculate_extended_ir(struct wiimote_t* wm, byte* data) {
354        struct ir_dot_t* dot = wm->ir.dot;
355        int i;
356
357        for (i = 0; i < 4; ++i) {
358                dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
359                dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
360
361                dot[i].size = data[(3*i)+2] & 0x0F;
362
363                /* if in range set to visible */
364                if (dot[i].ry == 1023)
365                        dot[i].visible = 0;
366                else
367                        dot[i].visible = 1;
368        }
369
370        interpret_ir_data(wm);
371}
372
373
374/**
375 *      @brief Interpret IR data into more user friendly variables.
376 *
377 *      @param wm               Pointer to a wiimote_t structure.
378 */
379static void interpret_ir_data(struct wiimote_t* wm) {
380        struct ir_dot_t* dot = wm->ir.dot;
381        int i;
382        float roll = 0.0f;
383        int last_num_dots = wm->ir.num_dots;
384
385        if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC))
386                roll = wm->orient.angle.roll;
387
388        /* count visible dots */
389        wm->ir.num_dots = 0;
390        for (i = 0; i < 4; ++i) {
391                if (dot[i].visible)
392                        wm->ir.num_dots++;
393        }
394
395        switch (wm->ir.num_dots) {
396                case 0:
397                {
398                        wm->ir.state = 0;
399
400                        /* reset the dot ordering */
401                        for (i = 0; i < 4; ++i)
402                                dot[i].order = 0;
403
404                        wm->ir.x = 0;
405                        wm->ir.y = 0;
406                        wm->ir.z = 0.0f;
407
408                        return;
409                }
410                case 1:
411                {
412                        fix_rotated_ir_dots(wm->ir.dot, roll);
413
414                        if (wm->ir.state < 2) {
415                                /*
416                                 *      Only 1 known dot, so use just that.
417                                 */
418                                for (i = 0; i < 4; ++i) {
419                                        if (dot[i].visible) {
420                                                wm->ir.x = dot[i].x;
421                                                wm->ir.y = dot[i].y;
422
423                                                wm->ir.ax = wm->ir.x;
424                                                wm->ir.ay = wm->ir.y;
425
426                                                /*      can't calculate yaw because we don't have the distance */
427                                                //wm->orient.yaw = calc_yaw(&wm->ir);
428
429                                                ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
430                                                break;
431                                        }
432                                }
433                        } else {
434                                /*
435                                 *      Only see 1 dot but know theres 2.
436                                 *      Try to estimate where the other one
437                                 *      should be and use that.
438                                 */
439                                for (i = 0; i < 4; ++i) {
440                                        if (dot[i].visible) {
441                                                int ox = 0;
442                                                int x, y;
443
444                                                if (dot[i].order == 1)
445                                                        /* visible is the left dot - estimate where the right is */
446                                                        ox = dot[i].x + wm->ir.distance;
447                                                else if (dot[i].order == 2)
448                                                        /* visible is the right dot - estimate where the left is */
449                                                        ox = dot[i].x - wm->ir.distance;
450
451                                                x = ((signed int)dot[i].x + ox) / 2;
452                                                y = dot[i].y;
453
454                                                wm->ir.ax = x;
455                                                wm->ir.ay = y;
456                                                wm->orient.angle.yaw = calc_yaw(&wm->ir);
457
458                                                if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
459                                                        ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
460                                                        wm->ir.x = x;
461                                                        wm->ir.y = y;
462                                                }
463
464                                                break;
465                                        }
466                                }
467                        }
468
469                        break;
470                }
471                case 2:
472                case 3:
473                case 4:
474                {
475                        /*
476                         *      Two (or more) dots known and seen.
477                         *      Average them together to estimate the true location.
478                         */
479                        int x, y;
480                        wm->ir.state = 2;
481
482                        fix_rotated_ir_dots(wm->ir.dot, roll);
483
484                        /* if there is at least 1 new dot, reorder them all */
485                        if (wm->ir.num_dots > last_num_dots) {
486                                reorder_ir_dots(dot);
487                                wm->ir.x = 0;
488                                wm->ir.y = 0;
489                        }
490
491                        wm->ir.distance = ir_distance(dot);
492                        wm->ir.z = 1023 - wm->ir.distance;
493
494                        get_ir_dot_avg(wm->ir.dot, &x, &y);
495
496                        wm->ir.ax = x;
497                        wm->ir.ay = y;
498                        wm->orient.angle.yaw = calc_yaw(&wm->ir);
499
500                        if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
501                                ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
502                                wm->ir.x = x;
503                                wm->ir.y = y;
504                        }
505
506                        break;
507                }
508                default:
509                {
510                        break;
511                }
512        }
513
514        #ifdef WITH_WIIC_DEBUG
515        {
516        int ir_level;
517        WIIC_GET_IR_SENSITIVITY(wm, &ir_level);
518        WIIC_DEBUG("IR sensitivity: %i", ir_level);
519        WIIC_DEBUG("IR visible dots: %i", wm->ir.num_dots);
520        for (i = 0; i < 4; ++i)
521                if (dot[i].visible)
522                        WIIC_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y);
523        WIIC_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y);
524        }
525        #endif
526}
527
528
529
530/**
531 *      @brief Fix the rotation of the IR dots.
532 *
533 *      @param dot              An array of 4 ir_dot_t objects.
534 *      @param ang              The roll angle to correct by (-180, 180)
535 *
536 *      If there is roll then the dots are rotated
537 *      around the origin and give a false cursor
538 *      position. Correct for the roll.
539 *
540 *      If the accelerometer is off then obviously
541 *      this will not do anything and the cursor
542 *      position may be inaccurate.
543 */
544static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) {
545        float s, c;
546        int x, y;
547        int i;
548
549        if (!ang) {
550                for (i = 0; i < 4; ++i) {
551                        dot[i].x = dot[i].rx;
552                        dot[i].y = dot[i].ry;
553                }
554                return;
555        }
556
557        s = sin(DEGREE_TO_RAD(ang));
558        c = cos(DEGREE_TO_RAD(ang));
559
560        /*
561         *      [ cos(theta)  -sin(theta) ][ ir->rx ]
562         *      [ sin(theta)  cos(theta)  ][ ir->ry ]
563         */
564
565        for (i = 0; i < 4; ++i) {
566                if (!dot[i].visible)
567                        continue;
568
569                x = dot[i].rx - (1024/2);
570                y = dot[i].ry - (768/2);
571
572                dot[i].x = (c * x) + (-s * y);
573                dot[i].y = (s * x) + (c * y);
574
575                dot[i].x += (1024/2);
576                dot[i].y += (768/2);
577        }
578}
579
580
581/**
582 *      @brief Average IR dots.
583 *
584 *      @param dot              An array of 4 ir_dot_t objects.
585 *      @param x                [out] Average X
586 *      @param y                [out] Average Y
587 */
588static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) {
589        int vis = 0, i = 0;
590
591        *x = 0;
592        *y = 0;
593
594        for (; i < 4; ++i) {
595                if (dot[i].visible) {
596                        *x += dot[i].x;
597                        *y += dot[i].y;
598                        ++vis;
599                }
600        }
601
602        *x /= vis;
603        *y /= vis;
604}
605
606
607/**
608 *      @brief Reorder the IR dots.
609 *
610 *      @param dot              An array of 4 ir_dot_t objects.
611 */
612static void reorder_ir_dots(struct ir_dot_t* dot) {
613        int i, j, order;
614
615        /* reset the dot ordering */
616        for (i = 0; i < 4; ++i)
617                dot[i].order = 0;
618
619        for (order = 1; order < 5; ++order) {
620                i = 0;
621
622                for (; !dot[i].visible || dot[i].order; ++i)
623                if (i > 4)
624                        return;
625
626                for (j = 0; j < 4; ++j) {
627                        if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x))
628                                i = j;
629                }
630
631                dot[i].order = order;
632        }
633}
634
635
636/**
637 *      @brief Calculate the distance between the first 2 visible IR dots.
638 *
639 *      @param dot              An array of 4 ir_dot_t objects.
640 */
641static float ir_distance(struct ir_dot_t* dot) {
642        int i1, i2;
643        int xd, yd;
644
645        for (i1 = 0; i1 < 4; ++i1)
646                if (dot[i1].visible)
647                        break;
648        if (i1 == 4)
649                return 0.0f;
650
651        for (i2 = i1+1; i2 < 4; ++i2)
652                if (dot[i2].visible)
653                        break;
654        if (i2 == 4)
655                return 0.0f;
656
657        xd = dot[i2].x - dot[i1].x;
658        yd = dot[i2].y - dot[i1].y;
659
660        return sqrt(xd*xd + yd*yd);
661}
662
663
664/**
665 *      @brief Correct for the IR bounding box.
666 *
667 *      @param x                [out] The current X, it will be updated if valid.
668 *      @param y                [out] The current Y, it will be updated if valid.
669 *      @param aspect   Aspect ratio of the screen.
670 *      @param offset_x The X offset of the bounding box.
671 *      @param offset_y The Y offset of the bounding box.
672 *
673 *      @return Returns 1 if the point is valid and was updated.
674 *
675 *      Nintendo was smart with this bit. They sacrifice a little
676 *      precision for a big increase in usability.
677 */
678static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) {
679        int x0, y0;
680        int xs, ys;
681
682        if (aspect == WIIC_ASPECT_16_9) {
683                xs = WM_ASPECT_16_9_X;
684                ys = WM_ASPECT_16_9_Y;
685        } else {
686                xs = WM_ASPECT_4_3_X;
687                ys = WM_ASPECT_4_3_Y;
688        }
689
690        x0 = ((1024 - xs) / 2) + offset_x;
691        y0 = ((768 - ys) / 2) + offset_y;
692
693        if ((*x >= x0)
694                && (*x <= (x0 + xs))
695                && (*y >= y0)
696                && (*y <= (y0 + ys)))
697        {
698                *x -= offset_x;
699                *y -= offset_y;
700
701                return 1;
702        }
703
704        return 0;
705}
706
707
708/**
709 *      @brief Interpolate the point to the user defined virtual screen resolution.
710 */
711static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy) {
712        int xs, ys;
713
714        if (aspect == WIIC_ASPECT_16_9) {
715                xs = WM_ASPECT_16_9_X;
716                ys = WM_ASPECT_16_9_Y;
717        } else {
718                xs = WM_ASPECT_4_3_X;
719                ys = WM_ASPECT_4_3_Y;
720        }
721
722        *x -= ((1024-xs)/2);
723        *y -= ((768-ys)/2);
724
725        *x = (*x / (float)xs) * vx;
726        *y = (*y / (float)ys) * vy;
727}
728
729
730/**
731 *      @brief Calculate yaw given the IR data.
732 *
733 *      @param ir       IR data structure.
734 */
735float calc_yaw(struct ir_t* ir) {
736        float x;
737
738        x = ir->ax - 512;
739        x = x * (ir->z / 1024.0f);
740
741        return RAD_TO_DEGREE( atanf(x / ir->z) );
742}
Note: See TracBrowser for help on using the repository browser.