Add support for blanking the screen
This commit is contained in:
		
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							| @ -7,7 +7,7 @@ LD=clang | |||||||
| LDFLAGS=-lgpio -lfigpar -lpthread ${SQLITE3_LDFLAGS} | LDFLAGS=-lgpio -lfigpar -lpthread ${SQLITE3_LDFLAGS} | ||||||
| SRCS=src/main.c src/util.c src/lcd.c src/ths.c src/button.c src/ui/screen.c\ | SRCS=src/main.c src/util.c src/lcd.c src/ths.c src/button.c src/ui/screen.c\ | ||||||
|      src/ui/datesel.c src/ui/statsby.c src/ui/datapoints.c src/ui/timesel.c\ |      src/ui/datesel.c src/ui/statsby.c src/ui/datapoints.c src/ui/timesel.c\ | ||||||
|      src/ui/statrange.c src/config.c |      src/ui/statrange.c src/config.c src/ui/blankscreen.c | ||||||
| PROG=rpi4b-temp-humidity | PROG=rpi4b-temp-humidity | ||||||
|  |  | ||||||
| OBJS=${SRCS:C/^src/bin/:C/.c$/.o/} | OBJS=${SRCS:C/^src/bin/:C/.c$/.o/} | ||||||
| @ -38,6 +38,7 @@ bin/main.o bin/config.o: src/config.h | |||||||
| bin/main.o bin/button.o bin/ui/screen.o: src/button.h | bin/main.o bin/button.o bin/ui/screen.o: src/button.h | ||||||
| bin/main.o bin/ui/statsby.o: src/ui/statsby.h | bin/main.o bin/ui/statsby.o: src/ui/statsby.h | ||||||
| bin/main.o bin/ui/datapoints.o: src/ui/datapoints.h | bin/main.o bin/ui/datapoints.o: src/ui/datapoints.h | ||||||
|  | bin/main.o bin/ui/blankscreen.o: src/ui/blankscreen.h | ||||||
| bin/main.o bin/ui/statrange.o: src/ui/statrange.h | bin/main.o bin/ui/statrange.o: src/ui/statrange.h | ||||||
|  |  | ||||||
| .if "${DEFAULT_TEMP_UNIT}" != "F" && "${DEFAULT_TEMP_UNIT}" != "C" &&\ | .if "${DEFAULT_TEMP_UNIT}" != "F" && "${DEFAULT_TEMP_UNIT}" != "C" &&\ | ||||||
|  | |||||||
							
								
								
									
										29
									
								
								src/config.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/config.c
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * config.h - Config file parsing |  * config.c - Config file parsing | ||||||
|  * Copyright (C) 2024  Alexander Rosenberg |  * Copyright (C) 2024  Alexander Rosenberg | ||||||
|  * |  * | ||||||
|  * This program is free software: you can redistribute it and/or modify it under |  * This program is free software: you can redistribute it and/or modify it under | ||||||
| @ -29,17 +29,32 @@ static int unknown_key_callback(struct figpar_config *opt, uint32_t line, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int parse_int_callback(struct figpar_config *opt, uint32_t line, | ||||||
|  |                                char *directive, char *value) { | ||||||
|  |     char last_char; | ||||||
|  |     if (sscanf(value, "%" SCNi32 " %c", &opt->value.num, &last_char) < 1 || | ||||||
|  |         (last_char && !isdigit(last_char))) { | ||||||
|  |         warnx("line %" PRIu32 ": not a valid number \"%s\"", line, value); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     LOG_VERBOSE("Loaded config int option: %s = %" PRIi32 "\n", directive, | ||||||
|  |                 opt->value.num); | ||||||
|  |     opt->type = FIGPAR_TYPE_INT; | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int parse_uint_callback(struct figpar_config *opt, uint32_t line, | static int parse_uint_callback(struct figpar_config *opt, uint32_t line, | ||||||
|                                char *directive, char *value) { |                                char *directive, char *value) { | ||||||
|     char last_char; |     char last_char; | ||||||
|     if (sscanf(value, "%" SCNu32 " %c", &opt->value.u_num, &last_char) < 1 || |     if (sscanf(value, "%" SCNu32 " %c", &opt->value.u_num, &last_char) < 1 || | ||||||
|         (last_char && !isdigit(last_char))) { |         (last_char && !isdigit(last_char))) { | ||||||
|         warnx("line %" PRIu32 ": not a valid number \"%s\"", line, value); |         warnx("line %" PRIu32 ": not a valid unsigned number \"%s\"", line, | ||||||
|  |               value); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     LOG_VERBOSE("Loaded config uint option: %s = %" PRIu32 "\n", directive, |     LOG_VERBOSE("Loaded config uint option: %s = %" PRIu32 "\n", directive, | ||||||
|                 opt->value.u_num); |                 opt->value.u_num); | ||||||
|     opt->type = FIGPAR_TYPE_INT; |     opt->type = FIGPAR_TYPE_UINT; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -183,6 +198,8 @@ static void set_options_from_entries(struct figpar_config *entries, | |||||||
|     GLOBAL_OPTS.back_pin = entries[14].value.u_num; |     GLOBAL_OPTS.back_pin = entries[14].value.u_num; | ||||||
|  |  | ||||||
|     GLOBAL_OPTS.temp_unit = entries[15].value.num; |     GLOBAL_OPTS.temp_unit = entries[15].value.num; | ||||||
|  |  | ||||||
|  |     GLOBAL_OPTS.bl_pin = entries[16].value.num; | ||||||
| } | } | ||||||
|  |  | ||||||
| static char *strdup_default_opt(const char *def) { | static char *strdup_default_opt(const char *def) { | ||||||
| @ -283,6 +300,12 @@ void parse_config_file(const char *path) { | |||||||
|             .action = parse_temp_unit_callback, |             .action = parse_temp_unit_callback, | ||||||
|             .value = {.num = DEFAULT_TEMP_UNIT} |             .value = {.num = DEFAULT_TEMP_UNIT} | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             .directive = "bl_pin", | ||||||
|  |             .type = FIGPAR_TYPE_INT, | ||||||
|  |             .action = parse_int_callback, | ||||||
|  |             .value = {.num = -1} | ||||||
|  |         }, | ||||||
|         { .directive = NULL }, |         { .directive = NULL }, | ||||||
|     }; |     }; | ||||||
|     size_t entry_count = sizeof(entries) / sizeof(struct figpar_config); |     size_t entry_count = sizeof(entries) / sizeof(struct figpar_config); | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								src/lcd.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/lcd.c
									
									
									
									
									
								
							| @ -47,9 +47,11 @@ static void lcd_pulse_enable(LCD *lcd) { | |||||||
|  |  | ||||||
| LCD *lcd_open(gpio_handle_t handle, gpio_pin_t rs, gpio_pin_t rw, gpio_pin_t en, | LCD *lcd_open(gpio_handle_t handle, gpio_pin_t rs, gpio_pin_t rw, gpio_pin_t en, | ||||||
|               gpio_pin_t d0, gpio_pin_t d1, gpio_pin_t d2, gpio_pin_t d3, |               gpio_pin_t d0, gpio_pin_t d1, gpio_pin_t d2, gpio_pin_t d3, | ||||||
|               gpio_pin_t d4, gpio_pin_t d5, gpio_pin_t d6, gpio_pin_t d7) { |               gpio_pin_t d4, gpio_pin_t d5, gpio_pin_t d6, gpio_pin_t d7, | ||||||
|  |               int32_t bl) { | ||||||
|     LOG_VERBOSE("Initializing LCD: rs=%d, rw=%d, en=%d, d={%d, %d, %d, %d, %d, " |     LOG_VERBOSE("Initializing LCD: rs=%d, rw=%d, en=%d, d={%d, %d, %d, %d, %d, " | ||||||
|                 "%d, %d, %d}\n", rs, rw, en, d0, d1, d2, d3, d4, d5, d6, d7); |                 "%d, %d, %d}, bl=%d\n", rs, rw, en, d0, d1, d2, d3, d4, d5, d6, | ||||||
|  |                 d7, bl); | ||||||
|     LCD *lcd = malloc_checked(sizeof(LCD)); |     LCD *lcd = malloc_checked(sizeof(LCD)); | ||||||
|     lcd->handle = handle; |     lcd->handle = handle; | ||||||
|     lcd->rs = rs; |     lcd->rs = rs; | ||||||
| @ -63,13 +65,18 @@ LCD *lcd_open(gpio_handle_t handle, gpio_pin_t rs, gpio_pin_t rw, gpio_pin_t en, | |||||||
|     lcd->d5 = d5; |     lcd->d5 = d5; | ||||||
|     lcd->d6 = d6; |     lcd->d6 = d6; | ||||||
|     lcd->d7 = d7; |     lcd->d7 = d7; | ||||||
|  |     lcd->bl = bl; | ||||||
|     gpio_pin_output(lcd->handle, lcd->rw); |     gpio_pin_output(lcd->handle, lcd->rw); | ||||||
|     gpio_pin_output(lcd->handle, lcd->en); |     gpio_pin_output(lcd->handle, lcd->en); | ||||||
|     gpio_pin_output(lcd->handle, lcd->rs); |     gpio_pin_output(lcd->handle, lcd->rs); | ||||||
|  |     if (lcd->bl >= 0) { | ||||||
|  |         gpio_pin_output(lcd->handle, lcd->bl); | ||||||
|  |     } | ||||||
|     lcd_clear(lcd); |     lcd_clear(lcd); | ||||||
|     lcd_call(lcd, 0, 0, 0, 0, 1, 1, 1, 0, 0); // 5x8 font, 2 lines, 8bit |     lcd_call(lcd, 0, 0, 0, 0, 1, 1, 1, 0, 0); // 5x8 font, 2 lines, 8bit | ||||||
|     lcd_entry_mode(lcd, LCD_INCREMENT, LCD_CURSOR_MOVE); |     lcd_entry_mode(lcd, LCD_INCREMENT, LCD_CURSOR_MOVE); | ||||||
|     lcd_display_control(lcd, LCD_CURSOR_NO_BLINK, LCD_CURSOR_OFF, LCD_DISPLAY_ON); |     lcd_display_control(lcd, LCD_CURSOR_NO_BLINK, LCD_CURSOR_OFF, LCD_DISPLAY_ON); | ||||||
|  |     lcd_backlight_set_enabled(lcd, true); | ||||||
|     LOG_VERBOSE("LCD Initialization done\n"); |     LOG_VERBOSE("LCD Initialization done\n"); | ||||||
|     return lcd; |     return lcd; | ||||||
| } | } | ||||||
| @ -145,3 +152,9 @@ bool lcd_is_busy(LCD *lcd) { | |||||||
|     usleep(1); |     usleep(1); | ||||||
|     return busy; |     return busy; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void lcd_backlight_set_enabled(LCD *lcd, bool enable) { | ||||||
|  |     if (lcd->bl > 0) { | ||||||
|  |         gpio_pin_set(lcd->handle, lcd->bl, enable); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/lcd.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/lcd.h
									
									
									
									
									
								
							| @ -28,6 +28,7 @@ typedef struct { | |||||||
|     gpio_pin_t d5; |     gpio_pin_t d5; | ||||||
|     gpio_pin_t d6; |     gpio_pin_t d6; | ||||||
|     gpio_pin_t d7; |     gpio_pin_t d7; | ||||||
|  |     int32_t bl; | ||||||
|  |  | ||||||
|     // gpio_value_ternal use |     // gpio_value_ternal use | ||||||
|     bool is_read; |     bool is_read; | ||||||
| @ -37,12 +38,14 @@ typedef struct { | |||||||
|  * Allocate and initialize a new LCD object and return a pogpio_value_ter to it. HANDLE |  * Allocate and initialize a new LCD object and return a pogpio_value_ter to it. HANDLE | ||||||
|  * is a gpio_handle_t, each of the other arguments corresponds to the GPIO pin |  * is a gpio_handle_t, each of the other arguments corresponds to the GPIO pin | ||||||
|  * number that the given controller pin is connected to: "register select", |  * number that the given controller pin is connected to: "register select", | ||||||
|  * "read-write", "enable", and data pins 0-7. |  * "read-write", "enable", and data pins 0-7. If BL is 0 or greater, it is a pin | ||||||
|  |  *  that will enable the backlight when HIGH, and disable the backlight when LOW. | ||||||
|  * Return: the newly created object. |  * Return: the newly created object. | ||||||
|  */ |  */ | ||||||
| LCD *lcd_open(gpio_handle_t handle, gpio_pin_t rs, gpio_pin_t rw, gpio_pin_t en, | LCD *lcd_open(gpio_handle_t handle, gpio_pin_t rs, gpio_pin_t rw, gpio_pin_t en, | ||||||
|               gpio_pin_t d0, gpio_pin_t d1, gpio_pin_t d2, gpio_pin_t d3, |               gpio_pin_t d0, gpio_pin_t d1, gpio_pin_t d2, gpio_pin_t d3, | ||||||
|               gpio_pin_t d4, gpio_pin_t d5, gpio_pin_t d6, gpio_pin_t d7); |               gpio_pin_t d4, gpio_pin_t d5, gpio_pin_t d6, gpio_pin_t d7, | ||||||
|  |               int32_t bl); | ||||||
| /* | /* | ||||||
|  * Close LCD by freeing any resources associated with it. |  * Close LCD by freeing any resources associated with it. | ||||||
|  */ |  */ | ||||||
| @ -106,4 +109,9 @@ void lcd_cursor_shift(LCD *lcd, gpio_value_t sc, gpio_value_t rl); | |||||||
|  */ |  */ | ||||||
| bool lcd_is_busy(LCD *lcd); | bool lcd_is_busy(LCD *lcd); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Set the backlight's power to ENABLE. | ||||||
|  |  */ | ||||||
|  | void lcd_backlight_set_enabled(LCD *lcd, bool enable); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -17,6 +17,7 @@ | |||||||
| #include "ui/statsby.h" | #include "ui/statsby.h" | ||||||
| #include "ui/datapoints.h" | #include "ui/datapoints.h" | ||||||
| #include "ui/statrange.h" | #include "ui/statrange.h" | ||||||
|  | #include "ui/blankscreen.h" | ||||||
|  |  | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <err.h> | #include <err.h> | ||||||
| @ -88,7 +89,7 @@ int main(int argc, char *const *argv) { | |||||||
|                         GLOBAL_OPTS.data_pins[1], GLOBAL_OPTS.data_pins[2], |                         GLOBAL_OPTS.data_pins[1], GLOBAL_OPTS.data_pins[2], | ||||||
|                         GLOBAL_OPTS.data_pins[3], GLOBAL_OPTS.data_pins[4], |                         GLOBAL_OPTS.data_pins[3], GLOBAL_OPTS.data_pins[4], | ||||||
|                         GLOBAL_OPTS.data_pins[5], GLOBAL_OPTS.data_pins[6], |                         GLOBAL_OPTS.data_pins[5], GLOBAL_OPTS.data_pins[6], | ||||||
|                         GLOBAL_OPTS.data_pins[7]); |                         GLOBAL_OPTS.data_pins[7], GLOBAL_OPTS.bl_pin); | ||||||
|     setup_signals(); |     setup_signals(); | ||||||
|     open_database(); |     open_database(); | ||||||
|     initialize_util_queries(DATABASE); |     initialize_util_queries(DATABASE); | ||||||
| @ -104,6 +105,7 @@ int main(int argc, char *const *argv) { | |||||||
|     screen_manager_add(screen_manager, (Screen *) stats_by_screen_new()); |     screen_manager_add(screen_manager, (Screen *) stats_by_screen_new()); | ||||||
|     screen_manager_add(screen_manager, (Screen *) data_points_screen_new()); |     screen_manager_add(screen_manager, (Screen *) data_points_screen_new()); | ||||||
|     screen_manager_add(screen_manager, (Screen *) stat_range_screen_new()); |     screen_manager_add(screen_manager, (Screen *) stat_range_screen_new()); | ||||||
|  |     screen_manager_add(screen_manager, blank_screen_new()); | ||||||
|     while (RUNNING) { |     while (RUNNING) { | ||||||
|         lock_stat_globals(); |         lock_stat_globals(); | ||||||
|         uint32_t temp = LAST_TEMP; |         uint32_t temp = LAST_TEMP; | ||||||
|  | |||||||
							
								
								
									
										34
									
								
								src/ui/blankscreen.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/ui/blankscreen.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | /* | ||||||
|  |  * blankscreen.c - Screen that disables the display | ||||||
|  |  * Copyright (C) 2024  Alexander Rosenberg | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License as published by the Free Software | ||||||
|  |  * Foundation, either version 3 of the License, or (at your option) any later | ||||||
|  |  * version. See the LICENSE file for more information. | ||||||
|  |  */ | ||||||
|  | #include "blankscreen.h" | ||||||
|  |  | ||||||
|  | static bool blank_screen_dispatch(Screen *screen, | ||||||
|  |                                   SensorState *state) { | ||||||
|  |     if (state->back_down || state->sel_down || state->up_down || | ||||||
|  |         state->down_down) { | ||||||
|  |         lcd_display_control(state->lcd, LCD_CURSOR_NO_BLINK, LCD_CURSOR_OFF, | ||||||
|  |                             LCD_DISPLAY_ON); | ||||||
|  |         lcd_backlight_set_enabled(state->lcd, true); | ||||||
|  |         return true; | ||||||
|  |     } else if (state->force_draw) { | ||||||
|  |         lcd_display_control(state->lcd, LCD_CURSOR_NO_BLINK, LCD_CURSOR_OFF, | ||||||
|  |                             LCD_DISPLAY_OFF); | ||||||
|  |         lcd_backlight_set_enabled(state->lcd, false); | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Screen *blank_screen_new() { | ||||||
|  |     Screen *s = malloc_checked(sizeof(Screen)); | ||||||
|  |     screen_init(s, "Blank Display", | ||||||
|  |                 (ScreenDispatchFunc) blank_screen_dispatch, | ||||||
|  |                 (ScreenCleanupFunc) free); | ||||||
|  |     return s; | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								src/ui/blankscreen.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/ui/blankscreen.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | /* | ||||||
|  |  * blankscreen.h - Screen that disables the display | ||||||
|  |  * Copyright (C) 2024  Alexander Rosenberg | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License as published by the Free Software | ||||||
|  |  * Foundation, either version 3 of the License, or (at your option) any later | ||||||
|  |  * version. See the LICENSE file for more information. | ||||||
|  |  */ | ||||||
|  | #ifndef INCLUDED_BLANKSCREEN_H | ||||||
|  | #define INCLUDED_BLANKSCREEN_H | ||||||
|  |  | ||||||
|  | #include "screen.h" | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Create a new blank screen that will simply disable the display. | ||||||
|  |  */ | ||||||
|  | Screen *blank_screen_new(void); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @ -34,6 +34,7 @@ typedef struct { | |||||||
|     gpio_pin_t rs_pin; |     gpio_pin_t rs_pin; | ||||||
|     gpio_pin_t rw_pin; |     gpio_pin_t rw_pin; | ||||||
|     gpio_pin_t data_pins[8]; |     gpio_pin_t data_pins[8]; | ||||||
|  |     gpio_pin_t bl_pin; | ||||||
|     char *database_location; // location of sqlite3 database |     char *database_location; // location of sqlite3 database | ||||||
|     char *temp_key; // sysctl key for temperature |     char *temp_key; // sysctl key for temperature | ||||||
|     char *humid_key; // sysctl key for humidity |     char *humid_key; // sysctl key for humidity | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user