Subversion Repositories chibiosIgnition

Rev

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