###############################   MAIN.C  ######################################

#include <avr/io.h>
#include <inttypes.h>
#include "stdlib.h"
#include "intern_adc.h"			// intern_ADC-Funktionen
#include "ad7305.h"				// DAC-Funktionen
#include "funktionen.h"			// Treiberfunktionen

int main(void)
{
 ad7305_init();					// DAC INIT PORTs und Grundstellung
 intern_adc_init(CH0);			// internen ADC auf Kanal 0 einstellen
   
for(;;)
{
 backward();		
 					
 forward();
}

return 0;
}

###############################   AD7305.C  ######################################

#include <inttypes.h>
#include <avr/io.h>
#include "stdlib.h"
#include "ad7305.h"

void ad7305_init(void)
{
 DACPORTDIR 	 	 = 0xFF;	// DACPORT alles Ausgänge
 DAC_CONPORTDIR	 = 0xFF;	// WR LDAC A0 A1 = Ausgänge (PD0,PD1,PD5,PD6)

 DACPORT		 = 0x00;	// Spannungswert = NULL
 DAC_CONPORT	 = 0x63;	// Adresse auf Kanal A  + WR & LDAC = High
}

void ad7305_one(uint8_t kanal, uint8_t daten)
{
 uint8_t		dac_kanal;
 uint8_t		dac_daten;

 dac_kanal = kanal;
 dac_daten = daten;

 DAC_CONPORT = (DAC_CONPORT & 0xFC) | dac_kanal; 	// Adresse einstellen (A,B,C oder D)

 cbi(DAC_CONPORT,WR);					// WR-Bit LOW
 	asm("nop");
 	asm("nop");

 DACPORT = dac_daten;					// Daten an den Port legen
 	asm("nop");
 	asm("nop");
  	asm("nop");
 	asm("nop");

 sbi(DAC_CONPORT,WR);					// WR-Bit HIGH

 cbi(DAC_CONPORT,LDAC);					// Ausgabe aktualisieren
  	asm("nop");
 	asm("nop");

 sbi(DAC_CONPORT,LDAC);					// LDAC toggeln um DAC-Wert auszugeben
 
}

###############################  intern_adc.c ######################################

#include <avr/io.h>
#include <inttypes.h>
#include "stdlib.h"			// Standard-Funktionen
#include "intern_adc.h"			// intern_ADC-Funktionen

void intern_adc_init(uint8_t channel)
{
 ADCPORTDIR = 0x00;			// ADCPORT = alles Eingänge

 ADMUX = 0x40|(channel & 0x07);	// Vref=AVCC | Ergebnis=rechtsbündig | Kanal=channel
 
 SFIOR = SFIOR & 0x0F;		// nur falls ADATE,dann FREE RUNNING MODE
 
 ADCSRA = 0xE6;			// ADEN=1| ADSC=1| ADATE=1| ADIF=>1(clear)| Int=disa| Prescal=64

}

uint16_t getConversion_intern_adc(void)
{
 uint16_t	value=0,mittel;
 uint8_t		lauf=0;

 //loop_until_bit_is_clear(ADCSRA,ADSC);	// ni erforderlich da free running
if(bit_is_set(ADCSRA,ADIF)!=0)			// pollt ADIF wenn eins: wandlung fertig
 {
   value = (uint16_t)(value | ADCL);		// value = xxxx|ADCL
   value = (uint16_t)(value | (ADCH<<8));		// value = ADCH|ADCL
   sbi(ADCSRA,ADIF);				// Reset/Clear Interrupt-Flag
 }
 
//sbi(ADCSRA,ADSC);				// ni nötig, da "free running"

return value;					// Wert-Rückgabe
}

############################  funktionen.c  ############################################
####################################################################################

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "stdlib.h"
#include "intern_adc.h"			// intern_ADC-Funktionen
#include "ad7305.h"			// DAC-Funktionen
#include "funktionen.h"			// Treiberfunktionen

const uint8_t sin_table_array[] PROGMEM = {

0x7F, 0x82,0x85,0x88,0x8B,0x8E,0x91,0x94,
0x97, 0x9A,0x9D,0xA0,0xA3,0xA6,0xA9,0xAC,
0xAF, 0xB2,0xB5,0xB8,0xBA,0xBD,0xC0,0xC2,
0xC5, 0xC8,0xCA,0xCD,0xCF,0xD1,0xD4,0xD6,
0xD8, 0xDA,0xDD,0xDF,0xE1,0xE3,0xE5,0xE6,
0xE8, 0xEA,0xEB,0xED,0xEF,0xF0,0xF1,0xF3,
0xF4, 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFA,
0xFB, 0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFD,
0xFE, 0xFD,0xFD,0xFD,0xFD,0xFD,0xFC,0xFC,
0xFB, 0xFA,0xFA,0xF9,0xF8,0xF7,0xF6,0xF5,
0xF4, 0xF3,0xF1,0xF0,0xEF,0xED,0xEB,0xEA,
0xE8, 0xE6,0xE5,0xE3,0xE1,0xDF,0xDD,0xDA,
0xD8, 0xD6,0xD4,0xD1,0xCF,0xCD,0xCA,0xC8,
0xC5, 0xC2,0xC0,0xBD,0xBA,0xB8,0xB5,0xB2,
0xAF, 0xAC,0xA9,0xA6,0xA3,0xA0,0x9D,0x9A,
0x97, 0x94,0x91,0x8E,0x8B,0x88,0x85,0x82,
0x7F, 0x7B,0x78,0x75,0x72,0x6F,0x6C,0x69,
0x66, 0x63,0x60,0x5D,0x5A,0x57,0x54,0x51,
0x4E, 0x4B,0x48,0x45,0x43,0x40,0x3D,0x3B,
0x38, 0x35,0x33,0x30,0x2E,0x2C,0x29,0x27,
0x25, 0x23,0x20,0x1E,0x1C,0x1A,0x18,0x17,
0x15, 0x13,0x12,0x10,0xE,0xD,0xC,0xA,
0x9, 0x8,0x7,0x6,0x5,0x4,0x3,0x3,
0x2, 0x1,0x1,0x0,0x0,0x0,0x0,0x0,
0x0, 0x0,0x0,0x0,0x0,0x0,0x1,0x1,
0x2, 0x3,0x3,0x4,0x5,0x6,0x7,0x8,
0x9, 0xA,0xC,0xD,0xE,0x10,0x12,0x13,
0x15, 0x17,0x18,0x1A,0x1C,0x1E,0x20,0x23,
0x25, 0x27,0x29,0x2C,0x2E,0x30,0x33,0x35,
0x38, 0x3B,0x3D,0x40,0x43,0x45,0x48,0x4B,
0x4E, 0x51,0x54,0x57,0x5A,0x5D,0x60,0x63,
0x66, 0x69,0x6C,0x6F,0x72,0x75,0x78,0x7B
};															// PageMemorySpace

void forward(void)
{
 uint16_t	adc16 = 512;
 uint8_t		adc8, diff8, step, step_a=0, step_b=64, step_c=128, step_d=192;
 uint8_t		dac_wert;

  	adc16 =  getConversion_intern_adc();			 // ADC-Wandlung durchlaufen
  	adc8 = adc16>>2;					 // 10bit zu 8bit

  	while(HALF_8 <= adc8)
 		{
 		 adc16 =  getConversion_intern_adc(); 		// ADC-Wandlung durchlaufen
  		 adc8 = adc16>>2;				// 10bit zu 8bit
  		 
  //adc8f = 200;   // #################### DEBUG-Zeile zum simulieren
  		
  		 diff8 = adc8 - HALF_8;			// Differnz min=0 max=128
  		 //stepf = (diff8f>>2);			// Schrittweite ermitteln
  				 
  		 step_a += (diff8>>2);			// Feld-Adresse Kanal A
  		 step_b += (diff8>>2);			// Feld-Adresse Kanal B
  		 step_c += (diff8>>2);			// Feld-Adresse Kanal C
  		 step_d += (diff8>>2);			// Feld-Adresse Kanal D
  		 		 
  		 dac_wert = pgm_read_byte(&sin_table_array[step_a]);
  		 ad7305_one(0x01, dac_wert);			// DAC - Kanal A
  		 		 
  		 dac_wert = pgm_read_byte(&sin_table_array[step_b]);
  		 ad7305_one(C, dac_wert);			// DAC - Kanal B
  	 
  	 	 dac_wert = pgm_read_byte(&sin_table_array[step_c]);
 	 	 ad7305_one(B, dac_wert);			// DAC - Kanal C
  	 			 
  	 	 dac_wert = pgm_read_byte(&sin_table_array[step_d]);
  	 	 ad7305_one(A, dac_wert);			// DAC - Kanal D
  		
  		};
}

// #############################################################################

void backward(void)
{
 uint16_t	adc16=512;
 uint8_t		adc8, diff8, step, step_a=0, step_b=64, step_c=128, step_d=192;
 uint8_t		dac_wert;

 		 adc16 =  getConversion_intern_adc(); 		// ADC-Wandlung durchlaufen
  		 adc8  =  adc16>>2;				// 10bit zu 8bit

  	while(adc8 <= HALF_8)
 		{
 		 adc16 =  getConversion_intern_adc(); // ADC-Wandlung durchlaufen
  		 adc8 = adc16>>2;				// 10bit zu 8bit
  				 diff8 = HALF_8 - adc8;		// Differnz min=0 max=128
  				 step = 32 - (diff8>>4);		// Schrittweite ermitteln

  				 step_a += step;	// Feld-Adresse Kanal A
  				 step_b += step;	// Feld-Adresse Kanal B
  				 step_c += step;	// Feld-Adresse Kanal C
  				 step_d += step;	// Feld-Adresse Kanal D

  		 dac_wert = pgm_read_byte(&sin_table_array[step_a]);
  		 ad7305_one(D, dac_wert);			// DAC - Kanal A
  		 		 
  		 dac_wert = pgm_read_byte(&sin_table_array[step_b]);
  		 ad7305_one(C, dac_wert);			// DAC - Kanal B
  	 
  	 	 dac_wert = pgm_read_byte(&sin_table_array[step_c]);
 	 	 ad7305_one(B, dac_wert);			// DAC - Kanal C
  	 			 
  	 	 dac_wert = pgm_read_byte(&sin_table_array[step_d]);
  	 	 ad7305_one(A, dac_wert);			// DAC - Kanal D
	
  		};
}

#################################################################################
#######										#####
#######			HEADER-FILES						#####
#######										#####
#################################################################################

###############################   AD7305.H  ######################################

//   DEFINES

#define DACPORTDIR		DDRB		// DAC Datenrichtungsregister
#define DACPORT		PORTB		// DAC Port
#define DACPIN			PINB		// DAC Pin

#define DAC_CONPORTDIR	DDRD		// DAC Kontrollport-Datenrichtung
#define DAC_CONPORT		PORTD		// DAC KontrollPort
#define DAC_CONPIN		PIND		// DAC KontrollPin

#define A			0x00		// DAC - Adresse A
#define B			0x01		// DAC - Adresse B
#define C			0x02		// DAC - Adresse C
#define D			0x03		// DAC - Adresse D

#define WR			5
#define LDAC			6

// INITIALISIERUNGEN

void ad7305_init(void);				// DAC Init
void ad7305_one(uint8_t kanal, uint8_t daten);	// schreibt Daten
						// auf einen Kanal

###############################   intern_adc.H  ######################################

// ###################  DEFINES

#define ADCPORTDIR	DDRA		
#define ADCPORT		PORTA		
#define ADCPIN			PINA

#define CH0				0x00	// die einzeln mögl. Kanäle
#define CH1				0x01
#define CH2				0x02
#define CH3				0x03
#define CH4				0x04
#define CH5				0x05
#define CH6				0x06
#define CH7				0x07

// ################### INITIALISIERUNGEN

void intern_adc_init(uint8_t channel);		// initialisiert ADC
uint16_t getConversion_intern_adc(void); 		// startet 1 ADC-Wandlung

###############################   funktionen.H  ######################################

// ###################  DEFINES

#define	HALF_8	127				// ADC-Mitte (in 8bit !)

// ################### INITIALISIERUNGEN

void backward(void);
void forward(void);

// ####################################   ENDE #####################################