summaryrefslogtreecommitdiff
path: root/arduino
diff options
context:
space:
mode:
authorerdgeist <erdgeist@bauklotz.fritz.box>2016-08-12 14:47:28 +0200
committererdgeist <erdgeist@bauklotz.fritz.box>2016-08-12 14:47:28 +0200
commit830ec9041b5b70782f5a3781d27af9b149c028b1 (patch)
treeebdd5e8719d03c8b94d6bff1072a27298dea5c84 /arduino
parenta8be0d3d20f07d4561826b01f566ca307eb23526 (diff)
arduino
Diffstat (limited to 'arduino')
-rw-r--r--arduino/Laserharfe/Laserharfe.ino282
1 files changed, 282 insertions, 0 deletions
diff --git a/arduino/Laserharfe/Laserharfe.ino b/arduino/Laserharfe/Laserharfe.ino
new file mode 100644
index 0000000..8ad5f56
--- /dev/null
+++ b/arduino/Laserharfe/Laserharfe.ino
@@ -0,0 +1,282 @@
1/*
2 * MIDIUSB_test.ino
3 *
4 * Created: 4/6/2015 10:47:08 AM
5 * Author: gurbrinder grewal
6 * Modified by Arduino LLC (2015)
7 */
8
9#include "MIDIUSB.h"
10#include <Wire.h>
11
12#include "engine.h"
13#include "config.h"
14
15int led = 13;
16
17enum {
18 MODE_STANDALONE = 0,
19 MODE_REPORTPOINTS = 1,
20 MODE_REPORTPOINTS_PLAY = 2,
21} g_mode = MODE_REPORTPOINTS_PLAY;
22
23/*
24// First parameter is the event type (0x09 = note on, 0x08 = note off).
25// Second parameter is note-on/note-off, combined with the channel.
26// Channel can be anything between 0-15. Typically reported to the user as 1-16.
27// Third parameter is the note number (48 = middle C).
28// Fourth parameter is the velocity (64 = normal, 127 = fastest).
29void noteOn(byte channel, byte pitch, byte velocity) {
30 midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
31 MidiUSB.sendMIDI(noteOn);
32}
33
34void noteOff(byte channel, byte pitch, byte velocity) {
35 midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
36 MidiUSB.sendMIDI(noteOff);
37}
38*/
39
40void setup_pwm() {
41 // Set up the generic clock (GCLK4) used to clock timers
42 REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 2: 48MHz/2=24MHz
43 GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
44 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
45
46 REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
47 GCLK_GENCTRL_GENEN | // Enable GCLK4
48 GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
49 GCLK_GENCTRL_ID(4); // Select GCLK4
50 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
51
52 // Feed GCLK4 to TC4 and TC5
53 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5
54 GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
55 GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5
56 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
57
58 REG_TC4_CTRLA |= TC_CTRLA_MODE_COUNT8; // Set the counter to 8-bit mode
59 while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
60
61 REG_TC4_COUNT8_CC0 = 0; // Set the TC4 CC0 register to some arbitary value
62 while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
63 REG_TC4_COUNT8_CC1 = 0; // Set the TC4 CC1 register to some arbitary value
64 while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
65 REG_TC4_COUNT8_PER = 1; // Set the PER (period) register to flip each time
66 while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
67
68 NVIC_DisableIRQ(TC4_IRQn);
69 NVIC_ClearPendingIRQ(TC4_IRQn);
70 // NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
71 // NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC)
72
73 REG_TC4_INTFLAG |= TC_INTFLAG_MC1 | TC_INTFLAG_MC0 | TC_INTFLAG_OVF; // Clear the interrupt flags
74 //REG_TC4_INTENSET = TC_INTENSET_MC1 | TC_INTENSET_MC0 | TC_INTENSET_OVF; // Enable TC4 interrupts
75 REG_TC4_INTENCLR = TC_INTENCLR_MC1 | TC_INTENCLR_MC0 | TC_INTENCLR_OVF; // Disable TC4 interrupts
76
77 int outpin = 15;
78
79 // Enable the port multiplexer for the digital pin D0
80 PORT->Group[g_APinDescription[outpin].ulPort].PINCFG[g_APinDescription[outpin].ulPin].bit.PMUXEN = 1;
81
82 // Connect the TC4 timer to the port output D0 - port pins are paired odd PMUXO and even PMUXE
83 // Peripheral E specifies the TC timers, on this pin: TC4
84 PORT->Group[g_APinDescription[outpin].ulPort].PMUX[g_APinDescription[outpin].ulPin >> 1].reg |= /*PORT_PMUX_PMUXO_E |*/ PORT_PMUX_PMUXE_E;
85
86 REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1 | // Set prescaler to 1, 24MHz/1 = 24MHz
87 TC_CTRLA_ENABLE; // Enable TC4
88 while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization
89}
90
91static void set_cam_register(uint8_t r, uint8_t v) {
92 Wire.beginTransmission(0x58);
93 Wire.write(r);
94 Wire.write(v);
95 Wire.endTransmission();
96}
97
98static void setup_cam() {
99 set_cam_register(0x30, 0x01);
100 set_cam_register(0x06, 0x90);
101 set_cam_register(0x08, 0xc0);
102 set_cam_register(0x1a, 0x40);
103 set_cam_register(0x33, 0x01);
104 set_cam_register(0x30, 0x08);
105}
106
107void setup() {
108 pinMode(led, OUTPUT);
109
110 Wire.begin();
111 digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
112 setup_pwm();
113
114 // Let PWM settle for a bit
115 delay(100);
116 setup_cam();
117
118 Serial.begin(115200);
119 digitalWrite(led, LOW); // turn the LED on (HIGH is the voltage level)
120}
121
122void handle_wire() {
123 uint8_t ic2_result[32];
124 char text[64];
125
126 Wire.beginTransmission(0x58);
127 Wire.write(0x36);
128 Wire.endTransmission();
129 Wire.requestFrom(0x58, 11);
130
131 for (int i=0; Wire.available() && i<=11; ++i)
132 ic2_result[i] = Wire.read();
133
134 LPoint p1, p2, p3, p4;
135
136 int Ix1,Iy1,Ix2,Iy2;
137 int Ix3,Iy3,Ix4,Iy4;
138 int s;
139
140 s = ic2_result[3];
141 p1.x = ((int)ic2_result[1]) | ( ( s << 4) & 0x300);
142 p1.y = ((int)ic2_result[2]) | ( ( s << 2) & 0x300);
143 p2.x = ((int)ic2_result[4]) | ( ( s << 8) & 0x300);
144 p2.y = ((int)ic2_result[5]) | ( ( s << 6) & 0x300);
145
146 s = ic2_result[8];
147 p3.x = ((int)ic2_result[6]) | ( ( s << 4) & 0x300);
148 p3.y = ((int)ic2_result[7]) | ( ( s << 2) & 0x300);
149 p4.x = ((int)ic2_result[9]) | ( ( s << 8) & 0x300);
150 p4.y = ((int)ic2_result[10])| ( ( s << 6) & 0x300);
151
152 if (p1.x==1023 && p2.x==1023 && p3.x==1023 && p4.x==1023)
153 return;
154
155 long now = millis();
156 if (g_mode==MODE_STANDALONE || g_mode==MODE_REPORTPOINTS_PLAY) {
157 if (p1.x!=1023)
158 engine_handle_point(&p1, now);
159 if (p2.x!=1023)
160 engine_handle_point(&p2, now);
161 if (p3.x!=1023)
162 engine_handle_point(&p3, now);
163 if (p4.x!=1023)
164 engine_handle_point(&p4, now);
165 }
166
167 if (g_mode==MODE_STANDALONE)
168 return;
169 if (p1.x!=1023)
170 Serial.write(text, sprintf(text, "%04d:%04d ", p1.x, p1.y));
171 if (p2.x!=1023)
172 Serial.write(text, sprintf(text, "%04d:%04d ", p2.x, p2.y));
173 if (p3.x!=1023)
174 Serial.write(text, sprintf(text, "%04d:%04d ", p3.x, p3.y));
175 if (p4.x!=1023)
176 Serial.write(text, sprintf(text, "%04d:%04d ", p4.x, p4.y));
177 Serial.println("");
178}
179
180/* Do a fast nibble to hex representation conversion */
181static unsigned char fromhex(unsigned char x) {
182 x-='0'; if( x<=9) return x;
183 x&=~0x20; x-='A'-'0';
184 if( x<6 ) return x+10;
185 return 0xff;
186}
187
188void handle_midi(char *command) {
189// midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
190 uint8_t m[6];
191 /* expect 6 hex encoded MIDI bytes and a newline */
192 for (int i=0; i<6; ++i)
193 if ((m[i] = fromhex(command[i])) == 0xff)
194 return;
195 if (command[6] != '\n')
196 return;
197
198 midiEventPacket_t p = { m[0], (m[0]<<4) | m[1], (m[2]<<4) | m[3], (m[4]<<4) | m[5] };
199 MidiUSB.sendMIDI(p);
200 // MidiUSB.flush();
201}
202
203void handle_configure(char *command) {
204
205}
206
207void handle_command(char *command) {
208 switch (*command) {
209 case 'M': /* Getting MIDI instruction */
210 handle_midi(command+1);
211 break;
212 case 'S': /* Getting set mode instruction */
213 switch (command[1]) {
214 case '1':
215 g_mode = MODE_STANDALONE;
216 break;
217 case '2':
218 g_mode = MODE_REPORTPOINTS_PLAY;
219 break;
220 case '3':
221 g_mode = MODE_REPORTPOINTS;
222 break;
223 default:
224 break;
225 }
226 break;
227 case 'C': /* Getting configure command */
228 handle_configure(command+1);
229 break;
230 default:
231 break;
232 }
233}
234
235void handle_serial() {
236 static char command[128];
237 static int command_len;
238 static int skip_command;
239
240 while (Serial.available()) {
241 char c = command[command_len++] = Serial.read();
242 if (c=='\n') {
243 if (!skip_command) {
244 command[command_len] = 0;
245 handle_command(command);
246 }
247 skip_command = 0;
248 command_len = 0;
249 // Read at max one command to allow polling the cam
250 return;
251 }
252 if (command_len==sizeof(command)) {
253 // If we end up at end of buffer, ignore everying to next \n
254 skip_command = 1;
255 command_len = 0;
256 }
257 }
258}
259
260void loop() {
261 static int led_state;
262
263 handle_wire();
264 handle_serial();
265
266/*
267 Serial.write((const uint8_t*)"Sending note on\r\n", 17);
268 noteOn(0, note, 64); // Channel 0, middle C, normal velocity
269 MidiUSB.flush();
270 delay(500);
271 digitalWrite(led, LOW); // turn the LED on (HIGH is the voltage level)
272
273 Serial.write((const uint8_t*)"Sending note off\r\n", 18);
274 noteOff(0, note, 64); // Channel 0, middle C, normal velocity
275 MidiUSB.flush();
276 delay(1500);
277*/
278
279 engine_checksilence(millis());
280 digitalWrite(led, ++led_state & 1 ? HIGH : LOW); // turn the LED on (HIGH is the voltage level)
281}
282