1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  */
9 #include <rtthread.h>
10 #include "board.h"
11 
12 #define LED_DEVICE_CTRL     0x81        /*LED control command*/
13 
14 #define LED_NUM    4
15 struct led_ctrl
16 {
17     uint32_t num;
18     LPC_GPIO_TypeDef *port;
19 };
20 
21 struct lpc_led
22 {
23     /* inherit from rt_device */
24     struct rt_device parent;
25 
26     struct led_ctrl ctrl[LED_NUM];
27 };
28 
29 static struct lpc_led led;
30 
rt_led_init(rt_device_t dev)31 static rt_err_t rt_led_init(rt_device_t dev)
32 {
33     /* led0 : P4.27,led1:P4.15 ,led2:P4.16 ,led3:P4.17*/
34     /* set P4.14,P4.15,P4.16,P4.17 as GPIO. */
35     LPC_IOCON->P4_27 = 0x00;
36     LPC_IOCON->P4_15 = 0x00;
37     LPC_IOCON->P4_16 = 0x00;
38     LPC_IOCON->P4_17 = 0x00;
39     /* set P4.27,P4.15,P4.16,P4.17  output. */
40     LPC_GPIO4->DIR |= (0x07 << 15) | (0x01 << 27);
41     /* turn off all the led */
42     LPC_GPIO4->SET = (0x07 << 15) | (0x01 << 27);
43     led.ctrl[3].num = 27;
44     led.ctrl[3].port = LPC_GPIO4;
45     led.ctrl[2].num = 15;
46     led.ctrl[2].port = LPC_GPIO4;
47     led.ctrl[1].num = 16;
48     led.ctrl[1].port = LPC_GPIO4;
49     led.ctrl[0].num = 17;
50     led.ctrl[0].port = LPC_GPIO4;
51     return RT_EOK;
52 }
53 
rt_led_open(rt_device_t dev,rt_uint16_t oflag)54 static rt_err_t rt_led_open(rt_device_t dev, rt_uint16_t oflag)
55 {
56     return RT_EOK;
57 }
58 
rt_led_close(rt_device_t dev)59 static rt_err_t rt_led_close(rt_device_t dev)
60 {
61     return RT_EOK;
62 }
63 
rt_led_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)64 static rt_ssize_t rt_led_read(rt_device_t dev, rt_off_t pos, void *buffer,
65                              rt_size_t size)
66 {
67     rt_ubase_t index = 0;
68     rt_ubase_t nr = size;
69     rt_uint8_t *value = buffer;
70 
71     RT_ASSERT(dev == &led.parent);
72     RT_ASSERT((pos + size) <= LED_NUM);
73 
74     for (index = 0; index < nr; index++)
75     {
76         if ((led.ctrl[pos + index].port->PIN) & 1 << led.ctrl[pos + index].num)
77         {
78             *value = 0;
79         }
80         else
81         {
82             *value = 1;
83         }
84         value++;
85     }
86     return index;
87 }
88 
rt_led_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)89 static rt_ssize_t rt_led_write(rt_device_t dev, rt_off_t pos,
90                               const void *buffer, rt_size_t size)
91 {
92     rt_ubase_t index = 0;
93     rt_ubase_t nw = size;
94     const rt_uint8_t *value = buffer;
95 
96     RT_ASSERT(dev == &led.parent);
97     RT_ASSERT((pos + size) <= LED_NUM);
98 
99     for (index = 0; index < nw; index++)
100     {
101         if (*value++)
102         {
103             led.ctrl[pos + index].port->CLR |= (1 << led.ctrl[pos + index].num);
104         }
105         else
106         {
107             led.ctrl[pos + index].port->SET |= (1 << led.ctrl[pos + index].num);
108         }
109     }
110     return index;
111 }
112 
rt_led_control(rt_device_t dev,int cmd,void * args)113 static rt_err_t rt_led_control(rt_device_t dev, int cmd, void *args)
114 {
115     RT_ASSERT(dev == &led.parent);
116 
117     if (cmd == LED_DEVICE_CTRL)
118     {
119         rt_uint32_t *led_num = args;
120         *led_num = LED_NUM;
121     }
122     return RT_EOK;
123 }
124 
rt_hw_led_init(void)125 int rt_hw_led_init(void)
126 {
127     led.parent.type         = RT_Device_Class_Char;
128     led.parent.rx_indicate  = RT_NULL;
129     led.parent.tx_complete  = RT_NULL;
130     led.parent.init         = rt_led_init;
131     led.parent.open         = rt_led_open;
132     led.parent.close        = rt_led_close;
133     led.parent.read         = rt_led_read;
134     led.parent.write        = rt_led_write;
135     led.parent.control      = rt_led_control;
136     led.parent.user_data    = RT_NULL;
137 
138     /* register a character device */
139     rt_device_register(&led.parent, "led", RT_DEVICE_FLAG_RDWR);
140     /* init led device */
141     rt_led_init(&led.parent);
142     return 0;
143 }
144 INIT_DEVICE_EXPORT(rt_hw_led_init);
145 
146 #ifdef RT_USING_FINSH
147 #include <finsh.h>
led_test(rt_uint32_t led_num,rt_uint32_t value)148 void led_test(rt_uint32_t led_num, rt_uint32_t value)
149 {
150     rt_uint8_t led_value = value;
151     rt_led_write(&led.parent, led_num, &led_value, 1);
152 }
153 FINSH_FUNCTION_EXPORT(led_test, e.g: led_test(0, 100).)
154 #endif
155