Hi.
SDK:11.0
Our product is ready to add a ws2812 on the basis of the original peripheral and drive the implementation through hardware pwm. The lamp has 30 beads, each requiring 3byte to achieve RGB three colors. Therefore, a ws2812 requires 720 bytes of data. I am experiencing insufficient IRAM while loading the PWM array. Is there any other optimization I can do to enable 720byte data to be written to drive the entire strip each time ’nrf_drv_pwm_simple_playback‘ is called.
https://www.mouser.com/pdfDocs/WS2812B-2020_V10_EN_181106150240761.pdf
#define WS2812_T1H 14 | 0x8000 // In each value, the most significant bit (15)determines the polarity of the output and theothers (14-0) compose the 15-bit value #define WS2812_T0H 6 | 0x8000 #define LED_MATRIX_WIDTH 30 #define LED_MATRIX_HEIGHT 1 #define WS2812_PIN 6 #define LED_MATRIX_TOTAL_BYTE_WIDTH LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT * 3 #define LED_MATRIX_TOTAL_BIT_WIDTH LED_MATRIX_TOTAL_BYTE_WIDTH * 8 static rgb_color_t led_matrix_buffer[LED_MATRIX_WIDTH][LED_MATRIX_HEIGHT]; static nrf_drv_pwm_t m_pwm2 = NRF_DRV_PWM_INSTANCE(0); static nrf_pwm_values_individual_t pwm_duty_cycle_values[LED_MATRIX_TOTAL_BIT_WIDTH]; static nrf_pwm_sequence_t pwm_sequence = { .values.p_individual = pwm_duty_cycle_values, .length = (sizeof(pwm_duty_cycle_values) / sizeof(uint16_t)), .repeats = 0, .end_delay = 0 }; #define USED_PWM(idx) (1UL << idx) static uint8_t m_used = 0; static uint32_t pwm_init(void) { nrf_drv_pwm_config_t const pwm_config = { .output_pins = { NRF_DRV_PWM_PIN_NOT_USED, // channel 0 WS2812_PIN , // channel 1 NRF_DRV_PWM_PIN_NOT_USED, // channel 2 NRF_DRV_PWM_PIN_NOT_USED, // channel 3 }, .irq_priority = APP_IRQ_PRIORITY_LOW, .base_clock = NRF_PWM_CLK_16MHz, .count_mode = NRF_PWM_MODE_UP, // WS2812 protocol requires a 800 kHz PWM frequency. PWM Top value = 20 and Base Clock = 16 MHz achieves this .top_value = 20, .load_mode = NRF_PWM_LOAD_INDIVIDUAL, .step_mode = NRF_PWM_STEP_AUTO }; APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm2, &pwm_config, pwm_handler)); m_used |= USED_PWM(0); //return nrf_drv_pwm_init(&m_pwm2, &pwm_config, pwm_handler); } static void convert_rgb_to_pwm_sequence(void) { uint8_t * ptr = (uint8_t *)led_matrix_buffer; uint32_t i = 0; for(int led = 0; led < LED_MATRIX_TOTAL_BYTE_WIDTH; led++) { for(int bit = 7; bit >= 0; bit--) { uint8_t code = (*ptr >> bit) & 0x01; uint16_t pwm_value = 0; if(code == 1) { pwm_value = WS2812_T1H; } else { pwm_value = WS2812_T0H; } pwm_duty_cycle_values[i++].channel_1 = pwm_value; } ptr++; } } uint32_t drv_ws2812_init(void) { volatile uint32_t length = sizeof(pwm_duty_cycle_values) ; volatile uint32_t size = sizeof(led_matrix_buffer); memset(led_matrix_buffer, 0x00, sizeof(led_matrix_buffer)); return pwm_init(); } uint32_t drv_ws2812_display(void) { if(!pwm_sequencue_finished) { return NRF_ERROR_BUSY; } convert_rgb_to_pwm_sequence(); pwm_sequencue_finished = false; (void)nrf_drv_pwm_simple_playback(&m_pwm2, &pwm_sequence, 1, NRF_DRV_PWM_FLAG_STOP); }
Best regard!