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

/*
* 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