RCOutput_Sysfs.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (C) 2015 Intel Corporation. All rights reserved.
  3. *
  4. * This file is free software: you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This file is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * See the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "RCOutput_Sysfs.h"
  18. #include <AP_HAL/AP_HAL.h>
  19. #include <AP_Math/AP_Math.h>
  20. namespace Linux {
  21. RCOutput_Sysfs::RCOutput_Sysfs(uint8_t chip, uint8_t channel_base, uint8_t channel_count)
  22. : _chip(chip)
  23. , _channel_base(channel_base)
  24. , _channel_count(channel_count)
  25. , _pwm_channels(new PWM_Sysfs_Base *[_channel_count])
  26. , _pending(new uint16_t[_channel_count])
  27. {
  28. }
  29. RCOutput_Sysfs::~RCOutput_Sysfs()
  30. {
  31. for (uint8_t i = 0; i < _channel_count; i++) {
  32. delete _pwm_channels[i];
  33. }
  34. delete [] _pwm_channels;
  35. }
  36. void RCOutput_Sysfs::init()
  37. {
  38. for (uint8_t i = 0; i < _channel_count; i++) {
  39. #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO
  40. _pwm_channels[i] = new PWM_Sysfs_Bebop(_channel_base+i);
  41. #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_RST_ZYNQ
  42. _pwm_channels[i] = new PWM_Sysfs(_chip+i, 0);
  43. #else
  44. _pwm_channels[i] = new PWM_Sysfs(_chip, _channel_base+i);
  45. #endif
  46. if (!_pwm_channels[i]) {
  47. AP_HAL::panic("RCOutput_Sysfs_PWM: Unable to setup PWM pin.");
  48. }
  49. _pwm_channels[i]->init();
  50. _pwm_channels[i]->enable(false);
  51. /* Set the initial frequency */
  52. _pwm_channels[i]->set_freq(50);
  53. _pwm_channels[i]->set_duty_cycle(0);
  54. _pwm_channels[i]->set_polarity(PWM_Sysfs::Polarity::NORMAL);
  55. }
  56. }
  57. void RCOutput_Sysfs::set_freq(uint32_t chmask, uint16_t freq_hz)
  58. {
  59. for (uint8_t i = 0; i < _channel_count; i++) {
  60. if (chmask & 1 << i) {
  61. _pwm_channels[i]->set_freq(freq_hz);
  62. }
  63. }
  64. }
  65. uint16_t RCOutput_Sysfs::get_freq(uint8_t ch)
  66. {
  67. if (ch >= _channel_count) {
  68. return 0;
  69. }
  70. return _pwm_channels[ch]->get_freq();
  71. }
  72. void RCOutput_Sysfs::enable_ch(uint8_t ch)
  73. {
  74. if (ch >= _channel_count) {
  75. return;
  76. }
  77. _pwm_channels[ch]->enable(true);
  78. }
  79. void RCOutput_Sysfs::disable_ch(uint8_t ch)
  80. {
  81. if (ch >= _channel_count) {
  82. return;
  83. }
  84. _pwm_channels[ch]->enable(false);
  85. }
  86. void RCOutput_Sysfs::write(uint8_t ch, uint16_t period_us)
  87. {
  88. if (ch >= _channel_count) {
  89. return;
  90. }
  91. if (_corked) {
  92. _pending[ch] = period_us;
  93. _pending_mask |= (1U<<ch);
  94. } else {
  95. _pwm_channels[ch]->set_duty_cycle(usec_to_nsec(period_us));
  96. }
  97. }
  98. uint16_t RCOutput_Sysfs::read(uint8_t ch)
  99. {
  100. if (ch >= _channel_count) {
  101. return 1000;
  102. }
  103. return nsec_to_usec(_pwm_channels[ch]->get_duty_cycle());
  104. }
  105. void RCOutput_Sysfs::read(uint16_t *period_us, uint8_t len)
  106. {
  107. for (int i = 0; i < MIN(len, _channel_count); i++) {
  108. period_us[i] = read(i);
  109. }
  110. for (int i = _channel_count; i < len; i++) {
  111. period_us[i] = 1000;
  112. }
  113. }
  114. void RCOutput_Sysfs::cork(void)
  115. {
  116. _corked = true;
  117. }
  118. void RCOutput_Sysfs::push(void)
  119. {
  120. if (!_corked) {
  121. return;
  122. }
  123. for (uint8_t i=0; i<_channel_count; i++) {
  124. if ((1U<<i) & _pending_mask) {
  125. _pwm_channels[i]->set_duty_cycle(usec_to_nsec(_pending[i]));
  126. }
  127. }
  128. _pending_mask = 0;
  129. _corked = false;
  130. }
  131. }