Subversion Repositories chibiosIgnition

Rev

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