From 1fddc966d25022ba3e198ab7100e500c4ce1450d Mon Sep 17 00:00:00 2001 From: David Phillips Date: Sat, 2 Mar 2019 23:25:29 +1300 Subject: Rename from test to clock-disp --- test.c | 397 ----------------------------------------------------------------- 1 file changed, 397 deletions(-) delete mode 100644 test.c (limited to 'test.c') diff --git a/test.c b/test.c deleted file mode 100644 index c8d8c74..0000000 --- a/test.c +++ /dev/null @@ -1,397 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -enum ALIGN_MODE { - ALIGN_MODE_LEFT, - ALIGN_MODE_CENTRE, - ALIGN_MODE_RIGHT, -}; - -#define WINDOW_TITLE "Clock Display" -#define SCREEN_WIDTH 800 -#define SCREEN_HEIGHT 480 - -#define TIME_X 0 -#define TIME_Y -50 - -#define NO_LOCK_Y 150 - -#define DATE_1_X 20 -#define DATE_1_Y 295 -#define DATE_2_X 20 -#define DATE_2_Y 350 - -#define SECONDS_X SCREEN_WIDTH - 80 -#define SECONDS_Y SCREEN_HEIGHT - 55 - -#define NTP_INFO_X 240 -#define NTP_INFO_Y SCREEN_HEIGHT - 55 -#define SAT_INFO_X 20 -#define SAT_INFO_Y NTP_INFO_Y - -#define SUN_INFO_X SCREEN_WIDTH -20 -#define SUN_INFO_1_Y DATE_1_Y -#define SUN_INFO_2_Y DATE_2_Y - -/* Common colours used */ -#define COLOUR_WHITE ((SDL_Color){255,255,255,255}) -#define COLOUR_YELLOW ((SDL_Color){255,191, 32,255}) -#define COLOUR_40GRAY ((SDL_Color){100,100,100,255}) - -static sem_t data_lock; -struct clock_data { - int is_unread; - char sunrise_time[8]; - char sunset_time[8]; - int sat_seen; - int sat_used; - int leap_second; - int offset; - char offset_units[8]; - int no_gps_lock; -}; - -static volatile struct clock_data shared_data; - -/** - * Publish a struct clock_data to the volatile global clock data object. - * Caller MUST already hold data_lock - */ -void publish_clock_data(struct clock_data *l) -{ - char *d = (char*)&shared_data; - char *s = (char*)l; - size_t i = 0; - for (i = 0; i < sizeof(struct clock_data); i++) { - d[i] = s[i]; - } - shared_data.is_unread = 1; -} - -/** - * Copy the published struct clock_data to a non-volatile clock data object. - * Caller MUST already hold data_lock - */ -void get_clock_data(struct clock_data *l) -{ - char *d = (char*)l; - char *s = (char*)&shared_data; - size_t i = 0; - for (i = 0; i < sizeof(struct clock_data); i++) { - d[i] = s[i]; - } -} - -/** - * Read clock's statistics from files and push them into shared data area for - * display thread to pick up - */ -void *read_stats(void* unused) -{ - char buffer[32]; - char *next = buffer; - FILE *f = NULL; - struct clock_data l; - memset(&l, 0, sizeof(l)); - - while (1) { - /* Read sunrise, sunset */ - if (f = fopen("/tmp/stats-sun", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - /* format is %d/%d\n, first is used sats, second is total seen */ - if (next = strchr(buffer, ',')) { - *(next++) = '\0'; - next[strcspn(next, "\n\r\t")] = '\0'; - strncpy(l.sunrise_time, buffer, sizeof(l.sunrise_time)); - strncpy(l.sunset_time, next, sizeof(l.sunset_time)); - } - } - fclose(f); - } - - /* Read satellite stats */ - if (f = fopen("/tmp/stats-sats", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - /* format is %d,%d\n, first is used sats, second is total seen */ - if (next = strchr(buffer, '/')) { - *(next++) = '\0'; - l.sat_used = strtod(buffer, NULL); - l.sat_seen = strtod(next, NULL); - } - } - fclose(f); - } - - /* read leap second status file - also helps determine lock */ - if (f = fopen("/tmp/stats-leap", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - buffer[strcspn(buffer, "\n\r\t")] = '\0'; - l.no_gps_lock = !strcmp(buffer, "Not synchronised"); - l.leap_second = strcmp(buffer, "Normal"); - } - fclose(f); - } - - if (f = fopen("/tmp/stats-clock", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - const char *units[] = { "s", "ms", "µs", "ns", "ps", "fs" }; - int i = 0; - double offset = fabs(strtod(buffer, NULL)); - while (offset < 1 && i < sizeof(units)/sizeof(units[0]) - 1) { - i++; - offset *= 1000; - } - l.offset = offset; - strncpy(l.offset_units, units[i], sizeof(l.offset_units)); - } - fclose(f); - } - sem_wait(&data_lock); - publish_clock_data(&l); - sem_post(&data_lock); - sleep(5); - } -} - -const char *get_th_suffix(unsigned int day) -{ - if (11 <= day && day <= 19) { - return "th"; - } else { - switch (day % 10) { - case 1: return "st"; - case 2: return "nd"; - case 3: return "rd"; - default: /* 0, 4-9 */ - return "th"; - } - } -} - -TTF_Font *loadFont(const char *file, int size) -{ - TTF_Font *font = TTF_OpenFont(file, size); - if (!font) { - printf("Error: TTF_OpenFont: %s\n", TTF_GetError()); - return NULL; - } - return font; -} - -void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y){ - //Setup the destination rectangle to be at the position we want - SDL_Rect dst; - dst.x = x; - dst.y = y; - //Query the texture to get its width and height to use - SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); - SDL_RenderCopy(ren, tex, NULL, &dst); -} - - -SDL_Texture* renderText(const char *message, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer) -{ - //We need to first render to a surface as that's what TTF_RenderText - //returns, then load that surface into a texture - SDL_Surface *surf = TTF_RenderUTF8_Blended(font, message, color); - if (!surf){ - printf("Error in TTF_RenderUTF8_Blended\n"); - return NULL; - } - SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf); - if (!texture){ - printf("Error in SDL_CreateTextureFromSurface\n"); - } - //Clean up the surface and font - SDL_FreeSurface(surf); - return texture; -} - -int drawText(const char *text, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer, int x, int y, enum ALIGN_MODE mode) { - /* FIXME does this need better error detection */ - int text_w; - SDL_Texture *image; - image = renderText(text, font, color, renderer); - SDL_QueryTexture(image, NULL, NULL, &text_w, NULL); - - if (mode == ALIGN_MODE_CENTRE) { - x = SCREEN_WIDTH / 2 - text_w / 2; - } else if (mode == ALIGN_MODE_RIGHT) { - x -= text_w; - } - renderTexture(image, renderer, x, y); - SDL_DestroyTexture(image); - return x + (mode == ALIGN_MODE_RIGHT? 0 : 1) * text_w; -} - -int main(void) -{ - struct clock_data l; - - /* initial unread indicator value */ - shared_data.is_unread = 0; - - strncpy(l.sunrise_time, "??:??", sizeof(l.sunrise_time)); - strncpy(l.sunset_time, "??:??", sizeof(l.sunset_time)); - l.sat_seen = 0; - l.sat_used = 0; - l.leap_second = 0; - l.offset = 0; - strncpy(l.offset_units, "?", sizeof(l.offset_units)); - l.no_gps_lock = 1; - - if (sem_init(&data_lock, 0, 1)) { - perror("sem_init"); - return 1; - } - - int stop = 0; - SDL_Event e; - SDL_Window *window; - - SDL_Init(SDL_INIT_VIDEO); - TTF_Init(); - - TTF_Font *mainTimeFont = loadFont("/usr/share/fonts/TTF/RobotoMono-Regular.ttf", 325); - TTF_Font *noLockFont = loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 130); - TTF_Font *secondsFont = loadFont("/usr/share/fonts/TTF/RobotoMono-Regular.ttf", 30); - - TTF_Font *dateFont = loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 50); - TTF_Font *dateSymbolFont = loadFont("/usr/share/fonts/TTF/Symbola.ttf", 50); - - TTF_Font *ntpInfoFont= loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 30); - TTF_Font *ntpSymbolFont = loadFont("/usr/share/fonts/TTF/Symbola.ttf", 30); - if ( !ntpSymbolFont - || !dateSymbolFont - || !mainTimeFont - || !dateFont - || !secondsFont - || !ntpInfoFont) { - return 1; - } - - /* launch pthread */ - pthread_t thread; - if (pthread_create(&thread, NULL, read_stats, NULL) != 0) { - perror("pthread_create"); - return 1; - } - - window = SDL_CreateWindow(WINDOW_TITLE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL); - if (!window) { - printf("Could not create window: %s\n", SDL_GetError()); - return 1; - } - - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (!renderer) { - SDL_DestroyWindow(window); - printf("SDL_CreateRenderer Error\n"); - SDL_Quit(); - return 1; - } - - while (!stop) - { - while (SDL_PollEvent(&e)){ - if ( e.type == SDL_QUIT - || e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_q) { - stop = 1; - } - } - char text[64]; - time_t t; - struct tm *time_s; - - - SDL_Texture *image; - int text_w; - - SDL_RenderClear(renderer); - - t = time(NULL); - if ((time_s = localtime(&t)) == NULL) { - /* FIXME error */ - continue; - } - - int next_x = 0; - - sem_wait(&data_lock); - if (shared_data.is_unread) { - get_clock_data(&l); - shared_data.is_unread = 0; - } - sem_post(&data_lock); - - if (l.sat_seen == 0 || l.sat_used == 0 || l.no_gps_lock) { - drawText("No GPS Lock", noLockFont, COLOUR_WHITE, renderer, 0, NO_LOCK_Y, ALIGN_MODE_CENTRE); - } else { - /* Have GPS lock, go for it */ - /**/ - strftime(text, sizeof(text), "%H%M", time_s); - drawText(text, mainTimeFont, COLOUR_WHITE, renderer, TIME_X, TIME_Y, ALIGN_MODE_CENTRE); - /**/ - - /********************/ - /* Draws a date string, normally like: - * Monday the 25th - * February, 2019 - */ - strftime(text, sizeof(text), "%A", time_s); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, DATE_1_X, DATE_1_Y, ALIGN_MODE_LEFT); - - next_x = drawText(" the ", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); - - snprintf(text, sizeof(text), "%d%s", time_s->tm_mday, get_th_suffix(time_s->tm_mday)); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); - next_x = drawText(".", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); - - strftime(text, sizeof(text), "%B", time_s); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, DATE_2_X, DATE_2_Y, ALIGN_MODE_LEFT); - - next_x = drawText(", ", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_2_Y, ALIGN_MODE_LEFT); - - strftime(text, sizeof(text), "%Y", time_s); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, next_x, DATE_2_Y, ALIGN_MODE_LEFT); - /********************/ - - /**/ - strftime(text, sizeof(text), ":%S", time_s); - next_x = drawText(text, secondsFont, COLOUR_WHITE, renderer, SECONDS_X, SECONDS_Y, ALIGN_MODE_LEFT); - /**/ - - /**/ - next_x = drawText("⏰ ", ntpSymbolFont, COLOUR_40GRAY, renderer, NTP_INFO_X, NTP_INFO_Y, ALIGN_MODE_LEFT); - snprintf(text, sizeof(text), " RMS %d %s%s ", l.offset, l.offset_units, - l.leap_second ? ", Leap second coming!" : ""); - next_x = drawText(text, ntpInfoFont, COLOUR_40GRAY, renderer, next_x, NTP_INFO_Y, ALIGN_MODE_LEFT); - /**/ - - /**/ - next_x = drawText(l.sunrise_time, dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_1_Y, ALIGN_MODE_RIGHT); - next_x = drawText("☀⬆", dateSymbolFont, COLOUR_YELLOW, renderer, next_x, SUN_INFO_1_Y, ALIGN_MODE_RIGHT); - next_x = drawText(l.sunset_time, dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_2_Y, ALIGN_MODE_RIGHT); - next_x = drawText("☀⬇", dateSymbolFont, COLOUR_YELLOW, renderer, next_x, SUN_INFO_2_Y, ALIGN_MODE_RIGHT); - // next_x = drawText("⭡05:45 ↓20:13", dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_Y); - /**/ - } - /**/ - next_x = drawText("🛰 ", ntpSymbolFont, COLOUR_40GRAY, renderer, SAT_INFO_X, SAT_INFO_Y, ALIGN_MODE_LEFT); - snprintf(text, sizeof(text), "%d (%d used)", l.sat_seen, l.sat_used); - next_x = drawText(text, ntpInfoFont, COLOUR_40GRAY, renderer, next_x, NTP_INFO_Y, ALIGN_MODE_LEFT); - /**/ - SDL_RenderPresent(renderer); - SDL_Delay(100); - } - - SDL_DestroyWindow(window); - SDL_Quit(); - return 0; -} - -- cgit v1.1