Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
- // Small example how to use the library.
- // For more examples, look at demo-main.cc
- //
- // This code is public domain
- // (but note, that the led-matrix library this depends on is GPL v2)
- #include "led-matrix.h"
- #include <unistd.h>
- #include <math.h>
- #include <stdio.h>
- #include <signal.h>
- #include <getopt.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- using rgb_matrix::GPIO;
- using rgb_matrix::RGBMatrix;
- using rgb_matrix::Canvas;
- // IntPoint data type
- struct IntPoint
- {
- int X;
- int Y;
- IntPoint(int InX, int InY)
- {
- X = InX;
- Y = InY;
- }
- };
- // Color data type
- struct Color
- {
- int R;
- int G;
- int B;
- Color(int InR, int InG, int InB)
- {
- R = InR;
- G = InG;
- B = InB;
- }
- };
- volatile bool interrupt_received = false;
- static void InterruptHandler(int signo) {
- interrupt_received = true;
- }
- /*
- static int abs(int n)
- {
- if (n >= 0)
- return n;
- else
- return n * -1;
- }
- */
- // Parse a string into a color
- static bool parseColor(Color *color, const char *str)
- {
- return sscanf(str, "%hhu,%hhu,%hhu", &color->R, &color->G, &color->B) == 3;
- }
- // Function do draw a circle with given radius and center point
- static void DrawCircle(Canvas *canvas, float radius, IntPoint center, Color color)
- {
- /*float angleStep = 1.0 / 360;
- for (float a = 0, r = 0; r < radius; a+= angleStep, r+= angleStep) {
- float dotX = cos(a * 2 * M_PI) * r;
- float dotY = sin(a * 2 * M_PI) * r;
- canvas->SetPixel(center.X + dotX, center.Y + dotY, color.R, color.G, color.B);
- }*/
- for (int y = -radius; y <= radius; y++)
- {
- for(int x = -radius; x <= radius; x++)
- {
- if (x*x + y*y <= radius*radius + radius * 0.8)
- {
- canvas->SetPixel(center.X + x, center.Y + y, color.R, color.G, color.B);
- }
- }
- }
- }
- // Function to fill a specific area with color
- static void FillArea(Canvas *canvas, IntPoint topLeft, IntPoint bottomRight, Color color)
- {
- for (int x = topLeft.X; x <= bottomRight.X; x++)
- {
- for (int y = topLeft.Y; y <= bottomRight.Y; y++)
- {
- canvas->SetPixel(x, y, color.R, color.G, color.B);
- }
- }
- }
- // Function to draw a line from point A to point B
- static void DrawLine(Canvas *canvas, IntPoint A, IntPoint B, Color color)
- {
- int deltaX = B.X - A.X;
- signed char const ix = (deltaX > 0) - (deltaX < 0);
- deltaX = 2 * abs(deltaX);
- int deltaY = B.Y - A.Y;
- signed char const iy = (deltaY > 0) - (deltaY < 0);
- deltaY = 2 * abs(deltaY);
- int x1 = A.X;
- int y1 = A.Y;
- int x2 = B.X;
- int y2 = B.Y;
- canvas->SetPixel(x1, y1, color.R, color.G, color.B);
- if (deltaX >= deltaY)
- {
- int error = deltaY - (deltaX / 2);
- while (x1 != x2)
- {
- if ((error > 0) || (!error && (ix > 0)))
- {
- error -= deltaX;
- y1 += iy;
- }
- error += deltaY;
- x1 += ix;
- canvas->SetPixel(x1, y1, color.R, color.G, color.B);
- }
- }
- else
- {
- int error = deltaX - (deltaY / 2);
- while (y1 != y2)
- {
- if ((error > 0) || (!error && (iy > 0)))
- {
- error -= deltaY;
- x1 += ix;
- }
- error += deltaX;
- y1 += iy;
- canvas->SetPixel(x1, y1, color.R, color.G, color.B);
- }
- }
- }
- static IntPoint CalculatePointerEndPoint(float progress, int pointerLength, IntPoint origin)
- {
- IntPoint result = IntPoint(0,0);
- result.X = origin.X + pointerLength * cos((progress * 2 * M_PI) - M_PI / 2);
- result.Y = origin.Y + pointerLength * sin((progress * 2 * M_PI) - M_PI / 2);
- //printf("Progress: %f, Angle: %f, nPi: %f, res: %d,%d\n", progress, progress * 360.0, progress * 2 * M_PI, result.X, result.Y);
- return result;
- }
- static void printUsage()
- {
- printf("Invalid command line. Options:\n");
- printf("\t-o <r,g,b> : Clock circle and center point color. Default 255,0,0.\n");
- printf("\t-h <r,g,b> : Hour pointer color. Default 0,255,0.\n");
- printf("\t-m <r,g,b> : Minute pointer color. Default 0,255,0.\n");
- printf("\t-s <r,g,b> : Second pointer color. Default 0,0,255.\n");
- printf("\t-r <radius> : Clock radius. Default 25.\n");
- printf("\t-d <depth> : Outer circle depth. Default 2.\n");
- }
- // Main function
- int main(int argc, char *argv[])
- {
- // Set up display
- RGBMatrix::Options defaults;
- defaults.hardware_mapping = "regular"; // or e.g. "adafruit-hat"
- defaults.rows = 64;
- defaults.chain_length = 2;
- defaults.parallel = 1;
- defaults.show_refresh_rate = true;
- Canvas *canvas = rgb_matrix::CreateMatrixFromFlags(&argc, &argv, &defaults);
- if (canvas == NULL)
- return 1;
- // Adjustable settings
- Color outlineColor = Color(255,0,0);
- Color hourPointerColor = Color(0,255,0);
- Color minPointerColor = Color(0,255,0);
- Color secPointerColor = Color(0,0,255);
- int clockRadius = 25;
- int circleDepth = 2;
- int opt;
- while ((opt = getopt(argc, argv, "o:h:m:s:r:d:")) != -1)
- {
- switch(opt)
- {
- case 'o':
- if (!parseColor(&outlineColor, optarg))
- {
- printf("Invalid outline color: %s\n", optarg);
- printUsage();
- }
- break;
- case 'h':
- if (!parseColor(&hourPointerColor, optarg))
- {
- printf("Invalid hour pointer color: %s\n", optarg);
- printUsage();
- }
- break;
- case 'm':
- if (!parseColor(&minPointerColor, optarg))
- {
- printf("Invalid min pointer color: %s\n", optarg);
- printUsage();
- }
- break;
- case 's':
- if (!parseColor(&secPointerColor, optarg))
- {
- printf("Invalid sec pointer color: %s\n", optarg);
- printUsage();
- }
- break;
- case 'r': clockRadius = atoi(optarg); break;
- case 'd': circleDepth = atoi(optarg); break;
- default:
- printUsage();
- break;
- }
- }
- // Set up interrupt handlers
- signal(SIGTERM, InterruptHandler);
- signal(SIGINT, InterruptHandler);
- IntPoint centerOfScreen = IntPoint(canvas->width() / 2, canvas->height() / 2);
- // Draw clock circle
- DrawCircle(canvas, clockRadius, centerOfScreen, outlineColor);
- DrawCircle(canvas, clockRadius - circleDepth, centerOfScreen, Color(0,0,0));
- // Draw center clock point
- FillArea(canvas, IntPoint(centerOfScreen.X - 1, centerOfScreen.Y - 1), IntPoint(centerOfScreen.X + 1, centerOfScreen.Y + 1), Color(255,0,0));
- struct timespec next_time;
- next_time.tv_sec = time(NULL);
- next_time.tv_nsec = 0;
- struct tm tm;
- IntPoint lastHourPointerEnd = IntPoint(0,0);
- while (!interrupt_received)
- {
- localtime_r(&next_time.tv_sec, &tm);
- // Remove pointers from last tick
- DrawLine(canvas, centerOfScreen, lastHourPointerEnd, Color(0,0,0));
- DrawLine(canvas, centerOfScreen, CalculatePointerEndPoint((tm.tm_min - 1) / 60.0, clockRadius - 5, centerOfScreen), Color(0,0,0));
- DrawLine(canvas, centerOfScreen, CalculatePointerEndPoint((tm.tm_sec - 1) / 60.0, clockRadius - 8, centerOfScreen), Color(0,0,0));
- // Draw new pointers
- lastHourPointerEnd = CalculatePointerEndPoint((tm.tm_hour / 12.0) + (tm.tm_min / 600.0), clockRadius - 11, centerOfScreen);
- DrawLine(canvas, centerOfScreen, lastHourPointerEnd, hourPointerColor);
- DrawLine(canvas, centerOfScreen, CalculatePointerEndPoint(tm.tm_min / 60.0, clockRadius - 5, centerOfScreen), minPointerColor);
- DrawLine(canvas, centerOfScreen, CalculatePointerEndPoint(tm.tm_sec / 60.0, clockRadius - 8, centerOfScreen), secPointerColor);
- // Draw center point on top
- FillArea(canvas, IntPoint(centerOfScreen.X - 1, centerOfScreen.Y - 1), IntPoint(centerOfScreen.X + 1, centerOfScreen.Y + 1), outlineColor);
- // Sleep for a second
- clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next_time, NULL);
- next_time.tv_sec += 1;
- }
- canvas->Clear();
- delete canvas;
- return 0;
- }
Add Comment
Please, Sign In to add comment