---
 src/target/firmware/Makefile         |    3 +-
 src/target/firmware/apps/menu/main.c |  353 ++++++++++++++++++++++++++++++++++
 2 files changed, 355 insertions(+), 1 deletions(-)
 create mode 100644 src/target/firmware/apps/menu/main.c

diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile
index 42f7ad4..0f4120f 100644
--- a/src/target/firmware/Makefile
+++ b/src/target/firmware/Makefile
@@ -84,11 +84,12 @@ BOARD_se_j100_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
 #
 
 # List of all applications (meant to be overridden on command line)
-APPLICATIONS?=hello_world compal_dsp_dump layer1 loader rssi
+APPLICATIONS?=hello_world compal_dsp_dump layer1 loader rssi menu
 
 # Applications specific env requirements
 APP_loader_ENVIRONMENTS=compalram highram
 APP_rssi_ENVIRONMENTS=* -compalram
+APP_menu_ENVIRONMENTS=* -highram
 
 # Various objects that are currently linked into all applications
 FLASH_OBJS=flash/cfi_flash.o
diff --git a/src/target/firmware/apps/menu/main.c 
b/src/target/firmware/apps/menu/main.c
new file mode 100644
index 0000000..47aadc4
--- /dev/null
+++ b/src/target/firmware/apps/menu/main.c
@@ -0,0 +1,353 @@
+/* Menu for Calypso Phone to load applicatios from flash */
+
+/* (C) 2013 by Andreas Eversberg <[email protected]>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <debug.h>
+#include <memory.h>
+#include <delay.h>
+#include <byteorder.h>
+#include <rffe.h>
+#include <keypad.h>
+#include <board.h>
+#include <abb/twl3025.h>
+#include <rf/trf6151.h>
+#include <calypso/clock.h>
+#include <calypso/tpu.h>
+#include <calypso/tsp.h>
+#include <calypso/dsp.h>
+#include <calypso/irq.h>
+#include <calypso/misc.h>
+#include <calypso/timer.h>
+#include <comm/sercomm.h>
+#include <comm/timer.h>
+#include <uart.h>
+#include <fb/framebuffer.h>
+#include <battery/battery.h>
+#include <asm/system.h>
+
+#define RAM 0x00820000
+#define MAGIC 0x0083ff00
+
+enum key_codes key_code = KEY_INV;
+static volatile enum key_states key_state;
+
+int cursor = 0, scroll_apps = 0;
+
+struct apps {
+       char name[16];
+       void *start;
+       int len;
+} apps[32];
+
+int _memcmp(char *s1, char *s2, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (*s1 < *s2)
+                       return -1;
+               if (*s1 > *s2)
+                       return 1;
+               s1++;
+               s2++;
+       }
+
+       return 0;
+}
+
+static void locate_apps(void)
+{
+       int i, j, k;
+       char *p;
+
+       memset(apps, 0, sizeof(apps));
+
+       for (j = 0, i = 0x010000; i < 0x200000; i += 0x10000) {
+               p = (char *)i;
+               /* check for highram header: "highram:" */
+               if (!!_memcmp(p, "highram:", 8))
+                       continue;
+               p += 8;
+               /* check for app name after header: "highram:<name>\n" */
+               printf("found highram image at flash mem address 0x%p\n",
+                       (char *)i);
+               for (k = 0; k < (int)sizeof(apps[j].name) - 1; k++) {
+                       if (p[k] == '\n')
+                               break;
+               }
+               if (k == sizeof(apps[j].name) - 3) {
+                       printf("skipping: corrupt highram header, no '\\n' "
+                               "after image name or name more larger than %d "
+                               "digits\n", (int)sizeof(apps[j].name) - 3);
+                               continue;
+               }
+               if (j < 9)
+                       apps[j].name[0] = '1' + j;
+               else if (j == 9)
+                       apps[j].name[0] = '0';
+               else
+                       apps[j].name[0] = ' ';
+               apps[j].name[1] = ' ';
+               memcpy(apps[j].name + 2, p, k);
+               apps[j].len = 0x20000;
+               p += k + 1;
+               /* p points to highram image after header */
+               apps[j].start = p;
+               j++;
+       }
+}
+
+static void wait_key_release(void)
+{
+       /* wait for key release */
+       while (key_state == PRESSED) {
+               delay_ms(10);
+               keypad_poll();
+       }
+}
+
+static void load_app(void)
+{
+       static int i;
+       static void (*f) (void) = (void (*)(void))RAM;
+
+       wait_key_release();
+
+       local_irq_disable();
+
+       for (i = 0; i < apps[cursor].len; i++)
+               ((unsigned char *)RAM)[i] = ((unsigned char 
*)apps[cursor].start)[i];
+       f();
+}
+
+/* UI */
+
+static void refresh_display(void)
+{
+#if 0
+       char text[16];
+       int bat = battery_info.battery_percent;
+#endif
+       int i;
+
+       fb_clear();
+
+       /* header */
+       fb_setbg(FB_COLOR_WHITE);
+       if (1) {
+               fb_setfg(FB_COLOR_BLUE);
+               fb_setfont(FB_FONT_HELVR08);
+               fb_gotoxy(0, 7);
+               fb_putstr("Osmocom Menu", -1);
+               fb_setfg(FB_COLOR_RGB(0xc0, 0xc0, 0x00));
+               fb_setfont(FB_FONT_SYMBOLS);
+#if 0
+               fb_gotoxy(framebuffer->width - 15, 8);
+               if (bat >= 100 && (battery_info.flags & BATTERY_CHG_ENABLED)
+                && !(battery_info.flags & BATTERY_CHARGING))
+                       fb_putstr("@HHBC", framebuffer->width);
+               else {
+                       sprintf(text, "@%c%c%cC", (bat >= 30) ? 'B':'A',
+                               (bat >= 60) ? 'B':'A', (bat >= 90) ? 'B':'A');
+                       fb_putstr(text, framebuffer->width);
+               }
+#endif
+               fb_gotoxy(0, 8);
+               fb_putstr("GGEGG", framebuffer->width);
+               fb_setfg(FB_COLOR_GREEN);
+               fb_gotoxy(0, 10);
+               fb_boxto(framebuffer->width - 1, 10);
+       }
+       fb_setfg(FB_COLOR_BLACK);
+       fb_setfont(FB_FONT_C64);
+
+
+       for (i = 0; i < 5; i++) {
+               if (!apps[scroll_apps + i].name)
+                       break;
+               if (scroll_apps + i == cursor) {
+                       fb_setfg(FB_COLOR_WHITE);
+                       fb_setbg(FB_COLOR_BLUE);
+               }
+               fb_gotoxy(0, 20 + i * 10);
+               fb_putstr(apps[scroll_apps + i].name,
+                       framebuffer->width);
+               if (scroll_apps + i == cursor) {
+                       fb_setfg(FB_COLOR_BLACK);
+                       fb_setbg(FB_COLOR_WHITE);
+               }
+       }
+       if (i == 0) {
+               fb_gotoxy(0, 50);
+               fb_putstr("No apps!", -1);
+       }
+
+       fb_flush();
+}
+
+static void handle_key_code()
+{
+       if (key_code == KEY_INV)
+               return;
+
+       switch (key_code) {
+       case KEY_1:
+       case KEY_2:
+       case KEY_3:
+       case KEY_4:
+       case KEY_5:
+       case KEY_6:
+       case KEY_7:
+       case KEY_8:
+       case KEY_9:
+               if (apps[key_code - KEY_1].len) {
+                       cursor = key_code - KEY_1;
+                       load_app();
+               }
+               break;
+       case KEY_0:
+               if (apps[9].len) {
+                       cursor = 9;
+                       load_app();
+               }
+               break;
+       case KEY_UP:
+               if (cursor == 0)
+                       return;
+               cursor--;
+               if (cursor < scroll_apps)
+                       scroll_apps = cursor;
+               refresh_display();
+               break;
+       case KEY_DOWN:
+               if (!apps[cursor + 1].name[0])
+                       return;
+               cursor++;
+               if (cursor >= scroll_apps + 5)
+                       scroll_apps = cursor - 4;
+               refresh_display();
+               break;
+       case KEY_OK:
+               if (apps[cursor].len)
+                       load_app();
+               break;
+       case KEY_POWER:
+               wait_key_release();
+               twl3025_power_off();
+               break;
+       default:
+               break;
+       }
+
+       key_code = KEY_INV;
+}
+
+/* Main Program */
+const char *hr = 
"======================================================================\n";
+
+static void key_handler(enum key_codes code, enum key_states state)
+{
+       key_state = state;
+
+       if (state != PRESSED)
+               return;
+
+       key_code = code;
+}
+
+extern void putchar_asm(uint32_t c);
+
+static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 
};
+
+int main(void)
+{
+       int i;
+
+       /* Simulate a compal loader saying "ACK" */
+       for (i = 0; i < (int)sizeof(phone_ack); i++) {
+               putchar_asm(phone_ack[i]);
+       }
+
+       board_init(0);
+
+       puts("\n\nOsmocomBB Menu (revision " GIT_REVISION ")\n");
+       puts(hr);
+
+       fb_clear();
+
+       fb_setfg(FB_COLOR_BLACK);
+       fb_setbg(FB_COLOR_WHITE);
+       fb_setfont(FB_FONT_HELVB14);
+
+       fb_gotoxy(2,20);
+       fb_putstr("menu",framebuffer->width-4);
+
+       fb_setfg(FB_COLOR_RED);
+       fb_setbg(FB_COLOR_BLUE);
+
+       fb_gotoxy(2,25);
+       fb_boxto(framebuffer->width-3,38);
+
+       fb_setfg(FB_COLOR_WHITE);
+       fb_setfont(FB_FONT_HELVR08);
+       fb_gotoxy(8,33);
+       fb_putstr("osmocom-bb",framebuffer->width-4);
+
+       fb_flush();
+
+       /* Dump device identification */
+       dump_dev_id();
+       puts(hr);
+
+       /* Dump clock config before PLL set */
+       calypso_clk_dump();
+       puts(hr);
+
+       keypad_set_handler(&key_handler);
+
+       /* Dump clock config after PLL set */
+       calypso_clk_dump();
+       puts(hr);
+
+//     display_unset_attr(DISP_ATTR_INVERT);
+
+       locate_apps();
+
+       while (1) {
+               for (i = 0; i < 50; i++) {
+                       keypad_poll();
+                       delay_ms(10);
+                       osmo_timers_update();
+                       handle_key_code();
+               }
+               refresh_display();
+       }
+
+       /* NOT REACHED */
+
+       twl3025_power_off();
+}
+
-- 
1.7.3.4


Reply via email to