You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

222 lines
6.8 KiB

/*
* 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 Internal function of kw2xrf driver
*
* @author Johann Fischer <j.fischer@phytec.de>
* @}
*/
#include "panic.h"
#include "kw2xrf.h"
#include "kw2xrf_spi.h"
#include "kw2xrf_reg.h"
#include "kw2xrf_getset.h"
#include "kw2xrf_intern.h"
#include "overwrites.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
void kw2xrf_disable_interrupts(kw2xrf_t *dev)
{
DEBUG("[kw2xrf] disable interrupts\n");
/* Clear and disable all interrupts */
kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL2, 0xff);
int reg = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL3);
reg |= MKW2XDM_PHY_CTRL3_WAKE_MSK | MKW2XDM_PHY_CTRL3_PB_ERR_MSK;
kw2xrf_write_dreg(dev, MKW2XDM_PHY_CTRL3, reg);
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS1, 0x7f);
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS2, 0x03);
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, 0xff);
}
/* update overwrites register */
void kw2xrf_update_overwrites(kw2xrf_t *dev)
{
kw2xrf_write_dreg(dev, MKW2XDM_OVERWRITE_VER, overwrites_direct[0].data);
for (uint8_t i = 0; i < sizeof(overwrites_indirect)/sizeof(overwrites_t); i++) {
kw2xrf_write_iregs(dev, overwrites_indirect[i].address,
(uint8_t *)&(overwrites_indirect[i].data), 1);
}
}
void kw2xrf_set_out_clk(kw2xrf_t *dev)
{
/* TODO: add clock select */
/* check modem's crystal oscillator, CLK_OUT shall be 4MHz */
uint8_t tmp = kw2xrf_read_dreg(dev, MKW2XDM_CLK_OUT_CTRL);
if (tmp != 0x8Bu) {
core_panic(PANIC_GENERAL_ERROR, "Could not start MKW2XD radio transceiver");
}
}
void kw2xrf_set_power_mode(kw2xrf_t *dev, kw2xrf_powermode_t pm)
{
DEBUG("[kw2xrf] set power mode to %d\n", pm);
uint8_t reg = 0;
switch (pm) {
case KW2XRF_HIBERNATE:
/* VREG off, XTAL off, Timer off, Current cons. < 1uA */
reg = 0;
dev->state = NETOPT_STATE_SLEEP;
break;
case KW2XRF_DOZE:
/* VREG off, XTAL on, Timer on/off, Current cons. 600uA */
reg = MKW2XDM_PWR_MODES_XTALEN;
dev->state = NETOPT_STATE_SLEEP;
break;
case KW2XRF_IDLE:
/* VREG on, XTAL on, Timer on, Current cons. 700uA */
reg = MKW2XDM_PWR_MODES_XTALEN | MKW2XDM_PWR_MODES_PMC_MODE;
dev->state = NETOPT_STATE_IDLE;
break;
case KW2XRF_AUTODOZE:
reg = MKW2XDM_PWR_MODES_XTALEN | MKW2XDM_PWR_MODES_AUTODOZE;
dev->state = NETOPT_STATE_IDLE;
break;
}
kw2xrf_write_dreg(dev, MKW2XDM_PWR_MODES, reg);
}
int kw2xrf_can_switch_to_idle(kw2xrf_t *dev)
{
uint8_t state = kw2xrf_read_dreg(dev, MKW2XDM_SEQ_STATE);
uint8_t seq = kw2xrf_read_dreg(dev, MKW2XDM_PHY_CTRL1) & MKW2XDM_PHY_CTRL1_XCVSEQ_MASK;
DEBUG("[kw2xrf] state 0x%0x, seq 0x%0x\n", state, seq);
if ((seq != XCVSEQ_TRANSMIT) && (seq != XCVSEQ_TX_RX)) {
return 1;
}
if (state != 0) {
return 0;
}
return 0;
}
/** Load the timer value (Setting Current Time) */
static void kw2xrf_timer_load(kw2xrf_t *dev, uint32_t value)
{
kw2xrf_write_dregs(dev, MKW2XDM_T1CMP_LSB, (uint8_t *)&value, sizeof(value));
kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TMRLOAD);
}
static uint32_t kw2xrf_timer_get(kw2xrf_t *dev)
{
uint32_t tmp;
kw2xrf_read_dregs(dev, MKW2XDM_EVENT_TIMER_LSB, (uint8_t*)&tmp, sizeof(tmp));
return tmp;
}
/** Set an absolute timeout value for the given compare register of the Event Timer */
static void kw2xrf_timer_set_absolute(kw2xrf_t *dev, uint8_t cmp_reg, uint32_t value)
{
kw2xrf_write_dregs(dev, cmp_reg, (uint8_t *)&value, 3);
}
/** Set an timeout value for the given compare register of the Event Timer */
static void kw2xrf_timer_set(kw2xrf_t *dev, uint8_t cmp_reg, uint32_t timeout)
{
uint32_t now = kw2xrf_timer_get(dev);
DEBUG("[kw2xrf] timer now: %" PRIx32 ", set %" PRIx32 "\n", now, now + timeout);
kw2xrf_timer_set_absolute(dev, cmp_reg, now + timeout);
}
void kw2xrf_timer_init(kw2xrf_t *dev, kw2xrf_timer_timebase_t tb)
{
uint8_t tmp = MKW2XDMI_TMR_PRESCALE_SET(tb);
kw2xrf_write_iregs(dev, MKW2XDMI_TMR_PRESCALE, &tmp, 1);
kw2xrf_timer_load(dev, 0);
}
void kw2xrf_timer2_seq_start_on(kw2xrf_t *dev)
{
kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL1, MKW2XDM_PHY_CTRL1_TMRTRIGEN);
}
void kw2xrf_timer2_seq_start_off(kw2xrf_t *dev)
{
kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL1, MKW2XDM_PHY_CTRL1_TMRTRIGEN);
}
void kw2xrf_timer3_seq_abort_on(kw2xrf_t *dev)
{
kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TC3TMOUT);
}
void kw2xrf_timer3_seq_abort_off(kw2xrf_t *dev)
{
kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL4, MKW2XDM_PHY_CTRL4_TC3TMOUT);
}
void kw2xrf_trigger_tx_ops_enable(kw2xrf_t *dev, uint32_t timeout)
{
kw2xrf_timer_set(dev, MKW2XDM_T2CMP_LSB, timeout);
kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR2CMP_EN);
}
void kw2xrf_trigger_tx_ops_disable(kw2xrf_t *dev)
{
kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR2CMP_EN);
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, MKW2XDM_IRQSTS3_TMR2IRQ);
DEBUG("[kw2xrf] trigger_tx_ops_disable, now: %" PRIx32 "\n", kw2xrf_timer_get(dev));
}
void kw2xrf_abort_rx_ops_enable(kw2xrf_t *dev, uint32_t timeout)
{
kw2xrf_timer_set(dev, MKW2XDM_T3CMP_LSB, timeout);
kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR3CMP_EN);
}
void kw2xrf_abort_rx_ops_disable(kw2xrf_t *dev)
{
kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR3CMP_EN);
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, MKW2XDM_IRQSTS3_TMR3IRQ);
DEBUG("[kw2xrf] abort_rx_ops_disable, now: %" PRIx32 "\n", kw2xrf_timer_get(dev));
}
void kw2xrf_seq_timeout_on(kw2xrf_t *dev, uint32_t timeout)
{
kw2xrf_mask_irq_b(dev);
kw2xrf_timer_set(dev, MKW2XDM_T4CMP_LSB, timeout);
/* enable and clear irq for timer 3 */
uint8_t irqsts3 = kw2xrf_read_dreg(dev, MKW2XDM_IRQSTS3) & 0xf0;
irqsts3 &= ~MKW2XDM_IRQSTS3_TMR4MSK;
irqsts3 |= MKW2XDM_IRQSTS3_TMR4IRQ;
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, irqsts3);
kw2xrf_set_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR4CMP_EN);
kw2xrf_enable_irq_b(dev);
}
void kw2xrf_seq_timeout_off(kw2xrf_t *dev)
{
kw2xrf_clear_dreg_bit(dev, MKW2XDM_PHY_CTRL3, MKW2XDM_PHY_CTRL3_TMR4CMP_EN);
kw2xrf_write_dreg(dev, MKW2XDM_IRQSTS3, MKW2XDM_IRQSTS3_TMR4IRQ);
DEBUG("[kw2xrf] seq_timeout_off, now: %" PRIx32 "\n", kw2xrf_timer_get(dev));
}
uint32_t kw2xrf_get_timestamp(kw2xrf_t *dev)
{
uint32_t tmp;
kw2xrf_read_dregs(dev, MKW2XDM_TIMESTAMP_LSB, (uint8_t*)&tmp, sizeof(tmp));
return tmp;
}