You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
8.2 KiB
309 lines
8.2 KiB
/* |
|
* EEZ Generic Firmware |
|
* Copyright (C) 2018-present, Envox d.o.o. |
|
* |
|
* This program is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, either version 3 of the License, or |
|
* (at your option) any later version. |
|
|
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
|
|
* You should have received a copy of the GNU General Public License |
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
#include <string.h> |
|
|
|
#include <eez/core/unit.h> |
|
|
|
#if OPTION_SCPI |
|
#include <scpi/types.h> |
|
#endif |
|
|
|
namespace eez { |
|
|
|
const char *g_unitNames[] = { |
|
"", // UNIT_NONE |
|
"V", // UNIT_VOLT |
|
"mV", // UNIT_MILLI_VOLT |
|
"A", // UNIT_AMPER |
|
"mA", // UNIT_MILLI_AMPER |
|
"uA", // UNIT_MICRO_AMPER |
|
"W", // UNIT_WATT |
|
"mW", // UNIT_MILLI_WATT |
|
"s", // UNIT_SECOND |
|
"ms", // UNIT_MILLI_SECOND |
|
DEGREE_SYMBOL"C", // UNIT_CELSIUS |
|
"rpm", // UNIT_RPM |
|
"\xb4", // UNIT_OHM |
|
"K\xb4", // UNIT_KOHM |
|
"M\xb4", // UNIT_MOHM |
|
"%", // UNIT_PERCENT |
|
"Hz", // UNIT_HERTZ |
|
"mHz", // UNIT_MILLI_HERTZ |
|
"KHz", // UNIT_KHERTZ |
|
"MHz", // UNIT_MHERTZ |
|
"J", // UNIT_JOULE |
|
"F", // UNIT_FARAD |
|
"mF", // UNIT_MILLI_FARAD |
|
"uF", // UNIT_MICRO_FARAD |
|
"nF", // UNIT_NANO_FARAD |
|
"pF", // UNIT_PICO_FARAD |
|
"minutes", // UNIT_MINUTE |
|
"VA", // UNIT_VOLT_AMPERE |
|
"VAR", // UNIT_VOLT_AMPERE_REACTIVE |
|
DEGREE_SYMBOL, // UNIT_DEGREE |
|
"Vpp", // UNIT_VOLT_PP |
|
"mVpp", // UNIT_MILLI_VOLT_PP |
|
"App", // UNIT_AMPER_PP |
|
"mApp", // UNIT_MILLI_AMPER_PP |
|
"uApp", // UNIT_MICRO_AMPER_PP |
|
}; |
|
|
|
const Unit g_baseUnit[] = { |
|
UNIT_NONE, // UNIT_NONE |
|
UNIT_VOLT, // UNIT_VOLT |
|
UNIT_VOLT, // UNIT_MILLI_VOLT |
|
UNIT_AMPER, // UNIT_AMPER |
|
UNIT_AMPER, // UNIT_MILLI_AMPER |
|
UNIT_AMPER, // UNIT_MICRO_AMPER |
|
UNIT_WATT, // UNIT_WATT |
|
UNIT_WATT, // UNIT_MILLI_WATT |
|
UNIT_SECOND, // UNIT_SECOND |
|
UNIT_SECOND, // UNIT_MILLI_SECOND |
|
UNIT_CELSIUS, // UNIT_CELSIUS |
|
UNIT_RPM, // UNIT_RPM |
|
UNIT_OHM, // UNIT_OHM |
|
UNIT_OHM, // UNIT_KOHM |
|
UNIT_OHM, // UNIT_MOHM |
|
UNIT_PERCENT, // UNIT_PERCENT |
|
UNIT_HERTZ, // UNIT_HERTZ |
|
UNIT_HERTZ, // UNIT_MILLI_HERTZ |
|
UNIT_HERTZ, // UNIT_KHERTZ |
|
UNIT_HERTZ, // UNIT_MHERTZ |
|
UNIT_JOULE, // UNIT_JOULE |
|
UNIT_FARAD, // UNIT_FARAD |
|
UNIT_FARAD, // UNIT_MILLI_FARAD |
|
UNIT_FARAD, // UNIT_MICRO_FARAD |
|
UNIT_FARAD, // UNIT_NANO_FARAD |
|
UNIT_FARAD, // UNIT_PICO_FARAD |
|
UNIT_SECOND, // UNIT_MINUTE |
|
UNIT_VOLT_AMPERE, // UNIT_VOLT_AMPERE |
|
UNIT_VOLT_AMPERE, //UNIT_VOLT_AMPERE_REACTIVE |
|
UNIT_DEGREE, // UNIT_DEGREE |
|
UNIT_VOLT_PP, // UNIT_VOLT_PP |
|
UNIT_VOLT_PP, // UNIT_MILLI_VOLT_PP |
|
UNIT_AMPER_PP, // UNIT_AMPER_PP |
|
UNIT_AMPER_PP, // UNIT_MILLI_AMPER_PP |
|
UNIT_AMPER_PP, // UNIT_MICRO_AMPER_PP |
|
}; |
|
|
|
const float g_unitFactor[] = { |
|
1.0f, // UNIT_NONE |
|
1.0f, // UNIT_VOLT |
|
1E-3f, // UNIT_MILLI_VOLT |
|
1.0f, // UNIT_AMPER |
|
1E-3f, // UNIT_MILLI_AMPER |
|
1E-6f, // UNIT_MICRO_AMPER |
|
1.0f, // UNIT_WATT |
|
1E-3f, // UNIT_MILLI_WATT |
|
1.0f, // UNIT_SECOND |
|
1E-3f, // UNIT_MILLI_SECOND |
|
1.0f, // UNIT_CELSIUS |
|
1.0f, // UNIT_RPM |
|
1.0f, // UNIT_OHM |
|
1E3f, // UNIT_KOHM |
|
1E6f, // UNIT_MOHM |
|
1.0f, // UNIT_PERCENT |
|
1.0f, // UNIT_HERTZ |
|
1E-3f, // UNIT_MILLI_HERTZ |
|
1E3f, // UNIT_KHERTZ |
|
1E6f, // UNIT_MHERTZ |
|
1.0f, // UNIT_JOULE |
|
1.0f, // UNIT_FARAD |
|
1E-3f, // UNIT_MILLI_FARAD |
|
1E-6f, // UNIT_MICRO_FARAD |
|
1E-9f, // UNIT_NANO_FARAD |
|
1E-12f, // UNIT_PICO_FARAD |
|
60.0f, // UNIT_MINUTE |
|
1.0f, // UNIT_VOLT_AMPERE |
|
1.0f, //UNIT_VOLT_AMPERE_REACTIVE |
|
1.0f, // UNIT_DEGREE |
|
1.0f, // UNIT_VOLT_PP |
|
1E-3f, // UNIT_MILLI_VOLT_PP |
|
1.0f, // UNIT_AMPER_PP |
|
1E-3f, // UNIT_MILLI_AMPER_PP |
|
1E-6f, // UNIT_MICRO_AMPER_PP |
|
}; |
|
|
|
#if OPTION_SCPI |
|
static const int g_scpiUnits[] = { |
|
SCPI_UNIT_NONE, // UNIT_NONE |
|
SCPI_UNIT_VOLT, // UNIT_VOLT |
|
SCPI_UNIT_VOLT, // UNIT_MILLI_VOLT |
|
SCPI_UNIT_AMPER, // UNIT_AMPER |
|
SCPI_UNIT_AMPER, // UNIT_MILLI_AMPER |
|
SCPI_UNIT_AMPER, // UNIT_MICRO_AMPER |
|
SCPI_UNIT_WATT, // UNIT_WATT |
|
SCPI_UNIT_WATT, // UNIT_MILLI_WATT |
|
SCPI_UNIT_SECOND, // UNIT_SECOND |
|
SCPI_UNIT_SECOND, // UNIT_MILLI_SECOND |
|
SCPI_UNIT_CELSIUS, // UNIT_CELSIUS |
|
SCPI_UNIT_NONE, // UNIT_RPM |
|
SCPI_UNIT_OHM, // UNIT_OHM |
|
SCPI_UNIT_OHM, // UNIT_KOHM |
|
SCPI_UNIT_OHM, // UNIT_MOHM |
|
SCPI_UNIT_NONE, // UNIT_PERCENT |
|
SCPI_UNIT_HERTZ, // UNIT_HERTZ |
|
SCPI_UNIT_HERTZ, // UNIT_MILLI_HERTZ |
|
SCPI_UNIT_HERTZ, // UNIT_KHERTZ |
|
SCPI_UNIT_HERTZ, // UNIT_MHERTZ |
|
SCPI_UNIT_JOULE, // UNIT_JOULE |
|
SCPI_UNIT_FARAD, // UNIT_FARAD |
|
SCPI_UNIT_FARAD, // UNIT_MILLI_FARAD |
|
SCPI_UNIT_FARAD, // UNIT_MICRO_FARAD |
|
SCPI_UNIT_FARAD, // UNIT_NANO_FARAD |
|
SCPI_UNIT_FARAD, // UNIT_PICO_FARAD |
|
SCPI_UNIT_SECOND, // UNIT_MINUTE |
|
SCPI_UNIT_WATT, // UNIT_VOLT_AMPERE |
|
SCPI_UNIT_WATT, // UNIT_VOLT_AMPERE_REACTIVE |
|
SCPI_UNIT_DEGREE, // UNIT_DEGREE |
|
SCPI_UNIT_VOLT, // UNIT_VOLT_PP |
|
SCPI_UNIT_VOLT, // UNIT_MILLI_VOLT_PP |
|
SCPI_UNIT_AMPER, // UNIT_AMPER_PP |
|
SCPI_UNIT_AMPER, // UNIT_MILLI_AMPER_PP |
|
SCPI_UNIT_AMPER, // UNIT_MICRO_AMPER_PP |
|
}; |
|
#endif |
|
|
|
Unit getUnitFromName(const char *unitName) { |
|
if (unitName) { |
|
for (unsigned i = 0; i < sizeof(g_unitNames) / sizeof(const char *); i++) { |
|
if (strcmp(g_unitNames[i], unitName) == 0) { |
|
return (Unit)i; |
|
} |
|
} |
|
} |
|
return UNIT_NONE; |
|
} |
|
|
|
#if OPTION_SCPI |
|
int getScpiUnit(Unit unit) { |
|
if (unit == UNIT_UNKNOWN) { |
|
return SCPI_UNIT_NONE; |
|
} |
|
return g_scpiUnits[unit]; |
|
} |
|
#endif |
|
|
|
Unit getBaseUnit(Unit unit) { |
|
if (unit == UNIT_UNKNOWN) { |
|
return UNIT_UNKNOWN; |
|
} |
|
return g_baseUnit[unit]; |
|
} |
|
|
|
float getUnitFactor(Unit unit) { |
|
if (unit == UNIT_UNKNOWN) { |
|
return 1.0f; |
|
} |
|
return g_unitFactor[unit]; |
|
} |
|
|
|
static Unit getDerivedUnit(Unit unit, float factor) { |
|
if (unit == UNIT_UNKNOWN) { |
|
return UNIT_UNKNOWN; |
|
} |
|
|
|
for (size_t i = 0; i < sizeof(g_baseUnit); i++) { |
|
if (g_baseUnit[i] == g_baseUnit[unit] && g_unitFactor[i] == factor) { |
|
return (Unit)i; |
|
} |
|
} |
|
|
|
return UNIT_UNKNOWN; |
|
} |
|
|
|
static const float FACTORS[] = { 1E-12F, 1E-9F, 1E-6F, 1E-3F, 1E0F, 1E3F, 1E6F, 1E9F, 1E12F }; |
|
|
|
Unit findDerivedUnit(float value, Unit unit) { |
|
Unit result; |
|
|
|
for (int factorIndex = 1; ; factorIndex++) { |
|
float factor = FACTORS[factorIndex]; |
|
if (factor > 1.0F) { |
|
break; |
|
} |
|
if (value < factor) { |
|
result = getDerivedUnit(unit, FACTORS[factorIndex - 1]); |
|
if (result != UNIT_UNKNOWN) { |
|
return result; |
|
} |
|
} |
|
} |
|
|
|
for (int factorIndex = sizeof(FACTORS) / sizeof(float) - 1; factorIndex >= 0; factorIndex--) { |
|
float factor = FACTORS[factorIndex]; |
|
if (factor == 1.0F) { |
|
break; |
|
} |
|
if (value >= factor) { |
|
result = getDerivedUnit(unit, factor); |
|
if (result != UNIT_UNKNOWN) { |
|
return result; |
|
} |
|
} |
|
} |
|
|
|
return unit; |
|
} |
|
|
|
float getSmallerFactor(float factor) { |
|
for (int factorIndex = sizeof(FACTORS) / sizeof(float) - 1; factorIndex > 0; factorIndex--) { |
|
float itFactor = FACTORS[factorIndex]; |
|
if (itFactor < factor) { |
|
return itFactor; |
|
} |
|
} |
|
return FACTORS[0]; |
|
} |
|
|
|
Unit getSmallerUnit(Unit unit, float min, float precision) { |
|
float factor = getUnitFactor(unit); |
|
if (precision <= factor || min <= factor) { |
|
return getDerivedUnit(unit, getSmallerFactor(factor)); |
|
} |
|
return UNIT_UNKNOWN; |
|
} |
|
|
|
Unit getBiggestUnit(Unit unit, float max) { |
|
for (int factorIndex = sizeof(FACTORS) / sizeof(float) - 1; factorIndex >= 0; factorIndex--) { |
|
float factor = FACTORS[factorIndex]; |
|
if (max >= factor) { |
|
auto result = getDerivedUnit(unit, factor); |
|
if (result != UNIT_UNKNOWN) { |
|
return result; |
|
} |
|
} |
|
} |
|
return UNIT_UNKNOWN; |
|
} |
|
|
|
Unit getSmallestUnit(Unit unit, float min, float precision) { |
|
for (int factorIndex = 0; factorIndex < int(sizeof(FACTORS) / sizeof(float)); factorIndex++) { |
|
float factor = FACTORS[factorIndex]; |
|
if (precision <= factor || min <= factor) { |
|
auto result = getDerivedUnit(unit, factor); |
|
if (result != UNIT_UNKNOWN) { |
|
return result; |
|
} |
|
} |
|
} |
|
return UNIT_UNKNOWN; |
|
} |
|
|
|
} // namespace eez
|
|
|