Subversion Repositories HomeAutomation

Rev

Rev 584 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
413 noddan 1
/**
2
 * CAN RGB LED. This application is used to control a RGB LED.
3
 * Still under heavy development
4
 *
5
 * @date    2007-02-10
546 noddan 6
 * @author  Martin Nordén
413 noddan 7
 *
8
 * TODO: Better CAN Integration, Failsafe mode, Tempsensors etc.
9
 * Also, check current/destination intensity better when in a program?
584 noddan 10
 *
413 noddan 11
 * A little comment here :)
12
 */
13
 
14
 
15
/*-----------------------------------------------------------------------------
16
 * Includes
17
 *---------------------------------------------------------------------------*/
18
/* system files */
19
#include <avr/interrupt.h>
20
#include <inttypes.h>
21
#include <stdio.h>
584 noddan 22
#include <avr/pgmspace.h> //To allow read/write from flash
23
 
24
#include <math.h>
25
 
26
#include <drivers/timer/timebase.h>
27
 
28
#include <config.h> // All configuration parameters
413 noddan 29
#include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
584 noddan 30
 
546 noddan 31
#include <string.h> //for memcpy
413 noddan 32
/* lib files */
33
#include <bios.h>
584 noddan 34
//#include <funcdefs/funcdefs.h>
35
 
36
//#include <settings.h>
413 noddan 37
 
38
/*----------------------------------------------------------------------------
39
 * Defines
40
 * -------------------------------------------------------------------------*/
41
 
42
//Working on implementing all of these...
43
 
44
#define RGBLED_CMD_STATUS           0x00    /* Get status */
45
#define RGBLED_CMD_SETRGB           0x01    /* Set RGB Triplet */
46
#define RGBLED_CMD_CHANGERGB        0x02    /* Change RGB +/- */
810 noddan 47
#define RGBLED_CMD_SETPROGRAM       0x03    /* Set program */
48
#define RGBLED_CMD_SETFADESPEED     0x04    /* Set fadespeed */
49
#define RGBLED_CMD_SETDIMSPEED      0x05    /* Set dimspeed */
50
#define RGBLED_CMD_SETINTENS        0x10    /* Set intensity */
413 noddan 51
 
584 noddan 52
#define APP_TYPE    CAN_APPTYPES_RGBLED
413 noddan 53
#define APP_VERSION 0x0001
54
 
55
#define GROUP_ID    0x01L // FIXME
56
#define TRUE 1
584 noddan 57
#define FALSE !TRUE
413 noddan 58
 
59
 
60
/*----------------------------------------------------------------------------
61
 * Ehm, struct?
62
 * -------------------------------------------------------------------------*/
63
typedef struct
64
{
65
    uint8_t R;
66
    uint8_t G;
67
    uint8_t B;
68
    uint8_t Intens;
69
} Color;
70
 
71
/*-----------------------------------------------------------------------------
72
 * Programs! There will be a better way to add programs here.. some day.
73
 *---------------------------------------------------------------------------*/
74
 
75
//Special combinations that means something special
76
//The combinations are useless for lighting anyway
77
//So we might as well use them!
78
//0x00, 0x00, 0x00, 0x00 means end of program, keep looping it
79
//0x00, 0x00, 0x00, 0x01 means end of program, halt 
80
 
81
Color pgm1[] PROGMEM = {
82
{0xff,0x00,0x00,0x64},
83
{0xff,0xff,0x00,0x10},
84
{0x00,0xff,0x00,0xa0},
85
{0x00,0xff,0xff,0x7f},
86
{0x00,0x00,0xff,0x7f},
87
{0xff,0x00,0xff,0x40},
88
{0x00,0x00,0x00,0x00}
89
};
90
 
91
Color pgm2[] PROGMEM = {
92
{0xff,0x00,0x00,0x00},
93
{0xff,0xff,0x00,0x00},
94
{0xff,0xff,0xff,0x00},
95
{0xa0,0x00,0xa0,0x00},
96
{0x00,0x00,0xff,0x00},
97
{0x00,0x00,0x00,0x00}
98
};
99
 
100
Color pgm3[] PROGMEM = {
101
{0xff,0xff,0xff,0x00},
102
{0x00,0x00,0x00,0x01}
103
};
104
 
105
Color* programs[] PROGMEM = {
106
(Color*)pgm1,
107
(Color*)pgm2,
108
(Color*)pgm3
109
};
110
 
111
 
112
 
113
/*-----------------------------------------------------------------------------
114
 * Global variables
115
 *---------------------------------------------------------------------------*/
116
uint32_t timeStamp; //TimeStamp to keep track of time
117
uint32_t dimStamp;  //Timestamp to keep track of dimmer changes
118
 
119
Color currColor;    //Current color
120
Color destColor;    //Destination color
121
 
122
uint16_t fadeSpeed; //Fadingspeed. 16bit for reaaaally slow fading. Sets the speed of colorchange.
123
uint8_t dimSpeed;       //Dimmer speed. Sets the speed of intensitychange.
124
 
125
uint8_t currProgram;    //This variable keeps track of what program is currently running. 
126
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
584 noddan 127
 
128
Can_Message_t txMsg;    //Transmit message storage
413 noddan 129
 
584 noddan 130
volatile Can_Message_t rxMsg; // Message storage
131
volatile uint8_t rxMsgFull;   // Synchronization flag
132
 
133
uint8_t lastr;
134
uint8_t lastg;
135
uint8_t lastb;
563 andfri 136
 
413 noddan 137
/*----------------------------------------------------------------------------
138
 * Functions
139
 * -------------------------------------------------------------------------*/
546 noddan 140
void updateLED(void);
413 noddan 141
void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright);
142
void changeColor(int8_t amount, uint8_t* color);
143
void fade(uint8_t* current, uint8_t* destination);
144
 
145
 
546 noddan 146
/* Takes care of incoming messages and parses them if this node is adressed */
584 noddan 147
void can_receive(Can_Message_t *msg)
148
{ // CAN callback function
149
    if (!rxMsgFull) {
150
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
151
        rxMsgFull = 1;
152
    }
413 noddan 153
}
154
 
155
 
156
/*-----------------------------------------------------------------------------
157
 * Main Program
158
 *---------------------------------------------------------------------------*/
159
int main(void) {
160
 
161
//Setting up OC1A, 16 bit counter used as 8 bit.
162
    TCCR1A |= (1<<COM1A1) | (1<<WGM11); /* Set OC1A at TOP, mode 14 */
584 noddan 163
    TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11)| (1<<CS10); /* Timer uses main system clock with ? prescale */
413 noddan 164
    ICR1 = 256; //8 bit precision to match the other two counters.
165
    OCR1A = 0;  //0% as standard
166
    DDRB |= (1<<PB1); /* Enable pin as output */
167
//Setting up OC0A
168
    TCCR0A |= (1<<COM0A1)|(1<<WGM01)|(1<<WGM00); /* Set OC0A at TOP, Mode 7 */
584 noddan 169
    TCCR0B |= (1<<CS01)|  (1<<CS00); /* Prescaler updating now */
413 noddan 170
    OCR0A = 0;  //0% standard
171
    DDRD |= (1<<PD6);
172
//Setting up OC0B
173
    TCCR0A |= (1<<COM0B1);
174
    OCR0B = 0;
175
    DDRD |= (1<<PD5);
176
 
177
//Initialize variables
584 noddan 178
    fadeSpeed = 40;
413 noddan 179
    dimSpeed = 10;
180
    timeStamp = 0;
181
    dimStamp = 0;
182
 
183
    reformatRGB(0x00,0x00,0x00,1);
584 noddan 184
    destColor.Intens = 0xa0;
413 noddan 185
    currColor = destColor;
186
 
187
//Just temporary for now, they keep track of some kind of demo-program.
188
    currProgram = 1;
189
    programMode = 0;
190
    uint16_t temp_adress = pgm_read_word(&programs[currProgram-1]); //Get adress for program 0
191
 
192
    sei();
193
 
194
    BIOS_CanCallback = &can_receive;
584 noddan 195
 
413 noddan 196
 
197
//Send a message that we are alive!
198
    txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
199
    txMsg.DataLength = 4;
200
    txMsg.RemoteFlag = 0;
201
    txMsg.ExtendedFlag = 1;
202
    txMsg.Data.words[0] = APP_TYPE;
203
    txMsg.Data.words[1] = APP_VERSION;
584 noddan 204
    BIOS_CanSend(&txMsg);
205
 
206
//Lets get timebase up and running
413 noddan 207
    Timebase_Init();
208
 
209
 
210
    /* main loop */
211
    while (1) {
212
 
213
        /* Time to fade color? */
214
        if ((Timebase_CurrentTime() - timeStamp) >= fadeSpeed) {
215
            fade(&currColor.R, &destColor.R);          
216
            fade(&currColor.G, &destColor.G);
217
            fade(&currColor.B, &destColor.B);
218
 
219
            timeStamp = Timebase_CurrentTime();
220
            updateLED();
221
        }
222
 
223
 
224
        /* Time to fade intensity? */
225
        if (Timebase_CurrentTime() - dimStamp >= dimSpeed) {
226
            fade(&currColor.Intens, &destColor.Intens);
227
            dimStamp = Timebase_CurrentTime();
228
            updateLED();
229
        }
230
 
231
 
232
        /* Program management */
233
        if (currProgram != 0) { //Check if a program is currently running
234
            if ((currColor.R == destColor.R)&(currColor.G == destColor.G)&(currColor.B == destColor.B)&(currColor.Intens == destColor.Intens)){//Is the current sequence finished?
235
                //Now we have to check if the program is finished and if we should loop
236
                if ((pgm_read_byte(temp_adress)==0)&(pgm_read_byte(temp_adress+1)==0)&(pgm_read_byte(temp_adress+2)==0)){
237
                    //The program has ended! Shall we loop it?
238
                    if (pgm_read_byte(temp_adress+3)==0){
239
                        //Yes, let's loop it
240
                        temp_adress = pgm_read_word(&programs[currProgram-1]);
241
                    } else {
242
                        //No, halt!
243
                        currProgram = 0;
244
                    }
245
                } else {
246
                    //The program has not ended, let's get the next RGB-triplet!
247
                    destColor.R = pgm_read_byte(temp_adress);
248
                    destColor.G = pgm_read_byte(temp_adress + 1);
249
                    destColor.B = pgm_read_byte(temp_adress + 2);
250
                    if (programMode == 1){
251
                        destColor.Intens = pgm_read_byte(temp_adress + 3);
252
                    }
253
 
254
                    temp_adress = temp_adress + 4;             
255
                }
256
 
257
            }
258
 
259
        }
584 noddan 260
 
261
 
262
        /* Check if any messages has been recieved */
263
        if (rxMsgFull) {
264
            uint16_t acttype;
265
            uint8_t rgbledid;          
266
 
267
            if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT){
268
                // Actuator package
269
                acttype =(uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE);
270
                rgbledid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);
271
 
272
                if ((acttype == ACT_TYPE_RGBLED) && (rgbledid == THISRGBLEDID)) {                                                          
273
                    // This is a message for this rgbled
546 noddan 274
                    if( rxMsg.Data.bytes[0] == RGBLED_CMD_SETPROGRAM ){
584 noddan 275
                        /* Set a program! Untested! */
546 noddan 276
                        currProgram = rxMsg.Data.bytes[1];
277
                        temp_adress = pgm_read_word(&programs[currProgram-1]);             
278
                    } else if ( rxMsg.Data.bytes[0] == RGBLED_CMD_SETINTENS ){
584 noddan 279
                        /* Set intensity! Works!*/
546 noddan 280
                        if (rxMsg.Data.bytes[1] == TRUE){
281
                            currColor.Intens = rxMsg.Data.bytes[2];                
282
                        }
283
                        destColor.Intens = rxMsg.Data.bytes[2];
284
                        if (rxMsg.Data.bytes[3] != 0){
285
                            dimSpeed = rxMsg.Data.bytes[3];
286
                        }
287
                    } else if( rxMsg.Data.bytes[0] == RGBLED_CMD_SETRGB) {
288
                        /* Set RGB-triplet! */
289
                        reformatRGB(rxMsg.Data.bytes[2],rxMsg.Data.bytes[3],rxMsg.Data.bytes[4],0);
290
                        if (rxMsg.Data.bytes[5] != 0){
291
                            destColor.Intens = rxMsg.Data.bytes[5];
292
                        }
293
                        if (rxMsg.Data.bytes[1] == TRUE){
294
                            currColor = destColor;
295
                        }
413 noddan 296
 
546 noddan 297
                        if (rxMsg.Data.bytes[7] != 0){
298
                            fadeSpeed = rxMsg.Data.bytes[6] * 255 + rxMsg.Data.bytes[7];
299
                        }
300
                        currProgram = 0;               
301
                    }
584 noddan 302
 
303
                }
304
            }
305
            rxMsgFull = 0; //  
306
 
307
        }
546 noddan 308
        /* Done checking incoming packages */
413 noddan 309
 
310
    }
311
 
312
    return 0;
313
}
314
 
315
 
316
 
317
 
318
/************************************************************************************************
319
 *     updateLED updates the PWM counter values and thus changes the color of the RGBLED.       *
320
 *     It doesn't reculculate anything, except the values to write to the PWM registers.        *
546 noddan 321
 *     TODO: Get rid of the tempcontainer!                                                      *
413 noddan 322
 ************************************************************************************************/
323
void updateLED(){
584 noddan 324
    uint8_t tempcontainer;
325
 
326
    tempcontainer = currColor.R * currColor.Intens / 0xff;  //I really want to skip this, don't know how yet though.
327
    OCR1A = tempcontainer;
328
    OCR0A = currColor.G * currColor.Intens / 0xff;
329
    OCR0B = currColor.B * currColor.Intens / 0xff;
330
 
810 noddan 331
    //Just for debug
413 noddan 332
    Can_Message_t txMsg;
333
    txMsg.Id = 0x55;
334
    txMsg.RemoteFlag = 0;
335
    txMsg.ExtendedFlag = 1;
336
    txMsg.DataLength = 4;
584 noddan 337
    txMsg.Data.bytes[0] = currColor.R * currColor.Intens / 0xff;
338
    txMsg.Data.bytes[1] = currColor.G * currColor.Intens / 0xff;
339
    txMsg.Data.bytes[2] = currColor.B * currColor.Intens / 0xff;
340
    txMsg.Data.bytes[3] = currColor.Intens;
413 noddan 341
 
584 noddan 342
    //BIOS_CanSend(&txMsg); //Strictly for debug..
413 noddan 343
 
344
}
345
 
346
 
347
 
348
/************************************************************************************************
349
 *     reformatRGB sets a new target RGB triplet to fade to. It reformats it so that            *
350
 *     the highest color always gets 0xff. Brightness is recalculated.                          *
546 noddan 351
 *     if setBright is set to 0, the brightness will not be updated.                            *
352
 *     TODO: Smarter 16-bit arithmetics would be nice.                                          *
413 noddan 353
 ************************************************************************************************/
354
void reformatRGB(uint8_t R, uint8_t G, uint8_t B, uint8_t setBright){
355
    uint8_t maxvalue;
356
    uint16_t tempcontainer;
357
 
358
    if ((R>=G)&(R>=B)){
359
        maxvalue = R;
360
    } else if ((G>=R)&(G>=B)){
361
        maxvalue = G;
362
    } else {
363
        maxvalue = B;
364
    }
365
 
366
    tempcontainer = R * 255;
367
    destColor.R = tempcontainer/maxvalue;
368
    tempcontainer = G * 255;
369
    destColor.G = tempcontainer/maxvalue;
370
    tempcontainer = B * 255;
371
    destColor.B = tempcontainer/maxvalue;
372
 
373
    if (setBright){
374
        destColor.Intens = maxvalue;
375
    }
376
}
377
 
378
 
379
/************************************************************************************************
546 noddan 380
 *     fade takes two pointers, current and destination and fades current                       *
381
 *     one tick closer to destination.                                                          *
413 noddan 382
 ************************************************************************************************/
383
void fade(uint8_t* current, uint8_t* destination){
384
    if (*current > *destination){
385
        *current = *current - 1;
386
    } else if (*current < *destination){
387
        *current = *current + 1;
388
    }
389
}
390
 
391
 
392
/************************************************************************************************
393
 *     changeColor changes a color accord to amount. -127>127.                                  *
394
 *     color is either dest och curr R,G,B.                                                     *
395
 *     Maybe TODO: If red is already 255 and we want to increase it, decrease the other ones.   *
396
 ************************************************************************************************/
397
void changeColor(int8_t amount, uint8_t* color){
546 noddan 398
    if ( ((amount > 0)&(*color < 255)) || ((amount < 0)&(*color > 0)) ) //Se till att vi inte slår över *color
413 noddan 399
    *color = *color + amount;
400
}
401