feat(school_stm32): 添加基础的 STM32F103RCT6 项目结构
- 创建了项目的基本目录结构和文件 - 添加了 CMakeLists.txt 和 Makefile 构建配置 - 创建了 main.c 文件,实现了简单的 LED 闪烁和按键检测功能 - 集成了 SEGGER RTT 库 - 添加了 .gitignore 文件,排除了不必要的生成文件
This commit is contained in:
88
libs/ge_interface/ge_input.c
Normal file
88
libs/ge_interface/ge_input.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include <main.h>
|
||||
#include "ge_interface.h"
|
||||
#include "include/ge_kfifo.h"
|
||||
|
||||
#define SCAN_BTN(lnum, hnum) do { \
|
||||
/*GE_SET_OFF(KEY_L ## hnum);*/ \
|
||||
if (GE_IS_BIN_PRESSD(H ## hnum)) \
|
||||
event.num = GE_ITYPE_KEY_L ## lnum ## H ## hnum, \
|
||||
ctx->func_send(ctx, event); \
|
||||
} while(0)
|
||||
|
||||
void input_btn_func(ge_input_t* ctx) {
|
||||
ge_input_event_t event;
|
||||
|
||||
if (GE_IS_BIN_PRESSD(1)) event.num = GE_ITYPE_KEY_1, ctx->func_send(ctx, event);
|
||||
if (GE_IS_BIN_PRESSD(2)) event.num = GE_ITYPE_KEY_2, ctx->func_send(ctx, event);
|
||||
if (GE_IS_BIN_PRESSD(3)) event.num = GE_ITYPE_KEY_3, ctx->func_send(ctx, event);
|
||||
if (GE_IS_BIN_PRESSD(4)) event.num = GE_ITYPE_KEY_4, ctx->func_send(ctx, event);
|
||||
|
||||
GE_SET_OFF(KEY_L1);
|
||||
SCAN_BTN(1, 1);
|
||||
SCAN_BTN(1, 2);
|
||||
SCAN_BTN(1, 3);
|
||||
SCAN_BTN(1, 4);
|
||||
HAL_Delay(10);
|
||||
GE_SET_ON(KEY_L1);
|
||||
|
||||
GE_SET_OFF(KEY_L2);
|
||||
SCAN_BTN(2, 1);
|
||||
SCAN_BTN(2, 2);
|
||||
SCAN_BTN(2, 3);
|
||||
SCAN_BTN(2, 4);
|
||||
HAL_Delay(10);
|
||||
GE_SET_ON(KEY_L2);
|
||||
|
||||
GE_SET_OFF(KEY_L3);
|
||||
SCAN_BTN(3, 1);
|
||||
SCAN_BTN(3, 2);
|
||||
SCAN_BTN(3, 3);
|
||||
SCAN_BTN(3, 4);
|
||||
HAL_Delay(10);
|
||||
GE_SET_ON(KEY_L3);
|
||||
|
||||
GE_SET_OFF(KEY_L4);
|
||||
SCAN_BTN(4, 1);
|
||||
SCAN_BTN(4, 2);
|
||||
SCAN_BTN(4, 3);
|
||||
SCAN_BTN(4, 4);
|
||||
HAL_Delay(10);
|
||||
GE_SET_ON(KEY_L4);
|
||||
}
|
||||
|
||||
DECLARE_GE_KFIFO(ge_input_fifo, ge_input_event_t, 16, ge_input_fifo_t);
|
||||
|
||||
int ge_input_send (ge_input_t* ctx, ge_input_event_t event) {
|
||||
struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context;
|
||||
if (ge_kfifo_is_full(fifo)) {
|
||||
return -1;
|
||||
}
|
||||
ge_kfifo_put(fifo, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ge_input_peek (ge_input_t* ctx, ge_input_event_t* event) {
|
||||
struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context;
|
||||
if (ge_kfifo_is_empty(fifo)) {
|
||||
return -1;
|
||||
}
|
||||
ge_kfifo_peek(fifo, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ge_input_recv (ge_input_t* ctx, ge_input_event_t* event) {
|
||||
struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context;
|
||||
if (ge_kfifo_is_empty(fifo)) {
|
||||
return -1;
|
||||
}
|
||||
ge_kfifo_get(fifo, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ge_input_t ge_input = {
|
||||
.context = &ge_input_fifo,
|
||||
|
||||
.func_send = ge_input_send,
|
||||
.func_peek = ge_input_peek,
|
||||
.func_recv = ge_input_recv,
|
||||
};
|
55
libs/ge_interface/ge_interface.h
Normal file
55
libs/ge_interface/ge_interface.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef __GE_INTERFACE_H__
|
||||
#define __GE_INTERFACE_H__
|
||||
|
||||
#include "include/ge_input.h"
|
||||
#include "include/ge_render.h"
|
||||
#include "include/ge_resource.h"
|
||||
#include "include/ge_timer.h"
|
||||
#include <pynic_log/pynic_log.h>
|
||||
|
||||
extern ge_input_t ge_input;
|
||||
extern ge_render_t ge_render;
|
||||
extern ge_resource_t ge_resource;
|
||||
extern ge_timer_t ge_timer;
|
||||
|
||||
enum {
|
||||
GE_ITYPE_NONE,
|
||||
GE_ITYPE_KEY_1,
|
||||
GE_ITYPE_KEY_2,
|
||||
GE_ITYPE_KEY_3,
|
||||
GE_ITYPE_KEY_4,
|
||||
GE_ITYPE_KEY_L1H1,
|
||||
GE_ITYPE_KEY_L1H2,
|
||||
GE_ITYPE_KEY_L1H3,
|
||||
GE_ITYPE_KEY_L1H4,
|
||||
GE_ITYPE_KEY_L2H1,
|
||||
GE_ITYPE_KEY_L2H2,
|
||||
GE_ITYPE_KEY_L2H3,
|
||||
GE_ITYPE_KEY_L2H4,
|
||||
GE_ITYPE_KEY_L3H1,
|
||||
GE_ITYPE_KEY_L3H2,
|
||||
GE_ITYPE_KEY_L3H3,
|
||||
GE_ITYPE_KEY_L3H4,
|
||||
GE_ITYPE_KEY_L4H1,
|
||||
GE_ITYPE_KEY_L4H2,
|
||||
GE_ITYPE_KEY_L4H3,
|
||||
GE_ITYPE_KEY_L4H4,
|
||||
};
|
||||
|
||||
#define GE_FAST_SET_ON(name) (name##_GPIO_Port->BSRR = name##_Pin)
|
||||
#define GE_FAST_SET_OFF(name) (name##_GPIO_Port->BRR = name##_Pin)
|
||||
// #define GE_FAST_SET_OFF(name) (name##_GPIO_Port->BSRR = (uint32_t)name##_Pin << 16u;)
|
||||
|
||||
#define GE_SET_STATE(name, state) HAL_GPIO_WritePin(name##_GPIO_Port, name##_Pin, state)
|
||||
#define GE_SET_ON(name) GE_SET_STATE(name, GPIO_PIN_SET)
|
||||
#define GE_SET_OFF(name) GE_SET_STATE(name, GPIO_PIN_RESET)
|
||||
|
||||
#define GE_LED_SET(num, state) HAL_GPIO_WritePin(LED_##num##_GPIO_Port, LED_##num##_Pin, state);
|
||||
#define GE_LED_TOGGLE(num) HAL_GPIO_TogglePin(LED_##num##_GPIO_Port, LED_##num##_Pin);
|
||||
#define GE_LED_ON(num) GE_LED_SET(num, GPIO_PIN_SET)
|
||||
#define GE_LED_OFF(num) GE_LED_SET(num, GPIO_PIN_RESET)
|
||||
#define GE_IS_BIN_PRESSD(num) (HAL_GPIO_ReadPin(KEY_##num##_GPIO_Port, KEY_##num##_Pin) == GPIO_PIN_RESET)
|
||||
|
||||
void input_btn_func(ge_input_t* ctx);
|
||||
|
||||
#endif // __GE_INTERFACE_H__
|
333
libs/ge_interface/ge_render.c
Normal file
333
libs/ge_interface/ge_render.c
Normal file
@ -0,0 +1,333 @@
|
||||
#include <main.h>
|
||||
#include "ge_interface.h"
|
||||
|
||||
/**
|
||||
* lcd_driver
|
||||
*/
|
||||
|
||||
#define lcd_write_bit_reg(bit) \
|
||||
do { \
|
||||
(bit) ? GE_FAST_SET_ON(LCD_SDA) : GE_FAST_SET_OFF(LCD_SDA); \
|
||||
GE_FAST_SET_OFF(LCD_SCL); GE_FAST_SET_ON(LCD_SCL); \
|
||||
} while (0)
|
||||
|
||||
#define lcd_write_byte(data) \
|
||||
do { \
|
||||
uint8_t __d = (data); \
|
||||
lcd_write_bit_reg(__d & 0x80); \
|
||||
lcd_write_bit_reg(__d & 0x40); \
|
||||
lcd_write_bit_reg(__d & 0x20); \
|
||||
lcd_write_bit_reg(__d & 0x10); \
|
||||
lcd_write_bit_reg(__d & 0x08); \
|
||||
lcd_write_bit_reg(__d & 0x04); \
|
||||
lcd_write_bit_reg(__d & 0x02); \
|
||||
lcd_write_bit_reg(__d & 0x01); \
|
||||
} while (0)
|
||||
|
||||
#define lcd_write_32bit(data) \
|
||||
do { \
|
||||
uint32_t __d32 = (data); \
|
||||
lcd_write_byte(__d32 >> 24); \
|
||||
lcd_write_byte(__d32 >> 16); \
|
||||
lcd_write_byte(__d32 >> 8); \
|
||||
lcd_write_byte(__d32); \
|
||||
} while (0)
|
||||
|
||||
static inline void lcd_write_raw_data(const uint8_t* data, uint32_t len) {
|
||||
if (!data || len == 0) return;
|
||||
|
||||
// 32位对齐部分(高效处理)
|
||||
uint32_t word_count = len >> 2; // len / 4
|
||||
uint32_t* word_ptr = (uint32_t*)data;
|
||||
|
||||
while (word_count--) {
|
||||
lcd_write_32bit(*word_ptr++); // 使用32位写入宏
|
||||
}
|
||||
|
||||
// 处理剩余字节(非4字节对齐部分)
|
||||
uint8_t remain = len % 4;
|
||||
if (remain) {
|
||||
uint8_t* byte_ptr = (uint8_t*)word_ptr;
|
||||
for (uint8_t i = 0; i < remain; i++) {
|
||||
lcd_write_byte(*byte_ptr++); // 使用8位写入宏
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_write_cmd(uint8_t cmd, const uint8_t* data, uint32_t len) {
|
||||
// write index
|
||||
GE_FAST_SET_OFF(LCD_CS);
|
||||
GE_FAST_SET_OFF(LCD_DC);
|
||||
lcd_write_byte(cmd);
|
||||
GE_FAST_SET_ON(LCD_CS);
|
||||
|
||||
if (len == 0 || data == NULL) return;
|
||||
// write data
|
||||
GE_FAST_SET_OFF(LCD_CS);
|
||||
GE_FAST_SET_ON(LCD_DC);
|
||||
lcd_write_raw_data(data, len);
|
||||
GE_FAST_SET_ON(LCD_CS);
|
||||
}
|
||||
|
||||
static inline void lcd_reset(void) {
|
||||
// LCD_RES_Pin
|
||||
// 重启屏幕 RES(RE Set)
|
||||
GE_SET_OFF(LCD_RES);
|
||||
HAL_Delay(100);
|
||||
GE_SET_ON(LCD_RES);
|
||||
HAL_Delay(50);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const uint8_t cmd;
|
||||
const uint32_t len;
|
||||
const uint8_t* data;
|
||||
} lcd_init_cmds[] = {
|
||||
{0x11, 0, NULL},
|
||||
|
||||
//ST7735R Frame Rate
|
||||
{0xB1, 3, (uint8_t[]){0x01, 0x2C, 0x2D}},
|
||||
{0xB2, 3, (uint8_t[]){0x01, 0x2C, 0x2D}},
|
||||
{0xB3, 6, (uint8_t[]){0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D}},
|
||||
|
||||
// Column inversion
|
||||
{0xB4, 1, (uint8_t[]){0x07}},
|
||||
|
||||
// ST7735R Power Sequence
|
||||
{0xC0, 3, (uint8_t[]){0xA2, 0x02, 0x84}},
|
||||
{0xC1, 1, (uint8_t[]){0xC5}},
|
||||
{0xC2, 2, (uint8_t[]){0x0A, 0x00}},
|
||||
{0xC3, 2, (uint8_t[]){0x8A, 0x2A}},
|
||||
{0xC4, 2, (uint8_t[]){0x8A, 0xEE}},
|
||||
|
||||
// VCOM
|
||||
{0xC5, 1, (uint8_t[]){0x0E}},
|
||||
|
||||
//MX, MY, RGB mode
|
||||
{0x36, 1, (uint8_t[]){0xC8}},
|
||||
|
||||
// Gamma Sequence (正极性)
|
||||
{0xE0, 16, (uint8_t[]){
|
||||
0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22,
|
||||
0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10
|
||||
}},
|
||||
|
||||
// Gamma Sequence (负极性)
|
||||
{0xE1, 16, (uint8_t[]){
|
||||
0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e,
|
||||
0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10
|
||||
}},
|
||||
|
||||
// 设置X方向地址范围
|
||||
{0x2A, 4, (uint8_t[]){0x00, 0x00, 0x00, 0x7f}},
|
||||
|
||||
// 设置Y方向地址范围
|
||||
{0x2B, 4, (uint8_t[]){0x00, 0x00, 0x00, 0x9f}},
|
||||
|
||||
// 测试命令
|
||||
{0xF0, 1, (uint8_t[]){0x01}}, // Enable test command
|
||||
{0xF6, 1, (uint8_t[]){0x00}}, // Disable ram power save mode
|
||||
|
||||
// 颜色模式
|
||||
{0x3A, 1, (uint8_t[]){0x05}}, // 65k mode (16-bit RGB565)
|
||||
|
||||
// 显示开启
|
||||
{0x29, 0, NULL} // Display on
|
||||
};
|
||||
|
||||
static inline init_lcd() {
|
||||
lcd_reset(); //Reset before LCD Init.
|
||||
|
||||
//LCD Init For 1.44Inch LCD Panel with ST7735R.
|
||||
lcd_write_cmd(0x11, NULL, 0); //Sleep exit
|
||||
HAL_Delay(120);
|
||||
|
||||
// 批量处理初始化序列
|
||||
for (size_t i = 0; i < sizeof(lcd_init_cmds)/sizeof(lcd_init_cmds[0]); i++) {
|
||||
lcd_write_cmd(lcd_init_cmds[i].cmd, lcd_init_cmds[i].data, lcd_init_cmds[i].len);
|
||||
}
|
||||
|
||||
// 开启背光 (Back Light)
|
||||
GE_SET_ON(LCD_BL);
|
||||
}
|
||||
|
||||
static inline void lcd_set_region(int pos_x, int pos_y, int size_x, int size_y) {
|
||||
#define LCD_WRITE_INDEX(data) do { \
|
||||
GE_FAST_SET_OFF(LCD_CS); \
|
||||
GE_FAST_SET_OFF(LCD_DC); \
|
||||
lcd_write_byte(data); \
|
||||
GE_FAST_SET_ON(LCD_CS); \
|
||||
} while(0)
|
||||
|
||||
#define LCD_WRITE_DATA(data) do { \
|
||||
GE_FAST_SET_OFF(LCD_CS); \
|
||||
GE_FAST_SET_ON(LCD_DC); \
|
||||
lcd_write_byte(data); \
|
||||
GE_FAST_SET_ON(LCD_CS); \
|
||||
} while(0)
|
||||
const uint8_t x_start = pos_x;
|
||||
const uint8_t x_end = pos_x + size_x - 1;
|
||||
const uint8_t y_start = pos_y;
|
||||
const uint8_t y_end = pos_y + size_y - 1;
|
||||
|
||||
LCD_WRITE_INDEX(0x2a);
|
||||
LCD_WRITE_DATA(0x00);
|
||||
LCD_WRITE_DATA(x_start+2);
|
||||
LCD_WRITE_DATA(0x00);
|
||||
LCD_WRITE_DATA(x_end+2);
|
||||
|
||||
LCD_WRITE_INDEX(0x2b);
|
||||
LCD_WRITE_DATA(0x00);
|
||||
LCD_WRITE_DATA(y_start+3);
|
||||
LCD_WRITE_DATA(0x00);
|
||||
LCD_WRITE_DATA(y_end+3);
|
||||
|
||||
LCD_WRITE_INDEX(0x2c);
|
||||
}
|
||||
|
||||
static int lcd_draw_point(ge_render_t* ctx, const ge_render_pos2_t* pos, uint16_t color) {
|
||||
(void)ctx;
|
||||
Assert(pos != NULL);
|
||||
lcd_set_region(pos->x, pos->y, 1, 1);
|
||||
|
||||
GE_FAST_SET_OFF(LCD_CS);
|
||||
GE_FAST_SET_ON(LCD_DC);
|
||||
|
||||
lcd_write_byte(color);
|
||||
lcd_write_byte(color >> 8);
|
||||
|
||||
GE_FAST_SET_OFF(LCD_DC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_draw_rect(ge_render_t* ctx, const ge_render_rect_t* rect, uint16_t color) {
|
||||
(void)ctx;
|
||||
const int pos_x = rect ? rect->pos.x : 0;
|
||||
const int pos_y = rect ? rect->pos.y : 0;
|
||||
const int size_x = rect ? rect->size.x : ctx->screen_size.x;
|
||||
const int size_y = rect ? rect->size.y : ctx->screen_size.y;
|
||||
const int len = size_x * size_y;
|
||||
|
||||
lcd_set_region(pos_x, pos_y, size_x, size_y);
|
||||
|
||||
// MUST SET
|
||||
GE_FAST_SET_OFF(LCD_CS);
|
||||
// MUST SET
|
||||
GE_FAST_SET_ON(LCD_DC);
|
||||
for (int i = 0; i < len; i++) {
|
||||
lcd_write_byte(color >> 8);
|
||||
lcd_write_byte(color);
|
||||
}
|
||||
GE_FAST_SET_ON(LCD_CS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 隔行扫描(Interlaced Rendering) 或半帧缓冲(Half-Frame Buffer)
|
||||
* 借鉴NES古早游戏的绘制优化策略减少闪屏和闪烁
|
||||
* 重新设计绘制接口
|
||||
*/
|
||||
|
||||
#define SCREEN_HEIGHT 128
|
||||
#define SCREEN_WIDTH 128
|
||||
typedef enum {
|
||||
GE_RENDER_EVEN_LINES, // 渲染偶数数行
|
||||
GE_RENDER_ODD_LINES, // 渲染奇数数行
|
||||
} ge_render_field_t;
|
||||
static struct ge_content {
|
||||
uint16_t head_canary;
|
||||
uint16_t screen_buffer[SCREEN_HEIGHT / 2][SCREEN_WIDTH];
|
||||
uint16_t tail_canary;
|
||||
} ge_content;
|
||||
static ge_render_field_t current_field = GE_RENDER_EVEN_LINES;
|
||||
|
||||
#define CTX_BUF(ctx) (((struct ge_content*)ctx->context)->screen_buffer)
|
||||
#define CTX_BUF_PTR(ctx, x, y) ((uint16_t*)CTX_BUF(ctx) + SCREEN_WIDTH * (y) + (x))
|
||||
|
||||
#define HEAD_CANARY 0xDEAD
|
||||
#define TAIL_CANARY 0xBEEF
|
||||
|
||||
static int init(ge_render_t* ctx, const ge_render_pos2_t* init_screen_size) {
|
||||
(void)init_screen_size;
|
||||
init_lcd();
|
||||
/**
|
||||
* set canary
|
||||
*/
|
||||
((struct ge_content*)ctx->context)->head_canary = HEAD_CANARY;
|
||||
((struct ge_content*)ctx->context)->tail_canary = TAIL_CANARY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flush(ge_render_t* ctx) {
|
||||
AssertFmt(((struct ge_content*)ctx->context)->head_canary == HEAD_CANARY, "Invalid head canary");
|
||||
AssertFmt(((struct ge_content*)ctx->context)->tail_canary == TAIL_CANARY, "Invalid tail canary");
|
||||
uint16_t* buffer = ((struct ge_content*)ctx->context)->screen_buffer;
|
||||
|
||||
const int start_y = (current_field == GE_RENDER_EVEN_LINES) ? 0 : 1;
|
||||
for (int buffer_y = 0; buffer_y < ctx->screen_size.y / 2; buffer_y++) {
|
||||
const int screen_y = start_y + buffer_y * 2;
|
||||
|
||||
// 设置当前行区域 (1行高)
|
||||
lcd_set_region(0, screen_y, ctx->screen_size.y, 1);
|
||||
|
||||
GE_FAST_SET_OFF(LCD_CS);
|
||||
GE_FAST_SET_ON(LCD_DC);
|
||||
|
||||
// 传输整行数据
|
||||
uint16_t* line_ptr = buffer + buffer_y * ctx->screen_size.x;
|
||||
for (int x = 0; x < ctx->screen_size.x; x++) {
|
||||
lcd_write_byte(*line_ptr >> 8); // 高字节
|
||||
lcd_write_byte(*line_ptr & 0xFF); // 低字节
|
||||
line_ptr++;
|
||||
}
|
||||
|
||||
GE_FAST_SET_ON(LCD_CS);
|
||||
}
|
||||
|
||||
// 切换模式
|
||||
current_field = (current_field == GE_RENDER_EVEN_LINES) ?
|
||||
GE_RENDER_ODD_LINES : GE_RENDER_EVEN_LINES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_need_flush(ge_render_t* ctx, const ge_render_pos2_t* pos) {
|
||||
const int isOdd = pos->y % 2;
|
||||
const int isNeedOdd = (current_field == GE_RENDER_ODD_LINES) ? 1 : 0;
|
||||
return isOdd == isNeedOdd;
|
||||
}
|
||||
|
||||
static inline int should_render_line(int y) {
|
||||
return (y % 2) == (current_field == GE_RENDER_ODD_LINES);
|
||||
}
|
||||
|
||||
static int buf_draw_rect(ge_render_t* ctx, const ge_render_rect_t* rect, uint16_t color) {
|
||||
Assert(ctx != NULL && rect != NULL);
|
||||
|
||||
// 只更新属于当前场的行
|
||||
for (int y = rect->pos.y; y < rect->pos.y + rect->size.y; y++) {
|
||||
if (!should_render_line(y)) {
|
||||
continue;
|
||||
}
|
||||
for (int x = rect->pos.x; x < rect->pos.x + rect->size.x; x++) {
|
||||
*CTX_BUF_PTR(ctx, x, y / 2) = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ge_render_t ge_render = {
|
||||
.context = &ge_content,
|
||||
.screen_size = {
|
||||
.x = 128,
|
||||
.y = 128,
|
||||
},
|
||||
|
||||
.init_func = init,
|
||||
.func_flush = flush,
|
||||
|
||||
.func_draw_point = (ge_render_draw_point_func_t)lcd_draw_point,
|
||||
.func_draw_rect = (ge_render_draw_rect_func_t)buf_draw_rect,
|
||||
.func_draw_text = 0,
|
||||
.func_draw_res = 0,
|
||||
};
|
0
libs/ge_interface/ge_resource.c
Normal file
0
libs/ge_interface/ge_resource.c
Normal file
0
libs/ge_interface/ge_timer.c
Normal file
0
libs/ge_interface/ge_timer.c
Normal file
24
libs/ge_interface/include/ge_input.h
Normal file
24
libs/ge_interface/include/ge_input.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __GE_INPUT_H__
|
||||
#define __GE_INPUT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct ge_input;
|
||||
typedef struct ge_input ge_input_t;
|
||||
typedef union ge_input_event {
|
||||
void* ctx;
|
||||
uintptr_t num;
|
||||
} ge_input_event_t;
|
||||
|
||||
typedef int(*ge_input_send_func_t)(ge_input_t* ctx, ge_input_event_t event);
|
||||
typedef int(*ge_input_peek_func_t)(ge_input_t* ctx, ge_input_event_t* event);
|
||||
typedef int(*ge_input_recv_func_t)(ge_input_t* ctx, ge_input_event_t* event);
|
||||
|
||||
struct ge_input {
|
||||
void* context;
|
||||
ge_input_send_func_t func_send;
|
||||
ge_input_peek_func_t func_peek;
|
||||
ge_input_recv_func_t func_recv;
|
||||
};
|
||||
|
||||
#endif // __GE_INPUT_H__
|
236
libs/ge_interface/include/ge_kfifo.h
Normal file
236
libs/ge_interface/include/ge_kfifo.h
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* A generic kernel FIFO implementation
|
||||
*
|
||||
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __GE_KFIFO_H__
|
||||
#define __GE_KFIFO_H__
|
||||
/**
|
||||
* 仿照linux内核中的kfifo实现
|
||||
*/
|
||||
|
||||
#ifndef GE_MEMORY_BARRIR
|
||||
#define GE_MEMORY_BARRIR() __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#ifndef GE_ARRAY_SIZE
|
||||
#define GE_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif
|
||||
|
||||
struct __ge_kfifo {
|
||||
unsigned int in;
|
||||
unsigned int out;
|
||||
unsigned int mask;
|
||||
unsigned int esize;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define __STRUCT_GE_KFIFO(type, size) \
|
||||
{ \
|
||||
struct __ge_kfifo kfifo; \
|
||||
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
|
||||
}
|
||||
|
||||
/**
|
||||
* DECLARE_KFIFO - macro to declare a fifo object
|
||||
* @fifo: name of the declared fifo
|
||||
* @type: type of the fifo elements
|
||||
* @size: the number of elements in the fifo, this must be a power of 2
|
||||
*/
|
||||
#define DECLARE_GE_KFIFO(fifo, type, size, tname) struct tname __STRUCT_GE_KFIFO(type, size) fifo
|
||||
|
||||
#define INIT_GE_KFIFO(fifo) do { \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__kfifo->in = 0; \
|
||||
__kfifo->out = 0; \
|
||||
__kfifo->mask = GE_ARRAY_SIZE((fifo)->buf) - 1; \
|
||||
__kfifo->esize = sizeof(*((fifo)->buf)); \
|
||||
__kfifo->data = (fifo)->buf; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* DEFINE_KFIFO - macro to define and initialize a fifo
|
||||
* @fifo: name of the declared fifo datatype
|
||||
* @type: type of the fifo elements
|
||||
* @size: the number of elements in the fifo, this must be a power of 2
|
||||
*
|
||||
* Note: the macro can be used for global and local fifo data type variables.
|
||||
*/
|
||||
#define DEFINE_GE_KFIFO(fifo, type, size, tname) \
|
||||
DECLARE_GE_KFIFO(fifo, type, size, tname) = \
|
||||
(struct tname) { { \
|
||||
.in = 0, \
|
||||
.out = 0, \
|
||||
.mask = GE_ARRAY_SIZE((fifo).buf) - 1, \
|
||||
.esize = sizeof(*(fifo).buf), \
|
||||
.data = (fifo).buf, \
|
||||
}, { 0 } }
|
||||
|
||||
/**
|
||||
* kfifo_size - returns the size of the fifo in elements
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_size(fifo) \
|
||||
((fifo)->kfifo.mask + 1)
|
||||
|
||||
/**
|
||||
* kfifo_len - returns the number of used elements in the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_len(fifo) \
|
||||
((fifo)->kfifo.in - (fifo)->kfifo.out)
|
||||
|
||||
/**
|
||||
* kfifo_is_empty - returns true if the fifo is empty
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_is_empty(fifo) \
|
||||
((fifo)->kfifo.in == (fifo)->kfifo.out)
|
||||
|
||||
/**
|
||||
* kfifo_is_full - returns true if the fifo is full
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_is_full(fifo) (ge_kfifo_len(fifo) > (fifo)->kfifo.mask)
|
||||
|
||||
/**
|
||||
* kfifo_put - put data into the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @val: the data to be added
|
||||
*
|
||||
* This macro copies the given value into the fifo.
|
||||
* It returns 0 if the fifo was full. Otherwise it returns the number
|
||||
* processed elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
#define ge_kfifo_put(fifo, val) do { \
|
||||
unsigned int __ret; \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__ret = !ge_kfifo_is_full(fifo); \
|
||||
if (__ret) { \
|
||||
((fifo)->buf)[__kfifo->in & __kfifo->mask] = val; \
|
||||
/*smp_wmb();*/ \
|
||||
GE_MEMORY_BARRIR(); \
|
||||
__kfifo->in++; \
|
||||
} \
|
||||
/*__ret;*/ \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* kfifo_get - get data from the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @val: address where to store the data
|
||||
*
|
||||
* This macro reads the data from the fifo.
|
||||
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
||||
* processed elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
#define ge_kfifo_get(fifo, val) do { \
|
||||
unsigned int __ret; \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__ret = !ge_kfifo_is_empty(fifo); \
|
||||
if (__ret) { \
|
||||
*val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \
|
||||
/*smp_wmb();*/ \
|
||||
GE_MEMORY_BARRIR(); \
|
||||
__kfifo->out++; \
|
||||
} \
|
||||
/*__ret;*/ \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* kfifo_peek - get data from the fifo without removing
|
||||
* @fifo: address of the fifo to be used
|
||||
* @val: address where to store the data
|
||||
*
|
||||
* This reads the data from the fifo without removing it from the fifo.
|
||||
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
||||
* processed elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
#define ge_kfifo_peek(fifo, val) do { \
|
||||
unsigned int __ret; \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__ret = !ge_kfifo_is_empty(fifo); \
|
||||
if (__ret) { \
|
||||
*val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \
|
||||
/*smp_wmb();*/ \
|
||||
GE_MEMORY_BARRIR(); \
|
||||
} \
|
||||
/*__ret;*/ \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* kfifo_in - put data into the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @buf: the data to be added
|
||||
* @n: number of elements to be added
|
||||
*
|
||||
* This macro copies the given buffer into the fifo and returns the
|
||||
* number of copied elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
/*
|
||||
#define kfifo_in(fifo, buf, n) \
|
||||
({ \
|
||||
typeof((fifo) + 1) __tmp = (fifo); \
|
||||
typeof(__tmp->ptr_const) __buf = (buf); \
|
||||
unsigned long __n = (n); \
|
||||
const size_t __recsize = sizeof(*__tmp->rectype); \
|
||||
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||
(__recsize) ?\
|
||||
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
|
||||
__kfifo_in(__kfifo, __buf, __n); \
|
||||
})
|
||||
*/
|
||||
/**
|
||||
* kfifo_out - get data from the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @buf: pointer to the storage buffer
|
||||
* @n: max. number of elements to get
|
||||
*
|
||||
* This macro gets some data from the fifo and returns the numbers of elements
|
||||
* copied.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
/*
|
||||
#define kfifo_out(fifo, buf, n) \
|
||||
({ \
|
||||
typeof((fifo) + 1) __tmp = (fifo); \
|
||||
typeof(__tmp->ptr) __buf = (buf); \
|
||||
unsigned long __n = (n); \
|
||||
const size_t __recsize = sizeof(*__tmp->rectype); \
|
||||
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||
(__recsize) ?\
|
||||
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
|
||||
__kfifo_out(__kfifo, __buf, __n); \
|
||||
})
|
||||
*/
|
||||
|
||||
#endif // __GE_KFIFO_H__
|
42
libs/ge_interface/include/ge_render.h
Normal file
42
libs/ge_interface/include/ge_render.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef __GE_RENDER_H__
|
||||
#define __GE_RENDER_H__
|
||||
|
||||
#include "ge_resource.h"
|
||||
|
||||
typedef int ge_render_unit_t;
|
||||
typedef int ge_render_color_t;
|
||||
|
||||
typedef struct ge_render_pos2 {
|
||||
ge_render_unit_t x;
|
||||
ge_render_unit_t y;
|
||||
} ge_render_pos2_t;
|
||||
|
||||
typedef struct ge_render_rect {
|
||||
ge_render_pos2_t pos;
|
||||
ge_render_pos2_t size;
|
||||
} ge_render_rect_t;
|
||||
|
||||
struct ge_render;
|
||||
typedef struct ge_render ge_render_t;
|
||||
|
||||
typedef int(*ge_render_init_func_t) (ge_render_t* ctx, const ge_render_pos2_t* init_screen_size);
|
||||
typedef int(*ge_render_flush_func_t) (ge_render_t* ctx);
|
||||
|
||||
typedef int(*ge_render_draw_point_func_t) (ge_render_t* ctx, const ge_render_pos2_t* pos, ge_render_color_t color);
|
||||
typedef int(*ge_render_draw_rect_func_t) (ge_render_t* ctx, const ge_render_rect_t* rect, ge_render_color_t color);
|
||||
typedef int(*ge_render_draw_text_func_t) (ge_render_t* ctx, const ge_render_pos2_t* pos, const char* text);
|
||||
typedef int(*ge_render_draw_resource_func_t)(ge_render_t* ctx, const ge_render_pos2_t* pos, const ge_resource_t* res);
|
||||
|
||||
struct ge_render {
|
||||
void* context;
|
||||
const ge_render_pos2_t screen_size;
|
||||
ge_render_init_func_t init_func;
|
||||
ge_render_flush_func_t func_flush;
|
||||
|
||||
ge_render_draw_point_func_t func_draw_point;
|
||||
ge_render_draw_rect_func_t func_draw_rect;
|
||||
ge_render_draw_text_func_t func_draw_text;
|
||||
ge_render_draw_resource_func_t func_draw_res;
|
||||
};
|
||||
|
||||
#endif // __GE_RENDER_H__
|
12
libs/ge_interface/include/ge_resource.h
Normal file
12
libs/ge_interface/include/ge_resource.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef __GE_RESOURCE_H__
|
||||
#define __GE_RESOURCE_H__
|
||||
|
||||
struct ge_resource;
|
||||
typedef struct ge_resource ge_resource_t;
|
||||
|
||||
struct ge_resource {
|
||||
int type;
|
||||
void* context;
|
||||
};
|
||||
|
||||
#endif // __GE_RESOURCE_H__
|
23
libs/ge_interface/include/ge_timer.h
Normal file
23
libs/ge_interface/include/ge_timer.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __GE_TIMER_H__
|
||||
#define __GE_TIMER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
typedef uint64_t ge_time_t;
|
||||
|
||||
struct ge_timer;
|
||||
typedef struct ge_timer ge_timer_t;
|
||||
|
||||
typedef void(*ge_timer_getus_func_t)(ge_timer_t* timer);
|
||||
typedef void(*ge_timer_sleepus_func_t)(const ge_timer_t* timer);
|
||||
typedef void(*ge_timer_getms_func_t)(ge_timer_t* timer);
|
||||
typedef void(*ge_timer_sleepms_func_t)(const ge_timer_t* timer);
|
||||
|
||||
struct ge_timer {
|
||||
ge_time_t time;
|
||||
ge_timer_getms_func_t func_getms;
|
||||
ge_timer_sleepms_func_t func_sleepms;
|
||||
ge_timer_getus_func_t func_getus;
|
||||
ge_timer_sleepus_func_t func_sleepus;
|
||||
};
|
||||
|
||||
#endif // __GE_TIMER_H__
|
Reference in New Issue
Block a user