From be98d13782b05e7659f601980ef695a493d6bee1 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Wed, 21 Aug 2024 17:29:28 +0800
Subject: [PATCH] Add infrared source code

---
 hal/api/led.h      |    8 -
 hal/api/infrared.h |   60 ++++++++
 hal/api/relay.c    |    6 
 hal/api/relay.h    |    7 -
 hal/api/infrared.c |  307 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 371 insertions(+), 17 deletions(-)

diff --git a/hal/api/infrared.c b/hal/api/infrared.c
new file mode 100644
index 0000000..6aa2e36
--- /dev/null
+++ b/hal/api/infrared.c
@@ -0,0 +1,307 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2024 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  infrared.h
+ *    Description:  This file is HC-SR501 infrared sensor code
+ *
+ * Pin connection:
+ *               HC-SR501 Module          IGKBoard-IMX6ULL
+ *                  VCC       <----->      5V
+ *                  I/O       <----->      #Pin22(GPIO3_IO23)
+ *                  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 <getopt.h>
+#include <libgen.h>
+
+#include "infrared.h"
+
+int g_stop = 0;
+
+static inline void msleep(unsigned long ms);
+void sig_handler(int signum);
+
+static void program_usage(const char *progname)
+{
+    printf("Usage: %s [OPTION]...\n", progname);
+    printf(" This is infrared detect program. \n");
+
+    printf(" -d[device  ]  Specify infrared device, such as 0\n");
+    printf(" -h[help    ]  Display this help information\n");
+
+    printf("\n");
+    printf("%s program Version v1.0.0\n", progname);
+    printf("Copyright (C) 2023 LingYun IoT System Studio.\n");
+
+    return;
+}
+
+int main(int argc, char **argv)
+{
+    char           *progname=NULL;
+    int             rv;
+    int             which = -1;
+
+    struct option long_options[] = {
+        {"device", required_argument, NULL, 'd'},
+        {"help", no_argument, NULL, 'h'},
+        {NULL, 0, NULL, 0}
+    };
+
+    progname = basename(argv[0]);
+
+    /* Parser the command line parameters */
+    while ((rv = getopt_long(argc, argv, "d:h", long_options, NULL)) != -1)
+    {
+        switch (rv)
+        {
+            case 'd': /*  Set infrared number, such as 0...max */
+                which = atoi(optarg);
+                break;
+
+
+            case 'h':  /* Get help information */
+                program_usage(progname);
+                return 0;
+
+            default:
+                break;
+        }
+    }
+
+    if( (rv=init_infrared()) < 0 )
+    {
+        printf("initial infrared gpio failure, rv=%d\n", rv);
+        return 1;
+    }
+
+    signal(SIGINT,  sig_handler);
+    signal(SIGTERM, sig_handler);
+
+    while( !g_stop )
+    {
+        rv = detect_infrared(which);
+        printf("Infrared[%d] monitor: %s\n", which, rv ? "Someone is closing!":"No one nearby!");
+        sleep(1);
+    }
+
+    term_infrared();
+    return 0;
+}
+
+/*+-------------------------------------+
+ *| Infrared API based on libgpiod v2.0 |
+ *+-------------------------------------+*/
+
+static infrared_t ir_info[IR_CNT] =
+{
+    {"IR1",   2, 23, IR_ACTIVE_HIGH, NULL}, /* #Pin22, GPIO3_IO23 on chip2 line 23, active high */
+};
+
+/* infrareds context */
+static infrareds_t infrareds =
+{
+    .infrareds  = ir_info,
+    .count = IR_CNT,
+};
+
+int init_infrared(void)
+{
+    infrared_t                  *infrared;
+    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 */
+
+    /* 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<infrareds.count; i++)
+    {
+        infrared = &infrareds.infrareds[i];
+
+        snprintf(chip_dev, sizeof(chip_dev), "/dev/gpiochip%d", infrared->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 input direction */
+        gpiod_line_settings_reset(settings);
+        gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
+
+        /* set gpio line */
+        gpiod_line_config_reset(line_cfg);
+        gpiod_line_config_add_line_settings(line_cfg, &infrared->gpio_num, 1, settings);
+
+        /* Can be NULL for default settings. */
+        gpiod_request_config_set_consumer(req_cfg, infrared->name);
+
+        /* Request a set of lines for exclusive usage. */
+        infrared->request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+
+        gpiod_chip_close(chip);
+        //printf("request %5s infrared[%d] for gpio output okay\n", infrared->name, infrared->gpio);
+    }
+
+cleanup:
+
+    if( rv< 0 )
+        term_infrared();
+
+    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 term_infrared(void)
+{
+    infrared_t     *infrared;
+    int             i;
+
+    printf("terminate infrared gpios\n");
+
+    for(i=0; i<infrareds.count; i++)
+    {
+        infrared = &infrareds.infrareds[i];
+
+        if( infrared->request )
+        {
+            gpiod_line_request_release(infrared->request);
+        }
+    }
+
+    return 0;
+}
+
+int detect_infrared(int which)
+{
+    int            rv = 0;
+    infrared_t    *infrared;
+
+    if( which<0 || which>=infrareds.count )
+    {
+        printf("Invalid input arguments\n");
+        return 0;
+    }
+
+    infrared = &infrareds.infrareds[which];
+
+    return gpiod_line_request_get_value(infrared->request, infrared->gpio_num)==infrared->active ? 1 : 0;
+}
+
+/*+-------------------------------+
+ *|      Misc functions API       |
+ *+-------------------------------+*/
+
+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 ;
+}
+
+void sig_handler(int signum)
+{
+    switch( signum )
+    {
+        case SIGINT:
+        case SIGTERM:
+            g_stop = 1;
+
+        default:
+            break;
+    }
+
+    return ;
+}
+
diff --git a/hal/api/infrared.h b/hal/api/infrared.h
new file mode 100644
index 0000000..fb57c8e
--- /dev/null
+++ b/hal/api/infrared.h
@@ -0,0 +1,60 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2024 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  infrared.h
+ *    Description:  This file is HC-SR501 infrared sensor code
+ *
+ * Pin connection:
+ *               HC-SR501 Module          IGKBoard-IMX6ULL
+ *                  VCC       <----->      5V
+ *                  I/O       <----->      #Pin37(GPIO5_IO09)
+ *                  GND       <----->      GND
+ *
+ ********************************************************************************/
+
+#ifndef  _INFRARED_H_
+#define  _INFRARED_H_
+
+#include "gpiod.h"
+
+/* infrared number */
+enum
+{
+    IR1 = 0,
+    IR_CNT,
+};
+
+enum
+{
+    IR_ACTIVE_LOW,  /* Low level active */
+    IR_ACTIVE_HIGH, /* High level active */
+};
+
+/* infrared hardware information */
+typedef struct infrared_s
+{
+    const char               *name;      /* infrared name  */
+    int                       chip_num;  /* infrared connect chip */
+    int                       gpio_num;  /* infrared connect line */
+    int                       active;    /* infrared active level */
+    struct gpiod_line_request *request;  /* libgpiod gpio request handler */
+} infrared_t;
+
+/* infrared structure */
+typedef struct infrareds_s
+{
+    infrared_t          *infrareds;/* infrared pointer to infrareds_info */
+    int                  count; /* infrared count */
+} infrareds_t;
+
+/* initial infrareds */
+int init_infrared(void);
+
+/* terminate infrareds   */
+int term_infrared(void);
+
+/* detect infrareds */
+int detect_infrared(int which);
+
+#endif
diff --git a/hal/api/led.h b/hal/api/led.h
index 4f2937c..f2105ad 100644
--- a/hal/api/led.h
+++ b/hal/api/led.h
@@ -5,14 +5,6 @@
  *       Filename:  led.h
  *    Description:  This file is used to control RGB 3-colors LED
  *
- *
- * Pin connection:
- *               RGB Led Module           IGKBoard-IMX6ULL
- *                   R        <----->      #Pin36 (GPIO1_IO11)
- *                   G        <----->      #Pin38 (GPIO1_IO10)
- *                   B        <----->      #Pin40 (GPIO5_IO09)
- *                  GND       <----->      GND
- *
  ********************************************************************************/
 
 #ifndef  _LED_H_
diff --git a/hal/api/relay.c b/hal/api/relay.c
index 4d14ae2..b7bb24d 100644
--- a/hal/api/relay.c
+++ b/hal/api/relay.c
@@ -9,7 +9,7 @@
  * Pin connection:
  *                 Relay Module           IGKBoard-IMX6ULL
  *                  VCC       <----->      5V
- *                   I        <----->      #Pin22 (GPIO3_IO23)
+ *                   I        <----->      #Pin37 (GPIO5_IO08)
  *                  GND       <----->      GND
  *
  ********************************************************************************/
@@ -92,6 +92,8 @@
 
     turn_relay(which, status);
 
+	term_relay();
+
     return 0;
 }
 
@@ -102,7 +104,7 @@
 
 static relay_t relays_info[RELAY_CNT] =
 {
-    {"relay1",  2, 23,  ACTIVE_HIGH, 0, NULL}, /* #Pin22, GPIO3_IO23 on chip2 line 23, active high */
+    {"relay1",  4, 8,  ACTIVE_HIGH, 0, NULL}, /* #Pin37, GPIO5_IO08 on chip4 line 8, active high */
 };
 
 /* relays context */
diff --git a/hal/api/relay.h b/hal/api/relay.h
index c03cd9f..bf678b2 100644
--- a/hal/api/relay.h
+++ b/hal/api/relay.h
@@ -5,13 +5,6 @@
  *       Filename:  relay.h
  *    Description:  This file is used to control relay
  *
- *
- * Pin connection:
- *                 Relay Module           IGKBoard-IMX6ULL
- *                  VCC       <----->      5V
- *                   I        <----->      #Pin22 (GPIO3_IO23)
- *                  GND       <----->      GND
- *
  ********************************************************************************/
 
 #ifndef  _RELAY_H_

--
Gitblit v1.9.1