analog.cpp 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /*
  14. analog capture for IOMCU. This uses direct register access to avoid
  15. using up a DMA channel and to minimise latency. We capture a single
  16. sample at a time
  17. */
  18. #include "ch.h"
  19. #include "hal.h"
  20. #include "analog.h"
  21. #if HAL_USE_ADC != TRUE
  22. #error "HAL_USE_ADC must be set"
  23. #endif
  24. /*
  25. initialise ADC capture
  26. */
  27. void adc_init(void)
  28. {
  29. adc_lld_init();
  30. rccEnableADC1(true);
  31. /* set channels 4 and 5 for 28.5us sample time */
  32. ADC1->SMPR2 = ADC_SMPR2_SMP_AN4(ADC_SAMPLE_28P5) | ADC_SMPR2_SMP_AN5(ADC_SAMPLE_28P5);
  33. /* capture a single sample at a time */
  34. ADC1->SQR1 = 0;
  35. ADC1->SQR2 = 0;
  36. }
  37. /*
  38. capture one sample on a channel
  39. */
  40. static uint16_t adc_sample_channel(uint32_t channel)
  41. {
  42. // clear EOC
  43. ADC1->SR = 0;
  44. /* capture one sample */
  45. ADC1->SQR3 = channel;
  46. ADC1->CR2 |= ADC_CR2_ADON;
  47. /* wait for the conversion to complete */
  48. uint32_t counter = 16;
  49. while (!(ADC1->SR & ADC_SR_EOC)) {
  50. if (--counter == 0) {
  51. // ensure EOC is clear
  52. ADC1->SR = 0;
  53. return 0xffff;
  54. }
  55. }
  56. // return sample (this also clears EOC flag)
  57. return ADC1->DR;
  58. }
  59. /*
  60. capture VSERVO in mV
  61. */
  62. uint16_t adc_sample_vservo(void)
  63. {
  64. const uint32_t channel = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN4);
  65. return adc_sample_channel(channel) * 9900 / 4096;
  66. }
  67. /*
  68. capture VRSSI in mV
  69. */
  70. uint16_t adc_sample_vrssi(void)
  71. {
  72. const uint32_t channel = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN5);
  73. return adc_sample_channel(channel) * 9900 / 4096;
  74. }