mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #16232 from maribu/drivers/cc110x
drivers/cc110x: add power off (sleep) functions
This commit is contained in:
commit
8f9233f329
@ -89,6 +89,13 @@ int cc110x_apply_config(cc110x_t *dev, const cc110x_config_t *conf,
|
||||
return cc110x_full_calibration(dev);
|
||||
}
|
||||
|
||||
static void _set_tx_power(cc110x_t *dev, cc110x_tx_power_t power)
|
||||
{
|
||||
uint8_t frend0 = 0x10 | (uint8_t)power;
|
||||
cc110x_write(dev, CC110X_REG_FREND0, frend0);
|
||||
dev->tx_power = power;
|
||||
}
|
||||
|
||||
int cc110x_set_tx_power(cc110x_t *dev, cc110x_tx_power_t power)
|
||||
{
|
||||
DEBUG("[cc110x] Applying TX power setting at index %u\n", (unsigned)power);
|
||||
@ -114,9 +121,8 @@ int cc110x_set_tx_power(cc110x_t *dev, cc110x_tx_power_t power)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
uint8_t frend0 = 0x10 | (uint8_t)power;
|
||||
cc110x_write(dev, CC110X_REG_FREND0, frend0);
|
||||
dev->tx_power = power;
|
||||
_set_tx_power(dev, power);
|
||||
|
||||
cc110x_release(dev);
|
||||
return 0;
|
||||
}
|
||||
@ -176,3 +182,47 @@ int cc110x_set_channel(cc110x_t *dev, uint8_t channel)
|
||||
dev->netdev.event_callback(&dev->netdev, NETDEV_EVENT_FHSS_CHANGE_CHANNEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cc110x_wakeup(cc110x_t *dev)
|
||||
{
|
||||
int err = cc110x_power_on_and_acquire(dev);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* PA_TABLE is lost on SLEEP, see 10.6 in the CC1101 data sheet */
|
||||
cc110x_burst_write(dev, CC110X_MULTIREG_PATABLE,
|
||||
dev->params.patable->data, CC110X_PATABLE_LEN);
|
||||
_set_tx_power(dev, dev->tx_power);
|
||||
|
||||
cc110x_enter_rx_mode(dev);
|
||||
cc110x_release(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cc110x_sleep(cc110x_t *dev)
|
||||
{
|
||||
cc110x_acquire(dev);
|
||||
if (dev->state == CC110X_STATE_OFF) {
|
||||
cc110x_release(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Datasheet page 9 table 4.
|
||||
*
|
||||
* To achieve the lowest power consumption GDO's must
|
||||
* be programmed to 0x2F
|
||||
*/
|
||||
cc110x_write(dev, CC110X_REG_IOCFG2, CC110X_GDO_CONSTANT_LOW);
|
||||
cc110x_write(dev, CC110X_REG_IOCFG1, CC110X_GDO_CONSTANT_LOW);
|
||||
cc110x_write(dev, CC110X_REG_IOCFG0, CC110X_GDO_CONSTANT_LOW);
|
||||
|
||||
/* transition to SLEEP only from state IDLE possible */
|
||||
cc110x_cmd(dev, CC110X_STROBE_IDLE);
|
||||
/* go to SLEEP */
|
||||
cc110x_cmd(dev, CC110X_STROBE_OFF);
|
||||
dev->state = CC110X_STATE_OFF;
|
||||
cc110x_release(dev);
|
||||
}
|
||||
|
@ -18,13 +18,16 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "cc110x.h"
|
||||
#include "cc110x_communication.h"
|
||||
#include "cc110x_constants.h"
|
||||
#include "cc110x_internal.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/spi.h"
|
||||
#include "xtimer.h"
|
||||
#include "cc110x.h"
|
||||
#include "cc110x_constants.h"
|
||||
|
||||
int cc110x_power_on(cc110x_t *dev)
|
||||
int cc110x_power_on_and_acquire(cc110x_t *dev)
|
||||
{
|
||||
gpio_t cs = dev->params.cs;
|
||||
|
||||
@ -32,9 +35,19 @@ int cc110x_power_on(cc110x_t *dev)
|
||||
return -EIO;
|
||||
}
|
||||
gpio_clear(cs);
|
||||
xtimer_usleep(150);
|
||||
xtimer_usleep(CC110X_WAKEUP_TIME_US);
|
||||
gpio_set(cs);
|
||||
spi_init_cs(dev->params.spi, dev->params.cs);
|
||||
|
||||
if (cc110x_acquire(dev) != SPI_OK) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
while (cc110x_state_from_status(cc110x_status(dev)) != CC110X_STATE_IDLE) {
|
||||
cc110x_cmd(dev, CC110X_STROBE_IDLE);
|
||||
xtimer_usleep(CC110X_WAKEUP_TIME_US);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -120,36 +120,36 @@ static int identify_device(cc110x_t *dev)
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case 3:
|
||||
DEBUG("[cc110x] Detected CC1100 transceiver\n");
|
||||
/* RSSI offset is 78dBm @ 868MHz & 250kBaud.
|
||||
* Depends on the symbol rate and base band and ranges from
|
||||
* 74dBm to 79dBm.
|
||||
*/
|
||||
dev->rssi_offset = 78;
|
||||
return 0;
|
||||
case 5:
|
||||
DEBUG("[cc110x] Detected CC1100E transceiver\n");
|
||||
/* RSSI offset is 79 dBm @ 250kbps & 250 kbps.
|
||||
* Depends on base band and symbol rate and ranges from
|
||||
* 75dBm to 79dBm
|
||||
*/
|
||||
dev->rssi_offset = 79;
|
||||
return 0;
|
||||
case 4:
|
||||
/* falls through */
|
||||
case 14:
|
||||
/* falls through */
|
||||
case 20:
|
||||
/* RSSI offset for the CC1101 is independent of symbol rate and
|
||||
* base 74 dBm
|
||||
*/
|
||||
dev->rssi_offset = 74;
|
||||
DEBUG("[cc110x] Detected CC1101 transceiver\n");
|
||||
return 0;
|
||||
default:
|
||||
DEBUG("[cc110x] Device not a CC110x transceiver\n");
|
||||
return -1;
|
||||
case 3:
|
||||
DEBUG("[cc110x] Detected CC1100 transceiver\n");
|
||||
/* RSSI offset is 78dBm @ 868MHz & 250kBaud.
|
||||
* Depends on the symbol rate and base band and ranges from
|
||||
* 74dBm to 79dBm.
|
||||
*/
|
||||
dev->rssi_offset = 78;
|
||||
return 0;
|
||||
case 5:
|
||||
DEBUG("[cc110x] Detected CC1100E transceiver\n");
|
||||
/* RSSI offset is 79 dBm @ 250kbps & 250 kbps.
|
||||
* Depends on base band and symbol rate and ranges from
|
||||
* 75dBm to 79dBm
|
||||
*/
|
||||
dev->rssi_offset = 79;
|
||||
return 0;
|
||||
case 4:
|
||||
/* falls through */
|
||||
case 14:
|
||||
/* falls through */
|
||||
case 20:
|
||||
/* RSSI offset for the CC1101 is independent of symbol rate and
|
||||
* base 74 dBm
|
||||
*/
|
||||
dev->rssi_offset = 74;
|
||||
DEBUG("[cc110x] Detected CC1101 transceiver\n");
|
||||
return 0;
|
||||
default:
|
||||
DEBUG("[cc110x] Device not a CC110x transceiver\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,37 +247,25 @@ static int cc110x_init(netdev_t *netdev)
|
||||
/* Make sure the crystal is stable and the chip ready. This is needed as
|
||||
* the reset is done via an SPI command, but the SPI interface must not be
|
||||
* used unless the chip is ready according to the data sheet. After the
|
||||
* reset, a second call to cc110x_power_on() is needed to finally have
|
||||
* reset, a second call to cc110x_power_on_and_acquire() is needed to finally have
|
||||
* the transceiver in a known state and ready for SPI communication.
|
||||
*/
|
||||
if (cc110x_power_on(dev)) {
|
||||
if (cc110x_power_on_and_acquire(dev)) {
|
||||
DEBUG("[cc110x] netdev_driver_t::init(): Failed to pull CS pin low\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (cc110x_acquire(dev) != SPI_OK) {
|
||||
DEBUG("[cc110x] netdev_driver_t::init(): Failed to setup/acquire SPI "
|
||||
"interface\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Performing a reset of the transceiver to get it in a known state */
|
||||
cc110x_cmd(dev, CC110X_STROBE_RESET);
|
||||
cc110x_release(dev);
|
||||
|
||||
/* Again, make sure the crystal is stable and the chip ready */
|
||||
if (cc110x_power_on(dev)) {
|
||||
if (cc110x_power_on_and_acquire(dev)) {
|
||||
DEBUG("[cc110x] netdev_driver_t::init(): Failed to pull CS pin low "
|
||||
"after reset\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (cc110x_acquire(dev) != SPI_OK) {
|
||||
DEBUG("[cc110x] netdev_driver_t::init(): Failed to setup/acquire SPI "
|
||||
"interface after reset\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (identify_device(dev)) {
|
||||
DEBUG("[cc110x] netdev_driver_t::init(): Device identification failed\n");
|
||||
cc110x_release(dev);
|
||||
@ -414,20 +402,23 @@ static int cc110x_send(netdev_t *netdev, const iolist_t *iolist)
|
||||
}
|
||||
|
||||
switch (dev->state) {
|
||||
case CC110X_STATE_FSTXON:
|
||||
/* falls through */
|
||||
case CC110X_STATE_RX_MODE:
|
||||
break;
|
||||
case CC110X_STATE_RECEIVING:
|
||||
cc110x_release(dev);
|
||||
DEBUG("[cc110x] netdev_driver_t::send(): Refusing to send while "
|
||||
"receiving a frame\n");
|
||||
return -EBUSY;
|
||||
default:
|
||||
cc110x_release(dev);
|
||||
DEBUG("[cc110x] netdev_driver_t::send(): Driver state %i prevents "
|
||||
"sending\n", (int)dev->state);
|
||||
return -1;
|
||||
case CC110X_STATE_FSTXON:
|
||||
/* falls through */
|
||||
case CC110X_STATE_RX_MODE:
|
||||
break;
|
||||
case CC110X_STATE_RECEIVING:
|
||||
cc110x_release(dev);
|
||||
DEBUG("[cc110x] netdev_driver_t::send(): Refusing to send while "
|
||||
"receiving a frame\n");
|
||||
return -EBUSY;
|
||||
case CC110X_STATE_OFF:
|
||||
cc110x_release(dev);
|
||||
return -ENOTSUP;
|
||||
default:
|
||||
cc110x_release(dev);
|
||||
DEBUG("[cc110x] netdev_driver_t::send(): Driver state %i prevents "
|
||||
"sending\n", (int)dev->state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy data to send into frame buffer */
|
||||
@ -530,42 +521,73 @@ static int cc110x_get(netdev_t *netdev, netopt_t opt,
|
||||
|
||||
(void)max_len; /* only used in assert() */
|
||||
switch (opt) {
|
||||
case NETOPT_DEVICE_TYPE:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = NETDEV_TYPE_CC110X;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_PROTO:
|
||||
assert(max_len == sizeof(gnrc_nettype_t));
|
||||
*((gnrc_nettype_t *)val) = CC110X_DEFAULT_PROTOCOL;
|
||||
return sizeof(gnrc_nettype_t);
|
||||
case NETOPT_MAX_PDU_SIZE:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = CC110X_MAX_FRAME_SIZE - sizeof(cc1xxx_l2hdr_t);
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_ADDR_LEN:
|
||||
/* falls through */
|
||||
case NETOPT_SRC_LEN:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = CC1XXX_ADDR_SIZE;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_ADDRESS:
|
||||
assert(max_len >= CC1XXX_ADDR_SIZE);
|
||||
*((uint8_t *)val) = dev->addr;
|
||||
return CC1XXX_ADDR_SIZE;
|
||||
case NETOPT_CHANNEL:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = dev->channel;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_TX_POWER:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = dbm_from_tx_power[dev->tx_power];
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_PROMISCUOUSMODE:
|
||||
assert(max_len == sizeof(netopt_enable_t));
|
||||
return cc110x_get_promiscuous_mode(dev, val);
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
case NETOPT_DEVICE_TYPE:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = NETDEV_TYPE_CC110X;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_PROTO:
|
||||
assert(max_len == sizeof(gnrc_nettype_t));
|
||||
*((gnrc_nettype_t *)val) = CC110X_DEFAULT_PROTOCOL;
|
||||
return sizeof(gnrc_nettype_t);
|
||||
case NETOPT_MAX_PDU_SIZE:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = CC110X_MAX_FRAME_SIZE - sizeof(cc1xxx_l2hdr_t);
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_ADDR_LEN:
|
||||
/* falls through */
|
||||
case NETOPT_SRC_LEN:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = CC1XXX_ADDR_SIZE;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_ADDRESS:
|
||||
assert(max_len >= CC1XXX_ADDR_SIZE);
|
||||
*((uint8_t *)val) = dev->addr;
|
||||
return CC1XXX_ADDR_SIZE;
|
||||
case NETOPT_CHANNEL:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = dev->channel;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_TX_POWER:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = dbm_from_tx_power[dev->tx_power];
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_PROMISCUOUSMODE:
|
||||
assert(max_len == sizeof(netopt_enable_t));
|
||||
return cc110x_get_promiscuous_mode(dev, val);
|
||||
case NETOPT_STATE:
|
||||
assert(max_len == sizeof(netopt_state_t));
|
||||
{
|
||||
netopt_state_t *state = val;
|
||||
switch (dev->state) {
|
||||
case CC110X_STATE_RECEIVING:
|
||||
case CC110X_STATE_FRAME_READY:
|
||||
case CC110X_STATE_RXFIFO_OVERFLOW:
|
||||
*state = NETOPT_STATE_RX;
|
||||
break;
|
||||
case CC110X_STATE_IDLE:
|
||||
*state = NETOPT_STATE_STANDBY;
|
||||
break;
|
||||
case CC110X_STATE_OFF:
|
||||
*state = NETOPT_STATE_SLEEP;
|
||||
break;
|
||||
case CC110X_STATE_TX_MODE:
|
||||
case CC110X_STATE_TX_COMPLETING:
|
||||
case CC110X_STATE_TXFIFO_UNDERFLOW:
|
||||
*state = NETOPT_STATE_TX;
|
||||
break;
|
||||
case CC110X_STATE_RX_MODE:
|
||||
*state = NETOPT_STATE_IDLE;
|
||||
break;
|
||||
default:
|
||||
*state = NETOPT_STATE_RESET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -619,41 +641,56 @@ static int cc110x_set(netdev_t *netdev, netopt_t opt,
|
||||
cc110x_t *dev = (cc110x_t *)netdev;
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_ADDRESS:
|
||||
assert(len == CC1XXX_ADDR_SIZE);
|
||||
return cc110x_set_addr(dev, *((uint8_t *)val));
|
||||
case NETOPT_CHANNEL:
|
||||
{
|
||||
assert(len == sizeof(uint16_t));
|
||||
int retval;
|
||||
uint16_t channel = *((uint16_t *)val);
|
||||
if (channel >= CC110X_MAX_CHANNELS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((retval = cc110x_set_channel(dev, (uint8_t)channel))) {
|
||||
return retval;
|
||||
case NETOPT_ADDRESS:
|
||||
assert(len == CC1XXX_ADDR_SIZE);
|
||||
return cc110x_set_addr(dev, *((uint8_t *)val));
|
||||
case NETOPT_CHANNEL:
|
||||
{
|
||||
assert(len == sizeof(uint16_t));
|
||||
int retval;
|
||||
uint16_t channel = *((uint16_t *)val);
|
||||
if (channel >= CC110X_MAX_CHANNELS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((retval = cc110x_set_channel(dev, (uint8_t)channel))) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_TX_POWER:
|
||||
{
|
||||
assert(len == sizeof(int16_t));
|
||||
int16_t dbm = *((int16_t *)val);
|
||||
cc110x_tx_power_t power = CC110X_TX_POWER_MINUS_30_DBM;
|
||||
for ( ; power < CC110X_TX_POWER_PLUS_10_DBM; power++) {
|
||||
if ((int16_t)tx_power_from_dbm[power] >= dbm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_TX_POWER:
|
||||
{
|
||||
assert(len == sizeof(int16_t));
|
||||
int16_t dbm = *((int16_t *)val);
|
||||
cc110x_tx_power_t power = CC110X_TX_POWER_MINUS_30_DBM;
|
||||
for ( ; power < CC110X_TX_POWER_PLUS_10_DBM; power++) {
|
||||
if ((int16_t)tx_power_from_dbm[power] >= dbm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cc110x_set_tx_power(dev, power)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (cc110x_set_tx_power(dev, power)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_PROMISCUOUSMODE:
|
||||
assert(len == sizeof(netopt_enable_t));
|
||||
return cc110x_set_promiscuous_mode(dev, *((const netopt_enable_t *)val));
|
||||
}
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_PROMISCUOUSMODE:
|
||||
assert(len == sizeof(netopt_enable_t));
|
||||
return cc110x_set_promiscuous_mode(dev, *((const netopt_enable_t *)val));
|
||||
case NETOPT_STATE:
|
||||
assert(len == sizeof(netopt_state_t));
|
||||
switch (*((netopt_state_t *)val)) {
|
||||
case NETOPT_STATE_RESET:
|
||||
case NETOPT_STATE_IDLE:
|
||||
cc110x_wakeup(dev);
|
||||
return sizeof(netopt_state_t);
|
||||
case NETOPT_STATE_OFF:
|
||||
case NETOPT_STATE_SLEEP:
|
||||
cc110x_sleep(dev);
|
||||
return sizeof(netopt_state_t);
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,9 @@ extern "C" {
|
||||
* @retval SPI_NOMODE SPI mode 0 not supported by MCU
|
||||
* @retval SPI_NOCLK SPI clock given in @ref cc110x_params_t is not supported
|
||||
*
|
||||
* @pre @ref cc110x_power_on has be called before calling this function.
|
||||
* (Only needed *once* when the driver initializes.)
|
||||
* @pre When first acquiring the device either after boot or after having put
|
||||
* the device to sleep mode, use @ref cc110x_power_on_and_acquire
|
||||
* instead. Subsequently, this function should be used (it is faster).
|
||||
*/
|
||||
static inline int cc110x_acquire(cc110x_t *dev)
|
||||
{
|
||||
@ -200,11 +201,13 @@ uint8_t cc110x_status(cc110x_t *dev);
|
||||
* of messing with the SPI interface, this driver simply waits for this upper
|
||||
* bound, as suggested in the note below Table 22 on page 30 in the data sheet.
|
||||
*
|
||||
* @pre The device was not acquired and in low power mode
|
||||
* @post The device is in IDLE mode and acquired
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EIO Couldn't pull the CS pin down (@ref cc110x_params_t::cs)
|
||||
*/
|
||||
int cc110x_power_on(cc110x_t *dev);
|
||||
|
||||
int cc110x_power_on_and_acquire(cc110x_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -570,6 +570,11 @@ extern "C" {
|
||||
#define CC110X_PKTCTRL1_GET_ADDR_MODE 0x03
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Time in micro seconds the CC110X takes to wake up from SLEEP state
|
||||
*/
|
||||
#define CC110X_WAKEUP_TIME_US 150
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -235,7 +235,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup drivers_cc110x_config CC1100/CC1100e/CC1101 Sub-GHz transceiver driver compile configuration
|
||||
* @defgroup drivers_cc110x_config CC1100/CC1100e/CC1101 Sub-GHz transceiver driver
|
||||
* compile time configuration
|
||||
* @ingroup config_drivers_netdev
|
||||
* @{
|
||||
*/
|
||||
@ -263,7 +264,7 @@ typedef enum {
|
||||
*/
|
||||
CC110X_STATE_FRAME_READY = 0x08,
|
||||
/**
|
||||
* @brief Frame received, waiting for upper layer to retrieve it
|
||||
* @brief Devices is powered down
|
||||
*
|
||||
* Transceiver is in SLEEP state. There is no matching representation in the
|
||||
* status byte, as reading the status byte will power up the transceiver in
|
||||
@ -324,7 +325,6 @@ typedef struct {
|
||||
uint8_t data[8]; /**< Magic number to store in the configuration register */
|
||||
} cc110x_patable_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configuration of the transceiver to use
|
||||
*
|
||||
@ -633,6 +633,21 @@ int cc110x_set_channel(cc110x_t *dev, uint8_t channel);
|
||||
*/
|
||||
int cc110x_set_tx_power(cc110x_t *dev, cc110x_tx_power_t power);
|
||||
|
||||
/**
|
||||
* @brief Wakes the transceiver from SLEEP mode and enters RX mode
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EIO Communication with the transceiver failed
|
||||
*/
|
||||
int cc110x_wakeup(cc110x_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets the transceiver into SLEEP mode.
|
||||
*
|
||||
* Only @ref cc110x_wakeup can awake the device again.
|
||||
*/
|
||||
void cc110x_sleep(cc110x_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -31,10 +31,14 @@
|
||||
|
||||
static int sc_dump(int argc, char **argv);
|
||||
int sc_cc110x(int argc, char **argv);
|
||||
int sc_cc110x_sleep(int argc, char **argv);
|
||||
int sc_cc110x_wakeup(int argc, char **argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "dump", "Enable/disable dumping of frames", sc_dump },
|
||||
{ "cc110x", "Print the low level state of an CC110x device", sc_cc110x },
|
||||
{ "sleep", "Set CC110x onto sleep mode", sc_cc110x_sleep },
|
||||
{ "wakeup", "Wake-up CC110x device", sc_cc110x_wakeup },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -126,7 +130,13 @@ int main(void)
|
||||
"- Using \"cc110x\":\n"
|
||||
" - This tool will print low level details for all CC110x devices\n"
|
||||
" attached\n"
|
||||
" - This will be mostly useful for debugging, not for testing\n");
|
||||
" - This will be mostly useful for debugging, not for testing\n"
|
||||
"- Using \"sleep\":\n"
|
||||
" - Puts the given (or all, if no iface is given) transceiver into\n"
|
||||
" deep sleep mode\n"
|
||||
"- Using \"awake\":\n"
|
||||
" - Wakes up the given (or all, if no iface is given) transceiver(s)"
|
||||
" \n");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
|
@ -32,30 +32,30 @@ static const char *pa_settings[] = {
|
||||
static const char *state2s(cc110x_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case CC110X_STATE_IDLE:
|
||||
return "IDLE";
|
||||
case CC110X_STATE_FRAME_READY:
|
||||
return "Frame ready";
|
||||
case CC110X_STATE_OFF:
|
||||
return "Off";
|
||||
case CC110X_STATE_RX_MODE:
|
||||
return "RX mode";
|
||||
case CC110X_STATE_RECEIVING:
|
||||
return "RX mode and currently receiving frame";
|
||||
case CC110X_STATE_TX_MODE:
|
||||
return "TX";
|
||||
case CC110X_STATE_TX_COMPLETING:
|
||||
return "TX completing";
|
||||
case CC110X_STATE_FSTXON:
|
||||
return "Fast TX on";
|
||||
case CC110X_STATE_CALIBRATE:
|
||||
return "Calibrating";
|
||||
case CC110X_STATE_SETTLING:
|
||||
return "Settling";
|
||||
case CC110X_STATE_RXFIFO_OVERFLOW:
|
||||
return "RX FIFO overflow";
|
||||
case CC110X_STATE_TXFIFO_UNDERFLOW:
|
||||
return "TX FIFO underflow";
|
||||
case CC110X_STATE_IDLE:
|
||||
return "IDLE";
|
||||
case CC110X_STATE_FRAME_READY:
|
||||
return "Frame ready";
|
||||
case CC110X_STATE_OFF:
|
||||
return "Off";
|
||||
case CC110X_STATE_RX_MODE:
|
||||
return "RX mode";
|
||||
case CC110X_STATE_RECEIVING:
|
||||
return "RX mode and currently receiving frame";
|
||||
case CC110X_STATE_TX_MODE:
|
||||
return "TX";
|
||||
case CC110X_STATE_TX_COMPLETING:
|
||||
return "TX completing";
|
||||
case CC110X_STATE_FSTXON:
|
||||
return "Fast TX on";
|
||||
case CC110X_STATE_CALIBRATE:
|
||||
return "Calibrating";
|
||||
case CC110X_STATE_SETTLING:
|
||||
return "Settling";
|
||||
case CC110X_STATE_RXFIFO_OVERFLOW:
|
||||
return "RX FIFO overflow";
|
||||
case CC110X_STATE_TXFIFO_UNDERFLOW:
|
||||
return "TX FIFO underflow";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
@ -63,22 +63,22 @@ static const char *state2s(cc110x_state_t state)
|
||||
static const char *gdoconf2s(uint8_t conf)
|
||||
{
|
||||
switch (conf) {
|
||||
case CC110X_GDO_ON_RX_DATA:
|
||||
return "High when frame received or RX FIFO needs draining";
|
||||
case CC110X_GDO_ON_TX_DATA:
|
||||
return "Low when TX FIFO needs refilling";
|
||||
case CC110X_GDO_ON_TRANSMISSION:
|
||||
return "High while frame is incoming / outgoing";
|
||||
case CC110X_GDO_ON_CHANNEL_CLEAR:
|
||||
return "High when channel is clear";
|
||||
case CC110X_GDO_ON_PLL_IN_LOCK:
|
||||
return "High when frequency generator is on and PLL is in lock";
|
||||
case CC110X_GDO_CONSTANT_LOW:
|
||||
return "Constant low";
|
||||
case CC110X_GDO_CONSTANT_HIGH:
|
||||
return "Constant high";
|
||||
case CC110X_GDO0_ANALOG_TEMPERATURE:
|
||||
return "Analog output of the temperature sensor (GDO0 only)";
|
||||
case CC110X_GDO_ON_RX_DATA:
|
||||
return "High when frame received or RX FIFO needs draining";
|
||||
case CC110X_GDO_ON_TX_DATA:
|
||||
return "Low when TX FIFO needs refilling";
|
||||
case CC110X_GDO_ON_TRANSMISSION:
|
||||
return "High while frame is incoming / outgoing";
|
||||
case CC110X_GDO_ON_CHANNEL_CLEAR:
|
||||
return "High when channel is clear";
|
||||
case CC110X_GDO_ON_PLL_IN_LOCK:
|
||||
return "High when frequency generator is on and PLL is in lock";
|
||||
case CC110X_GDO_CONSTANT_LOW:
|
||||
return "Constant low";
|
||||
case CC110X_GDO_CONSTANT_HIGH:
|
||||
return "Constant high";
|
||||
case CC110X_GDO0_ANALOG_TEMPERATURE:
|
||||
return "Analog output of the temperature sensor (GDO0 only)";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
@ -109,6 +109,12 @@ static void print_state(cc110x_t *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->state == CC110X_STATE_OFF) {
|
||||
cc110x_release(dev);
|
||||
puts("Device in SLEEP mode");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reading out the RSSI changes it, as SPI communication seems to generate
|
||||
* some noise. Reading the RSSI out first yields up to 20 dBm lower
|
||||
* values... (E.g. about -100dBm instead of about -80dBm with no
|
||||
@ -174,34 +180,106 @@ static void print_state(cc110x_t *dev)
|
||||
int sc_cc110x(int argc, char **argv)
|
||||
{
|
||||
switch (argc) {
|
||||
case 1:
|
||||
for (unsigned i = 0; i < CC110X_NUM; i++){
|
||||
printf("CC110x #%u:\n", i);
|
||||
print_state(&_cc110x_devs[i]);
|
||||
case 1:
|
||||
for (unsigned i = 0; i < CC110X_NUM; i++){
|
||||
printf("CC110x #%u:\n", i);
|
||||
print_state(&_cc110x_devs[i]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
|
||||
printf("Usage: %s [NUM]\n"
|
||||
"\n"
|
||||
"Prints the status of the CC1100/CC1101 transceiver "
|
||||
"identified by NUM, or of\n"
|
||||
"all available CC110x transceivers if no argument is "
|
||||
"given\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
unsigned pos = atoi(argv[1]);
|
||||
if (pos >= CC110X_NUM) {
|
||||
puts("No such transceiver");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
|
||||
printf("Usage: %s [NUM]\n"
|
||||
"\n"
|
||||
"Prints the status of the CC1100/CC1101 transceiver "
|
||||
"identified by NUM, or of\n"
|
||||
"all available CC110x transceivers if no argument is "
|
||||
"given\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
unsigned pos = atoi(argv[1]);
|
||||
if (pos >= CC110X_NUM) {
|
||||
puts("No such transceiver");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("CC110x #%u:\n", pos);
|
||||
print_state(&_cc110x_devs[pos]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Usage: %s [NUM]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
printf("CC110x #%u:\n", pos);
|
||||
print_state(&_cc110x_devs[pos]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Usage: %s [NUM]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_cc110x_sleep(int argc, char **argv)
|
||||
{
|
||||
switch (argc) {
|
||||
case 1:
|
||||
for (unsigned i = 0; i < CC110X_NUM; i++){
|
||||
printf("Putting to sleep CC110x #%u:\n", i);
|
||||
cc110x_sleep(&_cc110x_devs[i]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
|
||||
printf("Usage: %s [NUM]\n"
|
||||
"\n"
|
||||
"Sets into sleep mode the CC1100/CC1101 transceiver "
|
||||
"identified by NUM, or of\n"
|
||||
"all available CC110x transceivers if no argument is "
|
||||
"given\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
unsigned pos = atoi(argv[1]);
|
||||
if (pos >= CC110X_NUM) {
|
||||
puts("No such transceiver");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("Putting to sleep CC110x #%u:\n", pos);
|
||||
cc110x_sleep(&_cc110x_devs[pos]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Usage: %s [NUM]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_cc110x_wakeup(int argc, char **argv)
|
||||
{
|
||||
switch (argc) {
|
||||
case 1:
|
||||
for (unsigned i = 0; i < CC110X_NUM; i++){
|
||||
printf("Waking up CC110x #%u:\n", i);
|
||||
cc110x_wakeup(&_cc110x_devs[i]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
|
||||
printf("Usage: %s [NUM]\n"
|
||||
"\n"
|
||||
"Wakes up the CC1100/CC1101 transceiver "
|
||||
"identified by NUM, or of\n"
|
||||
"all available CC110x transceivers if no argument is "
|
||||
"given\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
unsigned pos = atoi(argv[1]);
|
||||
if (pos >= CC110X_NUM) {
|
||||
puts("No such transceiver");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("Waking up CC110x #%u:\n", pos);
|
||||
cc110x_wakeup(&_cc110x_devs[pos]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Usage: %s [NUM]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
Loading…
Reference in New Issue
Block a user