@thereza's ADC patch

Post Reply
WayOutWest
Posts: 198
Joined: Thu Jul 16, 2015 12:18 am
Location: Washington State, USA

@thereza's ADC patch

Post by WayOutWest »

Since there isn't a thread dedicated to it, and since the posting is hard to find, and since I spent the time to carefully rebase his tarball (@thereza, don't EVER delete the .git directory like that!), I've created this thread.

His original posting is here: http://www.liteplacer.com/phpBB/viewtop ... rt=10#p483

Click that link, download the tarball, and extract the firmware/code directory... this contains Atmel-copyrighted software and I don't think it's supposed to be redistributed (no cost, but they want to force you to register on their website, ugh), so I haven't included it in my patch.

Then apply the patch below and

Code: Select all

cd firmware/tinyg/default
make clean
make all
... and you should get tinyg.hex with $adc0 support.

I had to do this since it has become clear that I absolutely will not be able to avoid modifying the TinyG firmware... there are bugs (like G38.2 not backing off the switch!) that must be fixed. So I need to be able to bring his patch forward as I follow the TinyG upstream repo.

On a more positive note, I'll be adding support for passively detecting that the part was accidentally dropped so the host doesn't have to poll $adc0 continuously.
Last edited by WayOutWest on Wed Sep 30, 2015 8:46 pm, edited 2 times in total.
- Adam
WayOutWest
Posts: 198
Joined: Thu Jul 16, 2015 12:18 am
Location: Washington State, USA

Re: @thereza's ADC patch

Post by WayOutWest »

Gee, lovely, when I try to attach the patch the forum says

"The extension txt is not allowed."

Juha, could you please fix this?
Last edited by WayOutWest on Wed Sep 30, 2015 8:41 pm, edited 1 time in total.
- Adam
WayOutWest
Posts: 198
Joined: Thu Jul 16, 2015 12:18 am
Location: Washington State, USA

Re: @thereza's ADC patch

Post by WayOutWest »

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
- Adam
JuKu
Site Admin
Posts: 1114
Joined: Thu Feb 14, 2013 3:06 pm
Location: Tampere, Finland
Contact:

Re: @thereza's ADC patch

Post by JuKu »

WayOutWest wrote:Gee, lovely, when I try to attach the patch the forum says

"The extension txt is not allowed."

Juha, could you please fix this?
Fixed.
thereza
Posts: 138
Joined: Fri Feb 13, 2015 11:49 pm

Re: @thereza's ADC patch

Post by thereza »

WayOutWest wrote:Since there isn't a thread dedicated to it, and since the posting is hard to find, and since I spent the time to carefully rebase his tarball (@thereza, don't EVER delete the .git directory like that!), I've created this thread.
Don't recall deleting it, but ok. So I've not used the liteplacer in like 6 months. need to use it again. what's the latest on this - should i upgrade the tinyg firmware?
Jet
Posts: 100
Joined: Mon Apr 17, 2017 4:13 am

Re: @thereza's ADC patch

Post by Jet »

I've compiled TinyG Build 440.20 with this patch using Atmel Studio v6.2.1563, so that
it's not necessary to recompile it to use the latest supported version of TinyG.

It identifies as Build 440.21 once installed, and $adc0 will then return a value.

Make sure to copy the output of $$ before updating, and check afterwards to reset any settings that have changed after updating the firmware.

(Hex file contained inside the zip)
tinyg-440_21ADC.zip
(99.79 KiB) Downloaded 768 times
User avatar
Markk
Posts: 5
Joined: Sat Aug 05, 2017 2:14 pm

Re: @thereza's ADC patch

Post by Markk »

WayOutWest wrote:Meanwhile, here's the patch, although it's probably not going to work after being pasted into a forum post.
Hi,

Does anybody have the original source code or patch? As predicted by @WayOutWest the version in the post does not work. Well, I don't know much about patch files, honestly, so it may just be my mistake in applying it (I just tried Tortoise git's patch menu).

I would like to try and integrate ADC into the OpenPnP version of TinyG.

https://makr.zone/tinyg-new-g-code-comm ... p-use/577/

This version might also be useful for use with the Liteplacer Software. ;-)

_Mark
Post Reply