infrared_controller.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include "infrared_controller.h"
  2. #include <furi.h>
  3. #include <infrared_worker.h>
  4. #include <infrared_signal.h>
  5. #include <notification/notification_messages.h>
  6. #define TAG "InfraredController"
  7. const NotificationSequence sequence_hit = {
  8. &message_vibro_on,
  9. &message_note_d4,
  10. &message_delay_1000,
  11. &message_vibro_off,
  12. &message_sound_off,
  13. NULL,
  14. };
  15. struct InfraredController {
  16. LaserTagTeam team;
  17. InfraredWorker* worker;
  18. InfraredSignal* signal;
  19. NotificationApp* notification;
  20. bool hit_received;
  21. bool processing_signal;
  22. };
  23. static void infrared_rx_callback(void* context, InfraredWorkerSignal* received_signal) {
  24. FURI_LOG_I(TAG, "RX callback triggered");
  25. InfraredController* controller = (InfraredController*)context;
  26. if(controller->processing_signal) {
  27. FURI_LOG_W(TAG, "Already processing a signal, skipping callback");
  28. return;
  29. }
  30. controller->processing_signal = true;
  31. if(!received_signal) {
  32. FURI_LOG_E(TAG, "Received signal is NULL");
  33. controller->processing_signal = false;
  34. return;
  35. }
  36. const InfraredMessage* message = infrared_worker_get_decoded_signal(received_signal);
  37. FURI_LOG_I(TAG, "Received signal - signal address: %p", (void*)received_signal);
  38. if(message) {
  39. FURI_LOG_I(
  40. TAG,
  41. "Received message: protocol=%d, address=0x%lx, command=0x%lx",
  42. message->protocol,
  43. (unsigned long)message->address,
  44. (unsigned long)message->command);
  45. if((controller->team == TeamRed && message->command == IR_COMMAND_BLUE_TEAM) ||
  46. (controller->team == TeamBlue && message->command == IR_COMMAND_RED_TEAM)) {
  47. controller->hit_received = true;
  48. FURI_LOG_I(
  49. TAG, "Hit detected for team: %s", controller->team == TeamRed ? "Red" : "Blue");
  50. notification_message_block(controller->notification, &sequence_hit);
  51. }
  52. } else {
  53. FURI_LOG_W(TAG, "RX callback received NULL message");
  54. }
  55. FURI_LOG_I(TAG, "RX callback completed");
  56. controller->processing_signal = false;
  57. }
  58. InfraredController* infrared_controller_alloc() {
  59. FURI_LOG_I(TAG, "Allocating InfraredController");
  60. InfraredController* controller = malloc(sizeof(InfraredController));
  61. if(!controller) {
  62. FURI_LOG_E(TAG, "Failed to allocate InfraredController");
  63. return NULL;
  64. }
  65. controller->team = TeamRed;
  66. controller->worker = infrared_worker_alloc();
  67. controller->signal = infrared_signal_alloc();
  68. controller->notification = furi_record_open(RECORD_NOTIFICATION);
  69. controller->hit_received = false;
  70. controller->processing_signal = false;
  71. if(controller->worker && controller->signal && controller->notification) {
  72. FURI_LOG_I(
  73. TAG, "InfraredWorker, InfraredSignal, and NotificationApp allocated successfully");
  74. } else {
  75. FURI_LOG_E(TAG, "Failed to allocate resources");
  76. free(controller);
  77. return NULL;
  78. }
  79. FURI_LOG_I(TAG, "Setting up RX callback");
  80. infrared_worker_rx_set_received_signal_callback(
  81. controller->worker, infrared_rx_callback, controller);
  82. FURI_LOG_I(TAG, "InfraredController allocated successfully");
  83. return controller;
  84. }
  85. void infrared_controller_free(InfraredController* controller) {
  86. FURI_LOG_I(TAG, "Freeing InfraredController");
  87. if(controller) {
  88. FURI_LOG_I(TAG, "Stopping InfraredWorker RX");
  89. infrared_worker_rx_stop(controller->worker);
  90. FURI_LOG_I(TAG, "Freeing InfraredWorker and InfraredSignal");
  91. infrared_worker_free(controller->worker);
  92. infrared_signal_free(controller->signal);
  93. FURI_LOG_I(TAG, "Closing NotificationApp");
  94. furi_record_close(RECORD_NOTIFICATION);
  95. free(controller);
  96. FURI_LOG_I(TAG, "InfraredController freed successfully");
  97. } else {
  98. FURI_LOG_W(TAG, "Attempted to free NULL InfraredController");
  99. }
  100. }
  101. void infrared_controller_set_team(InfraredController* controller, LaserTagTeam team) {
  102. FURI_LOG_I(TAG, "Setting team to %s", team == TeamRed ? "Red" : "Blue");
  103. controller->team = team;
  104. }
  105. void infrared_controller_send(InfraredController* controller) {
  106. FURI_LOG_I(TAG, "Preparing to send infrared signal");
  107. InfraredMessage message = {
  108. .protocol = InfraredProtocolNEC,
  109. .address = 0x00,
  110. .command = (controller->team == TeamRed) ? IR_COMMAND_RED_TEAM : IR_COMMAND_BLUE_TEAM};
  111. FURI_LOG_I(
  112. TAG,
  113. "Prepared message: protocol=%d, address=0x%lx, command=0x%lx",
  114. message.protocol,
  115. (unsigned long)message.address,
  116. (unsigned long)message.command);
  117. FURI_LOG_I(TAG, "Setting message for infrared signal");
  118. infrared_signal_set_message(controller->signal, &message);
  119. FURI_LOG_I(TAG, "Starting infrared signal transmission");
  120. infrared_signal_transmit(controller->signal);
  121. FURI_LOG_I(TAG, "Infrared signal transmission completed");
  122. }
  123. bool infrared_controller_receive(InfraredController* controller) {
  124. FURI_LOG_I(TAG, "Starting infrared signal reception");
  125. if(controller->processing_signal) {
  126. FURI_LOG_W(TAG, "Cannot start reception, another signal is still being processed");
  127. return false;
  128. }
  129. infrared_worker_rx_start(controller->worker);
  130. furi_delay_ms(50);
  131. infrared_worker_rx_stop(controller->worker);
  132. bool hit = controller->hit_received;
  133. FURI_LOG_I(TAG, "Signal reception complete, hit received: %s", hit ? "true" : "false");
  134. controller->hit_received = false;
  135. return hit;
  136. }