robert@464
|
1 /*
|
robert@464
|
2 ____ _____ _ _
|
robert@464
|
3 | __ )| ____| | / \
|
robert@464
|
4 | _ \| _| | | / _ \
|
robert@464
|
5 | |_) | |___| |___ / ___ \
|
robert@464
|
6 |____/|_____|_____/_/ \_\
|
robert@464
|
7
|
robert@464
|
8 The platform for ultra-low latency audio and sensor processing
|
robert@464
|
9
|
robert@464
|
10 http://bela.io
|
robert@464
|
11
|
robert@464
|
12 A project of the Augmented Instruments Laboratory within the
|
robert@464
|
13 Centre for Digital Music at Queen Mary University of London.
|
robert@464
|
14 http://www.eecs.qmul.ac.uk/~andrewm
|
robert@464
|
15
|
robert@464
|
16 (c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
|
robert@464
|
17 Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
|
robert@464
|
18 Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
|
robert@464
|
19
|
robert@464
|
20 The Bela software is distributed under the GNU Lesser General Public License
|
robert@464
|
21 (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
|
robert@464
|
22 */
|
robert@464
|
23
|
robert@464
|
24
|
robert@464
|
25 #include <Bela.h>
|
robert@464
|
26
|
robert@464
|
27 #define NUM_PINS 12
|
robert@464
|
28
|
robert@464
|
29 // Breadboard wiring layout:
|
robert@464
|
30 // 11 10 12 9 8 7
|
robert@464
|
31 // [ LED DISP ]
|
robert@464
|
32 // 1 2 3 6 4 5
|
robert@464
|
33
|
robert@464
|
34 // Organised by display segments:
|
robert@464
|
35 // e d . X c g b X X X f a
|
robert@464
|
36 const int kPins[NUM_PINS] = {P8_07, P8_08, P8_09, P8_10, P8_11, P8_12,
|
robert@464
|
37 P8_15, P8_16, P8_27, P8_28, P8_29, P8_30};
|
robert@464
|
38
|
robert@464
|
39 // Indices into the above array: pins 12, 9, 8, 6
|
robert@464
|
40 const int kDigits[4] = {9, 8, 7, 3};
|
robert@464
|
41
|
robert@464
|
42 int gCurrentlyDisplayingDigit = 0;
|
robert@464
|
43 int gDigitDisplayTime = 0;
|
robert@464
|
44 const int kDigitMaxDisplayTime = 44;
|
robert@464
|
45
|
robert@464
|
46 int gState = 0;
|
robert@464
|
47 int gStateCounter = 0;
|
robert@464
|
48 const int kMaxState = 25;
|
robert@464
|
49
|
robert@464
|
50 // . g f e d c b a
|
robert@464
|
51 //const unsigned char kBELA[4] = {0x7C, 0x79, 0x38, 0x77};
|
robert@464
|
52 const unsigned char kBELA[4] = {0x7C, 0x7B, 0x38, 0x5F};
|
robert@464
|
53 const unsigned char kPerimeter[6] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20};
|
robert@464
|
54
|
robert@464
|
55 int gCharacterToDisplay[4] = {0, 0, 0, 0};
|
robert@464
|
56
|
robert@464
|
57 // setup() is called once before the audio rendering starts.
|
robert@464
|
58 // Use it to perform any initialisation and allocation which is dependent
|
robert@464
|
59 // on the period size or sample rate.
|
robert@464
|
60 //
|
robert@464
|
61 // userData holds an opaque pointer to a data structure that was passed
|
robert@464
|
62 // in from the call to initAudio().
|
robert@464
|
63 //
|
robert@464
|
64 // Return true on success; returning false halts the program.
|
robert@464
|
65
|
robert@464
|
66 bool setup(BelaContext *context, void *userData)
|
robert@464
|
67 {
|
robert@464
|
68 // This project makes the assumption that the audio and digital
|
robert@464
|
69 // sample rates are the same. But check it to be sure!
|
robert@464
|
70 if(context->audioFrames != context->digitalFrames) {
|
robert@464
|
71 rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
|
robert@464
|
72 return false;
|
robert@464
|
73 }
|
robert@464
|
74
|
robert@464
|
75 for(int i = 0; i < NUM_PINS; i++) {
|
robert@464
|
76 pinMode(context, 0, kPins[i], OUTPUT);
|
robert@464
|
77 }
|
robert@464
|
78
|
robert@464
|
79 return true;
|
robert@464
|
80 }
|
robert@464
|
81
|
robert@464
|
82 // render() is called regularly at the highest priority by the audio engine.
|
robert@464
|
83 // Input and output are given from the audio hardware and the other
|
robert@464
|
84 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
|
robert@464
|
85 // will be 0.
|
robert@464
|
86
|
robert@464
|
87 void render(BelaContext *context, void *userData)
|
robert@464
|
88 {
|
robert@464
|
89 for(unsigned int n = 0; n < context->audioFrames; n++) {
|
robert@464
|
90 // Check for rotation between digits
|
robert@464
|
91 if(--gDigitDisplayTime <= 0) {
|
robert@464
|
92 gCurrentlyDisplayingDigit = (gCurrentlyDisplayingDigit + 1) % 4;
|
robert@464
|
93 gDigitDisplayTime = kDigitMaxDisplayTime;
|
robert@464
|
94 }
|
robert@464
|
95
|
robert@464
|
96 // Write the currently displaying digit low and the rest high
|
robert@464
|
97 for(int i = 0; i < 4; i++)
|
robert@464
|
98 digitalWriteOnce(context, n, kPins[kDigits[i]], HIGH);
|
robert@464
|
99 digitalWriteOnce(context, n, kPins[kDigits[gCurrentlyDisplayingDigit]], LOW);
|
robert@464
|
100
|
robert@464
|
101 // Write the digit to the other outputs
|
robert@464
|
102 digitalWriteOnce(context, n, kPins[11],
|
robert@464
|
103 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x01); // a
|
robert@464
|
104 digitalWriteOnce(context, n, kPins[6],
|
robert@464
|
105 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x02); // b
|
robert@464
|
106 digitalWriteOnce(context, n, kPins[4],
|
robert@464
|
107 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x04); // c
|
robert@464
|
108 digitalWriteOnce(context, n, kPins[1],
|
robert@464
|
109 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x08); // d
|
robert@464
|
110 digitalWriteOnce(context, n, kPins[0],
|
robert@464
|
111 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x10); // e
|
robert@464
|
112 digitalWriteOnce(context, n, kPins[10],
|
robert@464
|
113 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x20); // f
|
robert@464
|
114 digitalWriteOnce(context, n, kPins[5],
|
robert@464
|
115 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x40); // g
|
robert@464
|
116 digitalWriteOnce(context, n, kPins[2],
|
robert@464
|
117 gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x80); // .
|
robert@464
|
118
|
robert@464
|
119 // Check for changing state
|
robert@464
|
120 if(--gStateCounter <= 0) {
|
robert@464
|
121 gState = (gState + 1) % kMaxState;
|
robert@464
|
122 if(gState != (kMaxState - 1)) {
|
robert@464
|
123 for(int i = 0; i < 4; i++)
|
robert@464
|
124 gCharacterToDisplay[i] = 1 << (gState % 6);
|
robert@464
|
125 gStateCounter = 2000;
|
robert@464
|
126 }
|
robert@464
|
127 else {
|
robert@464
|
128 for(int i = 0; i < 4; i++)
|
robert@464
|
129 gCharacterToDisplay[i] = kBELA[i];
|
robert@464
|
130 gStateCounter = 50000;
|
robert@464
|
131 }
|
robert@464
|
132 }
|
robert@464
|
133 }
|
robert@464
|
134 }
|
robert@464
|
135
|
robert@464
|
136 // cleanup() is called once at the end, after the audio has stopped.
|
robert@464
|
137 // Release any resources that were allocated in setup().
|
robert@464
|
138
|
robert@464
|
139 void cleanup(BelaContext *context, void *userData)
|
robert@464
|
140 {
|
robert@464
|
141
|
robert@464
|
142 }
|