rt_inputcapture.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-08-13 balanceTWK the first version
  9. */
  10. #include <rtdevice.h>
  11. #define DBG_TAG "incap"
  12. #define DBG_LVL DBG_WARNING
  13. #include <rtdbg.h>
  14. static rt_err_t rt_inputcapture_init(struct rt_device *dev)
  15. {
  16. rt_err_t ret;
  17. struct rt_inputcapture_device *inputcapture;
  18. RT_ASSERT(dev != RT_NULL);
  19. ret = RT_EOK;
  20. inputcapture = (struct rt_inputcapture_device *)dev;
  21. inputcapture->watermark = RT_INPUT_CAPTURE_RB_SIZE / 2;
  22. if (inputcapture->ops->init)
  23. {
  24. ret = inputcapture->ops->init(inputcapture);
  25. }
  26. return ret;
  27. }
  28. static rt_err_t rt_inputcapture_open(struct rt_device *dev, rt_uint16_t oflag)
  29. {
  30. rt_err_t ret;
  31. struct rt_inputcapture_device *inputcapture;
  32. RT_ASSERT(dev != RT_NULL);
  33. ret = RT_EOK;
  34. inputcapture = (struct rt_inputcapture_device *)dev;
  35. if (inputcapture->ringbuff == RT_NULL)
  36. {
  37. inputcapture->ringbuff = rt_ringbuffer_create(sizeof(struct rt_inputcapture_data) * RT_INPUT_CAPTURE_RB_SIZE);
  38. }
  39. if (inputcapture->ops->open)
  40. {
  41. ret = inputcapture->ops->open(inputcapture);
  42. }
  43. return ret;
  44. }
  45. static rt_err_t rt_inputcapture_close(struct rt_device *dev)
  46. {
  47. rt_err_t ret;
  48. struct rt_inputcapture_device *inputcapture;
  49. RT_ASSERT(dev != RT_NULL);
  50. ret = -RT_ERROR;
  51. inputcapture = (struct rt_inputcapture_device *)dev;
  52. if (inputcapture->ops->close)
  53. {
  54. ret = inputcapture->ops->close(inputcapture);
  55. }
  56. if (ret != RT_EOK)
  57. {
  58. return ret;
  59. }
  60. if (inputcapture->ringbuff)
  61. {
  62. rt_ringbuffer_destroy(inputcapture->ringbuff);
  63. inputcapture->ringbuff = RT_NULL;
  64. }
  65. return ret;
  66. }
  67. static rt_ssize_t rt_inputcapture_read(struct rt_device *dev,
  68. rt_off_t pos,
  69. void *buffer,
  70. rt_size_t size)
  71. {
  72. rt_size_t receive_size;
  73. struct rt_inputcapture_device *inputcapture;
  74. RT_ASSERT(dev != RT_NULL);
  75. inputcapture = (struct rt_inputcapture_device *)dev;
  76. receive_size = rt_ringbuffer_get(inputcapture->ringbuff, (rt_uint8_t *)buffer, sizeof(struct rt_inputcapture_data) * size);
  77. return receive_size / sizeof(struct rt_inputcapture_data);
  78. }
  79. static rt_err_t rt_inputcapture_control(struct rt_device *dev, int cmd, void *args)
  80. {
  81. rt_err_t result;
  82. struct rt_inputcapture_device *inputcapture;
  83. RT_ASSERT(dev != RT_NULL);
  84. result = RT_EOK;
  85. inputcapture = (struct rt_inputcapture_device *)dev;
  86. switch (cmd)
  87. {
  88. case INPUTCAPTURE_CMD_CLEAR_BUF:
  89. if (inputcapture->ringbuff)
  90. {
  91. rt_ringbuffer_reset(inputcapture->ringbuff);
  92. }
  93. break;
  94. case INPUTCAPTURE_CMD_SET_WATERMARK:
  95. inputcapture->watermark = *(rt_size_t *)args;
  96. break;
  97. default:
  98. result = -RT_ENOSYS;
  99. break;
  100. }
  101. return result;
  102. }
  103. #ifdef RT_USING_DEVICE_OPS
  104. const static struct rt_device_ops inputcapture_ops =
  105. {
  106. rt_inputcapture_init,
  107. rt_inputcapture_open,
  108. rt_inputcapture_close,
  109. rt_inputcapture_read,
  110. RT_NULL,
  111. rt_inputcapture_control
  112. };
  113. #endif
  114. rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, const char *name, void *user_data)
  115. {
  116. struct rt_device *device;
  117. RT_ASSERT(inputcapture != RT_NULL);
  118. RT_ASSERT(inputcapture->ops != RT_NULL);
  119. RT_ASSERT(inputcapture->ops->get_pulsewidth != RT_NULL);
  120. device = &(inputcapture->parent);
  121. device->type = RT_Device_Class_Miscellaneous;
  122. device->rx_indicate = RT_NULL;
  123. device->tx_complete = RT_NULL;
  124. inputcapture->ringbuff = RT_NULL;
  125. #ifdef RT_USING_DEVICE_OPS
  126. device->ops = &inputcapture_ops;
  127. #else
  128. device->init = rt_inputcapture_init;
  129. device->open = rt_inputcapture_open;
  130. device->close = rt_inputcapture_close;
  131. device->read = rt_inputcapture_read;
  132. device->write = RT_NULL;
  133. device->control = rt_inputcapture_control;
  134. #endif
  135. device->user_data = user_data;
  136. return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE);
  137. }
  138. /**
  139. * This function is ISR for inputcapture interrupt.
  140. * level: RT_TRUE denotes high level pulse, and RT_FALSE denotes low level pulse.
  141. */
  142. void rt_hw_inputcapture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level)
  143. {
  144. struct rt_inputcapture_data data;
  145. rt_size_t receive_size;
  146. if (inputcapture->ops->get_pulsewidth(inputcapture, &data.pulsewidth_us) != RT_EOK)
  147. {
  148. return;
  149. }
  150. data.is_high = level;
  151. if (rt_ringbuffer_put(inputcapture->ringbuff, (rt_uint8_t *)&data, sizeof(struct rt_inputcapture_data)) == 0)
  152. {
  153. LOG_W("inputcapture ringbuffer doesn't have enough space.");
  154. }
  155. receive_size = rt_ringbuffer_data_len(inputcapture->ringbuff) / sizeof(struct rt_inputcapture_data);
  156. if (receive_size >= inputcapture->watermark)
  157. {
  158. /* indicate to upper layer application */
  159. if (inputcapture->parent.rx_indicate != RT_NULL)
  160. inputcapture->parent.rx_indicate(&inputcapture->parent, receive_size);
  161. }
  162. }