From d00a9379a9a66e495cdbb2a87ef50195e8c75a67 Mon Sep 17 00:00:00 2001 From: StepanovPlaton Date: Thu, 16 Oct 2025 01:21:57 +0400 Subject: [PATCH] Add micro --- src/Makefile | 55 ++++- src/engine/camera.c | 10 +- src/engine/engine.h | 2 + src/engine/matrix.c | 7 +- src/engine/object.c | 10 +- src/engine/point.c | 14 +- src/engine/point.h | 6 +- src/engine/vector.c | 10 +- src/engine/vector.h | 4 +- src/main.c | 47 ++--- src/objects.h | 71 +++---- src/platforms/micro/lib/ST7789/ST7789.c | 257 ++++++++++++++++++++++++ src/platforms/micro/lib/ST7789/ST7789.h | 46 +++++ src/platforms/micro/micro.c | 27 +++ src/platforms/micro/micro.h | 6 + src/platforms/platform.h | 25 ++- src/platforms/{ => win}/win.c | 2 +- src/platforms/{ => win}/win.h | 0 src/utils/math.c | 32 +++ src/utils/math.h | 10 + 20 files changed, 535 insertions(+), 106 deletions(-) create mode 100644 src/platforms/micro/lib/ST7789/ST7789.c create mode 100644 src/platforms/micro/lib/ST7789/ST7789.h create mode 100644 src/platforms/micro/micro.c create mode 100644 src/platforms/micro/micro.h rename src/platforms/{ => win}/win.c (98%) rename src/platforms/{ => win}/win.h (100%) create mode 100644 src/utils/math.c create mode 100644 src/utils/math.h diff --git a/src/Makefile b/src/Makefile index 868908e..5c3689c 100644 --- a/src/Makefile +++ b/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 \ No newline at end of file +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); \ No newline at end of file diff --git a/src/engine/camera.c b/src/engine/camera.c index 82d00d2..fd90c17 100644 --- a/src/engine/camera.c +++ b/src/engine/camera.c @@ -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) / diff --git a/src/engine/engine.h b/src/engine/engine.h index b55f079..fa4c119 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -1,6 +1,8 @@ #ifndef ENGINE_H #define ENGINE_H +#include "../utils/math.h" + #include "camera.h" #include "matrix.h" #include "object.h" diff --git a/src/engine/matrix.c b/src/engine/matrix.c index 2404b46..2798d5d 100644 --- a/src/engine/matrix.c +++ b/src/engine/matrix.c @@ -1,6 +1,5 @@ #include "matrix.h" - -#include +#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++) { diff --git a/src/engine/object.c b/src/engine/object.c index b03fae5..f8a066c 100644 --- a/src/engine/object.c +++ b/src/engine/object.c @@ -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); } } \ No newline at end of file diff --git a/src/engine/point.c b/src/engine/point.c index 0849b05..a3292f7 100644 --- a/src/engine/point.c +++ b/src/engine/point.c @@ -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]; diff --git a/src/engine/point.h b/src/engine/point.h index b3c65e1..0660eba 100644 --- a/src/engine/point.h +++ b/src/engine/point.h @@ -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 \ No newline at end of file diff --git a/src/engine/vector.c b/src/engine/vector.c index 5283b7b..b5914b4 100644 --- a/src/engine/vector.c +++ b/src/engine/vector.c @@ -1,27 +1,27 @@ #include "vector.h" -#include +#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]) { diff --git a/src/engine/vector.h b/src/engine/vector.h index b6789dd..b07cd60 100644 --- a/src/engine/vector.h +++ b/src/engine/vector.h @@ -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]); diff --git a/src/main.c b/src/main.c index 391307b..e1856c3 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,4 @@ -#include -#include +// #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); } diff --git a/src/objects.h b/src/objects.h index f13fc08..98eb952 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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 \ No newline at end of file diff --git a/src/platforms/micro/lib/ST7789/ST7789.c b/src/platforms/micro/lib/ST7789/ST7789.c new file mode 100644 index 0000000..d1f99a5 --- /dev/null +++ b/src/platforms/micro/lib/ST7789/ST7789.c @@ -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; + } + } +} \ No newline at end of file diff --git a/src/platforms/micro/lib/ST7789/ST7789.h b/src/platforms/micro/lib/ST7789/ST7789.h new file mode 100644 index 0000000..6a3c65d --- /dev/null +++ b/src/platforms/micro/lib/ST7789/ST7789.h @@ -0,0 +1,46 @@ +#ifndef ST7789_H +#define ST7789_H + +#include +#include +#include + +#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 \ No newline at end of file diff --git a/src/platforms/micro/micro.c b/src/platforms/micro/micro.c new file mode 100644 index 0000000..4fd0e22 --- /dev/null +++ b/src/platforms/micro/micro.c @@ -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; +} \ No newline at end of file diff --git a/src/platforms/micro/micro.h b/src/platforms/micro/micro.h new file mode 100644 index 0000000..ebe6ff5 --- /dev/null +++ b/src/platforms/micro/micro.h @@ -0,0 +1,6 @@ +#ifndef MICRO_H +#define MICRO_H + +#include "./lib/ST7789/ST7789.h" + +#endif \ No newline at end of file diff --git a/src/platforms/platform.h b/src/platforms/platform.h index 70329a9..a36e194 100644 --- a/src/platforms/platform.h +++ b/src/platforms/platform.h @@ -5,18 +5,31 @@ #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); void tic(); void destroy(); -#endif \ No newline at end of file +#endif diff --git a/src/platforms/win.c b/src/platforms/win/win.c similarity index 98% rename from src/platforms/win.c rename to src/platforms/win/win.c index 7c812e8..16c119a 100644 --- a/src/platforms/win.c +++ b/src/platforms/win/win.c @@ -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: { diff --git a/src/platforms/win.h b/src/platforms/win/win.h similarity index 100% rename from src/platforms/win.h rename to src/platforms/win/win.h diff --git a/src/utils/math.c b/src/utils/math.c new file mode 100644 index 0000000..dc21d12 --- /dev/null +++ b/src/utils/math.c @@ -0,0 +1,32 @@ +#include "math.h" +#include +#include + +#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 diff --git a/src/utils/math.h b/src/utils/math.h new file mode 100644 index 0000000..a575028 --- /dev/null +++ b/src/utils/math.h @@ -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 \ No newline at end of file