<commit_before>/**
  * cc2420.c - Implementation of cc2420 functions.
  * Copyright (C) 2013 <NAME> <<EMAIL>>
  * Copyright (C) 2014 <NAME> <<EMAIL>>
  *
 * 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.
  */

#include "panic.h"
#include "cc2420.h"
#include "cc2420_spi.h"
#include "cc2420_settings.h"
#include "cc2420_arch.h"
#include "hwtimer.h"
#include "transceiver.h"

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


/* number of attempts to turn on transceiver at startup, before panicking */
#define CC2420_STARTUP_ATTEMPTS  3

/* startup timeout (2 ms) in 16MHz-clock cycles */
#define CC2420_STARTUP_TIMEOUT  32000U


/* implementation of driver's functions */

void cc2420_initialize(void)
{
    cc2420_spi_init();
    hwtimer_wait(CC2420_WAIT_TIME);
    cc2420_reset();

    bool ok = false;
    for (int i = 0; i < CC2420_STARTUP_ATTEMPTS; i++) {
        ok = cc2420_on();
        if (ok) break;
    }
    if (!ok) {
        core_panic(0x2420, "Could not start CC2420 radio transceiver");
    }

    hwtimer_wait(CC2420_WAIT_TIME);

    uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
    reg |= CC2420_ADR_DECODE;                     /* enable auto adress decoding */
    reg |= CC2420_AUTOACK;                        /* enable auto ACK */
    reg |= CC2420_AUTOCRC;                        /* enable auto CRC */
    reg &= ~(CC2420_RES_FRM_MODE);                /* disable reserved frames */
    cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);

    /* Change default values as recomended in the data sheet, */
    /* RX bandpass filter = 1.3uA. */
    reg = cc2420_read_reg(CC2420_REG_RXCTRL1);
    reg |= CC2420_RXBPF_LOCUR;
    cc2420_write_reg(CC2420_REG_RXCTRL1, reg);

    /* Set the FIFOP threshold to maximum. */
    cc2420_write_reg(CC2420_REG_IOCFG0, 127);

    /* Turn off "Security enable" (page 32). */
    reg = cc2420_read_reg(CC2420_REG_SECCTRL0);
    reg &= ~CC2420_RXFIFO_PROTECTION;
    cc2420_write_reg(CC2420_REG_SECCTRL0, reg);

    cc2420_set_tx_power(0);
    cc2420_set_channel(CC2420_DEFAULT_CHANNR);
    cc2420_set_pan(0x1111);
    DEBUG("CC2420 initialized and set to channel %i and pan 0x1111\n", CC2420_DEFAULT_CHANNR);
    cc2420_init_interrupts();
    cc2420_switch_to_rx();
}

void cc2420_init(kernel_pid_t tpid)
{
    transceiver_pid = tpid;
    cc2420_initialize();
}

bool cc2420_on(void)
{
    /* enable transceiver's crystal oscillator */
    cc2420_strobe(CC2420_STROBE_XOSCON);
    /* wait for the oscillator to be stable */
    unsigned int delay_on = 0;
    do {
        delay_on++;
        if (delay_on >= CC2420_STARTUP_TIMEOUT) {
            /* could not start up radio transceiver! */
            return false;
        }
    } while ((cc2420_status_byte() & CC2420_STATUS_XOSC16M_STABLE) == 0);
    hwtimer_wait(CC2420_WAIT_TIME);
    /* discard any potential garbage in TX buffer */
    cc2420_strobe(CC2420_STROBE_FLUSHTX);
    /* switch to RX mode */
    cc2420_switch_to_rx();
    /* OK, radio is on */
    return true;
}

void cc2420_off(void)
{
    /* halt any pending communication... */
    cc2420_strobe(CC2420_STROBE_RFOFF);
    /* ... and put the transceiver in power-down mode */
    cc2420_strobe(CC2420_STROBE_XOSCOFF);
}

bool cc2420_is_on(void)
{
    return ((cc2420_status_byte() & CC2420_STATUS_XOSC16M_STABLE) != 0);
}

void cc2420_switch_to_rx(void)
{
    cc2420_strobe(CC2420_STROBE_RFOFF);
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
    cc2420_strobe(CC2420_STROBE_RXON);
}

void cc2420_rxoverflow_irq(void)
{
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
    /* CC2420 datasheet says to do this twice... */
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
}

void cc2420_rx_irq(void)
{
    cc2420_rx_handler();
}

void cc2420_set_monitor(bool mode)
{
    uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
    if (mode) {
        reg &= ~CC2420_ADR_DECODE;
    } else {
        reg |= CC2420_ADR_DECODE;
    }
    cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);
}

bool cc2420_get_monitor(void)
{
    uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
    return ((reg & CC2420_ADR_DECODE) == 0);
}

int cc2420_set_channel(unsigned int chan)
{
    if (chan < 11 || chan > 26) {
        DEBUG("Invalid channel %i set. Valid channels are 11 through 26\n", chan);
        return -1;
    }
    /*
     * calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50
     */
    uint16_t freq = 357 + (5 * (chan - 11));
    cc2420_write_reg(CC2420_REG_FSCTRL, freq);
    return ((unsigned int) chan);
}

unsigned int cc2420_get_channel(void)
{
    /* undo calculation from cc2420_set_channel() */
    return ((cc2420_read_reg(CC2420_REG_FSCTRL) - 357) / 5) + 11;
}

uint16_t cc2420_set_address(uint16_t addr)
{
    uint8_t buf[2];
    buf[0] = (uint8_t)(addr & 0xFF);
    buf[1] = (uint8_t)(addr >> 8);
    cc2420_write_ram(CC2420_RAM_SHORTADR, buf, 2);
    cc2420_set_address_long(0xFFFF & addr);
    return addr;
}

uint64_t cc2420_set_address_long(uint64_t addr)
{
    uint8_t buf[8];
    buf[0] = (uint8_t)(addr & 0xFF);
    buf[1] = (uint8_t)(addr >> 8);
    buf[2] = (uint8_t)(addr >> 16);
    buf[3] = (uint8_t)(addr >> 24);
    buf[4] = (uint8_t)(addr >> 32);
    buf[5] = (uint8_t)(addr >> 40);
    buf[6] = (uint8_t)(addr >> 48);
    buf[7] = (uint8_t)(addr >> 56);<commit_msg>cc2420: mask FSCTRL register for frequency access<commit_after>/**
  * cc2420.c - Implementation of cc2420 functions.
  * Copyright (C) 2013 <NAME> <<EMAIL>>
  * Copyright (C) 2014 <NAME> <<EMAIL>>
  *
 * 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.
  */

#include "panic.h"
#include "cc2420.h"
#include "cc2420_spi.h"
#include "cc2420_settings.h"
#include "cc2420_arch.h"
#include "hwtimer.h"
#include "transceiver.h"

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


/* number of attempts to turn on transceiver at startup, before panicking */
#define CC2420_STARTUP_ATTEMPTS  3

/* startup timeout (2 ms) in 16MHz-clock cycles */
#define CC2420_STARTUP_TIMEOUT  32000U


/* implementation of driver's functions */

void cc2420_initialize(void)
{
    cc2420_spi_init();
    hwtimer_wait(CC2420_WAIT_TIME);
    cc2420_reset();

    bool ok = false;
    for (int i = 0; i < CC2420_STARTUP_ATTEMPTS; i++) {
        ok = cc2420_on();
        if (ok) break;
    }
    if (!ok) {
        core_panic(0x2420, "Could not start CC2420 radio transceiver");
    }

    hwtimer_wait(CC2420_WAIT_TIME);

    uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
    reg |= CC2420_ADR_DECODE;                     /* enable auto adress decoding */
    reg |= CC2420_AUTOACK;                        /* enable auto ACK */
    reg |= CC2420_AUTOCRC;                        /* enable auto CRC */
    reg &= ~(CC2420_RES_FRM_MODE);                /* disable reserved frames */
    cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);

    /* Change default values as recomended in the data sheet, */
    /* RX bandpass filter = 1.3uA. */
    reg = cc2420_read_reg(CC2420_REG_RXCTRL1);
    reg |= CC2420_RXBPF_LOCUR;
    cc2420_write_reg(CC2420_REG_RXCTRL1, reg);

    /* Set the FIFOP threshold to maximum. */
    cc2420_write_reg(CC2420_REG_IOCFG0, 127);

    /* Turn off "Security enable" (page 32). */
    reg = cc2420_read_reg(CC2420_REG_SECCTRL0);
    reg &= ~CC2420_RXFIFO_PROTECTION;
    cc2420_write_reg(CC2420_REG_SECCTRL0, reg);

    cc2420_set_tx_power(0);
    cc2420_set_channel(CC2420_DEFAULT_CHANNR);
    cc2420_set_pan(0x1111);
    DEBUG("CC2420 initialized and set to channel %i and pan 0x1111\n", CC2420_DEFAULT_CHANNR);
    cc2420_init_interrupts();
    cc2420_switch_to_rx();
}

void cc2420_init(kernel_pid_t tpid)
{
    transceiver_pid = tpid;
    cc2420_initialize();
}

bool cc2420_on(void)
{
    /* enable transceiver's crystal oscillator */
    cc2420_strobe(CC2420_STROBE_XOSCON);
    /* wait for the oscillator to be stable */
    unsigned int delay_on = 0;
    do {
        delay_on++;
        if (delay_on >= CC2420_STARTUP_TIMEOUT) {
            /* could not start up radio transceiver! */
            return false;
        }
    } while ((cc2420_status_byte() & CC2420_STATUS_XOSC16M_STABLE) == 0);
    hwtimer_wait(CC2420_WAIT_TIME);
    /* discard any potential garbage in TX buffer */
    cc2420_strobe(CC2420_STROBE_FLUSHTX);
    /* switch to RX mode */
    cc2420_switch_to_rx();
    /* OK, radio is on */
    return true;
}

void cc2420_off(void)
{
    /* halt any pending communication... */
    cc2420_strobe(CC2420_STROBE_RFOFF);
    /* ... and put the transceiver in power-down mode */
    cc2420_strobe(CC2420_STROBE_XOSCOFF);
}

bool cc2420_is_on(void)
{
    return ((cc2420_status_byte() & CC2420_STATUS_XOSC16M_STABLE) != 0);
}

void cc2420_switch_to_rx(void)
{
    cc2420_strobe(CC2420_STROBE_RFOFF);
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
    cc2420_strobe(CC2420_STROBE_RXON);
}

void cc2420_rxoverflow_irq(void)
{
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
    /* CC2420 datasheet says to do this twice... */
    cc2420_strobe(CC2420_STROBE_FLUSHRX);
}

void cc2420_rx_irq(void)
{
    cc2420_rx_handler();
}

void cc2420_set_monitor(bool mode)
{
    uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
    if (mode) {
        reg &= ~CC2420_ADR_DECODE;
    } else {
        reg |= CC2420_ADR_DECODE;
    }
    cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);
}

bool cc2420_get_monitor(void)
{
    uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
    return ((reg & CC2420_ADR_DECODE) == 0);
}

int cc2420_set_channel(unsigned int chan)
{
    if (chan < 11 || chan > 26) {
        DEBUG("Invalid channel %i set. Valid channels are 11 through 26\n", chan);
        return -1;
    }
    /*
     * calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50
     */
    uint16_t freq= cc2420_read_reg(CC2420_REG_FSCTRL);
    freq &= ~CC2420_FREQ_MASK;
    freq |= (357 + (5 * (chan - 11)));
    cc2420_write_reg(CC2420_REG_FSCTRL, freq);
    return ((unsigned int) chan);
}

unsigned int cc2420_get_channel(void)
{
    /* undo calculation from cc2420_set_channel() */
    return (((cc2420_read_reg(CC2420_REG_FSCTRL) & CC2420_FREQ_MASK) - 357) / 5) + 11;
}

uint16_t cc2420_set_address(uint16_t addr)
{
    uint8_t buf[2];
    buf[0] = (uint8_t)(addr & 0xFF);
    buf[1] = (uint8_t)(addr >> 8);
    cc2420_write_ram(CC2420_RAM_SHORTADR, buf, 2);
    cc2420_set_address_long(0xFFFF & addr);
    return addr;
}

uint64_t cc2420_set_address_long(uint64_t addr)
{
    uint8_t buf[8];
    buf[0] = (uint8_t)(addr & 0xFF);
    buf[1] = (uint8_t)(addr >> 8);
    buf[2] = (uint8_t)(addr >> 16);
    buf[3] = (uint8_t)(addr >> 24);
    buf[4] = (uint8_t)(addr >> 32);
    buf[5] = (uint8_t)(addr >> 40);
    buf[6] = (uint8_t)(addr >> 48);
    buf[7] = (uint8_t)(addr >> 56);
{'fraction_non_alphanumeric': 0.11927107061503417, 'fraction_numerical': 0.10441913439635535, 'mean_word_length': 3.2774746687451284, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5684132', 'n_tokens_mistral': 4951, 'n_tokens_neox': 4312, 'n_words': 862}