-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathir_transmit.cpp
More file actions
132 lines (110 loc) · 3.91 KB
/
Copy pathir_transmit.cpp
File metadata and controls
132 lines (110 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "ir_transmit.h"
#include <IRutils.h>
#include <WiFi.h>
#include "esp_task_wdt.h"
// Mutex para proteger seção crítica de transmissão IR
static portMUX_TYPE irMux = portMUX_INITIALIZER_UNLOCKED;
IRTransmitManager::IRTransmitManager()
: _irsend(IR_SEND_PIN),
_ac(IR_SEND_PIN) {
}
void IRTransmitManager::begin() {
_irsend.begin();
// Desabilitar Wi-Fi sleep mode para reduzir jitter nas transmissões IR
WiFi.setSleep(false);
Serial.println("[IR-TX] Transmissor iniciado no GPIO " + String(IR_SEND_PIN));
Serial.println("[IR-TX] WiFi sleep desabilitado");
}
bool IRTransmitManager::sendByProtocol(const String& protocol, const String& hexCode,
uint16_t bits, uint16_t repeat) {
decode_type_t type = _stringToProtocol(protocol);
if (type == decode_type_t::UNKNOWN) {
Serial.println("[IR-TX] Protocolo desconhecido: " + protocol);
return false;
}
if (hasACState(type)) {
uint16_t stateLen = bits / 8;
uint8_t state[stateLen];
String hex = hexCode;
hex.replace("0x", "");
hex.replace("0X", "");
for (uint16_t i = 0; i < stateLen && (i * 2 + 1) < hex.length(); i++) {
String byteStr = hex.substring(i * 2, i * 2 + 2);
state[i] = (uint8_t)strtoul(byteStr.c_str(), NULL, 16);
}
yield();
portENTER_CRITICAL(&irMux);
bool success = _irsend.send(type, state, stateLen);
portEXIT_CRITICAL(&irMux);
yield();
Serial.println("[IR-TX] State enviado (protegido): " + protocol + " " +
String(success ? "OK" : "FALHA"));
return success;
} else {
uint64_t value = strtoull(hexCode.c_str(), NULL, 16);
yield();
portENTER_CRITICAL(&irMux);
bool success = _irsend.send(type, value, bits, repeat);
portEXIT_CRITICAL(&irMux);
yield();
Serial.println("[IR-TX] Enviado (protegido): " + protocol + " " +
String(success ? "OK" : "FALHA"));
return success;
}
}
bool IRTransmitManager::sendRaw(uint16_t timings[], uint16_t count, uint16_t freqKhz) {
// Feed do watchdog antes de entrar na seção crítica
yield();
// Seção crítica: desabilita todas as interrupções do core atual
// Isso protege o timing da transmissão contra interrupções do Wi-Fi,
// WebServer, WebSocket e outras tasks do FreeRTOS
portENTER_CRITICAL(&irMux);
_irsend.sendRaw(timings, count, freqKhz);
portEXIT_CRITICAL(&irMux);
// Feed do watchdog ao sair
yield();
Serial.println("[IR-TX] Raw enviado (protegido): " + String(count) + " timings @ " +
String(freqKhz) + "kHz");
return true;
}
bool IRTransmitManager::replayFromJSON(const String& json) {
// Extrair raw timings do JSON
// Procurar "timings":[...]
int start = json.indexOf("\"timings\":[");
if (start < 0) return false;
start = json.indexOf("[", start);
int end = json.indexOf("]", start);
if (end < 0) return false;
String timingsStr = json.substring(start + 1, end);
// Contar timings
uint16_t count = 1;
for (int i = 0; i < timingsStr.length(); i++) {
if (timingsStr.charAt(i) == ',') count++;
}
// Parse timings
uint16_t timings[count];
int idx = 0;
int pos = 0;
while (pos < timingsStr.length() && idx < count) {
int comma = timingsStr.indexOf(',', pos);
if (comma < 0) comma = timingsStr.length();
String val = timingsStr.substring(pos, comma);
val.trim();
timings[idx++] = (uint16_t)val.toInt();
pos = comma + 1;
}
return sendRaw(timings, count, 38);
}
decode_type_t IRTransmitManager::_stringToProtocol(const String& name) {
// Usar a função da biblioteca para converter string -> enum
String upper = name;
upper.toUpperCase();
for (int i = 0; i <= (int)decode_type_t::kLastDecodeType; i++) {
String pName = typeToString((decode_type_t)i);
pName.toUpperCase();
if (pName == upper) {
return (decode_type_t)i;
}
}
return decode_type_t::UNKNOWN;
}