Skip to content

Commit fa4cf5c

Browse files
committed
Add lcddrvce example for half-res mode
1 parent f068f1b commit fa4cf5c

File tree

3 files changed

+233
-0
lines changed

3 files changed

+233
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
obj/
2+
bin/
3+
src/gfx/*.c
4+
src/gfx/*.h
5+
src/gfx/*.8xv
6+
.DS_Store
7+
convimg.yaml.lst
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# ----------------------------
2+
# Makefile Options
3+
# ----------------------------
4+
5+
NAME = DEMO
6+
ICON = icon.png
7+
DESCRIPTION = "CE C Toolchain Demo"
8+
COMPRESSED = NO
9+
10+
CFLAGS = -Wall -Wextra -Oz
11+
CXXFLAGS = -Wall -Wextra -Oz
12+
13+
# ----------------------------
14+
15+
include $(shell cedev-config --makefile)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#include <lcddrvce.h>
2+
#include <graphx.h>
3+
#include <sys/lcd.h>
4+
#include <ti/getcsc.h>
5+
#include <stdint.h>
6+
#include <string.h>
7+
8+
#define HALF_LCD_WIDTH (LCD_WIDTH / 2)
9+
#define HALF_LCD_HEIGHT (LCD_HEIGHT / 2)
10+
11+
/* Function Prototypes */
12+
void PrintCentered(const char *str, unsigned int border);
13+
void QuarterResFillScreen(uint8_t color);
14+
void QuarterResSwapDraw(void);
15+
void SetHalfResMode(bool enable);
16+
17+
int main(void)
18+
{
19+
/* Initialize GraphX first, because it sets LCD timing */
20+
gfx_Begin();
21+
22+
/* Set half-resolution mode */
23+
SetHalfResMode(true);
24+
25+
/* Set clipping to an 160x120 area that draws to every second line of the half-res buffer */
26+
gfx_SetClipRegion(0, 0, HALF_LCD_WIDTH - 1, HALF_LCD_HEIGHT - 1);
27+
gfx_SetDrawBuffer();
28+
29+
unsigned int border = 2;
30+
int dir = 1;
31+
32+
/* Wait for a keypress */
33+
while (!os_GetCSC())
34+
{
35+
/* Clear the screen, gfx_FillScreen covers too much area so use this instead */
36+
QuarterResFillScreen(255);
37+
38+
/* Print the message on the screen */
39+
PrintCentered("Hello, World!", border);
40+
41+
/* Swap buffers and fill in every second line */
42+
QuarterResSwapDraw();
43+
44+
/* Change the border size for the next frame */
45+
border += dir;
46+
if (border <= 2 || border >= 25)
47+
{
48+
dir = -dir;
49+
}
50+
}
51+
52+
/* Ensure one empty frame is fully displayed to make the transition to full-res clean */
53+
gfx_FillScreen(255);
54+
gfx_SwapDraw();
55+
gfx_FillScreen(255);
56+
gfx_SwapDraw();
57+
58+
/* Restore normal resolution mode */
59+
SetHalfResMode(false);
60+
61+
/* Wait for the second empty frame to display */
62+
gfx_Wait();
63+
64+
/* Deinitialize GraphX */
65+
gfx_End();
66+
67+
return 0;
68+
}
69+
70+
/* Prints a quarter-res screen centered string */
71+
void PrintCentered(const char *str, unsigned int border)
72+
{
73+
unsigned int width = gfx_GetStringWidth(str);
74+
gfx_PrintStringXY(str,
75+
(HALF_LCD_WIDTH - width) / 2,
76+
(HALF_LCD_HEIGHT - 8) / 2);
77+
gfx_Circle(HALF_LCD_WIDTH / 2, HALF_LCD_HEIGHT / 2, width / 2 + border);
78+
}
79+
80+
/* Fills the drawable area of a quarter-res screen */
81+
void QuarterResFillScreen(uint8_t color)
82+
{
83+
uint8_t oldColor = gfx_SetColor(color);
84+
gfx_FillRectangle_NoClip(0, 0, HALF_LCD_WIDTH, HALF_LCD_HEIGHT);
85+
gfx_SetColor(oldColor);
86+
}
87+
88+
/* Copies the rendered lines to the unrendered lines before swapping the buffer */
89+
void QuarterResSwapDraw(void)
90+
{
91+
gfx_CopyRectangle(gfx_buffer, gfx_buffer, 0, 0, HALF_LCD_WIDTH, 0, HALF_LCD_WIDTH, HALF_LCD_HEIGHT);
92+
gfx_SwapDraw();
93+
}
94+
95+
void SetHalfResMode(bool enable)
96+
{
97+
typedef struct lcd_timing
98+
{
99+
uint32_t : 2;
100+
uint32_t PPL : 6;
101+
uint32_t HSW : 8;
102+
uint32_t HFP : 8;
103+
uint32_t HBP : 8;
104+
105+
uint32_t LPP : 10;
106+
uint32_t VSW : 6;
107+
uint32_t VFP : 8;
108+
uint32_t VBP : 8;
109+
110+
uint32_t PCD_LO : 5;
111+
uint32_t CLKSEL : 1;
112+
uint32_t ACB : 5;
113+
uint32_t IVS : 1;
114+
uint32_t IHS : 1;
115+
uint32_t IPC : 1;
116+
uint32_t IOE : 1;
117+
uint32_t : 1;
118+
uint32_t CPL : 10;
119+
uint32_t BCD : 1;
120+
uint32_t PCD_HI : 5;
121+
} lcd_timing_t;
122+
123+
typedef struct res_settings
124+
{
125+
uint8_t frctrl2;
126+
uint8_t bpa;
127+
uint16_t xe;
128+
uint8_t tfa;
129+
uint8_t ramctrl1;
130+
lcd_timing_t timing;
131+
} res_settings_t;
132+
133+
static res_settings_t settings[2] =
134+
{
135+
{
136+
/* Default ST7789 settings */
137+
.frctrl2 = LCD_FRCTRL2_DEFAULT,
138+
.bpa = LCD_BPA_DEFAULT,
139+
.xe = LCD_WIDTH - 1,
140+
.tfa = 0,
141+
.ramctrl1 = LCD_RAMCTRL1_DEFAULT
142+
},
143+
{
144+
/* With the following ST7789 timing:
145+
* Refreshes LCD in at most 16.51 ms after VSYNC, assuming worst case 9.5 MHz clock
146+
* Waits at least 3.42 ms after VSYNC to read LCD memory, assuming worst case 10.5 MHz clock
147+
*/
148+
.frctrl2 = 8, /* 378 clocks per line */
149+
.bpa = 95, /* 95 lines of back porch */
150+
.xe = HALF_LCD_WIDTH - 1,
151+
.tfa = HALF_LCD_WIDTH,
152+
.ramctrl1 = LCD_RAM_RGB | LCD_DM_VSYNC,
153+
/* With the following PL111 timing:
154+
* Refreshes LCD at 60 Hz = 24 MHz / (800*250*2), a VSYNC period of 16.67 ms
155+
* Outputs 38400 pixels to LCD memory within the first 3.40 ms after VSYNC
156+
*/
157+
.timing =
158+
{
159+
.PPL = 768 / 16 - 1, /* 768 pixels per line */
160+
.HSW = 1 - 1,
161+
.HFP = (800 - 768 - 1 - 1) - 1, /* 800 total clocks per line */
162+
.HBP = 1 - 1,
163+
.LPP = HALF_LCD_WIDTH * LCD_HEIGHT / 768, /* 50 lines */
164+
.VSW = 1 - 1,
165+
.VFP = 250 - (HALF_LCD_WIDTH * LCD_HEIGHT / 768) - 1, /* 250 total lines */
166+
.VBP = 0,
167+
.PCD_LO = (2 - 2) & 0x1F, /* clock divisor of 2 */
168+
.CLKSEL = 0,
169+
.ACB = 0,
170+
.IVS = 1,
171+
.IHS = 1,
172+
.IPC = 1,
173+
.IOE = 1,
174+
.CPL = 768 - 1,
175+
.BCD = 0,
176+
.PCD_HI = (2 - 2) >> 5
177+
}
178+
}
179+
};
180+
181+
const res_settings_t *p = &settings[enable];
182+
183+
/* Initialize LCD driver */
184+
lcd_Init();
185+
186+
/* Set clocks per line */
187+
lcd_SetNormalFrameRateControl(p->frctrl2);
188+
/* Set back porch */
189+
lcd_SendCommand1(LCD_CMD_PORCTRL, p->bpa);
190+
/* Set horizontal output window */
191+
lcd_SetColumnAddress(0, p->xe);
192+
/* Set fixed left scroll area */
193+
lcd_SetScrollArea(p->tfa, LCD_WIDTH - p->tfa, 0);
194+
/* Set starting vertical scroll address to 0 */
195+
lcd_SetScrollAddress(0);
196+
/* Set display mode */
197+
lcd_SetRamInterface(p->ramctrl1);
198+
/* Set interlace mode */
199+
lcd_SetInterlacedMode(enable);
200+
201+
/* Save old display timing when enabling */
202+
if (enable)
203+
{
204+
memcpy(&settings[0].timing, (const void *)&lcd_Timing0, sizeof(settings[0].timing));
205+
}
206+
/* Set display timing */
207+
memcpy((void *)&lcd_Timing0, &p->timing, sizeof(p->timing));
208+
209+
/* Cleanup LCD driver */
210+
lcd_Cleanup();
211+
}

0 commit comments

Comments
 (0)