[diag] add power calibration related diag commands (#8584)

he power calibration is supported by OT, this commit adds diag
commands that are used to measure the mapping between the actual power
and raw power settings, show the platform used power settings table.
1. Add "diag powersettings" to show the platform currently used power
   settings table.
2. Add "diag rawpowersetting" to make the platform to use the given
   raw power settings to transmit frames.
3. Add "diag cw" to transmit the continuous carrier wave.
This commit is contained in:
Zhanglong Xia
2023-01-23 12:55:48 -08:00
committed by GitHub
parent 65a8d520b1
commit 03c98e08eb
12 changed files with 741 additions and 17 deletions
+52
View File
@@ -55,6 +55,8 @@ enum
static otGpioMode sGpioMode = OT_GPIO_MODE_INPUT;
static bool sGpioValue = false;
static uint8_t sRawPowerSetting[OPENTHREAD_CONFIG_POWER_CALIBRATION_RAW_POWER_SETTING_SIZE];
static uint16_t sRawPowerSettingLength = 0;
void otPlatDiagModeSet(bool aMode) { sDiagMode = aMode; }
@@ -116,4 +118,54 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
exit:
return error;
}
otError otPlatDiagRadioSetRawPowerSetting(otInstance *aInstance,
const uint8_t *aRawPowerSetting,
uint16_t aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
otError error = OT_ERROR_NONE;
otEXPECT_ACTION((aRawPowerSetting != NULL) && (aRawPowerSettingLength <= sizeof(sRawPowerSetting)),
error = OT_ERROR_INVALID_ARGS);
memcpy(sRawPowerSetting, aRawPowerSetting, aRawPowerSettingLength);
sRawPowerSettingLength = aRawPowerSettingLength;
exit:
return error;
}
otError otPlatDiagRadioGetRawPowerSetting(otInstance *aInstance,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
otError error = OT_ERROR_NONE;
otEXPECT_ACTION((aRawPowerSetting != NULL) && (aRawPowerSettingLength != NULL), error = OT_ERROR_INVALID_ARGS);
otEXPECT_ACTION((sRawPowerSettingLength != 0), error = OT_ERROR_NOT_FOUND);
otEXPECT_ACTION((sRawPowerSettingLength <= *aRawPowerSettingLength), error = OT_ERROR_INVALID_ARGS);
memcpy(aRawPowerSetting, sRawPowerSetting, sRawPowerSettingLength);
*aRawPowerSettingLength = sRawPowerSettingLength;
exit:
return error;
}
otError otPlatDiagRadioRawPowerSettingEnable(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
return OT_ERROR_NONE;
}
otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
return OT_ERROR_NONE;
}
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (278)
#define OPENTHREAD_API_VERSION (279)
/**
* @addtogroup api-instance
+85
View File
@@ -200,6 +200,91 @@ otError otPlatDiagGpioSetMode(uint32_t aGpio, otGpioMode aMode);
*/
otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode);
/**
* Set the radio raw power setting for diagnostics module.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aRawPowerSetting A pointer to the raw power setting byte array.
* @param[in] aRawPowerSettingLength The length of the @p aRawPowerSetting.
*
* @retval OT_ERROR_NONE Successfully set the raw power setting.
* @retval OT_ERROR_INVALID_ARGS The @p aRawPowerSetting is NULL or the @p aRawPowerSettingLength is too long.
* @retval OT_ERROR_NOT_IMPLEMENTED This method is not implemented.
*
*/
otError otPlatDiagRadioSetRawPowerSetting(otInstance *aInstance,
const uint8_t *aRawPowerSetting,
uint16_t aRawPowerSettingLength);
/**
* Get the radio raw power setting for diagnostics module.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[out] aRawPowerSetting A pointer to the raw power setting byte array.
* @param[in,out] aRawPowerSettingLength On input, a pointer to the size of @p aRawPowerSetting.
* On output, a pointer to the length of the raw power setting data.
*
* @retval OT_ERROR_NONE Successfully set the raw power setting.
* @retval OT_ERROR_INVALID_ARGS The @p aRawPowerSetting or @p aRawPowerSettingLength is NULL or
* @aRawPowerSettingLength is too short.
* @retval OT_ERROR_NOT_FOUND The raw power setting is not set.
* @retval OT_ERROR_NOT_IMPLEMENTED This method is not implemented.
*
*/
otError otPlatDiagRadioGetRawPowerSetting(otInstance *aInstance,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength);
/**
* Enable/disable the platform layer to use the raw power setting set by `otPlatDiagRadioSetRawPowerSetting()`.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aEnable TRUE to enable or FALSE to disable the raw power setting.
*
* @retval OT_ERROR_NONE Successfully enabled/disabled the raw power setting.
* @retval OT_ERROR_NOT_IMPLEMENTED This method is not implemented.
*
*/
otError otPlatDiagRadioRawPowerSettingEnable(otInstance *aInstance, bool aEnable);
/**
* Start/stop the platform layer to transmit continuous carrier wave.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aEnable TRUE to enable or FALSE to disable the platform layer to transmit continuous carrier wave.
*
* @retval OT_ERROR_NONE Successfully enabled/disabled .
* @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state.
* @retval OT_ERROR_NOT_IMPLEMENTED This method is not implemented.
*
*/
otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable);
/**
* Get the power settings for the given channel.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aChannel The radio channel.
* @param[out] aTargetPower The target power in 0.01 dBm.
* @param[out] aActualPower The actual power in 0.01 dBm.
* @param[out] aRawPowerSetting A pointer to the raw power setting byte array.
* @param[in,out] aRawPowerSettingLength On input, a pointer to the size of @p aRawPowerSetting.
* On output, a pointer to the length of the raw power setting data.
*
* @retval OT_ERROR_NONE Successfully got the target power.
* @retval OT_ERROR_INVALID_ARGS The @p aChannel is invalid, @aTargetPower, @p aActualPower, @p aRawPowerSetting or
* @p aRawPowerSettingLength is NULL or @aRawPowerSettingLength is too short.
* @retval OT_ERROR_NOT_FOUND The power settings for the @p aChannel was not found.
* @retval OT_ERROR_NOT_IMPLEMENTED This method is not implemented.
*
*/
otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
uint8_t aChannel,
int16_t *aTargetPower,
int16_t *aActualPower,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength);
/**
* @}
*
+87
View File
@@ -9,10 +9,13 @@ The diagnostics module supports common diagnostics features that are listed belo
- [diag](#diag)
- [diag start](#diag-start)
- [diag channel](#diag-channel)
- [diag cw](#diag-cw-start)
- [diag power](#diag-power)
- [diag powersettings](#diag-powersettings)
- [diag send](#diag-send-packets-length)
- [diag repeat](#diag-repeat-delay-length)
- [diag radio](#diag-radio-sleep)
- [diag rawpowersetting](#diag-rawpowersetting)
- [diag stats](#diag-stats)
- [diag gpio](#diag-gpio-get-gpio)
- [diag stop](#diag-stop)
@@ -55,6 +58,24 @@ set channel to 11
status 0x00
```
### diag cw start
Start transmitting continuous carrier wave.
```bash
> diag cw start
Done
```
### diag cw stop
Stop transmitting continuous carrier wave.
```bash
> diag cw stop
Done
```
### diag power
Get the tx power value(dBm) for diagnostics module.
@@ -74,6 +95,35 @@ set tx power to -10 dBm
status 0x00
```
### diag powersettings
Show the currently used power settings table.
- Note: The unit of `TargetPower` and `ActualPower` is 0.01dBm.
```bash
> diag powersettings
| StartCh | EndCh | TargetPower | ActualPower | RawPowerSetting |
+---------+-------+-------------+-------------+-----------------+
| 11 | 14 | 1700 | 1000 | 223344 |
| 15 | 24 | 2000 | 1900 | 112233 |
| 25 | 25 | 1600 | 1000 | 223344 |
| 26 | 26 | 1600 | 1500 | 334455 |
Done
```
### diag powersettings \<channel\>
Show the currently used power settings for the given channel.
```bash
> diag powersettings 11
TargetPower(0.01dBm): 1700
ActualPower(0.01dBm): 1000
RawPowerSetting: 223344
Done
```
### diag send \<packets\> \<length\>
Transmit a fixed number of packets with fixed length.
@@ -137,6 +187,43 @@ Return the state of the radio.
sleep
```
### diag rawpowersetting
Show the raw power setting for diagnostics module.
```bash
> diag rawpowersetting
112233
Done
```
### diag rawpowersetting \<settings\>
Set the raw power setting for diagnostics module.
```bash
> diag rawpowersetting 112233
Done
```
### diag rawpowersetting enable
Enable the platform layer to use the value set by the command `diag rawpowersetting \<settings\>`.
```bash
> diag rawpowersetting enable
Done
```
### diag rawpowersetting disable
Disable the platform layer to use the value set by the command `diag rawpowersetting \<settings\>`.
```bash
> diag rawpowersetting disable
Done
```
### diag stats
Print statistics during diagnostics mode.
+206 -5
View File
@@ -70,8 +70,15 @@ namespace FactoryDiags {
#if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
const struct Diags::Command Diags::sCommands[] = {
{"channel", &Diags::ProcessChannel}, {"echo", &Diags::ProcessEcho}, {"gpio", &Diags::ProcessGpio},
{"power", &Diags::ProcessPower}, {"start", &Diags::ProcessStart}, {"stop", &Diags::ProcessStop},
{"channel", &Diags::ProcessChannel},
{"cw", &Diags::ProcessContinuousWave},
{"echo", &Diags::ProcessEcho},
{"gpio", &Diags::ProcessGpio},
{"power", &Diags::ProcessPower},
{"powersettings", &Diags::ProcessPowerSettings},
{"rawpowersetting", &Diags::ProcessRawPowerSetting},
{"start", &Diags::ProcessStart},
{"stop", &Diags::ProcessStop},
};
Diags::Diags(Instance &aInstance)
@@ -178,9 +185,18 @@ extern "C" void otPlatDiagAlarmFired(otInstance *aInstance) { otPlatDiagAlarmCal
#else // OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
// For OPENTHREAD_FTD, OPENTHREAD_MTD, OPENTHREAD_RADIO_CLI
const struct Diags::Command Diags::sCommands[] = {
{"channel", &Diags::ProcessChannel}, {"gpio", &Diags::ProcessGpio}, {"power", &Diags::ProcessPower},
{"radio", &Diags::ProcessRadio}, {"repeat", &Diags::ProcessRepeat}, {"send", &Diags::ProcessSend},
{"start", &Diags::ProcessStart}, {"stats", &Diags::ProcessStats}, {"stop", &Diags::ProcessStop},
{"channel", &Diags::ProcessChannel},
{"cw", &Diags::ProcessContinuousWave},
{"gpio", &Diags::ProcessGpio},
{"power", &Diags::ProcessPower},
{"powersettings", &Diags::ProcessPowerSettings},
{"rawpowersetting", &Diags::ProcessRawPowerSetting},
{"radio", &Diags::ProcessRadio},
{"repeat", &Diags::ProcessRepeat},
{"send", &Diags::ProcessSend},
{"start", &Diags::ProcessStart},
{"stats", &Diags::ProcessStats},
{"stop", &Diags::ProcessStop},
};
Diags::Diags(Instance &aInstance)
@@ -537,6 +553,137 @@ exit:
#endif // OPENTHREAD_RADIO
Error Diags::ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
Error error = kErrorInvalidArgs;
VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
VerifyOrExit(aArgsLength > 0, error = kErrorInvalidArgs);
if (strcmp(aArgs[0], "start") == 0)
{
SuccessOrExit(error = otPlatDiagRadioTransmitCarrier(&GetInstance(), true));
}
else if (strcmp(aArgs[0], "stop") == 0)
{
SuccessOrExit(error = otPlatDiagRadioTransmitCarrier(&GetInstance(), false));
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
return error;
}
Error Diags::GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings)
{
aPowerSettings.mRawPowerSetting.mLength = RawPowerSetting::kMaxDataSize;
return otPlatDiagRadioGetPowerSettings(&GetInstance(), aChannel, &aPowerSettings.mTargetPower,
&aPowerSettings.mActualPower, aPowerSettings.mRawPowerSetting.mData,
&aPowerSettings.mRawPowerSetting.mLength);
}
Error Diags::ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
Error error = kErrorInvalidArgs;
uint8_t channel;
PowerSettings powerSettings;
VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
if (aArgsLength == 0)
{
bool isPrePowerSettingsValid = false;
uint8_t preChannel = 0;
PowerSettings prePowerSettings;
int n;
n = snprintf(aOutput, aOutputMaxLen,
"| StartCh | EndCh | TargetPower | ActualPower | RawPowerSetting |\r\n"
"+---------+-------+-------------+-------------+-----------------+\r\n");
VerifyOrExit((n > 0) && (n < static_cast<int>(aOutputMaxLen)), error = kErrorNoBufs);
aOutput += n;
aOutputMaxLen -= static_cast<size_t>(n);
for (channel = Radio::kChannelMin; channel <= Radio::kChannelMax + 1; channel++)
{
error = (channel == Radio::kChannelMax + 1) ? kErrorNotFound : GetPowerSettings(channel, powerSettings);
if (isPrePowerSettingsValid && ((powerSettings != prePowerSettings) || (error != kErrorNone)))
{
n = snprintf(aOutput, aOutputMaxLen, "| %7u | %5u | %11d | %11d | %15s |\r\n", preChannel, channel - 1,
prePowerSettings.mTargetPower, prePowerSettings.mActualPower,
prePowerSettings.mRawPowerSetting.ToString().AsCString());
VerifyOrExit((n > 0) && (n < static_cast<int>(aOutputMaxLen)), error = kErrorNoBufs);
aOutput += n;
aOutputMaxLen -= static_cast<size_t>(n);
isPrePowerSettingsValid = false;
}
if ((error == kErrorNone) && (!isPrePowerSettingsValid))
{
preChannel = channel;
prePowerSettings = powerSettings;
isPrePowerSettingsValid = true;
}
}
error = kErrorNone;
}
else if (aArgsLength == 1)
{
SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint8(aArgs[0], channel));
VerifyOrExit(channel >= Radio::kChannelMin && channel <= Radio::kChannelMax, error = kErrorInvalidArgs);
SuccessOrExit(error = GetPowerSettings(channel, powerSettings));
snprintf(aOutput, aOutputMaxLen,
"TargetPower(0.01dBm): %d\r\nActualPower(0.01dBm): %d\r\nRawPowerSetting: %s\r\n",
powerSettings.mTargetPower, powerSettings.mActualPower,
powerSettings.mRawPowerSetting.ToString().AsCString());
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
return error;
}
Error Diags::GetRawPowerSetting(RawPowerSetting &aRawPowerSetting)
{
aRawPowerSetting.mLength = RawPowerSetting::kMaxDataSize;
return otPlatDiagRadioGetRawPowerSetting(&GetInstance(), aRawPowerSetting.mData, &aRawPowerSetting.mLength);
}
Error Diags::ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
Error error = kErrorInvalidArgs;
RawPowerSetting setting;
VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
if (aArgsLength == 0)
{
SuccessOrExit(error = GetRawPowerSetting(setting));
snprintf(aOutput, aOutputMaxLen, "%s\r\n", setting.ToString().AsCString());
}
else if (strcmp(aArgs[0], "enable") == 0)
{
SuccessOrExit(error = otPlatDiagRadioRawPowerSettingEnable(&GetInstance(), true));
}
else if (strcmp(aArgs[0], "disable") == 0)
{
SuccessOrExit(error = otPlatDiagRadioRawPowerSettingEnable(&GetInstance(), false));
}
else
{
setting.mLength = RawPowerSetting::kMaxDataSize;
SuccessOrExit(error = Utils::CmdLineParser::ParseAsHexString(aArgs[0], setting.mLength, setting.mData));
SuccessOrExit(error = otPlatDiagRadioSetRawPowerSetting(&GetInstance(), setting.mData, setting.mLength));
}
exit:
AppendErrorResult(error, aOutput, aOutputMaxLen);
return error;
}
Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
Error error = kErrorInvalidArgs;
@@ -755,4 +902,58 @@ OT_TOOL_WEAK otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatDiagRadioSetRawPowerSetting(otInstance *aInstance,
const uint8_t *aRawPowerSetting,
uint16_t aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aRawPowerSetting);
OT_UNUSED_VARIABLE(aRawPowerSettingLength);
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatDiagRadioGetRawPowerSetting(otInstance *aInstance,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aRawPowerSetting);
OT_UNUSED_VARIABLE(aRawPowerSettingLength);
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatDiagRadioRawPowerSettingEnable(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
uint8_t aChannel,
int16_t *aTargetPower,
int16_t *aActualPower,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aChannel);
OT_UNUSED_VARIABLE(aTargetPower);
OT_UNUSED_VARIABLE(aActualPower);
OT_UNUSED_VARIABLE(aRawPowerSetting);
OT_UNUSED_VARIABLE(aRawPowerSettingLength);
return OT_ERROR_NOT_IMPLEMENTED;
}
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
+44
View File
@@ -45,6 +45,7 @@
#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/string.hpp"
namespace ot {
namespace FactoryDiags {
@@ -142,12 +143,52 @@ private:
uint8_t mLastLqi;
};
struct RawPowerSetting
{
static constexpr uint16_t kMaxDataSize = OPENTHREAD_CONFIG_POWER_CALIBRATION_RAW_POWER_SETTING_SIZE;
static constexpr uint16_t kInfoStringSize = kMaxDataSize * 2 + 1;
typedef String<kInfoStringSize> InfoString;
InfoString ToString(void) const
{
InfoString string;
string.AppendHexBytes(mData, mLength);
return string;
}
bool operator!=(const RawPowerSetting &aOther) const
{
return (mLength != aOther.mLength) || (memcmp(mData, aOther.mData, mLength) != 0);
}
uint8_t mData[kMaxDataSize];
uint16_t mLength;
};
struct PowerSettings
{
bool operator!=(const PowerSettings &aOther) const
{
return (mTargetPower != aOther.mTargetPower) || (mActualPower != aOther.mActualPower) ||
(mRawPowerSetting != aOther.mRawPowerSetting);
}
int16_t mTargetPower;
int16_t mActualPower;
RawPowerSetting mRawPowerSetting;
};
Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
Error ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
@@ -156,6 +197,9 @@ private:
Error ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
#endif
Error GetRawPowerSetting(RawPowerSetting &aRawPowerSetting);
Error GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings);
void TransmitPacket(void);
static void AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen);
+38 -7
View File
@@ -29,6 +29,7 @@
#include "power_calibration.hpp"
#if OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
#include <openthread/platform/diag.h>
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
@@ -131,9 +132,11 @@ exit:
return error;
}
Error PowerCalibration::GetRawPowerSetting(uint8_t aChannel,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
Error PowerCalibration::GetPowerSettings(uint8_t aChannel,
int16_t *aTargetPower,
int16_t *aActualPower,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
Error error = kErrorNone;
uint8_t chIndex;
@@ -168,8 +171,20 @@ Error PowerCalibration::GetRawPowerSetting(uint8_t aChannel,
exit:
if (error == kErrorNone)
{
error = mCalibratedPowerTables[mLastChannel - Radio::kChannelMin][mCalibratedPowerIndex].GetRawPowerSetting(
aRawPowerSetting, aRawPowerSettingLength);
chIndex = mLastChannel - Radio::kChannelMin;
if (aTargetPower != nullptr)
{
*aTargetPower = mTargetPowerTable[chIndex];
}
if (aActualPower != nullptr)
{
*aActualPower = mCalibratedPowerTables[chIndex][mCalibratedPowerIndex].GetActualPower();
}
error = mCalibratedPowerTables[chIndex][mCalibratedPowerIndex].GetRawPowerSetting(aRawPowerSetting,
aRawPowerSettingLength);
}
return error;
@@ -208,7 +223,23 @@ otError otPlatRadioGetRawPowerSetting(otInstance *aInstance,
AssertPointerIsNotNull(aRawPowerSetting);
AssertPointerIsNotNull(aRawPowerSettingLength);
return AsCoreType(aInstance).Get<Utils::PowerCalibration>().GetRawPowerSetting(aChannel, aRawPowerSetting,
aRawPowerSettingLength);
return AsCoreType(aInstance).Get<Utils::PowerCalibration>().GetPowerSettings(
aChannel, nullptr, nullptr, aRawPowerSetting, aRawPowerSettingLength);
}
otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
uint8_t aChannel,
int16_t *aTargetPower,
int16_t *aActualPower,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
AssertPointerIsNotNull(aRawPowerSetting);
AssertPointerIsNotNull(aRawPowerSettingLength);
return AsCoreType(aInstance).Get<Utils::PowerCalibration>().GetPowerSettings(
aChannel, aTargetPower, aActualPower, aRawPowerSetting, aRawPowerSettingLength);
}
#endif // OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+13 -4
View File
@@ -99,22 +99,31 @@ public:
Error SetChannelTargetPower(uint8_t aChannel, int16_t aTargetPower);
/**
* Get the raw power setting for the given channel.
* Get the power settings for the given channel.
*
* Platform radio layer should parse the raw power setting based on the radio layer defined format and set the
* parameters of each radio hardware module.
*
* @param[in] aChannel The radio channel.
* @param[out] aTargetPower A pointer to the target power in 0.01 dBm. May be set to nullptr if
* the caller doesn't want to get the target power.
* @param[out] aActualPower A pointer to the actual power in 0.01 dBm. May be set to nullptr if
* the caller doesn't want to get the actual power.
* @param[out] aRawPowerSetting A pointer to the raw power setting byte array.
* @param[in,out] aRawPowerSettingLength On input, a pointer to the size of @p aRawPowerSetting.
* On output, a pointer to the length of the raw power setting data.
*
* @retval kErrorNone Successfully got the target power.
* @retval kErrorInvalidArgs The @p aChannel is invalid or @p aRawPowerSetting is nullptr.
* @retval kErrorNotFound The raw power setting for the @p aChannel was not found.
* @retval kErrorInvalidArgs The @p aChannel is invalid, @p aRawPowerSetting or @p aRawPowerSettingLength is
* nullptr or @aRawPowerSettingLength is too short.
* @retval kErrorNotFound The power settings for the @p aChannel was not found.
*
*/
Error GetRawPowerSetting(uint8_t aChannel, uint8_t *aRawPowerSetting, uint16_t *aRawPowerSettingLength);
Error GetPowerSettings(uint8_t aChannel,
int16_t *aTargetPower,
int16_t *aActualPower,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength);
private:
class CalibratedPowerEntry
@@ -44,6 +44,16 @@
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 256
#endif
/**
* @def OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE
*
* Define OpenThread diagnostic mode output buffer size in bytes
*
*/
#ifndef OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE
#define OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE 500
#endif
/**
* @def OPENTHREAD_CONFIG_LOG_PLATFORM
*
+112
View File
@@ -41,6 +41,7 @@
#include "common/new.hpp"
#include "lib/spinel/radio_spinel.hpp"
#include "posix/platform/radio.hpp"
#include "utils/parse_cmdline.hpp"
#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_UART
#include "hdlc_interface.hpp"
@@ -623,6 +624,117 @@ exit:
return error;
}
otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
uint8_t aChannel,
int16_t *aTargetPower,
int16_t *aActualPower,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
static constexpr uint16_t kRawPowerStringSize = OPENTHREAD_CONFIG_POWER_CALIBRATION_RAW_POWER_SETTING_SIZE * 2 + 1;
static constexpr uint16_t kFmtStringSize = 100;
otError error;
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
int targetPower;
int actualPower;
char rawPowerSetting[kRawPowerStringSize];
char fmt[kFmtStringSize];
assert((aTargetPower != nullptr) && (aActualPower != nullptr) && (aRawPowerSetting != nullptr) &&
(aRawPowerSettingLength != nullptr));
snprintf(cmd, sizeof(cmd), "powersettings %d", aChannel);
SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, output, sizeof(output)));
snprintf(fmt, sizeof(fmt), "TargetPower(0.01dBm): %%d\r\nActualPower(0.01dBm): %%d\r\nRawPowerSetting: %%%us\r\n",
kRawPowerStringSize);
VerifyOrExit(sscanf(output, fmt, &targetPower, &actualPower, rawPowerSetting) == 3, error = OT_ERROR_FAILED);
SuccessOrExit(
error = ot::Utils::CmdLineParser::ParseAsHexString(rawPowerSetting, *aRawPowerSettingLength, aRawPowerSetting));
*aTargetPower = static_cast<int16_t>(targetPower);
*aActualPower = static_cast<int16_t>(actualPower);
exit:
return error;
}
otError otPlatDiagRadioSetRawPowerSetting(otInstance *aInstance,
const uint8_t *aRawPowerSetting,
uint16_t aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
otError error;
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
int nbytes;
assert(aRawPowerSetting != nullptr);
nbytes = snprintf(cmd, sizeof(cmd), "rawpowersetting ");
for (uint16_t i = 0; i < aRawPowerSettingLength; i++)
{
nbytes += snprintf(cmd + nbytes, sizeof(cmd) - static_cast<size_t>(nbytes), "%02x", aRawPowerSetting[i]);
VerifyOrExit(nbytes < static_cast<int>(sizeof(cmd)), error = OT_ERROR_INVALID_ARGS);
}
SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, nullptr, 0));
exit:
return error;
}
otError otPlatDiagRadioGetRawPowerSetting(otInstance *aInstance,
uint8_t *aRawPowerSetting,
uint16_t *aRawPowerSettingLength)
{
OT_UNUSED_VARIABLE(aInstance);
otError error;
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
char *str;
assert((aRawPowerSetting != nullptr) && (aRawPowerSettingLength != nullptr));
snprintf(cmd, sizeof(cmd), "rawpowersetting");
SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, output, sizeof(output)));
VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
SuccessOrExit(error = ot::Utils::CmdLineParser::ParseAsHexString(str, *aRawPowerSettingLength, aRawPowerSetting));
exit:
return error;
}
otError otPlatDiagRadioRawPowerSettingEnable(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
otError error;
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "rawpowersetting %s", aEnable ? "enable" : "disable");
SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, nullptr, 0));
exit:
return error;
}
otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
otError error;
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "cw %s", aEnable ? "start" : "stop");
SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, nullptr, 0));
exit:
return error;
}
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
OT_UNUSED_VARIABLE(aInstance);
+19
View File
@@ -175,6 +175,25 @@ send "diag gpio mode 0\n"
expect "out"
expect_line "Done"
send "diag cw start\n"
expect_line "Done"
send "diag cw stop\n"
expect_line "Done"
send "diag rawpowersetting 112233\n"
expect_line "Done"
send "diag rawpowersetting\n"
expect "112233"
expect_line "Done"
send "diag rawpowersetting enable\n"
expect_line "Done"
send "diag rawpowersetting disable\n"
expect_line "Done"
send "diag invalid_commad\n"
expect "Error 35: InvalidCommand"
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2022, The OpenThread Authors.
# All rights reserved.
#
# 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 the copyright holder 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.
#
source "tests/scripts/expect/_common.exp"
spawn_node 1
send "diag start\n"
expect "start diagnostics mode"
expect "status 0x00"
expect_line "Done"
send "diag powersettings 11\n"
expect "failed"
expect "status 0x17"
expect_line "Error 23: NotFound"
send "diag powersettings\n"
expect "| StartCh | EndCh | TargetPower | ActualPower | RawPowerSetting |"
expect "+---------+-------+-------------+-------------+-----------------+"
expect_line "Done"
send "diag stop\n"
expect_line "Done"
send "region US\n"
expect_line "Done"
send "diag start\n"
expect "start diagnostics mode"
expect "status 0x00"
expect_line "Done"
send "diag powersettings 11\n"
expect -re {TargetPower\(0\.01dBm\): -?\d+}
expect -re {ActualPower\(0\.01dBm\): -?\d+}
expect -re {RawPowerSetting: [0-9]{1,16}}
expect_line "Done"
send "diag powersettings\n"
expect "| StartCh | EndCh | TargetPower | ActualPower | RawPowerSetting |"
expect "+---------+-------+-------------+-------------+-----------------+"
for {set i 1} {$i <= 4} {incr i} {
expect -re "\\| +\\d+ | +\\d+ | +\\d+ | +\\d+ | +\[0-9\]\{1,16\} |"
}
expect_line "Done"
dispose_all