seg_led_manager.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file led manager interface
  8. */
  9. #include <os_common_api.h>
  10. #include <mem_manager.h>
  11. #include <led_manager.h>
  12. #include <kernel.h>
  13. #include <string.h>
  14. #include <sys_monitor.h>
  15. #define SYS_LOG_NO_NEWLINE
  16. #ifdef SYS_LOG_DOMAIN
  17. #undef SYS_LOG_DOMAIN
  18. #endif
  19. #define SYS_LOG_DOMAIN "seg_led_manager"
  20. #include <seg_led_manager.h>
  21. struct seg_led_image {
  22. sys_snode_t snode;
  23. uint8_t num[4];
  24. uint8_t icon;
  25. uint8_t flash_state:1;
  26. uint8_t num_state:4;
  27. uint8_t flash_cnt;
  28. uint8_t flash_period;
  29. uint8_t current_period;
  30. uint16_t flash_map;
  31. seg_led_flash_callback cb;
  32. };
  33. struct seg_led_manager_ctx_t {
  34. struct device *dev;
  35. struct seg_led_image image;
  36. uint8_t timeout;
  37. uint8_t update_direct:1;
  38. uint8_t timeout_event_lock:1;
  39. seg_led_timeout_callback timeout_cb;
  40. sys_slist_t image_list;
  41. };
  42. static struct seg_led_manager_ctx_t global_seg_led_manager_ctx;
  43. OS_MUTEX_DEFINE(seg_led_manager_mutex);
  44. static struct seg_led_manager_ctx_t *_seg_led_get_ctx(void)
  45. {
  46. return &global_seg_led_manager_ctx;
  47. }
  48. static int _seg_led_display_update(void)
  49. {
  50. int i = 0;
  51. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  52. if (ctx->timeout_event_lock || ctx->update_direct) {
  53. return 0;
  54. }
  55. for (i = 0 ; i < 8; i++) {
  56. bool display = (((1 << i) & ctx->image.icon) != 0);
  57. if ((ctx->image.flash_map & (1 << i))) {
  58. display = ctx->image.flash_state;
  59. }
  60. segled_display_icon(ctx->dev, i, display);
  61. }
  62. for (i = 0 ; i < 4; i++) {
  63. bool display = (((1 << i) & ctx->image.num_state) != 0);
  64. if ((ctx->image.flash_map & (1 << (i + 8)))) {
  65. display = ctx->image.flash_state;
  66. }
  67. segled_display_number(ctx->dev, i, ctx->image.num[i], display);
  68. }
  69. return 0;
  70. }
  71. int seg_led_display_number(uint8_t num_addr, uint8_t c, bool display)
  72. {
  73. int ret = 0;
  74. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  75. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  76. num_addr -= SLED_NUMBER1;
  77. if (!ctx->update_direct) {
  78. ctx->image.num[num_addr] = c;
  79. if (display) {
  80. ctx->image.num_state |= (1 << num_addr);
  81. } else {
  82. ctx->image.num_state &= (~(1 << num_addr));
  83. }
  84. }
  85. if (!ctx->timeout_event_lock || ctx->update_direct) {
  86. ret = segled_display_number(ctx->dev, num_addr, c, display);
  87. }
  88. os_mutex_unlock(&seg_led_manager_mutex);
  89. return ret;
  90. }
  91. int seg_led_display_string(uint8_t start_pos, const uint8_t *str, bool display)
  92. {
  93. int ret = 0;
  94. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  95. int len = strlen(str);
  96. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  97. start_pos -= SLED_NUMBER1;
  98. if (len + start_pos > sizeof(ctx->image.num)) {
  99. len = sizeof(ctx->image.num) - start_pos;
  100. }
  101. if (!ctx->update_direct) {
  102. for (int i = start_pos; i < (len + start_pos); i++) {
  103. if (display) {
  104. ctx->image.num_state |= (1 << i);
  105. } else {
  106. ctx->image.num_state &= (~(1 << i));
  107. }
  108. }
  109. memcpy(&ctx->image.num[start_pos], str, len);
  110. }
  111. if (!ctx->timeout_event_lock || ctx->update_direct) {
  112. ret = segled_display_number_string(ctx->dev, start_pos, str, display);
  113. }
  114. os_mutex_unlock(&seg_led_manager_mutex);
  115. return ret;
  116. }
  117. int seg_led_display_icon(uint8_t icon_idx, bool display)
  118. {
  119. int ret = 0;
  120. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  121. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  122. if (!ctx->update_direct) {
  123. if (display) {
  124. ctx->image.icon |= (1 << icon_idx);
  125. } else {
  126. ctx->image.icon &= (~(1 << icon_idx));
  127. }
  128. ctx->image.flash_map &= ~(1 << icon_idx);
  129. if (!ctx->image.flash_map) {
  130. ctx->image.flash_state = 0;
  131. }
  132. }
  133. if (!ctx->timeout_event_lock || ctx->update_direct) {
  134. ret = segled_display_icon(ctx->dev, icon_idx, display);
  135. }
  136. os_mutex_unlock(&seg_led_manager_mutex);
  137. return ret;
  138. }
  139. int seg_led_display_set_flash(uint16_t flash_map, uint16_t flash_period, uint16_t flash_cnt, seg_led_flash_callback cb)
  140. {
  141. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  142. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  143. ctx->image.flash_map = flash_map;
  144. ctx->image.flash_period = flash_period / CONFIG_MONITOR_PERIOD / 2;
  145. if (flash_cnt < FLASH_FOREVER / 2) {
  146. ctx->image.flash_cnt = flash_cnt * 2;
  147. } else {
  148. ctx->image.flash_cnt = FLASH_FOREVER;
  149. }
  150. ctx->image.flash_state = 1;
  151. ctx->image.current_period = ctx->image.flash_period;
  152. ctx->image.cb = cb;
  153. _seg_led_display_update();
  154. os_mutex_unlock(&seg_led_manager_mutex);
  155. return 0;
  156. }
  157. int seg_led_manager_clear_screen(uint8_t clr_mode)
  158. {
  159. int ret = 0;
  160. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  161. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  162. if (!ctx->update_direct && clr_mode == LED_CLEAR_ALL) {
  163. memset(&ctx->image, 0, sizeof(struct seg_led_image));
  164. }
  165. if (!ctx->timeout_event_lock || ctx->update_direct) {
  166. ret = segled_clear_screen(ctx->dev, clr_mode);
  167. }
  168. os_mutex_unlock(&seg_led_manager_mutex);
  169. return ret;
  170. }
  171. int seg_led_manager_sleep(void)
  172. {
  173. int ret = 0;
  174. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  175. seg_led_manager_store();
  176. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  177. ret = segled_sleep(ctx->dev);
  178. os_mutex_unlock(&seg_led_manager_mutex);
  179. return ret;
  180. }
  181. int seg_led_manager_wake_up(void)
  182. {
  183. int ret = 0;
  184. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  185. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  186. ret = segled_wakeup(ctx->dev);
  187. os_mutex_unlock(&seg_led_manager_mutex);
  188. seg_led_manager_restore();
  189. return ret;
  190. }
  191. int seg_led_manager_store(void)
  192. {
  193. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  194. struct seg_led_image *image_history = mem_malloc(sizeof(struct seg_led_image));
  195. if (!image_history)
  196. return -ENOMEM;
  197. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  198. memcpy(image_history, &ctx->image, sizeof(struct seg_led_image));
  199. sys_slist_append(&ctx->image_list, (sys_snode_t *)image_history);
  200. os_mutex_unlock(&seg_led_manager_mutex);
  201. return 0;
  202. }
  203. int seg_led_manager_restore(void)
  204. {
  205. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  206. struct seg_led_image *image_history = (struct seg_led_image *)sys_slist_peek_tail(&ctx->image_list);
  207. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  208. if (image_history) {
  209. memcpy(&ctx->image, image_history, sizeof(struct seg_led_image));
  210. sys_slist_find_and_remove(&ctx->image_list, (sys_snode_t *)image_history);
  211. mem_free(image_history);
  212. } else {
  213. SYS_LOG_ERR("no history");
  214. return -ENODEV;
  215. }
  216. _seg_led_display_update();
  217. os_mutex_unlock(&seg_led_manager_mutex);
  218. return 0;
  219. }
  220. int seg_led_manager_set_timeout_restore(int timeout)
  221. {
  222. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  223. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  224. if (ctx->timeout == FLASH_FOREVER) {
  225. os_mutex_unlock(&seg_led_manager_mutex);
  226. seg_led_manager_store();
  227. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  228. }
  229. ctx->timeout = timeout / CONFIG_MONITOR_PERIOD;
  230. ctx->timeout_cb = seg_led_manager_restore;
  231. os_mutex_unlock(&seg_led_manager_mutex);
  232. return 0;
  233. }
  234. int seg_led_manager_set_timeout_event_start(void)
  235. {
  236. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  237. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  238. ctx->update_direct = 1;
  239. ctx->timeout_event_lock = 1;
  240. os_mutex_unlock(&seg_led_manager_mutex);
  241. return 0;
  242. }
  243. int seg_led_manager_set_timeout_event(int timeout, seg_led_flash_callback cb)
  244. {
  245. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  246. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  247. ctx->timeout_cb = cb;
  248. ctx->timeout = timeout / CONFIG_MONITOR_PERIOD;
  249. ctx->update_direct = 0;
  250. os_mutex_unlock(&seg_led_manager_mutex);
  251. return 0;
  252. }
  253. static int _seg_led_manager_work_handle(void)
  254. {
  255. struct seg_led_manager_ctx_t *ctx = _seg_led_get_ctx();
  256. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  257. if (ctx->timeout != FLASH_FOREVER) {
  258. if (ctx->timeout-- == 0) {
  259. ctx->timeout = FLASH_FOREVER;
  260. ctx->update_direct = 0;
  261. ctx->timeout_event_lock = 0;
  262. _seg_led_display_update();
  263. os_mutex_unlock(&seg_led_manager_mutex);
  264. if (ctx->timeout_cb) {
  265. ctx->timeout_cb();
  266. ctx->timeout_cb = NULL;
  267. }
  268. return 0;
  269. }
  270. }
  271. ctx->image.current_period--;
  272. if (ctx->image.flash_map != 0
  273. && !ctx->image.current_period) {
  274. ctx->image.current_period = ctx->image.flash_period;
  275. if (ctx->image.flash_state) {
  276. ctx->image.flash_state = 0;
  277. } else {
  278. ctx->image.flash_state = 1;
  279. }
  280. _seg_led_display_update();
  281. if (ctx->image.flash_cnt != FLASH_FOREVER) {
  282. ctx->image.flash_cnt--;
  283. if (ctx->image.flash_cnt == 0) {
  284. ctx->image.flash_map = 0;
  285. if (ctx->image.cb) {
  286. os_mutex_unlock(&seg_led_manager_mutex);
  287. ctx->image.cb();
  288. os_mutex_lock(&seg_led_manager_mutex, OS_FOREVER);
  289. }
  290. }
  291. }
  292. }
  293. os_mutex_unlock(&seg_led_manager_mutex);
  294. return 0;
  295. }
  296. int seg_led_manager_init(void)
  297. {
  298. memset(&global_seg_led_manager_ctx, 0, sizeof(struct seg_led_manager_ctx_t));
  299. global_seg_led_manager_ctx.dev = device_get_binding(CONFIG_SEG_LED_DEVICE_NAME);
  300. if (!global_seg_led_manager_ctx.dev)
  301. return -ENODEV;
  302. if (sys_monitor_add_work(_seg_led_manager_work_handle)) {
  303. SYS_LOG_ERR("add work failed\n");
  304. return -EFAULT;
  305. }
  306. sys_slist_init(&global_seg_led_manager_ctx.image_list);
  307. global_seg_led_manager_ctx.timeout = FLASH_FOREVER;
  308. return 0;
  309. }
  310. int seg_led_manager_deinit(void)
  311. {
  312. return 0;
  313. }