/* * 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 * @} */ #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; }