1 | /*
|
---|
2 | * TOPPERS/ASP Kernel
|
---|
3 | * Toyohashi Open Platform for Embedded Real-Time Systems/
|
---|
4 | * Advanced Standard Profile Kernel
|
---|
5 | *
|
---|
6 | * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
|
---|
7 | * Toyohashi Univ. of Technology, JAPAN
|
---|
8 | * Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
|
---|
9 | * Graduate School of Information Science, Nagoya Univ., JAPAN
|
---|
10 | * Copyright (C) 2015-2020 by TOPPERS PROJECT Educational Working Group.
|
---|
11 | *
|
---|
12 | * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
|
---|
13 | * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
|
---|
14 | * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
|
---|
15 | * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
|
---|
16 | * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
|
---|
17 | * スコード中に含まれていること.
|
---|
18 | * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
|
---|
19 | * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
|
---|
20 | * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
|
---|
21 | * の無保証規定を掲載すること.
|
---|
22 | * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
|
---|
23 | * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
|
---|
24 | * と.
|
---|
25 | * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
|
---|
26 | * 作権表示,この利用条件および下記の無保証規定を掲載すること.
|
---|
27 | * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
|
---|
28 | * 報告すること.
|
---|
29 | * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
|
---|
30 | * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
|
---|
31 | * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
|
---|
32 | * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
|
---|
33 | * 免責すること.
|
---|
34 | *
|
---|
35 | * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
|
---|
36 | * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
|
---|
37 | * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
|
---|
38 | * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
|
---|
39 | * の責任を負わない.
|
---|
40 | *
|
---|
41 | * $Id$
|
---|
42 | */
|
---|
43 |
|
---|
44 | /*
|
---|
45 | * Written by Limor Fried/Ladyada for Adafruit Industries.
|
---|
46 | * MIT license, all text above must be included in any redistribution
|
---|
47 | * http://opensource.org/licenses/mit-license.php
|
---|
48 | */
|
---|
49 |
|
---|
50 | /*
|
---|
51 | * ADAFRUIT ST7789 LCD制御プログラムの本体
|
---|
52 | */
|
---|
53 |
|
---|
54 | #include <kernel.h>
|
---|
55 | #include <t_syslog.h>
|
---|
56 | #include <t_stdlib.h>
|
---|
57 | #include <stdio.h>
|
---|
58 | #include <string.h>
|
---|
59 | #include <target_syssvc.h>
|
---|
60 | #include "syssvc/serial.h"
|
---|
61 | #include "syssvc/syslog.h"
|
---|
62 | #include "device.h"
|
---|
63 | #include "adafruit_st7789.h"
|
---|
64 |
|
---|
65 | /*
|
---|
66 | * サービスコールのエラーのログ出力
|
---|
67 | */
|
---|
68 | Inline void
|
---|
69 | svc_perror(const char *file, int_t line, const char *expr, ER ercd)
|
---|
70 | {
|
---|
71 | if (ercd < 0) {
|
---|
72 | t_perror(LOG_ERROR, file, line, expr, ercd);
|
---|
73 | }
|
---|
74 | }
|
---|
75 |
|
---|
76 | #define SVC_PERROR(expr) svc_perror(__FILE__, __LINE__, #expr, (expr))
|
---|
77 | #define ABS(X) ((X) > 0 ? (X) : -(X))
|
---|
78 |
|
---|
79 |
|
---|
80 | // Rather than a bazillion writecommand() and writedata() calls, screen
|
---|
81 | // initialization commands and arguments are organized in these tables
|
---|
82 | // stored in PROGMEM. The table may look bulky, but that's mostly the
|
---|
83 | // formatting -- storage-wise this is hundreds of bytes more compact
|
---|
84 | // than the equivalent code. Companion function follows.
|
---|
85 | #define DELAY 0x80
|
---|
86 | static const uint8_t
|
---|
87 | Gcmd[] = { // Initialization commands for 7789 screens
|
---|
88 | 9, // 9 commands in list:
|
---|
89 | ST7789_SWRESET, DELAY, // 1: Software reset, no args, w/delay
|
---|
90 | 150, // 150 ms delay
|
---|
91 | ST7789_SLPOUT , DELAY, // 2: Out of sleep mode, no args, w/delay
|
---|
92 | 10, // 10 ms delay
|
---|
93 | ST7789_COLMOD , 1+DELAY, // 3: Set color mode, 1 arg + delay:
|
---|
94 | 0x55, // 16-bit color
|
---|
95 | 10, // 10 ms delay
|
---|
96 | ST7789_MADCTL , 1, // 4: Mem access ctrl (directions), 1 arg:
|
---|
97 | 0x08, // Row/col addr, bottom-top refresh
|
---|
98 | ST7789_CASET , 4, // 5: Column addr set, 4 args, no delay:
|
---|
99 | 0x00, //
|
---|
100 | 0, // XSTART = 0
|
---|
101 | 0, //
|
---|
102 | 240, // XEND = 240
|
---|
103 | ST7789_RASET , 4, // 6: Row addr set, 4 args, no delay:
|
---|
104 | 0x00,
|
---|
105 | 0, // YSTART = 0
|
---|
106 | 320>>8,
|
---|
107 | 320&0xFF, // YEND = 320
|
---|
108 | ST7789_INVON , DELAY, // 7: hack
|
---|
109 | 10, // 10 ms delay
|
---|
110 | ST7789_NORON , DELAY, // 8: Normal display on, no args, w/delay
|
---|
111 | 10, // 10 ms delay
|
---|
112 | ST7789_DISPON , DELAY, // 9: Main screen turn on, no args, delay
|
---|
113 | 10 }; // 10 ms delay
|
---|
114 |
|
---|
115 |
|
---|
116 |
|
---|
117 |
|
---|
118 | /* Buffer used for transmission */
|
---|
119 | static uint8_t aTxBuffer[4];
|
---|
120 |
|
---|
121 | #define PORT_HIGH 1
|
---|
122 | #define PORT_LOW 0
|
---|
123 |
|
---|
124 | #define cs_set(sw) digitalWrite(hlcd->cs_pin, sw)
|
---|
125 | #define rs_set(sw) digitalWrite(hlcd->rs_pin, sw)
|
---|
126 | #define rst_set(sw) digitalWrite(hlcd->rst_pin, sw)
|
---|
127 | #define cs2_set(sw) digitalWrite(hlcd->cs2_pin, sw)
|
---|
128 |
|
---|
129 | /*
|
---|
130 | * LCDへのコマンド送信関数
|
---|
131 | */
|
---|
132 | ER
|
---|
133 | lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c)
|
---|
134 | {
|
---|
135 | ER ercd = E_OK;
|
---|
136 |
|
---|
137 | if(hlcd->spi_lock != 0){
|
---|
138 | if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
|
---|
139 | return ercd;
|
---|
140 | }
|
---|
141 | rs_set(PORT_LOW);
|
---|
142 | cs_set(PORT_LOW);
|
---|
143 |
|
---|
144 | aTxBuffer[0] = c;
|
---|
145 | #if SPI_WAIT_TIME != 0
|
---|
146 | ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
|
---|
147 | #else
|
---|
148 | if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
|
---|
149 | ercd = spi_wait(hlcd->hspi, 100);
|
---|
150 | }
|
---|
151 | #endif
|
---|
152 |
|
---|
153 | cs_set(PORT_HIGH);
|
---|
154 | if(hlcd->spi_lock != 0)
|
---|
155 | sig_sem(hlcd->spi_lock);
|
---|
156 | return ercd;
|
---|
157 | }
|
---|
158 |
|
---|
159 | /*
|
---|
160 | * LCDへのデータ送信関数
|
---|
161 | */
|
---|
162 | ER
|
---|
163 | lcd_writedata(LCD_Handler_t *hlcd, uint8_t *p, uint32_t len)
|
---|
164 | {
|
---|
165 | ER ercd = E_OK;
|
---|
166 |
|
---|
167 | if(hlcd->spi_lock != 0){
|
---|
168 | if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
|
---|
169 | return ercd;
|
---|
170 | }
|
---|
171 | rs_set(PORT_HIGH);
|
---|
172 | cs_set(PORT_LOW);
|
---|
173 | sil_dly_nse(100);
|
---|
174 |
|
---|
175 | #if SPI_WAIT_TIME != 0
|
---|
176 | ercd = spi_transmit(hlcd->hspi, (uint8_t*)p, len);
|
---|
177 | #else
|
---|
178 | if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)p, len)) == E_OK){
|
---|
179 | ercd = spi_wait(hlcd->hspi, 100);
|
---|
180 | }
|
---|
181 | #endif
|
---|
182 |
|
---|
183 | sil_dly_nse(100);
|
---|
184 | cs_set(PORT_HIGH);
|
---|
185 | if(hlcd->spi_lock != 0)
|
---|
186 | sig_sem(hlcd->spi_lock);
|
---|
187 | return ercd;
|
---|
188 | }
|
---|
189 |
|
---|
190 | /*
|
---|
191 | * LCDへの2バイトデータ送信関数
|
---|
192 | */
|
---|
193 | ER
|
---|
194 | lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt)
|
---|
195 | {
|
---|
196 | ER ercd = E_OK;
|
---|
197 | int i;
|
---|
198 |
|
---|
199 | if(cnt == 0)
|
---|
200 | return ercd;
|
---|
201 | if(hlcd->spi_lock != 0){
|
---|
202 | if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
|
---|
203 | return ercd;
|
---|
204 | }
|
---|
205 | rs_set(PORT_HIGH);
|
---|
206 | cs_set(PORT_LOW);
|
---|
207 | sil_dly_nse(100);
|
---|
208 | aTxBuffer[0] = c>>8;
|
---|
209 | aTxBuffer[1] = (uint8_t)c;
|
---|
210 | for(i = 0 ; i < cnt ; i++){
|
---|
211 | if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
|
---|
212 | break;
|
---|
213 | }
|
---|
214 | #if SPI_WAIT_TIME == 0
|
---|
215 | if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
|
---|
216 | break;
|
---|
217 | }
|
---|
218 | #endif
|
---|
219 | }
|
---|
220 | sil_dly_nse(100);
|
---|
221 | cs_set(PORT_HIGH);
|
---|
222 | if(hlcd->spi_lock != 0)
|
---|
223 | sig_sem(hlcd->spi_lock);
|
---|
224 | return ercd;
|
---|
225 | }
|
---|
226 |
|
---|
227 | /*
|
---|
228 | * LCDへのRGBデータ送信関数
|
---|
229 | */
|
---|
230 | ER
|
---|
231 | lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height)
|
---|
232 | {
|
---|
233 | ER ercd = E_OK;
|
---|
234 | int index, i;
|
---|
235 |
|
---|
236 | if(width == 0 || height == 0)
|
---|
237 | return ercd;
|
---|
238 | if(hlcd->spi_lock != 0){
|
---|
239 | if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
|
---|
240 | return ercd;
|
---|
241 | }
|
---|
242 | rs_set(PORT_HIGH);
|
---|
243 | cs_set(PORT_LOW);
|
---|
244 | sil_dly_nse(100);
|
---|
245 | for(index=0; index < height; index++){
|
---|
246 | uint8_t *p = pbmp;
|
---|
247 | for (i = 0; i < width; i++){
|
---|
248 | aTxBuffer[0] = (*p++) & 0xf8;
|
---|
249 | aTxBuffer[0] |= *p >> 5;
|
---|
250 | aTxBuffer[1] = (*p++ << 3) & 0xE0;
|
---|
251 | aTxBuffer[1] |= (*p++ >> 3) & 0x1F;
|
---|
252 | if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
|
---|
253 | break;
|
---|
254 | }
|
---|
255 | #if SPI_WAIT_TIME == 0
|
---|
256 | if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
|
---|
257 | break;
|
---|
258 | }
|
---|
259 | #endif
|
---|
260 | }
|
---|
261 | pbmp -= width*3;
|
---|
262 | }
|
---|
263 | sil_dly_nse(100);
|
---|
264 | cs_set(PORT_HIGH);
|
---|
265 | if(hlcd->spi_lock != 0)
|
---|
266 | sig_sem(hlcd->spi_lock);
|
---|
267 | return ercd;
|
---|
268 | }
|
---|
269 |
|
---|
270 | /*
|
---|
271 | * ST7789へのコマンドリスト送信
|
---|
272 | */
|
---|
273 | static void
|
---|
274 | displayInit(LCD_Handler_t *hlcd, const uint8_t *addr)
|
---|
275 | {
|
---|
276 | uint8_t numCommands, numArgs;
|
---|
277 | uint8_t data[4];
|
---|
278 | uint16_t ms;
|
---|
279 |
|
---|
280 | numCommands = *addr++; // Number of commands to follow
|
---|
281 | while(numCommands--) { // For each command...
|
---|
282 | SVC_PERROR(lcd_writecommand(hlcd, *addr++)); // Read, issue command
|
---|
283 | numArgs = *addr++; // Number of args to follow
|
---|
284 | ms = numArgs & DELAY; // If hibit set, delay follows args
|
---|
285 | numArgs &= ~DELAY; // Mask out delay bit
|
---|
286 | while(numArgs--) { // For each argument...
|
---|
287 | data[0] = *addr++;
|
---|
288 | SVC_PERROR(lcd_writedata(hlcd, data, 1)); // Read, issue argument
|
---|
289 | }
|
---|
290 |
|
---|
291 | if(ms) {
|
---|
292 | ms = *addr++; // Read post-command delay time (ms)
|
---|
293 | if(ms == 255) ms = 500; // If 255, delay for 500 ms
|
---|
294 | dly_tsk(ms);
|
---|
295 | }
|
---|
296 | }
|
---|
297 | }
|
---|
298 |
|
---|
299 |
|
---|
300 | /*
|
---|
301 | * ST7735B または ST7735RタイプのLEDの共通初期化関数
|
---|
302 | */
|
---|
303 | static void
|
---|
304 | commonInit(LCD_Handler_t *hlcd, uint16_t width, uint16_t height)
|
---|
305 | {
|
---|
306 | hlcd->colstart = hlcd->rowstart = 0; // May be overridden in init func
|
---|
307 | hlcd->lcd_width = width;
|
---|
308 | hlcd->lcd_height = height;
|
---|
309 | if(width == 240 && height == 240){ /* 1.3" and 1.54 displays */
|
---|
310 | hlcd->lcd_colstart = 0;
|
---|
311 | hlcd->lcd_rowstart = 80;
|
---|
312 | }
|
---|
313 | else if(width == 135 && height == 240){ /*1.13" display */
|
---|
314 | hlcd->lcd_colstart = 53;
|
---|
315 | hlcd->lcd_rowstart = 40;
|
---|
316 | }
|
---|
317 | else{
|
---|
318 | hlcd->lcd_colstart = 0;
|
---|
319 | hlcd->lcd_rowstart = 0;
|
---|
320 | }
|
---|
321 |
|
---|
322 | // toggle RST low to reset; CS low so it'll listen to us
|
---|
323 | cs_set(PORT_LOW);
|
---|
324 | rst_set(PORT_HIGH);
|
---|
325 | dly_tsk(500);
|
---|
326 | rst_set(PORT_LOW);
|
---|
327 | dly_tsk(500);
|
---|
328 | rst_set(PORT_HIGH);
|
---|
329 | }
|
---|
330 |
|
---|
331 | /*
|
---|
332 | * 表示ウィンドウ設定
|
---|
333 | */
|
---|
334 | void
|
---|
335 | lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
|
---|
336 | {
|
---|
337 | uint8_t data[4];
|
---|
338 |
|
---|
339 | SVC_PERROR(lcd_writecommand(hlcd, ST7789_CASET)); // Column addr set
|
---|
340 | data[0] = (uint8_t)((x0 + hlcd->colstart) >> 8);
|
---|
341 | data[1] = (uint8_t)(x0 + hlcd->colstart); // XSTART
|
---|
342 | data[2] = (uint8_t)((x1 + hlcd->colstart) >> 8);
|
---|
343 | data[3] = (uint8_t)(x1 + hlcd->colstart); // XEND
|
---|
344 | SVC_PERROR(lcd_writedata(hlcd, data, 4));
|
---|
345 |
|
---|
346 | SVC_PERROR(lcd_writecommand(hlcd, ST7789_RASET)); // Row addr set
|
---|
347 | data[0] = (uint8_t)((y0 + hlcd->rowstart) >> 8);
|
---|
348 | data[1] = (uint8_t)(y0 + hlcd->rowstart); // YSTART
|
---|
349 | data[2] = (uint8_t)((y1 + hlcd->rowstart) >> 8);
|
---|
350 | data[3] = (uint8_t)(y1 + hlcd->rowstart); // YEND
|
---|
351 | SVC_PERROR(lcd_writedata(hlcd, data, 4));
|
---|
352 |
|
---|
353 | SVC_PERROR(lcd_writecommand(hlcd, ST7789_RAMWR)); // write to RAM
|
---|
354 | }
|
---|
355 |
|
---|
356 | /*
|
---|
357 | * オリエンテーション設定
|
---|
358 | * param1 hlcd: Pointer to LCD Handler
|
---|
359 | * param2 m: orientation value(0-3)
|
---|
360 | */
|
---|
361 | void
|
---|
362 | lcd_setRotation(LCD_Handler_t *hlcd, uint8_t m)
|
---|
363 | {
|
---|
364 | uint8_t madctl[4];
|
---|
365 |
|
---|
366 | hlcd->rotation = m & 3; // can't be higher than 3
|
---|
367 | madctl[0] = 0;
|
---|
368 |
|
---|
369 | switch(hlcd->rotation){
|
---|
370 | case 0:
|
---|
371 | madctl[0] = ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB;
|
---|
372 | hlcd->colstart = hlcd->lcd_colstart;
|
---|
373 | hlcd->rowstart = hlcd->lcd_rowstart;
|
---|
374 | hlcd->_width = hlcd->lcd_width;
|
---|
375 | hlcd->_height = hlcd->lcd_height;
|
---|
376 | break;
|
---|
377 | case 1:
|
---|
378 | madctl[0] = ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB;
|
---|
379 | hlcd->colstart = hlcd->lcd_rowstart;
|
---|
380 | hlcd->rowstart = hlcd->lcd_colstart;
|
---|
381 | hlcd->_height = hlcd->lcd_width;
|
---|
382 | hlcd->_width = hlcd->lcd_height;
|
---|
383 | break;
|
---|
384 | case 2:
|
---|
385 | madctl[0] = ST7789_MADCTL_RGB;
|
---|
386 | if(hlcd->lcd_width == 135 && hlcd->lcd_height == 240){
|
---|
387 | hlcd->colstart = hlcd->lcd_colstart-1;
|
---|
388 | hlcd->rowstart = hlcd->lcd_rowstart;
|
---|
389 | }
|
---|
390 | else{
|
---|
391 | hlcd->colstart = 0;
|
---|
392 | hlcd->rowstart = 0;
|
---|
393 | }
|
---|
394 | hlcd->_width = hlcd->lcd_width;
|
---|
395 | hlcd->_height = hlcd->lcd_height;
|
---|
396 | break;
|
---|
397 | case 3:
|
---|
398 | madctl[0] = ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB;
|
---|
399 | if(hlcd->lcd_width == 135 && hlcd->lcd_height == 240){
|
---|
400 | hlcd->colstart = hlcd->lcd_rowstart;
|
---|
401 | hlcd->rowstart = hlcd->lcd_colstart;
|
---|
402 | }
|
---|
403 | else{
|
---|
404 | hlcd->colstart = 0;
|
---|
405 | hlcd->rowstart = 0;
|
---|
406 | }
|
---|
407 | hlcd->_height = hlcd->lcd_width;
|
---|
408 | hlcd->_width = hlcd->lcd_height;
|
---|
409 | break;
|
---|
410 | }
|
---|
411 | SVC_PERROR(lcd_writecommand(hlcd, ST7789_MADCTL));
|
---|
412 | SVC_PERROR(lcd_writedata(hlcd, madctl, 1));
|
---|
413 | }
|
---|
414 |
|
---|
415 | /*
|
---|
416 | * ST7789 screensの初期化関数
|
---|
417 | */
|
---|
418 | void
|
---|
419 | lcd_init(LCD_Handler_t *hlcd, uint16_t width, uint16_t height)
|
---|
420 | {
|
---|
421 | commonInit(hlcd, width, height);
|
---|
422 |
|
---|
423 | displayInit(hlcd, Gcmd);
|
---|
424 | lcd_setRotation(hlcd, hlcd->rotation);
|
---|
425 | syslog_2(LOG_NOTICE, "## width(%d) height(%d) ##", hlcd->_width, hlcd->_height);
|
---|
426 | }
|
---|
427 |
|
---|
428 | /*
|
---|
429 | * RECTANGLEのフィル描画
|
---|
430 | * param1 hlcd: Pointer to LCD Handler
|
---|
431 | * param2 x: start X position
|
---|
432 | * param3 y: start Y position
|
---|
433 | * param4 w: width
|
---|
434 | * param5 h: height
|
---|
435 | * param6 color: color value
|
---|
436 | */
|
---|
437 | void
|
---|
438 | lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color)
|
---|
439 | {
|
---|
440 | // rudimentary clipping (drawChar w/big text requires this)
|
---|
441 | if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
|
---|
442 | if((x + w - 1) >= hlcd->_width) w = hlcd->_width - x;
|
---|
443 | if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
|
---|
444 |
|
---|
445 | lcd_setAddrWindow(hlcd, x, y, x+w-1, y+h-1);
|
---|
446 | SVC_PERROR(lcd_writedata2(hlcd, color, h*w));
|
---|
447 | }
|
---|
448 |
|
---|
449 | void
|
---|
450 | lcd_pushColor(LCD_Handler_t *hlcd, color_t color)
|
---|
451 | {
|
---|
452 | SVC_PERROR(lcd_writedata2(hlcd, color, 1));
|
---|
453 | }
|
---|
454 |
|
---|
455 | /*
|
---|
456 | * PIXEL描画
|
---|
457 | * param1 hlcd: Pointer to LCD Handler
|
---|
458 | * param2 x: X position
|
---|
459 | * param3 y: Y position
|
---|
460 | * param4 color: color value
|
---|
461 | */
|
---|
462 | void
|
---|
463 | lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color)
|
---|
464 | {
|
---|
465 | if((x < 0) ||(x >= hlcd->_width) || (y < 0) || (y >= hlcd->_height)) return;
|
---|
466 |
|
---|
467 | lcd_setAddrWindow(hlcd, x, y, x, y);
|
---|
468 | SVC_PERROR(lcd_writedata2(hlcd, color, 1));
|
---|
469 | }
|
---|
470 |
|
---|
471 | /*
|
---|
472 | * 垂直方向LINEの高速描画
|
---|
473 | * param1 hlcd: Pointer to LCD Handler
|
---|
474 | * param2 x: start X position
|
---|
475 | * param3 y: start Y position
|
---|
476 | * param4 h: height
|
---|
477 | * param5 color: color value
|
---|
478 | */
|
---|
479 | void
|
---|
480 | lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color)
|
---|
481 | {
|
---|
482 | // Rudimentary clipping
|
---|
483 | if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
|
---|
484 | if((y+h-1) >= hlcd->_height) h = hlcd->_height-y;
|
---|
485 | lcd_setAddrWindow(hlcd, x, y, x, y+h-1);
|
---|
486 | SVC_PERROR(lcd_writedata2(hlcd, color, h));
|
---|
487 | }
|
---|
488 |
|
---|
489 | /*
|
---|
490 | * 水平方向LINEの高速描画
|
---|
491 | * param1 hlcd: Pointer to LCD Handler
|
---|
492 | * param2 x: start X position
|
---|
493 | * param3 y: start Y position
|
---|
494 | * param4 w: width
|
---|
495 | * param5 color: color value
|
---|
496 | */
|
---|
497 | void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color)
|
---|
498 | {
|
---|
499 | // Rudimentary clipping
|
---|
500 | if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
|
---|
501 | if((x+w-1) >= hlcd->_width) w = hlcd->_width-x;
|
---|
502 | lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
|
---|
503 | SVC_PERROR(lcd_writedata2(hlcd, color, w));
|
---|
504 | }
|
---|
505 |
|
---|
506 | /*
|
---|
507 | * DRAW IMAGE LINE描画
|
---|
508 | * param1 hlcd: Pointer to LCD Handler
|
---|
509 | * param2 x: X position
|
---|
510 | * param3 y: Y position
|
---|
511 | * param4 w: width
|
---|
512 | * param5 pcolor: color value
|
---|
513 | */
|
---|
514 | void
|
---|
515 | lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor)
|
---|
516 | {
|
---|
517 | uint32_t i;
|
---|
518 |
|
---|
519 | if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
|
---|
520 | if((x+w-1) >= hlcd->_width) w = hlcd->_width-x;
|
---|
521 |
|
---|
522 | lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
|
---|
523 | for(i = 0 ; i < w ; i++, pcolor++)
|
---|
524 | SVC_PERROR(lcd_writedata2(hlcd, *pcolor, 1));
|
---|
525 | }
|
---|
526 |
|
---|
527 | /*
|
---|
528 | * BITMAP描画
|
---|
529 | * param1 hlcd: Pointer to LCD Handler
|
---|
530 | * param2 x0: Bmp X position in the LCD
|
---|
531 | * param3 y0: Bmp Y position in the LCD
|
---|
532 | * param4 pbmp: Pointer to Bmp picture address in the internal Flash
|
---|
533 | */
|
---|
534 | void
|
---|
535 | lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp)
|
---|
536 | {
|
---|
537 | uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
|
---|
538 | uint32_t input_color_mode = 0;
|
---|
539 |
|
---|
540 | /* Get bitmap data address offset */
|
---|
541 | index = *(uint16_t *) (pbmp + 10);
|
---|
542 | index |= (*(uint16_t *) (pbmp + 12)) << 16;
|
---|
543 |
|
---|
544 | /* Read bitmap width */
|
---|
545 | width = *(uint16_t *) (pbmp + 18);
|
---|
546 | width |= (*(uint16_t *) (pbmp + 20)) << 16;
|
---|
547 |
|
---|
548 | /* Read bitmap height */
|
---|
549 | height = *(uint16_t *) (pbmp + 22);
|
---|
550 | height |= (*(uint16_t *) (pbmp + 24)) << 16;
|
---|
551 |
|
---|
552 | /* Read bit/pixel */
|
---|
553 | bit_pixel = *(uint16_t *) (pbmp + 28);
|
---|
554 |
|
---|
555 | /* Get the layer pixel format */
|
---|
556 | if ((bit_pixel/8) == 4){
|
---|
557 | input_color_mode = CM_ARGB8888;
|
---|
558 | }
|
---|
559 | else if ((bit_pixel/8) == 2){
|
---|
560 | input_color_mode = CM_RGB565;
|
---|
561 | }
|
---|
562 | else{
|
---|
563 | input_color_mode = CM_RGB888;
|
---|
564 | }
|
---|
565 |
|
---|
566 | /* Bypass the bitmap header */
|
---|
567 | pbmp += (index + (width * (height - 1) * (bit_pixel/8)));
|
---|
568 | syslog_4(LOG_NOTICE, "## input_color_mode(%d) width(%d) height(%d) bit_pixel(%d) ##", input_color_mode, width, height, bit_pixel);
|
---|
569 |
|
---|
570 | lcd_setAddrWindow(hlcd, x0, y0, x0+width-1, y0+height-1);
|
---|
571 | lcd_writedata3(hlcd, pbmp, width, height);
|
---|
572 | }
|
---|
573 |
|
---|
574 | /*
|
---|
575 | * INVERT DISPLAY
|
---|
576 | * param1 hlcd: Pointer to LCD Handler
|
---|
577 | * param2 i: invert value
|
---|
578 | */
|
---|
579 | void
|
---|
580 | lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i)
|
---|
581 | {
|
---|
582 | SVC_PERROR(lcd_writecommand(hlcd, i ? ST7789_INVOFF : ST7789_INVON));
|
---|
583 | }
|
---|
584 |
|
---|
585 |
|
---|
586 | /*
|
---|
587 | * スクリーンフィル
|
---|
588 | * param1 pDrawProp: Pointer to Draw Prop
|
---|
589 | */
|
---|
590 | void
|
---|
591 | lcd_fillScreen(LCD_DrawProp_t *pDrawProp)
|
---|
592 | {
|
---|
593 | lcd_fillRect(pDrawProp->hlcd, 0, 0, pDrawProp->hlcd->_width, pDrawProp->hlcd->_height, pDrawProp->BackColor);
|
---|
594 | }
|
---|
595 |
|
---|
596 | /*
|
---|
597 | * RECTANGLE描画
|
---|
598 | * param1 pDrawProp: Pointer to Draw Prop
|
---|
599 | * param2 x: left X position
|
---|
600 | * param3 y: top Y position
|
---|
601 | * param4 w: width
|
---|
602 | * param5 h: height
|
---|
603 | */
|
---|
604 | void
|
---|
605 | lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h)
|
---|
606 | {
|
---|
607 | LCD_Handler_t *hlcd = pDrawProp->hlcd;
|
---|
608 | color_t color;
|
---|
609 |
|
---|
610 | // rudimentary clipping (drawChar w/big text requires this)
|
---|
611 | if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
|
---|
612 | if((x + w - 1) >= hlcd->_width) w = hlcd->_width - x;
|
---|
613 | if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
|
---|
614 |
|
---|
615 | color = pDrawProp->TextColor;
|
---|
616 | lcd_drawFastVLine(hlcd, x, y, h, color);
|
---|
617 | lcd_drawFastHLine(hlcd, x, y+h-1, w, color);
|
---|
618 | lcd_drawFastVLine(hlcd, x+w-1, y, h, color);
|
---|
619 | lcd_drawFastHLine(hlcd, x, y, w, color);
|
---|
620 | }
|
---|
621 |
|
---|
622 | /*
|
---|
623 | * 円描画
|
---|
624 | * param1 pDrawProp: Pointer to Draw Prop
|
---|
625 | * param2 x0: X position
|
---|
626 | * param3 y0: Y position
|
---|
627 | * param4 Radius: Circle radius
|
---|
628 | */
|
---|
629 | void
|
---|
630 | lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius)
|
---|
631 | {
|
---|
632 | LCD_Handler_t *hlcd = pDrawProp->hlcd;
|
---|
633 | int32_t decision; /* Decision Variable */
|
---|
634 | uint32_t current_x; /* Current X Value */
|
---|
635 | uint32_t current_y; /* Current Y Value */
|
---|
636 |
|
---|
637 | decision = 3 - (Radius << 1);
|
---|
638 | current_x = 0;
|
---|
639 | current_y = Radius;
|
---|
640 |
|
---|
641 | while(current_x <= current_y){
|
---|
642 | lcd_drawPixel(hlcd, (x0 + current_x), (y0 - current_y), pDrawProp->TextColor);
|
---|
643 | lcd_drawPixel(hlcd, (x0 - current_x), (y0 - current_y), pDrawProp->TextColor);
|
---|
644 | lcd_drawPixel(hlcd, (x0 + current_y), (y0 - current_x), pDrawProp->TextColor);
|
---|
645 | lcd_drawPixel(hlcd, (x0 - current_y), (y0 - current_x), pDrawProp->TextColor);
|
---|
646 | lcd_drawPixel(hlcd, (x0 + current_x), (y0 + current_y), pDrawProp->TextColor);
|
---|
647 | lcd_drawPixel(hlcd, (x0 - current_x), (y0 + current_y), pDrawProp->TextColor);
|
---|
648 | lcd_drawPixel(hlcd, (x0 + current_y), (y0 + current_x), pDrawProp->TextColor);
|
---|
649 | lcd_drawPixel(hlcd, (x0 - current_y), (y0 + current_x), pDrawProp->TextColor);
|
---|
650 |
|
---|
651 | if (decision < 0){
|
---|
652 | decision += (current_x << 2) + 6;
|
---|
653 | }
|
---|
654 | else{
|
---|
655 | decision += ((current_x - current_y) << 2) + 10;
|
---|
656 | current_y--;
|
---|
657 | }
|
---|
658 | current_x++;
|
---|
659 | }
|
---|
660 | }
|
---|
661 |
|
---|
662 | /*
|
---|
663 | * 線描画
|
---|
664 | * param1 pDrawProp: Pointer to Draw Prop
|
---|
665 | * param2 x1: Point 1 X position
|
---|
666 | * param3 y1: Point 1 Y position
|
---|
667 | * param4 x2: Point 2 X position
|
---|
668 | * param5 y2: Point 2 Y position
|
---|
669 | */
|
---|
670 | void
|
---|
671 | lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
|
---|
672 | {
|
---|
673 | LCD_Handler_t *hlcd = pDrawProp->hlcd;
|
---|
674 | int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
|
---|
675 | yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0,
|
---|
676 | curpixel = 0;
|
---|
677 |
|
---|
678 | deltax = ABS(x2 - x1); /* The difference between the x's */
|
---|
679 | deltay = ABS(y2 - y1); /* The difference between the y's */
|
---|
680 | x = x1; /* Start x off at the first pixel */
|
---|
681 | y = y1; /* Start y off at the first pixel */
|
---|
682 |
|
---|
683 | if(x2 >= x1){ /* The x-values are increasing */
|
---|
684 | xinc1 = 1;
|
---|
685 | xinc2 = 1;
|
---|
686 | }
|
---|
687 | else{ /* The x-values are decreasing */
|
---|
688 | xinc1 = -1;
|
---|
689 | xinc2 = -1;
|
---|
690 | }
|
---|
691 |
|
---|
692 | if(y2 >= y1){ /* The y-values are increasing */
|
---|
693 | yinc1 = 1;
|
---|
694 | yinc2 = 1;
|
---|
695 | }
|
---|
696 | else{ /* The y-values are decreasing */
|
---|
697 | yinc1 = -1;
|
---|
698 | yinc2 = -1;
|
---|
699 | }
|
---|
700 |
|
---|
701 | if(deltax >= deltay){ /* There is at least one x-value for every y-value */
|
---|
702 | xinc1 = 0; /* Don't change the x when numerator >= denominator */
|
---|
703 | yinc2 = 0; /* Don't change the y for every iteration */
|
---|
704 | den = deltax;
|
---|
705 | num = deltax / 2;
|
---|
706 | num_add = deltay;
|
---|
707 | num_pixels = deltax; /* There are more x-values than y-values */
|
---|
708 | }
|
---|
709 | else{ /* There is at least one y-value for every x-value */
|
---|
710 | xinc2 = 0; /* Don't change the x for every iteration */
|
---|
711 | yinc1 = 0; /* Don't change the y when numerator >= denominator */
|
---|
712 | den = deltay;
|
---|
713 | num = deltay / 2;
|
---|
714 | num_add = deltax;
|
---|
715 | num_pixels = deltay; /* There are more y-values than x-values */
|
---|
716 | }
|
---|
717 |
|
---|
718 | for (curpixel = 0; curpixel <= num_pixels; curpixel++){
|
---|
719 | lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor); /* Draw the current pixel */
|
---|
720 | num += num_add; /* Increase the numerator by the top of the fraction */
|
---|
721 | if(num >= den){ /* Check if numerator >= denominator */
|
---|
722 | num -= den; /* Calculate the new numerator value */
|
---|
723 | x += xinc1; /* Change the x as appropriate */
|
---|
724 | y += yinc1; /* Change the y as appropriate */
|
---|
725 | }
|
---|
726 | x += xinc2; /* Change the x as appropriate */
|
---|
727 | y += yinc2; /* Change the y as appropriate */
|
---|
728 | }
|
---|
729 | }
|
---|
730 |
|
---|
731 | /*
|
---|
732 | * PLOY-LINE描画
|
---|
733 | * param1 pDrawProp: Pointer to Draw Prop
|
---|
734 | * param2 Points: Pointer to the points array
|
---|
735 | * param3 PointCount: Number of points
|
---|
736 | */
|
---|
737 | void
|
---|
738 | lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
|
---|
739 | {
|
---|
740 | int16_t x = 0, y = 0;
|
---|
741 |
|
---|
742 | if(PointCount < 2){
|
---|
743 | return;
|
---|
744 | }
|
---|
745 |
|
---|
746 | lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
|
---|
747 | while(--PointCount){
|
---|
748 | x = Points->X;
|
---|
749 | y = Points->Y;
|
---|
750 | Points++;
|
---|
751 | lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
|
---|
752 | }
|
---|
753 | }
|
---|
754 |
|
---|