2002-10-01 08:20:33 +00:00
|
|
|
|
Rockbox From A Technical Angle
|
|
|
|
|
==============================
|
|
|
|
|
|
|
|
|
|
Background
|
|
|
|
|
|
2008-02-06 23:33:23 +00:00
|
|
|
|
[Most, if not all, of this document is completely outdated. You should rather
|
|
|
|
|
hunt down this info in the Rockbox wiki or source code!]
|
|
|
|
|
|
2008-05-05 10:32:46 +00:00
|
|
|
|
Björn Stenberg started this venture back in the late year 2001. The first
|
2002-10-01 08:20:33 +00:00
|
|
|
|
Rockbox code was committed to CVS end of March 2002. Rockbox 1.0 was
|
|
|
|
|
released in June.
|
|
|
|
|
|
|
|
|
|
Booting and (De)Scrambling
|
|
|
|
|
|
|
|
|
|
The built-in firmware in the Archos Jukebox reads a file from disk into
|
|
|
|
|
memory, descrambles it, verifies the checksum and then runs it as code. When
|
|
|
|
|
we build Rockbox images, we scramble the result file to use the same kind of
|
|
|
|
|
scrambling that the original Archos firmware uses so that it can be loaded
|
|
|
|
|
by the built-in firmware.
|
|
|
|
|
|
2002-10-30 23:39:37 +00:00
|
|
|
|
1) The built-in firmware starts
|
|
|
|
|
2) It looks in the root directory for a file called "archos.mod" (player)
|
|
|
|
|
or "ajbrec.ajz" (recorder)
|
|
|
|
|
3) If it finds one, it loads the file, descrambles it and runs it
|
|
|
|
|
|
2002-10-01 08:20:33 +00:00
|
|
|
|
CPU
|
|
|
|
|
|
2002-10-30 23:39:37 +00:00
|
|
|
|
The CPU in use is a SH7034 from Hitachi, running at 11.0592MHz (recorder)
|
|
|
|
|
or 12MHz (player).
|
|
|
|
|
Most single instructions are executed in 1 cycle. There is a 4KB internal RAM
|
|
|
|
|
and a 2MB external RAM.
|
2002-10-01 08:20:33 +00:00
|
|
|
|
|
|
|
|
|
Memory Usage
|
|
|
|
|
|
2002-10-30 23:39:37 +00:00
|
|
|
|
All Archos Jukebox models have only 2MB RAM. The RAM is used for everything,
|
2002-10-01 08:20:33 +00:00
|
|
|
|
including code, graphics and config. To be able to play as long as possible
|
|
|
|
|
without having to load more data, the size of the mpeg playing buffer must
|
|
|
|
|
remain as big as possible. Also, since we need to be able to do almost
|
|
|
|
|
everything in Rockbox simultaneously, we use no dynamic memory allocation
|
|
|
|
|
system at all. All sub-parts that needs memory must allocate their needs
|
|
|
|
|
staticly. This puts a great responsibility on all coders.
|
|
|
|
|
|
|
|
|
|
Playing MPEG
|
|
|
|
|
|
|
|
|
|
The MPEG decoding is performed by an external circuit, MAS3507D (for the
|
|
|
|
|
Player/Studio models) or MAS3587F (for the Recorder models).
|
|
|
|
|
|
2002-10-30 23:39:37 +00:00
|
|
|
|
The CPU has a serial connection to the MAS for MP3 playback, using serial
|
|
|
|
|
port 0 at approx. 1mbit/s. The MAS has a handshake signal called DEMAND,
|
|
|
|
|
that informs the CPU when it wants more MP3 data. Whenever the DEMAND
|
|
|
|
|
signal goes high, it wants data sent over the serial line, and it wants it
|
|
|
|
|
quickly, within ~1ms. When the MAS has received enough data, it negates the
|
|
|
|
|
DEMAND signal and expects the incoming data stream to stop within 1ms.
|
|
|
|
|
|
|
|
|
|
The DEMAND signal is connected to a port pin on the CPU which can generate
|
|
|
|
|
an IRQ, but only on the falling edge. That means that the mpeg driver code
|
2008-05-05 10:32:46 +00:00
|
|
|
|
must poll the DEMAND signal every ms to keep the MAS happy. The mpeg code
|
2002-10-30 23:39:37 +00:00
|
|
|
|
does use the IRQ to detect the falling edge when the MAS is "full".
|
|
|
|
|
|
|
|
|
|
Unfortunately, the serial port on the CPU sends the LSB first, and the MAS
|
|
|
|
|
expects the MSB first. Therefore we have to revers the bit order in every
|
|
|
|
|
byte in the loaded MP3 data. This is referred to as "bit swapping" in the
|
|
|
|
|
Rockbox code.
|
|
|
|
|
|
|
|
|
|
The internal DMA controller is used to feed the serial port with data. The
|
|
|
|
|
driver works roughly like this:
|
|
|
|
|
|
|
|
|
|
1) Load MP3 data into the RAM buffer
|
|
|
|
|
2) Bitswap the data
|
|
|
|
|
3) Load the DMA source pointer to the next 64Kbyte block to be transferred
|
|
|
|
|
4) Wait until DEMAND is high
|
|
|
|
|
5) Enable the DMA
|
|
|
|
|
6) Wait until the falling DEMAND pin generates an IRQ
|
|
|
|
|
7) Disable the DMA
|
|
|
|
|
8) Go to 4
|
|
|
|
|
|
|
|
|
|
The DMA generates an IRQ when the 64Kbyte block is transferred, and the
|
|
|
|
|
IRQ handler updates the DMA source pointer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_____________________________
|
|
|
|
|
| |
|
|
|
|
|
DEMAND __________| |_____________
|
|
|
|
|
_ _ _ _ _ _ _ _ _
|
|
|
|
|
SC0 _____________/ \/ \/ \/ \/ \/ \/ \/ \/ \____________
|
|
|
|
|
\_/\_/\_/\_/\_/\_/\_/\_/\_/
|
|
|
|
|
^ ^
|
|
|
|
|
| |
|
|
|
|
|
Poll sees the DEMAND The DEMAND pin generates
|
|
|
|
|
signal go high and an IRQ that in turn disables
|
|
|
|
|
enables the DMA the DMA again
|
2002-10-01 08:20:33 +00:00
|
|
|
|
|
|
|
|
|
Spinning The Disk Up/Down
|
|
|
|
|
|
|
|
|
|
To save battery, the spinning of the harddrive must be kept at a minimum.
|
|
|
|
|
Rockbox features a timeout, so that if no action has been performed within N
|
|
|
|
|
seconds, the disk will spin-down automaticly. However, if the disk was used
|
|
|
|
|
for mpeg-loading for music playback, the spin-down will be almost immediate
|
|
|
|
|
as then there's no point in timing out. The N second timer is thus only used
|
|
|
|
|
when the disk-activity is trigged by a user.
|
|
|
|
|
|
|
|
|
|
FAT and Mounting
|
|
|
|
|
|
|
|
|
|
Rockbox scans the partitions of the disk and tries to mount them as fat32
|
|
|
|
|
filesystems at boot.
|
|
|
|
|
|
|
|
|
|
Directory Buffer
|
|
|
|
|
|
|
|
|
|
When using the "dir browser" in Rockbox to display a single directory, it
|
|
|
|
|
loads all entries in the directory into memory first, then sorts them and
|
|
|
|
|
presents them on screen. The buffer used for all file entries is limited to
|
|
|
|
|
maximum 16K or 400 entries. If the file names are longish, the 16K will run
|
|
|
|
|
out before 400 entries have been used.
|
|
|
|
|
|
|
|
|
|
This rather limited buffer size is of course again related to the necessity
|
|
|
|
|
to keep the footprint small to keep the mpeg buffer as large as possible.
|
|
|
|
|
|
|
|
|
|
Playlist Concepts
|
|
|
|
|
|
|
|
|
|
One of the most obvious limitations in the firmware Rockbox tries to
|
|
|
|
|
outperform, was the way playlists were dealt with.
|
|
|
|
|
|
|
|
|
|
When loading a playlist (which is a plain text file with file names
|
|
|
|
|
separated by newlines), Rockbox will scan through the file and store indexes
|
|
|
|
|
to all file names in an array. The array itself has a 10000-entry limit (for
|
|
|
|
|
memory size reasons).
|
|
|
|
|
|
|
|
|
|
To play a specific song from the playlist, Rockbox checks the index and then
|
|
|
|
|
seeks to that position in the original file on disk and gets the file name
|
|
|
|
|
from there. This way, very little memory is wasted and yet very large
|
|
|
|
|
playlists are supported.
|
|
|
|
|
|
|
|
|
|
Playing a Directory
|
|
|
|
|
|
|
|
|
|
Playing a full directory is using the same technique as with playlists. The
|
|
|
|
|
difference is that the playlist is not a file on disk, but is the directory
|
|
|
|
|
buffer.
|
|
|
|
|
|
|
|
|
|
Shuffle
|
|
|
|
|
|
|
|
|
|
Since the playlist is a an array of indexes to where to read the file name,
|
2002-10-30 23:39:37 +00:00
|
|
|
|
shuffle modifies the order of these indexes in the array. The algorithm is
|
|
|
|
|
pretty much like shuffling a deck of cards, and it uses a pseudo random
|
|
|
|
|
generator called the Mersenne Twister. The randomness is identical for the
|
|
|
|
|
same random seed. This is the secret to good resume. Even when you've shut
|
|
|
|
|
down your unit and re-starts it, using the same random seed as the previous
|
|
|
|
|
time will give exactly the same random order.
|
2002-10-01 08:20:33 +00:00
|
|
|
|
|
|
|
|
|
Saving Config Data
|
|
|
|
|
|
|
|
|
|
The Player/Studio models have no battery-backuped memory while the Recorder
|
|
|
|
|
models have 44 bytes battery-backuped.
|
|
|
|
|
|
|
|
|
|
To save data to be persistent and around even after reboots, Rockbox uses
|
|
|
|
|
harddisk sector 63, which is outside the FAT32 filesystem. (Recorder models
|
|
|
|
|
also get some data stored in the battery-backuped area).
|
|
|
|
|
|
|
|
|
|
The config is only saved when the disk is spinning. This is important to
|
|
|
|
|
realize, as if you change a config setting and then immediately shuts your
|
|
|
|
|
unit down, the new config is not saved.
|
|
|
|
|
|
2002-10-03 10:02:22 +00:00
|
|
|
|
DEVELOPERS:
|
|
|
|
|
The config checksum includes a header with a version number. This version
|
|
|
|
|
number must be increased when the config structure becomes incompatible.
|
|
|
|
|
This makes the checksum check fail, and the settings are reset to default
|
|
|
|
|
values.
|
|
|
|
|
|
2002-10-01 08:20:33 +00:00
|
|
|
|
Resume Explained
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
Charging
|
|
|
|
|
|
|
|
|
|
(Charging concerns Recorder models only, the other models have hardware-
|
|
|
|
|
controlled charging that Rockbox can't affect.)
|
|
|
|
|
|
|
|
|
|
...
|
2006-01-18 20:54:13 +00:00
|
|
|
|
|
|
|
|
|
Profiling
|
|
|
|
|
|
|
|
|
|
Rockbox contains a profiling system which can be used to monitor call count
|
|
|
|
|
and time in function for a specific set of functions on a single thread.
|
|
|
|
|
|
|
|
|
|
To use this functionality:
|
|
|
|
|
1) Configure a developer build with profiling support.
|
|
|
|
|
2) Make sure that the functions of interest will be compiled with the
|
|
|
|
|
PROFILE_OPTS added to their CFLAGS
|
|
|
|
|
3) On the same thread as these functions will be run, surround the relevent
|
|
|
|
|
running time with calls to profile_thread and profstop. (For codecs,
|
|
|
|
|
this can be done in the codec.c file for example)
|
|
|
|
|
4) Compile and run the code on the target, after the section to be profiled
|
|
|
|
|
exits (when profstop is called) a profile.out file will be written to
|
|
|
|
|
the player's root.
|
|
|
|
|
5) Use the tools/profile_reader/profile_reader.pl script to convert the
|
|
|
|
|
profile.out into a human readable format. This script requires the
|
|
|
|
|
relevent map files and object (or library) files created in the build.
|
|
|
|
|
(ex: ./profile_reader.pl profile.out vorbis.map libTremor.a 0)
|
|
|
|
|
|
|
|
|
|
There is also a profile_comparator.pl script which can compare two profile
|
|
|
|
|
runs as output by the above script to show percent change from optimization
|
|
|
|
|
|
|
|
|
|
profile_reader.pl requires a recent binutils that can automatically handle
|
|
|
|
|
target object files, or objdump in path to be the target-objdump.
|