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 |
*/
|