Hello, I am currently trying to program a WS2812B LED matrix using output compare. There's 256 LEDs, and each LED is controlled by 24 bits. However, it has somewhat strict timing requirements, and my current code is not efficient enough. The LEDs are resetting after about half of the LEDs are lit up. I am new to programming and I am wondering if I can get some advice on how I can improve my code or improve the timing? Thank you!
#include <stdbool.h> #include <stdint.h> void outputBit(int value) { if (value == 1) { /* Pin high for approx. 0.8 us, then go low for 0.45 us */ NRF_P0->OUTSET = (1UL << 27); // Set pin to high NRF_TIMER0->CC[0] = 6; NRF_TIMER0->TASKS_START = 1; // Starts the clock signal while (!(NRF_TIMER0->EVENTS_COMPARE[0])); // Wait for event to occur NRF_TIMER0->TASKS_STOP = 1; // Starts the clock signal NRF_TIMER0->CC[0] = 4; NRF_TIMER0->EVENTS_COMPARE[0] = 0; // Clear the event NRF_TIMER0->TASKS_START = 1; // Starts the clock signal while (!(NRF_TIMER0->EVENTS_COMPARE[0])); // Wait for event to occur NRF_TIMER0->TASKS_STOP = 1; // Starts the clock signal NRF_TIMER0->EVENTS_COMPARE[0] = 0; // Clear the event } else { /* Pin high for approx. 0.35 us, then go low for 0.85 us */ NRF_P0->OUTSET = (1UL << 27); // Set pin to high NRF_TIMER0->CC[0] = 3; NRF_TIMER0->TASKS_START = 1; // Starts the clock signal while (!(NRF_TIMER0->EVENTS_COMPARE[0])); // Wait for event to occur NRF_TIMER0->TASKS_STOP = 1; // Starts the clock signal NRF_TIMER0->CC[0] = 7; NRF_TIMER0->EVENTS_COMPARE[0] = 0; // Clear the event NRF_TIMER0->TASKS_START = 1; // Starts the clock signal while (!(NRF_TIMER0->EVENTS_COMPARE[0])); // Wait for event to occur NRF_TIMER0->TASKS_STOP = 1; // Starts the clock signal NRF_TIMER0->EVENTS_COMPARE[0] = 0; // Clear the event } } int main(void) { NRF_P0->PIN_CNF[27] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); // Enable high frequency oscillator if not already enabled if (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { NRF_CLOCK->TASKS_HFCLKSTART = 1; while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { } } NRF_TIMER0->PRESCALER = 1; // 8MHz NRF_TIMER0->BITMODE = 0; NRF_TIMER0->SHORTS |= (1UL << 0); // Automatically clear the count whenever an event is triggered NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Task | (27 << GPIOTE_CONFIG_PSEL_Pos) | (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos); /*Connect TIMER event to GPIOTE out task*/ NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER0->EVENTS_COMPARE[0]; NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0]; NRF_PPI->CHENSET |= (1UL << 0); NRF_TIMER0->EVENTS_COMPARE[0] = 0; // Clear the event for (int i = 0; i < 6144; ++i) { outputBit(1); } }