Project

General

Profile

Statistics
| Revision:

root / branches / lights / projects / libdragonfly / lights.c @ 544

History | View | Annotate | Download (5.71 KB)

1
#include "lights.h"
2
#include "dragonfly_lib.h"
3
#include <avr/interrupt.h>
4

    
5
#define ORB_RESET 1025
6
#define ORBPORT PORTC
7
#define ORBDDR DDRC
8
#define ORBMASK 0x77
9

    
10
/***** Port and Pin Definitions ****/
11

    
12
//Orb Ports and Registers
13
#define ORB_PORT        PORTC
14
#define ORB_DDR         DDRC
15

    
16
//Orb Pins
17
#define ORB1_RED        0x01
18
#define ORB1_GREEN      0x02
19
#define ORB1_BLUE       0x04
20
#define ORB2_RED        0x10
21
#define ORB2_GREEN      0x20
22
#define ORB2_BLUE       0x40
23

    
24
//this used to be 8 but i changed it. i suspect it was 8 cuz of the led pins + 2 enc pins, but not sure
25
#define ORB_COUNT 6        //please dont change this, or bad things might happen, number of orb pins off port, this should more accurately be called LED_COUNT i think
26

    
27
// an orb node
28
struct ORB_NODE {
29
   uint8_t num;
30
   uint16_t angle;
31
   uint16_t port_val;
32
   int time_split; // this will store the amount of time the timer needs to be set to from previous pin
33
} ORB_NODE;
34

    
35
// the status of the orbs
36
struct ORB_STATUS_STRUCT {
37
   struct ORB_NODE orbs[ORB_COUNT];
38
   int changes[ORB_COUNT]; // when an orb changes, its number will go from 0 to 1
39
   uint8_t change_count;
40
   uint8_t new_angles;
41
   uint8_t current_orb;
42
} ORB_STATUS;
43

    
44
struct ORB_CHANGED_ORBS {
45
        int orb_number;
46
        uint16_t new_angle;
47
} ORB_CHANGED_ORBS;
48

    
49
struct ORB_CHANGED_ORBS_STRUCT {
50
        struct ORB_CHANGED_ORBS changed_orbs[ORB_COUNT];
51
} ORB_CHANGED_ORBS_STRUCT;
52

    
53
struct ORB_ORDER { // 0 will store number of first orb to turn off, 1 of second, etc.
54
        int order[ORB_COUNT];
55
} ORB_ORDER;
56

    
57
void sort_orbs(void); // this function will copy new values into angle values
58
void calc_split_times(void); // this function will calculate split times and place them in the appropriate orbs
59

    
60
// use compare C to reset every pulse + check new times
61
SIGNAL (SIG_OUTPUT_COMPARE3C){
62

    
63
      ORB_STATUS.current_orb=0; // reset the orb we're looking at
64

    
65
                if(ORB_STATUS.change_count>0)
66
                {
67
                        sort_orbs();
68
                        calc_split_times();
69
                }
70
          
71
          // now that we've done everything, turn on all the lights
72
          ORB_PORT |= ORBMASK;
73
          // reset the time
74
          OCR3C = TCNT3+ORB_RESET;
75
          // turn ocr3a back on and set the time for the lights off counter
76
          ETIMSK |= _BV(OCIE3A); //turn on oc3a interrupt
77
          OCR3A = TCNT3+ORB_STATUS.orbs[0].time_split; //set time
78
          
79
}
80

    
81
// use compare A for turning lights off
82
SIGNAL (SIG_OUTPUT_COMPARE3A){
83
                //pull the correct ones down
84
      ORBPORT &= ~(ORB_STATUS.orbs[ORB_ORDER.order[ORB_STATUS.current_orb]].port_val);
85
          
86
          int num_updated_orbs = 1;
87
                // HERE, YOU ALSO NEED TO CHECK IF ANY OTHER ORBS HAVE THE SAME TIME!!!!!!!!!!!!!!!!@#!#!@#!@#!@#, update num updated
88
      
89
          ORB_STATUS.current_orb+=num_updated_orbs; //now look at next orb transition
90

    
91
      if (ORB_STATUS.current_orb < ORB_COUNT) { //if it isnt the end...
92
                        //setup timer for next pull down
93
         OCR3C = TCNT3+ORB_STATUS.orbs[ORB_STATUS.current_orb].time_split;
94
                 
95
     }
96
      else { //we are done with these pulses
97
                //turn off this timer until it is reset
98
                ETIMSK &= ~(_BV(OCIE3A)); 
99
          }
100

    
101
}
102

    
103
void orb_init()
104
{
105
   uint8_t mysreg;
106
      int i;
107
        ORBDDR |= ORBMASK;        //make all the pins output ports
108

    
109
   
110
        mysreg=SREG;
111
        cli(); //turn off interrupts for now
112

    
113
        //we're looking at the 1st orb
114
        ORB_STATUS.current_orb=0;
115
        //store values
116
        for (i = 0; i < ORB_COUNT; ++i) {
117
      ORB_STATUS.orbs[i].num = i;
118
          //i'm not sure why he starts at 1023, so i'm making it 0 for now
119
      ORB_STATUS.orbs[i].angle = 0; //1023;        //127 is a pretty stupid start angle, but oh well
120
          ORB_STATUS.changes[i]=1; // each orb has been "changed"
121
        }
122
        ORB_STATUS.orbs[0].port_val=ORB1_RED;
123
        ORB_STATUS.orbs[1].port_val=ORB1_GREEN;
124
        ORB_STATUS.orbs[2].port_val=ORB1_BLUE;
125
        ORB_STATUS.orbs[3].port_val=ORB2_RED;
126
        ORB_STATUS.orbs[4].port_val=ORB2_GREEN;
127
        ORB_STATUS.orbs[5].port_val=ORB2_BLUE;
128
        
129
        //init timer3
130
        TCCR3A = 0; // sets normal operation
131
        TCCR3B = _BV(CS31); //set a prescale of 8
132
        TCCR3C = 0; // sets normal operation
133
        ETIMSK |= _BV(OCIE3C); //turn on oc3c interrupt
134
        ETIMSK |= _BV(OCIE3A); //turn on oc3a interrupt
135
        OCR3C = TCNT3+ORB_RESET; // WHAT HAPPENS IF THE TIMER IS ON FOR A VERY LONG TIME; OVERFLOW?
136
        OCR3A = TCNT3+ORB_RESET;
137
        
138
        SREG=mysreg;
139
}
140

    
141
//sets a channel to a value
142
void orb_set_angle(int orb, int angle) {
143
        uint8_t mysreg;
144
        
145
        orb=orb&0x07; //only have 8
146
        angle=angle&0xff; //only accept 0-255
147
        angle=255-angle; //inverse intensity
148

    
149
/*
150
        angle=angle<<2; //scale up so that we dont run it too often
151
        angle+=3; //0 values dont really work
152
  */
153
  
154
        // check if the angle is different, if it is, update our status
155
        if(angle!=ORB_STATUS.orbs[orb].angle)
156
        {
157
                ORB_STATUS.new_angles++;
158
                ORB_STATUS.changes[orb]=1;
159
        }
160
  
161
        mysreg=SREG;
162
        cli();
163
  ORB_CHANGED_ORBS_STRUCT.changed_orbs[orb].new_angle=angle;
164
//    ORB_STATUS.orbs[orb].angle = angle; //update angle
165
        SREG = mysreg;
166

    
167
  // dont see why you need to track changes, so might as well just change it
168
  /*
169
        mysreg=SREG;
170
        cli();
171
    ORB_STATUS.orb_angles[orb] = angle; //update angle
172
        SREG = mysreg;
173
        */
174
/*
175
        if (ORB_STATUS.orb_angles[orb] != angle) { //if the angle has changed
176
          mysreg=SREG; 
177
          cli(); //disable interrupts
178
      ORB_STATUS.orb_angles[orb] = angle; //update angle
179
      ORB_STATUS.new_angles = 1;
180
          SREG=mysreg; //put interrupt status back
181
   }
182
   */
183
}
184

    
185
void orb1_set(unsigned char red, unsigned char green, unsigned char blue)
186
{
187
        orb_set_angle(0,red);
188
        orb_set_angle(1,green);
189
        orb_set_angle(2,blue);
190
}
191

    
192
void orb2_set(unsigned char red, unsigned char green, unsigned char blue)
193
{
194
        orb_set_angle(3,red);
195
        orb_set_angle(4,green);
196
        orb_set_angle(5,blue);
197
}
198

    
199

    
200
/*
201
        PORTC = 0bFF; //turns on all lights
202
        PORTC &= ~0x08; //turns off light in 4th bit (enc_cs)
203
*/