/********************************************************************************* * Copyright: (C) 2021 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 Raspberry Pi Board * R <-----> #Pin33(BCM GPIO13) * G <-----> #Pin35(BCM GPIO19) * B <-----> #Pin37(BCM GPIO26) * GND <-----> GND * * RGB Led Module Raspberry Pi Board * R <-----> #Pin36(BCM GPIO16) * G <-----> #Pin38(BCM GPIO20) * B <-----> #Pin40(BCM GPIO21) * GND <-----> GND * * System install: * sudo apt install -y libgpiod-dev gpiod * * ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #define DELAY 500 #define ON 1 #define OFF 0 /* Three LEDs code */ enum { LED_R = 0, LED_G, LED_B, LEDCNT, }; /* Three LEDs hardware information */ typedef struct led_info_s { const char *name; /* RGB 3-color LED name */ int gpio; /* RGB 3-color LED BCM pin number */ int active;/* RGB 3-color LED active GPIO level: 0->low 1->high */ struct gpiod_line *line; /* libgpiod line */ } led_info_t; #define CONFIG_PIN_333537 //#define CONFIG_PIN_363840 static led_info_t leds_info[LEDCNT] = { #ifdef CONFIG_PIN_333537 {"red", 13, 1, NULL }, {"green", 19, 1, NULL }, {"blue", 26, 1, NULL }, #elif (defined CONFIG_PIN_363840) {"red", 16, 1, NULL }, {"green", 20, 1, NULL }, {"blue", 21, 1, NULL }, #endif }; /* Three LEDs API context */ typedef struct led_ctx_s { struct gpiod_chip *chip; led_info_t *leds; int count; } led_ctx_t; int init_led(led_ctx_t *ctx); int term_led(led_ctx_t *ctx); int turn_led(led_ctx_t *ctx, 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; led_ctx_t led_ctx = { .chip = NULL, .leds = leds_info, .count = LEDCNT, }; if( (rv=init_led(&led_ctx)) < 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(&led_ctx, LED_R, ON); msleep(DELAY); turn_led(&led_ctx, LED_R, OFF); msleep(DELAY); turn_led(&led_ctx, LED_G, ON); msleep(DELAY); turn_led(&led_ctx, LED_G, OFF); msleep(DELAY); turn_led(&led_ctx, LED_B, ON); msleep(DELAY); turn_led(&led_ctx, LED_B, OFF); msleep(DELAY); } term_led(&led_ctx); return 0; } int term_led(led_ctx_t *ctx) { int i; led_info_t *led; printf("terminate RGB Led gpios\n"); if( !ctx ) { printf("Invalid input arguments\n"); return -1; } if( !ctx->chip ) return 0; for(i=0; icount; i++) { led = &ctx->leds[i]; if( led->line ) gpiod_line_release(led->line); } gpiod_chip_close(ctx->chip); return 0; } int init_led(led_ctx_t *ctx) { int i, rv; led_info_t *led; if( !ctx ) { printf("Invalid input arguments\n"); return -1; } ctx->chip = gpiod_chip_open_by_name("gpiochip0"); if( !ctx->chip ) { printf("open gpiochip failure, maybe you need running as root\n"); return -2; } for(i=0; icount; i++) { led = &ctx->leds[i]; led->line = gpiod_chip_get_line(ctx->chip, led->gpio); if( !led->line ) { printf("open gpioline for %s[%d] failed\n", led->name, led->gpio); rv = -3; goto failed; } rv = gpiod_line_request_output(led->line, led->name, !led->active); if( rv ) { printf("request gpio output for %5s[%d] failed\n", led->name, led->gpio); rv = -4; goto failed; } //printf("request %5s led[%d] for gpio output okay\n", led->name, led->gpio); } return 0; failed: term_led(ctx); return rv; } int turn_led(led_ctx_t *ctx, int which, int cmd) { int rv = 0; led_info_t *led; if( !ctx || which<0 || which>=ctx->count ) { printf("Invalid input arguments\n"); return -1; } led = &ctx->leds[which]; if( OFF == cmd ) { gpiod_line_set_value(led->line, !led->active); } else { gpiod_line_set_value(led->line, led->active); } 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 ; }