| 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 | +}
|