Merge remote-tracking branch 'refs/remotes/pascallanger/master'

# Conflicts: all resolved by taking the master's code since all changes
were already taken into master
#	Multiprotocol/CABELL_nrf224l01.ino
#	Multiprotocol/Multiprotocol.h
#	Multiprotocol/Multiprotocol.ino
#	Multiprotocol/NRF24l01_SPI.ino
#	Multiprotocol/Validate.h
#	Multiprotocol/_Config.h
This commit is contained in:
Dennis 2017-11-24 00:13:31 -05:00
commit 8b8812a194
75 changed files with 29111 additions and 1211 deletions

View File

@ -1,99 +0,0 @@
{
"packages": [
{
"name": "MULTI",
"maintainer": "Pascal",
"help": {
"online": "https://www.rcgroups.com/forums/showthread.php?2165676-DIY-Multiprotocol-TX-Module/page555"
},
"websiteURL": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module",
"platforms": [
{
"name": "Multi 4in1 Atmega328p",
"architecture": "avr",
"version": "1.0.0",
"category": "Multi",
"help": {
"online": "https://www.rcgroups.com/forums/showthread.php?2165676-DIY-Multiprotocol-TX-Module/page555"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module",
"archiveFileName": "multi_avr-1.0.0.zip",
"checksum": "SHA-256:ec3ff8a1dc96d3ba6f432b9b837a35fd4174a34b3d2927de1d51010e8b94f9f1",
"size": "15005",
"boards": [
{"name": "Multi 4in1 Atmega328p"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino5"
}
]
},
{
"name": "Multi 4in1 STM32",
"architecture": "stm32",
"version": "1.0.0",
"category": "Multi",
"help": {
"online": "https://www.rcgroups.com/forums/showthread.php?2165676-DIY-Multiprotocol-TX-Module/page555"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module",
"archiveFileName": "multi_stm32-1.0.0.zip",
"checksum": "SHA-256:ec3ff8a1dc96d3ba6f432b9b837a35fd4174a34b3d2927de1d51010e8b94f9f1",
"size": "15005",
"boards": [
{"name": "Multi 4in1 STM32"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino5"
}
]
},
{
"name": "Multi 4in1 OrangeTX",
"architecture": "xmega",
"version": "1.0.0",
"category": "Multi",
"help": {
"online": "https://www.rcgroups.com/forums/showthread.php?2165676-DIY-Multiprotocol-TX-Module/page555"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module",
"archiveFileName": "multi_xmega-1.0.0.zip",
"checksum": "SHA-256:ec3ff8a1dc96d3ba6f432b9b837a35fd4174a34b3d2927de1d51010e8b94f9f1",
"size": "15005",
"boards": [
{"name": "Multi 4in1 OrangeTX"}
],
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
"version": "4.8.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
"version": "6.0.1-arduino5"
}
]
}
],
"tools":[]
}
]
}

View File

@ -0,0 +1,2 @@
:02000000FFFF00
:00000001FF

View File

@ -0,0 +1,34 @@
:107E0000112484B714BE9FEF9BB99CE395B991E010
:107E100098B98370A9F08AEF80938500109284004E
:107E200085E08093810096BBB09BFECF10928100CD
:107E300093B186B181709C73892B8D3109F0B3D0D9
:107E400082E08093C00088E18093C10086E0809347
:107E5000C20081E28093C400259AC0E0D0E093E0A4
:107E6000F92EEE24E39425E0D22E31E1C32EA9D0E1
:107E7000813481F4A6D08EBBABD08EB3823811F49E
:107E800085E006C08EB3813811F484E001C083E040
:107E900091D086C0823411F484E103C0853419F492
:107EA00085E09DD07DC0853541F48BD0C82F89D029
:107EB000D0E0D82BCC0FDD1F72C0863521F484E0D2
:107EC0008ED080E0E5CF843609F03DC07AD079D0FD
:107ED000B82E77D0C11520E7D20718F000E011E0E6
:107EE00004C0FE01F7BEE895F9CF6BD0F80181938D
:107EF0008F01BE12FACFCE01905781159E4018F423
:107F0000FE01F7BEE89564D0C115FEE7DF0708F073
:107F100047C007B600FCFDCFFE01A0E0B1E08D91A7
:107F20009D910C01E7BEE89511243296A03821E01E
:107F3000B207A9F7FE01D7BEE89507B600FCFDCF52
:107F4000C7BEE8952DC08437B1F43BD03AD0B82EE7
:107F500038D03ED0FE01AC2EAB0C8F010F5F1F4F0F
:107F6000849128D0A01205C02196BA94CB0DD11DC2
:107F700017C0F801F2CF853739F42AD08EE11AD034
:107F800085E918D08FE084CF813549F421D080E194
:107F900011D08091C00086FFFCCF05D001C018D061
:107FA00080E108D064CFE0E0F0E084918F3F09F0F9
:107FB000099408959091C00095FFFCCF8093C6006E
:107FC00008958091C00087FFFCCF8091C60008957E
:107FD000F8DF803211F085E1EDDF84E1EBCFCF9364
:107FE000C82FEFDFC150E9F7CF91F2CFA8950895E0
:0C7FF000E0E6F0E098E1908380830895C3
:0400000300007E007B
:00000001FF

View File

@ -0,0 +1,504 @@
# Makefile for ATmegaBOOT
# E.Lins, 18.7.2005
# $Id$
#
# Instructions
#
# To make bootloader .hex file:
# make diecimila
# make lilypad
# make ng
# etc...
#
# To burn bootloader .hex file:
# make diecimila_isp
# make lilypad_isp
# make ng_isp
# etc...
# program name should not be changed...
PROGRAM = optiboot
# The default behavior is to build using tools that are in the users
# current path variables, but we can also build using an installed
# Arduino user IDE setup, or the Arduino source tree.
# Uncomment this next lines to build within the arduino environment,
# using the arduino-included avrgcc toolset (mac and pc)
# ENV ?= arduino
# ENV ?= arduinodev
# OS ?= macosx
# OS ?= windows
# enter the parameters for the avrdude isp tool -b19200
#
# These are the parameters for a usb-based STK500v2 programmer.
# Exact type unknown. (historical Makefile values.)
ISPTOOL = stk500v2
ISPPORT = usb
ISPSPEED = -b 57600
#
#
# These are parameters for using an Arduino with the ArduinoISP sketch
# as the programmer. On a mac, for a particular Uno as programmer.
#ISPTOOL = stk500v1 -C /Applications/arduino/arduino-0022/hardware/tools/avr/etc/avrdude.conf
#ISPPORT = /dev/tty.usbmodemfd3141
#ISPSPEED = -b19200
MCU_TARGET = atmega168
LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
# Build environments
# Start of some ugly makefile-isms to allow optiboot to be built
# in several different environments. See the README.TXT file for
# details.
# default
fixpath = $(1)
ifeq ($(ENV), arduino)
# For Arduino, we assume that we're connected to the optiboot directory
# included with the arduino distribution, which means that the full set
# of avr-tools are "right up there" in standard places.
TOOLROOT = ../../../tools
GCCROOT = $(TOOLROOT)/avr/bin/
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
ifeq ($(OS), windows)
# On windows, SOME of the tool paths will need to have backslashes instead
# of forward slashes (because they use windows cmd.exe for execution instead
# of a unix/mingw shell?) We also have to ensure that a consistent shell
# is used even if a unix shell is installed (ie as part of WINAVR)
fixpath = $(subst /,\,$1)
SHELL = cmd.exe
endif
else ifeq ($(ENV), arduinodev)
# Arduino IDE source code environment. Use the unpacked compilers created
# by the build (you'll need to do "ant build" first.)
ifeq ($(OS), macosx)
TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
endif
ifeq ($(OS), windows)
TOOLROOT = ../../../../build/windows/work/hardware/tools
endif
GCCROOT = $(TOOLROOT)/avr/bin/
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
else
GCCROOT =
AVRDUDE_CONF =
endif
#
# End of build environment code.
# the efuse should really be 0xf8; since, however, only the lower
# three bits of that byte are used on the atmega168, avrdude gets
# confused if you specify 1's for the higher bits, see:
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
#
# similarly, the lock bits should be 0xff instead of 0x3f (to
# unlock the bootloader section) and 0xcf instead of 0x2f (to
# lock it), but since the high two bits of the lock byte are
# unused, avrdude would get confused.
ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
-U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
OBJ = $(PROGRAM).o
OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types
# -mshort-calls
DEFS =
LIBS =
CC = $(GCCROOT)avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib
OBJCOPY = $(GCCROOT)avr-objcopy
OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump)
SIZE = $(GCCROOT)avr-size
#Voice board test
# ATmega328
#
#atmega328: TARGET = atmega328p
#atmega328: MCU_TARGET = atmega328p
#atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
#atmega328: AVR_FREQ = 12000000L
#atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
#atmega328: $(PROGRAM)_atmega328.hex
#atmega328: $(PROGRAM)_atmega328.lst
atmega328: TARGET = atmega328
atmega328: MCU_TARGET = atmega328p
atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
atmega328: AVR_FREQ = 16000000L
atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328: $(PROGRAM)_atmega328_16.hex
atmega328: $(PROGRAM)_atmega328_16.lst
xmega32D4: TARGET = atxmega32d4
xmega32D4: MCU_TARGET = atxmega32d4
xmega32D4: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
xmega32D4: AVR_FREQ = 32000000L
xmega32D4: LDSECTIONS = -Wl,--section-start=.text=0x8000
xmega32D4: $(PROGRAM)_xmega32d4.hex
xmega32D4: $(PROGRAM)_xmega32d4.lst
# Test platforms
# Virtual boot block test
virboot328: TARGET = atmega328
virboot328: MCU_TARGET = atmega328p
virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DVIRTUAL_BOOT'
virboot328: AVR_FREQ = 16000000L
virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
virboot328: $(PROGRAM)_atmega328.hex
virboot328: $(PROGRAM)_atmega328.lst
# 20MHz clocked platforms
#
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
#
pro20: TARGET = pro_20mhz
pro20: MCU_TARGET = atmega168
pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
pro20: AVR_FREQ = 20000000L
pro20: $(PROGRAM)_pro_20mhz.hex
pro20: $(PROGRAM)_pro_20mhz.lst
pro20_isp: pro20
pro20_isp: TARGET = pro_20mhz
# 2.7V brownout
pro20_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro20_isp: LFUSE = C6
# 512 byte boot
pro20_isp: EFUSE = 04
pro20_isp: isp
# 16MHz clocked platforms
#
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
#
pro16: TARGET = pro_16MHz
pro16: MCU_TARGET = atmega168
pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
pro16: AVR_FREQ = 16000000L
pro16: $(PROGRAM)_pro_16MHz.hex
pro16: $(PROGRAM)_pro_16MHz.lst
pro16_isp: pro16
pro16_isp: TARGET = pro_16MHz
# 2.7V brownout
pro16_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro16_isp: LFUSE = C6
# 512 byte boot
pro16_isp: EFUSE = 04
pro16_isp: isp
# Diecimila, Duemilanove with m168, and NG use identical bootloaders
# Call it "atmega168" for generality and clarity, keep "diecimila" for
# backward compatibility of makefile
#
atmega168: TARGET = atmega168
atmega168: MCU_TARGET = atmega168
atmega168: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
atmega168: AVR_FREQ = 12000000L
atmega168: $(PROGRAM)_atmega168.hex
atmega168: $(PROGRAM)_atmega168.lst
atmega168_isp: atmega168
atmega168_isp: TARGET = atmega168
# 2.7V brownout
atmega168_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega168_isp: LFUSE = FF
# 512 byte boot
atmega168_isp: EFUSE = 04
atmega168_isp: isp
diecimila: TARGET = diecimila
diecimila: MCU_TARGET = atmega168
diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
diecimila: AVR_FREQ = 16000000L
diecimila: $(PROGRAM)_diecimila.hex
diecimila: $(PROGRAM)_diecimila.lst
diecimila_isp: diecimila
diecimila_isp: TARGET = diecimila
# 2.7V brownout
diecimila_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
diecimila_isp: LFUSE = FF
# 512 byte boot
diecimila_isp: EFUSE = 04
diecimila_isp: isp
atmega328_isp: atmega328
atmega328_isp: TARGET = atmega328
atmega328_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega328_isp: LFUSE = FF
# 2.7V brownout
atmega328_isp: EFUSE = FD
atmega328_isp: isp
atmega1284: TARGET = atmega1284p
atmega1284: MCU_TARGET = atmega1284p
atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
atmega1284: AVR_FREQ = 16000000L
atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
atmega1284: $(PROGRAM)_atmega1284p.hex
atmega1284: $(PROGRAM)_atmega1284p.lst
atmega1284_isp: atmega1284
atmega1284_isp: TARGET = atmega1284p
atmega1284_isp: MCU_TARGET = atmega1284p
# 1024 byte boot
atmega1284_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega1284_isp: LFUSE = FF
# 2.7V brownout
atmega1284_isp: EFUSE = FD
atmega1284_isp: isp
# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
#
sanguino: TARGET = atmega644p
sanguino: MCU_TARGET = atmega644p
sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
sanguino: AVR_FREQ = 16000000L
sanguino: LDSECTIONS = -Wl,--section-start=.text=0xfc00 -Wl,--section-start=.version=0xfffe
sanguino: $(PROGRAM)_atmega644p.hex
sanguino: $(PROGRAM)_atmega644p.lst
sanguino_isp: sanguino
sanguino_isp: TARGET = atmega644p
sanguino_isp: MCU_TARGET = atmega644p
# 1024 byte boot
sanguino_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
sanguino_isp: LFUSE = FF
# 2.7V brownout
sanguino_isp: EFUSE = FD
sanguino_isp: isp
# Mega has a minimum boot size of 1024 bytes, so enable extra functions
#mega: TARGET = atmega1280
mega1280: MCU_TARGET = atmega1280
mega1280: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
mega1280: AVR_FREQ = 16000000L
mega1280: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
mega1280: $(PROGRAM)_atmega1280.hex
mega1280: $(PROGRAM)_atmega1280.lst
mega1280_isp: mega
mega1280_isp: TARGET = atmega1280
mega1280_isp: MCU_TARGET = atmega1280
# 1024 byte boot
mega1280_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
mega1280_isp: LFUSE = FF
# 2.7V brownout
mega1280_isp: EFUSE = FD
mega1280_isp: isp
# ATmega8
#
atmega8: TARGET = atmega8
atmega8: MCU_TARGET = atmega8
atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega8: AVR_FREQ = 16000000L
atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
atmega8: $(PROGRAM)_atmega8.hex
atmega8: $(PROGRAM)_atmega8.lst
atmega8_isp: atmega8
atmega8_isp: TARGET = atmega8
atmega8_isp: MCU_TARGET = atmega8
# SPIEN, CKOPT, Bootsize=512B
atmega8_isp: HFUSE = CC
# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms
atmega8_isp: LFUSE = BF
atmega8_isp: isp
# ATmega88
#
atmega88: TARGET = atmega88
atmega88: MCU_TARGET = atmega88
atmega88: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
atmega88: AVR_FREQ = 12000000L
atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
atmega88: $(PROGRAM)_atmega88.hex
atmega88: $(PROGRAM)_atmega88.lst
atmega88_isp: atmega88
atmega88_isp: TARGET = atmega88
atmega88_isp: MCU_TARGET = atmega88
# 2.7V brownout
atmega88_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atemga88_isp: LFUSE = FF
# 512 byte boot
atmega88_isp: EFUSE = 04
atmega88_isp: isp
# 8MHz clocked platforms
#
# These are capable of 38400 baud
#
lilypad: TARGET = lilypad
lilypad: MCU_TARGET = atmega168
lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
lilypad: AVR_FREQ = 8000000L
lilypad: $(PROGRAM)_lilypad.hex
lilypad: $(PROGRAM)_lilypad.lst
lilypad_isp: lilypad
lilypad_isp: TARGET = lilypad
# 2.7V brownout
lilypad_isp: HFUSE = DD
# Internal 8MHz osc (8MHz) Slow rising power
lilypad_isp: LFUSE = E2
# 512 byte boot
lilypad_isp: EFUSE = 04
lilypad_isp: isp
lilypad_resonator: TARGET = lilypad_resonator
lilypad_resonator: MCU_TARGET = atmega168
lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
lilypad_resonator: AVR_FREQ = 8000000L
lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
lilypad_resonator_isp: lilypad_resonator
lilypad_resonator_isp: TARGET = lilypad_resonator
# 2.7V brownout
lilypad_resonator_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
lilypad_resonator_isp: LFUSE = C6
# 512 byte boot
lilypad_resonator_isp: EFUSE = 04
lilypad_resonator_isp: isp
pro8: TARGET = pro_8MHz
pro8: MCU_TARGET = atmega168
pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
pro8: AVR_FREQ = 8000000L
pro8: $(PROGRAM)_pro_8MHz.hex
pro8: $(PROGRAM)_pro_8MHz.lst
pro8_isp: pro8
pro8_isp: TARGET = pro_8MHz
# 2.7V brownout
pro8_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro8_isp: LFUSE = C6
# 512 byte boot
pro8_isp: EFUSE = 04
pro8_isp: isp
atmega328_pro8: TARGET = atmega328_pro_8MHz
atmega328_pro8: MCU_TARGET = atmega328p
atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega328_pro8: AVR_FREQ = 8000000L
atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
atmega328_pro8_isp: atmega328_pro8
atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
atmega328_pro8_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_pro8_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega328_pro8_isp: LFUSE = FF
# 2.7V brownout
atmega328_pro8_isp: EFUSE = DE
atmega328_pro8_isp: isp
# 1MHz clocked platforms
#
# These are capable of 9600 baud
#
luminet: TARGET = luminet
luminet: MCU_TARGET = attiny84
luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600'
luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
luminet: AVR_FREQ = 1000000L
luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
luminet: $(PROGRAM)_luminet.hex
luminet: $(PROGRAM)_luminet.lst
luminet_isp: luminet
luminet_isp: TARGET = luminet
luminet_isp: MCU_TARGET = attiny84
# Brownout disabled
luminet_isp: HFUSE = DF
# 1MHz internal oscillator, slowly rising power
luminet_isp: LFUSE = 62
# Self-programming enable
luminet_isp: EFUSE = FE
luminet_isp: isp
#
# Generic build instructions
#
#
isp: $(TARGET)
$(ISPFUSES)
$(ISPFLASH)
isp-stk500: $(PROGRAM)_$(TARGET).hex
$(STK500-1)
$(STK500-2)
%.elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
$(SIZE) $@
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@

View File

@ -0,0 +1,848 @@
/* Modified to use out for SPM access
** Peter Knight, Optiboot project http://optiboot.googlecode.com
**
** Todo: Tidy up
**
** "_short" routines execute 1 cycle faster and use 1 less word of flash
** by using "out" instruction instead of "sts".
**
** Additional elpm variants that trust the value of RAMPZ
*/
/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Eric B. Weddington
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
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. */
/* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */
#ifndef _AVR_BOOT_H_
#define _AVR_BOOT_H_ 1
/** \file */
/** \defgroup avr_boot <avr/boot.h>: Bootloader Support Utilities
\code
#include <avr/io.h>
#include <avr/boot.h>
\endcode
The macros in this module provide a C language interface to the
bootloader support functionality of certain AVR processors. These
macros are designed to work with all sizes of flash memory.
Global interrupts are not automatically disabled for these macros. It
is left up to the programmer to do this. See the code example below.
Also see the processor datasheet for caveats on having global interrupts
enabled during writing of the Flash.
\note Not all AVR processors provide bootloader support. See your
processor datasheet to see if it provides bootloader support.
\todo From email with Marek: On smaller devices (all except ATmega64/128),
__SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
instructions - since the boot loader has a limited size, this could be an
important optimization.
\par API Usage Example
The following code shows typical usage of the boot API.
\code
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
void boot_program_page (uint32_t page, uint8_t *buf)
{
uint16_t i;
uint8_t sreg;
// Disable interrupts.
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait (); // Wait until the memory is erased.
for (i=0; i<SPM_PAGESIZE; i+=2)
{
// Set up little-endian word.
uint16_t w = *buf++;
w += (*buf++) << 8;
boot_page_fill (page + i, w);
}
boot_page_write (page); // Store buffer in flash page.
boot_spm_busy_wait(); // Wait until the memory is written.
// Reenable RWW-section again. We need this if we want to jump back
// to the application after bootloading.
boot_rww_enable ();
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
}\endcode */
#include <avr/eeprom.h>
#include <avr/io.h>
#include <inttypes.h>
#include <limits.h>
/* Check for SPM Control Register in processor. */
#if defined (SPMCSR)
# define __SPM_REG SPMCSR
#elif defined (SPMCR)
# define __SPM_REG SPMCR
#else
# error AVR processor does not provide bootloader support!
#endif
/* Check for SPM Enable bit. */
#if defined(SPMEN)
# define __SPM_ENABLE SPMEN
#elif defined(SELFPRGEN)
# define __SPM_ENABLE SELFPRGEN
#else
# error Cannot find SPM Enable bit definition!
#endif
/** \ingroup avr_boot
\def BOOTLOADER_SECTION
Used to declare a function or variable to be placed into a
new section called .bootloader. This section and its contents
can then be relocated to any address (such as the bootloader
NRWW area) at link-time. */
#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
/* Create common bit definitions. */
#ifdef ASB
#define __COMMON_ASB ASB
#else
#define __COMMON_ASB RWWSB
#endif
#ifdef ASRE
#define __COMMON_ASRE ASRE
#else
#define __COMMON_ASRE RWWSRE
#endif
/* Define the bit positions of the Boot Lock Bits. */
#define BLB12 5
#define BLB11 4
#define BLB02 3
#define BLB01 2
/** \ingroup avr_boot
\def boot_spm_interrupt_enable()
Enable the SPM interrupt. */
#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
/** \ingroup avr_boot
\def boot_spm_interrupt_disable()
Disable the SPM interrupt. */
#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
/** \ingroup avr_boot
\def boot_is_spm_interrupt()
Check if the SPM interrupt is enabled. */
#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
/** \ingroup avr_boot
\def boot_rww_busy()
Check if the RWW section is busy. */
#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
/** \ingroup avr_boot
\def boot_spm_busy()
Check if the SPM instruction is busy. */
#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
/** \ingroup avr_boot
\def boot_spm_busy_wait()
Wait while the SPM instruction is busy. */
#define boot_spm_busy_wait() do{}while(boot_spm_busy())
#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
#define __boot_page_fill_short(address, data) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r0, %3\n\t" \
"out %0, %1\n\t" \
"spm\n\t" \
"clr r1\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_FILL), \
"z" ((uint16_t)address), \
"r" ((uint16_t)data) \
: "r0" \
); \
}))
#define __boot_page_fill_normal(address, data) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r0, %3\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
"clr r1\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_FILL), \
"z" ((uint16_t)address), \
"r" ((uint16_t)data) \
: "r0" \
); \
}))
#define __boot_page_fill_alternate(address, data)\
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r0, %3\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
"clr r1\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_FILL), \
"z" ((uint16_t)address), \
"r" ((uint16_t)data) \
: "r0" \
); \
}))
#define __boot_page_fill_extended(address, data) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r0, %4\n\t" \
"movw r30, %A3\n\t" \
"sts %1, %C3\n\t" \
"sts %0, %2\n\t" \
"spm\n\t" \
"clr r1\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"i" (_SFR_MEM_ADDR(RAMPZ)), \
"r" ((uint8_t)__BOOT_PAGE_FILL), \
"r" ((uint32_t)address), \
"r" ((uint16_t)data) \
: "r0", "r30", "r31" \
); \
}))
#define __boot_page_fill_extended_short(address, data) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r0, %4\n\t" \
"movw r30, %A3\n\t" \
"out %1, %C3\n\t" \
"out %0, %2\n\t" \
"spm\n\t" \
"clr r1\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"i" (_SFR_IO_ADDR(RAMPZ)), \
"r" ((uint8_t)__BOOT_PAGE_FILL), \
"r" ((uint32_t)address), \
"r" ((uint16_t)data) \
: "r0", "r30", "r31" \
); \
}))
#define __boot_page_erase_short(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"out %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
"z" ((uint16_t)address) \
); \
}))
#define __boot_page_erase_normal(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
"z" ((uint16_t)address) \
); \
}))
#define __boot_page_erase_alternate(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
"z" ((uint16_t)address) \
); \
}))
#define __boot_page_erase_extended(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r30, %A3\n\t" \
"sts %1, %C3\n\t" \
"sts %0, %2\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"i" (_SFR_MEM_ADDR(RAMPZ)), \
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
"r" ((uint32_t)address) \
: "r30", "r31" \
); \
}))
#define __boot_page_erase_extended_short(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r30, %A3\n\t" \
"out %1, %C3\n\t" \
"out %0, %2\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"i" (_SFR_IO_ADDR(RAMPZ)), \
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
"r" ((uint32_t)address) \
: "r30", "r31" \
); \
}))
#define __boot_page_write_short(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"out %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
"z" ((uint16_t)address) \
); \
}))
#define __boot_page_write_normal(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
"z" ((uint16_t)address) \
); \
}))
#define __boot_page_write_alternate(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
"z" ((uint16_t)address) \
); \
}))
#define __boot_page_write_extended(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r30, %A3\n\t" \
"sts %1, %C3\n\t" \
"sts %0, %2\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"i" (_SFR_MEM_ADDR(RAMPZ)), \
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
"r" ((uint32_t)address) \
: "r30", "r31" \
); \
}))
#define __boot_page_write_extended_short(address) \
(__extension__({ \
__asm__ __volatile__ \
( \
"movw r30, %A3\n\t" \
"out %1, %C3\n\t" \
"out %0, %2\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"i" (_SFR_IO_ADDR(RAMPZ)), \
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
"r" ((uint32_t)address) \
: "r30", "r31" \
); \
}))
#define __boot_rww_enable_short() \
(__extension__({ \
__asm__ __volatile__ \
( \
"out %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_RWW_ENABLE) \
); \
}))
#define __boot_rww_enable() \
(__extension__({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_RWW_ENABLE) \
); \
}))
#define __boot_rww_enable_alternate() \
(__extension__({ \
__asm__ __volatile__ \
( \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_RWW_ENABLE) \
); \
}))
/* From the mega16/mega128 data sheets (maybe others):
Bits by SPM To set the Boot Loader Lock bits, write the desired data to
R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
that may prevent the Application and Boot Loader section from any
software update by the MCU.
If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
will be programmed if an SPM instruction is executed within four cycles
after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is
don't care during this operation, but for future compatibility it is
recommended to load the Z-pointer with $0001 (same as used for reading the
Lock bits). For future compatibility It is also recommended to set bits 7,
6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the
Lock bits the entire Flash can be read during the operation. */
#define __boot_lock_bits_set_short(lock_bits) \
(__extension__({ \
uint8_t value = (uint8_t)(~(lock_bits)); \
__asm__ __volatile__ \
( \
"ldi r30, 1\n\t" \
"ldi r31, 0\n\t" \
"mov r0, %2\n\t" \
"out %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"r" (value) \
: "r0", "r30", "r31" \
); \
}))
#define __boot_lock_bits_set(lock_bits) \
(__extension__({ \
uint8_t value = (uint8_t)(~(lock_bits)); \
__asm__ __volatile__ \
( \
"ldi r30, 1\n\t" \
"ldi r31, 0\n\t" \
"mov r0, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"r" (value) \
: "r0", "r30", "r31" \
); \
}))
#define __boot_lock_bits_set_alternate(lock_bits) \
(__extension__({ \
uint8_t value = (uint8_t)(~(lock_bits)); \
__asm__ __volatile__ \
( \
"ldi r30, 1\n\t" \
"ldi r31, 0\n\t" \
"mov r0, %2\n\t" \
"sts %0, %1\n\t" \
"spm\n\t" \
".word 0xffff\n\t" \
"nop\n\t" \
: \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"r" (value) \
: "r0", "r30", "r31" \
); \
}))
/*
Reading lock and fuse bits:
Similarly to writing the lock bits above, set BLBSET and SPMEN (or
SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an
LPM instruction.
Z address: contents:
0x0000 low fuse bits
0x0001 lock bits
0x0002 extended fuse bits
0x0003 high fuse bits
Sounds confusing, doesn't it?
Unlike the macros in pgmspace.h, no need to care for non-enhanced
cores here as these old cores do not provide SPM support anyway.
*/
/** \ingroup avr_boot
\def GET_LOW_FUSE_BITS
address to read the low fuse bits, using boot_lock_fuse_bits_get
*/
#define GET_LOW_FUSE_BITS (0x0000)
/** \ingroup avr_boot
\def GET_LOCK_BITS
address to read the lock bits, using boot_lock_fuse_bits_get
*/
#define GET_LOCK_BITS (0x0001)
/** \ingroup avr_boot
\def GET_EXTENDED_FUSE_BITS
address to read the extended fuse bits, using boot_lock_fuse_bits_get
*/
#define GET_EXTENDED_FUSE_BITS (0x0002)
/** \ingroup avr_boot
\def GET_HIGH_FUSE_BITS
address to read the high fuse bits, using boot_lock_fuse_bits_get
*/
#define GET_HIGH_FUSE_BITS (0x0003)
/** \ingroup avr_boot
\def boot_lock_fuse_bits_get(address)
Read the lock or fuse bits at \c address.
Parameter \c address can be any of GET_LOW_FUSE_BITS,
GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
\note The lock and fuse bits returned are the physical values,
i.e. a bit returned as 0 means the corresponding fuse or lock bit
is programmed.
*/
#define boot_lock_fuse_bits_get_short(address) \
(__extension__({ \
uint8_t __result; \
__asm__ __volatile__ \
( \
"ldi r30, %3\n\t" \
"ldi r31, 0\n\t" \
"out %1, %2\n\t" \
"lpm %0, Z\n\t" \
: "=r" (__result) \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"M" (address) \
: "r0", "r30", "r31" \
); \
__result; \
}))
#define boot_lock_fuse_bits_get(address) \
(__extension__({ \
uint8_t __result; \
__asm__ __volatile__ \
( \
"ldi r30, %3\n\t" \
"ldi r31, 0\n\t" \
"sts %1, %2\n\t" \
"lpm %0, Z\n\t" \
: "=r" (__result) \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
"M" (address) \
: "r0", "r30", "r31" \
); \
__result; \
}))
/** \ingroup avr_boot
\def boot_signature_byte_get(address)
Read the Signature Row byte at \c address. For some MCU types,
this function can also retrieve the factory-stored oscillator
calibration bytes.
Parameter \c address can be 0-0x1f as documented by the datasheet.
\note The values are MCU type dependent.
*/
#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
#define boot_signature_byte_get_short(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ __volatile__ \
( \
"out %1, %2\n\t" \
"lpm %0, Z" "\n\t" \
: "=r" (__result) \
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
"r" ((uint8_t) __BOOT_SIGROW_READ), \
"z" (__addr16) \
); \
__result; \
}))
#define boot_signature_byte_get(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ __volatile__ \
( \
"sts %1, %2\n\t" \
"lpm %0, Z" "\n\t" \
: "=r" (__result) \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t) __BOOT_SIGROW_READ), \
"z" (__addr16) \
); \
__result; \
}))
/** \ingroup avr_boot
\def boot_page_fill(address, data)
Fill the bootloader temporary page buffer for flash
address with data word.
\note The address is a byte address. The data is a word. The AVR
writes data to the buffer a word at a time, but addresses the buffer
per byte! So, increment your address by 2 between calls, and send 2
data bytes in a word format! The LSB of the data is written to the lower
address; the MSB of the data is written to the higher address.*/
/** \ingroup avr_boot
\def boot_page_erase(address)
Erase the flash page that contains address.
\note address is a byte address in flash, not a word address. */
/** \ingroup avr_boot
\def boot_page_write(address)
Write the bootloader temporary page buffer
to flash page that contains address.
\note address is a byte address in flash, not a word address. */
/** \ingroup avr_boot
\def boot_rww_enable()
Enable the Read-While-Write memory section. */
/** \ingroup avr_boot
\def boot_lock_bits_set(lock_bits)
Set the bootloader lock bits.
\param lock_bits A mask of which Boot Loader Lock Bits to set.
\note In this context, a 'set bit' will be written to a zero value.
Note also that only BLBxx bits can be programmed by this command.
For example, to disallow the SPM instruction from writing to the Boot
Loader memory section of flash, you would use this macro as such:
\code
boot_lock_bits_set (_BV (BLB11));
\endcode
\note Like any lock bits, the Boot Loader Lock Bits, once set,
cannot be cleared again except by a chip erase which will in turn
also erase the boot loader itself. */
/* Normal versions of the macros use 16-bit addresses.
Extended versions of the macros use 32-bit addresses.
Alternate versions of the macros use 16-bit addresses and require special
instruction sequences after LPM.
FLASHEND is defined in the ioXXXX.h file.
USHRT_MAX is defined in <limits.h>. */
#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
|| defined(__AVR_ATmega323__)
/* Alternate: ATmega161/163/323 and 16 bit address */
#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
#define boot_page_erase(address) __boot_page_erase_alternate(address)
#define boot_page_write(address) __boot_page_write_alternate(address)
#define boot_rww_enable() __boot_rww_enable_alternate()
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
#elif (FLASHEND > USHRT_MAX)
/* Extended: >16 bit address */
#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
#define boot_page_erase(address) __boot_page_erase_extended_short(address)
#define boot_page_write(address) __boot_page_write_extended_short(address)
#define boot_rww_enable() __boot_rww_enable_short()
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
#else
/* Normal: 16 bit address */
#define boot_page_fill(address, data) __boot_page_fill_short(address, data)
#define boot_page_erase(address) __boot_page_erase_short(address)
#define boot_page_write(address) __boot_page_write_short(address)
#define boot_rww_enable() __boot_rww_enable_short()
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
#endif
/** \ingroup avr_boot
Same as boot_page_fill() except it waits for eeprom and spm operations to
complete before filling the page. */
#define boot_page_fill_safe(address, data) \
do { \
boot_spm_busy_wait(); \
eeprom_busy_wait(); \
boot_page_fill(address, data); \
} while (0)
/** \ingroup avr_boot
Same as boot_page_erase() except it waits for eeprom and spm operations to
complete before erasing the page. */
#define boot_page_erase_safe(address) \
do { \
boot_spm_busy_wait(); \
eeprom_busy_wait(); \
boot_page_erase (address); \
} while (0)
/** \ingroup avr_boot
Same as boot_page_write() except it waits for eeprom and spm operations to
complete before writing the page. */
#define boot_page_write_safe(address) \
do { \
boot_spm_busy_wait(); \
eeprom_busy_wait(); \
boot_page_write (address); \
} while (0)
/** \ingroup avr_boot
Same as boot_rww_enable() except waits for eeprom and spm operations to
complete before enabling the RWW mameory. */
#define boot_rww_enable_safe() \
do { \
boot_spm_busy_wait(); \
eeprom_busy_wait(); \
boot_rww_enable(); \
} while (0)
/** \ingroup avr_boot
Same as boot_lock_bits_set() except waits for eeprom and spm operations to
complete before setting the lock bits. */
#define boot_lock_bits_set_safe(lock_bits) \
do { \
boot_spm_busy_wait(); \
eeprom_busy_wait(); \
boot_lock_bits_set (lock_bits); \
} while (0)
#endif /* _AVR_BOOT_H_ */

View File

@ -0,0 +1,891 @@
/**********************************************************/
/* Optiboot bootloader for Arduino */
/* */
/* http://optiboot.googlecode.com */
/* */
/* Arduino-maintained version : See README.TXT */
/* http://code.google.com/p/arduino/ */
/* It is the intent that changes not relevant to the */
/* Arduino production envionment get moved from the */
/* optiboot project to the arduino project in "lumps." */
/* */
/* Heavily optimised bootloader that is faster and */
/* smaller than the Arduino standard bootloader */
/* */
/* Enhancements: */
/* Fits in 512 bytes, saving 1.5K of code space */
/* Background page erasing speeds up programming */
/* Higher baud rate speeds up programming */
/* Written almost entirely in C */
/* Customisable timeout with accurate timeconstant */
/* Optional virtual UART. No hardware UART required. */
/* Optional virtual boot partition for devices without. */
/* */
/* What you lose: */
/* Implements a skeleton STK500 protocol which is */
/* missing several features including EEPROM */
/* programming and non-page-aligned writes */
/* High baud rate breaks compatibility with standard */
/* Arduino flash settings */
/* */
/* Fully supported: */
/* ATmega168 based devices (Diecimila etc) */
/* ATmega328P based devices (Duemilanove etc) */
/* */
/* Beta test (believed working.) */
/* ATmega8 based devices (Arduino legacy) */
/* ATmega328 non-picopower devices */
/* ATmega644P based devices (Sanguino) */
/* ATmega1284P based devices */
/* */
/* Alpha test */
/* ATmega1280 based devices (Arduino Mega) */
/* */
/* Work in progress: */
/* ATtiny84 based devices (Luminet) */
/* */
/* Does not support: */
/* USB based devices (eg. Teensy) */
/* */
/* Assumptions: */
/* The code makes several assumptions that reduce the */
/* code size. They are all true after a hardware reset, */
/* but may not be true if the bootloader is called by */
/* other means or on other hardware. */
/* No interrupts can occur */
/* UART and Timer 1 are set to their reset state */
/* SP points to RAMEND */
/* */
/* Code builds on code, libraries and optimisations from: */
/* stk500boot.c by Jason P. Kyle */
/* Arduino bootloader http://arduino.cc */
/* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
/* avr-libc project http://nongnu.org/avr-libc */
/* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
/* AVR305 Atmel Application Note */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will */
/* be useful, but WITHOUT ANY WARRANTY; without even the */
/* implied warranty of MERCHANTABILITY or FITNESS FOR A */
/* PARTICULAR PURPOSE. See the GNU General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with this program; if not, write */
/* to the Free Software Foundation, Inc., */
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* Licence can be viewed at */
/* http://www.fsf.org/licenses/gpl.txt */
/* */
/**********************************************************/
/**********************************************************/
/* */
/* Optional defines: */
/* */
/**********************************************************/
/* */
/* BIG_BOOT: */
/* Build a 1k bootloader, not 512 bytes. This turns on */
/* extra functionality. */
/* */
/* BAUD_RATE: */
/* Set bootloader baud rate. */
/* */
/* LUDICROUS_SPEED: */
/* 230400 baud :-) */
/* */
/* SOFT_UART: */
/* Use AVR305 soft-UART instead of hardware UART. */
/* */
/* LED_START_FLASHES: */
/* Number of LED flashes on bootup. */
/* */
/* LED_DATA_FLASH: */
/* Flash LED when transferring data. For boards without */
/* TX or RX LEDs, or for people who like blinky lights. */
/* */
/* SUPPORT_EEPROM: */
/* Support reading and writing from EEPROM. This is not */
/* used by Arduino, so off by default. */
/* */
/* TIMEOUT_MS: */
/* Bootloader timeout period, in milliseconds. */
/* 500,1000,2000,4000,8000 supported. */
/* */
/* UART: */
/* UART number (0..n) for devices with more than */
/* one hardware uart (644P, 1284P, etc) */
/* */
/**********************************************************/
/**********************************************************/
/* Version Numbers! */
/* */
/* Arduino Optiboot now includes this Version number in */
/* the source and object code. */
/* */
/* Version 3 was released as zip from the optiboot */
/* repository and was distributed with Arduino 0022. */
/* Version 4 starts with the arduino repository commit */
/* that brought the arduino repository up-to-date with */
/* the optiboot source tree changes since v3. */
/* */
/**********************************************************/
/**********************************************************/
/* Edit History: */
/* */
/* Nov 2012 */
/* Specific version for 9x voice module */
/* by Mike Blandford */
/* Mar 2012 */
/* 4.5 WestfW: add infrastructure for non-zero UARTS. */
/* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
/* Jan 2012: */
/* 4.5 WestfW: fix NRWW value for m1284. */
/* 4.4 WestfW: use attribute OS_main instead of naked for */
/* main(). This allows optimizations that we */
/* count on, which are prohibited in naked */
/* functions due to PR42240. (keeps us less */
/* than 512 bytes when compiler is gcc4.5 */
/* (code from 4.3.2 remains the same.) */
/* 4.4 WestfW and Maniacbug: Add m1284 support. This */
/* does not change the 328 binary, so the */
/* version number didn't change either. (?) */
/* June 2011: */
/* 4.4 WestfW: remove automatic soft_uart detect (didn't */
/* know what it was doing or why.) Added a */
/* check of the calculated BRG value instead. */
/* Version stays 4.4; existing binaries are */
/* not changed. */
/* 4.4 WestfW: add initialization of address to keep */
/* the compiler happy. Change SC'ed targets. */
/* Return the SW version via READ PARAM */
/* 4.3 WestfW: catch framing errors in getch(), so that */
/* AVRISP works without HW kludges. */
/* http://code.google.com/p/arduino/issues/detail?id=368n*/
/* 4.2 WestfW: reduce code size, fix timeouts, change */
/* verifySpace to use WDT instead of appstart */
/* 4.1 WestfW: put version number in binary. */
/**********************************************************/
#define OPTIBOOT_MAJVER 4
#define OPTIBOOT_MINVER 5
#define MULTI_CALLED 1
#define MAKESTR(a) #a
#define MAKEVER(a, b) MAKESTR(a*256+b)
//asm(" .section .version\n"
// "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
// " .section .text\n");
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
// <avr/boot.h> uses sts instructions, but this version uses out instructions
// This saves cycles and program memory.
#include "boot.h"
// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
#include "pin_defs.h"
#include "stk500.h"
#ifndef LED_START_FLASHES
#define LED_START_FLASHES 0
#endif
#ifdef LUDICROUS_SPEED
#define BAUD_RATE 230400L
#endif
/* set the UART baud rate defaults */
#ifndef BAUD_RATE
#if F_CPU >= 8000000L
#define BAUD_RATE 38400L // Highest rate Avrdude win32 will support
#elsif F_CPU >= 1000000L
#define BAUD_RATE 9600L // 19200 also supported, but with significant error
#elsif F_CPU >= 128000L
#define BAUD_RATE 4800L // Good for 128kHz internal RC
#else
#define BAUD_RATE 1200L // Good even at 32768Hz
#endif
#endif
#ifndef UART
#define UART 0
#endif
#if 0
/* Switch in soft UART for hard baud rates */
/*
* I don't understand what this was supposed to accomplish, where the
* constant "280" came from, or why automatically (and perhaps unexpectedly)
* switching to a soft uart is a good thing, so I'm undoing this in favor
* of a range check using the same calc used to config the BRG...
*/
#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
#ifndef SOFT_UART
#define SOFT_UART
#endif
#endif
#else // 0
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
#error Unachievable baud rate (too slow) BAUD_RATE
#endif // baud rate slow check
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
#error Unachievable baud rate (too fast) BAUD_RATE
#endif // baud rate fastn check
#endif
/* Watchdog settings */
#define WATCHDOG_OFF (0)
#define WATCHDOG_16MS (_BV(WDE))
#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
#ifndef __AVR_ATmega8__
#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
#endif
/* Function Prototypes */
/* The main function is in init9, which removes the interrupt vector table */
/* we don't need. It is also 'naked', which means the compiler does not */
/* generate any entry or exit code itself. */
int main(void) __attribute__ ((OS_main)) __attribute__ ((noreturn)) __attribute__ ((section (".init9")));
void putch(char);
uint8_t getch(void);
static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
void verifySpace();
#if LED_START_FLASHES > 0
static inline void flash_led(uint8_t);
#endif
uint8_t getLen();
//static inline void watchdogReset();
void watchdogConfig(uint8_t x);
#ifdef SOFT_UART
void uartDelay() __attribute__ ((naked));
#endif
static void appStart() ; // __attribute__ ((naked));
/*
* NRWW memory
* Addresses below NRWW (Non-Read-While-Write) can be programmed while
* continuing to run code from flash, slightly speeding up programming
* time. Beware that Atmel data sheets specify this as a WORD address,
* while optiboot will be comparing against a 16-bit byte address. This
* means that on a part with 128kB of memory, the upper part of the lower
* 64k will get NRWW processing as well, even though it doesn't need it.
* That's OK. In fact, you can disable the overlapping processing for
* a part entirely by setting NRWWSTART to zero. This reduces code
* space a bit, at the expense of being slightly slower, overall.
*
* RAMSTART should be self-explanatory. It's bigger on parts with a
* lot of peripheral registers.
*/
#if defined(__AVR_ATmega168__)
#define RAMSTART (0x100)
#define NRWWSTART (0x3800)
#elif defined(__AVR_ATmega328P__)
#define RAMSTART (0x100)
#define NRWWSTART (0x7000)
#elif defined(__AVR_ATmega328__)
#define RAMSTART (0x100)
#define NRWWSTART (0x7000)
#elif defined (__AVR_ATmega644P__)
#define RAMSTART (0x100)
#define NRWWSTART (0xE000)
// correct for a bug in avr-libc
#undef SIGNATURE_2
#define SIGNATURE_2 0x0A
#elif defined (__AVR_ATmega1284P__)
#define RAMSTART (0x100)
#define NRWWSTART (0xE000)
#elif defined(__AVR_ATtiny84__)
#define RAMSTART (0x100)
#define NRWWSTART (0x0000)
#elif defined(__AVR_ATmega1280__)
#define RAMSTART (0x200)
#define NRWWSTART (0xE000)
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
#define RAMSTART (0x100)
#define NRWWSTART (0x1800)
#endif
/* C zero initialises all global variables. However, that requires */
/* These definitions are NOT zero initialised, but that doesn't matter */
/* This allows us to drop the zero init code, saving us memory */
#define buff ((uint8_t*)(RAMSTART))
#ifdef VIRTUAL_BOOT_PARTITION
#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
#endif
/*
* Handle devices with up to 4 uarts (eg m1280.) Rather inelegantly.
* Note that mega8 still needs special handling, because ubrr is handled
* differently.
*/
#if UART == 0
# define UART_SRA UCSR0A
# define UART_SRB UCSR0B
# define UART_SRC UCSR0C
# define UART_SRL UBRR0L
# define UART_UDR UDR0
#elif UART == 1
# define UART_SRA UCSR1A
# define UART_SRB UCSR1B
# define UART_SRC UCSR1C
# define UART_SRL UBRR1L
# define UART_UDR UDR1
#elif UART == 2
# define UART_SRA UCSR2A
# define UART_SRB UCSR2B
# define UART_SRC UCSR2C
# define UART_SRL UBRR2L
# define UART_UDR UDR2
#elif UART == 3
# define UART_SRA UCSR3A
# define UART_SRB UCSR3B
# define UART_SRC UCSR3C
# define UART_SRL UBRR3L
# define UART_UDR UDR3
#endif
/* main program starts here */
int main(void) {
uint8_t ch;
/*
* Making these local and in registers prevents the need for initializing
* them, and also saves space because code no longer stores to memory.
* (initializing address keeps the compiler happy, but isn't really
* necessary, and uses 4 bytes of flash.)
*/
register uint16_t address = 0;
// After the zero init loop, this is the first code to run.
//
// This code makes the following assumptions:
// No interrupts will execute
// SP points to RAMEND
// r1 contains zero
//
// If not, uncomment the following instructions:
// cli();
asm volatile ("clr __zero_reg__");
#ifdef __AVR_ATmega8__
SP=RAMEND; // This is done by hardware reset
#endif
// Adaboot no-wait mod
ch = MCUSR;
MCUSR = 0;
// Here, if power on, wait 0.5 secs, then check for
// serial Rx signal low, if so, stay in bootloader
// else go to application
PORTD = 0xFF ;
PORTB = 0x3C ;
PORTC = 1 ;
if (ch & (_BV(PORF) | (_BV(EXTRF)) ) )
{
#ifdef MULTI_CALLED
#if F_CPU == 12000000L
TCNT1H = 256 - 8 ;
#else
#if F_CPU == 16000000L
TCNT1H = 256 - 6 ;
#else
TCNT1H = 256 - 127 ;
#endif
TCNT1L = 0 ;
#endif
#else
#if F_CPU == 12000000L
TCNT1 = 65535-5859 ;
#else
#if F_CPU == 16000000L
TCNT1 = 65535-7813 ;
#else
TCNT1 = 65535-32767 ;
#endif
#endif
#endif
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
TIFR1 = _BV(TOV1);
while(!(TIFR1 & _BV(TOV1)))
;
TCCR1B = 0 ; // Stop timer
uint8_t x ;
x = PINB & 0x3C ;
x |= PINC & 1 ;
if ( x != 0x1D )
{
appStart() ; // Power on, go to voice application
// if loaded
}
}
#if LED_START_FLASHES > 0
// Set up Timer 1 for timeout counter
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
#endif
#ifndef SOFT_UART
UART_SRA = _BV(U2X0); //Double speed mode USART0
UART_SRB = _BV(RXEN0) | _BV(TXEN0);
UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
// UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
// Baudrate of 57600
#if F_CPU == 12000000L
UART_SRL = 25 ;
#else
#if F_CPU == 16000000L
UART_SRL = 33 ;
#else
#ERROR Baud rate not available
#endif
#endif
#endif
// Set up watchdog to trigger after 500ms
// watchdogConfig(WATCHDOG_1S);
/* Set LED pin as output */
LED_DDR |= _BV(LED);
#ifdef SOFT_UART
/* Set TX pin as output */
UART_DDR |= _BV(UART_TX_BIT);
#endif
#if LED_START_FLASHES > 0
/* Flash onboard LED to signal entering of bootloader */
flash_led(LED_START_FLASHES * 2);
#endif
/* Forever loop */
for (;;)
{
/* get character from UART */
ch = getch();
if(ch == STK_GET_PARAMETER)
{
GPIOR0 = getch();
verifySpace();
if (GPIOR0 == 0x82)
{
/*
* Send optiboot version as "minor SW version"
*/
putch(OPTIBOOT_MINVER);
}
else if (GPIOR0 == 0x81)
{
putch(OPTIBOOT_MAJVER);
}
else
{
/*
* GET PARAMETER returns a generic 0x03 reply for
* other parameters - enough to keep Avrdude happy
*/
putch(0x03);
}
}
else if(ch == STK_SET_DEVICE) {
// SET DEVICE is ignored
getNch(20);
}
else if(ch == STK_SET_DEVICE_EXT)
{
// SET DEVICE EXT is ignored
getNch(5);
}
else if(ch == STK_LOAD_ADDRESS)
{
// LOAD ADDRESS
uint16_t newAddress;
newAddress = getch() ;
newAddress = (newAddress & 0xff) | (getch() << 8);
#ifdef RAMPZ
// Transfer top bit to RAMPZ
RAMPZ = (newAddress & 0x8000) ? 1 : 0;
#endif
newAddress += newAddress; // Convert from word address to byte address
address = newAddress;
verifySpace();
}
else if(ch == STK_UNIVERSAL)
{
// UNIVERSAL command is ignored
getNch(4);
putch(0x00);
}
/* Write memory, length is big endian and is in bytes */
else if(ch == STK_PROG_PAGE)
{
// PROGRAM PAGE - we support flash programming only, not EEPROM
uint8_t *bufPtr;
uint16_t addrPtr;
register uint8_t length;
getch(); /* getlen() */
length = getch();
getch();
// If we are in RWW section, immediately start page erase
if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
// While that is going on, read in page contents
bufPtr = buff;
do *bufPtr++ = getch();
while (--length);
// If we are in NRWW section, page erase has to be delayed until now.
// Todo: Take RAMPZ into account
#ifdef MULTI_CALLED
if (address < 0x7E00)
#endif
{
if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
}
// Read command terminator, start reply
verifySpace();
// If only a partial page is to be programmed, the erase might not be complete.
// So check that here
#ifdef MULTI_CALLED
if (address < 0x7E00)
#endif
{
boot_spm_busy_wait();
#ifdef VIRTUAL_BOOT_PARTITION
if ((uint16_t)(void*)address == 0) {
// This is the reset vector page. We need to live-patch the code so the
// bootloader runs.
//
// Move RESET vector to WDT vector
uint16_t vect = buff[0] | (buff[1]<<8);
rstVect = vect;
wdtVect = buff[8] | (buff[9]<<8);
vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
buff[8] = vect & 0xff;
buff[9] = vect >> 8;
// Add jump to bootloader at RESET vector
buff[0] = 0x7f;
buff[1] = 0xce; // rjmp 0x1d00 instruction
}
#endif
// Copy buffer into programming buffer
bufPtr = buff;
addrPtr = (uint16_t)(void*)address;
ch = SPM_PAGESIZE / 2;
do {
uint16_t a;
// a = *bufPtr++;
// a |= (*bufPtr++) << 8;
a = *((uint16_t *)bufPtr) ;
bufPtr += 2 ;
__boot_page_fill_short((uint16_t)(void*)addrPtr,a);
addrPtr += 2;
} while (--ch);
// Write from programming buffer
__boot_page_write_short((uint16_t)(void*)address);
boot_spm_busy_wait();
#if defined(RWWSRE)
// Reenable read access to flash
boot_rww_enable();
#endif
}
}
/* Read memory block mode, length is big endian. */
else if(ch == STK_READ_PAGE)
{
register uint8_t length;
// READ PAGE - we only read flash
getch(); /* getlen() */
length = getch();
getch();
verifySpace();
#ifdef VIRTUAL_BOOT_PARTITION
do {
// Undo vector patch in bottom page so verify passes
if (address == 0) ch=rstVect & 0xff;
else if (address == 1) ch=rstVect >> 8;
else if (address == 8) ch=wdtVect & 0xff;
else if (address == 9) ch=wdtVect >> 8;
else ch = pgm_read_byte_near(address);
address++;
putch(ch);
} while (--length);
#else
#ifdef RAMPZ
// Since RAMPZ should already be set, we need to use EPLM directly.
// do putch(pgm_read_byte_near(address++));
// while (--length);
do {
uint8_t result;
__asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
putch(result);
address++;
}
while (--length);
#else
do putch(pgm_read_byte_near(address++));
while (--length);
#endif
#endif
}
/* Get device signature bytes */
else if(ch == STK_READ_SIGN)
{
// READ SIGN - return what Avrdude wants to hear
verifySpace();
putch(SIGNATURE_0);
putch(SIGNATURE_1);
putch(SIGNATURE_2);
}
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
// Adaboot no-wait mod
// watchdogConfig(WATCHDOG_16MS);
verifySpace();
#ifdef MULTI_CALLED
putch(STK_OK);
while (!(UART_SRA & _BV(TXC0)));
appStart() ;
#endif
}
else
{
// This covers the response to commands like STK_ENTER_PROGMODE
verifySpace();
}
putch(STK_OK);
}
}
void putch(char ch) {
#ifndef SOFT_UART
while (!(UART_SRA & _BV(UDRE0)));
UART_UDR = ch;
#else
__asm__ __volatile__ (
" com %[ch]\n" // ones complement, carry set
" sec\n"
"1: brcc 2f\n"
" cbi %[uartPort],%[uartBit]\n"
" rjmp 3f\n"
"2: sbi %[uartPort],%[uartBit]\n"
" nop\n"
"3: rcall uartDelay\n"
" rcall uartDelay\n"
" lsr %[ch]\n"
" dec %[bitcnt]\n"
" brne 1b\n"
:
:
[bitcnt] "d" (10),
[ch] "r" (ch),
[uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
[uartBit] "I" (UART_TX_BIT)
:
"r25"
);
#endif
}
uint8_t getch(void) {
uint8_t ch;
#ifdef LED_DATA_FLASH
#ifdef __AVR_ATmega8__
LED_PORT ^= _BV(LED);
#else
LED_PIN |= _BV(LED);
#endif
#endif
#ifdef SOFT_UART
__asm__ __volatile__ (
"1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
" rjmp 1b\n"
" rcall uartDelay\n" // Get to middle of start bit
"2: rcall uartDelay\n" // Wait 1 bit period
" rcall uartDelay\n" // Wait 1 bit period
" clc\n"
" sbic %[uartPin],%[uartBit]\n"
" sec\n"
" dec %[bitCnt]\n"
" breq 3f\n"
" ror %[ch]\n"
" rjmp 2b\n"
"3:\n"
:
[ch] "=r" (ch)
:
[bitCnt] "d" (9),
[uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
[uartBit] "I" (UART_RX_BIT)
:
"r25"
);
#else
while(!(UART_SRA & _BV(RXC0)))
// watchdogReset()
;
// if (!(UART_SRA & _BV(FE0))) {
/*
* A Framing Error indicates (probably) that something is talking
* to us at the wrong bit rate. Assume that this is because it
* expects to be talking to the application, and DON'T reset the
* watchdog. This should cause the bootloader to abort and run
* the application "soon", if it keeps happening. (Note that we
* don't care that an invalid char is returned...)
*/
// watchdogReset();
// }
ch = UART_UDR;
#endif
#ifdef LED_DATA_FLASH
#ifdef __AVR_ATmega8__
LED_PORT ^= _BV(LED);
#else
LED_PIN |= _BV(LED);
#endif
#endif
return ch;
}
#ifdef SOFT_UART
// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
#if UART_B_VALUE > 255
#error Baud rate too slow for soft UART
#endif
void uartDelay() {
__asm__ __volatile__ (
"ldi r25,%[count]\n"
"1:dec r25\n"
"brne 1b\n"
"ret\n"
::[count] "M" (UART_B_VALUE)
);
}
#endif
void getNch(uint8_t count) {
do getch(); while (--count);
verifySpace();
}
void verifySpace()
{
if ( getch() != CRC_EOP) {
putch(STK_NOSYNC);
// watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
//
// while (1) // and busy-loop so that WD causes
// ; // a reset and app start.
}
putch(STK_INSYNC);
}
#if LED_START_FLASHES > 0
void flash_led(uint8_t count) {
do {
TCNT1 = -(F_CPU/(1024*16));
TIFR1 = _BV(TOV1);
while(!(TIFR1 & _BV(TOV1)));
//#ifdef __AVR_ATmega8__
LED_PORT ^= _BV(LED);
//#else
// LED_PIN |= _BV(LED);
//#endif
watchdogReset();
} while (--count);
}
#endif
// Watchdog functions. These are only safe with interrupts turned off.
void watchdogReset() {
__asm__ __volatile__ (
"wdr\n"
);
}
void watchdogConfig(uint8_t x) {
WDTCSR = _BV(WDCE) | _BV(WDE);
WDTCSR = x;
}
void appStart()
{
// watchdogConfig(WATCHDOG_OFF);
// __asm__ __volatile__ (
//#ifdef VIRTUAL_BOOT_PARTITION
// // Jump to WDT vector
// "ldi r30,4\n"
// "clr r31\n"
//#else
// // Jump to RST vector
// "clr r30\n"
// "clr r31\n"
//#endif
// "ijmp\n"
// );
register void (*p)() ;
p = 0 ;
if ( pgm_read_byte( (uint16_t)p ) != 0xFF )
{
(*p)() ;
}
}

View File

@ -0,0 +1,80 @@
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB5
/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT PORTD
#define UART_PIN PIND
#define UART_DDR DDRD
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif
#if defined(__AVR_ATmega8__)
//Name conversion R.Wiersma
#define UCSR0A UCSRA
#define UDR0 UDR
#define UDRE0 UDRE
#define RXC0 RXC
#define FE0 FE
#define TIFR1 TIFR
#define WDTCSR WDTCR
#endif
/* Luminet support */
#if defined(__AVR_ATtiny84__)
/* Red LED is connected to pin PA4 */
#define LED_DDR DDRA
#define LED_PORT PORTA
#define LED_PIN PINA
#define LED PINA4
/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
#ifdef SOFT_UART
#define UART_PORT PORTA
#define UART_PIN PINA
#define UART_DDR DDRA
#define UART_TX_BIT 2
#define UART_RX_BIT 3
#endif
#endif
/* Sanguino support */
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
/* Onboard LED is connected to pin PB0 on Sanguino */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB0
/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT PORTD
#define UART_PIN PIND
#define UART_DDR DDRD
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif
/* Mega support */
#if defined(__AVR_ATmega1280__)
/* Onboard LED is connected to pin PB7 on Arduino Mega */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB7
/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT PORTE
#define UART_PIN PINE
#define UART_DDR DDRE
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif

View File

@ -0,0 +1,39 @@
/* STK500 constants list, from AVRDUDE */
#define STK_OK 0x10
#define STK_FAILED 0x11 // Not used
#define STK_UNKNOWN 0x12 // Not used
#define STK_NODEVICE 0x13 // Not used
#define STK_INSYNC 0x14 // ' '
#define STK_NOSYNC 0x15 // Not used
#define ADC_CHANNEL_ERROR 0x16 // Not used
#define ADC_MEASURE_OK 0x17 // Not used
#define PWM_CHANNEL_ERROR 0x18 // Not used
#define PWM_ADJUST_OK 0x19 // Not used
#define CRC_EOP 0x20 // 'SPACE'
#define STK_GET_SYNC 0x30 // '0'
#define STK_GET_SIGN_ON 0x31 // '1'
#define STK_SET_PARAMETER 0x40 // '@'
#define STK_GET_PARAMETER 0x41 // 'A'
#define STK_SET_DEVICE 0x42 // 'B'
#define STK_SET_DEVICE_EXT 0x45 // 'E'
#define STK_ENTER_PROGMODE 0x50 // 'P'
#define STK_LEAVE_PROGMODE 0x51 // 'Q'
#define STK_CHIP_ERASE 0x52 // 'R'
#define STK_CHECK_AUTOINC 0x53 // 'S'
#define STK_LOAD_ADDRESS 0x55 // 'U'
#define STK_UNIVERSAL 0x56 // 'V'
#define STK_PROG_FLASH 0x60 // '`'
#define STK_PROG_DATA 0x61 // 'a'
#define STK_PROG_FUSE 0x62 // 'b'
#define STK_PROG_LOCK 0x63 // 'c'
#define STK_PROG_PAGE 0x64 // 'd'
#define STK_PROG_FUSE_EXT 0x65 // 'e'
#define STK_READ_FLASH 0x70 // 'p'
#define STK_READ_DATA 0x71 // 'q'
#define STK_READ_FUSE 0x72 // 'r'
#define STK_READ_LOCK 0x73 // 's'
#define STK_READ_PAGE 0x74 // 't'
#define STK_READ_SIGN 0x75 // 'u'
#define STK_READ_OSCCAL 0x76 // 'v'
#define STK_READ_FUSE_EXT 0x77 // 'w'
#define STK_READ_OSCCAL_EXT 0x78 // 'x'

View File

@ -0,0 +1,45 @@
# See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
# See: http://code.google.com/p/arduino/wiki/Platforms
##############################################################
menu.bootloader=Bootloader
##############################################################
## Multi 4-in-1 (3.3V, 16 MHz) w/ ATmega328p
## --------------------------------------------------
multiatmega328p.name=Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)
multiatmega328p.upload.tool=arduino:avrdude
multiatmega328p.upload.protocol=arduino
multiatmega328p.upload.speed=57600
multiatmega328p.upload.maximum_data_size=2048
multiatmega328p.build.mcu=atmega328p
multiatmega328p.build.f_cpu=16000000L
multiatmega328p.build.core=arduino:arduino
multiatmega328p.build.variant=arduino:eightanaloginputs
multiatmega328p.build.extra_flags=-Wl,--relax
multiatmega328p.build.board=MULTI_AVR
multiatmega328p.bootloader.tool=arduino:avrdude
multiatmega328p.bootloader.low_fuses=0xFF
multiatmega328p.bootloader.extended_fuses=0xFD
multiatmega328p.bootloader.unlock_bits=0x3F
multiatmega328p.bootloader.lock_bits=0x0F
multiatmega328p.menu.bootloader.none=No bootloader
multiatmega328p.menu.bootloader.none.build.board=MULTI_NO_BOOT
multiatmega328p.menu.bootloader.none.upload.maximum_size=32768
multiatmega328p.menu.bootloader.none.bootloader.file=Multi4in1/AtmegaMultiEmpty.hex
multiatmega328p.menu.bootloader.none.bootloader.high_fuses=0xD7
multiatmega328p.menu.bootloader.optiboot=Flash from TX
multiatmega328p.menu.bootloader.optiboot.build.board=MULTI_FLASH_FROM_TX
multiatmega328p.menu.bootloader.optiboot.upload.maximum_size=32256
multiatmega328p.menu.bootloader.optiboot.bootloader.file=Multi4in1/AtmegaMultiBoot.hex
multiatmega328p.menu.bootloader.optiboot.bootloader.high_fuses=0xD6
##############################################################

View File

@ -0,0 +1,34 @@
:107E0000112484B714BE9FEF9BB99CE395B991E010
:107E100098B98370A9F08AEF80938500109284004E
:107E200085E08093810096BBB09BFECF10928100CD
:107E300093B186B181709C73892B8D3109F0B3D0D9
:107E400082E08093C00088E18093C10086E0809347
:107E5000C20081E28093C400259AC0E0D0E093E0A4
:107E6000F92EEE24E39425E0D22E31E1C32EA9D0E1
:107E7000813481F4A6D08EBBABD08EB3823811F49E
:107E800085E006C08EB3813811F484E001C083E040
:107E900091D086C0823411F484E103C0853419F492
:107EA00085E09DD07DC0853541F48BD0C82F89D029
:107EB000D0E0D82BCC0FDD1F72C0863521F484E0D2
:107EC0008ED080E0E5CF843609F03DC07AD079D0FD
:107ED000B82E77D0C11520E7D20718F000E011E0E6
:107EE00004C0FE01F7BEE895F9CF6BD0F80181938D
:107EF0008F01BE12FACFCE01905781159E4018F423
:107F0000FE01F7BEE89564D0C115FEE7DF0708F073
:107F100047C007B600FCFDCFFE01A0E0B1E08D91A7
:107F20009D910C01E7BEE89511243296A03821E01E
:107F3000B207A9F7FE01D7BEE89507B600FCFDCF52
:107F4000C7BEE8952DC08437B1F43BD03AD0B82EE7
:107F500038D03ED0FE01AC2EAB0C8F010F5F1F4F0F
:107F6000849128D0A01205C02196BA94CB0DD11DC2
:107F700017C0F801F2CF853739F42AD08EE11AD034
:107F800085E918D08FE084CF813549F421D080E194
:107F900011D08091C00086FFFCCF05D001C018D061
:107FA00080E108D064CFE0E0F0E084918F3F09F0F9
:107FB000099408959091C00095FFFCCF8093C6006E
:107FC00008958091C00087FFFCCF8091C60008957E
:107FD000F8DF803211F085E1EDDF84E1EBCFCF9364
:107FE000C82FEFDFC150E9F7CF91F2CFA8950895E0
:0C7FF000E0E6F0E098E1908380830895C3
:0400000300007E007B
:00000001FF

View File

@ -0,0 +1,2 @@
:02000000FFFF00
:00000001FF

View File

@ -0,0 +1 @@
# Empty

View File

@ -0,0 +1,9 @@
# Arduino AVR Core and platform.
# ------------------------------
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=Multi 4-in-1 Boards
version=1.0.0

View File

@ -0,0 +1,47 @@
:108000001F92CDB7DEB7CFD01124809178009FEFBB
:1080100090937800837099F088EA91E680936808DD
:108020009093690880E180934C0880914C0884FF0C
:10803000FCCF109240088091680682FD8FD082E0CC
:1080400080936106C12CD12C97D0813479F494D0DF
:10805000898399D08981823811F485E005C08138FF
:1080600011F484E001C083E080D075C0823411F443
:1080700084E103C0853419F485E08CD06CC085356B
:1080800059F47AD0C82E78D0D12CD82A8D2D881FBB
:108090008827881F8BBF5EC0863521F484E07AD0A4
:1080A00080E0E2CF843641F567D066D0F82E64D008
:1080B000C601DCD000E010E25FD0F80181938F01AF
:1080C000FE12FACF60D0D7FC46C0CBD0C601DAD0C2
:1080D000760100E010E2F801619171918F01C70112
:1080E000DBD0F2E0EF0EF11C011581E2180799F7E1
:1080F000C601E0D0B6D02FC08437C1F43DD03CD00B
:10810000F82E3AD040D0F601EC2CEF0C8F010F5F27
:108110001F4F84912AD0E01207C0EFEFCE1ADE0A7B
:10812000FA94CF0CD11C17C0F801F0CF853739F481
:108130002AD08EE11AD085E918D082E495CF813516
:1081400049F421D080E111D08091A10886FFFCCFB5
:1081500005D001C018D080E108D076CFE0E0F0E093
:1081600084918F3F09F0099408959091A10895FF9B
:10817000FCCF8093A00808958091A10887FFFCCFD1
:108180008091A0080895F8DF803211F085E1EDDFDD
:1081900084E1EBCFCF93C82FEFDFC150E9F7CF9148
:1081A000F2CFA895089583EC8093520080915000FF
:1081B0008860809350008091510083FFFCCF82EC57
:1081C0008093550080915000806180935000809191
:1081D000510084FFFCCF88ED84BF1092400084BF23
:1081E00024E02093400087E08093A20087E88093FA
:1081F0008301109241081092420810924308109295
:10820000440810924608109247088FEF9FEF809322
:1082100066089093670810926008109261088BE0DE
:1082200080934008209365062093620688E180933E
:10823000720698E0909345069093410692E29093DF
:10824000A6081092A7088093A4088091A3088F7CA9
:1082500080618093A30883E08093A5088091A008A3
:1082600008958091CF0187FDFCCF08958F939F9350
:1082700082E2E0ECF1E08287FF91EF918DE984BF2B
:10828000E8950895FC0186E28093CA0188ED84BFD9
:1082900081E08093CB0108950F921F92FC01062E7E
:1082A000172E83E28093CA018DE984BFE8951F9061
:1082B0000F900895FC018EE28093CA018DE984BF7E
:0482C000E8950895A0
:040000030000800079
:00000001FF

View File

@ -0,0 +1,503 @@
# Makefile for ATmegaBOOT
# E.Lins, 18.7.2005
# $Id$
#
# Instructions
#
# To make bootloader .hex file:
# make diecimila
# make lilypad
# make ng
# etc...
#
# To burn bootloader .hex file:
# make diecimila_isp
# make lilypad_isp
# make ng_isp
# etc...
# program name should not be changed...
PROGRAM = optiboot
# The default behavior is to build using tools that are in the users
# current path variables, but we can also build using an installed
# Arduino user IDE setup, or the Arduino source tree.
# Uncomment this next lines to build within the arduino environment,
# using the arduino-included avrgcc toolset (mac and pc)
# ENV ?= arduino
# ENV ?= arduinodev
# OS ?= macosx
# OS ?= windows
# enter the parameters for the avrdude isp tool -b19200
#
# These are the parameters for a usb-based STK500v2 programmer.
# Exact type unknown. (historical Makefile values.)
ISPTOOL = stk500v2
ISPPORT = usb
ISPSPEED = -b 57600
#
#
# These are parameters for using an Arduino with the ArduinoISP sketch
# as the programmer. On a mac, for a particular Uno as programmer.
#ISPTOOL = stk500v1 -C /Applications/arduino/arduino-0022/hardware/tools/avr/etc/avrdude.conf
#ISPPORT = /dev/tty.usbmodemfd3141
#ISPSPEED = -b19200
MCU_TARGET = atmega168
LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
# Build environments
# Start of some ugly makefile-isms to allow optiboot to be built
# in several different environments. See the README.TXT file for
# details.
# default
fixpath = $(1)
ifeq ($(ENV), arduino)
# For Arduino, we assume that we're connected to the optiboot directory
# included with the arduino distribution, which means that the full set
# of avr-tools are "right up there" in standard places.
TOOLROOT = ../../../tools
GCCROOT = $(TOOLROOT)/avr/bin/
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
ifeq ($(OS), windows)
# On windows, SOME of the tool paths will need to have backslashes instead
# of forward slashes (because they use windows cmd.exe for execution instead
# of a unix/mingw shell?) We also have to ensure that a consistent shell
# is used even if a unix shell is installed (ie as part of WINAVR)
fixpath = $(subst /,\,$1)
SHELL = cmd.exe
endif
else ifeq ($(ENV), arduinodev)
# Arduino IDE source code environment. Use the unpacked compilers created
# by the build (you'll need to do "ant build" first.)
ifeq ($(OS), macosx)
TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
endif
ifeq ($(OS), windows)
TOOLROOT = ../../../../build/windows/work/hardware/tools
endif
GCCROOT = $(TOOLROOT)/avr/bin/
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
else
GCCROOT =
AVRDUDE_CONF =
endif
#
# End of build environment code.
# the efuse should really be 0xf8; since, however, only the lower
# three bits of that byte are used on the atmega168, avrdude gets
# confused if you specify 1's for the higher bits, see:
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
#
# similarly, the lock bits should be 0xff instead of 0x3f (to
# unlock the bootloader section) and 0xcf instead of 0x2f (to
# lock it), but since the high two bits of the lock byte are
# unused, avrdude would get confused.
ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
-U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
OBJ = $(PROGRAM).o
OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types
# -mshort-calls
DEFS =
LIBS =
CC = $(GCCROOT)avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib
OBJCOPY = $(GCCROOT)avr-objcopy
OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump)
SIZE = $(GCCROOT)avr-size
#Voice board test
# ATmega328
#
#atmega328: TARGET = atmega328p
#atmega328: MCU_TARGET = atmega328p
#atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
#atmega328: AVR_FREQ = 12000000L
#atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
#atmega328: $(PROGRAM)_atmega328.hex
#atmega328: $(PROGRAM)_atmega328.lst
xmega32D4: TARGET = atxmega32d4
xmega32D4: MCU_TARGET = atxmega32d4
xmega32D4: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
xmega32D4: AVR_FREQ = 32000000L
xmega32D4: LDSECTIONS = -Wl,--section-start=.text=0x8000
xmega32D4: $(PROGRAM)_xmega32d4.hex
xmega32D4: $(PROGRAM)_xmega32d4.lst
atmega328: TARGET = atmega328
atmega328: MCU_TARGET = atmega328p
atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
atmega328: AVR_FREQ = 16000000L
atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328: $(PROGRAM)_atmega328_16.hex
atmega328: $(PROGRAM)_atmega328_16.lst
# Test platforms
# Virtual boot block test
virboot328: TARGET = atmega328
virboot328: MCU_TARGET = atmega328p
virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DVIRTUAL_BOOT'
virboot328: AVR_FREQ = 16000000L
virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
virboot328: $(PROGRAM)_atmega328.hex
virboot328: $(PROGRAM)_atmega328.lst
# 20MHz clocked platforms
#
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
#
pro20: TARGET = pro_20mhz
pro20: MCU_TARGET = atmega168
pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
pro20: AVR_FREQ = 20000000L
pro20: $(PROGRAM)_pro_20mhz.hex
pro20: $(PROGRAM)_pro_20mhz.lst
pro20_isp: pro20
pro20_isp: TARGET = pro_20mhz
# 2.7V brownout
pro20_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro20_isp: LFUSE = C6
# 512 byte boot
pro20_isp: EFUSE = 04
pro20_isp: isp
# 16MHz clocked platforms
#
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
#
pro16: TARGET = pro_16MHz
pro16: MCU_TARGET = atmega168
pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
pro16: AVR_FREQ = 16000000L
pro16: $(PROGRAM)_pro_16MHz.hex
pro16: $(PROGRAM)_pro_16MHz.lst
pro16_isp: pro16
pro16_isp: TARGET = pro_16MHz
# 2.7V brownout
pro16_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro16_isp: LFUSE = C6
# 512 byte boot
pro16_isp: EFUSE = 04
pro16_isp: isp
# Diecimila, Duemilanove with m168, and NG use identical bootloaders
# Call it "atmega168" for generality and clarity, keep "diecimila" for
# backward compatibility of makefile
#
atmega168: TARGET = atmega168
atmega168: MCU_TARGET = atmega168
atmega168: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
atmega168: AVR_FREQ = 12000000L
atmega168: $(PROGRAM)_atmega168.hex
atmega168: $(PROGRAM)_atmega168.lst
atmega168_isp: atmega168
atmega168_isp: TARGET = atmega168
# 2.7V brownout
atmega168_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega168_isp: LFUSE = FF
# 512 byte boot
atmega168_isp: EFUSE = 04
atmega168_isp: isp
diecimila: TARGET = diecimila
diecimila: MCU_TARGET = atmega168
diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
diecimila: AVR_FREQ = 16000000L
diecimila: $(PROGRAM)_diecimila.hex
diecimila: $(PROGRAM)_diecimila.lst
diecimila_isp: diecimila
diecimila_isp: TARGET = diecimila
# 2.7V brownout
diecimila_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
diecimila_isp: LFUSE = FF
# 512 byte boot
diecimila_isp: EFUSE = 04
diecimila_isp: isp
atmega328_isp: atmega328
atmega328_isp: TARGET = atmega328
atmega328_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega328_isp: LFUSE = FF
# 2.7V brownout
atmega328_isp: EFUSE = FD
atmega328_isp: isp
atmega1284: TARGET = atmega1284p
atmega1284: MCU_TARGET = atmega1284p
atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
atmega1284: AVR_FREQ = 16000000L
atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
atmega1284: $(PROGRAM)_atmega1284p.hex
atmega1284: $(PROGRAM)_atmega1284p.lst
atmega1284_isp: atmega1284
atmega1284_isp: TARGET = atmega1284p
atmega1284_isp: MCU_TARGET = atmega1284p
# 1024 byte boot
atmega1284_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega1284_isp: LFUSE = FF
# 2.7V brownout
atmega1284_isp: EFUSE = FD
atmega1284_isp: isp
# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
#
sanguino: TARGET = atmega644p
sanguino: MCU_TARGET = atmega644p
sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
sanguino: AVR_FREQ = 16000000L
sanguino: LDSECTIONS = -Wl,--section-start=.text=0xfc00 -Wl,--section-start=.version=0xfffe
sanguino: $(PROGRAM)_atmega644p.hex
sanguino: $(PROGRAM)_atmega644p.lst
sanguino_isp: sanguino
sanguino_isp: TARGET = atmega644p
sanguino_isp: MCU_TARGET = atmega644p
# 1024 byte boot
sanguino_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
sanguino_isp: LFUSE = FF
# 2.7V brownout
sanguino_isp: EFUSE = FD
sanguino_isp: isp
# Mega has a minimum boot size of 1024 bytes, so enable extra functions
#mega: TARGET = atmega1280
mega1280: MCU_TARGET = atmega1280
mega1280: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
mega1280: AVR_FREQ = 16000000L
mega1280: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
mega1280: $(PROGRAM)_atmega1280.hex
mega1280: $(PROGRAM)_atmega1280.lst
mega1280_isp: mega
mega1280_isp: TARGET = atmega1280
mega1280_isp: MCU_TARGET = atmega1280
# 1024 byte boot
mega1280_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
mega1280_isp: LFUSE = FF
# 2.7V brownout
mega1280_isp: EFUSE = FD
mega1280_isp: isp
# ATmega8
#
atmega8: TARGET = atmega8
atmega8: MCU_TARGET = atmega8
atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega8: AVR_FREQ = 16000000L
atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
atmega8: $(PROGRAM)_atmega8.hex
atmega8: $(PROGRAM)_atmega8.lst
atmega8_isp: atmega8
atmega8_isp: TARGET = atmega8
atmega8_isp: MCU_TARGET = atmega8
# SPIEN, CKOPT, Bootsize=512B
atmega8_isp: HFUSE = CC
# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms
atmega8_isp: LFUSE = BF
atmega8_isp: isp
# ATmega88
#
atmega88: TARGET = atmega88
atmega88: MCU_TARGET = atmega88
atmega88: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
atmega88: AVR_FREQ = 12000000L
atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
atmega88: $(PROGRAM)_atmega88.hex
atmega88: $(PROGRAM)_atmega88.lst
atmega88_isp: atmega88
atmega88_isp: TARGET = atmega88
atmega88_isp: MCU_TARGET = atmega88
# 2.7V brownout
atmega88_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atemga88_isp: LFUSE = FF
# 512 byte boot
atmega88_isp: EFUSE = 04
atmega88_isp: isp
# 8MHz clocked platforms
#
# These are capable of 38400 baud
#
lilypad: TARGET = lilypad
lilypad: MCU_TARGET = atmega168
lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
lilypad: AVR_FREQ = 8000000L
lilypad: $(PROGRAM)_lilypad.hex
lilypad: $(PROGRAM)_lilypad.lst
lilypad_isp: lilypad
lilypad_isp: TARGET = lilypad
# 2.7V brownout
lilypad_isp: HFUSE = DD
# Internal 8MHz osc (8MHz) Slow rising power
lilypad_isp: LFUSE = E2
# 512 byte boot
lilypad_isp: EFUSE = 04
lilypad_isp: isp
lilypad_resonator: TARGET = lilypad_resonator
lilypad_resonator: MCU_TARGET = atmega168
lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
lilypad_resonator: AVR_FREQ = 8000000L
lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
lilypad_resonator_isp: lilypad_resonator
lilypad_resonator_isp: TARGET = lilypad_resonator
# 2.7V brownout
lilypad_resonator_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
lilypad_resonator_isp: LFUSE = C6
# 512 byte boot
lilypad_resonator_isp: EFUSE = 04
lilypad_resonator_isp: isp
pro8: TARGET = pro_8MHz
pro8: MCU_TARGET = atmega168
pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
pro8: AVR_FREQ = 8000000L
pro8: $(PROGRAM)_pro_8MHz.hex
pro8: $(PROGRAM)_pro_8MHz.lst
pro8_isp: pro8
pro8_isp: TARGET = pro_8MHz
# 2.7V brownout
pro8_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro8_isp: LFUSE = C6
# 512 byte boot
pro8_isp: EFUSE = 04
pro8_isp: isp
atmega328_pro8: TARGET = atmega328_pro_8MHz
atmega328_pro8: MCU_TARGET = atmega328p
atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega328_pro8: AVR_FREQ = 8000000L
atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
atmega328_pro8_isp: atmega328_pro8
atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
atmega328_pro8_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_pro8_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega328_pro8_isp: LFUSE = FF
# 2.7V brownout
atmega328_pro8_isp: EFUSE = DE
atmega328_pro8_isp: isp
# 1MHz clocked platforms
#
# These are capable of 9600 baud
#
luminet: TARGET = luminet
luminet: MCU_TARGET = attiny84
luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600'
luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
luminet: AVR_FREQ = 1000000L
luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
luminet: $(PROGRAM)_luminet.hex
luminet: $(PROGRAM)_luminet.lst
luminet_isp: luminet
luminet_isp: TARGET = luminet
luminet_isp: MCU_TARGET = attiny84
# Brownout disabled
luminet_isp: HFUSE = DF
# 1MHz internal oscillator, slowly rising power
luminet_isp: LFUSE = 62
# Self-programming enable
luminet_isp: EFUSE = FE
luminet_isp: isp
#
# Generic build instructions
#
#
isp: $(TARGET)
$(ISPFUSES)
$(ISPFLASH)
isp-stk500: $(PROGRAM)_$(TARGET).hex
$(STK500-1)
$(STK500-2)
%.elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
$(SIZE) $@
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@

View File

@ -0,0 +1,980 @@
/**********************************************************/
/* Optiboot bootloader for Xmega */
/* */
/* http://optiboot.googlecode.com */
/* */
/* Arduino-maintained version : See README.TXT */
/* http://code.google.com/p/arduino/ */
/* It is the intent that changes not relevant to the */
/* Arduino production envionment get moved from the */
/* optiboot project to the arduino project in "lumps." */
/* */
/* Heavily optimised bootloader that is faster and */
/* smaller than the Arduino standard bootloader */
/* */
/* Enhancements: */
/* Fits in 512 bytes, saving 1.5K of code space */
/* Background page erasing speeds up programming */
/* Higher baud rate speeds up programming */
/* Written almost entirely in C */
/* Customisable timeout with accurate timeconstant */
/* Optional virtual UART. No hardware UART required. */
/* Optional virtual boot partition for devices without. */
/* */
/* What you lose: */
/* Implements a skeleton STK500 protocol which is */
/* missing several features including EEPROM */
/* programming and non-page-aligned writes */
/* High baud rate breaks compatibility with standard */
/* Arduino flash settings */
/* */
/* Fully supported: */
/* ATmega168 based devices (Diecimila etc) */
/* ATmega328P based devices (Duemilanove etc) */
/* */
/* Beta test (believed working.) */
/* ATmega8 based devices (Arduino legacy) */
/* ATmega328 non-picopower devices */
/* ATmega644P based devices (Sanguino) */
/* ATmega1284P based devices */
/* */
/* Alpha test */
/* ATmega1280 based devices (Arduino Mega) */
/* */
/* Work in progress: */
/* ATtiny84 based devices (Luminet) */
/* */
/* Does not support: */
/* USB based devices (eg. Teensy) */
/* */
/* Assumptions: */
/* The code makes several assumptions that reduce the */
/* code size. They are all true after a hardware reset, */
/* but may not be true if the bootloader is called by */
/* other means or on other hardware. */
/* No interrupts can occur */
/* UART and Timer 1 are set to their reset state */
/* SP points to RAMEND */
/* */
/* Code builds on code, libraries and optimisations from: */
/* stk500boot.c by Jason P. Kyle */
/* Arduino bootloader http://arduino.cc */
/* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
/* avr-libc project http://nongnu.org/avr-libc */
/* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
/* AVR305 Atmel Application Note */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will */
/* be useful, but WITHOUT ANY WARRANTY; without even the */
/* implied warranty of MERCHANTABILITY or FITNESS FOR A */
/* PARTICULAR PURPOSE. See the GNU General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with this program; if not, write */
/* to the Free Software Foundation, Inc., */
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* Licence can be viewed at */
/* http://www.fsf.org/licenses/gpl.txt */
/* */
/**********************************************************/
/**********************************************************/
/* */
/* Optional defines: */
/* */
/**********************************************************/
/* */
/* BIG_BOOT: */
/* Build a 1k bootloader, not 512 bytes. This turns on */
/* extra functionality. */
/* */
/* BAUD_RATE: */
/* Set bootloader baud rate. */
/* */
/* LUDICROUS_SPEED: */
/* 230400 baud :-) */
/* */
/* SOFT_UART: */
/* Use AVR305 soft-UART instead of hardware UART. */
/* */
/* LED_START_FLASHES: */
/* Number of LED flashes on bootup. */
/* */
/* LED_DATA_FLASH: */
/* Flash LED when transferring data. For boards without */
/* TX or RX LEDs, or for people who like blinky lights. */
/* */
/* SUPPORT_EEPROM: */
/* Support reading and writing from EEPROM. This is not */
/* used by Arduino, so off by default. */
/* */
/* TIMEOUT_MS: */
/* Bootloader timeout period, in milliseconds. */
/* 500,1000,2000,4000,8000 supported. */
/* */
/* UART: */
/* UART number (0..n) for devices with more than */
/* one hardware uart (644P, 1284P, etc) */
/* */
/**********************************************************/
/**********************************************************/
/* Version Numbers! */
/* */
/* Arduino Optiboot now includes this Version number in */
/* the source and object code. */
/* */
/* Version 3 was released as zip from the optiboot */
/* repository and was distributed with Arduino 0022. */
/* Version 4 starts with the arduino repository commit */
/* that brought the arduino repository up-to-date with */
/* the optiboot source tree changes since v3. */
/* */
/**********************************************************/
/**********************************************************/
/* Edit History: */
/* */
/* Nov 2012 */
/* Specific version for 9x voice module */
/* by Mike Blandford */
/* Mar 2012 */
/* 4.5 WestfW: add infrastructure for non-zero UARTS. */
/* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
/* Jan 2012: */
/* 4.5 WestfW: fix NRWW value for m1284. */
/* 4.4 WestfW: use attribute OS_main instead of naked for */
/* main(). This allows optimizations that we */
/* count on, which are prohibited in naked */
/* functions due to PR42240. (keeps us less */
/* than 512 bytes when compiler is gcc4.5 */
/* (code from 4.3.2 remains the same.) */
/* 4.4 WestfW and Maniacbug: Add m1284 support. This */
/* does not change the 328 binary, so the */
/* version number didn't change either. (?) */
/* June 2011: */
/* 4.4 WestfW: remove automatic soft_uart detect (didn't */
/* know what it was doing or why.) Added a */
/* check of the calculated BRG value instead. */
/* Version stays 4.4; existing binaries are */
/* not changed. */
/* 4.4 WestfW: add initialization of address to keep */
/* the compiler happy. Change SC'ed targets. */
/* Return the SW version via READ PARAM */
/* 4.3 WestfW: catch framing errors in getch(), so that */
/* AVRISP works without HW kludges. */
/* http://code.google.com/p/arduino/issues/detail?id=368n*/
/* 4.2 WestfW: reduce code size, fix timeouts, change */
/* verifySpace to use WDT instead of appstart */
/* 4.1 WestfW: put version number in binary. */
/**********************************************************/
#define OPTIBOOT_MAJVER 4
#define OPTIBOOT_MINVER 5
#define MULTI_CALLED 1
#define MAKESTR(a) #a
#define MAKEVER(a, b) MAKESTR(a*256+b)
// Page Size is 128 words (256 bytes)
//asm(" .section .version\n"
// "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
// " .section .text\n");
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
// <avr/boot.h> uses sts instructions, but this version uses out instructions
// This saves cycles and program memory.
//#include "boot.h"
// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
#include "pin_defs.h"
#include "stk500.h"
#define BIND_pin 2 //PD2
#define BIND_port PORTD
#define IS_BIND_BUTTON_on ( (BIND_port.IN & _BV(BIND_pin)) == 0x00 )
#ifndef LED_START_FLASHES
#define LED_START_FLASHES 0
#endif
#ifdef LUDICROUS_SPEED
#define BAUD_RATE 230400L
#endif
/* set the UART baud rate defaults */
#ifndef BAUD_RATE
#if F_CPU >= 8000000L
#define BAUD_RATE 38400L // Highest rate Avrdude win32 will support
#elsif F_CPU >= 1000000L
#define BAUD_RATE 9600L // 19200 also supported, but with significant error
#elsif F_CPU >= 128000L
#define BAUD_RATE 4800L // Good for 128kHz internal RC
#else
#define BAUD_RATE 1200L // Good even at 32768Hz
#endif
#endif
#ifndef UART
#define UART 0
#endif
#if 0
/* Switch in soft UART for hard baud rates */
/*
* I don't understand what this was supposed to accomplish, where the
* constant "280" came from, or why automatically (and perhaps unexpectedly)
* switching to a soft uart is a good thing, so I'm undoing this in favor
* of a range check using the same calc used to config the BRG...
*/
#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
#ifndef SOFT_UART
#define SOFT_UART
#endif
#endif
#else // 0
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
#error Unachievable baud rate (too slow) BAUD_RATE
#endif // baud rate slow check
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
#error Unachievable baud rate (too fast) BAUD_RATE
#endif // baud rate fastn check
#endif
/* Watchdog settings */
#define WATCHDOG_OFF (0)
#define WATCHDOG_16MS (_BV(WDE))
#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
#ifndef __AVR_ATmega8__
#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
#endif
/* Function Prototypes */
/* The main function is in init9, which removes the interrupt vector table */
/* we don't need. It is also 'naked', which means the compiler does not */
/* generate any entry or exit code itself. */
int main(void) __attribute__ ((OS_main)) __attribute__ ((noreturn)) __attribute__ ((section (".init9")));
void putch(char);
uint8_t getch(void);
static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
void verifySpace();
#if LED_START_FLASHES > 0
static inline void flash_led(uint8_t);
#endif
uint8_t getLen();
//static inline void watchdogReset();
void watchdogConfig(uint8_t x);
#ifdef SOFT_UART
void uartDelay() __attribute__ ((naked));
#endif
static void appStart() ; // __attribute__ ((naked));
void boot_spm_busy_wait() ;
void __boot_page_erase_short( uint16_t address ) ;
void __boot_page_fill_short( uint16_t address, uint16_t data) ;
void __boot_page_write_short( uint16_t address) ;
void __boot_erase_flash_buffer( uint16_t address ) ;
void init() ;
/*
* NRWW memory
* Addresses below NRWW (Non-Read-While-Write) can be programmed while
* continuing to run code from flash, slightly speeding up programming
* time. Beware that Atmel data sheets specify this as a WORD address,
* while optiboot will be comparing against a 16-bit byte address. This
* means that on a part with 128kB of memory, the upper part of the lower
* 64k will get NRWW processing as well, even though it doesn't need it.
* That's OK. In fact, you can disable the overlapping processing for
* a part entirely by setting NRWWSTART to zero. This reduces code
* space a bit, at the expense of being slightly slower, overall.
*
* RAMSTART should be self-explanatory. It's bigger on parts with a
* lot of peripheral registers.
*/
#if defined(__AVR_ATmega168__)
#define RAMSTART (0x100)
#define NRWWSTART (0x3800)
#elif defined(__AVR_ATmega328P__)
#define RAMSTART (0x100)
#define NRWWSTART (0x7000)
#elif defined(__AVR_ATmega328__)
#define RAMSTART (0x100)
#define NRWWSTART (0x7000)
#elif defined (__AVR_ATmega644P__)
#define RAMSTART (0x100)
#define NRWWSTART (0xE000)
// correct for a bug in avr-libc
#undef SIGNATURE_2
#define SIGNATURE_2 0x0A
#elif defined (__AVR_ATmega1284P__)
#define RAMSTART (0x100)
#define NRWWSTART (0xE000)
#elif defined(__AVR_ATtiny84__)
#define RAMSTART (0x100)
#define NRWWSTART (0x0000)
#elif defined(__AVR_ATmega1280__)
#define RAMSTART (0x200)
#define NRWWSTART (0xE000)
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
#define RAMSTART (0x100)
#define NRWWSTART (0x1800)
#endif
/* C zero initialises all global variables. However, that requires */
/* These definitions are NOT zero initialised, but that doesn't matter */
/* This allows us to drop the zero init code, saving us memory */
#define buff ((uint8_t*)(RAMSTART))
#ifdef VIRTUAL_BOOT_PARTITION
#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
#endif
/*
* Handle devices with up to 4 uarts (eg m1280.) Rather inelegantly.
* Note that mega8 still needs special handling, because ubrr is handled
* differently.
*/
#if UART == 0
# define UART_SRA UCSR0A
# define UART_SRB UCSR0B
# define UART_SRC UCSR0C
# define UART_SRL UBRR0L
# define UART_UDR UDR0
#elif UART == 1
# define UART_SRA UCSR1A
# define UART_SRB UCSR1B
# define UART_SRC UCSR1C
# define UART_SRL UBRR1L
# define UART_UDR UDR1
#elif UART == 2
# define UART_SRA UCSR2A
# define UART_SRB UCSR2B
# define UART_SRC UCSR2C
# define UART_SRL UBRR2L
# define UART_UDR UDR2
#elif UART == 3
# define UART_SRA UCSR3A
# define UART_SRB UCSR3B
# define UART_SRC UCSR3C
# define UART_SRL UBRR3L
# define UART_UDR UDR3
#endif
/* main program starts here */
int main(void)
{
uint8_t ch;
uint8_t byte ;
/*
* Making these local and in registers prevents the need for initializing
* them, and also saves space because code no longer stores to memory.
* (initializing address keeps the compiler happy, but isn't really
* necessary, and uses 4 bytes of flash.)
*/
register uint16_t address = 0;
init() ;
// After the zero init loop, this is the first code to run.
//
// This code makes the following assumptions:
// No interrupts will execute
// SP points to RAMEND
// r1 contains zero
//
// If not, uncomment the following instructions:
// cli();
asm volatile ("clr __zero_reg__");
ch = RST.STATUS ;
RST.STATUS = 0xFF ; // Clear all flags
// Here, if power on, wait 0.1 secs, then check for
// serial Rx signal low, if so, stay in bootloader
// else go to application
if (ch & (RST_EXTRF_bm | RST_PORF_bm ) )
{
TCC1.CCA = 25000 ;
TCC1.INTFLAGS = TC1_CCAIF_bm ;
while(!(TCC1.INTFLAGS & TC1_CCAIF_bm))
;
TCC1.CTRLA = 0 ; // Stop timer
uint8_t x ;
x = PORTD.IN & 0x04 ;
if ( x != 0 )
{
appStart() ; // Power on, go to app if loaded
}
}
//#ifndef SOFT_UART
// UART_SRA = _BV(U2X0); //Double speed mode USART0
// UART_SRB = _BV(RXEN0) | _BV(TXEN0);
// UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
//// UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
//// Baudrate of 57600
//#if F_CPU == 12000000L
// UART_SRL = 25 ;
//#else
//#if F_CPU == 16000000L
// UART_SRL = 33 ;
//#else
//#ERROR Baud rate not available
//#endif
//#endif
//#endif
// Set up watchdog to trigger after 500ms
// watchdogConfig(WATCHDOG_1S);
/* Set LED pin as output */
#define LED_pin 1 //PD1
#define LED_port PORTD
LED_port.DIRSET = _BV(LED_pin) ;
//#ifdef SOFT_UART
// /* Set TX pin as output */
// UART_DDR |= _BV(UART_TX_BIT);
//#endif
//#if LED_START_FLASHES > 0
// /* Flash onboard LED to signal entering of bootloader */
// flash_led(LED_START_FLASHES * 2);
//#endif
/* Forever loop */
for (;;)
{
/* get character from UART */
ch = getch();
if(ch == STK_GET_PARAMETER)
{
byte = getch();
verifySpace();
if ( byte == 0x82)
{
/*
* Send optiboot version as "minor SW version"
*/
putch(OPTIBOOT_MINVER);
}
else if ( byte == 0x81)
{
putch(OPTIBOOT_MAJVER);
}
else
{
/*
* GET PARAMETER returns a generic 0x03 reply for
* other parameters - enough to keep Avrdude happy
*/
putch(0x03);
}
}
else if(ch == STK_SET_DEVICE) {
// SET DEVICE is ignored
getNch(20);
}
else if(ch == STK_SET_DEVICE_EXT)
{
// SET DEVICE EXT is ignored
getNch(5);
}
else if(ch == STK_LOAD_ADDRESS)
{
// LOAD ADDRESS
uint16_t newAddress;
newAddress = getch() ;
newAddress = (newAddress & 0xff) | (getch() << 8);
#ifdef RAMPZ
// Transfer top bit to RAMPZ
RAMPZ = (newAddress & 0x8000) ? 1 : 0;
#endif
// newAddress += newAddress; // Convert from word address to byte address
address = newAddress;
verifySpace();
}
else if(ch == STK_UNIVERSAL)
{
// UNIVERSAL command is ignored
getNch(4);
putch(0x00);
}
/* Write memory, length is big endian and is in bytes */
else if(ch == STK_PROG_PAGE)
{
// PROGRAM PAGE - we support flash programming only, not EEPROM
uint8_t *bufPtr;
uint16_t addrPtr;
register uint8_t length;
getch(); /* getlen() */
length = getch();
getch();
// If we are in RWW section, immediately start page erase
// if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
__boot_page_erase_short((uint16_t)(void*)address);
// While that is going on, read in page contents
bufPtr = buff;
do *bufPtr++ = getch();
while (--length);
// If we are in NRWW section, page erase has to be delayed until now.
// Todo: Take RAMPZ into account
//#ifdef MULTI_CALLED
// if (address < 0x7E00)
//#endif
// {
// if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
// }
// Read command terminator, start reply
verifySpace();
// If only a partial page is to be programmed, the erase might not be complete.
// So check that here
#ifdef MULTI_CALLED
if (address < 0x8000)
#endif
{
boot_spm_busy_wait();
#ifdef VIRTUAL_BOOT_PARTITION
if ((uint16_t)(void*)address == 0) {
// This is the reset vector page. We need to live-patch the code so the
// bootloader runs.
//
// Move RESET vector to WDT vector
uint16_t vect = buff[0] | (buff[1]<<8);
rstVect = vect;
wdtVect = buff[8] | (buff[9]<<8);
vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
buff[8] = vect & 0xff;
buff[9] = vect >> 8;
// Add jump to bootloader at RESET vector
buff[0] = 0x7f;
buff[1] = 0xce; // rjmp 0x1d00 instruction
}
#endif
// Copy buffer into programming buffer
bufPtr = buff;
addrPtr = (uint16_t)(void*)address;
ch = SPM_PAGESIZE / 2;
__boot_erase_flash_buffer((uint16_t)(void*)addrPtr ) ;
do {
uint16_t a;
// a = *bufPtr++;
// a |= (*bufPtr++) << 8;
a = *((uint16_t *)bufPtr) ;
bufPtr += 2 ;
__boot_page_fill_short((uint16_t)(void*)addrPtr,a);
addrPtr += 2;
} while (--ch);
// Write from programming buffer
__boot_page_write_short((uint16_t)(void*)address);
boot_spm_busy_wait();
#if defined(RWWSRE)
// Reenable read access to flash
boot_rww_enable();
#endif
}
}
/* Read memory block mode, length is big endian. */
else if(ch == STK_READ_PAGE)
{
register uint8_t length;
// READ PAGE - we only read flash
getch(); /* getlen() */
length = getch();
getch();
verifySpace();
//#ifdef VIRTUAL_BOOT_PARTITION
// do {
// // Undo vector patch in bottom page so verify passes
// if (address == 0) ch=rstVect & 0xff;
// else if (address == 1) ch=rstVect >> 8;
// else if (address == 8) ch=wdtVect & 0xff;
// else if (address == 9) ch=wdtVect >> 8;
// else ch = pgm_read_byte_near(address);
// address++;
// putch(ch);
// } while (--length);
//#else
//#ifdef RAMPZ
//// Since RAMPZ should already be set, we need to use EPLM directly.
//// do putch(pgm_read_byte_near(address++));
//// while (--length);
// do {
// uint8_t result;
// __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
// putch(result);
// address++;
// }
// while (--length);
//#else
do putch(pgm_read_byte_near(address++));
while (--length);
//#endif
//#endif
}
/* Get device signature bytes */
else if(ch == STK_READ_SIGN)
{
// READ SIGN - return what Avrdude wants to hear
verifySpace();
putch(SIGNATURE_0);
putch(SIGNATURE_1);
putch(SIGNATURE_2);
}
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
// Adaboot no-wait mod
// watchdogConfig(WATCHDOG_16MS);
verifySpace();
#ifdef MULTI_CALLED
putch(STK_OK);
while(!(USARTC0.STATUS & USART_TXCIF_bm))
;
appStart() ;
#endif
}
else
{
// This covers the response to commands like STK_ENTER_PROGMODE
verifySpace();
}
putch(STK_OK);
}
}
void putch(char ch)
{
//#ifndef SOFT_UART
while(!(USARTC0.STATUS & USART_DREIF_bm))
;
USARTC0.DATA = ch ;
//#else
// __asm__ __volatile__ (
// " com %[ch]\n" // ones complement, carry set
// " sec\n"
// "1: brcc 2f\n"
// " cbi %[uartPort],%[uartBit]\n"
// " rjmp 3f\n"
// "2: sbi %[uartPort],%[uartBit]\n"
// " nop\n"
// "3: rcall uartDelay\n"
// " rcall uartDelay\n"
// " lsr %[ch]\n"
// " dec %[bitcnt]\n"
// " brne 1b\n"
// :
// :
// [bitcnt] "d" (10),
// [ch] "r" (ch),
// [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
// [uartBit] "I" (UART_TX_BIT)
// :
// "r25"
// );
//#endif
}
uint8_t getch(void)
{
uint8_t ch;
//#ifdef LED_DATA_FLASH
//#ifdef __AVR_ATmega8__
// LED_PORT ^= _BV(LED);
//#else
// LED_PIN |= _BV(LED);
//#endif
//#endif
//#ifdef SOFT_UART
// __asm__ __volatile__ (
// "1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
// " rjmp 1b\n"
// " rcall uartDelay\n" // Get to middle of start bit
// "2: rcall uartDelay\n" // Wait 1 bit period
// " rcall uartDelay\n" // Wait 1 bit period
// " clc\n"
// " sbic %[uartPin],%[uartBit]\n"
// " sec\n"
// " dec %[bitCnt]\n"
// " breq 3f\n"
// " ror %[ch]\n"
// " rjmp 2b\n"
// "3:\n"
// :
// [ch] "=r" (ch)
// :
// [bitCnt] "d" (9),
// [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
// [uartBit] "I" (UART_RX_BIT)
// :
// "r25"
//);
//#else
while(!(USARTC0.STATUS & USART_RXCIF_bm))
// watchdogReset()
;
// if (!(UART_SRA & _BV(FE0))) {
/*
* A Framing Error indicates (probably) that something is talking
* to us at the wrong bit rate. Assume that this is because it
* expects to be talking to the application, and DON'T reset the
* watchdog. This should cause the bootloader to abort and run
* the application "soon", if it keeps happening. (Note that we
* don't care that an invalid char is returned...)
*/
// watchdogReset();
// }
ch = USARTC0.DATA ;
//#endif
//#ifdef LED_DATA_FLASH
//#ifdef __AVR_ATmega8__
// LED_PORT ^= _BV(LED);
//#else
// LED_PIN |= _BV(LED);
//#endif
//#endif
return ch;
}
#ifdef SOFT_UART
// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
#if UART_B_VALUE > 255
#error Baud rate too slow for soft UART
#endif
void uartDelay() {
__asm__ __volatile__ (
"ldi r25,%[count]\n"
"1:dec r25\n"
"brne 1b\n"
"ret\n"
::[count] "M" (UART_B_VALUE)
);
}
#endif
void getNch(uint8_t count) {
do getch(); while (--count);
verifySpace();
}
void verifySpace()
{
if ( getch() != CRC_EOP) {
putch(STK_NOSYNC);
// watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
//
// while (1) // and busy-loop so that WD causes
// ; // a reset and app start.
}
putch(STK_INSYNC);
}
#if LED_START_FLASHES > 0
void flash_led(uint8_t count) {
do {
TCNT1 = -(F_CPU/(1024*16));
TIFR1 = _BV(TOV1);
while(!(TIFR1 & _BV(TOV1)));
//#ifdef __AVR_ATmega8__
LED_PORT ^= _BV(LED);
//#else
// LED_PIN |= _BV(LED);
//#endif
watchdogReset();
} while (--count);
}
#endif
// Watchdog functions. These are only safe with interrupts turned off.
void watchdogReset() {
__asm__ __volatile__ (
"wdr\n"
);
}
//void watchdogConfig(uint8_t x) {
// WDTCSR = _BV(WDCE) | _BV(WDE);
// WDTCSR = x;
//}
void init()
{
// Enable external oscillator (16MHz)
OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_256CLK_gc ;
OSC.CTRL |= OSC_XOSCEN_bm ;
while( ( OSC.STATUS & OSC_XOSCRDY_bm ) == 0 )
/* wait */ ;
// Enable PLL (*2 = 32MHz)
OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2 ;
OSC.CTRL |= OSC_PLLEN_bm ;
while( ( OSC.STATUS & OSC_PLLRDY_bm ) == 0 )
/* wait */ ;
// Switch to PLL clock
CPU_CCP = 0xD8 ;
CLK.CTRL = CLK_SCLKSEL_RC2M_gc ;
CPU_CCP = 0xD8 ;
CLK.CTRL = CLK_SCLKSEL_PLL_gc ;
PMIC.CTRL = 7 ; // Enable all interrupt levels
// Timer1 config
// TCC1 16-bit timer, clocked at 0.5uS
EVSYS.CH3MUX = 0x80 + 0x07 ; // Prescaler of 128
TCC1.CTRLB = 0; TCC1.CTRLC = 0; TCC1.CTRLD = 0; TCC1.CTRLE = 0;
TCC1.INTCTRLA = 0 ;
TCC1.INTCTRLB = 0 ;
TCC1.PER = 0xFFFF ;
TCC1.CNT = 0 ;
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
PORTD.OUTSET = 0x04 ;
PORTD.DIRCLR = 0x04 ;
PORTD.PIN2CTRL = 0x18 ; // Pullup
PORTC.OUTSET = 0x08 ;
PORTC.DIRSET = 0x08 ;
USARTC0.BAUDCTRLA = 34 ; // 57600
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ; // Enable Tx and Rx
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) ;
USARTC0.CTRLC = 0x03 ; // 8 bit, no parity, 1 stop
USARTC0.DATA ;
}
void boot_spm_busy_wait()
{
while(NVM.STATUS & NVM_NVMBUSY_bm)
;
}
#define A_NVM_CMD 0x1CA
void __boot_page_erase_short( uint16_t address )
{
asm( "push r24" ) ;
asm( "push r25" ) ;
NVM.CMD = NVM_CMD_ERASE_APP_PAGE_gc ;
asm( "pop r31" ) ;
asm( "pop r30" ) ;
CCP = CCP_SPM_gc ;
asm( "spm" ) ;
}
void __boot_erase_flash_buffer( uint16_t address )
{
asm( "movw r30,r24" ) ;
asm( "ldi r24,0x26" ) ;
asm("sts 0x1CA,r24");
CCP = CCP_IOREG_gc ;
asm( "ldi r24,1" ) ;
asm("sts 0x1CB,r24");
}
void __boot_page_fill_short( uint16_t address, uint16_t data)
{
asm( "push r0" ) ;
asm( "push r1" ) ;
asm( "movw r30,r24" ) ;
asm( "mov r0,r22" ) ;
asm( "mov r1,r23" ) ;
asm( "ldi r24,0x23" ) ;
asm("sts 0x1CA,r24");
CCP = CCP_SPM_gc ;
asm( "spm" ) ;
asm( "pop r1" ) ;
asm( "pop r0" ) ;
}
void __boot_page_write_short( uint16_t address)
{
asm( "movw r30,r24" ) ;
asm( "ldi r24,0x2E" ) ;
asm("sts 0x1CA,r24");
CCP = CCP_SPM_gc ;
asm( "spm" ) ;
}
void appStart()
{
// watchdogConfig(WATCHDOG_OFF);
// __asm__ __volatile__ (
//#ifdef VIRTUAL_BOOT_PARTITION
// // Jump to WDT vector
// "ldi r30,4\n"
// "clr r31\n"
//#else
// // Jump to RST vector
// "clr r30\n"
// "clr r31\n"
//#endif
// "ijmp\n"
// );
register void (*p)() ;
p = 0 ;
if ( pgm_read_byte( (uint16_t)p ) != 0xFF )
{
(*p)() ;
}
}

View File

@ -0,0 +1,80 @@
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB5
/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT PORTD
#define UART_PIN PIND
#define UART_DDR DDRD
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif
#if defined(__AVR_ATmega8__)
//Name conversion R.Wiersma
#define UCSR0A UCSRA
#define UDR0 UDR
#define UDRE0 UDRE
#define RXC0 RXC
#define FE0 FE
#define TIFR1 TIFR
#define WDTCSR WDTCR
#endif
/* Luminet support */
#if defined(__AVR_ATtiny84__)
/* Red LED is connected to pin PA4 */
#define LED_DDR DDRA
#define LED_PORT PORTA
#define LED_PIN PINA
#define LED PINA4
/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
#ifdef SOFT_UART
#define UART_PORT PORTA
#define UART_PIN PINA
#define UART_DDR DDRA
#define UART_TX_BIT 2
#define UART_RX_BIT 3
#endif
#endif
/* Sanguino support */
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
/* Onboard LED is connected to pin PB0 on Sanguino */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB0
/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT PORTD
#define UART_PIN PIND
#define UART_DDR DDRD
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif
/* Mega support */
#if defined(__AVR_ATmega1280__)
/* Onboard LED is connected to pin PB7 on Arduino Mega */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB7
/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT PORTE
#define UART_PIN PINE
#define UART_DDR DDRE
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif

View File

@ -0,0 +1,39 @@
/* STK500 constants list, from AVRDUDE */
#define STK_OK 0x10
#define STK_FAILED 0x11 // Not used
#define STK_UNKNOWN 0x12 // Not used
#define STK_NODEVICE 0x13 // Not used
#define STK_INSYNC 0x14 // ' '
#define STK_NOSYNC 0x15 // Not used
#define ADC_CHANNEL_ERROR 0x16 // Not used
#define ADC_MEASURE_OK 0x17 // Not used
#define PWM_CHANNEL_ERROR 0x18 // Not used
#define PWM_ADJUST_OK 0x19 // Not used
#define CRC_EOP 0x20 // 'SPACE'
#define STK_GET_SYNC 0x30 // '0'
#define STK_GET_SIGN_ON 0x31 // '1'
#define STK_SET_PARAMETER 0x40 // '@'
#define STK_GET_PARAMETER 0x41 // 'A'
#define STK_SET_DEVICE 0x42 // 'B'
#define STK_SET_DEVICE_EXT 0x45 // 'E'
#define STK_ENTER_PROGMODE 0x50 // 'P'
#define STK_LEAVE_PROGMODE 0x51 // 'Q'
#define STK_CHIP_ERASE 0x52 // 'R'
#define STK_CHECK_AUTOINC 0x53 // 'S'
#define STK_LOAD_ADDRESS 0x55 // 'U'
#define STK_UNIVERSAL 0x56 // 'V'
#define STK_PROG_FLASH 0x60 // '`'
#define STK_PROG_DATA 0x61 // 'a'
#define STK_PROG_FUSE 0x62 // 'b'
#define STK_PROG_LOCK 0x63 // 'c'
#define STK_PROG_PAGE 0x64 // 'd'
#define STK_PROG_FUSE_EXT 0x65 // 'e'
#define STK_READ_FLASH 0x70 // 'p'
#define STK_READ_DATA 0x71 // 'q'
#define STK_READ_FUSE 0x72 // 'r'
#define STK_READ_LOCK 0x73 // 's'
#define STK_READ_PAGE 0x74 // 't'
#define STK_READ_SIGN 0x75 // 'u'
#define STK_READ_OSCCAL 0x76 // 'v'
#define STK_READ_FUSE_EXT 0x77 // 'w'
#define STK_READ_OSCCAL_EXT 0x78 // 'x'

32
BootLoaders/README.md Normal file
View File

@ -0,0 +1,32 @@
# Arduino IDE board definition for Multi 4-in-1 transmitter module
At this point the only supported board/module is the Atmega328p-based module, the STM32-based module is not yet supported.
## Installing
The board definition is installed using the Arduino IDE Boards Manager.
1. Open the Arduino IDE
2. Go to File->Preferences (or Ctrl+Comma)
3. Locate the 'Aditional Boards Manager URLs' field and paste in this URL: https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module/master/BootLoaders/package_multi_4in1_board_index.json
4. Click OK to save the change
5. Click Tools->Board [Board Name]->Boards Manager
6. Scroll to the bottom of the list of boards and click on 'Multi 4-in-1 Boards' then click the Install button
7. Click Close to close the Boards Manager
## Selecting the board
1. Click Tools->Board [Board Name]
2. Scroll down the list to 'Multi 4-in-1 Boards' and select 'Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)'
## Choosing the bootloader
There are two bootloader options. The default 'No bootloader' won't install a bootloader, allowing the maximum space for protocols. The 'Flash from TX' option installs a small Optiboot bootloader which is compatible with Ersky9x and OpenTX option to flash firmware from the transmitter's maintenance menu.
1. Click Tools->Bootloader [Bootloader Option]
2. Select the desired bootloader
**Recommended:** Click Tools->Burn Bootloader to set the fuses, even if the 'No bootloader' option was selected.
## Compiling / uploading firmware with the 'Flash from TX' bootloader
1. Follow the normal compiling method.
2. Copy the compiled .hex file (usually Multiprotocol.ino.hex) in the "/firmware" directory of the SD card.
3. Start Ersky9x in "Maintenance Mode" by holding the horizontal trims APART while powering on the transmitter.
4. Select "Update Multi", then change "File Type" to "HEX", then select "Update", choose the firmware to flash, long pressto select it and long press to flash it.
5. When finished, long press EXIT to reboot in normal mode.

View File

@ -0,0 +1 @@
[Source for the StmMultiBooloader](https://github.com/MikeBland/StmMultiBoot)

Binary file not shown.

View File

@ -0,0 +1,2 @@
[Source for the StmMultiUSB=STM32duino-bootloader](https://github.com/rogerclarkmelbourne/STM32duino-bootloader)
If you want the latest version, you should look for the file generic_boot20_pa1.bin.

Binary file not shown.

View File

@ -0,0 +1,33 @@
{
"packages": [
{
"name": "Multi 4-in-1",
"maintainer": "Pascal Langer",
"websiteURL": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module",
"email": "pascal_langer@yahoo.fr",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"platforms": [
{
"name": "Multi 4-in-1 Boards",
"architecture": "avr",
"version": "1.0",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/package_multi_4in1_board_v1.0.0.zip",
"archiveFileName": "package_multi_4in1_board_v1.0.0.zip",
"checksum": "SHA-256:61AB463B5B91BCCBF285EB4C801B37E4F46138CA8762E4C04CCB09C2FF157CB7",
"size": "3161",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"}
],
"toolsDependencies": []
}
],
"tools": []
}
]
}

Binary file not shown.

View File

@ -179,12 +179,26 @@ static void AFHDS2A_build_packet(uint8_t type)
packet[0] = 0x56;
for(uint8_t ch=0; ch<14; ch++)
{
/*if((Model.limits[ch].flags & CH_FAILSAFE_EN))
#ifdef AFHDS2A_FAILSAFE
int8_t failsafe = AFHDS2AFailsafe[ch];
//
if(failsafe != -1)
{
packet[9 + ch*2] = Servo_data[CH_AETR[ch]] & 0xff;
packet[10+ ch*2] = (Servo_data[CH_AETR[ch]] >> 8) & 0xff;
//
if (failsafe > AFHDS2AFailsafeMAX)
failsafe = AFHDS2AFailsafeMAX;
//
if (failsafe < AFHDS2AFailsafeMIN)
failsafe = AFHDS2AFailsafeMIN;
//
double scale = (float)failsafe/(float)100;
int16_t failsafeMicros = 1500 + ((float)512 * scale);
//
packet[9 + ch*2] = failsafeMicros & 0xff;
packet[10+ ch*2] = ( failsafeMicros >> 8) & 0xff;
}
else*/
else
#endif
{
packet[9 + ch*2] = 0xff;
packet[10+ ch*2] = 0xff;
@ -260,6 +274,7 @@ uint16_t ReadAFHDS2A()
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetPower();
A7105_SetTxRxMode(TXRX_OFF); // Turn LNA off since we are in near range and we want to prevent swamping
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
@ -325,6 +340,7 @@ uint16_t ReadAFHDS2A()
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetPower();
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;

View File

@ -53,7 +53,11 @@ void ASSAN_send_packet()
uint16_t temp;
for(uint8_t i=0;i<8;i++)
{
temp=Servo_data[i]<<3;
if(mode_select != MODE_SERIAL) // If in PPM mode extend the output to 1000...2000µs
temp=convert_channel_16b_nolim(i,1000,2000);
else
temp=Servo_data[i];
temp<<=3;
packet[2*i]=temp>>8;
packet[2*i+1]=temp;
}

View File

@ -25,6 +25,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#define BAYANG_PACKET_SIZE 15
#define BAYANG_RF_NUM_CHANNELS 4
#define BAYANG_RF_BIND_CHANNEL 0
#define BAYANG_RF_BIND_CHANNEL_X16_AH 10
#define BAYANG_ADDRESS_LENGTH 5
enum BAYANG_FLAGS {
@ -35,9 +36,11 @@ enum BAYANG_FLAGS {
BAYANG_FLAG_VIDEO = 0x10,
BAYANG_FLAG_PICTURE = 0x20,
// flags going to packet[3]
BAYANG_FLAG_INVERTED = 0x80 // inverted flight on Floureon H101
BAYANG_FLAG_INVERTED = 0x80, // inverted flight on Floureon H101
BAYANG_FLAG_TAKE_OFF = 0x20, // take off / landing on X16 AH
};
uint8_t bayang_bind_chan;
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
{
uint8_t i;
@ -53,13 +56,29 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[i+1]=rx_tx_addr[i];
for(i=0;i<4;i++)
packet[i+6]=hopping_frequency[i];
switch (sub_protocol)
{
case X16_AH:
packet[10] = 0x00;
packet[11] = 0x00;
break;
default:
packet[10] = rx_tx_addr[0]; // txid[0]
packet[11] = rx_tx_addr[1]; // txid[1]
break;
}
}
else
{
uint16_t val;
switch (sub_protocol) {
case X16_AH:
packet[0] = 0xA6;
break;
default:
packet[0] = 0xA5;
break;
}
packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa
//Flags packet[2]
@ -78,7 +97,8 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[3] = 0x00;
if(Servo_AUX6)
packet[3] = BAYANG_FLAG_INVERTED;
if(Servo_AUX7)
packet[3] |= BAYANG_FLAG_TAKE_OFF;
//Aileron
val = convert_channel_10b(AILERON);
packet[4] = (val>>8) + ((val>>2) & 0xFC);
@ -96,13 +116,26 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[10] = (val>>8) + (val>>2 & 0xFC);
packet[11] = val & 0xFF;
}
switch (sub_protocol)
{
case H8S3D:
packet[12] = rx_tx_addr[2]; // txid[2]
packet[13] = sub_protocol==H8S3D?0x34:0x0A;
packet[13] = 0x34;
break;
case X16_AH:
packet[12] = 0;
packet[13] = 0;
break;
default:
packet[12] = rx_tx_addr[2]; // txid[2]
packet[13] = 0x0A;
break;
}
packet[14] = 0;
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
packet[14] += packet[i];
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? BAYANG_RF_BIND_CHANNEL:hopping_frequency[hopping_frequency_no++]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? bayang_bind_chan:hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;
// clear packet status bits and TX FIFO
@ -121,7 +154,6 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
#ifdef BAYANG_HUB_TELEMETRY
if (option)
{ // switch radio to rx as soon as packet is sent
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
}
@ -131,7 +163,7 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
}
#ifdef BAYANG_HUB_TELEMETRY
static void __attribute__((unused)) check_rx(void)
static void __attribute__((unused)) BAYANG_check_rx(void)
{
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // data received from model
@ -204,7 +236,7 @@ uint16_t BAYANG_callback()
}
if (packet_count > 1)
check_rx();
BAYANG_check_rx();
packet_count %= 5;
}
@ -251,10 +283,18 @@ uint16_t initBAYANG(void)
BAYANG_initialize_txid();
BAYANG_init();
packet_count=0;
#ifdef BAYANG_HUB_TELEMETRY
switch (sub_protocol) {
case X16_AH:
bayang_bind_chan = BAYANG_RF_BIND_CHANNEL_X16_AH;
break;
default:
bayang_bind_chan = BAYANG_RF_BIND_CHANNEL;
break;
}
#ifdef BAYANG_HUB_TELEMETRY
init_frskyd_link_telemetry();
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
#endif
#endif
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
}

View File

@ -24,8 +24,7 @@ Multiprotocol is distributed in the hope that it will be useful,
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// The Receiver for this protocol is available at: https://github.com/soligen2010/RC_RX_CABELL_V3_FHSS
// The Receiver for this protocol is available at: https://github.com/soligen2010/RC_RX_CABELL_V3_FHSS
#if defined(CABELL_NRF24L01_INO)
@ -49,8 +48,10 @@ Multiprotocol is distributed in the hope that it will be useful,
#define CABELL_OPTION_SHIFT_RECIEVER_OUTPUT_MODE 4
#define CABELL_OPTION_MASK_MAX_POWER_OVERRIDE 0x40
typedef struct {
enum RxMode_t : uint8_t { // Note bit 8 is used to indicate if the packet is the first of 2 on the channel. Mask out this bit before using the enum
typedef struct
{
enum RxMode_t : uint8_t
{ // Note bit 8 is used to indicate if the packet is the first of 2 on the channel. Mask out this bit before using the enum
normal = 0,
bind = 1,
setFailSafe = 2,
@ -76,7 +77,8 @@ typedef struct {
} CABELL_RxTxPacket_t;
//-----------------------------------------------------------------------------------------
static uint8_t __attribute__((unused)) CABELL_getNextChannel (uint8_t seqArray[], uint8_t seqArraySize, uint8_t prevChannel) {
static uint8_t __attribute__((unused)) CABELL_getNextChannel (uint8_t seqArray[], uint8_t seqArraySize, uint8_t prevChannel)
{
/* Possible channels are in 5 bands, each band comprised of seqArraySize channels
* seqArray contains seqArraySize elements in the relative order in which we should progress through the band
*
@ -84,26 +86,28 @@ static uint8_t __attribute__((unused)) CABELL_getNextChannel (uint8_t seqArray[]
* different non-adjacent band. Both the band changes and the index in seqArray is incremented.
*/
prevChannel -= CABELL_RADIO_MIN_CHANNEL_NUM; // Subtract CABELL_RADIO_MIN_CHANNEL_NUM because it was added to the return value
prevChannel = constrain(prevChannel,0,(seqArraySize * 5) ); // Constrain the values just in case something bogus was sent in.
if(prevChannel>(seqArraySize * 5))
prevChannel=seqArraySize * 5; // Constrain the values just in case something bogus was sent in.
uint8_t currBand = prevChannel / seqArraySize;
uint8_t nextBand = (currBand + 3) % 5;
uint8_t prevChannalSeqArrayValue = prevChannel % seqArraySize;
uint8_t prevChannalSeqArrayPosition = 0;
for (int x = 0; x < seqArraySize; x++) { // Find the position of the previous channel in the array
if (seqArray[x] == prevChannalSeqArrayValue) {
for (int x = 0; x < seqArraySize; x++)
{ // Find the position of the previous channel in the array
if (seqArray[x] == prevChannalSeqArrayValue)
prevChannalSeqArrayPosition = x;
}
}
uint8_t nextChannalSeqArrayPosition = prevChannalSeqArrayPosition + 1;
if (nextChannalSeqArrayPosition >= seqArraySize) nextChannalSeqArrayPosition = 0;
if (nextChannalSeqArrayPosition >= seqArraySize)
nextChannalSeqArrayPosition = 0;
return (seqArraySize * nextBand) + seqArray[nextChannalSeqArrayPosition] + CABELL_RADIO_MIN_CHANNEL_NUM; // Add CABELL_RADIO_MIN_CHANNEL_NUM so we dont use channel 0 as it may bleed below 2.400 GHz
}
//-----------------------------------------------------------------------------------------
#if defined TELEMETRY
#if defined CABELL_HUB_TELEMETRY
static void __attribute__((unused)) CABELL_get_telemetry()
{
// calculate TX rssi based on past 250 expected telemetry packets. Cannot use full second count because telemetry_counter is not large enough
@ -117,7 +121,8 @@ static void __attribute__((unused)) CABELL_get_telemetry()
}
// Process incoming telemetry packet of it was received
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) { // data received from model
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // data received from model
NRF24L01_ReadPayload(packet, CABELL_TELEMETRY_PACKET_LENGTH);
if ((packet[0] & 0x7F) == CABELL_RxTxPacket_t::RxMode_t::telemetryResponse) // ignore high order bit in compare because it toggles with each packet
{
@ -125,9 +130,12 @@ static void __attribute__((unused)) CABELL_get_telemetry()
v_lipo1 = packet[2]; // Directly from analog input of receiver, but reduced to 8-bit depth (0 to 255). Scaling depends on the input to the analog pin of the receiver.
v_lipo2 = packet[3]; // Directly from analog input of receiver, but reduced to 8-bit depth (0 to 255). Scaling depends on the input to the analog pin of the receiver.
telemetry_counter++;
if(telemetry_lost==0) telemetry_link=1;
if(telemetry_lost==0)
telemetry_link=1;
}
} else {
}
else
{
// If no telemetry packet was received then delay by the typical telemetry packet processing time
// This is done to try to keep the sendPacket process timing more consistent. Since the SPI payload read takes some time
delayMicroseconds(50);
@ -140,36 +148,42 @@ static void __attribute__((unused)) CABELL_get_telemetry()
//-----------------------------------------------------------------------------------------
static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
{
#if defined TELEMETRY
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY)) { // check for incoming packet and switch radio back to TX mode if we were listening for telemetry
#if defined CABELL_HUB_TELEMETRY
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY)) // check for incoming packet and switch radio back to TX mode if we were listening for telemetry
CABELL_get_telemetry();
}
#endif
CABELL_RxTxPacket_t TxPacket;
uint8_t channelReduction = constrain((option & CABELL_OPTION_MASK_CHANNEL_REDUCTION),0,CABELL_NUM_CHANNELS-CABELL_MIN_CHANNELS); // Max 12 - cannot reduce below 4 channels
if (bindMode) {
if (bindMode)
channelReduction = 0; // Send full packet to bind as higher channels will contain bind info
}
uint8_t packetSize = sizeof(TxPacket) - ((((channelReduction - (channelReduction%2))/ 2)) * 3); // reduce 3 bytes per 2 channels, but not last channel if it is odd
uint8_t maxPayloadValueIndex = sizeof(TxPacket.payloadValue) - (sizeof(TxPacket) - packetSize);
if ((sub_protocol == CABELL_UNBIND) && !bindMode) {
if ((sub_protocol == CABELL_UNBIND) && !bindMode)
{
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::unBind;
TxPacket.option = option;
} else {
if (sub_protocol == CABELL_SET_FAIL_SAFE && !bindMode) {
}
else
{
if (sub_protocol == CABELL_SET_FAIL_SAFE && !bindMode)
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::setFailSafe;
} else {
if (bindMode) {
else
{
if (bindMode)
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::bind;
} else {
switch (sub_protocol) {
case CABELL_V3_TELEMETRY : TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normalWithTelemetry;
else
{
switch (sub_protocol)
{
case CABELL_V3_TELEMETRY:
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normalWithTelemetry;
break;
default : TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normal;
default:
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normal;
break;
}
}
@ -184,8 +198,10 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
int payloadIndex = 0;
uint16_t holdValue;
for (int x = 0;(x < CABELL_NUM_CHANNELS - channelReduction); x++) {
switch (x) {
for (int x = 0;(x < CABELL_NUM_CHANNELS - channelReduction); x++)
{
switch (x)
{
case 0 : adjusted_x = ELEVATOR; break;
case 1 : adjusted_x = AILERON; break;
case 2 : adjusted_x = RUDDER; break;
@ -193,8 +209,10 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
default : adjusted_x = x; break;
}
holdValue = map(limit_channel_100(adjusted_x),servo_min_100,servo_max_100,1000,2000); // valid channel values are 1000 to 2000
if (bindMode) {
switch (adjusted_x) {
if (bindMode)
{
switch (adjusted_x)
{
case THROTTLE : holdValue = 1000; break; // always set throttle to off when binding for safety
//tx address sent for bind
case 11 : holdValue = 1000 + rx_tx_addr[0]; break;
@ -206,21 +224,21 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
}
// use 12 bits per value
if (x % 2) { //output channel number is ODD
if (x % 2)
{ //output channel number is ODD
holdValue = holdValue<<4;
payloadIndex--;
} else {
holdValue &= 0x0FFF;
}
else
holdValue &= 0x0FFF;
TxPacket.payloadValue[payloadIndex] |= (uint8_t)(holdValue & 0x00FF);
payloadIndex++;
TxPacket.payloadValue[payloadIndex] |= (uint8_t)((holdValue>>8) & 0x00FF);
payloadIndex++;
}
for(int x = 0; x < maxPayloadValueIndex ; x++) {
for(int x = 0; x < maxPayloadValueIndex ; x++)
checkSum += TxPacket.payloadValue[x]; // Finish Calculate checksum
}
TxPacket.checkSum_MSB = checkSum >> 8;
TxPacket.checkSum_LSB = checkSum & 0x00FF;
@ -240,8 +258,9 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
CABELL_SetPower();
NRF24L01_WritePayload((uint8_t*)&TxPacket, packetSize);
#if defined TELEMETRY
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY)) { // switch radio to rx as soon as packet is sent
#if defined CABELL_HUB_TELEMETRY
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY))
{ // switch radio to rx as soon as packet is sent
// calculate transmit time based on packet size and data rate of 1MB per sec
// This is done because polling the status register during xmit caused issues.
// bits = packst_size * 8 + 73 bits overhead
@ -250,13 +269,15 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
delayMicroseconds(((((unsigned long)packetSize * 8ul) + 73ul) * 4ul) + 140ul) ;
packet_period = CABELL_PACKET_PERIOD + (constrain(((int16_t)(CABELL_NUM_CHANNELS - channelReduction) - (int16_t)6 ),(int16_t)0 ,(int16_t)10 ) * (int16_t)100); // increase packet period by 100 us for each channel over 6
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // RX mode with 16 bit CRC
} else
}
else
#endif
packet_period = CABELL_PACKET_PERIOD; // Standard packet period when not in telemetry mode.
}
//-----------------------------------------------------------------------------------------
static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[], uint8_t numChannels, uint64_t permutation) {
static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[], uint8_t numChannels, uint64_t permutation)
{
/* This procedure initializes an array with the sequence progression of channels.
* This is not the actual channels itself, but the sequence base to be used within bands of
* channels.
@ -270,14 +291,15 @@ static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[
* variables to overflow, yielding unknown results (possibly infinite loop?). Therefor
* this routine constrains the value.
*/
uint64_t i; //iterator counts numChannels
uint8_t i; //iterator counts numChannels
uint64_t indexOfNextSequenceValue;
uint64_t numChannelsFactorial=1;
uint8_t sequenceValue;
numChannels = constrain(numChannels,1,20);
for (i = 1; i <= numChannels;i++) {
for (i = 1; i <= numChannels;i++)
{
numChannelsFactorial *= i; // Calculate n!
outArray[i-1] = i-1; // Initialize array with the sequence
}
@ -285,7 +307,8 @@ static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[
permutation = (permutation % numChannelsFactorial) + 1; // permutation must be between 1 and n! or this algorithm will infinite loop
//Rearrange the array elements based on the permutation selected
for (i=0, permutation--; i<numChannels; i++ ) {
for (i=0, permutation--; i<numChannels; i++ )
{
numChannelsFactorial /= ((uint64_t)numChannels)-i;
indexOfNextSequenceValue = i+(permutation/numChannelsFactorial);
permutation %= numChannelsFactorial;
@ -294,9 +317,9 @@ static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[
sequenceValue = outArray[indexOfNextSequenceValue];
//Shift the unused elements in the array to make room to move in the one just selected
for( ; indexOfNextSequenceValue > i; indexOfNextSequenceValue--) {
for( ; indexOfNextSequenceValue > i; indexOfNextSequenceValue--)
outArray[indexOfNextSequenceValue] = outArray[indexOfNextSequenceValue-1];
}
// Copy the selected value into it's new array slot
outArray[i] = sequenceValue;
}
@ -307,21 +330,21 @@ static void __attribute__((unused)) CABELL_setAddress()
{
uint64_t CABELL_addr;
// Serial.print("NORM ID: ");Serial.print((uint32_t)(CABELL_normal_addr>>32)); Serial.print(" ");Serial.println((uint32_t)((CABELL_normal_addr<<32)>>32));
// Serial.print("NORM ID: ");Serial.print((uint32_t)(CABELL_normal_addr>>32)); Serial.print(" ");Serial.println((uint32_t)((CABELL_normal_addr<<32)>>32));
if (IS_BIND_DONE_on) {
if (IS_BIND_DONE_on)
{
CABELL_addr = (((uint64_t)rx_tx_addr[0]) << 32) +
(((uint64_t)rx_tx_addr[1]) << 24) +
(((uint64_t)rx_tx_addr[2]) << 16) +
(((uint64_t)rx_tx_addr[3]) << 8) +
(((uint64_t)rx_tx_addr[4])); // Address to use after binding
}
else {
CABELL_addr = CABELL_BIND_RADIO_ADDR; //static addr for binding
}
else
CABELL_addr = CABELL_BIND_RADIO_ADDR; // Static addr for binding
CABELL_getChannelSequence(hopping_frequency,CABELL_RADIO_CHANNELS,CABELL_addr); // Get the sequence for hopping through channels
rf_ch_num = CABELL_RADIO_MIN_CHANNEL_NUM; // initialize the channel sequence
rf_ch_num = CABELL_RADIO_MIN_CHANNEL_NUM; // Initialize the channel sequence
packet_count=0;
@ -363,7 +386,8 @@ static void CABELL_SetPower() // This over-ride the standard Set Power to all
// Note that on many modules max power may actually be worse than the normal high power setting
// test and only use max if it helps the range
{
if(IS_BIND_DONE_on && !IS_RANGE_FLAG_on && ((option & CABELL_OPTION_MASK_MAX_POWER_OVERRIDE) != 0)) { // If we are not in range or bind mode and power setting override is in effect, then set max power, else standard power logic
if(IS_BIND_DONE_on && !IS_RANGE_FLAG_on && ((option & CABELL_OPTION_MASK_MAX_POWER_OVERRIDE) != 0))
{ // If we are not in range or bind mode and power setting override is in effect, then set max power, else standard power logic
if(prev_power != NRF_POWER_3) // prev_power is global variable for NRF24L01; NRF_POWER_3 is max power
{
uint8_t rf_setup = NRF24L01_ReadReg(NRF24L01_06_RF_SETUP);
@ -372,21 +396,18 @@ static void CABELL_SetPower() // This over-ride the standard Set Power to all
prev_power=NRF_POWER_3;
}
}
else {
else
NRF24L01_SetPower();
}
}
//-----------------------------------------------------------------------------------------
uint16_t CABELL_callback()
{
if (IS_BIND_DONE_on) {
if (IS_BIND_DONE_on)
{
CABELL_send_packet(0); // packet_period is set/adjusted in CABELL_send_packet
return packet_period;
}
else
{
if (bind_counter == 0)
{
BIND_DONE;
@ -398,21 +419,17 @@ uint16_t CABELL_callback()
bind_counter--;
}
return CABELL_PACKET_PERIOD;
}
}
//-----------------------------------------------------------------------------------------
uint16_t initCABELL(void)
{
if (IS_BIND_DONE_on) {
if (IS_BIND_DONE_on)
bind_counter = 0;
}
else
{
bind_counter = CABELL_BIND_COUNT;
}
CABELL_init();
#if defined TELEMETRY
#if defined CABELL_HUB_TELEMETRY
init_frskyd_link_telemetry();
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
#endif

View File

@ -78,6 +78,7 @@ uint8_t CYRF_Reset()
*/
void CYRF_GetMfgData(uint8_t data[])
{
#ifndef FORCE_CYRF_ID
/* Fuses power on */
CYRF_WriteRegister(CYRF_25_MFG_ID, 0xFF);
@ -85,6 +86,9 @@ void CYRF_GetMfgData(uint8_t data[])
/* Fuses power off */
CYRF_WriteRegister(CYRF_25_MFG_ID, 0x00);
#else
memcpy(data,FORCE_CYRF_ID,6);
#endif
}
/*

View File

@ -0,0 +1,157 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// compatible with DM002
#if defined(DM002_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define DM002_PACKET_PERIOD 6100 // Timeout for callback in uSec
#define DM002_INITIAL_WAIT 500
#define DM002_PACKET_SIZE 12 // packets have 12-byte payload
#define DM002_RF_BIND_CHANNEL 0x27
#define DM002_BIND_COUNT 655 // 4 seconds
enum DM002_FLAGS {
// flags going to packet[9]
DM002_FLAG_FLIP = 0x01,
DM002_FLAG_LED = 0x02,
DM002_FLAG_MEDIUM = 0x04,
DM002_FLAG_HIGH = 0x08,
DM002_FLAG_RTH = 0x10,
DM002_FLAG_HEADLESS = 0x20,
DM002_FLAG_CAMERA1 = 0x40,
DM002_FLAG_CAMERA2 = 0x80,
};
static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
{
memcpy(packet+5,(uint8_t *)"\x00\x7F\x7F\x7F\x00\x00\x00",7);
if(bind)
{
packet[0] = 0xAA;
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = rx_tx_addr[2];
packet[4] = rx_tx_addr[3];
}
else
{
packet[0]=0x55;
// Throttle : 0 .. 200
packet[1]=convert_channel_8b_scale(THROTTLE,0,200);
// Other channels min 0x57, mid 0x7F, max 0xA7
packet[2] = convert_channel_8b_scale(RUDDER,0x57,0xA7);
packet[3] = convert_channel_8b_scale(AILERON, 0x57,0xA7);
packet[4] = convert_channel_8b_scale(ELEVATOR, 0xA7, 0x57);
// Features
packet[9] = GET_FLAG(Servo_AUX1,DM002_FLAG_FLIP)
| GET_FLAG(!Servo_AUX2,DM002_FLAG_LED)
| GET_FLAG(Servo_AUX3,DM002_FLAG_CAMERA1)
| GET_FLAG(Servo_AUX4,DM002_FLAG_CAMERA2)
| GET_FLAG(Servo_AUX5,DM002_FLAG_HEADLESS)
| GET_FLAG(Servo_AUX6,DM002_FLAG_RTH)
| GET_FLAG(!Servo_AUX7,DM002_FLAG_HIGH);
// Packet counter
if(packet_count&0x03)
{
packet_count++;
hopping_frequency_no++;
hopping_frequency_no&=4;
}
packet_count&=0x0F;
packet[10] = packet_count;
packet_count++;
}
//CRC
for(uint8_t i=0;i<DM002_PACKET_SIZE-1;i++)
packet[11]+=packet[i];
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, DM002_RF_BIND_CHANNEL);
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, DM002_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) DM002_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
}
uint16_t DM002_callback()
{
if(IS_BIND_DONE_on)
DM002_send_packet(0);
else
{
if (bind_counter == 0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 5);
}
else
{
DM002_send_packet(1);
bind_counter--;
}
}
return DM002_PACKET_PERIOD;
}
static void __attribute__((unused)) DM002_initialize_txid()
{
// Only 2 IDs/RFs are available, RX_NUM is used to switch between them
if(rx_tx_addr[3]&1)
{
memcpy(hopping_frequency,(uint8_t *)"\x34\x39\x43\x48",4);
memcpy(rx_tx_addr,(uint8_t *)"\x47\x93\x00\x00\xD5",5);
}
else
{
memcpy(hopping_frequency,(uint8_t *)"\x35\x39\x3B\x3D",4);
memcpy(rx_tx_addr,(uint8_t *)"\xAC\xA1\x00\x00\xD5",5);
}
}
uint16_t initDM002(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = DM002_BIND_COUNT;
DM002_initialize_txid();
DM002_init();
return DM002_INITIAL_WAIT;
}
#endif

View File

@ -273,13 +273,9 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
uint16_t value = 0xffff;;
if (idx != 0xff)
{
if (!IS_BIND_DONE_on)
{ // Failsafe position during binding
value=max/2; //all channels to middle
if(idx==0)
value=1; //except throttle
}
else
/* Spektrum own remotes transmit normal values during bind and actually
* use this (e.g. Nano CP X) to select the transmitter mode (e.g. computer vs
* non-computer radio, so always end normal output */
value=map(Servo_data[CH_TAER[idx]],servo_min_125,servo_max_125,0,max);
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
}

View File

@ -133,7 +133,7 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
{
uint8_t i;
//servodata timing range for flysky.
////-100% =~ 0x03e8//=1000us(min)
//-100% =~ 0x03e8//=1000us(min)
//+100% =~ 0x07ca//=1994us(max)
//Center = 0x5d9//=1497us(center)
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
@ -147,6 +147,8 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
uint16_t temp=Servo_data[CH_AETR[i]];
if(sub_protocol == CX20 && CH_AETR[i] == ELEVATOR)
temp=servo_mid-temp; //reverse channel
if(mode_select != MODE_SERIAL) //if in PPM mode extend the output to 1000...2000µs
temp=map(temp,servo_min_100,servo_max_100,1000,2000);
packet[5 + i*2]=temp&0xFF; //low byte of servo timing(1000-2000us)
packet[6 + i*2]=(temp>>8)&0xFF; //high byte of servo timing(1000-2000us)
}

View File

@ -21,8 +21,11 @@
#include "iface_cc2500.h"
uint8_t chanskip;
uint8_t seq_last_sent;
uint8_t seq_last_rcvd;
//uint8_t seq_last_sent;
//uint8_t seq_last_rcvd;
uint8_t FrX_send_seq ;
uint8_t FrX_receive_seq ;
static void __attribute__((unused)) set_start(uint8_t ch )
{
@ -151,11 +154,7 @@ static void __attribute__((unused)) frskyX_data_frame()
packet[9+i+2]=chan_1>>4;
}
packet[21] = seq_last_sent << 4 | seq_last_rcvd;//8 at start
if (seq_last_sent < 0x08 && seq_last_rcvd < 8)
seq_last_sent = (seq_last_sent + 1) % 4;
else if (seq_last_rcvd == 0x00)
seq_last_sent = 1;
packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms
lpass = 0 ;
@ -208,9 +207,9 @@ uint16_t ReadFrSkyX()
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1);
//
frskyX_data_frame();
// frskyX_data_frame();
state++;
return 5500;
return 5200;
case FRSKY_DATA2:
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SIDLE);
@ -219,7 +218,7 @@ uint16_t ReadFrSkyX()
case FRSKY_DATA3:
CC2500_Strobe(CC2500_SRX);
state++;
return 3000;
return 3100;
case FRSKY_DATA4:
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
@ -238,8 +237,10 @@ uint16_t ReadFrSkyX()
// restart sequence on missed packet - might need count or timeout instead of one missed
if(packet_count>100)
{//~1sec
seq_last_sent = 0;
seq_last_rcvd = 8;
// seq_last_sent = 0;
// seq_last_rcvd = 8;
FrX_send_seq = 0x08 ;
// FrX_receive_seq = 0 ;
packet_count=0;
#if defined TELEMETRY
telemetry_lost=1;
@ -247,8 +248,13 @@ uint16_t ReadFrSkyX()
}
CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO
}
frskyX_data_frame();
if ( FrX_send_seq != 0x08 )
{
FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
}
state = FRSKY_DATA1;
return 300;
return 500;
}
return 1;
}
@ -277,8 +283,10 @@ uint16_t initFrSkyX()
state = FRSKY_DATA1;
initialize_data(0);
}
seq_last_sent = 0;
seq_last_rcvd = 8;
// seq_last_sent = 0;
// seq_last_rcvd = 8;
FrX_send_seq = 0x08 ;
FrX_receive_seq = 0 ;
return 10000;
}
#endif

View File

@ -11,7 +11,7 @@
11,SLT,SLT,VISTA
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
13,CG023,CG023,YD829,H8_3D
14,Bayang,Bayang,H8S3D
14,Bayang,Bayang,H8S3D,X16_AH
15,FrskyX,CH_16,CH_8,EU_16,EU_8
16,ESky
17,MT99xx,MT,H7,YZ,LS,FY805
@ -30,3 +30,5 @@
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
31,Q303,Q303,CX35,CX10D,CX10WD
32,GW008
33,DM002
34,CABELL,CAB_V3,C_TELEM,-,-,-,-,F_SAFE,UNBIND

View File

@ -19,7 +19,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 1
#define VERSION_REVISION 6
#define VERSION_PATCH_LEVEL 20
#define VERSION_PATCH_LEVEL 29
//******************
// Protocols
//******************
@ -58,6 +58,7 @@ enum PROTOCOLS
MODE_WK2x01 = 30, // =>CYRF6936
MODE_Q303 = 31, // =>NRF24L01
MODE_GW008 = 32, // =>NRF24L01
MODE_DM002 = 33, // =>NRF24L01
MODE_CABELL = 34, // =>NRF24L01
};
@ -136,7 +137,8 @@ enum CG023
enum BAYANG
{
BAYANG = 0,
H8S3D = 1
H8S3D = 1,
X16_AH = 2,
};
enum MT99XX
{
@ -199,8 +201,8 @@ enum CABELL
{
CABELL_V3 = 0,
CABELL_V3_TELEMETRY = 1,
CABELL_SET_FAIL_SAFE = 6,
CABELL_UNBIND = 7
CABELL_SET_FAIL_SAFE= 6,
CABELL_UNBIND = 7,
};
#define NONE 0
@ -400,7 +402,7 @@ enum CC2500_POWER
CC2500_POWER_16 = 0xFE, // 0dbm
CC2500_POWER_17 = 0xFF // +1dbm
};
#define CC2500_HIGH_POWER CC2500_POWER_16
#define CC2500_HIGH_POWER CC2500_POWER_17
#define CC2500_LOW_POWER CC2500_POWER_13
#define CC2500_RANGE_POWER CC2500_POWER_1
#define CC2500_BIND_POWER CC2500_POWER_1
@ -488,7 +490,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
WK2x01 30
Q303 31
GW008 32
CABELL 33
DM002 33
CABELL 34
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
@ -544,6 +547,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==BAYANG
BAYANG 0
H8S3D 1
X16_AH 2
sub_protocol==MT99XX
MT99 0
H7 1
@ -591,9 +595,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
CX10D 2
CX10WD 3
sub_protocol==CABELL
CABELL_V3 0,
CABELL_V3_TELEMETRY 1,
CABELL_SET_FAIL_SAFE 6,
CABELL_V3 0
CABELL_V3_TELEMETRY 1
CABELL_SET_FAIL_SAFE 6
CABELL_UNBIND 7
Power value => 0x80 0=High/1=Low

View File

@ -22,13 +22,25 @@
*/
#include <avr/pgmspace.h>
//#define DEBUG_TX
#define USE_MY_CONFIG
#ifdef ARDUINO_AVR_XMEGA32D4
#include "MultiOrange.h"
#endif
#include "Multiprotocol.h"
//Multiprotocol module configuration file
#include "_Config.h"
// Let's automatically select the board
// if arm is selected
#ifdef __arm__
#define STM32_BOARD // Let's automatically select this board if arm is selected since this is the only one for now...
#define STM32_BOARD
#endif
//Personal config file
#if defined USE_MY_CONFIG
#include "_MyConfig.h"
#endif
#include "Pins.h"
#include "TX_Def.h"
#include "Validate.h"
@ -97,6 +109,18 @@ uint8_t RX_num;
uint8_t calData[48];
#endif
#ifdef CHECK_FOR_BOOTLOADER
uint8_t BootTimer ;
uint8_t BootState ;
uint8_t NotBootChecking ;
uint8_t BootCount ;
#define BOOT_WAIT_30_IDLE 0
#define BOOT_WAIT_30_DATA 1
#define BOOT_WAIT_20 2
#define BOOT_READY 3
#endif
//Channel mapping for protocols
const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8, AUX9, AUX10};
const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8};
@ -145,7 +169,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
uint8_t pktt[MAX_PKT];//telemetry receiving packets
#ifdef BASH_SERIAL
// For bit-bashed serial output
#define TXBUFFER_SIZE 128
#define TXBUFFER_SIZE 192
volatile struct t_serial_bash
{
uint8_t head ;
@ -155,7 +179,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
uint8_t speed ;
} SerialControl ;
#else
#define TXBUFFER_SIZE 64
#define TXBUFFER_SIZE 96
volatile uint8_t tx_buff[TXBUFFER_SIZE];
volatile uint8_t tx_head=0;
volatile uint8_t tx_tail=0;
@ -198,6 +222,7 @@ void setup()
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
#elif defined STM32_BOARD
//STM32
afio_cfg_debug_ports(AFIO_DEBUG_NONE);
pinMode(A7105_CSN_pin,OUTPUT);
pinMode(CC25_CSN_pin,OUTPUT);
pinMode(NRF_CSN_pin,OUTPUT);
@ -382,7 +407,11 @@ void setup()
protocol=0;
servo_max_100=SERIAL_MAX_100; servo_min_100=SERIAL_MIN_100;
servo_max_125=SERIAL_MAX_125; servo_min_125=SERIAL_MIN_125;
#ifdef CHECK_FOR_BOOTLOADER
Mprotocol_serial_init(1); // Configure serial and enable RX interrupt
#else
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
#endif
#endif //ENABLE_SERIAL
}
servo_mid=servo_min_100+servo_max_100; //In fact 2* mid_value
@ -475,6 +504,11 @@ void loop()
uint8_t Update_All()
{
#ifdef ENABLE_SERIAL
#ifdef CHECK_FOR_BOOTLOADER
if ( (mode_select==MODE_SERIAL) && (NotBootChecking == 0) )
pollBoot() ;
else
#endif
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
{
update_serial_data(); // Update protocol and data
@ -505,7 +539,7 @@ uint8_t Update_All()
update_led_status();
#if defined(TELEMETRY)
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
if((protocol==MODE_FRSKYD) || (protocol==MODE_BAYANG) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) || (protocol==MODE_CABELL) )
if( (protocol==MODE_FRSKYD) || (protocol==MODE_BAYANG) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) || (protocol==MODE_CABELL) )
#endif
TelemetryUpdate();
#endif
@ -948,6 +982,12 @@ static void protocol_init()
remote_callback = GW008_callback;
break;
#endif
#if defined(DM002_NRF24L01_INO)
case MODE_DM002:
next_callback=initDM002();
remote_callback = DM002_callback;
break;
#endif
#if defined(CABELL_NRF24L01_INO)
case MODE_CABELL:
next_callback=initCABELL();
@ -1083,7 +1123,11 @@ void modules_reset()
prev_power=0xFD; // unused power value
}
void Mprotocol_serial_init()
#ifdef CHECK_FOR_BOOTLOADER
void Mprotocol_serial_init( uint8_t boot )
#else
void Mprotocol_serial_init()
#endif
{
#ifdef ORANGE_TX
PORTC.OUTSET = 0x08 ;
@ -1093,18 +1137,41 @@ void Mprotocol_serial_init()
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCC) | 0x11 ;
USARTC0.CTRLC = 0x2B ;
UDR0 ;
#ifdef INVERT_SERIAL
PORTC.PIN3CTRL |= 0x40 ;
#endif
#ifdef CHECK_FOR_BOOTLOADER
if ( boot )
{
USARTC0.BAUDCTRLB = 0 ;
USARTC0.BAUDCTRLA = 33 ; // 57600
USARTC0.CTRLA = (USARTC0.CTRLA & 0xC0) ;
USARTC0.CTRLC = 0x03 ; // 8 bit, no parity, 1 stop
USARTC0.CTRLB = 0x18 ; // Enable Tx and Rx
PORTC.PIN3CTRL &= ~0x40 ;
}
#endif // CHECK_FOR_BOOTLOADER
#elif defined STM32_BOARD
#ifdef CHECK_FOR_BOOTLOADER
if ( boot )
{
usart2_begin(57600,SERIAL_8N1);
USART2_BASE->CR1 &= ~USART_CR1_RXNEIE ;
(void)UDR0 ;
}
else
#endif // CHECK_FOR_BOOTLOADER
{
usart2_begin(100000,SERIAL_8E2);
usart3_begin(100000,SERIAL_8E2);
USART2_BASE->CR1 |= USART_CR1_PCE_BIT;
USART3_BASE->CR1 &= ~ USART_CR1_RE;//disable
USART2_BASE->CR1 &= ~ USART_CR1_TE;//disable transmit
}
usart3_begin(100000,SERIAL_8E2);
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable
USART2_BASE->CR1 &= ~ USART_CR1_TE; //disable transmit
#else
//ATMEGA328p
#include <util/setbaud.h>
@ -1113,7 +1180,7 @@ void Mprotocol_serial_init()
UCSR0A = 0 ; // Clear X2 bit
//Set frame format to 8 data bits, even parity, 2 stop bits
UCSR0C = _BV(UPM01)|_BV(USBS0)|_BV(UCSZ01)|_BV(UCSZ00);
while ( UCSR0A & (1 << RXC0) )//flush receive buffer
while ( UCSR0A & (1 << RXC0) ) //flush receive buffer
UDR0;
//enable reception and RC complete interrupt
UCSR0B = _BV(RXEN0)|_BV(RXCIE0);//rx enable and interrupt
@ -1122,9 +1189,130 @@ void Mprotocol_serial_init()
initTXSerial( SPEED_100K ) ;
#endif //TELEMETRY
#endif //DEBUG_TX
#ifdef CHECK_FOR_BOOTLOADER
if ( boot )
{
UBRR0H = 0;
UBRR0L = 33; // 57600
UCSR0C &= ~_BV(UPM01); // No parity
UCSR0B &= ~_BV(RXCIE0); // No rx interrupt
UCSR0A |= _BV(U2X0); // Double speed mode USART0
}
#endif // CHECK_FOR_BOOTLOADER
#endif //ORANGE_TX
}
#ifdef CHECK_FOR_BOOTLOADER
void pollBoot()
{
uint8_t rxchar ;
uint8_t lState = BootState ;
uint8_t millisTime = millis(); // Call this once only
#ifdef ORANGE_TX
if ( USARTC0.STATUS & USART_RXCIF_bm )
#elif defined STM32_BOARD
if ( USART2_BASE->SR & USART_SR_RXNE )
#else
if ( UCSR0A & ( 1 << RXC0 ) )
#endif
{
rxchar = UDR0 ;
BootCount += 1 ;
if ( ( lState == BOOT_WAIT_30_IDLE ) || ( lState == BOOT_WAIT_30_DATA ) )
{
if ( lState == BOOT_WAIT_30_IDLE ) // Waiting for 0x30
BootTimer = millisTime ; // Start timeout
if ( rxchar == 0x30 )
lState = BOOT_WAIT_20 ;
else
lState = BOOT_WAIT_30_DATA ;
}
else
if ( lState == BOOT_WAIT_20 && rxchar == 0x20 ) // Waiting for 0x20
lState = BOOT_READY ;
}
else // No byte received
{
if ( lState != BOOT_WAIT_30_IDLE ) // Something received
{
uint8_t time = millisTime - BootTimer ;
if ( time > 5 )
{
#ifdef STM32_BOARD
if ( BootCount > 4 )
#else
if ( BootCount > 2 )
#endif
{ // Run normally
NotBootChecking = 0xFF ;
Mprotocol_serial_init( 0 ) ;
}
else if ( lState == BOOT_READY )
{
#ifdef STM32_BOARD
#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */
#define __I volatile /*!< defines 'read only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
typedef struct
{
__I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register */
__IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register */
__IO uint32_t VTOR; /*!< Offset: 0x08 Vector Table Offset Register */
__IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register */
__IO uint32_t SCR; /*!< Offset: 0x10 System Control Register */
__IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register */
__IO uint8_t SHP[12]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */
__IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */
__IO uint32_t CFSR; /*!< Offset: 0x28 Configurable Fault Status Register */
__IO uint32_t HFSR; /*!< Offset: 0x2C Hard Fault Status Register */
__IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */
__IO uint32_t MMFAR; /*!< Offset: 0x34 Mem Manage Address Register */
__IO uint32_t BFAR; /*!< Offset: 0x38 Bus Fault Address Register */
__IO uint32_t AFSR; /*!< Offset: 0x3C Auxiliary Fault Status Register */
__I uint32_t PFR[2]; /*!< Offset: 0x40 Processor Feature Register */
__I uint32_t DFR; /*!< Offset: 0x48 Debug Feature Register */
__I uint32_t ADR; /*!< Offset: 0x4C Auxiliary Feature Register */
__I uint32_t MMFR[4]; /*!< Offset: 0x50 Memory Model Feature Register */
__I uint32_t ISAR[5]; /*!< Offset: 0x60 ISA Feature Register */
} SCB_Type;
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */
#define SCB_AIRCR_PRIGROUP_Msk (7ul << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
#define SCB_AIRCR_SYSRESETREQ_Msk (1ul << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
// NVIC_SystemReset
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */
asm("dsb");
while(1); /* wait until reset */
#else
cli(); // Disable global int due to RW of 16 bits registers
void (*p)();
#ifndef ORANGE_TX
p = (void (*)())0x3F00 ; // Word address (0x7E00 byte)
#else
p = (void (*)())0x4000 ; // Word address (0x8000 byte)
#endif
(*p)() ; // go to boot
#endif
}
else
{
lState = BOOT_WAIT_30_IDLE ;
BootCount = 0 ;
}
}
}
}
BootState = lState ;
}
#endif //CHECK_FOR_BOOTLOADER
#if defined(TELEMETRY)
void PPM_Telemetry_serial_init()
{
@ -1164,16 +1352,17 @@ static uint32_t random_value(void)
}
#endif
static uint32_t random_id(uint16_t adress, uint8_t create_new)
static uint32_t random_id(uint16_t address, uint8_t create_new)
{
#ifndef FORCE_GLOBAL_ID
uint32_t id=0;
if(eeprom_read_byte((EE_ADDR)(adress+10))==0xf0 && !create_new)
if(eeprom_read_byte((EE_ADDR)(address+10))==0xf0 && !create_new)
{ // TXID exists in EEPROM
for(uint8_t i=4;i>0;i--)
{
id<<=8;
id|=eeprom_read_byte((EE_ADDR)adress+i-1);
id|=eeprom_read_byte((EE_ADDR)address+i-1);
}
if(id!=0x2AD141A7) //ID with seed=0
return id;
@ -1188,11 +1377,16 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
#endif
for(uint8_t i=0;i<4;i++)
{
eeprom_write_byte((EE_ADDR)adress+i,id);
eeprom_write_byte((EE_ADDR)address+i,id);
id>>=8;
}
eeprom_write_byte((EE_ADDR)(adress+10),0xf0);//write bind flag in eeprom.
eeprom_write_byte((EE_ADDR)(address+10),0xf0);//write bind flag in eeprom.
return id;
#else
(void)address;
(void)create_new;
return FORCE_GLOBAL_ID;
#endif
}
/**************************/

View File

@ -27,6 +27,7 @@ uint8_t rf_setup;
void NRF24L01_Initialize()
{
rf_setup = 0x09;
prev_power = 0x00; // Make sure prev_power is inline with current power
XN297_SetScrambledMode(XN297_SCRAMBLED);
}
@ -133,8 +134,8 @@ void NRF24L01_SetBitrate(uint8_t bitrate)
// Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
prev_power=(rf_setup>>1)&0x03; // Make sure prev_power is inline with current power
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
prev_power = NRF_POWER_0; // Power setting was just reset. This will get updated in the next call to SetPower
}
/*
@ -168,9 +169,9 @@ void NRF24L01_SetPower()
#endif
if(IS_RANGE_FLAG_on)
power=NRF_POWER_0;
rf_setup = (rf_setup & 0xF9) | (power << 1);
if(prev_power != power)
{
rf_setup = (rf_setup & 0xF9) | (power << 1);
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
prev_power=power;
}

View File

@ -23,14 +23,14 @@
#define SFHSS_PACKET_LEN 13
#define SFHSS_TX_ID_LEN 2
uint8_t fhss_code; // 0-27
uint8_t fhss_code=0; // 0-27
enum {
SFHSS_START = 0x00,
SFHSS_CAL = 0x01,
SFHSS_DATA1 = 0x02, // do not change this value
SFHSS_DATA2 = 0x0B, // do not change this value
SFHSS_TUNE = 0x0F
SFHSS_DATA1 = 0x02,
SFHSS_DATA2 = 0x03,
SFHSS_TUNE = 0x04
};
#define SFHSS_FREQ0_VAL 0xC4
@ -122,58 +122,78 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
}
}
/*// Channel values are 10-bit values between 86 and 906, 496 is the middle.
// Values grow down and to the right.
static void __attribute__((unused)) SFHSS_build_data_packet()
{
#define spacer1 0x02
#define spacer2 (spacer1 << 4)
uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
uint16_t ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],86,906);
uint16_t ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],86,906);
uint16_t ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],86,906);
uint16_t ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],86,906);
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = 0;
packet[4] = 0;
packet[5] = (rf_ch_num << 3) | spacer1 | ((ch1 >> 9) & 0x01);
packet[6] = (ch1 >> 1);
packet[7] = (ch1 << 7) | spacer2 | ((ch2 >> 5) & 0x1F);
packet[8] = (ch2 << 3) | spacer1 | ((ch3 >> 9) & 0x01);
packet[9] = (ch3 >> 1);
packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0x1F);
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07);
packet[12] = (fhss_code << 6) | phase;
}
*/
// Channel values are 12-bit values between 1020 and 2020, 1520 is the middle.
// Futaba @140% is 2070...1520...970
// Values grow down and to the right.
static void __attribute__((unused)) SFHSS_build_data_packet()
{
uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
uint16_t ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],2020,1020);
uint16_t ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],2020,1020);
uint16_t ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],2020,1020);
uint16_t ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],2020,1020);
uint16_t ch1,ch2,ch3,ch4;
// command.bit0 is the packet number indicator: =0 -> SFHSS_DATA1, =1 -> SFHSS_DATA2
// command.bit1 is unknown but seems to be linked to the payload[0].bit0 but more dumps are needed: payload[0]=0x82 -> =0, payload[0]=0x81 -> =1
// command.bit2 is the failsafe transmission indicator: =0 -> normal data, =1->failsafe data
// command.bit3 is the channels indicator: =0 -> CH1-4, =1 -> CH5-8
//Coding below matches the Futaba T8J transmission scheme DATA1->CH1-4, DATA2->CH5-8, DATA1->CH5-8, DATA2->CH1-4,...
// XK, T10J and TM-FH are different with a classic DATA1->CH1-4, DATA2->CH5-8,...
//Failsafe is sent twice every couple of seconds (unknown but >5s)
uint8_t command= (phase == SFHSS_DATA1) ? 0 : 1; // Building packet for Data1 or Data2
counter+=command;
if( (counter&0x3FC) == 0x3FC )
{ // Transmit failsafe data twice every 7s
if( ((counter&1)^(command&1)) == 0 )
command|=0x04; // Failsafe
}
else
command|=0x02; // Assuming packet[0] == 0x81
counter&=0x3FF; // Reset failsafe counter
if(counter&1) command|=0x08; // Transmit lower and upper channels twice in a row
uint8_t ch_offset = ((command&0x08) >> 1) | ((command&0x04) << 1); // CH1..CH4 or CH5..CH8, if failsafe CH9..CH12 or CH13..CH16
ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],2020,1020);
ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],2020,1020);
ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],2020,1020);
ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],2020,1020);
if(command&0x04)
{ //Failsafe data are:
// 0 to 1023 -> no output on channel
// 1024-2047 -> hold output on channel
// 2048-4095 -> channel_output=(data&0x3FF)*5/4+880 in µs
// Notes:
// 2048-2559 -> does not look valid since it only covers the range from 1520µs to 2160µs
// 2560-3583 -> valid for any channel values from 880µs to 2160µs
// 3584-4095 -> looks to be used for the throttle channel with values ranging from 880µs to 1520µs
#ifdef SFHSS_FAILSAFE_CH9_16
ch1=((5360-ch1)<<2)/5; //((1520*2-ch1)<<2)/5+1856;
ch2=((5360-ch2)<<2)/5;
ch3=((5360-ch3)<<2)/5;
if((command&0x08)==0 && ch3<3072) // Throttle
ch3+=1024;
ch4=((5360-ch4)<<2)/5;
#else
ch1=1024;ch2=1024;ch4=1024; // All channels hold their positions
ch3=((command&0x08)==0)?3664:1024; // except throttle value set to 980µs
#endif
}
// XK [0]=0x81 [3]=0x00 [4]=0x00
// T8J [0]=0x81 [3]=0x42 [4]=0x07
// T10J [0]=0x81 [3]=0x0F [4]=0x09
// TM-FH [0]=0x82 [3]=0x9A [4]=0x06
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = 0x0f; //10J
packet[4] = 0x09; //10J
packet[3] = rx_tx_addr[2]; // ID?
packet[4] = rx_tx_addr[3]; // ID?
packet[5] = (rf_ch_num << 3) | ((ch1 >> 9) & 0x07);
packet[6] = (ch1 >> 1);
packet[7] = (ch1 << 7) | ((ch2 >> 5) & 0x7F );
packet[8] = (ch2 << 3) | ((ch3 >> 9) & 0x07);
packet[8] = (ch2 << 3) | ((ch3 >> 9) & 0x07 );
packet[9] = (ch3 >> 1);
packet[10] = (ch3 << 7) | ((ch4 >> 5) & 0x7F );
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07 );
packet[12] = (fhss_code << 6) | phase;
packet[12] = (fhss_code << 6) | command;
}
static void __attribute__((unused)) SFHSS_send_packet()
@ -197,28 +217,31 @@ uint16_t ReadSFHSS()
else
{
rf_ch_num = 0;
counter = 0;
phase = SFHSS_DATA1;
}
return 2000;
/* Work cycle, 6.8ms, second packet 1.65ms after first */
/* Work cycle: 6.8ms */
#define SFHSS_PACKET_PERIOD 6800
#define SFHSS_DATA2_TIMING 1630 // Adjust this value between 1600 and 1650 if your RX(s) are not operating properly
case SFHSS_DATA1:
SFHSS_build_data_packet();
SFHSS_send_packet();
phase = SFHSS_DATA2;
return 1650;
return SFHSS_DATA2_TIMING; // original 1650
case SFHSS_DATA2:
SFHSS_build_data_packet();
SFHSS_send_packet();
SFHSS_calc_next_chan();
phase = SFHSS_TUNE;
return 2000;
return (SFHSS_PACKET_PERIOD -2000 -SFHSS_DATA2_TIMING); // original 2000
case SFHSS_TUNE:
phase = SFHSS_DATA1;
SFHSS_tune_freq();
SFHSS_tune_chan_fast();
CC2500_SetPower();
return 3150;
return 2000; // original 3150
}
return 0;
}
@ -226,13 +249,13 @@ uint16_t ReadSFHSS()
// Generate internal id
static void __attribute__((unused)) SFHSS_get_tx_id()
{
uint32_t fixed_id;
// Some receivers (Orange) behaves better if they tuned to id that has
// no more than 6 consecutive zeros and ones
uint32_t fixed_id;
uint8_t run_count = 0;
// add guard for bit count
fixed_id = 1 ^ (MProtocol_id & 1);
for (uint8_t i = 0; i < 16; ++i)
for (uint8_t i = 0; i < 32; ++i)
{
fixed_id = (fixed_id << 1) | (MProtocol_id & 1);
MProtocol_id >>= 1;
@ -249,8 +272,10 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
run_count = 0;
}
// fixed_id = 0xBC11;
rx_tx_addr[0] = fixed_id >> 8;
rx_tx_addr[1] = fixed_id;
rx_tx_addr[0] = fixed_id >> 24;
rx_tx_addr[1] = fixed_id >> 16;
rx_tx_addr[2] = fixed_id >> 8;
rx_tx_addr[3] = fixed_id >> 0;
}
uint16_t initSFHSS()
@ -258,7 +283,7 @@ uint16_t initSFHSS()
BIND_DONE; // Not a TX bind protocol
SFHSS_get_tx_id();
fhss_code=rx_tx_addr[2]%28; // Initialize it to random 0-27 inclusive
fhss_code=random(0xfefefefe)%28; // Initialize it to random 0-27 inclusive
SFHSS_rf_init();
phase = SFHSS_START;

View File

@ -13,7 +13,6 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// compatible with Syma X5C-1, X11, X11C, X12 and for sub protocol X5C Syma X5C (original), X2
// Last sync with hexfet new_protocols/cx10_nrf24l01.c dated 2015-09-28
#if defined(SYMAX_NRF24L01_INO)
@ -30,6 +29,7 @@
#define SYMAX_FLAG_VIDEO 0x02
#define SYMAX_FLAG_PICTURE 0x04
#define SYMAX_FLAG_HEADLESS 0x08
#define SYMAX_XTRM_RATES 0x10
#define SYMAX_PAYLOADSIZE 10 // receive data pipes set to this size, but unused
#define SYMAX_MAX_PACKET_LENGTH 16 // X11,X12,X5C-1 10-byte, X5C 16-byte
@ -58,6 +58,7 @@ static void __attribute__((unused)) SYMAX_read_controls()
{
// Protocol is registered AETRF, that is
// Aileron is channel 1, Elevator - 2, Throttle - 3, Rudder - 4, Flip control - 5
// Extended (trim-added) Rates - 6, Photo - 7, Video - 8, Headless - 9
aileron = convert_channel_s8b(AILERON);
elevator = convert_channel_s8b(ELEVATOR);
throttle = convert_channel_8b(THROTTLE);
@ -67,6 +68,9 @@ static void __attribute__((unused)) SYMAX_read_controls()
// Channel 5
if (Servo_AUX1)
flags = SYMAX_FLAG_FLIP;
// Channel 6
if (Servo_AUX2)
flags |= SYMAX_XTRM_RATES;
// Channel 7
if (Servo_AUX3)
flags |= SYMAX_FLAG_PICTURE;
@ -75,7 +79,10 @@ static void __attribute__((unused)) SYMAX_read_controls()
flags |= SYMAX_FLAG_VIDEO;
// Channel 9
if (Servo_AUX5)
{
flags |= SYMAX_FLAG_HEADLESS;
flags &= ~SYMAX_XTRM_RATES; // Extended rates & headless incompatible
}
}
#define X5C_CHAN2TRIM(X) ((((X) & 0x80 ? 0xff - (X) : 0x80 + (X)) >> 2) + 0x20)
@ -98,9 +105,18 @@ static void __attribute__((unused)) SYMAX_build_packet_x5c(uint8_t bind)
packet[1] = rudder;
packet[2] = elevator ^ 0x80; // reversed from default
packet[3] = aileron;
packet[4] = X5C_CHAN2TRIM(rudder ^ 0x80);// drive trims for extra control range
if (flags & SYMAX_XTRM_RATES)
{ // drive trims for extra control range
packet[4] = X5C_CHAN2TRIM(rudder ^ 0x80);
packet[5] = X5C_CHAN2TRIM(elevator);
packet[6] = X5C_CHAN2TRIM(aileron ^ 0x80);
}
else
{
packet[4] = 0x00;
packet[5] = 0x00;
packet[6] = 0x00;
}
packet[7] = 0xae;
packet[8] = 0xa9;
packet[9] = 0x00;
@ -138,9 +154,15 @@ static void __attribute__((unused)) SYMAX_build_packet(uint8_t bind)
packet[2] = rudder;
packet[3] = aileron;
packet[4] = (flags & SYMAX_FLAG_VIDEO ? 0x80 : 0x00) | (flags & SYMAX_FLAG_PICTURE ? 0x40 : 0x00);
packet[5] = (elevator >> 2) | 0xc0; //always high rates (bit 7 is rate control)
packet[6] = (rudder >> 2) | (flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00);
packet[7] = (aileron >> 2) | (flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00);
packet[5] = 0xc0; //always high rates (bit 7 is rate control)
packet[6] = flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00;
packet[7] = flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00;
if (flags & SYMAX_XTRM_RATES)
{ // use trims to extend controls
packet[5] |= elevator >> 2;
packet[6] |= rudder >> 2;
packet[7] |= aileron >> 2;
}
packet[8] = 0x00;
}
packet[9] = SYMAX_checksum(packet);

View File

@ -31,6 +31,34 @@ uint8_t RetrySequence ;
uint8_t sport_counter=0;
uint8_t RxBt = 0;
uint8_t sport = 0;
#define MAX_PKTX 10
#define FX_BUFFERS 4
uint8_t pktx[MAX_PKTX];
uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS];
uint8_t indx;
//struct t_fx_rx_packet
//{
// uint8_t validSequence ;
// uint8_t count ;
// uint8_t payload[6] ;
//} ;
// Store for out of sequence packet
//struct t_fx_rx_packet FrskyxRxTelemetry ;
uint8_t FrskyxRxTelemetryValidSequence ;
struct t_fx_rx_frame
{
uint8_t valid ;
uint8_t count ;
uint8_t payload[6] ;
} ;
// Store for FrskyX telemetry
struct t_fx_rx_frame FrskyxRxFrames[4] ;
uint8_t NextFxFrameToForward ;
#endif
#if defined HUB_TELEMETRY
#define USER_MAX_BYTES 6
@ -40,10 +68,6 @@ uint8_t RetrySequence ;
#define START_STOP 0x7e
#define BYTESTUFF 0x7d
#define STUFF_MASK 0x20
#define MAX_PKTX 10
uint8_t pktx[MAX_PKTX];
uint8_t pktx1[MAX_PKTX];
uint8_t indx;
uint8_t frame[18];
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
@ -155,7 +179,8 @@ void frskySendStuffed()
void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
{
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len ==(pkt[0] + 3))
uint8_t clen = pkt[0] + 3 ;
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len == clen )
{
telemetry_link|=1; // Telemetry data is available
/*previous version
@ -205,19 +230,144 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
telemetry_lost=0;
if (protocol==MODE_FRSKYX)
{
if ((pktt[5] >> 4 & 0x0f) == 0x08)
uint16_t lcrc = crc_x(&pkt[3], len-7 ) ;
// if ( ( sub_protocol & 2 ) == 0 )
// {
// if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) )
// {
// lcrc = 0 ;
// }
// else
// {
// lcrc = 1 ;
// }
// }
// if ( lcrc == 0 )
if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) )
{
seq_last_sent = 8;
seq_last_rcvd = 0;
pass=0;
// Check if in sequence
if ( (pkt[5] & 0x0F) == 0x08 )
{
FrX_receive_seq = 0x08 ;
NextFxFrameToForward = 0 ;
FrskyxRxFrames[0].valid = 0 ;
FrskyxRxFrames[1].valid = 0 ;
FrskyxRxFrames[2].valid = 0 ;
FrskyxRxFrames[3].valid = 0 ;
}
else if ( (pkt[5] & 0x03) == (FrX_receive_seq & 0x03 ) )
{
// OK to process
struct t_fx_rx_frame *p ;
uint8_t count ;
p = &FrskyxRxFrames[FrX_receive_seq & 3] ;
count = pkt[6] ;
if ( count <= 6 )
{
p->count = count ;
for ( uint8_t i = 0 ; i < count ; i += 1 )
{
p->payload[i] = pkt[i+7] ;
}
}
else
{
if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
seq_last_rcvd = (seq_last_rcvd + 1) % 4;
else
pass=0;//reset if sequence wrong
p->count = 0 ;
}
p->valid = 1 ;
FrX_receive_seq = ( FrX_receive_seq + 1 ) & 0x03 ;
if ( FrskyxRxTelemetryValidSequence & 0x80 )
{
FrX_receive_seq = ( FrskyxRxTelemetryValidSequence + 1 ) & 3 ;
FrskyxRxTelemetryValidSequence &= 0x7F ;
}
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
// {
// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
// FrskyxRxTelemetry.validSequence &= 0x7F ;
// }
}
else
{
// Save and request correct packet
// struct t_fx_rx_packet *p ;
struct t_fx_rx_frame *q ;
uint8_t count ;
// pkt[4] RSSI
// pkt[5] sequence control
// pkt[6] payload count
// pkt[7-12] payload
pktt[6] = 0 ; // Don't process
if ( (pkt[5] & 0x03) == ( ( FrX_receive_seq +1 ) & 3 ) )
{
q = &FrskyxRxFrames[(pkt[5] & 0x03)] ;
count = pkt[6] ;
if ( count <= 6 )
{
q->count = count ;
for ( uint8_t i = 0 ; i < count ; i += 1 )
{
q->payload[i] = pkt[i+7] ;
}
}
else
{
q->count = 0 ;
}
q->valid = 1 ;
FrskyxRxTelemetryValidSequence = 0x80 | ( pkt[5] & 0x03 ) ;
}
// p = &FrskyxRxTelemetry ;
// count = pkt[6] ;
// if ( count <= 6 )
// {
// p->count = count ;
// for ( uint8_t i = 0 ; i < count ; i += 1 )
// {
// p->payload[i] = pkt[i+7] ;
// }
// p->validSequence = 0x80 | ( pkt[5] & 0x03 ) ;
// }
FrX_receive_seq = ( FrX_receive_seq & 0x03 ) | 0x04 ; // Request re-transmission
}
if (((pktt[5] >> 4) & 0x0f) == 0x08)
{
FrX_send_seq = 0 ;
// FrX_receive_seq = 0x08 ;
}
}
// packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
// if ( FrX_send_seq != 0x08 )
// {
// FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
// }
// if ((pktt[5] >> 4 & 0x0f) == 0x08)
// {
// seq_last_sent = 8;
// seq_last_rcvd = 0;
// pass=0;
// }
// else
// {
// if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
// seq_last_rcvd = (seq_last_rcvd + 1) % 4;
// else
// pass=0;//reset if sequence wrong
// }
}
#endif
}
@ -363,12 +513,25 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
0x34 0x0A 0xC3 0x56 0xF3
*/
const uint8_t PROGMEM Indices[] = { 0x00, 0xA1, 0x22, 0x83, 0xE4, 0x45,
0xC6, 0x67, 0x48, 0xE9, 0x6A, 0xCB,
0xAC, 0x0D, 0x8E, 0x2F, 0xD0, 0x71,
0xF2, 0x53, 0x34, 0x95, 0x16, 0xB7,
0x98, 0x39, 0xBA, 0x1B } ;
#ifdef MULTI_TELEMETRY
void sportSend(uint8_t *p)
{
multi_send_header(MULTI_TELEMETRY_SPORT, 9);
uint16_t crc_s = 0;
Serial_write(p[0]) ;
uint8_t x = p[0] ;
if ( x <= 0x1B )
{
x = pgm_read_byte_near( &Indices[x] ) ;
}
Serial_write(x) ;
for (uint8_t i = 1; i < 9; i++)
{
if (i == 8)
@ -462,7 +625,13 @@ void sportSendFrame()
{
for (i=0;i<FRSKY_SPORT_PACKET_SIZE;i++)
frame[i]=pktx1[i];
sport=0;
sport -= 1 ;
if ( sport )
{
uint8_t j = sport * FRSKY_SPORT_PACKET_SIZE ;
for (i=0;i<j;i++)
pktx1[i] = pktx1[i+FRSKY_SPORT_PACKET_SIZE] ;
}
break;
}
else
@ -506,19 +675,20 @@ void proces_sport_data(uint8_t data)
} // end switch
if (indx >= FRSKY_SPORT_PACKET_SIZE)
{//8 bytes no crc
if ( sport )
{
// overrun!
}
else
if ( sport < FX_BUFFERS )
{
uint8_t dest = sport * FRSKY_SPORT_PACKET_SIZE ;
uint8_t i ;
for ( i = 0 ; i < FRSKY_SPORT_PACKET_SIZE ; i += 1 )
{
pktx1[i] = pktx[i] ; // Double buffer
pktx1[dest++] = pktx[i] ; // Triple buffer
}
sport = 1;//ok to send
sport += 1 ;//ok to send
}
// else
// {
// // Overrun
// }
pass = 0;//reset
}
}
@ -534,11 +704,14 @@ void TelemetryUpdate()
h = SerialControl.head ;
t = SerialControl.tail ;
if ( h >= t )
t += 128 - h ;
t += 192 - h ;
else
t -= h ;
// if ( t < 32 )
if ( t < 64 )
{
return ;
}
#else
uint8_t h ;
uint8_t t ;
@ -549,7 +722,9 @@ void TelemetryUpdate()
else
t -= h ;
if ( t < 32 )
{
return ;
}
#endif
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
{
@ -566,15 +741,62 @@ void TelemetryUpdate()
#if defined SPORT_TELEMETRY
if (protocol==MODE_FRSKYX)
{ // FrSkyX
// struct t_fx_rx_frame *p ;
// uint8_t count ;
for(;;)
{
struct t_fx_rx_frame *p ;
uint8_t count ;
p = &FrskyxRxFrames[NextFxFrameToForward] ;
if ( p->valid )
{
count = p->count ;
for (uint8_t i=0; i < count ; i++)
proces_sport_data(p->payload[i]) ;
p->valid = 0 ; // Sent on
NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ;
}
else
{
break ;
}
}
// p = &FrskyxRxFrames[NextFxFrameToForward] ;
// if ( p->valid )
// {
// count = p->count ;
// for (uint8_t i=0; i < count ; i++)
// proces_sport_data(p->payload[i]) ;
// p->valid = 0 ; // Sent on
// NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ;
// }
if(telemetry_link)
{
if(pktt[4] & 0x80)
RX_RSSI=pktt[4] & 0x7F ;
else
RxBt = (pktt[4]<<1) + 1 ;
if(pktt[6] && pktt[6]<=6)
for (uint8_t i=0; i < pktt[6]; i++)
proces_sport_data(pktt[7+i]);
// if(pktt[6] && pktt[6]<=6)
// {
// for (uint8_t i=0; i < pktt[6]; i++)
// proces_sport_data(pktt[7+i]);
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
// {
// // Process out of sequence packet
// for (uint8_t i=0; i < FrskyxRxTelemetry.count ; i++)
// {
// proces_sport_data( FrskyxRxTelemetry.payload[i] ) ;
// }
//// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
// FrskyxRxTelemetry.validSequence = 0 ;
// }
// }
telemetry_link=0;
}
uint32_t now = micros();
@ -928,7 +1150,13 @@ ISR(TIMER0_COMPB_vect)
{
GPIOR0 = ptr->data[ptr->tail] ;
GPIOR2 = ptr->data[ptr->tail+1] ;
ptr->tail = ( ptr->tail + 2 ) & 0x7F ;
uint8_t nextTail ;
nextTail = ptr->tail + 2 ;
if ( nextTail > 192 )
{
nextTail = 0 ;
}
ptr->tail = nextTail ;
GPIOR1 = 8 ;
OCR0A = OCR0B + 40 ;
OCR0B = OCR0A + 8 * 20 ;

View File

@ -4,7 +4,7 @@
#endif
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
//Atmega328p
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
#error You must select one of these boards: "Multi 4-in-1", "Arduino Pro or Pro Mini" or "Arduino Mini"
#endif
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
@ -18,6 +18,14 @@
#endif
#endif
//Change/Force configuration for the bootloader option
#if defined ARDUINO_MULTI_FLASH_FROM_TX
#define CHECK_FOR_BOOTLOADER
#endif
#if defined ARDUINO_MULTI_NO_BOOT
#undef CHECK_FOR_BOOTLOADER
#endif
//Change/Force configuration if OrangeTX
#ifdef ORANGE_TX
#undef ENABLE_PPM // Disable PPM for OrangeTX module
@ -70,6 +78,7 @@
#undef HONTAI_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef GW008_NRF24L01_INO
#undef DM002_NRF24L01_INO
#undef CABELL_NRF24L01_INO
#endif
@ -79,6 +88,7 @@
#undef AFHDS2A_FW_TELEMETRY
#undef AFHDS2A_HUB_TELEMETRY
#undef BAYANG_HUB_TELEMETRY
#undef CABELL_HUB_TELEMETRY
#undef HUBSAN_HUB_TELEMETRY
#undef HUB_TELEMETRY
#undef SPORT_TELEMETRY
@ -92,6 +102,9 @@
#if not defined(BAYANG_NRF24L01_INO)
#undef BAYANG_HUB_TELEMETRY
#endif
#if not defined(CABELL_NRF24L01_INO)
#undef CABELL_HUB_TELEMETRY
#endif
#if not defined(HUBSAN_A7105_INO)
#undef HUBSAN_HUB_TELEMETRY
#endif
@ -108,7 +121,7 @@
#if not defined(DSM_CYRF6936_INO)
#undef DSM_TELEMETRY
#endif
#if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS)
#if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#endif

View File

@ -49,6 +49,13 @@
//The goal is to prevent binding other people's model when powering up the TX, changing model or scanning through protocols.
#define WAIT_FOR_BIND
/*************************/
/*** BOOTLOADER USE ***/
/*************************/
//Allow flashing multimodule directly with TX(erky9x or opentx modified firmwares)
//Check https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/BootLoaders
//To enable this feature remove the "//" on the next line. It is automatically enabled/disabled when you use the AVR Multi boards.
//#define CHECK_FOR_BOOTLOADER
/****************/
/*** RF CHIPS ***/
@ -71,6 +78,22 @@
//#define NRF24L01_ENABLE_LOW_POWER
/*****************/
/*** GLOBAL ID ***/
/*****************/
//A global ID is used by most protocols to bind and retain the bind to models. To prevent duplicate IDs, it is automatically
// generated using a random 32 bits number the first time the eeprom is initialized.
//If you have 2 Multi modules which you want to share the same ID so you can use either to control the same RC model
// then you can force the ID to a certain known value using the lines below.
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
//#define FORCE_GLOBAL_ID 0x12345678
//Protocols using the CYRF6936 (DSM, Devo, Walkera...) are using the CYRF ID instead which should prevent duplicated IDs.
//If you have 2 Multi modules which you want to share the same ID so you can use either to control the same RC model
// then you can force the ID to a certain known value using the lines below.
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
//#define FORCE_CYRF_ID "\x12\x34\x56\x78\x9A\xBC"
/****************************/
/*** PROTOCOLS TO INCLUDE ***/
/****************************/
@ -115,8 +138,49 @@
#define HONTAI_NRF24L01_INO
#define Q303_NRF24L01_INO
#define GW008_NRF24L01_INO
#define DM002_NRF24L01_INO
#define CABELL_NRF24L01_INO
/**************************/
/*** FAILSAFE SETTINGS ***/
/**************************/
//SHFSS failsafe is by default set to all channels hold their positions except throttle forced to low (980µs)
//You can uncomment the setting below to use channels 9(1) to 16(8) instead
//#define SFHSS_FAILSAFE_CH9_16
#define AFHDS2A_FAILSAFE
#ifdef AFHDS2A_FAILSAFE
/*
Failsafe Min/Max values 962 <-> 2038
*/
const int8_t AFHDS2AFailsafeMIN = -105;
const int8_t AFHDS2AFailsafeMAX = 105;
//
const int8_t AFHDS2AFailsafe[14]= {
/*
Failsafe examples
988 <-> 2012µs -100% = 988 = 1500 + (2012-988)/2 * (-100/100) = 1500 - 512 = 988
988 <-> 2012µs 0% = 1500 = 1500 + (2012-988)/2 * ( 0/100) = 1500 + 0 = 1500
988 <-> 2012µs 100% = 2012 = 1500 + (2012-988)/2 * ( 100/100) = 1500 + 512 = 2012
988 <-> 2012µs -105% = 962 = 1500 + (2012-988)/2 * (-105/100) = 1500 - 538 = 962
*/
/* ch 1 */ -1,
/* ch 2 */ -1,
/* ch 3 */ -105,
/* ch 4 */ -1,
/* ch 5 */ -1,
/* ch 6 */ -1,
/* ch 7 */ -1,
/* ch 8 */ -1,
/* ch 9 */ -1,
/* ch 10 */ -1,
/* ch 11 */ -1,
/* ch 12 */ -1,
/* ch 13 */ -1,
/* ch 14 */ -1
};
#endif
/**************************/
/*** TELEMETRY SETTINGS ***/
/**************************/
@ -149,7 +213,7 @@
#define AFHDS2A_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define BAYANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
/****************************/
/*** SERIAL MODE SETTINGS ***/
@ -161,7 +225,6 @@
//If you do not plan to use the Serial mode comment this line using "//" to save Flash space
#define ENABLE_SERIAL
/*************************/
/*** PPM MODE SETTINGS ***/
/*************************/
@ -211,8 +274,8 @@ const PPM_Parameters PPM_prot[15]= {
/* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 5 */ {MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 6 */ {MODE_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 6 */ {MODE_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
/* 7 */ {MODE_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 6 },
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {MODE_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 10 */ {MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
@ -288,6 +351,7 @@ const PPM_Parameters PPM_prot[15]= {
MODE_BAYANG
BAYANG
H8S3D
X16_AH
MODE_ESKY
NONE
MODE_MT99XX
@ -340,6 +404,8 @@ const PPM_Parameters PPM_prot[15]= {
CX10WD
MODE_GW008
NONE
MODE_DM002
NONE
MODE_CABELL
CABELL_V3
CABELL_V3_TELEMETRY

24
Multiprotocol/_MyConfig.h Normal file
View File

@ -0,0 +1,24 @@
//#define FORCE_GLOBAL_ID 0x12345678
#if not defined STM32_BOARD
// #undef AFHDS2A_A7105_INO
// #undef DEVO_CYRF6936_INO
// #undef J6PRO_CYRF6936_INO
// #undef WK2x01_CYRF6936_INO
// #undef FRSKYV_CC2500_INO
// #undef FRSKYX_CC2500_INO
// #undef KN_NRF24L01_INO
// #undef SLT_NRF24L01_INO
// #undef FY326_NRF24L01_INO
// #undef FQ777_NRF24L01_INO
// #undef ASSAN_NRF24L01_INO
// #undef HONTAI_NRF24L01_INO
// #undef Q303_NRF24L01_INO
// #undef GW008_NRF24L01_INO
// #undef DM002_NRF24L01_INO
// #undef CABELL_NRF24L01_INO
#endif

View File

@ -1,4 +1,4 @@
#Protocols details
# Protocols details
Here are detailed descriptions of every supported protocols (sorted by RF modules) as well as the available options for each protocol.
If you want to see a list of models that use these protocols see the [Models](docs/Models.md) page.
@ -37,24 +37,23 @@ Dial|Protocol|Sub_protocol|RX Num|Power|Auto Bind|Option|RF Module
1. The transmitter will automatically initiate a bind sequence on power up. This is for models where the receiver expects to rebind every time it is powered up. In these protocols you do not need to press the bind button at power up to bind, it will be done automatically.
2. Enable Bind from channel feature:
* Bind from channel can be globally enabled/disabled in _config.h using ENABLE_BIND_CH.
* Bind from channel can be locally enabled/disabled by setting Autobind to Y/N per model for serial or per dial switch number for ppm.
* Bind channel can be choosen on any channel between 5 and 16 using BIND_CH in _config.h.
* Bind will only happen if all these elements are happening at the same time:
* Bind from channel can be globally enabled/disabled in _config.h using ENABLE_BIND_CH.
* Bind from channel can be locally enabled/disabled by setting Autobind to Y/N per model for serial or per dial switch number for ppm.
* Bind channel can be choosen on any channel between 5 and 16 using BIND_CH in _config.h.
* Bind will only happen if all these elements are happening at the same time:
- Autobind = Y
- Throttle = LOW (<-95%)
- Bind channel is going from -100% to +100%
* Additional notes:
- It's recommended to combine Throttle cut with another button to drive the bind channel. This will prevent to launch a bind while flying...
- Bind channel does not have to be assigned to a free channel. Since it only acts when Throttle is Low (and throttle cut active), it could be used on the same channel as Flip for example since you are not going to flip your model when Throttle is low... Same goes for RTH and such other features.
- Using channel 16 for the bind channel seems the most relevant as only one protocol so far is using 16 channels which is FrSkyX. But even on FrSkyX this feature won't have any impact since there is NO valid reason to have Autobind set to Y for such a protocol.
***
#A7105 RF Module
# A7105 RF Module
##FLYSKY - *1*
## FLYSKY - *1*
Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
@ -63,30 +62,30 @@ A|E|T|R|CH5|CH6|CH7|CH8
Note that the RX ouput will be AETR.
###Sub_protocol Flysky - *0*
### Sub_protocol Flysky - *0*
###Sub_protocol V9X9 - *1*
### Sub_protocol V9X9 - *1*
CH5|CH6|CH7|CH8
---|---|---|---
FLIP|LIGHT|PICTURE|VIDEO
###Sub_protocol V6X6 - *2*
### Sub_protocol V6X6 - *2*
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---
FLIP|LIGHT|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
###Sub_protocol V912 - *3*
### Sub_protocol V912 - *3*
CH5|CH6
---|---
BTMBTN|TOPBTN
###Sub_protocol CX20 - *4*
### Sub_protocol CX20 - *4*
Model: Cheerson Cx-20
CH5|CH6|CH7
---|---|---
##FLYSKY AFHDS2A - *28*
## FLYSKY AFHDS2A - *28*
Extended limits supported
Telemetry enabled for battery voltage and RX&TX RSSI using FrSky Hub protocol
@ -101,12 +100,12 @@ A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
Note that the RX ouput will be AETR.
###Sub_protocol PWM_IBUS - *0*
###Sub_protocol PPM_IBUS - *1*
###Sub_protocol PWM_SBUS - *2*
###Sub_protocol PPM_SBUS - *3*
### Sub_protocol PWM_IBUS - *0*
### Sub_protocol PPM_IBUS - *1*
### Sub_protocol PWM_SBUS - *2*
### Sub_protocol PPM_SBUS - *3*
##HUBSAN - *2*
## HUBSAN - *2*
Models: Hubsan H102D, H107/L/C/D and Hubsan H107P/C+/D+
Autobind protocol
@ -120,9 +119,9 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
***
#CC2500 RF Module
# CC2500 RF Module
##FRSKYV = FrSky 1 way - *25*
## FRSKYV = FrSky 1 way - *25*
Models: FrSky receivers V8R4, V8R7 and V8FR.
Extended limits supported
@ -137,7 +136,7 @@ CH1|CH2|CH3|CH4
---|---|---|---
CH1|CH2|CH3|CH4
##FRSKYD - *3*
## FRSKYD - *3*
Models: FrSky receivers D4R and D8R. DIY RX-F801 and RX-F802 receivers. Also known as D8.
Extended limits supported
@ -154,7 +153,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
##FRSKYX - *15*
## FRSKYX - *15*
Models: FrSky receivers X4R, X6R and X8R. Also known as D16.
Extended limits supported
@ -167,35 +166,35 @@ Option for this protocol is fine frequency tuning. This value is different for e
- set the value to half way between min and max.
- [video showing the process](https://youtu.be/C483uNWwAaM)
###Sub_protocol CH_16 - *0*
### Sub_protocol CH_16 - *0*
FCC protocol 16 channels @18ms.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
###Sub_protocol CH_8 - *1*
### Sub_protocol CH_8 - *1*
FCC protocol 8 channels @9ms.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
###Sub_protocol EU_16 - *2*
### Sub_protocol EU_16 - *2*
EU-LBT protocol 16 channels @18ms. Note that the LBT part is not implemented, the TX transmits right away.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
###Sub_protocol EU_8 - *3*
### Sub_protocol EU_8 - *3*
EU-LBT protocol 8 channels @9ms. Note that the LBT part is not implemented, the TX transmits right away.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
##SFHSS - *21*
## SFHSS - *21*
Models: Futaba RXs and XK models.
Extended limits supported
@ -210,10 +209,12 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
***
#CYRF6936 RF Module
Channels 9 to 16 are used as failsafe values for the channels 1 to 8.
##DEVO - *7*
***
# CYRF6936 RF Module
## DEVO - *7*
Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
@ -243,13 +244,13 @@ Bind procedure using PPM:
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the dial number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
##WK2X01 - *30*
## WK2X01 - *30*
Extended limits supported
Autobind protocol
Note: RX ouput will always be AETR independently of the input AETR, RETA...
###Sub_protocol WK2801 - *0*
### Sub_protocol WK2801 - *0*
This roughly corresponds to the number of channels supported, but many of the newer 6-channel receivers actually support the WK2801 protocol. It is recommended to try the WK2801 protocol 1st when working with older Walkera models before attempting the WK2601 or WK2401 mode, as the WK2801 is a superior protocol. The WK2801 protocol supports up to 8 channels.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
@ -277,28 +278,28 @@ Bind procedure using PPM:
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the dial number. Which means that you can have multiple dial numbers set to the same protocol WK2X01 and sub_protocol WK2801 with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match.
###Sub_protocol WK2401 - *1*
### Sub_protocol WK2401 - *1*
The WK2401 protocol is used to control older Walkera models.
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
###Sub_protocol W6_5_1 - *2*
### Sub_protocol W6_5_1 - *2*
WK2601 5+1: AIL, ELE, THR, RUD, GYRO (ch 7) are proportional. Gear (ch 5) is binary. Ch 6 is disabled
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|GEAR|DIS|GYRO
###Sub_protocol W6_6_1 - *3*
### Sub_protocol W6_6_1 - *3*
WK2601 6+1: AIL, ELE, THR, RUD, COL (ch 6), GYRO (ch 7) are proportional. Gear (ch 5) is binary. **This mode is highly experimental.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|GEAR|COL|GYRO
###Sub_protocol W6_HEL - *4* and W6HEL_I - *5*
### Sub_protocol W6_HEL - *4* and W6HEL_I - *5*
WK2601 Heli: AIL, ELE, THR, RUD, GYRO are proportional. Gear (ch 5) is binary. COL (ch 6) is linked to Thr. If Ch6 >= 0, the receiver will apply a 3D curve to the Thr. If Ch6 < 0, the receiver will apply normal curves to the Thr. The value of Ch6 defines the ratio of COL to THR.
W6HEL_I: Invert COL servo
@ -309,7 +310,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|GEAR|COL|GYRO
##DSM - *6*
## DSM - *6*
Extended limits supported
Telemetry enabled for TSSI and plugins
@ -324,31 +325,31 @@ Notes:
- model/type/number of channels indicated on the RX can be different from what the RX is in fact wanting to see. So don't hesitate to test different combinations until you have something working. Using Auto is the best way to find these settings.
- RX ouput will always be TAER independently of the input AETR, RETA...
###Sub_protocol DSM2_22 - *0*
### Sub_protocol DSM2_22 - *0*
DSM2, Resolution 1024, refresh rate 22ms
###Sub_protocol DSM2_11 - *1*
### Sub_protocol DSM2_11 - *1*
DSM2, Resolution 2048, refresh rate 11ms
###Sub_protocol DSMX_22 - *2*
### Sub_protocol DSMX_22 - *2*
DSMX, Resolution 2048, refresh rate 22ms
###Sub_protocol DSMX_11 - *3*
### Sub_protocol DSMX_11 - *3*
DSMX, Resolution 2048, refresh rate 11ms
###Sub_protocol AUTO - *4*
### Sub_protocol AUTO - *4*
The "AUTO" feature enables the TX to automatically choose what are the best settings for your DSM RX and update your model protocol settings accordingly.
The current radio firmware which are able to use the "AUTO" feature are ersky9x (9XR Pro, 9Xtreme, Taranis, ...) and er9x for M128 (9XR) and M2561.
For these firmwares, you must have a telemetry enabled TX and you have to make sure you set the Telemetry "Usr proto" to "DSMx".
Also on er9x you will need to be sure to match the polarity of the telemetry serial (normal or inverted by bitbashing), while on ersky9x you can set "Invert COM1" accordinlgy.
##J6Pro - *22*
## J6Pro - *22*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
***
#NRF24L01 RF Module
# NRF24L01 RF Module
##ASSAN - *24*
## ASSAN - *24*
Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
@ -357,47 +358,69 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
The transmitter must be close to the receiver while binding.
##BAYANG - *14*
## BAYANG - *14*
Models: EAchine H8(C) mini, BayangToys X6/X7/X9, JJRC JJ850, Floureon H101 ...
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
A|E|T|R|FLIP|RTH|PICTURE|VIDEO|HEADLESS|INVERTED
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|---
A|E|T|R|FLIP|RTH|PICTURE|VIDEO|HEADLESS|INVERTED|TAKE_OFF
###Sub_protocol BAYANG - *0*
### Sub_protocol BAYANG - *0*
Option=0 -> normal Bayang protocol
Option=1 -> enable telemetry with [Silverxxx firmware](https://github.com/silver13/H101-acro/tree/master). Value returned to the TX using FrSkyD Hub are RX RSSI, TX RSSI, A1=uncompensated battery voltage, A2=compensated battery voltage
###Sub_protocol H8S3D - *1*
### Sub_protocol H8S3D - *1*
Model: H8S 3D
Same channels assignement as above.
##CG023 - *13*
### Sub_protocol X16_AH - *2*
Model: X16 AH
Same channels assignement as above.
## Cabell - *34*
Homegrown protocol with variable number of channels (4-16) and telemetry (RSSI, V1, V2).
RXs details are located here: https://github.com/soligen2010/RC_RX_CABELL_V3_FHSS
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
### Sub_protocol CABELL_V3 - *0*
### Sub_protocol CABELL_V3_TELEMETRY - *1*
### Sub_protocol CABELL_SET_FAIL_SAFE - *6*
### Sub_protocol CABELL_UNBIND - *7*
## CG023 - *13*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
###Sub_protocol CG023 - *0*
### Sub_protocol CG023 - *0*
Models: EAchine CG023/CG031/3D X4
###Sub_protocol YD829 - *1*
### Sub_protocol YD829 - *1*
Models: Attop YD-822/YD-829/YD-829C ...
CH5|CH6|CH7|CH8|CH9
---|---|---|---|---
FLIP||PICTURE|VIDEO|HEADLESS
###Sub_protocol H8_3D - *2*
### Sub_protocol H8_3D - *2*
Models: EAchine H8 mini 3D, JJRC H20/H22/H11D
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---
---|---|---|---|---|---|---|---|---
FLIP|LIGTH|PICTURE|VIDEO|OPT1|OPT2|CAL1|CAL2|GIMBAL
JJRC H20: OPT1=Headless, OPT2=RTH
@ -409,7 +432,7 @@ H8 3D: OPT1=RTH then press a direction to enter headless mode (like stock TX), O
CAL1: H8 3D acc calib, H20 headless calib
CAL2: H11D/H20 acc calib
##CX10 - *12*
## CX10 - *12*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6
@ -418,12 +441,12 @@ A|E|T|R|FLIP|RATE
Rate: -100%=rate 1, 0%=rate 2, +100%=rate 3
###Sub_protocol GREEN - *0*
### Sub_protocol GREEN - *0*
Models: Cheerson CX-10 green pcb
Same channels assignement as above.
###Sub_protocol BLUE - *1*
### Sub_protocol BLUE - *1*
Models: Cheerson CX-10 blue pcb & some newer red pcb, CX-10A, CX-10C, CX11, CX12, Floureon FX10, JJRC DHD D1
CH5|CH6|CH7|CH8
@ -432,66 +455,59 @@ FLIP|RATE|PICTURE|VIDEO
Rate: -100%=rate 1, 0%=rate 2, +100%=rate 3 or headless for CX-10A
###Sub_protocol DM007 - *2*
### Sub_protocol DM007 - *2*
CH5|CH6|CH7|CH8|CH9
---|---|---|---|---
FLIP|MODE|PICTURE|VIDEO|HEADLESS
###Sub_protocol JC3015_1 - *4*
### Sub_protocol JC3015_1 - *4*
CH5|CH6|CH7|CH8
---|---|---|---
FLIP|MODE|PICTURE|VIDEO
###Sub_protocol JC3015_2 - *5*
### Sub_protocol JC3015_2 - *5*
CH5|CH6|CH7|CH8
---|---|---|---
FLIP|MODE|LED|DFLIP
###Sub_protocol MK33041 - *6*
### Sub_protocol MK33041 - *6*
CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---
FLIP|MODE|PICTURE|VIDEO|HEADLESS|RTH
##Q2X2 - *29*
###Sub_protocol Q222 - *0*
Models: Q222 v1 and V686 v2
## DM002 - *33*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|MODULE2|MODULE1|HEADLESS|RTH|XCAL|YCAL
**Only 2 TX IDs available, change RX_Num value 0-1 to cycle through them**
###Sub_protocol Q242 - *1* and Q282 - *2*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LED|CAMERA1|CAMERA2|HEADLESS|RTH|RATE_LOW
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
Model: JXD 509 is using Q282 with CH12=Start/Stop motors
##ESKY - *16*
## ESKY - *16*
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GYRO|PITCH
##FY326 - *20*
## FY326 - *20*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT|CALIBRATE
##FQ777 - *23*
## FQ777 - *23*
Model: FQ777-124 (with SV7241A)
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
##GW008 - *32*
## GW008 - *32*
Model: Global Drone GW008 from Banggood
There are 3 versions of this small quad, this protocol is for the one with a XNS104 IC in the stock Tx and PAN159CY IC in the quad. The xn297 version is compatible with the CX10 protocol (green pcb). The LT8910 version is not supported yet.
@ -500,96 +516,96 @@ CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|FLIP
##HISKY - *4*
###Sub_protocol Hisky - *0*
## HISKY - *4*
### Sub_protocol Hisky - *0*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|GEAR|PITCH|GYRO|CH8
GYRO: -100%=6G, +100%=3G
###Sub_protocol HK310 - *1*
### Sub_protocol HK310 - *1*
Models: RX HK-3000, HK3100 and XY3000 (TX are HK-300, HK-310 and TL-3C)
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
|||T|R|AUX|T_FSAFE|R_FSAFE|AUX_FSAFE
| | |T|R|AUX|T_FSAFE|R_FSAFE|AUX_FSAFE
##KN - *9*
## KN - *9*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|DR|THOLD|IDLEUP|GYRO|Ttrim|Atrim|Etrim
Dual Rate: +100%=full range, Throttle Hold: +100%=hold, Idle Up: +100%=3D, GYRO: -100%=6G, +100%=3G
###Sub_protocol WLTOYS - *0*
###Sub_protocol FEILUN - *1*
### Sub_protocol WLTOYS - *0*
### Sub_protocol FEILUN - *1*
Same channels assignement as above.
##HONTAI - *26*
## HONTAI - *26*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|CAL
###Sub_protocol HONTAI - *0*
###Sub_protocol JJRCX1 - *1*
### Sub_protocol HONTAI - *0*
### Sub_protocol JJRCX1 - *1*
CH6|
---|
ARM|
###Sub_protocol X5C1 clone - *2*
### Sub_protocol X5C1 clone - *2*
###Sub_protocol FQ777_951 - *3*
### Sub_protocol FQ777_951 - *3*
##MJXQ - *18*
## MJXQ - *18*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|AUTOFLIP|PAN|TILT
###Sub_protocol WLH08 - *0*
###Sub_protocol X600 - *1*
### Sub_protocol WLH08 - *0*
### Sub_protocol X600 - *1*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
###Sub_protocol X800 - *2*
### Sub_protocol X800 - *2*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
###Sub_protocol H26D - *3*
### Sub_protocol H26D - *3*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
###Sub_protocol E010 - *4*
### Sub_protocol E010 - *4*
15 TX IDs available, change RX_Num value 0..14 to cycle through them
If the E010 does not respond well to inputs or hard to bind, set Power to Low.
###Sub_protocol H26WH - *5*
### Sub_protocol H26WH - *5*
CH6|
---|
ARM|
Only 1 TX ID available
##MT99XX - *17*
## MT99XX - *17*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS
###Sub_protocol MT99 - *0*
### Sub_protocol MT99 - *0*
Models: MT99xx
###Sub_protocol H7 - *1*
### Sub_protocol H7 - *1*
Models: Eachine H7, Cheerson CX023
###Sub_protocol YZ - *2*
### Sub_protocol YZ - *2*
Model: Yi Zhan i6S
Only one model can be flown at the same time since the ID is hardcoded.
###Sub_protocol LS - *3*
### Sub_protocol LS - *3*
Models: LS114, 124, 215
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|INVERT|PICTURE|VIDEO|HEADLESS
###Sub_protocol FY805 - *4*
### Sub_protocol FY805 - *4*
Model: FY805
Only 1 ID available
@ -598,14 +614,30 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP||||HEADLESS
##Q303 - *31*
## Q2X2 - *29*
### Sub_protocol Q222 - *0*
Models: Q222 v1 and V686 v2
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|MODULE2|MODULE1|HEADLESS|RTH|XCAL|YCAL
### Sub_protocol Q242 - *1* and Q282 - *2*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
Model: JXD 509 is using Q282 with CH12=Start/Stop motors
## Q303 - *31*
Autobind protocol
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
###Sub_protocol Q303 - *0*
### Sub_protocol Q303 - *0*
Q303 warning: this sub_protocol is known to not work at all/properly with 4in1 RF modules.
CH5|CH6|CH7|CH8|CH9|CH10|CH11
@ -614,7 +646,7 @@ AHOLD|FLIP|PICTURE|VIDEO|HEADLESS|RTH|GIMBAL
GIMBAL needs 3 position -100%/0%/100%
###Sub_protocol CX35 - *1*
### Sub_protocol CX35 - *1*
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
ARM|VTX|PICTURE|VIDEO||RTH|GIMBAL
@ -625,14 +657,14 @@ Each toggle of VTX will increment the channel.
Gimbal is full range.
###Sub_protocol CX10D - *2* and Sub_protocol CX10WD - *3*
### Sub_protocol CX10D - *2* and Sub_protocol CX10WD - *3*
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
##Shenqi - *19*
## Shenqi - *19*
Autobind protocol
Model: Shenqiwei 1/20 Mini Motorcycle
@ -643,57 +675,55 @@ CH1|CH2|CH3|CH4
Throttle +100%=full forward,0%=stop,-100%=full backward.
##SLT - *11*
## SLT - *11*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GEAR|PITCH
##Symax - *10*
## Symax - *10*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP||PICTURE|VIDEO|HEADLESS
A|E|T|R|FLIP|RATES|PICTURE|VIDEO|HEADLESS
###Sub_protocol SYMAX - *0*
### Sub_protocol SYMAX - *0*
Models: Syma X5C-1/X11/X11C/X12
###Sub_protocol SYMAX5C - *1*
### Sub_protocol SYMAX5C - *1*
Model: Syma X5C (original) and X2
##V2X2 - *5*
## V2X2 - *5*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS|MAG_CAL_X|MAG_CAL_Y
###Sub_protocol V2x2 - *0*
### Sub_protocol V2x2 - *0*
Models: WLToys V202/252/272, JXD 385/388, JJRC H6C, Yizhan Tarantula X6 ...
PICTURE: also automatic Missile Launcher and Hoist in one direction
VIDEO: also Sprayer, Bubbler, Missile Launcher(1), and Hoist in the other dir
###Sub_protocol JXD506 - *1*
### Sub_protocol JXD506 - *1*
Model: JXD 506
CH10|CH11|CH12
---|---|---
Start/Stop|EMERGENCY|CAMERA_UP/DN
##YD717 - *8*
## YD717 - *8*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
###Sub_protocol YD717 - *0*
###Sub_protocol SKYWLKR - *1*
###Sub_protocol SYMAX4 - *2*
###Sub_protocol XINXUN - *3*
###Sub_protocol NIHUI - *4*
### Sub_protocol YD717 - *0*
### Sub_protocol SKYWLKR - *1*
### Sub_protocol SYMAX4 - *2*
### Sub_protocol XINXUN - *3*
### Sub_protocol NIHUI - *4*
Same channels assignement as above.

View File

@ -18,8 +18,8 @@ The source code is partly based on the [Deviation TX project](http://www.deviati
1. [Transmitters and serial/telemetry options](docs/Transmitters.md)
1. [Module Hardware options](docs/Hardware.md)
1. Compiling and programming the module
* [4in1/DIY Mutliprotocol module based on ATmega328](docs/Compiling.md)
* [DIY Mutliprotocol module based on STM32](docs/Compiling_STM32.md)
* [4in1/DIY Multiprotocol module based on ATmega328](docs/Compiling.md)
* [DIY Multiprotocol module based on STM32](docs/Compiling_STM32.md)
1. [Transmitter Setup](docs/Transmitters.md)
1. [How to for popular models](docs/Models.md)
1. [Troubleshooting](docs/Troubleshooting.md)
@ -32,11 +32,8 @@ A functioning MULTI-Module consists of (see image below):
1. A host RC Tx
1. A Multiprotocol Transmitter Module (MULTI-Module) that connects to a host transmitter. This module is typically comprised of
* A microcontroller (currently ATMega328P or STM32) that interfaces with the Tx, controls the module functions and forwards the RC commands to the RF hardware
* One or more (but at least one) RF modules that provide the capability to communicate with RC receivers. To communicate with the receiver the RF module in the Tx must match with the RF module type in the receiver. The four most common 2.4GHz RF chips on the market are supported TI CC2500, Nordic NRF24L01, Cypress CYRF6936, and the Amiccom A7105
* MULTI-firmware loaded on to the microprocessor. At a high level, this firmware performs a few different functions:
* It interfaces with signals from the host Tx and decodes these for transmission to the model, it manages the activation of the correct hardware RF module for each protocol
* It implements the unique communication protocols for each receiver/model and manages the all-important binding process with a receiver/model
@ -47,7 +44,7 @@ One of the most attractive features of the MULTI-module is the ability to send t
In constructing a functioning MULTI-Module there are important choices to be made and tradeoffs to be aware of. The most important are:
##**Choice 1:** Which MULTI-Module hardware option
## **Choice 1:** Which MULTI-Module hardware option
There are currently four generic paths to get your hands on an MULTI-Module. These are outlined in detail on the [hardware](docs/Hardware.md) page. Here they are, in order of increasing difficulty:
- **Ready-made MULTI-Module** - Available from Banggood which includes a 4-in-1 RF module and an antenna switcher
@ -59,35 +56,35 @@ The last option is where it all started and how the pioneers in this project mad
For more information on these options see the [hardware](docs/Hardware.md) page
##**Choice 2:** Which RF modules to include in the MULTI-Module
## **Choice 2:** Which RF modules to include in the MULTI-Module
This depends on your specific needs. However, recent the availability of the 4-in-1 RF modules from Banggood for less than $35 makes it easy to “have it all”. Most manufacturers of RC systems (Spektrum, FrSky, FlySky) and toys (Syma, Hubsan, etc.) use one of these four RF chips to manage the RF link between the transmitter and the reciever/model. Here is an incomplete list of the RF modules and some of the most popular toys that use them. For the complete list see the [Protocol Details](Protocols_Details.md) page.
Manufacturer|RF Chip|Example Protocols
:-----------|-------|:-------
Cyprus Semiconductor| CYRF6936|DSM/DSMX
| |Walkera Devo
| |J6Pro
Texas Instruments|CC2500|FrSky
| |Futaba SFHSS
Amiccom|A7105|FlySky
| |FlySky AFHDS2A
| |Hubsan
Nordic Semiconductor|NRF24L01|HiSky
| |Syma
| |ASSAN
| |and most other Chinese models
|Manufacturer|RF Chip|Example Protocols|
|---|---|---|
|Cyprus Semiconductor|CYRF6936|DSM/DSMX|
|||Walkera Devo|
|||J6Pro|
|Texas Instruments|CC2500|FrSky|
|||Futaba SFHSS|
|Amiccom|A7105|FlySky|
|||FlySky AFHDS2A|
|||Hubsan|
|Nordic Semiconductor|NRF24L01|HiSky|
|||Syma|
|||ASSAN|
|||and most other Chinese models|
For example, if you have no interest in binding your Tx to an model with and FrSky or Futaba SFHSS receiver you do not need to include the CC2500 RF module in your system.
##**Choice 3:** Which protocols to upload to the MULTI-Module
## **Choice 3:** Which protocols to upload to the MULTI-Module
Of course there is always a catch. In this case it is the 32KB memory limit on the ATmega328 processor. Due to the amazing work done by devs on this project, the memory required by all the possible protocols exceeds this limit considerably. This means that you will need to make a choice of which protocols you will compile into your firmware. Fortunately, the process of selecting and compiling is not too difficult and it is fully documented on the [Compiling and Programming](docs/Compiling.md) page.
Also, the lead dev Pascal Langer (rcgroups:hpnuts) makes this process even easier for many users by making compiled binaries available for three popular combinations of RF modules. These are always “fresh” (based on the latest stable firmware) and available on the [Releases](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) page.
An alternatice is to use a STM32 ARM microcontroller based module. If you go the route of building this version of the DIY MULTI-Module then the memory limits do not apply anymore.
##**Choice 4:** Choosing the type of interface between the MULTI-Module and your radio (PPM or Serial)
## **Choice 4:** Choosing the type of interface between the MULTI-Module and your radio (PPM or Serial)
The MULTI-Module supports industry standard PPM interface that works with all transmitters with either:
- a module bay or
@ -100,7 +97,7 @@ If you are the owner of a transmitter that supports the er9X/erSky9X or OpenTX f
- The model protocol selection and binding is done from the Model Settings menu on the Tx
- For telemetry capable transmitters, the telemetry integration is done seamlessly with the Tx firmware. (Note that FrSky TH9X/Turnigy 9X/R transmitters require a telemetry mod to be done before telemetry can work). Click on the link corressponding to your Tx on the [Transmitters](docs/Transmitters.md) page for more details.
#How to get started?
# How to get started?
1. Browse the [Protocols](Protocols_Details.md) page to see which protocols you would like on your module
1. Go to the [Hardware Options](docs/Hardware.md) page to decide which of the MULTI-Module hardware options appeals to you and which RF modules you plan to integrate
1. Once you have your module, you should review what jumper settings or modifications are required to the module to support serial communication and possibly telemetry
@ -108,7 +105,7 @@ If you are the owner of a transmitter that supports the er9X/erSky9X or OpenTX f
1. Finally, you should visit the setup page for your transmitter by clicking on the link corressponding to your Tx on the [Transmitters](docs/Transmitters.md) page to configure the last few settings before you can fly to your hearts content!!!!!
# Troubleshooting
Visit the [Troubleshooting](docs/Troubleshooting.md) page. Please bear in mind that the MULTI-Module is a complex system of hardware and software and it make take some patience to get it up and running. Also remember that the developers of the system are actual users of the system. This means that at any moment in time the system is working perfectly for them. A corollary to this is that if you are struggling there are likely two scenarios. First, that the problem is with your hardware or with your configuration, second, and much more unlikely but not impossible scenario, is that you are struggling with a new undiscovered bug. (The author of this documentation speaks from experience ;-) Please check the RC Groups forum and search for keywords relating to your problem before posting a reply. When you do post a reply please so humbly and respectfully you will find many helpful people there. In your reply please include as much relevant information as possible and attach compilation output and _Config.h files as text attachments to keep the forum clean.
Visit the [Troubleshooting](docs/Troubleshooting.md) page. Please bear in mind that the MULTI-Module is a complex system of hardware and software and it make take some patience to get it up and running. Also remember that the developers of the system are actual users of the system. This means that at any moment in time the system is working perfectly for them. A corollary to this is that if you are struggling there are likely two scenarios. First, that the problem is with your hardware or with your configuration, second, and much more unlikely but not impossible scenario, is that you are struggling with a new undiscovered bug. (The author of this documentation speaks from experience ;-) Please check the RC Groups forum and search for keywords relating to your problem before posting a reply. When you do post a reply please so humbly and respectfully you will find many helpful people there. In your reply please include as much relevant information as possible and attach compilation output and ```_Config.h``` files as text attachments to keep the forum clean.
# A final word
A very big thanks to all the people who have shared their time so graciously to create this great project. If you come across them on RC Groups, please be kind and show appreciation. In no particular order:
* Pascal Langer (rcgroups: hpnuts)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#ATmega Serial Uploader
# ATmega Serial Uploader
Mike Blandford adapted the optiboot bootloader for the 4-in-1 module to allow flashing of the module using a standard Arduino USB to serial adapter or FTDI adapter. No need to open the module case. Once set up is very easy to use:
@ -22,7 +22,7 @@ While the bootloader is running, if it detects a communication problem, it confi
This bootloader is for reading and writing the flash only, the EEPROM is not supported, neither is reading/writing the fuses, but it only uses 512 bytes of flash.
##Install the bootloader
## Install the bootloader
To get the bootloader onto the ATmega you need to connect an flashing tool (like USBasp) to the 6-pin ISP connector on the board.
Simply flash the .hex file to get the bootloader on the chip, and change the high fuse at the same time.

View File

@ -1,5 +1,6 @@
#Bluetooth Telemetry in PPM Mode
###Telemetry
# Bluetooth Telemetry in PPM Mode
## Telemetry
There are 4 protocols supporting telemetry: Hubsan, DSM, FrSkyD and FrSkyX.
@ -11,7 +12,7 @@ FrSkyD displays full telemetry (A0, A1, RX RSSI, TX RSSI and Hub).
FrSkyX displays full telemetry (A1, A2, RX RSSI, TX RSSI and Hub).
### If used in PPM mode
## If used in PPM mode
Telemetry is available as a serial output on the TX pin of the Atmega328p using the FrSky hub format for Hubsan, FrSkyD, FrSkyX and DSM format for DSM2/X. The serial paramets depends on the protocol:

View File

@ -1,19 +1,17 @@
#Manually Uploading HEX files and setting Fuses on ATmega328
# Manually Uploading HEX files and setting Fuses on ATmega328
**The .hex files provided are only for tests purpose. The recommended method is to use [Compiling and Programming](Compiling.md).**
There are many different options to upload a .hex firmware file to the MULTI-Module and to set the correct fuses. This document outlines an approach that uses a USBASP programmer and which is equally compatible with OSX, Windows and Linux operating systems.
1. Follow this section: [Material you need to upload the firmware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Compiling.md#material-you-need-to-upload-the-firmware)
1. Follow this section: [Install the Arduino IDE](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Compiling.md#install-the-arduino-ide-and-the-multiprotocol-project-firmware)
1. Follow this section: [Material you need to upload the firmware](Compiling.md#material-you-need-to-upload-the-firmware)
1. Follow this section: [Install the Arduino IDE](Compiling.md#install-the-arduino-ide-and-the-multiprotocol-project-firmware)
1. Make sure to write down the location of your installation since you need to know where avrdude is installed to configure the AVR8 Burn-O-Mat. For example on a default windows installation, avrdude.exe is located in "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin" where "C:\Program Files (x86)\Arduino" is the installation path.
1. Install [AVR8 Burn-O-Mat](http://avr8-burn-o-mat.brischalle.de/avr8_burn_o_mat_avrdude_gui_en.php) which is available for all platforms. Installation instructions are on the software page (Don't forget to install [Java](http://java.sun.com/javase/downloads) as explained).
1. Launch AVR8 Burn-O-Mat.
1. You should now have a window which looks like this:
<img src="images/AVR8BurnOMat-main.png" />
1. Click on **Settings->AVRDUDE** and fill in the details about avrdude location using the installation path written previously as well as selecting USBASP for the programmer:
<img src="images/AVR8BurnOMat-settings.png" />
1. You should now have a window which looks like this: <br> <img src="images/AVR8BurnOMat-main.png" />
1. Click on **Settings->AVRDUDE** and fill in the details about avrdude location using the installation path written previously as well as selecting USBASP for the programmer: <br> <img src="images/AVR8BurnOMat-settings.png" />
1. Once done click on OK.
1. You are now done with all the installations/configuration and ready to program your Multi-module.
@ -32,15 +30,14 @@ Banggood 4-in-1 module with [custom mikeb bootloader](Advanced_ATmega_Serial_Upl
If you don't know which one to take the 1st line is the one you want.
###Burn the fuses
1. Follow this section: [Connect the programmer](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Compiling.md#connect-the-programmer)
### Burn the fuses
1. Follow this section: [Connect the programmer](Compiling.md#connect-the-programmer)
1. Launch AVR8 Burn-O-Mat.
1. In the **AVR type** drop down select **ATmega328P** and click on **Fuses**
1. In the **ATmega328P Fuses** window which just open click on read fuses.
1. Ignore the error "warning : Can not Set sck period . usbasp please check for firmware update .".
1. If you get an error there is something wrong with your connections, your programmer, or your board. Verify everything and go back to the 1st bullet point.
1. Set the 3 Fuse values
<img src="images/AVR8BurnOMat-fuses.png" />
1. Set the 3 Fuse values <br> <img src="images/AVR8BurnOMat-fuses.png" />
1. Click on **apply**
1. Click on **write fuses**
1. Ignore the error "warning : Can not Set sck period . usbasp please check for firmware update .".
@ -48,7 +45,7 @@ If you don't know which one to take the 1st line is the one you want.
1. You are done with setting the Fuses and can close the **ATmega328P Fuses** window
## Upload the firmware
1. Follow this section: [Connect the programmer](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Compiling.md#connect-the-programmer)
1. Follow this section: [Connect the programmer](Compiling.md#connect-the-programmer)
1. Download the [latest release firmware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) you want to burn and store it in a knwon location
1. Launch AVR8 Burn-O-Mat.
1. In the **AVR type** drop down select **ATmega328P**

View File

@ -1,26 +1,28 @@
#Advanced Topics {This page is currently a proof of concept}
# Advanced Topics {This page is currently a proof of concept}
Warning: the topics on this page are not for the fainthearted. It is strongly recommended that you have some experience in getting up and runnning with your module before you dive in there. On the other hand what is described on this page are some very useful options that could greatly increase the value and the enjoyment of your Multiprotocol module.
#Serial uploader that works through the transmitter pins
# Serial uploader that works through the transmitter pins
This document describes how you can set up your ATmega-based Mulitprotocol module to allow you to update the firmware by connecting a USB to TTL serial (like a FTDI) adapter to the module's transmitter interface pins. It is great if you exclusively use the Serial interface with your transmitter because the Bind button is used as "bootloader" button. It requires a small custom bootloader to be uploaded and a simple interface cable to be soldered up. See the [Advanced ATmega Serial Uploader](Advanced_ATmega_Serial_Uploader.md) page for more details.
Created and supported by: Mike Blandford
RCGroups page: http://www.rcgroups.com/forums/showpost.php?p=35584619&postcount=4867
#Telemetry in PPM mode
# Telemetry in PPM mode
It is possible to access the telemetry stream coming from the receiver through the MULTI-module. This document describes a simple bluetooth module to stream telemetry information to a mobile device like an Android smartphone or tablet. The method may be generalized to feed telemetry to the transmitter if the transmitter has the capabilities to process the information. This is very useful with modules used in the PPM mode with transmitters that do not support telemetry. See the [Advanced Bluetooth Telemetry](Advanced_Bluetooth_Telemetry.md) page for more details.
Created and supported by: Midelic
RCGroups page: None
#Manually setting fuses on ATmega328
# Manually setting fuses on ATmega328
This document describes a relatively simple process to set the fuses on ATmega328 using the flexibility of the command line. It does not require installation of AVRdude because it uses the AVRdude that is bundled with the Arduino IDE. See the [Advanced Manually Setting ATmega328 Fuses](Advanced_Manually_Setting_ATmega328_Fuses.md) page for more details.
Created and supported by: hpnuts
## Flashing Multi_STM32 module.
####Flashing without Tx power
#### Flashing without Tx power
This is another method of Flshing Multi_STM32 which is riskier.This method is for skilled users who understand the task.
The key difference of this method is that the 3.3V FTDI cable must also provide power to the 5V circuitry during the flashing process. To do this, a jumper must be enabled connecting the 3.3V VCC to the 5V line. The risk is to forget 3.3V jumper in, after flashing and when TX restarted.
@ -32,18 +34,19 @@ The key difference of this method is that the 3.3V FTDI cable must also provide
1. Remove the module from the transmitter bay
1. Set BOOT0 jumper Skip this step if you made your own cable.
1. Set the 3.3V jumper.
1. Connect your 3.3V FTDI cable (USB - TTL serial) to Multiprotocol serial port (RX,TX,GND,5V). Connect the pins as follows:
- Module RX pin to FTDI TX pin
- Module TX pin to FTDI Rx pin
- Module GND to FTDI GND
- Module 5V to FTDI 3.3V FTDI power supply.
1. Connect your 3.3V FTDI cable (USB - TTL serial) to Multiprotocol serial port (RX,TX,GND,5V).
Connect the pins as follows:
* Module RX pin to FTDI TX pin
* Module TX pin to FTDI Rx pin
* Module GND to FTDI GND
* Module 5V to FTDI 3.3V FTDI power supply
1. In arduino IDE under the **Tools** -> **Board:** check that you have selected the **Generic STM32F103C series** board
1. Under **Tools** -> **Upload Method:** select **Serial**.
1. Click "Upload" and the sketch will be uploaded normally.
1. Once the firmware has uploaded:
- Remove the 3.3V jumper!!!!
- Remove the BOOT0 jumper
- Check that you removed the 3.3V jumper
* Remove the 3.3V jumper!!!!
* Remove the BOOT0 jumper
* Check that you removed the 3.3V jumper
1. Insert the module into the transmitter bay

View File

@ -1,8 +1,8 @@
#Bill of Materials DIY ATmega Module
# Bill of Materials DIY ATmega Module
Here is the bill of materials for the ATmega328 version of the DIY MPTM.
If you are looking for the BOM for the DIY STM32 version click [here](BOM_DIY_STM32.md).
If you are looking for the BOM for the DIY STM32 version click [here](BOM_DIY_STM32%20&amp;%20Schematic.md).
Digikey may not be your preferred supplier, but you should find enough information on their page to cross reference parts.

View File

@ -1,4 +1,4 @@
#Bill of Materials DIY STM32 Module
# Bill of Materials DIY STM32 Module
Here is the bill of materials for the STM32 version of the DIY MPTM. There are three versions. Carefully compare your board with the pictures below to determine which version you have.
@ -7,19 +7,32 @@ All diagrams and eagle files are available [here](https://github.com/pascallange
If you are looking for the BOM for the DIY ATmega328 3.2d version click [here](BOM_DIY_ATmega.md).
Digikey may not be your preferred supplier, but you should find enough information on their page to cross reference parts.
If digikey is your prefered supplier, their is a link to shared carts to make checkout easier at the begining of the BOM.
## IMPORTANT NOTE on Telemetry
In the case of the Turnigy 9X/9XR/9XR Pro you don't need to invert the telemetry signal therefore the instalation of the inverter chip SN74LVC2G86DCTR is **OPTIONAL**. In this case and in order to have telemetry you need to solder **SJ1/SJ301** on the back of the board depending on which board version you have.
The inverted telemetry signal is required by TARANIS TX and other boards so for telemetry to work properly the inverter chip must be installed.
## BOM DIY STM32 PCB V1.0t - the USB version
## BOM DIY STM32 PCB V1.1t - USB version update
The board is available at OSHpark [here](https://oshpark.com/shared_projects/eWtNW6jo)
<img src="images/Board_PCB_STM32_USB_V1.1-2.png" width="300" height="400"/> <img src="images/Board_PCB_STM32_USB_V1.1-1.png" width="300" height="400"/>
## BOM DIY STM32 PCB V1.0t & V1.1 - the USB version
This BOM is for the board with the USB port which allows firmware upload.
The board is available at OSHpark [here](https://oshpark.com/shared_projects/GX51nEoH)
<img src="images/Board_PCB_STM32_USB-1.png" width="300" height="400"/> <img src="images/Board_PCB_STM32_USB-2.png" width="300" height="400"/>
Digikey BOM shared cart for building 1 module [here](http://www.digikey.com/short/3dn71h)
Digikey BOM shared cart for building 3 modules [here](http://www.digikey.com/short/3dnt2r)
Please Note - With the Digikey shared carts it is cheaper to order 10 piece stips with some parts like resistors and capacitors. These extra parts are not reflected or needed in the followong BOM list.
Qty|Part|Description|Value|Package|Digikey Part Number
---|----|-----------|-----|-------|-------------------
1|J301|Receptacle|5-pin||[WM3103-ND](http://www.digikey.com/product-search/en?keywords=WM3103-ND)
@ -33,7 +46,7 @@ Qty|Part|Description|Value|Package|Digikey Part Number
1|C203|Cap Ceramic|4u7|0805|[311-1371-1-ND](https://www.digikey.com/product-detail/en/yageo/CC0805ZRY5V6BB475/311-1371-1-ND/2103155)
1|C207|Cap Ceramic|1uF|0805|[311-1365-1-ND](https://www.digikey.com/product-detail/en/yageo/CC0805KKX7R7BB105/311-1365-1-ND/2103149)
1|C208|Cap Ceramic|10nF|0805|[311-1136-1-ND](http://www.digikey.com/products/en?keywords=311-1136-1-ND)
4|D201,301,302,303|Diode Shottky|BAT48|SOD123|[497-5712-1-ND](http://www.digikey.com/products/en?keywords=497-5712-1-ND)
5|D101*,201,301,302,303|Diode Shottky|BAT48|SOD123|[497-5712-1-ND](http://www.digikey.com/products/en?keywords=497-5712-1-ND)
1|IC101|Voltage reg 5V|AMS1117-50|SOT223|[LM1117MP-5.0/NOPBCT-ND](https://www.digikey.com/product-detail/en/texas-instruments/LM1117MP-5.0-NOPB/LM1117MP-5.0-NOPBCT-ND/363589)
1|IC102|Voltage reg 3.3V|AMS1117-33|SOT223|[LM1117MPX-3.3/NOPBCT-ND](https://www.digikey.com/product-detail/en/texas-instruments/LM1117MPX-3.3-NOPB/LM1117MPX-3.3-NOPBCT-ND/1010516)
1|L101|High Freq Inductor|10uH|1812|[CM453232-100KLCT-ND](https://www.digikey.com/product-detail/en/bourns-inc/CM453232-100KL/CM453232-100KLCT-ND/3437938)
@ -55,6 +68,8 @@ Qty|Part|Description|Value|Package|Digikey Part Number
1|U301|Dual INPUT-XOR|SN74LVC2G86DCTR|SSM8|[296-13274-1-ND](http://www.digikey.com/product-detail/en/texas-instruments/SN74LVC2G86DCTR/296-13274-1-ND/484501)
1|CON401|ANT.conn SMD|||[WM5587CT-ND](https://www.digikey.com/product-detail/en/molex-llc/0734120110/WM5587CT-ND/1894612)
* Diode D101 is only required for the V1.1 board
PCB STM32 V1.0t Schematic
<img src="https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/STM32%20PCB/Schematic_Multiprotocol_STM32_MB_v1.0_t.jpg" width="1000" height="500" />
@ -98,9 +113,8 @@ Qty|Part|Description|Value|Package|Digikey Part Number
## BOM DIY STM32 PCB - the first Version
This BOM is for the board that looks like this - check carefully:
<img src="https://camo.githubusercontent.com/9b8dc4eb5618583ebe8fc01f03f2da75766080b3/68747470733a2f2f36343464623464653335303563343061303434342d33323737323362636532393865336666353831336662343262616565666261612e73736c2e6366312e7261636b63646e2e636f6d2f66326435393865616364386539656562633338313861646634373737373139392e706e67" width="300" height="400"/>
<img
src="https://644db4de3505c40a0444-327723bce298e3ff5813fb42baeefbaa.ssl.cf1.rackcdn.com/2026cfd1d0187a770570052590168df1.png" width="300" height="400"/>
src="https://644db4de3505c40a0444-327723bce298e3ff5813fb42baeefbaa.ssl.cf1.rackcdn.com/2026cfd1d0187a770570052590168df1.png" width="300" height="400"/> <img src="https://camo.githubusercontent.com/9b8dc4eb5618583ebe8fc01f03f2da75766080b3/68747470733a2f2f36343464623464653335303563343061303434342d33323737323362636532393865336666353831336662343262616565666261612e73736c2e6366312e7261636b63646e2e636f6d2f66326435393865616364386539656562633338313861646634373737373139392e706e67" width="300" height="400"/>
Qty|Part|Description|Value|Package|Digikey Part Number

View File

@ -1,4 +1,4 @@
#Getting your Bind timing right.
# Getting your Bind timing right.
On many consumer models it it important for the Tx to send a bind signal in a narrow window once the model has powered up.
If the bind signal is not recieved during this window, the bind sequence times out. Try this:

View File

@ -4,7 +4,7 @@ Multiprotocol source are compiled using the well known Arduino IDE.
The procedure below will guide you through all the steps to upload successfully a customized firmware.
##Install the Arduino IDE and the Multiprotocol project firmware
## Install the Arduino IDE and the Multiprotocol project firmware
1. Download and install the Arduino IDE. The currently supported Arduino version is 1.6.12. available for [Windows]( https://www.arduino.cc/download_handler.php?f=/arduino-1.6.12-windows.exe) and [Mac OSX](https://www.arduino.cc/download_handler.php?f=/arduino-1.6.12-macosx.zip)
1. It is recommended to upgrade Java to the [latest version](https://www.java.com/en/download/)
1. Download the zip file with the Multiprotocol module source code from [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/archive/master.zip)
@ -13,50 +13,42 @@ The procedure below will guide you through all the steps to upload successfully
## Upload the firmware
###Material you need to upload the firmware
1. USBASP programmer supporting 3.3V: <img src="images/USBasp_Programmer.jpeg" width="200" height="200" /> [(example aliexpress link)](https://www.aliexpress.com/item/USBasp-USB-ISP-3-3V-5V-AVR-Programmer-USB-ATMEGA8-ATMEGA128-New-10PIN-Wire-Support/2036402518.html?spm=2114.30010308.8.10.jIbHzs). There are reports that some of the cheap programmers are not safe to use with 3.3V units, usually the black PCB versions are ok.
1. 10pin to 6pin adapter: <img src="images/10pin_2_6pin.JPG" width="150" height="150" /> [(example ebay link)](http://www.ebay.fr/itm/10-Pin-a-6-Pin-Carte-Adaptateur-M-F-pour-AVRISP-USBASP-STK500-Noir-Bleu-WT-/291862396761?hash=item43f45abf59:g:gXsAAOSwMgdXyGnh)
1. 6 pin header like this one: <img src="images/6pin_header.jpg" width="100" height="100" /> [(example Digi-Key link)](http://www.digikey.com/products/en?keywords=3M%20961206-6404-AR)
### Material you need to upload the firmware
The 6 Pin header needs to be solder on the board like indicated by the red rectangle:
* Banggood readymade 4-in-1 module:
<img src="images/V2b_ISP.jpeg" width="189" height="200" />
* DIY Mulitprotocol modules (like the 2.3d board):
<img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201" />
* Arduino Pro Mini module:
<img src="images/ProMini_ISP.png" width="195" height="200" />
1. USBASP programmer supporting 3.3V: <br> <img src="images/USBasp_Programmer.jpeg" width="200" height="200"/> <br> [(example aliexpress link)](https://www.aliexpress.com/item/USBasp-USB-ISP-3-3V-5V-AVR-Programmer-USB-ATMEGA8-ATMEGA128-New-10PIN-Wire-Support/2036402518.html?spm=2114.30010308.8.10.jIbHzs) <br> There are reports that some of the cheap programmers are not safe to use with 3.3V units, usually the black PCB versions are ok. <br>
1. 10pin to 6pin adapter: <br> <img src="images/10pin_2_6pin.JPG" width="150" height="150"/> <br> [(example ebay link)](http://www.ebay.fr/itm/10-Pin-a-6-Pin-Carte-Adaptateur-M-F-pour-AVRISP-USBASP-STK500-Noir-Bleu-WT-/291862396761?hash=item43f45abf59:g:gXsAAOSwMgdXyGnh) <br>
1. 6 pin header like this one: <br> <img src="images/6pin_header.jpg" width="100" height="100"/> <br> [(example Digi-Key link)](http://www.digikey.com/products/en?keywords=3M%20961206-6404-AR) <br>
1. The 6 Pin header needs to be solder on the board like indicated by the red rectangle:
* Banggood readymade 4-in-1 module: <br><img src="images/V2b_ISP.jpeg" width="189" height="200"/> <br>
* DIY Mulitprotocol modules (like the 2.3d board): <br><img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201"/> <br>
* Arduino Pro Mini module: <br><img src="images/ProMini_ISP.png" width="195" height="200"/> <br>
###Connect the programmer
### Connect the programmer
1. Before you connect the programmer make sure that you have selected the 3.3V mode and not 5V. The RF Modules are not 5V tolerant and you will break them with 5V. On most programmers this is done by moving a jumper.
<img src="images/USBasp_Programmer_jumper.png" width="200" height="200" />
1. Before you connect the programmer make sure that you have selected the 3.3V mode and not 5V. The RF Modules are not 5V tolerant and you will break them with 5V. On most programmers this is done by moving a jumper. <br> <img src="images/USBasp_Programmer_jumper.png" width="200" height="200" />
1. Please re-read item 1. above before going on.
1. Turn the rotary switch on the DIY Multiprotocol module to the 0 position. If you do not have a switch for Serial mode only then it is the same as being in the 0 position. The upload will not work if the switch is in any other position.
1. Connect the 6-pin programming connector to the 6-pin ASP IVR connector on the DIY Multiprotocol board. Be sure to match the ground pin of the programmer connector to the ground pin on the board.
The images below indicates the pin layout and the location of the ground pin on the board:
* Banggood readymade 4-in-1 module:
<img src="images/V2b_ISP.jpeg" width="189" height="200" />
* DIY Mulitprotocol modules (like the 2.3d board):
<img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201" />
* Arduino Pro Mini module:
<img src="images/ProMini_ISP.png" width="195" height="200" />
* Banggood readymade 4-in-1 module: <br> <img src="images/V2b_ISP.jpeg" width="189" height="200" /> <br>
* DIY Mulitprotocol modules (like the 2.3d board): <br> <img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201" /> <br>
* Arduino Pro Mini module: <br> <img src="images/ProMini_ISP.png" width="195" height="200" /> <br>
You are now ready to plug in the USB programmer to the computer
If you are looking for a good working USBASP Windows driver, [use this one](http://www.protostack.com/download/USBasp-win-driver-x86-x64-v3.0.7.zip).
###Configure Arduino IDE for Multiprotocol
### Configure Arduino IDE for Multiprotocol
1. Under Tools -> Board select the Arduino Pro or Pro Mini
1. Under Tools -> Processor select the ATmega328 (5V, 16MHz)
1. Under Tools -> Programmer select your programmer type (probably USBASP from the shopping list above)
<a name="CustomizeFirmareToYourNeeds"></a>
###Customize the firmware to match your hardware and your needs
### Customize the firmware to match your hardware and your needs
All customization is done by editing the ```_Config.h ``` file in the Multiprotocol Arduino project.
In the Arduino IDE, click on the down arrow on the far right of the tab bar to show a list of project files (see the red circle on the screenshot below). Scroll down and select the _Config.h file.
<img src="images/Arduino.png" width="600" height="400" />
In the Arduino IDE, click on the down arrow on the far right of the tab bar to show a list of project files (see the red circle on the screenshot below). Scroll down and select the _Config.h file. <br> <img src="images/Arduino.png" width="600" height="400" />
The file has different sections which are explained in details. The best is to go through them one by one carefully and apply the configuration which matches your needs.
@ -64,9 +56,7 @@ Most of the default settings should get you started quickly. But on modules with
To fill in the "PROTOCOLS TO INCLUDE" section, it would be good to review all the available protocols on the [Protocol Details](../Protocols_Details.md) page and identify which one you would like to add on your module.
To check that the program will compile correctly and fit in the Atmega press the Check mark as shown below.
<img src="images/Arduino_check.jpg" width="99" height="130" />
To check that the program will compile correctly and fit in the Atmega press the Check mark as shown below. <br> <img src="images/Arduino_check.jpg" width="99" height="130" />
If you see something like the following, your firmware is still too big and you need to deselect additional protocols:
> Sketch uses 34,096 bytes (104%) of program storage space. Maximum is 32,768 bytes.
@ -75,13 +65,12 @@ If you see something like the following, your firmware is still too big and you
If there is another error carefully read it, go to the line number indicated and correct your typo.
###Flash the firmware
### Flash the firmware
1. If you have a 4in1 Multiprotocol module you can skip this step. If you've just finished to build your DIY Multiprotocol module (like v2.3d), the first step is to flash the fuses of the microcontroller. This needs to be done only once. For this purpose, click on **Tools -> Burn Bootloader**
1. You are now ready to flash the firmware. In the Arduino IDE click **Sketch -> Upload Using Programmer**.
If the output indicates that the firmware has been uploaded successfully - give yourself a pat on the back. Well done, you have successfully programmed your DIY Multiprotocol module. You can already go to the final step [Setting up your Transmitter](TransmitterSetup.md) and begin to fly!!!! But don't forget to visit the next topic [Advanced settings](#AdvancedSettings) which has some extra steps needed to use your module at his full potential.
If the output indicates that the firmware has been uploaded successfully - give yourself a pat on the back. Well done, you have successfully programmed your DIY Multiprotocol module. You can already go to the final step [Setting up your Transmitter](Transmitters.md#compatible-transmitters) and begin to fly!!!! But don't forget to visit the next topic [Advanced settings](#AdvancedSettings) which has some extra steps needed to use your module at his full potential.
**Troubleshooting**
@ -105,49 +94,47 @@ First, we need to append some text to the Arduino file boards.txt.
#### On Windows
1. Close the Arduino IDE
1. Search Windows for the application WordPad (DO NOT USE Notepad). Right click on WordPad and select "Run as Administrator":
<img src="images/WordPad_Admin.jpg" height="200" />
1. Search Windows for the application WordPad (DO NOT USE Notepad). <br> Right click on WordPad and select "Run as Administrator": <br> <img src="images/WordPad_Admin.jpg" height="200" /> <br>
1. Open the file ```boards.txt``` located in this folder ```C:\Program Files(x86)\Arduino\hardware\arduino\avr ``` or the equivalent if you have installed Aduino in a different directory.
1. Append the following text into the end of the file and save it:
```
##############################################################
## Multi 4-in-1 (3.3V, 16 MHz) w/ ATmega328
## --------------------------------------------------
multi.name=Multi 4-in-1
```
##############################################################
## Multi 4-in-1 (3.3V, 16 MHz) w/ ATmega328
## --------------------------------------------------
multi.name=Multi 4-in-1
multi.upload.tool=avrdude
multi.upload.protocol=arduino
multi.upload.tool=avrdude
multi.upload.protocol=arduino
multi.bootloader.tool=avrdude
multi.bootloader.unlock_bits=0x3F
multi.bootloader.lock_bits=0x0F
multi.bootloader.tool=avrdude
multi.bootloader.unlock_bits=0x3F
multi.bootloader.lock_bits=0x0F
multi.build.board=AVR_PRO
multi.build.core=arduino
multi.build.variant=eightanaloginputs
multi.build.extra_flags=-Wl,--relax
multi.build.board=AVR_PRO
multi.build.core=arduino
multi.build.variant=eightanaloginputs
multi.build.extra_flags=-Wl,--relax
multi.menu.cpu.16MHzatmega328=ATmega328 (3.3V, 16 MHz)
multi.menu.cpu.16MHzatmega328=ATmega328 (3.3V, 16 MHz)
multi.menu.cpu.16MHzatmega328.upload.maximum_size=32768
multi.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
multi.menu.cpu.16MHzatmega328.upload.speed=57600
multi.menu.cpu.16MHzatmega328.upload.maximum_size=32768
multi.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
multi.menu.cpu.16MHzatmega328.upload.speed=57600
multi.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
multi.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xD3
multi.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0xFD
multi.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
multi.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xD3
multi.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0xFD
multi.menu.cpu.16MHzatmega328.build.mcu=atmega328p
multi.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
##############################################################
```
multi.menu.cpu.16MHzatmega328.build.mcu=atmega328p
multi.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
##############################################################
```
#### On Mac OSX:
1. Close the Arduino IDE
1. Using finder navigate to ```Applications``` folder
1. Ctl-Click on the Arduino application and select **Show Package Contents**.
1. Browse to ```Contents/Java/hardware/arduino/avr`` and double click on boards.txt
1. Browse to ```Contents/Java/hardware/arduino/avr``` and double click on boards.txt
1. Copy and paste the "Multi 4-in-1" text listed above into the end of the file and save it.
### Burn Bootloader

View File

@ -7,71 +7,58 @@ Multiprotocol source can be compiled using the Arduino IDE using STM32 Core (Map
On all modules with STM32F103 microcontroller, the program flash memory on the microcontroller is large enough to accommodate all the protocols. You do not have to make choices on which protocols to upload. Also, it is likely that you used the Banggood 4-in-1 RF module and you will therefore have access to all the RF modules.Now for programmng multimodule with STM32 chip you have 2 options presented below.
1. Compiling and flashing in Arduino IDE.
1. Flashing precompiled binaries from [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases)
- If using one of these TX with multimodule like Turnigy 9X,9XR,9X+ the binary file for flashing is **Multiprotocol_V1.X.X_STM32.bin**.
- If using TARANIS TX the binary file is **Multiprotocol_V1.X.X_STM32_INV.bin**
Flashing precompiled **binaries** is done very simple with the cable setup presented below and an utility(GUI) **ST Flash Loader Demonstrator.**
## Compiling source and flashing in Arduino.
##Compiling source and flashing in Arduino.
###Install the Arduino IDE and the Multiprotocol project
### Install the Arduino IDE and the Multiprotocol project
1. Download the Arduino IDE. The currently supported Arduino version is 1.6.11 available for [Windows]( https://www.arduino.cc/download_handler.php?f=/arduino-1.6.12-windows.exe) and [Mac OSX](http://arduino.cc/download_handler.php?f=/arduino-1.6.12-macosx.zip)
1. It is recommended to upgrade Java to the [latest version](https://www.java.com/en/download/)
1. Download the [STM32 Core](https://github.com/rogerclarkmelbourne/Arduino_STM32/archive/master.zip) and copy the Arduino_STM32 folder to:
- OSX: ```Arduino.app/Contents/Java/hardware``` (you can open Arduino.app by Ctl Clicking on Arduino.app and selecting "Show Package Contents")
- Windows: ```C:\Program Files (x86)\Arduino\hardware```
- Make sure the folder tree structure is like this .....\hardware\Arduino_STM32\.....and **NOT** ...... \hardware\Arduino_STM32-master\Arduino_STM32-master\......So move the folders /rename accordingly.
1. Download the zip file with the Multiprotocol module source code from [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)
1. Unzip and copy the source code folder ```Multiprotocol``` to a folder of your choosing
1. Click on the ```Multiprotocol.ino file``` in the ```Multiprotocol``` folder and the Arduino environment should appear and the Multiprotocol project will be loaded.
###Prepare the Arduino IDE:
### Prepare the Arduino IDE:
1. In order to compile successfully you need also to modify a maple library file. In ```....\hardware\Arduino_STM32\STM32F1\cores\maple\libmaple\usart_f1.c``` comment out the 2 functions as shown below. This is required to have low-level access to the USART interrupt.
1. In order to compile successfully you need also to modify a maple library file. In ```....\hardware\Arduino_STM32\STM32F1\cores\maple\libmaple\usart_f1.c``` comment out the 2 functions as shown below. This is required to have low-level access to the USART interrupt. <br>
```
/* void __irq_usart2(void){
usart_irq(&usart2_rb, USART2_BASE);
}
**/***
**void __irq_usart2(void){**
**usart_irq(&usart2_rb, USART2_BASE);**
**}**
**void __irq_usart3(void) {**
**usart_irq(&usart3_rb, USART3_BASE);**
**}
*/**
1. Run the IDE, and on the **Tools** menu, select **Board** and then **Boards manager**. Click on the Arduino DUE (32 Bits ARM-Cortex M3) from the list of available boards. You must do this step, it installs the arm-none-eabi-g++ toolchain!
void __irq_usart3(void) {
usart_irq(&usart3_rb, USART3_BASE);
} */
```
1. Run the IDE, and on the **Tools** menu, select **Board** and then **Boards manager**. <br> Click on the Arduino DUE (32 Bits ARM-Cortex M3) from the list of available boards. You must do this step, it installs the arm-none-eabi-g++ toolchain!
1. Close and reopen the Arduino IDE and load the Multiprotocol project.
1. In arduino IDE under the **Tools** -> **Board:** select the **Generic STM32F103C series** board
1. Click on the **Verify** button to test compile the before you make any changes. If there are any errors check the process above and be sure to have the right version of the Arduino IDE.The binary file generated location is presented at the bottom of Arduino IDE compiling window.Now continue with flashing procedure.
1. Click on the **Verify** button to test compile the before you make any changes. <br> If there are any errors check the process above and be sure to have the right version of the Arduino IDE.The binary file generated location is presented at the bottom of Arduino IDE compiling window.Now continue with flashing procedure.
### Flashing the multimodule
There are three options for flashing the firmware. But We will present here only 2 methods ,the third one is presented in advanced topics.
There are three options for flashing the firmware. But We will present here only 3 methods ,the 4-th one is presented in advanced topics.
The first (and strongly recommended) is flashing it while it is plugged into and powered by the transmitter.The second is preparing the board for flashing with a USB cable.
The second method is definitely the easiest in the long-term, but it does require the USB bord and setting up the bootloader on the STM32 MCU.
The third method is also highly recommended and involving flashing using TX (firmware).At this methid is available for 9X ,9X pro ,Taranis with ersky9X fimrware.
####Option 1: Flashing with Tx power(highly recommended)
#### Option 1: Flashing with Tx power(highly recommended)
1. Put the module in the Tx
1. Place a jumper over the BOOT0 pins.Skip this one if you made your own cable for flashing ,see below.
1. Connect your 3.3V/5V FTDI cable (USB - TTL serial) to Multiprotocol serial port. Connect only RX, TX and GND. **Do not connect the 5V or 3.3V between the FTDI cable and the module - the power will be supplied by the transmitter**. Connect the pins as follows:
1. Connect your 3.3V/5V FTDI cable (USB - TTL serial) to Multiprotocol serial port. <br> Connect only RX, TX and GND. **Do not connect the 5V or 3.3V between the FTDI cable and the module - the power will be supplied by the transmitter**. Connect the pins as follows:
- Module RX pin to FTDI TX pin
- Module TX pin to FTDI Rx pin
- Module GND to FTDI GND
1. In arduino IDE under the **Tools** -> **Board:** check that you have selected the **Generic STM32F103C series** board
1. Under **Tools** -> **Upload Method:** select **Serial**
1. Click "Upload" and the sketch will be uploaded normally. This is valid for all arduino versions.
@ -80,28 +67,41 @@ The second method is definitely the easiest in the long-term, but it does requi
If you have the module inside a box and to be inserted in TX bay, you may build a flashing cable like in the picture below.
You can attach and solder a 5 pin header female and top outside the box.**ALways insert first the USB serial device in USB port , and TX start after.**
[<img src="images/Multi_STM32_ flashing.jpg" />]
<img src="images/Multi_STM32_ flashing.jpg" />
See below my module for reference
[<img src="images/Multi_STM32 module.JPG" width="600" height="400" />]
<img src="images/Multi_STM32 module.JPG" width="600" height="400" />
####Option 2: Flashing with USB cable.
#### Option 2: Flashing with USB cable.
This method use USB connector on the STM32 V1.0 board or on the maple clone board.
1. Install first maple USB driver by running the batch file found in Arduino STM32 package folder "..\hardware\Arduino_STM32\drivers\win\install_drivers.bat"
1. Download the free STM32 flash loader demonstrator from [ST.com](http://www.st.com/en/development-tools/flasher-stm32.html) and using a USB-TTL device (like FTDI cable) flash the STM32duino bootloader available from Roger Clark's great STM32 site [here](https://github.com/rogerclarkmelbourne/STM32duino-bootloader/tree/master/STM32F1/binaries) .Use bootloader **generic_boot20_pa1.bin**
1. Open Arduino IDE,browse to multiprotocol folder,load the sketch multiprotocol.ino.
1. In Arduino IDE under "Upload method" select **STM32duino**-bootloader.Wait until upload is complete.
1. Install first maple USB driver by running the batch file found in Arduino STM32 package folder ```..\hardware\Arduino_STM32\drivers\win\install_drivers.bat```
1. Download the free STM32 flash loader demonstrator from [ST.com](http://www.st.com/en/development-tools/flasher-stm32.html) and use a USB-TTL device (like FTDI cable) to flash the [StmMultiUSB.bin](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/StmMultiUSB/StmMultiUSB.bin) bootloader.
1. Open Arduino IDE,browse to multiprotocol folder,load the sketch multiprotocol.ino.Select the serial COM port(see notes below)
1. In Arduino IDE under "Upload method" select **STM32duino**-bootloader.Click upload ,wait until upload is complete.
Notes:
- When you use multiSTM32_USB for the first time,the USB drivers are not recognized and port is not open/recognized(arduino IDE port selection is grey/unavailable). After this first time use, any subsequent update of the program, you'll have to select the correct serial port and upload sketches normally in Arduino using USB port.
- When you use multiSTM32_USB for the first time,the USB drivers are not recognized and com port is not open/recognized(arduino IDE port selection is grey/unavailable). After this first time use, any subsequent update of the program, you'll have to select the correct serial port and upload sketches normally in Arduino using USB port.
- More explanations how all these work you find [here](http://www.stm32duino.com/viewtopic.php?f=32&t=1774_)
- If the initial upload fails, make sure you are running the latest [Java version](https://www.java.com/en/download/)
- If using Banggood multiSTM32_USB module, follow instructions from step1(USB drivers on your computer) and jump after, to step 3(most probably generic bootloader is installed on multi module and no need to be installed again).I don't have one for test so this is an educated guess.
#### Option 3: Flashing with TX radio(firmware)
1. Flash new STM32 bootloader(StmMultiBoot) on multimodule:
- Flash precompiled binary [**StmMuliBoot.bin**](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/StmMultiBoot/StmMultiBoot.bin) using **ST Flash loader demonstrator** and USB serial device(FTDI) , with same custom cable presented above.This process is the same as flashing with precompiled binaries.For BG(green) module you can folow the paper instructions for flashing coming with the module using bridge pins provided.
- After this process is complete switch off TX,remove cables FTDI serila device and/or mutimodule jumper used for flashing.The multimodule should be back in the same state as before.
1. Compile multiprotocol source in arduino IDE ,choose this time Upload method **STM32duino bootloader** ,select **"Export compiled Binary"** to show the binary file in the same folder as source.
1. Copy the resulted binary file to the TX radio SD card in the "/firmware" folder.
1. Now flash the TX radio with the latest firmware(for ersky9x it's version P221 "e2" test version or higher).
1. Enter in TX radio maintenance mode (for ersky9X, start the transmitter with both bottom trims pushed outwards). Select **Update Multi** press menu button select also the right com port,update ,then the multiprotocol.bin file (see the correct name) and press menu and again for flashing. You'll see a bar fill slowly .Wait for the procces to be complete.Press exit( or switch off TX) several times to come out of the maintenace mode.
1. Any subsequent update of the multiprotocol will follow 2-3 and 5-6 steps. There is no need anymore to use a USB serial device or cables for flashing.
## Flashing precompiled binaries:
If you want to flash a pre-compiled binary file (like the Release .bin files) you need specialized software and the same FTDI cable setup already posted [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Compiling_STM32.md#option-1-flashing-with-tx-powerhighly-recommended).
If you want to flash a pre-compiled binary file (like the Release .bin files) you need specialized software and the same FTDI cable setup already posted [here](Compiling_STM32.md#option-1-flashing-with-tx-powerhighly-recommended).
1. Set BOOT0 jumper(skip this step if you aready made your own cable ,see above)
1. Connect your 3.3V FTDI cable (USB - TTL serial) to Multiprotocol serial port (RX,TX,GND pins when flashing with TX power).
@ -113,14 +113,12 @@ For uploading binaries(.bin files) there is a specialized software you need to i
#### Windows:
Download the **ST Flash Loader Demonstrator** from here: http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/flasher-stm32.html
Run the ST Flash Loader program. There are many tutorials on the web on how to use this program.For example
[here](http://www.scienceprog.com/flashing-programs-to-stm32-embedded-bootloader)
Run the ST Flash Loader program. There are many tutorials on the web on how to use this program.For example: [here](http://www.scienceprog.com/flashing-programs-to-stm32-embedded-bootloader)
#### OSX:
To be checked.
###Report issues for the STM32 board
### Report issues for the STM32 board
You can report your problem using the [GitHub issue](https://github.com/midelic/DIY-Multiprotocol-TX-Module/issues) system or go to the [Main thread on RCGROUPS](http://www.rcgroups.com/forums/showthread.php?t=2165676) to ask your question.
Please provide the following information:

View File

@ -1,14 +1,13 @@
#Documentation ToDos
1. Documentation on all the FlySky boards: (MikeB?)
# Documentation ToDos
- [ ] Documentation on all the FlySky boards: (MikeB?)
- SKY board erSky9x
- AR9X board erSky9x
- 9Xtreme board erSky9x
- AR9X UNI board
1. Add to the troubleshooting page
1. Add how to do custom protocol setup on er9x and OpenTx
1. Document the OrangeRx Transmitter module (Mikeb?)
1. enabling Serial on the DIY PCB page
1. lots of pictures mentioned between the {} markers
1. Someone to add the Build the board from scratch if it is still relevant
1. Move to atmega specific and add ftdi to stm32 AVR ISP programmer like the popular USBASP programming dongle that is 3.3V safe - available from many sellers on ebay. There are reports that some of the cheap programmers are not safe to use with 3.3V units (like this unit). Look for USBAsp programmers with the “LC Technologies” label. {Pascal to confirm these reports are true} Also, you will need a 10-pin to 6-pin connector to connect the USBASP to the board.
- [ ] Add to the troubleshooting page
- [ ] Add how to do custom protocol setup on er9x and OpenTx
- [ ] Document the OrangeRx Transmitter module (Mikeb?)
- [ ] enabling Serial on the DIY PCB page
- [ ] lots of pictures mentioned between the {} markers
- [ ] Someone to add the Build the board from scratch if it is still relevant
- [ ] Move to atmega specific and add ftdi to stm32 AVR ISP programmer like the popular USBASP programming dongle that is 3.3V safe - available from many sellers on ebay. There are reports that some of the cheap programmers are not safe to use with 3.3V units (like this unit). Look for USBAsp programmers with the “LC Technologies” label. {Pascal to confirm these reports are true} Also, you will need a 10-pin to 6-pin connector to connect the USBASP to the board.

View File

@ -2,7 +2,7 @@
The choice of **Multiprotocol Transmitter Module (MULTI-Module)** hardware is the single biggest choice you will make. Due to the growing popularity of this project the number of hardware choices is growing almost monthly.
There are currently four common hardware options. They are (click on the pictures for more info):
There are currently four common hardware options. They are (`click on the pictures for more info`):
1. A ready-made 4-in-1 MULTI-Module which integrates the microcontroller with all four supported RF modules and a hardware antenna switcher.
[<img src="images/4-in-1_Module_BG.jpeg" width="200" height="200" />](Module_BG_4-in-1.md)

View File

@ -1,19 +1,24 @@
#Model Setup
# Model Setup
This is the page to document model or receiver specific setup instructions.
The Deviation project (on which this project was based) have a useful list of models [here](http://www.deviationtx.com/wiki/supported_models).
#Syma X5C
# Syma X5C
<img src="http://img2.cheapdrone.co.uk/images/upload/2014/12/X5C%203/SKU115108-7.jpg" Width="200" Height="200" />
##Channel Map
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RATES|PICTURE|VIDEO
##Binding
## Channel Map
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RATES|PICTURE|VIDEO|HEADLESS
## Binding
There are no special binding instructions. The model powers up in Autobind mode and expects the bind sequence from the transmitter within the first 4-5 seconds.
##Tx Setup
## Tx Setup
A basic 4-channel setup works perfectly, but some improvements are possible:
###Setting up a switch to Flip
### Setting up a switch to Flip
1. Choose your "Rates" switch - typically the momentary TRN switch
1. In the Mixer create an entry for CH5
@ -21,7 +26,7 @@ A basic 4-channel setup works perfectly, but some improvements are possible:
- er9X: Source: sTRN, Weight 100 (or whatever switch you selected)
- OpenTx: Source: SH, Weight 200 (or whatever switch you selected)
###Setting up a swich for high rates
### Setting up a swich for high rates
1. Choose your "Rates" switch
1. In the Mixer create an entry for CH6
@ -31,7 +36,7 @@ A basic 4-channel setup works perfectly, but some improvements are possible:
When the switch is in the rear position the rates will be standard, when the switch is forward rates will be high. There is no need to move the throttle stick to the full up and full down position as with the standard controller.
###Setting up Idle-up
### Setting up Idle-up
One of the most annoying functions on the Syma X5C is that the motors stop when the throttle is pulled back. This can be fixed by implmenting Idle-up on the transmitter (think of this as a very simple version of the Betaflight "Air Mode"). Idle up will ensure that even when the throttle is all the way down, a minimum command is passed to the motor to keep them spinning and to activate the stabilization.
**To do this**:
@ -41,49 +46,73 @@ One of the most annoying functions on the Syma X5C is that the motors stop when
1. When you want to fly in "idle-up" mode flick the switch and your stabilization will always be active.
1. Remeber to switch off idle-up as soon as the quad lands (or crashes - to avoid damage to the motors)
#Inductrix (Horizon Hobby)
### Additional notes on rates:
The SymaX driver can add full trim to the control output. Doing so enables
dramatic rates, steep angles, and high speeds. If CH6 is low, the usual Syma
full rates will be in effect. If CH6 is high, the SymaX extreme trim rates will be
in effect. Be cautious when first trying out the extreme rates.
The extreme rates do not work with with headless mode because in this
mode the trim and the primary control directions may not be aligned - the
primary control directions will be based on the headless mode, but the trims
remain based upon the quadcopter's heading. So extreme rates are disabled
when headless mode is selected.
Be aware that the use of extreme rates and the resulting steep angles will
disorient the gyro responsible for maintaining headless mode, and that the
direction the quadcopter thinks you selected for headless mode may not be
correct after especially wild flights.
# Inductrix (Horizon Hobby)
<img src="https://s7d5.scene7.com/is/image/horizonhobby/BLH8700_a0" Width="200" Height="200" />
##Binding
## Binding
For telemetry enabled modules, you should just let the remote autodetect the settings. Otherwise choose DSMX 22ms with 6ch or 7ch. To bind the model, keep the transmitter off, power on the Inductrix. Wait until it flashes fast and then power up the Tx and use Bind.
##Tx Setup
Remember that 100% on your transmitter using the MULTI-Module corresponds to 125% on the DSM receiver side. On some functions sending 100% will confuse the model. Conversely 80% on your Tx is interpreted to be 100% at the model. Consider this when implementing the suggestions below.
###Throttle
### Throttle
For Inductrix FPV you might need to adjust the lower end of throttle to be a higher than default, otherwise motors will be spinning on minimal throttle. One way to do this is to set the throttle to 80% output (100% of DSM output) and then to enable the **Throttle Idle Trim Only** under the Model Setup menu. See image below:
<img src="images/Inductrix_Throttle_Setup.png" Width="600" Height="200" />
###Acro and Level Mode
### Acro and Level Mode
Setup channel 6 with a momemtary button or switch (e.g. SH on the Taranis) and use that switch to switch between modes. Set the output to somewhere between 40% to 60% for best results.
An addition consideration when flying in Acro mode is to reduce stick sensitivity and to add some expo. The screens below show one way of doing this. Customize to your needs.
####Inputs Screen
#### Inputs Screen
The follwing INPUTS screen shows one potential setup to introduce expo for Acro mode. The activation of the expo on Roll, Pitch and Yaw is when the SG switch is not in the back position. Add to taste.
<img src="images/Inductrix_Inputs.png" Width="600" Height="200" />
####Aileron Rates attached to Switch !SG-up
#### Aileron Rates attached to Switch !SG-up
The next screen shows and example of how the expo (50%) was set up on the stick input and how it is activated by !SG-up:
<img src="images/Inductrix_Aileron_Expo.png" Width="600" Height="200" />
####Mixer Menu
#### Mixer Menu
The next screen shows the mixer menu with the mode change on momentary switch SH and High-Low rates on switch SC:
<img src="images/Inductrix_Mixer.png" Width="600" Height="200" />
# Cheerson CX-20 / Quanum Nova
<img src="http://uaequadcopters.com/images/products/Large/932-cheersoncx20dronquad.jpg" Width="200" Height="155" />
##Channel Map
## Channel Map
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|MODE|AUX1|AUX2
##Binding
## Binding
The Rx powers up in binding mode so the transmitter should be set to autobind. If the Tx signal is lost due to power-off or going out of range the Rx will not re-bind, and requires power-cycling before it will bind again.
##Tx Setup
## Tx Setup
AETR are simple +100% mixes. Note that the model expects Elevator (CH2) to be reversed, which is handled in the module firmware, so no need to reverse it on the Tx.
###Flight modes
### Flight modes
CH5 is used to transmit the flight mode to the APM flight controller by setting the output to a value in a pre-defined range. The original Tx uses a 3-pos switch (SWA) and a 2-pos switch (SWB) to achieve six different combinations, but only five are used - with SWA at 0, 1500 is sent when SWB is at 0 and 1, leaving flight mode 3 unused. However, in the stock CX-20 flight controller settings, both flight mode 3 and 4 are set to the same flight mode, meaning we can configure our new Tx settings to send a value for mode 3 without changing the standard flight mode behaviour. Afterwards, you can optionally use Mission Planner to assign a new flight mode to mode 3 or mode 4, or reconfigure them altogether.
The values, modes, and switch positions for the stock Tx are:
@ -113,7 +142,7 @@ One easy way to acheive this is to configure six logical switches mapped to two
To simply map the old Tx modes to the new Tx using the same switch positions, use the following configuration. The stock SWA switch is replaced with the ID0/1/2 switch, SWB is replaced with the AIL D/R switch.
####Logical switches:
#### Logical switches:
Switch|Function|V1|V2
---|---|---|---
@ -124,7 +153,7 @@ L. Switch 4|AND|ID0|AIL
L. Switch 5|AND|ID1|AIL
L. Switch 6|AND|ID1|!AIL
####Flight modes (using CX-20 names):
#### light modes (using CX-20 names):
Mode|Name|Switch
---|---|---
@ -135,7 +164,7 @@ Mode|Name|Switch
5|DirLock|L5
6|Stable|L6
####Mixer setup:
#### Mixer setup:
Channel|Weight|Source|Switch|Multiplex
---|---|---|---|---
@ -154,11 +183,11 @@ CH6 and CH7 can be assigned to switches or pots to provide additionaly functiona
Replicating the stock setup of two pots, you would assign:
Channel|Weight|Source|Multiplex
---|---|---|---|---
---|---|---|---
CH6|+100%|P1|ADD
CH7|+100%|P3|ADD
##Full Mixer Setup
## Full Mixer Setup
Channel|Source|Weight|Switch|Multiplex
---|---|---|---|---

View File

@ -1,7 +1,7 @@
#4-in-1 module
# 4-in-1 module
Currently the form factor of this module is designed for the JR-style module bay. Many of the popular RC transmitters use the JR-style module bay: FrSky Taranis, FlySky Th9x, Turnigy 9X/R/Pro
##What you need
## What you need
A fully assembled module + case available from Banggood.com [here](http://www.banggood.com/CC2500-NRF24L01-A7105-CYRF693-4-In-1-RF-Module-With-Case-For-Futaba-JR-Frsky-Transmitter-p-1116892.html)
<img src="images/4-in-1_Module_Case_BG.jpeg" width="221" height="200" />
@ -21,9 +21,9 @@ For 9XR/9XR Pro, a new 3D printed module is available which makes use of the bui
<img src="images/9XR_module.jpg" width="113" height="200" /> <img src="images/9XR_module_connector.jpg" width="274" height="200" />
##Different working modes
## Different working modes
###PPM mode
### PPM mode
If you are only planning on using the PPM interface with your transmitter, you need to connect it as described:
<img src="images/PPM.png" width="574" height="340" />
@ -34,7 +34,7 @@ The same plug is available on all versions of the module with the same signal lo
If you wish to add an external device reading the telemetry, you need to enable serial mode as explained in the next topics otherwise you are now ready to go over to [Compiling and Programming](Compiling.md).
###Serial mode
### Serial mode
If you have a transmitter that can support serial communication with the board then you need to wire up the board appropriately. There are three versions of the module and the steps are slightly different.
Check which module you have and based on the pictures below. If you purchased the module after June 2016 then it is likely that you have a V1.1 type module. If you have purchased the version with case it is likely that you have a V1.2 type module.

View File

@ -1,4 +1,4 @@
#Build from stratch
# Build from stratch
If you can help to fully document this page, or just add additional detail please let us know on the rcgroups [forum](http://www.rcgroups.com/forums/showthread.php?t=2165676).
@ -14,9 +14,9 @@ A module case that fits your receiver like the one [here](https://www.xtremepowe
For 9XR/9XR Pro, a new 3D printed module is available which makes use of the built in antenna in the handle. This means nothing is getting out of the radio back. You can find all details of this module case on [Thingiverse](http://www.thingiverse.com/thing:2050717).
<img src="images/9XR_module.jpg" width="113" height="200" /> <img src="images/9XR_module_connector.jpg" width="274" height="200" />
##Reference Schematic <a name="Schematic"></a>
## Reference Schematic <a name="Schematic"></a>
Here is the schematic you can use to troubleshoot the module
<img src="images/DIY_Mulitprotocol_Module_Schematic.jpeg" width="1000" height="500" />
##Compiling and programming
## Compiling and programming
Follow the instruction on the [Compiling and programming page](Compiling.md)

View File

@ -1,10 +1,11 @@
#DIY MULTI-module by soldering components on a PCB
# DIY MULTI-module by soldering components on a PCB
Currently the form factor of this module is designed for the JR-style module bay. Many of the popular RC transmitters use the JR-style module bay: FrSky Taranis, FlySky Th9x, Turnigy 9X/R/Pro
##What you need
## What you need
First you must choose the PCB onto which to solder all the components. There are two PCB options:
- ATmega (8-bit) powered PCB V2.3d supporting individual RF modules
- STM32 (32-bit) powered PCB V1.0t supporting the 4-in-1 RF module
- ATmega (8-bit) powered PCB V2.3d supporting individual RF modules
- STM32 (32-bit) powered PCB V1.0t supporting the 4-in-1 RF module
The **ATmega-based board** has been designed to accept individual RF modules. This way you can select just the module or modules you want. The downside is that each module requires its own antenna. It can become cumbersome with 4 antennas protruding from the module. It is possible to soder the 4-in-1 module to the PCB using thin insulated wire. This 4-in-1 module requires only one antenna. Finally, the Atmega board has a 32KB flash memory. This is big enough to accommodate more than 15 protocols, but it cannot accommodate all the available protocols.
@ -14,7 +15,7 @@ The **STM32-based** board has been designed to accept the 4-in-1 RF module with
<img src="images/Board_PCB_STM32.jpeg" width="100" height="125" /> <img src="images/Multi_4-in-1_RF_module.jpg" width="65" height="82" />
###ATmega board V2.3d
### ATmega board V2.3d
1. ATmega (8-bit) powered PCB V2.3d available from OSHPark [here](https://oshpark.com/shared_projects/Ztus1ah8).
2. Individual RF modules The modules are available here:
- [CC2500](http://www.banggood.com/2_4G-500K-CC2500-Long-Range-Wireless-Transceiver-Module-p-1075492.html) for FrSkyV, FrSkyD, FrSkyX and SFHSS
@ -26,48 +27,39 @@ The **STM32-based** board has been designed to accept the 4-in-1 RF module with
The schematic for the board is [here](#V23D_Schematic). Please note that is is the general schematic - there will be some minor differences (like solder jumpers) between this and the board.
###STM32 powered PCB
### STM32 powered PCB
1. The latest STM32 (32-bit) powered PCB V1.0t supporting the 4-in-1 RF module available from OSHPark [here](https://oshpark.com/shared_projects/GX51nEoH).
2. The 4-in-1 RF module is available [here](http://www.banggood.com/DIY-2_4G-CC2500-NRF24L01-A7105-CYRF6936-Multi-RF-4-IN-1-Wireless-Module-p-1046308.html)
1. The schematic and BOM for this board V1.0t and older boards are available [here](BOM_DIY_STM32 & Schematic.md).
###Common parts
1. A module case that fits your module like the one [here](https://www.xtremepowersystems.net/proddetail.php?prod=XPS-J1CASE)
<img src="https://www.xtremepowersystems.net/prodimages/j1case.jpg" width="200" height="180" />
or you can 3D print your own from a selection on Thingiverse ([Example 1](http://www.thingiverse.com/thing:1852868) [Example 2](http://www.thingiverse.com/thing:1661833)).
[<img src="http://thingiverse-production-new.s3.amazonaws.com/renders/55/1c/cb/0a/e4/5d2c2b06be7f3f6f8f0ab4638dd7c6fc_preview_featured.jpg" width="250" height="200" /> ](http://www.thingiverse.com/thing:1852868)
For 9XR/9XR Pro, a new 3D printed module is available which makes use of the built in antenna in the handle. This means nothing is getting out of the radio back! You can find all details of this module case on [Thingiverse](http://www.thingiverse.com/thing:2050717).
<img src="images/9XR_module.jpg" width="113" height="200" /> <img src="images/9XR_module_connector.jpg" width="274" height="200" />
1. The schematic and BOM for this board V1.0t and older boards are available [here](BOM_DIY_STM32%20\&%20Schematic.md).
### Common parts
1. A module case that fits your module like the one [here](https://www.xtremepowersystems.net/proddetail.php?prod=XPS-J1CASE) <br> <img src="https://www.xtremepowersystems.net/prodimages/j1case.jpg" width="200" height="180" /> <br> or you can 3D print your own from a selection on Thingiverse ([Example 1](http://www.thingiverse.com/thing:1852868) [Example 2](http://www.thingiverse.com/thing:1661833)). <br> [<img src="http://thingiverse-production-new.s3.amazonaws.com/renders/55/1c/cb/0a/e4/5d2c2b06be7f3f6f8f0ab4638dd7c6fc_preview_featured.jpg" width="250" height="200" /> ](http://www.thingiverse.com/thing:1852868) <br> For 9XR/9XR Pro, a new 3D printed module is available which makes use of the built in antenna in the handle. This means nothing is getting out of the radio back! You can find all details of this module case on [Thingiverse](http://www.thingiverse.com/thing:2050717). <br> <img src="images/9XR_module.jpg" width="113" height="200" /> <img src="images/9XR_module_connector.jpg" width="274" height="200" />
1. A 2.4GHz antenna and pigtail
##Build instructions
## Build instructions
If you got this far you already know what you are doing!!
###Common steps
### Common steps
1. Solder all the parts according to the BOM part numbering and the images for your board (see OSHPARK for the images)
1. Fit the module into the module case. This may require some careful filing or sanding of the module to ensure a nice fit.
###PPM interface
### PPM interface
If you are only planning on using the PPM interface with transmitter you are ready to program the module as described in [Compiling and Programming](Compiling.md) the module.
###Enabling Serial and Telemetry interface
### Enabling Serial and Telemetry interface
If you have a transmitter that can support serial communication with the board then you need to solder some jumpers.
#### **ATmega V2.3d board**
There are four solder type jumpers on the bottom side of the board near the lower left corner when the bottom of the board is facing towards you. The silkscreen shows which jumper is which. These four jumpers enable the board to be configured in several ways as explaned below.
```
(J-1) Use (PPM V/V) if the incoming PPM signal is at a higher voltage level, leave open if ~~5V.
(J-2) Use (Jumper 2) to connect the incomming PPM signal to the RX pin on the processor
(J-3) Short (TELEM) only if you have done a telemetry mod to your radio, leave open if not needed. When connected, pin 2 of the two pin header (P3) is also connected.
(J-4) Use (MOD) only to connect the transmitter pin 2 to pin 1 of the two pin header (P3).
```
**It is most likely J-2 will be the only one needing to be shorted for the serial method of sending model protocols. If you plan to use telemetry you will also need to solder J-3**
@ -77,13 +69,13 @@ You are now ready to go over to [Compiling and Programming](Compiling.md).
You are now ready to go over to [Compiling and Programming STM32](Compiling_STM32.md).
#Reference Schematic <a name="Schematic"></a>
# Reference Schematic <a name="Schematic"></a>
Here is the schematic you can use to troubleshoot the module
## <a name="V23D_Schematic"></a> PCB 2.3d Schematic
General module schematic (reference)
<img src="images/DIY_Mulitprotocol_Module_Schematic.jpeg" width="1000" height="500" />
V2.3d Board Schematic
<img src="https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/PCB%20v2.3d/Schematic_v2.3d.jpg" width="1000" height="500" />
<img src="../PCB%20v2.3d/Schematic_v2.3d.jpg" width="1000" height="500" />
## <a name="STM32_Schematic"></a> PCB STM32 V1.0t Schematic
<img src="https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/STM32%20PCB/Schematic_Multiprotocol_STM32_MB_v1.0_t.jpg" width="1000" height="500" />
<img src="../STM32%20PCB/Schematic_Multiprotocol_STM32_MB_v1.0_t.jpg" width="1000" height="500" />

View File

@ -1,4 +1,4 @@
#OrangeRx Transmitter module
# OrangeRx Transmitter module
The OrangeRx transmitter module uses an Atmel XMega MCU. This requires a PDI programmer to flash firmware, the USBASP programmers do not work.

View File

@ -1,9 +1,9 @@
#PPM Setup
# PPM Setup
The Multiprotocol Module is compatible with any transmitter that is able to generate a PPM (Pulse Postion Modulation) output. This includes all transmitters with a module bay or a trainer port. It supports up to 16 channels from a PPM frame in the normal or inverted format (sometimes called positive or negative format in some transmitters).
If you want the best performance you can set the number of channels and framerate corresponding to the number of channels of the specific receiver/model.
##PPM Connections
## PPM Connections
If you do not have a module bay, there are only three wires you need to connect to get PPM to work. (The pins are numbered from top to bottom)
- PPM on pin 1
- vbat on pin 3
@ -12,7 +12,7 @@ If you do not have a module bay, there are only three wires you need to connect
Note: vbat should be between 6V and 13V when using the 4-in-1 and 2.3 PCB boards. If you built a module from scratch it depends on the voltage regulator you chose.
##Enabling PPM mode in your transmitter
## Enabling PPM mode in your transmitter
1. Enable the default Tx mode to be AETR. If you do not want to change the default channel order on your Tx you must remember to change the channel order for each new model using the module to AETR under the Model Mixer menu. (**This is really important - this is for all protocols - even for DSM as the MULTI-module firware will change the transmitted channel order according to the protocol.**)
1. The default PPM settings is 8 channels with a frame period of 22.5 ms (sometimes called the frame rate). If you want to optimize performance you should change the channels to the actual number of channels required by your model. The corresponding frame period should be set to (number of channels + 1) * 2.5 ms. For example:
@ -29,7 +29,7 @@ The default mapping of protocols to switch positions can be viewed on the Protoc
The mapping of protocols to protocol selection switch positions can be changed in configuration settings as described on the [Compiling and Programming page](Compiling.md).
##Binding in PPM mode
## Binding in PPM mode
In PPM mode follow the standard transmitter - receiver binding process:
1. Switch off the transmitter
@ -41,17 +41,17 @@ In PPM mode follow the standard transmitter - receiver binding process:
If you are having trouble binding to a consumer quad check the section below on [Getting your Bind Timing right](Bind_Timing.md). For more details on setting up specific receivers or models, check out the [Protocol Details page](Protocol_Details.md).
##Telemetry in PPM mode
## Telemetry in PPM mode
Telemetry is available as a serial stream on the TX pin of the Atmega328p in the FrSky HUB format. The serial parameters are based on the protocol selected by the protocol selection dial.
Protocol|Serial Parameters
--------|-----------------
---|---
Hubsan|9600bps 8n1
FrSkyD|9600bps 8n1
FrSkyX|57,600bps 8n1
DSM2/X|125,000bps 8n1
The serial stream is also available on pin 5 of the Module connector (pins numbered from top to bottom) on the [4-in-1 module]() and the [V2.3d modules]() provided the Tx jumper has been soldered. See the linked module documentation for what this means.
The serial stream is also available on pin 5 of the Module connector (pins numbered from top to bottom) on the [4-in-1 module](Module_BG_4-in-1.md) and the [V2.3d modules](Module_Build_yourself_PCB.md#atmega-board-v23d) provided the Tx jumper has been soldered. See the linked module documentation for what this means.
You can connect it to your TX if it is telemetry enabled or use a bluetooth adapter (HC05/HC06) along with an app on your phone/tablet [(app example)](https://play.google.com/store/apps/details?id=biz.onomato.frskydash&hl=fr) to display telemetry information and setup alerts.

View File

@ -1,4 +1,4 @@
#MULTI-Module Protocol Details
# MULTI-Module Protocol Details
**You'll find below a detailed description of every supported protocols sorted by RF modules.**
Legend:
@ -8,9 +8,9 @@ Legend:
The AETR mentionned here for all protocols depends on the TX settings compilation option set in _Config.h.
***
#A7105 RF Module
# A7105 RF Module
##FLYSKY
## FLYSKY
Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
@ -19,22 +19,22 @@ A|E|T|R|CH5|CH6|CH7|CH8
Note that the RX ouput will be AETR.
###Sub_protocol V9X9
### Sub_protocol V9X9
CH5|CH6|CH7|CH8
---|---|---|---
FLIP|LIGHT|PICTURE|VIDEO
###Sub_protocol V6X6
### Sub_protocol V6X6
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---
FLIP|LIGHT|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
###Sub_protocol V912
### Sub_protocol V912
CH5|CH6
---|---
BTMBTN|TOPBTN
##HUBSAN
## HUBSAN
Models: Hubsan H102D, H107/L/C/D and Hubsan H107P/C+/D+
Autobind protocol
@ -47,10 +47,9 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
***
#CC2500 RF Module
# CC2500 RF Module
##FRSKYV = FrSky 1 way
## FRSKYV = FrSky 1 way
Models: FrSky receivers V8R4, V8R7 and V8FR.
Extended limits supported
@ -61,7 +60,7 @@ CH1|CH2|CH3|CH4
---|---|---|---
CH1|CH2|CH3|CH4
##FRSKYD
## FRSKYD
Models: FrSky receivers D4R and D8R. DIY RX-F801 and RX-F802 receivers.
Extended limits supported
@ -74,7 +73,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
##FRSKYX
## FRSKYX
Models: FrSky receivers X4R, X6R and X8R.
Extended limits supported
@ -83,17 +82,17 @@ Telemetry enabled for A1 (RxBatt), A2, RSSI, TSSI and Hub
Option=fine frequency tuning. This value is different for each board. To determine the option value, find the two limits where the RX loses connection then set the option value to half way between them. If you have a 4in1 V2 board the value is around 40.
###Sub_protocol CH_16
### Sub_protocol CH_16
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
###Sub_protocol CH_8
### Sub_protocol CH_8
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
##SFHSS
## SFHSS
Models: Futaba RXs and XK models.
Option=fine frequency tuning. This value is different for each board. To determine the option value, find the two limits where the RX loses connection then set the option value to half way between them. If you have a 4in1 V2 board the value is around 40.
@ -102,10 +101,9 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
***
#CYRF6936 RF Module
# CYRF6936 RF Module
##DEVO
## DEVO
Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
@ -135,7 +133,7 @@ Bind procedure using PPM:
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the dial number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
##DSM
## DSM
Extended limits supported
Telemetry enabled for TSSI and plugins
@ -150,31 +148,34 @@ Notes:
- model/type/number of channels indicated on the RX can be different from what the RX is in fact wanting to see. So don't hesitate to test different combinations until you have something working. Using Auto is the best way to find these settings.
- RX ouput will always be TAER independently of the input AETR, RETA...
###Sub_protocol DSM2_22
### Sub_protocol DSM2_22
DSM2, Resolution 1024, refresh rate 22ms
###Sub_protocol DSM2_11
### Sub_protocol DSM2_11
DSM2, Resolution 2048, refresh rate 11ms
###Sub_protocol DSMX_22
### Sub_protocol DSMX_22
DSMX, Resolution 2048, refresh rate 22ms
###Sub_protocol DSMX_11
### Sub_protocol DSMX_11
DSMX, Resolution 2048, refresh rate 11ms
###Sub_protocol AUTO
### Sub_protocol AUTO
The "AUTO" feature enables the TX to automatically choose what are the best settings for your DSM RX and update your model protocol settings accordingly.
The current radio firmware which are able to use the "AUTO" feature are ersky9x (9XR Pro, 9Xtreme, Taranis, ...) and er9x for M128 (9XR) and M2561.
For these firmwares, you must have a telemetry enabled TX and you have to make sure you set the Telemetry "Usr proto" to "DSMx".
Also on er9x you will need to be sure to match the polarity of the telemetry serial (normal or inverted by bitbashing), while on ersky9x you can set "Invert COM1" accordinlgy.
##J6Pro
## J6Pro
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
***
#NRF24L01 RF Module
# NRF24L01 RF Module
##ASSAN
## ASSAN
Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
@ -183,7 +184,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
The transmitter must be close to the receiver while binding.
##BAYANG
## BAYANG
Models: EAchine H8(C) mini, BayangToys X6/X7/X9, JJRC JJ850, Floureon H101 ...
Autobind protocol
@ -192,7 +193,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
A|E|T|R|FLIP|RTH|PICTURE|VIDEO|HEADLESS|INVERTED
##CG023
## CG023
Models: EAchine CG023/CG031/3D X4
Autobind protocol
@ -201,14 +202,14 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
###Sub_protocol YD829
### Sub_protocol YD829
Models: Attop YD-822/YD-829/YD-829C ...
CH5|CH6|CH7|CH8|CH9
---|---|---|---|---
FLIP||PICTURE|VIDEO|HEADLESS
###Sub_protocol H8_3D
### Sub_protocol H8_3D
Models: EAchine H8 mini 3D, JJRC H20/H22
CH5|CH6|CH7|CH8|CH9
@ -223,7 +224,7 @@ H8 3D: OPT1=RTH then press a direction to enter headless mode (like stock TX), O
CAL: calibrate accelerometers
##CX10
## CX10
Extended limits supported
Autobind protocol
@ -234,12 +235,12 @@ A|E|T|R|FLIP|RATE
Rate: -100%=rate 1, 0%=rate 2, +100%=rate 3
###Sub_protocol GREEN
### Sub_protocol GREEN
Models: Cheerson CX-10 green pcb
Same channels assignement as above.
###Sub_protocol BLUE
### Sub_protocol BLUE
Models: Cheerson CX-10 blue pcb & some newer red pcb, CX-10A, CX-10C, CX11, CX12, Floureon FX10, JJRC DHD D1
CH5|CH6|CH7|CH8
@ -248,13 +249,13 @@ FLIP|RATE|PICTURE|VIDEO
Rate: -100%=rate 1, 0%=rate 2, +100%=rate 3 or headless for CX-10A
###Sub_protocol DM007
### Sub_protocol DM007
CH5|CH6|CH7|CH8|CH9
---|---|---|---|---
FLIP|MODE|PICTURE|VIDEO|HEADLESS
###Sub_protocol Q282 and Q242
### Sub_protocol Q282 and Q242
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---
@ -262,120 +263,129 @@ FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
Model: JXD 509 is using Q282 with CH12=Start/Stop motors
###Sub_protocol JC3015_1
### Sub_protocol JC3015_1
CH5|CH6|CH7|CH8
---|---|---|---
FLIP|MODE|PICTURE|VIDEO
###Sub_protocol JC3015_2
### Sub_protocol JC3015_2
CH5|CH6|CH7|CH8
---|---|---|---
FLIP|MODE|LED|DFLIP
###Sub_protocol MK33041
### Sub_protocol MK33041
CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---
FLIP|MODE|PICTURE|VIDEO|HEADLESS|RTH
##ESKY
## ESKY
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GYRO|PITCH
##FY326
## FY326
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT|CALIBRATE
##FQ777
## FQ777
Model: FQ777-124
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
##HISKY
## HISKY
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|GEAR|PITCH|GYRO|CH8
GYRO: -100%=6G, +100%=3G
###HK310
### HK310
Models: RX HK-3000, HK3100 and XY3000 (TX are HK-300, HK-310 and TL-3C)
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
|||T|R|AUX|T_FSAFE|R_FSAFE|AUX_FSAFE
##KN
## KN
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|DR|THOLD|IDLEUP|GYRO|Ttrim|Atrim|Etrim
Dual Rate: +100%=full range, Throttle Hold: +100%=hold, Idle Up: +100%=3D, GYRO: -100%=6G, +100%=3G
###Sub_protocol WLTOYS
###Sub_protocol FEILUN
### Sub_protocol WLTOYS
### Sub_protocol FEILUN
Same channels assignement as above.
##HONTAI
## HONTAI
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|CAL
###Sub_protocol HONTAI
###Sub_protocol JJRCX1
### Sub_protocol HONTAI
### Sub_protocol JJRCX1
CH6|
---|
ARM|
###Sub_protocol X5C1 clone
### Sub_protocol X5C1 clone
##MJXQ
## MJXQ
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|AUTOFLIP|PAN|TILT
###Sub_protocol WLH08
###Sub_protocol X600
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
###Sub_protocol X800
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
###Sub_protocol H26D
###Sub_protocol E010
### Sub_protocol WLH08
##MT99XX
### Sub_protocol X600
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol X800
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol H26D
### Sub_protocol E010
## MT99XX
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS
###Sub_protocol MT
### Sub_protocol MT
Models: MT99xx
###Sub_protocol H7
### Sub_protocol H7
Models: Eachine H7, Cheerson CX023
###Sub_protocol YZ
### Sub_protocol YZ
Model: Yi Zhan i6S
Only one model can be flown at the same time since the ID is hardcoded.
###Sub_protocol LS
### Sub_protocol LS
Models: LS114, 124, 215
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|INVERT|PICTURE|VIDEO|HEADLESS
##Shenqi
## Shenqi
Autobind protocol
Model: Shenqiwei 1/20 Mini Motorcycle
@ -386,27 +396,27 @@ CH1|CH2|CH3|CH4
Throttle +100%=full forward,0%=stop,-100%=full backward.
##SLT
## SLT
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GEAR|PITCH
##Symax
## Symax
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP||PICTURE|VIDEO|HEADLESS
###Sub_protocol SYMAX
### Sub_protocol SYMAX
Models: Syma X5C-1/X11/X11C/X12
###Sub_protocol SYMAX5C
### Sub_protocol SYMAX5C
Model: Syma X5C (original) and X2
##V2X2
## V2X2
Models: WLToys V202/252/272, JXD 385/388, JJRC H6C, Yizhan Tarantula X6 ...
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
@ -417,17 +427,21 @@ PICTURE: also automatic Missile Launcher and Hoist in one direction
VIDEO: also Sprayer, Bubbler, Missile Launcher(1), and Hoist in the other dir
##YD717
## YD717
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
###Sub_protocol YD717
###Sub_protocol SKYWLKR
###Sub_protocol SYMAX4
###Sub_protocol XINXUN
###Sub_protocol NIHUI
### Sub_protocol YD717
### Sub_protocol SKYWLKR
### Sub_protocol SYMAX4
### Sub_protocol XINXUN
### Sub_protocol NIHUI
Same channels assignement as above.

View File

@ -10,21 +10,21 @@ The source code is partly based on the Deviation TX project, thanks to all the d
**To download the latest compiled version (hex file), click on [Release](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) on the top menu.**
##Contents
## Contents
[Compatible TX](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module#compatible-tx)
[Compatible TX](README-old.md#compatible-tx)
[Protocols](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module#protocols)
[Protocols](README-old.md#protocols)
[Hardware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module#hardware)
[Hardware](README-old.md#hardware)
[Compilation and programmation](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module#compilation-and-programmation)
[Compilation and programmation](README-old.md#compilation-and-programmation)
[Troubleshooting](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module#troubleshooting)
[Troubleshooting](README-old.md#troubleshooting)
##Compatible TX
## Compatible TX
###Using standard PPM output (trainer port)
### Using standard PPM output (trainer port)
The multiprotocol TX module can be used on any TX with a trainer port.
Channels order is AETR by default but can be changed in the _Config.h.
@ -44,7 +44,7 @@ Settings per selection are located in _Config.h:
- Option: -127..+127 allowing to set specific protocol options. Like for Hubsan to set the video frequency.
- Autobind: Yes or No. At the model selection (or power applied to the TX) a bind sequence will be initiated
###Using a serial output
### Using a serial output
The multiprotocol TX module takes full advantage of being used on a Turnigy 9X, 9XR, 9XR Pro, Taranis, 9Xtreme, AR9X, ... running [er9x](http://openrcforums.com/forum/viewtopic.php?f=5&t=4598) or [ersky9X](http://openrcforums.com/forum/viewtopic.php?f=7&t=4676). An OpenTX version for Taranis is available [here](http://plaisthos.de/opentx/).
This enables full integration using the radio GUI to setup models with all the available protocols options.
@ -65,7 +65,7 @@ Notes:
- There are 2 versions of serial protocol either 8 or 16 channels. 16 channels is the latest and only available version going forward. Make sure to use the right version based on your version of er9x/ersky9x.
- Channels order is AETR by default but can be changed in _Config.h.
###Telemetry
### Telemetry
There are 4 protocols supporting telemetry: Hubsan, DSM, FrSkyD and FrSkyX.
@ -94,9 +94,9 @@ Enabling telemetry on a 9XR PRO and may be other TXs does not require any hardwa
Once the TX is telemetry enabled, it just needs to be configured on the model (see er9x/ersky9x documentation).
##Protocols
## Protocols
###TX ID
### TX ID
The multiprotocol TX module is using a 32bits ID generated randomly at first power up. This global ID is used by nearly all protocols.
There are little chances to get a duplicated ID.
@ -104,7 +104,7 @@ For DSM2/X and Devo the CYRF6936 unique manufacturer ID is used.
It's possible to generate a new ID using bind button on the Hubsan protocol during power up.
###Bind
### Bind
To bind a model in PPM Mode press the physical bind button, apply power and then release.
In Serial Mode you have 2 options:
@ -115,9 +115,9 @@ Notes:
- the physical bind button is only effective at power up. Pressing the button later has no effects.
- a bind in progress is indicated by the LED fast blinking. Make sure to bind during this period.
###Protocol selection
### Protocol selection
####Using the dial for PPM input
#### Using the dial for PPM input
PPM is only allowing access to a subset of existing protocols.
The protocols, subprotocols and all other settings can be personalized by modifying the **_Config.h** file.
@ -145,10 +145,10 @@ Dial|Protocol|Sub_protocol|RX Num|Power|Auto Bind|Option|RF Module
Note:
- The dial selection must be done before the power is applied.
####Using serial input with er9x/ersky9x
#### Using serial input with er9x/ersky9x
Serial is allowing access to all existing protocols & sub_protocols listed below.
#####A7105 RF module
##### A7105 RF module
Protocol|Sub_protocol
--------|------------
Flysky|
@ -158,7 +158,7 @@ Flysky|
|V912
Hubsan|
#####CC2500 RF module
##### CC2500 RF module
Protocol|Sub_protocol
--------|------------
FrSkyV|
@ -168,7 +168,7 @@ FrSkyX|
|CH_8
SFHSS|
#####CYRF6936 RF module
##### CYRF6936 RF module
Protocol|Sub_protocol
--------|------------
DSM|
@ -177,7 +177,7 @@ DSM|
Devo|
J6Pro|
#####NRF24L01 RF module
##### NRF24L01 RF module
Protocol|Sub_protocol
--------|------------
Hisky|
@ -235,12 +235,12 @@ HONTAI|
Note:
- The dial should be set to 0 for serial. Which means all protocol selection pins should be left unconnected.
###Protocols details
### Protocols details
**Check the [Protocols_Details.md](./Protocols_Details.md) file for a detailed description of every protocols with channels assignements.**
##Hardware
## Hardware
###RF modules
### RF modules
Up to 4 RF modules can be installed:
- [A7105](http://www.banggood.com/XL7105-D03-A7105-Modification-Module-Support-Deviation-Galee-Flysky-p-922603.html) for Flysky, Hubsan
- [CC2500](http://www.banggood.com/CC2500-PA-LNA-Romote-Wireless-Module-CC2500-SI4432-NRF24L01-p-922595.html) for FrSkyV, FrSkyD, FrSkyX and SFHSS
@ -251,21 +251,21 @@ RF modules can be installed for protocols need only. Example: if you only need t
You also need some [antennas](http://www.banggood.com/2_4GHz-3dBi-RP-SMA-Connector-Booster-Wireless-Antenna-Modem-Router-p-979407.html) and [cables](http://www.banggood.com/10cm-PCI-UFL-IPX-to-RPSMA-Female-Jack-Pigtail-Cable-p-924933.html).
###Board
### Board
The main program is running on an ATMEGA328p running @16MHz and 3.3V.
An [Arduino pro mini 16Mhz/5V](http://www.banggood.com/Wholesale-New-Ver-Pro-Mini-ATMEGA328-328p-5V-16MHz-Arduino-Compatible-Nano-Size-p-68534.html) powered at 3.3V (yes it works) can be used to build your own Multimodule. An Arduino Mini based on Atmega328p can also be used.
####Using stripboard:
#### Using stripboard:
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/t8214655-87-thumb-uploadfromtaptalk1405598143749.jpg?d=1441459923)
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/t8214656-102-thumb-uploadfromtaptalk1405598152484.jpg?d=1441459924)
####Using a [home made PCB](http://www.rcgroups.com/forums/showpost.php?p=32645328&postcount=1621):
#### Using a [home made PCB](http://www.rcgroups.com/forums/showpost.php?p=32645328&postcount=1621):
![Screenshot](http://static.rcgroups.net/forums/attachments/1/1/5/4/3/7/t8226720-197-thumb-IMG_20150715_230603155.jpg?d=1441816457)
![Screenshot](http://static.rcgroups.net/forums/attachments/1/1/5/4/3/7/t8226719-72-thumb-IMG_20150715_230024065.jpg?d=1441816456)
####Build your own board using [SMD components](http://www.rcgroups.com/forums/showpost.php?p=31064232&postcount=1020) and an [associated PCB v2.3c](https://oshpark.com/shared_projects/MaGYDg0y):
#### Build your own board using [SMD components](http://www.rcgroups.com/forums/showpost.php?p=31064232&postcount=1020) and an [associated PCB v2.3c](https://oshpark.com/shared_projects/MaGYDg0y):
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/t7566755-3-thumb-i.png?d=1423810885)
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/t7952726-108-thumb-image-62c29cf2.jpg?d=1433909893)
@ -284,7 +284,7 @@ lines through them.
[OSH Park link](https://oshpark.com/shared_projects/Ztus1ah8) if you want to order.
####Buy a ready to use and complete Multi module
#### Buy a ready to use and complete Multi module
![Screenshot](http://img.banggood.com/thumb/view/oaupload/banggood/images/1D/EB/19bb6434-4616-411e-b8fa-a4c21d9dca24.jpg)
This module can be purchased [here](http://www.banggood.com/2_4G-CC2500-A7105-Flysky-Frsky-Devo-DSM2-Multiprotocol-TX-Module-With-Antenna-p-1048377.html). All the 4 RF modules are already implemented A7105, NRF24L01, CC2500 and CYRF6936. The board is also equiped with an antenna switcher which means only one antenna for all.
@ -293,20 +293,18 @@ This module can be purchased [here](http://www.banggood.com/2_4G-CC2500-A7105-Fl
If you want to enable serial mode for er9x/ersky9x/Taranis/... and depending on your board revision, you have to do one of these modifications:
- 1st revision, add 2 resistors as shown here: ![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/a8895038-170-4in1%20module.jpg)
- 2nd revision, solder pads together as shown:
<img src="http://static.rcgroups.net/forums/attachments/4/8/3/5/8/4/a9206217-177-IMG_5790.jpg" width="350">
- 2nd revision, solder pads together as shown: <br> <img src="http://static.rcgroups.net/forums/attachments/4/8/3/5/8/4/a9206217-177-IMG_5790.jpg" width="350">
Note: if you have the 1st board revision (check pictures above), sometime bind occures at power up even without pressing the bind button or not having an autobind protocol. To solve this issue, replacing the BIND led resistor (on the board back) of 1.2K by a 4.7K.
###Schematic
### Schematic
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/a8443844-119-multiprotocol_diagram_rotary_serial_2.jpg)
Notes:
- Attention: All modules are 3.3V only, never power them with 5V.
- For serial, the dial switch is not needed and the bind button optionnal
###Radio integration
### Radio integration
If you build your own version of the board you can 3D print this case (details [here](http://www.rcgroups.com/forums/showpost.php?p=33294140&postcount=2034)):
![Screenshot](http://static.rcgroups.net/forums/attachments/1/1/5/4/3/7/t8462144-54-thumb-Multi_case_9XR.jpg?d=1448575289)
@ -318,9 +316,9 @@ If you have the Banggood ready to use board you can 3D print this case (details
<img src="http://static.rcgroups.net/forums/attachments/4/8/3/5/8/4/a9206411-90-IMG_5793.jpeg" width="200">
<img src="http://static.rcgroups.net/forums/attachments/4/8/3/5/8/4/a9206445-131-IMG_5796.jpeg" width="200">
##Compilation and programmation
## Compilation and programmation
###Toolchain
### Toolchain
Multiprotocol source can be compiled using the Arduino IDE.
The currently supported Arduino version is [1.6.10](https://www.arduino.cc/download_handler.php?f=/arduino-1.6.10-windows.exe).
@ -335,7 +333,7 @@ Notes:
- Compilation of the code posted here works. So if it doesn't for you this is a problem with your setup, please double check everything before asking.
- If you want to reduce the code size even further, you can modify the file platform.txt located in "C:\Program Files (x86)\Arduino\hardware\arduino\avr". Set the line "compiler.c.elf.extra_flags=" to "compiler.c.elf.extra_flags=-Wl,--relax".
###Upload the code using ISP (In System Programming)
### Upload the code using ISP (In System Programming)
It is recommended to use an external programmer like [USBASP](http://www.banggood.com/USBASP-USBISP-3_3-5V-AVR-Downloader-Programmer-With-ATMEGA8-ATMEGA128-p-934425.html) to upload the code in the Atmega328. The programmer should be set to 3.3V or nothing to not supply any over voltage to the multimodule and avoid any damages.
The dial must be set to 0 before flashing!
@ -344,7 +342,7 @@ From the Arduino environment, you can use this shortcut to compile and upload to
To flash the latest provided hex file under [Release](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases), you can use a tool like [AVR Burn-O-Mat](http://avr8-burn-o-mat.aaabbb.de/), set the microcontroller to m328p and flash it.
###Upload the code using FTDI (USB serial to TTL)
### Upload the code using FTDI (USB serial to TTL)
Use this method only for Arduino Pro Mini boards with bootloader.
Use an external FTDI adapter like [this one](http://www.banggood.com/FT232RL-FTDI-USB-To-TTL-Serial-Converter-Adapter-Module-For-Arduino-p-917226.html).
@ -355,7 +353,7 @@ From the Arduino environment, you can use Upload button which will compile and u
To upload the latest provided hex file under [Release](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases), you can use a tool like [XLoader](http://russemotto.com/xloader/), set the microcontroller to Atmega328 and upload it.
###Set fuses
### Set fuses
Use a tool like [AVR Burn-O-Mat](http://avr8-burn-o-mat.aaabbb.de/) to set the fuses of the Atmega328 to:
- Extended Fuse 0x05 (or 0xFD which is the same)
- High Fuse 0xD2
@ -363,25 +361,25 @@ Use a tool like [AVR Burn-O-Mat](http://avr8-burn-o-mat.aaabbb.de/) to set the f
This will make sure your ATMEGA328 is well configured and the global TX ID is not erased at each updates.
##Troubleshooting
## Troubleshooting
###LED status
### LED status
- off: program not running or a protocol selected with the associated module not installed.
- flash(on=0.1s,off=1s): invalid protocol selected (excluded from compilation or invalid protocol number)
- slow blink(on=0.5s,off=0.5s): serial has been selected but no valid signal has been seen on the RX pin.
- fast blink(on=0.1s,off=0.1s): bind in progress.
- on: normal operation.
###Protocol selection
####Input Mode - PPM
### Protocol selection
#### Input Mode - PPM
- The protocol/mode selection must be done before the power is applied.
- Connect 1 to 4 of the selection protocol pins to GND.
####Input Mode - Serial
#### Input Mode - Serial
- Make sure you have done the mods to the v2.3c PCB by adding the 2.2k and 470 ohm resistors as indicated in the [Board section] (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module#board).
- Leave all 4 selection pins unconnected.
###Bind
### Bind
Make sure to follow this procedure: press the bind button, apply power and then release it after 1sec. The LED should be blinking fast indicating a bind status and then fixed on when the bind period is over. It's normal that the LED turns off when you press the bind button, this behavior is not controlled by the Atmega328.
For serial, the preffered method is to bind via the GUI protocol page.
@ -389,7 +387,7 @@ If your module is always/sometime binding at power up without pressing the butto
- Arduino Pro Mini with an external status LED: to work around this issue connect a 10K resistor between D13 and 3.3V.
- 4in1 module V1 (check 4in1 pictures): to solve this issue, replacing the BIND led resistor (on the board back) of 1.2K by a 4.7K.
###Report issues
### Report issues
You can report your problem using the [GitHub issue](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues) system or go to the [Main thread on RCGROUPS](http://www.rcgroups.com/forums/showthread.php?t=2165676) to ask your question.
Please provide the following information:
- Multiprotocol code version

View File

@ -7,7 +7,7 @@ There are two different modes to interface the MULTI-Module and the transmitter:
Any Tx providing a PPM output (like a trainer port, or a transmitter with a RF module bay) is compatible with the MULTI-module.
##PPM
## PPM
The DIY Mulitprotocol module supports industry standard PPM interface that works with all transmitters with either a module bay, and/or a trainer port. Even the older 72MHz FM radios support this standard.
<img src="images/PPM.png" width="338" height="200" />
@ -22,7 +22,7 @@ Even in PPM mode it may still be possible to access telemetry information from s
For transmitter setup using the PPM protocol go to the [PPM Setup page](PPM_Setup.md)
##Serial
## Serial
Transmitters that run er9X, erSky9X or OpenTx firmwares (like the FrSky Taranis, FlySky TH9X and Turnigy 9X family of transmitters) have the option of using a fast serial communication protocol between the Tx and the DIY Multiprotocol module. Using this serial communication protocol has some significant advantages:
1. selecting the specific radio protocol (e.g. DSM) and the sub protocol (e.g. DSMX22) is done directly in the menu system of the Tx (see the picture below)
@ -50,7 +50,7 @@ Transmitter|Firmware Options|Telemetry Enabled
Click on your transmitter above to view specific setup instructions.
##Telemetry
## Telemetry
To enable serial telemetry you need one of the radios and firmwares listed in the table above and **may** require modifications to your Tx. See the table above. Before attempting telemetry check the following:
@ -59,7 +59,7 @@ To enable serial telemetry you need one of the radios and firmwares listed in th
1. Your transmitter hardware is telemetry enabled, or you have done the required mods. Check the table above.
<a name="Telemetry_Mod"></a>
##Optional Telemetry mod for 9X/R TH9X transmitters
## Optional Telemetry mod for 9X/R TH9X transmitters
The telemetry mod for these transmitters has evolved. The original and popular "FrSky Telemetry Mod" requires 2 pins on the transmitter module board to be modified (RX on pin 5 and TX on pin 2). All the recent MULTI-Module hardware options supports serial transmission on pin 1 (the same pin as the PPM signal) so, in this case, only the mod on pin 5 is required.
A good tutorial to follow is Oscar Liang's [here](http://blog.oscarliang.net/turnigy-9x-advance-mod/) but when you get to wiring up the Tx Module bay pins, you only need to perform the steps relevant for Pin 5.
@ -67,7 +67,7 @@ A good tutorial to follow is Oscar Liang's [here](http://blog.oscarliang.net/tur
You can see Midelic's original instructions [here](http://www.rcgroups.com/forums/showpost.php?p=28359305&postcount=2)
##Other Notes:
## Other Notes:
- er9X and erSky9X firmware already supports Multiprotocol Module as a standard feature. The next major release of OpenTx - OpenTx 2.2 - will have DIY Mulitprotocol support as a standard feature.
- Owners of Walkera Devo transmitters should look at the [Deviation-Tx](http://www.deviationtx.com) project for how to achieve the same end goal with your transmitters.

View File

@ -1,32 +1,39 @@
# Troubleshooting
##LED status
###Green LED
- Off: no power to the module
- On: module is powered up
## LED status
###Red LED (bind LED)
- Off: program not running or a protocol selected with the associated module not installed
- Flash(on=0.05s,off=1s): invalid protocol selected (excluded from compilation or invalid protocol number)
- Inverted Flash(on=1s,off=0.1s): module is waiting for a bind event (Bind from channel or Bind in radio GUI) to launch the protocol in bind mode
- Fast blink(on=0.1s,off=0.1s): bind in progress
- Slow blink(on=0.5s,off=0.5s): serial has been selected but no valid signal is being seen on the RX pin.
- Slower blink(on=1s,off=1s): PPM has been selected but no valid signal is being seen on the PPM pin.
- On: Module is in normal operation mode (transmitting control signals).
### Green LED
- **_Off_**: no power to the module
- **_On_**: module is powered up
### Red LED (bind LED)
- **_Off_**: program not running or a protocol selected with the associated module not installed
- **_Flash(on=0.05s,off=1s)_**: invalid protocol selected (excluded from compilation or invalid protocol number)
- **_Inverted Flash(on=1s,off=0.1s)_**: module is waiting for a bind event (Bind from channel or Bind in radio GUI) to launch the protocol in bind mode
- **_Fast blink(on=0.1s,off=0.1s)_**: bind in progress
- **_Slow blink(on=0.5s,off=0.5s)_**: serial has been selected but no valid signal is being seen on the RX pin.
- **_Slower blink(on=1s,off=1s)_**: PPM has been selected but no valid signal is being seen on the PPM pin.
- **_On_**: Module is in normal operation mode (transmitting control signals).
## Protocol selection
### Input Mode - PPM
##Protocol selection
###Input Mode - PPM
- The protocol/mode selection must be done before the power is applied to the module
- Often the signal is not sent to the module until the transmitter has performed safety checks (like switch and throttle position settings)
- Check that at least one of the protocol selection pins is connected to GND.
- Some radios have an open collector output (Futaba, Graupner...), in this case add a 4.7K resistor between PPM and BATT.
###Input Mode - Serial
- Make sure you have done the serial mods as indicated in the [hardware page for your board] (Hardware.md).
### Input Mode - Serial
- Make sure you have done the serial mods as indicated in the [hardware page for your board](Hardware.md).
- Protocol selection dial must be in the 0 position or leave all 4 selection pins unconnected.
- Often the signal is not sent to the module until the transmitter has performed safety checks (like switch and throttle position settings)
##Bind
## Bind
Make sure to follow this procedure: press the bind button, apply power and then release after the red LED starts flashing. The LED should be blinking fast indicating a bind status and then fixed on when the bind period is over. It's normal that the LED turns off when you press the bind button, this behavior is not controlled by the Atmega328.
For serial, the preffered method is to bind via the GUI protocol page.
@ -39,7 +46,8 @@ FrSky & SFHSS bind issues are ususally due to Option=fine frequency tuning not s
- find the values min/max where the RX loses connection. In serial mode you can change the value and see the effect live.
- set the value to half way between min and max.
##Report issues
## Report issues
You can report your problem using the [GitHub issue](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues) system or go to the [Main thread on RCGROUPS](http://www.rcgroups.com/forums/showthread.php?t=2165676) to ask your question.
Please provide the following information:
- Multiprotocol code version

View File

@ -1,4 +1,4 @@
#Flysky TH9X family of transmitters
# Flysky TH9X family of transmitters
This page is relevant to the following transmitters:
* FlySky TH9X
* Turnigy 9X, Turnigy 9XR
@ -19,7 +19,7 @@ Serial mode is only supported by the er9X firmware. Loading this firmware is be
er9X is very well documented, see [here](http://openrcforums.com/forum/viewtopic.php?f=5&t=6473#p90349)
###Enabling Serial Mode
### Enabling Serial Mode
1. Confirm that the MULTI-Module has the required physical connections between the pins on the back of the Tx and the ATMega328 microprocessor. This may require some soldering and depends on which version of the MULTI-Module you have. Check out your modules hardware page under the section **Enabling your MULTI-Module for Serial** for details. Click here for the [hardware](Hardware.md) pages.
1. Plug in your DIY Multiprotocol module into the transmitter module bay. If you have a rotary protocol selection switch, turn the switch to position 0 to put the unit into Serial mode.
1. Ensure throttle is down and all switches are in the start position and power up the Tx. The red LED on the DIY Multiprotocol module should be flashing with a period of about 1 second indicating that it has not established a valid serial link with the Tx. This is expected as we have not set up the Tx yet.
@ -27,13 +27,13 @@ er9X is very well documented, see [here](http://openrcforums.com/forum/viewtopic
1. In the Model Settings menu scroll down to change the RF settings to MULTI {mikeb - can you write this line }
1. The red LED on the MULTI-Module should briefly flash and then go off. This confirms that the MULTI-Module has established serial communication with the Tx. If the red LED on the module continues to flash at a period of about 1 seconds then it signals that serial communication has not been established. Check your settings under the model menu as described above and check that the protocol selection switch on the module is at 0 (enable Serial mode). If there is still no communication, power down and power up the Tx. Finally check that you have correctly enabled your module for serial as described on the hardware page for your module under the heading "Enabling your module for Serial". Click here to access the [hardware](Hardware.md) and then click on the picture of your module.
###Protocol Selection in Serial mode
### Protocol Selection in Serial mode
To select the protocol:
1. In the Model Setting menu, scroll through the available options under the MULTI option {mikeb to confirm}.
1. Depending on which protocol you have selected you may be required to select a sup-protocol and options. For example, the FrSky protocol has three sub-protocols FrSky_V, FrSky_D and FrSky_X. In some cases the sub-protocols have options that could specify the number of channels, packet frame rate or fine frequency tuning. Check out the [Protocol Details](Protocol_Details.md) page for detailed information and suggestions regarding the sub-protocols and options. The picture below shows the settings in the erSky Model Setup menu for FrSkyX subprotocol with {mike to insert} options:
1. Depending on which protocol you have selected you may be required to select a sup-protocol and options. For example, the FrSky protocol has three sub-protocols FrSky_V, FrSky_D and FrSky_X. In some cases the sub-protocols have options that could specify the number of channels, packet frame rate or fine frequency tuning. Check out the [Protocol Details](../Protocols_Details.md) page for detailed information and suggestions regarding the sub-protocols and options. The picture below shows the settings in the erSky Model Setup menu for FrSkyX subprotocol with {mike to insert} options:
{mikeb to send simple picture}
###Binding in Serial mode
### Binding in Serial mode
1. Switch on the model or put the receiver into bind mode
1. On the transmitter go to the Model Settings menu and scroll down to the [Bind] menu option and press Enter.
1. Press Enter again to exit Bind mode

View File

@ -17,15 +17,13 @@ The MULTI-module can be used with all transmitters and firmwares in PPM mode. T
## PPM Mode
Please refer to the [PPM Setup](PPM_Setup.md) page.
##Serial mode
###Enabling Serial Mode
## Serial mode
### Enabling Serial Mode
To operate in serial mode, you need one of these firmwares:
1. erSky9x
1. OpenTx supporting the MULTI-Module (Version 2.1.8 Multi or later)
Check and upload a supported firmware. The latest available version at time of writing are:
- erSky9x Revision 218 or later - the hex files are available [here](http://www.er9x.com) (Mike's latests test versions are available [here](http://openrcforums.com/forum/viewtopic.php?f=7&t=4676)).
- OpenTx 2.1.8 Multi or later - the hex files are available [here](http://plaisthos.de/opentx/)
1. erSky9x Revision 218 or later - the hex files are available [here](http://www.er9x.com) (Mike's latests test versions are available [here](http://openrcforums.com/forum/viewtopic.php?f=7&t=4676)).
1. OpenTx supporting the MULTI-Module (Version 2.1.8 Multi or later, 2.2 recommended). Check and upload a supported firmware. The latest available version at time of writing are:
- OpenTx 2.2RC16 or later [www.open-tx.org](http://www.open-tx.org/)
- Please make sure that the "multimodule" option in OpenTX Companion is checked: <br> <img src="images/opentx-config-multi.png"> <br>
Tutorials for uploading new firmware using the SD Card are available [here](http://www.dronetrest.com/t/how-to-upgrade-firmware-for-frsky-taranis-x9d/959) or the CompanionTx or eepe software (recommended) are available [here](http://open-txu.org/home/undergraduate-courses/fund-of-opentx/part-2-flashing-opentx/).
@ -33,38 +31,22 @@ Tutorials for uploading new firmware using the SD Card are available [here](http
First, confirm that the MULTI-Module has the required physical connections between the pins on the back of the Tx and the ATMega328 microprocessor. This may require some soldering and depends on which version of the DIY Multiprotocol module you have. Check out the specific pages for your module hardware (under the section "Enabling Serial") linked [here](Hardware.md) for details.
1. Plug in your MULTI-Module into the transmitter's module bay.
2. If you have a rotary protocol selection switch, turn the switch to position 0 to put the unit into Serial mode.
2. Ensure throttle is down and all switches are in the start position and power up the Transmitter. The red LED on the MULTI-Module should be flashing with a period of about 1s indicating that it has not established a valid serial link with the Tx. This is expected as we have not set up the Tx yet.
3. Create a new model (make sure channel order is AETR - **This is really important - this is for all protocols - even for DSM as the MULTI-module firware will change the transmitted channel order according to the protocol.**) and on the first Model Settings page scroll down to disable the internal RF and enable the external RF by selecting MULTI as the external RF. Your Transmitter settings should look like this:
1. Plug in your MULTI-Module into the transmitter's module bay.
1. If you have a rotary protocol selection switch, turn the switch to position 0 to put the unit into Serial mode.
1. Ensure throttle is down and all switches are in the start position and power up the Transmitter. The red LED on the MULTI-Module should be flashing with a period of about 1s indicating that it has not established a valid serial link with the Tx. This is expected as we have not set up the Tx yet.
1. Create a new model (make sure channel order is AETR - **This is really important - this is for all protocols - even for DSM as the MULTI-module firware will change the transmitted channel order according to the protocol.**) and on the first Model Settings page scroll down to disable the internal RF and enable the external RF by selecting MULTI as the external RF. Your Transmitter settings should look like this: <br> <img src="images/settings-horus.png" /> <br> or <br> <img src="images/settings-taranis.png" /> <br> The Red LED on the MULTI-Module should briefly flash and then stay on. This confirms that the MULTI-Module module has established serial communication with the Tx.
1. If the red LED on the module continues to flash at a period of about 1s then it signals that serial communication has not been established. Check your settings under the model menu as described above and check that the protocol selection switch on the module is at 0 (zero). If there is still no communication, power down and power up the Tx. Finally check that you have correctly enabled your module for serial as described in specific pages for your module hardware (under the section "Enabling Serial") linked [here](Hardware.md)
<img src="images/settings-horus.png" /> or <img src="images/settings-taranis.png" />
The Red LED on the MULTI-Module should briefly flash and then stay on. This confirms that the MULTI-Module module has established serial communication with the Tx.
4. If the red LED on the module continues to flash at a period of about 1s then it signals that serial communication has not been established. Check your settings under the model menu as described above and check that the protocol selection switch on the module is at 0 (zero). If there is still no communication, power down and power up the Tx. Finally check that you have correctly enabled your module for serial as described in specific pages for your module hardware (under the section "Enabling Serial") linked [here](Hardware.md)
###Protocol Selection in Serial mode
### Protocol Selection in Serial mode
To select the protocol, scroll through the available options under the Model Settings menu. Depending on which protocol you have selected you may be required to select a sup-protocol and options. For example, the FrSky protocol has three sub-protocols FrSkyV, FrSkyD and FrSkyX. Each of the sub-protocols may have options that specify the number of channels and the packet frame rate, etc.
The following picture shows DSM DSMX Option 6 (6 channels and 11ms frame rate). Check out the [Protocol Details](Protocol_Details.md) page for detailed information and suggestions regarding the sub-protocols and options.
###Protcol Status in Serial mode (OpenTX)
If you see ```NO MULTI_TELEMETRY``` or no ```NO TELEMETRY``` in the setup screen of the external module, like this:
<img width="594" height="213" src="images/X7-no-telemetry.png" />
you are missing the ```MULTI_TELEMETRY``` and/or ```INVERT_TELEMTRY``` option in your ```_Config.h``` and/or [you need to hardware modifications to enable telemetry](Hardware.md). OpenTX also shows the ```NO TELEMETRY``` message if no module status has been received in the last 2s which can indicate a non working module if the telemetry status worked before. With the option enabled, the right telemetry type is automatically detected and you will see the status of the module:
<img width="580" height="210" src="images/X7-protocol-invalid.png">
(Selected protocol is not available, most probably mssing from ```_Config.h```)
<img width="576" height="209" src="images/X7-bind.png">
(Module is currently binding and code on the module is running V1.1.6.10)
### Protcol Status in Serial mode (OpenTX)
If you see ```NO MULTI_TELEMETRY``` or no ```NO TELEMETRY``` in the setup screen of the external module, like this: <br> <img width="594" height="213" src="images/X7-no-telemetry.png" /> <br> you are missing the ```MULTI_TELEMETRY``` and/or ```INVERT_TELEMTRY``` option in your ```_Config.h``` and/or [you need to hardware modifications to enable telemetry](Hardware.md). OpenTX also shows the ```NO TELEMETRY``` message if no module status has been received in the last 2s which can indicate a non working module if the telemetry status worked before. With the option enabled, the right telemetry type is automatically detected and you will see the status of the module: <br> <img width="580" height="210" src="images/X7-protocol-invalid.png"> <br> (Selected protocol is not available, most probably mssing from ```_Config.h```) <br> <img width="576" height="209" src="images/X7-bind.png"> <br> (Module is currently binding and code on the module is running V1.1.6.10)
###Binding in Serial mode
### Binding in Serial mode
1. Switch on the model or put the receiver into bind mode
1. On the transmitter go to the Model Settings menu and scroll down to the [Bind] menu option and press Enter.
1. Press Enter again to exit Bind mode

View File

@ -1,4 +1,4 @@
#erSky9X family of transmitters
# erSky9X family of transmitters
This page is relevant to the following transmitters:
- Taranis running erSky9X (for the Taranis running OpenTx see [here](Tx-Taranis.md))
- Turnigy 9XR Pro (for Turnigy 9X see [here](Tx-FlyskyTH9X.md))
@ -21,7 +21,7 @@ Serial mode is only supported by the erSky9X firmware. Loading this firmware is
erSky9X is well documented, the slightly outdated erSky9X documentation is [here](http://openrcforums.com/forum/viewtopic.php?f=5&t=6473#p90349). You may find the new Er9x manual very helpful in understanding Ersky9x as the two firmwares are very closely related. It provides more detailed explanations and numerous relevant programming examples and is available [here](http://openrcforums.com/forum/viewtopic.php?f=5&t=6473#p90349).
###Enabling Serial Mode
### Enabling Serial Mode
1. Confirm that the MULTI-Module has the required physical connections between the pins on the back of the Tx and the ATMega328 microprocessor. This may require some soldering and depends on which version of the MULTI-Module you have. Check out your modules hardware page under the section **Enabling your module for Serial** for details. Click on the image that corresponds to your MULTI-Module on the [hardware](Hardware.md) page.
1. Plug in your MULTI-Module into the transmitter module bay. If you have a rotary protocol selection switch, turn the switch to position 0 to put the unit into Serial mode.
1. Ensure throttle is down and all switches are in the start position and power up the Tx. The red LED on the MULTI-Module should be flashing with a period of about 1 second indicating that it has not established a valid serial link with the Tx. This is expected as we have not set up the Tx yet.
@ -29,13 +29,13 @@ erSky9X is well documented, the slightly outdated erSky9X documentation is [here
1. In the Model Setup menu scroll down to the **Protocol** submenu and change the RF settings to MULTI. This should reveal a set of additional options (like Protocol and Options)
1. The red LED on the MULTI-Module should briefly flash and then remain solid. This confirms that the MULTI-Module has established serial communication with the Tx. If the red LED on the module continues to flash at a period of about 1 seconds then it signals that serial communication has not been established. Check your settings under the model menu as described above and check that the protocol selection switch on the module is at 0 (enable Serial mode). If there is still no communication, power down and power up the Tx. Finally check that you have correctly enabled your module for serial as described on the hardware page for your module under the heading "Enabling your module for Serial". Click here to access the [hardware](Hardware.md) and then click on the picture of your module.
###Protocol Selection in Serial mode
### Protocol Selection in Serial mode
To select the protocol:
1. In the Model Setting menu, scroll through the available options under the MULTI protocol
1. Depending on which protocol you have selected you may be required to select a sup-protocol and options. For example, there are three protocols that correspond to FrSky recievers: FrSky_V, FrSky_D and FrSky_X. In some cases the sub-protocols have options that could specify the number of channels, packet frame rate or fine frequency tuning. Check out the [Protocol Details](Protocol_Details.md) page for detailed information and suggestions regarding the sub-protocols and options. The picture below shows the settings in the erSky Model Setup menu for FrSkyX subprotocol with {mike to insert} options:
1. Depending on which protocol you have selected you may be required to select a sup-protocol and options. For example, there are three protocols that correspond to FrSky recievers: FrSky_V, FrSky_D and FrSky_X. In some cases the sub-protocols have options that could specify the number of channels, packet frame rate or fine frequency tuning. Check out the [Protocol Details](../Protocols_Details.md) page for detailed information and suggestions regarding the sub-protocols and options. The picture below shows the settings in the erSky Model Setup menu for FrSkyX subprotocol with {mike to insert} options:
{mikeb to send simple picture}
###Binding in Serial mode
### Binding in Serial mode
1. Switch on the model or put the receiver into bind mode
1. On the transmitter go to the Model Settings menu and scroll down to the [Bind] menu option and press Enter.
1. Press Enter again to exit Bind mode

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB