Merge branch 'master' into master

This commit is contained in:
Florian Eich 2017-10-13 15:31:07 +02:00 committed by GitHub
commit 2a0150cbbb
191 changed files with 11189 additions and 11970 deletions

View file

@ -152,7 +152,7 @@ bool bmp180_measure(i2c_dev_t *dev, bmp180_constants_t *c, int32_t *temperature,
if (!temperature && !pressure)
return false;
// Temperature is always needed, allso required for pressure only.
// Temperature is always needed, also required for pressure only.
//
// Calculation taken from BMP180 Datasheet
int32_t UT, X1, X2, B5;

View file

@ -14,18 +14,28 @@
* BSD Licensed as described in the file LICENSE
*/
#include <string.h>
#include <strings.h>
#include <FreeRTOS.h>
#include <task.h>
#include <lwip/netif.h>
#include <lwip/api.h>
#include "esplibs/libmain.h"
#if (DHCP_DEBUG == LWIP_DBG_ON)
#define debug(s, ...) printf("%s: " s "\n", "DHCP", ## __VA_ARGS__)
#else
#define debug(s, ...)
#endif
/* Grow the size of the lwip dhcp_msg struct's options field, as LWIP
defaults to a 68 octet options field for its DHCP client, and most
full-sized clients send us more than this. */
#define DHCP_OPTIONS_LEN 312
#include <lwip/dhcp.h>
#include <lwip/ip.h>
#include <lwip/prot/dhcp.h>
#include <lwip/prot/iana.h>
_Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 312, "dhcp_msg_t should have extended options size");
@ -35,15 +45,20 @@ _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 3
typedef struct {
uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
uint8_t active;
uint32_t expires;
} dhcp_lease_t;
typedef struct {
struct netconn *nc;
uint8_t max_leases;
ip_addr_t first_client_addr;
ip4_addr_t first_client_addr;
struct netif *server_if;
dhcp_lease_t *leases; /* length max_leases */
/* Optional router */
ip4_addr_t router;
/* Optional DNS server */
ip4_addr_t dns;
} server_state_t;
/* Only one DHCP server task can run at once, so we have global state
@ -68,39 +83,54 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr);
/* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */
inline static void sprintf_ipaddr(const ip_addr_t *addr, char *dest)
inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest)
{
if(addr == NULL)
if (addr == NULL)
sprintf(dest, "NULL");
else
sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr),
ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr));
}
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases)
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases)
{
/* Stop any existing running dhcpserver */
if(dhcpserver_task_handle)
if (dhcpserver_task_handle)
dhcpserver_stop();
state = malloc(sizeof(server_state_t));
state->max_leases = max_leases;
state->leases = calloc(max_leases, sizeof(dhcp_lease_t));
bzero(state->leases, max_leases * sizeof(dhcp_lease_t));
// state->server_if is assigned once the task is running - see comment in dhcpserver_task()
ip_addr_copy(state->first_client_addr, *first_client_addr);
ip4_addr_copy(state->first_client_addr, *first_client_addr);
xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle);
/* Clear options */
ip4_addr_set_zero(&state->router);
ip4_addr_set_zero(&state->dns);
xTaskCreate(dhcpserver_task, "DHCP Server", 448, NULL, 2, &dhcpserver_task_handle);
}
void dhcpserver_stop(void)
{
if(dhcpserver_task_handle) {
if (dhcpserver_task_handle) {
vTaskDelete(dhcpserver_task_handle);
free(state);
dhcpserver_task_handle = NULL;
}
}
void dhcpserver_set_router(const ip4_addr_t *router)
{
ip4_addr_copy(state->router, *router);
}
void dhcpserver_set_dns(const ip4_addr_t *dns)
{
ip4_addr_copy(state->dns, *dns);
}
static void dhcpserver_task(void *pxParameter)
{
/* netif_list isn't assigned until after user_init completes, which is why we do it inside the task */
@ -108,11 +138,12 @@ static void dhcpserver_task(void *pxParameter)
state->nc = netconn_new (NETCONN_UDP);
if(!state->nc) {
printf("DHCP Server Error: Failed to allocate socket.\r\n");
debug("DHCP Server Error: Failed to allocate socket.");
return;
}
netconn_bind(state->nc, IP_ADDR_ANY, DHCP_SERVER_PORT);
netconn_bind(state->nc, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_SERVER);
netconn_bind_if (state->nc, netif_get_index(state->server_if));
while(1)
{
@ -122,29 +153,32 @@ static void dhcpserver_task(void *pxParameter)
/* Receive a DHCP packet */
err_t err = netconn_recv(state->nc, &netbuf);
if(err != ERR_OK) {
printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err);
debug("DHCP Server Error: Failed to receive DHCP packet. err=%d", err);
continue;
}
/* expire any leases that have passed */
uint32_t now = xTaskGetTickCount();
for(int i = 0; i < state->max_leases; i++) {
uint32_t expires = state->leases[i].expires;
if(expires && expires < now)
state->leases[i].expires = 0;
for (int i = 0; i < state->max_leases; i++) {
if (state->leases[i].active) {
uint32_t expires = state->leases[i].expires - now;
if (expires >= 0x80000000) {
state->leases[i].active = 0;
}
}
}
ip_addr_t received_ip;
u16_t port;
netconn_addr(state->nc, &received_ip, &port);
if(netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
if (netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
/* too short to be a valid DHCP client message */
netbuf_delete(netbuf);
continue;
}
if(netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
printf("DHCP Server Warning: Client sent more options than we know how to parse. len=%d\r\n", netbuf_len(netbuf));
debug("DHCP Server Warning: Client sent more options than we know how to parse. len=%d", netbuf_len(netbuf));
}
netbuf_copy(netbuf, &received, sizeof(struct dhcp_msg));
@ -153,18 +187,19 @@ static void dhcpserver_task(void *pxParameter)
uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE,
DHCP_OPTION_MESSAGE_TYPE_LEN, NULL);
if(!message_type) {
printf("DHCP Server Error: No message type field found");
debug("DHCP Server Error: No message type field found");
continue;
}
printf("State dump. Message type %d\n", *message_type);
#if (DHCP_DEBUG == LWIP_DBG_ON)
debug("State dump. Message type %d", *message_type);
for(int i = 0; i < state->max_leases; i++) {
dhcp_lease_t *lease = &state->leases[i];
printf("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, lease->expires, lease->hwaddr[0],
debug("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x", i, lease->expires, lease->hwaddr[0],
lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
lease->hwaddr[5]);
}
#endif
switch(*message_type) {
case DHCP_DISCOVER:
@ -175,8 +210,9 @@ static void dhcpserver_task(void *pxParameter)
break;
case DHCP_RELEASE:
handle_dhcp_release(&received);
break;
default:
printf("DHCP Server Error: Unsupported message type %d\r\n", *message_type);
debug("DHCP Server Error: Unsupported message type %d", *message_type);
break;
}
}
@ -184,14 +220,14 @@ static void dhcpserver_task(void *pxParameter)
static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
{
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
return;
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
return;
dhcp_lease_t *freelease = find_lease_slot(dhcpmsg->chaddr);
if(!freelease) {
printf("DHCP Server: All leases taken.\r\n");
debug("DHCP Server: All leases taken.");
return; /* Nothing available, so do nothing */
}
@ -199,13 +235,19 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
dhcpmsg->op = DHCP_BOOTREPLY;
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
ip_addr_copy(dhcpmsg->yiaddr, state->first_client_addr);
ip4_addr4(&(dhcpmsg->yiaddr)) += (freelease - state->leases);
dhcpmsg->yiaddr.addr = lwip_htonl(lwip_ntohl(state->first_client_addr.addr) + (freelease - state->leases));
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
if (!ip4_addr_isany_val(state->router)) {
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
}
if (!ip4_addr_isany_val(state->dns)) {
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
}
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
struct netbuf *netbuf = netbuf_new();
@ -218,60 +260,64 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
{
static char ipbuf[16];
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
return;
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
return;
ip_addr_t requested_ip;
ip4_addr_t requested_ip;
uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL);
if(requested_ip_opt) {
memcpy(&requested_ip.addr, requested_ip_opt, 4);
} else if(ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) {
ip_addr_copy(requested_ip, dhcpmsg->ciaddr);
if (requested_ip_opt) {
memcpy(&requested_ip.addr, requested_ip_opt, 4);
} else if (ip4_addr_cmp(&requested_ip, IP4_ADDR_ANY4)) {
ip4_addr_copy(requested_ip, dhcpmsg->ciaddr);
} else {
printf("DHCP Server Error: No requested IP\r\n");
debug("DHCP Server Error: No requested IP");
send_dhcp_nak(dhcpmsg);
return;
}
/* Test the first 4 octets match */
if(ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|| ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr)
|| ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) {
sprintf_ipaddr(&requested_ip, ipbuf);
printf("DHCP Server Error: %s not an allowed IP\r\n", ipbuf);
debug("DHCP Server Error: %s not an allowed IP", ipbuf);
send_dhcp_nak(dhcpmsg);
return;
}
/* Test the last octet is in the MAXCLIENTS range */
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr);
if(octet_offs < 0 || octet_offs >= state->max_leases) {
printf("DHCP Server Error: Address out of range\r\n");
debug("DHCP Server Error: Address out of range");
send_dhcp_nak(dhcpmsg);
return;
}
dhcp_lease_t *requested_lease = state->leases + octet_offs;
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
{
printf("DHCP Server Error: Lease for address already taken\r\n");
debug("DHCP Server Error: Lease for address already taken");
send_dhcp_nak(dhcpmsg);
return;
}
memcpy(requested_lease->hwaddr, dhcpmsg->chaddr, dhcpmsg->hlen);
sprintf_ipaddr(&requested_ip, ipbuf);
printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
debug("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x", ipbuf, requested_lease->hwaddr[0],
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
requested_lease->hwaddr[5]);
requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
uint32_t now = xTaskGetTickCount();
requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
requested_lease->active = 1;
sdk_wifi_softap_set_station_info(requested_lease->hwaddr, &requested_ip);
/* Reuse the REQUEST message as the ACK message */
dhcpmsg->op = DHCP_BOOTREPLY;
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
ip_addr_copy(dhcpmsg->yiaddr, requested_ip);
ip4_addr_copy(dhcpmsg->yiaddr, requested_ip);
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK);
@ -279,6 +325,13 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
if (!ip4_addr_isany_val(state->router)) {
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
}
if (!ip4_addr_isany_val(state->dns)) {
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
}
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
struct netbuf *netbuf = netbuf_new();
@ -291,7 +344,8 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
static void handle_dhcp_release(struct dhcp_msg *dhcpmsg)
{
dhcp_lease_t *lease = find_lease_slot(dhcpmsg->chaddr);
if(lease) {
if (lease) {
lease->active = 0;
lease->expires = 0;
}
}
@ -319,17 +373,17 @@ static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8
uint8_t *start = (uint8_t *)&msg->options;
uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg);
for(uint8_t *p = start; p < msg_end-2;) {
for (uint8_t *p = start; p < msg_end-2;) {
uint8_t type = *p++;
uint8_t len = *p++;
if(type == DHCP_OPTION_END)
if (type == DHCP_OPTION_END)
return NULL;
if(p+len >= msg_end)
if (p+len >= msg_end)
break; /* We've overrun our valid DHCP message size, or this isn't a valid option */
if(type == option_num) {
if(len < min_length)
if (type == option_num) {
if (len < min_length)
break;
if(length)
if (length)
*length = len;
return p; /* start of actual option data */
}
@ -349,7 +403,7 @@ static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value)
static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len)
{
*opt++ = type;
if(len) {
if (len) {
*opt++ = len;
memcpy(opt, value, len);
}
@ -360,8 +414,8 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr)
{
dhcp_lease_t *empty_lease = NULL;
for(int i = 0; i < state->max_leases; i++) {
if(state->leases[i].expires == 0 && !empty_lease)
for (int i = 0; i < state->max_leases; i++) {
if (!state->leases[i].active && !empty_lease)
empty_lease = &state->leases[i];
else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
return &state->leases[i];

View file

@ -26,14 +26,20 @@ extern "C" {
to a client. Subsequent lease addresses are calculated by
incrementing the final octet of the IPv4 address, up to max_leases.
*/
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases);
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases);
void dhcpserver_get_lease(const ip_addr_t *first_client_addr, uint8_t max_leases);
void dhcpserver_get_lease(const ip4_addr_t *first_client_addr, uint8_t max_leases);
/* Stop DHCP server.
*/
void dhcpserver_stop(void);
/* Set a router address to send as an option. */
void dhcpserver_set_router(const ip4_addr_t *router);
/* Set a DNS address to send as an option. */
void dhcpserver_set_dns(const ip4_addr_t *dns);
#ifdef __cplusplus
}
#endif

View file

@ -15,13 +15,13 @@
/* Convert normal decimal to binary coded decimal */
static inline uint8_t decToBcd(uint8_t dec)
{
return(((dec / 10) * 16) + (dec % 10));
return (dec / 10) * 16 + dec % 10;
}
/* Convert binary coded decimal to normal decimal */
static inline uint8_t bcdToDec(uint8_t bcd)
{
return(((bcd / 16) * 10) + (bcd % 16));
return (bcd / 16) * 10 + bcd % 16;
}
/* Send a number of bytes to the rtc over i2c
@ -48,6 +48,8 @@ int ds3231_setTime(i2c_dev_t *dev, struct tm *time)
data[0] = decToBcd(time->tm_sec);
data[1] = decToBcd(time->tm_min);
data[2] = decToBcd(time->tm_hour);
/* The week data must be in the range 1 to 7, and to keep the start on the
* same day as for tm_wday have it start at 1 on Sunday. */
data[3] = decToBcd(time->tm_wday + 1);
data[4] = decToBcd(time->tm_mday);
data[5] = decToBcd(time->tm_mon + 1);

View file

@ -139,7 +139,7 @@
/** Set this to 1 on platforms where strnstr is not available */
#ifndef LWIP_HTTPD_STRNSTR_PRIVATE
#define LWIP_HTTPD_STRNSTR_PRIVATE 1
#define LWIP_HTTPD_STRNSTR_PRIVATE 0
#endif
/** Set this to one to show error pages when parsing a request fails instead
@ -2675,7 +2675,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
* Initialize the httpd with the specified local address.
*/
static void
httpd_init_addr(ip_addr_t *local_addr)
httpd_init_addr(const ip_addr_t *local_addr)
{
struct tcp_pcb *pcb;
err_t err;

View file

@ -2,11 +2,12 @@
This time a driver for the excellent esp-open-rtos. This is a bit banging I2C driver based on the Wikipedia pesudo C code [1].
### Usage
### Basic usage
````
```C
#include <i2c.h>
#define BUS (0)
#define SCL_PIN (0)
#define SDA_PIN (2)
@ -14,19 +15,19 @@ uint8_t slave_addr = 0x20;
uint8_t reg_addr = 0x1f;
uint8_t reg_data;
i2c_init(SCL_PIN, SDA_PIN);
i2c_init(BUS, SCL_PIN, SDA_PIN, I2C_FREQ_400K);
// Write 1 byte to slave register
int err = i2c_slave_write(slave_addr, &reg_addr, &data, 1);
int err = i2c_slave_write(BUS, slave_addr, &reg_addr, &data, 1);
if (err != 0)
{
// do something with error
}
// Issue write to slave, sending reg_addr, followed by reading 1 byte
err = i2c_slave_read(slave_addr, &reg_addr, &reg_data, 1);
err = i2c_slave_read(BUS, slave_addr, &reg_addr, &reg_data, 1);
````
```
For details please see `extras/i2c/i2c.h`.

View file

@ -22,10 +22,13 @@
* THE SOFTWARE.
*/
#include "i2c.h"
#include <esp8266.h>
#include <espressif/esp_misc.h> // sdk_os_delay_us
#include <espressif/esp_system.h>
#include "i2c.h"
#include <FreeRTOS.h>
#include <task.h>
//#define I2C_DEBUG true
@ -37,7 +40,28 @@
#define CLK_STRETCH (10)
static uint8_t freq ; // Store CPU frequency for optimisation speed in delay function ( Warning: Don't change CPU frequency during a transaction)
// Following array contain delay values for different frequencies
// Warning: 1 is minimal, that mean at 80MHz clock, frequency max is 320kHz
const static uint8_t i2c_freq_array[][2] = {
[I2C_FREQ_80K] = {255, 35},
[I2C_FREQ_100K] = {100, 20},
[I2C_FREQ_400K] = {10, 1},
[I2C_FREQ_500K] = {6, 1}
};
static uint8_t freq; // Store CPU frequency for optimisation speed in delay function (Warning: Don't change CPU frequency during a transaction)
// Bus settings
typedef struct i2c_bus_description
{
uint8_t g_scl_pin; // SCL pin
uint8_t g_sda_pin; // SDA pin
i2c_freq_t frequency; // Frequency
bool started;
bool flag;
bool force;
} i2c_bus_description_t;
static i2c_bus_description_t i2c_bus[MAX_I2C_BUS];
inline bool i2c_status(uint8_t bus)
@ -48,10 +72,10 @@ inline bool i2c_status(uint8_t bus)
void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq)
{
i2c_bus[bus].started = false;
i2c_bus[bus].flag = false ;
i2c_bus[bus].flag = false;
i2c_bus[bus].g_scl_pin = scl_pin;
i2c_bus[bus].g_sda_pin = sda_pin;
i2c_bus[bus].frequency = freq ;
i2c_bus[bus].frequency = freq;
// Just to prevent these pins floating too much if not connected.
gpio_set_pullup(i2c_bus[bus].g_scl_pin, 1, 1);
@ -73,7 +97,7 @@ void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq)
void i2c_frequency(uint8_t bus, i2c_freq_t freq)
{
i2c_bus[bus].frequency = freq ;
i2c_bus[bus].frequency = freq;
}
static inline void i2c_delay(uint8_t bus)
@ -136,13 +160,14 @@ void i2c_start(uint8_t bus)
(void) read_sda(bus);
i2c_delay(bus);
uint32_t clk_stretch = CLK_STRETCH;
while (read_scl(bus) == 0 && clk_stretch--) ;
while (read_scl(bus) == 0 && clk_stretch--)
;
// Repeated start setup time, minimum 4.7us
i2c_delay(bus);
}
i2c_bus[bus].started = true;
if (read_sda(bus) == 0) {
debug("arbitration lost in i2c_start from bus %u",bus);
debug("arbitration lost in i2c_start from bus %u", bus);
}
// SCL is high, set SDA from 1 to 0.
clear_sda(bus);
@ -158,17 +183,18 @@ bool i2c_stop(uint8_t bus)
clear_sda(bus);
i2c_delay(bus);
// Clock stretching
while (read_scl(bus) == 0 && clk_stretch--) ;
while (read_scl(bus) == 0 && clk_stretch--)
;
// Stop bit setup time, minimum 4us
i2c_delay(bus);
// SCL is high, set SDA from 0 to 1
if (read_sda(bus) == 0) {
debug("arbitration lost in i2c_stop from bus %u",bus);
debug("arbitration lost in i2c_stop from bus %u", bus);
}
i2c_delay(bus);
if (!i2c_bus[bus].started) {
debug("bus %u link was break!",bus);
return false ; //If bus was stop in other way, the current transmission Failed
debug("bus %u link was break!", bus);
return false; // If bus was stop in other way, the current transmission Failed
}
i2c_bus[bus].started = false;
return true;
@ -185,11 +211,12 @@ static void i2c_write_bit(uint8_t bus, bool bit)
}
i2c_delay(bus);
// Clock stretching
while (read_scl(bus) == 0 && clk_stretch--) ;
while (read_scl(bus) == 0 && clk_stretch--)
;
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
if (bit && read_sda(bus) == 0) {
debug("arbitration lost in i2c_write_bit from bus %u",bus);
debug("arbitration lost in i2c_write_bit from bus %u", bus);
}
i2c_delay(bus);
clear_scl(bus);
@ -204,7 +231,8 @@ static bool i2c_read_bit(uint8_t bus)
(void) read_sda(bus);
i2c_delay(bus);
// Clock stretching
while (read_scl(bus) == 0 && clk_stretch--) ;
while (read_scl(bus) == 0 && clk_stretch--)
;
// SCL is high, now data is valid
bit = read_sda(bus);
i2c_delay(bus);
@ -217,7 +245,7 @@ bool i2c_write(uint8_t bus, uint8_t byte)
bool nack;
uint8_t bit;
for (bit = 0; bit < 8; bit++) {
i2c_write_bit(bus,(byte & 0x80) != 0);
i2c_write_bit(bus, (byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit(bus);
@ -231,22 +259,22 @@ uint8_t i2c_read(uint8_t bus, bool ack)
for (bit = 0; bit < 8; bit++) {
byte = ((byte << 1)) | (i2c_read_bit(bus));
}
i2c_write_bit(bus,ack);
i2c_write_bit(bus, ack);
return byte;
}
void i2c_force_bus(uint8_t bus, bool state)
{
i2c_bus[bus].force = state ;
i2c_bus[bus].force = state;
}
static int i2c_bus_test(uint8_t bus)
{
taskENTER_CRITICAL(); // To prevent task swaping after checking flag and before set it!
bool status = i2c_bus[bus].flag ; // get current status
bool status = i2c_bus[bus].flag; // get current status
if(i2c_bus[bus].force)
{
i2c_bus[bus].flag = true ; // force bus on
i2c_bus[bus].flag = true; // force bus on
taskEXIT_CRITICAL();
if(status)
i2c_stop(bus); //Bus was busy, stop it.
@ -258,72 +286,72 @@ static int i2c_bus_test(uint8_t bus)
taskEXIT_CRITICAL();
debug("busy");
taskYIELD(); // If bus busy, change task to try finish last com.
return -EBUSY ; // If bus busy, inform user
return -EBUSY; // If bus busy, inform user
}
else
{
i2c_bus[bus].flag = true ; // Set Bus busy
i2c_bus[bus].flag = true; // Set Bus busy
taskEXIT_CRITICAL();
}
}
return 0 ;
return 0;
}
int i2c_slave_write(uint8_t bus, uint8_t slave_addr, const uint8_t *data, const uint8_t *buf, uint32_t len)
{
if(i2c_bus_test(bus))
return -EBUSY ;
return -EBUSY;
i2c_start(bus);
if (!i2c_write(bus, slave_addr << 1))
goto error;
if(data != NULL)
if (!i2c_write(bus,*data))
if (!i2c_write(bus, *data))
goto error;
while (len--) {
if (!i2c_write(bus,*buf++))
if (!i2c_write(bus, *buf++))
goto error;
}
if (!i2c_stop(bus))
goto error;
i2c_bus[bus].flag = false ; // Bus free
i2c_bus[bus].flag = false; // Bus free
return 0;
error:
debug("Bus %u Write Error",bus);
error:
debug("Bus %u Write Error", bus);
i2c_stop(bus);
i2c_bus[bus].flag = false ; // Bus free
i2c_bus[bus].flag = false; // Bus free
return -EIO;
}
int i2c_slave_read(uint8_t bus, uint8_t slave_addr, const uint8_t *data, uint8_t *buf, uint32_t len)
{
if(i2c_bus_test(bus))
return -EBUSY ;
return -EBUSY;
if(data != NULL) {
i2c_start(bus);
if (!i2c_write(bus,slave_addr << 1))
if (!i2c_write(bus, slave_addr << 1))
goto error;
if (!i2c_write(bus,*data))
if (!i2c_write(bus, *data))
goto error;
if (!i2c_stop(bus))
goto error;
}
i2c_start(bus);
if (!i2c_write(bus,slave_addr << 1 | 1)) // Slave address + read
if (!i2c_write(bus, slave_addr << 1 | 1)) // Slave address + read
goto error;
while(len) {
*buf = i2c_read(bus,len == 1);
*buf = i2c_read(bus, len == 1);
buf++;
len--;
}
if (!i2c_stop(bus))
goto error;
i2c_bus[bus].flag = false ; // Bus free
i2c_bus[bus].flag = false; // Bus free
return 0;
error:
error:
debug("Read Error");
i2c_stop(bus);
i2c_bus[bus].flag = false ; // Bus free
i2c_bus[bus].flag = false; // Bus free
return -EIO;
}

View file

@ -21,6 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* I2C driver for ESP8266 written for use with esp-open-rtos
* Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol
*/
#ifndef __I2C_H__
#define __I2C_H__
@ -28,62 +32,36 @@
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <FreeRTOS.h>
#include <task.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Define i2c bus max number
/**
* Define i2c bus max number
*/
#define MAX_I2C_BUS 2
#ifndef MAX_I2C_BUS
#define MAX_I2C_BUS 2
#endif
/*
* following array contain value for different frequency
* Warning : 1 is minimal, that mean at 80MHz clock, frequency max is 320kHz
* Array format is { {160MHz, 80MHz} , {160MHz, 80MHz} , ... }
*/
#define NB_FREQ_AVAILABLE 4
typedef enum {
I2C_FREQ_80K = 0,
I2C_FREQ_100K,
I2C_FREQ_400K,
I2C_FREQ_500K,
typedef enum
{
I2C_FREQ_80K = 0,//!< I2C_FREQ_80K
I2C_FREQ_100K, //!< I2C_FREQ_100K
I2C_FREQ_400K, //!< I2C_FREQ_400K
I2C_FREQ_500K, //!< I2C_FREQ_500K
} i2c_freq_t;
const static uint8_t i2c_freq_array[NB_FREQ_AVAILABLE][2] = { {255,35}, {100,20}, {10,1}, {6,1} } ;
/**
* Device descriptor
*/
typedef struct i2c_dev {
uint8_t bus ;
uint8_t addr ;
} i2c_dev_t ;
typedef struct i2c_dev
{
uint8_t bus;
uint8_t addr;
} i2c_dev_t;
/**
* Bus settings
*/
typedef struct i2c_bus_description {
uint8_t g_scl_pin; // Scl pin
uint8_t g_sda_pin; // Sda pin
uint8_t frequency; // frequency selection
bool started;
bool flag;
bool force;
} i2c_bus_description_t ;
// I2C driver for ESP8266 written for use with esp-open-rtos
// Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol
// With calling overhead, we end up at ~320kbit/s
//Level 0 API
/// Level 0 API
/**
* Init bitbanging I2C driver on given pins
@ -137,7 +115,7 @@ bool i2c_stop(uint8_t bus);
*/
bool i2c_status(uint8_t bus);
//Level 1 API (Don't need functions above)
/// Level 1 API (Don't need functions above)
/**
* This function will allow you to force a transmission I2C, cancel current transmission.

View file

@ -62,7 +62,7 @@ void sdk_rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id,
reg_add##_lsb, indata)
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins)
{
// reset DMA
SET_MASK_BITS(SLC.CONF0, SLC_CONF0_RX_LINK_RESET);
@ -83,7 +83,7 @@ void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
SLC_RX_DESCRIPTOR_CONF_RX_EOF_MODE | SLC_RX_DESCRIPTOR_CONF_RX_FILL_MODE);
if (isr) {
_xt_isr_attach(INUM_SLC, isr);
_xt_isr_attach(INUM_SLC, isr, arg);
SET_MASK_BITS(SLC.INT_ENABLE, SLC_INT_ENABLE_RX_EOF);
SLC.INT_CLEAR = 0xFFFFFFFF;
_xt_isr_unmask(1<<INUM_SLC);

View file

@ -32,7 +32,7 @@
extern "C" {
#endif
typedef void (*i2s_dma_isr_t)(void);
typedef void (*i2s_dma_isr_t)(void *);
typedef struct dma_descriptor {
uint32_t blocksize:12;
@ -61,10 +61,11 @@ typedef struct {
* Initialize I2S and DMA subsystems.
*
* @param isr ISR handler. Can be NULL if interrupt handling is not needed.
* @param arg ISR handler arg.
* @param clock_div I2S clock configuration.
* @param pins I2S pin configuration. Specifies which pins are enabled in I2S.
*/
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins);
void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins);
/**
* Calculate I2S dividers for the specified frequency.

View file

@ -43,7 +43,7 @@ typedef struct pwmInfoDefinition
static PWMInfo pwmInfo;
static void frc1_interrupt_handler(void)
static void frc1_interrupt_handler(void *arg)
{
uint8_t i = 0;
bool out = true;
@ -97,7 +97,7 @@ void pwm_init(uint8_t npins, const uint8_t* pins)
pwm_stop();
/* set up ISRs */
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
/* Flag not running */
pwmInfo.running = 0;

View file

@ -38,7 +38,7 @@
#include "sntp.h"
#include "lwip/timers.h"
#include "lwip/timeouts.h"
#include "lwip/udp.h"
#include "lwip/dns.h"
#include "lwip/ip_addr.h"
@ -136,12 +136,12 @@
#define SNTP_STARTUP_DELAY 0
#endif
/** SNTP receive timeout - in milliseconds
/** SNTP receive timeout - in seconds
* Also used as retry timeout - this shouldn't be too low.
* Default is 3 seconds.
*/
#ifndef SNTP_RECV_TIMEOUT
#define SNTP_RECV_TIMEOUT 3000
#define SNTP_RECV_TIMEOUT 3
#endif
/** SNTP update delay - in milliseconds
@ -384,8 +384,8 @@ sntp_request(void *arg)
/* bind to local address */
if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) {
/* set recv timeout */
timeout = SNTP_RECV_TIMEOUT;
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
const struct timeval timeout = { SNTP_RECV_TIMEOUT, 0 };
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
/* prepare SNTP request */
sntp_initialize_request(&sntpmsg);
@ -511,7 +511,7 @@ sntp_try_next_server(void* arg)
/** UDP recv callback for the sntp pcb */
static void
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
u8_t mode;
u8_t stratum;
@ -597,7 +597,7 @@ sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t
* @param server_addr resolved IP address of the SNTP server
*/
static void
sntp_send_request(ip_addr_t *server_addr)
sntp_send_request(const ip_addr_t *server_addr)
{
struct pbuf* p;
p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
@ -611,7 +611,7 @@ sntp_send_request(ip_addr_t *server_addr)
pbuf_free(p);
/* set up receive timeout: try next server or retry on timeout */
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
sys_timeout((u32_t)SNTP_RECV_TIMEOUT * 1000, sntp_try_next_server, NULL);
#if SNTP_CHECK_RESPONSE >= 1
/* save server address to verify it in sntp_recv */
ip_addr_set(&sntp_last_server_address, server_addr);
@ -629,7 +629,7 @@ sntp_send_request(ip_addr_t *server_addr)
* DNS found callback when using DNS names as server address.
*/
static void
sntp_dns_found(const char* hostname, ip_addr_t *ipaddr, void *arg)
sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
{
LWIP_UNUSED_ARG(hostname);
LWIP_UNUSED_ARG(arg);

View file

@ -102,7 +102,7 @@ void sntp_update_rtc(time_t t, uint32_t us) {
// DEBUG: Compute and print drift
int64_t sntp_current = sntp_base + TIMER_COUNT - tim_ref;
int64_t sntp_correct = (((uint64_t)us + (uint64_t)t * 1000000U)<<12) / cal;
printf("\nRTC Adjust: drift = %ld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), cal);
printf("\nRTC Adjust: drift = %lld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), (uint32_t)cal);
tim_ref = TIMER_COUNT;
cal = sdk_system_rtc_clock_cali_proc();

View file

@ -44,7 +44,7 @@ static SemaphoreHandle_t uart0_sem = NULL;
static bool inited = false;
static void uart0_rx_init(void);
IRAM void uart0_rx_handler(void)
IRAM void uart0_rx_handler(void *arg)
{
// TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively
if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
@ -97,7 +97,7 @@ static void uart0_rx_init(void)
int trig_lvl = 1;
uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0);
_xt_isr_attach(INUM_UART, uart0_rx_handler);
_xt_isr_attach(INUM_UART, uart0_rx_handler, NULL);
_xt_isr_unmask(1 << INUM_UART);
// reset the rx fifo

View file

@ -0,0 +1,10 @@
# Component makefile for extras/wificfg
# Expected anyone using wificfg includes it as 'wificfg/wificfg.h'
INC_DIRS += $(wificfg_ROOT)..
# args for passing into compile rule generation
wificfg_INC_DIR =
wificfg_SRC_DIR = $(wificfg_ROOT)
$(eval $(call component_compile_rules,wificfg))

View file

@ -0,0 +1,30 @@
"<!DOCTYPE html><html lang=\"en\">"
"<head>"
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
"<script src=\"/script.js\"></script>"
"<title>",
"</title>"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"</head>"
"<body>"
"<ul class=\"topnav\" id=\"myTopnav\">"
"<li><a href=\"/\">Home</a></li>"
"<li class=\"active\"><a href=\"/wificfg/\">WiFi Config</a></li>"
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
"<li class=\"icon\">"
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">&#9776;</a>"
"</li>"
"</ul>"
"<form action=\"/challenge.html\" method=\"post\">"
"<fieldset>"
"<legend>Unlock the configuration interface</legend>"
"<dl class=\"dlh\">"
"<dt><label for=\"pw\">Password</label></dt>"
"<dd><input id=\"pw\" type=\"text\" maxlength=\"32\" name=\"cfg_password\" "
"placeholder=\"unlock-password\" value=\"\"></dd>"
"</dl>"
"<center><input type=\"submit\" value=\"Unlock\"></center>"
"</fieldset>"
"</form>"
"</body></html>"

View file

@ -0,0 +1,11 @@
"HTTP/1.1 200 \r\n"
"Content-Type: image/svg+xml\r\n"
"Cache-Control: max-age=900\r\n"
"Transfer-Encoding: chunked\r\n"
"Connection: close\r\n"
"\r\n",
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
"<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" version=\"1.1\">"
"<defs><linearGradient id=\"g1\" y2=\"248.63\" gradientUnits=\"userSpaceOnUse\" x2=\"153\" gradientTransform=\"matrix(.20068 0 0 .20068 -54.336 -1.0508)\" y1=\"15.424\" x1=\"99.777\"><stop style=\"stop-color:#0088FF\" offset=\"0\"/><stop style=\"stop-color:#b2dbff\" offset=\"1\"/></linearGradient></defs>"
"<path style=\"stroke-linejoin:round;color:#000000;stroke:#aaaaaa;stroke-linecap:round;fill:url(#g1)\" d=\"m22.7 0.94747c-0.474 0.03238-0.934 0.10563-1.398 0.15883h-0.032l-1.112 6.068c-1.812 0.4127-3.517 1.1132-5.051 2.065l-4.988-3.59c-1.3485 1.0468-2.5754 2.2677-3.6536 3.59l3.4628 5.0517c-1.0514 1.606-1.842 3.441-2.2874 5.369v0.031l-6.0361 0.953c-0.1104 0.902-0.1589 1.833-0.1589 2.764 0 0.762 0.021 1.514 0.0953 2.256l6.0362 1.08c0.4293 2.096 1.2448 4.054 2.3827 5.782l-3.5899 4.924c1.0281 1.277 2.2151 2.439 3.4946 3.463l5.0833-3.494c1.776 1.133 3.759 1.928 5.909 2.319l0.953 6.004c0.677 0.062 1.372 0.064 2.065 0.064 0.979 0 1.914-0.037 2.859-0.159l1.144-6.132c2.041-0.507 3.958-1.389 5.623-2.573l4.893 3.558c1.268-1.079 2.429-2.32 3.431-3.653l-3.558-5.147c0.963-1.664 1.631-3.5 1.969-5.464l6.005-0.953c0.052-0.627 0.063-1.234 0.063-1.875 0-1.112-0.129-2.203-0.286-3.272l-6.099-1.112c-0.478-1.765-1.263-3.412-2.256-4.892l3.59-4.9245c-1.113-1.3608-2.382-2.618-3.781-3.6852l-5.178 3.5581c-1.488-0.8802-3.09-1.5556-4.829-1.9379l-0.953-6.0362c-0.868-0.102-1.742-0.15883-2.637-0.15883-0.242 0-0.491-0.00761-0.731 0-0.117 0.00371-0.232-0.00681-0.349 0-0.032 0.00184-0.064-0.00216-0.095 0zm0.826 15.44c0.116-0.006 0.231 0 0.349 0 3.761 0 6.83 3.07 6.83 6.831 0 3.76-3.069 6.798-6.83 6.798s-6.799-3.038-6.799-6.798c0-3.643 2.852-6.648 6.45-6.831z\"/>"
"</svg>"

View file

@ -0,0 +1,8 @@
"HTTP/1.1 200 \r\n"
"Content-Type: text/javascript\r\n"
"Cache-Control: max-age=900\r\n"
"Transfer-Encoding: chunked\r\n"
"Connection: close\r\n"
"\r\n",
"function myFunction() { var x = document.getElementById(\"myTopnav\");"
"if (x.className === \"topnav\") { x.className += \" responsive\"; } else { x.className = \"topnav\"; } }"

View file

@ -0,0 +1,19 @@
"HTTP/1.1 200 \r\n"
"Content-Type: text/css\r\n"
"Cache-Control: max-age=900\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n",
".dlh dd,h1{font-weight:300}.dlh{font-size:0;text-align:center}"
".dlh dd,.dlh dt{width:48%;width:calc(50% - 10px);margin:8px 0;display:inline-block;font-size:16px;vertical-align:middle}"
".dlh dt{text-align:right;padding-right:10px}"
".dlh dd{font-size:18px;text-align:left;padding-left:10px}"
"ul.topnav{list-style-type:none;margin:0;padding:0;overflow:hidden;background-color:#bbb}"
"ul.topnav li{float:left}"
"ul.topnav li a{display:inline-block;color:#444;text-align:center;padding:14px 16px;text-decoration:none;transition:.3s;font-size:17px}"
"ul.topnav li a:hover{background-color:#ddd}ul.topnav li.icon{display:none}"
"@media screen and (max-width:680px){ul.topnav li:not(.active){display:none}ul.topnav li.icon{float:right;display:inline-block}ul.topnav.responsive{position:relative}ul.topnav.responsive li.icon{position:absolute;right:0;top:0}ul.topnav.responsive li{float:none;display:inline}ul.topnav.responsive li a{display:block;text-align:left}}"
"html{min-height:100%}"
"body{background:#d0e4f7;background:-moz-linear-gradient(top, #d0e4f7 0%, #73b1e7 24%, #0a77d5 50%, #539fe1 79%, #87bcea 100%);background:-webkit-linear-gradient(top, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);background:linear-gradient(to bottom, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d0e4f7', endColorstr='#87bcea',GradientType=0)}"
"body{font-family:helvetica,arial,sans-serif;font-size:16px}"
"h1{font-size:26px}"
"p{font-size:14px}"

View file

@ -0,0 +1,18 @@
"<!DOCTYPE html><html lang=\"en\">"
"<head>"
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
"<script src=\"/script.js\"></script>"
"<title>",
"</title>"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"</head>"
"<body>"
"<ul class=\"topnav\" id=\"myTopnav\">"
"<li><a href=\"/\">Home</a></li>"
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
"<li class=\"active\"><a href=\"/tasks.html\">Tasks</a></li>"
"<li class=\"icon\">"
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">&#9776;</a>"
"</li>"
"</ul>",
"</body></html>"

View file

@ -0,0 +1,90 @@
"<!DOCTYPE html><html lang=\"en\">"
"<head>"
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
"<script src=\"/script.js\"></script>"
"<title>",
"</title>"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"</head>"
"<body>"
"<ul class=\"topnav\" id=\"myTopnav\">"
"<li><a href=\"/\">Home</a></li>"
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
"<li class=\"active\"><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
"<li class=\"icon\">"
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">&#9776;</a>"
"</li>"
"</ul>"
"<form action=\"/wificfg/ap.html\" method=\"post\">"
"<fieldset>"
"<legend>WiFi Access Point configuration</legend>"
"<dl class=\"dlh\">"
"<dt><label for=\"enable\">Enable AP mode</label></dt>"
"<dd><input id=\"enable\" type=\"checkbox\" name=\"ap_enable\" value=\"1\" ",
" /></dd>"
"<dt><label for=\"disable_if_sta\">Auto disable if station connection</label></dt>"
"<dd><input id=\"hidden\" type=\"checkbox\" name=\"ap_disable_if_sta\" value=\"1\" ",
" /></dd>"
"<dt><label for=\"disabled_restarts\">Disabled restarts</label></dt>"
"<dd><input id=\"disabled_restarts\" type=\"number\" size=\"2\" min=\"0\" step=\"1\" "
"name=\"ap_disabled_restarts\" placeholder=\"0\" value=\"",
"\"/></dd>"
"<dt><label for=\"ssid\">SSID</label></dt>"
"<dd><input id=\"ssid\" type=\"text\" minlength=\"1\" maxlength=\"31\" name=\"ap_ssid\" "
"placeholder=\"my access point\" value=\"",
"\"></dd>"
"<dt><label for=\"ap\">Password</label></dt>"
"<dd><input id=\"ap\" type=\"text\" minlength=\"8\" maxlength=\"63\" name=\"ap_password\" "
"placeholder=\"password\" value=\"",
"\"></dd>"
"<dt><label for=\"hidden\">SSID Hidden</label></dt>"
"<dd><input id=\"hidden\" type=\"checkbox\" name=\"ap_ssid_hidden\" value=\"1\" ",
" /></dd>"
"<dt><label for=\"ch\">Channel</label></dt>"
"<dd><input id=\"ch\" type=\"number\" size=\"2\" min=\"1\" max=\"14\" step=\"1\" "
"name=\"ap_channel\" placeholder=\"6\" value=\"",
"\"></dd>"
"<dt><label for=\"am\">Authentication Mode</label></dt>"
"<dd><select id=\"am\" name=\"ap_authmode\">"
"<option value=\"0\"",
">Open</option>"
"<option value=\"1\"",
">WEP</option>"
"<option value=\"2\"",
">WPA_PSK</option>"
"<option value=\"3\"",
">WPA2_PSK</option>"
"<option value=\"4\"",
">WPA_WPA2_PSK</option></select></dd>"
"<dt><label for=\"mc\">Max connections</label></dt>"
"<dd><input id=\"mc\" type=\"number\" size=\"2\" min=\"1\" max=\"8\" step=\"1\" "
"name=\"ap_max_conn\" placeholder=\"3\" value=\"",
"\"></dd>"
"<dt><label for=\"bi\">Beacon interval</label></dt>"
"<dd><input id=\"bi\" type=\"number\" size=\"6\" min=\"0\" max=\"10000\" step=\"1\" "
"name=\"ap_beacon_interval\" placeholder=\"100\" value=\"",
"\"></dd>"
"<dt><label for=\"ip\">IP Address</label></dt>"
"<dd><input id=\"ip\" type=\"text\" maxlength=\"15\" size=\"15\" "
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
"name=\"ap_ip_addr\" placeholder=\"192.168.4.1\" value=\"",
"\"></dd>"
"<dt><label for=\"nm\">Netmask</label></dt>"
"<dd><input id=\"nm\" type=\"text\" maxlength=\"15\" size=\"15\" "
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
"name=\"ap_netmask\" placeholder=\"255.255.255.0\" value=\"",
"\"></dd>"
"<dt><label for=\"dhcp\">DHCP Server Max Leases</label></dt>"
"<dd><input id=\"dhcp\" type=\"number\" size=\"2\" min=\"0\" max=\"16\" step=\"1\" "
"name=\"ap_dhcp_leases\" placeholder=\"4\" value=\"",
"\"></dd>"
"<dt><label for=\"dns_en\">DNS enabled</label></dt>"
"<dd><input id=\"dns_en\" type=\"checkbox\" name=\"ap_dns\" value=\"1\" ",
" /></dd>"
"</dl>"
"<center><input type=\"reset\">&nbsp;<input type=\"submit\" value=\"Save\"></center>"
"</fieldset>"
"<input type=\"hidden\" name=\"done\">"
"</form>"
"</body></html>"

View file

@ -0,0 +1,52 @@
"<!DOCTYPE html><html lang=\"en\">"
"<head>"
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
"<script src=\"/script.js\"></script>"
"<title>",
"</title>"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"</head>"
"<body>"
"<ul class=\"topnav\" id=\"myTopnav\">"
"<li><a href=\"/\">Home</a></li>"
"<li class=\"active\"><a href=\"/wificfg/\">WiFi Config</a></li>"
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
"<li class=\"icon\">"
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">&#9776;</a>"
"</li>"
"</ul>"
"<h1>WiFi Status</h1>"
"<dl class=\"dlh\">",
"</dl>"
"<br>"
"<form action=\"/wificfg/\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to lock the configuration interface, and have you noted the password?');\">"
"<fieldset>"
"<legend>Lock the configuration interface</legend>"
"<p>These WiFi configuration pages can be disabled for security on a shared network. If a password is supplied then they can be unlocked. Warning: if no password is supplied then it will not be possible to unlock these pages via this interface.</p>"
"<dl class=\"dlh\">"
"<dt><label for=\"pw\">Password</label></dt>"
"<dd><input id=\"pw\" type=\"text\" maxlength=\"32\" name=\"cfg_password\" "
"placeholder=\"unlock-password\" value=\"",
"\"></dd>"
"</dl>"
"<input type=\"hidden\" name=\"cfg_enable\" value=\"0\">"
"<center><input type=\"submit\" value=\"Lock\"></center>"
"</fieldset>"
"</form>"
"<form action=\"/wificfg/restart.html\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to restart the device?');\">"
"<fieldset>"
"<legend>Restart device</legend>"
"<p>A restart is necessary for some changes to take effect.</p>"
"<center><button>Restart</button></center>"
"</fieldset></form>"
"<form action=\"/wificfg/erase.html\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to erase the configuration?');\">"
"<fieldset>"
"<legend>Erase configuration</legend>"
"<p>Erases the device configuration stored in the flash memory and restarts the device. "
"This might be useful to clear stored passwords and private configuration information."
"</p>"
"<center><button>Erase Configuration</button></center>"
"</fieldset>"
"</form>",
"</body></html>"

View file

@ -0,0 +1,68 @@
"<!DOCTYPE html><html lang=\"en\">"
"<head>"
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
"<script src=\"/script.js\"></script>"
"<title>",
"</title>"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"</head>"
"<body>"
"<ul class=\"topnav\" id=\"myTopnav\">"
"<li><a href=\"/\">Home</a></li>"
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
"<li class=\"active\"><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
"<li class=\"icon\">"
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">&#9776;</a>"
"</li>"
"</ul>"
"<form action=\"/wificfg/sta.html\" method=\"post\">"
"<fieldset>"
"<legend>WiFi Station configuration</legend>"
"<dl class=\"dlh\">"
"<dt><label for=\"enable\">Enable Station mode</label></dt>"
"<dd><input id=\"enable\" type=\"checkbox\" name=\"sta_enable\" value=\"1\" ",
" /></dd>"
"<dt><label for=\"disabled_restarts\">Disabled restarts</label></dt>"
"<dd><input id=\"disabled_restarts\" type=\"number\" size=\"2\" min=\"0\" step=\"1\" "
"name=\"sta_disabled_restarts\" placeholder=\"0\" value=\"",
"\" /></dd>"
"<dt><label for=\"ssid\">SSID</label></dt>"
"<dd><input id=\"ssid\" minlength=\"1\" maxlength=\"31\" type=\"text\" name=\"sta_ssid\" "
"placeholder=\"my access point\" value=\"",
"\"></dd>"
"<dt><label for=\"pw\">Password</label></dt>"
"<dd><input id=\"pw\" type=\"text\" minlength=\"8\" maxlength=\"63\" name=\"sta_password\" "
"placeholder=\"password\" value=\"",
"\"></dd>"
"<dt><label for=\"hostname\">Hostname</label></dt>"
"<dd><input id=\"hostname\" type=\"text\" maxlength=\"63\" name=\"hostname\" "
"placeholder=\"device-hostname\" value=\"",
"\"></dd>"
"<dt><label for=\"dhcp\">Enable DHCP</label></dt>"
"<dd><input id=\"dhcp\" type=\"radio\" name=\"sta_dhcp\" value=\"1\" ",
" /></dd>"
"<dt><label for=\"static\">Disable DHCP (static address below)</label></dt>"
"<dd><input id=\"static\" type=\"radio\" name=\"sta_dhcp\" value=\"0\" ",
" /></dd>"
"<dt><label for=\"ip\">Static IP Address</label></dt>"
"<dd><input id=\"ip\" type=\"text\" maxlength=\"15\" size=\"15\" "
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
"name=\"sta_ip_addr\" placeholder=\"192.168.1.50\" value=\"",
"\"></dd>"
"<dt><label for=\"nm\">Static Netmask</label></dt>"
"<dd><input id=\"nm\" type=\"text\" maxlength=\"15\" size=\"15\" "
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
"name=\"sta_netmask\" placeholder=\"255.255.255.0\" value=\"",
"\"></dd>"
"<dt><label for=\"gw\">Static Gateway</label></dt>"
"<dd><input id=\"gw\" type=\"text\" maxlength=\"15\" size=\"15\" "
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
"name=\"sta_gateway\" placeholder=\"192.168.1.1\" value=\"",
"\"></dd>"
"</dl>"
"<center><input type=\"reset\">&nbsp;<input type=\"submit\" value=\"Save\"></center>"
"</fieldset>"
"<input type=\"hidden\" name=\"done\">"
"</form>"
"</body></html>"

2022
extras/wificfg/wificfg.c Normal file

File diff suppressed because it is too large Load diff

137
extras/wificfg/wificfg.h Normal file
View file

@ -0,0 +1,137 @@
/*
* WiFi configuration via a simple web server.
*
* Copyright (C) 2016 OurAirQuality.org
*
* Licensed under the Apache License, Version 2.0, January 2004 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
#ifndef __WIFICFG_H__
#define __WIFICFG_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Printf format used to initialize a default AP ssid. It is passed the last
* three bytes of the mac address. This may be NULL to not default the ssid,
* but the AP network will not run without a ssid.
*/
extern char *wificfg_default_ssid;
/*
* A default password for the AP interface. This may be NULL to not default the
* password, but the AP network will not run without a password. The minimum
* length is 8 characters.
*/
extern char *wificfg_default_password;
/*
* A default hostname printf format string. This may be NULL to not default the
* hostname.
*/
extern char *wificfg_default_hostname;
/*
* The web server parses the http method string in these enums. The ANY method
* is only use for dispatch. The method enum is passed to the handler functions.
*/
typedef enum {
HTTP_METHOD_GET,
HTTP_METHOD_POST,
HTTP_METHOD_HEAD,
HTTP_METHOD_OTHER,
HTTP_METHOD_ANY,
} wificfg_method;
/*
* The web server parses these content-type header values. This is passed to the
* dispatch function.
*/
typedef enum {
HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED,
HTTP_CONTENT_TYPE_OTHER
} wificfg_content_type;
/*
* The function signature for the http server request handler functions.
*
* The buffer, with its length, is usable by the handler.
*/
typedef int (* wificfg_handler)(int s, wificfg_method method,
uint32_t content_length,
wificfg_content_type content_type,
char *buf, size_t len);
typedef struct {
const char *path;
wificfg_method method;
wificfg_handler handler;
bool secure;
} wificfg_dispatch;
/*
* Start the Wifi Configuration http server task. The IP port number
* and a path dispatch list are needed. The dispatch list can not be
* stack allocated as it is passed to another task.
*/
void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch);
/*
* Support for reading a form name or value from the socket. The name or value
* is truncated to the buffer length. The number of characters read is limited
* to the remainder which is updated. The 'valp' flag is set if a value follows.
*/
int wificfg_form_name_value(int s, bool *valp, size_t *rem, char *buf, size_t len);
/* Support for form url-encoding decoder. */
void wificfg_form_url_decode(char *string);
/* Support for html-escaping of form values. */
void wificfg_html_escape(char *string, char *buf, size_t len);
/* Support for writing a string in a response. */
int wificfg_write_string(int s, const char *str);
/* Support for writing a string in a response, with chunk transfer encoding.
* An optional buffer may be supplied to use to construct a chunk with the
* header and trailer, reducing the number of write() calls, and the str may be
* at the start of this buffer.
*/
int wificfg_write_string_chunk(int s, const char *str, char *buf, size_t len);
/* Write a chunk transfer encoding end marker. */
int wificfg_write_chunk_end(int s);
/* Write a chunk offset 4 bytes into the buffer. */
int wificfg_write_buffer_chunk(int s, char *buf);
/* Write a html title meta data, using the hostname or AP SSI. */
int wificfg_write_html_title(int s, char *buf, size_t len, const char *str);
/* Callback to notify the wificfg logic that a station connection has been
* successfully established. It might use this to disable the AP interface after
* a restart.
*/
void wificfg_got_sta_connect(void);
#ifdef __cplusplus
}
#endif
#endif // __WIFICFG_H__

View file

@ -37,7 +37,7 @@
#endif
#define MAX_DMA_BLOCK_SIZE 4095
#define DMA_PIXEL_SIZE 12 // each colour takes 4 bytes
// #define DMA_PIXEL_SIZE 16 // each colour takes 4 bytes
/**
* Amount of zero data to produce WS2812 reset condition.
@ -60,7 +60,7 @@ volatile uint32_t dma_isr_counter = 0;
static volatile bool i2s_dma_processing = false;
static void dma_isr_handler(void)
static void dma_isr_handler(void *arg)
{
if (i2s_dma_is_eof_interrupt()) {
#ifdef WS2812_I2S_DEBUG
@ -117,9 +117,9 @@ static inline void init_descriptors_list(uint8_t *buf, uint32_t total_dma_data_s
}
}
void ws2812_i2s_init(uint32_t pixels_number)
void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type)
{
dma_buffer_size = pixels_number * DMA_PIXEL_SIZE;
dma_buffer_size = pixels_number * type;
dma_block_list_size = dma_buffer_size / MAX_DMA_BLOCK_SIZE;
if (dma_buffer_size % MAX_DMA_BLOCK_SIZE) {
@ -145,7 +145,7 @@ void ws2812_i2s_init(uint32_t pixels_number)
debug("i2s clock dividers, bclk=%d, clkm=%d\n",
clock_div.bclk_div, clock_div.clkm_div);
i2s_dma_init(dma_isr_handler, clock_div, i2s_pins);
i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
}
const IRAM_DATA int16_t bitpatterns[16] =
@ -156,13 +156,13 @@ const IRAM_DATA int16_t bitpatterns[16] =
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
void ws2812_i2s_update(ws2812_pixel_t *pixels)
void ws2812_i2s_update(ws2812_pixel_t *pixels, pixeltype_t type)
{
while (i2s_dma_processing) {};
uint16_t *p_dma_buf = dma_buffer;
for (uint32_t i = 0; i < (dma_buffer_size / DMA_PIXEL_SIZE); i++) {
for (uint32_t i = 0; i < (dma_buffer_size / type); i++) {
// green
*p_dma_buf++ = bitpatterns[pixels[i].green & 0x0F];
*p_dma_buf++ = bitpatterns[pixels[i].green >> 4];
@ -174,6 +174,12 @@ void ws2812_i2s_update(ws2812_pixel_t *pixels)
// blue
*p_dma_buf++ = bitpatterns[pixels[i].blue & 0x0F];
*p_dma_buf++ = bitpatterns[pixels[i].blue >> 4];
if(type == PIXEL_RGBW) {
// white
*p_dma_buf++ = bitpatterns[pixels[i].white & 0x0F];
*p_dma_buf++ = bitpatterns[pixels[i].white >> 4];
}
}
i2s_dma_processing = true;

View file

@ -35,8 +35,14 @@ typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t white;
} ws2812_pixel_t;
typedef enum {
PIXEL_RGB = 12,
PIXEL_RGBW = 16
} pixeltype_t;
/**
* Initialize i2s and dma subsystems to work with ws2812 led strip.
*
@ -44,7 +50,7 @@ typedef struct {
*
* @param pixels_number Number of pixels in the strip.
*/
void ws2812_i2s_init(uint32_t pixels_number);
void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type);
/**
* Update ws2812 pixels.
@ -52,7 +58,7 @@ void ws2812_i2s_init(uint32_t pixels_number);
* @param pixels Array of 'pixels_number' pixels. The array must contain all
* the pixels.
*/
void ws2812_i2s_update(ws2812_pixel_t *pixels);
void ws2812_i2s_update(ws2812_pixel_t *pixels, pixeltype_t type);
#ifdef __cplusplus
}