Trammell Hudson avatar Trammell Hudson committed c612a8e Draft

Use sin_table() to compute positions and draw hands

Comments (0)

Files changed (4)

 	usb_serial.c \
 	bits.c \
 	hershey.c \
+	sin_table.c \
 
 
 # MCU name, you MUST set this to match the board you are using
 #include "usb_serial.h"
 #include "bits.h"
 #include "hershey.h"
+#include "sin_table.h"
 
 
 /** Track the number of miliseconds, sec, min and hour since midnight */
 static volatile uint16_t now_ms;
-static volatile uint8_t now_sec;
-static volatile uint8_t now_min;
-static volatile uint8_t now_hour;
+static volatile uint8_t now_sec = 30;
+static volatile uint8_t now_min = 19;
+static volatile uint8_t now_hour = 20;
 
 
 // Define CONFIG_HZ_IRQ to enable a timer interrupt rather than
 }
 
 
-static void
-draw_digit(
+static inline void
+_draw_digit(
 	uint8_t x,
 	uint8_t y,
-	uint8_t val
+	uint8_t val,
+	const uint8_t scale
 )
 {
 	const path_t * p = digits[val];
-	const int8_t scale = 2;
 
 	while (1)
 	{
 	}
 }
 
-static const uint8_t hour_pos[][2] = {
-{ 128,228 },
-{ 153,224 },
-{ 177,214 },
-{ 198,198 },
-{ 214,178 },
-{ 224,153 },
-{ 227,128 },
-{ 224,102 },
-{ 214,78 },
-{ 198,57 },
-{ 178,41 },
-{ 154,31 },
-{ 128,28 },
-{ 102,31 },
-{ 78,41 },
-{ 57,57 },
-{ 41,77 },
-{ 31,101 },
-{ 28,127 },
-{ 31,153 },
-{ 41,177 },
-{ 57,198 },
-{ 77,214 },
-{ 101,224 },
-};
 
+static void
+draw_digit_big(
+	uint8_t x,
+	uint8_t y,
+	uint8_t val
+)
+{
+	_draw_digit(x, y, val, 1);
+}
+
+
+static void
+draw_digit(
+	uint8_t x,
+	uint8_t y,
+	uint8_t val
+)
+{
+	_draw_digit(x, y, val, 2);
+}
 
 
 int main(void)
 		}
 
 
+		// Draw all the digits around the outside
 		for (uint8_t h = 0 ; h < 24 ; h++)
 		{
-			uint8_t x = hour_pos[h][0];
-			uint8_t y = hour_pos[h][1];
+			uint16_t h2 = h;
+			h2 = (h2 * 682) / 64;
+			uint8_t x = sin_lookup(h2) * 7 / 8 + 128;
+			uint8_t y = cos_lookup(h2) * 7 / 8 + 128;
 			draw_digit(x-8, y-4, h / 10);
 			draw_digit(x+2, y-4, h % 10);
 		}
 
 		// Draw the hour hand
 		uint8_t h = now_hour;
+		uint8_t m = now_min;
+		uint8_t s = now_sec;
 
-		draw_digit( 0+px, 64+py, h / 10);
-		draw_digit(32+px, 64+py, h % 10);
+		const uint8_t cx = 72;
+		const uint8_t cy = 64;
 
-		uint8_t m = now_min;
-		draw_digit(80+px, 64+py, m / 10);
-		draw_digit(80+32+px, 64+py, m % 10);
+		draw_digit_big( 0+cx, cy, h / 10);
+		draw_digit_big(16+cx, cy, h % 10);
+		draw_digit_big(40+cx, cy, m / 10);
+		draw_digit_big(56+cx, cy, m % 10);
+		draw_digit_big(80+cx, cy, s / 10);
+		draw_digit_big(96+cx, cy, s % 10);
 
-		uint8_t s = now_sec;
-		draw_digit(160+px, 64+py, s / 10);
-		draw_digit(160+32+px, 64+py, s % 10);
+		{
+			uint16_t h2 = h;
+			h2 = (h2 * 682 + m*11) / 64;
+			uint8_t hx = sin_lookup(h2) * 3 / 8 + 128;
+			uint8_t hy = cos_lookup(h2) * 3 / 8 + 128;
+			line(128, 128, hx, hy);
+		}
 
-		line(128, 128, hour_pos[s/3][0], hour_pos[s/3][1]);
+
+		{
+			uint16_t m2 = m;
+			m2 = (m2 * 273 + s*4) / 64;
+			uint8_t mx = sin_lookup(m2) * 5 / 8 + 128;
+			uint8_t my = cos_lookup(m2) * 5 / 8 + 128;
+			line(128, 128, mx, my);
+			line_horiz(mx - 5, my, 10);
+			line_vert(mx, my - 5, 10);
+		}
+
+
+		// seconds to "degrees" = 
+		{
+			uint16_t s2 = s;
+			s2 = (s2 * 1092 + now_ms) / 256;
+			uint8_t sx = sin_lookup(s2) * 6 / 8 + 128;
+			uint8_t sy = cos_lookup(s2) * 6 / 8 + 128;
+			line(128, 128, sx, sy);
+		}
 
 /*
-		draw_digit(0*32+px, py, (now_ms / 100) % 10);
-		draw_digit(1*32+px, py, (now_ms / 10) % 10);
-		draw_digit(2*32+px, py, (now_ms / 1) % 10);
-
-		draw_digit(4*32+px, py, (TCNT0 / 100) % 10);
-		draw_digit(5*32+px, py, (TCNT0 / 10) % 10);
-		draw_digit(6*32+px, py, (TCNT0 / 1) % 10);
-*/
-
-		//line(128, 128, (x & 255), x >> 8);
-
 		line_horiz(0,0,255);
 		line_horiz(0,255,255);
 		line_vert(0,0,255);
 		line_vert(255,0,255);
+*/
 	}
 }
 
+/** \file
+ * Fixed point sin() function.
+ */
+#include "sin_table.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static const uint8_t sin_table[] = {
+	0,
+	25,
+	50,
+	74,
+	98,
+	121,
+	142,
+	162,
+	181,
+	198,
+	213,
+	226,
+	237,
+	245,
+	251,
+	255,
+	255 // duplicate to avoid extra code for handling last case
+};
+
+
+int8_t
+sin_lookup(
+	uint8_t theta
+)
+{
+	int sign = 1;
+
+	if (theta < 64)
+	{
+		// q1, upward slope, normal theta, positive sign
+	} else
+	if (theta < 128)
+	{
+		theta = 128 - theta; // downward slope, still positive
+	} else
+	if (theta < 192)
+	{
+		// q3, downward slope, negative side
+		theta = theta - 128;
+		sign = -1;
+	} else
+	{
+		// q4, upward slope, negative side
+		theta = 256 - theta;
+		sign = -1;
+	}
+
+	int16_t s1 = sin_table[(theta >> 2) + 0];
+	int16_t s2 = sin_table[(theta >> 2) + 1];
+	int8_t result = (s1 + ((s2 - s1) * (theta & 0x3)) / 4) / 2;
+
+	if (sign == -1)
+		return -result;
+	else
+		return result;
+}
+
+
+#if 0
+int main(void)
+{
+	unsigned theta;
+
+	for (theta = 0 ; theta < 0x100 ; theta++)
+	{
+		double sx = sin_lookup(theta) / 128.0;
+		double sf = sin(theta * 2 * M_PI / 256.0);
+		double cx = cos_lookup(theta) / 128.0;
+		double cf = cos(theta * 2 * M_PI / 256.0);
+
+		printf("%.4f %.4f %.4f\n",
+			cx,
+			cf,
+			cf - cx
+		);
+	}
+}
+#endif
+/** \file
+ * Approximate sin function.
+ * theta goes from 0 == 0 Pi to 255 == 2 Pi
+ */
+#ifndef _sin_table_h_
+#define _sin_table_h_
+
+#include <stdint.h>
+
+extern int8_t sin_lookup(uint8_t theta);
+
+static inline int8_t
+cos_lookup(
+	uint8_t theta
+)
+{
+	return sin_lookup(theta + 64);
+}
+
+
+#endif
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.