kopia lustrzana https://github.com/bristol-seds/pico-tracker
683 wiersze
19 KiB
C
683 wiersze
19 KiB
C
/*
|
|
* Functions for controlling Si Labs Transceivers
|
|
* Copyright (C) 2014 Richard Meadows <richardeoin>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "samd20.h"
|
|
#include "si_trx.h"
|
|
#include "system/port.h"
|
|
#include "spi_bitbang.h"
|
|
#include "si_trx_defs.h"
|
|
#include "hw_config.h"
|
|
|
|
#define VCXO_FREQUENCY SI4xxx_TCXO_FREQUENCY
|
|
|
|
|
|
/**
|
|
* =============================================================================
|
|
* Helper Functions
|
|
* =============================================================================
|
|
*/
|
|
|
|
/**
|
|
* Convenience transfer functions
|
|
*/
|
|
static void _si_trx_set_property_8(uint8_t group, uint8_t property, uint8_t value)
|
|
{
|
|
uint8_t buffer[5];
|
|
|
|
buffer[0] = SI_CMD_SET_PROPERTY;
|
|
buffer[1] = group;
|
|
buffer[2] = 1;
|
|
buffer[3] = property;
|
|
buffer[4] = value;
|
|
|
|
_si_trx_transfer(5, 0, buffer);
|
|
}
|
|
static void _si_trx_set_property_16(uint8_t group, uint8_t property, uint16_t value)
|
|
{
|
|
uint8_t buffer[6];
|
|
|
|
buffer[0] = SI_CMD_SET_PROPERTY;
|
|
buffer[1] = group;
|
|
buffer[2] = 2;
|
|
buffer[3] = property;
|
|
buffer[4] = (value >> 8);
|
|
buffer[5] = (value);
|
|
|
|
_si_trx_transfer(6, 0, buffer);
|
|
}
|
|
static void _si_trx_set_property_24(uint8_t group, uint8_t property, uint32_t value)
|
|
{
|
|
uint8_t buffer[8];
|
|
|
|
buffer[0] = SI_CMD_SET_PROPERTY;
|
|
buffer[1] = group;
|
|
buffer[2] = 3;
|
|
buffer[3] = property;
|
|
buffer[4] = (value >> 16);
|
|
buffer[5] = (value >> 8);
|
|
buffer[6] = (value);
|
|
|
|
_si_trx_transfer(7, 0, buffer);
|
|
}
|
|
static void _si_trx_set_property_32(uint8_t group, uint8_t property, uint32_t value)
|
|
{
|
|
uint8_t buffer[8];
|
|
|
|
buffer[0] = SI_CMD_SET_PROPERTY;
|
|
buffer[1] = group;
|
|
buffer[2] = 4;
|
|
buffer[3] = property;
|
|
buffer[4] = (value >> 24);
|
|
buffer[5] = (value >> 16);
|
|
buffer[6] = (value >> 8);
|
|
buffer[7] = (value);
|
|
|
|
_si_trx_transfer(8, 0, buffer);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void _si_trx_transfer_nocts(int tx_count, int rx_count, uint8_t *data)
|
|
{
|
|
/* Unused */
|
|
(void)rx_count;
|
|
|
|
/* Send command */
|
|
_si_trx_cs_enable();
|
|
|
|
for (int i = 0; i < tx_count; i++) {
|
|
spi_bitbang_transfer(data[i]);
|
|
}
|
|
|
|
_si_trx_cs_disable();
|
|
}
|
|
|
|
/**
|
|
* Generic SPI Send / Receive
|
|
*/
|
|
void _si_trx_transfer(int tx_count, int rx_count, uint8_t *data)
|
|
{
|
|
uint8_t response;
|
|
|
|
/* Send command */
|
|
_si_trx_cs_enable();
|
|
|
|
for (int i = 0; i < tx_count; i++) {
|
|
spi_bitbang_transfer(data[i]);
|
|
}
|
|
|
|
_si_trx_cs_disable();
|
|
|
|
/**
|
|
* Poll CTS. From the docs:
|
|
*
|
|
* READ_CMD_BUFF is used to poll the CTS signal via the SPI bus. The
|
|
* NSEL line should be pulled low, followed by sending the
|
|
* READ_CMD_BUFF command on SDI. While NSEL remains asserted low, an
|
|
* additional eight clock pulses are sent on SCLK and the CTS
|
|
* response byte is read on SDO. If the CTS response byte is not
|
|
* 0xFF, the host MCU should pull NSEL high and repeat the polling
|
|
* procedure.
|
|
*/
|
|
|
|
do {
|
|
for (int i = 0; i < 200; i++); /* Approx. 20µS */
|
|
_si_trx_cs_enable();
|
|
|
|
/* Issue READ_CMD_BUFF */
|
|
spi_bitbang_transfer(SI_CMD_READ_CMD_BUFF);
|
|
response = spi_bitbang_transfer(0xFF);
|
|
|
|
/* If the reply is 0xFF, read the response */
|
|
if (response == 0xFF) break;
|
|
|
|
/* Otherwise repeat the procedure */
|
|
_si_trx_cs_disable();
|
|
|
|
} while (1); /* TODO: Timeout? */
|
|
|
|
/**
|
|
* Read response. From the docs:
|
|
*
|
|
* If the CTS response byte is 0xFF, the host MCU should keep NSEL
|
|
* asserted low and provide additional clock cycles on SCLK to read
|
|
* out as many response bytes (on SDO) as necessary. The host MCU
|
|
* should pull NSEL high upon completion of reading the response
|
|
* stream.
|
|
*/
|
|
for (int i = 0; i < rx_count; i++) {
|
|
data[i] = spi_bitbang_transfer(0xFF);
|
|
}
|
|
|
|
_si_trx_cs_disable();
|
|
}
|
|
|
|
|
|
/**
|
|
* Issues the POWER_UP command
|
|
*/
|
|
static void si_trx_power_up(uint8_t clock_source, uint32_t xo_freq)
|
|
{
|
|
uint8_t buffer[7];
|
|
|
|
buffer[0] = SI_CMD_POWER_UP;
|
|
buffer[1] = SI_POWER_UP_FUNCTION;
|
|
buffer[2] = clock_source;
|
|
buffer[3] = (xo_freq >> 24);
|
|
buffer[4] = (xo_freq >> 16);
|
|
buffer[5] = (xo_freq >> 8);
|
|
buffer[6] = (xo_freq);
|
|
|
|
_si_trx_transfer(7, 0, buffer);
|
|
}
|
|
/**
|
|
* Gets the 16 bit part number
|
|
*/
|
|
static uint16_t si_trx_get_part_info(void)
|
|
{
|
|
uint8_t buffer[3];
|
|
|
|
buffer[0] = SI_CMD_PART_INFO;
|
|
|
|
_si_trx_transfer(1, 3, buffer);
|
|
|
|
return (buffer[1] << 8) | buffer[2];
|
|
}
|
|
/**
|
|
* Clears pending interrupts. Set the corresponding bit low to clear
|
|
* the interrupt.
|
|
*/
|
|
static void si_trx_clear_pending_interrupts(uint8_t packet_handler_clear_pending,
|
|
uint8_t chip_clear_pending)
|
|
{
|
|
uint8_t buffer[4];
|
|
|
|
buffer[0] = SI_CMD_GET_INT_STATUS;
|
|
buffer[1] = packet_handler_clear_pending & ((1<<5)|(1<<1)); /* Mask used bits */
|
|
buffer[2] = 0;
|
|
buffer[3] = chip_clear_pending;
|
|
|
|
_si_trx_transfer(4, 0, buffer);
|
|
|
|
/* This command returns the interrupts status, but we don't use it */
|
|
}
|
|
/**
|
|
* Sets the GPIO configuration for each pin
|
|
*/
|
|
static void si_trx_set_gpio_configuration(si_gpio_t gpio0, si_gpio_t gpio1,
|
|
si_gpio_t gpio2, si_gpio_t gpio3,
|
|
uint8_t drive_strength)
|
|
{
|
|
uint8_t buffer[8];
|
|
buffer[0] = SI_CMD_GPIO_PIN_CFG;
|
|
buffer[1] = gpio0;
|
|
buffer[2] = gpio1;
|
|
buffer[3] = gpio2;
|
|
buffer[4] = gpio3;
|
|
buffer[5] = SI_GPIO_PIN_CFG_NIRQ_MODE_DONOTHING;
|
|
buffer[6] = SI_GPIO_PIN_CFG_SDO_MODE_DONOTHING;
|
|
buffer[7] = drive_strength;
|
|
|
|
_si_trx_transfer(8, 0, buffer);
|
|
}
|
|
/**
|
|
* Starts transmitting
|
|
*/
|
|
static void si_trx_start_tx(uint8_t channel)
|
|
{
|
|
uint8_t buffer[5];
|
|
buffer[0] = SI_CMD_START_TX;
|
|
buffer[1] = channel;
|
|
buffer[2] = (1 << 4);
|
|
buffer[3] = 0;
|
|
buffer[4] = 0;
|
|
|
|
_si_trx_transfer(5, 0, buffer);
|
|
}
|
|
/**
|
|
* Gets readings from the auxillary ADC
|
|
*/
|
|
static void si_trx_get_adc_reading(uint8_t enable, uint8_t configuration,
|
|
uint16_t* gpio_value,
|
|
uint16_t* battery_value,
|
|
uint16_t* temperature_value)
|
|
{
|
|
uint8_t buffer[6];
|
|
buffer[0] = SI_CMD_GET_ADC_READING;
|
|
buffer[1] = enable;
|
|
buffer[2] = configuration;
|
|
|
|
_si_trx_transfer(3, 6, buffer);
|
|
|
|
*gpio_value = ((buffer[0] & 0x7) << 8) | buffer[1];
|
|
*battery_value = ((buffer[2] & 0x7) << 8) | buffer[3];
|
|
*temperature_value = ((buffer[4] & 0x7) << 8) | buffer[5];
|
|
}
|
|
/**
|
|
* Returns the measured internal die temperature of the radio
|
|
*/
|
|
float si_trx_get_temperature(void)
|
|
{
|
|
uint16_t raw_gpio, raw_battery, raw_temperature;
|
|
|
|
/* Get the reading from the adc */
|
|
si_trx_get_adc_reading(SI_GET_ADC_READING_TEMPERATURE, 0,
|
|
&raw_gpio, &raw_battery, &raw_temperature);
|
|
|
|
return (((float)raw_temperature * 568.0) / 2560.0) - 297.0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the internal frac-n pll synthesiser divisiors
|
|
*/
|
|
static void si_trx_frequency_control_set_divider(uint8_t integer_divider,
|
|
uint32_t fractional_divider)
|
|
{
|
|
uint32_t divider = (fractional_divider & 0xFFFFFF) | (integer_divider << 24);
|
|
|
|
_si_trx_set_property_32(SI_PROPERTY_GROUP_FREQ_CONTROL,
|
|
SI_FREQ_CONTROL_INTE,
|
|
divider);
|
|
}
|
|
/**
|
|
* Sets the output divider of the frac-n pll synthesiser
|
|
*/
|
|
static void si_trx_frequency_control_set_band(uint8_t band, uint8_t sy_sel)
|
|
{
|
|
_si_trx_set_property_8(SI_PROPERTY_GROUP_MODEM,
|
|
SI_MODEM_CLKGEN_BAND,
|
|
sy_sel | (band & 0x7));
|
|
}
|
|
/**
|
|
* Set the control word of the modem delta-sigma modulator
|
|
*/
|
|
static void si_trx_modem_set_dsm_ctrl(uint8_t ctrl_word)
|
|
{
|
|
_si_trx_set_property_8(SI_PROPERTY_GROUP_MODEM,
|
|
SI_MODEM_DSM_CTRL,
|
|
ctrl_word);
|
|
}
|
|
|
|
/**
|
|
* Sets the modem frequency deviation. This is how much the external
|
|
* pin deviates the synthesiser from the centre frequency. In units of
|
|
* the resolution of the frac-n pll synthsiser.
|
|
*
|
|
* This is an unsigned 17-bit value.
|
|
*/
|
|
void si_trx_modem_set_deviation(uint32_t deviation)
|
|
{
|
|
_si_trx_set_property_24(SI_PROPERTY_GROUP_MODEM,
|
|
SI_MODEM_FREQ_DEV,
|
|
deviation);
|
|
}
|
|
|
|
|
|
static void si_trx_modem_set_tx_datarate(uint32_t rate)
|
|
{
|
|
uint32_t nco_max_count = ((float)SI4xxx_TCXO_FREQUENCY / 10);
|
|
|
|
/* Set TX_NCO_MODE */
|
|
_si_trx_set_property_32(SI_PROPERTY_GROUP_MODEM,
|
|
SI_MODEM_TX_NCO_MODE,
|
|
(SI_MODEM_TX_NCO_TXOSR_10X |
|
|
(nco_max_count & 0x03FFFFFF)));
|
|
|
|
/* Set DATA_RATE */
|
|
_si_trx_set_property_24(SI_PROPERTY_GROUP_MODEM,
|
|
SI_MODEM_DATA_RATE,
|
|
rate & 0xFFFFFF);
|
|
}
|
|
/**
|
|
* Writes the coefficients of the modem tx filter
|
|
*
|
|
*/
|
|
static void si_trx_modem_tx_filter_coefficients(uint8_t* coeff_array)
|
|
{
|
|
uint8_t buffer[4+9];
|
|
|
|
buffer[0] = SI_CMD_SET_PROPERTY;
|
|
buffer[1] = SI_PROPERTY_GROUP_MODEM; // group
|
|
buffer[2] = 9;
|
|
buffer[3] = SI_MODEM_TX_FILTER_COEFF8; // prop
|
|
/* Write filter coefficents 8 to 0 */
|
|
for (int i = 0; i < 9; i++) {
|
|
buffer[4+i] = coeff_array[8-i];
|
|
}
|
|
|
|
_si_trx_transfer(4+9, 0, buffer);
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the modem frequency offset manually. In units of the
|
|
* resolution of the frac-n pll synthsiser.
|
|
*
|
|
* This is a signed 16-bit value.
|
|
*/
|
|
void si_trx_modem_set_offset(int16_t offset)
|
|
{
|
|
/* _si_trx_set_property_16(SI_PROPERTY_GROUP_MODEM, */
|
|
/* SI_MODEM_FREQ_OFFSET, */
|
|
/* offset); */
|
|
|
|
uint8_t buffer[6];
|
|
|
|
buffer[0] = SI_CMD_SET_PROPERTY;
|
|
buffer[1] = SI_PROPERTY_GROUP_MODEM; // group
|
|
buffer[2] = 2;
|
|
buffer[3] = SI_MODEM_FREQ_OFFSET; // prop
|
|
buffer[4] = (offset >> 8);
|
|
buffer[5] = (offset);
|
|
|
|
_si_trx_transfer_nocts(6, 0, buffer);
|
|
}
|
|
|
|
/**
|
|
* Sets the modulation mode
|
|
*/
|
|
static void si_trx_modem_set_modulation(uint8_t tx_direct_mode,
|
|
uint8_t tx_direct_gpio,
|
|
uint8_t tx_modulation_source,
|
|
uint8_t modulation_type)
|
|
{
|
|
_si_trx_set_property_8(SI_PROPERTY_GROUP_MODEM, SI_MODEM_MOD_TYPE,
|
|
tx_direct_mode | tx_direct_gpio |
|
|
tx_modulation_source | modulation_type);
|
|
}
|
|
/**
|
|
* Sets the tx power
|
|
*/
|
|
static void si_trx_set_tx_power(uint8_t tx_power)
|
|
{
|
|
_si_trx_set_property_8(SI_PROPERTY_GROUP_PA, SI_PA_PWR_LVL, tx_power);
|
|
}
|
|
/**
|
|
* Set the duty cycle of the tx power amplifier drive signal
|
|
*/
|
|
static void si_trx_set_tx_pa_duty_cycle(uint8_t pa_duty_cycle)
|
|
{
|
|
_si_trx_set_property_8(SI_PROPERTY_GROUP_PA, SI_PA_BIAS_CLKDUTY, pa_duty_cycle);
|
|
}
|
|
|
|
|
|
/**
|
|
* Pre-calculates sythesiser paramters for use with si_trx_set_frequency
|
|
* Might be called before module is initialised, so should just contain math
|
|
*
|
|
* frequency: Floating-point value for the frequency
|
|
*/
|
|
void si_trx_get_frequency_configuration(struct si_frequency_configuration* config,
|
|
uint32_t frequency)
|
|
{
|
|
/* Higher frequency resolution, but also higher power (~+200µA) */
|
|
config->nprescaler = 2;
|
|
|
|
if (frequency < 705000000UL) {
|
|
config->outdiv = 6; config->band = SI_MODEM_CLKGEN_FVCO_DIV_6;
|
|
}
|
|
if (frequency < 525000000UL) {
|
|
config->outdiv = 8; config->band = SI_MODEM_CLKGEN_FVCO_DIV_8;
|
|
}
|
|
if (frequency < 353000000UL) {
|
|
config->outdiv = 12; config->band = SI_MODEM_CLKGEN_FVCO_DIV_12;
|
|
}
|
|
if (frequency < 239000000UL) {
|
|
config->outdiv = 16; config->band = SI_MODEM_CLKGEN_FVCO_DIV_16;
|
|
}
|
|
if (frequency < 177000000UL) {
|
|
config->outdiv = 24; config->band = SI_MODEM_CLKGEN_FVCO_DIV_24;
|
|
}
|
|
|
|
float f_pfd = config->nprescaler * VCXO_FREQUENCY / config->outdiv;
|
|
|
|
config->n = ((uint16_t)(frequency / f_pfd)) - 1;
|
|
|
|
float ratio = (float)frequency / f_pfd;
|
|
float rest = ratio - (float)config->n;
|
|
|
|
config->m = (uint32_t)(rest * (float)(1 << 19));
|
|
|
|
/* Check n and m are in valid ranges, halt otherwise */
|
|
if (config->n > 0x7f || config->m > 0xfffff) while (1);
|
|
|
|
/* Calculate the LSB tuning resolution of the frac-n pll synthesiser. */
|
|
config->lsb_tuning_resolution = f_pfd / (float)(1 << 19);
|
|
}
|
|
|
|
/**
|
|
* Writes a pre-calculated frequency configuration to the si
|
|
* synthesiser. Also sets deviation
|
|
*/
|
|
static void si_trx_set_frequency(struct si_frequency_configuration* config,
|
|
uint16_t deviation)
|
|
{
|
|
/* Set the frac-n PLL output divider */
|
|
if (config->nprescaler == 4) { /* Prescaler */
|
|
si_trx_frequency_control_set_band(config->band, SI_MODEM_CLKGEN_SY_SEL_0);
|
|
} else { /* Default Mode */
|
|
si_trx_frequency_control_set_band(config->band, SI_MODEM_CLKGEN_SY_SEL_1);
|
|
}
|
|
|
|
/* Set the frac-n PLL divisior */
|
|
si_trx_frequency_control_set_divider(config->n, config->m);
|
|
|
|
/* Set the modem dsm control word. Allow even deviation values */
|
|
si_trx_modem_set_dsm_ctrl(SI_MODEM_DSM_CTRL_NOFORCE_DSM_LSB |
|
|
SI_MODEM_DSM_CTRL_MASH_1_1_1);
|
|
|
|
/* Set the modem frequency deviation (for the external pin)*/
|
|
si_trx_modem_set_deviation(deviation);
|
|
}
|
|
|
|
/**
|
|
* Resets the transceiver
|
|
*/
|
|
void si_trx_reset(uint8_t modulation_type, struct si_frequency_configuration* fconfig,
|
|
uint16_t deviation, uint8_t power, enum si_filter_model filter)
|
|
{
|
|
/* We expect to already be shutdown */
|
|
_si_trx_sdn_enable(); /* active high shutdown = reset */
|
|
|
|
for (int i = 0; i < 15; i++); /* a few microseconds */
|
|
|
|
_si_trx_sdn_disable(); /* booting. expected to take 15ms */
|
|
|
|
/* Poll for part number */
|
|
while (si_trx_get_part_info() != 17512);
|
|
|
|
/* Power Up */
|
|
si_trx_power_up(SI_POWER_UP_TCXO, VCXO_FREQUENCY);
|
|
|
|
/* Clear pending interrupts */
|
|
si_trx_clear_pending_interrupts(0, 0);
|
|
|
|
/* Disable all interrupts */
|
|
_si_trx_set_property_8(SI_PROPERTY_GROUP_INT_CTL, SI_INT_CTL_ENABLE, 0);
|
|
|
|
/* Configure GPIOs */
|
|
si_trx_set_gpio_configuration(SI_GPIO_PIN_CFG_GPIO_MODE_INPUT,
|
|
SI_GPIO_PIN_CFG_GPIO_MODE_INPUT | SI_GPIO_PIN_CFG_PULL_ENABLE,
|
|
SI_GPIO_PIN_CFG_GPIO_MODE_INPUT,
|
|
SI_GPIO_PIN_CFG_GPIO_MODE_INPUT | SI_GPIO_PIN_CFG_PULL_ENABLE,
|
|
SI_GPIO_PIN_CFG_DRV_STRENGTH_LOW);
|
|
|
|
si_trx_set_frequency(fconfig, deviation);
|
|
si_trx_set_tx_power(power);
|
|
|
|
/* Modem tx filter coefficients */
|
|
uint8_t rsid_si_coeff[] = {0x1, 0x4, 0x9, 0x11, 0x19, 0x22, 0x2a, 0x30, 0x31};
|
|
uint8_t p_si_coeff[] = {0x6, 0x8, 0x1, 0xf2, 0xe4, 0xe7, 0xff, 0x1d, 0x2b};
|
|
|
|
switch (filter) {
|
|
case SI_FILTER_APRS:
|
|
/**
|
|
* Modem tx filter coefficients for APRS
|
|
* 0dB @ 2.2kHz
|
|
* -6dB @ 1.2kHz (for pre-emphasis)
|
|
* < -30dB from 3.6KHz
|
|
*/
|
|
si_trx_modem_set_tx_datarate(1600); /* Filter sampling rate 1600*10 = 16kHz */
|
|
si_trx_modem_tx_filter_coefficients(p_si_coeff);
|
|
break;
|
|
case SI_FILTER_RSID:
|
|
/**
|
|
* Modem tx filter coefficients for RSID
|
|
* -6dB @ dc (for ±0.5 deviation max)
|
|
* < -50dB from 1.8KHz
|
|
*/
|
|
si_trx_modem_set_tx_datarate(1600); /* Filter sampling rate 1600*10 = 16kHz */
|
|
si_trx_modem_tx_filter_coefficients(rsid_si_coeff);
|
|
break;
|
|
default: /* Just leave the defaults from startup in place */
|
|
break;
|
|
}
|
|
|
|
/* Set modulation type */
|
|
si_trx_modem_set_modulation(SI_MODEM_MOD_DIRECT_MODE_SYNC, // ASYNC
|
|
SI_MODEM_MOD_GPIO_1,
|
|
SI_MODEM_MOD_SOURCE_DIRECT,
|
|
modulation_type);
|
|
|
|
si_trx_state_tx_tune();
|
|
}
|
|
|
|
/**
|
|
* Enables the radio and starts transmitting
|
|
*/
|
|
void si_trx_on(uint8_t modulation_type, struct si_frequency_configuration* fconfig,
|
|
uint16_t deviation, uint8_t power, enum si_filter_model filter)
|
|
{
|
|
si_trx_reset(modulation_type, fconfig, deviation, power, filter);
|
|
si_trx_start_tx(0);
|
|
}
|
|
/**
|
|
* Disables the radio and places it in shutdown
|
|
*/
|
|
void si_trx_off(void)
|
|
{
|
|
si_trx_state_ready();
|
|
|
|
/* Physical shutdown */
|
|
_si_trx_sdn_enable();
|
|
}
|
|
|
|
/**
|
|
* Resets the radio
|
|
*/
|
|
void si_trx_shutdown(void)
|
|
{
|
|
/* Configure the SDN pin */
|
|
port_pin_set_config(SI4xxx_SDN_PIN,
|
|
PORT_PIN_DIR_OUTPUT, /* Direction */
|
|
PORT_PIN_PULL_NONE, /* Pull */
|
|
false); /* Powersave */
|
|
|
|
/* Put the transciever in shutdown */
|
|
_si_trx_sdn_enable();
|
|
}
|
|
/**
|
|
* Initialises the radio interface to the radio
|
|
*/
|
|
void si_trx_init(void)
|
|
{
|
|
si_trx_shutdown();
|
|
|
|
/* Configure the SPI select pin */
|
|
port_pin_set_config(SI4xxx_SEL_PIN,
|
|
PORT_PIN_DIR_OUTPUT, /* Direction */
|
|
PORT_PIN_PULL_NONE, /* Pull */
|
|
false); /* Powersave */
|
|
|
|
/* Put the SEL pin in reset */
|
|
_si_trx_cs_disable();
|
|
|
|
/* Configure the GPIO pins */
|
|
port_pin_set_config(SI4xxx_GPIO0_PIN,
|
|
PORT_PIN_DIR_OUTPUT, /* Direction */
|
|
PORT_PIN_PULL_NONE, /* Pull */
|
|
false); /* Powersave */
|
|
port_pin_set_output_level(SI4xxx_GPIO0_PIN, 0);
|
|
port_pin_set_config(SI4xxx_GPIO1_PIN,
|
|
PORT_PIN_DIR_OUTPUT, /* Direction */
|
|
PORT_PIN_PULL_NONE, /* Pull */
|
|
false); /* Powersave */
|
|
port_pin_set_output_level(SI4xxx_GPIO1_PIN, 0);
|
|
|
|
/* Configure the IRQ pin */
|
|
// TODO
|
|
|
|
/* Configure the serial port */
|
|
spi_bitbang_init(SI4xxx_SERCOM_MOSI_PIN,
|
|
SI4xxx_SERCOM_MISO_PIN,
|
|
SI4xxx_SERCOM_SCK_PIN);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Quick and dirty loopback test. Should print 0x34
|
|
*/
|
|
void spi_loopback_test(void)
|
|
{
|
|
/* spi_init(SI_TRX_SERCOM, */
|
|
/* SPI_MODE_MASTER, /\** SPI mode *\/ */
|
|
/* SPI_DATA_ORDER_MSB, /\** Data order *\/ */
|
|
/* SPI_TRANSFER_MODE_0, /\** Transfer mode *\/ */
|
|
/* SI4xxx_SERCOM_MUX, /\** Mux setting *\/ */
|
|
/* SPI_CHARACTER_SIZE_8BIT, /\** SPI character size *\/ */
|
|
/* false, /\** Enabled in sleep *\/ */
|
|
/* true, /\** Enable receiver *\/ */
|
|
/* 100000, /\** Master - Baud rate *\/ */
|
|
/* 0, /\** Slave - Frame format *\/ */
|
|
/* 0, /\** Slave - Address mode *\/ */
|
|
/* 0, /\** Slave - Address *\/ */
|
|
/* 0, /\** Slave - Address mask *\/ */
|
|
/* false, /\** Slave - Preload data *\/ */
|
|
/* GCLK_GENERATOR_0, /\** GCLK generator to use *\/ */
|
|
/* SI4xxx_SERCOM_MOSI_PINMUX, /\** Pinmux *\/ */
|
|
/* SI4xxx_SERCOM_MISO_PINMUX, /\** Pinmux *\/ */
|
|
/* SI4xxx_SERCOM_SCK_PINMUX, /\** Pinmux *\/ */
|
|
/* PINMUX_UNUSED); /\** Pinmux *\/ */
|
|
/* spi_enable(SI_TRX_SERCOM); */
|
|
|
|
/* Init loopback */
|
|
spi_bitbang_init(SI4xxx_SERCOM_MOSI_PIN,
|
|
SI4xxx_SERCOM_MOSI_PIN,
|
|
SI4xxx_SERCOM_SCK_PIN);
|
|
|
|
/* Enable */
|
|
|
|
/* Test transfer */
|
|
uint8_t data = spi_bitbang_transfer(0x34);
|
|
|
|
/* Print result */
|
|
//semihost_printf("Rx'ed: 0x%02x\n", data);
|
|
}
|