Subversion Repositories chibiosIgnition

Rev

Rev 11 | Rev 13 | 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. // 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 SAMPLE_BUFF_SIZE 256
  22. uint16_t halfRot;
  23. uint16_t nominal  = 0;
  24. uint16_t phase10 = 100; // 10 degrees
  25. volatile uint16_t sampleCount = 0;
  26. uint16_t outSampleCount = 0;
  27. volatile uint16_t sampleBuff[SAMPLE_BUFF_SIZE];
  28. typedef enum { WAIT_GAP, SKIP_BOUNCE, HAVE_SAMPLE } sampleState_t ;
  29. sampleState_t  sampleState = WAIT_GAP;
  30. // difference between samples
  31. volatile uint16_t deltaTime;
  32.  
  33. static signed pdI = 0;
  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 active high
  52.  
  53.     TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | 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. }
  105.  
  106. uint16_t setRPM(uint16_t rpm_ )
  107. {
  108.         if(rpm_ >= 600 && rpm_ < 6000)
  109.         {
  110.           rpm = rpm_;
  111.           adjustRPM();
  112.         }
  113.           return halfRot;
  114. }
  115.  
  116. uint16_t getRPM(void)
  117. {
  118.         return rpm;
  119. }
  120.  
  121. uint16_t getDelta(void)
  122. {
  123.         return pdI&0xFFFF;
  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. // allows for wrapping
  134. uint16_t getSampleBuff(uint16_t index)
  135. {
  136.         chSysLock();
  137.         return sampleBuff[wrapIndex(index)];
  138.         chSysUnlock();
  139. }
  140.  
  141.  
  142. // waits for ignition pulse , debounces readings,
  143. // returns the pulse time, skips debounce time
  144. uint16_t getNextPulse(void)
  145. {
  146.         static uint16_t lastSampleIndex = 0;
  147.         while(1)
  148.         {
  149.                         while (outSampleCount == sampleCount)
  150.                                 chThdSleep(10);
  151.  
  152.                         uint16_t thisTime  = getSampleBuff(outSampleCount);
  153.  
  154.                         outSampleCount = wrapIndex(outSampleCount + 1);
  155.                         while (outSampleCount == sampleCount)
  156.                                 chThdSleep(10);
  157.  
  158.                         uint16_t nextTime = getSampleBuff(outSampleCount);
  159.  
  160.                         // calculate wrapped time delta : should be > than bounce time to allow
  161.                         uint16_t diffTime = nextTime - thisTime;
  162.  
  163.                         if(diffTime > BREAKER_COUNT_MIN)
  164.                         {
  165.                                 lastSampleIndex = outSampleCount;
  166.                                 return nextTime;
  167.                         }
  168.  
  169.         }
  170.   return 0;
  171. }
  172.  
  173.  
  174. void processNextPulse(uint16_t retVal)
  175. {
  176.  
  177.         static uint32_t VperiodAccumulator = 0;
  178.     // scale it up by 32
  179.         static uint32_t periodEstimate = 2000 * 256 ;
  180.         static uint16_t lastVal = 0;
  181.         // at this point we should try to phase lock
  182.     deltaTime = retVal - lastVal;
  183.  
  184.  
  185.  
  186.     if(deltaTime > 10000)
  187.     {
  188.         __asm(" BKPT #0");
  189.     }
  190.  
  191.     lastVal = retVal;
  192.  
  193.     // look at the values and try to pull them togwther
  194.  
  195.     // accumulate phase
  196.     VperiodAccumulator += periodEstimate;
  197.     VperiodAccumulator &= 0xFFFFFFF;
  198.  
  199.     uint16_t accum_low = (VperiodAccumulator) >> 8;
  200. #define WINDOW 1000
  201.  
  202. #define LIMIT 2048
  203.  
  204. #define STEP 32
  205.  
  206.     uint16_t diff = accum_low - retVal;
  207.     if(diff < WINDOW && diff != 0)
  208.         pdI += diff/10;
  209.     if(diff > 65536-WINDOW )
  210.         pdI -= (65536-diff)/10;
  211.  
  212.     if(pdI > LIMIT)
  213.         pdI = LIMIT;
  214.     if(pdI < -(LIMIT))
  215.         pdI = -(LIMIT);
  216.  
  217.  
  218.  
  219.     signed pd = (signed)(periodEstimate)- (signed)(deltaTime*256) + pdI;
  220.  
  221.  
  222.     periodEstimate -= pd / 100;
  223.  
  224.  
  225.  
  226.     TIM2->ARR = (periodEstimate+128)/256 ;
  227.     recalcPhase();
  228.  
  229.  
  230.  
  231. // calculate RPM
  232.     float nomRPM = 30E6 / (MICROSECS_PULSE * (periodEstimate/256));
  233.  
  234.         rpm =  nomRPM ;
  235.  
  236.  
  237.  
  238. //      rpm += delta / 256;
  239.  
  240.         adjustRPM();
  241.     }
  242.  
  243.  
  244.  
  245.  
  246. // set the timing advance from reference to
  247. void setAdvance(int16_t deg10)
  248. {
  249.     phase10 = deg10;
  250.     recalcPhase();
  251.  
  252. }
  253.  
  254. // timer 3 interrupt
  255. void VectorB4(void)
  256. {
  257.         uint16_t stat = TIM3->SR;
  258.         if(stat & TIM_SR_CC1IF)
  259.         {
  260.                 TIM3->SR &= ~TIM_SR_CC1IF;
  261.             uint16_t sample = TIM3->CCR1;
  262.             sampleBuff[sampleCount++] = sample;
  263.             if (sampleCount >= SAMPLE_BUFF_SIZE)
  264.                 sampleCount = 0;
  265.         }
  266. }
  267.  
  268.  
  269.  
  270.