| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include "os/mynewt.h" |
| #include <battery/battery.h> |
| #include <battery/battery_prop.h> |
| #include <battery/battery_drv.h> |
| #include <battery/battery_adc.h> |
| #include <adc/adc.h> |
| #include <hal/hal_gpio.h> |
| |
| /* Battery manager interface functions */ |
| |
| static int |
| battery_adc_property_get(struct battery_driver *driver, |
| struct battery_property *property, uint32_t timeout) |
| { |
| int rc = 0; |
| struct battery_adc *bat_adc = (struct battery_adc *)driver->bd_driver_data; |
| int val; |
| |
| /* Only one property is supported, voltage */ |
| if (property->bp_type == BATTERY_PROP_VOLTAGE_NOW && |
| property->bp_flags == 0) { |
| |
| /* Activate GPIO if it was configured */ |
| if (bat_adc->cfg.activation_pin_needed && |
| bat_adc->cfg.activation_pin != -1) { |
| hal_gpio_write(bat_adc->cfg.activation_pin, |
| bat_adc->cfg.activation_pin_level); |
| } |
| /* Blocking read of voltage */ |
| rc = adc_read_channel(bat_adc->adc_dev, bat_adc->cfg.channel, &val); |
| |
| /* Deactivate GPIO if it was configured */ |
| if (bat_adc->cfg.activation_pin_needed && |
| bat_adc->cfg.activation_pin != -1) { |
| hal_gpio_write(bat_adc->cfg.activation_pin, |
| bat_adc->cfg.activation_pin_level ? 0 : 1); |
| } |
| |
| if (rc == 0) { |
| property->bp_valid = 1; |
| /* Convert value to according to reference voltage and multiplier |
| * and divider if external resistor divider is used for measurement. |
| */ |
| property->bp_value.bpv_voltage = |
| adc_result_mv(bat_adc->adc_dev, bat_adc->cfg.channel, val) * |
| bat_adc->cfg.mul / bat_adc->cfg.div; |
| } |
| } else { |
| rc = -1; |
| assert(0); |
| } |
| |
| return rc; |
| } |
| |
| static int |
| battery_adc_property_set(struct battery_driver *driver, |
| struct battery_property *property) |
| { |
| int rc = -1; |
| |
| return rc; |
| } |
| |
| static int |
| battery_adc_enable(struct battery *battery) |
| { |
| return 0; |
| } |
| |
| static int |
| battery_adc_disable(struct battery *battery) |
| { |
| return 0; |
| } |
| |
| static const struct battery_driver_functions battery_adc_drv_funcs = { |
| .bdf_property_get = battery_adc_property_get, |
| .bdf_property_set = battery_adc_property_set, |
| |
| .bdf_enable = battery_adc_enable, |
| .bdf_disable = battery_adc_disable, |
| }; |
| |
| static const struct battery_driver_property battery_adc_properties[] = { |
| { BATTERY_PROP_VOLTAGE_NOW, 0, "VoltageADC" }, |
| { BATTERY_PROP_NONE }, |
| }; |
| |
| static int |
| battery_adc_open(struct os_dev *dev, uint32_t timeout, void *arg) |
| { |
| int rc = -1; |
| struct battery_adc *bat_adc = (struct battery_adc *)dev; |
| (void)arg; |
| |
| /* Open ADC with parameters specified in BSP */ |
| bat_adc->adc_dev = (struct adc_dev *)os_dev_open( |
| (char *)bat_adc->cfg.adc_dev_name, timeout, bat_adc->cfg.adc_open_arg); |
| if (bat_adc->adc_dev) { |
| /* Setup channel configuration to use for battery voltage */ |
| rc = adc_chan_config(bat_adc->adc_dev, bat_adc->cfg.channel, |
| bat_adc->cfg.adc_channel_cfg); |
| if (rc) { |
| return rc; |
| } |
| |
| /* Additional GPIO needed before measurement ? */ |
| if (bat_adc->cfg.activation_pin_needed && |
| bat_adc->cfg.activation_pin != -1) { |
| hal_gpio_init_out(bat_adc->cfg.activation_pin, |
| bat_adc->cfg.activation_pin_level ? 0 : 1); |
| } |
| rc = 0; |
| } |
| return rc; |
| } |
| |
| static int |
| battery_adc_close(struct os_dev *dev) |
| { |
| struct battery_adc *bat_adc = (struct battery_adc *)dev; |
| if (bat_adc->adc_dev) { |
| os_dev_close((struct os_dev *)&bat_adc->adc_dev); |
| bat_adc->adc_dev = NULL; |
| } |
| return 0; |
| } |
| |
| /* driver open implementation */ |
| int |
| battery_adc_init(struct os_dev *dev, void *arg) |
| { |
| struct battery_adc *bat_adc; |
| struct battery_adc_cfg *init_arg = (struct battery_adc_cfg *)arg; |
| |
| if (!dev || !arg) { |
| return SYS_ENODEV; |
| } |
| |
| OS_DEV_SETHANDLERS(dev, battery_adc_open, battery_adc_close); |
| |
| bat_adc = (struct battery_adc *)dev; |
| bat_adc->cfg = *((struct battery_adc_cfg *)arg); |
| bat_adc->dev.bd_funcs = &battery_adc_drv_funcs; |
| bat_adc->dev.bd_driver_data = bat_adc; |
| bat_adc->dev.bd_driver_properties = battery_adc_properties; |
| /* Divider and multiplier are set to 1 by default just make sure they |
| * are not set to 0 |
| */ |
| assert(bat_adc->cfg.div != 0); |
| assert(bat_adc->cfg.mul != 0); |
| /* Add driver to battery, this will update battery properties */ |
| battery_add_driver(init_arg->battery, &bat_adc->dev); |
| |
| return 0; |
| } |
| |