text: #include "app_config.h"
  
  #ifdef CONFIG_BOARD_AC635N_DEMO
  
  #include "system/includes.h"
  #include "asm/charge.h"
  #include "device/key_driver.h"
  #include "asm/power/p33.h"
  #include "asm/iic_soft.h"
  #ifdef CONFIG_LITE_AUDIO
  #include "media/includes.h"
  #endif/*CONFIG_LITE_AUDIO*/
  
  #define LOG_TAG_CONST       BOARD
  #define LOG_TAG             "[BOARD]"
  #define LOG_ERROR_ENABLE
  #define LOG_DEBUG_ENABLE
  #define LOG_INFO_ENABLE
  /* #define LOG_DUMP_ENABLE */
  #define LOG_CLI_ENABLE
  #include "debug.h"
  
  void board_power_init(void);
  const struct soft_iic_config soft_iic_cfg[] = {
      //iic0 data
      {
          .scl = IO_PORTC_04,                    //IIC CLK脚
          .sda = IO_PORTC_05,                   //IIC DAT脚
          .delay = 50,                //软件IIC延时参数，影响通讯时钟频率
          .io_pu = 1,                                     //是否打开上拉电阻，如果外部电路没有焊接上拉电阻需要置1
      },
  };
  
  /************************** LOW POWER config ****************************/
  const struct low_power_param power_param = {
      .config         = TCFG_LOWPOWER_LOWPOWER_SEL,          //0：sniff时芯片不进入低功耗  1：sniff时芯片进入powerdown
      .btosc_hz         = TCFG_CLOCK_OSC_HZ,                   //外接晶振频率
      .delay_us       = TCFG_CLOCK_SYS_HZ / 1000000L,        //提供给低功耗模块的延时(不需要需修改)
      .btosc_disable  = TCFG_LOWPOWER_BTOSC_DISABLE,         //进入低功耗时BTOSC是否保持
      .vddiom_lev     = TCFG_LOWPOWER_VDDIOM_LEVEL,          //强VDDIO等级,可选：2.0V  2.2V  2.4V  2.6V  2.8V  3.0V  3.2V  3.6V
      .vddiow_lev     = TCFG_LOWPOWER_VDDIOW_LEVEL,          //弱VDDIO等级,可选：2.1V  2.4V  2.8V  3.2V
      .osc_type       = OSC_TYPE_LRC,
      .dcdc_port      = TCFG_DCDC_PORT_SEL,
  };
  
  
  /************************** KEY MSG****************************/
  /*各个按键的消息设置，如果USER_CFG中设置了USE_CONFIG_KEY_SETTING为1，则会从配置文件读取对应的配置来填充改结构体*/
  u8 key_table[KEY_NUM_MAX][KEY_EVENT_MAX] = {
      // SHORT           LONG              HOLD              UP              DOUBLE           TRIPLE
  };
  
  
  // *INDENT-OFF*
  /************************** UART config****************************/
  #if TCFG_UART0_ENABLE
  UART0_PLATFORM_DATA_BEGIN(uart0_data)
      .tx_pin = TCFG_UART0_TX_PORT,                             //串口打印TX引脚选择
      .rx_pin = TCFG_UART0_RX_PORT,                             //串口打印RX引脚选择
      .baudrate = TCFG_UART0_BAUDRATE,                          //串口波特率
  
      .flags = UART_DEBUG,                                      //串口用来打印需要把改参数设置为UART_DEBUG
  UART0_PLATFORM_DATA_END()
  #endif //TCFG_UART0_ENABLE
  
  /************************** CHARGE config****************************/
  #if TCFG_CHARGE_ENABLE
  CHARGE_PLATFORM_DATA_BEGIN(charge_data)
      .charge_en              = TCFG_CHARGE_ENABLE,              //内置充电使能
      .charge_poweron_en      = TCFG_CHARGE_POWERON_ENABLE,      //是否支持充电开机
      .charge_full_V          = TCFG_CHARGE_FULL_V,              //充电截止电压
      .charge_full_mA			= TCFG_CHARGE_FULL_MA,             //充电截止电流
      .charge_mA				= TCFG_CHARGE_MA,                  //充电电流
  /*ldo5v拔出过滤值，过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出
   对于充满直接从5V掉到0V的充电仓，该值必须设置成0，对于充满由5V先掉到0V之后再升压到xV的
   充电仓，需要根据实际情况设置该值大小*/
  	.ldo5v_off_filter		= 100,
  /*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时，请将该变量置1,默认值设置为1
    对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱，请将该值改为0*/
  	.ldo5v_pulldown_en		= 0,
  CHARGE_PLATFORM_DATA_END()
  #endif//TCFG_CHARGE_ENABLE
  
      /************************** AD KEY ****************************/
  #if TCFG_ADKEY_ENABLE
  const struct adkey_platform_data adkey_data = {
      .enable = TCFG_ADKEY_ENABLE,                              //AD按键使能
      .adkey_pin = TCFG_ADKEY_PORT,                             //AD按键对应引脚
      .ad_channel = TCFG_ADKEY_AD_CHANNEL,                      //AD通道值
      .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE,              //是否使用外接上拉电阻
      .ad_value = {                                             //根据电阻算出来的电压值
          TCFG_ADKEY_VOLTAGE0,
          TCFG_ADKEY_VOLTAGE1,
          TCFG_ADKEY_VOLTAGE2,
          TCFG_ADKEY_VOLTAGE3,
          TCFG_ADKEY_VOLTAGE4,
          TCFG_ADKEY_VOLTAGE5,
          TCFG_ADKEY_VOLTAGE6,
          TCFG_ADKEY_VOLTAGE7,
          TCFG_ADKEY_VOLTAGE8,
          TCFG_ADKEY_VOLTAGE9,
      },
      .key_value = {                                             //AD按键各个按键的键值
          TCFG_ADKEY_VALUE0,
          TCFG_ADKEY_VALUE1,
          TCFG_ADKEY_VALUE2,
          TCFG_ADKEY_VALUE3,
          TCFG_ADKEY_VALUE4,
          TCFG_ADKEY_VALUE5,
          TCFG_ADKEY_VALUE6,
          TCFG_ADKEY_VALUE7,
          TCFG_ADKEY_VALUE8,
          TCFG_ADKEY_VALUE9,
      },
  };
  #endif
  
  void debug_uart_init(const struct uart_platform_data *data)
  {
  #if TCFG_UART0_ENABLE
      if (data) {
          uart_init(data);
      } else {
          uart_init(&uart0_data);
      }
  #endif
  }
  
  static void board_devices_init(void)
  {
  #if TCFG_PWMLED_ENABLE
      pwm_led_init(&pwm_led_data);
  #endif
  
  #if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_TOUCH_KEY_ENABLE)
  	key_driver_init();
  #endif
  }
  
  extern void set_dcdc_ctl_port(u8 port);
  extern void cfg_file_parse(u8 idx);
  void board_init()
  {
      board_power_init();
      adc_vbg_init();
      adc_init();
      cfg_file_parse(0);
      devices_init();
  
  	board_devices_init();
  
  #if TCFG_CHARGE_ENABLE
      charge_api_init((void *)&charge_data);
  #else
  	/*close FAST CHARGE */
  	CHARGE_EN(0);
  	CHGBG_EN(0);
  #endif
  
  	log_info("board_init");
  
  	if(get_charge_online_flag()){
  		log_info("charge...select LDO15");
  		power_set_mode(PWR_LDO15);
  	}else{
  		power_set_mode(TCFG_LOWPOWER_POWER_SEL);
  	}
  }
  
  /************************** DAC ****************************/
  #if TCFG_AUDIO_DAC_ENABLE
  struct dac_platform_data dac_data = {
      .ldo_volt       = TCFG_AUDIO_DAC_LDO_VOLT,                   //DACVDD等级.需要根据具体硬件来设置（高低压）可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V
  #if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF))
      .vcmo_en        = 0,                                         //四声道与双声道差分关闭VCOMO
  #else
      .vcmo_en        = 0,                                         //是否打开VCOMO
  #endif
      .output         = TCFG_AUDIO_DAC_CONNECT_MODE,               //DAC输出配置，和具体硬件连接有关，需根据硬件来设置
      .ldo_isel       = 3,
      .ldo_fb_isel    = 2,
      .lpf_isel       = 0x8,
  };
  #endif
  
  /************************** ADC ****************************/
  #if TCFG_AUDIO_ADC_ENABLE
  const struct ladc_port ladc_list[] = {
  	{// 0
  		.channel = TCFG_AUDIO_ADC_LINE_CHA0,
  	},
  	{// 1
  		.channel = TCFG_AUDIO_ADC_LINE_CHA1,
  	},
  	// total must < 4
  };
  struct adc_platform_data adc_data = {
  	.mic_channel    = TCFG_AUDIO_ADC_MIC_CHA,                   //MIC通道选择，对于693x，MIC只有一个通道，固定选择右声道
  /*MIC LDO电流档位设置：
      0:0.625ua    1:1.25ua    2:1.875ua    3:2.5ua*/
  	.mic_ldo_isel   = TCFG_AUDIO_ADC_LDO_SEL,
  /*MIC 是否省隔直电容：
      0: 不省电容  1: 省电容 */
  #if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF))
  	.mic_capless    = 0,//四声道与双声道差分使用，不省电容接法
  #else
  	.mic_capless    = 0,
  #endif
  /*MIC免电容方案需要设置，影响MIC的偏置电压
      21:1.18K	20:1.42K 	19:1.55K 	18:1.99K 	17:2.2K 	16:2.4K 	15:2.6K		14:2.91K	13:3.05K 	12:3.5K 	11:3.73K
  	10:3.91K  	9:4.41K 	8:5.0K  	7:5.6K		6:6K		5:6.5K		4:7K		3:7.6K		2:8.0K		1:8.5K				*/
      .mic_bias_res   = 16,
  /*MIC LDO电压档位设置,也会影响MIC的偏置电压
      0:2.3v  1:2.5v  2:2.7v  3:3.0v */
  	.mic_ldo_vsel  = 2,
  /*MIC电容隔直模式使用内部mic偏置(PC7)*/
  	.mic_bias_inside = 1,
  /*保持内部mic偏置输出*/
  	.mic_bias_keep = 0,
  
  	// ladc 通道
      .ladc_num = ARRAY_SIZE(ladc_list),
      .ladc = ladc_list,
  };
  #endif
  
  /************************** PWR config ****************************/
  struct port_wakeup port0 = {
  	.pullup_down_enable = ENABLE,                            //配置I/O 内部上下拉是否使能
  	.edge               = FALLING_EDGE,                      //唤醒方式选择,可选：上升沿\下降沿
  	.attribute          = BLUETOOTH_RESUME,                  //保留参数
  	.iomap              = TCFG_ADKEY_PORT,                   //唤醒口选择
      .filter_enable      = ENABLE,
  };
  
  const struct sub_wakeup sub_wkup = {
  	.attribute  = BLUETOOTH_RESUME,
  };
  
  const struct charge_wakeup charge_wkup = {
  	.attribute  = BLUETOOTH_RESUME,
  };
  
  const struct wakeup_param wk_param = {
  #if TCFG_ADKEY_ENABLE
  	.port[1] = &port0,
  #endif
  	.sub = &sub_wkup,
  	.charge = &charge_wkup,
  };
  
  //-----------------------------------------------
  static struct port_wakeup port1 = {
  	.pullup_down_enable = ENABLE,                            //配置I/O 内部上下拉是否使能
  	.edge               = FALLING_EDGE,                      //唤醒方式选择,可选：上升沿\下降沿
  	.attribute          = BLUETOOTH_RESUME,                  //保留参数
  	.iomap              = 0,                                 //唤醒口选择
      .filter_enable      = DISABLE,
  };
  
  
  enum {
      PORTA_GROUP = 0,
      PORTB_GROUP,
      PORTC_GROUP,
  };
  
  static void port_protect(u16 *port_group, u32 port_num)
  {
      if (port_num == NO_CONFIG_PORT) {
          return;
      }
      port_group[port_num / IO_GROUP_NUM] &= ~BIT(port_num % IO_GROUP_NUM);
  }
  
  /*进软关机之前默认将IO口都设置成高阻状态，需要保留原来状态的请修改该函数*/
  static void close_gpio(void)
  {
      u16 port_group[] = {
          [PORTA_GROUP] = 0xffff,
          [PORTB_GROUP] = 0xffff,
          [PORTC_GROUP] = 0xffff,
      };
  
  #if TCFG_ADKEY_ENABLE
      port_protect(port_group,TCFG_ADKEY_PORT);
  #endif
  
  #if TCFG_IOKEY_ENABLE
  	port_protect(port_group, TCFG_IOKEY_POWER_ONE_PORT);
      port_protect(port_group, TCFG_IOKEY_PREV_ONE_PORT);
      port_protect(port_group, TCFG_IOKEY_NEXT_ONE_PORT);
  #endif /* TCFG_IOKEY_ENABLE */
  
      //< close gpio
      gpio_dir(GPIOA, 0, 16, port_group[PORTA_GROUP], GPIO_OR);
      gpio_set_pu(GPIOA, 0, 16, ~port_group[PORTA_GROUP], GPIO_AND);
      gpio_set_pd(GPIOA, 0, 16, ~port_group[PORTA_GROUP], GPIO_AND);
      gpio_die(GPIOA, 0, 16, ~port_group[PORTA_GROUP], GPIO_AND);
      gpio_dieh(GPIOA, 0, 16, ~port_group[PORTA_GROUP], GPIO_AND);
  
      gpio_dir(GPIOB, 0, 16, port_group[PORTB_GROUP], GPIO_OR);
      gpio_set_pu(GPIOB, 0, 16, ~port_group[PORTB_GROUP], GPIO_AND);
      gpio_set_pd(GPIOB, 0, 16, ~port_group[PORTB_GROUP], GPIO_AND);
      gpio_die(GPIOB, 0, 16, ~port_group[PORTB_GROUP], GPIO_AND);
      gpio_dieh(GPIOB, 0, 16, ~port_group[PORTB_GROUP], GPIO_AND);
  
  
      gpio_dir(GPIOC, 0, 16, port_group[PORTC_GROUP], GPIO_OR);
      gpio_set_pu(GPIOC, 0, 16, ~port_group[PORTC_GROUP], GPIO_AND);
      gpio_set_pd(GPIOC, 0, 16, ~port_group[PORTC_GROUP], GPIO_AND);
      gpio_die(GPIOC, 0, 16, ~port_group[PORTC_GROUP], GPIO_AND);
      gpio_dieh(GPIOC, 0, 16, ~port_group[PORTC_GROUP], GPIO_AND);
  
      //< close usb io
      usb_iomode(1);
  }
  
  
  //-----------------------------------------------
  
  /*进软关机之前默认将IO口都设置成高阻状态，需要保留原来状态的请修改该函数*/
  extern void dac_power_off(void);
  void board_set_soft_poweroff(void)
  {
      u32 porta_value = 0xffff;
      u32 portb_value = 0xfffe;
      u32 portc_value = 0xffff;
  
  	if(TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15){
  		power_set_mode(PWR_LDO15);
  	}
  
      gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR);
      gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND);
      gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND);
      gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND);
      gpio_dieh(GPIOA, 0, 16, ~portc_value, GPIO_AND);
  
      //保留长按Reset Pin - PB1
      gpio_dir(GPIOB, 1, 15, portb_value, GPIO_OR);
      gpio_set_pu(GPIOB, 1, 15, ~portb_value, GPIO_AND);
      gpio_set_pd(GPIOB, 1, 15, ~portb_value, GPIO_AND);
      gpio_die(GPIOB, 1, 15, ~portb_value, GPIO_AND);
      gpio_dieh(GPIOB, 0, 16, ~portc_value, GPIO_AND);
  
      gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR);
      gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND);
      gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND);
      gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND);
      gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND);
  
      gpio_set_pull_up(IO_PORT_DP, 0);
      gpio_set_pull_down(IO_PORT_DP, 0);
      gpio_set_direction(IO_PORT_DP, 1);
      gpio_set_die(IO_PORT_DP, 0);
      gpio_set_dieh(IO_PORT_DP, 0);
  
      gpio_set_pull_up(IO_PORT_DM, 0);
      gpio_set_pull_down(IO_PORT_DM, 0);
      gpio_set_direction(IO_PORT_DM, 1);
      gpio_set_die(IO_PORT_DM, 0);
      gpio_set_dieh(IO_PORT_DM, 0);
  
  
  
  	/* dac_power_off(); */
  }
  
  #define     APP_IO_DEBUG_0(i,x)       //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);}
  #define     APP_IO_DEBUG_1(i,x)       //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);}
  
  
  void sleep_exit_callback(u32 usec)
  {
  	putchar('>');
      APP_IO_DEBUG_1(A, 6);
  
  	if(TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15){
  		/* putchar('}'); */
  		power_set_mode(TCFG_LOWPOWER_POWER_SEL);
  	}
  
  }
  
  void sleep_enter_callback(u8  step)
  {
      /* 此函数禁止添加打印 */
      if (step == 1) {
  		putchar('<');
          APP_IO_DEBUG_0(A, 6);
  #if TCFG_AUDIO_ENABLE
          dac_power_off();
  #endif/*TCFG_AUDIO_ENABLE*/
  		if(TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15){
  			/* putchar('{'); */
  			power_set_mode(PWR_LDO15);
  		}
      } else {
  
  		close_gpio();
  
  		gpio_set_pull_up(IO_PORTA_03, 0);
          gpio_set_pull_down(IO_PORTA_03, 0);
          gpio_set_direction(IO_PORTA_03, 1);
  
          gpio_set_pull_up(IO_PORT_DP, 0);
          gpio_set_pull_down(IO_PORT_DP, 0);
          gpio_set_direction(IO_PORT_DP, 1);
          gpio_set_die(IO_PORT_DP, 0);
  
          gpio_set_pull_up(IO_PORT_DM, 0);
          gpio_set_pull_down(IO_PORT_DM, 0);
          gpio_set_direction(IO_PORT_DM, 1);
          gpio_set_die(IO_PORT_DM, 0);
  	}
  }
  
  
  
  void board_power_init(void)
  {
      log_info("Power init : %s", __FILE__);
  
      power_init(&power_param);
  
      /*sdpg_config(1);*/
  
      power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff);
  
  	power_keep_dacvdd_en(0);
  
  	power_wakeup_init(&wk_param);
  
  #if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE)
      charge_check_and_set_pinr(0);
  #endif
  }
  #endif
  