2025-02-18 15:40:42 +08:00

175 lines
4.5 KiB
C

#include "system/includes.h"
#include "system/debug.h"
#include "generic/gpio.h"
#include "asm/clock.h"
#include "asm/ledc.h"
static JL_LEDC_TypeDef *JL_LEDCx[2] = {
JL_LEDC0,
JL_LEDC1
};
static void (*ledc0_isr_cbfun)(void) = NULL;
static void (*ledc1_isr_cbfun)(void) = NULL;
static OS_SEM ledc0_sem;
static OS_SEM ledc1_sem;
___interrupt
void ledc_isr(void)
{
if (JL_LEDC0->CON & BIT(7)) {
JL_LEDC0->CON |= BIT(6);
os_sem_post(&ledc0_sem);
if (ledc0_isr_cbfun) {
ledc0_isr_cbfun();
}
}
if (JL_LEDC1->CON & BIT(7)) {
JL_LEDC1->CON |= BIT(6);
os_sem_post(&ledc1_sem);
if (ledc1_isr_cbfun) {
ledc1_isr_cbfun();
}
}
}
static u8 t_div[9] = {1, 2, 3, 6, 12, 24, 48, 96, 192};
void ledc_init(const struct ledc_platform_data *arg)
{
gpio_set_die(arg->port, 1);
gpio_set_direction(arg->port, 0);
gpio_set_pull_up(arg->port, 0);
gpio_set_pull_down(arg->port, 0);
gpio_set_fun_output_port(arg->port, FO_LEDC0_DO + arg->index, 0, 1);
//std_48M
JL_LEDCK->CLK &= ~(0b11 << 0);
JL_LEDCK->CLK |= (0b11 << 0);
//set div
JL_LEDCK->CLK &= ~(0xff << 8);
JL_LEDCK->CLK |= ((t_div[arg->t_unit] - 1) << 8);
JL_LEDCx[arg->index]->CON = BIT(6);
os_sem_create(&ledc0_sem, 1);
os_sem_create(&ledc1_sem, 1);
request_irq(16, 1, ledc_isr, 0);
if (arg->cbfun) {
if (arg->index == 0) {
ledc0_isr_cbfun = arg->cbfun;
} else {
ledc1_isr_cbfun = arg->cbfun;
}
}
if (arg->idle_level) {
JL_LEDCx[arg->index]->CON |= BIT(4);
}
if (arg->out_inv) {
JL_LEDCx[arg->index]->CON |= BIT(3);
}
JL_LEDCx[arg->index]->CON |= (arg->bit_inv << 1);
JL_LEDCx[arg->index]->TIX = 0;
JL_LEDCx[arg->index]->TIX |= ((arg->t1h_cnt - 1) << 24);
JL_LEDCx[arg->index]->TIX |= ((arg->t1l_cnt - 1) << 16);
JL_LEDCx[arg->index]->TIX |= ((arg->t0h_cnt - 1) << 8);
JL_LEDCx[arg->index]->TIX |= ((arg->t0l_cnt - 1) << 0);
JL_LEDCx[arg->index]->RSTX = 0;
JL_LEDCx[arg->index]->RSTX |= (arg->t_rest_cnt << 8);
printf("JL_LEDCK->CLK = 0x%x\n", JL_LEDCK->CLK);
printf("JL_LEDCx[%d]->CON = 0x%x\n", arg->index, JL_LEDCx[arg->index]->CON);
printf("JL_LEDCx[%d]->TIX = 0x%x\n", arg->index, JL_LEDCx[arg->index]->TIX);
printf("JL_LEDCx[%d]->RSTX = 0x%x\n", arg->index, JL_LEDCx[arg->index]->RSTX);
}
void ledc_rgb_to_buf(u8 r, u8 g, u8 b, u8 *buf, int idx)
{
buf = buf + idx * 3;
buf[2] = b;
buf[1] = r;
buf[0] = g;
}
void ledc_send_rgbbuf(u8 index, u8 *rgbbuf, u32 led_num, u16 again_cnt)
{
if (!led_num) {
return;
}
JL_LEDCx[index]->ADR = (u32)rgbbuf;
JL_LEDCx[index]->FD = led_num * 3 * 8;
JL_LEDCx[index]->LP = again_cnt;
JL_LEDCx[index]->CON |= BIT(0);//启动
JL_LEDCx[index]->CON &= ~BIT(5);//关闭中断
while (!(JL_LEDCx[index]->CON & BIT(7)));
JL_LEDCx[index]->CON |= BIT(6);
}
void ledc_send_rgbbuf_isr(u8 index, u8 *rgbbuf, u32 led_num, u16 again_cnt)
{
if (!led_num) {
return;
}
if (index == 0) {
os_sem_pend(&ledc0_sem, 0);
} else {
os_sem_pend(&ledc1_sem, 0);
}
JL_LEDCx[index]->ADR = (u32)rgbbuf;
JL_LEDCx[index]->FD = led_num * 3 * 8;
JL_LEDCx[index]->LP = again_cnt;
JL_LEDCx[index]->CON |= BIT(0);//启动
JL_LEDCx[index]->CON |= BIT(5);//使能中断
}
// *INDENT-OFF*
/******************************* 参考示例 ***********************************/
LEDC_PLATFORM_DATA_BEGIN(ledc0_data)
.index = 0,
.port = IO_PORTA_04,
.idle_level = 0,
.out_inv = 0,
.bit_inv = 1,
.t_unit = t_42ns,
.t1h_cnt = 24,
.t1l_cnt = 7,
.t0h_cnt = 7,
.t0l_cnt = 24,
.t_rest_cnt = 20000,
.cbfun = NULL,
LEDC_PLATFORM_DATA_END()
#define LED_NUM_MAX 5
static u8 ledc_test_buf[3 * LED_NUM_MAX] __attribute__((aligned(4)));
void ledc_test(void)
{
printf("************* ledc test **************\n");
ledc_init(&ledc0_data);
u8 r_val = 0;
u8 g_val = 85;
u8 b_val = 175;
u16 sec_num = 5;//循环发送的次数,用于一条大灯带又分为几条效果一样的小灯带
extern void wdt_clear();
while (1) {
wdt_clear();
os_time_dly(1);
r_val += 1;
g_val += 1;
b_val += 1;
ledc_rgb_to_buf(r_val, g_val, b_val, ledc_test_buf, 0);
#if 0
ledc_send_rgbbuf(0, ledc_test_buf, 1, sec_num - 1);
#else
ledc_send_rgbbuf_isr(0, ledc_test_buf, 1, sec_num - 1);
#endif
}
}