26 #include "freertos/FreeRTOS.h" 27 #include "freertos/task.h" 29 #include "soc/i2s_struct.h" 30 #include "soc/i2s_reg.h" 31 #include "driver/periph_ctrl.h" 32 #include "rom/lldesc.h" 50 void GPIOStream::begin()
53 m_DMABuffer =
nullptr;
58 void GPIOStream::begin(
bool div1_onGPIO0, gpio_num_t div2, gpio_num_t div4, gpio_num_t div8, gpio_num_t div16, gpio_num_t div32, gpio_num_t div64, gpio_num_t div128, gpio_num_t div256)
63 setupGPIO(GPIO_NUM_0, -1, GPIO_MODE_OUTPUT);
64 setupGPIO(div2, 0, GPIO_MODE_OUTPUT);
65 setupGPIO(div4, 1, GPIO_MODE_OUTPUT);
66 setupGPIO(div8, 2, GPIO_MODE_OUTPUT);
67 setupGPIO(div16, 3, GPIO_MODE_OUTPUT);
68 setupGPIO(div32, 4, GPIO_MODE_OUTPUT);
69 setupGPIO(div64, 5, GPIO_MODE_OUTPUT);
70 setupGPIO(div128, 6, GPIO_MODE_OUTPUT);
71 setupGPIO(div256, 7, GPIO_MODE_OUTPUT);
73 m_DMAData = (
volatile uint8_t *) heap_caps_malloc(256, MALLOC_CAP_DMA);
74 for (
int i = 0; i < 256; ++i)
77 m_DMABuffer = (
volatile lldesc_t *) heap_caps_malloc(
sizeof(lldesc_t), MALLOC_CAP_DMA);
79 m_DMABuffer->sosf = 0;
80 m_DMABuffer->owner = 1;
81 m_DMABuffer->qe.stqe_next = (lldesc_t *) m_DMABuffer;
82 m_DMABuffer->offset = 0;
83 m_DMABuffer->size = 256;
84 m_DMABuffer->length = 256;
85 m_DMABuffer->buf = (uint8_t*) m_DMAData;
89 void GPIOStream::end()
98 void GPIOStream::setupGPIO(gpio_num_t gpio,
int bit, gpio_mode_t mode)
100 if (gpio != GPIO_UNUSED) {
104 WRITE_PERI_REG(PIN_CTRL, 0xF);
105 PIN_FUNC_SELECT(GPIO_PIN_REG_0, FUNC_GPIO0_CLK_OUT1);
107 configureGPIO(gpio, mode);
108 gpio_matrix_out(gpio, I2S1O_DATA_OUT0_IDX + bit,
false,
false);
115 void GPIOStream::play(
int freq, lldesc_t
volatile * dmaBuffers)
120 periph_module_enable(PERIPH_I2S1_MODULE);
123 I2S1.conf.tx_reset = 1;
124 I2S1.conf.tx_reset = 0;
127 I2S1.lc_conf.out_rst = 1;
128 I2S1.lc_conf.out_rst = 0;
131 I2S1.conf.tx_fifo_reset = 1;
132 I2S1.conf.tx_fifo_reset = 0;
136 I2S1.conf2.lcd_en = 1;
137 I2S1.conf2.lcd_tx_wrx2_en = 1;
138 I2S1.conf2.lcd_tx_sdx2_en = 0;
140 I2S1.sample_rate_conf.val = 0;
141 I2S1.sample_rate_conf.tx_bits_mod = 8;
145 I2S1.fifo_conf.val = 0;
146 I2S1.fifo_conf.tx_fifo_mod_force_en = 1;
147 I2S1.fifo_conf.tx_fifo_mod = 1;
148 I2S1.fifo_conf.tx_fifo_mod = 1;
149 I2S1.fifo_conf.tx_data_num = 32;
150 I2S1.fifo_conf.dscr_en = 1;
153 I2S1.conf1.tx_stop_en = 0;
154 I2S1.conf1.tx_pcm_bypass = 1;
156 I2S1.conf_chan.val = 0;
157 I2S1.conf_chan.tx_chan_mod = 1;
159 I2S1.conf.tx_right_first = 1;
164 I2S1.lc_conf.ahbm_rst = 1;
165 I2S1.lc_conf.ahbm_fifo_rst = 1;
166 I2S1.lc_conf.ahbm_rst = 0;
167 I2S1.lc_conf.ahbm_fifo_rst = 0;
170 I2S1.lc_conf.val = I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN;
171 I2S1.out_link.addr = (uint32_t) (dmaBuffers ? &dmaBuffers[0] : m_DMABuffer);
172 I2S1.out_link.start = 1;
173 I2S1.conf.tx_start = 1;
181 void GPIOStream::stop()
184 rtc_clk_apll_enable(
false, 0, 0, 0, 0);
185 periph_module_disable(PERIPH_I2S1_MODULE);
187 m_DMAStarted =
false;
203 #if FABGLIB_USE_APLL_AB_COEF 204 void floatToFraction(
double value,
int maxDen,
int * num,
int * den)
206 int64_t a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 };
208 while (value != floor(value)) {
213 for (
int i = 0; i < 64; ++i) {
221 if (k[1] * a + k[0] >= maxDen) {
222 x = (maxDen - k[0]) / k[1];
223 if (x * 2 >= a || k[1] >= maxDen)
228 h[2] = x * h[1] + h[0];
231 k[2] = x * k[1] + k[0];
350 static void APLLCalcParams(
double freq, APLLParams * params, uint8_t * a, uint8_t * b,
double * out_freq,
double * error)
352 double FXTAL = FABGLIB_XTAL;
356 double apll_freq = freq * 2;
358 for (
int o_div = 0; o_div <= 31; ++o_div) {
360 int idivisor = (2 * o_div + 4);
362 for (
int sdm2 = 4; sdm2 <= 8; ++sdm2) {
365 int minSDM1 = (sdm2 == 4 ? 192 : 0);
366 int maxSDM1 = (sdm2 == 8 ? 128 : 255);
368 int startSDM1 = ((apll_freq * idivisor - FXTAL * 4.0 - FXTAL * sdm2) * 256.0 / FXTAL);
369 #if FABGLIB_USE_APLL_AB_COEF 370 for (
int isdm1 = tmax(minSDM1, startSDM1); isdm1 <= maxSDM1; ++isdm1) {
372 int isdm1 = startSDM1; {
376 sdm1 = tmax(minSDM1, sdm1);
377 sdm1 = tmin(maxSDM1, sdm1);
380 int sdm0 = ((apll_freq * idivisor - FXTAL * 4.0 - FXTAL * sdm2 - FXTAL * sdm1 / 256.0) * 65536.0 / FXTAL);
382 sdm0 = (sdm2 == 8 && sdm1 == 128 ? 0 : tmin(255, sdm0));
383 sdm0 = tmax(0, sdm0);
386 double dividend = FXTAL * (4.0 + sdm2 + sdm1 / 256.0 + sdm0 / 65536.0);
387 if (dividend >= 350000000 && dividend <= 500000000) {
389 double oapll_freq = dividend / idivisor;
395 uint8_t oa = 1, ob = 0;
396 #if FABGLIB_USE_APLL_AB_COEF 397 double abr = oapll_freq / freq - 2.0;
398 if (abr > 0 && abr < 1) {
400 floatToFraction(abr, 63, &num, &den);
401 ob = tclamp(num, 0, 63);
402 oa = tclamp(den, 0, 63);
407 double ofreq = oapll_freq / (2.0 + (double)ob / oa);
408 double err = freq - ofreq;
409 if (abs(err) < abs(*error)) {
410 *params = (APLLParams){(uint8_t)sdm0, (uint8_t)sdm1, (uint8_t)sdm2, (uint8_t)o_div};
426 void GPIOStream::setupClock(
int freq)
428 APLLParams p = {0, 0, 0, 0};
429 double error, out_freq;
430 uint8_t a = 1, b = 0;
431 APLLCalcParams(freq, &p, &a, &b, &out_freq, &error);
433 I2S1.clkm_conf.val = 0;
434 I2S1.clkm_conf.clkm_div_b = b;
435 I2S1.clkm_conf.clkm_div_a = a;
436 I2S1.clkm_conf.clkm_div_num = 2;
438 I2S1.sample_rate_conf.tx_bck_div_num = 1;
440 rtc_clk_apll_enable(
true, p.sdm0, p.sdm1, p.sdm2, p.o_div);
442 I2S1.clkm_conf.clka_en = 1;
This file contains fabgl::GPIOStream definition.
This file contains some utility classes and functions.