0,0 → 1,212 |
/*------------------------------------------------------------------------------ |
** Ident : main.c ** |
** Project : MX16s 8->10 ppm channel expander ** |
** Author : lakeroe ** |
** Description : main module ** |
** Copyright (c) : 12.2011 lakeroe ** |
** Original code and idea : Jacques Wanders ** |
** http://forum.mikrokopter.de/topic-4405.html ** |
** http://forum.mikrokopter.de/topic-4556.html ** |
**----------------------------------------------------------------------------** |
** Release : v1.0 initial release ** |
** Date : 25-12-2011 ** |
**----------------------------------------------------------------------------** |
** The use of this project (hardware, software, binary files, sources and ** |
** documentation) is only permittet for non-commercial use ** |
** (directly or indirectly) ** |
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"** |
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** |
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** |
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ** |
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ** |
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ** |
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ** |
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ** |
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ** |
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ** |
** POSSIBILITY OF SUCH DAMAGE. ** |
------------------------------------------------------------------------------*/ |
|
#include <avr/io.h> |
#include <avr/interrupt.h> |
#include "main.h" |
|
enum |
{ |
stPPM_SYNC, |
stPPM_SYNC_WAIT, |
stPPM_CHANNEL_START, |
stPPM_CHANNEL_DATA, |
stPPM_CHANNEL_9_DATA, |
stPPM_CHANNEL_10_START, |
stPPM_CHANNEL_10_DATA, |
stPPM_FINISH_PULSE, |
stPPM_FRAME_END |
}; |
|
unsigned char channel_number = 0; |
unsigned char ppm_state = stPPM_SYNC; |
|
// timer1_capture_interrupt (void) |
// Synchronise PPM frame and copy input events to PPM_OUT, start mixing Ch9,10 data when detect start pulse of Ch9 |
ISR (TIM1_CAPT_vect) |
{ |
cli (); // disable interrupts |
unsigned int data; |
|
switch (ppm_state) |
{ |
case stPPM_SYNC: // detect rising edge pulse |
data = ICR1; // get timer value after input capture |
SET_COUNTER_TO_ZERO; |
FALLING_EDGE_TRIGGER; |
if(data >= MIN_SYNC_TIME && data <= MAX_SYNC_TIME) // valid sync trigger |
{ |
SET_PPM_OUT_HIGH; |
ppm_state = stPPM_CHANNEL_DATA; // next state: get data |
channel_number = 0; |
} |
else // trigger but not a valid sync time |
{ |
SET_PPM_OUT_LOW; |
ppm_state = stPPM_SYNC_WAIT; // next state: wait for next sync event |
} |
break; |
|
case stPPM_SYNC_WAIT: // detect falling edge pulse |
SET_PPM_OUT_LOW; // not nessecery, output should already be low |
SET_COUNTER_TO_ZERO; |
SET_CAPTURE_COUNTER_TO_ZERO; |
RISING_EDGE_TRIGGER; |
ppm_state = stPPM_SYNC; // next state: try again for new sync |
break; |
|
case stPPM_CHANNEL_START: // detect rising edge pulse |
SET_COUNTER_TO_ZERO; |
SET_PPM_OUT_HIGH; |
FALLING_EDGE_TRIGGER; |
channel_number++; // prepare for next MX16s channel clock |
if(channel_number>7) // all eight channels read |
{ |
SET_COUNTER_TO_ZERO; |
SET_PPM_OUT_HIGH; |
SET_TIMER_TO_COMPA_CTC; |
DISABLE_INPUT_CAPTURE; |
ENABLE_OUTPUT_COMPARE; |
OCR1A = START_PULSE; // startpulse length 0.4ms |
TRIGGER_INPUT_COMPARE_INTERRUPT; |
ppm_state = stPPM_CHANNEL_9_DATA; // 9th. channel but now self created |
channel_number = 0; |
} |
else |
ppm_state = stPPM_CHANNEL_DATA; |
break; |
|
case stPPM_CHANNEL_DATA: // detect falling edge pulse |
SET_COUNTER_TO_ZERO; |
SET_PPM_OUT_LOW; |
RISING_EDGE_TRIGGER; |
ppm_state = stPPM_CHANNEL_START; // wait for next channel rising edge pulse |
break; |
|
default: |
SET_PPM_OUT_LOW; // not nessecery, output should already be low |
SET_COUNTER_TO_ZERO; |
SET_CAPTURE_COUNTER_TO_ZERO; |
RISING_EDGE_TRIGGER; |
ppm_state = stPPM_SYNC; // next state: try again for new sync |
break; |
} |
sei (); |
} |
|
// timer1_compare_interrupt (void) |
// Mixing channel 9,10 data into ppm out, start input capture for frame synchronisation |
ISR (TIM1_COMPA_vect) |
{ |
cli (); |
switch (ppm_state) |
{ |
case stPPM_CHANNEL_9_DATA: |
SET_PPM_OUT_LOW; |
SET_COUNTER_TO_ZERO; |
if (PINA & (1 << CHANNEL_9)) // Channel 9 on/off |
OCR1A = PPM_PULSE_MAX - START_PULSE; |
else |
OCR1A = PPM_PULSE_MIN - START_PULSE; |
// set OCR1A between [PPM_PULSE_MIN-START_PULSE] and [PPM_PULSE_MAX-START_PULSE] for transmitting analog value |
ppm_state = stPPM_CHANNEL_10_START; // next State |
break; |
|
case stPPM_CHANNEL_10_START: |
SET_PPM_OUT_HIGH; |
SET_COUNTER_TO_ZERO; |
OCR1A = START_PULSE; // startpulse length 0.4ms |
ppm_state = stPPM_CHANNEL_10_DATA; // next State |
break; |
|
case stPPM_CHANNEL_10_DATA: |
SET_PPM_OUT_LOW; |
SET_COUNTER_TO_ZERO; |
if (PINA & (1 << CHANNEL_10)) // Channel 10 on/off |
OCR1A = PPM_PULSE_MAX - START_PULSE; |
else |
OCR1A = PPM_PULSE_MIN - START_PULSE; |
// set OCR1A between [PPM_PULSE_MIN-START_PULSE] and [PPM_PULSE_MAX-START_PULSE] for transmitting analog value |
ppm_state = stPPM_FINISH_PULSE; // next State |
break; |
|
case stPPM_FINISH_PULSE: // create last pulse |
SET_PPM_OUT_HIGH; |
SET_COUNTER_TO_ZERO; |
OCR1A = START_PULSE; // startpulse length 0.4ms |
ppm_state = stPPM_FRAME_END; // next State |
break; |
|
case stPPM_FRAME_END: |
default: |
SET_PPM_OUT_LOW; |
RISING_EDGE_TRIGGER; |
DISABLE_OUTPUT_COMPARE; |
ENABLE_INPUT_CAPTURE; |
SET_TIMER_TO_COMPA_CTC; |
SET_COUNTER_TO_ZERO; |
SET_COMPARE_COUNTER_TO_ZERO; |
SET_CAPTURE_COUNTER_TO_ZERO; |
ppm_state = stPPM_SYNC; // next State |
TRIGGER_INPUT_CAPTURE_INTERRUPT; |
break; |
} |
sei (); |
} |
|
int main (void) |
{ |
cli (); // disable interrupts |
|
DDRA &= ~(1<<PPM_IN); // set Input Capture Pin as input |
PORTA |= (1<<PPM_IN); // enable pullup |
|
DDRB |= (1<<PPM_OUT_PIN); // configure PPM_OUT pin as output |
SET_PPM_OUT_LOW; // set low |
|
DDRA &= ~(1 << CHANNEL_9); // Channel 9 (Pin 10) input |
PORTA |= (1 << CHANNEL_9); // enable pullup |
|
DDRA &= ~(1 << CHANNEL_10); // Channel 10 (Pin 9) input |
PORTA |= (1 << CHANNEL_10); // enable pullup |
|
TCCR1A = ((0<<WGM11)|(0<<WGM10)); // CTC mode |
TCCR1B = ((0<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10)); // CTC mode for COMPA, prescaler 8 / 8MHz => [1.0us] |
|
CLEAR_INPUT_CAPTURE_INTERRUPT_FLAG; // reset ICF flag |
SET_COUNTER_TO_ZERO; |
SET_COMPARE_COUNTER_TO_ZERO; |
ENABLE_INPUT_CAPTURE; |
DISABLE_OUTPUT_COMPARE; |
RISING_EDGE_TRIGGER; |
|
sei (); // enable interrupts |
|
while(1); |
} |