rt_inputcapture.c 5.2 KB

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