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