1 #define _PAGE_ Jukebox notes
4 <center><table class=rockbox width=70%><tr><td>
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.
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:
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>
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.
44 <p><table><tr valign="top"><td>
46 <p>Port A pin function configuration summary:
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>
69 <p>Port B pin function configuration summary:
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>
93 <p>Port C pin function configuration summary:
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>
108 <p>Note: Everything is about v5.03a.
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
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:
136 0x00000200: mov.l @(0x02C,pc),r1 ; 0x0000022C (0x09000000)
137 0x00000202: ldc r1,vbr
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.
145 0x00000204: mov.l @(0x024,pc),r15 ; 0x00000228 (0x0903F2BC)
148 <p>After that the code jumps to the hardware setup at 0xc8c0.
150 0x00000206: mov.l @(0x01C,pc),r0 ; 0x00000220 (0x0900C8C0)
154 <h3>DRAM controller</h3>
156 <p>First up is DRAM setup, at 0xc8c8. It sets the memory controller registers:
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
174 <h3>Serial port 0</h3>
176 <p>Code starting at 0x483c.
180 <table border><tr><td bgcolor="#a0d6e8">
182 void setup_sci0(void)
184 /* set PB12 to output */
187 /* Disable serial port */
190 /* Syncronous, 8N1, no prescale */
193 /* Set baudrate 1Mbit/s */
196 /* use SCK as serial clock output */
199 /* Clear FER and PER */
202 /* Set interrupt D priority to 0 */
205 /* set IRQ6 and IRQ7 to edge detect */
208 /* set PB15 and PB14 to inputs */
212 /* set IRQ6 prio 8 and IRQ7 prio 0 */
213 IPRB = ( IPRB & 0xff00 ) | 0x80;
215 /* Enable Tx (only!) */
222 <h3>Serial port 1</h3>
224 <p>Code starting at 0x47a0.
228 <table border><tr><td bgcolor="#a0d6e8">
230 #define SYSCLOCK 12000000
231 #define PRIORITY 8
233 void setup_sci1(int baudrate)
235 /* Disable serial port */
238 /* Set PB11 to Tx and PB10 to Rx */
239 PBCR1 = (PBCR1 & 0xff0f) | 0xa0;
241 /* Asynchronous, 8N1, no prescaler */
245 BRR1 = SYSCLOCK / (baudrate * 32) - 1;
247 /* Clear FER and PER */
250 /* Set interrupt priority to 8 */
251 IPRE = (IPRE & 0x0fff) | (PRIORITY << 12);
253 /* Enable Rx, Tx and Rx interrupt */
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.
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
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>
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:
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)
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
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>
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>
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:
371 <img src="codes_rec.png">
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">
385 void lcd_write(int byte, int data)
390 PBDR &= ~CS1; /* enable lcd chip select */
400 /* clock out each bit, MSB first */
409 PBDR |= CS1; /* disable lcd chip select */
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.