Реализация типа float24_t

Неа. Я не могу его скомпилировать без исправлений. Исправленный вариант для ESP32, который компилируется, но время выводить не будет:

#include "float24.h"

void printFloatE(const char *const str, const float &value, const uint8_t digits = 5) {
  char buf[16];
  Serial.print(str);
  Serial.print(" = ");
//  dtostre(value, buf, digits, DTOSTR_UPPERCASE); //undeclared here and below
  Serial.println(buf);
}

float kff[3][3] = { { 9.9237E-13, -1.2702E-09, 3.6321E-07 },
                    { -7.9330E-10, 3.7138E-06, 8.3755E-03 },
                    { 1.7514E-07, -8.0434E-04, -7.9905E-01 } };
float24_t kff24[3][3];


float calculatePressure(const uint16_t &nP, const uint16_t &nT) {

#if 0  
  cli();
  TCCR1A = 0;                          // Normal mode
  TCCR1B = (1 << CS11) | (1 << CS10);  // Prescaler = 64
  TCNT1 = 0;                           // сброс счётчика
#endif

  uint32_t usec = 0;  // надо исправить на uint64_t usec = esp_timer_get_time();, что-то заленился
  asm volatile ("nop\r\nnop\r\nnop");

  float fT = nT;
  float fT2 = fT * fT;
  float fP = nP;
  float fP2 = fP * fP;

  float a2 = kff[0][0] * fT2 + kff[0][1] * fT + kff[0][2];
  float a1 = kff[1][0] * fT2 + kff[1][1] * fT + kff[1][2];
  float a0 = kff[2][0] * fT2 + kff[2][1] * fT + kff[2][2];

  float result = a2 * fP2 + a1 * fP + a0;


  asm volatile ("nop\r\nnop\r\nnop");
  
#if 0
  TCCR1B = 0;  // stop timer
  sei();
  usec = TCNT1 * 4;
#endif  
  //usec = esp_timer_get_time() - usec; 

  Serial.print("duration: ");
  Serial.print(usec, 3);
  Serial.println(" usec");

  return result;
}

float24_t calculatePressure24(const uint16_t &nP, const uint16_t &nT) {
#if 0  
  cli();
  TCCR1A = 0;                          // Normal mode
  TCCR1B = (1 << CS11) | (1 << CS10);  // Prescaler = 64
  TCNT1 = 0;                           // сброс счётчика
#endif
  asm volatile ("nop\r\nnop\r\nnop");

uint32_t usec = 0;// надо исправить на uint64_t usec = esp_timer_get_time();, что-то заленился

  float24_t fT = nT;
  float24_t fT2 = fT * fT;
  float24_t fP = nP;
  float24_t fP2 = fP * fP;

  float24_t a2 = kff24[0][0] * fT2 + kff24[0][1] * fT + kff24[0][2];
  float24_t a1 = kff24[1][0] * fT2 + kff24[1][1] * fT + kff24[1][2];
  float24_t a0 = kff24[2][0] * fT2 + kff24[2][1] * fT + kff24[2][2];

  float24_t result = a2 * fP2 + a1 * fP + a0;

  asm volatile ("nop\r\nnop\r\nnop");
  
#if 0
  TCCR1B = 0;  // stop timer
  sei();
  usec = TCNT1 * 4;
#endif
  //usec = esp_timer_get_time() - usec; 

  Serial.print("duration: ");
  Serial.print(usec, 3);
  Serial.println(" usec");

  return result;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  for (uint8_t i = 0; i < 3; i++) {
    for (uint8_t j = 0; j < 3; j++) {
      kff24[i][j] = kff[i][j];
      char buf[16];
      //dtostre(kff24[i][j].asFloat(), buf, 5, DTOSTR_UPPERCASE);
      Serial.print(buf);
      Serial.print(" ");
    }
    Serial.println();
  }
  Serial.println();

  for (;;) {
    while (!Serial.available()) {}
    const uint16_t nP = Serial.parseInt();
    Serial.print("nP = ");
    Serial.println(nP);

    while (!Serial.available()) {}
    const uint16_t nT = Serial.parseInt();
    Serial.print("nT = ");
    Serial.println(nT);
    Serial.println();

    float press = calculatePressure(nP, nT);
    Serial.print("Press = ");
    Serial.println(press, 5);
    Serial.println();

    float24_t press24 = calculatePressure24(nP, nT);
    Serial.print("Press24 = ");
    Serial.println(press24.asFloat(), 5);
    Serial.println();
    Serial.println();
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

А, это ассемблер ЕСП32 такой вот. Вызовы методов вычисляются как смещения от чего-то. Там прибавляется каждый раз циферка разная - типа. указатель на разные методы получается. Я не знаю почему и кому в голову это пришло - сделать так.

Но если вы когда нибудь начнете читать даташыт на есп32 (Xtensa Instruction Set Architecture) у вас волосы дыбом встанут

А почему столько вызовов методов? Ну, как бы умножения, сложения, деления - это все вызовы методов. Которые компилятор причешет, если его попросить через -O2

ну скомпилировать-то всегда можно. Поддержка АВР в ИДЕ встроена по умолчанию, а плата для этого не нужна

Попробовал, скомпилировал. Но в ассемблер назад не могу превратить. avr-objdump -d ничего не делает.

Запустил Ghidra, та тоже - а для какого AVR код? А я откуда знаю. Arduino Uno. Не декомпилируется с дефолтовыми настройками.

Странные у Вас результаты тестирования.
То есть не важно, правильно считается или нет, важно только, чтобы побыстрее?
Я бы все-таки начал с оценки погрешности, а также с проверки, накапливается она или нет.
Возьмите кубик с неединичной гранью. Возьмите ортонормированный базис, вектора которого не параллельны сторонам кубика, а начало координат не совпадает с его центром. Повращайте кубик на угол порядка 0.5-1.0 градуса поочередно вокруг каждой из осей базиса. Шагов так порядка 1000-10000.
Проделайте это как для float, так и для float24_t, после чего сравните получившиеся координаты.
Если результаты устроят, можно двигаться дальше.
Только не забывайте повторять этот тест после каждого изменения исходников.

Удобнее умножать/делить на 2, 4, 8, 16, 32…

Чтобы скомпилировать под AVR, совершенно необязательно иметь его в железе.

Компилятор воле поступать, как ему заблагорассудится.
Но, как правило, оптимизация в этом случае сводится лишь к двум вариантам:

  • фрагмент помещается в листинг,
  • фрагмент выкидывается из листинга.

Ассемблерный код мне сгенерировать удалось, но весь он сюда не влезает. Как его показать?

Точность получилась около 5 знаков. Вот сравнение вычислений с float и float24_t

nP = 215
nT = 700

duration: 12111 usec
Press = 0.99798

duration: 2222 usec
Press24 = 0.99799

Отличается в 5 знаке. Более чем достаточно для датчика

Я так маскировал десятичную точку. При выводе числа на печать просто ставил ее после нужного разряда числа.

За сколько шагов?

float24_t calculatePressure24(const uint16_t &nP, const uint16_t &nT) {
  cli();
  TCCR1A = 0;                          // Normal mode
  TCCR1B = (1 << CS11) | (1 << CS10);  // Prescaler = 64
  TCNT1 = 0;                           // сброс счётчика

  float24_t fT = nT;
  float24_t fT2 = fT * fT;
  float24_t fP = nP;
  float24_t fP2 = fP * fP;

  float24_t a2 = kff24[0][0] * fT2 + kff24[0][1] * fT + kff24[0][2];
  float24_t a1 = kff24[1][0] * fT2 + kff24[1][1] * fT + kff24[1][2];
  float24_t a0 = kff24[2][0] * fT2 + kff24[2][1] * fT + kff24[2][2];

  float24_t result = a2 * fP2 + a1 * fP + a0;

  TCCR1B = 0;  // stop timer
  sei();
  uint32_t usec = TCNT1 * 4;

  Serial.print("duration: ");
  Serial.print(usec, 3);
  Serial.println(" usec");

  return result;
}

10 умножений и 8 сложений, если я правильно посчитал.

Я не о том спрашивал.
Вы арифметические операции над своим типом проверяли?

Единичные операции (сложение, вычитание, умножение, деление) проверял, в .т.ч. в сравнении с float. Скетч для проверки в 1 посте приводил.
А если Вы об этом,

то кажется понял что имелось в виду. Допишу недостающие методы (sin, cos) и попробую проверочный скетч сделать.