ESPHome 2026.3.0
Loading...
Searching...
No Matches
LwTx.cpp
Go to the documentation of this file.
1// LwTx.cpp
2//
3// LightwaveRF 434MHz tx interface for Arduino
4//
5// Author: Bob Tidey ([email protected])
6#ifdef USE_ESP8266
7
8#include "LwTx.h"
9#include <cstring>
10#include <Arduino.h>
12#include "esphome/core/log.h"
13
14namespace esphome {
15namespace lightwaverf {
16
17static const uint8_t TX_NIBBLE[] = {0xF6, 0xEE, 0xED, 0xEB, 0xDE, 0xDD, 0xDB, 0xBE,
18 0xBD, 0xBB, 0xB7, 0x7E, 0x7D, 0x7B, 0x77, 0x6F};
19
20static const uint8_t TX_STATE_IDLE = 0;
21static const uint8_t TX_STATE_MSGSTART = 1;
22static const uint8_t TX_STATE_BYTESTART = 2;
23static const uint8_t TX_STATE_SENDBYTE = 3;
24static const uint8_t TX_STATE_MSGEND = 4;
25static const uint8_t TX_STATE_GAPSTART = 5;
26static const uint8_t TX_STATE_GAPEND = 6;
30void LwTx::lwtx_settranslate(bool txtranslate) { tx_translate = txtranslate; }
31
32static void IRAM_ATTR isr_t_xtimer(LwTx *arg) {
33 // Set low after toggle count interrupts
34 arg->tx_toggle_count--;
35 if (arg->tx_toggle_count == arg->tx_trail_count) {
36 // ESP_LOGD("lightwaverf.sensor", "timer")
37 arg->tx_pin->digital_write(arg->txoff);
38 } else if (arg->tx_toggle_count == 0) {
39 arg->tx_toggle_count = arg->tx_high_count; // default high pulse duration
40 switch (arg->tx_state) {
41 case TX_STATE_IDLE:
42 if (arg->tx_msg_active) {
43 arg->tx_repeat = 0;
44 arg->tx_state = TX_STATE_MSGSTART;
45 }
46 break;
47 case TX_STATE_MSGSTART:
48 arg->tx_pin->digital_write(arg->txon);
49 arg->tx_num_bytes = 0;
50 arg->tx_state = TX_STATE_BYTESTART;
51 break;
52 case TX_STATE_BYTESTART:
53 arg->tx_pin->digital_write(arg->txon);
54 arg->tx_bit_mask = 0x80;
55 arg->tx_state = TX_STATE_SENDBYTE;
56 break;
57 case TX_STATE_SENDBYTE:
58 if (arg->tx_buf[arg->tx_num_bytes] & arg->tx_bit_mask) {
59 arg->tx_pin->digital_write(arg->txon);
60 } else {
61 // toggle count for the 0 pulse
62 arg->tx_toggle_count = arg->tx_low_count;
63 }
64 arg->tx_bit_mask >>= 1;
65 if (arg->tx_bit_mask == 0) {
66 arg->tx_num_bytes++;
68 arg->tx_state = TX_STATE_MSGEND;
69 } else {
70 arg->tx_state = TX_STATE_BYTESTART;
71 }
72 }
73 break;
74 case TX_STATE_MSGEND:
75 arg->tx_pin->digital_write(arg->txon);
76 arg->tx_state = TX_STATE_GAPSTART;
78 break;
79 case TX_STATE_GAPSTART:
80 arg->tx_toggle_count = arg->tx_gap_count;
81 if (arg->tx_gap_repeat == 0) {
82 arg->tx_state = TX_STATE_GAPEND;
83 } else {
84 arg->tx_gap_repeat--;
85 }
86 break;
87 case TX_STATE_GAPEND:
88 arg->tx_repeat++;
89 if (arg->tx_repeat >= arg->tx_repeats) {
90 // disable timer nterrupt
91 arg->lw_timer_stop();
92 arg->tx_msg_active = false;
93 arg->tx_state = TX_STATE_IDLE;
94 } else {
95 arg->tx_state = TX_STATE_MSGSTART;
96 }
97 break;
98 }
99 }
100}
101
105bool LwTx::lwtx_free() { return !this->tx_msg_active; }
106
110void LwTx::lwtx_send(const std::vector<uint8_t> &msg) {
111 if (msg.size() < TX_MSGLEN) {
112 ESP_LOGW("lightwaverf.sensor", "Message too short: %zu < %u", msg.size(), static_cast<unsigned>(TX_MSGLEN));
113 return;
114 }
115 if (this->tx_translate) {
116 for (uint8_t i = 0; i < TX_MSGLEN; i++) {
117 this->tx_buf[i] = TX_NIBBLE[msg[i] & 0xF];
118 ESP_LOGD("lightwaverf.sensor", "%x ", msg[i]);
119 }
120 } else {
121 // memcpy(tx_buf, msg, tx_msglen);
122 }
123 this->lw_timer_start();
124 this->tx_msg_active = true;
125}
126
130void LwTx::lwtx_setaddr(const uint8_t *addr) {
131 for (uint8_t i = 0; i < 5; i++) {
132 this->tx_buf[i + 4] = TX_NIBBLE[addr[i] & 0xF];
133 }
134}
135
139void LwTx::lwtx_cmd(uint8_t command, uint8_t parameter, uint8_t room, uint8_t device) {
140 // enable timer 2 interrupts
141 this->tx_buf[0] = TX_NIBBLE[parameter >> 4];
142 this->tx_buf[1] = TX_NIBBLE[parameter & 0xF];
143 this->tx_buf[2] = TX_NIBBLE[device & 0xF];
144 this->tx_buf[3] = TX_NIBBLE[command & 0xF];
145 this->tx_buf[9] = TX_NIBBLE[room & 0xF];
146 this->lw_timer_start();
147 this->tx_msg_active = true;
148}
149
153void LwTx::lwtx_setup(InternalGPIOPin *pin, uint8_t repeats, bool inverted, int u_sec) {
154 pin->setup();
155 tx_pin = pin;
156
159
160 if (repeats > 0 && repeats < 40) {
161 this->tx_repeats = repeats;
162 }
163 if (inverted) {
164 this->txon = 0;
165 this->txoff = 1;
166 } else {
167 this->txon = 1;
168 this->txoff = 0;
169 }
170
171 int period1 = 330;
172 /*
173 if (period > 32 && period < 1000) {
174 period1 = period;
175 } else {
176 // default 330 uSec
177 period1 = 330;
178 }*/
179 this->espPeriod = 5 * period1;
180 timer1_isr_init();
181}
182
183void LwTx::lwtx_set_tick_counts(uint8_t low_count, uint8_t high_count, uint8_t trail_count, uint8_t gap_count) {
184 this->tx_low_count = low_count;
185 this->tx_high_count = high_count;
186 this->tx_trail_count = trail_count;
187 this->tx_gap_count = gap_count;
188}
189
190void LwTx::lwtx_set_gap_multiplier(uint8_t gap_multiplier) { this->tx_gap_multiplier = gap_multiplier; }
191
193 {
194 InterruptLock lock;
195 static LwTx *arg;
196 arg = this;
197 timer1_attachInterrupt([] { isr_t_xtimer(arg); });
198 timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
199 timer1_write(this->espPeriod);
200 }
201}
202
204 {
205 InterruptLock lock;
206 timer1_disable();
207 timer1_detachInterrupt();
208 }
209}
210
211} // namespace lightwaverf
212} // namespace esphome
213#endif
virtual void pin_mode(gpio::Flags flags)=0
virtual void setup()=0
virtual void digital_write(bool value)=0
Helper class to disable interrupts.
Definition helpers.h:1791
void lwtx_set_gap_multiplier(uint8_t gap_multiplier)
Definition LwTx.cpp:190
uint8_t tx_buf[TX_MSGLEN]
Definition LwTx.h:68
void lwtx_setup(InternalGPIOPin *pin, uint8_t repeats, bool inverted, int u_sec)
Set things up to transmit LightWaveRF 434Mhz messages.
Definition LwTx.cpp:153
void lwtx_set_tick_counts(uint8_t low_count, uint8_t high_count, uint8_t trail_count, uint8_t gap_count)
Definition LwTx.cpp:183
static const uint8_t TX_MSGLEN
Definition LwTx.h:59
InternalGPIOPin * tx_pin
Definition LwTx.h:86
volatile bool tx_msg_active
Definition LwTx.h:65
void lwtx_send(const std::vector< uint8_t > &msg)
Send a LightwaveRF message (10 nibbles in bytes)
Definition LwTx.cpp:110
void lwtx_settranslate(bool txtranslate)
Set translate mode.
Definition LwTx.cpp:30
void lwtx_cmd(uint8_t command, uint8_t parameter, uint8_t room, uint8_t device)
Send a LightwaveRF message (10 nibbles in bytes)
Definition LwTx.cpp:139
uint8_t tx_gap_multiplier
Definition LwTx.h:81
void lwtx_setaddr(const uint8_t *addr)
Set 5 char address for future messages.
Definition LwTx.cpp:130
bool lwtx_free()
Check for send free.
Definition LwTx.cpp:105
@ FLAG_OUTPUT
Definition gpio.h:28
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7