Skip to content

Commit 964cc98

Browse files
committed
rmt driver initial version
1 parent c4c946a commit 964cc98

File tree

2 files changed

+403
-0
lines changed

2 files changed

+403
-0
lines changed

cores/esp32/esp32-hal-rmt.c

+340
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
#include "esp32-hal.h"
2+
#include "esp8266-compat.h"
3+
#include "soc/gpio_reg.h"
4+
#include "soc/gpio_reg.h"
5+
6+
#include "esp32-hal-rmt.h"
7+
#include "driver/periph_ctrl.h"
8+
9+
#include "soc/rmt_struct.h"
10+
#include "esp_intr_alloc.h"
11+
12+
13+
#define MAX_CHANNELS 8
14+
#define ABS(a) (a>0?a:-a)
15+
16+
17+
struct rmt_obj_s
18+
{
19+
bool allocated;
20+
intr_handle_t intr_handle;
21+
int pin;
22+
int channel;
23+
bool tx_not_rx;
24+
int buffers;
25+
};
26+
27+
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
28+
{ false, NULL, 0, 0, 0, 0},
29+
{ false, NULL, 0, 0, 0, 0},
30+
};
31+
32+
static intr_handle_t intr_handle;
33+
34+
static bool periph_enabled = false;
35+
36+
static void _initPin(int pin, int channel);
37+
38+
39+
bool rmtDeinit(rmt_obj_t *rmt)
40+
{
41+
if (!rmt) {
42+
return false;
43+
}
44+
45+
// sanity check
46+
if (rmt != &(g_rmt_objects[rmt->channel])) {
47+
return false;
48+
}
49+
50+
size_t from = rmt->channel;
51+
size_t to = rmt->buffers + rmt->channel;
52+
size_t i;
53+
54+
for (i = from; i < to; i++) {
55+
g_rmt_objects[i].allocated = false;
56+
}
57+
return true;
58+
g_rmt_objects[from].channel = 0;
59+
g_rmt_objects[from].buffers = 0;
60+
}
61+
62+
bool rmtSend(uint32_t* data, size_t size, rmt_obj_t* rmt)
63+
{
64+
if (!rmt) {
65+
return false;
66+
}
67+
int channel = rmt->channel;
68+
RMT.apb_conf.fifo_mask = 1;
69+
size_t i;
70+
for (i = 0; i < size; i++) {
71+
RMTMEM.chan[channel].data32[i].val = data[i];
72+
}
73+
74+
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
75+
76+
RMT.conf_ch[channel].conf1.tx_start = 1;
77+
78+
return true;
79+
}
80+
81+
rmt_obj_t* _rmtAllocate(int pin, int from, int size)
82+
{
83+
size_t i;
84+
// setup how many buffers shall we use
85+
g_rmt_objects[from].buffers = size;
86+
87+
for (i=0; i<size; i++) {
88+
// mark the block of channels as used
89+
g_rmt_objects[i+from].allocated = true;
90+
}
91+
return &(g_rmt_objects[from]);
92+
}
93+
94+
95+
float rmtSetTick(rmt_obj_t* rmt, float tick)
96+
{
97+
if (!rmt) {
98+
return false;
99+
}
100+
101+
int apb_div = 0xFF & (int)(tick/12.5);
102+
int ref_div = 0xFF & (int)(tick/1000);
103+
104+
float apb_tick = 12.5 * apb_div;
105+
float ref_tick = 1000.0 * ref_div;
106+
107+
size_t channel = rmt->channel;
108+
if (ABS(apb_tick - tick) < ABS(ref_tick - tick)) {
109+
RMT.conf_ch[channel].conf0.div_cnt = apb_div;
110+
RMT.conf_ch[channel].conf1.ref_always_on = 1;
111+
return apb_tick;
112+
} else {
113+
RMT.conf_ch[channel].conf0.div_cnt = ref_div;
114+
RMT.conf_ch[channel].conf1.ref_always_on = 0;
115+
return ref_tick;
116+
}
117+
}
118+
119+
rmt_obj_t* rmtInit(int pin, bool tx_not_rx, int entries, int period)
120+
{
121+
int buffers = 1 + entries/64;
122+
rmt_obj_t* rmt;
123+
size_t i;
124+
size_t j;
125+
for (i=0; i<MAX_CHANNELS; i++) {
126+
for (j=0; j<buffers && i+j < MAX_CHANNELS; j++) {
127+
// if the space is ocupied break and continue on other channel
128+
if (g_rmt_objects[i+j].allocated) {
129+
i += j; // continue searching from latter channel
130+
break;
131+
}
132+
}
133+
if (j == buffers) {
134+
// found a space in channel descriptors
135+
break;
136+
}
137+
}
138+
if (i == MAX_CHANNELS) {
139+
return NULL;
140+
}
141+
rmt = _rmtAllocate(pin, i, buffers);
142+
143+
size_t channel = i;
144+
rmt->pin = pin;
145+
rmt->tx_not_rx = tx_not_rx;
146+
rmt->buffers =buffers;
147+
rmt->channel = channel;
148+
_initPin(pin, channel);
149+
150+
// rmt tick from 1/80M -> 12.5ns (1x)
151+
// 3.2 us (FFx 00 is more)
152+
// rmt tick for 1 MHz -> 1us (1x)
153+
// 256us (00x)
154+
155+
// default config (period of 1us)
156+
RMT.conf_ch[channel].conf0.div_cnt = 1;
157+
RMT.conf_ch[channel].conf0.mem_size = buffers;
158+
RMT.conf_ch[channel].conf0.carrier_en = 0;
159+
RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
160+
RMT.conf_ch[channel].conf0.mem_pd = 0;
161+
162+
RMT.conf_ch[channel].conf1.rx_en = 1;
163+
RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
164+
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
165+
RMT.conf_ch[channel].conf1.rx_filter_en = 0;
166+
RMT.conf_ch[channel].conf1.rx_filter_thres = 0;
167+
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
168+
RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle
169+
RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock
170+
171+
if (tx_not_rx) {
172+
RMT.conf_ch[channel].conf1.rx_en = 0;
173+
RMT.conf_ch[channel].conf1.mem_owner = 0;
174+
} else {
175+
RMT.conf_ch[channel].conf1.rx_en = 1;
176+
RMT.conf_ch[channel].conf1.mem_owner = 1;
177+
}
178+
// RMT.conf_ch[channel].conf0.val = ((uint32_t*)config)[0];
179+
// RMT.conf_ch[channel].conf1.val = ((uint32_t*)config)[1];
180+
181+
return rmt;
182+
}
183+
184+
185+
186+
static void _initPin(int pin, int channel)
187+
// rmt_driver_config_t* config)
188+
{
189+
if (!periph_enabled) {
190+
periph_enabled = true;
191+
periph_module_enable( PERIPH_RMT_MODULE );
192+
}
193+
pinMode(pin, OUTPUT);
194+
pinMatrixOutAttach(pin, RMT_SIG_OUT0_IDX + channel, 0, 0);
195+
196+
// memcpy( (uint8_t*)&RMT.conf_ch[channel].conf0.val, (uint8_t*)config, 8);
197+
// memcpy( (uint8_t*)&RMT.conf_ch[channel].conf1.val, ((uint8_t*)config) + 4, sizeof(uint32_t));
198+
}
199+
200+
void initMemory(int offset, uint32_t* data, size_t size)
201+
{
202+
RMT.apb_conf.fifo_mask = 1;
203+
size_t i;
204+
// uint16_t * ptr = (uint16_t*)&(RMTMEM.chan[offset].data16[0]);
205+
// uint16_t * ptr = (uint16_t*)(0x3ff56800);
206+
// // uint16_t ptr[32];
207+
// memset(ptr, 0, 32);
208+
// for (i = 0; i < size; i++) {
209+
// printf(">> %x\n", ptr[i]);
210+
// }
211+
212+
for (i = 0; i < size; i++) {
213+
RMTMEM.chan[offset].data32[i].val = data[i];
214+
// printf(">> %x\n", data[i]);
215+
// RMTMEM.chan[offset].data16[i]
216+
// RMTMEM.chan[offset].data32[i].val = data[i];
217+
// printf(" %x\n", RMTMEM.chan[offset].data16[i].val);
218+
// RMTMEM.chan[offset].data16[i] = data[i];
219+
// *ptr++ = i;
220+
// ptr[i] = i;
221+
// RMTMEM.chan[i].data1 = 0x11+ i;
222+
// RMTMEM.chan[i].data2 = 0x22+ i;
223+
224+
// printf(" %x\n", RMTMEM.chan[offset].data16[i].val);
225+
// printf(" %x\n", RMTMEM.chan[offset].data32[i/2].val);
226+
// printf("--------\n");
227+
228+
// printf(" %x\n", RMTMEM.chan[offset].xx.data16[i]);
229+
// RMTMEM.chan[offset].xx.data16[i] = data[i];
230+
// printf(" %x\n", RMTMEM.chan[offset].xx.data16[i]);
231+
// printf(" %x\n", RMTMEM.chan[offset].xx.data32[i/2]);
232+
// printf("--------\n");
233+
234+
}
235+
236+
}
237+
238+
// 00000000
239+
// 00010000
240+
241+
242+
243+
void startTx(int channel)
244+
{
245+
// reset rd value
246+
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
247+
248+
RMT.conf_ch[channel].conf1.tx_start = 1;
249+
}
250+
251+
// struct rmt_struct_t {
252+
// uart_dev_t * dev;
253+
// #if !CONFIG_DISABLE_HAL_LOCKS
254+
// xSemaphoreHandle lock;
255+
// #endif
256+
// uint8_t num;
257+
// xQueueHandle queue;
258+
// intr_handle_t intr_handle;
259+
// };
260+
261+
static int state = 0;
262+
263+
static void IRAM_ATTR _rmt_isr(void* arg)
264+
{
265+
RMT.int_clr.val = 1;
266+
// printf("test");
267+
state ^= 1;
268+
digitalWrite(4, state);
269+
}
270+
271+
int config();
272+
273+
int setpin(int pin)
274+
{
275+
int channel = 0;
276+
pinMode(pin, OUTPUT);
277+
// *((uint32_t*)0x3FF49070) = 0x002A0000;
278+
pinMatrixOutAttach(pin, RMT_SIG_OUT0_IDX + channel, 0, 0);
279+
periph_module_enable( PERIPH_RMT_MODULE );
280+
281+
// 0x3ff49000 : 0x3FF49000 <Hex>
282+
// Address 0 - 3 4 - 7 8 - B C - F
283+
// 3FF49000 FF030000 00080000 00080000 00080000
284+
// 3FF49010 00080000 00080000 00080000 00080000
285+
// 3FF49020 00080000 00080000 00080000 000A0000
286+
// 3FF49030 000A0000 800A0000 000A0000 000B0000
287+
// 3FF49040 800A0000 000B0000 800A0000 000A0000
288+
// 3FF49050 000A0000 002B0000 002B0000 002B0000
289+
// 3FF49060 001B0000 002B0000 002B0000 000B0000
290+
// 3FF49070 002A0000 000A0000 000A0000 000A0000
291+
// 3FF49080 000A0000 000B0000 000A0000 000A0000
292+
// 3FF49090 00080000 00080000 00080000 00080000
293+
// 3FF490A0 00080000 00080000 00080000 00080000
294+
295+
*((unsigned int*)(0x3FF560F0)) = 1;
296+
// SET(RMT_DATA_REG, 0x8010020);
297+
*((uint32_t*)0x3ff56800) = 0x8FFF0FFF;
298+
*((uint32_t*)0x3ff56804) = 0x9FFF0FFF;
299+
*((uint32_t*)0x3ff56808) = 0;
300+
*((uint32_t*)0x3ff5680C) = 0;
301+
*((uint32_t*)0x3ff56810) = 0;
302+
*((uint32_t*)0x3FF560D0) = 0;
303+
// uint32_t test = 0x8010;
304+
// uint32_t zero = 0;
305+
// memcpy((uint8_t*)0x3ff56800, &test, 4);
306+
// memcpy((uint8_t*)0x3ff56804, &zero, 4);
307+
308+
RMT.conf_ch[0].conf0.val = 0x01000001;
309+
RMT.conf_ch[0].conf1.val = 0x20000;
310+
311+
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle);
312+
RMT.int_ena.val = 1;
313+
314+
// RMT[0].conf0 = 0x01000001;
315+
// // SET(RMT_CHnCONF0_REG(0), 0x31000001);
316+
// // SET(RMT_CHnCONF1_REG(0), 0x20000);
317+
// RMT[1].conf1 = 0x20000;
318+
319+
320+
// 0x311000ff
321+
//-- 0x01000ff
322+
323+
// 0xa0f00
324+
return 1;
325+
}
326+
327+
int run()
328+
{
329+
// SET(RMT_CHnCONF0_REG(0), 0x1000001);
330+
331+
// *((unsigned int*)(0x3FF560F0)) = 1;
332+
// // SET(RMT_DATA_REG, 0x8010020);
333+
// *((uint32_t*)0x3ff56800) = 0x8010;
334+
// *((uint32_t*)0x3ff56804) = 0;
335+
336+
// SET(RMT_CHnCONF1_REG(0), 0x20009);
337+
338+
return 0;
339+
340+
}

0 commit comments

Comments
 (0)