summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/config/sansaconnect.h10
-rw-r--r--firmware/powermgmt.c20
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c83
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h30
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c25
5 files changed, 153 insertions, 15 deletions
diff --git a/firmware/export/config/sansaconnect.h b/firmware/export/config/sansaconnect.h
index 5668d579fc..fa929f3c10 100644
--- a/firmware/export/config/sansaconnect.h
+++ b/firmware/export/config/sansaconnect.h
@@ -152,7 +152,15 @@
152#define BATTERY_CAPACITY_INC 100 /* capacity increment */ 152#define BATTERY_CAPACITY_INC 100 /* capacity increment */
153#define BATTERY_TYPES_COUNT 1 /* only one type */ 153#define BATTERY_TYPES_COUNT 1 /* only one type */
154 154
155#define CONFIG_BATTERY_MEASURE PERCENTAGE_MEASURE 155/* bq27000 provides voltage, percentage and time measure.
156 * Voltage reading is available every 2.56 seconds and does not need filtering.
157 * Read the measured voltage every 3 seconds so we are guaranteed to not read
158 * the same value twice (do not try to read every 2.56 seconds as clocks are
159 * not synchronized).
160 */
161#define CONFIG_BATTERY_MEASURE (VOLTAGE_MEASURE|PERCENTAGE_MEASURE|TIME_MEASURE)
162#define BATT_AVE_SAMPLES 1
163#define POWER_THREAD_STEP_TICKS (3*HZ)
156 164
157/* define current usage levels */ 165/* define current usage levels */
158#if 0 166#if 0
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index a05e0aeb68..51ea99f6fa 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -88,16 +88,12 @@ static long last_event_tick = 0;
88#if (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) == PERCENTAGE_MEASURE 88#if (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) == PERCENTAGE_MEASURE
89#ifdef SIMULATOR 89#ifdef SIMULATOR
90int _battery_level(void) { return -1; } 90int _battery_level(void) { return -1; }
91int _battery_voltage(void);
92extern const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11];
93extern const unsigned short percent_to_volt_charge[11];
94#else
95int _battery_voltage(void) { return -1; }
96const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11];
97const unsigned short percent_to_volt_charge[11];
98#endif 91#endif
99#elif (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) == VOLTAGE_MEASURE 92#else
100int _battery_level(void) { return -1; } 93int _battery_level(void) { return -1; }
94#endif
95
96#if (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) == VOLTAGE_MEASURE
101/* 97/*
102 * Average battery voltage and charger voltage, filtered via a digital 98 * Average battery voltage and charger voltage, filtered via a digital
103 * exponential filter (aka. exponential moving average, scaled): 99 * exponential filter (aka. exponential moving average, scaled):
@@ -106,10 +102,8 @@ int _battery_level(void) { return -1; }
106static unsigned int avgbat; 102static unsigned int avgbat;
107/* filtered battery voltage, millivolts */ 103/* filtered battery voltage, millivolts */
108static unsigned int battery_millivolts; 104static unsigned int battery_millivolts;
109#elif (CONFIG_BATTERY_MEASURE == 0) 105#else
110int _battery_voltage(void) { return -1; } 106int _battery_voltage(void) { return -1; }
111int _battery_level(void) { return -1; }
112
113const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11]; 107const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11];
114const unsigned short percent_to_volt_charge[11]; 108const unsigned short percent_to_volt_charge[11];
115#endif 109#endif
@@ -156,9 +150,9 @@ void battery_read_info(int *voltage, int *level)
156 *voltage = millivolts; 150 *voltage = millivolts;
157 151
158 if (level) { 152 if (level) {
159 percent = voltage_to_battery_level(millivolts); 153 percent = _battery_level();
160 if (percent < 0) 154 if (percent < 0)
161 percent = _battery_level(); 155 percent = voltage_to_battery_level(millivolts);
162 *level = percent; 156 *level = percent;
163 } 157 }
164} 158}
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
index 8ebba3a8d5..ed7dab1572 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
+++ b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
@@ -104,8 +104,15 @@
104#define SYS_CTRL_EN_TS_THERM 0x06 104#define SYS_CTRL_EN_TS_THERM 0x06
105#define SYS_CTRL_FRESET 0x80 105#define SYS_CTRL_FRESET 0x80
106 106
107/* HDQ status codes */
108#define HDQ_STATUS_OK 0x00
109#define HDQ_STATUS_NOT_READY 0x01
110#define HDQ_STATUS_TIMEOUT 0x02
111
107/* protects spi avr commands from concurrent access */ 112/* protects spi avr commands from concurrent access */
108static struct mutex avr_mtx; 113static struct mutex avr_mtx;
114/* serializes hdq read/write and status retrieval */
115static struct mutex hdq_mtx;
109 116
110/* AVR thread events */ 117/* AVR thread events */
111#define INPUT_INTERRUPT 1 118#define INPUT_INTERRUPT 1
@@ -498,6 +505,7 @@ void avr_hid_init(void)
498 IO_SERIAL1_MODE = 0x6DB; 505 IO_SERIAL1_MODE = 0x6DB;
499 506
500 mutex_init(&avr_mtx); 507 mutex_init(&avr_mtx);
508 mutex_init(&hdq_mtx);
501} 509}
502 510
503int _battery_level(void) 511int _battery_level(void)
@@ -510,6 +518,17 @@ int _battery_level(void)
510 return avr_battery_level & BATTERY_LEVEL_PERCENTAGE_MASK; 518 return avr_battery_level & BATTERY_LEVEL_PERCENTAGE_MASK;
511} 519}
512 520
521int _battery_voltage(void)
522{
523 return avr_hid_hdq_read_short(HDQ_REG_VOLT);
524}
525
526int _battery_time(void)
527{
528 /* HDQ_REG_TTE reads as 65535 when charging */
529 return avr_hid_hdq_read_short(HDQ_REG_TTE);
530}
531
513unsigned int power_input_status(void) 532unsigned int power_input_status(void)
514{ 533{
515 if (avr_battery_status & BATTERY_STATUS_CHARGER_CONNECTED) 534 if (avr_battery_status & BATTERY_STATUS_CHARGER_CONNECTED)
@@ -524,6 +543,70 @@ bool charging_state(void)
524 return (avr_battery_status & BATTERY_STATUS_CHARGING) != 0; 543 return (avr_battery_status & BATTERY_STATUS_CHARGING) != 0;
525} 544}
526 545
546static int avr_hid_hdq_read_byte_internal(uint8_t address)
547{
548 uint8_t result[2];
549
550 if (!avr_execute_command(CMD_HDQ_READ, &address, sizeof(address)))
551 {
552 return -1;
553 }
554
555 do
556 {
557 mdelay(10);
558 if (!avr_execute_command(CMD_HDQ_STATUS, result, sizeof(result)))
559 {
560 return -1;
561 }
562 }
563 while (result[0] == HDQ_STATUS_NOT_READY);
564
565 if (result[0] != HDQ_STATUS_OK)
566 {
567 logf("HDQ read %d status %d", address, result[0]);
568 return -1;
569 }
570
571 return result[1];
572}
573
574int avr_hid_hdq_read_byte(uint8_t address)
575{
576 int retry;
577 int value = -1;
578 for (retry = 0; (retry < 3) && (value < 0); retry++)
579 {
580 mutex_lock(&hdq_mtx);
581 value = avr_hid_hdq_read_byte_internal(address);
582 mutex_unlock(&hdq_mtx);
583 }
584 return value;
585}
586
587int avr_hid_hdq_read_short(uint8_t address)
588{
589 int old_hi = -1, old_lo = -1, hi = -2, lo = -2;
590 /* Keep reading until we read the same value twice.
591 * There's no atomic 16-bit value retrieval, so keep reading
592 * until we read the same value twice. HDQ registers update
593 * no more than once per 2.56 seconds so usually there will
594 * be 4 reads and sometimes 6 reads.
595 */
596 while ((old_hi != hi) || (old_lo != lo))
597 {
598 old_hi = hi;
599 old_lo = lo;
600 hi = avr_hid_hdq_read_byte(address + 1);
601 lo = avr_hid_hdq_read_byte(address);
602 }
603 if ((hi < 0) || (lo < 0))
604 {
605 return -1;
606 }
607 return (hi << 8) | lo;
608}
609
527static void avr_hid_enable_wheel(void) 610static void avr_hid_enable_wheel(void)
528{ 611{
529 uint8_t enable = 0x01; 612 uint8_t enable = 0x01;
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h
index baa7083760..ed23e84936 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h
+++ b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h
@@ -24,8 +24,38 @@
24 24
25#include "config.h" 25#include "config.h"
26 26
27/* HDQ (bq27000) RAM registers */
28#define HDQ_REG_CTRL 0x00
29#define HDQ_REG_MODE 0x01
30#define HDQ_REG_AR 0x02
31#define HDQ_REG_ARTTE 0x04
32#define HDQ_REG_TEMP 0x06
33#define HDQ_REG_VOLT 0x08
34#define HDQ_REG_FLAGS 0x0A
35#define HDQ_REG_RSOC 0x0B
36#define HDQ_REG_NAC 0x0C
37#define HDQ_REG_CACD 0x0E
38#define HDQ_REG_CACT 0x10
39#define HDQ_REG_LMD 0x12
40#define HDQ_REG_AI 0x14
41#define HDQ_REG_TTE 0x16
42#define HDQ_REG_TTF 0x18
43#define HDQ_REG_SI 0x1A
44#define HDQ_REG_STTE 0x1C
45#define HDQ_REG_MLI 0x1E
46#define HDQ_REG_MLTTE 0x20
47#define HDQ_REG_SAE 0x22
48#define HDQ_REG_AP 0x24
49#define HDQ_REG_TTECP 0x26
50#define HDQ_REG_CYCL 0x28
51#define HDQ_REG_CYCT 0x2A
52#define HDQ_REG_CSOC 0x2C
53
27void avr_hid_init(void); 54void avr_hid_init(void);
28 55
56int avr_hid_hdq_read_byte(uint8_t address);
57int avr_hid_hdq_read_short(uint8_t address);
58
29void avr_hid_enable_charger(void); 59void avr_hid_enable_charger(void);
30 60
31void avr_hid_wifi_pd(int high); 61void avr_hid_wifi_pd(int high);
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
index ccd91c6d2f..597fb6b7e0 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
+++ b/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
@@ -31,6 +31,29 @@
31#include "i2c-dm320.h" 31#include "i2c-dm320.h"
32#include "logf.h" 32#include "logf.h"
33 33
34
35const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
36{
37 3450
38};
39
40const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
41{
42 3400
43};
44
45/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
46const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
47{
48 { 3400, 3508, 3630, 3703, 3727, 3750, 3803, 3870, 3941, 4026, 4142 }
49};
50
51/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
52const unsigned short percent_to_volt_charge[11] =
53{
54 3540, 3788, 3860, 3890, 3916, 3956, 4016, 4085, 4164, 4180, 4190
55};
56
34/* (7-bit) address is 0x48, the LSB is read/write flag */ 57/* (7-bit) address is 0x48, the LSB is read/write flag */
35#define TPS65021_ADDR (0x48 << 1) 58#define TPS65021_ADDR (0x48 << 1)
36 59
@@ -54,7 +77,7 @@ void power_init(void)
54 77
55 /* PWM mode */ 78 /* PWM mode */
56 tps65021_write_reg(0x04, 0xB2); 79 tps65021_write_reg(0x04, 0xB2);
57 80
58 /* Set core voltage to 1.5V */ 81 /* Set core voltage to 1.5V */
59 tps65021_write_reg(0x06, 0x1C); 82 tps65021_write_reg(0x06, 0x1C);
60 83