ESPHome 2025.5.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>
11#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 (this->tx_translate) {
112 for (uint8_t i = 0; i < TX_MSGLEN; i++) {
113 this->tx_buf[i] = TX_NIBBLE[msg[i] & 0xF];
114 ESP_LOGD("lightwaverf.sensor", "%x ", msg[i]);
115 }
116 } else {
117 // memcpy(tx_buf, msg, tx_msglen);
118 }
119 this->lw_timer_start();
120 this->tx_msg_active = true;
121}
122
126void LwTx::lwtx_setaddr(const uint8_t *addr) {
127 for (uint8_t i = 0; i < 5; i++) {
128 this->tx_buf[i + 4] = TX_NIBBLE[addr[i] & 0xF];
129 }
130}
131
135void LwTx::lwtx_cmd(uint8_t command, uint8_t parameter, uint8_t room, uint8_t device) {
136 // enable timer 2 interrupts
137 this->tx_buf[0] = TX_NIBBLE[parameter >> 4];
138 this->tx_buf[1] = TX_NIBBLE[parameter & 0xF];
139 this->tx_buf[2] = TX_NIBBLE[device & 0xF];
140 this->tx_buf[3] = TX_NIBBLE[command & 0xF];
141 this->tx_buf[9] = TX_NIBBLE[room & 0xF];
142 this->lw_timer_start();
143 this->tx_msg_active = true;
144}
145
149void LwTx::lwtx_setup(InternalGPIOPin *pin, uint8_t repeats, bool inverted, int u_sec) {
150 pin->setup();
151 tx_pin = pin;
152
155
156 if (repeats > 0 && repeats < 40) {
157 this->tx_repeats = repeats;
158 }
159 if (inverted) {
160 this->txon = 0;
161 this->txoff = 1;
162 } else {
163 this->txon = 1;
164 this->txoff = 0;
165 }
166
167 int period1 = 330;
168 /*
169 if (period > 32 && period < 1000) {
170 period1 = period;
171 } else {
172 // default 330 uSec
173 period1 = 330;
174 }*/
175 this->espPeriod = 5 * period1;
176 timer1_isr_init();
177}
178
179void LwTx::lwtx_set_tick_counts(uint8_t low_count, uint8_t high_count, uint8_t trail_count, uint8_t gap_count) {
180 this->tx_low_count = low_count;
181 this->tx_high_count = high_count;
182 this->tx_trail_count = trail_count;
183 this->tx_gap_count = gap_count;
184}
185
186void LwTx::lwtx_set_gap_multiplier(uint8_t gap_multiplier) { this->tx_gap_multiplier = gap_multiplier; }
187
189 {
190 InterruptLock lock;
191 static LwTx *arg = this; // NOLINT
192 timer1_attachInterrupt([] { isr_t_xtimer(arg); });
193 timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
194 timer1_write(this->espPeriod);
195 }
196}
197
199 {
200 InterruptLock lock;
201 timer1_disable();
202 timer1_detachInterrupt();
203 }
204}
205
206} // namespace lightwaverf
207} // namespace esphome
208#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:614
void lwtx_set_gap_multiplier(uint8_t gap_multiplier)
Definition LwTx.cpp:186
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:149
void lwtx_set_tick_counts(uint8_t low_count, uint8_t high_count, uint8_t trail_count, uint8_t gap_count)
Definition LwTx.cpp:179
static const uint8_t TX_MSGLEN
Definition LwTx.h:59
InternalGPIOPin * tx_pin
Definition LwTx.h:86
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:135
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:126
bool lwtx_free()
Check for send free.
Definition LwTx.cpp:105
@ FLAG_OUTPUT
Definition gpio.h:19
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7