Example #1
0
void button_init(void)
{
    /* Init used objects first */
    queue_init(&button_queue, true);

#ifdef HAVE_BUTTON_DATA
    int temp;
#endif
    /* hardware inits */
    button_init_device();

#ifdef HAVE_BUTTON_DATA
    button_read(&temp);
    lastbtn = button_read(&temp);
#else
    button_read();
    lastbtn = button_read();
#endif
    
    reset_poweroff_timer();

#ifdef HAVE_LCD_BITMAP
    flipped = false;
#endif
#ifdef HAVE_BACKLIGHT
    filter_first_keypress = false;
#ifdef HAVE_REMOTE_LCD
    remote_filter_first_keypress = false;
#endif    
#endif
#ifdef HAVE_TOUCHSCREEN
    last_touchscreen_touch = 0xffff;
#endif    
    /* Start polling last */
    tick_add_task(button_tick);
}
Example #2
0
static void button_tick(void)
{
    static int count = 0;
    static int repeat_speed = REPEAT_INTERVAL_START;
    static int repeat_count = 0;
    static bool repeat = false;
    static bool post = false;
#ifdef HAVE_BACKLIGHT
    static bool skip_release = false;
#ifdef HAVE_REMOTE_LCD
    static bool skip_remote_release = false;
#endif
#endif
    int diff;
    int btn;
#ifdef HAVE_BUTTON_DATA
    int data = 0;
#else
    const int data = 0;
#endif

#if defined(HAS_SERIAL_REMOTE) && !defined(SIMULATOR)
    /* Post events for the remote control */
    btn = remote_control_rx();
    if(btn)
        button_try_post(btn, 0);
#endif

#ifdef HAVE_BUTTON_DATA
    btn = button_read(&data);
#else
    btn = button_read();
#endif
#if defined(HAVE_HEADPHONE_DETECTION)
    if (headphones_inserted() != phones_present)
    {
        /* Use the autoresetting oneshot to debounce the detection signal */
        phones_present = !phones_present;
        timeout_register(&hp_detect_timeout, btn_detect_callback,
                         HZ/2, phones_present);
    }
#endif

    /* Find out if a key has been released */
    diff = btn ^ lastbtn;
    if(diff && (btn & diff) == 0)
    {
#ifdef HAVE_BACKLIGHT
#ifdef HAVE_REMOTE_LCD
        if(diff & BUTTON_REMOTE)
            if(!skip_remote_release)
                button_try_post(BUTTON_REL | diff, data);
            else
                skip_remote_release = false;
        else
#endif
            if(!skip_release)
                button_try_post(BUTTON_REL | diff, data);
            else
                skip_release = false;
#else
        button_try_post(BUTTON_REL | diff, data);
#endif
    }
    else
    {
        if ( btn )
        {
            /* normal keypress */
            if ( btn != lastbtn )
            {
                post = true;
                repeat = false;
                repeat_speed = REPEAT_INTERVAL_START;
            }
            else /* repeat? */
            {
                if ( repeat )
                {
                    if (!post)
                        count--;
                    if (count == 0) {
                        post = true;
                        /* yes we have repeat */
                        if (repeat_speed > REPEAT_INTERVAL_FINISH)
                            repeat_speed--;
                        count = repeat_speed;

                        repeat_count++;

                        /* Send a SYS_POWEROFF event if we have a device
                           which doesn't shut down easily with the OFF
                           key */
#ifdef HAVE_SW_POWEROFF
                        if ((btn & POWEROFF_BUTTON
#ifdef RC_POWEROFF_BUTTON
                                    || btn == RC_POWEROFF_BUTTON
#endif
                                    ) &&
#if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING)
                                !charger_inserted() &&
#endif
                                repeat_count > POWEROFF_COUNT)
                        {
                            /* Tell the main thread that it's time to
                               power off */
                            sys_poweroff();

                            /* Safety net for players without hardware
                               poweroff */
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
                            if(repeat_count > POWEROFF_COUNT * 10)
                                power_off();
#endif
                        }
#endif
                    }
                }
                else
                {
                    if (count++ > REPEAT_START)
                    {
                        post = true;
                        repeat = true;
                        repeat_count = 0;
                        /* initial repeat */
                        count = REPEAT_INTERVAL_START;
                    }
#ifdef HAVE_TOUCHSCREEN
                    else if (lastdata != data && btn == lastbtn)
                    {   /* only coordinates changed, post anyway */
                        if (touchscreen_get_mode() == TOUCHSCREEN_POINT)
                            post = true;
                    }
#endif
                }
            }
            if ( post )
            {
                if (repeat)
                {
                    /* Only post repeat events if the queue is empty,
                     * to avoid afterscroll effects. */
                    if (button_try_post(BUTTON_REPEAT | btn, data))
                    {
#ifdef HAVE_BACKLIGHT
#ifdef HAVE_REMOTE_LCD
                        skip_remote_release = false;
#endif
                        skip_release = false;
#endif
                        post = false;
                    }
                }
                else
                {
#ifdef HAVE_BACKLIGHT
#ifdef HAVE_REMOTE_LCD
                    if (btn & BUTTON_REMOTE) {
                        if (!remote_filter_first_keypress 
                            || is_remote_backlight_on(false)
#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
                            || (remote_type()==REMOTETYPE_H300_NONLCD)
#endif
                            )
                            button_try_post(btn, data);
                        else
                            skip_remote_release = true;
                    }
                    else
#endif
                        if (!filter_first_keypress || is_backlight_on(false)
#if BUTTON_REMOTE
                                || (btn & BUTTON_REMOTE)
#endif
                           )
                            button_try_post(btn, data);
                        else
                            skip_release = true;
#else /* no backlight, nothing to skip */
                    button_try_post(btn, data);
#endif
                    post = false;
                }
#ifdef HAVE_REMOTE_LCD
                if(btn & BUTTON_REMOTE)
                    remote_backlight_on();
                else
#endif
                {
                    backlight_on();
#ifdef HAVE_BUTTON_LIGHT
                    buttonlight_on();
#endif
                }

                reset_poweroff_timer();
            }
        }
        else
        {
            repeat = false;
            count = 0;
        }
    }
    lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT);
#ifdef HAVE_BUTTON_DATA
    lastdata = data;
#endif
}
static void handle_scroll_wheel(int new_scroll)
{
    static const signed char scroll_state[4][4] = {
        {0, 1, -1, 0},
        {-1, 0, 0, 1},
        {1, 0, 0, -1},
        {0, -1, 1, 0}
    };

    static int prev_scroll = -1;
    static int direction = 0;
    static int count = 0;
    static long next_backlight_on = 0;

    int wheel_keycode = BUTTON_NONE;
    int scroll;

    static unsigned long wheel_delta = 1ul << 24;
    static unsigned long wheel_velocity = 0;
    static unsigned long last_wheel_usec = 0;
    static int prev_keypost = BUTTON_NONE;

    unsigned long usec;
    unsigned long v;

    if ( prev_scroll == -1 ) {
        prev_scroll = new_scroll;
        return;
    }
    
    scroll = scroll_state[prev_scroll][new_scroll];
    prev_scroll = new_scroll;

    if (direction != scroll) {
        /* direction reversal or was hold - reset all */
        direction = scroll;
        count = 0;
        prev_keypost = BUTTON_NONE;
        wheel_velocity = 0;
        wheel_delta = 1ul << 24;
        return;
    }

   /* poke backlight every 1/4s of activity */
    if (TIME_AFTER(current_tick, next_backlight_on)) {
        backlight_on();
        reset_poweroff_timer();
        next_backlight_on = current_tick + HZ/4;
    }

    if (++count < WHEEL_BASE_SENSITIVITY)
        return;

    count = 0;
    /* Mini 1st Gen wheel has inverse direction mapping
     * compared to 1st..3rd Gen wheel. */
    switch (direction) {
        case 1:
            wheel_keycode = BUTTON_SCROLL_FWD;
            break;
        case -1:
            wheel_keycode = BUTTON_SCROLL_BACK;
            break;
        default:
            /* only happens if we get out of sync */
            break;
    }

    /* have a keycode */

    usec = USEC_TIMER;
    v = usec - last_wheel_usec;

    /* calculate deg/s based upon sensitivity-adjusted interrupt period */

    if ((long)v <= 0) {
        /* timer wrapped (no activity for awhile), skip acceleration */
        v = 0;
        wheel_delta = 1ul << 24;
    }
    else {
        if (v > 0xfffffffful/WHEELCLICKS_PER_ROTATION) {
            v = 0xfffffffful/WHEELCLICKS_PER_ROTATION; /* check overflow below */
        }

        v = 360000000ul*WHEEL_BASE_SENSITIVITY / (v*WHEELCLICKS_PER_ROTATION);

        if (v > 0xfffffful)
            v = 0xfffffful; /* limit to 24 bits */
    }

    if (v < WHEEL_SMOOTHING_VELOCITY) {
        /* very slow - no smoothing */
        wheel_velocity = v;
        /* ensure backlight never gets stuck for an extended period if tick
         * wrapped such that next poke is very far ahead */
        next_backlight_on = current_tick - 1;
    }
    else {
        /* some velocity filtering to smooth things out */
        wheel_velocity = (7*wheel_velocity + v) / 8;
    }

    if (queue_empty(&button_queue)) {
        int key = wheel_keycode;

        if (v >= WHEEL_REPEAT_VELOCITY && prev_keypost == key) {
            /* quick enough and same key is being posted more than once in a
             * row - generate repeats - use unsmoothed v to guage */
            key |= BUTTON_REPEAT;
        }

        prev_keypost = wheel_keycode;

        /* post wheel keycode with wheel data */
        queue_post(&button_queue, key,
                   (wheel_velocity >= WHEEL_ACCEL_START ? (1ul << 31) : 0)
                    | wheel_delta | wheel_velocity);
        /* message posted - reset delta */
        wheel_delta = 1ul << 24;
    }
    else {
        /* skipped post - increment delta and limit to 7 bits */
        wheel_delta += 1ul << 24;

        if (wheel_delta > (0x7ful << 24))
            wheel_delta = 0x7ful << 24;
    }

    last_wheel_usec = usec;
}