Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
132 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emBIOS is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "clickwheel.h"
26
#include "button.h"
27
#include "thread.h"
28
#include "timer.h"
29
#include "s5l8701.h"
30
#include "contextswitch.h"
31
 
32
 
33
static struct wakeup clickwheel_wakeup IBSS_ATTR;
34
static volatile uint32_t clickwheel_packet IBSS_ATTR;
35
static uint32_t clickwheel_stack[0x100];
36
static bool oldtouched IBSS_ATTR;
37
static int oldpos IBSS_ATTR;
38
static int oldbuttons IBSS_ATTR;
39
static uint32_t lastpacket IBSS_ATTR;
40
static int packets IBSS_ATTR;
41
 
42
 
43
void clickwheel_thread(void) ICODE_ATTR;
44
void clickwheel_thread()
45
{
46
    int i;
47
    while (true)
48
    {
49
        wakeup_wait(&clickwheel_wakeup, TIMEOUT_BLOCK);
50
        uint32_t mode = enter_critical_section();
51
        uint32_t data = clickwheel_packet;
52
        leave_critical_section(mode);
53
        if ((data & 0x800000FF) == 0x8000001A)
54
        {
55
            int newbuttons = (data >> 8) & 0x1f;
56
            int newpos = (data >> 16) & 0xff;
57
            bool newtouched = (data & 0x40000000) ? true : false;
58
 
59
            int buttonschanged = oldbuttons ^ newbuttons;
60
            for (i = 0; i < 5; i++)
61
                if ((buttonschanged >> i) & 1)
62
                {
63
                    if ((oldbuttons >> i) & 1) button_send_event(BUTTON_RELEASE, i, 0);
64
                    else button_send_event(BUTTON_PRESS, i, 0);
65
                }
66
 
67
            if (newtouched)
68
            {
69
                if (!oldtouched) button_send_event(WHEEL_TOUCH, 0, newpos);
70
                button_send_event(WHEEL_POSITION, 0, newpos);
71
                if (TIMEOUT_EXPIRED(lastpacket, 200000)) packets = 5;
72
                else packets++;
73
                if (packets > 100) packets = 100;
74
                int distance = newpos - oldpos;
75
                if (distance < -48) distance += 96;
76
                else if (distance > 48) distance -= 96;
77
                distance *= packets;
78
                button_send_event(WHEEL_MOVED, 0, distance);
79
                enum button_event e = distance > 0 ? WHEEL_FORWARD : WHEEL_BACKWARD;
80
                distance = distance > 0 ? distance : -distance;
81
                button_send_event(e, 0, distance >> 6);
82
            }
83
            else if (oldtouched)
84
            {
85
                button_send_event(WHEEL_POSITION, 0, newpos);
86
                button_send_event(WHEEL_UNTOUCH, 0, newpos);
87
            }
88
 
89
            oldbuttons = newbuttons;
90
            oldpos = newpos;
91
            oldtouched = newtouched;
92
            lastpacket = USEC_TIMER;
93
        }
94
        else if ((data & 0x8000FFFF) == 0x8000023A && (data & 0x1F0000))
95
            oldbuttons = (data >> 16) & 0x1F;
96
    }
97
}
98
 
99
 
100
void clickwheel_init()
101
{
102
    wakeup_init(&clickwheel_wakeup);
103
    oldtouched = false;
104
    oldbuttons = 0;
105
    lastpacket = 0;
106
    INTMSK |= 1 << IRQ_WHEEL;
107
    PWRCON(1) &= ~1;
108
    PCON15 = (PCON15 & ~0xFFFF0000) | 0x22220000;
109
    PUNK15 = 0xF0;
110
    WHEEL08 = 0x3A980;
111
    WHEEL00 = 0x280000;
112
    WHEEL10 = 3;
113
    PCON10 = (PCON10 & ~0xFF0) | 0x10;
114
    PDAT10 |= 2;
115
    WHEELTX = 0x8000023A;
116
    WHEEL04 |= 1;
117
    PDAT10 &= ~2;
118
    thread_create("Clickwheel dispatcher", clickwheel_thread, clickwheel_stack,
119
                  sizeof(clickwheel_stack), OS_THREAD, 200, true);
120
}
121
 
122
void INT_WHEEL(void) ICODE_ATTR;
123
void INT_WHEEL()
124
{
125
    uint32_t events = WHEELINT;
126
    if (events & 4) WHEELINT = 4;
127
    if (events & 2) WHEELINT = 2;
128
    if (events & 1)
129
    {
130
        clickwheel_packet = WHEELRX;
131
        wakeup_signal(&clickwheel_wakeup);
132
        WHEELINT = 1;
133
    }
134
}
135
 
136
uint32_t clickwheel_get_state()
137
{
138
    return (oldtouched << 15) | (oldpos << 8) | oldbuttons;
139
}