Clemens Valens
/
touchpad
mbed with Nintendo DS touchpad, accelerometer & touchpad.
Revision 0:0a76ae27065b, committed 2010-05-05
- Comitter:
- Clemo
- Date:
- Wed May 05 12:10:15 2010 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accelerometer.cpp Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,52 @@ +/* +Accelerometer driver. + +CPV, 4/9/2009 +*/ + +#include "accelerometer.h" + + +void Accelerometer1D::initialise(PinName pin, int tau, int offset) +{ + m_pin = pin; + m_offset = offset; + m_filter.initialise(tau); +} + + +//=============================================== + + +Accelerometer2D::Accelerometer2D(PinName ch0, PinName ch1, int tau, int offset) +{ + m_channels[0].initialise(ch0,tau,offset); + m_channels[1].initialise(ch1,tau,offset); +} + + +void Accelerometer2D::tick(void) +{ + m_channels[0].tick(); + m_channels[1].tick(); +} + + +//=============================================== + + +Accelerometer3D::Accelerometer3D(PinName ch0, PinName ch1, PinName ch2, int tau, int offset) +{ + m_channels[0].initialise(ch0,tau,offset); + m_channels[1].initialise(ch1,tau,offset); + m_channels[2].initialise(ch2,tau,offset); +} + + +void Accelerometer3D::tick(void) +{ + m_channels[0].tick(); + m_channels[1].tick(); + m_channels[2].tick(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accelerometer.h Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,54 @@ +/* +Accelerometer driver. + +CPV, 4/9/2009 +*/ + +#ifndef __ACCELEROMETER_H__ +#define __ACCELEROMETER_H__ + + +#include "mbed.h" +#include "filters.h" + + +class Accelerometer1D +{ +public: + void initialise(PinName pin, int tau, int offset=0xffff>>1); + void tick(void) { m_filter.tick((int)AnalogIn(m_pin).read_u16()&0xfff0); } + int operator()(void) { return m_filter() - m_offset; } + int read(void) { return m_filter() - m_offset; } + +protected: + FilterIirI m_filter; + PinName m_pin; + int m_offset; +}; + + +class Accelerometer2D +{ +public: + Accelerometer2D(PinName ch0, PinName ch1, int tau, int offset=0xffff>>1); + void tick(void); + int read(int ch) { return m_channels[ch].read(); } + +protected: + Accelerometer1D m_channels[2]; +}; + + +class Accelerometer3D +{ +public: + Accelerometer3D(PinName ch0, PinName ch1, PinName ch2, int tau, int offset=0xffff>>1); + void tick(void); + int read(int ch) { return m_channels[ch].read(); } + +protected: + Accelerometer1D m_channels[3]; +}; + + +#endif // __ACCELEROMETER_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filters.cpp Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,84 @@ +/* +mbed touchpad & accelerometer experiments. + +CPV, 14/09/2009 +*/ + + +#include <string.h> +#include "filters.h" + + +void FilterBoxF::initialise(unsigned int size) +{ + m_size = size; + if (m_size>FILTER_MAX_SIZE) m_size = FILTER_MAX_SIZE; + memset(m_history,0,sizeof(float)*FILTER_MAX_SIZE); + m_index = 0; + m_out = 0; +} + + +float FilterBoxF::tick(float in) +{ + m_history[m_index] = in; + m_index += 1; + if (m_index>=m_size) m_index = 0; + + float sum = 0; + for (int i=0; i<m_size; i++) + { + sum += m_history[i]; + } + m_out = sum/m_size; + return m_out; +} + +//================================= + +void FilterBoxI::initialise(unsigned int size) +{ + m_size = size; + if (m_size>FILTER_MAX_SIZE) m_size = FILTER_MAX_SIZE; + memset(m_history,0,sizeof(int)*FILTER_MAX_SIZE); + m_index = 0; + m_out = 0; +} + + +int FilterBoxI::tick(int in) +{ + m_history[m_index] = in; + m_index += 1; + if (m_index>=m_size) m_index = 0; + + int sum = 0; + for (int i=0; i<m_size; i++) + { + sum += m_history[i]; + } + m_out = sum/m_size; + return m_out; +} + +//================================= + +void FilterIirI::initialise(int tau, int limit) +{ + m_tau = tau; + m_limit = limit; + m_remainder = 0; + m_out = 0; +} + + +int FilterIirI::tick(int in) +{ + int temp = in - m_out + m_remainder; + m_remainder = temp % m_tau; + m_out += temp / m_tau; + if (m_out>m_limit) m_out = m_limit; + if (m_out<-m_limit) m_out = -m_limit; + return m_out; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filters.h Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,62 @@ +/* +mbed touchpad & accelerometer experiments. + +CPV, 14/09/2009 +*/ + + +#ifndef __FILTERS_H__ +#define __FILTERS_H__ + +#define FILTER_MAX_SIZE 16 + +class FilterBoxF +{ +public: + FilterBoxF(void) { initialise(FILTER_MAX_SIZE); } + void initialise(unsigned int size); + float tick(float in); + float get() { return m_out; } + float operator()(void) { return m_out; } + +protected: + float m_history[FILTER_MAX_SIZE]; + unsigned int m_size; + unsigned int m_index; + float m_out; +}; + + +class FilterBoxI +{ +public: + FilterBoxI(void) { initialise(FILTER_MAX_SIZE); } + void initialise(unsigned int size); + int tick(int in); + int operator()(void) { return m_out; } + +protected: + int m_history[FILTER_MAX_SIZE]; + unsigned int m_size; + unsigned int m_index; + int m_out; +}; + + +class FilterIirI +{ +public: + FilterIirI(void) { initialise(); } + void initialise(int tau=1, int limit=0xffff); + int tick(int in); + int operator()(void) { return m_out; } + +protected: + int m_out; + int m_remainder; + int m_limit; + int m_tau; +}; + + +#endif // __FILTERS_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,123 @@ +/* +mbed touchpad & accelerometer experiments. + +CPV, 14/09/2009 +*/ + +#include "mbed.h" +#include "touchpad.h" +#include "accelerometer.h" +#include "my_pwm_out.h" + + +// Pin definitions. +#define ACC0 p20 +#define ACC1 p19 +#define X0 p18 +#define Y0 p17 +#define X1 p16 +#define Y1 p15 + + +// Some global objects. +DigitalOut led1(LED1); +Ticker timer1; // Sample clock. +Ticker timer2; // "keyboard" scan clock. +Ticker timer3; // LED clock. +Touchpad tp(X0,X1,Y0,Y1); +Accelerometer2D acc(ACC0,ACC1,10); +MyPwmOut buzzer(p21); // Subclassed from PwmOut. + + +float DutyCycle = 0.0; // No sound. +int Period = 1136; // in us => 880 Hz. +int FlagUpdateSound = 0; + +// Periods in us. +const int freq[4][6] = +{ + { 1607, 1517, 1432, 1351, 1276, 1204 }, + { 1136, 1073, 1012, 956, 902, 851 }, + { 804, 758, 716, 676, 638, 602 }, + { 568, 536, 506, 478, 451, 426 }, +}; + + +void sample(void) +{ + tp.tick(); + acc.tick(); +} + + +void scan_keyboard(void) +{ + if (tp.hotspot()>0) + { + int x = tp.get_hotspot_x(); + int y = tp.get_hotspot_y(); + Period = freq[y][x]*(1.0+acc.read(0)/64000.0); + DutyCycle = 0.5 + acc.read(1)/32000.0; + FlagUpdateSound = 1; + } + else + { + if (DutyCycle!=0.0) + { + DutyCycle = 0.0; + FlagUpdateSound = 1; + } + } +} + + +void toggle_led(void) +{ + if (led1==1) led1 = 0; + else led1 = 1; +} + + +int main() +{ + printf("\n"); + printf("-=o Touch, Shake & Whine o=-\n"); + printf("\n"); + printf("mbed touchpad & 2D accelerometer demo\n"); + printf("\n"); + printf("A buzzer is driven by a PWM signal to generate musical notes.\n"); + printf("A touchpad is used as a keypad, divided in a 6 by 4 matrix.\n"); + printf("The position on the touchpad determines the note played by the\n"); + printf("buzzer. A 2-axis accelerometer is used to modulate the frequency\n"); + printf("and the duty-cycle of the PWM signal.\n"); + printf("A blinking LED shows that the system is running.\n"); + printf("\n"); + printf("Touch & shake the circuit to make it whine.\n"); + printf("\n"); + printf("Demonstrates:\n"); + printf("- the use of a resistive touchpad\n"); + printf("- the use of a 2D accelerometer\n"); + printf("- the use of PWM for smooth frequency generation\n"); + printf("- on-the-fly pin function switching\n"); + printf("- mbed \"base\" class extension\n"); + printf("\n"); + printf("CPV, 14/09/2009\n"); + printf("\n"); + printf(" -end-\n\n"); + + led1 = 1; // LED on. + + timer1.attach_us(&sample,1000); // Sample every 1 ms. + timer2.attach_us(&scan_keyboard,10000); // Scan the touchpad every 10 ms. + timer3.attach_us(&toggle_led,500000); // Toggle the LED every 500 ms. + + while (1) + { + if (FlagUpdateSound==1) + { + // Only update period & duty-cycle when new data is available. + FlagUpdateSound = 0; + buzzer.set(Period/1000000.0,DutyCycle); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/f63353af7be8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/my_pwm_out.cpp Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,56 @@ +/* +mbed touchpad & accelerometer experiments. + +CPV, 14/09/2009 +*/ + + +#include "my_pwm_out.h" + + +using namespace mbed; + + +MyPwmOut::MyPwmOut(PinName pin, const char *name) : PwmOut(pin,name) +{ + m_channel = (pin&0x0000001f) + 1; // Between 1 and 6. + m_p_mrx = (uint32_t *)&LPC_PWM1->MR0 + m_channel; // Select MRx register for this channel. + if (m_channel>=4) m_p_mrx += 6; // Skip CR registers if needed. + m_pclk = get_pclk(); +} + + +float MyPwmOut::get_pclk(void) +{ + float Fin = 12000000; // From the mbed schematic. + uint32_t m = 1 + (LPC_SC->PLL0STAT&0x00007fff); + uint32_t n = 1 + ((LPC_SC->PLL0STAT&0x00ff0000)>>16); + float Fcco = 2*m*Fin/n; // PLL frequency. + float cclk = Fcco/(1+(LPC_SC->CCLKCFG&0x000000ff)); // Get CCLK from Fcco. + + m_pclk = cclk/4; + switch ((LPC_SC->PCLKSEL0&0x00003000)>>12) + { + case 0: m_pclk = cclk/4; break; + case 1: m_pclk = cclk; break; + case 2: m_pclk = cclk/2; break; + case 3: m_pclk = cclk/8; break; + } + + //printf("Fin = %0.0f\n",Fin); + //printf("m = %d, n = %d\n",m,n); + //printf("Fcco = %0.0f\n",Fcco); + //printf("CLKC = %0.0f\n",cclk); + //printf("PLCK = %0.0f\n",m_pclk); + + return m_pclk; +} + + +void MyPwmOut::set(float period, float duty_cycle) +{ + LPC_PWM1->MR0 = period*m_pclk; // Set new period in seconds. + *m_p_mrx = duty_cycle * LPC_PWM1->MR0; // Set new duty-cycle. + LPC_PWM1->LER |= (1<<m_channel)|1; // Use MRx & MR0 value on next TC reset. +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/my_pwm_out.h Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,51 @@ +/* +mbed touchpad & accelerometer experiments. + +CPV, 14/09/2009 +*/ + + +#ifndef __MY_PWM_OUT_H__ +#define __MY_PWM_OUT_H__ + + +#include "PwmOut.h" +namespace mbed +{ + +class MyPwmOut : public PwmOut +{ +public: + /* Constructor: PwmOut + * Create a PwmOut connected to the specified pin + * + * Variables: + * pin - PwmOut pin to connect to + */ + MyPwmOut(PinName pin, const char *name = NULL); + + /* Function: set + * Set the PWM period, specified in seconds (float) + * and the ouput duty-cycle, specified as a percentage (float) + * + * Variables: + * period - A floating-point value representing the output period, + * specified in seconds. + * duty_cycle - A floating-point value representing the output duty-cycle, + * specified as a percentage. The value should lie between + * 0.0f (representing on 0%) and 1.0f (representing on 100%). + * Values outside this range will be saturated to 0.0f or 1.0f. + */ + void set(float period, float duty_cycle); + + float get_pclk(void); + +protected: + float m_pclk; + uint32_t m_channel; + uint32_t *m_p_mrx; +}; + +} // namespace mbed + +#endif // __MY_PWM_OUT_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/touchpad.cpp Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,66 @@ +/* +Touchpad driver. + +CPV, 3/9/2009 +*/ + +#include "touchpad.h" + + +void TouchpadChannel::initialise(int min, int quantise_step) +{ + m_min = min; + m_quantise_step = quantise_step; + m_filter.initialise(8); + m_quantised = -1; +} + + +int TouchpadChannel::quantise(void) +{ + m_quantised = -1; + int raw = m_filter(); + if (raw>m_min) + { + m_quantised = 0; + while(raw>m_quantise_step) + { + raw -= m_quantise_step; + m_quantised += 1; + } + } + return m_quantised; +} + + +//=============================================== + + +Touchpad::Touchpad(PinName x0, PinName x1, PinName y0, PinName y1) +{ + m_x0 = x0; + m_x1 = x1; + m_y0 = y0; + m_y1 = y1; + m_ch_x.initialise(0.1*0xffff,0.16*0xffff); + m_ch_y.initialise(0.1*0xffff,0.22*0xffff); +} + + +int Touchpad::read(PinName drive_hi, PinName drive_lo, PinName read_hi, PinName read_lo) +{ + DigitalOut out1(drive_hi); + DigitalOut out0(drive_lo); + AnalogIn in1(read_hi); + AnalogIn in0(read_lo); + out0 = 0; + out1 = 1; + return in1.read_u16(); +} + + +void Touchpad::tick(void) +{ + m_ch_x.tick(read_x()); + m_ch_y.tick(read_y()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/touchpad.h Wed May 05 12:10:15 2010 +0000 @@ -0,0 +1,61 @@ +/* +Touchpad driver. + +CPV, 3/9/2009 +*/ + +#ifndef __TOUCHPAD_H__ +#define __TOUCHPAD_H__ + + +#include "mbed.h" +#include "filters.h" + + +class TouchpadChannel +{ +public: + void initialise(int min, int quantise_step); + void tick(int v) { m_filter.tick(v); } + int quantise(void); + int operator()(void) { return m_quantised; } + int get_raw(void) { return m_filter(); } + +protected: + FilterBoxI m_filter; + int m_min; + int m_quantise_step; + int m_quantised; +}; + + +class Touchpad +{ +public: + Touchpad(PinName x0, PinName x1, PinName y0, PinName y1); + + void tick(void); + + int get_raw_x(void) { return m_ch_x.get_raw(); } + int get_raw_y(void) { return m_ch_y.get_raw(); } + + int hotspot(void) { return (m_ch_x.quantise()>=0 && m_ch_y.quantise()>=0); } + int get_hotspot_x(void) { return m_ch_x(); } + int get_hotspot_y(void) { return m_ch_y(); } + +protected: + TouchpadChannel m_ch_x; + TouchpadChannel m_ch_y; + + PinName m_x0; + PinName m_x1; + PinName m_y0; + PinName m_y1; + + int read(PinName drive_hi, PinName drive_lo, PinName read_hi, PinName read_lo); + int read_x(void) { return read(m_x1,m_x0,m_y1,m_y0); } + int read_y(void) { return read(m_y1,m_y0,m_x1,m_x0); } +}; + + +#endif // __TOUCHPAD_H__