led_matrix/main/i80_controller_example_main.c

230 lines
8.3 KiB
C
Raw Normal View History

2024-01-28 19:03:19 +08:00
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
2024-01-29 14:42:04 +08:00
#include "esp_lcd_panel_io_i80_hub75.h"
2024-01-28 19:03:19 +08:00
#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
2024-01-29 14:42:04 +08:00
#define HUB75_G0 1
#define HUB75_R0 2
2024-01-28 19:03:19 +08:00
#define HUB75_B0 3
2024-01-29 14:42:04 +08:00
#define HUB75_G1 4
#define HUB75_R1 5
2024-01-28 19:03:19 +08:00
#define HUB75_B1 6
2024-01-29 14:42:04 +08:00
#define HUB75_G2 37
#define HUB75_R2 38
2024-01-28 19:03:19 +08:00
#define HUB75_B2 39
2024-01-29 14:42:04 +08:00
#define HUB75_G3 40
#define HUB75_R3 41
2024-01-28 19:03:19 +08:00
#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)
{
2024-01-29 14:42:04 +08:00
// 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); /* 锁存拉高 */
// vTaskDelay(pdMS_TO_TICKS(1));
// gpio_set_level(HUB75_LAT_PIN_NUM, 0); /* 拉低锁存,下降沿锁存 */
// gpio_set_level(HUB75_OE_PIN_NUM, 0); /* 使能显示 */
// ESP_LOGI(TAG, "line trans done");
2024-01-28 19:03:19 +08:00
return false;
}
void app_main(void)
{
/* 8080总线配置 */
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
2024-01-29 14:42:04 +08:00
esp_lcd_i80_hub75_bus_handle_t i80_bus = NULL;
esp_lcd_i80_hub75_bus_config_t bus_config = {
2024-01-28 19:03:19 +08:00
.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,
};
2024-01-29 14:42:04 +08:00
ESP_ERROR_CHECK(esp_lcd_new_i80_hub75_bus(&bus_config, &i80_bus));
2024-01-28 19:03:19 +08:00
/* 8080IO设备申请 */
esp_lcd_panel_io_handle_t io_handle = NULL;
2024-01-29 14:42:04 +08:00
esp_lcd_panel_io_i80_hub75_config_t io_config = {
2024-01-28 19:03:19 +08:00
.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,
// },
2024-01-29 14:42:04 +08:00
.flags = {
// .swap_color_bytes = !LV_COLOR_16_SWAP, // Swap can be done in LvGL (default) or DMA
.pclk_idle_low = 1,
},
.on_color_trans_done = NULL,
2024-01-28 19:03:19 +08:00
.user_ctx = NULL,
.lcd_cmd_bits = 0,
.lcd_param_bits = 0,
};
2024-01-29 14:42:04 +08:00
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80_hub75(i80_bus, &io_config, &io_handle));
/* 控制引脚GPIO初始化 */
gpio_config_t io_conf = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL << HUB75_LAT_PIN_NUM) |
(1ULL << HUB75_OE_PIN_NUM) |
(1ULL << HUB75_LINE_ADDR_A_PIN_NUM) |
(1ULL << HUB75_LINE_ADDR_B_PIN_NUM) |
(1ULL << HUB75_LINE_ADDR_C_PIN_NUM) |
(1ULL << HUB75_LINE_ADDR_D_PIN_NUM),
2024-01-28 19:03:19 +08:00
};
2024-01-29 14:42:04 +08:00
ESP_ERROR_CHECK(gpio_config(&io_conf));
// /* 定时进行行扫描 */
// 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));
// gpio_set_level(HUB75_OE_PIN_NUM, 1); /* 使能显示 */
2024-01-28 19:03:19 +08:00
while (1) {
2024-01-29 14:42:04 +08:00
/* 测试,发送一次数据 */
ESP_LOGI(TAG, "Test send data to LCD");
/* HUB75_COL_COUNT */
int i = 0;
uint16_t color_data[128] = {0};
// for (i = 0; i < 64; i++)
color_data[0] = 0x9; /* 红 */
color_data[1] = 0x12; /* 绿 */
color_data[2] = 0x24; /* 蓝 */
color_data[64 + 0] = 0x24; /* 红 */
color_data[64 + 1] = 0x12; /* 绿 */
color_data[64 + 2] = 0x9; /* 蓝 */
esp_lcd_panel_io_tx_color(io_handle, -1, color_data, sizeof(color_data));
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_LOGI(TAG, "line trans done");
gpio_set_level(HUB75_OE_PIN_NUM, 1); /* 失能显示 */
gpio_set_level(HUB75_LAT_PIN_NUM, 1); /* 锁存拉高 */
vTaskDelay(pdMS_TO_TICKS(1));
gpio_set_level(HUB75_LAT_PIN_NUM, 0); /* 拉低锁存,下降沿锁存 */
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);
line ++;
gpio_set_level(HUB75_OE_PIN_NUM, 0); /* 使能显示 */
vTaskDelay(pdMS_TO_TICKS(1000));
2024-01-28 19:03:19 +08:00
}
2024-01-29 14:42:04 +08:00
2024-01-28 19:03:19 +08:00
}