gpio.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include "kbf/gpio.h"
  2. #include <esp_log.h>
  3. #include <esp_sleep.h>
  4. #include "kbf.h"
  5. #include "kbf/macros.h"
  6. using namespace kbf;
  7. using namespace kbf::rtos;
  8. using std::string;
  9. gpio::Output::Output(int pin) : pin(static_cast<gpio_num_t>(pin)) {
  10. ESP_LOGI(TAG, "setting GPIO %d to OUTPUT mode", pin);
  11. CHECK(gpio_reset_pin(this->pin));
  12. CHECK(gpio_set_direction(this->pin, GPIO_MODE_OUTPUT));
  13. }
  14. void gpio::Output::high() const {
  15. gpio_set_level(pin, 1);
  16. }
  17. void gpio::Output::low() const {
  18. gpio_set_level(pin, 0);
  19. }
  20. void gpio::Output::startPulse(int delay_ms, int limit) {
  21. ESP_LOGI(TAG, "starting pulse on GPIO %d; delay = %d, limit = %d", pin, delay_ms, limit);
  22. string taskName = "kbf_gpio_p" + std::to_string(pin);
  23. if (pulseTask != nullptr && pulseTask->isRunning()) {
  24. ESP_LOGE(TAG, "pulse task already running");
  25. ABORT("fix me");
  26. }
  27. pulseDelay = delay_ms;
  28. pulseLimit = limit;
  29. delete pulseTask;
  30. pulseTask = new Task(taskName, pulseCallback, this);
  31. }
  32. void gpio::Output::stopPulse() {
  33. ESP_LOGI(TAG, "stopping pulse on GPIO %d", pin);
  34. if (pulseTask == nullptr) {
  35. ESP_LOGE(TAG, "pulse task not running");
  36. ABORT("fix me");
  37. }
  38. pulseTask->stop();
  39. low();
  40. }
  41. void gpio::Output::pulseCallback(void *arg_ptr) {
  42. auto output = static_cast<Output *>(arg_ptr);
  43. int count = 0;
  44. while (output->pulseLimit < 0 || count++ < output->pulseLimit) {
  45. output->high();
  46. kbf::sleep(output->pulseDelay);
  47. output->low();
  48. kbf::sleep(output->pulseDelay);
  49. }
  50. }
  51. gpio::Input::Input(int pin, void *userData) : pin(static_cast<gpio_num_t>(pin)), userData(userData) {
  52. ESP_LOGI(TAG, "setting GPIO %d to INPUT mode", pin);
  53. static bool isrInstalled = false;
  54. if (!isrInstalled) {
  55. ESP_LOGI(TAG, "installing ISR service");
  56. CHECK(gpio_install_isr_service(0));
  57. isrInstalled = true;
  58. }
  59. CHECK(gpio_reset_pin(this->pin));
  60. CHECK(gpio_set_direction(this->pin, GPIO_MODE_INPUT));
  61. CHECK(gpio_set_intr_type(this->pin, GPIO_INTR_ANYEDGE));
  62. CHECK(gpio_isr_handler_add(this->pin, interruptHandler, this));
  63. }
  64. void gpio::Input::interruptHandler(void *data) {
  65. auto input = static_cast<Input *>(data);
  66. if (input->isHigh() && input->onHigh) {
  67. input->onHigh(*input);
  68. } else if (input->isLow() && input->onLow) {
  69. input->onLow(*input);
  70. }
  71. }
  72. bool gpio::Input::isHigh() const {
  73. return gpio_get_level(pin) == 1;
  74. }
  75. bool gpio::Input::isLow() const {
  76. return gpio_get_level(pin) == 0;
  77. }
  78. gpio::Input::~Input() {
  79. CHECK_ABORT(gpio_isr_handler_remove(pin));
  80. }