rt_inputcapture.c 5.1 KB

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