You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
7.7 KiB
297 lines
7.7 KiB
#include <M5StickC.h>
|
|
#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;
|
|
}
|
|
|