From 275a30092e84f9d026a18bcf90b2f29721302a33 Mon Sep 17 00:00:00 2001 From: Robert Kukla Date: Sun, 26 Jul 2009 14:26:14 +0000 Subject: [PATCH] initial commit of remote support for m:robe 100 courtesy of lowlight; simulator support including small fixes for the m:robe 500 git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22053 a1c6a512-1295-4272-9138-f99709370657 --- apps/keymaps/keymap-mr100.c | 10 +- apps/plugins/stats.c | 1 + firmware/SOURCES | 1 + firmware/export/config-mrobe100.h | 24 +- .../arm/olympus/mrobe-100/backlight-mr100.c | 13 + .../arm/olympus/mrobe-100/backlight-target.h | 5 + .../arm/olympus/mrobe-100/button-mr100.c | 72 ++- .../arm/olympus/mrobe-100/button-target.h | 30 +- .../arm/olympus/mrobe-100/lcd-remote-mr100.c | 562 ++++++++++++++++++ .../arm/olympus/mrobe-100/lcd-remote-target.h | 40 ++ .../arm/olympus/mrobe-100/power-mr100.c | 5 + firmware/target/arm/system-pp502x.c | 6 + tools/configure | 2 + uisimulator/common/README | 3 - uisimulator/sdl/UI-mrobe100.bmp | Bin 309558 -> 343782 bytes uisimulator/sdl/UI-mrobe500.bmp | Bin 630054 -> 473254 bytes uisimulator/sdl/button.c | 28 +- uisimulator/sdl/uisdl.h | 10 +- 18 files changed, 777 insertions(+), 35 deletions(-) create mode 100644 firmware/target/arm/olympus/mrobe-100/lcd-remote-mr100.c create mode 100644 firmware/target/arm/olympus/mrobe-100/lcd-remote-target.h diff --git a/apps/keymaps/keymap-mr100.c b/apps/keymaps/keymap-mr100.c index 514d38b4e6..efbbca4d1b 100644 --- a/apps/keymaps/keymap-mr100.c +++ b/apps/keymaps/keymap-mr100.c @@ -275,12 +275,12 @@ static const struct button_mapping button_context_keyboard[] = { static const struct button_mapping remote_button_context_standard[] = { { ACTION_STD_PREV, BUTTON_RC_PLAY, BUTTON_NONE }, { ACTION_STD_PREVREPEAT, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RC_DISPLAY, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RC_DISPLAY|BUTTON_REPEAT,BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RC_DOWN, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RC_DOWN|BUTTON_REPEAT,BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_RC_REW, BUTTON_NONE }, { ACTION_STD_OK, BUTTON_RC_FF|BUTTON_REL, BUTTON_RC_FF }, { ACTION_STD_CONTEXT, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_RC_FF }, - { ACTION_STD_MENU, BUTTON_RC_FAV, BUTTON_NONE }, + { ACTION_STD_MENU, BUTTON_RC_HEART, BUTTON_NONE }, LAST_ITEM_IN_LIST }; @@ -297,7 +297,7 @@ static const struct button_mapping remote_button_context_wps[] = { { ACTION_WPS_STOPSEEK, BUTTON_RC_FF|BUTTON_REL, BUTTON_RC_FF|BUTTON_REPEAT }, { ACTION_WPS_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_RC_PLAY }, - { ACTION_WPS_MENU, BUTTON_RC_FAV, BUTTON_NONE }, + { ACTION_WPS_MENU, BUTTON_RC_HEART, BUTTON_NONE }, { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, @@ -340,7 +340,7 @@ static const struct button_mapping remote_button_context_usb_hid[] = { { ACTION_USB_HID_VOLUP, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_USB_HID_VOLDOWN, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, { ACTION_USB_HID_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_USB_HID_MENU, BUTTON_RC_FAV, BUTTON_NONE }, + { ACTION_USB_HID_MENU, BUTTON_RC_HEART, BUTTON_NONE }, LAST_ITEM_IN_LIST }; /* remote_button_context_usb_hid */ diff --git a/apps/plugins/stats.c b/apps/plugins/stats.c index 976fd262f8..accb286369 100644 --- a/apps/plugins/stats.c +++ b/apps/plugins/stats.c @@ -75,6 +75,7 @@ static bool abort; #elif CONFIG_KEYPAD == MROBE100_PAD #define STATS_STOP BUTTON_POWER +#define STATS_STOP_REMOTE BUTTON_RC_DOWN #elif CONFIG_KEYPAD == IAUDIO_M3_PAD #define STATS_STOP BUTTON_REC diff --git a/firmware/SOURCES b/firmware/SOURCES index 3a6e49d0d2..46c1f58cb3 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -909,6 +909,7 @@ target/arm/tms320dm320/creative-zvm/usb-creativezvm.c #ifndef SIMULATOR #ifndef BOOTLOADER drivers/synaptics-mep.c +target/arm/olympus/mrobe-100/lcd-remote-mr100.c #endif /* BOOTLOADER */ drivers/sw_i2c.c target/arm/ata-as-arm.S diff --git a/firmware/export/config-mrobe100.h b/firmware/export/config-mrobe100.h index b1299a820a..3fcef555d4 100644 --- a/firmware/export/config-mrobe100.h +++ b/firmware/export/config-mrobe100.h @@ -45,7 +45,24 @@ /*#define IRAM_LCDFRAMEBUFFER IDATA_ATTR */ /* put the lcd frame buffer in IRAM */ -#define CONFIG_KEYPAD MROBE100_PAD +#ifndef BOOTLOADER +/* Define this if you have an remote lcd */ +#define HAVE_REMOTE_LCD + +#define LCD_REMOTE_WIDTH 79 +#define LCD_REMOTE_HEIGHT 16 +#define LCD_REMOTE_DEPTH 1 +#define LCD_REMOTE_PIXELFORMAT VERTICAL_PACKING + +/* Remote display colours, for screenshots and sim (0xRRGGBB) */ +#define LCD_REMOTE_DARKCOLOR 0x000000 +#define LCD_REMOTE_BRIGHTCOLOR 0x5a915a +#define LCD_REMOTE_BL_DARKCOLOR 0x000000 +#define LCD_REMOTE_BL_BRIGHTCOLOR 0x82b4fa +#endif /* BOOTLOADER */ + +#define CONFIG_KEYPAD MROBE100_PAD +#define CONFIG_REMOTE_KEYPAD MROBE_REMOTE /* Define this if you do software codec */ #define CONFIG_CODEC SWCODEC @@ -90,6 +107,11 @@ #define HAVE_BUTTONLIGHT_BRIGHTNESS +/* Remote LCD contrast range and defaults */ +#define MIN_REMOTE_CONTRAST_SETTING 0 +#define MAX_REMOTE_CONTRAST_SETTING 15 +#define DEFAULT_REMOTE_CONTRAST_SETTING 8 + /* Define this if your LCD can be enabled/disabled */ /* TODO: #define HAVE_LCD_ENABLE */ diff --git a/firmware/target/arm/olympus/mrobe-100/backlight-mr100.c b/firmware/target/arm/olympus/mrobe-100/backlight-mr100.c index f3891c5000..7dd80946cd 100644 --- a/firmware/target/arm/olympus/mrobe-100/backlight-mr100.c +++ b/firmware/target/arm/olympus/mrobe-100/backlight-mr100.c @@ -22,6 +22,7 @@ #include "config.h" #include "system.h" #include "backlight-target.h" +#include "lcd-remote-target.h" #define MIN_BRIGHTNESS 0x80ff08ff @@ -62,3 +63,15 @@ void _buttonlight_off(void) /* turn off all touchpad leds */ GPIOA_OUTPUT_VAL &= ~BUTTONLIGHT_ALL; } + +#ifdef HAVE_REMOTE_LCD +void _remote_backlight_on(void) +{ + lcd_remote_backlight(true); +} + +void _remote_backlight_off(void) +{ + lcd_remote_backlight(false); +} +#endif diff --git a/firmware/target/arm/olympus/mrobe-100/backlight-target.h b/firmware/target/arm/olympus/mrobe-100/backlight-target.h index ca5c548eff..df25106d1a 100644 --- a/firmware/target/arm/olympus/mrobe-100/backlight-target.h +++ b/firmware/target/arm/olympus/mrobe-100/backlight-target.h @@ -26,6 +26,11 @@ bool _backlight_init(void); /* Returns backlight current state (true=ON). */ void _backlight_hw_on(void); void _backlight_hw_off(void); +#ifdef HAVE_REMOTE_LCD +void _remote_backlight_on(void); +void _remote_backlight_off(void); +#endif + #ifdef BOOTLOADER #define _backlight_on() _backlight_hw_on() #define _backlight_off() _backlight_hw_off() diff --git a/firmware/target/arm/olympus/mrobe-100/button-mr100.c b/firmware/target/arm/olympus/mrobe-100/button-mr100.c index d4479278ef..e7979a4174 100644 --- a/firmware/target/arm/olympus/mrobe-100/button-mr100.c +++ b/firmware/target/arm/olympus/mrobe-100/button-mr100.c @@ -25,6 +25,12 @@ #include "backlight-target.h" #include "synaptics-mep.h" +#ifdef HAVE_REMOTE_LCD +#include "lcd-remote-target.h" +static bool remote_hold = false; +static bool headphones_status = true; +#endif + #define LOGF_ENABLE #include "logf.h" @@ -56,6 +62,13 @@ void button_init_device(void) { logf("touchpad not ready"); } + + /* headphone detection bit */ + GPIOD_OUTPUT_EN &= ~0x80; + GPIOD_ENABLE |= 0x80; + + /* remote detection (via headphone state) */ + headphones_int(); } /* @@ -102,13 +115,35 @@ void button_init_device(void){} */ int button_read_device(void) { - int btn = int_btn; + int btn = BUTTON_NONE; - if(button_hold()) - return BUTTON_NONE; - - if (~GPIOA_INPUT_VAL & 0x40) - btn |= BUTTON_POWER; +#ifdef HAVE_REMOTE_LCD + unsigned char data[5]; + + if (lcd_remote_read_device(data)) + { + remote_hold = (data[2] & 0x80) ? true : false; + if (!remote_hold) + { + if (data[1] & 0x1) btn |= BUTTON_RC_PLAY; + if (data[1] & 0x2) btn |= BUTTON_RC_DOWN; + if (data[1] & 0x4) btn |= BUTTON_RC_FF; + if (data[1] & 0x8) btn |= BUTTON_RC_REW; + if (data[1] & 0x10) btn |= BUTTON_RC_VOL_UP; + if (data[1] & 0x20) btn |= BUTTON_RC_VOL_DOWN; + if (data[1] & 0x40) btn |= BUTTON_RC_MODE; + if (data[1] & 0x80) btn |= BUTTON_RC_HEART; + } + } +#endif + + if(!button_hold()) + { + btn |= int_btn; + + if (~GPIOA_INPUT_VAL & 0x40) + btn |= BUTTON_POWER; + } return btn; } @@ -118,7 +153,32 @@ bool button_hold(void) return (GPIOD_INPUT_VAL & 0x10) ? false : true; } +#ifdef HAVE_REMOTE_LCD +bool remote_button_hold(void) +{ + return remote_hold; +} + +bool headphones_inserted(void) +{ + return headphones_status; +} + +void headphones_int(void) +{ + int state = 0x80 & ~GPIOD_INPUT_VAL; + headphones_status = (state) ? true : false; + + GPIO_CLEAR_BITWISE(GPIOD_INT_EN, 0x80); + GPIO_WRITE_BITWISE(GPIOD_INT_LEV, state, 0x80); + GPIO_WRITE_BITWISE(GPIOD_INT_CLR, 0x80, 0x80); + GPIO_SET_BITWISE(GPIOD_INT_EN, 0x80); + + lcd_remote_on(); +} +#else bool headphones_inserted(void) { return (GPIOD_INPUT_VAL & 0x80) ? false : true; } +#endif diff --git a/firmware/target/arm/olympus/mrobe-100/button-target.h b/firmware/target/arm/olympus/mrobe-100/button-target.h index 900211ebe4..93d42d62fb 100644 --- a/firmware/target/arm/olympus/mrobe-100/button-target.h +++ b/firmware/target/arm/olympus/mrobe-100/button-target.h @@ -29,22 +29,14 @@ #define MEP_BUTTON_ID 0x09 #define MEP_ABSOLUTE_HEADER 0x0b -#define HAS_BUTTON_HOLD - bool button_hold(void); void button_init_device(void); -int button_read_device(void); +int button_read_device(void); #ifndef BOOTLOADER void button_int(void); #endif -#define POWEROFF_BUTTON BUTTON_POWER -#define POWEROFF_COUNT 10 - -/* FIXME: Until the buttons are figured out, we use the button definitions - for the H10 keypad & remote. THESE ARE NOT CORRECT! */ - /* Main unit's buttons */ #define BUTTON_PLAY 0x00000001 #define BUTTON_MENU 0x00000002 @@ -61,18 +53,32 @@ void button_int(void); |BUTTON_RIGHT|BUTTON_SELECT|BUTTON_UP|BUTTON_SLIDE_UP\ |BUTTON_DOWN|BUTTON_SLIDE_DOWN|BUTTON_POWER) +#define HAS_BUTTON_HOLD + +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 10 + +#ifdef HAVE_REMOTE_LCD +void headphones_int(void); +bool remote_button_hold(void); + /* Remote control's buttons */ #define BUTTON_RC_PLAY 0x00010000 #define BUTTON_RC_REW 0x00020000 #define BUTTON_RC_FF 0x00040000 -#define BUTTON_RC_DISPLAY 0x00080000 -#define BUTTON_RC_FAV 0x00100000 +#define BUTTON_RC_DOWN 0x00080000 +#define BUTTON_RC_HEART 0x00100000 #define BUTTON_RC_MODE 0x00200000 #define BUTTON_RC_VOL_UP 0x00400000 #define BUTTON_RC_VOL_DOWN 0x00800000 #define BUTTON_REMOTE (BUTTON_RC_PLAY|BUTTON_RC_REW|BUTTON_RC_FF\ - |BUTTON_RC_DISPLAY|BUTTON_RC_FAV|BUTTON_RC_MODE\ + |BUTTON_RC_DOWN|BUTTON_RC_HEART|BUTTON_RC_MODE\ |BUTTON_RC_VOL_UP|BUTTON_RC_VOL_DOWN) + +#define HAS_REMOTE_BUTTON_HOLD #define RC_POWEROFF_BUTTON BUTTON_RC_PLAY +#else +#define BUTTON_REMOTE 0 +#endif /* HAVE_REMOTE_LCD */ #endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/olympus/mrobe-100/lcd-remote-mr100.c b/firmware/target/arm/olympus/mrobe-100/lcd-remote-mr100.c new file mode 100644 index 0000000000..036b6ae71c --- /dev/null +++ b/firmware/target/arm/olympus/mrobe-100/lcd-remote-mr100.c @@ -0,0 +1,562 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 Mark Arigo + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "cpu.h" +#include "kernel.h" +#include "thread.h" +#include "system.h" +#include "lcd-remote.h" +#include "button.h" +#include "button-target.h" + +/* Temporary defines until we sort out why the gui stuff doesn't like this size + (I believe the status bar isn't doing sanity checks and is writing outside + the frame buffer size). */ +#define RC_WIDTH 79 +#define RC_HEIGHT 16 + +#define RC_CONTRAST_MASK 0x000000ff +#define RC_SCREEN_ON 0x00000100 +#define RC_BACKLIGHT_ON 0x00000200 + +#define RC_DEV_INIT 0x00001000 +#define RC_DETECTED 0x00002000 +#define RC_AWAKE 0x00004000 +#define RC_POWER_OFF 0x00008000 + +#define RC_UPDATE_LCD 0x00010000 +#define RC_UPDATE_CONTROLLER 0x00020000 +#define RC_UPDATE_ICONS 0x00040000 +#define RC_UPDATE_MASK (RC_UPDATE_LCD|RC_UPDATE_CONTROLLER|RC_UPDATE_ICONS) + +#define RC_TX_ERROR 0x00100000 +#define RC_RX_ERROR 0x00200000 +#define RC_TIMEOUT_ERROR 0x00400000 +#define RC_ERROR_MASK (RC_TX_ERROR|RC_RX_ERROR|RC_TIMEOUT_ERROR) + +#define RC_FORCE_DETECT 0x80000000 + +#define RX_READY 0x01 +#define TX_READY 0x20 + +#define POLL_TIMEOUT 50000 + +bool remote_initialized = false; +unsigned int rc_status = 0; +unsigned char rc_buf[5]; + +/* ================================================== */ +/* Remote thread functions */ +/* These functions are private to the remote thread */ +/* ================================================== */ +static struct wakeup rc_thread_wakeup; +static unsigned int remote_thread_id; +static int remote_stack[256/sizeof(int)]; +static const char * const remote_thread_name = "remote"; + +static bool remote_wait_ready(int ready_mask) +{ + unsigned long current; + unsigned long start = USEC_TIMER; + unsigned long timeout = start + POLL_TIMEOUT; + + rc_status &= ~RC_TIMEOUT_ERROR; + + if (start <= timeout) + { + do + { + if (SER1_LSR & ready_mask) + return true; + + //~ sleep(1); + + current = USEC_TIMER; + } while (current < timeout); + } + else + { + do + { + if (SER1_LSR & ready_mask) + return true; + + //~ sleep(1); + + current = USEC_TIMER - POLL_TIMEOUT; + } while (current < start); + } + + rc_status |= RC_TIMEOUT_ERROR; + return false; +} + +static bool remote_rx(void) +{ + int i; + unsigned char chksum[2]; + + rc_status &= ~RC_RX_ERROR; + + for (i = 0; i < 5; i++) + { + if (!remote_wait_ready(RX_READY)) + { + rc_status |= RC_RX_ERROR; + return false; + } + + rc_buf[i] = SER1_RBR; + } + + /* check opcode */ + if ((rc_buf[0] & 0xf0) != 0xf0) + { + rc_status |= RC_RX_ERROR; + return false; + } + + /* verify the checksums */ + chksum[0] = chksum[1] = 0; + for (i = 0; i < 3; i++) + { + chksum[0] ^= rc_buf[i]; + chksum[1] += rc_buf[i]; + } + + if ((chksum[0] != rc_buf[3]) && (chksum[1] != rc_buf[4])) + { + rc_status |= RC_RX_ERROR; + return false; + } + + /* reception error */ + if ((rc_buf[0] & 0x1) || (rc_buf[0] & 0x2) || (rc_buf[0] & 0x4)) + { + rc_status |= RC_RX_ERROR; + return false; + } + + return true; +} + +static bool remote_tx(unsigned char *data, int len) +{ + int i; + unsigned char chksum[2]; + + rc_status &= ~RC_TX_ERROR; + + chksum[0] = chksum[1] = 0; + + for (i = 0; i < len; i++) + { + if (!remote_wait_ready(TX_READY)) + { + rc_status |= RC_TX_ERROR; + return false; + } + + SER1_THR = data[i]; + chksum[0] ^= data[i]; + chksum[1] += data[i]; + } + + for (i = 0; i < 2; i++) + { + if (!remote_wait_ready(TX_READY)) + { + rc_status |= RC_TX_ERROR; + return false; + } + + SER1_THR = chksum[i]; + } + + return remote_rx(); +} + +static void remote_dev_enable(bool enable) +{ + if (enable) + { + outl(inl(0x70000018) | 0xaa000, 0x70000018); + DEV_INIT2 &= ~0x800; + + GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x80); + GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x80); + + DEV_EN |= DEV_SER1; + + SER1_RBR; + SER1_LCR = 0x80; + SER1_DLL = 0x50; + SER1_DLM = 0x00; + SER1_LCR = 0x03; + SER1_FCR = 0x07; + + rc_status |= RC_DEV_INIT; + } + else + { + outl(inl(0x70000018) & ~0xaa000, 0x70000018); + DEV_INIT2 &= ~0x800; + + GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x80); + GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x80); + + DEV_RS |= DEV_SER1; + nop; + DEV_RS &= ~DEV_SER1; + + DEV_EN &= ~DEV_SER1; + + rc_status &= ~RC_DEV_INIT; + } +} + +void remote_update_lcd(void) +{ + int x, y, draw_now; + unsigned char data[RC_WIDTH + 7]; + + /* If the draw_now bit is set, the draw occurs directly on the LCD. + Otherwise, the data is stored in an off-screen buffer and displayed + the next time a draw operation is executed with this flag set. */ + draw_now = 0; + + for (y = 0; y < 2; y++) + { + data[0] = 0x51; + data[1] = draw_now << 7; + data[2] = RC_WIDTH; /* width */ + data[3] = 0; /* x1 */ + data[4] = y << 3; /* y1 */ + data[5] = RC_WIDTH; /* x2 */ + data[6] = (y + 1) << 3; /* y2 */ + + for (x = 0; x < RC_WIDTH; x++) + data[x + 7] = lcd_remote_framebuffer[y][x]; + + remote_tx(data, RC_WIDTH + 7); + + draw_now = 1; + } +} + +static void remote_update_controller(void) +{ + unsigned char data[3]; + + data[0] = 0x31; + data[1] = 0x00; + if (rc_status & RC_SCREEN_ON) + data[1] |= 0x80; + if (rc_status & RC_BACKLIGHT_ON) + data[1] |= 0x40; + data[2] = (unsigned char)(rc_status & RC_CONTRAST_MASK); + remote_tx(data, 3); +} + +#if 0 +static void remote_update_icons(unsigned char symbols) +{ + unsigned char data[2]; + + if (!(rc_status & RC_AWAKE) && !(rc_status & RC_SCREEN_ON)) + return; + + data[0] = 0x41; + data[1] = symbols; + remote_tx(data, 2); +} +#endif + +static bool remote_nop(void) +{ + unsigned char val[2]; + + val[0] = 0x11; + val[1] = 0x30; + return remote_tx(val, 2); +} + +static void remote_wake(void) +{ + if (remote_nop()) + { + rc_status |= RC_AWAKE; + return; + } + + rc_status &= ~RC_AWAKE; + return; +} + +static void remote_sleep(void) +{ + unsigned char data[2]; + + if (rc_status & RC_AWAKE) + { + data[0] = 0x71; + data[1] = 0x30; + remote_tx(data, 2); + + udelay(25000); + } + + rc_status &= ~RC_AWAKE; +} + +static void remote_off(void) +{ + if (rc_status & RC_AWAKE) + remote_sleep(); + + if (rc_status & RC_DEV_INIT) + remote_dev_enable(false); + + rc_status &= ~(RC_DETECTED | RC_ERROR_MASK | RC_UPDATE_MASK); + remote_initialized = false; +} + +static void remote_on(void) +{ + if (!(rc_status & RC_DEV_INIT)) + remote_dev_enable(true); + + remote_wake(); + + if (rc_status & RC_AWAKE) + { + rc_status |= RC_DETECTED; + remote_initialized = true; + + rc_status |= (RC_UPDATE_MASK | RC_SCREEN_ON | RC_BACKLIGHT_ON); + //~ remote_update_icons(0xf0); /* show battery */ + } + else + { + rc_status &= ~RC_DETECTED; + remote_initialized = false; + } +} + +static void remote_thread(void) +{ + int rc_thread_sleep_count = 10; + int rc_thread_wait_timeout = TIMEOUT_BLOCK; + + while (1) + { + wakeup_wait(&rc_thread_wakeup, rc_thread_wait_timeout); + + /* Error handling (most likely due to remote not present) */ + if (rc_status & RC_ERROR_MASK) + { + if (--rc_thread_sleep_count == 0) + rc_status |= RC_POWER_OFF; + } + + /* Power-off (thread sleeps) */ + if (rc_status & RC_POWER_OFF) + { + remote_off(); + + rc_thread_sleep_count = 10; + rc_thread_wait_timeout = TIMEOUT_BLOCK; + + continue; + } + + /* Detection */ + if (!(rc_status & RC_DETECTED)) + { + rc_thread_wait_timeout = HZ; + + if (headphones_inserted()) + { + remote_on(); + + if (rc_status & RC_AWAKE) + { + rc_thread_sleep_count = 10; + rc_thread_wait_timeout = HZ/20; /* ~50ms for updates */ + } + } + else + { + if (--rc_thread_sleep_count == 0) + rc_status &= ~RC_POWER_OFF; + } + + continue; + } + + /* Update the remote (one per wakeup cycle) */ + if (headphones_inserted() && (rc_status & RC_AWAKE)) + { + if (rc_status & RC_SCREEN_ON) + { + /* In order of importance */ + if (rc_status & RC_UPDATE_CONTROLLER) + { + remote_update_controller(); + rc_status &= ~RC_UPDATE_CONTROLLER; + } + else if (rc_status & RC_UPDATE_LCD) + { + remote_update_lcd(); + rc_status &= ~RC_UPDATE_LCD; + } + else + { + remote_nop(); + } + } + else + { + remote_nop(); + } + } + } +} + +/* ============================================= */ +/* Public functions */ +/* These should only set the update flags that */ +/* will be executed in the remote thread. */ +/* ============================================= */ +bool lcd_remote_read_device(unsigned char *data) +{ + if (!(rc_status & RC_AWAKE) || (rc_status & RC_ERROR_MASK)) + return false; + + /* Return the most recent data. While the remote is plugged, + this is updated ~50ms */ + data[0] = rc_buf[0]; + data[1] = rc_buf[1]; + data[2] = rc_buf[2]; + data[3] = rc_buf[3]; + data[4] = rc_buf[4]; + + return true; +} + +void lcd_remote_set_invert_display(bool yesno) +{ + /* dummy function...need to introduce HAVE_LCD_REMOTE_INVERT */ + (void)yesno; +} + +/* turn the display upside down (call lcd_remote_update() afterwards) */ +void lcd_remote_set_flip(bool yesno) +{ + /* dummy function...need to introduce HAVE_LCD_REMOTE_FLIP */ + (void)yesno; +} + +int lcd_remote_default_contrast(void) +{ + return DEFAULT_REMOTE_CONTRAST_SETTING; +} + +void lcd_remote_set_contrast(int val) +{ + rc_status = (rc_status & ~RC_CONTRAST_MASK) | (val & RC_CONTRAST_MASK); + rc_status |= RC_UPDATE_CONTROLLER; +} + +void lcd_remote_backlight(bool on) +{ + if (on) + rc_status |= RC_BACKLIGHT_ON; + else + rc_status &= ~RC_BACKLIGHT_ON; + + rc_status |= RC_UPDATE_CONTROLLER; +} + +void lcd_remote_off(void) +{ + /* should only be used to power off at shutdown */ + rc_status |= RC_POWER_OFF; + wakeup_signal(&rc_thread_wakeup); + + /* wait until the things are powered off */ + while (rc_status & RC_DEV_INIT) + sleep(HZ/10); +} + +void lcd_remote_on(void) +{ + /* Only wake the remote thread if it's in the blocked state. */ + struct thread_entry *rc_thread = thread_id_entry(remote_thread_id); + if (rc_thread->state == STATE_BLOCKED || (rc_status & RC_FORCE_DETECT)) + { + rc_status &= ~RC_FORCE_DETECT; + rc_status &= ~RC_POWER_OFF; + wakeup_signal(&rc_thread_wakeup); + } +} + +bool remote_detect(void) +{ + return (rc_status & RC_DETECTED); +} + +void lcd_remote_init_device(void) +{ + /* reset */ + remote_dev_enable(false); + rc_status |= RC_FORCE_DETECT; /* force detection at startup */ + + /* unknown */ + GPIO_SET_BITWISE(GPIOL_ENABLE, 0x80); + GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x80); + GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x80); + + /* a thread is required to poll & update the remote */ + wakeup_init(&rc_thread_wakeup); + remote_thread_id = create_thread(remote_thread, remote_stack, + sizeof(remote_stack), 0, remote_thread_name + IF_PRIO(, PRIORITY_SYSTEM) + IF_COP(, CPU)); +} + +/* Update the display. + This must be called after all other LCD functions that change the display. */ +void lcd_remote_update(void) +{ + rc_status |= RC_UPDATE_LCD; +} + +/* Update a fraction of the display. */ +void lcd_remote_update_rect(int x, int y, int width, int height) +{ + (void)x; + (void)y; + (void)width; + (void)height; + + rc_status |= RC_UPDATE_LCD; +} diff --git a/firmware/target/arm/olympus/mrobe-100/lcd-remote-target.h b/firmware/target/arm/olympus/mrobe-100/lcd-remote-target.h new file mode 100644 index 0000000000..b5a501046a --- /dev/null +++ b/firmware/target/arm/olympus/mrobe-100/lcd-remote-target.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: lcd-remote-target.h 11967 2007-01-09 23:29:07Z linus $ + * + * Copyright (C) 2007 by Jens Arnold + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef LCD_REMOTE_TARGET_H +#define LCD_REMOTE_TARGET_H + +bool remote_detect(void); /* returns detection status */ + +void lcd_remote_set_invert_display(bool yesno); +void lcd_remote_set_flip(bool yesno); +void lcd_remote_backlight(bool on); + +void lcd_remote_init_device(void); +void lcd_remote_on(void); +void lcd_remote_off(void); +void lcd_remote_update(void); +void lcd_remote_update_rect(int, int, int, int); +bool lcd_remote_read_device(unsigned char *data); + +extern bool remote_initialized; +extern unsigned int rc_status; +extern unsigned char rc_buf[5]; +#endif diff --git a/firmware/target/arm/olympus/mrobe-100/power-mr100.c b/firmware/target/arm/olympus/mrobe-100/power-mr100.c index 25757f62c1..26dd4ef14f 100644 --- a/firmware/target/arm/olympus/mrobe-100/power-mr100.c +++ b/firmware/target/arm/olympus/mrobe-100/power-mr100.c @@ -27,6 +27,7 @@ #include "power.h" #include "logf.h" #include "usb.h" +#include "lcd-remote-target.h" void power_init(void) { @@ -57,6 +58,10 @@ bool ide_powered(void) void power_off(void) { +#ifdef HAVE_REMOTE_LCD + lcd_remote_off(); +#endif + /* Disable interrupts on this core */ disable_interrupt(IRQ_FIQ_STATUS); diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c index 967144ad0b..6ce45a12f3 100644 --- a/firmware/target/arm/system-pp502x.c +++ b/firmware/target/arm/system-pp502x.c @@ -29,6 +29,9 @@ #include "button-target.h" #include "usb-target.h" #include "usb_drv.h" +#ifdef HAVE_REMOTE_LCD +#include "lcd-remote-target.h" +#endif #ifndef BOOTLOADER extern void TIMER1(void); @@ -121,6 +124,9 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void) else if (CPU_HI_INT_STAT & GPIO0_MASK) { if (GPIOD_INT_STAT & 0x02) button_int(); + if (GPIOD_INT_STAT & 0x80) + headphones_int(); + } else if (CPU_HI_INT_STAT & GPIO2_MASK) { if (GPIOL_INT_STAT & 0x04) diff --git a/tools/configure b/tools/configure index 802173f1b6..946cbdac75 100755 --- a/tools/configure +++ b/tools/configure @@ -1569,6 +1569,8 @@ fi tool="$rootdir/tools/scramble -mi4v2 -model=m100 -type=RBOS" bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" bmp2rb_native="$rootdir/tools/bmp2rb -f 0" + bmp2rb_remotemono="$rootdir/tools/bmp2rb -f 0" + bmp2rb_remotenative="$rootdir/tools/bmp2rb -f 0" output="rockbox.mi4" appextra="recorder:gui" plugins="yes" diff --git a/uisimulator/common/README b/uisimulator/common/README index 6f920cf43e..3ee2b45f0e 100644 --- a/uisimulator/common/README +++ b/uisimulator/common/README @@ -8,6 +8,3 @@ This directory is for code that is shared between all versions of the simulator, but is not needed for the target device. -The first code is for the software mpeg audio decoder. The actual -mpeg decoding code is here and the O/S specific sound drivers should -be located in the x11 and win32 directories as appropriate. diff --git a/uisimulator/sdl/UI-mrobe100.bmp b/uisimulator/sdl/UI-mrobe100.bmp index 19e5e1f3d301213e9a52746ce24433de04d22d3e..2a9df60cf15ad16e3db9a29442d9eb103f2ed255 100644 GIT binary patch delta 27722 zcmb__2Xqui)-{qQcAThDLV>7&5DK82!zgDYa?TRT#>RM!+g@FK)t-m6!yYBqM7e*A|;$}0IW zO+ASG8;8G8{N2RgVUIzBJO=q7H)zm$oFBptlK?b)fy)jgD(KkhYVH2QGKDwO_l~afRYS#}xZ<0nv8p63~7Lm*IBWuC(LU+OKwWT)BD`Pn`Vg=s>2e4IO}czj_Vdx~=`n zrOWLXE+XyfxN_rK=k=?d9c|aHc6434(oNEi?yjrXyE|{*x_Vn(1ujAC+yEpINyLscEcW(dl?wx<$yGwBQ&OdJ7x_9d)3jYDz zzU7L0ICb~ly<4{lZr{0k^VW@PU0qkMc3-)A=Jbze&zv7L=*6yxccsoN9c>pbw4FbD z`P_+%r~Z8I__4F!|M~3qe?9a4pHKhoPpAI&?a9A>^TS_`o%qYK@4q|zw{H)9F9R6` ze>%GV+r!P@9HQ9wbt}O!k~V*Rs0HcKgZqvgXgadL>2OQqA)tA0YxAB%Eqhx5sbw!I zlF{1O(7I>$!9BYUHtagkuygNkXIt~`txY?(?Ax_<-!A00 zH8*T;A=t6MVcUV-n+`N=I@qxJ;GQk5z}~Hg8n+#8+J0o;&ZEr~yN$jgr;oC=Hhs2k)B1Ir*OL_a4IjS0{)6|v{OE%%pMMH${_K;z z+ctl5u;t?U_LC>hzIZL-J?Z#g|MJQE@BR8o=@)BOzVz%vFFw8E)hAZGvG#%2*RFVd z?ftK>UH+N_OJ99r3B_wqE_Gtr>rX9vW$ogZ*VMlR{G8xL;PJW_A4du-23~l4@$-+> z1HX~#e)DJ@GAMcB@g*-lzT^c7f5`oODe$Yu7C$G|1J6EM_w4GrXI3wI<`EgI7Cp04 z#zTvqC8#4`WdSh6Fgi$^=EYxDITetL{RUF$&b_nE+uu7R?B#_ zezF2-@svk_B~vL@FPXY}@f3r>tH&?U5x@AFiKFuw?4WB~u<; zJb6Xkr27_4SiYcU>Adkv=2b75SF?EjgG&bFspXSf+-7U*VdHhmgT3E<|UNp zCs!4vRu`uORYhr)1t}E;Db>Yk$RmTZ6cvT3)kW!(i*qIyXHT{lXHP21Cb^QFsinD7 z%kn0dWlkx}oLovUsWgLTCYNQ+C@-8+k~gh1e`aOTYS)5DSLE9R%AuysPc@6lJxMR^zdQ@C;>7fN>U?Ak|Roilu>0AsgdPCN@RKR zsQxHUiYQ15cS6ZW*b^gi<0Ent9LP(E$V-qS@)AeoC5+08#{tRM6M@KlASseukPwAh7}}+<|mBIj~{7|9|1^ti6irH zoD^D+90ueijIbw+$WIQnr-a#)L-UeH<|dBFP8gOoZfNG%kc_cIQsagt$AqNB49QLk zt1U^HSe~Af9G)6CBsDfDEiM>oN=#t#n8Arr{)wag5+eP^Mc5J|eUrxoq>}Ogl*ENu z#|$@x`|@EvT&Uf~g!-@%etcA*F>a{$xZytIMtF}MVFlubnPZ2VV}_cdhZtjqn4*KN zqXSIQLDsmTK2d?@q|m^+NoDW8@XXgo|I~Krs?4P$yLT-bUzIo_XjHIyScn)9!Up;? zLB33o4-@Fa2HIGpK|WlNFBjy^j|eb?4mJ$;=R<6Kus1*4PZ;XM2P1D2f+)O&Aa5a1 z#$X%Q3qD++3{vO~umM)qU$Qd(7QLSt(D_>&2(ap0;cwRY8GFIsqytEyK@a%%hL5PV z@@j7dg4$b#nbR0pohyv2q%*Qw_h7UlqvaS)f3SKDtJC&}PN(&92enqKSG$2$t&u!c z>OS!BQlZ34?FK5fMyt~6HCnAkWi+zs>G4@vsd}wOuhrr+G&&uHRNojEvsdC zoglCrrxOgk$t0K!`d}M#|NNSFUs?0r!Edg2T$j1@byMTQ+S*b6zCOI(AZQp7;Pe8o z<2fzIX;@anP%yk;}C7@eISEKn9Cj*6CTD4q&u;Mx$p?i$ce; zdX4~x8Xf(zj80-09Ra>60mJnH8Ydsau)G80*a1DhAtO-e89{-L;qm4BL&x(vQRoec z9BTz$!*hU^XI-J^Io2&W^1b_m;dw?B`hyh&o)_Ih;slZ91%Sbm<*VQdr zuwdc*`EzE?%E`*&SXRaAG(4jfSO6I{r>BPu&uUmbn1OGCr|4_Z-M_H*otGc~_Q2OS zuiTKi^j+)0`f1a{{R6#ugF!U%CW}U}s(Gu5x2QO?mkV^Fw@Po&a278Or)G?vI)j$C z0vguT8%7OFpkfRv#;9fqG@MC>S;LuCtkDZ+DJ1znHD~%snAMyc;O0D7iyLs3LGIwe zn><8AZ%77D6bYh-AoPcd7j*+b&l%l-7xAp!LC_00MZma#6-0>_4ICgd>R)mR{V1{q zqaX@A>+LOOW+vw3qzfEp5Jgwwu{`)gz=@)0wxDsm>3B(bP5_sR@(bhR#u`P@Vlw&J zeSFMDBX}MX6jWAHGJM!jkOwT%8z5Tn>TwjvvjT(*i!aBD_P{M#=*{!Po# zuC^|jOMg0Yc=3$cp?*PTy^&+l*A^8E4v1>j-~eY(%ka|igS>PsZo%qjvihsgvS`t; z1|k4iH_)?q*F=3k=r~aeun>ZRT4H!L!>jZhpkW1aLWYJFU7<$Re(>T9p1iRyIHSiv zU=5y(10IY)hD84JWDQ=NQGq9Cr0^n7!X1=n(>p`H0L%4l%>QfgEAuhugZ zO1WzW5*H6$fDmJKMl+wBHa0CI88V$01pEOyjwf*51lmMvXaPz^)*!6OXr4A@T4Z>H zmxl)!1PzxL9Tlba@-hfQRz^lxXsD-7qhj@19{LQ54WilsM&O~Sh*ZQ4@H&f8TR*4j zt(SlP&HkgeyKc)|`s=Zy%V*CE_Y3jnECLU1m_ZC^A_z=EY^S7U1zx36CnqJ>jIVj( zi6SydcCnfG?2dT0s4vkp=Jd=lu18mc|pbVZou&pr4S_y zp#h}?VTBvu^@L>L(4{cuOl)FGY)V?9p22mzLOG{RLRh4dff7nEXitm9I)C1R*qB(T ztK`JQ3HF+rSut z7*o?T#@Ezlq@|^&rsmmma$s`jW@qQ;=043o0$|rD1*if}VKtxs|I{|LQj{ zJ@<>}S4(Syf`+NJ;1aBB6RdGU5}nust>C4>wW3OAQ0t8vy%8y(a)Hbx9WIkWi0FW) z-q;%kPjIw1NM)THsB}j6U<5CY>kY|y%yVA-fVWW@S1B2cM`hrh>kp1Tygn)3PKI*> zXhX>%aOAGTt4}*kE_7IquG}E+2Zri;y-KSROngd461b#e^$_x|#B&j7qDFwF$x`X3 z(&_PHgbW=vbJlE(<5t{v-wOME_uaQ_*#r0AKYi-d5yOUwf}qfvUgo9KqXdjnu@J5> zqlr9*fCramPc3`<)u)d(ALzc;E$g_`fBEj`_b-na>~Dj04iU=1UILc{nkw%YYz_Ds zl9JOGE?V--U%l|qs?|x!X$GSeV+e+W1S6NAj#|e7q%r|Y1ho!@J$YE{y?|%gbFAZ4 z{|RW*{ZsnE{ZsOW^o2x)s&lO(+hyTV63s$#dSY5u8mt3w3H(v2(F|pjJgfniNP`-d$U3BE zZ(skxgZ%;q``hssFgPG!u(yvdc&3H1t}suQl|6?nqarHLpyN!Cj2Pt2omTqhi;o>> zKG4-k$8l%=`lmH3mWL1a_vSI&6ZFLP?%@Vy1*oFu3|=a&Aew4wC;#k`$7ar&XY&cb zI|B8smx~!o?qS4eDLZOYI~pk z+n=9UxnfjcfR*P3m};CE9iqq?$|bM@C29?mXD@nW_2Y||-1p>D&rO&()ok%Wq1GXV zs4Q|xVQ6W2wHCtN1RsKb;INQk;loBmjtn0Y77-mvA>qGpU<@f86%!sA7akc4gaM;s zfKa4ziEAM(M@fY9RCr`exLjXuBzDy3xCjS&>Yy-k%vfMllmaPEE*%#Y6CV{FKbl~i z17pTTj&bIr<56KuY(jKwVsspk6djwaU`$N%n3yCWDmroWm;{Q*sD#Lf^>HmRF4b&GRph3>^h7X=J_T zqS~Bvg88k5KsFjoe!)Y+@#s_2?b*2{_JWH1!b+f^sH#B1pA*HUH6>-WeSpHElJSMb z)%}5Toc;fU^i$X4BXP5?_lpvIYEdyz;}*pwwf#|0Se=_!-XD4Paw#{zJS(pxE3Y^? zJ!fcWgpN0mj+T{?LW7<8z*^ogA9bIS?E`d&z zUJ937>7;_7MK86W)`+6P zH)QCjvE$OSa!T?Gt7KAu9pg!_NF_DJKxu7BX>DoQgtGF9?l1wT+@hpxf)jm7*uzP= zakSr4(!*GZlv2Ku+xa)~A9Bep>rhxwG+xTFmuKac43SfAgis4<9<#d5!u6E}Zz=uOC|-H*&a5BwS*63$>TPA_^!t$`j1@O`1GidTcGy zC!T!v&ELMYblHmZj2zKuRp>-@B2sb*xTF$PYH-PK*zl;tq#S#GWl8A-ytjCcNRcm* zNhNXR9lVA3)02{>FNpajiRQmNE>o6Wy^{KRF;9{{74-}m6E zhaVkZGs$fAh18;=$(2i549(Rd<`~;VJ6UMlr}`^uB0VkOR*c2luUHXv9hwsZc$P? zNrG(3%dadb9uF>sMaId)I?S*49h5m}AnQ1|CN+8;xCGlfJu3~aOK^#DMj;_G04+q? z=PYz6lgQCK)LuV40g|o_k|LWTP zEv?;MH)VV2;)%b%^3)UY;bFul02@hfl7}w6JZ|6;%qRE+fQ-!Cy82~Prp}Cx85a~h z%xtm2_U=O@Dwl|7Nkc@FVDKG2JSr(MCqJ*ExNv-FiOeNg6gjv==mg0FI>}HNMGxH) z35B?%A2&z|r6riz2Pp4XU*=MO3jK?c^2u&FGf*Ko=9YVqVBk`Xy#O}j_*{E=XhbZ= z%Aga5b&3q>m4WSziC6dw8E{ERN=r=7O2<5xN~`zK=smTtmkDhsa0uXX94cpVNMsjM zYINIWtDDjZqKPOwJu^tH8RVt%P-~C}oj|HVD%BvZYLHInMcgM45LzS8ESOmaE*;o^ zsH>C430ye-_cxw5B_yjVu@>W0kbEvkJ4?ThuT=MkP z5O<|Klv4y6%|Nvh&!ko~82uwcW789JOY*9!iY8Q)PAo5*2!%#;m(*K%DO{=JZ$KY5yQPSnn9j$EwF*XL%edI)O`yzUz~5t6XKu^`cV`mx_ueP(v!epkh>1EZ$sjNkhDm&f&02 z23+#gi(r~or!|}SjI_ku+$_YQ7z~Cydv0ZQB|ML*sj0JP&w22{ho(-QK6r3Yd}31V z#7T8amrb5N!`nXq!Uo=aH7iRe2q?RA+K*aVYBCusrl)1!xBS5c3+nCmqR^3}qQ{I~ zv~Y3VoH-RmrSY*z@v+G(mfsf=Xqz%2_pLXdKHPM$v+bI!<1U~4;jQO?og5kIBN|2G z(Zo2;y<9@j+0)Pba>WCy!oy+wq=8E?yb*oZhfB&sfLy}h57Q{Hy~9Vwq$lJS=T=q~ z)>f7hp#-3Bt0kviQzVk2;FL@svi-|Lw=#wZ!QL`ZK6J_@w_I{hjDd*+Ub(--#a5>* z>fusx@kC;p7uCQ?0=e|>bID>76fPm6sJI~iap}>ei|ZH6nOj^?2!l<}VBjk3i5SeB0Uqxdca~Xw1*GSCp1lS5z%tRKM!Mhh|Kfo|>3kkzX)x z+N}E*uUIf^(dw0}!iMkq&sFiI*ZnFKBY|2CIkIUsmdOSqIubev!? zuq>OFm~h|X`Z?35l@%0@4h@eOKC-r=dg;RYvV!6rq7Iwi1hM=+mQqcQ90CC zEPwMg5YfVS)1|=D+jG z6G!*8b~$uh$Jx{GzxGPnm}uxY!X?%^ki7)jfYb>IDVUPO97;-RCb&d`f#KM9nMMJN zs1KosOQLV+@G+_J*+n@Ogi9q8+}leEF%&ZNFHuhY7a4c*N+QzA-3ekrxm9o|bWfOp zi8qjrBV3|#spvnDOOW=6$9CZo;vx;koQ(7dRh7eogG2lSVk4u9F)S=D9T_roXkgHo zh{(*8w29RGHMGze)5H3ZfjLV{2DleH(R!ZnZx)44Ar6(17^eMq%AA#}H zhsx#sGxS22a*2HWK+XMxTyjgNKDJZOVX4DcpeQ&xtb?s26&6z86S2K95kzh8pR|`K zmvo9;5=|z=FNKAU7!?tYuuGj*>us@wjSL$(Yy>Q4gw0t^=8(YPk;6xVMTpfWAY*+w zKB^CwAo36n6&M^eGIXTX+X}M`KxSm<2$Ml1aS>X<*X%!fL};+ZFsCM0=2EMZOIOdG z{qW5XOpR(y}Uy8nNDl#tBd&p_;2)LPV2Rw!HV0OaJ>^ zvYJKMOWE0(2D8~qr-LgIv#$U`Ry=Wt^-UPBLH>}XKqMkuc0D3;8D~+=IkD15E~yya zgW)~({2&c82<|FY06gKb(z9MzpTZ$1i1?SVpvA|;&YF<-_RDKsxODx}#n0aULwaLpH$w5@>nn9A>u3qgI2w4ta26lG zA>pIq5|XeKt0*t8EZ<)4fTZN?<#;pmWY7s!w<)dAry34(?PWktUMWEH{Zo2YNiofw zohy~(*l;mU=1KC+cKvpJA3o|kc)3XKuPW1t5x|F147W5#aFfF~vEu@sRg5(r? zT6$qpYTl6HqqK|xlL-AiOSA-@LJvk%Vdht-F`9(b)P$VeEa*5gAB!1YtWUs<89YdE z8nKAZMuagYN{HVG!F9xqgt&9Km=M`QoJlAV)ONi8(00UkNxV$Nv&je^TGm6y(bQ81 z?>UF)auv^dX!V{Ntc@^fGu)O(7SdcR3OlQlEEr&f*iXDO-iIl0+{OY(dit>Z9+WOIm6L!OUQ=2mDOh#%0B zz%F~(sUIBPZvb-`u7Fk~%7)MkE^*9oAhOelpkRxMtF6xY?Q2gp@85s5v_YRe!l8)5!=fAp#5&ID)}u z^9>FP2?e9V!lJ{&V}OY8*a!)KPK1WX$gxaFdm|zyj35?pJvAb93^06T6fkVW=%K?S z-2$g5@Yx|lBNQMGCU}Sxj^iOiB8ECKBqSW5heJ>s*Yrd1(1^g0u%IE~|1LtpgF+(u zBQQ8z@*h0XFJMGKP^f?42&2Ux6DSY^w8#6WgiEqqQb8_(ODW(|mcbpDlxyk4oWdnA z4MD$HFoWO`z{`%XSDCexNJv2*g-di0)rU)1u!-e%luN&R?Wsep2d`dkb8_kPcit*W zO#_#B)&MTafr>_jNR%pI3vBPffkV>Lvvczxva=Dq#4v)XJ*0gEpS9Gu>#^=dvS?s zJ#YyW+PZDm&Ru((TUytD{uS|i>p6_$TtyQ#zh!-gDP_tf_{K3KK*Ds9dXZ=-CnO~& zXL@44UE{#D)AkG1Mgbn8(5za0yfV&T*FF2$C~ij3~<`#OP{F1}-HrE;l>VY&L7K zz8kCZos|_LAw$cNQMg3UdLX#PMJ_qxES&>L%A(#}LXZH_aT+Zm09dn$t*y>}^OYwK zHZ@*6cTVQg&9=*5zV~ibZmzGvB*ONVxkTwiDWs$@voR9~pVHWINd<+apMLfQB2NMW zf~f?fYK{`APpaIPLw33bdeL>e^y|6WTQpA_rFTGOA1!gI*%PC!6yoy~DcvVSZ^flh zB2j)|caJJ?nW9JNhtfa2GAMTkEECa@bykEC$jb|lWeZoHHzhBBZ$O(#UK$M2U1I|{ zPXv(kmNUv{Bih=N@SFH5%|o2Wo+P&kFgG+a>T-o^kd*khPKcm?wT48&0 zg1JAJKp5()#C)zjzqqid3~~uvG8oM0UaIEkUAPhncjS6V^JGY(7?!SFQmQJfpc#As z6?~LV%GrT9g9@~!+f=z+{y2%upkhXoK4yAfO1I#UhHtp`2Cb>oahvJ+ehzs6t~$cY zTr=RXgy1)sOH^)A*4LNvijW%O8t%_qml=4NGhTdXi#m5-zs(nH)UjXZI+ zz~u@U;$bD4L2W0Lr{g#h4hP2*eLm!=$jZ*qDdZ)Pxuk)MN#Rn~8!xYIX==E5hU&Px z*RF1Qe;sCn{EZfi(VG*!S(!_ESV1tVWgrhD%F|1ekd(Tsq4DsMZ}zpc{{8r=X)|WS zqQ^QEDw=Q?j!%~TZ1TO3u2OoB_AU9Er2k|{N=`0yyM>3h8S=Ghh^9msaK%>>$WWhpk9aatzn4NHz zV7Z_m28Ij`2oCY_AN;Eq;Q4;jYK1?F*h@rm$V;HLxHU&)W{>`%Rt$Lov7AWDW9tJ4 zBrQ3n7;r%gp=KXLh?qGrXQ*j|3^8q->+$4|@A+(cR(?J`kBC}H8olIfSJqk18+U#K z+1sH=H|3kjLuibX9h#0@g)dFujB8frCrKUDRNOa2%~4kl96z{3lJAZ-MCzdw;YR3N zS4t>(taMZ{1~TN*Y0PFZIbkfO;ry&NEVgvq4KbOBa>cDsMXOK)-2{P#xTffsxPZaI z=&V6%9ma78(B(|tHVn-}hL0FFGR$fVK*ST43~KO%$smJXPRM6FnBZWiYy-gTaREF+1bBwv5(~|xGFc4C z$qCqnE5PPMxa6?U2$6a~Rs>?h905~Z&>$wGskFG{;gu_Es;W~`Q-=;8F4_$Sm0BG# zWJt|~3HgPERn;|EW#k2Wjllwb#MqG)g~+fB0`6GEbb4vw7`3QC1rs-|H06&kKDKxF zu8U`>?R~4Gqv4CMW{$7LK;39E^A-@vEXojgGr)5u3XP|3Y~;92pKd<>?TP)n54`u= z|4WHW!*)+Z9PtJPijtrvB}vI6LIjtC5z07+jD^TrOLY& zsMhG<<4Z|N$;r+xEXZH6V#VUci^J^LjKb5?&(E*8xHvZ#rf@+*QW~roMVvt{LGEI> z4#A|>z<$JDT2@FZn~AL{h=1+bRXewCRc!C8SN3k&GJC=#8x)*i(2Js8G%*IV3vdW| zWfoa0r!@xHhWMBRy^a1VPrYgo<7W+Gu;M^AtCS~5GxRC-_m)s|){#nX;@W#2uCobZ z0()v@WiQ7xD}C#*x}4IGiU*}joEb-hHn8^5}EhVG+#ud8d{_MHo+&j|MM_px|;TfB8lEGm&MC>qt^}iyIl@fx919&XqG-BHUWg?iGAjHm) zWYdaBeG+hhdv*dU+X=dPAPGm1>(D*ISl)m}DM-^jz@l{L#)I+#buu;}H-t6duoy5@ zAX|(%>q}$_yPoVgg}ETdUOpu7PzFj|H#t!%V6vUmSKz#mmb+_;22;SUb$}XXIKLgX8x*V?RxoQ&k6oXlXG4SRd($=)jtkj)fj zpmB!B$O!rgVg)N4O>uEC_Pm_2aWR4Zeg@RHYt%Zm3PDPl>1ip63F&ER!^6TTKRZd2#Bmo__et&(~i#bz1f>-MP`dXUER@GiHv&B5fc4 z5UY>T+h*{#305og9cwb_4F;Vk;_HB+c%2Lu8-#>jFv908n7w(ERbUNdk4Dyj?e9cv zch>_EI~zJSzoWY_VY#vk$Oe@X{+s|emCYWp%S+ETNLaxmZ|W&;aw+d_NjAU4SO$-j z0-JsIO+e|Mm@Eo4cuZuoOpK{zfXh0xuGK03^a$T@0_9rzkL)(8)zE*4 zn5K{qQLg+$BYOFt+<>D=L;xY?Uaiup(Q8g<5RR&5(2tUu{L>JS=16NYboc@ekj+a8 zROA%d=oIZCD8SEV$VwfTmzFfd=4~Q7qLEEM`vQBO%A1N}|1Uy8oyKN14)*ajf*)En zt5#X;hzMfzxPGwB8y1a^#e_~n$O;~u9BDxM22GPx{yyX`$t`&K`-m0AnNR9Ie1~ro%Hb&Vm_@F%a2r0>c81I4!V$hwRUA>?Fz1 zLIKj$%wa{cXvOytjW#-yW3u|1EIvlbY%`c_Mohezd`xCvv)RvL@wa*hc-w%%HlM*h z4g~u6DjgZ+Gi{Jlqqh2&u$-Gtb%!T!PCRv(inL$H|y zn^A#CzMjG8YcdB|%)vJAV4KCyAov*#fi{cH!28-w;?Mx!U|(+^qv$OP0p2EGt1-aG z;%_t4jGwp3W)^*|COjDMEx_A?IzhhX@L>U^`RR{7w0z?i8!ntaBg>^5w{JG=+O=%q zqMYcl#j%Oy(Fvt738k@#Wyr@R0TpADE61e(Me*aR($kO@C&ZT~C6=WmmnA1vq^1-l zXBH-97A0pDCTAg~8RU!8vPyvT?9z;!vdmm8o38+}5gCH`5JZXOSJ(?HC3|62eo=K{ z2~d+?TAN=wp`aX?SXeQ+xC)q3Qa!D_dV0n98C5m2#!n=uo`C$cit%%5Ce52TW&Xse z3nounIAuoN)S30uX4Oxhg*-|YOrE}AlAIzVAL7)KnRAxTn!9ZFyrr|}EtxfU@eFBB z-LzSC(`VMrm{~t#*5X;Sm(H2HeD3`F=Pz8bV37k07p+*h=z&Fb57yPoSp49k`Ue)) zp+p8LTv@jm>HP~9EuXhw+1&X{=gdPpi)YQLpEbLF=B&jt=PsE!zkd4MMN{W2nl=ZS z#WUwGoxO0`+=bGzdGmqg^B3H=VB!7blj?v6>KCtEx@_f=r81CNMh=%QdvM9}6-$>d zt6Nk*Z`QI!vz9NMIb(czSypCcPEJ)GL1kWcWo~vwP8Lv}omrZhS)74le_j94$FKhSH?KVR%U7TM z#aqAl^*g_M{@q`{@PE(0wC<%>KYsO%PhbBnutf&7>2KHl=l=j8C?^_xE1uzCF#n?L=0=Z1~jKmW36%l5rrZP~uz ztL+jj2RvVHf)t-HV4g0umJo3`!UyuESjj>auJnzruPC!=}W z&X(=F6ztpC(6npMzTJD8ckgX(XxzW2Y5!h=#$639dm0by-PgQpPt&%Y2Y2l~+Sq(> zN5lSIdk!=-9@x`(a8Fa~-hBu6HXYn6HQ_+cHMTZ39ctQlcwh6;=9XhE`;YBEaBTm< zqx%mc?TZ7gM-R3hJ#f$kIBY%Kvi}ffD)%)z(A3;2<8V{U(Z>CU_qMb)>}zdkLV9>l z^O3zRhZ~!v*2aCU@~0kdZaLDt|7Z(7^}vyq1Eeh($jCs+frHI0Ex^8}eT}=D@!fZB z{^FB$pZ?z;zgYLdhX4EH=fHdKuK(jZ>)(6lvp>G`$vba-`tG|M-e33md+&ew{s-GW z{dDU`A8uLq!M2Y+-1y-KUw-n@=j-0zU`Oub4>x@H!DsKk_r=HSwtV)<)=xg#^w9^K zK3cc+(~q`&^3jgZKH2&Cr#sevwrAtU#*JU@+3;EO#`Q;bZ8_4g{n);}r~dM%uJ-oU zh6ZXc-Me@D_HF!lOILfxz0U4`bX~vQ)qT7BI&i1^`rYd{6x_bnd8f1MURU?su5M)R z$cJ~3zlmRSxqZ9)=8Y?z*E_D=y4HRBS~q@(=VoX3Eg4;H9XGFb-R!<`9lzIerSoR@ z^_yMSad`9kjhj+uH>rnQ_l+A}*B$8Wz5!h8x`BqSc3p4BZ~0v5y4(SD;#YfQT)WuT zaS=bH)7EzJGI06AC5lVuFJ6-K=gaPsVNf>Xy&NR28YO;Ieq5*snZwEoV|4ZLPuNM?OV6*-Me@F z)~&0Zot;;%;_3e5?mYlMjdL4M`udH|YuB#hcXaOEyKBFB3;ogE+0}imv%9P7dRO-? z^!=SX-T%1PdHWWs-nmKIx^d_3?K}UxbC-bp7|)%5{^RyP@8Jh{u3rCJ(}7o3uaUX* zKl`Po|L%vHr2pA3HT`!#)FidHx3&LIeyOSb@}>Xchnl4S*)KKycR$or_&@rkrp+6^ ccv14Su6f?`spmaC@JIgl+Vs4q>b;Hs50&lP3IG5A delta 278 zcmaF%S7h5Kp-?AZvz;sqAYcZ>8bJIVh!-$2FfcMm09il)lvn0v0Aq*%1H%_E`1I-1 zjT<)(95}FN&z_@4kDh^mQ>QLWR_GC7zIgh~B;uJqLcl4*-&s`uk_@WUW0`FJ9lA4d$;cZqCMNTL(uN6+wh|un>J%bll419 Xn;kpa9Xl9-mx&QEZqhG1Qv_Q diff --git a/uisimulator/sdl/UI-mrobe500.bmp b/uisimulator/sdl/UI-mrobe500.bmp index 6aebbee8fd86950a700cf7a690ac8e7dfe281c03..c7d0bec36220a2137a0b5075a2b7997fc015803e 100755 GIT binary patch literal 473254 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 literal 630054 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 IO2