Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1396 - 1
/*------------------------------------------------------------------------------
2
** Ident                  : main.c                                            **
3
** Project                : MX16s 8->9 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_FINISH_PULSE,
42
   stPPM_FRAME_END
43
 };
44
 
45
unsigned char channel_number = 0;
46
unsigned char ppm_state      = stPPM_SYNC;
47
 
48
// timer1_capture_interrupt (void)
49
// Synchronise PPM frame and copy input events to PPM_OUT, start mixing Ch9 data when detect start pulse of Ch9
50
ISR (TIM1_CAPT_vect)
51
 {
52
   cli ();                                                                      // disable interrupts
53
   unsigned int data;
54
 
55
   switch (ppm_state)
56
    {
57
      case stPPM_SYNC:                                                          // detect rising edge pulse
58
        data = ICR1;                                                            // get timer value after input capture
59
        SET_COUNTER_TO_ZERO;
60
        FALLING_EDGE_TRIGGER;
61
        if(data >= MIN_SYNC_TIME && data <= MAX_SYNC_TIME)                      // valid sync trigger
62
         {
63
           SET_PPM_OUT_HIGH;
64
           ppm_state = stPPM_CHANNEL_DATA;                                      // next state: get data
65
           channel_number = 0;
66
         }
67
        else                                                                    // trigger but not a valid sync time
68
         {
69
           SET_PPM_OUT_LOW;
70
           ppm_state = stPPM_SYNC_WAIT;                                         // next state: wait for next sync event
71
         }
72
        break;
73
 
74
      case stPPM_SYNC_WAIT:                                                     // detect falling edge pulse
75
        SET_PPM_OUT_LOW;                                                        // not nessecery, output should already be low
76
        SET_COUNTER_TO_ZERO;
77
        SET_CAPTURE_COUNTER_TO_ZERO;
78
        RISING_EDGE_TRIGGER;
79
        ppm_state = stPPM_SYNC;                                                 // next state: try again for new sync
80
        break;
81
 
82
      case stPPM_CHANNEL_START:                                                 // detect rising edge pulse
83
        SET_COUNTER_TO_ZERO;
84
        SET_PPM_OUT_HIGH;
85
        FALLING_EDGE_TRIGGER;
86
        channel_number++;                                                       // prepare for next MX16s channel clock
87
        if(channel_number>7)                                                    // all eight channels read
88
         {
89
           SET_COUNTER_TO_ZERO;
90
           SET_PPM_OUT_HIGH;
91
           SET_TIMER_TO_COMPA_CTC;
92
           DISABLE_INPUT_CAPTURE;
93
           ENABLE_OUTPUT_COMPARE;
94
           OCR1A = START_PULSE;                                                 // startpulse length 0.4ms
95
           TRIGGER_INPUT_COMPARE_INTERRUPT;
96
           ppm_state = stPPM_CHANNEL_9_DATA;                                    // 9th. channel but now self created
97
           channel_number = 0;
98
         }
99
        else
100
          ppm_state = stPPM_CHANNEL_DATA;
101
        break;
102
 
103
      case stPPM_CHANNEL_DATA:                                                  // detect falling edge pulse
104
        SET_COUNTER_TO_ZERO;
105
        SET_PPM_OUT_LOW;
106
        RISING_EDGE_TRIGGER;
107
        ppm_state = stPPM_CHANNEL_START;                                        // wait for next channel rising edge pulse
108
        break;
109
 
110
      default:
111
        SET_PPM_OUT_LOW;                                                        // not nessecery, output should already be low
112
        SET_COUNTER_TO_ZERO;
113
        SET_CAPTURE_COUNTER_TO_ZERO;
114
        RISING_EDGE_TRIGGER;
115
        ppm_state = stPPM_SYNC;                                                 // next state: try again for new sync
116
        break;
117
    }
118
   sei ();
119
 }
120
 
121
// timer1_compare_interrupt (void)
122
// Mixing channel 9 data into ppm out, start input capture for frame synchronisation
123
ISR (TIM1_COMPA_vect)
124
 {
125
   cli ();
126
   switch (ppm_state)
127
    {
128
      case stPPM_CHANNEL_9_DATA:
129
        SET_PPM_OUT_LOW;
130
        SET_COUNTER_TO_ZERO;
131
        if (PINA & (1 << CHANNEL_9))                                            // Channel 9 on/off
132
          OCR1A = PPM_PULSE_MAX - START_PULSE;
133
        else
134
          OCR1A = PPM_PULSE_MIN - START_PULSE;
135
        // set OCR1A between [PPM_PULSE_MIN-START_PULSE] and [PPM_PULSE_MAX-START_PULSE] for transmitting analog value
136
        ppm_state = stPPM_FINISH_PULSE;                                         // next State
137
        break;
138
 
139
      case stPPM_FINISH_PULSE:                                                  // create last pulse
140
        SET_PPM_OUT_HIGH;
141
        SET_COUNTER_TO_ZERO;
142
        OCR1A = START_PULSE;                                                    // startpulse length 0.4ms
143
        ppm_state = stPPM_FRAME_END;                                            // next State
144
        break;
145
 
146
      case stPPM_FRAME_END:
147
      default:
148
        SET_PPM_OUT_LOW;
149
        RISING_EDGE_TRIGGER;
150
        DISABLE_OUTPUT_COMPARE;
151
        ENABLE_INPUT_CAPTURE;
152
        SET_TIMER_TO_COMPA_CTC;
153
        SET_COUNTER_TO_ZERO;
154
        SET_COMPARE_COUNTER_TO_ZERO;
155
        SET_CAPTURE_COUNTER_TO_ZERO;
156
        ppm_state = stPPM_SYNC;                                                 // next State
157
        TRIGGER_INPUT_CAPTURE_INTERRUPT;
158
        break;
159
    }
160
   sei ();
161
}
162
 
163
int main (void)
164
 {
165
   cli ();                                                                      // disable interrupts
166
 
167
   DDRA &= ~(1<<PPM_IN);                                                        // set Input Capture Pin as input
168
   PORTA |= (1<<PPM_IN);                                                        // enable pullup
169
 
170
   DDRB  |=  (1<<PPM_OUT_PIN);                                                  // configure PPM_OUT pin as output
171
   SET_PPM_OUT_LOW;                                                             // set low
172
 
173
   DDRA  &= ~(1 << CHANNEL_9);                                                  // Channel 9 (Pin 10) input
174
   PORTA |=  (1 << CHANNEL_9);                                                  // enable pullup
175
 
176
   TCCR1A = ((0<<WGM11)|(0<<WGM10));                                            // CTC mode
177
   TCCR1B = ((0<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10));              // CTC mode for COMPA, prescaler 8 / 8MHz => [1.0us]
178
 
179
   CLEAR_INPUT_CAPTURE_INTERRUPT_FLAG;                                          // reset ICF flag
180
   SET_COUNTER_TO_ZERO;
181
   SET_COMPARE_COUNTER_TO_ZERO;
182
   ENABLE_INPUT_CAPTURE;
183
   DISABLE_OUTPUT_COMPARE;
184
   RISING_EDGE_TRIGGER;
185
 
186
   sei ();                                                                      // enable interrupts
187
 
188
   while(1);
189
 }