LoRaFEMControl.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "LoRaFEMControl.h"
  2. #include <driver/rtc_io.h>
  3. #include <esp_sleep.h>
  4. #include <Arduino.h>
  5. void LoRaFEMControl::init(void)
  6. {
  7. // Power on FEM LDO — set registers before releasing RTC hold for
  8. // atomic transition (no glitch on deep sleep wake).
  9. pinMode(P_LORA_PA_POWER, OUTPUT);
  10. digitalWrite(P_LORA_PA_POWER, HIGH);
  11. rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
  12. esp_reset_reason_t reason = esp_reset_reason();
  13. if (reason != ESP_RST_DEEPSLEEP) {
  14. delay(1); // FEM startup time after cold power-on
  15. }
  16. // Auto-detect FEM type via shared GPIO2 default pull level.
  17. // GC1109 CSD: internal pull-down → reads LOW
  18. // KCT8103L CSD: internal pull-up → reads HIGH
  19. rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
  20. pinMode(P_LORA_KCT8103L_PA_CSD, INPUT);
  21. delay(1);
  22. if(digitalRead(P_LORA_KCT8103L_PA_CSD)==HIGH) {
  23. // FEM is KCT8103L (V4.3)
  24. fem_type= KCT8103L_PA;
  25. pinMode(P_LORA_KCT8103L_PA_CSD, OUTPUT);
  26. digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
  27. rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CTX);
  28. pinMode(P_LORA_KCT8103L_PA_CTX, OUTPUT);
  29. digitalWrite(P_LORA_KCT8103L_PA_CTX, lna_enabled ? LOW : HIGH);
  30. setLnaCanControl(true);
  31. } else {
  32. // FEM is GC1109 (V4.2)
  33. fem_type= GC1109_PA;
  34. pinMode(P_LORA_GC1109_PA_EN, OUTPUT);
  35. digitalWrite(P_LORA_GC1109_PA_EN, HIGH);
  36. pinMode(P_LORA_GC1109_PA_TX_EN, OUTPUT);
  37. digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW);
  38. }
  39. }
  40. void LoRaFEMControl::setSleepModeEnable(void)
  41. {
  42. if(fem_type==GC1109_PA) {
  43. /*
  44. * Do not switch the power on and off frequently.
  45. * After turning off P_LORA_PA_EN, the power consumption has dropped to the uA level.
  46. */
  47. digitalWrite(P_LORA_GC1109_PA_EN, LOW);
  48. digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW);
  49. } else if(fem_type==KCT8103L_PA) {
  50. // shutdown the PA
  51. digitalWrite(P_LORA_KCT8103L_PA_CSD, LOW);
  52. }
  53. }
  54. void LoRaFEMControl::setTxModeEnable(void)
  55. {
  56. if(fem_type==GC1109_PA) {
  57. digitalWrite(P_LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
  58. digitalWrite(P_LORA_GC1109_PA_TX_EN, HIGH); // CPS: 1=full PA, 0=bypass (for RX, CPS is don't care)
  59. } else if(fem_type==KCT8103L_PA) {
  60. digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
  61. digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH);
  62. }
  63. }
  64. void LoRaFEMControl::setRxModeEnable(void)
  65. {
  66. if(fem_type==GC1109_PA) {
  67. digitalWrite(P_LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
  68. digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW);
  69. } else if(fem_type==KCT8103L_PA) {
  70. digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
  71. if(lna_enabled) {
  72. digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW); // LNA on
  73. } else {
  74. digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); // LNA bypass
  75. }
  76. }
  77. }
  78. void LoRaFEMControl::setRxModeEnableWhenMCUSleep(void)
  79. {
  80. digitalWrite(P_LORA_PA_POWER, HIGH);
  81. rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
  82. if(fem_type==GC1109_PA) {
  83. digitalWrite(P_LORA_GC1109_PA_EN, HIGH);
  84. rtc_gpio_hold_en((gpio_num_t)P_LORA_GC1109_PA_EN);
  85. gpio_pulldown_en((gpio_num_t)P_LORA_GC1109_PA_TX_EN);
  86. } else if(fem_type==KCT8103L_PA) {
  87. digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
  88. rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
  89. if(lna_enabled) {
  90. digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW); // LNA on
  91. } else {
  92. digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); // LNA bypass
  93. }
  94. rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CTX);
  95. }
  96. }
  97. void LoRaFEMControl::setLNAEnable(bool enabled)
  98. {
  99. lna_enabled = enabled;
  100. }