mirror of
https://github.com/mysensors/MySensors.git
synced 2026-02-19 17:11:28 +01:00
MySensors Diagnostics (#1333)
* MySensors Diagnostics * Fix Cppcheck issues * Fix formatting in PrintHex8 function
This commit is contained in:
18
MyConfig.h
18
MyConfig.h
@@ -133,6 +133,22 @@
|
||||
*/
|
||||
//#define MY_SPECIAL_DEBUG
|
||||
|
||||
/**
|
||||
* @def MY_DIAGNOSTICS
|
||||
* @brief Define MY_DIAGNOSTICS to show a diagnostics serial user interface
|
||||
*
|
||||
*/
|
||||
//#define MY_DIAGNOSTICS
|
||||
|
||||
/**
|
||||
* @def MY_DIAGNOSTICS_CRYPTO
|
||||
* @brief Define MY_DIAGNOSTICS_CRYPTO to include crypto testing functions.
|
||||
*
|
||||
* This feature is disabled on AVR architectures due to limited flash/RAM space but can be enabled if needed.
|
||||
*
|
||||
*/
|
||||
//#define MY_DIAGNOSTICS
|
||||
|
||||
/**
|
||||
* @def MY_DISABLED_SERIAL
|
||||
* @brief Define MY_DISABLED_SERIAL if you want to use the UART TX/RX pins as normal I/O pins.
|
||||
@@ -2633,6 +2649,8 @@
|
||||
#define MY_SPECIAL_DEBUG
|
||||
#define MY_DISABLED_SERIAL
|
||||
#define MY_SPLASH_SCREEN_DISABLED
|
||||
#define MY_DIAGNOSTICS
|
||||
#define MY_DIAGNOSTICS_CRYPTO
|
||||
// linux
|
||||
#define MY_LINUX_SERIAL_PORT
|
||||
#define MY_LINUX_SERIAL_IS_PTY
|
||||
|
||||
16
MySensors.h
16
MySensors.h
@@ -40,9 +40,19 @@
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(MY_DIAGNOSTICS)
|
||||
#if !defined(ARDUINO_ARCH_AVR)
|
||||
// more flash available
|
||||
#define MY_DIAGNOSTICS_CRYPTO
|
||||
#endif
|
||||
#define MY_DEBUG_VERBOSE_TRANSPORT
|
||||
#define MY_DEBUG_VERBOSE_TRANSPORT_HAL
|
||||
#define MY_SPECIAL_DEBUG
|
||||
#include "core/MyDiagnostics.h"
|
||||
#endif
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "core/MyHelperFunctions.cpp"
|
||||
|
||||
#include "core/MySplashScreen.h"
|
||||
#include "core/MySensorsCore.h"
|
||||
|
||||
@@ -457,6 +467,10 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
|
||||
#include "core/MySplashScreen.cpp"
|
||||
#include "core/MySensorsCore.cpp"
|
||||
|
||||
#if defined(MY_DIAGNOSTICS)
|
||||
#include "core/MyDiagnostics.cpp"
|
||||
#endif
|
||||
|
||||
// HW mains
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#include "hal/architecture/AVR/MyMainAVR.cpp"
|
||||
|
||||
958
core/MyDiagnostics.cpp
Normal file
958
core/MyDiagnostics.cpp
Normal file
@@ -0,0 +1,958 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in RAM or EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2026 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#include "MyDiagnostics.h"
|
||||
|
||||
static char inputBuffer[15];
|
||||
static char inputCmd;
|
||||
static uint8_t inputBufferPosition;
|
||||
static String inputParameter;
|
||||
|
||||
void diagnosticsFlushSerial(void)
|
||||
{
|
||||
delay(100);
|
||||
while (MY_SERIALDEVICE.available()) {
|
||||
(void)MY_SERIALDEVICE.read();
|
||||
}
|
||||
}
|
||||
|
||||
void diagnosticsSerialInput(void)
|
||||
{
|
||||
bool cmdReceived = false;
|
||||
inputBufferPosition = 0;
|
||||
while (!cmdReceived) {
|
||||
if (MY_SERIALDEVICE.available()) {
|
||||
const char inputChr = MY_SERIALDEVICE.read();
|
||||
if (inputChr == '\n' || inputBufferPosition == sizeof(inputBuffer) - 1) {
|
||||
cmdReceived = true;
|
||||
} else {
|
||||
inputBuffer[inputBufferPosition++] = inputChr;
|
||||
}
|
||||
}
|
||||
}
|
||||
diagnosticsFlushSerial();
|
||||
// null termination
|
||||
inputBuffer[inputBufferPosition] = 0;
|
||||
inputParameter = String(&inputBuffer[1]);
|
||||
inputCmd = toUpperCase(inputBuffer[0]);
|
||||
}
|
||||
|
||||
void PRINT(const char *fmt, ...)
|
||||
{
|
||||
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
|
||||
va_end(args);
|
||||
MY_SERIALDEVICE.print(fmtBuffer);
|
||||
}
|
||||
|
||||
void PrintHex8(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
for (uint16_t i = 0; i < length; ++i) {
|
||||
PRINT(PSTR("%02" PRIX8 " "), data[i]);
|
||||
if ( ((i + 1u) % 16u == 0u) || (i + 1u == length) ) {
|
||||
MY_SERIALDEVICE.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void diagnosticsPrintSeparationLine(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < 50; i++) {
|
||||
MY_SERIALDEVICE.print("=");
|
||||
}
|
||||
MY_SERIALDEVICE.println();
|
||||
}
|
||||
|
||||
void diagnosticsMySensorsEEPROMDump(void)
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
PRINT(PSTR("> MYS E2P START: 0x%04" PRIX16 "\n"), EEPROM_START);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> NODE_ID="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_NODE_ID_ADDRESS), SIZE_NODE_ID);
|
||||
PrintHex8(buffer, SIZE_NODE_ID);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> PAR_ID="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_PARENT_NODE_ID_ADDRESS),
|
||||
SIZE_PARENT_NODE_ID);
|
||||
PrintHex8(buffer, SIZE_PARENT_NODE_ID);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> D_GW="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_DISTANCE_ADDRESS), SIZE_DISTANCE);
|
||||
PrintHex8(buffer, SIZE_DISTANCE);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> RTE TABLE:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_ROUTES_ADDRESS), SIZE_ROUTES);
|
||||
PrintHex8(buffer, SIZE_ROUTES);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> CTRL_CFG:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_CONTROLLER_CONFIG_ADDRESS),
|
||||
SIZE_CONTROLLER_CONFIG);
|
||||
PrintHex8(buffer, SIZE_CONTROLLER_CONFIG);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> PERS_CRC="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS),
|
||||
SIZE_PERSONALIZATION_CHECKSUM);
|
||||
PrintHex8(buffer, SIZE_PERSONALIZATION_CHECKSUM);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> FW_TYPE="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_FIRMWARE_TYPE_ADDRESS),
|
||||
SIZE_PERSONALIZATION_CHECKSUM);
|
||||
PrintHex8(buffer, SIZE_PERSONALIZATION_CHECKSUM);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> FW_VERS="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_FIRMWARE_VERSION_ADDRESS),
|
||||
SIZE_FIRMWARE_VERSION);
|
||||
PrintHex8(buffer, SIZE_FIRMWARE_VERSION);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> FW_BLOCKS="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_FIRMWARE_BLOCKS_ADDRESS),
|
||||
SIZE_FIRMWARE_BLOCKS);
|
||||
PrintHex8(buffer, SIZE_FIRMWARE_BLOCKS);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> FW_CRC="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_FIRMWARE_CRC_ADDRESS), SIZE_FIRMWARE_CRC);
|
||||
PrintHex8(buffer, SIZE_FIRMWARE_CRC);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> SGN_REQ_TABLE:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS),
|
||||
SIZE_SIGNING_REQUIREMENT_TABLE);
|
||||
PrintHex8(buffer, SIZE_SIGNING_REQUIREMENT_TABLE);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> WL_REQ_TABLE:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS),
|
||||
SIZE_WHITELIST_REQUIREMENT_TABLE);
|
||||
PrintHex8(buffer, SIZE_WHITELIST_REQUIREMENT_TABLE);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> SGN_SOFT_KEY:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS),
|
||||
SIZE_SIGNING_SOFT_HMAC_KEY);
|
||||
PrintHex8(buffer, SIZE_SIGNING_SOFT_HMAC_KEY);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> SGN_SOFT_SER:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_SIGNING_SOFT_SERIAL_ADDRESS),
|
||||
SIZE_SIGNING_SOFT_SERIAL);
|
||||
PrintHex8(buffer, SIZE_SIGNING_SOFT_SERIAL);
|
||||
|
||||
MY_SERIALDEVICE.println(F("> AES_KEY:"));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS),
|
||||
SIZE_RF_ENCRYPTION_AES_KEY);
|
||||
PrintHex8(buffer, SIZE_RF_ENCRYPTION_AES_KEY);
|
||||
|
||||
MY_SERIALDEVICE.print(F("> NL_CNT="));
|
||||
hwReadConfigBlock(buffer, reinterpret_cast<void *>(EEPROM_NODE_LOCK_COUNTER_ADDRESS),
|
||||
SIZE_NODE_LOCK_COUNTER);
|
||||
PrintHex8(buffer, SIZE_NODE_LOCK_COUNTER);
|
||||
|
||||
PRINT(PSTR("> USER E2P >= 0x%04" PRIX16 "\n"), EEPROM_LOCAL_CONFIG_ADDRESS);
|
||||
}
|
||||
|
||||
void diagnosticsClearMySensorsEEPROMConfig(void)
|
||||
{
|
||||
for (uint16_t i = EEPROM_START; i < EEPROM_START + EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
|
||||
hwWriteConfig(i, 0xFF);
|
||||
if (hwReadConfig(i) != 0xFF) {
|
||||
PRINT(PSTR("!ERR POS 0x02%" PRIX8 "\n"), i);
|
||||
}
|
||||
}
|
||||
MY_SERIALDEVICE.println(F("> E2P CLR"));
|
||||
}
|
||||
|
||||
void diagnosticsClearMySensorsRoutingTable(void)
|
||||
{
|
||||
for (uint16_t i = 0; i < SIZE_ROUTES; i++) {
|
||||
hwWriteConfig(EEPROM_ROUTES_ADDRESS + i, 0xFF);
|
||||
if (hwReadConfig(EEPROM_ROUTES_ADDRESS + i) != 0xFF) {
|
||||
PRINT(PSTR("!ERR POS 0x02%" PRIu8 "\n"), i);
|
||||
}
|
||||
}
|
||||
MY_SERIALDEVICE.println(F("> RTE TABLE CLR"));
|
||||
}
|
||||
|
||||
void diagnosticsClearMySensorsTransportSettings(void)
|
||||
{
|
||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, 0xFF);
|
||||
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF);
|
||||
hwWriteConfig(EEPROM_DISTANCE_ADDRESS, 0xFF);
|
||||
MY_SERIALDEVICE.println(F("> TSP CFG CLR"));
|
||||
}
|
||||
|
||||
void diagnosticsEEPROMTest(void)
|
||||
{
|
||||
MY_SERIALDEVICE.println(F("EEPROM test:"));
|
||||
uint16_t success = 0;
|
||||
for (uint16_t i = 0; i < (EEPROM_LOCAL_CONFIG_ADDRESS - EEPROM_START); i++) {
|
||||
if (i % 80 == 0) {
|
||||
MY_SERIALDEVICE.println();
|
||||
MY_SERIALDEVICE.print(i + EEPROM_START, HEX);
|
||||
MY_SERIALDEVICE.print(": ");
|
||||
} else {
|
||||
MY_SERIALDEVICE.print(".");
|
||||
}
|
||||
const uint8_t originalContent = hwReadConfig(i + EEPROM_START);
|
||||
hwWriteConfig(i + EEPROM_START, 0xAA);
|
||||
if (hwReadConfig(i + EEPROM_START) == 0xAA) {
|
||||
success++;
|
||||
} else {
|
||||
PRINT(PSTR("!ERR POS 0x02%" PRIu8 "\n"), i + EEPROM_START);
|
||||
}
|
||||
hwWriteConfig(i + EEPROM_START, 0x55);
|
||||
if (hwReadConfig(i + EEPROM_START) == 0x55) {
|
||||
success++;
|
||||
}
|
||||
// write back original byte
|
||||
hwWriteConfig(i + EEPROM_START, originalContent);
|
||||
if (hwReadConfig(i + EEPROM_START) == originalContent) {
|
||||
success++;
|
||||
} else {
|
||||
PRINT(PSTR("!ERR POS 0x02%" PRIu8 "\n"), i + EEPROM_START);
|
||||
}
|
||||
}
|
||||
MY_SERIALDEVICE.print(F("\n>E2P check: "));
|
||||
if (success == (EEPROM_LOCAL_CONFIG_ADDRESS - EEPROM_START) * 3) {
|
||||
MY_SERIALDEVICE.println(F("pass"));
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("failed!"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void diagnosticsEEPROMMenu(void)
|
||||
{
|
||||
while (true) {
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("EEPROM:\n\n"
|
||||
"[D] Dump\n"
|
||||
"[T] Test\n"
|
||||
"[C] CLR\n"
|
||||
"[R] CLR TSP RTE\n"
|
||||
"[S] CLR TSP CFG\n"
|
||||
"[X] Exit"
|
||||
));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsFlushSerial();
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'D') {
|
||||
diagnosticsMySensorsEEPROMDump();
|
||||
} else if (inputCmd == 'T') {
|
||||
diagnosticsEEPROMTest();
|
||||
} else if (inputCmd == 'C') {
|
||||
diagnosticsClearMySensorsEEPROMConfig();
|
||||
} else if (inputCmd== 'R') {
|
||||
diagnosticsClearMySensorsRoutingTable();
|
||||
} else if (inputCmd == 'S') {
|
||||
diagnosticsClearMySensorsTransportSettings();
|
||||
} else if (inputCmd == 'X') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MY_DIAGNOSTICS_CRYPTO)
|
||||
bool diagnosticsCryptoMenu(void)
|
||||
{
|
||||
MY_SERIALDEVICE.println(F("Testing:"));
|
||||
const uint8_t test_data[64] = { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
|
||||
0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
|
||||
0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
|
||||
0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
|
||||
};
|
||||
const uint8_t test_psk[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
|
||||
uint8_t aes_iv[16];
|
||||
for (uint8_t i = 0; i < sizeof(aes_iv); i++) {
|
||||
aes_iv[i] = i;
|
||||
}
|
||||
|
||||
AES128CBCInit(test_psk);
|
||||
#if defined(CRYPTO_OUTPUT)
|
||||
MY_SERIALDEVICE.println(F("AES128CBC input:"));
|
||||
PrintHex8(test_data, sizeof(test_data));
|
||||
MY_SERIALDEVICE.println(F("AES128CBC key:"));
|
||||
PrintHex8(test_psk, sizeof(test_psk));
|
||||
MY_SERIALDEVICE.println(F("AES128CBC IV:"));
|
||||
PrintHex8(aes_iv, sizeof(aes_iv));
|
||||
#endif
|
||||
uint8_t temp_iv[16];
|
||||
uint8_t temp_data[64];
|
||||
(void)memcpy(temp_iv, aes_iv, sizeof(aes_iv));
|
||||
(void)memcpy(temp_data, test_data, sizeof(temp_data));
|
||||
AES128CBCEncrypt(temp_iv, temp_data, sizeof(test_data));
|
||||
MY_SERIALDEVICE.print(F("- AES128 CBC encryption: "));
|
||||
const uint8_t aes_ciphertext[64] = {
|
||||
0x46,0xE3,0x35,0xB8,0xEA,0x11,0xBC,0xC5,0xB4,0xEB,0x7F,0x49,0xD1,0x14,0xFF,0x43,0x28,0x22,0x15,
|
||||
0xAD,0x3A,0xCF,0xF1,0x6B,0xE1,0x9B,0x6F,0x71,0x1A,0xA1,0x3B,0x89,0x69,0xFD,0x9F,0xB7,0x98,0x2A,
|
||||
0x37,0x03,0xE8,0x16,0x14,0x3F,0x89,0x62,0x56,0x0F,0xDA,0x85,0xAD,0x94,0xD3,0x4E,0x54,0x18,0x2A,
|
||||
0x52,0x5C,0x2B,0x28,0xFA,0x0E,0xAB
|
||||
};
|
||||
// result verified here: http://extranet.cryptomathic.com/aescalc/index
|
||||
if (memcmp(temp_data, &aes_ciphertext, sizeof(aes_ciphertext)) == 0) {
|
||||
MY_SERIALDEVICE.println(F("OK"));
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
};
|
||||
#if defined(CRYPTO_OUTPUT)
|
||||
PrintHex8(temp_data, sizeof(test_data));
|
||||
#endif
|
||||
(void)memcpy(temp_iv, aes_iv, sizeof(aes_iv));
|
||||
AES128CBCDecrypt(temp_iv, temp_data, sizeof(temp_data));
|
||||
MY_SERIALDEVICE.print(F("- AES128 CBC decryption: "));
|
||||
if (memcmp(test_data, temp_data, sizeof(temp_data)) == 0) {
|
||||
MY_SERIALDEVICE.println(F("OK"));
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
};
|
||||
#if defined(CRYPTO_OUTPUT)
|
||||
PrintHex8(temp_data, sizeof(temp_data));
|
||||
#endif
|
||||
MY_SERIALDEVICE.print(F("- SHA256: "));
|
||||
uint8_t dest[64];
|
||||
SHA256(dest, test_data, sizeof(test_data));
|
||||
#if defined(CRYPTO_OUTPUT)
|
||||
MY_SERIALDEVICE.println(F("SHA256 input:"));
|
||||
PrintHex8(test_data, sizeof(test_data));
|
||||
MY_SERIALDEVICE.println(F("SHA256 output:"));
|
||||
PrintHex8(dest, 32);
|
||||
#endif
|
||||
// result verified here: http://extranet.cryptomathic.com/hashcalc/index
|
||||
const uint8_t sha256result[32] = { 0x51,0x3f,0xa7,0x82,0x3d,0xc3,0x05,0x3d,0xc6,0x43,0xa4,0x4b,0x8f,0xb8,0xdd,0x62,
|
||||
0x36,0x0b,0x00,0x44,0xf1,0xab,0x69,0x65,0xf8,0x36,0x29,0xd2,0xb1,0x64,0xbf,0x14
|
||||
};
|
||||
//PRINT(PSTR("SHA256 test: "));
|
||||
if (memcmp(dest, &sha256result, sizeof(sha256result)) == 0) {
|
||||
MY_SERIALDEVICE.println(F("OK"));
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
};
|
||||
|
||||
MY_SERIALDEVICE.print(F("- HMAC SHA256: "));
|
||||
#if defined(CRYPTO_OUTPUT)
|
||||
MY_SERIALDEVICE.println(F("HMAC input:"));
|
||||
PrintHex8(test_data, sizeof(test_data));
|
||||
MY_SERIALDEVICE.println(F("HMAC key:"));
|
||||
PrintHex8(test_psk, sizeof(test_psk));
|
||||
#endif
|
||||
SHA256HMAC(dest, test_psk, sizeof(test_psk), test_data, sizeof(test_data));
|
||||
#if defined(CRYPTO_OUTPUT)
|
||||
MY_SERIALDEVICE.println(F("HMAC output:"));
|
||||
PrintHex8(dest, sizeof(dest));
|
||||
#endif
|
||||
// result verified here: http://extranet.cryptomathic.com/hmaccalc/index
|
||||
const uint8_t hmacresult[32] = { 0xcc,0xa7,0x5f,0x5d,0xd5,0xeb,0x50,0x34,0x02,0x53,0x12,0x17,0x40,0x72,0xaf,0x29,
|
||||
0xe6,0xc9,0xb5,0xb1,0x9b,0x26,0x8b,0x23,0x0f,0x5c,0xeb,0x50,0x24,0x63,0xc2,0x33
|
||||
};
|
||||
//PRINT(PSTR("HMAC test: "));
|
||||
if (memcmp(dest, &hmacresult, sizeof(sha256result)) == 0) {
|
||||
MY_SERIALDEVICE.println(F("OK"));
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
};
|
||||
MY_SERIALDEVICE.println(F("> MUL speed:"));
|
||||
uint32_t startMS, stopMS;
|
||||
uint32_t cnt;
|
||||
MY_SERIALDEVICE.print(F("- 8bit MUL: "));
|
||||
startMS = hwMillis();
|
||||
uint8_t u8 = 1;
|
||||
cnt = 0xFFFFF;
|
||||
while (cnt--) {
|
||||
u8 *= 3;
|
||||
}
|
||||
stopMS = hwMillis();
|
||||
if (u8 == 171) {
|
||||
PRINT(PSTR("OK, %" PRIu32 " ms\n"), stopMS - startMS);
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
}
|
||||
|
||||
MY_SERIALDEVICE.print(F("- 16bit MUL: "));
|
||||
startMS = hwMillis();
|
||||
uint16_t u16 = 1;
|
||||
cnt = 0xFFFFF;
|
||||
while (cnt--) {
|
||||
u16 *= 3;
|
||||
}
|
||||
stopMS = hwMillis();
|
||||
if (u16 == 43691) {
|
||||
PRINT(PSTR("OK, %" PRIu32 " ms\n"), stopMS - startMS);
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
}
|
||||
|
||||
MY_SERIALDEVICE.print(F("- 32bit MUL: "));
|
||||
startMS = hwMillis();
|
||||
uint32_t u32 = 1;
|
||||
cnt = 0xFFFFF;
|
||||
while (cnt--) {
|
||||
u32 *= 3;
|
||||
}
|
||||
stopMS = hwMillis();
|
||||
if (u32 == 3664423595) {
|
||||
PRINT(PSTR("OK, %" PRIu32 " ms\n"), stopMS - startMS);
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("FAIL!"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
void diagnosticsWatchdogTest(void)
|
||||
{
|
||||
MY_SERIALDEVICE.println(F("Set WDT to 4s\n"));
|
||||
hwWatchdogReset();
|
||||
wdt_enable(WDTO_4S);
|
||||
for (uint8_t timer = 0; timer < 10; timer++) {
|
||||
MY_SERIALDEVICE.print(timer);
|
||||
delay(1000);
|
||||
}
|
||||
MY_SERIALDEVICE.println(F("WDT failed!\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MY_RADIO_RFM95)
|
||||
void diagnosticsRFM95Menu(void)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MY_RADIO_RFM69) && defined(MY_RFM69_NEW_DRIVER)
|
||||
void diagnosticsRFM69Menu(void)
|
||||
{
|
||||
RFM69_initialise(RFM69_868MHZ);
|
||||
while (true) {
|
||||
diagnosticsFlushSerial();
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("RFM69:\n"));
|
||||
PRINT(PSTR("SPI: MOSI=%" PRIu8 ", MISO=%" PRIu8 ", SCK=%" PRIu8 ", CS=%" PRIu8 ", IRQ=%" PRIu8
|
||||
"\n"),
|
||||
MOSI, MISO, SCK, MY_RFM69_CS_PIN, MY_RFM69_IRQ_PIN);
|
||||
PRINT(PSTR("RF: ID=%" PRIu8 ", FREQ=%" PRIu32 ", POW=%" PRIu8 "\n"),
|
||||
RFM69_getAddress(), RFM69_getFrequency(), RFM69_getTxPowerLevel());
|
||||
|
||||
MY_SERIALDEVICE.println(F(
|
||||
"[I] Init\n"
|
||||
"[D] Dump REG\n"
|
||||
"[Ax] ADDR=x\n"
|
||||
"[Fx] FREQ=x\n"
|
||||
"[Wx] POW=X\n"
|
||||
"[L] SLP\n"
|
||||
"[B] STDBY\n"
|
||||
"[O] CAR on\n"
|
||||
"[Q] CAR off\n"
|
||||
"[R] RX\n"
|
||||
"[Tx] TX to x\n"
|
||||
"[P] Poll STAT\n"
|
||||
"[X] Exit"
|
||||
));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'I') {
|
||||
RFM69_initialise(RFM69_868MHZ);
|
||||
} else if (inputCmd == 'A') {
|
||||
RFM69_setAddress(inputParameter.toInt());
|
||||
} else if (inputCmd == 'F') {
|
||||
RFM69_setFrequency(inputParameter.toInt());
|
||||
} else if (inputCmd == 'W') {
|
||||
RFM69_setTxPowerLevel(inputParameter.toInt());
|
||||
} else if (inputCmd == 'L') {
|
||||
RFM69_sleep();
|
||||
} else if (inputCmd == 'B') {
|
||||
RFM69_standBy();
|
||||
} else if (inputCmd == 'R') {
|
||||
(void)RFM69_setRadioMode(RFM69_RADIO_MODE_RX);
|
||||
} else if (inputCmd == 'T') {
|
||||
uint8_t buffer[] = { 'T','E','S','T','R','F','M','6','9' };
|
||||
RFM69_sendWithRetry(inputParameter.toInt(), buffer, sizeof(buffer), true);
|
||||
} else if (inputCmd == 'P') {
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("Press any key to exit"));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsFlushSerial();
|
||||
while (!MY_SERIALDEVICE.available()) {
|
||||
PRINT(PSTR("IRQF1=0x%02" PRIX8 ", IRQF2=0x%02" PRIX8 ", IRQF=%" PRIu8 "\n"),
|
||||
RFM69_readReg(RFM69_REG_IRQFLAGS1), RFM69_readReg(RFM69_REG_IRQFLAGS2), RFM69_irq);
|
||||
delay(300);
|
||||
}
|
||||
MY_SERIALDEVICE.println(F("Exiting..."));
|
||||
} else if (inputCmd == 'O') {
|
||||
(void)RFM69_setRadioMode(RFM69_RADIO_MODE_TX);
|
||||
} else if (inputCmd == 'Q') {
|
||||
(void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY);
|
||||
} else if (inputCmd == 'D') {
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
PRINT(PSTR("Reg 0x%02" PRIX8 " = 0x%02" PRIX8 "\n"), i, RFM69_readReg(i));
|
||||
} while (i++ != 0xFF);
|
||||
} else if (inputCmd == 'X') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MY_RADIO_RF24)
|
||||
void diagnosticsRF24Menu(void)
|
||||
{
|
||||
RF24_initialize();
|
||||
while (true) {
|
||||
diagnosticsFlushSerial();
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("RF24:\n"));
|
||||
PRINT(PSTR("SPI: MOSI=%" PRIu8 ", MISO=%" PRIu8 ", SCK=%" PRIu8 ", CS=%" PRIu8 ", CE=%" PRIu8 "\n"),
|
||||
MOSI, MISO, SCK, MY_RF24_CS_PIN, MY_RF24_CE_PIN);
|
||||
PRINT(PSTR("RF: ADDR=%" PRIu8 ", CH=%" PRIu8 ", POW=%" PRIu8 ", CFG=%" PRIu8 "\n"),
|
||||
RF24_getNodeID(),
|
||||
RF24_getChannel(), RF24_getRawTxPowerLevel(), RF24_getRFConfiguration());
|
||||
|
||||
MY_SERIALDEVICE.println(F("[I] Init\n"
|
||||
"[D] Dump REG\n"
|
||||
"[Ax] ADDR=x\n"
|
||||
"[Cx] CH=x\n"
|
||||
"[Wx] POW=X\n"
|
||||
"[L] SLP\n"
|
||||
"[B] STDBY\n"
|
||||
"[O] CAR on\n"
|
||||
"[Q] CAR off\n"
|
||||
"[R] RX\n"
|
||||
"[Tx] TX to x\n"
|
||||
"[P] Poll STAT\n"
|
||||
"[S] Scan CHs\n"
|
||||
"[X] Exit"
|
||||
));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'I') {
|
||||
RF24_initialize();
|
||||
} else if (inputCmd == 'A') {
|
||||
RF24_setNodeAddress(inputParameter.toInt());
|
||||
} else if (inputCmd == 'C') {
|
||||
RF24_setChannel(inputParameter.toInt());
|
||||
} else if (inputCmd == 'W') {
|
||||
RF24_setTxPowerLevel(inputParameter.toInt());
|
||||
} else if (inputCmd == 'L') {
|
||||
RF24_sleep();
|
||||
} else if (inputCmd == 'B') {
|
||||
RF24_standBy();
|
||||
} else if (inputCmd == 'R') {
|
||||
RF24_startListening();
|
||||
} else if (inputCmd == 'T') {
|
||||
uint8_t buffer[] = { 'T','E','S','T','R','F','2','4' };
|
||||
RF24_sendMessage(inputParameter.toInt(), buffer, sizeof(buffer), false);
|
||||
} else if (inputCmd == 'P') {
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("Press any key to exit"));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsFlushSerial();
|
||||
while (!MY_SERIALDEVICE.available()) {
|
||||
PRINT(PSTR("status=%02" PRIX8 "\n"), RF24_getStatus());
|
||||
delay(300);
|
||||
}
|
||||
MY_SERIALDEVICE.println(F("Exiting..."));
|
||||
} else if (inputCmd == 'O') {
|
||||
RF24_enableConstantCarrierWave();
|
||||
} else if (inputCmd == 'Q') {
|
||||
RF24_disableConstantCarrierWave();
|
||||
} else if (inputCmd == 'D') {
|
||||
//uint8_t buffer[16];
|
||||
for (uint8_t i = 0; i < 0x20; i++) {
|
||||
PRINT(PSTR("Reg 0x%02" PRIX8 " = 0x%02" PRIX8 "\n"), i, RF24_readByteRegister(i));
|
||||
/*
|
||||
(void)RF24_readMultiByteRegister(i, buffer, sizeof(buffer));
|
||||
PrintHex8(buffer, sizeof(buffer));
|
||||
for (uint8_t cnt = 0; cnt < sizeof(buffer); cnt++) {
|
||||
buffer[cnt] = 0xFF;
|
||||
}
|
||||
(void)RF24_writeMultiByteRegister(i, buffer, sizeof(buffer));
|
||||
(void)RF24_readMultiByteRegister(i, buffer, sizeof(buffer));
|
||||
PrintHex8(buffer, sizeof(buffer));
|
||||
|
||||
for (uint8_t cnt = 0; cnt < sizeof(buffer); cnt++) {
|
||||
buffer[cnt] = 0x00;
|
||||
}
|
||||
(void)RF24_writeMultiByteRegister(i, buffer, sizeof(buffer));
|
||||
(void)RF24_readMultiByteRegister(i, buffer, sizeof(buffer));
|
||||
PrintHex8(buffer, sizeof(buffer));
|
||||
*/
|
||||
}
|
||||
} else if (inputCmd == 'S') {
|
||||
|
||||
MY_SERIALDEVICE.println(F("Press any key to exit"));
|
||||
diagnosticsFlushSerial();
|
||||
|
||||
const uint8_t num_channels = 126;
|
||||
|
||||
for(uint8_t i = 0; i < num_channels; i++) {
|
||||
PRINT(PSTR("%" PRIX8), i >> 4);
|
||||
}
|
||||
MY_SERIALDEVICE.println();
|
||||
|
||||
for (uint8_t i = 0; i < num_channels; i++) {
|
||||
PRINT(PSTR("%" PRIX8), i & 0xf);
|
||||
}
|
||||
|
||||
MY_SERIALDEVICE.println();
|
||||
|
||||
|
||||
while (!MY_SERIALDEVICE.available()) {
|
||||
|
||||
uint8_t values[num_channels];
|
||||
// disable ACK on all pipes
|
||||
RF24_setAutoACK(0);
|
||||
// clear result array
|
||||
(void)memset(values, 0, sizeof(values));
|
||||
for (uint8_t rep_counter = 0; rep_counter < 100; rep_counter++) {
|
||||
for (uint8_t channel = 0; channel < num_channels; channel++) {
|
||||
RF24_setChannel(channel);
|
||||
RF24_startListening();
|
||||
delayMicroseconds(130 + 40);
|
||||
// Carrier detected?
|
||||
if (RF24_getReceivedPowerDetector()) {
|
||||
values[channel] = values[channel] + 1;
|
||||
}
|
||||
RF24_stopListening();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < num_channels; i++) {
|
||||
PRINT(PSTR("%" PRIX8), min(0xf, values[i]));
|
||||
}
|
||||
|
||||
MY_SERIALDEVICE.println();
|
||||
}
|
||||
} else if (inputCmd == 'X') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MY_SENSOR_NETWORK)
|
||||
void diagnosticsTSMStatus(void)
|
||||
{
|
||||
PRINT(PSTR("%" PRIu32 " TSM,%" PRIu8 ",%" PRIu8 ",%" PRIu8 ",%" PRIu32 ",%" PRIu32 ",%" PRIu8 ",%"
|
||||
PRIu8 ",%" PRIu8 ",%" PRIu8 ",%" PRIu8 ",%" PRIu8 ",%" PRIu8 ",%" PRIu8 "\n"),
|
||||
hwMillis(),
|
||||
transportSanityCheck(),
|
||||
getNodeId(),
|
||||
getParentNodeId(),
|
||||
_transportSM.stateEnter,
|
||||
_transportSM.lastUplinkCheck,
|
||||
_transportSM.findingParentNode,
|
||||
_transportSM.uplinkOk,
|
||||
_transportSM.pingActive,
|
||||
_transportSM.transportActive,
|
||||
_transportSM.stateRetries,
|
||||
_transportSM.failedUplinkTransmissions,
|
||||
_transportSM.failureCounter,
|
||||
_transportSM.pingResponse);
|
||||
}
|
||||
#endif
|
||||
|
||||
void diagnosticsTransportSM(void)
|
||||
{
|
||||
while (true) {
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("TSP SM:\n"));
|
||||
#if defined(MY_SENSOR_NETWORK)
|
||||
PRINT(PSTR("ADDR=%" PRIu8 ",PAR=%" PRIu8 ",DGW=%" PRIu8 ",TSP=%" PRIu8 "\n"), getNodeId(),
|
||||
getDistanceGW(), getParentNodeId(),
|
||||
isTransportReady());
|
||||
MY_SERIALDEVICE.println(F("[I] Init TSP\n"
|
||||
"[S] Step TSM\n"
|
||||
"[R] Run TSM"
|
||||
));
|
||||
#endif
|
||||
MY_SERIALDEVICE.println(F("[X] Exit"));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsFlushSerial();
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'I') {
|
||||
#if defined(MY_SENSOR_NETWORK)
|
||||
transportInitialise();
|
||||
#endif
|
||||
} else if (inputCmd == 'S') {
|
||||
#if defined(MY_SENSOR_NETWORK)
|
||||
transportProcess();
|
||||
diagnosticsTSMStatus();
|
||||
#endif
|
||||
} else if (inputCmd == 'R') {
|
||||
#if defined(MY_SENSOR_NETWORK)
|
||||
MY_SERIALDEVICE.println(F("[U] CKU\n"
|
||||
"[F] FPAR\n"
|
||||
"[E] TSP ERR\n"
|
||||
"[I] INIT\n"
|
||||
"[Cx] PNG x\n"
|
||||
"[Nx] ID=x\n"
|
||||
"[Px] PAR=x\n"
|
||||
"[Tx] TX x\n"
|
||||
"[Sx] Sleep x ms\n"
|
||||
"[X] EXIT\n"
|
||||
));
|
||||
uint32_t lastTimer = 0;
|
||||
bool exitSignal = false;
|
||||
while (!exitSignal) {
|
||||
if (MY_SERIALDEVICE.available()) {
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'U') {
|
||||
transportCheckUplink();
|
||||
} else if (inputCmd == 'F') {
|
||||
transportSwitchSM(stParent);
|
||||
} else if (inputCmd == 'E') {
|
||||
transportSwitchSM(stFailure);
|
||||
} else if (inputCmd == 'I') {
|
||||
transportInitialise();
|
||||
} else if (inputCmd == 'C') {
|
||||
_transportSM.pingActive = false;
|
||||
transportPingNode(inputParameter.toInt());
|
||||
} else if (inputCmd == 'N') {
|
||||
const uint8_t nodeID = inputParameter.toInt();
|
||||
_transportConfig.nodeId = nodeID;
|
||||
transportHALSetAddress(nodeID);
|
||||
// Write ID to EEPROM
|
||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, nodeID);
|
||||
} else if (inputCmd == 'P') {
|
||||
_transportConfig.parentNodeId = inputParameter.toInt();
|
||||
} else if (inputCmd == 'T') {
|
||||
transportSendRoute(build(_msgTmp, inputParameter.toInt(), NODE_SENSOR_ID, C_SET, V_VAR1,
|
||||
false).set((uint32_t)0xDEADBEAF));
|
||||
} else if (inputCmd == 'S') {
|
||||
(void)sleep((uint32_t)inputParameter.toInt(), false);
|
||||
} else if (inputCmd == 'X') {
|
||||
exitSignal = true;
|
||||
}
|
||||
|
||||
}
|
||||
transportProcess();
|
||||
if (hwMillis() - lastTimer > 1000ul) {
|
||||
lastTimer = hwMillis();
|
||||
diagnosticsTSMStatus();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (inputCmd == 'X') {
|
||||
return;
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("!CMD"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void diagnosticsMCUMenu(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
MY_SERIALDEVICE.println(F("ARCH: ESP8266"));
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
MY_SERIALDEVICE.println(F("ARCH: ESP32"));
|
||||
#elif defined(ARDUINO_ARCH_AVR)
|
||||
MY_SERIALDEVICE.println(F("ARCH: AVR"));
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
MY_SERIALDEVICE.println(F("ARCH: SAMD"));
|
||||
#elif defined(ARDUINO_ARCH_STM32)
|
||||
MY_SERIALDEVICE.println(F("ARCH: STM32"));
|
||||
#elif defined(ARDUINO_ARCH_NRF5) || defined(ARDUINO_ARCH_NRF52)
|
||||
MY_SERIALDEVICE.println(F("ARCH: NRF5"));
|
||||
#elif defined(__arm__) && defined(TEENSYDUINO)
|
||||
MY_SERIALDEVICE.println(F("ARCH: Teensyduino"));
|
||||
#elif defined(__linux__)
|
||||
MY_SERIALDEVICE.println(F("ARCH: Linux"));
|
||||
#else
|
||||
MY_SERIALDEVICE.println(F("ARCH: Unknown"));
|
||||
#endif
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
PRINT(PSTR("AVR fuses: L:%02" PRIX8 ",H:%02" PRIX8 ",E:%02" PRIX8 ",LK:%02" PRIX8
|
||||
"\n"),
|
||||
boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS),
|
||||
boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS),
|
||||
boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS),
|
||||
boot_lock_fuse_bits_get(GET_LOCK_BITS));
|
||||
#endif
|
||||
PRINT(PSTR("T_CPU: %" PRIi8 " C\n"), hwCPUTemperature());
|
||||
PRINT(PSTR("V_CPU: %" PRIu16 " mV\n"), hwCPUVoltage());
|
||||
MY_SERIALDEVICE.print(F("F_CPU: "));
|
||||
MY_SERIALDEVICE.print(hwCPUFrequency() / 10.0);
|
||||
MY_SERIALDEVICE.println(F(" MHz"));
|
||||
MY_SERIALDEVICE.print(F("CPU ID: "));
|
||||
unique_id_t ID;
|
||||
const bool result = hwUniqueID(&ID);
|
||||
PrintHex8(ID, sizeof(ID));
|
||||
PRINT(PSTR("UID unique: %s\n"), result ? "true" : "false");
|
||||
#if defined(MY_HW_HAS_GETENTROPY)
|
||||
MY_SERIALDEVICE.println(F("RNG: True"));
|
||||
#else
|
||||
MY_SERIALDEVICE.println(F("RNG: Pseudo"));
|
||||
#endif
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
PRINT(PSTR("Chip rev: %" PRIu8 "\n"), ESP.getChipRevision());
|
||||
PRINT(PSTR("Cycles: %" PRIu32 "\n"), ESP.getCycleCount());
|
||||
PRINT(PSTR("SDK: %s\n"), ESP.getSdkVersion());
|
||||
PRINT(PSTR("EFUSE: %16" PRIX64 "\n"), ESP.getEfuseMac());
|
||||
PRINT(PSTR("Total HEAP size: %" PRIu32 "\n"), ESP.getHeapSize());
|
||||
PRINT(PSTR("Free HEAP size: %" PRIu32 "\n"), ESP.getFreeHeap());
|
||||
PRINT(PSTR("Min HEAP level: %" PRIu32 "\n"), ESP.getMinFreeHeap());
|
||||
PRINT(PSTR("Max HEAP alloc: %" PRIu32 "\n"), ESP.getMaxAllocHeap());
|
||||
PRINT(PSTR("PSRAM size: %" PRIu32 "\n"), ESP.getPsramSize());
|
||||
PRINT(PSTR("Free PSRAM: %" PRIu32 "\n"), ESP.getFreePsram());
|
||||
PRINT(PSTR("Min PSRAM level: %" PRIu32 "\n"), ESP.getMinFreePsram());
|
||||
PRINT(PSTR("Max PSRAM alloc: %" PRIu32 "\n"), ESP.getMaxAllocPsram());
|
||||
PRINT(PSTR("Flash size: %" PRIu32 "\n"), ESP.getFlashChipSize());
|
||||
PRINT(PSTR("Flash speed: %" PRIu32 "\n"), ESP.getFlashChipSpeed());
|
||||
PRINT(PSTR("Sketch size: %" PRIu32 "\n"), ESP.getSketchSize());
|
||||
PRINT(PSTR("Free sketch space: %" PRIu32 "\n"), ESP.getFreeSketchSpace());
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
PRINT(PSTR("Chip id: %08" PRIX32 "\n"), ESP.getChipId());
|
||||
PRINT(PSTR("Cycles: %" PRIu32 "\n"), ESP.getCycleCount());
|
||||
PRINT(PSTR("SDK: %s\n"), ESP.getSdkVersion());
|
||||
PRINT(PSTR("Free HEAP size: %" PRIu32 "\n"), ESP.getFreeHeap());
|
||||
PRINT(PSTR("HEAP fragmentation: %" PRIu8 "\n"), ESP.getHeapFragmentation());
|
||||
PRINT(PSTR("Max block alloc: %" PRIu32 "\n"), ESP.getMaxFreeBlockSize());
|
||||
PRINT(PSTR("Flash id: %08" PRIX32 "\n"), ESP.getFlashChipId());
|
||||
PRINT(PSTR("Flash size: %" PRIu32 "\n"), ESP.getFlashChipSize());
|
||||
PRINT(PSTR("Flash speed: %" PRIu32 "\n"), ESP.getFlashChipSpeed());
|
||||
PRINT(PSTR("Sketch size: %" PRIu32 "\n"), ESP.getSketchSize());
|
||||
PRINT(PSTR("Free sketch space: %" PRIu32 "\n"), ESP.getFreeSketchSpace());
|
||||
#endif
|
||||
while (true) {
|
||||
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("MCU:\n\n"
|
||||
"[Dx] Read PIN\n"
|
||||
"[Sx] Set PIN\n"
|
||||
"[Rx] Reset PIN\n"
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
"[W] WDT\n"
|
||||
#endif
|
||||
"[Px] Sleep x ms\n"
|
||||
"[X] Exit\n"
|
||||
));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsFlushSerial();
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'D') {
|
||||
hwPinMode(inputParameter.toInt(), INPUT);
|
||||
PRINT(PSTR("PIN %" PRIu8 " = %" PRIu8 "\n"), inputParameter.toInt(),
|
||||
hwDigitalRead(inputParameter.toInt()));
|
||||
} else if (inputCmd == 'S') {
|
||||
PRINT(PSTR("SET PIN %" PRIu8 "\n"), inputParameter.toInt());
|
||||
hwPinMode(inputParameter.toInt(), OUTPUT);
|
||||
hwDigitalWrite(inputParameter.toInt(), HIGH);
|
||||
} else if (inputCmd == 'R') {
|
||||
PRINT(PSTR("CLR PIN %" PRIu8 "\n"), inputParameter.toInt());
|
||||
hwPinMode(inputParameter.toInt(), OUTPUT);
|
||||
hwDigitalWrite(inputParameter.toInt(), LOW);
|
||||
} else if (inputCmd == 'W') {
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
diagnosticsWatchdogTest();
|
||||
#endif
|
||||
} else if (inputCmd == 'P') {
|
||||
PRINT(PSTR("Sleeping %" PRIu32 "ms\n"), inputParameter.toInt());
|
||||
transportSleep();
|
||||
hwSleep((uint32_t)inputParameter.toInt());
|
||||
PRINT(PSTR("waking up\n"));
|
||||
transportStandBy();
|
||||
} else if (inputCmd == 'X') {
|
||||
return;
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("!CMD"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void diagnosticsMainMenu(void)
|
||||
{
|
||||
while (true) {
|
||||
diagnosticsPrintSeparationLine();
|
||||
MY_SERIALDEVICE.println(F("Main:\n\n"
|
||||
"[M] MCU\n"
|
||||
"[E] EEPROM\n"
|
||||
"[C] CRYPTO\n"
|
||||
"[R] Reboot\n"
|
||||
"[I] Info\n"
|
||||
|
||||
"[T] TSP SM\n"
|
||||
#if defined(MY_RADIO_RF24)
|
||||
"[2] RF24\n"
|
||||
#endif
|
||||
#if defined(MY_RADIO_RFM69) && defined(MY_RFM69_NEW_DRIVER)
|
||||
"[6] RFM69\n"
|
||||
#endif
|
||||
#if defined(MY_RADIO_RFM95)
|
||||
"[9] RFM95\n"
|
||||
#endif
|
||||
));
|
||||
diagnosticsPrintSeparationLine();
|
||||
diagnosticsFlushSerial();
|
||||
diagnosticsSerialInput();
|
||||
if (inputCmd == 'T') {
|
||||
diagnosticsTransportSM();
|
||||
} else if (inputCmd == 'E') {
|
||||
diagnosticsEEPROMMenu();
|
||||
} else if (inputCmd == 'C') {
|
||||
#if defined(MY_DIAGNOSTICS_CRYPTO)
|
||||
diagnosticsCryptoMenu();
|
||||
#else
|
||||
MY_SERIALDEVICE.println(F("> Define MY_DIAGNOSTICS_CRYPTO to enable"));
|
||||
#endif
|
||||
} else if (inputCmd == 'M') {
|
||||
diagnosticsMCUMenu();
|
||||
} else if (inputCmd == '2') {
|
||||
#if defined(MY_RADIO_RF24)
|
||||
diagnosticsRF24Menu();
|
||||
#endif
|
||||
} else if (inputCmd == '6') {
|
||||
#if defined(MY_RADIO_RFM69)
|
||||
diagnosticsRFM69Menu();
|
||||
#endif
|
||||
} else if (inputCmd == '9') {
|
||||
#if defined(MY_RADIO_RFM95)
|
||||
diagnosticsRFM95Menu();
|
||||
#endif
|
||||
} else if (inputCmd == 'R') {
|
||||
hwReboot();
|
||||
} else if (inputCmd == 'I') {
|
||||
MY_SERIALDEVICE.println(F("Press any key to exit\n"));
|
||||
hwRandomNumberInit();
|
||||
while (!MY_SERIALDEVICE.available()) {
|
||||
PRINT(PSTR("> T_CPU=%" PRIi8 ", V_CPU=%" PRIu16 ", RNG=%" PRIu8 "\n"),
|
||||
hwCPUTemperature(), hwCPUVoltage(), random(256));
|
||||
doYield();
|
||||
delay(100);
|
||||
}
|
||||
} else {
|
||||
MY_SERIALDEVICE.println(F("!CMD"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void diagnosticsRun(void)
|
||||
{
|
||||
MY_SERIALDEVICE.println(F("\nMySensors Diagnostics v1.0"));
|
||||
diagnosticsPrintSeparationLine();
|
||||
PRINT(PSTR("LIB: MySensors %s\n"), MYSENSORS_LIBRARY_VERSION);
|
||||
PRINT(PSTR("REL: %" PRIu8 "\n"), MYSENSORS_LIBRARY_VERSION_PRERELEASE_NUMBER);
|
||||
PRINT(PSTR("VER: %" PRIx32 "\n"), MYSENSORS_LIBRARY_VERSION_INT);
|
||||
PRINT(PSTR("CAP: %s\n"), MY_CAPABILITIES);
|
||||
diagnosticsMainMenu();
|
||||
}
|
||||
29
core/MyDiagnostics.h
Normal file
29
core/MyDiagnostics.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in RAM or EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2026 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyDiagnostics_h
|
||||
#define MyDiagnostics_h
|
||||
|
||||
/**
|
||||
* @brief Show diagnostics serial user interface
|
||||
*
|
||||
*/
|
||||
void diagnosticsRun(void);
|
||||
|
||||
#endif
|
||||
@@ -98,6 +98,11 @@ void _infiniteLoop(void)
|
||||
|
||||
void _begin(void)
|
||||
{
|
||||
#if defined(MY_DIAGNOSTICS)
|
||||
(void)hwInit();
|
||||
diagnosticsRun();
|
||||
_infiniteLoop();
|
||||
#endif
|
||||
#if defined(MY_CORE_ONLY)
|
||||
// initialize HW and run setup if present
|
||||
(void)hwInit();
|
||||
|
||||
28
examples/diagnostics_rf24/diagnostics_rf24.ino
Normal file
28
examples/diagnostics_rf24/diagnostics_rf24.ino
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2026 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*/
|
||||
#define MY_DEBUG
|
||||
#define MY_RADIO_RF24
|
||||
#define MY_DIAGNOSTICS
|
||||
|
||||
#include <MySensors.h>
|
||||
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
29
examples/diagnostics_rfm69/diagnostics_rfm69.ino
Normal file
29
examples/diagnostics_rfm69/diagnostics_rfm69.ino
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2026 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*/
|
||||
#define MY_DEBUG
|
||||
#define MY_RADIO_RFM69
|
||||
#define MY_RFM69_NEW_DRIVER
|
||||
#define MY_DIAGNOSTICS
|
||||
|
||||
#include <MySensors.h>
|
||||
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
28
examples/diagnostics_rfm95/diagnostics_rfm95.ino
Normal file
28
examples/diagnostics_rfm95/diagnostics_rfm95.ino
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2026 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*/
|
||||
#define MY_DEBUG
|
||||
#define MY_RADIO_RFM95
|
||||
#define MY_DIAGNOSTICS
|
||||
|
||||
#include <MySensors.h>
|
||||
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* Arduino core for ESP32: https://github.com/espressif/arduino-esp32
|
||||
*
|
||||
* MySensors ESP32 implementation, Copyright (C) 2017-2018 Olivier Mauti <olivier@mysensors.org>
|
||||
* MySensors ESP32 implementation, Copyright (C) 2017-2026 Olivier Mauti <olivier@mysensors.org>
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -142,8 +142,16 @@ int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t inte
|
||||
|
||||
uint16_t hwCPUVoltage(void)
|
||||
{
|
||||
// in mV
|
||||
return FUNCTION_NOT_SUPPORTED;
|
||||
// experimental, not documented feature and inaccurate?
|
||||
uint16_t internalBatReading;
|
||||
if (WiFi.status() == 255) {
|
||||
btStart();
|
||||
internalBatReading = rom_phy_get_vdd33();
|
||||
btStop();
|
||||
} else {
|
||||
internalBatReading = rom_phy_get_vdd33();
|
||||
}
|
||||
return internalBatReading;
|
||||
}
|
||||
|
||||
uint16_t hwCPUFrequency(void)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* Arduino core for ESP32: https://github.com/espressif/arduino-esp32
|
||||
*
|
||||
* MySensors ESP32 implementation, Copyright (C) 2017-2018 Olivier Mauti <olivier@mysensors.org>
|
||||
* MySensors ESP32 implementation, Copyright (C) 2017-2026 Olivier Mauti <olivier@mysensors.org>
|
||||
*
|
||||
* Radio wiring ESP32(Node32s): RF24, RFM69, RFM95:
|
||||
*
|
||||
@@ -76,6 +76,9 @@
|
||||
#define hwRandomNumberInit() randomSeed(esp_random())
|
||||
#define hwGetSleepRemaining() (0ul)
|
||||
|
||||
// experimental, not documented feature
|
||||
extern "C" int rom_phy_get_vdd33();
|
||||
|
||||
bool hwInit(void);
|
||||
void hwReadConfigBlock(void *buf, void *addr, size_t length);
|
||||
void hwWriteConfigBlock(void *buf, void *addr, size_t length);
|
||||
|
||||
@@ -127,13 +127,15 @@ LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd)
|
||||
LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd)
|
||||
{
|
||||
const uint8_t value = RF24_spiMultiByteTransfer(cmd, NULL, 1, true);
|
||||
RF24_DEBUG(PSTR("RF24:RBR:REG=%" PRIu8 ",VAL=%" PRIu8 "\n"), cmd & RF24_REGISTER_MASK, value);
|
||||
RF24_DEBUG(PSTR("RF24:RBR:REG=0x%02" PRIX8 ",VAL=0x%02" PRIX8 "\n"), cmd & RF24_REGISTER_MASK,
|
||||
value);
|
||||
return value;
|
||||
}
|
||||
|
||||
LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, uint8_t value)
|
||||
{
|
||||
RF24_DEBUG(PSTR("RF24:WBR:REG=%" PRIu8 ",VAL=%" PRIu8 "\n"), cmd & RF24_REGISTER_MASK, value);
|
||||
RF24_DEBUG(PSTR("RF24:WBR:REG=0x%02" PRIX8 ",VAL=0x%02" PRIX8 "\n"), cmd & RF24_REGISTER_MASK,
|
||||
value);
|
||||
return RF24_spiMultiByteTransfer( cmd, &value, 1, false);
|
||||
}
|
||||
|
||||
@@ -161,7 +163,12 @@ LOCAL uint8_t RF24_getFIFOStatus(void)
|
||||
|
||||
LOCAL void RF24_setChannel(const uint8_t channel)
|
||||
{
|
||||
RF24_writeByteRegister(RF24_REG_RF_CH,channel);
|
||||
RF24_writeByteRegister(RF24_REG_RF_CH, channel);
|
||||
}
|
||||
|
||||
LOCAL uint8_t RF24_getChannel(void)
|
||||
{
|
||||
return RF24_readByteRegister(RF24_REG_RF_CH);
|
||||
}
|
||||
|
||||
LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount)
|
||||
@@ -211,6 +218,11 @@ LOCAL void RF24_setDynamicPayload(const uint8_t pipe)
|
||||
RF24_writeByteRegister(RF24_REG_DYNPD, pipe);
|
||||
}
|
||||
|
||||
LOCAL uint8_t RF24_getRFConfiguration(void)
|
||||
{
|
||||
return RF24_readByteRegister(RF24_REG_NRF_CONFIG);
|
||||
}
|
||||
|
||||
LOCAL void RF24_setRFConfiguration(const uint8_t configuration)
|
||||
{
|
||||
RF24_writeByteRegister(RF24_REG_NRF_CONFIG, configuration);
|
||||
@@ -400,10 +412,15 @@ LOCAL bool RF24_sanityCheck(void)
|
||||
return (RF24_readByteRegister(RF24_REG_RF_SETUP) == RF24_RF_SETUP) && (RF24_readByteRegister(
|
||||
RF24_REG_RF_CH) == MY_RF24_CHANNEL);
|
||||
}
|
||||
|
||||
LOCAL uint8_t RF24_getRawTxPowerLevel(void)
|
||||
{
|
||||
return (RF24_readByteRegister(RF24_REG_RF_SETUP) >> 1) & 3;
|
||||
}
|
||||
LOCAL int16_t RF24_getTxPowerLevel(void)
|
||||
{
|
||||
// in dBm
|
||||
return (int16_t)((-6) * (3-((RF24_readByteRegister(RF24_REG_RF_SETUP) >> 1) & 3)));
|
||||
return (int16_t)((-6) * (3 - RF24_getRawTxPowerLevel()));
|
||||
}
|
||||
|
||||
LOCAL uint8_t RF24_getTxPowerPercent(void)
|
||||
|
||||
@@ -177,8 +177,9 @@ LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value)
|
||||
|
||||
// helper macros
|
||||
#define RF24_readByteRegister(__reg) RF24_RAW_readByteRegister(RF24_CMD_READ_REGISTER | (RF24_REGISTER_MASK & (__reg))) //!< RF24_readByteRegister
|
||||
#define RF24_readMultiByteRegister(__reg,__buf,__len) RF24_spiMultiByteTransfer(RF24_CMD_READ_REGISTER | (RF24_REGISTER_MASK & (__reg)), (uint8_t *)__buf, __len, true) //!< RF24_readMultiByteRegister
|
||||
#define RF24_writeByteRegister(__reg,__value) RF24_RAW_writeByteRegister(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)), __value) //!< RF24_writeByteRegister
|
||||
#define RF24_writeMultiByteRegister(__reg,__buf,__len) RF24_spiMultiByteTransfer(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)),(uint8_t *)__buf, __len,false) //!< RF24_writeMultiByteRegister
|
||||
#define RF24_writeMultiByteRegister(__reg,__buf,__len) RF24_spiMultiByteTransfer(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)), (uint8_t *)__buf, __len, false) //!< RF24_writeMultiByteRegister
|
||||
|
||||
/**
|
||||
* @brief RF24_flushRX
|
||||
@@ -278,6 +279,11 @@ LOCAL bool RF24_initialize(void);
|
||||
*/
|
||||
LOCAL void RF24_setChannel(const uint8_t channel);
|
||||
/**
|
||||
* @brief RF24_getChannel
|
||||
* @return channel
|
||||
*/
|
||||
LOCAL uint8_t RF24_getChannel(void) __attribute__((unused));
|
||||
/**
|
||||
* @brief RF24_setRetries
|
||||
* @param retransmitDelay
|
||||
* @param retransmitCount
|
||||
@@ -319,6 +325,11 @@ LOCAL void RF24_setAutoACK(const uint8_t pipe);
|
||||
*/
|
||||
LOCAL void RF24_setDynamicPayload(const uint8_t pipe);
|
||||
/**
|
||||
* @brief RF24_getRFConfiguration
|
||||
* @return RF configuration
|
||||
*/
|
||||
LOCAL uint8_t RF24_getRFConfiguration(void) __attribute__((unused));
|
||||
/**
|
||||
* @brief RF24_setRFConfiguration
|
||||
* @param configuration
|
||||
*/
|
||||
@@ -357,8 +368,13 @@ LOCAL void RF24_enableFeatures(void);
|
||||
*/
|
||||
LOCAL uint8_t RF24_getTxPowerPercent(void);
|
||||
/**
|
||||
* @brief RF24_getRawTxPowerLevel
|
||||
* @return power level
|
||||
*/
|
||||
LOCAL uint8_t RF24_getRawTxPowerLevel(void);
|
||||
/**
|
||||
* @brief RF24_getTxPowerLevel
|
||||
* @return
|
||||
* @return power level in pseudo-dBm
|
||||
*/
|
||||
LOCAL int16_t RF24_getTxPowerLevel(void);
|
||||
/**
|
||||
|
||||
@@ -425,6 +425,16 @@ LOCAL bool RFM69_send(const uint8_t recipient, uint8_t *data, const uint8_t len,
|
||||
return RFM69_sendFrame(&packet, increaseSequenceCounter);
|
||||
}
|
||||
|
||||
LOCAL uint32_t RFM69_getFrequency(void)
|
||||
{
|
||||
uint32_t freqHz;
|
||||
freqHz = (uint32_t)RFM69_readReg(RFM69_REG_FRFMSB) << 16;
|
||||
freqHz |= RFM69_readReg(RFM69_REG_FRFMID) << 8;
|
||||
freqHz |= RFM69_readReg(RFM69_REG_FRFLSB);
|
||||
freqHz *= RFM69_FSTEP;
|
||||
return freqHz;
|
||||
}
|
||||
|
||||
LOCAL void RFM69_setFrequency(const uint32_t frequencyHz)
|
||||
{
|
||||
const uint32_t freqHz = (uint32_t)(frequencyHz / RFM69_FSTEP);
|
||||
|
||||
@@ -410,6 +410,11 @@ LOCAL bool RFM69_sendFrame(rfm69_packet_t *packet, const bool increaseSequenceCo
|
||||
LOCAL bool RFM69_send(const uint8_t recipient, uint8_t *data, const uint8_t len,
|
||||
const rfm69_controlFlags_t flags, const bool increaseSequenceCounter = true);
|
||||
|
||||
/**
|
||||
* @brief Gets the transmitter and receiver center frequency
|
||||
* @return frequencyHz Frequency in Hz
|
||||
*/
|
||||
LOCAL uint32_t RFM69_getFrequency(void) __attribute__((unused));
|
||||
/**
|
||||
* @brief Sets the transmitter and receiver center frequency
|
||||
* @param frequencyHz Frequency in Hz
|
||||
|
||||
@@ -86,6 +86,8 @@ MY_DEBUG LITERAL1
|
||||
MY_DEBUGDEVICE LITERAL1
|
||||
MY_DEBUG_VERBOSE_GATEWAY LITERAL1
|
||||
MY_SPECIAL_DEBUG LITERAL1
|
||||
MY_DIAGNOSTICS LITERAL1
|
||||
MY_DIAGNOSTICS_CRYPTO LITERAL1
|
||||
|
||||
# OTA
|
||||
MY_DEBUG_OTA LITERAL1
|
||||
|
||||
Reference in New Issue
Block a user