diff options
Diffstat (limited to 'firmware/e300/battery/fpga.c')
-rw-r--r-- | firmware/e300/battery/fpga.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/firmware/e300/battery/fpga.c b/firmware/e300/battery/fpga.c new file mode 100644 index 000000000..20404e5a1 --- /dev/null +++ b/firmware/e300/battery/fpga.c @@ -0,0 +1,296 @@ +/* USRP E310 FPGA driver + * Copyright (C) 2014 Ettus Research + * This file is part of the USRP E310 Firmware + * The USRP E310 Firmware is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * The USRP E310 Firmware is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with the USRP E310 Firmware. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "eeprom.h" +#include "fpga.h" +#include "spi.h" +#include "mcu_settings.h" +#include "utils.h" +#include <util/delay.h> +#include <string.h> +#include <stdbool.h> + +typedef struct fpga_tx_mem_map0 { + uint16_t battery_voltage; + uint8_t battery_status; + uint8_t charger_status; + uint8_t unused[2]; + uint8_t version; + uint8_t type; +} fpga_tx_mem_map0_t; + +typedef struct fpga_tx_mem_map1 { + uint8_t status; + uint16_t voltage; + uint16_t temp; + uint16_t charge; + uint8_t type; +} fpga_tx_mem_map1_t; + +typedef struct fpga_tx_mem_map2 { + uint8_t unused[4]; + uint8_t settings; + uint16_t charge_last_full; + uint8_t type; +} fpga_tx_mem_map2_t; + +typedef struct fpga_rx_mem_map0 { + uint8_t unused[2]; + uint16_t value; + uint8_t reg; + uint8_t os_status; +} fpga_rx_mem_map0_t; + +typedef struct fpga_rx_mem_map1 { + uint8_t unused[3]; + uint16_t value; + uint8_t reg; +} fpga_rx_mem_map1_t; + +typedef struct fpga_rx_mem_map { + uint8_t valid; + union { + fpga_rx_mem_map0_t map0; + fpga_rx_mem_map1_t map1; + }; + uint8_t type; +} fpga_rx_mem_map_t; + +static bool shutdown = false; +static bool write_charge = false; +static bool write_settings = false; + +static volatile fpga_tx_mem_map0_t fpga_tx0; +static volatile fpga_tx_mem_map1_t fpga_tx1; +static volatile fpga_tx_mem_map2_t fpga_tx2; +static volatile fpga_rx_mem_map_t fpga_rx; + +/* battery status */ +static const uint8_t BATTERY_TEMP_ALERT_MASK = BIT(7) | BIT(6); +static const uint8_t BATTERY_TEMP_ALERT_SHIFT = 6; +static const uint8_t BATTERY_ONLINE_MASK = BIT(5); +static const uint8_t BATTERY_ONLINE_SHIFT = 5; +static const uint8_t BATTERY_HEALTH_MASK = BIT(4) | BIT(3) | BIT(2); +static const uint8_t BATTERY_HEALTH_SHIFT = 2; +static const uint8_t BATTERY_STATUS_MASK = BIT(1) | BIT(0); +static const uint8_t BATTERY_STATUS_SHIFT = 0; + +/* charger_status */ +static const uint8_t CHARGER_HEALTH_MASK = BIT(5) | BIT(4); +static const uint8_t CHARGER_HEALTH_SHIFT = 4; +static const uint8_t CHARGER_ONLINE_MASK = BIT(3); +static const uint8_t CHARGER_ONLINE_SHIFT = 3; +/* BIT(2) is unused */ +static const uint8_t CHARGER_CHARGE_TYPE_MASK = BIT(1) | BIT(0); +static const uint8_t CHARGER_CHARGE_TYPE_SHIFT = 0; + + +void fpga_set_battery_voltage(uint16_t voltage) +{ + fpga_tx0.battery_voltage = voltage; +} + +void fpga_set_battery_temp_alert(uint8_t alert) +{ + uint8_t status = fpga_tx0.battery_status; + + status &= ~BATTERY_TEMP_ALERT_MASK; + status |= alert << BATTERY_TEMP_ALERT_SHIFT; + + fpga_tx0.battery_status = status; +} + +void fpga_set_battery_online(bool online) +{ + uint8_t status = fpga_tx0.battery_status; + + status &= ~BATTERY_ONLINE_MASK; + status |= (online ? 1 : 0) << BATTERY_ONLINE_SHIFT; + + fpga_tx0.battery_status = status; +} + +void fpga_set_battery_health(uint8_t health) +{ + uint8_t status = fpga_tx0.battery_status; + + status &= ~BATTERY_HEALTH_MASK; + status |= health << BATTERY_HEALTH_SHIFT; + + fpga_tx0.battery_status = status; +} + +void fpga_set_battery_status(uint8_t st) +{ + uint8_t status = fpga_tx0.battery_status; + + status &= ~BATTERY_STATUS_MASK; + status |= st << BATTERY_STATUS_SHIFT; + + fpga_tx0.battery_status = status; +} + +void fpga_set_charger_health(uint8_t health) +{ + uint8_t status = fpga_tx0.charger_status; + + status &= ~CHARGER_HEALTH_MASK; + status |= health << CHARGER_HEALTH_SHIFT; + + fpga_tx0.charger_status = status; +} + +void fpga_set_charger_online(bool online) +{ + uint8_t status = fpga_tx0.charger_status; + + status &= ~CHARGER_ONLINE_MASK; + status |= (online ? 1 : 0) << CHARGER_ONLINE_SHIFT; + + fpga_tx0.charger_status = status; +} + +void fpga_set_charger_charge_type(uint8_t type) +{ + uint8_t status = fpga_tx0.charger_status; + + status &= ~CHARGER_CHARGE_TYPE_MASK; + status |= type << CHARGER_CHARGE_TYPE_SHIFT; + + fpga_tx0.charger_status = status; +} + +void fpga_set_gauge_charge(uint16_t charge) +{ + fpga_tx1.charge = charge; +} + +uint16_t fpga_get_gauge_charge(void) +{ + return fpga_tx1.charge; +} + +bool fpga_get_write_charge(void) +{ + bool ret = false; + + if (write_charge) { + ret = write_charge; + write_charge = false; + } + + return ret; +} + +uint8_t fpga_get_settings(void) +{ + return fpga_tx2.settings; +} + +bool fpga_get_write_settings(void) +{ + bool ret = false; + + if (write_settings) { + ret = write_settings; + write_settings = false; + } + + return ret; +} + +void fpga_set_gauge_charge_last_full(uint16_t charge) +{ + fpga_tx2.charge_last_full = charge; +} + +void fpga_set_gauge_temp(uint16_t temp) +{ + fpga_tx1.temp = temp; +} + +void fpga_set_gauge_voltage(uint16_t volt) +{ + fpga_tx1.voltage = volt; +} + +void fpga_set_gauge_status(uint8_t status) +{ + fpga_tx1.status = status; +} + +bool fpga_get_shutdown(void) +{ + return shutdown; +} + +void fpga_init(void) +{ + memset((void *) &fpga_tx0, 0, sizeof(fpga_tx0)); + memset((void *) &fpga_tx1, 0, sizeof(fpga_tx1)); + memset((void *) &fpga_tx2, 0, sizeof(fpga_tx2)); + fpga_tx0.type = 0; + fpga_tx0.version = VERSION_MAJ << 4 | VERSION_MIN; + + fpga_tx1.type = 1; + fpga_tx2.type = 2; + + /* get autoboot value from eeprom, keep TX reg on */ + fpga_tx2.settings = BIT(1) | eeprom_get_autoboot() ? 0x1 : 0x0; + + memset((void *) &fpga_rx, 0, sizeof(fpga_rx)); + + shutdown = false; +} + +void fpga_handle_write(uint8_t reg, uint16_t value) +{ + if (reg == 0x10) { + fpga_tx1.charge = value; + write_charge = true; + } else if (reg == 0x14) { + fpga_tx1.status = value; + } else if (reg == 0x1c) { + fpga_tx2.settings = (uint8_t) value; + write_settings = true; + } +} + +void fpga_sync(void) +{ + fpga_rx_mem_map_t rx; + + spi_transact_buf((uint8_t *) &fpga_tx0, (uint8_t *) &rx, 8); + if (rx.valid) { + if (rx.type == 0 && rx.map0.os_status == 0x7a) + shutdown = true; + else if (rx.type == 1) + fpga_handle_write(rx.map1.reg, rx.map1.value); + } + spi_transact_buf((uint8_t *) &fpga_tx1, (uint8_t *) &rx, 8); + if (rx.valid) { + if (rx.type == 0 && rx.map0.os_status == 0x7a) + shutdown = true; + else if (rx.type == 1) + fpga_handle_write(rx.map1.reg, rx.map1.value); + } + spi_transact_buf((uint8_t *) &fpga_tx2, (uint8_t *) &rx, 8); + if (rx.valid) { + if (rx.type == 0 && rx.map0.os_status == 0x7a) + shutdown = true; + else if (rx.type == 1) + fpga_handle_write(rx.map1.reg, rx.map1.value); + } +} |