<commit_before>/*
 * Copyright (c) 2018 Nuvoton Technology Corp.
 * Copyright (c) 2018 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (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/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 * Description:   NuMaker EMAC
 */

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "cmsis_os.h"

#include "mbed_interface.h"
#include "mbed_assert.h"
#include "netsocket/nsapi_types.h"
#include "mbed_shared_queues.h"

//#define NU_TRACE

#include "numaker_emac_config.h"
#include "numaker_emac.h"
#include "numaker_eth_hal.h"

/********************************************************************************
 *
 ********************************************************************************/
#define NU_BUFF_ALIGNMENT       4
#define PHY_LINKED_STATE        1
#define PHY_UNLINKED_STATE      0
#define PACKET_BUFFER_SIZE      NU_ETH_MAX_FLEN

extern "C" void numaker_eth_rx_next(void);
/* \brief Flags for worker thread */
#define FLAG_TX  1
#define FLAG_RX  2

/** \brief  Driver thread priority */
#define THREAD_PRIORITY (osPriorityNormal)

#define PHY_TASK_PERIOD_MS      200

NUMAKER_EMAC::NUMAKER_EMAC() : thread(0), hwaddr()
{
}

static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb)
{
    osThreadAttr_t attr = {0};
    attr.name = threadName;
    attr.stack_mem  = malloc(stacksize);
    attr.cb_mem  = thread_cb;
    attr.stack_size = stacksize;
    attr.cb_size = sizeof(mbed_rtos_storage_thread_t);
    attr.priority = priority;
    return osThreadNew(thread, arg, &attr);
}

/** \brief Ethernet receive interrupt handler
 *
 *  This function handles the receive interrupt.
 */
void NUMAKER_EMAC::rx_isr()
{
    if (thread) {
        osThreadFlagsSet(thread, FLAG_RX);
    }
}

void NUMAKER_EMAC::tx_isr()
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::ethernet_callback(char event, void *param)
{
    NUMAKER_EMAC *enet = static_cast<NUMAKER_EMAC *>(param);
    switch (event)
    {
      case 'R': //For RX event
        enet->rx_isr();
        break;
      case 'T': //For TX event
        enet->tx_isr();
        break;
      default:
        break;
    }
}

/**
 * In this function, the hardware should be initialized.
 */
bool NUMAKER_EMAC::low_level_init_successful()
{
    /* Init ETH */

    mbed_mac_address((char *)hwaddr);
    printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]);
    /* Enable clock & set EMAC configuration         */
    /* Enable MAC and DMA transmission and reception */
    numaker_eth_init(hwaddr);

    numaker_eth_set_cb(&NUMAKER_EMAC::ethernet_callback, this);

    return true;
}

int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf)
{
    uint16_t len = 0;
    uint8_t *buffer;
    uint32_t bufferoffset = 0;
    uint32_t byteslefttocopy = 0;
    emac_mem_buf_t *q;
    uint32_t payloadoffset = 0;

    /* get received frame */
    if ( numaker_eth_get_rx_buf(&len, &buffer) != 0) {
        return -1;
    }
    byteslefttocopy = len;

    if (len > 0) {
        /* Allocate a memory buffer chain from buffer pool */
        *buf = memory_manager->alloc_pool(len, 0);
    }
    NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, len, *buf));
    if (*buf != NULL) {
        bufferoffset = 0;
        for (q = *buf; q != NULL; q = memory_manager->get_next(q)) {
            byteslefttocopy = memory_manager->get_len(q);
            payloadoffset = 0;
            NU_DEBUGF(("offset=[%d], bytes-to-copy[%d]\r\n",bufferoffset,byteslefttocopy));
            /* Copy data in pbuf */
            memcpy(static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, static_cast<uint8_t *>(buffer) + bufferoffset, byteslefttocopy);

            bufferoffset = bufferoffset + byteslefttocopy;
        }
    }

    return 0;
}

/** \brief  Worker thread.
 *
 * Woken by thread flags to receive packets or clean up transmit
 *
 *  \param[in] pvParameters pointer to the interface data
 */

void NUMAKER_EMAC::thread_function(void* pvParameters)
{
    static struct NUMAKER_EMAC *nu_enet = static_cast<NUMAKER_EMAC *>(pvParameters);

    for (;;) {
        uint32_t flags = osThreadFlagsWait(FLAG_RX, osFlagsWaitAny, osWaitForever);

        if (flags & FLAG_RX) {
            nu_enet->packet_rx();
        }
    }
}

/** \brief  Packet reception task
 *
 * This task is called when a packet is received. It will
 * pass the packet to the LWIP core.
 */
void NUMAKER_EMAC::packet_rx()
{
  /* move received packet into a new buf */
  while (1) {
      emac_mem_buf_t *p = NULL;
      if (low_level_input(&p) < 0) {
          break;
      }
      if (p) {
          NU_DEBUGF(("%s ... p=0x%x\r\n",__FUNCTION__,p));
          emac_link_input_cb(p);
      }
      numaker_eth_rx_next();
  }
  numaker_eth_trigger_rx();

}

/**
 * This function should do the actual transmission of the packet. The packet is
 * contained in the buf that is passed to the function. This buf
 * might be chained.
 *
 * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return true if the packet could be sent
 *         false value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *       strange results. You might consider waiting for space in the DMA queue
 *       to become available since the stack doesn't retry to send a packet
 *       dropped because of memory failure (except for the TCP timers).
 */
bool NUMAKER_EMAC::link_out(emac_mem_buf_t *buf)
{
    bool result;
    emac_mem_buf_t *q;
    uint8_t *buffer = NULL;
    uint32_t framelength = 0;
    uint32_t bufferoffset = 0;
    uint32_t byteslefttocopy = 0;
    uint32_t payloadoffset = 0;

    /* Get exclusive access */
    TXLockMutex.lock();
    buffer = numaker_eth_get_tx_buf();
    NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
    if( buffer == NULL ) goto error;
    /* copy frame from buf to driver buffers */
    for (q = buf; q != NULL; q = memory_manager->get_next(q)) {

        /* Get bytes in current lwIP buffer */
        byteslefttocopy = memory_manager->get_len(q);
        payloadoffset = 0;
        NU_DEBUGF(("offset=%d, bytes-to-copy=%d\r\n",bufferoffset, byteslefttocopy));
        /* Check if the length of data to copy is bigger than Tx buffer size*/
        while ((byteslefttocopy + bufferoffset) > PACKET_BUFFER_SIZE) {
            /* Copy data to Tx buffer*/
            memcpy(static_cast<uint8_t *>(buffer) + bufferoffset, static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, (PACKET_BUFFER_SIZE - bufferoffset));

            /* Point to next descriptor */
            numaker_eth_trigger_tx(PACKET_BUFFER_SIZE, NULL);
            buffer = numaker_eth_get_tx_buf();
            if( buffer == NULL ) goto error;

            byteslefttocopy = byteslefttocopy - (PACKET_BUFFER_SIZE - bufferoffset);
            payloadoffset = payloadoffset + (PACKET_BUFFER_SIZE - bufferoffset);
            framelength = framelength + (PACKET_BUFFER_SIZE - bufferoffset);
            bufferoffset = 0;
        }

        /* Copy the remaining bytes */
        memcpy(static_cast<uint8_t *>(buffer) + bufferoffset, static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy);
        bufferoffset = bufferoffset + byteslefttocopy;
        framelength = framelength + byteslefttocopy;
    }

    /* Prepare transmit descriptors to give to DMA */
    numaker_eth_trigger_tx(framelength, NULL);

    result = true;

error:

    memory_manager->free(buf);

    /* Restore access */
    TXLockMutex.unlock();

    return result;
}

void NUMAKER_EMAC::phy_task()
{

    // Get current status
    int state;
    state = numaker_eth_link_ok();

    if ((state & PHY_LINKED_STATE) && !(phy_state & PHY_LINKED_STATE)) {
        NU_DEBUGF(("Link Up\r\n"));
        if (emac_link_state_cb) emac_link_state_cb(true);
    } else if (!(state & PHY_LINKED_STATE) && (phy_state & PHY_LINKED_STATE)) {
        NU_DEBUGF(("Link Down\r\n"));
        if (emac_link_state_cb) emac_link_state_cb(false);
    }
    phy_state = state;

}

bool NUMAKER_EMAC::power_up()
{
  /* Initialize the hardware */
  if (!low_level_init_successful())
    return false;

  /* Worker thread */
  thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);

  /* PHY monitoring task */
  phy_state = PHY_UNLINKED_STATE;

  phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &NUMAKER_EMAC::phy_task));

  /* Allow the PHY task to detect the initial link state and set up the proper flags */
  osDelay(10);
  numaker_eth_enable_interrupts();
  return true;
}

uint32_t NUMAKER_EMAC::get_mtu_size() const
{
  return NU_ETH_MTU_SIZE;
}

uint32_t NUMAKER_EMAC::get_align_preference() const
{
  return NU_BUFF_ALIGNMENT;
}

void NUMAKER_EMAC::get_ifname(char *name, uint8_t size) const
{
  memcpy(name, NU_ETH_IF_NAME, (size < sizeof(NU_ETH_IF_NAME)) ? size : sizeof(NU_ETH_IF_NAME));
}

uint8_t NUMAKER_EMAC::get_hwaddr_size() const
{
    return NU_HWADDR_SIZE;
}

bool NUMAKER_EMAC::get_hwaddr(uint8_t *addr) const
{
    mbed_mac_address((char *)addr);
    return true;
}

void NUMAKER_EMAC::set_hwaddr(const uint8_t *addr)
{
  memcpy(hwaddr, addr, sizeof hwaddr);
  numaker_set_mac_addr(const_cast<uint8_t*>(addr));
}

void NUMAKER_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
{
  emac_link_input_cb = input_cb;
}

void NUMAKER_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
{
  emac_link_state_cb = state_cb;
}

void NUMAKER_EMAC::add_multicast_group(const uint8_t *addr)
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::remove_multicast_group(const uint8_t *addr)
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::set_all_multicast(bool all)
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::power_down()
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
{
    memory_manager = &mem_mngr;
}

NUMAKER_EMAC &NUMAKER_EMAC::get_instance() {
    static NUMAKER_EMAC emac;
    return emac;
}

// Weak so a module can override
MBED_WEAK EMAC &EMAC::get_default_instance() {
    return NUMAKER_EMAC::get_instance();
}

<commit_msg>Initialized return value of numaker_emac link-out<commit_after>/*
 * Copyright (c) 2018 Nuvoton Technology Corp.
 * Copyright (c) 2018 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (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/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 * Description:   NuMaker EMAC
 */

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "cmsis_os.h"

#include "mbed_interface.h"
#include "mbed_assert.h"
#include "netsocket/nsapi_types.h"
#include "mbed_shared_queues.h"

//#define NU_TRACE

#include "numaker_emac_config.h"
#include "numaker_emac.h"
#include "numaker_eth_hal.h"

/********************************************************************************
 *
 ********************************************************************************/
#define NU_BUFF_ALIGNMENT       4
#define PHY_LINKED_STATE        1
#define PHY_UNLINKED_STATE      0
#define PACKET_BUFFER_SIZE      NU_ETH_MAX_FLEN

extern "C" void numaker_eth_rx_next(void);
/* \brief Flags for worker thread */
#define FLAG_TX  1
#define FLAG_RX  2

/** \brief  Driver thread priority */
#define THREAD_PRIORITY (osPriorityNormal)

#define PHY_TASK_PERIOD_MS      200

NUMAKER_EMAC::NUMAKER_EMAC() : thread(0), hwaddr()
{
}

static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb)
{
    osThreadAttr_t attr = {0};
    attr.name = threadName;
    attr.stack_mem  = malloc(stacksize);
    attr.cb_mem  = thread_cb;
    attr.stack_size = stacksize;
    attr.cb_size = sizeof(mbed_rtos_storage_thread_t);
    attr.priority = priority;
    return osThreadNew(thread, arg, &attr);
}

/** \brief Ethernet receive interrupt handler
 *
 *  This function handles the receive interrupt.
 */
void NUMAKER_EMAC::rx_isr()
{
    if (thread) {
        osThreadFlagsSet(thread, FLAG_RX);
    }
}

void NUMAKER_EMAC::tx_isr()
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::ethernet_callback(char event, void *param)
{
    NUMAKER_EMAC *enet = static_cast<NUMAKER_EMAC *>(param);
    switch (event)
    {
      case 'R': //For RX event
        enet->rx_isr();
        break;
      case 'T': //For TX event
        enet->tx_isr();
        break;
      default:
        break;
    }
}

/**
 * In this function, the hardware should be initialized.
 */
bool NUMAKER_EMAC::low_level_init_successful()
{
    /* Init ETH */

    mbed_mac_address((char *)hwaddr);
    printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]);
    /* Enable clock & set EMAC configuration         */
    /* Enable MAC and DMA transmission and reception */
    numaker_eth_init(hwaddr);

    numaker_eth_set_cb(&NUMAKER_EMAC::ethernet_callback, this);

    return true;
}

int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf)
{
    uint16_t len = 0;
    uint8_t *buffer;
    uint32_t bufferoffset = 0;
    uint32_t byteslefttocopy = 0;
    emac_mem_buf_t *q;
    uint32_t payloadoffset = 0;

    /* get received frame */
    if ( numaker_eth_get_rx_buf(&len, &buffer) != 0) {
        return -1;
    }
    byteslefttocopy = len;

    if (len > 0) {
        /* Allocate a memory buffer chain from buffer pool */
        *buf = memory_manager->alloc_pool(len, 0);
    }
    NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, len, *buf));
    if (*buf != NULL) {
        bufferoffset = 0;
        for (q = *buf; q != NULL; q = memory_manager->get_next(q)) {
            byteslefttocopy = memory_manager->get_len(q);
            payloadoffset = 0;
            NU_DEBUGF(("offset=[%d], bytes-to-copy[%d]\r\n",bufferoffset,byteslefttocopy));
            /* Copy data in pbuf */
            memcpy(static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, static_cast<uint8_t *>(buffer) + bufferoffset, byteslefttocopy);

            bufferoffset = bufferoffset + byteslefttocopy;
        }
    }

    return 0;
}

/** \brief  Worker thread.
 *
 * Woken by thread flags to receive packets or clean up transmit
 *
 *  \param[in] pvParameters pointer to the interface data
 */

void NUMAKER_EMAC::thread_function(void* pvParameters)
{
    static struct NUMAKER_EMAC *nu_enet = static_cast<NUMAKER_EMAC *>(pvParameters);

    for (;;) {
        uint32_t flags = osThreadFlagsWait(FLAG_RX, osFlagsWaitAny, osWaitForever);

        if (flags & FLAG_RX) {
            nu_enet->packet_rx();
        }
    }
}

/** \brief  Packet reception task
 *
 * This task is called when a packet is received. It will
 * pass the packet to the LWIP core.
 */
void NUMAKER_EMAC::packet_rx()
{
  /* move received packet into a new buf */
  while (1) {
      emac_mem_buf_t *p = NULL;
      if (low_level_input(&p) < 0) {
          break;
      }
      if (p) {
          NU_DEBUGF(("%s ... p=0x%x\r\n",__FUNCTION__,p));
          emac_link_input_cb(p);
      }
      numaker_eth_rx_next();
  }
  numaker_eth_trigger_rx();

}

/**
 * This function should do the actual transmission of the packet. The packet is
 * contained in the buf that is passed to the function. This buf
 * might be chained.
 *
 * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return true if the packet could be sent
 *         false value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *       strange results. You might consider waiting for space in the DMA queue
 *       to become available since the stack doesn't retry to send a packet
 *       dropped because of memory failure (except for the TCP timers).
 */
bool NUMAKER_EMAC::link_out(emac_mem_buf_t *buf)
{
    bool result = false;
    emac_mem_buf_t *q;
    uint8_t *buffer = NULL;
    uint32_t framelength = 0;
    uint32_t bufferoffset = 0;
    uint32_t byteslefttocopy = 0;
    uint32_t payloadoffset = 0;

    /* Get exclusive access */
    TXLockMutex.lock();
    buffer = numaker_eth_get_tx_buf();
    NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
    if( buffer == NULL ) goto error;
    /* copy frame from buf to driver buffers */
    for (q = buf; q != NULL; q = memory_manager->get_next(q)) {

        /* Get bytes in current lwIP buffer */
        byteslefttocopy = memory_manager->get_len(q);
        payloadoffset = 0;
        NU_DEBUGF(("offset=%d, bytes-to-copy=%d\r\n",bufferoffset, byteslefttocopy));
        /* Check if the length of data to copy is bigger than Tx buffer size*/
        while ((byteslefttocopy + bufferoffset) > PACKET_BUFFER_SIZE) {
            /* Copy data to Tx buffer*/
            memcpy(static_cast<uint8_t *>(buffer) + bufferoffset, static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, (PACKET_BUFFER_SIZE - bufferoffset));

            /* Point to next descriptor */
            numaker_eth_trigger_tx(PACKET_BUFFER_SIZE, NULL);
            buffer = numaker_eth_get_tx_buf();
            if( buffer == NULL ) goto error;

            byteslefttocopy = byteslefttocopy - (PACKET_BUFFER_SIZE - bufferoffset);
            payloadoffset = payloadoffset + (PACKET_BUFFER_SIZE - bufferoffset);
            framelength = framelength + (PACKET_BUFFER_SIZE - bufferoffset);
            bufferoffset = 0;
        }

        /* Copy the remaining bytes */
        memcpy(static_cast<uint8_t *>(buffer) + bufferoffset, static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy);
        bufferoffset = bufferoffset + byteslefttocopy;
        framelength = framelength + byteslefttocopy;
    }

    /* Prepare transmit descriptors to give to DMA */
    numaker_eth_trigger_tx(framelength, NULL);

    result = true;

error:

    memory_manager->free(buf);

    /* Restore access */
    TXLockMutex.unlock();

    return result;
}

void NUMAKER_EMAC::phy_task()
{

    // Get current status
    int state;
    state = numaker_eth_link_ok();

    if ((state & PHY_LINKED_STATE) && !(phy_state & PHY_LINKED_STATE)) {
        NU_DEBUGF(("Link Up\r\n"));
        if (emac_link_state_cb) emac_link_state_cb(true);
    } else if (!(state & PHY_LINKED_STATE) && (phy_state & PHY_LINKED_STATE)) {
        NU_DEBUGF(("Link Down\r\n"));
        if (emac_link_state_cb) emac_link_state_cb(false);
    }
    phy_state = state;

}

bool NUMAKER_EMAC::power_up()
{
  /* Initialize the hardware */
  if (!low_level_init_successful())
    return false;

  /* Worker thread */
  thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);

  /* PHY monitoring task */
  phy_state = PHY_UNLINKED_STATE;

  phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &NUMAKER_EMAC::phy_task));

  /* Allow the PHY task to detect the initial link state and set up the proper flags */
  osDelay(10);
  numaker_eth_enable_interrupts();
  return true;
}

uint32_t NUMAKER_EMAC::get_mtu_size() const
{
  return NU_ETH_MTU_SIZE;
}

uint32_t NUMAKER_EMAC::get_align_preference() const
{
  return NU_BUFF_ALIGNMENT;
}

void NUMAKER_EMAC::get_ifname(char *name, uint8_t size) const
{
  memcpy(name, NU_ETH_IF_NAME, (size < sizeof(NU_ETH_IF_NAME)) ? size : sizeof(NU_ETH_IF_NAME));
}

uint8_t NUMAKER_EMAC::get_hwaddr_size() const
{
    return NU_HWADDR_SIZE;
}

bool NUMAKER_EMAC::get_hwaddr(uint8_t *addr) const
{
    mbed_mac_address((char *)addr);
    return true;
}

void NUMAKER_EMAC::set_hwaddr(const uint8_t *addr)
{
  memcpy(hwaddr, addr, sizeof hwaddr);
  numaker_set_mac_addr(const_cast<uint8_t*>(addr));
}

void NUMAKER_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
{
  emac_link_input_cb = input_cb;
}

void NUMAKER_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
{
  emac_link_state_cb = state_cb;
}

void NUMAKER_EMAC::add_multicast_group(const uint8_t *addr)
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::remove_multicast_group(const uint8_t *addr)
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::set_all_multicast(bool all)
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::power_down()
{
  /* No-op at this stage */
}

void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
{
    memory_manager = &mem_mngr;
}

NUMAKER_EMAC &NUMAKER_EMAC::get_instance() {
    static NUMAKER_EMAC emac;
    return emac;
}

// Weak so a module can override
MBED_WEAK EMAC &EMAC::get_default_instance() {
    return NUMAKER_EMAC::get_instance();
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#include <unistd.h>
#include <zubax_chibios/sys/sys.h>
#include <uavcan_stm32/uavcan_stm32.hpp>
#include <uavcan/protocol/global_time_sync_slave.hpp>
#include <uavcan/protocol/dynamic_node_id_client.hpp>
#include "board/board.hpp"

namespace app
{
namespace
{

uavcan_stm32::CanInitHelper<128> can;

constexpr unsigned NodePoolSize = 16384;

uavcan::Node<NodePoolSize>& getNode()
{
    static uavcan::Node<NodePoolSize> node(can.driver, uavcan_stm32::SystemClock::instance());
    return node;
}

void init()
{
    board::init();

    int res = 0;
    do
    {
        ::sleep(1);
        ::lowsyslog("CAN auto bit rate detection...\n");

        std::uint32_t bitrate = 0;
        res = can.init([]() { ::usleep(can.getRecommendedListeningDelay().toUSec()); }, bitrate);
        if (res >= 0)
        {
            ::lowsyslog("CAN inited at %u bps\n", unsigned(bitrate));
        }
    }
    while (res < 0);
}

class : public chibios_rt::BaseStaticThread<8192>
{
    void configureNodeInfo()
    {
        getNode().setName("org.uavcan.stm32_test_stm32f107");

        /*
         * Software version
         * TODO: Fill other fields too
         */
        uavcan::protocol::SoftwareVersion swver;

        swver.vcs_commit = GIT_HASH;
        swver.optional_field_flags = swver.OPTIONAL_FIELD_FLAG_VCS_COMMIT;

        getNode().setSoftwareVersion(swver);

        lowsyslog("Git commit hash: 0x%08x\n", GIT_HASH);

        /*
         * Hardware version
         * TODO: Fill other fields too
         */
        uavcan::protocol::HardwareVersion hwver;

        std::uint8_t uid[board::UniqueIDSize] = {};
        board::readUniqueID(uid);
        std::copy(std::begin(uid), std::end(uid), std::begin(hwver.unique_id));

        getNode().setHardwareVersion(hwver);

        lowsyslog("UDID:");
        for (auto b : hwver.unique_id)
        {
            lowsyslog(" %02x", unsigned(b));
        }
        lowsyslog("\n");
    }

    void performDynamicNodeIDAllocation()
    {
        uavcan::DynamicNodeIDClient client(getNode());

        const int client_start_res = client.start(getNode().getHardwareVersion().unique_id);
        if (client_start_res < 0)
        {
            board::die(client_start_res);
        }

        lowsyslog("Waiting for dynamic node ID allocation...\n");
        while (!client.isAllocationComplete())
        {
            const int spin_res = getNode().spin(uavcan::MonotonicDuration::fromMSec(100));
            if (spin_res < 0)
            {
                lowsyslog("Spin failure: %i\n", spin_res);
            }
        }

        lowsyslog("Dynamic node ID %d allocated by %d\n",
                  int(client.getAllocatedNodeID().get()),
                  int(client.getAllocatorNodeID().get()));

        getNode().setNodeID(client.getAllocatedNodeID());
    }

public:
    msg_t main()
    {
        /*
         * Setting up the node parameters
         */
        configureNodeInfo();

        /*
         * Initializing the UAVCAN node
         */
        const int node_init_res = getNode().start();
        if (node_init_res < 0)
        {
            board::die(node_init_res);
        }

        /*
         * Waiting for a dynamic node ID allocation
         */
        performDynamicNodeIDAllocation();

        /*
         * Time synchronizer
         */
        static uavcan::GlobalTimeSyncSlave time_sync_slave(getNode());
        {
            const int res = time_sync_slave.start();
            if (res < 0)
            {
                board::die(res);
            }
        }

        /*
         * Main loop
         */
        lowsyslog("UAVCAN node started\n");
        getNode().setModeOperational();
        while (true)
        {
            const int spin_res = getNode().spin(uavcan::MonotonicDuration::fromMSec(5000));
            if (spin_res < 0)
            {
                lowsyslog("Spin failure: %i\n", spin_res);
            }

            lowsyslog("Time sync master: %u\n", unsigned(time_sync_slave.getMasterNodeID().get()));

            lowsyslog("Memory usage: free=%u used=%u worst=%u\n",
                      getNode().getAllocator().getNumFreeBlocks(),
                      getNode().getAllocator().getNumUsedBlocks(),
                      getNode().getAllocator().getPeakNumUsedBlocks());

            lowsyslog("CAN errors: %lu %lu\n",
                      static_cast<unsigned long>(can.driver.getIface(0)->getErrorCount()),
                      static_cast<unsigned long>(can.driver.getIface(1)->getErrorCount()));

#if !UAVCAN_TINY
            node.getLogger().setLevel(uavcan::protocol::debug::LogLevel::INFO);
            node.logInfo("app", "UTC %* sec, %* corr, %* jumps",
                         uavcan_stm32::clock::getUtc().toMSec() / 1000,
                         uavcan_stm32::clock::getUtcSpeedCorrectionPPM(),
                         uavcan_stm32::clock::getUtcAjdustmentJumpCount());
#endif
        }
        return msg_t();
    }
} uavcan_node_thread;

}
}

int main()
{
    app::init();

    lowsyslog("Starting the UAVCAN thread\n");
    app::uavcan_node_thread.start(LOWPRIO);

    while (true)
    {
        for (int i = 0; i < 200; i++)
        {
            board::setLed(app::can.driver.hadActivity());
            ::usleep(25000);
        }

        const uavcan::UtcTime utc = uavcan_stm32::clock::getUtc();
        lowsyslog("UTC %lu sec   Rate corr: %fPPM   Jumps: %lu   Locked: %i\n",
                  static_cast<unsigned long>(utc.toMSec() / 1000),
                  uavcan_stm32::clock::getUtcRateCorrectionPPM(),
                  uavcan_stm32::clock::getUtcJumpCount(),
                  int(uavcan_stm32::clock::isUtcLocked()));
    }
}
<commit_msg>STM32 example - notes on auto bit rate detection<commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#include <unistd.h>
#include <zubax_chibios/sys/sys.h>
#include <uavcan_stm32/uavcan_stm32.hpp>
#include <uavcan/protocol/global_time_sync_slave.hpp>
#include <uavcan/protocol/dynamic_node_id_client.hpp>
#include "board/board.hpp"

namespace app
{
namespace
{

uavcan_stm32::CanInitHelper<128> can;

constexpr unsigned NodePoolSize = 16384;

uavcan::Node<NodePoolSize>& getNode()
{
    static uavcan::Node<NodePoolSize> node(can.driver, uavcan_stm32::SystemClock::instance());
    return node;
}

void init()
{
    board::init();

    /*
     * CAN auto bit rate detection.
     * Automatic bit rate detection requires that the bus has at least one other CAN node publishing some
     * frames periodically.
     * Auto bit rate detection can be bypassed byif the desired bit rate is passed directly to can.init(), e.g.:
     *   can.init(1000000);
     */
    int res = 0;
    do
    {
        ::sleep(1);
        ::lowsyslog("CAN auto bit rate detection...\n");

        std::uint32_t bitrate = 0;
        res = can.init([]() { ::usleep(can.getRecommendedListeningDelay().toUSec()); }, bitrate);
        if (res >= 0)
        {
            ::lowsyslog("CAN inited at %u bps\n", unsigned(bitrate));
        }
    }
    while (res < 0);
}

class : public chibios_rt::BaseStaticThread<8192>
{
    void configureNodeInfo()
    {
        getNode().setName("org.uavcan.stm32_test_stm32f107");

        /*
         * Software version
         * TODO: Fill other fields too
         */
        uavcan::protocol::SoftwareVersion swver;

        swver.vcs_commit = GIT_HASH;
        swver.optional_field_flags = swver.OPTIONAL_FIELD_FLAG_VCS_COMMIT;

        getNode().setSoftwareVersion(swver);

        lowsyslog("Git commit hash: 0x%08x\n", GIT_HASH);

        /*
         * Hardware version
         * TODO: Fill other fields too
         */
        uavcan::protocol::HardwareVersion hwver;

        std::uint8_t uid[board::UniqueIDSize] = {};
        board::readUniqueID(uid);
        std::copy(std::begin(uid), std::end(uid), std::begin(hwver.unique_id));

        getNode().setHardwareVersion(hwver);

        lowsyslog("UDID:");
        for (auto b : hwver.unique_id)
        {
            lowsyslog(" %02x", unsigned(b));
        }
        lowsyslog("\n");
    }

    void performDynamicNodeIDAllocation()
    {
        uavcan::DynamicNodeIDClient client(getNode());

        const int client_start_res = client.start(getNode().getHardwareVersion().unique_id);
        if (client_start_res < 0)
        {
            board::die(client_start_res);
        }

        lowsyslog("Waiting for dynamic node ID allocation...\n");
        while (!client.isAllocationComplete())
        {
            const int spin_res = getNode().spin(uavcan::MonotonicDuration::fromMSec(100));
            if (spin_res < 0)
            {
                lowsyslog("Spin failure: %i\n", spin_res);
            }
        }

        lowsyslog("Dynamic node ID %d allocated by %d\n",
                  int(client.getAllocatedNodeID().get()),
                  int(client.getAllocatorNodeID().get()));

        getNode().setNodeID(client.getAllocatedNodeID());
    }

public:
    msg_t main()
    {
        /*
         * Setting up the node parameters
         */
        configureNodeInfo();

        /*
         * Initializing the UAVCAN node
         */
        const int node_init_res = getNode().start();
        if (node_init_res < 0)
        {
            board::die(node_init_res);
        }

        /*
         * Waiting for a dynamic node ID allocation
         */
        performDynamicNodeIDAllocation();

        /*
         * Time synchronizer
         */
        static uavcan::GlobalTimeSyncSlave time_sync_slave(getNode());
        {
            const int res = time_sync_slave.start();
            if (res < 0)
            {
                board::die(res);
            }
        }

        /*
         * Main loop
         */
        lowsyslog("UAVCAN node started\n");
        getNode().setModeOperational();
        while (true)
        {
            const int spin_res = getNode().spin(uavcan::MonotonicDuration::fromMSec(5000));
            if (spin_res < 0)
            {
                lowsyslog("Spin failure: %i\n", spin_res);
            }

            lowsyslog("Time sync master: %u\n", unsigned(time_sync_slave.getMasterNodeID().get()));

            lowsyslog("Memory usage: free=%u used=%u worst=%u\n",
                      getNode().getAllocator().getNumFreeBlocks(),
                      getNode().getAllocator().getNumUsedBlocks(),
                      getNode().getAllocator().getPeakNumUsedBlocks());

            lowsyslog("CAN errors: %lu %lu\n",
                      static_cast<unsigned long>(can.driver.getIface(0)->getErrorCount()),
                      static_cast<unsigned long>(can.driver.getIface(1)->getErrorCount()));

#if !UAVCAN_TINY
            node.getLogger().setLevel(uavcan::protocol::debug::LogLevel::INFO);
            node.logInfo("app", "UTC %* sec, %* corr, %* jumps",
                         uavcan_stm32::clock::getUtc().toMSec() / 1000,
                         uavcan_stm32::clock::getUtcSpeedCorrectionPPM(),
                         uavcan_stm32::clock::getUtcAjdustmentJumpCount());
#endif
        }
        return msg_t();
    }
} uavcan_node_thread;

}
}

int main()
{
    app::init();

    lowsyslog("Starting the UAVCAN thread\n");
    app::uavcan_node_thread.start(LOWPRIO);

    while (true)
    {
        for (int i = 0; i < 200; i++)
        {
            board::setLed(app::can.driver.hadActivity());
            ::usleep(25000);
        }

        const uavcan::UtcTime utc = uavcan_stm32::clock::getUtc();
        lowsyslog("UTC %lu sec   Rate corr: %fPPM   Jumps: %lu   Locked: %i\n",
                  static_cast<unsigned long>(utc.toMSec() / 1000),
                  uavcan_stm32::clock::getUtcRateCorrectionPPM(),
                  uavcan_stm32::clock::getUtcJumpCount(),
                  int(uavcan_stm32::clock::isUtcLocked()));
    }
}
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "MultiAppPostprocessorInterpolationTransfer.h"

// MOOSE includes
#include "FEProblem.h"
#include "MooseMesh.h"
#include "MooseTypes.h"
#include "MultiApp.h"

#include "libmesh/meshfree_interpolation.h"
#include "libmesh/numeric_vector.h"
#include "libmesh/system.h"
#include "libmesh/radial_basis_interpolation.h"

registerMooseObject("MooseApp", MultiAppPostprocessorInterpolationTransfer);

InputParameters
MultiAppPostprocessorInterpolationTransfer::validParams()
{
  InputParameters params = MultiAppTransfer::validParams();
  params.addClassDescription("Transfer postprocessor data from sub-application into field data on "
                             "the master application.");
  params.addRequiredParam<AuxVariableName>(
      "variable", "The auxiliary variable to store the transferred values in.");
  params.addRequiredParam<PostprocessorName>("postprocessor", "The Postprocessor to interpolate.");
  params.addParam<unsigned int>(
      "num_points", 3, "The number of nearest points to use for interpolation.");
  params.addParam<Real>(
      "power", 2, "The polynomial power to use for calculation of the decay in the interpolation.");

  MooseEnum interp_type("inverse_distance radial_basis", "inverse_distance");

  params.addParam<MooseEnum>("interp_type", interp_type, "The algorithm to use for interpolation.");

  params.addParam<Real>("radius",
                        -1,
                        "Radius to use for radial_basis interpolation.  If negative "
                        "then the radius is taken as the max distance between "
                        "points.");

  return params;
}

MultiAppPostprocessorInterpolationTransfer::MultiAppPostprocessorInterpolationTransfer(
    const InputParameters & parameters)
  : MultiAppTransfer(parameters),
    _postprocessor(getParam<PostprocessorName>("postprocessor")),
    _to_var_name(getParam<AuxVariableName>("variable")),
    _num_points(getParam<unsigned int>("num_points")),
    _power(getParam<Real>("power")),
    _interp_type(getParam<MooseEnum>("interp_type")),
    _radius(getParam<Real>("radius")),
    _nodal(false)
{
  if (_directions.contains(TO_MULTIAPP))
    mooseError("Can't interpolate to a MultiApp!");

  if (isParamValid("to_multi_app"))
    mooseError("Bi-directional or MultiApp-to-MultiApp transfers are not implemented");

  auto & to_fe_type =
      getFromMultiApp()->problemBase().getStandardVariable(0, _to_var_name).feType();
  if ((to_fe_type.order != CONSTANT || to_fe_type.family != MONOMIAL) &&
      (to_fe_type.order != FIRST || to_fe_type.family != LAGRANGE))
    paramError("variable", "Must be either CONSTANT MONOMIAL or FIRST LAGRANGE");

  _nodal = to_fe_type.family == LAGRANGE;
}

void
MultiAppPostprocessorInterpolationTransfer::execute()
{
  TIME_SECTION("MultiAppPostprocessorInterpolationTransfer::execute()",
               5,
               "Transferring/interpolating postprocessors");

  switch (_current_direction)
  {
    case TO_MULTIAPP:
    {
      mooseError("Interpolation from a variable to a MultiApp postprocessors has not been "
                 "implemented. Use MultiAppVariableValueSamplePostprocessorTransfer!");
      break;
    }
    case FROM_MULTIAPP:
    {
      InverseDistanceInterpolation<LIBMESH_DIM> * idi;

      switch (_interp_type)
      {
        case 0:
          idi = new InverseDistanceInterpolation<LIBMESH_DIM>(_communicator, _num_points, _power);
          break;
        case 1:
          idi = new RadialBasisInterpolation<LIBMESH_DIM>(_communicator, _radius);
          break;
        default:
          mooseError("Unknown interpolation type!");
      }

      std::vector<Point> & src_pts(idi->get_source_points());
      std::vector<Number> & src_vals(idi->get_source_vals());

      std::vector<std::string> field_vars;
      field_vars.push_back(_to_var_name);
      idi->set_field_variables(field_vars);

      {
        for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
        {
          if (getFromMultiApp()->hasLocalApp(i) && getFromMultiApp()->isRootProcessor())
          {
            src_pts.push_back(getFromMultiApp()->position(i));
            src_vals.push_back(getFromMultiApp()->appPostprocessorValue(i, _postprocessor));
          }
        }
      }

      // We have only set local values - prepare for use by gathering remote gata
      idi->prepare_for_use();

      // Loop over the master nodes and set the value of the variable
      {
        System * to_sys = find_sys(getFromMultiApp()->problemBase().es(), _to_var_name);

        unsigned int sys_num = to_sys->number();
        unsigned int var_num = to_sys->variable_number(_to_var_name);

        NumericVector<Real> & solution = *to_sys->solution;

        MooseMesh & mesh = getFromMultiApp()->problemBase().mesh();

        std::vector<std::string> vars;

        vars.push_back(_to_var_name);

        if (_nodal)
        {
          // handle linear lagrange shape functions
          for (const auto & node : as_range(mesh.localNodesBegin(), mesh.localNodesEnd()))
          {
            if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
            {
              std::vector<Point> pts;
              std::vector<Number> vals;

              pts.push_back(*node);
              vals.resize(1);

              idi->interpolate_field_data(vars, pts, vals);

              Real value = vals.front();

              // The zero only works for LAGRANGE!
              dof_id_type dof = node->dof_number(sys_num, var_num, 0);

              solution.set(dof, value);
            }
          }
        }
        else
        {
          // handle constant monomial shape functions
          for (const auto & elem :
               as_range(mesh.getMesh().local_elements_begin(), mesh.getMesh().local_elements_end()))
          {
            // Exclude the elements without dofs
            if (elem->n_dofs(sys_num, var_num) > 0)
            {
              std::vector<Point> pts;
              std::vector<Number> vals;

              pts.push_back(elem->vertex_average());
              vals.resize(1);

              idi->interpolate_field_data(vars, pts, vals);

              Real value = vals.front();

              dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
              solution.set(dof, value);
            }
          }
        }

        solution.close();
      }

      getFromMultiApp()->problemBase().es().update();

      delete idi;

      break;
    }
  }

}
<commit_msg>Update PostprocessorInterpolationTransfer to MooseCoordTransform<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "MultiAppPostprocessorInterpolationTransfer.h"

// MOOSE includes
#include "FEProblem.h"
#include "MooseMesh.h"
#include "MooseTypes.h"
#include "MultiApp.h"
#include "MooseCoordTransform.h"

#include "libmesh/meshfree_interpolation.h"
#include "libmesh/numeric_vector.h"
#include "libmesh/system.h"
#include "libmesh/radial_basis_interpolation.h"

registerMooseObject("MooseApp", MultiAppPostprocessorInterpolationTransfer);

InputParameters
MultiAppPostprocessorInterpolationTransfer::validParams()
{
  InputParameters params = MultiAppTransfer::validParams();
  params.addClassDescription("Transfer postprocessor data from sub-application into field data on "
                             "the master application.");
  params.addRequiredParam<AuxVariableName>(
      "variable", "The auxiliary variable to store the transferred values in.");
  params.addRequiredParam<PostprocessorName>("postprocessor", "The Postprocessor to interpolate.");
  params.addParam<unsigned int>(
      "num_points", 3, "The number of nearest points to use for interpolation.");
  params.addParam<Real>(
      "power", 2, "The polynomial power to use for calculation of the decay in the interpolation.");

  MooseEnum interp_type("inverse_distance radial_basis", "inverse_distance");

  params.addParam<MooseEnum>("interp_type", interp_type, "The algorithm to use for interpolation.");

  params.addParam<Real>("radius",
                        -1,
                        "Radius to use for radial_basis interpolation.  If negative "
                        "then the radius is taken as the max distance between "
                        "points.");

  return params;
}

MultiAppPostprocessorInterpolationTransfer::MultiAppPostprocessorInterpolationTransfer(
    const InputParameters & parameters)
  : MultiAppTransfer(parameters),
    _postprocessor(getParam<PostprocessorName>("postprocessor")),
    _to_var_name(getParam<AuxVariableName>("variable")),
    _num_points(getParam<unsigned int>("num_points")),
    _power(getParam<Real>("power")),
    _interp_type(getParam<MooseEnum>("interp_type")),
    _radius(getParam<Real>("radius")),
    _nodal(false)
{
  if (_directions.contains(TO_MULTIAPP))
    mooseError("Can't interpolate to a MultiApp!");

  if (isParamValid("to_multi_app"))
    mooseError("Bi-directional or MultiApp-to-MultiApp transfers are not implemented");

  auto & to_fe_type =
      getFromMultiApp()->problemBase().getStandardVariable(0, _to_var_name).feType();
  if ((to_fe_type.order != CONSTANT || to_fe_type.family != MONOMIAL) &&
      (to_fe_type.order != FIRST || to_fe_type.family != LAGRANGE))
    paramError("variable", "Must be either CONSTANT MONOMIAL or FIRST LAGRANGE");

  _nodal = to_fe_type.family == LAGRANGE;
}

void
MultiAppPostprocessorInterpolationTransfer::execute()
{
  TIME_SECTION("MultiAppPostprocessorInterpolationTransfer::execute()",
               5,
               "Transferring/interpolating postprocessors");

  getAppInfo();

  switch (_current_direction)
  {
    case TO_MULTIAPP:
    {
      mooseError("Interpolation from a variable to a MultiApp postprocessors has not been "
                 "implemented. Use MultiAppVariableValueSamplePostprocessorTransfer!");
      break;
    }
    case FROM_MULTIAPP:
    {
      InverseDistanceInterpolation<LIBMESH_DIM> * idi;

      switch (_interp_type)
      {
        case 0:
          idi = new InverseDistanceInterpolation<LIBMESH_DIM>(_communicator, _num_points, _power);
          break;
        case 1:
          idi = new RadialBasisInterpolation<LIBMESH_DIM>(_communicator, _radius);
          break;
        default:
          mooseError("Unknown interpolation type!");
      }

      std::vector<Point> & src_pts(idi->get_source_points());
      std::vector<Number> & src_vals(idi->get_source_vals());

      std::vector<std::string> field_vars;
      field_vars.push_back(_to_var_name);
      idi->set_field_variables(field_vars);

      {
        const auto & to_coord_transform = getFromMultiApp()->problemBase().coordTransform();
        for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
        {
          if (getFromMultiApp()->hasLocalApp(i) && getFromMultiApp()->isRootProcessor())
          {
            src_pts.push_back(
                to_coord_transform.mapBack(getFromMultiApp()->transformedPosition(i)));
            src_vals.push_back(getFromMultiApp()->appPostprocessorValue(i, _postprocessor));
          }
        }
      }

      // We have only set local values - prepare for use by gathering remote gata
      idi->prepare_for_use();

      // Loop over the master nodes and set the value of the variable
      {
        System * to_sys = find_sys(getFromMultiApp()->problemBase().es(), _to_var_name);

        unsigned int sys_num = to_sys->number();
        unsigned int var_num = to_sys->variable_number(_to_var_name);

        NumericVector<Real> & solution = *to_sys->solution;

        MooseMesh & mesh = getFromMultiApp()->problemBase().mesh();

        std::vector<std::string> vars;

        vars.push_back(_to_var_name);

        if (_nodal)
        {
          // handle linear lagrange shape functions
          for (const auto & node : as_range(mesh.localNodesBegin(), mesh.localNodesEnd()))
          {
            if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
            {
              std::vector<Point> pts;
              std::vector<Number> vals;

              pts.push_back(*node);
              vals.resize(1);

              idi->interpolate_field_data(vars, pts, vals);

              Real value = vals.front();

              // The zero only works for LAGRANGE!
              dof_id_type dof = node->dof_number(sys_num, var_num, 0);

              solution.set(dof, value);
            }
          }
        }
        else
        {
          // handle constant monomial shape functions
          for (const auto & elem :
               as_range(mesh.getMesh().local_elements_begin(), mesh.getMesh().local_elements_end()))
          {
            // Exclude the elements without dofs
            if (elem->n_dofs(sys_num, var_num) > 0)
            {
              std::vector<Point> pts;
              std::vector<Number> vals;

              pts.push_back(elem->vertex_average());
              vals.resize(1);

              idi->interpolate_field_data(vars, pts, vals);

              Real value = vals.front();

              dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
              solution.set(dof, value);
            }
          }
        }

        solution.close();
      }

      getFromMultiApp()->problemBase().es().update();

      delete idi;

      break;
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>cppcheck: memset on union containing floating pointer number<commit_after><|endoftext|>


<commit_before>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkFlattenableBuffers.h"
#include "SkMaskFilter.h"

class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
                         uint32_t flags);

    // overrides from SkMaskFilter
    virtual SkMask::Format getFormat() SK_OVERRIDE;
    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
                            SkIPoint* margin) SK_OVERRIDE;
    virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
    virtual void setAsABlur(const BlurInfo&) SK_OVERRIDE;
    virtual void computeFastBounds(const SkRect& src, SkRect* dst) SK_OVERRIDE;

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)

protected:
    virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&,
                                           const SkIRect& clipBounds,
                                           NinePatch*) SK_OVERRIDE;

private:
    SkScalar                    fRadius;
    SkBlurMaskFilter::BlurStyle fBlurStyle;
    uint32_t                    fBlurFlags;

    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;

    typedef SkMaskFilter INHERITED;
};

SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
                                       SkBlurMaskFilter::BlurStyle style,
                                       uint32_t flags) {
    // use !(radius > 0) instead of radius <= 0 to reject NaN values
    if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
        || flags > SkBlurMaskFilter::kAll_BlurFlag) {
        return NULL;
    }

    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
}

///////////////////////////////////////////////////////////////////////////////

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
                                           SkBlurMaskFilter::BlurStyle style,
                                           uint32_t flags)
    : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
#if 0
    fGamma = NULL;
    if (gammaScale) {
        fGamma = new U8[256];
        if (gammaScale > 0)
            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
        else
            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
    }
#endif
    SkASSERT(radius >= 0);
    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}

SkMask::Format SkBlurMaskFilterImpl::getFormat() {
    return SkMask::kA8_Format;
}

bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
                                      const SkMatrix& matrix, SkIPoint* margin) {
    SkScalar radius;
    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
        radius = fRadius;
    } else {
        radius = matrix.mapRadius(fRadius);
    }

    // To avoid unseemly allocation requests (esp. for finite platforms like
    // handset) we limit the radius so something manageable. (as opposed to
    // a request like 10,000)
    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
    radius = SkMinScalar(radius, MAX_RADIUS);
    SkBlurMask::Quality blurQuality =
        (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
            SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;

#ifdef SK_BLUR_MASK_SEPARABLE
    return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                            blurQuality, margin);
#else
    return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                            blurQuality, margin);
#endif
}

#include "SkCanvas.h"

static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) {
    rects[0].roundOut(&mask->fBounds);
    mask->fRowBytes = SkAlign4(mask->fBounds.width());
    mask->fFormat = SkMask::kA8_Format;
    size_t size = mask->computeImageSize();
    mask->fImage = SkMask::AllocImage(size);
    if (NULL == mask->fImage) {
        return false;
    }
    sk_bzero(mask->fImage, size);

    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kA8_Config,
                     mask->fBounds.width(), mask->fBounds.height(),
                     mask->fRowBytes);
    bitmap.setPixels(mask->fImage);

    SkCanvas canvas(bitmap);
    canvas.translate(-SkIntToScalar(mask->fBounds.left()),
                     -SkIntToScalar(mask->fBounds.top()));

    SkPaint paint;
    paint.setAntiAlias(true);

    if (1 == count) {
        canvas.drawRect(rects[0], paint);
    } else {
        // todo: do I need a fast way to do this?
        SkPath path;
        path.addRect(rects[0]);
        path.addRect(rects[1]);
        path.setFillType(SkPath::kEvenOdd_FillType);
        canvas.drawPath(path, paint);
    }
    return true;
}

static bool rect_exceeds(const SkRect& r, SkScalar v) {
    return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v ||
           r.width() > v || r.height() > v;
}

SkMaskFilter::FilterReturn
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
                                        const SkMatrix& matrix,
                                        const SkIRect& clipBounds,
                                        NinePatch* patch) {
    if (count < 1 || count > 2) {
        return kUnimplemented_FilterReturn;
    }

    // TODO: take clipBounds into account to limit our coordinates up front
    // for now, just skip too-large src rects (to take the old code path).
    if (rect_exceeds(rects[0], SkIntToScalar(32767))) {
        return kUnimplemented_FilterReturn;
    }

    SkIPoint margin;
    SkMask  srcM, dstM;
    rects[0].roundOut(&srcM.fBounds);
    srcM.fImage = NULL;
    srcM.fFormat = SkMask::kA8_Format;
    srcM.fRowBytes = 0;
    if (!this->filterMask(&dstM, srcM, matrix, &margin)) {
        return kFalse_FilterReturn;
    }

    /*
     *  smallR is the smallest version of 'rect' that will still guarantee that
     *  we get the same blur results on all edges, plus 1 center row/col that is
     *  representative of the extendible/stretchable edges of the ninepatch.
     *  Since our actual edge may be fractional we inset 1 more to be sure we
     *  don't miss any interior blur.
     *  x is an added pixel of blur, and { and } are the (fractional) edge
     *  pixels from the original rect.
     *
     *   x x { x x .... x x } x x
     *
     *  Thus, in this case, we inset by a total of 5 (on each side) beginning
     *  with our outer-rect (dstM.fBounds)
     */
    SkRect smallR[2];
    SkIPoint center;

    // +2 is from +1 for each edge (to account for possible fractional edges
    int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2;
    int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2;
    SkIRect innerIR;

    if (1 == count) {
        innerIR = srcM.fBounds;
        center.set(smallW, smallH);
    } else {
        SkASSERT(2 == count);
        rects[1].roundIn(&innerIR);
        center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
                   smallH + (innerIR.top() - srcM.fBounds.top()));
    }

    // +1 so we get a clean, stretchable, center row/col
    smallW += 1;
    smallH += 1;

    // we want the inset amounts to be integral, so we don't change any
    // fractional phase on the fRight or fBottom of our smallR.
    const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
    const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
    if (dx < 0 || dy < 0) {
        // we're too small, relative to our blur, to break into nine-patch,
        // so we ask to have our normal filterMask() be called.
        return kUnimplemented_FilterReturn;
    }

    smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy);
    SkASSERT(!smallR[0].isEmpty());
    if (2 == count) {
        smallR[1].set(rects[1].left(), rects[1].top(),
                      rects[1].right() - dx, rects[1].bottom() - dy);
        SkASSERT(!smallR[1].isEmpty());
    }

    if (!drawRectsIntoMask(smallR, count, &srcM)) {
        return kFalse_FilterReturn;
    }

    SkAutoMaskFreeImage amf(srcM.fImage);

    if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
        return kFalse_FilterReturn;
    }
    patch->fMask.fBounds.offsetTo(0, 0);
    patch->fOuterRect = dstM.fBounds;
    patch->fCenter = center;
    return kTrue_FilterReturn;
}

void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
    dst->set(src.fLeft - fRadius, src.fTop - fRadius,
             src.fRight + fRadius, src.fBottom + fRadius);
}

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
        : SkMaskFilter(buffer) {
    fRadius = buffer.readScalar();
    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
    fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
    SkASSERT(fRadius >= 0);
    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
}

void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.writeScalar(fRadius);
    buffer.writeInt(fBlurStyle);
    buffer.writeUInt(fBlurFlags);
}

static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
    SkMaskFilter::kNormal_BlurType,
    SkMaskFilter::kSolid_BlurType,
    SkMaskFilter::kOuter_BlurType,
    SkMaskFilter::kInner_BlurType,
};

SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const {
    if (info) {
        info->fRadius = fRadius;
        info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
        info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
    }
    return gBlurStyle2BlurType[fBlurStyle];
}

void SkBlurMaskFilterImpl::setAsABlur(const BlurInfo& info) {
    fRadius = info.fRadius;
    fBlurFlags = (fBlurFlags & ~(SkBlurMaskFilter::kIgnoreTransform_BlurFlag
                                 | SkBlurMaskFilter::kHighQuality_BlurFlag))
            | (info.fIgnoreTransform ? SkBlurMaskFilter::kIgnoreTransform_BlurFlag : 0)
            | (info.fHighQuality ? SkBlurMaskFilter::kHighQuality_BlurFlag : 0);
}

SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
<commit_msg>Turn on the separable blur (release the hounds!).  This will require rebaselines of the following Skia tests:  tilemodes, texteffects, shadows, drawlooper, drawbitmaprect, circles, blurrect_grad, blurrect, blurs, drawbitmapmatrix (max. pixel change in 8888 is 5).<commit_after>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkFlattenableBuffers.h"
#include "SkMaskFilter.h"

class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
                         uint32_t flags);

    // overrides from SkMaskFilter
    virtual SkMask::Format getFormat() SK_OVERRIDE;
    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
                            SkIPoint* margin) SK_OVERRIDE;
    virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
    virtual void setAsABlur(const BlurInfo&) SK_OVERRIDE;
    virtual void computeFastBounds(const SkRect& src, SkRect* dst) SK_OVERRIDE;

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)

protected:
    virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&,
                                           const SkIRect& clipBounds,
                                           NinePatch*) SK_OVERRIDE;

private:
    SkScalar                    fRadius;
    SkBlurMaskFilter::BlurStyle fBlurStyle;
    uint32_t                    fBlurFlags;

    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;

    typedef SkMaskFilter INHERITED;
};

SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
                                       SkBlurMaskFilter::BlurStyle style,
                                       uint32_t flags) {
    // use !(radius > 0) instead of radius <= 0 to reject NaN values
    if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
        || flags > SkBlurMaskFilter::kAll_BlurFlag) {
        return NULL;
    }

    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
}

///////////////////////////////////////////////////////////////////////////////

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
                                           SkBlurMaskFilter::BlurStyle style,
                                           uint32_t flags)
    : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
#if 0
    fGamma = NULL;
    if (gammaScale) {
        fGamma = new U8[256];
        if (gammaScale > 0)
            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
        else
            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
    }
#endif
    SkASSERT(radius >= 0);
    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}

SkMask::Format SkBlurMaskFilterImpl::getFormat() {
    return SkMask::kA8_Format;
}

bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
                                      const SkMatrix& matrix, SkIPoint* margin) {
    SkScalar radius;
    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
        radius = fRadius;
    } else {
        radius = matrix.mapRadius(fRadius);
    }

    // To avoid unseemly allocation requests (esp. for finite platforms like
    // handset) we limit the radius so something manageable. (as opposed to
    // a request like 10,000)
    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
    radius = SkMinScalar(radius, MAX_RADIUS);
    SkBlurMask::Quality blurQuality =
        (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
            SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;

#ifndef SK_DISABLE_SEPARABLE_MASK_BLUR
    return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                            blurQuality, margin);
#else
    return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                            blurQuality, margin);
#endif
}

#include "SkCanvas.h"

static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) {
    rects[0].roundOut(&mask->fBounds);
    mask->fRowBytes = SkAlign4(mask->fBounds.width());
    mask->fFormat = SkMask::kA8_Format;
    size_t size = mask->computeImageSize();
    mask->fImage = SkMask::AllocImage(size);
    if (NULL == mask->fImage) {
        return false;
    }
    sk_bzero(mask->fImage, size);

    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kA8_Config,
                     mask->fBounds.width(), mask->fBounds.height(),
                     mask->fRowBytes);
    bitmap.setPixels(mask->fImage);

    SkCanvas canvas(bitmap);
    canvas.translate(-SkIntToScalar(mask->fBounds.left()),
                     -SkIntToScalar(mask->fBounds.top()));

    SkPaint paint;
    paint.setAntiAlias(true);

    if (1 == count) {
        canvas.drawRect(rects[0], paint);
    } else {
        // todo: do I need a fast way to do this?
        SkPath path;
        path.addRect(rects[0]);
        path.addRect(rects[1]);
        path.setFillType(SkPath::kEvenOdd_FillType);
        canvas.drawPath(path, paint);
    }
    return true;
}

static bool rect_exceeds(const SkRect& r, SkScalar v) {
    return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v ||
           r.width() > v || r.height() > v;
}

SkMaskFilter::FilterReturn
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
                                        const SkMatrix& matrix,
                                        const SkIRect& clipBounds,
                                        NinePatch* patch) {
    if (count < 1 || count > 2) {
        return kUnimplemented_FilterReturn;
    }

    // TODO: take clipBounds into account to limit our coordinates up front
    // for now, just skip too-large src rects (to take the old code path).
    if (rect_exceeds(rects[0], SkIntToScalar(32767))) {
        return kUnimplemented_FilterReturn;
    }

    SkIPoint margin;
    SkMask  srcM, dstM;
    rects[0].roundOut(&srcM.fBounds);
    srcM.fImage = NULL;
    srcM.fFormat = SkMask::kA8_Format;
    srcM.fRowBytes = 0;
    if (!this->filterMask(&dstM, srcM, matrix, &margin)) {
        return kFalse_FilterReturn;
    }

    /*
     *  smallR is the smallest version of 'rect' that will still guarantee that
     *  we get the same blur results on all edges, plus 1 center row/col that is
     *  representative of the extendible/stretchable edges of the ninepatch.
     *  Since our actual edge may be fractional we inset 1 more to be sure we
     *  don't miss any interior blur.
     *  x is an added pixel of blur, and { and } are the (fractional) edge
     *  pixels from the original rect.
     *
     *   x x { x x .... x x } x x
     *
     *  Thus, in this case, we inset by a total of 5 (on each side) beginning
     *  with our outer-rect (dstM.fBounds)
     */
    SkRect smallR[2];
    SkIPoint center;

    // +2 is from +1 for each edge (to account for possible fractional edges
    int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2;
    int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2;
    SkIRect innerIR;

    if (1 == count) {
        innerIR = srcM.fBounds;
        center.set(smallW, smallH);
    } else {
        SkASSERT(2 == count);
        rects[1].roundIn(&innerIR);
        center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
                   smallH + (innerIR.top() - srcM.fBounds.top()));
    }

    // +1 so we get a clean, stretchable, center row/col
    smallW += 1;
    smallH += 1;

    // we want the inset amounts to be integral, so we don't change any
    // fractional phase on the fRight or fBottom of our smallR.
    const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
    const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
    if (dx < 0 || dy < 0) {
        // we're too small, relative to our blur, to break into nine-patch,
        // so we ask to have our normal filterMask() be called.
        return kUnimplemented_FilterReturn;
    }

    smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy);
    SkASSERT(!smallR[0].isEmpty());
    if (2 == count) {
        smallR[1].set(rects[1].left(), rects[1].top(),
                      rects[1].right() - dx, rects[1].bottom() - dy);
        SkASSERT(!smallR[1].isEmpty());
    }

    if (!drawRectsIntoMask(smallR, count, &srcM)) {
        return kFalse_FilterReturn;
    }

    SkAutoMaskFreeImage amf(srcM.fImage);

    if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
        return kFalse_FilterReturn;
    }
    patch->fMask.fBounds.offsetTo(0, 0);
    patch->fOuterRect = dstM.fBounds;
    patch->fCenter = center;
    return kTrue_FilterReturn;
}

void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
    dst->set(src.fLeft - fRadius, src.fTop - fRadius,
             src.fRight + fRadius, src.fBottom + fRadius);
}

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
        : SkMaskFilter(buffer) {
    fRadius = buffer.readScalar();
    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
    fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
    SkASSERT(fRadius >= 0);
    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
}

void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.writeScalar(fRadius);
    buffer.writeInt(fBlurStyle);
    buffer.writeUInt(fBlurFlags);
}

static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
    SkMaskFilter::kNormal_BlurType,
    SkMaskFilter::kSolid_BlurType,
    SkMaskFilter::kOuter_BlurType,
    SkMaskFilter::kInner_BlurType,
};

SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const {
    if (info) {
        info->fRadius = fRadius;
        info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
        info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
    }
    return gBlurStyle2BlurType[fBlurStyle];
}

void SkBlurMaskFilterImpl::setAsABlur(const BlurInfo& info) {
    fRadius = info.fRadius;
    fBlurFlags = (fBlurFlags & ~(SkBlurMaskFilter::kIgnoreTransform_BlurFlag
                                 | SkBlurMaskFilter::kHighQuality_BlurFlag))
            | (info.fIgnoreTransform ? SkBlurMaskFilter::kIgnoreTransform_BlurFlag : 0)
            | (info.fHighQuality ? SkBlurMaskFilter::kHighQuality_BlurFlag : 0);
}

SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
<|endoftext|>


<commit_before>#include "line.h"
#include <QDebug>
#include <QMatrix>
#include <QDebug>

Line::Line(QObject *parent, QColor newColor, unsigned int uiSeed) :
	QObject(parent)
{
	m_seed = uiSeed;
	m_start = QPointF(0, 0);
	m_end = QPointF(0, 10);
	m_color = newColor;
}

Line::Line(const Line & oldLine) :
	QObject(oldLine.parent())
{
	m_seed = oldLine.seed();
	m_start = oldLine.start();
	m_end = oldLine.end();
	m_color = oldLine.color();
}

Line::Line(QObject *parent, QPointF newStart, QPointF newEnd, QColor newColor, unsigned int uiSeed):
	QObject(parent)
{
	m_seed = uiSeed;
	m_start = newStart;
	m_end = newEnd;
	m_color = newColor;
}

QPointF midPoint(QPointF point1, QPointF point2)
{
	QPointF ret((point1.x() + point2.x()) / 2.0, (point1.y() + point2.y()) / 2.0);
	return ret;
}

qreal distance(QPointF point1, QPointF point2)
{
	qreal x = fabs(point2.x() - point1.x());
	qreal y = fabs(point2.y() - point1.y());
	return qSqrt((x * x) + (y * y));
}

qreal rotation(QPointF point1, QPointF point2)
{
	qreal dx = point2.x() - point1.x();
	qreal dy = point2.y() - point1.y();
	return qAtan2(dy, dx) * 180 / 3.141592;
}

QPolygonF Line::polyLine() const
{
	QPolygonF ret;
	ret << QPointF(0, 0) << QPointF(distance(m_start, m_end), 0);
	//ret.setPoints(2, 0, 0, distance(m_start, m_end), 0);
	qsrand(1234);
	qsrand(m_seed);
	for(int i = 0; i < qrand() % 127; i++){
		qrand();
	}
	unsigned int m_iterations = (unsigned int)(qSqrt(distance(m_start, m_end)) / 1.5);
	if(m_iterations > 11)
		m_iterations = 11;
	for(unsigned int i = 0; i < m_iterations; i++){
		for(unsigned int j = ret.count() - 1; j > 0; j--){
			QPointF point1 = ret.at(j - 1);
			QPointF point2 = ret.at(j);
			QPointF point3 = midPoint(point1, point2);
			qreal dist = distance(point1, point2) / 4;
			qreal min = -dist;
			qreal max = dist;
			qreal offset = -1.0 + (((qreal)qrand() / (qreal)RAND_MAX) * 2.0);
			offset *= dist;
			qDebug() << offset;
			point3.setY(point3.y() + offset);
			ret.insert(j, point3);
		}
	}

	QMatrix matrix1;
	QMatrix matrix2;
	qreal rot = rotation(m_start, m_end);
	//qDebug() << rot << "\n" << m_start;
	matrix1.rotate(rot);
	matrix2.translate(m_start.x(), m_start.y());
	ret = matrix1.map(ret);
	ret = matrix2.map(ret);
	return ret;
}

QRectF Line::boundingRect()
{
	return polyLine().boundingRect();
}

void Line::paint(QPainter &painter) const
{
	QPolygonF pLine = polyLine();
	painter.setPen(QPen(m_color, 1, Qt::SolidLine));
	painter.drawPolyline(pLine);
}
<commit_msg>Added a comment for the fix to stop it from always going positive on the first iteration.<commit_after>#include "line.h"
#include <QDebug>
#include <QMatrix>
#include <QDebug>

Line::Line(QObject *parent, QColor newColor, unsigned int uiSeed) :
	QObject(parent)
{
	m_seed = uiSeed;
	m_start = QPointF(0, 0);
	m_end = QPointF(0, 10);
	m_color = newColor;
}

Line::Line(const Line & oldLine) :
	QObject(oldLine.parent())
{
	m_seed = oldLine.seed();
	m_start = oldLine.start();
	m_end = oldLine.end();
	m_color = oldLine.color();
}

Line::Line(QObject *parent, QPointF newStart, QPointF newEnd, QColor newColor, unsigned int uiSeed):
	QObject(parent)
{
	m_seed = uiSeed;
	m_start = newStart;
	m_end = newEnd;
	m_color = newColor;
}

QPointF midPoint(QPointF point1, QPointF point2)
{
	QPointF ret((point1.x() + point2.x()) / 2.0, (point1.y() + point2.y()) / 2.0);
	return ret;
}

qreal distance(QPointF point1, QPointF point2)
{
	qreal x = fabs(point2.x() - point1.x());
	qreal y = fabs(point2.y() - point1.y());
	return qSqrt((x * x) + (y * y));
}

qreal rotation(QPointF point1, QPointF point2)
{
	qreal dx = point2.x() - point1.x();
	qreal dy = point2.y() - point1.y();
	return qAtan2(dy, dx) * 180 / 3.141592;
}

QPolygonF Line::polyLine() const
{
	QPolygonF ret;
	ret << QPointF(0, 0) << QPointF(distance(m_start, m_end), 0);
	//ret.setPoints(2, 0, 0, distance(m_start, m_end), 0);
	qsrand(1234);
	qsrand(m_seed);
	for(int i = 0; i < qrand() % 127; i++){  // don't know why I have to do this, but if I don't the first offset is always positive
		qrand();
	}
	unsigned int m_iterations = (unsigned int)(qSqrt(distance(m_start, m_end)) / 1.5);
	if(m_iterations > 11)
		m_iterations = 11;
	for(unsigned int i = 0; i < m_iterations; i++){
		for(unsigned int j = ret.count() - 1; j > 0; j--){
			QPointF point1 = ret.at(j - 1);
			QPointF point2 = ret.at(j);
			QPointF point3 = midPoint(point1, point2);
			qreal dist = distance(point1, point2) / 4;
			qreal min = -dist;
			qreal max = dist;
			qreal offset = -1.0 + (((qreal)qrand() / (qreal)RAND_MAX) * 2.0);
			offset *= dist;
			qDebug() << offset;
			point3.setY(point3.y() + offset);
			ret.insert(j, point3);
		}
	}

	QMatrix matrix1;
	QMatrix matrix2;
	qreal rot = rotation(m_start, m_end);
	//qDebug() << rot << "\n" << m_start;
	matrix1.rotate(rot);
	matrix2.translate(m_start.x(), m_start.y());
	ret = matrix1.map(ret);
	ret = matrix2.map(ret);
	return ret;
}

QRectF Line::boundingRect()
{
	return polyLine().boundingRect();
}

void Line::paint(QPainter &painter) const
{
	QPolygonF pLine = polyLine();
	painter.setPen(QPen(m_color, 1, Qt::SolidLine));
	painter.drawPolyline(pLine);
}
<|endoftext|>


<commit_before>// Problem1
// hyungyu.jang@lge.com

#if defined _EXTERNAL_DEBUGGER && defined _DEBUG
    #include <code/debug.h>
#else
    #define trace printf
#endif

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <set>

using namespace std;

class Line {
public:
    Line(int f, int t) : from(f), to(t) {}
    int from, to;
    bool operator<(const Line &l) const {return from < l.from;}
};

typedef map<int, set<Line> > map_type;
map<int, set<Line> > hor; // horizontal (y)
map<int, set<Line> > ver; // vertical (x)

const size_t BOARD_SIZE = 10000;
set<int> board[BOARD_SIZE];
set<int> board_temp[BOARD_SIZE];

map <int, int> index_map_x; // index map x (value - index)
map <int, int> index_map_y; // index map y (value - index)

map <int, int> value_map_x; // index map x (index - value)
map <int, int> value_map_y; // index map y (index - value)

int count = 0;
int maxArea = 0;

///////////////////////////////////////////////////////////////////////
int n;

void print(map_type &m) {
    map<int, set<Line> >::iterator i = m.begin();
    for (; i != m.end(); i++) {
        cout << i->first << " : " << endl;

        set<Line>::iterator j = i->second.begin();
        for (; j != i->second.end(); j++) {
            cout << "     " << j->from << " " << j->to << endl;
        }
    }
}

void makeIndexMap(map_type &m, map<int, int> &index_map) {
    map<int, set<Line> >::iterator i = m.begin();
    int index = 0;
    for (; i != m.end(); i++) {
        index_map[i->first] = index++;
    }
}

void makeValueMap(map_type &m, map<int, int> &index_map) {
    map<int, set<Line> >::iterator i = m.begin();
    int index = 0;
    for (; i != m.end(); i++) {
        index_map[index++] = i->first;
    }
}

void getInput() {
    scanf("%d", &n);
    int left, top, right, bottom;
    for (int i = 0; i < n; i++) {
        scanf("%d %d %d %d", &left, &top, &right, &bottom);
        hor[top].insert(Line(left, right));
        hor[bottom].insert(Line(left, right));
        ver[left].insert(Line(top, bottom));
        ver[right].insert(Line(top, bottom));
    }

    makeIndexMap(hor, index_map_y);
    makeIndexMap(ver, index_map_x);

    makeValueMap(hor, value_map_y);
    makeValueMap(ver, value_map_x);
}

int indexof(map<int, int> &index_map, int key) {
    return index_map[key];
}

int valueof(map<int, int> &value_map, int key) {
    return value_map[key];
}

void push_hor(map_type &m) {
    map<int, set<Line> >::iterator i = m.begin();
    int row = 0;
    for (; i != m.end(); i++, row++) {
        set<Line>::iterator j = i->second.begin();
        for (; j != i->second.end(); j++) {
            int from = indexof(index_map_x, j->from);
            int to = indexof(index_map_x, j->to);
            for (int k = from; k <= to; k++) {
                if (board_temp[row].find(k) == board_temp[row].end()) {
                    board_temp[row].insert(k); // vertex
                }
                else {
                    board[row].insert(k); // real point
                }
            }
        }
    }
}

void push_ver(map_type &m) {
    map<int, set<Line> >::iterator i = m.begin();
    int col = 0;
    for (; i != m.end(); i++, col++) {
        set<Line>::iterator j = i->second.begin();
        for (; j != i->second.end(); j++) {
            int from = indexof(index_map_y, j->from);
            int to = indexof(index_map_y, j->to);
            for (int k = from; k <= to; k++)
                if (board_temp[k].find(col) == board_temp[k].end()) {
                    board_temp[k].insert(col); // vertex
                }
                else {
                    board[k].insert(col); // real point
                }
        }
    }
}

int exist(int row, int from, int to) { // return height
    int size = n * 2;
    for (int i = row + 1; i < size; i++) {
        if (board[i].find(from) != board[i].end() && board[i].find(to) != board[i].end()) return i - row;
    }
    return 0; // not exist
}

int simpleArea(int top, int bottom, int left, int right) {
    int width = valueof(value_map_x, right) - valueof(value_map_x, left);
    int height = valueof(value_map_y, bottom) - valueof(value_map_y, top);
    return width * height;
}

int getArea(int top, int bottom, int left, int right) {
    int area = simpleArea(top, bottom, left, right);

    // handle overlaped
    int size = n * 2;
    for (int row = top; row <= bottom ; row++) {
        int from = -1;
        int to;
        set<int>::const_iterator col = board[row].begin();
        for (; col != board[row].end(); col++) {
            if (*col < left) continue;
            if (*col > right) break;

            if (from == -1) from = *col;
            else {
                to = *col;
                if (from == left && to == right) continue;
                int height = exist(row, from, to);
                if (height > 0) {
                    area -= simpleArea(row, row + height, from, to);
                }
            }
        }
    }

    return area;
}

void check() {
    int size = n * 2;
    for (int row = 0; row < size; row++) {
        int from = -1;
        int to;
        set<int>::const_iterator col = board[row].begin();
        for (; col != board[row].end(); col++) {
            if (from == -1) from = *col;
            else { // exist another ?
                to = *col;
                int height = exist(row, from, to);
                if (height > 0) {
                    count++;
                    int area = getArea(row, row + height, from, to);
                    maxArea = max(maxArea, area);
                    from = *col; // init
                }
            }
        }
    }
}

void solve() {
    push_hor(hor);
    push_ver(ver);
    check();

    trace("%d %d\n", count, maxArea);
}

int main(int argc, char *argv[]) {
    getInput();
    solve();
    return 0;
}
<commit_msg>temp (lge code jam 1)<commit_after>// Problem1
// hyungyu.jang@lge.com

#if defined _EXTERNAL_DEBUGGER && defined _DEBUG
    #include <code/debug.h>
#else
    #define trace printf
#endif

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

using namespace std;

class Line {
public:
    Line(int f, int t) : from(f), to(t) {}
    int from, to;
    bool operator<(const Line &l) const {return from < l.from;}
};

typedef map<int, vector<Line> > map_type;
map<int, vector<Line> > hor; // horizontal (y)
map<int, vector<Line> > ver; // vertical (x)

const size_t BOARD_SIZE = 10000;
set<int> board[BOARD_SIZE];
set<int> board_temp[BOARD_SIZE];

map <int, int> index_map_x; // index map x (value - index)
map <int, int> index_map_y; // index map y (value - index)

map <int, int> value_map_x; // index map x (index - value)
map <int, int> value_map_y; // index map y (index - value)

int _count = 0;
int maxArea = 0;

///////////////////////////////////////////////////////////////////////
int n;

void print(map_type &m) {
    map<int, vector<Line> >::iterator i = m.begin();
    for (; i != m.end(); i++) {
        cout << i->first << " : " << endl;

        vector<Line>::iterator j = i->second.begin();
        for (; j != i->second.end(); j++) {
            cout << "     " << j->from << " " << j->to << endl;
        }
    }
}

void makeIndexValueMap(map_type &m, map<int, int> &index_map, map<int, int> &value_map) {
    map<int, vector<Line> >::iterator i = m.begin();
    int index = 0;
    for (; i != m.end(); i++, index++) {
        index_map[i->first] = index;
        value_map[index] = i->first;
    }
}

void getInput() {
    scanf("%d", &n);
    int left, top, right, bottom;
    for (int i = 0; i < n; i++) {
        scanf("%d %d %d %d", &left, &top, &right, &bottom);
        hor[top].push_back(Line(left, right));
        hor[bottom].push_back(Line(left, right));
        ver[left].push_back(Line(top, bottom));
        ver[right].push_back(Line(top, bottom));
    }

    makeIndexValueMap(hor, index_map_y, value_map_y);
    makeIndexValueMap(ver, index_map_x, value_map_x);
}

int indexof(map<int, int> &index_map, int key) {
    return index_map[key];
}

int valueof(map<int, int> &value_map, int key) {
    return value_map[key];
}

void push_hor(map_type &m) {
    map<int, vector<Line> >::iterator i = m.begin();
    int row = 0;
    for (; i != m.end(); i++, row++) {
        vector<Line>::iterator j = i->second.begin();
        for (; j != i->second.end(); j++) {
            int from = indexof(index_map_x, j->from);
            int to = indexof(index_map_x, j->to);
            for (int k = from; k <= to; k++) {
                if (board_temp[row].find(k) == board_temp[row].end()) {
                    board_temp[row].insert(k); // vertex
                }
                else {
                    board[row].insert(k); // real point
                }
            }
        }
    }
}

void push_ver(map_type &m) {
    map<int, vector<Line> >::iterator i = m.begin();
    int col = 0;
    for (; i != m.end(); i++, col++) {
        vector<Line>::iterator j = i->second.begin();
        for (; j != i->second.end(); j++) {
            int from = indexof(index_map_y, j->from);
            int to = indexof(index_map_y, j->to);
            for (int k = from; k <= to; k++)
                if (board_temp[k].find(col) == board_temp[k].end()) {
                    board_temp[k].insert(col); // vertex
                }
                else {
                    board[k].insert(col); // real point
                }
        }
    }
}

int exist(int row, int from, int to) { // return height
    int size = n * 2;
    for (int i = row + 1; i < size; i++) {
        if (board[i].find(from) != board[i].end() && board[i].find(to) != board[i].end()) return i - row;
    }
    return 0; // not exist
}

int simpleArea(int top, int bottom, int left, int right) {
    int width = valueof(value_map_x, right) - valueof(value_map_x, left);
    int height = valueof(value_map_y, bottom) - valueof(value_map_y, top);
    return width * height;
}

int getArea(int top, int bottom, int left, int right) {
    int area = simpleArea(top, bottom, left, right);

    // handle overlaped
    int size = n * 2;
    for (int row = top; row <= bottom ; row++) {
        int from = -1;
        int to;
        set<int>::const_iterator col = board[row].begin();
        for (; col != board[row].end(); col++) {
            if (*col < left) continue;
            if (*col > right) break;

            if (from == -1) from = *col;
            else {
                to = *col;
                if (from == left && to == right) continue;
                int height = exist(row, from, to);
                if (height > 0) {
                    area -= simpleArea(row, row + height, from, to);
                }
            }
        }
    }

    return area;
}

void check() {
    int size = n * 2;
    for (int row = 0; row < size; row++) {
        int from = -1;
        int to;
        set<int>::const_iterator col = board[row].begin();
        for (; col != board[row].end(); col++) {
            if (from == -1) from = *col;
            else { // exist another ?
                to = *col;
                int height = exist(row, from, to);
                if (height > 0) {
                    _count++;
                    int area = getArea(row, row + height, from, to);
                    maxArea = max(maxArea, area);
                    from = *col; // init
                }
            }
        }
    }
}

void solve() {
    push_hor(hor);
    push_ver(ver);
    check();

    trace("%d %d\n", _count, maxArea);
}

int main(int argc, char *argv[]) {
    getInput();
    solve();
    return 0;
}
<|endoftext|>


<commit_before>/* AFE Firmware for smart home devices
  LICENSE: https://github.com/tschaban/AFE-Firmware/blob/master/LICENSE
  DOC: https://www.smartnydom.pl/afe-firmware-pl/ */

#include "AFE-Wifi.h"

AFEWiFi::AFEWiFi() {}

void AFEWiFi::begin(uint8_t mode) {

  AFEDataAccess Data;
  AFEDevice Device;
  networkConfiguration = Data.getNetworkConfiguration();
  // Init LED
  uint8_t systeLedID = Data.getSystemLedID();
  if (systeLedID > 0) {
    Led.begin(systeLedID - 1);
  }

  // Cleaning @TODO is it neded?
  Data = {};
  WiFi.hostname(Device.configuration.name);
  if (mode == MODE_ACCESS_POINT) {
    IPAddress apIP(192, 168, 5, 1);
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    WiFi.softAP(Device.configuration.name);
    dnsServer.setTTL(300);
    dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
    dnsServer.start(53, "www.example.com", apIP);
  } else {
    if (!networkConfiguration.isDHCP) {
      WiFi.config(networkConfiguration.ip, networkConfiguration.gateway,
                  networkConfiguration.subnet);
    }
    WiFi.mode(WIFI_STA);
  }
}

void AFEWiFi::listener() {
  if (!connected()) {
    if (sleepMode) {
      if (millis() - sleepStartTime >=
          networkConfiguration.waitTimeSeries * 1000) {
        sleepMode = false;
      }
    } else {
      if (delayStartTime == 0) {
        delayStartTime = millis();
        if (connections == 0) {
          WiFi.begin(networkConfiguration.ssid, networkConfiguration.password);
          /*
                    Serial << endl << "INFO: Starting establishing WiFi
             connection"; Serial << endl
                           << networkConfiguration.ssid << "@"
                           << networkConfiguration.password;
          */
        }
      }

      if (ledStartTime == 0) {
        ledStartTime = millis();
      }

      if (millis() > ledStartTime + 500) {
        Led.toggle();
        ledStartTime = 0;
      }

      if (millis() >
          delayStartTime + (networkConfiguration.waitTimeConnections * 1000)) {
        connections++;
        /*
                Serial << endl
                       << "INFO: WiFi connection attempt: " << connections + 1
                       << " from " << networkConfiguration.noConnectionAttempts;
                       */
        delayStartTime = 0;
      }

      if (connections == networkConfiguration.noConnectionAttempts) {
        sleepMode = true;
        WiFi.disconnect();
        sleepStartTime = millis();
        delayStartTime = 0;
        ledStartTime = 0;
        Led.off();
        connections = 0;
        /*
                Serial << endl
                       << "WARN: Not able to connect.Going to sleep mode for "
                       << networkConfiguration.waitTimeSeries << "sec.";
                       */
      }
    }
  } else {
    if (connections > 0) {
      connections = 0;
      delayStartTime = 0;
      ledStartTime = 0;
      Led.off();
      /*
      Serial << endl
             << "INFO: Connection established"
             << ", MAC: " << WiFi.macAddress() << ", IP: " << WiFi.localIP();
             */
    }
  }
}

boolean AFEWiFi::connected() {
  if (WiFi.status() == WL_CONNECTED) {
    return true;
  } else {
    return false;
  }
}

void AFEWiFi::APListener() { dnsServer.processNextRequest(); }

boolean AFEWiFi::eventConnected() {
   boolean returnValue = eventConnectionEstablished;
   eventConnectionEstablished = false;
   return returnValue;
}
<commit_msg>defect with event triggering<commit_after>/* AFE Firmware for smart home devices
  LICENSE: https://github.com/tschaban/AFE-Firmware/blob/master/LICENSE
  DOC: https://www.smartnydom.pl/afe-firmware-pl/ */

#include "AFE-Wifi.h"

AFEWiFi::AFEWiFi() {}

void AFEWiFi::begin(uint8_t mode) {

  AFEDataAccess Data;
  AFEDevice Device;
  networkConfiguration = Data.getNetworkConfiguration();
  // Init LED
  uint8_t systeLedID = Data.getSystemLedID();
  if (systeLedID > 0) {
    Led.begin(systeLedID - 1);
  }

  // Cleaning @TODO is it neded?
  Data = {};
  WiFi.hostname(Device.configuration.name);
  if (mode == MODE_ACCESS_POINT) {
    IPAddress apIP(192, 168, 5, 1);
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    WiFi.softAP(Device.configuration.name);
    dnsServer.setTTL(300);
    dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
    dnsServer.start(53, "www.example.com", apIP);
  } else {
    if (!networkConfiguration.isDHCP) {
      WiFi.config(networkConfiguration.ip, networkConfiguration.gateway,
                  networkConfiguration.subnet);
    }
    WiFi.mode(WIFI_STA);
  }
}

void AFEWiFi::listener() {
  if (!connected()) {
    if (sleepMode) {
      if (millis() - sleepStartTime >=
          networkConfiguration.waitTimeSeries * 1000) {
        sleepMode = false;
      }
    } else {
      if (delayStartTime == 0) {
        delayStartTime = millis();
        if (connections == 0) {
          WiFi.begin(networkConfiguration.ssid, networkConfiguration.password);
          /*
                    Serial << endl << "INFO: Starting establishing WiFi
             connection"; Serial << endl
                           << networkConfiguration.ssid << "@"
                           << networkConfiguration.password;
          */
        }
      }

      if (ledStartTime == 0) {
        ledStartTime = millis();
      }

      if (millis() > ledStartTime + 500) {
        Led.toggle();
        ledStartTime = 0;
      }

      if (millis() >
          delayStartTime + (networkConfiguration.waitTimeConnections * 1000)) {
        connections++;
        /*
                Serial << endl
                       << "INFO: WiFi connection attempt: " << connections + 1
                       << " from " << networkConfiguration.noConnectionAttempts;
                       */
        delayStartTime = 0;
      }

      if (connections == networkConfiguration.noConnectionAttempts) {
        sleepMode = true;
        WiFi.disconnect();
        sleepStartTime = millis();
        delayStartTime = 0;
        ledStartTime = 0;
        Led.off();
        connections = 0;
        /*
                Serial << endl
                       << "WARN: Not able to connect.Going to sleep mode for "
                       << networkConfiguration.waitTimeSeries << "sec.";
                       */
      }
    }
  } else {
    if (connections > 0) {
      connections = 0;
      delayStartTime = 0;
      ledStartTime = 0;
      Led.off();
      /*
      Serial << endl
             << "INFO: Connection established"
             << ", MAC: " << WiFi.macAddress() << ", IP: " << WiFi.localIP();
             */
    }
  }
}

boolean AFEWiFi::connected() {
  if (WiFi.status() == WL_CONNECTED) {
    eventConnectionEstablished = true;
    return true;
  } else {
    return false;
  }
}

void AFEWiFi::APListener() { dnsServer.processNextRequest(); }

boolean AFEWiFi::eventConnected() {
  boolean returnValue = eventConnectionEstablished;
  eventConnectionEstablished = false;
  return returnValue;
}
<|endoftext|>