diff options
| author | tmk <nobody@nowhere> | 2014-09-04 05:30:00 +0900 |
|---|---|---|
| committer | tmk <nobody@nowhere> | 2014-09-04 05:30:00 +0900 |
| commit | 02939ab1d831ab7bb02edb28cb0b21fb61bced56 (patch) | |
| tree | fe55ff730af3c2b4e13a4077725f965d651e3ad5 /keyboard/hhkb_rn42 | |
| parent | 807ed33a9a29ee3c5248226d0e865d0580d7eebc (diff) | |
| download | qmk_firmware-02939ab1d831ab7bb02edb28cb0b21fb61bced56.tar.gz qmk_firmware-02939ab1d831ab7bb02edb28cb0b21fb61bced56.zip | |
Add battery management
Diffstat (limited to 'keyboard/hhkb_rn42')
| -rw-r--r-- | keyboard/hhkb_rn42/rn42.mk | 1 | ||||
| -rw-r--r-- | keyboard/hhkb_rn42/rn42/battery.c | 119 | ||||
| -rw-r--r-- | keyboard/hhkb_rn42/rn42/battery.h | 34 | ||||
| -rw-r--r-- | keyboard/hhkb_rn42/rn42/rn42_task.c | 71 |
4 files changed, 165 insertions, 60 deletions
diff --git a/keyboard/hhkb_rn42/rn42.mk b/keyboard/hhkb_rn42/rn42.mk index 653a80924..fd6f7db1a 100644 --- a/keyboard/hhkb_rn42/rn42.mk +++ b/keyboard/hhkb_rn42/rn42.mk | |||
| @@ -4,6 +4,7 @@ SRC += serial_uart.c \ | |||
| 4 | rn42/suart.S \ | 4 | rn42/suart.S \ |
| 5 | rn42/rn42.c \ | 5 | rn42/rn42.c \ |
| 6 | rn42/rn42_task.c \ | 6 | rn42/rn42_task.c \ |
| 7 | rn42/battery.c \ | ||
| 7 | rn42/main.c | 8 | rn42/main.c |
| 8 | 9 | ||
| 9 | OPT_DEFS += -DPROTOCOL_RN42 | 10 | OPT_DEFS += -DPROTOCOL_RN42 |
diff --git a/keyboard/hhkb_rn42/rn42/battery.c b/keyboard/hhkb_rn42/rn42/battery.c new file mode 100644 index 000000000..32de86448 --- /dev/null +++ b/keyboard/hhkb_rn42/rn42/battery.c | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | #include <avr/io.h> | ||
| 2 | #include <util/delay.h> | ||
| 3 | #include "battery.h" | ||
| 4 | |||
| 5 | |||
| 6 | /* | ||
| 7 | * Battery | ||
| 8 | */ | ||
| 9 | void battery_init(void) | ||
| 10 | { | ||
| 11 | // blink | ||
| 12 | battery_led(LED_ON); _delay_ms(500); | ||
| 13 | battery_led(LED_OFF); _delay_ms(500); | ||
| 14 | battery_led(LED_ON); _delay_ms(500); | ||
| 15 | battery_led(LED_OFF); _delay_ms(500); | ||
| 16 | // LED indicates charger status | ||
| 17 | battery_led(LED_CHARGER); | ||
| 18 | |||
| 19 | // ADC setting for voltage monitor | ||
| 20 | // Ref:2.56V band-gap, Input:ADC0(PF0), Prescale:128(16MHz/128=125KHz) | ||
| 21 | ADMUX = (1<<REFS1) | (1<<REFS0); | ||
| 22 | ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); | ||
| 23 | ADCSRA |= (1<<ADEN); | ||
| 24 | } | ||
| 25 | |||
| 26 | // Indicator for battery | ||
| 27 | void battery_led(battery_led_t val) | ||
| 28 | { | ||
| 29 | if (val == LED_TOGGLE) { | ||
| 30 | // Toggle LED | ||
| 31 | DDRF |= (1<<5); | ||
| 32 | PINF |= (1<<5); | ||
| 33 | } else if (val == LED_ON) { | ||
| 34 | // On overriding charger status | ||
| 35 | DDRF |= (1<<5); | ||
| 36 | PORTF &= ~(1<<5); | ||
| 37 | } else if (val == LED_OFF) { | ||
| 38 | // Off overriding charger status | ||
| 39 | DDRF |= (1<<5); | ||
| 40 | PORTF |= (1<<5); | ||
| 41 | } else { | ||
| 42 | // Display charger status | ||
| 43 | DDRF &= ~(1<<5); | ||
| 44 | PORTF &= ~(1<<5); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | bool battery_charging(void) | ||
| 49 | { | ||
| 50 | if (!(USBSTA&(1<<VBUS))) return false; | ||
| 51 | |||
| 52 | // MCP73831:STAT | ||
| 53 | // HiZ: Shutdown/No Battery | ||
| 54 | // Low: Charging | ||
| 55 | // Hi: Charged | ||
| 56 | |||
| 57 | // preserve last register status | ||
| 58 | uint8_t ddrf_prev = DDRF; | ||
| 59 | uint8_t portf_prev = PORTF; | ||
| 60 | |||
| 61 | // Input with pullup | ||
| 62 | DDRF &= ~(1<<5); | ||
| 63 | PORTF |= (1<<5); | ||
| 64 | _delay_ms(1); | ||
| 65 | bool charging = PINF&(1<<5) ? false : true; | ||
| 66 | |||
| 67 | // restore last register status | ||
| 68 | DDRF = (DDRF&~(1<<5)) | (ddrf_prev&(1<<5)); | ||
| 69 | PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5)); | ||
| 70 | |||
| 71 | return charging; | ||
| 72 | } | ||
| 73 | |||
| 74 | // Returns voltage in mV | ||
| 75 | uint16_t battery_voltage(void) | ||
| 76 | { | ||
| 77 | volatile uint16_t bat; | ||
| 78 | //ADCSRA |= (1<<ADEN); | ||
| 79 | |||
| 80 | // discard first result | ||
| 81 | ADCSRA |= (1<<ADSC); | ||
| 82 | while (ADCSRA & (1<<ADSC)) ; | ||
| 83 | bat = ADC; | ||
| 84 | |||
| 85 | // discard second result | ||
| 86 | ADCSRA |= (1<<ADSC); | ||
| 87 | while (ADCSRA & (1<<ADSC)) ; | ||
| 88 | bat = ADC; | ||
| 89 | |||
| 90 | ADCSRA |= (1<<ADSC); | ||
| 91 | while (ADCSRA & (1<<ADSC)) ; | ||
| 92 | bat = ADC; | ||
| 93 | |||
| 94 | //ADCSRA &= ~(1<<ADEN); | ||
| 95 | |||
| 96 | return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION; | ||
| 97 | } | ||
| 98 | |||
| 99 | static bool low_voltage(void) { | ||
| 100 | static bool low = false; | ||
| 101 | uint16_t v = battery_voltage(); | ||
| 102 | if (v < BATTERY_VOLTAGE_LOW_LIMIT) { | ||
| 103 | low = true; | ||
| 104 | } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) { | ||
| 105 | low = false; | ||
| 106 | } | ||
| 107 | return low; | ||
| 108 | } | ||
| 109 | |||
| 110 | battery_status_t battery_status(void) | ||
| 111 | { | ||
| 112 | if (USBSTA&(1<<VBUS)) { | ||
| 113 | /* powered */ | ||
| 114 | return battery_charging() ? CHARGING : FULL_CHARGED; | ||
| 115 | } else { | ||
| 116 | /* not powered */ | ||
| 117 | return low_voltage() ? LOW_VOLTAGE : DISCHARGING; | ||
| 118 | } | ||
| 119 | } | ||
diff --git a/keyboard/hhkb_rn42/rn42/battery.h b/keyboard/hhkb_rn42/rn42/battery.h new file mode 100644 index 000000000..60fc8adfc --- /dev/null +++ b/keyboard/hhkb_rn42/rn42/battery.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef POWER_H | ||
| 2 | #define POWER_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | |||
| 7 | typedef enum { | ||
| 8 | FULL_CHARGED, | ||
| 9 | CHARGING, | ||
| 10 | DISCHARGING, | ||
| 11 | LOW_VOLTAGE, | ||
| 12 | } battery_status_t; | ||
| 13 | |||
| 14 | typedef enum { | ||
| 15 | LED_CHARGER = 0, | ||
| 16 | LED_ON, | ||
| 17 | LED_OFF, | ||
| 18 | LED_TOGGLE, | ||
| 19 | } battery_led_t; | ||
| 20 | |||
| 21 | /* Battery API */ | ||
| 22 | void battery_init(void); | ||
| 23 | void battery_led(battery_led_t val); | ||
| 24 | bool battery_charging(void); | ||
| 25 | uint16_t battery_voltage(void); | ||
| 26 | battery_status_t battery_status(void); | ||
| 27 | |||
| 28 | #define BATTERY_VOLTAGE_LOW_LIMIT 3500 | ||
| 29 | #define BATTERY_VOLTAGE_LOW_RECOVERY 3700 | ||
| 30 | // ADC offset:16, resolution:5mV | ||
| 31 | #define BATTERY_ADC_OFFSET 16 | ||
| 32 | #define BATTERY_ADC_RESOLUTION 5 | ||
| 33 | |||
| 34 | #endif | ||
diff --git a/keyboard/hhkb_rn42/rn42/rn42_task.c b/keyboard/hhkb_rn42/rn42/rn42_task.c index 2813b1c5f..07b34e111 100644 --- a/keyboard/hhkb_rn42/rn42/rn42_task.c +++ b/keyboard/hhkb_rn42/rn42/rn42_task.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "print.h" | 9 | #include "print.h" |
| 10 | #include "timer.h" | 10 | #include "timer.h" |
| 11 | #include "command.h" | 11 | #include "command.h" |
| 12 | #include "battery.h" | ||
| 12 | 13 | ||
| 13 | static bool config_mode = false; | 14 | static bool config_mode = false; |
| 14 | static bool force_usb = false; | 15 | static bool force_usb = false; |
| @@ -24,65 +25,9 @@ static void status_led(bool on) | |||
| 24 | } | 25 | } |
| 25 | } | 26 | } |
| 26 | 27 | ||
| 27 | static void battery_adc_init(void) | ||
| 28 | { | ||
| 29 | ADMUX = (1<<REFS1) | (1<<REFS0); // Ref:2.56V band-gap, Input:ADC0(PF0) | ||
| 30 | ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Prescale:128 16MHz/128=125KHz | ||
| 31 | ADCSRA |= (1<<ADEN); // enable ADC | ||
| 32 | } | ||
| 33 | |||
| 34 | static uint16_t battery_adc(void) | ||
| 35 | { | ||
| 36 | volatile uint16_t bat; | ||
| 37 | ADCSRA |= (1<<ADEN); | ||
| 38 | |||
| 39 | // discard first result | ||
| 40 | ADCSRA |= (1<<ADSC); | ||
| 41 | while (ADCSRA & (1<<ADSC)) ; | ||
| 42 | bat = ADC; | ||
| 43 | |||
| 44 | // discard second result | ||
| 45 | ADCSRA |= (1<<ADSC); | ||
| 46 | while (ADCSRA & (1<<ADSC)) ; | ||
| 47 | bat = ADC; | ||
| 48 | |||
| 49 | ADCSRA |= (1<<ADSC); | ||
| 50 | while (ADCSRA & (1<<ADSC)) ; | ||
| 51 | bat = ADC; | ||
| 52 | |||
| 53 | ADCSRA &= ~(1<<ADEN); | ||
| 54 | return bat; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void battery_led(bool on) | ||
| 58 | { | ||
| 59 | if (on) { | ||
| 60 | DDRF |= (1<<5); | ||
| 61 | PORTF &= ~(1<<5); // Low | ||
| 62 | } else { | ||
| 63 | DDRF &= ~(1<<5); | ||
| 64 | PORTF &= ~(1<<5); // HiZ | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | static bool battery_charging(void) | ||
| 69 | { | ||
| 70 | // MCP73831:STAT | ||
| 71 | // Hi-Z: Shutdown/No Battery | ||
| 72 | // Low: Charging | ||
| 73 | // Hi: Charged | ||
| 74 | DDRF &= ~(1<<5); | ||
| 75 | PORTF |= (1<<5); | ||
| 76 | return PINF&(1<<5) ? false : true; | ||
| 77 | } | ||
| 78 | |||
| 79 | void rn42_task_init(void) | 28 | void rn42_task_init(void) |
| 80 | { | 29 | { |
| 81 | battery_adc_init(); | 30 | battery_init(); |
| 82 | |||
| 83 | // battery charging(HiZ) | ||
| 84 | DDRF &= ~(1<<5); | ||
| 85 | PORTF &= ~(1<<5); | ||
| 86 | } | 31 | } |
| 87 | 32 | ||
| 88 | void rn42_task(void) | 33 | void rn42_task(void) |
| @@ -136,7 +81,12 @@ void rn42_task(void) | |||
| 136 | } | 81 | } |
| 137 | } | 82 | } |
| 138 | 83 | ||
| 139 | /* Battery monitor */ | 84 | /* Low voltage alert */ |
| 85 | if (battery_status() == LOW_VOLTAGE) { | ||
| 86 | battery_led(LED_ON); | ||
| 87 | } else { | ||
| 88 | battery_led(LED_CHARGER); | ||
| 89 | } | ||
| 140 | 90 | ||
| 141 | /* Connection monitor */ | 91 | /* Connection monitor */ |
| 142 | if (rn42_linked()) { | 92 | if (rn42_linked()) { |
| @@ -214,12 +164,13 @@ bool command_extra(uint8_t code) | |||
| 214 | xprintf("config_mode: %X\n", config_mode); | 164 | xprintf("config_mode: %X\n", config_mode); |
| 215 | xprintf("VBUS: %X\n", USBSTA&(1<<VBUS)); | 165 | xprintf("VBUS: %X\n", USBSTA&(1<<VBUS)); |
| 216 | xprintf("battery_charging: %X\n", battery_charging()); | 166 | xprintf("battery_charging: %X\n", battery_charging()); |
| 167 | xprintf("battery_status: %X\n", battery_status()); | ||
| 217 | return true; | 168 | return true; |
| 218 | case KC_B: | 169 | case KC_B: |
| 219 | // battery monitor | 170 | // battery monitor |
| 220 | t = timer_read32()/1000; | 171 | t = timer_read32()/1000; |
| 221 | b = battery_adc(); | 172 | b = battery_voltage(); |
| 222 | xprintf("BAT: %umV(%04X)\t", (b-16)*5, b); | 173 | xprintf("BAT: %umV\t", b); |
| 223 | xprintf("%02u:", t/3600); | 174 | xprintf("%02u:", t/3600); |
| 224 | xprintf("%02u:", t%3600/60); | 175 | xprintf("%02u:", t%3600/60); |
| 225 | xprintf("%02u\n", t%60); | 176 | xprintf("%02u\n", t%60); |
