Ardupilot2/libraries/AP_HAL_Linux/AnalogIn_Navio2.cpp
Lucas De Marchi 490841a814 AP_HAL_Linux: add O_CLOEXEC in places missing it
By opening with O_CLOEXEC we make sure we don't leak the file descriptor
when we are exec'ing or calling out subprograms. Right now we currently
don't do it so there's no harm, but it's good practice in Linux to have
it.
2016-11-07 12:37:30 -03:00

126 lines
2.3 KiB
C++

#include <cstdio>
#include <cstdlib>
#include <errno.h>
#include <unistd.h>
#include <AP_HAL/AP_HAL.h>
#include "AnalogIn_Navio2.h"
static const AP_HAL::HAL &hal = AP_HAL::get_HAL();
#define ADC_BASE_PATH "/sys/kernel/rcio/adc"
void AnalogSource_Navio2::set_channel(uint8_t pin)
{
char *channel_path;
if (pin == ANALOG_INPUT_NONE) {
return;
}
if (asprintf(&channel_path, "%s/ch%d", ADC_BASE_PATH, pin) == -1) {
AP_HAL::panic("asprintf failed\n");
}
if (_fd >= 0) {
::close(_fd);
}
_fd = ::open(channel_path, O_RDONLY|O_CLOEXEC);
if (_fd < 0) {
hal.console->printf("%s not opened: %s\n", channel_path, strerror(errno));
}
free(channel_path);
}
AnalogSource_Navio2::AnalogSource_Navio2(uint8_t pin)
: _pin(pin)
{
set_channel(pin);
}
void AnalogSource_Navio2::set_pin(uint8_t pin)
{
if (_pin == pin) {
return;
}
set_channel(pin);
_pin = pin;
}
float AnalogSource_Navio2::read_average()
{
return read_latest();
}
float AnalogSource_Navio2::read_latest()
{
return voltage_average();
}
float AnalogSource_Navio2::voltage_average()
{
char buffer[12];
if (pread(_fd, buffer, sizeof(buffer) - 1, 0) <= 0) {
/* Don't log fails since this could spam the console */
return -1.0f;
}
/* Avoid overriding NULL char at the end of the string */
buffer[sizeof(buffer) - 1] = '\0';
_value = atoi(buffer) / 1000.0f;
return _value;
}
float AnalogSource_Navio2::voltage_latest()
{
read_latest();
return _value;
}
float AnalogSource_Navio2::voltage_average_ratiometric()
{
return voltage_average();
}
AnalogIn_Navio2::AnalogIn_Navio2()
{
}
float AnalogIn_Navio2::board_voltage(void)
{
return _board_voltage_pin->voltage_average();
}
float AnalogIn_Navio2::servorail_voltage(void)
{
return _servorail_pin->voltage_average();
}
AP_HAL::AnalogSource *AnalogIn_Navio2::channel(int16_t pin)
{
for (uint8_t j = 0; j < _channels_number; j++) {
if (_channels[j] == nullptr) {
_channels[j] = new AnalogSource_Navio2(pin);
return _channels[j];
}
}
hal.console->println("Out of analog channels");
return nullptr;
}
void AnalogIn_Navio2::init()
{
_board_voltage_pin = channel(0);
_servorail_pin = channel(1);
}