Subversion Repositories chibiosIgnition

Rev

Rev 21 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 mjames 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"
23 mjames 12
#define  MICROSECS_PULSE 4
6 mjames 13
 
14
// with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000
15
// freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the
16
// first pulse longer than 1/300 of a second as being a proper closure .
20 mjames 17
// the TIM2 counter counts in 1uS increments,
6 mjames 18
#define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300))
19
 
13 mjames 20
#define COUNT_FROM_RPM(RPM) ((1E6/(MICROSECS_PULSE * 30 / (RPM ) )))
21
 
20 mjames 22
int16_t nominal = 0;
6 mjames 23
uint16_t halfRot;
20 mjames 24
int16_t phase10 = 100; // 10 degrees
19 mjames 25
volatile uint16_t sampleVar;
13 mjames 26
volatile uint16_t sampleRef;
6 mjames 27
 
19 mjames 28
volatile uint16_t lastSampleRef = 0;
17 mjames 29
 
19 mjames 30
volatile uint8_t refCount = 0;
31
volatile uint8_t varCount = 0;
17 mjames 32
 
23 mjames 33
volatile uint16_t samplePeriod = 0;
14 mjames 34
 
19 mjames 35
static signed phaseSamp = 0;
36
static uint8_t validPhaseSamp = 0;
6 mjames 37
 
23 mjames 38
int gainControl = 1000;
6 mjames 39
 
19 mjames 40
uint16_t rpm;
41
signed count;
42
signed delta;
6 mjames 43
 
23 mjames 44
void
45
recalcPhase ()
6 mjames 46
{
23 mjames 47
  nominal = halfRot * (long) (phase10) / 3600;
6 mjames 48
}
49
 
23 mjames 50
void
51
adjustRPM (void)
6 mjames 52
{
23 mjames 53
  if (rpm < 600)
54
    rpm = 600;
55
  if (rpm > 5000)
56
    rpm = 5000;
6 mjames 57
 
58
}
59
 
23 mjames 60
uint16_t
61
setRPM (uint16_t rpm_)
6 mjames 62
{
23 mjames 63
  if (rpm_ >= 600 && rpm_ < 6000)
64
    {
65
      rpm = rpm_;
66
      adjustRPM ();
67
    }
68
  return halfRot;
6 mjames 69
}
70
 
23 mjames 71
uint16_t
72
getRPM (void)
6 mjames 73
{
23 mjames 74
  return rpm;
6 mjames 75
}
76
 
23 mjames 77
signed
78
getDelta (void)
11 mjames 79
{
23 mjames 80
  return delta;
11 mjames 81
}
82
 
23 mjames 83
signed
84
getCount (void)
6 mjames 85
{
23 mjames 86
  return count;
6 mjames 87
}
88
 
23 mjames 89
void
90
setGain (int gain)
17 mjames 91
{
23 mjames 92
  gainControl = gain;
17 mjames 93
}
6 mjames 94
 
23 mjames 95
void
96
processPhase (void)
6 mjames 97
{
23 mjames 98
  // lpcl
99
  const signed pdClip = 10000;
100
  static signed pd;
101
  if (validPhaseSamp)
102
    {
103
      chSysLock ();
6 mjames 104
 
23 mjames 105
      pd = phaseSamp - nominal;
14 mjames 106
 
23 mjames 107
      validPhaseSamp = 0;
108
      chSysUnlock ();
6 mjames 109
 
23 mjames 110
      if (pd > pdClip)
111
        pd = pdClip;
112
      if (pd < -pdClip)
113
        pd = -pdClip;
11 mjames 114
 
23 mjames 115
    }
116
  else
117
    return;
20 mjames 118
 
23 mjames 119
  delta = pd;
20 mjames 120
 
23 mjames 121
  static int sampleAverage = 0;
11 mjames 122
 
23 mjames 123
  static int phaseAverage = 0;
124
  const int freqScale =  16;
11 mjames 125
 
23 mjames 126
  const int periodScale= 4;  // 1/periodScale  of difference between period measured and average is added to period.
127
  const int phaseScale = 50;
20 mjames 128
 
23 mjames 129
  // measure sample period devi
130
  sampleAverage = sampleAverage + (samplePeriod *freqScale  - sampleAverage) / periodScale;
20 mjames 131
 
23 mjames 132
  int32_t arr;
6 mjames 133
 
23 mjames 134
  //    if(lock)
17 mjames 135
 
23 mjames 136
  int intSample = sampleAverage / freqScale;
14 mjames 137
 
23 mjames 138
  int deltaPd = pd / phaseScale;
14 mjames 139
 
23 mjames 140
  if (deltaPd == 0)
141
    {
142
      if (pd > 0)
143
        deltaPd = 1;
14 mjames 144
 
23 mjames 145
      if (pd < 0)
146
        deltaPd = -1;
147
    }
6 mjames 148
 
23 mjames 149
  arr = intSample + deltaPd;
11 mjames 150
 
21 mjames 151
// clamp values
14 mjames 152
 
23 mjames 153
  if (arr > 65535)
154
    arr = 65535;
155
  if (arr < 1000)
156
    arr = 1000;
14 mjames 157
 
23 mjames 158
  count = arr;
14 mjames 159
 
23 mjames 160
  TIM2->ARR = arr - 1;
12 mjames 161
 
23 mjames 162
  nominal = intSample * (long) (phase10) / 3600;
12 mjames 163
 
23 mjames 164
  float nomRPM = 30E6 / (MICROSECS_PULSE * arr);
12 mjames 165
 
23 mjames 166
  rpm = nomRPM;
12 mjames 167
 
23 mjames 168
  adjustRPM ();
169
}
12 mjames 170
 
20 mjames 171
// set the timing advance from reference in 0.1 degrees units
23 mjames 172
void
173
setAdvance (int16_t deg10)
6 mjames 174
{
23 mjames 175
  phase10 = deg10;
6 mjames 176
 
177
}
178
 
19 mjames 179
// specialist timer setup :
21 mjames 180
// timer 2 is a reloading counter with a cycle period controlled by its ARR register.
181
// Just before terminal count it produces a pulse of 200 microseconds using its CCR1 count compare register,
182
// used to drive the strobe LED.
183
// Timer 3 is then used to count the time of the reload of Timer 2 via its Trigger Out being selected as reload.
184
// The time is latched in TIM3  CCR2
185
// and ignition pulses are latched on TIM3 CCR1, to allow it to be used in a PLL.
186
//
23 mjames 187
void
188
initTimers ()
19 mjames 189
{
23 mjames 190
  rccEnableTIM2 (FALSE);
191
  rccResetTIM2 ();
19 mjames 192
 
23 mjames 193
  TIM2->PSC = 72 * MICROSECS_PULSE;
194
  TIM2->ARR = 60000;
195
  TIM2->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE);
19 mjames 196
 
23 mjames 197
  /// pulse width 200 uS
198
  TIM2->CCR1 = 200 / MICROSECS_PULSE;
19 mjames 199
 
23 mjames 200
  TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P; //enabled and active high
19 mjames 201
 
23 mjames 202
  TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2
203
      | TIM_CCMR1_OC1PE;
19 mjames 204
 
23 mjames 205
  TIM2->CR2 = TIM_CR2_MMS_1; // trigger out is 010 = update
19 mjames 206
 
23 mjames 207
  rccEnableTIM3 (FALSE);
208
  rccResetTIM3 ();
209
  // TIM3 on the PA6 ... pins : remap code 00
210
  AFIO->MAPR &= ~AFIO_MAPR_TIM3_REMAP;
19 mjames 211
 
23 mjames 212
  TIM3->PSC = 72 * MICROSECS_PULSE;
213
  TIM3->ARR = 0xFFFF;
19 mjames 214
 
23 mjames 215
  TIM3->CCMR1 =
216
      TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */; // filter 16, input
19 mjames 217
 
23 mjames 218
  // link TIM3 ITR2 to TIM2 reload
219
  // use TS = 001 to make TRC from Tim2 TRIGGER
220
  TIM3->SMCR &= ~(TIM_SMCR_TS_Msk);
221
  TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC
19 mjames 222
 
23 mjames 223
  TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0; //  The CC2S bits are 11, use TRC
19 mjames 224
 
23 mjames 225
  TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
19 mjames 226
 
23 mjames 227
  TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE);
19 mjames 228
 
23 mjames 229
  nvicEnableVector (TIM3_IRQn, 4);
19 mjames 230
 
23 mjames 231
  TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE;
19 mjames 232
}
233
 
6 mjames 234
// timer 3 interrupt
23 mjames 235
void
236
VectorB4 (void)
6 mjames 237
{
13 mjames 238
 
23 mjames 239
  if (TIM3->SR & TIM_SR_CC1IF)
240
    {
241
      uint16_t sample = TIM3->CCR1;
242
//              if(sample-lastSampleRef >  1000 /*BREAKER_COUNT_MIN */)
6 mjames 243
        {
14 mjames 244
 
23 mjames 245
          samplePeriod = sample - sampleRef;
19 mjames 246
 
23 mjames 247
          sampleRef = sample;
19 mjames 248
 
23 mjames 249
          ++refCount;
6 mjames 250
        }
23 mjames 251
      lastSampleRef = sample;
13 mjames 252
 
23 mjames 253
    }
254
  if (TIM3->SR & TIM_SR_CC2IF)
19 mjames 255
    {
23 mjames 256
      sampleVar = TIM3->CCR2;
257
      ++varCount;
258
    }
13 mjames 259
 
23 mjames 260
  if (refCount == 1 && varCount == 1)
261
    {
262
      if (sampleRef == sampleVar)
263
        phaseSamp = 0;
264
      else
265
        {
13 mjames 266
 
23 mjames 267
          uint16_t refToVar = sampleRef - sampleVar;
268
          uint16_t varToRef = sampleVar - sampleRef;
13 mjames 269
 
23 mjames 270
          if (refToVar < varToRef)
271
            phaseSamp = refToVar;
272
          else if (varToRef <= refToVar)
273
            phaseSamp = -varToRef;
13 mjames 274
 
23 mjames 275
        }
13 mjames 276
 
23 mjames 277
      validPhaseSamp = 1;
278
      refCount = 0;
279
      varCount = 0;
13 mjames 280
 
19 mjames 281
    }
13 mjames 282
 
23 mjames 283
  // frequency error, should deal with by direct period measurement
284
  if (refCount > 1 || varCount > 1)
19 mjames 285
    {
23 mjames 286
      refCount = 0;
287
      varCount = 0;
19 mjames 288
 
289
    }
290
 
6 mjames 291
}
292