From 7e455c591a4bb12172d58af1b2a2074735cf4a54 Mon Sep 17 00:00:00 2001 From: Passthem <514827965@qq.com> Date: Fri, 11 Apr 2025 15:40:18 +0800 Subject: [PATCH] init --- .gitignore | 6 ++++ .vscode/settings.json | 13 +++++++ Makefile | 24 +++++++++++++ color_utils.c | 84 +++++++++++++++++++++++++++++++++++++++++++ color_utils.h | 22 ++++++++++++ main.c | 68 +++++++++++++++++++++++++++++++++++ shader.c | 5 +++ shader.h | 8 +++++ spi_utils.c | 43 ++++++++++++++++++++++ spi_utils.h | 23 ++++++++++++ 10 files changed, 296 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Makefile create mode 100644 color_utils.c create mode 100644 color_utils.h create mode 100644 main.c create mode 100644 shader.c create mode 100644 shader.h create mode 100644 spi_utils.c create mode 100644 spi_utils.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9d18ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/dist/ + +*.o +*.out +*.swp +*.swo \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9263958 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "files.associations": { + "*.py": "python", + "types.h": "c", + "spidev.h": "c", + "fcntl.h": "c", + "stdlib.h": "c", + "math.h": "c", + "spi_utils.h": "c", + "cstdint": "c", + "color_utils.h": "c" + } +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..04d7e23 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +CC = gcc +CFLAGS = -Wall -Wextra -O2 +LDFLAGS = -lm + +SRCS = main.c spi_utils.c color_utils.c shader.c +OBJS = $(SRCS:%.c=dist/%.o) +TARGET = dist/main + +MKDIR_P = mkdir -p + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(MKDIR_P) dist + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +dist/%.o: %.c + $(MKDIR_P) dist + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -rf dist + +.PHONY: all clean \ No newline at end of file diff --git a/color_utils.c b/color_utils.c new file mode 100644 index 0000000..f161528 --- /dev/null +++ b/color_utils.c @@ -0,0 +1,84 @@ +#include "color_utils.h" +#include + +Color hex_to_color(int hex) { + Color color; + + color.r = (hex >> 16) % 256; + color.g = (hex >> 8) % 256; + color.b = hex % 256; + + return color; +} + +Color hsv_to_color(double h, double s, double v) { + h = fmod(h, 360); + if (s > 1) + s = fmod(s, 1); + if (v > 1) + v = fmod(v, 1); + + double c = v * s; + double x = c * (1 - fabs(fmod(h / 60, 2) - 1)); + double m = v - c; + + double r0, g0, b0; + + if (h >= 0 && h < 60) { + r0 = c; + g0 = x; + b0 = 0; + } else if (h >= 60 && h < 120) { + r0 = x; + g0 = c; + b0 = 0; + } else if (h >= 120 && h < 180) { + r0 = 0; + g0 = c; + b0 = x; + } else if (h >= 180 && h < 240) { + r0 = 0; + g0 = x; + b0 = c; + } else if (h >= 240 && h < 300) { + r0 = x; + g0 = 0; + b0 = c; + } else { + r0 = c; + g0 = 0; + b0 = x; + } + + Color color; + + color.r = (r0 + m) * 255; + color.g = (g0 + m) * 255; + color.b = (b0 + m) * 255; + + return color; +} + +void set_color(uint8_t* buffer, const Color color) { + for (int i = 7; i >= 0; i--) + *buffer++ = (color.g & (1 << i)) ? 0b11111000 : 0b10000000; + + for (int i = 7; i >= 0; i--) + *buffer++ = (color.r & (1 << i)) ? 0b11111000 : 0b10000000; + + for (int i = 7; i >= 0; i--) + *buffer++ = (color.b & (1 << i)) ? 0b11111000 : 0b10000000; +} + +int construct_buffer(uint8_t* buffer, + const Color* colors, + const int num_leds, + const int color_bytes, + const int res_bytes) { + const int data_size = num_leds * color_bytes + res_bytes; + memset(buffer, 0, data_size); + for (int i = 0; i < num_leds; i++) { + set_color(buffer + i * color_bytes, colors[i]); + } + return data_size; +} \ No newline at end of file diff --git a/color_utils.h b/color_utils.h new file mode 100644 index 0000000..ff92db3 --- /dev/null +++ b/color_utils.h @@ -0,0 +1,22 @@ +#ifndef COLOR_UTILS_H +#define COLOR_UTILS_H + +#include +#include + +typedef struct Color { + uint8_t g; + uint8_t r; + uint8_t b; +} Color; + +Color hex_to_color(int hex); +Color hsv_to_color(double h, double s, double v); +void set_color(uint8_t* buffer, const Color color); +int construct_buffer(uint8_t* buffer, + const Color* colors, + const int num_leds, + const int color_bytes, + const int res_bytes); + +#endif \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..4fd5aba --- /dev/null +++ b/main.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include "spi_utils.h" +#include "color_utils.h" +#include "shader.h" + +#define RES_BYTES 40 +#define COLOR_BYTES 24 + +volatile sig_atomic_t stop = 0; + +void handle_sigint(int sig) { + stop = 1; +} + +int main() { + signal(SIGINT, handle_sigint); + + const char* device = "/dev/spidev1.0"; + const uint8_t spi_mode = SPI_MODE_0; + const uint8_t spi_bits = 8; + const uint32_t spi_speed = 6400000; + + int fd = init_device(device, spi_mode, spi_bits, spi_speed); + if (fd < 0) + return -1; + + const int num_leds = 60; + const int data_size = COLOR_BYTES * num_leds + RES_BYTES; + + uint8_t* buffer = malloc(data_size); + Color* colors = malloc(sizeof(Color) * num_leds); + + struct timeval start_time; + gettimeofday(&start_time, NULL); + + while (!stop) { + struct timeval current_time; + gettimeofday(¤t_time, NULL); + + double time_elapsed = + (current_time.tv_sec - start_time.tv_sec) + + (current_time.tv_usec - start_time.tv_usec) / 1000000.0; + + for (int i = 0; i < num_leds; i++) { + colors[i] = shader(i, time_elapsed); + } + + construct_buffer(buffer, colors, num_leds, COLOR_BYTES, RES_BYTES); + send_buffer(fd, buffer, data_size, spi_speed, spi_bits); + } + + for (int i = 0; i < num_leds; i++) { + colors[i] = hex_to_color(0x000000); + } + + construct_buffer(buffer, colors, num_leds, COLOR_BYTES, RES_BYTES); + send_buffer(fd, buffer, data_size, spi_speed, spi_bits); + + free(buffer); + free(colors); + close(fd); + + return 0; +} \ No newline at end of file diff --git a/shader.c b/shader.c new file mode 100644 index 0000000..501f180 --- /dev/null +++ b/shader.c @@ -0,0 +1,5 @@ +#include "shader.h" + +Color shader(int index, double time) { + return hsv_to_color(time * 120 + index * 6, 1, 1); +} \ No newline at end of file diff --git a/shader.h b/shader.h new file mode 100644 index 0000000..35ab603 --- /dev/null +++ b/shader.h @@ -0,0 +1,8 @@ +#ifndef SHADER_H +#define SHADER_H + +#include "color_utils.h" + +Color shader(int index, double time); + +#endif \ No newline at end of file diff --git a/spi_utils.c b/spi_utils.c new file mode 100644 index 0000000..d0539c6 --- /dev/null +++ b/spi_utils.c @@ -0,0 +1,43 @@ +#include "spi_utils.h" + +int init_device(const char* device, + uint8_t spi_mode, + uint8_t spi_bits, + uint32_t spi_speed) { + int fd; + + if ((fd = open(device, O_RDWR)) < 0) { + perror("SPI 设备打开失败"); + close(fd); + return -1; + } + + ioctl(fd, SPI_IOC_WR_MODE, &spi_mode); + ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits); + ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed); + + return fd; +} + +int send_buffer(int fd, + uint8_t* buffer, + const int data_size, + uint32_t spi_speed, + uint8_t spi_bits) { + int ret; + + struct spi_ioc_transfer tr = { + .tx_buf = (unsigned long)buffer, + .len = data_size, + .speed_hz = spi_speed, + .bits_per_word = spi_bits, + }; + + ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); + + if (ret < 0) { + perror("SPI 信息发送失败"); + } + + return ret; +} \ No newline at end of file diff --git a/spi_utils.h b/spi_utils.h new file mode 100644 index 0000000..e6ecc2a --- /dev/null +++ b/spi_utils.h @@ -0,0 +1,23 @@ +#ifndef SPI_UTILS_H +#define SPI_UTILS_H + +#include +#include +#include +#include +#include + +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; + +int init_device(const char* device, + uint8_t spi_mode, + uint8_t spi_bits, + uint32_t spi_speed); +int send_buffer(int fd, + uint8_t* buffer, + const int data_size, + uint32_t spi_speed, + uint8_t spi_bits); + +#endif \ No newline at end of file