#include #include "Kernel.h" #include "EAT.h" #include "Util.h" #include "UI.h" #define CLOCK_FACE_OUTLINE_SIZE_PCNT 4 #define CLOCK_FACE_OUTLINE_COLOUR 0x666666 #define CLOCK_FACE_COLOUR 0xAAAAAA #define CLOCK_FACE_MARKER_COLOUR 0x666666 #define CLOCK_FACE_MARKER_TOP_COLOUR 0x333333 #define CLOCK_FACE_MARKER_SIZE_PCNT 10 #define CLOCK_HOUR_LENGTH_PCNT 20 #define CLOCK_HOUR_COLOUR 0x333333 #define CLOCK_MINUTE_LENGTH_PCNT 30 #define CLOCK_MINUTE_COLOUR 0x666666 #define DEGREES_TO_RADIANS 0.0174533 RTC_TimeTypeDef time_to_rtc(char* time); RTC_DateTypeDef date_to_rtc(char* date); void Clock_draw(int hwnd, int wnd_x, int wnd_y, int wnd_width, int wnd_height); void Clock_draw_arm(int center_x, int center_y, int angle, int length, unsigned int colour); int last_minute = -1; int Clock(int pid, unsigned int signal) { if (signal & SIGNAL_START) { Kernel_signal_mask(pid, SIGNAL_START | SIGNAL_STOP | SIGNAL_TICK); UI_create_window(&Clock_draw, 1); RTC_TimeTypeDef compile_time = time_to_rtc(__TIME__); RTC_DateTypeDef compile_date = date_to_rtc(__DATE__); if (EAT_allocate(2, 6) || EAT_read(2, 0) != compile_time.Hours || EAT_read(2, 1) != compile_time.Minutes || EAT_read(2, 2) != compile_time.Seconds || EAT_read(2, 3) != (compile_date.Year & 0xFF) || EAT_read(2, 4) != compile_date.Month || EAT_read(2, 5) != compile_date.Date) { M5.Rtc.SetTime(&compile_time); M5.Rtc.SetData(&compile_date); EAT_write(2, 0, compile_time.Hours); EAT_write(2, 1, compile_time.Minutes); EAT_write(2, 2, compile_time.Seconds); EAT_write(2, 3, compile_date.Year & 0xFF); EAT_write(2, 4, compile_date.Month); EAT_write(2, 5, compile_date.Date); } } if (signal & SIGNAL_STOP) { return 255; } if (signal & SIGNAL_TICK) { RTC_TimeTypeDef time; M5.Rtc.GetTime(&time); if (time.Minutes != last_minute) { last_minute = time.Minutes; Kernel_signal(SIGNAL_REDRAW); } } return 0; } void Clock_draw(int hwnd, int wnd_x, int wnd_y, int wnd_width, int wnd_height) { RTC_TimeTypeDef time; M5.Rtc.GetTime(&time); RTC_DateTypeDef date; M5.Rtc.GetData(&date); int size = 0; if (wnd_width < wnd_height) { size = wnd_width; } else { size = wnd_height; } int center_x = wnd_x + (size / 2); int center_y = wnd_y + (size / 2); int radius = size / 2; int outline_size = size * (CLOCK_FACE_OUTLINE_SIZE_PCNT / 100.0); int inner_radius = radius - (outline_size / 2); // Draw face M5.Lcd.fillCircle(center_x, center_y, radius, rgb_to_colour(CLOCK_FACE_OUTLINE_COLOUR)); M5.Lcd.fillCircle(center_x, center_y, inner_radius, rgb_to_colour(CLOCK_FACE_COLOUR)); // Draw lines int marker_size = size * (CLOCK_FACE_MARKER_SIZE_PCNT / 100.0); for (int i=0; i<360; i+=(360/12)) { int x1 = (inner_radius - marker_size) * cos(i * DEGREES_TO_RADIANS); int y1 = (inner_radius - marker_size) * sin(i * DEGREES_TO_RADIANS); int x2 = (inner_radius + 1) * cos(i * DEGREES_TO_RADIANS); int y2 = (inner_radius + 1) * sin(i * DEGREES_TO_RADIANS); x1 += center_x; x2 += center_x; y1 += center_y; y2 += center_y; // 0 degrees = right, draw top at 270 M5.Lcd.drawLine(x1, y1, x2, y2, i == 270 ? rgb_to_colour(CLOCK_FACE_MARKER_TOP_COLOUR) : rgb_to_colour(CLOCK_FACE_MARKER_COLOUR)); } int hour = time.Hours; if (hour > 12) hour -= 12; int minute = time.Minutes; int minute_angle = 360.0 * (minute / 60.0); int hour_angle = (360.0 * (hour / 12.0)) + (minute_angle / 12.0); Clock_draw_arm(center_x, center_y, hour_angle, size * (CLOCK_HOUR_LENGTH_PCNT / 100.0), rgb_to_colour(CLOCK_HOUR_COLOUR)); Clock_draw_arm(center_x, center_y, minute_angle, size * (CLOCK_MINUTE_LENGTH_PCNT / 100.0), rgb_to_colour(CLOCK_MINUTE_COLOUR)); } void Clock_draw_arm(int center_x, int center_y, int angle, int length, unsigned int colour) { // 0 = right, adjust for 0=up angle -= 90; int x = length * cos(angle * DEGREES_TO_RADIANS); int y = length * sin(angle * DEGREES_TO_RADIANS); M5.Lcd.drawLine(center_x, center_y, center_x + x, center_y + y, colour); } /* void redraw(RTC_TimeTypeDef time, RTC_DateTypeDef date) { draw_face(); // Write date? int center_x = CLOCK_OFFSET_X + (CLOCK_SIZE / 2); int center_y = CLOCK_OFFSET_Y + (CLOCK_SIZE / 2); M5.Lcd.setCursor(center_x + (CLOCK_SIZE / 16), center_y + (CLOCK_SIZE / 6)); M5.Lcd.setTextColor(rgb_to_colour(CLOCK_FACE_OUTLINE_COLOUR), rgb_to_colour(CLOCK_FACE_COLOUR)); M5.Lcd.print(date.Date); int hour = time.Hours; if (hour > 12) hour -= 12; int minute = time.Minutes; int minute_angle = 360.0 * (minute / 60.0); int hour_angle = (360.0 * (hour / 12.0)) + (minute_angle / 12.0); draw_arm(hour_angle, CLOCK_HOUR_LENGTH, rgb_to_colour(CLOCK_HOUR_COLOUR)); draw_arm(minute_angle, CLOCK_MINUTE_LENGTH, rgb_to_colour(CLOCK_MINUTE_COLOUR)); //M5.Lcd.setCursor(0, 40); //char time_str[6]; //sprintf(time_str, "%02d:%02d", time.Hours, time.Minutes); //M5.Lcd.print(time_str); } */ RTC_TimeTypeDef time_to_rtc(char* time) { RTC_TimeTypeDef time_ret; int buffer_idx = 0; char buffer[3]; char* current; int state = 0; for (current = time; ; current++) { if (*current == ':' || *current == '\0') { buffer[buffer_idx++] = '\0'; int next = atoi(buffer); switch (state++) { case 0: time_ret.Hours = next; break; case 1: time_ret.Minutes = next; break; case 2: time_ret.Seconds = next; break; } buffer_idx = 0; } else { buffer[buffer_idx++] = *current; } if (*current == '\0') { break; } } return time_ret; } RTC_DateTypeDef date_to_rtc(char* date) { RTC_DateTypeDef date_ret; int buffer_idx = 0; char buffer[5]; char* current; int state = 0; for (current = date; ; current++) { if (*current == ' ' || *current == '\0') { buffer[buffer_idx++] = '\0'; switch (state++) { case 0: // month if (strcmp(buffer, "Jan") == 0) { date_ret.Month = 1; } else if (strcmp(buffer, "Feb") == 0) { date_ret.Month = 2; } else if (strcmp(buffer, "Mar") == 0) { date_ret.Month = 3; } else if (strcmp(buffer, "Apr") == 0) { date_ret.Month = 4; } else if (strcmp(buffer, "May") == 0) { date_ret.Month = 5; } else if (strcmp(buffer, "Jun") == 0) { date_ret.Month = 6; } else if (strcmp(buffer, "Jul") == 0) { date_ret.Month = 7; } else if (strcmp(buffer, "Aug") == 0) { date_ret.Month = 8; } else if (strcmp(buffer, "Sep") == 0) { date_ret.Month = 9; } else if (strcmp(buffer, "Oct") == 0) { date_ret.Month = 10; } else if (strcmp(buffer, "Nov") == 0) { date_ret.Month = 11; } else if (strcmp(buffer, "Dec") == 0) { date_ret.Month = 12; } break; case 1: // day date_ret.Date = atoi(buffer); break; case 2: // year date_ret.Year = atoi(buffer); break; } buffer_idx = 0; } else { buffer[buffer_idx++] = *current; } if (*current == '\0') { break; } } return date_ret; }