bsp_charge.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. #include "include.h"
  2. #if CHARGE_EN
  3. #define TRACE_EN 0
  4. #if TRACE_EN
  5. #define TRACE(...) printf(__VA_ARGS__)
  6. #else
  7. #define TRACE(...)
  8. #endif
  9. #define DC_IN() ((RTCCON >> 20) & 0x01) //VUSB Online state: 0->not online, 1->online
  10. extern inbox_cb_t inbox_cb;
  11. extern u32 user_timer_isr_en;
  12. void charge_stop(u8 mode);
  13. void charge_init(charge_cfg_t *p);
  14. void bsp_188led_charge_full_disp(void);
  15. //充满电亮蓝灯时间table表, 秒单位
  16. AT(.rodata.charge)
  17. const u8 chag_bled_timeout_tbl[8] = {0, 10, 20, 30, 60, 120, 180, 255};
  18. //充电时间(单位30分钟)
  19. AT(.rodata.charge)
  20. const u8 chag_limited_tbl[8] = {0, 4, 5, 6, 7, 8, 10, 255};
  21. //AT(.com_rodata.tkey)
  22. //const char charge_on_str[] = "Charge on\n";
  23. //AT(.com_rodata.tkey)
  24. //const char charge_off_str[] = "Charge off: %d\n";
  25. /*
  26. ///降低充电时主控耗电
  27. AT(.text.bsp.charge) ALIGNED(512)
  28. void bsp_charge_power_save(void)
  29. {
  30. if (chbox_cb.pwrsave_en) {
  31. sys_clk_set(SYS_26M); //跑XOSC 26M
  32. adpll_disable();
  33. CLKGAT0 &= ~BIT(20); //disable bt 52m clock
  34. XO26MCON &= ~BIT(5); //DI_EN_CCKOUT_X2
  35. if (chbox_cb.pwrsave_en == 2) { //关晶振跑RC
  36. sys_clk_set(SYS_RC3M);
  37. sys.rc3m_clk = sys_get_rc2m_clkhz(0);
  38. vusb_uart_baud_set(0); //VUSB UART1使用系统时钟
  39. sys_uart0_baud_set(115200); //时钟频率太低, 使用低波特率
  40. RI_VIO_TC(0);
  41. GLOBAL_INT_DISABLE();
  42. TMR0CNT = 0;
  43. TMR0PR = sys.rc3m_clk / 1000 - 1; //1ms
  44. TMR0CON &= ~BIT(2); //tmr0 select sysclk
  45. if (sys_cb.breathe_led_sta) {
  46. breathe_led_timer_start(0);
  47. }
  48. RSTCON0 &= ~BIT(7); //reset adda_clk48_a
  49. CLKGAT0 &= ~(BIT(12) | BIT(22)); //disable dac clk
  50. GLOBAL_INT_RESTORE();
  51. XO26MCON &= ~((0xf<<24) | BIT(10) | BIT(5));//X26 output, xosc, xosc52m disable
  52. PLL0CON &= ~(BIT(12) | BIT(0) | BIT(1)); //PLL0 & XOSC关电
  53. }
  54. }
  55. }
  56. AT(.text.bsp.charge) ALIGNED(512)
  57. void bsp_charge_power_recover(void)
  58. {
  59. if (chbox_cb.pwrsave_en) {
  60. if (chbox_cb.pwrsave_en == 2) {
  61. PLL0CON |= BIT(0) | BIT(12); //enable xosc & pll电源,DI_EN_AVDD_SUPPLY
  62. XO26MCON |= BIT(10) | (0xf<<24); //xosc en, output
  63. RI_VIO_TC(3);
  64. delay_ms(5);
  65. GLOBAL_INT_DISABLE();
  66. CLKCON1 = (CLKCON1 & ~0x03) | 2; //dac clk select xosc26m_clk
  67. delay_us(2);
  68. CLKGAT0 |= (BIT(12) | BIT(22)); //dac clkgate enable
  69. RSTCON0 |= BIT(7); //release adda_clk48_a
  70. TMR0CNT = 0;
  71. TMR0PR = 1000 - 1; //1ms
  72. TMR0CON |= BIT(2); //tmr0 select tmr_inc
  73. if (sys_cb.breathe_led_sta) {
  74. breathe_led_timer_start(1);
  75. }
  76. GLOBAL_INT_RESTORE();
  77. sys_clk_set(SYS_26M); //跑XOSC 26M
  78. vusb_uart_baud_set(1); //VUSB UART1使用xosc_div_clk
  79. sys_uart0_baud_set(1500000); //还原UART0波特率
  80. }
  81. XO26MCON |= BIT(5); //DI_EN_CCKOUT_X2
  82. CLKGAT0 |= BIT(20); //enable bt 52m clock
  83. adpll_init(DAC_OUT_SPR);
  84. dac_clk_source_sel(1); //dac clk select adpll_div(PLL0)
  85. sys_clk_set(SYS_CLK_SEL);
  86. }
  87. }*/
  88. //AT(.com_rodata.tkey)
  89. //const char charge_on_str[] = "Charge on\n";
  90. //AT(.com_rodata.tkey)
  91. //const char charge_off_str[] = "Charge off: %d\n";
  92. AT(.com_text.charge)
  93. u8 bsp_charge_sta_hook(u8 sta)
  94. {
  95. if (sta == 1) {
  96. //充电开启
  97. sys_cb.charge_sta = 1;
  98. sys_cb.charge_full_bled_flag = 0;
  99. if (sys_led.charge_led_2s_en) {
  100. sys_cb.charge_full_bled_flag = 2; //借用下这个变量实现只亮2秒红灯
  101. sys_cb.ch_bled_cnt = 2;
  102. }
  103. charge_led_on();
  104. // printf(charge_on_str);
  105. } else {
  106. //充电关闭
  107. // printf(charge_off_str, sta);
  108. sys_cb.charge_sta = 0;
  109. sys_cb.charge_full_bled_flag = 0;
  110. charge_led_off(sta);
  111. if (sta == 2) {
  112. sys_cb.charge_sta = 2;
  113. //充电满亮蓝灯
  114. if (BLED_CHARGE_FULL > 1) {
  115. sys_cb.charge_full_bled_flag = 1;
  116. sys_cb.ch_bled_cnt = charge_cfg.bled_on_pr;
  117. charge_bled_on();
  118. #if LED_188LED_DISP_EN
  119. bsp_188led_charge_full_disp();
  120. #endif
  121. }
  122. }
  123. }
  124. return 1; //返回0时时用回rom的代码
  125. }
  126. #if TRACE_EN
  127. AT(.com_rodata.tkey)
  128. const char charge_on_str[] = "Charge on\n";
  129. AT(.com_rodata.tkey)
  130. const char charge_off_str[] = "Charge off: %d\n";
  131. #endif
  132. void bsp_charge_init(void)
  133. {
  134. charge_cfg_t *p = &charge_cfg;
  135. memset(p, 0, sizeof(charge_cfg_t));
  136. if (xcfg_cb.charge_en) {
  137. p->trick_curr_en = CHARGE_TRICK_EN;
  138. p->const_curr = CHARGE_CONSTANT_CURR & 0x1f;
  139. if (p->const_curr > 15) {
  140. p->const_curr = (p->const_curr - 15) * 2 + 15;
  141. }
  142. p->trick_curr = CHARGE_TRICKLE_CURR & 0x07;
  143. p->stop_curr = CHARGE_STOP_CURR & 0x0f;
  144. p->stop_volt = 0;
  145. p->dcin_reset = CHARGE_DC_RESET & 0x01;
  146. p->volt_follow = CHARGE_VOLT_FOLLOW;
  147. p->stop_time = 18000; //默认30分钟
  148. p->bled_on_pr = chag_bled_timeout_tbl[BLED_CHARGE_FULL];
  149. p->limited_time = UINT_MAX;
  150. p->stop_curr_thd = (xcfg_cb.ch_stop_curr_thd + 1) * 15;
  151. if (xcfg_cb.charge_limited_time > 6) {
  152. xcfg_cb.charge_limited_time = 0;
  153. }
  154. if (xcfg_cb.charge_limited_time) {
  155. p->limited_time = (u32)chag_limited_tbl[xcfg_cb.charge_limited_time] * 18000;
  156. }
  157. cfg_vio_chg_en = !CHARGE_PULL_OUT_FILTER_EN;
  158. // if (RTCCON3 & BIT(12)) {
  159. // sys_cb.inbox_wken_flag = 1;
  160. // }
  161. // RTCCON3 &= ~BIT(12); //RTCCON3[12], INBOX Wakeup disable
  162. if (!xcfg_cb.ch_inbox_sel) {
  163. RTCCON8 |= BIT(4); //inbox voltage selection. 1'b1, 1.7v; 1'b0, 1.1v
  164. } else {
  165. RTCCON8 &= ~BIT(4);
  166. }
  167. RTCCON11 &= ~BIT(6); //VUSB pull out filter disable
  168. bsp_charge_leakage_set(1, 0); //开机先打开leakage
  169. charge_init(p);
  170. }
  171. #if VUSB_SMART_VBAT_HOUSE_EN
  172. bsp_smart_vhouse_init();
  173. #endif
  174. if (xcfg_cb.charge_dc_reset && !(RTCCON & BIT(6))) {
  175. vusb_delay_rst_en(8); //soft kick vusb延时8秒复位使能
  176. sys_cb.dc_rst_flag = 1;
  177. }
  178. #if CHARGE_TSEN_DETECT
  179. sys_cb1.trick_curr_bkp = p->trick_curr;
  180. sys_cb1.const_curr_bkp = p->const_curr;
  181. #endif
  182. }
  183. ///5ms调用一次
  184. static u32 bsp_charge_box_process_do(void)
  185. {
  186. u8 chbox_sta, vhouse_sta = 0;
  187. chbox_cb.counter++;
  188. if ((user_timer_isr_en & BIT(1)) == 0) {
  189. if ((chbox_cb.counter % 20) == 0) { //100ms
  190. charge_detect();
  191. }
  192. if ((chbox_cb.counter % 180) == 0) { //1s
  193. bsp_charge_bled_ctrl();
  194. }
  195. #if USER_NTC
  196. sys_ntc_check();
  197. #endif // USER_NTC
  198. #if CHARGE_TSEN_DETECT
  199. charge_tsen_check(20);
  200. #endif
  201. }
  202. #if TRY_CHARGEBOX_PWROFF
  203. if(sys_cb1.charge_pwroff_flag)
  204. {
  205. msg_enqueue(EVT_CHARGE_PWROFF_BT_DISCONNECT);
  206. u8 charge_pwroff_delay = 100;
  207. while(charge_pwroff_delay--)
  208. {
  209. WDT_CLR();
  210. delay_ms(5);
  211. }
  212. sys_cb1.charge_pwroff_flag = false;
  213. sys_cb1.charge_pwroff_check_ticks = 0;
  214. sfunc_pwrdown(1);
  215. }
  216. #endif // TRY_CHARGEBOX_PWROFF
  217. #if VUSB_TBOX_QTEST_EN
  218. if(get_qtest_mode()){
  219. return 2;
  220. }
  221. #endif
  222. #if VUSB_SMART_VBAT_HOUSE_EN
  223. vhouse_sta = bsp_smart_vhouse_process(1);
  224. #endif
  225. if ((bsp_charge_box_sta() == 2) || (vhouse_sta == 2) || (sys_cb.ntc_2_pwrdwn_flag)) { //是否充满或NTC关机
  226. u8 vusb_wakeup_en = 1;
  227. if ((!sys_cb.ntc_2_pwrdwn_flag) || CHARGE_INBOX()) {
  228. bsp_charge_inbox_wakeup_enable(); //INBOX Wakeup enable
  229. vusb_wakeup_en = 0;
  230. }
  231. saradc_exit(adc_cb.channel);
  232. bsp_charge_tebcnt_calibration_stop();
  233. #if !TRY_CHARGEBOX_PWROFF
  234. sfunc_pwrdown(1);
  235. // sfunc_pwrdown(vusb_wakeup_en);
  236. #endif // TRY_CHARGEBOX_PWROFF
  237. }
  238. if (!CHARGE_DC_IN()) { //DC IN online?
  239. if (chbox_cb.dc_in) { //VUSB拔出?
  240. chbox_cb.dc_in = 0;
  241. bsp_charge_leakage_set(0, 0); //无VUSB电容的直接关漏电,防止唤醒先充满的耳机。
  242. if (xcfg_cb.ch_out_leakage_sel) {
  243. bsp_charge_leakage_set(0x81, xcfg_cb.ch_out_leakage_sel);
  244. }
  245. }
  246. chbox_sta = bsp_charge_inbox_check() & 0x3; //检查inbox online状态
  247. if ((chbox_sta == 0) && tick_check_expire(chbox_cb.ticks, 3000)) { //兼容IP5303的仓维持电压不稳且处于检测临界态问题
  248. chbox_sta = (!xcfg_cb.ch_inbox_sel) ? 2 : 1; //inbox 1.1v临界状态认为拿起,1.7v临界状态认为inbox在线。
  249. }
  250. #if VUSB_SMART_VBAT_HOUSE_EN
  251. if (vhouse_sta) { //智能充电仓已开盖, 需要退出充电流程
  252. bsp_charge_leakage_set(1, 0);
  253. if (chbox_sta == 1) { //dc_in = 0, 且inbox = 0
  254. sys_cb.outbox_pwron_flag = 1;
  255. }
  256. return 2;
  257. }
  258. #endif
  259. if (chbox_sta == 1) { //dc_in = 0, 且inbox = 0
  260. bsp_charge_leakage_set(1, 0);
  261. if (chbox_cb.out2pwr_en) { //拿起开机
  262. sys_cb.outbox_pwron_flag = 1;
  263. return 2;
  264. }
  265. return 1;
  266. } else if (chbox_sta == 2) { //dc_in = 0, inbox = 1, 仓内维持电压状态,需要关机
  267. bsp_charge_inbox_wakeup_enable(); //INBOX Wakeup enable
  268. saradc_exit(adc_cb.channel);
  269. bsp_charge_tebcnt_calibration_stop();
  270. sfunc_pwrdown(3);
  271. }
  272. } else {
  273. chbox_cb.dc_in = 1;
  274. chbox_cb.out2pwr_en = xcfg_cb.ch_out_auto_pwron_en;
  275. inbox_cb.off_cnt = 0;
  276. inbox_cb.on_cnt = 0;
  277. bsp_charge_leakage_set(1, 0);
  278. chbox_cb.ticks = tick_get();
  279. if ((chbox_cb.counter % 1000) == 0) { //5秒
  280. bsp_charge_bcnt_calibration((xcfg_cb.chbox_smart_en) ? 100 : 500);
  281. } else if (chbox_cb.counter == 400) {
  282. bsp_charge_bcnt_calibration((xcfg_cb.chbox_smart_en) ? 100 : 150);
  283. }
  284. }
  285. return 0;
  286. }
  287. u32 bsp_charge_box_process(void)
  288. {
  289. u32 charge_sta = bsp_charge_box_process_do();
  290. bsp_charge_tebcnt_calibration();
  291. return charge_sta;
  292. }
  293. void bsp_charge_box_enter(u32 out_auto_pwron)
  294. {
  295. #if TRY_CHARGEBOX_PWROFF
  296. sys_cb1.high_v_time = false;
  297. sys_cb1.low_v_time = true;
  298. sys_cb1.high_v_time_count = 0;
  299. sys_cb1.low_v_time_count = 0;
  300. sys_cb1.high_v_count = 0;
  301. sys_cb1.low_v_count = 0;
  302. sys_cb1.charge_pwroff_flag = false;
  303. sys_cb1.charge_pwroff_check_ticks = 0;
  304. #endif // TRY_CHARGEBOX_PWROFF
  305. memset(&chbox_cb, 0, sizeof(chbox_cb));
  306. chbox_cb.out2pwr_en = out_auto_pwron;
  307. #if (UART0_PRINTF_SEL != PRINTF_NONE)
  308. xcfg_cb.charge_lowpwr_en = 0;
  309. #endif
  310. chbox_cb.pwrsave_en = xcfg_cb.charge_lowpwr_en + 1;
  311. #if TRY_CHARGEBOX_PWROFF
  312. bsp_charge_inbox_chk_init(40/*20*/, 20/*120*/); //inbox online检测长点,等待VUSB电容放电
  313. #else
  314. bsp_charge_inbox_chk_init(20, 120); //inbox online检测长点,等待VUSB电容放电
  315. #endif // TRY_CHARGEBOX_PWROFF
  316. if (!xcfg_cb.ch_box_type_sel) { //短暂掉0V的仓
  317. inbox_cb.off_delay = 100+(u16)xcfg_cb.chbox_out_delay*20; //inbox offline check 500ms + n*100ms
  318. }
  319. chbox_cb.ticks = tick_get();
  320. bsp_bcnt_temp_calibration_start();
  321. bsp_charge_power_save();
  322. }
  323. void bsp_charge_box_reinit(void)
  324. {
  325. sys_cb.inbox_wken_flag = 0;
  326. bsp_charge_inbox_chk_init(10, 20);
  327. chbox_cb.leakage_sta = 0;
  328. if (bsp_chbox_type_is_maintain_volt()) {
  329. chbox_cb.inbox_rtt_check = 1;
  330. }
  331. }
  332. void bsp_charge_box_exit(void)
  333. {
  334. bsp_charge_power_recover();
  335. #if VUSB_TBOX_NEW_QTEST_EN
  336. chbox_cb.pwrsave_en = 0;
  337. #endif
  338. bsp_charge_box_reinit();
  339. bsp_charge_tebcnt_calibration_stop();
  340. #if TRY_CHARGEBOX_PWROFF
  341. sys_cb1.high_v_time = false;
  342. sys_cb1.low_v_time = true;
  343. sys_cb1.high_v_time_count = 0;
  344. sys_cb1.low_v_time_count = 0;
  345. sys_cb1.high_v_count = 0;
  346. sys_cb1.low_v_count = 0;
  347. sys_cb1.charge_pwroff_flag = false;
  348. sys_cb1.charge_pwroff_check_ticks = 0;
  349. #endif // TRY_CHARGEBOX_PWROFF
  350. }
  351. #if CHARGE_NTC_DETECT
  352. AT(.com_text.charge)
  353. u8 charge_ntc_get_sta(void)
  354. {
  355. if (sys_cb1.chg_ntc_stop) {
  356. return 1; // 1: 关闭充电灯,2:开启充电灯
  357. }
  358. return 0;
  359. }
  360. //AT(.com_rodata.text)
  361. //const char charge_ntc_check_str[] = "charge enable\n";
  362. //
  363. //AT(.com_rodata.text)
  364. //const char charge_ntc_check_str1[] = "charge disable\n";
  365. AT(.com_text.charge)
  366. void charge_ntc_check(void)
  367. {
  368. static int chg_en_cnt = 0;
  369. static int chg_dis_cnt = 0;
  370. if (xcfg_cb.sys_ntc_en && xcfg_cb.charge_en) {
  371. if (adc_cb.ntc_val <= CHARGE_NTC_DETECT_VAL) {
  372. if (chg_dis_cnt < 20) {
  373. chg_dis_cnt++;
  374. } else if (chg_dis_cnt == 20) {
  375. chg_dis_cnt = 30;
  376. RTCCON8 = (RTCCON8 & ~BIT(6)) | BIT(1); //disable charger function
  377. sys_cb1.chg_ntc_stop = 1;
  378. // printf(charge_ntc_check_str1);
  379. }
  380. chg_en_cnt = 0;
  381. } else {
  382. if (chg_en_cnt < 20) {
  383. chg_en_cnt++;
  384. } else if (chg_en_cnt == 20) {
  385. chg_en_cnt = 30;
  386. RTCCON8 = (RTCCON8 & ~BIT(1)) | BIT(6); //enable charger function
  387. charge_stop(0); //enter charge
  388. sys_cb1.chg_ntc_stop = 0;
  389. // printf(charge_ntc_check_str);
  390. }
  391. chg_dis_cnt = 0;
  392. }
  393. }
  394. }
  395. #endif
  396. #if CHARGE_TSEN_DETECT
  397. //AT(.com_rodata.text)
  398. //const char charge_tsen_check_str[] = "---> charge enable\n";
  399. //
  400. //AT(.com_rodata.text)
  401. //const char charge_tsen_check_str1[] = "---> charge disable\n";
  402. //
  403. //AT(.com_rodata.text)
  404. //const char charge_tsen_check_str2[] = "---> charge slow\n";
  405. AT(.com_text.charge)
  406. void charge_tsen_check(u8 change_cnt)
  407. {
  408. static int chg_tsen_en_cnt = 0;
  409. static int chg_tsen_dis_cnt = 0;
  410. static int chg_tsen_slow_cnt = 0;
  411. if (xcfg_cb.charge_en) {
  412. if (sys_cb1.adc_tsen_val >= CHARGE_TSEN_STOP_VAL) {
  413. if (chg_tsen_dis_cnt < change_cnt) {
  414. chg_tsen_dis_cnt++;
  415. } else if (chg_tsen_dis_cnt == change_cnt) {
  416. chg_tsen_dis_cnt = change_cnt + 10;
  417. RTCCON8 = (RTCCON8 & ~BIT(6)) | BIT(1); //disable charger function
  418. // printf(charge_tsen_check_str1);
  419. }
  420. chg_tsen_en_cnt = 0;
  421. chg_tsen_slow_cnt = 0;
  422. } else if (sys_cb1.adc_tsen_val < CHARGE_TSEN_SLOW_VAL) {
  423. if (chg_tsen_slow_cnt < change_cnt) {
  424. chg_tsen_slow_cnt++;
  425. } else if (chg_tsen_slow_cnt == change_cnt) {
  426. chg_tsen_slow_cnt = change_cnt + 10;
  427. charge_cfg.trick_curr = CHARGE_TSEN_SLOW_CURR;
  428. charge_cfg.const_curr = CHARGE_TSEN_SLOW_CURR;
  429. RTCCON8 = (RTCCON8 & ~BIT(1)) | BIT(6); //enable charger function
  430. charge_stop(0);
  431. // printf(charge_tsen_check_str2);
  432. }
  433. chg_tsen_en_cnt = 0;
  434. chg_tsen_dis_cnt = 0;
  435. } else {
  436. if (chg_tsen_en_cnt < change_cnt) {
  437. chg_tsen_en_cnt++;
  438. } else if (chg_tsen_en_cnt == change_cnt) {
  439. chg_tsen_en_cnt = change_cnt + 10;
  440. charge_cfg.trick_curr = sys_cb1.trick_curr_bkp;
  441. charge_cfg.const_curr = sys_cb1.const_curr_bkp;
  442. RTCCON8 = (RTCCON8 & ~BIT(1)) | BIT(6); //enable charger function
  443. charge_stop(0);
  444. // printf(charge_tsen_check_str);
  445. }
  446. chg_tsen_slow_cnt = 0;
  447. chg_tsen_dis_cnt = 0;
  448. }
  449. }
  450. }
  451. #endif
  452. #endif // CHARGE_EN