You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
7.1 KiB
C
196 lines
7.1 KiB
C
/***************************************************************************//**
|
|
* @file
|
|
* @brief This is the states machine for the base test application. It handles
|
|
* transmit, receive, and various debug modes.
|
|
*******************************************************************************
|
|
* # License
|
|
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
|
|
*******************************************************************************
|
|
*
|
|
* SPDX-License-Identifier: Zlib
|
|
*
|
|
* The licensor of this software is Silicon Laboratories Inc.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event will the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software
|
|
* in a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "rail.h"
|
|
#include "response_print.h"
|
|
#include "app_common.h"
|
|
|
|
// At any given time, at least one of (currAppMode, prevAppMode)
|
|
// should be NONE, due to the way that setAppModeInternal works
|
|
volatile char nextCommandBuf[16];
|
|
volatile char *nextCommand;
|
|
volatile bool enableMode = true;
|
|
volatile AppMode_t nextAppMode = NONE;
|
|
volatile AppMode_t currAppMode = NONE;
|
|
volatile AppMode_t prevAppMode = NONE;
|
|
volatile bool transitionPend = false;
|
|
RAIL_TxOptions_t antOptions = RAIL_TX_OPTIONS_DEFAULT;
|
|
RAIL_StreamMode_t streamMode = RAIL_STREAM_PN9_STREAM;
|
|
|
|
AppMode_t currentAppMode()
|
|
{
|
|
return currAppMode;
|
|
}
|
|
|
|
AppMode_t previousAppMode()
|
|
{
|
|
return prevAppMode;
|
|
}
|
|
|
|
void enableAppMode(AppMode_t next, bool enable, char *command)
|
|
{
|
|
// Should disable current mode instead of enabling NONE
|
|
if (!transitionPend && (next != NONE)) {
|
|
transitionPend = true;
|
|
nextAppMode = next;
|
|
enableMode = enable;
|
|
if (command == NULL) {
|
|
nextCommand = (logLevel & ASYNC_RESPONSE) ? "appMode" : NULL;
|
|
} else {
|
|
memcpy((char *)&nextCommandBuf[0], command, sizeof(nextCommandBuf));
|
|
nextCommand = &nextCommandBuf[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *streamModeNames(RAIL_StreamMode_t streamMode)
|
|
{
|
|
char *streamModes[] = { "Tone", "PN9", "10Stream" };
|
|
return streamModes[streamMode];
|
|
}
|
|
|
|
const char *appModeNames(AppMode_t appMode)
|
|
{
|
|
char *appModes[] = { "None", "Stream", "Tone", "ContinuousTx", "DirectMode",
|
|
"PacketTx", "ScheduledTx", "SchTxAfterRx", "RxOverflow",
|
|
"TxUnderflow", "TxCancel", "RfSense", "PER", "BER",
|
|
"ScheduledRx" };
|
|
return appModes[appMode];
|
|
}
|
|
// Has the logic for disabling and enabling AppMode
|
|
// Note that at least one of (nextAppMode, currAppMode) should be NONE,
|
|
// due to the way we handling AppMode changing
|
|
static void transitionAppMode(AppMode_t nextAppMode)
|
|
{
|
|
if (currAppMode == NONE && nextAppMode != TX_SCHEDULED) {
|
|
RAIL_CancelTimer(railHandle);
|
|
} else if (currAppMode == TX_STREAM) {
|
|
RAIL_StopTxStream(railHandle);
|
|
} else if (currAppMode == DIRECT) {
|
|
RAIL_EnableDirectMode(railHandle, false);
|
|
} else if (currAppMode == TX_CONTINUOUS || currAppMode == TX_N_PACKETS
|
|
|| currAppMode == TX_SCHEDULED || currAppMode == TX_UNDERFLOW
|
|
|| currAppMode == TX_CANCEL) {
|
|
// Disable timer just in case
|
|
RAIL_CancelTimer(railHandle);
|
|
txCount = 0;
|
|
pendFinishTxSequence();
|
|
} else if (currAppMode == RF_SENSE) {
|
|
(void) RAIL_StartRfSense(railHandle, RAIL_RFSENSE_OFF, 0, NULL);
|
|
} else if (currAppMode == PER) {
|
|
RAIL_CancelTimer(railHandle);
|
|
} else if (currAppMode == BER) {
|
|
RAIL_Idle(railHandle, RAIL_IDLE_ABORT, false);
|
|
}
|
|
|
|
if (nextAppMode == TX_STREAM) {
|
|
RAIL_StartTxStreamAlt(railHandle, channel, streamMode, antOptions);
|
|
} else if (nextAppMode == DIRECT) {
|
|
RAIL_EnableDirectMode(railHandle, true);
|
|
} else if (nextAppMode == TX_CONTINUOUS || nextAppMode == TX_N_PACKETS) {
|
|
pendPacketTx();
|
|
} else if (nextAppMode == TX_SCHEDULED || nextAppMode == TX_CANCEL) {
|
|
txCount = 1;
|
|
pendPacketTx();
|
|
} else if (nextAppMode == SCHTX_AFTER_RX || nextAppMode == RX_OVERFLOW) {
|
|
RAIL_StartRx(railHandle, channel, NULL);
|
|
}
|
|
prevAppMode = currAppMode;
|
|
currAppMode = nextAppMode;
|
|
}
|
|
|
|
// This has the rules of when we are allowed to change the AppMode, along
|
|
// with the printouts that should happen when a AppMode change happens
|
|
static void setAppModeInternal(void)
|
|
{
|
|
AppMode_t next = enableMode ? nextAppMode : NONE;
|
|
char *paramNextCommand = (char *)nextCommand;
|
|
AppMode_t paramNextAppMode = nextAppMode;
|
|
AppMode_t paramCurrAppMode = currAppMode;
|
|
bool paramEnableMode = enableMode;
|
|
// TX_STREAM is special-cased to let one switch from one stream mode to
|
|
// another (or the same) without having to first disable the mode.
|
|
if ((paramCurrAppMode == paramNextAppMode)
|
|
&& paramEnableMode
|
|
&& (paramNextAppMode != TX_STREAM)) {
|
|
if (paramNextCommand) {
|
|
responsePrint(paramNextCommand, "%s:Enabled", appModeNames(next));
|
|
}
|
|
} else if (((paramCurrAppMode == paramNextAppMode)
|
|
&& (!paramEnableMode || (paramNextAppMode == TX_STREAM)))
|
|
|| ((paramCurrAppMode == NONE) && paramEnableMode)) {
|
|
if (paramNextCommand) {
|
|
if (next == TX_STREAM) {
|
|
if (paramCurrAppMode == TX_STREAM) {
|
|
responsePrint(paramNextCommand,
|
|
"%s:Enabled,StreamMode:%s,Time:%u",
|
|
appModeNames(next),
|
|
streamModeNames(streamMode),
|
|
RAIL_GetTime());
|
|
} else {
|
|
responsePrint(paramNextCommand,
|
|
"%s:Enabled,%s:Disabled,StreamMode:%s,Time:%u",
|
|
appModeNames(next),
|
|
appModeNames(paramCurrAppMode),
|
|
streamModeNames(streamMode),
|
|
RAIL_GetTime());
|
|
}
|
|
} else {
|
|
responsePrint(paramNextCommand,
|
|
"%s:Enabled,%s:Disabled,Time:%u",
|
|
appModeNames(next),
|
|
appModeNames(paramCurrAppMode),
|
|
RAIL_GetTime());
|
|
}
|
|
}
|
|
transitionAppMode(next);
|
|
} else { // Ignore mode change request
|
|
if (paramNextCommand) {
|
|
responsePrintError(paramNextCommand, 1, "Can't %s %s during %s",
|
|
paramEnableMode ? "enable" : "disable",
|
|
appModeNames(paramNextAppMode), appModeNames(paramCurrAppMode));
|
|
}
|
|
}
|
|
}
|
|
|
|
// This should be called from a main loop, to update the AppMode
|
|
void changeAppModeIfPending()
|
|
{
|
|
if (transitionPend) {
|
|
transitionPend = false;
|
|
setAppModeInternal();
|
|
}
|
|
}
|