diff --git a/.gitignore b/.gitignore index 4578b5d..6e17407 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ src/main.exe src/main +src/main.elf +src/main.hex *.wo *.uo *.mo \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b32d149 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "files.associations": { + "array": "c", + "string_view": "c", + "format": "c", + "initializer_list": "c", + "ranges": "c", + "span": "c", + "micro.h": "c", + "MP6050.C": "cpp", + "MPU6050.C": "cpp", + "mpu6050.h": "c", + "st7789.h": "c", + "i2c_unit_conf.h": "c", + "mpu6050_conf.h": "c", + "i2c_unit.h": "c", + "variant": "c" + } +} diff --git a/src/Makefile b/src/Makefile index 5c3689c..27d68da 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,7 +26,7 @@ UNIX_SOURCES = $(BASE_SOURCES) platforms/unix.c UNIX_OBJECTS = $(UNIX_SOURCES:.c=.uo) UNIX_TARGET = $(TARGET) -MICRO_SOURCES = $(BASE_SOURCES) platforms/micro/micro.c platforms/micro/lib/ST7789/ST7789.c +MICRO_SOURCES = $(BASE_SOURCES) platforms/micro/micro.c platforms/micro/lib/ST7789/ST7789.c platforms/micro/lib/MPU6050/MPU6050.c platforms/micro/lib/I2C/I2C.c MICRO_OBJECTS = $(MICRO_SOURCES:.c=.mo) MICRO_TARGET = $(TARGET) ELF = $(TARGET).elf @@ -35,7 +35,7 @@ HEX = $(TARGET).hex win: $(WIN_TARGET) $(WIN_TARGET): $(WIN_OBJECTS) - $(GCC) -o $@ $^ $(LIBS) + $(CC) -o $@ $^ $(LIBS) micro: $(HEX) @@ -53,7 +53,7 @@ $(ELF): $(MICRO_OBJECTS) $(CC) $(CFLAGS) -DUNIX -c $< -o $@ %.mo: %.c - $(MICRO_CC) $(MICRO_CFLAGS) -DMICRO -c $< -o $@ + $(MICRO_CC) $(MICRO_CFLAGS) -DMICRO -c $< -o $@ run_win: $(WIN_TARGET) .\$(WIN_TARGET) diff --git a/src/engine/camera.c b/src/engine/camera.c index fd90c17..8ec362a 100644 --- a/src/engine/camera.c +++ b/src/engine/camera.c @@ -3,8 +3,7 @@ #include "../utils/math.h" #include "vector.h" -void camera_get_view_matrix(const Camera *const camera, - float view_matrix[4][4]) { +void camera_get_view_matrix(const Camera *const camera, float *view_matrix) { float forward[3]; vector_substruct(3, camera->position->coordinates, camera->target->coordinates, forward); @@ -23,32 +22,33 @@ void camera_get_view_matrix(const Camera *const camera, float *vectors[] = {normal_right, normal_up, normal_forward}; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - view_matrix[i][j] = 0; + view_matrix[i * 4 + j] = 0; if (i == 3) { if (j == 3) - view_matrix[i][j] = 1; + view_matrix[i * 4 + j] = 1; } else if (j == 3) { - view_matrix[i][j] = + view_matrix[i * 4 + j] = -1 * vector_dot_product(vectors[i], camera->position->coordinates); } else { - view_matrix[i][j] = vectors[i][j]; + view_matrix[i * 4 + j] = vectors[i][j]; } } } } void camera_get_projection_matrix(const Camera *const camera, - float projection_matrix[4][4]) { + float *projection_matrix) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - projection_matrix[i][j] = 0; + projection_matrix[i * 4 + j] = 0; } } 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) / - (camera->min_distance - camera->max_distance); - projection_matrix[3][2] = -1; - projection_matrix[2][3] = (2 * camera->max_distance * camera->min_distance) / - (camera->min_distance - camera->max_distance); + projection_matrix[0 * 4 + 0] = f / camera->aspect_ratio; + projection_matrix[1 * 4 + 1] = f; + projection_matrix[2 * 4 + 2] = (camera->max_distance + camera->min_distance) / + (camera->min_distance - camera->max_distance); + projection_matrix[3 * 4 + 2] = -1; + projection_matrix[2 * 4 + 3] = + (2 * camera->max_distance * camera->min_distance) / + (camera->min_distance - camera->max_distance); } \ No newline at end of file diff --git a/src/engine/camera.h b/src/engine/camera.h index 2f39936..8164a61 100644 --- a/src/engine/camera.h +++ b/src/engine/camera.h @@ -13,9 +13,8 @@ typedef struct Camera { const float aspect_ratio; } Camera; -void camera_get_view_matrix(const Camera *const camera, - float view_matrix[4][4]); +void camera_get_view_matrix(const Camera *const camera, float *view_matrix); void camera_get_projection_matrix(const Camera *const camera, - float projection_matrix[4][4]); + float *projection_matrix); #endif \ No newline at end of file diff --git a/src/engine/matrix.c b/src/engine/matrix.c index 2798d5d..9c6e8f7 100644 --- a/src/engine/matrix.c +++ b/src/engine/matrix.c @@ -1,37 +1,35 @@ #include "matrix.h" #include "../utils/math.h" -void matrix_mult_matrix(int size, const float matrix1[size][size], - const float matrix2[size][size], - float result[size][size]) { +void matrix_mult_matrix(int size, const float *matrix1, const float *matrix2, + float *result) { for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { - result[i][j] = 0; + result[i * size + j] = 0; } } for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { for (int k = 0; k < size; k++) { - result[i][j] += matrix1[i][k] * matrix2[k][j]; + result[i * size + j] += matrix1[i * size + k] * matrix2[k * size + j]; } } } } -void matrix_mult_vector(int size, const float matrix[size][size], - const float vector[size], float result[size]) { +void matrix_mult_vector(int size, const float *matrix, const float vector[size], + float result[size]) { for (int i = 0; i < size; i++) result[i] = 0; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { - result[i] += matrix[i][j] * vector[j]; + result[i] += matrix[i * size + j] * vector[j]; } } } -void create_axis_rotate_matrix(int axis, float angle, - float rotate_matrix[3][3]) { +void create_axis_rotate_matrix(int axis, float angle, float *rotate_matrix) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - rotate_matrix[i][j] = 0; + rotate_matrix[i * 3 + j] = 0; } } @@ -42,17 +40,17 @@ void create_axis_rotate_matrix(int axis, float angle, for (int j = 0; j < 3; j++) { if (i == axis || j == axis) { if (i == j) - rotate_matrix[i][j] = 1; + rotate_matrix[i * 3 + j] = 1; else - rotate_matrix[i][j] = 0; + rotate_matrix[i * 3 + j] = 0; } else { if (i == j) { - rotate_matrix[i][j] = cos_angle; + rotate_matrix[i * 3 + j] = cos_angle; } else { if ((i < j && axis == 2) || (i > j && axis != 2)) { - rotate_matrix[i][j] = sin_angle; + rotate_matrix[i * 3 + j] = sin_angle; } else { - rotate_matrix[i][j] = -sin_angle; + rotate_matrix[i * 3 + j] = -sin_angle; } } } @@ -60,15 +58,14 @@ void create_axis_rotate_matrix(int axis, float angle, } } -void create_rotate_matrix(const float rotate_speed[3], - float rotate_matrix[3][3]) { - float x_rotate[3][3]; +void create_rotate_matrix(const float rotate_speed[3], float *rotate_matrix) { + float x_rotate[3 * 3]; create_axis_rotate_matrix(0, rotate_speed[0], x_rotate); - float y_rotate[3][3]; + float y_rotate[3 * 3]; create_axis_rotate_matrix(1, rotate_speed[1], y_rotate); - float z_rotate[3][3]; + float z_rotate[3 * 3]; create_axis_rotate_matrix(2, rotate_speed[2], z_rotate); - float xy_rotate[3][3]; + float xy_rotate[3 * 3]; matrix_mult_matrix(3, x_rotate, y_rotate, xy_rotate); matrix_mult_matrix(3, xy_rotate, z_rotate, rotate_matrix); } diff --git a/src/engine/matrix.h b/src/engine/matrix.h index 360f3d6..bd161eb 100644 --- a/src/engine/matrix.h +++ b/src/engine/matrix.h @@ -1,16 +1,13 @@ #ifndef MATRIX_H #define MATRIX_H -void matrix_mult_matrix(int size, const float matrix1[size][size], - const float matrix2[size][size], - float result[size][size]); -void matrix_mult_vector(int size, const float matrix[size][size], - const float vector[size], float result[size]); +void matrix_mult_matrix(int size, const float *matrix1, const float *matrix2, + float *result); +void matrix_mult_vector(int size, const float *matrix, const float vector[size], + float result[size]); -void create_axis_rotate_matrix(int axis, float angle, - float rotate_matrix[3][3]); -void create_rotate_matrix(const float rotate_speed[3], - float rotate_matrix[3][3]); +void create_axis_rotate_matrix(int axis, float angle, float *rotate_matrix); +void create_rotate_matrix(const float rotate_speed[3], float *rotate_matrix); // void print_matrix(int size, float matrix[size][size]); #endif \ No newline at end of file diff --git a/src/engine/object.c b/src/engine/object.c index f8a066c..261976d 100644 --- a/src/engine/object.c +++ b/src/engine/object.c @@ -3,8 +3,7 @@ #include "../utils/screen.h" #include "vector.h" -void object_transform(Object *const object, int size, - float translate_matrix[size][size]) { +void object_transform(Object *const object, int size, float *translate_matrix) { for (int i = 0; i < object->number_of_points; i++) { point_transform(&(object->points[i]), size, translate_matrix); } @@ -27,13 +26,13 @@ Point object_get_centroid(const Object *const object) { return centroid; } -void object_draw(const Object *object, Screen *screen, - const float render_matrix[4][4]) { +void object_draw(const Object *object, const Screen *const screen, + const float *render_matrix, const Color *const color) { for (int i = 0; i < object->number_of_edges; i++) { 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); + screen->draw_line(&screen_point1, &screen_point2, color); } } \ No newline at end of file diff --git a/src/engine/object.h b/src/engine/object.h index 6f0887c..ba150b6 100644 --- a/src/engine/object.h +++ b/src/engine/object.h @@ -14,10 +14,9 @@ typedef struct Object { const float (*const rotate_speed)[3]; } Object; -void object_transform(Object *const object, int size, - float translate_matrix[size][size]); +void object_transform(Object *const object, int size, float *translate_matrix); Point object_get_centroid(const Object *const object); -void object_draw(const Object *object, Screen *screen, - const float render_matrix[4][4]); +void object_draw(const Object *object, const Screen *const screen, + const float *render_matrix, const Color *const color); #endif \ No newline at end of file diff --git a/src/engine/point.c b/src/engine/point.c index a3292f7..30cf6a4 100644 --- a/src/engine/point.c +++ b/src/engine/point.c @@ -14,8 +14,8 @@ void point_mult_number(Point *const point, const int k) { } void point_transform(Point *const point, int size, - const float translate_matrix[size][size]) { - float new_coordinates[3]; + const float *translate_matrix) { + float new_coordinates[size]; float old_coordinates[] = {point->coordinates[0], point->coordinates[1], point->coordinates[2], 1.0f}; matrix_mult_vector(size, translate_matrix, old_coordinates, new_coordinates); @@ -23,20 +23,20 @@ void point_transform(Point *const point, int size, point->coordinates[i] = new_coordinates[i]; } void point_create_translate_matrix(const Point *const position, - float translate_matrix[4][4], int k) { + float *translate_matrix, int k) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - translate_matrix[i][j] = 0; + translate_matrix[i * 4 + j] = 0; if (i == j) - translate_matrix[i][j] = 1; + translate_matrix[i * 4 + j] = 1; else if (j == 3) - translate_matrix[i][j] = position->coordinates[i] * k; + translate_matrix[i * 4 + j] = position->coordinates[i] * k; } } } -ScreenPoint point_to_screen_point(Point *point, Screen *screen, - const float render_matrix[4][4]) { +ScreenPoint point_to_screen_point(Point *point, const Screen *const screen, + const float *render_matrix) { 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 0660eba..233895a 100644 --- a/src/engine/point.h +++ b/src/engine/point.h @@ -10,10 +10,10 @@ typedef struct 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]); + const float *translate_matrix); void point_create_translate_matrix(const Point *const position, - float translate_matrix[4][4], int k); -ScreenPoint point_to_screen_point(Point *point, Screen *screen, - const float render_matrix[4][4]); + float *translate_matrix, int k); +ScreenPoint point_to_screen_point(Point *point, const Screen *const screen, + const float *render_matrix); #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index e1856c3..1b52c9e 100644 --- a/src/main.c +++ b/src/main.c @@ -9,18 +9,21 @@ #include "objects.h" -float render_matrix[4][4]; +float *render_matrix; void init_engine() { logff(BLUE ITALIC, "Engine init..."); - float view_matrix[4][4]; + render_matrix = (float *)malloc(4 * 4 * sizeof(float)); + + float view_matrix[4 * 4]; camera_get_view_matrix(&camera, view_matrix); logf("View matrix created\n"); - float projection_matrix[4][4]; + float projection_matrix[4 * 4]; camera_get_projection_matrix(&camera, projection_matrix); logf("Projection matrix created\n"); + matrix_mult_matrix(4, projection_matrix, view_matrix, render_matrix); logf("Render matrix created\n"); @@ -29,7 +32,7 @@ void init_engine() { point_mult_number(¢er_of_object, -1); point_add_point(¢er_of_object, objects[i].position); - float translate_matrix[4][4]; + float translate_matrix[4 * 4]; point_create_translate_matrix(¢er_of_object, translate_matrix, 1); object_transform(&(objects[i]), 4, translate_matrix); @@ -42,19 +45,33 @@ void init_engine() { logff(BLUE BOLD UNDERLINE, "Engine init complete!"); } -void render(Screen screen) { +void render(const Screen *const screen, const Color *const color) { for (int i = 0; i < number_of_objects; i++) { - object_draw(&(objects[i]), &screen, render_matrix); + object_draw(&(objects[i]), screen, render_matrix, color); } } -void tic() { +void rotate(const float angles_speed[3]) { for (int i = 0; i < number_of_objects; i++) { - float translate_matrix[4][4]; + 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]; + float rotate_matrix[3 * 3]; + create_rotate_matrix(angles_speed, rotate_matrix); + object_transform(&(objects[i]), 3, rotate_matrix); + + point_create_translate_matrix(objects[i].position, translate_matrix, 1); + object_transform(&(objects[i]), 4, translate_matrix); + } +} +void tic() { + for (int i = 0; i < number_of_objects; i++) { + 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); @@ -63,4 +80,4 @@ void tic() { } } -void destroy() {} \ No newline at end of file +void destroy() { free(render_matrix); } \ No newline at end of file diff --git a/src/objects.h b/src/objects.h index 98eb952..9dd3bad 100644 --- a/src/objects.h +++ b/src/objects.h @@ -21,43 +21,41 @@ 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 = 1; -// Object objects[] = {cube, pyramid, prism}; -Object objects[] = {cube}; +const int number_of_objects = 3; +Object objects[] = {cube, pyramid, prism}; Point camera_position = {.coordinates = {0.0f, 0.0f, 0.0f}}; Point camera_target = {.coordinates = {1.0f, 1.0f, 1.0f}}; diff --git a/src/platforms/micro/lib/I2C/I2C.c b/src/platforms/micro/lib/I2C/I2C.c new file mode 100644 index 0000000..ceb386e --- /dev/null +++ b/src/platforms/micro/lib/I2C/I2C.c @@ -0,0 +1,73 @@ +#include "I2C.h" +#include +#include + +// Тайм-аут для ожидания TWINT (подберите под вашу частоту) +#define I2C_TIMEOUT 30000 + +void i2c_init(void) { + TWSR = 0; // Предделитель = 1 + TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; +} + +static uint8_t i2c_wait_for_completion(void) { + uint16_t timeout = I2C_TIMEOUT; + while (!(TWCR & (1 << TWINT))) { + if (--timeout == 0) + return 1; // Тайм-аут + } + return 0; +} + +uint8_t i2c_start(uint8_t address) { + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); + if (i2c_wait_for_completion()) + return 1; + + uint8_t status = TWSR & 0xF8; + if (status != TW_START && status != TW_REP_START) + return 1; + + TWDR = address; + TWCR = (1 << TWINT) | (1 << TWEN); + if (i2c_wait_for_completion()) + return 1; + + status = TWSR & 0xF8; + if (status == TW_MT_SLA_ACK || status == TW_MR_SLA_ACK) + return 0; + else + return 1; +} + +void i2c_stop(void) { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + // TWSTO автоматически сбрасывается, но не виснем навсегда + uint16_t timeout = I2C_TIMEOUT; + while ((TWCR & (1 << TWSTO)) && --timeout) { + // Ждём завершения STOP + } +} + +uint8_t i2c_write(uint8_t data) { + TWDR = data; + TWCR = (1 << TWINT) | (1 << TWEN); + if (i2c_wait_for_completion()) + return 1; + + return ((TWSR & 0xF8) == TW_MT_DATA_ACK) ? 0 : 1; +} + +uint8_t i2c_read_ack(void) { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); + if (i2c_wait_for_completion()) + return 0; // Возвращаем 0 при ошибке + return TWDR; +} + +uint8_t i2c_read_nack(void) { + TWCR = (1 << TWINT) | (1 << TWEN); + if (i2c_wait_for_completion()) + return 0; + return TWDR; +} \ No newline at end of file diff --git a/src/platforms/micro/lib/I2C/I2C.h b/src/platforms/micro/lib/I2C/I2C.h new file mode 100644 index 0000000..e21724c --- /dev/null +++ b/src/platforms/micro/lib/I2C/I2C.h @@ -0,0 +1,15 @@ +#ifndef I2C_H +#define I2C_H + +#include + +#define TWI_FREQ 400000UL // 400 kHz + +void i2c_init(void); +uint8_t i2c_start(uint8_t address); +void i2c_stop(void); +uint8_t i2c_write(uint8_t data); +uint8_t i2c_read_ack(void); +uint8_t i2c_read_nack(void); + +#endif \ No newline at end of file diff --git a/src/platforms/micro/lib/MPU6050/MPU6050.c b/src/platforms/micro/lib/MPU6050/MPU6050.c new file mode 100644 index 0000000..46ddf71 --- /dev/null +++ b/src/platforms/micro/lib/MPU6050/MPU6050.c @@ -0,0 +1,111 @@ +#include "../I2C/I2C.h" +#include "MPU6050.h" +#include +#include + +void mpu6050_init(void) { + i2c_init(); + + // Отправляем: START + ADDR(W) + REG + DATA + STOP + if (i2c_start(MPU6050_ADDR)) + goto error; + if (i2c_write(MPU6050_REG_PWR_MGMT_1)) + goto error; + if (i2c_write(0x00)) + goto error; // Wake up + i2c_stop(); + return; + + int16_t gx_off, gy_off, gz_off; + mpu6050_calibrate_gyro(&gx_off, &gy_off, &gz_off); + mpu6050_set_gyro_offsets(gx_off, gy_off, gz_off); + +error: + i2c_stop(); // На всякий случай + // Можно добавить обработку ошибки (мигание LED и т.п.) +} + +static void mpu6050_read_burst(uint8_t reg, uint8_t *buf, uint8_t len) { + // Запись адреса регистра БЕЗ STOP + if (i2c_start(MPU6050_ADDR)) + goto error; + if (i2c_write(reg)) + goto error; + + // Repeated START для чтения + if (i2c_start(MPU6050_ADDR | 0x01)) + goto error; + + for (uint8_t i = 0; i < len - 1; i++) { + buf[i] = i2c_read_ack(); + } + buf[len - 1] = i2c_read_nack(); + i2c_stop(); + return; + +error: + i2c_stop(); + // При ошибке заполняем нулями (или обрабатываем иначе) + for (uint8_t i = 0; i < len; i++) + buf[i] = 0; +} + +void mpu6050_read_accel(float *ax, float *ay, float *az) { + uint8_t buf[6]; + mpu6050_read_burst(MPU6050_REG_ACCEL_XOUT_H, buf, 6); + + // Данные в формате Big-Endian, знаковые 16-битные + int16_t x = (buf[0] << 8) | buf[1]; + int16_t y = (buf[2] << 8) | buf[3]; + int16_t z = (buf[4] << 8) | buf[5]; + + // Масштаб: по умолчанию ±2g → 16384 LSB/g + const float accel_scale = 16384.0f; + *ax = (float)x / accel_scale; + *ay = (float)y / accel_scale; + *az = (float)z / accel_scale; +} + +// Глобальные переменные для смещений (лучше сделать static в .c файле) +static int16_t gyro_offset_x = 0; +static int16_t gyro_offset_y = 0; +static int16_t gyro_offset_z = 0; + +void mpu6050_set_gyro_offsets(int16_t x, int16_t y, int16_t z) { + gyro_offset_x = x; + gyro_offset_y = y; + gyro_offset_z = z; +} + +void mpu6050_read_gyro(float *gx, float *gy, float *gz) { + uint8_t buf[6]; + mpu6050_read_burst(MPU6050_REG_GYRO_XOUT_H, buf, 6); + + int16_t raw_x = ((buf[0] << 8) | buf[1]) - gyro_offset_x; + int16_t raw_y = ((buf[2] << 8) | buf[3]) - gyro_offset_y; + int16_t raw_z = ((buf[4] << 8) | buf[5]) - gyro_offset_z; + + const float gyro_scale = 131.0f; + *gx = (float)raw_x / gyro_scale; + *gy = (float)raw_y / gyro_scale; + *gz = (float)raw_z / gyro_scale; +} + +void mpu6050_calibrate_gyro(int16_t *gx_offset, int16_t *gy_offset, + int16_t *gz_offset) { + const int samples = 1000; + int32_t sum_x = 0, sum_y = 0, sum_z = 0; + + for (int i = 0; i < samples; i++) { + uint8_t buf[6]; + mpu6050_read_burst(MPU6050_REG_GYRO_XOUT_H, buf, 6); + sum_x += (buf[0] << 8) | buf[1]; + sum_y += (buf[2] << 8) | buf[3]; + sum_z += (buf[4] << 8) | buf[5]; + _delay_ms(2); // небольшая пауза + } + + *gx_offset = sum_x / samples; + *gy_offset = sum_y / samples; + *gz_offset = sum_z / samples; +} \ No newline at end of file diff --git a/src/platforms/micro/lib/MPU6050/MPU6050.h b/src/platforms/micro/lib/MPU6050/MPU6050.h new file mode 100644 index 0000000..8e79ab5 --- /dev/null +++ b/src/platforms/micro/lib/MPU6050/MPU6050.h @@ -0,0 +1,21 @@ +#ifndef MPU6050_H +#define MPU6050_H + +#include + +// Адрес по умолчанию: AD0 = GND → 0x68 → сдвинутый = 0xD0 +// Если AD0 = VCC → 0x69 → 0xD2 +#define MPU6050_ADDR 0xD0 + +#define MPU6050_REG_PWR_MGMT_1 0x6B +#define MPU6050_REG_ACCEL_XOUT_H 0x3B +#define MPU6050_REG_GYRO_XOUT_H 0x43 + +void mpu6050_init(void); +void mpu6050_read_accel(float *ax, float *ay, float *az); +void mpu6050_read_gyro(float *gx, float *gy, float *gz); +void mpu6050_set_gyro_offsets(int16_t x, int16_t y, int16_t z); +void mpu6050_calibrate_gyro(int16_t *gx_offset, int16_t *gy_offset, + int16_t *gz_offset); + +#endif \ No newline at end of file diff --git a/src/platforms/micro/micro.c b/src/platforms/micro/micro.c index 4fd0e22..4630530 100644 --- a/src/platforms/micro/micro.c +++ b/src/platforms/micro/micro.c @@ -1,26 +1,39 @@ +#include "./lib/MPU6050/MPU6050.h" #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); +void draw_line(const ScreenPoint *sp1, const ScreenPoint *sp2, + const Color *const color) { st7789_draw_line(sp1->coordinates[0], sp1->coordinates[1], - sp2->coordinates[0], sp2->coordinates[1], COLOR_WHITE); + sp2->coordinates[0], sp2->coordinates[1], + RGB565(color->red, color->green, color->blue)); }; -Screen screen = { +const Screen screen = { .width = DISPLAY_WIDTH, .height = DISPLAY_HEIGHT, .draw_line = &draw_line}; +const Color white = {255, 255, 255}; +const Color black = {0, 0, 0}; + +float gx, gy, gz; + int main(void) { + st7789_init(); + mpu6050_init(); + init_engine(); - st7789_init(); + st7789_fill_screen(RGB565(0, 0, 0)); while (1) { - st7789_fill_screen(COLOR_BLACK); - render(screen); + render(&screen, &black); - _delay_ms(1000 / FPS); + mpu6050_read_gyro(&gx, &gy, &gz); + float angles_speed[3] = {gx / 255.0f, gy / 255.0f, gz / 255.0f}; + rotate(angles_speed); + + render(&screen, &white); } return 0; diff --git a/src/platforms/micro/micro.h b/src/platforms/micro/micro.h index ebe6ff5..52c2cb6 100644 --- a/src/platforms/micro/micro.h +++ b/src/platforms/micro/micro.h @@ -2,5 +2,6 @@ #define MICRO_H #include "./lib/ST7789/ST7789.h" +#include #endif \ No newline at end of file diff --git a/src/platforms/platform.h b/src/platforms/platform.h index a36e194..937e74e 100644 --- a/src/platforms/platform.h +++ b/src/platforms/platform.h @@ -17,7 +17,7 @@ #ifdef MICRO -#define FPS 5 +#define FPS 25 #include "micro/micro.h" #define DISPLAY_WIDTH 160 @@ -28,8 +28,9 @@ #endif // MICRO void init_engine(); -void render(Screen screen); +void render(const Screen *const screen, const Color *const color); void tic(); +void rotate(const float angles_speed[3]); void destroy(); #endif diff --git a/src/platforms/win/win.c b/src/platforms/win/win.c index 16c119a..d5e60fd 100644 --- a/src/platforms/win/win.c +++ b/src/platforms/win/win.c @@ -1,7 +1,9 @@ -#include "platform.h" +#include "../platform.h" #include "win.h" +const Color white = {255, 255, 255}; + LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { @@ -19,20 +21,20 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, float width = rect.right - rect.left; float height = rect.bottom - rect.top; - HPEN hPen = CreatePen(PS_SOLID, 1, COLOR); - HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); - - void draw_line(const ScreenPoint *sp1, const ScreenPoint *sp2) { + void draw_line(const ScreenPoint *sp1, const ScreenPoint *sp2, + const Color *const color) { + HPEN hPen = + CreatePen(PS_SOLID, 1, RGB(color->red, color->green, color->blue)); + HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); MoveToEx(hdc, sp1->coordinates[0], sp1->coordinates[1], NULL); LineTo(hdc, sp2->coordinates[0], sp2->coordinates[1]); + SelectObject(hdc, hOldPen); + DeleteObject(hPen); }; Screen screen = {.width = width, .height = height, .draw_line = &draw_line}; - render(screen); - - SelectObject(hdc, hOldPen); - DeleteObject(hPen); + render(&screen, &white); EndPaint(hwnd, &ps); return 0; @@ -44,7 +46,6 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, case WM_TIMER: tic(); - InvalidateRect(hwnd, NULL, TRUE); return 0; diff --git a/src/utils/cos_table.h b/src/utils/cos_table.h new file mode 100644 index 0000000..e848927 --- /dev/null +++ b/src/utils/cos_table.h @@ -0,0 +1,138 @@ +#ifndef COS_TABLE_H +#define COS_TABLE_H + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846f +#endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923f +#endif + +#define COS_TABLE_SIZE 256 + +static float cos_table_angles[COS_TABLE_SIZE] = { + 0.0000000000f, 0.0245436926f, 0.0490873852f, 0.0736310778f, 0.0981747704f, + 0.1227184630f, 0.1472621556f, 0.1718058482f, 0.1963495408f, 0.2208932335f, + 0.2454369261f, 0.2699806187f, 0.2945243113f, 0.3190680039f, 0.3436116965f, + 0.3681553891f, 0.3926990817f, 0.4172427743f, 0.4417864669f, 0.4663301595f, + 0.4908738521f, 0.5154175447f, 0.5399612373f, 0.5645049299f, 0.5890486225f, + 0.6135923152f, 0.6381360078f, 0.6626797004f, 0.6872233930f, 0.7117670856f, + 0.7363107782f, 0.7608544708f, 0.7853981634f, 0.8099418560f, 0.8344855486f, + 0.8590292412f, 0.8835729338f, 0.9081166264f, 0.9326603190f, 0.9572040116f, + 0.9817477042f, 1.0062913969f, 1.0308350895f, 1.0553787821f, 1.0799224747f, + 1.1044661673f, 1.1290098599f, 1.1535535525f, 1.1780972451f, 1.2026409377f, + 1.2271846303f, 1.2517283229f, 1.2762720155f, 1.3008157081f, 1.3253594007f, + 1.3499030933f, 1.3744467859f, 1.3989904786f, 1.4235341712f, 1.4480778638f, + 1.4726215564f, 1.4971652490f, 1.5217089416f, 1.5462526342f, 1.5707963268f, + 1.5953400194f, 1.6198837120f, 1.6444274046f, 1.6689710972f, 1.6935147898f, + 1.7180584824f, 1.7426021750f, 1.7671458676f, 1.7916895603f, 1.8162332529f, + 1.8407769455f, 1.8653206381f, 1.8898643307f, 1.9144080233f, 1.9389517159f, + 1.9634954085f, 1.9880391011f, 2.0125827937f, 2.0371264863f, 2.0616701789f, + 2.0862138715f, 2.1107575641f, 2.1353012567f, 2.1598449493f, 2.1843886419f, + 2.2089323346f, 2.2334760272f, 2.2580197198f, 2.2825634124f, 2.3071071050f, + 2.3316507976f, 2.3561944902f, 2.3807381828f, 2.4052818754f, 2.4298255680f, + 2.4543692606f, 2.4789129532f, 2.5034566458f, 2.5280003384f, 2.5525440310f, + 2.5770877236f, 2.6016314163f, 2.6261751089f, 2.6507188015f, 2.6752624941f, + 2.6998061867f, 2.7243498793f, 2.7488935719f, 2.7734372645f, 2.7979809571f, + 2.8225246497f, 2.8470683423f, 2.8716120349f, 2.8961557275f, 2.9206994201f, + 2.9452431127f, 2.9697868053f, 2.9943304980f, 3.0188741906f, 3.0434178832f, + 3.0679615758f, 3.0925052684f, 3.1170489610f, 3.1415926536f, 3.1661363462f, + 3.1906800388f, 3.2152237314f, 3.2397674240f, 3.2643111166f, 3.2888548092f, + 3.3133985018f, 3.3379421944f, 3.3624858870f, 3.3870295797f, 3.4115732723f, + 3.4361169649f, 3.4606606575f, 3.4852043501f, 3.5097480427f, 3.5342917353f, + 3.5588354279f, 3.5833791205f, 3.6079228131f, 3.6324665057f, 3.6570101983f, + 3.6815538909f, 3.7060975835f, 3.7306412761f, 3.7551849687f, 3.7797286614f, + 3.8042723540f, 3.8288160466f, 3.8533597392f, 3.8779034318f, 3.9024471244f, + 3.9269908170f, 3.9515345096f, 3.9760782022f, 4.0006218948f, 4.0251655874f, + 4.0497092800f, 4.0742529726f, 4.0987966652f, 4.1233403578f, 4.1478840504f, + 4.1724277430f, 4.1969714357f, 4.2215151283f, 4.2460588209f, 4.2706025135f, + 4.2951462061f, 4.3196898987f, 4.3442335913f, 4.3687772839f, 4.3933209765f, + 4.4178646691f, 4.4424083617f, 4.4669520543f, 4.4914957469f, 4.5160394395f, + 4.5405831321f, 4.5651268247f, 4.5896705174f, 4.6142142100f, 4.6387579026f, + 4.6633015952f, 4.6878452878f, 4.7123889804f, 4.7369326730f, 4.7614763656f, + 4.7860200582f, 4.8105637508f, 4.8351074434f, 4.8596511360f, 4.8841948286f, + 4.9087385212f, 4.9332822138f, 4.9578259064f, 4.9823695991f, 5.0069132917f, + 5.0314569843f, 5.0560006769f, 5.0805443695f, 5.1050880621f, 5.1296317547f, + 5.1541754473f, 5.1787191399f, 5.2032628325f, 5.2278065251f, 5.2523502177f, + 5.2768939103f, 5.3014376029f, 5.3259812955f, 5.3505249881f, 5.3750686808f, + 5.3996123734f, 5.4241560660f, 5.4486997586f, 5.4732434512f, 5.4977871438f, + 5.5223308364f, 5.5468745290f, 5.5714182216f, 5.5959619142f, 5.6205056068f, + 5.6450492994f, 5.6695929920f, 5.6941366846f, 5.7186803772f, 5.7432240698f, + 5.7677677625f, 5.7923114551f, 5.8168551477f, 5.8413988403f, 5.8659425329f, + 5.8904862255f, 5.9150299181f, 5.9395736107f, 5.9641173033f, 5.9886609959f, + 6.0132046885f, 6.0377483811f, 6.0622920737f, 6.0868357663f, 6.1113794589f, + 6.1359231515f, 6.1604668441f, 6.1850105368f, 6.2095542294f, 6.2340979220f, + 6.2586416146f, +}; + +static float cos_table_values[COS_TABLE_SIZE] = { + 1.0000000000f, 0.9996988187f, 0.9987954562f, 0.9972904567f, + 0.9951847267f, 0.9924795346f, 0.9891765100f, 0.9852776424f, + 0.9807852804f, 0.9757021300f, 0.9700312532f, 0.9637760658f, + 0.9569403357f, 0.9495281806f, 0.9415440652f, 0.9329927988f, + 0.9238795325f, 0.9142097557f, 0.9039892931f, 0.8932243012f, + 0.8819212643f, 0.8700869911f, 0.8577286100f, 0.8448535652f, + 0.8314696123f, 0.8175848132f, 0.8032075315f, 0.7883464276f, + 0.7730104534f, 0.7572088465f, 0.7409511254f, 0.7242470830f, + 0.7071067812f, 0.6895405447f, 0.6715589548f, 0.6531728430f, + 0.6343932842f, 0.6152315906f, 0.5956993045f, 0.5758081914f, + 0.5555702330f, 0.5349976199f, 0.5141027442f, 0.4928981922f, + 0.4713967368f, 0.4496113297f, 0.4275550934f, 0.4052413140f, + 0.3826834324f, 0.3598950365f, 0.3368898534f, 0.3136817404f, + 0.2902846773f, 0.2667127575f, 0.2429801799f, 0.2191012402f, + 0.1950903220f, 0.1709618888f, 0.1467304745f, 0.1224106752f, + 0.0980171403f, 0.0735645636f, 0.0490676743f, 0.0245412285f, + 0.0000000000f, -0.0245412285f, -0.0490676743f, -0.0735645636f, + -0.0980171403f, -0.1224106752f, -0.1467304745f, -0.1709618888f, + -0.1950903220f, -0.2191012402f, -0.2429801799f, -0.2667127575f, + -0.2902846773f, -0.3136817404f, -0.3368898534f, -0.3598950365f, + -0.3826834324f, -0.4052413140f, -0.4275550934f, -0.4496113297f, + -0.4713967368f, -0.4928981922f, -0.5141027442f, -0.5349976199f, + -0.5555702330f, -0.5758081914f, -0.5956993045f, -0.6152315906f, + -0.6343932842f, -0.6531728430f, -0.6715589548f, -0.6895405447f, + -0.7071067812f, -0.7242470830f, -0.7409511254f, -0.7572088465f, + -0.7730104534f, -0.7883464276f, -0.8032075315f, -0.8175848132f, + -0.8314696123f, -0.8448535652f, -0.8577286100f, -0.8700869911f, + -0.8819212643f, -0.8932243012f, -0.9039892931f, -0.9142097557f, + -0.9238795325f, -0.9329927988f, -0.9415440652f, -0.9495281806f, + -0.9569403357f, -0.9637760658f, -0.9700312532f, -0.9757021300f, + -0.9807852804f, -0.9852776424f, -0.9891765100f, -0.9924795346f, + -0.9951847267f, -0.9972904567f, -0.9987954562f, -0.9996988187f, + -1.0000000000f, -0.9996988187f, -0.9987954562f, -0.9972904567f, + -0.9951847267f, -0.9924795346f, -0.9891765100f, -0.9852776424f, + -0.9807852804f, -0.9757021300f, -0.9700312532f, -0.9637760658f, + -0.9569403357f, -0.9495281806f, -0.9415440652f, -0.9329927988f, + -0.9238795325f, -0.9142097557f, -0.9039892931f, -0.8932243012f, + -0.8819212643f, -0.8700869911f, -0.8577286100f, -0.8448535652f, + -0.8314696123f, -0.8175848132f, -0.8032075315f, -0.7883464276f, + -0.7730104534f, -0.7572088465f, -0.7409511254f, -0.7242470830f, + -0.7071067812f, -0.6895405447f, -0.6715589548f, -0.6531728430f, + -0.6343932842f, -0.6152315906f, -0.5956993045f, -0.5758081914f, + -0.5555702330f, -0.5349976199f, -0.5141027442f, -0.4928981922f, + -0.4713967368f, -0.4496113297f, -0.4275550934f, -0.4052413140f, + -0.3826834324f, -0.3598950365f, -0.3368898534f, -0.3136817404f, + -0.2902846773f, -0.2667127575f, -0.2429801799f, -0.2191012402f, + -0.1950903220f, -0.1709618888f, -0.1467304745f, -0.1224106752f, + -0.0980171403f, -0.0735645636f, -0.0490676743f, -0.0245412285f, + -0.0000000000f, 0.0245412285f, 0.0490676743f, 0.0735645636f, + 0.0980171403f, 0.1224106752f, 0.1467304745f, 0.1709618888f, + 0.1950903220f, 0.2191012402f, 0.2429801799f, 0.2667127575f, + 0.2902846773f, 0.3136817404f, 0.3368898534f, 0.3598950365f, + 0.3826834324f, 0.4052413140f, 0.4275550934f, 0.4496113297f, + 0.4713967368f, 0.4928981922f, 0.5141027442f, 0.5349976199f, + 0.5555702330f, 0.5758081914f, 0.5956993045f, 0.6152315906f, + 0.6343932842f, 0.6531728430f, 0.6715589548f, 0.6895405447f, + 0.7071067812f, 0.7242470830f, 0.7409511254f, 0.7572088465f, + 0.7730104534f, 0.7883464276f, 0.8032075315f, 0.8175848132f, + 0.8314696123f, 0.8448535652f, 0.8577286100f, 0.8700869911f, + 0.8819212643f, 0.8932243012f, 0.9039892931f, 0.9142097557f, + 0.9238795325f, 0.9329927988f, 0.9415440652f, 0.9495281806f, + 0.9569403357f, 0.9637760658f, 0.9700312532f, 0.9757021300f, + 0.9807852804f, 0.9852776424f, 0.9891765100f, 0.9924795346f, + 0.9951847267f, 0.9972904567f, 0.9987954562f, 0.9996988187f, +}; + +#endif diff --git a/src/utils/create_trig_table.py b/src/utils/create_trig_table.py new file mode 100644 index 0000000..1c2032f --- /dev/null +++ b/src/utils/create_trig_table.py @@ -0,0 +1,53 @@ +import math +import json + +def generate_cos_table(size=360, output_file="cos_table.h"): + angles = [2 * math.pi * i / size for i in range(size)] + cos_values = [math.cos(angle) for angle in angles] + + with open(output_file, 'w') as f: + f.write("#ifndef COS_TABLE_H\n") + f.write("#define COS_TABLE_H\n\n") + + f.write("#include \n\n") + + f.write("#ifndef M_PI\n") + f.write("#define M_PI 3.14159265358979323846f\n") + f.write("#endif\n\n") + + f.write("#ifndef M_PI_2\n") + f.write("#define M_PI_2 1.57079632679489661923f\n") + f.write("#endif\n\n") + + f.write("#define COS_TABLE_SIZE {}\n\n".format(size)) + + f.write("static float cos_table_angles[COS_TABLE_SIZE] = {\n") + for i in range(0, size, 8): + line_values = [] + for j in range(i, min(i+8, size)): + line_values.append(f"{angles[j]:.10f}f") + f.write(" " + ", ".join(line_values) + ",\n") + f.write("};\n\n") + + f.write("static float cos_table_values[COS_TABLE_SIZE] = {\n") + for i in range(0, size, 8): + line_values = [] + for j in range(i, min(i+8, size)): + line_values.append(f"{cos_values[j]:.10f}f") + f.write(" " + ", ".join(line_values) + ",\n") + f.write("};\n\n") + + f.write("#endif\n") + + print(f"Таблица косинусов размером {size} точек сохранена в {output_file}") + + return { + 'size': size, + 'angles': angles, + 'cos': cos_values + } + +if __name__ == "__main__": + n = int(input("Размер таблицы:")) + print("Генерация таблиц косинусов...") + generate_cos_table(n, "cos_table.h") \ No newline at end of file diff --git a/src/utils/math.c b/src/utils/math.c index dc21d12..b0d08a9 100644 --- a/src/utils/math.c +++ b/src/utils/math.c @@ -2,7 +2,6 @@ #include #include -#define FMATH #ifdef FMATH float e_rsqrt(float x) { @@ -17,9 +16,43 @@ float e_rsqrt(float x) { 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); } +#include "cos_table.h" +// Вспомогательная функция для нормализации угла в [0, 2π) +static inline float normalize_angle(float angle) { + // Используем fmodf для быстрой нормализации + angle = fmodf(angle, 2.0f * M_PI); + if (angle < 0.0f) + angle += 2.0f * M_PI; + return angle; +} + +float e_cos(float angle) { + angle = normalize_angle(angle); + float step = (2.0f * M_PI) / (COS_TABLE_SIZE - 1); // если таблица включает 2π + int index = (int)(angle / step); + if (index >= COS_TABLE_SIZE - 1) + index = COS_TABLE_SIZE - 2; + if (fabsf(angle - cos_table_angles[index]) < 1e-6f) + return cos_table_values[index]; + float x0 = cos_table_angles[index]; + float x1 = cos_table_angles[index + 1]; + float y0 = cos_table_values[index]; + float y1 = cos_table_values[index + 1]; + if (x1 == x0) + return y0; + float t = (angle - x0) / (x1 - x0); + return y0 + t * (y1 - y0); +} + +float e_sin(float angle) { return e_cos(angle - M_PI_2); } + +float e_tan(float angle) { + float c = e_cos(angle); + if (fabsf(c) < 1e-6f) + return (e_sin(angle) > 0) ? HUGE_VALF : -HUGE_VALF; + + return e_sin(angle) / c; +} #else diff --git a/src/utils/screen.h b/src/utils/screen.h index 5feb1bf..2a5dc93 100644 --- a/src/utils/screen.h +++ b/src/utils/screen.h @@ -1,16 +1,21 @@ #ifndef UTILS_H #define UTILS_H -struct ScreenPoint { +typedef struct ScreenPoint { int coordinates[2]; -}; -typedef struct ScreenPoint ScreenPoint; +} ScreenPoint; -struct Screen { +typedef struct Color { + char red; + char green; + char blue; +} Color; + +typedef struct Screen { int width; int height; - void (*draw_line)(const ScreenPoint *sp1, const ScreenPoint *sp2); -}; -typedef struct Screen Screen; + void (*draw_line)(const ScreenPoint *sp1, const ScreenPoint *sp2, + const Color *const color); +} Screen; #endif \ No newline at end of file