2020-09-15 14:03:07 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2020 <janvi@veith.net>
|
2021-02-12 00:47:08 +00:00
|
|
|
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
2020-09-15 14:03:07 +00:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2021-10-05 15:17:29 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2020-09-15 14:03:07 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* E-Values derived from a geometric sequence formula by Charles Renard were already
|
|
|
|
* accepted and widely used before the ISO recommendation no. 3 has been published.
|
|
|
|
* For this historical reason, rounding rules of some values are sometimes irregular.
|
|
|
|
* Although all E-Values could be calculated at runtime, we initialize them in a lookup table
|
|
|
|
* what seems the most easy way to consider any inconvenient irregular rules. Same table is
|
2021-06-09 19:32:58 +00:00
|
|
|
* also used to lookup non calculable but readable BOM value strings. Supported E-series are:
|
2020-09-15 14:03:07 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
enum { E1, E3, E6, E12 };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This calculator suggests solutions for 2R, 3R and 4R replacement combinations
|
|
|
|
*/
|
|
|
|
|
|
|
|
enum { S2R, S3R, S4R };
|
|
|
|
|
|
|
|
/**
|
2021-01-24 19:41:43 +00:00
|
|
|
* 6 decade E-series values from 10 Ohms to 1M and its associated BOM strings.
|
2020-09-15 14:03:07 +00:00
|
|
|
* Series E3,E6,E12 are defined by additional values for cumulative use with previous series
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define E1_VAL { true, "1K", 1000 },\
|
|
|
|
{ true, "10K", 10000 },\
|
|
|
|
{ true, "100K", 100000 },\
|
|
|
|
{ true, "10R", 10 },\
|
|
|
|
{ true, "100R", 100 },\
|
|
|
|
{ true, "1M", 1000000 }
|
|
|
|
|
|
|
|
#define E3_ADD { true, "22R", 22 },\
|
|
|
|
{ true, "47R", 47 },\
|
|
|
|
{ true, "220R", 220 },\
|
|
|
|
{ true, "470R", 470 },\
|
|
|
|
{ true, "2K2", 2200 },\
|
|
|
|
{ true, "4K7", 4700 },\
|
|
|
|
{ true, "22K", 22000 },\
|
|
|
|
{ true, "47K", 47000 },\
|
|
|
|
{ true, "220K", 220000 },\
|
|
|
|
{ true, "470K", 470000 }
|
|
|
|
|
|
|
|
#define E6_ADD { true, "15R", 15 },\
|
|
|
|
{ true, "33R", 33 },\
|
|
|
|
{ true, "68R", 68 },\
|
|
|
|
{ true, "150R", 150 },\
|
|
|
|
{ true, "330R", 330 },\
|
|
|
|
{ true, "680R", 680 },\
|
|
|
|
{ true, "1K5", 1500 },\
|
|
|
|
{ true, "3K3", 3300 },\
|
|
|
|
{ true, "6K8", 6800 },\
|
|
|
|
{ true, "15K", 15000 },\
|
|
|
|
{ true, "33K", 33000 },\
|
|
|
|
{ true, "68K", 68000 },\
|
|
|
|
{ true, "150K", 150000 },\
|
|
|
|
{ true, "330K", 330000 },\
|
|
|
|
{ true, "680K", 680000 }
|
|
|
|
|
|
|
|
#define E12_ADD { true, "12R", 12 },\
|
|
|
|
{ true, "18R", 18 },\
|
|
|
|
{ true, "27R", 27 },\
|
|
|
|
{ true, "39R", 39 },\
|
|
|
|
{ true, "56R", 56 },\
|
|
|
|
{ true, "82R", 82 },\
|
|
|
|
{ true, "120R", 120 },\
|
|
|
|
{ true, "180R", 180 },\
|
|
|
|
{ true, "270R", 270 },\
|
|
|
|
{ true, "390R", 390 },\
|
|
|
|
{ true, "560R", 560 },\
|
|
|
|
{ true, "820R", 820 },\
|
|
|
|
{ true, "1K2", 1200 },\
|
|
|
|
{ true, "1K8", 1800 },\
|
|
|
|
{ true, "2K7", 2700 },\
|
|
|
|
{ true, "3K9", 3900 },\
|
|
|
|
{ true, "5K6", 5600 },\
|
|
|
|
{ true, "8K2", 8200 },\
|
|
|
|
{ true, "12K", 12000 },\
|
|
|
|
{ true, "18K", 18000 },\
|
|
|
|
{ true, "27K", 27000 },\
|
|
|
|
{ true, "39K", 39000 },\
|
|
|
|
{ true, "56K", 56000 },\
|
|
|
|
{ true, "82K", 82000 },\
|
|
|
|
{ true, "120K", 120000 },\
|
|
|
|
{ true, "180K", 180000 },\
|
|
|
|
{ true, "270K", 270000 },\
|
|
|
|
{ true, "390K", 390000 },\
|
|
|
|
{ true, "560K", 560000 },\
|
|
|
|
{ true, "820K", 820000 }
|
|
|
|
|
2021-10-04 11:05:51 +00:00
|
|
|
struct R_DATA
|
|
|
|
{
|
|
|
|
bool e_use;
|
|
|
|
std::string e_name;
|
|
|
|
double e_value;
|
|
|
|
};
|
2020-09-15 14:03:07 +00:00
|
|
|
|
2021-10-04 11:05:51 +00:00
|
|
|
class E_SERIE
|
2020-09-15 14:03:07 +00:00
|
|
|
{
|
2021-02-12 00:47:08 +00:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* If any value of the selected E-serie not available, it can be entered as an exclude value.
|
|
|
|
*
|
|
|
|
* @param aValue is the value to exclude from calculation
|
|
|
|
* Values to exclude are set to false in the selected E-serie source lookup table
|
|
|
|
*/
|
|
|
|
void Exclude( double aValue );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* initialize next calculation and erase results from previous calculation
|
|
|
|
*/
|
|
|
|
void NewCalc( void );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* called on calculate button to execute all the 2R, 3R and 4R calculations
|
|
|
|
*/
|
|
|
|
void Calculate( void );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interface for CheckBox, RadioButton, RequriedResistor and calculated Results
|
|
|
|
*/
|
|
|
|
void SetSeries( uint32_t aSeries ) { m_series = aSeries; }
|
|
|
|
void SetRequiredValue( double aValue ) { m_required_value = aValue; }
|
|
|
|
|
2021-10-04 11:05:51 +00:00
|
|
|
std::array<R_DATA,S4R+1> GetResults( void ) { return m_results; }
|
2021-02-12 00:47:08 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Build all 2R combinations from the selected E-serie values
|
|
|
|
*
|
|
|
|
* Pre-calculated value combinations are saved in intermediate look up table m_cmb_lut
|
|
|
|
* @return is the number of found combinations what also depends from exclude values
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
uint32_t combine2( void );
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
/**
|
|
|
|
* Search for closest two component solution
|
|
|
|
*
|
|
|
|
* @param aSize is the number of valid 2R combinations in m_cmb_lut on where to search
|
|
|
|
* The 2R result with smallest deviation will be saved in results
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
void simple_solution( uint32_t aSize );
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
/**
|
|
|
|
* Check if there is a better 3 R solution than previous one using only two components.
|
|
|
|
*
|
|
|
|
* @param aSize gives the number of available combinations to be checked inside m_cmb_lut
|
|
|
|
* Therefore m_cmb_lut is combinated with the primary E-serie look up table
|
|
|
|
* The 3R result with smallest deviation will be saved in results if better than 2R
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
void combine3( uint32_t aSize );
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
/**
|
|
|
|
* Check if there is a better four component solution.
|
|
|
|
*
|
|
|
|
* @param aSsize gives the number of 2R combinations to be checked inside m_cmb_lut
|
|
|
|
* Occupied calculation time depends from number of available E-serie values
|
|
|
|
* with the power of 4 why execution for E12 is conditional with 4R check box
|
|
|
|
* for the case the previously found 3R solution is already exact
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
void combine4( uint32_t aSize );
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
/*
|
|
|
|
* Strip redundant braces from three component result
|
|
|
|
*
|
|
|
|
* Example: R1+(R2+R3) become R1+R2+R3
|
|
|
|
* and R1|(R2|R3) become R1|R2|R3
|
|
|
|
* while R1+(R2|R3) or (R1+R2)|R3) remains untouched
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
void strip3( void );
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
/*
|
|
|
|
* Strip redundant braces from four component result
|
|
|
|
*
|
|
|
|
* Example: (R1+R2)+(R3+R4) become R1+R2+R3+R4
|
|
|
|
* and (R1|R2)|(R2|R3) become R1|R2|R3|R4
|
|
|
|
* while (R1+R2)|(R3+R4) remains untouched
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
void strip4( void );
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
private:
|
2021-10-04 11:05:51 +00:00
|
|
|
std::vector<std::vector<R_DATA>> m_luts
|
|
|
|
{
|
|
|
|
{ E1_VAL },
|
|
|
|
{ E1_VAL, E3_ADD },
|
|
|
|
{ E1_VAL, E3_ADD, E6_ADD },
|
|
|
|
{ E1_VAL, E3_ADD, E6_ADD, E12_ADD }
|
|
|
|
};
|
|
|
|
|
2021-02-12 00:47:08 +00:00
|
|
|
/*
|
|
|
|
* TODO: Manual array size calculation is dangerous. Unlike legacy ANSI-C Arrays
|
|
|
|
* std::array can not drop length param by providing aggregate init list up
|
|
|
|
* to C++17. Reserved array size should be 2*E12² of std::vector primary list.
|
|
|
|
* Exceeding memory limit 7442 will crash the calculator without any warnings !
|
|
|
|
* Compare to previous MAX_COMB macro for legacy ANSI-C array automatic solution
|
2021-10-04 11:05:51 +00:00
|
|
|
* #define E12_SIZE sizeof ( e12_lut ) / sizeof ( R_DATA )
|
2021-02-12 00:47:08 +00:00
|
|
|
* #define MAX_COMB (2 * E12_SIZE * E12_SIZE)
|
|
|
|
* 2 component combinations including redundant swappable terms are for the moment
|
|
|
|
* 72 combinations for E1
|
|
|
|
* 512 combinations for E3
|
|
|
|
* 1922 combinations for E6
|
|
|
|
* 7442 combinations for E12
|
|
|
|
*/
|
2020-09-15 14:03:07 +00:00
|
|
|
|
2021-10-04 11:05:51 +00:00
|
|
|
#define MAX_CMB 7442 // maximum combinations for E12
|
2020-09-15 14:03:07 +00:00
|
|
|
|
2021-10-04 11:05:51 +00:00
|
|
|
std::array<R_DATA, MAX_CMB> m_cmb_lut; // intermediate 2R combinations
|
|
|
|
std::array<R_DATA, S4R+1> m_results; // 2R, 3R and 4R results
|
|
|
|
uint32_t m_series = E6; // Radio Button State
|
2021-02-12 00:47:08 +00:00
|
|
|
uint32_t m_enable_4R = false; // Check Box 4R enable
|
2021-10-04 11:05:51 +00:00
|
|
|
double m_required_value = 0.0; // required Resistor
|
2020-09-15 14:03:07 +00:00
|
|
|
};
|