andrewm@268
|
1 /*
|
andrewm@268
|
2 * render.cpp
|
andrewm@268
|
3 *
|
andrewm@268
|
4 * Created on: Oct 24, 2014
|
andrewm@268
|
5 * Author: parallels
|
andrewm@268
|
6 */
|
andrewm@268
|
7
|
andrewm@268
|
8
|
giuliomoro@301
|
9 #include <Bela.h>
|
andrewm@268
|
10
|
andrewm@268
|
11 const int kStepLengthSlow = 1000;
|
andrewm@268
|
12 const int kStepLengthFast = 500;
|
andrewm@268
|
13
|
andrewm@268
|
14 int gStepLengthSamples = kStepLengthSlow;
|
andrewm@268
|
15
|
andrewm@268
|
16 const int gPinA1 = P8_27;
|
andrewm@268
|
17 const int gPinA2 = P8_28;
|
andrewm@268
|
18 const int gPinB1 = P8_29;
|
andrewm@268
|
19 const int gPinB2 = P8_30;
|
andrewm@268
|
20 const int gPinServo = P9_16;
|
andrewm@268
|
21
|
andrewm@268
|
22 int gStepCounter = 0;
|
andrewm@268
|
23 int gPhase = 0;
|
andrewm@268
|
24
|
andrewm@268
|
25 int gServoCounter = 0;
|
andrewm@268
|
26
|
andrewm@268
|
27
|
andrewm@268
|
28 enum {
|
andrewm@268
|
29 kStateMoveRight1 = 0,
|
andrewm@268
|
30 kStateMoveLeft1,
|
andrewm@268
|
31 kStateMoveRight2,
|
andrewm@268
|
32 kStateMoveLeft2,
|
andrewm@268
|
33 kStateMoveRight3,
|
andrewm@268
|
34 kStateMoveLeft3,
|
andrewm@268
|
35 kStateSpin,
|
andrewm@268
|
36 kStateMax
|
andrewm@268
|
37 };
|
andrewm@268
|
38
|
andrewm@268
|
39 int gState = 0;
|
andrewm@268
|
40 int gStateCounter = 0;
|
andrewm@268
|
41
|
andrewm@268
|
42 // setup() is called once before the audio rendering starts.
|
andrewm@268
|
43 // Use it to perform any initialisation and allocation which is dependent
|
andrewm@268
|
44 // on the period size or sample rate.
|
andrewm@268
|
45 //
|
andrewm@268
|
46 // userData holds an opaque pointer to a data structure that was passed
|
andrewm@268
|
47 // in from the call to initAudio().
|
andrewm@268
|
48 //
|
andrewm@268
|
49 // Return true on success; returning false halts the program.
|
andrewm@268
|
50
|
giuliomoro@301
|
51 bool setup(BelaContext *context, void *userData)
|
andrewm@268
|
52 {
|
andrewm@268
|
53 // This project makes the assumption that the audio and digital
|
andrewm@268
|
54 // sample rates are the same. But check it to be sure!
|
andrewm@268
|
55 if(context->audioFrames != context->digitalFrames) {
|
andrewm@268
|
56 rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
|
andrewm@268
|
57 return false;
|
andrewm@268
|
58 }
|
andrewm@268
|
59
|
andrewm@310
|
60 pinMode(context, 0, gPinA1, OUTPUT);
|
andrewm@310
|
61 pinMode(context, 0, gPinA2, OUTPUT);
|
andrewm@310
|
62 pinMode(context, 0, gPinB1, OUTPUT);
|
andrewm@310
|
63 pinMode(context, 0, gPinB2, OUTPUT);
|
andrewm@310
|
64 pinMode(context, 0, gPinServo, OUTPUT);
|
andrewm@268
|
65
|
andrewm@268
|
66 return true;
|
andrewm@268
|
67 }
|
andrewm@268
|
68
|
andrewm@268
|
69 // render() is called regularly at the highest priority by the audio engine.
|
andrewm@268
|
70 // Input and output are given from the audio hardware and the other
|
andrewm@268
|
71 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
|
andrewm@268
|
72 // will be 0.
|
andrewm@268
|
73
|
giuliomoro@301
|
74 void render(BelaContext *context, void *userData)
|
andrewm@268
|
75 {
|
andrewm@268
|
76 for(unsigned int n = 0; n < context->audioFrames; n++) {
|
andrewm@268
|
77 if(gPhase == 0 || gPhase == 1) {
|
andrewm@308
|
78 digitalWriteOnce(context, n, gPinB1, HIGH);
|
andrewm@308
|
79 digitalWriteOnce(context, n, gPinB2, LOW);
|
andrewm@268
|
80 }
|
andrewm@268
|
81 else {
|
andrewm@308
|
82 digitalWriteOnce(context, n, gPinB1, LOW);
|
andrewm@308
|
83 digitalWriteOnce(context, n, gPinB2, HIGH);
|
andrewm@268
|
84 }
|
andrewm@268
|
85
|
andrewm@268
|
86 if(gPhase == 1 || gPhase == 2) {
|
andrewm@308
|
87 digitalWriteOnce(context, n, gPinA1, HIGH);
|
andrewm@308
|
88 digitalWriteOnce(context, n, gPinA2, LOW);
|
andrewm@268
|
89 }
|
andrewm@268
|
90 else {
|
andrewm@308
|
91 digitalWriteOnce(context, n, gPinA1, LOW);
|
andrewm@308
|
92 digitalWriteOnce(context, n, gPinA2, HIGH);
|
andrewm@268
|
93 }
|
andrewm@268
|
94
|
andrewm@268
|
95 if(--gServoCounter > 0)
|
andrewm@308
|
96 digitalWriteOnce(context, n, gPinServo, HIGH);
|
andrewm@268
|
97 else
|
andrewm@308
|
98 digitalWriteOnce(context, n, gPinServo, LOW);
|
andrewm@268
|
99
|
andrewm@268
|
100 if(++gStepCounter >= gStepLengthSamples) {
|
andrewm@268
|
101 gStateCounter++;
|
andrewm@268
|
102
|
andrewm@268
|
103 switch(gState) {
|
andrewm@268
|
104 case kStateMoveRight1:
|
andrewm@268
|
105 case kStateMoveRight2:
|
andrewm@268
|
106 case kStateMoveRight3:
|
andrewm@268
|
107 gPhase = (gPhase + 1) & 3;
|
andrewm@268
|
108 break;
|
andrewm@268
|
109 case kStateMoveLeft1:
|
andrewm@268
|
110 case kStateMoveLeft2:
|
andrewm@268
|
111 case kStateMoveLeft3:
|
andrewm@268
|
112 gPhase = (gPhase + 3) & 3;
|
andrewm@268
|
113 break;
|
andrewm@268
|
114 case kStateSpin:
|
andrewm@268
|
115 gPhase = (gPhase + 1) & 3;
|
andrewm@268
|
116 break;
|
andrewm@268
|
117 }
|
andrewm@268
|
118
|
andrewm@268
|
119 if(gState == kStateSpin) {
|
andrewm@268
|
120 if(gStateCounter >= 48) {
|
andrewm@268
|
121 gStateCounter = 0;
|
andrewm@268
|
122 gState = 0;
|
andrewm@268
|
123 gStepLengthSamples = kStepLengthSlow;
|
andrewm@268
|
124 }
|
andrewm@268
|
125 }
|
andrewm@268
|
126 else {
|
andrewm@268
|
127 if(gStateCounter >= 16) {
|
andrewm@268
|
128 gStateCounter = 0;
|
andrewm@268
|
129 gState++;
|
andrewm@268
|
130 if(gState & 1)
|
andrewm@268
|
131 gServoCounter = 120;
|
andrewm@268
|
132 else
|
andrewm@268
|
133 gServoCounter = 80;
|
andrewm@268
|
134 if(gState == kStateSpin)
|
andrewm@268
|
135 gStepLengthSamples = kStepLengthFast;
|
andrewm@268
|
136 }
|
andrewm@268
|
137 }
|
andrewm@268
|
138
|
andrewm@268
|
139 gStepCounter = 0;
|
andrewm@268
|
140 }
|
andrewm@268
|
141 }
|
andrewm@268
|
142 }
|
andrewm@268
|
143
|
andrewm@268
|
144 // cleanup() is called once at the end, after the audio has stopped.
|
andrewm@268
|
145 // Release any resources that were allocated in setup().
|
andrewm@268
|
146
|
giuliomoro@301
|
147 void cleanup(BelaContext *context, void *userData)
|
andrewm@268
|
148 {
|
andrewm@268
|
149
|
andrewm@268
|
150 }
|