feat(school_stm32): 添加基础的 STM32F103RCT6 项目结构

- 创建了项目的基本目录结构和文件
- 添加了 CMakeLists.txt 和 Makefile 构建配置
- 创建了 main.c 文件,实现了简单的 LED 闪烁和按键检测功能
- 集成了 SEGGER RTT 库
- 添加了 .gitignore 文件,排除了不必要的生成文件
This commit is contained in:
ZZY
2025-06-27 23:09:57 +08:00
parent 5f560c1268
commit 52097a36ee
37 changed files with 7714 additions and 0 deletions

View 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,
};

View 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__

View 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,
};

View File

View File

View 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__

View 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__

View 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__

View 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__

View 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__