Oops: clipping detection optimization broke pre-recording
[Rockbox.git] / www / notes.t
blob668b46fcfd94c9622c6598dcf07a17b659d188c6
1 #define _PAGE_ Jukebox notes
2 #include "head.t"
4 <center><table class=rockbox width=70%><tr><td>
5 <h2>Important:</h2>
6 <p>This page was written in late 2001/early 2002 during the initial reverse engineering of the hardware. Much of the information has since turned out to be wrong.
7 <p>View this page as a historical anecdote more than hard facts.
8 <p align=right>/Björn
9 </td></tr></table>
10 </center>
12 <h2>Exception vectors</h2>
14 <p>The first 0x200 bytes of the image appears to be the exception vector table.
15 The vectors are explained on pages 54 and 70-71 in the SH-1 Hardware Manual, 
17 <p>Here's the vector table for v5.03a:
19 <table border=1><tr>
20 <th>Vector</th><th>Address</th><th>Description/interrupt source</th>
21 <tr><td>  0</td><td>09000200</td><td>Power-on reset PC</td></tr>
22 <tr><td>  1</td><td>0903f2bc</td><td>Power-on reset SP</td></tr>
23 <tr><td>  2</td><td>09000200</td><td>Manual reset PC</td></tr>
24 <tr><td>  3</td><td>0903f2bc</td><td>Manual reset SP</td></tr>
25 <tr><td> 11</td><td>09000cac</td><td>NMI</td></tr>
26 <tr><td> 64</td><td>0900c060</td><td>IRQ0</td></tr>
27 <tr><td> 70</td><td>09004934</td><td>IRQ6</td></tr>
28 <tr><td> 78</td><td>09004a38</td><td>DMAC3 DEI3</td></tr>
29 <tr><td> 80</td><td>0900dfd0</td><td>ITU0 IMIA0</td></tr>
30 <tr><td> 88</td><td>0900df60</td><td>ITU2 IMIA2</td></tr>
31 <tr><td> 90</td><td>0900df60</td><td>ITU2 OVI2</td></tr>
32 <tr><td>104</td><td>09004918</td><td>SCI1 ERI1</td></tr>
33 <tr><td>105</td><td>090049e0</td><td>SCI1 Rxl1</td></tr>
34 <tr><td>109</td><td>09010270</td><td>A/D ITI</td></tr>
35 </table>
37 <p>From the use of address 0x0903f2bc as stack pointer, we can deduce
38 that the DRAM is located at address 0x09000000.
39 This is backed by the HW manual p102, which says that DRAM can only be at put on CS1, which is either 0x01000000 (8-bit) or 0x09000000 (16-bit).
41 <p>The vector table also corresponds with the fact that there is code at address 0x200 of the image file. 0x200 is thus the starting point for all code.
43 <h2>Port pins</h2>
44 <p><table><tr valign="top"><td>
46 <p>Port A pin function configuration summary:
47 <table border=1>
48 <tr><th>Pin</th><th>Function</th><th>Input/output</th><th>Initial value</th><th>Used for</th></tr>
49 <tr><td>PA0</td><td>i/o</td><td>Input</td><td></td><td>DC adapter detect</td></tr>
50 <tr><td>PA1</td><td>/RAS</td><td>Output</td><td></td><td>DRAM</td></tr>
51 <tr><td>PA2</td><td>/CS6</td><td>Output</td><td></td><td>IDE</td></tr>
52 <tr><td>PA3</td><td>/WAIT</td></tr>
53 <tr><td>PA4</td><td>/WR</td><td>Output</td><td></td><td>DRAM+Flash</td></tr>
54 <tr><td>PA5</td><td>i/o</td><td>Input</td><td></td><td>Key: ON</td></tr>
55 <tr><td>PA6</td><td>/RD</td><td>Output</td><td></td><td>IDE</td></tr>
56 <tr><td>PA7</td><td>i/o</td><td>Output</td><td>0</td></tr>
57 <tr><td>PA8</td><td>i/o</td><td>Output</td><td>0</td></tr>
58 <tr><td>PA9</td><td>i/o</td><td>Output</td><td>1</td></tr>
59 <tr><td>PA10</td><td>i/o</td><td>Output</td></tr>
60 <tr><td>PA11</td><td>i/o</td><td>Input</td><td></td><td>Key: STOP</td></tr>
61 <tr><td>PA12</td><td>/IRQ0</td></tr>
62 <tr><td>PA13</td><td>i/o</td></tr>
63 <tr><td>PA14</td><td>i/o</td><td>Output</td><td></td><td>Backlight</td></tr>
64 <tr><td>PA15</td><td>i/o</td><td>Input</td><td></td><td>USB cable detect</td></tr>
65 </table>
67 </td><td>
69 <p>Port B pin function configuration summary:
70 <table border=1>
71 <tr><th>Pin</th><th>Function</th><th>Input/output</th><th>Initial value</th><th>Used for</th></tr>
72 <tr><td>PB0</td><td>i/o</td><td>Output</td><td></td><td>LCD</td></tr>
73 <tr><td>PB1</td><td>i/o</td><td>Output</td><td></td><td>LCD</td></tr>
74 <tr><td>PB2</td><td>i/o</td><td>Output</td><td></td><td>LCD</td></tr>
75 <tr><td>PB3</td><td>i/o</td><td>Output</td><td></td><td>LCD</td></tr>
76 <tr><td>PB4</td><td>i/o</td><td>Input</td></tr>
77 <tr><td>PB5</td><td>i/o</td><td>Output</td><td>1</td><td>MAS WSEN</td></tr>
78 <tr><td>PB6</td><td>i/o</td><td>Output</td><td>0</td></tr>
79 <tr><td>PB7</td><td>i/o</td><td>Output</td><td></td><td>I²C data</td></tr>
80 <tr><td>PB8</td><td>i/o</td></tr>
81 <tr><td>PB9</td><td>TxD0</td><td>Output</td><td></td><td>MPEG</td></tr>
82 <tr><td>PB10</td><td>RxD1</td><td>Input</td></td><td></td><td>Remote</td></tr>
83 <tr><td>PB11</td><td>TxD1</td><td>Output</td><td></td><td>Remote?</td></tr>
84 <tr><td>PB12</td><td>SCK0</td><td>Output</td><td></td><td>MPEG</td></tr>
85 <tr><td>PB13</td><td>i/o</td><td>Output</td><td></td><td>I²C clock</td></tr>
86 <tr><td>PB14</td><td>/IRQ6</td><td>Input</td><td></td><td>MAS demand</td></tr>
87 <tr><td>PB15</td><td>i/o</td><td>Input</td><td></td><td>MAS MP3 frame sync</td></tr>
88 </table>
91 </td></tr></table>
93 <p>Port C pin function configuration summary:
94 <table border=1>
95 <tr><th>Pin</th><th>Function</th><th>Input/output</th><th>Used for</th></tr>
96 <tr><td>PC0</td><td>i/o</td><td>Input</td><td>Key: - / PREV</td></tr>
97 <tr><td>PC1</td><td>i/o</td><td>Input</td><td>Key: MENU</td></tr>
98 <tr><td>PC2</td><td>i/o</td><td>Input</td><td>Key: + / NEXT</td></tr>
99 <tr><td>PC3</td><td>i/o</td><td>Input</td><td>Key: PLAY</td></tr>
100 <tr><td>PC4</td><td>i/o</td><td>Input</td></tr>
101 <tr><td>PC5</td><td>i/o</td><td>Input</td></tr>
102 <tr><td>PC6</td><td>i/o</td><td>Input</td></tr>
103 <tr><td>PC7</td><td>i/o</td><td>Input</td></tr>
104 </table>
107 <h2>Labels</h2>
108 <p>Note: Everything is about v5.03a.
110 <ul>
111 <li>0x0200: Start point
112 <li>0x383d: Text: "Archos Jukebox hard drive is not bootable! Please insert a bootable floppy and press any key to try again" :-)
113 <li>0xc390: Address of "Update" string shown early on LCD.
114 <li>0xc8c0: Start of setup code
115 <li>0xc8c8: DRAM setup
116 <li>0xc4a0: Serial port 1 setup
117 <li>0xc40a: Port configuration setup
118 <li>0xe3bc: Character set conversion table
119 <li>0xfcd0: ITU setup
120 <li>0xc52a: Memory area #6 setup
121 <li>0x114b0: Start of menu strings
122 </ul>
125 <h2>Setup</h2>
127 <p>The startup code at 0x200 (0x09000200) naturally begins with setting up the system.
129 <h3>Vector Base Register</h3>
131 <p>The first thing the code does is setting the VBR, Vector Base Register,
132 and thus move the exception vector table from the internal ROM at address 0
133 to the DRAM at address 0x09000000:
135 <pre>
136 0x00000200: mov.l  @(0x02C,pc),r1  ; 0x0000022C (0x09000000)
137 0x00000202: ldc    r1,vbr
138 </pre>
140 <h3>Stack</h3>
142 <p>The next instruction loads r15 with the contents of 0x228, which is 0x0903f2bc. This is the stack pointer, which is used all over the code.
144 <pre>
145 0x00000204: mov.l  @(0x024,pc),r15 ; 0x00000228 (0x0903F2BC)
146 </pre>
148 <p>After that the code jumps to the hardware setup at 0xc8c0.
149 <pre>
150 0x00000206: mov.l  @(0x01C,pc),r0   ; 0x00000220 (0x0900C8C0)
151 0x00000208: jsr    @r0
152 </pre>
154 <h3>DRAM controller</h3>
156 <p>First up is DRAM setup, at 0xc8c8. It sets the memory controller registers:
158 <pre>
159 0x0000C8C8: mov.l  @(0x068,pc),r2  ; 0x0000C930 (0x05FFFFA8)
160 0x0000C8CA: mov.w  @(0x05A,pc),r1  ; 0x0000C924 (0x1E00)
161 0x0000C8CC: mov.l  @(0x068,pc),r7  ; 0x0000C934 (0x0F0001C0)
162 0x0000C8CE: mov.w  r1,@r2          ; 0x1e00 -> DCR
163 0x0000C8D0: mov.l  @(0x068,pc),r2  ; 0x0000C938 (0x05FFFFAC)
164 0x0000C8D2: mov.w  @(0x054,pc),r1  ; 0x0000C926 (0x5AB0)
165 0x0000C8D4: mov.w  r1,@r2          ; 0x5ab0 -> RCR
166 0x0000C8D6: mov.l  @(0x068,pc),r2  ; 0x0000C93C (0x05FFFFB2)
167 0x0000C8D8: mov.w  @(0x050,pc),r1  ; 0x0000C928 (0x9605)
168 0x0000C8DA: mov.w  r1,@r2          ; 0x9505 -> RTCOR
169 0x0000C8DC: mov.l  @(0x064,pc),r2  ; 0x0000C940 (0x05FFFFAE)
170 0x0000C8DE: mov.w  @(0x04C,pc),r1  ; 0x0000C92A (0xA518)
171 0x0000C8E0: mov.w  r1,@r2          ; 0xa518 -> RTCSR
172 </pre>
174 <h3>Serial port 0</h3>
176 <p>Code starting at 0x483c.
178 <p>As C code:
180 <table border><tr><td bgcolor="#a0d6e8">
181 <pre>
182 void setup_sci0(void)
184     /* set PB12 to output */
185     PBIOR |= 0x1000;
186 &nbsp;    
187     /* Disable serial port */
188     SCR0 = 0x00;
189 &nbsp;
190     /* Syncronous, 8N1, no prescale */
191     SMR0 = 0x80;
192 &nbsp;
193     /* Set baudrate 1Mbit/s */
194     BRR0 = 0x03;
195 &nbsp;
196     /* use SCK as serial clock output */
197     SCR0 = 0x01;
198 &nbsp;
199     /* Clear FER and PER */
200     SSR0 &= 0xe7;
201 &nbsp;
202     /* Set interrupt D priority to 0 */
203     IPRD &= 0x0ff0;
204 &nbsp;
205     /* set IRQ6 and IRQ7 to edge detect */
206     ICR |= 0x03;
207 &nbsp;
208     /* set PB15 and PB14 to inputs */
209     PBIOR &= 0x7fff;
210     PBIOR &= 0xbfff;
211 &nbsp;
212     /* set IRQ6 prio 8 and IRQ7 prio 0 */
213     IPRB = ( IPRB & 0xff00 ) | 0x80;
214 &nbsp;
215     /* Enable Tx (only!) */
216     SCR0 = 0x20;
218 </pre>
219 </td></tr></table>
222 <h3>Serial port 1</h3>
224 <p>Code starting at 0x47a0.
226 <p>As C code:
228 <table border><tr><td bgcolor="#a0d6e8">
229 <pre>
230 &#35;define SYSCLOCK 12000000
231 &#35;define PRIORITY 8
232 &nbsp;
233 void setup_sci1(int baudrate)
235     /* Disable serial port */
236     SCR1 = 0;
237 &nbsp;    
238     /* Set PB11 to Tx and PB10 to Rx */
239     PBCR1 = (PBCR1 & 0xff0f) | 0xa0;
240 &nbsp;
241     /* Asynchronous, 8N1, no prescaler */
242     SMR1 = 0;
243 &nbsp;
244     /* Set baudrate */
245     BRR1 = SYSCLOCK / (baudrate * 32) - 1;
246 &nbsp;
247     /* Clear FER and PER */
248     SSR1 &= 0xe7;
249 &nbsp;
250     /* Set interrupt priority to 8 */
251     IPRE = (IPRE & 0x0fff) | (PRIORITY << 12);
252 &nbsp;
253     /* Enable Rx, Tx and Rx interrupt */
254     SCR1 = 0x70;
256 </pre>
257 </td></tr></table>
259 <h3>Pin configuration</h3>
261 <p>Starting at 0xc40a:
263 <p><tt>CASCR = 0xafff</tt>: Column Address Strobe Pin Control Register. Set bits CASH MD1 and CASL MD1.
265 <h4>Port A</h4>
266 <br><tt>PACR1 = 0x0102</tt>: Set pin functions
267 <br><tt>PACR2 = 0xbb98</tt>: Set pin functions
268 <br><tt>PAIOR &= 0xfffe</tt>: PA0 is input
269 <br><tt>PAIOR &= 0xffdf</tt>: PA5 is input
270 <br><tt>PADR &= 0xff7f</tt>: Set pin PA7 low
271 <br><tt>PAIOR |= 0x80</tt>: PA7 is output
272 <br><tt>PAIOR |= 0x100</tt>: PA8 is output
273 <br><tt>PADR |= 0x200</tt>: Set pin PA9 high
274 <br><tt>PAIOR |= 0x200</tt>: PA9 is output
275 <br><tt>PAIOR |= 0x400</tt>: PA10 is output
276 <br><tt>PAIOR &= 0xf7ff</tt>: PA11 is input
277 <br><tt>PAIOR &= 0xbfff</tt>: PA14 is input
278 <br><tt>PAIOR = 0x7fff</tt>: PA15 is input
279 <br><tt>PADR &= 0xfeff</tt>: Set pin PA8 low
281 <h4>Port B</h4>
282 <br><tt>PBCR1 = 0x12a8</tt>: Set pin functions
283 <br><tt>PBCR2 = 0x0000</tt>: Set pin functions
284 <br><tt>PBDR &= 0xffef</tt>: Set pin PB4 low
285 <br><tt>PBIOR &= 0xffef</tt>: PB4 is input
286 <br><tt>PBIOR |= 0x20</tt>: PB5 is output
287 <br><tt>PBIOR |= 0x40</tt>: PA6 is output
288 <br><tt>PBDR &= 0xffbf</tt>: Set pin PB6 low
289 <br><tt>PBDR |= 0x20</tt>: Set pin PB5 high
291 <h3>ITU (Integrated Timer Pulse Unit)</h3>
293 <p>Starting at 0xfcd0:
295 <p><tt>TSNC &= 0xfe</tt>: The timer counter for channel 0 (TCNT0) operates independently of other channels
296 <br><tt>TMDR &= 0xfe</tt>: Channel 0 operates in normal (not PWM) mode
297 <br><tt>GRA0 = 0x1d4c</tt>:
298 <br><tt>TCR0 &= 0x67; TCR0 |= 0x23</tt>: TCNT is cleared by general register A (GRA) compare match or input capture. Counter clock = f/8
299 <br><tt>TIOR0 = 0x88</tt>: Compare disabled
300 <br><tt>TIER0 = 0xf9</tt>: Enable interrupt requests by IMFA (IMIA)
301 <br><tt>IPRC &= 0xff0f; IPRC |= 0x30</tt>: Set ITU0 interrupt priority level 3.
302 <br><tt>TSTR |= 0x01</tt>: Start TCNT0
304 <h3>Memory area #6 ?</h3>
306 <p>From 0xc52a:
308 <p><tt>PADR |= 0x0200</tt>: Set PA13 high
309 <br><tt>WCR1 = 0x40ff</tt>: Enable /WAIT support for memory area 6. Hmmm, what's on CS6?
310 <br><tt>WCR1 &= 0xfdfd</tt>: Turn off RW5 (was off already) and WW1 (enable short address output cycle).
311 <br><tt>WCR3 &= 0xe7ff</tt>: Turn off A6LW1 and A6LW0; 1 wait state for CS6.
312 <br><tt>ICR |= 0x80</tt>: Interrupt is requested on falling edge of IRQ0 input
314 <h2>Remote control</h2>
315 <p>Tjerk Schuringa reports:
316 "Finally got that extra bit going on my bitpattern generator. So far I fed only
317 simple characters to my jukebox, and this is the result:
319 <pre>
320 START D0 1 2 3 4 5 6 7 STOP FUNCTION
321 0      0 0 0 0 0 1 1 1    1 VOL- (the one I got already)
322        0 0 0 0 1 0 1 1      VOL+ (figures)
323        0 0 0 1 0 0 1 1      +
324        0 0 1 0 0 0 1 1      -
325        0 1 0 0 0 0 1 1      STOP
326        1 0 0 0 0 0 1 1      PLAY
327 </pre>
329 <p>I also found that "repeat" functions (keep a button depressed) needs to be
330 faster than 0.5 s. If it is around 1 second or more it is interpreted as a
331 seperate keypress. So far I did not get the "fast forward" function because the
332 fastest I can get is 0.5 s.
334 <p>Very important: the baudrate is indeed 9600 baud! These pulses are fed to the
335 second ring on the headphone jack, and (if I understood correctly) go to RxD1
336 of the SH1."
338 <h2>LCD display</h2>
340 <p>The Recorder uses a Shing Yih Technology G112064-30 graphic LCD display with 112x64 pixels. The controller is a Solomon SSD1815Z.
342 <p>It's not yet known what display/controller the Jukebox has, but I'd be surprised if it doesn't use a similar controller.
344 <p>Starting at 0xE050, the code flicks PB2 and PB3 a great deal and then some with PB1 and PB0. Which gives us the following connections:
346 <table border><tr><th>CPU pin</th><th>LCD pin</th></tr>
347 <tr><td>PB0</td><td>DC</td></tr>
348 <tr><td>PB1</td><td>CS1</td></tr>
349 <tr><td>PB2</td><td>SCK</td></tr>
350 <tr><td>PB3</td><td>SDA</td></tr>
351 </table>
353 <p>The Recorder apparently has the connections this way (according to Gary Czvitkovicz):
354 <table border><tr><th>CPU pin</th><th>LCD pin</th></tr>
355 <tr><td>PB0</td><td>SDA</td></tr>
356 <tr><td>PB1</td><td>SCK</td></tr>
357 <tr><td>PB2</td><td>DC</td></tr>
358 <tr><td>PB3</td><td>CS1</td></tr>
359 </table>
361 <a name="charsets"><p>The player charsets:
363 <p><table border=0><tr>
364 <td><img src="codes_old.png" width=272 height=272><br>
365 <small>Old LCD charset (before v4.50)</small></td>
366 <td><img src="codes_new.png" width=272 height=272><br>
367 <small>New LCD charset (after v4.50)</small></td></tr></table>
369 <p>And the Recorder charset looks like this:
370 <br>
371 <img src="codes_rec.png">
373 <h3>Code</h3>
375 <p>This C snippet write a byte to the Jukebox LCD controller.
376 The 'data' flag inticates if the byte is a command byte or a data byte.
378 <table border><tr><td bgcolor="#a0d6e8">
379 <pre>
380 &#35;define DC  1
381 &#35;define CS1 2
382 &#35;define SDA 4
383 &#35;define SCK 8
384 &nbsp;
385 void lcd_write(int byte, int data)
387    int i;
388    char on,off;
389 &nbsp;
390    PBDR &= ~CS1; /* enable lcd chip select */
391 &nbsp;
392    if ( data ) {
393       on=~(SDA|SCK);
394       off=SCK|DC;
395    }
396    else {
397       on=~(SDA|SCK|DC);
398       off=SCK;
399    }
400    /* clock out each bit, MSB first */
401    for (i=0x80;i;i>>=1)
402    {
403       PBDR &= on;
404       if (i & byte)
405          PBDR |= SDA;
406       PBDR |= off;
407    }
408 &nbsp;
409    PBDR |= CS1; /* disable lcd chip select */
411 </pre>
412 </td></tr></table>
414 <h2>Firmware size</h2>
416 <p>Joachim Schiffer found out that firmware files have to be at least 51200
417 bytes to be loaded by newer firmware ROMs. 
418 So my "first program" only works on players with older firmware in ROM
419 (my has 3.18). Joachim posted a
420 <a href="mail/archive/rockbox-archive-2001-12/att-0087/01-AJBREC.ajz">padded version</a> that works everywhere.
422 <p>Tests have shown that firmware sizes above 200K won't load.
424 #include "foot.t"