1 /*
2  * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-02-25     lik          first version
9  */
10 
11 #include "drv_rgb_lcd.h"
12 
13 #ifdef BSP_USING_RGB_LCD
14 #include "rgb_lcd_port.h"
15 
16 #define DRV_DEBUG
17 #define LOG_TAG "drv.rgb_lcd"
18 #include <drv_log.h>
19 
20 #define LCD_DEVICE(dev) (struct swm_rgb_lcd_device *)(dev)
21 
22 struct swm_rgb_lcd_device rgb_lcd_obj;
23 
swm_rgb_lcd_configure(struct rt_device * device)24 static rt_err_t swm_rgb_lcd_configure(struct rt_device *device)
25 {
26     struct swm_rgb_lcd_device *rgb_lcd = LCD_DEVICE(device);
27     /* nothing, right now */
28     rgb_lcd = rgb_lcd;
29     return RT_EOK;
30 }
31 
swm_rgb_lcd_control(struct rt_device * device,int cmd,void * args)32 static rt_err_t swm_rgb_lcd_control(struct rt_device *device, int cmd, void *args)
33 {
34     struct swm_rgb_lcd_device *rgb_lcd = LCD_DEVICE(device);
35 
36     switch (cmd)
37     {
38     case RTGRAPHIC_CTRL_GET_INFO:
39     {
40         struct rt_device_graphic_info *info = (struct rt_device_graphic_info *)args;
41 
42         RT_ASSERT(info != RT_NULL);
43         info->pixel_format = rgb_lcd->lcd_info.pixel_format;
44         info->bits_per_pixel = rgb_lcd->lcd_info.bits_per_pixel;
45         info->width = rgb_lcd->lcd_info.width;
46         info->height = rgb_lcd->lcd_info.height;
47         info->framebuffer = rgb_lcd->lcd_info.framebuffer;
48     }
49     break;
50 
51     default:
52         return -RT_EINVAL;
53     }
54 
55     return RT_EOK;
56 }
57 
58 #if defined(LCD_BACKLIGHT_USING_PWM)
turn_on_lcd_backlight(void)59 static void turn_on_lcd_backlight(void)
60 {
61     struct rt_device_pwm *pwm_dev;
62 
63     /* turn on the LCD backlight */
64     pwm_dev = (struct rt_device_pwm *)rt_device_find(LCD_PWM_DEV_NAME);
65     /* pwm frequency:100K = 10000ns */
66     rt_pwm_set(pwm_dev, LCD_PWM_DEV_CHANNEL, 10000, 10000);
67     rt_pwm_enable(pwm_dev, LCD_PWM_DEV_CHANNEL);
68 }
69 #elif defined(LCD_BACKLIGHT_USING_GPIO)
turn_on_lcd_backlight(void)70 static void turn_on_lcd_backlight(void)
71 {
72     rt_pin_mode(LCD_DISP_GPIO, PIN_MODE_OUTPUT);
73     rt_pin_write(LCD_DISP_GPIO, PIN_HIGH);
74 
75     rt_pin_mode(LCD_BL_GPIO, PIN_MODE_OUTPUT);
76     rt_pin_write(LCD_BL_GPIO, PIN_HIGH);
77 }
78 #else
turn_on_lcd_backlight(void)79 static void turn_on_lcd_backlight(void)
80 {
81 }
82 #endif
83 
84 #ifdef RT_USING_DEVICE_OPS
85 static const struct rt_device_ops swm_lcd_ops =
86     {
87         .init = swm_rgb_lcd_configure,
88         .open = RT_NULL,
89         .close = RT_NULL,
90         .read = RT_NULL,
91         .write = RT_NULL,
92         .control = swm_rgb_lcd_control};
93 #endif
94 
swm_rgb_lcd_init(void)95 int swm_rgb_lcd_init(void)
96 {
97     rt_err_t result = RT_EOK;
98     struct rt_device *device = &rgb_lcd_obj.parent;
99 
100     /* memset rgb_lcd_obj to zero */
101     memset(&rgb_lcd_obj, 0x00, sizeof(rgb_lcd_obj));
102 
103     /* config LCD dev info */
104     rgb_lcd_obj.lcd_info.height = LCD_HEIGHT;
105     rgb_lcd_obj.lcd_info.width = LCD_WIDTH;
106     rgb_lcd_obj.lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
107     rgb_lcd_obj.lcd_info.pixel_format = LCD_PIXEL_FORMAT;
108 
109     /* malloc memory for Triple Buffering */
110     rgb_lcd_obj.lcd_info.framebuffer = rt_malloc_align(LCD_BUF_SIZE,4);
111     if (rgb_lcd_obj.lcd_info.framebuffer == RT_NULL)
112     {
113         LOG_E("init frame buffer failed!\n");
114         result = -RT_ENOMEM;
115         goto __exit;
116     }
117     /* memset buff to 0xFF */
118     memset(rgb_lcd_obj.lcd_info.framebuffer, 0xFF, LCD_BUF_SIZE);
119 
120     device->type = RT_Device_Class_Graphic;
121 #ifdef RT_USING_DEVICE_OPS
122     device->ops = &swm_lcd_ops;
123 #else
124     device->init = swm_rgb_lcd_configure;
125     device->control = swm_rgb_lcd_control;
126 #endif
127     /* register lcd device */
128     rt_device_register(device, "rgb_lcd", RT_DEVICE_FLAG_RDWR);
129 
130     LCD_InitStructure LCD_initStruct;
131 
132     // PORT_Init(PORTB, PIN1, PORTB_PIN1_LCD_B0, 0);
133     // PORT_Init(PORTB, PIN11, PORTB_PIN11_LCD_B1, 0);
134     // PORT_Init(PORTB, PIN13, PORTB_PIN13_LCD_B2, 0);
135     PORT_Init(PORTB, PIN15, PORTB_PIN15_LCD_B3, 0);
136     PORT_Init(PORTA, PIN2, PORTA_PIN2_LCD_B4, 0);
137     PORT_Init(PORTA, PIN9, PORTA_PIN9_LCD_B5, 0);
138     PORT_Init(PORTA, PIN10, PORTA_PIN10_LCD_B6, 0);
139     PORT_Init(PORTA, PIN11, PORTA_PIN11_LCD_B7, 0);
140 
141     // PORT_Init(PORTA, PIN12, PORTA_PIN12_LCD_G0, 0);
142     // PORT_Init(PORTA, PIN13, PORTA_PIN13_LCD_G1, 0);
143     PORT_Init(PORTA, PIN14, PORTA_PIN14_LCD_G2, 0);
144     PORT_Init(PORTA, PIN15, PORTA_PIN15_LCD_G3, 0);
145     PORT_Init(PORTC, PIN0, PORTC_PIN0_LCD_G4, 0);
146     PORT_Init(PORTC, PIN1, PORTC_PIN1_LCD_G5, 0);
147     PORT_Init(PORTC, PIN2, PORTC_PIN2_LCD_G6, 0);
148     PORT_Init(PORTC, PIN3, PORTC_PIN3_LCD_G7, 0);
149 
150     // PORT_Init(PORTC, PIN4, PORTC_PIN4_LCD_R0, 0);
151     // PORT_Init(PORTC, PIN5, PORTC_PIN5_LCD_R1, 0);
152     // PORT_Init(PORTC, PIN8, PORTC_PIN8_LCD_R2, 0);
153     PORT_Init(PORTC, PIN9, PORTC_PIN9_LCD_R3, 0);
154     PORT_Init(PORTC, PIN10, PORTC_PIN10_LCD_R4, 0);
155     PORT_Init(PORTC, PIN11, PORTC_PIN11_LCD_R5, 0);
156     PORT_Init(PORTC, PIN12, PORTC_PIN12_LCD_R6, 0);
157     PORT_Init(PORTC, PIN13, PORTC_PIN13_LCD_R7, 0);
158 
159     PORT_Init(PORTB, PIN2, PORTB_PIN2_LCD_VSYNC, 0);
160     PORT_Init(PORTB, PIN3, PORTB_PIN3_LCD_HSYNC, 0);
161     PORT_Init(PORTB, PIN4, PORTB_PIN4_LCD_DEN, 0);
162     PORT_Init(PORTB, PIN5, PORTB_PIN5_LCD_DCLK, 0);
163 
164     LCD_initStruct.ClkDiv = LCD_CLK_DIV;
165     LCD_initStruct.Format = ((LCD_BITS_PER_PIXEL == 16) ? LCD_FMT_RGB565 : LCD_FMT_RGB888);
166     LCD_initStruct.HnPixel = LCD_WIDTH;
167     LCD_initStruct.VnPixel = LCD_HEIGHT;
168     LCD_initStruct.Hfp = LCD_HFP;
169     LCD_initStruct.Hbp = LCD_HBP;
170     LCD_initStruct.Vfp = LCD_VFP;
171     LCD_initStruct.Vbp = LCD_VBP;
172     LCD_initStruct.HsyncWidth = LCD_HSYNC_WIDTH;
173     LCD_initStruct.VsyncWidth = LCD_VSYNC_WIDTH;
174 
175     LCD_initStruct.DataSource = (uint32_t)rgb_lcd_obj.lcd_info.framebuffer;
176     LCD_initStruct.Background = 0xFFFFFF;
177     LCD_initStruct.SampleEdge = LCD_SAMPLE_FALL;
178     LCD_initStruct.IntEOTEn = 0;
179     LCD_Init(LCD, &LCD_initStruct);
180     LCD_Start(LCD);
181     turn_on_lcd_backlight();
182 __exit:
183     if (result != RT_EOK)
184     {
185         if (rgb_lcd_obj.lcd_info.framebuffer)
186         {
187             rt_free(rgb_lcd_obj.lcd_info.framebuffer);
188         }
189     }
190     return result;
191 }
192 INIT_BOARD_EXPORT(swm_rgb_lcd_init);
193 
lcd_test(void)194 int lcd_test(void)
195 {
196     struct swm_rgb_lcd_device *rgb_lcd;
197     rgb_lcd = (struct swm_rgb_lcd_device *)rt_device_find("rgb_lcd");
198 
199     // while (1)
200     {
201         /* red */
202         for (int i = 0; i < LCD_BUF_SIZE / 2; i++)
203         {
204             rgb_lcd->lcd_info.framebuffer[2 * i] = 0x00;
205             rgb_lcd->lcd_info.framebuffer[2 * i + 1] = 0xF8;
206         }
207         rgb_lcd->parent.control(&rgb_lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
208         rt_thread_mdelay(1000);
209         /* green */
210         for (int i = 0; i < LCD_BUF_SIZE / 2; i++)
211         {
212             rgb_lcd->lcd_info.framebuffer[2 * i] = 0xE0;
213             rgb_lcd->lcd_info.framebuffer[2 * i + 1] = 0x07;
214         }
215         rgb_lcd->parent.control(&rgb_lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
216         rt_thread_mdelay(1000);
217         /* blue */
218         for (int i = 0; i < LCD_BUF_SIZE / 2; i++)
219         {
220             rgb_lcd->lcd_info.framebuffer[2 * i] = 0x1F;
221             rgb_lcd->lcd_info.framebuffer[2 * i + 1] = 0x00;
222         }
223         rgb_lcd->parent.control(&rgb_lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
224         rt_thread_mdelay(1000);
225     }
226     return 0;
227 }
228 MSH_CMD_EXPORT(lcd_test, lcd_test);
229 
230 #endif /* BSP_USING_RGB_LCD */
231