pwm2.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Software PWM using soft-interrupt timer1.
  3. * Supports higher frequencies compared to Espressif provided one.
  4. *
  5. * Nikolay Fiykov
  6. */
  7. // Module for interfacing with PWM2 driver
  8. #include <stdint.h>
  9. #include "lauxlib.h"
  10. #include "module.h"
  11. #include "driver/pwm2.h"
  12. #define luaL_argcheck2(L, cond, numarg, extramsg) \
  13. if (!(cond)) return luaL_argerror(L, (numarg), (extramsg))
  14. //############################
  15. // lua bindings
  16. static int lpwm2_open(lua_State *L) {
  17. pwm2_init();
  18. return 0;
  19. }
  20. static int lpwm2_get_timer_data(lua_State *L) {
  21. lua_pushboolean(L, pwm2_get_module_data()->setupData.isStarted);
  22. lua_pushinteger(L, pwm2_get_module_data()->setupData.interruptTimerCPUTicks);
  23. lua_pushinteger(L, pwm2_get_module_data()->setupData.interruptTimerTicks);
  24. return 3;
  25. }
  26. static int lpwm2_get_pin_data(lua_State *L) {
  27. const uint8 pin = luaL_checkinteger(L, 1);
  28. luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, 1, "invalid pin number");
  29. lua_pushinteger(L, pwm2_is_pin_setup(pin));
  30. lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].duty);
  31. lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].pulseResolutions);
  32. lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].divisableFrequency);
  33. lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].frequencyDivisor);
  34. lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].resolutionCPUTicks);
  35. lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].resolutionInterruptCounterMultiplier);
  36. return 7;
  37. }
  38. static int lpwm2_setup_pin_common(lua_State *L, const bool isFreqHz) {
  39. if (pwm2_is_started()) {
  40. return luaL_error(L, "pwm2 : already started, stop it before setting up pins.");
  41. }
  42. const int pin = lua_tointeger(L, 1);
  43. const int freq = lua_tointeger(L, 2);
  44. const int resolution = lua_tointeger(L, 3);
  45. const int initDuty = lua_tointeger(L, 4);
  46. const int freqFractions = luaL_optinteger(L, 5, 1);
  47. luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, 1, "invalid pin number");
  48. luaL_argcheck2(L, freq > 0, 2, "invalid frequency");
  49. luaL_argcheck2(L, resolution > 0, 3, "invalid frequency resolution");
  50. luaL_argcheck2(L, initDuty >= 0 && initDuty <= resolution, 4, "invalid duty");
  51. luaL_argcheck2(L, freqFractions > 0, 5, "invalid frequency fractions");
  52. if (isFreqHz) {
  53. pwm2_setup_pin(pin, freqFractions, freq, resolution, initDuty);
  54. } else {
  55. pwm2_setup_pin(pin, freq, freqFractions, resolution, initDuty);
  56. }
  57. return 0;
  58. }
  59. static int lpwm2_setup_pin_hz(lua_State *L) {
  60. return lpwm2_setup_pin_common(L, true);
  61. }
  62. static int lpwm2_setup_pin_sec(lua_State *L) {
  63. return lpwm2_setup_pin_common(L, false);
  64. }
  65. static int lpwm2_set_duty(lua_State *L) {
  66. int pos = 0;
  67. while (true) {
  68. int pin = luaL_optinteger(L, ++pos, -1);
  69. if (pin == -1) {
  70. break;
  71. }
  72. luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, pos, "invalid pin number");
  73. int duty = luaL_optinteger(L, ++pos, -1);
  74. luaL_argcheck2(L, duty >= 0 && duty <= pwm2_get_module_data()->setupData.pin[pin].pulseResolutions, pos, "invalid duty");
  75. if (!pwm2_is_pin_setup(pin)) {
  76. return luaL_error(L, "pwm2 : pin=%d is not setup yet", pin);
  77. }
  78. pwm2_set_duty(pin, duty);
  79. }
  80. return 0;
  81. }
  82. static int lpwm2_release_pin(lua_State *L) {
  83. if (pwm2_is_started()) {
  84. return luaL_error(L, "pwm2 : pwm is started, stop it first.");
  85. }
  86. int pos = 0;
  87. while (true) {
  88. int pin = luaL_optinteger(L, ++pos, -1);
  89. if (pin == -1) {
  90. break;
  91. }
  92. luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, pos, "invalid pin number");
  93. pwm2_release_pin(2);
  94. }
  95. return 0;
  96. }
  97. static int lpwm2_stop(lua_State *L) {
  98. pwm2_stop();
  99. return 0;
  100. }
  101. static int lpwm2_start(lua_State *L) {
  102. if (!pwm2_start()) {
  103. luaL_error(L, "pwm2: currently platform timer1 is being used by another module.\n");
  104. lua_pushboolean(L, false);
  105. } else {
  106. lua_pushboolean(L, true);
  107. }
  108. return 1;
  109. }
  110. // Module function map
  111. LROT_BEGIN(pwm2, NULL, 0)
  112. LROT_FUNCENTRY(setup_pin_hz, lpwm2_setup_pin_hz)
  113. LROT_FUNCENTRY(setup_pin_sec, lpwm2_setup_pin_sec)
  114. LROT_FUNCENTRY(release_pin, lpwm2_release_pin)
  115. LROT_FUNCENTRY(start, lpwm2_start)
  116. LROT_FUNCENTRY(stop, lpwm2_stop)
  117. LROT_FUNCENTRY(set_duty, lpwm2_set_duty)
  118. LROT_FUNCENTRY(get_timer_data, lpwm2_get_timer_data)
  119. LROT_FUNCENTRY(get_pin_data, lpwm2_get_pin_data)
  120. // LROT_FUNCENTRY(print_setup, lpwm2_print_setup)
  121. // LROT_FUNCENTRY( time_it, lpwm2_timeit)
  122. // LROT_FUNCENTRY( test_tmr_manual, lpwm2_timing_frc1_manual_load_overhead)
  123. // LROT_FUNCENTRY( test_tmr_auto, lpwm2_timing_frc1_auto_load_overhead)
  124. LROT_END(pwm2, NULL, 0)
  125. NODEMCU_MODULE(PWM2, "pwm2", pwm2, lpwm2_open);