Wiki > Main > PortingApplication (compare)
Difference: PortingApplication (r2 vs. r1)
Work in progress
This page tries to describe steps and requirements for porting Rockbox as an application (RaaA?), as well as common pitfalls.
Rockbox is historically an operating system for embedded systems. Yet, it has many audio and playback related features that you cannot find on a single media player application. But it lacks features of OSes shipped on devices (such as telephony or networking) which makes it illogical to run Rockbox as an OS on those devices. Additionally, Rockbox as an OS needs to be tailored for every specific device. Therefore it's desirable to run Rockbox as an application, within a hosted environment.
As part of SummerOfCode2010, Rockbox has been successfully ported to two platforms, SDL and Android.
Platform can mean an specific OS or a (cross platform) user space library. Rockbox is ported to the platforms then, not to the devices.
Because Rockbox has always an OS, it has virtually no dependencies. But to reach the best degree of integration and to reduce Rockbox' memory footprint the goal is to use supporting OS/library routines where possible.
There's a set of drivers mandatory for each port, I'll refer to them in the OS terms.
Rockbox draws into a flat memory region, the LCD framebuffer. It then uses lcd_update() and lcd_update_rect() to display the framebuffer. The following bits are interesting for the lcd driver.
typedef unsigned short fb_data; #define LCD_FBWIDTH ((LCD_WIDTH+7)/8) #define LCD_FBHEIGHT LCD_HEIGHT fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; extern void lcd_init_device(void); extern void lcd_update(void); extern void lcd_update_rect(int x, int y, int width, int height);
The above shows the RGB565 (so, 16bit) case (i.e. each pixel has 5 bits of red, 6 bits of green and 5 bits of blue). Currently there's no driver for more bits, so you need to write one if you want to use it. But that'd be a lot of effort, because you'd also need to properly convert the compiled-in bitmaps. So it's recommended you stick to the 16bit driver, then all compiled-in bitmaps will also work as is.
What the driver needs to implement is the 3 functions shown.
It is important that lcd_update[_rect] schedules the update completely, otherwise you might see artifacts on the display.
Example: The Android port creates an RockboxFramebuffer? object in lcd_init_device. The object holds a back buffer. The OS updates from this back buffer. The back buffer is needed because you cannot determine when Android does the actual update. lcd_update() also emits a postInvalidate() call which notifies the OS that we're ready to draw.
Rockbox reads the button state in each tick. The input driver is responsible for mapping the states to appropriate buttons (as used in apps/keymap-*.c). Rockbox currently has no complete keyboard support, so don't waste time on trying to implement it. Instead, focus on the touchscreen and button interface.
The Touchscreen interface can be used for touchscreen input, obviously. But it can also re-purposed to mouse navigation.
With button interface you can send arbitrary buttons to the core. You need to have them defined (so they can be bitwise OR'ed) in the button-target.h file and you need to give them a function in the apps/keymap-*.c file.
extern void button_init_device(void); extern int button_read_device(int *data);
You need to implement the above functions. button_init_device() is much like the aforementioned lcd_init_device() functions, i.e. you use it to initialize the driver and connect it with the host.
button_read_device() is what's being called periodically, every tick. It should be fast to execute. It only has the data parameter if you implement the touchscreen interface. It's expected to return the appropriate bit for each pressed button (e.g. BUTTON_UP|BUTTON_LEFT), or BUTTON_NONE if nothing was pressed. You should return the value of touchscreen_to_pixels() if you received a button press with the touchscreen interface. Pass through the data parameter if you call it. It'll handle the current touchscreen mode for you and return the correct press on its own.
int touchscreen_to_pixels(int x, int y, int *data);
Rockbox uses "tick tasks" for a variety of purposes. tick tasks are small C functions that are called in a fixed intervall HZ times per second (HZ is usually 100).
extern bool timer_register(int reg_prio, void (*unregister_callback)(void),<br /> long cycles, void (*timer_callback)(void)) extern bool timer_set_period(long cycles); extern void timer_unregister(void); #define HZ 100 extern void tick_start(unsigned int interval_in_ms);
extern void call_tick_tasks(void);
The first three functions need to be stubbed, for now, since it's only used in (some) plugins which the application doesn't build right now.
The last however, tick_start(), is important. This function needs to set up a mechanism which enables the tick tasks to be called. In most cases this means setting up a timer task, which runs periodically at a HZ rate.
The timer task function needs to call call_tick_tasks().
-- ThomasMartitz - 2010-08-15
r3 - 15 Aug 2010 - 21:58:59 - ThomasMartitzRevision r2 - 15 Aug 2010 - 19:47 - ThomasMartitz
Revision r1 - 15 Aug 2010 - 18:43 - ThomasMartitz
Copyright © by the contributing authors.