Subversion Repositories chibiosIgnition

Rev

Rev 19 | 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 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. static unsigned strange = 0;
  147.  
  148.  
  149.        int deltaPd= pd/ phaseScale;
  150.  
  151.  
  152.        if(pd < -2000 || pd > 2000)
  153.        {
  154.            strange++;
  155.        }
  156.  
  157.        arr =  intSample + deltaPd;
  158.  
  159.  
  160.  
  161.  
  162.  
  163.     if(arr > 65535)
  164.         arr = 65535;
  165.     if(arr < 1000)
  166.         arr = 1000;
  167.  
  168.  
  169.  
  170.      count = arr;
  171.  
  172.     TIM2->ARR = arr -1;
  173.  
  174.         nominal = intSample * (long) (phase10)/ 3600;
  175.  
  176.  
  177.  
  178.     float nomRPM = 30E6 / (MICROSECS_PULSE * arr);
  179.  
  180.         rpm =  nomRPM ;
  181.  
  182.  
  183.         adjustRPM();
  184.     }
  185.  
  186.  
  187.  
  188.  
  189. // set the timing advance from reference in 0.1 degrees units
  190. void setAdvance(int16_t deg10)
  191. {
  192.     phase10 = deg10;
  193.  
  194. }
  195.  
  196.  
  197.  
  198. // specialist timer setup :
  199. void initTimer2()
  200. {
  201.         rccEnableTIM2(FALSE);
  202.         rccResetTIM2();
  203.  
  204.         TIM2->PSC = 72*MICROSECS_PULSE;
  205.         TIM2->ARR = 60000;
  206.         TIM2->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN |
  207.                         TIM_CR1_ARPE );
  208.  
  209.         /// pulse width 200 uS
  210.         TIM2->CCR1 = 200/MICROSECS_PULSE;
  211.  
  212.     TIM2->CCER =  TIM_CCER_CC1E | TIM_CCER_CC1P  ; //enabled and active high
  213.  
  214.     TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
  215.                            TIM_CCMR1_OC1PE ;
  216.  
  217.  
  218.     TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update
  219.  
  220.  
  221.     // change the TIM2 CC2 to TIM3 CC1
  222.         rccEnableTIM3(FALSE);
  223.         rccResetTIM3();
  224.         // TIM3 on the PA6 ... pins : remap code 00
  225.         AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP;
  226.  
  227.         TIM3->PSC = 72*MICROSECS_PULSE;
  228.         TIM3->ARR = 0xFFFF;
  229.  
  230.  
  231.         TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ;  // filter 16, input
  232.  
  233.  
  234.     // link TIM3 ITR2 to TIM2 reload
  235.     // use TS = 001 to make TRC from Tim2 TRIGGER
  236.         TIM3->SMCR  &= ~(TIM_SMCR_TS_Msk );
  237.         TIM3->SMCR  |=  TIM_SMCR_TS_0; // select ITR2 as trigger source TRC
  238.  
  239.     TIM3->CCMR1 |=  TIM_CCMR1_CC2S_1 |  TIM_CCMR1_CC2S_0 ; //  The CC2S bits are 11, use TRC
  240.  
  241.         TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
  242.  
  243.         TIM3->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN | TIM_CR1_ARPE );
  244.  
  245.  
  246.     nvicEnableVector(TIM3_IRQn,
  247.                           4);
  248.  
  249.  
  250.  
  251.     TIM3->DIER |= TIM_DIER_CC1IE  | TIM_DIER_CC2IE;
  252. }
  253.  
  254.  
  255. // timer 3 interrupt
  256. void VectorB4(void)
  257. {
  258.  
  259.         if(TIM3->SR & TIM_SR_CC1IF)
  260.         {
  261.                 uint16_t sample = TIM3->CCR1;
  262. //              if(sample-lastSampleRef >  1000 /*BREAKER_COUNT_MIN */)
  263.                 {
  264.  
  265.                 samplePeriod = sample-sampleRef;
  266.  
  267.                 sampleRef = sample;
  268.  
  269.                         ++refCount;
  270.                 }
  271.                 lastSampleRef= sample;
  272.  
  273.         }
  274.         if(TIM3->SR & TIM_SR_CC2IF)
  275.         {
  276.                  sampleVar  = TIM3->CCR2;
  277.                  ++varCount;
  278.         }
  279.  
  280.     if(refCount == 1 && varCount == 1)
  281.     {
  282.         if(sampleRef == sampleVar)
  283.                 phaseSamp = 0;
  284.         else
  285.         {
  286.  
  287.         uint16_t refToVar = sampleRef - sampleVar;
  288.         uint16_t varToRef = sampleVar - sampleRef;
  289.  
  290.         if(refToVar < varToRef)
  291.                 phaseSamp = refToVar;
  292.         else if(varToRef <= refToVar)
  293.                 phaseSamp = -varToRef;
  294.  
  295.         }
  296.  
  297.  
  298.         validPhaseSamp = 1;
  299.         refCount=0;
  300.         varCount=0;
  301.  
  302.     }
  303.  
  304.     // frequency error, should deal with by direct period measurement
  305.     if(refCount > 1 || varCount > 1  )
  306.     {
  307.         refCount = 0;
  308.         varCount = 0;
  309.  
  310.     }
  311.  
  312. }
  313.  
  314.  
  315.  
  316.