MarlinのLeib rampアルゴリズムの謎

結論から言うと、Marlinの中ではLeib Rampアルゴリズムは使われていなかった。
Acceleration fails to reach plateaux speed by the end of the ramp · Issue #1921 · MarlinFirmware/Marlin · GitHub
The comments in the code say that it uses the Leib ramp method but I don't think it does.

This doesn't have anything to do with the Leib ramp algorithm at all, which uses a Taylor series to calculate the next period from the previous one using multiplies and adds.

昔のMarlin(v1)にはstepper.cppというファイルがあり、その中には以下の記載があった。
// The slope of acceleration is calculated with the leib ramp alghorithm.
Marlin/Marlin/stepper.cpp at d9c04498203b6e67cb543eb8a02344b3f70b1a33 · MarlinFirmware/Marlin · GitHub

これを真に受けてLeib rampでDelay(Marlin内における変数timerの値)を計算していると思っていたが、モータ速度step_rateの逆数をとっていただけだった。つまり、Leib rampが避けたいといっていた逆数を取る操作を実際はやっていたわけである。
ここで、逆数をそのまま計算しているわけではなく、
timer = 200_0000 / step_rate
という計算をしている。200万という数字は以下に説明があるが、step_rateが1000HzのときにOCR1Aが2000となることからも成り立つことがわかる。
[question] Minimal speed stepper.ccp · Issue #1443 · MarlinFirmware/Marlin · GitHub
Each unit means 0.5us, I mean, if you wanna pulse the stepper at 1Khz, just set OCR1A with 2000.

実際は逆数を計算しているわけではなく、ルックアップテーブルから読み出している。以下の2つのサイトに記載がある。
[question] Minimal speed stepper.ccp · Issue #1443 · MarlinFirmware/Marlin · GitHub
Ok found something about the lookuptable. http://softsolder.com/2013/06/04/marlin-firmware-stepper-interrupt-timing/#comment-22123 This is close the same as 2,000,000/step_rate, just slightly faster. (16MHz/8Prescaler = 2M...)
Marlin Firmware: Stepper Interrupt Timing – The Smell of Molten Projects in the Morning
The actual calculation which the lookup table is replacing is
timer = (uint16_t)((uint32_t)2000000 / (uint32_t)step_rate);

このルックアップテーブル(Marlin v1のspeed_lookuptable.h)を解析してみたところ、おおむねstep_rateからtimer(=2000000/step_rate)に変換するテーブルになっているようである。calc_timer()ないの以下の部分でルックアップテーブルを用いてstep_rateをcalc_timer()に変換している。
上記のサイトで言われていたように、timerの計算を以下に変換しても原理上は動くはずである(除算が間に合えば?)
timer = (uint16_t)((uint32_t)2000000 / (uint32_t)step_rate);

  if(step_rate >= (8*256)){ // higher step rate 
    unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
    unsigned char tmp_step_rate = (step_rate & 0x00ff);
    unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);
    MultiU16X8toH16(timer, tmp_step_rate, gain);
    timer = (unsigned short)pgm_read_word_near(table_address) - timer;
  }
  else { // lower step rates
    unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0];
    table_address += ((step_rate)>>1) & 0xfffc;
    timer = (unsigned short)pgm_read_word_near(table_address);
    timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3);
  }
  if(timer < 100) { timer = 100; Serial.print("Steprate to high : "); Serial.println(step_rate); }//(20kHz this should never happen)
  return timer;