123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /*
- * Copyright (c) 2017 Intel Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /*
- * References:
- *
- * https://www.microbit.co.uk/device/screen
- * https://lancaster-university.github.io/microbit-docs/ubit/display/
- */
- #include <zephyr.h>
- #include <init.h>
- #include <board.h>
- #include <drivers/gpio.h>
- #include <device.h>
- #include <string.h>
- #include <soc.h>
- #include <errno.h>
- #define LOG_LEVEL 2
- #include <logging/log.h>
- LOG_MODULE_REGISTER(led);
- #include <display/led_display.h>
- #define MAX_DUTY (32 * 255)
- #ifdef BOARD_LED_MAP
- const led_map ledmaps[] = {
- BOARD_LED_MAP
- };
-
- struct pwm_chans{
- u8_t chan;
- u8_t gpio_num;
- };
- struct pwm_chans chan_gpio_num[] = {
- {0, 3}, {0, 4}, {0, 14}, {0, 36}, {0, 49},\
- {1, 5}, {1, 15}, {1, 37}, {1, 50},\
- {2, 6}, {2, 21}, {2, 38}, {2, 51},\
- {3, 7}, {3, 17}, {3, 39}, {3, 52},\
- {4, 8}, {4, 18}, {4, 40}, {4, 53},\
- {5, 9}, {5, 19}, {5, 41}, {5, 54},\
- {6, 10}, {6, 20}, {6, 42}, {6, 55},\
- {7, 11}, {7, 21}, {7, 43}, {7, 45}, {7, 56},\
- {8, 12}, {8, 22}, {8, 44}, {8, 46}, {8, 57},\
- };
- typedef struct
- {
- u8_t led_id;
- u8_t led_pin;
- u8_t led_pwm;
- u8_t active_level;
- u8_t state;
- led_pixel_value pixel_value;
- struct device *op_dev;
- }led_dot;
- typedef struct
- {
- u16_t led_dot_num;
- led_dot pixel[ARRAY_SIZE(ledmaps)];
- }led_panel;
- static led_panel led;
- static u16_t get_chan(int led_index)
- {
- for(int i = 0; i < sizeof(chan_gpio_num)/sizeof(struct pwm_chans); i++)
- if(led_index == chan_gpio_num[i].gpio_num)
- return chan_gpio_num[i].chan;
- return -EINVAL;
- }
- static int led_display_init(struct device *dev)
- {
- int i = 0;
- ARG_UNUSED(dev);
- led.led_dot_num = ARRAY_SIZE(ledmaps);
- for (i = 0; i < led.led_dot_num; i ++) {
- led_dot *dot = &led.pixel[i];
- dot->led_pin = ledmaps[i].led_pin;
- dot->led_id = ledmaps[i].led_id;
- dot->active_level = ledmaps[i].active_level;
- dot->led_pwm = ledmaps[i].led_pwm;
- if (dot->led_pwm != 0xff) {
- #ifdef CONFIG_PWM
- dot->op_dev = device_get_binding("PWM");
- #endif
- } else {
- if(dot->led_pin/32 == 0)
- dot->op_dev = device_get_binding("GPIOA");
- else if(dot->led_pin/32 == 1)
- dot->op_dev = device_get_binding("GPIOB");
- else if(dot->led_pin/32 == 2)
- dot->op_dev = device_get_binding("GPIOC");
- gpio_pin_configure(dot->op_dev, dot->led_pin%32, GPIO_OUTPUT_ACTIVE);
- }
- if (!dot->op_dev) {
- LOG_ERR("cannot found dev gpio \n");
- goto err_exit;
- }
- memset(&dot->pixel_value, 0 , sizeof(dot->pixel_value));
- }
- return 0;
- err_exit:
- return -1;
- }
- SYS_INIT(led_display_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
- #endif
- int led_draw_pixel(int led_id, u32_t color, pwm_breath_ctrl_t *ctrl)
- {
- #ifdef BOARD_LED_MAP
- int i = 0;
- led_dot *dot = NULL;
- led_pixel_value pixel;
- int chan;
- memcpy(&pixel, &color, 4);
- for (i = 0; i < led.led_dot_num; i ++) {
- dot = &led.pixel[i];
- if (dot->led_id == led_id) {
- break;
- }
- }
- if (!dot) {
- return 0;
- }
- dot->pixel_value = pixel;
- switch (pixel.op_code) {
- case LED_OP_OFF:
- if (dot->led_pwm) {
- #ifdef CONFIG_PWM
- chan = get_chan(dot->led_pin);
- if (dot->active_level) {
- pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, 0, START_VOLTAGE_HIGH);
- } else {
- pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, MAX_DUTY, START_VOLTAGE_HIGH);
- }
- #endif
- } else {
- gpio_pin_set(dot->op_dev, dot->led_pin, !(dot->active_level));
- }
- break;
- case LED_OP_ON:
- if (dot->led_pwm) {
- #ifdef CONFIG_PWM
- chan = get_chan(dot->led_pin);
- if (dot->active_level) {
- pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, MAX_DUTY, START_VOLTAGE_HIGH);
- } else {
- pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, 0, START_VOLTAGE_HIGH);
- }
- #endif
- } else {
- gpio_pin_set(dot->op_dev, dot->led_pin, dot->active_level);
- }
- break;
- case LED_OP_BREATH:
- if (dot->led_pwm) {
- #ifdef CONFIG_PWM
- chan = get_chan(dot->led_pin);
- pwm_set_breath_mode(dot->op_dev, chan, ctrl);
- #endif
- }
- break;
- case LED_OP_BLINK:
- if (dot->led_pwm) {
- #ifdef CONFIG_PWM
- chan = get_chan(dot->led_pin);
- pwm_pin_set_cycles(dot->op_dev, chan, dot->pixel_value.period, dot->pixel_value.pulse, pixel.start_state);
- //pwm_pin_set_usec(dot->op_dev, dot->led_pwm, dot->pixel_value.period * 1000, dot->pixel_value.pulse * 1000, pixel.start_state);
- #endif
- }
- }
- #endif
- return 0;
- }
|