Created
October 26, 2023 00:36
-
-
Save greed9/982dd291a13458fd37d35724a332ea00 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Turntable/sequencer to MIDI | |
// Tracks numbered zero-relative from the hub outwards | |
#define TRACK_3_PIN 51 | |
#define TRACK_2_PIN 52 | |
#define TRACK_1_PIN 49 | |
#define TRACK_0_PIN 50 | |
#define FLASH_PIN 4 // Flash LED strips when mark detected | |
#define INTERRUPT_PIN 48 | |
#define pitchD3 50 // any old pitch for now, irrelevant for drum | |
#define pitchG2 43 | |
#define pitchE2 40 | |
#define pitchC1 24 | |
#define CHANNEL 1 // channels will be 1-4 | |
volatile uint32_t edge_detected = 0; | |
// info on Pins, Tracks and Notes | |
typedef struct track_type { | |
uint16_t pin ; | |
uint16_t status ; | |
uint16_t note ; | |
} TRACK ; | |
// maps optical tracks to hw pins | |
// Status of each track, mark not mark | |
static TRACK sensors[4] = { | |
{ TRACK_0_PIN, 0, pitchD3 }, | |
{ TRACK_1_PIN, 0, pitchG2 }, | |
{ TRACK_2_PIN, 0, pitchE2 }, | |
{ TRACK_3_PIN, 0, pitchC1 } | |
} ; | |
// Logical structure of a MIDI message | |
typedef struct | |
{ | |
uint8_t header; | |
uint8_t byte1; | |
uint8_t byte2; | |
uint8_t byte3; | |
} midiEventPacket_t; | |
// saw white to black | |
void optical_isr() { | |
edge_detected = 1; | |
} | |
// Send MIDI notes | |
void noteOn(byte channel, byte pitch, byte velocity) { | |
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity}; | |
sendMIDISerial(noteOn); | |
} | |
void noteOff(byte channel, byte pitch, byte velocity) { | |
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity}; | |
sendMIDISerial(noteOff); | |
} | |
void debugPrintMIDI( midiEventPacket_t event) | |
{ | |
Serial.print (event.header); | |
Serial.print ( "," ) ; | |
Serial.print ( event.byte1 ) ; | |
Serial.print( ",") ; | |
Serial.print ( event.byte2 ) ; | |
Serial.print( ",") ; | |
Serial.print ( event.byte3 ) ; | |
Serial.println(";") ; | |
} | |
// low-level serial send | |
void sendMIDISerial(midiEventPacket_t event) | |
{ | |
uint8_t data[4]; | |
data[0] = event.header; | |
data[1] = event.byte1; | |
data[2] = event.byte2; | |
data[3] = event.byte3; | |
debugPrintMIDI( event ) ; | |
//Serial.write(data, 4); | |
} | |
// send note on and immediate note off for selected sensor(s) | |
void playNotes( TRACK sensor_array[4]) | |
{ | |
// send MIDI to serial for the tripped optical sensor | |
for( int i = 0 ; i < 4 ; i++) | |
{ | |
if( sensor_array[i].status) { | |
noteOn(CHANNEL + i, sensor_array[i].note, 127) ; | |
// do I need/dare a delay here? | |
noteOff(CHANNEL + i, sensor_array[i].note, 127) ; | |
} | |
} | |
} | |
// One-time init | |
void setup() { | |
// MIDI runs at 31.25kbps | |
Serial.begin(31250); | |
// map track numbers to pin numbers | |
for( int i = 0 ; i < 4 ; i++ ) { | |
pinMode( sensors[i].pin, INPUT_PULLUP) ; | |
} | |
// Timing track | |
pinMode(INTERRUPT_PIN, INPUT_PULLUP); | |
// Control LED strip | |
pinMode( FLASH_PIN, OUTPUT) ; | |
//attachInterrupt(digitalPinToInterrupt(4), left, CHANGE); | |
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), optical_isr, FALLING); | |
} | |
// Event loop | |
void loop() { | |
uint16_t mark_detected = 0 ; | |
uint16_t current_pin_status = 0 ; | |
if (edge_detected) { | |
edge_detected = 0; | |
for( int i = 0 ; i < 4 ; i++ ) { | |
current_pin_status = !digitalRead( sensors[i].pin) ; | |
sensors[i].status = current_pin_status ; | |
mark_detected |= current_pin_status ; | |
} | |
// flash if any marks detected | |
if (mark_detected) { | |
digitalWrite( FLASH_PIN, 1 ) ; | |
playNotes(sensors) ; | |
} | |
else | |
{ | |
digitalWrite( FLASH_PIN, 0) ; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment