Add micro

This commit is contained in:
2025-10-16 01:21:57 +04:00
parent 7698d0e657
commit d00a9379a9
20 changed files with 535 additions and 106 deletions

View File

@@ -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);

View File

@@ -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) /

View File

@@ -1,6 +1,8 @@
#ifndef ENGINE_H
#define ENGINE_H
#include "../utils/math.h"
#include "camera.h"
#include "matrix.h"
#include "object.h"

View File

@@ -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++) {

View File

@@ -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);
}
}

View File

@@ -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];

View File

@@ -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

View File

@@ -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]) {

View File

@@ -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]);

View File

@@ -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(&center_of_object, -1);
point_add_point(&center_of_object, objects[i].position);
float translate_matrix[4][4];
point_create_translate_matrix(objects[i].position, translate_matrix, 1);
point_create_translate_matrix(&center_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(&center_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(&center_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);
}

View File

@@ -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

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

View 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

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

View File

@@ -0,0 +1,6 @@
#ifndef MICRO_H
#define MICRO_H
#include "./lib/ST7789/ST7789.h"
#endif

View File

@@ -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);

View File

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