-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathyapg.c
executable file
·182 lines (152 loc) · 4.45 KB
/
yapg.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// evan kahn
// e155, final project
#include "easyPIO.h"
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <signal.h>
#include <math.h>
#define PI 3.14159265
#define LEDOUT 1 // turn on for LED output
#define DEBUG 0 // turn on for debug prints
#define RPM 500 // set rotation speed here
uint16_t pixels, revs, total_frames, speed;
struct pixel {
unsigned char r, g, b;
};
//help with pixel_data structure from eric mueller; adapted from following code:
// https://gist.github.com/hmc-cs-emueller/c4ebbe9f3b4064fed16a
struct pixel *getPixel(struct pixel *frames, unsigned i, unsigned j, unsigned k){
unsigned addr = i + j * pixels + k * pixels * revs;
return frames + addr;
}
// details on gamma correction here:
// https://learn.adafruit.com/led-tricks-gamma-correction/the-quick-fix
unsigned char gamma_correct(unsigned char color){
int corrected = pow(color,3)/(255*255);
return (unsigned char) corrected;
}
void setLED (struct pixel *p){
if (LEDOUT){
spiSendReceive(0xff); // full brightness; sending partial brightness on APA102 is pointless
spiSendReceive(gamma_correct(p->b));
spiSendReceive(gamma_correct(p->g));
spiSendReceive(gamma_correct(p->r));
}
}
// LED information here:
// https://cdn-shop.adafruit.com/datasheets/APA102.pdf
void initFrame (){
int i;
if (LEDOUT) for (i=0;i<4;i++) spiSendReceive(0x00);
}
void endFrame (){
if (LEDOUT){ // end SPI frame
spiSendReceive(0xff);
spiSendReceive(0xff);
spiSendReceive(0xff);
spiSendReceive(0xff);
}
}
void lightUp(struct pixel *frames, int revnum, int framenum){
int i;
initFrame();
struct pixel *p;
if (DEBUG == 1) printf("\nbegin horiz %d\n", revnum);
for (i=0;i<pixels;i++){
p = getPixel(frames, i, revnum, framenum);
if (DEBUG){
printf("%02d 0x%02x%02x%02x ",i,p->b,p->g,p->r);
}
setLED(p);
if (DEBUG && ((i+1) % 8 == 0)) printf("\n");
}
endFrame();
}
void sighandler (int sig){ // if user hits ctrl-C during operation, shut down the globe
if (LEDOUT){
digitalWrite(22, 0);
delayMicros(100000);
int i;
struct pixel p;
p.r = 0x00;
p.g = 0x00;
p.b = 0x00;
initFrame();
for (i = 0; i < pixels; ++i){
setLED(&p); // turn off all LEDs
}
endFrame();
}
exit(0);
}
int main() {
signal(SIGINT, sighandler);
unsigned int time_1;
if (LEDOUT){ // if we're writing to LEDs and not debugging
pioInit();
spiInit(10000000); // initialize SPI output to LED strip
pinMode(22, OUTPUT); // pin 22 tells the FPGA to turn the motor on
pinMode(27, OUTPUT); // pin 27 resets the FPGA
digitalWrite(27, 1); // reset the FPGA
delayMicros(10000);
digitalWrite(27, 0);
}
// frames per revolution: revs
// revolutions per second: revs/60
// seconds per revolution: 60/RPM
// seconds per frame: 60/revs/RPM
// microseconds per frame: 1000000 * 60 / (revs * RPM)
unsigned revolutions = 0;
struct pixel *frames;
char fname[64];
int done = 0;
FILE *fp;
do{
printf("Enter filename: ");
scanf("%s",fname);
strcat(fname, ".led");
if( access( fname, F_OK ) != -1 ) {
fp = fopen(fname, "r");
uint8_t p1, p2, r1, r2, s1, s2, f1, f2;
fscanf(fp, "%c%c%c%c%c%c%c%c", &p1, &p2, &r1, &r2, &s1, &s2, &f1, &f2);
pixels = (p1 << 8) | p2;
revs = (r1 << 8) | r2;
speed = (s1 << 8) | s2;
total_frames = (f1 << 8) | f2;
char junk;
fscanf(fp, "%c%c%c%c", &junk, &junk, &junk, &junk);
unsigned long size = pixels * revs * total_frames * sizeof(struct pixel);
frames = malloc(size);
if (!frames){
printf("malloc failed");
exit(1);
}
memset(frames, 0x00, size);
fread(frames, sizeof(char), size, fp); // load frame data into memory
done = 1;
}else{
printf("not found.\n");
}
}while (!done);
digitalWrite(22,1);
int revnum = revs - 1; // revs counts the number of vertical lines in one full revolution
int delay = 1000000 * 60 / (revs * RPM); // constant delay based on motor speed and revs
int framenum = 0; // if we are displaying an animation, keep track of what frame we're on
while(1){
time_1 = getTime();
lightUp(frames,revnum, framenum);
if (revnum == 0) revnum = revs - 1;
else revnum = revnum - 1;
if (revnum == 0){
++revolutions;
}
if (revolutions == speed){ // speed variable controls the number of times one frame of an animation is displayed
revolutions = 0;
framenum = ((framenum + 1)%total_frames); // increment frame
}
while (getTime() < time_1 + delay){}; // wait until next line should be displayed
}
printf("\n");
return(0);
}