Skip to content

Commit

Permalink
新增 GPIO 类,添加任务等待功能,重命名波特率枚举,更新相机和配置管理器接口,优化打印格式,增加 INDI 服务器中间件功能
Browse files Browse the repository at this point in the history
  • Loading branch information
AstroAir committed Nov 9, 2024
1 parent 13c671f commit a49a6ef
Show file tree
Hide file tree
Showing 22 changed files with 2,510 additions and 1,086 deletions.
5 changes: 5 additions & 0 deletions src/atom/async/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,9 @@ auto Timer::getTaskCount() const -> size_t {
std::unique_lock lock(m_mutex);
return m_taskQueue.size();
}

void Timer::wait() {
std::unique_lock lock(m_mutex);
m_cond.wait(lock, [&]() { return m_taskQueue.empty(); });
}
} // namespace atom::async
5 changes: 5 additions & 0 deletions src/atom/async/timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ class Timer {
*/
void stop();

/**
* @brief Blocks the calling thread until all tasks are completed.
*/
void wait();

/**
* @brief Sets a callback function to be called when a task is executed.
*
Expand Down
127 changes: 127 additions & 0 deletions src/atom/system/gpio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include "gpio.hpp"

#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <thread>
#include <utility>

#include "atom/error/exception.hpp"
#include "atom/log/loguru.hpp"

#define GPIO_EXPORT "/sys/class/gpio/export"
#define GPIO_PATH "/sys/class/gpio"

namespace atom::system {
class GPIO::Impl {
public:
explicit Impl(std::string pin) : pin_(std::move(pin)) {
exportGPIO();
setGPIODirection("out");
}

~Impl() {
try {
setGPIODirection("in");
} catch (...) {
// Suppress all exceptions
}
}

void setValue(bool value) { setGPIOValue(value ? "1" : "0"); }

bool getValue() { return readGPIOValue(); }

void setDirection(const std::string& direction) {
setGPIODirection(direction);
}

static void notifyOnChange(const std::string& pin,
const std::function<void(bool)>& callback) {
std::thread([pin, callback]() {
std::string path =
std::string(GPIO_PATH) + "/gpio" + pin + "/value";
int fd = open(path.c_str(), O_RDONLY);
if (fd < 0) {
LOG_F(ERROR, "Failed to open gpio value for reading");
return;
}

char lastValue = '0';
while (true) {
char value[3] = {0};
if (read(fd, value, sizeof(value) - 1) > 0) {
if (value[0] != lastValue) {
lastValue = value[0];
callback(value[0] == '1');
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
lseek(fd, 0, SEEK_SET);
}
close(fd);
}).detach();
}

private:
std::string pin_;

void exportGPIO() { executeGPIOCommand(GPIO_EXPORT, pin_); }

void setGPIODirection(const std::string& direction) {
std::string path =
std::string(GPIO_PATH) + "/gpio" + pin_ + "/direction";
executeGPIOCommand(path, direction);
}

void setGPIOValue(const std::string& value) {
std::string path = std::string(GPIO_PATH) + "/gpio" + pin_ + "/value";
executeGPIOCommand(path, value);
}

auto readGPIOValue() -> bool {
std::string path = std::string(GPIO_PATH) + "/gpio" + pin_ + "/value";
char value[3] = {0};
int fd = open(path.c_str(), O_RDONLY);
if (fd < 0) {
THROW_RUNTIME_ERROR("Failed to open gpio value for reading");
}
ssize_t bytes = read(fd, value, sizeof(value) - 1);
close(fd);
if (bytes < 0) {
THROW_RUNTIME_ERROR("Failed to read gpio value");
}
return value[0] == '1';
}

static void executeGPIOCommand(const std::string& path,
const std::string& command) {
int fd = open(path.c_str(), O_WRONLY);
if (fd < 0) {
THROW_RUNTIME_ERROR("Failed to open gpio path: " + path);
}
ssize_t bytes = write(fd, command.c_str(), command.length());
close(fd);
if (bytes != static_cast<ssize_t>(command.length())) {
THROW_RUNTIME_ERROR("Failed to write to gpio path: " + path);
}
}
};

GPIO::GPIO(const std::string& pin) : impl_(std::make_unique<Impl>(pin)) {}

GPIO::~GPIO() = default;

void GPIO::setValue(bool value) { impl_->setValue(value); }

bool GPIO::getValue() { return impl_->getValue(); }

void GPIO::setDirection(const std::string& direction) {
impl_->setDirection(direction);
}

void GPIO::notifyOnChange(const std::string& pin,
std::function<void(bool)> callback) {
Impl::notifyOnChange(pin, std::move(callback));
}
} // namespace atom::system
26 changes: 26 additions & 0 deletions src/atom/system/gpio.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef ATOM_SYSTEM_GPIO_HPP
#define ATOM_SYSTEM_GPIO_HPP

#include <functional>
#include <memory>
#include <string>

namespace atom::system {
class GPIO {
public:
GPIO(const std::string& pin);
~GPIO();

void setValue(bool value);
bool getValue();
void setDirection(const std::string& direction);
static void notifyOnChange(const std::string& pin,
std::function<void(bool)> callback);

private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace atom::system

#endif // ATOM_SYSTEM_GPIO_HPP
5 changes: 2 additions & 3 deletions src/atom/utils/print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,12 @@ class FormatLiteral {
std::make_format_args(std::forward<Args>(args)...));
}
};
} // namespace atom::utils

constexpr auto operator""_fmt(const char* str, std::size_t len) {
return FormatLiteral(std::string_view(str, len));
return atom::utils::FormatLiteral(std::string_view(str, len));
}

} // namespace atom::utils

#if __cplusplus >= 202302L
namespace std {

Expand Down
Loading

0 comments on commit a49a6ef

Please sign in to comment.