Meanwhile, here's the patch, although it's probably not going to work after being pasted into a forum post.
diff --git a/firmware/tinyg/canonical_machine.c b/firmware/tinyg/canonical_machine.c
index 0a5c16e..68bb1c6 100755
--- a/firmware/tinyg/canonical_machine.c
+++ b/firmware/tinyg/canonical_machine.c
@@ -1835,6 +1835,8 @@ const char fmt_dist[] PROGMEM = "Distance mode: %s\n";
const char fmt_frmo[] PROGMEM = "Feed rate mode: %s\n";
const char fmt_tool[] PROGMEM = "Tool number %d\n";
+const char fmt_adc[] PROGMEM = "ADC: %d\n";
+
const char fmt_pos[] PROGMEM = "%c position:%15.3f%s\n";
const char fmt_mpo[] PROGMEM = "%c machine posn:%11.3f%s\n";
const char fmt_ofs[] PROGMEM = "%c work offset:%12.3f%s\n";
@@ -1870,6 +1872,8 @@ void cm_print_gco(nvObj_t *nv) { text_print_int(nv, fmt_gco);}
void cm_print_gpa(nvObj_t *nv) { text_print_int(nv, fmt_gpa);}
void cm_print_gdi(nvObj_t *nv) { text_print_int(nv, fmt_gdi);}
+void cm_print_adc(nvObj_t *nv) { text_print_int(nv, fmt_adc);}
+
/* system state print functions */
const char fmt_ja[] PROGMEM = "[ja] junction acceleration%8.0f%s\n";
diff --git a/firmware/tinyg/canonical_machine.h b/firmware/tinyg/canonical_machine.h
index 8f348b5..5b9dbff 100755
--- a/firmware/tinyg/canonical_machine.h
+++ b/firmware/tinyg/canonical_machine.h
@@ -767,6 +767,7 @@ stat_t cm_set_xjh(nvObj_t *nv); // set jerk homing with 1,000,000 correction
#define cm_print_cycs tx_print_stub
#define cm_print_mots tx_print_stub
#define cm_print_hold tx_print_stub
+ #define cm_print_adc tx_print_stub
#define cm_print_home tx_print_stub
#define cm_print_unit tx_print_stub
#define cm_print_coor tx_print_stub
diff --git a/firmware/tinyg/config_app.c b/firmware/tinyg/config_app.c
index dae467c..d2ce389 100755
--- a/firmware/tinyg/config_app.c
+++ b/firmware/tinyg/config_app.c
@@ -100,6 +100,9 @@ static stat_t get_rx(nvObj_t *nv); // get bytes in RX buffer
* uint16_t in the config.h file.
*/
+// RN this function is located in main.c
+stat_t get_adc(nvObj_t *nv);
+
const cfgItem_t cfgArray[] PROGMEM = {
// group token flags p, print_func, get_func, set_func, target for get/set, default value
{ "sys", "fb", _fipn,2, hw_print_fb, get_flt, set_nul, (float *)&cs.fw_build, TINYG_FIRMWARE_BUILD }, // MUST BE FIRST!
@@ -528,7 +531,10 @@ const cfgItem_t cfgArray[] PROGMEM = {
{ "udd","udd1", _fip, 0, tx_print_int, get_data, set_data,(float *)&cfg.user_data_d[1], USER_DATA_D1 },
{ "udd","udd2", _fip, 0, tx_print_int, get_data, set_data,(float *)&cfg.user_data_d[2], USER_DATA_D2 },
{ "udd","udd3", _fip, 0, tx_print_int, get_data, set_data,(float *)&cfg.user_data_d[3], USER_DATA_D3 },
+ // ADC
+ { "adc","adc0", _f0, 0, tx_print_int, get_adc, set_nul,(float *)&cs.null, 0 },
+
// Diagnostic parameters
#ifdef __DIAGNOSTIC_PARAMETERS
{ "_te","_tex",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_X], 0 }, // X target endpoint
@@ -899,6 +905,7 @@ static stat_t set_ex(nvObj_t *nv) // enable XON/XOFF or RTS/CTS flow control
return(_set_comm_helper(nv, XIO_XOFF, XIO_NOXOFF));
}
+
static stat_t get_rx(nvObj_t *nv)
{
#ifdef __AVR
diff --git a/firmware/tinyg/default/Makefile b/firmware/tinyg/default/Makefile
index dea771d..0732801 100755
--- a/firmware/tinyg/default/Makefile
+++ b/firmware/tinyg/default/Makefile
@@ -40,7 +40,7 @@ HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
LIBS = -lm
## Objects that must be built in order to link
-OBJECTS = util.o canonical_machine.o config.o controller.o cycle_homing.o gcode_parser.o gpio.o help.o json_parser.o kinematics.o main.o planner.o report.o spindle.o stepper.o hardware.o test.o xmega_rtc.o xmega_eeprom.o xmega_init.o xmega_interrupts.o xio_usb.o xio_pgm.o xio_rs485.o xio_usart.o pwm.o plan_line.o plan_arc.o xio_spi.o xio_file.o network.o config_app.o text_parser.o switch.o cycle_probing.o xio.o cycle_jogging.o plan_exec.o encoder.o plan_zoid.o persistence.o
+OBJECTS = util.o canonical_machine.o config.o controller.o cycle_homing.o gcode_parser.o gpio.o help.o json_parser.o kinematics.o main.o planner.o report.o spindle.o stepper.o hardware.o test.o xmega_rtc.o adc_driver.o xmega_eeprom.o xmega_init.o xmega_interrupts.o xio_usb.o xio_pgm.o xio_rs485.o xio_usart.o pwm.o plan_line.o plan_arc.o xio_spi.o xio_file.o network.o config_app.o text_parser.o switch.o cycle_probing.o xio.o cycle_jogging.o plan_exec.o encoder.o plan_zoid.o persistence.o
## Objects explicitly added by the user
LINKONLYOBJECTS =
@@ -103,6 +103,9 @@ test.o: ../test.c
xmega_rtc.o: ../xmega/xmega_rtc.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<
+adc_driver.o: ../xmega/adc_driver.c
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
xmega_eeprom.o: ../xmega/xmega_eeprom.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<
diff --git a/firmware/tinyg/main.c b/firmware/tinyg/main.c
index 74edb7b..3b03dc9 100755
--- a/firmware/tinyg/main.c
+++ b/firmware/tinyg/main.c
@@ -35,6 +35,7 @@
#include "test.h"
#include "pwm.h"
#include "xio.h"
+#include "xmega/adc_driver.h"
#ifdef __AVR
#include <avr/interrupt.h>
@@ -103,6 +104,48 @@ void _system_init(void)
delay(1000);
#endif
}
+
+
+/* Thre are two ADC pins available
+** J15 pin 2 = pB0
+** J13 pin 2 = PB3 <- this is the best option as it's only confiured at /SS2 For an external SPI Interface
+*/
+void adc_init(void) {
+ /* Move stored calibration values to ADC A. */
+ ADC_CalibrationValues_Load(&ADCB);
+
+ /* Set up ADC A to have signed conversion mode and 12 bit resolution. */
+ ADC_ConvMode_and_Resolution_Config(&ADCB, ADC_ConvMode_Unsigned, ADC_RESOLUTION_12BIT_gc);
+
+ /* Set sample rate. */
+ ADC_Prescaler_Config(&ADCB, ADC_PRESCALER_DIV32_gc);
+
+ /* Set reference voltage on ADC A to be VCC/1.6 V.*/
+ ADC_Reference_Config(&ADCB, ADC_REFSEL_VCC_gc);
+
+ /* Setup channel 0*/
+ ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH0, ADC_CH_INPUTMODE_SINGLEENDED_gc, ADC_DRIVER_CH_GAIN_NONE);
+
+ /* Set input to the channels in ADC b */
+ ADC_Ch_InputMux_Config(&ADCB.CH0, ADC_CH_MUXPOS_PIN3_gc, 0);
+
+ /* Enable ADC A .*/
+ ADC_Enable(&ADCB);
+}
+
+
+stat_t get_adc(nvObj_t *nv){
+ uint16_t result;
+ // get value
+ ADC_Ch_Conversion_Start(&ADCB.CH0);
+ while(!ADC_Ch_Conversion_Complete(&ADCB.CH0));
+ result = ADC_ResultCh_GetWord_Unsigned(&ADCB.CH0, 0);
+ //return it
+ nv->value = (float)result;
+ nv->valuetype = TYPE_INTEGER;
+ return (STAT_OK);
+}
+
/*
* _application_init()
@@ -127,6 +170,9 @@ static void _application_init(void)
switch_init(); // switches
// gpio_init(); // parallel IO
pwm_init(); // pulse width modulation drivers - must follow gpio_init()
+
+ //RN adc
+ adc_init();
controller_init(STD_IN, STD_OUT, STD_ERR);// must be first app init; reqs xio_init()
config_init(); // config records from eeprom - must be next app init
diff --git a/firmware/tinyg/text_parser.c b/firmware/tinyg/text_parser.c
index aba8c75..c9d162f 100755
--- a/firmware/tinyg/text_parser.c
+++ b/firmware/tinyg/text_parser.c
@@ -265,6 +265,7 @@ void tx_print_flt(nvObj_t *nv) { text_print_flt(nv, fmt_flt);}
void text_print_nul(nvObj_t *nv, const char *format) { fprintf_P(stderr, format);} // just print the format string
void text_print_str(nvObj_t *nv, const char *format) { fprintf_P(stderr, format, *nv->stringp);}
void text_print_ui8(nvObj_t *nv, const char *format) { fprintf_P(stderr, format, (uint8_t)nv->value);}
+void text_print_ui16(nvObj_t *nv, const char *format) { fprintf_P(stderr, format, (uint16_t)nv->value);}
void text_print_int(nvObj_t *nv, const char *format) { fprintf_P(stderr, format, (uint32_t)nv->value);}
void text_print_flt(nvObj_t *nv, const char *format) { fprintf_P(stderr, format, nv->value);}
diff --git a/firmware/tinyg/tinyg.h b/firmware/tinyg/tinyg.h
index d5d37d7..efb1864 100755
--- a/firmware/tinyg/tinyg.h
+++ b/firmware/tinyg/tinyg.h
@@ -62,7 +62,8 @@
#define __TEXT_MODE // enables text mode (~10Kb)
#define __HELP_SCREENS // enables help screens (~3.5Kb)
-#define __CANNED_TESTS // enables $tests (~12Kb)
+//#define __CANNED_TESTS // enables $tests (~12Kb)
+#undef __CANNED_TESTS // enables $tests (~12Kb)
#define __TEST_99 // enables diagnostic test 99 (independent of other tests)
/****** DEVELOPMENT SETTINGS ******/
diff --git a/firmware/tinyg/xio.c b/firmware/tinyg/xio.c
index 30c73b2..d3d0b55 100755
--- a/firmware/tinyg/xio.c
+++ b/firmware/tinyg/xio.c
@@ -108,7 +108,8 @@ void xio_init()
xio_open(XIO_DEV_USB, 0, USB_FLAGS);
xio_open(XIO_DEV_RS485,0, RS485_FLAGS);
xio_open(XIO_DEV_SPI1, 0, SPI_FLAGS);
- xio_open(XIO_DEV_SPI2, 0, SPI_FLAGS);
+ // RN - for adc
+// xio_open(XIO_DEV_SPI2, 0, SPI_FLAGS);
xio_init_assertions();
}
@@ -132,8 +133,9 @@ uint8_t xio_test_assertions()
if (ds[XIO_DEV_RS485].magic_end != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
if (ds[XIO_DEV_SPI1].magic_start != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
if (ds[XIO_DEV_SPI1].magic_end != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
- if (ds[XIO_DEV_SPI2].magic_start != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
- if (ds[XIO_DEV_SPI2].magic_end != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
+ // RN - dissabled spi2 for adc
+// if (ds[XIO_DEV_SPI2].magic_start != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
+// if (ds[XIO_DEV_SPI2].magic_end != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
// if (ds[XIO_DEV_PGM].magic_start != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
// if (ds[XIO_DEV_PGM].magic_end != MAGICNUM) return (STAT_XIO_ASSERTION_FAILURE);
if (stderr != xio.stderr_shadow) return (STAT_XIO_ASSERTION_FAILURE);
diff --git a/firmware/tinyg/xio.h b/firmware/tinyg/xio.h
index f7a409c..1688d07 100755
--- a/firmware/tinyg/xio.h
+++ b/firmware/tinyg/xio.h
@@ -73,7 +73,7 @@ enum xioDevNum_t { // TYPE: DEVICE:
XIO_DEV_USB, // USART USB device
XIO_DEV_RS485, // USART RS485 device
XIO_DEV_SPI1, // SPI SPI channel #1
- XIO_DEV_SPI2, // SPI SPI channel #2
+ //XIO_DEV_SPI2, // SPI SPI channel #2
// XIO_DEV_SPI3, // SPI SPI channel #3
// XIO_DEV_SPI4, // SPI SPI channel #4
XIO_DEV_PGM, // FILE Program memory file (read only)
@@ -85,7 +85,9 @@ enum xioDevNum_t { // TYPE: DEVICE:
#define XIO_DEV_USART_COUNT 2 // # of USART devices
#define XIO_DEV_USART_OFFSET 0 // offset for computing indices
-#define XIO_DEV_SPI_COUNT 2 // # of SPI devices
+// RN - changed spi count to 1 from 2 so that \SS2 will not be used and can be used
+// for the adc input instead
+#define XIO_DEV_SPI_COUNT 1 // # of SPI devices
#define XIO_DEV_SPI_OFFSET XIO_DEV_USART_COUNT // offset for computing indicies
#define XIO_DEV_FILE_COUNT 1 // # of FILE devices
diff --git a/firmware/tinyg/xmega/adc_driver.c b/firmware/tinyg/xmega/adc_driver.c
new file mode 100755
index 0000000..4e264bd
--- /dev/null
+++ b/firmware/tinyg/xmega/adc_driver.c
@@ -0,0 +1,380 @@
+/*
+ * adc_driver.c
+ *
+ * Created: 6/14/2015 11:42:15 AM
+ * Author: reza
+ */
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief
+ * XMEGA ADC driver source file.
+ *
+ * This file contains the function implementations the XMEGA ADC driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA ADC module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * Several functions use the following construct:
+ * "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..."
+ * Although the use of the ternary operator ( if ? then : else ) is discouraged,
+ * in some occasions the operator makes it possible to write pretty clean and
+ * neat code. In this driver, the construct is used to set or not set a
+ * configuration bit based on a boolean input parameter, such as
+ * the "some_parameter" in the example above.
+ *
+ * \par Application note:
+ * AVR1300: Using the XMEGA ADC
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation:
http://www.atmel.com \n
+ * Support email:
avr@atmel.com
+ *
+ * $Revision: 2793 $
+ * $Date: 2009-09-21 11:12:00 +0200 (ma, 21 sep 2009) $ \n
+ *
+ * Copyright (c) 2008, 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "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 EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#include "adc_driver.h"
+
+
+/*! \brief This function get the calibration data from the production calibration.
+ *
+ * The calibration data is loaded from flash and stored in the calibration
+ * register. The calibration data reduces the non-linearity error in the adc.
+ *
+ * \param adc Pointer to ADC module register section.
+ */
+void ADC_CalibrationValues_Load(ADC_t * adc)
+{
+ if(&ADCA == adc){
+ /* Get ADCACAL0 from production signature . */
+ adc->CALL = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL0_offset );
+ adc->CALH = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL1_offset );
+ }else {
+ /* Get ADCBCAL0 from production signature */
+ adc->CALL = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCBCAL0_offset );
+ adc->CALH = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCBCAL1_offset );
+ }
+}
+
+
+/*! \brief This function clears the interrupt flag and returns the unsigned coversion result.
+ *
+ * This function should be used together with the ADC_Ch_Conversion_Complete.
+ * When the conversion result is ready this funciton reads out the result.
+ *
+ * \param adc_ch Pointer to ADC channel register section.
+ * \param offset Unsigned offset value to subtract.
+ * \return The unsigned Conversion result with the offset substracted.
+ */
+uint16_t ADC_ResultCh_GetWord_Unsigned(ADC_CH_t * adc_ch, uint8_t offset)
+{
+ uint16_t answer;
+
+ /* Clear interrupt flag.*/
+ adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
+
+ /* Return result register contents*/
+ answer = adc_ch->RES - offset;
+
+ return answer;
+}
+
+
+/*! \brief This function clears the interrupt flag and returns the signed coversion result.
+ *
+ * This function should be used together with the ADC_Ch_Conversion_Complete.
+ * When the conversion result is ready this funciton reads out the result.
+ *
+ * \param adc_ch Pointer to ADC channel register section.
+ * \param signedOffset Offset value to subtract.
+ * \return The signed Conversion result with the offset substracted.
+ */
+int16_t ADC_ResultCh_GetWord_Signed(ADC_CH_t * adc_ch, int8_t signedOffset)
+{
+ int16_t answer;
+
+ /* Clear interrupt flag.*/
+ adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
+
+ /* Return result register contents*/
+ answer = adc_ch->RES - signedOffset;
+
+ return answer;
+}
+
+/*! \brief This function clears the interrupt flag and returns the coversion result without compensating for offset.
+ *
+ * This function should be used together with the ADC_Ch_Conversion_Complete.
+ * When the conversion result is ready this funciton reads out the result.
+ *
+ * \param adc_ch Pointer to ADC channel register section.
+ * \return Signed conversion result.
+ */
+uint16_t ADC_ResultCh_GetWord(ADC_CH_t * adc_ch)
+{
+ /* Clear interrupt flag.*/
+ adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
+
+ /* Return result register contents*/
+ return adc_ch->RES;;
+}
+
+
+/*! \brief This function clears the interrupt flag and returns the low byte of the coversion result.
+ *
+ * This funtion should be used together with the ADC_Ch_Conversion_Complete.
+ * When the conversion result is ready this funciton reads out the result.
+ *
+ * \note If this function is used with 12-bit right adjusted results, it
+ * returns the 8 LSB only. Offset is not compensated.
+ *
+ * \param adc_ch Pointer to ADC channel register section.
+ *
+ * \return Low byte of conversion result.
+ */
+uint8_t ADC_ResultCh_GetLowByte(ADC_CH_t * adc_ch)
+{
+ /* Clear interrupt flag.*/
+ adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
+ /* Return result register contents*/
+ return adc_ch->RESL;
+}
+
+/*! \brief This function clears the interrupt flag and returns the high byte of the coversion result.
+ *
+ * This funtion should be used together with the ADC_ResultCh_ConversionComplete.
+ * When the conversion result is ready this function reads out the result.
+ *
+ * \note If this function is used with 12-bit right adjusted results, it
+ * returns the 8 LSB only. Offset is not compensated.
+ *
+ * \param adc_ch Pointer to ADC channel register section.
+ *
+ * \return High byte of conversion result.
+ */
+uint8_t ADC_ResultCh_GetHighByte(ADC_CH_t * adc_ch)
+{
+ /* Clear interrupt flag.*/
+ adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
+
+ /* Return low byte result register contents.*/
+ return adc_ch->RESH;
+}
+
+/*! \brief This function waits until the adc common mode is settled.
+ *
+ * After the ADC clock has been turned on, the common mode voltage in the ADC
+ * need some time to settle. The time it takes equals one dummy conversion.
+ * Instead of doing a dummy conversion this function waits until the common
+ * mode is settled.
+ *
+ * \note The function sets the prescaler to the minimum value to minimize the
+ * time it takes the common mode to settle. If the clock speed is higher
+ * than 8 MHz use the ADC_wait_32MHz function.
+ *
+ * \param adc Pointer to ADC module register section.
+ */
+void ADC_Wait_8MHz(ADC_t * adc)
+{
+ /* Store old prescaler value. */
+ uint8_t prescaler_val = adc->PRESCALER;
+
+ /* Set prescaler value to minimum value. */
+ adc->PRESCALER = ADC_PRESCALER_DIV4_gc;
+
+ /* Wait 4*COMMON_MODE_CYCLES for common mode to settle. */
+ delay_us(4*COMMON_MODE_CYCLES);
+
+ /* Set prescaler to old value*/
+ adc->PRESCALER = prescaler_val;
+}
+
+
+/*! \brief This function waits until the adc common mode is settled.
+ *
+ * After the ADC clock has been turned on, the common mode voltage in the ADC
+ * need some time to settle. The time it takes equals one dummy conversion.
+ * Instead of doing a dummy conversion this function waits until the common
+ * mode is settled.
+ *
+ * \note The function sets the prescaler to the minimum value possible when the
+ * clock speed is larger than 8 MHz to minimize the time it takes the
+ * common mode to settle.
+ *
+ * \note The ADC clock is turned off every time the ADC i disabled or the
+ * device goes into sleep (not Idle sleep mode).
+ *
+ * \param adc Pointer to ADC module register section.
+ */
+void ADC_Wait_32MHz(ADC_t * adc)
+{
+ /* Store old prescaler value. */
+ uint8_t prescaler_val = adc->PRESCALER;
+
+ /* Set prescaler value to minimum value. */
+ adc->PRESCALER = ADC_PRESCALER_DIV8_gc;
+
+ /* wait 8*COMMON_MODE_CYCLES for common mode to settle*/
+ delay_us(8*COMMON_MODE_CYCLES);
+
+ /* Set prescaler to old value*/
+ adc->PRESCALER = prescaler_val;
+}
+
+/*! \brief This function gets the offset of the ADC when it is configured in unsigned mode
+ *
+ * This function does one or several measurements to determine the offset of
+ * the ADC.
+ *
+ * \note The ADC must be configured and enabled before this function is run.
+ *
+ * \note This function only return the low byte of the 12-bit convertion,
+ * because the offset should never be more than +-8 LSB off.
+ *
+ * \param adc Pointer to the ADC to calculate offset from.
+ * \param ch Pointer to the ADC channel to measure on.
+ * \param oversampling false for one measurement. true for averaging several measurements.
+ *
+ * \return Offset on the selected ADC
+ */
+uint8_t ADC_Offset_Get_Unsigned(ADC_t * adc, ADC_CH_t *ch, bool oversampling)
+{
+ if (oversampling)
+ {
+ uint16_t offset=0;
+ for (int i=0; i<4; i++)
+ {
+ /* Do one conversion to find offset. */
+ ADC_Ch_Conversion_Start(ch);
+
+ do{
+ }while(!ADC_Ch_Conversion_Complete(ch));
+ offset += ADC_ResultCh_GetWord_Unsigned(ch, 0x00);
+ }
+ return ((uint8_t)(offset>>2));
+ }
+ else
+ {
+ uint8_t offset=0;
+
+ /* Do one conversion to find offset. */
+ ADC_Ch_Conversion_Start(ch);
+
+ do{
+ }while(!ADC_Ch_Conversion_Complete(ch));
+ offset = (uint8_t)ADC_ResultCh_GetWord(ch);
+
+ return offset;
+ }
+}
+
+/*! \brief This function gets the offset of the ADC when it is configured in signed mode
+ *
+ * This function does one or several measurements to determine the offset of
+ * the ADC.
+ *
+ * \note The ADC must be configured and enabled before this function is run.
+ *
+ * \note This function only return the low byte of the 12-bit convertion,
+ * because the offset should never be more than +-8 LSB off.
+ *
+ * \param adc Pointer to the ADC to calculate offset from.
+ * \param ch Pointer to the ADC channel to measure on.
+ * \param oversampling false for one measurement. true for averaging several measurements.
+ *
+ * \return Offset on the selected ADC
+ */
+int8_t ADC_Offset_Get_Signed(ADC_t * adc, ADC_CH_t *ch, bool oversampling)
+{
+ if (oversampling)
+ {
+ int16_t offset=0;
+ for (int i=0; i<4; i++)
+ {
+ /* Do one conversion to find offset. */
+ ADC_Ch_Conversion_Start(ch);
+
+ do{
+ }while(!ADC_Ch_Conversion_Complete(ch));
+ offset += ADC_ResultCh_GetWord_Signed(ch, 0x00);
+ }
+ return ((int8_t)(offset/4));
+ }
+ else
+ {
+ int8_t offset=0;
+
+ /* Do one conversion to find offset. */
+ ADC_Ch_Conversion_Start(ch);
+
+ do{
+ }while(!ADC_Ch_Conversion_Complete(ch));
+ offset = (uint8_t)ADC_ResultCh_GetWord_Signed(ch, 0x00);
+
+ return offset;
+ }
+}
+
+
+#ifdef __GNUC__
+
+/*! \brief Function for GCC to read out calibration byte.
+ *
+ * \note For IAR support, include the adc_driver_asm.S90 file in your project.
+ *
+ * \param index The index to the calibration byte.
+ *
+ * \return Calibration byte.
+ */
+uint8_t SP_ReadCalibrationByte( uint8_t index )
+{
+ uint8_t result;
+
+ /* Load the NVM Command register to read the calibration row. */
+ NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
+ result = pgm_read_byte(index);
+
+ /* Clean up NVM Command register. */
+ NVM_CMD = NVM_CMD_NO_OPERATION_gc;
+
+ return result;
+}
+
+#endif
\ No newline at end of file
diff --git a/firmware/tinyg/xmega/adc_driver.h b/firmware/tinyg/xmega/adc_driver.h
new file mode 100755
index 0000000..d7d1f55
--- /dev/null
+++ b/firmware/tinyg/xmega/adc_driver.h
@@ -0,0 +1,382 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief XMEGA ADC driver header file.
+ *
+ * This file contains the function prototypes and enumerator definitions
+ * for various configuration parameters for the XMEGA ADC driver that is
+ * implemented in C.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA ADC module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * \par Application note:
+ * AVR1300: Using the XMEGA ADC
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation:
http://www.atmel.com \n
+ * Support email:
avr@atmel.com
+ *
+ * $Revision: 2644 $
+ * $Date: 2009-08-04 12:37:51 +0200 (ti, 04 aug 2009) $ \n
+ *
+ * Copyright (c) 2008, 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "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 EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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 ADC_DRIVER_H
+#define ADC_DRIVER_H
+
+#include "avr_compiler.h"
+
+
+#define COMMON_MODE_CYCLES 16
+
+
+/* Macros */
+
+/*! \brief This macro enables the selected adc.
+ *
+ * Before the ADC is enabled the first time the function
+ * ADC_CalibrationValues_Set should be used to reduce the gain error in the
+ * ADC.
+ *
+ * \note After the ADC is enabled the commen mode voltage in the ADC is ready
+ * after 12 ADC clock cycels. Do one dummy conversion or wait the required
+ * number of clock cycles to reasure correct conversion.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_Enable(_adc) ((_adc)->CTRLA |= ADC_ENABLE_bm)
+
+/*! \brief This macro disables the selected adc.
+ *
+ * \param _adc Pointer to ADC module register section
+ */
+#define ADC_Disable(_adc) ((_adc)->CTRLA = (_adc)->CTRLA & (~ADC_ENABLE_bm))
+
+/*! \brief This macro flushes the pipline in the selected adc.
+ *
+ * \param _adc Pointer to ADC module register section
+ */
+#define ADC_Pipeline_Flush(_adc) ((_adc)->CTRLA |= ADC_FLUSH_bm)
+
+
+/*! \brief This macro set the conversion mode and resolution in the selected adc.
+ *
+ * This macro configures the conversion mode to signed or unsigned and set
+ * the resolution in and the way the results are put in the result
+ * registers.
+ *
+ * \param _adc Pointer to ADC module register section
+ * \param _signedMode Selects conversion mode: signed (true)
+ * or unsigned (false). USE bool type.
+ * \param _resolution Resolution and presentation selection.
+ * Use ADC_RESOLUTION_t type.
+ */
+
+#define ADC_ConvMode_and_Resolution_Config(_adc, _signedMode, _resolution) \
+ ((_adc)->CTRLB = ((_adc)->CTRLB & (~(ADC_RESOLUTION_gm|ADC_CONMODE_bm)))| \
+ (_resolution| ( _signedMode? ADC_CONMODE_bm : 0)))
+
+/*! \brief Helper macro for increased readability with ADC_ConvMode_and_Resolution_Config
+ *
+ * \sa ADC_ConvMode_and_Resolution_Config
+ */
+#define ADC_ConvMode_Signed true
+
+/*! \brief Helper macro for increased readability with ADC_ConvMode_and_Resolution_Config
+ *
+ * \sa ADC_ConvMode_and_Resolution_Config
+ */
+#define ADC_ConvMode_Unsigned false
+
+
+/*! \brief This macro set the prescaler factor in the selected adc.
+ *
+ * This macro configures the division factor between the XMEGA
+ * IO-clock and the ADC clock. Given a certain IO-clock, the prescaler
+ * must be configured so the the ADC clock is within recommended limits.
+ * A faster IO-clock required higher division factors.
+ *
+ * \note The maximum ADC sample rate is always one fourth of the IO clock.
+ *
+ * \param _adc Pointer to ADC module register section.
+ * \param _div ADC prescaler division factor setting. Use ADC_PRESCALER_t type
+ */
+#define ADC_Prescaler_Config(_adc, _div) \
+ ((_adc)->PRESCALER = ((_adc)->PRESCALER & (~ADC_PRESCALER_gm)) | _div)
+
+
+/*! \brief This macro set the conversion reference in the selected adc.
+ *
+ * \param _adc Pointer to ADC module register section.
+ * \param _convRef Selects reference voltage for all conversions.
+ * Use ADC_REFSEL_t type.
+ */
+#define ADC_Reference_Config(_adc, _convRef) \
+ ((_adc)->REFCTRL = ((_adc)->REFCTRL & ~(ADC_REFSEL_gm)) | _convRef)
+
+
+/*! \brief This macro sets the sweep channel settings.
+ *
+ * \param _adc Pointer to ADC module register section.
+ * \param _sweepChannels Sweep channel selection. Use ADC_SWEEP_t type
+ */
+#define ADC_SweepChannels_Config(_adc, _sweepChannels) \
+ ((_adc)->EVCTRL = ((_adc)->EVCTRL & (~ADC_SWEEP_gm)) | _sweepChannels)
+
+
+/*! \brief This macro configures the event channels used and the event mode.
+ *
+ * This macro configures the way events are used to trigger conversions for
+ * the virtual channels. Use the eventChannels parameter to select which event
+ * channel to associate with virtual channel 0 or to trigger a conversion sweep,
+ * depending on the selected eventMode parameter.
+ *
+ * \param _adc Pointer to ADC module register section.
+ * \param _eventChannels The first event channel to be used for triggering.
+ * Use ADC_EVSEL_t type.
+ * \param _eventMode Select event trigger mode.
+ * Use ADC_EVACT_t type.
+ */
+#define ADC_Events_Config(_adc, _eventChannels, _eventMode) \ \
+ (_adc)->EVCTRL = ((_adc)->EVCTRL & (~(ADC_EVSEL_gm | ADC_EVACT_gm))) | \
+ ((uint8_t) _eventChannels | _eventMode)
+
+
+/*! \brief This macro configures the interrupt mode and level for one channel.
+ *
+ * The interrupt mode affects the interrupt flag for the virtual channel,
+ * and thus also affects code that polls this flag instead of using interrupts.
+ *
+ * \note When using the result comparator function, the compare value must be
+ * set using the ADC_SetCompareValue function.
+ *
+ * \param _adc_ch Pointer to ADC channel register section.
+ * \param _interruptMode Interrupt mode, flag on complete or above/below
+ * compare value. Use ADC_CH_INTMODE_t type.
+ * \param _interruptLevel Disable or set low/med/high priority for this
+ * virtual channel. Use ADC_CH_INTLVL_t type.
+ */
+#define ADC_Ch_Interrupts_Config(_adc_ch, _interruptMode, _interruptLevel) \
+ (_adc_ch)->INTCTRL = (((_adc_ch)->INTCTRL & \
+ (~(ADC_CH_INTMODE_gm | ADC_CH_INTLVL_gm))) | \
+ ((uint8_t) _interruptMode | _interruptLevel))
+
+
+/*! \brief This macro configures the input mode and gain to a specific virtual channel.
+ *
+ * \param _adc_ch Pointer to ADC channel register section.
+ * \param _inputMode Input mode for this channel, differential,
+ * single-ended, gain etc. Use ADC_CH_INPUTMODE_t type.
+ * \param _gain The preamplifiers gain value.
+ * Use ADC_CH_GAINFAC_t type.
+ *
+ */
+#define ADC_Ch_InputMode_and_Gain_Config(_adc_ch, _inputMode, _gain) \
+ (_adc_ch)->CTRL = ((_adc_ch)->CTRL & \
+ (~(ADC_CH_INPUTMODE_gm|ADC_CH_GAINFAC_gm))) | \
+ ((uint8_t) _inputMode|_gain)
+
+
+/*! \brief Helper macro for increased readability with ADC_Ch_InputMode_and_Gain_Config
+ *
+ * \sa ADC_Ch_InputMode_and_Gain_Config
+ */
+#define ADC_DRIVER_CH_GAIN_NONE ADC_CH_GAIN_1X_gc
+
+
+/*! \brief This macro configures the Positiv and negativ inputs.
+ *
+ * \param _adc_ch Which ADC channel to configure.
+ * \param _posInput Which pin (or internal signal) to connect to positive
+ * ADC input. Use ADC_CH_MUXPOS_enum type.
+ * \param _negInput Which pin to connect to negative ADC input.
+ * Use ADC_CH_MUXNEG_t type.
+ *
+ * \note The negative input is connected to GND for single-ended and internal input modes.
+ */
+#define ADC_Ch_InputMux_Config(_adc_ch, _posInput, _negInput) \
+ ((_adc_ch)->MUXCTRL = (uint8_t) _posInput | _negInput)
+
+
+/*! \brief This macro returns the channel conversion complete flag..
+ *
+ * \param _adc_ch Pointer to ADC Channel register section.
+ *
+ * \return value of channels conversion complete flag.
+ */
+#define ADC_Ch_Conversion_Complete(_adc_ch) \
+ (((_adc_ch)->INTFLAGS & ADC_CH_CHIF_bm) != 0x00)
+
+
+/*! \brief This macro sets the value in the ADC compare register.
+ *
+ * The value in the ADC compare register is used by the result comparator for
+ * channels that are configured to notify when result is above or below this
+ * value. Even if the ADC compare value register is always left adjusted, the input
+ * to this function is adjusted according to the result presentation setup
+ * for the ADC. This means that the value will be right adjusted unless the
+ * "12-bit left adjust" result mode is selected with
+ * ADC_ConvMode_and_Resolution_Config.
+ *
+ * \param _adc Pointer to ADC module register section.
+ * \param _value 12-bit value used by the result comparator. Use uint16_t type.
+ */
+#define ADC_CompareValue_Set(_adc, _value) ((_adc)->CMP = _value)
+
+
+/*! \brief This macro enables the Free Running mode in the selected adc.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_FreeRunning_Enable(_adc) ((_adc)->CTRLB |= ADC_FREERUN_bm)
+
+
+/*! \brief This macro disables the Free Running mode in the selected adc.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_FreeRunning_Disable(_adc) \
+ ((_adc)->CTRLB = (_adc)->CTRLB & (~ADC_FREERUN_bm))
+
+
+/*! \brief This macro starts one channel conversion
+ *
+ * Use the ADC_GetWordResultCh or ADC_GetByteResultCh functions to
+ * retrieve the conversion result. This macro is not to be used
+ * when the ADC is running in free-running mode.
+ *
+ * \param _adc_ch Pointer to ADC Channel module register section.
+ */
+#define ADC_Ch_Conversion_Start(_adc_ch) ((_adc_ch)->CTRL |= ADC_CH_START_bm)
+
+
+/*! \brief This macro starts multiple channel conversions
+ *
+ * This macro starts a conversion for the channels selected by
+ * the channel mask parameter. Use the bit mask defines for each
+ * channel and combine them into one byte using bitwise OR.
+ * The available masks are ADC_CH0START_bm, ADC_CH1START_bm,
+ * ADC_CH2START_bm and ADC_CH3START_bm.
+ *
+ * \param _adc Pointer to ADC module register section.
+ * \param _channelMask A bitmask selecting which channels to check.
+ */
+#define ADC_Conversions_Start(_adc, _channelMask) \
+ (_adc)->CTRLA |= _channelMask & \
+ (ADC_CH0START_bm | ADC_CH1START_bm | \
+ ADC_CH2START_bm | ADC_CH3START_bm)
+
+
+/*! \brief This macro pre enables the Bandgap Reference.
+ *
+ * \note If the ADC is enabled the Bandgap Reference is automaticly enabled.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_BandgapReference_Enable(_adc) ((_adc)->REFCTRL |= ADC_BANDGAP_bm)
+
+
+/*! \brief This macro disables the pre enabled the Bandgap Reference.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_BandgapReference_Disable(_adc) ((_adc)->REFCTRL &= ~ADC_BANDGAP_bm)
+
+
+/*! \brief This macro makes sure that the temperature reference circuitry is enabled.
+ *
+ * \note Enabling the temperature reference automatically enables the bandgap reference.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_TempReference_Enable(_adc) ((_adc)->REFCTRL |= ADC_TEMPREF_bm)
+
+
+/*! \brief This macro disables the temperature reference.
+ *
+ * \param _adc Pointer to ADC module register section.
+ */
+#define ADC_TempReference_Disable(_adc) \
+ ((_adc)->REFCTRL = (_adc)->REFCTRL & (~ADC_TEMPREF_bm))
+
+
+/* Prototype for assembly macro. */
+uint8_t SP_ReadCalibrationByte( uint8_t index );
+
+/* Prototypes for functions. */
+void ADC_CalibrationValues_Load(ADC_t * adc);
+
+uint16_t ADC_ResultCh_GetWord_Unsigned(ADC_CH_t * adc_ch, uint8_t offset);
+int16_t ADC_ResultCh_GetWord_Signed(ADC_CH_t * adc_ch, int8_t offset);
+
+uint8_t ADC_Offset_Get_Unsigned(ADC_t * adc, ADC_CH_t *ch, bool oversampling);
+int8_t ADC_Offset_Get_Signed(ADC_t * adc, ADC_CH_t *ch, bool oversampling);
+
+uint16_t ADC_ResultCh_GetWord(ADC_CH_t * adc_ch);
+uint8_t ADC_ResultCh_GetLowByte(ADC_CH_t * adc_ch);
+uint8_t ADC_ResultCh_GetHighByte(ADC_CH_t * adc_ch);
+
+void ADC_Wait_8MHz(ADC_t * adc);
+void ADC_Wait_32MHz(ADC_t * adc);
+
+/*! Deprecated functions: Compatibility with previous application note version.
+ * These functions will be removed in later releases of the driver
+ * \name Deprecated functions
+ */
+//@{
+#define ADC_Referance_Config(_adc, _convRef) ADC_Reference_Config(_adc, _convRef)
+#define ADC_CalibrationValues_Set(_adc) ADC_CalibrationValues_Load(_adc)
+//@}
+
+
+/*! Offset addresses for production signature row on which is not in current GCC
+ * header files
+ * \name GCC compatibility macros
+ */
+//@{
+#ifndef ADCACAL0_offset
+
+#define ADCACAL0_offset 0x20
+#define ADCACAL1_offset 0x21
+#define ADCBCAL0_offset 0x24
+#define ADCBCAL1_offset 0x25
+#endif
+//@}
+
+#endif
\ No newline at end of file
diff --git a/firmware/tinyg/xmega/avr_compiler.h b/firmware/tinyg/xmega/avr_compiler.h
new file mode 100755
index 0000000..1c71e85
--- /dev/null
+++ b/firmware/tinyg/xmega/avr_compiler.h
@@ -0,0 +1,153 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief This file implements some macros that makes the IAR C-compiler and
+ * avr-gcc work with the same code base for the AVR architecture.
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation:
http://www.atmel.com \n
+ * Support email:
avr@atmel.com
+ *
+ * $Revision: 613 $
+ * $Date: 2006-04-07 14:40:07 +0200 (fr, 07 apr 2006) $ \n
+ *
+ * Copyright (c) 2008, 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "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 EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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 COMPILER_AVR_H
+#define COMPILER_AVR_H
+
+#ifndef F_CPU
+/*! \brief Define default CPU frequency, if this is not already defined. */
+#define F_CPU 2000000UL
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+/*! \brief This macro will protect the following code from interrupts. */
+#define AVR_ENTER_CRITICAL_REGION( ) uint8_t volatile saved_sreg = SREG; \
+ cli();
+
+/*! \brief This macro must always be used in conjunction with AVR_ENTER_CRITICAL_REGION
+ * so the interrupts are enabled again.
+ */
+#define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;
+
+#if defined( __ICCAVR__ )
+
+#include <inavr.h>
+#include <ioavr.h>
+#include <intrinsics.h>
+#include <pgmspace.h>
+
+#ifndef __HAS_ELPM__
+#define _MEMATTR __flash
+#else /* __HAS_ELPM__ */
+#define _MEMATTR __farflash
+#endif /* __HAS_ELPM__ */
+
+/*! \brief Perform a delay of \c us microseconds.
+ *
+ * The macro F_CPU is supposed to be defined to a constant defining the CPU
+ * clock frequency (in Hertz).
+ *
+ * The maximal possible delay is 262.14 ms / F_CPU in MHz.
+ *
+ * \note For the IAR compiler, currently F_CPU must be a
+ * multiple of 1000000UL (1 MHz).
+ */
+#define delay_us( us ) ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) )
+
+/*! \brief Preprocessor magic.
+ *
+ * Some preprocessor magic to allow for a header file abstraction of
+ * interrupt service routine declarations for the IAR compiler. This
+ * requires the use of the C99 _Pragma() directive (rather than the
+ * old #pragma one that could not be used as a macro replacement), as
+ * well as two different levels of preprocessor concetanations in
+ * order to do both, assign the correct interrupt vector name, as well
+ * as construct a unique function name for the ISR.
+ *
+ * \note Do *NOT* try to reorder the macros below, as this will only
+ * work in the given order.
+ */
+#define PRAGMA(x) _Pragma( #x )
+#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
+#define sei( ) (__enable_interrupt( ))
+#define cli( ) (__disable_interrupt( ))
+
+/*! \brief Define the no operation macro. */
+#define nop( ) (__no_operation())
+
+/*! \brief Define the watchdog reset macro. */
+#define watchdog_reset( ) (__watchdog_reset( ))
+
+
+#define INLINE PRAGMA( inline=forced ) static
+
+#define FLASH_DECLARE(x) _MEMATTR x
+#define FLASH_STRING(x) ((_MEMATTR const char *)(x))
+#define FLASH_STRING_T char const _MEMATTR *
+#define FLASH_BYTE_ARRAY_T uint8_t const _MEMATTR *
+#define PGM_READ_BYTE(x) *(x)
+#define PGM_READ_WORD(x) *(x)
+
+#define SHORTENUM /**/
+
+#elif defined( __GNUC__ )
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <util/delay.h>
+
+/*! \brief Define the delay_us macro for GCC. */
+#define delay_us( us ) (_delay_us( us ))
+
+#define INLINE static inline
+
+/*! \brief Define the no operation macro. */
+#define nop() do { __asm__ __volatile__ ("nop"); } while (0)
+
+#define MAIN_TASK_PROLOGUE int
+
+
+#define MAIN_TASK_EPILOGUE() return -1;
+
+#define SHORTENUM __attribute__ ((packed))
+
+#else
+#error Compiler not supported.
+#endif
+
+#endif