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