nexaTransmit.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <sys/time.h>
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "esp_sleep.h"
  9. #include "esp_log.h"
  10. #include "driver/uart.h"
  11. #include "driver/rtc_io.h"
  12. #include "esp_intr_alloc.h"
  13. #include "esp_attr.h"
  14. #include "driver/timer.h"
  15. #include <stddef.h>
  16. #include "esp_intr_alloc.h"
  17. #include "transceiver.h"
  18. #include "rxTimer.h"
  19. #include "led.h"
  20. #include "udp_client.h"
  21. #include "nexaTransmit.h"
  22. QueueHandle_t nexaTxQueue = NULL;
  23. /*****************************************************************************
  24. * Nexa : http://elektronikforumet.com/wiki/index.php/RF_Protokoll_-_Nexa_sj%C3%A4lvl%C3%A4rande
  25. * "1" = 295 µs hög och 170 µs låg
  26. * "0" = 295 µs hög och 920 µs låg
  27. * Etta skickas som 10 och Nolla som 01
  28. * Dessa siffror från web-sidan stämmer inte med den Nexa-kontroll som jag har.
  29. * Jag har rättat dessa med siffror från verkligheten. Finns i define's nedan.
  30. *
  31. * ---------------------------------------------------------------------------
  32. * From: https://github.com/TheCarlG/NexaCtrl/blob/master/NexaCtrl.cpp
  33. *
  34. * bits 0-25: the group code - a 26bit number assigned to controllers.
  35. * bit 26: group flag
  36. * bit 27: on/off/dim flag
  37. * bits 28-31: the device code - 4bit number.
  38. * bits 32-35: the dim level - 4bit number.
  39. *
  40. * The extra 4 dim bits are optional and used for setting absolute dim level
  41. * Normally the on/off-bit is transmitted as a normal On=10, Off=01, but when
  42. * including a dim-level the on/off-bit is transmitted as 00
  43. *
  44. * Dim levels are 0-15. 0=Lowest dim, 15=100%
  45. * 0 is not off. A separate off needs to be sent to turn the light off.
  46. * ***************************************************************************/
  47. // <NT01995080>
  48. // <NT01995090>
  49. // Timing for NEXA Remote controls
  50. #define HIGH_PULSE 260
  51. #define LOW_PULSE_0 310
  52. #define LOW_PULSE_1 1330
  53. #define SYNC_PULSE 2720
  54. #define STOP_PULSE 10000
  55. static void send1() {
  56. trcvSendHighLowPulse( HIGH_PULSE, LOW_PULSE_1); // 1
  57. trcvSendHighLowPulse( HIGH_PULSE, LOW_PULSE_0 ); // 0
  58. }
  59. static void send0() {
  60. trcvSendHighLowPulse( HIGH_PULSE, LOW_PULSE_0 ); // 0
  61. trcvSendHighLowPulse( HIGH_PULSE, LOW_PULSE_1); // 1
  62. }
  63. // Special 00-bit used when including 4 dim bits last in message
  64. static void send00() {
  65. trcvSendHighLowPulse( HIGH_PULSE, LOW_PULSE_0 ); // 0
  66. trcvSendHighLowPulse( HIGH_PULSE, LOW_PULSE_0); // 0
  67. }
  68. static void sendSync() {
  69. trcvSendHighLowPulse( HIGH_PULSE, SYNC_PULSE );
  70. }
  71. static void sendStop() {
  72. trcvSendHighLowPulse( HIGH_PULSE, STOP_PULSE );
  73. }
  74. static void sendNexaCodeNo(uint32_t orig_code, bool send_dim, uint8_t dim_level) {
  75. uint32_t code=0;
  76. int32_t i;
  77. int32_t loop;
  78. if( send_dim == true )
  79. ESP_LOGI("NEXA TX", "<NT%08lX> + Dim:%u",(unsigned long int)orig_code, dim_level);
  80. else
  81. ESP_LOGI("NEXA TX", "<NT%08lX>",(unsigned long int)orig_code);
  82. blinkTheLED();
  83. if( 1 ) {
  84. trcvSwitch2transmit();
  85. for( loop=5; loop>0; loop--) {
  86. code = orig_code;
  87. sendSync();
  88. for(i=0; i < 32; i++) {
  89. // Bit 27 is the on/off/dim-bit
  90. // Check if we should send it as a special dim-bit
  91. if( i == 27 && send_dim == true ) {
  92. send00();
  93. }
  94. else {
  95. // Normal on/off control
  96. if( code & 0x80000000 ) send1(); else send0();
  97. }
  98. code = (code << 1);
  99. }
  100. code = dim_level;
  101. // Check if we should send 4 extra dim-bits at the end
  102. if( send_dim == true ) {
  103. for(i=0; i < 4; i++) {
  104. if( code & 0x00000008 ) send1(); else send0();
  105. code = (code << 1);
  106. }
  107. }
  108. sendStop();
  109. }
  110. trcvSwitch2receive();
  111. }
  112. }
  113. /**
  114. * Public interface for sending a NEXA Code
  115. */
  116. void sendNexaCode(uint32_t data, bool send_dim, uint8_t dim_level ) {
  117. nexaCodeData_t txData;
  118. txData.data = data;
  119. txData.send_dim = send_dim;
  120. txData.dim_level = dim_level;
  121. if( nexaTxQueue != NULL ) xQueueSend( nexaTxQueue, &txData, 0 );
  122. }
  123. // Public interface for sending a NEXA Code in string format. For example: <NT4C90AD91>
  124. void sendNexaCodeStr(char *str) {
  125. const uint32_t now = millis();
  126. static char oldData[40];
  127. static uint32_t oldDataTime = 0;
  128. // Check if we have a retransmission of exactly the same data within 250mS
  129. // If we have a identical re-transmission, then skip that one
  130. if( ((now - oldDataTime) < 250) && strncmp(str,oldData,40)==0 ) {
  131. ESP_LOGW("NEXA TX", "Retransm: %10d mS",now - oldDataTime);
  132. oldDataTime = now;
  133. return;
  134. }
  135. strncpy(oldData,str,40);
  136. oldDataTime = now;
  137. char diffLevel = '\0'; // 0-F = 0-15 Dim-level
  138. if( strlen(str) == 13 && str[0] == '<' && str[12] == '>' ) {
  139. diffLevel = str[11]; // 0-F = 0-15 Dim-level
  140. str[11] = '>';
  141. str[12] = '\0';
  142. }
  143. if( strlen(str) == 12 && str[0] == '<' && str[11] == '>' ) {
  144. uint32_t code;
  145. bool send_dim = (diffLevel == '\0') ? false : true;
  146. uint8_t dim_level = (send_dim == true) ? diffLevel - '0' : 0;
  147. sscanf((const char *)str,"<NT%08lX>",(long unsigned int *)&code);
  148. sendNexaCode(code, send_dim, dim_level);
  149. }
  150. }
  151. // GIT ESP32 Before: 0ae960f2fe92de1ee9c7c624b7115d06faca119e
  152. static void nexaTxTask(void *pvParameter)
  153. {
  154. ESP_LOGI("NEXA TX", "Task started.");
  155. nexaCodeData_t txData;
  156. while (1)
  157. {
  158. while( xQueueReceive( nexaTxQueue, &txData, portMAX_DELAY ) == pdTRUE ) {
  159. sendNexaCodeNo(txData.data, txData.send_dim, txData.dim_level); // Do the radio-transmission
  160. // Forward the NEXA code to the next transceiver
  161. char strCode[20];
  162. sprintf(strCode,"<NT%08lX>",(unsigned long int)txData.data);
  163. forwardNEXAMessage(strCode);
  164. vTaskDelay(200 / portTICK_PERIOD_MS); // Wait a while between transmits
  165. }
  166. }
  167. vTaskDelete(NULL);
  168. }
  169. void initNexaTransmit() {
  170. nexaTxQueue = xQueueCreate( 20, sizeof( nexaCodeData_t ) );
  171. xTaskCreatePinnedToCore(&nexaTxTask, "nexaTxTask", 8192, NULL, tskIDLE_PRIORITY + 10, NULL, 1);
  172. }