discoverpixy
tft.c
Go to the documentation of this file.
1 /**************************************************************************************************************************************
2 * Project: discoverpixy
3 * Website: https://github.com/t-moe/discoverpixy
4 * Authors: Aaron Schmocker, Timo Lang
5 * Institution: BFH Bern University of Applied Sciences
6 * File: common/tft/tft.c
7 *
8 * Version History:
9 * Date Autor Email SHA Changes
10 * 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
11 * 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
12 * 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow.
13 * 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator)
14 * 2015-04-27 timolang@gmail.com e249fb2 Added font support
15 * 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
16 * 2015-05-10 timolang@gmail.com b6ab7c8 Fixed compiler warning in tft and screen module.
17 * 2015-05-15 timolang@gmail.com b08a897 Added tft method to draw a bmp from filesystem. Added another font to emulator.
18 * 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
19 *
20 **************************************************************************************************************************************/
21 
22 #include "tft.h"
23 #include "ll_tft.h"
24 #include <string.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include "filesystem.h"
28 
29 /* The idea is as follows:
30  * Most of the tft_* functions can be forwarded to the lowlevel implementation.
31  * The exceptions are commented below.
32  * Make sure to have a look at the doxygen comments for the lowlevel functions and for the tft_* functions
33  */
34 
35 /* Possible improvements:
36  * For formatted printing implement putchar, instead of writing into a buffer and drawing that buffer afterwards
37  */
38 
39 bool tft_init()
40 {
41  return ll_tft_init();
42 
43 }
44 
45 void tft_clear(uint16_t color)
46 {
47  ll_tft_clear(color);
48 }
49 
50 void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
51 {
52  ll_tft_draw_line(x1, y1, x2, y2, color);
53 }
54 
55 
56 void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
57 {
58  ll_tft_draw_pixel(x, y, color);
59 }
60 
61 void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
62 {
63  //could be implemented with 4 lines instead of introducing a ll func
64  ll_tft_draw_rectangle(x1, y1, x2, y2, color);
65 }
66 
67 void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
68 {
69  ll_tft_fill_rectangle(x1, y1, x2, y2, color);
70 }
71 
72 void tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat)
73 {
74  ll_tft_draw_bitmap_unscaled(x, y, width, height, dat);
75 }
76 
77 void tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
78 {
79  ll_tft_draw_circle(x, y, r, color);
80 }
81 
82 uint8_t tft_num_fonts()
83 {
84  return ll_tft_num_fonts();
85 }
86 
87 uint8_t tft_font_height(uint8_t fontnum)
88 {
89  return ll_tft_font_height(fontnum);
90 }
91 
92 uint8_t tft_font_width(uint8_t fontnum)
93 {
94  return ll_tft_font_width(fontnum);
95 }
96 
97 //Print line can be done with multiple calls to draw_char
98 void tft_print_line(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* text)
99 {
100  if (font >= ll_tft_num_fonts()) {
101  return; //invalid font index
102  }
103 
104  for (int i = 0; i < strlen(text); i++) { //for each char in the line
105  ll_tft_draw_char(x, y, color, bgcolor, font, text[i]); //draw the char
106  x += ll_tft_font_width(font); //and increase the x position
107  }
108 }
109 
110 //Printing a formatted line can be done by printing the line in a buffer using "sprintf" and then calling print_line
111 void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* format, ...)
112 {
113  static char buffer[128]; //buffer to save the formatted text into
114 
115  //Since we have variable arguments, we need to forward them. We have to use vsprintf instead of sprintf for that.
116  va_list args;
117  va_start(args, format); //start the varg-list
118  vsprintf(buffer, format, args); //let vsprintf render the formatted string
119  tft_print_line(x, y, color, bgcolor, font, buffer); //print the string as normal text
120  va_end(args); //end the varg-list
121 }
122 
123 bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char* filename)
124 {
125  //This method reads a .bmp file from the filesystem and tries to draw it.
126  //Note: The bmp implementation is not complete, it has some limitations and it makes assumptions. See doxygen comment for this method.
127  //Source Copied and adapted from: http://stackoverflow.com/a/17040962/2606757
128 
129  FILE_HANDLE* file = filesystem_file_open(filename); //try to open the file
130 
131  if (file == NULL) { //file opening failed
132  return false;
133  }
134 
135  unsigned char info[54];
136 
137  if (filesystem_file_read(file, info, 54) != F_OK) { //try to read the 54 byte header
138  filesystem_file_close(file);
139  return false; //reading the header failed
140  }
141 
142  // extract image height and width from header
143  uint32_t width = *(uint32_t*)&info[18]; //width in pixel
144  uint32_t height = *(uint32_t*)&info[22]; //height in pixel
145  uint16_t depth = *(uint16_t*)&info[28]; //bit's per pixel (color depth)
146  depth /= 8; //we want the number of bytes per pixel
147 
148  filesystem_file_seek(file, *(uint32_t*)&info[10]); //seek to the place where img data begins
149 
150  uint32_t row_padded = (width * depth + 3) & (~3); //row size must be aligned to 4 bytes
151 
152  unsigned char data [row_padded]; //allocate space for one row (incl. padding)
153 
154  for (int i = 0; i < height; i++) { //for each row
155  filesystem_file_read(file, data, row_padded); //read row into buffer
156 
157  for (int j = 0; j < width * depth; j += depth) { //for each pixel
158  unsigned char a, r, g, b;
159 
160  if (depth == 4) { //a,r,g,b 8bit each
161  a = data[j];
162  r = data[j + 1];
163  g = data[j + 2];
164  b = data[j + 3];
165  } else if (depth == 3) { // b,g,r, 8bit each
166  a = 255;
167  r = data[j + 2];
168  g = data[j + 1];
169  b = data[j];
170  }
171 
172  if (a != 0) {
173  //bmp's are stored "bottom-up", so we start drawing at the bottom
174  tft_draw_pixel(x + j / depth, y + height - 1 - i, RGB(r, g, b));
175  }
176  }
177  }
178 
179  filesystem_file_close(file);
180 
181  return true;
182 
183 }
uint8_t tft_font_height(uint8_t fontnum)
Definition: tft.c:87
uint8_t tft_font_width(uint8_t fontnum)
Definition: tft.c:92
FILE_STATUS filesystem_file_seek(FILE_HANDLE *handle, uint32_t offset)
Definition: filesystem.c:43
void tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
Definition: tft.c:77
void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:50
void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char *format,...)
Definition: tft.c:111
void tft_print_line(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char *text)
Definition: tft.c:98
uint8_t tft_num_fonts()
Definition: tft.c:82
#define RGB(r, g, b)
Definition: tft.h:48
uint8_t ll_tft_font_width(uint8_t fontnum)
void tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat)
Definition: tft.c:72
FILE_HANDLE * filesystem_file_open(const char *filename)
Definition: filesystem.c:33
void filesystem_file_close(FILE_HANDLE *handle)
Definition: filesystem.c:38
void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
Definition: tft.c:56
uint8_t ll_tft_num_fonts()
bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char *filename)
Definition: tft.c:123
void ll_tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c)
void tft_clear(uint16_t color)
Definition: tft.c:45
uint8_t ll_tft_font_height(uint8_t fontnum)
void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:67
void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
void ll_tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
bool ll_tft_init()
Everything ok.
Definition: filesystem.h:91
void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:61
void ll_tft_clear(uint16_t color)
bool tft_init()
Definition: tft.c:39
void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
FILE_STATUS filesystem_file_read(FILE_HANDLE *handle, uint8_t *buf, uint32_t size)
Definition: filesystem.c:48
void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat)