Subversion Repositories chibiosIgnition

Rev

Rev 23 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * timer2.c
  3.  *
  4.  *  Created on: 2 Apr 2018
  5.  *      Author: Mike
  6.  */
  7.  
  8. #include "ch.h"  // needs for all ChibiOS programs
  9. #include "hal.h" // hardware abstraction layer header
  10.  
  11. #include "timer2.h"
  12. #define  MICROSECS_PULSE 4
  13.  
  14. // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000
  15. // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the
  16. // first pulse longer than 1/300 of a second as being a proper closure .
  17. // the TIM2 counter counts in 1uS increments,
  18. #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300))
  19.  
  20. #define COUNT_FROM_RPM(RPM) ((1E6/(MICROSECS_PULSE * 30 / (RPM ) )))
  21.  
  22. int16_t nominal = 0;
  23. uint16_t halfRot;
  24. int16_t phase10 = 100; // 10 degrees
  25. volatile uint16_t sampleVar;
  26. volatile uint16_t sampleRef;
  27.  
  28. volatile uint16_t lastSampleRef = 0;
  29.  
  30. volatile uint8_t refCount = 0;
  31. volatile uint8_t varCount = 0;
  32.  
  33. volatile uint16_t samplePeriod = 0;
  34.  
  35. static signed phaseSamp = 0;
  36. static uint8_t validPhaseSamp = 0;
  37.  
  38. static uint8_t locked = 0; // in lock if true
  39. int gainControl = 1000;
  40.  
  41. uint16_t rpm;
  42. signed count;
  43. signed delta;
  44.  
  45. void
  46. recalcPhase ()
  47. {
  48.   nominal = halfRot * (long) (phase10) / 3600;
  49. }
  50.  
  51. void
  52. adjustRPM (void)
  53. {
  54.   if (rpm < 500)
  55.     rpm = 500;
  56.   if (rpm > 10000)
  57.     rpm = 10000;
  58.  
  59. }
  60.  
  61. uint16_t
  62. setRPM (uint16_t rpm_)
  63. {
  64.   if (rpm_ >= 500 && rpm_ < 10000)
  65.     {
  66.       rpm = rpm_;
  67.       adjustRPM ();
  68.     }
  69.   return halfRot;
  70. }
  71.  
  72. uint16_t
  73. getRPM (void)
  74. {
  75.   return rpm;
  76. }
  77.  
  78. signed
  79. getDelta (void)
  80. {
  81.   return delta;
  82. }
  83.  
  84. signed
  85. getCount (void)
  86. {
  87.   return count;
  88. }
  89.  
  90. void
  91. setGain (int gain)
  92. {
  93.   gainControl = gain;
  94. }
  95.  
  96. void
  97. processPhase (void)
  98. {
  99.   // lpcl
  100.   const signed pdClip = 1000;
  101.   static signed pd;
  102.   if (validPhaseSamp)
  103.     {
  104.       chSysLock ();
  105.  
  106.       pd = phaseSamp - nominal;
  107.  
  108.       validPhaseSamp = 0;
  109.       chSysUnlock ();
  110.  
  111.       if (pd > pdClip)
  112.         pd = pdClip;
  113.       if (pd < -pdClip)
  114.         pd = -pdClip;
  115.  
  116.     }
  117.   else
  118.     return;
  119.  
  120.   delta = pd;
  121.  
  122.   static int sampleAverage = 0;
  123.  
  124.   static int phaseAverage = 0;
  125.   const int freqScale = 1024;  // scale up calculations
  126.  
  127.   const int periodScale = 8; // 1/periodScale  of difference between period measured and average is added to period.
  128.   const int phaseScale = 500;
  129.   const int phaseLim = 1; // total contribution of phase accumulator
  130.   // measure sample period devi
  131.   sampleAverage = sampleAverage
  132.       + (samplePeriod * freqScale - sampleAverage) / periodScale;
  133.  
  134.   int32_t arr;
  135.  
  136.   //    if(lock)
  137.  
  138.   int intSample = sampleAverage;
  139.  
  140.   // dont phase lock until r and v in lock
  141.   if (locked == 1)
  142.     {
  143.       phaseAverage += pd;
  144.     }
  145.   else
  146.     {
  147.       phaseAverage = 0;
  148.     }
  149.  
  150.   if(phaseAverage > phaseScale * phaseLim)
  151.     phaseAverage = phaseScale * phaseLim;
  152.   if (phaseAverage < -phaseScale * phaseLim)
  153.     phaseAverage = -phaseScale *phaseLim;
  154.  
  155.   arr = sampleAverage / freqScale + phaseAverage / phaseScale;
  156.  
  157. // clamp values
  158.  
  159.   if (arr > 65535)
  160.     arr = 65535;
  161.   if (arr < 1000)
  162.     arr = 1000;
  163.  
  164.   count = arr;
  165.  
  166.   TIM2->ARR = arr - 1;
  167.  
  168.   nominal = count * (long) (phase10) / 3600;
  169.  
  170.   float nomRPM = 30E6 / (MICROSECS_PULSE * arr);
  171.  
  172.   rpm = nomRPM;
  173.  
  174.   adjustRPM ();
  175. }
  176.  
  177. // set the timing advance from reference in 0.1 degrees units
  178. void
  179. setAdvance (int16_t deg10)
  180. {
  181.   phase10 = deg10;
  182.  
  183. }
  184.  
  185. // specialist timer setup :
  186. // timer 2 is a reloading counter with a cycle period controlled by its ARR register.
  187. // Just before terminal count it produces a pulse of 200 microseconds using its CCR1 count compare register,
  188. // used to drive the strobe LED.
  189. // Timer 3 is then used to count the time of the reload of Timer 2 via its Trigger Out being selected as reload.
  190. // The time is latched in TIM3  CCR2
  191. // and ignition pulses are latched on TIM3 CCR1, to allow it to be used in a PLL.
  192. //
  193. void
  194. initTimers ()
  195. {
  196.   rccEnableTIM2 (FALSE);
  197.   rccResetTIM2 ();
  198.  
  199.   TIM2->PSC = 72 * MICROSECS_PULSE;
  200.   TIM2->ARR = 60000;
  201.   TIM2->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE);
  202.  
  203.   /// pulse width 200 uS
  204.   TIM2->CCR1 = 200 / MICROSECS_PULSE;
  205.  
  206.   TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P; //enabled and active high
  207.  
  208.   TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2
  209.       | TIM_CCMR1_OC1PE;
  210.  
  211.   TIM2->CR2 = TIM_CR2_MMS_1; // trigger out is 010 = update
  212.  
  213.   rccEnableTIM3 (FALSE);
  214.   rccResetTIM3 ();
  215.   // TIM3 on the PA6 ... pins : remap code 00
  216.   AFIO->MAPR &= ~AFIO_MAPR_TIM3_REMAP;
  217.  
  218.   TIM3->PSC = 72 * MICROSECS_PULSE;
  219.   TIM3->ARR = 0xFFFF;
  220.  
  221.   TIM3->CCMR1 =
  222.       TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */; // filter 16, input
  223.  
  224.   // link TIM3 ITR2 to TIM2 reload
  225.   // use TS = 001 to make TRC from Tim2 TRIGGER
  226.   TIM3->SMCR &= ~(TIM_SMCR_TS_Msk);
  227.   TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC
  228.  
  229.   TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0; //  The CC2S bits are 11, use TRC
  230.  
  231.   TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
  232.  
  233.   TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE);
  234.  
  235.   nvicEnableVector (TIM3_IRQn, 4);
  236.  
  237.   TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE;
  238. }
  239.  
  240. // timer 3 interrupt
  241. void
  242. VectorB4 (void)
  243. {
  244.  
  245.   if (TIM3->SR & TIM_SR_CC1IF)
  246.     {
  247.       uint16_t sample = TIM3->CCR1;
  248. //              if(sample-lastSampleRef >  1000 /*BREAKER_COUNT_MIN */)
  249.         {
  250.  
  251.           samplePeriod = sample - sampleRef;
  252.  
  253.           sampleRef = sample;
  254.  
  255.           ++refCount;
  256.         }
  257.       lastSampleRef = sample;
  258.  
  259.     }
  260.   if (TIM3->SR & TIM_SR_CC2IF)
  261.     {
  262.       sampleVar = TIM3->CCR2;
  263.       ++varCount;
  264.     }
  265.  
  266.   if (refCount == 1 && varCount == 1)
  267.     {
  268.       if (sampleRef == sampleVar)
  269.         phaseSamp = 0;
  270.       else
  271.         {
  272.  
  273.           uint16_t refToVar = sampleRef - sampleVar;
  274.           uint16_t varToRef = sampleVar - sampleRef;
  275.  
  276.           if (refToVar < varToRef)
  277.             phaseSamp = refToVar;
  278.           else if (varToRef <= refToVar)
  279.             phaseSamp = -varToRef;
  280.  
  281.         }
  282.  
  283.       validPhaseSamp = 1;
  284.       refCount = 0;
  285.       varCount = 0;
  286.       locked = 1;
  287.     }
  288.  
  289.  
  290.   if (refCount > 1 || varCount > 1)
  291.     {
  292.       refCount = 0;
  293.       varCount = 0;
  294.       locked = 0;
  295.     }
  296.  
  297. }
  298.  
  299.