Consolidate FastPrecisePowf

This commit is contained in:
Theo Arends 2020-05-24 17:13:10 +02:00
parent 9e0637cc60
commit 3829265e6d
4 changed files with 30 additions and 69 deletions

View File

@ -327,30 +327,6 @@ int16_t MutichannelGasSensor::readR(void)
** Returns: ** Returns:
float value - concentration of the gas float value - concentration of the gas
*********************************************************************************************************/ *********************************************************************************************************/
float MutichannelGasSensor_pow(float a, float b)
{
// https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/
// calculate approximation with fraction of the exponent
int e = abs((int)b);
union {
double d;
int x[2];
} u = { a };
u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447);
u.x[0] = 0;
// exponentiation by squaring with the exponent's integer part
// double r = u.d makes everything much slower, not sure why
double r = 1.0;
while (e) {
if (e & 1) {
r *= a;
}
a *= a;
e >>= 1;
}
return r * u.d;
}
float MutichannelGasSensor::calcGas(int gas) float MutichannelGasSensor::calcGas(int gas)
{ {
@ -382,9 +358,9 @@ float MutichannelGasSensor::calcGas(int gas)
int An_1 = get_addr_dta(CH_VALUE_CO); int An_1 = get_addr_dta(CH_VALUE_CO);
int An_2 = get_addr_dta(CH_VALUE_NO2); int An_2 = get_addr_dta(CH_VALUE_NO2);
ratio0 = (float)An_0/(float)A0_0*(1023.0-A0_0)/(1023.0-An_0); ratio0 = (float)An_0/(float)A0_0*(1023.0f-A0_0)/(1023.0f-An_0);
ratio1 = (float)An_1/(float)A0_1*(1023.0-A0_1)/(1023.0-An_1); ratio1 = (float)An_1/(float)A0_1*(1023.0f-A0_1)/(1023.0f-An_1);
ratio2 = (float)An_2/(float)A0_2*(1023.0-A0_2)/(1023.0-An_2); ratio2 = (float)An_2/(float)A0_2*(1023.0f-A0_2)/(1023.0f-An_2);
} }
@ -394,42 +370,42 @@ float MutichannelGasSensor::calcGas(int gas)
{ {
case CO: case CO:
{ {
c = MutichannelGasSensor_pow(ratio1, -1.179)*4.385; //mod by jack c = pow(ratio1, -1.179f)*4.385f; //mod by jack
break; break;
} }
case NO2: case NO2:
{ {
c = MutichannelGasSensor_pow(ratio2, 1.007)/6.855; //mod by jack c = pow(ratio2, 1.007f)/6.855f; //mod by jack
break; break;
} }
case NH3: case NH3:
{ {
c = MutichannelGasSensor_pow(ratio0, -1.67)/1.47; //modi by jack c = pow(ratio0, -1.67f)/1.47f; //modi by jack
break; break;
} }
case C3H8: //add by jack case C3H8: //add by jack
{ {
c = MutichannelGasSensor_pow(ratio0, -2.518)*570.164; c = pow(ratio0, -2.518f)*570.164f;
break; break;
} }
case C4H10: //add by jack case C4H10: //add by jack
{ {
c = MutichannelGasSensor_pow(ratio0, -2.138)*398.107; c = pow(ratio0, -2.138f)*398.107f;
break; break;
} }
case GAS_CH4: //add by jack case GAS_CH4: //add by jack
{ {
c = MutichannelGasSensor_pow(ratio1, -4.363)*630.957; c = pow(ratio1, -4.363f)*630.957f;
break; break;
} }
case H2: //add by jack case H2: //add by jack
{ {
c = MutichannelGasSensor_pow(ratio1, -1.8)*0.73; c = pow(ratio1, -1.8f)*0.73f;
break; break;
} }
case C2H5OH: //add by jack case C2H5OH: //add by jack
{ {
c = MutichannelGasSensor_pow(ratio1, -1.552)*1.622; c = pow(ratio1, -1.552f)*1.622f;
break; break;
} }
default: default:
@ -630,7 +606,7 @@ float MutichannelGasSensor::getR0(unsigned char ch) // 0:CH3, 1:CO, 2:NO
default:; default:;
} }
float r = 56.0*(float)a/(1023.0-(float)a); float r = 56.0f*(float)a/(1023.0f-(float)a);
return r; return r;
} }
@ -661,7 +637,7 @@ float MutichannelGasSensor::getRs(unsigned char ch) // 0:CH3, 1:CO, 2:NO
default:; default:;
} }
float r = 56.0*(float)a/(1023.0-(float)a); float r = 56.0f*(float)a/(1023.0f-(float)a);
return r; return r;
} }

View File

@ -68,9 +68,13 @@
enum{CO, NO2, NH3, C3H8, C4H10, GAS_CH4, H2, C2H5OH}; enum{CO, NO2, NH3, C3H8, C4H10, GAS_CH4, H2, C2H5OH};
// FastPrecisePowf from tasmota/support_float.ino
extern float FastPrecisePowf(const float x, const float y);
class MutichannelGasSensor{ class MutichannelGasSensor{
private: private:
static inline float pow(float a, float b) { return FastPrecisePowf(a, b); }
int __version; int __version;
int __send_error; int __send_error;

View File

@ -35,36 +35,12 @@ uint16_t ESPKNXIP::data_to_2byte_uint(uint8_t *data)
return (uint16_t)((data[1] << 8) | data[2]); return (uint16_t)((data[1] << 8) | data[2]);
} }
float esp_knx_pow(float a, float b)
{
// https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/
// calculate approximation with fraction of the exponent
int e = abs((int)b);
union {
double d;
int x[2];
} u = { a };
u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447);
u.x[0] = 0;
// exponentiation by squaring with the exponent's integer part
// double r = u.d makes everything much slower, not sure why
double r = 1.0;
while (e) {
if (e & 1) {
r *= a;
}
a *= a;
e >>= 1;
}
return r * u.d;
}
float ESPKNXIP::data_to_2byte_float(uint8_t *data) float ESPKNXIP::data_to_2byte_float(uint8_t *data)
{ {
//uint8_t sign = (data[1] & 0b10000000) >> 7; //uint8_t sign = (data[1] & 0b10000000) >> 7;
uint8_t expo = (data[1] & 0b01111000) >> 3; uint8_t expo = (data[1] & 0b01111000) >> 3;
int16_t mant = ((data[1] & 0b10000111) << 8) | data[2]; int16_t mant = ((data[1] & 0b10000111) << 8) | data[2];
return 0.01f * mant * esp_knx_pow(2, expo); return 0.01f * mant * pow(2, expo);
} }
time_of_day_t ESPKNXIP::data_to_3byte_time(uint8_t *data) time_of_day_t ESPKNXIP::data_to_3byte_time(uint8_t *data)

View File

@ -397,6 +397,9 @@ typedef struct __callback_assignment
callback_id_t callback_id; callback_id_t callback_id;
} callback_assignment_t; } callback_assignment_t;
// FastPrecisePowf from tasmota/support_float.ino
extern float FastPrecisePowf(const float x, const float y);
class ESPKNXIP { class ESPKNXIP {
public: public:
ESPKNXIP(); ESPKNXIP();
@ -564,6 +567,8 @@ class ESPKNXIP {
callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id); callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id);
void __callback_delete_assignment(callback_assignment_id_t id); void __callback_delete_assignment(callback_assignment_id_t id);
static inline float pow(float a, float b) { return FastPrecisePowf(a, b); }
ESP8266WebServer *server; ESP8266WebServer *server;
address_t physaddr; address_t physaddr;