/*
|
* Licensed to the Apache Software Foundation (ASF) under one
|
* or more contributor license agreements. See the NOTICE file
|
* distributed with this work for additional information
|
* regarding copyright ownership. The ASF licenses this file
|
* to you under the Apache License, Version 2.0 (the
|
* "License"); you may not use this file except in compliance
|
* with the License. You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing,
|
* software distributed under the License is distributed on an
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
* KIND, either express or implied. See the License for the
|
* specific language governing permissions and limitations
|
* under the License.
|
*/
|
|
#include "nimble_syscfg.h"
|
|
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
|
|
#include "mesh/mesh.h"
|
#include "bsp.h"
|
#include "pwm/pwm.h"
|
#include "light_model.h"
|
#include "ws2812.h"
|
|
#if (!MYNEWT_VAL(USE_NEOPIXEL))
|
#if MYNEWT_VAL(PWM_0)
|
struct pwm_dev *pwm0;
|
#endif
|
#if MYNEWT_VAL(PWM_1)
|
struct pwm_dev *pwm1;
|
#endif
|
#if MYNEWT_VAL(PWM_2)
|
struct pwm_dev *pwm2;
|
#endif
|
#if MYNEWT_VAL(PWM_3)
|
struct pwm_dev *pwm3;
|
#endif
|
|
static uint16_t top_val;
|
#endif
|
|
#if (MYNEWT_VAL(USE_NEOPIXEL))
|
static uint32_t neopixel[WS2812_NUM_LED];
|
#endif
|
|
static uint8_t gen_onoff_state;
|
static int16_t gen_level_state;
|
|
static void light_set_lightness(uint8_t percentage)
|
{
|
#if (!MYNEWT_VAL(USE_NEOPIXEL))
|
int rc;
|
|
uint16_t pwm_val = (uint16_t) (percentage * top_val / 100);
|
|
#if MYNEWT_VAL(PWM_0)
|
rc = pwm_set_duty_cycle(pwm0, 0, pwm_val);
|
assert(rc == 0);
|
#endif
|
#if MYNEWT_VAL(PWM_1)
|
rc = pwm_set_duty_cycle(pwm1, 0, pwm_val);
|
assert(rc == 0);
|
#endif
|
#if MYNEWT_VAL(PWM_2)
|
rc = pwm_set_duty_cycle(pwm2, 0, pwm_val);
|
assert(rc == 0);
|
#endif
|
#if MYNEWT_VAL(PWM_3)
|
rc = pwm_set_duty_cycle(pwm3, 0, pwm_val);
|
assert(rc == 0);
|
#endif
|
#else
|
int i;
|
uint32_t lightness;
|
uint8_t max_lightness = 0x1f;
|
|
lightness = (uint8_t) (percentage * max_lightness / 100);
|
|
for (i = 0; i < WS2812_NUM_LED; i++) {
|
neopixel[i] = (lightness | lightness << 8 | lightness << 16);
|
}
|
ws2812_write(neopixel);
|
#endif
|
}
|
|
static void update_light_state(void)
|
{
|
uint16_t level = (uint16_t)gen_level_state;
|
int percent = 100 * level / 0xffff;
|
|
if (gen_onoff_state == 0) {
|
percent = 0;
|
}
|
light_set_lightness((uint8_t) percent);
|
}
|
|
int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
|
{
|
*state = gen_onoff_state;
|
return 0;
|
}
|
|
int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
|
{
|
gen_onoff_state = state;
|
update_light_state();
|
return 0;
|
}
|
|
int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
|
{
|
*level = gen_level_state;
|
return 0;
|
}
|
|
int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
|
{
|
gen_level_state = level;
|
if ((uint16_t)gen_level_state > 0x0000) {
|
gen_onoff_state = 1;
|
}
|
if ((uint16_t)gen_level_state == 0x0000) {
|
gen_onoff_state = 0;
|
}
|
update_light_state();
|
return 0;
|
}
|
|
int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
|
{
|
return light_model_gen_level_get(model, lightness);
|
}
|
|
int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
|
{
|
return light_model_gen_level_set(model, lightness);
|
}
|
|
#if (!MYNEWT_VAL(USE_NEOPIXEL))
|
struct pwm_dev_cfg dev_conf = {
|
.n_cycles = 0,
|
.int_prio = 3,
|
};
|
|
#if MYNEWT_VAL(PWM_0)
|
static struct pwm_chan_cfg led1_conf = {
|
.pin = LED_1,
|
.inverted = true,
|
};
|
#endif
|
|
#if MYNEWT_VAL(PWM_1)
|
static struct pwm_chan_cfg led2_conf = {
|
.pin = LED_2,
|
.inverted = true,
|
};
|
#endif
|
|
#if MYNEWT_VAL(PWM_2)
|
static struct pwm_chan_cfg led3_conf = {
|
.pin = LED_3,
|
.inverted = true,
|
};
|
#endif
|
#endif
|
|
#if MYNEWT_VAL(PWM_3)
|
static struct pwm_chan_cfg led4_conf = {
|
.pin = LED_4,
|
.inverted = true,
|
};
|
#endif
|
|
#if (!MYNEWT_VAL(USE_NEOPIXEL))
|
void init_pwm_dev(struct pwm_dev **pwm, char *dev_name, struct pwm_chan_cfg *chan_cfg)
|
{
|
int rc = 0;
|
|
*pwm = (struct pwm_dev *) os_dev_open(dev_name, 0, NULL);
|
assert(pwm);
|
rc = pwm_configure_device(*pwm, &dev_conf);
|
assert(rc == 0);
|
rc = pwm_configure_channel(*pwm, 0, chan_cfg);
|
assert(rc == 0);
|
rc = pwm_enable(*pwm);
|
assert(rc == 0);
|
}
|
|
int pwm_init(void)
|
{
|
|
#if MYNEWT_VAL(PWM_0)
|
init_pwm_dev(&pwm0, "pwm0", &led1_conf);
|
#endif
|
|
#if MYNEWT_VAL(PWM_1)
|
init_pwm_dev(&pwm1, "pwm1", &led2_conf);
|
#endif
|
|
#if MYNEWT_VAL(PWM_2)
|
init_pwm_dev(&pwm2, "pwm2", &led3_conf);
|
#endif
|
|
#if MYNEWT_VAL(PWM_3)
|
init_pwm_dev(&pwm3, "pwm3", &led4_conf);
|
#endif
|
|
if (!pwm0) {
|
return 0;
|
}
|
|
top_val = (uint16_t) pwm_get_top_value(pwm0);
|
update_light_state();
|
|
return 0;
|
}
|
#endif
|
#endif
|
|
int light_model_init(void)
|
{
|
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
|
int rc;
|
#if (!MYNEWT_VAL(USE_NEOPIXEL))
|
rc = pwm_init();
|
assert(rc == 0);
|
#else
|
rc = ws2812_init();
|
assert(rc == 0);
|
update_light_state();
|
#endif
|
return rc;
|
#else
|
return 0;
|
#endif
|
}
|