RaspberrPi project source code
Guo Wenxue
2024-04-11 5b381c80976c76bb7e0d779f1ff878416c93db78
commit | author | age
d6b4a7 1 /*********************************************************************************
G 2  *      Copyright:  (C) 2021 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  led.c
6  *    Description:  This file is used to control RGB 3-colors LED
7  *
8  *
9  * Pin connection:
10  *               RGB Led Module           Raspberry Pi Board
11  *                   R        <----->      #Pin33(BCM GPIO13)
12  *                   G        <----->      #Pin35(BCM GPIO19)
13  *                   B        <----->      #Pin37(BCM GPIO26)
14  *                  GND       <----->      GND
15  *
16  * System install:
17  *                  sudo apt install -y libgpiod-dev gpiod
18  *
19  *
20  ********************************************************************************/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <dirent.h>
27 #include <string.h>
28 #include <time.h>
29 #include <errno.h>
30 #include <signal.h>
31
32 #include <gpiod.h>
33
34 #define DELAY     500
35
36 #define ON        1
37 #define OFF       0
38
39 /* Three LEDs code */
40 enum
41 {
42     LED_R = 0,
43     LED_G,
44     LED_B,
45     LEDCNT,
46 };
47
48 /* Three LEDs hardware information */
49 typedef struct led_info_s
50 {
51     const char         *name;  /* RGB 3-color LED name  */
52     int                 gpio;  /* RGB 3-color LED BCM pin number */
53     int                 active;/* RGB 3-color LED active GPIO level: 0->low 1->high */
54     struct gpiod_line  *line;  /* libgpiod line */
55 } led_info_t;
56
57 static led_info_t    leds_info[LEDCNT] =
58 {
59     {"red",   13, 1, NULL },
60     {"green", 19, 1, NULL },
61     {"blue",  26, 1, NULL },
62 };
63
64 /* Three LEDs API context */
65 typedef struct led_ctx_s
66 {
67     struct gpiod_chip   *chip;
68     led_info_t          *leds;
69     int                  count;
70 } led_ctx_t;
71
72 int init_led(led_ctx_t *ctx);
73 int term_led(led_ctx_t *ctx);
74 int turn_led(led_ctx_t *ctx, int which, int cmd);
75 static inline void msleep(unsigned long ms);
76
77
78 int g_stop = 0;
79
80 void sig_handler(int signum)
81 {
82     switch( signum )
83     {
84         case SIGINT:
85         case SIGTERM:
86             g_stop = 1;
87
88         default:
89             break;
90     }
91
92     return ;
93 }
94
95 int main(int argc, char *argv[])
96 {
97     int                 rv;
98     led_ctx_t           led_ctx =
99     {
100         .chip  = NULL,
101         .leds  = leds_info,
102         .count = LEDCNT,
103     };
104
105     if( (rv=init_led(&led_ctx)) < 0 )
106     {
107         printf("initial leds gpio failure, rv=%d\n", rv);
108         return 1;
109     }
cbbab6 110     printf("initial RGB Led gpios okay\n");
d6b4a7 111
G 112     signal(SIGINT,  sig_handler);
113     signal(SIGTERM, sig_handler);
114
115     while( !g_stop )
116     {
117         turn_led(&led_ctx, LED_R, ON);
118         msleep(DELAY);
119         turn_led(&led_ctx, LED_R, OFF);
120         msleep(DELAY);
121
122         turn_led(&led_ctx, LED_G, ON);
123         msleep(DELAY);
124         turn_led(&led_ctx, LED_G, OFF);
125         msleep(DELAY);
126
127         turn_led(&led_ctx, LED_B, ON);
128         msleep(DELAY);
129         turn_led(&led_ctx, LED_B, OFF);
130         msleep(DELAY);
131     }
132
133     term_led(&led_ctx);
134     return 0;
135 }
136
137 int term_led(led_ctx_t *ctx)
138 {
139     int            i;
140     led_info_t    *led;
141
142     printf("terminate RGB Led gpios\n");
143
144     if( !ctx )
145     {
146         printf("Invalid input arguments\n");
147         return -1;
148     }
149
150     if( !ctx->chip )
151         return 0;
152
153     for(i=0; i<ctx->count; i++)
154     {
155         led = &ctx->leds[i];
156
157         if( led->line )
158             gpiod_line_release(led->line);
159     }
160
161     gpiod_chip_close(ctx->chip);
162     return 0;
163 }
164
165
166 int init_led(led_ctx_t *ctx)
167 {
168     int            i, rv;
169     led_info_t    *led;
170
171     if( !ctx )
172     {
173         printf("Invalid input arguments\n");
174         return -1;
175     }
176
177     ctx->chip = gpiod_chip_open_by_name("gpiochip0");
178     if( !ctx->chip )
179     {
180         printf("open gpiochip failure, maybe you need running as root\n");
181         return -2;
182     }
183
184
185     for(i=0; i<ctx->count; i++)
186     {
187         led = &ctx->leds[i];
188
189         led->line = gpiod_chip_get_line(ctx->chip, led->gpio);
190         if( !led->line )
191         {
192             printf("open gpioline for %s[%d] failed\n", led->name, led->gpio);
193             rv = -3;
194             goto failed;
195         }
196
197         rv  = gpiod_line_request_output(led->line, led->name, !led->active);
198         if( rv )
199         {
200             printf("request gpio output for %5s[%d] failed\n", led->name, led->gpio);
201             rv = -4;
202             goto failed;
203         }
204
205         //printf("request %5s led[%d] for gpio output okay\n", led->name, led->gpio);
206     }
207
208     return 0;
209
210 failed:
211     term_led(ctx);
212     return rv;
213 }
214
215 int turn_led(led_ctx_t *ctx, int which, int cmd)
216 {
217     int            rv = 0;
218     led_info_t    *led;
219
220     if( !ctx || which<0 || which>=ctx->count )
221     {
222         printf("Invalid input arguments\n");
223         return -1;
224     }
225
226     led = &ctx->leds[which];
227
228     if( OFF == cmd )
229     {
230         gpiod_line_set_value(led->line, !led->active);
231     }
232     else
233     {
234         gpiod_line_set_value(led->line, led->active);
235     }
236
237     return 0;
238 }
239
240 static inline void msleep(unsigned long ms)
241 {
242     struct timespec cSleep;
243     unsigned long ulTmp;
244
245     cSleep.tv_sec = ms / 1000;
246     if (cSleep.tv_sec == 0)
247     {
248         ulTmp = ms * 10000;
249         cSleep.tv_nsec = ulTmp * 100;
250     }
251     else
252     {
253         cSleep.tv_nsec = 0;
254     }
255
256     nanosleep(&cSleep, 0);
257
258     return ;
259 }
260