Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1398 - 1
/*------------------------------------------------------------------------------
2
** Ident                  : main.c                                            **
3
** Project                : MX16s 8->10 ppm channel expander                  **
4
** Author                 : lakeroe                                           **
5
** Description            : main module                                       **
6
** Copyright (c)          : 12.2011 lakeroe                                   **
7
** Original code and idea : Jacques Wanders                                   **
8
**                          http://forum.mikrokopter.de/topic-4405.html       **
9
**                          http://forum.mikrokopter.de/topic-4556.html       **
10
**----------------------------------------------------------------------------**
11
** Release                : v1.0 initial release                              **
12
** Date                   : 25-12-2011                                        **
13
**----------------------------------------------------------------------------**
14
** The use of this project (hardware, software, binary files, sources and     **
15
** documentation) is only permittet for non-commercial use                    **
16
** (directly or indirectly)                                                   **
17
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"**
18
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  **
19
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE **
20
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE   **
21
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR        **
22
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF       **
23
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS   **
24
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN    **
25
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)    **
26
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE **
27
** POSSIBILITY OF SUCH DAMAGE.                                                **
28
------------------------------------------------------------------------------*/
29
 
30
#include <avr/io.h>
31
#include <avr/interrupt.h>
32
#include "main.h"
33
 
34
enum
35
 {
36
   stPPM_SYNC,
37
   stPPM_SYNC_WAIT,
38
   stPPM_CHANNEL_START,
39
   stPPM_CHANNEL_DATA,
40
   stPPM_CHANNEL_9_DATA,
41
   stPPM_CHANNEL_10_START,
42
   stPPM_CHANNEL_10_DATA,
43
   stPPM_FINISH_PULSE,
44
   stPPM_FRAME_END
45
 };
46
 
47
unsigned char channel_number = 0;
48
unsigned char ppm_state      = stPPM_SYNC;
49
 
50
// timer1_capture_interrupt (void)
51
// Synchronise PPM frame and copy input events to PPM_OUT, start mixing Ch9,10 data when detect start pulse of Ch9
52
ISR (TIM1_CAPT_vect)
53
 {
54
   cli ();                                                                      // disable interrupts
55
   unsigned int data;
56
 
57
   switch (ppm_state)
58
    {
59
      case stPPM_SYNC:                                                          // detect rising edge pulse
60
        data = ICR1;                                                            // get timer value after input capture
61
        SET_COUNTER_TO_ZERO;
62
        FALLING_EDGE_TRIGGER;
63
        if(data >= MIN_SYNC_TIME && data <= MAX_SYNC_TIME)                      // valid sync trigger
64
         {
65
           SET_PPM_OUT_HIGH;
66
           ppm_state = stPPM_CHANNEL_DATA;                                      // next state: get data
67
           channel_number = 0;
68
         }
69
        else                                                                    // trigger but not a valid sync time
70
         {
71
           SET_PPM_OUT_LOW;
72
           ppm_state = stPPM_SYNC_WAIT;                                         // next state: wait for next sync event
73
         }
74
        break;
75
 
76
      case stPPM_SYNC_WAIT:                                                     // detect falling edge pulse
77
        SET_PPM_OUT_LOW;                                                        // not nessecery, output should already be low
78
        SET_COUNTER_TO_ZERO;
79
        SET_CAPTURE_COUNTER_TO_ZERO;
80
        RISING_EDGE_TRIGGER;
81
        ppm_state = stPPM_SYNC;                                                 // next state: try again for new sync
82
        break;
83
 
84
      case stPPM_CHANNEL_START:                                                 // detect rising edge pulse
85
        SET_COUNTER_TO_ZERO;
86
        SET_PPM_OUT_HIGH;
87
        FALLING_EDGE_TRIGGER;
88
        channel_number++;                                                       // prepare for next MX16s channel clock
89
        if(channel_number>7)                                                    // all eight channels read
90
         {
91
           SET_COUNTER_TO_ZERO;
92
           SET_PPM_OUT_HIGH;
93
           SET_TIMER_TO_COMPA_CTC;
94
           DISABLE_INPUT_CAPTURE;
95
           ENABLE_OUTPUT_COMPARE;
96
           OCR1A = START_PULSE;                                                 // startpulse length 0.4ms
97
           TRIGGER_INPUT_COMPARE_INTERRUPT;
98
           ppm_state = stPPM_CHANNEL_9_DATA;                                    // 9th. channel but now self created
99
           channel_number = 0;
100
         }
101
        else
102
          ppm_state = stPPM_CHANNEL_DATA;
103
        break;
104
 
105
      case stPPM_CHANNEL_DATA:                                                  // detect falling edge pulse
106
        SET_COUNTER_TO_ZERO;
107
        SET_PPM_OUT_LOW;
108
        RISING_EDGE_TRIGGER;
109
        ppm_state = stPPM_CHANNEL_START;                                        // wait for next channel rising edge pulse
110
        break;
111
 
112
      default:
113
        SET_PPM_OUT_LOW;                                                        // not nessecery, output should already be low
114
        SET_COUNTER_TO_ZERO;
115
        SET_CAPTURE_COUNTER_TO_ZERO;
116
        RISING_EDGE_TRIGGER;
117
        ppm_state = stPPM_SYNC;                                                 // next state: try again for new sync
118
        break;
119
    }
120
   sei ();
121
 }
122
 
123
// timer1_compare_interrupt (void)
124
// Mixing channel 9,10 data into ppm out, start input capture for frame synchronisation
125
ISR (TIM1_COMPA_vect)
126
 {
127
   cli ();
128
   switch (ppm_state)
129
    {
130
      case stPPM_CHANNEL_9_DATA:
131
        SET_PPM_OUT_LOW;
132
        SET_COUNTER_TO_ZERO;
133
        if (PINA & (1 << CHANNEL_9))                                            // Channel 9 on/off
134
          OCR1A = PPM_PULSE_MAX - START_PULSE;
135
        else
136
          OCR1A = PPM_PULSE_MIN - START_PULSE;
137
        // set OCR1A between [PPM_PULSE_MIN-START_PULSE] and [PPM_PULSE_MAX-START_PULSE] for transmitting analog value
138
        ppm_state = stPPM_CHANNEL_10_START;                                     // next State
139
        break;
140
 
141
      case stPPM_CHANNEL_10_START:
142
        SET_PPM_OUT_HIGH;
143
        SET_COUNTER_TO_ZERO;
144
        OCR1A = START_PULSE;                                                    // startpulse length 0.4ms
145
        ppm_state = stPPM_CHANNEL_10_DATA;                                      // next State
146
        break;
147
 
148
      case stPPM_CHANNEL_10_DATA:
149
        SET_PPM_OUT_LOW;
150
        SET_COUNTER_TO_ZERO;
151
        if (PINA & (1 << CHANNEL_10))                                           // Channel 10 on/off
152
          OCR1A = PPM_PULSE_MAX - START_PULSE;
153
        else
154
          OCR1A = PPM_PULSE_MIN - START_PULSE;
155
        // set OCR1A between [PPM_PULSE_MIN-START_PULSE] and [PPM_PULSE_MAX-START_PULSE] for transmitting analog value
156
        ppm_state = stPPM_FINISH_PULSE;                                         // next State
157
        break;
158
 
159
      case stPPM_FINISH_PULSE:                                                  // create last pulse
160
        SET_PPM_OUT_HIGH;
161
        SET_COUNTER_TO_ZERO;
162
        OCR1A = START_PULSE;                                                    // startpulse length 0.4ms
163
        ppm_state = stPPM_FRAME_END;                                            // next State
164
        break;
165
 
166
      case stPPM_FRAME_END:
167
      default:
168
        SET_PPM_OUT_LOW;
169
        RISING_EDGE_TRIGGER;
170
        DISABLE_OUTPUT_COMPARE;
171
        ENABLE_INPUT_CAPTURE;
172
        SET_TIMER_TO_COMPA_CTC;
173
        SET_COUNTER_TO_ZERO;
174
        SET_COMPARE_COUNTER_TO_ZERO;
175
        SET_CAPTURE_COUNTER_TO_ZERO;
176
        ppm_state = stPPM_SYNC;                                                 // next State
177
        TRIGGER_INPUT_CAPTURE_INTERRUPT;
178
        break;
179
    }
180
   sei ();
181
}
182
 
183
int main (void)
184
 {
185
   cli ();                                                                      // disable interrupts
186
 
187
   DDRA &= ~(1<<PPM_IN);                                                        // set Input Capture Pin as input
188
   PORTA |= (1<<PPM_IN);                                                        // enable pullup
189
 
190
   DDRB  |=  (1<<PPM_OUT_PIN);                                                  // configure PPM_OUT pin as output
191
   SET_PPM_OUT_LOW;                                                             // set low
192
 
193
   DDRA  &= ~(1 << CHANNEL_9);                                                  // Channel 9 (Pin 10) input
194
   PORTA |=  (1 << CHANNEL_9);                                                  // enable pullup
195
 
196
   DDRA  &= ~(1 << CHANNEL_10);                                                 // Channel 10 (Pin 9) input
197
   PORTA |=  (1 << CHANNEL_10);                                                 // enable pullup
198
 
199
   TCCR1A = ((0<<WGM11)|(0<<WGM10));                                            // CTC mode
200
   TCCR1B = ((0<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10));              // CTC mode for COMPA, prescaler 8 / 8MHz => [1.0us]
201
 
202
   CLEAR_INPUT_CAPTURE_INTERRUPT_FLAG;                                          // reset ICF flag
203
   SET_COUNTER_TO_ZERO;
204
   SET_COMPARE_COUNTER_TO_ZERO;
205
   ENABLE_INPUT_CAPTURE;
206
   DISABLE_OUTPUT_COMPARE;
207
   RISING_EDGE_TRIGGER;
208
 
209
   sei ();                                                                      // enable interrupts
210
 
211
   while(1);
212
 }