boop/boop/main.c
2017-07-14 23:49:15 +02:00

422 lines
8.7 KiB
C

/*
main.c - main program routines
Copyright (C) 2007 Ch. Klippel <ck@mamalala.net>
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 3 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, see <http://www.gnu.org/licenses/>.
*/
//typedef volatile unsigned int *reg32_t;
#include "lpc2220.h"
#include "lcd.h"
#include "irq.h"
#include "keyboard.h"
#include "lcd.h"
#include "fonty.h"
#include "sid.h"
#include "sound.h"
//#include "sounds.h"
//#include "sound3.h"
#include "infrared.h"
#include "pwm.h"
#include "codes.h"
#include "encoders.h"
#include "ir_selector.h"
#include "serial.h"
#include "flash.h"
#include "rf.h"
#include "menu.h"
#include "testmenu.h"
#include "mainmenu.h"
#include "timerfuncs.h"
#define __MAIN_C__
#include "global.h"
#include "adc.h"
#include "backlight.h"
#include "rtc.h"
#include "i2c.h"
#include "bfs.h"
#include "settingsmenu.h"
#include "ir_raw.h"
#include "ir_capture.h"
#include "controls.h"
#include "buffer.h"
unsigned char sysInfo;
extern volatile char timeout;
extern ir_sfn irSend;
extern ir_fn irRepeat;
extern ir_fn irStop;
const char hval[16] = "0123456789ABCDEF";
unsigned int oldkeys[2];
unsigned int key_state;
extern unsigned char act_encoder, act_set;
extern unsigned char bl_val;
// betty runs on 10 MHz * 1/4 on reset
// this enables the PLL clock generation and sets the prescaler
void setSpeed(unsigned char sp)
{
disableIRQ();
switch(sp)
{
case SPEED_60: // turbo speed (60 mhz)
BCFG0 = 0x100005EF;
PLLCFG = 0x45; // 0100.0101 = PSEL=10=4 MSEL=00101=6 = 240mhz Fcco
PLLFEED = 0xAA;
PLLFEED = 0x55;
VPBDIV = 0x00;
BCFG0 = 0x100004A0;
BCFG2 = 0x100004A0;
BCFG1 = 0x00000C21;
sysInfo |= SYS_TURBO;
break;
case SPEED_30: // normal speed (30 mhz)
default:
BCFG0 = 0x100005EF;
PLLCFG = 0x42; // 0100.0010 = PSEL=10=4 MSEL=00010=3
PLLFEED = 0xAA;
PLLFEED = 0x55;
VPBDIV = 0x02;
BCFG0 = 0x10000420;
BCFG2 = 0x10000420;
BCFG1 = 0x00000400;
sysInfo &= ~SYS_TURBO;
break;
}
enableIRQ();
}
/*
// draw "emitting waves" symbol
// used when a button is pressed
void draw_ir (unsigned char x, unsigned char y, unsigned char m)
{
//~ 0 1: #####
//~ 1 2: # #
//~ 2 4: ###
//~ 3 8: # #
//~ 4 1:
//~ 5 2: ###
//~ 6 4: #####
draw_hline(x+1,y,5,3,m); // 0
draw_pixel(x ,y+1,3,m); // 1
draw_pixel(x+6,y+1,3,m); // 1
draw_hline(x+2,y+2,3,3,m); // 2
draw_pixel(x+1,y+3,3,m); // 3
draw_pixel(x+5,y+3,3,m); // 3
draw_hline(x+2,y+5,3,3,m); // 5
draw_hline(x+1,y+6,5,3,m); // 6
draw_symbol(x,y,7,(unsigned char*)symIR,LCD_COLOR_B,m);
}*/
// shows current IR set on top of main screen
void drawSet (void)
{
set_font(SMALLFONT);
draw_block (0, 0, 99, 9, LCD_COLOR_B, DRAW_ERASE);
draw_string (0,0,getSetName (irDevTab.device[irDevTab.active].encoder, irDevTab.device[irDevTab.active].set), LCD_COLOR_B, DRAW_PUT);
}
//
void drawMainscreen (void)
{
//~ set_font(SMALLFONT); // done in drawSet()
lcd_fill(0);
draw_logo();
// top bar
drawSet();
/* is updated in main loop
// time
#if FF_LARGE_IDLE_CLOCK
printTime (6,20, (struct time_ *)&rtc.time, 1);
#else
printTime (86,152, (struct time_ *)&rtc.time, 0);
printDate(0,152,(struct date_ *)&rtc.date,0);
#endif
*/
showBat(0xff); // battery indicator
redraw_symbols(); //
}
//unsigned char i;
/** let the LPC2200 sleep until the next IRQ
*
* This function tries to enter the sleep mode and stays
* there until the next interrupt wakes up the CPU.
* If that is not possible, the function returns immediately.
*/
extern unsigned char sact;
void cpu_idle ()
{
/* fall through if a key was pressed */
if (ANYKEY)
return;
//fall through if UART0 Scratch pad register is not empty
//OpenOCD can set this register with "mwb 0xE000C01C 0x01" to disable idle and power down mode
if(U0SCR)
return;
return;
/* only idle mode instead of power down when:
* * backlight on
* * IR transmission
* * RF is activated
* * sound is playing
* * I2C access
* * SYS_NOPDOWN in sysInfo is set
*/
if (bl_val != 0 || key_state != KEY_IDLE ||
(RF.state > RFidle) ||
(SID.flags & SIDenable) || sact || i2ccurrentjob || (sysInfo & SYS_NOPDOWN))
{
if(sysInfo & SYS_NOIDLE)
return;
/* WARNING: no code reuse here:
* PCON = <dynamic_variable> causes timing problems */
EXTINT = 0x08;
PCON = PCON_IDLE;
PLLFEED = 0xAA;
PLLFEED = 0x55;
}
else
{
refresh_symbols(0xff);
EXTINT = 0x08;
sysInfo |= SYS_NOIDLE;
PCON = PCON_PDOWN;
PLLFEED = 0xAA;
PLLFEED = 0x55;
}
} // cpu_idle
int main(void)
{
sysInfo = SYS_NOIDLE;
SCS |= 0x01;
FIODIR0 |= ((1<<21) | (1<<11) | (1<<6) | (1<<23) | (1<<19) | (1<<17));
FIODIR0 |= (1<<12);
FIOSET0 |= (1<<12);
FIOCLR0 |= (1<<4);
setSpeed(SPEED_30);
lcd_init(0);
serial_init();
startTimerIRQ();
startADC();
initKeys();
initSound();
startSoundIRQ();
initIR();
startIrIRQ();
PWM_init();
RF_init();
load_RF_setting();
startRFIRQ();
RF_changestate(RFwor);
initI2C();
initRTC();
startRtcIRQ();
enableIRQ();
//testmenu_init();
init_menu();
initBacklight();
oldkeys[0] = keys[0];
oldkeys[1] = keys[0];
key_state = KEY_IDLE;
set_font(BOLDFONT);
BFS_Mount(); // flash file system
load_RC_setting(); // learned remote codes
load_setting(); // display settings
// recorded raw IR commands
{
struct RAWset_ RAWset;
unsigned char x;
unsigned long RAWcmdbase;
RAWcmdbase = FLASH1_BASE +(secaddr[0]<<1); // data address
x=memcmp((void*)RAWcmdbase,"RC01",4); // check ID
if(!x) //
{
memcpy(&RAWset,(void *)RAWcmdbase,sizeof(struct RAWset_));
RAWset.name[7] = 0;
BFS_SaveFile(BFS_ID_RAWslot0, sizeof(struct RAWset_), (unsigned char*) &RAWset);
eraseSector(1,0);
}
}
setEncoder(irDevTab.device[irDevTab.active].encoder, irDevTab.device[irDevTab.active].set);
drawMainscreen();
ask_for_time(0);
/*
playSound((unsigned char*)sound1_data, sound1_len);
waitSound();
playSound((unsigned char*)sound2_data, sound2_len);
*/
// main loop
while (1)
{
// detect keyboard action (keyboard matrix scanned by interrupt)
if(keys[0] != oldkeys[0] || keys[1] != oldkeys[1])
{
oldkeys[0] = keys[0];
oldkeys[1] = keys[1];
sysInfo |= SYS_KEY;
}
// determine keyboard actions on main screen
switch(key_state)
{
case KEY_IDLE:
if(sysInfo & SYS_KEY)
{
sysInfo &= ~SYS_KEY;
if(KEY_Betty)
{
setBacklight(BL_AUTO); // activate backlight
menu_exec(&mainMenu); // select menu
setEncoder(irDevTab.device[irDevTab.active].encoder, irDevTab.device[irDevTab.active].set);
drawMainscreen(); // draw new menu
while(KEY_Exit); // block until
}
//~ else if(KEY_2)
//~ {
//setSpeed(SPEED_30);
//~ }
//~ else if(KEY_3)
//~ {
//setSpeed(SPEED_60);
//~ }
else if(KEY_A || KEY_B || KEY_C || KEY_D)
{
// select encoder
unsigned char x;
//playSound((unsigned char*)sound3_data, sound3_len);
x=0;
if (KEY_B) x=1;
if (KEY_C) x=2;
if (KEY_D) x=3;
if (setEncoder(irDevTab.device[x].encoder, irDevTab.device[x].set)) {
setBacklight(BL_AUTO);
irDevTab.active = x;
//~ drawMainscreen();
drawSet();
}
}
// (last-minute detection of regular key?)
if((keys[0] != 0) || (keys[1] != 0))
key_state = KEY_PRESS;
}
break;
case KEY_PRESS:
irSend(getCode());
key_state = KEY_HOLD;
if(!(T1TCR & 0x02))
draw_symbol(90,0,7,(unsigned char*)symIR,LCD_COLOR_B,DRAW_PUT);
// autorepeat = 0;
break;
case KEY_HOLD:
// if(autorepeat >= AUTO_TIMEOUT)
irRepeat();
//draw_ir(90, 0, DRAW_XOR);
if(keys[0] == 0 && keys[1] == 0)
key_state = KEY_RELEASE;
break;
case KEY_RELEASE:
if(!(T1TCR & 0x02))
draw_symbol(90,0,7,(unsigned char*)symIR,LCD_COLOR_B,DRAW_ERASE);
irStop();
key_state = KEY_IDLE;
break;
}
cpu_idle(); // let the LPC2200 sleep until the next IRQ
// display time
if (timeInfo & TIMECHANGED)
{
#if FF_LARGE_IDLE_CLOCK
// time large, no date
printTime( 6, 20, (struct time_ *)&rtc.time, 1);
#else
// time and date small
printTime( 86, 152, (struct time_ *)&rtc.time, 0);
printDate( 0, 152, (struct date_ *)&rtc.date, 0);
#endif
timeInfo &= ~TIMECHANGED; // clear update flag
}
} // while (1)
return 0; // never returns
} // main