From 506db4eaf5e7a823925068cd60c603657b9a7c13 Mon Sep 17 00:00:00 2001 From: pkancir Date: Thu, 20 Aug 2015 14:21:26 +0200 Subject: [PATCH] AP_HAL_Linux: add ADC support for PXF cape --- libraries/AP_HAL_Linux/AP_HAL_Linux_Private.h | 1 + libraries/AP_HAL_Linux/AnalogIn_PXF.cpp | 142 ++++++++++++++++++ libraries/AP_HAL_Linux/AnalogIn_PXF.h | 55 +++++++ libraries/AP_HAL_Linux/HAL_Linux_Class.cpp | 2 + 4 files changed, 200 insertions(+) create mode 100644 libraries/AP_HAL_Linux/AnalogIn_PXF.cpp create mode 100644 libraries/AP_HAL_Linux/AnalogIn_PXF.h diff --git a/libraries/AP_HAL_Linux/AP_HAL_Linux_Private.h b/libraries/AP_HAL_Linux/AP_HAL_Linux_Private.h index 54070af485..8d0f4a0b08 100644 --- a/libraries/AP_HAL_Linux/AP_HAL_Linux_Private.h +++ b/libraries/AP_HAL_Linux/AP_HAL_Linux_Private.h @@ -14,6 +14,7 @@ #include "AnalogIn.h" #include "AnalogIn_ADS1115.h" #include "RaspilotAnalogIn.h" +#include "AnalogIn_PXF.h" #include "Storage.h" #include "GPIO.h" #include "RCInput.h" diff --git a/libraries/AP_HAL_Linux/AnalogIn_PXF.cpp b/libraries/AP_HAL_Linux/AnalogIn_PXF.cpp new file mode 100644 index 0000000000..640177e551 --- /dev/null +++ b/libraries/AP_HAL_Linux/AnalogIn_PXF.cpp @@ -0,0 +1,142 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +#include + +#if CONFIG_HAL_BOARD == HAL_BOARD_LINUX +#include "AnalogIn_PXF.h" + +extern const AP_HAL::HAL& hal; + + + +const char* PXFAnalogSource::analog_sources[PXF_ANALOG_IN_COUNT] = { + "in_voltage0_raw", + "in_voltage1_raw", + "in_voltage2_raw", + "in_voltage3_raw", + "in_voltage4_raw", + "in_voltage5_raw", + "in_voltage6_raw", + "in_voltage7_raw", +}; + +PXFAnalogSource::PXFAnalogSource(int16_t pin, float initial_value) : + _pin(pin), + _value(initial_value), + _sum_value(0), + _sum_count(0), + _pin_fd(-1) +{ + reopen_pin(); +} + +void PXFAnalogSource::reopen_pin(void) +{ + char buf[100]; + + if (_pin_fd != -1) { + close(_pin_fd); + _pin_fd = -1; + } + + if (_pin < 0) { + return; + } + + if (_pin > PXF_ANALOG_IN_COUNT) { + // invalid pin + return; + } + + // Construct the path by appending strings + strncpy(buf, PXF_ANALOG_IN_DIR, sizeof(buf)); + strncat(buf, PXFAnalogSource::analog_sources[_pin], sizeof(buf)); + + _pin_fd = open(buf, O_RDONLY | O_NONBLOCK); + if (_pin_fd == -1) { + ::printf("Failed to open analog pin %s\n", buf); + } +} + +float PXFAnalogSource::read_average() +{ + read_latest(); + if (_sum_count == 0) { + return _value; + } + hal.scheduler->suspend_timer_procs(); + _value = _sum_value / _sum_count; + // _value_ratiometric = _sum_ratiometric / _sum_count; + _sum_value = 0; + // _sum_ratiometric = 0; + _sum_count = 0; + hal.scheduler->resume_timer_procs(); + return _value; +} + +float PXFAnalogSource::read_latest() +{ + char sbuf[10]; + + if (_pin_fd == -1) { + _latest = 0; + return 0; + } + + memset(sbuf, 0, sizeof(sbuf)); + pread(_pin_fd, sbuf, sizeof(sbuf)-1, 0); + + _latest = atoi(sbuf) * BBB_VOLTAGE_SCALING; + _sum_value += _latest; + _sum_count++; + + return _latest; +} + +// output is in volts +float PXFAnalogSource::voltage_average() +{ + return read_average(); +} + +float PXFAnalogSource::voltage_latest() +{ + read_latest(); + return _latest; +} + +void PXFAnalogSource::set_pin(uint8_t pin) +{ + if (_pin == pin) { + return; + } + + hal.scheduler->suspend_timer_procs(); + _pin = pin; + _sum_value = 0; + // _sum_ratiometric = 0; + _sum_count = 0; + _latest = 0; + _value = 0; + reopen_pin(); + // _value_ratiometric = 0; + hal.scheduler->resume_timer_procs(); +} + +void PXFAnalogSource::set_stop_pin(uint8_t p) +{} + +void PXFAnalogSource::set_settle_time(uint16_t settle_time_ms) +{} + +PXFAnalogIn::PXFAnalogIn() +{} + +void PXFAnalogIn::init(void* machtnichts) +{} + + +AP_HAL::AnalogSource* PXFAnalogIn::channel(int16_t pin) { + return new PXFAnalogSource(pin, 0); +} + +#endif // CONFIG_HAL_BOARD diff --git a/libraries/AP_HAL_Linux/AnalogIn_PXF.h b/libraries/AP_HAL_Linux/AnalogIn_PXF.h new file mode 100644 index 0000000000..2c362b3f03 --- /dev/null +++ b/libraries/AP_HAL_Linux/AnalogIn_PXF.h @@ -0,0 +1,55 @@ + +#ifndef __AP_HAL_PXF_ANALOGIN_H__ +#define __AP_HAL_PXF_ANALOGIN_H__ + +#include "AP_HAL_Linux.h" +#include +#include +#include +#include +#include +#include + + +#define PXF_ANALOG_IN_COUNT 8 +// Note that echo BB-ADC cape should be loaded +#define PXF_ANALOG_IN_DIR "/sys/bus/iio/devices/iio:device0/" +#define BBB_VOLTAGE_SCALING 0.00142602816 + +class PXFAnalogSource : public AP_HAL::AnalogSource { +public: + friend class PXFAnalogIn; + PXFAnalogSource(int16_t pin, float v); + float read_average(); + float read_latest(); + void set_pin(uint8_t p); + void set_stop_pin(uint8_t p); + void set_settle_time(uint16_t settle_time_ms); + float voltage_average(); + float voltage_latest(); + float voltage_average_ratiometric() { return voltage_average(); } +private: + float _value; + float _latest; + float _sum_value; + // float _value_ratiometric; + uint8_t _sum_count; + int16_t _pin; + int _pin_fd; + + void reopen_pin(void); + + static const char *analog_sources[PXF_ANALOG_IN_COUNT]; +}; + +class PXFAnalogIn : public AP_HAL::AnalogIn { +public: + PXFAnalogIn(); + void init(void* implspecific); + AP_HAL::AnalogSource* channel(int16_t n); + + // we don't yet know how to get the board voltage + float board_voltage(void) { return 0.0f; } + +}; +#endif // __AP_HAL_PXF_ANALOGIN_H__ diff --git a/libraries/AP_HAL_Linux/HAL_Linux_Class.cpp b/libraries/AP_HAL_Linux/HAL_Linux_Class.cpp index e3f3bc642e..13bceab1a6 100644 --- a/libraries/AP_HAL_Linux/HAL_Linux_Class.cpp +++ b/libraries/AP_HAL_Linux/HAL_Linux_Class.cpp @@ -82,6 +82,8 @@ static ADS1115AnalogIn analogIn; static RaspilotAnalogIn analogIn; #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_QFLIGHT static Empty::AnalogIn analogIn; +#elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLE +static PXFAnalogIn analogIn; #else static AnalogIn analogIn; #endif