Subversion Repositories FlightCtrl

Rev

Rev 2099 | Rev 2125 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2099 Rev 2124
1
#include <inttypes.h>
1
#include <inttypes.h>
2
#include <avr/io.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
3
#include <avr/interrupt.h>
4
#include "eeprom.h"
4
#include "eeprom.h"
5
#include "analog.h"
5
#include "analog.h"
6
#include "controlMixer.h"
6
#include "controlMixer.h"
7
 
7
 
8
#include "timer0.h"
8
#include "timer0.h"
9
#include "output.h"
9
#include "output.h"
10
 
10
 
11
#ifdef USE_MK3MAG
11
#ifdef DO_PROFILE
-
 
12
uint32_t profileTimers[NUM_PROFILE_TIMERS];
12
#include "mk3mag.h"
13
uint32_t runningProfileTimers[NUM_PROFILE_TIMERS];
13
#endif
14
#endif
14
 
15
 
15
volatile uint32_t globalMillisClock = 0;
16
volatile uint32_t globalMillisClock = 0;
16
volatile uint8_t  runFlightControl = 0;
17
volatile uint8_t  runFlightControl = 0;
17
volatile uint16_t beepTime = 0;
18
volatile uint16_t beepTime = 0;
18
volatile uint16_t beepModulation = BEEP_MODULATION_NONE;
19
volatile uint16_t beepModulation = BEEP_MODULATION_NONE;
19
 
-
 
20
#ifdef USE_NAVICTRL
-
 
21
volatile uint8_t SendSPI = 0;
-
 
22
#endif
-
 
23
 
20
 
24
/*****************************************************
21
/*****************************************************
25
 * Initialize Timer 0                  
22
 * Initialize Timer 0                  
26
 *****************************************************/
23
 *****************************************************/
27
// timer 0 is used for the PWM generation to control the offset voltage at the air pressure sensor
24
// timer 0 is used for the PWM generation to control the offset voltage at the air pressure sensor
28
// Its overflow interrupt routine is used to generate the beep signal and the flight control motor update rate
25
// Its overflow interrupt routine is used to generate the beep signal and the flight control motor update rate
29
void timer0_init(void) {
26
void timer0_init(void) {
30
  uint8_t sreg = SREG;
27
  uint8_t sreg = SREG;
31
 
28
 
32
  // disable all interrupts before reconfiguration
29
  // disable all interrupts before reconfiguration
33
  cli();
30
  cli();
34
 
31
 
35
  // Configure speaker port as output.
32
  // Configure speaker port as output.
36
  if (boardRelease == 10) { // Speaker at PD2
33
  if (boardRelease == 10) { // Speaker at PD2
37
    DDRD |= (1 << DDD2);
34
    DDRD |= (1 << DDD2);
38
    PORTD &= ~(1 << PORTD2);
35
    PORTD &= ~(1 << PORTD2);
39
  } else { // Speaker at PC7
36
  } else { // Speaker at PC7
40
    DDRC |= (1 << DDC7);
37
    DDRC |= (1 << DDC7);
41
    PORTC &= ~(1 << PORTC7);
38
    PORTC &= ~(1 << PORTC7);
42
  }
39
  }
43
 
40
 
44
  // set PB3 and PB4 as output for the PWM used as offset for the pressure sensor
41
  // set PB3 and PB4 as output for the PWM used as offset for the pressure sensor
45
  DDRB |= (1 << DDB4) | (1 << DDB3);
42
  DDRB |= (1 << DDB4) | (1 << DDB3);
46
  PORTB &= ~((1 << PORTB4) | (1 << PORTB3));
43
  PORTB &= ~((1 << PORTB4) | (1 << PORTB3));
47
 
44
 
48
  // Timer/Counter 0 Control Register A
45
  // Timer/Counter 0 Control Register A
49
 
46
 
50
  // Waveform Generation Mode is Fast PWM (Bits WGM02 = 0, WGM01 = 1, WGM00 = 1)
47
  // Waveform Generation Mode is Fast PWM (Bits WGM02 = 0, WGM01 = 1, WGM00 = 1)
51
  // Clear OC0A on Compare Match, set OC0A at BOTTOM, noninverting PWM (Bits COM0A1 = 1, COM0A0 = 0)
48
  // Clear OC0A on Compare Match, set OC0A at BOTTOM, noninverting PWM (Bits COM0A1 = 1, COM0A0 = 0)
52
  // Clear OC0B on Compare Match, set OC0B at BOTTOM, (Bits COM0B1 = 1, COM0B0 = 0)
49
  // Clear OC0B on Compare Match, set OC0B at BOTTOM, (Bits COM0B1 = 1, COM0B0 = 0)
53
  TCCR0A &= ~((1 << COM0A0) | (1 << COM0B0));
50
  TCCR0A &= ~((1 << COM0A0) | (1 << COM0B0));
54
  TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
51
  TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
55
 
52
 
56
  // Timer/Counter 0 Control Register B
53
  // Timer/Counter 0 Control Register B
57
  // set clock divider for timer 0 to SYSCLOCK/8 = 20MHz/8 = 2.5MHz
54
  // set clock divider for timer 0 to SYSCLOCK/8 = 20MHz/8 = 2.5MHz
58
  // i.e. the timer increments from 0x00 to 0xFF with an update rate of 2.5 MHz
55
  // i.e. the timer increments from 0x00 to 0xFF with an update rate of 2.5 MHz
59
  // hence the timer overflow interrupt frequency is 2.5 MHz/256 = 9.765 kHz
56
  // hence the timer overflow interrupt frequency is 2.5 MHz/256 = 9.765 kHz
60
 
57
 
61
  // divider 8 (Bits CS02 = 0, CS01 = 1, CS00 = 0)
58
  // divider 8 (Bits CS02 = 0, CS01 = 1, CS00 = 0)
62
  TCCR0B &= ~((1 << FOC0A) | (1 << FOC0B) | (1 << WGM02));
59
  TCCR0B &= ~((1 << FOC0A) | (1 << FOC0B) | (1 << WGM02));
63
  TCCR0B = (TCCR0B & 0xF8) | (0 << CS02) | (1 << CS01) | (0 << CS00);
60
  TCCR0B = (TCCR0B & 0xF8) | (0 << CS02) | (1 << CS01) | (0 << CS00);
64
 
61
 
65
  // initialize the Output Compare Register A & B used for PWM generation on port PB3 & PB4
62
  // initialize the Output Compare Register A & B used for PWM generation on port PB3 & PB4
66
  OCR0A = 0; // for PB3
63
  OCR0A = 0; // for PB3
67
  OCR0B = 120; // for PB4
64
  OCR0B = 120; // for PB4
68
 
65
 
69
  // init Timer/Counter 0 Register
66
  // init Timer/Counter 0 Register
70
  TCNT0 = 0;
67
  TCNT0 = 0;
71
 
68
 
72
  // Timer/Counter 0 Interrupt Mask Register
69
  // Timer/Counter 0 Interrupt Mask Register
73
  // enable timer overflow interrupt only
70
  // enable timer overflow interrupt only
74
  TIMSK0 &= ~((1 << OCIE0B) | (1 << OCIE0A));
71
  TIMSK0 &= ~((1 << OCIE0B) | (1 << OCIE0A));
75
  TIMSK0 |= (1 << TOIE0);
72
  TIMSK0 |= (1 << TOIE0);
-
 
73
 
-
 
74
#ifdef DO_PROFILE
-
 
75
  for (uint8_t i=0; i<NUM_PROFILE_TIMERS; i++) {
-
 
76
          profileTimers[i] = 0;
-
 
77
  }
-
 
78
#endif
76
 
79
 
77
  SREG = sreg;
80
  SREG = sreg;
78
}
81
}
79
 
82
 
80
/*****************************************************/
83
/*****************************************************/
81
/*          Interrupt Routine of Timer 0             */
84
/*          Interrupt Routine of Timer 0             */
82
/*****************************************************/
85
/*****************************************************/
83
ISR(TIMER0_OVF_vect) { // 9765.625 Hz
86
ISR(TIMER0_OVF_vect) { // 9765.625 Hz
84
  static uint8_t cnt_1ms = 1, cnt = 0;
87
  static uint8_t cnt_1ms = 1, cnt = 0;
85
  uint8_t beeperOn = 0;
88
  uint8_t beeperOn = 0;
86
 
-
 
87
#ifdef USE_NAVICTRL
-
 
88
  if(SendSPI) SendSPI--; // if SendSPI is 0, the transmit of a byte via SPI bus to and from The Navicontrol is done
-
 
89
#endif
-
 
90
 
89
 
91
  if (!cnt--) { // every 10th run (9.765625kHz/10 = 976.5625Hz)
90
  if (!cnt--) { // every 10th run (9.765625kHz/10 = 976.5625Hz)
92
    cnt = 9;
91
    cnt = 9;
93
    cnt_1ms ^= 1;
92
    cnt_1ms ^= 1;
94
    if (!cnt_1ms) {
93
    if (!cnt_1ms) {
95
      if (runFlightControl == 1)
-
 
96
        debugOut.digital[1] |= DEBUG_MAINLOOP_TIMER;
-
 
97
      else
-
 
98
        debugOut.digital[1] &= ~DEBUG_MAINLOOP_TIMER;
-
 
99
      runFlightControl = 1; // every 2nd run (976.5625 Hz/2 = 488.28125 Hz)
94
      runFlightControl = 1; // every 2nd run (976.5625 Hz/2 = 488.28125 Hz)
100
    }
95
    }
101
    globalMillisClock++; // increment millisecond counter
96
    globalMillisClock++; // increment millisecond counter
102
  }
97
  }
103
 
98
 
104
  // beeper on if duration is not over
99
  // beeper on if duration is not over
105
  if (beepTime) {
100
  if (beepTime) {
106
    beepTime--; // decrement BeepTime
101
    beepTime--; // decrement BeepTime
107
    if (beepTime & beepModulation)
102
    if (beepTime & beepModulation)
108
      beeperOn = 1;
103
      beeperOn = 1;
109
    else
104
    else
110
      beeperOn = 0;
105
      beeperOn = 0;
111
  } else { // beeper off if duration is over
106
  } else { // beeper off if duration is over
112
    beeperOn = 0;
107
    beeperOn = 0;
113
    beepModulation = BEEP_MODULATION_NONE;
108
    beepModulation = BEEP_MODULATION_NONE;
114
  }
109
  }
115
 
110
 
116
  if (beeperOn) {
111
  if (beeperOn) {
117
    // set speaker port to high.
112
    // set speaker port to high.
118
    if (boardRelease == 10)
113
    if (boardRelease == 10)
119
      PORTD |= (1 << PORTD2); // Speaker at PD2
114
      PORTD |= (1 << PORTD2); // Speaker at PD2
120
    else
115
    else
121
      PORTC |= (1 << PORTC7); // Speaker at PC7
116
      PORTC |= (1 << PORTC7); // Speaker at PC7
122
  } else { // beeper is off
117
  } else { // beeper is off
123
    // set speaker port to low
118
    // set speaker port to low
124
    if (boardRelease == 10)
119
    if (boardRelease == 10)
125
      PORTD &= ~(1 << PORTD2);// Speaker at PD2
120
      PORTD &= ~(1 << PORTD2);// Speaker at PD2
126
    else
121
    else
127
      PORTC &= ~(1 << PORTC7);// Speaker at PC7
122
      PORTC &= ~(1 << PORTC7);// Speaker at PC7
128
  }
123
  }
129
 
124
 
130
#ifdef USE_MK3MAG
125
#ifdef USE_MK3MAG
131
  // update compass value if this option is enabled in the settings
126
  // update compass value if this option is enabled in the settings
132
  if (staticParams.bitConfig & CFG_COMPASS_ENABLED) {
127
  if (staticParams.bitConfig & CFG_COMPASS_ENABLED) {
133
    MK3MAG_periodicTask(); // read out mk3mag pwm
128
    MK3MAG_periodicTask(); // read out mk3mag pwm
134
  }
129
  }
135
#endif
130
#endif
136
}
131
}
137
 
132
 
138
// -----------------------------------------------------------------------
133
// -----------------------------------------------------------------------
139
uint16_t setDelay(uint16_t t) {
134
uint16_t setDelay(uint16_t t) {
140
  return (globalMillisClock + t - 1);
135
  return (globalMillisClock + t - 1);
141
}
136
}
142
 
137
 
143
// -----------------------------------------------------------------------
138
// -----------------------------------------------------------------------
144
int8_t checkDelay(uint16_t t) {
139
int8_t checkDelay(uint16_t t) {
145
  return (((t - globalMillisClock) & 0x8000) >> 8); // check sign bit
140
  return (((t - globalMillisClock) & 0x8000) >> 8); // check sign bit
146
}
141
}
147
 
142
 
148
// -----------------------------------------------------------------------
143
// -----------------------------------------------------------------------
149
void delay_ms(uint16_t w) {
144
void delay_ms(uint16_t w) {
150
  uint16_t t_stop = setDelay(w);
145
  uint16_t t_stop = setDelay(w);
151
  while (!checkDelay(t_stop))
146
  while (!checkDelay(t_stop))
152
    ;
147
    ;
153
}
148
}
154
 
149
 
155
// -----------------------------------------------------------------------
150
// -----------------------------------------------------------------------
156
void delay_ms_with_adc_measurement(uint16_t w, uint8_t stop) {
151
void delay_ms_with_adc_measurement(uint16_t w, uint8_t stop) {
157
  uint16_t t_stop;
152
  uint16_t t_stop;
158
  t_stop = setDelay(w);
153
  t_stop = setDelay(w);
159
  while (!checkDelay(t_stop)) {
154
  while (!checkDelay(t_stop)) {
160
        if (analogDataReady) {
155
        if (analogDataReady) {
161
          analog_update();
156
          analog_update();
162
          startAnalogConversionCycle();
157
          startAnalogConversionCycle();
163
        }
158
        }
164
  }
159
  }
165
  if (stop) {
160
  if (stop) {
166
  // Wait for new samples to get prepared but do not restart AD conversion after that!
161
  // Wait for new samples to get prepared but do not restart AD conversion after that!
167
  // Caller MUST to that.
162
  // Caller MUST to that.
168
        while (!analogDataReady);
163
        while (!analogDataReady);
169
  }
164
  }
170
}
165
}
-
 
166
 
-
 
167
#ifdef DO_PROFILE
-
 
168
void startProfileTimer(uint8_t timer) {
-
 
169
  runningProfileTimers[timer] = globalMillisClock;
-
 
170
}
-
 
171
 
-
 
172
void stopProfileTimer(uint8_t timer) {
-
 
173
  int32_t t = globalMillisClock - runningProfileTimers[timer];
-
 
174
  profileTimers[timer] += t;
-
 
175
}
-
 
176
 
-
 
177
void debugProfileTimers(uint8_t index) {
-
 
178
  for (uint8_t i=0; i<NUM_PROFILE_TIMERS; i++) {
-
 
179
        uint16_t tenths = profileTimers[i] / 10000L;
-
 
180
        debugOut.analog[i+index] = tenths;
-
 
181
  }
-
 
182
  uint16_t tenths = globalMillisClock / 10000L;
-
 
183
  debugOut.analog[index + NUM_PROFILE_TIMERS] = tenths;
-
 
184
}
-
 
185
#endif;
171
 
186