1
0
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:
benpicco 2021-07-06 12:24:26 +02:00 committed by GitHub
commit 8f9233f329
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 418 additions and 207 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;