comparison src/cs/drivers/drv_app/fchg/fchg_process.c @ 262:7420959e02ec

FCHG rework for charger plug/unplug debouncing
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 14 May 2021 05:38:55 +0000
parents 1a4413c4eb7e
children
comparison
equal deleted inserted replaced
261:841a848ba762 262:7420959e02ec
19 #if defined(CONFIG_TARGET_C155) || defined(CONFIG_TARGET_J100) 19 #if defined(CONFIG_TARGET_C155) || defined(CONFIG_TARGET_J100)
20 #define LEDC 0x20 20 #define LEDC 0x20
21 #else 21 #else
22 #define LEDC 0 22 #define LEDC 0
23 #endif 23 #endif
24
25 #define CHARGER_PLUG_DEBOUNCE_MS 200
24 26
25 /* 27 /*
26 * The following global variable captures the initial battery voltage 28 * The following global variable captures the initial battery voltage
27 * at the time of system boot - it is intended to be used for various 29 * at the time of system boot - it is intended to be used for various
28 * system start-up decisions. 30 * system start-up decisions.
286 handle_discharge(); 288 handle_discharge();
287 return; 289 return;
288 case FCHG_STATE_READY_TO_CHARGE: 290 case FCHG_STATE_READY_TO_CHARGE:
289 handle_discharge(); 291 handle_discharge();
290 if (!(msg->data[9] & CHGPRES)) { 292 if (!(msg->data[9] & CHGPRES)) {
291 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 293 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
292 return; 294 return;
293 } 295 }
294 if (pwr_ctrl->batt_mv < pwr_ctrl->config.start_thresh) 296 if (pwr_ctrl->batt_mv < pwr_ctrl->config.start_thresh)
295 start_charge_condition_met(); 297 start_charge_condition_met();
296 return; 298 return;
297 case FCHG_STATE_READY_TO_RECHARGE: 299 case FCHG_STATE_READY_TO_RECHARGE:
298 handle_discharge(); 300 handle_discharge();
299 if (!(msg->data[9] & CHGPRES)) { 301 if (!(msg->data[9] & CHGPRES)) {
300 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 302 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
301 return; 303 return;
302 } 304 }
303 if (pwr_ctrl->batt_mv < pwr_ctrl->config.restart_thresh) 305 if (pwr_ctrl->batt_mv < pwr_ctrl->config.restart_thresh)
304 start_charge_condition_met(); 306 start_charge_condition_met();
305 return; 307 return;
306 case FCHG_STATE_I2V_CAL_1: 308 case FCHG_STATE_I2V_CAL_1:
307 if (!(msg->data[9] & CHGPRES)) { 309 if (!(msg->data[9] & CHGPRES)) {
308 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 310 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
309 return; 311 return;
310 } 312 }
311 if (pwr_ctrl->config.bciconf) 313 if (pwr_ctrl->config.bciconf)
312 start_i2v_cal(); 314 start_i2v_cal();
313 else { 315 else {
320 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); 322 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
321 rvf_send_trace("i2v offset (MADC code) ", 23, 323 rvf_send_trace("i2v offset (MADC code) ", 23,
322 pwr_ctrl->i2v_offset, 324 pwr_ctrl->i2v_offset,
323 RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); 325 RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID);
324 if (!(msg->data[9] & CHGPRES)) { 326 if (!(msg->data[9] & CHGPRES)) {
325 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 327 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
326 pwr_init_discharge(); 328 pwr_init_discharge();
327 return; 329 return;
328 } 330 }
329 start_ci_charging(); 331 start_ci_charging();
330 return; 332 return;
331 case FCHG_STATE_CI_CHARGING: 333 case FCHG_STATE_CI_CHARGING:
332 ci_progress_trace(msg->data[2]); 334 ci_progress_trace(msg->data[2]);
333 if (!(msg->data[9] & CHGPRES)) { 335 if (!(msg->data[9] & CHGPRES)) {
334 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); 336 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
335 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 337 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
336 pwr_init_discharge(); 338 pwr_init_discharge();
337 return; 339 return;
338 } 340 }
339 if (charging_time_limit_check()) 341 if (charging_time_limit_check())
340 return; 342 return;
342 start_cv_charging(); 344 start_cv_charging();
343 return; 345 return;
344 case FCHG_STATE_CV_CHARGING: 346 case FCHG_STATE_CV_CHARGING:
345 if (!(msg->data[9] & CHGPRES)) { 347 if (!(msg->data[9] & CHGPRES)) {
346 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); 348 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
347 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 349 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
348 pwr_init_discharge(); 350 pwr_init_discharge();
349 return; 351 return;
350 } 352 }
351 if (cv_ichg_process(msg->data[2])) 353 if (cv_ichg_process(msg->data[2]))
352 return; 354 return;
414 process_adc_bsim(msg); 416 process_adc_bsim(msg);
415 else 417 else
416 process_adc_regular(msg); 418 process_adc_regular(msg);
417 } 419 }
418 420
419 void pwr_handle_timer(void) 421 void pwr_charger_plug_unplug_ind(void)
420 {
421 if (pwr_ctrl->state != FCHG_STATE_PWR_PLUG_TIMER)
422 return;
423 rvf_send_trace("Timer expired, ready to charge", 30, NULL_PARAM,
424 RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID);
425 pwr_ctrl->state = FCHG_STATE_READY_TO_CHARGE;
426 }
427
428 void pwr_charger_plug(void)
429 {
430 if (pwr_ctrl->state != FCHG_STATE_NO_EXT_PWR) {
431 rvf_send_trace("Charger plug event in unexpected state", 38,
432 pwr_ctrl->state, RV_TRACE_LEVEL_ERROR,
433 FCHG_USE_ID);
434 return;
435 }
436 if (pwr_ctrl->bsim_mode) {
437 rvf_send_trace("Charger plug in BSIM mode", 25, NULL_PARAM,
438 RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID);
439 pwr_ctrl->state = FCHG_STATE_READY_TO_CHARGE;
440 if (pwr_ctrl->event_handler)
441 pwr_ctrl->event_handler(FCHG_EVENT_CHARGER_PLUG);
442 return;
443 }
444 if (!pwr_ctrl->config_present) {
445 rvf_send_trace(
446 "Charger plugged in, but no config: won't charge", 47,
447 NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID);
448 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
449 return;
450 }
451 if (pwr_ctrl->config.start_delay) {
452 rvf_send_trace("Charger plug, starting timer", 28, NULL_PARAM,
453 RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID);
454 rvf_start_timer(FCHG_TIMER,
455 RVF_MS_TO_TICKS(pwr_ctrl->config.start_delay),
456 FALSE);
457 pwr_ctrl->state = FCHG_STATE_PWR_PLUG_TIMER;
458 } else {
459 rvf_send_trace("Charger plug, ready to charge", 29, NULL_PARAM,
460 RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID);
461 pwr_ctrl->state = FCHG_STATE_READY_TO_CHARGE;
462 }
463 if (pwr_ctrl->event_handler)
464 pwr_ctrl->event_handler(FCHG_EVENT_CHARGER_PLUG);
465 }
466
467 void pwr_charger_unplug(void)
468 { 422 {
469 switch (pwr_ctrl->state) { 423 switch (pwr_ctrl->state) {
470 case FCHG_STATE_NO_EXT_PWR: 424 case FCHG_STATE_NO_EXT_PWR:
471 rvf_send_trace("Charger unplug, already handled", 31, 425 rvf_send_trace("Charger plug interrupt, beginning debounce",
472 NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, 426 42, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW,
473 FCHG_USE_ID); 427 FCHG_USE_ID);
474 /* nothing to do */ 428 pwr_ctrl->state = FCHG_STATE_PWR_PLUG_TIMER;
475 break; 429 break;
476 case FCHG_STATE_PWR_PLUG_TIMER: 430 case FCHG_STATE_PWR_PLUG_TIMER:
431 /* debouncing in action - nothing to do here */
432 break;
477 case FCHG_STATE_READY_TO_CHARGE: 433 case FCHG_STATE_READY_TO_CHARGE:
478 case FCHG_STATE_READY_TO_RECHARGE: 434 case FCHG_STATE_READY_TO_RECHARGE:
479 case FCHG_STATE_I2V_CAL_1: 435 case FCHG_STATE_I2V_CAL_1:
480 case FCHG_STATE_RECHARGE_TIMER: 436 case FCHG_STATE_RECHARGE_TIMER:
481 case FCHG_STATE_NO_CHARGING: 437 case FCHG_STATE_NO_CHARGING:
482 rvf_send_trace("Charger unplug", 14, NULL_PARAM, 438 rvf_send_trace("Charger unplug", 14, NULL_PARAM,
483 RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); 439 RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID);
484 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 440 pwr_ctrl->state = FCHG_STATE_PWR_PLUG_TIMER;
441 if (pwr_ctrl->event_handler)
442 pwr_ctrl->event_handler(FCHG_EVENT_CHARGER_UNPLUG);
485 break; 443 break;
486 case FCHG_STATE_I2V_CAL_2: 444 case FCHG_STATE_I2V_CAL_2:
487 case FCHG_STATE_CI_CHARGING: 445 case FCHG_STATE_CI_CHARGING:
488 case FCHG_STATE_CV_CHARGING: 446 case FCHG_STATE_CV_CHARGING:
489 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); 447 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
490 rvf_send_trace("Charger unplug, charging stopped", 32, 448 rvf_send_trace("Charger unplug, charging stopped", 32,
491 NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, 449 NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH,
492 FCHG_USE_ID); 450 FCHG_USE_ID);
493 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; 451 pwr_ctrl->state = FCHG_STATE_PWR_PLUG_TIMER;
494 pwr_init_discharge(); 452 pwr_init_discharge();
453 if (pwr_ctrl->event_handler)
454 pwr_ctrl->event_handler(FCHG_EVENT_CHARGER_UNPLUG);
495 break; 455 break;
496 default: 456 default:
497 rvf_send_trace("Invalid state in pwr_charger_unplug()", 37, 457 rvf_send_trace("Invalid state in pwr_charger_plug_unplug_ind()",
498 pwr_ctrl->state, RV_TRACE_LEVEL_ERROR, 458 46, pwr_ctrl->state, RV_TRACE_LEVEL_ERROR,
499 FCHG_USE_ID); 459 FCHG_USE_ID);
500 } 460 }
501 if (pwr_ctrl->event_handler) 461 rvf_start_timer(FCHG_TIMER, RVF_MS_TO_TICKS(CHARGER_PLUG_DEBOUNCE_MS),
502 pwr_ctrl->event_handler(FCHG_EVENT_CHARGER_UNPLUG); 462 FALSE);
463 /* unmask further charger interrupts */
464 ABB_Write_Register_on_page(PAGE0, ITMASK, 0);
465 }
466
467 void pwr_handle_timer(void)
468 {
469 SYS_UWORD16 abb_status;
470
471 if (pwr_ctrl->state != FCHG_STATE_PWR_PLUG_TIMER) {
472 rvf_send_trace(
473 "Charger debounce timer expired in unexpected state",
474 50, pwr_ctrl->state, RV_TRACE_LEVEL_ERROR,
475 FCHG_USE_ID);
476 return;
477 }
478 /* so was it a plug or an unplug after all? */
479 abb_status = ABB_Read_Status();
480 if (abb_status & CHGPRES) {
481 /* charger plug */
482 if (pwr_ctrl->config_present || pwr_ctrl->bsim_mode) {
483 rvf_send_trace("Charger plug, ready to charge", 29,
484 NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH,
485 FCHG_USE_ID);
486 pwr_ctrl->state = FCHG_STATE_READY_TO_CHARGE;
487 if (pwr_ctrl->event_handler)
488 pwr_ctrl->event_handler(FCHG_EVENT_CHARGER_PLUG);
489 } else {
490 rvf_send_trace(
491 "Charger plugged in, but no config: won't charge", 47,
492 NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID);
493 pwr_ctrl->state = FCHG_STATE_NO_CHARGING;
494 }
495 } else {
496 /* charger unplug, already handled */
497 pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR;
498 }
503 } 499 }
504 500
505 void pwr_charge_start_req(void) 501 void pwr_charge_start_req(void)
506 { 502 {
507 switch (pwr_ctrl->state) { 503 switch (pwr_ctrl->state) {
508 case FCHG_STATE_NO_EXT_PWR: 504 case FCHG_STATE_NO_EXT_PWR:
505 case FCHG_STATE_PWR_PLUG_TIMER:
509 rvf_send_trace("Cannot charge without a power source", 36, 506 rvf_send_trace("Cannot charge without a power source", 36,
510 NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); 507 NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID);
511 return; 508 return;
512 case FCHG_STATE_NO_CHARGING: 509 case FCHG_STATE_NO_CHARGING:
513 if (!pwr_ctrl->config_present && !pwr_ctrl->bsim_mode) { 510 if (!pwr_ctrl->config_present && !pwr_ctrl->bsim_mode) {
515 NULL_PARAM, RV_TRACE_LEVEL_ERROR, 512 NULL_PARAM, RV_TRACE_LEVEL_ERROR,
516 FCHG_USE_ID); 513 FCHG_USE_ID);
517 return; 514 return;
518 } 515 }
519 /* FALL THRU */ 516 /* FALL THRU */
520 case FCHG_STATE_PWR_PLUG_TIMER:
521 case FCHG_STATE_READY_TO_CHARGE: 517 case FCHG_STATE_READY_TO_CHARGE:
522 case FCHG_STATE_READY_TO_RECHARGE: 518 case FCHG_STATE_READY_TO_RECHARGE:
523 case FCHG_STATE_RECHARGE_TIMER: 519 case FCHG_STATE_RECHARGE_TIMER:
524 rvf_send_trace("Starting charge on user request", 31, 520 rvf_send_trace("Starting charge on user request", 31,
525 NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, 521 NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH,
543 539
544 void pwr_charge_stop_req(void) 540 void pwr_charge_stop_req(void)
545 { 541 {
546 switch (pwr_ctrl->state) { 542 switch (pwr_ctrl->state) {
547 case FCHG_STATE_NO_EXT_PWR: 543 case FCHG_STATE_NO_EXT_PWR:
544 case FCHG_STATE_PWR_PLUG_TIMER:
548 case FCHG_STATE_NO_CHARGING: 545 case FCHG_STATE_NO_CHARGING:
549 /* nothing to do */ 546 /* nothing to do */
550 return; 547 return;
551 case FCHG_STATE_PWR_PLUG_TIMER:
552 case FCHG_STATE_READY_TO_CHARGE: 548 case FCHG_STATE_READY_TO_CHARGE:
553 case FCHG_STATE_READY_TO_RECHARGE: 549 case FCHG_STATE_READY_TO_RECHARGE:
554 case FCHG_STATE_I2V_CAL_1: 550 case FCHG_STATE_I2V_CAL_1:
555 case FCHG_STATE_RECHARGE_TIMER: 551 case FCHG_STATE_RECHARGE_TIMER:
556 rvf_send_trace("Charging disabled by user request", 33, 552 rvf_send_trace("Charging disabled by user request", 33,