Skip to content

Instantly share code, notes, and snippets.

@lionello
Last active September 16, 2017 01:08
Show Gist options
  • Save lionello/7c414558da6ef2653a69 to your computer and use it in GitHub Desktop.
Save lionello/7c414558da6ef2653a69 to your computer and use it in GitHub Desktop.
Bit-banging a WS2812/WS2812B LED on Nordic nRF51 platform (nRF51422 or nRF51822)
#define NOP() __asm volatile ( "NOP" )
void ws2812_init(void)
{
NRF_GPIO->PIN_CNF[PIN_WS_DIN] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos)
| (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
}
void ws2812_rgb(uint8_t r, uint8_t g, uint8_t b)
{
const uint8_t END = 1;
int32_t a = (g<<24)|(r<<16)|(b<<8)|END;
while (1) {
if (a==END<<24)
break;
NRF_GPIO->OUTSET = (1<<PIN_WS_DIN);
if (a >= 0)
{
a <<= 1;
NOP();
NRF_GPIO->OUTCLR = (1<<PIN_WS_DIN);
NOP();
NOP();
NOP();
NOP();
}
else
{
a <<= 1;
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NRF_GPIO->OUTCLR = (1<<PIN_WS_DIN);
NOP();
}
}
}
@lionello
Copy link
Author

This code assumes the CPU runs at 16MHz.

@morganrallen
Copy link

curious if you're using a level shifter or if you've manage to get it working at 3.3v.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment