Source

watches / lunar / lunar.c

Full commit
/** \file
 * Draw a lunar face clock as well as the sun-up, sun-down times.
 * None of that is ready yet; this is a first import with copy.
 */
#include <string.h>
#include "main.h"
#include "draw.h"
#include "sin_table.h"


static uint8_t last_sec;
static PulseResource image_id;

void
init(void)
{
}


void
button_down(void)
{
	init();
	last_sec = 0;
	image_id = 0;
}


void
button_up(
	uint32_t ms
)
{
	// Nothing to do
	(void) ms;
}




static void
circle_line(
	color24_t color,
	int32_t x0,
	int32_t y0,
	int32_t radius
)
{
	int32_t f = 1 - radius;
	int ddF_x = 1;
	int ddF_y = -2 * radius;
	int x = 0;
	int y = radius;

	draw_pixel(color, x0, y0 + radius);
	draw_pixel(color, x0, y0 - radius);
	draw_pixel(color, x0 + radius, y0);
	draw_pixel(color, x0 - radius, y0);

	while (x < y)
	{
		if (f >= 0)
		{
			y--;
			ddF_y += 2;
			f += ddF_y;
		}
		x++;
		ddF_x += 2;
		f += ddF_x;

		draw_pixel(color, x0 + x, y0 + y);
		draw_pixel(color, x0 + x, y0 - y);
		draw_pixel(color, x0 - x, y0 + y);
		draw_pixel(color, x0 - x, y0 - y);

		draw_pixel(color, x0 + y, y0 + x);
		draw_pixel(color, x0 + y, y0 - x);
		draw_pixel(color, x0 - y, y0 + x);
		draw_pixel(color, x0 - y, y0 - x);
	}
}


void
fill(
	color24_t color,
	int32_t x0,
	int32_t y0,
	int32_t x1,
	int32_t y1
)
{
	int32_t temp;
	if (x0 > x1)
	{
		temp = x0;
		x0 = x1;
		x1 = temp;
	}
	if (y0 > y1)
	{
		temp = y0;
		y0 = y1;
		y1 = temp;
	}

	if (x1 < 0 || y1 < 0)
		return;
	if (x0 >= SCREEN_WIDTH || y1 >= SCREEN_HEIGHT)
		return;
	if (x0 < 0)
		x0 = 0;
	if (y0 < 0)
		y0 = 0;
	if (x1 >= SCREEN_WIDTH)
		x1 = SCREEN_WIDTH - 1;
	if (y1 >= SCREEN_HEIGHT)
		y1 = SCREEN_HEIGHT - 1;

	int32_t h = y1 - y0 + 1;
	int32_t w = x1 - x0 + 1;
	uint16_t num = w * h;
	if (num == 0)
		return;
	
	pulse_set_draw_window(x0, y0, x1, y1);

	while (num--)
		pulse_draw_point24(color);
}


static void
circle_fill(
	color24_t color,
	int32_t x0,
	int32_t y0,
	int32_t radius
)
{
	int32_t f = 1 - radius;
	int ddF_x = 1;
	int ddF_y = -2 * radius;
	int x = 0;
	int y = radius;

	fill(color, x0 - radius, y0, x0 + radius, y0);

	while (x < y)
	{
		if (f >= 0)
		{
			y--;
			ddF_y += 2;
			f += ddF_y;
		}
		x++;
		ddF_x += 2;
		f += ddF_x;

		fill(color, x0 - x, y0 + y, x0 + x, y0 + y);
		fill(color, x0 - x, y0 - y, x0 + x, y0 - y);
		fill(color, x0 - y, y0 + x, x0 + y, y0 + x);
		fill(color, x0 - y, y0 - x, x0 + y, y0 - x);
	}
}


#if 0
static void
draw_gradient_arc(
	int32_t radius,
	int32_t dot_radius,
	uint16_t initial_angle
)
{
	const uint16_t arc_len = 0xB000;
	const uint16_t step = 128;

	for (uint32_t t = 0 ; t < arc_len  ; t += step)
	{
		const uint16_t angle = initial_angle + t - arc_len;
		const int16_t sx = (radius * sin_lookup(angle)) / 32768;
		const int16_t sy = (radius * cos_lookup(angle)) / 32768;

		color24_t color = {
			(t * dot_color.red) / arc_len,
			(t * dot_color.green) / arc_len,
			(t * dot_color.blue) / arc_len,
		};

		circle_fill(
			color,
			SCREEN_WIDTH/2 + sx,
			SCREEN_HEIGHT/2 - sy,
			dot_radius
		);
	}
}
#endif


void
draw(
	uint32_t cur_ms
)
{
	uint32_t ms = cur_ms % 1000; cur_ms /= 1000;
	const uint32_t new_sec = cur_ms % 60; cur_ms /= 60;
	const uint8_t new_min = cur_ms % 60; cur_ms /= 60;
	const uint8_t new_hour = cur_ms % 12; // cur_ms %= 24;

	if (last_sec == new_sec)
		return;
	last_sec = new_sec;

	if (image_id < IMAGE_M000
	||  image_id >= IMAGE_M346)
		image_id = IMAGE_M000;

	image_draw_gray(image_id, (SCREEN_WIDTH - 81)/2, 0);
	image_id++;
	

#if 0
	const uint16_t sec_angle = ((new_sec * 6 + (ms*6) / 1000) * 32768) / 180;
	const uint16_t min_angle = ((new_min * 6 + (new_sec*6) / 60) * 32768) / 180;
	const uint16_t hour_angle = ((new_hour * 30 + (new_min*30) / 60) * 32768) / 180;

	const int32_t sec_radius = SCREEN_WIDTH/2;
	const int32_t sec_dot_radius = 3;
	if (sec_angle != last_sec_angle || first_time)
	{
		draw_gradient_arc(
			sec_radius,
			sec_dot_radius,
			sec_angle
		);
		last_sec_angle = sec_angle;
	}

	const int32_t min_dot_radius =  8;
	const int32_t min_radius = sec_radius - sec_dot_radius - min_dot_radius - 1;
	if (min_angle != last_min_angle || first_time)
	{
		draw_gradient_arc(
			min_radius,
			min_dot_radius,
			min_angle
		);
		last_min_angle = min_angle;
	}

	const int32_t hour_dot_radius = 12;
	const int32_t hour_radius = min_radius - min_dot_radius - hour_dot_radius - 1;
	if (hour_angle != last_hour_angle || first_time)
	{
		draw_gradient_arc(
			hour_radius,
			hour_dot_radius,
			hour_angle
		);
		last_hour_angle = hour_angle;
	}

	first_time = 0;
#endif
}