Rei Vilo
Published © CC BY-NC-SA

Multi-Touch with CapTIvate

Use CapTIvate technology for multi-touch with 64 pads!

IntermediateFull instructions provided2 hours2,855
Multi-Touch with CapTIvate

Things used in this project

Hardware components

MSP430 Microcontroller
Texas Instruments MSP430 Microcontroller
×1
Texas Instruments CapTIvate MCU Development Kit
×1

Software apps and online services

Energia
Texas Instruments Energia
Code Composer Studio
Texas Instruments Code Composer Studio
Texas Instruments CapTIvate Design Center GUIhttp://www.ti.com/tool/mspcaptdsnctr

Story

Read more

Code

CapTIvate-64.ino

C/C++
///
/// @file	      CapTIvate_public.ino
/// @brief      Main sketch
///
/// @details    CapTIvate project for Hackster.io
/// @n @a       Developed with [embedXcode+](http://embedXcode.weebly.com)
///
/// @author     Rei Vilo
/// @author     http://www.embeddedcomputing.weebly.com
/// @date       Jul 17, 2016
/// @version    101
///
/// @copyright	(c) Rei Vilo, 2016
/// @copyright	CC = BY SA NC
///
/// @see		    ReadMe.txt for references
/// @n
///


// Core library for code-sense - IDE-based
#include "Energia.h"

// Set parameters
#define I2C_SLAVE 0x0a
#define pinIRQ 8
#define pinSingleTouch 11
#define pinMultipleTouch 12

// Include application, user and local libraries
#include "Wire.h"
#include "SPI.h"
#include "Screen_K35_SPI.h"
Screen_K35_SPI myScreen;

// Define structures and classes
struct element_t
{
  uint16_t LTAValue;                                                          // long term average
  uint16_t countValue;
};

struct packetCycle_t
{
  uint8_t byteCommand;
  uint8_t byteSensorID;
  uint8_t byteCycleID;
  uint16_t bitsCycleTouchState;
  uint16_t bitsCycleProximityState;
  uint32_t bitsCycleState;
  uint8_t numberElements;
  element_t element[12];
  uint16_t packetChecksum;
};

enum state_t
{
  stateNone,
  stateProximity,
  stateTouch
};

// Define variables and constants
uint8_t buffer[54];
packetCycle_t packetCycle;
uint8_t numberBytes;
state_t table[8][8] = { stateNone };
state_t oldTable[8][8] = { stateNone };
uint8_t x, y;
uint8_t countTouch = 0;
uint8_t countProximity = 0;
String text;

// Prototypes
bool isSomething();
void getCapTIvate64();
void prepareScreen();
void refreshScreen();

// Functions
bool isSomething()
{
  return (countProximity + countTouch > 0);
}

void getCapTIvate64()
{
  uint16_t calculatedChecksum = 0;
  bool flagComplete = false;
  uint16_t cycles = 0;

  // Initialise scan
  memset(table, stateNone, sizeof(table));
  countTouch = 0;
  countProximity = 0;

  // Perform scan
  while (!flagComplete)
  {
    if (digitalRead(pinIRQ))
    {
      packetCycle.numberElements = (numberBytes - 8) / 4;

      Wire.requestFrom(I2C_SLAVE, 48);
      numberBytes = Wire.read();

      calculatedChecksum = 0;
      for (uint8_t i = 0; i < numberBytes; i++)
      {
        buffer[i] = Wire.read();
        if (i < numberBytes - 2)
        {
          calculatedChecksum += buffer[i];
        }
      }

      // Scan cycles management
      packetCycle.byteCycleID = buffer[2];
      bitSet(cycles, packetCycle.byteCycleID);
      flagComplete = (cycles == 0xffff);

      packetCycle.packetChecksum = buffer[numberBytes - 2] + buffer[numberBytes - 1] * 256;
      if (calculatedChecksum == packetCycle.packetChecksum)               // Is checksum correct?
      {
        // Command byte
        packetCycle.byteCommand = buffer[0];
        // Is packet and is there some proximity or touch state?
        if ((packetCycle.byteCommand == 0x01) and (buffer[3] or buffer[4] or buffer[5]))
        {
          packetCycle.numberElements = (numberBytes - 8) / 4;         // 4 bytes per element
          packetCycle.byteSensorID = buffer[1];
          packetCycle.byteCycleID = buffer[2];

          packetCycle.bitsCycleState = (uint32_t)((buffer[5] << 16) + (buffer[4] << 8) + buffer[3]);

          for (uint8_t elementID = 0; elementID < packetCycle.numberElements; elementID++)
          {
            x = 2 * elementID + (packetCycle.byteCycleID % 2);
            y = packetCycle.byteCycleID / 2;

            if (bitRead(packetCycle.bitsCycleState, (elementID)))
            {
              if (table[x][y] != stateTouch)
              {
                table[x][y] = stateProximity;
                countProximity += 1;
              }
            }
            if (bitRead(packetCycle.bitsCycleState, (12 + elementID)))
            {
              table[x][y] = stateTouch;
              countTouch += 1;
            }
          }
        }
      }
    }
  }
}

void prepareScreen()
{
  myScreen.begin();
  myScreen.setOrientation(0);
  myScreen.setFontSize(0);
  myScreen.gText(0, myScreen.screenSizeY() - 2 * myScreen.fontSizeY(), "MSP432 LP and CapTIvate BP");
  myScreen.gText(0, myScreen.screenSizeY() - myScreen.fontSizeY(), "LCD_screen with Energia");

  myScreen.setOrientation(1);

  myScreen.setPenSolid(false);
  for (uint8_t j = 0; j < 8; j++)
  {
    for (uint8_t i = 0; i < 8; i++)
    {
      myScreen.dRectangle(30 * i, 30 * j, 28, 28, whiteColour);
      text = String(j * 8 + i + 1);
      myScreen.gText(30 * i + 4 + (20 - myScreen.fontSizeX() * text.length()) / 2, 30 * j + 4 + (20 - myScreen.fontSizeY()) / 2, text, whiteColour);
    }
  }
  myScreen.setPenSolid(true);
  myScreen.setFontSolid(false);
}

void refreshScreen()
{
  uint16_t colourRectangle = blackColour;
  uint16_t colourText = whiteColour;

  for (uint8_t j = 0; j < 8; j++)
  {
    for (uint8_t i = 0; i < 8; i++)
    {
      if (table[i][j] != oldTable[i][j])
      {
        text = String(j * 8 + i + 1);
        switch (table[i][j])
        {
          case stateProximity:

            colourRectangle = orangeColour;
            colourText = blackColour;
            break;

          case stateTouch:

            colourRectangle = greenColour;
            colourText = blackColour;
            break;

          default:

            colourRectangle = blackColour;
            colourText = whiteColour;
            break;
        }
        myScreen.dRectangle(30 * i + 4, 30 * j + 4, 20, 20, colourRectangle);
        myScreen.gText(30 * i + 4 + (20 - myScreen.fontSizeX() * text.length()) / 2, 30 * j + 4 + (20 - myScreen.fontSizeY()) / 2, text, colourText);
      }
    }
  }
  memcpy(oldTable, table, sizeof(table));
}

// Add setup code
void setup()
{
  Wire.begin();

  pinMode(pinIRQ, INPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(pinSingleTouch, INPUT); // Single touch
  pinMode(pinMultipleTouch, INPUT); // Multiple touch

  prepareScreen();
}

// Add loop code
void loop()
{
  getCapTIvate64();
  refreshScreen();
}

Credits

Rei Vilo

Rei Vilo

14 projects • 25 followers

Comments