Subversion Repositories chibiosIgnition

Rev

Rev 11 | Rev 13 | 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"
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];
11 mjames 28
typedef enum { WAIT_GAP, SKIP_BOUNCE, HAVE_SAMPLE } sampleState_t ;
6 mjames 29
sampleState_t  sampleState = WAIT_GAP;
11 mjames 30
// difference between samples
31
volatile uint16_t deltaTime;
6 mjames 32
 
12 mjames 33
static signed pdI = 0;
6 mjames 34
 
12 mjames 35
 
6 mjames 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
 
7 mjames 48
        /// pulse width 200 uS
49
        TIM2->CCR1 = 200/MICROSECS_PULSE;
6 mjames 50
 
11 mjames 51
    TIM2->CCER =  TIM_CCER_CC1E | TIM_CCER_CC1P  ; //enabled and active high
6 mjames 52
 
11 mjames 53
    TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
6 mjames 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,
7 mjames 83
                          4);
6 mjames 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
{
12 mjames 108
        if(rpm_ >= 600 && rpm_ < 6000)
6 mjames 109
        {
110
          rpm = rpm_;
111
          adjustRPM();
112
        }
113
          return halfRot;
114
}
115
 
116
uint16_t getRPM(void)
117
{
118
        return rpm;
119
}
120
 
11 mjames 121
uint16_t getDelta(void)
122
{
12 mjames 123
        return pdI&0xFFFF;
11 mjames 124
}
125
 
6 mjames 126
uint16_t wrapIndex(uint16_t index)
127
{
11 mjames 128
        if (index >= SAMPLE_BUFF_SIZE)
6 mjames 129
                index -= SAMPLE_BUFF_SIZE;
130
    return index;
131
}
132
 
133
// allows for wrapping
134
uint16_t getSampleBuff(uint16_t index)
135
{
11 mjames 136
        chSysLock();
6 mjames 137
        return sampleBuff[wrapIndex(index)];
11 mjames 138
        chSysUnlock();
6 mjames 139
}
140
 
11 mjames 141
 
142
// waits for ignition pulse , debounces readings,
143
// returns the pulse time, skips debounce time
6 mjames 144
uint16_t getNextPulse(void)
145
{
11 mjames 146
        static uint16_t lastSampleIndex = 0;
147
        while(1)
6 mjames 148
        {
11 mjames 149
                        while (outSampleCount == sampleCount)
150
                                chThdSleep(10);
6 mjames 151
 
11 mjames 152
                        uint16_t thisTime  = getSampleBuff(outSampleCount);
6 mjames 153
 
11 mjames 154
                        outSampleCount = wrapIndex(outSampleCount + 1);
155
                        while (outSampleCount == sampleCount)
156
                                chThdSleep(10);
6 mjames 157
 
158
                        uint16_t nextTime = getSampleBuff(outSampleCount);
159
 
160
                        // calculate wrapped time delta : should be > than bounce time to allow
11 mjames 161
                        uint16_t diffTime = nextTime - thisTime;
6 mjames 162
 
11 mjames 163
                        if(diffTime > BREAKER_COUNT_MIN)
6 mjames 164
                        {
11 mjames 165
                                lastSampleIndex = outSampleCount;
166
                                return nextTime;
6 mjames 167
                        }
168
 
169
        }
11 mjames 170
  return 0;
171
}
6 mjames 172
 
11 mjames 173
 
174
void processNextPulse(uint16_t retVal)
175
{
176
 
12 mjames 177
        static uint32_t VperiodAccumulator = 0;
178
    // scale it up by 32
179
        static uint32_t periodEstimate = 2000 * 256 ;
11 mjames 180
        static uint16_t lastVal = 0;
6 mjames 181
        // at this point we should try to phase lock
11 mjames 182
    deltaTime = retVal - lastVal;
6 mjames 183
 
11 mjames 184
 
185
 
186
    if(deltaTime > 10000)
187
    {
188
        __asm(" BKPT #0");
189
    }
190
 
6 mjames 191
    lastVal = retVal;
192
 
12 mjames 193
    // look at the values and try to pull them togwther
6 mjames 194
 
12 mjames 195
    // accumulate phase
196
    VperiodAccumulator += periodEstimate;
197
    VperiodAccumulator &= 0xFFFFFFF;
11 mjames 198
 
12 mjames 199
    uint16_t accum_low = (VperiodAccumulator) >> 8;
200
#define WINDOW 1000
11 mjames 201
 
12 mjames 202
#define LIMIT 2048
11 mjames 203
 
12 mjames 204
#define STEP 32
11 mjames 205
 
12 mjames 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;
6 mjames 211
 
12 mjames 212
    if(pdI > LIMIT)
213
        pdI = LIMIT;
214
    if(pdI < -(LIMIT))
215
        pdI = -(LIMIT);
6 mjames 216
 
217
 
218
 
12 mjames 219
    signed pd = (signed)(periodEstimate)- (signed)(deltaTime*256) + pdI;
6 mjames 220
 
221
 
12 mjames 222
    periodEstimate -= pd / 100;
6 mjames 223
 
12 mjames 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
 
6 mjames 238
//      rpm += delta / 256;
239
 
240
        adjustRPM();
11 mjames 241
    }
6 mjames 242
 
243
 
244
 
11 mjames 245
 
6 mjames 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;
11 mjames 263
            if (sampleCount >= SAMPLE_BUFF_SIZE)
6 mjames 264
                sampleCount = 0;
265
        }
266
}
267
 
268
 
269