1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 Copyright Kévin Ferrare based on Zakk Roberts's work
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "clock_draw_analog.h"
24 #include "lib/fixedpoint.h"
25 #include "clock_bitmaps.h"
26 #include "clock_bitmap_strings.h"
28 #define ANALOG_SECOND_RADIUS(screen, round) \
29 ANALOG_MINUTE_RADIUS(screen, round)
30 #define ANALOG_MINUTE_RADIUS(screen, round) \
31 (round?MIN(screen->getheight()/2 -10, screen->getwidth()/2 -10):screen->getheight()/2)
32 #define ANALOG_HOUR_RADIUS(screen, round) \
33 (2*ANALOG_MINUTE_RADIUS(screen, round)/3)
35 #define HOUR_ANGLE(hour, minute, second) (30*(hour) +(minute)/2)
36 #define MINUTE_ANGLE(minute, second) (6*(minute)+(second)/10)
37 #define SECOND_ANGLE(second) (6 * (second))
39 /* Note that the given angle's origin is midday and not 3 o'clock */
40 void polar_to_cartesian(int a
, int r
, int* x
, int* y
)
42 #if CONFIG_LCD == LCD_SSD1815
43 /* Correct non-square pixel aspect of archos recorder LCD */
44 *x
= (fp14_sin(a
) * 5 / 4 * r
) >> 14;
46 *x
= (fp14_sin(a
) * r
) >> 14;
48 *y
= (fp14_sin(a
-90) * r
) >> 14;
51 void polar_to_cartesian_screen_centered(struct screen
* display
,
52 int a
, int r
, int* x
, int* y
)
54 polar_to_cartesian(a
, r
, x
, y
);
55 *x
+=display
->getwidth()/2;
56 *y
+=display
->getheight()/2;
59 void angle_to_square(int square_width
, int square_height
,
60 int a
, int* x
, int* y
)
63 if(a
>45 && a
<=135){/* top line */
65 *x
=square_width
-(square_width
*2*a
)/90;
67 }else if(a
>135 && a
<=225){/* left line */
70 *y
=square_height
-(square_height
*2*a
)/90;
71 }else if(a
>225 && a
<=315){/* bottom line */
73 *x
=(square_width
*2*a
)/90-square_width
;
75 }else if(a
>315 || a
<=45){/* right line */
81 *y
=(square_height
*2*a
)/90-square_height
;
85 void angle_to_square_screen_centered(struct screen
* display
,
86 int square_width
, int square_height
,
87 int a
, int* x
, int* y
)
89 angle_to_square(square_width
, square_height
, a
, x
, y
);
90 *x
+=display
->getwidth()/2;
91 *y
+=display
->getheight()/2;
94 void draw_hand(struct screen
* display
, int angle
,
95 int radius
, int thickness
, bool round
)
97 int x1
, y1
; /* the longest */
98 int x2
, y2
, x3
, y3
; /* the base */
99 if(round
){/* round clock */
100 polar_to_cartesian_screen_centered(display
, angle
, radius
, &x1
, &y1
);
101 }else{/* fullscreen clock, hands describes square motions */
102 int square_width
, square_height
;
103 /* radius is defined smallest between getwidth() and getheight() */
104 square_height
=radius
;
105 square_width
=(radius
*display
->getwidth())/display
->getheight();
106 angle_to_square_screen_centered(
107 display
, square_width
, square_height
, angle
, &x1
, &y1
);
109 polar_to_cartesian_screen_centered(display
, (angle
+120)%360,
110 radius
/40+thickness
, &x2
, &y2
);
111 polar_to_cartesian_screen_centered(display
, (angle
+240)%360,
112 radius
/40+thickness
, &x3
, &y3
);
113 xlcd_filltriangle_screen(display
, x1
, y1
, x2
, y2
, x3
, y3
);
114 rb
->lcd_drawline(x1
, y1
, x2
, y2
);
115 rb
->lcd_drawline(x1
, y1
, x3
, y3
);
118 void draw_hands(struct screen
* display
, int hour
, int minute
, int second
,
119 int thickness
, bool round
, bool draw_seconds
)
122 draw_hand(display
, SECOND_ANGLE(second
),
123 ANALOG_SECOND_RADIUS(display
, round
), thickness
, round
);
125 draw_hand(display
, MINUTE_ANGLE(minute
, second
),
126 ANALOG_MINUTE_RADIUS(display
, round
), thickness
+2, round
);
127 draw_hand(display
, HOUR_ANGLE(hour
, minute
, second
),
128 ANALOG_HOUR_RADIUS(display
, round
), thickness
+2, round
);
131 void draw_counter(struct screen
* display
, struct counter
* counter
)
134 int second_str_w
, hour_str_w
, str_h
;
135 const struct picture
* smalldigits_bitmaps
=
136 &(smalldigits
[display
->screen_type
]);
137 struct time counter_time
;
138 counter_get_elapsed_time(counter
, &counter_time
);
139 rb
->snprintf(buffer
, 10, "%02d:%02d",
140 counter_time
.hour
, counter_time
.minute
);
141 getstringsize(smalldigits_bitmaps
, buffer
, &hour_str_w
, &str_h
);
142 draw_string(display
, smalldigits_bitmaps
, buffer
,
143 display
->getwidth()-hour_str_w
,
144 display
->getheight()-2*str_h
);
146 rb
->snprintf(buffer
, 10, "%02d", counter_time
.second
);
147 getstringsize(smalldigits_bitmaps
, buffer
, &second_str_w
, &str_h
);
148 draw_string(display
, smalldigits_bitmaps
, buffer
,
149 display
->getwidth()-(hour_str_w
+second_str_w
)/2,
150 display
->getheight()-str_h
);
153 void draw_date(struct screen
* display
, struct time
* time
, int date_format
)
156 int year_str_w
, monthday_str_w
, str_h
;
157 int year_line
=date_format
==JAPANESE
?1:2;
158 int monthday_line
=date_format
==JAPANESE
?2:1;
159 const struct picture
* smalldigits_bitmaps
=
160 &(smalldigits
[display
->screen_type
]);
161 if(date_format
==ENGLISH
|| date_format
==JAPANESE
){
162 rb
->snprintf(buffer
, 10, "%02d/%02d", time
->month
, time
->day
);
164 rb
->snprintf(buffer
, 10, "%02d/%02d", time
->day
, time
->month
);
166 /* draws month and day */
167 getstringsize(smalldigits_bitmaps
, buffer
, &monthday_str_w
, &str_h
);
168 draw_string(display
, smalldigits_bitmaps
, buffer
,
169 0, display
->getheight()-year_line
*str_h
);
170 rb
->snprintf(buffer
, 10, "%04d", time
->year
);
173 getstringsize(smalldigits_bitmaps
, buffer
, &year_str_w
, &str_h
);
174 draw_string(display
, smalldigits_bitmaps
, buffer
,
175 (monthday_str_w
-year_str_w
)/2,
176 display
->getheight()-monthday_line
*str_h
);
179 void draw_border(struct screen
* display
, int skin
)
181 /* Draws square dots every 5 minutes */
184 int size
=display
->getheight()/50;/* size of the square dots */
185 if(size
%2)/* a pair number */
187 for(i
=0; i
< 60; i
+=5){
189 polar_to_cartesian_screen_centered(display
, MINUTE_ANGLE(i
, 0),
190 ANALOG_MINUTE_RADIUS(display
, skin
), &x
, &y
);
192 angle_to_square_screen_centered(
193 display
, display
->getwidth()/2-size
/2, display
->getheight()/2-size
/2,
194 MINUTE_ANGLE(i
, 0), &x
, &y
);
196 display
->fillrect(x
-size
/2, y
-size
/2, size
, size
);
200 void draw_hour(struct screen
* display
, struct time
* time
,
201 bool show_seconds
, int skin
)
207 /* Crappy fake antialiasing (color LCDs only)!
208 * how this works is we draw a large mid-gray hr/min/sec hand,
209 * then the actual (slightly smaller) hand on top of those.
210 * End result: mid-gray edges to the black hands, smooths them out. */
211 #ifdef HAVE_LCD_COLOR
212 if(display
->is_color
){
213 display
->set_foreground(LCD_RGBPACK(100,110,125));
214 draw_hands(display
, hour
, time
->minute
, time
->second
,
215 1, skin
, show_seconds
);
216 display
->set_foreground(LCD_BLACK
);
219 draw_hands(display
, hour
, time
->minute
, time
->second
,
220 0, skin
, show_seconds
);
223 void draw_center_cover(struct screen
* display
)
225 display
->hline((display
->getwidth()/2)-1,
226 (display
->getwidth()/2)+1, (display
->getheight()/2)+3);
227 display
->hline((display
->getwidth()/2)-3,
228 (display
->getwidth()/2)+3, (display
->getheight()/2)+2);
229 display
->fillrect((display
->getwidth()/2)-4, (display
->getheight()/2)-1, 9, 3);
230 display
->hline((display
->getwidth()/2)-3,
231 (display
->getwidth()/2)+3, (display
->getheight()/2)-2);
232 display
->hline((display
->getwidth()/2)-1,
233 (display
->getwidth()/2)+1, (display
->getheight()/2)-3);
236 void analog_clock_draw(struct screen
* display
, struct time
* time
,
237 struct clock_settings
* settings
,
238 struct counter
* counter
,
242 draw_hour(display
, time
, settings
->analog
.show_seconds
, skin
);
243 if(settings
->analog
.show_border
)
244 draw_border(display
, skin
);
246 draw_counter(display
, counter
);
247 if(settings
->analog
.show_date
&& settings
->general
.date_format
!=NONE
)
248 draw_date(display
, time
, settings
->general
.date_format
);
249 draw_center_cover(display
);