Automated update
This commit is contained in:
@@ -107,13 +107,17 @@ void update_time(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
|||||||
time(&rawtime);
|
time(&rawtime);
|
||||||
timeinfo = localtime(&rawtime);
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
// Correcting hour and minute hand angles
|
// Calculate the angle for the hour hand
|
||||||
float hour_angle = ((timeinfo->tm_hour % 12) * 30 + timeinfo->tm_min * 0.5) * (M_PI / 180.0) - M_PI / 2;
|
float hour_angle_degrees = (30 * timeinfo->tm_hour) + (timeinfo->tm_min * 0.5);
|
||||||
float minute_angle = (timeinfo->tm_min * 6 + timeinfo->tm_sec * 0.1) * (M_PI / 180.0) - M_PI / 2;
|
float hour_angle = - hour_angle_degrees * M_PI / 180.0 + M_PI / 2; // Convert to radians and adjust to 12 o'clock start
|
||||||
|
|
||||||
// Draw both hands in black color
|
// Calculate the angle for the minute hand
|
||||||
draw_hand(framebuffer, vinfo, hour_angle, HOUR_HAND_LENGTH, 0x000000); // Hour hand in black
|
float minute_angle_degrees = 6 * timeinfo->tm_min;
|
||||||
draw_hand(framebuffer, vinfo, minute_angle, MINUTE_HAND_LENGTH, 0x000000); // Minute hand in black
|
float minute_angle = - minute_angle_degrees * M_PI / 180.0 + M_PI / 2; // Convert to radians and adjust to 12 o'clock start
|
||||||
|
|
||||||
|
// Draw both hands in white (0xFFFFFF)
|
||||||
|
draw_hand(framebuffer, vinfo, hour_angle, HOUR_HAND_LENGTH, 0xFFFFFF); // Hour hand is shorter
|
||||||
|
draw_hand(framebuffer, vinfo, minute_angle, MINUTE_HAND_LENGTH, 0xFFFFFF); // Minute hand is longer
|
||||||
|
|
||||||
// Display the date
|
// Display the date
|
||||||
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo);
|
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo);
|
||||||
@@ -124,7 +128,6 @@ void update_time(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
|||||||
draw_text(framebuffer, vinfo, time_buffer, CENTER_X - 80, CENTER_Y + 350, 3, 0xFFFFFF); // Moved lower and increased size
|
draw_text(framebuffer, vinfo, time_buffer, CENTER_X - 80, CENTER_Y + 350, 3, 0xFFFFFF); // Moved lower and increased size
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main function
|
|
||||||
int main() {
|
int main() {
|
||||||
// Open the framebuffer device
|
// Open the framebuffer device
|
||||||
int fbfd = open("/dev/fb0", O_RDWR);
|
int fbfd = open("/dev/fb0", O_RDWR);
|
||||||
|
|||||||
3
display/README.md
Normal file
3
display/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# clock Project
|
||||||
|
|
||||||
|
This is a C project generated with the setup tool.
|
||||||
24
display/build/Makefile
Normal file
24
display/build/Makefile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# build/Makefile
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -I../include
|
||||||
|
SRCDIR = ../src
|
||||||
|
OBJDIR = ../obj
|
||||||
|
BINDIR = ../build
|
||||||
|
TARGET = clock
|
||||||
|
|
||||||
|
# Gather all source files in src directory
|
||||||
|
SOURCES = $(wildcard $(SRCDIR)/*.c)
|
||||||
|
OBJECTS = $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJECTS)
|
||||||
|
$(CC) $(CFLAGS) -o $(BINDIR)/$(TARGET) $(OBJECTS) -lm
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJDIR)/*.o $(BINDIR)/$(TARGET)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
BIN
display/build/clock
Executable file
BIN
display/build/clock
Executable file
Binary file not shown.
43
display/include/clock.h
Normal file
43
display/include/clock.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// include/clock.h
|
||||||
|
#ifndef CLOCK_H
|
||||||
|
#define CLOCK_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 800
|
||||||
|
#define SCREEN_HEIGHT 600
|
||||||
|
#define CENTER_X (SCREEN_WIDTH / 2)
|
||||||
|
#define CENTER_Y (SCREEN_HEIGHT / 2)
|
||||||
|
#define RADIUS 200
|
||||||
|
#define HOUR_HAND_LENGTH 100
|
||||||
|
#define MINUTE_HAND_LENGTH 150
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
} Point;
|
||||||
|
|
||||||
|
void draw_circle(int *framebuffer, struct fb_var_screeninfo vinfo);
|
||||||
|
void draw_hand(int *framebuffer, struct fb_var_screeninfo vinfo, float angle, int length, int color);
|
||||||
|
void draw_clock_face(int *framebuffer, struct fb_var_screeninfo vinfo);
|
||||||
|
void update_time(int *framebuffer, struct fb_var_screeninfo vinfo);
|
||||||
|
void draw_text(int *framebuffer, struct fb_var_screeninfo vinfo, const char *text, int x, int y, int size, int color);
|
||||||
|
void update_system_info(int *framebuffer, struct fb_var_screeninfo vinfo);
|
||||||
|
int get_cpu_usage();
|
||||||
|
int get_ram_usage();
|
||||||
|
int get_disk_usage();
|
||||||
|
int get_battery_percentage();
|
||||||
|
int get_cpu_temperature();
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
display/obj/clock.o
Normal file
BIN
display/obj/clock.o
Normal file
Binary file not shown.
270
display/src/clock.c
Normal file
270
display/src/clock.c
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
#include "../include/clock.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/statvfs.h> // Include this for statvfs
|
||||||
|
|
||||||
|
// Set a pixel at (x, y) with color in the framebuffer
|
||||||
|
void set_pixel(int *framebuffer, struct fb_var_screeninfo vinfo, int x, int y, int color) {
|
||||||
|
if (x >= 0 && x < vinfo.xres_virtual && y >= 0 && y < vinfo.yres_virtual) {
|
||||||
|
framebuffer[y * vinfo.xres_virtual + x] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bresenham's line algorithm for drawing lines
|
||||||
|
void draw_line(int *framebuffer, struct fb_var_screeninfo vinfo, int x0, int y0, int x1, int y1, int color) {
|
||||||
|
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||||
|
int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||||
|
int err = dx + dy, e2;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
set_pixel(framebuffer, vinfo, x0, y0, color);
|
||||||
|
if (x0 == x1 && y0 == y1) break;
|
||||||
|
e2 = 2 * err;
|
||||||
|
if (e2 >= dy) { err += dy; x0 += sx; }
|
||||||
|
if (e2 <= dx) { err += dx; y0 += sy; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a simple filled rectangle to represent text characters
|
||||||
|
void draw_char(int *framebuffer, struct fb_var_screeninfo vinfo, char c, int x, int y, int size, int color) {
|
||||||
|
static const char font[10][5][3] = {
|
||||||
|
{ "111", "101", "101", "101", "111" }, // '0'
|
||||||
|
{ "110", "010", "010", "010", "111" }, // '1'
|
||||||
|
{ "111", "001", "111", "100", "111" }, // '2'
|
||||||
|
{ "111", "001", "111", "001", "111" }, // '3'
|
||||||
|
{ "101", "101", "111", "001", "001" }, // '4'
|
||||||
|
{ "111", "100", "111", "001", "111" }, // '5'
|
||||||
|
{ "111", "100", "111", "101", "111" }, // '6'
|
||||||
|
{ "111", "001", "001", "001", "001" }, // '7'
|
||||||
|
{ "111", "101", "111", "101", "111" }, // '8'
|
||||||
|
{ "111", "101", "111", "001", "111" } // '9'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
int index = c - '0';
|
||||||
|
for (int row = 0; row < 5; ++row) {
|
||||||
|
for (int col = 0; col < 3; ++col) {
|
||||||
|
if (font[index][row][col] == '1') {
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
for (int j = 0; j < size; ++j) {
|
||||||
|
set_pixel(framebuffer, vinfo, x + col * size + i, y + row * size + j, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a string of characters
|
||||||
|
void draw_text(int *framebuffer, struct fb_var_screeninfo vinfo, const char *text, int x, int y, int size, int color) {
|
||||||
|
for (const char *p = text; *p; ++p) {
|
||||||
|
draw_char(framebuffer, vinfo, *p, x, y, size, color);
|
||||||
|
x += size * 4; // Move to the next character position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw numbers around the clock face
|
||||||
|
void draw_circle(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
for (int i = 1; i <= 12; ++i) {
|
||||||
|
float angle = (i * 30 - 90) * M_PI / 180.0;
|
||||||
|
int x = CENTER_X + (int)(RADIUS * cos(angle));
|
||||||
|
int y = CENTER_Y + (int)(RADIUS * sin(angle));
|
||||||
|
|
||||||
|
char buffer[3];
|
||||||
|
sprintf(buffer, "%d", i);
|
||||||
|
draw_text(framebuffer, vinfo, buffer, x - 10, y - 10, 3, 0xFFFFFF); // Increased the size to '3' for visibility
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw clock hands
|
||||||
|
void draw_hand(int *framebuffer, struct fb_var_screeninfo vinfo, float angle, int length, int color) {
|
||||||
|
int x_end = CENTER_X + length * cos(angle);
|
||||||
|
int y_end = CENTER_Y - length * sin(angle);
|
||||||
|
draw_line(framebuffer, vinfo, CENTER_X, CENTER_Y, x_end, y_end, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the clock face with numbers
|
||||||
|
void draw_clock_face(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
memset(framebuffer, 0, vinfo.yres_virtual * vinfo.xres_virtual * sizeof(int)); // Clear screen
|
||||||
|
draw_circle(framebuffer, vinfo); // Draw the numbers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to read the first line of a file
|
||||||
|
int read_first_line(const char *path, char *buffer, size_t size) {
|
||||||
|
FILE *file = fopen(path, "r");
|
||||||
|
if (file == NULL) return -1;
|
||||||
|
if (fgets(buffer, size, file) == NULL) {
|
||||||
|
fclose(file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get system data
|
||||||
|
int get_cpu_usage() {
|
||||||
|
char buffer[256];
|
||||||
|
unsigned long long int user, nice, system, idle;
|
||||||
|
read_first_line("/proc/stat", buffer, sizeof(buffer));
|
||||||
|
sscanf(buffer, "cpu %llu %llu %llu %llu", &user, &nice, &system, &idle);
|
||||||
|
|
||||||
|
static unsigned long long int prev_user = 0, prev_nice = 0, prev_system = 0, prev_idle = 0;
|
||||||
|
unsigned long long int total_diff = (user - prev_user) + (nice - prev_nice) + (system - prev_system);
|
||||||
|
unsigned long long int idle_diff = idle - prev_idle;
|
||||||
|
int cpu_usage = (total_diff * 100) / (total_diff + idle_diff);
|
||||||
|
|
||||||
|
prev_user = user;
|
||||||
|
prev_nice = nice;
|
||||||
|
prev_system = system;
|
||||||
|
prev_idle = idle;
|
||||||
|
|
||||||
|
return cpu_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_ram_usage() {
|
||||||
|
char buffer[256];
|
||||||
|
unsigned long mem_total, mem_available;
|
||||||
|
read_first_line("/proc/meminfo", buffer, sizeof(buffer));
|
||||||
|
sscanf(buffer, "MemTotal: %lu kB", &mem_total);
|
||||||
|
read_first_line("/proc/meminfo", buffer, sizeof(buffer));
|
||||||
|
sscanf(buffer, "MemAvailable: %lu kB", &mem_available);
|
||||||
|
|
||||||
|
int ram_usage = ((mem_total - mem_available) * 100) / mem_total;
|
||||||
|
return ram_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_disk_usage() {
|
||||||
|
struct statvfs stat;
|
||||||
|
if (statvfs("/", &stat) != 0) return -1;
|
||||||
|
|
||||||
|
unsigned long total_blocks = stat.f_blocks;
|
||||||
|
unsigned long free_blocks = stat.f_bfree;
|
||||||
|
int disk_usage = ((total_blocks - free_blocks) * 100) / total_blocks;
|
||||||
|
|
||||||
|
return disk_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_battery_percentage() {
|
||||||
|
char buffer[16];
|
||||||
|
read_first_line("/sys/class/power_supply/BAT0/capacity", buffer, sizeof(buffer));
|
||||||
|
return atoi(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_cpu_temperature() {
|
||||||
|
char buffer[16];
|
||||||
|
read_first_line("/sys/class/thermal/thermal_zone0/temp", buffer, sizeof(buffer));
|
||||||
|
return atoi(buffer) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a percentage bar using [#####] style
|
||||||
|
void draw_percentage_bar(int *framebuffer, struct fb_var_screeninfo vinfo, int x, int y, int percentage, int size, int color) {
|
||||||
|
char bar[6];
|
||||||
|
int num_hashes = (percentage / 20);
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
bar[i] = i < num_hashes ? '#' : ' ';
|
||||||
|
}
|
||||||
|
bar[5] = '\0';
|
||||||
|
draw_text(framebuffer, vinfo, bar, x, y, size, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update system info on the screen
|
||||||
|
void update_system_info(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
int battery_percentage = get_battery_percentage();
|
||||||
|
int cpu_usage = get_cpu_usage();
|
||||||
|
int ram_usage = get_ram_usage();
|
||||||
|
int disk_usage = get_disk_usage();
|
||||||
|
int cpu_temp = get_cpu_temperature();
|
||||||
|
|
||||||
|
char buffer[80];
|
||||||
|
|
||||||
|
// Draw battery info
|
||||||
|
sprintf(buffer, "Battery: %d%%", battery_percentage);
|
||||||
|
draw_text(framebuffer, vinfo, buffer, CENTER_X - 100, CENTER_Y + 300, 2, 0xFFFFFF);
|
||||||
|
draw_percentage_bar(framebuffer, vinfo, CENTER_X + 60, CENTER_Y + 300, battery_percentage, 2, 0xFFFFFF);
|
||||||
|
|
||||||
|
// Draw CPU usage
|
||||||
|
sprintf(buffer, "CPU: %d%% Temp: %d°C", cpu_usage, cpu_temp);
|
||||||
|
draw_text(framebuffer, vinfo, buffer, CENTER_X - 100, CENTER_Y + 350, 2, 0xFFFFFF);
|
||||||
|
draw_percentage_bar(framebuffer, vinfo, CENTER_X + 60, CENTER_Y + 350, cpu_usage, 2, 0xFFFFFF);
|
||||||
|
|
||||||
|
// Draw RAM usage
|
||||||
|
sprintf(buffer, "RAM: %d%%", ram_usage);
|
||||||
|
draw_text(framebuffer, vinfo, buffer, CENTER_X - 100, CENTER_Y + 400, 2, 0xFFFFFF);
|
||||||
|
draw_percentage_bar(framebuffer, vinfo, CENTER_X + 60, CENTER_Y + 400, ram_usage, 2, 0xFFFFFF);
|
||||||
|
|
||||||
|
// Draw Disk usage
|
||||||
|
sprintf(buffer, "Disk: %d%%", disk_usage);
|
||||||
|
draw_text(framebuffer, vinfo, buffer, CENTER_X - 100, CENTER_Y + 450, 2, 0xFFFFFF);
|
||||||
|
draw_percentage_bar(framebuffer, vinfo, CENTER_X + 60, CENTER_Y + 450, disk_usage, 2, 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the clock hands and date/time display
|
||||||
|
void update_time(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm *timeinfo;
|
||||||
|
char date_buffer[80];
|
||||||
|
char time_buffer[80];
|
||||||
|
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
|
float hour_angle_degrees = (30 * timeinfo->tm_hour) + (timeinfo->tm_min * 0.5);
|
||||||
|
float hour_angle = - hour_angle_degrees * M_PI / 180.0 + M_PI / 2;
|
||||||
|
|
||||||
|
float minute_angle_degrees = 6 * timeinfo->tm_min;
|
||||||
|
float minute_angle = - minute_angle_degrees * M_PI / 180.0 + M_PI / 2;
|
||||||
|
|
||||||
|
draw_hand(framebuffer, vinfo, hour_angle, HOUR_HAND_LENGTH, 0xFFFFFF);
|
||||||
|
draw_hand(framebuffer, vinfo, minute_angle, MINUTE_HAND_LENGTH, 0xFFFFFF);
|
||||||
|
|
||||||
|
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo);
|
||||||
|
draw_text(framebuffer, vinfo, date_buffer, CENTER_X - 100, CENTER_Y + 200, 3, 0xFFFFFF);
|
||||||
|
|
||||||
|
strftime(time_buffer, sizeof(time_buffer), "%H:%M:%S", timeinfo);
|
||||||
|
draw_text(framebuffer, vinfo, time_buffer, CENTER_X - 80, CENTER_Y + 250, 3, 0xFFFFFF);
|
||||||
|
|
||||||
|
update_system_info(framebuffer, vinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int fbfd = open("/dev/fb0", O_RDWR);
|
||||||
|
if (fbfd == -1) {
|
||||||
|
perror("Error: cannot open framebuffer device");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fb_var_screeninfo vinfo;
|
||||||
|
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
|
||||||
|
perror("Error reading variable information");
|
||||||
|
close(fbfd);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t screensize = vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8;
|
||||||
|
int *framebuffer = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
|
||||||
|
if (framebuffer == MAP_FAILED) {
|
||||||
|
perror("Error mapping framebuffer device to memory");
|
||||||
|
close(fbfd);
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
draw_clock_face(framebuffer, vinfo);
|
||||||
|
update_time(framebuffer, vinfo);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(framebuffer, screensize);
|
||||||
|
close(fbfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
168
display/src/clock.c.bak
Normal file
168
display/src/clock.c.bak
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
// src/clock.c
|
||||||
|
#include "../include/clock.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// Set a pixel at (x, y) with color in the framebuffer
|
||||||
|
void set_pixel(int *framebuffer, struct fb_var_screeninfo vinfo, int x, int y, int color) {
|
||||||
|
if (x >= 0 && x < vinfo.xres_virtual && y >= 0 && y < vinfo.yres_virtual) {
|
||||||
|
framebuffer[y * vinfo.xres_virtual + x] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bresenham's line algorithm for drawing lines
|
||||||
|
void draw_line(int *framebuffer, struct fb_var_screeninfo vinfo, int x0, int y0, int x1, int y1, int color) {
|
||||||
|
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||||
|
int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||||
|
int err = dx + dy, e2;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
set_pixel(framebuffer, vinfo, x0, y0, color);
|
||||||
|
if (x0 == x1 && y0 == y1) break;
|
||||||
|
e2 = 2 * err;
|
||||||
|
if (e2 >= dy) { err += dy; x0 += sx; }
|
||||||
|
if (e2 <= dx) { err += dx; y0 += sy; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a simple filled rectangle to represent text characters
|
||||||
|
void draw_char(int *framebuffer, struct fb_var_screeninfo vinfo, char c, int x, int y, int size, int color) {
|
||||||
|
static const char font[10][5][3] = {
|
||||||
|
{ "111", "101", "101", "101", "111" }, // '0'
|
||||||
|
{ "110", "010", "010", "010", "111" }, // '1'
|
||||||
|
{ "111", "001", "111", "100", "111" }, // '2'
|
||||||
|
{ "111", "001", "111", "001", "111" }, // '3'
|
||||||
|
{ "101", "101", "111", "001", "001" }, // '4'
|
||||||
|
{ "111", "100", "111", "001", "111" }, // '5'
|
||||||
|
{ "111", "100", "111", "101", "111" }, // '6'
|
||||||
|
{ "111", "001", "001", "001", "001" }, // '7'
|
||||||
|
{ "111", "101", "111", "101", "111" }, // '8'
|
||||||
|
{ "111", "101", "111", "001", "111" } // '9'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
int index = c - '0';
|
||||||
|
for (int row = 0; row < 5; ++row) {
|
||||||
|
for (int col = 0; col < 3; ++col) {
|
||||||
|
if (font[index][row][col] == '1') {
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
for (int j = 0; j < size; ++j) {
|
||||||
|
set_pixel(framebuffer, vinfo, x + col * size + i, y + row * size + j, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a string of characters
|
||||||
|
void draw_text(int *framebuffer, struct fb_var_screeninfo vinfo, const char *text, int x, int y, int size, int color) {
|
||||||
|
for (const char *p = text; *p; ++p) {
|
||||||
|
draw_char(framebuffer, vinfo, *p, x, y, size, color);
|
||||||
|
x += size * 4; // Move to the next character position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw numbers around the clock face
|
||||||
|
void draw_circle(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
for (int i = 1; i <= 12; ++i) {
|
||||||
|
float angle = (i * 30 - 90) * M_PI / 180.0;
|
||||||
|
int x = CENTER_X + (int)(RADIUS * cos(angle));
|
||||||
|
int y = CENTER_Y + (int)(RADIUS * sin(angle));
|
||||||
|
|
||||||
|
char buffer[3];
|
||||||
|
sprintf(buffer, "%d", i);
|
||||||
|
draw_text(framebuffer, vinfo, buffer, x - 10, y - 10, 3, 0xFFFFFF); // Increased the size to '3' for visibility
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw clock hands
|
||||||
|
void draw_hand(int *framebuffer, struct fb_var_screeninfo vinfo, float angle, int length, int color) {
|
||||||
|
int x_end = CENTER_X + length * cos(angle);
|
||||||
|
int y_end = CENTER_Y - length * sin(angle);
|
||||||
|
draw_line(framebuffer, vinfo, CENTER_X, CENTER_Y, x_end, y_end, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the clock face with numbers
|
||||||
|
void draw_clock_face(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
memset(framebuffer, 0, vinfo.yres_virtual * vinfo.xres_virtual * sizeof(int)); // Clear screen
|
||||||
|
draw_circle(framebuffer, vinfo); // Draw the numbers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the clock hands and date/time display
|
||||||
|
void update_time(int *framebuffer, struct fb_var_screeninfo vinfo) {
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm *timeinfo;
|
||||||
|
char date_buffer[80];
|
||||||
|
char time_buffer[80];
|
||||||
|
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
|
// Calculate the angle for the hour hand
|
||||||
|
float hour_angle_degrees = (30 * timeinfo->tm_hour) + (timeinfo->tm_min * 0.5);
|
||||||
|
float hour_angle = - hour_angle_degrees * M_PI / 180.0 + M_PI / 2; // Convert to radians and adjust to 12 o'clock start
|
||||||
|
|
||||||
|
// Calculate the angle for the minute hand
|
||||||
|
float minute_angle_degrees = 6 * timeinfo->tm_min;
|
||||||
|
float minute_angle = - minute_angle_degrees * M_PI / 180.0 + M_PI / 2; // Convert to radians and adjust to 12 o'clock start
|
||||||
|
|
||||||
|
// Draw both hands in white (0xFFFFFF)
|
||||||
|
draw_hand(framebuffer, vinfo, hour_angle, HOUR_HAND_LENGTH, 0xFFFFFF); // Hour hand is shorter
|
||||||
|
draw_hand(framebuffer, vinfo, minute_angle, MINUTE_HAND_LENGTH, 0xFFFFFF); // Minute hand is longer
|
||||||
|
|
||||||
|
// Display the date
|
||||||
|
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo);
|
||||||
|
draw_text(framebuffer, vinfo, date_buffer, CENTER_X - 100, CENTER_Y + 300, 3, 0xFFFFFF); // Moved lower and increased size
|
||||||
|
|
||||||
|
// Display the time
|
||||||
|
strftime(time_buffer, sizeof(time_buffer), "%H:%M:%S", timeinfo);
|
||||||
|
draw_text(framebuffer, vinfo, time_buffer, CENTER_X - 80, CENTER_Y + 350, 3, 0xFFFFFF); // Moved lower and increased size
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Open the framebuffer device
|
||||||
|
int fbfd = open("/dev/fb0", O_RDWR);
|
||||||
|
if (fbfd == -1) {
|
||||||
|
perror("Error: cannot open framebuffer device");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get variable screen information
|
||||||
|
struct fb_var_screeninfo vinfo;
|
||||||
|
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
|
||||||
|
perror("Error reading variable information");
|
||||||
|
close(fbfd);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the framebuffer to user memory
|
||||||
|
size_t screensize = vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8;
|
||||||
|
int *framebuffer = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
|
||||||
|
if (framebuffer == MAP_FAILED) {
|
||||||
|
perror("Error mapping framebuffer device to memory");
|
||||||
|
close(fbfd);
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continuously update the clock
|
||||||
|
while (1) {
|
||||||
|
draw_clock_face(framebuffer, vinfo);
|
||||||
|
update_time(framebuffer, vinfo);
|
||||||
|
sleep(1); // Sleep for 1 second to update the clock every second
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
munmap(framebuffer, screensize);
|
||||||
|
close(fbfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user