1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * devices for ESP32 Heltec WB32 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 * Hook up bitbang i2c, display driver and display 29d4afb5ceSopenharmony_ci */ 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_cistatic void 32d4afb5ceSopenharmony_ciesp32_i2c_delay(void) 33d4afb5ceSopenharmony_ci{ 34d4afb5ceSopenharmony_ci volatile int n = 0; 35d4afb5ceSopenharmony_ci 36d4afb5ceSopenharmony_ci while (n < 20) 37d4afb5ceSopenharmony_ci n++; 38d4afb5ceSopenharmony_ci} 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_cistatic const lws_bb_i2c_t li2c = { 41d4afb5ceSopenharmony_ci .bb_ops = lws_bb_i2c_ops, 42d4afb5ceSopenharmony_ci .scl = GPIO_NUM_15, 43d4afb5ceSopenharmony_ci .sda = GPIO_NUM_4, 44d4afb5ceSopenharmony_ci .gpio = &lws_gpio_plat, 45d4afb5ceSopenharmony_ci .delay = esp32_i2c_delay 46d4afb5ceSopenharmony_ci}; 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci/* 49d4afb5ceSopenharmony_ci * Button controller 50d4afb5ceSopenharmony_ci */ 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_cistatic const lws_button_map_t bcm[] = { 53d4afb5ceSopenharmony_ci { 54d4afb5ceSopenharmony_ci .gpio = GPIO_NUM_0, 55d4afb5ceSopenharmony_ci .smd_interaction_name = "user" 56d4afb5ceSopenharmony_ci }, 57d4afb5ceSopenharmony_ci}; 58d4afb5ceSopenharmony_ci 59d4afb5ceSopenharmony_cistatic const lws_button_controller_t bc = { 60d4afb5ceSopenharmony_ci .smd_bc_name = "bc", 61d4afb5ceSopenharmony_ci .gpio_ops = &lws_gpio_plat, 62d4afb5ceSopenharmony_ci .button_map = &bcm[0], 63d4afb5ceSopenharmony_ci .active_state_bitmap = 0, 64d4afb5ceSopenharmony_ci .count_buttons = LWS_ARRAY_SIZE(bcm), 65d4afb5ceSopenharmony_ci}; 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci/* 68d4afb5ceSopenharmony_ci * pwm controller 69d4afb5ceSopenharmony_ci */ 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_cistatic const lws_pwm_map_t pwm_map[] = { 72d4afb5ceSopenharmony_ci { .gpio = GPIO_NUM_25, .index = 0, .active_level = 1 } 73d4afb5ceSopenharmony_ci}; 74d4afb5ceSopenharmony_ci 75d4afb5ceSopenharmony_cistatic const lws_pwm_ops_t pwm_ops = { 76d4afb5ceSopenharmony_ci lws_pwm_plat_ops, 77d4afb5ceSopenharmony_ci .pwm_map = &pwm_map[0], 78d4afb5ceSopenharmony_ci .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) 79d4afb5ceSopenharmony_ci}; 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_cistatic const lws_display_ssd1306_t disp = { 82d4afb5ceSopenharmony_ci .disp = { 83d4afb5ceSopenharmony_ci lws_display_ssd1306_ops, 84d4afb5ceSopenharmony_ci .w = 128, 85d4afb5ceSopenharmony_ci .h = 64 86d4afb5ceSopenharmony_ci }, 87d4afb5ceSopenharmony_ci .i2c = (lws_i2c_ops_t *)&li2c, 88d4afb5ceSopenharmony_ci .gpio = &lws_gpio_plat, 89d4afb5ceSopenharmony_ci .reset_gpio = GPIO_NUM_16, 90d4afb5ceSopenharmony_ci .i2c7_address = SSD1306_I2C7_ADS1 91d4afb5ceSopenharmony_ci}; 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci/* 94d4afb5ceSopenharmony_ci * led controller 95d4afb5ceSopenharmony_ci */ 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_cistatic const lws_led_gpio_map_t lgm[] = { 98d4afb5ceSopenharmony_ci { 99d4afb5ceSopenharmony_ci .name = "alert", 100d4afb5ceSopenharmony_ci .gpio = GPIO_NUM_25, 101d4afb5ceSopenharmony_ci .pwm_ops = &pwm_ops, /* managed by pwm */ 102d4afb5ceSopenharmony_ci .active_level = 1, 103d4afb5ceSopenharmony_ci }, 104d4afb5ceSopenharmony_ci}; 105d4afb5ceSopenharmony_ci 106d4afb5ceSopenharmony_cistatic const lws_led_gpio_controller_t lgc = { 107d4afb5ceSopenharmony_ci .led_ops = lws_led_gpio_ops, 108d4afb5ceSopenharmony_ci .gpio_ops = &lws_gpio_plat, 109d4afb5ceSopenharmony_ci .led_map = &lgm[0], 110d4afb5ceSopenharmony_ci .count_leds = LWS_ARRAY_SIZE(lgm) 111d4afb5ceSopenharmony_ci}; 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci/* 114d4afb5ceSopenharmony_ci * Settings stored in platform nv 115d4afb5ceSopenharmony_ci */ 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_cistatic const lws_settings_ops_t sett = { 118d4afb5ceSopenharmony_ci lws_settings_ops_plat 119d4afb5ceSopenharmony_ci}; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci/* 122d4afb5ceSopenharmony_ci * Wifi 123d4afb5ceSopenharmony_ci */ 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_cistatic const lws_netdev_ops_t wifi_ops = { 126d4afb5ceSopenharmony_ci lws_netdev_wifi_plat_ops 127d4afb5ceSopenharmony_ci}; 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ciint 130d4afb5ceSopenharmony_ciinit_plat_devices(struct lws_context *ctx) 131d4afb5ceSopenharmony_ci{ 132d4afb5ceSopenharmony_ci lws_settings_instance_t *si; 133d4afb5ceSopenharmony_ci lws_netdevs_t *netdevs = lws_netdevs_from_ctx(ctx); 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci si = lws_settings_init(&sett, (void *)"nvs"); 136d4afb5ceSopenharmony_ci if (!si) { 137d4afb5ceSopenharmony_ci lwsl_err("%s: failed to create settings instance\n", __func__); 138d4afb5ceSopenharmony_ci return 1; 139d4afb5ceSopenharmony_ci } 140d4afb5ceSopenharmony_ci netdevs->si = si; 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci#if 0 143d4afb5ceSopenharmony_ci /* 144d4afb5ceSopenharmony_ci * This is a temp hack to bootstrap the settings to contain the test 145d4afb5ceSopenharmony_ci * AP ssid and passphrase for one time, so the settings can be stored 146d4afb5ceSopenharmony_ci * while there's no UI atm 147d4afb5ceSopenharmony_ci */ 148d4afb5ceSopenharmony_ci { 149d4afb5ceSopenharmony_ci lws_wifi_creds_t creds; 150d4afb5ceSopenharmony_ci 151d4afb5ceSopenharmony_ci memset(&creds, 0, sizeof(creds)); 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); 154d4afb5ceSopenharmony_ci lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); 155d4afb5ceSopenharmony_ci lws_dll2_add_tail(&creds.list, &netdevs->owner_creds); 156d4afb5ceSopenharmony_ci 157d4afb5ceSopenharmony_ci if (lws_netdev_credentials_settings_set(netdevs)) { 158d4afb5ceSopenharmony_ci lwsl_err("%s: failed to write bootstrap creds\n", 159d4afb5ceSopenharmony_ci __func__); 160d4afb5ceSopenharmony_ci return 1; 161d4afb5ceSopenharmony_ci } 162d4afb5ceSopenharmony_ci } 163d4afb5ceSopenharmony_ci#endif 164d4afb5ceSopenharmony_ci 165d4afb5ceSopenharmony_ci /* create the wifi network device and configure it */ 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci wnd = (lws_netdev_instance_wifi_t *) 168d4afb5ceSopenharmony_ci wifi_ops.create(ctx, &wifi_ops, "wl0", NULL); 169d4afb5ceSopenharmony_ci if (!wnd) { 170d4afb5ceSopenharmony_ci lwsl_err("%s: failed to create wifi object\n", __func__); 171d4afb5ceSopenharmony_ci return 1; 172d4afb5ceSopenharmony_ci } 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci wnd->flags |= LNDIW_MODE_STA; 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci if (wifi_ops.configure(&wnd->inst, NULL)) { 177d4afb5ceSopenharmony_ci lwsl_err("%s: failed to configure wifi object\n", __func__); 178d4afb5ceSopenharmony_ci return 1; 179d4afb5ceSopenharmony_ci } 180d4afb5ceSopenharmony_ci 181d4afb5ceSopenharmony_ci wifi_ops.up(&wnd->inst); 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci lls = lgc.led_ops.create(&lgc.led_ops); 184d4afb5ceSopenharmony_ci if (!lls) { 185d4afb5ceSopenharmony_ci lwsl_err("%s: could not create led\n", __func__); 186d4afb5ceSopenharmony_ci return 1; 187d4afb5ceSopenharmony_ci } 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci /* pwm init must go after the led controller init */ 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci pwm_ops.init(&pwm_ops); 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci bcs = lws_button_controller_create(ctx, &bc); 194d4afb5ceSopenharmony_ci if (!bcs) { 195d4afb5ceSopenharmony_ci lwsl_err("%s: could not create buttons\n", __func__); 196d4afb5ceSopenharmony_ci return 1; 197d4afb5ceSopenharmony_ci } 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci /* 200d4afb5ceSopenharmony_ci * Show the lws logo on the display 201d4afb5ceSopenharmony_ci */ 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci lws_display_state_init(&lds, ctx, 10000, 20000, lls, &disp.disp); 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); 206d4afb5ceSopenharmony_ci lws_led_transition(lls, "alert", &lws_pwmseq_static_off, 207d4afb5ceSopenharmony_ci &lws_pwmseq_static_on); 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci return 0; 210d4afb5ceSopenharmony_ci} 211