mbed with Nintendo DS touchpad, accelerometer & touchpad.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Clemo
Date:
Wed May 05 12:10:15 2010 +0000
Commit message:

Changed in this revision

accelerometer.cpp Show annotated file Show diff for this revision Revisions of this file
accelerometer.h Show annotated file Show diff for this revision Revisions of this file
filters.cpp Show annotated file Show diff for this revision Revisions of this file
filters.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
my_pwm_out.cpp Show annotated file Show diff for this revision Revisions of this file
my_pwm_out.h Show annotated file Show diff for this revision Revisions of this file
touchpad.cpp Show annotated file Show diff for this revision Revisions of this file
touchpad.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 0a76ae27065b accelerometer.cpp
--- /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();
+}
+
diff -r 000000000000 -r 0a76ae27065b accelerometer.h
--- /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__
diff -r 000000000000 -r 0a76ae27065b filters.cpp
--- /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;
+}
+
diff -r 000000000000 -r 0a76ae27065b filters.h
--- /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__
diff -r 000000000000 -r 0a76ae27065b main.cpp
--- /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);
+    }
+  }
+}
diff -r 000000000000 -r 0a76ae27065b mbed.bld
--- /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
diff -r 000000000000 -r 0a76ae27065b my_pwm_out.cpp
--- /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.
+}
+
diff -r 000000000000 -r 0a76ae27065b my_pwm_out.h
--- /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__
diff -r 000000000000 -r 0a76ae27065b touchpad.cpp
--- /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());
+}
diff -r 000000000000 -r 0a76ae27065b touchpad.h
--- /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__