kopia lustrzana https://github.com/bristol-seds/pico-tracker
Merge branch 'master' into contestia_dev
commit
5f9735805e
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Definitions and macros for the Si406x
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SI406X_DEFS_H
|
||||
#define SI406X_DEFS_H
|
||||
|
||||
/**
|
||||
* Si406x Boot Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_POWER_UP = 0x02,
|
||||
};
|
||||
/**
|
||||
* Si406x Common Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_NOP = 0x00,
|
||||
SI_CMD_PART_INFO = 0x01,
|
||||
SI_CMD_FUNC_INFO = 0x10,
|
||||
SI_CMD_SET_PROPERTY = 0x11,
|
||||
SI_CMD_GET_PROPERTY = 0x12,
|
||||
SI_CMD_GPIO_PIN_CFG = 0x13,
|
||||
SI_CMD_FIFO_INFO = 0x15,
|
||||
SI_CMD_GET_INT_STATUS = 0x20,
|
||||
SI_CMD_REQUEST_DEVICE_STATE = 0x33,
|
||||
SI_CMD_CHANGE_STATE = 0x34,
|
||||
SI_CMD_READ_CMD_BUFF = 0x44,
|
||||
SI_CMD_FRR_A_READ = 0x50,
|
||||
SI_CMD_FRR_B_READ = 0x51,
|
||||
SI_CMD_FRR_C_READ = 0x53,
|
||||
SI_CMD_FRR_D_READ = 0x57,
|
||||
};
|
||||
/**
|
||||
* Si406x Tx Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_START_TX = 0x31,
|
||||
SI_CMD_WRITE_TX_FIFO = 0x66,
|
||||
};
|
||||
/**
|
||||
* Si406x Rx Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_PACKET_INFO = 0x16,
|
||||
SI_CMD_GET_MODEM_STATUS = 0x22,
|
||||
SI_CMD_START_RX = 0x32,
|
||||
SI_CMD_RX_HOP = 0x36,
|
||||
SI_CMD_READ_RX_FIFO = 0x77,
|
||||
};
|
||||
/**
|
||||
* Si406x Advanced Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_GET_ADC_READING = 0x14,
|
||||
SI_CMD_PROTOCOL_CFG = 0x18,
|
||||
SI_CMD_GET_PH_STATUS = 0x21,
|
||||
SI_CMD_GET_CHIP_STATUS = 0x23,
|
||||
};
|
||||
|
||||
/**
|
||||
* Si406x State Change Commands
|
||||
*/
|
||||
enum {
|
||||
SI_STATE_CHANGE_NOCHANGE = (0 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_SLEEP = (1 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_SPI_ACTIVE = (2 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_READY = (3 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_TX_TUNE = (5 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_RX_TUNE = (6 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_TX = (7 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_RX = (8 << 8) | SI_CMD_CHANGE_STATE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic SPI Send / Receive for the Si406x
|
||||
*/
|
||||
void _si406x_transfer(int tx_count, int rx_count, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* Chip Select. Active Low (High = Inactive, Low = Active)
|
||||
*/
|
||||
#define _si406x_cs_enable() \
|
||||
port_pin_set_output_level(SI406X_SEL_PIN, 0)
|
||||
#define _si406x_cs_disable() \
|
||||
port_pin_set_output_level(SI406X_SEL_PIN, 1)
|
||||
|
||||
/**
|
||||
* Shutdown. Active High (High = Shutdown, Low = Run)
|
||||
*/
|
||||
#define _si406x_sdn_enable() \
|
||||
port_pin_set_output_level(SI406X_SDN_PIN, 1)
|
||||
#define _si406x_sdn_disable() \
|
||||
port_pin_set_output_level(SI406X_SDN_PIN, 0)
|
||||
|
||||
/**
|
||||
* HF Clock
|
||||
*/
|
||||
#define _si406x_hf_clock_enable(void) \
|
||||
/* TODO: Clock is always enabled */
|
||||
#define _si406x_hf_clock_disable(void) \
|
||||
/* TODO: Clock is always enabled */
|
||||
|
||||
|
||||
/**
|
||||
* Convenience transfer functions
|
||||
*/
|
||||
static void _si406x_transfer_uint16(uint16_t value)
|
||||
{
|
||||
_si406x_transfer(2, 0, (uint8_t*)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* State changes
|
||||
*/
|
||||
#define si406x_state_ready() \
|
||||
_si406x_transfer_uint16(SI_STATE_CHANGE_READY)
|
||||
/**
|
||||
* Change to TX tune state
|
||||
*/
|
||||
#define si406x_state_tx_tune() \
|
||||
_si406x_transfer_uint16(SI_STATE_CHANGE_TX_TUNE)
|
||||
/**
|
||||
* Change to RX tune state
|
||||
*/
|
||||
#define si406x_state_rx_tune() \
|
||||
_si406x_transfer_uint16(SI_STATE_CHANGE_RX_TUNE)
|
||||
/**
|
||||
* Change to TX state
|
||||
*/
|
||||
#define si406x_state_tx() \
|
||||
_si406x_transfer_uint16(SI_STATE_CHANGE_TX)
|
||||
/**
|
||||
* Change to RX state
|
||||
*/
|
||||
#define si406x_state_rx() \
|
||||
_si406x_transfer_uint16(SI_STATE_CHANGE_RX)
|
||||
|
||||
|
||||
|
||||
#endif /* SI406X_DEFS_H */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* <one line to give the program's name and a brief idea of what it does.>
|
||||
* Functions for controlling Si Labs Transceivers
|
||||
* Copyright (C) 2014 Richard Meadows <richardeoin>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -22,10 +22,16 @@
|
|||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SI406X_H
|
||||
#define SI406X_H
|
||||
#ifndef SI_TRX_H
|
||||
#define SI_TRX_H
|
||||
|
||||
float si_trx_get_temperature(void);
|
||||
|
||||
void si_trx_on(void);
|
||||
void si_trx_off(void);
|
||||
|
||||
void si_trx_init(void);
|
||||
|
||||
void si406x_init(void);
|
||||
void spi_loopback_test(void);
|
||||
|
||||
#endif /* SI406X_H */
|
||||
#endif /* SI_TRX_H */
|
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* Definitions and macros for Si Labs Tranceivers
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SI_TRX_DEFS_H
|
||||
#define SI_TRX_DEFS_H
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* COMMAND DEFINITIONS
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Si Boot Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_POWER_UP = 0x02,
|
||||
};
|
||||
/**
|
||||
* Si Common Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_NOP = 0x00,
|
||||
SI_CMD_PART_INFO = 0x01,
|
||||
SI_CMD_FUNC_INFO = 0x10,
|
||||
SI_CMD_SET_PROPERTY = 0x11,
|
||||
SI_CMD_GET_PROPERTY = 0x12,
|
||||
SI_CMD_GPIO_PIN_CFG = 0x13,
|
||||
SI_CMD_FIFO_INFO = 0x15,
|
||||
SI_CMD_GET_INT_STATUS = 0x20,
|
||||
SI_CMD_REQUEST_DEVICE_STATE = 0x33,
|
||||
SI_CMD_CHANGE_STATE = 0x34,
|
||||
SI_CMD_READ_CMD_BUFF = 0x44,
|
||||
SI_CMD_FRR_A_READ = 0x50,
|
||||
SI_CMD_FRR_B_READ = 0x51,
|
||||
SI_CMD_FRR_C_READ = 0x53,
|
||||
SI_CMD_FRR_D_READ = 0x57,
|
||||
};
|
||||
/**
|
||||
* Si Tx Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_START_TX = 0x31,
|
||||
SI_CMD_WRITE_TX_FIFO = 0x66,
|
||||
};
|
||||
/**
|
||||
* Si Rx Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_PACKET_INFO = 0x16,
|
||||
SI_CMD_GET_MODEM_STATUS = 0x22,
|
||||
SI_CMD_START_RX = 0x32,
|
||||
SI_CMD_RX_HOP = 0x36,
|
||||
SI_CMD_READ_RX_FIFO = 0x77,
|
||||
};
|
||||
/**
|
||||
* Si Advanced Commands
|
||||
*/
|
||||
enum {
|
||||
SI_CMD_GET_ADC_READING = 0x14,
|
||||
SI_CMD_PROTOCOL_CFG = 0x18,
|
||||
SI_CMD_GET_PH_STATUS = 0x21,
|
||||
SI_CMD_GET_CHIP_STATUS = 0x23,
|
||||
};
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* COMMAND ARGUMENTS
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Si Power Up
|
||||
*/
|
||||
enum {
|
||||
SI_POWER_UP_FUNCTION = 0x01,
|
||||
SI_POWER_UP_XTAL = 0x00,
|
||||
SI_POWER_UP_TCXO = 0x01,
|
||||
};
|
||||
|
||||
/**
|
||||
* Si GPIO configuration
|
||||
*/
|
||||
typedef uint8_t si_gpio_t;
|
||||
enum {
|
||||
SI_GPIO_PIN_CFG_PULL_ENABLE = 0x40, /* enable or disable pull-up resistor */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_DONOTHING = 0x00, /* pin behaviour is not changed */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_TRISTATE = 0x01, /* input and output drivers are disabled */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_DRIVE0 = 0x02, /* CMOS output "low" */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_DRIVE1 = 0x03, /* CMOS output "high" */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_INPUT = 0x04, /* GPIO is input, for TXDATA etc, function is not configured here */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_32K_CLK = 0x05, /* outputs the 32kHz CLK when selected in CLK32_CLK_SEL */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_BOOT_CLK = 0x06, /* outputs boot clock when SPI_ACTIVE */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_DIV_CLK = 0x07, /* outputs divided xtal clk */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_CTS = 0x08, /* output, '1' when device is ready to accept new command */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_INV_CNT = 0x09, /* output, inverted CTS */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_CMD_OVERLAP = 0x0a, /* output, '1' if a command was issued while not ready */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_SDO = 0x0b, /* output, serial data out for SPI */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_POR = 0x0c, /* output, '0' while in POR state */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_CAL_WUT = 0x0d, /* output, '1' on expiration of wake up timer */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_WUT = 0x0e, /* wake up timer output */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_EN_PA = 0x0f, /* output, '1' when PA is enabled */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_TX_DATA_CLK = 0x10, /* data clock output, for TX direct sync mode */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_TX_DATA = 0x11, /* data output from TX FIFO, for debugging purposes */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_IN_SLEEP = 0x12, /* output, '0' when in sleep state */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_TX_STATE = 0x13, /* output, '1' when in TX state */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_TX_FIFO_EMPTY = 0x14, /* output, '1' when FIFO is empty */
|
||||
SI_GPIO_PIN_CFG_GPIO_MODE_LOW_BATT = 0x15, /* output, '1' if low battery is detected */
|
||||
SI_GPIO_PIN_CFG_NIRQ_MODE_DONOTHING = 0x00,
|
||||
SI_GPIO_PIN_CFG_SDO_MODE_DONOTHING = 0x00,
|
||||
SI_GPIO_PIN_CFG_DRV_STRENGTH_HIGH = (0x00 << 5),
|
||||
SI_GPIO_PIN_CFG_DRV_STRENGTH_MED_HIGH = (0x01 << 5),
|
||||
SI_GPIO_PIN_CFG_DRV_STRENGTH_MED_LOW = (0x02 << 5),
|
||||
SI_GPIO_PIN_CFG_DRV_STRENGTH_LOW = (0x03 << 5),
|
||||
};
|
||||
|
||||
/**
|
||||
* Si State Change
|
||||
*/
|
||||
enum {
|
||||
SI_STATE_CHANGE_NOCHANGE = (0 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_SLEEP = (1 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_SPI_ACTIVE = (2 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_READY = (3 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_TX_TUNE = (5 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_RX_TUNE = (6 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_TX = (7 << 8) | SI_CMD_CHANGE_STATE,
|
||||
SI_STATE_CHANGE_RX = (8 << 8) | SI_CMD_CHANGE_STATE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Si Get ADC reading
|
||||
*/
|
||||
enum {
|
||||
SI_GET_ADC_READING_TEMPERATURE = (1 << 4),
|
||||
SI_GET_ADC_READING_BATTERY = (1 << 3),
|
||||
SI_GET_ADC_READING_GPIO = (1 << 2),
|
||||
SI_GET_ADC_READING_GPIO_PIN_GPIO3 = 3,
|
||||
SI_GET_ADC_READING_GPIO_PIN_GPIO2 = 2,
|
||||
SI_GET_ADC_READING_GPIO_PIN_GPIO1 = 1,
|
||||
SI_GET_ADC_READING_GPIO_PIN_GPIO0 = 0,
|
||||
SI_GET_ADC_READING_RANGE_0V8 = 0,
|
||||
SI_GET_ADC_READING_RANGE_1V6 = 4,
|
||||
SI_GET_ADC_READING_RANGE_3V2 = 5,
|
||||
SI_GET_ADC_READING_RANGE_2V4 = 8,
|
||||
SI_GET_ADC_READING_RANGE_3V6 = 9
|
||||
};
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* PROPERTY DEFINITIONS
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Si Property Groups
|
||||
*/
|
||||
enum {
|
||||
SI_PROPERTY_GROUP_GLOBAL = 0x00,
|
||||
SI_PROPERTY_GROUP_INT_CTL = 0x01,
|
||||
SI_PROPERTY_GROUP_FRR_CTL = 0x02,
|
||||
SI_PROPERTY_GROUP_PREAMBLE = 0x10,
|
||||
SI_PROPERTY_GROUP_SYNC = 0x11,
|
||||
SI_PROPERTY_GROUP_PKT = 0x12,
|
||||
SI_PROPERTY_GROUP_MODEM = 0x20,
|
||||
SI_PROPERTY_GROUP_PA = 0x22,
|
||||
SI_PROPERTY_GROUP_SYNTH = 0x23,
|
||||
SI_PROPERTY_GROUP_FREQ_CONTROL = 0x40,
|
||||
};
|
||||
/**
|
||||
* Si Interrupt Control Properties
|
||||
*/
|
||||
enum {
|
||||
SI_INT_CTL_ENABLE = 0x00,
|
||||
SI_INT_CTL_PH_ENABLE = 0x01,
|
||||
SI_INT_CTL_CHIP_ENABLE = 0x02,
|
||||
};
|
||||
/**
|
||||
* Si Global Properties
|
||||
*/
|
||||
enum {
|
||||
SI_GLOBAL_XO_TUNE = 0x00,
|
||||
SI_GLOBAL_CONFIG = 0x03,
|
||||
};
|
||||
/**
|
||||
* Si Preamble Properties
|
||||
*/
|
||||
enum {
|
||||
SI_PREAMBLE_TX_LENGTH = 0x00,
|
||||
};
|
||||
/**
|
||||
* Si Sync Properties
|
||||
*/
|
||||
enum {
|
||||
SI_SYNC_CONFIG = 0x11,
|
||||
};
|
||||
/**
|
||||
* Si Modem Properties
|
||||
*/
|
||||
enum {
|
||||
SI_MODEM_MOD_TYPE = 0x00,
|
||||
SI_MODEM_MOD_TYPE_CW = 0x00,
|
||||
SI_MODEM_MOD_TYPE_OOK = 0x01,
|
||||
SI_MODEM_MOD_TYPE_2FSK = 0x02, /* default */
|
||||
SI_MODEM_MOD_TYPE_2GFSK = 0x03,
|
||||
SI_MODEM_MOD_TYPE_4FSK = 0x04,
|
||||
SI_MODEM_MOD_TYPE_4GFSK = 0x05,
|
||||
SI_MODEM_MOD_SOURCE_PACKET = (0x00 << 3), /* default */
|
||||
SI_MODEM_MOD_SOURCE_DIRECT = (0x01 << 3),
|
||||
SI_MODEM_MOD_SOURCE_PSEUDO = (0x02 << 3),
|
||||
SI_MODEM_MOD_GPIO_0 = (0x00 << 5), /* default */
|
||||
SI_MODEM_MOD_GPIO_1 = (0x01 << 5),
|
||||
SI_MODEM_MOD_GPIO_2 = (0x02 << 5),
|
||||
SI_MODEM_MOD_GPIO_3 = (0x03 << 5),
|
||||
SI_MODEM_MOD_DIRECT_MODE_SYNC = (0x00 << 7), /* default */
|
||||
SI_MODEM_MOD_DIRECT_MODE_ASYNC = (0x01 << 7),
|
||||
SI_MODEM_FREQ_DEV = 0x0a,
|
||||
SI_MODEM_FREQ_OFFSET = 0x0d,
|
||||
SI_MODEM_CLKGEN_BAND = 0x51,
|
||||
SI_MODEM_CLKGEN_SY_SEL_0 = (0x00 << 3), /* low power */
|
||||
SI_MODEM_CLKGEN_SY_SEL_1 = (0x01 << 3), /* default */
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_4 = 0x00, /* default */
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_6 = 0x01,
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_8 = 0x02, /* for 70cm ISM band */
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_12 = 0x03,
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_16 = 0x04,
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_24 = 0x05,
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_24_2 = 0x06,
|
||||
SI_MODEM_CLKGEN_FVCO_DIV_24_3 = 0x07,
|
||||
};
|
||||
/**
|
||||
* Si PA Properties
|
||||
*/
|
||||
enum {
|
||||
SI_PA_MODE = 0x00,
|
||||
SI_PA_PWR_LVL = 0x01,
|
||||
SI_PA_BIAS_CLKDUTY = 0x02,
|
||||
SI_PA_BIAS_CLKDUTY_SIN_25 = (0x03 << 6), /* for si4060 */
|
||||
SI_PA_BIAS_CLKDUTY_DIFF_50 = (0x00 << 6), /* for si4063 */
|
||||
};
|
||||
/**
|
||||
* Si Synthesizer Properties
|
||||
*/
|
||||
enum {
|
||||
SI_SYNTH_PFDCP_CPFF = 0x00,
|
||||
SI_SYNTH_PFDCP_CPINT = 0x01,
|
||||
SI_SYNTH_VCO_KV = 0x02,
|
||||
SI_SYNTH_LPFILT3 = 0x03,
|
||||
SI_SYNTH_LPFILT2 = 0x04,
|
||||
SI_SYNTH_LPFILT1 = 0x05,
|
||||
SI_SYNTH_LPFILT0 = 0x06,
|
||||
SI_SYNTH_VCO_KVCAL = 0x07,
|
||||
};
|
||||
/**
|
||||
* Si Frequency Control Properties
|
||||
*/
|
||||
enum {
|
||||
SI_FREQ_CONTROL_INTE = 0x00,
|
||||
SI_FREQ_CONTROL_FRAC = 0x01,
|
||||
SI_FREQ_CONTROL_CHANNEL_STEP_SIZE = 0x04,
|
||||
SI_FREQ_CONTROL_W_SIZE = 0x06,
|
||||
};
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* Hardware Definitions
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generic SPI Send / Receive
|
||||
*/
|
||||
void _si_trx_transfer(int tx_count, int rx_count, uint8_t *data);
|
||||
|
||||
/**
|
||||
* Chip Select. Active Low (High = Inactive, Low = Active)
|
||||
*/
|
||||
#define _si_trx_cs_enable() \
|
||||
port_pin_set_output_level(SI406X_SEL_PIN, 0)
|
||||
#define _si_trx_cs_disable() \
|
||||
port_pin_set_output_level(SI406X_SEL_PIN, 1)
|
||||
|
||||
/**
|
||||
* Shutdown. Active High (High = Shutdown, Low = Run)
|
||||
*/
|
||||
#define _si_trx_sdn_enable() \
|
||||
port_pin_set_output_level(SI406X_SDN_PIN, 1)
|
||||
#define _si_trx_sdn_disable() \
|
||||
port_pin_set_output_level(SI406X_SDN_PIN, 0)
|
||||
|
||||
/**
|
||||
* HF Clock
|
||||
*/
|
||||
#define _si_trx_hf_clock_enable(void) \
|
||||
/* NOT USED: Clock is always enabled */
|
||||
#define _si_trx_hf_clock_disable(void) \
|
||||
/* NOT USED: Clock is always enabled */
|
||||
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* Helper Functions
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convenience transfer functions
|
||||
*/
|
||||
static void _si_trx_transfer_uint16(uint16_t value)
|
||||
{
|
||||
_si_trx_transfer(2, 0, (uint8_t*)&value);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* State changes
|
||||
*/
|
||||
#define si_trx_state_ready() \
|
||||
_si_trx_transfer_uint16(SI_STATE_CHANGE_READY)
|
||||
/**
|
||||
* Change to TX tune state
|
||||
*/
|
||||
#define si_trx_state_tx_tune() \
|
||||
_si_trx_transfer_uint16(SI_STATE_CHANGE_TX_TUNE)
|
||||
/**
|
||||
* Change to RX tune state
|
||||
*/
|
||||
#define si_trx_state_rx_tune() \
|
||||
_si_trx_transfer_uint16(SI_STATE_CHANGE_RX_TUNE)
|
||||
/**
|
||||
* Change to TX state
|
||||
*/
|
||||
#define si_trx_state_tx() \
|
||||
_si_trx_transfer_uint16(SI_STATE_CHANGE_TX)
|
||||
/**
|
||||
* Change to RX state
|
||||
*/
|
||||
#define si_trx_state_rx() \
|
||||
_si_trx_transfer_uint16(SI_STATE_CHANGE_RX)
|
||||
|
||||
|
||||
|
||||
#endif /* SI_TRX_DEFS_H */
|
|
@ -38,58 +38,15 @@
|
|||
#include "system/wdt.h"
|
||||
#include "timepulse.h"
|
||||
#include "telemetry.h"
|
||||
//#include "si406x.h"
|
||||
#include "si_trx.h"
|
||||
#include "si_trx_defs.h"
|
||||
#include "analogue.h"
|
||||
#include "si4060.h"
|
||||
#include "spi_bitbang.h"
|
||||
#include "rtty.h"
|
||||
#include "system/interrupt.h"
|
||||
|
||||
#define CALLSIGN "UBSEDSx"
|
||||
|
||||
void si4060_hw_init(void)
|
||||
{
|
||||
/* Configure the SDN pin */
|
||||
port_pin_set_config(SI406X_SDN_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
|
||||
/* Put the SI406x in shutdown */
|
||||
//_si406x_sdn_enable();
|
||||
si4060_shutdown();
|
||||
|
||||
/* Configure the SDN pin */
|
||||
port_pin_set_config(SI406X_SEL_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
|
||||
/* Put the SEL pin in reset */
|
||||
_si406x_cs_disable();
|
||||
|
||||
/* Configure the serial port */
|
||||
spi_bitbang_init(SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_MISO_PIN,
|
||||
SI406X_SERCOM_SCK_PIN);
|
||||
}
|
||||
void si4060_gpio_init()
|
||||
{
|
||||
/* Configure the GPIO and IRQ pins */
|
||||
port_pin_set_config(SI406X_GPIO0_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
port_pin_set_output_level(SI406X_GPIO0_PIN, 0);
|
||||
/* Configure the GPIO and IRQ pins */
|
||||
port_pin_set_config(SI406X_GPIO1_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
port_pin_set_output_level(SI406X_GPIO1_PIN, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialises the status LED
|
||||
|
@ -233,7 +190,7 @@ void output_telemetry_string(void)
|
|||
|
||||
/* Analogue */
|
||||
float battery = get_battery();
|
||||
float temperature = si4060_get_temperature();
|
||||
float temperature = si_trx_get_temperature();
|
||||
|
||||
/* Sleep Wait */
|
||||
while (rtty_get_index() < (len - 4)) {
|
||||
|
@ -330,7 +287,7 @@ int main(void)
|
|||
system_set_sleepmode(SYSTEM_SLEEPMODE_IDLE_2); /* Disable CPU, AHB and APB */
|
||||
|
||||
/* Configure the Power Manager */
|
||||
powermananger_init();
|
||||
//powermananger_init();
|
||||
|
||||
/* Timer 0 for 50Hz triggering */
|
||||
timer0_tick_init(50);
|
||||
|
@ -341,34 +298,23 @@ int main(void)
|
|||
*/
|
||||
|
||||
/* Set the wdt here. We should get to the first reset in one min */
|
||||
wdt_init();
|
||||
wdt_reset_count();
|
||||
//wdt_init();
|
||||
//wdt_reset_count();
|
||||
|
||||
led_init();
|
||||
gps_init();
|
||||
|
||||
/* Initialise Si4060 */
|
||||
si4060_hw_init();
|
||||
si4060_gpio_init();
|
||||
si4060_reset();
|
||||
si_trx_init();
|
||||
|
||||
/* check radio communication */
|
||||
int i = si4060_part_info();
|
||||
if (i != 0x4063) {
|
||||
while(1);
|
||||
}
|
||||
|
||||
si4060_power_up();
|
||||
si4060_setup(MOD_TYPE_2FSK);
|
||||
|
||||
si4060_gpio_init();
|
||||
si4060_start_tx(0);
|
||||
/* Start transmitting */
|
||||
si_trx_on();
|
||||
|
||||
led_on();
|
||||
|
||||
while (1) {
|
||||
/* Watchdog */
|
||||
wdt_reset_count();
|
||||
//wdt_reset_count();
|
||||
|
||||
/* Send the next packet */
|
||||
output_telemetry_string();
|
||||
|
|
|
@ -1,348 +0,0 @@
|
|||
/*
|
||||
* Functions for controlling Si406x radios
|
||||
* 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 "semihosting.h"
|
||||
#include "system/port.h"
|
||||
#include "spi_bitbang.h"
|
||||
#include "si406x_defs.h"
|
||||
#include "hw_config.h"
|
||||
|
||||
#define RADIO_FREQ 434600000
|
||||
// Quite low power
|
||||
#define RADIO_PWR 0x7f
|
||||
#define VCXO_FREQ SI406X_TCXO_FREQUENCY
|
||||
|
||||
uint32_t active_freq = RADIO_FREQ;
|
||||
uint8_t active_pwr = RADIO_PWR;
|
||||
uint16_t si446x_powerlevel = RADIO_PWR;
|
||||
|
||||
/**
|
||||
* Generic SPI Send / Receive for the Si406x
|
||||
*/
|
||||
void _si406x_transfer(int tx_count, int rx_count, const uint8_t *data)
|
||||
{
|
||||
uint8_t response[100];
|
||||
|
||||
/* Send command */
|
||||
_si406x_cs_enable();
|
||||
|
||||
for (int i = 0; i < tx_count; i++) {
|
||||
spi_bitbang_transfer(data[i]);
|
||||
}
|
||||
|
||||
_si406x_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.
|
||||
*/
|
||||
|
||||
for (int i = 0; i < 20000; i++); // 20µS
|
||||
_si406x_cs_enable();
|
||||
|
||||
do {
|
||||
/* Issue READ_CMD_BUFF */
|
||||
spi_bitbang_transfer(SI_CMD_READ_CMD_BUFF);
|
||||
response[0] = spi_bitbang_transfer(0xFF);
|
||||
|
||||
/* If the reply is 0xFF, read the response */
|
||||
if (response[0] == 0xFF) break;
|
||||
|
||||
/* Otherwise repeat the procedure */
|
||||
_si406x_cs_disable();
|
||||
for (int i = 0; i < 200; i++); // 20µS
|
||||
_si406x_cs_enable();
|
||||
|
||||
} 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 = 1; i < rx_count; i++) {
|
||||
response[i] = spi_bitbang_transfer(0xFF);
|
||||
}
|
||||
|
||||
_si406x_cs_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Si406x synthesiser to the given frequency
|
||||
*/
|
||||
static void si406x_set_frequency(uint32_t frequency)
|
||||
{
|
||||
uint8_t outdiv, band;
|
||||
|
||||
if (frequency < 705000000UL) {
|
||||
outdiv = 6; band = 1;
|
||||
}
|
||||
if (frequency < 525000000UL) {
|
||||
if (VCXO_FREQ < 24000000) { // clock < 24mhz
|
||||
outdiv = 4; band = 0;
|
||||
} else {
|
||||
outdiv = 8; band = 2;
|
||||
}
|
||||
}
|
||||
if (frequency < 353000000UL) {
|
||||
outdiv = 12; band = 3;
|
||||
}
|
||||
if (frequency < 239000000UL) {
|
||||
outdiv = 16; band = 4;
|
||||
}
|
||||
if (frequency < 177000000UL) {
|
||||
outdiv = 24; band = 5;
|
||||
}
|
||||
|
||||
uint32_t f_pfd = 2 * VCXO_FREQ / outdiv;
|
||||
|
||||
uint16_t n = ((uint16_t)(frequency / f_pfd)) - 1;
|
||||
|
||||
float ratio = (float)frequency / (float)f_pfd;
|
||||
float rest = ratio - (float)n;
|
||||
|
||||
uint32_t m = (uint32_t)(rest * 524288UL); // 2^19
|
||||
|
||||
// set the band parameter
|
||||
uint8_t sy_sel = 8;
|
||||
uint8_t set_band_property_command[] = {0x11, 0x20, 0x01, 0x51, (band + sy_sel)};
|
||||
// send parameters
|
||||
_si406x_transfer(5, 1, set_band_property_command);
|
||||
|
||||
// Set the pll parameters
|
||||
uint16_t m2 = m / 0x10000;
|
||||
uint16_t m1 = (m - m2 * 0x10000) / 0x100;
|
||||
uint16_t m0 = (m - m2 * 0x10000 - m1 * 0x100);
|
||||
|
||||
// assemble parameter string
|
||||
const uint8_t set_frequency_control_inte[] = {0x11, 0x40, 0x04, 0x00, n, m2, m1, m0};
|
||||
// const uint8_t set_frequency_control_inte[] = {
|
||||
// 0x11, 0x40, 0x08, 0x00, n, m2, m1, m0, 0x0B, 0x61, 0x20, 0xFA};
|
||||
//const uint8_t set_frequency_control_inte[] = {0x11, 0x40, 0x08, 0x00, n, m2, m1, m0, 0x0B, 0x61, 0x20, 0xFA};
|
||||
|
||||
// send parameters
|
||||
_si406x_transfer(8, 1, set_frequency_control_inte);
|
||||
|
||||
// Read parameters
|
||||
const uint8_t get_frequency_control[] = { 0x12, 0x40, 0x04, 0x00 };
|
||||
_si406x_transfer(4, 5, get_frequency_control);
|
||||
}
|
||||
|
||||
void si406x_init(void)
|
||||
{
|
||||
/* Configure the SDN pin */
|
||||
port_pin_set_config(SI406X_SDN_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
|
||||
/* Put the SI406x in shutdown */
|
||||
_si406x_sdn_enable();
|
||||
|
||||
/* Configure the SDN pin */
|
||||
port_pin_set_config(SI406X_SEL_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
|
||||
/* Put the SEL pin in reset */
|
||||
_si406x_cs_disable();
|
||||
|
||||
/* Configure the GPIO and IRQ pins */
|
||||
|
||||
/* Configure the serial port */
|
||||
spi_bitbang_init(SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_MISO_PIN,
|
||||
SI406X_SERCOM_SCK_PIN);
|
||||
|
||||
/* Boot */
|
||||
for (int i = 0; i < 15*10000; i++); // 15ms
|
||||
_si406x_sdn_disable();
|
||||
for (int i = 0; i < 15*10000; i++); // 15ms
|
||||
|
||||
const uint8_t PART_INFO_command[] = {0x01}; // Part Info
|
||||
_si406x_transfer(1, 9, PART_INFO_command);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the modem into CW mode
|
||||
*/
|
||||
static void si446xSetModem(void)
|
||||
{
|
||||
// Set to CW mode
|
||||
const uint8_t set_modem_mod_type_command[] = {0x11, 0x20, 0x01, 0x00, 0x00};
|
||||
_si406x_transfer(5, 1, set_modem_mod_type_command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tx power
|
||||
*/
|
||||
void si446xSetPower(uint8_t pwr)
|
||||
{
|
||||
// Set the Power
|
||||
// uint8_t set_pa_pwr_lvl_property_command[] = {0x11, 0x22, 0x01, 0x01, pwr};
|
||||
// _si406x_transfer(5, 1, set_pa_pwr_lvl_property_command);
|
||||
}
|
||||
|
||||
// Config reset ----------------------------------------------------------
|
||||
static void si446xReset(void)
|
||||
{
|
||||
// _si406x_hf_clock_enable();
|
||||
_si406x_sdn_enable(); // active high shutdown = reset
|
||||
|
||||
for (int i = 0; i < 15*10000; i++); // 15ms
|
||||
_si406x_sdn_disable(); // booting
|
||||
for (int i = 0; i < 15*10000; i++); // 15ms
|
||||
|
||||
|
||||
const uint8_t PART_INFO_command[] = {0x01}; // Part Info
|
||||
_si406x_transfer(1, 9, PART_INFO_command);
|
||||
|
||||
//divide VCXO_FREQ into its bytes; MSB first
|
||||
uint16_t x3 = VCXO_FREQ / 0x1000000;
|
||||
uint16_t x2 = (VCXO_FREQ - x3 * 0x1000000) / 0x10000;
|
||||
uint16_t x1 = (VCXO_FREQ - x3 * 0x1000000 - x2 * 0x10000) / 0x100;
|
||||
uint16_t x0 = (VCXO_FREQ - x3 * 0x1000000 - x2 * 0x10000 - x1 * 0x100);
|
||||
|
||||
/* ---- POWER_UP ---- */
|
||||
/* no patch, boot main app. img, FREQ_VCXO, return 1 byte */
|
||||
/* */
|
||||
const uint8_t init_command[] = {0x02, 0x01, 0x01, x3, x2, x1, x0};
|
||||
_si406x_transfer(7, 1 , init_command);
|
||||
|
||||
|
||||
// Clear all pending interrupts and get the interrupt status back
|
||||
const uint8_t get_int_status_command[] = {0x20, 0x00, 0x00, 0x00};
|
||||
_si406x_transfer(4, 9, get_int_status_command);
|
||||
// cliPrint("Radio ready\n");
|
||||
|
||||
const uint8_t set_int_ctrl_enable[] = {0x11, 0x01, 0x01, 0x00, 0x00};
|
||||
_si406x_transfer(5, 1, set_int_ctrl_enable);
|
||||
// cliPrint("Setting no Interrupts (see WDS)\n");
|
||||
|
||||
// Set all GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength
|
||||
const uint8_t gpio_pin_cfg_command[] = {0x13, 0x02, 0x02, 0x02, 0x02, 0x08, 0x0B, 0x00};
|
||||
_si406x_transfer(8, 8, gpio_pin_cfg_command);
|
||||
// cliPrint("LEDs should be switched off at this point\n");
|
||||
|
||||
//const uint8_t set_global_config1[] = {0x11, 0x00, 0x01, 0x03, 0x60};
|
||||
//_si406x_transfer(5, 1, set_global_config1);
|
||||
// Sequencer Mode = Fast, Fifo = Half Duplex
|
||||
// cliPrint("Setting special global Config 1 changes (see WDS)\n");
|
||||
|
||||
// const uint8_t set_global_xo_tune_command[] = {0x11, 0x00, 0x01, 0x00, 0x00};
|
||||
//_si406x_transfer(5, 1, set_global_xo_tune_command);
|
||||
// cliPrint("Setting no additional capacitance on VXCO\n");
|
||||
|
||||
si406x_set_frequency(active_freq);
|
||||
|
||||
si446xSetPower(active_pwr);
|
||||
|
||||
si446xSetModem();
|
||||
// cliPrint("CW mode set\n");
|
||||
|
||||
si406x_state_tx_tune();
|
||||
// cliPrint("TX tune\n");
|
||||
}
|
||||
|
||||
void si446xPTTOn(void)
|
||||
{
|
||||
si446xReset();
|
||||
|
||||
// turn on the LED (GPIO0) to indicate TX
|
||||
// Set GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength
|
||||
const uint8_t gpio_pin_cfg_command2[] = {0x13, 0x02, 0x02, 0x02, 0x02, 0x08, 0x0B, 0x00};
|
||||
_si406x_transfer(8, 1, gpio_pin_cfg_command2);
|
||||
|
||||
si406x_state_tx();
|
||||
|
||||
const uint8_t get_state[] = {0x33};
|
||||
_si406x_transfer(1, 3, get_state);
|
||||
}
|
||||
|
||||
void si446xPTTOff(void)
|
||||
{
|
||||
si406x_state_ready();
|
||||
|
||||
// turn off the LED (GPIO1)
|
||||
// Set GPIO0 HIGH
|
||||
const uint8_t gpio_pin_cfg_command0[] = {0x13, 0x03, 0x0, 0x0, 0x0, 0x0, 0x0, 0x00};
|
||||
_si406x_transfer(8, 1, gpio_pin_cfg_command0);
|
||||
|
||||
_si406x_sdn_enable(); // active high = shutdown
|
||||
_si406x_hf_clock_disable(); // keep enabled for now
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick and dirty loopback test. Should print 0x34
|
||||
*/
|
||||
void spi_loopback_test(void)
|
||||
{
|
||||
/* spi_init(SI406X_SERCOM, */
|
||||
/* SPI_MODE_MASTER, /\** SPI mode *\/ */
|
||||
/* SPI_DATA_ORDER_MSB, /\** Data order *\/ */
|
||||
/* SPI_TRANSFER_MODE_0, /\** Transfer mode *\/ */
|
||||
/* SI406X_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 *\/ */
|
||||
/* SI406X_SERCOM_MOSI_PINMUX, /\** Pinmux *\/ */
|
||||
/* SI406X_SERCOM_MISO_PINMUX, /\** Pinmux *\/ */
|
||||
/* SI406X_SERCOM_SCK_PINMUX, /\** Pinmux *\/ */
|
||||
/* PINMUX_UNUSED); /\** Pinmux *\/ */
|
||||
|
||||
/* Init loopback */
|
||||
spi_bitbang_init(SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_SCK_PIN);
|
||||
|
||||
/* Enable */
|
||||
|
||||
/* Test transfer */
|
||||
uint8_t data = spi_bitbang_transfer(0x34);
|
||||
|
||||
/* Print result */
|
||||
semihost_printf("Rx'ed: 0x%02x\n", data);
|
||||
}
|
||||
|
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* 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 "semihosting.h"
|
||||
#include "system/port.h"
|
||||
#include "spi_bitbang.h"
|
||||
#include "si_trx_defs.h"
|
||||
#include "hw_config.h"
|
||||
|
||||
#define RADIO_FREQUENCY 434600000
|
||||
#define RADIO_POWER 0x3f
|
||||
#define VCXO_FREQUENCY SI406X_TCXO_FREQUENCY
|
||||
#define RF_DEVIATION 200
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* 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 step size between adjacent channels, in units of the
|
||||
* resolution of the frac-n pll synthesiser.
|
||||
*/
|
||||
static void si_trx_frequency_control_set_channel_step_size(uint16_t step_size)
|
||||
{
|
||||
_si_trx_set_property_16(SI_PROPERTY_GROUP_FREQ_CONTROL,
|
||||
SI_FREQ_CONTROL_CHANNEL_STEP_SIZE,
|
||||
step_size);
|
||||
}
|
||||
/**
|
||||
* Sets the output divider of the frac-n pll synthesiser
|
||||
*/
|
||||
static void si_trx_frequency_control_set_band(uint8_t band)
|
||||
{
|
||||
/* Force SY_SEL = 1, operation when SY_SEL = 0 is currently undefined */
|
||||
_si_trx_set_property_8(SI_PROPERTY_GROUP_MODEM,
|
||||
SI_MODEM_CLKGEN_BAND,
|
||||
SI_MODEM_CLKGEN_SY_SEL_1 | (band & 0x7));
|
||||
}
|
||||
/**
|
||||
* Sets the frequency deviation in the modem
|
||||
*/
|
||||
static void si_trx_modem_set_deviation(uint32_t deviation)
|
||||
{
|
||||
_si_trx_set_property_24(SI_PROPERTY_GROUP_MODEM,
|
||||
SI_MODEM_FREQ_DEV,
|
||||
deviation);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the synthesiser to the given frequency
|
||||
*/
|
||||
static void si_trx_set_frequency(uint32_t frequency)
|
||||
{
|
||||
uint8_t outdiv, band;
|
||||
|
||||
if (frequency < 705000000UL) {
|
||||
outdiv = 6; band = SI_MODEM_CLKGEN_FVCO_DIV_6;
|
||||
}
|
||||
if (frequency < 525000000UL) {
|
||||
outdiv = 8; band = SI_MODEM_CLKGEN_FVCO_DIV_8;
|
||||
}
|
||||
if (frequency < 353000000UL) {
|
||||
outdiv = 12; band = SI_MODEM_CLKGEN_FVCO_DIV_12;
|
||||
}
|
||||
if (frequency < 239000000UL) {
|
||||
outdiv = 16; band = SI_MODEM_CLKGEN_FVCO_DIV_16;
|
||||
}
|
||||
if (frequency < 177000000UL) {
|
||||
outdiv = 24; band = SI_MODEM_CLKGEN_FVCO_DIV_24;
|
||||
}
|
||||
|
||||
uint32_t f_pfd = 2 * VCXO_FREQUENCY / outdiv;
|
||||
|
||||
uint16_t n = ((uint16_t)(frequency / f_pfd)) - 1;
|
||||
|
||||
float ratio = (float)frequency / (float)f_pfd;
|
||||
float rest = ratio - (float)n;
|
||||
|
||||
uint32_t m = (uint32_t)(rest * (float)(1 << 19));
|
||||
|
||||
float dev_ratio = (float)RF_DEVIATION / (float)f_pfd;
|
||||
uint32_t dev = (uint32_t)(dev_ratio * (float)(1 << 19));
|
||||
|
||||
/* Set the frac-n PLL output divider */
|
||||
si_trx_frequency_control_set_band(band);
|
||||
|
||||
/* Set the frac-n PLL divisior */
|
||||
si_trx_frequency_control_set_divider(n, m);
|
||||
|
||||
/* Set the frequency deviation in the modem */
|
||||
si_trx_modem_set_deviation(dev);
|
||||
|
||||
//const uint8_t set_frequency_control_inte[] = {0x11, 0x40, 0x08, 0x00, n, m2, m1, m0, 0x0B, 0x61, 0x20, 0xFA};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the transceiver
|
||||
*/
|
||||
void si_trx_reset(void)
|
||||
{
|
||||
_si_trx_sdn_enable(); /* active high shutdown = reset */
|
||||
|
||||
for (int i = 0; i < 15*10000; i++); /* Approx. 15ms */
|
||||
_si_trx_sdn_disable(); /* booting */
|
||||
for (int i = 0; i < 15*10000; i++); /* Approx. 15ms */
|
||||
|
||||
|
||||
uint16_t part_number = si_trx_get_part_info();
|
||||
|
||||
/* 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(RADIO_FREQUENCY);
|
||||
si_trx_set_tx_power(RADIO_POWER);
|
||||
|
||||
/* RTTY from GPIO1 */
|
||||
si_trx_modem_set_modulation(SI_MODEM_MOD_DIRECT_MODE_ASYNC,
|
||||
SI_MODEM_MOD_GPIO_1,
|
||||
SI_MODEM_MOD_SOURCE_DIRECT,
|
||||
SI_MODEM_MOD_TYPE_2FSK);
|
||||
|
||||
si_trx_state_tx_tune();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the radio and starts transmitting
|
||||
*/
|
||||
void si_trx_on(void)
|
||||
{
|
||||
si_trx_reset();
|
||||
si_trx_state_tx();
|
||||
}
|
||||
/**
|
||||
* Disables the radio and places it in shutdown
|
||||
*/
|
||||
void si_trx_off(void)
|
||||
{
|
||||
si_trx_state_ready();
|
||||
_si_trx_sdn_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the radio interface to the radio
|
||||
*/
|
||||
void si_trx_init(void)
|
||||
{
|
||||
/* Configure the SDN pin */
|
||||
port_pin_set_config(SI406X_SDN_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
|
||||
/* Put the transciever in shutdown */
|
||||
_si_trx_sdn_enable();
|
||||
|
||||
/* Configure the SPI select pin */
|
||||
port_pin_set_config(SI406X_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(SI406X_GPIO0_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
port_pin_set_output_level(SI406X_GPIO0_PIN, 0);
|
||||
port_pin_set_config(SI406X_GPIO1_PIN,
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
port_pin_set_output_level(SI406X_GPIO1_PIN, 0);
|
||||
|
||||
/* Configure the IRQ pin */
|
||||
// TODO
|
||||
|
||||
/* Configure the serial port */
|
||||
spi_bitbang_init(SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_MISO_PIN,
|
||||
SI406X_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 *\/ */
|
||||
/* SI406X_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 *\/ */
|
||||
/* SI406X_SERCOM_MOSI_PINMUX, /\** Pinmux *\/ */
|
||||
/* SI406X_SERCOM_MISO_PINMUX, /\** Pinmux *\/ */
|
||||
/* SI406X_SERCOM_SCK_PINMUX, /\** Pinmux *\/ */
|
||||
/* PINMUX_UNUSED); /\** Pinmux *\/ */
|
||||
|
||||
/* Init loopback */
|
||||
spi_bitbang_init(SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_MOSI_PIN,
|
||||
SI406X_SERCOM_SCK_PIN);
|
||||
|
||||
/* Enable */
|
||||
|
||||
/* Test transfer */
|
||||
uint8_t data = spi_bitbang_transfer(0x34);
|
||||
|
||||
/* Print result */
|
||||
semihost_printf("Rx'ed: 0x%02x\n", data);
|
||||
}
|
Ładowanie…
Reference in New Issue