Subversion Repositories chibiosIgnition

Rev

Rev 6 | Rev 8 | 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
 
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
 
7 mjames 48
        /// pulse width 200 uS
49
        TIM2->CCR1 = 200/MICROSECS_PULSE;
6 mjames 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,
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
        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