adc.S 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* ULP Example: using ADC in deep sleep
  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
  9. measures input voltage on the given ADC channel 'adc_oversampling_factor'
  10. times. Measurements are accumulated and average value is calculated.
  11. Average value is compared to the two thresholds: 'low_thr' and 'high_thr'.
  12. If the value is less than 'low_thr' or more than 'high_thr', ULP wakes up
  13. the chip from deep sleep.
  14. */
  15. /* ULP assembly files are passed through C preprocessor first, so include directives
  16. and C macros may be used in these files
  17. */
  18. #include "soc/rtc_cntl_reg.h"
  19. #include "soc/soc_ulp.h"
  20. /* ADC1 channel 6, GPIO34 */
  21. .set adc_channel, 6
  22. /* Configure the number of ADC samples to average on each measurement.
  23. For convenience, make it a power of 2. */
  24. .set adc_oversampling_factor_log, 2
  25. .set adc_oversampling_factor, (1 << adc_oversampling_factor_log)
  26. /* Define variables, which go into .bss section (zero-initialized data) */
  27. .bss
  28. /* Low threshold of ADC reading.
  29. Set by the main program. */
  30. .global low_thr
  31. low_thr:
  32. .long 0
  33. /* High threshold of ADC reading.
  34. Set by the main program. */
  35. .global high_thr
  36. high_thr:
  37. .long 0
  38. /* Counter of measurements done */
  39. .global sample_counter
  40. sample_counter:
  41. .long 0
  42. .global last_result
  43. last_result:
  44. .long 0
  45. /* Code goes into .text section */
  46. .text
  47. .global entry
  48. entry:
  49. /* increment sample counter */
  50. move r3, sample_counter
  51. ld r2, r3, 0
  52. add r2, r2, 1
  53. st r2, r3, 0
  54. /* do measurements using ADC */
  55. /* r0 will be used as accumulator */
  56. move r0, 0
  57. /* initialize the loop counter */
  58. stage_rst
  59. measure:
  60. /* measure and add value to accumulator */
  61. adc r1, 0, adc_channel + 1
  62. add r0, r0, r1
  63. /* increment loop counter and check exit condition */
  64. stage_inc 1
  65. jumps measure, adc_oversampling_factor, lt
  66. /* divide accumulator by adc_oversampling_factor.
  67. Since it is chosen as a power of two, use right shift */
  68. rsh r0, r0, adc_oversampling_factor_log
  69. /* averaged value is now in r0; store it into last_result */
  70. move r3, last_result
  71. st r0, r3, 0
  72. /* compare with low_thr; wake up if value < low_thr */
  73. move r3, low_thr
  74. ld r3, r3, 0
  75. sub r3, r0, r3
  76. jump wake_up, ov
  77. /* compare with high_thr; wake up if value > high_thr */
  78. move r3, high_thr
  79. ld r3, r3, 0
  80. sub r3, r3, r0
  81. jump wake_up, ov
  82. /* value within range, end the program */
  83. .global exit
  84. exit:
  85. halt
  86. .global wake_up
  87. wake_up:
  88. /* Check if the system can be woken up */
  89. READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
  90. and r0, r0, 1
  91. jump exit, eq
  92. /* Wake up the SoC, end program */
  93. wake
  94. WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
  95. halt