machine_lcd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2019 SummerGift <SummerGift@qq.com>
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include "py/mphal.h"
  29. #include "py/runtime.h"
  30. #include "py/mperrno.h"
  31. #if MICROPY_PY_MACHINE_LCD
  32. #include <dfs_posix.h>
  33. #include "machine_lcd.h"
  34. #include <drv_lcd.h>
  35. #define MAX_CO (2400 - 1)
  36. typedef struct _machine_lcd_obj_t {
  37. mp_obj_base_t base;
  38. } machine_lcd_obj_t;
  39. STATIC void error_check(bool status, const char *msg) {
  40. if (!status) {
  41. nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
  42. }
  43. }
  44. /// \classmethod \constructor(skin_position)
  45. ///
  46. /// Construct an LCD object.
  47. STATIC mp_obj_t machine_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  48. // check arguments
  49. mp_arg_check_num(n_args, n_kw, 0, 0, false);
  50. // create lcd object
  51. machine_lcd_obj_t *lcd = m_new_obj(machine_lcd_obj_t);
  52. lcd->base.type = &machine_lcd_type;
  53. return MP_OBJ_FROM_PTR(lcd);
  54. }
  55. /// \method light(value)
  56. ///
  57. /// Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off.
  58. STATIC mp_obj_t machine_lcd_light(mp_obj_t self_in, mp_obj_t value) {
  59. if (mp_obj_is_true(value)) {
  60. lcd_display_on(); // set pin high to turn backlight on
  61. } else {
  62. lcd_display_off();// set pin low to turn backlight off
  63. }
  64. return mp_const_none;
  65. }
  66. STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_light_obj, machine_lcd_light);
  67. /// \method fill(colour)
  68. ///
  69. /// Fill the screen with the given colour.
  70. ///
  71. STATIC mp_obj_t machine_lcd_fill(mp_obj_t self_in, mp_obj_t col_in) {
  72. int col = mp_obj_get_int(col_in);
  73. lcd_clear(col);
  74. return mp_const_none;
  75. }
  76. STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_fill_obj, machine_lcd_fill);
  77. /// \method pixel(x, y, colour)
  78. ///
  79. /// Set the pixel at `(x, y)` to the given colour.
  80. ///
  81. STATIC mp_obj_t machine_lcd_pixel(size_t n_args, const mp_obj_t *args) {
  82. int x = mp_obj_get_int(args[1]);
  83. int y = mp_obj_get_int(args[2]);
  84. error_check((x >= 0 && x <= MAX_CO) && (y >= 0 && y <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  85. int col = mp_obj_get_int(args[3]);
  86. lcd_draw_point_color(x, y, col);
  87. return mp_const_none;
  88. }
  89. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_pixel_obj, 4, 4, machine_lcd_pixel);
  90. /// \method text(str, x, y, size)
  91. ///
  92. /// Draw the given text to the position `(x, y)` using the given size (16 24 32).
  93. ///
  94. STATIC mp_obj_t machine_lcd_text(size_t n_args, const mp_obj_t *args) {
  95. size_t len;
  96. const char *data = mp_obj_str_get_data(args[1], &len);
  97. int x = mp_obj_get_int(args[2]);
  98. int y = mp_obj_get_int(args[3]);
  99. int size = mp_obj_get_int(args[4]);
  100. error_check((x >= 0 && x <= MAX_CO) && (y >= 0 && y <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  101. error_check(size == 16 || size == 24 || size == 32, "lcd only support font size 16 24 32");
  102. lcd_show_string(x, y, size, data);
  103. return mp_const_none;
  104. }
  105. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_text_obj, 5, 5, machine_lcd_text);
  106. /// \method line(x1, y1, x2, y2)
  107. ///
  108. /// display a line on the lcd, from (x1, y1) to (x2, y2).
  109. ///
  110. STATIC mp_obj_t machine_lcd_line(size_t n_args, const mp_obj_t *args) {
  111. int x1 = mp_obj_get_int(args[1]);
  112. int y1 = mp_obj_get_int(args[2]);
  113. int x2 = mp_obj_get_int(args[3]);
  114. int y2 = mp_obj_get_int(args[4]);
  115. error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  116. error_check((x2 >= 0 && x2 <= MAX_CO) && (y2 >= 0 && y2 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  117. lcd_draw_line(x1, y1, x2, y2);
  118. return mp_const_none;
  119. }
  120. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_line_obj, 5, 5, machine_lcd_line);
  121. /// \method rectangle(x1, y1, x2, y2)
  122. ///
  123. /// display a rectangle on the lcd, from (x1, y1) to (x2, y2).
  124. ///
  125. STATIC mp_obj_t machine_lcd_rectangle(size_t n_args, const mp_obj_t *args) {
  126. int x1 = mp_obj_get_int(args[1]);
  127. int y1 = mp_obj_get_int(args[2]);
  128. int x2 = mp_obj_get_int(args[3]);
  129. int y2 = mp_obj_get_int(args[4]);
  130. error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  131. error_check((x2 >= 0 && x2 <= MAX_CO) && (y2 >= 0 && y2 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  132. lcd_draw_rectangle(x1, y1, x2, y2);
  133. return mp_const_none;
  134. }
  135. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_rectangle_obj, 5, 5, machine_lcd_rectangle);
  136. /// \method circle(x1, y1, r)
  137. ///
  138. /// display a circle on the lcd, center(x1, y1) R = r.
  139. ///
  140. STATIC mp_obj_t machine_lcd_circle(size_t n_args, const mp_obj_t *args) {
  141. int x1 = mp_obj_get_int(args[1]);
  142. int y1 = mp_obj_get_int(args[2]);
  143. int r = mp_obj_get_int(args[3]);
  144. error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
  145. lcd_draw_circle(x1, y1, r);
  146. return mp_const_none;
  147. }
  148. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_circle_obj, 4, 4, machine_lcd_circle);
  149. /// \method set_color(back, fore)
  150. ///
  151. /// Set background color and foreground color.
  152. ///
  153. STATIC mp_obj_t machine_lcd_set_color(size_t n_args, const mp_obj_t *args) {
  154. rt_uint16_t back = mp_obj_get_int(args[1]);
  155. rt_uint16_t fore = mp_obj_get_int(args[2]);
  156. lcd_set_color(back, fore);
  157. return mp_const_none;
  158. }
  159. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_set_color_obj, 3, 3, machine_lcd_set_color);
  160. /// \method show_image array
  161. ///
  162. /// display the image on the lcd..
  163. /// @param x x position
  164. /// @param y y position
  165. /// @param length length of image
  166. /// @param wide wide of image
  167. /// @param p image_array
  168. STATIC mp_obj_t machine_lcd_show_image(size_t n_args, const mp_obj_t *args) {
  169. rt_uint16_t x = mp_obj_get_int(args[1]);
  170. rt_uint16_t y = mp_obj_get_int(args[2]);
  171. rt_uint16_t length = mp_obj_get_int(args[3]);
  172. rt_uint16_t wide = mp_obj_get_int(args[4]);
  173. mp_buffer_info_t bufinfo;
  174. if (mp_get_buffer(args[5], &bufinfo, MP_BUFFER_READ))
  175. {
  176. lcd_show_image( x, y, length, wide, (const rt_uint8_t *)bufinfo.buf);
  177. }
  178. return mp_const_none;
  179. }
  180. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_image_obj, 6, 6, machine_lcd_show_image);
  181. STATIC rt_uint16_t rgb888to565(rt_uint32_t RGB)
  182. {
  183. int R, G, B;
  184. R = (RGB >> 19) & 0x1F;
  185. G = (RGB >> 10) & 0x3F;
  186. B = (RGB >> 3) & 0x1F;
  187. return (R << 11) | (G << 5) | B;
  188. }
  189. /// \method show_image array
  190. ///
  191. /// display the image on the lcd.
  192. /// @param x x position
  193. /// @param y y position
  194. /// @param file bmp file pathname
  195. STATIC mp_obj_t machine_lcd_show_bmp(size_t n_args, const mp_obj_t *args) {
  196. #define BMP_INFO_SIZE 54
  197. rt_uint16_t x = mp_obj_get_int(args[1]);
  198. rt_uint16_t y = mp_obj_get_int(args[2]);
  199. const char *pathname = mp_obj_str_get_str(args[3]);
  200. int fd, len;
  201. fd = open(pathname, O_RDONLY, 0);
  202. if (fd < 0)
  203. {
  204. mp_raise_OSError(MP_EINVAL);
  205. }
  206. void *bmp_info = rt_malloc(BMP_INFO_SIZE);
  207. if (bmp_info == RT_NULL)
  208. {
  209. mp_raise_OSError(MP_ENOMEM);
  210. }
  211. len = read(fd, bmp_info, BMP_INFO_SIZE);
  212. if (len < 0)
  213. {
  214. close(fd);
  215. mp_raise_OSError(MP_EINVAL);
  216. }
  217. rt_uint32_t width = *(rt_uint32_t *)(bmp_info + 18);
  218. rt_uint32_t heigth = *(rt_uint32_t *)(bmp_info + 22);
  219. rt_uint16_t bit_count = *(rt_uint16_t *)(bmp_info + 28);
  220. if (bit_count != 32)
  221. {
  222. nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
  223. "bit count : %d, only support 32-bit bmp picture", bit_count));
  224. }
  225. void *image_buf = rt_malloc(2 * width);
  226. if (image_buf == RT_NULL)
  227. {
  228. mp_raise_OSError(MP_ENOMEM);
  229. }
  230. void *row_buf = rt_malloc(4 * width);
  231. if (row_buf == RT_NULL)
  232. {
  233. mp_raise_OSError(MP_ENOMEM);
  234. }
  235. int image_index, row_index;
  236. rt_uint16_t rgb565_temp;
  237. for(int i = 0; i < heigth; i++)
  238. {
  239. image_index = 0;
  240. row_index = 0;
  241. len = read(fd, row_buf, 4 * width);
  242. if (len < 0)
  243. {
  244. close(fd);
  245. mp_raise_OSError(MP_EINVAL);
  246. }
  247. while(row_index < (4 * width))
  248. {
  249. rgb565_temp = rgb888to565(*(rt_uint32_t *)(row_buf + row_index));
  250. *(rt_uint8_t *)(image_buf + image_index) = (rgb565_temp >> 8);
  251. *(rt_uint8_t *)(image_buf + image_index + 1) = rgb565_temp & 0xff;
  252. row_index += 4;
  253. image_index += 2;
  254. }
  255. lcd_show_image( x, y--, width, 1, (const rt_uint8_t *)image_buf);
  256. }
  257. close(fd);
  258. rt_free(bmp_info);
  259. rt_free(image_buf);
  260. rt_free(row_buf);
  261. return mp_const_none;
  262. }
  263. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_bmp_obj, 4, 4, machine_lcd_show_bmp);
  264. STATIC const mp_rom_map_elem_t machine_lcd_locals_dict_table[] = {
  265. // instance methods
  266. { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&machine_lcd_light_obj) },
  267. { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&machine_lcd_fill_obj) },
  268. { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&machine_lcd_pixel_obj) },
  269. { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&machine_lcd_text_obj) },
  270. { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&machine_lcd_line_obj) },
  271. { MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&machine_lcd_rectangle_obj) },
  272. { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&machine_lcd_circle_obj) },
  273. { MP_ROM_QSTR(MP_QSTR_set_color), MP_ROM_PTR(&machine_lcd_set_color_obj) },
  274. { MP_ROM_QSTR(MP_QSTR_show_image), MP_ROM_PTR(&machine_lcd_show_image_obj) },
  275. { MP_ROM_QSTR(MP_QSTR_show_bmp), MP_ROM_PTR(&machine_lcd_show_bmp_obj) },
  276. // color
  277. { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(WHITE) },
  278. { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(BLACK) },
  279. { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(BLUE) },
  280. { MP_ROM_QSTR(MP_QSTR_BRED), MP_ROM_INT(BRED) },
  281. { MP_ROM_QSTR(MP_QSTR_GRED), MP_ROM_INT(GRED) },
  282. { MP_ROM_QSTR(MP_QSTR_GBLUE), MP_ROM_INT(GBLUE) },
  283. { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(RED) },
  284. { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(MAGENTA) },
  285. { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(GREEN) },
  286. { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(CYAN) },
  287. { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(YELLOW) },
  288. { MP_ROM_QSTR(MP_QSTR_BROWN), MP_ROM_INT(BROWN) },
  289. { MP_ROM_QSTR(MP_QSTR_BRRED), MP_ROM_INT(BRRED) },
  290. { MP_ROM_QSTR(MP_QSTR_GRAY), MP_ROM_INT(GRAY) },
  291. { MP_ROM_QSTR(MP_QSTR_GRAY175), MP_ROM_INT(GRAY175) },
  292. { MP_ROM_QSTR(MP_QSTR_GRAY151), MP_ROM_INT(GRAY151) },
  293. { MP_ROM_QSTR(MP_QSTR_GRAY187), MP_ROM_INT(GRAY187) },
  294. { MP_ROM_QSTR(MP_QSTR_GRAY240), MP_ROM_INT(GRAY240) },
  295. };
  296. STATIC MP_DEFINE_CONST_DICT(machine_lcd_locals_dict, machine_lcd_locals_dict_table);
  297. const mp_obj_type_t machine_lcd_type = {
  298. { &mp_type_type },
  299. .name = MP_QSTR_LCD,
  300. .make_new = machine_lcd_make_new,
  301. .locals_dict = (mp_obj_dict_t*)&machine_lcd_locals_dict,
  302. };
  303. #endif // MICROPY_PY_MACHINE_LCD