summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-12-05 14:30:03 +0000
committerAidan MacDonald <amachronic@protonmail.com>2021-12-28 15:20:27 +0000
commit2d891439623bb76d38b98202ca5f3eea3c01c5f0 (patch)
tree50e52529843835d057bd07b4797545da2b0e4d9e /firmware/target
parentb774699560dc37db272d122cb140e73dd08b643b (diff)
downloadrockbox-2d891439623bb76d38b98202ca5f3eea3c01c5f0.tar.gz
rockbox-2d891439623bb76d38b98202ca5f3eea3c01c5f0.zip
AXP PMU rewrite (again)
I noticed a few mistakes in the old driver code and it was in need of an overhaul anyway... I decided to scale things back, simplify the code and remove most of the debug menus, netting a nice code size savings. One new feature is an advanced debug menu which is accessible by recompiling the code with AXP_EXTRA_DEBUG. It adds quite a bit of code size and isn't useful other than for development so it must be manually enabled by editing the source. Change-Id: I30e17c1194c14823decd726a574ed14451d4cb2d
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c10
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c60
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c8
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c59
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c8
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c49
6 files changed, 110 insertions, 84 deletions
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
index 1583db175a..64041795a3 100644
--- a/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
@@ -24,7 +24,7 @@
24#include "backlight.h" 24#include "backlight.h"
25#include "powermgmt.h" 25#include "powermgmt.h"
26#include "panic.h" 26#include "panic.h"
27#include "axp-pmu.h" 27#include "axp192.h"
28#include "gpio-x1000.h" 28#include "gpio-x1000.h"
29#include "irq-x1000.h" 29#include "irq-x1000.h"
30#include "i2c-x1000.h" 30#include "i2c-x1000.h"
@@ -89,7 +89,7 @@ static int hp_detect_tmo_cb(struct timeout* tmo)
89static void hp_detect_init(void) 89static void hp_detect_init(void)
90{ 90{
91 static struct timeout tmo; 91 static struct timeout tmo;
92 static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; 92 static const uint8_t gpio_reg = AXP_REG_GPIOLEVEL1;
93 static i2c_descriptor desc = { 93 static i2c_descriptor desc = {
94 .slave_addr = AXP_PMU_ADDR, 94 .slave_addr = AXP_PMU_ADDR,
95 .bus_cond = I2C_START | I2C_STOP, 95 .bus_cond = I2C_START | I2C_STOP,
@@ -105,11 +105,11 @@ static void hp_detect_init(void)
105 105
106 /* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1, 106 /* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1,
107 * set them to inputs. */ 107 * set them to inputs. */
108 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO0FUNCTION, 0x01); /* HP detect */ 108 axp_set_gpio_function(0, AXP_GPIO_INPUT); /* HP detect */
109 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); /* LO detect */ 109 axp_set_gpio_function(1, AXP_GPIO_INPUT); /* LO detect */
110 110
111 /* Get an initial reading before startup */ 111 /* Get an initial reading before startup */
112 int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); 112 int r = axp_read(gpio_reg);
113 if(r >= 0) 113 if(r >= 0)
114 { 114 {
115 hp_detect_reg = r; 115 hp_detect_reg = r;
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
index a1a4d2c2b2..17cdb4d645 100644
--- a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
@@ -28,7 +28,7 @@
28#ifdef HAVE_USB_CHARGING_ENABLE 28#ifdef HAVE_USB_CHARGING_ENABLE
29# include "usb_core.h" 29# include "usb_core.h"
30#endif 30#endif
31#include "axp-pmu.h" 31#include "axp192.h"
32#include "i2c-x1000.h" 32#include "i2c-x1000.h"
33 33
34const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = 34const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
@@ -56,27 +56,30 @@ const unsigned short percent_to_volt_charge[11] =
56 56
57void power_init(void) 57void power_init(void)
58{ 58{
59 /* Initialize driver */ 59 /* Configure I2C bus */
60 i2c_x1000_set_freq(2, I2C_FREQ_400K); 60 i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K);
61 axp_init(); 61
62 62 /* FIXME: Copy paste from M3K. Probably not necessary */
63 /* Set lowest sample rate */ 63 axp_modify(AXP_REG_DCDCMODE, 0, 0xc0);
64 axp_adc_set_rate(AXP_ADC_RATE_25HZ); 64
65 65 /* Power on required supplies */
66 /* Ensure battery voltage ADC is enabled */ 66 axp_set_enabled_supplies(
67 int bits = axp_adc_get_enabled(); 67 (1 << AXP_SUPPLY_EXTEN) |
68 bits |= (1 << ADC_BATTERY_VOLTAGE); 68 (1 << AXP_SUPPLY_DCDC1) |
69 axp_adc_set_enabled(bits); 69 (1 << AXP_SUPPLY_DCDC2) |
70 70 (1 << AXP_SUPPLY_DCDC3) |
71 /* Turn on all power outputs */ 71 (1 << AXP_SUPPLY_LDO2) |
72 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 72 (1 << AXP_SUPPLY_LDO3));
73 AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); 73
74 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 74 /* Enable required ADCs */
75 AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); 75 axp_set_enabled_adcs(
76 76 (1 << AXP_ADC_BATTERY_VOLTAGE) |
77 /* Set the default charging current. This is the same as the 77 (1 << AXP_ADC_CHARGE_CURRENT) |
78 * OF's setting, although it's not strictly within the USB spec. */ 78 (1 << AXP_ADC_DISCHARGE_CURRENT) |
79 axp_set_charge_current(780); 79 (1 << AXP_ADC_VBUS_VOLTAGE) |
80 (1 << AXP_ADC_VBUS_CURRENT) |
81 (1 << AXP_ADC_INTERNAL_TEMP) |
82 (1 << AXP_ADC_APS_VOLTAGE));
80 83
81 /* Delay to give power outputs time to stabilize. 84 /* Delay to give power outputs time to stabilize.
82 * With the power thread delay, this can apparently go as low as 50, 85 * With the power thread delay, this can apparently go as low as 50,
@@ -104,20 +107,25 @@ void power_off(void)
104 107
105bool charging_state(void) 108bool charging_state(void)
106{ 109{
107 return axp_battery_status() == AXP_BATT_CHARGING; 110 return axp_is_charging();
111}
112
113unsigned int power_input_status(void)
114{
115 return axp_power_input_status();
108} 116}
109 117
110int _battery_voltage(void) 118int _battery_voltage(void)
111{ 119{
112 return axp_adc_read(ADC_BATTERY_VOLTAGE); 120 return axp_read_adc(AXP_ADC_BATTERY_VOLTAGE);
113} 121}
114 122
115#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 123#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
116int _battery_current(void) 124int _battery_current(void)
117{ 125{
118 if(charging_state()) 126 if(charging_state())
119 return axp_adc_read(ADC_CHARGE_CURRENT); 127 return axp_read_adc(AXP_ADC_CHARGE_CURRENT);
120 else 128 else
121 return axp_adc_read(ADC_DISCHARGE_CURRENT); 129 return axp_read_adc(AXP_ADC_DISCHARGE_CURRENT);
122} 130}
123#endif 131#endif
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
index 24daf2ef69..0ef7bd2f64 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
@@ -24,7 +24,7 @@
24#include "backlight.h" 24#include "backlight.h"
25#include "powermgmt.h" 25#include "powermgmt.h"
26#include "panic.h" 26#include "panic.h"
27#include "axp-pmu.h" 27#include "axp192.h"
28#include "ft6x06.h" 28#include "ft6x06.h"
29#include "gpio-x1000.h" 29#include "gpio-x1000.h"
30#include "irq-x1000.h" 30#include "irq-x1000.h"
@@ -393,7 +393,7 @@ static int hp_detect_tmo_cb(struct timeout* tmo)
393static void hp_detect_init(void) 393static void hp_detect_init(void)
394{ 394{
395 static struct timeout tmo; 395 static struct timeout tmo;
396 static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; 396 static const uint8_t gpio_reg = AXP_REG_GPIOLEVEL1;
397 static i2c_descriptor desc = { 397 static i2c_descriptor desc = {
398 .slave_addr = AXP_PMU_ADDR, 398 .slave_addr = AXP_PMU_ADDR,
399 .bus_cond = I2C_START | I2C_STOP, 399 .bus_cond = I2C_START | I2C_STOP,
@@ -408,10 +408,10 @@ static void hp_detect_init(void)
408 }; 408 };
409 409
410 /* Headphone detect is wired to AXP192 GPIO: set it to input state */ 410 /* Headphone detect is wired to AXP192 GPIO: set it to input state */
411 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO2FUNCTION, 0x01); 411 axp_set_gpio_function(2, AXP_GPIO_INPUT);
412 412
413 /* Get an initial reading before startup */ 413 /* Get an initial reading before startup */
414 int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); 414 int r = axp_read(gpio_reg);
415 if(r >= 0) 415 if(r >= 0)
416 hp_detect_reg = r; 416 hp_detect_reg = r;
417 417
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
index 2d28ad0975..53451ffa6c 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
@@ -26,7 +26,7 @@
26#ifdef HAVE_USB_CHARGING_ENABLE 26#ifdef HAVE_USB_CHARGING_ENABLE
27# include "usb_core.h" 27# include "usb_core.h"
28#endif 28#endif
29#include "axp-pmu.h" 29#include "axp192.h"
30#include "i2c-x1000.h" 30#include "i2c-x1000.h"
31 31
32const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = 32const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
@@ -54,27 +54,29 @@ const unsigned short percent_to_volt_charge[11] =
54 54
55void power_init(void) 55void power_init(void)
56{ 56{
57 /* Initialize driver */ 57 /* Configure I2C bus */
58 i2c_x1000_set_freq(2, I2C_FREQ_400K); 58 i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K);
59 axp_init(); 59
60 60 /* Set DCDC1 and DCDC2 to fixed PWM mode to match OF settings. */
61 /* Set lowest sample rate */ 61 axp_modify(AXP_REG_DCDCMODE, 0, 0x0c);
62 axp_adc_set_rate(AXP_ADC_RATE_25HZ); 62
63 63 /* Power on required supplies */
64 /* Ensure battery voltage ADC is enabled */ 64 axp_set_enabled_supplies(
65 int bits = axp_adc_get_enabled(); 65 (1 << AXP_SUPPLY_DCDC1) | /* not sure (3.3 V) */
66 bits |= (1 << ADC_BATTERY_VOLTAGE); 66 (1 << AXP_SUPPLY_DCDC2) | /* not sure (1.4 V) */
67 axp_adc_set_enabled(bits); 67 (1 << AXP_SUPPLY_DCDC3) | /* for CPU (1.8 V) */
68 68 (1 << AXP_SUPPLY_LDO2) | /* LCD controller (3.3 V) */
69 /* Turn on all power outputs */ 69 (1 << AXP_SUPPLY_LDO3)); /* SD bus (3.3 V) */
70 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 70
71 AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); 71 /* Enable required ADCs */
72 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 72 axp_set_enabled_adcs(
73 AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); 73 (1 << AXP_ADC_BATTERY_VOLTAGE) |
74 74 (1 << AXP_ADC_CHARGE_CURRENT) |
75 /* Set the default charging current. This is the same as the 75 (1 << AXP_ADC_DISCHARGE_CURRENT) |
76 * OF's setting, although it's not strictly within the USB spec. */ 76 (1 << AXP_ADC_VBUS_VOLTAGE) |
77 axp_set_charge_current(780); 77 (1 << AXP_ADC_VBUS_CURRENT) |
78 (1 << AXP_ADC_INTERNAL_TEMP) |
79 (1 << AXP_ADC_APS_VOLTAGE));
78 80
79 /* Short delay to give power outputs time to stabilize */ 81 /* Short delay to give power outputs time to stabilize */
80 mdelay(200); 82 mdelay(200);
@@ -99,20 +101,25 @@ void power_off(void)
99 101
100bool charging_state(void) 102bool charging_state(void)
101{ 103{
102 return axp_battery_status() == AXP_BATT_CHARGING; 104 return axp_is_charging();
105}
106
107unsigned int power_input_status(void)
108{
109 return axp_power_input_status();
103} 110}
104 111
105int _battery_voltage(void) 112int _battery_voltage(void)
106{ 113{
107 return axp_adc_read(ADC_BATTERY_VOLTAGE); 114 return axp_read_adc(AXP_ADC_BATTERY_VOLTAGE);
108} 115}
109 116
110#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 117#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
111int _battery_current(void) 118int _battery_current(void)
112{ 119{
113 if(charging_state()) 120 if(charging_state())
114 return axp_adc_read(ADC_CHARGE_CURRENT); 121 return axp_read_adc(AXP_ADC_CHARGE_CURRENT);
115 else 122 else
116 return axp_adc_read(ADC_DISCHARGE_CURRENT); 123 return axp_read_adc(AXP_ADC_DISCHARGE_CURRENT);
117} 124}
118#endif 125#endif
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
index 13b0cdd078..1976dde793 100644
--- a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
@@ -23,7 +23,7 @@
23#include "button.h" 23#include "button.h"
24#include "touchscreen.h" 24#include "touchscreen.h"
25#include "ft6x06.h" 25#include "ft6x06.h"
26#include "axp-pmu.h" 26#include "axp192.h"
27#include "kernel.h" 27#include "kernel.h"
28#include "backlight.h" 28#include "backlight.h"
29#include "powermgmt.h" 29#include "powermgmt.h"
@@ -57,7 +57,7 @@ static void hp_detect_init(void)
57{ 57{
58 /* TODO: replace this copy paste cruft with an API in axp-pmu */ 58 /* TODO: replace this copy paste cruft with an API in axp-pmu */
59 static struct timeout tmo; 59 static struct timeout tmo;
60 static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; 60 static const uint8_t gpio_reg = AXP_REG_GPIOLEVEL1;
61 static i2c_descriptor desc = { 61 static i2c_descriptor desc = {
62 .slave_addr = AXP_PMU_ADDR, 62 .slave_addr = AXP_PMU_ADDR,
63 .bus_cond = I2C_START | I2C_STOP, 63 .bus_cond = I2C_START | I2C_STOP,
@@ -72,10 +72,10 @@ static void hp_detect_init(void)
72 }; 72 };
73 73
74 /* Headphone detect is wired to AXP192 GPIO: set it to input state */ 74 /* Headphone detect is wired to AXP192 GPIO: set it to input state */
75 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); 75 axp_set_gpio_function(1, AXP_GPIO_INPUT);
76 76
77 /* Get an initial reading before startup */ 77 /* Get an initial reading before startup */
78 int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); 78 int r = axp_read(gpio_reg);
79 if(r >= 0) 79 if(r >= 0)
80 hp_detect_reg = r; 80 hp_detect_reg = r;
81 81
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
index 75f8031dd9..65d1bc163f 100644
--- a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
@@ -22,7 +22,7 @@
22#include "power.h" 22#include "power.h"
23#include "adc.h" 23#include "adc.h"
24#include "system.h" 24#include "system.h"
25#include "axp-pmu.h" 25#include "axp192.h"
26#ifdef HAVE_CW2015 26#ifdef HAVE_CW2015
27# include "cw2015.h" 27# include "cw2015.h"
28#endif 28#endif
@@ -73,24 +73,30 @@ const unsigned short percent_to_volt_charge[11] =
73void power_init(void) 73void power_init(void)
74{ 74{
75 i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K); 75 i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K);
76 axp_init();
77#ifdef HAVE_CW2015 76#ifdef HAVE_CW2015
78 cw2015_init(); 77 cw2015_init();
79#endif 78#endif
80 79
81 /* Change supply voltage from the default of 1250 mV to 1200 mV, 80 /* Set DCDC2 to 1.2 V to match OF settings. */
82 * this matches the original firmware's settings. Didn't observe 81 axp_set_supply_voltage(AXP_SUPPLY_DCDC2, 1200);
83 * any obviously bad behavior at 1250 mV, but better to be safe. */ 82
84 axp_supply_set_voltage(AXP_SUPPLY_DCDC2, 1200); 83 /* Power on required supplies */
85 84 axp_set_enabled_supplies(
86 /* For now, just turn everything on... definitely the touchscreen 85 (1 << AXP_SUPPLY_DCDC1) | /* SD bus (3.3 V) */
87 * is powered by one of the outputs */ 86 (1 << AXP_SUPPLY_DCDC2) | /* LCD (1.2 V) */
88 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 87 (1 << AXP_SUPPLY_DCDC3) | /* CPU (1.8 V) */
89 AXP_REG_PWROUTPUTCTRL1, 0, 0x05, NULL); 88 (1 << AXP_SUPPLY_LDO2) | /* Touchscreen (3.3 V) */
90 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 89 (1 << AXP_SUPPLY_LDO3)); /* not sure (2.5 V) */
91 AXP_REG_PWROUTPUTCTRL2, 0, 0x0f, NULL); 90
92 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 91 /* Enable required ADCs */
93 AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); 92 axp_set_enabled_adcs(
93 (1 << AXP_ADC_BATTERY_VOLTAGE) |
94 (1 << AXP_ADC_CHARGE_CURRENT) |
95 (1 << AXP_ADC_DISCHARGE_CURRENT) |
96 (1 << AXP_ADC_VBUS_VOLTAGE) |
97 (1 << AXP_ADC_VBUS_CURRENT) |
98 (1 << AXP_ADC_INTERNAL_TEMP) |
99 (1 << AXP_ADC_APS_VOLTAGE));
94 100
95 /* Delay to give power output time to stabilize */ 101 /* Delay to give power output time to stabilize */
96 mdelay(20); 102 mdelay(20);
@@ -111,23 +117,28 @@ void power_off(void)
111 117
112bool charging_state(void) 118bool charging_state(void)
113{ 119{
114 return axp_battery_status() == AXP_BATT_CHARGING; 120 return axp_is_charging();
121}
122
123unsigned int power_input_status(void)
124{
125 return axp_power_input_status();
115} 126}
116 127
117int _battery_voltage(void) 128int _battery_voltage(void)
118{ 129{
119 /* CW2015 can also read battery voltage, but the AXP consistently 130 /* CW2015 can also read battery voltage, but the AXP consistently
120 * reads ~20-30 mV higher so I suspect it's the "real" voltage. */ 131 * reads ~20-30 mV higher so I suspect it's the "real" voltage. */
121 return axp_adc_read(ADC_BATTERY_VOLTAGE); 132 return axp_read_adc(AXP_ADC_BATTERY_VOLTAGE);
122} 133}
123 134
124#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 135#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
125int _battery_current(void) 136int _battery_current(void)
126{ 137{
127 if(charging_state()) 138 if(charging_state())
128 return axp_adc_read(ADC_CHARGE_CURRENT); 139 return axp_read_adc(AXP_ADC_CHARGE_CURRENT);
129 else 140 else
130 return axp_adc_read(ADC_DISCHARGE_CURRENT); 141 return axp_read_adc(AXP_ADC_DISCHARGE_CURRENT);
131} 142}
132#endif 143#endif
133 144