FreeCalypso > hg > ffs-editor
comparison src/cs/drivers/drv_app/lcc/lcc_handle_message.c @ 0:92470e5d0b9e
src: partial import from FC Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 15 May 2020 01:28:16 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92470e5d0b9e |
---|---|
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 |