Subversion Repositories chibiosIgnition

Rev

Rev 7 | 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 10
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19. // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000
  20. // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the
  21. // first pulse longer than 1/300 of a second as being a proper closure .
  22. // the TIM2 counter counts in 10uS increments,
  23. #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300))
  24.  
  25. #define SAMPLE_BUFF_SIZE 256
  26. uint16_t halfRot;
  27. uint16_t nominal  = 0;
  28. uint16_t phase10 = 100; // 10 degrees
  29. volatile uint16_t sampleCount = 0;
  30. uint16_t outSampleCount = 0;
  31. volatile uint16_t sampleBuff[SAMPLE_BUFF_SIZE];
  32. typedef enum { WAIT_GAP, SKIP_BOUNCE } sampleState_t ;
  33. sampleState_t  sampleState = WAIT_GAP;
  34.  
  35.  
  36. uint16_t rpm;
  37.  
  38. void initTimer2()
  39. {
  40.         rccEnableTIM2(FALSE);
  41.         rccResetTIM2();
  42.  
  43.         TIM2->PSC = 72*MICROSECS_PULSE;
  44.         TIM2->ARR = 60000;
  45.         TIM2->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN |
  46.                         TIM_CR1_ARPE );
  47.  
  48.         TIM2->CCR1 = 100/MICROSECS_PULSE;
  49.  
  50.     TIM2->CCER =  TIM_CCER_CC1E | TIM_CCER_CC1P  ; //enabled and low
  51.  
  52.     TIM2->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
  53.                            TIM_CCMR1_OC1PE ;
  54.  
  55.  
  56.     TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update
  57.  
  58.  
  59.     // change the TIM2 CC2 to TIM3 CC1
  60.         rccEnableTIM3(FALSE);
  61.         rccResetTIM3();
  62.         // TIM3 on the PA6 ... pins : remap code 00
  63.         AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP;
  64.  
  65.         TIM3->PSC = 72*MICROSECS_PULSE;
  66.         TIM3->ARR = 0xFFFF;
  67.  
  68.  
  69.         TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ;  // filter 16, input
  70.  
  71.         TIM3->CCER = TIM_CCER_CC1E;
  72.  
  73.     // link TIM3 ITR1 to TIM2 reload
  74.     // use CCR3
  75.     TIM3->CCMR2 = TIM_CCMR2_CC3S_1 | TIM_CCMR2_CC3S_0 ; //  The
  76.  
  77.  
  78.         TIM3->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN | TIM_CR1_ARPE );
  79.  
  80.  
  81.     nvicEnableVector(TIM3_IRQn,
  82.                           CORTEX_PRIORITY_MASK(4));
  83.  
  84.  
  85.  
  86.     TIM3->DIER |= TIM_DIER_CC1IE ;
  87. }
  88.  
  89.  
  90. void recalcPhase(void)
  91. {
  92.         nominal = halfRot * (long) (phase10)/ 1800;
  93. }
  94.  
  95. void adjustRPM(void)
  96. {
  97.         if(rpm < 600)
  98.                 rpm = 600;
  99.         if(rpm >  5000)
  100.                 rpm = 5000;
  101.  
  102.  
  103.         float pulseSec = rpm /30;
  104.  
  105. halfRot = 1e6 / (pulseSec * MICROSECS_PULSE) ;
  106.  
  107.   TIM2->ARR = halfRot;
  108. recalcPhase();
  109. }
  110.  
  111. uint16_t setRPM(uint16_t rpm_ )
  112. {
  113.         if(rpm_ >= 600 && rpm_ < 5000)
  114.         {
  115.           rpm = rpm_;
  116.           adjustRPM();
  117.         }
  118.           return halfRot;
  119. }
  120.  
  121. uint16_t getRPM(void)
  122. {
  123.         return rpm;
  124. }
  125.  
  126. uint16_t wrapIndex(uint16_t index)
  127. {
  128.         if (index > SAMPLE_BUFF_SIZE)
  129.                 index -= SAMPLE_BUFF_SIZE;
  130.     return index;
  131. }
  132.  
  133.  
  134. // allows for wrapping
  135. uint16_t getSampleBuff(uint16_t index)
  136. {
  137.         return sampleBuff[wrapIndex(index)];
  138. }
  139.  
  140. // waits for ignition pulse , debounces readings
  141. uint16_t getNextPulse(void)
  142. {
  143.         static uint16_t lastVal = 0;
  144.         uint16_t retVal ;
  145.         uint8_t done = 0;
  146.         while(done == 0)
  147.         {
  148.                 uint16_t diff;
  149.                 // wait until there are enough samples
  150.                 while(1)
  151.                 {
  152.  
  153.                         diff = sampleCount - outSampleCount;
  154.                         if(outSampleCount > sampleCount)
  155.                                 diff = sampleCount - outSampleCount;
  156.                         else
  157.                                 diff = SAMPLE_BUFF_SIZE + sampleCount - outSampleCount;
  158.  
  159.                         if(diff > 1)
  160.                                 break;
  161.                         chThdSleep(1);
  162.                 }
  163.  
  164.                 // pick the next out of gap sample
  165.                 if(sampleState == WAIT_GAP)
  166.                 {
  167.                         done = 1;
  168.                         retVal = getSampleBuff(outSampleCount);
  169.                 }
  170.                 // see how many samples are too close together
  171.                 sampleState = SKIP_BOUNCE;
  172.                 uint16_t endCount = sampleCount;
  173.                 while((sampleState == SKIP_BOUNCE) && (outSampleCount != endCount))
  174.                 {
  175.                         uint16_t thisTime  = getSampleBuff(outSampleCount);
  176.                         outSampleCount = wrapIndex(outSampleCount + 1);
  177.                         uint16_t nextTime = getSampleBuff(outSampleCount);
  178.  
  179.                         uint16_t deltaTime;
  180.  
  181.                         // calculate wrapped time delta : should be > than bounce time to allow
  182.                         if(nextTime > thisTime)
  183.                                 deltaTime = nextTime - thisTime;
  184.                         else
  185.                                 deltaTime = 65536 + nextTime - thisTime;
  186.  
  187.                         if(deltaTime > BREAKER_COUNT_MIN)
  188.                         {
  189.                                 sampleState = WAIT_GAP;
  190.                                 break;
  191.                         }
  192.  
  193.                 }
  194.         }
  195.  
  196.         // at this point we should try to phase lock
  197.     uint32_t period;
  198.     if(retVal > lastVal)
  199.         period = retVal - lastVal;
  200.     else
  201.         period = 65536 + retVal - lastVal;
  202.  
  203.     lastVal = retVal;
  204.  
  205.     float nomRPM = 30E6 / (MICROSECS_PULSE * period) ;
  206.  
  207.         rpm = rpm + (nomRPM -rpm)/10;
  208.  
  209.  
  210.  
  211.  
  212.         uint16_t skew = 32768 - nominal;
  213.  
  214.         long delta = (retVal+skew) - (nominal+skew);
  215.  
  216.         if(delta > 10)
  217.                 rpm = rpm - 1;
  218.         if(delta -10)
  219.                 rpm = rpm + 1;
  220.  
  221. //      rpm += delta / 256;
  222.  
  223.         adjustRPM();
  224.  
  225.         return retVal;
  226. }
  227.  
  228.  
  229. // set the timing advance from reference to
  230. void setAdvance(int16_t deg10)
  231. {
  232.     phase10 = deg10;
  233.     recalcPhase();
  234.  
  235. }
  236.  
  237. // timer 3 interrupt
  238. void VectorB4(void)
  239. {
  240.         uint16_t stat = TIM3->SR;
  241.         if(stat & TIM_SR_CC1IF)
  242.         {
  243.                 TIM3->SR &= ~TIM_SR_CC1IF;
  244.             uint16_t sample = TIM3->CCR1;
  245.             sampleBuff[sampleCount++] = sample;
  246.             if (sampleCount > SAMPLE_BUFF_SIZE)
  247.                 sampleCount = 0;
  248.         }
  249. }
  250.  
  251.  
  252.  
  253.