From 36451d2972ef4a59f93a7a0fb7539305cc44308a Mon Sep 17 00:00:00 2001 From: Daniel Agar Date: Tue, 4 Jun 2019 15:33:04 -0400 Subject: [PATCH] WIP: adc to WQ --- ROMFS/px4fmu_common/init.d/rc.sensors | 1 + boards/aerotenna/ocpoc/CMakeLists.txt | 2 +- .../aerotenna/ocpoc}/adc/CMakeLists.txt | 2 +- boards/aerotenna/ocpoc/adc/adc.cpp | 207 +++++++ .../aerotenna/ocpoc/ocpoc_adc/ocpoc_adc.cpp | 248 -------- boards/airmind/mindpx-v2/default.cmake | 4 +- boards/airmind/mindpx-v2/src/board_config.h | 2 - boards/auav/x21/default.cmake | 4 +- boards/auav/x21/src/board_config.h | 1 - boards/av/x-v1/default.cmake | 3 +- boards/beaglebone/blue/CMakeLists.txt | 2 +- .../blue/adc}/CMakeLists.txt | 8 +- boards/beaglebone/blue/adc/adc.cpp | 210 +++++++ .../beaglebone/blue/bbblue_adc/CMakeLists.txt | 51 -- .../beaglebone/blue/bbblue_adc/bbblue_adc.cpp | 251 -------- boards/beaglebone/blue/cross.cmake | 2 + boards/beaglebone/blue/native.cmake | 2 + boards/bitcraze/crazyflie/src/board_config.h | 7 - boards/emlid/navio2/CMakeLists.txt | 2 +- .../navio2/{navio_adc => adc}/CMakeLists.txt | 12 +- boards/emlid/navio2/adc/adc.cpp | 311 ++++++++++ boards/emlid/navio2/cross.cmake | 2 + boards/emlid/navio2/native.cmake | 2 + boards/emlid/navio2/navio_adc/navio_adc.cpp | 335 ---------- boards/holybro/kakutef7/default.cmake | 4 +- boards/intel/aerofc-v1/CMakeLists.txt | 3 +- .../{aerofc_adc => adc}/CMakeLists.txt | 11 +- boards/intel/aerofc-v1/adc/adc.cpp | 274 ++++++++ .../intel/aerofc-v1/aerofc_adc/aerofc_adc.cpp | 319 ---------- boards/intel/aerofc-v1/src/board_config.h | 8 - boards/nxp/fmuk66-v3/default.cmake | 4 +- boards/nxp/fmuk66-v3/src/board_config.h | 2 - boards/omnibus/f4sd/default.cmake | 5 +- boards/px4/fmu-v2/default.cmake | 4 +- boards/px4/fmu-v2/fixedwing.cmake | 4 +- boards/px4/fmu-v2/lpe.cmake | 4 +- boards/px4/fmu-v2/multicopter.cmake | 4 +- boards/px4/fmu-v2/rover.cmake | 4 +- boards/px4/fmu-v2/test.cmake | 4 +- boards/px4/fmu-v3/default.cmake | 4 +- boards/px4/fmu-v3/rtps.cmake | 4 +- boards/px4/fmu-v3/stackcheck.cmake | 4 +- boards/px4/fmu-v4/default.cmake | 4 +- boards/px4/fmu-v4/rtps.cmake | 4 +- boards/px4/fmu-v4/src/board_config.h | 2 - boards/px4/fmu-v4/stackcheck.cmake | 4 +- boards/px4/fmu-v4pro/default.cmake | 4 +- boards/px4/fmu-v4pro/rtps.cmake | 4 +- boards/px4/fmu-v5/default.cmake | 4 +- boards/px4/fmu-v5/fixedwing.cmake | 4 +- boards/px4/fmu-v5/multicopter.cmake | 4 +- boards/px4/fmu-v5/rover.cmake | 4 +- boards/px4/fmu-v5/rtps.cmake | 4 +- boards/px4/fmu-v5/stackcheck.cmake | 4 +- boards/px4/fmu-v5x/default.cmake | 4 +- boards/px4/fmu-v5x/fixedwing.cmake | 4 +- boards/px4/fmu-v5x/multicopter.cmake | 4 +- boards/px4/fmu-v5x/rover.cmake | 4 +- boards/px4/fmu-v5x/rtps.cmake | 4 +- boards/px4/fmu-v5x/stackcheck.cmake | 4 +- boards/px4/raspberrypi/cross.cmake | 1 + boards/px4/raspberrypi/native.cmake | 1 + boards/px4/sitl/default.cmake | 2 +- boards/px4/sitl/rtps.cmake | 2 +- boards/px4/sitl/test.cmake | 2 +- msg/adc_report.msg | 7 +- msg/system_power.msg | 29 +- src/drivers/adc/ADC.cpp | 203 ++++++ src/drivers/{drv_adc.h => adc/ADC.hpp} | 68 +- src/drivers/adc/CMakeLists.txt | 43 ++ src/drivers/boards/common/board_common.h | 35 ++ .../boards/common/board_internal_common.h | 37 +- .../boards/common/kinetis/CMakeLists.txt | 1 + .../boards/common/kinetis/board_adc.cpp | 185 ++++++ .../boards/common/stm32/CMakeLists.txt | 7 +- src/drivers/boards/common/stm32/board_adc.cpp | 195 ++++++ .../boards/common/stm32/board_hw_rev_ver.c | 5 +- src/drivers/kinetis/CMakeLists.txt | 6 +- src/drivers/kinetis/adc/adc.cpp | 520 ---------------- src/drivers/kinetis/tone_alarm/CMakeLists.txt | 3 +- src/drivers/rc_input/RCInput.cpp | 6 +- src/drivers/rc_input/RCInput.hpp | 1 + src/drivers/{stm32/adc => sim}/CMakeLists.txt | 7 +- src/drivers/sim/tone_alarm/CMakeLists.txt | 3 +- src/drivers/stm32/CMakeLists.txt | 6 +- src/drivers/stm32/adc/adc.cpp | 586 ------------------ src/drivers/stm32/tone_alarm/CMakeLists.txt | 3 +- .../tone_alarm/ToneAlarmInterfacePWM.cpp | 4 + src/drivers/system_power/CMakeLists.txt | 41 ++ src/drivers/system_power/SystemPower.cpp | 225 +++++++ .../system_power/SystemPower.hpp} | 78 +-- src/modules/sensors/sensors.cpp | 213 +++---- src/systemcmds/tests/CMakeLists.txt | 2 - src/systemcmds/tests/test_jig_voltages.c | 133 ---- src/systemcmds/tests/tests_main.c | 2 - src/systemcmds/tests/tests_main.h | 2 - 96 files changed, 2244 insertions(+), 2827 deletions(-) rename {src/drivers/kinetis => boards/aerotenna/ocpoc}/adc/CMakeLists.txt (95%) create mode 100644 boards/aerotenna/ocpoc/adc/adc.cpp delete mode 100644 boards/aerotenna/ocpoc/ocpoc_adc/ocpoc_adc.cpp rename boards/{aerotenna/ocpoc/ocpoc_adc => beaglebone/blue/adc}/CMakeLists.txt (93%) create mode 100644 boards/beaglebone/blue/adc/adc.cpp delete mode 100644 boards/beaglebone/blue/bbblue_adc/CMakeLists.txt delete mode 100644 boards/beaglebone/blue/bbblue_adc/bbblue_adc.cpp rename boards/emlid/navio2/{navio_adc => adc}/CMakeLists.txt (91%) create mode 100644 boards/emlid/navio2/adc/adc.cpp delete mode 100644 boards/emlid/navio2/navio_adc/navio_adc.cpp rename boards/intel/aerofc-v1/{aerofc_adc => adc}/CMakeLists.txt (92%) create mode 100644 boards/intel/aerofc-v1/adc/adc.cpp delete mode 100644 boards/intel/aerofc-v1/aerofc_adc/aerofc_adc.cpp create mode 100644 src/drivers/adc/ADC.cpp rename src/drivers/{drv_adc.h => adc/ADC.hpp} (57%) create mode 100644 src/drivers/adc/CMakeLists.txt create mode 100644 src/drivers/boards/common/kinetis/board_adc.cpp create mode 100644 src/drivers/boards/common/stm32/board_adc.cpp delete mode 100644 src/drivers/kinetis/adc/adc.cpp rename src/drivers/{stm32/adc => sim}/CMakeLists.txt (96%) delete mode 100644 src/drivers/stm32/adc/adc.cpp create mode 100644 src/drivers/system_power/CMakeLists.txt create mode 100644 src/drivers/system_power/SystemPower.cpp rename src/{systemcmds/tests/test_adc.c => drivers/system_power/SystemPower.hpp} (60%) delete mode 100644 src/systemcmds/tests/test_jig_voltages.c diff --git a/ROMFS/px4fmu_common/init.d/rc.sensors b/ROMFS/px4fmu_common/init.d/rc.sensors index 208175a3d45a..f394963d7f60 100644 --- a/ROMFS/px4fmu_common/init.d/rc.sensors +++ b/ROMFS/px4fmu_common/init.d/rc.sensors @@ -22,6 +22,7 @@ then ms5611 -T 0 -s start adc start + system_power start fi ############################################################################### diff --git a/boards/aerotenna/ocpoc/CMakeLists.txt b/boards/aerotenna/ocpoc/CMakeLists.txt index eba25ee15bc9..17779b08cd1e 100644 --- a/boards/aerotenna/ocpoc/CMakeLists.txt +++ b/boards/aerotenna/ocpoc/CMakeLists.txt @@ -31,4 +31,4 @@ # ############################################################################ -add_subdirectory(ocpoc_adc) +add_subdirectory(adc) diff --git a/src/drivers/kinetis/adc/CMakeLists.txt b/boards/aerotenna/ocpoc/adc/CMakeLists.txt similarity index 95% rename from src/drivers/kinetis/adc/CMakeLists.txt rename to boards/aerotenna/ocpoc/adc/CMakeLists.txt index bf0eca22c49f..055a8bb59a3b 100644 --- a/src/drivers/kinetis/adc/CMakeLists.txt +++ b/boards/aerotenna/ocpoc/adc/CMakeLists.txt @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (c) 2016 PX4 Development Team. All rights reserved. +# Copyright (c) 2015-2019 PX4 Development Team. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions diff --git a/boards/aerotenna/ocpoc/adc/adc.cpp b/boards/aerotenna/ocpoc/adc/adc.cpp new file mode 100644 index 000000000000..ef566c8abfb1 --- /dev/null +++ b/boards/aerotenna/ocpoc/adc/adc.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file adc.cpp + * + * OcPoC ADC Driver + * + * @author Lianying Ji + * @author Dave Royer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADC_VOLTAGE_PATH "/sys/bus/iio/devices/iio:device0/in_voltage8_raw" + +using namespace time_literals; + +class ADC : public ModuleBase, public px4::ScheduledWorkItem +{ +public: + ADC(); + ~ADC(); + + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); + + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::print_status() */ + int print_status() override; + + int start(); + int stop(); + +private: + void Run() override; + + void update_adc_report(const hrt_abstime &now); + + static constexpr uint32_t TICKRATE{10_ms}; /**< 100Hz base rate */ + + perf_counter_t _sample_perf; + adc_report_s _samples{}; /**< sample buffer */ + + uORB::Publication _adc_report_pub{ORB_ID(adc_report)}; +}; + +ADC::ADC() : + ScheduledWorkItem(px4::wq_configurations::hp_default), + _sample_perf(perf_alloc(PC_ELAPSED, "adc_sample")) +{ + for (int i = 0; i < adc_report_s::MAX_CHANNELS; i++) { + _samples.channel_id[i] = -1; + } +} + +ADC::~ADC() +{ + ScheduleClear(); + perf_free(_sample_perf); +} + +int +ADC::start() +{ + /* and schedule regular updates */ + ScheduleOnInterval(TICKRATE); + return PX4_OK; +} + +void +ADC::Run() +{ + uint32_t buff[1] {}; + FILE *xadc_fd = fopen(ADC_VOLTAGE_PATH, "r"); + + if (xadc_fd != NULL) { + int ret = fscanf(xadc_fd, "%d", buff); + + if (ret < 0) { + // do something + } + + fclose(xadc_fd); + + _samples.channel_id[0] = ADC_BATTERY_VOLTAGE_CHANNEL; + _samples.channel_value[0] = buff[0]; + + _samples.timestamp = hrt_absolute_time(); + _adc_report_pub.publish(_samples); + } +} + +int +ADC::print_status() +{ + PX4_INFO("Running"); + + perf_print_counter(_sample_perf); + + return 0; +} + +int +ADC::custom_command(int argc, char *argv[]) +{ + return print_usage("unknown command"); +} + +int +ADC::task_spawn(int argc, char *argv[]) +{ + ADC *instance = new ADC(ADC_CHANNELS); + + if (instance) { + _object.store(instance); + _task_id = task_id_is_work_queue; + + if (instance->start() == PX4_OK) { + return PX4_OK; + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + _object.store(nullptr); + _task_id = -1; + + return PX4_ERROR; +} + +int +ADC::print_usage(const char *reason) +{ + if (reason) { + PX4_WARN("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +ADC driver. +)DESCR_STR"); + + PRINT_MODULE_USAGE_COMMAND("start"); + + PRINT_MODULE_USAGE_NAME("adc", "driver"); + + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; +} + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int adc_main(int argc, char *argv[]); + +int adc_main(int argc, char *argv[]) +{ + return ADC::main(argc, argv); +} diff --git a/boards/aerotenna/ocpoc/ocpoc_adc/ocpoc_adc.cpp b/boards/aerotenna/ocpoc/ocpoc_adc/ocpoc_adc.cpp deleted file mode 100644 index 9c759c9b2a32..000000000000 --- a/boards/aerotenna/ocpoc/ocpoc_adc/ocpoc_adc.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012-2017 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file ocpoc_adc.cpp - * - * OcPoC ADC Driver - * - * @author Lianying Ji - * @author Dave Royer - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#define ADC_BASE_DEV_PATH "/dev/adc" -#define ADC_VOLTAGE_PATH "/sys/bus/iio/devices/iio:device0/in_voltage8_raw" - -__BEGIN_DECLS -__EXPORT int ocpoc_adc_main(int argc, char *argv[]); -__END_DECLS - -class OcpocADC: public DriverFramework::VirtDevObj -{ -public: - OcpocADC(); - virtual ~OcpocADC(); - - virtual int init(); - - virtual ssize_t devRead(void *buf, size_t count) override; - virtual int devIOCTL(unsigned long request, unsigned long arg) override; - -protected: - virtual void _measure() override; - -private: - int read(px4_adc_msg_t(*buf)[PX4_MAX_ADC_CHANNELS], unsigned int len); - - pthread_mutex_t _samples_lock; - px4_adc_msg_t _samples; -}; - -OcpocADC::OcpocADC() - : DriverFramework::VirtDevObj("ocpoc_adc", ADC0_DEVICE_PATH, ADC_BASE_DEV_PATH, 1e6 / 100) -{ - pthread_mutex_init(&_samples_lock, NULL); -} - -OcpocADC::~OcpocADC() -{ - pthread_mutex_destroy(&_samples_lock); -} - -void OcpocADC::_measure() -{ - px4_adc_msg_t tmp_samples[PX4_MAX_ADC_CHANNELS]; - - int ret = read(&tmp_samples, sizeof(tmp_samples)); - - if (ret != 0) { - PX4_ERR("ocpoc_adc_read: %d", ret); - } - - pthread_mutex_lock(&_samples_lock); - memcpy(&_samples, &tmp_samples, sizeof(tmp_samples)); - pthread_mutex_unlock(&_samples_lock); -} - -int OcpocADC::init() -{ - int ret; - - ret = DriverFramework::VirtDevObj::init(); - - if (ret != PX4_OK) { - PX4_ERR("init failed"); - return ret; - } - - return PX4_OK; -} - -int OcpocADC::devIOCTL(unsigned long request, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t OcpocADC::devRead(void *buf, size_t count) -{ - const size_t maxsize = sizeof(_samples); - int ret; - - if (count > maxsize) { - count = maxsize; - } - - ret = pthread_mutex_trylock(&_samples_lock); - - if (ret != 0) { - return 0; - } - - memcpy(buf, &_samples, count); - pthread_mutex_unlock(&_samples_lock); - - return count; -} - -int OcpocADC::read(px4_adc_msg_t(*buf)[PX4_MAX_ADC_CHANNELS], unsigned int len) -{ - uint32_t buff[1]; - int ret = 0; - - FILE *xadc_fd = fopen(ADC_VOLTAGE_PATH, "r"); - - if (xadc_fd != NULL) { - int ret_tmp = fscanf(xadc_fd, "%d", buff); - - if (ret_tmp < 0) { - ret = ret_tmp; - } - - fclose(xadc_fd); - - (*buf)[0].am_data = buff[0]; - - } else { - (*buf)[0].am_data = 0; - ret = -1; - } - - (*buf)[0].am_channel = ADC_BATTERY_VOLTAGE_CHANNEL; - - return ret; -} - -static OcpocADC *instance = nullptr; - -int ocpoc_adc_main(int argc, char *argv[]) -{ - int ret; - - if (argc < 2) { - PX4_WARN("usage: {start|stop|test}"); - return PX4_ERROR; - } - - if (!strcmp(argv[1], "start")) { - if (instance) { - PX4_WARN("already started"); - return PX4_OK; - } - - instance = new OcpocADC; - - if (!instance) { - PX4_WARN("not enough memory"); - return PX4_ERROR; - } - - if (instance->init() != PX4_OK) { - delete instance; - instance = nullptr; - PX4_WARN("init failed"); - return PX4_ERROR; - } - - return PX4_OK; - - } else if (!strcmp(argv[1], "stop")) { - if (!instance) { - PX4_WARN("already stopped"); - return PX4_OK; - } - - delete instance; - instance = nullptr; - return PX4_OK; - - } else if (!strcmp(argv[1], "test")) { - if (!instance) { - PX4_ERR("start first"); - return PX4_ERROR; - } - - px4_adc_msg_t adc_msgs[PX4_MAX_ADC_CHANNELS]; - - ret = instance->devRead((char *)&adc_msgs, sizeof(adc_msgs)); - - if (ret < 0) { - PX4_ERR("ret: %s (%d)\n", strerror(ret), ret); - return ret; - - } else { - PX4_INFO("ADC Data: %d", adc_msgs[0].am_data); - } - - return PX4_OK; - - } else { - PX4_WARN("action (%s) not supported", argv[1]); - - return PX4_ERROR; - } - - return PX4_OK; - -} diff --git a/boards/airmind/mindpx-v2/default.cmake b/boards/airmind/mindpx-v2/default.cmake index c35ff05a2725..61970e140c34 100644 --- a/boards/airmind/mindpx-v2/default.cmake +++ b/boards/airmind/mindpx-v2/default.cmake @@ -15,6 +15,7 @@ px4_add_board( TEL2:/dev/ttyS2 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_trigger @@ -41,8 +42,7 @@ px4_add_board( px4fmu rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/airmind/mindpx-v2/src/board_config.h b/boards/airmind/mindpx-v2/src/board_config.h index c02d24ca93b1..4d32de9e4945 100644 --- a/boards/airmind/mindpx-v2/src/board_config.h +++ b/boards/airmind/mindpx-v2/src/board_config.h @@ -300,8 +300,6 @@ #define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_OTGFS_VBUS)) #define BOARD_ADC_BRICK_VALID (1) #define BOARD_ADC_SERVO_VALID (1) -#define BOARD_ADC_PERIPH_5V_OC (0) -#define BOARD_ADC_HIPOWER_5V_OC (0) #define BOARD_HAS_PWM DIRECT_PWM_OUTPUT_CHANNELS diff --git a/boards/auav/x21/default.cmake b/boards/auav/x21/default.cmake index 30aa0e77a6db..89a0f5e4a640 100644 --- a/boards/auav/x21/default.cmake +++ b/boards/auav/x21/default.cmake @@ -16,6 +16,7 @@ px4_add_board( TEL2:/dev/ttyS2 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -47,8 +48,7 @@ px4_add_board( px4io roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/auav/x21/src/board_config.h b/boards/auav/x21/src/board_config.h index f0deaf03f726..427f7b27069d 100644 --- a/boards/auav/x21/src/board_config.h +++ b/boards/auav/x21/src/board_config.h @@ -211,7 +211,6 @@ #define BOARD_ADC_BRICK_VALID (!px4_arch_gpioread(GPIO_VDD_BRICK_VALID)) #define BOARD_ADC_SERVO_VALID (1) #define BOARD_ADC_PERIPH_5V_OC (!px4_arch_gpioread(GPIO_VDD_5V_PERIPH_OC)) -#define BOARD_ADC_HIPOWER_5V_OC (0) #define BOARD_HAS_PWM DIRECT_PWM_OUTPUT_CHANNELS diff --git a/boards/av/x-v1/default.cmake b/boards/av/x-v1/default.cmake index c6b9177d85bc..f841524c581f 100644 --- a/boards/av/x-v1/default.cmake +++ b/boards/av/x-v1/default.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -48,7 +49,7 @@ px4_add_board( rc_input #roboclaw stm32 - stm32/adc + system_power #stm32/tone_alarm tap_esc telemetry # all available telemetry drivers diff --git a/boards/beaglebone/blue/CMakeLists.txt b/boards/beaglebone/blue/CMakeLists.txt index 479f6d55c40f..bf663b2cc00c 100644 --- a/boards/beaglebone/blue/CMakeLists.txt +++ b/boards/beaglebone/blue/CMakeLists.txt @@ -31,7 +31,7 @@ # ############################################################################ -add_subdirectory(bbblue_adc) +add_subdirectory(adc) ############################################################################ diff --git a/boards/aerotenna/ocpoc/ocpoc_adc/CMakeLists.txt b/boards/beaglebone/blue/adc/CMakeLists.txt similarity index 93% rename from boards/aerotenna/ocpoc/ocpoc_adc/CMakeLists.txt rename to boards/beaglebone/blue/adc/CMakeLists.txt index 88d3bb8edb03..3148232885af 100644 --- a/boards/aerotenna/ocpoc/ocpoc_adc/CMakeLists.txt +++ b/boards/beaglebone/blue/adc/CMakeLists.txt @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (c) 2015-2017 PX4 Development Team. All rights reserved. +# Copyright (c) 2018-2019 PX4 Development Team. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ ############################################################################ px4_add_module( - MODULE drivers__ocpoc_adc - MAIN ocpoc_adc + MODULE drivers__adc + MAIN adc SRCS - ocpoc_adc.cpp + adc.cpp ) diff --git a/boards/beaglebone/blue/adc/adc.cpp b/boards/beaglebone/blue/adc/adc.cpp new file mode 100644 index 000000000000..14a331c4c23e --- /dev/null +++ b/boards/beaglebone/blue/adc/adc.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file bbblue_adc.cpp + * + * BBBlue ADC Driver + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __DF_BBBLUE +#include +#include +#endif + +#define BBBLUE_MAX_ADC_CHANNELS (6) +#define BBBLUE_MAX_ADC_USER_CHANNELS (4) +#define BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL (5) +#define BBBLUE_ADC_LIPO_BATTERY_VOLTAGE_CHANNEL (6) + +class ADC : public ModuleBase, public px4::ScheduledWorkItem +{ +public: + ADC(); + ~ADC(); + + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); + + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::print_status() */ + int print_status() override; + + int start(); + int stop(); + +private: + void Run() override; + + void update_adc_report(const hrt_abstime &now); + + static constexpr uint32_t TICKRATE{10_ms}; /**< 100Hz base rate */ + + perf_counter_t _sample_perf; + adc_report_s _samples{}; /**< sample buffer */ + + uORB::Publication _adc_report_pub{ORB_ID(adc_report)}; + uORB::Publication _system_power_pub{ORB_ID(system_power)}; +}; + +ADC::ADC() : + ScheduledWorkItem(px4::wq_configurations::hp_default), + _sample_perf(perf_alloc(PC_ELAPSED, "adc_sample")) +{ + for (int i = 0; i < adc_report_s::MAX_CHANNELS; i++) { + _samples.channel_id[i] = -1; + } +} + +ADC::~ADC() +{ + ScheduleClear(); + perf_free(_sample_perf); +} + +int +ADC::start() +{ + /* and schedule regular updates */ + ScheduleOnInterval(TICKRATE); + return PX4_OK; +} + +void +ADC::Run() +{ + px4_adc_msg_t tmp_samples[BBBLUE_MAX_ADC_CHANNELS]; + + for (int i = 0; i < BBBLUE_MAX_ADC_USER_CHANNELS; ++i) { + tmp_samples[i].am_channel = i; + tmp_samples[i].am_data = rc_adc_read_raw(i); + } + + tmp_samples[BBBLUE_MAX_ADC_USER_CHANNELS].am_channel = BBBLUE_ADC_LIPO_BATTERY_VOLTAGE_CHANNEL; + tmp_samples[BBBLUE_MAX_ADC_USER_CHANNELS].am_data = rc_adc_read_raw(BBBLUE_ADC_LIPO_BATTERY_VOLTAGE_CHANNEL); + + tmp_samples[BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL].am_channel = BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL; + tmp_samples[BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL].am_data = rc_adc_read_raw(BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL); + + _samples.timestamp = hrt_absolute_time(); + _adc_report_pub.publish(_samples); +} + +int +ADC::print_status() +{ + PX4_INFO("Running"); + + perf_print_counter(_sample_perf); + + return 0; +} + +int +ADC::custom_command(int argc, char *argv[]) +{ + return print_usage("unknown command"); +} + +int +ADC::task_spawn(int argc, char *argv[]) +{ + ADC *instance = new ADC(ADC_CHANNELS); + + if (instance) { + _object.store(instance); + _task_id = task_id_is_work_queue; + + if (instance->start() == PX4_OK) { + return PX4_OK; + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + _object.store(nullptr); + _task_id = -1; + + return PX4_ERROR; +} + +int +ADC::print_usage(const char *reason) +{ + if (reason) { + PX4_WARN("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +ADC driver. +)DESCR_STR"); + + PRINT_MODULE_USAGE_COMMAND("start"); + + PRINT_MODULE_USAGE_NAME("adc", "driver"); + + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; +} + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int adc_main(int argc, char *argv[]); + +int adc_main(int argc, char *argv[]) +{ + return ADC::main(argc, argv); +} diff --git a/boards/beaglebone/blue/bbblue_adc/CMakeLists.txt b/boards/beaglebone/blue/bbblue_adc/CMakeLists.txt deleted file mode 100644 index f7c6fec3de23..000000000000 --- a/boards/beaglebone/blue/bbblue_adc/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################ -# -# Copyright (c) 2018 PX4 Development Team. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name PX4 nor the names of its contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -############################################################################ - -px4_add_module( - MODULE drivers__bbblue_adc - MAIN bbblue_adc - COMPILE_FLAGS - -Wno-error - SRCS - bbblue_adc.cpp - - # Previous board specific code is now precluded from build after - # the following was added to Frimware/CMakeLists.txt: - # - # add_subdirectory(src/drivers/boards EXCLUDE_FROM_ALL) - # - # so include bbblue board specific code here: - ../src/init.c - DEPENDS - -) diff --git a/boards/beaglebone/blue/bbblue_adc/bbblue_adc.cpp b/boards/beaglebone/blue/bbblue_adc/bbblue_adc.cpp deleted file mode 100644 index a912c354c9c9..000000000000 --- a/boards/beaglebone/blue/bbblue_adc/bbblue_adc.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012-2018 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file bbblue_adc.cpp - * - * BBBlue ADC Driver - * - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#ifdef __DF_BBBLUE -#include -#include -#endif - -#define ADC_BASE_DEV_PATH "/dev/null" - -#define BBBLUE_MAX_ADC_CHANNELS (6) -#define BBBLUE_MAX_ADC_USER_CHANNELS (4) -#define BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL (5) -#define BBBLUE_ADC_LIPO_BATTERY_VOLTAGE_CHANNEL (6) - -__BEGIN_DECLS -__EXPORT int bbblue_adc_main(int argc, char *argv[]); -__END_DECLS - -class BBBlueADC: public DriverFramework::VirtDevObj -{ -public: - BBBlueADC(); - virtual ~BBBlueADC(); - - virtual int init(); - - virtual ssize_t devRead(void *buf, size_t count) override; - virtual int devIOCTL(unsigned long request, unsigned long arg) override; - -protected: - virtual void _measure() override; - -private: - pthread_mutex_t _samples_lock; - px4_adc_msg_t _samples[BBBLUE_MAX_ADC_CHANNELS]; -}; - -BBBlueADC::BBBlueADC() - : DriverFramework::VirtDevObj("bbblue_adc", ADC0_DEVICE_PATH, ADC_BASE_DEV_PATH, 1e6 / 100) -{ - pthread_mutex_init(&_samples_lock, NULL); -} - -BBBlueADC::~BBBlueADC() -{ - pthread_mutex_destroy(&_samples_lock); - - rc_cleaning(); -} - -void BBBlueADC::_measure() -{ -#ifdef __DF_BBBLUE - px4_adc_msg_t tmp_samples[BBBLUE_MAX_ADC_CHANNELS]; - - for (int i = 0; i < BBBLUE_MAX_ADC_USER_CHANNELS; ++i) { - tmp_samples[i].am_channel = i; - tmp_samples[i].am_data = rc_adc_read_raw(i); - } - - tmp_samples[BBBLUE_MAX_ADC_USER_CHANNELS].am_channel = BBBLUE_ADC_LIPO_BATTERY_VOLTAGE_CHANNEL; - tmp_samples[BBBLUE_MAX_ADC_USER_CHANNELS].am_data = rc_adc_read_raw(BBBLUE_ADC_LIPO_BATTERY_VOLTAGE_CHANNEL); - - tmp_samples[BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL].am_channel = BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL; - tmp_samples[BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL].am_data = rc_adc_read_raw(BBBLUE_ADC_DC_JACK_VOLTAGE_CHANNEL); - - pthread_mutex_lock(&_samples_lock); - memcpy(&_samples, &tmp_samples, sizeof(tmp_samples)); - pthread_mutex_unlock(&_samples_lock); -#endif -} - -int BBBlueADC::init() -{ - rc_init(); - - int ret = DriverFramework::VirtDevObj::init(); - - if (ret != PX4_OK) { - PX4_ERR("init failed"); - return ret; - } - - _measure(); // start the initial conversion so that the test command right - // after the start command can return values - return PX4_OK; -} - -int BBBlueADC::devIOCTL(unsigned long request, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t BBBlueADC::devRead(void *buf, size_t count) -{ - const size_t maxsize = sizeof(_samples); - int ret; - - if (count > maxsize) { - count = maxsize; - } - - ret = pthread_mutex_trylock(&_samples_lock); - - if (ret != 0) { - return 0; - } - - memcpy(buf, &_samples, count); - pthread_mutex_unlock(&_samples_lock); - - return count; -} - -static BBBlueADC *instance = nullptr; - -int bbblue_adc_main(int argc, char *argv[]) -{ - int ret; - - if (argc < 2) { - PX4_WARN("usage: {start|stop|test}"); - return PX4_ERROR; - } - - if (!strcmp(argv[1], "start")) { - if (instance) { - PX4_WARN("already started"); - return PX4_OK; - } - - instance = new BBBlueADC; - - if (!instance) { - PX4_WARN("not enough memory"); - return PX4_ERROR; - } - - if (instance->init() != PX4_OK) { - delete instance; - instance = nullptr; - PX4_WARN("init failed"); - return PX4_ERROR; - } - - PX4_INFO("BBBlueADC started"); - return PX4_OK; - - } else if (!strcmp(argv[1], "stop")) { - if (!instance) { - PX4_WARN("already stopped"); - return PX4_OK; - } - - delete instance; - instance = nullptr; - return PX4_OK; - - } else if (!strcmp(argv[1], "test")) { - if (!instance) { - PX4_ERR("start first"); - return PX4_ERROR; - } - - px4_adc_msg_t adc_msgs[BBBLUE_MAX_ADC_CHANNELS]; - - ret = instance->devRead((char *)&adc_msgs, sizeof(adc_msgs)); - - if (ret < 0) { - PX4_ERR("ret: %s (%d)\n", strerror(ret), ret); - return ret; - - } else if (ret != sizeof(adc_msgs)) { - PX4_ERR("incomplete read: %d expected %d", ret, sizeof(adc_msgs)); - return ret; - } - - for (int i = 0; i < BBBLUE_MAX_ADC_USER_CHANNELS; ++i) { - PX4_INFO("ADC channel: %d; value: %d", (int)adc_msgs[i].am_channel, - adc_msgs[i].am_data); - } - - for (int i = BBBLUE_MAX_ADC_USER_CHANNELS; i < BBBLUE_MAX_ADC_CHANNELS; ++i) { - PX4_INFO("ADC channel: %d; value: %d, voltage: %6.2f V", (int)adc_msgs[i].am_channel, - adc_msgs[i].am_data, adc_msgs[i].am_data * 1.8 / 4095.0 * 11.0); - - } - - return PX4_OK; - - } else { - PX4_WARN("action (%s) not supported", argv[1]); - - return PX4_ERROR; - } - - return PX4_OK; - -} - - diff --git a/boards/beaglebone/blue/cross.cmake b/boards/beaglebone/blue/cross.cmake index 70ad59e04ab4..05881cc1c4b6 100644 --- a/boards/beaglebone/blue/cross.cmake +++ b/boards/beaglebone/blue/cross.cmake @@ -9,6 +9,7 @@ px4_add_board( TESTING DRIVERS + adc #barometer # all available barometer drivers batt_smbus camera_trigger @@ -18,6 +19,7 @@ px4_add_board( #imu # all available imu drivers #magnetometer # all available magnetometer drivers pwm_out_sim + system_power #telemetry # all available telemetry drivers linux_pwm_out diff --git a/boards/beaglebone/blue/native.cmake b/boards/beaglebone/blue/native.cmake index 1374ad6f60ba..40b8cf751b8e 100644 --- a/boards/beaglebone/blue/native.cmake +++ b/boards/beaglebone/blue/native.cmake @@ -7,6 +7,7 @@ px4_add_board( TESTING DRIVERS + adc #barometer # all available barometer drivers batt_smbus camera_trigger @@ -16,6 +17,7 @@ px4_add_board( #imu # all available imu drivers #magnetometer # all available magnetometer drivers pwm_out_sim + system_power #telemetry # all available telemetry drivers linux_pwm_out diff --git a/boards/bitcraze/crazyflie/src/board_config.h b/boards/bitcraze/crazyflie/src/board_config.h index 2daa86cc8321..de43d90ae40d 100644 --- a/boards/bitcraze/crazyflie/src/board_config.h +++ b/boards/bitcraze/crazyflie/src/board_config.h @@ -146,13 +146,6 @@ */ #define GPIO_OTGFS_VBUS (GPIO_INPUT|GPIO_FLOAT|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN9) -/* - * ADC channels - * - * These are the channel numbers of the ADCs of the microcontroller that can be used by the Px4 Firmware in the adc driver - */ -#define ADC_CHANNELS 0 - // ADC defines to be used in sensors.cpp to read from a particular channel // Crazyflie 2 performs battery sensing via the NRF module #define ADC_BATTERY_VOLTAGE_CHANNEL ((uint8_t)(-1)) diff --git a/boards/emlid/navio2/CMakeLists.txt b/boards/emlid/navio2/CMakeLists.txt index 2245838e0a69..1fe72a149545 100644 --- a/boards/emlid/navio2/CMakeLists.txt +++ b/boards/emlid/navio2/CMakeLists.txt @@ -31,7 +31,7 @@ # ############################################################################ -add_subdirectory(navio_adc) +add_subdirectory(adc) add_subdirectory(navio_rgbled) add_subdirectory(navio_sysfs_rc_in) diff --git a/boards/emlid/navio2/navio_adc/CMakeLists.txt b/boards/emlid/navio2/adc/CMakeLists.txt similarity index 91% rename from boards/emlid/navio2/navio_adc/CMakeLists.txt rename to boards/emlid/navio2/adc/CMakeLists.txt index 955b30260fe2..055a8bb59a3b 100644 --- a/boards/emlid/navio2/navio_adc/CMakeLists.txt +++ b/boards/emlid/navio2/adc/CMakeLists.txt @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (c) 2015-2017 PX4 Development Team. All rights reserved. +# Copyright (c) 2015-2019 PX4 Development Team. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -30,12 +30,10 @@ # POSSIBILITY OF SUCH DAMAGE. # ############################################################################ + px4_add_module( - MODULE drivers__navio_adc - MAIN navio_adc - COMPILE_FLAGS + MODULE drivers__adc + MAIN adc SRCS - navio_adc.cpp - DEPENDS + adc.cpp ) - diff --git a/boards/emlid/navio2/adc/adc.cpp b/boards/emlid/navio2/adc/adc.cpp new file mode 100644 index 000000000000..65adee0ffd17 --- /dev/null +++ b/boards/emlid/navio2/adc/adc.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file adc.cpp + * + * Navio2 ADC Driver + * + * This driver exports the sysfs-based ADC driver on Navio2. + * + * @author Nicolae Rosia + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADC_SYSFS_PATH "/sys/kernel/rcio/adc/ch0" +#define ADC_MAX_CHAN 6 + +/* + * ADC Channels: + * A0 - Board voltage (5V) + * A1 - servo rail voltage + * A2 - power module voltage (ADC0, POWER port) + * A3 - power module current (ADC1, POWER port) + * A4 - ADC2 (ADC port) + * A5 - ADC3 (ADC port) + */ + +#define NAVIO_ADC_BATTERY_VOLTAGE_CHANNEL (2) +#define NAVIO_ADC_BATTERY_CURRENT_CHANNEL (3) + +using namespace time_literals; + +class ADC : public ModuleBase, public px4::ScheduledWorkItem +{ +public: + ADC(); + ~ADC(); + + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); + + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::print_status() */ + int print_status() override; + int init(); + int start(); + int stop(); + +private: + void Run() override; + + void update_adc_report(const hrt_abstime &now); + + static constexpr uint32_t TICKRATE{10_ms}; /**< 100Hz base rate */ + + perf_counter_t _sample_perf; + adc_report_s _samples{}; /**< sample buffer */ + + uORB::Publication _adc_report_pub{ORB_ID(adc_report)}; + + int _fd[ADC_MAX_CHAN] {}; +}; + +ADC::ADC() : + ScheduledWorkItem(px4::wq_configurations::hp_default), + _sample_perf(perf_alloc(PC_ELAPSED, "adc_sample")) +{ + for (int i = 0; i < ADC_MAX_CHAN; i++) { + _fd[i] = -1; + } + + for (int i = 0; i < adc_report_s::MAX_CHANNELS; i++) { + _samples.channel_id[i] = -1; + } +} + +ADC::~ADC() +{ + ScheduleClear(); + perf_free(_sample_perf); + + for (int i = 0; i < ADC_MAX_CHAN; i++) { + if (_fd[i] != -1) { + close(_fd[i]); + } + } +} + +int +ADC::start() +{ + /* and schedule regular updates */ + ScheduleOnInterval(TICKRATE); + return PX4_OK; +} + +void +ADC::Run() +{ + adc_report_s tmp_samples{}; + + for (int i = 0; i < ADC_MAX_CHAN; ++i) { + /* Currently we only use these channels */ + if (i != NAVIO_ADC_BATTERY_VOLTAGE_CHANNEL && + i != NAVIO_ADC_BATTERY_CURRENT_CHANNEL) { + + tmp_samples.channel_id[i] = i; + tmp_samples.channel_value[i] = 0; + + continue; + } + + tmp_samples.channel_value[i] = board_adc_sample(i); + + // if (ret < 0) { + // PX4_ERR("read_channel(%d): %d", i, ret); + // tmp_samples.channel_id[i] = i; + // tmp_samples.channel_value[i] = 0; + // } + } + + //tmp_samples[NAVIO_ADC_BATTERY_VOLTAGE_CHANNEL].am_channel = ADC_BATTERY_VOLTAGE_CHANNEL; + //tmp_samples[NAVIO_ADC_BATTERY_CURRENT_CHANNEL].am_channel = ADC_BATTERY_CURRENT_CHANNEL; + + tmp_samples.timestamp = hrt_absolute_time(); + + _adc_report_pub.publish(tmp_samples); +} + +int +ADC::init() +{ + for (int i = 0; i < ADC_MAX_CHAN; i++) { + char channel_path[sizeof(ADC_SYSFS_PATH)] {}; + strncpy(channel_path, ADC_SYSFS_PATH, sizeof(ADC_SYSFS_PATH)); + channel_path[sizeof(ADC_SYSFS_PATH) - 2] += i; + + _fd[i] = ::open(channel_path, O_RDONLY); + + if (_fd[i] == -1) { + PX4_ERR("init: open: %s (%d)", strerror(err), err); + goto cleanup; + } + } + + ScheduleOnInterval(100_ms); + + return PX4_OK; + +cleanup: + + for (int i = 0; i < ADC_MAX_CHAN; i++) { + if (_fd[i] != -1) { + close(_fd[i]); + } + } + + return ret; +} + +uint16_t board_adc_sample(unsigned channel) +{ + uint16_t result = 0xffff; + + char buffer[11] {}; /* 32bit max INT has maximum 10 chars */ + + if (channel < 0 || channel >= ADC_MAX_CHAN) { + return result; + } + + int ret = lseek(_fd[channel], 0, SEEK_SET); + + if (ret == -1) { + PX4_ERR("read_channel %d: lseek: %s (%d)", channel, strerror(ret), ret); + return result; + } + + ret = ::read(_fd[channel], buffer, sizeof(buffer) - 1); + + if (ret == -1) { + ret = errno; + PX4_ERR("read_channel %d: read: %s (%d)", channel, strerror(ret), ret); + return result; + + } else if (ret == 0) { + PX4_ERR("read_channel %d: read empty", channel); + return result; + } + + buffer[ret] = 0; + + result = strtol(buffer, NULL, 10); + + return result; +} + +int +ADC::print_status() +{ + PX4_INFO("Running"); + + perf_print_counter(_sample_perf); + + return 0; +} + +int +ADC::custom_command(int argc, char *argv[]) +{ + return print_usage("unknown command"); +} + +int +ADC::task_spawn(int argc, char *argv[]) +{ + ADC *instance = new ADC(ADC_CHANNELS); + + if (instance) { + _object.store(instance); + _task_id = task_id_is_work_queue; + + if (instance->start() == PX4_OK) { + return PX4_OK; + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + _object.store(nullptr); + _task_id = -1; + + return PX4_ERROR; +} + +int +ADC::print_usage(const char *reason) +{ + if (reason) { + PX4_WARN("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +ADC driver. +)DESCR_STR"); + + PRINT_MODULE_USAGE_COMMAND("start"); + + PRINT_MODULE_USAGE_NAME("adc", "driver"); + + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; +} + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int adc_main(int argc, char *argv[]); + +int adc_main(int argc, char *argv[]) +{ + return ADC::main(argc, argv); +} diff --git a/boards/emlid/navio2/cross.cmake b/boards/emlid/navio2/cross.cmake index 367fa6acd1a3..80c2ca944e53 100644 --- a/boards/emlid/navio2/cross.cmake +++ b/boards/emlid/navio2/cross.cmake @@ -9,6 +9,7 @@ px4_add_board( TESTING DRIVERS + adc #barometer # all available barometer drivers batt_smbus camera_trigger @@ -18,6 +19,7 @@ px4_add_board( #imu # all available imu drivers #magnetometer # all available magnetometer drivers pwm_out_sim + system_power #telemetry # all available telemetry drivers linux_pwm_out diff --git a/boards/emlid/navio2/native.cmake b/boards/emlid/navio2/native.cmake index 781ad8f32b52..a9f38d140818 100644 --- a/boards/emlid/navio2/native.cmake +++ b/boards/emlid/navio2/native.cmake @@ -7,6 +7,7 @@ px4_add_board( TESTING DRIVERS + adcc #barometer # all available barometer drivers batt_smbus camera_trigger @@ -16,6 +17,7 @@ px4_add_board( #imu # all available imu drivers #magnetometer # all available magnetometer drivers pwm_out_sim + system_power #telemetry # all available telemetry drivers linux_pwm_out diff --git a/boards/emlid/navio2/navio_adc/navio_adc.cpp b/boards/emlid/navio2/navio_adc/navio_adc.cpp deleted file mode 100644 index 6614a65eedef..000000000000 --- a/boards/emlid/navio2/navio_adc/navio_adc.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012-2017 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file navio_adc.cpp - * - * Navio2 ADC Driver - * - * This driver exports the sysfs-based ADC driver on Navio2. - * - * @author Nicolae Rosia - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#define ADC_BASE_DEV_PATH "/dev/adc" -#define ADC_SYSFS_PATH "/sys/kernel/rcio/adc/ch0" -#define ADC_MAX_CHAN 6 - -/* - * ADC Channels: - * A0 - Board voltage (5V) - * A1 - servo rail voltage - * A2 - power module voltage (ADC0, POWER port) - * A3 - power module current (ADC1, POWER port) - * A4 - ADC2 (ADC port) - * A5 - ADC3 (ADC port) - */ - -#define NAVIO_ADC_BATTERY_VOLTAGE_CHANNEL (2) -#define NAVIO_ADC_BATTERY_CURRENT_CHANNEL (3) - -__BEGIN_DECLS -__EXPORT int navio_adc_main(int argc, char *argv[]); -__END_DECLS - -class NavioADC: public DriverFramework::VirtDevObj -{ -public: - NavioADC(); - virtual ~NavioADC(); - - virtual int init() override; - - virtual ssize_t devRead(void *buf, size_t count) override; - virtual int devIOCTL(unsigned long request, unsigned long arg) override; - -protected: - virtual void _measure() override; - -private: - int read_channel(px4_adc_msg_t *adc_msg, int channel); - - pthread_mutex_t _samples_lock; - int _fd[ADC_MAX_CHAN]; - px4_adc_msg_t _samples[ADC_MAX_CHAN]; -}; - -NavioADC::NavioADC() - : DriverFramework::VirtDevObj("navio_adc", ADC0_DEVICE_PATH, ADC_BASE_DEV_PATH, 1e6 / 100) -{ - pthread_mutex_init(&_samples_lock, NULL); - - for (int i = 0; i < ADC_MAX_CHAN; i++) { - _fd[i] = -1; - } -} - -NavioADC::~NavioADC() -{ - pthread_mutex_destroy(&_samples_lock); - - for (int i = 0; i < ADC_MAX_CHAN; i++) { - if (_fd[i] != -1) { - close(_fd[i]); - } - } -} - -void NavioADC::_measure() -{ - px4_adc_msg_t tmp_samples[ADC_MAX_CHAN]; - - for (int i = 0; i < ADC_MAX_CHAN; ++i) { - int ret; - - /* Currently we only use these channels */ - if (i != NAVIO_ADC_BATTERY_VOLTAGE_CHANNEL && - i != NAVIO_ADC_BATTERY_CURRENT_CHANNEL) { - tmp_samples[i].am_channel = i; - tmp_samples[i].am_data = 0; - - continue; - } - - ret = read_channel(&tmp_samples[i], i); - - if (ret < 0) { - PX4_ERR("read_channel(%d): %d", i, ret); - tmp_samples[i].am_channel = i; - tmp_samples[i].am_data = 0; - } - } - - tmp_samples[NAVIO_ADC_BATTERY_VOLTAGE_CHANNEL].am_channel = ADC_BATTERY_VOLTAGE_CHANNEL; - tmp_samples[NAVIO_ADC_BATTERY_CURRENT_CHANNEL].am_channel = ADC_BATTERY_CURRENT_CHANNEL; - - pthread_mutex_lock(&_samples_lock); - memcpy(&_samples, &tmp_samples, sizeof(tmp_samples)); - pthread_mutex_unlock(&_samples_lock); -} - -int NavioADC::init() -{ - int ret; - - ret = DriverFramework::VirtDevObj::init(); - - if (ret != PX4_OK) { - PX4_ERR("init failed"); - return ret; - } - - for (int i = 0; i < ADC_MAX_CHAN; i++) { - char channel_path[sizeof(ADC_SYSFS_PATH)]; - strncpy(channel_path, ADC_SYSFS_PATH, sizeof(ADC_SYSFS_PATH)); - channel_path[sizeof(ADC_SYSFS_PATH) - 2] += i; - - _fd[i] = ::open(channel_path, O_RDONLY); - - if (_fd[i] == -1) { - int err = errno; - ret = -1; - PX4_ERR("init: open: %s (%d)", strerror(err), err); - goto cleanup; - } - } - - return PX4_OK; - -cleanup: - - for (int i = 0; i < ADC_MAX_CHAN; i++) { - if (_fd[i] != -1) { - close(_fd[i]); - } - } - - return ret; -} - -int NavioADC::devIOCTL(unsigned long request, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t NavioADC::devRead(void *buf, size_t count) -{ - const size_t maxsize = sizeof(_samples); - int ret; - - if (count > maxsize) { - count = maxsize; - } - - ret = pthread_mutex_trylock(&_samples_lock); - - if (ret != 0) { - return 0; - } - - memcpy(buf, &_samples, count); - pthread_mutex_unlock(&_samples_lock); - - return count; -} - -int NavioADC::read_channel(px4_adc_msg_t *adc_msg, int channel) -{ - char buffer[11]; /* 32bit max INT has maximum 10 chars */ - int ret; - - if (channel < 0 || channel >= ADC_MAX_CHAN) { - return -EINVAL; - } - - ret = lseek(_fd[channel], 0, SEEK_SET); - - if (ret == -1) { - ret = errno; - PX4_ERR("read_channel %d: lseek: %s (%d)", channel, strerror(ret), ret); - return ret; - } - - ret = ::read(_fd[channel], buffer, sizeof(buffer) - 1); - - if (ret == -1) { - ret = errno; - PX4_ERR("read_channel %d: read: %s (%d)", channel, strerror(ret), ret); - return ret; - - } else if (ret == 0) { - PX4_ERR("read_channel %d: read empty", channel); - ret = -EINVAL; - return ret; - } - - buffer[ret] = 0; - - adc_msg->am_channel = channel; - adc_msg->am_data = strtol(buffer, NULL, 10); - ret = 0; - - return ret; -} - -static NavioADC *instance = nullptr; - -int navio_adc_main(int argc, char *argv[]) -{ - int ret; - - if (argc < 2) { - PX4_WARN("usage: "); - return PX4_ERROR; - } - - if (!strcmp(argv[1], "start")) { - if (instance) { - PX4_WARN("already started"); - return PX4_OK; - } - - instance = new NavioADC; - - if (!instance) { - PX4_WARN("not enough memory"); - return PX4_ERROR; - } - - if (instance->init() != PX4_OK) { - delete instance; - instance = nullptr; - PX4_WARN("init failed"); - return PX4_ERROR; - } - - return PX4_OK; - - } else if (!strcmp(argv[1], "stop")) { - if (!instance) { - PX4_WARN("already stopped"); - return PX4_OK; - } - - delete instance; - instance = nullptr; - return PX4_OK; - - } else if (!strcmp(argv[1], "test")) { - if (!instance) { - PX4_ERR("start first"); - return PX4_ERROR; - } - - px4_adc_msg_t adc_msgs[ADC_MAX_CHAN]; - - ret = instance->devRead((char *)&adc_msgs, sizeof(adc_msgs)); - - if (ret < 0) { - PX4_ERR("ret: %s (%d)\n", strerror(ret), ret); - return ret; - - } else if (ret != sizeof(adc_msgs)) { - PX4_ERR("incomplete read: %d expected %d", ret, sizeof(adc_msgs)); - return ret; - } - - for (int i = 0; i < ADC_MAX_CHAN; ++i) { - PX4_INFO("chan: %d; value: %d", (int)adc_msgs[i].am_channel, - adc_msgs[i].am_data); - } - - return PX4_OK; - - } else { - PX4_WARN("action (%s) not supported", argv[1]); - - return PX4_ERROR; - } - - return PX4_OK; - -} diff --git a/boards/holybro/kakutef7/default.cmake b/boards/holybro/kakutef7/default.cmake index 393316ea0706..557a6a5beb1c 100644 --- a/boards/holybro/kakutef7/default.cmake +++ b/boards/holybro/kakutef7/default.cmake @@ -17,6 +17,7 @@ px4_add_board( # /dev/ttyS5: UART7 (ESC telemetry) DRIVERS + adc barometer/bmp280 gps imu/mpu6000 @@ -26,8 +27,7 @@ px4_add_board( px4fmu rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power telemetry tone_alarm osd diff --git a/boards/intel/aerofc-v1/CMakeLists.txt b/boards/intel/aerofc-v1/CMakeLists.txt index 342bbda02cd7..c553696959bb 100644 --- a/boards/intel/aerofc-v1/CMakeLists.txt +++ b/boards/intel/aerofc-v1/CMakeLists.txt @@ -31,8 +31,7 @@ # ############################################################################ -add_subdirectory(aerofc_adc) - +add_subdirectory(adc) ############################################################################ diff --git a/boards/intel/aerofc-v1/aerofc_adc/CMakeLists.txt b/boards/intel/aerofc-v1/adc/CMakeLists.txt similarity index 92% rename from boards/intel/aerofc-v1/aerofc_adc/CMakeLists.txt rename to boards/intel/aerofc-v1/adc/CMakeLists.txt index 847020a866e6..9d78af22b553 100644 --- a/boards/intel/aerofc-v1/aerofc_adc/CMakeLists.txt +++ b/boards/intel/aerofc-v1/adc/CMakeLists.txt @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 Intel Corporation. All rights reserved. +# Copyright (C) 2016-2019 Intel Corporation. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -30,12 +30,13 @@ # POSSIBILITY OF SUCH DAMAGE. # ############################################################################ + px4_add_module( - MODULE drivers__aerofc_adc - MAIN aerofc_adc - COMPILE_FLAGS + MODULE drivers__adc + MAIN adc SRCS - aerofc_adc.cpp + adc.cpp DEPENDS drivers__device + px4_work_queue ) diff --git a/boards/intel/aerofc-v1/adc/adc.cpp b/boards/intel/aerofc-v1/adc/adc.cpp new file mode 100644 index 000000000000..6beaccd3870c --- /dev/null +++ b/boards/intel/aerofc-v1/adc/adc.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** + * + * Copyright (C) 2016-2019 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace time_literals; + +#define SLAVE_ADDR 0x50 +#define ADC_ENABLE_REG 0x00 +#define ADC_CHANNEL_REG 0x05 +#define MAX_CHANNEL 5 + +enum AEROFC_ADC_BUS { + AEROFC_ADC_BUS_ALL = 0, + AEROFC_ADC_BUS_I2C_INTERNAL, + AEROFC_ADC_BUS_I2C_EXTERNAL +}; + +static constexpr struct aerofc_adc_bus_option { + enum AEROFC_ADC_BUS busid; + uint8_t busnum; +} bus_options[] = { +#ifdef PX4_I2C_BUS_EXPANSION + { AEROFC_ADC_BUS_I2C_EXTERNAL, PX4_I2C_BUS_EXPANSION }, +#endif +#ifdef PX4_I2C_BUS_EXPANSION1 + { AEROFC_ADC_BUS_I2C_EXTERNAL, PX4_I2C_BUS_EXPANSION1 }, +#endif +#ifdef PX4_I2C_BUS_ONBOARD + { AEROFC_ADC_BUS_I2C_INTERNAL, PX4_I2C_BUS_ONBOARD }, +#endif +}; + +class ADC : public ModuleBase, public device::I2C, public px4::ScheduledWorkItem +{ +public: + ADC(uint8_t bus); + ~ADC(); + + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); + + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::print_status() */ + int print_status() override; + + int init(); + + int probe() override; + + int start(); + int stop(); + +private: + void Run() override; + + void update_adc_report(const hrt_abstime &now); + + static constexpr uint32_t TICKRATE{10_ms}; /**< 100Hz base rate */ + + perf_counter_t _sample_perf; + adc_report_s _samples{}; /**< sample buffer */ + + uORB::Publication _adc_report_pub{ORB_ID(adc_report)}; +}; + +ADC::ADC(uint8_t bus) : + I2C("AEROFC_ADC", nullptr, bus, SLAVE_ADDR, 400000), + ScheduledWorkItem(px4::device_bus_to_wq(get_device_id())), + _sample_perf(perf_alloc(PC_ELAPSED, "adc_sample")) +{ + for (int i = 0; i < adc_report_s::MAX_CHANNELS; i++) { + _samples.channel_id[i] = -1; + } +} + +ADC::~ADC() +{ + ScheduleClear(); + perf_free(_sample_perf); +} + +int +ADC::init() +{ + int ret = I2C::init(); + + if (ret != PX4_OK) { + return ret; + } + + return start(); +} + +int +ADC::start() +{ + /* and schedule regular updates */ + ScheduleOnInterval(TICKRATE); + return PX4_OK; +} + +int +ADC::stop() +{ + ScheduleClear(); + return PX4_OK; +} + +int +ADC::probe() +{ + uint8_t buffer[2] {}; + + _retries = 3; + + /* Enable ADC */ + buffer[0] = ADC_ENABLE_REG; + buffer[1] = 0x01; + int ret = transfer(buffer, 2, NULL, 0); + + if (ret != PX4_OK) { + return -EIO; + } + + usleep(10000); + + /* Read ADC value */ + buffer[0] = ADC_CHANNEL_REG; + ret = transfer(buffer, 1, buffer, 2); + + if (ret != PX4_OK) { + return -EIO; + } + + return PX4_OK; +} + +void +ADC::Run() +{ + uint8_t buffer[2] {}; + + buffer[0] = ADC_CHANNEL_REG; + int ret = transfer(buffer, 1, buffer, sizeof(buffer)); + + if (ret != PX4_OK) { + PX4_ERR("Error reading sample"); + return; + } + + _samples.channel_id[0] = ADC_BATTERY_VOLTAGE_CHANNEL; + _samples.channel_value[0] = (buffer[0] | (buffer[1] << 8)); + + _samples.timestamp = hrt_absolute_time(); + + _adc_report_pub.publish(_samples); +} + +int +ADC::print_status() +{ + PX4_INFO("Running"); + + perf_print_counter(_sample_perf); + + return 0; +} + +int +ADC::custom_command(int argc, char *argv[]) +{ + return print_usage("unknown command"); +} + +int +ADC::task_spawn(int argc, char *argv[]) +{ + ADC *instance = new ADC(ADC_CHANNELS); + + if (instance) { + _object.store(instance); + _task_id = task_id_is_work_queue; + + if (instance->init() == PX4_OK) { + return instance->start(); + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + _object.store(nullptr); + _task_id = -1; + + return PX4_ERROR; +} + +int +ADC::print_usage(const char *reason) +{ + if (reason) { + PX4_WARN("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +ADC driver. +)DESCR_STR"); + + PRINT_MODULE_USAGE_COMMAND("start"); + + PRINT_MODULE_USAGE_NAME("adc", "driver"); + + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; +} + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int adc_main(int argc, char *argv[]); + +int adc_main(int argc, char *argv[]) +{ + return ADC::main(argc, argv); +} diff --git a/boards/intel/aerofc-v1/aerofc_adc/aerofc_adc.cpp b/boards/intel/aerofc-v1/aerofc_adc/aerofc_adc.cpp deleted file mode 100644 index a84f5eae83df..000000000000 --- a/boards/intel/aerofc-v1/aerofc_adc/aerofc_adc.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2016 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -#include -#include - -#include - -#include - -#include -#include - -#include - -#include -#include - -#include - -#define SLAVE_ADDR 0x50 -#define ADC_ENABLE_REG 0x00 -#define ADC_CHANNEL_REG 0x05 -#define MAX_CHANNEL 5 - -// 10Hz -#define CYCLE_TICKS_DELAY MSEC2TICK(100) - -enum AEROFC_ADC_BUS { - AEROFC_ADC_BUS_ALL = 0, - AEROFC_ADC_BUS_I2C_INTERNAL, - AEROFC_ADC_BUS_I2C_EXTERNAL -}; - -static constexpr struct aerofc_adc_bus_option { - enum AEROFC_ADC_BUS busid; - uint8_t busnum; -} bus_options[] = { -#ifdef PX4_I2C_BUS_EXPANSION - { AEROFC_ADC_BUS_I2C_EXTERNAL, PX4_I2C_BUS_EXPANSION }, -#endif -#ifdef PX4_I2C_BUS_EXPANSION1 - { AEROFC_ADC_BUS_I2C_EXTERNAL, PX4_I2C_BUS_EXPANSION1 }, -#endif -#ifdef PX4_I2C_BUS_ONBOARD - { AEROFC_ADC_BUS_I2C_INTERNAL, PX4_I2C_BUS_ONBOARD }, -#endif -}; - -extern "C" { __EXPORT int aerofc_adc_main(int argc, char *argv[]); } - -class AEROFC_ADC : public device::I2C -{ -public: - AEROFC_ADC(uint8_t bus); - virtual ~AEROFC_ADC(); - - virtual int init(); - virtual int ioctl(file *filp, int cmd, unsigned long arg); - virtual ssize_t read(file *filp, char *buffer, size_t len); - -private: - virtual int probe(); - - void cycle(); - static void cycle_trampoline(void *arg); - - struct work_s _work; - px4_adc_msg_t _sample; - pthread_mutex_t _sample_mutex; -}; - -static AEROFC_ADC *instance = nullptr; - -static void test() -{ - int fd = open(ADC0_DEVICE_PATH, O_RDONLY); - - if (fd < 0) { - err(1, "can't open ADC device"); - } - - px4_adc_msg_t data[MAX_CHANNEL]; - ssize_t count = read(fd, data, sizeof(data)); - - if (count < 0) { - errx(1, "read error"); - } - - unsigned channels = count / sizeof(data[0]); - - for (unsigned j = 0; j < channels; j++) { - printf("%d: %u ", data[j].am_channel, data[j].am_data); - } - - printf("\n"); - - exit(0); -} - -static void help() -{ - printf("missing command: try 'start' or 'test'\n"); - printf("options:\n"); - printf(" -I only internal I2C bus\n"); - printf(" -X only external I2C bus\n"); -} - -int aerofc_adc_main(int argc, char *argv[]) -{ - int ch; - enum AEROFC_ADC_BUS busid = AEROFC_ADC_BUS_ALL; - - while ((ch = getopt(argc, argv, "XI")) != EOF) { - switch (ch) { - case 'X': - busid = AEROFC_ADC_BUS_I2C_EXTERNAL; - break; - - case 'I': - busid = AEROFC_ADC_BUS_I2C_INTERNAL; - break; - - default: - help(); - return -1; - } - } - - if (optind >= argc) { - help(); - return PX4_ERROR; - } - - const char *verb = argv[optind]; - - if (!strcmp(verb, "start")) { - if (instance) { - warn("AEROFC_ADC was already started"); - return PX4_OK; - } - - for (uint8_t i = 0; i < (sizeof(bus_options) / sizeof(bus_options[0])); i++) { - if (busid != AEROFC_ADC_BUS_ALL && busid != bus_options[i].busid) { - continue; - } - - instance = new AEROFC_ADC(bus_options[i].busnum); - - if (!instance) { - warn("No memory to instance AEROFC_ADC"); - return PX4_ERROR; - } - - if (instance->init() == PX4_OK) { - break; - } - - warn("AEROFC_ADC not found on busnum=%u", bus_options[i].busnum); - delete instance; - instance = nullptr; - } - - if (!instance) { - warn("AEROFC_ADC not found"); - return PX4_ERROR; - } - - } else if (!strcmp(verb, "test")) { - test(); - - } else { - warn("Action not supported"); - help(); - return PX4_ERROR; - } - - return PX4_OK; -} - -AEROFC_ADC::AEROFC_ADC(uint8_t bus) : - I2C("AEROFC_ADC", ADC0_DEVICE_PATH, bus, SLAVE_ADDR, 400000), - _sample{} -{ - _sample.am_channel = 1; - pthread_mutex_init(&_sample_mutex, NULL); -} - -AEROFC_ADC::~AEROFC_ADC() -{ - work_cancel(HPWORK, &_work); -} - -int AEROFC_ADC::init() -{ - int ret = I2C::init(); - - if (ret != PX4_OK) { - return ret; - } - - work_queue(HPWORK, &_work, (worker_t)&AEROFC_ADC::cycle_trampoline, this, - CYCLE_TICKS_DELAY); - - return PX4_OK; -} - -int AEROFC_ADC::probe() -{ - uint8_t buffer[2]; - int ret; - - _retries = 3; - - /* Enable ADC */ - buffer[0] = ADC_ENABLE_REG; - buffer[1] = 0x01; - ret = transfer(buffer, 2, NULL, 0); - - if (ret != PX4_OK) { - goto error; - } - - usleep(10000); - - /* Read ADC value */ - buffer[0] = ADC_CHANNEL_REG; - ret = transfer(buffer, 1, buffer, 2); - - if (ret != PX4_OK) { - goto error; - } - - return PX4_OK; - -error: - return -EIO; -} - -int AEROFC_ADC::ioctl(file *filp, int cmd, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t AEROFC_ADC::read(file *filp, char *buffer, size_t len) -{ - if (len < sizeof(_sample)) { - return -ENOSPC; - } - - if (len > sizeof(_sample)) { - len = sizeof(_sample); - } - - pthread_mutex_lock(&_sample_mutex); - memcpy(buffer, &_sample, len); - pthread_mutex_unlock(&_sample_mutex); - - return len; -} - -void AEROFC_ADC::cycle_trampoline(void *arg) -{ - AEROFC_ADC *dev = reinterpret_cast(arg); - dev->cycle(); -} - -void AEROFC_ADC::cycle() -{ - uint8_t buffer[2]; - int ret; - - buffer[0] = ADC_CHANNEL_REG; - ret = transfer(buffer, 1, buffer, sizeof(buffer)); - - if (ret != PX4_OK) { - warn("Error reading sample"); - return; - } - - pthread_mutex_lock(&_sample_mutex); - - _sample.am_data = (buffer[0] | (buffer[1] << 8)); - - pthread_mutex_unlock(&_sample_mutex); - - work_queue(HPWORK, &_work, (worker_t)&AEROFC_ADC::cycle_trampoline, this, - CYCLE_TICKS_DELAY); -} diff --git a/boards/intel/aerofc-v1/src/board_config.h b/boards/intel/aerofc-v1/src/board_config.h index 0fb14686c7d6..3c0d61c6bf7b 100644 --- a/boards/intel/aerofc-v1/src/board_config.h +++ b/boards/intel/aerofc-v1/src/board_config.h @@ -91,14 +91,6 @@ #define PX4_SPI_BUS_SENSORS 1 #define PX4_SPIDEV_MPU PX4_MK_SPI_SEL(PX4_SPI_BUS_SENSORS, 1) -/* - * STM32 ADC channels - * - * These are the channel numbers of the ADCs of the microcontroller that can - * be used by the PX4 Firmware in the adc driver - */ -#define ADC_CHANNELS 0 - /* * ADC channels: these use the ADC block implemented in the FPGA. There are 5 * channels in the FPGA, but only 1 is phisically connected, that's dedicated diff --git a/boards/nxp/fmuk66-v3/default.cmake b/boards/nxp/fmuk66-v3/default.cmake index 0f24e48135d0..70984baed51d 100644 --- a/boards/nxp/fmuk66-v3/default.cmake +++ b/boards/nxp/fmuk66-v3/default.cmake @@ -15,6 +15,7 @@ px4_add_board( TEL2:/dev/ttyS1 DRIVERS + adc barometer # all available barometer drivers barometer/mpl3115a2 batt_smbus @@ -31,8 +32,6 @@ px4_add_board( imu/mpu9250 irlock kinetis - kinetis/adc - kinetis/tone_alarm lights/blinkm lights/oreoled lights/rgbled @@ -46,6 +45,7 @@ px4_add_board( pwm_out_sim px4fmu rc_input + system_power tap_esc telemetry # all available telemetry drivers #test_ppm # NOT Portable YET diff --git a/boards/nxp/fmuk66-v3/src/board_config.h b/boards/nxp/fmuk66-v3/src/board_config.h index 64a44ad6389d..5cd48aa09304 100644 --- a/boards/nxp/fmuk66-v3/src/board_config.h +++ b/boards/nxp/fmuk66-v3/src/board_config.h @@ -420,8 +420,6 @@ __BEGIN_DECLS #define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_USB_VBUS_VALID)) #define BOARD_ADC_BRICK_VALID (1) #define BOARD_ADC_SERVO_VALID (1) -#define BOARD_ADC_PERIPH_5V_OC (0) -#define BOARD_ADC_HIPOWER_5V_OC (0) #define BOARD_HAS_PWM DIRECT_PWM_OUTPUT_CHANNELS diff --git a/boards/omnibus/f4sd/default.cmake b/boards/omnibus/f4sd/default.cmake index 3a6f44902385..25ef754578d6 100644 --- a/boards/omnibus/f4sd/default.cmake +++ b/boards/omnibus/f4sd/default.cmake @@ -12,6 +12,7 @@ px4_add_board( URT6:/dev/ttyS2 DRIVERS + adc #barometer # all available barometer drivers barometer/bmp280 #batt_smbus @@ -30,19 +31,19 @@ px4_add_board( magnetometer/hmc5883 #mkblctrl optical_flow/px4flow + osd #pca9685 #pwm_input #pwm_out_sim px4fmu rc_input stm32 - stm32/adc #stm32/tone_alarm + system_power #tap_esc #telemetry # all available telemetry drivers telemetry/frsky_telemetry #test_ppm - osd MODULES attitude_estimator_q diff --git a/boards/px4/fmu-v2/default.cmake b/boards/px4/fmu-v2/default.cmake index a73d2fcc6bc8..18b09bcd057f 100644 --- a/boards/px4/fmu-v2/default.cmake +++ b/boards/px4/fmu-v2/default.cmake @@ -20,6 +20,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc #barometer # all available barometer drivers barometer/ms5611 #batt_smbus @@ -56,8 +57,7 @@ px4_add_board( px4io #roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power #tap_esc #telemetry # all available telemetry drivers #test_ppm diff --git a/boards/px4/fmu-v2/fixedwing.cmake b/boards/px4/fmu-v2/fixedwing.cmake index f0a6355cd6bb..ed5550d97b83 100644 --- a/boards/px4/fmu-v2/fixedwing.cmake +++ b/boards/px4/fmu-v2/fixedwing.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc #barometer # all available barometer drivers barometer/ms5611 batt_smbus @@ -36,8 +37,7 @@ px4_add_board( px4fmu px4io stm32 - stm32/adc - stm32/tone_alarm + system_power #telemetry # all available telemetry drivers telemetry/iridiumsbd tone_alarm diff --git a/boards/px4/fmu-v2/lpe.cmake b/boards/px4/fmu-v2/lpe.cmake index 56b916812363..f002e8c13642 100644 --- a/boards/px4/fmu-v2/lpe.cmake +++ b/boards/px4/fmu-v2/lpe.cmake @@ -19,6 +19,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc #barometer # all available barometer drivers barometer/ms5611 #batt_smbus @@ -52,8 +53,7 @@ px4_add_board( px4fmu px4io stm32 - stm32/adc - stm32/tone_alarm + system_power #tap_esc #telemetry # all available telemetry drivers #test_ppm diff --git a/boards/px4/fmu-v2/multicopter.cmake b/boards/px4/fmu-v2/multicopter.cmake index 4fb16fdf4ca5..7183710710e6 100644 --- a/boards/px4/fmu-v2/multicopter.cmake +++ b/boards/px4/fmu-v2/multicopter.cmake @@ -19,6 +19,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc barometer/ms5611 #batt_smbus camera_capture @@ -36,8 +37,7 @@ px4_add_board( px4fmu px4io stm32 - stm32/adc - stm32/tone_alarm + system_power tone_alarm MODULES diff --git a/boards/px4/fmu-v2/rover.cmake b/boards/px4/fmu-v2/rover.cmake index 36290de0cff4..a421285de604 100644 --- a/boards/px4/fmu-v2/rover.cmake +++ b/boards/px4/fmu-v2/rover.cmake @@ -16,6 +16,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc barometer/ms5611 batt_smbus camera_capture @@ -32,8 +33,7 @@ px4_add_board( px4fmu px4io stm32 - stm32/adc - stm32/tone_alarm + system_power tone_alarm MODULES diff --git a/boards/px4/fmu-v2/test.cmake b/boards/px4/fmu-v2/test.cmake index 52f18422298f..121f0372fa96 100644 --- a/boards/px4/fmu-v2/test.cmake +++ b/boards/px4/fmu-v2/test.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc #barometer # all available barometer drivers barometer/ms5611 #batt_smbus @@ -52,8 +53,7 @@ px4_add_board( px4fmu px4io stm32 - stm32/adc - stm32/tone_alarm + system_power #tap_esc #telemetry # all available telemetry drivers #test_ppm diff --git a/boards/px4/fmu-v3/default.cmake b/boards/px4/fmu-v3/default.cmake index 9deece41a488..fb6b09d29577 100644 --- a/boards/px4/fmu-v3/default.cmake +++ b/boards/px4/fmu-v3/default.cmake @@ -20,6 +20,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -55,8 +56,7 @@ px4_add_board( px4io roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v3/rtps.cmake b/boards/px4/fmu-v3/rtps.cmake index 1e4a4a4305be..287c51461165 100644 --- a/boards/px4/fmu-v3/rtps.cmake +++ b/boards/px4/fmu-v3/rtps.cmake @@ -20,6 +20,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -54,8 +55,7 @@ px4_add_board( px4io roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v3/stackcheck.cmake b/boards/px4/fmu-v3/stackcheck.cmake index 9f10338263db..4b2b761c6f54 100644 --- a/boards/px4/fmu-v3/stackcheck.cmake +++ b/boards/px4/fmu-v3/stackcheck.cmake @@ -20,6 +20,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -54,8 +55,7 @@ px4_add_board( px4io roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v4/default.cmake b/boards/px4/fmu-v4/default.cmake index 4ca73855bb3a..b6bfd3478e79 100644 --- a/boards/px4/fmu-v4/default.cmake +++ b/boards/px4/fmu-v4/default.cmake @@ -16,6 +16,7 @@ px4_add_board( TEL2:/dev/ttyS2 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -39,8 +40,7 @@ px4_add_board( px4fmu rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v4/rtps.cmake b/boards/px4/fmu-v4/rtps.cmake index a7f747616dba..ca8d86927fb6 100644 --- a/boards/px4/fmu-v4/rtps.cmake +++ b/boards/px4/fmu-v4/rtps.cmake @@ -16,6 +16,7 @@ px4_add_board( TEL2:/dev/ttyS2 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -41,8 +42,7 @@ px4_add_board( px4fmu rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v4/src/board_config.h b/boards/px4/fmu-v4/src/board_config.h index 86faaeca8c76..2171454632cc 100644 --- a/boards/px4/fmu-v4/src/board_config.h +++ b/boards/px4/fmu-v4/src/board_config.h @@ -346,8 +346,6 @@ #define BOARD_ADC_BRICK_VALID (px4_arch_gpioread(GPIO_VDD_BRICK_VALID)) #define BOARD_ADC_USB_VALID (px4_arch_gpioread(GPIO_VDD_USB_VALID)) #define BOARD_ADC_SERVO_VALID (1) -#define BOARD_ADC_PERIPH_5V_OC (0) -#define BOARD_ADC_HIPOWER_5V_OC (0) #define BOARD_HAS_PWM DIRECT_PWM_OUTPUT_CHANNELS diff --git a/boards/px4/fmu-v4/stackcheck.cmake b/boards/px4/fmu-v4/stackcheck.cmake index 7ea6552244fa..e17bb5660244 100644 --- a/boards/px4/fmu-v4/stackcheck.cmake +++ b/boards/px4/fmu-v4/stackcheck.cmake @@ -16,6 +16,7 @@ px4_add_board( TEL2:/dev/ttyS2 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -39,8 +40,7 @@ px4_add_board( px4fmu rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v4pro/default.cmake b/boards/px4/fmu-v4pro/default.cmake index b8f26718342d..f5332fbca85d 100644 --- a/boards/px4/fmu-v4pro/default.cmake +++ b/boards/px4/fmu-v4pro/default.cmake @@ -19,6 +19,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -53,8 +54,7 @@ px4_add_board( px4io roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v4pro/rtps.cmake b/boards/px4/fmu-v4pro/rtps.cmake index 65dab309769e..5b95da50426a 100644 --- a/boards/px4/fmu-v4pro/rtps.cmake +++ b/boards/px4/fmu-v4pro/rtps.cmake @@ -19,6 +19,7 @@ px4_add_board( TEL4:/dev/ttyS6 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_trigger @@ -52,8 +53,7 @@ px4_add_board( px4io roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v5/default.cmake b/boards/px4/fmu-v5/default.cmake index da482d7fcf21..d667decf110c 100644 --- a/boards/px4/fmu-v5/default.cmake +++ b/boards/px4/fmu-v5/default.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -53,8 +54,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v5/fixedwing.cmake b/boards/px4/fmu-v5/fixedwing.cmake index a5a9a7103c2e..d50ac86b33bf 100644 --- a/boards/px4/fmu-v5/fixedwing.cmake +++ b/boards/px4/fmu-v5/fixedwing.cmake @@ -17,6 +17,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -37,8 +38,7 @@ px4_add_board( px4io rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power telemetry # all available telemetry drivers tone_alarm uavcan diff --git a/boards/px4/fmu-v5/multicopter.cmake b/boards/px4/fmu-v5/multicopter.cmake index a0aa28ce4396..278fa518b7a3 100644 --- a/boards/px4/fmu-v5/multicopter.cmake +++ b/boards/px4/fmu-v5/multicopter.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -41,8 +42,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers tone_alarm diff --git a/boards/px4/fmu-v5/rover.cmake b/boards/px4/fmu-v5/rover.cmake index 03b0fef0eaae..f127e6d8e51a 100644 --- a/boards/px4/fmu-v5/rover.cmake +++ b/boards/px4/fmu-v5/rover.cmake @@ -17,6 +17,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -41,8 +42,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power telemetry # all available telemetry drivers tone_alarm uavcan diff --git a/boards/px4/fmu-v5/rtps.cmake b/boards/px4/fmu-v5/rtps.cmake index 87da8279ef40..7b9db92f0ebd 100644 --- a/boards/px4/fmu-v5/rtps.cmake +++ b/boards/px4/fmu-v5/rtps.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -51,8 +52,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v5/stackcheck.cmake b/boards/px4/fmu-v5/stackcheck.cmake index a93567e1daa7..529042502d3c 100644 --- a/boards/px4/fmu-v5/stackcheck.cmake +++ b/boards/px4/fmu-v5/stackcheck.cmake @@ -18,6 +18,7 @@ px4_add_board( TEL4:/dev/ttyS3 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -51,8 +52,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v5x/default.cmake b/boards/px4/fmu-v5x/default.cmake index 054b543564b6..8b8d98cd32ce 100644 --- a/boards/px4/fmu-v5x/default.cmake +++ b/boards/px4/fmu-v5x/default.cmake @@ -19,6 +19,7 @@ px4_add_board( GPS2:/dev/ttyS0 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -53,8 +54,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v5x/fixedwing.cmake b/boards/px4/fmu-v5x/fixedwing.cmake index 4a6a74e2d5c9..a8f979c29adc 100644 --- a/boards/px4/fmu-v5x/fixedwing.cmake +++ b/boards/px4/fmu-v5x/fixedwing.cmake @@ -18,6 +18,7 @@ px4_add_board( GPS2:/dev/ttyS0 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -47,8 +48,7 @@ px4_add_board( px4io rc_input stm32 - stm32/adc - stm32/tone_alarm + system_power telemetry # all available telemetry drivers tone_alarm uavcan diff --git a/boards/px4/fmu-v5x/multicopter.cmake b/boards/px4/fmu-v5x/multicopter.cmake index 5e37e8cedd9a..37b9ba8112d3 100644 --- a/boards/px4/fmu-v5x/multicopter.cmake +++ b/boards/px4/fmu-v5x/multicopter.cmake @@ -19,6 +19,7 @@ px4_add_board( GPS2:/dev/ttyS0 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -48,8 +49,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers tone_alarm diff --git a/boards/px4/fmu-v5x/rover.cmake b/boards/px4/fmu-v5x/rover.cmake index d695514e9795..067d8c28b453 100644 --- a/boards/px4/fmu-v5x/rover.cmake +++ b/boards/px4/fmu-v5x/rover.cmake @@ -18,6 +18,7 @@ px4_add_board( GPS2:/dev/ttyS0 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -51,8 +52,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power telemetry # all available telemetry drivers tone_alarm uavcan diff --git a/boards/px4/fmu-v5x/rtps.cmake b/boards/px4/fmu-v5x/rtps.cmake index 975527927fdc..4653db2c3184 100644 --- a/boards/px4/fmu-v5x/rtps.cmake +++ b/boards/px4/fmu-v5x/rtps.cmake @@ -19,6 +19,7 @@ px4_add_board( GPS2:/dev/ttyS0 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -53,8 +54,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/fmu-v5x/stackcheck.cmake b/boards/px4/fmu-v5x/stackcheck.cmake index 8e1c010ec9da..76bb45cf7c61 100644 --- a/boards/px4/fmu-v5x/stackcheck.cmake +++ b/boards/px4/fmu-v5x/stackcheck.cmake @@ -19,6 +19,7 @@ px4_add_board( GPS2:/dev/ttyS0 DRIVERS + adc barometer # all available barometer drivers batt_smbus camera_capture @@ -53,8 +54,7 @@ px4_add_board( rc_input roboclaw stm32 - stm32/adc - stm32/tone_alarm + system_power tap_esc telemetry # all available telemetry drivers test_ppm diff --git a/boards/px4/raspberrypi/cross.cmake b/boards/px4/raspberrypi/cross.cmake index 04c5a723a05f..91bfb98ff537 100644 --- a/boards/px4/raspberrypi/cross.cmake +++ b/boards/px4/raspberrypi/cross.cmake @@ -9,6 +9,7 @@ px4_add_board( TESTING DRIVERS + adc #barometer # all available barometer drivers batt_smbus camera_trigger diff --git a/boards/px4/raspberrypi/native.cmake b/boards/px4/raspberrypi/native.cmake index da7bb770907e..b8ce73ca4c5a 100644 --- a/boards/px4/raspberrypi/native.cmake +++ b/boards/px4/raspberrypi/native.cmake @@ -7,6 +7,7 @@ px4_add_board( TESTING DRIVERS + adc #barometer # all available barometer drivers batt_smbus camera_trigger diff --git a/boards/px4/sitl/default.cmake b/boards/px4/sitl/default.cmake index b7faf27a45be..186c39144a61 100644 --- a/boards/px4/sitl/default.cmake +++ b/boards/px4/sitl/default.cmake @@ -17,7 +17,7 @@ px4_add_board( #magnetometer # all available magnetometer drivers pwm_out_sim #telemetry # all available telemetry drivers - sim/tone_alarm + sim tone_alarm #uavcan diff --git a/boards/px4/sitl/rtps.cmake b/boards/px4/sitl/rtps.cmake index 89d84b15636a..6f441cd2b414 100644 --- a/boards/px4/sitl/rtps.cmake +++ b/boards/px4/sitl/rtps.cmake @@ -17,7 +17,7 @@ px4_add_board( #magnetometer # all available magnetometer drivers pwm_out_sim #telemetry # all available telemetry drivers - sim/tone_alarm + sim tone_alarm #uavcan diff --git a/boards/px4/sitl/test.cmake b/boards/px4/sitl/test.cmake index 1e270c641c12..df7d9da076c4 100644 --- a/boards/px4/sitl/test.cmake +++ b/boards/px4/sitl/test.cmake @@ -17,7 +17,7 @@ px4_add_board( #magnetometer # all available magnetometer drivers pwm_out_sim #telemetry # all available telemetry drivers - sim/tone_alarm + sim tone_alarm #uavcan diff --git a/msg/adc_report.msg b/msg/adc_report.msg index b4eca08b43ac..1614a8a29e6d 100644 --- a/msg/adc_report.msg +++ b/msg/adc_report.msg @@ -1,3 +1,8 @@ uint64 timestamp # time since system start (microseconds) + +uint8 MAX_CHANNELS = 12 + int16[12] channel_id # ADC channel IDs, negative for non-existent -float32[12] channel_value # ADC channel value in volt, valid if channel ID is positive +int16[12] channel_value # ADC convert result (2 bytes) + +uint8 channels diff --git a/msg/system_power.msg b/msg/system_power.msg index f0d5d2f86148..bfd8789b7e5f 100644 --- a/msg/system_power.msg +++ b/msg/system_power.msg @@ -1,19 +1,18 @@ uint64 timestamp # time since system start (microseconds) + +bool v5_valid # Sensor 5V rail voltage was read. float32 voltage5v_v # peripheral 5V rail voltage + +bool v3v3_valid # Sensor 3V3 rail voltage was read. float32 voltage3v3_v # Sensor 3V3 rail voltage -uint8 v3v3_valid # Sensor 3V3 rail voltage was read. -uint8 usb_connected # USB is connected when 1 -uint8 brick_valid # brick bits power is good when bit 1 -uint8 usb_valid # USB is valid when 1 -uint8 servo_valid # servo power is good when 1 -uint8 periph_5v_oc # peripheral overcurrent when 1 -uint8 hipower_5v_oc # hi power peripheral overcurrent when 1 -uint8 BRICK1_VALID_SHIFTS=0 -uint8 BRICK1_VALID_MASK=1 -uint8 BRICK2_VALID_SHIFTS=1 -uint8 BRICK2_VALID_MASK=2 -uint8 BRICK3_VALID_SHIFTS=2 -uint8 BRICK3_VALID_MASK=4 -uint8 BRICK4_VALID_SHIFTS=3 -uint8 BRICK4_VALID_MASK=8 +bool usb_connected # USB is connected when true + +bool brick_valid # brick bits power is good when true + +bool usb_valid # USB is valid when true + +bool servo_valid # servo power is good when true + +bool periph_5v_oc # peripheral overcurrent when true +bool hipower_5v_oc # hi power peripheral overcurrent when true diff --git a/src/drivers/adc/ADC.cpp b/src/drivers/adc/ADC.cpp new file mode 100644 index 000000000000..1454bd06c66c --- /dev/null +++ b/src/drivers/adc/ADC.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** + * + * Copyright (C) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include "ADC.hpp" + +static constexpr unsigned ADC_TOTAL_CHANNELS = 32; + +ADC::ADC() : + ScheduledWorkItem(px4::wq_configurations::hp_default), + _sample_perf(perf_alloc(PC_ELAPSED, "adc: sample")) +{ + for (int i = 0; i < adc_report_s::MAX_CHANNELS; i++) { + _samples.channel_id[i] = -1; + } + + uint32_t channels = ADC_CHANNELS; + + // allocate the sample array + _samples.channels = 0; + + for (unsigned i = 0; i < ADC_TOTAL_CHANNELS; i++) { + if (channels & (1 << i)) { + _samples.channels++; + } + } + + // prefill the channel numbers in the sample array + unsigned index = 0; + + for (unsigned i = 0; i < ADC_TOTAL_CHANNELS; i++) { + if (channels & (1 << i)) { + _samples.channel_id[index] = i; + _samples.channel_value[index] = 0; + index++; + } + + if (index >= adc_report_s::MAX_CHANNELS) { + break; + } + } +} + +ADC::~ADC() +{ + ScheduleClear(); + perf_free(_sample_perf); +} + +int +ADC::init() +{ + int rv = board_adc_init(); + + if (rv < 0) { + PX4_DEBUG("sample timeout"); + return rv; + } + + return start(); +} + +int +ADC::start() +{ + // schedule regular updates + ScheduleOnInterval(TICKRATE); + return PX4_OK; +} + +int +ADC::stop() +{ + ScheduleClear(); + return PX4_OK; +} + +void +ADC::Run() +{ + perf_begin(_sample_perf); + + // scan the channel set and sample each + _samples.timestamp = hrt_absolute_time(); + + for (unsigned i = 0; i < _samples.channels; i++) { + + uint16_t result = board_adc_sample(_samples.channel_id[i]); + + if (result == 0xffff) { + _samples.channel_value[i] = 0; + PX4_ERR("sample timeout"); + + } else { + _samples.channel_value[i] = result; + } + } + + _adc_report_pub.publish(_samples); + + perf_end(_sample_perf); +} + +int +ADC::print_status() +{ + PX4_INFO("Running"); + + perf_print_counter(_sample_perf); + + return 0; +} + +int +ADC::custom_command(int argc, char *argv[]) +{ + return print_usage("unknown command"); +} + +int +ADC::task_spawn(int argc, char *argv[]) +{ + ADC *instance = new ADC(); + + if (instance) { + _object.store(instance); + _task_id = task_id_is_work_queue; + + if (instance->init() == PX4_OK) { + return instance->start(); + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + _object.store(nullptr); + _task_id = -1; + + return PX4_ERROR; +} + +int +ADC::print_usage(const char *reason) +{ + if (reason) { + PX4_WARN("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +ADC driver. +)DESCR_STR"); + + PRINT_MODULE_USAGE_COMMAND("start"); + + PRINT_MODULE_USAGE_NAME("adc", "driver"); + + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; +} + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int adc_main(int argc, char *argv[]); + +int adc_main(int argc, char *argv[]) +{ + return ADC::main(argc, argv); +} diff --git a/src/drivers/drv_adc.h b/src/drivers/adc/ADC.hpp similarity index 57% rename from src/drivers/drv_adc.h rename to src/drivers/adc/ADC.hpp index 4fdfa2d6a9e9..8ed2932b947a 100644 --- a/src/drivers/drv_adc.h +++ b/src/drivers/adc/ADC.hpp @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Copyright (C) 2012-2019 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,34 +32,58 @@ ****************************************************************************/ /** - * @file drv_adc.h + * @file ADC.cpp * - * ADC driver interface. + * Driver for the ADC. * - * This defines additional operations over and above the standard NuttX - * ADC API. + * This is a low-rate driver, designed for sampling things like voltages + * and so forth. It avoids the gross complexity of the NuttX ADC driver. */ #pragma once -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -/* Define the PX4 low level format ADC and the maximum - * number of channels that can be returned by a lowlevel - * ADC driver. Drivers may return less than PX4_MAX_ADC_CHANNELS - * but no more than PX4_MAX_ADC_CHANNELS. - * - */ -#define PX4_MAX_ADC_CHANNELS 12 -typedef struct __attribute__((packed)) px4_adc_msg_t { - uint8_t am_channel; /* The 8-bit ADC Channel */ - int32_t am_data; /* ADC convert result (4 bytes) */ -} px4_adc_msg_t; +using namespace time_literals; +class ADC : public ModuleBase, public px4::ScheduledWorkItem +{ +public: + ADC(); + ~ADC() override; -#define ADC0_DEVICE_PATH "/dev/adc0" + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); -/* - * ioctl definitions - */ + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::print_status() */ + int print_status() override; + + int init(); + + int start(); + int stop(); + +private: + void Run() override; + + static constexpr uint32_t TICKRATE{10_ms}; /**< 100Hz base rate */ + + perf_counter_t _sample_perf; + adc_report_s _samples{}; /**< sample buffer */ + + uORB::Publication _adc_report_pub{ORB_ID(adc_report)}; +}; diff --git a/src/drivers/adc/CMakeLists.txt b/src/drivers/adc/CMakeLists.txt new file mode 100644 index 000000000000..6ea48d7d431e --- /dev/null +++ b/src/drivers/adc/CMakeLists.txt @@ -0,0 +1,43 @@ +############################################################################ +# +# Copyright (c) 2019 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +px4_add_module( + MODULE drivers__adc + MAIN adc + SRCS + ADC.cpp + ADC.hpp + DEPENDS + drivers_boards_common_arch + px4_work_queue + ) diff --git a/src/drivers/boards/common/board_common.h b/src/drivers/boards/common/board_common.h index 9dad6e913a67..2a0273252432 100644 --- a/src/drivers/boards/common/board_common.h +++ b/src/drivers/boards/common/board_common.h @@ -995,6 +995,41 @@ int board_shutdown(void); static inline int board_register_power_state_notification_cb(power_button_state_notification_t cb) { return 0; } static inline int board_shutdown(void) { return -EINVAL; } #endif + + +/************************************************************************************ + * Name: board_adc_init + * + * Description: + * boards may provide this function to allow complex version-ing. + * + * Input Parameters: + * None. + * + * Returned Value: + * + * OK, or -1 if the function failed. + */ + +int board_adc_init(void); + + +/************************************************************************************ + * Name: board_adc_sample + * + * Description: + * boards provide this function to allow complex version-ing. + * + * Input Parameters: + * channel - The number of the adc channel to read. + * + * Returned Value: + * The ADC DN read for the channel or 0xffff if there + * is an error reading the channel. + */ + +uint16_t board_adc_sample(unsigned channel); + __END_DECLS /************************************************************************************ diff --git a/src/drivers/boards/common/board_internal_common.h b/src/drivers/boards/common/board_internal_common.h index 47181b473f7f..cb0231044df4 100644 --- a/src/drivers/boards/common/board_internal_common.h +++ b/src/drivers/boards/common/board_internal_common.h @@ -41,42 +41,6 @@ #pragma once -/************************************************************************************ - * Included Files - ************************************************************************************/ - -/************************************************************************************ - * Name: board_adc_init - * - * Description: - * boards may provide this function to allow complex version-ing. - * - * Input Parameters: - * None. - * - * Returned Value: - * - * OK, or -1 if the function failed. - */ - -__EXPORT int board_adc_init(void); - -/************************************************************************************ - * Name: board_adc_sample - * - * Description: - * boards provide this function to allow complex version-ing. - * - * Input Parameters: - * channel - The number of the adc channel to read. - * - * Returned Value: - * The ADC DN read for the channel or 0xffff if there - * is an error reading the channel. - */ - -__EXPORT uint16_t board_adc_sample(unsigned channel); - /************************************************************************************ * Name: board_gpio_init @@ -95,6 +59,7 @@ __EXPORT uint16_t board_adc_sample(unsigned channel); __EXPORT void board_gpio_init(const uint32_t list[], int count); + /************************************************************************************ * Name: board_determine_hw_info * diff --git a/src/drivers/boards/common/kinetis/CMakeLists.txt b/src/drivers/boards/common/kinetis/CMakeLists.txt index ae962c702317..a778122bd3ec 100644 --- a/src/drivers/boards/common/kinetis/CMakeLists.txt +++ b/src/drivers/boards/common/kinetis/CMakeLists.txt @@ -32,6 +32,7 @@ ############################################################################ add_library(drivers_boards_common_arch + board_adc.cpp board_identity.c board_mcu_version.c board_reset.c diff --git a/src/drivers/boards/common/kinetis/board_adc.cpp b/src/drivers/boards/common/kinetis/board_adc.cpp new file mode 100644 index 000000000000..e8d3120cb711 --- /dev/null +++ b/src/drivers/boards/common/kinetis/board_adc.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** + * + * Copyright (C) 2016-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file board_adc.cpp + * + * TODO:This is stubbed out leving the code intact to document the needed + * mechinsm for porting. + * + * Driver for the Kinetis ADC. + * + * This is a low-rate driver, designed for sampling things like voltages + * and so forth. It avoids the gross complexity of the NuttX ADC driver. + */ + +#include + +#include +#include + +#include +#include +#include + +#if defined(ADC_CHANNELS) + +#define _REG(_addr) (*(volatile uint32_t *)(_addr)) + +// ADC register accessors +#define REG(a, _reg) _REG(KINETIS_ADC##a##_BASE + (_reg)) + +#define rSC1A(adc) REG(adc, KINETIS_ADC_SC1A_OFFSET) /* ADC status and control registers 1 */ +#define rSC1B(adc) REG(adc, KINETIS_ADC_SC1B_OFFSET) /* ADC status and control registers 1 */ +#define rCFG1(adc) REG(adc, KINETIS_ADC_CFG1_OFFSET) /* ADC configuration register 1 */ +#define rCFG2(adc) REG(adc, KINETIS_ADC_CFG2_OFFSET) /* Configuration register 2 */ +#define rRA(adc) REG(adc, KINETIS_ADC_RA_OFFSET) /* ADC data result register */ +#define rRB(adc) REG(adc, KINETIS_ADC_RB_OFFSET) /* ADC data result register */ +#define rCV1(adc) REG(adc, KINETIS_ADC_CV1_OFFSET) /* Compare value registers */ +#define rCV2(adc) REG(adc, KINETIS_ADC_CV2_OFFSET) /* Compare value registers */ +#define rSC2(adc) REG(adc, KINETIS_ADC_SC2_OFFSET) /* Status and control register 2 */ +#define rSC3(adc) REG(adc, KINETIS_ADC_SC3_OFFSET) /* Status and control register 3 */ +#define rOFS(adc) REG(adc, KINETIS_ADC_OFS_OFFSET) /* ADC offset correction register */ +#define rPG(adc) REG(adc, KINETIS_ADC_PG_OFFSET) /* ADC plus-side gain register */ +#define rMG(adc) REG(adc, KINETIS_ADC_MG_OFFSET) /* ADC minus-side gain register */ +#define rCLPD(adc) REG(adc, KINETIS_ADC_CLPD_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLPS(adc) REG(adc, KINETIS_ADC_CLPS_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLP4(adc) REG(adc, KINETIS_ADC_CLP4_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLP3(adc) REG(adc, KINETIS_ADC_CLP3_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLP2(adc) REG(adc, KINETIS_ADC_CLP2_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLP1(adc) REG(adc, KINETIS_ADC_CLP1_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLP0(adc) REG(adc, KINETIS_ADC_CLP0_OFFSET) /* ADC plus-side general calibration value register */ +#define rCLMD(adc) REG(adc, KINETIS_ADC_CLMD_OFFSET) /* ADC minus-side general calibration value register */ +#define rCLMS(adc) REG(adc, KINETIS_ADC_CLMS_OFFSET) /* ADC minus-side general calibration value register */ +#define rCLM4(adc) REG(adc, KINETIS_ADC_CLM4_OFFSET) /* ADC minus-side general calibration value register */ +#define rCLM3(adc) REG(adc, KINETIS_ADC_CLM3_OFFSET) /* ADC minus-side general calibration value register */ +#define rCLM2(adc) REG(adc, KINETIS_ADC_CLM2_OFFSET) /* ADC minus-side general calibration value register */ +#define rCLM1(adc) REG(adc, KINETIS_ADC_CLM1_OFFSET) /* ADC minus-side general calibration value register */ +#define rCLM0(adc) REG(adc, KINETIS_ADC_CLM0_OFFSET) /* ADC minus-side general calibration value register */ + +int board_adc_init() +{ + static bool once = false; + + if (!once) { + + once = true; + + // Input is Buss Clock 56 Mhz We will use /8 for 7 Mhz + + irqstate_t flags = px4_enter_critical_section(); + + _REG(KINETIS_SIM_SCGC3) |= SIM_SCGC3_ADC1; + rCFG1(1) = ADC_CFG1_ADICLK_BUSCLK | ADC_CFG1_MODE_1213BIT | ADC_CFG1_ADIV_DIV8; + rCFG2(1) = 0; + rSC2(1) = ADC_SC2_REFSEL_DEFAULT; + + px4_leave_critical_section(flags); + + // Clear the CALF and begin the calibration + rSC3(1) = ADC_SC3_CAL | ADC_SC3_CALF; + + while ((rSC1A(1) & ADC_SC1_COCO) == 0) { + usleep(100); + + if (rSC3(1) & ADC_SC3_CALF) { + return -1; + } + } + + // dummy read to clear COCO of calibration + int32_t r = rRA(1); + + // Check the state of CALF at the end of calibration + if (rSC3(1) & ADC_SC3_CALF) { + return -1; + } + + // Calculate the calibration values for single ended positive + r = rCLP0(1) + rCLP1(1) + rCLP2(1) + rCLP3(1) + rCLP4(1) + rCLPS(1) ; + r = 0x8000U | (r >> 1U); + rPG(1) = r; + + // Calculate the calibration values for double ended Negitive + r = rCLM0(1) + rCLM1(1) + rCLM2(1) + rCLM3(1) + rCLM4(1) + rCLMS(1) ; + r = 0x8000U | (r >> 1U); + rMG(1) = r; + + // kick off a sample and wait for it to complete + const hrt_abstime now = hrt_absolute_time(); + + rSC1A(1) = ADC_SC1_ADCH(ADC_SC1_ADCH_TEMP); + + while (!(rSC1A(1) & ADC_SC1_COCO)) { + // don't wait for more than 500us, since that means something broke - should reset here if we see this + if (hrt_elapsed_time(&now) > 500) { + return -1; + } + + break; + } + } // once + + return OK; +} + +uint16_t board_adc_sample(unsigned channel) +{ + irqstate_t flags = px4_enter_critical_section(); + + // clear any previous COCC + rRA(1); + + // run a single conversion right now - should take about 35 cycles (5 microseconds) max + rSC1A(1) = ADC_SC1_ADCH(channel); + + // wait for the conversion to complete + const hrt_abstime now = hrt_absolute_time(); + + while (!(rSC1A(1) & ADC_SC1_COCO)) { + // don't wait for more than 10us, since that means something broke - should reset here if we see this + if (hrt_elapsed_time(&now) > 10) { + px4_leave_critical_section(flags); + return 0xffff; + } + } + + // read the result and clear EOC + uint16_t result = rRA(1); + + px4_leave_critical_section(flags); + + return result; +} + +#endif // ADC_CHANNELS diff --git a/src/drivers/boards/common/stm32/CMakeLists.txt b/src/drivers/boards/common/stm32/CMakeLists.txt index 5c3dc2b680ae..758cf6c0d39f 100644 --- a/src/drivers/boards/common/stm32/CMakeLists.txt +++ b/src/drivers/boards/common/stm32/CMakeLists.txt @@ -32,12 +32,13 @@ ############################################################################ add_library(drivers_boards_common_arch + board_adc.cpp + board_critmon.c + board_hw_rev_ver.c board_identity.c board_mcu_version.c board_reset.c - board_hw_rev_ver.c - board_critmon.c -) + ) add_dependencies(drivers_boards_common_arch prebuild_targets) target_compile_options(drivers_boards_common_arch PRIVATE -Wno-cast-align) # TODO: fix and enable target_link_libraries(drivers_boards_common_arch PRIVATE nuttx_arch) diff --git a/src/drivers/boards/common/stm32/board_adc.cpp b/src/drivers/boards/common/stm32/board_adc.cpp new file mode 100644 index 000000000000..a5371a5f71ae --- /dev/null +++ b/src/drivers/boards/common/stm32/board_adc.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** + * + * Copyright (C) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file board_adc.cpp + * + * Driver for the STM32 ADC. + * + * This is a low-rate driver, designed for sampling things like voltages + * and so forth. It avoids the gross complexity of the NuttX ADC driver. + */ + +#include + +#include +#include + +#include + +#if defined(ADC_CHANNELS) + +/* + * Register accessors. + * For now, no reason not to just use ADC1. + */ +#define REG(_reg) (*(volatile uint32_t *)(STM32_ADC1_BASE + _reg)) + +#define rSR REG(STM32_ADC_SR_OFFSET) +#define rCR1 REG(STM32_ADC_CR1_OFFSET) +#define rCR2 REG(STM32_ADC_CR2_OFFSET) +#define rSMPR1 REG(STM32_ADC_SMPR1_OFFSET) +#define rSMPR2 REG(STM32_ADC_SMPR2_OFFSET) +#define rSQR1 REG(STM32_ADC_SQR1_OFFSET) +#define rSQR2 REG(STM32_ADC_SQR2_OFFSET) +#define rSQR3 REG(STM32_ADC_SQR3_OFFSET) +#define rDR REG(STM32_ADC_DR_OFFSET) + +#ifdef STM32_ADC_CCR +# define rCCR REG(STM32_ADC_CCR_OFFSET) + +/* Assuming VDC 2.4 - 3.6 */ +#define ADC_MAX_FADC 36000000 + +# if STM32_PCLK2_FREQUENCY/2 <= ADC_MAX_FADC +# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV2 +# elif STM32_PCLK2_FREQUENCY/4 <= ADC_MAX_FADC +# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV4 +# elif STM32_PCLK2_FREQUENCY/6 <= ADC_MAX_FADC +# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV6 +# elif STM32_PCLK2_FREQUENCY/8 <= ADC_MAX_FADC +# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV8 +# else +# error "ADC PCLK2 too high - no divisor found " +# endif +#endif + +int board_adc_init() +{ + static bool once = false; + + if (!once) { + + once = true; + +#ifdef ADC_CR2_CAL + // do calibration if supported + rCR2 |= ADC_CR2_CAL; + usleep(100); + + if (rCR2 & ADC_CR2_CAL) { + return -1; + } + +#endif // ADC_CR2_CAL + + // arbitrarily configure all channels for 55 cycle sample time + rSMPR1 = 0b00000011011011011011011011011011; + rSMPR2 = 0b00011011011011011011011011011011; + + // XXX for F2/4, might want to select 12-bit mode? + rCR1 = 0; + + +#ifdef ADC_CR2_TSVREFE + // enable the temperature sensor / Vrefint channel if supported + rCR2 = ADC_CR2_TSVREFE; +#else + rCR2 = 0; +#endif // ADC_CR2_TSVREFE + + +#ifdef STM32_ADC_CCR + // Soc have CCR +# ifdef ADC_CCR_TSVREFE + // enable temperature sensor in CCR + rCCR = ADC_CCR_TSVREFE | ADC_CCR_ADCPRE_DIV; +# else + rCCR = ADC_CCR_ADCPRE_DIV; +# endif // ADC_CCR_TSVREFE +#endif // STM32_ADC_CCR + + + // configure for a single-channel sequence + rSQR1 = 0; + rSQR2 = 0; + rSQR3 = 0; // will be updated with the channel each tick + + + // power-cycle the ADC and turn it on + rCR2 &= ~ADC_CR2_ADON; + usleep(10); + rCR2 |= ADC_CR2_ADON; + usleep(10); + rCR2 |= ADC_CR2_ADON; + usleep(10); + + + // kick off a sample and wait for it to complete + const hrt_abstime now = hrt_absolute_time(); + rCR2 |= ADC_CR2_SWSTART; + + while (!(rSR & ADC_SR_EOC)) { + // don't wait for more than 500us, since that means something broke - should reset here if we see this + if (hrt_elapsed_time(&now) > 500) { + return -1; + } + } + } // once + + return OK; +} + +uint16_t board_adc_sample(unsigned channel) +{ + irqstate_t flags = px4_enter_critical_section(); + + // clear any previous EOC + if (rSR & ADC_SR_EOC) { + rSR &= ~ADC_SR_EOC; + } + + // run a single conversion right now - should take about 60 cycles (a few microseconds) max + rSQR3 = channel; + rCR2 |= ADC_CR2_SWSTART; + + // wait for the conversion to complete + const hrt_abstime now = hrt_absolute_time(); + + while (!(rSR & ADC_SR_EOC)) { + // don't wait for more than 50us, since that means something broke - should reset here if we see this + if (hrt_elapsed_time(&now) > 50) { + px4_leave_critical_section(flags); + return 0xffff; + } + } + + // read the result and clear EOC + uint16_t result = rDR; + + px4_leave_critical_section(flags); + + return result; +} + +#endif // ADC_CHANNELS diff --git a/src/drivers/boards/common/stm32/board_hw_rev_ver.c b/src/drivers/boards/common/stm32/board_hw_rev_ver.c index bd59bd7c76d2..bec84fcac2b7 100644 --- a/src/drivers/boards/common/stm32/board_hw_rev_ver.c +++ b/src/drivers/boards/common/stm32/board_hw_rev_ver.c @@ -41,7 +41,7 @@ #include #include "board_config.h" -#include "../board_internal_common.h" +#include #include @@ -77,7 +77,6 @@ static char hw_info[] = HW_INFO_INIT; static int dn_to_ordinal(uint16_t dn) { - const struct { uint16_t low; // High(n-1) + 1 uint16_t high; // Average High(n)+Low(n+1) EX. 1356 = AVRG(1331,1382) @@ -196,9 +195,7 @@ static int read_id_dn(int *id, uint32_t gpio_drive, uint32_t gpio_sense, int adc if ((high ^ low) && low == 0) { - /* Yes - Fire up the ADC (it has once control) */ - if (board_adc_init() == OK) { /* Read the value */ diff --git a/src/drivers/kinetis/CMakeLists.txt b/src/drivers/kinetis/CMakeLists.txt index a2fe213eb4d4..deb5c2325b8a 100644 --- a/src/drivers/kinetis/CMakeLists.txt +++ b/src/drivers/kinetis/CMakeLists.txt @@ -33,12 +33,14 @@ add_library(drivers_arch drv_hrt.c + drv_input_capture.c drv_io_timer.c + drv_led_pwm.cpp drv_pwm_servo.c drv_pwm_trigger.c - drv_input_capture.c - drv_led_pwm.cpp ) add_dependencies(drivers_arch prebuild_targets) target_link_libraries(drivers_arch PRIVATE drivers_board) target_compile_options(drivers_arch PRIVATE -Wno-cast-align) # TODO: fix and enable + +add_subdirectory(tone_alarm) diff --git a/src/drivers/kinetis/adc/adc.cpp b/src/drivers/kinetis/adc/adc.cpp deleted file mode 100644 index e1888d431891..000000000000 --- a/src/drivers/kinetis/adc/adc.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2016 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file adc.cpp - * - * TODO:This is stubbed out leving the code intact to document the needed - * mechinsm for porting. - * - * Driver for the Kinetis ADC. - * - * This is a low-rate driver, designed for sampling things like voltages - * and so forth. It avoids the gross complexity of the NuttX ADC driver. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#if defined(ADC_CHANNELS) - -typedef uint32_t adc_chan_t; -#define ADC_TOTAL_CHANNELS 32 - -#define _REG(_addr) (*(volatile uint32_t *)(_addr)) - -/* ADC register accessors */ - -#define REG(a, _reg) _REG(KINETIS_ADC##a##_BASE + (_reg)) - -#define rSC1A(adc) REG(adc, KINETIS_ADC_SC1A_OFFSET) /* ADC status and control registers 1 */ -#define rSC1B(adc) REG(adc, KINETIS_ADC_SC1B_OFFSET) /* ADC status and control registers 1 */ -#define rCFG1(adc) REG(adc, KINETIS_ADC_CFG1_OFFSET) /* ADC configuration register 1 */ -#define rCFG2(adc) REG(adc, KINETIS_ADC_CFG2_OFFSET) /* Configuration register 2 */ -#define rRA(adc) REG(adc, KINETIS_ADC_RA_OFFSET) /* ADC data result register */ -#define rRB(adc) REG(adc, KINETIS_ADC_RB_OFFSET) /* ADC data result register */ -#define rCV1(adc) REG(adc, KINETIS_ADC_CV1_OFFSET) /* Compare value registers */ -#define rCV2(adc) REG(adc, KINETIS_ADC_CV2_OFFSET) /* Compare value registers */ -#define rSC2(adc) REG(adc, KINETIS_ADC_SC2_OFFSET) /* Status and control register 2 */ -#define rSC3(adc) REG(adc, KINETIS_ADC_SC3_OFFSET) /* Status and control register 3 */ -#define rOFS(adc) REG(adc, KINETIS_ADC_OFS_OFFSET) /* ADC offset correction register */ -#define rPG(adc) REG(adc, KINETIS_ADC_PG_OFFSET) /* ADC plus-side gain register */ -#define rMG(adc) REG(adc, KINETIS_ADC_MG_OFFSET) /* ADC minus-side gain register */ -#define rCLPD(adc) REG(adc, KINETIS_ADC_CLPD_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLPS(adc) REG(adc, KINETIS_ADC_CLPS_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLP4(adc) REG(adc, KINETIS_ADC_CLP4_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLP3(adc) REG(adc, KINETIS_ADC_CLP3_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLP2(adc) REG(adc, KINETIS_ADC_CLP2_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLP1(adc) REG(adc, KINETIS_ADC_CLP1_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLP0(adc) REG(adc, KINETIS_ADC_CLP0_OFFSET) /* ADC plus-side general calibration value register */ -#define rCLMD(adc) REG(adc, KINETIS_ADC_CLMD_OFFSET) /* ADC minus-side general calibration value register */ -#define rCLMS(adc) REG(adc, KINETIS_ADC_CLMS_OFFSET) /* ADC minus-side general calibration value register */ -#define rCLM4(adc) REG(adc, KINETIS_ADC_CLM4_OFFSET) /* ADC minus-side general calibration value register */ -#define rCLM3(adc) REG(adc, KINETIS_ADC_CLM3_OFFSET) /* ADC minus-side general calibration value register */ -#define rCLM2(adc) REG(adc, KINETIS_ADC_CLM2_OFFSET) /* ADC minus-side general calibration value register */ -#define rCLM1(adc) REG(adc, KINETIS_ADC_CLM1_OFFSET) /* ADC minus-side general calibration value register */ -#define rCLM0(adc) REG(adc, KINETIS_ADC_CLM0_OFFSET) /* ADC minus-side general calibration value register */ - -class ADC : public device::CDev -{ -public: - ADC(adc_chan_t channels); - ~ADC(); - - virtual int init(); - - virtual int ioctl(file *filp, int cmd, unsigned long arg); - virtual ssize_t read(file *filp, char *buffer, size_t len); - -protected: - virtual int open_first(struct file *filp); - virtual int close_last(struct file *filp); - -private: - static const hrt_abstime _tickrate = 10000; /**< 100Hz base rate */ - - hrt_call _call; - perf_counter_t _sample_perf; - - adc_chan_t _channels; /**< bits set for channels */ - unsigned _channel_count; - adc_msg_s *_samples; /**< sample buffer */ - - orb_advert_t _to_system_power; - orb_advert_t _to_adc_report; - - /** work trampoline */ - static void _tick_trampoline(void *arg); - - /** worker function */ - void _tick(); - - /** - * Sample a single channel and return the measured value. - * - * @param channel The channel to sample. - * @return The sampled value, or 0xffff if - * sampling failed. - */ - uint16_t _sample(unsigned channel); - - // update system_power ORB topic, only on FMUv2 - void update_system_power(hrt_abstime now); - - void update_adc_report(hrt_abstime now); -}; - -ADC::ADC(adc_chan_t channels) : - CDev("adc", ADC0_DEVICE_PATH), - _sample_perf(perf_alloc(PC_ELAPSED, "adc_samples")), - _channels(channels), - _channel_count(0), - _samples(nullptr), - _to_system_power(nullptr), - _to_adc_report(nullptr) -{ - _debug_enabled = true; - - /* always enable the temperature sensor */ - channels |= 1 << (ADC_SC1_ADCH_TEMP >> ADC_SC1_ADCH_SHIFT); - - /* allocate the sample array */ - for (unsigned i = 0; i < ADC_TOTAL_CHANNELS; i++) { - if (channels & (1 << i)) { - _channel_count++; - } - } - - _samples = new adc_msg_s[_channel_count]; - - /* prefill the channel numbers in the sample array */ - - if (_samples != nullptr) { - unsigned index = 0; - - for (unsigned i = 0; i < ADC_TOTAL_CHANNELS; i++) { - if (channels & (1 << i)) { - _samples[index].am_channel = i; - _samples[index].am_data = 0; - index++; - } - } - } -} - -ADC::~ADC() -{ - if (_samples != nullptr) { - delete _samples; - } - - irqstate_t flags = px4_enter_critical_section(); - _REG(KINETIS_SIM_SCGC3) &= ~SIM_SCGC3_ADC1; - px4_leave_critical_section(flags); -} - -int -ADC::init() -{ - /* Input is Buss Clock 56 Mhz We will use /8 for 7 Mhz */ - - irqstate_t flags = px4_enter_critical_section(); - - _REG(KINETIS_SIM_SCGC3) |= SIM_SCGC3_ADC1; - rCFG1(1) = ADC_CFG1_ADICLK_BUSCLK | ADC_CFG1_MODE_1213BIT | ADC_CFG1_ADIV_DIV8; - rCFG2(1) = 0; - rSC2(1) = ADC_SC2_REFSEL_DEFAULT; - - px4_leave_critical_section(flags); - - /* Clear the CALF and begin the calibration */ - - rSC3(1) = ADC_SC3_CAL | ADC_SC3_CALF; - - while ((rSC1A(1) & ADC_SC1_COCO) == 0) { - usleep(100); - - if (rSC3(1) & ADC_SC3_CALF) { - return -1; - } - } - - /* dummy read to clear COCO of calibration */ - - int32_t r = rRA(1); - - /* Check the state of CALF at the end of calibration */ - - if (rSC3(1) & ADC_SC3_CALF) { - return -1; - } - - /* Calculate the calibration values for single ended positive */ - - r = rCLP0(1) + rCLP1(1) + rCLP2(1) + rCLP3(1) + rCLP4(1) + rCLPS(1) ; - r = 0x8000U | (r >> 1U); - rPG(1) = r; - - /* Calculate the calibration values for double ended Negitive */ - - r = rCLM0(1) + rCLM1(1) + rCLM2(1) + rCLM3(1) + rCLM4(1) + rCLMS(1) ; - r = 0x8000U | (r >> 1U); - rMG(1) = r; - - /* kick off a sample and wait for it to complete */ - hrt_abstime now = hrt_absolute_time(); - - rSC1A(1) = ADC_SC1_ADCH(ADC_SC1_ADCH_TEMP); - - while (!(rSC1A(1) & ADC_SC1_COCO)) { - - /* don't wait for more than 500us, since that means something broke - should reset here if we see this */ - if ((hrt_absolute_time() - now) > 500) { - DEVICE_LOG("sample timeout"); - return -1; - } - - break; - } - - - /* create the device node */ - return CDev::init(); -} - -int -ADC::ioctl(file *filp, int cmd, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t -ADC::read(file *filp, char *buffer, size_t len) -{ - const size_t maxsize = sizeof(adc_msg_s) * _channel_count; - - if (len > maxsize) { - len = maxsize; - } - - /* block interrupts while copying samples to avoid racing with an update */ - irqstate_t flags = px4_enter_critical_section(); - memcpy(buffer, _samples, len); - px4_leave_critical_section(flags); - - return len; -} - -int -ADC::open_first(struct file *filp) -{ - /* get fresh data */ - _tick(); - - /* and schedule regular updates */ - hrt_call_every(&_call, _tickrate, _tickrate, _tick_trampoline, this); - - return 0; -} - -int -ADC::close_last(struct file *filp) -{ - hrt_cancel(&_call); - return 0; -} - -void -ADC::_tick_trampoline(void *arg) -{ - (reinterpret_cast(arg))->_tick(); -} - -void -ADC::_tick() -{ - hrt_abstime now = hrt_absolute_time(); - - /* scan the channel set and sample each */ - for (unsigned i = 0; i < _channel_count; i++) { - _samples[i].am_data = _sample(_samples[i].am_channel); - } - - update_adc_report(now); - update_system_power(now); -} - -void -ADC::update_adc_report(hrt_abstime now) -{ - adc_report_s adc = {}; - adc.timestamp = now; - - unsigned max_num = _channel_count; - - if (max_num > (sizeof(adc.channel_id) / sizeof(adc.channel_id[0]))) { - max_num = (sizeof(adc.channel_id) / sizeof(adc.channel_id[0])); - } - - for (unsigned i = 0; i < max_num; i++) { - adc.channel_id[i] = _samples[i].am_channel; - adc.channel_value[i] = _samples[i].am_data * 3.3f / 4096.0f; - } - - int instance; - orb_publish_auto(ORB_ID(adc_report), &_to_adc_report, &adc, &instance, ORB_PRIO_HIGH); -} - -void -ADC::update_system_power(hrt_abstime now) -{ -#if defined (BOARD_ADC_USB_CONNECTED) - system_power_s system_power = {}; - system_power.timestamp = now; - - system_power.voltage5v_v = 0; - -#if defined(ADC_5V_RAIL_SENSE) - - for (unsigned i = 0; i < _channel_count; i++) { - - if (_samples[i].am_channel == ADC_5V_RAIL_SENSE) { - // it is 2:1 scaled - system_power.voltage5v_v = _samples[i].am_data * (6.6f / 4096.0f); - } - } - -#endif - - - /* Note once the board_config.h provides BOARD_ADC_USB_CONNECTED, - * It must provide the true logic GPIO BOARD_ADC_xxxx macros. - */ - // these are not ADC related, but it is convenient to - // publish these to the same topic - - system_power.usb_connected = BOARD_ADC_USB_CONNECTED; - /* If provided used the Valid signal from HW*/ -#if defined(BOARD_ADC_USB_VALID) - system_power.usb_valid = BOARD_ADC_USB_VALID; -#else - /* If not provided then use connected */ - system_power.usb_valid = system_power.usb_connected; -#endif - - system_power.brick_valid = BOARD_ADC_BRICK_VALID; - system_power.servo_valid = BOARD_ADC_SERVO_VALID; - - // OC pins are active low - system_power.periph_5v_oc = BOARD_ADC_PERIPH_5V_OC; - system_power.hipower_5v_oc = BOARD_ADC_HIPOWER_5V_OC; - - /* lazily publish */ - if (_to_system_power != nullptr) { - orb_publish(ORB_ID(system_power), _to_system_power, &system_power); - - } else { - _to_system_power = orb_advertise(ORB_ID(system_power), &system_power); - } - -#endif // BOARD_ADC_USB_CONNECTED -} - -uint16_t -ADC::_sample(unsigned channel) -{ - perf_begin(_sample_perf); - - /* clear any previous COCC */ - uint16_t result = rRA(1); - - /* run a single conversion right now - should take about 35 cycles (5 microseconds) max */ - - rSC1A(1) = ADC_SC1_ADCH(channel); - - /* wait for the conversion to complete */ - hrt_abstime now = hrt_absolute_time(); - - while (!(rSC1A(1) & ADC_SC1_COCO)) { - - /* don't wait for more than 10us, since that means something broke - should reset here if we see this */ - if ((hrt_absolute_time() - now) > 10) { - DEVICE_LOG("sample timeout"); - return 0xffff; - } - } - - /* read the result and clear EOC */ - result = rRA(1); - - perf_end(_sample_perf); - return result; -} - -/* - * Driver 'main' command. - */ -extern "C" __EXPORT int adc_main(int argc, char *argv[]); - -namespace -{ -ADC *g_adc; - -void -test(void) -{ - - int fd = open(ADC0_DEVICE_PATH, O_RDONLY); - - if (fd < 0) { - PX4_ERR("can't open ADC device %d", errno); - exit(1); - } - - for (unsigned i = 0; i < 50; i++) { - adc_msg_s data[ADC_TOTAL_CHANNELS]; - ssize_t count = read(fd, data, sizeof(data)); - - if (count < 0) { - PX4_ERR("read error"); - exit(1); - } - - unsigned channels = count / sizeof(data[0]); - - for (unsigned j = 0; j < channels; j++) { - printf("%d: %u ", data[j].am_channel, data[j].am_data); - } - - printf("\n"); - usleep(500000); - } - - exit(0); -} -} - -int -adc_main(int argc, char *argv[]) -{ - if (g_adc == nullptr) { - /* XXX this hardcodes the default channel set for the board in board_config.h - should be configurable */ - g_adc = new ADC(ADC_CHANNELS); - - if (g_adc == nullptr) { - PX4_ERR("couldn't allocate the ADC driver"); - exit(1); - } - - if (g_adc->init() != OK) { - delete g_adc; - PX4_ERR("ADC init failed"); - exit(1); - } - } - - if (argc > 1) { - if (!strcmp(argv[1], "test")) { - test(); - } - } - - exit(0); -} -#endif diff --git a/src/drivers/kinetis/tone_alarm/CMakeLists.txt b/src/drivers/kinetis/tone_alarm/CMakeLists.txt index 5251d3910a7a..782b20e41af4 100644 --- a/src/drivers/kinetis/tone_alarm/CMakeLists.txt +++ b/src/drivers/kinetis/tone_alarm/CMakeLists.txt @@ -31,6 +31,7 @@ # ############################################################################ -px4_add_library(tone_alarm_interface +add_library(tone_alarm_interface ToneAlarmInterface.cpp ) +target_link_libraries(tone_alarm_interface PRIVATE prebuild_targets) diff --git a/src/drivers/rc_input/RCInput.cpp b/src/drivers/rc_input/RCInput.cpp index 58fe8002d8bf..bf99ceb015dc 100644 --- a/src/drivers/rc_input/RCInput.cpp +++ b/src/drivers/rc_input/RCInput.cpp @@ -371,11 +371,13 @@ RCInput::cycle() for (unsigned i = 0; i < adc_chans; i++) { if (adc.channel_id[i] == ADC_RC_RSSI_CHANNEL) { + float rssi_volts = adc.channel_value[i] * 3.3f / 4096.0f; + if (_analog_rc_rssi_volt < 0.0f) { - _analog_rc_rssi_volt = adc.channel_value[i]; + _analog_rc_rssi_volt = rssi_volts; } - _analog_rc_rssi_volt = _analog_rc_rssi_volt * 0.995f + adc.channel_value[i] * 0.005f; + _analog_rc_rssi_volt = _analog_rc_rssi_volt * 0.995f + rssi_volts * 0.005f; /* only allow this to be used if we see a high RSSI once */ if (_analog_rc_rssi_volt > 2.5f) { diff --git a/src/drivers/rc_input/RCInput.hpp b/src/drivers/rc_input/RCInput.hpp index d8e62d0d50f1..42ca830dcd18 100644 --- a/src/drivers/rc_input/RCInput.hpp +++ b/src/drivers/rc_input/RCInput.hpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include diff --git a/src/drivers/stm32/adc/CMakeLists.txt b/src/drivers/sim/CMakeLists.txt similarity index 96% rename from src/drivers/stm32/adc/CMakeLists.txt rename to src/drivers/sim/CMakeLists.txt index 46f8f429de00..db68be961e35 100644 --- a/src/drivers/stm32/adc/CMakeLists.txt +++ b/src/drivers/sim/CMakeLists.txt @@ -31,9 +31,4 @@ # ############################################################################ -px4_add_module( - MODULE drivers__adc - MAIN adc - SRCS - adc.cpp - ) +add_subdirectory(tone_alarm) diff --git a/src/drivers/sim/tone_alarm/CMakeLists.txt b/src/drivers/sim/tone_alarm/CMakeLists.txt index 5251d3910a7a..782b20e41af4 100644 --- a/src/drivers/sim/tone_alarm/CMakeLists.txt +++ b/src/drivers/sim/tone_alarm/CMakeLists.txt @@ -31,6 +31,7 @@ # ############################################################################ -px4_add_library(tone_alarm_interface +add_library(tone_alarm_interface ToneAlarmInterface.cpp ) +target_link_libraries(tone_alarm_interface PRIVATE prebuild_targets) diff --git a/src/drivers/stm32/CMakeLists.txt b/src/drivers/stm32/CMakeLists.txt index aa444a97dd4f..d24ca0098eab 100644 --- a/src/drivers/stm32/CMakeLists.txt +++ b/src/drivers/stm32/CMakeLists.txt @@ -33,12 +33,14 @@ add_library(drivers_arch drv_hrt.c + drv_input_capture.c drv_io_timer.c + drv_led_pwm.cpp drv_pwm_servo.c drv_pwm_trigger.c - drv_input_capture.c - drv_led_pwm.cpp ) add_dependencies(drivers_arch prebuild_targets) target_link_libraries(drivers_arch PRIVATE drivers_board) target_compile_options(drivers_arch PRIVATE -Wno-cast-align) # TODO: fix and enable + +add_subdirectory(tone_alarm) diff --git a/src/drivers/stm32/adc/adc.cpp b/src/drivers/stm32/adc/adc.cpp deleted file mode 100644 index 7846d9bdbfe9..000000000000 --- a/src/drivers/stm32/adc/adc.cpp +++ /dev/null @@ -1,586 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2012 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file adc.cpp - * - * Driver for the STM32 ADC. - * - * This is a low-rate driver, designed for sampling things like voltages - * and so forth. It avoids the gross complexity of the NuttX ADC driver. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#if defined(ADC_CHANNELS) - -/* - * Register accessors. - * For now, no reason not to just use ADC1. - */ -#define REG(_reg) (*(volatile uint32_t *)(STM32_ADC1_BASE + _reg)) - -#define rSR REG(STM32_ADC_SR_OFFSET) -#define rCR1 REG(STM32_ADC_CR1_OFFSET) -#define rCR2 REG(STM32_ADC_CR2_OFFSET) -#define rSMPR1 REG(STM32_ADC_SMPR1_OFFSET) -#define rSMPR2 REG(STM32_ADC_SMPR2_OFFSET) -#define rJOFR1 REG(STM32_ADC_JOFR1_OFFSET) -#define rJOFR2 REG(STM32_ADC_JOFR2_OFFSET) -#define rJOFR3 REG(STM32_ADC_JOFR3_OFFSET) -#define rJOFR4 REG(STM32_ADC_JOFR4_OFFSET) -#define rHTR REG(STM32_ADC_HTR_OFFSET) -#define rLTR REG(STM32_ADC_LTR_OFFSET) -#define rSQR1 REG(STM32_ADC_SQR1_OFFSET) -#define rSQR2 REG(STM32_ADC_SQR2_OFFSET) -#define rSQR3 REG(STM32_ADC_SQR3_OFFSET) -#define rJSQR REG(STM32_ADC_JSQR_OFFSET) -#define rJDR1 REG(STM32_ADC_JDR1_OFFSET) -#define rJDR2 REG(STM32_ADC_JDR2_OFFSET) -#define rJDR3 REG(STM32_ADC_JDR3_OFFSET) -#define rJDR4 REG(STM32_ADC_JDR4_OFFSET) -#define rDR REG(STM32_ADC_DR_OFFSET) - -#ifdef STM32_ADC_CCR -# define rCCR REG(STM32_ADC_CCR_OFFSET) - -/* Assuming VDC 2.4 - 3.6 */ - -#define ADC_MAX_FADC 36000000 - -# if STM32_PCLK2_FREQUENCY/2 <= ADC_MAX_FADC -# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV2 -# elif STM32_PCLK2_FREQUENCY/4 <= ADC_MAX_FADC -# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV4 -# elif STM32_PCLK2_FREQUENCY/6 <= ADC_MAX_FADC -# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV6 -# elif STM32_PCLK2_FREQUENCY/8 <= ADC_MAX_FADC -# define ADC_CCR_ADCPRE_DIV ADC_CCR_ADCPRE_DIV8 -# else -# error "ADC PCLK2 too high - no divisor found " -# endif -#endif - -class ADC : public cdev::CDev -{ -public: - ADC(uint32_t channels); - ~ADC(); - - virtual int init(); - - virtual int ioctl(file *filp, int cmd, unsigned long arg); - virtual ssize_t read(file *filp, char *buffer, size_t len); - -protected: - virtual int open_first(struct file *filp); - virtual int close_last(struct file *filp); - -private: - static const hrt_abstime _tickrate = 10000; /**< 100Hz base rate */ - - hrt_call _call; - perf_counter_t _sample_perf; - - unsigned _channel_count; - px4_adc_msg_t *_samples; /**< sample buffer */ - - orb_advert_t _to_system_power; - orb_advert_t _to_adc_report; - - /** work trampoline */ - static void _tick_trampoline(void *arg); - - /** worker function */ - void _tick(); - - /** - * Sample a single channel and return the measured value. - * - * @param channel The channel to sample. - * @return The sampled value, or 0xffff if - * sampling failed. - */ - uint16_t _sample(unsigned channel); - - // update system_power ORB topic, only on FMUv2 - void update_system_power(hrt_abstime now); - - void update_adc_report(hrt_abstime now); -}; - -ADC::ADC(uint32_t channels) : - CDev(ADC0_DEVICE_PATH), - _sample_perf(perf_alloc(PC_ELAPSED, "adc_samples")), - _channel_count(0), - _samples(nullptr), - _to_system_power(nullptr), - _to_adc_report(nullptr) -{ - /* always enable the temperature sensor */ - channels |= 1 << 16; - - /* allocate the sample array */ - for (unsigned i = 0; i < 32; i++) { - if (channels & (1 << i)) { - _channel_count++; - } - } - - if (_channel_count > PX4_MAX_ADC_CHANNELS) { - PX4_ERR("PX4_MAX_ADC_CHANNELS is too small:is %d needed:%d", PX4_MAX_ADC_CHANNELS, _channel_count); - } - - _samples = new px4_adc_msg_t[_channel_count]; - - /* prefill the channel numbers in the sample array */ - if (_samples != nullptr) { - unsigned index = 0; - - for (unsigned i = 0; i < 32; i++) { - if (channels & (1 << i)) { - _samples[index].am_channel = i; - _samples[index].am_data = 0; - index++; - } - } - } -} - -ADC::~ADC() -{ - if (_samples != nullptr) { - delete _samples; - } -} - -int board_adc_init() -{ - static bool once = false; - - if (!once) { - - once = true; - - /* do calibration if supported */ -#ifdef ADC_CR2_CAL - rCR2 |= ADC_CR2_CAL; - px4_usleep(100); - - if (rCR2 & ADC_CR2_CAL) { - return -1; - } - -#endif - - /* arbitrarily configure all channels for 55 cycle sample time */ - rSMPR1 = 0b00000011011011011011011011011011; - rSMPR2 = 0b00011011011011011011011011011011; - - /* XXX for F2/4, might want to select 12-bit mode? */ - rCR1 = 0; - - /* enable the temperature sensor / Vrefint channel if supported*/ - rCR2 = -#ifdef ADC_CR2_TSVREFE - /* enable the temperature sensor in CR2 */ - ADC_CR2_TSVREFE | -#endif - 0; - - /* Soc have CCR */ -#ifdef STM32_ADC_CCR -# ifdef ADC_CCR_TSVREFE - /* enable temperature sensor in CCR */ - rCCR = ADC_CCR_TSVREFE | ADC_CCR_ADCPRE_DIV; -# else - rCCR = ADC_CCR_ADCPRE_DIV; -# endif -#endif - - /* configure for a single-channel sequence */ - rSQR1 = 0; - rSQR2 = 0; - rSQR3 = 0; /* will be updated with the channel each tick */ - - /* power-cycle the ADC and turn it on */ - rCR2 &= ~ADC_CR2_ADON; - px4_usleep(10); - rCR2 |= ADC_CR2_ADON; - px4_usleep(10); - rCR2 |= ADC_CR2_ADON; - px4_usleep(10); - - /* kick off a sample and wait for it to complete */ - hrt_abstime now = hrt_absolute_time(); - rCR2 |= ADC_CR2_SWSTART; - - while (!(rSR & ADC_SR_EOC)) { - - /* don't wait for more than 500us, since that means something broke - should reset here if we see this */ - if ((hrt_absolute_time() - now) > 500) { - return -1; - } - } - } // once - - return OK; -} - -int -ADC::init() -{ - int rv = board_adc_init(); - - if (rv < 0) { - PX4_DEBUG("sample timeout"); - return rv; - } - - /* create the device node */ - return CDev::init(); -} - -int -ADC::ioctl(file *filp, int cmd, unsigned long arg) -{ - return -ENOTTY; -} - -ssize_t -ADC::read(file *filp, char *buffer, size_t len) -{ - const size_t maxsize = sizeof(px4_adc_msg_t) * _channel_count; - - if (len > maxsize) { - len = maxsize; - } - - /* block interrupts while copying samples to avoid racing with an update */ - irqstate_t flags = px4_enter_critical_section(); - memcpy(buffer, _samples, len); - px4_leave_critical_section(flags); - - return len; -} - -int -ADC::open_first(struct file *filp) -{ - /* get fresh data */ - _tick(); - - /* and schedule regular updates */ - hrt_call_every(&_call, _tickrate, _tickrate, _tick_trampoline, this); - - return 0; -} - -int -ADC::close_last(struct file *filp) -{ - hrt_cancel(&_call); - return 0; -} - -void -ADC::_tick_trampoline(void *arg) -{ - (reinterpret_cast(arg))->_tick(); -} - -void -ADC::_tick() -{ - hrt_abstime now = hrt_absolute_time(); - - /* scan the channel set and sample each */ - for (unsigned i = 0; i < _channel_count; i++) { - _samples[i].am_data = _sample(_samples[i].am_channel); - } - - update_adc_report(now); - update_system_power(now); -} - -void -ADC::update_adc_report(hrt_abstime now) -{ - adc_report_s adc = {}; - adc.timestamp = now; - - unsigned max_num = _channel_count; - - if (max_num > (sizeof(adc.channel_id) / sizeof(adc.channel_id[0]))) { - max_num = (sizeof(adc.channel_id) / sizeof(adc.channel_id[0])); - } - - for (unsigned i = 0; i < max_num; i++) { - adc.channel_id[i] = _samples[i].am_channel; - adc.channel_value[i] = _samples[i].am_data * 3.3f / 4096.0f; - } - - int instance; - orb_publish_auto(ORB_ID(adc_report), &_to_adc_report, &adc, &instance, ORB_PRIO_HIGH); -} - -void -ADC::update_system_power(hrt_abstime now) -{ -#if defined (BOARD_ADC_USB_CONNECTED) - system_power_s system_power = {}; - system_power.timestamp = now; - - system_power.voltage5v_v = 0; - system_power.voltage3v3_v = 0; - system_power.v3v3_valid = 0; - - /* Assume HW provides only ADC_SCALED_V5_SENSE */ - int cnt = 1; - /* HW provides both ADC_SCALED_V5_SENSE and ADC_SCALED_V3V3_SENSORS_SENSE */ -# if defined(ADC_SCALED_V5_SENSE) && defined(ADC_SCALED_V3V3_SENSORS_SENSE) - cnt++; -# endif - - for (unsigned i = 0; i < _channel_count; i++) { -# if defined(ADC_SCALED_V5_SENSE) - - if (_samples[i].am_channel == ADC_SCALED_V5_SENSE) { - // it is 2:1 scaled - system_power.voltage5v_v = _samples[i].am_data * (ADC_V5_V_FULL_SCALE / 4096.0f); - cnt--; - - } else -# endif -# if defined(ADC_SCALED_V3V3_SENSORS_SENSE) - { - if (_samples[i].am_channel == ADC_SCALED_V3V3_SENSORS_SENSE) { - // it is 2:1 scaled - system_power.voltage3v3_v = _samples[i].am_data * (ADC_3V3_SCALE * (3.3f / 4096.0f)); - system_power.v3v3_valid = 1; - cnt--; - } - } - -# endif - - if (cnt == 0) { - break; - } - } - - /* Note once the board_config.h provides BOARD_ADC_USB_CONNECTED, - * It must provide the true logic GPIO BOARD_ADC_xxxx macros. - */ - // these are not ADC related, but it is convenient to - // publish these to the same topic - - system_power.usb_connected = BOARD_ADC_USB_CONNECTED; - /* If provided used the Valid signal from HW*/ -#if defined(BOARD_ADC_USB_VALID) - system_power.usb_valid = BOARD_ADC_USB_VALID; -#else - /* If not provided then use connected */ - system_power.usb_valid = system_power.usb_connected; -#endif - - /* The valid signals (HW dependent) are associated with each brick */ -#if !defined(BOARD_NUMBER_DIGITAL_BRICKS) - bool valid_chan[BOARD_NUMBER_BRICKS] = BOARD_BRICK_VALID_LIST; - system_power.brick_valid = 0; - - for (int b = 0; b < BOARD_NUMBER_BRICKS; b++) { - system_power.brick_valid |= valid_chan[b] ? 1 << b : 0; - } - -#endif - - system_power.servo_valid = BOARD_ADC_SERVO_VALID; - -#ifdef BOARD_ADC_PERIPH_5V_OC - // OC pins are active low - system_power.periph_5v_oc = BOARD_ADC_PERIPH_5V_OC; -#else - system_power.periph_5v_oc = 0; -#endif -#ifdef BOARD_ADC_HIPOWER_5V_OC - system_power.hipower_5v_oc = BOARD_ADC_HIPOWER_5V_OC; -#else - system_power.hipower_5v_oc = 0; -#endif - - /* lazily publish */ - if (_to_system_power != nullptr) { - orb_publish(ORB_ID(system_power), _to_system_power, &system_power); - - } else { - _to_system_power = orb_advertise(ORB_ID(system_power), &system_power); - } - -#endif // BOARD_ADC_USB_CONNECTED -} - -uint16_t board_adc_sample(unsigned channel) -{ - /* clear any previous EOC */ - - if (rSR & ADC_SR_EOC) { - rSR &= ~ADC_SR_EOC; - } - - /* run a single conversion right now - should take about 60 cycles (a few microseconds) max */ - rSQR3 = channel; - rCR2 |= ADC_CR2_SWSTART; - - /* wait for the conversion to complete */ - hrt_abstime now = hrt_absolute_time(); - - while (!(rSR & ADC_SR_EOC)) { - - /* don't wait for more than 50us, since that means something broke - should reset here if we see this */ - if ((hrt_absolute_time() - now) > 50) { - return 0xffff; - } - } - - /* read the result and clear EOC */ - uint16_t result = rDR; - return result; -} - -uint16_t -ADC::_sample(unsigned channel) -{ - perf_begin(_sample_perf); - uint16_t result = board_adc_sample(channel); - - if (result == 0xffff) { - PX4_ERR("sample timeout"); - } - - perf_end(_sample_perf); - return result; -} - -/* - * Driver 'main' command. - */ -extern "C" __EXPORT int adc_main(int argc, char *argv[]); - -namespace -{ -ADC *g_adc; - -void -test(void) -{ - - int fd = open(ADC0_DEVICE_PATH, O_RDONLY); - - if (fd < 0) { - err(1, "can't open ADC device"); - } - - for (unsigned i = 0; i < 50; i++) { - px4_adc_msg_t data[PX4_MAX_ADC_CHANNELS]; - ssize_t count = read(fd, data, sizeof(data)); - - if (count < 0) { - errx(1, "read error"); - } - - unsigned channels = count / sizeof(data[0]); - - for (unsigned j = 0; j < channels; j++) { - printf("%d: %u ", data[j].am_channel, data[j].am_data); - } - - printf("\n"); - px4_usleep(500000); - } - - exit(0); -} -} - -int -adc_main(int argc, char *argv[]) -{ - if (g_adc == nullptr) { - /* XXX this hardcodes the default channel set for the board in board_config.h - should be configurable */ - g_adc = new ADC(ADC_CHANNELS); - - if (g_adc == nullptr) { - errx(1, "couldn't allocate the ADC driver"); - } - - if (g_adc->init() != OK) { - delete g_adc; - errx(1, "ADC init failed"); - } - } - - if (argc > 1) { - if (!strcmp(argv[1], "test")) { - test(); - } - } - - exit(0); -} -#endif diff --git a/src/drivers/stm32/tone_alarm/CMakeLists.txt b/src/drivers/stm32/tone_alarm/CMakeLists.txt index 5251d3910a7a..782b20e41af4 100644 --- a/src/drivers/stm32/tone_alarm/CMakeLists.txt +++ b/src/drivers/stm32/tone_alarm/CMakeLists.txt @@ -31,6 +31,7 @@ # ############################################################################ -px4_add_library(tone_alarm_interface +add_library(tone_alarm_interface ToneAlarmInterface.cpp ) +target_link_libraries(tone_alarm_interface PRIVATE prebuild_targets) diff --git a/src/drivers/stm32/tone_alarm/ToneAlarmInterfacePWM.cpp b/src/drivers/stm32/tone_alarm/ToneAlarmInterfacePWM.cpp index eb72700a0adc..8191580d4dc9 100644 --- a/src/drivers/stm32/tone_alarm/ToneAlarmInterfacePWM.cpp +++ b/src/drivers/stm32/tone_alarm/ToneAlarmInterfacePWM.cpp @@ -36,6 +36,8 @@ #include #include +#ifdef TONE_ALARM_TIMER + /* Check that tone alarm and HRT timers are different */ #if defined(TONE_ALARM_TIMER) && defined(HRT_TIMER) # if TONE_ALARM_TIMER == HRT_TIMER @@ -284,3 +286,5 @@ void ToneAlarmInterface::stop_note() // Ensure the GPIO is not driving the speaker. px4_arch_configgpio(GPIO_TONE_ALARM_IDLE); } + +#endif // TONE_ALARM_TIMER diff --git a/src/drivers/system_power/CMakeLists.txt b/src/drivers/system_power/CMakeLists.txt new file mode 100644 index 000000000000..ce9780845227 --- /dev/null +++ b/src/drivers/system_power/CMakeLists.txt @@ -0,0 +1,41 @@ +############################################################################ +# +# Copyright (c) 2019 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +px4_add_module( + MODULE drivers__system_power + MAIN system_power + SRCS + SystemPower.cpp + DEPENDS + px4_work_queue + ) diff --git a/src/drivers/system_power/SystemPower.cpp b/src/drivers/system_power/SystemPower.cpp new file mode 100644 index 000000000000..f1fa09fa1d35 --- /dev/null +++ b/src/drivers/system_power/SystemPower.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** + * + * Copyright (C) 2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include "SystemPower.hpp" + +SystemPower::SystemPower() : + ScheduledWorkItem(px4::wq_configurations::hp_default), + _sample_perf(perf_alloc(PC_ELAPSED, "system_power: sample")) +{ +} + +SystemPower::~SystemPower() +{ + ScheduleClear(); + perf_free(_sample_perf); +} + +int +SystemPower::init() +{ + return start(); +} + +int +SystemPower::start() +{ + // schedule regular updates + ScheduleOnInterval(TICKRATE); + return PX4_OK; +} + +int +SystemPower::stop() +{ + ScheduleClear(); + return PX4_OK; +} + +void +SystemPower::Run() +{ + perf_begin(_sample_perf); + + adc_report_s adc_report{}; + + if (_adc_report_sub.update(&adc_report)) { + system_power_s system_power {}; + + for (unsigned i = 0; i < adc_report_s::MAX_CHANNELS; i++) { + +#if defined(ADC_SCALED_V5_SENSE) + + if (adc_report.channel_id[i] == ADC_SCALED_V5_SENSE) { + // it is 2:1 scaled + system_power.v5_valid = true; + system_power.voltage5v_v = adc_report.channel_value[i] * (ADC_V5_V_FULL_SCALE / 4096.0f); + } + +#endif // ADC_SCALED_V5_SENSE + +#if defined(ADC_SCALED_V3V3_SENSORS_SENSE) + + if (adc_report.channel_id[i] == ADC_SCALED_V3V3_SENSORS_SENSE) { + // it is 2:1 scaled + system_power.v3v3_valid = true; + system_power.voltage3v3_v = adc_report.channel_value[i] * (ADC_3V3_SCALE * (3.3f / 4096.0f)); + } + +#endif // ADC_SCALED_V3V3_SENSORS_SENSE + } + +#if defined (BOARD_ADC_USB_CONNECTED) + /* Note once the board_config.h provides BOARD_ADC_USB_CONNECTED, + * It must provide the true logic GPIO BOARD_ADC_xxxx macros. + */ + + system_power.usb_connected = BOARD_ADC_USB_CONNECTED; + + +#if defined(BOARD_ADC_USB_VALID) + // If provided used the Valid signal from HW + system_power.usb_valid = BOARD_ADC_USB_VALID; +#else + // If not provided then use connected + system_power.usb_valid = system_power.usb_connected; +#endif // BOARD_ADC_USB_VALID + + +#if !defined(BOARD_NUMBER_DIGITAL_BRICKS) + // The valid signals (HW dependent) are associated with each brick + bool valid_chan[BOARD_NUMBER_BRICKS] = BOARD_BRICK_VALID_LIST; + + for (int b = 0; b < BOARD_NUMBER_BRICKS; b++) { + system_power.brick_valid |= valid_chan[b] ? 1 << b : 0; + } + +#endif // BOARD_NUMBER_DIGITAL_BRICKS + + +#ifdef BOARD_ADC_SERVO_VALID + system_power.servo_valid = BOARD_ADC_SERVO_VALID; +#endif // BOARD_ADC_SERVO_VALID + + +#ifdef BOARD_ADC_PERIPH_5V_OC + // OC pins are active low + system_power.periph_5v_oc = BOARD_ADC_PERIPH_5V_OC; +#endif // BOARD_ADC_PERIPH_5V_OC + + +#ifdef BOARD_ADC_HIPOWER_5V_OC + system_power.hipower_5v_oc = BOARD_ADC_HIPOWER_5V_OC; +#endif // BOARD_ADC_HIPOWER_5V_OC + + +#endif // BOARD_ADC_USB_CONNECTED + + system_power.timestamp = hrt_absolute_time(); + _system_power_pub.publish(system_power); + } + + perf_end(_sample_perf); +} + +int +SystemPower::print_status() +{ + PX4_INFO("Running"); + + perf_print_counter(_sample_perf); + + return 0; +} + +int +SystemPower::custom_command(int argc, char *argv[]) +{ + return print_usage("unknown command"); +} + +int +SystemPower::task_spawn(int argc, char *argv[]) +{ + SystemPower *instance = new SystemPower(); + + if (instance) { + _object.store(instance); + _task_id = task_id_is_work_queue; + + if (instance->init() == PX4_OK) { + return instance->start(); + } + + } else { + PX4_ERR("alloc failed"); + } + + delete instance; + _object.store(nullptr); + _task_id = -1; + + return PX4_ERROR; +} + +int +SystemPower::print_usage(const char *reason) +{ + if (reason) { + PX4_WARN("%s\n", reason); + } + + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +### Description +ADC driver. +)DESCR_STR"); + + PRINT_MODULE_USAGE_COMMAND("start"); + + PRINT_MODULE_USAGE_NAME("system_power", "driver"); + + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; +} + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int system_power_main(int argc, char *argv[]); + +int system_power_main(int argc, char *argv[]) +{ + return SystemPower::main(argc, argv); +} diff --git a/src/systemcmds/tests/test_adc.c b/src/drivers/system_power/SystemPower.hpp similarity index 60% rename from src/systemcmds/tests/test_adc.c rename to src/drivers/system_power/SystemPower.hpp index 99252a2dd4f8..f6a1971c177c 100644 --- a/src/systemcmds/tests/test_adc.c +++ b/src/drivers/system_power/SystemPower.hpp @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Copyright (C) 2019 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,62 +31,52 @@ * ****************************************************************************/ -/** - * @file test_adc.c - * Test for the analog to digital converter. - */ +#pragma once -#include +#include +#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include -#include +using namespace time_literals; -#include -#include -#include -#include -#include - -#include "tests_main.h" - -#include - -int test_adc(int argc, char *argv[]) +class SystemPower : public ModuleBase, public px4::ScheduledWorkItem { - int fd = px4_open(ADC0_DEVICE_PATH, O_RDONLY); +public: + SystemPower(); + ~SystemPower() override; - if (fd < 0) { - PX4_ERR("ERROR: can't open ADC device"); - return 1; - } + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); - for (unsigned i = 0; i < 5; i++) { - /* make space for a maximum number of channels */ - px4_adc_msg_t data[PX4_MAX_ADC_CHANNELS]; - /* read all channels available */ - ssize_t count = px4_read(fd, data, sizeof(data)); + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); - if (count < 0) { - goto errout_with_dev; - } + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); - unsigned channels = count / sizeof(data[0]); + /** @see ModuleBase::print_status() */ + int print_status() override; - for (unsigned j = 0; j < channels; j++) { - printf("%d: %u ", data[j].am_channel, data[j].am_data); - } + int init(); - printf("\n"); - px4_usleep(150000); - } + int start(); + int stop(); - printf("\t ADC test successful.\n"); +private: + void Run() override; -errout_with_dev: + static constexpr uint32_t TICKRATE{10_ms}; /**< 100Hz base rate */ - if (fd != 0) { px4_close(fd); } + perf_counter_t _sample_perf; - return OK; -} + uORB::Subscription _adc_report_sub{ORB_ID(adc_report)}; + uORB::Publication _system_power_pub{ORB_ID(system_power)}; +}; diff --git a/src/modules/sensors/sensors.cpp b/src/modules/sensors/sensors.cpp index 4f838af8514f..3efd08ff11d4 100644 --- a/src/modules/sensors/sensors.cpp +++ b/src/modules/sensors/sensors.cpp @@ -64,7 +64,6 @@ #include #include -#include #include #include @@ -75,7 +74,8 @@ #include -#include +#include +#include #include #include #include @@ -156,14 +156,10 @@ class Sensors : public ModuleBase, public ModuleParams int print_status() override; private: - DevHandle _h_adc; /**< ADC driver handle */ - - hrt_abstime _last_adc{0}; /**< last time we took input from the ADC */ - - const bool _hil_enabled; /**< if true, HIL is active */ bool _armed{false}; /**< arming status of the vehicle */ uORB::Subscription _actuator_ctrl_0_sub{ORB_ID(actuator_controls_0)}; /**< attitude controls sub */ + uORB::Subscription _adc_sub{ORB_ID(adc_report)}; /**< ADC report sub */ uORB::Subscription _diff_pres_sub{ORB_ID(differential_pressure)}; /**< raw differential pressure subscription */ uORB::Subscription _vcontrol_mode_sub{ORB_ID(vehicle_control_mode)}; /**< vehicle control mode subscription */ uORB::Subscription _params_sub{ORB_ID(parameter_update)}; /**< notification of parameter updates */ @@ -207,11 +203,6 @@ class Sensors : public ModuleBase, public ModuleParams */ int parameters_update(); - /** - * Do adc-related initialisation. - */ - int adc_init(); - /** * Poll the differential pressure sensor for updated data. * @@ -236,7 +227,6 @@ class Sensors : public ModuleBase, public ModuleParams Sensors::Sensors(bool hil_enabled) : ModuleParams(nullptr), - _hil_enabled(hil_enabled), _loop_perf(perf_alloc(PC_ELAPSED, "sensors")), _rc_update(_parameters), _voted_sensors_update(_parameters, hil_enabled) @@ -275,31 +265,17 @@ Sensors::parameters_update() return ret; } - -int -Sensors::adc_init() -{ - DevMgr::getHandle(ADC0_DEVICE_PATH, _h_adc); - - if (!_h_adc.isValid()) { - PX4_ERR("no ADC found: %s (%d)", ADC0_DEVICE_PATH, _h_adc.getError()); - return PX4_ERROR; - } - - return OK; -} - void Sensors::diff_pres_poll(const vehicle_air_data_s &raw) { - differential_pressure_s diff_pres{}; + differential_pressure_s diff_pres; if (_diff_pres_sub.update(&diff_pres)) { float air_temperature_celsius = (diff_pres.temperature > -300.0f) ? diff_pres.temperature : (raw.baro_temp_celcius - PCB_TEMP_ESTIMATE_DEG); - airspeed_s airspeed; + airspeed_s airspeed{}; airspeed.timestamp = diff_pres.timestamp; /* push data into validator */ @@ -382,19 +358,9 @@ Sensors::parameter_update_poll(bool forced) void Sensors::adc_poll() { - /* only read if not in HIL mode */ - if (_hil_enabled) { - return; - } + adc_report_s adc_report; - hrt_abstime t = hrt_absolute_time(); - - /* rate limit to 100 Hz */ - if (t - _last_adc >= 10000) { - /* make space for a maximum of twelve channels (to ensure reading all channels at once) */ - px4_adc_msg_t buf_adc[PX4_MAX_ADC_CHANNELS]; - /* read all channels available */ - int ret = _h_adc.read(&buf_adc, sizeof(buf_adc)); + if (_adc_sub.update(&adc_report)) { #if BOARD_NUMBER_BRICKS > 0 //todo:abosorb into new class Power @@ -415,7 +381,7 @@ Sensors::adc_poll() bat_voltage_v_chan[0] = _parameters.battery_adc_channel; } -#endif +#endif // BOARD_NUMBER_DIGITAL_BRICKS /* The valid signals (HW dependent) are associated with each brick */ bool valid_chan[BOARD_NUMBER_BRICKS] = BOARD_BRICK_VALID_LIST; @@ -433,135 +399,126 @@ Sensors::adc_poll() #endif /* BOARD_NUMBER_BRICKS > 0 */ - if (ret >= (int)sizeof(buf_adc[0])) { - - /* Read add channels we got */ - for (unsigned i = 0; i < ret / sizeof(buf_adc[0]); i++) { + /* Read add channels we got */ + for (unsigned i = 0; i < adc_report.channels; i++) { #ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL - if (ADC_AIRSPEED_VOLTAGE_CHANNEL == buf_adc[i].am_channel) { + if (ADC_AIRSPEED_VOLTAGE_CHANNEL == adc_report.channel_id[i]) { - /* calculate airspeed, raw is the difference from */ - const float voltage = (float)(buf_adc[i].am_data) * 3.3f / 4096.0f * 2.0f; // V_ref/4096 * (voltage divider factor) + /* calculate airspeed, raw is the difference from */ + const float voltage = (float)(adc_report.channel_value[i]) * 3.3f / 4096.0f * + 2.0f; // V_ref/4096 * (voltage divider factor) - /** - * The voltage divider pulls the signal down, only act on - * a valid voltage from a connected sensor. Also assume a non- - * zero offset from the sensor if its connected. - */ - if (voltage > 0.4f && (_parameters.diff_pres_analog_scale > 0.0f)) { + /** + * The voltage divider pulls the signal down, only act on + * a valid voltage from a connected sensor. Also assume a non- + * zero offset from the sensor if its connected. + */ + if (voltage > 0.4f && (_parameters.diff_pres_analog_scale > 0.0f)) { - const float diff_pres_pa_raw = voltage * _parameters.diff_pres_analog_scale - _parameters.diff_pres_offset_pa; + const float diff_pres_pa_raw = voltage * _parameters.diff_pres_analog_scale - _parameters.diff_pres_offset_pa; - _diff_pres.timestamp = t; - _diff_pres.differential_pressure_raw_pa = diff_pres_pa_raw; - _diff_pres.differential_pressure_filtered_pa = (_diff_pres.differential_pressure_filtered_pa * 0.9f) + - (diff_pres_pa_raw * 0.1f); - _diff_pres.temperature = -1000.0f; + _diff_pres.timestamp = adc_report.timestamp; + _diff_pres.differential_pressure_raw_pa = diff_pres_pa_raw; + _diff_pres.differential_pressure_filtered_pa = (_diff_pres.differential_pressure_filtered_pa * 0.9f) + + (diff_pres_pa_raw * 0.1f); + _diff_pres.temperature = -1000.0f; - int instance; - orb_publish_auto(ORB_ID(differential_pressure), &_diff_pres_pub, &_diff_pres, &instance, ORB_PRIO_DEFAULT); - } + int instance; + orb_publish_auto(ORB_ID(differential_pressure), &_diff_pres_pub, &_diff_pres, &instance, ORB_PRIO_DEFAULT); + } - } else + } else #endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */ - { + { #if BOARD_NUMBER_BRICKS > 0 - for (int b = 0; b < BOARD_NUMBER_BRICKS; b++) { - - /* Once we have subscriptions, Do this once for the lowest (highest priority - * supply on power controller) that is valid. - */ - if (_battery_pub[b] != nullptr && selected_source < 0 && valid_chan[b]) { - /* Indicate the lowest brick (highest priority supply on power controller) - * that is valid as the one that is the selected source for the - * VDD_5V_IN - */ - selected_source = b; + for (int b = 0; b < BOARD_NUMBER_BRICKS; b++) { -# if BOARD_NUMBER_BRICKS > 1 + /* Once we have subscriptions, Do this once for the lowest (highest priority + * supply on power controller) that is valid. + */ + if (_battery_pub[b] != nullptr && selected_source < 0 && valid_chan[b]) { + /* Indicate the lowest brick (highest priority supply on power controller) + * that is valid as the one that is the selected source for the + * VDD_5V_IN + */ + selected_source = b; - /* Move the selected_source to instance 0 */ - if (_battery_pub_intance0ndx != selected_source) { +#if BOARD_NUMBER_BRICKS > 1 - orb_advert_t tmp_h = _battery_pub[_battery_pub_intance0ndx]; - _battery_pub[_battery_pub_intance0ndx] = _battery_pub[selected_source]; - _battery_pub[selected_source] = tmp_h; - _battery_pub_intance0ndx = selected_source; - } + /* Move the selected_source to instance 0 */ + if (_battery_pub_intance0ndx != selected_source) { -# endif /* BOARD_NUMBER_BRICKS > 1 */ + orb_advert_t tmp_h = _battery_pub[_battery_pub_intance0ndx]; + _battery_pub[_battery_pub_intance0ndx] = _battery_pub[selected_source]; + _battery_pub[selected_source] = tmp_h; + _battery_pub_intance0ndx = selected_source; } +#endif /* BOARD_NUMBER_BRICKS > 1 */ + } + # if !defined(BOARD_NUMBER_DIGITAL_BRICKS) - // todo:per brick scaling - /* look for specific channels and process the raw voltage to measurement data */ - if (bat_voltage_v_chan[b] == buf_adc[i].am_channel) { - /* Voltage in volts */ - bat_voltage_v[b] = (buf_adc[i].am_data * _parameters.battery_voltage_scaling) * _parameters.battery_v_div; + // todo:per brick scaling + /* look for specific channels and process the raw voltage to measurement data */ + if (bat_voltage_v_chan[b] == adc_report.channel_id[i]) { + /* Voltage in volts */ + bat_voltage_v[b] = (adc_report.channel_value[i] * _parameters.battery_voltage_scaling) * _parameters.battery_v_div; - } else if (bat_voltage_i_chan[b] == buf_adc[i].am_channel) { - bat_current_a[b] = ((buf_adc[i].am_data * _parameters.battery_current_scaling) - - _parameters.battery_current_offset) * _parameters.battery_a_per_v; - } + } else if (bat_voltage_i_chan[b] == adc_report.channel_id[i]) { + bat_current_a[b] = ((adc_report.channel_value[i] * _parameters.battery_current_scaling) + - _parameters.battery_current_offset) * _parameters.battery_a_per_v; -# endif /* !defined(BOARD_NUMBER_DIGITAL_BRICKS) */ } -#endif /* BOARD_NUMBER_BRICKS > 0 */ +# endif /* !defined(BOARD_NUMBER_DIGITAL_BRICKS) */ + } + +#endif /* BOARD_NUMBER_BRICKS > 0 */ } + } #if BOARD_NUMBER_BRICKS > 0 - if (_parameters.battery_source == 0) { + if (_parameters.battery_source == 0) { - for (int b = 0; b < BOARD_NUMBER_BRICKS; b++) { + for (int b = 0; b < BOARD_NUMBER_BRICKS; b++) { - /* Consider the brick connected if there is a voltage */ - bool connected = bat_voltage_v[b] > BOARD_ADC_OPEN_CIRCUIT_V; + /* Consider the brick connected if there is a voltage */ + bool connected = bat_voltage_v[b] > BOARD_ADC_OPEN_CIRCUIT_V; - /* In the case where the BOARD_ADC_OPEN_CIRCUIT_V is - * greater than the BOARD_VALID_UV let the HW qualify that it - * is connected. - */ - if (BOARD_ADC_OPEN_CIRCUIT_V > BOARD_VALID_UV) { - connected &= valid_chan[b]; - } + /* In the case where the BOARD_ADC_OPEN_CIRCUIT_V is + * greater than the BOARD_VALID_UV let the HW qualify that it + * is connected. + */ + if (BOARD_ADC_OPEN_CIRCUIT_V > BOARD_VALID_UV) { + connected &= valid_chan[b]; + } - actuator_controls_s ctrl{}; - _actuator_ctrl_0_sub.copy(&ctrl); + actuator_controls_s ctrl{}; + _actuator_ctrl_0_sub.copy(&ctrl); - battery_status_s battery_status{}; - _battery[b].updateBatteryStatus(t, bat_voltage_v[b], bat_current_a[b], - connected, selected_source == b, b, - ctrl.control[actuator_controls_s::INDEX_THROTTLE], - _armed, &battery_status); - int instance; - orb_publish_auto(ORB_ID(battery_status), &_battery_pub[b], &battery_status, &instance, ORB_PRIO_DEFAULT); - } + battery_status_s battery_status; + _battery[b].updateBatteryStatus(adc_report.timestamp, bat_voltage_v[b], bat_current_a[b], + connected, selected_source == b, b, + ctrl.control[actuator_controls_s::INDEX_THROTTLE], + _armed, &battery_status); + int instance; + orb_publish_auto(ORB_ID(battery_status), &_battery_pub[b], &battery_status, &instance, ORB_PRIO_DEFAULT); } + } #endif /* BOARD_NUMBER_BRICKS > 0 */ - - _last_adc = t; - } } } - void Sensors::run() { - if (!_hil_enabled) { -#if !defined(__PX4_QURT) && BOARD_NUMBER_BRICKS > 0 - adc_init(); -#endif - } - sensor_combined_s raw = {}; sensor_preflight_s preflt = {}; vehicle_air_data_s airdata = {}; diff --git a/src/systemcmds/tests/CMakeLists.txt b/src/systemcmds/tests/CMakeLists.txt index 3c33ef4db0ce..d521b4842176 100644 --- a/src/systemcmds/tests/CMakeLists.txt +++ b/src/systemcmds/tests/CMakeLists.txt @@ -32,7 +32,6 @@ ############################################################################ set(srcs - test_adc.c test_autodeclination.cpp test_bezierQuad.cpp test_bson.cpp @@ -46,7 +45,6 @@ set(srcs test_hrt.cpp test_int.cpp test_IntrusiveQueue.cpp - test_jig_voltages.c test_led.c test_List.cpp test_mathlib.cpp diff --git a/src/systemcmds/tests/test_jig_voltages.c b/src/systemcmds/tests/test_jig_voltages.c deleted file mode 100644 index 80b386c3db36..000000000000 --- a/src/systemcmds/tests/test_jig_voltages.c +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2012-2019 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file test_jig_voltages.c - * Tests for jig voltages. - */ - -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "tests_main.h" - -#include -#include - -int test_jig_voltages(int argc, char *argv[]) -{ - int fd = open(ADC0_DEVICE_PATH, O_RDONLY); - int ret = OK; - - if (fd < 0) { - PX4_ERR("can't open ADC device"); - return 1; - } - - /* make space for the maximum channels */ - px4_adc_msg_t data[PX4_MAX_ADC_CHANNELS]; - - /* read all channels available */ - ssize_t count = read(fd, data, sizeof(data)); - - if (count < 0) { - close(fd); - PX4_ERR("can't read from ADC driver. Forgot 'adc start' command?"); - return 1; - } - - unsigned channels = count / sizeof(data[0]); - - for (unsigned j = 0; j < channels; j++) { - printf("%d: %u ", data[j].am_channel, data[j].am_data); - } - - printf("\n"); - - PX4_INFO("\t ADC operational.\n"); - - /* Expected values */ - int16_t expected_min[] = {2800, 2800, 1800, 800}; - int16_t expected_max[] = {3100, 3100, 2100, 1100}; - char *check_res[channels]; - - if (channels < 4) { - close(fd); - PX4_ERR("not all four test channels available, aborting."); - return 1; - - } else { - /* Check values */ - check_res[0] = (expected_min[0] < data[0].am_data && expected_max[0] > data[0].am_data) ? "OK" : "FAIL"; - check_res[1] = (expected_min[1] < data[1].am_data && expected_max[1] > data[1].am_data) ? "OK" : "FAIL"; - check_res[2] = (expected_min[2] < data[2].am_data && expected_max[2] > data[2].am_data) ? "OK" : "FAIL"; - check_res[3] = (expected_min[3] < data[3].am_data && expected_max[3] > data[3].am_data) ? "OK" : "FAIL"; - - /* Accumulate result */ - ret += (expected_min[0] > data[0].am_data || expected_max[0] < data[0].am_data) ? 1 : 0; - ret += (expected_min[1] > data[1].am_data || expected_max[1] < data[1].am_data) ? 1 : 0; - ret += (expected_min[2] > data[2].am_data || expected_max[2] < data[2].am_data) ? 1 : 0; - ret += (expected_min[3] > data[3].am_data || expected_max[3] < data[3].am_data) ? 1 : 0; - - PX4_INFO("Sample:"); - PX4_INFO("channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s", - data[0].am_channel, (int)(data[0].am_data), expected_min[0], expected_max[0], check_res[0]); - PX4_INFO("channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s", - data[1].am_channel, (int)(data[1].am_data), expected_min[1], expected_max[1], check_res[1]); - PX4_INFO("channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s", - data[2].am_channel, (int)(data[2].am_data), expected_min[2], expected_max[2], check_res[2]); - PX4_INFO("channel: %d value: %d (allowed min: %d, allowed max: %d), result: %s", - data[3].am_channel, (int)(data[3].am_data), expected_min[3], expected_max[3], check_res[3]); - - if (ret != OK) { - PX4_ERR("\t JIG voltages test FAILED. Some channels where out of allowed range. Check supply voltages."); - goto errout_with_dev; - } - } - - PX4_INFO("JIG voltages test successful."); - -errout_with_dev: - - if (fd != 0) { close(fd); } - - return ret; -} diff --git a/src/systemcmds/tests/tests_main.c b/src/systemcmds/tests/tests_main.c index 7dabaf082a47..688a6e127c0e 100644 --- a/src/systemcmds/tests/tests_main.c +++ b/src/systemcmds/tests/tests_main.c @@ -70,7 +70,6 @@ const struct { {"jig", test_jig, OPT_NOJIGTEST | OPT_NOALLTEST}, #ifdef __PX4_NUTTX - {"adc", test_adc, OPT_NOJIGTEST}, {"file", test_file, OPT_NOJIGTEST | OPT_NOALLTEST}, {"led", test_led, 0}, {"sensors", test_sensors, 0}, @@ -95,7 +94,6 @@ const struct { {"hrt", test_hrt, OPT_NOJIGTEST | OPT_NOALLTEST}, {"int", test_int, 0}, {"IntrusiveQueue", test_IntrusiveQueue, 0}, - {"jig_voltages", test_jig_voltages, OPT_NOALLTEST}, {"List", test_List, 0}, {"mathlib", test_mathlib, 0}, {"matrix", test_matrix, 0}, diff --git a/src/systemcmds/tests/tests_main.h b/src/systemcmds/tests/tests_main.h index 604e017b8e15..c0c24080da1f 100644 --- a/src/systemcmds/tests/tests_main.h +++ b/src/systemcmds/tests/tests_main.h @@ -43,7 +43,6 @@ __BEGIN_DECLS -extern int test_adc(int argc, char *argv[]); extern int test_autodeclination(int argc, char *argv[]); extern int test_bezierQuad(int argc, char *argv[]); extern int test_bson(int argc, char *argv[]); @@ -57,7 +56,6 @@ extern int test_hott_telemetry(int argc, char *argv[]); extern int test_hrt(int argc, char *argv[]); extern int test_int(int argc, char *argv[]); extern int test_IntrusiveQueue(int argc, char *argv[]); -extern int test_jig_voltages(int argc, char *argv[]); extern int test_led(int argc, char *argv[]); extern int test_List(int argc, char *argv[]); extern int test_mathlib(int argc, char *argv[]);