• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * devices for ESP WROVER KIT
3  *
4  * Written in 2010-2020 by Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  */
9 
10 #define LWIP_PROVIDE_ERRNO 1
11 #define _ESP_PLATFORM_ERRNO_H_
12 
13 #include <stdio.h>
14 #include "sdkconfig.h"
15 #include "freertos/FreeRTOS.h"
16 #include "freertos/task.h"
17 
18 #include <driver/gpio.h>
19 
20 #include <libwebsockets.h>
21 
22 struct lws_led_state *lls;
23 lws_display_state_t lds;
24 struct lws_button_state *bcs;
25 lws_netdev_instance_wifi_t *wnd;
26 
27 /*
28  * Button controller
29  *
30  * On the WROVER KIT, it's a bit overloaded... the two buttons are reset and
31  * gpio0, gpio is also used for one of the RGB LEDs channels control so it's not
32  * really usable as a general user button.
33  *
34  * Instead we use GPIO 14 (available on J1) for a button with the other side
35  * of the switch connected to 0V.
36  */
37 
38 static const lws_button_map_t bcm[] = {
39 	{
40 		.gpio			= GPIO_NUM_14,
41 		.smd_interaction_name	= "user"
42 	},
43 };
44 
45 static const lws_button_controller_t bc = {
46 	.smd_bc_name			= "bc",
47 	.gpio_ops			= &lws_gpio_plat,
48 	.button_map			= &bcm[0],
49 	.active_state_bitmap		= 0,
50 	.count_buttons			= LWS_ARRAY_SIZE(bcm),
51 };
52 
53 /*
54  * pwm controller
55  */
56 
57 static const lws_pwm_map_t pwm_map[] = {
58 	{ .gpio = GPIO_NUM_2, .index = 0, .active_level = 1 },
59 	{ .gpio = GPIO_NUM_0, .index = 1, .active_level = 1 },
60 	{ .gpio = GPIO_NUM_4, .index = 2, .active_level = 1 },
61 	{ .gpio = GPIO_NUM_5, .index = 3, .active_level = 0 }
62 };
63 
64 static const lws_pwm_ops_t pwm_ops = {
65 	lws_pwm_plat_ops,
66 	.pwm_map			= &pwm_map[0],
67 	.count_pwm_map			= LWS_ARRAY_SIZE(pwm_map)
68 };
69 
70 /*
71  * led controller
72  */
73 
74 static const lws_led_gpio_map_t lgm[] = {
75 	{
76 		.name			= "red",
77 		.gpio			= GPIO_NUM_2,
78 		.pwm_ops		= &pwm_ops, /* managed by pwm */
79 		.active_level		= 1,
80 	},
81 	{
82 		.name			= "green",
83 		.gpio			= GPIO_NUM_0,
84 		.pwm_ops		= &pwm_ops, /* managed by pwm */
85 		.active_level		= 1,
86 	},
87 	{
88 		.name			= "blue",
89 		.gpio			= GPIO_NUM_4,
90 		.pwm_ops		= &pwm_ops, /* managed by pwm */
91 		.active_level		= 1,
92 	},
93 	{
94 		.name			= "backlight",
95 		.gpio			= GPIO_NUM_5,
96 		.pwm_ops		= &pwm_ops, /* managed by pwm */
97 		.active_level		= 0,
98 		/*
99 		 * The wrover kit uses a 2 NPN in series to drive the backlight
100 		 * which means if the GPIO provides no current, the backlight is
101 		 * full-on.  This causes a white flash during boot... they mark
102 		 * the first stage with "Modify In ESP-WROVER-KIT!" on the
103 		 * schematics but on Kit v4.1, it's still like that.
104 		 */
105 	},
106 };
107 
108 static const lws_led_gpio_controller_t lgc = {
109 	.led_ops			= lws_led_gpio_ops,
110 	.gpio_ops			= &lws_gpio_plat,
111 	.led_map			= &lgm[0],
112 	.count_leds			= LWS_ARRAY_SIZE(lgm)
113 };
114 
115 /*
116  * Bitbang SPI configuration for display
117  */
118 
119 static const lws_bb_spi_t lbspi = {
120 		.bb_ops = {
121 			lws_bb_spi_ops,
122 			.bus_mode = LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING
123 		},
124 		.gpio		= &lws_gpio_plat,
125 		.clk		= GPIO_NUM_19,
126 		.ncs		= { GPIO_NUM_22 },
127 		.ncmd		= { GPIO_NUM_21 },
128 		.mosi		= GPIO_NUM_23,
129 		.miso		= GPIO_NUM_25,
130 		.flags		= LWSBBSPI_FLAG_USE_NCS0 |
131 				  LWSBBSPI_FLAG_USE_NCMD0
132 };
133 
134 /*
135  * SPI display
136  */
137 
138 static const lws_display_ili9341_t disp = {
139 	.disp = {
140 		lws_display_ili9341_ops,
141 		.bl_pwm_ops		= &pwm_ops,
142 		.bl_active		= &lws_pwmseq_static_on,
143 		.bl_dim			= &lws_pwmseq_static_half,
144 		.bl_transition		= &lws_pwmseq_linear_wipe,
145 		.bl_index		= 3,
146 		.w			= 320,
147 		.h			= 240,
148 		.latency_wake_ms	= 150,
149 	},
150 	.spi				= (lws_spi_ops_t *)&lbspi,
151 	.gpio				= &lws_gpio_plat,
152 	.reset_gpio			= GPIO_NUM_18,
153 	.spi_index			= 0
154 };
155 
156 /*
157  * Settings stored in platform nv
158  */
159 
160 static const lws_settings_ops_t sett = {
161 	lws_settings_ops_plat
162 };
163 
164 /*
165  * Wifi
166  */
167 
168 static const lws_netdev_ops_t wifi_ops = {
169 	lws_netdev_wifi_plat_ops
170 };
171 
172 int
init_plat_devices(struct lws_context * ctx)173 init_plat_devices(struct lws_context *ctx)
174 {
175 	lws_settings_instance_t *si;
176 	lws_netdevs_t *netdevs = lws_netdevs_from_ctx(ctx);
177 
178 	si = lws_settings_init(&sett, (void *)"nvs");
179 	if (!si) {
180 		lwsl_err("%s: failed to create settings instance\n", __func__);
181 		return 1;
182 	}
183 	netdevs->si = si;
184 
185 #if 0
186 	/*
187 	 * This is a temp hack to bootstrap the settings to contain the test
188 	 * AP ssid and passphrase for one time, so the settings can be stored
189 	 * while there's no UI atm
190 	 */
191 	{
192 		lws_wifi_creds_t creds;
193 
194 		memset(&creds, 0, sizeof(creds));
195 
196 		lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid));
197 		lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase));
198 		lws_dll2_add_tail(&creds.list, &netdevs->owner_creds);
199 
200 		if (lws_netdev_credentials_settings_set(netdevs)) {
201 			lwsl_err("%s: failed to write bootstrap creds\n",
202 					__func__);
203 			return 1;
204 		}
205 	}
206 #endif
207 
208 //	if (lws_netdev_instance_wifi_settings_get(si, "netdev.wl0", &niw, &ac)) {
209 //		lwsl_err("%s: unable to fetch wl0 settings\n", __func__);
210 //		return 1;
211 //	}
212 
213 	/* create the wifi network device and configure it */
214 
215 	wnd = (lws_netdev_instance_wifi_t *)
216 				wifi_ops.create(ctx, &wifi_ops, "wl0", NULL);
217 	if (!wnd) {
218 		lwsl_err("%s: failed to create wifi object\n", __func__);
219 		return 1;
220 	}
221 
222 	wnd->flags |= LNDIW_MODE_STA;
223 
224 	if (wifi_ops.configure(&wnd->inst, NULL)) {
225 		lwsl_err("%s: failed to configure wifi object\n", __func__);
226 		return 1;
227 	}
228 
229 	wifi_ops.up(&wnd->inst);
230 
231 	/* bring up the led controller */
232 
233 	lls = lgc.led_ops.create(&lgc.led_ops);
234 	if (!lls) {
235 		lwsl_err("%s: could not create led\n", __func__);
236 		return 1;
237 	}
238 
239 	/* pwm init must go after the led controller init */
240 
241 	pwm_ops.init(&pwm_ops);
242 
243 	/* ... and the button controller */
244 
245 	bcs = lws_button_controller_create(ctx, &bc);
246 	if (!bcs) {
247 		lwsl_err("%s: could not create buttons\n", __func__);
248 		return 1;
249 	}
250 
251 	lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user"));
252 
253 	/* ... bring up spi bb and the display */
254 
255 	lbspi.bb_ops.init(&lbspi.bb_ops);
256 	lws_display_state_init(&lds, ctx, 30000, 10000, lls, &disp.disp);
257 
258 	/*
259 	 * Make the RGB LED do something using sequenced PWM... pressing the
260 	 * GPIO14 button with single-presses advances the blue channel between
261 	 * different sequences
262 	 */
263 
264 	lws_led_transition(lls, "blue", &lws_pwmseq_sine_endless_fast,
265 					&lws_pwmseq_linear_wipe);
266 	lws_led_transition(lls, "green", &lws_pwmseq_sine_endless_slow,
267 					 &lws_pwmseq_linear_wipe);
268 	lws_led_transition(lls, "red", &lws_pwmseq_sine_endless_slow,
269 				       &lws_pwmseq_linear_wipe);
270 
271 	return 0;
272 }
273