OTP cpu Remote Controller - Power Switcher

/*-------------------------------------------
Function name: main.c
Designed By: Milo Lu
Version:     2020-11-21 
            1. adapted,first functional draft.
Description:
1.  K1 project
2.  SC8P1153A
//                    SC8P1153A
//                 ---------------
// LEARN_S3-PA0-|               |-PA1
//        LED,PB7-|               |-PA2
//      ON_S1,PB6-|RST            |-PA3
//            VCC-|               |-GND
//            PB5-|               |-PB0-OFF_S2
//            PB4-|               |-PB1-SDA
//       DATA,PB3-|               |-PB2-SCL
//                 ---------------
-------------------------------------------*/


#include <sc.h>                    //sc library,system search h file automatically.

//----------- My Define -----------------
#define     Button1_S1        PORTB6            // input
#define        Button2_S2        PORTB0            // input
#define     Button3_S3        PORTA0            // input

#define        DIR_OUTPUT        0                //Output direction
#define        DIR_INPUT        1                //Input direction
#define        SDA_DIR            TRISB1            //DIR
#define        SDA                PORTB1
#define        SCL                PORTB2            // output

#define        LED_4            PORTB7            // output
#define        DATA_IN            PORTB3            // input
#define        RELAY_CTL        PORTA2            // output


//----------- My variable parameters -------
unsigned int     Learn_Time_ms;
unsigned char     SysTick;
unsigned char     START_RX;
unsigned char     RemoteID_Index;
unsigned int     DATA_RECEIVED;
unsigned char     CMD_VALUE;
unsigned char     My_Led_Blink;
unsigned char     My_Led_Delay;
unsigned char     My_Mode;
unsigned int     My_Remot0ID;
unsigned int    My_Remot1ID;
unsigned int    My_Remot2ID;
//-------------- 24C02 --------------------
void delay5us()
{
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
}

void iic_start()//SDA falling when SCL is high
{
    SDA_DIR = DIR_OUTPUT;
    SDA = 1;
    asm("nop");asm("nop");
    SCL = 1;
    delay5us();
    SDA = 0;
    delay5us();
    SCL = 0;
}
void iic_stop()//SDA rise when SCL is high
{
    SDA_DIR = DIR_OUTPUT;
    SDA = 0;
    asm("nop");
    SCL = 1;
    delay5us();
    SDA = 1;
    delay5us();
    SCL = 0;
}
void iic_ack()
{
    SCL = 0;
    asm("nop");asm("nop");asm("nop");
    SCL = 1;
    delay5us();
    SCL = 0;
    asm("nop");asm("nop");
}
void iic_NoAck()
{
    SDA_DIR = DIR_OUTPUT;
    SDA = 1;
    asm("nop");asm("nop");asm("nop");
    SCL = 1;
    delay5us();
    SCL = 0;
    asm("nop");asm("nop");
}
void iic_write_byte(unsigned char u8_value)
{
    unsigned char i;
    SDA_DIR = DIR_OUTPUT;
    for(i=0;i<8;i++)
    {
        SCL = 0;
        delay5us();
        if(u8_value&0x80) SDA = 1;
        else SDA = 0;
        delay5us();
        SCL = 1;
        delay5us();
        u8_value<<=1;
    }
    SCL = 0;
    delay5us();
    SDA = 1;
}
unsigned char iic_read_byte()
{
    unsigned char i,ret_val=0;
    SDA_DIR = DIR_INPUT;
    SDA = 1;
    for(i=0;i<8;i++)
    {
        SCL = 0;
        delay5us();
        SCL = 1;
        delay5us();
        ret_val<<=1;
        if(SDA)
            ret_val |= 1;
    }
    return ret_val;
}
void iic_write_byte_to_addr(unsigned char addr,unsigned char val)
{
    iic_start();
    iic_write_byte(0xa0);
    iic_ack();
    iic_write_byte(addr);
    iic_ack();
    iic_write_byte(val);
    iic_ack();
    iic_stop();
}
unsigned char iic_read_byte_from_addr(unsigned char addr)
{
    unsigned char ret_val;
    iic_start();
    iic_write_byte(0xa0);
    iic_ack();
    iic_write_byte(addr);
    iic_ack();
    iic_start();
    iic_write_byte(0xa1);
    iic_ack();
    ret_val = iic_read_byte();
    SCL = 0;
    iic_NoAck();
    iic_stop();
    return ret_val;
}

/*******************************************
** Main Function
********************************************/
void main(void)
{
    //------------ My static variable ---------
    static unsigned char Btn1_Debouncing,Btn2_Debouncing;//,Btn3_Debouncing;
    //------------- variable -----------
    unsigned char tmp,j;
    unsigned int i;
    
    //---------- System Start ----------
    asm("nop");
    asm("clrwdt");
    
    //-------- System Init -------------
    OPTION_REG =0;                    //Fdev for TMR0  
    OSCCON = 0XF1;                    //8M
    
    //---------- PORTA PORTB Init -------------
    // pull-up and pull-down resistor
    // Bit7~Bit4--pull up resistor;Bit3~Bit0--pull down resistor;0=disable;1=enable
    UPDOWNA = 0B00010100;    //PA0 pull-up,PA2 pull-down registor enable
    // Bit7~Bit0--pull-up registor. enable;1=enable;0=disable.
    WPUB    = 0B01001001;    //PB6,PB3,PB0 pull-up registor enable
    // Bit7~Bit0--pull-down registor enable;1=enable;0=disable.
    PDCONB    = 0b00000000;    //PB disable all pull-down registor
    // Bit7~Bit0--output open enable;1=enable;0=disable
    ODCONB     = 0B10000000;    //PB7 enable
    //IO input output direction option--0=Output;1=Input
    TRISA     = 0B00000001;    //PA0=Input;Others=Output
    TRISB    = 0B01111001;    //PB1=Output,Others=Input
    SDA = 0;                //PB1 = 0
    RELAY_CTL = 0;
    My_Mode = 0;            //Normal mode
    
    //------------- Read 24C02 ----------
    //iic_write_byte_to_addr(j,tmp++);        //test
    RemoteID_Index = iic_read_byte_from_addr(0xFB);
    if(RemoteID_Index > 14)RemoteID_Index = 0;
    DATA_RECEIVED = 0;
    My_Remot0ID = iic_read_byte_from_addr(0);
    My_Remot0ID<<=8;
    My_Remot0ID |=iic_read_byte_from_addr(1);
    
    My_Remot1ID = iic_read_byte_from_addr(2);
    My_Remot1ID<<=8;
    My_Remot1ID |=iic_read_byte_from_addr(3);
    
    My_Remot2ID = iic_read_byte_from_addr(4);
    My_Remot2ID<<=8;
    My_Remot2ID |=iic_read_byte_from_addr(5);
    
    //------------- TIMER0 --------------
    TMR0 = 0;                // CNT++ = 1us
    OPTION_REG = 0x00;        // Focs/4
    TMR0PRD = 50;            // Load default value interrupt trigger per 50us
    
    //----------- Interrupt ------------------
    INTCON     = 0x00;            //Disable Gobal interrupt
    IOCB    = 0B00001000;    // Enable level PB3 change interrupt
    OSCCON |= 0X01;            //TIMER0 Start...
    INTCON  = 0xA8;            //TIMER0 Interrupt enable,PORTB Level changed interrupt enable
    while(1)
    {
        asm("clrwdt");
        
        //--------- Button1--Connect Key Press down -----------
        if(!Button1_S1)
        {
            if(Btn1_Debouncing < 200) Btn1_Debouncing++;
            else if(Btn1_Debouncing == 200)
            {
                if(!Button1_S1)
                {
                    RELAY_CTL = 1;
                    Btn1_Debouncing++;
                }
            }
        }
        else if(Btn1_Debouncing != 0) Btn1_Debouncing =0;
        
        //------------ Button2--Disconnect Key Press down ------------
        if(!Button2_S2)
        {
            if(Btn2_Debouncing < 200) Btn2_Debouncing++;
            else if(Btn2_Debouncing == 200)
            {
                if(!Button2_S2)
                {
                    RELAY_CTL = 0;
                    Btn2_Debouncing++;
                }
            }
        }
        else if(Btn2_Debouncing != 0) Btn2_Debouncing =0;
        
        //------------ Button3--Learn Key Press down -------------
        switch(My_Mode)
        {
            case 0:
            {
                if(!Button3_S3)
                {
                    Learn_Time_ms = 20;
                    My_Mode =1;                    //key down event trigger
                }
                break;
            }
            case 1:
            {
                if(!Button3_S3)
                {
                    if(Learn_Time_ms==0)        //debouncing time out
                    {
                        Learn_Time_ms=9000;        //9 second to confirn a long key press down
                        My_Mode =2;                //key down evnet confirn
                    }
                }
                else 
                {
                    My_Mode = 0;                //invaid key
                }
                break;
            }
            case 2:                                //wait for key release
            {
                if(!Button3_S3)                    //key continue press down
                {
                    if(Learn_Time_ms==0)        //key press down for more than 9 seconds,reset remote ID
                    {
                        GIE = 0;                //disable interrupt
                        Learn_Time_ms = 0;
                        RemoteID_Index = 0;
                        
                        My_Remot0ID = 0;
                        My_Remot1ID = 0;
                        My_Remot2ID = 0;
                        iic_write_byte_to_addr(0xFB,RemoteID_Index);
                        for(i=0;i<200;i++)delay5us();
                        asm("clrwdt");
                        for(tmp=0;tmp<16;tmp++)
                        {
                            iic_write_byte_to_addr(tmp,0x00);
                            for(i=0;i<200;i++)delay5us();        //a delay should be add.
                            asm("clrwdt");
                        }
                        My_Led_Blink = 6;        //led blinks
                        My_Mode = 3;            //wait for key release
                        GIE = 1;                //interrupt enable
                    }
                }
                else if(Learn_Time_ms > 7000)    //key release within 3 second
                {
                    My_Mode = 4;                //Learn Mode
                    My_Led_Blink = 6;            //Led blinks
                    Learn_Time_ms = 20000;        //Learn time:20 seconds.
                }
                break;
            }
            case 3:
            {
                if(Button3_S3)                    //key release event trigger
                {
                    for(i=0;i<200;i++)delay5us();    //delay block CPU.
                    if(Button3_S3)                //key release event confirn
                    {
                        My_Mode = 0;            //normal mode
                    }
                }
                break;
            }
            case 4:
            {
                if(Learn_Time_ms==0)            //time out, exit learn mode
                {
                    My_Mode = 0;                //normal mode
                }
                break;
            }
            default:
            {
                My_Mode = 0;
                break;
            }
        }
        /*if(!Button3_S3)
        {
            if(Btn3_Debouncing < 200) Btn3_Debouncing++;
            else if(My_Mode==0)
            {
                if(!Button3_S3)
                {
                    Learn_Time_ms = 9000;
                    My_Mode = 1;
                }
            }
            else if(My_Mode==1)                    //continue press down for more than 9 seconds
            {
                if(Learn_Time_ms==0)
                {
                    GIE = 0;
                    Learn_Time_ms = 0;
                    RemoteID_Index = 0;
                    
                    My_Remot0ID = 0;
                    My_Remot1ID = 0;
                    My_Remot2ID = 0;
                    iic_write_byte_to_addr(0xFB,RemoteID_Index);
                    for(i=0;i<200;i++)delay5us();
                    asm("clrwdt");
                    for(tmp=0;tmp<16;tmp++)
                    {
                        iic_write_byte_to_addr(tmp,0x00);
                        for(i=0;i<200;i++)delay5us();
                        asm("clrwdt");
                    }
                    My_Led_Blink = 6;
                    My_Mode = 2;                //avoid to reset again
                    GIE = 1;
                }
            }
        }
        else if(Btn3_Debouncing != 0) 
        {
            if((My_Mode == 1)&&(Learn_Time_ms >= 7000))
            {
                My_Led_Blink = 3;
                Learn_Time_ms = 20000;
                My_Mode = 3;
            }
            else if(My_Mode!=0)
            {
                My_Mode=0;
            }
            Btn3_Debouncing =0;
        }
        */
        
        //---------------- Paraser ------------------
        if(DATA_RECEIVED!=0)
        {
            GIE = 0;
            if(My_Mode==4)                        //learn mode
            {
                switch(RemoteID_Index)
                {
                    case 0:
                        {
                            My_Remot0ID = DATA_RECEIVED;
                            break;
                        }
                    case 2:
                        {
                            My_Remot1ID = DATA_RECEIVED;
                            break;
                        }
                    case 4:
                        {
                            My_Remot2ID = DATA_RECEIVED;
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
                tmp = (DATA_RECEIVED>>8);                //High byte first
                iic_write_byte_to_addr(RemoteID_Index,tmp);
                for(i=0;i<200;i++)delay5us();
                asm("clrwdt");
                tmp = DATA_RECEIVED&0x00FF;                //Low byte second
                RemoteID_Index ++;
                iic_write_byte_to_addr(RemoteID_Index,tmp);
                for(i=0;i<200;i++)delay5us();
                asm("clrwdt");
                RemoteID_Index ++;
                if(RemoteID_Index >= 16)                //Remote Number Max 8,save
                    RemoteID_Index = 0;
                iic_write_byte_to_addr(0xFB,RemoteID_Index);
                for(i=0;i<200;i++)delay5us();
                asm("clrwdt");
                My_Led_Blink = 6;
                Learn_Time_ms = 0;                        //Exit learn mode
            }
            else                                        //CMD from Remote
            {
                //it is faster to get id from RAM than ROM.
                if(DATA_RECEIVED == My_Remot0ID || DATA_RECEIVED == My_Remot1ID || DATA_RECEIVED == My_Remot2ID )
                {
                    tmp = 0;
                }
                else 
                {
                    for(tmp=0,j=0;tmp<16;tmp++)
                    {
                        i=iic_read_byte_from_addr(j);
                        i<<=8;
                        j++;
                        i|=iic_read_byte_from_addr(j);
                        asm("clrwdt");
                        j++;
                        if(DATA_RECEIVED == i)
                        {
                            tmp = 0;
                            break;
                        }
                    }
                }
                if(!tmp )    //id active
                {
                    My_Led_Blink = 1;
                    switch (CMD_VALUE)
                    {
                        case 1:
                        {
                            break;
                        }
                        case 2:                                //For PGST Remote, this cmd is arm
                        {
                            RELAY_CTL = 0;
                            break;
                        }
                        case 4:                                //For PGST Remote, this cmd is Disarm
                        {
                            break;
                        }
                        case 8:                                //For PGST Remote,this cmd is Home Arm
                        {
                            RELAY_CTL = 1;
                            break;
                        }
                        default:
                        {
                            break;
                        }
                    }
                }
            }
            GIE = 1;
            DATA_RECEIVED = 0;
        }
    }
}

/*******************************************
**     Timer0 interrupt
**    Timer=200us
**     PB0 interrupt
**    RF data received
********************************************/
void interrupt Isr_Routine()
{
    static unsigned int id,tmp;
    static unsigned char bits_of_byte,TAR_50us;
    static unsigned long one_byte;
    unsigned char IO_State;
    if(T0IF)                        //TIMER0 Interrupt
    {
        T0IF = 0;
        if(SysTick++ >= 20)        // 20*50us = 1ms
        {
            if(Learn_Time_ms != 0)
            {
                Learn_Time_ms--;
            }
            if(My_Led_Blink != 0)
            {
                if(My_Led_Delay++ < 100) 
                    LED_4 = 1;
                else if(My_Led_Delay < 200) 
                    LED_4 = 0;
                else 
                {
                    My_Led_Delay = 0;
                    My_Led_Blink--;
                }
            }
            SysTick = 0;
        }
        TAR_50us++;
    }
    if(PBIF)                        //PORTB Interrupt
    {
        PBIF = 0;
        
        //----------------------------------------------------------------------------
        //            RF Data Format:NRZ Encoder
        //            1B = 400usH+1000usL; 0B = 1000usH+400usL; T = 1500us
        //            Bootstrap: 1ms H + 400us L
        //            5bytes = 2bytesID + 1ByteData + 2bytesReserver(FFFFH)
        //            Data:F7H, F5H, FFH, FDH
        //            Down Midle  Up  Learn
        //            ASM Modulation
        //----------------------------------------------------------------------------
        IO_State = (unsigned char)DATA_IN;
        if(IO_State)                // Low to high transition
        {
            // Low state time is upper than 1.5ms,OR Paraser busy, data crash, retry again
            if((TAR_50us >= 30)||(DATA_RECEIVED!=0))            
            {
                START_RX = 0;
            }
            TAR_50us = 0;
        }
        else                        // High to low transition
        {
            if(!START_RX)                                         // The first header doesn't receive
            {
                if((TAR_50us > 14)&&(TAR_50us < 30))             // 1.5ms > T > 0.7ms
                {
                    one_byte = 1;
                    bits_of_byte = 1;
                    START_RX = 1;
                }
            }
            else                                                  // The second header received,
            {                                                   // start to get RF data
                if((TAR_50us >4)&&(TAR_50us< 12))                //0 600us > T > 200us
                {
                    one_byte <<=1;
                    bits_of_byte++;
                }
                else if((TAR_50us > 14)&&(TAR_50us < 30))         // 1.5ms > T > 0.7ms
                {
                    one_byte<<=1;
                    one_byte+=1;
                    bits_of_byte++;
                }
                else
                {
                    START_RX = 0x00;                            // data crash, retry again
                }
                if(bits_of_byte >= 24)                             // got one byte, got id
                {
                    CMD_VALUE = (one_byte&0x0F);                //lowest 4 bits are command
                    one_byte>>=4;
                    tmp = one_byte;
                    if(id != tmp)
                    {
                        id = tmp;                                //got new id 
                    }
                    else                                        //at least 2 times get the same id
                    {
                        DATA_RECEIVED = id;                        //load RF data
                    }
                    START_RX = 0x00;                            // Receiving repeat
                    one_byte = 0;
                    bits_of_byte = 0;
                }
            }
            TAR_50us = 0;
        }
    }
}

IIC bus using by OTP cpu example.

Enjoy.

posted on 2020-11-24 18:42  Milo_lu  阅读(209)  评论(0编辑  收藏  举报

导航