mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-07 06:01:35 +03:00
Migrate from astyle to clang-format (#8464)
This commit is contained in:
committed by
Max Prokhorov
parent
46190b61f1
commit
19b7a29720
@ -23,7 +23,7 @@
|
||||
// these functions must exists as-is with "C" interface,
|
||||
// nonos-sdk calls them at boot time and later
|
||||
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
|
||||
#include <lwip/netif.h>
|
||||
#include "LwipDhcpServer.h"
|
||||
@ -35,8 +35,7 @@ DhcpServer dhcpSoftAP(&netif_git[SOFTAP_IF]);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void dhcps_start(struct ip_info *info, netif* apnetif)
|
||||
void dhcps_start(struct ip_info* info, netif* apnetif)
|
||||
{
|
||||
// apnetif is esp interface, replaced by lwip2's
|
||||
// netif_git[SOFTAP_IF] interface in constructor
|
||||
@ -61,4 +60,4 @@ extern "C"
|
||||
dhcpSoftAP.end();
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,12 +31,11 @@
|
||||
#ifndef __DHCPS_H__
|
||||
#define __DHCPS_H__
|
||||
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
|
||||
class DhcpServer
|
||||
{
|
||||
public:
|
||||
|
||||
DhcpServer(netif* netif);
|
||||
~DhcpServer();
|
||||
|
||||
@ -53,72 +52,64 @@ public:
|
||||
|
||||
// legacy public C structure and API to eventually turn into C++
|
||||
|
||||
void init_dhcps_lease(uint32 ip);
|
||||
bool set_dhcps_lease(struct dhcps_lease *please);
|
||||
bool get_dhcps_lease(struct dhcps_lease *please);
|
||||
bool set_dhcps_offer_option(uint8 level, void* optarg);
|
||||
bool set_dhcps_lease_time(uint32 minute);
|
||||
bool reset_dhcps_lease_time(void);
|
||||
void init_dhcps_lease(uint32 ip);
|
||||
bool set_dhcps_lease(struct dhcps_lease* please);
|
||||
bool get_dhcps_lease(struct dhcps_lease* please);
|
||||
bool set_dhcps_offer_option(uint8 level, void* optarg);
|
||||
bool set_dhcps_lease_time(uint32 minute);
|
||||
bool reset_dhcps_lease_time(void);
|
||||
uint32 get_dhcps_lease_time(void);
|
||||
bool add_dhcps_lease(uint8 *macaddr);
|
||||
bool add_dhcps_lease(uint8* macaddr);
|
||||
|
||||
void dhcps_set_dns(int num, const ipv4_addr_t* dns);
|
||||
|
||||
protected:
|
||||
|
||||
// legacy C structure and API to eventually turn into C++
|
||||
|
||||
typedef struct _list_node
|
||||
{
|
||||
void *pnode;
|
||||
struct _list_node *pnext;
|
||||
void* pnode;
|
||||
struct _list_node* pnext;
|
||||
} list_node;
|
||||
|
||||
void node_insert_to_list(list_node **phead, list_node* pinsert);
|
||||
void node_remove_from_list(list_node **phead, list_node* pdelete);
|
||||
uint8_t* add_msg_type(uint8_t *optptr, uint8_t type);
|
||||
uint8_t* add_offer_options(uint8_t *optptr);
|
||||
uint8_t* add_end(uint8_t *optptr);
|
||||
void create_msg(struct dhcps_msg *m);
|
||||
void send_offer(struct dhcps_msg *m);
|
||||
void send_nak(struct dhcps_msg *m);
|
||||
void send_ack(struct dhcps_msg *m);
|
||||
uint8_t parse_options(uint8_t *optptr, sint16_t len);
|
||||
sint16_t parse_msg(struct dhcps_msg *m, u16_t len);
|
||||
static void S_handle_dhcp(void *arg,
|
||||
struct udp_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
const ip_addr_t *addr,
|
||||
void node_insert_to_list(list_node** phead, list_node* pinsert);
|
||||
void node_remove_from_list(list_node** phead, list_node* pdelete);
|
||||
uint8_t* add_msg_type(uint8_t* optptr, uint8_t type);
|
||||
uint8_t* add_offer_options(uint8_t* optptr);
|
||||
uint8_t* add_end(uint8_t* optptr);
|
||||
void create_msg(struct dhcps_msg* m);
|
||||
void send_offer(struct dhcps_msg* m);
|
||||
void send_nak(struct dhcps_msg* m);
|
||||
void send_ack(struct dhcps_msg* m);
|
||||
uint8_t parse_options(uint8_t* optptr, sint16_t len);
|
||||
sint16_t parse_msg(struct dhcps_msg* m, u16_t len);
|
||||
static void S_handle_dhcp(void* arg, struct udp_pcb* pcb, struct pbuf* p, const ip_addr_t* addr,
|
||||
uint16_t port);
|
||||
void handle_dhcp(
|
||||
struct udp_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
const ip_addr_t *addr,
|
||||
uint16_t port);
|
||||
void kill_oldest_dhcps_pool(void);
|
||||
void dhcps_coarse_tmr(void); // CURRENTLY NOT CALLED
|
||||
void dhcps_client_leave(u8 *bssid, struct ipv4_addr *ip, bool force);
|
||||
uint32 dhcps_client_update(u8 *bssid, struct ipv4_addr *ip);
|
||||
void handle_dhcp(struct udp_pcb* pcb, struct pbuf* p, const ip_addr_t* addr, uint16_t port);
|
||||
void kill_oldest_dhcps_pool(void);
|
||||
void dhcps_coarse_tmr(void); // CURRENTLY NOT CALLED
|
||||
void dhcps_client_leave(u8* bssid, struct ipv4_addr* ip, bool force);
|
||||
uint32 dhcps_client_update(u8* bssid, struct ipv4_addr* ip);
|
||||
|
||||
netif* _netif;
|
||||
|
||||
struct udp_pcb *pcb_dhcps;
|
||||
ip_addr_t broadcast_dhcps;
|
||||
struct udp_pcb* pcb_dhcps;
|
||||
ip_addr_t broadcast_dhcps;
|
||||
struct ipv4_addr server_address;
|
||||
struct ipv4_addr client_address;
|
||||
struct ipv4_addr dns_address;
|
||||
uint32 dhcps_lease_time;
|
||||
uint32 dhcps_lease_time;
|
||||
|
||||
struct dhcps_lease dhcps_lease;
|
||||
list_node *plist;
|
||||
uint8 offer;
|
||||
bool renew;
|
||||
list_node* plist;
|
||||
uint8 offer;
|
||||
bool renew;
|
||||
|
||||
static const uint32 magic_cookie;
|
||||
};
|
||||
|
||||
// SoftAP DHCP server always exists and is started on boot
|
||||
extern DhcpServer dhcpSoftAP;
|
||||
extern "C" int fw_has_started_softap_dhcps;
|
||||
extern "C" int fw_has_started_softap_dhcps;
|
||||
|
||||
#endif // __DHCPS_H__
|
||||
#endif // __DHCPS_H__
|
||||
|
@ -1,12 +1,13 @@
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#if LWIP_IPV6
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#endif
|
||||
|
||||
#include <user_interface.h>
|
||||
@ -24,19 +25,23 @@ extern "C" {
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
|
||||
bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3,
|
||||
IPAddress& gateway, IPAddress& netmask, IPAddress& dns1)
|
||||
bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1,
|
||||
const IPAddress& arg2, const IPAddress& arg3, IPAddress& gateway,
|
||||
IPAddress& netmask, IPAddress& dns1)
|
||||
{
|
||||
//To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order, otherwise Arduino order.
|
||||
// To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order,
|
||||
// otherwise Arduino order.
|
||||
gateway = arg1;
|
||||
netmask = arg2;
|
||||
dns1 = arg3;
|
||||
dns1 = arg3;
|
||||
|
||||
if (netmask[0] != 255)
|
||||
{
|
||||
//octet is not 255 => interpret as Arduino order
|
||||
// octet is not 255 => interpret as Arduino order
|
||||
gateway = arg2;
|
||||
netmask = arg3[0] == 0 ? IPAddress(255, 255, 255, 0) : arg3; //arg order is arduino and 4th arg not given => assign it arduino default
|
||||
netmask = arg3[0] == 0 ? IPAddress(255, 255, 255, 0)
|
||||
: arg3; // arg order is arduino and 4th arg not given => assign it
|
||||
// arduino default
|
||||
dns1 = arg1;
|
||||
}
|
||||
|
||||
@ -46,7 +51,7 @@ bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1
|
||||
return false;
|
||||
}
|
||||
|
||||
//ip and gateway must be in the same netmask
|
||||
// ip and gateway must be in the same netmask
|
||||
if (gateway.isSet() && (local_ip.v4() & netmask.v4()) != (gateway.v4() & netmask.v4()))
|
||||
{
|
||||
return false;
|
||||
@ -143,7 +148,6 @@ bool LwipIntf::hostname(const char* aHostname)
|
||||
// harmless for AP, also compatible with ethernet adapters (to come)
|
||||
for (netif* intf = netif_list; intf; intf = intf->next)
|
||||
{
|
||||
|
||||
// unconditionally update all known interfaces
|
||||
intf->hostname = wifi_station_get_hostname();
|
||||
|
||||
@ -162,4 +166,3 @@ bool LwipIntf::hostname(const char* aHostname)
|
||||
|
||||
return ret && compliant;
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
class LwipIntf
|
||||
{
|
||||
public:
|
||||
|
||||
using CBType = std::function <void(netif*)>;
|
||||
using CBType = std::function<void(netif*)>;
|
||||
|
||||
static bool stateUpCB(LwipIntf::CBType&& cb);
|
||||
|
||||
@ -24,12 +23,12 @@ public:
|
||||
// arg3 | dns1 netmask
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
static
|
||||
bool ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3,
|
||||
IPAddress& gateway, IPAddress& netmask, IPAddress& dns1);
|
||||
static bool ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1,
|
||||
const IPAddress& arg2, const IPAddress& arg3, IPAddress& gateway,
|
||||
IPAddress& netmask, IPAddress& dns1);
|
||||
|
||||
String hostname();
|
||||
bool hostname(const String& aHostname)
|
||||
bool hostname(const String& aHostname)
|
||||
{
|
||||
return hostname(aHostname.c_str());
|
||||
}
|
||||
@ -42,8 +41,7 @@ public:
|
||||
const char* getHostname();
|
||||
|
||||
protected:
|
||||
|
||||
static bool stateChangeSysCB(LwipIntf::CBType&& cb);
|
||||
};
|
||||
|
||||
#endif // _LWIPINTF_H
|
||||
#endif // _LWIPINTF_H
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#define NETIF_STATUS_CB_SIZE 3
|
||||
|
||||
static int netifStatusChangeListLength = 0;
|
||||
LwipIntf::CBType netifStatusChangeList [NETIF_STATUS_CB_SIZE];
|
||||
static int netifStatusChangeListLength = 0;
|
||||
LwipIntf::CBType netifStatusChangeList[NETIF_STATUS_CB_SIZE];
|
||||
|
||||
extern "C" void netif_status_changed(struct netif* netif)
|
||||
{
|
||||
@ -33,12 +33,14 @@ bool LwipIntf::stateChangeSysCB(LwipIntf::CBType&& cb)
|
||||
|
||||
bool LwipIntf::stateUpCB(LwipIntf::CBType&& cb)
|
||||
{
|
||||
return stateChangeSysCB([cb](netif * nif)
|
||||
{
|
||||
if (netif_is_up(nif))
|
||||
schedule_function([cb, nif]()
|
||||
return stateChangeSysCB(
|
||||
[cb](netif* nif)
|
||||
{
|
||||
cb(nif);
|
||||
if (netif_is_up(nif))
|
||||
schedule_function(
|
||||
[cb, nif]()
|
||||
{
|
||||
cb(nif);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/apps/sntp.h>
|
||||
|
||||
#include <user_interface.h> // wifi_get_macaddr()
|
||||
#include <user_interface.h> // wifi_get_macaddr()
|
||||
|
||||
#include "SPI.h"
|
||||
#include "Schedule.h"
|
||||
@ -25,41 +25,36 @@
|
||||
#define DEFAULT_MTU 1500
|
||||
#endif
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
class LwipIntfDev: public LwipIntf, public RawDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
LwipIntfDev(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1):
|
||||
RawDev(cs, spi, intr),
|
||||
_mtu(DEFAULT_MTU),
|
||||
_intrPin(intr),
|
||||
_started(false),
|
||||
_default(false)
|
||||
LwipIntfDev(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1) :
|
||||
RawDev(cs, spi, intr), _mtu(DEFAULT_MTU), _intrPin(intr), _started(false), _default(false)
|
||||
{
|
||||
memset(&_netif, 0, sizeof(_netif));
|
||||
}
|
||||
|
||||
boolean config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3 = IPADDR_NONE, const IPAddress& dns2 = IPADDR_NONE);
|
||||
boolean config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2,
|
||||
const IPAddress& arg3 = IPADDR_NONE, const IPAddress& dns2 = IPADDR_NONE);
|
||||
|
||||
// default mac-address is inferred from esp8266's STA interface
|
||||
boolean begin(const uint8_t *macAddress = nullptr, const uint16_t mtu = DEFAULT_MTU);
|
||||
boolean begin(const uint8_t* macAddress = nullptr, const uint16_t mtu = DEFAULT_MTU);
|
||||
|
||||
const netif* getNetIf() const
|
||||
{
|
||||
return &_netif;
|
||||
}
|
||||
|
||||
IPAddress localIP() const
|
||||
IPAddress localIP() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)));
|
||||
}
|
||||
IPAddress subnetMask() const
|
||||
IPAddress subnetMask() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.netmask)));
|
||||
}
|
||||
IPAddress gatewayIP() const
|
||||
IPAddress gatewayIP() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.gw)));
|
||||
}
|
||||
@ -77,12 +72,11 @@ public:
|
||||
wl_status_t status();
|
||||
|
||||
protected:
|
||||
|
||||
err_t netif_init();
|
||||
void netif_status_callback();
|
||||
|
||||
static err_t netif_init_s(netif* netif);
|
||||
static err_t linkoutput_s(netif *netif, struct pbuf *p);
|
||||
static err_t linkoutput_s(netif* netif, struct pbuf* p);
|
||||
static void netif_status_callback_s(netif* netif);
|
||||
|
||||
// called on a regular basis or on interrupt
|
||||
@ -90,18 +84,19 @@ protected:
|
||||
|
||||
// members
|
||||
|
||||
netif _netif;
|
||||
|
||||
uint16_t _mtu;
|
||||
int8_t _intrPin;
|
||||
uint8_t _macAddress[6];
|
||||
bool _started;
|
||||
bool _default;
|
||||
netif _netif;
|
||||
|
||||
uint16_t _mtu;
|
||||
int8_t _intrPin;
|
||||
uint8_t _macAddress[6];
|
||||
bool _started;
|
||||
bool _default;
|
||||
};
|
||||
|
||||
template <class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2)
|
||||
template<class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& gateway,
|
||||
const IPAddress& netmask, const IPAddress& dns1,
|
||||
const IPAddress& dns2)
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
@ -132,7 +127,7 @@ boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& g
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu)
|
||||
{
|
||||
if (mtu)
|
||||
@ -162,9 +157,9 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
memset(_macAddress, 0, 6);
|
||||
_macAddress[0] = 0xEE;
|
||||
#endif
|
||||
_macAddress[3] += _netif.num; // alter base mac address
|
||||
_macAddress[0] &= 0xfe; // set as locally administered, unicast, per
|
||||
_macAddress[0] |= 0x02; // https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
|
||||
_macAddress[3] += _netif.num; // alter base mac address
|
||||
_macAddress[0] &= 0xfe; // set as locally administered, unicast, per
|
||||
_macAddress[0] |= 0x02; // https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
|
||||
}
|
||||
|
||||
if (!RawDev::begin(_macAddress))
|
||||
@ -183,7 +178,8 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
ip_addr_copy(netmask, _netif.netmask);
|
||||
ip_addr_copy(gw, _netif.gw);
|
||||
|
||||
if (!netif_add(&_netif, ip_2_ip4(&ip_addr), ip_2_ip4(&netmask), ip_2_ip4(&gw), this, netif_init_s, ethernet_input))
|
||||
if (!netif_add(&_netif, ip_2_ip4(&ip_addr), ip_2_ip4(&netmask), ip_2_ip4(&gw), this,
|
||||
netif_init_s, ethernet_input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -212,20 +208,24 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
{
|
||||
if (RawDev::interruptIsPossible())
|
||||
{
|
||||
//attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
// attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
}
|
||||
else
|
||||
{
|
||||
::printf((PGM_P)F("lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
::printf((PGM_P)F(
|
||||
"lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
_intrPin = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_intrPin < 0 && !schedule_recurrent_function_us([&]()
|
||||
{
|
||||
this->handlePackets();
|
||||
return true;
|
||||
}, 100))
|
||||
if (_intrPin < 0
|
||||
&& !schedule_recurrent_function_us(
|
||||
[&]()
|
||||
{
|
||||
this->handlePackets();
|
||||
return true;
|
||||
},
|
||||
100))
|
||||
{
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
@ -234,14 +234,14 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
wl_status_t LwipIntfDev<RawDev>::status()
|
||||
{
|
||||
return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif *netif, struct pbuf *pbuf)
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif* netif, struct pbuf* pbuf)
|
||||
{
|
||||
LwipIntfDev* ths = (LwipIntfDev*)netif->state;
|
||||
|
||||
@ -255,37 +255,34 @@ err_t LwipIntfDev<RawDev>::linkoutput_s(netif *netif, struct pbuf *pbuf)
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture)
|
||||
{
|
||||
phy_capture(ths->_netif.num, (const char*)pbuf->payload, pbuf->len, /*out*/1, /*success*/len == pbuf->len);
|
||||
phy_capture(ths->_netif.num, (const char*)pbuf->payload, pbuf->len, /*out*/ 1,
|
||||
/*success*/ len == pbuf->len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return len == pbuf->len ? ERR_OK : ERR_MEM;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init_s(struct netif* netif)
|
||||
{
|
||||
return ((LwipIntfDev*)netif->state)->netif_init();
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback_s(struct netif* netif)
|
||||
{
|
||||
((LwipIntfDev*)netif->state)->netif_status_callback();
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init()
|
||||
{
|
||||
_netif.name[0] = 'e';
|
||||
_netif.name[1] = '0' + _netif.num;
|
||||
_netif.mtu = _mtu;
|
||||
_netif.name[0] = 'e';
|
||||
_netif.name[1] = '0' + _netif.num;
|
||||
_netif.mtu = _mtu;
|
||||
_netif.chksum_flags = NETIF_CHECKSUM_ENABLE_ALL;
|
||||
_netif.flags =
|
||||
NETIF_FLAG_ETHARP
|
||||
| NETIF_FLAG_IGMP
|
||||
| NETIF_FLAG_BROADCAST
|
||||
| NETIF_FLAG_LINK_UP;
|
||||
_netif.flags = NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP;
|
||||
|
||||
// lwIP's doc: This function typically first resolves the hardware
|
||||
// address, then sends the packet. For ethernet physical layer, this is
|
||||
@ -301,7 +298,7 @@ err_t LwipIntfDev<RawDev>::netif_init()
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback()
|
||||
{
|
||||
if (connected())
|
||||
@ -321,14 +318,14 @@ void LwipIntfDev<RawDev>::netif_status_callback()
|
||||
}
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
{
|
||||
int pkt = 0;
|
||||
while (1)
|
||||
{
|
||||
if (++pkt == 10)
|
||||
// prevent starvation
|
||||
// prevent starvation
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
@ -374,7 +371,8 @@ err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture)
|
||||
{
|
||||
phy_capture(_netif.num, (const char*)pbuf->payload, tot_len, /*out*/0, /*success*/err == ERR_OK);
|
||||
phy_capture(_netif.num, (const char*)pbuf->payload, tot_len, /*out*/ 0,
|
||||
/*success*/ err == ERR_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -384,11 +382,10 @@ err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
return err;
|
||||
}
|
||||
// (else) allocated pbuf is now lwIP's responsibility
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::setDefault()
|
||||
{
|
||||
_default = true;
|
||||
@ -398,4 +395,4 @@ void LwipIntfDev<RawDev>::setDefault()
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _LWIPINTFDEV_H
|
||||
#endif // _LWIPINTFDEV_H
|
||||
|
@ -19,20 +19,17 @@
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <StreamDev.h>
|
||||
|
||||
size_t Stream::sendGeneric(Print* to,
|
||||
const ssize_t len,
|
||||
const int readUntilChar,
|
||||
size_t Stream::sendGeneric(Print* to, const ssize_t len, const int readUntilChar,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
setReport(Report::Success);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
return 0; // conveniently avoids timeout for no requested data
|
||||
return 0; // conveniently avoids timeout for no requested data
|
||||
}
|
||||
|
||||
// There are two timeouts:
|
||||
@ -57,14 +54,17 @@ size_t Stream::sendGeneric(Print* to,
|
||||
return SendGenericRegular(to, len, timeoutMs);
|
||||
}
|
||||
|
||||
|
||||
size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int readUntilChar, const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
size_t
|
||||
Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int readUntilChar,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
// "neverExpires (default, impossible)" is translated to default timeout
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout() : timeoutMs);
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(
|
||||
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
|
||||
: timeoutMs);
|
||||
// len==-1 => maxLen=0 <=> until starvation
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
|
||||
while (!maxLen || written < maxLen)
|
||||
{
|
||||
@ -90,13 +90,13 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
|
||||
if (w)
|
||||
{
|
||||
const char* directbuf = peekBuffer();
|
||||
bool foundChar = false;
|
||||
bool foundChar = false;
|
||||
if (readUntilChar >= 0)
|
||||
{
|
||||
const char* last = (const char*)memchr(directbuf, readUntilChar, w);
|
||||
if (last)
|
||||
{
|
||||
w = std::min((size_t)(last - directbuf), w);
|
||||
w = std::min((size_t)(last - directbuf), w);
|
||||
foundChar = true;
|
||||
}
|
||||
}
|
||||
@ -104,7 +104,7 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
|
||||
{
|
||||
peekConsume(w);
|
||||
written += w;
|
||||
timedOut.reset(); // something has been written
|
||||
timedOut.reset(); // something has been written
|
||||
}
|
||||
if (foundChar)
|
||||
{
|
||||
@ -145,16 +145,20 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int readUntilChar, const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
size_t
|
||||
Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int readUntilChar,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
// regular Stream API
|
||||
// no other choice than reading byte by byte
|
||||
|
||||
// "neverExpires (default, impossible)" is translated to default timeout
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout() : timeoutMs);
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(
|
||||
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
|
||||
: timeoutMs);
|
||||
// len==-1 => maxLen=0 <=> until starvation
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
|
||||
while (!maxLen || written < maxLen)
|
||||
{
|
||||
@ -186,7 +190,7 @@ size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int r
|
||||
break;
|
||||
}
|
||||
written += 1;
|
||||
timedOut.reset(); // something has been written
|
||||
timedOut.reset(); // something has been written
|
||||
}
|
||||
|
||||
if (timedOut)
|
||||
@ -221,16 +225,19 @@ size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int r
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
size_t Stream::SendGenericRegular(Print* to, const ssize_t len,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
// regular Stream API
|
||||
// use an intermediary buffer
|
||||
|
||||
// "neverExpires (default, impossible)" is translated to default timeout
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout() : timeoutMs);
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(
|
||||
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
|
||||
: timeoutMs);
|
||||
// len==-1 => maxLen=0 <=> until starvation
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
|
||||
while (!maxLen || written < maxLen)
|
||||
{
|
||||
@ -243,7 +250,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
|
||||
size_t w = to->availableForWrite();
|
||||
if (w == 0 && !to->outputCanTimeout())
|
||||
// no more data can be written, ever
|
||||
// no more data can be written, ever
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -256,7 +263,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
w = std::min(w, (decltype(w))temporaryStackBufferSize);
|
||||
if (w)
|
||||
{
|
||||
char temp[w];
|
||||
char temp[w];
|
||||
ssize_t r = read(temp, w);
|
||||
if (r < 0)
|
||||
{
|
||||
@ -270,7 +277,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
setReport(Report::WriteError);
|
||||
break;
|
||||
}
|
||||
timedOut.reset(); // something has been written
|
||||
timedOut.reset(); // something has been written
|
||||
}
|
||||
|
||||
if (timedOut)
|
||||
@ -305,19 +312,19 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
return written;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, String& string)
|
||||
Stream& operator<<(Stream& out, String& string)
|
||||
{
|
||||
StreamConstPtr(string).sendAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, StreamString& stream)
|
||||
Stream& operator<<(Stream& out, StreamString& stream)
|
||||
{
|
||||
stream.sendAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, Stream& stream)
|
||||
Stream& operator<<(Stream& out, Stream& stream)
|
||||
{
|
||||
if (stream.streamRemaining() < 0)
|
||||
{
|
||||
@ -339,13 +346,13 @@ Stream& operator << (Stream& out, Stream& stream)
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, const char* text)
|
||||
Stream& operator<<(Stream& out, const char* text)
|
||||
{
|
||||
StreamConstPtr(text, strlen_P(text)).sendAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, const __FlashStringHelper* text)
|
||||
Stream& operator<<(Stream& out, const __FlashStringHelper* text)
|
||||
{
|
||||
StreamConstPtr(text).sendAll(out);
|
||||
return out;
|
||||
|
@ -35,16 +35,9 @@
|
||||
class S2Stream: public Stream
|
||||
{
|
||||
public:
|
||||
S2Stream(String& string, int peekPointer = -1) : string(&string), peekPointer(peekPointer) { }
|
||||
|
||||
S2Stream(String& string, int peekPointer = -1):
|
||||
string(&string), peekPointer(peekPointer)
|
||||
{
|
||||
}
|
||||
|
||||
S2Stream(String* string, int peekPointer = -1):
|
||||
string(string), peekPointer(peekPointer)
|
||||
{
|
||||
}
|
||||
S2Stream(String* string, int peekPointer = -1) : string(string), peekPointer(peekPointer) { }
|
||||
|
||||
virtual int available() override
|
||||
{
|
||||
@ -207,18 +200,15 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
String* string;
|
||||
int peekPointer; // -1:String is consumed / >=0:resettable pointer
|
||||
int peekPointer; // -1:String is consumed / >=0:resettable pointer
|
||||
};
|
||||
|
||||
|
||||
// StreamString is a S2Stream holding the String
|
||||
|
||||
class StreamString: public String, public S2Stream
|
||||
{
|
||||
protected:
|
||||
|
||||
void resetpp()
|
||||
{
|
||||
if (peekPointer > 0)
|
||||
@ -228,55 +218,68 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
StreamString(StreamString&& bro): String(bro), S2Stream(this) { }
|
||||
StreamString(const StreamString& bro): String(bro), S2Stream(this) { }
|
||||
StreamString(StreamString&& bro) : String(bro), S2Stream(this) { }
|
||||
StreamString(const StreamString& bro) : String(bro), S2Stream(this) { }
|
||||
|
||||
// duplicate String constructors and operator=:
|
||||
|
||||
StreamString(const char* text = nullptr): String(text), S2Stream(this) { }
|
||||
StreamString(const String& string): String(string), S2Stream(this) { }
|
||||
StreamString(const __FlashStringHelper *str): String(str), S2Stream(this) { }
|
||||
StreamString(String&& string): String(string), S2Stream(this) { }
|
||||
StreamString(const char* text = nullptr) : String(text), S2Stream(this) { }
|
||||
StreamString(const String& string) : String(string), S2Stream(this) { }
|
||||
StreamString(const __FlashStringHelper* str) : String(str), S2Stream(this) { }
|
||||
StreamString(String&& string) : String(string), S2Stream(this) { }
|
||||
|
||||
explicit StreamString(char c): String(c), S2Stream(this) { }
|
||||
explicit StreamString(unsigned char c, unsigned char base = 10): String(c, base), S2Stream(this) { }
|
||||
explicit StreamString(int i, unsigned char base = 10): String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned int i, unsigned char base = 10): String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(long l, unsigned char base = 10): String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned long l, unsigned char base = 10): String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(float f, unsigned char decimalPlaces = 2): String(f, decimalPlaces), S2Stream(this) { }
|
||||
explicit StreamString(double d, unsigned char decimalPlaces = 2): String(d, decimalPlaces), S2Stream(this) { }
|
||||
explicit StreamString(char c) : String(c), S2Stream(this) { }
|
||||
explicit StreamString(unsigned char c, unsigned char base = 10) :
|
||||
String(c, base), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(int i, unsigned char base = 10) : String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned int i, unsigned char base = 10) : String(i, base), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(long l, unsigned char base = 10) : String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned long l, unsigned char base = 10) :
|
||||
String(l, base), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(float f, unsigned char decimalPlaces = 2) :
|
||||
String(f, decimalPlaces), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(double d, unsigned char decimalPlaces = 2) :
|
||||
String(d, decimalPlaces), S2Stream(this)
|
||||
{
|
||||
}
|
||||
|
||||
StreamString& operator= (const StreamString& rhs)
|
||||
StreamString& operator=(const StreamString& rhs)
|
||||
{
|
||||
String::operator=(rhs);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (const String& rhs)
|
||||
StreamString& operator=(const String& rhs)
|
||||
{
|
||||
String::operator=(rhs);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (const char* cstr)
|
||||
StreamString& operator=(const char* cstr)
|
||||
{
|
||||
String::operator=(cstr);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (const __FlashStringHelper* str)
|
||||
StreamString& operator=(const __FlashStringHelper* str)
|
||||
{
|
||||
String::operator=(str);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (String&& rval)
|
||||
StreamString& operator=(String&& rval)
|
||||
{
|
||||
String::operator=(rval);
|
||||
resetpp();
|
||||
@ -284,4 +287,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __STREAMSTRING_H
|
||||
#endif // __STREAMSTRING_H
|
||||
|
@ -24,9 +24,8 @@
|
||||
#include "wiring_private.h"
|
||||
#include "PolledTimeout.h"
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include "twi_util.h"
|
||||
#include "ets_sys.h"
|
||||
};
|
||||
@ -57,78 +56,113 @@ static inline __attribute__((always_inline)) bool SCL_READ(const int twi_scl)
|
||||
return (GPI & (1 << twi_scl)) != 0;
|
||||
}
|
||||
|
||||
|
||||
// Implement as a class to reduce code size by allowing access to many global variables with a single base pointer
|
||||
// Implement as a class to reduce code size by allowing access to many global variables with a
|
||||
// single base pointer
|
||||
class Twi
|
||||
{
|
||||
private:
|
||||
unsigned int preferred_si2c_clock = 100000;
|
||||
uint32_t twi_dcount = 18;
|
||||
unsigned char twi_sda = 0;
|
||||
unsigned char twi_scl = 0;
|
||||
unsigned char twi_addr = 0;
|
||||
uint32_t twi_clockStretchLimit = 0;
|
||||
unsigned int preferred_si2c_clock = 100000;
|
||||
uint32_t twi_dcount = 18;
|
||||
unsigned char twi_sda = 0;
|
||||
unsigned char twi_scl = 0;
|
||||
unsigned char twi_addr = 0;
|
||||
uint32_t twi_clockStretchLimit = 0;
|
||||
|
||||
// These are int-wide, even though they could all fit in a byte, to reduce code size and avoid any potential
|
||||
// issues about RmW on packed bytes. The int-wide variations of asm instructions are smaller than the equivalent
|
||||
// byte-wide ones, and since these emums are used everywhere, the difference adds up fast. There is only a single
|
||||
// instance of the class, though, so the extra 12 bytes of RAM used here saves a lot more IRAM.
|
||||
volatile enum { TWIPM_UNKNOWN = 0, TWIPM_IDLE, TWIPM_ADDRESSED, TWIPM_WAIT} twip_mode = TWIPM_IDLE;
|
||||
volatile enum { TWIP_UNKNOWN = 0, TWIP_IDLE, TWIP_START, TWIP_SEND_ACK, TWIP_WAIT_ACK, TWIP_WAIT_STOP, TWIP_SLA_W, TWIP_SLA_R, TWIP_REP_START, TWIP_READ, TWIP_STOP, TWIP_REC_ACK, TWIP_READ_ACK, TWIP_RWAIT_ACK, TWIP_WRITE, TWIP_BUS_ERR } twip_state = TWIP_IDLE;
|
||||
// These are int-wide, even though they could all fit in a byte, to reduce code size and avoid
|
||||
// any potential issues about RmW on packed bytes. The int-wide variations of asm instructions
|
||||
// are smaller than the equivalent byte-wide ones, and since these emums are used everywhere,
|
||||
// the difference adds up fast. There is only a single instance of the class, though, so the
|
||||
// extra 12 bytes of RAM used here saves a lot more IRAM.
|
||||
volatile enum {
|
||||
TWIPM_UNKNOWN = 0,
|
||||
TWIPM_IDLE,
|
||||
TWIPM_ADDRESSED,
|
||||
TWIPM_WAIT
|
||||
} twip_mode
|
||||
= TWIPM_IDLE;
|
||||
volatile enum {
|
||||
TWIP_UNKNOWN = 0,
|
||||
TWIP_IDLE,
|
||||
TWIP_START,
|
||||
TWIP_SEND_ACK,
|
||||
TWIP_WAIT_ACK,
|
||||
TWIP_WAIT_STOP,
|
||||
TWIP_SLA_W,
|
||||
TWIP_SLA_R,
|
||||
TWIP_REP_START,
|
||||
TWIP_READ,
|
||||
TWIP_STOP,
|
||||
TWIP_REC_ACK,
|
||||
TWIP_READ_ACK,
|
||||
TWIP_RWAIT_ACK,
|
||||
TWIP_WRITE,
|
||||
TWIP_BUS_ERR
|
||||
} twip_state
|
||||
= TWIP_IDLE;
|
||||
volatile int twip_status = TW_NO_INFO;
|
||||
volatile int bitCount = 0;
|
||||
volatile int bitCount = 0;
|
||||
|
||||
volatile uint8_t twi_data = 0x00;
|
||||
volatile int twi_ack = 0;
|
||||
volatile int twi_ack_rec = 0;
|
||||
volatile int twi_timeout_ms = 10;
|
||||
volatile uint8_t twi_data = 0x00;
|
||||
volatile int twi_ack = 0;
|
||||
volatile int twi_ack_rec = 0;
|
||||
volatile int twi_timeout_ms = 10;
|
||||
|
||||
volatile enum { TWI_READY = 0, TWI_MRX, TWI_MTX, TWI_SRX, TWI_STX } twi_state = TWI_READY;
|
||||
volatile uint8_t twi_error = 0xFF;
|
||||
volatile uint8_t twi_error = 0xFF;
|
||||
|
||||
uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
|
||||
volatile int twi_txBufferIndex = 0;
|
||||
uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
|
||||
volatile int twi_txBufferIndex = 0;
|
||||
volatile int twi_txBufferLength = 0;
|
||||
|
||||
uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
|
||||
uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
|
||||
volatile int twi_rxBufferIndex = 0;
|
||||
|
||||
void (*twi_onSlaveTransmit)(void);
|
||||
void (*twi_onSlaveReceive)(uint8_t*, size_t);
|
||||
|
||||
// ETS queue/timer interfaces
|
||||
enum { EVENTTASK_QUEUE_SIZE = 1, EVENTTASK_QUEUE_PRIO = 2 };
|
||||
enum { TWI_SIG_RANGE = 0x00000100, TWI_SIG_RX = 0x00000101, TWI_SIG_TX = 0x00000102 };
|
||||
enum
|
||||
{
|
||||
EVENTTASK_QUEUE_SIZE = 1,
|
||||
EVENTTASK_QUEUE_PRIO = 2
|
||||
};
|
||||
enum
|
||||
{
|
||||
TWI_SIG_RANGE = 0x00000100,
|
||||
TWI_SIG_RX = 0x00000101,
|
||||
TWI_SIG_TX = 0x00000102
|
||||
};
|
||||
ETSEvent eventTaskQueue[EVENTTASK_QUEUE_SIZE];
|
||||
ETSTimer timer;
|
||||
|
||||
// Event/IRQ callbacks, so they can't use "this" and need to be static
|
||||
static void IRAM_ATTR onSclChange(void);
|
||||
static void IRAM_ATTR onSdaChange(void);
|
||||
static void eventTask(ETSEvent *e);
|
||||
static void IRAM_ATTR onTimer(void *unused);
|
||||
static void eventTask(ETSEvent* e);
|
||||
static void IRAM_ATTR onTimer(void* unused);
|
||||
|
||||
// Allow not linking in the slave code if there is no call to setAddress
|
||||
bool _slaveEnabled = false;
|
||||
|
||||
// Internal use functions
|
||||
void IRAM_ATTR busywait(unsigned int v);
|
||||
bool write_start(void);
|
||||
bool write_stop(void);
|
||||
bool write_bit(bool bit);
|
||||
bool read_bit(void);
|
||||
bool write_byte(unsigned char byte);
|
||||
unsigned char read_byte(bool nack);
|
||||
bool write_start(void);
|
||||
bool write_stop(void);
|
||||
bool write_bit(bool bit);
|
||||
bool read_bit(void);
|
||||
bool write_byte(unsigned char byte);
|
||||
unsigned char read_byte(bool nack);
|
||||
void IRAM_ATTR onTwipEvent(uint8_t status);
|
||||
|
||||
// Handle the case where a slave needs to stretch the clock with a time-limited busy wait
|
||||
inline void WAIT_CLOCK_STRETCH()
|
||||
{
|
||||
esp8266::polledTimeout::oneShotFastUs timeout(twi_clockStretchLimit);
|
||||
esp8266::polledTimeout::oneShotFastUs timeout(twi_clockStretchLimit);
|
||||
esp8266::polledTimeout::periodicFastUs yieldTimeout(5000);
|
||||
while (!timeout && !SCL_READ(twi_scl)) // outer loop is stretch duration up to stretch limit
|
||||
while (!timeout
|
||||
&& !SCL_READ(twi_scl)) // outer loop is stretch duration up to stretch limit
|
||||
{
|
||||
if (yieldTimeout) // inner loop yields every 5ms
|
||||
if (yieldTimeout) // inner loop yields every 5ms
|
||||
{
|
||||
yield();
|
||||
}
|
||||
@ -139,19 +173,21 @@ private:
|
||||
void twi_scl_valley(void);
|
||||
|
||||
public:
|
||||
void setClock(unsigned int freq);
|
||||
void setClockStretchLimit(uint32_t limit);
|
||||
void init(unsigned char sda, unsigned char scl);
|
||||
void setAddress(uint8_t address);
|
||||
unsigned char writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop);
|
||||
unsigned char readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop);
|
||||
uint8_t status();
|
||||
uint8_t transmit(const uint8_t* data, uint8_t length);
|
||||
void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
|
||||
void attachSlaveTxEvent(void (*function)(void));
|
||||
void setClock(unsigned int freq);
|
||||
void setClockStretchLimit(uint32_t limit);
|
||||
void init(unsigned char sda, unsigned char scl);
|
||||
void setAddress(uint8_t address);
|
||||
unsigned char writeTo(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop);
|
||||
unsigned char readFrom(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop);
|
||||
uint8_t status();
|
||||
uint8_t transmit(const uint8_t* data, uint8_t length);
|
||||
void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
|
||||
void attachSlaveTxEvent(void (*function)(void));
|
||||
void IRAM_ATTR reply(uint8_t ack);
|
||||
void IRAM_ATTR releaseBus(void);
|
||||
void enableSlave();
|
||||
void enableSlave();
|
||||
};
|
||||
|
||||
static Twi twi;
|
||||
@ -176,7 +212,8 @@ void Twi::setClock(unsigned int freq)
|
||||
freq = 400000;
|
||||
}
|
||||
twi_dcount = (500000000 / freq); // half-cycle period in ns
|
||||
twi_dcount = (1000 * (twi_dcount - 1120)) / 62500; // (half cycle - overhead) / busywait loop time
|
||||
twi_dcount
|
||||
= (1000 * (twi_dcount - 1120)) / 62500; // (half cycle - overhead) / busywait loop time
|
||||
|
||||
#else
|
||||
|
||||
@ -185,7 +222,8 @@ void Twi::setClock(unsigned int freq)
|
||||
freq = 800000;
|
||||
}
|
||||
twi_dcount = (500000000 / freq); // half-cycle period in ns
|
||||
twi_dcount = (1000 * (twi_dcount - 560)) / 31250; // (half cycle - overhead) / busywait loop time
|
||||
twi_dcount
|
||||
= (1000 * (twi_dcount - 560)) / 31250; // (half cycle - overhead) / busywait loop time
|
||||
|
||||
#endif
|
||||
}
|
||||
@ -195,8 +233,6 @@ void Twi::setClockStretchLimit(uint32_t limit)
|
||||
twi_clockStretchLimit = limit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Twi::init(unsigned char sda, unsigned char scl)
|
||||
{
|
||||
// set timer function
|
||||
@ -210,7 +246,7 @@ void Twi::init(unsigned char sda, unsigned char scl)
|
||||
pinMode(twi_sda, INPUT_PULLUP);
|
||||
pinMode(twi_scl, INPUT_PULLUP);
|
||||
twi_setClock(preferred_si2c_clock);
|
||||
twi_setClockStretchLimit(150000L); // default value is 150 mS
|
||||
twi_setClockStretchLimit(150000L); // default value is 150 mS
|
||||
}
|
||||
|
||||
void Twi::setAddress(uint8_t address)
|
||||
@ -234,7 +270,8 @@ void IRAM_ATTR Twi::busywait(unsigned int v)
|
||||
unsigned int i;
|
||||
for (i = 0; i < v; i++) // loop time is 5 machine cycles: 31.25ns @ 160MHz, 62.5ns @ 80MHz
|
||||
{
|
||||
__asm__ __volatile__("nop"); // minimum element to keep GCC from optimizing this function out.
|
||||
__asm__ __volatile__(
|
||||
"nop"); // minimum element to keep GCC from optimizing this function out.
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +287,8 @@ bool Twi::write_start(void)
|
||||
// A high-to-low transition on the SDA line while the SCL is high defines a START condition.
|
||||
SDA_LOW(twi_sda);
|
||||
busywait(twi_dcount);
|
||||
// An additional delay between the SCL line high-to-low transition and setting up the SDA line to prevent a STOP condition execute.
|
||||
// An additional delay between the SCL line high-to-low transition and setting up the SDA line
|
||||
// to prevent a STOP condition execute.
|
||||
SCL_LOW(twi_scl);
|
||||
busywait(twi_dcount);
|
||||
return true;
|
||||
@ -308,7 +346,7 @@ bool Twi::write_byte(unsigned char byte)
|
||||
write_bit(byte & 0x80);
|
||||
byte <<= 1;
|
||||
}
|
||||
return !read_bit();//NACK/ACK
|
||||
return !read_bit(); // NACK/ACK
|
||||
}
|
||||
|
||||
unsigned char Twi::read_byte(bool nack)
|
||||
@ -323,12 +361,13 @@ unsigned char Twi::read_byte(bool nack)
|
||||
return byte;
|
||||
}
|
||||
|
||||
unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop)
|
||||
unsigned char Twi::writeTo(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
unsigned int i;
|
||||
if (!write_start())
|
||||
{
|
||||
return 4; //line busy
|
||||
return 4; // line busy
|
||||
}
|
||||
if (!write_byte(((address << 1) | 0) & 0xFF))
|
||||
{
|
||||
@ -336,7 +375,7 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
|
||||
{
|
||||
write_stop();
|
||||
}
|
||||
return 2; //received NACK on transmit of address
|
||||
return 2; // received NACK on transmit of address
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@ -346,7 +385,7 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
|
||||
{
|
||||
write_stop();
|
||||
}
|
||||
return 3;//received NACK on transmit of data
|
||||
return 3; // received NACK on transmit of data
|
||||
}
|
||||
}
|
||||
if (sendStop)
|
||||
@ -368,12 +407,13 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop)
|
||||
unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
unsigned int i;
|
||||
if (!write_start())
|
||||
{
|
||||
return 4; //line busy
|
||||
return 4; // line busy
|
||||
}
|
||||
if (!write_byte(((address << 1) | 1) & 0xFF))
|
||||
{
|
||||
@ -381,7 +421,7 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
|
||||
{
|
||||
write_stop();
|
||||
}
|
||||
return 2;//received NACK on transmit of address
|
||||
return 2; // received NACK on transmit of address
|
||||
}
|
||||
for (i = 0; i < (len - 1); i++)
|
||||
{
|
||||
@ -420,21 +460,25 @@ uint8_t Twi::status()
|
||||
WAIT_CLOCK_STRETCH(); // wait for a slow slave to finish
|
||||
if (!SCL_READ(twi_scl))
|
||||
{
|
||||
return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to recover
|
||||
return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to
|
||||
// recover
|
||||
}
|
||||
|
||||
int clockCount = 20;
|
||||
while (!SDA_READ(twi_sda) && clockCount-- > 0) // if SDA low, read the bits slaves have to sent to a max
|
||||
while (!SDA_READ(twi_sda)
|
||||
&& clockCount-- > 0) // if SDA low, read the bits slaves have to sent to a max
|
||||
{
|
||||
read_bit();
|
||||
if (!SCL_READ(twi_scl))
|
||||
{
|
||||
return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock stretch time
|
||||
return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock
|
||||
// stretch time
|
||||
}
|
||||
}
|
||||
if (!SDA_READ(twi_sda))
|
||||
{
|
||||
return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after n bits.
|
||||
return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after
|
||||
// n bits.
|
||||
}
|
||||
|
||||
return I2C_OK;
|
||||
@ -476,58 +520,57 @@ void Twi::attachSlaveTxEvent(void (*function)(void))
|
||||
twi_onSlaveTransmit = function;
|
||||
}
|
||||
|
||||
// DO NOT INLINE, inlining reply() in combination with compiler optimizations causes function breakup into
|
||||
// parts and the IRAM_ATTR isn't propagated correctly to all parts, which of course causes crashes.
|
||||
// DO NOT INLINE, inlining reply() in combination with compiler optimizations causes function
|
||||
// breakup into parts and the IRAM_ATTR isn't propagated correctly to all parts, which of course
|
||||
// causes crashes.
|
||||
// TODO: test with gcc 9.x and if it still fails, disable optimization with -fdisable-ipa-fnsplit
|
||||
void IRAM_ATTR Twi::reply(uint8_t ack)
|
||||
{
|
||||
// transmit master read ready signal, with or without ack
|
||||
if (ack)
|
||||
{
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
}
|
||||
else
|
||||
{
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 0; // ~_BV(TWEA)
|
||||
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 0; // ~_BV(TWEA)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IRAM_ATTR Twi::releaseBus(void)
|
||||
{
|
||||
// release bus
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
SDA_HIGH(twi.twi_sda);
|
||||
|
||||
// update twi state
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
|
||||
|
||||
void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
{
|
||||
twip_status = status;
|
||||
switch (status)
|
||||
{
|
||||
// Slave Receiver
|
||||
case TW_SR_SLA_ACK: // addressed, returned ack
|
||||
case TW_SR_GCALL_ACK: // addressed generally, returned ack
|
||||
case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_SLA_ACK: // addressed, returned ack
|
||||
case TW_SR_GCALL_ACK: // addressed generally, returned ack
|
||||
case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
|
||||
// enter slave receiver mode
|
||||
twi_state = TWI_SRX;
|
||||
// indicate that rx buffer can be overwritten and ack
|
||||
twi_rxBufferIndex = 0;
|
||||
reply(1);
|
||||
break;
|
||||
case TW_SR_DATA_ACK: // data received, returned ack
|
||||
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
|
||||
case TW_SR_DATA_ACK: // data received, returned ack
|
||||
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
|
||||
// if there is still room in the rx buffer
|
||||
if (twi_rxBufferIndex < TWI_BUFFER_LENGTH)
|
||||
{
|
||||
@ -541,29 +584,29 @@ void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_SR_STOP: // stop or repeated start condition received
|
||||
case TW_SR_STOP: // stop or repeated start condition received
|
||||
// put a null char after data if there's room
|
||||
if (twi_rxBufferIndex < TWI_BUFFER_LENGTH)
|
||||
{
|
||||
twi_rxBuffer[twi_rxBufferIndex] = '\0';
|
||||
}
|
||||
// callback to user-defined callback over event task to allow for non-RAM-residing code
|
||||
//twi_rxBufferLock = true; // This may be necessary
|
||||
// twi_rxBufferLock = true; // This may be necessary
|
||||
ets_post(EVENTTASK_QUEUE_PRIO, TWI_SIG_RX, twi_rxBufferIndex);
|
||||
|
||||
// since we submit rx buffer to "wire" library, we can reset it
|
||||
twi_rxBufferIndex = 0;
|
||||
break;
|
||||
|
||||
case TW_SR_DATA_NACK: // data received, returned nack
|
||||
case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
|
||||
case TW_SR_DATA_NACK: // data received, returned nack
|
||||
case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
|
||||
// nack back at master
|
||||
reply(0);
|
||||
break;
|
||||
|
||||
// Slave Transmitter
|
||||
case TW_ST_SLA_ACK: // addressed, returned ack
|
||||
case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
|
||||
case TW_ST_SLA_ACK: // addressed, returned ack
|
||||
case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
|
||||
// enter slave transmitter mode
|
||||
twi_state = TWI_STX;
|
||||
// ready the tx buffer index for iteration
|
||||
@ -576,7 +619,7 @@ void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
ets_post(EVENTTASK_QUEUE_PRIO, TWI_SIG_TX, 0);
|
||||
break;
|
||||
|
||||
case TW_ST_DATA_ACK: // byte sent, ack returned
|
||||
case TW_ST_DATA_ACK: // byte sent, ack returned
|
||||
// copy data to output register
|
||||
twi_data = twi_txBuffer[twi_txBufferIndex++];
|
||||
|
||||
@ -602,33 +645,32 @@ void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_ST_DATA_NACK: // received nack, we are done
|
||||
case TW_ST_LAST_DATA: // received ack, but we are done already!
|
||||
case TW_ST_DATA_NACK: // received nack, we are done
|
||||
case TW_ST_LAST_DATA: // received ack, but we are done already!
|
||||
// leave slave receiver state
|
||||
releaseBus();
|
||||
break;
|
||||
|
||||
// All
|
||||
case TW_NO_INFO: // no state information
|
||||
case TW_NO_INFO: // no state information
|
||||
break;
|
||||
case TW_BUS_ERROR: // bus error, illegal stop/start
|
||||
case TW_BUS_ERROR: // bus error, illegal stop/start
|
||||
twi_error = TW_BUS_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR Twi::onTimer(void *unused)
|
||||
void IRAM_ATTR Twi::onTimer(void* unused)
|
||||
{
|
||||
(void)unused;
|
||||
twi.releaseBus();
|
||||
twi.onTwipEvent(TW_BUS_ERROR);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_BUS_ERR;
|
||||
}
|
||||
|
||||
void Twi::eventTask(ETSEvent *e)
|
||||
void Twi::eventTask(ETSEvent* e)
|
||||
{
|
||||
|
||||
if (e == NULL)
|
||||
{
|
||||
return;
|
||||
@ -643,7 +685,7 @@ void Twi::eventTask(ETSEvent *e)
|
||||
if (twi.twi_txBufferLength == 0)
|
||||
{
|
||||
twi.twi_txBufferLength = 1;
|
||||
twi.twi_txBuffer[0] = 0x00;
|
||||
twi.twi_txBuffer[0] = 0x00;
|
||||
}
|
||||
|
||||
// Initiate transmission
|
||||
@ -663,7 +705,7 @@ void Twi::eventTask(ETSEvent *e)
|
||||
// compared to the logical-or of all states with the same branch. This removes the need
|
||||
// for a large series of straight-line compares. The biggest win is when multiple states
|
||||
// all have the same branch (onSdaChange), but for others there is some benefit, still.
|
||||
#define S2M(x) (1<<(x))
|
||||
#define S2M(x) (1 << (x))
|
||||
// Shorthand for if the state is any of the or'd bitmask x
|
||||
#define IFSTATE(x) if (twip_state_mask & (x))
|
||||
|
||||
@ -677,7 +719,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
sda = SDA_READ(twi.twi_sda);
|
||||
scl = SCL_READ(twi.twi_scl);
|
||||
|
||||
twi.twip_status = 0xF8; // reset TWI status
|
||||
twi.twip_status = 0xF8; // reset TWI status
|
||||
|
||||
int twip_state_mask = S2M(twi.twip_state);
|
||||
IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SLA_W) | S2M(TWIP_READ))
|
||||
@ -752,13 +794,13 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SDA_HIGH(twi.twi_sda);
|
||||
twi.twip_mode = TWIPM_ADDRESSED;
|
||||
if (!(twi.twi_data & 0x01))
|
||||
{
|
||||
twi.onTwipEvent(TW_SR_SLA_ACK);
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_SLA_W;
|
||||
}
|
||||
else
|
||||
@ -770,18 +812,18 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SDA_HIGH(twi.twi_sda);
|
||||
if (!twi.twi_ack)
|
||||
{
|
||||
twi.onTwipEvent(TW_SR_DATA_NACK);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_WAIT_STOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
twi.onTwipEvent(TW_SR_DATA_ACK);
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_READ;
|
||||
}
|
||||
}
|
||||
@ -837,7 +879,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
else
|
||||
{
|
||||
twi.twi_ack_rec = !sda;
|
||||
twi.twip_state = TWIP_RWAIT_ACK;
|
||||
twi.twip_state = TWIP_RWAIT_ACK;
|
||||
}
|
||||
}
|
||||
else IFSTATE(S2M(TWIP_RWAIT_ACK))
|
||||
@ -848,7 +890,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
if (twi.twi_ack && twi.twi_ack_rec)
|
||||
{
|
||||
twi.onTwipEvent(TW_ST_DATA_ACK);
|
||||
@ -858,7 +900,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
{
|
||||
// we have no more data to send and/or the master doesn't want anymore
|
||||
twi.onTwipEvent(twi.twi_ack_rec ? TW_ST_LAST_DATA : TW_ST_DATA_NACK);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_WAIT_STOP;
|
||||
}
|
||||
}
|
||||
@ -875,7 +917,7 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
scl = SCL_READ(twi.twi_scl);
|
||||
|
||||
int twip_state_mask = S2M(twi.twip_state);
|
||||
if (scl) /* !DATA */
|
||||
if (scl) /* !DATA */
|
||||
{
|
||||
IFSTATE(S2M(TWIP_IDLE))
|
||||
{
|
||||
@ -886,17 +928,19 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
else
|
||||
{
|
||||
// START
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_START;
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
}
|
||||
}
|
||||
else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK) | S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK) | S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
|
||||
else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK)
|
||||
| S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK)
|
||||
| S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
|
||||
{
|
||||
// START or STOP
|
||||
SDA_HIGH(twi.twi_sda); // Should not be necessary
|
||||
SDA_HIGH(twi.twi_sda); // Should not be necessary
|
||||
twi.onTwipEvent(TW_BUS_ERROR);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_BUS_ERR;
|
||||
}
|
||||
else IFSTATE(S2M(TWIP_WAIT_STOP) | S2M(TWIP_BUS_ERR))
|
||||
@ -904,10 +948,10 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
if (sda)
|
||||
{
|
||||
// STOP
|
||||
SCL_LOW(twi.twi_scl); // generates a low SCL pulse after STOP
|
||||
SCL_LOW(twi.twi_scl); // generates a low SCL pulse after STOP
|
||||
ets_timer_disarm(&twi.timer);
|
||||
twi.twip_state = TWIP_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
SCL_HIGH(twi.twi_scl);
|
||||
}
|
||||
else
|
||||
@ -919,9 +963,9 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_REP_START;
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -932,28 +976,28 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
{
|
||||
// inside byte transfer - error
|
||||
twi.onTwipEvent(TW_BUS_ERROR);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_BUS_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// during first bit in byte transfer - ok
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
twi.onTwipEvent(TW_SR_STOP);
|
||||
if (sda)
|
||||
{
|
||||
// STOP
|
||||
ets_timer_disarm(&twi.timer);
|
||||
twi.twip_state = TWIP_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// START
|
||||
twi.bitCount = 8;
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
twi.twip_state = TWIP_REP_START;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -961,8 +1005,8 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
}
|
||||
|
||||
// C wrappers for the object, since API is exposed only as C
|
||||
extern "C" {
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void twi_init(unsigned char sda, unsigned char scl)
|
||||
{
|
||||
return twi.init(sda, scl);
|
||||
@ -983,12 +1027,14 @@ extern "C" {
|
||||
twi.setClockStretchLimit(limit);
|
||||
}
|
||||
|
||||
uint8_t twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop)
|
||||
uint8_t twi_writeTo(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
return twi.writeTo(address, buf, len, sendStop);
|
||||
}
|
||||
|
||||
uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop)
|
||||
uint8_t twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
return twi.readFrom(address, buf, len, sendStop);
|
||||
}
|
||||
@ -998,7 +1044,7 @@ extern "C" {
|
||||
return twi.status();
|
||||
}
|
||||
|
||||
uint8_t twi_transmit(const uint8_t * buf, uint8_t len)
|
||||
uint8_t twi_transmit(const uint8_t* buf, uint8_t len)
|
||||
{
|
||||
return twi.transmit(buf, len);
|
||||
}
|
||||
@ -1027,5 +1073,4 @@ extern "C" {
|
||||
{
|
||||
twi.enableSlave();
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ void __iamslow(const char* what)
|
||||
#endif
|
||||
|
||||
IRAM_ATTR
|
||||
void hexdump(const void *mem, uint32_t len, uint8_t cols)
|
||||
void hexdump(const void* mem, uint32_t len, uint8_t cols)
|
||||
{
|
||||
const char* src = (const char*)mem;
|
||||
os_printf("\n[HEXDUMP] Address: %p len: 0x%X (%d)", src, len, len);
|
||||
|
@ -5,44 +5,54 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef DEBUG_ESP_CORE
|
||||
#define DEBUGV(fmt, ...) ::printf((PGM_P)PSTR(fmt), ## __VA_ARGS__)
|
||||
#define DEBUGV(fmt, ...) ::printf((PGM_P)PSTR(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGV
|
||||
#define DEBUGV(...) do { (void)0; } while (0)
|
||||
#define DEBUGV(...) \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" void hexdump(const void *mem, uint32_t len, uint8_t cols = 16);
|
||||
extern "C" void hexdump(const void* mem, uint32_t len, uint8_t cols = 16);
|
||||
#else
|
||||
void hexdump(const void *mem, uint32_t len, uint8_t cols);
|
||||
void hexdump(const void* mem, uint32_t len, uint8_t cols);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void __unhandled_exception(const char *str) __attribute__((noreturn));
|
||||
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
|
||||
void __unhandled_exception(const char* str) __attribute__((noreturn));
|
||||
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
|
||||
#define panic() __panic_func(PSTR(__FILE__), __LINE__, __func__)
|
||||
|
||||
#ifdef DEBUG_ESP_CORE
|
||||
extern void __iamslow(const char* what);
|
||||
#define IAMSLOW() \
|
||||
do { \
|
||||
static bool once = false; \
|
||||
if (!once) { \
|
||||
once = true; \
|
||||
__iamslow((PGM_P)FPSTR(__FUNCTION__)); \
|
||||
} \
|
||||
extern void __iamslow(const char* what);
|
||||
#define IAMSLOW() \
|
||||
do \
|
||||
{ \
|
||||
static bool once = false; \
|
||||
if (!once) \
|
||||
{ \
|
||||
once = true; \
|
||||
__iamslow((PGM_P)FPSTR(__FUNCTION__)); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define IAMSLOW() do { (void)0; } while (0)
|
||||
#define IAMSLOW() \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif//ARD_DEBUG_H
|
||||
#endif // ARD_DEBUG_H
|
||||
|
Reference in New Issue
Block a user