mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-01 10:17:53 +00:00
Board Definition Updates (#121)
This commit is contained in:
parent
f46b8366b0
commit
5c568da125
@ -1,3 +1,16 @@
|
|||||||
## Save hex
|
## Save hex
|
||||||
recipe.output.tmp_file={build.project_name}.hex
|
recipe.output.tmp_file={build.project_name}.hex
|
||||||
recipe.output.save_file=multifw.hex
|
recipe.output.save_file=multi-avr.hex
|
||||||
|
|
||||||
|
## Copy hex
|
||||||
|
# Make a copy of the compiled binary with the version number in the file name
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
|
||||||
|
# If we're exporting the hex file, rename it with the version number
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
47
BootLoaders/Boards/avr/tools/linux/do_version
Executable file
47
BootLoaders/Boards/avr/tools/linux/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=avr
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
47
BootLoaders/Boards/avr/tools/linux64/do_version
Executable file
47
BootLoaders/Boards/avr/tools/linux64/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=avr
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
47
BootLoaders/Boards/avr/tools/macosx/do_version
Executable file
47
BootLoaders/Boards/avr/tools/macosx/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=avr
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
54
BootLoaders/Boards/avr/tools/win/do_version.bat
Normal file
54
BootLoaders/Boards/avr/tools/win/do_version.bat
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SETLOCAL EnableDelayedExpansion
|
||||||
|
|
||||||
|
SET BUILD_PATH=%1
|
||||||
|
SET PROJECT_NAME=%2
|
||||||
|
SET SKETCH_PATH=%3
|
||||||
|
SET MULTI_BOARD=%4
|
||||||
|
SET EXPORT_FLAG=%5
|
||||||
|
|
||||||
|
REM ECHO Multi board: %MULTI_BOARD%
|
||||||
|
|
||||||
|
SET MULTI_TYPE=avr
|
||||||
|
|
||||||
|
IF EXIST "%1\sketch\Multiprotocol.h" (
|
||||||
|
REM ECHO Getting Multi-MODULE firmware version from "%1\sketch\Multiprotocol.h"
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%D") do SET PATCH_VERSION=%%i
|
||||||
|
SET MULTI_VER=!MAJOR_VERSION!.!MINOR_VERSION!.!REVISION_VERSION!.!PATCH_VERSION!
|
||||||
|
) ELSE (
|
||||||
|
SET MULTI_VER=
|
||||||
|
)
|
||||||
|
|
||||||
|
REM ECHO Multi-MODULE firmware version: %MULTI_VER%
|
||||||
|
|
||||||
|
REM Copy the compiled file to the sketch folder with the version number in the file name
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" (
|
||||||
|
REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" (
|
||||||
|
REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF "%EXPORT_FLAG%"=="EXPORT" (
|
||||||
|
REM Copy the compiled file to the sketch folder with the version number in the file name
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" (
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" (
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" (
|
||||||
|
DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL
|
||||||
|
)
|
||||||
|
IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" (
|
||||||
|
DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" >NUL
|
||||||
|
)
|
||||||
|
)
|
15067
BootLoaders/Boards/orangerx/avrdude.conf
Normal file
15067
BootLoaders/Boards/orangerx/avrdude.conf
Normal file
File diff suppressed because it is too large
Load Diff
19
BootLoaders/Boards/orangerx/boards.txt
Normal file
19
BootLoaders/Boards/orangerx/boards.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||||
|
# See: http://code.google.com/p/arduino/wiki/Platforms
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
## Multi 4-in-1 (OrangeRX)
|
||||||
|
## --------------------------------------------------
|
||||||
|
multixmega32d4.name=Multi 4-in-1 (OrangeRX)
|
||||||
|
multixmega32d4.build.board=MULTI_ORANGERX
|
||||||
|
multixmega32d4.upload.protocol=arduino
|
||||||
|
multixmega32d4.upload.maximum_size=32768
|
||||||
|
multixmega32d4.upload.speed=115200
|
||||||
|
multixmega32d4.build.mcu=atxmega32d4
|
||||||
|
multixmega32d4.build.f_cpu=32000000L
|
||||||
|
multixmega32d4.build.core=xmega
|
||||||
|
multixmega32d4.build.variant=xmega32d4
|
||||||
|
|
||||||
|
##############################################################
|
450
BootLoaders/Boards/orangerx/cores/xmega/Arduino.h
Normal file
450
BootLoaders/Boards/orangerx/cores/xmega/Arduino.h
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
/*
|
||||||
|
Arduino.h - standard definitions for Arduino build environment
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2007 David A. Mellis [duplicated from pins_arduino.h, not present in original]
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
for the XMegaForArduino project - http://github.com/XMegaForArduino
|
||||||
|
|
||||||
|
In some cases, the xmega updates make assumptions about the pin assignments.
|
||||||
|
See 'pins_arduino.h' for more detail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Arduino_h
|
||||||
|
#define Arduino_h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#include "binary.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define HIGH 0x1
|
||||||
|
#define LOW 0x0
|
||||||
|
|
||||||
|
#define INPUT 0x0 /* totem poll, input */
|
||||||
|
#define OUTPUT 0x1 /* totem poll, output */
|
||||||
|
#define INPUT_BUS_KEEPER 0x2 /* weak pull up/down to maintain state when switched to or in input mode */
|
||||||
|
#define INPUT_PULLUP 0x3 /* pullup resistor on input */
|
||||||
|
#define INPUT_PULLDOWN 0x4 /* pulldown resistor on input */
|
||||||
|
#define OUTPUT_OR 0x5 /* output open drain 'or', no pulldown */
|
||||||
|
#define OUTPUT_AND 0x6 /* output open drain 'and', no pullup */
|
||||||
|
#define INPUT_OR_PULLDOWN 0x7 /* output open drain 'or' with pulldown */
|
||||||
|
#define INPUT_AND_PULLUP 0x8 /* output open drain 'and' with pullup */
|
||||||
|
#define OUTPUT_OR_PULLDOWN 0x9 /* output open drain 'or' with pulldown */
|
||||||
|
#define OUTPUT_AND_PULLUP 0xa /* output open drain 'and' with pullup */
|
||||||
|
#define INPUT_OUTPUT_MASK 0xf /* mask for INPUT/OUTPUT flags */
|
||||||
|
#define INPUT_SENSE_DEFAULT 0 /* input sense default - currently 'BOTH' */
|
||||||
|
#define INPUT_SENSE_RISING 0x10 /* just rising */
|
||||||
|
#define INPUT_SENSE_FALLING 0x20 /* just falling */
|
||||||
|
#define INPUT_SENSE_BOTH 0x30 /* rising AND falling */
|
||||||
|
#define INPUT_SENSE_LEVEL 0x40 /* high level (or low if I invert it) */
|
||||||
|
#define INPUT_SENSE_DISABLED 0x50 /* buffered input disabled (most pins won't be able to use 'IN' if you do this) */
|
||||||
|
#define INPUT_SENSE_MASK 0x70 /* mask for 'input sense' bits */
|
||||||
|
#define INPUT_OUTPUT_INVERT 0x80 /* bit for 'inverted' I/O - note that digitalRead and digitalWrite will re-invert to maintain consistency */
|
||||||
|
|
||||||
|
// NOTE: 'INPUT_OUTPUT_INVER' is primarily there to support LOW LEVEL interrupts. if you specify this flag for normal
|
||||||
|
// digital I/O, there will be no 'visible effect' since digitalRead and digitalWrite will "re-invert" the bit value
|
||||||
|
// and act as if the invert flag weren't set. That way, if you select 'LOW LEVEL' interrupt, you will read the
|
||||||
|
// low level as a '0' (as it should be) via digitalRead, even though the value MUST be inverted for this to work.
|
||||||
|
|
||||||
|
// NOTE: the values of 'true' and 'false' should be defined by C++ already
|
||||||
|
#define true /*0x1*/(!0) /* rather than '1' true is defined as '!0' - it's logically accurate */
|
||||||
|
#define false 0x0
|
||||||
|
|
||||||
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
#define HALF_PI 1.5707963267948966192313216916398
|
||||||
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
|
||||||
|
/* I do not know what these next 4 #defines do, but all 4 seem to be WRONG - bf */
|
||||||
|
#define SERIAL 0x0
|
||||||
|
#define DISPLAY 0x1
|
||||||
|
|
||||||
|
#define LSBFIRST 0
|
||||||
|
#define MSBFIRST 1
|
||||||
|
|
||||||
|
// INTERRUPT TYPE - LOW, HIGH, CHANGE, FALLING, RISING (compatibility with DUE etc.)
|
||||||
|
// 'LOW' is defined as '0' already
|
||||||
|
// 'HIGH' is defined as '1' already
|
||||||
|
#define CHANGE 2
|
||||||
|
#define FALLING 3
|
||||||
|
#define RISING 4
|
||||||
|
|
||||||
|
// definitions for atmega328 etc. carried forward - not sure what this is for
|
||||||
|
#define INTERNAL 3
|
||||||
|
#define DEFAULT 1
|
||||||
|
#define EXTERNAL 0
|
||||||
|
|
||||||
|
// undefine stdlib's abs if encountered (from 'arduino' version)
|
||||||
|
#ifdef abs
|
||||||
|
#undef abs
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define min(a,b) ((a)<(b)?(a):(b))
|
||||||
|
#define max(a,b) ((a)>(b)?(a):(b))
|
||||||
|
#define abs(x) ((x)>0?(x):-(x))
|
||||||
|
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||||
|
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||||
|
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||||
|
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||||
|
#define sq(x) ((x)*(x))
|
||||||
|
|
||||||
|
#define interrupts() sei()
|
||||||
|
#define noInterrupts() cli()
|
||||||
|
|
||||||
|
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||||
|
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
||||||
|
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
||||||
|
|
||||||
|
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||||
|
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||||
|
|
||||||
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||||
|
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||||
|
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned int word;
|
||||||
|
|
||||||
|
#define bit(b) (1UL << (b))
|
||||||
|
|
||||||
|
typedef uint8_t boolean;
|
||||||
|
typedef uint8_t byte;
|
||||||
|
|
||||||
|
void init(void);
|
||||||
|
void initVariant(void);
|
||||||
|
|
||||||
|
int atexit(void (*func)()) __attribute__((weak));
|
||||||
|
|
||||||
|
void adc_setup(void); // implemented in wiring_analog.c - configures ADC for analogRead()
|
||||||
|
// adc_setup must be called whenever exiting SLEEP MODE or ADC will malfunction
|
||||||
|
// It is automatically called from 'init()' but sleep mode typically resets the controller
|
||||||
|
|
||||||
|
void pinMode(uint8_t, uint8_t);
|
||||||
|
void digitalWrite(uint8_t, uint8_t);
|
||||||
|
int digitalRead(uint8_t);
|
||||||
|
int analogRead(uint8_t);
|
||||||
|
void analogReference(uint8_t mode); // somewhat different for xmega (default is Vcc/2) - see 'enum _analogReference_', below
|
||||||
|
// pass only one of THOSE values as 'mode'
|
||||||
|
void analogWrite(uint8_t, int);
|
||||||
|
|
||||||
|
// special XMEGA-specific functions for the analog inputs
|
||||||
|
|
||||||
|
int analogReadDeltaWithGain(uint8_t pin, uint8_t negpin, uint8_t gain);
|
||||||
|
// typically 'pin' can be A0 through An, 'negpin' may be restricted but typically A4-A7 or 'ANALOG_READ_DELTA_USE_GND' to use GND
|
||||||
|
// NOTE: On the A-series processors it is NOT possible to use 'diff input with gain' on MORE than A0-A7
|
||||||
|
// On later processors (like D series) it _IS_ possible.
|
||||||
|
|
||||||
|
|
||||||
|
#define ANALOG_READ_DELTA_USE_GND 0xff
|
||||||
|
|
||||||
|
// there is a bug in several headers for ADC_REFSEL_gm - should be 0x70, not 0x30 (and it gets re-defined, too)
|
||||||
|
#ifdef ADC_REFSEL_gm
|
||||||
|
#undef ADC_REFSEL_gm
|
||||||
|
#endif // ADC_REFSEL_gm
|
||||||
|
#define ADC_REFSEL_gm 0x70
|
||||||
|
|
||||||
|
enum _analogReference_ // pass to 'analogReference' function - see D manual section 22.14.3, or 28.16.3 in 'AU' manual
|
||||||
|
{
|
||||||
|
analogReference_INT1V = (ADC_REFSEL_INT1V_gc),
|
||||||
|
analogReference_PORTA0 = (ADC_REFSEL_AREFA_gc), // PORT A pin 0 is the AREF
|
||||||
|
|
||||||
|
#if !defined (__AVR_ATxmega8E5__) && !defined (__AVR_ATxmega16E5__) && !defined (__AVR_ATxmega32E5__)
|
||||||
|
// these 2 aren't valid for 'E' series
|
||||||
|
analogReference_PORTB0 = (ADC_REFSEL_AREFB_gc), // PORT B pin 0 is the AREF
|
||||||
|
|
||||||
|
analogReference_VCC = (ADC_REFSEL0_bm) /* (ADC_REFSEL_VCC_gc)*/, // VCC / 10, actually
|
||||||
|
// NOTE: 'ADC_REFSEL_VCC_gc' exists for some headers, and others 'ADC_REFSEL_INTVCC_gc'
|
||||||
|
// to avoid compile problems I use the bitmask instead.
|
||||||
|
#endif // E series
|
||||||
|
|
||||||
|
#if defined(__AVR_ATxmega64d4__) || defined(__AVR_ATxmega64a1u__) || defined(__AVR_ATxmega128a1u__)
|
||||||
|
analogReference_VCCDIV2 = (ADC_REFSEL_VCCDIV2_gc) // using THIS forces gain to 1/2, so it's rail-rail
|
||||||
|
#else
|
||||||
|
analogReference_VCCDIV2 = (0x04<<4) // (ADC_REFSEL_VCCDIV2_gc)
|
||||||
|
// NOTE that for some processor headers, ADC_REFSEL_VCCDIV2_gc is not properly defined
|
||||||
|
// this definition '(0x04<<4)' is taken from the 64d4 header. it's also THE DEFAULT for max compatibility
|
||||||
|
#endif // processors that define ADC_REFSEL_VCCDIV2_gc correctly
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: this constant isn't always defined, either
|
||||||
|
#ifndef ADC_CH_GAIN_gm
|
||||||
|
#define ADC_CH_GAIN_gm 0x1C /* Gain Factor group mask. */
|
||||||
|
#endif // ADC_CH_GAIN_gm
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long millis(void);
|
||||||
|
unsigned long micros(void);
|
||||||
|
void delay(unsigned long);
|
||||||
|
void delayMicroseconds(unsigned int us);
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||||
|
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||||
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
||||||
|
|
||||||
|
// XMEGA specific
|
||||||
|
void wait_for_interrupt(void); // uses 'IDLE' sleep mode to wait for an interrupt, then returns
|
||||||
|
void low_power_delay(unsigned long ms); // similar to 'delay' but goes into low power 'IDLE sleep' state
|
||||||
|
|
||||||
|
|
||||||
|
// X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A
|
||||||
|
//
|
||||||
|
// NOTE: for 'attachInterrupt' the 'mode' parameter indicates non-default input pins
|
||||||
|
// and the interrupt mode, as well as the interrupt priority. If the interrupt
|
||||||
|
// priority is INT_MODE_PRI_DEFAULT (0), it will be assigned a 'default' value.
|
||||||
|
// Default interrupt pin is pin 2 except for PORTR (since it doesn't have a pin 2)
|
||||||
|
// when it has not been specified.
|
||||||
|
//
|
||||||
|
// usage:
|
||||||
|
// attachInterrupt(PORTD_INT0, the specific interrupt vector - see pins_arduino.h
|
||||||
|
// my_callback, user-defined callback function
|
||||||
|
// RISING interrupt mode (can be LOW, HIGH, RISING, FALLING, CHANGE)
|
||||||
|
// | INT_MODE_PIN_DEFAULT the pin(s) to assign to this interrupt, or default pin 2 (optional)
|
||||||
|
// | INT_MODE_PRI_DEFAULT); interrupt priority, default is 'high' (optional)
|
||||||
|
//
|
||||||
|
// Additional note, the 'pin' constants (see below) refer to the port's pin number, and
|
||||||
|
// NOT the 'digital I/O pin' number. See 'pins_arduino.h' for more on this.
|
||||||
|
//
|
||||||
|
// for compatibility with newer arduino environment, attachInterrupt 'interruptNum' parameter
|
||||||
|
// can use the return value from 'digitalPinToInterrupt(pin)'
|
||||||
|
//
|
||||||
|
// X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
void attachInterrupt(uint8_t interruptNum, void (*)(void), int mode = 0); // default 'mode' param is: LOW | INT_MODE_PRI_DEFAULT | INT_MODE_PIN_DEFAULT
|
||||||
|
#else // not __cplusplus
|
||||||
|
void attachInterrupt(uint8_t interruptNum, void (*)(void), int mode);
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
void detachInterrupt(uint8_t interruptNum); // NOTE: detaches ALL interrupts for that port (special exceptions for serial flow control)
|
||||||
|
|
||||||
|
|
||||||
|
// this next function reads data from the calibration row, including the serial # info.
|
||||||
|
// This is often referred to as the 'PRODUCT SIGNATURE ROW'. It is xmega-specific.
|
||||||
|
uint8_t readCalibrationData(uint16_t iIndex);
|
||||||
|
|
||||||
|
|
||||||
|
// INTERRUPT MODE FLAGS - for attachInterrupt 'mode' parameter
|
||||||
|
|
||||||
|
#define INT_MODE_MODE_MASK 0x003f
|
||||||
|
#define INT_MODE_PRI_MASK 0x00c0
|
||||||
|
#define INT_MODE_PRI_DEFAULT 0
|
||||||
|
#define INT_MODE_PRI_LOW 0x0040
|
||||||
|
#define INT_MODE_PRI_MED 0x0080
|
||||||
|
#define INT_MODE_PRI_HIGH 0x00c0
|
||||||
|
#define INT_MODE_PRI_SHIFT 6 /* shift right 6 bits to get a 0, 1, 2 or 3 for priority (0 is 'default') */
|
||||||
|
#define INT_MODE_PIN_MASK 0xff00
|
||||||
|
#define INT_MODE_PIN0 0x0100
|
||||||
|
#define INT_MODE_PIN1 0x0200
|
||||||
|
#define INT_MODE_PIN2 0x0400
|
||||||
|
#define INT_MODE_PIN3 0x0800
|
||||||
|
#define INT_MODE_PIN4 0x1000
|
||||||
|
#define INT_MODE_PIN5 0x2000
|
||||||
|
#define INT_MODE_PIN6 0x4000
|
||||||
|
#define INT_MODE_PIN7 0x8000
|
||||||
|
#define INT_MODE_PIN_DEFAULT 0 /* no 'pin bits' set implies 'default' which is pin 2 on each capable port */
|
||||||
|
#define INT_MODE_PIN_SHIFT 8 /* shift right 8 bits to get the pin bits in a single byte */
|
||||||
|
|
||||||
|
// NOTE: the 'pin' constants refer to the port's pin number, and not the digital I/O pin
|
||||||
|
// The default 'pin 2' refers to the port's pin 2. See 'pins_arduino.h' for more on this.
|
||||||
|
// Multiple pins may be specified, so it is a bit mask. If a pin is specified by using
|
||||||
|
// digitalPinToInterrupt() and you also specify pins using the 'INT_MODE_PINx' flags, the
|
||||||
|
// pin specified in the 'interruptNum' parameter will be 'or'd with the pins specified in
|
||||||
|
// 'mode'. This can result in some unpredictable outcomes, so you should either use
|
||||||
|
// 'digitalPinToInterrupt' for 'interruptNum', or specify the port as 'interruptNum' and
|
||||||
|
// then specfify the pin info in 'mode'.
|
||||||
|
|
||||||
|
|
||||||
|
#define NOT_AN_INTERRUPT (-1) /* a placeholder for various arrays, etc. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// SETUP and LOOP (no changes from Arduino classic)
|
||||||
|
|
||||||
|
void setup(void);
|
||||||
|
void loop(void);
|
||||||
|
|
||||||
|
|
||||||
|
// hardware flow control 'helpers'
|
||||||
|
void serial_0_cts_callback(void);
|
||||||
|
void serial_1_cts_callback(void);
|
||||||
|
void InitSerialFlowControlInterrupts(void);
|
||||||
|
|
||||||
|
|
||||||
|
// On the xmega, the addresses of the port registers are
|
||||||
|
// greater than 255, so we can't store them in uint8_t's.
|
||||||
|
extern const uint16_t PROGMEM port_to_mode_PGM[];
|
||||||
|
extern const uint16_t PROGMEM port_to_input_PGM[];
|
||||||
|
extern const uint16_t PROGMEM port_to_output_PGM[];
|
||||||
|
extern const uint16_t PROGMEM digital_pin_to_control_PGM[];
|
||||||
|
|
||||||
|
// these contain index values so they CAN be uint8_t's
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
|
||||||
|
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; not used on xmega
|
||||||
|
extern const uint16_t PROGMEM port_to_input_PGM[];
|
||||||
|
|
||||||
|
// Get the bit location within the hardware port of the given virtual pin.
|
||||||
|
// This comes from the pins_*.c file for the active board configuration.
|
||||||
|
//
|
||||||
|
// These perform slightly better as macros compared to inline functions
|
||||||
|
//
|
||||||
|
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
|
||||||
|
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
|
||||||
|
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
|
||||||
|
// note pins_arduino.h may need to override this next one, depending
|
||||||
|
#define analogInPinToBit(P) ((P) & 7) /* analog pin 0 = 0 (PORTA), analog pin 8 = 0 (PORTB) */
|
||||||
|
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
|
||||||
|
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
|
||||||
|
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
|
||||||
|
#define pinControlRegister(P) ( (volatile uint8_t *)( pgm_read_word( digital_pin_to_control_PGM + (P))) )
|
||||||
|
|
||||||
|
// use THIS macro to convert a _BV(n) value into 'n'
|
||||||
|
#define pinBitValueToIndex(B) ( (B)==_BV(0) ? 0 : (B)==_BV(1) ? 1 : (B)==_BV(2) ? 2 : (B)==_BV(3) ? 3 : \
|
||||||
|
(B)==_BV(4) ? 4 : (B)==_BV(5) ? 5 : (B)==_BV(6) ? 6 : (B)==_BV(7) ? 7 : 0 )
|
||||||
|
|
||||||
|
#define NOT_A_PIN 0
|
||||||
|
#define NOT_A_PORT 0
|
||||||
|
|
||||||
|
#ifdef ARDUINO_MAIN
|
||||||
|
// use of '_' prefix to prevent collisions with iox64d#.h and for consistency
|
||||||
|
#define _PA 1
|
||||||
|
#define _PB 2
|
||||||
|
#define _PC 3
|
||||||
|
#define _PD 4
|
||||||
|
#define _PE 5
|
||||||
|
#define _PR 6 /* was PF */
|
||||||
|
#define _PF 7
|
||||||
|
#define _PH 8
|
||||||
|
#define _PJ 9
|
||||||
|
#define _PK 10
|
||||||
|
#define _PQ 11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// modified timer definitions for xmega
|
||||||
|
// TCD2 --> TIMERD2
|
||||||
|
// TCC2 --> TIMERC2
|
||||||
|
// TCE0 --> TIMERE0 - 'D' series which has only 4 pins on PORTE */
|
||||||
|
// TCE2 --> TIMERE2 - A series and others that use all 8 pins for port E
|
||||||
|
// TCF2 --> TIMERF2 - A series and others that have PORT F
|
||||||
|
#define NOT_ON_TIMER 0
|
||||||
|
#define TIMERD2 1
|
||||||
|
#define TIMERC2 2
|
||||||
|
#define TIMERE0 3
|
||||||
|
#define TIMERE2 4
|
||||||
|
#define TIMERF2 5
|
||||||
|
#define TIMERC4 6
|
||||||
|
#define TIMERD5 7
|
||||||
|
// not using TCD0,1 nor TCC0,1
|
||||||
|
// The first 16 IO pins (PD0-PD7, PC0-PC7) will be PWM capable, as are PE0-PE3 (or PE0-PE7) and PF0-PF7 (when there)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include "WCharacter.h"
|
||||||
|
#include "WString.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
|
||||||
|
uint16_t makeWord(uint16_t w);
|
||||||
|
uint16_t makeWord(byte h, byte l);
|
||||||
|
|
||||||
|
#define word(...) makeWord(__VA_ARGS__)
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// these are not currently implemented - TODO implement them
|
||||||
|
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
||||||
|
void noTone(uint8_t _pin);
|
||||||
|
|
||||||
|
|
||||||
|
// WMath prototypes
|
||||||
|
long random(long);
|
||||||
|
long random(long, long);
|
||||||
|
void randomSeed(unsigned int);
|
||||||
|
long map(long, long, long, long, long);
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
// at this point we include the pin definitions from 'pins_arduino.h'
|
||||||
|
// you can customize 'pins_arduino.h' for your specific hardware
|
||||||
|
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
// The default SPI interface is SPIC if not already defined
|
||||||
|
#ifndef DEFAULT_SPI
|
||||||
|
#define DEFAULT_SPI SPIC
|
||||||
|
#endif // DEFAULT_SPI
|
||||||
|
|
||||||
|
// the default TWI interface is TWIC if not already defined
|
||||||
|
#ifndef DEFAULT_TWI
|
||||||
|
#define DEFAULT_TWI TWIC
|
||||||
|
#endif // DEFAULT_TWI
|
||||||
|
|
||||||
|
|
||||||
|
// added support for hardware serial flow control - spans multiple files
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_RTS_PORT_NAME) && defined(SERIAL_0_RTS_PIN_INDEX)
|
||||||
|
#define SERIAL_0_RTS_ENABLED
|
||||||
|
#define SERIAL_0_RTS_PORT (&SERIAL_0_RTS_PORT_NAME)
|
||||||
|
#define SERIAL_0_RTS_PIN _BV(SERIAL_0_RTS_PIN_INDEX)
|
||||||
|
#endif // defined(SERIAL_0_RTS_PORT) && defined(SERIAL_0_RTS_PIN)
|
||||||
|
|
||||||
|
#if defined(SERIAL_1_RTS_PORT_NAME) && defined(SERIAL_1_RTS_PIN_INDEX)
|
||||||
|
#define SERIAL_1_RTS_ENABLED
|
||||||
|
#define SERIAL_1_RTS_PORT (&SERIAL_1_RTS_PORT_NAME)
|
||||||
|
#define SERIAL_1_RTS_PIN _BV(SERIAL_1_RTS_PIN_INDEX)
|
||||||
|
#endif // defined(SERIAL_1_RTS_PORT) && defined(SERIAL_1_RTS_PIN)
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_PORT_NAME) && defined(SERIAL_0_CTS_PIN_INDEX)
|
||||||
|
#define SERIAL_0_CTS_ENABLED
|
||||||
|
#define SERIAL_0_CTS_PORT (&SERIAL_0_CTS_PORT_NAME)
|
||||||
|
#define SERIAL_0_CTS_PIN _BV(SERIAL_0_CTS_PIN_INDEX)
|
||||||
|
#endif // defined(SERIAL_0_CTS_PORT) && defined(SERIAL_0_CTS_PIN)
|
||||||
|
|
||||||
|
#if defined(SERIAL_1_CTS_PORT_NAME) && defined(SERIAL_1_CTS_PIN_INDEX)
|
||||||
|
#define SERIAL_1_CTS_ENABLED
|
||||||
|
#define SERIAL_1_CTS_PORT (&SERIAL_1_CTS_PORT_NAME)
|
||||||
|
#define SERIAL_1_CTS_PIN _BV(SERIAL_1_CTS_PIN_INDEX)
|
||||||
|
#endif // defined(SERIAL_1_CTS_PORT) && defined(SERIAL_1_CTS_PIN)
|
||||||
|
|
||||||
|
|
||||||
|
#endif // Arduino_h
|
||||||
|
|
||||||
|
|
541
BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp
Normal file
541
BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// ____ ____ ____ //
|
||||||
|
// / ___|| _ \ / ___| ___ _ __ _ __ //
|
||||||
|
// | | | | | || | / __|| '_ \ | '_ \ //
|
||||||
|
// | |___ | |_| || |___ _| (__ | |_) || |_) | //
|
||||||
|
// \____||____/ \____|(_)\___|| .__/ | .__/ //
|
||||||
|
// |_| |_| //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* Copyright (c) 2011, Peter Barrett
|
||||||
|
**
|
||||||
|
** Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
** any purpose with or without fee is hereby granted, provided that the
|
||||||
|
** above copyright notice and this permission notice appear in all copies.
|
||||||
|
**
|
||||||
|
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||||
|
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||||
|
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
** SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Updated for the XMegaForArduino project by Bob Frazier, S.F.T. Inc.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// XMEGA NOTES:
|
||||||
|
//
|
||||||
|
// a) major re-factoring, including API functions
|
||||||
|
// b) K&R style is hard to read. I won't use it. Hard tabs are evil. Same.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "USBAPI.h"
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
|
||||||
|
#if defined(USBCON)
|
||||||
|
#ifdef CDC_ENABLED
|
||||||
|
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#define PROGMEM_ORIG PROGMEM
|
||||||
|
#else // PROGMEM workaround
|
||||||
|
|
||||||
|
// to avoid the bogus "initialized variables" warning
|
||||||
|
#ifdef PROGMEM
|
||||||
|
#undef PROGMEM
|
||||||
|
#endif // PROGMEM re-define
|
||||||
|
|
||||||
|
#define PROGMEM __attribute__((section(".progmem.cdc")))
|
||||||
|
#define PROGMEM_ORIG __attribute__((__progmem__))
|
||||||
|
|
||||||
|
#endif // check for GNUC >= or < 4.6
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 dwDTERate; // little-endian line rate
|
||||||
|
u8 bCharFormat; // stop bits = one, one-and-a-half, two (0, 1, 2 respectively)
|
||||||
|
u8 bParityType; // none, odd, even, mark, space (0 through 4)
|
||||||
|
u8 bDataBits; // char bits 5, 6, 7, 8
|
||||||
|
} __attribute__((aligned(1))) LineInfo;
|
||||||
|
|
||||||
|
static volatile LineInfo _usbLineInfo; // for initialization, see CDC_Reset
|
||||||
|
static u8 _cdcLineState;
|
||||||
|
static u16 _cdcSerialState;
|
||||||
|
static uint16_t wInterval;
|
||||||
|
|
||||||
|
#define WEAK __attribute__ ((weak))
|
||||||
|
|
||||||
|
extern const DeviceDescriptor _cdcDeviceDescriptor PROGMEM;
|
||||||
|
extern const IADDescriptor _cdcIADDesc PROGMEM;
|
||||||
|
extern const CDCDescriptor _cdcInterface PROGMEM;
|
||||||
|
|
||||||
|
|
||||||
|
// CDC DEVICE DESCRIPTOR (for CDC device) - sent by CDC_SendDeviceDescriptor()
|
||||||
|
|
||||||
|
const DeviceDescriptor _cdcDeviceDescriptor PROGMEM =
|
||||||
|
D_DEVICE(USB_DEVICE_CLASS_COMMUNICATIONS, // device class (COMM)
|
||||||
|
CDC_COMMUNICATION_INTERFACE_CLASS, // device sub-class (CDC COMM)
|
||||||
|
CDC_ABSTRACT_CONTROL_MODEL, // device protocol (ACM)
|
||||||
|
64, // packet size (64)
|
||||||
|
USB_VID, // vendor ID for the USB device
|
||||||
|
USB_PID, // product ID for the USB device
|
||||||
|
0x100, // device release version as BCD (1.00)
|
||||||
|
USB_STRING_INDEX_MANUFACTURER, // string index for mfg
|
||||||
|
USB_STRING_INDEX_PRODUCT, // string index for product name
|
||||||
|
USB_STRING_INDEX_SERIAL, // string index for serial number (0 for 'none')
|
||||||
|
1); // number of configurations (1)
|
||||||
|
|
||||||
|
|
||||||
|
// IAD descriptor - REQUIRED for composite interfaces, sent via CDC_SendIAD()
|
||||||
|
|
||||||
|
const IADDescriptor _cdcIADDesc = D_IAD(0, // first interface
|
||||||
|
2, // count (interfaces, not endpoints)
|
||||||
|
CDC_COMMUNICATION_INTERFACE_CLASS, // interface class
|
||||||
|
CDC_ABSTRACT_CONTROL_MODEL, // interface sub-class
|
||||||
|
1); // protocol
|
||||||
|
|
||||||
|
// CDC interface descriptor - sent by CDC_SendInterfaceData()
|
||||||
|
|
||||||
|
const CDCDescriptor _cdcInterface = // needs to be no more than 55 bytes in length
|
||||||
|
{
|
||||||
|
// FIRST INTERFACE
|
||||||
|
// CDC communication interface (endpoint 0)
|
||||||
|
D_INTERFACE(CDC_ACM_INTERFACE, // 'n'
|
||||||
|
1, // number of endpoints
|
||||||
|
CDC_COMMUNICATION_INTERFACE_CLASS, // interface class
|
||||||
|
CDC_ABSTRACT_CONTROL_MODEL, // interface sub-class
|
||||||
|
0), // protocol
|
||||||
|
|
||||||
|
// these headers describe the supported interfaces
|
||||||
|
D_CDCCS(CDC_HEADER,0x10,0x01), // CDCCS InterfaceDescriptor Header (1.10 bcd) - version 1.10?
|
||||||
|
// D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (seems to be optional)
|
||||||
|
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
|
||||||
|
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 (?)
|
||||||
|
|
||||||
|
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM), // IN endpoint for CDC_ENDPOINT_ACM
|
||||||
|
USB_ENDPOINT_TYPE_INTERRUPT, // INTERRUPT type
|
||||||
|
0x10, // max packet size 16
|
||||||
|
0x40), // interval 64 frames i.e. 64 msec (see USB spec table 9-13)
|
||||||
|
|
||||||
|
// SECOND INTERFACE
|
||||||
|
// CDC data interface (endpoints 1, 2)
|
||||||
|
D_INTERFACE(CDC_DATA_INTERFACE, // 'n'
|
||||||
|
2, // number of endpoints
|
||||||
|
CDC_DATA_INTERFACE_CLASS, // interface class
|
||||||
|
0, // interface sub-class
|
||||||
|
0), // protocol
|
||||||
|
|
||||||
|
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), // OUT endpoint, index 'CDC_ENDPOINT_OUT'
|
||||||
|
USB_ENDPOINT_TYPE_BULK, // BULK data transfers
|
||||||
|
0x40, // max packet size 64
|
||||||
|
1), // interval 1 (was 0)
|
||||||
|
|
||||||
|
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN), // IN endpoint, index 'CDC_ENDPOINT_IN'
|
||||||
|
USB_ENDPOINT_TYPE_BULK, // BULK data transfers
|
||||||
|
0x40, // max packet size 64
|
||||||
|
0) // interval 0 (apparently not needed)
|
||||||
|
};
|
||||||
|
|
||||||
|
void WEAK CDC_Reset(void)
|
||||||
|
{
|
||||||
|
_usbLineInfo.dwDTERate = 115200;
|
||||||
|
|
||||||
|
_usbLineInfo.bCharFormat
|
||||||
|
= _usbLineInfo.bParityType
|
||||||
|
= _usbLineInfo.bDataBits
|
||||||
|
= 0; // says I'm not initialized, basically
|
||||||
|
|
||||||
|
_cdcLineState = 0;
|
||||||
|
_cdcSerialState = 0;
|
||||||
|
|
||||||
|
wInterval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WEAK CDC_SendIAD(void)
|
||||||
|
{
|
||||||
|
return USB_SendControl(TRANSFER_PGM, &_cdcIADDesc, sizeof(_cdcIADDesc))
|
||||||
|
!= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WEAK CDC_GetNumInterfaces(void)
|
||||||
|
{
|
||||||
|
return 2; // always 2
|
||||||
|
}
|
||||||
|
|
||||||
|
int WEAK CDC_GetInterfaceDataLength(void)
|
||||||
|
{
|
||||||
|
return sizeof(_cdcInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WEAK CDC_SendInterfaceData(void)
|
||||||
|
{
|
||||||
|
return USB_SendControl(TRANSFER_PGM, &_cdcInterface, sizeof(_cdcInterface));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WEAK CDC_SendDeviceDescriptor(void)
|
||||||
|
{
|
||||||
|
return 0 != USB_SendControl(TRANSFER_PGM, &_cdcDeviceDescriptor, sizeof(_cdcDeviceDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WEAK CDC_Setup(Setup& setup)
|
||||||
|
{
|
||||||
|
u8 r = setup.bRequest;
|
||||||
|
u8 requestType = setup.bmRequestType;
|
||||||
|
|
||||||
|
if(REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
||||||
|
{
|
||||||
|
if (CDC_GET_LINE_CODING == r)
|
||||||
|
{
|
||||||
|
error_printP(F("Get Line Coding"));
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
USB_SendControl(0,(void*)&_usbLineInfo, sizeof(_usbLineInfo)/*7*/);
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
|
||||||
|
{
|
||||||
|
if(CDC_SET_LINE_CODING == r)
|
||||||
|
{
|
||||||
|
error_printP_(F("CDC_SET_LINE_CODING"));
|
||||||
|
|
||||||
|
// setup packet is followed by data?
|
||||||
|
memcpy((void *)&_usbLineInfo, (char *)&(setup) + sizeof(Setup), sizeof(_usbLineInfo));
|
||||||
|
|
||||||
|
error_printP_(F(" rate:"));
|
||||||
|
error_printL_(_usbLineInfo.dwDTERate);
|
||||||
|
error_printP_(F(" fmt:"));
|
||||||
|
error_printL_(_usbLineInfo.bCharFormat);
|
||||||
|
error_printP_(F(" par:"));
|
||||||
|
error_printL_(_usbLineInfo.bParityType);
|
||||||
|
error_printP_(F(" bit:"));
|
||||||
|
error_printL(_usbLineInfo.bDataBits);
|
||||||
|
|
||||||
|
USB_SendControl(0, NULL, 0); // send a ZLP
|
||||||
|
|
||||||
|
_cdcLineState = CONTROL_LINE_STATE_DTR; // for now... assume "this"
|
||||||
|
|
||||||
|
// now set up the ACM interrupt info in '_cdcSerialState' and send it back
|
||||||
|
|
||||||
|
_cdcSerialState = SERIAL_STATE_TX_CARRIER_DSR; // to tell host "I have data" (always)
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(CDC_SET_CONTROL_LINE_STATE == r)
|
||||||
|
{
|
||||||
|
error_printP_(F("Set Control Line State: "));
|
||||||
|
error_printL(setup.wValueL);
|
||||||
|
|
||||||
|
_cdcLineState = setup.wValueL;
|
||||||
|
|
||||||
|
// NOTE: this next part is for the 'caterina' CDC bootloader, arduino/bootloaders/caterina/Caterina.c
|
||||||
|
// it has some "special" code in it, like using 0x0800 in RAM as an address for a 'key' (7777H)
|
||||||
|
// to indicate it was soft-booted. XMEGA has better ways of handling this, like a CPU flag that
|
||||||
|
// indicates "I was soft-booted" as one example, and a 'WDT' timeout flag on top of that.
|
||||||
|
|
||||||
|
// auto-reset into the bootloader is triggered when the port, already
|
||||||
|
// open at 1200 bps, is closed. this is the signal to start the watchdog
|
||||||
|
// with a relatively long period so it can finish housekeeping tasks
|
||||||
|
// like servicing endpoints before the sketch ends
|
||||||
|
|
||||||
|
if (1200 == _usbLineInfo.dwDTERate)
|
||||||
|
{
|
||||||
|
// We check DTR state to determine if host port is open (bit 0 of _cdcLineState).
|
||||||
|
if ((_cdcLineState & 0x01) == 0)
|
||||||
|
{
|
||||||
|
// This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently)
|
||||||
|
//
|
||||||
|
// *(uint16_t *)0x0800 = 0x7777; note that on XMEGA this is a VERY bad thing
|
||||||
|
// wdt_enable(WDTO_120MS);
|
||||||
|
//
|
||||||
|
// on the atmega, address 800H is the start of the final 256-byte page in RAM space for 2k RAM
|
||||||
|
//
|
||||||
|
// atmega328(p) RAM goes from 0x100 through 0x8ff - see datasheet for atmega 328 [etc.] section 8.3
|
||||||
|
// 32U4 RAM goes through 0xaff - see datasheet for U4 processors, section 5.2
|
||||||
|
// 8/16/32U2 RAM goes through 4FFH so this won't even work - see datasheet for U2 processors, section 7.2
|
||||||
|
// basically it's a 'hack' and needs to be re-evaluated
|
||||||
|
|
||||||
|
// TODO: would it be safe to enable interrupts, NOT return from this function,
|
||||||
|
// and simply wait until the appropriate time has elapsed? Or, as is
|
||||||
|
// handled in the section below, this 'wait period' is canceled
|
||||||
|
|
||||||
|
// TODO: if I use a function that's part of the USB driver to trigger a soft boot, I can detect
|
||||||
|
// that a soft boot has taken place using the bits in the 'RESET' status register. If all
|
||||||
|
// I have to do is detect this, it's not a problem, and I won't need "magic memory locations"
|
||||||
|
|
||||||
|
// TODO: timeout-based reboot
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Most OSs do some intermediate steps when configuring ports and DTR can
|
||||||
|
// twiggle more than once before stabilizing.
|
||||||
|
// To avoid spurious resets we set the watchdog to 250ms and eventually
|
||||||
|
// cancel if DTR goes back high.
|
||||||
|
|
||||||
|
// This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently)
|
||||||
|
//
|
||||||
|
// TODO: reset whatever boot timeout I did
|
||||||
|
// wdt_disable();
|
||||||
|
// wdt_reset();
|
||||||
|
// *(uint16_t *)0x0800 = 0x0; note that on XMEGA this is a VERY bad thing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_SendControl(0, NULL, 0); // send a ZLP
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unrecognized request - report it
|
||||||
|
|
||||||
|
error_printP_(F("CDC request: type="));
|
||||||
|
error_printL_(requestType);
|
||||||
|
error_printP_(F(" request="));
|
||||||
|
error_printL(r);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'frame received' callback - notification that a 'Start Of Frame' took place
|
||||||
|
|
||||||
|
void CDC_FrameReceived(void)
|
||||||
|
{
|
||||||
|
bool bSend = false;
|
||||||
|
|
||||||
|
// NOTE: if I haven't configured the baud/bits yet, or the DTR bit is cleared,
|
||||||
|
// do NOT send anything nor muck with the flags. Wait until the device
|
||||||
|
// is actually RUNNING, first.
|
||||||
|
|
||||||
|
if(!_usbLineInfo.bDataBits || !(_cdcLineState & CONTROL_LINE_STATE_DTR))
|
||||||
|
{
|
||||||
|
return; // don't do anything if I haven't properly set up the data bits yet
|
||||||
|
}
|
||||||
|
|
||||||
|
if(USB_Available(CDC_RX) >= 64) // allow ~64 buffered bytes
|
||||||
|
{
|
||||||
|
if(_cdcSerialState & SERIAL_STATE_RX_CARRIER_DCD) // was on?
|
||||||
|
{
|
||||||
|
_cdcSerialState &= ~SERIAL_STATE_RX_CARRIER_DCD;
|
||||||
|
|
||||||
|
bSend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!(_cdcSerialState & SERIAL_STATE_RX_CARRIER_DCD)) // was off?
|
||||||
|
{
|
||||||
|
_cdcSerialState |= SERIAL_STATE_RX_CARRIER_DCD;
|
||||||
|
|
||||||
|
bSend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(USB_SendQLength(CDC_TX) > 0) // anything to send??
|
||||||
|
// {
|
||||||
|
// if(!(_cdcSerialState & SERIAL_STATE_TX_CARRIER_DSR))
|
||||||
|
// {
|
||||||
|
// _cdcSerialState |= SERIAL_STATE_TX_CARRIER_DSR; // to tell host "I have data"
|
||||||
|
//
|
||||||
|
// bSend = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if(_cdcSerialState & SERIAL_STATE_TX_CARRIER_DSR)
|
||||||
|
// {
|
||||||
|
// _cdcSerialState &= ~SERIAL_STATE_TX_CARRIER_DSR; // to tell host "I have data"
|
||||||
|
//
|
||||||
|
// bSend = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
if((bSend || wInterval >= 64) // will send every 64 'bus cycles' or when there's a change
|
||||||
|
&& !USB_SendQLength(CDC_ACM))
|
||||||
|
{
|
||||||
|
CDC_SendACM();
|
||||||
|
|
||||||
|
wInterval = 0;
|
||||||
|
}
|
||||||
|
else if(wInterval < 64)
|
||||||
|
{
|
||||||
|
wInterval++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDC_SendACM(void)
|
||||||
|
{
|
||||||
|
USB_Send(CDC_ACM, &_cdcSerialState, sizeof(_cdcSerialState), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial_::begin(unsigned long baud_count)
|
||||||
|
{
|
||||||
|
peek_buffer = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial_::begin(unsigned long baud_count, byte config)
|
||||||
|
{
|
||||||
|
peek_buffer = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial_::end(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serial_::available(void)
|
||||||
|
{
|
||||||
|
if (peek_buffer >= 0)
|
||||||
|
{
|
||||||
|
return 1 + USB_Available(CDC_RX);
|
||||||
|
}
|
||||||
|
|
||||||
|
return USB_Available(CDC_RX);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serial_::peek(void)
|
||||||
|
{
|
||||||
|
if (peek_buffer < 0)
|
||||||
|
{
|
||||||
|
if(USBDevice.configured())
|
||||||
|
{
|
||||||
|
peek_buffer = USB_Recv(CDC_RX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return peek_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serial_::read(void)
|
||||||
|
{
|
||||||
|
if (peek_buffer >= 0)
|
||||||
|
{
|
||||||
|
int c = peek_buffer;
|
||||||
|
peek_buffer = -1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(USBDevice.configured())
|
||||||
|
{
|
||||||
|
return USB_Recv(CDC_RX);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial_::flush(void)
|
||||||
|
{
|
||||||
|
if(USBDevice.configured())
|
||||||
|
{
|
||||||
|
USB_Flush(CDC_TX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Serial_::write(uint8_t c)
|
||||||
|
{
|
||||||
|
return write(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Serial_::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
/* only try to send bytes if the high-level CDC connection itself
|
||||||
|
is open (not just the pipe) - the OS should set _cdcLineState when the port
|
||||||
|
is opened and clear _cdcLineState when the port is closed.
|
||||||
|
bytes sent before the user opens the connection or after
|
||||||
|
the connection is closed are lost - just like with a UART. */
|
||||||
|
|
||||||
|
// NOTE: if my outgoing buffer is too full, stop sending
|
||||||
|
|
||||||
|
// TODO - ZE - check behavior on different OSes and test what happens if an
|
||||||
|
// open connection isn't broken cleanly (cable is yanked out, host dies
|
||||||
|
// or locks up, or host virtual serial port hangs)
|
||||||
|
|
||||||
|
if(USBDevice.configured() && // make sure I'm running
|
||||||
|
// !USB_IsStalled(CDC_TX) && // make sure I'm not stalled
|
||||||
|
!USB_IsSendQFull(CDC_TX)) // make sure I'm not flooding the queue
|
||||||
|
{
|
||||||
|
if(_cdcLineState & CONTROL_LINE_STATE_DTR) // make sure DTR is set
|
||||||
|
{
|
||||||
|
if(size > 128)
|
||||||
|
{
|
||||||
|
size = 128; // adjust size DOWN to limit output buffer size
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = USB_Send(CDC_TX, buffer, size, 1);
|
||||||
|
|
||||||
|
// TODO: check for partial sends and retry??
|
||||||
|
|
||||||
|
if(r > 0)
|
||||||
|
{
|
||||||
|
CDC_FrameReceived(); // inform the host of my data send/receive state
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: block?
|
||||||
|
|
||||||
|
setWriteError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This operator is a convenient way for a sketch to check whether the
|
||||||
|
// port has actually been configured and opened by the host (as opposed
|
||||||
|
// to just being connected to the host). It can be used, for example, in
|
||||||
|
// setup() before printing to ensure that an application on the host is
|
||||||
|
// actually ready to receive and display the data.
|
||||||
|
|
||||||
|
Serial_::operator bool()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if(USBDevice.configured()
|
||||||
|
&& (_cdcLineState & CONTROL_LINE_STATE_DTR)
|
||||||
|
&& !USB_IsSendQFull(CDC_TX)
|
||||||
|
// && !USB_IsStalled(CDC_TX)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We add a short delay before returning to fix a bug observed by Federico
|
||||||
|
// where the port is configured (_cdcLineState != 0) but not quite opened.
|
||||||
|
// delay(10);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
{
|
||||||
|
if(!USBDevice.configured())
|
||||||
|
{
|
||||||
|
error_printP(F("USB device not configured"));
|
||||||
|
}
|
||||||
|
else if(!(_cdcLineState & CONTROL_LINE_STATE_DTR))
|
||||||
|
{
|
||||||
|
error_printP(F("DTR is off"));
|
||||||
|
}
|
||||||
|
else if(USB_IsSendQFull(CDC_TX))
|
||||||
|
{
|
||||||
|
error_printP(F("Send Queue FULL"));
|
||||||
|
}
|
||||||
|
// else if(USB_IsStalled(CDC_TX))
|
||||||
|
// {
|
||||||
|
// error_printP(F("USB is stalled"));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial_ Serial;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* if defined(USBCON) */
|
||||||
|
|
45
BootLoaders/Boards/orangerx/cores/xmega/Client.h
Normal file
45
BootLoaders/Boards/orangerx/cores/xmega/Client.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Client.h - Base class that provides Client
|
||||||
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef client_h
|
||||||
|
#define client_h
|
||||||
|
#include "Print.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "IPAddress.h"
|
||||||
|
|
||||||
|
class Client : public Stream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||||
|
virtual int connect(const char *host, uint16_t port) =0;
|
||||||
|
virtual size_t write(uint8_t) =0;
|
||||||
|
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
virtual void stop() = 0;
|
||||||
|
virtual uint8_t connected() = 0;
|
||||||
|
virtual operator bool() = 0;
|
||||||
|
protected:
|
||||||
|
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
593
BootLoaders/Boards/orangerx/cores/xmega/HID.cpp
Normal file
593
BootLoaders/Boards/orangerx/cores/xmega/HID.cpp
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// _ _ ___ ____ //
|
||||||
|
// | | | ||_ _|| _ \ ___ _ __ _ __ //
|
||||||
|
// | |_| | | | | | | | / __|| '_ \ | '_ \ //
|
||||||
|
// | _ | | | | |_| |_| (__ | |_) || |_) | //
|
||||||
|
// |_| |_||___||____/(_)\___|| .__/ | .__/ //
|
||||||
|
// |_| |_| //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* Copyright (c) 2011, Peter Barrett
|
||||||
|
**
|
||||||
|
** Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
** any purpose with or without fee is hereby granted, provided that the
|
||||||
|
** above copyright notice and this permission notice appear in all copies.
|
||||||
|
**
|
||||||
|
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||||
|
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||||
|
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
** SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// XMEGA NOTES:
|
||||||
|
//
|
||||||
|
// a) it appears that, at one time at least, this was intended to be overridden
|
||||||
|
// by user code, hence the use of 'WEAK' all over the place;
|
||||||
|
// b) This API is *VERY* 'tricky' in that it's tied in heavily with the atmega
|
||||||
|
// USB implementation and (in some cases) does 'magic things' that are not
|
||||||
|
// apparently obvious to someone trying to port it to another processor
|
||||||
|
// (for an example see original use of CDC_GetInterface - lame!)
|
||||||
|
// c) Given the fact that it's (in my view) POORLY WRITTEN, it deserves a makeover.
|
||||||
|
// d) K&R style is hard to read. I won't use it. Hard tabs are evil. Same.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "USBAPI.h"
|
||||||
|
#include "USBDesc.h"
|
||||||
|
|
||||||
|
#if defined(USBCON)
|
||||||
|
#ifdef HID_ENABLED
|
||||||
|
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#define PROGMEM_ORIG PROGMEM
|
||||||
|
#else // PROGMEM workaround
|
||||||
|
|
||||||
|
// to avoid the bogus "initialized variables" warning
|
||||||
|
#ifdef PROGMEM
|
||||||
|
#undef PROGMEM
|
||||||
|
#endif // PROGMEM re-define
|
||||||
|
|
||||||
|
#define PROGMEM __attribute__((section(".progmem.hid")))
|
||||||
|
#define PROGMEM_ORIG __attribute__((__progmem__))
|
||||||
|
|
||||||
|
#endif // check for GNUC >= or < 4.6
|
||||||
|
|
||||||
|
|
||||||
|
//#define RAWHID_ENABLED
|
||||||
|
|
||||||
|
// Singletons for mouse and keyboard
|
||||||
|
|
||||||
|
Mouse_ Mouse;
|
||||||
|
Keyboard_ Keyboard;
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
|
||||||
|
// HID report descriptor
|
||||||
|
|
||||||
|
#define LSB(_x) ((_x) & 0xFF)
|
||||||
|
#define MSB(_x) ((_x) >> 8)
|
||||||
|
|
||||||
|
#define RAWHID_USAGE_PAGE 0xFFC0
|
||||||
|
#define RAWHID_USAGE 0x0C00
|
||||||
|
#define RAWHID_TX_SIZE 64
|
||||||
|
#define RAWHID_RX_SIZE 64
|
||||||
|
|
||||||
|
const u8 _hidReportDescriptor[] PROGMEM =
|
||||||
|
{
|
||||||
|
// Mouse
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
|
||||||
|
0x09, 0x02, // USAGE (Mouse)
|
||||||
|
0xa1, 0x01, // COLLECTION (Application)
|
||||||
|
0x09, 0x01, // USAGE (Pointer)
|
||||||
|
0xa1, 0x00, // COLLECTION (Physical)
|
||||||
|
0x85, 0x01, // REPORT_ID (1)
|
||||||
|
0x05, 0x09, // USAGE_PAGE (Button)
|
||||||
|
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||||
|
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||||
|
0x95, 0x03, // REPORT_COUNT (3)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x05, // REPORT_SIZE (5)
|
||||||
|
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x30, // USAGE (X)
|
||||||
|
0x09, 0x31, // USAGE (Y)
|
||||||
|
0x09, 0x38, // USAGE (Wheel)
|
||||||
|
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||||
|
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x95, 0x03, // REPORT_COUNT (3)
|
||||||
|
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||||
|
0xc0, // END_COLLECTION
|
||||||
|
0xc0, // END_COLLECTION
|
||||||
|
|
||||||
|
// Keyboard
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
|
||||||
|
0x09, 0x06, // USAGE (Keyboard)
|
||||||
|
0xa1, 0x01, // COLLECTION (Application)
|
||||||
|
0x85, 0x02, // REPORT_ID (2)
|
||||||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||||
|
|
||||||
|
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||||
|
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
|
||||||
|
0x95, 0x08, // REPORT_COUNT (8)
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||||
|
|
||||||
|
0x95, 0x06, // REPORT_COUNT (6)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x65, // LOGICAL_MAXIMUM (101)
|
||||||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||||
|
|
||||||
|
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||||
|
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||||
|
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||||
|
0xc0, // END_COLLECTION
|
||||||
|
|
||||||
|
#ifdef RAWHID_ENABLED
|
||||||
|
// RAW HID
|
||||||
|
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
|
||||||
|
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||||
|
|
||||||
|
0xA1, 0x01, // Collection 0x01
|
||||||
|
0x85, 0x03, // REPORT_ID (3)
|
||||||
|
0x75, 0x08, // report size = 8 bits
|
||||||
|
0x15, 0x00, // logical minimum = 0
|
||||||
|
0x26, 0xFF, 0x00, // logical maximum = 255
|
||||||
|
|
||||||
|
0x95, 64, // report count TX
|
||||||
|
0x09, 0x01, // usage
|
||||||
|
0x81, 0x02, // Input (array)
|
||||||
|
|
||||||
|
0x95, 64, // report count RX
|
||||||
|
0x09, 0x02, // usage
|
||||||
|
0x91, 0x02, // Output (array)
|
||||||
|
0xC0 // end collection
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const HIDDescriptor _hidInterface PROGMEM =
|
||||||
|
{
|
||||||
|
D_INTERFACE(HID_INTERFACE,1,3,0,0),
|
||||||
|
D_HIDREPORT(sizeof(_hidReportDescriptor)),
|
||||||
|
D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
|
||||||
|
};
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Driver
|
||||||
|
|
||||||
|
u8 _hid_protocol = 1;
|
||||||
|
u8 _hid_idle = 1;
|
||||||
|
|
||||||
|
#define WEAK __attribute__ ((weak))
|
||||||
|
|
||||||
|
int WEAK HID_GetNumInterfaces(void)
|
||||||
|
{
|
||||||
|
return 1; // always 1
|
||||||
|
}
|
||||||
|
|
||||||
|
int WEAK HID_GetInterfaceDataLength(void)
|
||||||
|
{
|
||||||
|
return sizeof(_hidInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WEAK HID_SendInterfaceData(void)
|
||||||
|
{
|
||||||
|
return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface));
|
||||||
|
}
|
||||||
|
|
||||||
|
int WEAK HID_GetDescriptor(int i)
|
||||||
|
{
|
||||||
|
// NOTE: 'i' is the max size for the request. Should I pay attention to it?
|
||||||
|
|
||||||
|
return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WEAK HID_SendReport(u8 id, const void* data, int len)
|
||||||
|
{
|
||||||
|
USB_Send(HID_TX, &id, 1, 0);
|
||||||
|
USB_Send(HID_TX,data,len, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WEAK HID_Setup(Setup& setup)
|
||||||
|
{
|
||||||
|
u8 r = setup.bRequest;
|
||||||
|
u8 requestType = setup.bmRequestType;
|
||||||
|
|
||||||
|
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
||||||
|
{
|
||||||
|
if (HID_GET_REPORT == r)
|
||||||
|
{
|
||||||
|
//HID_GetReport();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (HID_GET_PROTOCOL == r)
|
||||||
|
{
|
||||||
|
//Send8(_hid_protocol); // TODO
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
|
||||||
|
{
|
||||||
|
if (HID_SET_PROTOCOL == r)
|
||||||
|
{
|
||||||
|
_hid_protocol = setup.wValueL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HID_SET_IDLE == r)
|
||||||
|
{
|
||||||
|
_hid_idle = setup.wValueL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Mouse
|
||||||
|
|
||||||
|
Mouse_::Mouse_(void) : _buttons(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::begin(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::end(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::click(uint8_t b)
|
||||||
|
{
|
||||||
|
_buttons = b;
|
||||||
|
move(0,0,0);
|
||||||
|
_buttons = 0;
|
||||||
|
move(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::move(signed char x, signed char y, signed char wheel)
|
||||||
|
{
|
||||||
|
u8 m[4];
|
||||||
|
m[0] = _buttons;
|
||||||
|
m[1] = x;
|
||||||
|
m[2] = y;
|
||||||
|
m[3] = wheel;
|
||||||
|
HID_SendReport(1,m,4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::buttons(uint8_t b)
|
||||||
|
{
|
||||||
|
if (b != _buttons)
|
||||||
|
{
|
||||||
|
_buttons = b;
|
||||||
|
move(0,0,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::press(uint8_t b)
|
||||||
|
{
|
||||||
|
buttons(_buttons | b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse_::release(uint8_t b)
|
||||||
|
{
|
||||||
|
buttons(_buttons & ~b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mouse_::isPressed(uint8_t b)
|
||||||
|
{
|
||||||
|
if ((b & _buttons) > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Keyboard
|
||||||
|
|
||||||
|
Keyboard_::Keyboard_(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard_::begin(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard_::end(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard_::sendReport(KeyReport* keys)
|
||||||
|
{
|
||||||
|
HID_SendReport(2,keys,sizeof(KeyReport));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern
|
||||||
|
const uint8_t _asciimap[128] PROGMEM;
|
||||||
|
|
||||||
|
#define SHIFT 0x80
|
||||||
|
const uint8_t _asciimap[128] =
|
||||||
|
{
|
||||||
|
0x00, // NUL
|
||||||
|
0x00, // SOH
|
||||||
|
0x00, // STX
|
||||||
|
0x00, // ETX
|
||||||
|
0x00, // EOT
|
||||||
|
0x00, // ENQ
|
||||||
|
0x00, // ACK
|
||||||
|
0x00, // BEL
|
||||||
|
0x2a, // BS Backspace
|
||||||
|
0x2b, // TAB Tab
|
||||||
|
0x28, // LF Enter
|
||||||
|
0x00, // VT
|
||||||
|
0x00, // FF
|
||||||
|
0x00, // CR
|
||||||
|
0x00, // SO
|
||||||
|
0x00, // SI
|
||||||
|
0x00, // DEL
|
||||||
|
0x00, // DC1
|
||||||
|
0x00, // DC2
|
||||||
|
0x00, // DC3
|
||||||
|
0x00, // DC4
|
||||||
|
0x00, // NAK
|
||||||
|
0x00, // SYN
|
||||||
|
0x00, // ETB
|
||||||
|
0x00, // CAN
|
||||||
|
0x00, // EM
|
||||||
|
0x00, // SUB
|
||||||
|
0x00, // ESC
|
||||||
|
0x00, // FS
|
||||||
|
0x00, // GS
|
||||||
|
0x00, // RS
|
||||||
|
0x00, // US
|
||||||
|
|
||||||
|
0x2c, // ' '
|
||||||
|
0x1e|SHIFT, // !
|
||||||
|
0x34|SHIFT, // "
|
||||||
|
0x20|SHIFT, // #
|
||||||
|
0x21|SHIFT, // $
|
||||||
|
0x22|SHIFT, // %
|
||||||
|
0x24|SHIFT, // &
|
||||||
|
0x34, // '
|
||||||
|
0x26|SHIFT, // (
|
||||||
|
0x27|SHIFT, // )
|
||||||
|
0x25|SHIFT, // *
|
||||||
|
0x2e|SHIFT, // +
|
||||||
|
0x36, // ,
|
||||||
|
0x2d, // -
|
||||||
|
0x37, // .
|
||||||
|
0x38, // /
|
||||||
|
0x27, // 0
|
||||||
|
0x1e, // 1
|
||||||
|
0x1f, // 2
|
||||||
|
0x20, // 3
|
||||||
|
0x21, // 4
|
||||||
|
0x22, // 5
|
||||||
|
0x23, // 6
|
||||||
|
0x24, // 7
|
||||||
|
0x25, // 8
|
||||||
|
0x26, // 9
|
||||||
|
0x33|SHIFT, // :
|
||||||
|
0x33, // ;
|
||||||
|
0x36|SHIFT, // <
|
||||||
|
0x2e, // =
|
||||||
|
0x37|SHIFT, // >
|
||||||
|
0x38|SHIFT, // ?
|
||||||
|
0x1f|SHIFT, // @
|
||||||
|
0x04|SHIFT, // A
|
||||||
|
0x05|SHIFT, // B
|
||||||
|
0x06|SHIFT, // C
|
||||||
|
0x07|SHIFT, // D
|
||||||
|
0x08|SHIFT, // E
|
||||||
|
0x09|SHIFT, // F
|
||||||
|
0x0a|SHIFT, // G
|
||||||
|
0x0b|SHIFT, // H
|
||||||
|
0x0c|SHIFT, // I
|
||||||
|
0x0d|SHIFT, // J
|
||||||
|
0x0e|SHIFT, // K
|
||||||
|
0x0f|SHIFT, // L
|
||||||
|
0x10|SHIFT, // M
|
||||||
|
0x11|SHIFT, // N
|
||||||
|
0x12|SHIFT, // O
|
||||||
|
0x13|SHIFT, // P
|
||||||
|
0x14|SHIFT, // Q
|
||||||
|
0x15|SHIFT, // R
|
||||||
|
0x16|SHIFT, // S
|
||||||
|
0x17|SHIFT, // T
|
||||||
|
0x18|SHIFT, // U
|
||||||
|
0x19|SHIFT, // V
|
||||||
|
0x1a|SHIFT, // W
|
||||||
|
0x1b|SHIFT, // X
|
||||||
|
0x1c|SHIFT, // Y
|
||||||
|
0x1d|SHIFT, // Z
|
||||||
|
0x2f, // [
|
||||||
|
0x31, // bslash
|
||||||
|
0x30, // ]
|
||||||
|
0x23|SHIFT, // ^
|
||||||
|
0x2d|SHIFT, // _
|
||||||
|
0x35, // `
|
||||||
|
0x04, // a
|
||||||
|
0x05, // b
|
||||||
|
0x06, // c
|
||||||
|
0x07, // d
|
||||||
|
0x08, // e
|
||||||
|
0x09, // f
|
||||||
|
0x0a, // g
|
||||||
|
0x0b, // h
|
||||||
|
0x0c, // i
|
||||||
|
0x0d, // j
|
||||||
|
0x0e, // k
|
||||||
|
0x0f, // l
|
||||||
|
0x10, // m
|
||||||
|
0x11, // n
|
||||||
|
0x12, // o
|
||||||
|
0x13, // p
|
||||||
|
0x14, // q
|
||||||
|
0x15, // r
|
||||||
|
0x16, // s
|
||||||
|
0x17, // t
|
||||||
|
0x18, // u
|
||||||
|
0x19, // v
|
||||||
|
0x1a, // w
|
||||||
|
0x1b, // x
|
||||||
|
0x1c, // y
|
||||||
|
0x1d, // z
|
||||||
|
0x2f|SHIFT, //
|
||||||
|
0x31|SHIFT, // |
|
||||||
|
0x30|SHIFT, // }
|
||||||
|
0x35|SHIFT, // ~
|
||||||
|
0 // DEL
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t USBPutChar(uint8_t c);
|
||||||
|
|
||||||
|
// press() adds the specified key (printing, non-printing, or modifier)
|
||||||
|
// to the persistent key report and sends the report. Because of the way
|
||||||
|
// USB HID works, the host acts like the key remains pressed until we
|
||||||
|
// call release(), releaseAll(), or otherwise clear the report and resend.
|
||||||
|
size_t Keyboard_::press(uint8_t k)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
if (k >= 136) // it's a non-printing key (not a modifier)
|
||||||
|
{
|
||||||
|
k = k - 136;
|
||||||
|
}
|
||||||
|
else if (k >= 128)
|
||||||
|
{ // it's a modifier key
|
||||||
|
_keyReport.modifiers |= (1<<(k-128));
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
else // it's a printing key
|
||||||
|
{
|
||||||
|
k = pgm_read_byte(_asciimap + k);
|
||||||
|
if (!k)
|
||||||
|
{
|
||||||
|
setWriteError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (k & 0x80) // it's a capital letter or other character reached with shift
|
||||||
|
{
|
||||||
|
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||||
|
k &= 0x7F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add k to the key report only if it's not already present
|
||||||
|
// and if there is an empty slot.
|
||||||
|
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||||
|
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||||
|
_keyReport.keys[4] != k && _keyReport.keys[5] != k)
|
||||||
|
{
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
if (_keyReport.keys[i] == 0x00)
|
||||||
|
{
|
||||||
|
_keyReport.keys[i] = k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 6)
|
||||||
|
{
|
||||||
|
setWriteError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReport(&_keyReport);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// release() takes the specified key out of the persistent key report and
|
||||||
|
// sends the report. This tells the OS the key is no longer pressed and that
|
||||||
|
// it shouldn't be repeated any more.
|
||||||
|
size_t Keyboard_::release(uint8_t k)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
if (k >= 136)
|
||||||
|
{ // it's a non-printing key (not a modifier)
|
||||||
|
k = k - 136;
|
||||||
|
}
|
||||||
|
else if (k >= 128)
|
||||||
|
{ // it's a modifier key
|
||||||
|
_keyReport.modifiers &= ~(1<<(k-128));
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // it's a printing key
|
||||||
|
k = pgm_read_byte(_asciimap + k);
|
||||||
|
if (!k)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (k & 0x80)
|
||||||
|
{ // it's a capital letter or other character reached with shift
|
||||||
|
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||||
|
k &= 0x7F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the key report to see if k is present. Clear it if it exists.
|
||||||
|
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
if (0 != k && _keyReport.keys[i] == k)
|
||||||
|
{
|
||||||
|
_keyReport.keys[i] = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReport(&_keyReport);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard_::releaseAll(void)
|
||||||
|
{
|
||||||
|
_keyReport.keys[0] = 0;
|
||||||
|
_keyReport.keys[1] = 0;
|
||||||
|
_keyReport.keys[2] = 0;
|
||||||
|
_keyReport.keys[3] = 0;
|
||||||
|
_keyReport.keys[4] = 0;
|
||||||
|
_keyReport.keys[5] = 0;
|
||||||
|
_keyReport.modifiers = 0;
|
||||||
|
sendReport(&_keyReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Keyboard_::write(uint8_t c)
|
||||||
|
{
|
||||||
|
uint8_t p = press(c); // Keydown
|
||||||
|
/*uint8_t r =*/ release(c); // Keyup
|
||||||
|
return (p); // just return the result of press() since release() almost always returns 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* if defined(USBCON) */
|
||||||
|
|
1869
BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp
Normal file
1869
BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp
Normal file
File diff suppressed because it is too large
Load Diff
143
BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h
Normal file
143
BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
HardwareSerial.h - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
Modified 14 August 2012 by Alarus
|
||||||
|
|
||||||
|
Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
|
||||||
|
In some cases, the xmega updates make assumptions about the pin assignments.
|
||||||
|
See 'pins_arduino.h' for more detail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HardwareSerial_h
|
||||||
|
#define HardwareSerial_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
struct ring_buffer;
|
||||||
|
|
||||||
|
class HardwareSerial : public Stream
|
||||||
|
{
|
||||||
|
protected: // NEVER 'private'
|
||||||
|
// NOTE: xmega uses a structure pointer rather than individual pointers
|
||||||
|
// and the bit flags are consistent for all USART devices
|
||||||
|
ring_buffer *_rx_buffer;
|
||||||
|
ring_buffer *_tx_buffer;
|
||||||
|
volatile USART_t *_usart;
|
||||||
|
bool transmitting;
|
||||||
|
public:
|
||||||
|
HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, uint16_t usart) __attribute__ ((noinline));
|
||||||
|
void init(ring_buffer *rx_buffer, ring_buffer *tx_buffer, uint16_t usart) __attribute__ ((noinline));
|
||||||
|
void begin(unsigned long);
|
||||||
|
void begin(unsigned long, uint8_t);
|
||||||
|
void end();
|
||||||
|
virtual int available(void);
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual int read(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
virtual size_t write(uint8_t);
|
||||||
|
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(long n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(int n) { return write((uint8_t)n); }
|
||||||
|
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||||
|
operator bool();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define config for Serial.begin(baud, config);
|
||||||
|
// PMODE 5:4 00=none 10=even 11=odd
|
||||||
|
// SBMODE 3 0=1 stop 1=2 stop
|
||||||
|
// CHSIZE 2:0 000=5 bit 001=6 bit 010=7 bit 011=8 bit 111=9 bit
|
||||||
|
|
||||||
|
#define SERIAL_TWO_STOP _BV(USART_SBMODE_bp)
|
||||||
|
#define SERIAL_EVEN_PARITY _BV(USART_PMODE1_bp)
|
||||||
|
#define SERIAL_ODD_PARITY (_BV(USART_PMODE1_bp) | _BV(USART_PMODE0_bp))
|
||||||
|
|
||||||
|
#define SERIAL_5N1 0x00
|
||||||
|
#define SERIAL_6N1 0x01
|
||||||
|
#define SERIAL_7N1 0x02
|
||||||
|
#define SERIAL_8N1 0x03
|
||||||
|
#define SERIAL_5N2 (SERIAL_5N1 | SERIAL_TWO_STOP)
|
||||||
|
#define SERIAL_6N2 (SERIAL_6N1 | SERIAL_TWO_STOP)
|
||||||
|
#define SERIAL_7N2 (SERIAL_7N1 | SERIAL_TWO_STOP)
|
||||||
|
#define SERIAL_8N2 (SERIAL_8N1 | SERIAL_TWO_STOP)
|
||||||
|
#define SERIAL_5E1 (SERIAL_5N1 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_6E1 (SERIAL_6N1 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_7E1 (SERIAL_7N1 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_8E1 (SERIAL_8N1 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_5E2 (SERIAL_5N2 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_6E2 (SERIAL_6N2 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_7E2 (SERIAL_7N2 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_8E2 (SERIAL_8N2 | SERIAL_EVEN_PARITY)
|
||||||
|
#define SERIAL_5O1 (SERIAL_5N1 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_6O1 (SERIAL_6N1 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_7O1 (SERIAL_7N1 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_8O1 (SERIAL_8N1 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_5O2 (SERIAL_5N2 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_6O2 (SERIAL_6N2 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_7O2 (SERIAL_7N2 | SERIAL_ODD_PARITY)
|
||||||
|
#define SERIAL_8O2 (SERIAL_8N2 | SERIAL_ODD_PARITY)
|
||||||
|
|
||||||
|
|
||||||
|
// this is where I must include 'pins_arduino.h' to get the 'USBCON' definition
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
// DEFAULT SERIAL or 'SERIAL 1'
|
||||||
|
#if defined(USBCON)
|
||||||
|
// NOTE: 'Serial1' will be the hardware serial and 'Serial' the USB serial
|
||||||
|
// whenever 'USBCON' is defined in pins_arduino.h
|
||||||
|
|
||||||
|
#include <USBAPI.h>
|
||||||
|
|
||||||
|
extern HardwareSerial Serial1;
|
||||||
|
#else // normal hardware serial
|
||||||
|
extern HardwareSerial Serial;
|
||||||
|
#define Serial1 Serial /* define as 'Serial' so compatible code won't break */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern HardwareSerial Serial2; // this is the same regardless of USBCON (there will always be at least 2)
|
||||||
|
|
||||||
|
#ifdef SERIAL_2_PORT_NAME /* note these names are off by 1 with the 'Serial_N_' definitions */
|
||||||
|
extern HardwareSerial Serial3;
|
||||||
|
#endif // SERIAL_2_PORT_NAME
|
||||||
|
#ifdef SERIAL_3_PORT_NAME
|
||||||
|
extern HardwareSerial Serial4;
|
||||||
|
#endif // SERIAL_3_PORT_NAME
|
||||||
|
#ifdef SERIAL_4_PORT_NAME
|
||||||
|
extern HardwareSerial Serial5;
|
||||||
|
#endif // SERIAL_4_PORT_NAME
|
||||||
|
#ifdef SERIAL_5_PORT_NAME
|
||||||
|
extern HardwareSerial Serial6;
|
||||||
|
#endif // SERIAL_5_PORT_NAME
|
||||||
|
#ifdef SERIAL_6_PORT_NAME
|
||||||
|
extern HardwareSerial Serial7;
|
||||||
|
#endif // SERIAL_6_PORT_NAME
|
||||||
|
#ifdef SERIAL_7_PORT_NAME
|
||||||
|
extern HardwareSerial Serial8;
|
||||||
|
#endif // SERIAL_7_PORT_NAME
|
||||||
|
|
||||||
|
// this function calls the serial event handlers. you can override them (hence 'weak')
|
||||||
|
// the default implementation checks for data available and executes the callback if so
|
||||||
|
extern void serialEventRun(void) __attribute__((weak));
|
||||||
|
|
||||||
|
#endif // HardwareSerial_h
|
||||||
|
|
74
BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp
Normal file
74
BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
IPAddress.cpp - Base class that provides IPAddress
|
||||||
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
|
IPAddress::IPAddress()
|
||||||
|
{
|
||||||
|
memset(_address, 0, sizeof(_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||||
|
{
|
||||||
|
_address[0] = first_octet;
|
||||||
|
_address[1] = second_octet;
|
||||||
|
_address[2] = third_octet;
|
||||||
|
_address[3] = fourth_octet;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(uint32_t address)
|
||||||
|
{
|
||||||
|
memcpy(_address, &address, sizeof(_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address, address, sizeof(_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address, address, sizeof(_address));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress& IPAddress::operator=(uint32_t address)
|
||||||
|
{
|
||||||
|
memcpy(_address, (const uint8_t *)&address, sizeof(_address));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPAddress::operator==(const uint8_t* addr)
|
||||||
|
{
|
||||||
|
return memcmp(addr, _address, sizeof(_address)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t IPAddress::printTo(Print& p) const
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (int i =0; i < 3; i++)
|
||||||
|
{
|
||||||
|
n += p.print(_address[i], DEC);
|
||||||
|
n += p.print('.');
|
||||||
|
}
|
||||||
|
n += p.print(_address[3], DEC);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
82
BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h
Normal file
82
BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
IPAddress.h - Base class that provides IPAddress
|
||||||
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IPAddress_h
|
||||||
|
#define IPAddress_h
|
||||||
|
|
||||||
|
#include <Printable.h>
|
||||||
|
|
||||||
|
// A class to make it easier to handle and pass around IP addresses
|
||||||
|
|
||||||
|
class IPAddress : public Printable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _address[4]; // IPv4 address
|
||||||
|
// Access the raw byte array containing the address. Because this returns a pointer
|
||||||
|
// to the internal structure rather than a copy of the address this function should only
|
||||||
|
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||||
|
// stored.
|
||||||
|
uint8_t* raw_address() { return _address; };
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
IPAddress();
|
||||||
|
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||||
|
IPAddress(uint32_t address);
|
||||||
|
IPAddress(const uint8_t *address);
|
||||||
|
|
||||||
|
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||||
|
// to a four-byte uint8_t array is expected
|
||||||
|
operator uint32_t()
|
||||||
|
{
|
||||||
|
register const uint32_t *p1 = (const uint32_t *)(const void *)_address;
|
||||||
|
return *p1;
|
||||||
|
};
|
||||||
|
bool operator==(const IPAddress& addr)
|
||||||
|
{
|
||||||
|
register const uint32_t *p1 = (const uint32_t*)_address;
|
||||||
|
register const uint32_t *p2 = (const uint32_t*)(addr._address);
|
||||||
|
|
||||||
|
return *p1 == *p2;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const uint8_t* addr);
|
||||||
|
|
||||||
|
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||||
|
uint8_t operator[](int index) const { return _address[index]; };
|
||||||
|
uint8_t& operator[](int index) { return _address[index]; };
|
||||||
|
|
||||||
|
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||||
|
IPAddress& operator=(const uint8_t *address);
|
||||||
|
IPAddress& operator=(uint32_t address);
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const;
|
||||||
|
|
||||||
|
friend class EthernetClass;
|
||||||
|
friend class UDP;
|
||||||
|
friend class Client;
|
||||||
|
friend class Server;
|
||||||
|
friend class DhcpClass;
|
||||||
|
friend class DNSClient;
|
||||||
|
};
|
||||||
|
|
||||||
|
const IPAddress INADDR_NONE(0,0,0,0);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
27
BootLoaders/Boards/orangerx/cores/xmega/Platform.h
Normal file
27
BootLoaders/Boards/orangerx/cores/xmega/Platform.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#ifndef __PLATFORM_H__
|
||||||
|
#define __PLATFORM_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/eeprom.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#ifndef _PLATFORM_H_TYPES_DEFINED_
|
||||||
|
#define _PLATFORM_H_TYPES_DEFINED_
|
||||||
|
// this is a temporary fix for USCore.h data types and header file include order issues
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned long u32;
|
||||||
|
#endif // _PLATFORM_H_TYPES_DEFINED_
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#if defined(USBCON)
|
||||||
|
#include "USBDesc.h"
|
||||||
|
#include "USBCore.h"
|
||||||
|
#include "USBAPI.h"
|
||||||
|
#endif /* if defined(USBCON) */
|
||||||
|
|
||||||
|
#endif
|
381
BootLoaders/Boards/orangerx/cores/xmega/Print.cpp
Normal file
381
BootLoaders/Boards/orangerx/cores/xmega/Print.cpp
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
Print.cpp - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* default implementation: may be overridden */
|
||||||
|
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
register size_t cb = write(*buffer++);
|
||||||
|
|
||||||
|
if(!cb) // error return (prevents infinite loops)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n += cb;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||||
|
{
|
||||||
|
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
|
||||||
|
size_t n = 0;
|
||||||
|
char tbuf[32]; // will write 32 chars at a time (helps for USB)
|
||||||
|
register char *p1;
|
||||||
|
|
||||||
|
|
||||||
|
p1 = tbuf;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
unsigned char c = pgm_read_byte(p++);
|
||||||
|
|
||||||
|
if(c == 0)
|
||||||
|
{
|
||||||
|
if(p1 > &(tbuf[0]))
|
||||||
|
{
|
||||||
|
n += write(tbuf, p1 - &(tbuf[0])); // write whatever I've got
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p1 >= &(tbuf[sizeof(tbuf)]))
|
||||||
|
{
|
||||||
|
register size_t cb = write(tbuf, p1 - &(tbuf[0]));
|
||||||
|
|
||||||
|
if(!cb) // error (prevents infinite loops)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n += cb;
|
||||||
|
p1 = tbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(p1++) = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const String &s)
|
||||||
|
{
|
||||||
|
return write(s.c_str(), s.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const char str[])
|
||||||
|
{
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(char c)
|
||||||
|
{
|
||||||
|
return write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
return print((unsigned long) b, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(int n, int base)
|
||||||
|
{
|
||||||
|
return print((long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned int n, int base)
|
||||||
|
{
|
||||||
|
return print((unsigned long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0)
|
||||||
|
{
|
||||||
|
return write(n);
|
||||||
|
}
|
||||||
|
else if (base == 10)
|
||||||
|
{
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
int t = print('-');
|
||||||
|
n = -n;
|
||||||
|
return printNumber(n, 10) + t;
|
||||||
|
}
|
||||||
|
return printNumber(n, 10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return printNumber(n, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0)
|
||||||
|
return write(n);
|
||||||
|
else
|
||||||
|
return printNumber(n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(double n, int digits)
|
||||||
|
{
|
||||||
|
return printFloat(n, digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||||
|
{
|
||||||
|
size_t n = print(ifsh);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const Printable& x)
|
||||||
|
{
|
||||||
|
return x.printTo(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(void)
|
||||||
|
{
|
||||||
|
char tbuf[2];
|
||||||
|
|
||||||
|
tbuf[0] = '\r'; // this should be more efficient, and smaller
|
||||||
|
tbuf[1] = '\n';
|
||||||
|
return write(tbuf, 2);
|
||||||
|
// size_t n = print('\r');
|
||||||
|
// n += print('\n');
|
||||||
|
// return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const String &s)
|
||||||
|
{
|
||||||
|
size_t n = print(s);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const char c[])
|
||||||
|
{
|
||||||
|
size_t n = print(c);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(char c)
|
||||||
|
{
|
||||||
|
size_t n = print(c);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(b, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(int num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned int num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(double num, int digits)
|
||||||
|
{
|
||||||
|
size_t n = print(num, digits);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const Printable& x)
|
||||||
|
{
|
||||||
|
size_t n = print(x);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
size_t Print::printNumber(unsigned long n, uint8_t base)
|
||||||
|
{
|
||||||
|
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
|
char *str = &buf[sizeof(buf) - 1];
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
// prevent crash if called with base == 1
|
||||||
|
if (base < 2)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
unsigned long m = n;
|
||||||
|
n /= base;
|
||||||
|
char c = m - base * n;
|
||||||
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
|
} while(n);
|
||||||
|
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::printFloat(double number, uint8_t digits)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
if (isnan(number))
|
||||||
|
return print("nan");
|
||||||
|
if (isinf(number))
|
||||||
|
return print("inf");
|
||||||
|
if (number > 4294967040.0)
|
||||||
|
return print ("ovf"); // constant determined empirically
|
||||||
|
if (number <-4294967040.0)
|
||||||
|
return print ("ovf"); // constant determined empirically
|
||||||
|
|
||||||
|
// Handle negative numbers
|
||||||
|
if (number < 0.0)
|
||||||
|
{
|
||||||
|
n += print('-');
|
||||||
|
number = -number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
|
double rounding = 0.5;
|
||||||
|
for (uint8_t i=0; i<digits; ++i)
|
||||||
|
{
|
||||||
|
rounding /= 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
number += rounding;
|
||||||
|
|
||||||
|
// Extract the integer part of the number and print it
|
||||||
|
unsigned long int_part = (unsigned long)number;
|
||||||
|
double remainder = number - (double)int_part;
|
||||||
|
n += print(int_part);
|
||||||
|
|
||||||
|
// Print the decimal point, but only if there are digits beyond
|
||||||
|
if (digits > 0)
|
||||||
|
{
|
||||||
|
n += print(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract digits from the remainder one at a time
|
||||||
|
while (digits-- > 0)
|
||||||
|
{
|
||||||
|
remainder *= 10.0;
|
||||||
|
int toPrint = int(remainder);
|
||||||
|
n += print(toPrint);
|
||||||
|
remainder -= toPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// things that I added
|
||||||
|
|
||||||
|
int Print::printf(const char *pszFormat, ...) /*__attribute__ ((format(printf, 2, 3)))*/ // added API for 'printf' since it has been suggested...
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
int cbOut;
|
||||||
|
|
||||||
|
va_start(va, pszFormat);
|
||||||
|
|
||||||
|
cbOut = vsnprintf(NULL, 0, pszFormat, va);
|
||||||
|
|
||||||
|
if(cbOut > 0)
|
||||||
|
{
|
||||||
|
char *p1 = (char *)malloc(cbOut + 2);
|
||||||
|
|
||||||
|
if(p1)
|
||||||
|
{
|
||||||
|
cbOut = vsnprintf(p1, cbOut + 1, pszFormat, va);
|
||||||
|
print(p1);
|
||||||
|
free(p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
return cbOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Print::printf_P(const char *pszFormat, ...) /*__attribute__ ((format(printf_P, 2, 3)))*/ // added API for 'printf' since it has been suggested...
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
int cbOut;
|
||||||
|
|
||||||
|
va_start(va, pszFormat);
|
||||||
|
|
||||||
|
cbOut = vsnprintf_P(NULL, 0, (const char *)pszFormat, va);
|
||||||
|
|
||||||
|
if(cbOut > 0)
|
||||||
|
{
|
||||||
|
char *p1 = (char *)malloc(cbOut + 2);
|
||||||
|
|
||||||
|
if(p1)
|
||||||
|
{
|
||||||
|
cbOut = vsnprintf_P(p1, cbOut + 1, (const char *)pszFormat, va);
|
||||||
|
print(p1);
|
||||||
|
free(p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
return cbOut;
|
||||||
|
}
|
||||||
|
|
97
BootLoaders/Boards/orangerx/cores/xmega/Print.h
Normal file
97
BootLoaders/Boards/orangerx/cores/xmega/Print.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
Print.h - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Print_h
|
||||||
|
#define Print_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h> // for size_t
|
||||||
|
|
||||||
|
#include "WString.h"
|
||||||
|
#include "Printable.h"
|
||||||
|
|
||||||
|
#define DEC 10
|
||||||
|
#define HEX 16
|
||||||
|
#define OCT 8
|
||||||
|
#define BIN 2
|
||||||
|
|
||||||
|
class Print
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int write_error;
|
||||||
|
size_t printNumber(unsigned long, uint8_t);
|
||||||
|
size_t printFloat(double, uint8_t);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setWriteError(int err = 1) { write_error = err; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
Print() : write_error(0) {} // default constructor only assigns 0 to 'write_error'
|
||||||
|
|
||||||
|
int getWriteError() { return write_error; }
|
||||||
|
void clearWriteError() { setWriteError(0); }
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t) = 0; // derived class must implement
|
||||||
|
size_t write(const char *str)
|
||||||
|
{
|
||||||
|
if (str == NULL) return 0;
|
||||||
|
return write((const uint8_t *)str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
// write multiple characters from a buffer - default calls 'write(uint8_t)' on each byte
|
||||||
|
// NOTE: for better efficiency, a derived class SHOULD implement its own 'write' for a buffer
|
||||||
|
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size); // overridable
|
||||||
|
size_t write(const char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
return write((const uint8_t *)buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom mod - implement 'printf' member function
|
||||||
|
int printf(const char *pszFormat, ...) __attribute__ ((format(printf, 2, 3))); // added API for 'printf' since it has been suggested...
|
||||||
|
int printf_P(const char *pszFormat, ...) __attribute__ ((format(printf, 2, 3))); // added API for 'printf_P' since it has been suggested...
|
||||||
|
|
||||||
|
size_t print(const __FlashStringHelper *);
|
||||||
|
size_t print(const String &);
|
||||||
|
size_t print(const char[]);
|
||||||
|
size_t print(char);
|
||||||
|
size_t print(unsigned char, int = DEC);
|
||||||
|
size_t print(int, int = DEC);
|
||||||
|
size_t print(unsigned int, int = DEC);
|
||||||
|
size_t print(long, int = DEC);
|
||||||
|
size_t print(unsigned long, int = DEC);
|
||||||
|
size_t print(double, int = 2);
|
||||||
|
size_t print(const Printable&);
|
||||||
|
|
||||||
|
size_t println(const __FlashStringHelper *);
|
||||||
|
size_t println(const String &s);
|
||||||
|
size_t println(const char[]);
|
||||||
|
size_t println(char);
|
||||||
|
size_t println(unsigned char, int = DEC);
|
||||||
|
size_t println(int, int = DEC);
|
||||||
|
size_t println(unsigned int, int = DEC);
|
||||||
|
size_t println(long, int = DEC);
|
||||||
|
size_t println(unsigned long, int = DEC);
|
||||||
|
size_t println(double, int = 2);
|
||||||
|
size_t println(const Printable&);
|
||||||
|
size_t println(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
40
BootLoaders/Boards/orangerx/cores/xmega/Printable.h
Normal file
40
BootLoaders/Boards/orangerx/cores/xmega/Printable.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Printable.h - Interface class that allows printing of complex types
|
||||||
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Printable_h
|
||||||
|
#define Printable_h
|
||||||
|
|
||||||
|
#include <new.h>
|
||||||
|
|
||||||
|
class Print;
|
||||||
|
|
||||||
|
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||||
|
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||||
|
for users to print out instances of this class by passing them into the usual
|
||||||
|
Print::print and Print::println methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual size_t printTo(Print& p) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
28
BootLoaders/Boards/orangerx/cores/xmega/Server.h
Normal file
28
BootLoaders/Boards/orangerx/cores/xmega/Server.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
Server.h - Base class that provides Server
|
||||||
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef server_h
|
||||||
|
#define server_h
|
||||||
|
|
||||||
|
class Server : public Print {
|
||||||
|
public:
|
||||||
|
virtual void begin() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
362
BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp
Normal file
362
BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
Stream.cpp - adds parsing methods to Stream class
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Created July 2011
|
||||||
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
// if/branch optimization
|
||||||
|
#define UNLIKELY(x) (__builtin_expect (!!(x), 0))
|
||||||
|
#define LIKELY(x) (__builtin_expect (!!(x), 1))
|
||||||
|
|
||||||
|
|
||||||
|
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||||
|
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||||
|
|
||||||
|
// private method to read stream with timeout
|
||||||
|
int Stream::timedRead()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
_startMillis = millis();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = read();
|
||||||
|
|
||||||
|
if (c >= 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
|
wait_for_interrupt(); // XMega enhancement
|
||||||
|
|
||||||
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// private method to peek stream with timeout
|
||||||
|
int Stream::timedPeek()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
_startMillis = millis();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = peek();
|
||||||
|
|
||||||
|
if (c >= 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
|
wait_for_interrupt(); // XMega enhancement
|
||||||
|
|
||||||
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns peek of the next digit in the stream or -1 if timeout
|
||||||
|
// discards non-numeric characters
|
||||||
|
int Stream::peekNextDigit()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
c = timedPeek();
|
||||||
|
|
||||||
|
// refactored this for (possibly) better efficiency AND readability - seems to be the same size/footprint
|
||||||
|
// if (c < 0)
|
||||||
|
// return c; // timeout
|
||||||
|
//
|
||||||
|
// if (c == '-')
|
||||||
|
// return c;
|
||||||
|
//
|
||||||
|
// if (c >= '0' && c <= '9')
|
||||||
|
// return c;
|
||||||
|
|
||||||
|
if(UNLIKELY(c < 0) || // refactored. < 0 is a timeout
|
||||||
|
UNLIKELY(c == '-') || // negative (TODO: test for leading char only, or lead on exponent)
|
||||||
|
LIKELY(c >= '0' && c <= '9')) // numeric digit; TODO test for exponent on float?
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(); // discard non-numeric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||||
|
{
|
||||||
|
_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find returns true if the target string is found
|
||||||
|
bool Stream::find(char *target)
|
||||||
|
{
|
||||||
|
return findUntil(target, NULL/*""*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads data from the stream until the target string of given length is found
|
||||||
|
// returns true if target string is found, false if timed out
|
||||||
|
bool Stream::find(char *target, size_t length)
|
||||||
|
{
|
||||||
|
return findUntil(target, length, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// as find but search ends if the terminator string is found
|
||||||
|
bool Stream::findUntil(char *target, char *terminator)
|
||||||
|
{
|
||||||
|
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads data from the stream until the target string of the given length is found
|
||||||
|
// search terminated if the terminator string is found
|
||||||
|
// returns true if target string is found, false if terminated or timed out
|
||||||
|
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||||
|
{
|
||||||
|
size_t index = 0; // maximum target string length is 64k bytes!
|
||||||
|
size_t termIndex = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if(!target || *target == 0) // update, allow NULL pointer
|
||||||
|
{
|
||||||
|
return true; // return true if target is a null string
|
||||||
|
}
|
||||||
|
|
||||||
|
while( (c = timedRead()) > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(c != target[index])
|
||||||
|
{
|
||||||
|
index = 0; // reset index if any char does not match
|
||||||
|
}
|
||||||
|
|
||||||
|
if( c == target[index])
|
||||||
|
{
|
||||||
|
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
||||||
|
if(++index >= targetLen) // return true if all chars in the target match
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow for NULL 'terminator'
|
||||||
|
if(terminator && termLen > 0 &&
|
||||||
|
UNLIKELY(c == terminator[termIndex]))
|
||||||
|
{
|
||||||
|
if(++termIndex >= termLen)
|
||||||
|
{
|
||||||
|
return false; // return false if terminate string found before target string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
termIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the first valid (long) integer value from the current position.
|
||||||
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
|
// function is terminated by the first character that is not a digit.
|
||||||
|
long Stream::parseInt()
|
||||||
|
{
|
||||||
|
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// as above but a given skipChar is ignored
|
||||||
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
long Stream::parseInt(char skipChar)
|
||||||
|
{
|
||||||
|
boolean isNegative = false;
|
||||||
|
long value = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = peekNextDigit();
|
||||||
|
// ignore non numeric leading characters
|
||||||
|
if(c < 0)
|
||||||
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(c == skipChar)
|
||||||
|
; // ignore this charactor
|
||||||
|
else if(c == '-')
|
||||||
|
isNegative = true;
|
||||||
|
else if(c >= '0' && c <= '9') // is c a digit?
|
||||||
|
value = value * 10 + c - '0';
|
||||||
|
read(); // consume the character we got with peek
|
||||||
|
c = timedPeek();
|
||||||
|
}
|
||||||
|
while( (c >= '0' && c <= '9') || c == skipChar )
|
||||||
|
;
|
||||||
|
|
||||||
|
if(isNegative)
|
||||||
|
value = -value;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// as parseInt but returns a floating point value
|
||||||
|
float Stream::parseFloat()
|
||||||
|
{
|
||||||
|
return parseFloat(NO_SKIP_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// as above but the given skipChar is ignored
|
||||||
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
float Stream::parseFloat(char skipChar)
|
||||||
|
{
|
||||||
|
boolean isNegative = false;
|
||||||
|
boolean isFraction = false;
|
||||||
|
long value = 0;
|
||||||
|
char c;
|
||||||
|
float fraction = 1.0;
|
||||||
|
|
||||||
|
c = peekNextDigit();
|
||||||
|
// ignore non numeric leading characters
|
||||||
|
if(c < 0)
|
||||||
|
{
|
||||||
|
return 0; // zero returned if timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(c == skipChar)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
else if(c == '-')
|
||||||
|
{
|
||||||
|
isNegative = true;
|
||||||
|
}
|
||||||
|
else if (c == '.')
|
||||||
|
{
|
||||||
|
isFraction = true;
|
||||||
|
}
|
||||||
|
else if(c >= '0' && c <= '9') // is c a digit?
|
||||||
|
{
|
||||||
|
value = value * 10 + c - '0';
|
||||||
|
|
||||||
|
if(isFraction)
|
||||||
|
{
|
||||||
|
fraction *= 0.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read(); // consume the character we got with peek
|
||||||
|
c = timedPeek();
|
||||||
|
}
|
||||||
|
|
||||||
|
while( (c >= '0' && c <= '9') || c == '.' || c == skipChar )
|
||||||
|
;
|
||||||
|
|
||||||
|
if(isNegative)
|
||||||
|
value = -value;
|
||||||
|
if(isFraction)
|
||||||
|
return value * fraction;
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read characters from stream into buffer
|
||||||
|
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||||
|
// returns the number of characters placed in the buffer
|
||||||
|
// the buffer is NOT null terminated.
|
||||||
|
//
|
||||||
|
size_t Stream::readBytes(char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
while (count < length)
|
||||||
|
{
|
||||||
|
int c = timedRead();
|
||||||
|
|
||||||
|
if (c < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*buffer++ = (char)c;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// as readBytes with terminator character
|
||||||
|
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
if (length < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
while (index < length)
|
||||||
|
{
|
||||||
|
int c = timedRead();
|
||||||
|
if (c < 0 || c == terminator) break;
|
||||||
|
*buffer++ = (char)c;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index; // return number of characters, not including null terminator
|
||||||
|
}
|
||||||
|
|
||||||
|
String Stream::readString()
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
|
||||||
|
int c = timedRead();
|
||||||
|
|
||||||
|
while (c >= 0)
|
||||||
|
{
|
||||||
|
ret += (char)c;
|
||||||
|
c = timedRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Stream::readStringUntil(char terminator)
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
|
||||||
|
int c = timedRead();
|
||||||
|
|
||||||
|
while (c >= 0 && c != terminator)
|
||||||
|
{
|
||||||
|
ret += (char)c;
|
||||||
|
c = timedRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
96
BootLoaders/Boards/orangerx/cores/xmega/Stream.h
Normal file
96
BootLoaders/Boards/orangerx/cores/xmega/Stream.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
Stream.h - base class for character-based streams.
|
||||||
|
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Stream_h
|
||||||
|
#define Stream_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
// compatability macros for testing
|
||||||
|
/*
|
||||||
|
#define getInt() parseInt()
|
||||||
|
#define getInt(skipChar) parseInt(skipchar)
|
||||||
|
#define getFloat() parseFloat()
|
||||||
|
#define getFloat(skipChar) parseFloat(skipChar)
|
||||||
|
#define getString( pre_string, post_string, buffer, length)
|
||||||
|
readBytesBetween( pre_string, terminator, buffer, length)
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Stream : public Print
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||||
|
unsigned long _startMillis; // used for timeout measurement
|
||||||
|
int timedRead(); // private method to read stream with timeout
|
||||||
|
int timedPeek(); // private method to peek stream with timeout
|
||||||
|
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
|
||||||
|
Stream() {_timeout=1000;}
|
||||||
|
|
||||||
|
// parsing methods
|
||||||
|
|
||||||
|
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||||
|
|
||||||
|
bool find(char *target); // reads data from the stream until the target string is found
|
||||||
|
// returns true if target string is found, false if timed out (see setTimeout)
|
||||||
|
|
||||||
|
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||||
|
// returns true if target string is found, false if timed out
|
||||||
|
|
||||||
|
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
|
||||||
|
|
||||||
|
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||||
|
|
||||||
|
|
||||||
|
long parseInt(); // returns the first valid (long) integer value from the current position.
|
||||||
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
|
// integer is terminated by the first character that is not a digit.
|
||||||
|
|
||||||
|
float parseFloat(); // float version of parseInt
|
||||||
|
|
||||||
|
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
||||||
|
// terminates if length characters have been read or timeout (see setTimeout)
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||||
|
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
// Arduino String functions to be added here
|
||||||
|
String readString();
|
||||||
|
String readStringUntil(char terminator);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
||||||
|
// as above but the given skipChar is ignored
|
||||||
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
|
||||||
|
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
960
BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp
Normal file
960
BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp
Normal file
@ -0,0 +1,960 @@
|
|||||||
|
/* Tone.cpp
|
||||||
|
|
||||||
|
A Tone Generator Library
|
||||||
|
|
||||||
|
Written by Brett Hagman
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Version Modified By Date Comments
|
||||||
|
------- ----------- -------- --------
|
||||||
|
0001 B Hagman 09/08/02 Initial coding
|
||||||
|
0002 B Hagman 09/08/18 Multiple pins
|
||||||
|
0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
|
||||||
|
0004 B Hagman 09/09/26 Fixed problems with ATmega8
|
||||||
|
0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
|
||||||
|
09/11/25 Changed pin toggle method to XOR
|
||||||
|
09/11/25 Fixed timer0 from being excluded
|
||||||
|
0006 D Mellis 09/12/29 Replaced objects with functions
|
||||||
|
0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
|
||||||
|
0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
// COMPLETE re-write for ATXMega by Bob Frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
|
||||||
|
// NOTE: this still only supports one tone output. However, xmega can do more than one
|
||||||
|
// due to the way the timers are. In fact, 'E' series can probably do a LOT more
|
||||||
|
// than one. If you want to implement that, it's a public project, so get it working
|
||||||
|
// reliably and submit the changes, thanks.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
#if defined(TCC4) || !defined(TCC2)
|
||||||
|
|
||||||
|
// in these cases this file isn't ready for prime time, so disable it for now
|
||||||
|
|
||||||
|
#ifdef TONE_SUPPORTED
|
||||||
|
#undef TONE_SUPPORTED
|
||||||
|
#endif // TONE_SUPPORTED
|
||||||
|
|
||||||
|
#else // !TCC4 && TCC2
|
||||||
|
|
||||||
|
#ifndef TONE_SUPPORTED
|
||||||
|
#define TONE_SUPPORTED // for now turn it off for 'E"
|
||||||
|
#endif // TONE_SUPPORTED
|
||||||
|
|
||||||
|
#endif // TCC4 || !TCC2
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TONE_SUPPORTED
|
||||||
|
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#define PROGMEM_ORIG PROGMEM
|
||||||
|
#else // PROGMEM workaround
|
||||||
|
|
||||||
|
// to avoid the bogus "initialized variables" warning
|
||||||
|
#ifdef PROGMEM
|
||||||
|
#undef PROGMEM
|
||||||
|
#endif // PROGMEM re-define
|
||||||
|
|
||||||
|
#define PROGMEM __attribute__((section(".progmem.tone")))
|
||||||
|
#define PROGMEM_ORIG __attribute__((__progmem__))
|
||||||
|
|
||||||
|
#endif // check for GNUC >= or < 4.6
|
||||||
|
|
||||||
|
|
||||||
|
static PORT_t *pTonePort = NULL; // must assign at startup due to ISR
|
||||||
|
static uint8_t bToneMask = 0; // bitmask for tone pin
|
||||||
|
static unsigned long toggle_count = 0; // number of cycles to output
|
||||||
|
|
||||||
|
static void toneBegin(uint8_t _pin, uint8_t _div, uint16_t _per)
|
||||||
|
{
|
||||||
|
pTonePort = (PORT_t *)portModeRegister(digitalPinToPort(_pin));
|
||||||
|
bToneMask = digitalPinToBitMask(_pin);
|
||||||
|
|
||||||
|
|
||||||
|
// Set the pinMode as OUTPUT
|
||||||
|
pinMode(_pin, OUTPUT);
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available */
|
||||||
|
|
||||||
|
TCE0_INTCTRLA = 0; // temporarily disable overflow interrupt
|
||||||
|
TCE0_INTCTRLB = 0; // disable other interrupts
|
||||||
|
TCE0_CTRLA = _div; // divisor for pre-scaler
|
||||||
|
TCE0_CTRLB = TC_WGMODE_NORMAL_gc; // 'normal' mode (interrupt on 'overflow')
|
||||||
|
TCE0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4)
|
||||||
|
TCE0_CTRLE = 0; // 16-bit mode
|
||||||
|
TCE0_PER = _per; // period (16-bit value)
|
||||||
|
TCE0_INTCTRLA = 3; // overflow int level 3 (enables interrupt)
|
||||||
|
|
||||||
|
#elif defined(TCC4) // E series and anything else with 'TCC4'
|
||||||
|
|
||||||
|
TCC4_INTCTRLA = 0; // temporarily disable overflow interrupt
|
||||||
|
TCC4_INTCTRLB = 0; // disable other interrupts
|
||||||
|
TCC4_CTRLA = _div; // divisor for pre-scaler
|
||||||
|
TCC4_CTRLB = TC45_WGMODE_NORMAL_gc; // 'normal' mode (interrupt on 'overflow')
|
||||||
|
TCC4_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4)
|
||||||
|
TCC4_CTRLE = 0; // 16-bit mode
|
||||||
|
TCC4_PER = _per; // period (16-bit value)
|
||||||
|
TCC4_INTCTRLA = 3; // overflow int level 3 (enables interrupt)
|
||||||
|
|
||||||
|
#else // other stuff not yet explored by me
|
||||||
|
|
||||||
|
TCC0_INTCTRLA = 0; // temporarily disable overflow interrupt
|
||||||
|
TCC0_INTCTRLB = 0; // disable other interrupts
|
||||||
|
TCC0_CTRLA = _div; // divisor for pre-scaler
|
||||||
|
TCC0_CTRLB = TC_WGMODE_NORMAL_gc; // 'normal' mode (interrupt on 'overflow')
|
||||||
|
TCC0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4)
|
||||||
|
TCC0_CTRLE = 0; // 16-bit mode
|
||||||
|
TCC0_PER = _per; // period (16-bit value)
|
||||||
|
TCC0_INTCTRLA = 3; // overflow int level 3 (enables interrupt)
|
||||||
|
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18
|
||||||
|
|
||||||
|
// tone starts now, shuts off when the 'toggle_count' hits zero
|
||||||
|
}
|
||||||
|
|
||||||
|
// frequency (in hertz) and duration (in milliseconds).
|
||||||
|
|
||||||
|
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
|
||||||
|
{
|
||||||
|
register int8_t b1;
|
||||||
|
unsigned short per, w2;
|
||||||
|
unsigned long ulTemp;
|
||||||
|
static const uint16_t aPreScaler[] PROGMEM = {1,2,4,8,64,256,1024}; // pre-scaler
|
||||||
|
|
||||||
|
// frequency
|
||||||
|
|
||||||
|
// based on the frequency, set up the divider and period
|
||||||
|
// period is 16-bits
|
||||||
|
|
||||||
|
// NOTE: use the smallest possible divisor
|
||||||
|
|
||||||
|
if(!frequency)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulTemp = frequency * 16384L; // ideal counter 16384
|
||||||
|
|
||||||
|
for(b1=sizeof(aPreScaler)/sizeof(aPreScaler[0]) - 1; b1 > 0; b1--)
|
||||||
|
{
|
||||||
|
w2 = pgm_read_word(&(aPreScaler[0]) + b1);
|
||||||
|
if(((unsigned long)F_CPU / 2 / w2) >= ulTemp) // note that I flip the bit every OTHER cycle
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!b1)
|
||||||
|
{
|
||||||
|
w2 = 1; // make sure
|
||||||
|
}
|
||||||
|
|
||||||
|
// b1 is the divisor bit value for CTRLA, per caches the actual divisor
|
||||||
|
|
||||||
|
per = (F_CPU / 2 / w2) / frequency;
|
||||||
|
if(!per)
|
||||||
|
{
|
||||||
|
per++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the toggle count
|
||||||
|
if (duration > 0)
|
||||||
|
{
|
||||||
|
toggle_count = 2 * frequency * duration / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toggle_count = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
toneBegin(_pin, b1, per);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: this function only works properly for timer E (the only one we use
|
||||||
|
// currently). Since I use the ISR on timer E to toggle the pin, it should
|
||||||
|
// be just fine.
|
||||||
|
|
||||||
|
void disableTimer(uint8_t _timer)
|
||||||
|
{
|
||||||
|
// parameter is ignored
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available */
|
||||||
|
|
||||||
|
// disable under/overflow and comparison interrupts FIRST
|
||||||
|
TCE0_INTCTRLA = 0; // no underflow interrupts
|
||||||
|
TCE0_INTCTRLB = 0; // no comparison interrupts
|
||||||
|
|
||||||
|
pTonePort = NULL; // make sure
|
||||||
|
|
||||||
|
// re-assign TCE0 defaults. see 'wiring.c'
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 22 /* meaning PORTE has 8 pins */
|
||||||
|
|
||||||
|
TCE2_CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1
|
||||||
|
TCE2_CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2)
|
||||||
|
// TCE2_CTRLC = 0; // when timer not running, sets compare (13.9.3)
|
||||||
|
TCE2_CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4
|
||||||
|
TCE2_CTRLF = 0; // not resetting or anything (13.9.7)
|
||||||
|
|
||||||
|
TCE2_LPER = 255; // count 255 to 0 (total period = 256)
|
||||||
|
TCE2_HPER = 255;
|
||||||
|
|
||||||
|
// pre-assign comparison registers to 'zero' (for PWM out) which is actually 255
|
||||||
|
// 'timer 2' counts DOWN. This, however, would generate a '1' output.
|
||||||
|
|
||||||
|
TCE2_LCMPA = 255;
|
||||||
|
TCE2_LCMPB = 255;
|
||||||
|
TCE2_LCMPC = 255;
|
||||||
|
TCE2_LCMPD = 255;
|
||||||
|
|
||||||
|
TCE2_HCMPA = 255;
|
||||||
|
TCE2_HCMPB = 255;
|
||||||
|
TCE2_HCMPC = 255;
|
||||||
|
TCE2_HCMPD = 255;
|
||||||
|
|
||||||
|
TCE2_INTCTRLA = 0; // no underflow interrupts
|
||||||
|
TCE2_INTCTRLB = 0; // no comparison interrupts
|
||||||
|
|
||||||
|
#else // 16-bit timer on TCE0
|
||||||
|
|
||||||
|
TCE0_CTRLA = 5; // b0101 - divide by 64 - D manual 12.11.1
|
||||||
|
TCE0_CTRLB = TC_WGMODE_SS_gc; // single-slope PWM. NOTE: this counts UP, whereas the other timers count DOWN
|
||||||
|
// other bits (high nybble) are OFF - they enable output on the 4 port E pins
|
||||||
|
// TCE0_CTRLC = 0; // when timer not running, sets compare (12.11.3)
|
||||||
|
TCE0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4)
|
||||||
|
TCE0_CTRLE = 1; // normal 8-bit timer (set to 0 for 16-bit mode) (12.11.5)
|
||||||
|
|
||||||
|
// make sure the timer E 'period' register is correctly set at 255 (i.e. 0-255 or 256 clock cycles).
|
||||||
|
TCE0_PER = 255;
|
||||||
|
|
||||||
|
// pre-assign comparison registers to 'zero' (for PWM out) which is actually 255
|
||||||
|
// timer 0 can be configured to count UP or DOWN, but for single-slope PWM it is
|
||||||
|
// always 'UP'. A value of '255' should generate a '1' output for each PWM.
|
||||||
|
|
||||||
|
TCE0_CCA = 255;
|
||||||
|
TCE0_CCB = 255;
|
||||||
|
TCE0_CCC = 255;
|
||||||
|
TCE0_CCD = 255;
|
||||||
|
|
||||||
|
#endif // 8/16 bit timer on E
|
||||||
|
|
||||||
|
#elif defined(TCC4) // E series and anything else with 'TCC4'
|
||||||
|
|
||||||
|
// disable under/overflow and comparison interrupts FIRST
|
||||||
|
TCC4_INTCTRLA = 0; // no underflow interrupts
|
||||||
|
TCC4_INTCTRLB = 0; // no comparison interrupts
|
||||||
|
|
||||||
|
pTonePort = NULL; // make sure
|
||||||
|
|
||||||
|
// re-assign TCC0 defaults. see 'wiring.c'
|
||||||
|
|
||||||
|
TCC4_CTRLA = 5; // b0101 - divide by 64 - E manual 13.13.1
|
||||||
|
TCC4_CTRLB = TC45_BYTEM_BYTEMODE_gc | TC45_WGMODE_SINGLESLOPE_gc; // byte mode, single slope
|
||||||
|
// TCC5_CTRLC = 0; // when timer not running, sets compare (13.9.3)
|
||||||
|
TCC4_CTRLD = 0; // events off
|
||||||
|
TCC4_CTRLE = 0; // no output on L pins
|
||||||
|
TCC4_CTRLF = 0; // no output on H pins
|
||||||
|
|
||||||
|
TCC4_PER = 255; // 255 for period limit
|
||||||
|
|
||||||
|
// pre-assign comparison registers to 'zero' (for PWM out) which is actually 255
|
||||||
|
// 'timer 2' counts DOWN.
|
||||||
|
|
||||||
|
TCC4_CCA = 65535;
|
||||||
|
TCC4_CCB = 65535;
|
||||||
|
TCC4_CCC = 65535;
|
||||||
|
TCC4_CCD = 65535;
|
||||||
|
|
||||||
|
#else // other stuff not yet explored by me
|
||||||
|
|
||||||
|
// disable under/overflow and comparison interrupts FIRST
|
||||||
|
TCC0_INTCTRLA = 0; // no underflow interrupts
|
||||||
|
TCC0_INTCTRLB = 0; // no comparison interrupts
|
||||||
|
|
||||||
|
pTonePort = NULL; // make sure
|
||||||
|
|
||||||
|
// re-assign TCC0 defaults. see 'wiring.c'
|
||||||
|
|
||||||
|
TCC2_CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1
|
||||||
|
TCC2_CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2)
|
||||||
|
// TCC2_CTRLC = 0; // when timer not running, sets compare (13.9.3)
|
||||||
|
TCC2_CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4
|
||||||
|
TCC2_CTRLF = 0; // not resetting or anything (13.9.7)
|
||||||
|
|
||||||
|
TCC2_LPER = 255; // count 255 to 0 (total period = 256)
|
||||||
|
TCC2_HPER = 255;
|
||||||
|
|
||||||
|
// pre-assign comparison registers to 'zero' (for PWM out) which is actually 255
|
||||||
|
// 'timer 2' counts DOWN. This, however, would generate a '1' output.
|
||||||
|
|
||||||
|
TCC2_LCMPA = 255;
|
||||||
|
TCC2_LCMPB = 255;
|
||||||
|
TCC2_LCMPC = 255;
|
||||||
|
TCC2_LCMPD = 255;
|
||||||
|
|
||||||
|
TCC2_HCMPA = 255;
|
||||||
|
TCC2_HCMPB = 255;
|
||||||
|
TCC2_HCMPC = 255;
|
||||||
|
TCC2_HCMPD = 255;
|
||||||
|
|
||||||
|
TCC2_INTCTRLA = 0; // no underflow interrupts
|
||||||
|
TCC2_INTCTRLB = 0; // no comparison interrupts
|
||||||
|
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18
|
||||||
|
}
|
||||||
|
|
||||||
|
void noTone(uint8_t _pin)
|
||||||
|
{
|
||||||
|
disableTimer(0);
|
||||||
|
|
||||||
|
digitalWrite(_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 18 /* meaning PORTE exists */
|
||||||
|
ISR(TCE0_OVF_vect) // the 'overflow' vector on timer E0
|
||||||
|
#elif defined(TCC4) // E series and anything else with 'TCC4'
|
||||||
|
ISR(TCC4_OVF_vect) // the 'overflow' vector on timer C4
|
||||||
|
#else // everything else
|
||||||
|
ISR(TCC0_OVF_vect) // the 'overflow' vector on timer C0
|
||||||
|
#endif // PORTE exist check
|
||||||
|
{
|
||||||
|
if(!toggle_count || !pTonePort || !bToneMask
|
||||||
|
#if 1 /* this section in for bullet-proofing, consider removing */
|
||||||
|
|| (pTonePort != &PORTA &&
|
||||||
|
#if NUM_ANALOG_PINS > 8
|
||||||
|
pTonePort != &PORTB &&
|
||||||
|
#endif // NUM_ANALOG_PINS > 8
|
||||||
|
pTonePort != &PORTC && pTonePort != &PORTD &&
|
||||||
|
#if NUM_DIGITAL_PINS > 18
|
||||||
|
pTonePort != &PORTE &&
|
||||||
|
#endif // PORTE exist check
|
||||||
|
pTonePort != &PORTR)
|
||||||
|
#endif // 1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// disable the timer (also disables the interrupt)
|
||||||
|
disableTimer(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// each time I get an overflow, toggle the tone pin
|
||||||
|
|
||||||
|
pTonePort->OUTTGL = bToneMask; // toggle that bit
|
||||||
|
toggle_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 // OLD CODE for reference only
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
||||||
|
#define TCCR2A TCCR2
|
||||||
|
#define TCCR2B TCCR2
|
||||||
|
#define COM2A1 COM21
|
||||||
|
#define COM2A0 COM20
|
||||||
|
#define OCR2A OCR2
|
||||||
|
#define TIMSK2 TIMSK
|
||||||
|
#define OCIE2A OCIE2
|
||||||
|
#define TIMER2_COMPA_vect TIMER2_COMP_vect
|
||||||
|
#define TIMSK1 TIMSK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// timerx_toggle_count:
|
||||||
|
// > 0 - duration specified
|
||||||
|
// = 0 - stopped
|
||||||
|
// < 0 - infinitely (until stop() method called, or new play() called)
|
||||||
|
|
||||||
|
#if !defined(__AVR_ATmega8__)
|
||||||
|
volatile long timer0_toggle_count;
|
||||||
|
volatile uint8_t *timer0_pin_port;
|
||||||
|
volatile uint8_t timer0_pin_mask;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile long timer1_toggle_count;
|
||||||
|
volatile uint8_t *timer1_pin_port;
|
||||||
|
volatile uint8_t timer1_pin_mask;
|
||||||
|
volatile long timer2_toggle_count;
|
||||||
|
volatile uint8_t *timer2_pin_port;
|
||||||
|
volatile uint8_t timer2_pin_mask;
|
||||||
|
|
||||||
|
#if defined(TIMSK3)
|
||||||
|
volatile long timer3_toggle_count;
|
||||||
|
volatile uint8_t *timer3_pin_port;
|
||||||
|
volatile uint8_t timer3_pin_mask;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIMSK4)
|
||||||
|
volatile long timer4_toggle_count;
|
||||||
|
volatile uint8_t *timer4_pin_port;
|
||||||
|
volatile uint8_t timer4_pin_mask;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIMSK5)
|
||||||
|
volatile long timer5_toggle_count;
|
||||||
|
volatile uint8_t *timer5_pin_port;
|
||||||
|
volatile uint8_t timer5_pin_mask;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
|
||||||
|
#define AVAILABLE_TONE_PINS 1
|
||||||
|
#define USE_TIMER2
|
||||||
|
|
||||||
|
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
|
||||||
|
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ };
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega8__)
|
||||||
|
|
||||||
|
#define AVAILABLE_TONE_PINS 1
|
||||||
|
#define USE_TIMER2
|
||||||
|
|
||||||
|
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
|
||||||
|
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
|
|
||||||
|
#define AVAILABLE_TONE_PINS 1
|
||||||
|
#define USE_TIMER3
|
||||||
|
|
||||||
|
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ };
|
||||||
|
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define AVAILABLE_TONE_PINS 1
|
||||||
|
#define USE_TIMER2
|
||||||
|
|
||||||
|
// Leave timer 0 to last.
|
||||||
|
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
|
||||||
|
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: K&R coding style edited away. Allman style rules - BF
|
||||||
|
|
||||||
|
static int8_t toneBegin(uint8_t _pin)
|
||||||
|
{
|
||||||
|
int8_t _timer = -1;
|
||||||
|
|
||||||
|
// if we're already using the pin, the timer should be configured.
|
||||||
|
for (int i = 0; i < AVAILABLE_TONE_PINS; i++)
|
||||||
|
{
|
||||||
|
if (tone_pins[i] == _pin)
|
||||||
|
{
|
||||||
|
return pgm_read_byte(tone_pin_to_timer_PGM + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for an unused timer.
|
||||||
|
for (int i = 0; i < AVAILABLE_TONE_PINS; i++)
|
||||||
|
{
|
||||||
|
if (tone_pins[i] == 255)
|
||||||
|
{
|
||||||
|
tone_pins[i] = _pin;
|
||||||
|
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_timer != -1)
|
||||||
|
{
|
||||||
|
// Set timer specific stuff
|
||||||
|
// All timers in CTC mode
|
||||||
|
// 8 bit timers will require changing prescalar values,
|
||||||
|
// whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
|
||||||
|
switch (_timer)
|
||||||
|
{
|
||||||
|
#if defined(TCCR0A) && defined(TCCR0B)
|
||||||
|
case 0:
|
||||||
|
// 8 bit timer
|
||||||
|
TCCR0A = 0;
|
||||||
|
TCCR0B = 0;
|
||||||
|
bitWrite(TCCR0A, WGM01, 1);
|
||||||
|
bitWrite(TCCR0B, CS00, 1);
|
||||||
|
timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
||||||
|
timer0_pin_mask = digitalPinToBitMask(_pin);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12)
|
||||||
|
case 1:
|
||||||
|
// 16 bit timer
|
||||||
|
TCCR1A = 0;
|
||||||
|
TCCR1B = 0;
|
||||||
|
bitWrite(TCCR1B, WGM12, 1);
|
||||||
|
bitWrite(TCCR1B, CS10, 1);
|
||||||
|
timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
||||||
|
timer1_pin_mask = digitalPinToBitMask(_pin);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR2A) && defined(TCCR2B)
|
||||||
|
case 2:
|
||||||
|
// 8 bit timer
|
||||||
|
TCCR2A = 0;
|
||||||
|
TCCR2B = 0;
|
||||||
|
bitWrite(TCCR2A, WGM21, 1);
|
||||||
|
bitWrite(TCCR2B, CS20, 1);
|
||||||
|
timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
||||||
|
timer2_pin_mask = digitalPinToBitMask(_pin);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3)
|
||||||
|
case 3:
|
||||||
|
// 16 bit timer
|
||||||
|
TCCR3A = 0;
|
||||||
|
TCCR3B = 0;
|
||||||
|
bitWrite(TCCR3B, WGM32, 1);
|
||||||
|
bitWrite(TCCR3B, CS30, 1);
|
||||||
|
timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
||||||
|
timer3_pin_mask = digitalPinToBitMask(_pin);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4)
|
||||||
|
case 4:
|
||||||
|
// 16 bit timer
|
||||||
|
TCCR4A = 0;
|
||||||
|
TCCR4B = 0;
|
||||||
|
#if defined(WGM42)
|
||||||
|
bitWrite(TCCR4B, WGM42, 1);
|
||||||
|
#elif defined(CS43)
|
||||||
|
#warning this may not be correct
|
||||||
|
// atmega32u4
|
||||||
|
bitWrite(TCCR4B, CS43, 1);
|
||||||
|
#endif
|
||||||
|
bitWrite(TCCR4B, CS40, 1);
|
||||||
|
timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
||||||
|
timer4_pin_mask = digitalPinToBitMask(_pin);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5)
|
||||||
|
case 5:
|
||||||
|
// 16 bit timer
|
||||||
|
TCCR5A = 0;
|
||||||
|
TCCR5B = 0;
|
||||||
|
bitWrite(TCCR5B, WGM52, 1);
|
||||||
|
bitWrite(TCCR5B, CS50, 1);
|
||||||
|
timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
||||||
|
timer5_pin_mask = digitalPinToBitMask(_pin);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// frequency (in hertz) and duration (in milliseconds).
|
||||||
|
|
||||||
|
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
|
||||||
|
{
|
||||||
|
uint8_t prescalarbits = 0b001;
|
||||||
|
long toggle_count = 0;
|
||||||
|
uint32_t ocr = 0;
|
||||||
|
int8_t _timer;
|
||||||
|
|
||||||
|
_timer = toneBegin(_pin);
|
||||||
|
|
||||||
|
if (_timer >= 0)
|
||||||
|
{
|
||||||
|
// Set the pinMode as OUTPUT
|
||||||
|
pinMode(_pin, OUTPUT);
|
||||||
|
|
||||||
|
// if we are using an 8 bit timer, scan through prescalars to find the best fit
|
||||||
|
if (_timer == 0 || _timer == 2)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 - 1;
|
||||||
|
prescalarbits = 0b001; // ck/1: same for both timers
|
||||||
|
if (ocr > 255)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 / 8 - 1;
|
||||||
|
prescalarbits = 0b010; // ck/8: same for both timers
|
||||||
|
|
||||||
|
if (_timer == 2 && ocr > 255)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 / 32 - 1;
|
||||||
|
prescalarbits = 0b011;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocr > 255)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 / 64 - 1;
|
||||||
|
prescalarbits = _timer == 0 ? 0b011 : 0b100;
|
||||||
|
|
||||||
|
if (_timer == 2 && ocr > 255)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 / 128 - 1;
|
||||||
|
prescalarbits = 0b101;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocr > 255)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 / 256 - 1;
|
||||||
|
prescalarbits = _timer == 0 ? 0b100 : 0b110;
|
||||||
|
if (ocr > 255)
|
||||||
|
{
|
||||||
|
// can't do any better than /1024
|
||||||
|
ocr = F_CPU / frequency / 2 / 1024 - 1;
|
||||||
|
prescalarbits = _timer == 0 ? 0b101 : 0b111;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(TCCR0B)
|
||||||
|
if (_timer == 0)
|
||||||
|
{
|
||||||
|
TCCR0B = prescalarbits;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if defined(TCCR2B)
|
||||||
|
{
|
||||||
|
TCCR2B = prescalarbits;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
// dummy place holder to make the above ifdefs work
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// two choices for the 16 bit timers: ck/1 or ck/64
|
||||||
|
ocr = F_CPU / frequency / 2 - 1;
|
||||||
|
|
||||||
|
prescalarbits = 0b001;
|
||||||
|
if (ocr > 0xffff)
|
||||||
|
{
|
||||||
|
ocr = F_CPU / frequency / 2 / 64 - 1;
|
||||||
|
prescalarbits = 0b011;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_timer == 1)
|
||||||
|
{
|
||||||
|
#if defined(TCCR1B)
|
||||||
|
TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(TCCR3B)
|
||||||
|
else if (_timer == 3)
|
||||||
|
TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
|
||||||
|
#endif
|
||||||
|
#if defined(TCCR4B)
|
||||||
|
else if (_timer == 4)
|
||||||
|
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
|
||||||
|
#endif
|
||||||
|
#if defined(TCCR5B)
|
||||||
|
else if (_timer == 5)
|
||||||
|
TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate the toggle count
|
||||||
|
if (duration > 0)
|
||||||
|
{
|
||||||
|
toggle_count = 2 * frequency * duration / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toggle_count = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the OCR for the given timer,
|
||||||
|
// set the toggle count,
|
||||||
|
// then turn on the interrupts
|
||||||
|
switch (_timer)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
|
||||||
|
case 0:
|
||||||
|
OCR0A = ocr;
|
||||||
|
timer0_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK0, OCIE0A, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
|
||||||
|
OCR1A = ocr;
|
||||||
|
timer1_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK1, OCIE1A, 1);
|
||||||
|
#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
|
||||||
|
// this combination is for at least the ATmega32
|
||||||
|
OCR1A = ocr;
|
||||||
|
timer1_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK, OCIE1A, 1);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
|
||||||
|
case 2:
|
||||||
|
OCR2A = ocr;
|
||||||
|
timer2_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK2, OCIE2A, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIMSK3)
|
||||||
|
case 3:
|
||||||
|
OCR3A = ocr;
|
||||||
|
timer3_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK3, OCIE3A, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIMSK4)
|
||||||
|
case 4:
|
||||||
|
OCR4A = ocr;
|
||||||
|
timer4_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK4, OCIE4A, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
|
||||||
|
case 5:
|
||||||
|
OCR5A = ocr;
|
||||||
|
timer5_toggle_count = toggle_count;
|
||||||
|
bitWrite(TIMSK5, OCIE5A, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// XXX: this function only works properly for timer 2 (the only one we use
|
||||||
|
// currently). for the others, it should end the tone, but won't restore
|
||||||
|
// proper PWM functionality for the timer.
|
||||||
|
void disableTimer(uint8_t _timer)
|
||||||
|
{
|
||||||
|
switch (_timer)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
#if defined(TIMSK0)
|
||||||
|
TIMSK0 = 0;
|
||||||
|
#elif defined(TIMSK)
|
||||||
|
TIMSK = 0; // atmega32
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if defined(TIMSK1) && defined(OCIE1A)
|
||||||
|
case 1:
|
||||||
|
bitWrite(TIMSK1, OCIE1A, 0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
#if defined(TIMSK2) && defined(OCIE2A)
|
||||||
|
bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt
|
||||||
|
#endif
|
||||||
|
#if defined(TCCR2A) && defined(WGM20)
|
||||||
|
TCCR2A = (1 << WGM20);
|
||||||
|
#endif
|
||||||
|
#if defined(TCCR2B) && defined(CS22)
|
||||||
|
TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
|
||||||
|
#endif
|
||||||
|
#if defined(OCR2A)
|
||||||
|
OCR2A = 0;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if defined(TIMSK3)
|
||||||
|
case 3:
|
||||||
|
TIMSK3 = 0;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIMSK4)
|
||||||
|
case 4:
|
||||||
|
TIMSK4 = 0;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIMSK5)
|
||||||
|
case 5:
|
||||||
|
TIMSK5 = 0;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: this function only works properly for timer 2 (the only one we use
|
||||||
|
// currently). for the others, it should end the tone, but won't restore
|
||||||
|
// proper PWM functionality for the timer.
|
||||||
|
void disableTimer(uint8_t _timer)
|
||||||
|
|
||||||
|
void noTone(uint8_t _pin)
|
||||||
|
{
|
||||||
|
int8_t _timer = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < AVAILABLE_TONE_PINS; i++)
|
||||||
|
{
|
||||||
|
if (tone_pins[i] == _pin)
|
||||||
|
{
|
||||||
|
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
|
||||||
|
tone_pins[i] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disableTimer(_timer);
|
||||||
|
|
||||||
|
digitalWrite(_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_TIMER0
|
||||||
|
ISR(TIMER0_COMPA_vect)
|
||||||
|
{
|
||||||
|
if (timer0_toggle_count != 0)
|
||||||
|
{
|
||||||
|
// toggle the pin
|
||||||
|
*timer0_pin_port ^= timer0_pin_mask;
|
||||||
|
|
||||||
|
if (timer0_toggle_count > 0)
|
||||||
|
timer0_toggle_count--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disableTimer(0);
|
||||||
|
*timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_TIMER1
|
||||||
|
ISR(TIMER1_COMPA_vect)
|
||||||
|
{
|
||||||
|
if (timer1_toggle_count != 0)
|
||||||
|
{
|
||||||
|
// toggle the pin
|
||||||
|
*timer1_pin_port ^= timer1_pin_mask;
|
||||||
|
|
||||||
|
if (timer1_toggle_count > 0)
|
||||||
|
timer1_toggle_count--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disableTimer(1);
|
||||||
|
*timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_TIMER2
|
||||||
|
ISR(TIMER2_COMPA_vect)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (timer2_toggle_count != 0)
|
||||||
|
{
|
||||||
|
// toggle the pin
|
||||||
|
*timer2_pin_port ^= timer2_pin_mask;
|
||||||
|
|
||||||
|
if (timer2_toggle_count > 0)
|
||||||
|
timer2_toggle_count--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// need to call noTone() so that the tone_pins[] entry is reset, so the
|
||||||
|
// timer gets initialized next time we call tone().
|
||||||
|
// XXX: this assumes timer 2 is always the first one used.
|
||||||
|
noTone(tone_pins[0]);
|
||||||
|
// disableTimer(2);
|
||||||
|
// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_TIMER3
|
||||||
|
ISR(TIMER3_COMPA_vect)
|
||||||
|
{
|
||||||
|
if (timer3_toggle_count != 0)
|
||||||
|
{
|
||||||
|
// toggle the pin
|
||||||
|
*timer3_pin_port ^= timer3_pin_mask;
|
||||||
|
|
||||||
|
if (timer3_toggle_count > 0)
|
||||||
|
timer3_toggle_count--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disableTimer(3);
|
||||||
|
*timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_TIMER4
|
||||||
|
ISR(TIMER4_COMPA_vect)
|
||||||
|
{
|
||||||
|
if (timer4_toggle_count != 0)
|
||||||
|
{
|
||||||
|
// toggle the pin
|
||||||
|
*timer4_pin_port ^= timer4_pin_mask;
|
||||||
|
|
||||||
|
if (timer4_toggle_count > 0)
|
||||||
|
timer4_toggle_count--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disableTimer(4);
|
||||||
|
*timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_TIMER5
|
||||||
|
ISR(TIMER5_COMPA_vect)
|
||||||
|
{
|
||||||
|
if (timer5_toggle_count != 0)
|
||||||
|
{
|
||||||
|
// toggle the pin
|
||||||
|
*timer5_pin_port ^= timer5_pin_mask;
|
||||||
|
|
||||||
|
if (timer5_toggle_count > 0)
|
||||||
|
timer5_toggle_count--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disableTimer(5);
|
||||||
|
*timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // 0 [OLD CODE]
|
||||||
|
|
||||||
|
#endif // TONE_SUPPORTED
|
||||||
|
|
275
BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h
Normal file
275
BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// _ _ ____ ____ _ _ _ //
|
||||||
|
// | | | |/ ___| | __ ) / \ _ __ (_) | |__ //
|
||||||
|
// | | | |\___ \ | _ \ / _ \ | '_ \ | | | '_ \ //
|
||||||
|
// | |_| | ___) || |_) |/ ___ \ | |_) || | _ | | | | //
|
||||||
|
// \___/ |____/ |____//_/ \_\| .__/ |_|(_)|_| |_| //
|
||||||
|
// |_| //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef __USBAPI__
|
||||||
|
#define __USBAPI__
|
||||||
|
|
||||||
|
#if defined(USBCON)
|
||||||
|
|
||||||
|
#include "USBCore.h" /* make sure since I use its definitions here */
|
||||||
|
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif // __cplusplus
|
||||||
|
extern void error_print(const char *p1); // TEMPORARY
|
||||||
|
extern void error_print_(const char *p1); // TEMPORARY
|
||||||
|
extern void error_printH(unsigned long); // TEMPORARY
|
||||||
|
extern void error_printH_(unsigned long); // TEMPORARY
|
||||||
|
extern void error_printL(unsigned long); // TEMPORARY
|
||||||
|
extern void error_printL_(unsigned long); // TEMPORARY
|
||||||
|
extern void error_printP(const void * /*PROGMEM*/ p1); // TEMPORARY
|
||||||
|
extern void error_printP_(const void * /*PROGMEM*/ p1); // TEMPORARY
|
||||||
|
extern void DumpHex(void *pBuf, uint8_t nBytes);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#else // DEBUG_CODE
|
||||||
|
|
||||||
|
#define error_print(p1)
|
||||||
|
#define error_print_(p1)
|
||||||
|
#define error_printH(X)
|
||||||
|
#define error_printH_(X)
|
||||||
|
#define error_printL(X)
|
||||||
|
#define error_printL_(X)
|
||||||
|
#define error_printP(p1)
|
||||||
|
#define error_printP_(p1)
|
||||||
|
#define DumpHex(X,Y)
|
||||||
|
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// USB
|
||||||
|
|
||||||
|
class USBDevice_
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
USBDevice_();
|
||||||
|
bool configured();
|
||||||
|
|
||||||
|
void attach();
|
||||||
|
void detach(); // Serial port goes down too...
|
||||||
|
void poll();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static XMegaEPDataStruct *GetEPData(); // necessary
|
||||||
|
};
|
||||||
|
|
||||||
|
extern USBDevice_ USBDevice;
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Serial over CDC (Serial1 is the physical port)
|
||||||
|
|
||||||
|
class Serial_ : public Stream
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int peek_buffer;
|
||||||
|
public:
|
||||||
|
Serial_() { peek_buffer = -1; };
|
||||||
|
void begin(unsigned long);
|
||||||
|
void begin(unsigned long, uint8_t);
|
||||||
|
void end(void);
|
||||||
|
|
||||||
|
virtual int available(void);
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual int read(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
virtual size_t write(uint8_t);
|
||||||
|
virtual size_t write(const uint8_t*, size_t);
|
||||||
|
|
||||||
|
using Print::write; // pull in write(str) etc. from Print
|
||||||
|
|
||||||
|
operator bool();
|
||||||
|
};
|
||||||
|
extern Serial_ Serial; // NOTE: HardwareSerial.h defines the 1st port as 'Serial1' whenever USBCON defined
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Mouse
|
||||||
|
|
||||||
|
#define MOUSE_LEFT 1
|
||||||
|
#define MOUSE_RIGHT 2
|
||||||
|
#define MOUSE_MIDDLE 4
|
||||||
|
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
|
||||||
|
|
||||||
|
class Mouse_
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
uint8_t _buttons;
|
||||||
|
void buttons(uint8_t b);
|
||||||
|
public:
|
||||||
|
Mouse_(void);
|
||||||
|
void begin(void);
|
||||||
|
void end(void);
|
||||||
|
void click(uint8_t b = MOUSE_LEFT);
|
||||||
|
void move(signed char x, signed char y, signed char wheel = 0);
|
||||||
|
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
|
||||||
|
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
|
||||||
|
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
|
||||||
|
};
|
||||||
|
extern Mouse_ Mouse;
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Keyboard
|
||||||
|
|
||||||
|
#define KEY_LEFT_CTRL 0x80
|
||||||
|
#define KEY_LEFT_SHIFT 0x81
|
||||||
|
#define KEY_LEFT_ALT 0x82
|
||||||
|
#define KEY_LEFT_GUI 0x83
|
||||||
|
#define KEY_RIGHT_CTRL 0x84
|
||||||
|
#define KEY_RIGHT_SHIFT 0x85
|
||||||
|
#define KEY_RIGHT_ALT 0x86
|
||||||
|
#define KEY_RIGHT_GUI 0x87
|
||||||
|
|
||||||
|
#define KEY_UP_ARROW 0xDA
|
||||||
|
#define KEY_DOWN_ARROW 0xD9
|
||||||
|
#define KEY_LEFT_ARROW 0xD8
|
||||||
|
#define KEY_RIGHT_ARROW 0xD7
|
||||||
|
#define KEY_BACKSPACE 0xB2
|
||||||
|
#define KEY_TAB 0xB3
|
||||||
|
#define KEY_RETURN 0xB0
|
||||||
|
#define KEY_ESC 0xB1
|
||||||
|
#define KEY_INSERT 0xD1
|
||||||
|
#define KEY_DELETE 0xD4
|
||||||
|
#define KEY_PAGE_UP 0xD3
|
||||||
|
#define KEY_PAGE_DOWN 0xD6
|
||||||
|
#define KEY_HOME 0xD2
|
||||||
|
#define KEY_END 0xD5
|
||||||
|
#define KEY_CAPS_LOCK 0xC1
|
||||||
|
#define KEY_F1 0xC2
|
||||||
|
#define KEY_F2 0xC3
|
||||||
|
#define KEY_F3 0xC4
|
||||||
|
#define KEY_F4 0xC5
|
||||||
|
#define KEY_F5 0xC6
|
||||||
|
#define KEY_F6 0xC7
|
||||||
|
#define KEY_F7 0xC8
|
||||||
|
#define KEY_F8 0xC9
|
||||||
|
#define KEY_F9 0xCA
|
||||||
|
#define KEY_F10 0xCB
|
||||||
|
#define KEY_F11 0xCC
|
||||||
|
#define KEY_F12 0xCD
|
||||||
|
|
||||||
|
// Low level key report: up to 6 keys and shift, ctrl etc at once
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t modifiers;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t keys[6];
|
||||||
|
} KeyReport;
|
||||||
|
|
||||||
|
class Keyboard_ : public Print
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
KeyReport _keyReport;
|
||||||
|
void sendReport(KeyReport* keys);
|
||||||
|
public:
|
||||||
|
Keyboard_(void);
|
||||||
|
void begin(void);
|
||||||
|
void end(void);
|
||||||
|
virtual size_t write(uint8_t k);
|
||||||
|
virtual size_t press(uint8_t k);
|
||||||
|
virtual size_t release(uint8_t k);
|
||||||
|
virtual void releaseAll(void);
|
||||||
|
};
|
||||||
|
extern Keyboard_ Keyboard;
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// Low level API
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t bmRequestType;
|
||||||
|
uint8_t bRequest;
|
||||||
|
uint8_t wValueL;
|
||||||
|
uint8_t wValueH;
|
||||||
|
uint16_t wIndex;
|
||||||
|
uint16_t wLength;
|
||||||
|
} Setup;
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// HID 'Driver'
|
||||||
|
|
||||||
|
int HID_GetNumInterfaces(void);
|
||||||
|
int HID_GetInterfaceDataLength(void);
|
||||||
|
int HID_SendInterfaceData(void);
|
||||||
|
bool HID_SendDeviceDescriptor(void);
|
||||||
|
|
||||||
|
int HID_GetDescriptor(int i); // handles the 'GET DESCRIPTOR' control packet
|
||||||
|
bool HID_Setup(Setup& setup); // handles a 'SETUP' control packet
|
||||||
|
|
||||||
|
void HID_SendReport(uint8_t id, const void* data, int len);
|
||||||
|
|
||||||
|
void HID_Reset(void); // called whenever I get a bus reset
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
// CDC 'Driver'
|
||||||
|
|
||||||
|
bool CDC_SendIAD(void);
|
||||||
|
int CDC_GetNumInterfaces(void);
|
||||||
|
int CDC_GetInterfaceDataLength(void);
|
||||||
|
int CDC_SendInterfaceData(void);
|
||||||
|
bool CDC_SendDeviceDescriptor(void);
|
||||||
|
|
||||||
|
int CDC_GetDescriptor(int i); // handles the 'GET DESCRIPTOR' control packet
|
||||||
|
bool CDC_Setup(Setup& setup); // handles a 'SETUP' control packet
|
||||||
|
void CDC_FrameReceived(void); // call when frame is received and EP is configured
|
||||||
|
void CDC_SendACM(void); // call when you need to send a packet on the interrupt EP
|
||||||
|
|
||||||
|
void CDC_Reset(void); // called whenever I get a bus reset
|
||||||
|
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//================================================================================
|
||||||
|
|
||||||
|
#define TRANSFER_PGM 0x80
|
||||||
|
#define TRANSFER_RELEASE 0x40
|
||||||
|
#define TRANSFER_TOGGLE_ON 0x20 /* assign this to pre-set the 'toggle' bit on - only works when send queue is empty */
|
||||||
|
#define TRANSFER_TOGGLE_OFF 0x10 /* assign this to pre-set the 'toggle' bit off - only works when send queue is empty */
|
||||||
|
|
||||||
|
// NOTE: USB_SendControl returns # of bytes sent, or 0x8000 if a ZLP is sent
|
||||||
|
// it will return 0 on error, such as the inability to allocate a buffer
|
||||||
|
// control packets send 64 bytes at a time, so the total size is limited
|
||||||
|
// by the number of available buffers.
|
||||||
|
|
||||||
|
int USB_SendControl(uint8_t flags, const void* d, int len);
|
||||||
|
#ifdef PROGMEM
|
||||||
|
int USB_SendControlP(uint8_t flags, const void * PROGMEM d, int len);
|
||||||
|
// called internally if you use TRANSFER_PGM flag; you can also call this directly
|
||||||
|
#endif // PROGMEM
|
||||||
|
|
||||||
|
uint16_t USB_Available(uint8_t ep); // returns # of bytes in the buffer on an OUT or CONTROL endpoint
|
||||||
|
uint16_t USB_SendQLength(uint8_t ep); // returns # of buffers in the send queue for an IN or CONTROL endpoint
|
||||||
|
bool USB_IsSendQFull(uint8_t ep); // this returns TRUE if there are too many outgoing buffers already (IN, CONTROL)
|
||||||
|
bool USB_IsStalled(uint8_t ep); // this tells me I'm 'stalled' (BULK IN, INTERRUPT, CONTROL)
|
||||||
|
int USB_Send(uint8_t ep, const void* data, // send endpoint data. bSendNow marks it "to send"
|
||||||
|
int len, uint8_t bSendNow);
|
||||||
|
int USB_Recv(uint8_t ep, void* data, // 'receive' data from endpoint receive queue. returns < 0 on error, or # of bytes
|
||||||
|
int len);
|
||||||
|
int USB_Recv(uint8_t ep); // 'receive' one byte of data from endpoint receive queue
|
||||||
|
void USB_Flush(uint8_t ep); // 'sends' all pending data by marking the buffers "to send"
|
||||||
|
|
||||||
|
uint16_t GetFrameNumber(void); // a debug API to obtain the latest USB frame number
|
||||||
|
uint8_t USB_GetEPType(uint8_t nEP); // another debug API to return endpoint type by index
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* if defined(USBCON) */
|
||||||
|
|
3745
BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp
Normal file
3745
BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp
Normal file
File diff suppressed because it is too large
Load Diff
442
BootLoaders/Boards/orangerx/cores/xmega/USBCore.h
Normal file
442
BootLoaders/Boards/orangerx/cores/xmega/USBCore.h
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// _ _ ____ ____ ____ _ //
|
||||||
|
// | | | |/ ___| | __ ) / ___| ___ _ __ ___ | |__ //
|
||||||
|
// | | | |\___ \ | _ \ | | / _ \ | '__|/ _ \ | '_ \ //
|
||||||
|
// | |_| | ___) || |_) || |___| (_) || | | __/ _ | | | | //
|
||||||
|
// \___/ |____/ |____/ \____|\___/ |_| \___|(_)|_| |_| //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Copyright (c) 2010, Peter Barrett
|
||||||
|
/*
|
||||||
|
** Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
** any purpose with or without fee is hereby granted, provided that the
|
||||||
|
** above copyright notice and this permission notice appear in all copies.
|
||||||
|
**
|
||||||
|
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||||
|
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||||
|
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
** SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USBCORE_H__
|
||||||
|
#define __USBCORE_H__
|
||||||
|
|
||||||
|
// USB implementation MUST have USB_VID and USB_PID defined - can be done in 'boards.txt'
|
||||||
|
#if defined(USBCON) /* TODO add others here, things that require VID and PID for USB */
|
||||||
|
#ifdef USB_VID
|
||||||
|
#if USB_VID==null
|
||||||
|
#error cannot work with NULL value for VID
|
||||||
|
#endif // USB_VID==null
|
||||||
|
#else
|
||||||
|
#error must define USB_VID
|
||||||
|
#endif // USB_VID
|
||||||
|
|
||||||
|
#ifdef USB_PID
|
||||||
|
#if USB_PID==null
|
||||||
|
#error cannot work with NULL value for PID
|
||||||
|
#endif // USB_PID==null
|
||||||
|
#else
|
||||||
|
#error must define USB_PID
|
||||||
|
#endif // USB_PID
|
||||||
|
#endif // defined(USBCON)
|
||||||
|
|
||||||
|
|
||||||
|
#define FAST_USB /* necessary for 'FULL' speed operation - this is 12Mbit, not 480Mbit USB 2 'HIGH' speed - 'LOW' may not work properly */
|
||||||
|
|
||||||
|
#ifndef _PLATFORM_H_TYPES_DEFINED_ /* TEMPORARY FIX, SEE Platform.h */
|
||||||
|
#define _PLATFORM_H_TYPES_DEFINED_
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned long u32;
|
||||||
|
#endif // _PLATFORM_H_TYPES_DEFINED_
|
||||||
|
|
||||||
|
// Standard requests
|
||||||
|
#define GET_STATUS 0
|
||||||
|
#define CLEAR_FEATURE 1
|
||||||
|
#define SET_FEATURE 3
|
||||||
|
#define SET_ADDRESS 5
|
||||||
|
#define GET_DESCRIPTOR 6
|
||||||
|
#define SET_DESCRIPTOR 7
|
||||||
|
#define GET_CONFIGURATION 8
|
||||||
|
#define SET_CONFIGURATION 9
|
||||||
|
#define GET_INTERFACE 10
|
||||||
|
#define SET_INTERFACE 11
|
||||||
|
|
||||||
|
|
||||||
|
// bmRequestType
|
||||||
|
#define REQUEST_HOSTTODEVICE 0x00
|
||||||
|
#define REQUEST_DEVICETOHOST 0x80 /* device to host, i.e. 'in' - when not set, it's 'out' (host to device) */
|
||||||
|
#define REQUEST_DIRECTION 0x80
|
||||||
|
|
||||||
|
#define REQUEST_STANDARD 0x00
|
||||||
|
#define REQUEST_CLASS 0x20
|
||||||
|
#define REQUEST_VENDOR 0x40
|
||||||
|
#define REQUEST_TYPE 0x60
|
||||||
|
|
||||||
|
#define REQUEST_DEVICE 0x00
|
||||||
|
#define REQUEST_INTERFACE 0x01
|
||||||
|
#define REQUEST_ENDPOINT 0x02
|
||||||
|
#define REQUEST_OTHER 0x03
|
||||||
|
#define REQUEST_RECIPIENT 0x03
|
||||||
|
|
||||||
|
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
|
||||||
|
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
|
||||||
|
|
||||||
|
// Class requests
|
||||||
|
|
||||||
|
#define CDC_SET_LINE_CODING 0x20
|
||||||
|
#define CDC_GET_LINE_CODING 0x21
|
||||||
|
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||||
|
|
||||||
|
#define MSC_RESET 0xFF
|
||||||
|
#define MSC_GET_MAX_LUN 0xFE
|
||||||
|
|
||||||
|
#define HID_GET_REPORT 0x01
|
||||||
|
#define HID_GET_IDLE 0x02
|
||||||
|
#define HID_GET_PROTOCOL 0x03
|
||||||
|
#define HID_SET_REPORT 0x09
|
||||||
|
#define HID_SET_IDLE 0x0A
|
||||||
|
#define HID_SET_PROTOCOL 0x0B
|
||||||
|
|
||||||
|
// Descriptors
|
||||||
|
|
||||||
|
#define USB_DEVICE_DESC_SIZE 18
|
||||||
|
#define USB_CONFIGUARTION_DESC_SIZE 9
|
||||||
|
#define USB_INTERFACE_DESC_SIZE 9
|
||||||
|
#define USB_ENDPOINT_DESC_SIZE 7
|
||||||
|
|
||||||
|
|
||||||
|
#define USB_DEVICE_DESCRIPTOR_TYPE 1
|
||||||
|
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
|
||||||
|
#define USB_STRING_DESCRIPTOR_TYPE 3
|
||||||
|
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
|
||||||
|
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
|
||||||
|
#define USB_DEVICE_QUALIFIER_TYPE 6
|
||||||
|
#define USB_OTHER_SPEED_CONFIGURATION_TYPE 7
|
||||||
|
#define USB_INTERFACE_POWER_TYPE 8
|
||||||
|
#define USB_OTG_TYPE 9
|
||||||
|
#define USB_DEVICE_DEBUG_TYPE 10
|
||||||
|
#define USB_INTERFACE_ASSOCIATION_TYPE 11 /* see InterfaceAssociationDescriptor_ecn.pdf */
|
||||||
|
// NOTE: for USB_INTERFACE_ASSOCIATION_TYPE respond with IADDescriptor
|
||||||
|
|
||||||
|
#define USB_DEVICE_CLASS_ZERO 0x00
|
||||||
|
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
|
||||||
|
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
|
||||||
|
#define USB_DEVICE_CLASS_STORAGE 0x08
|
||||||
|
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
|
#define USB_CONFIG_POWERED_MASK 0x40
|
||||||
|
#define USB_CONFIG_BUS_POWERED 0x80
|
||||||
|
#define USB_CONFIG_SELF_POWERED 0xC0
|
||||||
|
#define USB_CONFIG_REMOTE_WAKEUP 0x20
|
||||||
|
|
||||||
|
// bMaxPower in Configuration Descriptor
|
||||||
|
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
|
||||||
|
|
||||||
|
// bEndpointAddress in Endpoint Descriptor
|
||||||
|
#define USB_ENDPOINT_DIRECTION_MASK 0x80
|
||||||
|
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
|
||||||
|
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
|
||||||
|
|
||||||
|
#define USB_ENDPOINT_TYPE_MASK 0x03
|
||||||
|
#define USB_ENDPOINT_TYPE_CONTROL 0x00
|
||||||
|
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
|
||||||
|
#define USB_ENDPOINT_TYPE_BULK 0x02
|
||||||
|
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
|
||||||
|
|
||||||
|
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
|
||||||
|
|
||||||
|
#define CDC_V1_10 0x0110
|
||||||
|
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
|
||||||
|
|
||||||
|
#define CDC_CALL_MANAGEMENT 0x01
|
||||||
|
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
|
||||||
|
#define CDC_HEADER 0x00
|
||||||
|
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
|
||||||
|
#define CDC_UNION 0x06
|
||||||
|
#define CDC_CS_INTERFACE 0x24
|
||||||
|
#define CDC_CS_ENDPOINT 0x25
|
||||||
|
#define CDC_DATA_INTERFACE_CLASS 0x0A
|
||||||
|
|
||||||
|
#define MSC_SUBCLASS_SCSI 0x06
|
||||||
|
#define MSC_PROTOCOL_BULK_ONLY 0x50
|
||||||
|
|
||||||
|
#define HID_HID_DESCRIPTOR_TYPE 0x21
|
||||||
|
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
|
||||||
|
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
|
||||||
|
|
||||||
|
// CONTROL LINE STATE and SERIAL STATE - BIT VALUES (16-bits, LE)
|
||||||
|
// USED BY 'SET CONTROL LINE STATE' and 'SERIAL STATE' FOR CAM INTERRUPT 'IN'
|
||||||
|
#define CONTROL_LINE_STATE_DTR 0x01 /* data terminal ready [ok to send on IN] */
|
||||||
|
#define CONTROL_LINE_STATE_RTS 0x02 /* ready to send [has data ready for OUT] */
|
||||||
|
#define SERIAL_STATE_RX_CARRIER_DCD 0x01 /* receive carrier detect - on to allow receive */
|
||||||
|
#define SERIAL_STATE_TX_CARRIER_DSR 0x02 /* data set ready - inform host I have data */
|
||||||
|
#define SERIAL_STATE_BREAK_DETECT 0x04 /* 'break' detect */
|
||||||
|
#define SERIAL_STATE_RING_DETECT 0x08 /* 'ring' detect */
|
||||||
|
#define SERIAL_STATE_FRAMING_ERROR 0x10 /* framing error */
|
||||||
|
#define SERIAL_STATE_PARITY_ERROR 0x20 /* parity error */
|
||||||
|
#define SERIAL_STATE_OVERRUN 0x40 /* overrun input (data lost) */
|
||||||
|
|
||||||
|
|
||||||
|
// A1U series needs 16-byte alignment for endpoint structure
|
||||||
|
#if defined(__AVR_ATxmega64A1U__) || defined(__AVR_ATxmega128A1U__)
|
||||||
|
#define A1U_SERIES
|
||||||
|
#endif // A1U
|
||||||
|
|
||||||
|
// Device
|
||||||
|
typedef struct _device_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 18
|
||||||
|
u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
|
||||||
|
u16 usbVersion; // 0x200
|
||||||
|
u8 deviceClass;
|
||||||
|
u8 deviceSubClass;
|
||||||
|
u8 deviceProtocol;
|
||||||
|
u8 packetSize0; // Packet 0
|
||||||
|
u16 idVendor;
|
||||||
|
u16 idProduct;
|
||||||
|
u16 deviceVersion; // 0x100
|
||||||
|
u8 iManufacturer;
|
||||||
|
u8 iProduct;
|
||||||
|
u8 iSerialNumber;
|
||||||
|
u8 bNumConfigurations;
|
||||||
|
} DeviceDescriptor;
|
||||||
|
|
||||||
|
// Config
|
||||||
|
typedef struct _config_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 9
|
||||||
|
u8 dtype; // 2
|
||||||
|
u16 clen; // total length
|
||||||
|
u8 numInterfaces;
|
||||||
|
u8 config;
|
||||||
|
u8 iconfig;
|
||||||
|
u8 attributes;
|
||||||
|
u8 maxPower;
|
||||||
|
} ConfigDescriptor;
|
||||||
|
|
||||||
|
// String
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
typedef struct _interface_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 9
|
||||||
|
u8 dtype; // 4
|
||||||
|
u8 number;
|
||||||
|
u8 alternate;
|
||||||
|
u8 numEndpoints;
|
||||||
|
u8 interfaceClass;
|
||||||
|
u8 interfaceSubClass;
|
||||||
|
u8 protocol;
|
||||||
|
u8 iInterface;
|
||||||
|
} InterfaceDescriptor;
|
||||||
|
|
||||||
|
// Endpoint
|
||||||
|
typedef struct _endpoint_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 7
|
||||||
|
u8 dtype; // 5
|
||||||
|
u8 addr;
|
||||||
|
u8 attr;
|
||||||
|
u16 packetSize;
|
||||||
|
u8 interval;
|
||||||
|
} EndpointDescriptor;
|
||||||
|
|
||||||
|
// Interface Association Descriptor
|
||||||
|
// Used to bind 2 interfaces together in CDC compostite device
|
||||||
|
typedef struct _iad_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 8
|
||||||
|
u8 dtype; // 11
|
||||||
|
u8 firstInterface;
|
||||||
|
u8 interfaceCount;
|
||||||
|
u8 functionClass;
|
||||||
|
u8 funtionSubClass;
|
||||||
|
u8 functionProtocol;
|
||||||
|
u8 iInterface;
|
||||||
|
} IADDescriptor;
|
||||||
|
|
||||||
|
// CDC CS interface descriptor
|
||||||
|
typedef struct _cdccs_interface_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 5
|
||||||
|
u8 dtype; // 0x24
|
||||||
|
u8 subtype;
|
||||||
|
u8 d0;
|
||||||
|
u8 d1;
|
||||||
|
} CDCCSInterfaceDescriptor;
|
||||||
|
|
||||||
|
typedef struct _cdccs_interface_descriptor4_
|
||||||
|
{
|
||||||
|
u8 len; // 4
|
||||||
|
u8 dtype; // 0x24
|
||||||
|
u8 subtype;
|
||||||
|
u8 d0;
|
||||||
|
} CDCCSInterfaceDescriptor4;
|
||||||
|
|
||||||
|
typedef struct _cm_functional_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 5
|
||||||
|
u8 dtype; // 0x24
|
||||||
|
u8 subtype; // 1
|
||||||
|
u8 bmCapabilities;
|
||||||
|
u8 bDataInterface;
|
||||||
|
} CMFunctionalDescriptor;
|
||||||
|
|
||||||
|
typedef struct _acm_functional_descriptor_
|
||||||
|
{
|
||||||
|
u8 len;
|
||||||
|
u8 dtype; // 0x24
|
||||||
|
u8 subtype; // 1
|
||||||
|
u8 bmCapabilities;
|
||||||
|
} ACMFunctionalDescriptor;
|
||||||
|
|
||||||
|
typedef struct _cdc_descriptor_
|
||||||
|
{
|
||||||
|
// // IAD
|
||||||
|
// IADDescriptor iad; // for complex endpoints (apparently not critical)
|
||||||
|
|
||||||
|
// Control
|
||||||
|
InterfaceDescriptor cif; //
|
||||||
|
CDCCSInterfaceDescriptor header;
|
||||||
|
// CMFunctionalDescriptor callManagement; // Call Management
|
||||||
|
ACMFunctionalDescriptor controlManagement; // ACM
|
||||||
|
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
|
||||||
|
EndpointDescriptor cifin;
|
||||||
|
|
||||||
|
// Data
|
||||||
|
InterfaceDescriptor dif;
|
||||||
|
EndpointDescriptor in;
|
||||||
|
EndpointDescriptor out;
|
||||||
|
} CDCDescriptor;
|
||||||
|
|
||||||
|
typedef struct _msc_descriptor_
|
||||||
|
{
|
||||||
|
InterfaceDescriptor msc;
|
||||||
|
EndpointDescriptor in;
|
||||||
|
EndpointDescriptor out;
|
||||||
|
} MSCDescriptor;
|
||||||
|
|
||||||
|
typedef struct _hid_desc_descriptor_
|
||||||
|
{
|
||||||
|
u8 len; // 9
|
||||||
|
u8 dtype; // 0x21
|
||||||
|
u8 addr;
|
||||||
|
u8 versionL; // 0x101
|
||||||
|
u8 versionH; // 0x101
|
||||||
|
u8 country;
|
||||||
|
u8 desctype; // 0x22 report
|
||||||
|
u8 descLenL;
|
||||||
|
u8 descLenH;
|
||||||
|
} HIDDescDescriptor;
|
||||||
|
|
||||||
|
typedef struct _hid_descriptor_
|
||||||
|
{
|
||||||
|
InterfaceDescriptor hid;
|
||||||
|
HIDDescDescriptor desc;
|
||||||
|
EndpointDescriptor in;
|
||||||
|
} HIDDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
// XMEGA STRUCTURES
|
||||||
|
|
||||||
|
#define MAXEP 5 /*15*/ /* 4 bit value, 0-15 - see 20.14.1 'CTRLA register' in AU manual */
|
||||||
|
// I assigned this to '5' because there are only 5 endpoints being used by THIS code.
|
||||||
|
// The 'mega' code could only have a total of 6 and 0 was always the 'control' endpoint
|
||||||
|
// and setting a 'smaller-than-maximum' value for XMEGA burns up less RAM.
|
||||||
|
// If this poses a problem I _could_ malloc the structures, but to be effective, it would
|
||||||
|
// have to require a reboot to change it, or you'd get major RAM fragmentation
|
||||||
|
//
|
||||||
|
// TODO: put MAXEP into pins_arduino.h and override if too small (or not defined already)
|
||||||
|
|
||||||
|
typedef union _xmega_fifo_entry_
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t h, l;
|
||||||
|
};
|
||||||
|
uint16_t heW; // high endian word
|
||||||
|
} XMegaFIFOEntry;
|
||||||
|
|
||||||
|
typedef struct _xmega_fifo_
|
||||||
|
{
|
||||||
|
XMegaFIFOEntry in;
|
||||||
|
XMegaFIFOEntry out;
|
||||||
|
} XMegaFIFO;
|
||||||
|
|
||||||
|
// see AU manual, pg 231 section 20.4
|
||||||
|
typedef struct _xmega_endpoint_descriptor_
|
||||||
|
{
|
||||||
|
volatile uint8_t status;
|
||||||
|
volatile uint8_t ctrl;
|
||||||
|
volatile uint16_t /*HLByteWord*/ cnt; // so, cnt.w is the 16-bit value, cnt.l and cnt.h the 8-bit low/high
|
||||||
|
// it is the 'data count' value. it may be zero.
|
||||||
|
// only bits 1:0 of cnt.h are valid. cnt.w should be 'and'd with 0x3ff
|
||||||
|
// the high bit of cnt.w and cnt.h is the 'AZLP' (auto zero length packet) bit
|
||||||
|
// see AU manual section 20.15.4
|
||||||
|
volatile uint16_t /*HLByteWord*/ dataptr; // pointer to data buffer. max packet length assigned to CTRL [1:0] or [2:0]
|
||||||
|
// see table 20-5 in AU manual for max packet length. may need 2 buffers "that long"
|
||||||
|
volatile uint16_t /*HLByteWord*/ auxdata; // used for multi-packet transfers
|
||||||
|
} XMegaEndpointDescriptor; // NOTE: 2 per channel (one 'out', one 'in') pointed by EPPTR
|
||||||
|
|
||||||
|
typedef struct _xmega_endpoint_channel_
|
||||||
|
{
|
||||||
|
XMegaEndpointDescriptor out;
|
||||||
|
XMegaEndpointDescriptor in;
|
||||||
|
} XMegaEndpointChannel
|
||||||
|
#ifdef A1U_SERIES
|
||||||
|
__attribute (( aligned (16) ));
|
||||||
|
#else // not an A1U series
|
||||||
|
__attribute__ (( aligned (2) /*, packed*/));
|
||||||
|
#endif // A1U or not
|
||||||
|
|
||||||
|
// also section 20.4 in AU manual
|
||||||
|
typedef struct _XMegaEPDataStruct_
|
||||||
|
{
|
||||||
|
#ifdef A1U_SERIES
|
||||||
|
#if ((MAXEP+1)%4) != 0 // A1U needs 16-byte boundary, not merely word-aligned
|
||||||
|
uint8_t padding[sizeof(XMegaFIFO) * (4 - ((MAXEP+1)%4))]; // this should 16-byte align 'endpoint' as required
|
||||||
|
#endif // needs padding
|
||||||
|
#endif // XMEGA A1U series
|
||||||
|
XMegaFIFO fifo[MAXEP + 1];
|
||||||
|
XMegaEndpointChannel endpoint[MAXEP + 1]; // point EPPTR to THIS (must be word boundary)
|
||||||
|
volatile uint16_t framenum; // 1 word frame number
|
||||||
|
} XMegaEPDataStruct /*__attribute__ ((packed))*/; // note: point EPPTR to &endpoint[0], word alignment needed
|
||||||
|
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
uint16_t endpoint_data_pointer(void);
|
||||||
|
#define EP_DATA_STRUCT() ((XMegaEPDataStruct *)(endpoint_data_pointer() - (uint16_t)&(((XMegaEPDataStruct *)0)->endpoint[0])))
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
|
||||||
|
// this is the USB Device Descriptor
|
||||||
|
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
|
||||||
|
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
|
||||||
|
|
||||||
|
#define D_CONFIG(_totalLength,_interfaces) \
|
||||||
|
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) }
|
||||||
|
|
||||||
|
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
|
||||||
|
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
|
||||||
|
|
||||||
|
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
|
||||||
|
{ 7, 5, _addr,_attr,_packetSize, _interval }
|
||||||
|
|
||||||
|
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
|
||||||
|
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
|
||||||
|
|
||||||
|
#define D_HIDREPORT(_descriptorLength) \
|
||||||
|
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
|
||||||
|
|
||||||
|
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
|
||||||
|
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
83
BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h
Normal file
83
BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// _ _ ____ ____ ____ _ //
|
||||||
|
// | | | |/ ___| | __ ) | _ \ ___ ___ ___ | |__ //
|
||||||
|
// | | | |\___ \ | _ \ | | | | / _ \/ __| / __| | '_ \ //
|
||||||
|
// | |_| | ___) || |_) || |_| || __/\__ \| (__ _ | | | | //
|
||||||
|
// \___/ |____/ |____/ |____/ \___||___/ \___|(_)|_| |_| //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* Copyright (c) 2011, Peter Barrett
|
||||||
|
**
|
||||||
|
** Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
** any purpose with or without fee is hereby granted, provided that the
|
||||||
|
** above copyright notice and this permission notice appear in all copies.
|
||||||
|
**
|
||||||
|
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||||
|
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||||
|
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
** SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE: don't define these here; define them in pins_arduino.h
|
||||||
|
//#define CDC_ENABLED
|
||||||
|
//#define HID_ENABLED
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CDC_ENABLED
|
||||||
|
#define CDC_INTERFACE_COUNT 2
|
||||||
|
#define CDC_ENDPOINT_COUNT 3
|
||||||
|
#else
|
||||||
|
#define CDC_INTERFACE_COUNT 0
|
||||||
|
#define CDC_ENPOINT_COUNT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HID_ENABLED
|
||||||
|
#define HID_INTERFACE_COUNT 1
|
||||||
|
#define HID_ENPOINT_COUNT 1
|
||||||
|
#else
|
||||||
|
#define HID_INTERFACE_COUNT 0
|
||||||
|
#define HID_ENPOINT_COUNT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CDC_ACM_INTERFACE 0 // CDC ACM interface
|
||||||
|
#define CDC_DATA_INTERFACE 1 // CDC Data interface
|
||||||
|
#define CDC_FIRST_ENDPOINT 1
|
||||||
|
#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First
|
||||||
|
#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1)
|
||||||
|
#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2)
|
||||||
|
|
||||||
|
#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface
|
||||||
|
#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
|
||||||
|
#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT)
|
||||||
|
|
||||||
|
#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT)
|
||||||
|
|
||||||
|
#ifdef CDC_ENABLED
|
||||||
|
#define CDC_RX CDC_ENDPOINT_OUT
|
||||||
|
#define CDC_TX CDC_ENDPOINT_IN
|
||||||
|
#define CDC_ACM CDC_ENDPOINT_ACM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HID_ENABLED
|
||||||
|
#define HID_TX HID_ENDPOINT_INT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// string indexes/indices for USB_STRING_DESCRIPTOR_TYPE
|
||||||
|
#define USB_STRING_INDEX_LANGUAGE 0 /* not actually a STRING though */
|
||||||
|
#define USB_STRING_INDEX_MANUFACTURER 1
|
||||||
|
#define USB_STRING_INDEX_PRODUCT 2
|
||||||
|
#define USB_STRING_INDEX_DESCRIPTION 3
|
||||||
|
#define USB_STRING_INDEX_VERSION 4
|
||||||
|
#define USB_STRING_INDEX_URL 5
|
||||||
|
#define USB_STRING_INDEX_SERIAL 6
|
||||||
|
#define USB_STRING_INDEX_CONFIG 7
|
||||||
|
|
||||||
|
|
||||||
|
|
88
BootLoaders/Boards/orangerx/cores/xmega/Udp.h
Normal file
88
BootLoaders/Boards/orangerx/cores/xmega/Udp.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Udp.cpp: Library to send/receive UDP packets.
|
||||||
|
*
|
||||||
|
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||||
|
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||||
|
* might not happen often in practice, but in larger network topologies, a UDP
|
||||||
|
* packet can be received out of sequence.
|
||||||
|
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||||
|
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||||
|
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||||
|
*
|
||||||
|
* MIT License:
|
||||||
|
* Copyright (c) 2008 Bjoern Hartmann
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* bjoern@cs.stanford.edu 12/30/2008
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef udp_h
|
||||||
|
#define udp_h
|
||||||
|
|
||||||
|
#include <Stream.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
|
class UDP : public Stream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||||
|
virtual void stop() =0; // Finish with the UDP socket
|
||||||
|
|
||||||
|
// Sending UDP packets
|
||||||
|
|
||||||
|
// Start building up a packet to send to the remote host specific in ip and port
|
||||||
|
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||||
|
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
|
||||||
|
// Start building up a packet to send to the remote host specific in host and port
|
||||||
|
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||||
|
virtual int beginPacket(const char *host, uint16_t port) =0;
|
||||||
|
// Finish off this packet and send it
|
||||||
|
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||||
|
virtual int endPacket() =0;
|
||||||
|
// Write a single byte into the packet
|
||||||
|
virtual size_t write(uint8_t) =0;
|
||||||
|
// Write size bytes from buffer into the packet
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size) =0;
|
||||||
|
|
||||||
|
// Start processing the next available incoming packet
|
||||||
|
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||||
|
virtual int parsePacket() =0;
|
||||||
|
// Number of bytes remaining in the current packet
|
||||||
|
virtual int available() =0;
|
||||||
|
// Read a single byte from the current packet
|
||||||
|
virtual int read() =0;
|
||||||
|
// Read up to len bytes from the current packet and place them into buffer
|
||||||
|
// Returns the number of bytes read, or 0 if none are available
|
||||||
|
virtual int read(unsigned char* buffer, size_t len) =0;
|
||||||
|
// Read up to len characters from the current packet and place them into buffer
|
||||||
|
// Returns the number of characters read, or 0 if none are available
|
||||||
|
virtual int read(char* buffer, size_t len) =0;
|
||||||
|
// Return the next byte from the current packet without moving on to the next byte
|
||||||
|
virtual int peek() =0;
|
||||||
|
virtual void flush() =0; // Finish reading the current packet
|
||||||
|
|
||||||
|
// Return the IP address of the host who sent the current incoming packet
|
||||||
|
virtual IPAddress remoteIP() =0;
|
||||||
|
// Return the port of the host who sent the current incoming packet
|
||||||
|
virtual uint16_t remotePort() =0;
|
||||||
|
protected:
|
||||||
|
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
168
BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h
Normal file
168
BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||||
|
Copyright (c) 2010 Hernando Barragan. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Character_h
|
||||||
|
#define Character_h
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
// WCharacter.h prototypes
|
||||||
|
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isControl(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||||
|
inline int toAscii(int c) __attribute__((always_inline));
|
||||||
|
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||||
|
inline int toUpperCase(int c)__attribute__((always_inline));
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an alphanumeric character.
|
||||||
|
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||||
|
inline boolean isAlphaNumeric(int c)
|
||||||
|
{
|
||||||
|
return ( isalnum(c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an alphabetic character.
|
||||||
|
// It is equivalent to (isupper(c) || islower(c)).
|
||||||
|
inline boolean isAlpha(int c)
|
||||||
|
{
|
||||||
|
return ( isalpha(c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks whether c is a 7-bit unsigned char value
|
||||||
|
// that fits into the ASCII character set.
|
||||||
|
inline boolean isAscii(int c)
|
||||||
|
{
|
||||||
|
return ( isascii (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a blank character, that is, a space or a tab.
|
||||||
|
inline boolean isWhitespace(int c)
|
||||||
|
{
|
||||||
|
return ( isblank (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a control character.
|
||||||
|
inline boolean isControl(int c)
|
||||||
|
{
|
||||||
|
return ( iscntrl (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a digit (0 through 9).
|
||||||
|
inline boolean isDigit(int c)
|
||||||
|
{
|
||||||
|
return ( isdigit (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character except space.
|
||||||
|
inline boolean isGraph(int c)
|
||||||
|
{
|
||||||
|
return ( isgraph (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a lower-case character.
|
||||||
|
inline boolean isLowerCase(int c)
|
||||||
|
{
|
||||||
|
return (islower (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character including space.
|
||||||
|
inline boolean isPrintable(int c)
|
||||||
|
{
|
||||||
|
return ( isprint (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character which is not a space
|
||||||
|
// or an alphanumeric character.
|
||||||
|
inline boolean isPunct(int c)
|
||||||
|
{
|
||||||
|
return ( ispunct (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for white-space characters. For the avr-libc library,
|
||||||
|
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||||
|
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||||
|
inline boolean isSpace(int c)
|
||||||
|
{
|
||||||
|
return ( isspace (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an uppercase letter.
|
||||||
|
inline boolean isUpperCase(int c)
|
||||||
|
{
|
||||||
|
return ( isupper (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||||
|
// 8 9 a b c d e f A B C D E F.
|
||||||
|
inline boolean isHexadecimalDigit(int c)
|
||||||
|
{
|
||||||
|
return ( isxdigit (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts c to a 7-bit unsigned char value that fits into the
|
||||||
|
// ASCII character set, by clearing the high-order bits.
|
||||||
|
inline int toAscii(int c)
|
||||||
|
{
|
||||||
|
return toascii (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Warning:
|
||||||
|
// Many people will be unhappy if you use this function.
|
||||||
|
// This function will convert accented letters into random
|
||||||
|
// characters.
|
||||||
|
|
||||||
|
// Converts the letter c to lower case, if possible.
|
||||||
|
inline int toLowerCase(int c)
|
||||||
|
{
|
||||||
|
return tolower (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts the letter c to upper case, if possible.
|
||||||
|
inline int toUpperCase(int c)
|
||||||
|
{
|
||||||
|
return toupper (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
808
BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c
Normal file
808
BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c
Normal file
@ -0,0 +1,808 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Wiring project - http://wiring.uniandes.edu.co
|
||||||
|
|
||||||
|
Copyright (c) 2004-05 Hernando Barragan
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Modified 24 November 2006 by David A. Mellis
|
||||||
|
Modified 1 August 2010 by Mark Sproul
|
||||||
|
|
||||||
|
Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
|
||||||
|
In some cases, the xmega updates make assumptions about the pin assignments.
|
||||||
|
See 'pins_arduino.h' for more detail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
// interrupts on the xmega are handled differently than the mega
|
||||||
|
// there are 2 interrupt vectors for each port. Typical xmega
|
||||||
|
// will use ports A, B, C, D, E, and R. The vectors for those
|
||||||
|
// are as follows:
|
||||||
|
//
|
||||||
|
// PORTn_INT0_vect
|
||||||
|
// - and -
|
||||||
|
// PORTn_INT1_vect
|
||||||
|
//
|
||||||
|
// where 'n' is A, B, C, D, E, or R
|
||||||
|
//
|
||||||
|
// Additional vectors are:
|
||||||
|
//
|
||||||
|
// OSC_XOSCF_vect (external oscillator failure, NMI)
|
||||||
|
//
|
||||||
|
// RTC_OVF_vect (real-time clock overflow)
|
||||||
|
// RTC_COMP_vect (real-time clock compare)
|
||||||
|
//
|
||||||
|
// TWIC_TWIS_vect (2-wire slave on port C)
|
||||||
|
// TWIC_TWIM_vect (2-wire master on port C)
|
||||||
|
// TWIE_TWIS_vect (2-wire slave on port E)
|
||||||
|
// TWIE_TWIM_vect (2-wire master on port E)
|
||||||
|
//
|
||||||
|
// timers - 'n' is C or D
|
||||||
|
// TCn0_OVF_vect (n timer 0 overflow)
|
||||||
|
// TCn1_OVF_vect (n timer 1 overflow)
|
||||||
|
// TCn2_LUNF_vect (n timer 2 low byte underflow)
|
||||||
|
// TCn2_HUNF_vect (n timer 2 high byte underflow)
|
||||||
|
// TCE0_OVF_vect (E timer 0 overflow)
|
||||||
|
// TCn0_ERR_vect (n timer 0 error)
|
||||||
|
// TCn1_ERR_vect (n timer 1 error)
|
||||||
|
// TCE0_ERR_vect (E timer 0 error)
|
||||||
|
// TCn0_CCA_vect (n timer 0 compare or capture A)
|
||||||
|
// TCn1_CCA_vect (n timer 1 compare or capture A)
|
||||||
|
// TCn2_LCMPA_vect (n timer 2 low-byte compare or capture A)
|
||||||
|
// TCE0_CCA_vect (E timer 0 compare or capture A)
|
||||||
|
// TCn0_CCB_vect (n timer 0 compare or capture B)
|
||||||
|
// TCn1_CCB_vect (n timer 1 compare or capture B)
|
||||||
|
// TCn2_LCMPB_vect (n timer 2 low-byte compare or capture B)
|
||||||
|
// TCE0_CCB_vect (E timer 0 compare or capture B)
|
||||||
|
// TCn0_CCC_vect (n timer 0 compare or capture C)
|
||||||
|
// TCn2_LCMPC_vect (n timer 2 low-byte compare or capture C)
|
||||||
|
// TCE0_CCC_vect (E timer 0 compare or capture C)
|
||||||
|
// TCn0_CCD_vect (n timer 0 compare or capture D)
|
||||||
|
// TCn2_LCMPD_vect (n timer 2 low-byte compare or capture D)
|
||||||
|
// TCE0_CCD_vect (E timer 0 compare or capture D)
|
||||||
|
//
|
||||||
|
// SPIn_INT_vect (SPI C or D)
|
||||||
|
//
|
||||||
|
// USARTn0_RXC_vect (USART 'n' [C or D] receive complete)
|
||||||
|
// USARTn0_DRE_vect (USART 'n' [C or D] data reg empty)
|
||||||
|
// USARTn0_TXC_vect (USART 'n' [C or D] transmit complete)
|
||||||
|
//
|
||||||
|
// NOTE: a 'USARTE' interrupt vector also exists, but isn't
|
||||||
|
// implemented on the D4 series
|
||||||
|
//
|
||||||
|
// ASYNC interrupts are only possible on pin 2 for each of the 5
|
||||||
|
// ports ('R' only has 2 pins, 0 and 1, so no async interrupt).
|
||||||
|
// Sleep modes typically need ASYNC interrupts to wake up.
|
||||||
|
|
||||||
|
// The interrupt will be handled for a particular port, and not for
|
||||||
|
// a particular interrupt. The 'attachInterrupt' function will default
|
||||||
|
// to pin 2 (asynchronous interrupt) unless otherwise specified in the
|
||||||
|
// 'mode' parameter.
|
||||||
|
|
||||||
|
// BOOTLOADER NOTES
|
||||||
|
//
|
||||||
|
// Bit 6 of the CTRL reg must be assigned to '0'. Bit 7 can be assigned
|
||||||
|
// to '1' to enable 'round robin' scheduling using the priority bits.
|
||||||
|
// Bits 0-2 (HILVLEN, MEDLVLEN, LOLVLEN) should also be assigned to '1'
|
||||||
|
// to allow all 3 interrupt levels to execute. ('D' manual 10.8.3 pg 102)
|
||||||
|
// The CTRL reg can be assigned to b10000111 to accomplish this. Bit 6
|
||||||
|
// needs to use the "configuration change protection" method to change it
|
||||||
|
// and may need to be assigned separately.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// interrupt mode - predefined values are LOW, CHANGE, RISING, FALLING, HIGH
|
||||||
|
// additional bits are 'or'd with mode
|
||||||
|
|
||||||
|
static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
|
||||||
|
static volatile uint8_t intPins[EXTERNAL_NUM_INTERRUPTS]; // added - store pins for this interrupt
|
||||||
|
// volatile static voidFuncPtr twiIntFunc;
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: I _HATE_ K&R style so I'll make it Allman style as I go along...
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
|
||||||
|
{
|
||||||
|
uint8_t iPinBits, iPriBits, iModeBits, iInv, iNum, iMask;
|
||||||
|
uint8_t oldSREG;
|
||||||
|
uint8_t intInfo;
|
||||||
|
PORT_t *port;
|
||||||
|
|
||||||
|
|
||||||
|
// for compatibility with newer IDE, 'interruptNum' can be encoded with pin information.
|
||||||
|
// if it is, then the pin info will be derived from pin info in 'mode' and 'interruptNum'
|
||||||
|
// pin info will be incorporated into it.
|
||||||
|
|
||||||
|
intInfo = ((interruptNum & 0xe0) >> 5); // is an int pin encoded here by digitalPinToInterrupt ?
|
||||||
|
interruptNum &= 0x1f; // so the rest of the code will work correctly
|
||||||
|
|
||||||
|
if(interruptNum >= EXTERNAL_NUM_INTERRUPTS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iPinBits = (uint8_t)((mode & INT_MODE_PIN_MASK) >> 8);
|
||||||
|
|
||||||
|
if(intInfo)
|
||||||
|
{
|
||||||
|
intInfo = ((intInfo + 2) & 7); // convert to actual pin number
|
||||||
|
|
||||||
|
iPinBits |= _BV(intInfo); // set respective bit in 'iPinBits'
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!iPinBits)
|
||||||
|
{
|
||||||
|
if(interruptNum == PORTR_INT0
|
||||||
|
#ifdef PORTR_INT1
|
||||||
|
|| interruptNum == PORTR_INT1
|
||||||
|
#endif // PORTR_INT1
|
||||||
|
) // not valid for these
|
||||||
|
{
|
||||||
|
return; // do nothing (for now)
|
||||||
|
}
|
||||||
|
|
||||||
|
iPinBits = _BV(2); // set bit for pin 2 if none specified [i.e. 'default']
|
||||||
|
}
|
||||||
|
|
||||||
|
iPriBits = (mode & INT_MODE_PRI_MASK)
|
||||||
|
>> INT_MODE_PRI_SHIFT;
|
||||||
|
|
||||||
|
if(!iPriBits) // not assigned
|
||||||
|
{
|
||||||
|
iPriBits = 3; // for now, just use the highest priority
|
||||||
|
}
|
||||||
|
|
||||||
|
mode &= INT_MODE_MODE_MASK;
|
||||||
|
iInv = 0;
|
||||||
|
|
||||||
|
if(mode == LOW) // normally will be this, for backward hardware compatibility
|
||||||
|
{
|
||||||
|
iModeBits = PORT_ISC_LEVEL_gc; // b011, high level continuously generates events
|
||||||
|
}
|
||||||
|
else if(mode == HIGH) // these constants correspond to the mega's bit mask on ISC00,ISC10
|
||||||
|
{
|
||||||
|
iModeBits = PORT_ISC_LEVEL_gc; // b011, high level continuously generates events
|
||||||
|
iInv = 1; // invert input (so 'high level' becomes 'low level')
|
||||||
|
|
||||||
|
// NOTE: this was verified by experimentation. The documentation is misleading, suggesting
|
||||||
|
// that a LEVEL interrupt triggered on HIGH, not on LOW. But it triggers on LOW. So
|
||||||
|
// if you want HIGH, you must invert it. Not the other way around. Yeah.
|
||||||
|
}
|
||||||
|
else if(mode == CHANGE)
|
||||||
|
{
|
||||||
|
iModeBits = PORT_ISC_BOTHEDGES_gc; // BOTHEDGES - see table 11-6
|
||||||
|
}
|
||||||
|
else if(mode == RISING)
|
||||||
|
{
|
||||||
|
iModeBits = PORT_ISC_RISING_gc; // b001, RISING
|
||||||
|
}
|
||||||
|
else if(mode == FALLING)
|
||||||
|
{
|
||||||
|
iModeBits = PORT_ISC_FALLING_gc; // b010, FALLING
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iModeBits = PORT_ISC_BOTHEDGES_gc; // BOTH (the default - note INTPUT_DISABLED (sic) won't buffer the input, so it's useless except for analog channels)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(iInv)
|
||||||
|
{
|
||||||
|
iModeBits |= _BV(PORT_INVEN_bp); // set the 'inverted' bit
|
||||||
|
}
|
||||||
|
|
||||||
|
oldSREG = SREG; // store the interrupt flag basically
|
||||||
|
|
||||||
|
cli(); // disable interrupts for a bit
|
||||||
|
|
||||||
|
intFunc[interruptNum] = userFunc;
|
||||||
|
intPins[interruptNum] = iPinBits; // save what pins I used
|
||||||
|
|
||||||
|
// Enable the interrupt (smaller code to use if/else and pointer)
|
||||||
|
|
||||||
|
iNum = 0;
|
||||||
|
if(interruptNum == PORTA_INT0
|
||||||
|
#ifdef PORTA_INT1
|
||||||
|
|| interruptNum == PORTA_INT1
|
||||||
|
#endif // PORTA_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTA;
|
||||||
|
#ifdef PORTA_INT1
|
||||||
|
if(interruptNum == PORTA_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTA_INT1
|
||||||
|
}
|
||||||
|
#if NUM_ANALOG_PINS > 8 /* which means we have PORT B */
|
||||||
|
else if(interruptNum == PORTB_INT0
|
||||||
|
#ifdef PORTB_INT1
|
||||||
|
|| interruptNum == PORTB_INT1
|
||||||
|
#endif // PORTB_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTB;
|
||||||
|
#ifdef PORTB_INT1
|
||||||
|
if(interruptNum == PORTB_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTB_INT1
|
||||||
|
}
|
||||||
|
#endif // NUM_ANALOG_PINS > 8
|
||||||
|
else if(interruptNum == PORTC_INT0
|
||||||
|
#ifdef PORTC_INT1
|
||||||
|
|| interruptNum == PORTC_INT1
|
||||||
|
#endif // PORTC_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTC;
|
||||||
|
#ifdef PORTC_INT1
|
||||||
|
if(interruptNum == PORTC_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTC_INT1
|
||||||
|
}
|
||||||
|
else if(interruptNum == PORTD_INT0
|
||||||
|
#ifdef PORTD_INT1
|
||||||
|
|| interruptNum == PORTD_INT1
|
||||||
|
#endif // PORTD_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTD;
|
||||||
|
#ifdef PORTD_INT1
|
||||||
|
if(interruptNum == PORTD_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTC_INT1
|
||||||
|
}
|
||||||
|
#if NUM_DIGITAL_PINS > 18 /* which means we have PORT E */
|
||||||
|
else if(interruptNum == PORTE_INT0
|
||||||
|
#ifdef PORTE_INT1
|
||||||
|
|| interruptNum == PORTE_INT1
|
||||||
|
#endif // PORTE_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTE;
|
||||||
|
#ifdef PORTE_INT1
|
||||||
|
if(interruptNum == PORTE_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTE_INT1
|
||||||
|
}
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18
|
||||||
|
else if(interruptNum == PORTR_INT0
|
||||||
|
#ifdef PORTR_INT1
|
||||||
|
|| interruptNum == PORTR_INT1
|
||||||
|
#endif // PORTR_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTR;
|
||||||
|
#ifdef PORTR_INT1
|
||||||
|
if(interruptNum == PORTR_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTR_INT1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return; // do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// On certain processors there's only one interrupt, so it's called 'INTMASK'
|
||||||
|
// we test for this here
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
if(!iNum)
|
||||||
|
{
|
||||||
|
// set interrupt mask for PORT A, int 0 vector
|
||||||
|
port->INTMASK |= iPinBits; // enable int zero for these pins
|
||||||
|
port->INTCTRL = (port->INTCTRL & ~(PORT_INTLVL_gm))
|
||||||
|
| (iPriBits & 3);
|
||||||
|
}
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
if(!iNum)
|
||||||
|
{
|
||||||
|
// set interrupt mask for PORT A, int 0 vector
|
||||||
|
port->INT0MASK |= iPinBits; // enable int zero for these pins
|
||||||
|
port->INTCTRL = (port->INTCTRL & ~(PORT_INT0LVL_gm))
|
||||||
|
| (iPriBits & 3);
|
||||||
|
}
|
||||||
|
else // if(iNum == 1)
|
||||||
|
{
|
||||||
|
port->INT1MASK |= iPinBits; // enable int zero for these pins
|
||||||
|
port->INTCTRL = (port->INTCTRL & ~(PORT_INT1LVL_gm))
|
||||||
|
| ((iPriBits & 3) << PORT_INT1LVL_gp);
|
||||||
|
}
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
|
||||||
|
for(iNum=0, iMask = 1; iNum < 8; iNum++, iMask <<= 1)
|
||||||
|
{
|
||||||
|
register8_t *pCTRL = &(port->PIN0CTRL) + iNum; // treat PIN0CTRL through PIN7CTRL as an array
|
||||||
|
|
||||||
|
// set corresponding 'type' in the interrupt control regs for the individual bits
|
||||||
|
|
||||||
|
if(iPinBits & iMask) // is this bit set in 'iPinBits'?
|
||||||
|
{
|
||||||
|
// enable the interrupt pin's mode bits and assign the 'invert' flag as needed
|
||||||
|
|
||||||
|
*pCTRL = (*pCTRL & ~(PORT_ISC_gm | PORT_INVEN_bm))
|
||||||
|
| iModeBits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SREG = oldSREG; // restore it, interrupts (probably) re-enabled
|
||||||
|
// NOTE that this may throw an interrupt right away
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void detachInterrupt(uint8_t interruptNum)
|
||||||
|
{
|
||||||
|
uint8_t iPinBits, iNum, iMask;
|
||||||
|
uint8_t oldSREG;
|
||||||
|
PORT_t *port;
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: this function will turn OFF the 'invert' bit if it's set for a HIGH level interrupt
|
||||||
|
// and digitalRead _SHOULD_ be consistent before/after this call.
|
||||||
|
|
||||||
|
if(interruptNum >= EXTERNAL_NUM_INTERRUPTS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldSREG = SREG; // keep track of interrupt flag state
|
||||||
|
|
||||||
|
cli(); // clear the interrupt flag
|
||||||
|
|
||||||
|
// grab 'pin bits' so I know what to flip around
|
||||||
|
iPinBits = intPins[interruptNum]; // what I used when I added it
|
||||||
|
|
||||||
|
intFunc[interruptNum] = 0;
|
||||||
|
intPins[interruptNum] = 0; // zero both of these
|
||||||
|
|
||||||
|
// disable the interrupt
|
||||||
|
|
||||||
|
// Enable the interrupt (smaller code to use if/else and pointer)
|
||||||
|
|
||||||
|
iNum = 0;
|
||||||
|
if(interruptNum == PORTA_INT0
|
||||||
|
#ifdef PORTA_INT1
|
||||||
|
|| interruptNum == PORTA_INT1
|
||||||
|
#endif // PORTA_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTA;
|
||||||
|
#ifdef PORTA_INT1
|
||||||
|
if(interruptNum == PORTA_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTA_INT1
|
||||||
|
}
|
||||||
|
#if NUM_ANALOG_PINS > 8 /* which means we have PORT B */
|
||||||
|
else if(interruptNum == PORTB_INT0
|
||||||
|
#ifdef PORTB_INT1
|
||||||
|
|| interruptNum == PORTB_INT1
|
||||||
|
#endif // PORTB_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTB;
|
||||||
|
#ifdef PORTB_INT1
|
||||||
|
if(interruptNum == PORTB_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTB_INT1
|
||||||
|
}
|
||||||
|
#endif // NUM_ANALOG_PINS > 8
|
||||||
|
else if(interruptNum == PORTC_INT0
|
||||||
|
#ifdef PORTC_INT1
|
||||||
|
|| interruptNum == PORTC_INT1
|
||||||
|
#endif // PORTC_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTC;
|
||||||
|
#ifdef PORTC_INT1
|
||||||
|
if(interruptNum == PORTC_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTC_INT1
|
||||||
|
}
|
||||||
|
else if(interruptNum == PORTD_INT0
|
||||||
|
#ifdef PORTD_INT1
|
||||||
|
|| interruptNum == PORTD_INT1
|
||||||
|
#endif // PORTD_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTD;
|
||||||
|
#ifdef PORTD_INT1
|
||||||
|
if(interruptNum == PORTD_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTD_INT1
|
||||||
|
}
|
||||||
|
#if NUM_DIGITAL_PINS > 18 /* which means we have PORT E */
|
||||||
|
else if(interruptNum == PORTE_INT0
|
||||||
|
#ifdef PORTE_INT1
|
||||||
|
|| interruptNum == PORTE_INT1
|
||||||
|
#endif // PORTE_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTE;
|
||||||
|
#ifdef PORTE_INT1
|
||||||
|
if(interruptNum == PORTE_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTE_INT1
|
||||||
|
}
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18
|
||||||
|
else if(interruptNum == PORTR_INT0
|
||||||
|
#ifdef PORTR_INT1
|
||||||
|
|| interruptNum == PORTR_INT1
|
||||||
|
#endif // PORTR_INT1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
port = &PORTR;
|
||||||
|
#ifdef PORTR_INT1
|
||||||
|
if(interruptNum == PORTR_INT1)
|
||||||
|
{
|
||||||
|
iNum = 1;
|
||||||
|
}
|
||||||
|
#endif // PORTR_INT1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return; // do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// On certain processors there's only one interrupt, so it's called 'INTMASK'
|
||||||
|
// we test for this here
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
if(!iNum)
|
||||||
|
{
|
||||||
|
// set interrupt mask for PORT A, int 0 vector
|
||||||
|
port->INTMASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ?
|
||||||
|
port->INTCTRL &= ~(PORT_INTLVL_gm); // set interrupt control to 'OFF'
|
||||||
|
port->INTFLAGS = _BV(0); // clear the int flag
|
||||||
|
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
if(!iNum)
|
||||||
|
{
|
||||||
|
// set interrupt mask for PORT A, int 0 vector
|
||||||
|
port->INT0MASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ?
|
||||||
|
port->INTCTRL &= ~(PORT_INT0LVL_gm); // set interrupt control to 'OFF'
|
||||||
|
port->INTFLAGS = _BV(0); // clear the int 0 flag
|
||||||
|
}
|
||||||
|
else // if(iNum == 1)
|
||||||
|
{
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
// if this matches a CTS port, I do _NOT_ want to disable interrupts
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED) && defined(SERIAL_1_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == port)
|
||||||
|
{
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
if(SERIAL_1_CTS_PORT == port)
|
||||||
|
{
|
||||||
|
port->INTMASK = SERIAL_0_CTS_PIN | SERIAL_1_CTS_PIN; // disable interrupts but leave BOTH enabled
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
port->INTMASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
if(SERIAL_1_CTS_PORT == port)
|
||||||
|
{
|
||||||
|
port->INT1MASK = SERIAL_0_CTS_PIN | SERIAL_1_CTS_PIN; // disable interrupts but leave BOTH enabled
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
port->INT1MASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
else if(SERIAL_1_CTS_PORT == port)
|
||||||
|
{
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
port->INTMASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
port->INT1MASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
#elif defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == port)
|
||||||
|
{
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
port->INTMASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
port->INT1MASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
#elif defined(SERIAL_1_CTS_ENABLED)
|
||||||
|
if(SERIAL_1_CTS_PORT == port)
|
||||||
|
{
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
port->INTMASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
port->INT1MASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled
|
||||||
|
|
||||||
|
port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0/1_CTS_ENABLED
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED) || defined(SERIAL_1_CTS_ENABLED)
|
||||||
|
else
|
||||||
|
#endif // SERIAL_0/1_CTS_ENABLED
|
||||||
|
|
||||||
|
{
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
port->INTMASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ?
|
||||||
|
port->INTCTRL &= ~(PORT_INTLVL_gm); // set interrupt control to 'OFF'
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
port->INT1MASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ?
|
||||||
|
port->INTCTRL &= ~(PORT_INT1LVL_gm); // set interrupt control to 'OFF'
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
port->INTFLAGS = _BV(0); // clear the int 0 flag
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
port->INTFLAGS = _BV(1); // clear the int 1 flag
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
|
||||||
|
for(iNum=0, iMask = 1; iNum < 8; iNum++, iMask <<= 1)
|
||||||
|
{
|
||||||
|
register8_t *pCTRL = &(port->PIN0CTRL) + iNum; // treat PIN0CTRL through PIN7CTRL as an array
|
||||||
|
|
||||||
|
// set corresponding 'type' in the interrupt control regs for the individual bits
|
||||||
|
|
||||||
|
if(iPinBits & iMask) // is this bit set in 'iPinBits'?
|
||||||
|
{
|
||||||
|
*pCTRL &= ~(PORT_ISC_gm | PORT_INVEN_bm); // turn off invert flag and reset to 'BOTH' (the default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SREG = oldSREG; // restore it, interrupts (probably) re-enabled
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
ISR(PORTA_INT_vect)
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
ISR(PORTA_INT0_vect)
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
{
|
||||||
|
if(intFunc[PORTA_INT0])
|
||||||
|
intFunc[PORTA_INT0]();
|
||||||
|
|
||||||
|
#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PORTA_INT1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTA_INT1])
|
||||||
|
intFunc[PORTA_INT1]();
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == &(PORTA)) // this should compile as a constant expression
|
||||||
|
{
|
||||||
|
serial_0_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0_CTS_ENABLED
|
||||||
|
|
||||||
|
#ifdef SERIAL_1_CTS_ENABLED
|
||||||
|
if(SERIAL_1_CTS_PORT == &(PORTA))
|
||||||
|
{
|
||||||
|
serial_1_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_1_CTS_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NUM_ANALOG_PINS > 8 /* which means we have PORT B */
|
||||||
|
ISR(PORTB_INT0_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTB_INT0])
|
||||||
|
intFunc[PORTB_INT0]();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PORTB_INT1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTB_INT1])
|
||||||
|
intFunc[PORTB_INT1]();
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == &(PORTB)) // this should compile as a constant expression
|
||||||
|
{
|
||||||
|
serial_0_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0_CTS_ENABLED
|
||||||
|
|
||||||
|
#ifdef SERIAL_1_CTS_ENABLED
|
||||||
|
if(SERIAL_1_CTS_PORT == &(PORTB))
|
||||||
|
{
|
||||||
|
serial_1_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_1_CTS_ENABLED
|
||||||
|
}
|
||||||
|
#endif // NUM_ANALOG_PINS > 8
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
ISR(PORTC_INT_vect)
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
ISR(PORTC_INT0_vect)
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
{
|
||||||
|
if(intFunc[PORTC_INT0])
|
||||||
|
intFunc[PORTC_INT0]();
|
||||||
|
#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PORTC_INT1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTC_INT1])
|
||||||
|
intFunc[PORTC_INT1]();
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == &(PORTC)) // this should compile as a constant expression
|
||||||
|
{
|
||||||
|
serial_0_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0_CTS_ENABLED
|
||||||
|
|
||||||
|
#ifdef SERIAL_1_CTS_ENABLED
|
||||||
|
if(SERIAL_1_CTS_PORT == &(PORTC))
|
||||||
|
{
|
||||||
|
serial_1_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_1_CTS_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
ISR(PORTD_INT_vect)
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
ISR(PORTD_INT0_vect)
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
{
|
||||||
|
if(intFunc[PORTD_INT0])
|
||||||
|
intFunc[PORTD_INT0]();
|
||||||
|
#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PORTD_INT1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTD_INT1])
|
||||||
|
intFunc[PORTD_INT1]();
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == &(PORTD)) // this should compile as a constant expression
|
||||||
|
{
|
||||||
|
serial_0_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0_CTS_ENABLED
|
||||||
|
|
||||||
|
#ifdef SERIAL_1_CTS_ENABLED
|
||||||
|
if(SERIAL_1_CTS_PORT == &(PORTD))
|
||||||
|
{
|
||||||
|
serial_1_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_1_CTS_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 18 /* which means we have PORT E */
|
||||||
|
ISR(PORTE_INT0_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTE_INT0])
|
||||||
|
intFunc[PORTE_INT0]();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PORTE_INT1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTE_INT1])
|
||||||
|
intFunc[PORTE_INT1]();
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == &(PORTE)) // this should compile as a constant expression
|
||||||
|
{
|
||||||
|
serial_0_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0_CTS_ENABLED
|
||||||
|
|
||||||
|
#ifdef SERIAL_1_CTS_ENABLED
|
||||||
|
if(SERIAL_1_CTS_PORT == &(PORTE))
|
||||||
|
{
|
||||||
|
serial_1_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_1_CTS_ENABLED
|
||||||
|
}
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18
|
||||||
|
|
||||||
|
// TODO: ISRs for PORTF, PORTH, PORTJ, PORTK, PORTQ
|
||||||
|
|
||||||
|
#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */
|
||||||
|
ISR(PORTR_INT_vect)
|
||||||
|
#else // INT0MASK and INT1MASK supported
|
||||||
|
ISR(PORTR_INT0_vect)
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
{
|
||||||
|
if(intFunc[PORTR_INT0])
|
||||||
|
intFunc[PORTR_INT0]();
|
||||||
|
#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PORTR_INT1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[PORTR_INT1])
|
||||||
|
intFunc[PORTR_INT1]();
|
||||||
|
#endif // INT0MASK and INT1MASK supported
|
||||||
|
|
||||||
|
#if defined(SERIAL_0_CTS_ENABLED)
|
||||||
|
if(SERIAL_0_CTS_PORT == &(PORTR)) // this should compile as a constant expression
|
||||||
|
{
|
||||||
|
serial_0_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_0_CTS_ENABLED
|
||||||
|
|
||||||
|
#ifdef SERIAL_1_CTS_ENABLED
|
||||||
|
if(SERIAL_1_CTS_PORT == &(PORTR))
|
||||||
|
{
|
||||||
|
serial_1_cts_callback();
|
||||||
|
}
|
||||||
|
#endif // SERIAL_1_CTS_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,14 +42,14 @@ long random(long howbig)
|
|||||||
return random() % howbig;
|
return random() % howbig;
|
||||||
}
|
}
|
||||||
|
|
||||||
//long random(long howsmall, long howbig)
|
long random(long howsmall, long howbig)
|
||||||
//{
|
{
|
||||||
// if (howsmall >= howbig) {
|
if (howsmall >= howbig) {
|
||||||
// return howsmall;
|
return howsmall;
|
||||||
// }
|
}
|
||||||
// long diff = howbig - howsmall;
|
long diff = howbig - howsmall;
|
||||||
// return random(diff) + howsmall;
|
return random(diff) + howsmall;
|
||||||
//}
|
}
|
||||||
|
|
||||||
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||||
{
|
{
|
744
BootLoaders/Boards/orangerx/cores/xmega/WString.cpp
Normal file
744
BootLoaders/Boards/orangerx/cores/xmega/WString.cpp
Normal file
@ -0,0 +1,744 @@
|
|||||||
|
/*
|
||||||
|
WString.cpp - String library for Wiring & Arduino
|
||||||
|
...mostly rewritten by Paul Stoffregen...
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||||
|
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Constructors */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
String::String(const char *cstr)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
if (cstr) copy(cstr, strlen(cstr));
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(const String &value)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
*this = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(const __FlashStringHelper *pstr)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
*this = pstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String::String(String &&rval)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
move(rval);
|
||||||
|
}
|
||||||
|
String::String(StringSumHelper &&rval)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
move(rval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String::String(char c)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[2];
|
||||||
|
buf[0] = c;
|
||||||
|
buf[1] = 0;
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned char value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned char)];
|
||||||
|
utoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(int value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[2 + 8 * sizeof(int)];
|
||||||
|
itoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned int value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned int)];
|
||||||
|
utoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(long value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[2 + 8 * sizeof(long)];
|
||||||
|
ltoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned long value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned long)];
|
||||||
|
ultoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(float value, unsigned char decimalPlaces)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[33];
|
||||||
|
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(double value, unsigned char decimalPlaces)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[33];
|
||||||
|
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::~String()
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Memory Management */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
inline void String::init(void)
|
||||||
|
{
|
||||||
|
buffer = NULL;
|
||||||
|
capacity = 0;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::invalidate(void)
|
||||||
|
{
|
||||||
|
if (buffer) free(buffer);
|
||||||
|
buffer = NULL;
|
||||||
|
capacity = len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::reserve(unsigned int size)
|
||||||
|
{
|
||||||
|
if (buffer && capacity >= size) return 1;
|
||||||
|
if (changeBuffer(size)) {
|
||||||
|
if (len == 0) buffer[0] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
||||||
|
{
|
||||||
|
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
||||||
|
if (newbuffer) {
|
||||||
|
buffer = newbuffer;
|
||||||
|
capacity = maxStrLen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Copy and Move */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
String & String::copy(const char *cstr, unsigned int length)
|
||||||
|
{
|
||||||
|
if (!reserve(length)) {
|
||||||
|
invalidate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
len = length;
|
||||||
|
strcpy(buffer, cstr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||||
|
{
|
||||||
|
if (!reserve(length)) {
|
||||||
|
invalidate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
len = length;
|
||||||
|
strcpy_P(buffer, (PGM_P)pstr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
void String::move(String &rhs)
|
||||||
|
{
|
||||||
|
if (buffer) {
|
||||||
|
if (capacity >= rhs.len) {
|
||||||
|
strcpy(buffer, rhs.buffer);
|
||||||
|
len = rhs.len;
|
||||||
|
rhs.len = 0;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer = rhs.buffer;
|
||||||
|
capacity = rhs.capacity;
|
||||||
|
len = rhs.len;
|
||||||
|
rhs.buffer = NULL;
|
||||||
|
rhs.capacity = 0;
|
||||||
|
rhs.len = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String & String::operator = (const String &rhs)
|
||||||
|
{
|
||||||
|
if (this == &rhs) return *this;
|
||||||
|
|
||||||
|
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String & String::operator = (String &&rval)
|
||||||
|
{
|
||||||
|
if (this != &rval) move(rval);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::operator = (StringSumHelper &&rval)
|
||||||
|
{
|
||||||
|
if (this != &rval) move(rval);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String & String::operator = (const char *cstr)
|
||||||
|
{
|
||||||
|
if (cstr) copy(cstr, strlen(cstr));
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::operator = (const __FlashStringHelper *pstr)
|
||||||
|
{
|
||||||
|
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* concat */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
unsigned char String::concat(const String &s)
|
||||||
|
{
|
||||||
|
return concat(s.buffer, s.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const char *cstr, unsigned int length)
|
||||||
|
{
|
||||||
|
unsigned int newlen = len + length;
|
||||||
|
if (!cstr) return 0;
|
||||||
|
if (length == 0) return 1;
|
||||||
|
if (!reserve(newlen)) return 0;
|
||||||
|
strcpy(buffer + len, cstr);
|
||||||
|
len = newlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const char *cstr)
|
||||||
|
{
|
||||||
|
if (!cstr) return 0;
|
||||||
|
return concat(cstr, strlen(cstr));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(char c)
|
||||||
|
{
|
||||||
|
char buf[2];
|
||||||
|
buf[0] = c;
|
||||||
|
buf[1] = 0;
|
||||||
|
return concat(buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned char num)
|
||||||
|
{
|
||||||
|
char buf[1 + 3 * sizeof(unsigned char)];
|
||||||
|
itoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(int num)
|
||||||
|
{
|
||||||
|
char buf[2 + 3 * sizeof(int)];
|
||||||
|
itoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned int num)
|
||||||
|
{
|
||||||
|
char buf[1 + 3 * sizeof(unsigned int)];
|
||||||
|
utoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(long num)
|
||||||
|
{
|
||||||
|
char buf[2 + 3 * sizeof(long)];
|
||||||
|
ltoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned long num)
|
||||||
|
{
|
||||||
|
char buf[1 + 3 * sizeof(unsigned long)];
|
||||||
|
ultoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(float num)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
char* string = dtostrf(num, 4, 2, buf);
|
||||||
|
return concat(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(double num)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
char* string = dtostrf(num, 4, 2, buf);
|
||||||
|
return concat(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const __FlashStringHelper * str)
|
||||||
|
{
|
||||||
|
if (!str) return 0;
|
||||||
|
int length = strlen_P((const char *) str);
|
||||||
|
if (length == 0) return 1;
|
||||||
|
unsigned int newlen = len + length;
|
||||||
|
if (!reserve(newlen)) return 0;
|
||||||
|
strcpy_P(buffer + len, (const char *) str);
|
||||||
|
len = newlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Concatenate */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(c)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(rhs)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Comparison */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
int String::compareTo(const String &s) const
|
||||||
|
{
|
||||||
|
if (!buffer || !s.buffer) {
|
||||||
|
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
||||||
|
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return strcmp(buffer, s.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equals(const String &s2) const
|
||||||
|
{
|
||||||
|
return (len == s2.len && compareTo(s2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equals(const char *cstr) const
|
||||||
|
{
|
||||||
|
if (len == 0) return (cstr == NULL || *cstr == 0);
|
||||||
|
if (cstr == NULL) return buffer[0] == 0;
|
||||||
|
return strcmp(buffer, cstr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator<(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator>(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator<=(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator>=(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if (this == &s2) return 1;
|
||||||
|
if (len != s2.len) return 0;
|
||||||
|
if (len == 0) return 1;
|
||||||
|
const char *p1 = buffer;
|
||||||
|
const char *p2 = s2.buffer;
|
||||||
|
while (*p1) {
|
||||||
|
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::startsWith( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if (len < s2.len) return 0;
|
||||||
|
return startsWith(s2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
||||||
|
{
|
||||||
|
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
||||||
|
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::endsWith( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
||||||
|
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Character Access */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
char String::charAt(unsigned int loc) const
|
||||||
|
{
|
||||||
|
return operator[](loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::setCharAt(unsigned int loc, char c)
|
||||||
|
{
|
||||||
|
if (loc < len) buffer[loc] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
char & String::operator[](unsigned int index)
|
||||||
|
{
|
||||||
|
static char dummy_writable_char;
|
||||||
|
if (index >= len || !buffer) {
|
||||||
|
dummy_writable_char = 0;
|
||||||
|
return dummy_writable_char;
|
||||||
|
}
|
||||||
|
return buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
char String::operator[]( unsigned int index ) const
|
||||||
|
{
|
||||||
|
if (index >= len || !buffer) return 0;
|
||||||
|
return buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
||||||
|
{
|
||||||
|
if (!bufsize || !buf) return;
|
||||||
|
if (index >= len) {
|
||||||
|
buf[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned int n = bufsize - 1;
|
||||||
|
if (n > len - index) n = len - index;
|
||||||
|
strncpy((char *)buf, buffer + index, n);
|
||||||
|
buf[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Search */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
int String::indexOf(char c) const
|
||||||
|
{
|
||||||
|
return indexOf(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||||
|
{
|
||||||
|
if (fromIndex >= len) return -1;
|
||||||
|
const char* temp = strchr(buffer + fromIndex, ch);
|
||||||
|
if (temp == NULL) return -1;
|
||||||
|
return temp - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(const String &s2) const
|
||||||
|
{
|
||||||
|
return indexOf(s2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
||||||
|
{
|
||||||
|
if (fromIndex >= len) return -1;
|
||||||
|
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
||||||
|
if (found == NULL) return -1;
|
||||||
|
return found - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf( char theChar ) const
|
||||||
|
{
|
||||||
|
return lastIndexOf(theChar, len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
||||||
|
{
|
||||||
|
if (fromIndex >= len) return -1;
|
||||||
|
char tempchar = buffer[fromIndex + 1];
|
||||||
|
buffer[fromIndex + 1] = '\0';
|
||||||
|
char* temp = strrchr( buffer, ch );
|
||||||
|
buffer[fromIndex + 1] = tempchar;
|
||||||
|
if (temp == NULL) return -1;
|
||||||
|
return temp - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(const String &s2) const
|
||||||
|
{
|
||||||
|
return lastIndexOf(s2, len - s2.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
||||||
|
{
|
||||||
|
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
||||||
|
if (fromIndex >= len) fromIndex = len - 1;
|
||||||
|
int found = -1;
|
||||||
|
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
||||||
|
p = strstr(p, s2.buffer);
|
||||||
|
if (!p) break;
|
||||||
|
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::substring(unsigned int left, unsigned int right) const
|
||||||
|
{
|
||||||
|
if (left > right) {
|
||||||
|
unsigned int temp = right;
|
||||||
|
right = left;
|
||||||
|
left = temp;
|
||||||
|
}
|
||||||
|
String out;
|
||||||
|
if (left > len) return out;
|
||||||
|
if (right > len) right = len;
|
||||||
|
char temp = buffer[right]; // save the replaced character
|
||||||
|
buffer[right] = '\0';
|
||||||
|
out = buffer + left; // pointer arithmetic
|
||||||
|
buffer[right] = temp; //restore character
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Modification */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
void String::replace(char find, char replace)
|
||||||
|
{
|
||||||
|
if (!buffer) return;
|
||||||
|
for (char *p = buffer; *p; p++) {
|
||||||
|
if (*p == find) *p = replace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::replace(const String& find, const String& replace)
|
||||||
|
{
|
||||||
|
if (len == 0 || find.len == 0) return;
|
||||||
|
int diff = replace.len - find.len;
|
||||||
|
char *readFrom = buffer;
|
||||||
|
char *foundAt;
|
||||||
|
if (diff == 0) {
|
||||||
|
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||||
|
memcpy(foundAt, replace.buffer, replace.len);
|
||||||
|
readFrom = foundAt + replace.len;
|
||||||
|
}
|
||||||
|
} else if (diff < 0) {
|
||||||
|
char *writeTo = buffer;
|
||||||
|
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||||
|
unsigned int n = foundAt - readFrom;
|
||||||
|
memcpy(writeTo, readFrom, n);
|
||||||
|
writeTo += n;
|
||||||
|
memcpy(writeTo, replace.buffer, replace.len);
|
||||||
|
writeTo += replace.len;
|
||||||
|
readFrom = foundAt + find.len;
|
||||||
|
len += diff;
|
||||||
|
}
|
||||||
|
strcpy(writeTo, readFrom);
|
||||||
|
} else {
|
||||||
|
unsigned int size = len; // compute size needed for result
|
||||||
|
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||||
|
readFrom = foundAt + find.len;
|
||||||
|
size += diff;
|
||||||
|
}
|
||||||
|
if (size == len) return;
|
||||||
|
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
|
||||||
|
int index = len - 1;
|
||||||
|
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||||
|
readFrom = buffer + index + find.len;
|
||||||
|
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
||||||
|
len += diff;
|
||||||
|
buffer[len] = 0;
|
||||||
|
memcpy(buffer + index, replace.buffer, replace.len);
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::remove(unsigned int index){
|
||||||
|
if (index >= len) { return; }
|
||||||
|
int count = len - index;
|
||||||
|
remove(index, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::remove(unsigned int index, unsigned int count){
|
||||||
|
if (index >= len) { return; }
|
||||||
|
if (count <= 0) { return; }
|
||||||
|
if (index + count > len) { count = len - index; }
|
||||||
|
char *writeTo = buffer + index;
|
||||||
|
len = len - count;
|
||||||
|
strncpy(writeTo, buffer + index + count,len - index);
|
||||||
|
buffer[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toLowerCase(void)
|
||||||
|
{
|
||||||
|
if (!buffer) return;
|
||||||
|
for (char *p = buffer; *p; p++) {
|
||||||
|
*p = tolower(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toUpperCase(void)
|
||||||
|
{
|
||||||
|
if (!buffer) return;
|
||||||
|
for (char *p = buffer; *p; p++) {
|
||||||
|
*p = toupper(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::trim(void)
|
||||||
|
{
|
||||||
|
if (!buffer || len == 0) return;
|
||||||
|
char *begin = buffer;
|
||||||
|
while (isspace(*begin)) begin++;
|
||||||
|
char *end = buffer + len - 1;
|
||||||
|
while (isspace(*end) && end >= begin) end--;
|
||||||
|
len = end + 1 - begin;
|
||||||
|
if (begin > buffer) memcpy(buffer, begin, len);
|
||||||
|
buffer[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Parsing / Conversion */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
long String::toInt(void) const
|
||||||
|
{
|
||||||
|
if (buffer) return atol(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float String::toFloat(void) const
|
||||||
|
{
|
||||||
|
if (buffer) return float(atof(buffer));
|
||||||
|
return 0;
|
||||||
|
}
|
224
BootLoaders/Boards/orangerx/cores/xmega/WString.h
Normal file
224
BootLoaders/Boards/orangerx/cores/xmega/WString.h
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
WString.h - String library for Wiring & Arduino
|
||||||
|
...mostly rewritten by Paul Stoffregen...
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||||
|
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef String_class_h
|
||||||
|
#define String_class_h
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
// When compiling programs with this class, the following gcc parameters
|
||||||
|
// dramatically increase performance and memory (RAM) efficiency, typically
|
||||||
|
// with little or no increase in code size.
|
||||||
|
// -felide-constructors
|
||||||
|
// -std=c++0x
|
||||||
|
|
||||||
|
class __FlashStringHelper;
|
||||||
|
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||||
|
|
||||||
|
// An inherited class for holding the result of a concatenation. These
|
||||||
|
// result objects are assumed to be writable by subsequent concatenations.
|
||||||
|
class StringSumHelper;
|
||||||
|
|
||||||
|
// The string class
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
// use a function pointer to allow for "if (s)" without the
|
||||||
|
// complications of an operator bool(). for more information, see:
|
||||||
|
// http://www.artima.com/cppsource/safebool.html
|
||||||
|
typedef void (String::*StringIfHelperType)() const;
|
||||||
|
void StringIfHelper() const {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
// creates a copy of the initial value.
|
||||||
|
// if the initial value is null or invalid, or if memory allocation
|
||||||
|
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||||
|
// be false).
|
||||||
|
String(const char *cstr = "");
|
||||||
|
String(const String &str);
|
||||||
|
String(const __FlashStringHelper *str);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String(String &&rval);
|
||||||
|
String(StringSumHelper &&rval);
|
||||||
|
#endif
|
||||||
|
explicit String(char c);
|
||||||
|
explicit String(unsigned char, unsigned char base=10);
|
||||||
|
explicit String(int, unsigned char base=10);
|
||||||
|
explicit String(unsigned int, unsigned char base=10);
|
||||||
|
explicit String(long, unsigned char base=10);
|
||||||
|
explicit String(unsigned long, unsigned char base=10);
|
||||||
|
explicit String(float, unsigned char decimalPlaces=2);
|
||||||
|
explicit String(double, unsigned char decimalPlaces=2);
|
||||||
|
~String(void);
|
||||||
|
|
||||||
|
// memory management
|
||||||
|
// return true on success, false on failure (in which case, the string
|
||||||
|
// is left unchanged). reserve(0), if successful, will validate an
|
||||||
|
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||||
|
unsigned char reserve(unsigned int size);
|
||||||
|
inline unsigned int length(void) const {return len;}
|
||||||
|
|
||||||
|
// creates a copy of the assigned value. if the value is null or
|
||||||
|
// invalid, or if the memory allocation fails, the string will be
|
||||||
|
// marked as invalid ("if (s)" will be false).
|
||||||
|
String & operator = (const String &rhs);
|
||||||
|
String & operator = (const char *cstr);
|
||||||
|
String & operator = (const __FlashStringHelper *str);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String & operator = (String &&rval);
|
||||||
|
String & operator = (StringSumHelper &&rval);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// concatenate (works w/ built-in types)
|
||||||
|
|
||||||
|
// returns true on success, false on failure (in which case, the string
|
||||||
|
// is left unchanged). if the argument is null or invalid, the
|
||||||
|
// concatenation is considered unsucessful.
|
||||||
|
unsigned char concat(const String &str);
|
||||||
|
unsigned char concat(const char *cstr);
|
||||||
|
unsigned char concat(char c);
|
||||||
|
unsigned char concat(unsigned char c);
|
||||||
|
unsigned char concat(int num);
|
||||||
|
unsigned char concat(unsigned int num);
|
||||||
|
unsigned char concat(long num);
|
||||||
|
unsigned char concat(unsigned long num);
|
||||||
|
unsigned char concat(float num);
|
||||||
|
unsigned char concat(double num);
|
||||||
|
unsigned char concat(const __FlashStringHelper * str);
|
||||||
|
|
||||||
|
// if there's not enough memory for the concatenated value, the string
|
||||||
|
// will be left unchanged (but this isn't signalled in any way)
|
||||||
|
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
||||||
|
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
||||||
|
String & operator += (char c) {concat(c); return (*this);}
|
||||||
|
String & operator += (unsigned char num) {concat(num); return (*this);}
|
||||||
|
String & operator += (int num) {concat(num); return (*this);}
|
||||||
|
String & operator += (unsigned int num) {concat(num); return (*this);}
|
||||||
|
String & operator += (long num) {concat(num); return (*this);}
|
||||||
|
String & operator += (unsigned long num) {concat(num); return (*this);}
|
||||||
|
String & operator += (float num) {concat(num); return (*this);}
|
||||||
|
String & operator += (double num) {concat(num); return (*this);}
|
||||||
|
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
||||||
|
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||||
|
|
||||||
|
// comparison (only works w/ Strings and "strings")
|
||||||
|
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
||||||
|
int compareTo(const String &s) const;
|
||||||
|
unsigned char equals(const String &s) const;
|
||||||
|
unsigned char equals(const char *cstr) const;
|
||||||
|
unsigned char operator == (const String &rhs) const {return equals(rhs);}
|
||||||
|
unsigned char operator == (const char *cstr) const {return equals(cstr);}
|
||||||
|
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
|
||||||
|
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
|
||||||
|
unsigned char operator < (const String &rhs) const;
|
||||||
|
unsigned char operator > (const String &rhs) const;
|
||||||
|
unsigned char operator <= (const String &rhs) const;
|
||||||
|
unsigned char operator >= (const String &rhs) const;
|
||||||
|
unsigned char equalsIgnoreCase(const String &s) const;
|
||||||
|
unsigned char startsWith( const String &prefix) const;
|
||||||
|
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||||
|
unsigned char endsWith(const String &suffix) const;
|
||||||
|
|
||||||
|
// character acccess
|
||||||
|
char charAt(unsigned int index) const;
|
||||||
|
void setCharAt(unsigned int index, char c);
|
||||||
|
char operator [] (unsigned int index) const;
|
||||||
|
char& operator [] (unsigned int index);
|
||||||
|
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
||||||
|
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
||||||
|
{getBytes((unsigned char *)buf, bufsize, index);}
|
||||||
|
const char * c_str() const { return buffer; }
|
||||||
|
|
||||||
|
// search
|
||||||
|
int indexOf( char ch ) const;
|
||||||
|
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||||
|
int indexOf( const String &str ) const;
|
||||||
|
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||||
|
int lastIndexOf( char ch ) const;
|
||||||
|
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||||
|
int lastIndexOf( const String &str ) const;
|
||||||
|
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||||
|
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
||||||
|
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||||
|
|
||||||
|
// modification
|
||||||
|
void replace(char find, char replace);
|
||||||
|
void replace(const String& find, const String& replace);
|
||||||
|
void remove(unsigned int index);
|
||||||
|
void remove(unsigned int index, unsigned int count);
|
||||||
|
void toLowerCase(void);
|
||||||
|
void toUpperCase(void);
|
||||||
|
void trim(void);
|
||||||
|
|
||||||
|
// parsing/conversion
|
||||||
|
long toInt(void) const;
|
||||||
|
float toFloat(void) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char *buffer; // the actual char array
|
||||||
|
unsigned int capacity; // the array length minus one (for the '\0')
|
||||||
|
unsigned int len; // the String length (not counting the '\0')
|
||||||
|
protected:
|
||||||
|
void init(void);
|
||||||
|
void invalidate(void);
|
||||||
|
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||||
|
unsigned char concat(const char *cstr, unsigned int length);
|
||||||
|
|
||||||
|
// copy and move
|
||||||
|
String & copy(const char *cstr, unsigned int length);
|
||||||
|
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
void move(String &rhs);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringSumHelper : public String
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringSumHelper(const String &s) : String(s) {}
|
||||||
|
StringSumHelper(const char *p) : String(p) {}
|
||||||
|
StringSumHelper(char c) : String(c) {}
|
||||||
|
StringSumHelper(unsigned char num) : String(num) {}
|
||||||
|
StringSumHelper(int num) : String(num) {}
|
||||||
|
StringSumHelper(unsigned int num) : String(num) {}
|
||||||
|
StringSumHelper(long num) : String(num) {}
|
||||||
|
StringSumHelper(unsigned long num) : String(num) {}
|
||||||
|
StringSumHelper(float num) : String(num) {}
|
||||||
|
StringSumHelper(double num) : String(num) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
#endif // String_class_h
|
267
BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c
Normal file
267
BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
/* Copyright (c) 2002, 2004, 2010 Joerg Wunsch
|
||||||
|
Copyright (c) 2010 Gerben van den Broeke
|
||||||
|
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: malloc.c 2149 2010-06-09 20:45:37Z joerg_wunsch $ */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sectionname.h"
|
||||||
|
#include "stdlib_private.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exported interface:
|
||||||
|
*
|
||||||
|
* When extending the data segment, the allocator will not try to go
|
||||||
|
* beyond the current stack limit, decreased by __malloc_margin bytes.
|
||||||
|
* Thus, all possible stack frames of interrupt routines that could
|
||||||
|
* interrupt the current function, plus all further nested function
|
||||||
|
* calls must not require more stack space, or they'll risk to collide
|
||||||
|
* with the data segment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* May be changed by the user only before the first malloc() call. */
|
||||||
|
|
||||||
|
size_t __malloc_margin = 128;
|
||||||
|
char *__malloc_heap_start = &__heap_start;
|
||||||
|
char *__malloc_heap_end = &__heap_end;
|
||||||
|
|
||||||
|
char *__brkval;
|
||||||
|
struct __freelist *__flp;
|
||||||
|
|
||||||
|
ATTRIBUTE_CLIB_SECTION
|
||||||
|
void *
|
||||||
|
malloc(size_t len)
|
||||||
|
{
|
||||||
|
struct __freelist *fp1, *fp2, *sfp1=NULL, *sfp2=NULL; // BBB - added '=NULL' for sfp1, sfp2 as they were warned as being uninitialized
|
||||||
|
char *cp;
|
||||||
|
size_t s, avail;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our minimum chunk size is the size of a pointer (plus the
|
||||||
|
* size of the "sz" field, but we don't need to account for
|
||||||
|
* this), otherwise we could not possibly fit a freelist entry
|
||||||
|
* into the chunk later.
|
||||||
|
*/
|
||||||
|
if (len < sizeof(struct __freelist) - sizeof(size_t))
|
||||||
|
len = sizeof(struct __freelist) - sizeof(size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, walk the free list and try finding a chunk that
|
||||||
|
* would match exactly. If we found one, we are done. While
|
||||||
|
* walking, note down the smallest chunk we found that would
|
||||||
|
* still fit the request -- we need it for step 2.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
for (s = 0, fp1 = __flp, fp2 = 0;
|
||||||
|
fp1;
|
||||||
|
fp2 = fp1, fp1 = fp1->nx) {
|
||||||
|
if (fp1->sz < len)
|
||||||
|
continue;
|
||||||
|
if (fp1->sz == len) {
|
||||||
|
/*
|
||||||
|
* Found it. Disconnect the chunk from the
|
||||||
|
* freelist, and return it.
|
||||||
|
*/
|
||||||
|
if (fp2)
|
||||||
|
fp2->nx = fp1->nx;
|
||||||
|
else
|
||||||
|
__flp = fp1->nx;
|
||||||
|
return &(fp1->nx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (s == 0 || fp1->sz < s) {
|
||||||
|
/* this is the smallest chunk found so far */
|
||||||
|
s = fp1->sz;
|
||||||
|
sfp1 = fp1;
|
||||||
|
sfp2 = fp2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Step 2: If we found a chunk on the freelist that would fit
|
||||||
|
* (but was too large), look it up again and use it, since it
|
||||||
|
* is our closest match now. Since the freelist entry needs
|
||||||
|
* to be split into two entries then, watch out that the
|
||||||
|
* difference between the requested size and the size of the
|
||||||
|
* chunk found is large enough for another freelist entry; if
|
||||||
|
* not, just enlarge the request size to what we have found,
|
||||||
|
* and use the entire chunk.
|
||||||
|
*/
|
||||||
|
if (s) {
|
||||||
|
if (s - len < sizeof(struct __freelist)) {
|
||||||
|
/* Disconnect it from freelist and return it. */
|
||||||
|
if (sfp2)
|
||||||
|
sfp2->nx = sfp1->nx;
|
||||||
|
else
|
||||||
|
__flp = sfp1->nx;
|
||||||
|
return &(sfp1->nx);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Split them up. Note that we leave the first part
|
||||||
|
* as the new (smaller) freelist entry, and return the
|
||||||
|
* upper portion to the caller. This saves us the
|
||||||
|
* work to fix up the freelist chain; we just need to
|
||||||
|
* fixup the size of the current entry, and note down
|
||||||
|
* the size of the new chunk before returning it to
|
||||||
|
* the caller.
|
||||||
|
*/
|
||||||
|
cp = (char *)sfp1;
|
||||||
|
s -= len;
|
||||||
|
cp += s;
|
||||||
|
sfp2 = (struct __freelist *)cp;
|
||||||
|
sfp2->sz = len;
|
||||||
|
sfp1->sz = s - sizeof(size_t);
|
||||||
|
return &(sfp2->nx);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Step 3: If the request could not be satisfied from a
|
||||||
|
* freelist entry, just prepare a new chunk. This means we
|
||||||
|
* need to obtain more memory first. The largest address just
|
||||||
|
* not allocated so far is remembered in the brkval variable.
|
||||||
|
* Under Unix, the "break value" was the end of the data
|
||||||
|
* segment as dynamically requested from the operating system.
|
||||||
|
* Since we don't have an operating system, just make sure
|
||||||
|
* that we don't collide with the stack.
|
||||||
|
*/
|
||||||
|
if (__brkval == 0)
|
||||||
|
__brkval = __malloc_heap_start;
|
||||||
|
cp = __malloc_heap_end;
|
||||||
|
if (cp == 0)
|
||||||
|
cp = STACK_POINTER() - __malloc_margin;
|
||||||
|
if (cp <= __brkval)
|
||||||
|
/*
|
||||||
|
* Memory exhausted.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
avail = cp - __brkval;
|
||||||
|
/*
|
||||||
|
* Both tests below are needed to catch the case len >= 0xfffe.
|
||||||
|
*/
|
||||||
|
if (avail >= len && avail >= len + sizeof(size_t)) {
|
||||||
|
fp1 = (struct __freelist *)__brkval;
|
||||||
|
__brkval += len + sizeof(size_t);
|
||||||
|
fp1->sz = len;
|
||||||
|
return &(fp1->nx);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Step 4: There's no help, just fail. :-/
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ATTRIBUTE_CLIB_SECTION
|
||||||
|
void
|
||||||
|
free(void *p)
|
||||||
|
{
|
||||||
|
struct __freelist *fp1, *fp2, *fpnew;
|
||||||
|
char *cp1, *cp2, *cpnew;
|
||||||
|
|
||||||
|
/* ISO C says free(NULL) must be a no-op */
|
||||||
|
if (p == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cpnew = p;
|
||||||
|
cpnew -= sizeof(size_t);
|
||||||
|
fpnew = (struct __freelist *)cpnew;
|
||||||
|
fpnew->nx = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trivial case first: if there's no freelist yet, our entry
|
||||||
|
* will be the only one on it. If this is the last entry, we
|
||||||
|
* can reduce __brkval instead.
|
||||||
|
*/
|
||||||
|
if (__flp == 0) {
|
||||||
|
if ((char *)p + fpnew->sz == __brkval)
|
||||||
|
__brkval = cpnew;
|
||||||
|
else
|
||||||
|
__flp = fpnew;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, find the position where our new entry belongs onto the
|
||||||
|
* freelist. Try to aggregate the chunk with adjacent chunks
|
||||||
|
* if possible.
|
||||||
|
*/
|
||||||
|
for (fp1 = __flp, fp2 = 0;
|
||||||
|
fp1;
|
||||||
|
fp2 = fp1, fp1 = fp1->nx) {
|
||||||
|
if (fp1 < fpnew)
|
||||||
|
continue;
|
||||||
|
cp1 = (char *)fp1;
|
||||||
|
fpnew->nx = fp1;
|
||||||
|
if ((char *)&(fpnew->nx) + fpnew->sz == cp1) {
|
||||||
|
/* upper chunk adjacent, assimilate it */
|
||||||
|
fpnew->sz += fp1->sz + sizeof(size_t);
|
||||||
|
fpnew->nx = fp1->nx;
|
||||||
|
}
|
||||||
|
if (fp2 == 0) {
|
||||||
|
/* new head of freelist */
|
||||||
|
__flp = fpnew;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Note that we get here either if we hit the "break" above,
|
||||||
|
* or if we fell off the end of the loop. The latter means
|
||||||
|
* we've got a new topmost chunk. Either way, try aggregating
|
||||||
|
* with the lower chunk if possible.
|
||||||
|
*/
|
||||||
|
fp2->nx = fpnew;
|
||||||
|
cp2 = (char *)&(fp2->nx);
|
||||||
|
if (cp2 + fp2->sz == cpnew) {
|
||||||
|
/* lower junk adjacent, merge */
|
||||||
|
fp2->sz += fpnew->sz + sizeof(size_t);
|
||||||
|
fp2->nx = fpnew->nx;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If there's a new topmost chunk, lower __brkval instead.
|
||||||
|
*/
|
||||||
|
for (fp1 = __flp, fp2 = 0;
|
||||||
|
fp1->nx != 0;
|
||||||
|
fp2 = fp1, fp1 = fp1->nx)
|
||||||
|
/* advance to entry just before end of list */;
|
||||||
|
cp2 = (char *)&(fp1->nx);
|
||||||
|
if (cp2 + fp1->sz == __brkval) {
|
||||||
|
if (fp2 == NULL)
|
||||||
|
/* Freelist is empty now. */
|
||||||
|
__flp = NULL;
|
||||||
|
else
|
||||||
|
fp2->nx = NULL;
|
||||||
|
__brkval = cp2 - sizeof(size_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
150
BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c
Normal file
150
BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/* Copyright (c) 2004, 2010 Joerg Wunsch
|
||||||
|
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: realloc.c 2127 2010-06-07 14:49:37Z joerg_wunsch $ */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sectionname.h"
|
||||||
|
#include "stdlib_private.h"
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
ATTRIBUTE_CLIB_SECTION
|
||||||
|
void *
|
||||||
|
realloc(void *ptr, size_t len)
|
||||||
|
{
|
||||||
|
struct __freelist *fp1, *fp2, *fp3, *ofp3;
|
||||||
|
char *cp, *cp1;
|
||||||
|
void *memp;
|
||||||
|
size_t s, incr;
|
||||||
|
|
||||||
|
/* Trivial case, required by C standard. */
|
||||||
|
if (ptr == 0)
|
||||||
|
return malloc(len);
|
||||||
|
|
||||||
|
cp1 = (char *)ptr;
|
||||||
|
cp1 -= sizeof(size_t);
|
||||||
|
fp1 = (struct __freelist *)cp1;
|
||||||
|
|
||||||
|
cp = (char *)ptr + len; /* new next pointer */
|
||||||
|
if (cp < cp1)
|
||||||
|
/* Pointer wrapped across top of RAM, fail. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See whether we are growing or shrinking. When shrinking,
|
||||||
|
* we split off a chunk for the released portion, and call
|
||||||
|
* free() on it. Therefore, we can only shrink if the new
|
||||||
|
* size is at least sizeof(struct __freelist) smaller than the
|
||||||
|
* previous size.
|
||||||
|
*/
|
||||||
|
if (len <= fp1->sz) {
|
||||||
|
/* The first test catches a possible unsigned int
|
||||||
|
* rollover condition. */
|
||||||
|
if (fp1->sz <= sizeof(struct __freelist) ||
|
||||||
|
len > fp1->sz - sizeof(struct __freelist))
|
||||||
|
return ptr;
|
||||||
|
fp2 = (struct __freelist *)cp;
|
||||||
|
fp2->sz = fp1->sz - len - sizeof(size_t);
|
||||||
|
fp1->sz = len;
|
||||||
|
free(&(fp2->nx));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we get here, we are growing. First, see whether there
|
||||||
|
* is space in the free list on top of our current chunk.
|
||||||
|
*/
|
||||||
|
incr = len - fp1->sz;
|
||||||
|
cp = (char *)ptr + fp1->sz;
|
||||||
|
fp2 = (struct __freelist *)cp;
|
||||||
|
for (s = 0, ofp3 = 0, fp3 = __flp;
|
||||||
|
fp3;
|
||||||
|
ofp3 = fp3, fp3 = fp3->nx) {
|
||||||
|
if (fp3 == fp2 && fp3->sz + sizeof(size_t) >= incr) {
|
||||||
|
/* found something that fits */
|
||||||
|
if (fp3->sz + sizeof(size_t) - incr > sizeof(struct __freelist)) {
|
||||||
|
/* split off a new freelist entry */
|
||||||
|
cp = (char *)ptr + len;
|
||||||
|
fp2 = (struct __freelist *)cp;
|
||||||
|
fp2->nx = fp3->nx;
|
||||||
|
fp2->sz = fp3->sz - incr;
|
||||||
|
fp1->sz = len;
|
||||||
|
} else {
|
||||||
|
/* it just fits, so use it entirely */
|
||||||
|
fp1->sz += fp3->sz + sizeof(size_t);
|
||||||
|
fp2 = fp3->nx;
|
||||||
|
}
|
||||||
|
if (ofp3)
|
||||||
|
ofp3->nx = fp2;
|
||||||
|
else
|
||||||
|
__flp = fp2;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Find the largest chunk on the freelist while
|
||||||
|
* walking it.
|
||||||
|
*/
|
||||||
|
if (fp3->sz > s)
|
||||||
|
s = fp3->sz;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If we are the topmost chunk in memory, and there was no
|
||||||
|
* large enough chunk on the freelist that could be re-used
|
||||||
|
* (by a call to malloc() below), quickly extend the
|
||||||
|
* allocation area if possible, without need to copy the old
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
if (__brkval == (char *)ptr + fp1->sz && len > s) {
|
||||||
|
cp1 = __malloc_heap_end;
|
||||||
|
cp = (char *)ptr + len;
|
||||||
|
if (cp1 == 0)
|
||||||
|
cp1 = STACK_POINTER() - __malloc_margin;
|
||||||
|
if (cp < cp1) {
|
||||||
|
__brkval = cp;
|
||||||
|
fp1->sz = len;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
/* If that failed, we are out of luck. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call malloc() for a new chunk, then copy over the data, and
|
||||||
|
* release the old region.
|
||||||
|
*/
|
||||||
|
if ((memp = malloc(len)) == 0)
|
||||||
|
return 0;
|
||||||
|
memcpy(memp, ptr, fp1->sz);
|
||||||
|
free(ptr);
|
||||||
|
return memp;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
/* Copyright (c) 2009 Atmel Corporation
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SECTIONNAME_H__
|
||||||
|
#define __SECTIONNAME_H__
|
||||||
|
|
||||||
|
/* Put all avr-libc functions in a common, unique sub-section name under .text. */
|
||||||
|
|
||||||
|
#define CLIB_SECTION .text.avr-libc
|
||||||
|
#define MLIB_SECTION .text.avr-libc.fplib
|
||||||
|
|
||||||
|
#define STR(x) _STR(x)
|
||||||
|
#define _STR(x) #x
|
||||||
|
|
||||||
|
#define ATTRIBUTE_CLIB_SECTION __attribute__ ((section (STR(CLIB_SECTION))))
|
||||||
|
#define ATTRIBUTE_MLIB_SECTION __attribute__ ((section (STR(MLIB_SECTION))))
|
||||||
|
|
||||||
|
#define ASSEMBLY_CLIB_SECTION .section CLIB_SECTION, "ax", @progbits
|
||||||
|
#define ASSEMBLY_MLIB_SECTION .section MLIB_SECTION, "ax", @progbits
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright (c) 2004, Joerg Wunsch
|
||||||
|
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: stdlib_private.h 1657 2008-03-24 17:11:08Z arcanum $ */
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
#if !defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
struct __freelist {
|
||||||
|
size_t sz;
|
||||||
|
struct __freelist *nx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern char *__brkval; /* first location not yet allocated */
|
||||||
|
extern struct __freelist *__flp; /* freelist pointer (head of freelist) */
|
||||||
|
extern size_t __malloc_margin; /* user-changeable before the first malloc() */
|
||||||
|
extern char *__malloc_heap_start;
|
||||||
|
extern char *__malloc_heap_end;
|
||||||
|
|
||||||
|
extern char __heap_start;
|
||||||
|
extern char __heap_end;
|
||||||
|
|
||||||
|
/* Needed for definition of AVR_STACK_POINTER_REG. */
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
#define STACK_POINTER() ((char *)AVR_STACK_POINTER_REG)
|
||||||
|
|
534
BootLoaders/Boards/orangerx/cores/xmega/binary.h
Normal file
534
BootLoaders/Boards/orangerx/cores/xmega/binary.h
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
/*
|
||||||
|
binary.h - Definitions for binary constants
|
||||||
|
Copyright (c) 2006 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Binary_h
|
||||||
|
#define Binary_h
|
||||||
|
|
||||||
|
#define B0 0
|
||||||
|
#define B00 0
|
||||||
|
#define B000 0
|
||||||
|
#define B0000 0
|
||||||
|
#define B00000 0
|
||||||
|
#define B000000 0
|
||||||
|
#define B0000000 0
|
||||||
|
#define B00000000 0
|
||||||
|
#define B1 1
|
||||||
|
#define B01 1
|
||||||
|
#define B001 1
|
||||||
|
#define B0001 1
|
||||||
|
#define B00001 1
|
||||||
|
#define B000001 1
|
||||||
|
#define B0000001 1
|
||||||
|
#define B00000001 1
|
||||||
|
#define B10 2
|
||||||
|
#define B010 2
|
||||||
|
#define B0010 2
|
||||||
|
#define B00010 2
|
||||||
|
#define B000010 2
|
||||||
|
#define B0000010 2
|
||||||
|
#define B00000010 2
|
||||||
|
#define B11 3
|
||||||
|
#define B011 3
|
||||||
|
#define B0011 3
|
||||||
|
#define B00011 3
|
||||||
|
#define B000011 3
|
||||||
|
#define B0000011 3
|
||||||
|
#define B00000011 3
|
||||||
|
#define B100 4
|
||||||
|
#define B0100 4
|
||||||
|
#define B00100 4
|
||||||
|
#define B000100 4
|
||||||
|
#define B0000100 4
|
||||||
|
#define B00000100 4
|
||||||
|
#define B101 5
|
||||||
|
#define B0101 5
|
||||||
|
#define B00101 5
|
||||||
|
#define B000101 5
|
||||||
|
#define B0000101 5
|
||||||
|
#define B00000101 5
|
||||||
|
#define B110 6
|
||||||
|
#define B0110 6
|
||||||
|
#define B00110 6
|
||||||
|
#define B000110 6
|
||||||
|
#define B0000110 6
|
||||||
|
#define B00000110 6
|
||||||
|
#define B111 7
|
||||||
|
#define B0111 7
|
||||||
|
#define B00111 7
|
||||||
|
#define B000111 7
|
||||||
|
#define B0000111 7
|
||||||
|
#define B00000111 7
|
||||||
|
#define B1000 8
|
||||||
|
#define B01000 8
|
||||||
|
#define B001000 8
|
||||||
|
#define B0001000 8
|
||||||
|
#define B00001000 8
|
||||||
|
#define B1001 9
|
||||||
|
#define B01001 9
|
||||||
|
#define B001001 9
|
||||||
|
#define B0001001 9
|
||||||
|
#define B00001001 9
|
||||||
|
#define B1010 10
|
||||||
|
#define B01010 10
|
||||||
|
#define B001010 10
|
||||||
|
#define B0001010 10
|
||||||
|
#define B00001010 10
|
||||||
|
#define B1011 11
|
||||||
|
#define B01011 11
|
||||||
|
#define B001011 11
|
||||||
|
#define B0001011 11
|
||||||
|
#define B00001011 11
|
||||||
|
#define B1100 12
|
||||||
|
#define B01100 12
|
||||||
|
#define B001100 12
|
||||||
|
#define B0001100 12
|
||||||
|
#define B00001100 12
|
||||||
|
#define B1101 13
|
||||||
|
#define B01101 13
|
||||||
|
#define B001101 13
|
||||||
|
#define B0001101 13
|
||||||
|
#define B00001101 13
|
||||||
|
#define B1110 14
|
||||||
|
#define B01110 14
|
||||||
|
#define B001110 14
|
||||||
|
#define B0001110 14
|
||||||
|
#define B00001110 14
|
||||||
|
#define B1111 15
|
||||||
|
#define B01111 15
|
||||||
|
#define B001111 15
|
||||||
|
#define B0001111 15
|
||||||
|
#define B00001111 15
|
||||||
|
#define B10000 16
|
||||||
|
#define B010000 16
|
||||||
|
#define B0010000 16
|
||||||
|
#define B00010000 16
|
||||||
|
#define B10001 17
|
||||||
|
#define B010001 17
|
||||||
|
#define B0010001 17
|
||||||
|
#define B00010001 17
|
||||||
|
#define B10010 18
|
||||||
|
#define B010010 18
|
||||||
|
#define B0010010 18
|
||||||
|
#define B00010010 18
|
||||||
|
#define B10011 19
|
||||||
|
#define B010011 19
|
||||||
|
#define B0010011 19
|
||||||
|
#define B00010011 19
|
||||||
|
#define B10100 20
|
||||||
|
#define B010100 20
|
||||||
|
#define B0010100 20
|
||||||
|
#define B00010100 20
|
||||||
|
#define B10101 21
|
||||||
|
#define B010101 21
|
||||||
|
#define B0010101 21
|
||||||
|
#define B00010101 21
|
||||||
|
#define B10110 22
|
||||||
|
#define B010110 22
|
||||||
|
#define B0010110 22
|
||||||
|
#define B00010110 22
|
||||||
|
#define B10111 23
|
||||||
|
#define B010111 23
|
||||||
|
#define B0010111 23
|
||||||
|
#define B00010111 23
|
||||||
|
#define B11000 24
|
||||||
|
#define B011000 24
|
||||||
|
#define B0011000 24
|
||||||
|
#define B00011000 24
|
||||||
|
#define B11001 25
|
||||||
|
#define B011001 25
|
||||||
|
#define B0011001 25
|
||||||
|
#define B00011001 25
|
||||||
|
#define B11010 26
|
||||||
|
#define B011010 26
|
||||||
|
#define B0011010 26
|
||||||
|
#define B00011010 26
|
||||||
|
#define B11011 27
|
||||||
|
#define B011011 27
|
||||||
|
#define B0011011 27
|
||||||
|
#define B00011011 27
|
||||||
|
#define B11100 28
|
||||||
|
#define B011100 28
|
||||||
|
#define B0011100 28
|
||||||
|
#define B00011100 28
|
||||||
|
#define B11101 29
|
||||||
|
#define B011101 29
|
||||||
|
#define B0011101 29
|
||||||
|
#define B00011101 29
|
||||||
|
#define B11110 30
|
||||||
|
#define B011110 30
|
||||||
|
#define B0011110 30
|
||||||
|
#define B00011110 30
|
||||||
|
#define B11111 31
|
||||||
|
#define B011111 31
|
||||||
|
#define B0011111 31
|
||||||
|
#define B00011111 31
|
||||||
|
#define B100000 32
|
||||||
|
#define B0100000 32
|
||||||
|
#define B00100000 32
|
||||||
|
#define B100001 33
|
||||||
|
#define B0100001 33
|
||||||
|
#define B00100001 33
|
||||||
|
#define B100010 34
|
||||||
|
#define B0100010 34
|
||||||
|
#define B00100010 34
|
||||||
|
#define B100011 35
|
||||||
|
#define B0100011 35
|
||||||
|
#define B00100011 35
|
||||||
|
#define B100100 36
|
||||||
|
#define B0100100 36
|
||||||
|
#define B00100100 36
|
||||||
|
#define B100101 37
|
||||||
|
#define B0100101 37
|
||||||
|
#define B00100101 37
|
||||||
|
#define B100110 38
|
||||||
|
#define B0100110 38
|
||||||
|
#define B00100110 38
|
||||||
|
#define B100111 39
|
||||||
|
#define B0100111 39
|
||||||
|
#define B00100111 39
|
||||||
|
#define B101000 40
|
||||||
|
#define B0101000 40
|
||||||
|
#define B00101000 40
|
||||||
|
#define B101001 41
|
||||||
|
#define B0101001 41
|
||||||
|
#define B00101001 41
|
||||||
|
#define B101010 42
|
||||||
|
#define B0101010 42
|
||||||
|
#define B00101010 42
|
||||||
|
#define B101011 43
|
||||||
|
#define B0101011 43
|
||||||
|
#define B00101011 43
|
||||||
|
#define B101100 44
|
||||||
|
#define B0101100 44
|
||||||
|
#define B00101100 44
|
||||||
|
#define B101101 45
|
||||||
|
#define B0101101 45
|
||||||
|
#define B00101101 45
|
||||||
|
#define B101110 46
|
||||||
|
#define B0101110 46
|
||||||
|
#define B00101110 46
|
||||||
|
#define B101111 47
|
||||||
|
#define B0101111 47
|
||||||
|
#define B00101111 47
|
||||||
|
#define B110000 48
|
||||||
|
#define B0110000 48
|
||||||
|
#define B00110000 48
|
||||||
|
#define B110001 49
|
||||||
|
#define B0110001 49
|
||||||
|
#define B00110001 49
|
||||||
|
#define B110010 50
|
||||||
|
#define B0110010 50
|
||||||
|
#define B00110010 50
|
||||||
|
#define B110011 51
|
||||||
|
#define B0110011 51
|
||||||
|
#define B00110011 51
|
||||||
|
#define B110100 52
|
||||||
|
#define B0110100 52
|
||||||
|
#define B00110100 52
|
||||||
|
#define B110101 53
|
||||||
|
#define B0110101 53
|
||||||
|
#define B00110101 53
|
||||||
|
#define B110110 54
|
||||||
|
#define B0110110 54
|
||||||
|
#define B00110110 54
|
||||||
|
#define B110111 55
|
||||||
|
#define B0110111 55
|
||||||
|
#define B00110111 55
|
||||||
|
#define B111000 56
|
||||||
|
#define B0111000 56
|
||||||
|
#define B00111000 56
|
||||||
|
#define B111001 57
|
||||||
|
#define B0111001 57
|
||||||
|
#define B00111001 57
|
||||||
|
#define B111010 58
|
||||||
|
#define B0111010 58
|
||||||
|
#define B00111010 58
|
||||||
|
#define B111011 59
|
||||||
|
#define B0111011 59
|
||||||
|
#define B00111011 59
|
||||||
|
#define B111100 60
|
||||||
|
#define B0111100 60
|
||||||
|
#define B00111100 60
|
||||||
|
#define B111101 61
|
||||||
|
#define B0111101 61
|
||||||
|
#define B00111101 61
|
||||||
|
#define B111110 62
|
||||||
|
#define B0111110 62
|
||||||
|
#define B00111110 62
|
||||||
|
#define B111111 63
|
||||||
|
#define B0111111 63
|
||||||
|
#define B00111111 63
|
||||||
|
#define B1000000 64
|
||||||
|
#define B01000000 64
|
||||||
|
#define B1000001 65
|
||||||
|
#define B01000001 65
|
||||||
|
#define B1000010 66
|
||||||
|
#define B01000010 66
|
||||||
|
#define B1000011 67
|
||||||
|
#define B01000011 67
|
||||||
|
#define B1000100 68
|
||||||
|
#define B01000100 68
|
||||||
|
#define B1000101 69
|
||||||
|
#define B01000101 69
|
||||||
|
#define B1000110 70
|
||||||
|
#define B01000110 70
|
||||||
|
#define B1000111 71
|
||||||
|
#define B01000111 71
|
||||||
|
#define B1001000 72
|
||||||
|
#define B01001000 72
|
||||||
|
#define B1001001 73
|
||||||
|
#define B01001001 73
|
||||||
|
#define B1001010 74
|
||||||
|
#define B01001010 74
|
||||||
|
#define B1001011 75
|
||||||
|
#define B01001011 75
|
||||||
|
#define B1001100 76
|
||||||
|
#define B01001100 76
|
||||||
|
#define B1001101 77
|
||||||
|
#define B01001101 77
|
||||||
|
#define B1001110 78
|
||||||
|
#define B01001110 78
|
||||||
|
#define B1001111 79
|
||||||
|
#define B01001111 79
|
||||||
|
#define B1010000 80
|
||||||
|
#define B01010000 80
|
||||||
|
#define B1010001 81
|
||||||
|
#define B01010001 81
|
||||||
|
#define B1010010 82
|
||||||
|
#define B01010010 82
|
||||||
|
#define B1010011 83
|
||||||
|
#define B01010011 83
|
||||||
|
#define B1010100 84
|
||||||
|
#define B01010100 84
|
||||||
|
#define B1010101 85
|
||||||
|
#define B01010101 85
|
||||||
|
#define B1010110 86
|
||||||
|
#define B01010110 86
|
||||||
|
#define B1010111 87
|
||||||
|
#define B01010111 87
|
||||||
|
#define B1011000 88
|
||||||
|
#define B01011000 88
|
||||||
|
#define B1011001 89
|
||||||
|
#define B01011001 89
|
||||||
|
#define B1011010 90
|
||||||
|
#define B01011010 90
|
||||||
|
#define B1011011 91
|
||||||
|
#define B01011011 91
|
||||||
|
#define B1011100 92
|
||||||
|
#define B01011100 92
|
||||||
|
#define B1011101 93
|
||||||
|
#define B01011101 93
|
||||||
|
#define B1011110 94
|
||||||
|
#define B01011110 94
|
||||||
|
#define B1011111 95
|
||||||
|
#define B01011111 95
|
||||||
|
#define B1100000 96
|
||||||
|
#define B01100000 96
|
||||||
|
#define B1100001 97
|
||||||
|
#define B01100001 97
|
||||||
|
#define B1100010 98
|
||||||
|
#define B01100010 98
|
||||||
|
#define B1100011 99
|
||||||
|
#define B01100011 99
|
||||||
|
#define B1100100 100
|
||||||
|
#define B01100100 100
|
||||||
|
#define B1100101 101
|
||||||
|
#define B01100101 101
|
||||||
|
#define B1100110 102
|
||||||
|
#define B01100110 102
|
||||||
|
#define B1100111 103
|
||||||
|
#define B01100111 103
|
||||||
|
#define B1101000 104
|
||||||
|
#define B01101000 104
|
||||||
|
#define B1101001 105
|
||||||
|
#define B01101001 105
|
||||||
|
#define B1101010 106
|
||||||
|
#define B01101010 106
|
||||||
|
#define B1101011 107
|
||||||
|
#define B01101011 107
|
||||||
|
#define B1101100 108
|
||||||
|
#define B01101100 108
|
||||||
|
#define B1101101 109
|
||||||
|
#define B01101101 109
|
||||||
|
#define B1101110 110
|
||||||
|
#define B01101110 110
|
||||||
|
#define B1101111 111
|
||||||
|
#define B01101111 111
|
||||||
|
#define B1110000 112
|
||||||
|
#define B01110000 112
|
||||||
|
#define B1110001 113
|
||||||
|
#define B01110001 113
|
||||||
|
#define B1110010 114
|
||||||
|
#define B01110010 114
|
||||||
|
#define B1110011 115
|
||||||
|
#define B01110011 115
|
||||||
|
#define B1110100 116
|
||||||
|
#define B01110100 116
|
||||||
|
#define B1110101 117
|
||||||
|
#define B01110101 117
|
||||||
|
#define B1110110 118
|
||||||
|
#define B01110110 118
|
||||||
|
#define B1110111 119
|
||||||
|
#define B01110111 119
|
||||||
|
#define B1111000 120
|
||||||
|
#define B01111000 120
|
||||||
|
#define B1111001 121
|
||||||
|
#define B01111001 121
|
||||||
|
#define B1111010 122
|
||||||
|
#define B01111010 122
|
||||||
|
#define B1111011 123
|
||||||
|
#define B01111011 123
|
||||||
|
#define B1111100 124
|
||||||
|
#define B01111100 124
|
||||||
|
#define B1111101 125
|
||||||
|
#define B01111101 125
|
||||||
|
#define B1111110 126
|
||||||
|
#define B01111110 126
|
||||||
|
#define B1111111 127
|
||||||
|
#define B01111111 127
|
||||||
|
#define B10000000 128
|
||||||
|
#define B10000001 129
|
||||||
|
#define B10000010 130
|
||||||
|
#define B10000011 131
|
||||||
|
#define B10000100 132
|
||||||
|
#define B10000101 133
|
||||||
|
#define B10000110 134
|
||||||
|
#define B10000111 135
|
||||||
|
#define B10001000 136
|
||||||
|
#define B10001001 137
|
||||||
|
#define B10001010 138
|
||||||
|
#define B10001011 139
|
||||||
|
#define B10001100 140
|
||||||
|
#define B10001101 141
|
||||||
|
#define B10001110 142
|
||||||
|
#define B10001111 143
|
||||||
|
#define B10010000 144
|
||||||
|
#define B10010001 145
|
||||||
|
#define B10010010 146
|
||||||
|
#define B10010011 147
|
||||||
|
#define B10010100 148
|
||||||
|
#define B10010101 149
|
||||||
|
#define B10010110 150
|
||||||
|
#define B10010111 151
|
||||||
|
#define B10011000 152
|
||||||
|
#define B10011001 153
|
||||||
|
#define B10011010 154
|
||||||
|
#define B10011011 155
|
||||||
|
#define B10011100 156
|
||||||
|
#define B10011101 157
|
||||||
|
#define B10011110 158
|
||||||
|
#define B10011111 159
|
||||||
|
#define B10100000 160
|
||||||
|
#define B10100001 161
|
||||||
|
#define B10100010 162
|
||||||
|
#define B10100011 163
|
||||||
|
#define B10100100 164
|
||||||
|
#define B10100101 165
|
||||||
|
#define B10100110 166
|
||||||
|
#define B10100111 167
|
||||||
|
#define B10101000 168
|
||||||
|
#define B10101001 169
|
||||||
|
#define B10101010 170
|
||||||
|
#define B10101011 171
|
||||||
|
#define B10101100 172
|
||||||
|
#define B10101101 173
|
||||||
|
#define B10101110 174
|
||||||
|
#define B10101111 175
|
||||||
|
#define B10110000 176
|
||||||
|
#define B10110001 177
|
||||||
|
#define B10110010 178
|
||||||
|
#define B10110011 179
|
||||||
|
#define B10110100 180
|
||||||
|
#define B10110101 181
|
||||||
|
#define B10110110 182
|
||||||
|
#define B10110111 183
|
||||||
|
#define B10111000 184
|
||||||
|
#define B10111001 185
|
||||||
|
#define B10111010 186
|
||||||
|
#define B10111011 187
|
||||||
|
#define B10111100 188
|
||||||
|
#define B10111101 189
|
||||||
|
#define B10111110 190
|
||||||
|
#define B10111111 191
|
||||||
|
#define B11000000 192
|
||||||
|
#define B11000001 193
|
||||||
|
#define B11000010 194
|
||||||
|
#define B11000011 195
|
||||||
|
#define B11000100 196
|
||||||
|
#define B11000101 197
|
||||||
|
#define B11000110 198
|
||||||
|
#define B11000111 199
|
||||||
|
#define B11001000 200
|
||||||
|
#define B11001001 201
|
||||||
|
#define B11001010 202
|
||||||
|
#define B11001011 203
|
||||||
|
#define B11001100 204
|
||||||
|
#define B11001101 205
|
||||||
|
#define B11001110 206
|
||||||
|
#define B11001111 207
|
||||||
|
#define B11010000 208
|
||||||
|
#define B11010001 209
|
||||||
|
#define B11010010 210
|
||||||
|
#define B11010011 211
|
||||||
|
#define B11010100 212
|
||||||
|
#define B11010101 213
|
||||||
|
#define B11010110 214
|
||||||
|
#define B11010111 215
|
||||||
|
#define B11011000 216
|
||||||
|
#define B11011001 217
|
||||||
|
#define B11011010 218
|
||||||
|
#define B11011011 219
|
||||||
|
#define B11011100 220
|
||||||
|
#define B11011101 221
|
||||||
|
#define B11011110 222
|
||||||
|
#define B11011111 223
|
||||||
|
#define B11100000 224
|
||||||
|
#define B11100001 225
|
||||||
|
#define B11100010 226
|
||||||
|
#define B11100011 227
|
||||||
|
#define B11100100 228
|
||||||
|
#define B11100101 229
|
||||||
|
#define B11100110 230
|
||||||
|
#define B11100111 231
|
||||||
|
#define B11101000 232
|
||||||
|
#define B11101001 233
|
||||||
|
#define B11101010 234
|
||||||
|
#define B11101011 235
|
||||||
|
#define B11101100 236
|
||||||
|
#define B11101101 237
|
||||||
|
#define B11101110 238
|
||||||
|
#define B11101111 239
|
||||||
|
#define B11110000 240
|
||||||
|
#define B11110001 241
|
||||||
|
#define B11110010 242
|
||||||
|
#define B11110011 243
|
||||||
|
#define B11110100 244
|
||||||
|
#define B11110101 245
|
||||||
|
#define B11110110 246
|
||||||
|
#define B11110111 247
|
||||||
|
#define B11111000 248
|
||||||
|
#define B11111001 249
|
||||||
|
#define B11111010 250
|
||||||
|
#define B11111011 251
|
||||||
|
#define B11111100 252
|
||||||
|
#define B11111101 253
|
||||||
|
#define B11111110 254
|
||||||
|
#define B11111111 255
|
||||||
|
|
||||||
|
#endif
|
68
BootLoaders/Boards/orangerx/cores/xmega/main.cpp
Normal file
68
BootLoaders/Boards/orangerx/cores/xmega/main.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
main.cpp - Main loop for Arduino sketches
|
||||||
|
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include <Arduino.h> Platform.h includes Arduino.h
|
||||||
|
#include <Platform.h> /* to make sure that Arduino.h is included, as well as pins_arduino.h and other things */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef EIND
|
||||||
|
// if I have an EIND register, I want it pre-loaded with the correct value
|
||||||
|
// for info on THIS thing, see http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
|
||||||
|
// in essence, 'init3' section functions run just before 'main()'
|
||||||
|
|
||||||
|
// must prototype it to get all of the attributes
|
||||||
|
static void __attribute__((section(".init3"),naked,used,no_instrument_function)) init3_set_eind (void);
|
||||||
|
|
||||||
|
void init3_set_eind (void)
|
||||||
|
{
|
||||||
|
__asm volatile ("ldi r24,pm_hh8(__trampolines_start)\n\t"
|
||||||
|
"out %i0,r24" :: "n" (&EIND) : "r24","memory");
|
||||||
|
}
|
||||||
|
#endif // EIND
|
||||||
|
|
||||||
|
//Declared weak in Arduino.h to allow user redefinitions.
|
||||||
|
int atexit(void (*func)()) { return 0; }
|
||||||
|
|
||||||
|
// Weak empty variant initialization function.
|
||||||
|
// May be redefined by variant files.
|
||||||
|
void initVariant() __attribute__((weak));
|
||||||
|
void initVariant() { }
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
initVariant();
|
||||||
|
|
||||||
|
// TEMPORARY - moved [so I can debug it]
|
||||||
|
//#if defined(USBCON)
|
||||||
|
// USBDevice.attach();
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
loop();
|
||||||
|
if (serialEventRun) serialEventRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
28
BootLoaders/Boards/orangerx/cores/xmega/new.cpp
Normal file
28
BootLoaders/Boards/orangerx/cores/xmega/new.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <new.h>
|
||||||
|
|
||||||
|
void * operator new(size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void * operator new[](size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void * ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void * ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
|
||||||
|
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
|
||||||
|
void __cxa_guard_abort (__guard *) {};
|
||||||
|
|
||||||
|
void __cxa_pure_virtual(void) {};
|
||||||
|
|
24
BootLoaders/Boards/orangerx/cores/xmega/new.h
Normal file
24
BootLoaders/Boards/orangerx/cores/xmega/new.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* Header to define new/delete operators as they aren't provided by avr-gcc by default
|
||||||
|
Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NEW_H
|
||||||
|
#define NEW_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void * operator new(size_t size);
|
||||||
|
void * operator new[](size_t size);
|
||||||
|
void operator delete(void * ptr);
|
||||||
|
void operator delete[](void * ptr);
|
||||||
|
|
||||||
|
__extension__ typedef int __guard __attribute__((mode (__DI__)));
|
||||||
|
|
||||||
|
extern "C" int __cxa_guard_acquire(__guard *);
|
||||||
|
extern "C" void __cxa_guard_release (__guard *);
|
||||||
|
extern "C" void __cxa_guard_abort (__guard *);
|
||||||
|
|
||||||
|
extern "C" void __cxa_pure_virtual(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1088
BootLoaders/Boards/orangerx/cores/xmega/wiring.c
Normal file
1088
BootLoaders/Boards/orangerx/cores/xmega/wiring.c
Normal file
File diff suppressed because it is too large
Load Diff
859
BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c
Normal file
859
BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c
Normal file
@ -0,0 +1,859 @@
|
|||||||
|
/*
|
||||||
|
wiring_analog.c - analog input and output
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
|
||||||
|
Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
|
||||||
|
In some cases, the xmega updates make assumptions about the pin assignments.
|
||||||
|
See 'pins_arduino.h' for more detail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
//#define DEBUG_CODE
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
extern void DebugOutL(unsigned long lVal);
|
||||||
|
extern void DebugOutP(const void * PROGMEM pStr);
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
|
||||||
|
#ifndef ADCA_SAMPCTRL
|
||||||
|
#define ADCA_SAMPCTRL _SFR_MEM8(0x0208) /* missing from header for some reason, struct defines it as reserved_0x08 */
|
||||||
|
#endif // ADCA_SAMPCTRL
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t analog_reference, muxctrl_muxneg; // = ADC_REFSEL2_bp;// the default analog reference is Vcc / 2 (now assigned in adc_setup)
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: On the A-series processors with more than a handful of inputs,
|
||||||
|
// it is NOT possible to use 'diff input with gain' on MORE than
|
||||||
|
// A0-A7. On later processors (like D series) it _IS_ possible.
|
||||||
|
// Because of this, the 'hack' that allows rail-rail measurements
|
||||||
|
// is no longer possible on PB0-PB7. PA0-PA7 will still work.
|
||||||
|
// IF PA0 or PB0 is used as VRef (see 28.16.3 in AU manual) via 'REFCTRL'
|
||||||
|
// then you can read all 15 remaining values with whatever VRef you want.
|
||||||
|
|
||||||
|
// adc_setup() - call this from init() and whenever you wake up from sleep mode
|
||||||
|
void adc_setup(void)
|
||||||
|
{
|
||||||
|
// calibration is a 16-bit register - CAL0 + (CAL1 << 8)
|
||||||
|
ADCA_CAL = (uint16_t)readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_ADCACAL0)
|
||||||
|
| (((uint16_t)readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_ADCACAL1)) << 8);
|
||||||
|
|
||||||
|
// must make sure power reduction register enables the ADC
|
||||||
|
PR_PRPA &= ~PR_ADC_bm; // clear this bit to enable the ADC clock
|
||||||
|
|
||||||
|
// assign clock prescaler for 100khz, and clear the interrupt bit
|
||||||
|
// also make sure the 'interrupt enable' is OFF
|
||||||
|
|
||||||
|
ADCA_EVCTRL = 0; // no triggering events (sect 22.14.4)
|
||||||
|
|
||||||
|
ADCA_PRESCALER = ADC_PRESCALER_DIV256_gc; // 100khz, approximately, for 32Mhz clock
|
||||||
|
|
||||||
|
ADCA_CTRLA = _BV(ADC_ENABLE_bp); // enables the ADC
|
||||||
|
ADCA_CTRLB = _BV(6) | _BV(4); // medium current limit, signed mode [temporary]
|
||||||
|
// _BV(6) | _BV(5); // section 22.14.2, 'HIGH' current limit, no apparent bit value constants in iox64d4.h
|
||||||
|
// NOTE: all other bits are zero - no 'freerun', 12-bit right-justified unsigned mode
|
||||||
|
|
||||||
|
analog_reference = 1; // which is NONE of the possibilities
|
||||||
|
ADCA_REFCTRL = 0; // pre-assign zero to this, as I'll OR bits into it
|
||||||
|
|
||||||
|
#ifdef USE_AREF
|
||||||
|
analogReference(USE_AREF);
|
||||||
|
#else // everything else - NOTE: do I want to do this different for 'A' series?
|
||||||
|
analogReference(analogReference_VCCDIV2);
|
||||||
|
#endif // USE_AREF
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: is this actually a RESERVED functionality?
|
||||||
|
ADCA_SAMPCTRL = 24; // sect 22.14.8 - this value + 1 is # of "half cycles" used for sampling
|
||||||
|
// in this case, it's 25 "half cycles" at 100khz, or appx 8khz (125uS)
|
||||||
|
// adjust this for 'best accuracy' without taking for-freaking-evar
|
||||||
|
// also make sure the sample rate is lower than the 'HIGH LIMIT' max rate (see 22.14.2)
|
||||||
|
|
||||||
|
// set up the channel (no offset calc at this time - later do an offset calc)
|
||||||
|
ADCA_CH0_SCAN = 0; // disable scan
|
||||||
|
ADCA_CH0_INTCTRL = 0; // no interrupts, flag on complete sect 22.15.3
|
||||||
|
|
||||||
|
|
||||||
|
// clear interrupt flag (probably not needed)
|
||||||
|
ADCA_INTFLAGS = _BV(ADC_CH0IF_bp); // write a 1 to the interrupt bit (which clears it - 22.14.6)
|
||||||
|
|
||||||
|
analogRead(0); // do a single conversion so that everything stabilizes
|
||||||
|
|
||||||
|
// these are taken care of at the beginning of the function, as a 16-bit register assignment to ADCA_CAL
|
||||||
|
// ADCA.CALL = readCalibrationData(&PRODSIGNATURES_ADCACAL0);
|
||||||
|
// ADCA.CALH = readCalibrationData(&PRODSIGNATURES_ADCACAL1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// see _analogReference_ enum
|
||||||
|
|
||||||
|
static uint8_t normal_adca_ch0_ctrl_bits(void) // also assigns 'muxctrl_muxneg'
|
||||||
|
{
|
||||||
|
#if defined (__AVR_ATxmega8E5__) || defined (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__)
|
||||||
|
|
||||||
|
// NOTE: the E5 has a significant difference in how it handles 'DIFF WITH GAIN'
|
||||||
|
// ADC_CH_INPUTMODE_DIFFWGAINL_gc uses A0-A3, GND, and internal GND (not same as D and earlier)
|
||||||
|
// ADC_CH_INPUTMODE_DIFFWGAINH_gc uses A4-A7 and GND (see E manual table 24-16,17 pg 366-7) (similar to D and earlier)
|
||||||
|
|
||||||
|
if(analog_reference == analogReference_VCCDIV2)
|
||||||
|
{
|
||||||
|
return ADC_CH_INPUTMODE_DIFFWGAINH_gc | ADC_CH_GAIN_DIV2_gc; // gain of 1/2 for VCC/2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ADC_CH_INPUTMODE_DIFFWGAINH_gc | ADC_CH_GAIN_1X_gc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // everything NOT an 'E' series
|
||||||
|
|
||||||
|
if(analog_reference == analogReference_VCCDIV2)
|
||||||
|
{
|
||||||
|
// NOTE: On the A-series processors with more than a handful of inputs,
|
||||||
|
// it is NOT possible to use 'diff input with gain' on MORE than
|
||||||
|
// A0-A7. On later processors (like D series) it _IS_ possible.
|
||||||
|
// Because of this, the 'hack' that allows rail-rail measurements
|
||||||
|
// is no longer possible on PB0-PB7. PA0-PA7 will still work.
|
||||||
|
// IF PA0 or PB0 is used as VRef (see 28.16.3 in AU manual) via 'REFCTRL'
|
||||||
|
// then you can read all 15 remaining values with whatever VRef you want.
|
||||||
|
|
||||||
|
return ADC_CH_INPUTMODE_DIFFWGAIN_gc | ADC_CH_GAIN_DIV2_gc; // gain of 1/2 for VCC/2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: this one uses a different 'muxneg' (see below, 'analogReference()')
|
||||||
|
|
||||||
|
return ADC_CH_INPUTMODE_DIFF_gc | ADC_CH_GAIN_1X_gc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // E series or not
|
||||||
|
}
|
||||||
|
|
||||||
|
void analogReference(uint8_t bMode)
|
||||||
|
{
|
||||||
|
if((bMode & ADC_REFSEL_gm) != bMode)
|
||||||
|
{
|
||||||
|
bMode &= ADC_REFSEL_gm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bMode != analog_reference)
|
||||||
|
{
|
||||||
|
analog_reference = bMode;
|
||||||
|
|
||||||
|
// changes to this must be reflected in ADCA_REFCTRL and ADCA_CH0_MUXCTRL
|
||||||
|
// when I read a specific pin. I assign the 'muxneg' bits according muxctrl_muxneg
|
||||||
|
|
||||||
|
ADCA_REFCTRL = (ADCA_REFCTRL & ~(ADC_REFSEL_gm))
|
||||||
|
| analog_reference // section 22.14.3, or 28.16.3 in 'AU' manual
|
||||||
|
| ADC_BANDGAP_bm; // enable 'bandgap' i.e. 1V reference
|
||||||
|
|
||||||
|
// NOTE: all other ADCA_REFCTRL bits are zero (like tempref) - section 22.14.3
|
||||||
|
|
||||||
|
// ASSIGNING ADCA_CH0_CTRL and muxctrl_muxneg
|
||||||
|
|
||||||
|
ADCA_CH0_CTRL = normal_adca_ch0_ctrl_bits();
|
||||||
|
|
||||||
|
// assign 'muxneg' according to what teh analog reference is
|
||||||
|
|
||||||
|
#if defined (__AVR_ATxmega8E5__) || (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__)
|
||||||
|
|
||||||
|
muxctrl_muxneg = 7; /* bits 111 which is GND for MUXNEG - see E manual 24.15.2 */
|
||||||
|
|
||||||
|
#else // everything NOT an 'E' series
|
||||||
|
|
||||||
|
if(analog_reference == analogReference_VCCDIV2)
|
||||||
|
{
|
||||||
|
// analog delta WITH GAIN always uses this
|
||||||
|
muxctrl_muxneg = 7; /* bits 111 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// analog delta WITHOUT GAIN uses THIS
|
||||||
|
muxctrl_muxneg = 5; /* bits 101 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // E series or not
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For 100% atmega compatibility, analogRead will return a value of 0-1023
|
||||||
|
// for input voltages of 0 to Vcc (assuming AVCC is connected to VCC, etc.)
|
||||||
|
// by using a gain of 1/2, a comparison of Vcc/2, and signed conversion
|
||||||
|
|
||||||
|
int analogRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
short iRval;
|
||||||
|
|
||||||
|
// this is pure XMEGA code
|
||||||
|
|
||||||
|
if(pin >= A0)
|
||||||
|
{
|
||||||
|
if(pin >= (NUM_ANALOG_INPUTS + A0)) // pin number too high?
|
||||||
|
{
|
||||||
|
return 0; // not a valid analog input
|
||||||
|
}
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
pin = analogInputToAnalogPin(pin);
|
||||||
|
#else // analogInputToAnalogPin
|
||||||
|
pin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: for pins less than 'A0', assume it's referring to the analog index (0 to NUM_ANALOG_INPUTS-1)
|
||||||
|
|
||||||
|
if(pin >= NUM_ANALOG_INPUTS)
|
||||||
|
{
|
||||||
|
return 0; // not a valid analog input
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
pin = analogInputToAnalogPin(pin + A0); // calc pin number (might not have 0 mapped to A0)
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANALOG REFERENCE - in some cases I can map one of the analog inputs
|
||||||
|
// as an analog reference. For now, assume it's Vcc/2.
|
||||||
|
|
||||||
|
// NOTE: On the A-series processors with more than a handful of inputs,
|
||||||
|
// it is NOT possible to use 'diff input with gain' on MORE than
|
||||||
|
// A0-A7. On later processors (like D series) it _IS_ possible.
|
||||||
|
// Because of this, the 'hack' that allows rail-rail measurements
|
||||||
|
// is no longer possible on PB0-PB7. PA0-PA7 will still work.
|
||||||
|
// IF PA0 or PB0 is used as VRef (see 28.16.3 in AU manual) via 'REFCTRL'
|
||||||
|
// then you can read all 15 remaining values with whatever VRef you want.
|
||||||
|
|
||||||
|
|
||||||
|
ADCA_CH0_SCAN = 0; // disable scan
|
||||||
|
ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual
|
||||||
|
| muxctrl_muxneg; // typically, GND is the 'other input' (change via 'analogReference()')
|
||||||
|
|
||||||
|
ADCA_CH0_INTCTRL = 0; // no interrupts, flag on complete sect 22.15.3
|
||||||
|
|
||||||
|
#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */
|
||||||
|
ADCA_CH0_INTFLAGS = ADC_CH_IF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4)
|
||||||
|
#else // everyone else
|
||||||
|
ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4)
|
||||||
|
#endif // ADC_CH_IF_bm
|
||||||
|
|
||||||
|
// NOTE: this will clear any re-assigned gain bits, etc.
|
||||||
|
// (if you want to preserve those, need to call 'analogReadDeltaWithGain()')
|
||||||
|
|
||||||
|
ADCA_CH0_CTRL = normal_adca_ch0_ctrl_bits()
|
||||||
|
| ADC_CH_START_bm; // conversion start (bit will clear itself I think)
|
||||||
|
|
||||||
|
#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */
|
||||||
|
while(!(ADCA_CH0_INTFLAGS & ADC_CH_IF_bm)) { }
|
||||||
|
#else // everyone else
|
||||||
|
while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm)) { }
|
||||||
|
#endif // ADC_CH_IF_bm
|
||||||
|
|
||||||
|
iRval = ADCA_CH0_RES;
|
||||||
|
|
||||||
|
if(iRval < 0) // backward compatibility
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iRval / 2; // -1023 to 1023 but clipped at zero (so 0 to 1023 only)
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS function returns a full 12-bit signed integer value (no scaling)
|
||||||
|
int analogReadDeltaWithGain(uint8_t pin, uint8_t negpin, uint8_t gain)
|
||||||
|
{
|
||||||
|
short iRval;
|
||||||
|
uint8_t mode;
|
||||||
|
|
||||||
|
// this is pure XMEGA code
|
||||||
|
// NOTE: On the A-series processors with more than a handful of inputs,
|
||||||
|
// it is NOT possible to use 'diff input with gain' on MORE than
|
||||||
|
// A0-A7. On later processors (like D series) it _IS_ possible.
|
||||||
|
|
||||||
|
// TODO: check for A0-A7 for 'pin' for A series?
|
||||||
|
|
||||||
|
|
||||||
|
if(pin >= A0)
|
||||||
|
{
|
||||||
|
if(pin >= (NUM_ANALOG_INPUTS + A0)) // pin number too high?
|
||||||
|
{
|
||||||
|
return 0; // not a valid analog input
|
||||||
|
}
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
pin = analogInputToAnalogPin(pin);
|
||||||
|
#else // analogInputToAnalogPin
|
||||||
|
pin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: for pins less than 'A0', assume it's referring to the analog index (0 to NUM_ANALOG_INPUTS-1)
|
||||||
|
|
||||||
|
if(pin >= NUM_ANALOG_INPUTS)
|
||||||
|
{
|
||||||
|
return 0; // not a valid analog input
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
pin = analogInputToAnalogPin(pin + A0); // calc pin number (might not have 0 mapped to A0)
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (__AVR_ATxmega8E5__) || defined (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__)
|
||||||
|
|
||||||
|
// NOTE: the E5 has a significant difference in how it handles 'DIFF WITH GAIN'
|
||||||
|
// ADC_CH_INPUTMODE_DIFFWGAINL_gc uses A0-A3, GND, and internal GND (not same as D and earlier)
|
||||||
|
// ADC_CH_INPUTMODE_DIFFWGAINH_gc uses A4-A7 and GND (see E manual table 24-16,17 pg 366-7) (similar to D and earlier)
|
||||||
|
|
||||||
|
if(negpin != ANALOG_READ_DELTA_USE_GND)
|
||||||
|
{
|
||||||
|
if(negpin >= A0)
|
||||||
|
{
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
negpin = analogInputToAnalogPin(negpin);
|
||||||
|
#else // analogInputToAnalogPin
|
||||||
|
negpin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(negpin >= NUM_ANALOG_INPUTS)
|
||||||
|
{
|
||||||
|
return 0; // not a valid analog input
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
negpin = analogInputToAnalogPin(negpin + A0); // calc pin number (might not have 0 mapped to A0)
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
|
||||||
|
if(negpin >= 0 && negpin <= 3)
|
||||||
|
{
|
||||||
|
mode = ADC_CH_INPUTMODE_DIFFWGAINL_gc;
|
||||||
|
}
|
||||||
|
else if(negpin > 7)
|
||||||
|
{
|
||||||
|
return 0; // dis-allowed combination
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = ADC_CH_INPUTMODE_DIFFWGAINH_gc;
|
||||||
|
|
||||||
|
negpin -= 4; // so that it's 0-3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = ADC_CH_INPUTMODE_DIFFWGAINL_gc; // see 24.15.2 section on 'MUXNEG' when using INTERNAL GND or PAD GND
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // NOT an 'E5'
|
||||||
|
|
||||||
|
mode = ADC_CH_INPUTMODE_DIFFWGAIN_gc;
|
||||||
|
|
||||||
|
// now for the negative pin, which will depend on a number of things
|
||||||
|
if(negpin != ANALOG_READ_DELTA_USE_GND)
|
||||||
|
{
|
||||||
|
if(negpin >= A0)
|
||||||
|
{
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
negpin = analogInputToAnalogPin(negpin);
|
||||||
|
#else // analogInputToAnalogPin
|
||||||
|
negpin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(negpin >= NUM_ANALOG_INPUTS)
|
||||||
|
{
|
||||||
|
return 0; // not a valid analog input
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef analogInputToAnalogPin
|
||||||
|
negpin = analogInputToAnalogPin(negpin + A0); // calc pin number (might not have 0 mapped to A0)
|
||||||
|
#endif // analogInputToAnalogPin
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(negpin >= 0 && negpin <= 3 && gain != ADC_CH_GAIN_1X_gc) // allow this *IF* gain is 1X
|
||||||
|
{
|
||||||
|
return 0; // dis-allowed combination
|
||||||
|
}
|
||||||
|
else if(negpin >= 0 && negpin <= 3)
|
||||||
|
{
|
||||||
|
mode = ADC_CH_INPUTMODE_DIFF_gc; // just 'diff' mode, with 1X gain, for A0 to A3
|
||||||
|
}
|
||||||
|
else if(negpin > 7)
|
||||||
|
{
|
||||||
|
return 0; // dis-allowed combination
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
negpin -= 4; // so that it's 0-3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // 'E' series, or not
|
||||||
|
|
||||||
|
ADCA_CH0_SCAN = 0; // disable scan
|
||||||
|
|
||||||
|
// NOTE: assume 'CONVMODE' (CTRLB) is set to 'Signed'
|
||||||
|
if(negpin == ANALOG_READ_DELTA_USE_GND)
|
||||||
|
{
|
||||||
|
#if defined (__AVR_ATxmega8E5__) || (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__)
|
||||||
|
ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual
|
||||||
|
| 7; /* bits 111 which is GND for MUXNEG - see E manual 24.15.2 */
|
||||||
|
#else // everything NOT an 'E' series
|
||||||
|
if(mode == ADC_CH_INPUTMODE_DIFFWGAIN_gc)
|
||||||
|
{
|
||||||
|
ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual
|
||||||
|
| 7; /* bits 111 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual
|
||||||
|
| 5; /* bits 101 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */
|
||||||
|
}
|
||||||
|
#endif // E series or not
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual
|
||||||
|
| negpin; // DIFF or 'DIFF WITH GAIN' uses this
|
||||||
|
}
|
||||||
|
|
||||||
|
ADCA_CH0_INTCTRL = 0; // no interrupts, flag on complete sect 22.15.3
|
||||||
|
|
||||||
|
#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */
|
||||||
|
ADCA_CH0_INTFLAGS = ADC_CH_IF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4)
|
||||||
|
#else // everyone else
|
||||||
|
ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4)
|
||||||
|
#endif // ADC_CH_IF_bm
|
||||||
|
|
||||||
|
|
||||||
|
if(negpin == ANALOG_READ_DELTA_USE_GND)
|
||||||
|
{
|
||||||
|
// NOTE: On the A-series processors with more than a handful of inputs,
|
||||||
|
// it is NOT possible to use 'diff input with gain' on MORE than
|
||||||
|
// A0-A7. On later processors (like D series) it _IS_ possible.
|
||||||
|
|
||||||
|
ADCA_CH0_CTRL = mode // ADC_CH_INPUTMODE_DIFFWGAIN_gc
|
||||||
|
| (gain & ADC_CH_GAIN_gm)
|
||||||
|
| ADC_CH_START_bm; // conversion start (bit will clear itself I think)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADCA_CH0_CTRL = mode // ADC_CH_INPUTMODE_DIFFWGAIN_gc
|
||||||
|
| (gain & ADC_CH_GAIN_gm)
|
||||||
|
| ADC_CH_START_bm; // conversion start (bit will clear itself I think)
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */
|
||||||
|
while(!(ADCA_CH0_INTFLAGS & ADC_CH_IF_bm)) { }
|
||||||
|
#else // everyone else
|
||||||
|
while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm)) { }
|
||||||
|
#endif // ADC_CH_IF_bm
|
||||||
|
|
||||||
|
iRval = ADCA_CH0_RES;
|
||||||
|
|
||||||
|
// TODO: scaling and clipping if needed, else +/- 2047
|
||||||
|
|
||||||
|
return iRval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Right now, PWM output only works on the pins with hardware support.
|
||||||
|
// These are defined in the appropriate pins_arduino.h file. For the
|
||||||
|
// rest of the pins, we default to digital output with a 1 or 0
|
||||||
|
|
||||||
|
#ifdef TCC4
|
||||||
|
static void DoAnalogWriteForPort(TC4_t *port, uint8_t bit, uint8_t val);
|
||||||
|
#elif defined(TCC2)
|
||||||
|
static void DoAnalogWriteForPort(TC2_t *port, uint8_t bit, uint8_t val);
|
||||||
|
#else // TCC0
|
||||||
|
static void DoAnalogWriteForPort(TC0_t *port, uint8_t bit, uint8_t val);
|
||||||
|
#endif // TCC4, TCC2, TCC0
|
||||||
|
|
||||||
|
// NOTE: for the xxE5, only 3, 4, 8, 9 seem to work properly with the default configuration
|
||||||
|
// that would be PORTD pins 4 and 5, and PORTC pins 2 and 3. PORTC pins 0 and 1
|
||||||
|
// are mapped to the TWI pins SDA and SCL. As such, PORTD pins 4 and 5, and PORTC pins 0-3
|
||||||
|
// will be allowed. Others will not. PORTD pins 6 and 7 are 'erratic' at best.
|
||||||
|
|
||||||
|
void analogWrite(uint8_t pin, int val)
|
||||||
|
{
|
||||||
|
// We need to make sure the PWM output is enabled for those pins
|
||||||
|
// that support it, as we turn it off when digitally reading or
|
||||||
|
// writing with them. Also, make sure the pin is in output mode
|
||||||
|
// for consistenty with Wiring, which doesn't require a pinMode
|
||||||
|
// call for the analog output pins.
|
||||||
|
|
||||||
|
// NOTE: period registers all contain zeros, which is the MAXIMUM period of 0-255
|
||||||
|
#ifdef TCC4 /* 'E' series and later that have TCC4 */
|
||||||
|
uint8_t mode;
|
||||||
|
#endif // TCC4
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
|
||||||
|
pinMode(pin, OUTPUT); // forces 'totem pole' - TODO allow for something different?
|
||||||
|
|
||||||
|
// note 'val' is a SIGNED INTEGER. deal with 'out of range' values accordingly
|
||||||
|
|
||||||
|
if (val <= 0)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
else if (val >= 255)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: according to the docs, 16-bit registers MUST be accessed
|
||||||
|
// low byte first, then high byte, before the actual value
|
||||||
|
// is transferred to the register. THIS code will.
|
||||||
|
// see A1U manual sect. 3.11 (and others as well)
|
||||||
|
|
||||||
|
switch(digitalPinToTimer(pin))
|
||||||
|
{
|
||||||
|
#ifdef TCC4 /* 'E' series and later that have TCC4 */
|
||||||
|
|
||||||
|
case TIMERC4:
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
DebugOutP(PSTR("TIMERC4 "));
|
||||||
|
DebugOutL(bit);
|
||||||
|
DebugOutP(PSTR(","));
|
||||||
|
DebugOutL(val);
|
||||||
|
DebugOutP(PSTR("\r\n"));
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
|
||||||
|
DoAnalogWriteForPort(&TCC4, bit, val); // TODO: smaller if inlined here?
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TIMERD5:
|
||||||
|
// THIS code is unique to the E5, most likely, so it's inlined
|
||||||
|
if(bit == 1 || bit == 16) // TODO: either bit? not sure if I can re-map these to 0-3
|
||||||
|
{
|
||||||
|
*((volatile uint16_t *)&(TCD5_CCA)) = (TCD5_CCA & 0xff00) | (val & 0xff);
|
||||||
|
mode = (TCD5_CTRLE & ~TC5_LCCAMODE_gm) | TC5_LCCAMODE0_bm;
|
||||||
|
}
|
||||||
|
else if(bit == 2 || bit == 32)
|
||||||
|
{
|
||||||
|
*((volatile uint16_t *)&(TCD5_CCB)) = (TCD5_CCB & 0xff00) | (val & 0xff);
|
||||||
|
mode = (TCD5_CTRLE & ~TC5_LCCBMODE_gm) | TC5_LCCBMODE0_bm;
|
||||||
|
}
|
||||||
|
else if(bit == 4 || bit == 64)
|
||||||
|
{
|
||||||
|
*((volatile uint16_t *)&(TCD5_CCA)) = (TCD5_CCA & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
mode = (TCD5_CTRLF & ~TC5_HCCAMODE_gm) | TC5_HCCAMODE0_bm;
|
||||||
|
}
|
||||||
|
else if(bit == 8 || bit == 128)
|
||||||
|
{
|
||||||
|
*((volatile uint16_t *)&(TCD5_CCB)) = (TCD5_CCB & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
mode = (TCD5_CTRLF & ~TC5_HCCBMODE_gm) | TC5_HCCBMODE0_bm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
DebugOutP(PSTR("TIMERD5 "));
|
||||||
|
DebugOutL(bit);
|
||||||
|
DebugOutP(PSTR(","));
|
||||||
|
DebugOutL(val);
|
||||||
|
DebugOutP(PSTR(","));
|
||||||
|
DebugOutL(TCD5_CCA);
|
||||||
|
DebugOutP(PSTR(","));
|
||||||
|
DebugOutL(TCD5_CCB);
|
||||||
|
DebugOutP(PSTR(","));
|
||||||
|
DebugOutL(mode);
|
||||||
|
DebugOutP(PSTR("\r\n"));
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
|
||||||
|
if(bit == 1 || bit == 2 || bit == 16 || bit == 32)
|
||||||
|
{
|
||||||
|
*((volatile uint8_t *)&(TCD5_CTRLE)) = mode;
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
DebugOutP(PSTR("E!\r\n"));
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*((volatile uint8_t *)&(TCD5_CTRLF)) = mode;
|
||||||
|
#ifdef DEBUG_CODE
|
||||||
|
DebugOutP(PSTR("F!\r\n"));
|
||||||
|
#endif // DEBUG_CODE
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#else // everything else NOT an 'E' series
|
||||||
|
|
||||||
|
case TIMERD2:
|
||||||
|
#ifndef TCD2
|
||||||
|
DoAnalogWriteForPort(&TCD0, bit, val);
|
||||||
|
#else // TCD2 defined
|
||||||
|
DoAnalogWriteForPort(&TCD2, bit, val);
|
||||||
|
#endif // TCD2 defined
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TIMERC2:
|
||||||
|
|
||||||
|
#ifndef TCC2
|
||||||
|
DoAnalogWriteForPort(&TCC0, bit, val);
|
||||||
|
#else // TCC2 defined
|
||||||
|
DoAnalogWriteForPort(&TCC2, bit, val);
|
||||||
|
#endif // TCC2 defined
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 22 /* meaning there is a PORT E available with 8 pins */
|
||||||
|
|
||||||
|
case TIMERE2: // TIMER 'E2' for 8-bits
|
||||||
|
|
||||||
|
#ifndef TCE2
|
||||||
|
DoAnalogWriteForPort(&TCE0, bit, val);
|
||||||
|
#else // TCE2 defined
|
||||||
|
DoAnalogWriteForPort(&TCE2, bit, val);
|
||||||
|
#endif // TCE2 defined
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 30 /* meaning there is a PORT F available */
|
||||||
|
|
||||||
|
case TIMERF2:
|
||||||
|
|
||||||
|
#ifndef TCF2
|
||||||
|
DoAnalogWriteForPort(&TCF0, bit, val);
|
||||||
|
#else // TCF2 defined
|
||||||
|
DoAnalogWriteForPort(&TCF2, bit, val);
|
||||||
|
#endif // TCF2 defined
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // NUM_DIGITAL_PINS > 30
|
||||||
|
|
||||||
|
#elif NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available but with only 4 pins */
|
||||||
|
|
||||||
|
case TIMERE0:
|
||||||
|
// timer E0 counts UP, but a value of 0 would still generate a '0' output because
|
||||||
|
// the output STARTS at a 1, and flips to 0 when the CTR reaches the CC register
|
||||||
|
// Similarly, a value of 255 would generate a '1'. see section 12.8.3 in the 'D' manual
|
||||||
|
if(bit == 1)
|
||||||
|
{
|
||||||
|
TCE0_CCA = val; // NOTE: these are 16-bit registers (but I'm in 8-bit mode so it's fine)
|
||||||
|
}
|
||||||
|
else if(bit == 2)
|
||||||
|
{
|
||||||
|
TCE0_CCB = val;
|
||||||
|
}
|
||||||
|
else if(bit == 4)
|
||||||
|
{
|
||||||
|
TCE0_CCC = val;
|
||||||
|
}
|
||||||
|
else if(bit == 8)
|
||||||
|
{
|
||||||
|
TCE0_CCD = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a reminder that the low nybble should be assigned the correct value for single-slope PWM mode
|
||||||
|
// TCE0_CTRLB = TC_WGMODE_SS_gc; // single-slope PWM. NOTE: this counts UP, whereas the other timers count DOWN
|
||||||
|
|
||||||
|
TCE0_CTRLB |= (bit << 4); // enables output (0-3 only, but that's all PORT E has anyway)
|
||||||
|
// note that the 'enable' bits are in CTRLB and in upper nybble
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // NUM_DIGITAL_PINS >= 18, 24
|
||||||
|
|
||||||
|
#endif // TCC4 check
|
||||||
|
|
||||||
|
case NOT_ON_TIMER:
|
||||||
|
default:
|
||||||
|
if (val < 128)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TCC4
|
||||||
|
void DoAnalogWriteForPort(TC4_t *port, uint8_t bit, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t modeE, modeF;
|
||||||
|
|
||||||
|
modeE = port->CTRLE;
|
||||||
|
modeF = port->CTRLF;
|
||||||
|
|
||||||
|
if(bit == 1)
|
||||||
|
{
|
||||||
|
port->CCA = (port->CCA & 0xff00) | (val & 0xff);
|
||||||
|
modeE = (modeE & ~TC4_LCCAMODE_gm) | TC45_LCCAMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 2)
|
||||||
|
{
|
||||||
|
port->CCB = (port->CCB & 0xff00) | (val & 0xff);
|
||||||
|
modeE = (modeE & ~TC4_LCCBMODE_gm) | TC45_LCCBMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 4)
|
||||||
|
{
|
||||||
|
port->CCC = (port->CCC & 0xff00) | (val & 0xff);
|
||||||
|
modeE = (modeE & ~TC4_LCCCMODE_gm) | TC45_LCCCMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 8)
|
||||||
|
{
|
||||||
|
port->CCD = (port->CCD & 0xff00) | (val & 0xff);
|
||||||
|
modeE = (modeE & ~TC4_LCCDMODE_gm) | TC45_LCCDMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 16)
|
||||||
|
{
|
||||||
|
port->CCA = (port->CCA & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
modeF = (modeF & ~TC4_HCCAMODE_gm) | TC45_HCCAMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 32)
|
||||||
|
{
|
||||||
|
port->CCB = (port->CCB & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
modeF = (modeF & ~TC4_HCCBMODE_gm) | TC45_HCCBMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 64)
|
||||||
|
{
|
||||||
|
port->CCC = (port->CCC & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
modeF = (modeF & ~TC4_HCCCMODE_gm) | TC45_HCCCMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else if(bit == 128)
|
||||||
|
{
|
||||||
|
port->CCD = (port->CCD & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
modeF = (modeF & ~TC4_HCCDMODE_gm) | TC45_HCCDMODE_COMP_gc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
port->CTRLE = modeE;
|
||||||
|
port->CTRLF = modeF;
|
||||||
|
|
||||||
|
// if(bit <= 8)
|
||||||
|
// {
|
||||||
|
// port->CTRLE = mode;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// port->CTRLF = mode;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
#elif defined(TCC2)
|
||||||
|
void DoAnalogWriteForPort(TC2_t *port, uint8_t bit, uint8_t val)
|
||||||
|
{
|
||||||
|
// NOTE: timers C2 and D2 count DOWN, always. However, the output starts at zero
|
||||||
|
// and flips to 1 when CTR reaches the CMP value. So a value of 255 would be
|
||||||
|
// '1' and 0 would be '0', as is expected. See 'D' manual 13.6.2
|
||||||
|
if(bit == 1)
|
||||||
|
{
|
||||||
|
port->LCMPA = val;
|
||||||
|
}
|
||||||
|
else if(bit == 2)
|
||||||
|
{
|
||||||
|
port->LCMPB = val;
|
||||||
|
}
|
||||||
|
else if(bit == 4)
|
||||||
|
{
|
||||||
|
port->LCMPC = val;
|
||||||
|
}
|
||||||
|
else if(bit == 8)
|
||||||
|
{
|
||||||
|
port->LCMPD = val;
|
||||||
|
}
|
||||||
|
else if(bit == 16)
|
||||||
|
{
|
||||||
|
port->HCMPA = val;
|
||||||
|
}
|
||||||
|
else if(bit == 32)
|
||||||
|
{
|
||||||
|
port->HCMPB = val;
|
||||||
|
}
|
||||||
|
else if(bit == 64)
|
||||||
|
{
|
||||||
|
port->HCMPC = val;
|
||||||
|
}
|
||||||
|
else if(bit == 128)
|
||||||
|
{
|
||||||
|
port->HCMPD = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a reminder that the low nybble should be assigned the correct value for single-slope PWM mode
|
||||||
|
// port->CTRLB = TC45_WGMODE_SINGLESLOPE_gc;
|
||||||
|
port->CTRLB |= bit; // enables output
|
||||||
|
}
|
||||||
|
#else // TCC0
|
||||||
|
void DoAnalogWriteForPort(TC0_t *port, uint8_t bit, uint8_t val)
|
||||||
|
{
|
||||||
|
// NOTE: timers C2 and D2 count DOWN, always. However, the output starts at zero
|
||||||
|
// and flips to 1 when CTR reaches the CMP value. So a value of 255 would be
|
||||||
|
// '1' and 0 would be '0', as is expected. See 'D' manual 13.6.2
|
||||||
|
if(bit == 1)
|
||||||
|
{
|
||||||
|
port->CCA = (port->CCA & 0xff00) | (val & 0xff);
|
||||||
|
}
|
||||||
|
else if(bit == 2)
|
||||||
|
{
|
||||||
|
port->CCB = (port->CCB & 0xff00) | (val & 0xff);
|
||||||
|
}
|
||||||
|
else if(bit == 4)
|
||||||
|
{
|
||||||
|
port->CCC = (port->CCC & 0xff00) | (val & 0xff);
|
||||||
|
}
|
||||||
|
else if(bit == 8)
|
||||||
|
{
|
||||||
|
port->CCD = (port->CCD & 0xff00) | (val & 0xff);
|
||||||
|
}
|
||||||
|
else if(bit == 16)
|
||||||
|
{
|
||||||
|
port->CCA = (port->CCA & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
}
|
||||||
|
else if(bit == 32)
|
||||||
|
{
|
||||||
|
port->CCB = (port->CCB & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
}
|
||||||
|
else if(bit == 64)
|
||||||
|
{
|
||||||
|
port->CCC = (port->CCC & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
}
|
||||||
|
else if(bit == 128)
|
||||||
|
{
|
||||||
|
port->CCD = (port->CCD & 0xff) | ((val << 8) & 0xff00);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a reminder that the low nybble should be assigned the correct value for single-slope PWM mode
|
||||||
|
// port->CTRLB = TC45_WGMODE_SINGLESLOPE_gc;
|
||||||
|
port->CTRLB |= bit; // enables output
|
||||||
|
}
|
||||||
|
#endif // TCC4, TCC2, TCC0
|
||||||
|
|
||||||
|
|
428
BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c
Normal file
428
BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
wiring_digital.c - digital input and output functions
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
|
||||||
|
Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
|
||||||
|
In some cases, the xmega updates make assumptions about the pin assignments.
|
||||||
|
See 'pins_arduino.h' for more detail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ARDUINO_MAIN
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
void pinMode(uint8_t pin, uint8_t mode)
|
||||||
|
{
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
uint8_t sense = mode & INPUT_SENSE_MASK;
|
||||||
|
uint8_t invert = mode & INPUT_OUTPUT_INVERT;
|
||||||
|
volatile uint8_t *reg, /* *out,*/ *ctrl;
|
||||||
|
|
||||||
|
mode &= INPUT_OUTPUT_MASK; // remove 'sense' bits
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = portModeRegister(port); // D manual section 11.12.1
|
||||||
|
|
||||||
|
if(sense == INPUT_SENSE_DISABLED && reg != &PORTR_DIR) // 'DISABLED'
|
||||||
|
{
|
||||||
|
sense = PORT_ISC_INPUT_DISABLE_gc; // bit values for 'INTPUT_DISABLED' (sic)
|
||||||
|
}
|
||||||
|
else if(sense == INPUT_SENSE_RISING)
|
||||||
|
{
|
||||||
|
sense = PORT_ISC_RISING_gc; // rising
|
||||||
|
}
|
||||||
|
else if(sense == INPUT_SENSE_FALLING)
|
||||||
|
{
|
||||||
|
sense = PORT_ISC_FALLING_gc; // falling
|
||||||
|
}
|
||||||
|
else if(sense == INPUT_SENSE_LEVEL)
|
||||||
|
{
|
||||||
|
sense = PORT_ISC_LEVEL_gc; // LOW level (except events, which use HIGH level)
|
||||||
|
}
|
||||||
|
else // if(sense == INPUT_SENSE_BOTH) all others including 'DEFAULT'
|
||||||
|
{
|
||||||
|
sense = PORT_ISC_BOTHEDGES_gc; // 'both rising and falling'
|
||||||
|
}
|
||||||
|
|
||||||
|
if(invert) // inverted bit value
|
||||||
|
{
|
||||||
|
sense |= _BV(PORT_INVEN_bp); // see 11.12.15 in D manual - 'invert' bit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// JWS: can I let the optimizer do this?
|
||||||
|
// reg = portModeRegister(port); // D manual section 11.12.1 (MOVED upwards, BBB)
|
||||||
|
// out = portOutputRegister(port); // D manual section 11.12.5 (not used - BBB)
|
||||||
|
ctrl = pinControlRegister(pin); // D manual section 11.12.15
|
||||||
|
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli(); // clear interrupt flag until I'm done assigning pin stuff
|
||||||
|
|
||||||
|
if (mode == INPUT)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_TOTEM_gc;
|
||||||
|
|
||||||
|
*reg &= ~bit;
|
||||||
|
}
|
||||||
|
else if (mode == INPUT_PULLUP)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_PULLUP_gc; // input pullup
|
||||||
|
|
||||||
|
*reg &= ~bit;
|
||||||
|
}
|
||||||
|
else if (mode == INPUT_AND_PULLUP)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_WIREDANDPULL_gc; // wired 'and' (open drain) with pullup
|
||||||
|
|
||||||
|
*reg &= ~bit;
|
||||||
|
}
|
||||||
|
else if (mode == INPUT_PULLDOWN)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_PULLDOWN_gc; // input pullDOWN
|
||||||
|
|
||||||
|
*reg &= ~bit;
|
||||||
|
}
|
||||||
|
else if (mode == INPUT_OR_PULLDOWN)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_WIREDORPULL_gc; // wired 'or' (open drain) with pulldown
|
||||||
|
|
||||||
|
*reg &= ~bit;
|
||||||
|
}
|
||||||
|
else if (mode == INPUT_BUS_KEEPER)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_BUSKEEPER_gc; // bus keeper
|
||||||
|
|
||||||
|
*reg &= ~bit;
|
||||||
|
}
|
||||||
|
else if (mode == OUTPUT_OR)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_WIREDOR_gc; // wired 'or' (open drain)
|
||||||
|
|
||||||
|
*reg |= bit;
|
||||||
|
}
|
||||||
|
else if (mode == OUTPUT_AND)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_WIREDAND_gc; // wired 'and' (open drain)
|
||||||
|
|
||||||
|
*reg |= bit;
|
||||||
|
}
|
||||||
|
else if (mode == OUTPUT_OR_PULLDOWN)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_WIREDORPULL_gc; // wired 'or' (open drain) with pulldown
|
||||||
|
|
||||||
|
*reg |= bit;
|
||||||
|
}
|
||||||
|
else if (mode == OUTPUT_AND_PULLUP)
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_WIREDANDPULL_gc; // wired 'and' (open drain) with pullup
|
||||||
|
|
||||||
|
*reg |= bit;
|
||||||
|
}
|
||||||
|
else // if(mode == OUTPUT) assume OUTPUT without open drain and/or nor pullup/down
|
||||||
|
{
|
||||||
|
*ctrl = sense | PORT_OPC_TOTEM_gc; // 'totem pole' (the default)
|
||||||
|
|
||||||
|
*reg |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SREG = oldSREG;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forcing this inline keeps the callers from having to push their own stuff
|
||||||
|
// on the stack. It is a good performance win and only takes 1 more byte per
|
||||||
|
// user than calling. (It will take more bytes on the 168.)
|
||||||
|
//
|
||||||
|
// But shouldn't this be moved into pinMode? Seems silly to check and do on
|
||||||
|
// each digitalread or write.
|
||||||
|
//
|
||||||
|
// Mark Sproul:
|
||||||
|
// - Removed inline. Save 170 bytes on atmega1280
|
||||||
|
// - changed to a switch statment; added 32 bytes but much easier to read and maintain.
|
||||||
|
// - Added more #ifdefs, now compiles for atmega645
|
||||||
|
//
|
||||||
|
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
|
||||||
|
//static inline void turnOffPWM(uint8_t timer)
|
||||||
|
|
||||||
|
// BBB - added 'bit' parameter for xmega - it's a bit MASK, not a bit number
|
||||||
|
// use the result from digitalPinToBitMask(pin) for 'bit'
|
||||||
|
|
||||||
|
static void turnOffPWM(uint8_t timer, uint8_t bit)
|
||||||
|
{
|
||||||
|
#ifdef TCC4 /* 'E' series and later that have TCC4 */
|
||||||
|
register uint8_t mode;
|
||||||
|
#endif // TCC4
|
||||||
|
|
||||||
|
switch (timer)
|
||||||
|
{
|
||||||
|
#ifdef TCC4 /* 'E' series and later that have TCC4 */
|
||||||
|
case TIMERC4:
|
||||||
|
|
||||||
|
if(bit == 1)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLE & ~TC4_LCCAMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 2)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLE & ~TC4_LCCBMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 4)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLE & ~TC4_LCCCMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 8)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLE & ~TC4_LCCDMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 16)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLF & ~TC4_HCCAMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 32)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLF & ~TC4_HCCBMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 64)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLF & ~TC4_HCCCMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 128)
|
||||||
|
{
|
||||||
|
mode = (TCC4_CTRLF & ~TC4_HCCDMODE_gm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bit <= 8)
|
||||||
|
{
|
||||||
|
TCC4_CTRLE = mode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TCC4_CTRLF = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TIMERD5:
|
||||||
|
|
||||||
|
if(bit == 1 || bit == 16)
|
||||||
|
{
|
||||||
|
mode = (TCD5_CTRLE & ~TC5_LCCAMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 2 || bit == 32)
|
||||||
|
{
|
||||||
|
mode = (TCD5_CTRLE & ~TC5_LCCBMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 4 || bit == 64)
|
||||||
|
{
|
||||||
|
mode = (TCD5_CTRLF & ~TC5_HCCAMODE_gm);
|
||||||
|
}
|
||||||
|
else if(bit == 8 || bit == 128)
|
||||||
|
{
|
||||||
|
mode = (TCD5_CTRLF & ~TC5_HCCBMODE_gm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check to see if it was enabled AND the bit was configured properly for PWM
|
||||||
|
// AND was properly mapped (L vs H, REMAP register?)
|
||||||
|
if(bit == 1 || bit == 2 || bit == 16 || bit == 32)
|
||||||
|
{
|
||||||
|
TCD5_CTRLE = mode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TCD5_CTRLF = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#else // everything else NOT an 'E' series
|
||||||
|
|
||||||
|
#ifndef TCC2 /* A1 series does not define this and I need TC0 */
|
||||||
|
|
||||||
|
case TIMERD2:
|
||||||
|
TCD0_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TIMERC2:
|
||||||
|
TCC0_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 22 /* which means we have PORT E but with 8 pins, not 4 */
|
||||||
|
|
||||||
|
case TIMERE2:
|
||||||
|
TCE0_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 30 /* which means we have PORT F */
|
||||||
|
|
||||||
|
case TIMERF2:
|
||||||
|
TCF0_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
#endif // NUM_DIGITAL_PINS > 30
|
||||||
|
|
||||||
|
#elif NUM_DIGITAL_PINS > 18 /* which means we have PORT E but only with 4 pins */
|
||||||
|
case TIMERE0:
|
||||||
|
TCE0_CTRLB &= ~(bit << 4); // DISables PWM output
|
||||||
|
// note that the 'enable' bits are in CTRLB and in upper nybble
|
||||||
|
break;
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18, 22
|
||||||
|
|
||||||
|
#else // TCC2
|
||||||
|
case TIMERD2:
|
||||||
|
TCD2_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TIMERC2:
|
||||||
|
TCC2_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 22 /* which means we have PORT E but with 8 pins, not 4 */
|
||||||
|
|
||||||
|
case TIMERE2:
|
||||||
|
TCE2_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if NUM_DIGITAL_PINS > 30 /* which means we have PORT F */
|
||||||
|
|
||||||
|
case TIMERF2:
|
||||||
|
TCF2_CTRLB &= ~bit; // DISables PWM output
|
||||||
|
break;
|
||||||
|
#endif // NUM_DIGITAL_PINS > 30
|
||||||
|
|
||||||
|
#elif NUM_DIGITAL_PINS > 18 /* which means we have PORT E but only with 4 pins */
|
||||||
|
// TODO: 64d4 has 4 pins on PORT E. 128A1 has 8 pins on PORT E. determine which to use?
|
||||||
|
case TIMERE0:
|
||||||
|
TCE0_CTRLB &= ~(bit << 4); // DISables PWM output
|
||||||
|
// note that the 'enable' bits are in CTRLB and in upper nybble
|
||||||
|
break;
|
||||||
|
#endif // NUM_DIGITAL_PINS > 18, 22
|
||||||
|
|
||||||
|
#endif // TCC2
|
||||||
|
#endif // TCC4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void digitalWrite(uint8_t pin, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t timer = digitalPinToTimer(pin);
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
volatile uint8_t *out, *ctrl;
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl = pinControlRegister(pin); // D manual section 11.12.15
|
||||||
|
|
||||||
|
if(*ctrl & _BV(PORT_INVEN_bp)) // inverted
|
||||||
|
{
|
||||||
|
val = !val; // invert the value (so it's consistent with the pin)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the pin that support PWM output, we need to turn it off
|
||||||
|
// before doing a digital write.
|
||||||
|
|
||||||
|
// TODO: move this feature to pinMode() like it should be
|
||||||
|
// or set a flag to be used with analogWrite()
|
||||||
|
// (for now it's probably faster just to call it)
|
||||||
|
|
||||||
|
if (timer != NOT_ON_TIMER)
|
||||||
|
{
|
||||||
|
turnOffPWM(timer, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
out = portOutputRegister(port);
|
||||||
|
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
|
||||||
|
if (val == LOW)
|
||||||
|
{
|
||||||
|
*out &= ~bit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*out |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
int digitalRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
uint8_t timer = digitalPinToTimer(pin);
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
volatile uint8_t *ctrl;
|
||||||
|
uint8_t bSet;
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN)
|
||||||
|
{
|
||||||
|
return LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the pin that support PWM output, we need to turn it off
|
||||||
|
// before getting a digital reading.
|
||||||
|
|
||||||
|
// TODO: move this feature to pinMode() like it should be
|
||||||
|
// or set a flag to be used with analogWrite()
|
||||||
|
// (for now it's probably faster just to call it)
|
||||||
|
|
||||||
|
if (timer != NOT_ON_TIMER)
|
||||||
|
{
|
||||||
|
turnOffPWM(timer, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
bSet = (*portInputRegister(port) & bit) ? true : false;
|
||||||
|
|
||||||
|
// if the 'invert' flag is on, I invert the digital value
|
||||||
|
// this is so that the result of 'digitalRead' and 'digitalWrite'
|
||||||
|
// are ALWAYS consistent with the actual pin level. Inversion is
|
||||||
|
// needed for proper interrupt control. So for the best consistency,
|
||||||
|
// the invert flag will only (really) be needed for LEVEL interrupts.
|
||||||
|
|
||||||
|
ctrl = pinControlRegister(pin); // D manual section 11.12.15
|
||||||
|
|
||||||
|
if(*ctrl & _BV(PORT_INVEN_bp)) // inverted
|
||||||
|
{
|
||||||
|
bSet = !bSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bSet ? HIGH : LOW;
|
||||||
|
}
|
||||||
|
|
125
BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h
Normal file
125
BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
wiring_private.h - Internal header file.
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WiringPrivate_h
|
||||||
|
#define WiringPrivate_h
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
// things that need to be defined in order for the code to compile
|
||||||
|
|
||||||
|
// definitions for ADC-related product signature row entries
|
||||||
|
#ifndef PRODSIGNATURES_ADCACAL0 /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_ADCACAL0 _SFR_MEM8(0x0020)
|
||||||
|
#endif // PRODSIGNATURES_ADCACAL0
|
||||||
|
|
||||||
|
#ifndef PRODSIGNATURES_ADCACAL1 /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_ADCACAL1 _SFR_MEM8(0x0021)
|
||||||
|
#endif // PRODSIGNATURES_ADCACAL1
|
||||||
|
|
||||||
|
#ifndef PRODSIGNATURES_ADCBCAL0 /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_ADCBCAL0 _SFR_MEM8(0x0024)
|
||||||
|
#endif // PRODSIGNATURES_ADCBCAL0
|
||||||
|
|
||||||
|
#ifndef PRODSIGNATURES_ADCBCAL1 /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_ADCBCAL1 _SFR_MEM8(0x0025)
|
||||||
|
#endif // PRODSIGNATURES_ADCBCAL1
|
||||||
|
|
||||||
|
// definitions for USB-related product signature row entries
|
||||||
|
#ifndef PRODSIGNATURES_USBCAL0 /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_USBCAL0 _SFR_MEM8(0x001a)
|
||||||
|
#endif // PRODSIGNATURES_USBCAL0
|
||||||
|
|
||||||
|
#ifndef PRODSIGNATURES_USBCAL1 /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_USBCAL1 _SFR_MEM8(0x001b)
|
||||||
|
#endif // PRODSIGNATURES_USBCAL1
|
||||||
|
|
||||||
|
#ifndef PRODSIGNATURES_USBRCOSC /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_USBRCOSC _SFR_MEM8(0x001c)
|
||||||
|
#endif // PRODSIGNATURES_USBRCOSC
|
||||||
|
|
||||||
|
#ifndef PRODSIGNATURES_USBRCOSCA /* _MOST_ headers don't define this properly - see ATMel Studio headers */
|
||||||
|
#define PRODSIGNATURES_USBRCOSCA _SFR_MEM8(0x001d)
|
||||||
|
#endif // PRODSIGNATURES_USBRCOSCA
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ADCA_CH0_SCAN /* A1 headers don't define this properly */
|
||||||
|
#define ADCA_CH0_SCAN _SFR_MEM8(0x0226)
|
||||||
|
#define ADC_REFSEL_INTVCC2_gc (0x04<<4)
|
||||||
|
#define ADC_CH_GAIN_DIV2_gc (0x07<<2)
|
||||||
|
#endif // ADCA_CH0_SCAN
|
||||||
|
|
||||||
|
#ifndef ADC_REFSEL2_bm /* A1 headers don't define this properly, but A1U headers do [and others] */
|
||||||
|
#define ADC_REFSEL2_bm (1<<6) /* Reference Selection bit 2 mask. */
|
||||||
|
#define ADC_REFSEL2_bp 6 /* Reference Selection bit 2 position. */
|
||||||
|
#endif // ADC_REFSEL2_bm
|
||||||
|
|
||||||
|
#ifndef PORT_USART0_bm
|
||||||
|
#define PORT_USART0_bm 0x10 /* Usart0 bit mask for port remap register. */
|
||||||
|
#endif // PORT_USART0_bm
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef cbi
|
||||||
|
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||||
|
#endif
|
||||||
|
#ifndef sbi
|
||||||
|
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: xmega is SO different that these need to be in pins_arduino.h
|
||||||
|
// some xmegas have 2 per port, others 1 per port, and the # of ports vary greatly
|
||||||
|
//#define EXTERNAL_INT_0 0
|
||||||
|
//#define EXTERNAL_INT_1 1
|
||||||
|
//#define EXTERNAL_INT_2 2
|
||||||
|
//#define EXTERNAL_INT_3 3
|
||||||
|
//#define EXTERNAL_INT_4 4
|
||||||
|
//#define EXTERNAL_INT_5 5
|
||||||
|
//#define EXTERNAL_INT_6 6
|
||||||
|
//#define EXTERNAL_INT_7 7
|
||||||
|
|
||||||
|
// CPU-specific definitions go into the 'pins_arduino.h' files anyway
|
||||||
|
//
|
||||||
|
//#if defined(SOME_CPU)
|
||||||
|
//#define EXTERNAL_NUM_INTERRUPTS 8
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
typedef void (*voidFuncPtr)(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
69
BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c
Normal file
69
BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
wiring_pulse.c - pulseIn() function
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
|
||||||
|
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
|
||||||
|
* to 3 minutes in length, but must be called at least a few dozen microseconds
|
||||||
|
* before the start of the pulse. */
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||||
|
{
|
||||||
|
// cache the port and bit of the pin in order to speed up the
|
||||||
|
// pulse width measuring loop and achieve finer resolution. calling
|
||||||
|
// digitalRead() instead yields much coarser resolution.
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
uint8_t stateMask = (state ? bit : 0);
|
||||||
|
unsigned long width = 0; // keep initialization out of time critical area
|
||||||
|
|
||||||
|
// convert the timeout from microseconds to a number of times through
|
||||||
|
// the initial loop; it takes 16 clock cycles per iteration.
|
||||||
|
unsigned long numloops = 0;
|
||||||
|
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
|
||||||
|
|
||||||
|
// wait for any previous pulse to end
|
||||||
|
while ((*portInputRegister(port) & bit) == stateMask)
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// wait for the pulse to start
|
||||||
|
while ((*portInputRegister(port) & bit) != stateMask)
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// wait for the pulse to stop
|
||||||
|
while ((*portInputRegister(port) & bit) == stateMask) {
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
width++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the reading to microseconds. The loop has been determined
|
||||||
|
// to be 20 clock cycles long and have about 16 clocks between the edge
|
||||||
|
// and the start of the loop. There will be some error introduced by
|
||||||
|
// the interrupt handlers.
|
||||||
|
return clockCyclesToMicroseconds(width * 21 + 16);
|
||||||
|
}
|
55
BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c
Normal file
55
BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
wiring_shift.c - shiftOut() function
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
||||||
|
uint8_t value = 0;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
digitalWrite(clockPin, HIGH);
|
||||||
|
if (bitOrder == LSBFIRST)
|
||||||
|
value |= digitalRead(dataPin) << i;
|
||||||
|
else
|
||||||
|
value |= digitalRead(dataPin) << (7 - i);
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (bitOrder == LSBFIRST)
|
||||||
|
digitalWrite(dataPin, !!(val & (1 << i)));
|
||||||
|
else
|
||||||
|
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
|
||||||
|
|
||||||
|
digitalWrite(clockPin, HIGH);
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
}
|
||||||
|
}
|
25
BootLoaders/Boards/orangerx/platform.local.txt
Normal file
25
BootLoaders/Boards/orangerx/platform.local.txt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
## Save hex
|
||||||
|
recipe.output.tmp_file={build.project_name}.hex
|
||||||
|
recipe.output.save_file=multi-orx.hex
|
||||||
|
|
||||||
|
## Override some platform.txt settings to create a .bin instead of a .hex file
|
||||||
|
## The two lines below can be uncommented to have the compiler create a .bin file instead of a .hex file
|
||||||
|
#compiler.elf2hex.flags=-O binary -R .eeprom
|
||||||
|
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"
|
||||||
|
|
||||||
|
## Make a .bin version of the .hex file
|
||||||
|
## The line below can be uncommented to have a .bin file made as well as the .hex file
|
||||||
|
#recipe.hooks.objcopy.postobjcopy.00.pattern.windows="{compiler.path}{compiler.objcopy.cmd}" -I ihex "{build.path}/{build.project_name}.hex" -O binary "{build.path}/{build.project_name}.bin"
|
||||||
|
|
||||||
|
## Copy hex
|
||||||
|
# Make a copy of the compiled binary with the version number in the file name
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
|
||||||
|
# If we're exporting the hex file, rename it with the version number
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
124
BootLoaders/Boards/orangerx/platform.txt
Normal file
124
BootLoaders/Boards/orangerx/platform.txt
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
name=Multi 4-in-1 OrangeRX
|
||||||
|
version=1.0.1
|
||||||
|
|
||||||
|
# this was borrowed from the installed version of 'platform.txt'
|
||||||
|
# XMEGA compile variables
|
||||||
|
# ---------------------
|
||||||
|
|
||||||
|
compiler.warning_flags=-w
|
||||||
|
compiler.warning_flags.none=-w
|
||||||
|
compiler.warning_flags.default=
|
||||||
|
compiler.warning_flags.more=-Wall
|
||||||
|
compiler.warning_flags.all=-Wall -Wextra
|
||||||
|
|
||||||
|
# Default "compiler.path" is correct, change only if you want to override the initial value
|
||||||
|
compiler.path={runtime.tools.avr-gcc.path}/bin/
|
||||||
|
compiler.c.cmd=avr-gcc
|
||||||
|
compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto
|
||||||
|
compiler.c.elf.flags={compiler.warning_flags} -Os -flto -Wl,--gc-sections
|
||||||
|
compiler.c.elf.cmd=avr-gcc
|
||||||
|
compiler.S.flags=-c -g -x assembler-with-cpp -flto
|
||||||
|
compiler.cpp.cmd=avr-g++
|
||||||
|
compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto
|
||||||
|
compiler.ar.cmd=avr-gcc-ar
|
||||||
|
compiler.ar.flags=rcs
|
||||||
|
compiler.objcopy.cmd=avr-objcopy
|
||||||
|
compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0
|
||||||
|
compiler.elf2hex.flags=-O ihex -R .eeprom
|
||||||
|
compiler.elf2hex.cmd=avr-objcopy
|
||||||
|
compiler.ldflags=
|
||||||
|
compiler.size.cmd=avr-size
|
||||||
|
|
||||||
|
# This can be overridden in boards.txt
|
||||||
|
build.extra_flags=
|
||||||
|
|
||||||
|
# These can be overridden in platform.local.txt
|
||||||
|
compiler.c.extra_flags=
|
||||||
|
compiler.c.elf.extra_flags=
|
||||||
|
compiler.S.extra_flags=
|
||||||
|
compiler.cpp.extra_flags=
|
||||||
|
compiler.ar.extra_flags=
|
||||||
|
compiler.objcopy.eep.extra_flags=
|
||||||
|
compiler.elf2hex.extra_flags=
|
||||||
|
|
||||||
|
# XMEGA compile patterns
|
||||||
|
# --------------------
|
||||||
|
|
||||||
|
## Compile c files
|
||||||
|
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||||
|
|
||||||
|
## Compile c++ files
|
||||||
|
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||||
|
|
||||||
|
## Compile S files
|
||||||
|
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||||
|
|
||||||
|
## Create archives
|
||||||
|
# archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value
|
||||||
|
archive_file_path={build.path}/{archive_file}
|
||||||
|
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
|
||||||
|
|
||||||
|
## Combine gc-sections, archives, and objects
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
|
||||||
|
|
||||||
|
## Create output files (.eep and .hex)
|
||||||
|
recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep"
|
||||||
|
recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
|
||||||
|
|
||||||
|
## Save hex
|
||||||
|
recipe.output.tmp_file={build.project_name}.hex
|
||||||
|
recipe.output.save_file={build.project_name}.{build.variant}.hex
|
||||||
|
|
||||||
|
## Compute size
|
||||||
|
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
|
||||||
|
recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).*
|
||||||
|
recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).*
|
||||||
|
recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
|
||||||
|
|
||||||
|
## Preprocessor
|
||||||
|
preproc.includes.flags=-w -x c++ -M -MG -MP
|
||||||
|
recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.includes.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}"
|
||||||
|
|
||||||
|
preproc.macros.flags=-w -x c++ -E -CC
|
||||||
|
recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{preprocessed_file_path}"
|
||||||
|
|
||||||
|
# XMEGA Uploader/Programmers tools
|
||||||
|
# ------------------------------
|
||||||
|
|
||||||
|
tools.avrdude.path={runtime.tools.avrdude.path}
|
||||||
|
tools.avrdude.cmd.path={path}/bin/avrdude
|
||||||
|
# NOTE: change to avrdude.conf path - using the one specified by this hardware package
|
||||||
|
# THIS is a LOT 'nicer' than overwriting the system file. Some packages actually do that...
|
||||||
|
tools.avrdude.config.path={runtime.platform.path}/avrdude.conf
|
||||||
|
|
||||||
|
tools.avrdude.upload.params.verbose=-v
|
||||||
|
tools.avrdude.upload.params.quiet=-q -q
|
||||||
|
# tools.avrdude.upload.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value
|
||||||
|
tools.avrdude.upload.verify=
|
||||||
|
tools.avrdude.upload.params.noverify=-V
|
||||||
|
tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i"
|
||||||
|
|
||||||
|
tools.avrdude.program.params.verbose=-v
|
||||||
|
tools.avrdude.program.params.quiet=-q -q
|
||||||
|
# tools.avrdude.program.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value
|
||||||
|
tools.avrdude.program.verify=
|
||||||
|
tools.avrdude.program.params.noverify=-V
|
||||||
|
tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i"
|
||||||
|
|
||||||
|
tools.avrdude.erase.params.verbose=-v
|
||||||
|
tools.avrdude.erase.params.quiet=-q -q
|
||||||
|
tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Ufuse1:w:{bootloader.fuse1}:m -Ufuse2:w:{bootloader.fuse2}:m -Ufuse4:w:{bootloader.fuse4}:m -Ufuse5:w:{bootloader.fuse5}:m
|
||||||
|
|
||||||
|
tools.avrdude.bootloader.params.verbose=-v
|
||||||
|
tools.avrdude.bootloader.params.quiet=-q -q
|
||||||
|
tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uboot:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m
|
||||||
|
|
||||||
|
tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu}
|
||||||
|
|
||||||
|
# USB Default Flags
|
||||||
|
# Default blank usb manufacturer will be filled in at compile time
|
||||||
|
# - from numeric vendor ID, set to Unknown otherwise
|
||||||
|
build.usb_manufacturer="Unknown"
|
||||||
|
build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'
|
||||||
|
|
||||||
|
|
47
BootLoaders/Boards/orangerx/tools/linux/do_version
Executable file
47
BootLoaders/Boards/orangerx/tools/linux/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=orx
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
47
BootLoaders/Boards/orangerx/tools/linux64/do_version
Executable file
47
BootLoaders/Boards/orangerx/tools/linux64/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=orx
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
47
BootLoaders/Boards/orangerx/tools/macosx/do_version
Executable file
47
BootLoaders/Boards/orangerx/tools/macosx/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=orx
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
54
BootLoaders/Boards/orangerx/tools/win/do_version.bat
Normal file
54
BootLoaders/Boards/orangerx/tools/win/do_version.bat
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SETLOCAL EnableDelayedExpansion
|
||||||
|
|
||||||
|
SET BUILD_PATH=%1
|
||||||
|
SET PROJECT_NAME=%2
|
||||||
|
SET SKETCH_PATH=%3
|
||||||
|
SET MULTI_BOARD=%4
|
||||||
|
SET EXPORT_FLAG=%5
|
||||||
|
|
||||||
|
REM ECHO Multi board: %MULTI_BOARD%
|
||||||
|
|
||||||
|
SET MULTI_TYPE=orx
|
||||||
|
|
||||||
|
IF EXIST "%1\sketch\Multiprotocol.h" (
|
||||||
|
REM ECHO Getting Multi-MODULE firmware version from "%1\sketch\Multiprotocol.h"
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%D") do SET PATCH_VERSION=%%i
|
||||||
|
SET MULTI_VER=!MAJOR_VERSION!.!MINOR_VERSION!.!REVISION_VERSION!.!PATCH_VERSION!
|
||||||
|
) ELSE (
|
||||||
|
SET MULTI_VER=
|
||||||
|
)
|
||||||
|
|
||||||
|
REM ECHO Multi-MODULE firmware version: %MULTI_VER%
|
||||||
|
|
||||||
|
REM Copy the compiled file to the sketch folder with the version number in the file name
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" (
|
||||||
|
REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" (
|
||||||
|
REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF "%EXPORT_FLAG%"=="EXPORT" (
|
||||||
|
REM Copy the compiled file to the sketch folder with the version number in the file name
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" (
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" (
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" (
|
||||||
|
DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL
|
||||||
|
)
|
||||||
|
IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" (
|
||||||
|
DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" >NUL
|
||||||
|
)
|
||||||
|
)
|
702
BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h
Normal file
702
BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h
Normal file
@ -0,0 +1,702 @@
|
|||||||
|
/*
|
||||||
|
pins_arduino.h - Pin definition functions for Arduino
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2007 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/
|
||||||
|
|
||||||
|
X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A
|
||||||
|
|
||||||
|
The xmega code mods make a considerable number of assumptions
|
||||||
|
about the pin number assignments (as defined here):
|
||||||
|
|
||||||
|
DEFAULT MAPPING ('DIGITAL_IO_PIN_SHIFT' NOT DEFINED)
|
||||||
|
----------------------------------------------------
|
||||||
|
PORTD - digital 0-7
|
||||||
|
PORTC - digital 8-15
|
||||||
|
PORTE - digital 16-20
|
||||||
|
PORTR - digital 20-21 (built-in LED on PORTR pin 1, aka '21')
|
||||||
|
PORTA - analog 0-7, digital 22-29
|
||||||
|
PORTB - analog 8-11, digital 30-33
|
||||||
|
|
||||||
|
SPI is assumed to be on PORTC (pins 4-7)
|
||||||
|
Serial is implemented on PORTD, Serial2 on PORTC, both using pins 2,3 (no flow control)
|
||||||
|
PORTR pin 1 is assumed to be connected to an LED. Pin 1 is the 'built-in' LED, defined
|
||||||
|
as 'LED_BUILTIN', and is active HIGH.
|
||||||
|
|
||||||
|
Your Mileage May Vary, depending on your board layout. Some boards shift the
|
||||||
|
digital pin assignments by 2 so that digital I/O pin 0 is PORTD Rx, pin 13 is PORTC SCK, just
|
||||||
|
like the Arduino ATmega board. Then they align the physical pins so that a regular Arduino shield
|
||||||
|
will work, and assign PORTD 0-1 to 2 different digital I/O pin numbers (such as 20 and 21).
|
||||||
|
|
||||||
|
To facilitate that specific change, uncomment the #define for 'DIGITAL_IO_PIN_SHIFT', below.
|
||||||
|
Alternately you can create a separate version of this file with a different variant name,
|
||||||
|
such as 'xmega-compat', with the #define uncommented, stored in an appropriately named directory.
|
||||||
|
|
||||||
|
============================
|
||||||
|
HARDWARE SERIAL FLOW CONTROL
|
||||||
|
============================
|
||||||
|
|
||||||
|
This version of the xmega Arduino startup+support files supports HARDWARE FLOW CONTROL on BOTH serial ports via
|
||||||
|
RTS (output) and CTS (input). CTS is implemented as input from remote device's DTR. RTS is implemented as DTR output.
|
||||||
|
|
||||||
|
To implement RTS/CTS, use definitions similar to the following in your version of this header file
|
||||||
|
|
||||||
|
NOTE: RTS(DTR) will be configured as an output, active low (high tells sender to stop sending data to the UART)
|
||||||
|
CTS will be configured as an input, active low (high stops data from being sent out via UART)
|
||||||
|
|
||||||
|
CTS high to low transition causes an interrupt that may result in serial I/O (for faster response time).
|
||||||
|
|
||||||
|
// RTS(DTR) as GPIO 0 (port D pin 0)
|
||||||
|
#define SERIAL_0_RTS_PORT_NAME PORTD
|
||||||
|
#define SERIAL_0_RTS_PIN_INDEX 0
|
||||||
|
|
||||||
|
// CTS as GPIO 1 (port D pin 1)
|
||||||
|
#define SERIAL_0_CTS_PORT_NAME PORTD
|
||||||
|
#define SERIAL_0_CTS_PIN_INDEX 1
|
||||||
|
|
||||||
|
use similar definitions for serial 1, aka 'SERIAL_1_CTS_PORT'
|
||||||
|
|
||||||
|
NOTE: you can even use PORTA or PORTB pins for this, if you don't need to measure analog volts on those pins
|
||||||
|
|
||||||
|
X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
// for now, the default xmega uses a simple assignment of digital pin numbers, beginning with port D
|
||||||
|
// to accomodate a useful "compatibility" shield design, these pins can be shifted so that the pin
|
||||||
|
// that maps to 'digitalRead(0)' would be D2 rather than D0. This also puts 'Serial' on pins 0 and 1
|
||||||
|
// exactly like the Arduino UNO. For any other mapping, create your own 'pins_arduino.h' file.
|
||||||
|
//
|
||||||
|
#define DIGITAL_IO_PIN_SHIFT /* COMMENT THIS to disable the shifting of digital pin assignments for Arduino shield compatibility */
|
||||||
|
|
||||||
|
// default two-wire port is TWIC. '#define'ing USE_TWIC maps it to digital pins 20 and 21. Only valid with DIGITAL_IO_PIN_SHIFT '#define'd
|
||||||
|
#define USE_TWIC /* define this to re-map TWIC to digital pins 20 and 21, similar to an Arduino Mega2560. requires DIGITAL_IO_PIN_SHIFT */
|
||||||
|
|
||||||
|
|
||||||
|
#define NUM_DIGITAL_PINS 22
|
||||||
|
#define NUM_ANALOG_INPUTS 12
|
||||||
|
#define analogInputToDigitalPin(p) ((p < 12) ? (p) + 22 : -1)
|
||||||
|
#ifdef DIGITAL_IO_PIN_SHIFT
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
#define digitalPinHasPWM(p) ((p) < 18 || (p) == 20 || (p) == 21) /* PORTC pins 0 and 1 are 20 and 21, respectively */
|
||||||
|
#else // USE_TWIC
|
||||||
|
#define digitalPinHasPWM(p) ((p) < 18 || (p) == 20 || (p) == 21) /* PORTD pins 0 and 1 are 20 and 21, respectively */
|
||||||
|
#endif // USE_TWIC
|
||||||
|
#else // no digital I/O pin shift
|
||||||
|
#define digitalPinHasPWM(p) ((p) < 20) /* port E pin 3 is the highest one that has PWM */
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
|
||||||
|
// this returns the DEFAULT INTERRUPT (in this case, interrupt 0) for any digital or analog pin
|
||||||
|
// If you choose a port's pin 2, it will be the same as using 'PORTn_INT0'
|
||||||
|
#define digitalPinToInterrupt(p) \
|
||||||
|
( pgm_read_byte(&port_to_int0_PGM[pgm_read_byte(&digital_pin_to_port_PGM[p])]) | \
|
||||||
|
( ((pgm_read_byte(&digital_pin_to_bit_mask_PGM[p]) - 2) & 7) << 5 ) )
|
||||||
|
|
||||||
|
|
||||||
|
// xmega-specific - Interrupt 'vector number' assignments:
|
||||||
|
|
||||||
|
// Interrupts are PORT-SPECIFIC, not pin specific.
|
||||||
|
// pin 2 on any port is always asynchronous (except for 'R' which doesn't have a pin 2)
|
||||||
|
// all other pins can manage synchronous interrupts. 'wakeup' from sleep mode
|
||||||
|
// and other async interrupts must be on a 'pin 2', on ports A through E
|
||||||
|
//
|
||||||
|
// Each port has 2 separate interrupt vectors. They can be assigned different pins.
|
||||||
|
// The same pin can also be assigned to both vectors on the same port, if desired.
|
||||||
|
|
||||||
|
#define PORTD_INT0 0
|
||||||
|
#define PORTD_INT1 1
|
||||||
|
#define PORTC_INT0 2
|
||||||
|
#define PORTC_INT1 3
|
||||||
|
#define PORTE_INT0 4
|
||||||
|
#define PORTE_INT1 5
|
||||||
|
#define PORTA_INT0 6
|
||||||
|
#define PORTA_INT1 7
|
||||||
|
#define PORTB_INT0 8
|
||||||
|
#define PORTB_INT1 9
|
||||||
|
#define PORTR_INT0 10
|
||||||
|
#define PORTR_INT1 11
|
||||||
|
|
||||||
|
#define EXTERNAL_NUM_INTERRUPTS 12 /* defined here instead of wiring_private.h - max value is 32 */
|
||||||
|
|
||||||
|
// was in wiring_external.h, moved here
|
||||||
|
#define EXTERNAL_INT_0 0
|
||||||
|
#define EXTERNAL_INT_1 1
|
||||||
|
#define EXTERNAL_INT_2 2
|
||||||
|
#define EXTERNAL_INT_3 3
|
||||||
|
#define EXTERNAL_INT_4 4
|
||||||
|
#define EXTERNAL_INT_5 5
|
||||||
|
#define EXTERNAL_INT_6 6
|
||||||
|
#define EXTERNAL_INT_7 7
|
||||||
|
#define EXTERNAL_INT_8 8
|
||||||
|
#define EXTERNAL_INT_9 9
|
||||||
|
#define EXTERNAL_INT_10 10
|
||||||
|
#define EXTERNAL_INT_11 11
|
||||||
|
|
||||||
|
// xmega 'D' series has 2 sets of UART and SPI.
|
||||||
|
// The default UART is assigned on Port D, pins PD2-3
|
||||||
|
// The default SPI is assigned on Port C, pins PC4-7
|
||||||
|
//
|
||||||
|
// Also there are multiple 2-wire ports, the default being assigned to PC0-1
|
||||||
|
// see definition for DEFAULT_TWI and USE_TWIC
|
||||||
|
//
|
||||||
|
// Standard GPIO pins are assigned as follows:
|
||||||
|
// PD0-7 Digital 0-7
|
||||||
|
// PC0-7 Digital 8-15
|
||||||
|
// PE0-3 digital 16-19
|
||||||
|
// PR0-1 digital 20-21
|
||||||
|
// PA0-7 analog A0-A7
|
||||||
|
// PB0-3 analog A8-A11
|
||||||
|
//
|
||||||
|
// '#define'ing DIGITAL_IO_PIN_SHIFT shifts this down by 2, and places PD0-1 on 20-21
|
||||||
|
// This is for Arduino 'atmega' compatibility with respect to existing shields, so that
|
||||||
|
// you don't have to re-map pin numbers with #defines in existing software that hard-codes them
|
||||||
|
// or makes assumptions about pin numbers vs functionality [except TWI won't ever match up]
|
||||||
|
//
|
||||||
|
// '#define'ing USE_TWIC puts PC0-1 on 20-21 (corresponding to TWI pins on later Arduinos)
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ALL PORT REMAP registers must be assigned to 0 (default mappings for pins)
|
||||||
|
// this puts PWM output on pins 0-3 for PORT E (the timers are split for C and D)
|
||||||
|
// Additionally, CLKOUT should be 0 (no clock outputs on any port/pin).
|
||||||
|
//
|
||||||
|
// TIMERS
|
||||||
|
// Timer 0 should be configured as 'Tx2' (for 8 PWM outputs) by default, essentially
|
||||||
|
// as a dual 8-bit timer, more or less compatible with the Arduino's 3 timers and
|
||||||
|
// supporting all 8 pins on ports C and D for PWM output. Port C's timer supports
|
||||||
|
// the system clock.
|
||||||
|
//
|
||||||
|
// See 'D' manual chapter 13 for more on this
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// DEFINITIONS FOR SERIAL PORTS AND TWI PORTS
|
||||||
|
// ------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// TWI ports
|
||||||
|
#define DEFAULT_TWI TWIC /* note see definitions for SDA and SCL, below - alter accordingly */
|
||||||
|
|
||||||
|
// the XMega64D4 has two TWI ports
|
||||||
|
#define TWI_PORT0 TWIC
|
||||||
|
#define TWI_VECTOR_S0 TWIC_TWIS_vect
|
||||||
|
#define TWI_VECTOR_M0 TWIC_TWIM_vect
|
||||||
|
#define TWI_PORT1 TWIE
|
||||||
|
#define TWI_VECTOR_S1 TWIE_TWIS_vect
|
||||||
|
#define TWI_VECTOR_M1 TWIE_TWIM_vect
|
||||||
|
|
||||||
|
#define TWI_INTERFACE_COUNT 2
|
||||||
|
|
||||||
|
|
||||||
|
// obsolete - consider removal in all of them
|
||||||
|
//#define TWIC_VECT_ENABLE /* use this to select the correct interrupt vectors for default */
|
||||||
|
|
||||||
|
|
||||||
|
// serial port 0
|
||||||
|
#define SERIAL_0_PORT_NAME PORTD
|
||||||
|
#define SERIAL_0_USART_NAME USARTD0
|
||||||
|
#define SERIAL_0_USART_DATA USARTD0_DATA
|
||||||
|
#define SERIAL_0_RXC_ISR ISR(USARTD0_RXC_vect)
|
||||||
|
#define SERIAL_0_DRE_ISR ISR(USARTD0_DRE_vect)
|
||||||
|
//#define SERIAL_0_REMAP PORTD_REMAP /* define THIS to re-map the pins from 0-3 to 4-7 on serial port 0 */
|
||||||
|
#define SERIAL_0_REMAP_BIT 4 /* the bit needed to remap the port if SERIAL_0_REMAP is defined */
|
||||||
|
#define SERIAL_0_RX_PIN_INDEX 2 /* the pin number on the port, not the mapped digital pin number */
|
||||||
|
#define SERIAL_0_TX_PIN_INDEX 3 /* the pin number on the port, not the mapped digital pin number */
|
||||||
|
#define USARTD0_VECTOR_EXISTS
|
||||||
|
|
||||||
|
// serial port 1
|
||||||
|
#define SERIAL_1_PORT_NAME PORTC
|
||||||
|
#define SERIAL_1_USART_NAME USARTC0
|
||||||
|
#define SERIAL_1_USART_DATA USARTC0_DATA
|
||||||
|
#define SERIAL_1_RXC_ISR ISR(USARTC0_RXC_vect)
|
||||||
|
#define SERIAL_1_DRE_ISR ISR(USARTC0_DRE_vect)
|
||||||
|
//#define SERIAL_1_REMAP PORTC_REMAP /* define THIS to re-map the pins from 0-3 to 4-7 on serial port 1 */
|
||||||
|
#define SERIAL_1_REMAP_BIT 4 /* the bit needed to remap the port if SERIAL_1_REMAP is defined */
|
||||||
|
#define SERIAL_1_RX_PIN_INDEX 2 /* the pin number on the port, not the mapped digital pin number */
|
||||||
|
#define SERIAL_1_TX_PIN_INDEX 3 /* the pin number on the port, not the mapped digital pin number */
|
||||||
|
#define USARTC0_VECTOR_EXISTS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// For atmega/Arduino shield compatibility, with DIGITAL_IO_PIN_SHIFT defined
|
||||||
|
// typical board/pin layout might be like this (for shield pins):
|
||||||
|
//
|
||||||
|
// NOTE: this design/layout assumes USE_TWIC is defined, so TWI is on TWIC (port C pins 0/1)
|
||||||
|
//
|
||||||
|
// M M
|
||||||
|
// S I O T R
|
||||||
|
// A C S S S x x
|
||||||
|
// S S R G K O I S 2 2 T R
|
||||||
|
// C D E N 1 1 1 1 x x
|
||||||
|
// L A F D 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
// ----o-o-o-o-o-o-o-o-o-o--o-o-o-o-o-o-o-o----
|
||||||
|
// P P P P P P P P P P P P P P P P
|
||||||
|
// C C C C C C C C C C D D D D D D
|
||||||
|
// 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// T O P V I E W
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// P P P P P P
|
||||||
|
// A A A A A A
|
||||||
|
// 5 4 3 2 1 0
|
||||||
|
// ------------o-o-o-o-o-o-o-o--o-o-o-o-o-o----
|
||||||
|
// G I R 3 5 G G V A A A A A A
|
||||||
|
// N O E . V N N i 5 4 3 2 1 0
|
||||||
|
// D R S 3 D D n
|
||||||
|
// E E V
|
||||||
|
// F T
|
||||||
|
//
|
||||||
|
// As with the MEGA2560 and other 'mega' Arduino boards, additional connectors would
|
||||||
|
// break out the additional pins, with appropriate labeling. Additionally, there should
|
||||||
|
// be an LED on PORTR pin 1 for 'LED_BUILTIN'.
|
||||||
|
//
|
||||||
|
// This layout is based on the 'Rev 3' Arduino.
|
||||||
|
//
|
||||||
|
// NOTE - NO AREF: AREF is not connected. AREF is a bit of an issue on xmega because
|
||||||
|
// it DOES! NOT! WORK! THE! SAME! as it does on the ATmegaXXX and so you would need to
|
||||||
|
// (literally) steal one of the additional analog input pins to implement it. It's not
|
||||||
|
// impossible, or even THAT difficult. I'm just not doing it here.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DIGITAL_IO_PIN_SHIFT // aka digital I/O pin 0 is PORTD pin 2
|
||||||
|
|
||||||
|
// SHIFTED I/O pins (atmega compatibility) - see xmega mod description in comment at top
|
||||||
|
|
||||||
|
// default SPI
|
||||||
|
static const uint8_t SS = 10;
|
||||||
|
static const uint8_t MOSI = 11;
|
||||||
|
static const uint8_t MISO = 12;
|
||||||
|
static const uint8_t SCK = 13;
|
||||||
|
|
||||||
|
// primary SPI on PC4-7
|
||||||
|
static const uint8_t SS0 = 10;
|
||||||
|
static const uint8_t MOSI0 = 11;
|
||||||
|
static const uint8_t MISO0 = 12;
|
||||||
|
static const uint8_t SCK0 = 13;
|
||||||
|
|
||||||
|
// secondary SPI on PD4-7
|
||||||
|
static const uint8_t SS1 = 2;
|
||||||
|
static const uint8_t MOSI1 = 3;
|
||||||
|
static const uint8_t MISO1 = 4;
|
||||||
|
static const uint8_t SCK1 = 5;
|
||||||
|
|
||||||
|
// default 2-wire on PC0,PC1 - TWIC
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
static const uint8_t SDA = 20;
|
||||||
|
static const uint8_t SCL = 21;
|
||||||
|
#else // !USE_TWIC
|
||||||
|
static const uint8_t SDA = 6;
|
||||||
|
static const uint8_t SCL = 7;
|
||||||
|
#endif // USE_TWIC
|
||||||
|
|
||||||
|
// port-specific 2-wire
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
static const uint8_t SDA0 = 20;
|
||||||
|
static const uint8_t SCL0 = 21;
|
||||||
|
#else // !USE_TWIC
|
||||||
|
static const uint8_t SDA0 = 6;
|
||||||
|
static const uint8_t SCL0 = 7;
|
||||||
|
#endif // USE_TWIC
|
||||||
|
static const uint8_t SDA1 = 14;
|
||||||
|
static const uint8_t SCL1 = 15;
|
||||||
|
|
||||||
|
|
||||||
|
// keep track of the indices for port R since its control register
|
||||||
|
// settings should be slightly different - D manual table 11-6
|
||||||
|
#define PR0 18
|
||||||
|
#define PR1 19
|
||||||
|
|
||||||
|
#else // no digital I/O pin shifting, PORTD pin 0 is digital I/O pin 0 (as it should be)
|
||||||
|
|
||||||
|
// default "no shift" pin assignments
|
||||||
|
|
||||||
|
// default SPI
|
||||||
|
static const uint8_t SS = 12;
|
||||||
|
static const uint8_t MOSI = 13;
|
||||||
|
static const uint8_t MISO = 14;
|
||||||
|
static const uint8_t SCK = 15;
|
||||||
|
|
||||||
|
// primary SPI on PC4-7
|
||||||
|
static const uint8_t SS0 = 12;
|
||||||
|
static const uint8_t MOSI0 = 13;
|
||||||
|
static const uint8_t MISO0 = 14;
|
||||||
|
static const uint8_t SCK0 = 15;
|
||||||
|
|
||||||
|
// secondary SPI on PD4-7
|
||||||
|
static const uint8_t SS1 = 4;
|
||||||
|
static const uint8_t MOSI1 = 5;
|
||||||
|
static const uint8_t MISO1 = 6;
|
||||||
|
static const uint8_t SCK1 = 7;
|
||||||
|
|
||||||
|
// default 2-wire on PC0,PC1 - TWIC (TWIE appears to be broken)
|
||||||
|
static const uint8_t SDA = 8;
|
||||||
|
static const uint8_t SCL = 9;
|
||||||
|
static const uint8_t SDA0 = 8;
|
||||||
|
static const uint8_t SCL0 = 9;
|
||||||
|
static const uint8_t SDA1 = 16;
|
||||||
|
static const uint8_t SCL1 = 17;
|
||||||
|
|
||||||
|
// keep track of the indices for port R since its control register
|
||||||
|
// settings should be slightly different - D manual table 11-6
|
||||||
|
#define PR0 20
|
||||||
|
#define PR1 21
|
||||||
|
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
|
||||||
|
|
||||||
|
// default 'status' LED on PR1
|
||||||
|
//static const uint8_t LED_BUILTIN = PR1;
|
||||||
|
#define LED_BUILTIN PR1 /* Arduino 1.06 uses #define, not a const uint8_t */
|
||||||
|
|
||||||
|
static const uint8_t A0 = 22;
|
||||||
|
static const uint8_t A1 = 23;
|
||||||
|
static const uint8_t A2 = 24;
|
||||||
|
static const uint8_t A3 = 25;
|
||||||
|
static const uint8_t A4 = 26;
|
||||||
|
static const uint8_t A5 = 27;
|
||||||
|
static const uint8_t A6 = 28;
|
||||||
|
static const uint8_t A7 = 29;
|
||||||
|
static const uint8_t A8 = 30;
|
||||||
|
static const uint8_t A9 = 31;
|
||||||
|
static const uint8_t A10 = 32;
|
||||||
|
static const uint8_t A11 = 33;
|
||||||
|
|
||||||
|
// on the xmega64d4, PA2, PB2, PC2, PD2, and PE2 are asynchronous ints. Others are 'synchronous' which means
|
||||||
|
// that they must be held in their 'interrupt state' long enough for the system to detect them. In any case
|
||||||
|
// all digital input pins can be use as interrupts, synchronous or otherwise.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ARDUINO_MAIN
|
||||||
|
|
||||||
|
|
||||||
|
const uint16_t PROGMEM port_to_mode_PGM[] = {
|
||||||
|
NOT_A_PORT, // 0
|
||||||
|
(uint16_t) &PORTA_DIR, // PA
|
||||||
|
(uint16_t) &PORTB_DIR, // PB
|
||||||
|
(uint16_t) &PORTC_DIR, // PC
|
||||||
|
(uint16_t) &PORTD_DIR, // PD
|
||||||
|
(uint16_t) &PORTE_DIR, // PE
|
||||||
|
(uint16_t) &PORTR_DIR, // PR
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM port_to_output_PGM[] = {
|
||||||
|
NOT_A_PORT, // 0
|
||||||
|
(uint16_t) &PORTA_OUT, // PA
|
||||||
|
(uint16_t) &PORTB_OUT, // PB
|
||||||
|
(uint16_t) &PORTC_OUT, // PC
|
||||||
|
(uint16_t) &PORTD_OUT, // PD
|
||||||
|
(uint16_t) &PORTE_OUT, // PE
|
||||||
|
(uint16_t) &PORTR_OUT, // PR
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM port_to_input_PGM[] = {
|
||||||
|
NOT_A_PORT, // 0
|
||||||
|
(uint16_t) &PORTA_IN, // PA
|
||||||
|
(uint16_t) &PORTB_IN, // PB
|
||||||
|
(uint16_t) &PORTC_IN, // PC
|
||||||
|
(uint16_t) &PORTD_IN, // PD
|
||||||
|
(uint16_t) &PORTE_IN, // PE
|
||||||
|
(uint16_t) &PORTR_IN, // PR
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_int0_PGM[] = {
|
||||||
|
NOT_AN_INTERRUPT, // 0
|
||||||
|
PORTA_INT0, // PA
|
||||||
|
PORTB_INT0, // PB
|
||||||
|
PORTC_INT0, // PC
|
||||||
|
PORTD_INT0, // PD
|
||||||
|
PORTE_INT0, // PE
|
||||||
|
PORTR_INT0, // PR
|
||||||
|
};
|
||||||
|
|
||||||
|
// xmega has a per-pin config register as well. Normally these will be 00000111 for analog, 00000000 for digital 'totem pole'
|
||||||
|
// for 'INPUT_PULLUP' these will be 00011111
|
||||||
|
// bits 2:0 (trigger) 000 both edges 001 rising 010 falling 011 level 111 input buffer disabled
|
||||||
|
// note: 'input buffer disabled' required to use the 'IN' register (so default here)
|
||||||
|
// also port R does not support 'INTPUT_DISABLED' (sic) so use BOTHEDGES [0] instead
|
||||||
|
// bits 5:3 (out/pull) 000 TOTEM [normal], 001 bus keeper [sticky], 010 pulldown, 011 pullup,
|
||||||
|
// 100 wired 'or', 101 wired 'and', 110 wired 'or' pulldown, 111 wired 'and' pullup
|
||||||
|
// bit 6: "invert logic" (0 = normal, 1 = inverted)
|
||||||
|
// bit 7: unused, must be zero
|
||||||
|
// NOTE: PORTA through PORTE (PORTF?) support 'input buffer disabled' and this setting is recommended
|
||||||
|
// for analog inputs. PORTR apparently does NOT support this (set to zero?)
|
||||||
|
|
||||||
|
const uint16_t PROGMEM digital_pin_to_control_PGM[] = {
|
||||||
|
#ifndef DIGITAL_IO_PIN_SHIFT
|
||||||
|
(uint16_t) &PORTD_PIN0CTRL, // PD 0 ** 0 **
|
||||||
|
(uint16_t) &PORTD_PIN1CTRL, // PD 1 ** 1 **
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined
|
||||||
|
(uint16_t) &PORTD_PIN2CTRL, // PD 2 ** 2 ** USARTD_RX ASYNC
|
||||||
|
(uint16_t) &PORTD_PIN3CTRL, // PD 3 ** 3 ** USARTD_TX
|
||||||
|
(uint16_t) &PORTD_PIN4CTRL, // PD 4 ** 4 **
|
||||||
|
(uint16_t) &PORTD_PIN5CTRL, // PD 5 ** 5 **
|
||||||
|
(uint16_t) &PORTD_PIN6CTRL, // PD 6 ** 6 **
|
||||||
|
(uint16_t) &PORTD_PIN7CTRL, // PD 7 ** 7 **
|
||||||
|
#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
(uint16_t) &PORTD_PIN0CTRL, // PD 0 ** 8 ** map PORTD pins 0/1 here if TWIC is used
|
||||||
|
(uint16_t) &PORTD_PIN1CTRL, // PD 1 ** 9 **
|
||||||
|
#else
|
||||||
|
(uint16_t) &PORTC_PIN0CTRL, // PC 0 ** 8 ** SDA
|
||||||
|
(uint16_t) &PORTC_PIN1CTRL, // PC 1 ** 9 ** SCL
|
||||||
|
#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
(uint16_t) &PORTC_PIN2CTRL, // PC 2 ** 10 ** ASYNC
|
||||||
|
(uint16_t) &PORTC_PIN3CTRL, // PC 3 ** 11 **
|
||||||
|
(uint16_t) &PORTC_PIN4CTRL, // PC 4 ** 12 ** SPI_SS
|
||||||
|
(uint16_t) &PORTC_PIN5CTRL, // PC 5 ** 13 ** SPI_MOSI
|
||||||
|
(uint16_t) &PORTC_PIN6CTRL, // PC 6 ** 14 ** SPI_MISO
|
||||||
|
(uint16_t) &PORTC_PIN7CTRL, // PC 7 ** 15 ** SPI_SCK
|
||||||
|
(uint16_t) &PORTE_PIN0CTRL, // PE 0 ** 16 ** SDA1
|
||||||
|
(uint16_t) &PORTE_PIN1CTRL, // PE 1 ** 17 ** SCL1
|
||||||
|
(uint16_t) &PORTE_PIN2CTRL, // PE 2 ** 18 ** ASYNC
|
||||||
|
(uint16_t) &PORTE_PIN3CTRL, // PE 3 ** 19 **
|
||||||
|
(uint16_t) &PORTR_PIN0CTRL, // PR 0 ** 20 **
|
||||||
|
(uint16_t) &PORTR_PIN1CTRL, // PR 1 ** 21 ** default LED
|
||||||
|
#ifdef DIGITAL_IO_PIN_SHIFT
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
(uint16_t) &PORTC_PIN0CTRL, // PC 0 ** the new 20 ** SDA, SDA0
|
||||||
|
(uint16_t) &PORTC_PIN1CTRL, // PC 1 ** the new 21 ** SCL, SCL0
|
||||||
|
#else
|
||||||
|
(uint16_t) &PORTD_PIN0CTRL, // PD 0 ** the new 20 **
|
||||||
|
(uint16_t) &PORTD_PIN1CTRL, // PD 1 ** the new 21 **
|
||||||
|
#endif // USE_TWIC
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
(uint16_t) &PORTA_PIN0CTRL, // PA 0 ** 22 ** A0
|
||||||
|
(uint16_t) &PORTA_PIN1CTRL, // PA 1 ** 23 ** A1
|
||||||
|
(uint16_t) &PORTA_PIN2CTRL, // PA 2 ** 24 ** A2 ASYNC
|
||||||
|
(uint16_t) &PORTA_PIN3CTRL, // PA 3 ** 25 ** A3
|
||||||
|
(uint16_t) &PORTA_PIN4CTRL, // PA 4 ** 26 ** A4
|
||||||
|
(uint16_t) &PORTA_PIN5CTRL, // PA 5 ** 27 ** A5
|
||||||
|
(uint16_t) &PORTA_PIN6CTRL, // PA 6 ** 28 ** A6
|
||||||
|
(uint16_t) &PORTA_PIN7CTRL, // PA 7 ** 29 ** A7
|
||||||
|
(uint16_t) &PORTB_PIN0CTRL, // PB 0 ** 30 ** A8
|
||||||
|
(uint16_t) &PORTB_PIN1CTRL, // PB 1 ** 31 ** A9
|
||||||
|
(uint16_t) &PORTB_PIN2CTRL, // PB 2 ** 32 ** A10 ASYNC
|
||||||
|
(uint16_t) &PORTB_PIN3CTRL, // PB 3 ** 33 ** A11
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
|
||||||
|
// PORTLIST
|
||||||
|
// -------------------------------------------
|
||||||
|
#ifndef DIGITAL_IO_PIN_SHIFT
|
||||||
|
_PD, // PD 0 ** 0 **
|
||||||
|
_PD, // PD 1 ** 1 **
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined
|
||||||
|
_PD, // PD 2 ** 2 ** USARTD_RX
|
||||||
|
_PD, // PD 3 ** 3 ** USARTD_TX
|
||||||
|
_PD, // PD 4 ** 4 **
|
||||||
|
_PD, // PD 5 ** 5 **
|
||||||
|
_PD, // PD 6 ** 6 **
|
||||||
|
_PD, // PD 7 ** 7 **
|
||||||
|
#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
_PD, // PD 0 ** 8 **
|
||||||
|
_PD, // PD 1 ** 9 **
|
||||||
|
#else
|
||||||
|
_PC, // PC 0 ** 8 ** SDA
|
||||||
|
_PC, // PC 1 ** 9 ** SCL
|
||||||
|
#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
_PC, // PC 2 ** 10 **
|
||||||
|
_PC, // PC 3 ** 11 **
|
||||||
|
_PC, // PC 4 ** 12 ** SPI_SS
|
||||||
|
_PC, // PC 5 ** 13 ** SPI_MOSI
|
||||||
|
_PC, // PC 6 ** 14 ** SPI_MISO
|
||||||
|
_PC, // PC 7 ** 15 ** SPI_SCK
|
||||||
|
_PE, // PE 0 ** 16 ** SDA
|
||||||
|
_PE, // PE 1 ** 17 ** SCL
|
||||||
|
_PE, // PE 2 ** 18 **
|
||||||
|
_PE, // PE 3 ** 19 **
|
||||||
|
_PR, // PR 0 ** 20 **
|
||||||
|
_PR, // PR 1 ** 21 ** default LED
|
||||||
|
#ifdef DIGITAL_IO_PIN_SHIFT
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
_PC, // PC 0 ** the new 20 ** SDA
|
||||||
|
_PC, // PC 1 ** the new 21 ** SCL
|
||||||
|
#else
|
||||||
|
_PD, // PD 0 ** the new 20 **
|
||||||
|
_PD, // PD 1 ** the new 21 **
|
||||||
|
#endif // USE_TWIC
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
_PA, // PA 0 ** 22 ** A0
|
||||||
|
_PA, // PA 1 ** 23 ** A1
|
||||||
|
_PA, // PA 2 ** 24 ** A2
|
||||||
|
_PA, // PA 3 ** 25 ** A3
|
||||||
|
_PA, // PA 4 ** 26 ** A4
|
||||||
|
_PA, // PA 5 ** 27 ** A5
|
||||||
|
_PA, // PA 6 ** 28 ** A6
|
||||||
|
_PA, // PA 7 ** 29 ** A7
|
||||||
|
_PB, // PB 0 ** 30 ** A8
|
||||||
|
_PB, // PB 1 ** 31 ** A9
|
||||||
|
_PB, // PB 2 ** 32 ** A10
|
||||||
|
_PB, // PB 3 ** 33 ** A11
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
|
||||||
|
// PIN IN PORT
|
||||||
|
// -------------------------------------------
|
||||||
|
#ifndef DIGITAL_IO_PIN_SHIFT
|
||||||
|
_BV( 0 ), // PD 0 ** 0 **
|
||||||
|
_BV( 1 ), // PD 1 ** 1 **
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined
|
||||||
|
_BV( 2 ), // PD 2 ** 2 ** USARTD_RX
|
||||||
|
_BV( 3 ), // PD 3 ** 3 ** USARTD_TX
|
||||||
|
_BV( 4 ), // PD 4 ** 4 **
|
||||||
|
_BV( 5 ), // PD 5 ** 5 **
|
||||||
|
_BV( 6 ), // PD 6 ** 6 **
|
||||||
|
_BV( 7 ), // PD 7 ** 7 **
|
||||||
|
#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
_BV( 0 ), // PD 0 ** 8 **
|
||||||
|
_BV( 1 ), // PD 1 ** 9 **
|
||||||
|
#else
|
||||||
|
_BV( 0 ), // PC 0 ** 8 ** SDA
|
||||||
|
_BV( 1 ), // PC 1 ** 9 ** SCL
|
||||||
|
#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
_BV( 2 ), // PC 2 ** 10 **
|
||||||
|
_BV( 3 ), // PC 3 ** 11 **
|
||||||
|
_BV( 4 ), // PC 4 ** 12 ** SPI_SS
|
||||||
|
_BV( 5 ), // PC 5 ** 13 ** SPI_MOSI
|
||||||
|
_BV( 6 ), // PC 6 ** 14 ** SPI_MISO
|
||||||
|
_BV( 7 ), // PC 7 ** 15 ** SPI_SCK
|
||||||
|
_BV( 0 ), // PE 0 ** 16 ** SDA
|
||||||
|
_BV( 1 ), // PE 1 ** 17 ** SCL
|
||||||
|
_BV( 2 ), // PE 2 ** 18 **
|
||||||
|
_BV( 3 ), // PE 3 ** 19 **
|
||||||
|
_BV( 0 ), // PR 0 ** 20 **
|
||||||
|
_BV( 1 ), // PR 1 ** 21 ** default LED
|
||||||
|
#ifdef DIGITAL_IO_PIN_SHIFT
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
_BV( 0 ), // PC 0 ** the new 20 ** SDA
|
||||||
|
_BV( 1 ), // PC 1 ** the new 21 ** SCL
|
||||||
|
#else
|
||||||
|
_BV( 0 ), // PD 0 ** the new 20 **
|
||||||
|
_BV( 1 ), // PD 1 ** the new 21 **
|
||||||
|
#endif // USE_TWIC
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
_BV( 0 ), // PA 0 ** 22 ** A0
|
||||||
|
_BV( 1 ), // PA 1 ** 23 ** A1
|
||||||
|
_BV( 2 ), // PA 2 ** 24 ** A2
|
||||||
|
_BV( 3 ), // PA 3 ** 25 ** A3
|
||||||
|
_BV( 4 ), // PA 4 ** 26 ** A4
|
||||||
|
_BV( 5 ), // PA 5 ** 27 ** A5
|
||||||
|
_BV( 6 ), // PA 6 ** 28 ** A6
|
||||||
|
_BV( 7 ), // PA 7 ** 29 ** A7
|
||||||
|
_BV( 0 ), // PB 0 ** 30 ** A8
|
||||||
|
_BV( 1 ), // PB 1 ** 31 ** A9
|
||||||
|
_BV( 2 ), // PB 2 ** 32 ** A10
|
||||||
|
_BV( 3 ), // PB 3 ** 33 ** A11
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
|
||||||
|
// TIMERS
|
||||||
|
// -------------------------------------------
|
||||||
|
// for now 'NOT_ON_TIMER' for all - later, assign timers based
|
||||||
|
// on pins 0-3 being enabled as PWM out for ports A through E
|
||||||
|
// corresponding to timers A through D (see D manual sections 11.12.14,
|
||||||
|
// also see D manual sect 13.6 for using the 'compare' channel on 'TCx2' to generate
|
||||||
|
// a PWM output. Must select pin as output, _AND_ enable the 'compare' output
|
||||||
|
// for the appropriate pin. LCMPENx/HCMPENx registers to enable it.
|
||||||
|
|
||||||
|
#ifndef DIGITAL_IO_PIN_SHIFT
|
||||||
|
TIMERD2, // PD 0 ** 0 **
|
||||||
|
TIMERD2, // PD 1 ** 1 **
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined
|
||||||
|
TIMERD2, // PD 2 ** 2 ** USARTD_RX
|
||||||
|
TIMERD2, // PD 3 ** 3 ** USARTD_TX
|
||||||
|
TIMERD2, // PD 4 ** 4 **
|
||||||
|
TIMERD2, // PD 5 ** 5 **
|
||||||
|
TIMERD2, // PD 6 ** 6 **
|
||||||
|
TIMERD2, // PD 7 ** 7 **
|
||||||
|
#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
TIMERD2, // PD 0 ** 8 **
|
||||||
|
TIMERD2, // PD 1 ** 9 **
|
||||||
|
#else
|
||||||
|
TIMERC2, // PC 0 ** 8 ** SDA
|
||||||
|
TIMERC2, // PC 1 ** 9 ** SCL
|
||||||
|
#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC)
|
||||||
|
TIMERC2, // PC 2 ** 10 **
|
||||||
|
TIMERC2, // PC 3 ** 11 **
|
||||||
|
TIMERC2, // PC 4 ** 12 ** SPI_SS
|
||||||
|
TIMERC2, // PC 5 ** 13 ** SPI_MOSI
|
||||||
|
TIMERC2, // PC 6 ** 14 ** SPI_MISO
|
||||||
|
TIMERC2, // PC 7 ** 15 ** SPI_SCK
|
||||||
|
TIMERE0, // PE 0 ** 16 ** SDA
|
||||||
|
TIMERE0, // PE 1 ** 17 ** SCL
|
||||||
|
TIMERE0, // PE 2 ** 18 **
|
||||||
|
TIMERE0, // PE 3 ** 19 **
|
||||||
|
NOT_ON_TIMER, // PR 0 ** 20 **
|
||||||
|
NOT_ON_TIMER, // PR 1 ** 21 ** default LED
|
||||||
|
#ifdef DIGITAL_IO_PIN_SHIFT
|
||||||
|
#ifdef USE_TWIC
|
||||||
|
TIMERC2, // PC 0 ** the new 20 ** SDA
|
||||||
|
TIMERC2, // PC 1 ** the new 21 ** SCL
|
||||||
|
#else
|
||||||
|
TIMERD2, // PD 0 ** the new 20 **
|
||||||
|
TIMERD2, // PD 1 ** the new 21 **
|
||||||
|
#endif // USE_TWIC
|
||||||
|
#endif // DIGITAL_IO_PIN_SHIFT
|
||||||
|
NOT_ON_TIMER, // PA 0 ** 22 ** A0
|
||||||
|
NOT_ON_TIMER, // PA 1 ** 23 ** A1
|
||||||
|
NOT_ON_TIMER, // PA 2 ** 24 ** A2
|
||||||
|
NOT_ON_TIMER, // PA 3 ** 25 ** A3
|
||||||
|
NOT_ON_TIMER, // PA 4 ** 26 ** A4
|
||||||
|
NOT_ON_TIMER, // PA 5 ** 27 ** A5
|
||||||
|
NOT_ON_TIMER, // PA 6 ** 28 ** A6
|
||||||
|
NOT_ON_TIMER, // PA 7 ** 29 ** A7
|
||||||
|
NOT_ON_TIMER, // PB 0 ** 30 ** A8
|
||||||
|
NOT_ON_TIMER, // PB 1 ** 31 ** A9
|
||||||
|
NOT_ON_TIMER, // PB 2 ** 32 ** A10
|
||||||
|
NOT_ON_TIMER, // PB 3 ** 33 ** A11
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// These serial port names are intended to allow libraries and architecture-neutral
|
||||||
|
// sketches to automatically default to the correct port name for a particular type
|
||||||
|
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
|
||||||
|
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
|
||||||
|
//
|
||||||
|
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
|
||||||
|
//
|
||||||
|
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
|
||||||
|
//
|
||||||
|
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
|
||||||
|
//
|
||||||
|
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
|
||||||
|
//
|
||||||
|
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
|
||||||
|
// pins are NOT connected to anything by default.
|
||||||
|
#define SERIAL_PORT_MONITOR Serial
|
||||||
|
#define SERIAL_PORT_HARDWARE Serial
|
||||||
|
#define SERIAL_HARDWARE_OPEN Serial2
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -103,7 +103,20 @@ recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).*
|
|||||||
## Save Compiled Binary
|
## Save Compiled Binary
|
||||||
recipe.output.tmp_file={build.project_name}.bin
|
recipe.output.tmp_file={build.project_name}.bin
|
||||||
#recipe.output.save_file={build.project_name}.{build.variant}.bin
|
#recipe.output.save_file={build.project_name}.{build.variant}.bin
|
||||||
recipe.output.save_file=multifw.bin
|
recipe.output.save_file=multi-stm.bin
|
||||||
|
|
||||||
|
## Copy hex
|
||||||
|
# Make a copy of the compiled binary with the version number in the file name
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
recipe.hooks.objcopy.postobjcopy.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board}
|
||||||
|
|
||||||
|
# If we're exporting the hex file, rename it with the version number
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
recipe.hooks.savehex.postsavehex.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT
|
||||||
|
|
||||||
# Uploader tools
|
# Uploader tools
|
||||||
# -------------------
|
# -------------------
|
||||||
|
0
BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util
Normal file → Executable file
47
BootLoaders/Boards/stm32/tools/linux/do_version
Executable file
47
BootLoaders/Boards/stm32/tools/linux/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=stm
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
17
BootLoaders/Boards/stm32/tools/linux/maple_upload
Normal file → Executable file
17
BootLoaders/Boards/stm32/tools/linux/maple_upload
Normal file → Executable file
@ -2,23 +2,32 @@
|
|||||||
|
|
||||||
#set -e
|
#set -e
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if [ $# -lt 4 ]; then
|
if [ $# -lt 4 ]; then
|
||||||
echo "Usage: $0 $# <dummy_port> <altID> <usbID> <binfile>" >&2
|
echo "Usage: $0 $# <dummy_port> <altID> <usbID> <binfile>" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dummy_port="$1"; altID="$2"; usbID="$3"; binfile="$4"; dummy_port_fullpath="/dev/$1"
|
dummy_port="$1"; altID="$2"; usbID="$3"; binfile="$4"; dummy_port_fullpath="/dev/$1"
|
||||||
|
|
||||||
if [ $# -eq 5 ]; then
|
if [ $# -eq 5 ]; then
|
||||||
dfuse_addr="--dfuse-address $5"
|
dfuse_addr="--dfuse-address $5"
|
||||||
else
|
else
|
||||||
dfuse_addr=""
|
dfuse_addr=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Get the directory where the script is running.
|
# Get the directory where the script is running.
|
||||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
|
# Get the right upload-reset tool
|
||||||
|
uname -m | grep "x86_64" 2>&1 1>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
# Do 64-bit stuff
|
||||||
|
RESET_UTIL=${DIR}/../linux64/upload-reset
|
||||||
|
else
|
||||||
|
# Do 32-bit stuff
|
||||||
|
RESET_UTIL=${DIR}/upload-reset
|
||||||
|
fi
|
||||||
|
|
||||||
# ----------------- IMPORTANT -----------------
|
# ----------------- IMPORTANT -----------------
|
||||||
# The 2nd parameter to upload-reset is the delay after resetting before it exits
|
# The 2nd parameter to upload-reset is the delay after resetting before it exits
|
||||||
# This value is in milliseonds
|
# This value is in milliseonds
|
||||||
@ -26,7 +35,7 @@ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
|||||||
# 750ms to 1500ms seems to work on my Mac
|
# 750ms to 1500ms seems to work on my Mac
|
||||||
|
|
||||||
|
|
||||||
"${DIR}/upload-reset" ${dummy_port_fullpath} 750
|
"${RESET_UTIL}" ${dummy_port_fullpath} 750
|
||||||
|
|
||||||
|
|
||||||
#DFU_UTIL=$(dirname $0)/dfu-util/dfu-util
|
#DFU_UTIL=$(dirname $0)/dfu-util/dfu-util
|
||||||
|
13
BootLoaders/Boards/stm32/tools/linux/serial_upload
Normal file → Executable file
13
BootLoaders/Boards/stm32/tools/linux/serial_upload
Normal file → Executable file
@ -1,2 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1"
|
port=$1
|
||||||
|
addr=$2
|
||||||
|
file=$3
|
||||||
|
|
||||||
|
uname -m | grep "x86_64" 2>&1 1>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
# Do 64-bit stuff
|
||||||
|
$(dirname $0)/../linux64/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port"
|
||||||
|
else
|
||||||
|
# Do 32-bit stuff
|
||||||
|
$(dirname $0)/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port"
|
||||||
|
fi
|
||||||
|
0
BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/tx_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/tx_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/upload-reset
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux/upload-reset
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util
Normal file → Executable file
47
BootLoaders/Boards/stm32/tools/linux64/do_version
Executable file
47
BootLoaders/Boards/stm32/tools/linux64/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=stm
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
0
BootLoaders/Boards/stm32/tools/linux64/maple_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/maple_upload
Normal file → Executable file
13
BootLoaders/Boards/stm32/tools/linux64/serial_upload
Normal file → Executable file
13
BootLoaders/Boards/stm32/tools/linux64/serial_upload
Normal file → Executable file
@ -1,2 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1"
|
port=$1
|
||||||
|
addr=$2
|
||||||
|
file=$3
|
||||||
|
|
||||||
|
uname -m | grep "x86_64" 2>&1 1>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
# Do 64-bit stuff
|
||||||
|
$(dirname $0)/../linux64/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port"
|
||||||
|
else
|
||||||
|
# Do 32-bit stuff
|
||||||
|
$(dirname $0)/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port"
|
||||||
|
fi
|
||||||
|
0
BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/tx_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/linux64/tx_upload
Normal file → Executable file
BIN
BootLoaders/Boards/stm32/tools/linux64/upload-reset
Normal file → Executable file
BIN
BootLoaders/Boards/stm32/tools/linux64/upload-reset
Normal file → Executable file
Binary file not shown.
0
BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util
Normal file → Executable file
47
BootLoaders/Boards/stm32/tools/macosx/do_version
Executable file
47
BootLoaders/Boards/stm32/tools/macosx/do_version
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PATH=$1
|
||||||
|
PROJECT_NAME=$2
|
||||||
|
SKETCH_PATH=$3
|
||||||
|
MULTI_BOARD=$4
|
||||||
|
EXPORT_FLAG=$5
|
||||||
|
|
||||||
|
MULTI_TYPE=stm
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then
|
||||||
|
MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}')
|
||||||
|
|
||||||
|
MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||||
|
else
|
||||||
|
MULTI_VERSION=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 5 ]; then
|
||||||
|
if [ $EXPORT_FLAG == "EXPORT" ]; then
|
||||||
|
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then
|
||||||
|
cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex"
|
||||||
|
fi
|
||||||
|
if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then
|
||||||
|
rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
0
BootLoaders/Boards/stm32/tools/macosx/maple_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/maple_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/serial_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/serial_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/tx_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/tx_upload
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/upload-reset
Normal file → Executable file
0
BootLoaders/Boards/stm32/tools/macosx/upload-reset
Normal file → Executable file
54
BootLoaders/Boards/stm32/tools/win/do_version.bat
Normal file
54
BootLoaders/Boards/stm32/tools/win/do_version.bat
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SETLOCAL EnableDelayedExpansion
|
||||||
|
|
||||||
|
SET BUILD_PATH=%1
|
||||||
|
SET PROJECT_NAME=%2
|
||||||
|
SET SKETCH_PATH=%3
|
||||||
|
SET MULTI_BOARD=%4
|
||||||
|
SET EXPORT_FLAG=%5
|
||||||
|
|
||||||
|
REM ECHO Multi board: %MULTI_BOARD%
|
||||||
|
|
||||||
|
SET MULTI_TYPE=stm
|
||||||
|
|
||||||
|
IF EXIST "%1\sketch\Multiprotocol.h" (
|
||||||
|
REM ECHO Getting Multi-MODULE firmware version from "%1\sketch\Multiprotocol.h"
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i
|
||||||
|
FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%D") do SET PATCH_VERSION=%%i
|
||||||
|
SET MULTI_VER=!MAJOR_VERSION!.!MINOR_VERSION!.!REVISION_VERSION!.!PATCH_VERSION!
|
||||||
|
) ELSE (
|
||||||
|
SET MULTI_VER=
|
||||||
|
)
|
||||||
|
|
||||||
|
REM ECHO Multi-MODULE firmware version: %MULTI_VER%
|
||||||
|
|
||||||
|
REM Copy the compiled file to the sketch folder with the version number in the file name
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" (
|
||||||
|
REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" (
|
||||||
|
REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF "%EXPORT_FLAG%"=="EXPORT" (
|
||||||
|
REM Copy the compiled file to the sketch folder with the version number in the file name
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" (
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" (
|
||||||
|
COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL
|
||||||
|
)
|
||||||
|
|
||||||
|
IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" (
|
||||||
|
DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL
|
||||||
|
)
|
||||||
|
IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" (
|
||||||
|
DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" >NUL
|
||||||
|
)
|
||||||
|
)
|
@ -1,9 +0,0 @@
|
|||||||
@ECHO OFF
|
|
||||||
|
|
||||||
FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i
|
|
||||||
FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i
|
|
||||||
FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i
|
|
||||||
FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%D") do SET PATCH_VERSION=%%i
|
|
||||||
|
|
||||||
SET MULTI_VER=%MAJOR_VERSION%.%MINOR_VERSION%.%REVISION_VERSION%.%PATCH_VERSION%
|
|
||||||
ECHO %MULTI_VER%
|
|
BIN
BootLoaders/package_multi_4in1_avr_board_v1.0.1.tar.gz
Normal file
BIN
BootLoaders/package_multi_4in1_avr_board_v1.0.1.tar.gz
Normal file
Binary file not shown.
@ -24,6 +24,23 @@
|
|||||||
}],
|
}],
|
||||||
"toolsDependencies": []
|
"toolsDependencies": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Multi 4-in-1 AVR Board",
|
||||||
|
"architecture": "avr",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"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_avr_board_v1.0.1.tar.gz",
|
||||||
|
"archiveFileName": "package_multi_4in1_avr_board_v1.0.1.tar.gz",
|
||||||
|
"checksum": "SHA-256:504A5C1ABFB366917FC35A3744CC21FA30D572AAA70007D2BC69277BC1D0E2C4",
|
||||||
|
"size": "3102",
|
||||||
|
"boards": [{
|
||||||
|
"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"
|
||||||
|
}],
|
||||||
|
"toolsDependencies": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Multi 4-in-1 STM32 Board",
|
"name": "Multi 4-in-1 STM32 Board",
|
||||||
"architecture": "STM32F1",
|
"architecture": "STM32F1",
|
||||||
@ -44,6 +61,44 @@
|
|||||||
"name": "arm-none-eabi-gcc",
|
"name": "arm-none-eabi-gcc",
|
||||||
"version": "4.8.3-2014q1"
|
"version": "4.8.3-2014q1"
|
||||||
}]
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Multi 4-in-1 STM32 Board",
|
||||||
|
"architecture": "STM32F1",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"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_stm32_board_v1.0.1.tar.gz",
|
||||||
|
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.1.tar.gz",
|
||||||
|
"checksum": "SHA-256:9CC271776146A6CEC8CFB5B8DAB4DB7270C6589B43BA5759D65984AB2D89EA96",
|
||||||
|
"size": "10336733",
|
||||||
|
"boards": [{
|
||||||
|
"name": "Multi 4-in-1 (STM32F103C)"
|
||||||
|
}],
|
||||||
|
"toolsDependencies": [{
|
||||||
|
"packager": "arduino",
|
||||||
|
"name": "arm-none-eabi-gcc",
|
||||||
|
"version": "4.8.3-2014q1"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Multi 4-in-1 OrangeRX Board",
|
||||||
|
"architecture": "orangerx",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"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_orangerx_board_v1.0.1.tar.gz",
|
||||||
|
"archiveFileName": "package_multi_4in1_orangerx_board_v1.0.1.tar.gz",
|
||||||
|
"checksum": "SHA-256:03D095CB9F79C881375B35C8F9671306224C03CE2F02117806E55903C77FF2D5",
|
||||||
|
"size": "162457",
|
||||||
|
"boards": [{
|
||||||
|
"name": "Multi 4-in-1 (OrangeRX)"
|
||||||
|
}],
|
||||||
|
"toolsDependencies": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tools": []
|
"tools": []
|
||||||
|
BIN
BootLoaders/package_multi_4in1_orangerx_board_v1.0.1.tar.gz
Normal file
BIN
BootLoaders/package_multi_4in1_orangerx_board_v1.0.1.tar.gz
Normal file
Binary file not shown.
BIN
BootLoaders/package_multi_4in1_stm32_board_v1.0.1.tar.gz
Normal file
BIN
BootLoaders/package_multi_4in1_stm32_board_v1.0.1.tar.gz
Normal file
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
@echo off
|
|
||||||
if "%AVR32_HOME%"=="" (
|
|
||||||
echo.
|
|
||||||
echo You must install winavr to compile Multi for OrangeTX: https://sourceforge.net/projects/winavr/
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
exit /b
|
|
||||||
)
|
|
||||||
if exist MultiOrange.cpp.orangetx ren *.orangetx *.
|
|
||||||
if exist .dep (make clean)
|
|
||||||
md .dep
|
|
||||||
make
|
|
||||||
if exist MultiOrange.hex (
|
|
||||||
avr-objcopy -I ihex MultiOrange.hex -O binary MultiOrange.bin
|
|
||||||
echo.
|
|
||||||
echo Compilation OK.
|
|
||||||
echo Use MultiOrange.hex or MultiOrange.bin to program your OrangeTX module.
|
|
||||||
echo.
|
|
||||||
)
|
|
||||||
pause
|
|
@ -1,624 +0,0 @@
|
|||||||
# Hey Emacs, this is a -*- makefile -*-
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# WinAVR Makefile
|
|
||||||
#
|
|
||||||
# On command line:
|
|
||||||
#
|
|
||||||
# make all = Make software.
|
|
||||||
#
|
|
||||||
# make clean = Clean out built project files.
|
|
||||||
#
|
|
||||||
# make coff = Convert ELF to AVR COFF.
|
|
||||||
#
|
|
||||||
# make extcoff = Convert ELF to AVR Extended COFF.
|
|
||||||
#
|
|
||||||
# make program = Download the hex file to the device, using avrdude.
|
|
||||||
# Please customize the avrdude settings below first!
|
|
||||||
#
|
|
||||||
# make debug = Start either simulavr or avarice as specified for debugging,
|
|
||||||
# with avr-gdb or avr-insight as the front end for debugging.
|
|
||||||
#
|
|
||||||
# make filename.s = Just compile filename.c into the assembler code only.
|
|
||||||
#
|
|
||||||
# make filename.i = Create a preprocessed source file for use in submitting
|
|
||||||
# bug reports to the GCC project.
|
|
||||||
#
|
|
||||||
# To rebuild project do "make clean" then "make all".
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# MCU name
|
|
||||||
MCU = atxmega32d4
|
|
||||||
|
|
||||||
|
|
||||||
# Processor frequency.
|
|
||||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
|
||||||
# processor frequency. You can then use this symbol in your source code to
|
|
||||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
|
||||||
# automatically to create a 32-bit value in your source code.
|
|
||||||
# Typical values are:
|
|
||||||
# F_CPU = 1000000
|
|
||||||
# F_CPU = 1843200
|
|
||||||
# F_CPU = 2000000
|
|
||||||
# F_CPU = 3686400
|
|
||||||
# F_CPU = 4000000
|
|
||||||
# F_CPU = 7372800
|
|
||||||
# F_CPU = 8000000
|
|
||||||
# F_CPU = 11059200
|
|
||||||
# F_CPU = 14745600
|
|
||||||
# F_CPU = 16000000
|
|
||||||
# F_CPU = 18432000
|
|
||||||
# F_CPU = 20000000
|
|
||||||
F_CPU = 32000000
|
|
||||||
|
|
||||||
|
|
||||||
# Output format. (can be srec, ihex, binary)
|
|
||||||
FORMAT = ihex
|
|
||||||
|
|
||||||
|
|
||||||
# Target file name (without extension).
|
|
||||||
TARGET = MultiOrange
|
|
||||||
|
|
||||||
|
|
||||||
# Object files directory
|
|
||||||
# To put object files in current directory, use a dot (.), do NOT make
|
|
||||||
# this an empty or blank macro!
|
|
||||||
OBJDIR = .
|
|
||||||
|
|
||||||
|
|
||||||
# List C source files here. (C dependencies are automatically generated.)
|
|
||||||
SRC =
|
|
||||||
|
|
||||||
|
|
||||||
# List C++ source files here. (C dependencies are automatically generated.)
|
|
||||||
CPPSRC = $(TARGET).cpp
|
|
||||||
CPPSRC += Wmath.cpp
|
|
||||||
#CPPSRC += DSM2_cyrf6936.cpp
|
|
||||||
|
|
||||||
# List Assembler source files here.
|
|
||||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
|
||||||
# will not be considered source files but generated files (assembler
|
|
||||||
# output from the compiler), and will be deleted upon "make clean"!
|
|
||||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
|
||||||
# it will preserve the spelling of the filenames, and gcc itself does
|
|
||||||
# care about how the name is spelled on its command-line.
|
|
||||||
ASRC =
|
|
||||||
|
|
||||||
|
|
||||||
# Optimization level, can be [0, 1, 2, 3, s].
|
|
||||||
# 0 = turn off optimization. s = optimize for size.
|
|
||||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
|
||||||
OPT = s
|
|
||||||
|
|
||||||
|
|
||||||
# Debugging format.
|
|
||||||
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
|
||||||
# AVR Studio 4.10 requires dwarf-2.
|
|
||||||
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
|
|
||||||
#DEBUG = stabs
|
|
||||||
DEBUG = dwarf-2
|
|
||||||
|
|
||||||
|
|
||||||
# List any extra directories to look for include files here.
|
|
||||||
# Each directory must be seperated by a space.
|
|
||||||
# Use forward slashes for directory separators.
|
|
||||||
# For a directory that has spaces, enclose it in quotes.
|
|
||||||
EXTRAINCDIRS =
|
|
||||||
|
|
||||||
|
|
||||||
# Compiler flag to set the C Standard level.
|
|
||||||
# c89 = "ANSI" C
|
|
||||||
# gnu89 = c89 plus GCC extensions
|
|
||||||
# c99 = ISO C99 standard (not yet fully implemented)
|
|
||||||
# gnu99 = c99 plus GCC extensions
|
|
||||||
CSTANDARD = -std=gnu99
|
|
||||||
|
|
||||||
|
|
||||||
# Place -D or -U options here for C sources
|
|
||||||
CDEFS = -DF_CPU=$(F_CPU)UL
|
|
||||||
|
|
||||||
|
|
||||||
# Place -D or -U options here for ASM sources
|
|
||||||
ADEFS = -DF_CPU=$(F_CPU)
|
|
||||||
|
|
||||||
|
|
||||||
# Place -D or -U options here for C++ sources
|
|
||||||
CPPDEFS = -DF_CPU=$(F_CPU)UL
|
|
||||||
#CPPDEFS += -D__STDC_LIMIT_MACROS
|
|
||||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Compiler Options C ----------------
|
|
||||||
# -g*: generate debugging information
|
|
||||||
# -O*: optimization level
|
|
||||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
|
||||||
# -Wall...: warning level
|
|
||||||
# -Wa,...: tell GCC to pass this to the assembler.
|
|
||||||
# -adhlns...: create assembler listing
|
|
||||||
CFLAGS = -g$(DEBUG)
|
|
||||||
CFLAGS += $(CDEFS)
|
|
||||||
CFLAGS += -O$(OPT)
|
|
||||||
CFLAGS += -funsigned-char
|
|
||||||
CFLAGS += -funsigned-bitfields
|
|
||||||
CFLAGS += -fpack-struct
|
|
||||||
CFLAGS += -fshort-enums
|
|
||||||
CFLAGS += -Wall
|
|
||||||
CFLAGS += -Wno-main
|
|
||||||
CFLAGS += -Wstrict-prototypes
|
|
||||||
#CFLAGS += -mshort-calls
|
|
||||||
#CFLAGS += -fno-unit-at-a-time
|
|
||||||
#CFLAGS += -Wundef
|
|
||||||
#CFLAGS += -Wunreachable-code
|
|
||||||
#CFLAGS += -Wsign-compare
|
|
||||||
CFLAGS += -Wa,-adlns=$(<:%.c=$(OBJDIR)/%.lst)
|
|
||||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
|
||||||
CFLAGS += $(CSTANDARD)
|
|
||||||
# Next line dumps rtl file
|
|
||||||
#CFLAGS += -dr
|
|
||||||
#CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Compiler Options C++ ----------------
|
|
||||||
# -g*: generate debugging information
|
|
||||||
# -O*: optimization level
|
|
||||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
|
||||||
# -Wall...: warning level
|
|
||||||
# -Wa,...: tell GCC to pass this to the assembler.
|
|
||||||
# -adhlns...: create assembler listing
|
|
||||||
CPPFLAGS = -g$(DEBUG)
|
|
||||||
CPPFLAGS += $(CPPDEFS)
|
|
||||||
CPPFLAGS += -O$(OPT)
|
|
||||||
CPPFLAGS += -funsigned-char
|
|
||||||
CPPFLAGS += -funsigned-bitfields
|
|
||||||
CPPFLAGS += -fpack-struct
|
|
||||||
CPPFLAGS += -fshort-enums
|
|
||||||
CPPFLAGS += -fno-exceptions
|
|
||||||
CPPFLAGS += -Wall
|
|
||||||
CFLAGS += -Wundef
|
|
||||||
#CPPFLAGS += -mshort-calls
|
|
||||||
#CPPFLAGS += -fno-unit-at-a-time
|
|
||||||
#CPPFLAGS += -Wstrict-prototypes
|
|
||||||
#CPPFLAGS += -Wunreachable-code
|
|
||||||
#CPPFLAGS += -Wsign-compare
|
|
||||||
CPPFLAGS += -Wa,-adlns=$(<:%.cpp=$(OBJDIR)/%.lst)
|
|
||||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
|
||||||
#CPPFLAGS += $(CSTANDARD)
|
|
||||||
#CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Assembler Options ----------------
|
|
||||||
# -Wa,...: tell GCC to pass this to the assembler.
|
|
||||||
# -adhlns: create listing
|
|
||||||
# -gstabs: have the assembler create line number information; note that
|
|
||||||
# for use in COFF files, additional information about filenames
|
|
||||||
# and function names needs to be present in the assembler source
|
|
||||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
|
||||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
|
|
||||||
# dump that will be displayed for a given single line of source input.
|
|
||||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Library Options ----------------
|
|
||||||
# Minimalistic printf version
|
|
||||||
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
|
|
||||||
|
|
||||||
# Floating point printf version (requires MATH_LIB = -lm below)
|
|
||||||
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
|
|
||||||
|
|
||||||
# If this is left blank, then it will use the Standard printf version.
|
|
||||||
PRINTF_LIB =
|
|
||||||
#PRINTF_LIB = $(PRINTF_LIB_MIN)
|
|
||||||
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
|
|
||||||
|
|
||||||
|
|
||||||
# Minimalistic scanf version
|
|
||||||
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
|
|
||||||
|
|
||||||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
|
|
||||||
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
|
|
||||||
|
|
||||||
# If this is left blank, then it will use the Standard scanf version.
|
|
||||||
SCANF_LIB =
|
|
||||||
#SCANF_LIB = $(SCANF_LIB_MIN)
|
|
||||||
#SCANF_LIB = $(SCANF_LIB_FLOAT)
|
|
||||||
|
|
||||||
|
|
||||||
MATH_LIB = -lm
|
|
||||||
|
|
||||||
|
|
||||||
# List any extra directories to look for libraries here.
|
|
||||||
# Each directory must be seperated by a space.
|
|
||||||
# Use forward slashes for directory separators.
|
|
||||||
# For a directory that has spaces, enclose it in quotes.
|
|
||||||
EXTRALIBDIRS =
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- External Memory Options ----------------
|
|
||||||
|
|
||||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
|
||||||
# used for variables (.data/.bss) and heap (malloc()).
|
|
||||||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
|
|
||||||
|
|
||||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
|
||||||
# only used for heap (malloc()).
|
|
||||||
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
|
|
||||||
|
|
||||||
EXTMEMOPTS =
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Linker Options ----------------
|
|
||||||
# -Wl,...: tell GCC to pass this to linker.
|
|
||||||
# -Map: create map file
|
|
||||||
# --cref: add cross reference to map file
|
|
||||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
|
||||||
LDFLAGS += $(EXTMEMOPTS)
|
|
||||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
|
|
||||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
|
||||||
#LDFLAGS += -Wl,--section-start=.text=0x00D0
|
|
||||||
#LDFLAGS += -Wl,--section-start=.vectors=0x0080
|
|
||||||
#LDFLAGS += -T avr3-167.ld
|
|
||||||
LDFLAGS += -N
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Programming Options (avrdude) ----------------
|
|
||||||
|
|
||||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
|
||||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
|
||||||
#
|
|
||||||
# Type: avrdude -c ?
|
|
||||||
# to get a full listing.
|
|
||||||
#
|
|
||||||
AVRDUDE_PROGRAMMER = stk500
|
|
||||||
|
|
||||||
# com1 = serial port. Use lpt1 to connect to parallel port.
|
|
||||||
AVRDUDE_PORT = com3
|
|
||||||
|
|
||||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
|
||||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
|
||||||
|
|
||||||
|
|
||||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
|
||||||
# Note that this counter needs to be initialized first using -Yn,
|
|
||||||
# see avrdude manual.
|
|
||||||
#AVRDUDE_ERASE_COUNTER = -y
|
|
||||||
|
|
||||||
# Uncomment the following if you do /not/ wish a verification to be
|
|
||||||
# performed after programming the device.
|
|
||||||
#AVRDUDE_NO_VERIFY = -V
|
|
||||||
|
|
||||||
# Increase verbosity level. Please use this when submitting bug
|
|
||||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
|
||||||
# to submit bug reports.
|
|
||||||
#AVRDUDE_VERBOSE = -v -v
|
|
||||||
|
|
||||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
|
||||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
|
||||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
|
||||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---------------- Debugging Options ----------------
|
|
||||||
|
|
||||||
# For simulavr only - target MCU frequency.
|
|
||||||
DEBUG_MFREQ = $(F_CPU)
|
|
||||||
|
|
||||||
# Set the DEBUG_UI to either gdb or insight.
|
|
||||||
# DEBUG_UI = gdb
|
|
||||||
DEBUG_UI = insight
|
|
||||||
|
|
||||||
# Set the debugging back-end to either avarice, simulavr.
|
|
||||||
DEBUG_BACKEND = avarice
|
|
||||||
#DEBUG_BACKEND = simulavr
|
|
||||||
|
|
||||||
# GDB Init Filename.
|
|
||||||
GDBINIT_FILE = __avr_gdbinit
|
|
||||||
|
|
||||||
# When using avarice settings for the JTAG
|
|
||||||
JTAG_DEV = /dev/com1
|
|
||||||
|
|
||||||
# Debugging port used to communicate between GDB / avarice / simulavr.
|
|
||||||
DEBUG_PORT = 4242
|
|
||||||
|
|
||||||
# Debugging host used to communicate between GDB / avarice / simulavr, normally
|
|
||||||
# just set to localhost unless doing some sort of crazy debugging when
|
|
||||||
# avarice is running on a different computer.
|
|
||||||
DEBUG_HOST = localhost
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
# Define programs and commands.
|
|
||||||
SHELL = sh
|
|
||||||
CC = avr-gcc
|
|
||||||
OBJCOPY = avr-objcopy
|
|
||||||
OBJDUMP = avr-objdump
|
|
||||||
SIZE = avr-size
|
|
||||||
AR = avr-ar rcs
|
|
||||||
NM = avr-nm
|
|
||||||
AVRDUDE = avrdude
|
|
||||||
REMOVE = rm -f
|
|
||||||
REMOVEDIR = rm -rf
|
|
||||||
COPY = cp
|
|
||||||
WINSHELL = cmd
|
|
||||||
|
|
||||||
|
|
||||||
# Define Messages
|
|
||||||
# English
|
|
||||||
MSG_ERRORS_NONE = Errors: none
|
|
||||||
MSG_BEGIN = -------- begin --------
|
|
||||||
MSG_END = -------- end --------
|
|
||||||
MSG_SIZE_BEFORE = Size before:
|
|
||||||
MSG_SIZE_AFTER = Size after:
|
|
||||||
MSG_COFF = Converting to AVR COFF:
|
|
||||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
|
||||||
MSG_FLASH = Creating load file for Flash:
|
|
||||||
MSG_EEPROM = Creating load file for EEPROM:
|
|
||||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
|
||||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
|
||||||
MSG_LINKING = Linking:
|
|
||||||
MSG_COMPILING = Compiling C:
|
|
||||||
MSG_COMPILING_CPP = Compiling C++:
|
|
||||||
MSG_ASSEMBLING = Assembling:
|
|
||||||
MSG_CLEANING = Cleaning project:
|
|
||||||
MSG_CREATING_LIBRARY = Creating library:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Define all object files.
|
|
||||||
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
|
|
||||||
|
|
||||||
# Define all listing files.
|
|
||||||
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
|
|
||||||
|
|
||||||
|
|
||||||
# Compiler flags to generate dependency files.
|
|
||||||
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
|
|
||||||
|
|
||||||
|
|
||||||
# Combine all necessary flags and optional flags.
|
|
||||||
# Add target processor to flags.
|
|
||||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
|
||||||
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
|
|
||||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Default target.
|
|
||||||
all: begin gccversion sizebefore build sizeafter end
|
|
||||||
|
|
||||||
# Change the build target to build a HEX file or a library.
|
|
||||||
build: elf hex eep lss sym bin
|
|
||||||
#build: lib
|
|
||||||
|
|
||||||
|
|
||||||
elf: $(TARGET).elf
|
|
||||||
hex: $(TARGET).hex
|
|
||||||
bin: $(TARGET).bin
|
|
||||||
eep: $(TARGET).eep
|
|
||||||
lss: $(TARGET).lss
|
|
||||||
sym: $(TARGET).sym
|
|
||||||
LIBNAME=lib$(TARGET).a
|
|
||||||
lib: $(LIBNAME)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Eye candy.
|
|
||||||
# AVR Studio 3.x does not check make's exit code but relies on
|
|
||||||
# the following magic strings to be generated by the compile job.
|
|
||||||
begin:
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_BEGIN)
|
|
||||||
|
|
||||||
end:
|
|
||||||
@echo $(MSG_END)
|
|
||||||
@echo
|
|
||||||
|
|
||||||
|
|
||||||
# Display size of file.
|
|
||||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
|
||||||
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
|
|
||||||
|
|
||||||
sizebefore:
|
|
||||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
|
|
||||||
2>/dev/null; echo; fi
|
|
||||||
|
|
||||||
sizeafter:
|
|
||||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
|
|
||||||
2>/dev/null; echo; fi
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Display compiler version information.
|
|
||||||
gccversion :
|
|
||||||
@$(CC) --version
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Program the device.
|
|
||||||
program: $(TARGET).hex $(TARGET).eep
|
|
||||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
|
||||||
|
|
||||||
|
|
||||||
# Generate avr-gdb config/init file which does the following:
|
|
||||||
# define the reset signal, load the target file, connect to target, and set
|
|
||||||
# a breakpoint at main().
|
|
||||||
gdb-config:
|
|
||||||
@$(REMOVE) $(GDBINIT_FILE)
|
|
||||||
@echo define reset >> $(GDBINIT_FILE)
|
|
||||||
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
|
|
||||||
@echo end >> $(GDBINIT_FILE)
|
|
||||||
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
|
|
||||||
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
|
|
||||||
ifeq ($(DEBUG_BACKEND),simulavr)
|
|
||||||
@echo load >> $(GDBINIT_FILE)
|
|
||||||
endif
|
|
||||||
@echo break main >> $(GDBINIT_FILE)
|
|
||||||
|
|
||||||
debug: gdb-config $(TARGET).elf
|
|
||||||
ifeq ($(DEBUG_BACKEND), avarice)
|
|
||||||
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
|
|
||||||
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
|
|
||||||
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
|
|
||||||
@$(WINSHELL) /c pause
|
|
||||||
|
|
||||||
else
|
|
||||||
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
|
|
||||||
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
|
|
||||||
endif
|
|
||||||
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
|
||||||
COFFCONVERT = $(OBJCOPY) --debugging
|
|
||||||
COFFCONVERT += --change-section-address .data-0x800000
|
|
||||||
COFFCONVERT += --change-section-address .bss-0x800000
|
|
||||||
COFFCONVERT += --change-section-address .noinit-0x800000
|
|
||||||
COFFCONVERT += --change-section-address .eeprom-0x810000
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
coff: $(TARGET).elf
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_COFF) $(TARGET).cof
|
|
||||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
|
||||||
|
|
||||||
|
|
||||||
extcoff: $(TARGET).elf
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
|
||||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Create final output files (.hex, .eep) from ELF output file.
|
|
||||||
%.hex: %.elf
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_FLASH) $@
|
|
||||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
|
||||||
|
|
||||||
%.bin: %.elf
|
|
||||||
$(OBJCOPY) -O binary $< $@
|
|
||||||
|
|
||||||
%.eep: %.elf
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_EEPROM) $@
|
|
||||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
|
||||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
|
|
||||||
|
|
||||||
# Create extended listing file from ELF output file.
|
|
||||||
%.lss: %.elf
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_EXTENDED_LISTING) $@
|
|
||||||
$(OBJDUMP) -h -S $< > $@
|
|
||||||
|
|
||||||
# Create a symbol table from ELF output file.
|
|
||||||
%.sym: %.elf
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_SYMBOL_TABLE) $@
|
|
||||||
$(NM) -n $< > $@
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Create library from object files.
|
|
||||||
.SECONDARY : $(TARGET).a
|
|
||||||
.PRECIOUS : $(OBJ)
|
|
||||||
%.a: $(OBJ)
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_CREATING_LIBRARY) $@
|
|
||||||
$(AR) $@ $(OBJ)
|
|
||||||
|
|
||||||
|
|
||||||
# Link: create ELF output file from object files.
|
|
||||||
.SECONDARY : $(TARGET).elf
|
|
||||||
.PRECIOUS : $(OBJ)
|
|
||||||
%.elf: $(OBJ)
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_LINKING) $@
|
|
||||||
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
|
|
||||||
|
|
||||||
|
|
||||||
# Compile: create object files from C source files.
|
|
||||||
$(OBJDIR)/%.o : %.c
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_COMPILING) $<
|
|
||||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Compile: create object files from C++ source files.
|
|
||||||
$(OBJDIR)/%.o : %.cpp
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_COMPILING_CPP) $<
|
|
||||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Compile: create assembler files from C source files.
|
|
||||||
%.s : %.c
|
|
||||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Compile: create assembler files from C++ source files.
|
|
||||||
%.s : %.cpp
|
|
||||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Assemble: create object files from assembler source files.
|
|
||||||
$(OBJDIR)/%.o : %.S
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_ASSEMBLING) $<
|
|
||||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Create preprocessed source for use in sending a bug report.
|
|
||||||
%.i : %.c
|
|
||||||
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Target: clean project.
|
|
||||||
clean: begin clean_list end
|
|
||||||
|
|
||||||
clean_list :
|
|
||||||
@echo
|
|
||||||
@echo $(MSG_CLEANING)
|
|
||||||
$(REMOVE) $(TARGET).hex
|
|
||||||
$(REMOVE) $(TARGET).eep
|
|
||||||
$(REMOVE) $(TARGET).cof
|
|
||||||
$(REMOVE) $(TARGET).elf
|
|
||||||
$(REMOVE) $(TARGET).map
|
|
||||||
$(REMOVE) $(TARGET).sym
|
|
||||||
$(REMOVE) $(TARGET).lss
|
|
||||||
$(REMOVE) $(CPPSRC:%.cpp=%.o)
|
|
||||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
|
|
||||||
$(REMOVE) $(SRC:.c=.s)
|
|
||||||
$(REMOVE) $(SRC:.c=.d)
|
|
||||||
$(REMOVE) $(SRC:.c=.i)
|
|
||||||
$(REMOVEDIR) .dep
|
|
||||||
|
|
||||||
|
|
||||||
# Create object files directory
|
|
||||||
$(shell mkdir $(OBJDIR) 2>/dev/null)
|
|
||||||
|
|
||||||
|
|
||||||
# Include the dependency files.
|
|
||||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
|
||||||
|
|
||||||
|
|
||||||
# Listing of phony targets.
|
|
||||||
.PHONY : all begin finish end sizebefore sizeafter gccversion \
|
|
||||||
build elf hex eep lss sym coff extcoff \
|
|
||||||
clean clean_list program debug gdb-config
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -55,6 +55,9 @@ extern void TelemetryUpdate() ;
|
|||||||
extern uint16_t initDsm() ;
|
extern uint16_t initDsm() ;
|
||||||
extern uint16_t ReadDsm() ;
|
extern uint16_t ReadDsm() ;
|
||||||
|
|
||||||
|
extern void setup() ;
|
||||||
|
extern void loop() ;
|
||||||
|
|
||||||
#define yield()
|
#define yield()
|
||||||
|
|
||||||
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||||
@ -139,27 +142,29 @@ void init()
|
|||||||
PORTA.PIN7CTRL = 0x18 ;
|
PORTA.PIN7CTRL = 0x18 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "Multiprotocol.ino"
|
//#ifndef ARDUINO_AVR_XMEGA32D4
|
||||||
#include "SPI.ino"
|
//#include "Multiprotocol.ino"
|
||||||
#include "Common.ino"
|
//#include "SPI.ino"
|
||||||
#include "Arduino.ino"
|
//#include "Common.ino"
|
||||||
|
//#include "Arduino.ino"
|
||||||
|
|
||||||
#include "cyrf6936_SPI.ino"
|
//#include "cyrf6936_SPI.ino"
|
||||||
#include "DSM_cyrf6936.ino"
|
//#include "DSM_cyrf6936.ino"
|
||||||
#include "Devo_cyrf6936.ino"
|
//#include "Devo_cyrf6936.ino"
|
||||||
#include "J6Pro_cyrf6936.ino"
|
//#include "J6Pro_cyrf6936.ino"
|
||||||
#include "WK2x01_cyrf6936.ino"
|
//#include "WK2x01_cyrf6936.ino"
|
||||||
|
|
||||||
#include "Telemetry.ino"
|
//#include "Telemetry.ino"
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
//int main(void)
|
||||||
{
|
//{
|
||||||
init() ;
|
// init() ;
|
||||||
setup() ;
|
// setup() ;
|
||||||
for(;;)
|
// for(;;)
|
||||||
{
|
// {
|
||||||
loop() ;
|
// loop() ;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
@ -28,7 +28,7 @@
|
|||||||
#ifdef __arm__ // Let's automatically select the board if arm is selected
|
#ifdef __arm__ // Let's automatically select the board if arm is selected
|
||||||
#define STM32_BOARD
|
#define STM32_BOARD
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_AVR_XMEGA32D4
|
#if defined (ARDUINO_AVR_XMEGA32D4) || defined (ARDUINO_MULTI_ORANGERX)
|
||||||
#include "MultiOrange.h"
|
#include "MultiOrange.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -49,7 +49,6 @@
|
|||||||
#ifndef STM32_BOARD
|
#ifndef STM32_BOARD
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#else
|
#else
|
||||||
#include <arduino.h>
|
|
||||||
#include <libmaple/usart.h>
|
#include <libmaple/usart.h>
|
||||||
#include <libmaple/timer.h>
|
#include <libmaple/timer.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
73
docs/Compiling_OrangeTx.md
Normal file
73
docs/Compiling_OrangeTx.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Compiling and Programming (OrangeRX)
|
||||||
|
|
||||||
|
Multiprotocol firmware is compiled using the Arduino IDE. The guide below will walk you through all the steps to compile and upload your customized firmware.
|
||||||
|
|
||||||
|
**These instructions are for the OrangeRX version of the Multiprotocol module.** If you are compling for a different module please go to the dedicated page [Atmega328p](Compiling.md) or [STM32](Compiling_STM32.md) page.
|
||||||
|
|
||||||
|
## Index
|
||||||
|
1. [Tools Required](#tools-required)
|
||||||
|
1. [Preparation](#preparation)
|
||||||
|
1. [Install the Arduino IDE](#install-the-arduino-ide)
|
||||||
|
1. [Download the Multiprotocol source and open the project](#download-the-multiprotocol-source-and-open-the-project)
|
||||||
|
1. [Install the Multi 4-in-1 board](#install-the-multi-4-in-1-board)
|
||||||
|
1. [Configure the Arduino IDE](#configure-the-arduino-ide)
|
||||||
|
1. [Configure the firmware](#configure-the-firmware)
|
||||||
|
1. [Customize the firmware to match your hardware and your needs](#customize-the-firmware-to-match-your-hardware-and-your-needs)
|
||||||
|
1. [Verify the firmware](#verify-the-firmware)
|
||||||
|
1. [Compiling and uploading the firmware](#compiling-and-uploading-the-firmware)
|
||||||
|
1. [Upload the firmware](#upload-the-firmware)
|
||||||
|
1. [Flash from TX](#flash-from-tx)
|
||||||
|
1. [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## Tools required
|
||||||
|
Flashing the bootloader to the OrangeRX module requires either a PPI-capable programmer or an Arduino Pro Mini programmed with a sketch which can program the bootloader.
|
||||||
|
|
||||||
|
Flashing the bootloader is outside the scope of this documentation. Full instructions are available [here](http://openrcforums.com/forum/viewtopic.php?f=40&t=8753&sid=bbd74327cc518303e1c7f9e2ace04339#p114549).
|
||||||
|
|
||||||
|
## Preparation
|
||||||
|
### Install the Arduino IDE
|
||||||
|
1. Download and install the Arduino IDE. The currently supported Arduino version is 1.8.5, available for [Windows]( https://www.arduino.cc/download_handler.php?f=/arduino-1.8.5-windows.exe) and [Mac OSX](https://www.arduino.cc/download_handler.php?f=/arduino-1.8.5-macosx.zip)
|
||||||
|
1. It is recommended to upgrade Java to the [latest version](https://www.java.com/en/download/)
|
||||||
|
|
||||||
|
### Download the Multiprotocol source and open the project
|
||||||
|
1. Either
|
||||||
|
1. Download the zip file with the Multiprotocol module source code from [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/archive/master.zip) and unzip and copy the source code folder **Multiprotocol** to a location of your choosing, or
|
||||||
|
1. Clone the project using Git or Github Desktop, then
|
||||||
|
1. Double-click the **Multiprotocol.ino** file in the **Multiprotocol** folder to open the project in the Arduino IDE
|
||||||
|
|
||||||
|
### Install the Multi 4-in-1 board
|
||||||
|
1. Follow [these instructions](/BootLoaders/README.md) to install the **Multi 4-in-1 OrangeRX Board** in the Arduino IDE
|
||||||
|
|
||||||
|
### Configure the Arduino IDE
|
||||||
|
1. Under **Tools -> Board** select **'Multi 4-in-1 (OrangeRX)'**
|
||||||
|
|
||||||
|
## Configure the firmware
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
The OrangeRX module has more than enough flash space for all the compatible protocols so, unlike the Atmega328p-based module, it is not necessary to disable unused protocols.
|
||||||
|
|
||||||
|
You can still disable protocols if you wish, and you may also enable or disable other optional Multiprotocol features.
|
||||||
|
|
||||||
|
### Verify the firmware
|
||||||
|
To check that the program will compile correctly and fit in the Atmega click **Sketch -> Verify/Compile**, or press **Ctrl+R**.
|
||||||
|
|
||||||
|
If there are no errors and you see output like this:
|
||||||
|
```
|
||||||
|
Sketch uses 31874 bytes (97%) of program storage space. Maximum is 32768 bytes.
|
||||||
|
Global variables use 1083 bytes (52%) of dynamic memory, leaving 965 bytes for local variables. Maximum is 2048 bytes.
|
||||||
|
```
|
||||||
|
You can proceed to the next step.
|
||||||
|
|
||||||
|
## Compiling and uploading the firmware
|
||||||
|
|
||||||
|
### Upload the firmware
|
||||||
|
You are now ready to upload the firmware to the multiprotocol module. Uploading is done via the 'Flash-from-TX' method.
|
||||||
|
|
||||||
|
**Note:** 'Flash from TX' is only available with radios running ersky9x r221e2 or newer.
|
||||||
|
|
||||||
|
#### Flash from TX
|
||||||
|
1. In the Arduino IDE click **Sketch -> Export compiled Binary**, or press **Ctrl+Alt+S**
|
||||||
|
1. Locate the file named **multi-orx-[version].hex** in the **Multiprotocol** folder
|
||||||
|
1. Follow the instructions [here](/docs/Flash_from_Tx.md) to upload the firmware using your radio
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user