Subversion Repositories chibiosIgnition

Rev

Rev 18 | Rev 20 | 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 10uS 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. uint16_t nominal = 0;
  25. uint16_t halfRot;
  26. uint16_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(void)
  53. {
  54.         nominal = halfRot * (long) (phase10)/ 1800;
  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. uint16_t setRPM(uint16_t rpm_ )
  67. {
  68.         if(rpm_ >= 600 && rpm_ < 6000)
  69.         {
  70.           rpm = rpm_;
  71.           adjustRPM();
  72.         }
  73.           return halfRot;
  74. }
  75.  
  76. uint16_t getRPM(void)
  77. {
  78.         return rpm;
  79. }
  80.  
  81. signed getDelta(void)
  82. {
  83.         return delta;
  84. }
  85.  
  86. signed getCount(void)
  87. {
  88.         return  count;
  89. }
  90.  
  91. void setGain(int gain)
  92. {
  93.         gainControl = gain;
  94. }
  95.  
  96.  
  97.  
  98.  
  99. void processPhase ( void )
  100. {
  101.     // lpcl
  102.         chSysLock();
  103.  
  104.         signed pd;
  105.         pd = 0;
  106. static  unsigned sp = 0;
  107.         if(validPhaseSamp)
  108.         {
  109.          pd =   phaseSamp;
  110.      validPhaseSamp = 0;
  111.  
  112.      delta = phaseSamp;
  113.  
  114.      sp = samplePeriod;
  115.         }
  116.  
  117.      chSysUnlock();
  118.  
  119.  
  120.      static int sampleAverage = 0;
  121.  
  122.      static int phaseAverage  = 0;
  123.      const int freqScale = 40;
  124.  
  125.      const int phaseScale = 200;
  126.  
  127.      sampleAverage = sampleAverage + (sp - sampleAverage/freqScale);
  128.  
  129.  
  130.  
  131.  
  132.  
  133.      int32_t arr;
  134.  
  135.    //   if(lock)
  136.  
  137.        int intSample = sampleAverage / freqScale;
  138.  
  139. static unsigned strange = 0;
  140.  
  141.  
  142.  
  143.        int deltaPd= pd/10;
  144.  
  145.        if(pd < -2000 || pd > 2000)
  146.        {
  147.            strange++;
  148.        }
  149.  
  150.        arr =  intSample + deltaPd;
  151.  
  152.  
  153.  
  154.  
  155.  
  156.     if(arr > 65535)
  157.         arr = 65535;
  158.     if(arr < 1000)
  159.         arr = 1000;
  160.  
  161.  
  162.  
  163.      count = arr;
  164.  
  165.     TIM2->ARR = arr -1;
  166.     recalcPhase();
  167.  
  168.  
  169.  
  170.     float nomRPM = 30E6 / (MICROSECS_PULSE * arr);
  171.  
  172.         rpm =  nomRPM ;
  173.  
  174.  
  175.         adjustRPM();
  176.     }
  177.  
  178.  
  179.  
  180.  
  181. // set the timing advance from reference to
  182. void setAdvance(int16_t deg10)
  183. {
  184.     phase10 = deg10;
  185.     recalcPhase();
  186.  
  187. }
  188.  
  189.  
  190.  
  191. // specialist timer setup :
  192. void initTimer2()
  193. {
  194.         rccEnableTIM2(FALSE);
  195.         rccResetTIM2();
  196.  
  197.         TIM2->PSC = 72*MICROSECS_PULSE;
  198.         TIM2->ARR = 60000;
  199.         TIM2->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN |
  200.                         TIM_CR1_ARPE );
  201.  
  202.         /// pulse width 200 uS
  203.         TIM2->CCR1 = 200/MICROSECS_PULSE;
  204.  
  205.     TIM2->CCER =  TIM_CCER_CC1E | TIM_CCER_CC1P  ; //enabled and active high
  206.  
  207.     TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
  208.                            TIM_CCMR1_OC1PE ;
  209.  
  210.  
  211.     TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update
  212.  
  213.  
  214.     // change the TIM2 CC2 to TIM3 CC1
  215.         rccEnableTIM3(FALSE);
  216.         rccResetTIM3();
  217.         // TIM3 on the PA6 ... pins : remap code 00
  218.         AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP;
  219.  
  220.         TIM3->PSC = 72*MICROSECS_PULSE;
  221.         TIM3->ARR = 0xFFFF;
  222.  
  223.  
  224.         TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ;  // filter 16, input
  225.  
  226.  
  227.     // link TIM3 ITR2 to TIM2 reload
  228.     // use TS = 001 to make TRC from Tim2 TRIGGER
  229.         TIM3->SMCR  &= ~(TIM_SMCR_TS_Msk );
  230.         TIM3->SMCR  |=  TIM_SMCR_TS_0; // select ITR2 as trigger source TRC
  231.  
  232.     TIM3->CCMR1 |=  TIM_CCMR1_CC2S_1 |  TIM_CCMR1_CC2S_0 ; //  The CC2S bits are 11, use TRC
  233.  
  234.         TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
  235.  
  236.         TIM3->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN | TIM_CR1_ARPE );
  237.  
  238.  
  239.     nvicEnableVector(TIM3_IRQn,
  240.                           4);
  241.  
  242.  
  243.  
  244.     TIM3->DIER |= TIM_DIER_CC1IE  | TIM_DIER_CC2IE;
  245. }
  246.  
  247.  
  248. // timer 3 interrupt
  249. void VectorB4(void)
  250. {
  251.  
  252.         if(TIM3->SR & TIM_SR_CC1IF)
  253.         {
  254.                 uint16_t sample = TIM3->CCR1;
  255. //              if(sample-lastSampleRef >  1000 /*BREAKER_COUNT_MIN */)
  256.                 {
  257.  
  258.                 samplePeriod = sample-sampleRef;
  259.  
  260.                 sampleRef = sample;
  261.  
  262.                         ++refCount;
  263.                 }
  264.                 lastSampleRef= sample;
  265.  
  266.         }
  267.         if(TIM3->SR & TIM_SR_CC2IF)
  268.         {
  269.                  sampleVar  = TIM3->CCR2;
  270.                  ++varCount;
  271.         }
  272.  
  273.     if(refCount == 1 && varCount == 1)
  274.     {
  275.         if(sampleRef == sampleVar)
  276.                 phaseSamp = 0;
  277.         else
  278.         {
  279.  
  280.         uint16_t refToVar = sampleRef - sampleVar;
  281.         uint16_t varToRef = sampleVar - sampleRef;
  282.  
  283.         if(refToVar < 32768)
  284.                 phaseSamp = refToVar;
  285.         else if(varToRef < 32768)
  286.                 phaseSamp = -varToRef;
  287.  
  288.         }
  289.  
  290.  
  291.         validPhaseSamp = 1;
  292.         refCount=0;
  293.         varCount=0;
  294.  
  295.     }
  296.  
  297.     // frequency error, should deal with by direct period measurement
  298.     if(refCount > 1 || varCount > 1  )
  299.     {
  300.         refCount = 0;
  301.         varCount = 0;
  302.  
  303.     }
  304.  
  305. }
  306.  
  307.  
  308.  
  309.