Subversion Repositories chibiosIgnition

Rev

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