Merge pull request #15120 from benpicco/driver/at86rf215-trim
driver/at86rf215: add functions to configure trim & clock output at run-time
This commit is contained in:
commit
665c07eb53
@ -125,7 +125,7 @@ if (!IS_ACTIVE(CONFIG_AT86RF215_USE_CLOCK_OUTPUT)){
|
|||||||
}
|
}
|
||||||
/* allow to configure board-specific trim */
|
/* allow to configure board-specific trim */
|
||||||
#ifdef CONFIG_AT86RF215_TRIM_VAL
|
#ifdef CONFIG_AT86RF215_TRIM_VAL
|
||||||
at86rf215_reg_write(dev, RG_RF_XOC, CONFIG_AT86RF215_TRIM_VAL | XOC_FS_MASK);
|
at86rf215_set_trim(dev, CONFIG_AT86RF215_TRIM_VAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* enable TXFE & RXFE IRQ */
|
/* enable TXFE & RXFE IRQ */
|
||||||
|
|||||||
@ -89,6 +89,18 @@ uint8_t at86rf215_get_chan(const at86rf215_t *dev)
|
|||||||
return at86rf215_reg_read16(dev, dev->RF->RG_CNL);
|
return at86rf215_reg_read16(dev, dev->RF->RG_CNL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void at86rf215_set_trim(at86rf215_t *dev, uint8_t trim)
|
||||||
|
{
|
||||||
|
assert(trim <= 0xF);
|
||||||
|
at86rf215_reg_write(dev, RG_RF_XOC, trim | XOC_FS_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void at86rf215_set_clock_output(at86rf215_t *dev,
|
||||||
|
at86rf215_clko_cur_t cur, at86rf215_clko_freq_t freq)
|
||||||
|
{
|
||||||
|
at86rf215_reg_write(dev, RG_RF_CLKO, cur | freq);
|
||||||
|
}
|
||||||
|
|
||||||
void at86rf215_set_chan(at86rf215_t *dev, uint16_t channel)
|
void at86rf215_set_chan(at86rf215_t *dev, uint16_t channel)
|
||||||
{
|
{
|
||||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||||
|
|||||||
@ -272,6 +272,33 @@ enum {
|
|||||||
AT86RF215_MODE_MR_FSK
|
AT86RF215_MODE_MR_FSK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Clock Output Driver Strength
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
AT86RF215_CLKO_2mA = 0 << 3, /**< 2 mA */
|
||||||
|
AT86RF215_CLKO_4mA = 1 << 3, /**< 4 mA */
|
||||||
|
AT86RF215_CLKO_6mA = 2 << 3, /**< 6 mA */
|
||||||
|
AT86RF215_CLKO_8mA = 3 << 3, /**< 8 mA */
|
||||||
|
} at86rf215_clko_cur_t;
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Clock Output Frequency
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
AT86RF215_CLKO_OFF = 0, /**< Clock Output Disabled */
|
||||||
|
AT86RF215_CLKO_26_MHz, /**< 26 MHz */
|
||||||
|
AT86RF215_CLKO_32_MHz, /**< 32 MHz */
|
||||||
|
AT86RF215_CLKO_16_MHz, /**< 16 MHz */
|
||||||
|
AT86RF215_CLKO_8_MHz, /**< 8 MHz */
|
||||||
|
AT86RF215_CLKO_4_MHz, /**< 4 MHz */
|
||||||
|
AT86RF215_CLKO_2_MHz, /**< 2 MHz */
|
||||||
|
AT86RF215_CLKO_1_MHz, /**< 1 MHz */
|
||||||
|
} at86rf215_clko_freq_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Internal device option flags
|
* @name Internal device option flags
|
||||||
* @{
|
* @{
|
||||||
@ -526,6 +553,42 @@ int8_t at86rf215_get_ed_level(at86rf215_t *dev);
|
|||||||
*/
|
*/
|
||||||
void at86rf215_set_option(at86rf215_t *dev, uint16_t option, bool state);
|
void at86rf215_set_option(at86rf215_t *dev, uint16_t option, bool state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set crystal oscillator trim value.
|
||||||
|
*
|
||||||
|
* An internal capacitance array is connected to the
|
||||||
|
* crystal oscillator pins TCXO and XTAL2.
|
||||||
|
*
|
||||||
|
* Each increment of the trim value adds 0.3pF capacitance
|
||||||
|
* to the oscillator circuit.
|
||||||
|
*
|
||||||
|
* To trim a board, enable the clock output with
|
||||||
|
* @ref at86rf215_set_clock_output and connect a frequency
|
||||||
|
* counter to the clock output pin.
|
||||||
|
* Then adjust the trim value until it the measured frequency
|
||||||
|
* closely matches the configured output frequency.
|
||||||
|
*
|
||||||
|
* It is recommended to use a 26 MHz output frequency for the
|
||||||
|
* test as this is the raw frequency of the external oscillator.
|
||||||
|
*
|
||||||
|
* The resulting trim value must then be stored in a persistent
|
||||||
|
* memory area of the board to be set via @ref CONFIG_AT86RF215_TRIM_VAL
|
||||||
|
*
|
||||||
|
* @param[in] dev device to configure
|
||||||
|
* @param[in] trim trim value
|
||||||
|
*/
|
||||||
|
void at86rf215_set_trim(at86rf215_t *dev, uint8_t trim);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure the Clock Output pin
|
||||||
|
*
|
||||||
|
* @param[in] dev device to configure
|
||||||
|
* @param[in] cur Clock output current
|
||||||
|
* @param[in] freq Clock output frequency
|
||||||
|
*/
|
||||||
|
void at86rf215_set_clock_output(at86rf215_t *dev,
|
||||||
|
at86rf215_clko_cur_t cur, at86rf215_clko_freq_t freq);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convenience function for simply sending data
|
* @brief Convenience function for simply sending data
|
||||||
*
|
*
|
||||||
|
|||||||
@ -297,6 +297,11 @@ typedef enum {
|
|||||||
} netdev_type_t;
|
} netdev_type_t;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Will match any device index
|
||||||
|
*/
|
||||||
|
#define NETDEV_INDEX_ANY (0xFF)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure to hold driver state
|
* @brief Structure to hold driver state
|
||||||
*
|
*
|
||||||
|
|||||||
@ -103,11 +103,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Will match any device index
|
|
||||||
*/
|
|
||||||
#define NETDEV_INDEX_ANY (0xFF)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Function for providing a EUI-48 to a device
|
* @brief Function for providing a EUI-48 to a device
|
||||||
*
|
*
|
||||||
|
|||||||
@ -566,6 +566,19 @@ int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt);
|
|||||||
int gnrc_netif_set_from_netdev(gnrc_netif_t *netif,
|
int gnrc_netif_set_from_netdev(gnrc_netif_t *netif,
|
||||||
const gnrc_netapi_opt_t *opt);
|
const gnrc_netapi_opt_t *opt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets an interface by the netdev type (and index)
|
||||||
|
*
|
||||||
|
* @pre The netdev has been registered with @ref netdev_register
|
||||||
|
*
|
||||||
|
* @param[in] type driver type of the netdev, can be @ref NETDEV_ANY
|
||||||
|
* @param[in] index index of the netdev, can be @ref NETDEV_INDEX_ANY
|
||||||
|
*
|
||||||
|
* @return The network interface that has a netdev of matching type and index
|
||||||
|
* NULL if no matching interface could be found
|
||||||
|
*/
|
||||||
|
gnrc_netif_t *gnrc_netif_get_by_type(netdev_type_t type, uint8_t index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Converts a hardware address to a human readable string.
|
* @brief Converts a hardware address to a human readable string.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -117,6 +117,31 @@ gnrc_netif_t *gnrc_netif_iter(const gnrc_netif_t *prev)
|
|||||||
return (gnrc_netif_t*) netif_iter((netif_t*) prev);
|
return (gnrc_netif_t*) netif_iter((netif_t*) prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gnrc_netif_t *gnrc_netif_get_by_type(netdev_type_t type, uint8_t index)
|
||||||
|
{
|
||||||
|
gnrc_netif_t *netif = NULL;
|
||||||
|
while ((netif = gnrc_netif_iter(netif))) {
|
||||||
|
|
||||||
|
#ifdef MODULE_NETDEV_REGISTER
|
||||||
|
if (netif->dev->type != type && type != NETDEV_ANY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netif->dev->index != index && index != NETDEV_INDEX_ANY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)type;
|
||||||
|
(void)index;
|
||||||
|
assert(index == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return netif;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt)
|
int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt)
|
||||||
{
|
{
|
||||||
int res = -ENOTSUP;
|
int res = -ENOTSUP;
|
||||||
|
|||||||
@ -20,13 +20,16 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "at86rf215.h"
|
#include "at86rf215.h"
|
||||||
|
#include "at86rf215_internal.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "shell_commands.h"
|
#include "shell_commands.h"
|
||||||
#include "sys/bus.h"
|
#include "sys/bus.h"
|
||||||
|
|
||||||
#include "net/gnrc/pktdump.h"
|
#include "net/gnrc/pktdump.h"
|
||||||
|
#include "net/gnrc/netif.h"
|
||||||
#include "net/gnrc.h"
|
#include "net/gnrc.h"
|
||||||
|
#include "od.h"
|
||||||
|
|
||||||
static char batmon_stack[THREAD_STACKSIZE_MAIN];
|
static char batmon_stack[THREAD_STACKSIZE_MAIN];
|
||||||
|
|
||||||
@ -74,8 +77,126 @@ static int cmd_enable_batmon(int argc, char **argv)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cmd_set_trim(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("usage: %s <trim>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t trim = atoi(argv[1]);
|
||||||
|
|
||||||
|
if (trim > 0xF) {
|
||||||
|
puts("Trim value out of range");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnrc_netif_t *netif = gnrc_netif_get_by_type(NETDEV_AT86RF215, 0);
|
||||||
|
|
||||||
|
if (netif == NULL) {
|
||||||
|
puts("No at86rf215 radio found");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
at86rf215_t* dev = (at86rf215_t*)netif->dev;
|
||||||
|
|
||||||
|
printf("setting trim to %u fF\n", 300U * trim);
|
||||||
|
at86rf215_set_trim(dev, trim);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_set_clock_out(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *keys[] = {
|
||||||
|
[AT86RF215_CLKO_OFF] = "off",
|
||||||
|
[AT86RF215_CLKO_26_MHz] = "26",
|
||||||
|
[AT86RF215_CLKO_32_MHz] = "32",
|
||||||
|
[AT86RF215_CLKO_16_MHz] = "16",
|
||||||
|
[AT86RF215_CLKO_8_MHz] = "8",
|
||||||
|
[AT86RF215_CLKO_4_MHz] = "4",
|
||||||
|
[AT86RF215_CLKO_2_MHz] = "2",
|
||||||
|
[AT86RF215_CLKO_1_MHz] = "1",
|
||||||
|
};
|
||||||
|
|
||||||
|
at86rf215_clko_freq_t freq = AT86RF215_CLKO_26_MHz;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
unsigned tmp = 0xFF;
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(keys); ++i) {
|
||||||
|
if (strcmp(argv[1], keys[i]) == 0) {
|
||||||
|
tmp = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp == 0xFF) {
|
||||||
|
printf("usage: %s [freq in MHz | off]\n", argv[0]);
|
||||||
|
printf("valid frequencies: off");
|
||||||
|
for (unsigned i = 1; i < ARRAY_SIZE(keys); ++i) {
|
||||||
|
printf(", %s MHz", keys[i]);
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
freq = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gnrc_netif_t *netif = gnrc_netif_get_by_type(NETDEV_AT86RF215, 0);
|
||||||
|
|
||||||
|
if (netif == NULL) {
|
||||||
|
puts("No at86rf215 radio found");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
at86rf215_t *dev = (at86rf215_t *)netif->dev;
|
||||||
|
|
||||||
|
printf("Clock output set to %s %s\n", keys[freq], freq ? "MHz" : "");
|
||||||
|
at86rf215_set_clock_output(dev, AT86RF215_CLKO_4mA, freq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_get_random(int argc, char **argv)
|
||||||
|
{
|
||||||
|
uint8_t values;
|
||||||
|
uint8_t buffer[256];
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
values = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
values = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values == 0) {
|
||||||
|
printf("usage: %s [num]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnrc_netif_t *netif = gnrc_netif_get_by_type(NETDEV_AT86RF215, 0);
|
||||||
|
|
||||||
|
if (netif == NULL) {
|
||||||
|
puts("No at86rf215 radio found");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
at86rf215_t *dev = (at86rf215_t *)netif->dev;
|
||||||
|
|
||||||
|
at86rf215_get_random(dev, buffer, values);
|
||||||
|
|
||||||
|
od_hex_dump(buffer, values, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const shell_command_t shell_commands[] = {
|
static const shell_command_t shell_commands[] = {
|
||||||
{ "batmon", "Enable the battery monitor", cmd_enable_batmon },
|
{ "batmon", "Enable the battery monitor", cmd_enable_batmon },
|
||||||
|
{ "set_trim", "at86rf215: Set the trim value of the crystal oscillator", cmd_set_trim },
|
||||||
|
{ "set_clko", "at86rf215: Configure the Clock Output pin", cmd_set_clock_out },
|
||||||
|
{ "get_random", "at86rf215: Get random values from the radio", cmd_get_random },
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user