You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2020/09/15 20:08:35 UTC

[GitHub] [incubator-nuttx] btashton opened a new pull request #1797: LED: Support for WS2812 led controller (aka Adafruit NeoPixel)

btashton opened a new pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797


   ## Summary
   The WS2812 is very common in LED strips as it is an integrated controller and LED. It is driven by a single data line, but the timing requirements can be met by using most SPI controllers and the use of DMA.
   
   https://cdn-shop.adafruit.com/datasheets/WS2812.pdf
   
   ## Impact
   Added support for WS2812 based LED light strips.
   
   ## Testing
   This driver has been validated on the nRF52 arch both with a single LED and a strip of 144.
   The timing requirements have also been validated for using a 8MHz and 4MHz SPI clock.
   
   Here is a video of a "jumping" demo that using the seek and write interfaces. https://giphy.com/gifs/TjGKy7TT7jwj88bh5x
   
   ![image](https://user-images.githubusercontent.com/173245/93258951-f0a65400-f753-11ea-9137-06ac83e04bce.png)
   
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] davids5 commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
davids5 commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489547703



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       What about ensuring the driver is holding the SPI lock before changing the SPI settings? 




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] davids5 commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
davids5 commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489011256



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       Do you need to lock the SPI bus and then call ws2812_configspi here?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] davids5 merged pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
davids5 merged pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797


   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] btashton commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
btashton commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489539752



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       Done.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] acassis commented on pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
acassis commented on pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#issuecomment-983933237


   Hi @baschuuuu you can use the stm32_appinit.c. I hope in the future we make the stm32_boot.c/stm32_appinit.c/stm32_bringup.c more consistent between all the boards. It is something that really confuses new users.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] btashton commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
btashton commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489562552



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       @davids5 sorry about that I did not `git add` the file... I was very confused, that is the change I made.
   https://github.com/apache/incubator-nuttx/pull/1797/files#diff-c94b56b8563460b40fec75e2c397c68cR136




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] davids5 commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
davids5 commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489322864



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       Ok, Then why not hold the lock `SPI_LOCK(priv->spi, true);` then do the init `ws2812_configspi(priv->spi);` ? 
   Also maybe add a disclaimer to not use this on a common bus to the [Kconfig]( https://github.com/apache/incubator-nuttx/pull/1797/files#diff-a616198bfed58f9e3b4f936ee5284b1cR97)
   




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] baschuuuu commented on pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
baschuuuu commented on pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#issuecomment-983852835


   Thank you @acassis. That has already helped me a lot.
   But I use a different board (Nucleo L476RG) which does **not** provide a stm32_bringup.c file.
   Hence I do not know where to call "board_ws2812_initialize(...)". I have created a bringup-file for my board but that did not work.
   I would have two follow-up questions.
   1) Why do some boards not have a stm32_bringup.c file?
   2) Where/how can I initialize the ws2812?
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] acassis commented on pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
acassis commented on pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#issuecomment-981912206


   @baschuuuu when I added the support to APA102 I added a test program to it, see: apps/examples/apa102 maybe you can adapt it to work on WS2812 as well.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] davids5 commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
davids5 commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489566203



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       No worries. All good now! Shall we merge it?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] btashton commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
btashton commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489024163



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       See the lock here https://github.com/apache/incubator-nuttx/pull/1797/files#diff-c94b56b8563460b40fec75e2c397c68cR453
   
   You cannot really share the bus if this device is connected to it so I just lock it on init so it should be very obvious something is wrong if you try to share.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] btashton commented on a change in pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
btashton commented on a change in pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#discussion_r489591084



##########
File path: drivers/leds/ws2812.c
##########
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/sensors/ws2812.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/leds/ws2812.h>
+
+#ifdef CONFIG_WS2812
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_WS2812_FREQUENCY
+#  define CONFIG_WS2812_FREQUENCY  8000000
+#endif
+
+/* These are the tuning parameters to meeting timeing requirements */
+
+#if CONFIG_WS2812_FREQUENCY == 4000000
+#  define WS2812_RST_CYCLES 30          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01000000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01110000  /* 750 ns (550ns - 850ns) */
+#elif CONFIG_WS2812_FREQUENCY == 8000000
+#  define WS2812_RST_CYCLES 60          /* 60us (>50us)*/
+#  define WS2812_ZERO_BYTE  0b01100000  /* 250 ns (200ns - 500ns) */
+#  define WS2812_ONE_BYTE   0b01111100  /* 750 ns (550ns - 850ns) */
+#else
+#  error "Unsupported SPI Frequency"
+#endif
+
+#define WS2812_BYTES_PER_LED  8 * 3
+#define WS2812_RW_PIXEL_SIZE  4
+
+/* Transmit buffer looks like:
+ * [<----reset bytes---->|<-RGBn->...<-RGB0->|<----reset bytes---->]
+ *
+ * It is important that this is shipped as close to one chunk as possible
+ * in order to meet timeing requirements and to keep MOSI from going high
+ * between transactions.  Some chips will leave MOSI at the state of the
+ * MSB of the last byte for this reason it is recommended to shift the
+ * bytes that represents the zero and one so that the MSB is 1. The reset
+ * clocks will pad the shortend low at the end.
+ */
+
+#define TXBUFF_SIZE(n) (WS2812_RST_CYCLES * 2 + n * WS2812_BYTES_PER_LED)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ws2812_dev_s
+{
+  FAR struct spi_dev_s *spi;  /* SPI interface */
+  uint16_t nleds;             /* Number of addressable LEDs */
+  uint8_t *tx_buf;            /* Buffer for write transaction and state */
+  sem_t exclsem;              /* Assures exclusive access to the driver */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi);
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb);
+
+/* Character driver methods */
+
+static int     ws2812_open(FAR struct file *filep);
+static int     ws2812_close(FAR struct file *filep);
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen);
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen);
+static off_t   ws2812_seek(FAR struct file *filep, off_t offset, int whence);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_ws2812fops =
+{
+  ws2812_open,    /* open */
+  ws2812_close,   /* close */
+  ws2812_read,    /* read */
+  ws2812_write,   /* write */
+  ws2812_seek,    /* seek */
+  NULL,           /* ioctl */
+  NULL,           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL            /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ws2812_configspi
+ *
+ * Description:
+ *   Set the SPI bus configuration
+ *
+ ****************************************************************************/
+
+static inline void ws2812_configspi(FAR struct spi_dev_s *spi)
+{
+  /* Configure SPI for the WS2812 */
+
+  SPI_SETMODE(spi, SPIDEV_MODE3);
+  SPI_SETBITS(spi, 8);
+  SPI_HWFEATURES(spi, 0);
+  SPI_SETFREQUENCY(spi, CONFIG_WS2812_FREQUENCY);
+}
+
+/****************************************************************************
+ * Name: ws2812_pack
+ *
+ * Description:
+ *   This writes the expanded SPI transaction to the transaction buffer
+ *   for a given 24bit RGB value.
+ *
+ * Input Parameters:
+ *   buf - The location in the transmit buffer to write.
+ *   rgb - A 24bit RGB color 8bit red, 8-bit green, 8-bit blue
+ *
+ ****************************************************************************/
+
+static void ws2812_pack(FAR uint8_t *buf, uint32_t rgb)
+{
+  uint8_t bit_idx;
+  uint8_t byte_idx;
+  uint8_t offset = 0;
+  uint8_t color;
+  uint32_t grb;
+
+  grb = (rgb & 0x00ff00) << 8;
+  grb |= (rgb & 0xff0000) >> 8;
+  grb |= rgb & 0x0000ff;
+
+  for (byte_idx = 0; byte_idx < 3; byte_idx++)
+    {
+      color = (uint8_t)(grb >> (8 * (2 - byte_idx)));
+      for (bit_idx = 0; bit_idx < 8; bit_idx++)
+        {
+          if (color & (1 << (7 - bit_idx)))
+            {
+              buf[offset] = WS2812_ONE_BYTE;
+            }
+          else
+            {
+              buf[offset] = WS2812_ZERO_BYTE;
+            }
+
+          offset++;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: ws2812_open
+ *
+ * Description:
+ *   This function is called whenever the WS2812 device is opened.
+ *
+ ****************************************************************************/
+
+static int ws2812_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_close
+ *
+ * Description:
+ *   This routine is called when the WS2812 device is closed.
+ *
+ ****************************************************************************/
+
+static int ws2812_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: ws2812_read
+ ****************************************************************************/
+
+static ssize_t ws2812_read(FAR struct file *filep, FAR char *buffer,
+                           size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: ws2812_write
+ *
+ * Description:
+ *   This routine is called when writing to the WS2812 device. Data buffer
+ *   should be an array of 32bit values holding 24bits of color information
+ *   in host byte ordering 0x**rrggbb.
+ *
+ ****************************************************************************/
+
+static ssize_t ws2812_write(FAR struct file *filep, FAR const char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct ws2812_dev_s *priv = inode->i_private;
+  FAR uint8_t *tx_pixel;
+  FAR uint32_t *pixel_buf = (FAR uint32_t *)buffer;
+  size_t cur_led;
+  size_t start_led;
+  size_t end_led;
+  size_t written = 0;
+
+  if (buffer == NULL)
+    {
+      lederr("ERROR: Buffer is null\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  /* We need at least one display, so 1 byte */
+
+  if (buflen < 1)
+    {
+      lederr("ERROR: You need to control at least 1 LED!\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  if ((buflen % WS2812_RW_PIXEL_SIZE) != 0)
+    {
+      lederr("ERROR: LED values must be 24bit packed in 32bit\n");
+      set_errno(EINVAL);
+      return -1;
+    }
+
+  nxsem_wait(&priv->exclsem);
+
+  start_led = filep->f_pos / WS2812_RW_PIXEL_SIZE;
+  tx_pixel = priv->tx_buf + WS2812_RST_CYCLES + \
+             start_led * WS2812_BYTES_PER_LED;
+
+  end_led = start_led + (buflen / WS2812_RW_PIXEL_SIZE) - 1;
+  ledinfo("Start: %d End: %d\n", start_led, end_led);
+
+  if (end_led  > (priv->nleds -1))
+    {
+      end_led = priv->nleds - 1;
+    }
+
+  for (cur_led = start_led; cur_led <= end_led; cur_led++)
+    {
+      ws2812_pack(tx_pixel, *pixel_buf & 0xffffff);
+      pixel_buf++;
+      tx_pixel += WS2812_BYTES_PER_LED;
+      written += WS2812_RW_PIXEL_SIZE;
+    }
+

Review comment:
       Sounds good to me.  I have thoughts to extend it with some IOCTL, but that would be in a future PR.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] baschuuuu commented on pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
baschuuuu commented on pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#issuecomment-981904885


   @btashton  would you share your test program?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [incubator-nuttx] acassis edited a comment on pull request #1797: LED: Support for WS2812 LED controller (aka Adafruit NeoPixel)

Posted by GitBox <gi...@apache.org>.
acassis edited a comment on pull request #1797:
URL: https://github.com/apache/incubator-nuttx/pull/1797#issuecomment-981912206


   @baschuuuu when I added support to APA102 I added a test program to it, see: apps/examples/apa102 maybe you can adapt it to work on WS2812 as well.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org