Skip to content

Instantly share code, notes, and snippets.

@monkbroc
Created September 16, 2018 23:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monkbroc/e204b870e776460ac45148fc1dda83d7 to your computer and use it in GitHub Desktop.
Save monkbroc/e204b870e776460ac45148fc1dda83d7 to your computer and use it in GitHub Desktop.
Hardware accelerated Neopixel for nRF52840
#include "application.h"
#include "nrfx_pwm.h"
#include "nrf_gpio.h"
#include "pinmap_impl.h"
SYSTEM_MODE(MANUAL);
#define PIXEL_COUNT 44
#define BITS_PER_PIXEL 24
#define pin D4
// D4 { NRF_PORT_1, 8, PIN_MODE_NONE, PF_NONE, ADC_CHANNEL_NONE, 1, 0, EXTI_CHANNEL_NONE},
#define NRFX_PWM_DUTY_INVERTED 0x8000
#define BIT0 (NRFX_PWM_DUTY_INVERTED | 5)
#define BIT1 (NRFX_PWM_DUTY_INVERTED | 14)
uint16_t seq_values[BITS_PER_PIXEL * PIXEL_COUNT] = { BIT0 };
uint8_t nrf_pins[NRF_PWM_CHANNEL_COUNT] = {
NRFX_PWM_PIN_NOT_USED,
NRFX_PWM_PIN_NOT_USED,
NRFX_PWM_PIN_NOT_USED,
NRFX_PWM_PIN_NOT_USED,
};
const nrfx_pwm_t pwms[] = {
NRFX_PWM_INSTANCE(0),
NRFX_PWM_INSTANCE(1),
NRFX_PWM_INSTANCE(2),
NRFX_PWM_INSTANCE(3)
};
void sequenceHandler(nrfx_pwm_evt_type_t event_type);
uint32_t Color(uint8_t r, uint8_t g, uint8_t b);
uint32_t Wheel(uint8_t WheelPos);
void show();
void rainbow();
void setPixelColor(uint8_t i, uint32_t color);
void setup() {
ret_code_t ret_code;
NRF5x_Pin_Info* PIN_MAP = HAL_Pin_Map();
uint8_t pwm_num = PIN_MAP[pin].pwm_instance;
uint8_t pwm_channel = PIN_MAP[pin].pwm_channel;
nrf_pwm_clk_t pwm_clock = NRF_PWM_CLK_16MHz;
uint16_t period_hwu = 20; // 800 kHz with 16 MHz clock
nrf_pins[pwm_channel] = NRF_GPIO_PIN_MAP(PIN_MAP[pin].gpio_port, PIN_MAP[pin].gpio_pin);
nrfx_pwm_config_t const config = {
.output_pins =
{
nrf_pins[0], // channel 0
nrf_pins[1], // channel 1
nrf_pins[2], // channel 2
nrf_pins[3], // channel 3
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,
.base_clock = pwm_clock,
.count_mode = NRF_PWM_MODE_UP,
.top_value = period_hwu,
.load_mode = NRF_PWM_LOAD_COMMON,
.step_mode = NRF_PWM_STEP_AUTO
};
ret_code = nrfx_pwm_init(&pwms[pwm_num], &config, sequenceHandler);
if (ret_code)
{
return;
}
HAL_Set_Pin_Function(pin, PF_PWM);
}
bool started = false;
uint32_t stopTime = 0;
void loop() {
if (started || millis() - stopTime < 20) {
return;
}
rainbow();
}
void show() {
started = true;
ret_code_t ret_code;
NRF5x_Pin_Info* PIN_MAP = HAL_Pin_Map();
uint8_t pwm_num = PIN_MAP[pin].pwm_instance;
nrf_pwm_sequence_t const seq = {
.values = { .p_common = seq_values },
.length = NRF_PWM_VALUES_LENGTH(seq_values),
.repeats = 0,
.end_delay = 0
};
ret_code = nrfx_pwm_simple_playback(&pwms[pwm_num], &seq, 1, NRFX_PWM_FLAG_STOP);
if (ret_code)
{
return;
}
}
void sequenceHandler(nrfx_pwm_evt_type_t event_type) {
if (event_type == NRFX_PWM_EVT_STOPPED) {
started = false;
stopTime = millis();
}
}
/* Fun! */
void rainbow() {
static uint8_t j = 0;
for(uint8_t i = 0; i < PIXEL_COUNT; i++) {
setPixelColor(i, Wheel(4 * i + j));
}
show();
j++;
}
uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
return (g << 16) | (r << 8) | b;
}
uint32_t Wheel(uint8_t WheelPos) {
if(WheelPos < 85) {
return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
void setPixelColor(uint8_t i, uint32_t color) {
uint16_t* p = &seq_values[i * BITS_PER_PIXEL];
uint32_t mask = 0x00800000;
while (mask) {
if (color & mask) {
*p = BIT1;
} else {
*p = BIT0;
}
mask >>= 1;
p++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment