u8x8_d_tga.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. #include "u8g2.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #define FACTOR 3
  6. #define XOFFSET (FACTOR*64)
  7. #define YOFFSET (FACTOR*32)
  8. #define DEFAULT_WIDTH (FACTOR*128)
  9. #define DEFAULT_HEIGHT (FACTOR*64)
  10. uint16_t tga_max_x;
  11. uint16_t tga_max_y;
  12. static uint16_t tga_width;
  13. static uint16_t tga_height;
  14. static uint8_t *tga_data = NULL;
  15. uint8_t tga_is_transparent = 0;
  16. uint8_t tga_fg_r = 0;
  17. uint8_t tga_fg_g = 0;
  18. uint8_t tga_fg_b = 0;
  19. uint8_t tga_bg_r = 255;
  20. uint8_t tga_bg_g = 255;
  21. uint8_t tga_bg_b = 255;
  22. uint8_t tga_desc_fg_r = 0;
  23. uint8_t tga_desc_fg_g = 0;
  24. uint8_t tga_desc_fg_b = 255;
  25. uint8_t tga_desc_bg_r = 0;
  26. uint8_t tga_desc_bg_g = 0;
  27. uint8_t tga_desc_bg_b = 0;
  28. uint8_t tga_lcd_fg_r = 0;
  29. uint8_t tga_lcd_fg_g = 0;
  30. uint8_t tga_lcd_fg_b = 0;
  31. uint8_t tga_lcd_bg_r = 255;
  32. uint8_t tga_lcd_bg_g = 255;
  33. uint8_t tga_lcd_bg_b = 255;
  34. int tga_init(uint16_t w, uint16_t h)
  35. {
  36. tga_max_x = 0;
  37. tga_max_y = 0;
  38. tga_width = 0;
  39. tga_height = 0;
  40. if ( tga_data != NULL )
  41. free(tga_data);
  42. tga_data = (uint8_t *)malloc(w*h*3);
  43. if ( tga_data == NULL )
  44. return 0;
  45. tga_width = w;
  46. tga_height = h;
  47. memset(tga_data, 255, tga_width*tga_height*3);
  48. return 1;
  49. }
  50. void tga_set_pixel(uint16_t x, uint16_t y, uint16_t f)
  51. {
  52. uint8_t *p;
  53. uint16_t xx,yy;
  54. for( yy = y; yy < y+f; yy++ )
  55. {
  56. for( xx = x; xx < x+f; xx++ )
  57. {
  58. if ( yy < tga_height && xx < tga_width )
  59. {
  60. //printf ("(%d %d) ", xx, yy);
  61. p = tga_data + (tga_height-yy-1)*tga_width*3 + xx*3;
  62. *p++ = tga_fg_b;
  63. *p++ = tga_fg_g;
  64. *p++ = tga_fg_r;
  65. }
  66. }
  67. }
  68. }
  69. void tga_clr_pixel(uint16_t x, uint16_t y, uint16_t f)
  70. {
  71. uint8_t *p;
  72. uint16_t xx,yy;
  73. if ( tga_is_transparent )
  74. return;
  75. for( yy = y; yy < y+f; yy++ )
  76. {
  77. for( xx = x; xx < x+f; xx++ )
  78. {
  79. p = tga_data + (tga_height-yy-1)*tga_width*3 + xx*3;
  80. *p++ = tga_bg_b;
  81. *p++ = tga_bg_g;
  82. *p++ = tga_bg_r;
  83. }
  84. }
  85. }
  86. void tga_set_8pixel(int x, int y, uint8_t pixel, uint16_t f)
  87. {
  88. int cnt = 8;
  89. while( cnt > 0 )
  90. {
  91. if ( (pixel & 1) != 0 )
  92. {
  93. tga_set_pixel(x,y, f);
  94. }
  95. else
  96. {
  97. tga_clr_pixel(x,y, f);
  98. }
  99. pixel >>= 1;
  100. y+=f;
  101. cnt--;
  102. }
  103. }
  104. void tga_set_multiple_8pixel(int x, int y, int cnt, uint8_t *pixel, uint16_t f)
  105. {
  106. uint8_t b;
  107. while( cnt > 0 )
  108. {
  109. b = *pixel;
  110. tga_set_8pixel(x, y, b, f);
  111. x+=f;
  112. pixel++;
  113. cnt--;
  114. }
  115. }
  116. void tga_write_byte(FILE *fp, uint8_t byte)
  117. {
  118. fputc(byte, fp);
  119. }
  120. void tga_write_word(FILE *fp, uint16_t word)
  121. {
  122. tga_write_byte(fp, word&255);
  123. tga_write_byte(fp, word>>8);
  124. }
  125. void tga_save(const char *name)
  126. {
  127. FILE *fp;
  128. if ( tga_data == NULL )
  129. return;
  130. printf("tga_save: File %s with %dx%d pixel\n", name, tga_width, tga_height);
  131. fp = fopen(name, "wb");
  132. if ( fp != NULL )
  133. {
  134. tga_write_byte(fp, 0); /* no ID */
  135. tga_write_byte(fp, 0); /* no color map */
  136. tga_write_byte(fp, 2); /* uncompressed true color */
  137. tga_write_word(fp, 0);
  138. tga_write_word(fp, 0);
  139. tga_write_byte(fp, 0);
  140. tga_write_word(fp, 0); /* x origin */
  141. tga_write_word(fp, 0); /* y origin */
  142. tga_write_word(fp, tga_width); /* width */
  143. tga_write_word(fp, tga_height); /* height */
  144. tga_write_byte(fp, 24); /* color depth */
  145. tga_write_byte(fp, 0);
  146. fwrite(tga_data, tga_width*tga_height*3, 1, fp);
  147. tga_write_word(fp, 0);
  148. tga_write_word(fp, 0);
  149. tga_write_word(fp, 0);
  150. tga_write_word(fp, 0);
  151. fwrite("TRUEVISION-XFILE.", 18, 1, fp);
  152. fclose(fp);
  153. }
  154. }
  155. void tga_save_png(const char *name)
  156. {
  157. char convert_cmd[1024*2];
  158. tga_save("tmp.tga");
  159. sprintf(convert_cmd, "convert tmp.tga -trim %s", name );
  160. system(convert_cmd);
  161. }
  162. /*==========================================*/
  163. /* tga description procedures */
  164. static const u8x8_display_info_t u8x8_tga_desc_info =
  165. {
  166. /* chip_enable_level = */ 0,
  167. /* chip_disable_level = */ 1,
  168. /* post_chip_enable_wait_ns = */ 0,
  169. /* pre_chip_disable_wait_ns = */ 0,
  170. /* reset_pulse_width_ms = */ 0,
  171. /* post_reset_wait_ms = */ 0,
  172. /* sda_setup_time_ns = */ 0,
  173. /* sck_pulse_width_ns = */ 0,
  174. /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  175. /* spi_mode = */ 1,
  176. /* i2c_bus_clock_100kHz = */ 0,
  177. /* data_setup_time_ns = */ 0,
  178. /* write_pulse_width_ns = */ 0,
  179. /* tile_width = */ (2*XOFFSET+DEFAULT_WIDTH)/8,
  180. /* tile_hight = */ (2*YOFFSET+DEFAULT_HEIGHT)/8,
  181. /* default_x_offset = */ 0,
  182. /* flipmode_x_offset = */ 0,
  183. /* pixel_width = */ (2*XOFFSET+DEFAULT_WIDTH),
  184. /* pixel_height = */ (2*YOFFSET+DEFAULT_HEIGHT)
  185. };
  186. uint8_t u8x8_d_tga_desc(u8x8_t *u8g2, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  187. {
  188. u8g2_uint_t x, y, c;
  189. uint8_t *ptr;
  190. switch(msg)
  191. {
  192. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  193. u8x8_d_helper_display_setup_memory(u8g2, &u8x8_tga_desc_info);
  194. break;
  195. case U8X8_MSG_DISPLAY_INIT:
  196. u8x8_d_helper_display_init(u8g2);
  197. if ( tga_data == NULL )
  198. tga_init(2*XOFFSET+DEFAULT_WIDTH, 2*YOFFSET+DEFAULT_HEIGHT);
  199. break;
  200. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  201. break;
  202. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  203. break;
  204. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  205. break;
  206. case U8X8_MSG_DISPLAY_DRAW_TILE:
  207. tga_fg_r = tga_desc_fg_r;
  208. tga_fg_g = tga_desc_fg_g;
  209. tga_fg_b = tga_desc_fg_b;
  210. tga_bg_r = tga_desc_bg_r;
  211. tga_bg_g = tga_desc_bg_g;
  212. tga_bg_b = tga_desc_bg_b;
  213. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  214. //printf("U8X8_MSG_DISPLAY_DRAW_TILE x=%d, ", x);
  215. x *= 8;
  216. x += u8g2->x_offset;
  217. y = ((u8x8_tile_t *)arg_ptr)->y_pos;
  218. //printf("y=%d, c=%d\n", y, ((u8x8_tile_t *)arg_ptr)->cnt);
  219. y *= 8;
  220. do
  221. {
  222. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  223. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  224. tga_set_multiple_8pixel(x, y, c*8, ptr, 1);
  225. arg_int--;
  226. x += c*8;
  227. } while( arg_int > 0 );
  228. break;
  229. default:
  230. return 0;
  231. }
  232. return 1;
  233. }
  234. void u8x8_Setup_TGA_DESC(u8x8_t *u8x8)
  235. {
  236. /* setup defaults */
  237. u8x8_SetupDefaults(u8x8);
  238. /* setup specific callbacks */
  239. u8x8->display_cb = u8x8_d_tga_desc;
  240. /* setup display info */
  241. u8x8_SetupMemory(u8x8);
  242. }
  243. void u8g2_SetupBuffer_TGA_DESC(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb)
  244. {
  245. static uint8_t buf[(XOFFSET+DEFAULT_WIDTH)*8];
  246. u8x8_Setup_TGA_DESC(u8g2_GetU8x8(u8g2));
  247. u8g2_SetupBuffer(u8g2, buf, 1, u8g2_ll_hvline_vertical_top_lsb, u8g2_cb);
  248. }
  249. /*==========================================*/
  250. /* tga LCD procedures */
  251. static const u8x8_display_info_t u8x8_tga_lcd_info =
  252. {
  253. /* chip_enable_level = */ 0,
  254. /* chip_disable_level = */ 1,
  255. /* post_chip_enable_wait_ns = */ 0,
  256. /* pre_chip_disable_wait_ns = */ 0,
  257. /* reset_pulse_width_ms = */ 0,
  258. /* post_reset_wait_ms = */ 0,
  259. /* sda_setup_time_ns = */ 0,
  260. /* sck_pulse_width_ns = */ 0,
  261. /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  262. /* spi_mode = */ 1,
  263. /* i2c_bus_clock_100kHz = */ 0,
  264. /* data_setup_time_ns = */ 0,
  265. /* write_pulse_width_ns = */ 0,
  266. /* tile_width = */ (DEFAULT_WIDTH)/FACTOR/8,
  267. /* tile_hight = */ (DEFAULT_HEIGHT)/FACTOR/8,
  268. /* default_x_offset = */ 0,
  269. /* flipmode_x_offset = */ 0,
  270. /* pixel_width = */ (DEFAULT_WIDTH)/FACTOR,
  271. /* pixel_height = */ (DEFAULT_HEIGHT)/FACTOR
  272. };
  273. uint8_t u8x8_d_tga_lcd(u8x8_t *u8g2, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  274. {
  275. u8g2_uint_t x, y, c;
  276. uint8_t *ptr;
  277. switch(msg)
  278. {
  279. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  280. u8x8_d_helper_display_setup_memory(u8g2, &u8x8_tga_lcd_info);
  281. break;
  282. case U8X8_MSG_DISPLAY_INIT:
  283. u8x8_d_helper_display_init(u8g2);
  284. if ( tga_data == NULL )
  285. tga_init(2*XOFFSET+DEFAULT_WIDTH, 2*YOFFSET+DEFAULT_HEIGHT);
  286. break;
  287. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  288. break;
  289. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  290. break;
  291. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  292. break;
  293. case U8X8_MSG_DISPLAY_DRAW_TILE:
  294. tga_fg_r = tga_lcd_fg_r;
  295. tga_fg_g = tga_lcd_fg_g;
  296. tga_fg_b = tga_lcd_fg_b;
  297. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  298. //printf("U8X8_MSG_DISPLAY_DRAW_TILE x=%d, ", x);
  299. x *= 8;
  300. x += u8g2->x_offset;
  301. x *= FACTOR;
  302. x += XOFFSET;
  303. y = ((u8x8_tile_t *)arg_ptr)->y_pos;
  304. //printf("y=%d, c=%d\n", y, ((u8x8_tile_t *)arg_ptr)->cnt);
  305. y *= 8;
  306. y *= FACTOR;
  307. y += YOFFSET;
  308. do
  309. {
  310. if ( (x/8+y/8) & 1 )
  311. {
  312. tga_bg_r = tga_lcd_bg_r;
  313. tga_bg_g = tga_lcd_bg_g;
  314. tga_bg_b = tga_lcd_bg_b;
  315. }
  316. else
  317. {
  318. tga_bg_r = (tga_lcd_bg_r*10)/11;
  319. tga_bg_g = (tga_lcd_bg_g*10)/11;
  320. tga_bg_b = (tga_lcd_bg_b*10)/11;
  321. }
  322. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  323. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  324. tga_set_multiple_8pixel(x, y, c*8, ptr, FACTOR);
  325. arg_int--;
  326. x += c*8*FACTOR;
  327. } while( arg_int > 0 );
  328. break;
  329. default:
  330. return 0;
  331. }
  332. return 1;
  333. }
  334. void u8x8_Setup_TGA_LCD(u8x8_t *u8x8)
  335. {
  336. /* setup defaults */
  337. u8x8_SetupDefaults(u8x8);
  338. /* setup specific callbacks */
  339. u8x8->display_cb = u8x8_d_tga_lcd;
  340. /* setup display info */
  341. u8x8_SetupMemory(u8x8);
  342. }
  343. void u8g2_SetupBuffer_TGA_LCD(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb)
  344. {
  345. static uint8_t buf[(DEFAULT_WIDTH/FACTOR)*8];
  346. u8x8_Setup_TGA_LCD(u8g2_GetU8x8(u8g2));
  347. u8g2_SetupBuffer(u8g2, buf, 1, u8g2_ll_hvline_vertical_top_lsb, u8g2_cb);
  348. }