pulse_cnt.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* ULP Example: pulse counting
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. This file contains assembly code which runs on the ULP.
  7. ULP wakes up to run this code at a certain period, determined by the values
  8. in SENS_ULP_CP_SLEEP_CYCx_REG registers. On each wake up, the program checks
  9. the input on GPIO0. If the value is different from the previous one, the
  10. program "debounces" the input: on the next debounce_max_count wake ups,
  11. it expects to see the same value of input.
  12. If this condition holds true, the program increments edge_count and starts
  13. waiting for input signal polarity to change again.
  14. When the edge counter reaches certain value (set by the main program),
  15. this program running triggers a wake up from deep sleep.
  16. */
  17. /* ULP assembly files are passed through C preprocessor first, so include directives
  18. and C macros may be used in these files
  19. */
  20. #include "soc/rtc_cntl_reg.h"
  21. #include "soc/rtc_io_reg.h"
  22. #include "soc/soc_ulp.h"
  23. /* Define variables, which go into .bss section (zero-initialized data) */
  24. .bss
  25. /* Next input signal edge expected: 0 (negative) or 1 (positive) */
  26. .global next_edge
  27. next_edge:
  28. .long 0
  29. /* Counter started when signal value changes.
  30. Edge is "debounced" when the counter reaches zero. */
  31. .global debounce_counter
  32. debounce_counter:
  33. .long 0
  34. /* Value to which debounce_counter gets reset.
  35. Set by the main program. */
  36. .global debounce_max_count
  37. debounce_max_count:
  38. .long 0
  39. /* Total number of signal edges acquired */
  40. .global edge_count
  41. edge_count:
  42. .long 0
  43. /* Number of edges to acquire before waking up the SoC.
  44. Set by the main program. */
  45. .global edge_count_to_wake_up
  46. edge_count_to_wake_up:
  47. .long 0
  48. /* RTC IO number used to sample the input signal.
  49. Set by main program. */
  50. .global io_number
  51. io_number:
  52. .long 0
  53. /* Code goes into .text section */
  54. .text
  55. .global entry
  56. entry:
  57. /* Read the value of lower 16 RTC IOs into R0 */
  58. READ_RTC_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT)
  59. /* Load io_number, extract the state of input */
  60. move r3, io_number
  61. ld r3, r3, 0
  62. rsh r0, r0, r3
  63. and r0, r0, 1
  64. /* State of input changed? */
  65. move r3, next_edge
  66. ld r3, r3, 0
  67. add r3, r0, r3
  68. and r3, r3, 1
  69. jump changed, eq
  70. /* Not changed */
  71. /* Reset debounce_counter to debounce_max_count */
  72. move r3, debounce_max_count
  73. move r2, debounce_counter
  74. ld r3, r3, 0
  75. st r3, r2, 0
  76. /* End program */
  77. halt
  78. .global changed
  79. changed:
  80. /* Input state changed */
  81. /* Has debounce_counter reached zero? */
  82. move r3, debounce_counter
  83. ld r2, r3, 0
  84. add r2, r2, 0 /* dummy ADD to use "jump if ALU result is zero" */
  85. jump edge_detected, eq
  86. /* Not yet. Decrement debounce_counter */
  87. sub r2, r2, 1
  88. st r2, r3, 0
  89. /* End program */
  90. halt
  91. .global edge_detected
  92. edge_detected:
  93. /* Reset debounce_counter to debounce_max_count */
  94. move r3, debounce_max_count
  95. move r2, debounce_counter
  96. ld r3, r3, 0
  97. st r3, r2, 0
  98. /* Flip next_edge */
  99. move r3, next_edge
  100. ld r2, r3, 0
  101. add r2, r2, 1
  102. and r2, r2, 1
  103. st r2, r3, 0
  104. /* Increment edge_count */
  105. move r3, edge_count
  106. ld r2, r3, 0
  107. add r2, r2, 1
  108. st r2, r3, 0
  109. /* Compare edge_count to edge_count_to_wake_up */
  110. move r3, edge_count_to_wake_up
  111. ld r3, r3, 0
  112. sub r3, r3, r2
  113. jump wake_up, eq
  114. /* Not yet. End program */
  115. halt
  116. .global wake_up
  117. wake_up:
  118. /* Check if the system can be woken up */
  119. READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
  120. and r0, r0, 1
  121. jump wake_up, eq
  122. /* Wake up the SoC, end program */
  123. wake
  124. halt