001/*****************************************
002 * Program for controlling 8 lights      *
003 * by serial interface                   *
004 * (c) 2005 by Rtm-electronics           *
005 *****************************************/
006//#include <math.h>
007//#include <stdio.h>
008//#include "i2c_ll.h"      // Low-Level Routines
009#include "reg51.h"
010#include "irq52.h"
011#include "rc5.h"
012
013#pragma cpu51 -small    //CPU has only internal RAM
014
015//P(out)=P(max)*((a-1/2*sin(a))/pi) where a is the ignition fase
016
017near char PWM_count [8];
018near char PWM_max [8]={200,200,200,200,200,200,200,200};
019
020code char PWM_KittScanner[15]={180,180,180,180,180,180,140,100,140,180,180,180,180,180,180};
021code char PWM_Wave[15]={170,140,110,100,110,140,170,180,170,140,110,100,110,140,170};
022
023near int  Speed=100;
024near char Intensitie=1;
025near char t,t2;
026near char Command, Effect=255, Peek;
027
028unsigned char bit  Direction=0; 
029unsigned char bit  FirstRun=0; 
030
031IRQ_VECTOR(int0,IRQ_INT0)
032
033void int0 (void) interrupt      //Tension zero-detect
034{
035    //Reset the counters
036    #asm
037            MOV TL0,TH0                     //Reset timer 0 for the fase cutting.
038            MOV _PWM_count  ,_PWM_max       //This seems te be te fastest way to do the job lol...
039            MOV _PWM_count+1,_PWM_max+1     //Total 8*2+2+2+1=21 Cycles = 10.5 uS 
040            MOV _PWM_count+2,_PWM_max+2
041            MOV _PWM_count+3,_PWM_max+3
042            MOV _PWM_count+4,_PWM_max+4
043            MOV _PWM_count+5,_PWM_max+5
044            MOV _PWM_count+6,_PWM_max+6
045            MOV _PWM_count+7,_PWM_max+7
046            //Turn gate current off (this happens before zero-crossing, so the triacs keep on conducting)
047            MOV P1,#255
048    #endasm
049}
050
051IRQ_VECTOR(timer0int,TIMER0)
052
053void timer0int (void) interrupt //20000 Hz = 50uS = 200 interrupts per half cycle (0-100%)
054{
055    #asm   
056            PUSH    PSW                 //2C
057            DJNZ    _PWM_count,next     //2C Counter not zero -> leave bit set to 1 -> No Gate current.
058            CLR     P1.0                //1C Counter zero -> reset bit to 0 -> Gate current on.
059    next:   DJNZ    _PWM_count+1,next2  //2C
060            CLR     P1.1                //1C
061    next2:  DJNZ    _PWM_count+2,next3  //2C
062            CLR     P1.2                //1C
063    next3:  DJNZ    _PWM_count+3,next4  //2C
064            CLR     P1.3                //1C
065    next4:  DJNZ    _PWM_count+4,next5  //2C
066            CLR     P1.4                //1C
067    next5:  DJNZ    _PWM_count+5,next6  //2C
068            CLR     P1.5                //1C
069    next6:  DJNZ    _PWM_count+6,next7  //2C
070            CLR     P1.6                //1C
071    next7:  DJNZ    _PWM_count+7,next8  //2C
072            CLR     P1.7                //1C
073    next8:  DJNZ    _RC5_Timer,TimerOk  //2C Decrease the RC5 bit lenght counter (DJNZ is faster)
074            INC     _RC5_Timer          //1C Don't let the timer underflow.
075TimerOk:    POP     PSW                 //2C + 2C for RETI = 33C = 16,5 uS max
076    #endasm
077}
078
079
080int main (void)
081{
082
083    EA   = 0;       // Disable all Interrupts (not necessary, but a good habbit)
084
085    // Set up UART - Find the description in the User's manual!
086    PCON|=128;      // Baudrate double
087    SCON = 126;     // 8 Bit UART - PC-compatible, TI-FLAG set!
088    TH1=256-(XTAL/(192L*BAUDRATE));   // Calculate baudrate divisor
089    TMOD=32;        // use timer 1 as baudrate generator
090    TCON=64;        // dto.
091                    // Init Timer0 (assume UART initialised by startup code)
092    TMOD &= 0xF0;   ;   // TMOD Timer 0: 8 bit coun
093    TMOD |= 0x02;   // 8 Bit Reload Mode
094    TH0   = -100;   // FRQ is (XTAL/12)/100  = 20,000 kHz : 24.000 MHz
095
096    IT0   = 1;      // EXT0 is edge-triggered
097    ET0   = 1;      // Enable timer0 interrupt
098    EX0   = 1;      // Enable external0 interrupt
099    PT0   = 1;      // Timer0 highest priority interrupt for the closest timing of the fase cutting 
100    PX0   = 1;      // (Was 0) EXT0 2nd highest priority interrupt
101    PT1   = 0;      // Timer 1 in the low priority mode.
102    EA    = 1;      // Global enable all enabled Interrupts
103
104    TR0   = 1;      // Start timer0
105    
106    RC5_Init();     // Start the RC5 decoder
107    while (1)
108    {
109        if ((RC5_GetSystem()&amp;0x1f) =f) ==0x11)  //Wait until the right system code i
110        {
111            Peek=RC5_PeekCommand();
112            if (Peek<0x0a)  //Is the latest RC5 code an effect?
113            {
114                if (Effect!=Peek)
115                {
116                    FirstRun = 1; //Effect changed so this is the first time the effect runs
117                }
118                Effect=Peek;
119            }
120            else
121            {
122                Command=Peek;
123            }
124        }
125        switch  (Effect)
126        {
127            case 0x00:              //All lights on
128            {
129                for (t=0;t<8;t++)
130                {
131                    PWM_max[t]=Intensitie;
132                }
133                _wait_ms(50);
134                break;
135
136            }
137            case 0x01:              //Kitt scanner.
138            {
139                for (t2=0;t2<8;t2++)
140                {
141                    for (t=0;t<8;t++)
142                    {
143                        PWM_max[t]=PWM_KittScanner[t+t2];
144                    }
145                    _wait_ms(Speed);
146                }
147                for (t2=6;t2>0;t2--)
148                {
149                    for (t=0;t<8;t++)
150                    {
151                        PWM_max[t]=PWM_KittScanner[t+t2];
152                    }
153                    _wait_ms(Speed);
154                }
155                break;
156            }
157            case 0x02:
158            {
159                if (FirstRun)
160                {
161                    if (Direction)
162                    {
163                        for(t=0;t<8;t++)
164                        {
165                            PWM_max[t]=(t*25+25);
166                        }
167                    }
168                    else
169                    {
170                        for(t=0;t<8;t++)
171                        {
172                            PWM_max[7-t]=(t*25+25);
173                        }
174                    }
175                    FirstRun=0;
176                }
177                for (t=0;t<8;t++)
178                {
179                    PWM_max[t]+=25;
180                    if (PWM_max[t]>200) PWM_max[t]=25;
181                }
182                _wait_ms(Speed);
183                break;
184            }
185            case 0x03:  //Van rechts naar links
186            {
187                if (Direction)
188                {
189                    for (t2=0;t2<8;t2++)
190                    {
191                        for (t=0;t<8;t++)
192                        {
193                            PWM_max[t]=PWM_Wave[t+t2];
194                        }
195                        _wait_ms(Speed);
196                    }
197                }
198                else
199                {
200                    for (t2=0;t2<8;t2++)
201                    {
202                        for (t=0;t<8;t++)
203                        {
204                            PWM_max[7-t]=PWM_Wave[t+t2];
205                        }
206                        _wait_ms(Speed);
207                    }
208                }
209                break;
210            }
211            case 0x04:
212            {
213                for (t=0;t<8;t++)
214                {
215                    PWM_max[t]=rand()%199+1;
216                }
217                _wait_ms(Speed);
218                break;
219            }
220            case 0x09:  //All lights off
221            {
222                for (t=0;t<8;t++)
223                {
224                    PWM_max[t]=200;
225                }
226                _wait_ms(50);
227                break;
228            }
229        }       
230        switch (Command)
231        {
232            case 0x10:              //Intensitie up
233            {
234                Intensitie--;
235                if (Intensitie<1) Intensitie=1;
236                break;
237            }
238            case 0x11:              //Intensitie down
239            {
240                Intensitie++;
241                if (Intensitie>200) Intensitie=200;
242                break;
243            }
244            case 0x1a:    //Direction right
245            {
246                if (Direction)
247                {
248                    Direction=0;
249                    FirstRun=1;
250                }
251                break;
252            }
253            case 0x1b:    //Direction left
254            {
255                if (!Direction)
256                {
257                    Direction=1;
258                    FirstRun=1;
259                }
260                break;
261            }
262            case 0x1f:        //Search- (Speed--)
263            {
264                Speed-=5;
265                if (Speed <15) Speed=15;
266                break;
267            }
268            case 0x1e:        //Search+ (Speed++)
269            {
270                Speed+=5;
271                if (Speed>1000) Speed=1000;
272                break;
273            }
274        }
275    }
276    return 0;
277}
278