comparison chipsetsw/drivers/drv_app/lcc/lcc_handle_message.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:509db1a7b7b8
1 /******************************************************************************
2 * Power Task (pwr)
3 * Design and coding by Svend Kristian Lindholm, skl@ti.com
4 *
5 * PWR Message Processing
6 *
7 * $Id: pwr_handle_message.c 1.3 Wed, 20 Aug 2003 15:17:25 +0200 skl $
8 *
9 ******************************************************************************/
10 #include <string.h>
11 #include "lcc/lcc.h"
12 #include "lcc/lcc_api.h"
13 #include "lcc/lcc_trace.h"
14 #include "lcc/lcc_task.h"
15 #include "lcc/lcc_tm_i.h"
16 #include "lcc/lcc_cfg_i.h"
17 #include "lcc/lcc_cfg.h"
18 #include "lcc/lcc_modulate.h"
19
20 #include "rv/rv_defined_swe.h"
21
22 #include "ffs/ffs.h"
23
24 #include "etm/etm_env.h"
25
26 #include "abb/abb.h"
27 /******************************************************************************
28 * Function prototypes
29 ******************************************************************************/
30
31 void ttr(unsigned trmask, char *format, ...);
32 void str(unsigned mask, char *string);
33
34 void *pwr_malloc(int size);
35
36 T_RVM_RETURN pwr_task_init(void);
37
38 UINT32 pwr_timer_elapsed(UINT32 time_begin, UINT32 current_timer);
39 void build_name(const char *ch_pre, char *cfg_id , UINT8 index, const char * ch_post, char * name);
40
41 void pwr_modulate_init(void);
42 void pwr_modulate_on(void);
43 int pwr_capacity(uint16 Vbat);
44
45 void pwr_check_timers();
46 void pwr_stop_timers();
47
48 T_RVM_RETURN pwr_start_timer(UINT32 *timer_begin);
49 T_RVM_RETURN pwr_stop_timer(UINT32 *timer_begin);
50
51 T_RVM_RETURN pwr_check_files(void);
52 T_RVM_RETURN pwr_read_files(void);
53 T_RVM_RETURN pwr_read_chg_files(void);
54 T_RVM_RETURN pwr_read_cal_files(void);
55
56 void pwr_send_msg(uint32 msg_id ,T_RVF_ADDR_ID src_addr_id, T_RVF_ADDR_ID dest_addr_id);
57 void mmi_send_msg(struct mmi_info_ind_s *event);
58
59 void start_q401_charge(void);
60 void start_q402_charge(void);
61 void start_pre_charge(void);
62 void stop_q401_charge(void);
63 void stop_q402_charge(void);
64 void stop_pre_charge(void);
65 void charger_unplug_house_keeping(void);
66 void cv_charging_house_keeping(void);
67 void end_charging_house_keeping(void);
68 int check_chg_unplug(void);
69
70 #if (TEST_PWR_MMI_INTERFACE == 1)
71 #include "lcc/pwr_mmi_api.c"
72 #endif
73
74 extern T_PWR_CTRL_BLOCK *pwr_ctrl;
75 extern T_PWR_CFG_BLOCK *pwr_cfg;
76
77 /******************************************************************************
78 * Functions
79 ******************************************************************************/
80
81 void build_name(const char *ch_pre, char *cfg_id, UINT8 index, const char * ch_post, char * name)
82 {
83 char tmp[2];
84
85 strcpy(name, ch_pre);
86 tmp[0] = *cfg_id;
87 tmp[1] = 0; // null-termination of strings!
88 strcpy(&(name[index]), tmp);
89 strcat(name, ch_post);
90 ttw(ttr(TTrInit, "build_name: '%s'" NL, name));
91 }
92
93
94 T_RVM_RETURN pwr_task_init()
95 {
96 // Perform battery initialization of the pwr task by
97 // reading battery id and FFS configuration files
98 T_FFS_SIZE error;
99
100 ttw(ttr(TTrInit, "pwr_task_init(%d)" NL, 0));
101
102 // Check configuration and calibration files
103 if ((error = pwr_check_files()) < 0)
104 return error;
105
106 // Read configuration files
107 if ((error = pwr_read_files()) < 0)
108 return error;
109
110 ttw(ttr(TTrInit, "pwr_task_init(%d)" NL, 0xFF));
111 return RV_OK;
112
113 }
114
115 int pwr_chg_start(int Tbat) {
116 int capacity;
117 // Tbat is the temperature measured in Celsius
118 // Check start conditions for charging - it is assumed that a charger is plugged
119 // This check is used in state SUP
120
121 // Charging start will _not_ be performed if ...
122 // 1) Battery temperature is outside limits (measurement)
123 // 2) Charger identity is unknown
124
125 ttw(ttr(TTrCharge, "pwr_chg_start(%d)" NL, 0));
126
127 // 1)
128 // Battery temperature is outside limits (measurement)
129 // FIXME: Check also low temperatures
130 // if ((Tbat < pwr_cfg->temp.tbat_min) || (Tbat > pwr_cfg->temp.tbat_max)) {
131 if ((Tbat > pwr_cfg->temp.tbat_max)) {
132 ttw(ttr(TTrCharge, "pwr_chg_start(%d) Tbat=(%d)" NL, 0xFF, Tbat));
133 return FALSE;
134 }
135
136 // 2)
137 // Charger identity unknown
138 if ((pwr_ctrl->flag_chg_unknown == 1) && (pwr_ctrl->flag_mmi_registered == 1)) {
139 ttw(ttr(TTrCharge, "pwr_chg_start(%d) Chg unknown=(%d)" NL, 0xFF, Tbat));
140 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_UNKNOWN_IND;
141 mmi_send_msg(pwr_ctrl->mmi_ptr);
142 // Send only once
143 pwr_ctrl->flag_bat_unknown = 0;
144 return FALSE;
145 }
146
147 ttw(ttr(TTrCharge, "pwr_chg_start(%d)" NL, 0xFF));
148 return TRUE;
149 }
150
151 int pwr_chg_stop(int Tbat, int Vbat) {
152 // Check stop conditions for charging
153 // I.e.
154 // - temperature (RF+Battery) thresholds
155 // - battery voltage thresholds
156 // - regulation loop gain (duty cycle)
157 //
158 // This check is used regularly in state CCI, LCI, CCV and LCV
159
160 // Charging will be stopped if ...
161 // 1) Battery temperature is outside limits
162 // 2) Battery voltage is equal to - or above - charging stop battery voltage
163
164 // Nickel checks:
165 // 3) The RF temperature versus battery temperature rise is above threshold (Possible?)
166 //
167 // Lithium checks:
168 // 4) The regulation parameter k is below configured threshold limit
169 // Returns TRUE if the charging algorithm should be stopped
170 // Returns FALSE if the charging algorithm should be continued
171
172
173 ttw(ttr(TTrCharge, "pwr_chg_stop(%d)" NL, 0));
174
175 // 1)
176 // Battery temperature is outside limits
177 // FIXME: Check also low temperatures
178 if (Tbat > pwr_cfg->temp.tbat_max) {
179 ttw(ttr(TTrCharge, "pwr_chg_stop(%d) Tbat=(%d)" NL, 0xFF, Tbat));
180 if (pwr_ctrl->flag_mmi_registered == 1) {
181 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_FAILED_IND;
182 pwr_ctrl->mmi_ptr->cause = BATTERY_TEMPERATURE_HIGH;
183 mmi_send_msg(pwr_ctrl->mmi_ptr);
184 }
185 return TRUE;
186 }
187
188 // 2)
189 // Battery voltage is equal to - or above - charging stop battery voltage
190 if ((Vbat > pwr_cfg->bat.chg_stop_thr)) {
191 ttw(ttr(TTrCharge, "pwr_chg_stop(%d) Vbat=(%d)" NL, 0xFF, Vbat));
192 ttw(ttr(TTrCharge, "pwr_cfg->bat.chg_stop_thr=%d" NL, 0xFF, pwr_cfg->bat.chg_stop_thr));
193 return TRUE;
194 }
195 #if 0
196 #ifndef PWR_FFS_CFG
197 pwr_cfg->common.rise_thr = PWR_RISE_THR ;
198 #endif
199
200 // 3)
201 // The RF temperature versus battery temperature rise is above threshold (Possible?)
202 // Did the battery temperature rise more than the RF temperature rise - stop for Nickel charging!
203 // Only for Nickel batteries
204 // FIXME: How big time difference should there be between the deltas? Configurable?
205 if ((pwr_cfg->data.dTbat - pwr_cfg->data.dT_rf > pwr_cfg->common.rise_thr) == TRUE) {
206 ttw(ttr(TTrCharge, "pwr_chg_stop(%d) d(Tbat-Trf)=(%d)" NL, 0xFF, pwr_cfg->data.dTbat - pwr_cfg->data.dT_rf));
207 return TRUE;
208 }
209 #endif
210
211 // 4) FIXME: Remove states in this part of the function
212 // Regulation parameter k is below the configured limit
213 if ((pwr_cfg->bat.type == LITHIUM) &&
214 ((pwr_ctrl->state == LCV) || (pwr_ctrl->state == CCV)) &&
215 (pwr_cfg->data.k < pwr_cfg->bat.chg_ctrl_thr)) {
216 ttw(ttr(TTrCharge, "k=%d < %d" NL, pwr_cfg->data.k, pwr_cfg->bat.chg_ctrl_thr));
217 return TRUE;
218 }
219
220 ttw(ttr(TTrCharge, "pwr_chg_stop(%d)" NL, 0xFF));
221 return FALSE;
222 }
223
224 int pwr_chg_ci_cv_transition(int Vbat) {
225 // Check CI -> CV condition for charging
226 // Only for Lithium batteries
227 // Returns TRUE if CI-> CV transition should be made
228 // Returns FALSE if CI-> CV transition should NOT be made
229
230 ttw(ttr(TTrCharge, "pwr_chg_ci_cv_transition(%d)" NL, 0));
231
232 // 1) Check CV charging start threshold
233 if ((Vbat > pwr_cfg->bat.chg_start_thr)) {
234 ttw(ttr(TTrCharge, "pwr_chg_ci_cv_transition(%d) Vbat=(%d)" NL, 0xFF, Vbat));
235 return TRUE;
236 }
237
238 ttw(ttr(TTrCharge, "pwr_chg_ci_cv_transition(%d)" NL, 0xFF));
239 return FALSE;
240 }
241
242 int pwr_capacity(uint16 Vbat) {
243 // Calculate the capacity, C(T,V), of the battery based on
244 // - Battery Voltage Measurement
245 // - Battery Temperature Measurement
246 // - Configuration Parameters
247 // Returns a value in the interval 0..100 [%]
248 uint8 i;
249 uint8 cap;
250
251 ttw(ttr(TTrEventLow,"pwr_capacity (Vbat=%d)" NL, Vbat));
252 cap = 100; // 100%
253 for (i=0;i<=9;i++) {
254 if (Vbat < pwr_cfg->temp.cap[i] ) {
255 cap -= 10; // Count down 10% for each index
256 ttw(ttr(TTrEventLow,"Trying cap=%d" NL, cap));
257 } else {
258 // FIXME: Interpolate ... instead of truncate
259 ttw(ttr(TTrEventLow,"capacity=%d" NL, cap));
260 return cap;
261 }
262 }
263 ttw(ttr(TTrEventLow,"pwr_capacity (%d)" NL, 0xFF));
264 return 0; // Couldn't lookup capacity
265 }
266
267 int8 pwr_temp_lookup(uint16 ADC, uint8 i_meas) {
268 // temperature = f(ADC, I_meas)
269 // f(x) is table-lized using ETM command 'pww 4 ...'
270
271 int i;
272 int temp;
273
274 #define MAX_TEMP_SIZE 9
275
276 i = 0;
277 temp = -20;
278 // FIXME: Always using the second current - should also use the first...
279 while (ADC < pwr_cfg->temp.v2t_2[i] && i < MAX_TEMP_SIZE) {
280 ttw(ttr(TTrEventLow,"ADC=%d < pwr_cfg->temp.v2t_2[%d]=0x%x" NL, ADC,i, pwr_cfg->temp.v2t_2[i]));
281 ttw(ttr(TTrEventLow,"temp=%d" NL, temp));
282 i++;
283 temp += 10;
284 }
285 if (i == MAX_TEMP_SIZE) {
286 // No temperature found - return NULL value (0xFF)
287 ttr(TTrWarning, "Temperature lookup failed %d" NL, ADC);
288 return 0xFF;
289 }
290 if (i != 0) {
291 // Interpolate
292 if (pwr_cfg->temp.v2t_2[i-1] == 0xFFFF)
293 temp += 10*(ADC - pwr_cfg->temp.v2t_2[i])/(pwr_cfg->temp.v2t_2[i] - 1024);
294 else
295 temp += 10*(ADC - pwr_cfg->temp.v2t_2[i])/(pwr_cfg->temp.v2t_2[i] - pwr_cfg->temp.v2t_2[i-1]);
296 ttw(ttr(TTrEventLow,"Interpolated temp=%d" NL, temp));
297 }
298 return ((int8)temp);
299 }
300
301
302 enum {
303 Vbat = 0,
304 Vchg = 1,
305 Ichg = 2,
306 Vbt2 = 3,
307 Type = 4,
308 Tbat = 5,
309 T_rf = 6,
310 Tc_x = 7,
311 Tc_y = 8,
312 State= 9
313 } adc_index_e;
314
315 // The driving element of the LCC task - the ADC measurements
316 T_RV_RET process_spi_adc_indication (T_PWR_REQ *request)
317 {
318 struct pwr_adc_ind_s *ind;
319 int error, i, index;
320 int8 temp;
321 UINT32 timer;
322 UINT16 status; // Result of charger plug - unplug - polled
323
324 ind = (struct pwr_adc_ind_s*)request;
325
326 ttw(ttr(TTrEventLow,"State=%d" NL, ind->data[State]));
327
328 // Basic trace - not for CAL
329 switch (pwr_ctrl->state) {
330 case PRE :
331 ttw(ttr(TTrEventLow,"Vbat=%d" NL, ADC_to_mV(ind->data[Vbat])));
332 ttw(ttr(TTrEventLow,"Vchg=%d" NL, ADC_to_mV(ind->data[Vchg])));
333 ttw(ttr(TTrEventLow,"Ichg=%d" NL, ind->data[Ichg]));
334 break;
335 case INI :
336 case SUP :
337 case CCI :
338 case LCI :
339 case CCV :
340 case LCV :
341 ttw(ttr(TTrEventLow,"Vbat=%d" NL, ADC_to_mV(ind->data[Vbat])));
342 ttw(ttr(TTrEventLow,"Vbat_adc=%d" NL, ind->data[Vbat]));
343 #if (USE_Q402_CHG_CIRCUIT == 1)
344 // Vchg Scaling factor for Q402 circuit
345 pwr_cfg->data.Vchg = 5*ADC_to_mV(ind->data[Vchg])/4;
346 ttw(ttr(TTrEventLow,"Vchg=%d" NL, pwr_cfg->data.Vchg));
347 #else
348 pwr_cfg->data.Vchg = ADC_to_mV(ind->data[Vchg]);
349 ttw(ttr(TTrEventLow,"Vchg=%d" NL, pwr_cfg->data.Vchg));
350 #endif
351 ttw(ttr(TTrEventLow,"Ichg=%d" NL, ind->data[Ichg]));
352 ttw(ttr(TTrEventLow,"Type=%d" NL, ind->data[Type]));
353 ttw(ttr(TTrEventLow,"Tbat=%d" NL, ind->data[Tbat]));
354 ttw(ttr(TTrEventLow,"T_rf=%d" NL, ind->data[T_rf]));
355 ttw(ttr(TTrEventLow,"Vbt2=%d" NL, ADC_to_mV(ind->data[Vbt2])));
356 break;
357 }
358
359 // Updates variables in 'service' mode - not for CAL, PRE & INI
360 switch (pwr_ctrl->state) {
361 case SUP :
362 case CCI :
363 case LCI :
364 case CCV :
365 case LCV :
366 index = pwr_ctrl->index % CONSECUTIVE_CHG_UNPLUGS;
367 ttw(ttr(TTrEventLow,"Using index: (%d)" NL, index));
368 pwr_ctrl->index++;
369 // Get current nucleus time
370 timer = rvf_get_tick_count();
371
372 // T0 timer expired?
373 pwr_ctrl->time_elapsed_T0 = pwr_timer_elapsed(pwr_ctrl->time_begin_T0, timer);
374 ttw(ttr(TTrTimerLow,"T0: %d ms elapsed " NL, pwr_ctrl->time_elapsed_T0));
375
376 // Compare T0 with configured sampling rate
377 if (pwr_ctrl->time_elapsed_T0 > pwr_cfg->common.sampling) {
378 ttw(ttr(TTrTimer, "T0 Reset: elapsed (%d)" NL, pwr_ctrl->time_elapsed_T0));
379 pwr_ctrl->time_begin_T0 = timer;
380 ttr(TTrAll,"Vbat_avg=%d" NL, ADC_to_mV(pwr_cfg->data.Vbat_avg));
381
382 }
383
384 pwr_cfg->data.Vbat = ind->data[Vbat];
385 pwr_cfg->data.Vbat_avg = (ind->data[Vbat] + pwr_cfg->common.alfa1 * pwr_cfg->data.Vbat_avg)/(pwr_cfg->common.alfa1 + 1);
386 pwr_cfg->data.Vbat_avg_mV = ADC_to_mV(pwr_cfg->data.Vbat_avg);
387 ttw(ttr(TTrEventLow,"Vbat_avg=%d" NL, pwr_cfg->data.Vbat_avg_mV));
388
389 pwr_cfg->data.Tbat = ind->data[Tbat];
390 pwr_cfg->data.Tbat_avg = (ind->data[Tbat] + pwr_cfg->common.alfa2 * pwr_cfg->data.Tbat_avg)/(pwr_cfg->common.alfa2 + 1);
391 ttw(ttr(TTrEventLow,"Tbat_avg=%d" NL, pwr_cfg->data.Tbat_avg));
392 temp = pwr_temp_lookup(pwr_cfg->data.Tbat_avg, 0x01);
393 ttw(ttr(TTrEventLow,"temp=%d" NL, temp));
394
395 pwr_cfg->data.T_rf_avg = ind->data[T_rf];
396 pwr_cfg->data.T_rf_avg = (ind->data[T_rf] + pwr_cfg->common.alfa3 * pwr_cfg->data.T_rf_avg)/(pwr_cfg->common.alfa3 + 1);
397 ttw(ttr(TTrEventLow,"T_rf_avg=%d" NL, pwr_cfg->data.T_rf_avg));
398
399 pwr_cfg->data.Ichg = ind->data[Ichg];
400 break;
401 }
402
403 // 'Main' switch
404 ttw(ttr(TTrEventLow,"state=%d" NL, pwr_ctrl->state));
405 switch (pwr_ctrl->state) {
406 case CAL :
407 // Read calibration files
408 // Decide if SW precharge should be started (state PRE) or if a normal configuration scheme should be inititated (state INI)
409 error = pwr_read_cal_files();
410 if (error >= 0) {
411 // Save measurements - also initial values for averaging
412 pwr_cfg->data.Vbat_avg = pwr_cfg->data.Vbat = ind->data[Vbat];
413 pwr_cfg->data.Vbat_avg_mV = ADC_to_mV(pwr_cfg->data.Vbat_avg);
414 ttw(ttr(TTrEventLow,"Vbat=%d" NL, ADC_to_mV(ind->data[Vbat])));
415 ttw(ttr(TTrEventLow,"Vchg=%d" NL, ADC_to_mV(ind->data[Vchg])));
416
417 // Charger was already inserted?
418 status = ind->data[State];
419
420 if (status & CHGPRES) {
421 // Charger plugged caused a wakeup
422 pwr_ctrl->flag_chg_plugged = 1;
423 pwr_ctrl->flag_chg_prev_plugged = 1;
424 ttw(ttr(TTrInitLow,"Polled - charger plugged (%d)" NL, status));
425 }
426
427 // Check Pre-charge - immediately change state to PRE
428 if ((pwr_cfg->data.Vbat_avg_mV < VBAT_PRECHG_START) && (pwr_ctrl->flag_chg_plugged == 1)) {
429 ttw(ttr(TTrInitLow,"precharge (%d)" NL, ADC_to_mV(ind->data[Vbat])));
430 // Charger interrupts (plug/unplug) are already masked off - in case it was a linear charger
431 pwr_ctrl->state = PRE;
432 } else {
433 pwr_ctrl->state = INI;
434 }
435 }
436 break;
437 case PRE :
438 // Start fast charge immediately after 3.2V boot
439 // Enter INI state - in order to read FFS configuration files - when Vbat reaches 3.6V
440
441 // Hardcoding moving average to PRECHG_AVG_WINDOW_SIZE since we haven't read any configuration
442 pwr_cfg->data.Vbat = ind->data[Vbat];
443 pwr_cfg->data.Vbat_avg = (ind->data[Vbat] + PRECHG_AVG_WINDOW_SIZE * pwr_cfg->data.Vbat_avg)/(PRECHG_AVG_WINDOW_SIZE + 1);
444 pwr_cfg->data.Vbat_avg_mV = ADC_to_mV(pwr_cfg->data.Vbat_avg);
445 if (pwr_cfg->data.Vbat_avg_mV > VBAT_PRECHG_STOP) {
446 ttw(ttr(TTrInitLow,"state PRE (%d > VBAT_PRECHG_STOP)" NL, pwr_cfg->data.Vbat_avg_mV));
447 pwr_ctrl->state = INI;
448 pwr_ctrl->flag_prechg_started = 0;
449 stop_pre_charge();
450 } else {
451 ttw(ttr(TTrInitLow,"state PRE (%d < VBAT_PRECHG_STOP)" NL, pwr_cfg->data.Vbat_avg_mV));
452 // Start fast charging NOW
453 if (pwr_ctrl->flag_prechg_started == 0) {
454 pwr_ctrl->flag_prechg_started = 1;
455 start_pre_charge();
456 }
457 }
458 break;
459 case INI :
460 // Charger was already inserted?
461 status = ind->data[State];
462 pwr_ctrl->chg_unplug_vec[index] = (status & CHGPRES);
463 if (status & CHGPRES) {
464 // Charger plugged caused a wakeup
465 pwr_ctrl->flag_chg_plugged = 1;
466 pwr_ctrl->flag_chg_prev_plugged = 1;
467 ttw(ttr(TTrInitLow,"Polled - charger plugged (%d)" NL, status));
468 }
469
470 if (pwr_ctrl->flag_ini_virgo == 0) {
471 // Perform some very basic initialization
472
473 /* Precharge (C/20) is switched OFF since it was finished in state PRE */
474 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0002);
475
476 // Enable battery type identification
477 // Switch on battery type identification (TYPEN)
478 // NOTE: Battery type identification is ALWAYS done with 10uA (TYPEN)
479 ttw(ttr(TTrInitLow,"Enable type ident (%d)" NL, 0x00));
480 ABB_Write_Register_on_page(PAGE0, BCICTL1, THERMAL_SENSOR_30uA | TYPEN);
481 pwr_ctrl->flag_ini_virgo = 1;
482
483 }
484
485 // Don't read battery files before we know which battery id to use
486 // We will ignore the first BATTERY_TYPE_SLIP measurements of battery id
487 if ((pwr_ctrl->count_bat_type == BATTERY_TYPE_SLIP)) {
488
489 error = pwr_task_init();
490
491 // Change state
492 pwr_ctrl->state = SUP;
493
494 // Readout /pwr/common.cfg
495 ttw(ttr(TTrInitLow,"common.cfg: pins: %d" NL, pwr_cfg->common.pins));
496 ttw(ttr(TTrInitLow,"chg_dedic %d" NL, pwr_cfg->common.chg_dedic));
497 ttw(ttr(TTrInitLow,"sampling %d" NL, pwr_cfg->common.sampling));
498 ttw(ttr(TTrInitLow,"mod_cycle %d" NL, pwr_cfg->common.mod_cycle));
499 ttw(ttr(TTrInitLow,"alfa1 %d" NL, pwr_cfg->common.alfa1));
500 ttw(ttr(TTrInitLow,"alfa2 %d" NL, pwr_cfg->common.alfa2));
501 ttw(ttr(TTrInitLow,"alfa3 %d" NL, pwr_cfg->common.alfa3));
502 ttw(ttr(TTrInitLow,"rise_thr %d" NL, pwr_cfg->common.rise_thr));
503
504 // Readout /pwr/bat/bat.cfg
505 ttw(ttr(TTrInitLow,"bat.cfg: type: %d" NL, pwr_cfg->bat.type));
506 ttw(ttr(TTrInitLow,"rf_temp: %d" NL, pwr_cfg->bat.rf_temp));
507 ttw(ttr(TTrInitLow,"id_low: %d" NL, pwr_cfg->bat.id_low));
508 ttw(ttr(TTrInitLow,"id_high: %d" NL, pwr_cfg->bat.id_high));
509 ttw(ttr(TTrInitLow,"cbat: %d" NL, pwr_cfg->bat.cbat));
510 ttw(ttr(TTrInitLow,"ratio: %d" NL, pwr_cfg->bat.ratio));
511 ttw(ttr(TTrInitLow,"T1: %d" NL, pwr_cfg->bat.T1));
512 ttw(ttr(TTrInitLow,"T2: %d" NL, pwr_cfg->bat.T2));
513 ttw(ttr(TTrInitLow,"T3: %d" NL, pwr_cfg->bat.T3));
514 ttw(ttr(TTrInitLow,"chg_start_thr: %d" NL, pwr_cfg->bat.chg_start_thr));
515 ttw(ttr(TTrInitLow,"chg_stop_thr: %d" NL, pwr_cfg->bat.chg_stop_thr));
516 ttw(ttr(TTrInitLow,"chg_ctrl_thr: %d" NL, pwr_cfg->bat.chg_ctrl_thr));
517 ttw(ttr(TTrInitLow,"chg_again_thr: %d" NL, pwr_cfg->bat.chg_again_thr));
518
519 // Readout /pwr/bat/temp<N>.cfg
520 ttw(ttr(TTrInitLow,"sizeof(temp): %d" NL, sizeof(pwr_cfg->temp)));
521 ttw(ttr(TTrInitLow,"sizeof(T_PWR_BAT_TEMP_CFG_BLOCK): %d" NL, sizeof(T_PWR_BAT_TEMP_CFG_BLOCK)));
522 ttw(ttr(TTrInitLow,"temp.cfg: tbat_min: %d" NL, pwr_cfg->temp.tbat_min));
523 ttw(ttr(TTrInitLow,"tbat_max: %d" NL, pwr_cfg->temp.tbat_max));
524 ttw(ttr(TTrInitLow,"i_meas1: %d" NL, pwr_cfg->temp.i_meas1));
525 for (i=0;i<=8;i++) {
526 ttw(ttr(TTrInitLow,"v2t_1[]: %d" NL, pwr_cfg->temp.v2t_1[i]));
527 }
528 ttw(ttr(TTrInitLow,"i_meas2: %d" NL, pwr_cfg->temp.i_meas2));
529 for (i=0;i<=8;i++) {
530 ttw(ttr(TTrInitLow,"v2t_2[]: %d" NL, pwr_cfg->temp.v2t_2[i]));
531 }
532 for (i=0;i<=9;i++) {
533 ttw(ttr(TTrInitLow,"cap[]: %d" NL, pwr_cfg->temp.cap[i]));
534 }
535 ttw(ttr(TTrInitLow,"a0: %d" NL, pwr_cfg->temp.a0));
536 ttw(ttr(TTrInitLow,"a1: %d" NL, pwr_cfg->temp.a1));
537 ttw(ttr(TTrInitLow,"a2: %d" NL, pwr_cfg->temp.a2));
538
539 // Readout /mmi/pwr/bsie.cfg
540 ttw(ttr(TTrInitLow,"mmi repetition: %d" NL, pwr_cfg->mmi.repetition));
541
542 // Initialize battery temperature - must not be made in the virgo part since Tbat=0
543 pwr_cfg->data.Tbat_avg = ind->data[Tbat];
544
545 // Setup thermal sensor - don't re-enable TYPEN
546 if (pwr_cfg->temp.i_meas2 == 50) {
547 ttw(ttr(TTrInitLow,"ABB set i_current: %d" NL, pwr_cfg->temp.i_meas2));
548 ABB_Write_Register_on_page(PAGE0, BCICTL1, THERMAL_SENSOR_50uA);
549 } else if (pwr_cfg->temp.i_meas2 == 30) {
550 ttw(ttr(TTrInitLow,"ABB set i_current: %d" NL, pwr_cfg->temp.i_meas2));
551 ABB_Write_Register_on_page(PAGE0, BCICTL1, THERMAL_SENSOR_30uA);
552 } else {
553 // Default 30uA
554 ttw(ttr(TTrInitLow,"ABB set i_current default: %d" NL, pwr_cfg->temp.i_meas2));
555 ABB_Write_Register_on_page(PAGE0, BCICTL1, THERMAL_SENSOR_30uA);
556 }
557
558 } else {
559 // Compare battery id with values found in FFS
560 // First value(s) are NOT to be trusted
561 pwr_ctrl->count_bat_type++;
562 pwr_cfg->data.bat_id = ind->data[Type];
563
564 }
565 break;
566 case SUP :
567 // Charger inserted?? Poll!!
568 // Reason: 100Hz interrupts will occur if an unregulated charger is inserted & charger interrupts are enabled
569 // This will cause an immediate crash!
570 status = ind->data[State];
571 pwr_ctrl->chg_unplug_vec[index] = (status & CHGPRES);
572 if (status & CHGPRES) {
573 // Charger is plugged - continue
574 ttw(ttr(TTrEventLow,"Polled - chg plugged (%d)" NL, status));
575 pwr_ctrl->flag_chg_plugged = 1;
576 pwr_ctrl->capacity = pwr_capacity(pwr_cfg->data.Vbat_avg_mV);
577 } else {
578 pwr_ctrl->flag_chg_plugged = 0;
579 }
580
581 if (pwr_ctrl->flag_mmi_registered == 1) {
582
583 // If the charger is plugged and no charging is initiated this message will be repeated until charging has started
584 // Charger plugged
585 if ((pwr_ctrl->flag_chg_plugged == 1) && (pwr_ctrl->flag_chg_prev_plugged == 0)) {
586 pwr_ctrl->flag_chg_prev_plugged = 1;
587 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_PLUG_IND;
588 mmi_send_msg(pwr_ctrl->mmi_ptr);
589 }
590 // Charger unplugged
591 if ((pwr_ctrl->flag_chg_plugged == 0) && (pwr_ctrl->flag_chg_prev_plugged == 1)) {
592 pwr_ctrl->flag_chg_prev_plugged = 0;
593 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_UNPLUG_IND;
594 mmi_send_msg(pwr_ctrl->mmi_ptr);
595 }
596
597 if (pwr_ctrl->flag_bat_unknown == 1) {
598 // Battery unknown - inform the MMI
599 pwr_ctrl->mmi_ptr->header.msg_id = MMI_BAT_UNKNOWN_IND;
600 mmi_send_msg(pwr_ctrl->mmi_ptr);
601 // Send only once
602 pwr_ctrl->flag_bat_unknown = 0;
603 }
604
605 }
606 pwr_check_timers();
607
608 // If charger is plugged AND charger configuration is not read AND capacity is below configured limit - charger id Vchg(Load=0) must be measured
609 if ((pwr_ctrl->flag_chg_plugged == 1) &&
610 (pwr_ctrl->flag_chg_cfg_read == 0) &&
611 (pwr_ctrl->capacity < pwr_cfg->bat.chg_again_thr)
612 ) {
613
614 // Measurement loop - Take the 2nd Vchg(0) measurements
615 if (pwr_ctrl->count_chg_type == CHARGER_TYPE_SLIP) {
616 if (pwr_cfg->data.Vchg > CHARGER_TYPE_OUT_OF_BOUND_LOW)
617 pwr_cfg->data.chg_id = pwr_cfg->data.Vchg;
618 else {
619 // Out of bound!!
620 ttr(TTrWarning, "Charger id out of bound! %d" NL, pwr_cfg->data.Vchg);
621 pwr_cfg->data.chg_id = CHARGER_TYPE_TYPICAL;
622 }
623 ttw(ttr(TTrEventLow,"Using chg id=%d" NL, pwr_cfg->data.chg_id));
624 error = pwr_read_chg_files();
625 pwr_ctrl->flag_chg_cfg_read = 1;
626
627 // Initialize the circular buffer with charger plugs
628 for (i=0;i<= CONSECUTIVE_CHG_UNPLUGS-1 ;i++)
629 pwr_ctrl->chg_unplug_vec[i] = CHGPRES;
630
631 if (pwr_chg_start(pwr_temp_lookup(pwr_cfg->data.Tbat_avg, 0x01)) == TRUE ) {
632 if (pwr_cfg->chg.type == CI) {
633 pwr_ctrl->state = CCI;
634 // Enable charger plug/unplug interrupts for a CI charger
635 ABB_Write_Register_on_page(PAGE0, ITMASK, ALL_IT_UMSK);
636 } else {
637 if (pwr_cfg->chg.type == UNREGULATED)
638 pwr_ctrl->state = LCI;
639 else {
640 ttr(TTrWarning, "Unknown charger type! %d" NL, pwr_cfg->chg.type);
641 pwr_ctrl->state = LCI;
642 }
643 }
644 #if (USE_Q401_CHG_CIRCUIT == 1)
645 start_q401_charge();
646 #endif
647
648 #if (USE_Q402_CHG_CIRCUIT == 1)
649 start_q402_charge();
650 #endif
651
652 // Stop the mmi info repetition timer
653 pwr_stop_timer(&pwr_ctrl->time_begin_mmi_rep);
654 }
655 } else {
656 pwr_ctrl->count_chg_type++;
657 ttw(ttr(TTrEventLow,"count_chg_type=%d" NL, pwr_ctrl->count_chg_type));
658 }
659 }
660 break;
661 case CCI :
662 pwr_check_timers();
663 // We are in the middle of a CI charging process - check stop criterias
664 //
665 if ( pwr_chg_stop(pwr_temp_lookup(pwr_cfg->data.Tbat_avg, 0x01), pwr_cfg->data.Vbat_avg_mV) == FALSE) {
666 // Continue to charge - change state?
667 if ((pwr_cfg->bat.type == LITHIUM) && (pwr_chg_ci_cv_transition(pwr_cfg->data.Vbat_avg_mV)== TRUE)) {
668 // Change state to CCV
669 // Calculate k value
670 // Start T2 timer
671 // Start DC timer
672 // Start T4 timer based on k value
673 // Modulation ON
674 pwr_ctrl->state = CCV;
675 cv_charging_house_keeping();
676 }
677 } else {
678 // Change state
679 pwr_ctrl->state = SUP;
680 end_charging_house_keeping();
681
682 }
683 break;
684 case LCI :
685 // Poll ABB for charger unplug - Linear - unregulated chargers ONLY
686 status = ind->data[State];
687 pwr_ctrl->chg_unplug_vec[index] = (status & CHGPRES);
688 if (status & CHGPRES) {
689 // Charger is still plugged - continue
690 ttw(ttr(TTrEventLow,"Polled - chg plugged (%d)" NL, status));
691 } else {
692 if (check_chg_unplug() == 1) {
693 // Charger is not plugged anymore - stop!!
694 ttw(ttr(TTrEventLow,"Verdict - chg not plugged (%d)" NL, status));
695 // Change state
696 pwr_ctrl->state = SUP;
697 charger_unplug_house_keeping();
698 pwr_free(request);
699 return;
700 } else {
701 // False alarm - don't set flags
702 ttw(ttr(TTrEventLow,"Polled - chg not plugged - FALSE alarm? (%d)" NL, status));
703 #if (USE_Q401_CHG_CIRCUIT == 1)
704 if ((ind->data[Ichg] == 0) && (pwr_cfg->data.Vchg > 0)) {
705 // Charging current has disappeared due to a fast unplug??? Bug in IOTA ABB?
706 pwr_ctrl->state = SUP;
707 charger_unplug_house_keeping();
708 pwr_free(request);
709 return;
710 }
711 #endif
712 #if (USE_Q402_CHG_CIRCUIT == 1)
713 // FIXME: Really no false alarm code for Q402??
714 #endif
715
716 }
717 }
718 pwr_check_timers();
719 // We are in the middle of a CI charging process - check stop criterias
720 if ( pwr_chg_stop(pwr_temp_lookup(pwr_cfg->data.Tbat_avg, 0x01), pwr_cfg->data.Vbat_avg_mV) == FALSE) {
721 // Continue to charge - change state?
722 if ((pwr_cfg->bat.type == LITHIUM) && (pwr_chg_ci_cv_transition(pwr_cfg->data.Vbat_avg_mV)== TRUE)) {
723 // Change state to LCV
724 // Calculate k value
725 // Start T2 timer
726 // Start DC timer
727 // Start T4 timer based on k value
728 // Modulation ON
729 pwr_ctrl->state = LCV;
730 cv_charging_house_keeping();
731 }
732 } else {
733
734 // Change state
735 pwr_ctrl->state = SUP;
736 end_charging_house_keeping();
737
738 }
739 break;
740 case CCV :
741 pwr_check_timers();
742 // We are in the middle of a CV charging process - check stop criterias
743 if (pwr_chg_stop(pwr_temp_lookup(pwr_cfg->data.Tbat_avg, 0x01), pwr_cfg->data.Vbat_avg_mV) == FALSE) {
744 // EMPTY - waiting for T4 and DC timeouts OR T2 timeout
745 } else {
746 // Change state
747 pwr_ctrl->state = SUP;
748 end_charging_house_keeping();
749 }
750 break;
751 case LCV :
752 // Poll ABB for charger unplug - Linear - unregulated chargers ONLY
753 status = ind->data[State];
754 pwr_ctrl->chg_unplug_vec[index] = (status & CHGPRES);
755 if (status & CHGPRES) {
756 // Charger is still plugged - continue
757 ttw(ttr(TTrEventLow,"Polled - chg plugged (%d)" NL, status));
758 } else {
759 #if (USE_Q401_CHG_CIRCUIT == 1)
760 // Charger is not plugged anymore - stop!!
761 ttw(ttr(TTrEventLow,"Verdict - chg not plugged (%d)" NL, status));
762 // Change state
763 pwr_ctrl->state = SUP;
764 charger_unplug_house_keeping();
765 pwr_free(request);
766 return;
767 #endif
768 #if (USE_Q402_CHG_CIRCUIT == 1)
769 if (check_chg_unplug() == 1) {
770 // Charger is not plugged anymore - stop!!
771 ttw(ttr(TTrEventLow,"Verdict - chg not plugged (%d)" NL, status));
772 // Change state
773 pwr_ctrl->state = SUP;
774 charger_unplug_house_keeping();
775 pwr_free(request);
776 return;
777 }
778 #endif
779 }
780 pwr_check_timers();
781 // We are in the middle of a CV charging process - check stop criterias
782 if (pwr_chg_stop(pwr_temp_lookup(pwr_cfg->data.Tbat_avg, 0x01), pwr_cfg->data.Vbat_avg_mV) == FALSE) {
783 // EMPTY - waiting for T4 and DC timeouts OR T2 timeout
784 } else {
785 // Change state
786 pwr_ctrl->state = SUP;
787 end_charging_house_keeping();
788 }
789 break;
790 default :
791 {
792 // Exception Handling - Unknown State
793 ttr(TTrFatal, "process_spi_adc_indication: Unknown State: %d" NL, pwr_ctrl->state);
794 }
795 }
796 pwr_free(request);
797 return RV_OK;
798 }
799
800 T_RV_RET process_abb_chg_unplugged_ind (T_PWR_REQ *request)
801 {
802
803 charger_unplug_house_keeping();
804 // Disable charger interrupts - they where enabled when the CI charger was connected
805 ABB_Write_Register_on_page(PAGE0, ITMASK, CHARGER_IT_MSK);
806
807 // A charger can be unplugged in any state
808 switch (pwr_ctrl->state) {
809 case SUP :
810 case CCI :
811 case CCV :
812 // Change state - T3 is running
813 pwr_ctrl->state = SUP;
814 break;
815 default :
816 {
817 // Exception Handling - Unknown State
818 ttr(TTrFatal, "process_abb_chg_unplugged_ind: Unknown State: %d" NL, pwr_ctrl->state);
819 }
820 }
821 pwr_free(request);
822 return RV_OK;
823 }
824
825 void pwr_send_msg(uint32 msg_id, T_RVF_ADDR_ID src_addr_id, T_RVF_ADDR_ID dest_addr_id) {
826 struct pwr_req_s *msg;
827
828 if ((msg = pwr_malloc(sizeof(struct pwr_req_s))) == NULL) {
829 return;
830 }
831 msg->header.msg_id = msg_id;
832 msg->header.src_addr_id = src_addr_id;
833 msg->header.dest_addr_id = dest_addr_id;
834 msg->header.callback_func = NULL;
835 if (rvf_send_msg(dest_addr_id, msg) != RV_OK) {
836 ttr(TTrFatal, "PWR FATAL: Send failed! %d" NL, 0xFF);
837 }
838 }
839
840 void mmi_send_msg(struct mmi_info_ind_s *event) {
841 ttw(ttr(TTrInit,"mmi_send_msg(%d)" NL, 0));
842 if (pwr_ctrl->rpath.callback_func) {
843 ttw(ttr(TTrInit,"Using callback (0x%x)" NL, pwr_ctrl->rpath.callback_func));
844 (pwr_ctrl->rpath.callback_func) (event);
845 } else {
846 if (pwr_ctrl->rpath.addr_id) {
847 // TESTME
848 rvf_send_msg(pwr_ctrl->rpath.addr_id, event);
849 } else {
850 ttr(TTrFatal,"PWR FATAL: mmi_send_msg(%d) No return path" NL, 0xFF);
851 return;
852 }
853 }
854 ttw(ttr(TTrInit,"mmi_send_msg(%d)" NL, 0xFF));
855 }
856
857 void start_pre_charge(void) {
858 ttw(ttr(TTrInitLow,"start_pre_charge" NL, 0x00));
859 #if (USE_Q401_CHG_CIRCUIT == 1)
860 /* Program the DAC with the constant current value */
861 // Value is hardcoded!! No configuration exist for state PRE
862 ABB_Write_Register_on_page(PAGE0, CHGREG, ICHG_PRECHG);
863
864 /* Enable the charger */
865 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0003);
866 #endif
867 #if (USE_Q402_CHG_CIRCUIT == 1)
868 pwr_modulate_init();
869 #endif
870 ttw(ttr(TTrInitLow,"start_pre_charge" NL, 0xFF));
871
872 }
873
874 void start_q401_charge(void) {
875
876 ttw(ttr(TTrInitLow,"start_q401_charge" NL, 0x00));
877 if (pwr_ctrl->flag_mmi_registered == 1) {
878 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_START_IND;
879 mmi_send_msg(pwr_ctrl->mmi_ptr);
880 }
881
882 /* Program the DAC with the constant current value taken from /pwr/chg/chg<N>.cfg */
883 ABB_Write_Register_on_page(PAGE0, CHGREG, pwr_cfg->chg.ichg_max);
884
885 /* Enable the CI charger */
886 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0003);
887
888 /* If not already started - start the overall charger timer T1 */
889 if (pwr_ctrl->time_begin_T1 == 0) {
890 pwr_start_timer(&pwr_ctrl->time_begin_T1);
891 ttw(ttr(TTrTimerLow,"T1 started(%d)" NL, 0));
892 }
893 ttw(ttr(TTrInitLow,"start_q401_charge" NL, 0xFF));
894
895 }
896
897 void start_q402_charge(void) {
898
899 ttw(ttr(TTrInitLow,"start_q402_charge(%d)" NL, 0x00));
900 if (pwr_ctrl->flag_mmi_registered == 1) {
901 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_START_IND;
902 mmi_send_msg(pwr_ctrl->mmi_ptr);
903 }
904
905 // Needed if we want Ichg measurements - else they are disabled!!
906 ABB_Write_Register_on_page(PAGE0, CHGREG, pwr_cfg->chg.ichg_max);
907 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0003);
908
909 pwr_modulate_init();
910
911 /* If not already started - start the overall charger timer T1 */
912 if (pwr_ctrl->time_begin_T1 == 0) {
913 pwr_start_timer(&pwr_ctrl->time_begin_T1);
914 ttw(ttr(TTrTimerLow,"T1 started(%d)" NL, 0));
915 }
916 ttw(ttr(TTrInitLow,"start_q402_charge(%d)" NL, 0xFF));
917
918 }
919
920 void stop_q401_charge(void) {
921
922 ttw(ttr(TTrInitLow,"stop_q401_charge(%d)" NL, 0x00));
923 if (pwr_ctrl->flag_mmi_registered == 1) {
924 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_STOP_IND;
925 mmi_send_msg(pwr_ctrl->mmi_ptr);
926 }
927 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
928 ttw(ttr(TTrInitLow,"stop_q401_charge(%d)" NL, 0xFF));
929
930 }
931
932 void stop_q402_charge(void) {
933
934 ttw(ttr(TTrInitLow,"stop_q402_charge(%d)" NL, 0x00));
935 if (pwr_ctrl->flag_mmi_registered == 1) {
936 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_STOP_IND;
937 mmi_send_msg(pwr_ctrl->mmi_ptr);
938 }
939 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
940
941 pwr_modulate_off();
942 ttw(ttr(TTrInitLow,"stop_q402_charge(%d)" NL, 0xFF));
943
944 }
945
946 void stop_pre_charge(void) {
947
948 ABB_Write_Register_on_page(PAGE0, BCICTL2, 0);
949
950 }
951
952 int check_chg_unplug() {
953 int i;
954
955 #if (USE_Q401_CHG_CIRCUIT == 1)
956 // Check that the latest values of charger status confirm that we have a charger unplug
957 // Search through the vector - charger is only assumed unplugged when ALL CONSECUTIVE_CHG_UNPLUGS elements are 0
958 // Returns 1 (TRUE) if the charger is assumed unplugged
959 // Returns 0 (FALSE) if the charger is assumed plugged
960 // Assume that the charger unplug was true if the battery voltage is sufficiently high
961 if (pwr_cfg->data.Vbat_avg_mV < VBAT_PRECHG_STOP) {
962 for (i=0;i<= CONSECUTIVE_CHG_UNPLUGS-1 ;i++) {
963 ttw(ttr(TTrTimerLow,"chg_unplug_vec(%d)" NL, pwr_ctrl->chg_unplug_vec[i]));
964 if (pwr_ctrl->chg_unplug_vec[i] != 0)
965 return 0;
966 }
967 }
968 return 1;
969 #endif
970 #if (USE_Q402_CHG_CIRCUIT == 1)
971 // Assume that the charger unplug was true if BOTH the charger voltage & charger current
972 // are below configurable Vchg & Ichg threshold values
973 if ((pwr_cfg->data.Vchg < VCHG_Q402_THR) && (pwr_cfg->data.Ichg < ICHG_Q402_THR)) {
974 ttw(ttr(TTrInitLow,"check_chg_unplug: Vchg=(%d)" NL, pwr_cfg->data.Vchg));
975 ttw(ttr(TTrInitLow,"check_chg_unplug: Ichg=(%d)" NL, pwr_cfg->data.Ichg));
976 return 1;
977 }
978 return 0;
979 #endif
980 }
981
982 void charger_unplug_house_keeping(void) {
983 // Flag the charger unplug
984 pwr_ctrl->flag_chg_plugged = 0;
985 pwr_ctrl->flag_chg_prev_plugged = 0;
986
987 // Read charger configuration next time charger is inserted
988 pwr_ctrl->flag_chg_cfg_read = 0;
989
990 // We must have more charger id measurements if the charger is re-connected
991 pwr_ctrl->count_chg_type = 0;
992
993 if (pwr_ctrl->flag_mmi_registered == 1) {
994 // Send charger unplug to the MMI
995 pwr_ctrl->mmi_ptr->header.msg_id = MMI_CHG_UNPLUG_IND;
996 mmi_send_msg(pwr_ctrl->mmi_ptr);
997
998 // Re-start the mmi info repetition timer
999 pwr_start_timer(&pwr_ctrl->time_begin_mmi_rep);
1000 }
1001
1002 // if T1 or T2 is running (which mean we have NOT had a normal charging stop)
1003 if ((pwr_ctrl->time_begin_T1 != 0) || (pwr_ctrl->time_begin_T2 != 0)) {
1004 // Start T3 timer if not already started
1005 if (pwr_ctrl->time_begin_T3 == 0) {
1006 pwr_start_timer(&pwr_ctrl->time_begin_T3);
1007 ttw(ttr(TTrTimerLow,"T3 started(%d)" NL, 0));
1008 }
1009 // Switch of charging circuit
1010
1011 #if (USE_Q401_CHG_CIRCUIT == 1)
1012 stop_q401_charge();
1013 #endif
1014 #if (USE_Q402_CHG_CIRCUIT == 1)
1015 stop_q402_charge();
1016 #endif
1017 }
1018 }
1019
1020 void cv_charging_house_keeping(void) {
1021 // Calculate k value
1022 // Start DC timer
1023 // Start T4 timer based on k value
1024 // Modulation ON
1025 ttw(ttr(TTrTimerLow,"Vbat_avg, chg_start_thr, chg_stop_thr (%d), (%d), (%d)" NL, pwr_cfg->data.Vbat_avg_mV, pwr_cfg->bat.chg_start_thr, pwr_cfg->bat.chg_stop_thr));
1026 if ((pwr_cfg->data.Vbat_avg_mV - pwr_cfg->bat.chg_start_thr) <= 0) {
1027 // Assign k to max value if Vbat_avg value is below start value
1028 pwr_cfg->data.k = PWR_MAX_K;
1029 } else {
1030 pwr_cfg->data.k = (255 * (pwr_cfg->bat.chg_stop_thr - pwr_cfg->data.Vbat_avg_mV) / (pwr_cfg->bat.chg_stop_thr - pwr_cfg->bat.chg_start_thr));
1031 if (pwr_cfg->data.k <= PWR_MIN_K)
1032 pwr_cfg->data.k = PWR_MIN_K;
1033 }
1034 pwr_start_timer(&pwr_ctrl->time_begin_T2);
1035 ttw(ttr(TTrTimerLow,"T2 started(%d)" NL, 0));
1036
1037 ttw(ttr(TTrTimerLow, "k=%d" NL, pwr_cfg->data.k));
1038 pwr_cfg->data.T4 = pwr_cfg->data.k * pwr_cfg->common.mod_cycle/255;
1039 ttw(ttr(TTrTimerLow,"T4 timer (%d)" NL, pwr_cfg->data.T4));
1040
1041 ttw(ttr(TTrTimerLow,"DC started(%d)" NL, 0));
1042 pwr_start_timer(&pwr_ctrl->time_begin_mod_cycle);
1043
1044 ttw(ttr(TTrTimerLow,"T4 started(%d)" NL, 0));
1045 pwr_start_timer(&pwr_ctrl->time_begin_T4);
1046
1047 pwr_modulate_on();
1048 }
1049
1050 void end_charging_house_keeping(void) {
1051 // Stop & reset timers
1052 pwr_stop_timers();
1053
1054 // Stop charging
1055 #if (USE_Q401_CHG_CIRCUIT == 1)
1056 stop_q401_charge();
1057 #endif
1058 #if (USE_Q402_CHG_CIRCUIT == 1)
1059 stop_q402_charge();
1060 #endif
1061
1062 // Start the mmi info repetition timer
1063 if (pwr_ctrl->flag_mmi_registered == 1)
1064 pwr_start_timer(&pwr_ctrl->time_begin_mmi_rep);
1065
1066 // Read charger configuration next time charger is inserted
1067 pwr_ctrl->flag_chg_cfg_read = 0;
1068 }
1069
1070 #if (TEST_PWR_MMI_INTERFACE == 1)
1071 // Callback function used for testing MMI reporting
1072 static void mmi_test_cb_function(void *ptr) {
1073 T_PWR_MMI_INFO_IND_EVENT *event;
1074
1075
1076 event = (T_PWR_MMI_INFO_IND_EVENT *)ptr;
1077
1078 ttw(ttr(TTrInit, "mmi_test_cb_function (%d)" NL, 0));
1079 ttw(ttr(TTrInit, "MMI event: (%d)" NL, event->header.msg_id));
1080 ttw(ttr(TTrInit, "mmi_test_cb_function (%d)" NL, 0xFF));
1081 }
1082 #endif