Last active
July 2, 2020 15:48
-
-
Save ceiborg/068e22726015e06d1f29831ded3a25aa to your computer and use it in GitHub Desktop.
MIDI+CapSense
This file contains 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
/* | |
#############%@ | |
#### #########% | |
## #########& | |
#% ########## | |
### ############ | |
################### ceiborg.com | |
################### tecnotextiles | |
################## | |
################# | |
############## | |
## | |
# | |
*/ | |
#include "FastLED.h" | |
#define NUM_LEDS 10 | |
CRGB leds[NUM_LEDS]; | |
#define PIXELLED 4 | |
int button =3; | |
float minS = 1.0f; | |
float maxS = 1.0f; | |
float s = 0.0f; | |
int currS; | |
#define resolution 8 | |
#define mains 50 // 60: north america, japan; 50: most other places | |
#define refresh 2 * 1000000 / mains | |
void setup() { | |
Serial.begin(9600); | |
FastLED.addLeds<NEOPIXEL, PIXELLED>(leds, NUM_LEDS); | |
// unused pins are fairly insignificant, | |
// but pulled low to reduce unknown variables | |
for(int i = 2; i < 14; i++) { | |
pinMode(i, OUTPUT); | |
digitalWrite(i, LOW); | |
} | |
for(int i = 8; i < 11; i++) | |
pinMode(i, INPUT); | |
pinMode (button, INPUT_PULLUP); | |
startTimer(); | |
} | |
void filterSensors(float rate, float minRate, float maxRate){ | |
s += (currS-s) * rate; | |
if ( (s <minS) && (s > 1.0f) ) | |
minS= s; | |
if (s> maxS) | |
maxS = s; | |
minS += (s-minS)/(minRate*minS); | |
maxS -= (maxS-s)/(maxRate*maxS); | |
} | |
int stateButton = 0; | |
void loop() { | |
int b = digitalRead(button); | |
// LOW means pressed | |
if ((b == LOW) && (stateButton==0) ){ | |
stateButton = 1; | |
sendNote(100); | |
} | |
// HIGH means released | |
if ((b == HIGH) && (stateButton==1) ){ | |
stateButton = 0; | |
sendNote(0); | |
} | |
currS = time(9, B00000010); | |
filterSensors(0.05f, 0.1f, 0.1f); | |
//printSensor(); | |
int hueMapped = sensorMap ( 0, 255); | |
for (int i=0;i<NUM_LEDS; i++){ | |
leds[i].setHue(hueMapped); | |
} | |
//todo: only send if changed | |
sendCc(hueMapped/2); | |
FastLED.show(); | |
delay (20); | |
} | |
void printSensor (){ | |
Serial.print(minS); | |
Serial.print(","); | |
Serial.print(maxS); | |
Serial.print(","); | |
Serial.print(currS); | |
Serial.print(","); | |
Serial.println (s); | |
} | |
int sensorMap ( int _from, int _to){ | |
return map (constrain (s, minS, maxS), minS, maxS, _from, _to); | |
} | |
void sendNote(byte velocity){ | |
sendMidi(0x90, 60, velocity); | |
} | |
void sendCc(byte value){ | |
sendMidi(0xB0, 1, value); | |
} | |
void sendMidi(byte cmd, byte data1, byte data2){ | |
Serial.write(cmd); | |
Serial.write(data1); | |
Serial.write(data2); | |
} | |
long time(int pin, byte mask) { | |
unsigned long count = 0, total = 0; | |
while(checkTimer() < refresh) { | |
// pinMode is about 6 times slower than assigning | |
// DDRB directly, but that pause is important | |
pinMode(pin, OUTPUT); | |
PORTB = 0; | |
pinMode(pin, INPUT); | |
while((PINB & mask) == 0) | |
count++; | |
total++; | |
} | |
startTimer(); | |
return (count << resolution) / total; | |
} | |
extern volatile unsigned long timer0_overflow_count; | |
void startTimer() { | |
timer0_overflow_count = 0; | |
TCNT0 = 0; | |
} | |
unsigned long checkTimer() { | |
return ((timer0_overflow_count << 8) + TCNT0) << 2; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment