Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
304 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
427 farthen 6
//    This file is part of emCORE.
304 theseven 7
//
427 farthen 8
//    emCORE is free software: you can redistribute it and/or
304 theseven 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
//
427 farthen 13
//    emCORE is distributed in the hope that it will be useful,
304 theseven 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
427 farthen 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
304 theseven 20
//
21
//
22
 
391 theseven 23
 
304 theseven 24
#include "global.h"
25
#include "clickwheel.h"
26
#include "button.h"
27
#include "thread.h"
28
#include "timer.h"
29
#include "s5l8702.h"
30
#include "contextswitch.h"
31
 
32
 
33
static struct wakeup clickwheel_wakeup IBSS_ATTR;
34
static volatile uint32_t clickwheel_packet IBSS_ATTR;
429 theseven 35
static struct scheduler_thread clickwheel_thread_handle;
36
static uint32_t clickwheel_stack[0x100] STACK_ATTR;
304 theseven 37
static bool oldtouched IBSS_ATTR;
38
static int oldpos IBSS_ATTR;
39
static int oldbuttons IBSS_ATTR;
40
static uint32_t lastpacket IBSS_ATTR;
41
static int packets IBSS_ATTR;
42
static int collect IBSS_ATTR;
43
static int lastdiff IBSS_ATTR;
44
 
45
 
46
void clickwheel_thread(void) ICODE_ATTR;
47
void clickwheel_thread()
48
{
49
    int i;
50
    while (true)
51
    {
52
        wakeup_wait(&clickwheel_wakeup, TIMEOUT_BLOCK);
53
        DEBUGF("Got clickwheel packet");
54
        uint32_t mode = enter_critical_section();
55
        uint32_t data = clickwheel_packet;
56
        leave_critical_section(mode);
57
        DEBUGF("Acquired clickwheel packet: %08X", data);
58
        if ((data & 0x800000FF) == 0x8000001A)
59
        {
60
            int newbuttons = (data >> 8) & 0x1f;
61
            int newpos = (data >> 16) & 0xff;
62
            bool newtouched = (data & 0x40000000) ? true : false;
63
 
64
            DEBUGF("This is a change packet, button state: %02X, position: %02d, touched: %d",
65
                   newbuttons, newpos, newtouched);
66
            int buttonschanged = oldbuttons ^ newbuttons;
67
            DEBUGF("Changed buttons: %02X", buttonschanged);
68
            for (i = 0; i < 5; i++)
69
                if ((buttonschanged >> i) & 1)
70
                {
71
                    if ((oldbuttons >> i) & 1) button_send_event(BUTTON_RELEASE, i, 0);
72
                    else button_send_event(BUTTON_PRESS, i, 0);
73
                }
74
 
75
            if (newtouched)
76
            {
390 theseven 77
                int distance = 0;
304 theseven 78
                if (!oldtouched) button_send_event(WHEEL_TOUCH, 0, newpos);
390 theseven 79
                else distance = newpos - oldpos;
304 theseven 80
                button_send_event(WHEEL_POSITION, 0, newpos);
81
                DEBUGF("Time since last packet: %d microseconds", USEC_TIMER - lastpacket);
82
                if (TIMEOUT_EXPIRED(lastpacket, 200000))
83
                {
84
                    DEBUGF("Resetting accel due to timeout");
85
                    packets = 10;
86
                }
87
                else if (lastdiff * distance < 0)
88
                {
89
                    DEBUGF("Resetting accel due to direction change");
90
                    packets = 10;
91
                }
92
                else packets++;
93
                lastdiff = distance;
94
                if (packets > 200) packets = 200;
95
                if (distance < -48) distance += 96;
96
                else if (distance > 48) distance -= 96;
97
                DEBUGF("Wheel moved %d units without accel", distance);
503 theseven 98
                button_send_event(WHEEL_MOVED, 0, distance);
304 theseven 99
                DEBUGF("Wheel moved %d units with accel", distance * packets);
503 theseven 100
                button_send_event(WHEEL_MOVED_ACCEL, 0, distance * packets);
304 theseven 101
                collect += distance * packets;
102
                enum button_event e = collect > 0 ? WHEEL_FORWARD : WHEEL_BACKWARD;
103
                int data = (collect > 0 ? collect : -collect) / 128;
104
                if (data) button_send_event(e, 0, data);
105
                collect %= 128;
106
                DEBUGF("Wheel moved %d steps (%d left)", data, collect);
107
            }
108
            else if (oldtouched)
109
            {
110
                DEBUGF("Wheel was untouched");
111
                button_send_event(WHEEL_POSITION, 0, newpos);
112
                button_send_event(WHEEL_UNTOUCH, 0, newpos);
113
                collect = 0;
114
                packets = 0;
115
                lastdiff = 0;
116
            }
117
 
118
            oldbuttons = newbuttons;
119
            oldpos = newpos;
120
            oldtouched = newtouched;
121
            lastpacket = USEC_TIMER;
122
        }
123
        else if ((data & 0x8000FFFF) == 0x8000023A)
124
        {
125
            if (data & 0x1F0000) oldbuttons = (data >> 16) & 0x1F;
126
            DEBUGF("This is an init packet, button state: %02X", oldbuttons);
127
        }
128
    }
129
}
130
 
131
 
132
void clickwheel_init()
133
{
134
    wakeup_init(&clickwheel_wakeup);
135
    oldtouched = false;
136
    oldbuttons = 0;
137
    lastpacket = 0;
138
    collect = 0;
139
    lastdiff = 0;
140
    interrupt_enable(IRQ_WHEEL, true);
141
    PUNA(2) &= ~2;
142
    PCON(14) = (PCON(14) & ~0xffff0000) | 0x22220000;
143
    WHEELINT = 7;
144
    WHEEL10 = 7;
145
    WHEEL00 = 0x380000;
146
    WHEEL08 = 0x20000;
147
    do
148
    {
149
        WHEELTX = 0x8001052A;
150
        while (WHEEL0C & 4) yield();
151
        WHEEL04 = 1;
152
        sleep(20000);
153
    }
154
    while (WHEEL0C & 4);
429 theseven 155
    thread_create(&clickwheel_thread_handle, "Clickwheel dispatcher",
156
                  clickwheel_thread, clickwheel_stack,
304 theseven 157
                  sizeof(clickwheel_stack), OS_THREAD, 200, true);
158
}
159
 
160
void INT_WHEEL(void) ICODE_ATTR;
161
void INT_WHEEL()
162
{
163
    uint32_t events = WHEELINT;
164
    if (events & 4) WHEELINT = 4;
165
    if (events & 2) WHEELINT = 2;
166
    if (events & 1)
167
    {
168
        clickwheel_packet = WHEELRX;
169
        wakeup_signal(&clickwheel_wakeup);
170
        WHEELINT = 1;
171
    }
172
}
173
 
174
uint32_t clickwheel_get_state()
175
{
176
    return (oldtouched << 15) | (oldpos << 8) | oldbuttons;
177
}