Subversion Repositories FlightCtrl

Rev

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

Rev 2055 Rev 2058
1
#include <stdlib.h>
1
#include <stdlib.h>
2
#include <avr/io.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
3
#include <avr/interrupt.h>
4
 
4
 
5
#include "rc.h"
5
#include "rc.h"
6
#include "controlMixer.h"
6
#include "controlMixer.h"
7
#include "configuration.h"
7
#include "configuration.h"
8
#include "commands.h"
8
#include "commands.h"
9
#include "output.h"
9
#include "output.h"
10
 
10
 
11
// The channel array is 0-based!
11
// The channel array is 0-based!
12
volatile int16_t PPM_in[MAX_CHANNELS];
12
volatile int16_t PPM_in[MAX_CHANNELS];
13
volatile int16_t PPM_diff[MAX_CHANNELS];
13
volatile int16_t PPM_diff[MAX_CHANNELS];
14
volatile uint8_t RCQuality;
14
volatile uint8_t RCQuality;
15
uint8_t lastRCCommand = COMMAND_NONE;
15
uint8_t lastRCCommand = COMMAND_NONE;
16
uint8_t commandTimer = 0;
16
uint8_t commandTimer = 0;
17
 
17
 
18
/***************************************************************
18
/***************************************************************
19
 *  16bit timer 1 is used to decode the PPM-Signal            
19
 *  16bit timer 1 is used to decode the PPM-Signal            
20
 ***************************************************************/
20
 ***************************************************************/
21
void RC_Init(void) {
21
void RC_Init(void) {
22
  uint8_t sreg = SREG;
22
  uint8_t sreg = SREG;
23
 
23
 
24
  // disable all interrupts before reconfiguration
24
  // disable all interrupts before reconfiguration
25
  cli();
25
  cli();
26
 
26
 
27
  // PPM-signal is connected to the Input Capture Pin (PD6) of timer 1
27
  // PPM-signal is connected to the Input Capture Pin (PD6) of timer 1
28
  DDRD &= ~(1<<6);
28
  DDRD &= ~(1<<6);
29
  PORTD |= (1<<PORTD6);
29
  PORTD |= (1<<PORTD6);
30
 
30
 
31
  // Channel 5,6,7 is decoded to servo signals at pin PD5 (J3), PD4(J4), PD3(J5)
31
  // Channel 5,6,7 is decoded to servo signals at pin PD5 (J3), PD4(J4), PD3(J5)
32
  // set as output
32
  // set as output
33
  DDRD |= (1<<DDD5) | (1<<DDD4) | (1<<DDD3);
33
  DDRD |= (1<<DDD5) | (1<<DDD4) | (1<<DDD3);
34
  // low level
34
  // low level
35
  PORTD &= ~((1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3));
35
  PORTD &= ~((1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3));
36
 
36
 
37
  // PD3 can't be used if 2nd UART is activated
37
  // PD3 can't be used if 2nd UART is activated
38
  // because TXD1 is at that port
38
  // because TXD1 is at that port
39
  if (CPUType != ATMEGA644P) {
39
  if (CPUType != ATMEGA644P) {
40
    DDRD |= (1<<PORTD3);
40
    DDRD |= (1<<PORTD3);
41
    PORTD &= ~(1<<PORTD3);
41
    PORTD &= ~(1<<PORTD3);
42
  }
42
  }
43
 
43
 
44
  // Timer/Counter1 Control Register A, B, C
44
  // Timer/Counter1 Control Register A, B, C
45
 
45
 
46
  // Normal Mode (bits: WGM13=0, WGM12=0, WGM11=0, WGM10=0)
46
  // Normal Mode (bits: WGM13=0, WGM12=0, WGM11=0, WGM10=0)
47
  // Compare output pin A & B is disabled (bits: COM1A1=0, COM1A0=0, COM1B1=0, COM1B0=0)
47
  // Compare output pin A & B is disabled (bits: COM1A1=0, COM1A0=0, COM1B1=0, COM1B0=0)
48
  // Set clock source to SYSCLK/64 (bit: CS12=0, CS11=1, CS10=1)
48
  // Set clock source to SYSCLK/64 (bit: CS12=0, CS11=1, CS10=1)
49
  // Enable input capture noise cancler (bit: ICNC1=1)
49
  // Enable input capture noise cancler (bit: ICNC1=1)
50
  // Trigger on positive edge of the input capture pin (bit: ICES1=1),
50
  // Trigger on positive edge of the input capture pin (bit: ICES1=1),
51
  // Therefore the counter incremets at a clock of 20 MHz/64 = 312.5 kHz or 3.2�s
51
  // Therefore the counter incremets at a clock of 20 MHz/64 = 312.5 kHz or 3.2�s
52
  // The longest period is 0xFFFF / 312.5 kHz = 0.209712 s.
52
  // The longest period is 0xFFFF / 312.5 kHz = 0.209712 s.
53
  TCCR1A &= ~((1 << COM1A1) | (1 << COM1A0) | (1 << COM1B1) | (1 << COM1B0) | (1 << WGM11) | (1 << WGM10));
53
  TCCR1A &= ~((1 << COM1A1) | (1 << COM1A0) | (1 << COM1B1) | (1 << COM1B0) | (1 << WGM11) | (1 << WGM10));
54
  TCCR1B &= ~((1 << WGM13) | (1 << WGM12) | (1 << CS12));
54
  TCCR1B &= ~((1 << WGM13) | (1 << WGM12) | (1 << CS12));
55
  TCCR1B |= (1 << CS11) | (1 << CS10) | (1 << ICES1) | (1 << ICNC1);
55
  TCCR1B |= (1 << CS11) | (1 << CS10) | (1 << ICES1) | (1 << ICNC1);
56
  TCCR1C &= ~((1 << FOC1A) | (1 << FOC1B));
56
  TCCR1C &= ~((1 << FOC1A) | (1 << FOC1B));
57
 
57
 
58
  // Timer/Counter1 Interrupt Mask Register
58
  // Timer/Counter1 Interrupt Mask Register
59
  // Enable Input Capture Interrupt (bit: ICIE1=1)
59
  // Enable Input Capture Interrupt (bit: ICIE1=1)
60
  // Disable Output Compare A & B Match Interrupts (bit: OCIE1B=0, OICIE1A=0)
60
  // Disable Output Compare A & B Match Interrupts (bit: OCIE1B=0, OICIE1A=0)
61
  // Enable Overflow Interrupt (bit: TOIE1=0)
61
  // Enable Overflow Interrupt (bit: TOIE1=0)
62
  TIMSK1 &= ~((1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1));
62
  TIMSK1 &= ~((1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1));
63
  TIMSK1 |= (1<<ICIE1);
63
  TIMSK1 |= (1<<ICIE1);
64
 
64
 
65
  RCQuality = 0;
65
  RCQuality = 0;
66
 
66
 
67
  SREG = sreg;
67
  SREG = sreg;
68
}
68
}
69
 
69
 
70
/********************************************************************/
70
/********************************************************************/
71
/*         Every time a positive edge is detected at PD6            */
71
/*         Every time a positive edge is detected at PD6            */
72
/********************************************************************/
72
/********************************************************************/
73
/*                               t-Frame
73
/*                               t-Frame
74
    <----------------------------------------------------------------------->
74
    <----------------------------------------------------------------------->
75
     ____   ______   _____   ________                ______    sync gap      ____
75
     ____   ______   _____   ________                ______    sync gap      ____
76
    |    | |      | |     | |        |              |      |                |
76
    |    | |      | |     | |        |              |      |                |
77
    |    | |      | |     | |        |              |      |                |
77
    |    | |      | |     | |        |              |      |                |
78
 ___|    |_|      |_|     |_|        |_.............|      |________________|
78
 ___|    |_|      |_|     |_|        |_.............|      |________________|
79
    <-----><-------><------><-----------            <------>                <---
79
    <-----><-------><------><-----------            <------>                <---
80
 t0       t1      t2       t4                     tn                     t0
80
 t0       t1      t2       t4                     tn                     t0
81
 
81
 
82
 The PPM-Frame length is 22.5 ms.
82
 The PPM-Frame length is 22.5 ms.
83
 Channel high pulse width range is 0.7 ms to 1.7 ms completed by an 0.3 ms low pulse.
83
 Channel high pulse width range is 0.7 ms to 1.7 ms completed by an 0.3 ms low pulse.
84
 The mininimum time delay of two events coding a channel is ( 0.7 + 0.3) ms = 1 ms.
84
 The mininimum time delay of two events coding a channel is ( 0.7 + 0.3) ms = 1 ms.
85
 The maximum time delay of two events coding a channel is ( 1.7 + 0.3) ms = 2 ms.
85
 The maximum time delay of two events coding a channel is ( 1.7 + 0.3) ms = 2 ms.
86
 The minimum duration of all channels at minimum value is  8 * 1 ms = 8 ms.
86
 The minimum duration of all channels at minimum value is  8 * 1 ms = 8 ms.
87
 The maximum duration of all channels at maximum value is  8 * 2 ms = 16 ms.
87
 The maximum duration of all channels at maximum value is  8 * 2 ms = 16 ms.
88
 The remaining time of (22.5 - 8 ms) ms = 14.5 ms  to (22.5 - 16 ms) ms = 6.5 ms is
88
 The remaining time of (22.5 - 8 ms) ms = 14.5 ms  to (22.5 - 16 ms) ms = 6.5 ms is
89
 the syncronization gap.
89
 the syncronization gap.
90
 */
90
 */
91
ISR(TIMER1_CAPT_vect) { // typical rate of 1 ms to 2 ms
91
ISR(TIMER1_CAPT_vect) { // typical rate of 1 ms to 2 ms
92
  int16_t signal = 0, tmp;
92
  int16_t signal = 0, tmp;
93
  static int16_t index;
93
  static int16_t index;
94
  static uint16_t oldICR1 = 0;
94
  static uint16_t oldICR1 = 0;
95
 
95
 
96
  // 16bit Input Capture Register ICR1 contains the timer value TCNT1
96
  // 16bit Input Capture Register ICR1 contains the timer value TCNT1
97
  // at the time the edge was detected
97
  // at the time the edge was detected
98
 
98
 
99
  // calculate the time delay to the previous event time which is stored in oldICR1
99
  // calculate the time delay to the previous event time which is stored in oldICR1
100
  // calculatiing the difference of the two uint16_t and converting the result to an int16_t
100
  // calculatiing the difference of the two uint16_t and converting the result to an int16_t
101
  // implicit handles a timer overflow 65535 -> 0 the right way.
101
  // implicit handles a timer overflow 65535 -> 0 the right way.
102
  signal = (uint16_t) ICR1 - oldICR1;
102
  signal = (uint16_t) ICR1 - oldICR1;
103
  oldICR1 = ICR1;
103
  oldICR1 = ICR1;
104
 
104
 
105
  //sync gap? (3.52 ms < signal < 25.6 ms)
105
  //sync gap? (3.52 ms < signal < 25.6 ms)
106
  if ((signal > 1100) && (signal < 8000)) {
106
  if ((signal > 1100) && (signal < 8000)) {
107
    index = 0;
107
    index = 0;
108
  } else { // within the PPM frame
108
  } else { // within the PPM frame
109
    if (index < MAX_CHANNELS) { // PPM24 supports 12 channels
109
    if (index < MAX_CHANNELS) { // PPM24 supports 12 channels
110
      // check for valid signal length (0.8 ms < signal < 2.1984 ms)
110
      // check for valid signal length (0.8 ms < signal < 2.1984 ms)
111
      // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
111
      // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
112
      if ((signal > 250) && (signal < 687)) {
112
      if ((signal > 250) && (signal < 687)) {
113
        // shift signal to zero symmetric range  -154 to 159
113
        // shift signal to zero symmetric range  -154 to 159
114
        signal -= 470; // offset of 1.4912 ms ??? (469 * 3.2us = 1.5008 ms)
114
        signal -= 470; // offset of 1.4912 ms ??? (469 * 3.2us = 1.5008 ms)
115
        // check for stable signal
115
        // check for stable signal
116
        if (abs(signal - PPM_in[index]) < 6) {
116
        if (abs(signal - PPM_in[index]) < 6) {
117
          if (RCQuality < 200)
117
          if (RCQuality < 200)
118
            RCQuality += 10;
118
            RCQuality += 10;
119
          else
119
          else
120
            RCQuality = 200;
120
            RCQuality = 200;
121
        }
121
        }
122
        // If signal is the same as before +/- 1, just keep it there. Naah lets get rid of this slimy sticy stuff.
122
        // If signal is the same as before +/- 1, just keep it there. Naah lets get rid of this slimy sticy stuff.
123
        // if (signal >= PPM_in[index] - 1 && signal <= PPM_in[index] + 1) {
123
        // if (signal >= PPM_in[index] - 1 && signal <= PPM_in[index] + 1) {
124
          // In addition, if the signal is very close to 0, just set it to 0.
124
          // In addition, if the signal is very close to 0, just set it to 0.
125
        if (signal >= -1 && signal <= 1) {
125
        if (signal >= -1 && signal <= 1) {
126
          tmp = 0;
126
          tmp = 0;
127
        //} else {
127
        //} else {
128
        //  tmp = PPM_in[index];
128
        //  tmp = PPM_in[index];
129
        //  }
129
        //  }
130
        } else
130
        } else
131
          tmp = signal;
131
          tmp = signal;
132
        // calculate signal difference on good signal level
132
        // calculate signal difference on good signal level
133
        if (RCQuality >= 195)
133
        if (RCQuality >= 195)
134
          PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
134
          PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
135
        else
135
        else
136
          PPM_diff[index] = 0;
136
          PPM_diff[index] = 0;
137
        PPM_in[index] = tmp; // update channel value
137
        PPM_in[index] = tmp; // update channel value
138
      }
138
      }
139
      index++; // next channel
139
      index++; // next channel
140
      // demux sum signal for channels 5 to 7 to J3, J4, J5
140
      // demux sum signal for channels 5 to 7 to J3, J4, J5
141
      // TODO: General configurability of this R/C channel forwarding. Or remove it completely - the
141
      // TODO: General configurability of this R/C channel forwarding. Or remove it completely - the
142
      // channels are usually available at the receiver anyway.
142
      // channels are usually available at the receiver anyway.
143
      // if(index == 5) J3HIGH; else J3LOW;
143
      // if(index == 5) J3HIGH; else J3LOW;
144
      // if(index == 6) J4HIGH; else J4LOW;
144
      // if(index == 6) J4HIGH; else J4LOW;
145
      // if(CPUType != ATMEGA644P) // not used as TXD1
145
      // if(CPUType != ATMEGA644P) // not used as TXD1
146
      //  {
146
      //  {
147
      //    if(index == 7) J5HIGH; else J5LOW;
147
      //    if(index == 7) J5HIGH; else J5LOW;
148
      //  }
148
      //  }
149
    }
149
    }
150
  }
150
  }
151
}
151
}
152
 
152
 
153
#define RCChannel(dimension) PPM_in[channelMap.channels[dimension]]
153
#define RCChannel(dimension) PPM_in[channelMap.channels[dimension]]
154
#define RCDiff(dimension) PPM_diff[channelMap.channels[dimension]]
154
#define RCDiff(dimension) PPM_diff[channelMap.channels[dimension]]
155
#define COMMAND_THRESHOLD 85
155
#define COMMAND_THRESHOLD 85
156
#define COMMAND_CHANNEL_VERTICAL CH_THROTTLE
156
#define COMMAND_CHANNEL_VERTICAL CH_THROTTLE
157
#define COMMAND_CHANNEL_HORIZONTAL CH_YAW
157
#define COMMAND_CHANNEL_HORIZONTAL CH_YAW
158
 
158
 
159
// Internal.
159
// Internal.
160
uint8_t RC_getStickCommand(void) {
160
uint8_t RC_getStickCommand(void) {
161
  if (RCChannel(COMMAND_CHANNEL_VERTICAL) > COMMAND_THRESHOLD) {
161
  if (RCChannel(COMMAND_CHANNEL_VERTICAL) > COMMAND_THRESHOLD) {
162
    // vertical is up
162
    // vertical is up
163
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) > COMMAND_THRESHOLD)
163
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) > COMMAND_THRESHOLD)
164
      return COMMAND_GYROCAL;
164
      return COMMAND_GYROCAL;
165
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) < -COMMAND_THRESHOLD)
165
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) < -COMMAND_THRESHOLD)
166
      return COMMAND_ACCCAL;
166
      return COMMAND_ACCCAL;
167
    return COMMAND_NONE;
167
    return COMMAND_NONE;
168
  } else if (RCChannel(COMMAND_CHANNEL_VERTICAL) < -COMMAND_THRESHOLD) {
168
  } else if (RCChannel(COMMAND_CHANNEL_VERTICAL) < -COMMAND_THRESHOLD) {
169
    // vertical is down
169
    // vertical is down
170
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) > COMMAND_THRESHOLD)
170
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) > COMMAND_THRESHOLD)
171
      return COMMAND_STOP;
171
      return COMMAND_STOP;
172
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) < -COMMAND_THRESHOLD)
172
    if (RCChannel(COMMAND_CHANNEL_HORIZONTAL) < -COMMAND_THRESHOLD)
173
      return COMMAND_START;
173
      return COMMAND_START;
174
    return COMMAND_NONE;
174
    return COMMAND_NONE;
175
  }
175
  }
176
  // vertical is around center
176
  // vertical is around center
177
  return COMMAND_NONE;
177
  return COMMAND_NONE;
178
}
178
}
179
 
179
 
180
/*
180
/*
181
 * Get Pitch, Roll, Throttle, Yaw values
181
 * Get Pitch, Roll, Throttle, Yaw values
182
 */
182
 */
183
void RC_periodicTaskAndPRTY(int16_t* PRTY) {
183
void RC_periodicTaskAndPRTY(int16_t* PRTY) {
184
  int16_t tmp1, tmp2;
184
  int16_t tmp1, tmp2;
185
  if (RCQuality) {
185
  if (RCQuality) {
186
    RCQuality--;
186
    RCQuality--;
187
    PRTY[CONTROL_PITCH]     += RCChannel(CH_PITCH) * staticParams.stickP + RCDiff(CH_PITCH) * staticParams.stickD;
187
    PRTY[CONTROL_PITCH]     += RCChannel(CH_PITCH) * staticParams.stickP + RCDiff(CH_PITCH) * staticParams.stickD;
188
    PRTY[CONTROL_ROLL]      += RCChannel(CH_ROLL) * staticParams.stickP + RCDiff(CH_ROLL) * staticParams.stickD;
188
    PRTY[CONTROL_ROLL]      += RCChannel(CH_ROLL) * staticParams.stickP + RCDiff(CH_ROLL) * staticParams.stickD;
189
    int16_t throttle = RCChannel(CH_THROTTLE) + RCDiff(CH_THROTTLE) * staticParams.stickThrottleD + 120;
189
    int16_t throttle = RCChannel(CH_THROTTLE) + RCDiff(CH_THROTTLE) * staticParams.stickThrottleD + 120;
190
    // Negative throttle values are taken as zero.
190
    // Negative throttle values are taken as zero.
191
    if (throttle > 0)
191
    if (throttle > 0)
192
      PRTY[CONTROL_THROTTLE]  += throttle;
192
      PRTY[CONTROL_THROTTLE]  += throttle;
193
    tmp1 = -RCChannel(CH_YAW) - RCDiff(CH_YAW);
193
    tmp1 = -RCChannel(CH_YAW) - RCDiff(CH_YAW);
194
    // exponential stick sensitivity in yawing rate
194
    // exponential stick sensitivity in yawing rate
195
    tmp2 = (int32_t)staticParams.stickYawP * ((int32_t)tmp1 * abs(tmp1)) >> 9; // expo  y = ax + bx^2
195
    tmp2 = (int32_t)staticParams.stickYawP * ((int32_t)tmp1 * abs(tmp1)) >> 9; // expo  y = ax + bx^2
196
    tmp2 += (staticParams.stickYawP * tmp1) >> 2;
196
    tmp2 += (staticParams.stickYawP * tmp1) >> 2;
197
    PRTY[CONTROL_YAW] += tmp2;
197
    PRTY[CONTROL_YAW] += tmp2;
198
 
198
 
199
    uint8_t command = RC_getStickCommand();
199
    uint8_t command = RC_getStickCommand();
200
    if (lastRCCommand == command) {
200
    if (lastRCCommand == command) {
201
      // Keep timer from overrunning.
201
      // Keep timer from overrunning.
202
      if (commandTimer < COMMAND_TIMER)
202
      if (commandTimer < COMMAND_TIMER)
203
        commandTimer++;
203
        commandTimer++;
204
    } else {
204
    } else {
205
      // There was a change.
205
      // There was a change.
206
      lastRCCommand = command;
206
      lastRCCommand = command;
207
      commandTimer = 0;
207
      commandTimer = 0;
208
    }
208
    }
209
  } // if RCQuality is no good, we just do nothing.
209
  } // if RCQuality is no good, we just do nothing.
210
  // debugOut.analog[18] = RCQuality;
-
 
211
}
210
}
212
 
211
 
213
/*
212
/*
214
 * Get other channel value
213
 * Get other channel value
215
 */
214
 */
216
int16_t RC_getVariable(uint8_t varNum) {
215
int16_t RC_getVariable(uint8_t varNum) {
217
  if (varNum < 4)
216
  if (varNum < 4)
218
    // 0th variable is 5th channel (1-based) etc.
217
    // 0th variable is 5th channel (1-based) etc.
219
    return RCChannel(varNum + CH_POTS) + POT_OFFSET;
218
    return RCChannel(varNum + CH_POTS) + POT_OFFSET;
220
  /*
219
  /*
221
   * Let's just say:
220
   * Let's just say:
222
   * The RC variable i is hardwired to channel i, i>=4
221
   * The RC variable i is hardwired to channel i, i>=4
223
   */
222
   */
224
  return PPM_in[varNum] + POT_OFFSET;
223
  return PPM_in[varNum] + POT_OFFSET;
225
}
224
}
226
 
225
 
227
uint8_t RC_getSignalQuality(void) {
226
uint8_t RC_getSignalQuality(void) {
228
  if (RCQuality >= 160)
227
  if (RCQuality >= 160)
229
    return SIGNAL_GOOD;
228
    return SIGNAL_GOOD;
230
  if (RCQuality >= 140)
229
  if (RCQuality >= 140)
231
    return SIGNAL_OK;
230
    return SIGNAL_OK;
232
  if (RCQuality >= 120)
231
  if (RCQuality >= 120)
233
    return SIGNAL_BAD;
232
    return SIGNAL_BAD;
234
  return SIGNAL_LOST;
233
  return SIGNAL_LOST;
235
}
234
}
236
 
235
 
237
/*
236
/*
238
 * To should fired only when the right stick is in the center position.
237
 * To should fired only when the right stick is in the center position.
239
 * This will cause the value of pitch and roll stick to be adjusted
238
 * This will cause the value of pitch and roll stick to be adjusted
240
 * to zero (not just to near zero, as per the assumption in rc.c
239
 * to zero (not just to near zero, as per the assumption in rc.c
241
 * about the rc signal. I had values about 50..70 with a Futaba
240
 * about the rc signal. I had values about 50..70 with a Futaba
242
 * R617 receiver.) This calibration is not strictly necessary, but
241
 * R617 receiver.) This calibration is not strictly necessary, but
243
 * for control logic that depends on the exact (non)center position
242
 * for control logic that depends on the exact (non)center position
244
 * of a stick, it may be useful.
243
 * of a stick, it may be useful.
245
 */
244
 */
246
void RC_calibrate(void) {
245
void RC_calibrate(void) {
247
  // Do nothing.
246
  // Do nothing.
248
}
247
}
249
 
248
 
250
/*
249
/*
251
 if (staticParams.GlobalConfig & CFG_HEADING_HOLD) {
250
 if (staticParams.GlobalConfig & CFG_HEADING_HOLD) {
252
 // In HH, it s OK to trim the R/C. The effect should not be conteracted here.
251
 // In HH, it s OK to trim the R/C. The effect should not be conteracted here.
253
 stickOffsetPitch = stickOffsetRoll = 0;
252
 stickOffsetPitch = stickOffsetRoll = 0;
254
 } else {
253
 } else {
255
 stickOffsetPitch = RCChannel(CH_PITCH) * staticParams.StickP;
254
 stickOffsetPitch = RCChannel(CH_PITCH) * staticParams.StickP;
256
 stickOffsetRoll = RCChannel(CH_ROLL)   * staticParams.StickP;
255
 stickOffsetRoll = RCChannel(CH_ROLL)   * staticParams.StickP;
257
 }
256
 }
258
 }
257
 }
259
 */
258
 */
260
 
259
 
261
uint8_t RC_getCommand(void) {
260
uint8_t RC_getCommand(void) {
262
  if (commandTimer == COMMAND_TIMER) {
261
  if (commandTimer == COMMAND_TIMER) {
263
    // Stick has been held long enough; command committed.
262
    // Stick has been held long enough; command committed.
264
    return lastRCCommand;
263
    return lastRCCommand;
265
  }
264
  }
266
  // Not yet sure what the command is.
265
  // Not yet sure what the command is.
267
  return COMMAND_NONE;
266
  return COMMAND_NONE;
268
}
267
}
269
 
268
 
270
/*
269
/*
271
 * Command arguments on R/C:
270
 * Command arguments on R/C:
272
 * 2--3--4
271
 * 2--3--4
273
 * |     |  +
272
 * |     |  +
274
 * 1  0  5  ^ 0
273
 * 1  0  5  ^ 0
275
 * |     |  |  
274
 * |     |  |  
276
 * 8--7--6
275
 * 8--7--6
277
 *    
276
 *    
278
 * + <--
277
 * + <--
279
 *    0
278
 *    0
280
 *
279
 *
281
 * Not in any of these positions: 0
280
 * Not in any of these positions: 0
282
 */
281
 */
283
 
282
 
284
#define ARGUMENT_THRESHOLD 70
283
#define ARGUMENT_THRESHOLD 70
285
#define ARGUMENT_CHANNEL_VERTICAL CH_PITCH
284
#define ARGUMENT_CHANNEL_VERTICAL CH_PITCH
286
#define ARGUMENT_CHANNEL_HORIZONTAL CH_ROLL
285
#define ARGUMENT_CHANNEL_HORIZONTAL CH_ROLL
287
 
286
 
288
uint8_t RC_getArgument(void) {
287
uint8_t RC_getArgument(void) {
289
  if (RCChannel(ARGUMENT_CHANNEL_VERTICAL) > ARGUMENT_THRESHOLD) {
288
  if (RCChannel(ARGUMENT_CHANNEL_VERTICAL) > ARGUMENT_THRESHOLD) {
290
    // vertical is up
289
    // vertical is up
291
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) > ARGUMENT_THRESHOLD)
290
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) > ARGUMENT_THRESHOLD)
292
      return 2;
291
      return 2;
293
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) < -ARGUMENT_THRESHOLD)
292
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) < -ARGUMENT_THRESHOLD)
294
      return 4;
293
      return 4;
295
    return 3;
294
    return 3;
296
  } else if (RCChannel(ARGUMENT_CHANNEL_VERTICAL) < -ARGUMENT_THRESHOLD) {
295
  } else if (RCChannel(ARGUMENT_CHANNEL_VERTICAL) < -ARGUMENT_THRESHOLD) {
297
    // vertical is down
296
    // vertical is down
298
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) > ARGUMENT_THRESHOLD)
297
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) > ARGUMENT_THRESHOLD)
299
      return 8;
298
      return 8;
300
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) < -ARGUMENT_THRESHOLD)
299
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) < -ARGUMENT_THRESHOLD)
301
      return 6;
300
      return 6;
302
    return 7;
301
    return 7;
303
  } else {
302
  } else {
304
    // vertical is around center
303
    // vertical is around center
305
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) > ARGUMENT_THRESHOLD)
304
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) > ARGUMENT_THRESHOLD)
306
      return 1;
305
      return 1;
307
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) < -ARGUMENT_THRESHOLD)
306
    if (RCChannel(ARGUMENT_CHANNEL_HORIZONTAL) < -ARGUMENT_THRESHOLD)
308
      return 5;
307
      return 5;
309
    return 0;
308
    return 0;
310
  }
309
  }
311
}
310
}
312
 
311
 
313
#ifdef USE_MK3MAG
312
#ifdef USE_MK3MAG
314
/*
313
/*
315
 * For each time the stick is pulled, returns true.
314
 * For each time the stick is pulled, returns true.
316
 */
315
 */
317
uint8_t RC_testCompassCalState(void) {
316
uint8_t RC_testCompassCalState(void) {
318
  static uint8_t stickPulled = 1;
317
  static uint8_t stickPulled = 1;
319
  // if pitch is centered or top set stick to zero
318
  // if pitch is centered or top set stick to zero
320
  if (RCChannel(CH_PITCH) > -20)
319
  if (RCChannel(CH_PITCH) > -20)
321
    stickPulled = 0;
320
    stickPulled = 0;
322
  // if pitch is down trigger to next cal state
321
  // if pitch is down trigger to next cal state
323
  if ((RCChannel(CH_PITCH) < -70) && !stickPulled) {
322
  if ((RCChannel(CH_PITCH) < -70) && !stickPulled) {
324
    stickPulled = 1;
323
    stickPulled = 1;
325
    return 1;
324
    return 1;
326
  }
325
  }
327
  return 0;
326
  return 0;
328
}
327
}
329
#endif
328
#endif
330
 
329
 
331
/*
330
/*
332
 * Abstract controls are not used at the moment.
331
 * Abstract controls are not used at the moment.
333
 t_control rc_control = {
332
 t_control rc_control = {
334
 RC_getPitch,
333
 RC_getPitch,
335
 RC_getRoll,
334
 RC_getRoll,
336
 RC_getYaw,
335
 RC_getYaw,
337
 RC_getThrottle,
336
 RC_getThrottle,
338
 RC_getSignalQuality,
337
 RC_getSignalQuality,
339
 RC_calibrate
338
 RC_calibrate
340
 };
339
 };
341
 */
340
 */
342
 
341