Advertisement
Guest User

SX126X example app

a guest
Feb 24th, 2025
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.10 KB | Source Code | 0 0
  1. /******************************************************************************
  2.  * apps/examples/sx126x_demo/sx126x_demo.c
  3.  *
  4.  * SPDX-License-Identifier: Apache-2.0
  5.  *
  6.  * Licensed to the Apache Software Foundation (ASF) under one or more
  7.  * contributor license agreements.  See the NOTICE file distributed with
  8.  * this work for additional information regarding copyright ownership.  The
  9.  * ASF licenses this file to you under the Apache License, Version 2.0 (the
  10.  * "License"); you may not use this file except in compliance with the
  11.  * License.  You may obtain a copy of the License at
  12.  *
  13.  *   http://www.apache.org/licenses/LICENSE-2.0
  14.  *
  15.  * Unless required by applicable law or agreed to in writing, software
  16.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  17.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
  18.  * License for the specific language governing permissions and limitations
  19.  * under the License.
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /******************************************************************************
  24.  * Included Files
  25.  ******************************************************************************/
  26.  
  27. #include <nuttx/config.h>
  28.  
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <sys/ioctl.h>
  32.  
  33. #include <stdint.h>
  34. #include <stdbool.h>
  35. #include <stdio.h>
  36. #include <unistd.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <errno.h>
  40. #include <debug.h>
  41. #include <poll.h>
  42. #include <fcntl.h>
  43.  
  44. #include <nuttx/wireless/lpwan/sx126x.h>
  45. #include <nuttx/wireless/ioctl.h>
  46.  
  47. /******************************************************************************
  48.  * Definitions
  49.  ******************************************************************************/
  50.  
  51. #define SX126X_DEMO_DEVPATH "/dev/sx1262-0"
  52. #define SX126X_DEMO_DEF_FREQ  869250000
  53. #define SX126X_DEMO_DEF_PWR   22
  54. #define SX126X_DEMO_DEF_SF    10
  55. #define SX126X_DEMO_DEF_BW    125
  56.  
  57. /******************************************************************************
  58.  * Data types
  59.  ******************************************************************************/
  60.  
  61. enum sx126x_demo_mode_e
  62. {
  63.   SX126X_DEMO_TX,
  64.   SX126X_DEMO_RX,
  65.   SX126X_DEMO_ECHO,
  66.   SX126X_DEMO_TXRX
  67. };
  68.  
  69. struct sx126x_demo_config_s
  70. {
  71.   enum sx126x_lora_sf_e sf;
  72.   enum sx126x_lora_bw_e bw;
  73.   int32_t pwr;
  74.   uint32_t frequency_hz;
  75.   char *payload;
  76.   size_t payload_size;
  77.   enum sx126x_demo_mode_e mode;
  78. };
  79.  
  80. /******************************************************************************
  81.  * Globals
  82.  ******************************************************************************/
  83.  
  84. /******************************************************************************
  85.  * Public Functions
  86.  ******************************************************************************/
  87.  
  88. enum sx126x_lora_bw_e to_nearest_lora_bw(int bw)
  89. {
  90.   static const int16_t possible_bws[] =
  91.   {
  92.     7, 10, 15, 20, 31, 41, 62, 125, 250, 500
  93.   };
  94.  
  95.   /* Find nearest bandwidth */
  96.  
  97.   int16_t record_deviation = INT16_MAX;
  98.   size_t record_index     = 0;
  99.  
  100.   for (size_t i = 0; i < sizeof(possible_bws) / sizeof(possible_bws[0]); i++)
  101.     {
  102.       /* Compare bandwidth */
  103.  
  104.       int16_t possible_bw = possible_bws[i];
  105.       int16_t deviation = abs(bw - possible_bw);
  106.  
  107.       /* Is this a better value? */
  108.  
  109.       if (deviation < record_deviation)
  110.         {
  111.           /* New record deviation */
  112.  
  113.           record_deviation = deviation;
  114.           record_index     = i;
  115.  
  116.           if (deviation == 0)
  117.             {
  118.               /* It is perfect */
  119.  
  120.               break;
  121.             }
  122.         }
  123.     }
  124.  
  125.   int16_t nearest_bw = possible_bws[record_index];
  126.  
  127.   /* Did not find the perfect match, but got nearest */
  128.  
  129.   if (record_deviation != 0)
  130.     {
  131.       printf("Bandwidth %dkHz is not available. \
  132.             Using nearest available: %dkHz\n",
  133.              bw, nearest_bw);
  134.     }
  135.  
  136.   /* Convert to bandwidth code enum */
  137.  
  138.   static const enum sx126x_lora_bw_e bw_enum_map[] =
  139.   {
  140.     SX126X_LORA_BW_7, SX126X_LORA_BW_10, SX126X_LORA_BW_15,
  141.     SX126X_LORA_BW_20, SX126X_LORA_BW_31, SX126X_LORA_BW_41,
  142.     SX126X_LORA_BW_62, SX126X_LORA_BW_125, SX126X_LORA_BW_250,
  143.     SX126X_LORA_BW_500
  144.   };
  145.  
  146.   return bw_enum_map[record_index];
  147. }
  148.  
  149. void get_flags(int argc, FAR char *argv[], struct sx126x_demo_config_s *config)
  150. {
  151.   /* For every arg, get flag */
  152.  
  153.   for (int i = 0; i < argc; i++)
  154.     {
  155.       char *arg = argv[i];
  156.  
  157.       /* Flag must start with - */
  158.  
  159.       if (arg[0] != '-')
  160.         {
  161.           continue;
  162.         }
  163.  
  164.       /* Read flag */
  165.  
  166.       char flag = arg[1];
  167.       switch (flag)
  168.         {
  169.           /* Is terminator */
  170.  
  171.           case '\0':
  172.             {
  173.               break;
  174.             }
  175.  
  176.           /* Is frequency */
  177.  
  178.           case 'f':
  179.             {
  180.               /* Get value */
  181.  
  182.               if (i < argc - 1)
  183.                 {
  184.                   uint32_t freq;
  185.                   freq = strtoul(argv[++i], NULL, 0);
  186.                   config->frequency_hz = freq;
  187.                 }
  188.               break;
  189.             }
  190.  
  191.           /* Is spreading factor */
  192.  
  193.           case 's':
  194.             {
  195.               /* Get value */
  196.  
  197.               if (i < argc - 1)
  198.                 {
  199.                   uint32_t sf;
  200.                   sf = strtoul(argv[++i], NULL, 0);
  201.                   config->sf = sf;
  202.                 }
  203.               break;
  204.             }
  205.  
  206.           /* Is power */
  207.  
  208.           case 'p':
  209.             {
  210.               /* Get value */
  211.  
  212.               if (i < argc - 1)
  213.                 {
  214.                   int32_t power;
  215.                   power = strtol(argv[++i], NULL, 0);
  216.                   config->pwr = power;
  217.                 }
  218.               break;
  219.             }
  220.  
  221.           /* Is bandwidth */
  222.  
  223.           case 'b':
  224.             {
  225.               /* Get value */
  226.  
  227.               if (i < argc - 1)
  228.                 {
  229.                   int bw;
  230.                   bw = strtol(argv[++i], NULL, 0);
  231.                   config->bw = to_nearest_lora_bw(bw);
  232.                 }
  233.               break;
  234.             }
  235.  
  236.           /* Transmit */
  237.  
  238.           case 't':
  239.             {
  240.               /* Get string */
  241.  
  242.               if (i < argc - 1)
  243.                 {
  244.                   config->mode = SX126X_DEMO_TX;
  245.                   config->payload = argv[++i];
  246.                   config->payload_size = strlen(config->payload);
  247.                 }
  248.               break;
  249.             }
  250.  
  251.           /* Receive */
  252.  
  253.           case 'r':
  254.             {
  255.               /* Enable */
  256.  
  257.               config->mode = SX126X_DEMO_RX;
  258.               break;
  259.             }
  260.  
  261.           /* Transmit and Receive */
  262.  
  263.           case 'x':
  264.             {
  265.               /* Get string */
  266.  
  267.               if (i < argc - 1)
  268.                 {
  269.                   config->mode = SX126X_DEMO_TXRX;
  270.                   config->payload = argv[++i];
  271.                   config->payload_size = strlen(config->payload);
  272.                 }
  273.               break;
  274.             }
  275.           /* Echo back */
  276.  
  277.           case 'e':
  278.             {
  279.               /* Enable */
  280.  
  281.               config->mode = SX126X_DEMO_ECHO;
  282.               break;
  283.             }
  284.  
  285.           /* Unknown flag */
  286.  
  287.           default:
  288.             {
  289.               printf("Unknown flag \"%c\"\n", flag);
  290.               break;
  291.             }
  292.         }
  293.     }
  294. }
  295.  
  296. void set_sx_defaults(struct sx126x_demo_config_s *config)
  297. {
  298.   config->bw = to_nearest_lora_bw(SX126X_DEMO_DEF_BW);
  299.   config->sf = SX126X_DEMO_DEF_SF;
  300.   config->frequency_hz = SX126X_DEMO_DEF_FREQ;
  301.   config->mode = SX126X_DEMO_TX;
  302. }
  303.  
  304. void list_config(struct sx126x_demo_config_s *config)
  305. {
  306.   printf("Frequency: %u\n", config->frequency_hz);
  307.   printf("Spreading factor: %d\n", config->sf);
  308.   printf("Bandwidth 0x%X\n", config->bw);
  309. }
  310.  
  311. int open_sx(struct sx126x_demo_config_s *config)
  312. {
  313.   int fd;
  314.  
  315.   fd = open(SX126X_DEMO_DEVPATH, O_RDWR);
  316.   if (fd < 0)
  317.     {
  318.       int errcode = errno;
  319.       printf("ERROR: Failed to open device %s: %d\n",
  320.              SX126X_DEMO_DEVPATH, errcode);
  321.       return -1;
  322.     }
  323.  
  324.   /* Config */
  325.  
  326.   uint32_t freq = config->frequency_hz;
  327.   ioctl(fd, WLIOC_SETRADIOFREQ, &freq);
  328.  
  329.   int pwr = config->pwr;
  330.   ioctl(fd, WLIOC_SETTXPOWER, &pwr);
  331.  
  332.   struct sx126x_lora_config_s deviceconfig =
  333.   {
  334.     .modulation =
  335.     {
  336.       .bandwidth                   = config->bw,
  337.       .coding_rate                 = SX126X_LORA_CR_4_8,
  338.       .low_datarate_optimization   = false,
  339.       .spreading_factor            = config->sf
  340.     },
  341.     .packet =
  342.     {
  343.       .crc_enable                  = true,
  344.       .fixed_length_header         = false,
  345.       .payload_length              = 0xff,
  346.       .invert_iq                   = false,
  347.       .preambles                   = 8
  348.     }
  349.   };
  350.  
  351.   ioctl(fd, SX126XIOC_LORACONFIGSET, &deviceconfig);
  352.  
  353.   return fd;
  354. }
  355.  
  356. void demo_tx(int fd, struct sx126x_demo_config_s *config)
  357. {
  358.   printf("Transmitting...");
  359.   write(fd, config->payload, config->payload_size);
  360.   printf("\n\r");
  361. }
  362.  
  363. void demo_rx(int fd, struct sx126x_demo_config_s *config)
  364. {
  365.   struct sx126x_read_header_s r_hdr;
  366.   printf("Receiving...");
  367.   int success = read(fd, &r_hdr, sizeof(r_hdr));
  368.  
  369.   if (success < 0)
  370.     {
  371.       printf("RX error\n");
  372.       return;
  373.     }
  374.  
  375.   if (r_hdr.crc_error)
  376.     {
  377.       printf("CRC error\n");
  378.       return;
  379.     }
  380.  
  381.   printf("Received\n");
  382.   printf("Got %u bytes, RSSI %d, SNR %d\n", r_hdr.payload_length, r_hdr.rssi_db, r_hdr.snr);
  383.  
  384.   for (size_t i=0;i<r_hdr.payload_length;i++)
  385.     {
  386.       printf("%c", r_hdr.payload[i]);
  387.     }
  388.   printf("\n");
  389.  
  390. }
  391.  
  392. void demo_echo(int fd, struct sx126x_demo_config_s *config)
  393. {
  394.   for (;;)
  395.     {
  396.       struct sx126x_read_header_s r_hdr;
  397.       printf("Receiving...");
  398.       int success = read(fd, &r_hdr, sizeof(r_hdr));
  399.       if (success < 0)
  400.         {
  401.           printf("RX error\n");
  402.           return;
  403.         }
  404.  
  405.       if (r_hdr.crc_error)
  406.         {
  407.           printf("CRC error\n");
  408.           continue;
  409.         }
  410.  
  411.       printf("Received\n");
  412.       printf("Got %u bytes, RSSI %d, SNR %d\n", r_hdr.payload_length, r_hdr.rssi_db, r_hdr.snr);
  413.      
  414.       for (size_t i=0;i<r_hdr.payload_length;i++)
  415.         {
  416.           printf("%c", r_hdr.payload[i]);
  417.         }
  418.       printf("\nEcho TX...");
  419.  
  420.       write(fd, r_hdr.payload, r_hdr.payload_length);
  421.  
  422.       if (success < 0)
  423.         {
  424.           printf("TX error\n");
  425.           return;
  426.         }
  427.  
  428.       printf("Done\n");
  429.     }
  430. }
  431.  
  432. int main(int argc, FAR char *argv[])
  433. {
  434.   struct sx126x_demo_config_s config;
  435.  
  436.   /* Prepare */
  437.  
  438.   get_flags(argc, argv, &config);
  439.   list_config(&config);
  440.  
  441.   /* Open device */
  442.  
  443.   int fd = open_sx(&config);
  444.  
  445.   switch (config.mode)
  446.   {
  447.     case SX126X_DEMO_TX:
  448.     {
  449.       demo_tx(fd, &config);
  450.       break;
  451.     }
  452.  
  453.     case SX126X_DEMO_RX:
  454.     {
  455.       demo_rx(fd, &config);
  456.       break;
  457.     }
  458.  
  459.     case SX126X_DEMO_TXRX:
  460.     {
  461.       demo_tx(fd, &config);
  462.       demo_rx(fd, &config);
  463.       break;
  464.     }
  465.  
  466.     case SX126X_DEMO_ECHO:
  467.     {
  468.       demo_echo(fd, &config);
  469.       break;
  470.     }
  471.   }
  472.  
  473.   /* Close */
  474.  
  475.   close(fd);
  476.  
  477.   return 0;
  478. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement