kw2xrf.c 3.6 KB
/*
 * Copyright (C) 2016 PHYTEC Messtechnik GmbH
 *
 * This file is subject to the terms and conditions of the GNU Lesser General
 * Public License v2.1. See the file LICENSE in the top level directory for more
 * details.
 */

/**
 * @ingroup     drivers_kw2xrf
 * @{
 * @file
 * @brief       Basic functionality of kw2xrf driver
 *
 * @author      Johann Fischer <j.fischer@phytec.de>
 * @author      Jonas Remmert <j.remmert@phytec.de>
 * @author      Oliver Hahm <oliver.hahm@inria.fr>
 * @author      Sebastian Meiling <s@mlng.net>
 * @}
 */
#include <stdint.h>
#include <string.h>

#include "log.h"
#include "mutex.h"
#include "msg.h"
#include "periph/gpio.h"
#include "periph/cpuid.h"
#include "net/gnrc.h"
#include "net/ieee802154.h"
#include "luid.h"

#include "kw2xrf.h"
#include "kw2xrf_spi.h"
#include "kw2xrf_reg.h"
#include "kw2xrf_netdev.h"
#include "kw2xrf_getset.h"
#include "kw2xrf_intern.h"

#define ENABLE_DEBUG    (0)
#include "debug.h"

static void kw2xrf_set_address(kw2xrf_t *dev)
{
    DEBUG("[kw2xrf] set MAC addresses\n");
    eui64_t addr_long;
    /* get an 8-byte unique ID to use as hardware address */
    luid_get(addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN);
    /* make sure we mark the address as non-multicast and not globally unique */
    addr_long.uint8[0] &= ~(0x01);
    addr_long.uint8[0] |=  (0x02);
    /* set short and long address */
    kw2xrf_set_addr_long(dev, ntohll(addr_long.uint64.u64));
    kw2xrf_set_addr_short(dev, ntohs(addr_long.uint16[0].u16));
}

void kw2xrf_setup(kw2xrf_t *dev, const kw2xrf_params_t *params)
{
    netdev_t *netdev = (netdev_t *)dev;

    netdev->driver = &kw2xrf_driver;
    /* initialize device descriptor */
    memcpy(&dev->params, params, sizeof(kw2xrf_params_t));
    dev->idle_state = XCVSEQ_RECEIVE;
    dev->state = 0;
    dev->pending_tx = 0;
    kw2xrf_spi_init(dev);
    kw2xrf_set_power_mode(dev, KW2XRF_IDLE);
    DEBUG("[kw2xrf] setup finished\n");
}

int kw2xrf_init(kw2xrf_t *dev, gpio_cb_t cb)
{
    if (dev == NULL) {
        return -ENODEV;
    }

    kw2xrf_set_out_clk(dev);
    kw2xrf_disable_interrupts(dev);
    /* set up GPIO-pin used for IRQ */
    gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_FALLING, cb, dev);

    kw2xrf_abort_sequence(dev);
    kw2xrf_update_overwrites(dev);
    kw2xrf_timer_init(dev, KW2XRF_TIMEBASE_62500HZ);
    DEBUG("[kw2xrf] init finished\n");

    return 0;
}

void kw2xrf_reset_phy(kw2xrf_t *dev)
{
    /* reset options and sequence number */
    dev->netdev.seq = 0;
    dev->netdev.flags = 0;

    /* set default protocol */
#ifdef MODULE_GNRC_SIXLOWPAN
    dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN;
#elif MODULE_GNRC
    dev->netdev.proto = GNRC_NETTYPE_UNDEF;
#endif

    dev->tx_power = KW2XRF_DEFAULT_TX_POWER;
    kw2xrf_set_tx_power(dev, dev->tx_power);

    kw2xrf_set_channel(dev, KW2XRF_DEFAULT_CHANNEL);

    kw2xrf_set_pan(dev, KW2XRF_DEFAULT_PANID);
    kw2xrf_set_address(dev);

    kw2xrf_set_cca_mode(dev, 1);

    kw2xrf_set_rx_watermark(dev, 1);

    kw2xrf_set_option(dev, KW2XRF_OPT_AUTOACK, true);
    kw2xrf_set_option(dev, KW2XRF_OPT_ACK_REQ, true);
    kw2xrf_set_option(dev, KW2XRF_OPT_AUTOCCA, true);

    kw2xrf_set_power_mode(dev, KW2XRF_AUTODOZE);
    kw2xrf_set_sequence(dev, dev->idle_state);

    kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_START, true);
    kw2xrf_set_option(dev, KW2XRF_OPT_TELL_RX_END, true);
    kw2xrf_set_option(dev, KW2XRF_OPT_TELL_TX_END, true);
    kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL2, MKW2XDM_PHY_CTRL2_SEQMSK);

    kw2xrf_enable_irq_b(dev);

    DEBUG("[kw2xrf] init phy and (re)set to channel %d and pan %d.\n",
          KW2XRF_DEFAULT_CHANNEL, KW2XRF_DEFAULT_PANID);
}