Subversion Repositories chibiosIgnition

Rev

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