{"id":20316105,"url":"https://github.com/lupyuen/pinedio-stack-nuttx","last_synced_at":"2026-03-04T23:32:25.355Z","repository":{"id":87766888,"uuid":"476979374","full_name":"lupyuen/pinedio-stack-nuttx","owner":"lupyuen","description":"PineDio Stack BL604 RISC-V Board on Apache NuttX RTOS","archived":false,"fork":false,"pushed_at":"2022-04-17T04:34:01.000Z","size":1325,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-04T20:56:29.907Z","etag":null,"topics":["bl604","i2c","lora","lvgl","nuttx","pinedio","riscv32","spi","st7789","sx1262"],"latest_commit_sha":null,"homepage":"https://lupyuen.github.io/articles/pinedio2","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lupyuen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["lupyuen"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["paypal.me/lupyuen"]}},"created_at":"2022-04-02T07:22:04.000Z","updated_at":"2022-05-19T14:40:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"22836b39-af0b-478f-8e48-17e5f8aa567b","html_url":"https://github.com/lupyuen/pinedio-stack-nuttx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lupyuen/pinedio-stack-nuttx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fpinedio-stack-nuttx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fpinedio-stack-nuttx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fpinedio-stack-nuttx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fpinedio-stack-nuttx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lupyuen","download_url":"https://codeload.github.com/lupyuen/pinedio-stack-nuttx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fpinedio-stack-nuttx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30099413,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T23:31:22.529Z","status":"ssl_error","status_checked_at":"2026-03-04T23:31:22.112Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bl604","i2c","lora","lvgl","nuttx","pinedio","riscv32","spi","st7789","sx1262"],"created_at":"2024-11-14T18:24:20.791Z","updated_at":"2026-03-04T23:32:25.317Z","avatar_url":"https://github.com/lupyuen.png","language":null,"funding_links":["https://github.com/sponsors/lupyuen","paypal.me/lupyuen"],"categories":[],"sub_categories":[],"readme":"![Apache NuttX RTOS, ST7789 Driver and LVGL Graphics Library all run OK on Pine64's PineDio Stack BL604!](https://lupyuen.github.io/images/pinedio2-title.jpg)\n\n# PineDio Stack BL604 RISC-V Board on Apache NuttX RTOS\n\nRead the article...\n\n-   [\"PineDio Stack BL604 runs Apache NuttX RTOS\"](https://lupyuen.github.io/articles/pinedio2)\n\n__PineDio Stack BL604__ is Pine64's newest microcontroller board, based on [__Bouffalo Lab's BL604__](https://lupyuen.github.io/articles/pinecone) RISC-V + WiFi + Bluetooth LE SoC.\n\n(Available any day now!)\n\nPineDio Stack is packed __chock-full of features__...\n\n-   ST7789 __Colour LCD Display__\n\n    (240 x 240 pixels)\n\n-   CST816S __Touch Panel__\n\n    (Connected on I2C)\n\n-   Semtech SX1262 __LoRa Transceiver__\n\n    (Works with LoRaWAN)\n\n-   AT6558 __GPS / GNSS Receiver__\n\n-   SGM40561 __Power Management Unit__\n\n-   __Heart Rate Sensor, Accelerometer, Compass, Vibrator__\n\n-   __SPI Flash, JTAG Debugging Port, Push Button__\n\n-   __2.4 GHz WiFi, Bluetooth LE__\n\n    (Thanks to BL604)\n\nWhich makes it an incredible gadget for __IoT Education__!\n\nSource code for Apache NuttX RTOS on PineDio Stack is here...\n\n-   [lupyuen/incubator-nuttx (pinedio branch)](https://github.com/lupyuen/incubator-nuttx/tree/pinedio)\n\n-   [lupyuen/incubator-nuttx-apps (pinedio branch)](https://github.com/lupyuen/incubator-nuttx-apps/tree/pinedio)\n\nNuttX Build Config for PineDio Stack BL604...\n\n-   [.config](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/configs/pinedio/defconfig)\n\nTo download, configure and build NuttX for PineDio Stack BL604...\n\n```bash\nmkdir nuttx\ncd nuttx\ngit clone --recursive --branch pinedio https://github.com/lupyuen/incubator-nuttx nuttx\ngit clone --recursive --branch pinedio https://github.com/lupyuen/incubator-nuttx-apps apps\ncd nuttx\n./tools/configure.sh bl602evb:pinedio\nmake\n```\n\n[(See the Build Log)](https://gist.github.com/lupyuen/3ff5b3a5b6c160c76d56e33c35745ef7)\n\n[__Follow the updates on Twitter__](https://twitter.com/MisterTechBlog/status/1510406086326513668)\n\n# Shared SPI Bus\n\nAcording to the PineDio Stack Schematic...\n\n-   [PineDio Stack Schematic (2021-09-15)](pinedio_stack_v1_0-2021_09_15-a.pdf)\n\n-   [PineDio Stack Baseboard Schematic (2021-09-27)](PINEDIO_STACK_BASEBOARD_V1_0-SCH-2021-09-27.pdf)\n\nThe SPI Bus is shared by...\n\n-   ST7789 Display Controller\n\n-   Semtech SX1262 LoRa Transceiver\n\n-   SPI Flash\n\n![Shared SPI Bus on PineDio Stack BL604](https://lupyuen.github.io/images/pinedio-spi2.jpg)\n\nHere are the BL604 GPIO Numbers for the shared SPI Bus...\n\n| Function | GPIO |\n| :------- | :---: |\n| SPI MOSI | 13 |\n| SPI MISO | 0  |\n| SPI SCK  | 11 |\n| SPI CS _(Unused)_ | 8 |\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/include/board.h#L99-L105)\n\nTo prevent crosstalk, we select each SPI Device by flipping its Chip Select Pin from High to Low...\n\n| SPI Device | Device ID | Swap MISO/MOSI | Chip Select | \n| :--------- | :-------: | :------------: | :---------: |\n| ST7789 Display     | 0x40000 | No  | 20\n| SX1262 Transceiver | 1       | Yes | 15\n| SPI Flash          | 2       | Yes | 14\n| _(Default Device)_ | -1      | Yes | 8 _(Unused)_\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/include/board.h#L106-L127)\n\n## SPI Device ID\n\nNuttX auto-assigns 0x40000 as the SPI Device ID for ST7789 Display. [(See this)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/include/nuttx/spi/spi.h#L459)\n\nWe assigned the other SPI Device IDs ourselves.\n\nDevice ID -1 is meant as a fallthrough to catch all SPI Devices that don't match the Device IDs. This also works for simple SPI setups where the Device ID is not needed.\n\n## Swap MISO / MOSI\n\nAccording to [BL602 Reference Manual](https://github.com/bouffalolab/bl_docs/blob/main/BL602_RM/en/BL602_BL604_RM_1.2_en.pdf) (Table 3.1 \"Pin Description\", Page 26)...\n\n-   GPIO 13 is MOSI\n\n-   GPIO 0 is MISO\n\nBut due to a BL602 SPI quirk we need to Swap MISO and MOSI to get this behaviour. That's why the \"Swap MISO / MOSI\" column is marked \"Yes\" for SX1262 Transceiver and SPI Flash.\n\nST7789 Display Controller is wired differently...\n\n-   ST7789 receives SPI Data on GPIO 0\n\n-   ST7789 Data / Command Pin is connected on GPIO 13\n\n    (High for ST7789 Data, Low for ST7789 Commands)\n\nThe direction of SPI Data is flipped for ST7789. That's why the \"Swap MISO / MOSI\" column is marked \"No\" for ST7789 Display Controller.\n\n## SPI Device Table\n\nWe represent the above SPI Device Table in NuttX as a flat int array...\n\n| SPI Device | Device ID | Swap MISO/MOSI | Chip Select | \n| :--------- | :-------: | :------------: | :---------: |\n| _ST7789 Display_     | 0x40000 | 0 | 20\n| _SX1262 Transceiver_ | 1       | 1 | 15\n| _SPI Flash_          | 2       | 1 | 14\n| _(Default Device)_   | -1      | 1 | 8\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c#L112-L133)\n\nHere's the source code...\n\n```c\n#ifdef CONFIG_BL602_SPI0\n/* SPI Device Table: SPI Device ID, Swap MISO/MOSI, Chip Select */\n\nstatic const int32_t bl602_spi_device_table[] =\n{\n#ifdef BOARD_LCD_DEVID  /* ST7789 Display */\n  BOARD_LCD_DEVID, BOARD_LCD_SWAP, BOARD_LCD_CS,\n#endif  /* BOARD_LCD_DEVID */\n\n#ifdef BOARD_SX1262_DEVID  /* LoRa SX1262 */\n  BOARD_SX1262_DEVID, BOARD_SX1262_SWAP, BOARD_SX1262_CS,\n#endif  /* BOARD_SX1262_DEVID */\n\n#ifdef BOARD_FLASH_DEVID  /* SPI Flash */\n  BOARD_FLASH_DEVID, BOARD_FLASH_SWAP, BOARD_FLASH_CS,\n#endif  /* BOARD_FLASH_DEVID */\n\n  /* Must end with Default SPI Device */\n\n  -1, 1, BOARD_SPI_CS,  /* Swap MISO/MOSI */\n};\n#endif  /* CONFIG_BL602_SPI0 */\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c#L112-L133)\n\nThe columns of the SPI Device Table...\n\n```c\n/* Columns in the SPI Device Table */\n\n#define DEVID_COL 0  /* SPI Device ID */\n#define SWAP_COL  1  /* 1 if MISO/MOSI should be swapped, else 0 */\n#define CS_COL    2  /* SPI Chip Select Pin */\n#define NUM_COLS  3  /* Number of columns in SPI Device Table */\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/include/board.h#L36-L41)\n\nHere are the functions for accessing the SPI Device Table...\n\n-   [bl602_spi_get_device](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c#L210-L239): Lookup a device in the SPI Device Table\n\n-   [bl602_spi_deselect_devices](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c#L178-L208): Deselect all devices in the SPI Device Table\n\n-   [bl602_spi_validate_devices](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c#L140-L176): Validate the devices in the SPI Device Table\n\n## Pin Definitions\n\nThe SPI Device Table above refers to the following Pin Definitions...\n\n```c\n/* SPI for PineDio Stack: Chip Select (unused), MOSI, MISO, SCK */\n\n#define BOARD_SPI_CS   (GPIO_INPUT | GPIO_PULLUP | GPIO_FUNC_SPI | GPIO_PIN8)  /* Unused */\n#define BOARD_SPI_MOSI (GPIO_INPUT | GPIO_PULLUP | GPIO_FUNC_SPI | GPIO_PIN13)\n#define BOARD_SPI_MISO (GPIO_INPUT | GPIO_PULLUP | GPIO_FUNC_SPI | GPIO_PIN0)\n#define BOARD_SPI_CLK  (GPIO_INPUT | GPIO_PULLUP | GPIO_FUNC_SPI | GPIO_PIN11)\n\n#ifdef CONFIG_LCD_ST7789\n/* ST7789 for PineDio Stack: Chip Select, Reset and Backlight */\n\n#define BOARD_LCD_DEVID SPIDEV_DISPLAY(0)  /* SPI Device ID: 0x40000 */\n#define BOARD_LCD_SWAP  0    /* Don't swap MISO/MOSI */\n#define BOARD_LCD_BL_INVERT  /* Backlight is active when Low */\n#define BOARD_LCD_CS  (GPIO_OUTPUT | GPIO_PULLUP | GPIO_FUNC_SWGPIO | GPIO_PIN20)\n#define BOARD_LCD_RST (GPIO_OUTPUT | GPIO_PULLUP | GPIO_FUNC_SWGPIO | GPIO_PIN3)\n#define BOARD_LCD_BL  (GPIO_OUTPUT | GPIO_PULLUP | GPIO_FUNC_SWGPIO | GPIO_PIN21)\n#endif  /* CONFIG_LCD_ST7789 */\n\n/* SX1262 for PineDio Stack: Chip Select */\n\n#define BOARD_SX1262_DEVID 1  /* SPI Device ID */\n#define BOARD_SX1262_SWAP  1  /* Swap MISO/MOSI */\n#define BOARD_SX1262_CS (GPIO_OUTPUT | GPIO_PULLUP | GPIO_FUNC_SWGPIO | GPIO_PIN15)\n\n/* SPI Flash for PineDio Stack: Chip Select */\n\n#define BOARD_FLASH_DEVID 2  /* SPI Device ID */\n#define BOARD_FLASH_SWAP  1  /* Swap MISO/MOSI */\n#define BOARD_FLASH_CS (GPIO_OUTPUT | GPIO_PULLUP | GPIO_FUNC_SWGPIO | GPIO_PIN14)\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/include/board.h#L99-L128)\n\n## Select / Deselect SPI Device\n\nBL602 NuttX SPI Driver looks up the SPI Device Table to 1️⃣ Swap MISO and MOSI Pins 2️⃣ Flip the Chip Select Pins. This is how we select and deselect each SPI Device...\n\n```c\n//  Enable/disable the SPI chip select\nstatic void bl602_spi_select(struct spi_dev_s *dev, uint32_t devid,\n                             bool selected)\n{\n  const int32_t *spidev;\n\n  spiinfo(\"devid: %lu, CS: %s\\n\", devid, selected ? \"select\" : \"free\");\n\n  /* get device from SPI Device Table */\n\n  spidev = bl602_spi_get_device(devid);\n  DEBUGASSERT(spidev != NULL);\n\n  /* swap MISO and MOSI if needed */\n\n  if (selected)\n    {\n      bl602_swap_spi_0_mosi_with_miso(spidev[SWAP_COL]);\n    }\n\n  /* set Chip Select */\n\n  bl602_gpiowrite(spidev[CS_COL], !selected);\n\n#ifdef CONFIG_SPI_CMDDATA\n  /* revert MISO and MOSI from GPIO Pins to SPI Pins */\n\n  if (!selected)\n    {\n      bl602_configgpio(BOARD_SPI_MISO);\n      bl602_configgpio(BOARD_SPI_MOSI);\n    }\n#endif\n}\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/arch/risc-v/src/bl602/bl602_spi.c#L439-L471)\n\n`bl602_spi_select` is called after locking the SPI Bus.\n\n## SPI Command / Data\n\nNuttX RTOS uses MISO as the ST7789 Data / Command Pin ... But ST7789 is wired \"backwards\" on PineDio Stack BL604! We use MOSI as the ST7789 Data / Command Pin instead.\n\nHere's how we flip the ST7789 Data / Command pin depending on MISO / MOSI Swap...\n\n```c\n#ifdef CONFIG_SPI_CMDDATA\nstatic int bl602_spi_cmddata(struct spi_dev_s *dev,\n                              uint32_t devid, bool cmd)\n{\n  spiinfo(\"devid: %\" PRIu32 \" CMD: %s\\n\", devid, cmd ? \"command\" :\n          \"data\");\n\n  if (devid == SPIDEV_DISPLAY(0))\n    {\n      const int32_t *spidev;\n      gpio_pinset_t dc;\n      gpio_pinset_t gpio;\n      int ret;\n\n      /* get device from SPI Device Table */\n\n      spidev = bl602_spi_get_device(devid);\n      DEBUGASSERT(spidev != NULL);\n\n      /* if MISO/MOSI are swapped, DC is MISO, else MOSI */\n\n      dc = spidev[SWAP_COL] ? BOARD_SPI_MISO : BOARD_SPI_MOSI;\n\n      /* reconfigure DC from SPI Pin to GPIO Pin */\n\n      gpio = (dc \u0026 GPIO_PIN_MASK)\n             | GPIO_OUTPUT | GPIO_PULLUP | GPIO_FUNC_SWGPIO;\n      ret = bl602_configgpio(gpio);\n      if (ret \u003c 0)\n        {\n          spierr(\"Failed to configure MISO as GPIO\\n\");\n          DEBUGPANIC();\n\n          return ret;\n        }\n\n      /* set DC to high (data) or low (command) */\n\n      bl602_gpiowrite(gpio, !cmd);\n\n      return OK;\n    }\n\n  spierr(\"SPI cmddata not supported\\n\");\n  DEBUGPANIC();\n\n  return -ENODEV;\n}\n#endif\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/arch/risc-v/src/bl602/bl602_spi.c#L726-L774)\n\n## Deselect All SPI Devices\n\nAt NuttX Startup, we deselect all SPI Devices ... By flipping their Chip Select Pins high...\n\n```c\nstatic void bl602_spi_init(struct spi_dev_s *dev)\n{\n  struct bl602_spi_priv_s *priv = (struct bl602_spi_priv_s *)dev;\n  const struct bl602_spi_config_s *config = priv-\u003econfig;\n\n  /* Initialize the SPI semaphore that enforces mutually exclusive access */\n\n  nxsem_init(\u0026priv-\u003eexclsem, 0, 1);\n\n  bl602_configgpio(BOARD_SPI_CS);\n  bl602_configgpio(BOARD_SPI_MOSI);\n  bl602_configgpio(BOARD_SPI_MISO);\n  bl602_configgpio(BOARD_SPI_CLK);\n\n  /* set master mode */\n\n  bl602_set_spi_0_act_mode_sel(1);\n\n  /* swap MOSI with MISO to be consistent with BL602 Reference Manual */\n\n  bl602_swap_spi_0_mosi_with_miso(1);\n\n  /* spi cfg  reg:\n   * cr_spi_deg_en 1\n   * cr_spi_m_cont_en 0\n   * cr_spi_byte_inv 0\n   * cr_spi_bit_inv 0\n   */\n\n  modifyreg32(BL602_SPI_CFG, SPI_CFG_CR_M_CONT_EN\n              | SPI_CFG_CR_BYTE_INV | SPI_CFG_CR_BIT_INV,\n              SPI_CFG_CR_DEG_EN);\n\n  /* disable rx ignore */\n\n  modifyreg32(BL602_SPI_CFG, SPI_CFG_CR_RXD_IGNR_EN, 0);\n\n  bl602_spi_setfrequency(dev, config-\u003eclk_freq);\n  bl602_spi_setbits(dev, 8);\n  bl602_spi_setmode(dev, config-\u003emode);\n\n  /* spi fifo clear */\n\n  modifyreg32(BL602_SPI_FIFO_CFG_0, SPI_FIFO_CFG_0_RX_CLR\n              | SPI_FIFO_CFG_0_TX_CLR, 0);\n\n  /* deselect all spi devices */\n\n  bl602_spi_deselect_devices();\n}\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/arch/risc-v/src/bl602/bl602_spi.c#L1191-L1240)\n\n## Test Shared SPI Bus\n\nWill ST7789 Display play nice with LoRa SX1262 on PineDio Stack BL604? Yep SX1262 works OK on the Shared SPI Bus!\n\nPineDio Stack boots and renders a Pink Screen...\n\n```text\ngpio_pin_register: Registering /dev/gpio0\ngpio_pin_register: Registering /dev/gpio1\ngpint_enable: Disable the interrupt\ngpio_pin_register: Registering /dev/gpio2\nbl602_gpio_set_intmod: ****gpio_pin=115, int_ctlmod=1, int_trgmod=0\nspi_test_driver_register: devpath=/dev/spitest0, spidev=0\nst7789_sleep: sleep: 0\nst7789_sendcmd: cmd: 0x11\nst7789_sendcmd: OK\nst7789_bpp: bpp: 16\nst7789_sendcmd: cmd: 0x3a\nst7789_sendcmd: OK\nst7789_setorientation:\nst7789_sendcmd: cmd: 0x36\nst7789_sendcmd: OK\nst7789_display: on: 1\nst7789_sendcmd: cmd: 0x29\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x21\nst7789_sendcmd: OK\nst7789_fill: color: 0xaaaa\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nboard_lcd_getdev: SPI port 0 bound to LCD 0\nst7789_getplaneinfo: planeno: 0 bpp: 16\n```\n\nWe run the `spi_test2` app to test SX1262...\n\n```text\nNuttShell (NSH) NuttX-10.2.0-RC0\nnsh\u003e\nnsh\u003e ?\nhelp usage:  help [-v] [\u003ccmd\u003e]\n\n  ?      cat    help   ls     uname\n\nBuiltin Apps:\n  tinycbor_test            spi_test                 nsh\n  lorawan_test             timer                    sensortest\n  sx1262_test              bl602_adc_test           ikea_air_quality_sensor\n  bas                      spi_test2                gpio\n  sh                       getprime\n  lvgldemo                 hello\nnsh\u003e spi_test2\nspi_test_driver_open:\ngpout_write: Writing 0\nspi_test_driver_write: buflen=2\nspi_test_driver_configspi:\nspi_test_driver_read: buflen=256\ngpout_write: Writing 1\nGet Status: received\n  a2 22\nSX1262 Status is 2\ngpout_write: Writing 0\nspi_test_driver_write: buflen=5\nspi_test_driver_configspi:\nspi_test_driver_read: buflen=256\ngpout_write: Writing 1\nRead Register 8: received\n  a2 a2 a2 a2 80\nSX1262 Register 8 is 0x80\n```\n\nSX1262 returns Register Value 0x80, which is correct!\n\nThen we run the LVGL Demo App...\n\n```text\nspi_test_driver_close:\nnsh\u003e lvgldemo\nfbdev_init: Failed to open /dev/fb0: 2\nst7789_getvideoinfo: fmt: 11 xres: 240 yres: 240 nplanes: 1\nlcddev_init: VideoInfo:\n        fmt: 11\n        xres: 240\n        yres: 240\n        nplanes: 1\nlcddev_init: PlaneInfo (plane 0):\n        bpp: 16\nst7789_putarea: row_start: 0 row_end: 19 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 20 row_end: 39 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 40 row_end:59 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 60 row_end: 79 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 80 row_end: 99 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 100 row_end: 119 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 120 row_end: 139 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 140 row_end: 159 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 160 row_end: 179 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 180 row_end: 199 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 200 row_end: 219 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nst7789_putarea: row_start: 220 row_end: 239 col_start: 0 col_end: 239\nst7789_sendcmd: cmd: 0x2b\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2a\nst7789_sendcmd: OK\nst7789_sendcmd: cmd: 0x2c\nst7789_sendcmd: OK\nmonitor_cb: 57600 px refreshed in 1110 ms\n```\n\nWhich renders the LVGL Demo Screen on ST7789 correctly!\n\n## SX1262 Chip Select\n\nThere's a potential Race Condition if we use the SX1262 Driver concurrently with the ST7789 Driver...\n\n-   During LoRa Transmission, SX1262 Driver calls `ioctl()` to flip SX1262 Chip Select to Low\n\n    [(See this)](https://github.com/lupyuen/lora-sx1262/blob/lorawan/src/sx126x-nuttx.c#L806-L832)\n\n-   SX1262 Driver calls SPI Test Driver `/dev/spitest0`, which locks (`SPI_LOCK`) and selects (`SPI_SELECT`) the SPI Bus (with SPI Device ID 0)\n\n    [(See this)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/drivers/rf/spi_test_driver.c#L161-L208)\n\n-   Note that the calls to `ioctl()` and `SPI_LOCK / SPI_SELECT` are NOT Atomic\n\n-   If the ST7789 Driver is active between the calls to `ioctl()` and `SPI_LOCK / SPI_SELECT`, both SX1262 Chip Select and ST7789 Chip Select will be flipped to Low\n\n-   This might transmit garbage to SX1262\n\nTo solve this problem, we will register a new SPI Test Driver `/dev/spitest1` with SPI Device ID 1.\n\nThe LoRa Driver will then access `/dev/spitest1`, which will `SPI_LOCK` and `SPI_SELECT` the SPI Bus (with SPI Device ID 1).\n\nSince the SPI Device ID is 1, `SPI_SELECT` will flip the SX1262 Chip Select to Low.\n\n# ST7789 Display\n\n## SPI Mode\n\nBL602 / BL604 talks to ST7789 Display at SPI Mode 1 or 3 ... Depends whether MISO / MOSI are swapped\n\n```c\n#ifdef CONFIG_BL602_SPI0\n#include \"../boards/risc-v/bl602/bl602evb/include/board.h\"\n#endif  /* CONFIG_BL602_SPI0 */\n\n#ifdef CONFIG_LCD_ST7789\n\n/****************************************************************************\n * Pre-processor Definitions\n ****************************************************************************/\n\n/* Verify that all configuration requirements have been met */\n\n#ifdef CONFIG_BL602_SPI0\n#  if defined(BOARD_LCD_SWAP) \u0026\u0026 BOARD_LCD_SWAP == 0  /* If MISO/MOSI not swapped... */\n#    warning Using SPI Mode 1 for ST7789 on BL602 (MISO/MOSI not swapped)\n#    define CONFIG_LCD_ST7789_SPIMODE SPIDEV_MODE1  /* SPI Mode 1: Workaround for BL602 */\n#  else\n#    warning Using SPI Mode 3 for ST7789 on BL602 (MISO/MOSI swapped)\n#    define CONFIG_LCD_ST7789_SPIMODE SPIDEV_MODE3  /* SPI Mode 3: Workaround for BL602 */\n#  endif /* BOARD_LCD_SWAP */\n#else\n#  ifndef CONFIG_LCD_ST7789_SPIMODE\n#    define CONFIG_LCD_ST7789_SPIMODE SPIDEV_MODE0\n#  endif /* CONFIG_LCD_ST7789_SPIMODE */\n#endif   /* CONFIG_BL602_SPI0 */\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/drivers/lcd/st7789.c#L42-L66)\n\n## SPI Frequency\n\nST7789 Display runs OK at SPI Frequency 4 MHz. Maybe we can go higher?\n\n```text\nCONFIG_LCD_ST7789_FREQUENCY=4000000\n```\n\n[(Source)](https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/configs/pinedio/defconfig#L542)\n\n## LVGL Test App\n\n![LVGL Test App](https://lupyuen.github.io/images/pinedio2-title.jpg)\n\nLVGL Test App is here...\n\n-   [lupyuen/lvgltest-nuttx](https://github.com/lupyuen/lvgltest-nuttx)\n\nTo run the app, enter this at the NuttX Shell...\n\n```bash\nlvgltest\n```\n\nHere's the code that renders the screen...\n\n```c\n//  Create the LVGL Widgets that will be rendered on the display\nstatic void create_widgets(void)\n{\n  //  Get the Active Screen\n  lv_obj_t *screen = lv_scr_act();\n\n  //  Create a Label Widget\n  lv_obj_t *label = lv_label_create(screen, NULL);\n\n  //  Wrap long lines in the label text\n  lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);\n\n  //  Interpret color codes in the label text\n  lv_label_set_recolor(label, true);\n\n  //  Center align the label text\n  lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);\n\n  //  Set the label text and colors\n  lv_label_set_text(\n    label, \n    \"#ff0000 HELLO# \"    //  Red Text\n    \"#00ff00 PINEDIO# \"  //  Green Text\n    \"#0000ff STACK!# \"   //  Blue Text\n  );\n\n  //  Set the label width\n  lv_obj_set_width(label, 200);\n\n  //  Align the label to the center of the screen, shift 30 pixels up\n  lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, -30);\n\n#ifdef CONFIG_USE_LV_CANVAS  //  LVGL Canvas Demo\n  //  Create the Canvas\n  lv_obj_t *canvas = lv_canvas_create(screen, NULL);\n\n  //  Set the Canvas Buffer (Warning: Might take a lot of RAM!)\n  static lv_color_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)];\n  lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_IMG_CF_TRUE_COLOR);\n\n  //  Align the canvas to the center of the screen, shift 50 pixels down\n  lv_obj_align(canvas, NULL, LV_ALIGN_CENTER, 0, 50);\n\n  //  Fill the canvas with white\n  lv_canvas_fill_bg(canvas, LV_COLOR_WHITE, LV_OPA_TRANSP);\n\n  //  Create a Rounded Rectangle\n  lv_draw_rect_dsc_t rect_dsc;\n  lv_draw_rect_dsc_init(\u0026rect_dsc);\n  rect_dsc.radius = 10;            //  Corner Radius\n  rect_dsc.bg_opa = LV_OPA_COVER;  //  Opacity: Opaque\n  rect_dsc.bg_grad_dir   = LV_GRAD_DIR_HOR;  //  Gradient Direction: Horizontal\n  rect_dsc.bg_color      = LV_COLOR_BLUE;    //  From Blue\n  rect_dsc.bg_grad_color = LV_COLOR_GREEN;   //  To Green\n  rect_dsc.border_width  = 2;  //  Border Width\n  rect_dsc.border_opa    = LV_OPA_90;        //  Border Opacity: 90%\n  rect_dsc.border_color  = LV_COLOR_SILVER;  //  Border Color\n  rect_dsc.shadow_width  = 5;  //  Shadow Width\n  rect_dsc.shadow_ofs_x  = 5;  //  Shadow Offset X\n  rect_dsc.shadow_ofs_y  = 5;  //  Shadow Offset Y\n\n  //  Draw the Rounded Rectangle to the canvas\n  lv_canvas_draw_rect(canvas, 0, 0, 95, 95, \u0026rect_dsc);\n#endif  //  CONFIG_USE_LV_CANVAS\n\n#ifdef CONFIG_EXAMPLES_LVGLTEST_MESSAGEBOX  //  LVGL Message Box Demo\n  //  Create a Message Box Widget\n  lv_obj_t *msgbox = lv_msgbox_create(screen, NULL);\n\n  //  Set the Message Box Text\n  lv_msgbox_set_text(msgbox, \"Hello PineDio Stack!\");\n\n  //  Define the Message Box Buttons\n  static const char *btns[] = {\"Cancel\", \"OK\", \"\"};\n\n  //  Add the buttons to the Message Box\n  lv_msgbox_add_btns(msgbox, btns);\n#endif  //  CONFIG_EXAMPLES_LVGLTEST_MESSAGEBOX\n}\n```\n\n[(Source)](https://github.com/lupyuen/lvgltest-nuttx/blob/main/lvgltest.c#L110-L198)\n\nTo render our own text and graphics, edit this source file and change the code above...\n\n```text\napps/examples/lvgltest/lvgltest.c\n```\n\n## LVGL Demo App\n\n![LVGL Demo App](https://lupyuen.github.io/images/pinedio2-dark2.jpg)\n\nTo run the app, enter this at the NuttX Shell...\n\n```bash\nlvgldemo\n```\n\nTo change the message in LVGL Demo App, edit `apps/examples/lvgldemo/lv_demos/src/lv_demo_widgets/lv_demo_widgets.c`...\n\n```c\nstatic void controls_create(lv_obj_t * parent)\n{\n    lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_TOP);\n\n    lv_disp_size_t disp_size = lv_disp_get_size_category(NULL);\n    lv_coord_t grid_w = lv_page_get_width_grid(parent, disp_size \u003c= LV_DISP_SIZE_SMALL ? 1 : 2, 1);\n\n#if LV_DEMO_WIDGETS_SLIDESHOW == 0\n    static const char * btns[] = {\"PineDio\", \"Stack\", \"\"};\n\n    lv_obj_t * m = lv_msgbox_create(lv_scr_act(), NULL);\n    lv_msgbox_add_btns(m, btns);\n    lv_obj_t * btnm = lv_msgbox_get_btnmatrix(m);\n    lv_btnmatrix_set_btn_ctrl(btnm, 1, LV_BTNMATRIX_CTRL_CHECK_STATE);\n#endif\n```\n\n# SX1262 LoRa Transceiver\n\n## Test LoRa\n\nTo test LoRa on PineDio Stack, edit [`sx1262_test_main.c`](https://github.com/lupyuen/sx1262_test/blob/main/sx1262_test_main.c) at...\n\n```text\napps/examples/sx1262_test/sx1262_test_main.c\n```\n\nAnd update the LoRa Parameters...\n\n-   [\"LoRa Parameters\"](https://lupyuen.github.io/articles/sx1262#lora-parameters)\n\n## Test LoRaWAN\n\nLoRaWAN works OK on Shared SPI Bus yay! PineDio Stack connects to LoRaWAN Gateway (ChirpStack) and sends data packets.\n\n(Internal Temperature Sensor on ADC works OK too)\n\nRemember to disable all Info Logging because it affects the LoRaWAN Timers.\n\nHere's how we set the LoRaWAN Parameters...\n\n-   [\"Device EUI, Join EUI and App Key\"](https://lupyuen.github.io/articles/lorawan3#device-eui-join-eui-and-app-key)\n\n-   [\"LoRaWAN Frequency\"](https://lupyuen.github.io/articles/lorawan3#lorawan-frequency)\n\n```text\nNuttShell (NSH) NuttX-10.2.0-RC0\nnsh\u003e lorawan_test\ninit_entropy_pool\noffset = 2228\ntemperature = 31.600670 Celsius\noffset = 2228\ntemperature = 31.084742 Celsius\noffset = 2228\ntemperature = 32.890495 Celsius\noffset = 2228\ntemperature = 33.535404 Celsius\n\n###### ===================================== ######\n\nApplication name   : lorawan_test\nApplication version: 1.2.0\nGitHub base version: 5.0.0\n\n###### ===================================== ######\n\ninit_event_queue\nTimerInit:     0x4201c750\ncallout_handler: lock\nTimerInit:     0x4201c76c\nTimerInit:     0x4201c788\nTimerInit:     0x4201c804\nTimerInit:     0x4201c8b8\nTimerInit:     0x4201c8d4\nTimerInit:     0x4201c8f0\nTimerInit:     0x4201c90c\nTODO: RtcGetCalendarTime\nTODO: SX126xReset\ninit_gpio\nDIO1 pintype before=5\ninit_gpio: change DIO1 to Trigger GPIO Interrupt on Rising Edge\ngpio_ioctl: Requested pintype 8, but actual pintype 5\nDIO1 pintype after=5\nStarting process_dio1\nprocess_dio1 started\nprocess_dio1: event=0x4201b878\ninit_spi\nSX126xSetTxParams: power=22, rampTime=7\nSX126xSetPaConfig: paDutyCycle=4, hpMax=7, deviceSel=0, paLut=1\nTimerInit:     0x4201b850\nTimerInit:     0x4201b7bc\nRadioSetModem\nRadioSetModem\nRadioSetPublicNetwork: public syncword=3444\nRadioSleep\nDIO1 add event\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nTODO: EepromMcuReadBuffer\nRadioSetModem\nRadioSetPublicNetwork: public syncword=3444\nDevEui      : 4B-C1-5E-E7-37-7B-B1-5B\nJoinEui     : 00-00-00-00-00-00-00-00\nPin         : 00-00-00-00\n\nTimerInit:     0x4201c3a8\nTimerInit:     0x4201c3c4\nTimerInit:     0x4201c288\nTODO: RtcGetCalendarTime\nTODO: RtcBkupRead\nTODO: RtcBkupRead\nRadioSetChannel: freq=923200000\nRadioSetTxConfig: modem=1, power=13, fdev=0, bandwidth=0, datarate=10, coderate=      1, preambleLen=8, fixLen=0, crcOn=1, freqHopOn=0, hopPeriod=0, iqInverted=0, tim      eout=4000\nRadioSetTxConfig: SpreadingFactor=10, Bandwidth=4, CodingRate=1, LowDatarateOpti      mize=0, PreambleLength=8, HeaderType=0, PayloadLength=255, CrcMode=1, InvertIQ=0\nRadioStandby\nRadioSetModem\nSX126xSetTxParams: power=13, rampTime=7\nSX126xSetPaConfig: paDutyCycle=4, hpMax=7, deviceSel=0, paLut=1\nSecureElementRandomNumber: 0xa8c2a6e7\nRadioSend: size=23\n00 00 00 00 00 00 00 00 00 5b b1 7b 37 e7 5e c1 4b e7 a6 80 b1 e0 e4\nRadioSend: PreambleLength=8, HeaderType=0, PayloadLength=23, CrcMode=1, InvertIQ      =0\nTimerStop:     0x4201b850\nTimerStart2:   0x4201b850, 4000 ms\ncallout_reset: evq=0x42013250, ev=0x4201b850\n\n###### =========== MLME-Request ============ ######\n######               MLME_JOIN               ######\n###### ===================================== ######\nSTATUS      : OK\nStartTxProcess\nTimerInit:     0x42015b7c\nTimerSetValue: 0x42015b7c, 42249 ms\nOnTxTimerEvent: timeout in 42249 ms, event=0\nTimerStop:     0x42015b7c\nTimerSetValue: 0x42015b7c, 42249 ms\nTimerStart:    0x42015b7c\nTimerStop:     0x42015b7c\nTimerStart2:   0x42015b7c, 42249 ms\ncallout_reset: evq=0x42013250, ev=0x42015b7c\nhandle_event_queue\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_TX_DONE\nTimerStop:     0x4201b850\nTODO: RtcGetCalendarTime\nTODO: RtcBkupRead\nRadioOnDioIrq\nRadioIrqProcess\nRadioSleep\nDIO1 add event\nTimerSetValue: 0x4201c76c, 4988 ms\nTimerStart:    0x4201c76c\nTimerStop:     0x4201c76c\nTimerStart2:   0x4201c76c, 4988 ms\ncallout_reset: evq=0x42013250, ev=0x4201c76c\nTimerSetValue: 0x4201c788, 5988 ms\nTimerStart:    0x4201c788\nTimerStop:     0x4201c788\nTimerStart2:   0x4201c788, 5988 ms\ncallout_reset: evq=0x42013250, ev=0x4201c788\nTODO: RtcGetCalendarTime\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\ncallout_handler: unlock\ncallout_handler: evq=0x42013250, ev=0x4201c76c\ncallout_handler: lock\nhandle_event_queue: ev=0x4201c76c\nTimerStop:     0x4201c76c\nRadioStandby\nRadioSetChannel: freq=923200000\nRadioSetRxConfig\nRadioStandby\nRadioSetModem\nRadioSetRxConfig done\nRadioRx\nTimerStop:     0x4201b7bc\nTimerStart2:   0x4201b7bc, 3000 ms\ncallout_reset: evq=0x42013250, ev=0x4201b7bc\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_PREAMBLE_DETECTED\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_HEADER_VALID\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_RX_DONE\nTimerStop:     0x4201b7bc\nRadioOnDioIrq\nRadioIrqProcess\nRadioSleep\nDIO1 add event\nTimerStop:     0x4201c788\nOnTxData\n\n###### =========== MLME-Confirm ============ ######\nSTATUS      : OK\nOnJoinRequest\n###### ===========   JOINED     ============ ######\n\nOTAA\n\nDevAddr     :  01097710\n\n\nDATA RATE   : DR_2\n\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nUplinkProcess\nPrepareTxFrame: Transmit to LoRaWAN: Hi NuttX (9 bytes)\nPrepareTxFrame: status=0, maxSize=11, currentSize=11\nLmHandlerSend: Data frame\nTODO: RtcGetCalendarTime\nTODO: RtcBkupRead\nRadioSetChannel: freq=923200000\nRadioSetTxConfig: modem=1, power=13, fdev=0, bandwidth=0, datarate=9, coderate=1      , preambleLen=8, fixLen=0, crcOn=1, freqHopOn=0, hopPeriod=0, iqInverted=0, time      out=4000\nRadioSetTxConfig: SpreadingFactor=9, Bandwidth=4, CodingRate=1, LowDatarateOptim      ize=0, PreambleLength=8, HeaderType=0, PayloadLength=128, CrcMode=1, InvertIQ=0\nRadioStandby\nRadioSetModem\nSX126xSetTxParams: power=13, rampTime=7\nSX126xSetPaConfig: paDutyCycle=4, hpMax=7, deviceSel=0, paLut=1\nRadioSend: size=22\n40 10 77 09 01 00 01 00 01 a5 12 b3 cc a2 27 27 57 dc c3 a7 eb ae\nRadioSend: PreambleLength=8, HeaderType=0, PayloadLength=22, CrcMode=1, InvertIQ      =0\nTimerStop:     0x4201b850\nTimerStart2:   0x4201b850, 4000 ms\ncallout_reset: evq=0x42013250, ev=0x4201b850\n\n###### =========== MCPS-Request ============ ######\n######           MCPS_UNCONFIRMED            ######\n###### ===================================== ######\nSTATUS      : OK\nPrepareTxFrame: Transmit OK\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_TX_DONE\nTimerStop:     0x4201b850\nTODO: RtcGetCalendarTime\nTODO: RtcBkupRead\nRadioOnDioIrq\nRadioIrqProcess\nRadioSleep\nDIO1 add event\nTimerSetValue: 0x4201c76c, 980 ms\nTimerStart:    0x4201c76c\nTimerStop:     0x4201c76c\nTimerStart2:   0x4201c76c, 980 ms\ncallout_reset: evq=0x42013250, ev=0x4201c76c\nTimerSetValue: 0x4201c788, 1988 ms\nTimerStart:    0x4201c788\nTimerStop:     0x4201c788\nTimerStart2:   0x4201c788, 1988 ms\ncallout_reset: evq=0x42013250, ev=0x4201c788\nTODO: RtcGetCalendarTime\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\ncallout_handler: unlock\ncallout_handler: evq=0x42013250, ev=0x4201c76c\ncallout_handler: lock\nhandle_event_queue: ev=0x4201c76c\nTimerStop:     0x4201c76c\nRadioStandby\nRadioSetChannel: freq=923200000\nRadioSetRxConfig\nRadioStandby\nRadioSetModem\nRadioSetRxConfig done\nRadioRx\nTimerStop:     0x4201b7bc\nTimerStart2:   0x4201b7bc, 3000 ms\ncallout_reset: evq=0x42013250, ev=0x4201b7bc\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_RX_TX_TIMEOUT\nTimerStop:     0x4201b7bc\nRadioOnDioIrq\nRadioIrqProcess\nRadioSleep\nDIO1 add event\nTimerStop:     0x4201c788\nTimerStop:     0x4201c750\nOnTxData\n\n###### =========== MCPS-Confirm ============ ######\nSTATUS      : OK\n\n###### =====   UPLINK FRAME        1   ===== ######\n\nCLASS       : A\n\nTX PORT     : 1\nTX DATA     : UNCONFIRMED\n48 69 20 4E 75 74 74 58 00\n\nDATA RATE   : DR_3\nU/L FREQ    : 923200000\nTX POWER    : 0\nCHANNEL MASK: 0003\n\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nUplinkProcess\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\nUplinkProcess\ncallout_handler: unlock\ncallout_handler: evq=0x42013250, ev=0x42015b7c\ncallout_handler: lock\nhandle_event_queue: ev=0x42015b7c\nOnTxTimerEvent: timeout in 42249 ms, event=0x42015b7c\nTimerStop:     0x42015b7c\nTimerSetValue: 0x42015b7c, 42249 ms\nTimerStart:    0x42015b7c\nTimerStop:     0x42015b7c\nTimerStart2:   0x42015b7c, 42249 ms\ncallout_reset: evq=0x42013250, ev=0x42015b7c\nRadioOnDioIrq\nRadioIrqProcess\nUplinkProcess\nPrepareTxFrame: Transmit to LoRaWAN: Hi NuttX (9 bytes)\nPrepareTxFrame: status=0, maxSize=53, currentSize=53\nLmHandlerSend: Data frame\nTODO: RtcGetCalendarTime\nTODO: RtcBkupRead\nRadioSetChannel: freq=923200000\nRadioSetTxConfig: modem=1, power=13, fdev=0, bandwidth=0, datarate=9, coderate=1, preambleLen=8, fixLen=0, crcOn=1, freqHopOn=0, hopPeriod=0, iqInverted=0, timeout=4000\nRadioSetTxConfig: SpreadingFactor=9, Bandwidth=4, CodingRate=1, LowDatarateOptimize=0, PreambleLength=8, HeaderType=0, PayloadLength=128, CrcMode=1, InvertIQ=0\nRadioStandby\nRadioSetModem\nSX126xSetTxParams: power=13, rampTime=7\nSX126xSetPaConfig: paDutyCycle=4, hpMax=7, deviceSel=0, paLut=1\nRadioSend: size=22\n40 10 77 09 01 00 02 00 01 ad b9 67 e6 1c 34 05 2d f3 d3 b5 c7 16\nRadioSend: PreambleLength=8, HeaderType=0, PayloadLength=22, CrcMode=1, InvertIQ=0\nTimerStop:     0x4201b850\nTimerStart2:   0x4201b850, 4000 ms\ncallout_reset: evq=0x42013250, ev=0x4201b850\n\n###### =========== MCPS-Request ============ ######\n######           MCPS_UNCONFIRMED            ######\n###### ===================================== ######\nSTATUS      : OK\nPrepareTxFrame: Transmit OK\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_TX_DONE\nTimerStop:     0x4201b850\nTODO: RtcGetCalendarTime\nTODO: RtcBkupRead\nRadioOnDioIrq\nRadioIrqProcess\nRadioSleep\nDIO1 add event\nTimerSetValue: 0x4201c76c, 980 ms\nTimerStart:    0x4201c76c\nTimerStop:     0x4201c76c\nTimerStart2:   0x4201c76c, 980 ms\ncallout_reset: evq=0x42013250, ev=0x4201c76c\nTimerSetValue: 0x4201c788, 1988 ms\nTimerStart:    0x4201c788\nTimerStop:     0x4201c788\nTimerStart2:   0x4201c788, 1988 ms\ncallout_reset: evq=0x42013250, ev=0x4201c788\nTODO: RtcGetCalendarTime\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\ncallout_handler: unlock\ncallout_handler: evq=0x42013250, ev=0x4201c76c\ncallout_handler: lock\nhandle_event_queue: ev=0x4201c76c\nTimerStop:     0x4201c76c\nRadioStandby\nRadioSetChannel: freq=923200000\nRadioSetRxConfig\nRadioStandby\nRadioSetModem\nRadioSetRxConfig done\nRadioRx\nTimerStop:     0x4201b7bc\nTimerStart2:   0x4201b7bc, 3000 ms\ncallout_reset: evq=0x42013250, ev=0x4201b7bc\nRadioOnDioIrq\nRadioIrqProcess\nDIO1 add event\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nIRQ_RX_TX_TIMEOUT\nTimerStop:     0x4201b7bc\nRadioOnDioIrq\nRadioIrqProcess\nRadioSleep\nDIO1 add event\nTimerStop:     0x4201c788\nTimerStop:     0x4201c750\nOnTxData\n\n###### =========== MCPS-Confirm ============ ######\nSTATUS      : OK\n\n###### =====   UPLINK FRAME        2   ===== ######\n\nCLASS       : A\n\nTX PORT     : 1\nTX DATA     : UNCONFIRMED\n48 69 20 4E 75 74 74 58 00\n\nDATA RATE   : DR_3\nU/L FREQ    : 923200000\nTX POWER    : 0\nCHANNEL MASK: 0003\n\nTODO: EepromMcuWriteBuffer\nTODO: EepromMcuWriteBuffer\nUplinkProcess\nhandle_event_queue: ev=0x4201b878\nRadioOnDioIrq\nRadioIrqProcess\nRadioOnDioIrq\nRadioIrqProcess\nUplinkProcess\n```\n\n# Touch Panel\n\nTODO: See [pinedio-stack-selftest/drivers/cst816s.c](https://codeberg.org/JF002/pinedio-stack-selftest/src/branch/master/drivers/cst816s.c)\n\n# Push Button\n\nTODO: See [pinedio-stack-selftest/pushbutton.c](https://codeberg.org/JF002/pinedio-stack-selftest/src/branch/master/pushbutton.c)\n\n# Accelerometer\n\nTODO: See [pinedio-stack-selftest/accelerometer.c](https://codeberg.org/JF002/pinedio-stack-selftest/src/branch/master/accelerometer.c)\n\n# Power Management\n\nTODO: See [pinedio-stack-selftest/battery.c](https://codeberg.org/JF002/pinedio-stack-selftest/src/branch/master/battery.c)\n\n# SPI Flash\n\nTODO\n\n# GPS\n\nTODO: NuttX has a GPS Demo App...\n\n[apps/examples/gps/gps_main.c](https://github.com/lupyuen/incubator-nuttx-apps/blob/pinedio/examples/gps/gps_main.c)\n\nAnd a GPS Parser...\n\n[apps/gpsutils](https://github.com/lupyuen/incubator-nuttx-apps/tree/pinedio/gpsutils)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flupyuen%2Fpinedio-stack-nuttx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flupyuen%2Fpinedio-stack-nuttx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flupyuen%2Fpinedio-stack-nuttx/lists"}