diff --git a/drivers/wireless/spirit/Make.defs b/drivers/wireless/spirit/Make.defs index d8debdb0d7..8962b301d6 100644 --- a/drivers/wireless/spirit/Make.defs +++ b/drivers/wireless/spirit/Make.defs @@ -39,5 +39,6 @@ ifeq ($(CONFIG_WL_SPIRIT),y) include wireless$(DELIM)spirit$(DELIM)lib$(DELIM)Make.defs include wireless$(DELIM)spirit$(DELIM)include$(DELIM)Make.defs +include wireless$(DELIM)spirit$(DELIM)drivers$(DELIM)Make.defs endif diff --git a/drivers/wireless/spirit/drivers/spirit_netdev.c b/drivers/wireless/spirit/drivers/spirit_netdev.c index fb0ce522c0..6b2b5b11d7 100644 --- a/drivers/wireless/spirit/drivers/spirit_netdev.c +++ b/drivers/wireless/spirit/drivers/spirit_netdev.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -67,17 +68,17 @@ #include "spirit_irq.h" #include "spirit_spi.h" #include "spirit_gpio.h" +#include "spirit_linearfifo.h" #include "spirit_commands.h" #include "spirit_radio.h" #include "spirit_pktbasic.h" #include "spirit_qi.h" +#include "spirit_management.h" #include "spirit_timer.h" #include "spirit_csma.h" #include -#include "spirit1.h" - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -94,6 +95,14 @@ # error 6LoWPAN network support is required. #endif +#ifndef CONFIG_SPIRIT_PKTLEN +# define CONFIG_SPIRIT_PKTLEN 128 +#endif + +#ifndef CONFIG_SPIRIT_MTU +# define CONFIG_SPIRIT_MTU 596 +#endif + /* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */ #define SPIRIT_WDDELAY (1*CLK_TCK) @@ -106,6 +115,13 @@ * Private Types ****************************************************************************/ +enum spirit_driver_state_e +{ + DRIVER_STATE_IDLE = 0, + DRIVER_STATE_SENDING, + DRIVER_STATE_RECEIVING +}; + /* SPIRIT1 device instance * * Make sure that struct ieee802154_radio_s remains first. If not it will break the @@ -114,34 +130,56 @@ struct spirit_driver_s { - struct ieee802154_driver_s ieee; /* Interface understood by the network */ - struct spirit_library_s spirit; /* Spirit library state */ - FAR const struct spirit1_lower_s *lower; /* Low-level MCU-specific support */ - struct work_s hpwork; /* Interrupt continuation work queue support */ - struct work_s lpwork; /* Net poll work queue support */ - WDOG_ID txpoll; /* TX poll timer */ - WDOG_ID txtimeout; /* TX timeout timer */ - bool ifup; /* Spirit is on and interface is up */ - bool receiving; /* Radio is receiving a packet */ - uint8_t panid[2]; /* PAN identifier, ffff = not set */ - uint16_t saddr; /* Short address, ffff = not set */ - uint8_t eaddr[8]; /* Extended address, ffffffffffffffff = not set */ - uint8_t channel; /* 11 to 26 for the 2.4 GHz band */ - uint8_t devmode; /* Device mode: device, coord, pancoord */ - uint8_t paenabled; /* Enable usage of PA */ - uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ - int32_t txpower; /* TX power in mBm = dBm/100 */ - struct ieee802154_cca_s cca; /* Clear channel assessement method */ + struct ieee802154_driver_s ieee; /* Interface understood by the network */ + struct spirit_library_s spirit; /* Spirit library state */ + FAR const struct spirit_lower_s *lower; /* Low-level MCU-specific support */ + FAR struct iob_s *txhead; /* Head of pending TX transfers */ + FAR struct iob_s *txtail; /* Tail of pending TX transfers */ + FAR struct iob_s *rxhead; /* Head of completed RX transfers */ + FAR struct iob_s *rxtail; /* Tail of completed RX transfers */ + struct work_s hpwork; /* Interrupt continuation work queue support */ + struct work_s lpwork; /* Net poll work queue support */ + WDOG_ID txpoll; /* TX poll timer */ + WDOG_ID txtimeout; /* TX timeout timer */ + sem_t exclsem; /* Mutually exclusive access */ + bool ifup; /* Spirit is on and interface is up */ + uint8_t state; /* See enum spirit_driver_state_e */ + uint8_t panid[2]; /* PAN identifier, ffff = not set */ + uint16_t saddr; /* Short address, ffff = not set */ + uint8_t eaddr[8]; /* Extended address, ffffffffffffffff = not set */ + uint8_t channel; /* 11 to 26 for the 2.4 GHz band */ + uint8_t devmode; /* Device mode: device, coord, pancoord */ + uint8_t paenabled; /* Enable usage of PA */ + uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ + int32_t txpower; /* TX power in mBm = dBm/100 */ + struct ieee802154_cca_s cca; /* Clear channel assessement method */ }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -/* Common TX logic */ +/* Helpers */ + +static void spirit_lock(FAR struct spirit_driver_s *priv); +#define spirit_unlock(priv) sem_post(&priv->exclsem); + +static int spirit_waitstatus(FAR struct spirit_library_s *spirit, + enum spirit_state_e state, unsigned int msec); +static int spirit_set_readystate(FAR struct spirit_driver_s *priv); + +/* TX-related logic */ static int spirit_transmit(FAR struct spirit_driver_s *priv); -static int spirit_txpoll(FAR struct net_driver_s *dev); +static void sprit_transmit_work(FAR void *arg); +static void spirit_schedule_transmit_work(FAR struct spirit_driver_s *priv); + +static int spirit_txpoll_callback(FAR struct net_driver_s *dev); + +/* RX-related logic */ + +static void sprit_receive_work(FAR void *arg); +static void spirit_schedule_receive_work(FAR struct spirit_driver_s *priv); /* Interrupt handling */ @@ -245,6 +283,147 @@ static const struct spirit_csma_init_s g_csma_init = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: spirit_waitstatus + * + * Description: + * Get exclusive access to the driver instance and to the spirit library. + * + * Parameters: + * priv - Reference to a driver state structure instance + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spirit_lock(FAR struct spirit_driver_s *priv) +{ + while (sem_wait(&priv->exclsem) < 0) + { + DEBUGASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: spirit_waitstatus + * + * Description: + * Poll until the Spirit status is the requested value or until a timeout + * occurs. + * + * Parameters: + * spirit - Reference to a Spirit library state structure instance + * state - That that we are waiting for. + * msec - Timeout in millisedonds + * + * Returned Value: + * OK on success; a negated errno on a timeout + * + * Assumptions: + * We have exclusive access to the driver state and to the spirit library. + * + ****************************************************************************/ + +static int spirit_waitstatus(FAR struct spirit_library_s *spirit, + enum spirit_state_e state, unsigned int msec) +{ + systime_t start; + unsigned int ticks; + unsigned int elapsed; + int ret; + + /* MSEC to clock ticks (add one to make sure we wait at least requested + * timeout) + */ + + ticks = MSEC2TICK(msec); + if (ticks == 0) + { + /* The timeout is below the current timer resolution */ + + ticks = 1; + } + + /* The time that we started the wait */ + + start = clock_systimer(); + + /* Loop until the status change occurs (or the wait times out) */ + + do + { + ret = spirit_update_status(spirit); + if (ret < 0) + { + return ret; + } + + elapsed = clock_systimer() - start; + } + while (spirit->u.state.MC_STATE != state && elapsed <= ticks); + + return (spirit->u.state.MC_STATE == state) ? OK : -ETIMEDOUT; +} + +/**************************************************************************** + * Name: spirit_set_readystate + * + * Description: + * Got to the READY state (if possible). + * + * Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * OK on success; a negated errno on a timeout + * + * Assumptions: + * We have exclusive access to the driver state and to the spirit library. + * + ****************************************************************************/ + +static int spirit_set_readystate(FAR struct spirit_driver_s *priv) +{ + FAR struct spirit_library_s *spirit = &priv->spirit; + int ret; + + DEBUGASSERT(priv->lower != NULL && priv->lower->enable != NULL); + priv->lower->enable(priv->lower, false); + + ret = spirit_command(spirit, CMD_FLUSHRXFIFO); + if (ret < 0) + { + goto errout_with_irqdisable; + } + + ret = spirit_update_status(spirit); + if (ret < 0) + { + goto errout_with_irqdisable; + } + + if (spirit->u.state.MC_STATE == MC_STATE_STANDBY) + { + ret = spirit_command(spirit, CMD_READY); + } + else if(spirit->u.state.MC_STATE == MC_STATE_RX) + { + ret = spirit_command(spirit, CMD_SABORT); + } + + if (ret < 0) + { + goto errout_with_irqdisable; + } + + ret = spirit_irq_clr_pending(spirit); + +errout_with_irqdisable: + priv->lower->enable(priv->lower, true); + return ret; +} + /**************************************************************************** * Name: spirit_transmit * @@ -257,36 +436,166 @@ static const struct spirit_csma_init_s g_csma_init = * Returned Value: * OK on success; a negated errno on failure * - * Assumptions: - * May or may not be called from an interrupt handler. In either case, - * the network is locked. - * ****************************************************************************/ static int spirit_transmit(FAR struct spirit_driver_s *priv) { - /* Verify that the hardware is ready to send another packet. If we get - * here, then we are committed to sending a packet; Higher level logic - * must have assured that there is no transmission in progress. + FAR struct spirit_library_s *spirit = &priv->spirit; + FAR struct iob_s *iob; + int ret; + + /* Check if there are any pending transfers in the TX AND if the hardware + * is not busy with another reception or transmission. */ - /* Increment statistics */ + spirit_lock(priv); + while (priv->txhead != NULL && priv->state == DRIVER_STATE_IDLE) + { + /* Remove the IOB from the head of the TX queue */ - NETDEV_TXPACKETS(&priv->ieee.i_dev); + iob = priv->txhead; + priv->txhead = iob->io_flink; - /* Send the packet: address=dev->d_buf, length=dev->d_len */ + if (priv->txhead == NULL) + { + priv->txtail = NULL; + } - /* Enable Tx interrupts */ + DEBUGASSERT(iob != NULL); - /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + /* Checks if the payload length is supported */ - (void)wd_start(priv->txtimeout, SPIRIT_TXTIMEOUT, - spirit_txtimeout_expiry, 1, (wdparm_t)priv); + if (iob->io_len > CONFIG_SPIRIT_PKTLEN) + { + NETDEV_RXDROPPED(&priv->ieee.i_dev); + iob_free(iob); + continue; + } + + priv->state = DRIVER_STATE_SENDING; + + /* Reset state to ready */ + + ret = spirit_set_readystate(priv); + if (ret < 0) + { + goto errout_with_iob; + } + + /* Sets the length of the packet to send */ + + ret = spirit_command(spirit, COMMAND_FLUSHTXFIFO); + if (ret < 0) + { + goto errout_with_iob; + } + + ret = spirit_pktbasic_set_payloadlen(spirit, iob->io_len); + if (ret < 0) + { + goto errout_with_iob; + } + + /* Enable CSMA */ + + ret = spirit_csma_enable(spirit, S_ENABLE); + if (ret < 0) + { + goto errout_with_iob; + } + + /* Write the packet to the linear FIFO */ + + ret = spirit_fifo_write(spirit, iob->io_data, iob->io_len); + if (ret < 0) + { + goto errout_with_iob; + } + + /* Puts the SPIRIT1 in TX state */ + + ret = spirit_command(spirit, COMMAND_TX); /* Starts transmission */ + if (ret < 0) + { + goto errout_with_iob; + } + + ret = spirit_waitstatus(spirit, MC_STATE_TX, 5); + if (ret < 0) + { + goto errout_with_iob; + } + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(priv->txtimeout, SPIRIT_TXTIMEOUT, + spirit_txtimeout_expiry, 1, (wdparm_t)priv); + } + + spirit_unlock(priv); return OK; + +errout_with_iob: + spirit_unlock(priv); + NETDEV_RXDROPPED(&priv->ieee.i_dev); + iob_free(iob); + return ret; } /**************************************************************************** - * Name: spirit_txpoll + * Name: sprit_transmit_work + * + * Description: + * Send data on the LP work queue. + * + * Parameters: + * arg - Reference to driver state structure (cast to void *) + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sprit_transmit_work(FAR void *arg) +{ + FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)arg; + + DEBUGASSERT(priv != NULL); + + net_lock(); + spirit_transmit(priv); + net_unlock(); +} + +/**************************************************************************** + * Name: spirit_schedule_transmit_work + * + * Description: + * Schedule to send data on the LP work queue. + * + * Parameters: + * priv - Reference to driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called from logic running the HP work queue. + * + ****************************************************************************/ + +static void spirit_schedule_transmit_work(FAR struct spirit_driver_s *priv) +{ + if(priv->txhead != NULL && priv->state == DRIVER_STATE_IDLE) + { + /* Schedule to perform the TX processing on the worker thread. */ + + work_queue(LPWORK, &priv->lpwork, sprit_transmit_work, priv, 0); + } +} + +/**************************************************************************** + * Name: spirit_txpoll_callback * * Description: * The transmitter is available, check if the network has any outgoing @@ -309,12 +618,68 @@ static int spirit_transmit(FAR struct spirit_driver_s *priv) * ****************************************************************************/ -static int spirit_txpoll(FAR struct net_driver_s *dev) +static int spirit_txpoll_callback(FAR struct net_driver_s *dev) { - FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)dev->d_private; + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + return 0; } +/**************************************************************************** + * Name: sprit_receive_work + * + * Description: + * Pass received packets to the network on the LP work queue. + * + * Parameters: + * arg - Reference to driver state structure (cast to void *) + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sprit_receive_work(FAR void *arg) +{ + FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)arg; + + DEBUGASSERT(priv != NULL); + + net_lock(); +#warning Missing logic + //spirit_receive(priv); + net_unlock(); +} + +/**************************************************************************** + * Name: spirit_schedule_receive_work + * + * Description: + * Schedule to receive data on the LP work queue. + * + * Parameters: + * priv - Reference to driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called from logic running the HP work queue. + * + ****************************************************************************/ + +static void spirit_schedule_receive_work(FAR struct spirit_driver_s *priv) +{ + if(priv->txhead != NULL && priv->state == DRIVER_STATE_IDLE) + { + /* Schedule to perform the TX processing on the worker thread. */ + + work_queue(LPWORK, &priv->lpwork, sprit_receive_work, priv, 0); + } +} + /**************************************************************************** * Name: spirit_interrupt_work * @@ -326,12 +691,15 @@ static int spirit_txpoll(FAR struct net_driver_s *dev) static void spirit_interrupt_work(FAR void *arg) { FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)arg; + FAR struct spirit_library_s *spirit; struct spirit_irqset_s irqstatus; DEBUGASSERT(priv != NULL); + spirit = &priv->spirit; /* Get the interrupt source from radio */ + spirit_lock(priv); DEBUGVERIFY(spirit_irq_get_pending(spirit, &irqstatus)); DEBUGVERIFY(spirit_irq_clr_pending(spirit)); @@ -341,15 +709,29 @@ static void spirit_interrupt_work(FAR void *arg) if (irqstatus.IRQ_RX_FIFO_ERROR != 0) { wlwarn("WARNING: Rx FIFO Error\n"); - DEBUGVERIFY(spirit_command(spririt, CMD_FLUSHRXFIFO)); - priv->receiving = false; + DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); + + priv->state = DRIVER_STATE_IDLE; + NETDEV_RXERRORS(&priv->ieee.i_dev); + + /* Send any pending packets */ + + spirit_csma_enable(spirit, S_DISABLE); + spirit_schedule_transmit_work(priv); } if (irqstatus.IRQ_TX_FIFO_ERROR != 0) { wlwarn("WARNING: Tx FIFO Error\n"); - DEBUGVERIFY(spirit_command(spririt, COMMAND_FLUSHTXFIFO)); - priv->receiving = false; + DEBUGVERIFY(spirit_command(spirit, COMMAND_FLUSHTXFIFO)); + + priv->state = DRIVER_STATE_IDLE; + NETDEV_TXERRORS(&priv->ieee.i_dev); + + /* Send any pending packets */ + + spirit_csma_enable(spirit, S_DISABLE); + spirit_schedule_transmit_work(priv); } /* The IRQ_TX_DATA_SENT bit notifies that a packet was sent. */ @@ -361,15 +743,33 @@ static void spirit_interrupt_work(FAR void *arg) DEBUGVERIFY(spirit_management_rxstrobe(spirit)); DEBUGVERIFY(spirit_command(spirit, CMD_RX)); + NETDEV_TXDONE(&priv->ieee.i_dev) + spirit_csma_enable(spirit, S_DISABLE); + /* Check if there are more packets to send */ + + DEBUGASSERT(priv->state == DRIVER_STATE_SENDING); + priv->state = DRIVER_STATE_IDLE; + spirit_schedule_transmit_work(priv); + } + +#ifdef CONFIG_SPIRIT_FIFOS + /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo. + * Necessary for sending large packets > sizeof(TX FIFO). + */ + + if (irqstatus.IRQ_TX_FIFO_ALMOST_EMPTY != 0) + { #warning Missing logic } +#endif /* The IRQ_VALID_SYNC bit is used to notify a new packet is coming */ if (irqstatus.IRQ_VALID_SYNC != 0) { - priv->receiving = true; + DEBUGASSERT(priv->state == DRIVER_STATE_IDLE); + priv->state = DRIVER_STATE_RECEIVING; } /* The IRQ_RX_DATA_READY notifies that a new packet has been received */ @@ -385,6 +785,12 @@ static void spirit_interrupt_work(FAR void *arg) if (count > CONFIG_IOB_BUFSIZE) { wlwarn("WARNING: Packet too large... dropping\n"); + DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); + priv->state = DRIVER_STATE_IDLE; + + /* Send any pending packets */ + + spirit_schedule_transmit_work(priv); } else { @@ -393,59 +799,100 @@ static void spirit_interrupt_work(FAR void *arg) * allocate a few I/O buffers? */ - iob = iob_alloc(); + iob = iob_alloc(0); if (iob == NULL) { wlerr("ERROR: Packet too large... dropping\n"); + + DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); + priv->state = DRIVER_STATE_IDLE; + NETDEV_RXDROPPED(&priv->ieee.i_dev); + + /* Send any pending packets */ + + spirit_schedule_transmit_work(priv); } + else + { - /* Read the packet into the I/O buffer */ + /* Read the packet into the I/O buffer */ - DEBUGVERIFY(spirit_fifo_read(count, iob->io_data); - iob->io_len = spirit_pktbasic_rxpktlen(spirit); + DEBUGVERIFY(spirit_fifo_read(spirit, iob->io_data, count)); + iob->io_len = spirit_pktbasic_rxpktlen(spirit); - DEBUGVERIFY(spirit_command(spririt, CMD_FLUSHRXFIFO)); - priv->receiving = false; + DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); + priv->state = DRIVER_STATE_IDLE; - /* Create the packet meta data and forward to the network */ + NETDEV_RXPACKETS(&priv->ieee.i_dev); + + /* Add the IO buffer to the tail of the completed RX transfers */ + + iob->io_flink = priv->rxtail; + priv->rxtail = iob; + + if (priv->rxhead == NULL) + { + priv->rxhead = iob; + } + + /* Create the packet meta data and forward to the network. This + * must be done on the LP work queue with the network lockes. + */ #warning Missing logic + + /* Forward the packet to the network. This must be done on the + * LP work queue with the network locked. + */ + + spirit_schedule_receive_work(priv); + + /* Try sending the next packet */ + + spirit_schedule_transmit_work(priv); + } } } - /* IRQ_RX_DATA_DISC indicates that Rx data wasdiscarded */ +#ifdef CONFIG_SPIRIT_FIFOS + /* The IRQ_RX_FIFO_ALMOST_FULL notifies an nearly full RX fifo. + * Necessary for receiving large packets > sizeof(RX FIFO). + */ + + if (irqstatus.IRQ_RX_FIFO_ALMOST_FULL != 0) + { +#warning Missing logic + } +#endif + + /* IRQ_RX_DATA_DISC indicates that Rx data was discarded */ if (irqstatus.IRQ_RX_DATA_DISC) { - DEBUGVERIFY(spirit_command(spririt, CMD_FLUSHRXFIFO)); - priv->receiving = false; + DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); + priv->state = DRIVER_STATE_IDLE; + NETDEV_RXDROPPED(&priv->ieee.i_dev); } /* Check the Spirit status. If it is IDLE, the setup to receive more */ DEBUGVERIFY(spirit_update_status(spirit)); - if (spirit->u.state.MC_STATE == SPIRIT1_STATE_READY) + if (spirit->u.state.MC_STATE == MC_STATE_READY) { - int timeout = 1000; - /* Set up to receive */ - DEBUGVERIFY(spirit_command(spririt, CMD_RX)); + DEBUGVERIFY(spirit_command(spirit, CMD_RX)); /* Wait for Spirit to enter the Tx state (or timeut) */ - do - { - DEBUGVERIFY(spirit_update_status(spirit)); - timeout--; - } - while (spirit->u.state.MC_STATE != MC_STATE_RX && timeout > 0); + DEBUGVERIFY(spirit_waitstatus(spirit, MC_STATE_RX, 1)); } /* Re-enable the interrupt. */ DEBUGASSERT(priv->lower != NULL && priv->lower->enable != NULL); priv->lower->enable(priv->lower, true); + spirit_unlock(priv); } /**************************************************************************** @@ -458,9 +905,9 @@ static void spirit_interrupt_work(FAR void *arg) static int spirit_interrupt(int irq, FAR void *context, FAR void *arg) { - FAR struct spirit_driver_s *dev = (FAR struct spirit_driver_s *)arg; + FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)arg; - DEBUGASSERT(dev != NULL); + DEBUGASSERT(priv != NULL); /* TODO: Determine if a TX transfer just completed . * If a TX transfer just completed, then cancel the TX timeout so @@ -481,10 +928,10 @@ static int spirit_interrupt(int irq, FAR void *context, FAR void *arg) * Interrupts are re-enabled in enc_irqworker() when the work is completed. */ - dev->lower->enable(dev->lower, false); + priv->lower->enable(priv->lower, false); - return work_queue(HPWORK, &dev->hpwork, spirit_interrupt_work, - (FAR void *)dev, 0); + return work_queue(HPWORK, &priv->hpwork, spirit_interrupt_work, + (FAR void *)priv, 0); } /**************************************************************************** @@ -524,7 +971,7 @@ static void spirit_txtimeout_work(FAR void *arg) /* Then poll the network for new XMIT data */ - (void)devif_poll(&priv->ieee.i_dev, spirit_txpoll); + (void)devif_poll(&priv->ieee.i_dev, spirit_txpoll_callback); net_unlock(); } @@ -600,7 +1047,8 @@ static inline void spirit_poll_process(FAR struct spirit_driver_s *priv) * OK on success * * Assumptions: - * The network is locked. + * Scheduled on the LP worker thread from the poll timer expiration + * handler. * ****************************************************************************/ @@ -616,18 +1064,9 @@ static void spirit_poll_work(FAR void *arg) net_lock(); - /* Perform the poll */ + /* Perform the periodic poll */ - /* Check if there is room in the send another TX packet. We cannot perform - * the TX poll if he are unable to accept another packet for transmission. - */ - - /* If so, update TCP timing states and poll the network for new XMIT data. - * Hmmm.. might be bug here. Does this mean if there is a transmit in - * progress, we will missing TCP time state updates? - */ - - (void)devif_timer(&priv->ieee.i_dev, spirit_txpoll); + (void)devif_timer(&priv->ieee.i_dev, spirit_txpoll_callback); /* Setup the watchdog poll timer again */ @@ -676,49 +1115,86 @@ static void spirit_poll_expiry(int argc, wdparm_t arg, ...) * Returned Value: * None * - * Assumptions: + * Called from the network layer and running on the LP working thread. * ****************************************************************************/ static int spirit_ifup(FAR struct net_driver_s *dev) { FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)dev->d_private; + FAR struct spirit_library_s *spirit; + int ret; -#ifdef CONFIG_NET_IPv4 - ninfo("Bringing up: %d.%d.%d.%d\n", - dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, - (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); -#endif -#ifdef CONFIG_NET_IPv6 - ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], - dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], - dev->d_ipv6addr[6], dev->d_ipv6addr[7]); -#endif + DEBUGASSERT(priv != NULL); + spirit = &priv->spirit; - /* Initialize PHYs, the Spirit interface, and setup up Spirit interrupts */ + if (!priv->ifup) + { + ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); - /* Instantiate the MAC address from dev->d_mac.ether.ether_addr_octet */ + /* Disable spirit interrupts */ -#ifdef CONFIG_NET_ICMPv6 - /* Set up IPv6 multicast address filtering */ + DEBUGASSERT(priv->lower->enable != NULL); + priv->lower->enable(priv->lower, false); - spirit_ipv6multicast(priv); -#endif + /* Ensure we are in READY state as we go from there to Rx. + * Since spirit interrupts are disabled, we don't need to be concerned + * about mutual exclusion. + */ - /* Set and activate a timer process */ + ret = spirit_command(spirit, CMD_READY); + if (ret < 0) + { + return ret; + } - (void)wd_start(priv->txpoll, SPIRIT_WDDELAY, spirit_poll_expiry, 1, - (wdparm_t)priv); + ret = spirit_waitstatus(spirit, MC_STATE_READY, 5); + if (ret < 0) + { + goto error_with_ifalmostup; + } - /* Enable the Spirit interrupt */ + /* Now we go to Rx */ - priv->ifup = true; + ret = spirit_command(spirit, CMD_RX); + if (ret < 0) + { + goto error_with_ifalmostup; + } - DEBUGASSERT(priv->lower->enable != NULL); - priv->lower->enable(priv->lower, true); + ret = spirit_waitstatus(spirit, MC_STATE_RX, 5); + if (ret < 0) + { + goto error_with_ifalmostup; + } + + /* Instantiate the MAC address from dev->d_mac.ether.ether_addr_octet */ +#warning Missing logic + + /* Set and activate a timer process */ + + (void)wd_start(priv->txpoll, SPIRIT_WDDELAY, spirit_poll_expiry, 1, + (wdparm_t)priv); + + /* Enables the interrupts from the SPIRIT1 */ + + DEBUGASSERT(priv->lower->enable != NULL); + priv->lower->enable(priv->lower, true); + + /* We are up! */ + + priv->ifup = true; + } return OK; + +error_with_ifalmostup: + priv->ifup = true; + (void)spirit_ifdown(dev); + return ret; } /**************************************************************************** @@ -734,36 +1210,80 @@ static int spirit_ifup(FAR struct net_driver_s *dev) * None * * Assumptions: + * Called from the network layer and running on the LP working thread. * ****************************************************************************/ static int spirit_ifdown(FAR struct net_driver_s *dev) { FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)dev->d_private; - irqstate_t flags; + FAR struct spirit_library_s *spirit; + int ret = OK; - /* Disable the Spirit interrupt */ + DEBUGASSERT(priv != NULL); + spirit = &priv->spirit; - flags = enter_critical_section(); + if (priv->ifup) + { + irqstate_t flags; + int status; - DEBUGASSERT(priv->lower->enable != NULL); - priv->lower->enable(priv->lower, false); + /* Disable the Spirit interrupt */ - /* Cancel the TX poll timer and TX timeout timers */ + flags = enter_critical_section(); - wd_cancel(priv->txpoll); - wd_cancel(priv->txtimeout); + DEBUGASSERT(priv->lower->enable != NULL); + priv->lower->enable(priv->lower, false); - /* Put the EMAC in its reset, non-operational state. This should be - * a known configuration that will guarantee the spirit_ifup() always - * successfully brings the interface back up. - */ + /* Cancel the TX poll timer and TX timeout timers */ - /* Mark the device "down" */ + wd_cancel(priv->txpoll); + wd_cancel(priv->txtimeout); + leave_critical_section(flags); - priv->ifup = false; - leave_critical_section(flags); - return OK; + /* First stop Rx/Tx + * Since spirit interrupts are disabled, we don't need to be concerned + * about mutual exclusion. + */ + + status = spirit_command(spirit, CMD_SABORT); + if (status < 0 && ret == 0) + { + ret = status; + } + + /* Clear any pending irqs */ + + status = spirit_irq_clr_pending(spirit); + if (status < 0 && ret == 0) + { + ret = status; + } + + status = spirit_waitstatus(spirit, MC_STATE_READY, 5); + if (status < 0 && ret == 0) + { + ret = status; + } + + /* Put the SPIRIT1 in STANDBY */ + + status = spirit_command(spirit, CMD_STANDBY); + if (status < 0 && ret == 0) + { + ret = status; + } + + status = spirit_waitstatus(spirit, MC_STATE_STANDBY, 5); + if (status < 0 && ret == 0) + { + ret = status; + } + + priv->ifup = false; + } + + return ret; } /**************************************************************************** @@ -803,7 +1323,7 @@ static void spirit_txavail_work(FAR void *arg) /* If so, then poll the network for new XMIT data */ - (void)devif_poll(&priv->ieee.i_dev, spirit_txpoll); + (void)devif_poll(&priv->ieee.i_dev, spirit_txpoll_callback); } net_unlock(); @@ -824,7 +1344,7 @@ static void spirit_txavail_work(FAR void *arg) * None * * Assumptions: - * Called in normal user mode + * Called from network logic running on the LP work queue * ****************************************************************************/ @@ -837,6 +1357,7 @@ static int spirit_txavail(FAR struct net_driver_s *dev) * availability action. */ + spirit_lock(priv); if (work_available(&priv->lpwork)) { /* Schedule to serialize the poll on the worker thread. */ @@ -844,6 +1365,7 @@ static int spirit_txavail(FAR struct net_driver_s *dev) work_queue(LPWORK, &priv->lpwork, spirit_txavail_work, priv, 0); } + spirit_unlock(priv); return OK; } @@ -874,8 +1396,8 @@ static int spirit_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) * Name: spirit_rmmac * * Description: - * NuttX Callback: Remove the specified MAC address from the hardware multicast - * address filtering + * NuttX Callback: Remove the specified MAC address from the hardware + * multicast address filtering * * Parameters: * dev - Reference to the NuttX driver state structure @@ -943,6 +1465,7 @@ static int spirit_ioctl(FAR struct net_driver_s *dev, int cmd, /* Decode and dispatch the driver-specific IOCTL command */ + spirit_lock(priv); switch (cmd) { /* Add cases here to support the IOCTL commands */ @@ -952,6 +1475,7 @@ static int spirit_ioctl(FAR struct net_driver_s *dev, int cmd, ret = -ENOTTY; /* Special return value for this case */ } + spirit_unlock(priv); return ret; } #endif @@ -970,6 +1494,9 @@ static int spirit_ioctl(FAR struct net_driver_s *dev, int cmd, * A non-negative MAC headeer length is returned on success; a negated * errno value is returned on any failure. * + * Assumptions: + * Called from network logic running on the low-priority work queue. + * ****************************************************************************/ static int spirit_get_mhrlen(FAR struct ieee802154_driver_s *netdev, @@ -980,6 +1507,9 @@ static int spirit_get_mhrlen(FAR struct ieee802154_driver_s *netdev, DEBUGASSERT(netdev != NULL && netdev->i_dev.d_private != NULL && meta != NULL); priv = (FAR struct spirit_driver_s *)netdev->i_dev.d_private; + spirit_lock(priv); +#warning Missing logic + spirit_unlock(priv); return -ENOSYS; } @@ -998,6 +1528,9 @@ static int spirit_get_mhrlen(FAR struct ieee802154_driver_s *netdev, * Zero (OK) returned on success; a negated errno value is returned on * any failure. * + * Assumptions: + * Called from network logic with the network locked. + * ****************************************************************************/ static int spirit_req_data(FAR struct ieee802154_driver_s *netdev, @@ -1006,7 +1539,6 @@ static int spirit_req_data(FAR struct ieee802154_driver_s *netdev, { FAR struct spirit_driver_s *priv; FAR struct iob_s *iob; - int ret; wlinfo("Received framelist\n"); @@ -1017,6 +1549,7 @@ static int spirit_req_data(FAR struct ieee802154_driver_s *netdev, /* Add the incoming list of frames to the MAC's outgoing queue */ + spirit_lock(priv); for (iob = framelist; iob != NULL; iob = framelist) { /* Increment statistics */ @@ -1032,18 +1565,23 @@ static int spirit_req_data(FAR struct ieee802154_driver_s *netdev, # warning Missing logic /* Add the IOB to the queue of outgoing IOBs. */ -# warning Missing logic - /* If there are no transmissions in progress, then start tranmssion - * of the frame in the IOB at the head of the IOB queue. + iob->io_flink = priv->txtail; + priv->txtail = iob; + + if (priv->txhead == NULL) + { + priv->txhead = iob; + } + + /* If there are no transmissions or receptions in progress, then start + * tranmission of the frame in the IOB at the head of the IOB queue. */ -# warning Missing logic - //NETDEV_TXERRORS(&priv->md_dev.i_dev); - - NETDEV_TXDONE(&priv->md_dev.i_dev); + spirit_transmit(priv); } + spirit_unlock(priv); return OK; } @@ -1283,14 +1821,12 @@ int spirit_hw_initialize(FAR struct spirit_driver_s *priv, int spirit_netdev_initialize(FAR struct spi_dev_s *spi, - FAR const struct spirit1_lower_s *lower) + FAR const struct spirit_lower_s *lower) { FAR struct spirit_driver_s *priv; FAR struct ieee802154_driver_s *ieee; FAR struct net_driver_s *dev; -#if 0 FAR uint8_t *pktbuf; -#endif int ret; /* Allocate a driver state structure instance */ @@ -1303,8 +1839,7 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi, } /* Allocate a packet buffer */ -#warning Missing logic -#if 0 + pktbuf = (uint8_t *)kmm_zalloc(CONFIG_SPIRIT_MTU + CONFIG_NET_GUARDSIZE); if (priv == NULL) { @@ -1312,7 +1847,6 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi, ret = -ENOMEM; goto errout_with_alloc; } -#endif /* Attach the interface, lower driver, and devops */ @@ -1325,6 +1859,8 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi, DEBUGASSERT(priv->txpoll != NULL && priv->txtimeout != NULL); + sem_init(&priv->exclsem, 0, 1); + /* Initialize the IEEE 802.15.4 network device fields */ ieee = &priv->ieee; @@ -1334,9 +1870,7 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi, /* Initialize the common network device fields */ dev = &ieee->i_dev; -#if 0 dev->d_buf = pktbuf; /* Single packet buffer */ -#endif dev->d_ifup = spirit_ifup; /* I/F up (new IP address) callback */ dev->d_ifdown = spirit_ifdown; /* I/F down callback */ dev->d_txavail = spirit_txavail; /* New TX data callback */ diff --git a/drivers/wireless/spirit/include/spirit_aes.h b/drivers/wireless/spirit/include/spirit_aes.h new file mode 100644 index 0000000000..668cafe630 --- /dev/null +++ b/drivers/wireless/spirit/include/spirit_aes.h @@ -0,0 +1,285 @@ +/******************************************************************************* + * include/nuttx/wireless/spirit/include/spirit_aes.h + * Configuration and management of SPIRIT AES Engine. + * + * Copyright(c) 2015 STMicroelectronics + * Author: VMA division - AMS + * Version 3.2.2 08-July-2015 + * + * Adapted for NuttX by: + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_AES_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_AES_H + +/* In order to encrypt data, the user must manage the AES_END IRQ. The data + * must be split in blocks of 16 bytes and written into the AES DATA IN + * registers. Then, after the key is written into the AES KEY registers, a + * command of Execute encryption has to be sent. + * + * Example: + * + * spirit_aes_write_datain(spirit, inbuffer , buflen); + * spirit_aes_encrypt(spirit); + * + * Wait for encryption done (signalled via interrupt) + * + * spirit_aes_read_dataout(espirit, outbuffer , buflen); + * + * In order to decrypt data, the user must manage the AES_END IRQ and have a + * decryption key. There are two operative modes to make the data + * decryption: + * + * 1. Derive the decryption key from the encryption key and decrypt data + * directly using the spirit_aes_derivekey_decrypt() function + * + * Example: + * + * spirit_aes_write_datain(spirit, inbuffer , buflen); + * spirit_aes_derivekey_decrypt(spirit); + * + * Wait for key derivation to complete (signalled via interrupt) + * + * spirit_aes_read_dataout(spirit, outbuffer , buflen); + * + * 2 Derive the decryption key from the encryption key using the + * spirit_aes_enc2deckey() function, store it into the AES KEY + * registers and then decrypt data using the spirit_aes_decrypt() + * function + * + * Example: + * + * spirit_aes_write_datain(spirit, keyenc, 16); + * spirit_aes_enc2deckey(spirit); + * + * Wait for key derivation to complete (signalled via interrupt) + * + * spirit_aes_read_dataout(spirit, keydec, 16); + * + * spirit_aes_write_key(key_dec); + * spirit_aes_write_datain(inbuffer , 16); + * spirit_aes_decrypt(spirit); + * + * Wait for encryption done (signalled via interrupt) + * + * spirit_aes_read_dataout(spirit, outbuffer, buflen); + */ + +/****************************************************************************** + * Included Files + ******************************************************************************/ + +#include "spirit_regs.h" +#include "spirit_types.h" + +/****************************************************************************** + * Public Function Prototypes + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************************************** + * Name: spirit_aes_enable + * + * Description: + * Enables or Disables the AES engine. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate new state for AES engine. + * This parameter can be: S_ENABLE or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_enable(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate); + +/****************************************************************************** + * Name: + * + * Description: + * Writes the data to encrypt or decrypt, or the encryption key for the + * derive decryption key operation into the AES_DATA_IN registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * buffer - Pointer to the user data buffer. The first byte of the array + * must be the MSB byte and it will be put in the AES_DATA_IN[0] + * register, while the last one must be the LSB and it will be + * put in the AES_DATA_IN[buflen-1] register. If data to write + * are less than 16 bytes the remaining AES_DATA_IN registers + * will be filled with bytes equal to 0. + * buflen - Length of data in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_write_datain(FAR struct spirit_library_s *spirit, + FAR const uint8_t *buffer, uint8_t buflen); + +/****************************************************************************** + * Name: + * + * Description: + * Returns the encrypted or decrypted data or the decription key from the + * AES_DATA_OUT register. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * buffer - pointer to the user data buffer. The AES_DATA_OUT[0] + * register value will be put as first element of the buffer + * (MSB), while the AES_DAT_OUT[buflen-1] register value will be + * put as last element of the buffer (LSB). + * buflen - Length of data to read in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_read_dataout(FAR struct spirit_library_s *spirit, + FAR uint8_t *buffer, uint8_t buflen); + +/****************************************************************************** + * Name: spirit_aes_write_key + * + * Description: + * Writes the encryption key into the AES_KEY_IN register. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * key - Pointer to the buffer of 4 words containing the AES key. + * The first byte of the buffer must be the most significant byte + * AES_KEY_0 of the AES key. The last byte of the buffer must be + * the less significant byte AES_KEY_15 of the AES key. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_write_key(FAR struct spirit_library_s *spirit, + FAR const uint8_t *key); + +/****************************************************************************** + * Name: + * + * Description: + * Returns the encryption/decryption key from the AES_KEY_IN register. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * key pointer to the buffer of 4 words (16 bytes) containing the AES key. + * The first byte of the buffer shall be the most significant byte AES_KEY_0 of the AES key. + * The last byte of the buffer shall be the less significant byte AES_KEY_15 of the AES key. + * This parameter is an uint8_t*. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_read_key(FAR struct spirit_library_s *spirit, FAR uint8_t *key); + +/****************************************************************************** + * Name: spirit_aes_enc2deckey + * + * Description: + * Derives the decryption key from a given encryption key. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_enc2deckey(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_aes_encrypt + * + * Description: + * Executes the encryption operation. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_encrypt(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: + * + * Description: + * Executes the decryption operation. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_decrypt(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_aes_derivekey_decrypt + * + * Description: + * Executes the key derivation and the decryption operation. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_derivekey_decrypt(FAR struct spirit_library_s *spirit); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_AES_H */ diff --git a/drivers/wireless/spirit/include/spirit_calibration.h b/drivers/wireless/spirit/include/spirit_calibration.h index e5e6e77c09..90532e73f7 100644 --- a/drivers/wireless/spirit/include/spirit_calibration.h +++ b/drivers/wireless/spirit/include/spirit_calibration.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_calibration.h + * include/nuttx/wireless/spirit/include/spirit_calibration.h * Configuration and management of SPIRIT VCO-RCO calibration. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,38 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_CALIBRAITON_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_CALIBRAITON_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_CALIBRAITON_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_CALIBRAITON_H + +/* This module allows the user to set some parameters which deal with the + * oscillators calibration. The state machine of Spirit contemplates some + * optional calibrating operations in the transition between the READY and + * the LOCK state. The user is allowed to enable or disable the automatic + * RCO/VCO calibration by calling the functions spirit_calib_enable_vco() + * spirit_calib_enable_rco(). + * + * The following example shows how to do an initial calibration of VCO. + * + * Example: + * + * uint8_t caldata; + * + * spirit_calib_enable_vco(spirit, S_ENABLE); + * spirit_command(spirit, CMD_LOCKTX); + * + * while(spirit->state.MC_STATE != MC_STATE_LOCK) + * { + * (void)spirit_update_status(spirit); + * } + * + * caldata = spirit_calib_get_vcotxcal(spirit); + * spirit_calib_set_vcotxcal(spirit, caldata); + * + * spirit_command(spirit, CMD_READY); + * spirit_calib_enable_vco(spirit, S_DISABLE); + * + * Similar operations can be done for the RCO calibrator. + */ /****************************************************************************** * Included Files @@ -50,7 +80,13 @@ /* Macros used in assertions */ -#define IS_VCO_SEL(ref) ((ref) == VCO_L || (ref) == VCO_H) +#define IS_VCO_SEL(ref) \ + ((ref) == VCO_L || (ref) == VCO_H) +#define IS_VCO_WIN(ref) \ + ((ref) == CALIB_TIME_7_33_US_24MHZ || (ref) == CALIB_TIME_14_67_US_24MHZ ||\ + (ref) == CALIB_TIME_29_33_US_24MHZ || (ref) == CALIB_TIME_58_67_US_24MHZ ||\ + (ref) == CALIB_TIME_6_77_US_26MHZ || (ref) == CALIB_TIME_13_54_US_26MHZ ||\ + (ref) == CALIB_TIME_27_08_US_26MHZ || (ref) == CALIB_TIME_54_15_US_26MHZ) /****************************************************************************** * Public Types @@ -60,8 +96,32 @@ enum spirit_vcoselect_e { - VCO_L = 0, /* VCO lower */ - VCO_H /* VCO higher */ + VCO_L = 0, /* VCO lower */ + VCO_H /* VCO higher */ +}; + +/* VCO / RCO calibration window. */ + +enum spirit_vcowin_e +{ + + CALIB_TIME_7_33_US_24MHZ = 0x00, /* Calibration window of 7.33 us + * with XTAL=24MHz */ + CALIB_TIME_14_67_US_24MHZ, /* Calibration window of 14.67 us + * with XTAL=24MHz */ + CALIB_TIME_29_33_US_24MHZ, /* Calibration window of 29.33 us + * with XTAL=24MHz */ + CALIB_TIME_58_67_US_24MHZ, /* Calibration window of 58.67 us + * with XTAL=24MHz */ + + CALIB_TIME_6_77_US_26MHZ = 0x00, /* Calibration window of 6.77 us + * with XTAL=26MHz */ + CALIB_TIME_13_54_US_26MHZ, /* Calibration window of 13.54 us + * with XTAL=26MHz */ + CALIB_TIME_27_08_US_26MHZ, /* Calibration window of 27.08 us + * with XTAL=26MHz */ + CALIB_TIME_54_15_US_26MHZ /* Dalibration window of 54.15 us with + * XTAL=26MHz */ }; /****************************************************************************** @@ -106,6 +166,46 @@ int spirit_calib_enable_rco(FAR struct spirit_library_s *spirit, int spirit_calib_enable_vco(FAR struct spirit_library_s *spirit, enum spirit_functional_state_e newstate); +/****************************************************************************** + * Name: spirit_calibration_set_rcocal + * + * Description: + * Sets the RCO calibration words. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * rwt - RWT word for RCO calibration. + * rfb - RFB word for RCO calibration. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_calibration_set_rcocal(FAR struct spirit_library_s *spirit, + uint8_t rwt, uint8_t rfb); + +/****************************************************************************** + * Name: spirit_calibration_get_rcocal + * + * Description: + * Returns the RCO calibration words. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * rwt - Pointer to the variable in which the RWT word has to be + * stored. + * rfb - Pointer to the variable in which the RFB word has to be + * stored. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_calibration_get_rcocal(FAR struct spirit_library_s *spirit, + FAR uint8_t *rwt, FAR uint8_t *rfb); + /****************************************************************************** * Name: spirit_calib_get_vcocal * @@ -190,6 +290,51 @@ int spirit_calib_set_vcorxcal(FAR struct spirit_library_s *spirit, uint8_t spirit_calib_get_vcorxcal(FAR struct spirit_library_s *spirit); +/****************************************************************************** + * Name: spirit_calibration_set_vcowin + * + * Description: + * Sets the VCO calibration window. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * refword - Value of REFWORD corresponding to the Ref_period according to + * the formula: + * + * CALIBRATION_WIN = 11*Ref_period/fxo. + * + * This parameter can be a value of enum spirit_vcowin_e. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_calibration_set_vcowin(FAR struct spirit_library_s *spirit, + enum spirit_vcowin_e refword); + +/****************************************************************************** + * Name: spirit_calibration_get_vcowin + * + * Description: + * Returns the VCO calibration window. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Value of REFWORD corresponding to the Ref_period according to the + * formula: + * + * CALIBRATION_WIN = 11*Ref_period/fxo. + * + * This parameter can be a value of enum spirit_vcowin_e. + * + ******************************************************************************/ + +enum spirit_vcowin_e + spirit_calibration_get_vcowin(FAR struct spirit_library_s *spirit); + /****************************************************************************** * Name: spirit_calib_select_vco * @@ -224,4 +369,4 @@ int spirit_calib_select_vco(FAR struct spirit_library_s *spirit, enum spirit_vcoselect_e spirit_calib_get_vco(FAR struct spirit_library_s *spirit); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_CALIBRAITON_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_CALIBRAITON_H */ diff --git a/drivers/wireless/spirit/include/spirit_commands.h b/drivers/wireless/spirit/include/spirit_commands.h index 3124b74ded..55192a6b84 100644 --- a/drivers/wireless/spirit/include/spirit_commands.h +++ b/drivers/wireless/spirit/include/spirit_commands.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_commands.h + * include/nuttx/wireless/spirit/include/spirit_commands.h * Management of SPIRIT Commands. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_COMMANDS_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_COMMANDS_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_COMMANDS_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_COMMANDS_H /* In this module can be found all the API used to strobe commands to * Spirit. Every command strobe is an SPI transaction with a specific command @@ -144,4 +144,4 @@ enum spirit_cmd_e } #endif -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_COMMANDS_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_COMMANDS_H */ diff --git a/drivers/wireless/spirit/include/spirit_config.h b/drivers/wireless/spirit/include/spirit_config.h index 0e03b04dee..18494ea8b5 100644 --- a/drivers/wireless/spirit/include/spirit_config.h +++ b/drivers/wireless/spirit/include/spirit_config.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_config.h + * include/nuttx/wireless/spirit/include/spirit_config.h * Spirit Configuration and useful defines * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_CONFIG_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_CONFIG_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_CONFIG_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_CONFIG_H /****************************************************************************** * Included Files @@ -43,4 +43,4 @@ #define DOUBLE_XTAL_THR 30000000 -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_CONFIG_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_CONFIG_H */ diff --git a/drivers/wireless/spirit/include/spirit_csma.h b/drivers/wireless/spirit/include/spirit_csma.h index 8a0a0732a3..6e69af7330 100644 --- a/drivers/wireless/spirit/include/spirit_csma.h +++ b/drivers/wireless/spirit/include/spirit_csma.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_csma.h + * include/nuttx/wireless/spirit/include/spirit_csma.h * Configuration and management of SPIRIT CSMA. * * Copyright(c) 2015 STMicroelectronics @@ -165,6 +165,330 @@ struct spirit_csma_init_s * Public Function Prototypes ******************************************************************************/ +/****************************************************************************** + * Name: spirit_csma_initialize + * + * Description: + * Initializes the SPIRIT CSMA according to the specified parameters in the + * struct spirit_csma_init_s. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * csmainit - Reference to the Csma init structure. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_initialize(FAR struct spirit_library_s *spirit, + FAR const struct spirit_csma_init_s *csmainit); + +/****************************************************************************** + * Name: spirit_csma_getinfo + * + * Description: + * Returns the fitted structure struct spirit_csma_init_s starting from the + * registers values. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * csmainit - Csma structure to be fitted. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_getinfo(FAR struct spirit_library_s *spirit, + FAR struct spirit_csma_init_s *csmainit); + +/****************************************************************************** + * Name: spirit_csma_enable + * + * Description: + * Enables or Disables the CSMA. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - The state of the CSMA mode. This parameter can be: S_ENABLE + * or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_enable(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate); + +/****************************************************************************** + * Name: spirit_csma_getstate + * + * Description: + * Gets the CSMA mode. Says if it is enabled or disabled. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CSMA mode. + * + ******************************************************************************/ + +enum spirit_functional_state_e + spirit_csma_getstate(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_persistentmode + * + * Description: + * Enables or Disables the persistent CSMA mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - The state of the persistent CSMA mode. This parameter can + * be: S_ENABLE or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_persistentmode(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate); + +/****************************************************************************** + * Name: spirit_csma_get_persistentmode + * + * Description: + * Gets the persistent CSMA mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CSMA persistent mode. + * + ******************************************************************************/ + +enum spirit_functional_state_e + spirit_csma_get_persistentmode(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_seedreload + * + * Description: + * Enables or Disables the seed reload mode (if enabled it reloads the back- + * off generator seed using the value written in the BU_COUNTER_SEED register). + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - The state of the seed reload mode. This parameter can be: + * S_ENABLE or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_seedreload(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate); + +/****************************************************************************** + * Name: spirit_csma_get_seedreload + * + * Description: + * Gets the seed reload state. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CSMA seed reload mode. + * + ******************************************************************************/ + +enum spirit_functional_state_e + spirit_csma_get_seedreload(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_bucounterseed + * + * Description: + * Sets the BU counter seed (BU_COUNTER_SEED register). The CSMA back off + * time is given by the formula: BO = rand(2^NB)*BU. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * seed - Seed of the random number generator used to apply the BBE + * algorithm. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_bucounterseed(FAR struct spirit_library_s *spirit, + uint16_t seed); + +/****************************************************************************** + * Name: spirit_csma_get_bucounterseed + * + * Description: + * Returns the BU counter seed (BU_COUNTER_SEED register). + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Seed of the random number generator used to apply the BBE algorithm. + * + ******************************************************************************/ + +uint16_t spirit_csma_get_bucounterseed(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_buprescaler + * + * Description: + * Sets the BU prescaler. The CSMA back off time is given by the formula: + * BO = rand(2^NB)*BU. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * prescaler - Used to program the back-off unit BU. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_buprescaler(FAR struct spirit_library_s *spirit, + uint8_t prescaler); + +/****************************************************************************** + * Name: spirit_csma_get_buprescaler + * + * Description: + * Returns the BU prescaler. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Value back-off unit (BU). + * + ******************************************************************************/ + +uint8_t spirit_csma_get_buprescaler(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_ccaperiod + * + * Description: + * Sets the CCA period. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * multbit - Value of CCA period to store. This parameter can be a value + * of enum spirit_cca_period_e. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_ccaperiod(FAR struct spirit_library_s *spirit, + enum spirit_cca_period_e multbit); + +/****************************************************************************** + * Name: spirit_csma_get_ccaperiod + * + * Description: + * Returns the CCA period. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CCA period. + * + ******************************************************************************/ + +enum spirit_cca_period_e + spirit_csma_get_ccaperiod(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_ccalen + * + * Description: + * Sets the CCA length. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * ccalen - The CCA length (a value between 1 and 15 that multiplies the + * CCA period). This parameter can be any value of enum + * spirit_csmalen_e. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_ccalen(FAR struct spirit_library_s *spirit, + enum spirit_csmalen_e ccalen); + +/****************************************************************************** + * Name: spirit_csma_get_ccalen + * + * Description: + * Returns the CCA length. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CCA length. + * + ******************************************************************************/ + +uint8_t spirit_csma_get_ccalen(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_csma_set_maxbackoff + * + * Description: + * Sets the max number of back-off. If reached Spirit stops the transmission. + * + * Input Parameters: + * maxnb the max number of back-off. + * This parameter is an uint8_t. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_maxbackoff(FAR struct spirit_library_s *spirit, + uint8_t maxnb); + +/****************************************************************************** + * Name: spirit_csma_get_maxbackoff + * + * Description: + * Returns the max number of back-off. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Max number of back-off. + * + ******************************************************************************/ + +uint8_t spirit_csma_get_maxbackoff(FAR struct spirit_library_s *spirit); + #ifdef __cplusplus } #endif diff --git a/drivers/wireless/spirit/include/spirit_directrf.h b/drivers/wireless/spirit/include/spirit_directrf.h new file mode 100644 index 0000000000..bbf412748c --- /dev/null +++ b/drivers/wireless/spirit/include/spirit_directrf.h @@ -0,0 +1,182 @@ +/****************************************************************************** + * include/nuttx/wireless/spirit/include/spirit_directrf.h + * Configuration and management of SPIRIT direct transmission / receive modes. + * + * Copyright(c) 2015 STMicroelectronics + * Author: VMA division - AMS + * Version 3.2.2 08-July-2015 + * + * Adapted for NuttX by: + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_DIRECTRF_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_DIRECTRF_H + +/* This module contains functions to manage the direct Tx/Rx mode. + * The user can choose the way to send data to Spirit through the + * enumerative types DirectTx/DirectRx. + */ + +/****************************************************************************** + * Included Files + ******************************************************************************/ + +#include "spirit_regs.h" +#include "spirit_types.h" + +/****************************************************************************** + * Pre-processor Definitions + ******************************************************************************/ + +/* Macros used for range-checking in assertions */ + +#define IS_DIRECT_TX(mode) \ + (((mode) == NORMAL_TX_MODE) || ((mode) == DIRECT_TX_FIFO_MODE) || \ + ((mode) == DIRECT_TX_GPIO_MODE) || ((mode) == PN9_TX_MODE)) +#define IS_DIRECT_RX(mode) \ + (((mode) == NORMAL_RX_MODE) || ((mode) == DIRECT_RX_FIFO_MODE) || \ + ((mode) == DIRECT_RX_GPIO_MODE)) + +/****************************************************************************** + * Public Types + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Direct transmission mode enumeration for SPIRIT. */ + +enum spirit_directtx_e +{ + NORMAL_TX_MODE = 0x00, /* Normal mode, no direct transmission is + * used */ + DIRECT_TX_FIFO_MODE = 0x04, /* Source is FIFO: payload bits are + * continuously read from the TX FIFO */ + DIRECT_TX_GPIO_MODE = 0x08, /* Source is GPIO: payload bits are + * continuously read from one of the GPIO + * ports and transmitted without any + * processing */ + PN9_TX_MODE = 0x0c /* A pseudorandom binary sequence is + * generated internally */ +}; + + +/* Direct receive mode enumeration for SPIRIT. */ + +enum spirit_directrx_e +{ + NORMAL_RX_MODE = 0x00, /* Normal mode, no direct reception is used */ + DIRECT_RX_FIFO_MODE = 0x10, /* Destination is FIFO: payload bits are + * continuously written to the RX FIFO and + * not subjected to any* processing */ + DIRECT_RX_GPIO_MODE = 0x20 /* Destination is GPIO: payload bits are + * continuously written to one of the GPIO + * ports and not subjected to any processing */ +}; + +/****************************************************************************** + * Public Function Prototypes + ******************************************************************************/ + +/****************************************************************************** + * Name: spirit_directrf_set_rxmode + * + * Description: + * Sets the DirectRF RX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * directrx - Code of the desired mode. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_directrf_set_rxmode(FAR struct spirit_library_s *spirit, + enum spirit_directrx_e directrx); + +/****************************************************************************** + * Name: + * + * Description: + * Returns the DirectRF RX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Direct Rx mode. + * + ******************************************************************************/ + +enum spirit_directrx_e + spirit_directrf_get_rxmode(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: + * + * Description: + * Sets the TX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * directtx - Code of the desired source. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_directrf_set_txmode(FAR struct spirit_library_s *spirit, + enum spirit_directtx_e directtx); + +/****************************************************************************** + * Name: + * + * Description: + * Returns the DirectRF TX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Direct Tx mode. + * + ******************************************************************************/ + +enum spirit_directtx_e + spirit_directrf_get_txmode(FAR struct spirit_library_s *spirit); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_DIRECTRF_H */ diff --git a/drivers/wireless/spirit/include/spirit_general.h b/drivers/wireless/spirit/include/spirit_general.h index 5eca02a15b..e8467937ca 100644 --- a/drivers/wireless/spirit/include/spirit_general.h +++ b/drivers/wireless/spirit/include/spirit_general.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_general.h + * include/nuttx/wireless/spirit/include/spirit_general.h * Configuration and management of SPIRIT General functionalities. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GENERAL_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GENERAL_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GENERAL_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GENERAL_H /****************************************************************************** * Included Files @@ -132,4 +132,4 @@ enum spirit_version_e * ******************************************************************************/ -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GENERAL_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GENERAL_H */ diff --git a/drivers/wireless/spirit/include/spirit_gpio.h b/drivers/wireless/spirit/include/spirit_gpio.h index a4505b0fdb..b1bb5a6287 100644 --- a/drivers/wireless/spirit/include/spirit_gpio.h +++ b/drivers/wireless/spirit/include/spirit_gpio.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_gpio.h + * include/nuttx/wireless/spirit/include/spirit_gpio.h * This file provides all the low level API to manage SPIRIT GPIO. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GPIO_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GPIO_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GPIO_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GPIO_H /****************************************************************************** * Included Files @@ -235,4 +235,4 @@ struct spirit_gpio_init_s int spirit_gpio_initialize(FAR struct spirit_library_s *spirit, FAR const struct spirit_gpio_init_s *gpioinit); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GPIO_H*/ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GPIO_H*/ diff --git a/drivers/wireless/spirit/include/spirit_irq.h b/drivers/wireless/spirit/include/spirit_irq.h index da5d436f4c..c3de4382ef 100644 --- a/drivers/wireless/spirit/include/spirit_irq.h +++ b/drivers/wireless/spirit/include/spirit_irq.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_irq.h + * include/nuttx/wireless/spirit/include/spirit_irq.h * Configuration and management of SPIRIT IRQs. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_IRQ_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_IRQ_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_IRQ_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_IRQ_H /* On the Spirit side specific IRQs can be enabled by setting a specific bitmask. * The Spirit libraries allow the user to do this in two different ways: @@ -452,4 +452,4 @@ bool spirit_irq_is_pending(FAR struct spirit_library_s *spirit, } #endif -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_IRQ_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_IRQ_H */ diff --git a/drivers/wireless/spirit/include/spirit_linearfifo.h b/drivers/wireless/spirit/include/spirit_linearfifo.h index 8467acfa9a..54f72b87ee 100644 --- a/drivers/wireless/spirit/include/spirit_linearfifo.h +++ b/drivers/wireless/spirit/include/spirit_linearfifo.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_Linearfifo.h + * include/nuttx/wireless/spirit/include/spirit_Linearfifo.h * Configuration and management of SPIRIT Fifo. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_FIFO_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_FIFO_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_FIFO_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_FIFO_H /****************************************************************************** * Included Files @@ -257,4 +257,4 @@ uint8_t spirit_fifo_get_txalmostempty(FAR struct spirit_library_s *spirit); } #endif -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_FIFO_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_FIFO_H */ diff --git a/drivers/wireless/spirit/include/spirit_management.h b/drivers/wireless/spirit/include/spirit_management.h index 392731fb79..91666c748a 100644 --- a/drivers/wireless/spirit/include/spirit_management.h +++ b/drivers/wireless/spirit/include/spirit_management.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_management.h + * include/nuttx/wireless/spirit/include/spirit_management.h * The management layer for SPIRIT1 library. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_MANAGEMENT_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_MANAGEMENT_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_MANAGEMENT_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_MANAGEMENT_H /****************************************************************************** * Included Files @@ -44,16 +44,6 @@ #include "spirit_config.h" #include "spirit_types.h" -/****************************************************************************** - * Pre-processor Definitions - ******************************************************************************/ - -/* Macros used in assertions */ - -/****************************************************************************** - * Public Types - ******************************************************************************/ - /****************************************************************************** * Public Function Prototypes ******************************************************************************/ @@ -107,6 +97,22 @@ int spirit_management_txstrobe(FAR struct spirit_library_s *spirit); int spirit_management_rxstrobe(FAR struct spirit_library_s *spirit); +/****************************************************************************** + * Name: spirit_management_waextracurrent + * + * Description: + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned on + * any failure. + * + ******************************************************************************/ + +int spirit_management_waextracurrent(FAR struct spirit_library_s *spirit); + /****************************************************************************** * Name: spirit_management_initcommstate * @@ -124,4 +130,4 @@ int spirit_management_rxstrobe(FAR struct spirit_library_s *spirit); void spirit_management_initcommstate(FAR struct spirit_library_s *spirit, uint32_t frequency); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_MANAGEMENT_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_MANAGEMENT_H */ diff --git a/drivers/wireless/spirit/include/spirit_pktbasic.h b/drivers/wireless/spirit/include/spirit_pktbasic.h index b661348057..ad265f9a19 100644 --- a/drivers/wireless/spirit/include/spirit_pktbasic.h +++ b/drivers/wireless/spirit/include/spirit_pktbasic.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_pktbasic.h + * include/nuttx/wireless/spirit/include/spirit_pktbasic.h * Configuration and management of SPIRIT Basic packets. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_PKTBASIC_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_PKTBASIC_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTBASIC_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTBASIC_H /* This module can be used to manage the configuration of Spirit Basic * packets. The user can obtain a packet configuration filling the @@ -118,8 +118,8 @@ struct pktbasic_init_s uint32_t syncwords; /* Specifies the sync words. This parameter is * a uint32_t word with format: * 0x|SYNC1|SYNC2|SYNC3|SYNC4 */ - uint8_t premblen; /* Specifies the preamble length. This parameter - * can be any value from enum pkt_premblen_e */ + uint8_t preamblen; /* Specifies the preamble length. This parameter + * can be any value from enum pkt_preamblen_e */ uint8_t synclen; /* Specifies the sync word length. The 32bit * word passed (syncwords) will be stored in * the SYNCx registers from the MSB until the @@ -199,6 +199,97 @@ struct pktbasic_addr_s int spirit_pktbasic_initialize(FAR struct spirit_library_s *spirit, FAR const struct pktbasic_init_s *pktbasic); +/****************************************************************************** + * Name: spirit_pktbasic_get_setup + * + * Description: + * Returns the SPIRIT Basic packet structure according to the specified + * parameters in the registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * pktbasic - Basic packet init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_get_setup(FAR struct spirit_library_s *spirit, + FAR struct pktbasic_init_s *pktbasic); + +/****************************************************************************** + * Name: spirit_pktbasic_addr_initialize + * + * Description: + * Initializes the SPIRIT Basic packet addresses according to the specified + * parameters in the struct struct pktbasic_init_s struct. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * basicaddr - Basic packet addresses init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_addr_initialize(FAR struct spirit_library_s *spirit, + FAR struct pktbasic_addr_s *basicaddr); + +/****************************************************************************** + * Name: spirit_pktbasic_get_addrsetup + * + * Description: + * Returns the SPIRIT Basic packet addresses structure according to the + * specified parameters in the registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * basicaddr - Basic packet addresses init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_get_addrsetup(FAR struct spirit_library_s *spirit, + FAR struct pktbasic_addr_s *basicaddr); + +/****************************************************************************** + * Name: spirit_pktbasic_set_format + * + * Description: + * Configures the Basic packet format as packet used by SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_set_format(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_pktbase_set_addrfield + * + * Description: + * Sets the address length for SPIRIT Basic packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * txdestaddr - Length of ADDRESS in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbase_set_addrfield(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e txdestaddr); + /****************************************************************************** * Name: spirit_pktbase_get_addrfield * @@ -238,6 +329,25 @@ enum spirit_functional_state_e int spirit_pktbasic_set_payloadlen(FAR struct spirit_library_s *spirit, uint16_t payloadlen); +/****************************************************************************** + * Name: spirit_pktbase_get_payloadlen + * + * Description: + * Returns the payload length for SPIRIT Basic packets. Since the packet + * length depends from the address and the control field size, this function + * reads the correspondent registers in order to determine the correct + * payload length to be returned. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Payload length in bytes. + * + ******************************************************************************/ + +uint16_t spirit_pktbase_get_payloadlen(FAR struct spirit_library_s *spirit); + /****************************************************************************** * Name: spirit_pktbasic_rxpktlen * @@ -254,4 +364,26 @@ int spirit_pktbasic_set_payloadlen(FAR struct spirit_library_s *spirit, uint16_t spirit_pktbasic_rxpktlen(FAR struct spirit_library_s *spirit); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_PKTBASIC_H*/ +/****************************************************************************** + * Name: spirit_pktbasic_set_varlen + * + * Description: + * Computes and sets the variable payload length for SPIRIT Basic packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * payloadlen - Payload length in bytes. + * txdestaddr - Enable or Disable Address Field. + * ctrllen - Control length in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_pktbasic_set_varlen(FAR struct spirit_library_s *spirit, + uint16_t payloadlen, + enum spirit_functional_state_e txdestaddr, + enum pkt_ctrllen_e ctrllen); + +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTBASIC_H*/ diff --git a/drivers/wireless/spirit/include/spirit_pktcommon.h b/drivers/wireless/spirit/include/spirit_pktcommon.h index 219ba1cf52..6393b8450f 100644 --- a/drivers/wireless/spirit/include/spirit_pktcommon.h +++ b/drivers/wireless/spirit/include/spirit_pktcommon.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_pktcommon.h + * include/nuttx/wireless/spirit/include/spirit_pktcommon.h * Configuration and management of the common features of SPIRIT packets. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_PKTCOMMON_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_PKTCOMMON_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTCOMMON_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTCOMMON_H /* This module provides all the common functions and definitions used by the * packets modules. Here are also defined all the generic enumeration types @@ -118,7 +118,7 @@ extern "C" /* Preamble length in bytes enumeration. */ -enum pkt_premblen_e +enum pkt_preamblen_e { PKT_PREAMBLE_LENGTH_01BYTE = 0x00, /* Preamble length 1 byte */ PKT_PREAMBLE_LENGTH_02BYTES = 0x08, /* Preamble length 2 bytes */ @@ -255,4 +255,4 @@ int spirit_pktcommon_enable_crcfilter(FAR struct spirit_library_s *spirit, } #endif -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_PKTCOMMON_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTCOMMON_H */ diff --git a/drivers/wireless/spirit/include/spirit_pktmbus.h b/drivers/wireless/spirit/include/spirit_pktmbus.h new file mode 100644 index 0000000000..c8fe909fce --- /dev/null +++ b/drivers/wireless/spirit/include/spirit_pktmbus.h @@ -0,0 +1,349 @@ +/****************************************************************************** + * drivers/wireless/spirit/include/spirit_pktmbus.h + * Configuration and management of SPIRIT MBUS packets. + * + * Copyright(c) 2015 STMicroelectronics + * Author: VMA division - AMS + * Version 3.2.2 08-July-2015 + * + * Adapted for NuttX by: + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __DRVIERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTMBUS_H +#define __DRVIERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTMBUS_H + +/* This module can be used to manage the configuration of Spirit MBUS packets. + * The user can obtain a packet configuration filling the structure + * struct spirit_pktmbus_init_s, defining in it some general parameters for the Spirit MBUS + * packet format. Since the MBUS protocol is a standard, the configuration + * of a MBUS* packet is very simple to do. + * + * Example: + * + * struct spirit_pktmbus_init_s mbusInit = + * { + * MBUS_SUBMODE_S1_S2_LONG_HEADER, // MBUS submode selection + * 36, // added "01" chips on preamble + * 16 // postamble length in "01" chips + * }; + * + * ... + * + * SpiritPktMbusInit(&mbusInit); + * + * ... + * + * The module provides some other functions that can be used to modify + * or read only some configuration parameters. + */ + +/****************************************************************************** + * Included Files + ******************************************************************************/ + +#include "spirit_regs.h" +#include "spirit_types.h" +#include "spirit_pktcommon.h" + +/****************************************************************************** + * Pre-processor Definitions + ******************************************************************************/ + +/* Macros used in assertions */ + +#define IS_MBUS_SUBMODE(mode) \ + (((mode) == MBUS_SUBMODE_S1_S2_LONG_HEADER) || \ + ((mode) == MBUS_SUBMODE_S1_M_S2_T2_OTHER_TO_METER) || \ + ((mode) == MBUS_SUBMODE_T1_T2_METER_TO_OTHER) || \ + ((mode) == MBUS_SUBMODE_R2_SHORT_HEADER)) + +/****************************************************************************** + * Public Types + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Configuration and management of SPIRIT MBUS packets. */ + +/* Pkt MBUS Exported Types */ + +/* MBUS submode enumeration. */ + +enum spirit_mbus_submode_e +{ + /* MBUS submode S1, S2 (long header): + * Header length = mbus_prmbl_ctrl + 279 (in "01" bit pairs) + * Sync word = 0x7696 (length 18 bits) + */ + + MBUS_SUBMODE_S1_S2_LONG_HEADER = MBUS_CTRL_MBUS_SUBMODE_S1_S2L, + + /* MBUS submode S1-m, S2, T2 (other to meter): + * Header length = mbus_prmbl_ctrl + 15 (in "01" bit pairs) + * Sync word = 0x7696 (length 18 bits) + */ + + MBUS_SUBMODE_S1_M_S2_T2_OTHER_TO_METER = MBUS_CTRL_MBUS_SUBMODE_S2_S1M_T2_OTHER, + + /* MBUS submode T1, T2 (meter to other): + * Header length = mbus_prmbl_ctrl + 19 (in "01" bit pairs): + * Sync word = 0x3d (length 10 bits) + */ + + MBUS_SUBMODE_T1_T2_METER_TO_OTHER = MBUS_CTRL_MBUS_SUBMODE_T1_T2_METER, + + /* MBUS submode R2, short header: + * Header length = mbus_prmbl_ctrl + 39 (in "01" bit pairs) + * Sync word = 0x7696 (length 18 bits) + */ + + MBUS_SUBMODE_R2_SHORT_HEADER = MBUS_CTRL_MBUS_SUBMODE_R2, +}; + +/* SPIRIT MBUS Packet Init structure definition */ + +struct spirit_pktmbus_init_s +{ + enum spirit_mbus_submode_e submode; /* Specifies the SUBMODE to be + * configured. This field can be any + * value from enum spirit_mbus_submode_e */ + uint8_t preamblen; /* Specifies the PREAMBLE length. This + * parameter can be any value between + * 0 and 255 chip sequence '01' */ + uint8_t postamblen; /* Specifies the POSTAMBLE length. This + * parameter can be any value between 0 + * and 255 chip sequence '01' */ +}; + +/****************************************************************************** + * Public Function Prototypes + ******************************************************************************/ + +/****************************************************************************** + * Name: spirit_pktmbus_initialize + * + * Description: + * Initializes the SPIRIT MBUS packet according to the specified parameters + * in the struct spirit_pktmbus_init_s structure. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * mbusinit - Pointer to a struct spirit_pktmbus_init_s structure that + * contains the configuration information for the specified + * SPIRIT MBUS PACKET FORMAT. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_initialize(FAR struct spirit_library_s *spirit, + FAR const struct spirit_pktmbus_init_s *mbusinit); + +/****************************************************************************** + * Name: spirit_pktmbus_get_setup + * + * Description: + * Returns the SPIRIT MBUS packet structure according to the specified + * parameters in the registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * mbusinit - MBUS packet init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_get_setup(FAR struct spirit_library_s *spirit, + FAR struct spirit_pktmbus_init_s *mbusinit); + +/****************************************************************************** + * Name: spirit_pktmbus_set_format + * + * Description: + * Configures the MBUS packet format as the one used by SPIRIT. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_format(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_pktmbus_set_preamble + * + * Description: + * Sets how many chip sequence “01†shall be added in the preamble respect + * to the minimum value as defined according to the specified sub-mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * preamble - The number of chip sequence. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_preamble(FAR struct spirit_library_s *spirit, + uint8_t preamble); + +/****************************************************************************** + * Name: spirit_pktmbus_get_preamble + * + * Description: + * Returns how many chip sequence "01" are added in the preamble respect to + * the minimum value as defined according to the specified sub-mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Preable in number of "01" chip sequences. + * + ******************************************************************************/ + +uint8_t spirit_pktmbus_get_preamble(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_pktmbus_set_postamble + * + * Description: + * Sets how many chip sequence “01†will be used in postamble + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * postamble - The number of chip sequence. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_postamble(FAR struct spirit_library_s *spirit, + uint8_t postamble); + +/****************************************************************************** + * Name: + * + * Description: + * Returns how many chip sequence "01" are used in the postamble + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Postamble in number of "01" chip sequences. + * + ******************************************************************************/ + +uint8_t spirit_pktmbus_get_postamble(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: + * + * Description: + * Sets the MBUS submode used. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * submode - The submode used. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_submode(FAR struct spirit_library_s *spirit, + enum spirit_mbus_submode_e submode); + +/****************************************************************************** + * Name: spirit_pktmbus_get_submode + * + * Description: + * Returns the MBUS submode used. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * MBUS submode. + * + ******************************************************************************/ + +enum spirit_mbus_submode_e + spirit_pktmbus_get_submode(FAR struct spirit_library_s *spirit); + +/****************************************************************************** + * Name: spirit_pktmbus_set_payloadlen + * + * Description: + * Sets the payload length for SPIRIT MBUS packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * payloadlen - Payload length in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_payloadlen(FAR struct spirit_library_s *spirit, + uint16_t payloadlen); + +/****************************************************************************** + * Name: spirit_pktmbus_get_payloadlen + * + * Description: + * Returns the payload length for SPIRIT MBUS packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Payload length in bytes. + * + ******************************************************************************/ + +uint16_t spirit_pktmbus_get_payloadlen(FAR struct spirit_library_s *spirit); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRVIERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_PKTMBUS_H */ diff --git a/drivers/wireless/spirit/include/spirit_qi.h b/drivers/wireless/spirit/include/spirit_qi.h index 8000f22ceb..d42d6a9ab9 100644 --- a/drivers/wireless/spirit/include/spirit_qi.h +++ b/drivers/wireless/spirit/include/spirit_qi.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_qi.h + * include/nuttx/wireless/spirit/include/spirit_qi.h * Configuration and management of SPIRIT QI. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_QI_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_QI_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_QI_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_QI_H /****************************************************************************** * Included Files @@ -191,4 +191,4 @@ enum spirit_sqi_threshold_e int spirit_qi_set_rssithreshold(FAR struct spirit_library_s *spirit, int dbmvalue); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_GENERAL_H*/ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_GENERAL_H*/ diff --git a/drivers/wireless/spirit/include/spirit_radio.h b/drivers/wireless/spirit/include/spirit_radio.h index d5e5dab36b..dbcfa412e4 100644 --- a/drivers/wireless/spirit/include/spirit_radio.h +++ b/drivers/wireless/spirit/include/spirit_radio.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_radio.h + * include/nuttx/wireless/spirit/include/spirit_radio.h * This file provides all the low level API to manage Analog and Digital radio * part of SPIRIT. * @@ -35,8 +35,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_RADIO_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_RADIO_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_RADIO_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_RADIO_H /* In order to configure the Radio main parameters, the user can fit struct * radio_init_s structure the and call the spirit_radio_initialize() @@ -222,17 +222,28 @@ /* Other macros used in assertions */ #define IS_XTAL_FLAG(flag) \ - (((flag) == XTAL_FLAG_24_MHz) || ((flag) == XTAL_FLAG_26_MHz)) + (((flag) == XTAL_FLAG_24_MHz) || ((flag) == XTAL_FLAG_26_MHz)) #define IS_BAND_SELECTED(band) \ - (((band) == HIGH_BAND) || ((band) == MIDDLE_BAND) || \ - ((band) == LOW_BAND) || ((band) == VERY_LOW_BAND)) + (((band) == HIGH_BAND) || ((band) == MIDDLE_BAND) || \ + ((band) == LOW_BAND) || ((band) == VERY_LOW_BAND)) #define IS_MODULATION_SELECTED(mod) \ - (((mod) == FSK) || ((mod) == GFSK_BT05) || \ - ((mod) == GFSK_BT1) || ((mod) == ASK_OOK) || \ + (((mod) == FSK) || ((mod) == GFSK_BT05) || \ + ((mod) == GFSK_BT1) || ((mod) == ASK_OOK) || \ ((mod) == MSK)) #define IS_PA_LOAD_CAP(cwc) \ - (((cwc) == LOAD_0_PF) || ((cwc) == LOAD_1_2_PF) || \ - ((cwc) == LOAD_2_4_PF) || ((cwc) == LOAD_3_6_PF)) + (((cwc) == LOAD_0_PF) || ((cwc) == LOAD_1_2_PF) || \ + ((cwc) == LOAD_2_4_PF) || ((cwc) == LOAD_3_6_PF)) +#define IS_AFC_MODE(mode) \ + ((mode) == AFC_SLICER_CORRECTION || (mode) == AFC_2ND_IF_CORRECTION) +#define IS_AGC_MODE(mode) \ + ((mode) == AGC_LINEAR_MODE || (mode) == AGC_BINARY_MODE) +#define IS_CLK_REC_MODE(mode) \ + ((mode) == CLK_REC_PLL || (mode) == CLK_REC_DLL) +#define IS_PST_FLT_LENGTH(len) \ + ((len) == PSTFLT_LENGTH_8 || (len) == PSTFLT_LENGTH_16) +#define IS_OOK_PEAK_DECAY(decay) \ + (((decay) == FAST_DECAY) || ((decay) == MEDIUM_FAST_DECAY) ||\ + ((decay) == MEDIUM_SLOW_DECAY) || ((decay) == SLOW_DECAY)) /****************************************************************************** * Public Types @@ -278,6 +289,49 @@ enum spirit_paload_capacitor_e LOAD_3_6_PF = PA_POWER0_CWC_3_6P /* 3.6pF additional PA load capacitor */ }; +/* SPIRIT AFC Mode selection */ + +enum spirit_afcmode_e +{ + AFC_SLICER_CORRECTION = AFC2_AFC_MODE_SLICER, /* AFC loop closed on slicer */ + AFC_2ND_IF_CORRECTION = AFC2_AFC_MODE_MIXER /* AFC loop closed on 2nd + * conversion stage */ +}; + +/* SPIRIT AGC Mode selection */ + +enum spirit_agcmode_e +{ + AGC_LINEAR_MODE = AGCCTRL0_AGC_MODE_LINEAR, /* AGC works in linear mode */ + AGC_BINARY_MODE = AGCCTRL0_AGC_MODE_BINARY /* AGC works in binary mode */ +}; + +/* SPIRIT Clock Recovery Mode selection */ + +enum spirit_clkrecmode_e +{ + CLK_REC_PLL = FDEV0_CLOCK_REG_ALGO_SEL_PLL, /* PLL alogrithm for clock recovery */ + CLK_REC_DLL = FDEV0_CLOCK_REG_ALGO_SEL_DLL /* DLL alogrithm for clock recovery */ +}; + +/* SPIRIT Postfilter length */ + +enum spirit_pstfltlen_e +{ + PSTFLT_LENGTH_8 = 0x00, /* Postfilter length is 8 symbols */ + PSTFLT_LENGTH_16 = 0x10 /* Postfilter length is 16 symbols */ +}; + +/* SPIRIT OOK Peak Decay */ + +enum spirit_ookpeakdelay_e +{ + FAST_DECAY = 0x00, /* Peak decay control for OOK: fast decay */ + MEDIUM_FAST_DECAY = 0x01, /* Peak decay control for OOK: medium_fast decay */ + MEDIUM_SLOW_DECAY = 0x02, /* Peak decay control for OOK: medium_fast decay */ + SLOW_DECAY = 0x03 /* Peak decay control for OOK: slow decay */ +}; + /* SPIRIT Radio initialization structure definition */ struct radio_init_s @@ -820,6 +874,25 @@ int spirit_radio_set_palevel_maxindex(FAR struct spirit_library_s *spirit, int spirit_radio_afcfreezeonsync(FAR struct spirit_library_s *spirit, enum spirit_functional_state_e newstate); +/****************************************************************************** + * Name: spirit_radio_enable_csblanking + * + * Description: + * Enables or Disables the received data blanking when the CS is under the + * threshold. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - New state of this mode. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_radio_enable_csblanking(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate); + /****************************************************************************** * Name: spirit_radio_persistentrx * @@ -908,4 +981,4 @@ int spirit_radio_enable_digdivider(FAR struct spirit_library_s *spirit, enum spirit_functional_state_e spirit_radio_isenabled_digdivider(FAR struct spirit_library_s *spirit); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_RADIO_H*/ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_RADIO_H*/ diff --git a/drivers/wireless/spirit/include/spirit_regs.h b/drivers/wireless/spirit/include/spirit_regs.h index 872df1e318..7ac3a0d4b0 100644 --- a/drivers/wireless/spirit/include/spirit_regs.h +++ b/drivers/wireless/spirit/include/spirit_regs.h @@ -1,5 +1,5 @@ /********************************************************************************************** - * include/nuttx/wireless/spirit/spirit_regs.h + * include/nuttx/wireless/spirit/include/spirit_regs.h * This file contains all the SPIRIT registers address and masks. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * **********************************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_REGS_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_REGS_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_REGS_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_REGS_H /********************************************************************************************** * Pre-processor Definitions @@ -2376,4 +2376,4 @@ #define COMMAND_FLUSHTXFIFO ((uint8_t)0x72) /* Clean the TX FIFO; valid from all * states */ -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_REGS_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_REGS_H */ diff --git a/drivers/wireless/spirit/include/spirit_timer.h b/drivers/wireless/spirit/include/spirit_timer.h index 4cec9656da..e240bbfce4 100644 --- a/drivers/wireless/spirit/include/spirit_timer.h +++ b/drivers/wireless/spirit/include/spirit_timer.h @@ -1,5 +1,5 @@ /****************************************************************************** - * include/nuttx/wireless/spirit/spirit_timer.h + * include/nuttx/wireless/spirit/include/spirit_timer.h * Configuration and management of SPIRIT timers. * * Copyright(c) 2015 STMicroelectronics @@ -34,8 +34,8 @@ * ******************************************************************************/ -#ifndef __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_TIMER_H -#define __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_TIMER_H +#ifndef __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_TIMER_H +#define __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_TIMER_H /****************************************************************************** * Included Files @@ -143,4 +143,4 @@ int spirit_timer_set_rxtimeout_stopcondition(FAR struct spirit_library_s *spirit enum spirit_rxtimeout_stopcondition_e stopcondition); -#endif /* __INCLUDE_NUTT_WIRELESS_SPIRIT_SPIRIT_TIMER_H */ +#endif /* __DRIVERS_WIRELESS_SPIRIT_INCLUDE_SPIRIT_TIMER_H */ diff --git a/drivers/wireless/spirit/lib/Make.defs b/drivers/wireless/spirit/lib/Make.defs index 3a00258898..8a39b76aec 100644 --- a/drivers/wireless/spirit/lib/Make.defs +++ b/drivers/wireless/spirit/lib/Make.defs @@ -35,10 +35,10 @@ # Include Spirit driver source files in the build -CSRCS += spirit_radio.c spirit_pktbasic.c spirit_pktcommon.c spirit_qi.c -CSRCS += spirit_calibration.c spirit_management.c spirit_csma.c -CSRCS += spirit_linearfifo.c spirit_irq.c spirit_timer.c spirit_gpio.c -CSRCS += spirit_spi.c +CSRCS += spirit_radio.c spirit_pktbasic.c spirit_pktcommon.c +CSRCS += spirit_pktmbus.c spirit_directrf.c spirit_qi.c spirit_calibration.c +CSRCS += spirit_management.c spirit_aes.c spirit_csma.c spirit_linearfifo.c +CSRCS += spirit_irq.c spirit_timer.c spirit_gpio.c spirit_spi.c # Include Spirit driver build support diff --git a/drivers/wireless/spirit/lib/spirit_aes.c b/drivers/wireless/spirit/lib/spirit_aes.c new file mode 100644 index 0000000000..df2f5a3192 --- /dev/null +++ b/drivers/wireless/spirit/lib/spirit_aes.c @@ -0,0 +1,361 @@ +/****************************************************************************** + * drivers/wireless/spirit/lib/spirit_aes.c + * Configuration and management of SPIRIT AES Engine. + * + * Copyright(c) 2015 STMicroelectronics + * Author: VMA division - AMS + * Version 3.2.2 08-July-2015 + * + * Adapted for NuttX by: + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/****************************************************************************** + * Included Files + ******************************************************************************/ + +#include + +#include "spirit_aes.h" +#include "spirit_spi.h" + +/****************************************************************************** + * Public Functions + ******************************************************************************/ + +/****************************************************************************** + * Name: spirit_aes_enable + * + * Description: + * Enables or Disables the AES engine. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate new state for AES engine. + * This parameter can be: S_ENABLE or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_enable(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate) +{ + uint8_t regval = 0; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(newstate)); + + /* Modifies the register value */ + + ret = spirit_reg_read(spirit, ANA_FUNC_CONF0_BASE, ®val, 1); + if (ret >= 0) + { + if (newstate == S_ENABLE) + { + regval |= AES_MASK; + } + else + { + regval &= ~AES_MASK; + } + + /* Write to the ANA_FUNC_CONF0 register to enable or disable the AES + * engine + */ + + ret = spirit_reg_write(spirit, ANA_FUNC_CONF0_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: + * + * Description: + * Writes the data to encrypt or decrypt, or the encryption key for the + * derive decryption key operation into the AES_DATA_IN registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * buffer - Pointer to the user data buffer. The first byte of the array + * must be the MSB byte and it will be put in the AES_DATA_IN[0] + * register, while the last one must be the LSB and it will be + * put in the AES_DATA_IN[buflen-1] register. If data to write + * are less than 16 bytes the remaining AES_DATA_IN registers + * will be filled with bytes equal to 0. + * buflen - Length of data in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_write_datain(FAR struct spirit_library_s *spirit, + FAR const uint8_t *buffer, uint8_t buflen) +{ + uint8_t datain[16]; + uint8_t i; + + /* Verifies that there are no more than 16 bytes */ + + (buflen > 16) ? (buflen = 16) : buflen; + + /* Fill the datain with the data buffer, using padding */ + + for (i = 0; i < 16; i++) + { + if (i < (16 - buflen)) + { + datain[i] = 0; + } + else + { + datain[i] = buffer[15 - i]; + } + } + + /* Writes the AES_DATA_IN registers */ + + return spirit_reg_write(spirit, AES_DATA_IN_15_BASE, datain, 16); +} + +/****************************************************************************** + * Name: + * + * Description: + * Returns the encrypted or decrypted data or the decription key from the + * AES_DATA_OUT register. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * buffer - pointer to the user data buffer. The AES_DATA_OUT[0] + * register value will be put as first element of the buffer + * (MSB), while the AES_DAT_OUT[buflen-1] register value will be + * put as last element of the buffer (LSB). + * buflen - Length of data to read in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_read_dataout(FAR struct spirit_library_s *spirit, + FAR uint8_t *buffer, uint8_t buflen) +{ + uint8_t dataout[16]; + uint8_t address; + int ret; + + /* Verifies that there are no more than 16 bytes */ + + if (buflen > 16) + { + buflen = 16; + } + + /* Evaluates the address of AES_DATA_OUT from which start to read */ + + address = AES_DATA_OUT_15_BASE + 16 - buflen; + + /* Reads the exact number of AES_DATA_OUT registers */ + + ret = spirit_reg_read(spirit, address, dataout, buflen); + if (ret >= 0) + { + int i; + + /* Copy in the user buffer the read values changing the order */ + + for (i = buflen - 1; i >= 0; i--) + { + *buffer++ = dataout[i]; + } + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_aes_write_key + * + * Description: + * Writes the encryption key into the AES_KEY_IN register. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * key - Pointer to the buffer of 4 words containing the AES key. + * The first byte of the buffer must be the most significant byte + * AES_KEY_0 of the AES key. The last byte of the buffer must be + * the less significant byte AES_KEY_15 of the AES key. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_write_key(FAR struct spirit_library_s *spirit, + FAR const uint8_t *key) +{ + uint8_t tmp[16]; + int i; + + for (i = 0; i < 16; i++) + { + tmp[15 - i] = key[i]; + } + + /* Write to the AES_DATA_IN registers */ + + return spirit_reg_write(spirit, AES_KEY_IN_15_BASE, tmp, 16); +} + +/****************************************************************************** + * Name: + * + * Description: + * Returns the encryption/decryption key from the AES_KEY_IN register. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * key pointer to the buffer of 4 words (16 bytes) containing the AES key. + * The first byte of the buffer shall be the most significant byte AES_KEY_0 of the AES key. + * The last byte of the buffer shall be the less significant byte AES_KEY_15 of the AES key. + * This parameter is an uint8_t*. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_read_key(FAR struct spirit_library_s *spirit, FAR uint8_t *key) +{ + uint8_t tmp[16]; + int ret; + int i; + + /* Reads the AES_DATA_IN registers */ + + ret = spirit_reg_read(spirit, AES_KEY_IN_15_BASE, tmp, 16); + if (ret >= 0) + { + for (i = 0; i < 16; i++) + { + key[i] = tmp[15 - i]; + } + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_aes_enc2deckey + * + * Description: + * Derives the decryption key from a given encryption key. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_enc2deckey(FAR struct spirit_library_s *spirit) +{ + /* Sends the COMMAND_AES_KEY command */ + + return spirit_command(spirit, COMMAND_AES_KEY); +} + +/****************************************************************************** + * Name: spirit_aes_encrypt + * + * Description: + * Executes the encryption operation. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_encrypt(FAR struct spirit_library_s *spirit) +{ + /* Sends the COMMAND_AES_ENC command */ + + return spirit_command(spirit, COMMAND_AES_ENC); +} + +/****************************************************************************** + * Name: + * + * Description: + * Executes the decryption operation. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_decrypt(FAR struct spirit_library_s *spirit) +{ + /* Sends the COMMAND_AES_DEC command */ + + return spirit_command(spirit, COMMAND_AES_DEC); +} + +/****************************************************************************** + * Name: spirit_aes_derivekey_decrypt + * + * Description: + * Executes the key derivation and the decryption operation. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_aes_derivekey_decrypt(FAR struct spirit_library_s *spirit) +{ + /* Sends the COMMAND_AES_KEY_DEC command */ + + return spirit_command(spirit, COMMAND_AES_KEY_DEC); +} diff --git a/drivers/wireless/spirit/lib/spirit_calibration.c b/drivers/wireless/spirit/lib/spirit_calibration.c index 405b54b6d7..0e6bfa599e 100644 --- a/drivers/wireless/spirit/lib/spirit_calibration.c +++ b/drivers/wireless/spirit/lib/spirit_calibration.c @@ -1,5 +1,5 @@ /****************************************************************************** - * drivers/wireless/spirit/spirit_calibration.c + * drivers/wireless/spirit/lib/spirit_calibration.c * Configuration and management of SPIRIT VCO-RCO calibration. * * Copyright(c) 2015 STMicroelectronics @@ -148,6 +148,90 @@ int spirit_calib_enable_vco(FAR struct spirit_library_s *spirit, return ret; } +/****************************************************************************** + * Name: spirit_calibration_set_rcocal + * + * Description: + * Sets the RCO calibration words. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * rwt - RWT word for RCO calibration. + * rfb - RFB word for RCO calibration. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_calibration_set_rcocal(FAR struct spirit_library_s *spirit, + uint8_t rwt, uint8_t rfb) +{ + uint8_t regval[2]; + int ret; + + /* Build the value of RWT and the MSbits of the RFB word */ + + regval[0] = (rwt << 4) | (rfb >> 1); + + /* Reads the register value to update the LSbit of RFB */ + + ret = spirit_reg_read(spirit, RCO_VCO_CALIBR_IN1_BASE, ®val[1], 1); + if (ret >= 0) + { + /* Build new value for the register */ + + regval[1] = (regval[1] & 0x7f) | (rfb << 7); + + /* Write the new value for RCO calibration words */ + + ret = spirit_reg_write(spirit, RCO_VCO_CALIBR_IN2_BASE, regval, 2); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_calibration_get_rcocal + * + * Description: + * Returns the RCO calibration words. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * rwt - Pointer to the variable in which the RWT word has to be + * stored. + * rfb - Pointer to the variable in which the RFB word has to be + * stored. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_calibration_get_rcocal(FAR struct spirit_library_s *spirit, + FAR uint8_t *rwt, FAR uint8_t *rfb) +{ + uint8_t regval[2]; + int ret; + + /* Read the registers values */ + + ret = spirit_reg_read(spirit, RCO_VCO_CALIBR_OUT1_BASE, regval, 2); + if (ret >= 0) + { + /* Build the RWT value */ + + (*rwt) = regval[0] >> 4; + + /* Build the RFB value */ + + (*rfb) = (regval[0] & 0x0F) << 1 | (regval[1] >> 7); + } + + return ret; +} + /****************************************************************************** * Name: spirit_calib_get_vcocal * @@ -307,6 +391,147 @@ uint8_t spirit_calib_get_vcorxcal(FAR struct spirit_library_s *spirit) return (regval & 0x7f); } +/****************************************************************************** + * Name: spirit_calibration_set_vcowin + * + * Description: + * Sets the VCO calibration window. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * refword - Value of REFWORD corresponding to the Ref_period according to + * the formula: + * + * CALIBRATION_WIN = 11*Ref_period/fxo. + * + * This parameter can be a value of enum spirit_vcowin_e. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on any failure. + * + ******************************************************************************/ + +int spirit_calibration_set_vcowin(FAR struct spirit_library_s *spirit, + enum spirit_vcowin_e refword) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_VCO_WIN(refword)); + + /* Reads the register value */ + + ret = spirit_reg_read(spirit, SYNTH_CONFIG1_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the values to be written */ + + regval &= 0xfc; + regval |= refword; + + /* Write the new value of VCO calibration window */ + + ret = spirit_reg_write(spirit, SYNTH_CONFIG1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_calibration_get_vcowin + * + * Description: + * Returns the VCO calibration window. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Value of REFWORD corresponding to the Ref_period according to the + * formula: + * + * CALIBRATION_WIN = 11*Ref_period/fxo. + * + * This parameter can be a value of enum spirit_vcowin_e. + * + ******************************************************************************/ + +enum spirit_vcowin_e + spirit_calibration_get_vcowin(FAR struct spirit_library_s *spirit) +{ + uint8_t regval1, regval2; + enum spirit_vcowin_e refword; + + /* Reads the register containing the REFWORD value */ + + (void)spirit_reg_read(spirit, SYNTH_CONFIG1_BASE, ®val1, 1); + + /* Reads the Xtal configuration */ + + (void)spirit_reg_read(spirit, ANA_FUNC_CONF0_BASE, ®val2, 1); + + /* Mask the REFWORD field */ + + regval1 &= 0x03; + + /* Mask the 24_26_MHz_SELECT field */ + + regval2 = ((regval2 & 0x40) >> 6); + + /* In case of 26 MHz crystal */ + + if (regval2 != 0) + { + switch (regval1) + { + case 0: + refword = CALIB_TIME_6_77_US_26MHZ; + break; + + case 1: + refword = CALIB_TIME_13_54_US_26MHZ; + break; + + case 2: + refword = CALIB_TIME_27_08_US_26MHZ; + break; + + case 3: + refword = CALIB_TIME_54_15_US_26MHZ; + break; + } + } + + /* In case of 24 MHz crystal */ + + else + { + switch (regval1) + { + case 0: + refword = CALIB_TIME_7_33_US_24MHZ; + break; + + case 1: + refword = CALIB_TIME_14_67_US_24MHZ; + break; + + case 2: + refword = CALIB_TIME_29_33_US_24MHZ; + break; + + case 3: + refword = CALIB_TIME_58_67_US_24MHZ; + break; + + } + } + + return refword; +} + /****************************************************************************** * Name: spirit_calib_select_vco * diff --git a/drivers/wireless/spirit/lib/spirit_csma.c b/drivers/wireless/spirit/lib/spirit_csma.c index e13801fe79..690382fcae 100644 --- a/drivers/wireless/spirit/lib/spirit_csma.c +++ b/drivers/wireless/spirit/lib/spirit_csma.c @@ -1,5 +1,5 @@ /****************************************************************************** - * drivers/wireless/spirit/spirit_csma.c + * drivers/wireless/spirit/lib/spirit_csma.c * Configuration and management of SPIRIT CSMA. * * Copyright(c) 2015 STMicroelectronics @@ -38,6 +38,7 @@ * Included Files ******************************************************************************/ +#include #include #include @@ -65,7 +66,7 @@ ******************************************************************************/ int spirit_csma_initialize(FAR struct spirit_library_s *spirit, - FAR struct spirit_csma_init_s *csmainit) + FAR const struct spirit_csma_init_s *csmainit) { uint8_t regval[5]; int ret; @@ -129,3 +130,675 @@ int spirit_csma_initialize(FAR struct spirit_library_s *spirit, ret = spirit_reg_write(spirit, CSMA_CONFIG3_BASE, regval, 4); return ret; } + +/****************************************************************************** + * Name: spirit_csma_getinfo + * + * Description: + * Returns the fitted structure struct spirit_csma_init_s starting from the + * registers values. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * csmainit - Csma structure to be fitted. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_getinfo(FAR struct spirit_library_s *spirit, + FAR struct spirit_csma_init_s *csmainit) +{ + uint8_t regval[5]; + int ret; + + /* Reads PROTOCOL1_BASE register */ + + ret = spirit_reg_read(spirit, PROTOCOL1_BASE, ®val[4], 1); + if (ret < 0) + { + return ret; + } + + /* Reads CSMA_CONFIGx_BASE registers */ + + ret = spirit_reg_read(spirit, CSMA_CONFIG3_BASE, regval, 4); + if (ret < 0) + { + return ret; + } + + /* Reads the bu counter seed */ + + csmainit->seed = (uint16_t)regval[1] | (uint16_t)regval[0] << 8; + + /* Reads the bu prescaler */ + + csmainit->prescaler = regval[2] >> 2; + + /* Reads the Cca period */ + + csmainit->multbit = (enum spirit_cca_period_e) (regval[2] & 0x03); + + /* Reads the Cca length */ + + csmainit->ccalen = (enum spirit_csmalen_e) (regval[3] & 0xF0); + + /* Reads the max number of back off */ + + csmainit->maxnb = regval[3] & 0x07; + + /* Reads the persistent mode enable bit */ + + csmainit->csmapersistent = + (enum spirit_functional_state_e)((regval[4] >> 1) & 0x01); + return OK; +} + +/****************************************************************************** + * Name: spirit_csma_enable + * + * Description: + * Enables or Disables the CSMA. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - The state of the CSMA mode. This parameter can be: S_ENABLE + * or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_enable(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(newstate)); + + /* Reads the PROTOCOL1 register value */ + + ret = spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + if (ret >= 0) + { + /* Sets or resets the CSMA enable bit */ + + if (newstate == S_ENABLE) + { + regval |= PROTOCOL1_CSMA_ON_MASK; + } + else + { + regval &= ~PROTOCOL1_CSMA_ON_MASK; + } + + /* Write the new value on the PROTOCOL1 register */ + + ret = spirit_reg_write(spirit, PROTOCOL1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_getstate + * + * Description: + * Gets the CSMA mode. Says if it is enabled or disabled. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CSMA mode. + * + ******************************************************************************/ + +enum spirit_functional_state_e + spirit_csma_getstate(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the PROTOCOL1 register value */ + + (void)spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + + /* Return if set or reset */ + + if (regval & PROTOCOL1_CSMA_ON_MASK) + { + return S_ENABLE; + } + else + { + return S_DISABLE; + } +} + +/****************************************************************************** + * Name: spirit_csma_set_persistentmode + * + * Description: + * Enables or Disables the persistent CSMA mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - The state of the persistent CSMA mode. This parameter can + * be: S_ENABLE or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_persistentmode(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(newstate)); + + /* Reads the PROTOCOL1 register value */ + + ret = spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + if (ret >= 0) + { + /* Enables/disables the CSMA persistent mode */ + + if (newstate == S_ENABLE) + { + regval |= PROTOCOL1_CSMA_PERS_ON_MASK; + } + else + { + regval &= ~PROTOCOL1_CSMA_PERS_ON_MASK; + } + + /* Write the new vaue on the PROTOCOL1 register */ + + ret = spirit_reg_write(spirit, PROTOCOL1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_get_persistentmode + * + * Description: + * Gets the persistent CSMA mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CSMA persistent mode. + * + ******************************************************************************/ + +enum spirit_functional_state_e + spirit_csma_get_persistentmode(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the PROTOCOL1 register value */ + + (void)spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + + /* Return if set or reset */ + + if (regval & PROTOCOL1_CSMA_PERS_ON_MASK) + { + return S_ENABLE; + } + else + { + return S_DISABLE; + } +} + +/****************************************************************************** + * Name: spirit_csma_set_seedreload + * + * Description: + * Enables or Disables the seed reload mode (if enabled it reloads the back- + * off generator seed using the value written in the BU_COUNTER_SEED register). + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - The state of the seed reload mode. This parameter can be: + * S_ENABLE or S_DISABLE. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_seedreload(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(newstate)); + + /* Reads the PROTOCOL1 register value */ + + ret = spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + if (ret >= 0) + { + /* Enables/disables the seed reload mode */ + + if (newstate == S_ENABLE) + { + regval |= PROTOCOL1_SEED_RELOAD_MASK; + } + else + { + regval &= ~PROTOCOL1_SEED_RELOAD_MASK; + } + + /* Write the new value on the PROTOCOL1 register */ + + ret = spirit_reg_write(spirit, PROTOCOL1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_get_seedreload + * + * Description: + * Gets the seed reload state. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CSMA seed reload mode. + * + ******************************************************************************/ + +enum spirit_functional_state_e + spirit_csma_get_seedreload(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the PROTOCOL1 register value */ + + (void)spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + + /* Return if set or reset */ + + if (regval & PROTOCOL1_SEED_RELOAD_MASK) + { + return S_ENABLE; + } + else + { + return S_DISABLE; + } +} + +/****************************************************************************** + * Name: spirit_csma_set_bucounterseed + * + * Description: + * Sets the BU counter seed (BU_COUNTER_SEED register). The CSMA back off + * time is given by the formula: BO = rand(2^NB)*BU. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * seed - Seed of the random number generator used to apply the BBE + * algorithm. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_bucounterseed(FAR struct spirit_library_s *spirit, + uint16_t seed) +{ + uint8_t regval[2]; + + /* Check parameters */ + + DEBUGASSERT(IS_BU_COUNTER_SEED(seed)); + + /* Build value (MSB) */ + + regval[0] = (uint8_t) (seed >> 8); + + /* Build value (LSB) */ + + regval[1] = (uint8_t) seed; + + /* Writes the CSMA_CONFIG3 registers */ + + return spirit_reg_write(spirit, CSMA_CONFIG3_BASE, regval, 2); +} + +/****************************************************************************** + * Name: spirit_csma_get_bucounterseed + * + * Description: + * Returns the BU counter seed (BU_COUNTER_SEED register). + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Seed of the random number generator used to apply the BBE algorithm. + * + ******************************************************************************/ + +uint16_t spirit_csma_get_bucounterseed(FAR struct spirit_library_s *spirit) +{ + uint8_t regval[2]; + + /* Reads the CSMA_CONFIGx registers value */ + + (void)spirit_reg_read(spirit, CSMA_CONFIG3_BASE, regval, 2); + + /* Build the counter seed and return it */ + + return ((uint16_t) regval[1] + (((uint16_t) regval[0]) << 8)); +} + +/****************************************************************************** + * Name: spirit_csma_set_buprescaler + * + * Description: + * Sets the BU prescaler. The CSMA back off time is given by the formula: + * BO = rand(2^NB)*BU. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * prescaler - Used to program the back-off unit BU. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_buprescaler(FAR struct spirit_library_s *spirit, + uint8_t prescaler) +{ + uint8_t regval; + int ret; + + /* Check parameters */ + + DEBUGASSERT(IS_BU_PRESCALER(prescaler)); + + /* Reads the CSMA_CONFIG1 register value */ + + ret = spirit_reg_read(spirit, CSMA_CONFIG1_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the new value for the BU prescaler */ + + regval &= 0x03; + regval |= (prescaler << 2); + + /* Write the new value on the CSMA_CONFIG1_BASE register */ + + ret = spirit_reg_write(spirit, CSMA_CONFIG1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_get_buprescaler + * + * Description: + * Returns the BU prescaler. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Value back-off unit (BU). + * + ******************************************************************************/ + +uint8_t spirit_csma_get_buprescaler(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the CSMA_CONFIG1 register value */ + + (void)spirit_reg_read(spirit, CSMA_CONFIG1_BASE, ®val, 1); + + /* Build and return the BU prescaler value */ + + return (regval >> 2); +} + +/****************************************************************************** + * Name: spirit_csma_set_ccaperiod + * + * Description: + * Sets the CCA period. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * multbit - Value of CCA period to store. This parameter can be a value + * of enum spirit_cca_period_e. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_ccaperiod(FAR struct spirit_library_s *spirit, + enum spirit_cca_period_e multbit) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_CCA_PERIOD(multbit)); + + /* Reads the CSMA_CONFIG1 register value */ + + ret = spirit_reg_read(spirit, CSMA_CONFIG1_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the new value setting the the CCA period */ + + regval &= 0xfc; + regval |= multbit; + + /* Write the new value on the CSMA_CONFIG1 register */ + + ret = spirit_reg_write(spirit, CSMA_CONFIG1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_get_ccaperiod + * + * Description: + * Returns the CCA period. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CCA period. + * + ******************************************************************************/ + +enum spirit_cca_period_e + spirit_csma_get_ccaperiod(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the CSMA_CONFIG1 register value */ + + (void)spirit_reg_read(spirit, CSMA_CONFIG1_BASE, ®val, 1); + + /* Build and return the CCA period value */ + + return (enum spirit_cca_period_e) (regval & 0x03); +} + +/****************************************************************************** + * Name: spirit_csma_set_ccalen + * + * Description: + * Sets the CCA length. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * ccalen - The CCA length (a value between 1 and 15 that multiplies the + * CCA period). This parameter can be any value of enum + * spirit_csmalen_e. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_ccalen(FAR struct spirit_library_s *spirit, + enum spirit_csmalen_e ccalen) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_CSMA_LENGTH(ccalen)); + + /* Reads the CSMA_CONFIG0 register value */ + + ret = spirit_reg_read(spirit, CSMA_CONFIG0_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the value of CCA length to be set */ + + regval &= 0x0f; + regval |= ccalen; + + /* Write the new value on the CSMA_CONFIG0 register */ + + ret = spirit_reg_write(spirit, CSMA_CONFIG0_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_get_ccalen + * + * Description: + * Returns the CCA length. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * CCA length. + * + ******************************************************************************/ + +uint8_t spirit_csma_get_ccalen(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the CSMA_CONFIG0 register value */ + + (void)spirit_reg_read(spirit, CSMA_CONFIG0_BASE, ®val, 1); + + /* Build and return the CCA length */ + + return regval >> 4; +} + +/****************************************************************************** + * Name: spirit_csma_set_maxbackoff + * + * Description: + * Sets the max number of back-off. If reached Spirit stops the transmission. + * + * Input Parameters: + * maxnb the max number of back-off. + * This parameter is an uint8_t. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_csma_set_maxbackoff(FAR struct spirit_library_s *spirit, + uint8_t maxnb) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_CMAX_NB(maxnb)); + + /* Reads the CSMA_CONFIG0 register value */ + + ret = spirit_reg_read(spirit, CSMA_CONFIG0_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the value of max back off to be set */ + + regval &= 0xf8; + regval |= maxnb; + + /* Write the new value on the CSMA_CONFIG0 register */ + + ret = spirit_reg_write(spirit, CSMA_CONFIG0_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_csma_get_maxbackoff + * + * Description: + * Returns the max number of back-off. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Max number of back-off. + * + ******************************************************************************/ + +uint8_t spirit_csma_get_maxbackoff(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the CSMA_CONFIG0 register value */ + + (void)spirit_reg_read(spirit, CSMA_CONFIG0_BASE, ®val, 1); + + /* Build and return the max number of back-off */ + + return (regval & 0x07); +} diff --git a/drivers/wireless/spirit/lib/spirit_directrf.c b/drivers/wireless/spirit/lib/spirit_directrf.c new file mode 100644 index 0000000000..2543acfc8b --- /dev/null +++ b/drivers/wireless/spirit/lib/spirit_directrf.c @@ -0,0 +1,190 @@ +/****************************************************************************** + * drivers/wireless/spirit/lib/spirit_directrf.c + * Configuration and management of SPIRIT direct transmission / receive modes. + * + * Copyright(c) 2015 STMicroelectronics + * Author: VMA division - AMS + * Version 3.2.2 08-July-2015 + * + * Adapted for NuttX by: + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/****************************************************************************** + * Included Files + ******************************************************************************/ + +#include + +#include "spirit_directrf.h" +#include "spirit_spi.h" + +/****************************************************************************** + * Public Functions + ******************************************************************************/ + +/****************************************************************************** + * Name: spirit_directrf_set_rxmode + * + * Description: + * Sets the DirectRF RX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * directrx - Code of the desired mode. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_directrf_set_rxmode(FAR struct spirit_library_s *spirit, + enum spirit_directrx_e directrx) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_DIRECT_RX(directrx)); + + /* Reads the register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL3_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the value to be stored */ + + regval &= ~PCKTCTRL3_RX_MODE_MASK; + regval |= (uint8_t)directrx; + + /* Write value to register */ + + ret = spirit_reg_write(spirit, PCKTCTRL3_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: + * + * Description: + * Returns the DirectRF RX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Direct Rx mode. + * + ******************************************************************************/ + +enum spirit_directrx_e + spirit_directrf_get_rxmode(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the register value and mask the RX_Mode field */ + + (void)spirit_reg_read(spirit, PCKTCTRL3_BASE, ®val, 1); + + /* Rebuild and return value */ + + return (enum spirit_directrx_e)(regval & 0x30); +} + +/****************************************************************************** + * Name: + * + * Description: + * Sets the TX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * directtx - Code of the desired source. + * + * Returned Value: + * Zero (OK) on success; A negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_directrf_set_txmode(FAR struct spirit_library_s *spirit, + enum spirit_directtx_e directtx) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_DIRECT_TX(directtx)); + + /* Reads the register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL1_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the value to be stored */ + + regval &= ~PCKTCTRL1_TX_SOURCE_MASK; + regval |= (uint8_t) directtx; + + /* Write value to register */ + + ret = spirit_reg_write(spirit, PCKTCTRL1_BASE, ®val, 1); + } + + return ret; +} + +/****************************************************************************** + * Name: + * + * Description: + * Returns the DirectRF TX mode of SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Direct Tx mode. + * + ******************************************************************************/ + +enum spirit_directtx_e + spirit_directrf_get_txmode(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the register value and mask the RX_Mode field */ + + (void)spirit_reg_read(spirit, PCKTCTRL1_BASE, ®val, 1); + + /* Returns value */ + + return (enum spirit_directtx_e)(regval & 0x0c); +} diff --git a/drivers/wireless/spirit/lib/spirit_linearfifo.c b/drivers/wireless/spirit/lib/spirit_linearfifo.c index 51bfcd3156..69c737d54e 100644 --- a/drivers/wireless/spirit/lib/spirit_linearfifo.c +++ b/drivers/wireless/spirit/lib/spirit_linearfifo.c @@ -1,5 +1,5 @@ /****************************************************************************** - * drivers/wireless/spirit/spirit_Linearfifo.c + * drivers/wireless/spirit/lib/spirit_Linearfifo.c * Configuration and management of SPIRIT Fifo. * * Copyright(c) 2015 STMicroelectronics diff --git a/drivers/wireless/spirit/lib/spirit_management.c b/drivers/wireless/spirit/lib/spirit_management.c index 508095c184..91f01256a5 100644 --- a/drivers/wireless/spirit/lib/spirit_management.c +++ b/drivers/wireless/spirit/lib/spirit_management.c @@ -550,6 +550,52 @@ int spirit_management_rxstrobe(FAR struct spirit_library_s *spirit) return OK; } +/****************************************************************************** + * Name: spirit_management_waextracurrent + * + * Description: + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned on + * any failure. + * + ******************************************************************************/ + +int spirit_management_waextracurrent(FAR struct spirit_library_s *spirit) +{ + uint8_t tmp; + int ret; + + tmp = 0xca; + ret = spirit_reg_write(spirit, 0xb2, &tmp, 1); + if (ret < 0) + { + return ret; + } + + tmp = 0x04; + ret = spirit_reg_write(spirit, 0xa8, &tmp, 1); + if (ret < 0) + { + return ret; + } + + /* Just a read to lose a few more microseconds */ + + ret = spirit_reg_read(spirit, 0xa8, &tmp, 1); + if (ret < 0) + { + return ret; + } + + tmp = 0x00; + ret = spirit_reg_write(spirit, 0xa8, &tmp, 1); + return ret; +} + /****************************************************************************** * Name: spirit_management_initcommstate * diff --git a/drivers/wireless/spirit/lib/spirit_pktbasic.c b/drivers/wireless/spirit/lib/spirit_pktbasic.c index 437e51dce5..c47f479cdc 100644 --- a/drivers/wireless/spirit/lib/spirit_pktbasic.c +++ b/drivers/wireless/spirit/lib/spirit_pktbasic.c @@ -38,6 +38,7 @@ * Included Files ******************************************************************************/ +#include #include #include @@ -76,7 +77,7 @@ int spirit_pktbasic_initialize(FAR struct spirit_library_s *spirit, /* Check the parameters */ - DEBUGASSERT(IS_PKT_PREAMBLE_LENGTH(pktpasic->premblen)); + DEBUGASSERT(IS_PKT_PREAMBLE_LENGTH(pktpasic->preamblen)); DEBUGASSERT(IS_PKT_SYNC_LENGTH(pktpasic->synclen)); DEBUGASSERT(IS_PKT_CRC_MODE(pktpasic->crcmode)); DEBUGASSERT(IS_PKT_LENGTH_WIDTH_BITS(pktpasic->pktlenwidth)); @@ -153,7 +154,7 @@ int spirit_pktbasic_initialize(FAR struct spirit_library_s *spirit, /* Preamble, sync and fixed or variable length setting */ - regval[2] = (uint8_t)pktpasic->premblen | (uint8_t)pktpasic->synclen | + regval[2] = (uint8_t)pktpasic->preamblen | (uint8_t)pktpasic->synclen | (uint8_t)pktpasic->fixedvarlen; /* CRC length, whitening and FEC setting */ @@ -211,6 +212,343 @@ int spirit_pktbasic_initialize(FAR struct spirit_library_s *spirit, return spirit_reg_write(spirit, SYNC4_BASE, regval, 4); } +/****************************************************************************** + * Name: spirit_pktbasic_get_setup + * + * Description: + * Returns the SPIRIT Basic packet structure according to the specified + * parameters in the registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * pktbasic - Basic packet init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_get_setup(FAR struct spirit_library_s *spirit, + FAR struct pktbasic_init_s *pktbasic) +{ + uint8_t regval[10]; + int ret; + int i; + + /* Reads registers */ + + ret = spirit_reg_read(spirit, PCKTCTRL4_BASE, regval, 10); + if (ret < 0) + { + return ret; + } + + /* Length width */ + + pktbasic->pktlenwidth = (regval[1] & 0x0f) + 1; + + /* Address field */ + + pktbasic->txdestaddr = + (enum spirit_functional_state_e)((regval[0] >> 3) & 0x01); + + /* Control length */ + + pktbasic->ctrllen = (enum pkt_ctrllen_e)(regval[0] & 0x07); + + /* CRC mode */ + + pktbasic->crcmode = (enum pkt_crcmode_e)(regval[3] & 0xe0); + + /* Whitening */ + + pktbasic->datawhite = + (enum spirit_functional_state_e) ((regval[3] >> 4) & 0x01); + + /* FEC */ + + pktbasic->fec = (enum spirit_functional_state_e)(regval[3] & 0x01); + + /* FIX or VAR bit */ + + pktbasic->fixedvarlen = (enum pkt_fixvar_len_e)(regval[2] & 0x01); + + /* Preamble length */ + + pktbasic->preamblen = (enum pkt_preamblen_e)(regval[2] & 0xf8); + + /* Sync length */ + + pktbasic->synclen = (enum pkt_synlen_e)(regval[2] & 0x06); + + /* Sync Words */ + + pktbasic->syncwords = 0; + for (i = 0; i < 4; i++) + { + if (i > 2 - (((uint8_t)pktbasic->synclen) >> 1)) + { + pktbasic->syncwords |= (uint32_t) (regval[i + 6]) << (8 * i); + } + } + + return OK; +} + +/****************************************************************************** + * Name: spirit_pktbasic_addr_initialize + * + * Description: + * Initializes the SPIRIT Basic packet addresses according to the specified + * parameters in the struct struct pktbasic_init_s struct. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * basicaddr - Basic packet addresses init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_addr_initialize(FAR struct spirit_library_s *spirit, + FAR struct pktbasic_addr_s *basicaddr) +{ + uint8_t regval[3]; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(basicaddr->destfilter)); + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(basicaddr->mcastfilter)); + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(basicaddr->bcastfilter)); + + /* Reads the PCKT_FLT_OPTIONS ragister */ + + ret = spirit_reg_read(spirit, PCKT_FLT_OPTIONS_BASE, ®val[0], 1); + if (ret < 0) + { + return ret; + } + + /* Enables or disables filtering on my address */ + + if (basicaddr->destfilter == S_ENABLE) + { + regval[0] |= PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK; + } + else + { + regval[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK; + } + + /* Enables or disables filtering on multicast address */ + + if (basicaddr->mcastfilter == S_ENABLE) + { + regval[0] |= PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK; + } + else + { + regval[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK; + } + + /* Enables or disables filtering on broadcast address */ + + if (basicaddr->bcastfilter == S_ENABLE) + { + regval[0] |= PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK; + } + else + { + regval[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK; + } + + /* Writes the new value on the PCKT_FLT_OPTIONS register */ + + ret = spirit_reg_write(spirit, PCKT_FLT_OPTIONS_BASE, ®val[0], 1); + + /* Fills the array with the addresses passed in the structure */ + + regval[0] = basicaddr->bcastaddr; + regval[1] = basicaddr->mcastaddr; + regval[2] = basicaddr->srcaddr; + + /* Writes values on the PCKT_FLT_GOALS registers */ + + return spirit_reg_write(spirit, PCKT_FLT_GOALS_BROADCAST_BASE, regval, 3); +} + +/****************************************************************************** + * Name: spirit_pktbasic_get_addrsetup + * + * Description: + * Returns the SPIRIT Basic packet addresses structure according to the + * specified parameters in the registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * basicaddr - Basic packet addresses init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_get_addrsetup(FAR struct spirit_library_s *spirit, + FAR struct pktbasic_addr_s *basicaddr) +{ + uint8_t regval[3]; + int ret; + + /* Reads values on the PCKT_FLT_GOALS registers */ + + ret = spirit_reg_read(spirit, PCKT_FLT_GOALS_BROADCAST_BASE, regval, 3); + if (ret >= 0) + { + /* Fit the structure with the read addresses */ + + basicaddr->bcastaddr = regval[0]; + basicaddr->mcastaddr = regval[1]; + basicaddr->srcaddr = regval[2]; + + ret = spirit_reg_read(spirit, PCKT_FLT_OPTIONS_BASE, ®val[0], 1); + if (ret >= 0) + { + /* Fit the structure with the read filtering bits */ + + basicaddr->bcastfilter = + (enum spirit_functional_state_e)((regval[0] >> 1) & 0x01); + basicaddr->mcastfilter = + (enum spirit_functional_state_e)((regval[0] >> 2) & 0x01); + basicaddr->destfilter = + (enum spirit_functional_state_e)((regval[0] >> 3) & 0x01); + } + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_pktbasic_set_format + * + * Description: + * Configures the Basic packet format as packet used by SPIRIT. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbasic_set_format(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + int ret; + + /* Reads the register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL3_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the new value. Also set to 0 the direct RX mode bits */ + + regval &= 0x0f; + regval |= (uint8_t) PCKTCTRL3_PCKT_FRMT_BASIC; + + /* Write the value to the PCKTCTRL3 register */ + + ret = spirit_reg_write(spirit, PCKTCTRL3_BASE, ®val, 1); + } + + if (ret >= 0) + { + /* Reads the PCKTCTRL1_BASE register */ + + ret = spirit_reg_read(spirit, PCKTCTRL1_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the new value. Set to 0 the direct TX mode bits */ + + regval &= 0xf3; + + /* Write the value to the PCKTCTRL1 register */ + + ret = spirit_reg_write(spirit, PCKTCTRL1_BASE, ®val, 1); + } + } + + if (ret >= 0) + { + /* Reads the PROTOCOL1 register */ + + ret = spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + if (ret >= 0) + { + /* Mask a reserved bit */ + + regval &= ~0x20; + + /* Write the value to the register */ + + ret = spirit_reg_write(spirit, PROTOCOL1_BASE, ®val, 1); + } + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_pktbase_set_addrfield + * + * Description: + * Sets the address length for SPIRIT Basic packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * txdestaddr - Length of ADDRESS in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktbase_set_addrfield(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e txdestaddr) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(txdestaddr)); + + /* Reads the PCKTCTRL4 register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL4_BASE, ®val, 1); + if (ret >= 0) + { + /* Build the address length for the register */ + + if (txdestaddr == S_ENABLE) + { + regval |= 0x08; + } + else + { + regval &= 0x07; + } + + /* Writes the new value on the PCKTCTRL4 register */ + + ret = spirit_reg_write(spirit, PCKTCTRL4_BASE, ®val, 1); + } + + return ret; +} + /****************************************************************************** * Name: spirit_pktbase_get_addrfield * @@ -293,6 +631,46 @@ int spirit_pktbasic_set_payloadlen(FAR struct spirit_library_s *spirit, return spirit_reg_write(spirit, PCKTLEN1_BASE, regval, 2); } +/****************************************************************************** + * Name: spirit_pktbase_get_payloadlen + * + * Description: + * Returns the payload length for SPIRIT Basic packets. Since the packet + * length depends from the address and the control field size, this function + * reads the correspondent registers in order to determine the correct + * payload length to be returned. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Payload length in bytes. + * + ******************************************************************************/ + +uint16_t spirit_pktbase_get_payloadlen(FAR struct spirit_library_s *spirit) +{ + uint8_t regval[2]; + uint16_t oversize = 0; + + /* Computes the oversize (address + control) size */ + + if (spirit_pktbase_get_addrfield(spirit)) + { + oversize = 1; + } + + oversize += (uint16_t)spirit_pktcommon_get_controllen(spirit); + + /* Reads the packet length registers */ + + (void)spirit_reg_read(spirit, PCKTLEN1_BASE, regval, 2); + + /* Returns the packet length */ + + return ((((uint16_t) regval[0]) << 8) + (uint16_t) regval[1]) - oversize; +} + /****************************************************************************** * Name: spirit_pktbasic_rxpktlen * @@ -329,3 +707,82 @@ uint16_t spirit_pktbasic_rxpktlen(FAR struct spirit_library_s *spirit) return (((((uint16_t) regval[0]) << 8) + (uint16_t)regval[1]) - oversize); } + +/****************************************************************************** + * Name: spirit_pktbasic_set_varlen + * + * Description: + * Computes and sets the variable payload length for SPIRIT Basic packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * payloadlen - Payload length in bytes. + * txdestaddr - Enable or Disable Address Field. + * ctrllen - Control length in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ******************************************************************************/ + +int spirit_pktbasic_set_varlen(FAR struct spirit_library_s *spirit, + uint16_t payloadlen, + enum spirit_functional_state_e txdestaddr, + enum pkt_ctrllen_e ctrllen) +{ + uint32_t pktlen; + uint8_t regval; + uint8_t addrlen; + int ret; + int i; + + /* Sets the address length according to txdestaddr */ + + if (txdestaddr == S_ENABLE) + { + addrlen = 1; + } + else + { + addrlen = 0; + } + + /* packet length = payload length + address length + control length */ + + pktlen = payloadlen + addrlen + ctrllen; + + /* Computes the number of bits */ + + for (i = 0; i < 16; i++) + { + if (pktlen == 0) + { + break; + } + + pktlen >>= 1; + } + + if (i == 0) + { + i = 1; + } + + /* Reads the PCKTCTRL3 register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL3_BASE, ®val, 1); + if (ret >= 0) + { + /* Build value for the length width */ + + regval &= ~PCKTCTRL3_LEN_WID_MASK; + regval |= (uint8_t)(i - 1); + + /* Write to the PCKTCTRL3 register value */ + + ret = spirit_reg_write(spirit, PCKTCTRL3_BASE, ®val, 1); + } + + return ret; +} + diff --git a/drivers/wireless/spirit/lib/spirit_pktcommon.c b/drivers/wireless/spirit/lib/spirit_pktcommon.c index 510fbaa16e..a911aee221 100644 --- a/drivers/wireless/spirit/lib/spirit_pktcommon.c +++ b/drivers/wireless/spirit/lib/spirit_pktcommon.c @@ -1,5 +1,5 @@ /****************************************************************************** - * drivers/wireless/spirit/spirit_pktcommon.c + * drivers/wireless/spirit/lib/spirit_pktcommon.c * Configuration and management of the common features of SPIRIT packets. * * Copyright(c) 2015 STMicroelectronics diff --git a/drivers/wireless/spirit/lib/spirit_pktmbus.c b/drivers/wireless/spirit/lib/spirit_pktmbus.c new file mode 100644 index 0000000000..b110663be0 --- /dev/null +++ b/drivers/wireless/spirit/lib/spirit_pktmbus.c @@ -0,0 +1,420 @@ +/****************************************************************************** + * drivers/wireless/spirit/spirit_pktmbus.c + * Configuration and management of SPIRIT MBUS packets. + * + * Copyright(c) 2015 STMicroelectronics + * Author: VMA division - AMS + * Version 3.2.2 08-July-2015 + * + * Adapted for NuttX by: + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/****************************************************************************** + * Included Files + ******************************************************************************/ + +#include + +#include "spirit_pktmbus.h" +#include "spirit_radio.h" +#include "spirit_spi.h" + +/****************************************************************************** + * Public Functions + ******************************************************************************/ + +/****************************************************************************** + * Name: spirit_pktmbus_initialize + * + * Description: + * Initializes the SPIRIT MBUS packet according to the specified parameters + * in the struct spirit_pktmbus_init_s structure. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * mbusinit - Pointer to a struct spirit_pktmbus_init_s structure that + * contains the configuration information for the specified + * SPIRIT MBUS PACKET FORMAT. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_initialize(FAR struct spirit_library_s *spirit, + FAR const struct spirit_pktmbus_init_s *mbusinit) +{ + uint8_t regval[3]; + + /* Check the parameters */ + + DEBUGASSERT(IS_MBUS_SUBMODE(mbusinit->submode)); + + /* Packet format config */ + + spirit_pktmbus_set_format(spirit); + spirit_pktcommon_enable_crcfilter(spirit, S_DISABLE); + spirit_radio_enable_csblanking(spirit, S_ENABLE); + + /* Preamble, postamble and submode config */ + + regval[0] = mbusinit->preamblen; + regval[1] = mbusinit->postamblen; + regval[2] = (uint8_t) mbusinit->submode; + + /* Writes the new values on the MBUS_PRMBL registers */ + + return spirit_reg_write(spirit, MBUS_PRMBL_BASE, regval, 3); +} + +/****************************************************************************** + * Name: spirit_pktmbus_get_setup + * + * Description: + * Returns the SPIRIT MBUS packet structure according to the specified + * parameters in the registers. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * mbusinit - MBUS packet init structure. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_get_setup(FAR struct spirit_library_s *spirit, + FAR struct spirit_pktmbus_init_s *mbusinit) +{ + uint8_t regval[3]; + int ret; + + /* Reads the MBUS regs value */ + + ret = spirit_reg_read(spirit, MBUS_PRMBL_BASE, regval, 3); + if (ret >= 0) + { + /* Fit the structure */ + + mbusinit->preamblen = regval[0]; + mbusinit->postamblen = regval[1]; + mbusinit->submode = (enum spirit_mbus_submode_e) (regval[2] & 0x0E); + } + + return ret; +} + +/****************************************************************************** + * Name: spirit_pktmbus_set_format + * + * Description: + * Configures the MBUS packet format as the one used by SPIRIT. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_format(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + int ret; + + /* Reads the PCKTCTRL3 register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL3_BASE, ®val, 1); + if (ret < 0) + { + return ret; + } + + /* Sets format bits. Also set to 0 the direct RX mode bits */ + + regval &= 0x0F; + regval |= ((uint8_t) PCKTCTRL3_PCKT_FRMT_MBUS); + + /* Writes value on the PCKTCTRL3 register */ + + ret = spirit_reg_write(spirit, PCKTCTRL3_BASE, ®val, 1); + if (ret < 0) + { + return ret; + } + + /* Reads the PCKTCTRL1 register value */ + + ret = spirit_reg_read(spirit, PCKTCTRL1_BASE, ®val, 1); + if (ret < 0) + { + return ret; + } + + /* Build the new value. Set to 0 the direct TX mode bits */ + + regval &= 0xf3; + + /* Writes the value on the PCKTCTRL1 register */ + + ret = spirit_reg_write(spirit, PCKTCTRL1_BASE, ®val, 1); + if (ret < 0) + { + return ret; + } + + /* Reads the PROTOCOL1 register */ + + ret = spirit_reg_read(spirit, PROTOCOL1_BASE, ®val, 1); + if (ret < 0) + { + return ret; + } + + /* Mask a reserved bit */ + + regval &= ~0x20; + + /* Writes the value on the PROTOCOL1 register */ + + return spirit_reg_write(spirit, PROTOCOL1_BASE, ®val, 1); +} + +/****************************************************************************** + * Name: spirit_pktmbus_set_preamble + * + * Description: + * Sets how many chip sequence “01” shall be added in the preamble respect + * to the minimum value as defined according to the specified sub-mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * preamble - The number of chip sequence. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_preamble(FAR struct spirit_library_s *spirit, + uint8_t preamble) +{ + /* Modifies the MBUS_PRMBL register value */ + + return spirit_reg_write(spirit, MBUS_PRMBL_BASE, &preamble, 1); +} + +/****************************************************************************** + * Name: spirit_pktmbus_get_preamble + * + * Description: + * Returns how many chip sequence "01" are added in the preamble respect to + * the minimum value as defined according to the specified sub-mode. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Preable in number of "01" chip sequences. + * + ******************************************************************************/ + +uint8_t spirit_pktmbus_get_preamble(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Modifies the MBUS_PRMBL register value */ + + (void)spirit_reg_read(spirit, MBUS_PRMBL_BASE, ®val, 1); + + /* Return value */ + + return regval; +} + +/****************************************************************************** + * Name: spirit_pktmbus_set_postamble + * + * Description: + * Sets how many chip sequence “01” will be used in postamble + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * postamble - The number of chip sequence. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_postamble(FAR struct spirit_library_s *spirit, + uint8_t postamble) +{ + /* Modifies the MBUS_PSTMBL register value */ + + return spirit_reg_write(spirit, MBUS_PSTMBL_BASE, &postamble, 1); +} + +/****************************************************************************** + * Name: + * + * Description: + * Returns how many chip sequence "01" are used in the postamble + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Postamble in number of "01" chip sequences. + * + ******************************************************************************/ + +uint8_t spirit_pktmbus_get_postamble(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the MBUS_PSTMBL register */ + + (void)spirit_reg_read(spirit, MBUS_PSTMBL_BASE, ®val, 1); + + /* Returns value */ + + return regval; +} + +/****************************************************************************** + * Name: + * + * Description: + * Sets the MBUS submode used. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * submode - The submode used. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_submode(FAR struct spirit_library_s *spirit, + enum spirit_mbus_submode_e submode) +{ + /* Modifies the MBUS_CTRL register value */ + + return spirit_reg_write(spirit, MBUS_CTRL_BASE, (FAR uint8_t *)submode, 1); +} + +/****************************************************************************** + * Name: spirit_pktmbus_get_submode + * + * Description: + * Returns the MBUS submode used. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * MBUS submode. + * + ******************************************************************************/ + +enum spirit_mbus_submode_e + spirit_pktmbus_get_submode(FAR struct spirit_library_s *spirit) +{ + uint8_t regval; + + /* Reads the MBUS_CTRL register value */ + + (void)spirit_reg_read(spirit, MBUS_CTRL_BASE, ®val, 1); + + /* Returns value */ + + return (enum spirit_mbus_submode_e) regval; +} + +/****************************************************************************** + * Name: spirit_pktmbus_set_payloadlen + * + * Description: + * Sets the payload length for SPIRIT MBUS packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * payloadlen - Payload length in bytes. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_pktmbus_set_payloadlen(FAR struct spirit_library_s *spirit, + uint16_t payloadlen) +{ + uint8_t regval[2]; + + /* Computes PCKTLEN0 value from payloadlen */ + + regval[1] = BUILD_PCKTLEN0(payloadlen); + + /* Computes PCKTLEN1 value from payloadlen */ + + regval[0] = BUILD_PCKTLEN1(payloadlen); + + /* Writes data on the PCKTLEN1/0 register */ + + return spirit_reg_write(spirit, PCKTLEN1_BASE, regval, 2); +} + +/****************************************************************************** + * Name: spirit_pktmbus_get_payloadlen + * + * Description: + * Returns the payload length for SPIRIT MBUS packets. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * + * Returned Value: + * Payload length in bytes. + * + ******************************************************************************/ + +uint16_t spirit_pktmbus_get_payloadlen(FAR struct spirit_library_s *spirit) +{ + uint8_t regval[2]; + + /* Reads the packet length registers */ + + (void)spirit_reg_read(spirit, PCKTLEN1_BASE, regval, 2); + + /* Returns the packet length */ + + return ((((uint16_t)regval[0]) << 8) + (uint16_t)regval[1]); +} diff --git a/drivers/wireless/spirit/lib/spirit_radio.c b/drivers/wireless/spirit/lib/spirit_radio.c index 3c615506de..43714b7741 100644 --- a/drivers/wireless/spirit/lib/spirit_radio.c +++ b/drivers/wireless/spirit/lib/spirit_radio.c @@ -1714,6 +1714,54 @@ int spirit_radio_afcfreezeonsync(FAR struct spirit_library_s *spirit, return ret; } +/****************************************************************************** + * Name: spirit_radio_enable_csblanking + * + * Description: + * Enables or Disables the received data blanking when the CS is under the + * threshold. + * + * Input Parameters: + * spirit - Reference to a Spirit library state structure instance + * newstate - New state of this mode. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ******************************************************************************/ + +int spirit_radio_enable_csblanking(FAR struct spirit_library_s *spirit, + enum spirit_functional_state_e newstate) +{ + uint8_t regval; + int ret; + + /* Check the parameters */ + + DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(newstate)); + + /* Reads the ANT_SELECT_CONF_BASE and mask the CS_BLANKING BIT field */ + + ret = spirit_reg_read(spirit, ANT_SELECT_CONF_BASE, ®val, 1); + if (ret >= 0) + { + if (newstate == S_ENABLE) + { + regval |= ANT_SELECT_CS_BLANKING_MASK; + } + else + { + regval &= (~ANT_SELECT_CS_BLANKING_MASK); + } + + /* Write the new value to the ANT_SELECT_CONF register */ + + ret = spirit_reg_write(spirit, ANT_SELECT_CONF_BASE, ®val, 1); + } + + return ret; +} + /****************************************************************************** * Name: spirit_radio_persistentrx *