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 22struct lws_led_state *lls; 23lws_display_state_t lds; 24struct lws_button_state *bcs; 25lws_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 38static const lws_button_map_t bcm[] = { 39 { 40 .gpio = GPIO_NUM_14, 41 .smd_interaction_name = "user" 42 }, 43}; 44 45static 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 57static 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 64static 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 74static 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 108static 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 119static 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 138static 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 160static const lws_settings_ops_t sett = { 161 lws_settings_ops_plat 162}; 163 164/* 165 * Wifi 166 */ 167 168static const lws_netdev_ops_t wifi_ops = { 169 lws_netdev_wifi_plat_ops 170}; 171 172int 173init_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