1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include "syscfg/syscfg.h"
21
22 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
23
24 #include "mesh/mesh.h"
25 #include "bsp.h"
26 #include "pwm/pwm.h"
27 #include "light_model.h"
28 #include "ws2812.h"
29
30 #if (!MYNEWT_VAL(USE_NEOPIXEL))
31 #if MYNEWT_VAL(PWM_0)
32 struct pwm_dev *pwm0;
33 #endif
34 #if MYNEWT_VAL(PWM_1)
35 struct pwm_dev *pwm1;
36 #endif
37 #if MYNEWT_VAL(PWM_2)
38 struct pwm_dev *pwm2;
39 #endif
40 #if MYNEWT_VAL(PWM_3)
41 struct pwm_dev *pwm3;
42 #endif
43
44 static uint16_t top_val;
45 #endif
46
47 #if (MYNEWT_VAL(USE_NEOPIXEL))
48 static uint32_t neopixel[WS2812_NUM_LED];
49 #endif
50
51 static u8_t gen_onoff_state;
52 static s16_t gen_level_state;
53
light_set_lightness(u8_t percentage)54 static void light_set_lightness(u8_t percentage)
55 {
56 #if (!MYNEWT_VAL(USE_NEOPIXEL))
57 int rc;
58
59 uint16_t pwm_val = (uint16_t) (percentage * top_val / 100);
60
61 #if MYNEWT_VAL(PWM_0)
62 rc = pwm_set_duty_cycle(pwm0, 0, pwm_val);
63 assert(rc == 0);
64 #endif
65 #if MYNEWT_VAL(PWM_1)
66 rc = pwm_set_duty_cycle(pwm1, 0, pwm_val);
67 assert(rc == 0);
68 #endif
69 #if MYNEWT_VAL(PWM_2)
70 rc = pwm_set_duty_cycle(pwm2, 0, pwm_val);
71 assert(rc == 0);
72 #endif
73 #if MYNEWT_VAL(PWM_3)
74 rc = pwm_set_duty_cycle(pwm3, 0, pwm_val);
75 assert(rc == 0);
76 #endif
77 #else
78 int i;
79 u32_t lightness;
80 u8_t max_lightness = 0x1f;
81
82 lightness = (u8_t) (percentage * max_lightness / 100);
83
84 for (i = 0; i < WS2812_NUM_LED; i++) {
85 neopixel[i] = (lightness | lightness << 8 | lightness << 16);
86 }
87 ws2812_write(neopixel);
88 #endif
89 }
90
update_light_state(void)91 static void update_light_state(void)
92 {
93 u16_t level = (u16_t)gen_level_state;
94 int percent = 100 * level / 0xffff;
95
96 if (gen_onoff_state == 0) {
97 percent = 0;
98 }
99 light_set_lightness((uint8_t) percent);
100 }
101
light_model_gen_onoff_get(struct bt_mesh_model * model,u8_t * state)102 int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
103 {
104 *state = gen_onoff_state;
105 return 0;
106 }
107
light_model_gen_onoff_set(struct bt_mesh_model * model,u8_t state)108 int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
109 {
110 gen_onoff_state = state;
111 update_light_state();
112 return 0;
113 }
114
light_model_gen_level_get(struct bt_mesh_model * model,s16_t * level)115 int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
116 {
117 *level = gen_level_state;
118 return 0;
119 }
120
light_model_gen_level_set(struct bt_mesh_model * model,s16_t level)121 int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
122 {
123 gen_level_state = level;
124 if ((u16_t)gen_level_state > 0x0000) {
125 gen_onoff_state = 1;
126 }
127 if ((u16_t)gen_level_state == 0x0000) {
128 gen_onoff_state = 0;
129 }
130 update_light_state();
131 return 0;
132 }
133
light_model_light_lightness_get(struct bt_mesh_model * model,s16_t * lightness)134 int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
135 {
136 return light_model_gen_level_get(model, lightness);
137 }
138
light_model_light_lightness_set(struct bt_mesh_model * model,s16_t lightness)139 int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
140 {
141 return light_model_gen_level_set(model, lightness);
142 }
143
144 #if (!MYNEWT_VAL(USE_NEOPIXEL))
145 struct pwm_dev_cfg dev_conf = {
146 .n_cycles = 0,
147 .int_prio = 3,
148 };
149
150 #if MYNEWT_VAL(PWM_0)
151 static struct pwm_chan_cfg led1_conf = {
152 .pin = LED_1,
153 .inverted = true,
154 };
155 #endif
156
157 #if MYNEWT_VAL(PWM_1)
158 static struct pwm_chan_cfg led2_conf = {
159 .pin = LED_2,
160 .inverted = true,
161 };
162 #endif
163
164 #if MYNEWT_VAL(PWM_2)
165 static struct pwm_chan_cfg led3_conf = {
166 .pin = LED_3,
167 .inverted = true,
168 };
169 #endif
170 #endif
171
172 #if MYNEWT_VAL(PWM_3)
173 static struct pwm_chan_cfg led4_conf = {
174 .pin = LED_4,
175 .inverted = true,
176 };
177 #endif
178
179 #if (!MYNEWT_VAL(USE_NEOPIXEL))
init_pwm_dev(struct pwm_dev ** pwm,char * dev_name,struct pwm_chan_cfg * chan_cfg)180 void init_pwm_dev(struct pwm_dev **pwm, char *dev_name, struct pwm_chan_cfg *chan_cfg)
181 {
182 int rc = 0;
183
184 *pwm = (struct pwm_dev *) os_dev_open(dev_name, 0, NULL);
185 assert(pwm);
186 rc = pwm_configure_device(*pwm, &dev_conf);
187 assert(rc == 0);
188 rc = pwm_configure_channel(*pwm, 0, chan_cfg);
189 assert(rc == 0);
190 rc = pwm_enable(*pwm);
191 assert(rc == 0);
192 }
193
pwm_init(void)194 int pwm_init(void)
195 {
196
197 #if MYNEWT_VAL(PWM_0)
198 init_pwm_dev(&pwm0, "pwm0", &led1_conf);
199 #endif
200
201 #if MYNEWT_VAL(PWM_1)
202 init_pwm_dev(&pwm1, "pwm1", &led2_conf);
203 #endif
204
205 #if MYNEWT_VAL(PWM_2)
206 init_pwm_dev(&pwm2, "pwm2", &led3_conf);
207 #endif
208
209 #if MYNEWT_VAL(PWM_3)
210 init_pwm_dev(&pwm3, "pwm3", &led4_conf);
211 #endif
212
213 if (!pwm0) {
214 return 0;
215 }
216
217 top_val = (uint16_t) pwm_get_top_value(pwm0);
218 update_light_state();
219
220 return 0;
221 }
222 #endif
223 #endif
224
light_model_init(void)225 int light_model_init(void)
226 {
227 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
228 int rc;
229 #if (!MYNEWT_VAL(USE_NEOPIXEL))
230 rc = pwm_init();
231 assert(rc == 0);
232 #else
233 rc = ws2812_init();
234 assert(rc == 0);
235 update_light_state();
236 #endif
237 return rc;
238 #else
239 return 0;
240 #endif
241 }
242
243