Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
285 noddan 1
/**
286 noddan 2
 * CAN RGB LED. This application is used to control a RGB LED.
287 noddan 3
 * Still under heavy development
285 noddan 4
 *
306 noddan 5
 * @date    2007-02-10
286 noddan 6
 * @author  Martin Nordén
306 noddan 7
 *
8
 * Set RGB: <byte0 RGBLED_CMD_SETRGB> <byte 1 Set/Fade> <byte2 R> <byte3 G> <byte4 B>
9
 * Change RGB: <byte 0 RGBLED_CMD_CHANGERGB> <byte 1 int R> <byte 2 int G> <byte 3 int B>  (Note that they are all signed)
10
 * Set Intens: <byte0 RGBLED_CMD_SETINTENS> <byte1 Set/Fade> <byte2 Intens> (<byte3 dimSpeed>)
11
 *
12
 * TODO: Better CAN Integration, Failsafe mode, Tempsensors etc.
285 noddan 13
 */
14
 
306 noddan 15
 
285 noddan 16
/*-----------------------------------------------------------------------------
17
 * Includes
18
 *---------------------------------------------------------------------------*/
19
/* system files */
20
#include <avr/io.h>
21
#include <avr/interrupt.h>
22
#include <avr/wdt.h>
23
#include <stdio.h>
306 noddan 24
#include <avr/pgmspace.h> //To allow read/write from flash
285 noddan 25
/* lib files */
26
#include <can.h>
27
#include <serial.h>
28
#include <timebase.h>
302 noddan 29
#include <math.h> //Not sure this is needed anymore..
285 noddan 30
 
306 noddan 31
/*----------------------------------------------------------------------------
32
 * Defines
33
 * -------------------------------------------------------------------------*/
301 noddan 34
 
306 noddan 35
//Not implemented yet. Will be implementet when I build a canUSB :)
36
 
37
#define RGBLED_CMD_GET      0x1400
38
#define RGBLED_CMD_SEND     0x1401
39
 
40
#define RGBLED_CMD_STATUS       0x00    /* Get status */
41
#define RGBLED_CMD_SETRGB       0x01    /* Set RGB Triplet */
42
#define RGBLED_CMD_CHANGERGB  0x02  /* Change RGB +/- */
43
#define RGBLED_CMD_SETINTENS  0x10  /* Set intensity */
44
 
301 noddan 45
/*----------------------------------------------------------------------------
46
 * Ehm, struct?
47
 * -------------------------------------------------------------------------*/
302 noddan 48
typedef struct
301 noddan 49
{
50
    uint8_t R;
51
    uint8_t G;
52
    uint8_t B;
53
    uint8_t Intens;
302 noddan 54
} Color;
55
 
56
/*-----------------------------------------------------------------------------
306 noddan 57
 * Programs! There will be a better way to add programs here.. some day.
302 noddan 58
 *---------------------------------------------------------------------------*/
59
 
305 noddan 60
//Special combinations that means something special
61
//The combinations are useless for lighting anyway
62
//So we might as well use them!
63
//0x00, 0x00, 0x00, 0x00 means end of program, keep looping it
64
//0x00, 0x00, 0x00, 0x01 means end of program, halt 
304 noddan 65
 
66
Color pgm1[] PROGMEM = {
306 noddan 67
{0xff,0x00,0x00,0x64},
68
{0xff,0xff,0x00,0x10},
69
{0x00,0xff,0x00,0xa0},
70
{0x00,0xff,0xff,0x7f},
71
{0x00,0x00,0xff,0x7f},
72
{0xff,0x00,0xff,0x40},
73
{0x00,0x00,0x00,0x00}
74
};
75
 
76
Color pgm2[] PROGMEM = {
304 noddan 77
{0xff,0x00,0x00,0x00},
78
{0xff,0xff,0x00,0x00},
306 noddan 79
{0xff,0xff,0xff,0x00},
80
{0xa0,0x00,0xa0,0x00},
304 noddan 81
{0x00,0x00,0xff,0x00},
82
{0x00,0x00,0x00,0x00}
301 noddan 83
};
84
 
306 noddan 85
Color pgm3[] PROGMEM = {
86
{0xff,0xff,0xff,0x00},
87
{0x00,0x00,0x00,0x01}
302 noddan 88
};
89
 
304 noddan 90
Color* programs[] PROGMEM = {
91
(Color*)pgm1,
306 noddan 92
(Color*)pgm2,
93
(Color*)pgm3
302 noddan 94
};
95
 
96
 
97
 
285 noddan 98
/*-----------------------------------------------------------------------------
99
 * Variables
100
 *---------------------------------------------------------------------------*/
289 noddan 101
uint32_t timeStamp; //TimeStamp to keep track of time
102
uint32_t dimStamp;  //Timestamp to keep track of dimmer changes
285 noddan 103
 
306 noddan 104
Color currColor;    //Current color
105
Color destColor;    //Destination color
285 noddan 106
 
289 noddan 107
uint16_t fadeSpeed; //Fadingspeed. 16bit for reaaaally slow fading. Sets the speed of colorchange.
108
uint8_t dimSpeed;       //Dimmer speed. Sets the speed of intensitychange.
285 noddan 109
 
306 noddan 110
uint8_t currProgram;    //This variable keeps track of what program is currently running. 
111
uint8_t programMode;    //This keeps track of what mode we are currently using. 0: the program obeyes the current brightness, 1: the program is allowed to set it's own brightness
289 noddan 112
 
285 noddan 113
/*----------------------------------------------------------------------------
114
 * Functions
115
 * -------------------------------------------------------------------------*/
116
void updateLED();
301 noddan 117
void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright);
298 noddan 118
void changeColor(int8_t amount, uint8_t* color);
302 noddan 119
void fade(uint8_t* current, uint8_t* destination);
285 noddan 120
 
121
/*-----------------------------------------------------------------------------
122
 * Main Program
123
 *---------------------------------------------------------------------------*/
124
int main(void) {
125
    Timebase_Init();
126
    Serial_Init();
286 noddan 127
    Can_Init();
285 noddan 128
 
129
//Setting up OC1A, 16 bit counter used as 8 bit.
130
    TCCR1A |= (1<<COM1A1) | (1<<WGM11); /* Set OC1A at TOP, mode 14 */
301 noddan 131
    TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS12); /* Timer uses main system clock with ? prescale */
285 noddan 132
    ICR1 = 256; //8 bit precision to match the other two counters.
298 noddan 133
    OCR1A = 0;  //0% as standard
285 noddan 134
    DDRB |= (1<<PB1); /* Enable pin as output */
298 noddan 135
//Setting up OC0A
302 noddan 136
    TCCR0A |= (1<<COM0A1)|(1<<WGM01)|(1<<WGM00); /* Set OC0A at TOP, Mode 7 */
137
    TCCR0B |= (1<<CS02); /* Prescaler updating now */
138
    OCR0A = 0;  //0% standard
139
    DDRD |= (1<<PD6);
298 noddan 140
//Setting up OC0B
302 noddan 141
    TCCR0A |= (1<<COM0B1);
142
    OCR0B = 0;
143
    DDRD |= (1<<PD5);
291 noddan 144
 
285 noddan 145
//Initialize variables
298 noddan 146
    fadeSpeed = 10;
306 noddan 147
    dimSpeed = 10;
286 noddan 148
    timeStamp = 0;
289 noddan 149
    dimStamp = 0;
301 noddan 150
    Can_Message_t rxMsg;   
285 noddan 151
 
301 noddan 152
    reformatRGB(0x00,0xff,0x00,1);
306 noddan 153
    destColor.Intens = 250;
301 noddan 154
    currColor = destColor;
285 noddan 155
 
301 noddan 156
//Just temporary for now, they keep track of some kind of demo-program.
305 noddan 157
    currProgram = 1;
306 noddan 158
    programMode = 0;
305 noddan 159
    uint16_t temp_adress = pgm_read_word(&programs[currProgram-1]); //Get adress for program 0
287 noddan 160
 
301 noddan 161
    sei();
298 noddan 162
 
285 noddan 163
    /* main loop */
164
    while (1) {
165
        /* service the CAN routines */
166
        Can_Service();
286 noddan 167
 
289 noddan 168
        /* Time to fade color? */
301 noddan 169
        if (Timebase_PassedTimeMillis(timeStamp) >= fadeSpeed) {
302 noddan 170
            fade(&currColor.R, &destColor.R);          
171
            fade(&currColor.G, &destColor.G);
172
            fade(&currColor.B, &destColor.B);
298 noddan 173
 
285 noddan 174
            timeStamp = Timebase_CurrentTime();
175
            updateLED();
176
        }
177
 
178
 
289 noddan 179
        /* Time to fade intensity? */
180
        if (Timebase_PassedTimeMillis(dimStamp) >= dimSpeed) {
302 noddan 181
            fade(&currColor.Intens, &destColor.Intens);
289 noddan 182
            dimStamp = Timebase_CurrentTime();
183
            updateLED();
184
        }
185
 
186
 
302 noddan 187
        /* Program management */
305 noddan 188
        if (currProgram != 0){ //Check if a program is currently running
189
            if ((currColor.R == destColor.R)&(currColor.G == destColor.G)&(currColor.B == destColor.B)&(currColor.Intens == destColor.Intens)){//Is the current sequence finished?
190
                //Now we have to check if the program is finished and if we should loop
191
                if ((pgm_read_byte(temp_adress)==0)&(pgm_read_byte(temp_adress+1)==0)&(pgm_read_byte(temp_adress+2)==0)){
192
                    //The program has ended! Shall we loop it?
193
                    if (pgm_read_byte(temp_adress+3)==0){
194
                        //Yes, let's loop it
195
                        temp_adress = pgm_read_word(&programs[currProgram-1]);
196
                    } else {
197
                        //No, halt!
198
                        currProgram = 0;
199
                    }
200
                } else {
201
                    //The program has not ended, let's get the next RGB-triplet!
306 noddan 202
                    destColor.R = pgm_read_byte(temp_adress);
203
                    destColor.G = pgm_read_byte(temp_adress + 1);
204
                    destColor.B = pgm_read_byte(temp_adress + 2);
205
                    if (programMode == 1){
206
                        destColor.Intens = pgm_read_byte(temp_adress + 3);
207
                    }
208
 
209
                    temp_adress = temp_adress + 4;             
305 noddan 210
                }
211
            }
302 noddan 212
        }
213
 
285 noddan 214
        /* check if any messages have been received */
215
        /* A lot of remote control crap going on here now for testing */
216
        while (Can_Receive(&rxMsg) == CAN_OK) {
306 noddan 217
            if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x01)){
218
                currProgram = 1;
219
                temp_adress = pgm_read_word(&programs[currProgram-1]);
285 noddan 220
            }
221
 
306 noddan 222
            if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x02)){
223
                currProgram = 2;
224
                temp_adress = pgm_read_word(&programs[currProgram-1]);
285 noddan 225
            }
306 noddan 226
 
227
            if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x03)){
228
                currProgram = 3;
229
                temp_adress = pgm_read_word(&programs[currProgram-1]);
230
            }
231
 
232
            if ((rxMsg.Data.bytes[0] == 0xf)&(rxMsg.Data.bytes[3] == 0x00)){
233
                currProgram = 0;
234
            }
235
 
236
 
237
 
286 noddan 238
        }
285 noddan 239
 
286 noddan 240
    }
241
 
242
    return 0;
243
}
285 noddan 244
 
245
 
246
 
247
 
301 noddan 248
/************************************************************************************************
249
 *     updateLED updates the PWM counter values and thus changes the color of the RGBLED.       *
250
 *     It doesn't reculculate anything, except the values to write to the PWM registers.        *
251
 *     TODO: Get rid of the tempcontainer!                                  *
252
 ************************************************************************************************/
286 noddan 253
void updateLED(){
301 noddan 254
    uint8_t tempcontainer;
255
 
256
    tempcontainer = currColor.R * currColor.Intens / 255;   //I really want to skip this, don't know how yet though.
257
    OCR1A = tempcontainer; 
258
      OCR0A = currColor.G * currColor.Intens / 255;
259
    OCR0B = currColor.B * currColor.Intens / 255;      
306 noddan 260
 
261
/*     
302 noddan 262
    //Bara för debugcrap
263
    Can_Message_t txMsg;
264
    txMsg.Id = 0x55;
265
    txMsg.RemoteFlag = 0;
266
    txMsg.ExtendedFlag = 1;
305 noddan 267
    txMsg.DataLength = 8;
268
    txMsg.Data.bytes[0] = currColor.R;
269
    txMsg.Data.bytes[1] = currColor.G;
270
    txMsg.Data.bytes[2] = currColor.B;
301 noddan 271
    txMsg.Data.bytes[3] = currColor.Intens;
305 noddan 272
 
287 noddan 273
    Can_Send(&txMsg);
306 noddan 274
*/
298 noddan 275
}
285 noddan 276
 
277
 
278
 
301 noddan 279
/************************************************************************************************
280
 *     reformatRGB sets a new target RGB triplet to fade to. It reformats it so that            *
281
 *     the highest color always gets 0xff. Brightness is recalculated.                          *
282
 *     if setBright is set to 0, the brightness will not be updated.                    *
283
 *     TODO: Smarter 16-bit arithmetics would be nice. Also a pointer to struct to be updated.  *
284
 ************************************************************************************************/
285
void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright){
298 noddan 286
    uint8_t maxvalue;
287
    uint16_t tempcontainer;
288
 
289
    if ((R>=G)&(R>=B)){
290
        maxvalue = R;
291
    } else if ((G>=R)&(G>=B)){
292
        maxvalue = G;
293
    } else {
294
        maxvalue = B;
295
    }
296
 
297
    tempcontainer = R * 255;
301 noddan 298
    destColor.R = tempcontainer/maxvalue;
298 noddan 299
    tempcontainer = G * 255;
301 noddan 300
    destColor.G = tempcontainer/maxvalue;
298 noddan 301
    tempcontainer = B * 255;
301 noddan 302
    destColor.B = tempcontainer/maxvalue;
298 noddan 303
 
301 noddan 304
    if (setBright){
305
        destColor.Intens = maxvalue;
306
    }
285 noddan 307
}
308
 
286 noddan 309
 
301 noddan 310
/************************************************************************************************
306 noddan 311
 *     fade takes two pointers, current and destination and fades current               *
312
 *     one tick closer to destination.                                                        *
301 noddan 313
 ************************************************************************************************/
302 noddan 314
void fade(uint8_t* current, uint8_t* destination){
315
    if (*current > *destination){
316
        *current = *current - 1;
317
    } else if (*current < *destination){
318
        *current = *current + 1;
289 noddan 319
    }
287 noddan 320
}
298 noddan 321
 
301 noddan 322
 
323
/************************************************************************************************
306 noddan 324
 *     changeColor changes a color accord to amount. -127>127.                                  *
325
 *     color is either dest och curr R,G,B.                                                     *
326
 *     Maybe TODO: If red is already 255 and we want to increase it, decrease the other ones.   *
301 noddan 327
 ************************************************************************************************/
298 noddan 328
void changeColor(int8_t amount, uint8_t* color){
329
    if ( ((amount > 0)&(*color < 255)) || ((amount < 0)&(*color > 0)) ) //Se till att vi inte slĺr över *color
330
    *color = *color + amount;
331
}
301 noddan 332