Goodday all
Im trying to drive some Neopixel LEDs with 52840DK SDK_17.1.0. and have been following this example. https://devzone.nordicsemi.com/f/nordic-q-a/70560/nrfx_i2s-library-never-recognized
The code works but there is a severe flicker on my LEDs as if they are switching on and off continuously. I have played around with the i2s_init() function but the best I can get is a solid white. I have a suspicion the method this code use to address the Neopixels is not correct
Any advice or dedicated neopixel libraries avail would be greatly appreciated
Other than the flickering, the colors and brightness work as expected.
#include "nrf_delay.h"
#include "nrf_drv_i2s.h"
#define neopixels_number 20 /**< Neopixels number. */
#define neopixel_pin 29 /**< Neopixel pin number. */
#define reset_bits 6 /**< Reset bits. */
#define i2s_buffer_size ((3 * neopixels_number) + reset_bits) /**< i2d buffer size for driving the neopixel. */
static uint32_t m_buffer_tx[i2s_buffer_size];
static uint32_t * volatile mp_block_to_fill = NULL;
static void set_neopixel_data(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
/**@brief Function for handeling the i2s data.
*
*/
static void i2s_data_handler(nrf_drv_i2s_buffers_t const * p_released,
uint32_t status)
{
ret_code_t err_code;
ASSERT(p_released);
if (!(status & NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED))
{
return;
}
if (!p_released->p_rx_buffer)
{
nrf_drv_i2s_buffers_t const next_buffers = {
.p_tx_buffer = m_buffer_tx,
};
err_code = nrf_drv_i2s_next_buffers_set(&next_buffers);
APP_ERROR_CHECK(err_code);
mp_block_to_fill = m_buffer_tx;
}
else
{
err_code = nrf_drv_i2s_next_buffers_set(p_released);
APP_ERROR_CHECK(err_code);
mp_block_to_fill = (uint32_t *)p_released->p_tx_buffer;
}
}
/**@brief Function for calculating the rgb channels data value.
*
*/
static uint32_t rgb_channels_value(uint8_t channel_level)
{
uint32_t value = 0;
// 0
if(channel_level == 0) {
value = 0x88888888;
}
// 255
else if (channel_level == 255) {
value = 0xeeeeeeee;
}
else
{
// apply 4-bit 0xe HIGH pattern wherever level bits are 1.
value = 0x88888888;
for (uint8_t i = 0; i < 8; i++)
{
if((1 << i) & channel_level)
{
uint32_t mask = ~(0x0f << 4*i);
uint32_t patt = (0x0e << 4*i);
value = (value & mask) | patt;
}
}
// swap 16 bits
value = (value >> 16) | (value << 16);
}
return value;
}
/**@brief Function for setting the leds (rgb) data in the i2s buffer.
*
*@param led_n neopixel number in the array starting with 0.
*@param r red led level.
*@param g green led level.
*@param b blue led level.
*/
static void set_neopixel_data(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b)
{
for(int i = 0; i < (3 * neopixels_number); i += 3)
{
if (i == (3 * led_index))
{
m_buffer_tx[i] = rgb_channels_value(g);
m_buffer_tx[i+1] = rgb_channels_value(r);
m_buffer_tx[i+2] = rgb_channels_value(b);
}
else
{
m_buffer_tx[i] = 0x88888888;
m_buffer_tx[i+1] = 0x88888888;
m_buffer_tx[i+2] = 0x88888888;
}
}
// reset
for(int i = (3 * neopixels_number); i < i2s_buffer_size; i++)
{
m_buffer_tx[i] = 0;
}
nrf_drv_i2s_buffers_t const initial_buffers = {
.p_tx_buffer = m_buffer_tx,
};
}
/**@brief Function for initialising the i2s.
*
*/
static void i2s_init()
{
uint32_t err_code = NRF_SUCCESS;
nrf_drv_i2s_config_t config = NRF_DRV_I2S_DEFAULT_CONFIG;
config.sdin_pin = NRFX_I2S_PIN_NOT_USED;
config.sdout_pin = neopixel_pin;
config.mck_setup = NRF_I2S_MCK_32MDIV10;
config.ratio = NRF_I2S_RATIO_32X;
config.channels = NRF_I2S_CHANNELS_STEREO;
err_code = nrf_drv_i2s_init(&config, i2s_data_handler);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for application main entry.
*/
int main(void)
{
ret_code_t err_code;
bool erase_bonds;
nrf_drv_i2s_buffers_t const initial_buffers =
{
.p_tx_buffer = m_buffer_tx
};
i2s_init();
err_code = nrf_drv_i2s_start(&initial_buffers, i2s_buffer_size, 0);
APP_ERROR_CHECK(err_code);
// Enter main loop.
for (;;)
{
set_neopixel_data(0,0,0,50); // Ttest some random colors
set_neopixel_data(1,0,0,50); //
set_neopixel_data(2,0,0,50); //
set_neopixel_data(3,0,0,50); //
set_neopixel_data(4,0,0,50); //
set_neopixel_data(5,0,0,50); //
set_neopixel_data(6,0,0,50); //
set_neopixel_data(0,0,0,50); //
set_neopixel_data(7,0,0,50); //
set_neopixel_data(8,0,0,50); //
set_neopixel_data(9,0,0,50); //
set_neopixel_data(10,0,0,50); //
set_neopixel_data(11,0,50,0); //
set_neopixel_data(12,0,50,0); //
set_neopixel_data(13,0,50,0); //
set_neopixel_data(14,0,50,0); //
set_neopixel_data(15,50,0,0); //
set_neopixel_data(16,50,0,0); //
set_neopixel_data(17,50,0,0); //
set_neopixel_data(18,50,0,0); //
set_neopixel_data(19,50,0,0); //
set_neopixel_data(20,50,0,0); //
}
}
/**
* @}
*/
/**/
