/*
 * Copyright (C) 2018 Otto-von-Guericke-Universität Magdeburg
 *
 * 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_cc110x
 * @{
 *
 * @file
 * @brief       On-chip settings for the TI CC1100/CC1101 transceiver
 *
 * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
 * @}
 */

#include "cc110x.h"
#include "cc110x_internal.h"

const uint8_t cc110x_conf[CC110X_CONF_SIZE] = {
    /*
     * IOCFG2; default: 0x29 (CHIP_RDYn)
     * Invert GDO2: off,
     * GDO2: Go high when RX data should be read
     *
     * Why not default?
     * GDO2 will be used to be notified about FIFO events (e.g. refilling TX
     * FIFO is needed during transmission, reading from RX FIFO is needed
     * during reception)
     */
    CC110X_GDO_ON_RX_DATA,
    /*
     * IOCFG1; default: 0x2E (3-state)
     * Invert GDO1: off,
     * GDO1: 3-state (required when SPI interface is shared with other devices)
     */
    0x2E,
    /*
     * IOCFG0; default: 0x3F (CLK_XOSC/192)
     * Invert GDO0: off,
     * GDO0: Go high on PLL in lock
     *
     * Why not default?
     * GDO0 will be used to be notified when a packet is coming while in RX
     * mode (will go high during transmission) and when sending is completed
     * while in TX (remains high during transmission and will go back low when
     * done).
     */
    CC110X_GDO_ON_TRANSMISSION,
    /*
     * FIFOTHR; default: 0x07
     * TEST1 = 0x31 and TEST2 = 0x88 when waking up from SLEEP,
     * 0dB RX attenuation,
     * threshold for FIFOs: TX FIFO = 33, RX FIFO = 32
     */
    0x07,
    /*
     * SYNC1, SYNC0; defaults: 0xD3, 0x91
     * Use 0xD3,0x91 as sync word
     */
    0xD3,   /*< SYNC1 */
    0x91,   /*< SYNC0 */
    /*
     * PKTLEN; default: 0xFF
     * Packet length in bytes in fixed length mode, else maximum length
     */
    0xff,
    /*
     * PKTCTRL1; default: 0x04
     * PQT: Accept all sync words, regardless of preamble quality
     * CRC_AUTOFLUSH: Do not auto-flush RX FIFO on incorrect CRC
     * APPEND_STATUS: Do not add 2 bytes of status information in RX FIFO
     * ADDR_CHK:  Filter incoming frames in hardware by address: Only frames
     *            with destination address 0x00 (broadcast) or with with the
     *            layer-2 address of the transceiver are accepted.
     *
     * Why not default?
     * - The RSSI, LQI and CRC info are also available via status registers.
     *   Thus, it is not worth to sacrifice two bytes of RX FIFO for it.
     * - Hardware address filtering could reduce the number IRQs generated
     *   (e.g. a huge frame is dropped before it fully received) which reduces
     *   the system's load. Thus, it is enabled.
     */
    CC110X_PKTCTRL1_VALUE | CC110X_PKTCTRL1_ADDR_MATCH,
    /*
     * PKTCTRL0; default: 0x45
     * Data whitening enabled, use RX/TX FIFOs, CRC enabled,
     * variable packet length
     */
    0x45,
    /*
     * ADDR; default: 0x00
     * Address will overwritten later
     *
     * Why not default?
     * 0x00 is used as broadcast address. Using it would increase chance to
     * receive message during device initialization and thus power consumption.
     */
    0xFF,
    /*
     * CHANNR; default: 0x00
     * Channel number 0 by default
     */
    0x00,
    /*
     * FSCTRL1; default: 0x0C
     * Intermediate frequency: 0x0C * 26MHz / 1024 = 304.7kHz
     *
     * Why not defaults?
     * See MDMCFG4, MDMCFG3
     */
    0x0C,
    /*
     * FSCTRL0; default: 0x00
     * Frequency offset to base frequency: 0kHz
     */
    0x00,
    /*
     * FREQ2, FREQ1, FREQ0; defaults: 0x1E, 0xC4, 0xEC
     * 0x2146E4 * 26MHz / 65536 = 865.1998 MHz (LoRa Channel 10)
     *
     * Why not defaults?
     * Default is 800.000 MHz, which is not in a license free frequency band.
     * Using LoRa channel 10 instead.
     */
    0x21,   /*< FREQ2 */
    0x46,   /*< FREQ1 */
    0xE4,   /*< FREQ0 */
    /*
     * MDMCFG4, MDMCFG3; defaults: 0x8C, 0x22
     * 541.67 kHz channel filter bandwidth,
     * 249.94 kBaud symbol rate
     *
     * Why not defaults?
     * Using 250 kBaud (==> 250kBit/s when 2-FSK/GFSK/ASK) to compete with
     * 802.15.4 in data rate.
     * Using settings listed in Table 7 (pages 12ff in the data sheet):
     *  - 250 kBaud
     *  - GFSK modulation
     *  - 304 kHz IF frequency
     *  - 540 kHz channel filter bandwidth
     *  - 127 kHz deviation
     */
    0x2D,   /*< MDMCFG4 */
    0x3B,   /*< MDMCFG3 */
    /*
     * MDMCFG2; default: 0x02
     * DC blocking filter on,
     * GFSK modulation,
     * no manchester code,
     * Enable RX when 30 bits of the 32 bits sync word are received correctly
     *
     * Why not default?
     * Default expects all 16 bits of a two byte sync word to be correctly
     * received. The data sheet recommends to expect 30 bits of a four byte
     * sync word to be correctly received instead (see section 15 on page 37),
     * so we go for this.
     *
     * Using GFSK instead of 2-FSK reduces the modulated spectrum width and is
     * suggested in Table 7 of the datasheet, see MDMCFG4, MDMCFG3
     */
    0x13,
    /*
     * MDMCFG1, MDMCFG0; defaults: 0x22, 0xF8
     * FEC disabled,
     * 4 preamble bytes,
     * 49.99 kHz distance between channel centre frequencies (closest to 50kHz)
     *
     * Why not defaults?
     * This driver uses an translation layer between physical channels (with
     * 50 kHz distance) and "virtual" channel numbers as seen outside of the
     * driver. This allows to set the frequency in a range of 12.75 MHz with
     * a resolution of 50kHz - this seems to allow to configure all desired
     * channel layouts.
     */
    0x20,   /*< MDMCFG1 */
    0xF8,   /*< MDMCFG0 */
    /*
     * DEVIATN; default: 0x47
     * Deviation of frequency to encode data: +- 126.953kHz in 2-FSK/4-FSK/GFSK
     *
     * Why not default?
     * Higher deviation required for reliable operation at 250 kbps data rate.
     */
    0x62,
    /*
     * MCSM2; default: 0x07
     * No direct RX termination on RSSI measurement (only for ASK/OOK),
     * on RX timeout check for sync word and ignore PQI,
     * no RX timeout
     */
    0x07,
    /*
     * MCSM1; default: 0x30
     * CCA: Enter TX even when channel is detected busy
     * go to idle after packet received,
     * go to idle after packet sent
     *
     * Why not default?
     * By default the transceiver refuses to enter TX when the channel is
     * detected busy. While this is desired, checking if TX was successfully
     * entered is too slow and generated interrupts on the GDO2 pin are easily
     * missed. However, reading the carrier sense value in the PKTSTATUS
     * registers allows to implement this feature in software in a faster
     * way. In addition to not missing GDO2 interrupts, this allows the send
     * function to give feedback right away when the channel is busy.
     */
    0x00,
    /*
     * MCSM0; default: 0x04
     * Auto calibration: Disabled, driver has to manage
     * delay to allow supply voltage to stabilize: 149-155 microseconds
     * pin radio control option is off,
     * oscillator is off in sleep state
     *
     * Why not default?
     * Using 149µs-155µs instead of the default 37µs-39µs as PO_TIMEOUT is
     * encouraged by the data sheet for robust operation
     */
    0x08,
    /*
     * FOCCFG; default: 0x36
     * Freeze frequency offset compensation etc until CS high: yes
     * frequency compensation loop gain before sync word: 3K
     * frequency compensation loop gain after sync word: K/2
     * saturation point for frequency offset compensation: 25% channel bandwidth
     * (incompatible with ASK/OOK)
     */
    0x36,
    /*
     * BSCFG; default: 0x6C
     * Clock recovery feedback loop integral gain before sync word: 2K_i,
     * clock recovery feedback loop proportional gain before sync word: 3K_p,
     * clock recovery feedback loop integral gain after sync word: K_i/2
     * clock recovery feedback loop proportional gain after sync word: K_p,
     * data rate offset compensation: Disabled
     */
    0x6C,
    /*
     * AGCCTRL2; default: 0x03
     * Maximum allowable DVGA gain: No limitation, maximum DVGA gain can be used
     * Maximum allowable LNA + LNA2 gain: No limitation
     * target amplitude from channel filter: 33 dB (default)
     */
    0x03,
    /*
     * AGCCTRL1; default: 0x40
     * LNA priority: Decrease LNA gain first, start decreasing LNA2 gain when
     *               LNA gain reached minimum
     * Relative carrier sense threshold: Disabled
     * Absolute carrier sense threshold: At MAGN_TARGET
     */
    0x40,
    /*
     * AGCCTRL0; default: 0x91
     * HYST_LEVEL: Medium hysteresis, medium asymmetric dead zone, medium gain
     * Adjust gain after how many channel filter samples: After 16 samples
     * Freeze AGC gain: Never; perform gain adjustments as required
     * FILTER_LENGTH:
     *     - 16 channel filter samples when 2-FSK, 4-FSK, or MSK is used
     *     - 8 dB decision baundry when OOK/ASK is used
     */
    0x91,
    /*
     * WOREVT1, WOREVT0, WORCTRL; defaults: 0x87, 0x6B, 0xF8
     * Event0 Timeout: 1.000 seconds
     * RC_PD: 1 (The datasheet is quite cryptic regarding this setting)
     * Event1 Timeout: 1.333ms - 1.385ms (depending on crystal frequency)
     * RC oscillator calibration: Enabled
     * WOR_RES: 0 (Relevant for Event0 resolution and maximum timeout)
     */
    0x87,   /*< WOREVT1 */
    0x6B,   /*< WOREVT0 */
    0xF8,   /*< WORCTRL */
    /*
     * FREND1; default: 0x56
     * LNA_CURRENT: 0b01
     * LNA2MIX_CURRENT: 0b01
     * LODIV_BUF_CURRENT_RW: 0b01
     * MIX_CURRENT: 0b10
     */
    0x56,
    /*
     * FREND0; default: 0x10
     * LODIV_BUF_CURRENT_TX: 0b01
     * Index in PA_POWER table (in 0..7, default is 0): 4 (0dBm)
     *
     * Why not default:
     * Use a reasonable TX power level instead of the lowest.
     */
    0x10 | CC110X_TX_POWER_0_DBM,
    /*
     * FSCAL3, FSCAL2, FSCAL1, FSCAL0; defaults: 0xA9, 0x0A, 0x20, 0x0d
     * These values store calibration date of the CC1100/CC1101 transceiver.
     * Once the transceiver performs a calibration, those registers are updated
     * with the new calibration data. In a "stable" environment (e.g. constant
     * channel/frequency, stable humidity, temperature, supply voltage etc.)
     * the obtained values could be written to the transceiver and calibration
     * could be turned off completely.
     *
     * Fast channel hopping could be performed by obtaining the FSCAL1
     * calibration data for each channel and storing it in the MCU's RAM.
     * The other calibration values is frequency independent according to the
     * data sheet, but depends on temperature etc.
     *
     * Once the FSCAL1 values for each channel are stored, the calibration can
     * be disabled and the stored FSCAL1 data can be uploaded for each channel
     * hop. A re-calibration from time to time is suggested to cope with changes
     * in the environment, e.g. in temperature or supply voltage.
     *
     * Why not defaults?
     * Using "magic" values obtained with SmartRF Studio software for 868 MHz
     * band.
     */
    0xEA,   /*< FSCAL3: charge pump current calibration, frequency independent */
    0x2A,   /*< FSCAL2: VCO current calibration, frequency independent */
    0x00,   /*< FSCAL1: VCO capacitance calibration, frequency dependent */
    0x1F,   /*< FSCAL0: "Magic number", use SmartRF Studio to obtain */
    /*
     * RCCTRL1, RCCTRL0; defaults: 0x41, 0x00
     * RC oscillator configuration, no explanation given in data sheet.
     */
    0x41,   /*< RCCTRL1 */
    0x00,   /*< RCCTRL0 */
};

const uint8_t cc110x_magic_registers[3] = { 0x88, 0x31, 0x09 };
