OTP CPU Receiver

  1 /*-------------------------------------------
  2 Function name: main.c
  3 Designed By: Milo Lu
  4 Version:     2020-11-21 
  5             1. adapted,first functional draft.
  6 Description:
  7 1.  K1 project
  8 2.  SC8P1153A
  9 //                    SC8P1153A
 10 //                 ---------------
 11 // LEARN_S3-PA0-|               |-PA1
 12 //        LED,PB7-|               |-PA2
 13 //      ON_S1,PB6-|RST            |-PA3
 14 //            VCC-|               |-GND
 15 //            PB5-|               |-PB0-OFF_S2
 16 //            PB4-|               |-PB1-SDA
 17 //       DATA,PB3-|               |-PB2-SCL
 18 //                 ---------------
 19 -------------------------------------------*/
 20 
 21 
 22 #include <sc.h>                    //sc library,system search h file automatically.
 23 
 24 //----------- My Define -----------------
 25 #define     Button1_S1        PORTB6            // input
 26 #define        Button2_S2        PORTB0            // input
 27 #define     Button3_S3        PORTA0            // input
 28 
 29 #define        DIR_OUTPUT        0                //Output direction
 30 #define        DIR_INPUT        1                //Input direction
 31 #define        SDA_DIR            TRISB1            //DIR
 32 #define        SDA                PORTB1
 33 #define        SCL                PORTB2            // output
 34 
 35 #define        LED_4            PORTB7            // output,0=led on,1=led off
 36 #define        DATA_IN            PORTB3            // input, modulation output
 37 #define        RELAY_CTL        PORTA2            // output, relay control
 38 
 39 
 40 //----------- My variable parameters -------
 41 unsigned char     My_Mode;
 42 unsigned char     Inching_Trigger;
 43 unsigned char   RX_Delay;
 44 unsigned char     START_RX;
 45 unsigned char     CMD_VALUE;
 46 unsigned char     My_Led_Blink;
 47 unsigned char     My_Led_Delay;
 48 unsigned char     RemoteID_Index;    //0xFB,one remote included 3bytes,there could be 83 pcs remotes stored in the abstract.
 49 unsigned char     Device_Sys_Mode;//0xFE, high 4bits:range=0-2:0 NORMAL,1 XOR,2 INCHING. Low 4bits=CONNECT_CMD
 50 
 51 unsigned int     My_Remot0ID;
 52 unsigned int     Learn_Time_ms;
 53 unsigned int     DATA_RECEIVED;
 54 
 55 //------------- delay about 5us -----------
 56 void delay5us()
 57 {
 58     asm("nop");
 59     asm("nop");
 60     asm("nop");
 61     asm("nop");
 62     asm("nop");
 63     asm("nop");
 64 }
 65 void delayms(unsigned char ms)
 66 {
 67     unsigned char i,j;
 68     
 69     for(i=0;i<ms;i++)
 70     {
 71         for(j=0;j<200;j++)
 72             delay5us();
 73         asm("clrwdt");
 74     }
 75 }
 76 
 77 //--------- iic bus for 24C02 -------------
 78 void iic_start()//SDA falling when SCL is high
 79 {
 80     SDA_DIR = DIR_OUTPUT;
 81     SDA = 1;
 82     asm("nop");asm("nop");
 83     SCL = 1;
 84     delay5us();
 85     SDA = 0;
 86     delay5us();
 87     SCL = 0;
 88 }
 89 void iic_stop()//SDA rise when SCL is high
 90 {
 91     SDA_DIR = DIR_OUTPUT;
 92     SDA = 0;
 93     asm("nop");
 94     SCL = 1;
 95     delay5us();
 96     SDA = 1;
 97     delay5us();
 98     SCL = 0;
 99 }
100 void iic_ack()
101 {
102     SCL = 0;
103     asm("nop");asm("nop");asm("nop");
104     SCL = 1;
105     delay5us();
106     SCL = 0;
107     asm("nop");asm("nop");
108 }
109 void iic_NoAck()
110 {
111     SDA_DIR = DIR_OUTPUT;
112     SDA = 1;
113     asm("nop");asm("nop");asm("nop");
114     SCL = 1;
115     delay5us();
116     SCL = 0;
117     asm("nop");asm("nop");
118 }
119 void iic_write_byte(unsigned char u8_value)
120 {
121     unsigned char i;
122     SDA_DIR = DIR_OUTPUT;
123     for(i=0;i<8;i++)
124     {
125         SCL = 0;
126         delay5us();
127         if(u8_value&0x80) SDA = 1;
128         else SDA = 0;
129         delay5us();
130         SCL = 1;
131         delay5us();
132         u8_value<<=1;
133     }
134     SCL = 0;
135     delay5us();
136     SDA = 1;
137 }
138 unsigned char iic_read_byte()
139 {
140     unsigned char i,ret_val=0;
141     SDA_DIR = DIR_INPUT;
142     SDA = 1;
143     for(i=0;i<8;i++)
144     {
145         SCL = 0;
146         delay5us();
147         SCL = 1;
148         delay5us();
149         ret_val<<=1;
150         if(SDA)
151             ret_val |= 1;
152     }
153     return ret_val;
154 }
155 void iic_write_byte_to_addr(unsigned char addr,unsigned char val)
156 {
157     iic_start();
158     iic_write_byte(0xa0);
159     iic_ack();
160     iic_write_byte(addr);
161     iic_ack();
162     iic_write_byte(val);
163     iic_ack();
164     iic_stop();
165 }
166 unsigned char iic_read_byte_from_addr(unsigned char addr)
167 {
168     unsigned char ret_val;
169     iic_start();
170     iic_write_byte(0xa0);
171     iic_ack();
172     iic_write_byte(addr);
173     iic_ack();
174     iic_start();
175     iic_write_byte(0xa1);
176     iic_ack();
177     ret_val = iic_read_byte();
178     SCL = 0;
179     iic_NoAck();
180     iic_stop();
181     return ret_val;
182 }
183 
184 /*******************************************
185 ** Main Function
186 ********************************************/
187 void main(void)
188 {
189     //------------ My static variable ---------
190     static unsigned char Btn1_Debouncing,Btn2_Debouncing;
191     //------------- variable -----------
192     unsigned char tmp,j;
193     unsigned int i;
194     
195     //---------- System Start ----------
196     asm("nop");
197     asm("clrwdt");
198     
199     //-------- System Init -------------
200     OPTION_REG =0;                    //Fdev for TMR0  
201     OSCCON = 0XF1;                    //8M
202     
203     //---------- PORTA PORTB Init -------------
204     // pull-up and pull-down resistor
205     // Bit7~Bit4--pull up resistor;Bit3~Bit0--pull down resistor;0=disable;1=enable
206     UPDOWNA = 0B00010100;    //PA0 pull-up,PA2 pull-down registor enable
207     // Bit7~Bit0--pull-up registor. enable;1=enable;0=disable.
208     WPUB    = 0B01001001;    //PB6,PB3,PB0 pull-up registor enable
209     // Bit7~Bit0--pull-down registor enable;1=enable;0=disable.
210     PDCONB    = 0b00000000;    //PB disable all pull-down registor
211     // Bit7~Bit0--output open enable;1=enable;0=disable
212     ODCONB     = 0B00000000;    //None enable
213     //IO input output direction option--0=Output;1=Input
214     TRISA     = 0B00000001;    //PA0=Input;Others=Output
215     TRISB    = 0B01111001;    //PB1=Output,Others=Input
216     SDA = 0;                //PB1 = 0
217     RELAY_CTL = 0;
218     
219     //------- RAM Data from 24C02 -------
220     //iic_write_byte_to_addr(0xFD,0x28);        //test
221     RemoteID_Index = iic_read_byte_from_addr(0xFB);
222     if(RemoteID_Index >= 48)//address index:a class is combined of:[2bytes id+1byte(high 4bits=mode,low 4bits=command)]*16=48bytes
223         RemoteID_Index = 0;
224     
225     My_Remot0ID = iic_read_byte_from_addr(0);    //id high byte
226     My_Remot0ID<<=8;
227     My_Remot0ID |=iic_read_byte_from_addr(1);    //id low byte
228     Device_Sys_Mode = iic_read_byte_from_addr(2);//high 4bits = mode and low 4bits = command
229     
230     DATA_RECEIVED = 0;        //clear RF data buffer
231     My_Mode = 0;            //mode for key option
232     
233     //------------- TIMER0 --------------
234     TMR0 = 0;                // CNT++ = 1us
235     OPTION_REG = 0x00;        // Focs/4
236     TMR0PRD = 50;            // Load default value interrupt trigger per 50us
237     
238     //----------- Interrupt ------------------
239     INTCON     = 0x00;            //Disable Gobal interrupt
240     IOCB    = 0B00001000;    // Enable level PB3 change interrupt
241     OSCCON |= 0X01;            //TIMER0 Start...
242     INTCON  = 0xA8;            //TIMER0 Interrupt enable,PORTB Level changed interrupt enable
243     
244     while(1)
245     {
246         asm("clrwdt");
247         
248         //--------- Button1--Connect Key Press down -----------
249         if(!Button1_S1)
250         {
251             if(Btn1_Debouncing < 250) Btn1_Debouncing++;//do not block cpu but only bit delay.
252             else if(Btn1_Debouncing == 250)
253             {
254                 if(!Button1_S1)
255                 {
256                     RELAY_CTL = 1;
257                     Btn1_Debouncing++;
258                 }
259             }
260         }
261         else if(Btn1_Debouncing != 0) Btn1_Debouncing =0;
262         
263         //------------ Button2--Disconnect Key Press down ------------
264         if(!Button2_S2)
265         {
266             if(Btn2_Debouncing < 250) Btn2_Debouncing++;//do not block cpu but only bit delay.
267             else if(Btn2_Debouncing == 250)
268             {
269                 if(!Button2_S2)
270                 {
271                     RELAY_CTL = 0;
272                     Btn2_Debouncing++;
273                 }
274             }
275         }
276         else if(Btn2_Debouncing != 0) Btn2_Debouncing =0;
277         
278         //------------ Button3--Learn Key Press down ----------------------
279         //-- 1.click enter normal learn mode; Led blinks once per 1.2s
280         //-- 2.click enter XOR learn mode; Led blinks twice per 1.2s
281         //-- 3.click enter inching learn mode; Led blinks 3 times per 1.2s
282         //-- 4.click repeat (goto step 1).
283         //-- 5.press down for more than 9s,clear ids, modes and commands.
284         //-----------------------------------------------------------------
285         switch(My_Mode&0x0F)
286         {
287             case 0:        //key press down
288             {
289                 if(!Button3_S3)
290                 {
291                     delayms(20);                    //delay block CPU.
292                     if(!Button3_S3)
293                     {
294                         GIE = 0;                    //Critical code for Learn_Time_ms
295                         if((My_Mode&0xF0)==0)        //first time press down
296                         {
297                             Learn_Time_ms = 900;    //learn mode confirn time:learn mode<3s, reset mode>9s
298                             My_Mode = 0x11;            //high 4bits means mode,low bit mean step
299                         }
300                         else if((My_Mode&0xF0)==0x20)    //press down again in learn mode(NORMAL)
301                         {
302                             My_Mode = 0x21;            //wait for key release
303                         }
304                         else if((My_Mode&0xF0)==0x30)    //press down again in learn mode(XOR)
305                         {
306                             My_Mode = 0x31;            //wait for key release
307                         }
308                         else if((My_Mode&0xF0)==0x40)    //press down again in learn mode(XOR)
309                         {
310                             My_Mode = 0x41;            //wait for key release
311                         }
312                         else
313                         {
314                             My_Mode = 0x01;
315                         }
316                         RX_Delay = 300;
317                         GIE = 1;                    //exit critical code for Learn_Time_ms
318                     }
319                 }
320                 break;
321             }
322             case 1:        //key release
323             {
324                 if(Button3_S3)
325                 {
326                     delayms(20);                    //delay block CPU.
327                     if(Button3_S3)
328                     {
329                         GIE = 0;                    //Critical code for Learn_Time_ms
330                         if(((My_Mode&0xF0)==0x10) && (Learn_Time_ms >= 600))    //sigle click
331                         {
332                             Learn_Time_ms = 2000;    //Time out
333                             My_Mode = 0x20;            //learn mode(NORMAL)
334                         }
335                         else if(((My_Mode&0xF0)==0x20)&&(Learn_Time_ms))        //last mode is NORMAL
336                         {
337                             Learn_Time_ms = 2000;
338                             My_Mode = 0x30;            //Learn mode(XOR)
339                         }
340                         else if(((My_Mode&0xF0)==0x30)&&(Learn_Time_ms))        //last mode is XOR
341                         {
342                             Learn_Time_ms = 2000;
343                             My_Mode = 0x40;            //Learn mode(INCHING)
344                         }
345                         else if(((My_Mode&0xF0)==0x40)&&(Learn_Time_ms))        //last mode is INCHING
346                         {
347                             Learn_Time_ms = 0;        //Time out 
348                             My_Mode = 0x00;            //exit learn mode(NORMAL)-->repeat
349                         }
350                         else
351                         {
352                             My_Mode=0x00;
353                         }
354                         RX_Delay = 300;
355                         GIE = 1;                    //exit critical code for Learn_Time_ms
356                     }
357                 }
358                 else if((!Button3_S3)&&(My_Mode&0x10))
359                 {
360                     if(Learn_Time_ms == 0)        //key press down for more than 9 seconds,reset remote ID
361                     {
362                         GIE = 0;                //disable interrupt
363                         //----- reset RAM --------
364                         RemoteID_Index = 0;
365                         My_Remot0ID = 0;
366                         //----- reset ROM -------
367                         iic_write_byte_to_addr(0xFB,RemoteID_Index);
368                         for(i=0;i<200;i++)delay5us();
369                         asm("clrwdt");
370                         for(tmp=0;tmp<48;tmp++)
371                         {
372                             iic_write_byte_to_addr(tmp,0x00);
373                             for(i=0;i<200;i++)delay5us();        //a delay should be add.
374                             asm("clrwdt");
375                         }
376                         //------ indication -----
377                         My_Mode=0x01;
378                         RX_Delay = 300;
379                         My_Led_Blink = 6;        //led blinks
380                         GIE = 1;                //interrupt enable
381                     }
382                 }
383                 break;
384             }
385         }
386         //---------------- Paraser ------------------
387         if(DATA_RECEIVED!=0)
388         {
389             GIE = 0;                            //enter critical code to avoid data crash,which from RF modulation
390             if(Learn_Time_ms)                    //learn mode
391             {
392                 tmp = My_Mode&0xF0;
393                 if(tmp == 0x20 || tmp == 0x30 || tmp == 0x40)    //Learn mode 0x20=Normal,0x30=OXR,0x40=Inching
394                 {
395                     Device_Sys_Mode=tmp;                    //mode
396                     Device_Sys_Mode|=CMD_VALUE;                //command
397                     My_Remot0ID = DATA_RECEIVED;            //id
398                     tmp = (DATA_RECEIVED>>8);                //High byte first,store in ROM
399                     iic_write_byte_to_addr(RemoteID_Index,tmp);
400                     for(i=0;i<200;i++)delay5us();
401                     asm("clrwdt");
402                     
403                     tmp = DATA_RECEIVED&0x00FF;                //Low byte second
404                     RemoteID_Index ++;
405                     iic_write_byte_to_addr(RemoteID_Index,tmp);
406                     for(i=0;i<200;i++)delay5us();
407                     asm("clrwdt");
408                     
409                     RemoteID_Index ++;                        //mode and command
410                     iic_write_byte_to_addr(RemoteID_Index,Device_Sys_Mode);
411                     for(i=0;i<200;i++)delay5us();
412                     asm("clrwdt");
413                     
414                     RemoteID_Index ++;                        //address index
415                     iic_write_byte_to_addr(0xFB,RemoteID_Index);
416                     for(i=0;i<200;i++)delay5us();
417                     asm("clrwdt");
418                     
419                     if(RemoteID_Index >= 48)                //Remote Number Max 8,save
420                         RemoteID_Index = 0;
421                     
422                     My_Led_Blink = 10;
423                     RX_Delay = 300;
424                     My_Mode = 0;
425                     Learn_Time_ms = 0;                        //Exit learn mode
426                 }
427             }
428             else                                        //CMD from Remote
429             {
430                 //it is faster to get id from RAM than ROM.
431                 if(DATA_RECEIVED == My_Remot0ID)
432                 {
433                     tmp = 0;
434                     j = Device_Sys_Mode & 0xF0;
435                     if(j == 0x20 || j == 0x30 || j==40);
436                     else 
437                     {
438                         My_Remot0ID = 0;
439                         tmp = 1;
440                     }
441                 }
442                 else                                     //read from ROM
443                 {
444                     for(tmp=0,j=0;tmp<16;tmp++)
445                     {
446                         i=iic_read_byte_from_addr(j);    //id high 8bits
447                         i<<=8;
448                         j++;
449                         i|=iic_read_byte_from_addr(j);    //id low 8bits
450                         j++;
451                         Device_Sys_Mode = iic_read_byte_from_addr(j);//mode and command
452                         j++;
453                         asm("clrwdt");
454                         if(DATA_RECEIVED == i)
455                         {
456                             tmp = 0;
457                             break;
458                         }
459                     }
460                 }
461                 if(!tmp )    //id active
462                 {
463                     tmp = Device_Sys_Mode&0xF0;                //mode
464                     j = Device_Sys_Mode&0x0F;                //command
465                     switch (tmp)
466                     {
467                         case 0x20:                            //Normal
468                         {
469                             if(CMD_VALUE == j)
470                             {
471                                 RELAY_CTL = 1;
472                             }
473                             else
474                             {
475                                 RELAY_CTL = 0;
476                             }
477                             if(My_Led_Blink == 0) My_Led_Blink = 1;
478                             break;
479                         }
480                         case 0x30:                            //XOR
481                         {
482                             if(CMD_VALUE == j)
483                             {
484                                 RELAY_CTL ^= 1;
485                                 RX_Delay = 300;                //delay to avoid repeat
486                                 if(My_Led_Blink == 0) My_Led_Blink = 1;
487                             }
488                             
489                             break;
490                         }
491                         case 0x40:                            //Inching
492                         {
493                             if(CMD_VALUE == j)
494                             {
495                                 RELAY_CTL = 1;
496                                 Inching_Trigger = 50;        //500ms
497                                 if(My_Led_Blink == 0) My_Led_Blink = 1;
498                             }
499                             break;
500                         }
501                         default:
502                         {
503                             break;
504                         }
505                     }
506                 }
507             }
508             GIE = 1;                            //exit critical code to open the receiver.
509             DATA_RECEIVED = 0;
510         }
511     }
512 }
513 
514 /*******************************************
515 **     Timer0 PB interrupt
516 **    Timer=50us
517 **     PB0 interrupt
518 **    RF data received
519 ********************************************/
520 void interrupt Isr_Routine()
521 {
522     static unsigned int id,tmp;
523     static unsigned char bits_of_byte,TAR_50us,SysTick;
524     static unsigned long one_byte;
525     unsigned char IO_State;
526     if(T0IF)                        //TIMER0 Interrupt
527     {
528         T0IF = 0;
529         if(SysTick++ >= 200)            // 200*50us = 10ms
530         {
531             if(My_Led_Blink != 0)
532             {
533                 if(My_Led_Delay++ < 5)    
534                     LED_4 = 0;
535                 else if(My_Led_Delay < 20)
536                     LED_4 = 1;
537                 else 
538                 {
539                     My_Led_Delay = 0;
540                     My_Led_Blink--;
541                 }
542             }
543             else if(Learn_Time_ms >= 1)
544             {
545                 if((My_Mode&0xF0)==0x20)        //blinks once
546                 {
547                     if(My_Led_Delay++ < 10)
548                         LED_4 = 0;
549                     else if(My_Led_Delay < 120)
550                         LED_4 = 1;
551                     else 
552                         My_Led_Delay = 0;
553                 }
554                 else if((My_Mode&0xF0)==0x30)    //blinks twice
555                 {
556                     if(My_Led_Delay++ < 10)    
557                         LED_4 = 0;
558                     else if(My_Led_Delay < 20)    
559                         LED_4 = 1;
560                     else if(My_Led_Delay < 30)    
561                         LED_4 = 0;
562                     else if(My_Led_Delay < 120)
563                         LED_4 = 1;
564                     else
565                         My_Led_Delay = 0;
566                 }
567                 else if((My_Mode&0xF0)==0x40)    //blinks 3
568                 {
569                     if(My_Led_Delay++ < 10)    
570                         LED_4 = 0;
571                     else if(My_Led_Delay < 20)    
572                         LED_4 = 1;
573                     else if(My_Led_Delay < 30)    
574                         LED_4 = 0;
575                     else if(My_Led_Delay < 40)    
576                         LED_4 = 1;
577                     else if(My_Led_Delay < 50)    
578                         LED_4 = 0;
579                     else if(My_Led_Delay < 120)
580                         LED_4 = 1;
581                     else
582                         My_Led_Delay = 0;
583                 }
584                 Learn_Time_ms--;
585                 
586             }
587             else if(Learn_Time_ms==1)
588             {
589                 LED_4 = 1;
590                 Learn_Time_ms--;
591             }
592             if(Inching_Trigger > 1)
593             {
594                 Inching_Trigger--;
595             }
596             else if(Inching_Trigger==1)
597             {
598                 RELAY_CTL = 0;
599                 Inching_Trigger--;
600             }
601             if(RX_Delay!=0)
602                 RX_Delay--;
603             SysTick = 0;
604         }
605         TAR_50us++;
606     }
607     if(PBIF)                        //PORTB Interrupt
608     {
609         PBIF = 0;
610         
611         //----------------------------------------------------------------------------
612         //            RF Data Format:NRZ Encoder
613         //            1B = 1000usH+300usL; 0B = 300usH+1000usL; T = 1300us
614         //            ASM Modulation
615         //----------------------------------------------------------------------------
616         IO_State = (unsigned char)DATA_IN;
617         if(IO_State)                // Low to high transition
618         {
619             // Low state time is upper than 1.5ms,OR Paraser busy, data crash, retry again
620             if((TAR_50us >= 30)||(DATA_RECEIVED!=0)||(RX_Delay!=0))
621             {
622                 START_RX = 0;
623             }
624             TAR_50us = 0;
625         }
626         else                        // High to low transition
627         {
628             if(!START_RX)                                         // The first header doesn't receive
629             {
630                 if((TAR_50us > 14)&&(TAR_50us < 30))             // 1.5ms > T > 0.7ms
631                 {
632                     one_byte = 1;
633                     bits_of_byte = 1;
634                     START_RX = 1;
635                 }
636             }
637             else                                                  // The second header received,
638             {                                                   // start to get RF data
639                 if((TAR_50us >4)&&(TAR_50us< 12))                //0 600us > T > 200us
640                 {
641                     one_byte <<=1;
642                     bits_of_byte++;
643                 }
644                 else if((TAR_50us > 14)&&(TAR_50us < 30))         // 1.5ms > T > 0.7ms
645                 {
646                     one_byte<<=1;
647                     one_byte+=1;
648                     bits_of_byte++;
649                 }
650                 else
651                 {
652                     START_RX = 0x00;                            // data crash, retry again
653                 }
654                 if(bits_of_byte >= 24)                             // got one byte, got id
655                 {
656                     CMD_VALUE = (one_byte&0x0F);                //lowest 4 bits are command
657                     one_byte>>=4;
658                     tmp = one_byte;
659                     if(id != tmp)
660                     {
661                         id = tmp;                                //got new id 
662                     }
663                     else                                        //at least 2 times get the same id
664                     {
665                         DATA_RECEIVED = id;                        //load RF data
666                     }
667                     START_RX = 0x00;                            // Receiving repeat
668                     one_byte = 0;
669                     bits_of_byte = 0;
670                 }
671             }
672             TAR_50us = 0;
673         }
674     }
675 }

Received 1248 code from Remote

posted on 2020-11-26 21:16  Milo_lu  阅读(107)  评论(0编辑  收藏  举报

导航