Onda's: add touchscreen boot menu for targets without/not much physical buttons ...
[kugel-rb.git] / bootloader / ondavx747.c
blobd60c311bb7d746799bd1366adc8a83591faa17f6
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
23 #include "jz4740.h"
24 #include "backlight.h"
25 #include "font.h"
26 #include "lcd.h"
27 #include "usb.h"
28 #include "system.h"
29 #include "button.h"
30 #include "common.h"
31 #include "storage.h"
32 #include "disk.h"
33 #include "string.h"
34 #include "adc.h"
36 extern int show_logo(void);
37 extern void power_off(void);
39 static void show_splash(int timeout, const char *msg)
41 reset_screen();
42 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
43 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
44 lcd_update();
46 sleep(timeout);
49 static void usb_mode(void)
51 int button;
53 /* Init USB */
54 usb_init();
55 usb_start_monitoring();
57 /* Wait for threads to connect */
58 show_splash(HZ/2, "Waiting for USB");
60 while (1)
62 button = button_get_w_tmo(HZ/2);
64 if (button == SYS_USB_CONNECTED)
65 break; /* Hit */
68 if (button == SYS_USB_CONNECTED)
70 /* Got the message - wait for disconnect */
71 show_splash(0, "Bootloader USB mode");
73 usb_acknowledge(SYS_USB_CONNECTED_ACK);
75 while (1)
77 button = button_get(true);
78 if (button == SYS_USB_DISCONNECTED)
80 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
81 break;
86 reset_screen();
89 static int boot_of(void)
91 int fd, rc, len, i, checksum = 0;
92 void (*kernel_entry)(int, void*, void*);
94 /* TODO: get this from the NAND flash instead of SD */
95 fd = open("/ccpmp.bin", O_RDONLY);
96 if(fd < 0)
97 return EFILE_NOT_FOUND;
99 lseek(fd, 4, SEEK_SET);
100 rc = read(fd, (char*)&len, 4); /* CPU is LE */
101 if(rc < 4)
102 return EREAD_IMAGE_FAILED;
104 len += 8;
105 printf("Reading %d bytes...", len);
107 lseek(fd, 0, SEEK_SET);
108 rc = read(fd, (void*)0x80004000, len);
109 if(rc < len)
110 return EREAD_IMAGE_FAILED;
112 close(fd);
114 for(i=0; i<len; i++)
115 checksum += ((unsigned char*)0x80004000)[i];
117 *((unsigned int*)0x80004000) = checksum;
119 printf("Starting the OF...");
121 /* OF requires all clocks on */
122 __cpm_start_all();
124 disable_interrupt();
125 __dcache_writeback_all();
126 __icache_invalidate_all();
128 for(i=8000; i>0; i--)
129 asm volatile("nop\n");
131 kernel_entry = (void*) 0x80004008;
132 kernel_entry(0, "Jan 10 2008", "15:34:42"); /* Reversed from the SPL */
134 return 0; /* Shouldn't happen */
137 static int boot_rockbox(void)
139 int rc;
140 void (*kernel_entry)(void);
142 printf("Loading firmware");
143 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000);
144 if(rc < 0)
145 return rc;
146 else
148 printf("Starting Rockbox...");
149 adc_close(); /* Disable SADC, seems to fix the re-init Rockbox does */
151 disable_interrupt();
152 kernel_entry = (void*) CONFIG_SDRAM_START;
153 kernel_entry();
155 return 0; /* Shouldn't happen */
159 #define RECT_X (LCD_WIDTH/8)
160 #define RECT_Y(i) (LCD_HEIGHT/20 + LCD_HEIGHT/10*i + RECT_HEIGHT*i)
161 #define RECT_WIDTH (LCD_WIDTH*3/4)
162 #define RECT_HEIGHT (LCD_HEIGHT/ARRAYLEN(strings) - LCD_HEIGHT/10)
163 #define TEXT_X(i) (RECT_X + RECT_WIDTH/2 - strlen(strings[i])*SYSFONT_WIDTH/2)
164 #define TEXT_Y(i) (RECT_Y(i) + RECT_HEIGHT/2 - SYSFONT_HEIGHT/2)
165 static int boot_menu(void)
167 const char* strings[] = {"Boot Rockbox", "Boot OF", "USB mode"};
168 int button, touch;
169 unsigned int i;
171 adc_init();
173 redraw:
174 lcd_clear_display();
175 for(i=0; i<ARRAYLEN(strings); i++)
177 lcd_drawrect(RECT_X, RECT_Y(i), RECT_WIDTH, RECT_HEIGHT);
178 lcd_putsxy(TEXT_X(i), TEXT_Y(i), strings[i]);
180 lcd_update();
182 while(1)
184 button = button_get_w_tmo(HZ/4);
185 if(button & (BUTTON_TOUCHSCREEN|BUTTON_REPEAT))
187 touch = button_get_data();
188 unsigned int x = touch & 0xFFFF, y = touch >> 16;
189 int found = -1;
190 for(i=0; i<ARRAYLEN(strings); i++)
192 if(x > RECT_X && x < RECT_X+RECT_WIDTH &&
193 y > RECT_Y(i) && y < RECT_Y(i)+RECT_HEIGHT)
195 found = i;
196 break;
200 switch(found)
202 case 0:
203 return boot_rockbox();
204 case 1:
205 return boot_of();
206 case 2:
207 usb_mode();
208 break;
211 if(found != -1)
212 goto redraw;
214 else if(button & (BUTTON_POWER|BUTTON_REPEAT))
215 power_off();
219 int main(void)
221 int rc;
222 #ifdef HAVE_TOUCHSCREEN
223 int dummy;
224 #endif
226 kernel_init();
227 lcd_init();
228 font_init();
229 lcd_setfont(FONT_SYSFIXED);
230 button_init();
231 backlight_init();
233 show_logo();
235 rc = storage_init();
236 if(rc)
237 error(EATA, rc);
239 #ifdef HAVE_TOUCHSCREEN
240 rc = button_read_device(&dummy);
241 #else
242 rc = button_read_device();
243 #endif
245 if(rc)
246 verbose = true;
248 #ifdef BUTTON_VOL_UP
249 if(rc & BUTTON_VOL_UP ||
250 #endif
252 rc = boot_menu();
254 if(verbose)
255 reset_screen();
256 printf(MODEL_NAME" Rockbox Bootloader");
257 printf("Version "APPSVERSION);
259 rc = disk_mount_all();
260 if (rc <= 0)
261 error(EDISK,rc);
263 #ifdef HAS_BUTTON_HOLD
264 if(button_hold())
265 rc = boot_of();
266 else
267 #endif
268 rc = boot_rockbox();
270 if(rc < 0)
271 printf("Error: %s", strerror(rc));
273 /* Halt */
274 while (1)
275 core_idle();
277 return 0;