/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: $ * * Copyright (C) 2009 Karl Kurbjun * * 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 "config.h" #include "system.h" #include "file.h" #include "lcd-remote.h" #include "scroll_engine.h" #include "uart-target.h" #include "button.h" #include "powermgmt.h" static enum remote_control_states { REMOTE_CONTROL_IDLE, REMOTE_CONTROL_NOP, REMOTE_CONTROL_POWER, REMOTE_CONTROL_MASK, REMOTE_CONTROL_DRAW, REMOTE_CONTROL_SLEEP } remote_state_control = REMOTE_CONTROL_MASK, remote_state_control_next; static enum remote_draw_states { DRAW_TOP, DRAW_BOTTOM, DRAW_PAUSE, } remote_state_draw = DRAW_TOP, remote_state_draw_next; static bool remote_hold_button=false; bool remote_initialized=true; static unsigned char remote_contrast=DEFAULT_REMOTE_CONTRAST_SETTING; static unsigned char remote_power=0x00; /*** hardware configuration ***/ int lcd_remote_default_contrast(void) { return DEFAULT_REMOTE_CONTRAST_SETTING; } void lcd_remote_sleep(void) { remote_state_control_next=REMOTE_CONTROL_SLEEP; } void lcd_remote_powersave(bool on) { if(on) { remote_power|=0xC0; remote_state_control_next=REMOTE_CONTROL_POWER; } else { remote_power&=~(0xC0); remote_state_control_next=REMOTE_CONTROL_POWER; } } void lcd_remote_set_contrast(int val) { remote_contrast=(char)val; remote_state_control_next=REMOTE_CONTROL_POWER; } void lcd_remote_set_invert_display(bool yesno) { (void)yesno; } bool remote_detect(void) { return true; } void lcd_remote_on(void) { remote_power|=0x80; remote_state_control_next=REMOTE_CONTROL_POWER; } void lcd_remote_off(void) { remote_power&=~(0x80); remote_state_control_next=REMOTE_CONTROL_POWER; } /* This is the maximum transfer size to the remote (op 0x51= 7 bytes setup+79 * bytes screen data+xor+sum */ unsigned char remote_payload[88]; unsigned char remote_payload_size; bool remote_repeat_draw=false; unsigned char remote_draw_x, remote_draw_y, remote_draw_width, remote_draw_height; /* Monitor remote hotswap */ static void remote_tick(void) { unsigned char i; int bat_level; static unsigned char pause_length=0; if(remote_state_control!=REMOTE_CONTROL_DRAW && remote_state_control!=REMOTE_CONTROL_IDLE) { remote_state_control=remote_state_control_next; remote_state_control_next=REMOTE_CONTROL_MASK; } switch (remote_state_control) { case REMOTE_CONTROL_IDLE: /* State machine never leaves idle unless remote_state_control is * manually set. */ remote_payload_size=0; remote_state_control=REMOTE_CONTROL_IDLE; break; case REMOTE_CONTROL_NOP: remote_payload[0]=0x11; remote_payload[1]=0x30; remote_payload_size=2; remote_state_control=REMOTE_CONTROL_MASK; break; case REMOTE_CONTROL_POWER: remote_payload[0]=0x31; remote_payload[1]=remote_power; remote_payload[2]=remote_contrast; remote_payload_size=3; remote_state_control=REMOTE_CONTROL_MASK; break; case REMOTE_CONTROL_MASK: bat_level=battery_level()>>5; remote_payload[1]=0; if(bat_level&0x02) { remote_payload[1] |= 0x07 << 5; } else if(bat_level&0x01) { remote_payload[1] |= 0x03 << 5; } else { remote_payload[1] |= 0x01 << 5; } remote_payload[1]|=1<<4; remote_payload[0]=0x41; remote_payload_size=2; remote_state_control=REMOTE_CONTROL_MASK; break; case REMOTE_CONTROL_DRAW: remote_payload[0]=0x51; remote_payload[1]=0x80; remote_payload[2]=remote_draw_width; remote_payload[3]=remote_draw_x; remote_payload[5]=remote_draw_x+remote_draw_width; remote_payload_size=7+remote_payload[2]; switch (remote_state_draw) { case DRAW_TOP: remote_payload[4]=0; remote_payload[6]=8; pause_length=6; remote_state_draw_next=DRAW_BOTTOM; remote_state_draw=DRAW_PAUSE; break; case DRAW_BOTTOM: remote_payload[4]=8; remote_payload[6]=16; pause_length=6; remote_state_draw_next=DRAW_TOP; remote_state_draw=DRAW_PAUSE; break; case DRAW_PAUSE: remote_payload_size=0; if(--pause_length==0) { if(remote_state_draw_next==DRAW_TOP) remote_state_control=REMOTE_CONTROL_MASK; remote_state_draw=remote_state_draw_next; } else remote_state_draw=DRAW_PAUSE; break; default: remote_payload_size=0; break; } break; case REMOTE_CONTROL_SLEEP: remote_payload[0]=0x71; remote_payload[1]=0x30; remote_payload_size=2; remote_state_control=REMOTE_CONTROL_IDLE; break; default: remote_payload_size=0; break; } if(remote_payload_size==0) { return; } if(remote_payload[0]==0x51) { for(i=7; i>3][i+remote_draw_x-7]; } } /* Calculate the xor and sum to place in the payload */ remote_payload[remote_payload_size]=remote_payload[0]; remote_payload[remote_payload_size+1]=remote_payload[0]; for(i=1; i=0) { int button_location; for(button_location=0;button_location<4;button_location++) { if((read_buffer[button_location]&0xF0)==0xF0 && (read_buffer[button_location+1]&0xF0)!=0xF0) break; } if(button_location==4) button_location=0; button_location++; read_button |= read_buffer[button_location]; /* Find the hold status location */ if(button_location==4) button_location=0; else button_location++; remote_hold_button=((read_buffer[button_location]&0x80)?true:false); uart1_clear_queue(); oldbutton=read_button; } else read_button=oldbutton; return read_button; } void _remote_backlight_on(void) { remote_power|=0x40; remote_state_control_next=REMOTE_CONTROL_POWER; } void _remote_backlight_off(void) { remote_power&=~(0x40); remote_state_control_next=REMOTE_CONTROL_POWER; }