giuliomoro@301: #include andrewm@268: #include andrewm@268: #include andrewm@268: #include andrewm@268: #include "I2C_MPR121.h" andrewm@268: andrewm@268: // How many pins there are andrewm@268: #define NUM_TOUCH_PINS 12 andrewm@268: andrewm@268: // Define this to print data to terminal andrewm@268: #undef DEBUG_MPR121 andrewm@268: andrewm@268: // Change this to change how often the MPR121 is read (in Hz) andrewm@268: int readInterval = 50; andrewm@268: andrewm@268: // Change this threshold to set the minimum amount of touch andrewm@268: int threshold = 40; andrewm@268: andrewm@268: // This array holds the continuous sensor values andrewm@268: int sensorValue[NUM_TOUCH_PINS]; andrewm@268: andrewm@268: // ---- test code stuff -- can be deleted for your example ---- andrewm@268: andrewm@268: // 12 notes of a C major scale... andrewm@268: 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}; andrewm@268: andrewm@268: // This is internal stuff for the demo andrewm@268: float gNormFrequencies[NUM_TOUCH_PINS]; andrewm@268: float gPhases[NUM_TOUCH_PINS] = {0}; andrewm@268: andrewm@268: // ---- internal stuff -- do not change ----- andrewm@268: andrewm@268: I2C_MPR121 mpr121; // Object to handle MPR121 sensing andrewm@268: AuxiliaryTask i2cTask; // Auxiliary task to read I2C andrewm@268: andrewm@268: int readCount = 0; // How long until we read again... andrewm@268: int readIntervalSamples = 0; // How many samples between reads andrewm@268: andrewm@268: void readMPR121(); andrewm@268: andrewm@268: // setup() is called once before the audio rendering starts. andrewm@268: // Use it to perform any initialisation and allocation which is dependent andrewm@268: // on the period size or sample rate. andrewm@268: // andrewm@268: // userData holds an opaque pointer to a data structure that was passed andrewm@268: // in from the call to initAudio(). andrewm@268: // andrewm@268: // Return true on success; returning false halts the program. andrewm@268: giuliomoro@301: bool setup(BelaContext *context, void *userData) andrewm@268: { andrewm@268: if(!mpr121.begin(1, 0x5A)) { andrewm@268: rt_printf("Error initialising MPR121\n"); andrewm@268: return false; andrewm@268: } andrewm@268: andrewm@303: i2cTask = Bela_createAuxiliaryTask(readMPR121, 50, "bela-mpr121"); andrewm@268: readIntervalSamples = context->audioSampleRate / readInterval; andrewm@268: andrewm@268: for(int i = 0; i < NUM_TOUCH_PINS; i++) { andrewm@268: gNormFrequencies[i] = 2.0 * M_PI * gFrequencies[i] / context->audioSampleRate; andrewm@268: } andrewm@268: andrewm@268: return true; andrewm@268: } andrewm@268: andrewm@268: // render() is called regularly at the highest priority by the audio engine. andrewm@268: // Input and output are given from the audio hardware and the other andrewm@268: // ADCs and DACs (if available). If only audio is available, numAnalogFrames andrewm@268: // will be 0. andrewm@268: giuliomoro@301: void render(BelaContext *context, void *userData) andrewm@268: { andrewm@268: for(int n = 0; n < context->audioFrames; n++) { andrewm@268: // Keep this code: it schedules the touch sensor readings andrewm@268: if(++readCount >= readIntervalSamples) { andrewm@268: readCount = 0; giuliomoro@301: Bela_scheduleAuxiliaryTask(i2cTask); andrewm@268: } andrewm@268: andrewm@268: float sample = 0.0; andrewm@268: andrewm@268: // This code can be replaced with your favourite audio code andrewm@268: for(int i = 0; i < NUM_TOUCH_PINS; i++) { andrewm@268: float amplitude = sensorValue[i] / 400.0; andrewm@268: andrewm@268: // Prevent clipping andrewm@268: if(amplitude > 0.5) andrewm@268: amplitude = 0.5; andrewm@268: andrewm@268: sample += amplitude * sinf(gPhases[i]); andrewm@268: gPhases[i] += gNormFrequencies[i]; andrewm@268: if(gPhases[i] > 2.0 * M_PI) andrewm@268: gPhases[i] -= 2.0 * M_PI; andrewm@268: } andrewm@268: andrewm@268: for(int ch = 0; ch < context->audioChannels; ch++) andrewm@268: context->audioOut[context->audioChannels * n + ch] = sample; andrewm@268: } andrewm@268: } andrewm@268: andrewm@268: // cleanup() is called once at the end, after the audio has stopped. andrewm@268: // Release any resources that were allocated in setup(). andrewm@268: giuliomoro@301: void cleanup(BelaContext *context, void *userData) andrewm@268: { andrewm@268: // Nothing to do here andrewm@268: } andrewm@268: andrewm@268: andrewm@268: // Auxiliary task to read the I2C board andrewm@268: void readMPR121() andrewm@268: { andrewm@268: for(int i = 0; i < NUM_TOUCH_PINS; i++) { andrewm@268: sensorValue[i] = -(mpr121.filteredData(i) - mpr121.baselineData(i)); andrewm@268: sensorValue[i] -= threshold; andrewm@268: if(sensorValue[i] < 0) andrewm@268: sensorValue[i] = 0; andrewm@268: #ifdef DEBUG_MPR121 andrewm@268: rt_printf("%d ", sensorValue[i]); andrewm@268: #endif andrewm@268: } andrewm@268: #ifdef DEBUG_MPR121 andrewm@268: rt_printf("\n"); andrewm@268: #endif andrewm@268: andrewm@268: // You can use this to read binary on/off touch state more easily andrewm@268: //rt_printf("Touched: %x\n", mpr121.touched()); giuliomoro@301: }