1*042d53a7SEvalZero /**
2*042d53a7SEvalZero * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero * or more contributor license agreements. See the NOTICE file
4*042d53a7SEvalZero * distributed with this work for additional information
5*042d53a7SEvalZero * regarding copyright ownership. The ASF licenses this file
6*042d53a7SEvalZero * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero * with the License. You may obtain a copy of the License at
9*042d53a7SEvalZero *
10*042d53a7SEvalZero * http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero *
12*042d53a7SEvalZero * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero * software distributed under the License is distributed on an
14*042d53a7SEvalZero * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero * KIND, either express or implied. See the License for the
16*042d53a7SEvalZero * specific language governing permissions and limitations
17*042d53a7SEvalZero * under the License.
18*042d53a7SEvalZero */
19*042d53a7SEvalZero
20*042d53a7SEvalZero #include <assert.h>
21*042d53a7SEvalZero #include <string.h>
22*042d53a7SEvalZero #include <stdio.h>
23*042d53a7SEvalZero #include "sysinit/sysinit.h"
24*042d53a7SEvalZero #include "os/os.h"
25*042d53a7SEvalZero #include "bsp/bsp.h"
26*042d53a7SEvalZero #include "pwm/pwm.h"
27*042d53a7SEvalZero #include "nrfx.h"
28*042d53a7SEvalZero #include "nrfx_pwm.h"
29*042d53a7SEvalZero #include "ws2812.h"
30*042d53a7SEvalZero
31*042d53a7SEvalZero #define BITS_PER_SEQ (24)
32*042d53a7SEvalZero #define BIT0 (0x8000 | 6)
33*042d53a7SEvalZero #define BIT1 (0x8000 | 11)
34*042d53a7SEvalZero
35*042d53a7SEvalZero static const nrfx_pwm_t pwm = NRFX_PWM_INSTANCE(WS2812_PWM);
36*042d53a7SEvalZero
37*042d53a7SEvalZero static const nrfx_pwm_config_t pwm_config = {
38*042d53a7SEvalZero .output_pins = { WS2812_GPIO, NRFX_PWM_PIN_NOT_USED, NRFX_PWM_PIN_NOT_USED, NRFX_PWM_PIN_NOT_USED },
39*042d53a7SEvalZero .irq_priority = 3,
40*042d53a7SEvalZero .base_clock = NRF_PWM_CLK_16MHz,
41*042d53a7SEvalZero .count_mode = NRF_PWM_MODE_UP,
42*042d53a7SEvalZero .top_value = 20,
43*042d53a7SEvalZero .load_mode = NRF_PWM_LOAD_COMMON,
44*042d53a7SEvalZero .step_mode = NRF_PWM_STEP_AUTO,
45*042d53a7SEvalZero };
46*042d53a7SEvalZero
47*042d53a7SEvalZero static uint16_t pwm_seq_values[2][BITS_PER_SEQ];
48*042d53a7SEvalZero
49*042d53a7SEvalZero static const nrf_pwm_sequence_t pwm_seq[2] = {
50*042d53a7SEvalZero {
51*042d53a7SEvalZero .values.p_raw = pwm_seq_values[0],
52*042d53a7SEvalZero .length = BITS_PER_SEQ,
53*042d53a7SEvalZero .repeats = 0,
54*042d53a7SEvalZero .end_delay = 0,
55*042d53a7SEvalZero }, {
56*042d53a7SEvalZero .values.p_raw = pwm_seq_values[1],
57*042d53a7SEvalZero .length = BITS_PER_SEQ,
58*042d53a7SEvalZero .repeats = 0,
59*042d53a7SEvalZero .end_delay = 0,
60*042d53a7SEvalZero },
61*042d53a7SEvalZero };
62*042d53a7SEvalZero
63*042d53a7SEvalZero static uint32_t led_color[WS2812_NUM_LED];
64*042d53a7SEvalZero static int led_idx;
65*042d53a7SEvalZero
66*042d53a7SEvalZero static void
load_pixel(void)67*042d53a7SEvalZero load_pixel(void)
68*042d53a7SEvalZero {
69*042d53a7SEvalZero uint16_t *seq_values;
70*042d53a7SEvalZero uint32_t grb;
71*042d53a7SEvalZero int i;
72*042d53a7SEvalZero
73*042d53a7SEvalZero seq_values = pwm_seq_values[led_idx & 1];
74*042d53a7SEvalZero grb = led_color[led_idx];
75*042d53a7SEvalZero
76*042d53a7SEvalZero for (i = 0; i < BITS_PER_SEQ; i++) {
77*042d53a7SEvalZero *seq_values = grb & 0x800000 ? BIT1 : BIT0;
78*042d53a7SEvalZero grb <<= 1;
79*042d53a7SEvalZero seq_values++;
80*042d53a7SEvalZero }
81*042d53a7SEvalZero
82*042d53a7SEvalZero led_idx++;
83*042d53a7SEvalZero }
84*042d53a7SEvalZero
85*042d53a7SEvalZero static void
pwm_handler_func(nrfx_pwm_evt_type_t event_type)86*042d53a7SEvalZero pwm_handler_func(nrfx_pwm_evt_type_t event_type)
87*042d53a7SEvalZero {
88*042d53a7SEvalZero switch (event_type) {
89*042d53a7SEvalZero case NRFX_PWM_EVT_END_SEQ0:
90*042d53a7SEvalZero case NRFX_PWM_EVT_END_SEQ1:
91*042d53a7SEvalZero load_pixel();
92*042d53a7SEvalZero break;
93*042d53a7SEvalZero default:
94*042d53a7SEvalZero break;
95*042d53a7SEvalZero }
96*042d53a7SEvalZero }
97*042d53a7SEvalZero
98*042d53a7SEvalZero int
ws2812_init(void)99*042d53a7SEvalZero ws2812_init(void)
100*042d53a7SEvalZero {
101*042d53a7SEvalZero nrfx_err_t err;
102*042d53a7SEvalZero
103*042d53a7SEvalZero err = nrfx_pwm_init(&pwm, &pwm_config, pwm_handler_func);
104*042d53a7SEvalZero
105*042d53a7SEvalZero return err != NRFX_SUCCESS;
106*042d53a7SEvalZero }
107*042d53a7SEvalZero
108*042d53a7SEvalZero int
ws2812_write(const uint32_t * rgb)109*042d53a7SEvalZero ws2812_write(const uint32_t *rgb)
110*042d53a7SEvalZero {
111*042d53a7SEvalZero uint32_t grb;
112*042d53a7SEvalZero int i;
113*042d53a7SEvalZero
114*042d53a7SEvalZero for (i = 0; i < WS2812_NUM_LED; i++) {
115*042d53a7SEvalZero grb = 0;
116*042d53a7SEvalZero grb |= (rgb[i] & 0x00FF00) << 8;
117*042d53a7SEvalZero grb |= (rgb[i] & 0xFF0000) >> 8;
118*042d53a7SEvalZero grb |= (rgb[i] & 0x0000FF);
119*042d53a7SEvalZero
120*042d53a7SEvalZero led_color[i] = grb;
121*042d53a7SEvalZero }
122*042d53a7SEvalZero
123*042d53a7SEvalZero led_idx = 0;
124*042d53a7SEvalZero
125*042d53a7SEvalZero load_pixel();
126*042d53a7SEvalZero load_pixel();
127*042d53a7SEvalZero nrfx_pwm_complex_playback(&pwm, &pwm_seq[0], &pwm_seq[1], WS2812_NUM_LED,
128*042d53a7SEvalZero NRFX_PWM_FLAG_SIGNAL_END_SEQ0 |
129*042d53a7SEvalZero NRFX_PWM_FLAG_SIGNAL_END_SEQ1 |
130*042d53a7SEvalZero NRFX_PWM_FLAG_STOP);
131*042d53a7SEvalZero
132*042d53a7SEvalZero return 0;
133*042d53a7SEvalZero }
134