zuätzliche Links:
http://de.wikipedia.org/wiki/R2R
http://www.avr-asm-tutorial.net/avr_de/avr_dac.html
aus dem Kurs Assembler http://www.avr-asm-tutorial.net/avr_de/
Seminarunterlagen : PGA103_PrgAmp.pdf
Manual als PDF:
und ein typisches IC PGA100.pdf
Unterfamilien beachten z.B. PGA103 pga103.pdf
einfach googeln
EGALE FILES:
Mit Widerständen
R2R-8BIT-VOUT_V2.sch
R2R-8BIT-VOUT_V2.brd
R2R-8BIT-VOUT_Diskret V5.sch
R2R-8BIT-VOUT_Diskret V5.brd
SMD Version
R2R-8BIT-VOUT_V7_SMD.sch
R2R-8BIT-VOUT_V7_SMD.brd
mit
vollstaendigem
C-Code Bespiel
R2R
oder
R-2R
Netzwerk oder R-2R
DAC (Digital Analog Converter)
Der
R-2R-Konverter ist der am häufigsten benutzte D/A-Wandler.
Prinzip
Man
erkennt, das der 2R immer zwischen einer Spannung (VCC) und 0V
geschaltet wird,. Also ideal wie ein TTL Ausgang 5V oder 0V.
Damit kann man mit einem µC Ausgang direkt in ein R2R Netz einkoppeln.
WiderstandsNiveau sollte aber so um 3...5KOhm ligen
Der
R-2R-Konverter ist ein D/A-Wandler,
der eine Widerstand-Matrix als Spannungsteiler benutzt. Die einzelnen Widerstände der Matrix werden
für die Umwandlung mit elektronischen Schaltern zu- und
abgeschaltet. Die Ausgangsspannung ist dabei proportional dem binären Digitalsignal
Prinzip einer R2R
Widerstandnsnetzwerkes zur Digital Analog Wandlung:
Achtung
Im Gegensatz
zu dem gewichteten Widerstands-Konverter, bei dem die Widerstandwerte
das 2-, 4-, 8- und 16-fache des Basiswiderstands entsprechen, gibt es
beim R-2R-Konverter nur zwei Widerstandswerte "R" und "2R". Letztere
allerdings mehrfach, da daraus die Spannungsteilung für den 4-, 8- und
16-fachen Wert erstellt werden. Dies geschieht indem man mehrere
Widerstände gleichzeitig in den Spannungsteiler zu- oder abschaltet.
Mit dem selben Prinzip kann eine PGA ( Programmable Gain Amplifier
)Schaltung generiert werden.
Statt der Referenz wird eben die Eingangs-Spannung angelegt
ein typischer Vertreter heißt PGA100.
Einfacher
8-Bit-Digital-zu-Analog-Wandler mit einem R/2R-Netzwerk
|
Die
Umwandlung von digitalen Werten in eine Analogspannung kann durch
integrierte Schaltungen bewerkstelligt werden. Eine billigere und
weniger anspruchsvolle Lösung ist ein selbstgebautes
R/2R-Widerstandsnetzwerk, gefolgt von einem Operationsverstärker.
Ein
R/2R-Netzwerk ist wie im Bild gezeigt aus Widerständen aufgebaut. Die
einzelnen Eingangsbits liegen entweder auf Null Volt oder auf der
Betriebsspannung und speisen über doppelt so große Widerstände ein wie
der vertikale Teil des Netzwerks. Jedes Bit trägt so seinen
spezifischen Teil zur resultierenden Ausgangsspannung bei. Das
funktioniert wirklich, und ziemlich gut! Kommerzielle
Digital-Analog-Wandler haben solche R/2R-Netzwerke im IC integriert.
Der
Ausgang eines AVR liefert nicht sehr viel Strom an seinen
Portausgängen, wenn die Spannungen in der Nähe der
Versorgungsspannungen bleiben sollen. Daher sollten die Widerstände des
R/2R-Netzwerks größer als einige 10 Kiloohm sein. Um das Netzwerk
möglichst gering zu belasten entkoppelt ein Operationsverstärker das
Netzwerk vom weiteren Verbraucher.
Die Widerstandswerte sollten
so genau eingehalten werden wie es vom gesamten Netzwerk erwartet wird.
Abweichungen von Widerstandswerten sind besonders bei den höherwertigen
Bits relevant. Die folgende Tabelle zeigt einige Beispiele für die
schrittweise Spannungssteigerung eines R/2R-Netzwerks mit einer
51k/100k-Kombination.
|
16Bit Passiv R2R
Netzwerk . Letzter Widerstand rechts an Masse ist 2R
Die Waagerechte sind bis auf diesen Lezten 1*R, die Senkrechten 2R
und jetzt die Platine mit Eagle. Man sieht die Ähnlichkeit mit der
Simulation
R2R-8BIT-VOUT_V2.sch
Das Layout...
R2R-8BIT-VOUT_V2.brd
So einfach kanns sein !!
Aufbau mit vom R-2R Erzeugtem Signalformen
|
|
|
|
|
|
|
S
Simulation der R2R Netzwerke |
Hier die Array Definition für eine Sinusausgabe mit dem R2R Netzwerk,
Amplitiude 0..255 und Stufen ebenfalls 256 stufen. Wer mehr möchte,
bitte...
uint8_t gu8SineVal[256];
gu8SineVal[iNN] = round( 127.5 * (sin( 2*M_PI* iNN/256.0) +
1 ) );
oder feste ProgMem Speichertabelle:
const char MCA_SINUS[] PROGMEM = {
// "256 Byte SINUS von 0..255
128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,176,179,182,\
185,188,190,193,196,198,201,203,206,208,211,213,215,218,220,222,224,226,228,\
230,232,234,235,237,238,240,241,243,244,245,246,248,249,250,250,251,252,253,\
253,254,254,254,255,255,255,255,255,255,255,254,254,254,253,253,252,251,250,\
250,249,248,246,245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,\
220,218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,176,173,\
170,167,165,162,158,155,152,149,146,143,140,137,134,131,128,124,121,118,115,\
112,109,106,103,100,97,93,90,88,85,82,79,76,73,70,67,65,62,59,57,54,52,49,47,\
44,42,40,37,35,33,31,29,27,25,23,21,20,18,17,15,14,12,11,10,9,7,6,5,5,4,3,2,\
2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,17,18,20,21,23,\
25,27,29,31,33,35,37,40,42,44,47,49,52,54,57,59,62,65,67,70,73,76,79,82,85,88,\
90,93,97,100,103,106,109,112,115,118,121,124};
P.S
Vcc:
Betriebsspannung (meist 5V)
Vdd: dasselbe wie Vcc, manchmal auch für eine andere Spannung neben den
5V (z.B. 3,3V)
Vee: negative Betriebsspannung, wenn nicht benötigt (z.B. bei 405x
Analogschalter): Mit Vss verbinden
Vss: Masse, GND, 0V
Hier
der vollständige Code ( fast Fertig) für einen mit R"R Netzwerk
realisierten SIgnal-Frequenz-generator.
Mit einem Timerinterrrupt gesteuerten Aausgabe.
Sinus, Rechteck mit
Amplitudensteuerung, Sägezahn (steigend, fallend),
zuerst die mögl Kommandos
#define
DATUM
"16.11.2010"
#define
FUNKTION "Frequenzgenerator
mit PGA"
#define
HARDWARE
"AT-Mega16 AVR Atmel"
#define
AUTOR
"(C) Christof Ermer,
Regensurg"
#define
ORGANISATION
"(C) Universität Regensburg -
Physik"
3
Leitungs- Serial, BAUD 9600 8Bit 1
Stop bit, No Handshake, No
XonXoff.
Pin 2 ist
Tx, Pin 3 ist Rx, Pin
5 ist GND
Sende
im Format:
Befehl[,Value1][,Value2]<CR>
(gross/klein Bucstaben = egal)
<CR>
= Ascii 13
Value ist ein Wert , im floatformat,
also z.B: 4 oder 4.321 oder 4.0
Anwendung:
Ping<CR> = Ping<13> à Antwort:
Pong<13>
MAX
Output Voltage = 5V/256
* 255 = 4.98
V à
PGA OutPut =
0..255 = 0..4.98V
Spannung
in
Volt(Teilen) eingeben. Eichung automatisch auf den nächsten mögl. Wert.
Auch
die Frequenz wird
automatisch quantisiert auf den nächst mögl. Wert.
Bereich:
Rechteck bis
100Khz, Sinus, Dreick, etc.
nur 0..580Hz
weil 256 Schritte/Periode
LIMITS
Frequenz
Rechteck <=
150 kHz,
Sinus, Dreieck, Sägezahn <=
585 Hz
Spannung:
in Teilen
von 256/5 = 551,2 mV Range 0.4.98V
main.c
bitte, wer in benutzt,
kann über eine kleine Spende nachdenken !
//------------------------------------------------------------------------------
// Programmed by Christof Ermer
//------------------------------------------------------------------------------
//SYSINFO
#define DATUM
"16.11.2010"
#define FUNKTION
"Frequenzgenerator mit PGA"
#define HARDWARE
"AT-Mega16 AVR Atmel"
#define UHRZEIT
"12:00"
#define AUTOR
"(C)
Christof Ermer, Regensburg"
#define ORGANISATION "(C) Universität
Regensburg - Physik"
/*
#define UART_BAUD_RATE 9600
#define F_CPU 16000000
gu8SineVal[iNN] = round( 127.5 * (sin( 2*M_PI* iNN/256.0) + 1 ) );
*/
/*
HISTORIE HISTORIE HISTORIE HISTORIE HISTORIE HISTORIE HISTORIE
UMSTELLUNG Timer 2 to Timer 0
Weil innterrupt des Timer eins vorrang hat !! MUSS Erste Priorität haben
#define
TIMER2_OVF_vect
_VECTOR(4)
#define
TIMER1_COMPA_vect
_VECTOR(6)
#define
TIMER0_OVF_vect
_VECTOR(9)
*/
#include <ctype.h>
#include <inttypes.h>
#include <avr\io.h>
#include <avr\pgmspace.h> // <--#include
<progmem.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <avr\interrupt.h> // obsolete #include
<avr\signal.h>
//ACHTUNG STELLT OBSOLETE Procedure in header wieder her
#include <compat\deprecated.h>
#include <avr\wdt.h>
//Produziert Fehler...
#include <util\delay.h>
//_delay_loop_1 _delay_loop_2 delay_ms
#include "main.h"
//with Hardware assigns
#include "uart.h"
#include "lcd.h"
void WarteMal(uint16_t u16WaitTicks);
void Set_Frq(float pfVal);
void FRQ_Off(void);
void FRQ_On(void);
void Timer0_PWM(unsigned char ucPwmRange);
#ifdef ADC_USED_ENABLED
uint16_t ADC_10Bit(uint8_t ucChan); // 0..7
uint16_t ADC_StatistiKRead(uint8_t u8Channel, uint16_t u16LastRead);
float PotiSkalierung( uint16_t u16Poti );
//Normiert Poti mit Offset auf 0..1 von 0..1000
#endif
#ifdef TIMER_TICK_USED
void StartTickTimer(void); //0.1
Seconds interrupt
uint32_t GetTickDifference(uint32_t u32Time);
#endif
#ifdef USE_TOGGLE_FLAG
void ToggleTEST_BIT(uint8_t ucCnt);
#endif
#ifdef UART_USE_ENABLED
void UART_TXRX_Check(void);
void ResetRxBuff(void);
void PrintCR(void);
void PrintStrCR(const char* pStr);
void Print_PStrCR(PGM_P pmStr);
void CheckOrder(char* pcStr);
void LongToNumStr(int32_t lVal);
void PrintLongCR(int32_t lVal);
void FloatToNumStr(double fVal);
void PrintFloatCR(double fVal);
#endif
//CONSTANT ARRAYs IN .TEXT = ROM ARREA .DATA IST
SRAM !! .BSS SRAM
//const char MCA_DELIMTERSTR[] PROGMEM = { ',',0 };
// GLOBALE VARIABLEN
//MSG
const char MCA_DELIMITER_MSG[] PROGMEM =
",";
const char MCA_SPACE[] PROGMEM = " ";
const char MCA_WELCOME1_MSG[] PROGMEM =
"I have no brain";
const char MCA_WELCOME2_MSG[] PROGMEM =
"use your own";
const char MCA_PGA[] PROGMEM = "PGA";
const char MCA_FREQUENZ[] PROGMEM =
"Frequenz";
const char MCA_GENERATOR[] PROGMEM =
"Generator";
//gu8SineVal[iNN] = round( 127.5 * sin(2*M_PI* iNN/256.0) + 1 );
// f(x)= Amplitude * sin ( 2* M_PI * NN/X_AUFLOESUNG ) + OFFSET
/*
//f(x) = a * sin (2*Pi*x - b) + o
a ist die Amplitude
b ist die Phasenverschiebung
o ist der "Offset"-Wert
für x setzt du halt n/d ein. (n € N)
d ist die Schrittanzahl pro Periode
*/
/*
ODER
iNN)= 0..255
F(x) = 128 + 127* sin( iNN/2562*M_PI* )
*/
const char MCA_SINUS[] PROGMEM = {
// 256 Werte!
128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,176,179,182,\
185,188,190,193,196,198,201,203,206,208,211,213,215,218,220,222,224,226,228,\
230,232,234,235,237,238,240,241,243,244,245,246,248,249,250,250,251,252,253,\
253,254,254,254,255,255,255,255,255,255,255,254,254,254,253,253,252,251,250,\
250,249,248,246,245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,\
220,218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,176,173,\
170,167,165,162,158,155,152,149,146,143,140,137,134,131,128,124,121,118,115,\
112,109,106,103,100,97,93,90,88,85,82,79,76,73,70,67,65,62,59,57,54,52,49,47,\
44,42,40,37,35,33,31,29,27,25,23,21,20,18,17,15,14,12,11,10,9,7,6,5,5,4,3,2,\
2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,17,18,20,21,23,\
25,27,29,31,33,35,37,40,42,44,47,49,52,54,57,59,62,65,67,70,73,76,79,82,85,88,\
90,93,97,100,103,106,109,112,115,118,121,124}; // "256 Byte SINUS von
0..255
// sinus = U-Halbe {0..255}* (sin ( 2 * M_PI *
Zaehler{0..255} / VOLLAUFLÖSUNG{256} +1)
//gu8SineVal[iNN] = round( 127.5 * (sin( 2*M_PI* iNN/256.0) + 1 ) );
//gu8SineVal[iNN] = round( ( gu8PGAVolume/ 2.0 + 0.5) * (sin( 2*M_PI*
iNN/SINUS_X_RESOLUTON) + 1 ) );
static volatile uint16_t gu16X_Resolution = SINUS_X_RESOLUTON; //256
Voreinstellung X
static volatile uint8_t * gpu8SineVal =
NULL; //pointer auf MEM
//static volatile uint8_t gu8Y_Resolution;
#ifdef UART_USE_ENABLED
volatile static char* gpcRxPars;
static char gcaRxStr[RX_STRMAX + 1]; //+1 for the 0
static char gcaNumStr[NUMMAX + 1]; //+1 for the 0
static char gcaStr[STRMAX + 1]; //+1 for the 0
static COMMAND_TYPE gsCmd;
#endif
//static uint8_t gcaSegmentStr[SEGMENTSTRMAX + 1]; //+1 for the 0
static volatile uint32_t gu32_Ticks; //T2
timeCounter, only NN_Counter for Keypressings
//POITS
static volatile uint16_t gu16ModePoti;
static volatile uint16_t gu16VolumePoti;
static volatile uint16_t gu16FrequenzPoti;
// START PARAMETER UND GLOBALS
static volatile uint8_t gu8ModeSelect =
RECHTECK_ON; //START Funktion
static volatile uint8_t gu8PGAVolume = START_PGA_VOLUME; //25 Realer
PGA Wert
static volatile double gfInterruptFRQ =
START_FREQUENZ; // Trägt die Information
der Interrupts
static volatile uint8_t gu8ProgMode_Flag;
//static volatile float gfFRQScaleFakor;
// fSelectedFRQ * XXX für SetFrequenz zb. Recnagle mal 2
//tatsaechliche FRq wird ausgerechnet, je nach Signalform z:B
RectangleFRQ=( FRQ/2 )
//static volatile uint8_t gu8LCD_FLAG;
static volatile uint8_t
gu8Timer_CSxxClkSelect; //z.B.#define
TCCR1B_CLOCKSEL_CPU_1024 0x05
//static volatile uint8_t gu8SineVal[256];
#ifdef TIMER_TICK_USED
// ****************************************************************
//volatile SIGNAL(TIMER2_OVF_vect) //oder
SIGNAL--INTERRUPT(SIG_OVERFLOW2) = mit SEI am Anfang
ISR( TIMER0_OVF_vect ) //oder SIGNAL--INTERRUPT(SIG_OVERFLOW2) = mit
SEI am Anfang
// *******************************************************************
{
gu32_Ticks++;
};
#endif
// ***** ***********************************************************
ISR( TIMER1_COMPA_vect )// signal handler
//#define SIG_OUTPUT_COMPARE1A _VECTOR(6)
// *******************************************************************
{//cli(); //I_SREG automtaic clear by Interrupt and Enabled by
RETI
//register regCnt;
static volatile uint16_t u16PositionToggle;
switch( gu8ModeSelect )
{
case SINUS_RESOLUTION_ON
:
{
//PORTC =
round( 127.5 * (sin( 2*M_PI * (gu8PGASTEPS++)/256.0) + 1) );
PORTC =
*(gpu8SineVal + u16PositionToggle++); //u16PositionToggle als zaehler
missbraucht
u16PositionToggle %= gu16X_Resolution;
break;
};
case SINUS_5V_AMPLIUDE
:
{
//PORTC =
round( 127.5 * (sin( 2*M_PI * (gu8PGASTEPS++)/256.0) + 1) );
PORTC =
pgm_read_byte_near( MCA_SINUS + (u16PositionToggle++ %
SINUS_5V_X_RESOLUTON));
break;
};
case RECHTECK_ON:
{
if( PORTC
)
{
PORTC = 0;
}
else
{
PORTC = gu8PGAVolume;
};
break;
};
case DREICKECK_ON :
{
if( PORTC
== gu8PGAVolume)
{
u16PositionToggle = 0;
};
if(
!PORTC )
{
u16PositionToggle = 1;
};
if(
u16PositionToggle )
{
PORTC++;
}
else
{
PORTC--;
};
break;
};
case SAEGEZAHN_UP :
{
if( PORTC
< gu8PGAVolume )
{
PORTC++;
}
else
{
PORTC = 0;
};
break;
};
case SAEGEZAHN_DOWN :
{
if(
!PORTC )
{
PORTC = gu8PGAVolume;
}
else
{
PORTC--;
};
break;
};
#ifdef PULSE_MODE_IMPLEMENTED
case PULSE_ON :
{
PORTC =
gu8PGAVolume;
//_delay_us(1);
PORTC =
0;
break;
};
#endif
};//switch
//sei();
};
#ifdef USE_TOGGLE_FLAG
// ****************************************************************
void ToggleTEST_BIT(uint8_t ucCnt)
// ****************************************************************
{ // #include <util\delay.h> muss da sein
while(ucCnt--)
{
SET_TESTBIT();
_delay_us(1);
CLR_TESTBIT();
_delay_us(1);
};
};
#endif
// *************************************
void Set_Frq(float fVal) //Verbessert mit Zielbereichskalierung des
Vorteilers.
// *************************************
{
float fComVal;
float fTimerDivider;
unsigned char sreg;
if( fVal > MAXIMAL_FRQ ) return;
if( fVal < MINIMAL_FRQ ) return;
//Voreinstellung
fTimerDivider = TIMER_DIVIDE_FRQ_0; //if( pfVal <
TIMER_HALFCOMP_FRQ_1024)
gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_1;
//Clock udn OCR1A so hoch als möglich
if( ( fComVal = F_CPU / fVal ) > 0xFFFF )
{
fTimerDivider = TIMER_DIVIDE_FRQ_8;
//if( pfVal <
TIMER_HALFCOMP_FRQ_1024)
gu8Timer_CSxxClkSelect =
TCCR1B_CLOCKSEL_CPU_8;
if( ( fComVal = TIMER_DIVIDE_FRQ_8 /
fVal ) > 0xFFFF )
{
fTimerDivider = TIMER_DIVIDE_FRQ_64;
//if( pfVal
< TIMER_HALFCOMP_FRQ_1024)
gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_64;
if( (
fComVal = TIMER_DIVIDE_FRQ_64 / fVal ) > 0xFFFF )
{
fTimerDivider =
TIMER_DIVIDE_FRQ_256; //if( pfVal <
TIMER_HALFCOMP_FRQ_1024)
gu8Timer_CSxxClkSelect =
TCCR1B_CLOCKSEL_CPU_256;
if( ( fComVal = TIMER_DIVIDE_FRQ_256 /
fVal ) > 0xFFFF )
{
fTimerDivider
= TIMER_DIVIDE_FRQ_1024; //if( pfVal <
TIMER_HALFCOMP_FRQ_1024)
gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_1024;
fComVal =
TIMER_DIVIDE_FRQ_1024 / fVal;
}}}};
cli();
sreg = SREG; //loakaler Speicher
TCNT1 = 0; //sicherung gegenen unbeabsichtigten Overrrun
OCR1A = (uint16_t)round( fComVal );
gfInterruptFRQ = fTimerDivider / OCR1A;
TCCR1B = TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;//Clear Timer on
Compare=CTC. MODE an OCR1A + / CLk/1024
SREG = sreg; //loakaler Speicher
sei();
/*
uart_putc(13);
uart_putc(13);
uart_puts("fComVal=");
PrintFloatCR(fComVal);
uart_puts("SelectedFRQ=");
PrintFloatCR( gfInterruptFRQ);
uart_puts("OCR1A=");
PrintLongCR( OCR1A );
uart_puts("TimerDivider=");
PrintLongCR( fTimerDivider );
uart_puts("gu8Timer_CSxxClkSelect=");
PrintLongCR( gu8Timer_CSxxClkSelect );
*/
};
// *************************************
void FRQ_Off(void)
// *************************************
{
unsigned char sreg;
cli();
sreg = SREG; //loakaler Speicher
TIMSK &= ~_BV( OCIE1A ); //Interrupt OFF
TCCR1B = TCCR1B_CLOCKSEL_STOP; //Stopen,
damit keine geschachtelten Interrrupts passieren...
SREG = sreg; //loakaler Speicher
sei();
};
// *************************************
void FRQ_On(void)
// *************************************
{
unsigned char sreg;
cli();
sreg = SREG; //loakaler Speicher
TCNT1 = 0; //sicherung gegenen unbeabsichtigten Overrrun
TIMSK |= _BV( OCIE1A ); //Interrupt ein
TCCR1B = TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;//Clear Timer on
Compare=CTC. MODE an OCR1A + / CLk/1024
SREG = sreg; //loakaler Speicher
sei();
};
/*
ISR( TIMER0_OVF_vect )
// *******************************************************************
{
PWM_ENABLE();
};
*/
/*
// *************************************
void Timer0_PWM(unsigned char ucPwmRange)
// *************************************
{ // 8BIT TIMER T0
unsigned char sreg;
sreg = SREG; //loakaler Speicher
cli();
TIMSK &= (~(_BV(TOIE0))) & (~(_BV(OCIE0)));
//8 Bit Timerx00); //Timer Inhalt
TCNT0= 0x00; //Timer MAX = TOP
Compare
OCR0 = ucPwmRange;
//TIMER STARTS with Presscale Select =256
//PWM= WGM01=0; WGM00=1
TCCR0 = TCCR0_CLK_1024 | TCCR0_FAST_PWM |
TCCR0_OC0_MODE; // 0000 0111//Timer
Counter CTRL
//timer_enable_int(_BV(TOIE2)); !!
WAHRNUNG ÜBERSCHREIBT OFFENBAR ANDERE BITS im TIMSK
//TIMSK |= TOIE0;
SREG = sreg;
sei();
};
*/
// *************************************
void StartTickTimer(void)
// *************************************
{//Normal MODE OC2 Disconnect Prescale 1024
unsigned char sreg;
sreg = SREG; //loakaler Speicher
cli();
//16000000 / 256 / 1024 = 61,03515625 Hz
TCCR0 = TCCR0_CLK_1024; //frq 15625,
NORMAL MODE=NO OCR0
TIMSK |= TIMSK_TOIE0_FLAG;
SREG = sreg;
sei();
};
// ****************************************************************
uint32_t GetTickDifference(uint32_t u32Time)
// ****************************************************************
{
return (gu32_Ticks - u32Time);
};
#ifdef ADC_USED_ENABLED
//****************************************************************
uint16_t ADC_10Bit(uint8_t u8Chan) // 0..7
//****************************************************************
{
DDRA &= ~_BV(u8Chan); //Bit loeshcne von port
A,Chanel Bit Input
PORTA &= ~_BV(u8Chan); //Wegen Pullup abschalten
//Activate ADC with Prescaler 16 --> 16Mhz/128 = 125 khz
//ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) |_BV(ADPS0);
//MIT INTERNER REFERENCE
ADCSRA = ADCSRA_ADEN | ADCSRA_PRESCALER_128; //ADC
EIN UND PreScaler
ADMUX = ADMUX_REFS1 | ADMUX_REFS0 |
u8Chan; // ADMUX_REFS0 Select pin ADCx
using MUX
_delay_us(1);
ADCSRA |= ADCSRA_ADSC; //ADCSRA |=
_BV(ADSC); //Start conversion
while( ADCSRA & ADCSRA_ADSC )
//wait until _BV(ADSC)=0 =converstion completed
{
//wdt_reset();
};
return ADC; //ADCW; //get converted value
};
#endif
#ifdef ADC_USED_ENABLED
// *******************************************
float PotiSkalierung( uint16_t u16Poti )
//Normiert Poti mit Offset auf 0..1 von 0..1000
//liefert Fakot 0..1 zurück wenn nix zu tun, rweturn -1;
// *******************************************
{
if( (u16Poti > POTI_ZERO_OFFSET ) && (u16Poti
< POTI_UPPER_LIMIT) )
{
return ((u16Poti - POTI_ZERO_OFFSET) /
(float)POTI_RANGE_LIMIT);
};
return -1;
};
#endif
#ifdef UART_USE_ENABLED
// *******************************************************************
void UART_TXRX_Check(void)
/*
* Get received character from ringbuffer
* uart_getc() returns in the lower byte the received character and
* in the higher byte (bitmask) the last receive error
* UART_NO_DATA is returned when no data is available.
*/
// *******************************************************************
{
uint16_t uiRxUart = uart_getc();//!FETCH ALLWAYS BYTE FROM RX RINGBUFF
INTERRUPT!
if ( !(uiRxUart & UART_NO_DATA) ) //0x0100
{
//new data available from UART and check for Frame or Overrun error
#ifdef UART_ERRORMSG
if( uiRxUart & (UART_FRAME_ERROR |
UART_OVERRUN_ERROR | UART_BUFFER_OVERFLOW) )
{
ResetRxBuff();
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) );// !! Init UART
interface
// Framing Error detected, i.e no stop bit detected
Print_PStrCR( PSTR("UartErr") );
};
#endif
//NOW SELECT ACTION FROM ORDER
//Check CR
if(gpcRxPars < (gcaRxStr +
RX_STRMAX)) //ENDANSCHLAG ERREICHT ?
{
switch(
(unsigned char)uiRxUart )
{
case 13: // order!! from Terminal
{
CheckOrder(gcaRxStr);//gcaRxStr = accumulated str
ResetRxBuff();
break;
};
default: //Accumulate
{
// Accumulate String
only to gcaRxStr with uiAAA Parser
*gpcRxPars++ =
(unsigned char)(uiRxUart & 0x0FF);//Append rxByte
*gpcRxPars = 0; //ZERO carry
};
};//switch
}// if
(pcRxPars < (gcaRxStr + RXSTRMAX))
else // To much data Rx, than
clear simple all
{
//overflow of RX clears all
ResetRxBuff(); // Clear Rx Parspointer in
Buff an terminate RxStr with 0
};
};//ENDE DER RX EMPFANGSAUSWERTUNG
};
#endif
#ifdef UART_USE_ENABLED
// *******************************************************************
void ResetRxBuff(void)
// *******************************************************************
{
gpcRxPars = gcaRxStr; // Set parse pointer back;
*gpcRxPars = 0; //clear Rx
};
#endif
#ifdef UART_USE_ENABLED //MAKLEFILE ANPASSEN
// *******************************************************************
void PrintCR(void)
// *******************************************************************
{
uart_putc( ASC_CR );
};
// *******************************************************************
void PrintStrCR(const char* pStr)
// *******************************************************************
{
uart_puts(pStr);
PrintCR();
};
// *******************************************************************
void Print_PStrCR(PGM_P pmStr)
// *******************************************************************
{
uart_puts_p(pmStr);
PrintCR();
};
// **********************************************
void LongToNumStr(int32_t lVal)
// **********************************************
{
//sprintf(gcaNumStr,"%ld", lVal); //Ulong = %ld
ltoa(lVal, gcaNumStr, 10);
//sprintf(gcaNumStr,"%li", lVal); //Ulong = %ld
};
// *******************************************************************
void PrintLongCR(int32_t lVal)
// *******************************************************************
{
LongToNumStr(lVal); PrintStrCR(gcaNumStr);
};
// **********************************************
void FloatToNumStr(double fVal)
// *************
{ // Kommastellen 2 DTOSTR_PLUS_SIGN
DTOSTR_ALWAYS_SIGN
//dtostre(fVal,gcaNumStr,2, DTOSTR_UPPERCASE ); EXPO //
[-]d.ddd
dtostrf(fVal, 6, 3, gcaNumStr ); //[-]d.ddd
//sprintf(gcaNumStr,"%.1f", fVal);
};
// *******************************************************************
void PrintFloatCR(double fVal)
// *******************************************************************
{
FloatToNumStr(fVal); PrintStrCR(gcaNumStr);
};
#endif
// *******************************************************************
void CheckOrder(char *pcStrOrder) //von gcaRxStr
// *******************************************************************
{ //INPUT ERWARTET INDER FOR "BEFEHL,WERT" BSP: "SFR,1000"
//uint16_t uiCnt =0;
char * pStrTok; // für strtok_r
char * pucCh = &pcStrOrder[ strlen(pcStrOrder) ]; // Stelle
POINTER auf \0 Ende // kein unsigned char*
strcpy(gcaStr, pcStrOrder);
strcpy_P(gcaNumStr, MCA_DELIMITER_MSG); //HILFSWEISE gcaNumStr für ","
if( (pStrTok = strtok_r( pcStrOrder, gcaNumStr ,
&pucCh)) != NULL)//Trenne CMD, von ID, -"$$$1,CMD
{
strcpy(gsCmd.ucaCmd, pStrTok);
}
else
{
*gsCmd.ucaCmd = 0;
};
gsCmd.ucaCmd[ COMAMNDSIZEMAX ] = 0; //Sicherheitsterminierung
COMAMNDSIZEMAX=10
//strcpy(gcaStr, pcStrOrder);
gsCmd.fCmdVal_1 = gsCmd.fCmdVal_2 = 0;
if( (pStrTok = strtok_r( NULL, gcaNumStr, &pucCh)) !=
NULL)
{
gsCmd.fCmdVal_1 = atof(pStrTok);// Und
dann TO Float
};
if( (pStrTok = strtok_r( NULL, gcaNumStr, &pucCh)) !=
NULL)
{
gsCmd.fCmdVal_2 = atof(pStrTok);// Und
dann TO Float
};
//========================================================================================
/*
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("SPC") ) )
{
DDRC=0XFF; //OUTPUTs
PORTC = (uint8_t)gsCmd.fCmdVal_1;
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("RPC") ) )
{
DDRC=0X00; //INPUTs
PORTC = 0X00; // PullUp AUS
PrintLongCR( PINC );
};
*/
//------------------------------------------------
// --- DIES GILT DANN FÜR ALLE FOLGENDEN BEFEHLE
//------------------------------------------------
if( gsCmd.fCmdVal_2 > ADC_4_98_MAX_VOLTAGE ) //
Überspannungseingabe wird abgefangen
{
gsCmd.fCmdVal_2 = ADC_4_98_MAX_VOLTAGE;
};
//------------------------------------------------
// --- DIES GILT DANN FÜR ALLE FOLGENDEN BEFEHLE
//------------------------------------------------
if( gu8ModeSelect != SINUS_RESOLUTION_ON ) // evtl nicht freien
Speuicher freigeben
if( gpu8SineVal != NULL )
{
cli();
free( (uint8_t*)gpu8SineVal
);
gpu8SineVal = NULL;
sei();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("PING") ) )
{
Print_PStrCR( PSTR("PONG")
);
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("FOF") ) )
{
FRQ_Off();
gu8ModeSelect = 0XFF;
PORTC = 0;
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("FON") ) )
{
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("RT") )
) //RT,fFRQ,fVolt Rectangle
{
FRQ_Off();
gu8ModeSelect =
RECHTECK_ON;
if( gsCmd.fCmdVal_1 && (
(gsCmd.fCmdVal_1 * 2.0 ) < INTERRUPT_FRQ_LIMIT ) )
{
Set_Frq( gsCmd.fCmdVal_1 * 2);
//RaufRunter
};
if( gsCmd.fCmdVal_2 )
{
gu8PGAVolume = round( BIT_PRO_TTLVOLT() * gsCmd.fCmdVal_2 );
};
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("TA") )
) //TRIANGLE
{
FRQ_Off();
gu8ModeSelect = DREICKECK_ON;
gu16X_Resolution = DREIECK_X_RESOLUTON;
if( gsCmd.fCmdVal_1 &&
((gsCmd.fCmdVal_1 *gu16X_Resolution) <=
INTERRUPT_FRQ_LIMIT) )
{
Set_Frq( gsCmd.fCmdVal_1 *
gu16X_Resolution);
};
if( gsCmd.fCmdVal_2 )
{
gu8PGAVolume = round( BIT_PRO_TTLVOLT() * gsCmd.fCmdVal_2 );
};
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("SIR") )
) //SINE Resolution
{
//gu8SineVal[iNN] = round( 127.5 * (sin(
2*M_PI* iNN/256.0) + 1 ) );
uint16_t u16NN;
FRQ_Off();
gu8ModeSelect = SINUS_RESOLUTION_ON;
if( gpu8SineVal != NULL )
{
cli();
free( (uint8_t*)gpu8SineVal
);
gpu8SineVal = NULL;
sei();
};
if( gsCmd.fCmdVal_1 &&
(gsCmd.fCmdVal_1 <=
MAX_X_RESOUTION) )
{
gu16X_Resolution = gsCmd.fCmdVal_1;
}
else
{
gu16X_Resolution = SINUS_X_RESOLUTON;
};
if( gsCmd.fCmdVal_2 &&
(gsCmd.fCmdVal_2 <= ADC_4_98_MAX_VOLTAGE ))
{
gu8PGAVolume = round( BIT_PRO_TTLVOLT() * gsCmd.fCmdVal_2 );
}
else
{
gu8PGAVolume = ADC_4_98_MAX_VOLTAGE;
};
if( gpu8SineVal == NULL )
{
cli();
gpu8SineVal = malloc( gu16X_Resolution );
for(u16NN=0; u16NN < gu16X_Resolution; u16NN++) // Compute
SineTable
{
//gu8SineVal[iNN]
= round( (SINUS_X_RESOLUTON / 2.0 + 0.5) * (sin( 2*M_PI*
iNN/SINUS_X_RESOLUTON) + 1 ) );
*(gpu8SineVal +
u16NN) = round( (gu8PGAVolume / 2.0) *
(sin( 2*M_PI*
u16NN/gu16X_Resolution) + 1 ) );
};
sei();
};
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("SIN") )
) //5V TTL SINE si,1000,4.0
{
FRQ_Off();
gu8ModeSelect = SINUS_5V_AMPLIUDE;
gu16X_Resolution = SINUS_5V_X_RESOLUTON;
//gu8SineVal[iNN] = round( 127.5 * (sin(
2*M_PI* iNN/256.0) + 1 ) );
if( gsCmd.fCmdVal_1 &&
((gsCmd.fCmdVal_1 *gu16X_Resolution) <= INTERRUPT_FRQ_LIMIT) )
{
Set_Frq( gsCmd.fCmdVal_1 *
SINUS_5V_X_RESOLUTON );
};
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("STU") )
) //SawTooth Sägezahn
{
FRQ_Off();
gu8ModeSelect = SAEGEZAHN_UP;
gu16X_Resolution =
SAWTOOTH_X_RESOLUTON;
if( gsCmd.fCmdVal_1 &&
((gsCmd.fCmdVal_1 *gu16X_Resolution) <= INTERRUPT_FRQ_LIMIT) )
{
Set_Frq(
gsCmd.fCmdVal_1 *
(float)SAWTOOTH_X_RESOLUTON ); //256
}
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("STD") )
) //SawTooth Sägezahn
{
FRQ_Off();
gu8ModeSelect = SAEGEZAHN_DOWN;
gu16X_Resolution =
SAWTOOTH_X_RESOLUTON;
if( gsCmd.fCmdVal_1 &&
((gsCmd.fCmdVal_1 *gu16X_Resolution) <= INTERRUPT_FRQ_LIMIT) )
{
Set_Frq( gsCmd.fCmdVal_1 *
SAWTOOTH_X_RESOLUTON );
}
FRQ_On();
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("VOL") ) )
//Amplitude einstellen
{
gu8PGAVolume = round( BIT_PRO_TTLVOLT() *
gsCmd.fCmdVal_1 );
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("FRQ") ) )
//Freqeunz einstellen
{
if( gsCmd.fCmdVal_1 <= INTERRUPT_FRQ_LIMIT)
{
Set_Frq(
gsCmd.fCmdVal_1 );
};
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("PGA") ) )
//Amplitude einstellen
{
if( gsCmd.fCmdVal_1 < PGA_AUFLOESUNG )
{
gu8PGAVolume =
(uint8_t)gsCmd.fCmdVal_1;
};
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("RES") )
) //gu16X_Resolution einstellen
{
if( gsCmd.fCmdVal_1 <
MAX_X_RESOUTION )
{
gu16X_Resolution = (uint16_t)gsCmd.fCmdVal_1;
};
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GV") )
) //Get Val
{
PrintLongCR(gu16VolumePoti);
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GF") )
) //Get Val
{
PrintLongCR(gu16FrequenzPoti);
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GM") )
) //Get Val
{
PrintLongCR(gu16ModePoti);
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GIF") )
) //Get interrupt Frq
{
PrintFloatCR( gfInterruptFRQ );
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GPGA") )
) //Get PGA Val
{
PrintLongCR( gu8PGAVolume );
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GVO") )
) //Get interrupt Frq
{
PrintFloatCR( (gu8PGAVolume *
TTL_VOLTAGE)/(float)PGA_AUFLOESUNG );
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GMO") )
) //Get Mode Selcet
{
PrintLongCR( gu8ModeSelect );
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("GR") )
) //Get Mode Selcet
{
PrintLongCR( gu16X_Resolution );
};
if( !strcasecmp_P( gsCmd.ucaCmd, PSTR("XX") ) )
{
//PrintCR();
PrintLongCR( gu32_Ticks );
//PrintFloatCR( ((gu16X_Resolution -
POTI_ZERO_OFFSET) / (float)POTI_RANGE_LIMIT));
//PrintFloatCR( PotiSkalierung(
gu16X_Resolution ) );
};
#ifdef ENDORDER_CMD_ECHO_ENABLED
Print_PStrCR( PSTR("OK") );
#endif
};
#ifdef ADC_USED_ENABLED
// ****************************************************************
uint16_t ADC_StatistiKRead(uint8_t u8Channel, uint16_t u16LastRead)
// ****************************************************************
{ //Poti erst nach stärkerer Bewegung wieder aktivieren, dann jedoch
empfindlicher
static uint32_t u32_PotiActiveTimeTicks;
//T2 timeCounter, only NN_Counter for Keypressings
uint8_t u8NN;
int16_t u16Diff;
int32_t i32Sampel = 0;
//erst mal lesen howmuch
u16Diff = fabs( (i32Sampel = ADC_10Bit( u8Channel )) - u16LastRead) ;
//1*lesen
if( u16Diff > ADC_AKTIVATE_MOVEMENT_DIV ) // NIX TUN WEN NNIX
PASSIERT
{
u32_PotiActiveTimeTicks = gu32_Ticks;
//Merke dir Zeit für Timeout
gu8ProgMode_Flag &=
~PROGMODE_POTI_FREEZE_STATUS; // zeigt an, daß Potis jetzt aktiv
};
if( (u16Diff >
ADC_MINI_MOVEMENT_DIV) &&
!(gu8ProgMode_Flag &
PROGMODE_POTI_FREEZE_STATUS)
)
//#define ADC_AKTIVATE_MOVEMENT_DIV 15
{
//Jetzt genau messen, statistisch
geglättet.
i32Sampel = 0;
for( u8NN=0; u8NN <
ADC_SAMPLE_CNT; u8NN++ ) //#define
SAMPLE_CNT 10.0
{
i32Sampel
+= ADC_10Bit( u8Channel );
};
i32Sampel = round(i32Sampel /
ADC_SAMPLE_CNT);
gu8ProgMode_Flag |=
PROGMODE_POTI_MINIDIV_DETECT | PROGMODE_NEWVAL_DETECT;
u32_PotiActiveTimeTicks = gu32_Ticks;
//Merke dir Zeit für Timeout
}
else
{
gu8ProgMode_Flag &=
~PROGMODE_POTI_MINIDIV_DETECT; // Damit ungültigkeit festgestellt
werden kann
};
if( GetTickDifference( u32_PotiActiveTimeTicks ) >
PULS_4SEcOND_1024 )
{
gu8ProgMode_Flag &=
~PROGMODE_POTI_MINIDIV_DETECT;
gu8ProgMode_Flag |=
PROGMODE_POTI_FREEZE_STATUS;
};
#ifdef SHOW_ADC_READVAL_ON_LCD
lcd_gotoxy(0,1);
FloatToNumStr( fabs(i32Sampel - u16LastRead) );
lcd_puts( gcaNumStr );
if( !(gu8ProgMode_Flag & PROGMODE_POTI_FREEZE_STATUS) )
{
lcd_puts_p( PSTR(" Act")
);
}
else
{
lcd_puts_p(
PSTR("
") );
};
if( gu8ProgMode_Flag & PROGMODE_POTI_MINIDIV_DETECT )
{
lcd_puts_p( PSTR(" Div")
);
};
#endif
return i32Sampel;
}
#endif
// *********************************
void WarteMal(uint16_t u16WaitTicks)
// *********************************
{
uint32_t u32TimeCompare = gu32_Ticks;
while( GetTickDifference( u32TimeCompare ) < u16WaitTicks)//
4*/sec
{
wdt_reset(); //WATCHDOG!
UART_TXRX_Check(); //IMMER VORHANDEN !!
IN ALLEN LOOPS DIE ZEIT BRAUCHEN
};
};
// *******************************************************************
int main(void)
// *******************************************************************
{
//static uint8_t u8Cnt;
//static uint8_t u16PositionToggle;
static uint32_t u32LCD_UpdateTimeCompare;
static uint32_t u32UARTTimeCompare; //Um
nihct zu schnell UART ohne interrupt zu lesen.
float fScaleFactor;
uint16_t u16PotiReadVal;
uint16_t u16NN;
//INITS
cli();//The global interrupt flag is maintained in the I bit of the
status register (SREG).
//Wichtige Schritte.. so bald wie möglich
//INIT HARDWARE
//USing of PORTOUTS 1=OUT, 0=IN
DDRA = PORTA_DDRX_OUTMASK;
PORTA = PORTA_PRESET_PULLMASK;
DDRB = PORTB_DDRX_OUTMASK;
PORTB = PORTB_PRESET_PULLMASK;
DDRC = PORTC_DDRX_OUTMASK;
PORTC = PORTC_PRESET_PULLMASK;
DDRD = PORTD_DDRX_OUTMASK;
PORTD = PORTD_PRESET_PULLMASK;
wdt_enable( WDTO_500MS ); //WDTO_250MS WDTO_500MS WDTO_1S
WDTO_2S WatchDog ENABLE
wdt_reset();
//WATCHDOG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ResetRxBuff();
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) );
StartTickTimer(); //8 Bit Timer 0//Wegen
Interrupt später!
#ifdef USE_TOGGLE_FLAG
INIT_TESTBIT_REG();
CLR_TESTBIT();
#endif
Print_PStrCR( MCA_WELCOME1_MSG );
Print_PStrCR( MCA_WELCOME2_MSG );
uart_puts_p( MCA_PGA );
uart_puts_p( MCA_SPACE );
uart_puts_p( MCA_FREQUENZ );
uart_puts_p( MCA_SPACE );
Print_PStrCR( MCA_GENERATOR );
lcd_init( LCD_DISP_ON );
_delay_ms(1);
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts_p( MCA_WELCOME1_MSG );
lcd_gotoxy(0,1);
lcd_puts_p( MCA_WELCOME2_MSG );
WarteMal( PULS_2SEcOND_1024 );
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts_p( MCA_PGA );
lcd_puts_p( MCA_SPACE );
lcd_puts_p( MCA_FREQUENZ );
lcd_gotoxy(0,1);
lcd_puts_p( MCA_GENERATOR );
WarteMal( PULS_1SEcOND_1024 );
gu32_Ticks = 0;
u32UARTTimeCompare = 0;
u32LCD_UpdateTimeCompare = 0;
u32UARTTimeCompare = 0;
//gfInterruptFRQ = START_FREQUENZ;
//PORTC= gu8PGAVolume;
SET_SWITCH_DDRX();
SET_SWITCH_PULLX();
Set_Frq( START_FREQUENZ );//1000
FRQ_On();
gu8ProgMode_Flag |= PROGMODE_MODESWITCH_CHANGE_DETECT |
PROGMODE_POTI_FREEZE_STATUS;
// ************ MAIN LOOP FOR EVER *********************
// MCUCR |= MCUCR_ADC_NOISE_REDUCTION;
for (;;) /* loop forever */ //Aber schnell > 200.000
mal/Sekunde
{
sei();
wdt_reset(); //WATCHDOG!
#ifdef USE_TOGGLE_FLAG
ToggleTEST_BIT(1);
#endif
#ifdef MODE_SWITCH_PRESENT
if( !READ_SWITCH() )
{
if(
!(gu8ProgMode_Flag & PROGMODE_MANUEL) )
{ // Im Umschaltmoment
gu8ProgMode_Flag &=
~PROGMODE_POTI_FREEZE_STATUS;
gu16VolumePoti
=
ADC_StatistiKRead( POTI_VOLUME,
0 ); // alles neu einlesen
gu16FrequenzPoti
=
ADC_StatistiKRead( POTI_FREQUENZ,0 ); // alles neu einlesen
gu16ModePoti =
ADC_StatistiKRead( POTI_MODE, 0 ); //
alles neu
einlesen
gu8ProgMode_Flag
|=
PROGMODE_MODESWITCH_CHANGE_DETECT |
PROGMODE_POTI_MINIDIV_DETECT
|
PROGMODE_FREQUENZ_CHANGE_DETECT
|
PROGMODE_VOLUME_CHANGE_DETECT
|
PROGMODE_MODE_SELECT_CHANGE_DETECT |
PROGMODE_MANUEL;
};
// POTIS CHecken POTI CHecken POTI
CHecken POTI CHecken POTI CHecken POTI
CHecken
u16PotiReadVal = ADC_StatistiKRead(
POTI_VOLUME,
gu16VolumePoti ); // Lese erst das Poti
if(
gu8ProgMode_Flag & PROGMODE_POTI_MINIDIV_DETECT )
{
gu16VolumePoti = u16PotiReadVal;
//um für Ruhe zu sorgen erst hier zuweisen
gu8ProgMode_Flag |=
PROGMODE_VOLUME_CHANGE_DETECT;
};
#ifndef NURMODEPOTITESTEN
u16PotiReadVal = ADC_StatistiKRead(
POTI_FREQUENZ,
gu16FrequenzPoti ); // Erforsche ob Änderung des Wertes
if(
gu8ProgMode_Flag & PROGMODE_POTI_MINIDIV_DETECT )
{
gu16FrequenzPoti =
u16PotiReadVal; //um für Ruhe zu sorgen erst hier zuweisen
gu8ProgMode_Flag |=
PROGMODE_FREQUENZ_CHANGE_DETECT;
};
u16PotiReadVal = ADC_StatistiKRead(
POTI_MODE,
gu16ModePoti ); // Lese erst das Poti
if(
gu8ProgMode_Flag & PROGMODE_POTI_MINIDIV_DETECT )
{
gu16ModePoti = u16PotiReadVal;
//um für Ruhe zu sorgen erst hier zuweisen
gu8ProgMode_Flag |=
PROGMODE_MODE_SELECT_CHANGE_DETECT;
};
#endif
//------------------- NOT FREZZE -------------------------------
//
-------------------------------------------------------------------
if(
!(gu8ProgMode_Flag & PROGMODE_POTI_FREEZE_STATUS) )
{
// VOLUME SELECT * VOLUME SELECT * VOLUME SELECT * VOLUME SELECT *
VOLUME SELECT * VOLUME SELECT *
// VOLUME SELECT * VOLUME SELECT * VOLUME SELECT * VOLUME SELECT *
VOLUME SELECT * VOLUME SELECT *
// VOLUME SELECT * VOLUME SELECT * VOLUME SELECT * VOLUME SELECT *
VOLUME SELECT * VOLUME SELECT *
if(gu8ProgMode_Flag &
PROGMODE_VOLUME_CHANGE_DETECT)
{
gu8ProgMode_Flag &=
~PROGMODE_VOLUME_CHANGE_DETECT;
if(
(fScaleFactor = PotiSkalierung( gu16VolumePoti )) != -1 )
{
gu8PGAVolume = round(PGA_255RANGE *
fScaleFactor); //10To8Bit = 1024/4.0 = 256
};
switch(
gu8ModeSelect )
{
case SINUS_RESOLUTION_ON:
{
break;
}
case DREICKECK_ON
: //Dreieck
case
SAEGEZAHN_UP: //SAEGEZAHN_UP
case
SAEGEZAHN_DOWN:
//SAEGEZAHN_DOWN
{
FRQ_Off();
Set_Frq(
gfInterruptFRQ );
FRQ_On();
break;
};
};//switch
#ifdef SHOW_POTSVALS_ONCOM_ON
uart_puts_p(PSTR("Vol=") );
PrintFloatCR( gu8PGAVolume
);
#endif
};
// FREQUENZ SELECT * FREQUENZ SELECT * FREQUENZ SELECT * FREQUENZ
SELECT * FREQUENZ SELECT * FREQUENZ
// FREQUENZ SELECT * FREQUENZ SELECT * FREQUENZ SELECT * FREQUENZ
SELECT * FREQUENZ SELECT * FREQUENZ
// FREQUENZ SELECT * FREQUENZ SELECT * FREQUENZ SELECT * FREQUENZ
SELECT * FREQUENZ SELECT * FREQUENZ
if( gu8ProgMode_Flag &
PROGMODE_FREQUENZ_CHANGE_DETECT)
{
gu8ProgMode_Flag &=
~PROGMODE_FREQUENZ_CHANGE_DETECT;
if(
(fScaleFactor = PotiSkalierung( gu16FrequenzPoti )) != -1 )
{
FRQ_Off(); //pow(M_E, oder 1y= (
10^x-1)/9
// gfInterruptFRQ
=; // umm
irgendwie zwischen 0.3..bis 150KHz zu kommemn
Set_Frq( INTERRUPT_FRQ_LIMIT *
((pow(10,fScaleFactor) -1) / 9) );
FRQ_On();
};
};
// MODE SELECT * MODE SELECT * MODE SELECT * MODE SELECT * MODE SELECT
* MODE SELECT * MODE SELECT *
// MODE SELECT * MODE SELECT * MODE SELECT * MODE SELECT * MODE SELECT
* MODE SELECT * MODE SELECT *
//
MODE SELECT * MODE SELECT * MODE SELECT * MODE SELECT * MODE SELECT *
MODE SELECT * MODE SELECT *
if(gu8ProgMode_Flag &
PROGMODE_MODE_SELECT_CHANGE_DETECT)
{
gu8ProgMode_Flag &=
~PROGMODE_MODE_SELECT_CHANGE_DETECT;
if(
(fScaleFactor = PotiSkalierung( gu16ModePoti )) != -1 )
{
gu8ModeSelect = round(
POSSIBLE_MODES_CNT *
fScaleFactor );
//PrintLongCR( gu8ModeSelect );
};
if(
(gpu8SineVal == NULL) && (gu8ModeSelect ==
SINUS_RESOLUTION_ON)
)
{
cli();
gpu8SineVal = malloc( gu16X_Resolution );
for(u16NN=0; u16NN <
gu16X_Resolution; u16NN++)
// Compute SineTable
{
//gu8SineVal[iNN]
= round( (SINUS_X_RESOLUTON / 2.0 + 0.5) * (sin( 2*M_PI*
iNN/SINUS_X_RESOLUTON) + 1 ) );
*(gpu8SineVal + u16NN) = round(
(gu8PGAVolume / 2.0) * (sin( 2*M_PI* u16NN/SINUS_X_RESOLUTON) + 1 ) );
};
sei();
};
if(
(gpu8SineVal != NULL) && (gu8ModeSelect !=
SINUS_RESOLUTION_ON) )
{
cli();
free( (uint8_t*)gpu8SineVal
);
gpu8SineVal = NULL;
sei();
};
#ifdef SHOW_POTSVALS_ONCOM_ON
uart_puts_p( PSTR("Frq=") );
PrintFloatCR(
gfInterruptFRQ);
#endif
};
//gu8ProgMode_Flag & PROGMODE_FREQUENZ_CHANGE_DETECT
};
//!(gu8ProgMode_Flag &
PROGMODE_POTI_FREEZE_STATUS)
}
else
//readswitch MANUEL Modus
{
if(
gu8ProgMode_Flag & PROGMODE_MANUEL )
{
ADCSRA &= ~ADCSRA_ADEN; //ADC
Ausschalten
ADMUX = 0;
//REF OFF
gu8ProgMode_Flag &=
~PROGMODE_MANUEL; //ALSO PC-STEUERUNG
gu8ProgMode_Flag |=
PROGMODE_MODESWITCH_CHANGE_DETECT | PROGMODE_POTI_FREEZE_STATUS;
};
};
#endif
//readswitch
//
---------------------------------------------------------------------------
//
---------------------------------------------------------------------------
//
---------------------------------------------------------------------------
//
---------------------------------------------------------------------------
//** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD
//** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD
//** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD
// Hier die Modusänderung anzeigen, nach
Switchänderung.
if( gu8ProgMode_Flag &
PROGMODE_MODESWITCH_CHANGE_DETECT )
{
gu8ProgMode_Flag &=
~PROGMODE_MODESWITCH_CHANGE_DETECT;
lcd_clrscr();
lcd_puts_p( PSTR("MODE=") );
if(
gu8ProgMode_Flag & PROGMODE_MANUEL)
{
lcd_puts_p( PSTR("MANUEL") );
}
else
{
lcd_puts_p( PSTR("REMOTE") );
};
//Wartemal 2
Sekunden
WarteMal(PULS_2SEcOND_1024);
};
#ifdef LCD_NORMALAUSGABE_ENABLED
if(GetTickDifference(
u32LCD_UpdateTimeCompare ) > PULS_1SEcOND_1024 )
{
u32LCD_UpdateTimeCompare = gu32_Ticks;
lcd_clrscr();
lcd_gotoxy(0, 0);
lcd_puts_p( PSTR("Vol=") );
if(
gu8ModeSelect == SINUS_5V_AMPLIUDE )
{
FloatToNumStr( ADC_4_98_MAX_VOLTAGE );
}
else
{
FloatToNumStr( TTLVOLT_PRO_BIT() *
gu8PGAVolume );
};
lcd_puts(
gcaNumStr );
lcd_puts_p( PSTR("V ") );
switch(
gu8ModeSelect )
{
case SINUS_RESOLUTION_ON :
{
lcd_puts_p( PSTR("SiRes") );
break;
};
case SINUS_5V_AMPLIUDE :
{
lcd_puts_p( PSTR("Sine") );
break;
};
case
RECHTECK_ON
:
{
lcd_puts_p( PSTR("Rectang") );
break;
};
case DREICKECK_ON :
{
lcd_puts_p( PSTR("Triang") );
break;
};
case SAEGEZAHN_UP :
{
lcd_puts_p( PSTR("SawU") );
break;
};
case SAEGEZAHN_DOWN :
{
lcd_puts_p( PSTR("SawD") );
break;
};
#ifdef PULSE_MODE_IMPLEMENTED
case PULSE_ON :
{
lcd_puts_p( PSTR("Puls") );
break;
};
#endif
};
//switch
// -----------------------------------------------------------------
lcd_gotoxy(0, 1);
lcd_puts_p( PSTR("Frq=") );
switch(
gu8ModeSelect )
{
case
SINUS_RESOLUTION_ON: //SINE
{
FloatToNumStr( gfInterruptFRQ / gu16X_Resolution );
break;
};
case
SINUS_5V_AMPLIUDE: //SINE
{
FloatToNumStr(
gfInterruptFRQ / SINUS_5V_X_RESOLUTON );
break;
};
case RECHTECK_ON: //RECT
{
FloatToNumStr( gfInterruptFRQ / 2.0 );
break;
};
case DREICKECK_ON
: //Dreieck
case
SAEGEZAHN_UP:
case SAEGEZAHN_DOWN:
{
FloatToNumStr( gfInterruptFRQ / gu16X_Resolution );
break;
};
};//switch
lcd_puts( gcaNumStr
);
lcd_puts_p( PSTR("Hz") );
if(
!(gu8ProgMode_Flag & PROGMODE_POTI_FREEZE_STATUS) )
{
lcd_puts_p( PSTR(" Act") );
};
/*
lcd_puts_p( PSTR(" ") );
LongToNumStr( OCR1A );
lcd_puts(
gcaNumStr
);
lcd_gotoxy(0,1);
lcd_puts_p( PSTR("Tick=") );
LongToNumStr( gu32_Ticks );
lcd_puts(
gcaNumStr
);
*/
// ---------------------------------------
#ifdef
SHOW_POTIS_BYMINIDIV_ON_LCD
if( gu8ProgMode_Flag
& PROGMODE_NEWVAL_DETECT ) // Zeig eim Falle des
{
gu8ProgMode_Flag &= ~PROGMODE_NEWVAL_DETECT;
lcd_clrscr();
lcd_gotoxy(0,0);
LongToNumStr( gu16VolumePoti );
lcd_puts( gcaNumStr );
if( gu8ProgMode_Flag & PROGMODE_VOLUME_CHANGE_DETECT )
{
lcd_puts_p( PSTR("X") );
}
else
{
lcd_puts_p( PSTR("=") );
};
lcd_puts_p( PSTR(" ") );
LongToNumStr( gu16FrequenzPoti );
lcd_puts( gcaNumStr );
if( gu8ProgMode_Flag & PROGMODE_FREQUENZ_CHANGE_DETECT )
{
lcd_puts_p( PSTR("X") );
}
else
{
lcd_puts_p( PSTR("=") );
};
lcd_puts_p( PSTR(" ") );
LongToNumStr( gu16ModePoti );
lcd_puts( gcaNumStr );
if( gu8ProgMode_Flag & PROGMODE_MODE_SELECT_CHANGE_DETECT )
{
lcd_puts_p( PSTR("X") );
}
else
{
lcd_puts_p( PSTR("=") );
};
};
#endif
}; //LCD SECUNDEN
UPDATE
#endif //#ifdef LCD_NORMALAUSGABE_ENABLED
if( (GetTickDifference(
u32UARTTimeCompare ) > PULS_250MS_TICK_1024) &&
!(gu8ProgMode_Flag & PROGMODE_MANUEL)
)
//PULS_PER_SEcONDTick_1024) //PULS_250MS_TICK_1024)
{
u32UARTTimeCompare = gu32_Ticks;
#ifdef
UART_USE_ENABLED
UART_TXRX_Check(); //IMMER
VORNAHANDEN !! IN ALLEN LOOPS DIE ZEIT BRAUCHEN
#endif
};
}; //main loop Ende
};
// ******************* MAIN END
********************************************
/*
CODE Schnipsl
//uart_puts_p(PSTR("X"));
*/
main.h
#ifndef MAIN_HEADER //Prevents multiple includes
#define MAIN_HEADERf
//#define USE_TOGGLE_FLAG
#define TIMER_TICK_USED
#define UART_USE_ENABLED
#define ADC_USED_ENABLED
//#define EEPROM_USED
//#define TEXT_SERVICE_USE_ENABLED
//#define ENDORDER_CMD_ECHO_ENABLED
#define UART_ERRORMSG
#ifdef USE_TOGGLE_FLAG
#define
TESTBIT_DIRREG
DDRD
#define
TESTBIT_PORT
PORTD
#define TESTBIT_BIT
0x04 //3te
leitung
#define
TESTBIT_INVERT_BIT 0xFB
#define
INIT_TESTBIT_REG() (TESTBIT_DIRREG |=
TESTBIT_BIT);
#define
SET_TESTBIT() (TESTBIT_PORT |=
TESTBIT_BIT);
#define
CLR_TESTBIT() (TESTBIT_PORT &=
TESTBIT_INVERT_BIT);
extern void ToggleTEST_BIT(uint8_t
ucCnt);
#endif
#define STRMAX 64
#define NUMMAX 32
#define RX_STRMAX 64
#define COMAMNDSIZEMAX 64
#define DELIMITER
','
#define DELIMITERSTR ","
//TYPEN DEKLARATION
typedef struct
{
char ucaCmd[COMAMNDSIZEMAX +1];
uint8_t ucCmdID;
float fCmdVal_1;
float fCmdVal_2;
//uint8_t ucCmdID;
}COMMAND_TYPE;
// Hardwareassignment
//F_CPU in makefile !!!
#define UART_BAUD_RATE
9600 /* 9600 baud */
//#define UART_BAUD_RATE 19200
//#define UART_BAUD_RATE 57600
/* FÜR Timer /256
#define PULS_PER_10TEL_SEc 25
#define PULS_PER_SEcONDTick 244
#define PULS_500MS_Tick
122
#define PULS_250MS_TICK
61
#define PULS_100MS_TICK
25
#define PULS_50MS_TICK
13
#define PULS_13MS_TICK
3
#define PULS_8MS_TICK
2
*/
//FÜR Timer /1024
//16000000 / 256 / 1024 = 61,03515625
#define PULS_5SEcOND_1024
305
#define PULS_4SEcOND_1024
244
#define PULS_2SEcOND_1024
122
#define PULS_1SEcOND_1024
61
#define PULS_500MS_Tick_1024 30
#define PULS_250MS_TICK_1024 15
#define PULS_100MS_TICK_1024 6
#define SYSCLK_256 (SYSCLK / 256) //
= 62500 //z.B.Timer2 Überlauf / 256 / Teilerfaktor
#define DISABLE_ALL_PULLUP_MAC (SFIOR |=
_BV(PUD));
#define ENABLE_ALLUP_SCL_MAC (SFIOR
&= ~(_BV(PUD)));
//========================================================================
//TIMERS
//TIMER2 = is 61 miliseconds Timer ~approx.
// 16MhZ / 1024 / 256 = 61,03515625 Hz
// T= 1/f = 0.016384 ms / Interrupt
//TIMER
#define TIMSK_TOIE0_FLAG 0x01
#define TIMSK_OCIE0_FLAG 0x02
#define TIMSK_TOIE1_FLAG 0x04
#define TIMSK_OCIE1B_FLAG 0x08
#define TIMSK_OCIE1A_FLAG 0x10
#define TIMSK_TICIE1_FLAG 0x20
#define TIMSK_TOIE2_FLAG
0x40 //#define TOIE2
6 (1 << TOIE2)
#define TIMSK_OCIE2_FLAG 0x80
#define TIMSK_T0_CLR_ALL_MASK 0b11111100
#define TIMSK_T1_CLR_ALL_MASK 0b11000011
#define TIMSK_T2_CLR_ALL_MASK 0b00111111
#define TIFR_TOV0_TIMER_OVERFLOW_FLAG 0x01
#define TIFR_OCF0_OUT_PCOMPARE_FLAG
0x02
#define TIFR_TOV1_TIMER_OVERFLOW_FLAG 0x04
#define TIFR_OCF1A_OUTP_COMPARE_A_FLAG
0x10
#define TIFR_OCF1B_OUTP_COMPARE_B_FLAG
0x08
#define TIFR_TOV2_TIMER_OVERFLOW_FLAG 0x40
#define TIFR_OCF2_OUTP_COMPARE_FLAG
0x80
//DELAY
//#define
TCCR2_CLK_64
0x04 //675 =
0,0014814814814814814814814814814815 mS Interrrupt
// 1 TICK = 1.4814814814814814814814814814815 ms
//NUR UNGEFÄHR
//BERECHUNG Xtime(ms) / 1.48....
#define TIMEOUT_1_5MS 1
#define TIMEOUT_2_9MS 2
#define TIMEOUT_4_4MS 3
#define TIMEOUT_10_3MS 7
#define TIMEOUT_100_7MS 68
#define TIMEOUT_500_7MS 338
#define TIMEOUT_1S
675
//!! uint16_t
#define TIMEOUT_5S
3375
//!! uint16_t
//REGISTER
#define TCCR0_FAST_PWM
0x48 //Mode 3
#define TCCR0_OC0_MODE
0x20 //Clear ON compare Match
#define TCCR0_OC0_DISCONNECT_MODE 0x00
#define TCCR0_CLK_STOP
0x00
#define TCCR0_CLK_0
0x01
#define TCCR0_CLK_8
0x02
#define TCCR0_CLK_64
0x03
#define TCCR0_CLK_256
0x04
#define TCCR0_CLK_1024
0x05
#define TCCR0_EXT_CLK_FALL_T0
0x06
#define TCCR0_EXT_CLK_RISE_T0
0x07
#define TCCR2_WGM_NORMAL
0x00
#define TCCR2_OC0_MODE
0x20 //Clear ON compare Match
#define TCCR2_CTC_MODE
0x08
//0000 1000
#define TCCR2_COM_NORMALPORT 0x00
#define TCCR2_CLK_STOP
0x00
#define TCCR2_FAST_PWM
0x48 //Mode 3
#define TCCR2_CS_BIST
0x0x //Mode 3
#define TCCR2_CLK_1024
0x07
#define TCCR2_CLK_256
0x06
#define TCCR2_CLK_128 0x05
#define TCCR2_CLK_64
0x04 //
#define TCCR2_CLK_32 0x03
#define TCCR2_CLK_8
0x02
// 1/F =
#define TCCR2_CLK_0
0x01
#define TCCR2_CLK_STOP
0x00
//TIMER2 WIRD BERECHNET /z.B:OverFLow SYSCLK / 256 /
TCCR2_CLK_64 = OVL/Sec
// 1/OVLS = 1/ =
//----->
//#define
TCCR1B_CLOCKSEL_CTC1
0x08 //Clear Timer/Counter on
Compare Match
Timer/Counter 1
#define TCCR1B_CLOCKSEL_STOP
0x00
//Clock Select Bits
#define
TCCR1B_CTC_MODE
0x08
//Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1
0x01
//Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_8
0x02
//Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_64
0x03 //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_256
0x04 //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1024
0x05 //Clock Select Bits
//BEI 16 MHz Quarz = F_CPU / Teiler
// QUARZ/DIVIDE = FREQUENZ
#define TIMER_DIVIDE_FRQ_0
((float)F_CPU) // 16000000UL
#define
TIMER_DIVIDE_FRQ_8
((float)F_CPU /
8) //2000000UL
#define TIMER_DIVIDE_FRQ_64 ((float)F_CPU
/ 64) //250000UL
#define TIMER_DIVIDE_FRQ_256
((float)F_CPU / 256) //62500U
#define TIMER_DIVIDE_FRQ_1024
((float)F_CPU / 1024) //15625U
#define MAXIMAL_FRQ ((float)F_CPU / 64)
#define MINIMAL_FRQ (F_CPU / 1024/ 0xFFFF
* 1.0) // 0.2385 //0,23842221713588158999008163576715 0,2384
//INTERUPT CTRL REG //NICHT mit MCUCSR verwechseln !
#define MCUCR_LOWLEVEL_INT0
0x00
#define MCUCR_ANYCHANGE_INT0
0x01 //=_BV(ISC01)
#define MCUCR_FALLING_EDGE_INT0
0x02
#define MCUCR_RISING_EDGE_INT0 0x03
#define MCUCR_LOWLEVEL_INT1
0x00
#define MCUCR_ANYCHANGE_INT1
0x04 //=_BV(ISC10)
#define MCUCR_FALLING_EDGE_INT1
0x08
#define MCUCR_RISING_EDGE_INT1 0x0C
#define MCUCR_ADC_NOISE_REDUCTION
0x10 //
_BV(SM0) //SLEEP MODE
#define GATE_ANYCHANGE_INT1_MODE_MAC
(MCUCR |= MCUCR_ANYCHANGE_INT1)
//Global Interrrupt CTRL REG
#define GICR_INT0_ON_MAC (GICR |=
_BV(INT0)) //_BV(INT0)
#define GICR_INT0_OFF_MAC (GICR
&= ~(_BV(INT0)))
#define GICR_INT1_ON_MAC (GICR |=
_BV(INT1))
#define GICR_INT1_OFF_MAC (GICR
&= ~(_BV(INT1)))
#define GICR_INT_0u1_OFF_MAC (GICR
&= 0x3F) //SIEHE DATENBLATT
#define RCO_B_INT_ON_MAC GICR_INT0_ON_MAC
#define RCO_B_INT_OFF_MAC
GICR_INT0_OFF_MAC
#define GATE_INT1_ON_MAC GICR_INT1_ON_MAC
#define GATE_INT1_OFF_MAC
GICR_INT1_OFF_MAC
#define OVERFLOW_CNT_ON_INT0_MAC
RCO_B_INT_ON_MAC
#define OVERFLOW_CNT_OFF_INT0_MAC
RCO_B_INT_OFF_MAC
#define GATE_ALL_EVENT_ON_INT1_MAC
GATE_INT1_ON_MAC
#define GATE_ALL_EVENT_OFF_INT1_MAC
GATE_INT1_OFF_MAC
//GIFR I_FLAG
#define GIFR_INTF0_SET_MAC (GIFR |=
_BV(INTF0)) //_BV(INT0)
#define GIFR_INTF0_CLR_MAC (GIFR
&= ~(_BV(INTF0)))
#define GIFR_INTF1_CLR_MAC (GIFR |=
_BV(INTF1))
#define GIFR_INTF1_SET_MAC (GIFR
&= ~(_BV(INTF1)))
#define GIFR_INTF_0u1_CLR_MAC (GIFR
&= 0x3F) //Siehe Datenblatt = letzten beiden Bits
//PORTB
#define
MOSI_I
3//BIT3
#define
MISO_0
4//BIT4
#define
SCK_I
5//BIT5
//#define
TCCR1B_CLOCKSEL_CTC1
0x08 //Clear Timer/Counter on
Compare Match
Timer/Counter 1
#define TCCR1B_CLOCKSEL_STOP
0x00
//Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1
0x01
//Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_8
0x02
//Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_64
0x03 //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_256
0x04 //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1024
0x05 //Clock Select Bits
//ADC //AT8
#define ADMUX_MUX0 0
#define ADMUX_MUX1 1
#define ADMUX_MUX2 2
#define ADMUX_MUX3 3
#define ADMUX_MUX4 4
#define ADMUX_MUX5 5
#define ADMUX_MUX_1_23V 0xE0
#define ADMUX_MUX_GND 0xF0
#define ADMUX_ADLAR 0x20
#define ADMUX_REFS0 0x40
#define ADMUX_REFS1 0x80
#define ADC_MUX_MASK 0x01F
#define ADCSRA_ADPS0 0x01
#define ADCSRA_ADPS1 0x02
#define ADCSRA_ADPS2 0x04
#define ADCSRA_ADIE 0x08
#define ADCSRA_ADIF
0x10 //INTERRRUPT FLAG
#define ADCSRA_ADATE
0x20 //AUTO TRIGGER ENABLE
#define ADCSRA_ADSC
0x40 //START //while (ADCSRA
& _BV(ADSC) )
#define ADCSRA_ADEN
0x80 //Enable
//PRESCALER
#define ADCSRA_PRESCALER_2 0x01
#define ADCSRA_PRESCALER_4 0x02
#define ADCSRA_PRESCALER_8 0x03
#define ADCSRA_PRESCALER_16 0x04
#define ADCSRA_PRESCALER_32 0x05
#define ADCSRA_PRESCALER_64 0x06
#define ADCSRA_PRESCALER_128
0x07
//WERT IN ADCW
//PORT_ASSIGMNEMTS
#define WDTO_2S 7 //WatchDog
//SOFTWARE USED DEFINES
#define ASC_CR 13
#define ASC_LF 10
#define ASC_DELIMITER ','
//CHECK PUD = PULLUPDISSABLE in SFIOR
//PORTA //1=OUT 6BIT
//1=OUT
#define PORTA_DDRX_OUTMASK
0X00 //3
und 4 auf INPUT
#define PORTA_PRESET_PULLMASK
0x08 //Ohne Pullup SCHALTER
//CHECK PUD = PULLUPDISSABLE in SFIOR
//PORT B //1=OUT 6BIT
//1=OUT
#define PORTB_DDRX_OUTMASK
0X00
#define PORTB_PRESET_PULLMASK
0X00 //Ohne
Pullup
//PORT C TWI //1=OUT 0 =
IN 6BIT
//STARTWERTE
#define PORTC_DDRX_OUTMASK
0xFF
#define PORTC_PRESET_PULLMASK
0X00 //Ohne Pullup
//PORT D //1=OUT 8 BIT
//TX/RX & zusatzhardware
#define PORTD_DDRX_OUTMASK
_BV( PD1 )
#define PORTD_PRESET_PULLMASK
0b00000000 //Ohne Pullup
#define RX_BIT
PD0 //0
#define TX_BIT
PD1 //1
// HIER PROJEKTSPEZIFISCHES
//LCD
#define LCD_BASEMSG__FLAG 0x80
//static volatile uint8_t gu8LCD_FLAG;
//Kurvensyntese
//gu8SineVal[iNN] = Round( 127.5 * (sin( 2*M_PI* iNN/256.0) + 1 ) );
#define SINUS_X_RESOLUTON
256
#define SINUS_5V_X_RESOLUTON 256 //
Starrer Wert weil Arrayfeld
#define DREIECK_X_RESOLUTON 256
#define SAWTOOTH_X_RESOLUTON 256
#define MAX_X_RESOUTION
401
#define INTERRUPT_FRQ_LIMIT 150001.0 //
Somit sind 75000 RT möglich
#define START_FREQUENZ 1000.0
//PGA Volume PRESET
#define START_PGA_VOLUME
51 //PRESET
#define TTL_VOLUME_ON 0x255
//PGA
#define TTL_VOLTAGE
( 5.0 )
#define ADC_4_98_MAX_VOLTAGE ( 4.98046875
) // 5V/256 * 255
#define PGA_AUFLOESUNG
( 256 )
#define PGA_255RANGE
( 255 )
#define TTLVOLT_PRO_BIT() (TTL_VOLTAGE /
PGA_AUFLOESUNG) // VOLT/BIT
#define BIT_PRO_TTLVOLT() (PGA_AUFLOESUNG
/ TTL_VOLTAGE) // BIT/VOLT
#define SINUS_RESOLUTION_ON
0 //2.er
#define SINUS_5V_AMPLIUDE
1 //2.er
#define RECHTECK_ON
2 //1.er //Start Preset
#define DREICKECK_ON
3 //3.er
#define SAEGEZAHN_UP
4 //4.er
#define SAEGEZAHN_DOWN
5 //5.er
#define PULSE_ON
6 //6.er
//gu8ModeSelect
#define POSSIBLE_MODES_CNT 5
//PROGRAMM MODUS
#define
PROGMODE_MANUEL
0x01
#define PROGMODE_POTI_FREEZE_STATUS
0x02
#define PROGMODE_POTI_MINIDIV_DETECT
0x04
#define PROGMODE_MODESWITCH_CHANGE_DETECT
0x08
#define
PROGMODE_MODE_SELECT_CHANGE_DETECT 0x10
#define PROGMODE_VOLUME_CHANGE_DETECT
0x20
#define PROGMODE_FREQUENZ_CHANGE_DETECT
0x40
#define
PROGMODE_NEWVAL_DETECT
0x80 //
allgemeine ereignisanzeige
//#define
PROGMODE_POTI_ACTIVE_DIFF_DETECT 0x80
//gu8PRogMode_Flag;
//ADC SECTION, READ MANUAL PAGE 205
// 8 Channel. ADC1, ADC0 ansd ADC3, ADC2 are PGAs 1*, 10*,200*
#define INTERNAL_VOLTAGE_REFERENCE
2.56 //V
#define ADCRESOLUTION
1024U //0..1023
#define
ADC_SAMPLE_CNT
2//3
//Statistische Reads mit
Durchschnittsbildung
#define
ADC_MINI_MOVEMENT_DIV
2 //Erst
diese Änderung akzepieren
( kein Poitflattern dadurch
#define ADC_AKTIVATE_MOVEMENT_DIV 15 //
Diese Wertaenderung startet Potijustage
#define POTI_RANGE_LIMIT 1000U
#define POTI_ZERO_OFFSET 11 //Ab diesem
Wert wird Wert als 0 definiert
#define POTI_UPPER_LIMIT 1012 //
ADCRESOLUTION - POTI_ZERO_OFFSET
#define POTI_VOLUME
2
#define POTI_FREQUENZ
1 //Reihenfolge rein zufällig
#define POTI_MODE
0
#define REMOTE_SWITCH 3
#define SWITCH_PORT_IN PINA
#define SWICHTPORT_OUT PORTA
#define DDRXSWICHTPORT DDRA
#define
SWITCH_PIN
0x08
//( Als HExausdruck von REMOTE_SWITCH )
#define SWITCH_PIN_INV
0xF7 //( Als HExausdruck )
#define SET_SWITCH_DDRX() (DDRXSWICHTPORT
&= SWITCH_PIN_INV) //SWITCH AUF INPUT=0
#define SET_SWITCH_PULLX()
(SWICHTPORT_OUT |= SWITCH_PIN) //SWITCH AUF INPUT=0
#define READ_SWITCH() (SWITCH_PORT_IN
& SWITCH_PIN) //READ SWITCH => !=0
// ** Programmcode Steuerung **
#define MODE_SWITCH_PRESENT
#define LCD_NORMALAUSGABE_ENABLED
//#define SHOW_POTIS_BYMINIDIV_ON_LCD // TESTAUSGABE der Potifunktion =
oder !=
//Erweiterungen
#define PULSE_MODE_IMPLEMENTED
//TESTAUSGABEN
//#define SHOW_POTSVALS_ONCOM_ON
//#define SHOW_ADC_READVAL_ON_LCD
//#define NURMODEPOTITESTEN
//1024 / 5 = 204.8
#endif //MAIN_HEADER