act_led_display.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (c) 2017 Intel Corporation
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. * References:
  8. *
  9. * https://www.microbit.co.uk/device/screen
  10. * https://lancaster-university.github.io/microbit-docs/ubit/display/
  11. */
  12. #include <zephyr.h>
  13. #include <init.h>
  14. #include <board.h>
  15. #include <drivers/gpio.h>
  16. #include <device.h>
  17. #include <string.h>
  18. #include <soc.h>
  19. #include <errno.h>
  20. #define LOG_LEVEL 2
  21. #include <logging/log.h>
  22. LOG_MODULE_REGISTER(led);
  23. #include <display/led_display.h>
  24. #define MAX_DUTY (32 * 255)
  25. #ifdef BOARD_LED_MAP
  26. const led_map ledmaps[] = {
  27. BOARD_LED_MAP
  28. };
  29. struct pwm_chans{
  30. u8_t chan;
  31. u8_t gpio_num;
  32. };
  33. struct pwm_chans chan_gpio_num[] = {
  34. {0, 3}, {0, 4}, {0, 14}, {0, 36}, {0, 49},\
  35. {1, 5}, {1, 15}, {1, 37}, {1, 50},\
  36. {2, 6}, {2, 21}, {2, 38}, {2, 51},\
  37. {3, 7}, {3, 17}, {3, 39}, {3, 52},\
  38. {4, 8}, {4, 18}, {4, 40}, {4, 53},\
  39. {5, 9}, {5, 19}, {5, 41}, {5, 54},\
  40. {6, 10}, {6, 20}, {6, 42}, {6, 55},\
  41. {7, 11}, {7, 21}, {7, 43}, {7, 45}, {7, 56},\
  42. {8, 12}, {8, 22}, {8, 44}, {8, 46}, {8, 57},\
  43. };
  44. typedef struct
  45. {
  46. u8_t led_id;
  47. u8_t led_pin;
  48. u8_t led_pwm;
  49. u8_t active_level;
  50. u8_t state;
  51. led_pixel_value pixel_value;
  52. struct device *op_dev;
  53. }led_dot;
  54. typedef struct
  55. {
  56. u16_t led_dot_num;
  57. led_dot pixel[ARRAY_SIZE(ledmaps)];
  58. }led_panel;
  59. static led_panel led;
  60. static u16_t get_chan(int led_index)
  61. {
  62. for(int i = 0; i < sizeof(chan_gpio_num)/sizeof(struct pwm_chans); i++)
  63. if(led_index == chan_gpio_num[i].gpio_num)
  64. return chan_gpio_num[i].chan;
  65. return -EINVAL;
  66. }
  67. static int led_display_init(struct device *dev)
  68. {
  69. int i = 0;
  70. ARG_UNUSED(dev);
  71. led.led_dot_num = ARRAY_SIZE(ledmaps);
  72. for (i = 0; i < led.led_dot_num; i ++) {
  73. led_dot *dot = &led.pixel[i];
  74. dot->led_pin = ledmaps[i].led_pin;
  75. dot->led_id = ledmaps[i].led_id;
  76. dot->active_level = ledmaps[i].active_level;
  77. dot->led_pwm = ledmaps[i].led_pwm;
  78. if (dot->led_pwm != 0xff) {
  79. #ifdef CONFIG_PWM
  80. dot->op_dev = device_get_binding("PWM");
  81. #endif
  82. } else {
  83. if(dot->led_pin/32 == 0)
  84. dot->op_dev = device_get_binding("GPIOA");
  85. else if(dot->led_pin/32 == 1)
  86. dot->op_dev = device_get_binding("GPIOB");
  87. else if(dot->led_pin/32 == 2)
  88. dot->op_dev = device_get_binding("GPIOC");
  89. gpio_pin_configure(dot->op_dev, dot->led_pin%32, GPIO_OUTPUT_ACTIVE);
  90. }
  91. if (!dot->op_dev) {
  92. LOG_ERR("cannot found dev gpio \n");
  93. goto err_exit;
  94. }
  95. memset(&dot->pixel_value, 0 , sizeof(dot->pixel_value));
  96. }
  97. return 0;
  98. err_exit:
  99. return -1;
  100. }
  101. SYS_INIT(led_display_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
  102. #endif
  103. int led_draw_pixel(int led_id, u32_t color, pwm_breath_ctrl_t *ctrl)
  104. {
  105. #ifdef BOARD_LED_MAP
  106. int i = 0;
  107. led_dot *dot = NULL;
  108. led_pixel_value pixel;
  109. int chan;
  110. memcpy(&pixel, &color, 4);
  111. for (i = 0; i < led.led_dot_num; i ++) {
  112. dot = &led.pixel[i];
  113. if (dot->led_id == led_id) {
  114. break;
  115. }
  116. }
  117. if (!dot) {
  118. return 0;
  119. }
  120. dot->pixel_value = pixel;
  121. switch (pixel.op_code) {
  122. case LED_OP_OFF:
  123. if (dot->led_pwm) {
  124. #ifdef CONFIG_PWM
  125. chan = get_chan(dot->led_pin);
  126. if (dot->active_level) {
  127. pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, 0, START_VOLTAGE_HIGH);
  128. } else {
  129. pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, MAX_DUTY, START_VOLTAGE_HIGH);
  130. }
  131. #endif
  132. } else {
  133. gpio_pin_set(dot->op_dev, dot->led_pin, !(dot->active_level));
  134. }
  135. break;
  136. case LED_OP_ON:
  137. if (dot->led_pwm) {
  138. #ifdef CONFIG_PWM
  139. chan = get_chan(dot->led_pin);
  140. if (dot->active_level) {
  141. pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, MAX_DUTY, START_VOLTAGE_HIGH);
  142. } else {
  143. pwm_pin_set_cycles(dot->op_dev, chan, MAX_DUTY, 0, START_VOLTAGE_HIGH);
  144. }
  145. #endif
  146. } else {
  147. gpio_pin_set(dot->op_dev, dot->led_pin, dot->active_level);
  148. }
  149. break;
  150. case LED_OP_BREATH:
  151. if (dot->led_pwm) {
  152. #ifdef CONFIG_PWM
  153. chan = get_chan(dot->led_pin);
  154. pwm_set_breath_mode(dot->op_dev, chan, ctrl);
  155. #endif
  156. }
  157. break;
  158. case LED_OP_BLINK:
  159. if (dot->led_pwm) {
  160. #ifdef CONFIG_PWM
  161. chan = get_chan(dot->led_pin);
  162. pwm_pin_set_cycles(dot->op_dev, chan, dot->pixel_value.period, dot->pixel_value.pulse, pixel.start_state);
  163. //pwm_pin_set_usec(dot->op_dev, dot->led_pwm, dot->pixel_value.period * 1000, dot->pixel_value.pulse * 1000, pixel.start_state);
  164. #endif
  165. }
  166. }
  167. #endif
  168. return 0;
  169. }