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.