annotate projects/mpr121/render.cpp @ 268:8d80eda512cd prerelease

Added new overlay for using PRU0 or PRU1, a script to halt board on button press, and several example projects
author andrewm
date Tue, 17 May 2016 14:46:26 +0100
parents
children
rev   line source
andrewm@268 1 #include <BeagleRT.h>
andrewm@268 2 #include <Utilities.h>
andrewm@268 3 #include <cmath>
andrewm@268 4 #include <rtdk.h>
andrewm@268 5 #include "I2C_MPR121.h"
andrewm@268 6
andrewm@268 7 // How many pins there are
andrewm@268 8 #define NUM_TOUCH_PINS 12
andrewm@268 9
andrewm@268 10 // Define this to print data to terminal
andrewm@268 11 #undef DEBUG_MPR121
andrewm@268 12
andrewm@268 13 // Change this to change how often the MPR121 is read (in Hz)
andrewm@268 14 int readInterval = 50;
andrewm@268 15
andrewm@268 16 // Change this threshold to set the minimum amount of touch
andrewm@268 17 int threshold = 40;
andrewm@268 18
andrewm@268 19 // This array holds the continuous sensor values
andrewm@268 20 int sensorValue[NUM_TOUCH_PINS];
andrewm@268 21
andrewm@268 22 // ---- test code stuff -- can be deleted for your example ----
andrewm@268 23
andrewm@268 24 // 12 notes of a C major scale...
andrewm@268 25 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 26
andrewm@268 27 // This is internal stuff for the demo
andrewm@268 28 float gNormFrequencies[NUM_TOUCH_PINS];
andrewm@268 29 float gPhases[NUM_TOUCH_PINS] = {0};
andrewm@268 30
andrewm@268 31 // ---- internal stuff -- do not change -----
andrewm@268 32
andrewm@268 33 I2C_MPR121 mpr121; // Object to handle MPR121 sensing
andrewm@268 34 AuxiliaryTask i2cTask; // Auxiliary task to read I2C
andrewm@268 35
andrewm@268 36 int readCount = 0; // How long until we read again...
andrewm@268 37 int readIntervalSamples = 0; // How many samples between reads
andrewm@268 38
andrewm@268 39 void readMPR121();
andrewm@268 40
andrewm@268 41 // setup() is called once before the audio rendering starts.
andrewm@268 42 // Use it to perform any initialisation and allocation which is dependent
andrewm@268 43 // on the period size or sample rate.
andrewm@268 44 //
andrewm@268 45 // userData holds an opaque pointer to a data structure that was passed
andrewm@268 46 // in from the call to initAudio().
andrewm@268 47 //
andrewm@268 48 // Return true on success; returning false halts the program.
andrewm@268 49
andrewm@268 50 bool setup(BeagleRTContext *context, void *userData)
andrewm@268 51 {
andrewm@268 52 if(!mpr121.begin(1, 0x5A)) {
andrewm@268 53 rt_printf("Error initialising MPR121\n");
andrewm@268 54 return false;
andrewm@268 55 }
andrewm@268 56
andrewm@268 57 i2cTask = BeagleRT_createAuxiliaryTask(readMPR121, 50, "beaglert-mpr121");
andrewm@268 58 readIntervalSamples = context->audioSampleRate / readInterval;
andrewm@268 59
andrewm@268 60 for(int i = 0; i < NUM_TOUCH_PINS; i++) {
andrewm@268 61 gNormFrequencies[i] = 2.0 * M_PI * gFrequencies[i] / context->audioSampleRate;
andrewm@268 62 }
andrewm@268 63
andrewm@268 64 return true;
andrewm@268 65 }
andrewm@268 66
andrewm@268 67 // render() is called regularly at the highest priority by the audio engine.
andrewm@268 68 // Input and output are given from the audio hardware and the other
andrewm@268 69 // ADCs and DACs (if available). If only audio is available, numAnalogFrames
andrewm@268 70 // will be 0.
andrewm@268 71
andrewm@268 72 void render(BeagleRTContext *context, void *userData)
andrewm@268 73 {
andrewm@268 74 for(int n = 0; n < context->audioFrames; n++) {
andrewm@268 75 // Keep this code: it schedules the touch sensor readings
andrewm@268 76 if(++readCount >= readIntervalSamples) {
andrewm@268 77 readCount = 0;
andrewm@268 78 BeagleRT_scheduleAuxiliaryTask(i2cTask);
andrewm@268 79 }
andrewm@268 80
andrewm@268 81 float sample = 0.0;
andrewm@268 82
andrewm@268 83 // This code can be replaced with your favourite audio code
andrewm@268 84 for(int i = 0; i < NUM_TOUCH_PINS; i++) {
andrewm@268 85 float amplitude = sensorValue[i] / 400.0;
andrewm@268 86
andrewm@268 87 // Prevent clipping
andrewm@268 88 if(amplitude > 0.5)
andrewm@268 89 amplitude = 0.5;
andrewm@268 90
andrewm@268 91 sample += amplitude * sinf(gPhases[i]);
andrewm@268 92 gPhases[i] += gNormFrequencies[i];
andrewm@268 93 if(gPhases[i] > 2.0 * M_PI)
andrewm@268 94 gPhases[i] -= 2.0 * M_PI;
andrewm@268 95 }
andrewm@268 96
andrewm@268 97 for(int ch = 0; ch < context->audioChannels; ch++)
andrewm@268 98 context->audioOut[context->audioChannels * n + ch] = sample;
andrewm@268 99 }
andrewm@268 100 }
andrewm@268 101
andrewm@268 102 // cleanup() is called once at the end, after the audio has stopped.
andrewm@268 103 // Release any resources that were allocated in setup().
andrewm@268 104
andrewm@268 105 void cleanup(BeagleRTContext *context, void *userData)
andrewm@268 106 {
andrewm@268 107 // Nothing to do here
andrewm@268 108 }
andrewm@268 109
andrewm@268 110
andrewm@268 111 // Auxiliary task to read the I2C board
andrewm@268 112 void readMPR121()
andrewm@268 113 {
andrewm@268 114 for(int i = 0; i < NUM_TOUCH_PINS; i++) {
andrewm@268 115 sensorValue[i] = -(mpr121.filteredData(i) - mpr121.baselineData(i));
andrewm@268 116 sensorValue[i] -= threshold;
andrewm@268 117 if(sensorValue[i] < 0)
andrewm@268 118 sensorValue[i] = 0;
andrewm@268 119 #ifdef DEBUG_MPR121
andrewm@268 120 rt_printf("%d ", sensorValue[i]);
andrewm@268 121 #endif
andrewm@268 122 }
andrewm@268 123 #ifdef DEBUG_MPR121
andrewm@268 124 rt_printf("\n");
andrewm@268 125 #endif
andrewm@268 126
andrewm@268 127 // You can use this to read binary on/off touch state more easily
andrewm@268 128 //rt_printf("Touched: %x\n", mpr121.touched());
andrewm@268 129 }