Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 103 → Rev 104

/RC-Expander/trunk/main.h
New file
0,0 → 1,101
/*------------------------------------------------------------------------------
** **
** Ident : main.h **
** Project : MX12 3 ppm channel expander **
** Author : J.Wanders **
** modified : 05.2008 Heinrich Fischer for use with WinAVR **
** **
** 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 <inttypes.h>
 
/* CONSTANTS */
#define TRUE 0xFF
#define FALSE 0x00
 
#define CHANNEL_7_ADC PORTA1 // (pin12)
#define CHANNEL_8_ADC PORTA2 // (pin11)
#define CHANNEL_9_ADC PORTA3 // (pin11)
#define PPM_IN PORTA7 // (pin6)
#define PPM_OUT_PIN PORTB2 // (pin5)
 
#define ADC_CHANNEL_7 0x01 // ADC1 - PORTA1 (pin12)
#define ADC_CHANNEL_8 0x02 // ADC2 - PORTA2 (pin11)
#define ADC_CHANNEL_9 0x03 // ADC3 - PORTA3 (pin10)
#define ADC_CHANNEL_MASK 0x03
 
 
#define START_PULSE_HIGH 400 // [0.4ms]
#define START_PULSE_LOW 600 // [0.6ms]
//#define FORCE_LOW_END_FRAME 2100 // [2.1ms]
//#define MIN_SYNC_TIME 2400 // [2.4ms]
//NEW definition in main.h
#define FORCE_LOW_END_FRAME 500 // [0,5ms]
#define MIN_SYNC_TIME 3000 // [3.0ms]
#define MAX_SYNC_TIME 22000 // total frame time - 8 x min channel frame time = 22ms - 8 x 1ms = 22 - 8
 
 
// minimum channel frame = START_PULSE_HIGH + START_PULSE_LOW = 400 + 600 counts = 1000 counts = 1ms
// PPM frame length = 22ms = 22000 counts
 
/**** MACROS ******************************************************************/
 
#define SET_PPM_OUT_HIGH PORTB |= (1<<PPM_OUT_PIN)
#define SET_PPM_OUT_LOW PORTB &= ~(1<<PPM_OUT_PIN)
 
#define FALLING_EDGE_TRIGGER TCCR1B &= ~(1<<ICES1)
#define RISING_EDGE_TRIGGER TCCR1B |= (1<<ICES1)
 
#define SET_COMPARE_COUNTER_TO_ZERO OCR1A = 0
#define SET_COUNTER_TO_ZERO TCNT1 = 0
#define SET_CAPTURE_COUNTER_TO_ZERO ICR1 = 0
 
#define DISABLE_INPUT_CAPTURE TIMSK1 &= ~(1<<ICIE1) // disable input capture
#define ENABLE_INPUT_CAPTURE TIMSK1 |= (1 << ICIE1) // enable input capture
 
#define DISABLE_OUTPUT_COMPARE TIMSK1 &= ~(1<<OCIE1A) // disable Output Compare A Match Interrupt
#define ENABLE_OUTPUT_COMPARE TIMSK1 |= (1<<OCIE1A) // enable Output Compare A Match Interrupt
 
#define TRIGGER_INPUT_CAPTURE_INTERRUPT TIFR1 |= (1<<ICF1) //
#define CLEAR_INPUT_CAPTURE_INTERRUPT_FLAG TIFR1 &= ~(1<<ICF1) // reset ICF flag
 
#define TRIGGER_INPUT_COMPARE_INTERRUPT TIFR1 |= (1<<OCF1A)
 
#define SET_TIMER_TO_ICP_CTC TCCR1B |= (1<<WGM13) // CTC mode for ICP, prescaler 8 / 8MHz => [1.0us]
#define SET_TIMER_TO_COMPA_CTC TCCR1B &= ~(1<<WGM13) // CTC mode for COMPA, prescaler 8 / 8MHz => [1.0us]
 
// clear ADC enable & ADC Start Conversion & ADC Interrupt Enable bit
#define ADC_DISABLE ADCSRA &= ~((1<<ADEN)|(1<<ADSC)|(1<<ADIE))
// set ADC enable & ADC Start Conversion & ADC Interrupt Enable bit
#define ADC_ENABLE ADCSRA |= (1<<ADEN)|(1<<ADSC)|(1<<ADIE)
 
 
/**** END MACROS *****************************************************************************/
 
 
 
 
 
//#define cli() __disable_interrupt()
//#define sei() __enable_interrupt()
 
 
 
 
 
/RC-Expander/trunk/MX12-Erweiterung.pnproj
New file
0,0 → 1,0
<Project name="MX12-Erweiterung"><File path="main.c"></File><File path="main.h"></File><File path="makefile"></File></Project>
/RC-Expander/trunk/makefile
New file
0,0 → 1,379
#--------------------------------------------------------------------
# MCU name
MCU = attiny24
F_CPU = 8000000
#-------------------------------------------------------------------
VERSION_MAJOR = 1
VERSION_MINOR = 2
VERSION_INDEX = 0
#-------------------------------------------------------------------
#OPTIONS
#-
#-------------------------------------------------------------------
 
ifeq ($(F_CPU), 8000000)
QUARZ = 8MHZ
endif
 
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
 
# Target file name (without extension).
 
ifeq ($(VERSION_INDEX), 0)
TARGET = MX12_extender_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)
endif
 
 
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
 
##########################################################################################################
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c
#SRC += < add more soure files>
 
##########################################################################################################
 
 
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
 
 
 
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS =
 
 
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create assembler listing
CFLAGS = -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-Wa,-adhlns=$(<:.c=.lst) \
$(patsubst %,-I%,$(EXTRAINCDIRS))
 
 
# Set a "language standard" compiler flag.
# Unremark just one line below to set the language standard to use.
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
#CFLAGS += -std=c89
#CFLAGS += -std=gnu89
#CFLAGS += -std=c99
CFLAGS += -std=gnu99
 
CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_INDEX=$(VERSION_INDEX)
 
 
# Optional assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
 
 
 
# Optional linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
 
# Additional libraries
 
# Minimalistic printf version
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
 
# Floating point printf version (requires -lm below)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
 
# -lm = math library
LDFLAGS += -lm
 
 
##LDFLAGS += -T./linkerfile/avr5.x
 
 
 
# Programming support using avrdude. Settings and variables.
 
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
#AVRDUDE_PROGRAMMER = dt006
#AVRDUDE_PROGRAMMER = stk200
#AVRDUDE_PROGRAMMER = ponyser
AVRDUDE_PROGRAMMER = avrispv2
#falls Ponyser ausgewählt wird, muss sich unsere avrdude-Configdatei im Bin-Verzeichnis des Compilers befinden
 
#AVRDUDE_PORT = com1 # programmer connected to serial device
#AVRDUDE_PORT = lpt1 # programmer connected to parallel port
AVRDUDE_PORT = usb # programmer connected to USB
 
#AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex $(FUSE_SETTINGS)
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
 
#avrdude -c avrispv2 -P usb -p m32 -U flash:w:blink.hex
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
 
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE += -y
 
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
AVRDUDE_FLAGS += -V
 
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_FLAGS += -v -v
 
# ---------------------------------------------------------------------------
# Define directories, if needed.
DIRAVR = c:/userprog/WinAVR-20070525
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
 
 
# Define programs and commands.
SHELL = sh
 
CC = avr-gcc
 
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
 
# Programming support using avrdude.
AVRDUDE = avrdude
 
REMOVE = rm -f
COPY = cp
 
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
 
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
 
 
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
 
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 
# Combine all necessary flags and optional flags.
# Add target processor to flags.
#ALL_CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -I. $(CFLAGS)
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
# Default target.
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
$(TARGET).lss $(TARGET).sym sizeafter finished end
 
 
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
 
finished:
@echo $(MSG_ERRORS_NONE)
 
end:
@echo $(MSG_END)
@echo
 
 
# Display size of file.
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
 
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
 
 
 
# Display compiler version information.
gccversion :
@$(CC) --version
 
 
# Convert ELF to COFF for use in debugging / simulating in
# AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
 
 
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
 
 
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
 
 
 
 
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
 
 
 
 
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
 
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
 
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
 
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
avr-nm -n $< > $@
 
 
 
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
 
 
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
 
 
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
 
 
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 
 
 
 
 
# Target: clean project.
clean: begin clean_list finished end
 
clean_list :
@echo
@echo $(MSG_CLEANING)
# $(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
 
 
# Automatically generate C source code dependencies.
# (Code originally taken from the GNU make user manual and modified
# (See README.txt Credits).)
#
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
# (see the SHELL variable defined above).
# This may not work with other shells or other seds.
#
%.d: %.c
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
[ -s $@ ] || rm -f $@
 
 
# Remove the '-' if you want to see the dependency files generated.
-include $(SRC:.c=.d)
 
 
 
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program
 
/RC-Expander/trunk/MX12_extender__V1_2.hex
New file
0,0 → 1,55
:1000000010C029C028C027C026C04EC0BAC023C017
:1000100022C021C020C01FC01EC036C11CC01BC0D2
:100020001AC011241FBECFEDCDBF10E0A0E6B0E096
:10003000E2E4F3E003C0C89531960D92A636B1070D
:10004000D1F710E0A6E6B0E001C01D92A936B107D5
:10005000E1F771D175C1D4CFD798DF9ABA9AC29817
:10006000D198D998D298DA98D398DB980895F894D3
:1000700081B1866081B917B881E086B913B886B1BD
:10008000886C86B978940895F8941FBC8AE08EBD78
:100090005D981DBC1CBC1BBC1ABC659A61988EB5D2
:1000A00080648EBD789408951F920F920FB60F92C0
:1000B00011242F933F938F939F93F894809167001F
:1000C0008230E9F0833018F4882339F046C0833059
:1000D00059F1843009F041C02FC024B535B51DBC9D
:1000E0001CBC8EB58F7B8EBD285B3B4029533A44A8
:1000F00018F4C29A83E011C0C29881E02BC01DBCE5
:100100001CBCC29A8EB58F7B8EBD809166008F5FBE
:1001100080936600863030F084E080936700109210
:10012000660025C083E016C01DBC1CBCC2988EB5FD
:1001300080648EBD82E00EC01DBC1CBCC2988EB512
:100140008F7E8EBD6598619A88E592E09BBD8ABDE1
:10015000599A85E0809367000AC0C2981DBC1CBCF8
:1001600015BC14BC8EB580648EBD10926700789467
:100170009F918F913F912F910F900FBE0F901F90E5
:1001800018951F920F920FB60F9211248F939F9381
:10019000F894809167008830B1F1893040F486305E
:1001A000D1F0873018F5853009F055C009C08A3084
:1001B00009F43FC08A3080F18B3009F04CC042C056
:1001C000C2981DBC1CBC80916000909161009BBDD9
:1001D0008ABD86E008C0C29A1DBC1CBC80E991E0C3
:1001E0009BBD8ABD87E08093670046C0C2981DBC56
:1001F0001CBC8091620090916300885A9D4F9BBD0A
:100200008ABD88E0F0CFC29A1DBC1CBC80E991E099
:100210009BBD8ABD89E0E7CFC2981DBC1CBC809104
:10022000640090916500885A9D4F9BBD8ABD8AE00D
:10023000DACFC29A1DBC1CBC80E991E09BBD8ABD8F
:100240008BE0D1CFC2981DBC1CBC84EF91E09BBD5C
:100250008ABD8CE0C8CF8EB580648EBD6198659AEA
:100260008EB58F7E8EBD1DBC1CBC1BBC1ABC15BCC4
:1002700014BC109267005D9A78949F918F910F90B3
:100280000FBE0F901F9018951F920F920FB60F92EE
:1002900011242F933F938F939F9386B1877386B9D1
:1002A00024B135B183E0293E380710F028EE33E061
:1002B00087B18C7F87B980916800813031F43093A9
:1002C00061002093600082E00DC0823031F43093F1
:1002D00063002093620083E005C0309365002093A3
:1002E000640081E08093680087B190916800892B59
:1002F00087B986B1886C86B99F918F913F912F9174
:100300000F900FBE0F901F901895809160009091F4
:1003100061008F5F9F4FC9F38091620090916300ED
:100320008F5F9F4F91F380916400909165008F5F84
:100330009F4F59F3089590DE9ADEE7DFA5DEFFCFE9
:02034000FFCFED
:06034200FFFFFFFFFFFFBB
:00000001FF
/RC-Expander/trunk/MX12-Erweiterung.pnps
New file
0,0 → 1,0
<pd><ViewState><e p="MX12-Erweiterung" x="true"></e></ViewState></pd>
/RC-Expander/trunk/main.c
New file
0,0 → 1,403
/*------------------------------------------------------------------------------
** **
** Ident : main.c **
** Project : MX12 2 (3) ppm channel expander **
** Author : Jacques Wanders **
** Description : main module **
** Copyright (c): 05.2008 Jacques Wanders **
** modified : 05.2008 Heinrich Fischer for use with WinAVR **
** **
**----------------------------------------------------------------------------**
** Release : v1.0 initial release **
** Date : 13-05-2008 **
**----------------------------------------------------------------------------**
** Release : v1.1 **
** Date : 13-05-2008 **
** Notes : Added Channel 9 **
**----------------------------------------------------------------------------**
** Release : v1.2 **
** Date : 22-05-2008 **
** Notes : Modified time definitions for FORCE_LOW_END_FRAME **
** and MIN_SYNC_TIME to avoid lost pulse groups **
**----------------------------------------------------------------------------**
** **
** 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. **
** **
------------------------------------------------------------------------------*/
 
#define ENABLE_BIT_DEFINITIONS
//#include <ioavr.h>
//#include <inavr.h>
#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_7_DATA_TRIGGER,
stPPM_CHANNEL_7_DATA,
stPPM_CHANNEL_8_START,
stPPM_CHANNEL_8_DATA,
stPPM_CHANNEL_9_START,
stPPM_CHANNEL_9_DATA,
stPPM_FINISH_PULSE,
stPPM_FINISH_FRAME,
stPPM_FRAME_END,
};
 
unsigned char channel_number = 0;
unsigned char ppm_state = stPPM_SYNC;
unsigned char adc_channel = 0;
volatile unsigned int channel_7 = 0xffff; // set to max. for testing if conversion is valid
volatile unsigned int channel_8 = 0xffff; // set to max. for testing if conversion is valid
volatile unsigned int channel_9 = 0xffff; // set to max. for testing if conversion is valid
 
 
/*------------------------------------------------------------------------------
** **
** function : init_pin(void) **
** purpose : Initialise I/O pins **
** **
**----------------------------------------------------------------------------*/
void init_pin(void)
{
 
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_7_ADC); // Channel 7 (pin12) input
PORTA &= ~(1 << CHANNEL_7_ADC); // disable pullup
 
DDRA &= ~(1 << CHANNEL_8_ADC); // Channel 8 (pin11) input
PORTA &= ~(1 << CHANNEL_8_ADC); // disable pullup
 
DDRA &= ~(1 << CHANNEL_9_ADC); // Channel 8 (pin11) input
PORTA &= ~(1 << CHANNEL_9_ADC); // disable pullup
 
}
/*-init_pin-------------------------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : init_adc(void) **
** purpose : Initialise ADC registers **
** **
**----------------------------------------------------------------------------*/
void init_adc(void)
{
 
cli(); // disable interrupts
 
DIDR0 |= ((1<<ADC2D)|(1<<ADC1D)); // digital input disable for pin 11 and 12
ADMUX = 0x00; // VCC as reference voltage, select channel 0
ADCSRA = (1 << ADPS2) | (1 << ADPS1)|| (0 << ADPS0); // 8.0 [Mhz] / 128 = 62,5 [kHz]
ADCSRB = 0x00; // free running mode
 
ADC_ENABLE;
 
sei(); // enable interrupts
}
/*-init_adc-------------------------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : init_timer1(void) **
** purpose : Initialise timer0 **
** Note(s) : Frequency : 8.0 [Mhz] **
** 8 / 8.0 Mhz : 1.00 [us] **
** **
**----------------------------------------------------------------------------*/
void init_timer1(void)
{
cli(); // disable interrupts
 
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
}
/*-init_timer1----------------------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : timer1_capture_interrupt(void) **
** purpose : Synchronise PPM frame and copy input events to PPM_OUT, **
** start mixing Ch7, 8 and 9 data when detect start pulse of Ch7 **
** **
**----------------------------------------------------------------------------*/
//#pragma vector=TIM1_CAPT_vect
//static __nested __interrupt void timer1_capture_interrupt (void)
ISR(TIMER1_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:
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 MX12 channel clock
if(channel_number>5) // all six channels read
{
ppm_state = stPPM_CHANNEL_7_DATA_TRIGGER; // 7th. 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;
 
case stPPM_CHANNEL_7_DATA_TRIGGER: // detect rising edge pulse
SET_COUNTER_TO_ZERO;
SET_PPM_OUT_LOW;
SET_TIMER_TO_COMPA_CTC;
DISABLE_INPUT_CAPTURE;
ENABLE_OUTPUT_COMPARE;
OCR1A = START_PULSE_LOW; // startpulse length 0.3ms
TRIGGER_INPUT_COMPARE_INTERRUPT;
ppm_state = stPPM_CHANNEL_7_DATA;
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_capture_interrupt---------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : timer1_compare_interrupt(void) **
** purpose : Mixing channel 7, 8 and 9 data into ppm out, **
** start input capture for frame synchronisation **
** **
**----------------------------------------------------------------------------*/
//#pragma vector=TIM1_COMPA_vect
//__interrupt void timer1_compare_interrupt (void)
ISR(TIM1_COMPA_vect)
{
cli();
switch (ppm_state)
{
case stPPM_CHANNEL_7_DATA: // create 7th channel data
SET_PPM_OUT_LOW;
SET_COUNTER_TO_ZERO;
OCR1A = channel_7; // COMPA: 0,7ms + channel 7 ADC value
ppm_state = stPPM_CHANNEL_8_START; // next State
break;
 
case stPPM_CHANNEL_8_START: // create 8th channel start pulse
SET_PPM_OUT_HIGH;
SET_COUNTER_TO_ZERO;
OCR1A = START_PULSE_HIGH; // startpulse length 0.3ms
ppm_state = stPPM_CHANNEL_8_DATA; // next State
break;
 
case stPPM_CHANNEL_8_DATA: // create 8th channel data
SET_PPM_OUT_LOW;
SET_COUNTER_TO_ZERO;
OCR1A = START_PULSE_LOW + channel_8; // COMPA: 0,7ms + channel 7 ADC value
ppm_state = stPPM_CHANNEL_9_START; // next State
break;
 
case stPPM_CHANNEL_9_START: // create 8th channel start pulse
SET_PPM_OUT_HIGH;
SET_COUNTER_TO_ZERO;
OCR1A = START_PULSE_HIGH; // startpulse length 0.3ms
ppm_state = stPPM_CHANNEL_9_DATA; // next State
break;
 
case stPPM_CHANNEL_9_DATA: // create 8th channel data
SET_PPM_OUT_LOW;
SET_COUNTER_TO_ZERO;
OCR1A = START_PULSE_LOW + channel_9; // COMPA: 0,7ms + channel 7 ADC 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_HIGH; // startpulse length 0.3ms
ppm_state = stPPM_FINISH_FRAME; // next State
break;
 
case stPPM_FINISH_FRAME: // create extra low pulse for masking PPM_IN data of channel 7 and 8
SET_PPM_OUT_LOW;
SET_COUNTER_TO_ZERO;
OCR1A = FORCE_LOW_END_FRAME; // keep last end low; 2 channels max - 2 channels min => 2x2ms - 2x1ms + extra length = 2 ms + 1 ms = 3ms => 3000 ticks
ppm_state = stPPM_FRAME_END; // next State
break;
 
case stPPM_FRAME_END:
default:
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();
}
/*-timer1_compare_interrupt---------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : adc_server(void) **
** purpose : Handle Analog conversion of RC channel 7, 8 and 9 **
** **
**----------------------------------------------------------------------------*/
//#pragma vector=ADC_vect
//__interrupt void adc_server(void)
ISR(ADC_vect)
{
unsigned int AdcResult;
 
ADC_DISABLE;
 
AdcResult = ADC;
if(AdcResult > 1000) // limit conversion value
AdcResult = 1000; // 1000 => 1ms
 
ADMUX &= ~(ADC_CHANNEL_MASK); // clear channel select bits
 
if(adc_channel == ADC_CHANNEL_7)
{
channel_7 = AdcResult; // set channel 7 value;
adc_channel = ADC_CHANNEL_8; // set next event for channel 8 conversion
}
else if(adc_channel == ADC_CHANNEL_8)
{
channel_8 = AdcResult; // set channel 8 value;
adc_channel = ADC_CHANNEL_9; // set next event for channel 9 conversion
}
else
{
channel_9 = AdcResult; // set channel 9 value;
adc_channel = ADC_CHANNEL_7; // set next event for channel 7 conversion
}
 
ADMUX |= adc_channel; // select new conversion channel
 
ADC_ENABLE;
}
/*-adc_server-----------------------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : check_valid_adc_value(void) **
** purpose : wait until 3 ADC channels are processed at least once **
** before init Input Capture/Timer1 **
** **
**----------------------------------------------------------------------------*/
void check_valid_adc_value (void)
{
unsigned char exit = FALSE;
 
do
{
if(channel_7 < 0xffff && channel_8 < 0xffff && channel_9 < 0xffff) // both channels must be processed
exit = TRUE;
 
}while (!exit);
}
/*-check_valid_adc_value------------------------------------------------------*/
 
 
/*------------------------------------------------------------------------------
** **
** function : main(void) **
** **
**----------------------------------------------------------------------------*/
int main(void)
{
 
init_pin();
init_adc();
check_valid_adc_value(); // wait until both ADC channels are processed at least once
init_timer1();
 
while(1)
{}
}
 
/*-main-----------------------------------------------------------------------*/