void FillPrevStateEndTime(void)
{
    if ( Get_DateTime(&Status.CurDateTime) )
    {
        PrevStateEnd_FullSec = ((Status.CurDateTime.hour*60UL) + Status.CurDateTime.min)*60UL + Status.CurDateTime.sec;
    }
    else
    {
        PrevStateEnd_FullSec = -1;
    }
}
void SwitchToRed(void)
{
    TDateTime DT;
    int32 NowFullSec;
    int32 CurLearn_sec;
    int   i;

    StopSound();

    DigMask = 0;

    if ( Get_DateTime(&DT) )
    {
        NowFullSec = ((DT.hour*60UL) + DT.min)*60UL + DT.sec;

        if (NowFullSec < PrevStateEnd_FullSec)
        {
            NowFullSec += 24*60*60UL; // + 1 day
        }
    }
    else
    {
        NowFullSec = -1;
    }

    if ( ((NowFullSec-PrevStateEnd_FullSec) >= OFF_LIMIT_SEC) || (PrevState != RED_STATE) )
    {
        // New Light
        //if ( ((RTime-RTime_prev) <= TIME_MAX_DELTA) && ((RTime-RTime_prev) >= -TIME_MAX_DELTA) )
        //{
        //    RStablePeriods++;
        //}
        //else
        //{
        //    RStablePeriods = 0;
        //}

        // Rounding Algorithm
        if ( RmsecCounter >= (1000-RRoundUpValue) )
        {
            RTime_sec++;
        }

        //if (RmsecCounter <= ROUND_DOWN_TIME)
        //{
        //    RTime -= RmsecCounter;
        //}

        //--------------------
        // Smart1 Learn Algorithm
        /*
        // Put Data To Buffer
        for (i=1; i<LEARN_BUF_SIZE; i++)
            LearnData.RLearnBuf[i-1] = LearnData.RLearnBuf[i];

        LearnData.RLearnBuf[LEARN_BUF_SIZE-1] = RTime_sec;

        if (LearnData.RLearnState == LEARNING_NOW)
        {
            LearnData.RLearnPeriod = FindPeriod2(&LearnData.RLearnBuf[0]);
            if (LearnData.RLearnPeriod)
            {
                LearnData.RLearnState = LEARN_FINISHED;
                LearnData.RLearnIndex = LEARN_BUF_SIZE - LearnData.RLearnPeriod;
            }
        }
        else
        {
            CurLearn_sec = LearnData.RLearnBuf[LearnData.RLearnIndex-1];

            if ( ((RTime_sec-CurLearn_sec) <= (TIME_MAX_DELTA/1000)) && ((RTime_sec-CurLearn_sec) >= -(TIME_MAX_DELTA/1000)) )
            {
                RStablePeriods++;
            }
            else
            {
                LearnData.RLearnPeriod = FindPeriod2(&LearnData.RLearnBuf[0]);
                if (LearnData.RLearnPeriod)
                {
                    LearnData.RLearnState = LEARN_FINISHED;
                    LearnData.RLearnIndex = LEARN_BUF_SIZE - LearnData.RLearnPeriod;
                }
                else
                {
                    RStablePeriods = 0;
                    LearnData.RLearnState = LEARNING_NOW;
                }
            }
        }
        */

        //--------------------
        // Smart2 Learn Algorithm
        // Put Data To Buffer
        for (i=1; i<LEARN_BUF_SIZE; i++)
            LearnData.RLearnBuf[i-1] = LearnData.RLearnBuf[i];

        LearnData.RLearnBuf[LEARN_BUF_SIZE-1] = RTime_sec;

        // Find Period
        LearnData.RLearnPeriod = FindPeriod2(&LearnData.RLearnBuf[0]);
        if (LearnData.RLearnPeriod)
        {
            LearnData.RLearnState = LEARN_FINISHED;
            LearnData.RLearnIndex = LEARN_BUF_SIZE - LearnData.RLearnPeriod;
        }
        else
        {
            LearnData.RLearnState = LEARNING_NOW;
        }

        //--------------------
        // Vulgar Learn Algorithm
        /*
        if (LearnData.RLearnState == LEARNING_NOW)
        {
            LearnData.RLearnBuf[LearnData.RLearnIndex++] = RTime_sec;
            if (LearnData.RLearnIndex >= LEARN_BUF_SIZE)
            {
                LearnData.RLearnPeriod = FindPeriod(&LearnData.RLearnBuf[0]);
                if (LearnData.RLearnPeriod)
                {
                    LearnData.RLearnState = LEARN_FINISHED;

                    for (i=0; i<LearnData.RLearnPeriod; i++)
                    {
                        LearnData.RLearnBuf[LearnData.RLearnPeriod-1-i] = LearnData.RLearnBuf[LEARN_BUF_SIZE-1-i];
                        LearnData.RLearnIndex = 0;
                    }
                }
                else
                {
                    for (i=1; i<LEARN_BUF_SIZE; i++)
                    {
                        LearnData.RLearnBuf[i-1] = LearnData.RLearnBuf[i];
                        LearnData.RLearnIndex = LEARN_BUF_SIZE-1;
                    }
                }
            }
        }
        else
        {
            CurLearn_sec = LearnData.RLearnBuf[LearnData.RLearnIndex];

            if ( ((RTime_sec-CurLearn_sec) <= (TIME_MAX_DELTA/1000)) && ((RTime_sec-CurLearn_sec) >= -(TIME_MAX_DELTA/1000)) )
            {
                RStablePeriods++;
                LearnData.RLearnBuf[LearnData.RLearnIndex++] = RTime_sec;
                //LearnData.RLearnIndex++;
                if (LearnData.RLearnIndex >= LearnData.RLearnPeriod)
                    LearnData.RLearnIndex = 0;
            }
            else
            {
                RStablePeriods = 0;
                LearnData.RLearnState = LEARNING_NOW;
                LearnData.RLearnIndex  = 0;
                LearnData.RLearnPeriod = 0;
                LearnData.RLearnBuf[LearnData.RLearnIndex++] = RTime_sec;
            }
        }
        */

        // Jitter Count
        RRoundUpValue = ROUND_UP_TIME1;
        if ( (RTime_sec == (RTime_sec_prev+TIME_JITTER_DELTA_SEC)) || (RTime_sec == (RTime_sec_prev-TIME_JITTER_DELTA_SEC)) )
        {
            RTimeJitterCount += TIME_JITTER_ADD_VALUE;

            if (RTimeJitterCount >= TIME_JITTER_COUNTER_LIMIT)
            {
                RTimeJitterCount = 0;
                if (RRoundUpValue != ROUND_UP_TIME1)
                    RRoundUpValue = ROUND_UP_TIME1;
                else
                    RRoundUpValue = ROUND_UP_TIME2;
            }
        }
        else
        {
            if (RTimeJitterCount >= TIME_JITTER_SUB_VALUE)
            {
                RTimeJitterCount -= TIME_JITTER_SUB_VALUE;
            }
            else
            {
                RTimeJitterCount = 0;
            }
        }

        RTime_sec_prev  = RTime_sec;
        RTime_prev = RTime;

        if (LearnData.RLearnState != LEARNING_NOW)
        //if (RStablePeriods >= Config.TeachingPeriods)
        {
            //RTimeLeft = RTime_sec;
            RTimeLeft = LearnData.RLearnBuf[LearnData.RLearnIndex];
    //        DigMask = CalcNumberMask(RTimeLeft, RED_MAX_COUNT);
        }
        else
        {
            RTimeLeft = -1;
            DigMask = 0;
        }

        // Init Counters
        RTime = 0;
        RTime_sec = 0;
        RmsecCounter = 0;
    }
    else
    {
        // Old Light

        // Algorithm 1
        //RTime += 1000 - RmsecCounter;
        //RTime_AddSec();
        //RmsecCounter = 0;

        // Algorithm 2
        //RTime      += 500;
        //RmsecCounter += 500;
        //if (RmsecCounter >= 1000)
        //{
        //    RTime_AddSec();
        //    RmsecCounter = 0;
        //}

        // Algorithm 3
        if (RmsecCounter < BLINK_ROUND_DOWN_TIME)
        {
            RTime -= RmsecCounter;
            RmsecCounter = 0;

            if (RTimeLeft>=0)
                DigMask = CalcNumberMask(RTimeLeft, RED_MAX_COUNT);
            else
                DigMask = 0;
        }
        else
        {
            RTime += 1000 - RmsecCounter;
            RTime_AddSec();
            RmsecCounter = 0;
        }
    }

    // Red On
    RedManVar   = RMAN_MASK;
    // All Green Off
    GreenManVar = 0;
    //DigMask         = 0;

    MainState = RED_STATE;
    PrevState = RED_STATE;
}
void SwitchToGreen(void)
{
    TDateTime DT;
    int32 NowFullSec;
    int32 CurLearn_sec;
    int   i;

    if ( Get_DateTime(&DT) )
    {
        NowFullSec = ((DT.hour*60UL) + DT.min)*60UL + DT.sec;

        if (NowFullSec < PrevStateEnd_FullSec)
        {
            NowFullSec += 24*60*60UL; // + 1 day
        }
    }
    else
    {
        NowFullSec = -1;
    }

    if ( ((NowFullSec-PrevStateEnd_FullSec) >= OFF_LIMIT_SEC) || (PrevState != GREEN_STATE) )
    {
        // New Light
        //if ( ((GTime-GTime_prev) <= TIME_MAX_DELTA) && ((GTime-GTime_prev) >= -TIME_MAX_DELTA) )
        //{
        //    GStablePeriods++;
        //}
        //else
        //{
        //    GStablePeriods = 0;
        //}

        //GRoundUpValue = ROUND_UP_TIME1;
        // Rounding Algorithm
        if ( GmsecCounter >= (1000-GRoundUpValue) )
        {
            GTime_sec++;
        }

        //if (GmsecCounter <= ROUND_DOWN_TIME)
        //{
        //    GTime -= GmsecCounter;
        //}

        //--------------------
        // Smart1 Learn Algorithm
        /*
        // Put Data To Buffer
        for (i=1; i<LEARN_BUF_SIZE; i++)
            LearnData.GLearnBuf[i-1] = LearnData.GLearnBuf[i];

        LearnData.GLearnBuf[LEARN_BUF_SIZE-1] = GTime_sec;

        if (LearnData.GLearnState == LEARNING_NOW)
        {
            LearnData.GLearnPeriod = FindPeriod2(&LearnData.GLearnBuf[0]);
            if (LearnData.GLearnPeriod)
            {
                LearnData.GLearnState = LEARN_FINISHED;
                LearnData.GLearnIndex = LEARN_BUF_SIZE - LearnData.GLearnPeriod;
            }
        }
        else
        {
            CurLearn_sec = LearnData.GLearnBuf[LearnData.GLearnIndex-1];

            if ( ((GTime_sec-CurLearn_sec) <= (TIME_MAX_DELTA/1000)) && ((GTime_sec-CurLearn_sec) >= -(TIME_MAX_DELTA/1000)) )
            {
                GStablePeriods++;
            }
            else
            {
                LearnData.GLearnPeriod = FindPeriod2(&LearnData.GLearnBuf[0]);
                if (LearnData.GLearnPeriod)
                {
                    LearnData.GLearnState = LEARN_FINISHED;
                    LearnData.GLearnIndex = LEARN_BUF_SIZE - LearnData.GLearnPeriod;
                }
                else
                {
                    GStablePeriods = 0;
                    LearnData.GLearnState = LEARNING_NOW;
                }
            }
        }
        */

        //--------------------
        // Smart2 Learn Algorithm
        // Put Data To Buffer
        for (i=1; i<LEARN_BUF_SIZE; i++)
            LearnData.GLearnBuf[i-1] = LearnData.GLearnBuf[i];

        LearnData.GLearnBuf[LEARN_BUF_SIZE-1] = GTime_sec;

        // Find Period
        LearnData.GLearnPeriod = FindPeriod2(&LearnData.GLearnBuf[0]);
        if (LearnData.GLearnPeriod)
        {
            LearnData.GLearnState = LEARN_FINISHED;
            LearnData.GLearnIndex = LEARN_BUF_SIZE - LearnData.GLearnPeriod;
        }
        else
        {
            LearnData.GLearnState = LEARNING_NOW;
        }

        //--------------------
        // Vulgar Learn Algorithm
        /*
        if (LearnData.GLearnState == LEARNING_NOW)
        {
            LearnData.GLearnBuf[LearnData.GLearnIndex++] = GTime_sec;
            if (LearnData.GLearnIndex >= LEARN_BUF_SIZE)
            {
                LearnData.GLearnPeriod = FindPeriod(&LearnData.GLearnBuf[0]);
                if (LearnData.GLearnPeriod)
                {
                    LearnData.GLearnState = LEARN_FINISHED;

                    for (i=0; i<LearnData.GLearnPeriod; i++)
                    {
                        LearnData.GLearnBuf[LearnData.GLearnPeriod-1-i] = LearnData.GLearnBuf[LEARN_BUF_SIZE-1-i];
                        LearnData.GLearnIndex = 0;
                    }
                }
                else
                {
                    for (i=1; i<LEARN_BUF_SIZE; i++)
                    {
                        LearnData.GLearnBuf[i-1] = LearnData.GLearnBuf[i];
                        LearnData.GLearnIndex = LEARN_BUF_SIZE-1;
                    }
                }
            }
        }
        else
        {
            CurLearn_sec = LearnData.GLearnBuf[LearnData.GLearnIndex];

            if ( ((GTime_sec-CurLearn_sec) <= (TIME_MAX_DELTA/1000)) && ((GTime_sec-CurLearn_sec) >= -(TIME_MAX_DELTA/1000)) )
            {
                GStablePeriods++;
                LearnData.GLearnBuf[LearnData.GLearnIndex++] = GTime_sec;
                //LearnData.GLearnIndex++;
                if (LearnData.GLearnIndex >= LearnData.GLearnPeriod)
                    LearnData.GLearnIndex = 0;
            }
            else
            {
                GStablePeriods = 0;
                LearnData.GLearnState = LEARNING_NOW;
                LearnData.GLearnIndex  = 0;
                LearnData.GLearnPeriod = 0;
                LearnData.GLearnBuf[LearnData.GLearnIndex++] = GTime_sec;
            }
        }
        */

        // Jitter Count
        GRoundUpValue = ROUND_UP_TIME1;
        if ( (GTime_sec == (GTime_sec_prev+TIME_JITTER_DELTA_SEC)) || (GTime_sec == (GTime_sec_prev-TIME_JITTER_DELTA_SEC)) )
        {
            GTimeJitterCount += TIME_JITTER_ADD_VALUE;

            if (GTimeJitterCount >= TIME_JITTER_COUNTER_LIMIT)
            {
                GTimeJitterCount = 0;
                if (GRoundUpValue != ROUND_UP_TIME1)
                    GRoundUpValue = ROUND_UP_TIME1;
                else
                    GRoundUpValue = ROUND_UP_TIME2;
            }
        }
        else
        {
            if (GTimeJitterCount >= TIME_JITTER_SUB_VALUE)
            {
                GTimeJitterCount -= TIME_JITTER_SUB_VALUE;
            }
            else
            {
                GTimeJitterCount = 0;
            }
        }

        GTime_sec_prev  = GTime_sec;
        GTime_prev = GTime;

        if (LearnData.GLearnState != LEARNING_NOW)
        //if (GStablePeriods >= Config.TeachingPeriods)
        {
            //GTimeLeft = GTime_sec;
            GTimeLeft = LearnData.GLearnBuf[LearnData.GLearnIndex];
            DigMask   = CalcNumberMask(GTimeLeft, GREEN_MAX_COUNT);
        }
        else
        {
            GTimeLeft = -1;
            DigMask = 0;
        }

        // Init Counters
        GTime = 0;
        GTime_sec = 0;
        GmsecCounter = 0;
    }
    else
    {
        // Old Light

        // Algorithm 1
        //GTime += 1000 - GmsecCounter;
        //GTime_AddSec();
        //GmsecCounter = 0;

        // Algorithm 2
        //GTime      += 500;
        //GmsecCounter += 500;
        //if (GmsecCounter >= 1000)
        //{
        //    GTime_AddSec();
        //    GmsecCounter = 0;
        //}

        // Algorithm 3
        if (GmsecCounter < BLINK_ROUND_DOWN_TIME)
        {
            GTime -= GmsecCounter;
            GmsecCounter = 0;

            if (GTimeLeft>=0)
                DigMask = CalcNumberMask(GTimeLeft, GREEN_MAX_COUNT);
            else
                DigMask = 0;
        }
        else
        {
            GTime += 1000 - GmsecCounter;
            GTime_AddSec();
            GmsecCounter = 0;
        }
    }

    ManStepCounter = 0;
    SoundRepeatCounter = 0;

    // Red Off
    RedManVar = 0;

    // Green On
    GreenManVar = GMAN0_MASK|GMAN1_MASK;
    GManPhase = 0;

    //Start Sound
    StartSound();

    MainState = GREEN_STATE;
    PrevState = GREEN_STATE;
}
void RF_Ready_Packet(void)
{
	uint16_t i=0;
	uint8_t i2;
	uint8_t *p8;
	sDateTimeStruct date_time;
	rf.length = 0;
	/* clear rf buffer */
	memset(&rf.buf, 0, sizeof(rf.buf));
	i = 0;
	/* reserv lenght byte */
	rf.buf[i++] = 0;
	rf.buf[i++] = ((UNICAL_NUMBER & 0xFF000000) >> 24);
	rf.buf[i++] = ((UNICAL_NUMBER & 0x00FF0000) >> 16);
	rf.buf[i++] = ((UNICAL_NUMBER & 0x0000FF00) >> 8);
	rf.buf[i++] = (UNICAL_NUMBER & 0xFF);
	/* Field id */
	rf.buf[i++]=   ((param.id & 0xFF000000)>>24);
	rf.buf[i++]=   ((param.id & 0x00FF0000)>>16);
	rf.buf[i++]=   ((param.id & 0x0000FF00)>>8);
	rf.buf[i++]=   ((param.id & 0x000000FF));
	/* Battery */
	p8 = (uint8_t*)&param.battery;
	for(i2=0; i2<sizeof(float); i2++) {
		rf.buf[i++] = (*p8);
		p8++;
	}
	/* mode */
	rf.buf[i++] = param.mode;

	/* input status */
	param.input_state = 0;
	if(TAMPER_IN & TAMPER_BIT)
		param.input_state |= RF_PACKET_TAMPER_HIGHT;
	if(INPUTS_1_IN & INPUTS_1_BIT)
		param.input_state |= RF_PACKET_INPUT_1_HIGHT;
	if(INPUTS_2_IN & INPUTS_2_BIT)
		param.input_state |= RF_PACKET_INPUT_2_HIGHT;

	/* input state */
	rf.buf[i++] = param.input_state;

	/* temperature */
	p8 = (uint8_t*)&param.temperature;
	for(i2=0; i2<sizeof(float); i2++) {
		rf.buf[i++] = (*p8);
		p8++;
	}
	rf.buf[i++]=   (param.counter1 & 0xFF000000)>>24;
	rf.buf[i++]=   (param.counter1 & 0x00FF0000)>>16;
	rf.buf[i++]=   (param.counter1 & 0x0000FF00)>>8;
	rf.buf[i++]=   (param.counter1 & 0x000000FF);
	rf.buf[i++]=   (param.counter2 & 0xFF000000)>>24;
	rf.buf[i++]=   (param.counter2 & 0x00FF0000)>>16;
	rf.buf[i++]=   (param.counter2 & 0x0000FF00)>>8;
	rf.buf[i++]=   (param.counter2 & 0x000000FF);
	/* get dateTime */
	date_time = Get_DateTime();
	/* year */
	rf.buf[i++]=   (date_time.year & 0x00FF);
	rf.buf[i++]=   ((date_time.year & 0xFF00)>>8);
	/* month */
	rf.buf[i++]=   date_time.month;
	/* day */
	rf.buf[i++]=   date_time.date;
	/* hour */
	rf.buf[i++]=   date_time.hour;
	/* minutes */
	rf.buf[i++]=   date_time.min;
	/* seconds */
	rf.buf[i++]=   date_time.sec;
	/* calc crc */
	rf.buf[i++] = 0x16;

	rf.length = i + 1;
	/* length rf packet */
	rf.buf[0] =  rf.length;
	/* calculate crc */
	rf.buf[i++] = CRC_Calc((uint8_t*)&rf.buf, rf.length);
}