robert@464: /* robert@464: ____ _____ _ _ robert@464: | __ )| ____| | / \ robert@464: | _ \| _| | | / _ \ robert@464: | |_) | |___| |___ / ___ \ robert@464: |____/|_____|_____/_/ \_\ robert@464: robert@464: The platform for ultra-low latency audio and sensor processing robert@464: robert@464: http://bela.io robert@464: robert@464: A project of the Augmented Instruments Laboratory within the robert@464: Centre for Digital Music at Queen Mary University of London. robert@464: http://www.eecs.qmul.ac.uk/~andrewm robert@464: robert@464: (c) 2016 Augmented Instruments Laboratory: Andrew McPherson, robert@464: Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack, robert@464: Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved. robert@464: robert@464: The Bela software is distributed under the GNU Lesser General Public License robert@464: (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt robert@464: */ robert@464: robert@464: robert@464: #include robert@464: #include robert@464: #include robert@464: #include "I2C_MPR121.h" robert@464: robert@464: // How many pins there are robert@464: #define NUM_TOUCH_PINS 12 robert@464: robert@464: // Define this to print data to terminal robert@464: #undef DEBUG_MPR121 robert@464: robert@464: // Change this to change how often the MPR121 is read (in Hz) robert@464: int readInterval = 50; robert@464: robert@464: // Change this threshold to set the minimum amount of touch robert@464: int threshold = 40; robert@464: robert@464: // This array holds the continuous sensor values robert@464: int sensorValue[NUM_TOUCH_PINS]; robert@464: robert@464: // ---- test code stuff -- can be deleted for your example ---- robert@464: robert@464: // 12 notes of a C major scale... robert@464: float gFrequencies[NUM_TOUCH_PINS] = {261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25, 698.25, 783.99}; robert@464: robert@464: // This is internal stuff for the demo robert@464: float gNormFrequencies[NUM_TOUCH_PINS]; robert@464: float gPhases[NUM_TOUCH_PINS] = {0}; robert@464: robert@464: // ---- internal stuff -- do not change ----- robert@464: robert@464: I2C_MPR121 mpr121; // Object to handle MPR121 sensing robert@464: AuxiliaryTask i2cTask; // Auxiliary task to read I2C robert@464: robert@464: int readCount = 0; // How long until we read again... robert@464: int readIntervalSamples = 0; // How many samples between reads robert@464: robert@464: void readMPR121(); robert@464: robert@464: // setup() is called once before the audio rendering starts. robert@464: // Use it to perform any initialisation and allocation which is dependent robert@464: // on the period size or sample rate. robert@464: // robert@464: // userData holds an opaque pointer to a data structure that was passed robert@464: // in from the call to initAudio(). robert@464: // robert@464: // Return true on success; returning false halts the program. robert@464: robert@464: bool setup(BelaContext *context, void *userData) robert@464: { robert@464: if(!mpr121.begin(1, 0x5A)) { robert@464: rt_printf("Error initialising MPR121\n"); robert@464: return false; robert@464: } robert@464: robert@464: i2cTask = Bela_createAuxiliaryTask(readMPR121, 50, "bela-mpr121"); robert@464: readIntervalSamples = context->audioSampleRate / readInterval; robert@464: robert@464: for(int i = 0; i < NUM_TOUCH_PINS; i++) { robert@464: gNormFrequencies[i] = 2.0 * M_PI * gFrequencies[i] / context->audioSampleRate; robert@464: } robert@464: robert@464: return true; robert@464: } robert@464: robert@464: // render() is called regularly at the highest priority by the audio engine. robert@464: // Input and output are given from the audio hardware and the other robert@464: // ADCs and DACs (if available). If only audio is available, numAnalogFrames robert@464: // will be 0. robert@464: robert@464: void render(BelaContext *context, void *userData) robert@464: { robert@464: for(int n = 0; n < context->audioFrames; n++) { robert@464: // Keep this code: it schedules the touch sensor readings robert@464: if(++readCount >= readIntervalSamples) { robert@464: readCount = 0; robert@464: Bela_scheduleAuxiliaryTask(i2cTask); robert@464: } robert@464: robert@464: float sample = 0.0; robert@464: robert@464: // This code can be replaced with your favourite audio code robert@464: for(int i = 0; i < NUM_TOUCH_PINS; i++) { robert@464: float amplitude = sensorValue[i] / 400.0; robert@464: robert@464: // Prevent clipping robert@464: if(amplitude > 0.5) robert@464: amplitude = 0.5; robert@464: robert@464: sample += amplitude * sinf(gPhases[i]); robert@464: gPhases[i] += gNormFrequencies[i]; robert@464: if(gPhases[i] > 2.0 * M_PI) robert@464: gPhases[i] -= 2.0 * M_PI; robert@464: } robert@464: robert@464: for(int ch = 0; ch < context->audioChannels; ch++) robert@464: context->audioOut[context->audioChannels * n + ch] = sample; robert@464: } robert@464: } robert@464: robert@464: // cleanup() is called once at the end, after the audio has stopped. robert@464: // Release any resources that were allocated in setup(). robert@464: robert@464: void cleanup(BelaContext *context, void *userData) robert@464: { robert@464: // Nothing to do here robert@464: } robert@464: robert@464: robert@464: // Auxiliary task to read the I2C board robert@464: void readMPR121() robert@464: { robert@464: for(int i = 0; i < NUM_TOUCH_PINS; i++) { robert@464: sensorValue[i] = -(mpr121.filteredData(i) - mpr121.baselineData(i)); robert@464: sensorValue[i] -= threshold; robert@464: if(sensorValue[i] < 0) robert@464: sensorValue[i] = 0; robert@464: #ifdef DEBUG_MPR121 robert@464: rt_printf("%d ", sensorValue[i]); robert@464: #endif robert@464: } robert@464: #ifdef DEBUG_MPR121 robert@464: rt_printf("\n"); robert@464: #endif robert@464: robert@464: // You can use this to read binary on/off touch state more easily robert@464: //rt_printf("Touched: %x\n", mpr121.touched()); robert@464: } robert@464: robert@464: /* ------------ Project Explantation ------------ */ robert@464: robert@464: /** robert@464: \example 06-capacitive-touch robert@464: robert@464: Capacitive touch sensing with MPR121 robert@464: --------------------------- robert@464: robert@464: This sketch allows you to hook up an MPR121 capactive touch sensing device robert@464: to Bela, for example the SparkFun Capacitive Touch Sensor Breakout - MPR121. robert@464: The breakout board gives you 12 electrode connections. robert@464: robert@464: To get this working with Bela you need to connect the breakout board to the I2C robert@464: terminal on the Bela board. See the Pin guide for details of which pin is which. robert@464: robert@464: The sensor data will then be available for you to use in the array robert@464: `sensorValue[NUM_TOUCH_PINS]`. robert@464: */