// KCO 2010.6.8
// main.c
#include "common.h"
#include "lcd.h"
#include "key.h"
#include "adc.h"
#include "i2c_eep.h"
#include "spi.h"
#include "timer.h"
#include "can.h"
#include "uart.h"

GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStruct;

#define LCD_XLEN        20
#define LCD_YLEN        4
#define LCD_HOME        0x00
#define LCD_RIGHT       0x01
#define LCD_LEFT        0x02
#define LCD_UP          0x03
#define LCD_DOWN        0x04
#define LCD_CUR_BLK_ON  0x05
#define LCD_CUR_BAR_ON  0x06
#define LCD_CUR_ALL_ON  0x07
#define LCD_CUR_OFF     0x08
#define LCD_CLEAR       0x09

enum    BPS {BPS_1200,BPS_2400,BPS_4800,BPS_9600,BPS_19200,BPS_38400,BPS_57600,BPS_115200,BPS_230400,BPS_END};
enum    VRP {VR_NO,VR_50MS,VR_100MS,VR_200MS,VR_500MS,VR_1S,VR_END};
enum    MODE {MODE_ASC,MODE_HEX,MODE_END};

int mcnt=0;
extern EEPROM_Info eeprom;
u32 eep_addr=0;
u8  spi_tx_run=1;
extern u16 spi2_rx_data[];
extern u8 spi2_rx_idx, spi2_rx_flag;
u16 spi1_tx_data[20];
extern u16 pul1_width,pul1_period;
extern u16 pul2_width,pul2_period;
extern u16 cap1_cnt,cap2_cnt;
u16 cap1_cnt_b=0,cap2_cnt_b=0;

extern CanTxMsg TxMessage;
extern CanRxMsg RxMessage;
extern u8 can_rx_flag,can_rx_cnt;
u8 can_txd[8];

u16 vr;

extern u8 uart1_rx_buf[];
extern u16 uart1_rx_pos, uart1_rx_end;
u8 lcd_x=0,lcd_y=0;

u8 bps = BPS_9600, vrp=VR_NO, mode = MODE_ASC;
u8 eep_bps, eep_vrp, eep_mode;

extern EEPROM_Info eeprom;
u8  eep_data[3];

u32 bps_val=9600;
const u32 bps_table[]={1200L,2400L,4800L,9600L,19200L,38400L,57600L,115200L,230400L};
const u16 vr_prd[]={0,50,100,200,500,1000};

void gpio_init(void){
    //*********************** GPIO Init *****************************
    // Enable GPIO clock and release reset
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
                         RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_GPIOC,
                         ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA |
                         RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_GPIOC,
                         DISABLE);
    // GPIO init.
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | 
       GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | 
       GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    OFF_LED1;    OFF_LED2;   OFF_LED3;   OFF_LED4;
    OFF_LED5;    OFF_LED6;   OFF_LED7;   OFF_LED8;
}
void timer1_init(void){
    //************************ Timer1 Init **************************
    // Enable Timer1 clock and release reset
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1,DISABLE);
    
    // Set timer period 100 usec
    TIM1_TimeBaseInitStruct.TIM_Prescaler = 72-1;  // 1us resolution
    TIM1_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM1_TimeBaseInitStruct.TIM_Period = 100-1;  // 100 us
    TIM1_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV2;   // for 36MHz
    TIM1_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1,&TIM1_TimeBaseInitStruct);
    // Clear update interrupt bit
    TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update);
    // Enable update interrupt
    TIM_ITConfig(TIM1,TIM_FLAG_Update,ENABLE);
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    // Enable timer counting
    TIM_Cmd(TIM1,ENABLE);
}

void TIM1_UP_IRQHandler(void){  // Timer1 interrupt routine: 100usec period
    // Clear update interrupt bit
    TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update);
    check_period_flag();
    T_LED1;
}

void	key_down_proc(BYTE c){
	switch(c){
		case 0: 
            uart1_putc('a');   
 			break;
		case 1:
            uart1_putc('b');   
			break;
		case 2:
            uart1_putc('c');   
           break;
		case 3:
            uart1_putc('d');   
			break;
		case 4:
            uart1_putc('e');   
 			break;
		default:	
			break;
	}
}

void	key_up_proc(BYTE c){
	switch(c){
		case 0:
			break;
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		default:	
			break;
	}
}

BYTE	key_cnt=0;
void	key_cont_proc(BYTE c){
	switch(c){
		case 0:
            key_down_proc(c);
            break;
		case 1:
            key_down_proc(c);
			break;
		case 2:
            key_down_proc(c);
			break;
		case 3:
            key_down_proc(c);
			break;
		case 4:
            key_down_proc(c);
			break;
		default:	
			break;
	}
}
WORD	key_code;
void	key_process(void){
WORD	i,c;
	key_code = key5_proc();
	for(i=0;i<5;i++){
	  	c = (key_code>>(2*i) )& 0x03;
		if(c == KEY_CONT) key_cont_proc(i);
		else if(c == KEY_DOWN) key_down_proc(i);
		else if(c == KEY_UP) key_up_proc(i);
	}
}
void    disp_bps(void){
    lcd_gotoxy(0,1);
    switch(bps){
        case BPS_1200:
            lcd_puts("COM Speed=  1200 bps");
            break;
        case BPS_2400:
            lcd_puts("COM Speed=  2400 bps");
            break;
        case BPS_4800:
            lcd_puts("COM Speed=  4800 bps");
            break;
        case BPS_9600:
            lcd_puts("COM Speed=  9600 bps");
            break;
        case BPS_19200:
            lcd_puts("COM Speed= 19200 bps");
            break;
        case BPS_38400:
            lcd_puts("COM Speed= 38400 bps");
            break;
        case BPS_57600:
            lcd_puts("COM Speed= 57400 bps");
            break;
        case BPS_115200:
            lcd_puts("COM Speed=115200 bps");
            break;
        case BPS_230400:
            lcd_puts("COM Speed=230400 bps");
            break;
        default:
            break;
    }
}

void disp_vr(void){
    vr = get_adc(8);
    lcd_gotoxy(15,0);
    lcd_putc('[');
    lcd_hex3(vr);
    lcd_putc(']');
}
void    disp_vrp(void){
    lcd_gotoxy(0,2);
    switch(vrp){
        case VR_NO:
            lcd_puts("VR tx period=   NO  ");
            break;
        case VR_50MS:
            lcd_puts("VR tx period=0.05sec");
            break;
        case VR_100MS:
            lcd_puts("VR tx period= 0.1sec");
            break;
        case VR_200MS:
            lcd_puts("VR tx period= 0.2sec");
            break;
        case VR_500MS:
            lcd_puts("VR tx period= 0.5sec");
            break;
        case VR_1S:
            lcd_puts("VR tx period= 1.0sec");
            break;
        default:
            break;
    }
}
void    disp_mode(void){
    lcd_gotoxy(0,3);
    if(mode==MODE_ASC){
        lcd_puts("Display Mode =  ASC ");
    }
    else{
        lcd_puts("Display Mode =  HEX ");
    }
}
void    write_eep_data(void){    
    eeprom.DeviceAddress = 0;
    eeprom.DataLength = 3;
    eeprom.InterAddress = 0;
    eeprom.Data[0]=bps;
    eeprom.Data[1]=vrp;
    eeprom.Data[2]=mode;
    if(i2c_eep_write(&eeprom)!=EEPROM_SUCCESS){
        lcd_gotoxy(0,0);
        lcd_printf("*** EEP Write err **");
    }
}
void    read_eep_data(void){    
    eeprom.DeviceAddress = 0;
    eeprom.DataLength = 3;
    eeprom.InterAddress = 0;
    if(i2c_eep_read(&eeprom)==EEPROM_SUCCESS){
        bps = eeprom.Data[0];
        vrp = eeprom.Data[1];
        mode = eeprom.Data[2];
    }
    else{
        lcd_gotoxy(0,0);
        lcd_printf("*** EEP Read err ***");
    }
}
u8 key_exit=0;
void ikey_down_proc(u8 c){		
	switch(c){
		case 0:
		    if(bps > 0) bps--;
		    eep_bps = bps;
            write_eep_data();
		    disp_bps();
			break;
		case 1:
		    if(bps<BPS_230400) bps++;
		    eep_bps = bps;
            write_eep_data();
		    disp_bps();
			break;
		case 2:
		    if(++vrp > VR_1S) vrp=0;
		    eep_vrp = vrp;
            write_eep_data();
		    disp_vrp();
			break;
		case 3:
		    if(mode==MODE_ASC) mode = MODE_HEX;
		    else mode = MODE_ASC;
		    eep_mode = mode;
            write_eep_data();
            disp_mode();
			break;
		case 4:
		    key_exit = 1;   return;
		default:
			break;
	}
    key_exit = 0;   return;
} 


void	ikey_process(void){
u16 i,c;
    key_code = key5_proc();
	for(i=0;i<5;i++){
	  	c = (key_code>>(2*i) )& 0x03;
		if(c == KEY_DOWN) ikey_down_proc(i);
	}
}

void    rx1_process(void){
BYTE    rd;
    rd = uart1_rx_buf[uart1_rx_end++];
    UART1_RX_END_MASK;
    if(mode==MODE_ASC){
      if((rd>=' ')&&(rd<0x7f)){
        lcd_putc(rd);
        lcd_x++;
        if(lcd_x>=LCD_XLEN){
            lcd_x = 0;
            lcd_y++;
            if(lcd_y>=LCD_YLEN) lcd_y=0;
            lcd_gotoxy(lcd_x,lcd_y);
        }
      }
      else if(rd==CR){
        lcd_x=0;
        lcd_gotoxy(lcd_x,lcd_y);
      }
      else if(rd==LF){
        if(lcd_y < (LCD_YLEN-1)) lcd_y++;
        lcd_gotoxy(lcd_x,lcd_y);
      }
      else if(rd==LCD_HOME){
        lcd_x=0;    lcd_y=0;
        lcd_gotoxy(lcd_x,lcd_x);
      }
      else if(rd==LCD_CUR_BLK_ON) lcd_cursor_blk_on();
      else if(rd==LCD_CUR_BAR_ON) lcd_cursor_bar_on();
      else if(rd==LCD_CUR_ALL_ON) lcd_cursor_all_on();
      else if(rd==LCD_CUR_OFF) lcd_cursor_off();
      else if(rd==LCD_CLEAR){
        lcd_init(LCD_XLEN,LCD_YLEN);
        lcd_x=0;    lcd_y=0;
        lcd_gotoxy(lcd_x,lcd_x);
      }
      else if(rd==LCD_RIGHT){
        if(lcd_x < (LCD_XLEN-1)) lcd_x++;
        lcd_gotoxy(lcd_x,lcd_y);
      }
      else if(rd==LCD_LEFT){
        if(lcd_x > 0) lcd_x--;
        lcd_gotoxy(lcd_x,lcd_y);
      }
      else if(rd==LCD_UP){
        if(lcd_y > 0) lcd_y--;
        lcd_gotoxy(lcd_x,lcd_y);
      }
      else if(rd==LCD_DOWN){
        if(lcd_y < (LCD_YLEN-1)) lcd_y++;
        lcd_gotoxy(lcd_x,lcd_y);
      }
    }
    else{   // MODE_HEX
        lcd_gotoxy(lcd_x,lcd_y);
        lcd_putc(hex2asc(rd>>4));
        lcd_gotoxy(lcd_x,lcd_y+1);
        lcd_putc(hex2asc(rd));
        
        if(++lcd_x>=LCD_XLEN){
            lcd_x = 0;
            if(LCD_YLEN==4){
                if(lcd_y==0) lcd_y=2;
                else lcd_y=0;
            }
            else lcd_y=0;
            lcd_gotoxy(lcd_x,lcd_y+1);
        }
    }
}

void init_terminal(void){
// read from eeprom  
    read_eep_data();
    
    if(bps >= BPS_END){
      bps = BPS_9600;   write_eep_data();
    }
    if(vrp >= VR_END){
      vrp = VR_NO;     write_eep_data();
    }
    if(mode >= MODE_END){
      mode = MODE_ASC;   write_eep_data();
    }

    if(IN_KEY != KEY_MASK){
        lcd_gotoxy(0,0);
        lcd_puts("<< Setting >>       ");
	    disp_bps();
	    disp_vrp();
	    disp_mode();

        while(IN_KEY != KEY_MASK){
            disp_vr();
            disp_mode();
            delay_ms(100);
        }

	    while(1){
            key_exit = 0;
            ikey_process();
            if(key_exit) break;
            disp_vr();
            delay_ms(10);
	    }
	}
    bps_val = bps_table[bps];
    init_uart(1,bps_val,0);    // uart1(RS232), bps, txenable

    lcd_gotoxy(0,0);
    lcd_puts("                    ");
    lcd_gotoxy(0,1);
    lcd_puts("                    ");
    lcd_gotoxy(0,2);
    lcd_puts("                    ");
    lcd_gotoxy(0,3);
    lcd_puts("                    ");
    lcd_gotoxy(0,0);

    if(mode==MODE_HEX){
        lcd_gotoxy(0,1);
        lcd_cursor_blk_on();
    }
    else{
        lcd_gotoxy(0,0);
        lcd_cursor_bar_on();
    }
}

u16 cnt_1ms=0;
u16 ttt=0;
void main(void){
    /* Setup STM32 system (clock, PLL and Flash configuration) */
    SystemInit();
    
    /* Set the Vector Table base location at 0x08000000 */
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    
    gpio_init();
    timer1_init();
	lcd_init(LCD_XLEN,LCD_YLEN);
    key_init();
    init_adc();
    init_i2c_eep(AT24C16);

    init_uart(2,9600,0);    // uart1(RS232), bps, txenable

    init_terminal();
    
    while(1){
        mcnt++;
        if(uart1_rx_ready()) rx1_process();
        
	    if(flag_1ms){
	    	flag_1ms = 0;
            if(vrp){
                vr = get_adc(8);
                if(++cnt_1ms >= vr_prd[vrp]){
                    cnt_1ms=0;
                    uart1_printf("%03X\r",vr);
                }
            }
	    }
	    if(flag_2ms){
	    	flag_2ms = 0;
	    }
	    if(flag_10ms){
            flag_10ms = 0;
		}
	    if(flag_50ms){
            flag_50ms = 0;
            key_process();
		}
	    if(flag_100ms){
	    	flag_100ms = 0;
            ttt++;
            uart2_printf("ttt=%04X(%5d)\r",ttt,ttt);
		}
	    if(flag_300ms){
	    	flag_300ms = 0;
		}
    }
}
