led_matrix/main/i80_controller_example_main.c
2024-01-28 19:03:19 +08:00

214 lines
7.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_lcd_panel_io.h"
#include "hub75.h"
#include "esp_lcd_panel_ops.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_rom_sys.h"
static const char *TAG = "led matrix";
#define HUB75_CLOCK_HZ (10 * 1000 * 1000)
#define HUB75_COL_COUNT (64)
#define HUB75_ROW_COUNT (32)
#define HUB75_COL_UNIT_COUNT (32) /* 实际扫描的时候送入数据的列数 */
#define HUB75_SCAN_LINE_CNT (16) /* 多少扫的 */
#define HUB75_LINE_ADDR_A_PIN_NUM 33
#define HUB75_LINE_ADDR_B_PIN_NUM 34
#define HUB75_LINE_ADDR_C_PIN_NUM 35
#define HUB75_LINE_ADDR_D_PIN_NUM 36
#define HUB75_LAT_PIN_NUM 8
#define HUB75_OE_PIN_NUM 21
#define HUB75_CLK_PIN_NUM 7
#define HUB75_R0 1
#define HUB75_G0 2
#define HUB75_B0 3
#define HUB75_R1 4
#define HUB75_G1 5
#define HUB75_B1 6
#define HUB75_R2 37
#define HUB75_G2 38
#define HUB75_B2 39
#define HUB75_R3 40
#define HUB75_G3 41
#define HUB75_B3 42
//#define LVGL_TICK_PERIOD_MS 2
#define LINE_SCAN_LOOP_PERIOD_MS 1000 /* 暂时测试用 */
#define LINE_SCAN_CNT 8 /* 用于全彩显示RGB323色彩最宽3bit取值0-7需要扫描8次进行灰度调节 */
#define PSRAM_DATA_ALIGNMENT 64
#define get_rgb_one_value(n, x) (n < (x) ? 1 : 0) /* 判断r、g、b其中一个本次是否应该点亮 */
/* 输入一个byte从高到低r 3bit, g 2bit, b 3bit */
/* 输出一个3bit值从高到低b, g, r */
#define get_rgb_value(n, x) (get_rgb_one_value(n, (x >> 5) & 0x07) | (get_rgb_one_value(n, (x >> 3) & 0x03) << 1) | (get_rgb_one_value(n, x & 0x07) << 2))
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
uint8_t ledbuf[HUB75_ROW_COUNT][HUB75_COL_COUNT];
static int line = 0; /* 本次扫描行32行16扫一次显示两行 */
void get_one_line(int *line_ret, uint16_t *line_data)
{
int i;
static int line_scan_cnt = 0; /* 本行已经扫描多少次8次 */
/* 准备一行数据 */
for (i = 0; i < HUB75_COL_UNIT_COUNT; i++)
{
/* 后面的注释为bit从低到高对应i80总线的数据线 */
line_data[i] = get_rgb_value(line_scan_cnt, ledbuf[line][i]) | /* r0, g0, b0 */
(get_rgb_value(line_scan_cnt, ledbuf[line + HUB75_SCAN_LINE_CNT][i]) << 3) | /* r1, g1, b1 */
(get_rgb_value(line_scan_cnt, ledbuf[line][i + HUB75_COL_UNIT_COUNT]) << 6) | /* r2, g2, b2 */
(get_rgb_value(line_scan_cnt, ledbuf[line + HUB75_SCAN_LINE_CNT][i + HUB75_COL_UNIT_COUNT]) << 9); /* r3, g3, b3 */
}
*line_ret = line;
/* 更新索引 */
line_scan_cnt++;
if (line_scan_cnt >= HUB75_SCAN_LINE_CNT)
line ++;
if (line >= HUB75_SCAN_LINE_CNT)
{
line = 0;
line_scan_cnt = 0;
}
}
static void line_scan_loop_cb(void *args)
{
int line;
uint16_t line_data[HUB75_COL_UNIT_COUNT];
esp_lcd_panel_io_handle_t io_handle = (esp_lcd_panel_io_handle_t)args;
get_one_line(&line, line_data);
esp_lcd_panel_io_tx_color(io_handle, -1, line_data, sizeof(line_data)); /* 发送行数据 */
}
static bool line_trans_done_cb(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
{
gpio_set_level(HUB75_OE_PIN_NUM, 1); /* 失能显示 */
gpio_set_level(HUB75_LINE_ADDR_A_PIN_NUM, line & 1); /* 行地址A是低位待求证 */
gpio_set_level(HUB75_LINE_ADDR_B_PIN_NUM, (line >> 1) & 1);
gpio_set_level(HUB75_LINE_ADDR_C_PIN_NUM, (line >> 2) & 1);
gpio_set_level(HUB75_LINE_ADDR_D_PIN_NUM, (line >> 3) & 1);
gpio_set_level(HUB75_LAT_PIN_NUM, 1); /* 锁存拉高 */
gpio_set_level(HUB75_LAT_PIN_NUM, 0); /* 拉低锁存,下降沿锁存 */
gpio_set_level(HUB75_LAT_PIN_NUM, 1);
gpio_set_level(HUB75_OE_PIN_NUM, 0); /* 使能显示 */
ESP_LOGI(TAG, "line trans done");
return false;
}
void app_main(void)
{
/* 8080总线配置 */
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = HUB75_CLK_PIN_NUM,
.dc_gpio_num = -1,
.wr_gpio_num = HUB75_CLK_PIN_NUM,
.data_gpio_nums = {
HUB75_R0,
HUB75_G0,
HUB75_B0,
HUB75_R1,
HUB75_G1,
HUB75_B1,
HUB75_R2,
HUB75_G2,
HUB75_B2,
HUB75_R3,
HUB75_G3,
HUB75_B3,
-1,
-1,
-1,
-1,
},
.bus_width = 16,
.max_transfer_bytes = HUB75_COL_COUNT * sizeof(uint16_t), /* 每次发一行 */
.psram_trans_align = PSRAM_DATA_ALIGNMENT,
.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
/* 8080IO设备申请 */
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = -1,
.pclk_hz = HUB75_CLOCK_HZ,
.trans_queue_depth = 10,
// .dc_levels = {
// .dc_idle_level = 0,
// .dc_cmd_level = 0,
// .dc_dummy_level = 0,
// .dc_data_level = 1,
// },
// .flags = {
// .swap_color_bytes = !LV_COLOR_16_SWAP, // Swap can be done in LvGL (default) or DMA
// },
.on_color_trans_done = line_trans_done_cb,
.user_ctx = NULL,
.lcd_cmd_bits = 0,
.lcd_param_bits = 0,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
/* hub75特定类型申请 */
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of hub75");
hub75_panel_config_t panel_config = {
.line_addr_num = 4,
.line_addr_gpio_num = {HUB75_LINE_ADDR_A_PIN_NUM, HUB75_LINE_ADDR_B_PIN_NUM, HUB75_LINE_ADDR_C_PIN_NUM, HUB75_LINE_ADDR_D_PIN_NUM},
.lat_gpio_num = HUB75_LAT_PIN_NUM,
.oe_gpio_num = HUB75_OE_PIN_NUM,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_hub75(io_handle, &panel_config, &panel_handle));
/* 定时进行行扫描 */
ESP_LOGI(TAG, "Create a timer to do line scan");
const esp_timer_create_args_t periodic_timer_args = {
.callback = line_scan_loop_cb,
.arg = io_handle,
.name = "line_scan_loop"
};
esp_timer_handle_t line_scan_loop_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &line_scan_loop_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(line_scan_loop_timer, LINE_SCAN_LOOP_PERIOD_MS * 1000));
// /* 测试,发送一次数据 */
// ESP_LOGI(TAG, "Test send data to LCD");
// uint16_t color_data[HUB75_COL_COUNT] = {1, 2, 4};
// gpio_set_level(HUB75_OE_PIN_NUM, 1);
// gpio_set_level(HUB75_LINE_ADDR_A_PIN_NUM, 0);
// gpio_set_level(HUB75_LINE_ADDR_B_PIN_NUM, 0);
// gpio_set_level(HUB75_LINE_ADDR_C_PIN_NUM, 0);
// gpio_set_level(HUB75_LINE_ADDR_D_PIN_NUM, 0);
// gpio_set_level(HUB75_LAT_PIN_NUM, 1);
// esp_lcd_panel_io_tx_color(io_handle, -1, color_data, sizeof(color_data));
while (1) {
vTaskDelay(pdMS_TO_TICKS(10));
}
}