| Index: embios/trunk/target/ipodnano3g/targetinit.c | 
| — | — | @@ -0,0 +1,127 @@ | 
|  | 2 | +// | 
|  | 3 | +// | 
|  | 4 | +//    Copyright 2010 TheSeven | 
|  | 5 | +// | 
|  | 6 | +// | 
|  | 7 | +//    This file is part of emBIOS. | 
|  | 8 | +// | 
|  | 9 | +//    emBIOS is free software: you can redistribute it and/or | 
|  | 10 | +//    modify it under the terms of the GNU General Public License as | 
|  | 11 | +//    published by the Free Software Foundation, either version 2 of the | 
|  | 12 | +//    License, or (at your option) any later version. | 
|  | 13 | +// | 
|  | 14 | +//    emBIOS is distributed in the hope that it will be useful, | 
|  | 15 | +//    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 16 | +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | 17 | +//    See the GNU General Public License for more details. | 
|  | 18 | +// | 
|  | 19 | +//    You should have received a copy of the GNU General Public License along | 
|  | 20 | +//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 21 | +// | 
|  | 22 | +// | 
|  | 23 | + | 
|  | 24 | + | 
|  | 25 | +#include "global.h" | 
|  | 26 | +#include "clickwheel.h" | 
|  | 27 | + | 
|  | 28 | + | 
|  | 29 | +#define sysi ((uint8_t*)0x2203fdf0) | 
|  | 30 | +#define sysiword ((uint32_t*)0x2203fdf0) | 
|  | 31 | + | 
|  | 32 | + | 
|  | 33 | +void targetinit_late() | 
|  | 34 | +{ | 
|  | 35 | +    int i; | 
|  | 36 | + | 
|  | 37 | +    clickwheel_init(); | 
|  | 38 | + | 
|  | 39 | +/*    uint32_t scfg_size = norword[0x401]; | 
|  | 40 | +    uint32_t scfg_entrycount = norword[0x405]; | 
|  | 41 | +    if (norword[0x400] == 0x53436667 && scfg_size <= 0x1000 | 
|  | 42 | +     && scfg_entrycount * 0x14 + 0x18 == scfg_size) | 
|  | 43 | +    { | 
|  | 44 | +        memset(sysi, 0, 0x104); | 
|  | 45 | +        sysiword[0] = 0x53797349; | 
|  | 46 | +        sysiword[1] = 0x104; | 
|  | 47 | +        sysiword[0x21] = 0x100000; | 
|  | 48 | +        for (i = 0; i < scfg_entrycount; i++) | 
|  | 49 | +            switch (norword[0x406 + i * 5]) | 
|  | 50 | +            { | 
|  | 51 | +                case 0x48774e6d: // HwNm | 
|  | 52 | +                    memcpy(&sysi[0x08], &norword[0x406 + i * 5 + 1], 16); | 
|  | 53 | +                    break; | 
|  | 54 | +                case 0x48775672: // HwVr | 
|  | 55 | +                    if (norword[0x406 + i * 5 + 1] == 0) | 
|  | 56 | +                        sysiword[0x21] = norword[0x406 + i * 5 + 2]; | 
|  | 57 | +                    break; | 
|  | 58 | +                case 0x53724e6d: // SrNm | 
|  | 59 | +                    memcpy(&sysi[0x18], &norword[0x406 + i * 5 + 1], 16); | 
|  | 60 | +                    break; | 
|  | 61 | +                case 0x46774964: // FwId | 
|  | 62 | +                    if (nor[0x1018 + i * 0x14 + 7] == 0) | 
|  | 63 | +                    { | 
|  | 64 | +                        memcpy(&sysi[0x38], &norword[0x406 + i * 5 + 2], 3); | 
|  | 65 | +                        sysi[0x3b] = 2; | 
|  | 66 | +                        sysiword[0xf] = 0xa2700; | 
|  | 67 | +                    } | 
|  | 68 | +                    else memcpy(&sysi[0x38], &norword[0x406 + i * 5 + 2], 8); | 
|  | 69 | +                    memset(&sysi[0x40], 10, 0); | 
|  | 70 | +                    break; | 
|  | 71 | +                case 0x556e7443: // UntC | 
|  | 72 | +                    memcpy(&sysi[0xbc], &norword[0x406 + i * 5 + 1], 16); | 
|  | 73 | +                    break; | 
|  | 74 | +                case 0x52746341: // RtcA | 
|  | 75 | +                    if (norword[0x406 + i * 5 + 1] == 1) | 
|  | 76 | +                        sysiword[0x80] = norword[0x406 + i * 5 + 2]; | 
|  | 77 | +                    break; | 
|  | 78 | +                case 0x42747279: // Btry | 
|  | 79 | +                    if (norword[0x406 + i * 5 + 1] == 1) | 
|  | 80 | +                        memcpy(&sysi[0x5c], &norword[0x406 + i * 5 + 2], 12); | 
|  | 81 | +                    break; | 
|  | 82 | +                case 0x5265676e: // Regn | 
|  | 83 | +                    if (nor[0x1018 + i * 0x14 + 4] == 1 && nor[0x1018 + i * 0x14 + 5] == 0) | 
|  | 84 | +                        memcpy(&sysi[0x92], &norword[0x406 + i * 5 + 2], 4); | 
|  | 85 | +                    break; | 
|  | 86 | +                case 0x4d6f6423: // Mod# | 
|  | 87 | +                    memcpy(&sysi[0x98], &norword[0x406 + i * 5 + 1], 16); | 
|  | 88 | +                    break; | 
|  | 89 | +                case 0x48774f31: // Hw01 | 
|  | 90 | +                    memcpy(&sysi[0xa8], &norword[0x406 + i * 5 + 1], 16); | 
|  | 91 | +                    break; | 
|  | 92 | +                case 0x436f6e74: // Cont | 
|  | 93 | +                    if (nor[0x1018 + i * 0x14 + 4] == 0 && nor[0x1018 + i * 0x14 + 5] == 0) | 
|  | 94 | +                    { | 
|  | 95 | +                        sysi[0xb8] = nor[0x1018 + i * 0x14 + 6]; | 
|  | 96 | +                        sysi[0xb9] = nor[0x1018 + i * 0x14 + 8]; | 
|  | 97 | +                    } | 
|  | 98 | +                    break; | 
|  | 99 | +                case 0x426b4c74: // BkLt | 
|  | 100 | +                    if (nor[0x1018 + i * 0x14 + 4] == 0xaa && nor[0x1018 + i * 0x14 + 5] == 0x55) | 
|  | 101 | +                    { | 
|  | 102 | +                        sysi[0xba] = nor[0x1018 + i * 0x14 + 6]; | 
|  | 103 | +                        sysi[0xbb] = nor[0x1018 + i * 0x14 + 8]; | 
|  | 104 | +                    } | 
|  | 105 | +                    break; | 
|  | 106 | +                case 0x44726d56: // DrmV | 
|  | 107 | +                    memcpy(&sysi[0xce], &norword[0x406 + i * 5 + 1], 16); | 
|  | 108 | +                    break; | 
|  | 109 | +            } | 
|  | 110 | +        sysiword[2] = 0x646f5069; | 
|  | 111 | +        sysiword[3] = 0x36334e20; | 
|  | 112 | +        sysi[0x88] = 0x4e; | 
|  | 113 | +        sysi[0x89] = 0x41; | 
|  | 114 | +#ifdef TARGET_ipodclassic | 
|  | 115 | +        sysiword[0x38] = 0x4000000; | 
|  | 116 | +#else | 
|  | 117 | +        sysiword[0x38] = 0x2000000; | 
|  | 118 | +#endif | 
|  | 119 | +        sysiword[0x39] = 0x8000000; | 
|  | 120 | +        sysiword[0x3a] = 0x40000; | 
|  | 121 | +        sysiword[0x3b] = 0x22000000; | 
|  | 122 | +        sysiword[0x3c] = 0x100000; | 
|  | 123 | +        sysiword[0x3d] = 0x24000000; | 
|  | 124 | +        sysiword[0x4a] = 0x53797349; | 
|  | 125 | +        sysiword[0x4b] = 0x2203fdf0; | 
|  | 126 | +    } | 
|  | 127 | +*/ | 
|  | 128 | +} | 
| Index: embios/trunk/target/ipodnano3g/clickwheel.c | 
| — | — | @@ -0,0 +1,175 @@ | 
|  | 2 | +// | 
|  | 3 | +// | 
|  | 4 | +//    Copyright 2010 TheSeven | 
|  | 5 | +// | 
|  | 6 | +// | 
|  | 7 | +//    This file is part of emBIOS. | 
|  | 8 | +// | 
|  | 9 | +//    emBIOS is free software: you can redistribute it and/or | 
|  | 10 | +//    modify it under the terms of the GNU General Public License as | 
|  | 11 | +//    published by the Free Software Foundation, either version 2 of the | 
|  | 12 | +//    License, or (at your option) any later version. | 
|  | 13 | +// | 
|  | 14 | +//    emBIOS is distributed in the hope that it will be useful, | 
|  | 15 | +//    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 16 | +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | 17 | +//    See the GNU General Public License for more details. | 
|  | 18 | +// | 
|  | 19 | +//    You should have received a copy of the GNU General Public License along | 
|  | 20 | +//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 21 | +// | 
|  | 22 | +// | 
|  | 23 | + | 
|  | 24 | + | 
|  | 25 | +#include "global.h" | 
|  | 26 | +#include "clickwheel.h" | 
|  | 27 | +#include "button.h" | 
|  | 28 | +#include "thread.h" | 
|  | 29 | +#include "timer.h" | 
|  | 30 | +#include "s5l8702.h" | 
|  | 31 | +#include "contextswitch.h" | 
|  | 32 | + | 
|  | 33 | + | 
|  | 34 | +static struct wakeup clickwheel_wakeup IBSS_ATTR; | 
|  | 35 | +static volatile uint32_t clickwheel_packet IBSS_ATTR; | 
|  | 36 | +static uint32_t clickwheel_stack[0x100]; | 
|  | 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 | +            { | 
|  | 77 | +                if (!oldtouched) button_send_event(WHEEL_TOUCH, 0, newpos); | 
|  | 78 | +                button_send_event(WHEEL_POSITION, 0, newpos); | 
|  | 79 | +                int distance = newpos - oldpos; | 
|  | 80 | +                DEBUGF("Time since last packet: %d microseconds", USEC_TIMER - lastpacket); | 
|  | 81 | +                if (TIMEOUT_EXPIRED(lastpacket, 200000)) | 
|  | 82 | +                { | 
|  | 83 | +                    DEBUGF("Resetting accel due to timeout"); | 
|  | 84 | +                    packets = 10; | 
|  | 85 | +                } | 
|  | 86 | +                else if (lastdiff * distance < 0) | 
|  | 87 | +                { | 
|  | 88 | +                    DEBUGF("Resetting accel due to direction change"); | 
|  | 89 | +                    packets = 10; | 
|  | 90 | +                } | 
|  | 91 | +                else packets++; | 
|  | 92 | +                lastdiff = distance; | 
|  | 93 | +                if (packets > 200) packets = 200; | 
|  | 94 | +                if (distance < -48) distance += 96; | 
|  | 95 | +                else if (distance > 48) distance -= 96; | 
|  | 96 | +                DEBUGF("Wheel moved %d units without accel", distance); | 
|  | 97 | +                DEBUGF("Wheel moved %d units with accel", distance * packets); | 
|  | 98 | +                button_send_event(WHEEL_MOVED, 0, distance); | 
|  | 99 | +                collect += distance * packets; | 
|  | 100 | +                enum button_event e = collect > 0 ? WHEEL_FORWARD : WHEEL_BACKWARD; | 
|  | 101 | +                int data = (collect > 0 ? collect : -collect) / 128; | 
|  | 102 | +                if (data) button_send_event(e, 0, data); | 
|  | 103 | +                collect %= 128; | 
|  | 104 | +                DEBUGF("Wheel moved %d steps (%d left)", data, collect); | 
|  | 105 | +            } | 
|  | 106 | +            else if (oldtouched) | 
|  | 107 | +            { | 
|  | 108 | +                DEBUGF("Wheel was untouched"); | 
|  | 109 | +                button_send_event(WHEEL_POSITION, 0, newpos); | 
|  | 110 | +                button_send_event(WHEEL_UNTOUCH, 0, newpos); | 
|  | 111 | +                collect = 0; | 
|  | 112 | +                packets = 0; | 
|  | 113 | +                lastdiff = 0; | 
|  | 114 | +            } | 
|  | 115 | + | 
|  | 116 | +            oldbuttons = newbuttons; | 
|  | 117 | +            oldpos = newpos; | 
|  | 118 | +            oldtouched = newtouched; | 
|  | 119 | +            lastpacket = USEC_TIMER; | 
|  | 120 | +        } | 
|  | 121 | +        else if ((data & 0x8000FFFF) == 0x8000023A) | 
|  | 122 | +        { | 
|  | 123 | +            if (data & 0x1F0000) oldbuttons = (data >> 16) & 0x1F; | 
|  | 124 | +            DEBUGF("This is an init packet, button state: %02X", oldbuttons); | 
|  | 125 | +        } | 
|  | 126 | +    } | 
|  | 127 | +} | 
|  | 128 | + | 
|  | 129 | + | 
|  | 130 | +void clickwheel_init() | 
|  | 131 | +{ | 
|  | 132 | +    wakeup_init(&clickwheel_wakeup); | 
|  | 133 | +    oldtouched = false; | 
|  | 134 | +    oldbuttons = 0; | 
|  | 135 | +    lastpacket = 0; | 
|  | 136 | +    collect = 0; | 
|  | 137 | +    lastdiff = 0; | 
|  | 138 | +    PWRCON(0) = 0; | 
|  | 139 | +    PWRCON(1) = 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); | 
|  | 155 | +    thread_create("Clickwheel dispatcher", clickwheel_thread, clickwheel_stack, | 
|  | 156 | +                  sizeof(clickwheel_stack), OS_THREAD, 200, true); | 
|  | 157 | +} | 
|  | 158 | + | 
|  | 159 | +void INT_WHEEL(void) ICODE_ATTR; | 
|  | 160 | +void INT_WHEEL() | 
|  | 161 | +{ | 
|  | 162 | +    uint32_t events = WHEELINT; | 
|  | 163 | +    if (events & 4) WHEELINT = 4; | 
|  | 164 | +    if (events & 2) WHEELINT = 2; | 
|  | 165 | +    if (events & 1) | 
|  | 166 | +    { | 
|  | 167 | +        clickwheel_packet = WHEELRX; | 
|  | 168 | +        wakeup_signal(&clickwheel_wakeup); | 
|  | 169 | +        WHEELINT = 1; | 
|  | 170 | +    } | 
|  | 171 | +} | 
|  | 172 | + | 
|  | 173 | +uint32_t clickwheel_get_state() | 
|  | 174 | +{ | 
|  | 175 | +    return (oldtouched << 15) | (oldpos << 8) | oldbuttons; | 
|  | 176 | +} |