mirror of
https://github.com/StepanovPlaton/C3DGraphicEngine.git
synced 2026-04-03 20:30:42 +04:00
Add micro
This commit is contained in:
55
src/Makefile
55
src/Makefile
@@ -1,21 +1,50 @@
|
||||
# Desktop options
|
||||
CC = gcc
|
||||
CFLAGS = -std=gnu23 -Wall -Wextra -O2
|
||||
LIBS = -lgdi32
|
||||
|
||||
WIN_TARGET = main.exe
|
||||
UNIX_TARGET = main
|
||||
# Micro options
|
||||
MCU = atmega328p
|
||||
F_CPU = 16000000
|
||||
PROGRAMMER = arduino
|
||||
PORT = COM4
|
||||
MICRO_CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
SIZE = avr-size
|
||||
AVRDUDE = avrdude
|
||||
MICRO_CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL $(CFLAGS)
|
||||
LDFLAGS = -mmcu=$(MCU)
|
||||
|
||||
BASE_SOURCES = main.c engine/engine.c engine/vector.c engine/matrix.c engine/point.c engine/camera.c engine/object.c
|
||||
WIN_SOURCES = $(BASE_SOURCES) platforms/win.c
|
||||
TARGET = main
|
||||
BASE_SOURCES = main.c engine/engine.c engine/vector.c engine/matrix.c engine/point.c engine/camera.c engine/object.c utils/math.c
|
||||
|
||||
WIN_SOURCES = $(BASE_SOURCES) platforms/win/win.c
|
||||
WIN_OBJECTS = $(WIN_SOURCES:.c=.wo)
|
||||
WIN_TARGET = $(TARGET).exe
|
||||
|
||||
UNIX_SOURCES = $(BASE_SOURCES) platforms/unix.c
|
||||
UNIX_OBJECTS = $(UNIX_SOURCES:.c=.uo)
|
||||
MICRO_SOURCES = $(BASE_SOURCES) platforms/micro.c
|
||||
UNIX_TARGET = $(TARGET)
|
||||
|
||||
MICRO_SOURCES = $(BASE_SOURCES) platforms/micro/micro.c platforms/micro/lib/ST7789/ST7789.c
|
||||
MICRO_OBJECTS = $(MICRO_SOURCES:.c=.mo)
|
||||
MICRO_TARGET = $(TARGET)
|
||||
ELF = $(TARGET).elf
|
||||
HEX = $(TARGET).hex
|
||||
|
||||
win: $(WIN_TARGET)
|
||||
|
||||
$(WIN_TARGET): $(WIN_OBJECTS)
|
||||
$(CC) -o $@ $^ $(LIBS)
|
||||
$(GCC) -o $@ $^ $(LIBS)
|
||||
|
||||
micro: $(HEX)
|
||||
|
||||
$(HEX): $(ELF)
|
||||
$(OBJCOPY) -O ihex -R .eeprom $< $@
|
||||
$(SIZE) $@
|
||||
|
||||
$(ELF): $(MICRO_OBJECTS)
|
||||
$(MICRO_CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
%.wo: %.c
|
||||
$(CC) $(CFLAGS) -DWIN -c $< -o $@
|
||||
@@ -24,10 +53,7 @@ $(WIN_TARGET): $(WIN_OBJECTS)
|
||||
$(CC) $(CFLAGS) -DUNIX -c $< -o $@
|
||||
|
||||
%.mo: %.c
|
||||
$(CC) $(CFLAGS) -DMICRO -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(WIN_TARGET) $(WIN_OBJECTS) $(UNIX_OBJECTS) $(MICRO_OBJECTS);
|
||||
$(MICRO_CC) $(MICRO_CFLAGS) -DMICRO -c $< -o $@
|
||||
|
||||
run_win: $(WIN_TARGET)
|
||||
.\$(WIN_TARGET)
|
||||
@@ -35,4 +61,11 @@ run_win: $(WIN_TARGET)
|
||||
run_unix: $(UNIX_TARGET)
|
||||
.\$(UNIX_TARGET)
|
||||
|
||||
.PHONY: all clean rebuild run
|
||||
upload_micro: $(HEX)
|
||||
$(AVRDUDE) -p $(MCU) -c $(PROGRAMMER) -P $(PORT) -b 115200 -U flash:w:$(HEX):i
|
||||
|
||||
clean:
|
||||
rm -f $(WIN_TARGET) $(WIN_OBJECTS) $(UNIX_TARGET) $(UNIX_OBJECTS) $(HEX) $(ELF) $(MICRO_OBJECTS);
|
||||
|
||||
clean_objects:
|
||||
rm -f $(WIN_OBJECTS) $(UNIX_OBJECTS) $(ELF) $(MICRO_OBJECTS);
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "camera.h"
|
||||
|
||||
#include "math.h"
|
||||
#include "../utils/math.h"
|
||||
#include "vector.h"
|
||||
|
||||
void camera_get_view_matrix(const Camera *const camera,
|
||||
@@ -11,12 +11,12 @@ void camera_get_view_matrix(const Camera *const camera,
|
||||
float normal_forward[3];
|
||||
vector_normalize(3, forward, normal_forward);
|
||||
float right[3];
|
||||
cross_product_vectors(camera->up, forward, right);
|
||||
vector_cross_product(camera->up, forward, right);
|
||||
float normal_right[3];
|
||||
vector_normalize(3, right, normal_right);
|
||||
|
||||
float up[3];
|
||||
cross_product_vectors(normal_forward, normal_right, up);
|
||||
vector_cross_product(normal_forward, normal_right, up);
|
||||
float normal_up[3];
|
||||
vector_normalize(3, up, normal_up);
|
||||
|
||||
@@ -29,7 +29,7 @@ void camera_get_view_matrix(const Camera *const camera,
|
||||
view_matrix[i][j] = 1;
|
||||
} else if (j == 3) {
|
||||
view_matrix[i][j] =
|
||||
-1 * dot_product_vectors(vectors[i], camera->position->coordinates);
|
||||
-1 * vector_dot_product(vectors[i], camera->position->coordinates);
|
||||
} else {
|
||||
view_matrix[i][j] = vectors[i][j];
|
||||
}
|
||||
@@ -43,7 +43,7 @@ void camera_get_projection_matrix(const Camera *const camera,
|
||||
projection_matrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
float f = 1 / tan(camera->fov / 2);
|
||||
float f = 1 / e_tan(camera->fov / 2);
|
||||
projection_matrix[0][0] = f / camera->aspect_ratio;
|
||||
projection_matrix[1][1] = f;
|
||||
projection_matrix[2][2] = (camera->max_distance + camera->min_distance) /
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "../utils/math.h"
|
||||
|
||||
#include "camera.h"
|
||||
#include "matrix.h"
|
||||
#include "object.h"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "matrix.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "../utils/math.h"
|
||||
|
||||
void matrix_mult_matrix(int size, const float matrix1[size][size],
|
||||
const float matrix2[size][size],
|
||||
@@ -36,8 +35,8 @@ void create_axis_rotate_matrix(int axis, float angle,
|
||||
}
|
||||
}
|
||||
|
||||
float cos_angle = cosf(angle);
|
||||
float sin_angle = sinf(angle);
|
||||
float cos_angle = e_cos(angle);
|
||||
float sin_angle = e_sin(angle);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
|
||||
@@ -30,12 +30,10 @@ Point object_get_centroid(const Object *const object) {
|
||||
void object_draw(const Object *object, Screen *screen,
|
||||
const float render_matrix[4][4]) {
|
||||
for (int i = 0; i < object->number_of_edges; i++) {
|
||||
Point point1 = object->points[object->edges[i][0]];
|
||||
ScreenPoint screen_point1 =
|
||||
point_convert_to_screen_point(&point1, screen, render_matrix);
|
||||
Point point2 = object->points[object->edges[i][1]];
|
||||
ScreenPoint screen_point2 =
|
||||
point_convert_to_screen_point(&point2, screen, render_matrix);
|
||||
ScreenPoint screen_point1 = point_to_screen_point(
|
||||
&object->points[object->edges[i][0]], screen, render_matrix);
|
||||
ScreenPoint screen_point2 = point_to_screen_point(
|
||||
&object->points[object->edges[i][1]], screen, render_matrix);
|
||||
screen->draw_line(&screen_point1, &screen_point2);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,16 @@
|
||||
#include "../utils/screen.h"
|
||||
#include "matrix.h"
|
||||
|
||||
void point_add_point(Point *const point, const Point *const other_point) {
|
||||
for (int i = 0; i < 3; i++)
|
||||
point->coordinates[i] += other_point->coordinates[i];
|
||||
}
|
||||
|
||||
void point_mult_number(Point *const point, const int k) {
|
||||
for (int i = 0; i < 3; i++)
|
||||
point->coordinates[i] *= k;
|
||||
}
|
||||
|
||||
void point_transform(Point *const point, int size,
|
||||
const float translate_matrix[size][size]) {
|
||||
float new_coordinates[3];
|
||||
@@ -25,8 +35,8 @@ void point_create_translate_matrix(const Point *const position,
|
||||
}
|
||||
}
|
||||
|
||||
ScreenPoint point_convert_to_screen_point(Point *point, Screen *screen,
|
||||
const float render_matrix[4][4]) {
|
||||
ScreenPoint point_to_screen_point(Point *point, Screen *screen,
|
||||
const float render_matrix[4][4]) {
|
||||
float tmp[] = {point->coordinates[0], point->coordinates[1],
|
||||
point->coordinates[2], 1.0f};
|
||||
float point_projection_view[4];
|
||||
|
||||
@@ -7,11 +7,13 @@ typedef struct Point {
|
||||
float coordinates[3];
|
||||
} Point;
|
||||
|
||||
void point_add_point(Point *const point, const Point *const other_point);
|
||||
void point_mult_number(Point *const point, const int k);
|
||||
void point_transform(Point *const point, int size,
|
||||
const float translate_matrix[size][size]);
|
||||
void point_create_translate_matrix(const Point *const position,
|
||||
float translate_matrix[4][4], int k);
|
||||
ScreenPoint point_convert_to_screen_point(Point *point, Screen *screen,
|
||||
const float render_matrix[4][4]);
|
||||
ScreenPoint point_to_screen_point(Point *point, Screen *screen,
|
||||
const float render_matrix[4][4]);
|
||||
|
||||
#endif
|
||||
@@ -1,27 +1,27 @@
|
||||
#include "vector.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "../utils/math.h"
|
||||
|
||||
void vector_substruct(int size, const float v1[size], const float v2[size],
|
||||
float r[size]) {
|
||||
for (int i = 0; i < size; i++)
|
||||
r[i] = v1[i] - v2[i];
|
||||
}
|
||||
void cross_product_vectors(const float v1[3], const float v2[3], float r[3]) {
|
||||
void vector_cross_product(const float v1[3], const float v2[3], float r[3]) {
|
||||
r[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
||||
r[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
||||
r[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
||||
}
|
||||
float dot_product_vectors(const float v1[3], const float v2[3]) {
|
||||
float vector_dot_product(const float v1[3], const float v2[3]) {
|
||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||
}
|
||||
void vector_normalize(int size, const float v[size], float r[size]) {
|
||||
float divider = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
divider += v[i] * v[i];
|
||||
divider = sqrt(divider);
|
||||
divider = e_rsqrt(divider);
|
||||
for (int i = 0; i < size; i++)
|
||||
r[i] = v[i] / divider;
|
||||
r[i] = v[i] * divider;
|
||||
}
|
||||
|
||||
// void print_vector(int size, float vector[size]) {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
void vector_substruct(int size, const float v1[size], const float v2[size],
|
||||
float r[size]);
|
||||
void cross_product_vectors(const float v1[3], const float v2[3], float r[3]);
|
||||
float dot_product_vectors(const float v1[3], const float v2[3]);
|
||||
void vector_cross_product(const float v1[3], const float v2[3], float r[3]);
|
||||
float vector_dot_product(const float v1[3], const float v2[3]);
|
||||
void vector_normalize(int size, const float v[size], float r[size]);
|
||||
// void print_vector(int size, float vector[size]);
|
||||
|
||||
|
||||
47
src/main.c
47
src/main.c
@@ -1,5 +1,4 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
// #define FMATH
|
||||
|
||||
#include "engine/engine.h"
|
||||
|
||||
@@ -13,29 +12,34 @@
|
||||
float render_matrix[4][4];
|
||||
|
||||
void init_engine() {
|
||||
printff(BLUE ITALIC, "Engine init...");
|
||||
logff(BLUE ITALIC, "Engine init...");
|
||||
|
||||
float view_matrix[4][4];
|
||||
camera_get_view_matrix(&camera, view_matrix);
|
||||
printf("View matrix created\n");
|
||||
logf("View matrix created\n");
|
||||
|
||||
float projection_matrix[4][4];
|
||||
camera_get_projection_matrix(&camera, projection_matrix);
|
||||
printf("Projection matrix created\n");
|
||||
logf("Projection matrix created\n");
|
||||
matrix_mult_matrix(4, projection_matrix, view_matrix, render_matrix);
|
||||
printf("Render matrix created\n");
|
||||
logf("Render matrix created\n");
|
||||
|
||||
for (int i = 0; i < number_of_objects; i++) {
|
||||
Point center_of_object = object_get_centroid(&(objects[i]));
|
||||
point_mult_number(¢er_of_object, -1);
|
||||
point_add_point(¢er_of_object, objects[i].position);
|
||||
|
||||
float translate_matrix[4][4];
|
||||
point_create_translate_matrix(objects[i].position, translate_matrix, 1);
|
||||
point_create_translate_matrix(¢er_of_object, translate_matrix, 1);
|
||||
object_transform(&(objects[i]), 4, translate_matrix);
|
||||
printf("Go %s to (%f, %f, %f)\n", objects[i].name,
|
||||
objects[i].position->coordinates[0],
|
||||
objects[i].position->coordinates[1],
|
||||
objects[i].position->coordinates[2]);
|
||||
|
||||
logf("Go %s to (%f, %f, %f)\n", objects[i].name,
|
||||
objects[i].position->coordinates[0],
|
||||
objects[i].position->coordinates[1],
|
||||
objects[i].position->coordinates[2]);
|
||||
}
|
||||
|
||||
printff(BLUE BOLD UNDERLINE, "Engine init complete!");
|
||||
logff(BLUE BOLD UNDERLINE, "Engine init complete!");
|
||||
}
|
||||
|
||||
void render(Screen screen) {
|
||||
@@ -46,27 +50,14 @@ void render(Screen screen) {
|
||||
|
||||
void tic() {
|
||||
for (int i = 0; i < number_of_objects; i++) {
|
||||
float reverse_translate_matrix[4][4];
|
||||
point_create_translate_matrix(objects[i].position, reverse_translate_matrix,
|
||||
-1);
|
||||
object_transform(&(objects[i]), 4, reverse_translate_matrix);
|
||||
|
||||
Point center_of_object = object_get_centroid(&(objects[i]));
|
||||
float reverse_center_translate_matrix[4][4];
|
||||
point_create_translate_matrix(¢er_of_object,
|
||||
reverse_center_translate_matrix, -1);
|
||||
object_transform(&(objects[i]), 4, reverse_center_translate_matrix);
|
||||
float translate_matrix[4][4];
|
||||
point_create_translate_matrix(objects[i].position, translate_matrix, -1);
|
||||
object_transform(&(objects[i]), 4, translate_matrix);
|
||||
|
||||
float rotate_matrix[3][3];
|
||||
create_rotate_matrix(*(objects[i].rotate_speed), rotate_matrix);
|
||||
object_transform(&(objects[i]), 3, rotate_matrix);
|
||||
|
||||
float center_translate_matrix[4][4];
|
||||
point_create_translate_matrix(¢er_of_object, center_translate_matrix,
|
||||
1);
|
||||
object_transform(&(objects[i]), 4, center_translate_matrix);
|
||||
|
||||
float translate_matrix[4][4];
|
||||
point_create_translate_matrix(objects[i].position, translate_matrix, 1);
|
||||
object_transform(&(objects[i]), 4, translate_matrix);
|
||||
}
|
||||
|
||||
@@ -21,41 +21,43 @@ const Object cube = {.name = "cube",
|
||||
.position = &cube_position,
|
||||
.rotate_speed = &cube_speed};
|
||||
|
||||
Point pyramid_points[] = {{.coordinates = {-1.0f, 0.0f, -1.0f}},
|
||||
{.coordinates = {1.0f, 0.0f, -1.0f}},
|
||||
{.coordinates = {1.0f, 0.0f, 1.0f}},
|
||||
{.coordinates = {-1.0f, 0.0f, 1.0f}},
|
||||
{.coordinates = {0.0f, 1.5f, 0.0f}}};
|
||||
Point pyramid_position = {.coordinates = {6.0f, 3.0f, 5.0f}};
|
||||
const int pyramid_edges[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},
|
||||
{0, 4}, {1, 4}, {2, 4}, {3, 4}};
|
||||
const float pyramid_speed[] = {0.0f, 0.0f, 0.03f};
|
||||
const Object pyramid = {.name = "pyramid",
|
||||
.points = pyramid_points,
|
||||
.edges = pyramid_edges,
|
||||
.number_of_points = 5,
|
||||
.number_of_edges = 8,
|
||||
.position = &pyramid_position,
|
||||
.rotate_speed = &pyramid_speed};
|
||||
// Point pyramid_points[] = {{.coordinates = {-1.0f, 0.0f, -1.0f}},
|
||||
// {.coordinates = {1.0f, 0.0f, -1.0f}},
|
||||
// {.coordinates = {1.0f, 0.0f, 1.0f}},
|
||||
// {.coordinates = {-1.0f, 0.0f, 1.0f}},
|
||||
// {.coordinates = {0.0f, 1.5f, 0.0f}}};
|
||||
// Point pyramid_position = {.coordinates = {6.0f, 3.0f, 5.0f}};
|
||||
// const int pyramid_edges[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},
|
||||
// {0, 4}, {1, 4}, {2, 4}, {3, 4}};
|
||||
// const float pyramid_speed[] = {0.0f, 0.0f, 0.03f};
|
||||
// const Object pyramid = {.name = "pyramid",
|
||||
// .points = pyramid_points,
|
||||
// .edges = pyramid_edges,
|
||||
// .number_of_points = 5,
|
||||
// .number_of_edges = 8,
|
||||
// .position = &pyramid_position,
|
||||
// .rotate_speed = &pyramid_speed};
|
||||
|
||||
Point prism_points[] = {
|
||||
{.coordinates = {0.0f, 0.0f, 0.0f}}, {.coordinates = {1.0f, 0.0f, 0.0f}},
|
||||
{.coordinates = {0.5f, 0.0f, 1.0f}}, {.coordinates = {0.0f, 1.0f, 0.0f}},
|
||||
{.coordinates = {1.0f, 1.0f, 0.0f}}, {.coordinates = {0.5f, 1.0f, 1.0f}}};
|
||||
Point prism_position = {.coordinates = {10.0f, 10.0f, 10.0f}};
|
||||
const int prism_edges[][2] = {{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5},
|
||||
{5, 3}, {0, 3}, {1, 4}, {2, 5}};
|
||||
const float prism_speed[] = {0.0f, 0.03f, 0.0f};
|
||||
const Object prism = {.name = "prism",
|
||||
.points = prism_points,
|
||||
.edges = prism_edges,
|
||||
.number_of_points = 6,
|
||||
.number_of_edges = 9,
|
||||
.position = &prism_position,
|
||||
.rotate_speed = &prism_speed};
|
||||
// Point prism_points[] = {
|
||||
// {.coordinates = {0.0f, 0.0f, 0.0f}}, {.coordinates = {1.0f, 0.0f, 0.0f}},
|
||||
// {.coordinates = {0.5f, 0.0f, 1.0f}}, {.coordinates = {0.0f, 1.0f, 0.0f}},
|
||||
// {.coordinates = {1.0f, 1.0f, 0.0f}}, {.coordinates =
|
||||
// {0.5f, 1.0f, 1.0f}}};
|
||||
// Point prism_position = {.coordinates = {10.0f, 10.0f, 10.0f}};
|
||||
// const int prism_edges[][2] = {{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5},
|
||||
// {5, 3}, {0, 3}, {1, 4}, {2, 5}};
|
||||
// const float prism_speed[] = {0.0f, 0.03f, 0.0f};
|
||||
// const Object prism = {.name = "prism",
|
||||
// .points = prism_points,
|
||||
// .edges = prism_edges,
|
||||
// .number_of_points = 6,
|
||||
// .number_of_edges = 9,
|
||||
// .position = &prism_position,
|
||||
// .rotate_speed = &prism_speed};
|
||||
|
||||
const int number_of_objects = 3;
|
||||
Object objects[] = {cube, pyramid, prism};
|
||||
const int number_of_objects = 1;
|
||||
// Object objects[] = {cube, pyramid, prism};
|
||||
Object objects[] = {cube};
|
||||
|
||||
Point camera_position = {.coordinates = {0.0f, 0.0f, 0.0f}};
|
||||
Point camera_target = {.coordinates = {1.0f, 1.0f, 1.0f}};
|
||||
@@ -65,6 +67,7 @@ const Camera camera = {.position = &camera_position,
|
||||
.fov = 120.0f,
|
||||
.max_distance = 20.0f,
|
||||
.min_distance = .0f,
|
||||
.aspect_ratio = WINDOW_WIDTH / WINDOW_HEIGHT};
|
||||
.aspect_ratio =
|
||||
(float)WINDOW_WIDTH / (float)WINDOW_HEIGHT};
|
||||
|
||||
#endif
|
||||
257
src/platforms/micro/lib/ST7789/ST7789.c
Normal file
257
src/platforms/micro/lib/ST7789/ST7789.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#include "ST7789.h"
|
||||
|
||||
#define DC_HIGH() (ST7789_PORT |= (1 << DC_PIN))
|
||||
#define DC_LOW() (ST7789_PORT &= ~(1 << DC_PIN))
|
||||
#define RESET_HIGH() (ST7789_PORT |= (1 << RESET_PIN))
|
||||
#define RESET_LOW() (ST7789_PORT &= ~(1 << RESET_PIN))
|
||||
#define CS_HIGH() (ST7789_PORT |= (1 << CS_PIN))
|
||||
#define CS_LOW() (ST7789_PORT &= ~(1 << CS_PIN))
|
||||
|
||||
static void _spi_init(void) {
|
||||
// Настройка пинов SPI: MOSI (PB3), SCK (PB5) как выходы
|
||||
DDRB |= (1 << PB3) | (1 << PB5);
|
||||
|
||||
// Включение SPI: Master, режим 0, частота F_CPU/4
|
||||
SPCR = (1 << SPE) | (1 << MSTR);
|
||||
SPSR = (1 << SPI2X); // Удвоение скорости (F_CPU/2)
|
||||
}
|
||||
static void _spi_write(uint8_t data) {
|
||||
SPDR = data;
|
||||
while (!(SPSR & (1 << SPIF)))
|
||||
;
|
||||
}
|
||||
|
||||
void _st7789_write_command(uint8_t cmd) {
|
||||
DC_LOW();
|
||||
CS_LOW();
|
||||
_spi_write(cmd);
|
||||
CS_HIGH();
|
||||
}
|
||||
void _st7789_write_data(uint8_t data) {
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
_spi_write(data);
|
||||
CS_HIGH();
|
||||
}
|
||||
void _st7789_write_data_16(uint16_t data) {
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
_spi_write(data >> 8); // Старший байт
|
||||
_spi_write(data & 0xFF); // Младший байт
|
||||
CS_HIGH();
|
||||
}
|
||||
void _st7789_set_address_window(uint16_t x0, uint16_t y0, uint16_t x1,
|
||||
uint16_t y1) {
|
||||
// Установка столбцов (CASET)
|
||||
_st7789_write_command(0x2A);
|
||||
_st7789_write_data(x0 >> 8);
|
||||
_st7789_write_data(x0 & 0xFF);
|
||||
_st7789_write_data(x1 >> 8);
|
||||
_st7789_write_data(x1 & 0xFF);
|
||||
|
||||
// Установка строк (RASET)
|
||||
_st7789_write_command(0x2B);
|
||||
_st7789_write_data(y0 >> 8);
|
||||
_st7789_write_data(y0 & 0xFF);
|
||||
_st7789_write_data(y1 >> 8);
|
||||
_st7789_write_data(y1 & 0xFF);
|
||||
|
||||
// Команда записи в память (RAMWR)
|
||||
_st7789_write_command(0x2C);
|
||||
}
|
||||
|
||||
void st7789_init(void) {
|
||||
// Настройка пинов управления
|
||||
ST7789_DDR |= (1 << DC_PIN) | (1 << RESET_PIN) | (1 << CS_PIN);
|
||||
|
||||
// Инициализация SPI
|
||||
_spi_init();
|
||||
|
||||
// Процедура сброса дисплея
|
||||
RESET_HIGH();
|
||||
_delay_ms(10);
|
||||
RESET_LOW();
|
||||
_delay_ms(10);
|
||||
RESET_HIGH();
|
||||
_delay_ms(150);
|
||||
|
||||
// Последовательность инициализации ST7789
|
||||
_st7789_write_command(0x01); // SWRESET: программный сброс
|
||||
_delay_ms(150);
|
||||
|
||||
_st7789_write_command(0x11); // SLPOUT: выход из спящего режима
|
||||
_delay_ms(255);
|
||||
|
||||
_st7789_write_command(0x3A); // COLMOD: установка формата цвета
|
||||
_st7789_write_data(0x05); // 16 бит на пиксель (RGB565)
|
||||
|
||||
// ВАЖНО: Установка горизонтальной ориентации
|
||||
_st7789_write_command(0x36); // MADCTL: управление ориентацией
|
||||
_st7789_write_data(MADCTL_LANDSCAPE); // Горизонтальная ориентация
|
||||
|
||||
// Дополнительные настройки для лучшего отображения
|
||||
_st7789_write_command(0xB2); // PORCTRL: настройка porch
|
||||
_st7789_write_data(0x0C);
|
||||
_st7789_write_data(0x0C);
|
||||
_st7789_write_data(0x00);
|
||||
_st7789_write_data(0x33);
|
||||
_st7789_write_data(0x33);
|
||||
|
||||
_st7789_write_command(0xB7); // GCTRL: настройка gate control
|
||||
_st7789_write_data(0x35);
|
||||
|
||||
_st7789_write_command(0xBB); // VCOMS: настройка VCOM
|
||||
_st7789_write_data(0x2B);
|
||||
|
||||
_st7789_write_command(0xC0); // LCMCTRL: настройка LCM
|
||||
_st7789_write_data(0x2C);
|
||||
|
||||
_st7789_write_command(0xC2); // VDVVRHEN: настройка VDV и VRH
|
||||
_st7789_write_data(0x01);
|
||||
_st7789_write_data(0xFF);
|
||||
|
||||
_st7789_write_command(0xC3); // VRHS: настройка VRH
|
||||
_st7789_write_data(0x11);
|
||||
|
||||
_st7789_write_command(0xC4); // VDVS: настройка VDV
|
||||
_st7789_write_data(0x20);
|
||||
|
||||
_st7789_write_command(0xC6); // FRCTRL2: настройка частоты
|
||||
_st7789_write_data(0x0F);
|
||||
|
||||
_st7789_write_command(0xD0); // PWCTRL1: настройка питания
|
||||
_st7789_write_data(0xA4);
|
||||
_st7789_write_data(0xA1);
|
||||
|
||||
// Включение нормального режима и дисплея
|
||||
_st7789_write_command(0x21); // INVON: инверсия цветов (опционально)
|
||||
_st7789_write_command(0x13); // NORON: нормальный режим
|
||||
_delay_ms(10);
|
||||
|
||||
_st7789_write_command(0x29); // DISPON: включение дисплея
|
||||
_delay_ms(100);
|
||||
}
|
||||
|
||||
void st7789_fill_screen(uint16_t color) {
|
||||
// Установка окна на весь экран
|
||||
_st7789_set_address_window(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
|
||||
|
||||
// Быстрая заливка через непрерывную передачу
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
uint32_t total_pixels = (uint32_t)DISPLAY_WIDTH * DISPLAY_HEIGHT;
|
||||
|
||||
// Оптимизированная заливка экрана
|
||||
for (uint32_t i = 0; i < total_pixels; i++) {
|
||||
_spi_write(color >> 8); // Старший байт цвета
|
||||
_spi_write(color & 0xFF); // Младший байт цвета
|
||||
}
|
||||
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void st7789_draw_hline(uint16_t x, uint16_t y, uint16_t length,
|
||||
uint16_t color) {
|
||||
// Проверка границ
|
||||
if (y >= DISPLAY_HEIGHT)
|
||||
return;
|
||||
if (x >= DISPLAY_WIDTH)
|
||||
return;
|
||||
|
||||
uint16_t x_end = x + length - 1;
|
||||
if (x_end >= DISPLAY_WIDTH)
|
||||
x_end = DISPLAY_WIDTH - 1;
|
||||
|
||||
_st7789_set_address_window(x, y, x_end, y);
|
||||
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
for (uint16_t i = x; i <= x_end; i++) {
|
||||
_spi_write(color >> 8);
|
||||
_spi_write(color & 0xFF);
|
||||
}
|
||||
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Рисование вертикальной линии
|
||||
* @param x X координата
|
||||
* @param y Начальная Y координата
|
||||
* @param length Длина линии
|
||||
* @param color Цвет линии
|
||||
*/
|
||||
void st7789_draw_vline(uint16_t x, uint16_t y, uint16_t length,
|
||||
uint16_t color) {
|
||||
// Проверка границ
|
||||
if (x >= DISPLAY_WIDTH)
|
||||
return;
|
||||
if (y >= DISPLAY_HEIGHT)
|
||||
return;
|
||||
|
||||
uint16_t y_end = y + length - 1;
|
||||
if (y_end >= DISPLAY_HEIGHT)
|
||||
y_end = DISPLAY_HEIGHT - 1;
|
||||
|
||||
_st7789_set_address_window(x, y, x, y_end);
|
||||
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
for (uint16_t i = y; i <= y_end; i++) {
|
||||
_spi_write(color >> 8);
|
||||
_spi_write(color & 0xFF);
|
||||
}
|
||||
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void st7789_draw_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
|
||||
uint16_t color) {
|
||||
// Оптимизация для горизонтальных и вертикальных линий
|
||||
if (y0 == y1) {
|
||||
if (x0 < x1)
|
||||
st7789_draw_hline(x0, y0, x1 - x0 + 1, color);
|
||||
else
|
||||
st7789_draw_hline(x1, y0, x0 - x1 + 1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
if (x0 == x1) {
|
||||
if (y0 < y1)
|
||||
st7789_draw_vline(x0, y0, y1 - y0 + 1, color);
|
||||
else
|
||||
st7789_draw_vline(x0, y1, y0 - y1 + 1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
// Алгоритм Брезенхэма для произвольных линий
|
||||
int16_t dx = (x1 > x0) ? (x1 - x0) : (x0 - x1);
|
||||
int16_t dy = (y1 > y0) ? (y1 - y0) : (y0 - y1);
|
||||
int16_t sx = (x0 < x1) ? 1 : -1;
|
||||
int16_t sy = (y0 < y1) ? 1 : -1;
|
||||
int16_t err = dx - dy;
|
||||
|
||||
while (1) {
|
||||
// Рисование пикселя (с проверкой границ)
|
||||
if (x0 < DISPLAY_WIDTH && y0 < DISPLAY_HEIGHT) {
|
||||
_st7789_set_address_window(x0, y0, x0, y0);
|
||||
_st7789_write_data_16(color);
|
||||
}
|
||||
|
||||
if (x0 == x1 && y0 == y1)
|
||||
break;
|
||||
|
||||
int16_t e2 = 2 * err;
|
||||
if (e2 > -dy) {
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/platforms/micro/lib/ST7789/ST7789.h
Normal file
46
src/platforms/micro/lib/ST7789/ST7789.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef ST7789_H
|
||||
#define ST7789_H
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <stdint.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define RGB565(r, g, b) \
|
||||
((((255 - r) & 0xF8) << 8) | (((255 - g) & 0xFC) << 3) | ((255 - b) >> 3))
|
||||
|
||||
#define COLOR_BLACK RGB565(0, 0, 0)
|
||||
#define COLOR_WHITE RGB565(255, 255, 255)
|
||||
|
||||
#define DISPLAY_WIDTH 160
|
||||
#define DISPLAY_HEIGHT 128
|
||||
#define ST7789_PORT PORTB
|
||||
#define ST7789_DDR DDRB
|
||||
#define DC_PIN PB0 // Data/Command
|
||||
#define RESET_PIN PB1 // Reset
|
||||
#define CS_PIN PB2 // Chip Select
|
||||
|
||||
#define MADCTL_MY 0x80 // Page Address Order (обратный по Y)
|
||||
#define MADCTL_MX 0x40 // Column Address Order (обратный по X)
|
||||
#define MADCTL_MV 0x20 // Page/Column Order (перестановка X/Y)
|
||||
#define MADCTL_ML 0x10 // Line Address Order (обратный порядок строк)
|
||||
#define MADCTL_RGB 0x00 // RGB порядок цветов
|
||||
#define MADCTL_BGR 0x08 // BGR порядок цветов
|
||||
#define MADCTL_MH 0x04 // Display Data Latch Order
|
||||
#define MADCTL_LANDSCAPE (MADCTL_MV | MADCTL_MX)
|
||||
|
||||
void st7789_init(void);
|
||||
|
||||
void st7789_fill_screen(uint16_t color);
|
||||
void st7789_draw_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
|
||||
uint16_t color);
|
||||
|
||||
void st7789_draw_hline(uint16_t x, uint16_t y, uint16_t length, uint16_t color);
|
||||
void st7789_draw_vline(uint16_t x, uint16_t y, uint16_t length, uint16_t color);
|
||||
|
||||
// void _st7789_write_command(uint8_t cmd);
|
||||
// void _st7789_write_data(uint8_t data);
|
||||
// void _st7789_write_data_16(uint16_t data);
|
||||
// void _st7789_set_address_window(uint16_t x0, uint16_t y0, uint16_t x1,
|
||||
// uint16_t y1);
|
||||
|
||||
#endif // ST7789_H
|
||||
27
src/platforms/micro/micro.c
Normal file
27
src/platforms/micro/micro.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "./lib/ST7789/ST7789.h"
|
||||
|
||||
#include "../platform.h"
|
||||
#include "micro.h"
|
||||
|
||||
void draw_line(const ScreenPoint *sp1, const ScreenPoint *sp2) {
|
||||
st7789_draw_line(0, 0, 160, 128, COLOR_WHITE);
|
||||
st7789_draw_line(sp1->coordinates[0], sp1->coordinates[1],
|
||||
sp2->coordinates[0], sp2->coordinates[1], COLOR_WHITE);
|
||||
};
|
||||
Screen screen = {
|
||||
.width = DISPLAY_WIDTH, .height = DISPLAY_HEIGHT, .draw_line = &draw_line};
|
||||
|
||||
int main(void) {
|
||||
init_engine();
|
||||
|
||||
st7789_init();
|
||||
|
||||
while (1) {
|
||||
st7789_fill_screen(COLOR_BLACK);
|
||||
render(screen);
|
||||
|
||||
_delay_ms(1000 / FPS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
src/platforms/micro/micro.h
Normal file
6
src/platforms/micro/micro.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef MICRO_H
|
||||
#define MICRO_H
|
||||
|
||||
#include "./lib/ST7789/ST7789.h"
|
||||
|
||||
#endif
|
||||
@@ -5,14 +5,27 @@
|
||||
#include "log.h"
|
||||
|
||||
#ifdef WIN
|
||||
#include "win.h"
|
||||
#include "win/win.h"
|
||||
|
||||
#define FPS 10
|
||||
#define WINDOW_WIDTH 800.0f
|
||||
#define WINDOW_HEIGHT 600.0f
|
||||
#define FPS 25
|
||||
#define WINDOW_WIDTH 800
|
||||
#define WINDOW_HEIGHT 600
|
||||
#define BG_COLOR BLACK_BRUSH
|
||||
#define COLOR RGB(255, 255, 255)
|
||||
#endif
|
||||
|
||||
#endif // WIN
|
||||
|
||||
#ifdef MICRO
|
||||
|
||||
#define FPS 5
|
||||
#include "micro/micro.h"
|
||||
|
||||
#define DISPLAY_WIDTH 160
|
||||
#define DISPLAY_HEIGHT 128
|
||||
#define WINDOW_WIDTH DISPLAY_WIDTH
|
||||
#define WINDOW_HEIGHT DISPLAY_HEIGHT
|
||||
|
||||
#endif // MICRO
|
||||
|
||||
void init_engine();
|
||||
void render(Screen screen);
|
||||
|
||||
@@ -6,7 +6,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
switch (uMsg) {
|
||||
case WM_CREATE:
|
||||
SetTimer(hwnd, 1, 50, NULL);
|
||||
SetTimer(hwnd, 1, 1000 / FPS, NULL);
|
||||
init_engine();
|
||||
return 0;
|
||||
case WM_PAINT: {
|
||||
32
src/utils/math.c
Normal file
32
src/utils/math.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "math.h"
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define FMATH
|
||||
#ifdef FMATH
|
||||
|
||||
float e_rsqrt(float x) {
|
||||
const float x2 = x * 0.5F;
|
||||
const float threehalfs = 1.5F;
|
||||
union {
|
||||
float f;
|
||||
uint32_t i;
|
||||
} conv = {x};
|
||||
conv.i = 0x5f3759df - (conv.i >> 1);
|
||||
conv.f *= threehalfs - x2 * conv.f * conv.f;
|
||||
return conv.f;
|
||||
}
|
||||
|
||||
float e_cos(float x) { return cosf(x); }
|
||||
float e_sin(float x) { return sinf(x); }
|
||||
float e_tan(float x) { return tanf(x); }
|
||||
|
||||
#else
|
||||
|
||||
float e_rsqrt(float x) { return 1.0f / sqrtf(x); }
|
||||
|
||||
float e_cos(float x) { return cosf(x); }
|
||||
float e_sin(float x) { return sinf(x); }
|
||||
float e_tan(float x) { return tanf(x); }
|
||||
|
||||
#endif
|
||||
10
src/utils/math.h
Normal file
10
src/utils/math.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef MATH_H
|
||||
#define MATH_H
|
||||
|
||||
float e_rsqrt(float x);
|
||||
|
||||
float e_cos(float x);
|
||||
float e_sin(float x);
|
||||
float e_tan(float x);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user