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 } |