Christof Ermer
zuletzt bearbeitet: 09.10.2024
Zurück
Titel: Drehfilter Lab 5005



Youtube; https://youtu.be/IdbiRn07Occ
Video: Filter_Dreher_09.10.2024.mp4
#Mnemonische_Kommandos
Schaltung des Mikrocontrollers: StepMot_V4_CE.pdf
Das binäre HEX File, Firmware des ATMega16 Controllers: main.hex
WINAVR Drehfilter C_Projekt: AVR_DrehFilter_08.10.24_1.zip
#Quell_ANSI_C_Files_Main.c_Main.h
LabView_Software: ../SOFTWAREs/LabView/Drehfilter_08.10.24.zip
Ansicht mit Kontrollerdeckel - 12 Volt ~1..2 A   erforderlich







Ansicht mit Mikrocontroller - 12 Volt ~1..2 A   erforderlich



Gabel Lichtschranke






















Mnemonische Kommandos

Mnemonische Befehle für Schrittmotorsteuerung mit Atmel ATMega16
BAUD = 9600, 8 bit, 1 Stopbit . PUTTY ist eine gutes Terminalprogramm für Tests
Befehle sind dann jeweils für den entsprechenden Modus aktiv
BEFEHL[,][WERT]               Bsp:   mopd,100,1
{notwendig}oder []=optional. (default).  0=Voreingestellt bei Weglassung von [WERT]Mnemonic    Bedeutung    ?-> =Frage --> Anwort erwartet
??     Menü, Befehlsliste   Ausgabe für Putty Terminal Programm
ping    Reponse PONG - DrehFilter
VER    Version mit Datum
SCI      = Scan Index --> Startet Indexsuche
?->  GIDX     -->  Get index get gsStatus.IndexOK_Flag
GOTOD,{grad 0.360}    Go to Degree
TAR_OK?       gsStatus.TargetSMPOS_Erreicht_F    1= Am Ziel angekommen
?-> BWGP    gfBigWeel_GradPos
?-> BWTP    gfBigWeel_Target_GradPos
IDXO    SET IndexOffset
SIX     Set Position to Indexpoint
?-> LICHTSCHRANKE  -->( Aktive = high = 1 ) '
?-> IDXCHANGE      Für Putty : Lese Optokopllerfunktion
TRX,{0..1}     Debugtraffic für PUTTY   0=0ff  1= on
CR_CRLF{0..1}    0= CR ONLY, 1 = CRLF
SMON[,1..nnn]    Motor ON [,mit Set Frequenz] =Pulse/Sekunde   
Bsp: 1.Aufruf  „SMON,123“  = 123 Clocks/Sek     PREDEF_STEPFREQUENZ 100
MOPD,{1..nn},[0/1]    Motor N Pulse mit Direction Motor On [, Pulszahl]
SMOFF    Motor OFF und Freigabe
SMSTOP    Motor Stop, !!nach 1 Sek. Motorfreigabe
SFR,{nnn}    Sfr,100  Set Frequenz = Steps/Sekunde
SDIR,[(0)..1]    Set Direction  1=links 0=rechts Default ( unidirection )
HALF    Halbschritt Modus  ( STANDARD )
FULL    Vollschritt Modus       
sdp    SEND Degree Position
spo    Send Position
SIT,[1..nn]    Set Set Index Timeout ~200 Seconds
sci    Scan Index automatic    MCA_SCI_CMD
SPR       Set Steps per Rotation  Schriottmotor -->100
SETO     Set ENBALE TIMEOUT if Stop
SIT    SET Scan_Index_Timeout
SIENA,{1,0}     ScanIDX_Start_EnaF
?--> COF    gsStMPar.iIndexOffset
?--> COFBIN    gsStMPar.u8StepMConditionFlag mit Binärausgabe für Putty
?--> POF    gsStMPar.u8SM_PostionFlag
?--> POFBIN    gsStMPar.u8SM_PostionFlag mit Binärausgabe für Putty
?-> BWFR    gfBigWeel_FullRotCnt
?-> SPD        gfStepsPerDegree
?-> DPS        gfDegreePerStep
?-> GPOS    glSM_RotPosition
?-> CPOSID,{SMpos)    CalcPostionInDegree
?-> CDISMPOS,{grad}     CalcDegreeIn_SMPos
?-> FLAGS    Zeigt eine Liste von Flags ( use Putty )
?-> POS       Zeigt eine Liste von Flags ( use Putty )
?-> TT    TickTimer
    Print_PStr( PSTR("SCI,GIDX,GOTOD,TAR_OK?SIX,TRX,GIDX,IDXO") );    Print_PStr( PSTR("SMON,MOPD,SMSTOP,SMSOFF,SFR,SDIR") );    Print_PStr( PSTR("HALF,FULL,SPR,SIENA,SIX,SIDXFRQ,SETO,SIT") );    Print_PStr( PSTR("SPO,SDP,GOD,COF,COFBIN,POF,POFBIN,POS,SIENA") );    Print_PStr( PSTR("BWFR,SPD,DPS,GPOS,BWGP,BWTP,CPOSID,CDISMPOS") );    Print_PStr( PSTR("LICHTSCHRANKE,IDXCHANGE,Flags,Ping,VER,CR_CRLF,TRX,TT") );   




QUELLFILES


MAIN.C

//------------------------------------------------------------------------------
// Programmed by Christof Ermer
// Regensburg 01.2006 und ab 27.09.2024
//------------------------------------------------------------------------------

///SYSINFO
#define VERSION        "Drehfilter mit SonderKeyfunktion ( Not STANDARD)"
#define DATUM        "08.10.2024"     //"15.3.2007"
#define    INSTITUT    "UNI-Regensburg"
#define AUTOR        "Christof Ermer"

// TEST DEVCPP
//B:\Drive\NASDrive\DEV_Cpp_NAS\DrehfilterTest_DEVCPP__LWC_07.10.24_1


// SCHALTER
//IN MAIN.H

/*HiSTORY
Rückbau der LED INdexxer,
'Einbau eines Gabelkopplers am PC0, HIGH = Gesachlossen

#define AVR_ATmega16
FUSE  H=xBF L=x89   09.24
SET COPT IN  FUSE BITS TO ENABLE XTAL

BAUDRATE = 9600,8,N,1
ICTRL = PD6
Neuer Indexer, Gabelkkoppler Wird high an PINC.0  09.24

NEUE AVRDUDE Version in make
# Program the device. 
program: $(TARGET).hex $(TARGET).eep
#    $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
    "C:\AVRDUDE\avrdude.exe" $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)


Strom nicht sofort auf Low geschaltet, sondern nach DelayTime
The maximal possible delay is 262.14 ms / F_CPU in MHz. = 16,39625

ÄNDERUNG ENABLE IMMER AN !!!

PIN 33 PA7=ADC7 wird Enable ICtrl über BUZ 11 wird ein Widerstand 2*4R7 5W auf GND Kurzgesloosen
% Modulo geht nur mit 2 Hoch N Reihen als Modulo..

// **** Hystorie Hystorie Hystorie Hystorie Hystorie Hystorie ****************
 commado MCA_CMD zugefügt

FLOAT TIMER UMGESTELLT
Änderung der Bezüge durch float Grad in Steps, Bezogen auf Motor mode und Steps/Rotation
STEPMotor ist an PORT A vorgesehen..

// IF ( ? : );
*/

#include <ctype.h>
#include <inttypes.h>
#include <avr\io.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <avr\interrupt.h>
#include <avr\pgmspace.h>
#include <avr\eeprom.h>   
#include <util\delay.h>
#include <avr\wdt.h>

#include "main.h"        //with Hardware assigns
#include "uart.h"
#include "lcd.h"


// GLOBALE VARIABLEN
volatile STATUS_TYPE gsStatus; //gsStatus.TickEvent
volatile uint32_t gulT2_Ticks; //  T2 timeCounter, only NN_Counter for Keypressingsuint32_t gu32TimeLatch; //Speed watch
volatile uint32_t gu32TimeLatch; //Speed watch

char gcaRxStr[RX_STRMAX + 1]; //+1 for the 0
char gcaNumStr[NUMMAX + 1]; //+1 for the 0
char gcaStr[STRMAX + 1]; //+1 for the 0

COMMAND_TYPE gsCmd;
char* gpcRxPars;

//STEP MOTOR RELATED
volatile STEPMPARTYPE gsStMPar;        //SPEICHERT DIE PARAMETER //deklarion in Main.H
volatile uint8_t gu8StepBitMusterPars; //+1 or -1 for the Bitpatternselect
volatile uint8_t gu8ModePatternModulo; // Modulo selector (HALF/FULLSTEP..)
PGM_P gpmpaStepPattern;  // PGM_P PGM_VOID_P
volatile uint32_t gulMovedSteps;    //compare with MovedSteps //Wieviel hat sich der Motor gedreht..   
uint32_t gulSM_ToRunCnt;    //PULSE die der Motor laufen soll   

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
long glSM_RotPosition;    //Single_Rotation-Haupztähler der Position! MUSS NEGATIV WERDEN KÖNNEN
volatile float gfBigWeel_FullRotCnt;    //200*2* (40/12) = 666.66666
volatile float gfStepsPerDegree;// WeelFullRotationsteps= 666.666/360 = 1,851851667.............
volatile float gfDegreePerStep;// 360/666.666 WeelFullRotationsteps / = 0.54000054
volatile float gfBigWeel_GradPos;   
volatile float gfBigWeel_Target_GradPos ;   
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


const char MCA_CRSTR[] PROGMEM = {13,0};
const char MCA_CRLFSTR[] PROGMEM = {13,10,0};
const char MCA_DELIMTERSTR[] PROGMEM = { ',',0 };

//MESSAGES
const char MCA_DELIMITER_MSG[] PROGMEM    = ",";
const char MCA_DPOINT_MSG[] PROGMEM = ":";
const char MCA_SPACE_MSG[] PROGMEM    = " ";
const char MCA_ISTGLEICH_MSG[] PROGMEM    = "=";

//const char MCA_EVENT_MSG[] PROGMEM    = "Event";
const char MCA_OK_MSG[] PROGMEM        = "OK";   
const char MCA_MOTOR_MSG[] PROGMEM    = "Motor";   
const char MCA_POS_MSG[] PROGMEM    = "Pos";


//FULLSTEP ENABLE_B ENABLE_A BITS 3..0
//0011 1010 = 0x3A
//0011 1001 = 0x39
//0011 0101 = 0x35
//0011 0110 = 0x36
//const MCA_FULLSTEPS[] PROGMEM = {0xBA,0xB9,0xB5,0xB6};    //CONST ARRAY
const char MCA_FULLSTEPS[] PROGMEM = {0x3A,0x39,0x35,0x36};    //CONST ARRAY
//HALFSTEP ENABLE_B ENABLE_A BITS 3..0
//0011 1010 = 0x3A
//0010 1000 = 0x28
//0011 1001 = 0x39
//0001 0001 = 0x11
//0011 0101 = 0x35
//0010 0100 = 0x24
//0011 0110 = 0x36
//0001 0010 = 0x12
const char MCA_HALFSTEPS[] PROGMEM = {0x3A,0x28,0x39,0x11,0x35,0x24,0x36,0x12};    //CONST ARRAY


// ******************
ISR(TIMER2_COMP_vect)
// ******************
{
if( !( (++gulT2_Ticks) % ONE_SECOND_TICKS) )
    {
    gsStatus.TickEvent_F = 1; // Sec Event
    }
//( READ_SENS_INDEX_ACTIVE_ISHIGH() ? (gsStatus.OptoKopplerActive_F = 1) : (gsStatus.OptoKopplerActive_F = 0) );
};

// ****************************************************************
ISR(TIMER1_COMPA_vect)// signal handler
//#define SIG_OUTPUT_COMPARE1A    _VECTOR(6)
// ******************
{
//static uint8_t ucBitpattern;
//I_SREG automtaic clear by Interrupt and Enabled by RETI   
//cli();f
if( gsStMPar.u8StepMConditionFlag & STEPM_RUN_FLAG )
    {
    //Target ->meint Target in einer Rotation
    if( (gsStMPar.u8SM_PostionFlag & POSITION_STOP_ON_TARGET_MODE_FLAG)// &&
    //Ziel so nahe wie möglich erreicht ? Also kleiner 1 Step...==40/12=3.3333
    )
        {
        gsStMPar.u8SM_PostionFlag &= ~POSITION_STOP_ON_TARGET_MODE_FLAG; //SCHON In  StepMotorStop();
        StepMotorStop();       
        gsStMPar.u8SM_PostionFlag |= POSITION_STOP_ON_TARGET_OK; //Meldung für main schon in motorstop
        return;       
        };

    if( gsStMPar.u8StepMConditionFlag & STEPM_DIRECTION_FLAG )       
        {//Linksrum Relativ zu Markerpfeil am Rand....
        gu8StepBitMusterPars--;
        glSM_RotPosition--;       
        gfBigWeel_GradPos -= gfDegreePerStep;
        }
    else
        {//Rechts
        gu8StepBitMusterPars++;
        glSM_RotPosition++;
        gfBigWeel_GradPos += gfDegreePerStep;
        };   
    gu8StepBitMusterPars &= gu8ModePatternModulo;
    //glSM_RotPosition %= gsStMPar.uiStepsPerRotation;       
    gfBigWeel_GradPos = FloatZahlenRing( gfBigWeel_GradPos, 360.0);
   
    ICTRL_HIGHPWR()    ;
    //Zuerst  Bitmuster wählen, damit Motor immer auf gu8StepBitMusterPars steht.
    STEPCTRL_PORTX =  //Aktueller Steppars..Enabeln
        ((STEPCTRL_PORTX) & (~STEPAMP_ALLCTRL_MASK))    | //ODER . erhalte alle anderen Bits   
        (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + gu8StepBitMusterPars) ) );              

    gulMovedSteps++; //Zähle die Pulse.. !!       
    wdt_reset();    //WATCHDOG    

    //check MOP Count...
    if( gsStMPar.u8StepMConditionFlag & STEPM_PULSE_MODE_FLAG )
        {
        if( gulMovedSteps >= gulSM_ToRunCnt )
            {       
            StepMotorStop();    //EVTL. MIT AUTORELEASE_TIMEOUT
            //gsStMPar.u8StepMConditionFlag &= ~STEPM_PULSE_MODE_FLAG;
            //gsStatus.TargetSMPOS_Erreicht_F = 1;
            };
        };       
       

    if( gsStatus.SMRUN_To_absoluteTarget_GradPOS_F )
        {
        if( round(gfBigWeel_GradPos)  == round(gfBigWeel_Target_GradPos) )
            {
            StepMotorStop();    //EVTL. MIT AUTORELEASE_TIMEOUT
            //gsStatus.TargetSMPOS_Erreicht_F = 1;
            //gsStatus.SMRUN_To_absoluteTarget_GradPOS_F = 0;
            };
/*
        ´else
            {
            //gsStatus.TargetSMPOS_Erreicht_F = 0;
            }
*/        };

// Check_Detectors
    if( gsStatus.ScanIndexRunning_F ) //IDX sci gefunden
        {
        wdt_reset();    //WATCHDOG
        if ( (gsStatus.OptoKoppler_OLD_VAL_F == 0) && READ_SENS_INDEX_ACTIVE_ISHIGH() ) // wechsel von 0 auf 1
            {       
            gsStatus.ScanIndexRunning_F = 0;
            StepMotorStop();
            Set_StepFRQ( gsStMPar.fStepMot_FRQ );
            gsStatus.IndexOK_F = 1;
            gsStatus.NewIndexFound_F = 1;
            glSM_RotPosition = 0;
            gfBigWeel_GradPos = 0; // 0..666.66
            }
        else  //0=Hier nicht gefunden
            {
            gsStatus.IndexOK_F = 0;
            gsStatus.OptoKoppler_OLD_VAL_F =  READ_SENS_INDEX_ACTIVE_ISHIGH();
            if( (gulT2_Ticks - gu32TimeLatch) > SM_IDX_SCAN_TIMEOUT ) // TimeOut
                {
                gsStatus.TimeOut_F = 1;
                gsStatus.ScanIndexRunning_F = 0;
                StepMotorStop();
                };               
            };
        }; //IDX Scan
        //---------------------
    }
else    //gsStMPar.u8StepMConditionFlag & STEPM_ENABLE_FLAG
    {
    StepMotorStop();
    };
};




// *************************************
void StartTimer2(void)    //0.1 Seconds  interrupt
// *************************************
{
TIMSK &= ~ _BV( OCIE2 );
gulT2_Ticks = 0;
OCR2 = 250;
TCNT2 = 0;    //Timer MAX = TOP Compare
TIMSK |= _BV( OCIE2 ); // BESSER
TCCR2 = _BV( WGM21) | TCCR2_CLK_256;    //CTC  ( _BV(CS22) | _BV(CS21) )
sei();
};


//****************************************************************
float FloatZahlenRing(float fZahl, float fLimit )
//****************************************************************
{
if( fZahl >= fLimit )
    {
    fZahl -= fLimit;
    };
if( fZahl < 0)
    {
    fZahl += fLimit;
    };
return fZahl;
};


// ******************
char* FloatToNumStr(double fVal)
// *************
{
return dtostrf(fVal, FLOAT_PRAEDIGITS_MAX, FLOAT_DIGITS_MAX, gcaNumStr ); //[-]d.ddd
};

// **********************************************
char* LongToNumStr(int32_t lVal)
// **********************************************
{
return ltoa(lVal, gcaNumStr, 10 );
};

// **********************************************
char* ULongToNumStr(uint32_t ulVal)
// **********************************************
{
return ultoa(ulVal, gcaNumStr, 10 );
};

// *******************************************************************
char * ByteToBin(uint8_t u8Byte)
// *******************************************************************
{
static char caHex[9]; //groesse 8+1
char * pcParser = caHex;
int8_t i8NN=7;
do
    {
    if( u8Byte & (1 << i8NN) )
        {
        *pcParser = '1';
        }
    else
        {
        *pcParser = '0';
        };
    pcParser++;
    }while(i8NN--);
caHex[8]=0; //Terminierung
return caHex;
};

int32_t Round(double fIn)
// **********************************************
{
return (int32_t)floor(fIn + 0.5);
};


// ******************
void Print_CRLF_CR(void)  //1=CRLF,0=CR ->gsStatus.CRLF_CR_F
// ******************
{
( gsStatus.CRLF_CR_F ? uart_puts_p(MCA_CRLFSTR) : uart_puts_p(MCA_CRSTR) );
};

// ******************
void Print_Str(const char* pStr)
// ******************
{
uart_puts(pStr);
};

// ******************
void Print_PStr(PGM_P pmStr)
// ******************
{
uart_puts_p(pmStr);
};

// ******************
void PrintOK_CRLF(void)
// ******************
{
uart_puts_p( PSTR("OK") );
Print_CRLF_CR();
};

// ******************
void Print_StrCRLF(const char* pStr)
// ******************
{
uart_puts(pStr);
Print_CRLF_CR();
};

// ******************
void Print_PStrCRLF(PGM_P pmStr)
// ******************
{
uart_puts_p(pmStr); Print_CRLF_CR();
};


// ******************
void PrintFloatCRLF(double fVal)
// ******************
{
FloatToNumStr(fVal); Print_StrCRLF(gcaNumStr);
};

// ******************
void PrintLongCRLF(int32_t lVal)
// ******************
{
LongToNumStr(lVal); Print_StrCRLF(gcaNumStr);
};

// ******************
void PrintULongCRLF(uint16_t uiVal)
// ******************
{
ULongToNumStr(uiVal); Print_StrCRLF(gcaNumStr);
};



//CALCUALTION PROCEDURES
// CCCC
// ******************
long CalcDegreeIn_SMPos(float fDegree)
// ******************
{
return round( (FloatZahlenRing(fDegree, 360.0) * gfStepsPerDegree) );
};

// ******************
float CalcPostionInDegree(long lPos)
// ******************
{
// Grad * 0.54
return FloatZahlenRing( (lPos * gfDegreePerStep ), 360 );
};



// *************************************
void Set_StepMotor_Mode(uint8_t ucVal)
//gsStMPar.u8StepMConditionFlag & STEPM_STEPMODE12_MASK
// *************************************
{ //0 = FULL_STEP 1= HALFSTEP;
//Berechne tatsächliche Schritte pro Rotation
gsStMPar.ucSM_Mode = ucVal;
switch(ucVal)
    {
    case MODE_FULLSTEP :    //*1
        {//FULL 1
        //gsStMPar.ucSM_Mode = MODE_FULLSTEP;
        gpmpaStepPattern = MCA_FULLSTEPS;    //MCA pointer Adr.
        gu8ModePatternModulo = FULLSTEP_ANDPARSMAX;//4-1
        gsStMPar.uiStepsPerRotation = SM_ROTATIONS_FULLSTEPS;    //Default 100       
       
        break;
        };
    case MODE_HALFSTEP :    //*2
        {
        //gsStMPar.ucSM_Mode = MODE_HALFSTEP;
        gpmpaStepPattern = MCA_HALFSTEPS;    //MCA pointer Adr.
        gu8ModePatternModulo = HALFSTEP_ANDPARSMAX;//8-1
        gsStMPar.uiStepsPerRotation = (SM_ROTATIONS_FULLSTEPS * 2);    //200 MODE_HALFSTEP
        break;
        };
    };
// Zahnradesektion
// UNTERSETZUNGSVERHAELTNIS(); // 40/12 = 3,333333333333
//200 * 3,333= // 666.666
gfBigWeel_FullRotCnt = gsStMPar.uiStepsPerRotation * UNTERSETZUNGSVERHAELTNIS(); // 666.666
gfStepsPerDegree =  gfBigWeel_FullRotCnt / 360.0;
gfDegreePerStep = 360.0 / gfBigWeel_FullRotCnt;
};


// *************************************
void SetMotorDirection(uint8_t ucVal)
// *************************************
{//0= Rechts  1=Linksrum
//Nur wenn nicht schon so eingestellt
//Geht nur, weil #define STEPM_DIRECTION_FLAG        0x01= NULL Bit --> Sonst Shift Bit
if(ucVal) //1 == links
    {
    gsStMPar.u8StepMConditionFlag |= STEPM_DIRECTION_FLAG;
    }
else//dir == 0 == rechts
    {
    gsStMPar.u8StepMConditionFlag &= ~STEPM_DIRECTION_FLAG;
    };
//Falls Motor grad aktiv ist,,halt in an,und ändere die Richtung       
if( gsStMPar.u8StepMConditionFlag & STEPM_RUN_FLAG )
    {
    StepMotorStop();
    StepMotorOn();
    };
};


// *************************************
void StepMotorOn(void)
// *************************************
{
//CPU_ICTRL_ONOFFLAG steuert ob dauerstrom oder PWM
    //Verriegelung, falls der Motor an den Anschlagschalterns steht,
    //das er in die falsche Richtung anstartet   
    //0x10 Wert des EXtswitch via INT1 = LINKS
    //define MODE_FULLSTEP 0x00    define MODE_HALFSTEP 0x01
    //1. Warte auf Stop --> Ist der Auftrag erledigt, (verhindert widersprechnede Befehle)
    //2.Warte nach Stop
    //Set_StepMotor_Mode( gsStMPar.ucSM_Mode );       
    ICTRL_HIGHPWR();    //Lege die letzen Bits an...
    gulMovedSteps = 0;    //COUNTSZÄHLER !!!!!!!
    wdt_reset();   //WATCHDOG
    //Unbedingt warten damit Magnetfeld sich aufbauen und fangen kann.
    if( !(gsStMPar.u8StepMConditionFlag & STEPM_ENABLE_FLAG) )
        {       
        STEPCTRL_PORTX =  //Aktueller Stepper..Enabel
            (( STEPCTRL_PORTX ) & ~STEPAMP_ALLCTRL_MASK)    | //ODER . clear SMbit und erhalte alle anderen Bits   
            (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + gu8StepBitMusterPars) ) );       
        };   
    wdt_reset();
    _delay_ms( 1 );    //Unbedingt warten damit Magnetfeld sich aufbauen und fangen kann.
   
    //3.erst dann Starte   
    gsStMPar.u8StepMConditionFlag &= ~(STEPM_STOP_ACTIVE_FLAG | STEPM_TIMEOUT_ENABLE_FLAG);    //Lösche Pausebedingung   
    gsStMPar.u8SM_PostionFlag &= ~POSITION_STOP_ON_TARGET_OK; // !u8SM_PostionFlag
    gsStatus.TargetSMPOS_Erreicht_F = 0;
    gsStMPar.u8StepMConditionFlag |= (STEPM_ENABLE_FLAG | STEPM_RUN_FLAG);//ENABLE ANZEIGEN (INTERRUPPT)UND SPEICHERN       
   
    if(    gsStatus.ScanIndexRunning_F )
        {
        Set_StepFRQ( gsStMPar.fSCan_SM_FRQ );
        }
    else
        {
        Set_StepFRQ( gsStMPar.fStepMot_FRQ );
        };
    gsStatus.SM_Running_Msg_F = 1;
    wdt_reset();
    //TIMER ON
    StepFRQ_OnOff(FRQ_ON);
};


// *************************************
void StepMotorStop(void)    //hält mOTOR an, ictrl/pwm,bleibt ENABLE !!
// *************************************
{
StepFRQ_OnOff(FRQ_OFF);    //0
gulSM_ToRunCnt = 0;
//ENABELD ( STROM AKTIV !!!!)
//Jetzt mit allen Flags aufräumen
STEPCTRL_PORTX =  //Aktueller Stepper..Enabel
    (( STEPCTRL_PORTX ) & ~STEPAMP_ALLCTRL_MASK)    | //ODER . clear SMbit und erhalte alle anderen Bits   
    (pgm_read_byte_near( (PGM_P)(gpmpaStepPattern + gu8StepBitMusterPars) ) );       
//KEIN ICTRL_LOWPWR();
gsStMPar.u32SMActiveStopTime = gulT2_Ticks; //Neu 
gsStMPar.u8StepMConditionFlag |= STEPM_STOP_ACTIVE_FLAG | STEPM_TIMEOUT_ENABLE_FLAG;    //Zeige Stopstatus-ENABLED an
//Nicht dauernd Stop sagen beim IDX Lauf

gsStMPar.u8StepMConditionFlag &= ~(STEPM_RUN_FLAG | STEPM_PULSE_MODE_FLAG);
gsStMPar.u8SM_PostionFlag &= ~(POSITION_STOP_ON_DISTANCE_MODE_FLAG | POSITION_STOP_ON_TARGET_MODE_FLAG);
gsStMPar.u8SM_PostionFlag |= POSITION_STOP_ON_TARGET_OK;
gsStatus.ScanIndexRunning_F = 0;
gsStatus.SMRUN_To_absoluteTarget_GradPOS_F  = 0;
gsStatus.TargetSMPOS_Erreicht_F = 1;
gsStatus.SM_NowSTOPed_Msg_F = 1; // Damit kein Text im Interrupt getriggert wird
};


// *************************************
void StepMotorOff(void)    //Komplett STOPS AND FREE axis.
// *************************************
{
StepMotorStop();
//Lösche Stopstatus
STEPCTRL_PORTX &= ~STEPAMP_ENABLE_MASK; // Lösche nur!  Enable Status
ICTRL_LOWPWR();
gsStMPar.u8StepMConditionFlag &= ~(STEPM_PULSE_MODE_FLAG | STEPM_ENABLE_FLAG | STEPM_STOP_ACTIVE_FLAG | STEPM_RUN_FLAG);
gsStatus.SMRUN_To_absoluteTarget_GradPOS_F  = 0;
gsStatus.SM_NowOFF_F = 1; // Damit kein Text im Interrupt getriggert wird
};


// *************************************
void Set_StepFRQ(float fVal)
// *************************************
{
if(fVal)
    {
    TCNT1 = 0;
    OCR1A = (uint16_t)Round( PULS_PER_SECOND_T1 / fVal ); //16^6/1024
    TCNT1 = 0;
    };
};


// *************************************
void StepFRQ_OnOff(uint8_t uOnOff)
// *************************************
{
TCCR1B = TCCR1B_CLOCKSEL_STOP;    //Stopen, damit keine geschachtelten Interrrupts passieren...
if( uOnOff )  // Im FALLE DAS FRQ = 0 MOTOR STOP !
    {
    TIMSK &= ~( _BV(OCIE1A ) | _BV(OCIE1B ) | _BV(TOIE1 ) );
    TCNT1 = 0;/* reset TCNT1 */        /* disable PWM and stuff */
    TIMSK |= _BV(OCIE1A );    //Interrupt ein
    TCCR1B = TCCR1B_CTC_MODE | TCCR1B_CLOCKSEL_CPU_1024;//Clear Timer on Compare=CTC.  MODE an OCR1A + / CLk/1024
    }
else
    {
    TIMSK &= ~_BV(OCIE1A );
    };
};

// CCC
/// ***************************
void Calc_Shortest_GradPos_Direction(float fBW_Target_GradPos )
// ***************************
{
//NEU BIDIR=0 UNIDIR=1 (Je Nach SET DIRECTION)
if( fBW_Target_GradPos > gfBigWeel_GradPos )
    {
    if( (fBW_Target_GradPos - gfBigWeel_GradPos)  <= 180 )
        {
        SetMotorDirection( SM_DIR_RECHTS );
        }
    else
        {
        SetMotorDirection( SM_DIR_LINKS);
        };
    }
else //fBW_Target_GradPos < gfBigWeel_GradPos
    {
    if( (gfBigWeel_GradPos - fBW_Target_GradPos ) < 180 )
        {       
        SetMotorDirection( SM_DIR_LINKS );
        }
    else
        {
        SetMotorDirection( SM_DIR_RECHTS );
        };           
    };
};



//MOPD
// ******************
void SM_Run_Puls_DIR(uint32_t ulPuls, uint8_t ucDir)
// ******************
{
StepMotorOff();
SetMotorDirection( ucDir );
gsStatus.SMRUN_To_absoluteTarget_GradPOS_F = 0;
gsStMPar.u8StepMConditionFlag |= STEPM_PULSE_MODE_FLAG;
gulMovedSteps = 0;
gulSM_ToRunCnt = ulPuls;
StepMotorOn();
};


//GOTOD
// ******************
void Run_To_SM_Absolute_GradTarget(float fBigWheel_Grad_Target )
// ******************
{
StepMotorOff();
gfBigWeel_Target_GradPos =  FloatZahlenRing( fBigWheel_Grad_Target,360.0);
//SetMotorDirection( ucDir );
Calc_Shortest_GradPos_Direction( fBigWheel_Grad_Target ); // //Round ( abs( SetMotorDirection( ucDir );
gsStMPar.u8StepMConditionFlag &= ~STEPM_PULSE_MODE_FLAG;
gsStatus.SMRUN_To_absoluteTarget_GradPOS_F = 1;
StepMotorOn();
};



// ******************
void StartScan_SM_Index(void)
// ******************
{
StepMotorOff();
Set_StepMotor_Mode( MODE_HALFSTEP );
SetMotorDirection( SM_DIR_DEFAULT ); //SM_DIR_RECHTS
Print_PStrCRLF( PSTR("* Index_run_is_started *") );

gsStMPar.u32SM_ActiveStartTime = gulT2_Ticks;
if( READ_SENS_INDEX_ACTIVE_ISHIGH() )  // == 1// Lasche steht im Optokoppler
    {
    Set_StepFRQ( gsStMPar.fStepMot_FRQ );
    // 200*3,333 = 666.666 aber etwas weniger, also nicht ganz rum!
    Print_PStrCRLF( PSTR("Drive near Index->") );
    gsStatus.ScanIndexRunning_F = 0;

//Print_PStr(PSTR("1->")); Print_StrCRLF( ByteToBin( gsStMPar.u8StepMConditionFlag) );
       
    SM_Run_Puls_DIR(580, SM_DIR_RECHTS ); //Drehe in raus aus der Lichschranke
    gu32TimeLatch = gulT2_Ticks;
    gsStatus.TimeOut_F = 0;
    Print_CRLF_CR();
    wdt_reset();    //WATCHDOG
    do
        {       
        if( (gulT2_Ticks - gu32TimeLatch) > SM_DRIVE_FAST_TO_INDEX_TIMEOUT )
            {
            Print_PStr( PSTR("*") );
            _delay_ms(500);
            wdt_reset();    //WATCHDOG
            gsStatus.TimeOut_F = 1;
            };
        }while( (gsStMPar.u8StepMConditionFlag & STEPM_PULSE_MODE_FLAG) && !gsStatus.TimeOut_F );
    Print_CRLF_CR();
    StepMotorStop();
    };   
    //Mache weiter mit Suche:
gsStatus.OptoKoppler_OLD_VAL_F = READ_SENS_INDEX_ACTIVE_ISHIGH();  // Stelle auf jetzt --> sollte NULL sein
//Print_PStr(PSTR("2->")); Print_StrCRLF( ByteToBin( gsStMPar.u8StepMConditionFlag) );
gsStMPar.u8StepMConditionFlag &= ~STEPM_PULSE_MODE_FLAG;
Print_PStrCRLF( PSTR("Wait:Suche Index") );
gu32TimeLatch = gulT2_Ticks;  // Für TimeOut
SetMotorDirection(SM_DIR_RECHTS);
Set_StepFRQ( gsStMPar.fSCan_SM_FRQ );
//Print_PStr(PSTR("3->")); Print_StrCRLF( ByteToBin( gsStMPar.u8StepMConditionFlag) );
gsStatus.IndexOK_F = 0;
gsStatus.ScanIndexRunning_F = 1;
gu32TimeLatch = gulT2_Ticks; // jetzt nochnmal merken, damit Int bescheid weiß
//Print_PStr(PSTR("4->")); Print_StrCRLF( ByteToBin( gsStMPar.u8StepMConditionFlag) );
StepMotorOn();
//Print_PStr(PSTR("5->")); Print_StrCRLF( ByteToBin( gsStMPar.u8StepMConditionFlag) );
};


// ******************
void ResetRxBuff(void)
// ******************
{
gpcRxPars = gcaRxStr; // Set parse pointer back;
*gpcRxPars = 0;    //clear Rx
};

// ******************
void UART_TXRX_Check(void)
// ******************
{
uint16_t uiRxUart;
uiRxUart = uart_getc();//!FETCH ALLWAYS BYTE FROM RX RINGBUFF INTERRUPT!
if ( !(uiRxUart & UART_NO_DATA) )  //0x0100
    {
//   * new data available from UART
//  * check for Frame or Overrun error
#if UART_ERRORMSG == 1
    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_PStrCRLF(  PSTR("UARTError") );
        };
#endif
//NOW SELCT ACTION FROM ORDER
//Check CR
    if(gpcRxPars < (gcaRxStr + RX_STRMAX))    //ENDANSCHLAG ERREICHT ?
        {
        switch( (unsigned  char)uiRxUart  )
            {
            case 10 : // LF
                {
                return;
                break;
                };
            case 13: // order!! from Terminal
                {
#if MSG == 1
//Print_StrCRLF(gcaRxStr);
#endif
                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
        };//if(gpcRxPars < (gcaRxStr + RXSTRMAX))
// ENDE DER RX EMPFANGSAUSWERTUNG
    };
};

// OOO
// ******************
void CheckOrder(char *pcStrOrder) //von gcaRxStr
// ******************
{ //INPUT ERWARTET INDER FOR "BEFEHL,WERT" BSP: "SFR,1000"

#ifdef DEGREE_FUNCTIONS_ENABLED
//uint16_t uiCnt =0;
#endif

char * pStrTok; // für strtok_r
char * pucCh = &pcStrOrder[ strlen(pcStrOrder) ]; // Stelle POINTER auf \0 Ende  // kein unsigned char*

strcpy(gcaStr, pcStrOrder);
#if LCD_4Bit_Module_USED == 1
WriteLCD(LCD_SHOW_CMD_LINE, gcaStr);//Füllt mit Sapce auf Vorsicht umkopieren..    //ZEIGE DAs Commando an
#endif
// Print_StrCRLF( pcStrOrder );  /Rausmachen da zuvile Trffic dabei entsteht.

/*
int8_t caCmd[COMAMNDSIZEMAX +1];
    uint8_t ucCmdID;
    float fCmdVal_1;
    float fCmdVal_2;
*/

// SETZE "," in gcaNumStr als RAMVARIABLE für Delimiter.
strcpy_P(gcaNumStr, MCA_DELIMITER_MSG); //HILFSWEISE gcaNumStr für ","
if( (pStrTok = strtok_r( pcStrOrder, gcaNumStr , &pucCh)) != NULL) //Trenne CMD, CMD
    {   
    strcpy(gsCmd.caCmd, pStrTok);
    }
else
    {
    *gsCmd.caCmd = 0;
    };

gsCmd.caCmd[ COMAMNDSIZEMAX ] = 0; //Sicherheitsterminierung COMAMNDSIZEMAX=10

gsCmd.fCmdVal_1 = gsCmd.fCmdVal_2 = 0;
if( (pStrTok = strtok_r( NULL,  gcaNumStr, &pucCh)) != NULL)//Hole nun einen Value nach "$$$1,COMMAND,VALUE
    {
    gsCmd.fCmdVal_1 = atof(pStrTok);// Und dann TO Float   
    };
   
if( (pStrTok = strtok_r( NULL,  gcaNumStr, &pucCh)) != NULL)//Hole nun einen Value nach "$$$1,COMMAND,VALUE
    {
    gsCmd.fCmdVal_2 = atof(pStrTok);// Und dann TO Float   
    };

//========================================================================================

if( !strcasecmp_P( gsCmd.caCmd, PSTR("PING") ) )
    {
    Print_PStrCRLF( PSTR("PONG - DrehFilter") ); return;
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("VER") ) )    
    {
    Print_PStr( PSTR( DATUM ) );
    Print_PStrCRLF( PSTR(" by Christof Ermer (C)Universitaet Regensburg") ); return;
    return;
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SCI") ) )
    {
    StartScan_SM_Index();
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("SIX" ) ) )     //Set INDEX gegenwärtige Position direkt eingestellt
    {
    gsStatus.ScanIndexRunning_F = 0;
    gsStatus.IndexOK_F = 1;
    gsStatus.NewIndexFound_F = 1;
    gfBigWeel_GradPos = 0;   
    glSM_RotPosition = 0;
    gfBigWeel_FullRotCnt = 0;
    return;
    };


if( !strcasecmp_P( gsCmd.caCmd, PSTR("GIDX") ) )
    {
    PrintULongCRLF( gsStatus.IndexOK_F); return;
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("GOTOD" ) ) )   //Goto DEGREE
    {
    Run_To_SM_Absolute_GradTarget( FloatZahlenRing( (gsCmd.fCmdVal_1 + gsStMPar.iIndexOffset), 360.0 ) );
    StepMotorOn();
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("TAR_OK?" ) ) )  //Target_Erreicht_F = 1
    {
    PrintLongCRLF( gsStatus.TargetSMPOS_Erreicht_F ); return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("GPOS" ) ) )
    {   
    PrintLongCRLF( glSM_RotPosition );     return;
    };   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("BWGP" ) ) )
    {   
    PrintFloatCRLF( gfBigWeel_GradPos ); return;
    };   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("BWTP" ) ) )
    {   
    PrintFloatCRLF( gfBigWeel_Target_GradPos  ); return;
    };   
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SMON") ) )
    {
    gsStMPar.u8StepMConditionFlag &= ~STEPM_PULSE_MODE_FLAG; //Kein Pulscount
    gsStatus.SMRUN_To_absoluteTarget_GradPOS_F = 0;
    if((uint8_t)gsCmd.fCmdVal_1)    //OPTIONAL; GLEICH MIT pULScountangabe
        {
        gsStMPar.fStepMot_FRQ = gsCmd.fCmdVal_1;       
        }
    else
        {
        gsStMPar.fStepMot_FRQ  = PREDEF_STEPFREQUENZ;
        };
    Set_StepFRQ( gsStMPar.fStepMot_FRQ );
    StepMotorOn();
    };

//MOPD
if( !strcasecmp_P( gsCmd.caCmd, PSTR("MOPD") ) ) //MOTOr ON Pulse, Direction
    {
    SM_Run_Puls_DIR( (uint32_t)gsCmd.fCmdVal_1, (uint8_t)gsCmd.fCmdVal_2 );    //Default ist 200...
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("SMOFF") ) )
    {
    StepMotorOff();
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("SMSTOP") ) )
    {
    StepMotorStop();
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SFR") ) )
   {
    if( gsCmd.fCmdVal_1 )
        { gsStMPar.fStepMot_FRQ = gsCmd.fCmdVal_1; }
    else
        { gsStMPar.fStepMot_FRQ = PREDEF_STEPFREQUENZ;    };   
    Set_StepFRQ( gsStMPar.fStepMot_FRQ );
    };

   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SDIR") ) )
   {
    if((uint8_t)gsCmd.fCmdVal_1)
        {
        SetMotorDirection( SM_DIR_LINKS );
        }
    else
        {
        SetMotorDirection( SM_DIR_RECHTS );
        };
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("HALF") ) )
    {   
    Set_StepMotor_Mode( MODE_HALFSTEP ); //2
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("FULL") ) )
    {
    Set_StepMotor_Mode(  MODE_FULLSTEP );    //1
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("SIDXFRQ") ) )    //SET INDEX SCAN FRQ
   {
    if( gsCmd.fCmdVal_1 )
        {gsStMPar.fSCan_SM_FRQ = gsCmd.fCmdVal_1; }
    else
        { gsStMPar.fSCan_SM_FRQ = PREDEF_SCAN_INDEX_FRQ;    };    //Default 25.0
    return;
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SPR") ) ) //Set Steps per Rotation
    {    //Default ist 200...
    gsStMPar.u16SM_HardwareBasisSteps = (uint16_t)gsCmd.fCmdVal_1; //Normal 200
    return;
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SETO") ) ) //Set ENBALE TIMEOUT if Stop
    {   
    gsStMPar.ulStepM_Enable_TimeOut = (uint32_t)gsCmd.fCmdVal_1;
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("SIT") )  )
    {
    gsStMPar.uiScan_Index_Timeout = (uint16_t)gsCmd.fCmdVal_1;
    return;
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SIENA") )  )
    {
    if( (uint16_t)gsCmd.fCmdVal_1)
        {
        gsStatus.ScanIDX_Start_EnaF = 1;
        }
    else
        {
        gsStatus.ScanIDX_Start_EnaF = 0;
        };
    return;
    };


if( !strcasecmp_P( gsCmd.caCmd, PSTR("IDXO" ) ) ) //indexOffset direkt eingestellt
    {
    gsStMPar.iIndexOffset = (int16_t)gsCmd.fCmdVal_1;
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("COF") ) )
    {
    PrintLongCRLF( gsStMPar.u8StepMConditionFlag );  return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("COFBIN") ) )
    {
    Print_StrCRLF( ByteToBin( gsStMPar.u8StepMConditionFlag ) ); return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("POF" ) ) )    //
    {
    PrintLongCRLF(gsStMPar.u8SM_PostionFlag); return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("POFBIN") ) )
    {
    Print_StrCRLF( ByteToBin( gsStMPar.u8SM_PostionFlag) ); return;
    };
// ..............................................

if( !strcasecmp_P( gsCmd.caCmd, PSTR("BWFR" ) ) )
    {   
    PrintFloatCRLF( gfBigWeel_FullRotCnt ); return;
    };   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("SPD" ) ) )
    {   
    PrintFloatCRLF( gfStepsPerDegree ); return;
    };   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("DPS" ) ) )
    {   
    PrintFloatCRLF( gfDegreePerStep );     return;
    };   

     
if( !strcasecmp_P( gsCmd.caCmd, PSTR("CPOSID" ) ) ) // TX PositionDefg
    {   
    PrintFloatCRLF( CalcPostionInDegree( gsCmd.fCmdVal_1 ) ); return;
    };   

if( !strcasecmp_P( gsCmd.caCmd, PSTR("CDISMPOS" ) ) ) // TX PositionDefg
    {   
    PrintLongCRLF( CalcDegreeIn_SMPos( gsCmd.fCmdVal_1 ) ); return;
    };   

if( !strcasecmp_P( gsCmd.caCmd, PSTR("LICHTSCHRANKE" ) ) ) // TX PositionDefg
    {   
    PrintLongCRLF( gsStatus.OptoKopplerActive_F );
    return;
    };   

// ***************************
    if( !strcasecmp_P( gsCmd.caCmd, PSTR("Flags") ) )    //0= CR ONLY, 1 = CRLF
    {
    Print_PStr(PSTR("ScanIDXStart?->"));PrintLongCRLF( (int)gsStatus.ScanIDX_Start_EnaF );
    Print_PStr(PSTR("ScanIndexRunning_F?->"));PrintLongCRLF( gsStatus.ScanIndexRunning_F );
    Print_PStr(PSTR("NewIndexFound_F?->"));PrintLongCRLF( gsStatus.NewIndexFound_F);
    Print_PStr(PSTR("IDXOK?->"));PrintLongCRLF( gsStatus.IndexOK_F );
    Print_PStr(PSTR("OptoKopplerActive_F?->"));PrintLongCRLF( gsStatus.OptoKopplerActive_F );
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("POS") ) )
    {
    Print_PStr(PSTR("gfBigWeel_FullRotCnt=\t"));PrintFloatCRLF( gfBigWeel_FullRotCnt );
    Print_PStr(PSTR("gfStepsPerDegree=\t"));PrintFloatCRLF( gfStepsPerDegree );
    Print_PStr(PSTR("gfBigWeel_GradPos=\t"));PrintFloatCRLF( gfBigWeel_GradPos );
    Print_PStr(PSTR("glSM_RotPosition=\t"));PrintULongCRLF(glSM_RotPosition );
    Print_PStr(PSTR("gfBigWeel_TargetPos=\t"));    PrintFloatCRLF(gfBigWeel_Target_GradPos  );
    Print_PStr(PSTR("Target_Erreicht_F=\t")); PrintLongCRLF( gsStatus.TargetSMPOS_Erreicht_F );
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("TRX" ) ) )  //& TZRAFFIC ON
    {
    gsStatus.ComTraffic_F =  (uint8_t)gsCmd.fCmdVal_1;
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("CR_CRLF" ) ) )    //0= CR ONLY, 1 = CRLF
    {
    gsStatus.CRLF_CR_F = (uint8_t)gsCmd.fCmdVal_1;
    return;
    };
   
if( !strcasecmp_P( gsCmd.caCmd, PSTR("IDXCHANGE" ) ) )
    {
    gsStatus.OptoKoppler_OLD_VAL_F = gsStatus.OptoKopplerActive_F;
   
    Print_PStr( PSTR("IDXChange=") );
    Print_Str( ULongToNumStr( gsStatus.OptoKopplerActive_F ) );
    Print_PStr( PSTR(" = ") );
    PrintULongCRLF( READ_SENS_INDEX_ACTIVE_ISHIGH() );           
    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("TT" ) ) )
    {
    PrintULongCRLF( gulT2_Ticks );    return;
    };

if( !strcasecmp_P( gsCmd.caCmd, PSTR("??") ) )
    {
    Print_PStr( PSTR("SCI,GIDX,GOTOD,TAR_OK?SIX,TRX,GIDX,IDXO") );
    Print_PStr( PSTR("SMON,MOPD,SMSTOP,SMSOFF,SFR,SDIR") );
    Print_PStr( PSTR("HALF,FULL,SPR,SIENA,SIX,SIDXFRQ,SETO,SIT") );
    Print_PStr( PSTR("SPO,SDP,GOD,COF,COFBIN,POF,POFBIN,POS,SIENA") );
    Print_PStr( PSTR("BWFR,SPD,DPS,GPOS,BWGP,BWTP,CPOSID,CDISMPOS") );
    Print_PStr( PSTR("LICHTSCHRANKE,IDXCHANGE,Flags,Ping,VER,CR_CRLF,TRX,TT") );
    return;
    };
   
#if CMD_OK_ECHO_ENABLED == 1

if( gsStatus.ComTraffic_F )
    {
    strcpy_P(gcaStr, PSTR("CMD:") );
    strcat(gcaStr, gsCmd.caCmd);
    strcat_P(gcaStr,MCA_DELIMITER_MSG);
    strcat(gcaStr, FloatToNumStr(gsCmd.fCmdVal_1) );
    strcat_P(gcaStr, MCA_SPACE_MSG);
    if( gsStatus.CRLF_CR_F )
        {
        strcat_P(gcaStr, MCA_OK_MSG );  
        }
    else
        {
        strcat_P(gcaStr, MCA_OK_MSG );  
        };
    Print_StrCRLF(gcaStr);  
    };
#endif
};//ENDE ORDER FUNC.


//MM
// ************ MAIN LOOP FOR EVER *********************
 int main(void)
// **********************************************************
{
uint32_t ulMainCnt = 0; //Speed watch
cli();//The global interrupt flag is maintained in the I bit of the status register (SREG). 
//INITS
wdt_reset();   //WATCHDOG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Wichtige Schritte.. so bald wie möglich

//INIT HARDWARE
//USing of PORTOUTS   like --->
DDRA = PORTA_OUTMASK;
PORTA = PORTA_PULLMASK; //=0
DDRB = PORTB_OUTMASK;
PORTB = PORTB_PULLMASK; //#define PORTB_PULLMASK 0x00 //Nothing PullUp
DDRC = PORTC_OUTMASK;    //DIREKT IN geppult ?
PORTC = PORTC_PULLMASK; //#define PORTC_PULLMASK 0x00 //
DDRD = PORTD_OUTMASK;    //1100 0010 #define PORTD_OUTMASK 0xC2    //DDRB = PORTD_OUTMAS;
PORTD = PORTD_PULLMASK;    //#define PORTD_PULLMASK 0x01

ICTRL_LOWPWR();

ResetRxBuff();
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) );// !! Init UART interface
gsStatus.CRLF_CR_F = CR_ODER_CRLF_DEFAULT;  //= 1 CRLF


gsStMPar.fStepMot_FRQ = PREDEF_STEPFREQUENZ;        //Default 100.0
gsStMPar.fSCan_SM_FRQ = PREDEF_SCAN_INDEX_FRQ;        //Default 25.0

gsStMPar.ucSM_Mode = PREDDEF_STEPMODE;                //MODE_HALFSTEP
gsStMPar.ulStepM_Enable_TimeOut = PREDEF_STEPM_ENABLE_TIMEOUT_SEC; // 610 // 10.0 SEc. / TIMER2_INTPERIODE (if ENABLED !!)
//gsStMPar.ulMotorRunTime = PREDEF_MOTOR_RUN_TIME; //0xFFFFFFFF = Allways
gulSM_ToRunCnt = PREDEF_STEPCLOCKS;//= 1 wieviele Steps soll der Motor gehen(Default= 1)
gsStMPar.u16SM_HardwareBasisSteps = SM_ROTATIONS_FULLSTEPS;    //Default 100  half steps

gsStMPar.uiStepsPerRotation = gsStMPar.u16SM_HardwareBasisSteps * gsStMPar.ucSM_Mode;
//gsStMPar.u8StepMConditionFlag & STEPM_BIDIRECTION_FLAG  = PREDEF_BIDIRECTION_MODE;
//gsStMPar.u8StepMConditionFlag = STEPM_BIDIRECTION_FLAG;    //Setze auf UNIDIR=1(Je NAch SET DIRECTION)

gsStMPar.uiScan_Index_Timeout = PREDEF_SCANINDEX_TIMEOUT;            //    4800 60 ~ 80 Sekunden
gsStMPar.iIndexOffset = PREDEF_INDEX_OFFFSET;    //#define PREDEF_INDEX_OFFFSET


//VARIABLEN löschen
glSM_RotPosition = 0;
gu8StepBitMusterPars = 0;
gsStMPar.u32SMActiveStopTime = 0;

sei();
Print_PStrCRLF( PSTR("**Neustart erfolgreich**" ) );
_delay_ms(50 );
wdt_reset();    //WATCHDOG

StepMotorOff();//Flags setzen
Set_StepMotor_Mode( MODE_HALFSTEP ); //MODE_FULLSTEP
SetMotorDirection( SM_DIR_DEFAULT ); //SM_DIR_RECHTS

//UNTERSETZUNGSVERHAELTNIS(); //3,3333333
//((float)((float)ZAHNRAD_GROSS / (float)ZAHNRAD_KLEIN)) //3,333333

wdt_reset();    //WATCHDOG
Print_PStrCRLF( PSTR("I have no brain") ) ;
Print_PStrCRLF( PSTR("use your own!") );
_delay_ms(100 );
//includes ucSM_Mode und gsStMPar.uiStepsPerRotation
//HALFSTEP; RAMPE = ON; TIMEOUT IF ACTIVE STOP AND ENABLED
//STEPM_DIRECTION_FLAG 0 = RECHTS_VOREINGESTELLT
//ZEROS
//MM
gsStatus.CRLF_CR_F =  CR_ODER_CRLF_DEFAULT;
gsStatus.ComTraffic_F  = 0;

wdt_enable(WDTO_2S); //Set 1.9Sec WatchDog ENABLE
wdt_reset();    //WATCHDOG

StartTimer2();    //8 Bit Timer 2 = MS Tick
sei();

gsStatus.ScanIDX_Start_EnaF = SCAN_IDX_BY_START_DEFAULT;

if( gsStatus.ScanIDX_Start_EnaF )
    {
    StartScan_SM_Index(); // Trigger Scan
    };

gsStMPar.u8SM_PostionFlag &= ~POSITION_STOP_ON_TARGET_OK;

for (;;)  /* loop forever */
   {
//@@@   
    wdt_reset();    //WATCHDOG
    ulMainCnt++;
// SEKUNDE TICKS
    if( gsStatus.TickEvent_F )    //SEKUNDEN PULS EVENT. in main loop
        {
        gsStatus.TickEvent_F = 0;
        LongToNumStr(ulMainCnt);
        ulMainCnt=0;
       
        if( gsStatus.ComTraffic_F )
            {
            Print_CRLF_CR();
            Print_StrCRLF( gcaNumStr);  //MainCount           
           
                //Check Enable TImeout.       
            if(    !(gsStMPar.u8StepMConditionFlag & STEPM_RUN_FLAG) && //0 =Aktiv. Timeoutcheck = 0 KEIN TIMEOUT=allways ON
                (gsStMPar.u8StepMConditionFlag & STEPM_STOP_ACTIVE_FLAG)    &&
                (gsStMPar.u8StepMConditionFlag & STEPM_TIMEOUT_ENABLE_FLAG)    &&
                ( (gulT2_Ticks - gsStMPar.u32SMActiveStopTime) > gsStMPar.ulStepM_Enable_TimeOut)
            )
                {
                //Bits belassen,
                ICTRL_LOWPWR();
                gsStMPar.u8StepMConditionFlag &= ~STEPM_TIMEOUT_ENABLE_FLAG;
                Print_PStrCRLF( PSTR( "I_PWR_OFF cause TimeOut" ) );
                };           
                   
            if( gsStatus.NewIndexFound_F )
                {
                gsStatus.NewIndexFound_F = 0;
                Print_PStrCRLF(PSTR("New INDEX Found" ) );
                ( gsStatus.IndexOK_F  ? Print_PStr(PSTR("OK")) : Print_PStr(PSTR("Wrong")) );
                };
               
            if( gsStatus.TimeOut_F )
                {
                gsStatus.TimeOut_F =0;
                Print_PStrCRLF(PSTR("TIME OUT") );   
                Print_PStr(PSTR("Index=") );   
                };

            if(!gsStatus.IndexOK_F) Print_PStrCRLF( PSTR("IDX Wrong"));
            strcpy_P(gcaStr, PSTR("WeelPos:") );
            strcat_P(gcaStr, MCA_ISTGLEICH_MSG);
            strcat(gcaStr, FloatToNumStr( gfBigWeel_GradPos ) );
            strcat_P(gcaStr, MCA_SPACE_MSG);

            strcat_P(gcaStr, PSTR("TargetPos:") );
            strcat_P(gcaStr, MCA_ISTGLEICH_MSG);
            strcat(gcaStr, FloatToNumStr( gfBigWeel_Target_GradPos  ) );
            strcat_P(gcaStr, MCA_SPACE_MSG);
            Print_StrCRLF(gcaStr);
           
           
    Print_PStr(PSTR("gfBigWeel_FullRotCnt=\t"));PrintFloatCRLF( gfBigWeel_FullRotCnt );
    Print_PStr(PSTR("gfStepsPerDegree=\t"));PrintFloatCRLF( gfStepsPerDegree );
    Print_PStr(PSTR("gfDegreePerStep=\t"));PrintFloatCRLF( gfDegreePerStep );
    Print_PStr(PSTR("glSM_RotPosition=\t"));PrintULongCRLF(glSM_RotPosition );
    Print_PStr(PSTR("gfBigWeel_GradPos=\t"));PrintFloatCRLF( gfBigWeel_GradPos );
    Print_PStr(PSTR("gfBigWeel_Target_GradPos=\t"));    PrintFloatCRLF(gfBigWeel_Target_GradPos  );
               
            };    //COM TRAFFIC
        };    // ENDE SEKUNDETICKS

    if(    gsStatus.SM_Running_Msg_F )
        {
        gsStatus.SM_Running_Msg_F = 0;
        if( gsStatus.ComTraffic_F )
            {
            Print_PStr( MCA_MOTOR_MSG );
            Print_PStrCRLF( PSTR( " RUNNING")  );
            };
        };

    if( gsStatus.SM_NowSTOPed_Msg_F ) //Damit kein Text im Interrupt getriggert wird
        {
        gsStatus.SM_NowSTOPed_Msg_F = 0;
        if( gsStatus.ComTraffic_F )
            {
            Print_PStr( MCA_MOTOR_MSG );
            Print_PStrCRLF( PSTR( " STOP")  );
            };
        };
       
    if( gsStatus.SM_NowOFF_F ) // Damit kein Text im Interrupt getriggert wird
        {
        gsStatus.SM_NowOFF_F = 0;
        if( gsStatus.ComTraffic_F )
            {
            Print_PStr( MCA_MOTOR_MSG );
            Print_PStrCRLF( PSTR( " OFF") );
            };           
        };
       
    //SCAN               
    if(  !gsStatus.ScanIndexRunning_F && //Wenn nicht gerade gesucht wird
        (gsStatus.OptoKopplerActive_F != gsStatus.OptoKoppler_OLD_VAL_F    )
    )
        {
        gsStatus.OptoKoppler_OLD_VAL_F = gsStatus.OptoKopplerActive_F;

        if( gsStatus.ComTraffic_F )
            {       
            Print_PStr( PSTR("IDXChange=") );
            Print_Str( ULongToNumStr( gsStatus.OptoKopplerActive_F ) );
            Print_PStr( PSTR(" =\t ") );
            PrintULongCRLF( READ_SENS_INDEX_ACTIVE_ISHIGH() );   
            };
        };
                               
    if( gsStMPar.u8SM_PostionFlag & POSITION_STOP_ON_TARGET_OK )
        {
        gsStatus.TargetSMPOS_Erreicht_F = 1;
        gsStMPar.u8SM_PostionFlag &= ~POSITION_STOP_ON_TARGET_OK;   
        if( gsStatus.ComTraffic_F )
            {
            strcpy_P(gcaStr, PSTR("TARGET") );
            strcat_P(gcaStr, MCA_ISTGLEICH_MSG);
            FloatToNumStr(gfBigWeel_Target_GradPos );
            strcat(gcaStr, gcaNumStr);
            Print_StrCRLF( gcaStr );
            };
        };

    //Read and Service UART   
    if( !(gulT2_Ticks & 0x1F )) {UART_TXRX_Check();}; //IMMER VORNAHANDEN !! IN ALLEN LOOPS DIE ZEIT BRAUCHEN

    }; // main   END END *************
};
// ******************* MAIN END ********************************************


MAIN.h

// Neu Bearbeitet 12.09.24
/*
INSTITUT    "UNI-Regensburg"
AUTOR        "Christof Ermer"
DATUM        12.09.2024 //"15.3.2007"
*/

#ifndef MAIN_HEADER  //Prevents multiple includes
#define MAIN_HEADER

//#define USE_DEBUGMSG
#define CR_ODER_CRLF_DEFAULT        0    //0 = CR ONLY 1=CRLF->gsStatus.CRLF_CR_F
#define UART_ERRORMSG                1
//#define MSG                        0
//Timeout von LCD wird simuliert
#define COM_TX_ENABLED                1

#define DEGREE_FUNCTIONS_ENABLED       

#define SCAN_IDX_BY_START_DEFAULT        0  // 1
#define ZAHNRADGETRIEBE_VORHANDEN        1
#define MSG_SUPPRESS_DIRECTIVE            0 //1= unterdrücke zuviel Traffic in der Ausgabe
#define MSG_STOP_ENABLED                0
#define CMD_OK_ECHO_ENABLED                1
#define MSG_SUPPRESS_DIRECTIVE            0

#define FLOAT_PRAEDIGITS_MAX    5 // DIgits vor   /dtostrf(fVal,NUMMAX, DIGITS_MAX, gcaNumStr);
#define FLOAT_DIGITS_MAX        3 // DIgits nach //dtostrf(fVal,NUMMAX, DIGITS_MAX, gcaNumStr);
#define ASC_CR    13
#define ASC_LF    10

//COMMAND
#define DELIMITER        ','
#define DELIMITERSTR    ","
#define COMAMNDSIZEMAX  20



/*
IF ( ? : );
const char MCA_CRSTR[] PROGMEM = {13,0};
const char MCA_CRLFSTR[] PROGMEM = {13,10,0};
const char MCA_DELIMTERSTR[] PROGMEM = { ',',0 };
const char MCA_DELIMITER_MSG[] PROGMEM    = ",";
const char MCA_DPOINT_MSG[] PROGMEM = ":";
const char  MCA_SPACE_MSG[] PROGMEM    = " ";
*/

typedef struct
{
uint8_t IndexOK_F : 1; // gsStatus.IndexOK_F
uint8_t TargetSMPOS_Erreicht_F : 1;    //gsStatus.TargetSMPOS_Erreicht_F
uint8_t SMRUN_To_absoluteTarget_GradPOS_F : 1;    //gsStatus.SMRUN_To_absoluteTarget_GradPOS_F
uint8_t SM_NowSTOPed_Msg_F : 1; // gsStatus.SM_NowSTOPed_Msg_F  // Damit kein Text im Interrupt getriggert wird
uint8_t SM_Running_Msg_F : 1; // gsStatus.SM_Running_Msg_F  // Damit kein Text im Interrupt getriggert wird
uint8_t SM_NowOFF_F : 1; // gsStatus.SM_NowOFF_F  // Damit kein Text im Interrupt getriggert wird

uint8_t ScanIDX_Start_EnaF : 1; // gsStatus.ScanIDX_Start_EnaF
uint8_t ScanIndexRunning_F : 1; // gsStatus.ScanIndexRunning_F
uint8_t OptoKopplerActive_F : 1;    //gsStatus.OptoKopplerActive_F
uint8_t OptoKoppler_OLD_VAL_F : 1;    //gsStatus.OptoKoppler_OLD_VAL_F
uint8_t NewIndexFound_F : 1; // gsStatus.NewIndexFound_F
uint8_t TimeOut_F : 1;    //gsStatus.TimeOut_F
uint8_t TickEvent_F : 1; // gsStatus.TickEvent_F
uint8_t ComTraffic_F : 1; // gsStatus.ComTraffic_F
uint8_t CRLF_CR_F : 1;    //gsStatus.CRLF_CR_F
}STATUS_TYPE;
// gsStatus.

#define TICKS_PER_SECOND    250
#define SM_STEP_TIMEOUT (TICKS_PER_SECOND*3)
#define SM_DRIVE_FAST_TO_INDEX_TIMEOUT (TICKS_PER_SECOND *10)  //30
#define SM_IDX_SCAN_TIMEOUT (TICKS_PER_SECOND *40)  //30



//in STRUCT STEPMPARTYPE;
//#define STEPM_RAMPE_FLAG            0x04    // MIT_RAMPE, ?
//#define STEPM_START_RAMPE_FLAG        0x08    // 0 = Selected Counts, 1 = Countinous

//Flags
#define POSITION_STOP_ON_TARGET_MODE_FLAG    0x01   
#define POSITION_STOP_ON_TARGET_OK            0x02   
#define POSITION_STOP_ON_DISTANCE_MODE_FLAG    0x04   
#define POSITION_STOP_ON_DISTANCE_OK        0x08   
//gsStMPar.u8SM_PostionFlag

#define STEPM_RUN_FLAG                0x01    //Ohne RemainTime Zurücksetzung Run=Continue condtition
#define STEPM_ENABLE_FLAG            0x02    // 0 = OFF
#define STEPM_PULSE_MODE_FLAG        0x04    // 0 = OFF
#define STEPM_STOP_ACTIVE_FLAG        0x08    //STOP, BUT ENABLED, (STROM ON!!) Absicht!!, STEMotor StoptMode ..mit ICTRL, SPÄTER PWM, oder Automatische Disable nach Timeout.
#define STEPM_DIRECTION_FLAG        0x10    //Syncron zu  SM_DIR_LINKS/rechts d 0 = rechts ?? unbestimmt je nach verdrahtung
#define STEPM_TIMEOUT_ENABLE_FLAG    0x20    //After Stop Auto Disable after TIMEOUT
//    gsStMPar.u8StepMConditionFlag;    //ISTZUSTAND

//TYPEN DEKLARATION
typedef struct
    {
    float fStepMot_FRQ;   
    float fSCan_SM_FRQ;       
//    float fRampeFrq;        //Wird incrementiert bis == gsStMPar.fStepMot_FRQ für Rampe
   
    uint8_t ucSM_Mode;    //Full=1 Half  = 2
    uint16_t u16SM_HardwareBasisSteps; //=PREFDEF_STEPS_PER_ROTATION
    uint16_t uiStepsPerRotation; //200 ucSM_Mode * u16SM_HardwareBasisSteps=PREFDEF_STEPS_PER_ROTATION=    
    int16_t iIndexOffset;
    uint32_t ulStepM_Enable_TimeOut;    //Nach zu langer Stopzeit--Auto Timeout Release (Hitzeschutz)
    uint16_t uiScan_Index_Timeout;
    uint32_t u32SM_ActiveStartTime;
    uint32_t u32SMActiveStopTime;
    uint8_t u8StepMConditionFlag;    //ISTZUSTAND
    uint8_t u8SM_PostionFlag;
    //uint8_t ucCPUModeFlag;        //COM OUT enabled etc....
    //uint8_t ucSysModeFlag;   
    //uint16_t uiScan_Index_Timeout;
       
}STEPMPARTYPE;    //gsStMPar.



typedef struct
    {
    char caCmd[COMAMNDSIZEMAX +1];
    float fCmdVal_1;
    float fCmdVal_2;
    }COMMAND_TYPE;    //gsCmd

/*
typedef struct    //Bisher unbenutzt
    {
    uint8_t ucMenueLevel;
    uint8_t ucMenueFlag;
    }Menue_Type;
*/


//MECHANIK
#define ZAHNRAD_GROSS        40 //Zähne ?Mit Kommma wegen float type
#define ZAHNRAD_KLEIN        12 //Zähne ?Mit Kommma wegen float type
#define UNTERSETZUNGSVERHAELTNIS()    ((float)((float)ZAHNRAD_GROSS / (float)ZAHNRAD_KLEIN)) //3,3333333333333333333333333333333
#define FULLROT_DEGREE_360        360.0    //muss float sein


#define FULLSTEP_ANDPARSMAX 3    //& 4-1
#define HALFSTEP_ANDPARSMAX 7  //& 8-1   
#define MODE_FULLSTEP    1    //Multiplikator 1X. gsStMPar.u8StepMConditionFlag |=  MODE_FULLSTEP
#define MODE_HALFSTEP     2    //Multiplikator 2X. Set_StepMotor_Mode(gsStMPar.u8StepMConditionFlag & STEPM_STEPMODE_)

#define SM_ROTATIONS_FULLSTEPS    100 //FULLSTEP ( Ein ziemlch grober Motor )
#define SM_ROTATIONS_HALFSTEPS    200 //
//#define SM_ROTATIONS_FULLSTEPS    200 //FULLSTEP ( Ein ziemlch grober Motor )
//#define SM_ROTATIONS_HALFSTEPS    400 //

// Hardwareassignment
//#define XTAL_CPU           16000000UL    /* 16Mhz */
//F_CPU  in makefile !!!
#define UART_BAUD_RATE     9600            /* 9600 baud */
//F_CPU/1024 = 15625 Counts/Sec  !!!!
#define PULS_PER_SECOND_T1    15625  // 16^6 / 1024 = 15625
#define Time_Per_count_T1    0.000064        //  1/15625

//ICTRL via  BUZ11 wird ein Widerstand (2*4R7) Kurzgeschlossen was ON bedeuted
#define ICTRL_DDRX    DDRD
#define ICTRL_PORT    PORTD
#define ICTRL_PIN    _BV(PD6)
#define ICTRL_HIGHPWR()    (ICTRL_PORT |= ICTRL_PIN)
#define ICTRL_LOWPWR()    (ICTRL_PORT &= ~ICTRL_PIN)

//PORT_ASSIGMNEMTS
//#define ADC_PORT        PORTA
#define STEPCTRL_PORTX        PORTA
#define STEPAMP_ALLCTRL_MASK    0x3F    //0011 1111
#define STEPAMP_CTRL_MASK        0x0F    //0000 1111
#define STEPAMP_ENABLE_MASK        0x30    //0011 0000

// NEUE HARDWARE DEFINITIONEN
#define SENS_PORT_IN            PINC
#define SENS_OPTOKOPPLER_IDX    _BV(PC0) //PC0 0x01 bitmask
//MAKROS
#define READ_SENS_INDEX_ACTIVE_ISHIGH() (SENS_PORT_IN & SENS_OPTOKOPPLER_IDX)

//1=OUT  1011 1111 0x00
//1=pullup 0x0001 1000 
//PORT A
#define PORTA_OUTMASK STEPAMP_ALLCTRL_MASK
#define PORTA_PULLMASK 0x00
//#define

//PORT B
///( 1=OUT ) 0000 1000 = 0x08
#define PORTB_OUTMASK 0b01111111  //1111 1111    //ULN2803
#define PORTB_PULLMASK 0x00 //Nothing PullUp Vpr allem LCD Dat 7 = PB3 = LOW

//PORT C   //STEPAMPLIFIERE
#define PORTC_OUTMASK    0// ALLES IN
#define PORTC_PULLMASK    0

//PORT D
#define PORTD_OUTMASK  0b01000010  // ICTRL_PIN
#define PORTD_PULLMASK 0b10111101

// -------------------------------

#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_1024    0x05    //~61,035 PWM
#define TCCR0_CLK_256    ( _BV( CS22 ) | _BV( CS21 ) )    //244,14Hz PWM
#define TCCR0_CLK_64        0x03    //976,56Hz PWM
#define TCCR0_CLK_8        0x02    //7812 Hz PWM
#define TCCR0_CLK_0        0x01    //62500 PWM
#define TCCR0_CLK_STOP    0x00   


//MODUS COMAPARE 250 = 250/Sec
#define TCCR2_WGM_NORMAL    0x00
#define TCCR2_CTC_MODE        0x08 //0000 1000
#define TCCR2_COM_NORMALPORT    0x00
#define TCCR2_CLK_1024        ( _BV(CS22) | _BV(CS21) | _BV(CS20) )
#define TCCR2_CLK_256        ( _BV(CS22) | _BV(CS21) )
#define TCCR2_CLK_STOP        0x00
#define TCCR2_FASTPWM        0x48    //Mode 3
#define TCCR2_CS_BIST        0x0x    //Mode 3

//#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


//PORTB
#define MOSI_I         5//BIT5
#define MISO_0         6//BIT6
#define SCK_I          7//BIT7

//#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
//-----------------------

//TIMERS
//TIMER2  = is 61 miliseconds Timer ~approx.
// 16MhZ / 1024 / 256  = 61,03515625 Hz
// T= 1/f = 0.016384 ms / Interrupt
#define TIMER2_INT_FREQUENCY    250
#define ONE_SECOND_TICKS        250    //1/ TIMER2_INTPERIODE
#define LONG_10DELAY_TICKS        2500    //1/ TIMER2_INTPERIODE
#define SM_AFTERSTOPDELAY_TICKS 4  // 1000/250= 4= 1ms

//MASKENBITS
//INTERRUPT
#define INTx_INPORT    PIND
//#define INT1_MASK    0x08  //PD3
//#define INT0_MASK    0x04  //PD2
#define INT0_PIN_NR    PD2
//#define INT1_PIN_NR    PD3


#define WDTO_2S   7 //WatchDog

//DEFAULTS
//Depends on MotorType
//#defie ANGLE_PER_STEP 1.8  //(360/PREFDEF_STEPS_PER_ROTATION) //DEFAULT
//#defie ANGLE_PER_STEP 3.6  //(360/PREFDEF_STEPS_PER_ROTATION) //DEFAULT

#define PREDDEF_STEPMODE        MODE_HALFSTEP  //MODE_HALFSTEP
#define PREDEF_LOW_SPEED         25
#define PREDEF_HIFG_SPEED         100
#define PREDEF_MOTOR_ID_DEFAULT         1
#define PREDEF_STEPFREQUENZ             100.0    //Hz
#define PREDEF_SCAN_INDEX_FRQ             25.0    //Hz
#define PREDEF_RAMPENSSTARTFRQ            10.0    //Die Frq ab der überhaubt erst eine Rampe gefahren wird..
#define PREDEF_RAMP_RISE                 0    //Anstieg der RampenFrequenz
#define PREDEF_STEPCLOCKS                  1    //STEPS
#define PREDEF_STEPM_ENABLE_TIMEOUT_SEC    2500 // 2500/Sec  TIMER2_INTPERIODE 10SEC

#define PREDEF_SCANINDEX_TIMEOUT        25000    //100sec 4800 / 60 ~ 80 Sekunden

#define PREDEF_INDEX_OFFFSET    0    // WORK EINSTELLEN
//#define PREDEF_TARGET_X_DIFFERENCE_SPACE    1000

#define PREDEF_BIDIRECTION_MODE    0 // 0=MONO; 1= BiDir
//#define PREDEF_MOTOR_RUN_TIME         UNLIMITED_MOTOR_RUNTIME    //RERALZEIT IN SEC 600.0 /TIMER2_INTPERIODE (default)//  TIMER  10 MINUTEN


//DIRECTION
#define SM_DIR_RECHTS    0x00 //=PREDEF  SYNCRONzu STEPM_DIRECTION_FLAG
#define SM_DIR_LINKS    0x01 // SYNCRONzu STEPM_DIRECTION_FLAG
#define SM_DIR_DEFAULT     SM_DIR_RECHTS // SYNCRONzu STEPM_DIRECTION_FLAG

//Es wird unterschieden nach CTRL und Condition Flags

//STEP FRQ
#define FRQ_OFF    0
#define FRQ_ON    1


// Das muss größer sein als MotorONTime, sonst verhacken sich die Werte..
#define SCAN_INDEX_PULS_DELAY_MS 20 // 50aber 10* da delay nicht so lang ist
//in STRUCT STEPMPARTYPE;
//    uint8_t ucCPUModeFlag;        //COM OUT enabled etc....
//gsStMPar.ucCPUModeFlag
//#define CPUMODEFLAG_COMOUT_ENABLED    0x01    ///Com TX ENABLED

//gsStMPar.ucSysModeFlag
#define SYSTEM STATUS FLAGS
#define SYS_UART_TX_ENABLED            0x01    //übtragen der StartUpInformationen
#define SYS_INFORMATION_FLAG            0x02    //übtragen der StartUpInformationen

//GLOBALS DEFINITION       !!!!!!   USES RAM !!!!!
#define STRMAX        64 //früher 61 warum
#define RX_STRMAX        64 //früher 61 warum
//#define SEGMENTSTRMAX 31
//#define NUMMAX            5  //int 0..65535
#define NUMMAX                25 //100.000000  sprintf %f
//#define ORDERSIZE            3    //ABC,1234
//#define VALUEDISTANCE    4    //BEISPIEL SFQ,1000  --> 1000 = 4


//static STEPMPARTYPE gsStMPar;        //SPEICHERT DIE PARAMETER

//DELAYS und Verzögerungen // T= 1/f = 0.016384 ms / Interrupt TIMER2_INTPERIODE
// T= 1/f = 0.016384 ms / Interrupt
//#define TIMER2_INTPERIODE 0.016384 //BY EVERY OVERFLOW  **UNION = 1 Second !

//LCD_SECTION
#define LCD_8Bit_MODE_USED_IN_HEADER 1
#if LCD_8Bit_MODE_USED_IN_HEADER == 1

#define LCD_VALUE1_LINE        1
#define LCD_VALUE2_LINE        2
#define LCD_INFO_LINE        3
#define LCD_SHOW_CMD_LINE    4
#define LCD_NENUE_LINE        4

#define LCD_PINSWITCHDELAY_US    15 //10F mikro sec erforderlich !!zu Schnell; LCD GEHT NIchT MEHR !!
#define LCD_STARTDELAY_MS 1 //10F mikro sec erforderlich !!zu Schnell; LCD GEHT NIchT MEHR !!
#define LCD_INSTRCTIONS_DELAY_MS 4 //10 mikro sec erforderlich !!zu Schnell; LCD GEHT NIchT MEHR !!
#define LCD_AFTERRESETDELAY_US    60 //   mikro sec gerforderlich !!zu Schnell; LCD GEHT NIchT MEHR !!
#define LCD_DAT_IO_PORT     PORTC //=Port 6 Belegung f�r Daten
#define LCD_DAT_DIR_REG     DDRC
#define LCD_DAT_DIR_MASK     0XFF    //1111 1111
#define LCD_PORT              PORTD    //Hier nicht echte adr= 7 Belegung f�r Steuerung
#define LCD_CMD_DIR_REG     DDRD 
#define LCD_CMD_DIR_MASK    0b11000000    //1100 0000
//#define LCDSTRINGMAXCOUNT 33 //2 * 16 + \0
#define LCD_RS        7 //    //Canal xy, bit nn etc.
//#define LCD_RW    //dauerhaft auf GND = Writemode
#define LCD_E1        6 ///Canal xy, bit nn etc.
#define LCD_USED 1    //#endif sign
#define LCDLINEMAXCHAR        (20) // 20 + \0
#define LCDMAXLINES            (4) //
//Speicherordnung des LCD-Disp
//40Zeilig ist wie durchgeschnittene Zweizeilige, rest und angesetzt
//F�r 2_zeilige Anzeigen mit einem durchgehenden Speicher
#define LCD_2_ZEILIG_MEM_1_END 0x4F //Speicher geht weiter als bei 4 Zeiliger Ver
//F�r 4_zeilige Anzeigen mit 2 durchgehenden Speichern
#define LCD_MEM_START 0x00
#define LCD_4_ZEILIG_MEM_1_END     0x27
#define LCD_4_ZEILIG_MEM_2_START 0x40
#define LCD_4_ZEILIG_MEM_2_END     0x67
#define WRITE_DD_RAM 0x80 // Commandobit
#define LCD_ROW_ADR1 LCD_MEM_START
#define LCD_ROW_ADR2 LCD_4_ZEILIG_MEM_2_START
#define LCD_ROW_ADR3 (LCD_MEM_START+LCDLINEMAXCHAR)
#define LCD_ROW_ADR4 (LCD_4_ZEILIG_MEM_2_START+LCDLINEMAXCHAR)
#endif

//DELAY
//delay.h 8-bit count,
// 8-bit count, 3 cycles/loop  _delay_loop_1(uint8_t __count)
//16-bit count, 4 cycles/loop  _delay_loop_2(uint16_t __count)
//_delay_loop_1(); = 3 CYCLES
//_delay_loop_2(); = 4 CYCLES
//EIn Aufruf von _delay_loop_2 = 4 Cyclen lan = 0.00000025 = 0.250 NanoSecunden
#define OneCycletime    0.0000000625  // 1 / F_CPU
#define DELAYCYCLE_3    0.0000001875 //375ns für eine Pause //CPU_CYCLE_TIME *3 für 8 Bit
#define DELAYCYCLE_4     0.00000025 //500ns für eine!!! Pause= _delay_loop_2(1); //CPU_CYCLE_TIME *4 für 16Bit
// 500nS sind 8 * OneCycletime
//1ms= 16000 * OneCycletime
#define DELAY_1NS        4    //4 * 4 Cycles
#define DELAY_1000NS    4000 //()

//Prototypen
void UART_TXRX_Check(void);
void ResetRxBuff(void);
int32_t Round(double fIn);
void StartTimer2(void);    //0.1 Seconds  interrupt

float FloatZahlenRing(float fZahl, float fLimit );

char* FloatToNumStr(double fVal);
char* LongToNumStr(int32_t lVal);
char* ULongToNumStr(uint32_t lVal);

void Print_Str(const char* pStr);
void Print_StrCRLF(const char* pStr); //gsStatus.CRLF_CR_F

void Print_PStr(PGM_P pmStr);
void Print_PStrCRLF(PGM_P pmStr);

void PrintOK_CRLF(void);
void Print_CRLF_CR(void) ;

void PrintFloatCRLF(double fVal);
void PrintLongCRLF(int32_t lVal);
void PrintULongCRLF(uint16_t uiVal);

void CheckOrder(char* pcStr);

void Set_StepMotor_Mode(uint8_t ucVal);
void SetMotorDirection(uint8_t ucVal);
void Set_StepFRQ(float fVal);
void StepFRQ_OnOff(uint8_t uOnOff);
void StepMotorOn(void);
void StepMotorOff(void);
void StepMotorStop(void);
void SM_Run_Puls_DIR(uint32_t uiPuls, uint8_t ucDir);
void StartScan_SM_Index(void);

long CalcDegreeIn_SMPos(float fDegree);
float CalcPostionInDegree(long lPos);
void Run_To_SM_Absolute_GradTarget(float fBigWheel_Grad_Target );
void Calc_Shortest_GradPos_Direction(float fBW_Target_GradPos );

#endif  //MAIN_HEADER