Dependencies:   Led-libary TextLCD mbed

main.cpp

Committer:
ogris
Date:
2016-04-01
Revision:
18:d747cf2de3bf
Parent:
17:0e7af2d4cd63
Child:
19:b07fa9e47577

File content as of revision 18:d747cf2de3bf:

#include "mbed.h"
#include "WS2812B.h"
#include "TextLCD.h"


/*Todo list
switch case aktualisieren
Autoplay
Switchcase alle Funktionen einfügen
Menü prüfen, erweitern
(
        Farben Menü für alle Spieler fehlt //rgb einstellen -> spieler 2-4 fehlt
        Würfel-> Farbe vll bereits ein älteres Menü zu benutzen
        Würfel -> Farbverhalten gleich wie oben
)

*/



I2C i2c(P0_5,P0_4);
Serial port(P0_19,P0_18);
BusOut myled(P1_8,P1_9,P1_10,P1_11,P1_0,P1_1,P1_3,P1_4,P1_6,P1_7,P1_12,P1_13);
AnalogIn ldr(P0_12);
AnalogIn poti(P0_11);
//BusOut rgb(P0_9,P1_15,P0_21);

RGBOut rgb(P0_21,P0_9,P1_15);

InterruptIn Button0(P0_1);
InterruptIn Button1(P1_16);
InterruptIn Button2(P0_23);
InterruptIn Button3(P0_10);
InterruptIn Button4(P0_15);
BusIn btn(P1_16,P0_23,P0_10,P0_15,P0_1);

LedOut Feld (p6);//P6
LedOut Home (p7);//P7
LedOut Dice (p8);//P8
//-> Würfel (ersten 3 LED in Binär-4. LED für 7. Zustand), Spieler, Referenz(auch RGB am board)

TextLCD lcd(p21, p22, p23, p24, p25, p26,TextLCD::LCD20x4);

InterruptIn DD_A(p29);//P29
InterruptIn DD_B(p30);//P30
InterruptIn DD_C(p35);//P35
DigitalIn DD_D(p35);
BusIn DD(p29,p30);//P29,P30

//Dice
Timer Random;
Timer RandomDice;

Ticker DiceAnim;
void DiceRun();
void setDice(char number);
void DicePrint();
void DiceCal(); //umrechning des 7.Zustands in eine Zahl zwischen 1 & 6
char dicePos = 0;
char diceEn = 0;
char diceTick = 0;
char diceNum = 0;
int16_t diceDecode [7]= {0x1,0x88,0x89,0xAA,0xAB,0x1BA,0x154};
//Game
#define Feldgrose 10
#define Spieler 4
#define Steine 4

char PlayPos[Spieler*Steine];   //Zahl zwischen 0 & 47 ((0xC0 -> Spieler)>>2 / 0x03 -> Stein)
char Start[Spieler*Steine];           //Enthält den Index für PlayPos (nur das 'normale' Spielfend)
char Ziel[Spieler*Steine];            //Enthält den Index für PlayPos (nur das 'normale' Spielfend)
char Drann;                    //Spieler, der drann ist
char count;                    //Für 6er & mehrfaches Würfeln beim Ansetzen
char last[Spieler];            //zuletzt benutzte Spielstein, der zuletzt benutzt wurde
char moglich[Steine];
char selected;                 //der aktuell ausgewählte Zug
char Field[Spieler*Feldgrose]; //Enthält den Index für PlayPos (nur das 'normale' Spielfend)
void FieldPrint();             //Ausgabe auf Com-Port
void FieldGenerate();          //Berechnung von PlayPos auf Start, Ziel, Field
void FeldPrint();              //Ausgabe von Field auf den Led-Streifen (Feld) der Farben
void GameCal();
Ticker MoveAnim;
void MoveRun();
char MoveShow;
void ColorPrint(uint32_t color);
//Animations
char AnimField[Spieler*Feldgrose];
char AnimStart[Spieler*Steine];           
char AnimZiel[Spieler*Steine];
char AnimPos[Spieler*Steine];
char AnimDo; //Feld_Animieren,Start Animieren, Ziel Animierenw
void AnimCal();
//Core Interactions
void reset();
void MoveDo();
void moveNext();
void moveLast();
void DiceStart();
void DiceStop();
//Button entprellung (funktioniert nicht...)
void btn0();
void btn1();
void btn2();
void btn3();
void btn4();
char btnLast;
//Farben
uint32_t Farben[Spieler];      //Berechnete Hellichkeiten der Speiler fertig zur Ausgabe...
uint32_t Background = 0;       //Hintergrund (Leerfeld)
uint32_t DiseC = 0x00FF00;     //Würfelfarbe
void ColorPrint(uint32_t color); //vorher den Header senden (manuell...)

char DD_last;
char DD_d;

void dreh();
void druck();

void up();
void down();
void accept();
void exit();
void print_menu();
void print_pos();
void print_default();
void posUpdate();
char ausfuehren(uint32_t postion);

//string test ("");
//                                "1234567890123456789","1234567890123456789","1234567890123456789","1234567890123456789",  ,"1234567890123456789","1234567890123456789","1234567890123456789",
const char * const  text_ln0[] = {"MENU:              ","Spiel-Menu:        ","Anzeige-Menu:      ","Speicher-Menu:     ","ERROR              ","7.Zustand-Menu:    ","Farben-Menu:       ","Spiel-Menu:        ","Spielregeln-Menu:  ","Spielregeln-Menu:  ","Hell./Sp.Led-Menu: ","Config-Menu:       ","Autplay-zeit       ","Autplay-Menu:      ","Wurfel-Menu:       ","Ofline/Com-Menu:   ","Enable/Manuell     ","Farben             ","Helligkeit Wert    ","Sp.Led-Verhalten   ","Farbverhalten      ","Farbverhalten def  ","Helligkeit Wert    "};
const char * const  text_ln1[] = {"Spiel              ","7.Zustand          ","Farben             ","Spiel              ","                   ","Disable            ","                   ","Laden              ","Taktik 1           ","Smeiszwang <I/0>   ","Wert: <wert>       ","Laden              ","normal             ","Zeit               ","Farbverhalten      ","New                ","                   ","R:                 ","100%               ","Verhalten 1        ","fixe Farbe         ","Standart           ","100%               "};
const char * const  text_ln2[] = {"Anzeige            ","Spielregeln        ","Hellichkeit/Sp.Led ","Config.            ","                   ","kleinstmoglich     ","SP: 1   2   3   4  ","Speichern          ","Taktik 2           ","Go Home first <I/0>","Sp.Led-Verhalten   ","Speichern          ","x2                 ","Agro/Taktik        ","Farb def           ","Reset              ","                   ","G:                 ","75%                ","Verhalten 2        ","Spieler Farbe      ","erlaubt            ","75%                "};
const char * const  text_ln3[] = {"Speicher           ","Autoplay           ","Wurfel             ","Ofline/Com         ","                   ","grostmoglich       ","                   ","Reset              ","Taktik 3           ","Ausfahrzwang <I/0> ","Andert: <wert> fehl","Reset              ","x4                 ","Enable/Manuell     ","Hellichkeit        ","Com                ","                   ","B:                 ","50%b               ","Verhalten 3        ","3 Farben           ","verboten           ","50%                "};
char textPos[]                 = {0x0                  ,0x1                  ,0x2                  ,0x3                  ,0x4                  ,0x5                  ,0x6                  ,0x7                  ,0x4                  ,0x9                 ,0xA                  ,0xB                  ,0x4                  ,0xD                  ,0xE                  ,0xF                  ,0x10                  ,0x11                 ,0x12                 ,0x13                 ,0x14                 ,0x15                 ,0x16,0x17,0x18,0x19,0x12,0x1B,0x1C,0xC,0x14,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x11,0x27,0x28,0x29,0x13,0x2B,0x10,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x16,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F};

char VHS = 0;
char mSelected[256];
char depth = 0;
uint32_t postion = 0;//Dafür brauche ich die Methode
char mDiceEn = 5;


void btn0()
{
    if((btnLast&0x10)==(btn&0x10))
        return;
    else  
    {
        if((btn&0x10)>0)
            reset();
        else
            /*DoNothing*/;
    }
    btnLast=(btnLast&(0x1F-0x10))|(btn&0x10);
}

void btn1()
{
    if((btnLast&0x01)==(btn&0x01))
        return;
    else  
    {
        if((btn&0x01)>0)
            DiceStart();
        else
            DiceStop();
    }
    btnLast=(btnLast&(0x1F-0x01))|(btn&0x01);
}

void btn2()
{
    if((btnLast&0x02)==(btn&0x02))
        return;
    else  
    {
        if((btn&0x02)>0)
            moveNext();
        else
            /*DoNothing*/;
    }
    btnLast=(btnLast&(0x1F-0x02))|(btn&0x02);
}

void btn3()
{
    if((btnLast&0x04)==(btn&0x04))
        return;
    else  
    {
        if((btn&0x04)>0)
            moveLast();
        else
            /*DoNothing*/;
    }
    btnLast=(btnLast&(0x1F-0x04))|(btn&0x04);
}

void btn4()
{
    if((btnLast&0x08)==(btn&0x08))
        return;
    else  
    {
        if((btn&0x08)>0)
            MoveDo();
        else
            /*DoNothing*/;
    }
    btnLast=(btnLast&(0x1F-0x08))|(btn&0x08);
}

void reset()
{
    MoveAnim.detach();
    DiceAnim.detach();
    for(char i = 0;i<Spieler*Steine;i++)
        PlayPos[i]=i%4;
    for (char i = 0; i < Spieler; i++)
        last[i]=0; 
    Drann=0;
    diceEn=0; 
    myled = myled&0xF0F;
    DicePrint();
    rgb.set_RGB(0);
    FieldGenerate();
    FieldPrint();
    FeldPrint();
}

void Control()
{
    while(port.readable ())
    {
        char message = port.getc();
        switch(message)
        {
            case '1':
            setDice(1);
            break;
            case '2':
            setDice(2);
            break;
            case '3':
            setDice(3);
            break;
            case '4':
            setDice(4);
            break;
            case '5':
            setDice(5);
            break;
            case '6':
            setDice(6);
            break;
            case '7':
            setDice(7);
            break;
            case 'A':
            DiceStart();
            break;
            case 'a':
            DiceStop();
            break;
            case 'B':
            moveNext();
            break;
            case 'C':
            moveLast();
            break;
            case 'D':
            MoveDo();
            break;
            case 'E':
                exit();
            break;
            case 'F':
                up();
            break;
            case 'G':
                down();
            break;
            case 'H':
                accept();
            break;
            case 'I':
                depth=0;
                mSelected[0]=0;
                print_default();
                mDiceEn=5;
                reset();
            break;
        }
    }
}

int main() 
{
    Random.start();
    //Random.stop();
    //Random.read_us();
    
    //Ticker:
    //.attach(&main,[sek]);
    //.attach_us(&main,[micro-sec]);
    //.detach();
    Button0.mode(PullDown);
    Button1.mode(PullDown);
    Button2.mode(PullDown);
    Button3.mode(PullDown);
    Button4.mode(PullDown);
    
    DD_A.mode(PullDown);
    DD_B.mode(PullDown);
    DD_C.mode(PullDown);
    
    wait(0.01);
    
    DD_A.rise(&dreh);
    DD_A.fall(&dreh);
    DD_B.rise(&dreh);
    DD_B.fall(&dreh);
    DD_C.rise(&druck);
    DD_C.fall(&druck);
    DD_last = DD;
    DD_d=DD_D;

    Button0.rise(&reset);
    Button1.rise(&btn1);
    Button1.fall(&btn1);
    Button2.rise(&btn2);
    Button2.fall(&btn2);
    Button3.rise(&btn3);
    Button3.fall(&btn3);
    Button4.rise(&btn4);
    Button4.fall(&btn4);

    //myled = 0xFFF;
    port.baud(76800);
    port.format(8,Serial::None, 1); 
    port.attach(&Control);
    /*
    Farben[0]=0x00FF00;//Rot
    Farben[1]=0xFF0000;//Blau
    Farben[2]=0x0000FF;//Grun
    Farben[3]=0x00FFFF;//Gelb
    Background = 0;    //Schwarz
    DiseC = 0x00FF00;  //Rot
    */
    Farben[0]=0x000800;//Rot
    Farben[1]=0x080000;//Blau
    Farben[2]=0x000008;//Grun
    Farben[3]=0x000808;//Gelb
    Background = 0;    //Schwarz
    DiseC = 0x000800;  //Rot
    /*
    Farben[0]=0xFFFFFF;//Weiß
    Farben[1]=0xFFFFFF;//Weiß
    Farben[2]=0xFFFFFF;//Weiß
    Farben[3]=0xFFFFFF;//Weiß
    Background = 0xFFFFFF;//Weiß
    DiseC = 0xFFFFFF;  //Weiß
    */

    __disable_irq();
    for(char i = 0;i<Spieler;i++)
    {
        Feld.WriteLed(Farben[i]);
        for(char j = 0;j<Feldgrose-1;j++)
            if((j==(Feldgrose-2))&(i==(Spieler-1)))
                Feld.WriteLed(0xFFFFFF);
            else
                Feld.WriteLed(Background);
    }
    __enable_irq();
    //reset();
    print_default();
    while(1) ;        
}

void DiceStart()
{
    if(diceEn==0)
    {
    RandomDice.start();
    DiceAnim.attach(&DiceRun,0.1);
    diceEn = 1;
    diceTick = 1;
    DicePrint();
    }
}

void DiceStop()
{
    if(diceEn==1)
    {
        if(RandomDice.read_us()> 200)
        {
            DiceAnim.detach();
            diceEn = 2;
            diceTick = 0;
            diceNum = Random.read_us()%7;
            diceNum = (RandomDice.read_us()+diceNum)%7+1;
            RandomDice.stop();
            RandomDice.reset();
            if(diceNum>=7)
                DiceCal();
            //port.printf("LDiceNum:%d\n",diceNum);
            DicePrint();
            GameCal();
        }
    }
}

void DiceCal()
{
    if((diceEn==2)||(diceEn==3))
    {
        if(diceNum>7)
            diceNum=7;
        if(diceNum==7)
        {
            diceEn=3;
            for(char i = 0;i<Steine;i++)
                if((PlayPos[(Drann<<2)|i]>3)&&(PlayPos[(Drann<<2)|i] < 44))
                    for(char j = 1;j<=6;j++)
                    {
                        char temp = Field[(PlayPos[(Drann<<2)|i]- Steine + Feldgrose * Drann+j) % (Feldgrose*Steine)];
                        if(temp>0)
                        {
                            temp--; //(Spieler<<2)|Stein
                            temp = (temp&0xC)>>2;//Spieler
                            if(temp!=Drann)
                                if(j<diceNum)
                                    diceNum=j;
                        }
                    }
            //PlayPos[(Drann<<2)|i] im Feld suchen, weiter setzen, wenn treffer, der kleiner als diceNum ->setzen von diceNum
        }//DiceNum == 7
        if(diceNum==7)
            diceNum=6;
        //port.printf("LdiceNum:%d\n",diceNum);
    }
}

void setDice(char number)
{
    if(diceEn==4)
    {
        port.printf("LWarning: diceEn:%d -> Game over\n",diceEn);
    }
    else if(diceEn<4)
    {
        port.printf("LdiceEn:%d\n",diceEn);
        if(diceEn==1)
        {
            DiceAnim.detach();
            diceTick = 0;
            RandomDice.stop();
            RandomDice.reset();
        }
        diceEn = 2;
        diceNum = number;
        if(diceNum>=7)
            DiceCal();
        //port.printf("LForceDice:%d\n",diceNum);
        DicePrint();
        GameCal();
    }
}

void DiceRun()
{
    if(diceTick)
    {
        diceTick=0;
        if(dicePos<7)
            dicePos++;
        else
            dicePos=0;
        }
    else
        diceTick=1;
    DicePrint();
}

void DicePrint()
{
    switch(diceEn)
    {
        case 0: //Schwarz & Drann überschreiben...
        myled=(myled&0xFF0);
        myled=(myled&0x0FF)|(0x100<<Drann);
        port.printf("W%c%c\n",27,27);
        break;
        case 1: //Animation
        char dice_help = 0xFF-(1<<dicePos);
        myled=(myled&0xFF0)|(5)|(diceTick<<1);
        //myled = (myled&0xF)|(dice_help<<4);
        
        port.printf("W%c%c\n" , 27 + diceTick+((dice_help&0x1F)<<1),27 + ((dice_help& 0xE0)>>5));
        break;
        case 2://Case 3 = Case 2 ->Anzeigen
        myled=(myled&0xFF0)|(diceNum);
        //myled=myled|0xFF0;
        
        port.printf("W%c%c\n" , 27 +(diceDecode[diceNum-1]&0x3F),27 + ((diceDecode[diceNum-1]&0x1C0)>>6));
        break;
        case 3:
        myled=(myled&0xFF0)|(diceNum)|8;
        //myled=myled|0xFF0;
        
        port.printf("W%c%c\n" , 27 +(diceDecode[diceNum-1]&0x3F),27 + ((diceDecode[diceNum-1]&0x1C0)>>6));
        break;
        case 4://Spiel beendet! Animation?
        myled=(myled&0xFF0);
        port.printf("W%c%c\n",27,27);
        break;
        case 5://Menu
        break;
    }
}

void FieldGenerate()
{
    for(char i = 0; i<Spieler*Feldgrose;i++)
        Field[i]=0; //Feld zurücksetzen
    for (char i = 0; i < Spieler*Steine; i++)
    {
        Ziel[i]=0;
        Start[i]=0;
    }
        
    for(char i = 0; i<Spieler;i++)
        for(char j = 0; j<Steine;j++)
        {
            if (PlayPos[(i<<2)|j] >= Steine)
            {
                if (PlayPos[(i<<2)|j] >= (Spieler * Feldgrose + Steine))
                {
                    //if (PlayPos[(i<<2)|j] < Steine * Feldgrose+Steine*2)
                        Ziel[(PlayPos[(i<<2)|j] - (Spieler * Feldgrose + Steine))|(i<<2)] = ((i<<2)|j) + 1;
                        //Ziel PlayPos[(i<<2)|j] - 44
                }
                else
                    Field[(PlayPos[(i<<2)|j]- Steine + Feldgrose * i) % (Steine * Feldgrose)] = ((i<<2)|j) + 1;
                    //Feld (PlayPos[(i<<2)|j]- 4 + 10 * i) % 40
            }
            else
                Start[PlayPos[(i<<2)|j]|(i<<2)] = ((i<<2)|j)+1;
                //start PlayPos[(i<<2)|j]
        }
}

void FieldPrint()
{
    port.printf("F");
    for(char i = 0;i<Spieler*Steine;i++)
    {
        port.printf("%c",27+PlayPos[i]);
    }
    port.printf("\n");
}

void FeldPrint()
{
    __disable_irq();
    for(char i = 0;i<Spieler*Feldgrose;i++)
        if(Field[i]>0)
            Feld.WriteLed(Farben[((Field[i]- 1)&0x0C)>>2]);
        else
            Feld.WriteLed(Background);
    //char Start[Spieler];
    //char Ziel[Spieler];
    char i = 0;
    char j = 0;
    while(i < Steine*Spieler)
    {
        if(Start[i]>0)
            Home.WriteLed(Farben[((Start[i]- 1)&0x0C)>>2]);
        else
            Home.WriteLed(Background);
        i++;
    }
    do
    {
        if(Ziel[j]>0)
            Home.WriteLed(Farben[((Ziel[j]- 1)&0x0C)>>2]);
        else
            Home.WriteLed(Background);
        j++;
    }while(j < Steine*Spieler);
    __enable_irq();
}

void AnimCal()
{
    for(char i = 0; i<Spieler*Feldgrose;i++)
        AnimField[i]=0; //Feld zurücksetzen
    for (char i = 0; i < Spieler*Steine; i++)
    {
        AnimZiel[i]=0;
        AnimStart[i]=0;
    }
    AnimDo=0;//Feld_Animieren,Start Animieren, Ziel Animieren

    //char AnimDo; //Feld_Animieren,Start Animieren, Ziel Animierenw

    for (char i = 0; i < Spieler*Steine; i++) //Hauptschleife
        if(i==((Drann<<2)|selected))
        {
            if(moglich[selected]==1)
            {
                if(PlayPos[i]<Steine) //nicht Draußsen
                {
                    AnimDo = AnimDo|3;//Feld&Start
                    AnimPos[i] = Steine; //Ausfahren
                    char temp = Field[Drann*Feldgrose]; //Ansetzfeld wird analysiert
                    if(temp>0)
                    {
                        //myled = myled|temp<<8;
                        temp--; //(Spieler<<2)|Stein
                        AnimPos[temp] = (temp & 0x03); //rücksetzung des Feldes...
                    }
                }
                else //Draußen
                {
                    AnimDo = AnimDo|1; //Feld
                    AnimPos[i] = PlayPos[i]+diceNum;; //Weitersetzen
                    //PlayPos[(Drann<<2)|selected]
                    if(AnimPos[i]<Steine+Spieler*Feldgrose) //noch nicht drinnen
                    {
                        //Field>0
                        char temp = Field[ (AnimPos[i]-Steine+Feldgrose*Drann) % (Feldgrose*Steine) ];
                        if(temp>0)
                        {
                            AnimDo = AnimDo|3;//Feld&Start
                            //myled = myled|temp<<8;
                            temp--; //(Spieler<<2)|Stein
                            AnimPos[temp] = (temp & 0x03); //rücksetzung des Feldes...
                        }
                    }
                    else
                        AnimDo=AnimDo|7;//Feld&Ziel (Start auch wegen Hardware)
                }
            }
            else
                AnimPos[i] = PlayPos[i]; //Spieler-pos Kopieren, weil es nicht möglich ist...
        }
        else
            AnimPos[i] = PlayPos[i]; //Spieler-pos Kopieren
    //FieldGenerate -> Anim...
    for(char i = 0; i<Spieler;i++)
        for(char j = 0; j<Steine;j++)
        {
            if (AnimPos[(i<<2)|j] >= Steine)
            {
                if (AnimPos[(i<<2)|j] >= (Spieler * Feldgrose + Steine))
                {
                    //if (AnimPos[(i<<2)|j] < Steine * Feldgrose+Steine*2)
                        AnimZiel[(AnimPos[(i<<2)|j] - (Spieler * Feldgrose + Steine))|(i<<2)] = ((i<<2)|j) + 1;
                        //AnimZiel AnimPos[(i<<2)|j] - 44
                }
                else
                    AnimField[(AnimPos[(i<<2)|j]- Steine + Feldgrose * i) % (Steine * Feldgrose)] = ((i<<2)|j) + 1;
                    //Feld (AnimPos[(i<<2)|j]- 4 + 10 * i) % 40
            }
            else
                AnimStart[AnimPos[(i<<2)|j]|(i<<2)] = ((i<<2)|j)+1;
                //start AnimPos[(i<<2)|j]
        }
}

void MoveRun() //Animation (zyklisch)
{
    if(MoveShow)
        MoveShow = 0;
    else
        MoveShow = 1;

    if(MoveShow>0)
    {
        port.printf("F");
        for(char i = 0;i<Spieler*Steine;i++)
        {
            port.printf("%c",27+AnimPos[i]);
        }
        port.printf("\n");
        
        __disable_irq();
        if((AnimDo&1)>0)
        {
            for(char i = 0;i<Spieler*Feldgrose;i++)
                if(AnimField[i]>0)
                    Feld.WriteLed(Farben[((AnimField[i]- 1)&0x0C)>>2]);
                else
                    Feld.WriteLed(Background);
        }
        //char Start[Spieler];
        //char Ziel[Spieler];
        char i = 0;
        char j = 0;
        if((AnimDo&2)>0)
        {
            while(i < Steine*Spieler)
            {
                if(AnimStart[i]>0)
                    Home.WriteLed(Farben[((AnimStart[i]- 1)&0x0C)>>2]);
                else
                    Home.WriteLed(Background);
                i++;
            }
        }
        if((AnimDo&4)>0)
        {
            do
            {
                if(AnimZiel[j]>0)
                    Home.WriteLed(Farben[((AnimZiel[j]- 1)&0x0C)>>2]);
                else
                    Home.WriteLed(Background);
                j++;
            }while(j < Steine*Spieler);
        }
        __enable_irq();
    }
    else
    {
        FieldPrint();
        __disable_irq();
        if((AnimDo&1)>0)
        {
            for(char i = 0;i<Spieler*Feldgrose;i++)
                if(Field[i]>0)
                    Feld.WriteLed(Farben[((Field[i]- 1)&0x0C)>>2]);
                else
                    Feld.WriteLed(Background);
        }
        //char Start[Spieler];
        //char Ziel[Spieler];
        char i = 0;
        char j = 0;
        if((AnimDo&2)>0)
        {
            while(i < Steine*Spieler)
            {
                if(Start[i]>0)
                    Home.WriteLed(Farben[((Start[i]- 1)&0x0C)>>2]);
                else
                    Home.WriteLed(Background);
                i++;
            }
        }
        if((AnimDo&4)>0)
        {
            do
            {
                if(Ziel[j]>0)
                    Home.WriteLed(Farben[((Ziel[j]- 1)&0x0C)>>2]);
                else
                    Home.WriteLed(Background);
                j++;
            }while(j < Steine*Spieler);
        }
        __enable_irq();
    }
}

void moveNext()
{
    selected = (selected+1)%Steine;
    for(char i = 0;i<Steine;i++)
        if(moglich[selected]>0)
            break;
        else
            selected = (selected+1)%Steine;
    AnimCal();
}

void moveLast()
{
    selected = (selected+3)%Steine;
    for(char i = 0;i<Steine;i++)
        if(moglich[selected]>0)
            break;
        else
            selected = (selected+3)%Steine;
    AnimCal();
}

void GameCal()
{
    char drausen = 0; //Ziel
    char feld = 0;
    char drinnen = 0; //start
    char moglichAny = 1;
    for(char i = 0;i<Steine;i++)
    {
        if(PlayPos[(Drann<<2)|i]>=Steine)
        {
            if(PlayPos[(Drann<<2)|i] >= (Steine+Spieler*Feldgrose))
                drausen++;
            else
                feld++;
        }
        else
            drinnen++;
        moglich[i]=0;
    }
    //Berechnung
    //Ausfahren:
    //drinnen >0 (Noch Spieler drinnen?)
    //Startfeld ist von Spieler belegt
    //Ziel ist frei
    if((drinnen>0)&&(moglichAny))
    {
        //port.printf("LDrinnen\n");
        if(((((Field[Feldgrose*Drann]-1) &0x0C) >>2)==Drann)&&(Field[Feldgrose*Drann]>0))
        {
            //port.printf("LAusfahrt Belegt\n");
            if(((((Field[(Feldgrose*Drann+diceNum)%(Feldgrose*Spieler)]-1) &0x0C) >>2)!=Drann)||(Field[(Feldgrose*Drann+diceNum)%(Feldgrose*Spieler)]==0))
            {
                //port.printf("LZiel frei (Done)\n");
                moglich[(Field[Feldgrose*Drann]-1) &0x03] = 1;
                moglichAny=0;
            }
        }
    }
    
    //Ansetzen
    // 6 gewürfelt
    //drinnen>0
    //Start-feld ist nicht von Spieler belegt
    if((drinnen>0)&&(moglichAny)&&(diceNum==6))
    {
        //port.printf("LDrinnen & 6 \n");
        if(((((Field[Feldgrose*Drann]-1) &0x0C) >>2)!=Drann)||(Field[Feldgrose*Drann]==0))
        {
            //port.printf("LAusfahrt frei (Done...Schleife)\n");
            moglichAny=0;
            for(char i = 0;i<Steine;i++)
                if(PlayPos[(Drann<<2)|i]<Steine)
                    moglich[i]=1;
        }
    }
    
    //Fahren
    if(moglichAny)
    {
        //port.printf("LNormal...\n");
        for(char i = 0;i<Steine;i++)
        {
            if(PlayPos[(Drann<<2)|i]>=Spieler) //Drausen
            {
                if((PlayPos[(Drann<<2)|i]+diceNum) < (Steine+Feldgrose*Spieler))//Zeil noch am Feld
                {
                    char temp = Field[(PlayPos[(Drann<<2)|i]- Steine + Feldgrose * Drann+diceNum) % (Feldgrose*Steine)]; //zielfeld
                    if(temp>0)
                    {
                        //myled = myled|temp<<8;
                        temp--; //(Spieler<<2)|Stein
                        temp = (temp&0xC)>>2;//Spieler
                        if(temp!=Drann)     //zielfeld ist nicht ich
                            moglich[i]=1;
                    }
                    else//Feld ist leer
                        moglich[i]=1;
                }
                else
                {//Kollisionsberechnung ins Ziel...
                    if((PlayPos[(Drann<<2)|i]+diceNum)<(Steine*2+ Feldgrose*Spieler))//Schiest nicht über das Ziel hinaus...
                        if(Ziel[(PlayPos[(Drann<<2)|i]-(Steine+Feldgrose*Spieler)+diceNum)|(Drann<<2)]==0)//Zielfeld ist leer (enthält ja nur mich)
                            moglich[i]=1;
                }
            }
        }
    }
        

    //Anzeigen der Möglichkeiten & überhaupt möglich?
    moglichAny=0;
    myled = myled&0xF0F;
    for(char i = 0;i<Steine;i++)
    {
        myled = myled|(moglich[i]<<i+4);
        moglichAny = moglichAny | moglich[i];
    }

    if(moglichAny) //Fahren möglich
    {
        selected = (last[Drann]+Steine-1)%Steine;
        moveNext();
        MoveAnim.attach(&MoveRun,0.3);
    }
    else //Fahren nicht möglich
    {
        if(feld<=0) //keine am Feld
        {
            if(count<2)
            {
                diceEn=0;
                count++;
                port.printf("LCount: %d\n",count);
            }
        }
        else //Fahren nicht möglich,spieler am Feld & 6 gewürfelt
        {
            if(diceNum==6)
                diceEn=0;
        }
    }
}

void MoveDo()
{
    if((diceEn>1)&&(diceEn<4))
    {
        if(moglich[selected]==1)
        {
            if(PlayPos[(Drann<<2)|selected]<Steine) //nicht Draußsen
            {
                PlayPos[(Drann<<2)|selected] = Steine; //Ausfahren
                char temp = Field[Drann*Feldgrose]; //Ansetzfeld wird analysiert
                if(temp>0)
                {
                    //myled = myled|temp<<8;
                    temp--; //(Spieler<<2)|Stein
                    PlayPos[temp] = (temp & 0x03); //rücksetzung des Feldes...
                }
            }
            else //Draußen
            {
                PlayPos[(Drann<<2)|selected] += diceNum; //Weitersetzen
                //PlayPos[(Drann<<2)|selected]
                if(PlayPos[(Drann<<2)|selected]<Steine+Spieler*Feldgrose) //noch nicht drinnen
                {
                    //Field>0
                    char temp = Field[ ( PlayPos[(Drann<<2)|selected] - Steine + (Feldgrose * Drann) ) % (Feldgrose*Steine) ];
                    if(temp>0)
                    {
                        //myled = myled|temp<<8;
                        temp--; //(Spieler<<2)|Stein
                        PlayPos[temp] = (temp & 0x03); //rücksetzung des Feldes...
                    }
                }
            }
            //else //nicht möglich
            
        }
        MoveAnim.detach();
        last[Drann]=selected;
        myled = myled&0xF0F;
        count = 0;
        FieldGenerate();
        //Check for Win!
        char temp = 0;
        char j = 0;
        char running = 1;
        do
        {
            temp = 0;
            for (char i = 0; i < Steine; i++)
                if (Ziel[(Drann<<2)|i]>0)
                    temp++;
            if((temp>=4)&&(diceEn>1))
                port.printf("LSpieler %d hat das Spiel beendet!\n",Drann);
            if(temp==4)
                Drann = (Drann+1)%Spieler;
            else
            {
                if(j==0)
                {
                    if(diceNum<6)
                        Drann = (Drann+1)%Spieler;
                    else
                        running = 0;
                }
                else
                    running = 0;
                
            }
            diceEn = 0;
            j++;
        }while((j<=Spieler)&(running>0));
        if(running==1)
        {
            port.printf("LSpiel beendet!\n");
            diceEn = 4;
        }
        DicePrint();
        FieldPrint();
        FeldPrint();
        port.printf("LDrann:%d\n",Drann);
    }
}

void ColorPrint(uint32_t color)
{
    port.printf("%c%c%c%c\n",27+((color&0xFC0000)>>18),27+((color&0x03f000)>>12),27+((color&0x000FC0)>>6),27+(color&0x00003F));
}

//http://www.repairfaq.org/REPAIR/F_SNES.html

void dreh()
{
    char temp = DD;
    if(DD_last == 3)
    { 
        if(temp == 0)
            DD_last = 0;
    }
    else
    {
        if(temp == 3)
        {
            if(DD_last == 1)
                up();
            if(DD_last == 2)
                down();
        }
        DD_last = temp;
    }
}

void druck()
{
    if(DD_D==DD_d)
        return;
    else  if(DD_D)
        accept();
    DD_d=DD_D;
}

char ausfuehren(uint32_t postion)
{
    char out = 1;//0 ende der postion
    VHS = 0;
    switch (postion)
    {
        case 0x15:
            out = 0;
            //zustand 7 aendern
            break;
        case 0x25:
            out = 0;
            //zustand kleinstmöglicher zustand
            break;
        case 0x35:
            out = 0;
            //zustand groestmoeglich
            break;
        case 0x19:
            out = 0;
            //schmeisszwang
            break;
        case 0x29:
            out = 0;
            //go home first
            break;
        case 0x39:
            out = 0;
            //ausfahrzwang
            break;
        case 0x17:
            out = 0;
            //Spiel-Menü:laden
            break;
        case 0x27:
            out = 0;
            //Spiel-Menü:speichern
            break;
        case 0x37:
            out = 0;
            //Spiel-Menü:reset
            break;
        case 0x1b:
            out = 0;
            //Config:laden
            break;
        case 0x2b:
            out = 0;
            //Config:speichern
            break;
        case 0x3b:
            out = 0;
            //Config:reset
            break;
        case 0x1f:
            out = 0;
            //Offline:new
            break;
        case 0x2f:
            out = 0;
            //Offline:reset
            break;
        case 0x3f:
            out = 0;
            //Offline:com
            break;
        case 0x6:
            VHS = 1;
            break;
        
    default:
        break;
    }
    return out;
}

void posUpdate()
{
    postion = 0;
    for(char i = 0;i<depth-1;i++)
        postion = postion|(mSelected[i]<<(i*2));
}

void up()
{
    if(depth>0)
    {
        if(mSelected[depth-1]<1)
        {
            if(VHS==0)
                mSelected[depth-1]=3;
            else if(VHS==1)
                mSelected[depth-1]=4;
            else
                mSelected[depth-1]=VHS;
        }
        else
            mSelected[depth-1]--;
        print_pos();
    }
}

void down()
{
    if(depth>0)
    {
        char temp=3;
        if(VHS==0)
            temp=3;
        else if(VHS==1)
            temp=4;
        else
            temp=VHS;
        if(mSelected[depth-1]>(temp-1))
            mSelected[depth-1]=0;
        else
            mSelected[depth-1]++;
        print_pos();
    }
}

void accept()
{
    if(depth>0)
    {
        postion = 0;
        for(char i = 0;i<depth;i++)
            postion = postion|(mSelected[i]<<(i*2));
        char temp = ausfuehren(postion);
        if(temp>0)
        {
            if(mSelected[depth-1]==0)
            {
                exit();
                return;
            }
            else
            {
                mSelected[depth]=1;
                depth++;
            }
        }
    }
    else
    {
        depth=1;
        mDiceEn = diceEn;
        if(mDiceEn==1)
        {
            DiceAnim.detach();
            diceTick = 0;
            RandomDice.stop();
            mDiceEn=0;
        }
        if((mDiceEn==2)||(mDiceEn==3))
        {
            MoveAnim.detach();
            MoveShow = 1;
            MoveRun();
        }
        diceEn=5;
        DicePrint();
        //StartMenu-Anim
    }
    posUpdate();
    port.printf("Lpostion:0x%x\n",postion);
    if(depth>0)
    {
        print_menu();
        print_pos();
    }
    else
        print_default();
}

void exit()
{
    if(depth>0)
    {
        depth--;
        mSelected[depth]=0;
    }
    if(depth==0)
    {
        if(mDiceEn<5)
        {
            diceEn=mDiceEn;
            if((mDiceEn==2)||(mDiceEn==3))
                MoveAnim.attach(&MoveRun,0.3);
            mDiceEn=5;
        }
    }
    posUpdate();
    ausfuehren(postion);
    if(depth>0)
    {
        print_menu();
        print_pos();
    }
    else
        print_default();
}

void print_menu()
{
    port.printf("DR\n");
    lcd.cls();
    lcd.locate(1,0);
    lcd.printf(text_ln0[textPos[postion]]);
    port.printf("D%c%c%s\n",28,27,text_ln0[textPos[postion]]);
    lcd.locate(1,1);
    lcd.printf(text_ln1[textPos[postion]]);
    port.printf("D%c%c%s\n",28,28,text_ln1[textPos[postion]]);
    lcd.locate(1,2);
    lcd.printf(text_ln2[textPos[postion]]);
    port.printf("D%c%c%s\n",28,29,text_ln2[textPos[postion]]);
    lcd.locate(1,3);
    lcd.printf(text_ln3[textPos[postion]]);
    port.printf("D%c%c%s\n",28,30,text_ln3[textPos[postion]]);
}

void print_pos()
{
    if (VHS==1)
    {
        lcd.locate(0,3);
        //         "--------------------"
        lcd.printf("                    ");
        port.printf("D%c%c                    \n",27,27+3);

        lcd.locate(0,0);
        if(mSelected[depth-1]==0)
        {
            port.printf("D%c%c<\n",27,27);
            lcd.putc('<');
        }
        else
        {
            port.printf("D%c%c \n",27,27);
            lcd.putc(' ');

            lcd.locate(4*mSelected[depth-1],3);
            lcd.putc('^');
            port.printf("D%c%c^\n",27+4*mSelected[depth-1],27+3);
        }
    }
    else
    {
        for(char i=0;i<4;i++)
        {
            lcd.locate(0,i);
            if((mSelected[depth-1]+0)==i)
            {
                if(i==0)
                {
                    port.printf("D%c%c<\n",27,i+27);
                    lcd.putc('<');
                }
                else
                {
                    port.printf("D%c%c>\n",27,i+27);
                    lcd.putc('>');
                }
            }
            else
            {
                port.printf("D%c%c \n",27,i+27);
                lcd.putc(' ');
            }
        }
    }
}

void print_default()
{
    lcd.cls();
        lcd.printf(" Spiel lauft...");
        lcd.locate(0,3);
        lcd.printf("12345678901234567890");
        port.printf("D%c%c Spiel lauft...     \n",27,27);
        port.printf("D%c%c                    \n",27,28);
        port.printf("D%c%c                    \n",27,29);
        port.printf("D%c%c12345678901234567890\n",27,30);
}