1
- #include "esp32_rmt_midea_ir_tx.h"
2
-
3
- #define PULSE_LENGTH 557; // Each pulse (one "time" unit or 1T) is 21 cycles of a 38KHz carrier burst (about 550µs long)
4
-
5
- volatile uint8_t _rmt_midea_ir_tx_txPin ;
6
- volatile uint8_t _rmt_midea_ir_tx_channel ;
7
-
8
- /*
9
- Convert a byte to its midea-protocol encoded counterpart as a RMT duration
10
- Idea borrowed from here: https://github.com/kimeckert/ESP32-RMT-Rx-raw
11
- */
12
- void ConvertByteToMideaRmtValues (uint8_t byteValue , int16_t rmtValues [], int16_t rmtValuesIndex , int16_t * rmtCount )
13
- {
14
- // A logic "1" is a 1T pulse followed by a 3T space and takes 2.25ms to transmit
15
- // A logic "0" is a 1T pulse followed by a 1T space and takes 1.125ms
16
-
17
- int16_t currentIndex = rmtValuesIndex ;
18
-
19
- for (int8_t j = 7 ; j >= 0 ; j -- )
20
- {
21
- currentIndex ++ ;
22
- rmtValues [currentIndex ] = 1 * PULSE_LENGTH ; // 1T pulse
23
- currentIndex ++ ;
24
-
25
- int8_t currentBitValue = (byteValue >> j ) & 1 ;
26
- if (currentBitValue == 1 )
27
- {
28
- rmtValues [currentIndex ] = -3 * PULSE_LENGTH ; // 3T space
29
- }
30
- else
31
- {
32
- rmtValues [currentIndex ] = -1 * PULSE_LENGTH ; // 1T space
33
- }
34
- }
35
- * rmtCount = currentIndex ;
36
- }
37
-
38
- /* Converts RMT durations to an array of rmt_item32_t */
39
- void ConvertRmtValuesToRmtObjects (int16_t rmtValues [], int16_t rmtValuesCount , rmt_item32_t rmtObjects [], int16_t * rmtObjectsCount )
40
- {
41
- int16_t rmtObjectsIndex = 0 ;
42
- bool isFirstPartOfRmtObjectOccupied = false;
43
-
44
- for (int16_t i = 0 ; i < rmtValuesCount ; i ++ )
45
- {
46
- if (isFirstPartOfRmtObjectOccupied == false)
47
- {
48
- rmtObjects [rmtObjectsIndex ].duration0 = abs (rmtValues [i ]);
49
- rmtObjects [rmtObjectsIndex ].level0 = (rmtValues [i ] > 0 ) ? 0 : 1 ;
50
- isFirstPartOfRmtObjectOccupied = true;
51
-
52
- rmtObjects [rmtObjectsIndex ].duration1 = 0 ;
53
- rmtObjects [rmtObjectsIndex ].level1 = 0 ;
54
- }
55
- else
56
- {
57
- rmtObjects [rmtObjectsIndex ].duration1 = abs (rmtValues [i ]);
58
- rmtObjects [rmtObjectsIndex ].level1 = (rmtValues [i ] > 0 ) ? 0 : 1 ;
59
- rmtObjectsIndex ++ ;
60
- isFirstPartOfRmtObjectOccupied = false;
61
- }
62
- }
63
- * rmtObjectsCount = rmtObjectsIndex + 1 ;
64
- }
65
-
66
- /* Add the bytes and their complements to the RmtArray */
67
- void AddBytesToRmtArray (uint8_t data [], uint8_t lengthOfData , int16_t rmtValues [], int16_t rmtValuesIndex , int16_t * rmtCount )
68
- {
69
- int16_t rmtValueIndex = rmtValuesIndex ;
70
-
71
- for (int8_t i = 0 ; i < lengthOfData ; i ++ )
72
- {
73
- ConvertByteToMideaRmtValues (data [i ], rmtValues , rmtValueIndex , & rmtValueIndex );
74
- int8_t flipped = (int8_t ) ~data [i ];
75
- ConvertByteToMideaRmtValues (flipped , rmtValues , rmtValueIndex , & rmtValueIndex );
76
- }
77
- * rmtCount = rmtValueIndex ;
78
- }
79
-
80
- /* Send the message using RMT */
81
- void rmt_midea_ir_tx_send_raw_message (uint8_t data [], uint8_t lengthOfData )
82
- {
83
- int16_t rmtValues [200 ] = { 0 };
84
- int16_t rmtValueIndex = -1 ;
85
-
86
- // #pragma region Add the whole message to the RmtArray for the first time
87
-
88
- // The AGC burst consists of a 4.5ms burst followed by 4.5ms space (8T pulse + 8T space)
89
- // frame start markers 4T down, 4T up
90
- rmtValues [0 ] = 8 * PULSE_LENGTH ;
91
- rmtValues [1 ] = -8 * PULSE_LENGTH ;
92
-
93
- rmtValueIndex = 1 ;
94
-
95
- // add the bytes and its complements to the RmtArray
96
- AddBytesToRmtArray (data , lengthOfData , rmtValues , rmtValueIndex , & rmtValueIndex );
97
-
98
- // add the end of frame marker to the RmtArray
99
- rmtValueIndex ++ ;
100
- rmtValues [rmtValueIndex ] = PULSE_LENGTH ;
101
- rmtValueIndex ++ ;
102
- rmtValues [rmtValueIndex ] = -9 * PULSE_LENGTH ;
103
-
104
- // #pragma endregion
105
-
106
- // #pragma region Add the whole message to the RmtArray again
107
-
108
- // frame start markers 4T down, 4T up
109
- rmtValueIndex ++ ;
110
- rmtValues [rmtValueIndex ] = 8 * PULSE_LENGTH ;
111
- rmtValueIndex ++ ;
112
- rmtValues [rmtValueIndex ] = -8 * PULSE_LENGTH ;
113
-
114
- // add the bytes and its complements to the RmtArray
115
- AddBytesToRmtArray (data , lengthOfData , rmtValues , rmtValueIndex , & rmtValueIndex );
116
-
117
- // add the end of frame marker to the RmtArray
118
- rmtValueIndex ++ ;
119
- rmtValues [rmtValueIndex ] = PULSE_LENGTH ;
120
- rmtValueIndex ++ ;
121
- rmtValues [rmtValueIndex ] = 0 ;
122
-
123
- // #pragma endregion
124
-
125
- rmt_item32_t rmtObjects [100 ];
126
- int16_t rmtObjectsCount ;
127
- ConvertRmtValuesToRmtObjects (rmtValues , rmtValueIndex + 1 , rmtObjects , & rmtObjectsCount );
128
-
129
- rmt_write_items (_rmt_midea_ir_tx_channel , rmtObjects , rmtObjectsCount , true);
130
- }
131
-
132
- /* Initialize RMT transmit channel */
133
- void rmt_midea_ir_tx_channel_init (uint8_t channel , uint8_t txPin )
134
- {
135
- _rmt_midea_ir_tx_channel = channel ;
136
- _rmt_midea_ir_tx_txPin = txPin ;
137
-
138
- rmt_config_t rmt_tx ;
139
-
140
- rmt_tx .channel = channel ;
141
- rmt_tx .gpio_num = txPin ;
142
- rmt_tx .clk_div = 80 ; // 1 MHz, 1 us - we set up sampling to every 1 microseconds
143
- rmt_tx .mem_block_num = 2 ;
144
- rmt_tx .rmt_mode = RMT_MODE_TX ;
145
- rmt_tx .tx_config .loop_en = false;
146
- rmt_tx .tx_config .carrier_duty_percent = 25 ;
147
- rmt_tx .tx_config .carrier_freq_hz = 38000 ;
148
- rmt_tx .tx_config .carrier_level = RMT_CARRIER_LEVEL_LOW ;
149
- rmt_tx .tx_config .carrier_en = true;
150
- rmt_tx .tx_config .idle_level = RMT_IDLE_LEVEL_HIGH ;
151
- rmt_tx .tx_config .idle_output_en = true;
152
-
153
- rmt_config (& rmt_tx );
154
- rmt_driver_install (rmt_tx .channel , 0 , 0 );
155
-
156
- // start the channel
157
- rmt_tx_start (_rmt_midea_ir_tx_channel , 1 );
158
- }
159
-
160
- /* Uninstall the RMT driver */
161
- void rmt_midea_ir_tx_channel_stop (uint8_t channel )
162
- {
163
- rmt_driver_uninstall (channel );
1
+ #include "esp32_rmt_midea_ir_tx.h"
2
+
3
+ #define PULSE_LENGTH 557; // Each pulse (one "time" unit or 1T) is 21 cycles of a 38KHz carrier burst (about 550µs long)
4
+
5
+ volatile uint8_t _rmt_midea_ir_tx_txPin ;
6
+ volatile uint8_t _rmt_midea_ir_tx_channel ;
7
+
8
+ /*
9
+ Convert a byte to its midea-protocol encoded counterpart as a RMT duration
10
+ Idea borrowed from here: https://github.com/kimeckert/ESP32-RMT-Rx-raw
11
+ */
12
+ void ConvertByteToMideaRmtValues (uint8_t byteValue , int16_t rmtValues [], int16_t rmtValuesIndex , int16_t * rmtCount )
13
+ {
14
+ // A logic "1" is a 1T pulse followed by a 3T space and takes 2.25ms to transmit
15
+ // A logic "0" is a 1T pulse followed by a 1T space and takes 1.125ms
16
+
17
+ int16_t currentIndex = rmtValuesIndex ;
18
+
19
+ for (int8_t j = 7 ; j >= 0 ; j -- )
20
+ {
21
+ currentIndex ++ ;
22
+ rmtValues [currentIndex ] = 1 * PULSE_LENGTH ; // 1T pulse
23
+ currentIndex ++ ;
24
+
25
+ int8_t currentBitValue = (byteValue >> j ) & 1 ;
26
+ if (currentBitValue == 1 )
27
+ {
28
+ rmtValues [currentIndex ] = -3 * PULSE_LENGTH ; // 3T space
29
+ }
30
+ else
31
+ {
32
+ rmtValues [currentIndex ] = -1 * PULSE_LENGTH ; // 1T space
33
+ }
34
+ }
35
+ * rmtCount = currentIndex ;
36
+ }
37
+
38
+ /* Converts RMT durations to an array of rmt_item32_t */
39
+ void ConvertRmtValuesToRmtObjects (int16_t rmtValues [], int16_t rmtValuesCount , rmt_item32_t rmtObjects [], int16_t * rmtObjectsCount )
40
+ {
41
+ int16_t rmtObjectsIndex = 0 ;
42
+ bool isFirstPartOfRmtObjectOccupied = false;
43
+
44
+ for (int16_t i = 0 ; i < rmtValuesCount ; i ++ )
45
+ {
46
+ if (isFirstPartOfRmtObjectOccupied == false)
47
+ {
48
+ rmtObjects [rmtObjectsIndex ].duration0 = abs (rmtValues [i ]);
49
+ rmtObjects [rmtObjectsIndex ].level0 = (rmtValues [i ] > 0 ) ? 0 : 1 ;
50
+ isFirstPartOfRmtObjectOccupied = true;
51
+
52
+ rmtObjects [rmtObjectsIndex ].duration1 = 0 ;
53
+ rmtObjects [rmtObjectsIndex ].level1 = 0 ;
54
+ }
55
+ else
56
+ {
57
+ rmtObjects [rmtObjectsIndex ].duration1 = abs (rmtValues [i ]);
58
+ rmtObjects [rmtObjectsIndex ].level1 = (rmtValues [i ] > 0 ) ? 0 : 1 ;
59
+ rmtObjectsIndex ++ ;
60
+ isFirstPartOfRmtObjectOccupied = false;
61
+ }
62
+ }
63
+ * rmtObjectsCount = rmtObjectsIndex + 1 ;
64
+ }
65
+
66
+ /* Add the bytes and their complements to the RmtArray */
67
+ void AddBytesToRmtArray (uint8_t data [], uint8_t lengthOfData , int16_t rmtValues [], int16_t rmtValuesIndex , int16_t * rmtCount )
68
+ {
69
+ int16_t rmtValueIndex = rmtValuesIndex ;
70
+
71
+ for (int8_t i = 0 ; i < lengthOfData ; i ++ )
72
+ {
73
+ ConvertByteToMideaRmtValues (data [i ], rmtValues , rmtValueIndex , & rmtValueIndex );
74
+ int8_t flipped = (int8_t ) ~data [i ];
75
+ ConvertByteToMideaRmtValues (flipped , rmtValues , rmtValueIndex , & rmtValueIndex );
76
+ }
77
+ * rmtCount = rmtValueIndex ;
78
+ }
79
+
80
+ /* Send the message using RMT */
81
+ void rmt_midea_ir_tx_send_raw_message (uint8_t data [], uint8_t lengthOfData )
82
+ {
83
+ int16_t rmtValues [200 ] = { 0 };
84
+ int16_t rmtValueIndex = -1 ;
85
+
86
+ // #pragma region Add the whole message to the RmtArray for the first time
87
+
88
+ // The AGC burst consists of a 4.5ms burst followed by 4.5ms space (8T pulse + 8T space)
89
+ // frame start markers 4T down, 4T up
90
+ rmtValues [0 ] = 8 * PULSE_LENGTH ;
91
+ rmtValues [1 ] = -8 * PULSE_LENGTH ;
92
+
93
+ rmtValueIndex = 1 ;
94
+
95
+ // add the bytes and its complements to the RmtArray
96
+ AddBytesToRmtArray (data , lengthOfData , rmtValues , rmtValueIndex , & rmtValueIndex );
97
+
98
+ // add the end of frame marker to the RmtArray
99
+ rmtValueIndex ++ ;
100
+ rmtValues [rmtValueIndex ] = PULSE_LENGTH ;
101
+ rmtValueIndex ++ ;
102
+ rmtValues [rmtValueIndex ] = -9 * PULSE_LENGTH ;
103
+
104
+ // #pragma endregion
105
+
106
+ // #pragma region Add the whole message to the RmtArray again
107
+
108
+ // frame start markers 4T down, 4T up
109
+ rmtValueIndex ++ ;
110
+ rmtValues [rmtValueIndex ] = 8 * PULSE_LENGTH ;
111
+ rmtValueIndex ++ ;
112
+ rmtValues [rmtValueIndex ] = -8 * PULSE_LENGTH ;
113
+
114
+ // add the bytes and its complements to the RmtArray
115
+ AddBytesToRmtArray (data , lengthOfData , rmtValues , rmtValueIndex , & rmtValueIndex );
116
+
117
+ // add the end of frame marker to the RmtArray
118
+ rmtValueIndex ++ ;
119
+ rmtValues [rmtValueIndex ] = PULSE_LENGTH ;
120
+ rmtValueIndex ++ ;
121
+ rmtValues [rmtValueIndex ] = 0 ;
122
+
123
+ // #pragma endregion
124
+
125
+ rmt_item32_t rmtObjects [100 ];
126
+ int16_t rmtObjectsCount ;
127
+ ConvertRmtValuesToRmtObjects (rmtValues , rmtValueIndex + 1 , rmtObjects , & rmtObjectsCount );
128
+
129
+ rmt_write_items (_rmt_midea_ir_tx_channel , rmtObjects , rmtObjectsCount , true);
130
+ }
131
+
132
+ /* Initialize RMT transmit channel */
133
+ void rmt_midea_ir_tx_channel_init (uint8_t channel , uint8_t txPin )
134
+ {
135
+ _rmt_midea_ir_tx_channel = channel ;
136
+ _rmt_midea_ir_tx_txPin = txPin ;
137
+
138
+ rmt_config_t rmt_tx ;
139
+
140
+ rmt_tx .channel = channel ;
141
+ rmt_tx .gpio_num = txPin ;
142
+ rmt_tx .clk_div = 80 ; // 1 MHz, 1 us - we set up sampling to every 1 microseconds
143
+ rmt_tx .mem_block_num = 2 ;
144
+ rmt_tx .rmt_mode = RMT_MODE_TX ;
145
+ rmt_tx .tx_config .loop_en = false;
146
+ rmt_tx .tx_config .carrier_duty_percent = 25 ;
147
+ rmt_tx .tx_config .carrier_freq_hz = 38000 ;
148
+ rmt_tx .tx_config .carrier_level = RMT_CARRIER_LEVEL_LOW ;
149
+ rmt_tx .tx_config .carrier_en = true;
150
+ rmt_tx .tx_config .idle_level = RMT_IDLE_LEVEL_HIGH ;
151
+ rmt_tx .tx_config .idle_output_en = true;
152
+
153
+ rmt_config (& rmt_tx );
154
+ rmt_driver_install (rmt_tx .channel , 0 , 0 );
155
+
156
+ // start the channel
157
+ rmt_tx_start (_rmt_midea_ir_tx_channel , 1 );
158
+ }
159
+
160
+ /* Uninstall the RMT driver */
161
+ void rmt_midea_ir_tx_channel_stop (uint8_t channel )
162
+ {
163
+ rmt_driver_uninstall (channel );
164
164
}
0 commit comments