Basic calculator example to show the LPC4088 Experiment Base Board with a touch LCD from DisplayModule

Dependencies:   DmTftLibrary mbed

Fork of dm_calc by Display Module

main.cpp

Committer:
embeddedartists
Date:
2014-09-11
Revision:
5:d2802a0c5af2
Parent:
4:71588a1e3618

File content as of revision 5:d2802a0c5af2:

/**********************************************************************************************
 Copyright (c) 2014 DisplayModule. All rights reserved.

 Redistribution and use of this source code, part of this source code or any compiled binary
 based on this source code is permitted as long as the above copyright notice and following
 disclaimer is retained.

 DISCLAIMER:
 THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES
 NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE.
 ********************************************************************************************/

/******************************************************************************
 * Includes
 *****************************************************************************/

#include "mbed.h"

#include "DmTftHX8353C.h"
#include "DmTftS6D0164.h"
#include "DmTftIli9325.h"
#include "DmTftIli9341.h"
#include "DmTftSsd2119.h"
#include "DmTouch.h"

#include "Button.h"

/******************************************************************************
 * Typedefs and defines
 *****************************************************************************/

typedef enum {
  MODE_WANT_ARG1,
  MODE_WANT_ARG1_OR_OP,
  MODE_WANT_ARG2,
  MODE_WANT_ARG2_OR_OP,
} calc_mode_t;

#define MARGIN  5

#define RESULT_MARGIN_X  (MARGIN*3)
#define RESULT_MARGIN_Y  (MARGIN*3)

#define NUM_BUTTONS  (sizeof(captions)/sizeof(captions[0]))

#define NUM_CHARS_IN_DISPLAY  20

#if 0
  /* Displays without adapter (DM_TFT28_105 & DM_TFT35_107) */
  #define DM_PIN_CS_TOUCH   D4
  #define DM_PIN_CS_TFT     D10
  #define DM_PIN_CS_SDCARD  D8
  #define DM_PIN_CS_FLASH   D6
#else
  /* Displays with adapter (all other displays) */
  #define DM_PIN_CS_TFT     D4
  #define DM_PIN_CS_SDCARD  D10
#endif

//#define LANDSCAPE

/******************************************************************************
 * Local variables
 *****************************************************************************/

DmTftIli9325 tft;   /* DM_TFT28_103 and DM_TFT24_104 with adapter in arduino J1 contact */
//DmTftIli9341 tft;   /* DM_TFT28_105 directly in arduino J1 contact (no adapter) */
//DmTftSsd2119 tft;   /* DM_TFT35_107 directly in arduino J1 contact (no adapter) */

//DmTouch touch(DmTouch::DM_TFT28_103, DmTouch::Software);
DmTouch touch(DmTouch::DM_TFT24_104, DmTouch::Software);
//DmTouch touch(DmTouch::DM_TFT28_105);
//DmTouch touch(DmTouch::DM_TFT35_107);

#ifdef DM_PIN_CS_TOUCH
  DigitalInOut csTouch(DM_PIN_CS_TOUCH, PIN_OUTPUT, PullUp, 1);
#endif
DigitalInOut csDisplay(DM_PIN_CS_TFT, PIN_OUTPUT, PullUp, 1);
DigitalInOut csSDCard(DM_PIN_CS_SDCARD, PIN_OUTPUT, PullUp, 1);
#ifdef DM_PIN_CS_FLASH
  DigitalInOut csFlash(DM_PIN_CS_FLASH, PIN_OUTPUT, PullUp, 1);
#endif  

#ifdef LANDSCAPE
  #define BUTTONS_PER_LINE   6
  #define BUTTONS_NUM_LINES  3
  /*
   *   1   2   3   4   5   +
   *   6   7   8   9   0   -
   *   *   /   =   clr
   */
  const char* captions[] = {
      "1","2","3","4","5","+",
      "6","7","8","9","0","-",
      "*","/","=","clr",
  };  
#else
  #define BUTTONS_PER_LINE   4
  #define BUTTONS_NUM_LINES  4
  /*
   *   1   2   3   +
   *   4   5   6   -
   *   7   8   9   *
   *   0   =  clr  /
   */
  const char* captions[] = {
      "1","2","3","+",
      "4","5","6","-",
      "7","8","9","*",
      "0","=","clr","/",
  };
#endif
  
Button* buttons[NUM_BUTTONS];

static char buff[NUM_CHARS_IN_DISPLAY + 1] = {0};
static bool redrawResult = true;
static bool clearResult = true;

/******************************************************************************
 * Global variables
 *****************************************************************************/


/******************************************************************************
 * Local functions
 *****************************************************************************/

void handleClick(uint32_t arg)
{
  static int val1 = 0;
  static int val2 = 0;
  static int op = 0;
  static calc_mode_t mode = MODE_WANT_ARG1;
  static int strpos = 0;
  
  if (strpos == NUM_CHARS_IN_DISPLAY) {
    // only accept 'clr' and '=' to prevent overflow
    if ((arg != 'c') && (arg != '=')) {
      return;
    }
  }
    
  switch (arg)
  {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      if ((mode == MODE_WANT_ARG1) || (mode == MODE_WANT_ARG1_OR_OP)) {
        val1 = val1*10 + (arg - '0');
        mode = MODE_WANT_ARG1_OR_OP;
        buff[strpos++] = arg;
      } else if ((mode == MODE_WANT_ARG2) || (mode == MODE_WANT_ARG2_OR_OP)) {
        val2 = val2*10 + (arg - '0');
        mode = MODE_WANT_ARG2_OR_OP;
        buff[strpos++] = arg;
      }
      break;
    case '+':
    case '-':
    case '*':
    case '/':
      if (mode == MODE_WANT_ARG1_OR_OP) {
        op = arg;
        mode = MODE_WANT_ARG2;
        buff[strpos++] = arg;
      } else if (mode == MODE_WANT_ARG2_OR_OP) {
        // already have "a op b", calculate it and go to "c op"
        switch (op) {
          case '+':  val1 = val1 + val2; break;
          case '-':  val1 = val1 - val2; break;
          case '*':  val1 = val1 * val2; break;
          case '/':  val1 = val1 / val2; break;
        }
        op = arg;
        val2 = 0;
        mode = MODE_WANT_ARG2;
        strpos = sprintf(buff, "%d%c", val1, op);
        clearResult = true;
      }
      break;
    case 'c':
      val1 = val2 = op = 0;
      mode = MODE_WANT_ARG1;
      strpos = 0;
      clearResult = true;
      break;
    case '=':
    default:
      if (mode == MODE_WANT_ARG2_OR_OP) {
        // already have "a op b", calculate it and go to "c"
        switch (op) {
          case '+':  val1 = val1 + val2; break;
          case '-':  val1 = val1 - val2; break;
          case '*':  val1 = val1 * val2; break;
          case '/':  val1 = val1 / val2; break;
        }
        mode = MODE_WANT_ARG1_OR_OP;
        val2 = 0;
        strpos = sprintf(buff, "%d", val1);
        clearResult = true;
      }
      break;
  }
  buff[strpos] = '\0';
  redrawResult = true;
}

/******************************************************************************
 * Main
 *****************************************************************************/

/*
 Hardware Setup:
 
 - Jumpers JP1..JP6 should be in position 1-2
 - Jumpers in J14 should NOT be inserted
 - Jumper J7 should be inserted
 - Display in arduino socket J1 depending on display
*/

/*
 Test Comments:
 
 - This example cannot be used with the DM-TFT18-101 or DM-TFT22-102 displays
   as they don't have touch support.
 - The DM-TFT22-102, DM-TFT28-103 and DM-TFT24-104 must all be used on top
   of the DM-ADTAU-001 board in the arduino J1 socket.
 - The DM-TFT28-105 and DM-TFT35-107 displays have direct arduino pinning and
   can be inserted directly in the J1 socket.
*/

int main() { 
  uint16_t x = 0;
  uint16_t y = 0;
  uint16_t w = tft.width();
  uint16_t h = tft.height();
  uint16_t size = (w - (BUTTONS_PER_LINE + 1)*MARGIN)/BUTTONS_PER_LINE;
  uint16_t yoff = h - (size + MARGIN)*BUTTONS_NUM_LINES;
  bool down = false;

  for (int i = 0; i < NUM_BUTTONS;i++) {
    x = MARGIN + (size + MARGIN) * (i % BUTTONS_PER_LINE);
    y = yoff + (size + MARGIN) * (i / BUTTONS_PER_LINE);
    buttons[i] = new Button(captions[i], x, y, size, size);
    buttons[i]->setAction(handleClick, captions[i][0]);
  }  
  
  tft.init();
  tft.clearScreen(BRIGHT_RED);
  tft.fillRectangle(RESULT_MARGIN_X, RESULT_MARGIN_Y, w-RESULT_MARGIN_X, yoff-RESULT_MARGIN_Y, BLACK);
  touch.init();

  for (int i = 0; i < NUM_BUTTONS; i++) {
    buttons[i]->draw(&tft);
  }

  while(true) {
    touch.readTouchData(x, y, down);
    
    for (int i = 0; i < NUM_BUTTONS; i++) {
      if (buttons[i]->handle(x, y, down)) {
        buttons[i]->draw(&tft);
      }
    }
    if (clearResult) {
      clearResult = false;
      tft.fillRectangle(RESULT_MARGIN_X, RESULT_MARGIN_Y, w-RESULT_MARGIN_X, yoff-RESULT_MARGIN_Y, BLACK);
    }
    if (redrawResult) {
      redrawResult = false;
      tft.drawStringCentered(RESULT_MARGIN_X, RESULT_MARGIN_Y, w-RESULT_MARGIN_X, yoff-RESULT_MARGIN_Y, &buff[0]);
    }
    wait(0.02);
  }
}