From 1e563e2b731d928942f43e1341c8c50b0faf1c01 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Fri, 31 May 2024 11:39:31 +0800 Subject: [PATCH] APPS:IGKBoard-IMX6ULL: Add test-apps source code: --- drivers/test-apps/leds.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 332 insertions(+), 0 deletions(-) diff --git a/drivers/test-apps/leds.c b/drivers/test-apps/leds.c new file mode 100644 index 0000000..1918a0b --- /dev/null +++ b/drivers/test-apps/leds.c @@ -0,0 +1,332 @@ +/********************************************************************************* + * Copyright: (C) 2024 LingYun IoT System Studio + * All rights reserved. + * + * Filename: led.c + * Description: This file is used to control RGB 3-colors LED + * + * + * Pin connection: + * RGB Led Module IGKBoard + * R <-----> #Pin33 + * G <-----> #Pin35 + * B <-----> #Pin37 + * GND <-----> GND + * + ********************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <signal.h> + +#include <gpiod.h> + +#define DELAY 300 + +#define ON 1 +#define OFF 0 + +/* Three LEDs number */ +enum +{ + LED_R = 0, + LED_G, + LED_B, + LEDCNT, +}; + +enum +{ + ACTIVE_HIGH, /* High level will turn led on */ + ACTIVE_LOW, /* Low level will turn led on */ +}; + +/* Three LEDs hardware information */ +typedef struct led_s +{ + const char *name; /* RGB 3-color LED name */ + int chip_num; /* RGB 3-color LED connect chip */ + int gpio_num; /* RGB 3-color LED connect line */ + int active; /* RGB 3-color LED active level */ + struct gpiod_line_request *request; /* libgpiod gpio request handler */ +} led_t; + +static led_t leds_info[LEDCNT] = +{ + {"red", 0, 23, ACTIVE_HIGH, NULL }, /* GPIO1_IO23 on chip0 line 23, active high */ + {"green", 4, 1, ACTIVE_HIGH, NULL }, /* GPIO5_IO01 on chip4 line 1, active high */ + {"blue", 4, 8, ACTIVE_HIGH, NULL }, /* GPIO5_IO08 on chip4 line 8, active high */ +}; + +/* Three LEDs API context */ +typedef struct leds_s +{ + led_t *leds; /* led pointer to leds_info */ + int count; /* led count */ +} leds_t; + + +/* function declaration */ +int init_led(leds_t *leds); +int term_led(leds_t *leds); +int turn_led(leds_t *leds, int which, int cmd); +static inline void msleep(unsigned long ms); + + +int g_stop = 0; + +void sig_handler(int signum) +{ + switch( signum ) + { + case SIGINT: + case SIGTERM: + g_stop = 1; + + default: + break; + } + + return ; +} + +int main(int argc, char *argv[]) +{ + int rv; + leds_t leds = + { + .leds = leds_info, + .count = LEDCNT, + }; + + if( (rv=init_led(&leds)) < 0 ) + { + printf("initial leds gpio failure, rv=%d\n", rv); + return 1; + } + printf("initial RGB Led gpios okay\n"); + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + while( !g_stop ) + { + turn_led(&leds, LED_R, ON); + msleep(DELAY); + turn_led(&leds, LED_R, OFF); + msleep(DELAY); + + turn_led(&leds, LED_G, ON); + msleep(DELAY); + turn_led(&leds, LED_G, OFF); + msleep(DELAY); + + turn_led(&leds, LED_B, ON); + msleep(DELAY); + turn_led(&leds, LED_B, OFF); + msleep(DELAY); + } + + term_led(&leds); + return 0; +} + +int term_led(leds_t *leds) +{ + int i; + led_t *led; + + printf("terminate RGB Led gpios\n"); + + if( !leds ) + { + printf("Invalid input arguments\n"); + return -1; + } + + for(i=0; i<leds->count; i++) + { + led = &leds->leds[i]; + + if( led->request ) + { + turn_led(leds, i, OFF); + gpiod_line_request_release(led->request); + } + } + + return 0; +} + + +int init_led(leds_t *leds) +{ + led_t *led; + int i, rv = 0; + char chip_dev[32]; + struct gpiod_chip *chip; /* gpio chip */ + struct gpiod_line_settings *settings; /* gpio direction, bias, active_low, value */ + struct gpiod_line_config *line_cfg; /* gpio line */ + struct gpiod_request_config *req_cfg; /* gpio consumer, it can be NULL */ + + + if( !leds ) + { + printf("Invalid input arguments\n"); + return -1; + } + + + /* defined in libgpiod-2.0/lib/line-settings.c: + + struct gpiod_line_settings { + enum gpiod_line_direction direction; + enum gpiod_line_edge edge_detection; + enum gpiod_line_drive drive; + enum gpiod_line_bias bias; + bool active_low; + enum gpiod_line_clock event_clock; + long debounce_period_us; + enum gpiod_line_value output_value; + }; + */ + settings = gpiod_line_settings_new(); + if (!settings) + { + printf("unable to allocate line settings\n"); + rv = -2; + goto cleanup; + } + + /* defined in libgpiod-2.0/lib/line-config.c + + struct gpiod_line_config { + struct per_line_config line_configs[LINES_MAX]; + size_t num_configs; + enum gpiod_line_value output_values[LINES_MAX]; + size_t num_output_values; + struct settings_node *sref_list; + }; + */ + + line_cfg = gpiod_line_config_new(); + if (!line_cfg) + { + printf("unable to allocate the line config structure"); + rv = -2; + goto cleanup; + } + + + /* defined in libgpiod-2.0/lib/request-config.c: + + struct gpiod_request_config { + char consumer[GPIO_MAX_NAME_SIZE]; + size_t event_buffer_size; + }; + */ + req_cfg = gpiod_request_config_new(); + if (!req_cfg) + { + printf("unable to allocate the request config structure"); + rv = -2; + goto cleanup; + } + + for(i=0; i<leds->count; i++) + { + led = &leds->leds[i]; + + snprintf(chip_dev, sizeof(chip_dev), "/dev/gpiochip%d", led->chip_num); + chip = gpiod_chip_open(chip_dev); + if( !chip ) + { + printf("open gpiochip failure, maybe you need running as root\n"); + rv = -3; + goto cleanup; + } + + /* Set as output direction, active low and default level as inactive */ + gpiod_line_settings_reset(settings); + gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT); + gpiod_line_settings_set_active_low(settings, led->active); + gpiod_line_settings_set_output_value(settings, GPIOD_LINE_VALUE_INACTIVE); + + /* set gpio line */ + gpiod_line_config_reset(line_cfg); + gpiod_line_config_add_line_settings(line_cfg, &led->gpio_num, 1, settings); + + /* Can be NULL for default settings. */ + gpiod_request_config_set_consumer(req_cfg, led->name); + + /* Request a set of lines for exclusive usage. */ + led->request = gpiod_chip_request_lines(chip, req_cfg, line_cfg); + + gpiod_chip_close(chip); + //printf("request %5s led[%d] for gpio output okay\n", led->name, led->gpio); + } + +cleanup: + + if( rv< 0 ) + term_led(leds); + + if( line_cfg ) + gpiod_line_config_free(line_cfg); + + if( req_cfg ) + gpiod_request_config_free(req_cfg); + + if( settings ) + gpiod_line_settings_free(settings); + + return rv; +} + +int turn_led(leds_t *leds, int which, int cmd) +{ + led_t *led; + int rv = 0; + int value = 0; + + if( !leds || which<0 || which>=leds->count ) + { + printf("Invalid input arguments\n"); + return -1; + } + + led = &leds->leds[which]; + + value = OFF==cmd ? GPIOD_LINE_VALUE_INACTIVE : GPIOD_LINE_VALUE_ACTIVE; + + gpiod_line_request_set_value(led->request, led->gpio_num, value); + + return 0; +} + +static inline void msleep(unsigned long ms) +{ + struct timespec cSleep; + unsigned long ulTmp; + + cSleep.tv_sec = ms / 1000; + if (cSleep.tv_sec == 0) + { + ulTmp = ms * 10000; + cSleep.tv_nsec = ulTmp * 100; + } + else + { + cSleep.tv_nsec = 0; + } + + nanosleep(&cSleep, 0); + + return ; +} -- Gitblit v1.9.1