feat: added PicoW_Sensor code template

Credits to @ext-erich.styger that provided the template
This commit is contained in:
SylvanArnold
2025-04-22 11:30:45 +02:00
committed by Sylvan Arnold
parent b2e9eab44e
commit 6cd510e749
985 changed files with 606823 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
/**
* \file
* \brief Configuration header file for Nordic Semiconductor nRF24L01+ transceiver
*
* This header file is used to configure settings of the nRF24L01 module.
*/
#ifndef __McuNRF24L01_CONFIG_H
#define __McuNRF24L01_CONFIG_H
#include "McuLib.h"
#ifndef McuNRF24L01_CONFIG_IS_ENABLED
#define McuNRF24L01_CONFIG_IS_ENABLED (0)
/*!< 1: enable driver/module; 0: module is not enabled */
#endif
#ifndef McuNRF24L01_CONFIG_IRQ_PIN_ENABLED
void McuNRF24L01_OnInterrupt(void); /* prototype for interrupt handler */
#define McuNRF24L01_CONFIG_IRQ_PIN_ENABLED (0)
/*!< 1: IRQ pin is enabled, 0: No IRQ pin available */
#endif
#ifndef McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK
#define McuNRF24L01_CONFIG_USE_ON_ACTIVATE_CALLBACK (0)
/*!< If McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK is called or not */
#endif
#ifndef McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK
void McuNRF24L01_OnActivate(void); /* prototype */
#define McuNRF24L01_CONFIG_ON_ACTIVATE_CALLBACK() McuNRF24L01_OnActivate()
/*!< User callback called before using device */
#endif
#ifndef McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK
#define McuNRF24L01_CONFIG_USE_ON_DEACTIVATE_CALLBACK (0)
/*!< If McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK is called or not */
#endif
#ifndef McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK
void McuNRF24L01_OnDeactivate(void); /* prototype */
#define McuNRF24L01_CONFIG_ON_DEACTIVATE_CALLBACK() McuNRF24L01_OnDeactivate()
/*!< User callback called after using device */
#endif
#ifndef McuNRF24L01_CONFIG_USE_MUTEX
#define McuNRF24L01_CONFIG_USE_MUTEX (1)
/*!< 1: Use FreeRTOS Mutex, 0: Do not use FreeRTOS mutex */
#endif
#ifndef McuNRF24L01_CONFIG_INITIALIZE_DURING_STARTUP
#define McuNRF24L01_CONFIG_INITIALIZE_DURING_STARTUP (0)
/*!< 1: Call Init() during startup, 0: Do not call Init() */
#endif
#ifndef McuNRF24L01_CONFIG_CE_CSN_PIN_PRE_INIT
#if McuLib_CONFIG_CPU_IS_RPxxxx
#define McuNRF24L01_CONFIG_CE_CSN_PIN_PRE_INIT() /* nothing needed */
#elif McuLib_CONFIG_CPU_IS_ESP32
#define McuNRF24L01_CONFIG_CE_CSN_PIN_PRE_INIT() /* nothing needed */
#elif McuLib_CONFIG_CPU_IS_KINETIS
#define McuNRF24L01_CONFIG_CE_CSN_PIN_PRE_INIT() CLOCK_EnableClock(kCLOCK_PortB)
/*!< Optional hardware initialization for CS Pin */
#endif
#endif
#ifndef McuNRF24L01_CONFIG_CE_PIN_GPIO
#define McuNRF24L01_CONFIG_CE_PIN_GPIO GPIOB
/*!< GPIO for CE Pin */
#endif
#ifndef McuNRF24L01_CONFIG_CE_PIN_PORT
#define McuNRF24L01_CONFIG_CE_PIN_PORT PORTB
/*!< PORT for CE Pin */
#endif
#ifndef McuNRF24L01_CONFIG_CE_PIN_NUMBER
#define McuNRF24L01_CONFIG_CE_PIN_NUMBER 10
/*!< Pin number of the CE Pin */
#endif
#ifndef McuNRF24L01_CONFIG_CSN_PIN_GPIO
#define McuNRF24L01_CONFIG_CSN_PIN_GPIO GPIOB
/*!< GPIO for CSN Pin */
#endif
#ifndef McuNRF24L01_CONFIG_CSN_PIN_PORT
#define McuNRF24L01_CONFIG_CSN_PIN_PORT PORTB
/*!< PORT for CSN Pin */
#endif
#ifndef McuNRF24L01_CONFIG_CSN_PIN_NUMBER
#define McuNRF24L01_CONFIG_CSN_PIN_NUMBER 0
/*!< Pin number of the CSN Pin */
#endif
#ifndef McuNRF24L01_CONFIG_IRQ_PIN_GPIO
#define McuNRF24L01_CONFIG_IRQ_PIN_GPIO GPIOB
/*!< GPIO for IRQ Pin */
#endif
#ifndef McuNRF24L01_CONFIG_IRQ_PIN_PORT
#define McuNRF24L01_CONFIG_IRQ_PIN_PORT PORTB
/*!< PORT for IRQ Pin */
#endif
#ifndef McuNRF24L01_CONFIG_IRQ_PIN_NUMBER
#define McuNRF24L01_CONFIG_IRQ_PIN_NUMBER 0
/*!< Pin number of the IRQ Pin */
#endif
#ifndef McuNRF24L01_CONFIG_IRQ_LINE_NUMBER
#define McuNRF24L01_CONFIG_IRQ_LINE_NUMBER PORTB_IRQn
/*!< Kinetis IRQ line number for interrupt settings */
#endif
#endif /* __McuNRF24L01_CONFIG_H */

View File

@@ -0,0 +1,204 @@
/* ###################################################################
** This component module is generated by Processor Expert. Do not modify it.
** Filename : McuRNet.h
** Component : McuRNet
** Version : Component 01.096, Driver 01.00, CPU db: 3.00.000
** Compiler : GNU C Compiler
** Date/Time : 2021-07-06, 16:35, # CodeGen: 0
** Abstract :
** This components implements the RNet Stack.
** Settings :
** Component name : McuRNet
** Transceiver :
** Transceiver Type : nRF24L01+
** nRF24L01+ : Enabled
** nRF24L01+ : McuNRF24L01
** Radio Channel : 81
** Data Rate : 2000 kBit
** Payload Size : 32
** Address : 0x11, 0x22, 0x33, 0x44, 0x55
** SMAC : Disabled
** Network :
** Address Size : 8 Bits
** Queues :
** Rx Message Queue Size : 15
** Tx Message Queue Size : 15
** Message Queue Blocking Time (ms) : 200
** Send Retry Count : 3
** Send Timeout (ms) : 250
** System :
** Utility : UTIL1
** RTOS : FRTOS1
** Shell : Enabled
** Remote StdIO : Enabled
** Queue length : 48
** Queue Timeout (ms) : 500
** Shell : McuShell
** Contents :
** SetChannel - uint8_t McuRNet_SetChannel(uint8_t channel);
** ParseCommand - uint8_t McuRNet_ParseCommand(const unsigned char *cmd, bool *handled, const...
** Init - void McuRNet_Init(void);
** Deinit - void McuRNet_Deinit(void);
**
** * Copyright (c) 2014-2019, Erich Styger
** * Web: https://mcuoneclipse.com
** * SourceForge: https://sourceforge.net/projects/mcuoneclipse
** * Git: https://github.com/ErichStyger/McuOnEclipse_PEx
** * All rights reserved.
** *
** * Redistribution and use in source and binary forms, with or without modification,
** * are permitted provided that the following conditions are met:
** *
** * - Redistributions of source code must retain the above copyright notice, this list
** * of conditions and the following disclaimer.
** *
** * - 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.
** *
** * 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.
** ###################################################################*/
/*!
** \file McuRNet.c
** \version 01.00
** \brief This module implements the RNet Stack.
*/
/*!
** @addtogroup McuRNet_module McuRNet module documentation
** @{
*/
/* MODULE McuRNet. */
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "McuRNet.h"
#include "RStack.h"
#include "Radio.h"
#include "RNWK.h"
#include "RMSG.h"
#include "RApp.h"
#include "RStdIO.h"
#include "McuNRF24L01.h"
/*
** ===================================================================
** Method : McuRNet_OnInterrupt (component RNet)
**
** Description :
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
void McuNRF24L01_OnInterrupt(void)
{
/* Write your code here ... */
}
/*
** ===================================================================
** Method : Init (component RNet)
**
** Description :
** Initializes the RNet Stack
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
void McuRNet_Init(void)
{
RSTACK_Init();
}
/*
** ===================================================================
** Method : Deinit (component RNet)
**
** Description :
** Deinitializes the RNet Stack
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
void McuRNet_Deinit(void)
{
RSTACK_Deinit();
}
/*
** ===================================================================
** Method : SetChannel (component RNet)
**
** Description :
** Sets the radio channel
** Parameters :
** NAME - DESCRIPTION
** channel - Channel number
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuRNet_SetChannel(uint8_t channel)
{
return RADIO_SetChannel(channel);
}
/*
** ===================================================================
** Method : ParseCommand (component RNet)
**
** Description :
** Shell Command Line parser. This method is enabled/disabled
** depending on if you have the Shell enabled/disabled in the
** properties.
** Parameters :
** NAME - DESCRIPTION
** * cmd - Pointer to command string
** * handled - Pointer to variable which tells if
** the command has been handled or not
** * io - Pointer to I/O structure
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuRNet_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io)
{
static const McuShell_ParseCommandCallback CmdParserTable[] =
{
RADIO_ParseCommand,
RNWK_ParseCommand,
RMSG_ParseCommand,
#if RNET_CONFIG_REMOTE_STDIO
#if RSTDIO_PARSE_COMMAND_ENABLED
RSTDIO_ParseCommand,
#endif
#endif
McuNRF24L01_ParseCommand,
NULL /* sentinel */
};
return McuShell_IterateTable(cmd, handled, io, CmdParserTable);
}
#if PL_HAS_RADIO
void McuRNet_OnRadioEvent(McuRNet_RadioEvent event)
{
(void)event;
/* Write your code here ... */
}
#endif
#endif /* McuRNET_CONFIG_IS_ENABLED */
/* END McuRNet. */
/*!
** @}
*/

View File

@@ -0,0 +1,161 @@
/* ###################################################################
** This component module is generated by Processor Expert. Do not modify it.
** Filename : McuRNet.h
** Project : INTRO_K22_Robo
** Processor : MK22FX512VLK12
** Component : RNet
** Version : Component 01.096, Driver 01.00, CPU db: 3.00.000
** Compiler : GNU C Compiler
** Date/Time : 2021-07-06, 16:35, # CodeGen: 0
** Abstract :
** This components implements the RNet Stack.
** Settings :
** Component name : McuRNet
** Transceiver :
** Transceiver Type : nRF24L01+
** nRF24L01+ : Enabled
** nRF24L01+ : McuNRF24L01
** Radio Channel : 81
** Data Rate : 2000 kBit
** Payload Size : 32
** Address : 0x11, 0x22, 0x33, 0x44, 0x55
** SMAC : Disabled
** Network :
** Address Size : 8 Bits
** Queues :
** Rx Message Queue Size : 15
** Tx Message Queue Size : 15
** Message Queue Blocking Time (ms) : 200
** Send Retry Count : 3
** Send Timeout (ms) : 250
** System :
** Utility : UTIL1
** RTOS : FRTOS1
** Shell : Enabled
** Remote StdIO : Enabled
** Queue length : 48
** Queue Timeout (ms) : 500
** Shell : CLS1
** Contents :
** ParseCommand - uint8_t McuRNet_ParseCommand(const unsigned char *cmd, bool *handled, const...
** Init - void McuRNet_Init(void);
** Deinit - void McuRNet_Deinit(void);
**
** * Copyright (c) 2014-2019, Erich Styger
** * Web: https://mcuoneclipse.com
** * SourceForge: https://sourceforge.net/projects/mcuoneclipse
** * Git: https://github.com/ErichStyger/McuOnEclipse_PEx
** * All rights reserved.
** *
** * Redistribution and use in source and binary forms, with or without modification,
** * are permitted provided that the following conditions are met:
** *
** * - Redistributions of source code must retain the above copyright notice, this list
** * of conditions and the following disclaimer.
** *
** * - 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.
** *
** * 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.
** ###################################################################*/
/*!
** @file McuRNet.h
** @version 01.00
** @brief
** This components implements the RNet Stack.
*/
/*!
** @addtogroup McuRNet_module McuRNet module documentation
** @{
*/
#ifndef __McuRNet_H
#define __McuRNet_H
/* MODULE McuRNet. */
#include "McuLib.h" /* SDK and API used */
#include "McuRNetConfig.h" /* configuration */
/* Include inherited components */
#include "McuNRF24L01.h"
#include "McuUtility.h"
#include "McuRTOS.h"
#include "McuShell.h"
#define McuRNet_PARSE_COMMAND_ENABLED 1 /* set to 1 if method ParseCommand() is present, 0 otherwise */
typedef enum {
McuRNet_RADIO_MSG_RECEIVED, /* message has been received */
McuRNet_RADIO_MSG_SENT, /* message has been sent */
McuRNet_RADIO_TIMEOUT, /* timeout, no response received */
McuRNet_RADIO_RETRY, /* retry, sending message again */
McuRNet_RADIO_RETRY_MSG_FAILED, /* creating retry message failed */
McuRNet_RADIO_ACK_RECEIVED /* acknowledge message received */
} McuRNet_RadioEvent;
#ifndef McuRNet_CREATE_EVENTS
#define McuRNet_CREATE_EVENTS 0 /* if to call user event handler */
#endif
void McuRNet_Init(void);
/*
** ===================================================================
** Method : Init (component RNet)
**
** Description :
** Initializes the RNet Stack
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
void McuRNet_Deinit(void);
/*
** ===================================================================
** Method : Deinit (component RNet)
**
** Description :
** Deinitializes the RNet Stack
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
uint8_t McuRNet_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io);
/*
** ===================================================================
** Method : ParseCommand (component RNet)
**
** Description :
** Shell Command Line parser. This method is enabled/disabled
** depending on if you have the Shell enabled/disabled in the
** properties.
** Parameters :
** NAME - DESCRIPTION
** * cmd - Pointer to command string
** * handled - Pointer to variable which tells if
** the command has been handled or not
** * io - Pointer to I/O structure
** Returns :
** --- - Error code
** ===================================================================
*/
/* END McuRNet. */
#endif
/* ifndef __McuRNet_H */
/*!
** @}
*/

View File

@@ -0,0 +1,117 @@
/**
* \file
* \brief This is a main configuration file for the RNet stack
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html)
*
* With this header file, the stack is configured. It sets the configuration defaults.
* The application can overwrite the configuration with a RNet_AppConfig.h header file.
*/
#ifndef __McuRNet_CONFIG_H
#define __McuRNet_CONFIG_H
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#ifndef McuRNet_CONFIG_APPLICATION_HEADER_FILE
#define McuRNet_CONFIG_APPLICATION_HEADER_FILE "RNet_AppConfig.h"
/*!< Header file to be used for the RNet application configuration */
#endif
#include "McuLib.h"
#include "McuRNet.h" /* component main header file */
#ifndef McuRNET_CONFIG_IS_ENABLED
#define McuRNET_CONFIG_IS_ENABLED (1 && McuLib_CONFIG_SDK_USE_FREERTOS)
#endif
/* remote standard I/O destination address */
#ifndef RSTDIO_CONFIG_SETTING_RSTDIO_DEFAULT_DESTINATION_ADDRESS
#define RSTDIO_CONFIG_SETTING_RSTDIO_DEFAULT_DESTINATION_ADDRESS 255
#endif
#ifndef RSTDIO_CONFIG_QUEUE_LENGTH
#define RSTDIO_CONFIG_QUEUE_LENGTH (48)
/*!< Size in bytes for the different RStdIO queues: RxStdOut, RxStdIn, RxStdErr, TxStdIn, TxStdErr */
#endif
/* Default configuration items, can be overwritten by the application configuration header file: */
#define RNET_CONFIG_TRANSCEIVER_NRF24 1
/*!< Nordic Semiconductor nRF24L01+ */
#define RNET_CONFIG_TRANSCEIVER_MC13201 2
/*!< Freescale MC13201/MC13213 */
#define RNET_CONFIG_TRANSCEIVER_TYPE RNET_CONFIG_TRANSCEIVER_NRF24
/*!< Transceiver type used */
#if RNET_CONFIG_TRANSCEIVER_TYPE==RNET_CONFIG_TRANSCEIVER_NRF24
/* nRF24L01+ specific settings */
#ifndef RNET_CONFIG_NRF24_DATA_RATE
#define RNET_CONFIG_NRF24_DATA_RATE (McuNRF24L01_RF_SETUP_RF_DR_2000)
/*!< default transceiver data rate */
#endif
#endif /* RNET_CONFIG_TRANSCEIVER_TYPE==RNET_CONFIG_TRANSCEIVER_NRF24 */
#if RNET_CONFIG_TRANSCEIVER_TYPE==RNET_CONFIG_TRANSCEIVER_MC13201
/* MC1320x specific settings */
#ifndef RNET_CONFIG_SMAC_OUPTUT_POWER
#define RNET_CONFIG_SMAC_OUPTUT_POWER (McuNRF24L01_RF_SETUP_RF_DR_2000)
/*!< default transceiver data rate */
#endif
#endif /* RNET_CONFIG_TRANSCEIVER_TYPE==RNET_CONFIG_TRANSCEIVER_MC13201 */
#ifndef RNET_CONFIG_TRANSCEIVER_PAYLOAD_SIZE
#define RNET_CONFIG_TRANSCEIVER_PAYLOAD_SIZE (32)
/*!< Size of the physical transceiver payload (bytes), max 32 bytes for nRF24L01+, max 128 bytes for MC1320x */
#endif
#ifndef RNET_CONFIG_TRANSCEIVER_CHANNEL
#define RNET_CONFIG_TRANSCEIVER_CHANNEL (81)
/*!< default radio channel of transceiver */
#endif
#ifndef RNET_CONFIG_SHORT_ADDR_SIZE
#define RNET_CONFIG_SHORT_ADDR_SIZE (1)
/*!< size of short address type. Either 1 or 2 */
#endif
#ifndef RNET_CONFIG_SEND_RETRY_CNT
#define RNET_CONFIG_SEND_RETRY_CNT (3)
/*!< Number of retries if message sending failed. Set to zero to disable retry. */
#endif
#ifndef RNET_CONFIG_RX_MULTIPLE_MESSAGE_COUNT
#define RNET_CONFIG_RX_MULTIPLE_MESSAGE_COUNT (10)
/*!< How many incomming messages should be handled togther. */
#endif
/* Configuration for Rx and Tx queues */
#ifndef RNET_CONFIG_MSG_QUEUE_NOF_RX_ITEMS
#define RNET_CONFIG_MSG_QUEUE_NOF_RX_ITEMS (15)
/*!< Number items in the Rx message queue. The higher, the more items can be buffered. */
#endif
#ifndef RNET_CONFIG_MSG_QUEUE_NOF_TX_ITEMS
#define RNET_CONFIG_MSG_QUEUE_NOF_TX_ITEMS (15)
/*!< Number items in the Tx message queue. The higher, the more items can be buffered. */
#endif
#ifndef RNET_CONFIG_MSG_QUEUE_PUT_BLOCK_TIME_TICKS
#define RNET_CONFIG_MSG_QUEUE_PUT_BLOCK_TIME_TICKS (pdMS_TO_TICKS(200))
/*!< Blocking number of RTOS ticks for putting items into the message queue before timeout. Use portMAX_DELAY for blocking. */
#endif
#ifndef RNET_CONFIG_REMOTE_STDIO
#define RNET_CONFIG_REMOTE_STDIO (1)
/*!< 1 for remote stdio over radio enabled, 0 for disabled. */
#endif
#ifndef RNET_RADIO_WAITNG_TIMEOUT_MS
#define RNET_RADIO_WAITNG_TIMEOUT_MS 250 /* timeout value in milliseconds, used for RADIO_WAITING_DATA_SENT */
#endif
#endif /* McuRNET_CONFIG_IS_ENABLED */
#endif /* __McuRNet_CONFIG_H */

View File

@@ -0,0 +1,174 @@
/**
* \file
* \brief This is the implementation for the Radio Application service part.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module provides application services of the network stack.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RApp.h"
#include "RNWK.h"
#include "McuUtility.h"
#include "McuLog.h"
static const RAPP_MsgHandler *RAPP_MsgHandlerTable;
uint8_t RAPP_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RAPP_MSG_Type type, RAPP_ShortAddrType dstAddr, RAPP_FlagsType flags) {
RAPP_BUF_TYPE(buf) = (uint8_t)type;
RAPP_BUF_SIZE(buf) = payloadSize;
return RNWK_PutPayload(buf, bufSize, payloadSize+RAPP_HEADER_SIZE, dstAddr, flags);
}
uint8_t RAPP_SendPayloadDataBlock(uint8_t *appPayload, uint8_t appPayloadSize, uint8_t msgType, RAPP_ShortAddrType dstAddr, RAPP_FlagsType flags) {
uint8_t buf[RAPP_BUFFER_SIZE]; /* payload data buffer */
int i;
if (appPayloadSize>RAPP_PAYLOAD_SIZE) {
return ERR_OVERFLOW; /* block too large for payload */
}
i = 0;
while(i<appPayloadSize) {
RAPP_BUF_PAYLOAD_START(buf)[i] = *appPayload;
appPayload++; i++;
}
return RAPP_PutPayload(buf, sizeof(buf), appPayloadSize, (RAPP_MSG_Type)msgType, dstAddr, flags);
}
static uint8_t IterateTable(RAPP_MSG_Type type, uint8_t size, uint8_t *data, RAPP_ShortAddrType srcAddr, bool *handled, RAPP_PacketDesc *packet, const RAPP_MsgHandler *table) {
uint8_t res = ERR_OK;
if (table==NULL) { /* no table??? */
return ERR_FAILED;
}
/* iterate through all parser functions in table */
while(*table!=NULL) {
if ((*table)(type, size, data, srcAddr, handled, packet)!=ERR_OK) {
res = ERR_FAILED;
}
table++;
}
return res;
}
static uint8_t ParseMessage(RAPP_MSG_Type type, uint8_t size, uint8_t *data, RAPP_ShortAddrType srcAddr, RAPP_PacketDesc *packet) {
bool handled = FALSE;
uint8_t res;
res = IterateTable(type, size, data, srcAddr, &handled, packet, RAPP_MsgHandlerTable); /* iterate through all parser functions in table */
if (!handled || res!=ERR_OK) { /* no handler has handled the command? */
res = ERR_FAILED;
}
return res;
}
static uint8_t RAPP_OnPacketRx(RAPP_PacketDesc *packet) {
uint8_t size;
uint8_t *data;
RAPP_MSG_Type type;
RAPP_ShortAddrType srcAddr;
type = (RAPP_MSG_Type)RAPP_BUF_TYPE(packet->phyData);
size = RAPP_BUF_SIZE(packet->phyData);
data = RAPP_BUF_PAYLOAD_START(packet->phyData);
srcAddr = RNWK_BUF_GET_SRC_ADDR(packet->phyData);
return ParseMessage(type, size, data, srcAddr, packet);
}
uint8_t RAPP_SetMessageHandlerTable(const RAPP_MsgHandler *table) {
RAPP_MsgHandlerTable = table;
return ERR_OK;
}
RAPP_ShortAddrType RAPP_GetThisNodeAddr(void) {
return RNWK_GetThisNodeAddr();
}
uint8_t RAPP_SetThisNodeAddr(RAPP_ShortAddrType addr) {
return RNWK_SetThisNodeAddr(addr);
}
void RAPP_SniffPacket(RAPP_PacketDesc *packet, bool isTx) {
int i;
uint8_t dataSize;
unsigned char flagsBuf[32];
unsigned char phyBuf[96];
unsigned char macBuf[32];
if (packet->flags!=RPHY_PACKET_FLAGS_NONE) {
flagsBuf[0] = '\0';
if (packet->flags&RPHY_PACKET_FLAGS_IS_ACK) {
McuUtility_strcat(flagsBuf, sizeof(flagsBuf), (unsigned char*)" IS_ACK");
}
if (packet->flags&RPHY_PACKET_FLAGS_REQ_ACK) {
McuUtility_strcat(flagsBuf, sizeof(flagsBuf), (unsigned char*)" REQ_ACK");
}
if (packet->flags&RPHY_PACKET_FLAGS_NO_ACK) {
McuUtility_strcat(flagsBuf, sizeof(flagsBuf), (unsigned char*)" NO_ACK");
}
if (packet->flags&RPHY_PACKET_FLAGS_POWER_DOWN) {
McuUtility_strcat(flagsBuf, sizeof(flagsBuf), (unsigned char*)" POWER_DOWN");
}
} else {
McuUtility_strcpy(flagsBuf, sizeof(flagsBuf), (unsigned char*)" ");
}
/* PHY */
phyBuf[0] = '\0';
dataSize = RPHY_BUF_SIZE(packet->phyData);
for(i=0; i<dataSize+RPHY_HEADER_SIZE;i++) {
McuUtility_strcatNum8Hex(phyBuf, sizeof(phyBuf), packet->phyData[i]);
McuUtility_chcat(phyBuf, sizeof(phyBuf), ' ');
}
/* MAC */
RMAC_DecodeType(macBuf, sizeof(macBuf), packet);
McuLog_trace("%s:flags:%02x%s size:%02x PHY: %sMAC: type:%02x%s, s#:%02x NWK: src:%02x dst:%02x",
isTx?"Tx":"Rx",
packet->flags,
flagsBuf,
packet->phySize,
/* PHY */
phyBuf,
/* MAC */
RMAC_BUF_TYPE(packet->phyData),
macBuf,
RMAC_BUF_SEQN(packet->phyData),
/* NWK */
RNWK_BUF_GET_SRC_ADDR(packet->phyData),
RNWK_BUF_GET_DST_ADDR(packet->phyData)
);
/* APP */
if (dataSize>RMAC_HEADER_SIZE+RNWK_HEADER_SIZE) { /* there is application data */
unsigned char appBuf[32];
dataSize = RAPP_BUF_SIZE(packet->phyData);
uint8_t *app_data = RAPP_BUF_PAYLOAD_START(packet->phyData);
appBuf[0] = '\0';
for(i=0; i<dataSize;i++) {
McuUtility_strcatNum8Hex(appBuf, sizeof(appBuf), app_data[i]);
McuUtility_strcat(appBuf, sizeof(appBuf), (unsigned char*)" ");
}
McuLog_trace("APP: type:%02x size:%02x data:%s",
/* APP */
RAPP_BUF_TYPE(packet->phyData),
RAPP_BUF_SIZE(packet->phyData),
appBuf
);
}
}
void RAPP_Deinit(void) {
/* nothing needed */
}
void RAPP_Init(void) {
(void)RNWK_SetAppOnPacketRxCallback(RAPP_OnPacketRx);
RAPP_MsgHandlerTable = NULL;
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,87 @@
/**
* \file
* \brief This is the interface for the Radio Application part.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module acts as the application part of the network stack.
*/
#ifndef RAPP_H_
#define RAPP_H_
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include McuRNet_CONFIG_APPLICATION_HEADER_FILE
#include "RNWK.h"
#include "RPHY.h"
/* payload format is:
* <type><size><data>
*/
#define RAPP_HEADER_SIZE (2) /* <type><size> */
#define RAPP_PAYLOAD_SIZE (RNWK_PAYLOAD_SIZE-RAPP_HEADER_SIZE)
#define RAPP_BUFFER_SIZE (RNWK_BUFFER_SIZE)
/* PHY buffer access macros */
#define RAPP_BUF_IDX_TYPE (RNWK_BUF_IDX_PAYLOAD+0) /* <type> index */
#define RAPP_BUF_IDX_SIZE (RNWK_BUF_IDX_PAYLOAD+1) /* <size> index */
#define RAPP_BUF_IDX_PAYLOAD (RNWK_BUF_IDX_PAYLOAD+2) /* <app payload> index */
#define RAPP_BUF_TYPE(phy) ((phy)[RAPP_BUF_IDX_TYPE])
#define RAPP_BUF_SIZE(phy) ((phy)[RAPP_BUF_IDX_SIZE])
#define RAPP_BUF_PAYLOAD_START(phy) (RNWK_BUF_PAYLOAD_START(phy)+RAPP_HEADER_SIZE)
/* wrapper defines of low level types */
#define RAPP_FlagsType RPHY_FlagsType
#define RAPP_ShortAddrType RNWK_ShortAddrType
#define RAPP_PacketDesc RPHY_PacketDesc
/* message handler */
typedef uint8_t (*RAPP_MsgHandler) (RAPP_MSG_Type type, uint8_t size, uint8_t *data, RAPP_ShortAddrType srcAddr, bool *handled, RAPP_PacketDesc *packet);
uint8_t RAPP_SetMessageHandlerTable(const RAPP_MsgHandler *table);
uint8_t RAPP_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RAPP_MSG_Type type, RAPP_ShortAddrType dstAddr, RAPP_FlagsType flags);
/*!
* \brief Returns the network node address
* \return Current network address of this node.
*/
RAPP_ShortAddrType RAPP_GetThisNodeAddr(void);
/*!
* \brief Sets the network address of this node.
* \param addr Network node address to set.
* \return Error code, ERR_OK for no failure.
*/
uint8_t RAPP_SetThisNodeAddr(RAPP_ShortAddrType addr);
/*!
* \brief Send an application payload data block.
* \param appPayload Size of application payload.
* \param appPayloadSize Application payload size.
* \param msgType Payload message type.
* \param dstAddr destination address.
* \param flags Packet flags.
* \return Error code, ERR_OK for no failure.
*/
uint8_t RAPP_SendPayloadDataBlock(uint8_t *appPayload, uint8_t appPayloadSize, uint8_t msgType, RAPP_ShortAddrType dstAddr, RAPP_FlagsType flags);
/*!
* \brief Sniffs and dumps a packet.
* \param packet Data packet.
* \param isTx If either Tx or Rx packet.
*/
void RAPP_SniffPacket(RAPP_PacketDesc *packet, bool isTx);
/*! \brief Initializes the module */
void RAPP_Init(void);
/*! \brief Deinitializes the module */
void RAPP_Deinit(void);
#endif /* McuRNET_CONFIG_IS_ENABLED */
#endif /* RAPP_H_ */

View File

@@ -0,0 +1,98 @@
/**
* \file
* \brief This is the implementation of the Radio MAC part.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module encapsulates the Media Access of network stack.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RMAC.h"
#include "RPHY.h"
#include "RNWK.h"
#include "McuUtility.h"
static uint8_t RMAC_SeqNr = 0;
static uint8_t RMAC_ExpectedAckSeqNr;
uint8_t RMAC_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags) {
if (flags&RPHY_PACKET_FLAGS_REQ_ACK) {
RMAC_BUF_TYPE(buf) = (uint8_t)((uint8_t)RMAC_MSG_TYPE_DATA|(uint8_t)RMAC_MSG_TYPE_REQ_ACK);
} else {
RMAC_BUF_TYPE(buf) = (uint8_t)RMAC_MSG_TYPE_DATA;
}
RMAC_ExpectedAckSeqNr = RMAC_SeqNr;
RMAC_BUF_SEQN(buf) = RMAC_SeqNr++;
return RPHY_PutPayload(buf, bufSize, payloadSize+RMAC_HEADER_SIZE, flags);
}
uint8_t RMAC_OnPacketRx(RPHY_PacketDesc *packet) {
return RNWK_OnPacketRx(packet); /* pass data packet up the stack */
}
uint8_t RMAC_SendACK(RPHY_PacketDesc *rxPacket, RPHY_PacketDesc *ackPacket) {
RMAC_BUF_TYPE(ackPacket->phyData) = (uint8_t)RMAC_MSG_TYPE_ACK; /* set type to ack */
RMAC_BUF_SEQN(ackPacket->phyData) = RMAC_BUF_SEQN(rxPacket->phyData);
/* use same sequence number as in the received package, so no change */
return RPHY_PutPayload(ackPacket->phyData, ackPacket->phySize, RMAC_HEADER_SIZE+RNWK_HEADER_SIZE, RPHY_PACKET_FLAGS_NONE);
}
RMAC_MsgType RMAC_GetType(uint8_t *buf, size_t bufSize) {
(void)bufSize; /* not used */
return (RMAC_MsgType)RMAC_BUF_TYPE(buf);
}
bool RMAC_IsExpectedACK(uint8_t *buf, size_t bufSize) {
(void)bufSize; /* not used */
return RMAC_BUF_SEQN(buf)==RMAC_ExpectedAckSeqNr;
}
void RMAC_SniffPacket(RPHY_PacketDesc *packet, bool isTx) {
RNWK_SniffPacket(packet, isTx);
}
void RMAC_DecodeType(uint8_t *buf, size_t bufSize, RPHY_PacketDesc *packet) {
RMAC_MsgType type;
bool first = TRUE;
type = (RMAC_MsgType)RMAC_BUF_TYPE(packet->phyData);
buf[0] = '\0';
McuUtility_chcat(buf, bufSize, '(');
if ((uint8_t)type&(uint8_t)RMAC_MSG_TYPE_REQ_ACK) {
McuUtility_strcat(buf, bufSize, (unsigned char*)"RACK");
first = FALSE;
} else {
McuUtility_strcat(buf, bufSize, (unsigned char*)"NACK");
first = FALSE;
}
if ((uint8_t)type&(uint8_t)RMAC_MSG_TYPE_DATA) {
if (!first) {
McuUtility_chcat(buf, bufSize, '|');
}
McuUtility_strcat(buf, bufSize, (unsigned char*)"DATA");
first = FALSE;
}
if ((uint8_t)type&(uint8_t)RMAC_MSG_TYPE_ACK) {
if (!first) {
McuUtility_chcat(buf, bufSize, '|');
}
McuUtility_strcat(buf, bufSize, (unsigned char*)"ACK");
}
if ((uint8_t)type&(uint8_t)RMAC_MSG_TYPE_CMD) {
McuUtility_strcat(buf, bufSize, (unsigned char*)"CMD");
}
McuUtility_chcat(buf, bufSize, ')');
}
void RMAC_Deinit(void) {
/* nothing needed */
}
void RMAC_Init(void) {
RMAC_SeqNr = 0;
RMAC_ExpectedAckSeqNr = 0;
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,110 @@
/**
* \file
* \brief This is the interface for the Radio MAC part.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module encapsulates the Media Access of network stack.
*/
#ifndef RMAC_H_
#define RMAC_H_
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RPHY.h"
typedef enum RMAC_MsgType {
RMAC_MSG_TYPE_INIT = 0x0, /* initialization value */
RMAC_MSG_TYPE_DATA = 0x1, /* flag: data message */
RMAC_MSG_TYPE_ACK = 0x2, /* flag: acknowledge message */
RMAC_MSG_TYPE_CMD = 0x4, /* flag: command message */
RMAC_MSG_TYPE_REQ_ACK = 0x80, /* flag: ack requested */
} RMAC_MsgType;
#define RMAC_MSG_TYPE_IS_DATA(type) ((uint8_t)(type)&(uint8_t)RMAC_MSG_TYPE_DATA)
#define RMAC_MSG_TYPE_IS_ACK(type) ((uint8_t)(type)&(uint8_t)RMAC_MSG_TYPE_ACK)
#define RMAC_MSG_TYPE_IS_CMD(type) ((uint8_t)(type)&(uint8_t)RMAC_MSG_TYPE_CMD)
#define RMAC_MSG_TYPE_REQ_ACK(type) ((uint8_t)(type)&(uint8_t)RMAC_MSG_TYPE_REQ_ACK)
/* payload format is:
* PHY: <size><phy payload>
* MAC: <type><seq#><mac payload>
* NWK: <saddr><dstaddr><nwk payload>
* APP: <type><size><data>
*/
#define RMAC_HEADER_SIZE (2) /* <type><seq#> */
#define RMAC_PAYLOAD_SIZE (RPHY_PAYLOAD_SIZE-RMAC_HEADER_SIZE)
#define RMAC_BUFFER_SIZE (RPHY_BUFFER_SIZE)
/* PHY buffer access macros */
#define RMAC_BUF_IDX_TYPE (RPHY_BUF_IDX_PAYLOAD+0) /* <type> index */
#define RMAC_BUF_IDX_SEQNR (RPHY_BUF_IDX_PAYLOAD+1) /* <seq#> index */
#define RMAC_BUF_IDX_PAYLOAD (RPHY_BUF_IDX_PAYLOAD+2) /* <mac payload> index */
#define RMAC_BUF_TYPE(phy) ((phy)[RMAC_BUF_IDX_TYPE])
#define RMAC_BUF_SEQN(phy) ((phy)[RMAC_BUF_IDX_SEQNR])
#define RMAC_BUF_PAYLOAD_START(phy) (RPHY_BUF_PAYLOAD_START(phy)+RMAC_HEADER_SIZE)
uint8_t RMAC_OnPacketRx(RPHY_PacketDesc *packet);
/*!
* \brief Puts the MAC payload data into a buffer to be sent later.
* \param[in] buf Buffer with the data, must be of RMAC_BUFFER_SIZE.
* \param[in] bufSize Buffer size.
* \param[in] payloadSize Size of MAC payload data.
* \param[in] flags Packet flags
* \return Error code, ERR_OK if everything is ok, ERR_OVERFLOW if buffer is too small.
*/
uint8_t RMAC_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags);
/*!
* \brief Sends an acknowledge message for the received MAC payload data.
* \param[in] packet Packet data for which we need to send the ack.
* \param[in] saddr Source address of the packet (our own address).
* \return Error code, ERR_OK if everything is ok, error code otherwise.
*/
uint8_t RMAC_SendACK(RPHY_PacketDesc *rxPacket, RPHY_PacketDesc *ackPacket);
/*!
* \brief Check if the expected ACK message is expected. This is done with checking the sequence number.
* \param[in] buf Pointer to the received packet.
* \param[in] bufSize size of the received packet.
* \return TRUE if it is an expected ACK packet, false otherwise (e.g. if sequence number does not match).
*/
bool RMAC_IsExpectedACK(uint8_t *buf, size_t bufSize);
/*!
* \brief Returns the type of the message.
* \param buf Pointer to the message buffer.
* \param bufSize Size of the buffer.
* \return Type of message.
*/
RMAC_MsgType RMAC_GetType(uint8_t *buf, size_t bufSize);
/*!
* \brief Sniffs and dumps a packet to the Shell.
* \param packet Data packet.
* \param isTx If either Tx or Rx packet.
*/
void RMAC_SniffPacket(RPHY_PacketDesc *packet, bool isTx);
/*!
* \brief Decodes the MAC type information as string.
* \param[out] buf Character buffer where to store the string.
* \param[in] bufSize Size of character buffer in bytes.
* \param[in] packet Packet information.
*/
void RMAC_DecodeType(uint8_t *buf, size_t bufSize, RPHY_PacketDesc *packet);
/*! \brief Initializes the module */
void RMAC_Init(void);
/*! \brief Deinitializes the module */
void RMAC_Deinit(void);
#endif /* McuRNET_CONFIG_IS_ENABLED */
#endif /* RMAC_H_ */

View File

@@ -0,0 +1,201 @@
/**
* \file
* \brief This implements a queue/buffer for radio messages
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module uses queues to retrieve and store radio messages.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "Radio.h"
#include "RMSG.h"
#include "McuRTOS.h"
#include "RPHY.h"
/* Configuration for tx and rx queues */
#define RMSG_QUEUE_RX_NOF_ITEMS (RNET_CONFIG_MSG_QUEUE_NOF_RX_ITEMS) /* number of items in the queue */
#define RMSG_QUEUE_TX_NOF_ITEMS (RNET_CONFIG_MSG_QUEUE_NOF_TX_ITEMS) /* number of items in the queue */
#define RMSG_QUEUE_PUT_WAIT (RNET_CONFIG_MSG_QUEUE_PUT_BLOCK_TIME_TICKS) /* blocking time (ticks!) for putting messages into queue */
static QueueHandle_t RMSG_MsgRxQueue, RMSG_MsgTxQueue; /* queue for messages, format is: kind(8bit) dataSize(8bit) data */
unsigned int RMSG_RxQueueNofItems(void) {
return (unsigned int)McuRTOS_uxQueueMessagesWaiting(RMSG_MsgRxQueue);
}
unsigned int RMSG_TxQueueNofItems(void) {
return (unsigned int)McuRTOS_uxQueueMessagesWaiting(RMSG_MsgTxQueue);
}
uint8_t RMSG_FlushRxQueue(void) {
if (McuRTOS_xQueueReset(RMSG_MsgRxQueue)!=pdPASS) {
return ERR_FAILED;
}
return ERR_OK;
}
uint8_t RMSG_FlushTxQueue(void) {
if (McuRTOS_xQueueReset(RMSG_MsgTxQueue)!=pdPASS) {
return ERR_FAILED;
}
return ERR_OK;
}
uint8_t RMSG_QueuePut(uint8_t *buf, size_t bufSize, uint8_t payloadSize, bool fromISR, bool isTx, bool toBack, RPHY_FlagsType flags) {
/* data format is: dataSize(8bit) data */
uint8_t res = ERR_OK;
QueueHandle_t queue;
BaseType_t qRes;
if (payloadSize>RPHY_PAYLOAD_SIZE) {
return ERR_OVERFLOW; /* more data than can fit into payload! */
}
if (bufSize!=RPHY_BUFFER_SIZE) {
return ERR_FAILED; /* must be exactly this buffer size!!! */
}
if (isTx) {
queue = RMSG_MsgTxQueue;
} else {
queue = RMSG_MsgRxQueue;
}
RPHY_BUF_FLAGS(buf) = flags;
RPHY_BUF_SIZE(buf) = payloadSize;
if (fromISR) {
BaseType_t pxHigherPriorityTaskWoken;
if (toBack) {
qRes = McuRTOS_xQueueSendToBackFromISR(queue, buf, &pxHigherPriorityTaskWoken);
} else {
qRes = McuRTOS_xQueueSendToFrontFromISR(queue, buf, &pxHigherPriorityTaskWoken);
}
if (qRes!=pdTRUE) {
/* was not able to send to the queue. Well, not much we can do here... */
res = ERR_BUSY;
} else {
if (isTx) {
RADIO_NotifyFromInterrupt(RADIO_FLAG_TX_REQUEST, &pxHigherPriorityTaskWoken);
}
}
} else {
if (toBack) {
qRes = McuRTOS_xQueueSendToBack(queue, buf, RMSG_QUEUE_PUT_WAIT);
} else {
qRes = McuRTOS_xQueueSendToFront(queue, buf, RMSG_QUEUE_PUT_WAIT);
}
if (qRes!=pdTRUE) {
res = ERR_BUSY;
} else {
if (isTx) {
RADIO_Notify(RADIO_FLAG_TX_REQUEST);
}
}
}
return res;
}
uint8_t RMSG_PutRetryTxMsg(uint8_t *buf, size_t bufSize) {
if (bufSize<RPHY_BUFFER_SIZE) {
return ERR_OVERFLOW; /* not enough space in buffer */
}
if (McuRTOS_xQueueSendToFront(RMSG_MsgTxQueue, buf, 0)==pdPASS) {
RADIO_Notify(RADIO_FLAG_TX_REQUEST);
return ERR_OK; /* success adding message to queue */
}
return ERR_RXEMPTY;
}
uint8_t RMSG_GetTxMsg(uint8_t *buf, size_t bufSize) {
if (bufSize<RPHY_BUFFER_SIZE) {
return ERR_OVERFLOW; /* not enough space in buffer */
}
if (McuRTOS_xQueueReceive(RMSG_MsgTxQueue, buf, 0)==pdPASS) {
return ERR_OK; /* received message from queue */
}
return ERR_RXEMPTY;
}
uint8_t RMSG_GetRxMsg(uint8_t *buf, size_t bufSize) {
/* first byte in the queue is the size of the item */
if (bufSize<RPHY_BUFFER_SIZE) {
return ERR_OVERFLOW; /* not enough space in buffer */
}
if (McuRTOS_xQueueReceive(RMSG_MsgRxQueue, buf, 0)==pdPASS) { /* immediately returns if queue is empty */
return ERR_OK; /* received message from queue */
}
return ERR_RXEMPTY;
}
uint8_t RMSG_QueueTxMsg(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags) {
return RMSG_QueuePut(buf, bufSize, payloadSize, FALSE, TRUE, TRUE, flags);
}
uint8_t RMSG_QueueRxMsg(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags) {
return RMSG_QueuePut(buf, bufSize, payloadSize, FALSE, FALSE, TRUE, flags);
}
static uint8_t RMSG_PrintHelp(const McuShell_StdIOType *io) {
McuShell_SendHelpStr((unsigned char*)"rmsg", (unsigned char*)"Group of rmsg commands\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" help|status", (unsigned char*)"Shows radio help or status\r\n", io->stdOut);
return ERR_OK;
}
static uint8_t RMSG_PrintStatus(const McuShell_StdIOType *io) {
uint8_t buf[32];
McuShell_SendStatusStr((unsigned char*)"rmsg", (unsigned char*)"\r\n", io->stdOut);
McuUtility_Num32uToStr(buf, sizeof(buf), RMSG_RxQueueNofItems());
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)" items\r\n");
McuShell_SendStatusStr((unsigned char*)" rx", buf, io->stdOut);
McuUtility_Num32uToStr(buf, sizeof(buf), RMSG_TxQueueNofItems());
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)" items\r\n");
McuShell_SendStatusStr((unsigned char*)" tx", buf, io->stdOut);
return ERR_OK;
}
uint8_t RMSG_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io) {
uint8_t res = ERR_OK;
if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, (char*)"rmsg help")==0) {
*handled = TRUE;
return RMSG_PrintHelp(io);
} else if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_STATUS)==0 || McuUtility_strcmp((char*)cmd, (char*)"rmsg status")==0) {
*handled = TRUE;
return RMSG_PrintStatus(io);
}
return res;
}
void RMSG_Deinit(void) {
McuRTOS_vQueueUnregisterQueue(RMSG_MsgRxQueue);
McuRTOS_vQueueDelete(RMSG_MsgRxQueue);
RMSG_MsgRxQueue = NULL;
McuRTOS_vQueueUnregisterQueue(RMSG_MsgTxQueue);
McuRTOS_vQueueDelete(RMSG_MsgTxQueue);
RMSG_MsgTxQueue = NULL;
}
void RMSG_Init(void) {
RMSG_MsgRxQueue = McuRTOS_xQueueCreate(RMSG_QUEUE_RX_NOF_ITEMS, RPHY_BUFFER_SIZE);
if (RMSG_MsgRxQueue==NULL) { /* queue creation failed! */
for(;;) {} /* not enough memory? */
}
McuRTOS_vQueueAddToRegistry(RMSG_MsgRxQueue, "RadioRxMsg");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RMSG_MsgRxQueue, "RadioRxMsg");
#endif
RMSG_MsgTxQueue = McuRTOS_xQueueCreate(RMSG_QUEUE_TX_NOF_ITEMS, RPHY_BUFFER_SIZE);
if (RMSG_MsgTxQueue==NULL) { /* queue creation failed! */
for(;;) {} /* not enough memory? */
}
McuRTOS_vQueueAddToRegistry(RMSG_MsgTxQueue, "RadioTxMsg");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RMSG_MsgTxQueue, "RadioTxMsg");
#endif
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,118 @@
/**
* \file
* \brief Radio Network Message Layer
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module implements radio message handling module of the radio network stack.
*/
#ifndef RADIOMESSAGE_H_
#define RADIOMESSAGE_H_
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RPHY.h"
#include "McuShell.h"
/*!
* \brief Parses a command
* \param cmd Command string to be parsed
* \param handled Sets this variable to TRUE if command was handled
* \param io I/O stream to be used for input/output
* \return Error code, ERR_OK if everything was fine
*/
uint8_t RMSG_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io);
/*!
* \brief Returns the number of messages in the Rx queue
* \return Number of items in the Rx queue
*/
unsigned int RMSG_RxQueueNofItems(void);
/*!
* \brief Returns the number of messages in the Tx queue
* \return Number of items in the Tx queue
*/
unsigned int RMSG_TxQueueNofItems(void);
/*!
* \brief Flushes the Rx queue (makes it empty).
* \return Error code, ERR_OK for everything fine.
*/
uint8_t RMSG_FlushRxQueue(void);
/*!
* \brief Flushes the Rx queue (makes it empty).
* \return Error code, ERR_OK for everything fine.
*/
uint8_t RMSG_FlushTxQueue(void);
/*!
* \brief Queues a message to be sent to the radio transceiver.
* \param buf Pointer to the message data to be sent.
* \param bufSize Size of buffer.
* \param payloadSize Size of payload data.
* \param fromISR If called from an ISR routine.
* \param isTx If message is TX or RX.
* \param toBack If message shall be sent to the back of the list.
* \param flags Packet flags.
* \return Error code, ERR_OK if message has been queued.
*/
uint8_t RMSG_QueuePut(uint8_t *buf, size_t bufSize, uint8_t payloadSize, bool fromISR, bool isTx, bool toBack, RPHY_FlagsType flags);
/*!
* \brief Puts a message into the TX queue for resending (in front of the queue)
* \param buf[in] pointer to message
* \param bufSize[in] size of message
* \return Error code, ERR_OK if message has been queued.
*/
uint8_t RMSG_PutRetryTxMsg(uint8_t *buf, size_t bufSize);
/*!
* \brief Used to check if we have a message incoming from the RX queue.
* \param[in] buf Buffer where to store the incoming message
* \param[in] bufSize Size of buffer, must be at least of size PHY_BUFFER_SIZE
* \param[in] payLoadPtr Pointer to payload start.
* \param[in] payloadSize Size of payload.
* \return ERR_OK if we have a message, otherwise error code.
*/
uint8_t RMSG_GetRxMsg(uint8_t *buf, size_t bufSize);
/*!
* \brief Used to check if we have a message outgoing in the TX queue.
* \param buf Buffer where to store the incoming message
* \param bufSize Size of buffer, must be at least of size RMSG_QUEUE_ITEM_SIZE
* \return ERR_OK if we have a message, otherwise error code.
*/
uint8_t RMSG_GetTxMsg(uint8_t *buf, size_t bufSize);
/*!
* \brief Add a message to the TX queue.
* \param buf Pointer to the message data.
* \param bufSize Size of the buffer in bytes, must be RPHY_BUFFER_SIZE.
* \param payloadSize Size of payload in buffer.
* \param flags Packet flags.
* \return ERR_OK, or error code.
*/
uint8_t RMSG_QueueTxMsg(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags);
/*!
* \brief Add a message to the RX queue.
* \param buf Pointer to the message data.
* \param bufSize Size of the buffer in bytes.
* \param payloadSize Size of payload in buffer.
* \param flags Packet flags
* \return ERR_OK, or error code.
*/
uint8_t RMSG_QueueRxMsg(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags);
/*! \brief Initializes the module */
void RMSG_Init(void);
/*! \brief Deinitializes the module */
void RMSG_Deinit(void);
#endif /* RADIOMESSAGE_H_ */
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,132 @@
/**
* \file
* \brief Radio Network NWK Layer Implementation
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module implements the NWK (Network) of the radio network stack.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RPHY.h"
#include "RMAC.h"
#include "RNWK.h"
#include "RApp.h"
#include "McuUtility.h"
static RNWK_ShortAddrType RNWK_ThisNodeAddr = RNWK_ADDR_BROADCAST; /* address of this network node */
static RNWK_AppOnRxCallbackType RNWK_AppOnRxCallback = NULL; /* notification callback installed by upper layer */
RNWK_ShortAddrType RNWK_GetThisNodeAddr(void) {
return RNWK_ThisNodeAddr;
}
uint8_t RNWK_SetThisNodeAddr(RNWK_ShortAddrType addr) {
RNWK_ThisNodeAddr = addr;
return ERR_OK;
}
uint8_t RNWK_SetAppOnPacketRxCallback(RNWK_AppOnRxCallbackType callback) {
RNWK_AppOnRxCallback = callback;
return ERR_OK;
}
uint8_t RNWK_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RNWK_ShortAddrType dstAddr, RPHY_FlagsType flags) {
RNWK_ShortAddrType srcAddr;
srcAddr = RNWK_GetThisNodeAddr();
RNWK_BUF_SET_SRC_ADDR(buf, srcAddr);
RNWK_BUF_SET_DST_ADDR(buf, dstAddr);
return RMAC_PutPayload(buf, bufSize, payloadSize+RNWK_HEADER_SIZE, flags);
}
uint8_t RNWK_SendACK(RPHY_PacketDesc *rxPacket, RNWK_ShortAddrType saddr) {
RNWK_ShortAddrType addr;
uint8_t buf[RMAC_BUFFER_SIZE];
RPHY_PacketDesc ackPacket;
ackPacket.flags = RPHY_PACKET_FLAGS_NONE;
ackPacket.phyData = buf;
ackPacket.phySize = sizeof(buf);
/* send an ack message back: this is is of type ack with src and dst address */
addr = RNWK_BUF_GET_SRC_ADDR(rxPacket->phyData); /* who should receive the ack? */
RNWK_BUF_SET_SRC_ADDR(ackPacket.phyData, saddr); /* set source address */
RNWK_BUF_SET_DST_ADDR(ackPacket.phyData, addr); /* destination address is from where we got the data */
return RMAC_SendACK(rxPacket, &ackPacket);
}
uint8_t RNWK_OnPacketRx(RPHY_PacketDesc *packet) {
RNWK_ShortAddrType addr;
RMAC_MsgType type;
addr = RNWK_BUF_GET_DST_ADDR(packet->phyData);
if (addr==RNWK_ADDR_BROADCAST || addr==RNWK_GetThisNodeAddr()) { /* it is for me :-) */
type = RMAC_GetType(packet->phyData, packet->phySize); /* get the type of the message */
if (RMAC_MSG_TYPE_IS_ACK(type) && RMAC_IsExpectedACK(packet->phyData, packet->phySize)) {
/* it is an ACK, and the sequence number matches. Mark it with a flag and return, as no need for further processing */
packet->flags |= RPHY_PACKET_FLAGS_IS_ACK;
return ERR_OK; /* no need to process the packet further */
} else if (RMAC_MSG_TYPE_IS_DATA(type)) { /* data packet received */
if (RNWK_AppOnRxCallback!=NULL) { /* do we have a callback? */
if (RMAC_MSG_TYPE_REQ_ACK(type)) { /* ACK requested */
(void)RNWK_SendACK(packet, RNWK_GetThisNodeAddr()); /* send ack message back */
}
return RNWK_AppOnRxCallback(packet); /* call upper layer */
}
} else {
return ERR_FAULT; /* wrong message type? */
}
}
return ERR_FAILED;
}
void RNWK_SniffPacket(RPHY_PacketDesc *packet, bool isTx) {
RAPP_SniffPacket(packet, isTx);
}
static uint8_t PrintHelp(const McuShell_StdIOType *io) {
McuShell_SendHelpStr((unsigned char*)"rnwk", (unsigned char*)"Group of rnwk commands\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" help|status", (unsigned char*)"Shows help or status\r\n", io->stdOut);
return ERR_OK;
}
static uint8_t PrintStatus(const McuShell_StdIOType *io) {
uint8_t buf[32];
McuShell_SendStatusStr((unsigned char*)"rnwk", (unsigned char*)"\r\n", io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"0x");
#if RNWK_SHORT_ADDR_SIZE==1
McuUtility_strcatNum8Hex(buf, sizeof(buf), RNWK_GetThisNodeAddr());
#else
McuUtility_strcatNum16Hex(buf, sizeof(buf), RNWK_GetThisNodeAddr());
#endif
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStatusStr((unsigned char*)" addr", buf, io->stdOut);
return ERR_OK;
}
uint8_t RNWK_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io) {
if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, (char*)"rnwk help")==0) {
*handled = TRUE;
return PrintHelp(io);
} else if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_STATUS)==0 || McuUtility_strcmp((char*)cmd, (char*)"rnwk status")==0) {
*handled = TRUE;
return PrintStatus(io);
}
return ERR_OK;
}
void RNWK_Deinit(void) {
/* nothing needed */
}
void RNWK_Init(void) {
RNWK_ThisNodeAddr = RNWK_ADDR_BROADCAST;
RNWK_AppOnRxCallback = NULL;
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,121 @@
/**
* \file
* \brief Radio Network NWK Layer
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module implements interface for the NWK (Network) of the radio network stack.
*/
#ifndef RNWK_H_
#define RNWK_H_
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RMAC.h"
#include "RPHY.h"
/* payload format is:
* PHY: <size><phy payload>
* MAC: <type><seq#><mac payload>
* NWK: <saddr><dstaddr><nwk payload>
* APP: <type><size><data>
*/
#define RNWK_SHORT_ADDR_SIZE RNET_CONFIG_SHORT_ADDR_SIZE /* size of short address type */
#if RNWK_SHORT_ADDR_SIZE==1
typedef uint8_t RNWK_ShortAddrType; /* short address type */
#elif RNWK_SHORT_ADDR_SIZE==2
typedef uint16_t RNWK_ShortAddrType; /* short address type */
#else
#error "ERROR: unsupported address size"
#endif
#define RNWK_HEADER_SIZE (2*RNWK_SHORT_ADDR_SIZE) /* <saddr><daddr> */
#define RNWK_PAYLOAD_SIZE (RMAC_PAYLOAD_SIZE-RNWK_HEADER_SIZE)
#define RNWK_BUFFER_SIZE (RMAC_BUFFER_SIZE)
/* PHY buffer access macros */
#define RNWK_BUF_IDX_SRC_ADDR (RMAC_BUF_IDX_PAYLOAD+0) /* <saddr> index */
#define RNWK_BUF_IDX_DST_ADDR (RMAC_BUF_IDX_PAYLOAD +RNWK_SHORT_ADDR_SIZE) /* <daddr#> index */
#define RNWK_BUF_IDX_PAYLOAD (RNWK_BUF_IDX_DST_ADDR+RNWK_SHORT_ADDR_SIZE) /* <nwk payload> index */
#if RNWK_SHORT_ADDR_SIZE==1
#define RNWK_BUF_SET_SRC_ADDR(phy, addr) ((phy)[RNWK_BUF_IDX_SRC_ADDR])=(addr);
#define RNWK_BUF_SET_DST_ADDR(phy, addr) ((phy)[RNWK_BUF_IDX_DST_ADDR])=(addr);
#define RNWK_ADDR_BROADCAST 0xFF
#elif RNWK_SHORT_ADDR_SIZE==2
#define RNWK_BUF_SET_SRC_ADDR(phy, addr) {((phy)[RNWK_BUF_IDX_SRC_ADDR])=(uint8_t)((addr)&0xFF); ((phy)[RNWK_BUF_IDX_SRC_ADDR+1])=(uint8_t)((addr>>8)&0xFF);}
#define RNWK_BUF_SET_DST_ADDR(phy, addr) {((phy)[RNWK_BUF_IDX_DST_ADDR])=(uint8_t)((addr)&0xFF); ((phy)[RNWK_BUF_IDX_DST_ADDR+1])=(uint8_t)((addr>>8)&0xFF);}
#define RNWK_ADDR_BROADCAST 0xFFFF
#else
#error "NYI"
#endif
#if RNWK_SHORT_ADDR_SIZE==1
#define RNWK_BUF_GET_SRC_ADDR(phy) ((phy)[RNWK_BUF_IDX_SRC_ADDR])
#define RNWK_BUF_GET_DST_ADDR(phy) ((phy)[RNWK_BUF_IDX_DST_ADDR])
#elif RNWK_SHORT_ADDR_SIZE==2
#define RNWK_BUF_GET_SRC_ADDR(phy) (((phy)[RNWK_BUF_IDX_SRC_ADDR+1])<<8)|((phy)[RNWK_BUF_IDX_SRC_ADDR])
#define RNWK_BUF_GET_DST_ADDR(phy) (((phy)[RNWK_BUF_IDX_DST_ADDR+1])<<8)|((phy)[RNWK_BUF_IDX_DST_ADDR])
#else
#error "NYI"
#endif
#define RNWK_BUF_PAYLOAD_START(phy) (RMAC_BUF_PAYLOAD_START(phy)+RNWK_HEADER_SIZE)
typedef uint8_t (*RNWK_AppOnRxCallbackType)(RPHY_PacketDesc *packet);
uint8_t RNWK_SetAppOnPacketRxCallback(RNWK_AppOnRxCallbackType callback);
uint8_t RNWK_OnPacketRx(RPHY_PacketDesc *packet);
/*!
* \brief Sents an ACK packet for a packet received.
* \param rxPacket Packet which has been received and for which an ACK should be sent.
* \param saddr Address to where to send the ACK back.
* \return Error code, ERR_OK for no error.
*/
uint8_t RNWK_SendACK(RPHY_PacketDesc *rxPacket, RNWK_ShortAddrType saddr);
/*!
* \brief Puts a payload into the buffer queue to be sent asynchronously.
* \param buf Message buffer with payload.
* \param bufSize Size of message buffer, must be of RNWK_BUFFER_SIZE.
* \param payloadSize Size of the payload in bytes.
* \param dstAddr Destination node address.
* \param flags Packet flags.
*/
uint8_t RNWK_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RNWK_ShortAddrType dstAddr, RPHY_FlagsType flags);
#include "McuShell.h"
uint8_t RNWK_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io);
/*!
* \brief Returns the node network address.
* \return Node short address.
*/
RNWK_ShortAddrType RNWK_GetThisNodeAddr(void);
/*!
* \brief Sets this node own address
* \param addr New address to use
*/
uint8_t RNWK_SetThisNodeAddr(RNWK_ShortAddrType addr);
/*!
* \brief Sniffs and dumps a packet.
* \param packet Data packet.
* \param isTx If either Tx or Rx packet.
*/
void RNWK_SniffPacket(RPHY_PacketDesc *packet, bool isTx);
/*! \brief Initializes the module */
void RNWK_Init(void);
/*! \brief Deinitializes the module */
void RNWK_Deinit(void);
#endif /* McuRNET_CONFIG_IS_ENABLED */
#endif /* RNWK_H_ */

View File

@@ -0,0 +1,49 @@
/**
* \file
* \brief This implements the PHY layer of the network stack.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module is used to process the raw payload packets.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RPHY.h"
#include "RMAC.h"
#include "RMSG.h"
uint8_t RPHY_FlushRxQueue(void) {
return RMSG_FlushRxQueue();
}
uint8_t RPHY_FlushTxQueue(void) {
return RMSG_FlushTxQueue();
}
uint8_t RPHY_GetPayload(RPHY_PacketDesc *packet) {
packet->flags = RPHY_PACKET_FLAGS_NONE;
return RMSG_GetRxMsg(packet->phyData, packet->phySize); /* ERR_OK, ERR_OVERFLOW or ERR_RXEMPTY */
}
uint8_t RPHY_OnPacketRx(RPHY_PacketDesc *packet) {
return RMAC_OnPacketRx(packet); /* pass message up the stack */
}
uint8_t RPHY_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags) {
return RMSG_QueueTxMsg(buf, bufSize, payloadSize, flags);
}
void RPHY_SniffPacket(RPHY_PacketDesc *packet, bool isTx) {
RMAC_SniffPacket(packet, isTx);
}
void RPHY_Deinit(void) {
/* nothing needed */
}
void RPHY_Init(void) {
/* nothing needed */
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,107 @@
/**
* \file
* \brief Radio PHY (Physical Interface)
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This interface is for the PHY (Physical) part of the stack.
*/
#ifndef RPHY_H_
#define RPHY_H_
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
/* payload format is:
* PHY: <flags><size><phy payload>
* MAC: <type><seq#><mac payload>
* NWK: <saddr><dstaddr><nwk payload>
* APP: <type><size><data>
*/
#define RPHY_HEADER_SIZE (2) /* <flags><size> */
#define RPHY_PAYLOAD_SIZE (RNET_CONFIG_TRANSCEIVER_PAYLOAD_SIZE) /* total number of payload bytes */
#define RPHY_BUFFER_SIZE (RPHY_HEADER_SIZE+RPHY_PAYLOAD_SIZE) /* <size><phy payload> */
/* PHY buffer access macros */
#define RPHY_BUF_IDX_FLAGS (0) /* <flags> index */
#define RPHY_BUF_IDX_SIZE (1) /* <size> index */
#define RPHY_BUF_IDX_PAYLOAD (2) /* <phy payload> index */
/* access macros */
#define RPHY_BUF_FLAGS(phy) ((phy)[RPHY_BUF_IDX_FLAGS])
#define RPHY_BUF_SIZE(phy) ((phy)[RPHY_BUF_IDX_SIZE])
#define RPHY_BUF_PAYLOAD_START(phy) ((phy)+RPHY_HEADER_SIZE)
typedef uint8_t RPHY_FlagsType;
/* flag bits inside PacketDesc below */
#define RPHY_PACKET_FLAGS_NONE (0)
/*!< initialization value */
#define RPHY_PACKET_FLAGS_IS_ACK (1<<0)
/*!< valid ACK received */
#define RPHY_PACKET_FLAGS_REQ_ACK (1<<1)
/*!< request acknowledge RNet acknowledge */
#define RPHY_PACKET_FLAGS_POWER_DOWN (1<<2)
/*!< power down transceiver */
#define RPHY_PACKET_FLAGS_NO_ACK (1<<3)
/*!< send package without low-level/shockburst acknowledge */
typedef struct {
RPHY_FlagsType flags;/*!< flags, see RPHY_PACKET_FLAGS_XXXX above */
uint8_t phySize; /*!< size of PHY data buffer */
uint8_t *phyData; /*!< pointer to the PHY data buffer */
uint8_t *rxtx; /*!< pointer into phyData, start of TX/RX data */
} RPHY_PacketDesc;
/*!
* \brief Flushes the Rx queue.
* \return Error code, ERR_OK for everything fine.
*/
uint8_t RPHY_FlushRxQueue(void);
/*!
* \brief Flushes the Tx queue.
* \return Error code, ERR_OK for everything fine.
*/
uint8_t RPHY_FlushTxQueue(void);
/*!
* \brief Function called on Rx of a packet.
* \param packet Pointer to packet
* \return ERR_OK, if everything is fine, error code otherwise.
*/
uint8_t RPHY_OnPacketRx(RPHY_PacketDesc *packet);
/*!
* \brief Returns the PHY payload data.
* \param[out] packet Pointer to packet descriptor.
* \return Error code, ERR_OK if everything is ok, ERR_OVERFLOW if buffer is too small, ERR_.
*/
uint8_t RPHY_GetPayload(RPHY_PacketDesc *packet);
/*!
* \brief Puts a packet into the queue to be sent.
* \param buf Pointer to the packet buffer.
* \param bufSize Size of the payload buffer.
* \param payloadSize Size of payload data.
* \param flags Packet flags.
* \return Error code, ERR_OK for everything fine.
*/
uint8_t RPHY_PutPayload(uint8_t *buf, size_t bufSize, uint8_t payloadSize, RPHY_FlagsType flags);
/*!
* \brief Sniffs and dumps a packet.
* \param packet Data packet.
* \param isTx If either Tx or Rx packet.
*/
void RPHY_SniffPacket(RPHY_PacketDesc *packet, bool isTx);
/*! \brief Initializes the module */
void RPHY_Init(void);
/*! \brief Deinitializes the module */
void RPHY_Deinit(void);
#endif /* McuRNET_CONFIG_IS_ENABLED */
#endif /* RPHY_H_ */

View File

@@ -0,0 +1,45 @@
/**
* \file
* \brief This main init module for the stack.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module is used to simplify stack initialization.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RStack.h"
#include "Radio.h"
#include "RMSG.h"
#include "RPHY.h"
#include "RMAC.h"
#include "RNWK.h"
#include "RStdIO.h"
#include "RApp.h"
void RSTACK_Init(void) {
/*lint -save -e522 function lacks side-effects */
RADIO_Init();
RMSG_Init();
RPHY_Init();
RMAC_Init();
RNWK_Init();
RSTDIO_Init();
RAPP_Init();
/*lint -restore */
}
void RSTACK_Deinit(void) {
/*lint -save -e522 function lacks side-effects */
RAPP_Deinit();
RSTDIO_Deinit();
RNWK_Deinit();
RMAC_Deinit();
RPHY_Deinit();
RMSG_Deinit();
RADIO_Deinit();
/*lint -restore */
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,20 @@
/**
* \file
* \brief Radio Network Stack Main file
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This interface is the common entry point for the stack.
*/
#ifndef RSTACK_H_
#define RSTACK_H_
/*! \brief Stack initialization function */
void RSTACK_Init(void);
/*! \brief Stack de-initialization function */
void RSTACK_Deinit(void);
#endif /* RSTACK_H_ */

View File

@@ -0,0 +1,511 @@
/**
* \file
* \brief Radio/remote Standard I/O module.
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module uses queues for remote/radio standard I/O handling.
*/
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RStdIO.h"
#include "McuRTOS.h"
#include "McuUtility.h"
#include "McuShell.h"
#include "Radio.h"
#include "RMSG.h"
#include "RNWK.h"
#include "RApp.h"
/* three shell queues, one for each channel.
* E.g. the command "radio send stdin help" will place "help" into the RSTDIO_RxStdIn queue, which then will be processed by the shell.
* */
static QueueHandle_t RSTDIO_RxStdInQ, RSTDIO_RxStdOutQ, RSTDIO_RxStdErrQ;
static QueueHandle_t RSTDIO_TxStdInQ, RSTDIO_TxStdOutQ, RSTDIO_TxStdErrQ;
#define RSTDIO_PAYLOAD_SIZE (RNWK_PAYLOAD_SIZE-1/*type*/-1/*size*/) /* data size we can transmit in one message. stdout string will be added */
#define RSTDIO_QUEUE_LENGTH RSTDIO_CONFIG_QUEUE_LENGTH /* items in queue, that's my buffer size */
#define RSTDIO_QUEUE_ITEM_SIZE 1 /* each item is a single character */
#define RSTDIO_QUEUE_TIMEOUT_MS 500 /* timeout for stdio queues */
static RNWK_ShortAddrType RSTDIO_dstAddr; /* destination address */
uint8_t RSTDIO_DefaultShellBuffer[McuShell_DEFAULT_SHELL_BUFFER_SIZE]; /* default buffer which can be used by the application */
void RSTDIO_SetDestinationAddress(RNWK_ShortAddrType addr) {
RSTDIO_dstAddr = addr;
}
/*!
* \brief Returns a queue handle for a Remote Standard I/O type
* \param queueType Type of queue
* \return Queue handle
*/
QueueHandle_t RSTDIO_GetQueueForType(RSTDIO_QueueType queueType) {
switch(queueType) {
case RSTDIO_QUEUE_RX_IN: return RSTDIO_RxStdInQ;
case RSTDIO_QUEUE_RX_OUT: return RSTDIO_RxStdOutQ;
case RSTDIO_QUEUE_RX_ERR: return RSTDIO_RxStdErrQ;
case RSTDIO_QUEUE_TX_IN: return RSTDIO_TxStdInQ;
case RSTDIO_QUEUE_TX_OUT: return RSTDIO_TxStdOutQ;
case RSTDIO_QUEUE_TX_ERR: return RSTDIO_TxStdErrQ;
default: break;
}
return NULL;
}
/*!
* \brief Adds binary data to the queue.
* \param queue Queue to be used
* \param data Pointer to the binary data
* \param dataSize Size of data in bytes
*/
static uint8_t AddToQueue(QueueHandle_t queue, const unsigned char *data, size_t dataSize) {
while(dataSize!=0) {
if (McuRTOS_xQueueSendToBack(queue, data, pdMS_TO_TICKS(RSTDIO_QUEUE_TIMEOUT_MS))!=pdPASS) {
return ERR_FAULT;
}
data++;
dataSize--;
}
return ERR_OK;
}
uint8_t RSTDIO_AddToQueue(RSTDIO_QueueType queueType, const unsigned char *data, size_t dataSize) {
switch(queueType) {
case RSTDIO_QUEUE_RX_IN: return AddToQueue(RSTDIO_RxStdInQ, data, dataSize);
case RSTDIO_QUEUE_RX_OUT: return AddToQueue(RSTDIO_RxStdOutQ, data, dataSize);
case RSTDIO_QUEUE_RX_ERR: return AddToQueue(RSTDIO_RxStdErrQ, data, dataSize);
case RSTDIO_QUEUE_TX_IN: return AddToQueue(RSTDIO_TxStdInQ, data, dataSize);
case RSTDIO_QUEUE_TX_OUT: return AddToQueue(RSTDIO_TxStdOutQ, data, dataSize);
case RSTDIO_QUEUE_TX_ERR: return AddToQueue(RSTDIO_TxStdErrQ, data, dataSize);
default: break;
}
return ERR_FAILED;
}
/*!
* \brief Peeks a character from the queue without removing it.
* \param queue Queue to be used
* \return '\0' if the queue is empty, otherwise it contains the character.
*/
static unsigned short RSTDIO_NofElements(QueueHandle_t queue) {
return (unsigned short)McuRTOS_uxQueueMessagesWaiting(queue);
}
/*!
* \brief Returns the number of elements in the queue
* \param queueType Queue type
* \return Number of elements in the queue, 0 if the queue is not known.
*/
uint8_t RSTDIO_NofInQueue(RSTDIO_QueueType queueType) {
switch(queueType) {
case RSTDIO_QUEUE_RX_IN: return RSTDIO_NofElements(RSTDIO_RxStdInQ);
case RSTDIO_QUEUE_RX_OUT: return RSTDIO_NofElements(RSTDIO_RxStdOutQ);
case RSTDIO_QUEUE_RX_ERR: return RSTDIO_NofElements(RSTDIO_RxStdErrQ);
case RSTDIO_QUEUE_TX_IN: return RSTDIO_NofElements(RSTDIO_TxStdInQ);
case RSTDIO_QUEUE_TX_OUT: return RSTDIO_NofElements(RSTDIO_TxStdOutQ);
case RSTDIO_QUEUE_TX_ERR: return RSTDIO_NofElements(RSTDIO_TxStdErrQ);
default: break;
}
return 0;
}
/*!
* \brief Receives an a message character from the queue, and returns immediately if the queue is empty.
* \return Message character, or '\0' if there was no message.
*/
static unsigned char RSTDIO_ReceiveChar(QueueHandle_t queue) {
unsigned char ch;
portBASE_TYPE res;
res = McuRTOS_xQueueReceive(queue, &ch, 0);
if (res==errQUEUE_EMPTY) {
return '\0';
} else {
return ch;
}
}
/*!
* \brief Returns a character from a queue
* \param queueType Queue type
* \return Character, or zero byte if queue is empty or unknown
*/
uint8_t RSTDIO_ReceiveQueueChar(RSTDIO_QueueType queueType) {
switch(queueType) {
case RSTDIO_QUEUE_RX_IN: return RSTDIO_ReceiveChar(RSTDIO_RxStdInQ);
case RSTDIO_QUEUE_RX_OUT: return RSTDIO_ReceiveChar(RSTDIO_RxStdOutQ);
case RSTDIO_QUEUE_RX_ERR: return RSTDIO_ReceiveChar(RSTDIO_RxStdErrQ);
case RSTDIO_QUEUE_TX_IN: return RSTDIO_ReceiveChar(RSTDIO_TxStdInQ);
case RSTDIO_QUEUE_TX_OUT: return RSTDIO_ReceiveChar(RSTDIO_TxStdOutQ);
case RSTDIO_QUEUE_TX_ERR: return RSTDIO_ReceiveChar(RSTDIO_TxStdErrQ);
default: break;
}
return '\0';
}
uint8_t RSTDIO_HandleStdioRxMessage(RAPP_MSG_Type type, uint8_t size, uint8_t *data, RNWK_ShortAddrType srcAddr, bool *handled, RPHY_PacketDesc *packet) {
(void)srcAddr;
(void)packet;
switch(type) {
case RAPP_MSG_TYPE_STDIN: /* <type><size><data> */
*handled = TRUE;
return RSTDIO_AddToQueue(RSTDIO_QUEUE_RX_IN, data, size);
case RAPP_MSG_TYPE_STDOUT: /* <type><size><data> */
*handled = TRUE;
return RSTDIO_AddToQueue(RSTDIO_QUEUE_RX_OUT, data, size);
case RAPP_MSG_TYPE_STDERR: /* <type><size><data> */
*handled = TRUE;
return RSTDIO_AddToQueue(RSTDIO_QUEUE_RX_ERR, data, size);
default:
break;
} /* switch */
return ERR_OK;
}
/*!
* \brief Flushes the given buffer/queue. The buffer will be sent over the radio.
* \return Error code, ERR_OK for no error.
*/
static uint8_t FlushAndTxQueue(RSTDIO_QueueType queueType, RAPP_MSG_Type msgType) {
unsigned char buf[RAPP_BUFFER_SIZE];
uint8_t i;
uint8_t res = ERR_OK;
uint8_t *p, ch;
p = RAPP_BUF_PAYLOAD_START(buf);
i = 0;
while (i<RAPP_PAYLOAD_SIZE) {
ch = RSTDIO_ReceiveQueueChar(queueType);
if (ch=='\0') { /* queue empty */
break;
}
*p++ = ch;
i++;
}
res = RAPP_PutPayload(buf, sizeof(buf), i, msgType, RSTDIO_dstAddr, RPHY_PACKET_FLAGS_NONE);
if (res!=ERR_OK) {
McuShell_ConstStdIOType *io = McuShell_GetStdio();
io->stdErr('*');
io->stdErr('F');
io->stdErr('A');
io->stdErr('I');
io->stdErr('L');
io->stdErr('*');
io->stdErr('\n');
return res;
}
return res;
}
/*!
* \brief Radio StdIn: sends a character to the wireless communication channel.
* \param ch Character to send
*/
static void RSTDIO_TxStdInSendChar(uint8_t ch) {
(void)RSTDIO_AddToQueue(RSTDIO_QUEUE_TX_IN, &ch, 1);
if (ch=='\n' || RSTDIO_NofInQueue(RSTDIO_QUEUE_TX_IN)>RSTDIO_PAYLOAD_SIZE) { /* can send string over radio */
(void)FlushAndTxQueue(RSTDIO_QUEUE_TX_IN, RAPP_MSG_TYPE_STDIN);
}
}
/*!
* \brief Radio StdOut: sends a character to the wireless communication channel.
* \param ch Character to send
*/
static void RSTDIO_TxStdOut(uint8_t ch) {
(void)RSTDIO_AddToQueue(RSTDIO_QUEUE_TX_OUT, &ch, 1);
if (ch=='\n' || RSTDIO_NofInQueue(RSTDIO_QUEUE_TX_OUT)>RSTDIO_PAYLOAD_SIZE) { /* can send string over radio */
(void)FlushAndTxQueue(RSTDIO_QUEUE_TX_OUT, RAPP_MSG_TYPE_STDOUT);
}
}
/*!
* \brief Radio StdErr: sends a character to the wireless communication channel.
* \param ch Character to send
*/
static void RSTDIO_TxStdErr(uint8_t ch) {
(void)RSTDIO_AddToQueue(RSTDIO_QUEUE_TX_ERR, &ch, sizeof(ch));
if (ch=='\n' || RSTDIO_NofInQueue(RSTDIO_QUEUE_TX_ERR)>RSTDIO_PAYLOAD_SIZE) { /* can send string over radio */
(void)FlushAndTxQueue(RSTDIO_QUEUE_TX_ERR, RAPP_MSG_TYPE_STDERR);
}
}
uint8_t RSTDIO_SendToTxStdio(RSTDIO_QueueType queueType, uint8_t *buf, size_t bufSize) {
if (queueType==RSTDIO_QUEUE_TX_IN) {
while(bufSize!=0) {
RSTDIO_TxStdInSendChar(*buf);
buf++; bufSize--;
}
} else if (queueType==RSTDIO_QUEUE_TX_OUT) {
while(bufSize!=0) {
RSTDIO_TxStdOut(*buf);
buf++; bufSize--;
}
} else if (queueType==RSTDIO_QUEUE_TX_ERR) {
while(bufSize!=0) {
RSTDIO_TxStdErr(*buf);
buf++; bufSize--;
}
} else {
return ERR_FAILED; /* unknown queue? */
}
return ERR_OK;
}
/*!
* \brief Radio StdIn: Reads a character from the StdIn queue and echoes it on the standard shell stdOut
*/
static void RSTDIO_RxStdInReadChar(uint8_t *ch) {
*ch = RSTDIO_ReceiveQueueChar(RSTDIO_QUEUE_RX_IN); /* will return '\0' if queue is empty */
}
/*!
* \brief Checks if we have a character in the stdin queue without removing it.
* \return TRUE if character is present.
*/
static bool RSTDIO_RxStdInKeyPressed(void) {
return (bool)(RSTDIO_NofElements(RSTDIO_RxStdInQ)!=0);
}
McuShell_ConstStdIOType RSTDIO_stdio = {
.stdIn = (McuShell_StdIO_In_FctType)RSTDIO_RxStdInReadChar, /* stdin */
.stdOut = (McuShell_StdIO_OutErr_FctType)RSTDIO_TxStdOut, /* stdout */
.stdErr = (McuShell_StdIO_OutErr_FctType)RSTDIO_TxStdErr, /* stderr */
.keyPressed = RSTDIO_RxStdInKeyPressed, /* if input is not empty */
#if McuShell_CONFIG_ECHO_ENABLED
.echoEnabled = false,
#endif
};
McuShell_ConstStdIOTypePtr RSTDIO_GetStdio(void) {
return &RSTDIO_stdio;
}
/*!
* \brief Called from the application task. This function checks the Radio RX queue and checks if it contains stdio messages.
* If so, it dispatches it to the corresponding shell queues.
*/
void RSTDIO_Print(McuShell_ConstStdIOTypePtr io) {
unsigned char ch;
for(;;) { /* breaks */
ch = RSTDIO_ReceiveChar(RSTDIO_RxStdOutQ);
if(ch=='\0') {
break; /* get out of for loop */
}
io->stdOut(ch); /* output character */
}
for(;;) { /* breaks */
ch = RSTDIO_ReceiveChar(RSTDIO_RxStdErrQ);
if(ch=='\0') {
break; /* get out of for loop */
}
io->stdErr(ch); /* output character */
}
}
unsigned int RSTDIO_AddIntoBuffer(unsigned char *buffer, size_t bufSize) {
unsigned char ch;
unsigned int nofChars = 0;
for(;;) { /* breaks */
ch = RSTDIO_ReceiveChar(RSTDIO_RxStdOutQ);
if(ch=='\0') {
break; /* get out of for loop */
}
McuUtility_chcat(buffer, bufSize, ch);
nofChars++;
}
for(;;) { /* breaks */
ch = RSTDIO_ReceiveChar(RSTDIO_RxStdErrQ);
if(ch=='\0') {
break; /* get out of for loop */
}
McuUtility_chcat(buffer, bufSize, ch);
nofChars++;
}
return nofChars;
}
static void PrintHelp(const McuShell_StdIOType *io) {
McuShell_SendHelpStr((unsigned char*)"rstdio", (unsigned char*)"Group of rstdio commands\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" help|status", (unsigned char*)"Shows help or status\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" daddr 0x<addr>", (unsigned char*)"Set destination node address\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" send (in/out/err)", (unsigned char*)"Send a string to remote stdio\r\n", io->stdOut);
}
static uint8_t PrintStatus(const McuShell_StdIOType *io) {
uint8_t buf[32];
McuShell_SendStatusStr((unsigned char*)"rstdio", (unsigned char*)"\r\n", io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"0x");
#if RNWK_SHORT_ADDR_SIZE==1
McuUtility_strcatNum8Hex(buf, sizeof(buf), RSTDIO_dstAddr);
#else
McuUtility_strcatNum16Hex(buf, sizeof(buf), RSTDIO_dstAddr);
#endif
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStatusStr((unsigned char*)" dest addr", buf, io->stdOut);
McuUtility_Num8uToStr(buf, sizeof(buf), RSTDIO_QUEUE_LENGTH);
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStatusStr((unsigned char*)" queue size", buf, io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"in: ");
McuUtility_strcatNum8u(buf, sizeof(buf), RSTDIO_NofInQueue(RSTDIO_QUEUE_RX_IN));
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)", out: ");
McuUtility_strcatNum8u(buf, sizeof(buf), RSTDIO_NofInQueue(RSTDIO_QUEUE_RX_OUT));
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)", err: ");
McuUtility_strcatNum8u(buf, sizeof(buf), RSTDIO_NofInQueue(RSTDIO_QUEUE_RX_ERR));
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStatusStr((unsigned char*)" Rx queue", buf, io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"in: ");
McuUtility_strcatNum8u(buf, sizeof(buf), RSTDIO_NofInQueue(RSTDIO_QUEUE_TX_IN));
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)", out: ");
McuUtility_strcatNum8u(buf, sizeof(buf), RSTDIO_NofInQueue(RSTDIO_QUEUE_TX_OUT));
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)", err: ");
McuUtility_strcatNum8u(buf, sizeof(buf), RSTDIO_NofInQueue(RSTDIO_QUEUE_TX_ERR));
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStatusStr((unsigned char*)" Tx queue", buf, io->stdOut);
return ERR_OK;
}
uint8_t RSTDIO_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io) {
uint8_t res = ERR_OK;
const uint8_t *p;
uint16_t val16;
if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, (char*)"rstdio help")==0) {
PrintHelp(io);
*handled = TRUE;
} else if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_STATUS)==0 || McuUtility_strcmp((char*)cmd, (char*)"rstdio status")==0) {
*handled = TRUE;
return PrintStatus(io);
} else if (McuUtility_strncmp((char*)cmd, (char*)"rstdio send", sizeof("rstdio send")-1)==0) {
unsigned char buf[McuShell_DEFAULT_SHELL_BUFFER_SIZE];
RSTDIO_QueueType queue;
if (McuUtility_strncmp((char*)cmd, (char*)"rstdio send in", sizeof("rstdio send in")-1)==0) {
queue = RSTDIO_QUEUE_TX_IN;
cmd += sizeof("rstdio send in");
} else if (McuUtility_strncmp((char*)cmd, (char*)"rstdio send out", sizeof("rstdio send out")-1)==0) {
queue = RSTDIO_QUEUE_TX_OUT;
cmd += sizeof("rstdio send out");
} else if (McuUtility_strncmp((char*)cmd, (char*)"rstdio send err", sizeof("rstdio send err")-1)==0) {
queue = RSTDIO_QUEUE_TX_ERR;
cmd += sizeof("rstdio send err");
} else {
return ERR_OK; /* not handled */
}
McuUtility_strcpy(buf, sizeof(buf), cmd);
McuUtility_chcat(buf, sizeof(buf), '\n');
buf[sizeof(buf)-2] = '\n'; /* have a '\n' in any case */
if (RSTDIO_SendToTxStdio(queue, buf, McuUtility_strlen((char*)buf))!=ERR_OK) {
McuShell_SendStr((unsigned char*)"failed!\r\n", io->stdErr);
}
*handled = TRUE;
} else if (McuUtility_strncmp((char*)cmd, (char*)"rstdio daddr", sizeof("rstdio daddr")-1)==0) {
p = cmd + sizeof("rstdio daddr")-1;
*handled = TRUE;
if (McuUtility_ScanHex16uNumber(&p, &val16)==ERR_OK) {
RSTDIO_dstAddr = val16;
} else {
McuShell_SendStr((unsigned char*)"ERR: wrong address\r\n", io->stdErr);
return ERR_FAILED;
}
}
return res;
}
/*! \brief Deinitializes the queue module */
void RSTDIO_Deinit(void) {
McuRTOS_vQueueUnregisterQueue(RSTDIO_RxStdInQ);
McuRTOS_vQueueDelete(RSTDIO_RxStdInQ);
RSTDIO_RxStdInQ = NULL;
McuRTOS_vQueueUnregisterQueue(RSTDIO_RxStdOutQ);
McuRTOS_vQueueDelete(RSTDIO_RxStdOutQ);
RSTDIO_RxStdOutQ = NULL;
McuRTOS_vQueueUnregisterQueue(RSTDIO_RxStdErrQ);
McuRTOS_vQueueDelete(RSTDIO_RxStdErrQ);
RSTDIO_RxStdErrQ = NULL;
McuRTOS_vQueueUnregisterQueue(RSTDIO_TxStdInQ);
McuRTOS_vQueueDelete(RSTDIO_TxStdInQ);
RSTDIO_TxStdInQ = NULL;
McuRTOS_vQueueUnregisterQueue(RSTDIO_TxStdOutQ);
McuRTOS_vQueueDelete(RSTDIO_TxStdOutQ);
RSTDIO_TxStdOutQ = NULL;
McuRTOS_vQueueUnregisterQueue(RSTDIO_TxStdErrQ);
McuRTOS_vQueueDelete(RSTDIO_TxStdErrQ);
RSTDIO_TxStdErrQ = NULL;
}
void RSTDIO_Init(void) {
RSTDIO_SetDestinationAddress(RSTDIO_CONFIG_SETTING_RSTDIO_DEFAULT_DESTINATION_ADDRESS);
RSTDIO_RxStdInQ = McuRTOS_xQueueCreate(RSTDIO_QUEUE_LENGTH, RSTDIO_QUEUE_ITEM_SIZE);
if (RSTDIO_RxStdInQ==NULL) {
for(;;){} /* out of memory? */
}
McuRTOS_vQueueAddToRegistry(RSTDIO_RxStdInQ, "RxStdInQ");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RSTDIO_RxStdInQ, "RxStdInQ");
#endif
RSTDIO_RxStdOutQ = McuRTOS_xQueueCreate(RSTDIO_QUEUE_LENGTH, RSTDIO_QUEUE_ITEM_SIZE);
if (RSTDIO_RxStdOutQ==NULL) {
for(;;){} /* out of memory? */
}
McuRTOS_vQueueAddToRegistry(RSTDIO_RxStdOutQ, "RxStdOutQ");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RSTDIO_RxStdOutQ, "RxStdOutQ");
#endif
RSTDIO_RxStdErrQ = McuRTOS_xQueueCreate(RSTDIO_QUEUE_LENGTH, RSTDIO_QUEUE_ITEM_SIZE);
if (RSTDIO_RxStdErrQ==NULL) {
for(;;){} /* out of memory? */
}
McuRTOS_vQueueAddToRegistry(RSTDIO_RxStdErrQ, "RxStdErrQ");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RSTDIO_RxStdErrQ, "RxStdErrQ");
#endif
RSTDIO_TxStdInQ = McuRTOS_xQueueCreate(RSTDIO_QUEUE_LENGTH, RSTDIO_QUEUE_ITEM_SIZE);
if (RSTDIO_TxStdInQ==NULL) {
for(;;){} /* out of memory? */
}
McuRTOS_vQueueAddToRegistry(RSTDIO_TxStdInQ, "TxStdInQ");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RSTDIO_TxStdInQ, "TxStdInQ");
#endif
RSTDIO_TxStdOutQ = McuRTOS_xQueueCreate(RSTDIO_QUEUE_LENGTH, RSTDIO_QUEUE_ITEM_SIZE);
if (RSTDIO_TxStdOutQ==NULL) {
for(;;){} /* out of memory? */
}
McuRTOS_vQueueAddToRegistry(RSTDIO_TxStdOutQ , "TxStdOutQ");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RSTDIO_TxStdOutQ, "TxStdOutQ");
#endif
RSTDIO_TxStdErrQ = McuRTOS_xQueueCreate(RSTDIO_QUEUE_LENGTH, RSTDIO_QUEUE_ITEM_SIZE);
if (RSTDIO_TxStdErrQ==NULL) {
for(;;){} /* out of memory? */
}
McuRTOS_vQueueAddToRegistry(RSTDIO_TxStdErrQ , "TxStdErrQ");
#if configUSE_TRACE_HOOKS
vTraceSetQueueName(RSTDIO_TxStdErrQ, "TxStdErrQ");
#endif
}
#endif /* McuRNET_CONFIG_IS_ENABLED */

View File

@@ -0,0 +1,133 @@
/**
* \file
* \brief This is the interface of the remote/radio standard I/O module
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module is used for radio/remote stdio.
*/
#ifndef RSTDIO_C_
#define RSTDIO_C_
#include "McuRNetConfig.h"
#if McuRNET_CONFIG_IS_ENABLED
#include "RApp.h"
#include "RPHY.h"
#include "RNWK.h"
#include "McuShell.h"
#include "McuRTOS.h"
typedef enum RSTDIO_QueueType {
/* Rx stdio queues: */
RSTDIO_QUEUE_RX_IN,
RSTDIO_QUEUE_RX_OUT,
RSTDIO_QUEUE_RX_ERR,
/* Tx stdio queues: */
RSTDIO_QUEUE_TX_IN,
RSTDIO_QUEUE_TX_OUT,
RSTDIO_QUEUE_TX_ERR
} RSTDIO_QueueType;
extern uint8_t RSTDIO_DefaultShellBuffer[McuShell_DEFAULT_SHELL_BUFFER_SIZE]; /* default buffer which can be used by the application */
extern McuShell_ConstStdIOType RSTDIO_stdio; /* default standard I/O */
#define RSTDIO_PARSE_COMMAND_ENABLED 1 /* set to 1 if method ParseCommand() is present, 0 otherwise */
/*!
* \brief Shell parser routine.
* \param cmd Pointer to command line string.
* \param handled Pointer to status if command has been handled. Set to TRUE if command was understood.
* \param io Pointer to stdio handle
* \return Error code, ERR_OK if everything was ok.
*/
uint8_t RSTDIO_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io);
/*!
* \brief Returns a queue handle for a Remote Standard I/O type
* \param queueType Type of queue
* \return Queue handle
*/
QueueHandle_t RSTDIO_GetQueueForType(RSTDIO_QueueType queueType);
/*!
* \brief Returns the number of elements in the queue
* \param queueType Queue type
* \return Number of elements in the queue, 0 if the queue is not known.
*/
uint8_t RSTDIO_NofInQueue(RSTDIO_QueueType queueType);
/*!
* \brief Returns a character from a queue
* \param queueType Queue type
* \return Character, or zero byte if queue is empty or unknown
*/
uint8_t RSTDIO_ReceiveQueueChar(RSTDIO_QueueType queueType);
/*!
* \brief Sends a message to a tx stdio queues and sends it if queue is full or has \n at the end
* \param queueType Which stdio queue to use
* \param buf Data buffer.
* \param bufSize Size of data buffer.
* \return Error code
*/
uint8_t RSTDIO_SendToTxStdio(RSTDIO_QueueType queueType, uint8_t *buf, size_t bufSize);
/*!
* \brief Adds a message to a tx queues without sending it
* \param queueType Which stdio queue to use
* \param buf Data buffer.
* \param bufSize Size of data buffer.
* \return Error code
*/
uint8_t RSTDIO_AddToQueue(RSTDIO_QueueType queueType, const unsigned char *data, size_t dataSize);
/*!
* \brief returns the Standard I/O hander for the remote Rx channel
* \return Standard I/O handler with stdin, stdout and stderr
*/
McuShell_ConstStdIOTypePtr RSTDIO_GetStdio(void);
/*!
* \brief Message handler for StdIO messages sent over the radio
* \param type Message type
* \param Size of the payload data
* \param data Payload data
* \param srcAddr Address of node who has sent the message
* \param[out] handled Message handler sets this to TRUE if message was handled
* \param packet Message data packet data
*/
uint8_t RSTDIO_HandleStdioRxMessage(RAPP_MSG_Type type, uint8_t size, uint8_t *data, RNWK_ShortAddrType srcAddr, bool *handled, RPHY_PacketDesc *packet);
/*!
* \brief Call this routines periodically. It will parse incoming remote messages and will dispatch them between stdin, stdout and stderr.
* \param io Standard I/O handle to be used for printing
*/
void RSTDIO_Print(McuShell_ConstStdIOTypePtr io);
/*!
* \brief Same as RSTDIO_Print(), but *adds* the input (in, err) into a buffer.
* \param buffer Buffer to be used
* \param bufSize Size of the buffer in bytes
* \return Number of characters added to buffer
*/
unsigned int RSTDIO_AddIntoBuffer(unsigned char *buffer, size_t bufSize);
/*!
* \brief Sets the destination address to be used for remote standard I/O
* \param addr Address to be used
*/
void RSTDIO_SetDestinationAddress(RNWK_ShortAddrType addr);
/*! \brief Initializes the module */
void RSTDIO_Init(void);
/*! \brief Deinitializes the module */
void RSTDIO_Deinit(void);
#endif /* McuRNET_CONFIG_IS_ENABLED */
#endif /* RSTDIO_C_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
/**
* \file
* \brief This is the interface to the Nordic Semiconductor nRF24L01+
* \author (c) 2013-2019 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module deals with the low level interface of the transceiver.
*/
#ifndef RADIO_H_
#define RADIO_H_
#include "McuRNetConfig.h"
/* direct task notification bits */
#define RADIO_FLAG_INTERRUPT (1<<0) /* transceiver interrupt */
#define RADIO_FLAG_TX_REQUEST (1<<1) /* request to send data using the Tx queue */
#define RADIO_FLAG_REQUEST_INIT (1<<2) /* request to re-initialize the radio */
void RADIO_Notify(uint32_t flags);
void RADIO_NotifyFromInterrupt(uint32_t flags, BaseType_t *pxHigherPriorityTaskWoken);
#include "McuShell.h"
/*!
* \brief Parses a command
* \param cmd Command string to be parsed
* \param handled Sets this variable to TRUE if command was handled
* \param io I/O stream to be used for input/output
* \return Error code, ERR_OK if everything was fine
*/
uint8_t RADIO_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io);
/*!
* \brief Set the radio communication channel
* \param channel New channel number.
* \return Error code, ERR_OK if everything is fine.
*/
uint8_t RADIO_SetChannel(uint8_t channel);
/*!
* \brief Determine if the radio transceiver is in a good shape. Radio transceiver could be affected by voltage drop.
* \return ERR_OK
*/
uint8_t RADIO_IsSane(void);
/*!
* \brief Radio power-on initialization.
* \return Error code, ERR_OK if everything is ok.
*/
uint8_t RADIO_PowerUp(void);
/*!
* \brief Function to determine if we could power down the radio.
* \return TRUE if there is no transmission pending so we can power down the radio.
*/
bool RADIO_CanDoPowerDown(uint32_t notifcationValue);
/*!
* \brief Power down the radio.
* \return Error code, ERR_OK if everything is ok.
*/
uint8_t RADIO_PowerDown(void);
/*!
* \brief Processes the radio state machine. Needs to be called frequently from the application.
* \param notifcationValue Direct Task Notification bits
* \return Error code, ERR_OK for no failure.
*/
void RADIO_Process(void);
/*!
* \brief Flushes the internal radio queues.
* \return Error code, ERR_OK for no failure.
*/
uint8_t RADIO_FlushQueues(void);
/*! \brief Radio transceiver initialization */
void RADIO_Init(void);
/*! \brief Radio transceiver de-initialization */
void RADIO_Deinit(void);
#endif /* RADIO_H_ */

View File

@@ -0,0 +1,18 @@
/**
* \file
* \brief This is the interface to the Nordic Semiconductor nRF24L01+
* \author (c) 2013-2014 Erich Styger, http://mcuoneclipse.com/
* \note MIT License (http://opensource.org/licenses/mit-license.html), see 'RNet_License.txt'
*
* This module deals with the low level interface of the transceiver.
*/
#ifndef RADIO_NRF24_H_
#define RADIO_NRF24_H_
#include "McuRNetConfig.h"
#include "Radio.h"
void RADIO_OnInterrupt(void);
#endif /* RADIO_NRF24_H_ */

View File

@@ -0,0 +1,4 @@
readme.txt
----------
'Remote Radio' (RNet) stack using the Nordic nRF24L01+ transceiver.