From 830ec9041b5b70782f5a3781d27af9b149c028b1 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Fri, 12 Aug 2016 14:47:28 +0200 Subject: arduino --- arduino/Laserharfe/Laserharfe.ino | 282 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 arduino/Laserharfe/Laserharfe.ino (limited to 'arduino') 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 @@ +/* + * MIDIUSB_test.ino + * + * Created: 4/6/2015 10:47:08 AM + * Author: gurbrinder grewal + * Modified by Arduino LLC (2015) + */ + +#include "MIDIUSB.h" +#include + +#include "engine.h" +#include "config.h" + +int led = 13; + +enum { + MODE_STANDALONE = 0, + MODE_REPORTPOINTS = 1, + MODE_REPORTPOINTS_PLAY = 2, +} g_mode = MODE_REPORTPOINTS_PLAY; + +/* +// First parameter is the event type (0x09 = note on, 0x08 = note off). +// Second parameter is note-on/note-off, combined with the channel. +// Channel can be anything between 0-15. Typically reported to the user as 1-16. +// Third parameter is the note number (48 = middle C). +// Fourth parameter is the velocity (64 = normal, 127 = fastest). +void noteOn(byte channel, byte pitch, byte velocity) { + midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity}; + MidiUSB.sendMIDI(noteOn); +} + +void noteOff(byte channel, byte pitch, byte velocity) { + midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity}; + MidiUSB.sendMIDI(noteOff); +} +*/ + +void setup_pwm() { + // Set up the generic clock (GCLK4) used to clock timers + REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 2: 48MHz/2=24MHz + GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW + GCLK_GENCTRL_GENEN | // Enable GCLK4 + GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source + GCLK_GENCTRL_ID(4); // Select GCLK4 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + // Feed GCLK4 to TC4 and TC5 + REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + REG_TC4_CTRLA |= TC_CTRLA_MODE_COUNT8; // Set the counter to 8-bit mode + while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization + + REG_TC4_COUNT8_CC0 = 0; // Set the TC4 CC0 register to some arbitary value + while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization + REG_TC4_COUNT8_CC1 = 0; // Set the TC4 CC1 register to some arbitary value + while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization + REG_TC4_COUNT8_PER = 1; // Set the PER (period) register to flip each time + while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_DisableIRQ(TC4_IRQn); + NVIC_ClearPendingIRQ(TC4_IRQn); + // NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + // NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + REG_TC4_INTFLAG |= TC_INTFLAG_MC1 | TC_INTFLAG_MC0 | TC_INTFLAG_OVF; // Clear the interrupt flags + //REG_TC4_INTENSET = TC_INTENSET_MC1 | TC_INTENSET_MC0 | TC_INTENSET_OVF; // Enable TC4 interrupts + REG_TC4_INTENCLR = TC_INTENCLR_MC1 | TC_INTENCLR_MC0 | TC_INTENCLR_OVF; // Disable TC4 interrupts + + int outpin = 15; + + // Enable the port multiplexer for the digital pin D0 + PORT->Group[g_APinDescription[outpin].ulPort].PINCFG[g_APinDescription[outpin].ulPin].bit.PMUXEN = 1; + + // Connect the TC4 timer to the port output D0 - port pins are paired odd PMUXO and even PMUXE + // Peripheral E specifies the TC timers, on this pin: TC4 + PORT->Group[g_APinDescription[outpin].ulPort].PMUX[g_APinDescription[outpin].ulPin >> 1].reg |= /*PORT_PMUX_PMUXO_E |*/ PORT_PMUX_PMUXE_E; + + REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1 | // Set prescaler to 1, 24MHz/1 = 24MHz + TC_CTRLA_ENABLE; // Enable TC4 + while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization +} + +static void set_cam_register(uint8_t r, uint8_t v) { + Wire.beginTransmission(0x58); + Wire.write(r); + Wire.write(v); + Wire.endTransmission(); +} + +static void setup_cam() { + set_cam_register(0x30, 0x01); + set_cam_register(0x06, 0x90); + set_cam_register(0x08, 0xc0); + set_cam_register(0x1a, 0x40); + set_cam_register(0x33, 0x01); + set_cam_register(0x30, 0x08); +} + +void setup() { + pinMode(led, OUTPUT); + + Wire.begin(); + digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) + setup_pwm(); + + // Let PWM settle for a bit + delay(100); + setup_cam(); + + Serial.begin(115200); + digitalWrite(led, LOW); // turn the LED on (HIGH is the voltage level) +} + +void handle_wire() { + uint8_t ic2_result[32]; + char text[64]; + + Wire.beginTransmission(0x58); + Wire.write(0x36); + Wire.endTransmission(); + Wire.requestFrom(0x58, 11); + + for (int i=0; Wire.available() && i<=11; ++i) + ic2_result[i] = Wire.read(); + + LPoint p1, p2, p3, p4; + + int Ix1,Iy1,Ix2,Iy2; + int Ix3,Iy3,Ix4,Iy4; + int s; + + s = ic2_result[3]; + p1.x = ((int)ic2_result[1]) | ( ( s << 4) & 0x300); + p1.y = ((int)ic2_result[2]) | ( ( s << 2) & 0x300); + p2.x = ((int)ic2_result[4]) | ( ( s << 8) & 0x300); + p2.y = ((int)ic2_result[5]) | ( ( s << 6) & 0x300); + + s = ic2_result[8]; + p3.x = ((int)ic2_result[6]) | ( ( s << 4) & 0x300); + p3.y = ((int)ic2_result[7]) | ( ( s << 2) & 0x300); + p4.x = ((int)ic2_result[9]) | ( ( s << 8) & 0x300); + p4.y = ((int)ic2_result[10])| ( ( s << 6) & 0x300); + + if (p1.x==1023 && p2.x==1023 && p3.x==1023 && p4.x==1023) + return; + + long now = millis(); + if (g_mode==MODE_STANDALONE || g_mode==MODE_REPORTPOINTS_PLAY) { + if (p1.x!=1023) + engine_handle_point(&p1, now); + if (p2.x!=1023) + engine_handle_point(&p2, now); + if (p3.x!=1023) + engine_handle_point(&p3, now); + if (p4.x!=1023) + engine_handle_point(&p4, now); + } + + if (g_mode==MODE_STANDALONE) + return; + if (p1.x!=1023) + Serial.write(text, sprintf(text, "%04d:%04d ", p1.x, p1.y)); + if (p2.x!=1023) + Serial.write(text, sprintf(text, "%04d:%04d ", p2.x, p2.y)); + if (p3.x!=1023) + Serial.write(text, sprintf(text, "%04d:%04d ", p3.x, p3.y)); + if (p4.x!=1023) + Serial.write(text, sprintf(text, "%04d:%04d ", p4.x, p4.y)); + Serial.println(""); +} + +/* Do a fast nibble to hex representation conversion */ +static unsigned char fromhex(unsigned char x) { + x-='0'; if( x<=9) return x; + x&=~0x20; x-='A'-'0'; + if( x<6 ) return x+10; + return 0xff; +} + +void handle_midi(char *command) { +// midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity}; + uint8_t m[6]; + /* expect 6 hex encoded MIDI bytes and a newline */ + for (int i=0; i<6; ++i) + if ((m[i] = fromhex(command[i])) == 0xff) + return; + if (command[6] != '\n') + return; + + midiEventPacket_t p = { m[0], (m[0]<<4) | m[1], (m[2]<<4) | m[3], (m[4]<<4) | m[5] }; + MidiUSB.sendMIDI(p); + // MidiUSB.flush(); +} + +void handle_configure(char *command) { + +} + +void handle_command(char *command) { + switch (*command) { + case 'M': /* Getting MIDI instruction */ + handle_midi(command+1); + break; + case 'S': /* Getting set mode instruction */ + switch (command[1]) { + case '1': + g_mode = MODE_STANDALONE; + break; + case '2': + g_mode = MODE_REPORTPOINTS_PLAY; + break; + case '3': + g_mode = MODE_REPORTPOINTS; + break; + default: + break; + } + break; + case 'C': /* Getting configure command */ + handle_configure(command+1); + break; + default: + break; + } +} + +void handle_serial() { + static char command[128]; + static int command_len; + static int skip_command; + + while (Serial.available()) { + char c = command[command_len++] = Serial.read(); + if (c=='\n') { + if (!skip_command) { + command[command_len] = 0; + handle_command(command); + } + skip_command = 0; + command_len = 0; + // Read at max one command to allow polling the cam + return; + } + if (command_len==sizeof(command)) { + // If we end up at end of buffer, ignore everying to next \n + skip_command = 1; + command_len = 0; + } + } +} + +void loop() { + static int led_state; + + handle_wire(); + handle_serial(); + +/* + Serial.write((const uint8_t*)"Sending note on\r\n", 17); + noteOn(0, note, 64); // Channel 0, middle C, normal velocity + MidiUSB.flush(); + delay(500); + digitalWrite(led, LOW); // turn the LED on (HIGH is the voltage level) + + Serial.write((const uint8_t*)"Sending note off\r\n", 18); + noteOff(0, note, 64); // Channel 0, middle C, normal velocity + MidiUSB.flush(); + delay(1500); +*/ + + engine_checksilence(millis()); + digitalWrite(led, ++led_state & 1 ? HIGH : LOW); // turn the LED on (HIGH is the voltage level) +} + -- cgit v1.2.3