mbed support for LPC4088 Display Module

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src

Dependents:   emptyProgram

Fork of DMSupport by Embedded Artists

DMBoard.cpp

Committer:
embeddedartists
Date:
2015-01-07
Revision:
17:4ea2509445ac
Parent:
13:2c60e28503f8
Child:
20:9df19da50290

File content as of revision 17:4ea2509445ac:

/*
 *  Copyright 2014 Embedded Artists AB
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "mbed.h"
#include "DMBoard.h"
#include "BiosEEPROM.h"
#include "bios.h"
#include "crc.h"

#if defined(DM_BOARD_USE_DISPLAY)
  #include "BiosDisplayAndTouch.h"
#endif

#if defined(DM_BOARD_ENABLE_MEASSURING_PINS)
  #include "meas.h"
#endif        


/******************************************************************************
 * Configuration Compatibility Control
 *****************************************************************************/

#if defined(DM_BOARD_USE_USB_DEVICE) && defined(DM_BOARD_USE_USB_HOST)
  #error The hardware supports either USB Device or USB Host - not both at the same time
#endif

#if defined(DM_BOARD_USE_TOUCH) && !defined(DM_BOARD_USE_DISPLAY)
  #error Cannot have touch controller without a display!
#endif

/******************************************************************************
 * Defines and typedefs
 *****************************************************************************/

#if defined(DM_BOARD_DISABLE_STANDARD_PRINTF)
class DevNull : public Stream {
 
public:
    DevNull(const char *name=NULL) : Stream(name) {}
 
protected:
    virtual int _getc()      {return 0;}
    virtual int _putc(int c) {return c;}
};
 
static DevNull null("null");
#endif

/*
 * Make sure that we reserve at least this amount of RAM for future
 * expansion of the BIOS. This prevents the user from squeezing out
 * the last drop of available RAM in his application.
 */
#define BIOS_RESERVED_CHUNK  0x1000
#define BIOS_MAX_SIZE        0x100000
#ifndef MAX
  #define MAX(__a, __b) (((__a)>(__b))?(__a):(__b))
#endif

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

/******************************************************************************
 * Private Functions
 *****************************************************************************/

DMBoard::DMBoard() : 
    _initialized(false),
    _conf(NULL), _confSize(0),
#if defined(DM_BOARD_USE_MCI_FS)
    _mcifs("mci", P4_16),
#endif
#if defined(DM_BOARD_USE_QSPI_FS)
    _qspifs("qspi"),
#endif
    _buzzer(P1_5),
    _button(p23),
    _led1(LED1),
    _led2(LED2),
    _led3(LED3),
    _led4(LED4)
{
}

DMBoard::~DMBoard()
{
  if (_conf != NULL) {
    free(_conf);
    _conf = NULL;
    _confSize = 0;
  }
}

#if defined(DM_BOARD_USE_DISPLAY)
DMBoard::BoardError DMBoard::readDisplayConfiguration(uint8_t** data, uint32_t* size)
{
  BoardError err = Ok;
  BiosEEPROM eeprom;
  file_header_t fh;

  if (_conf != NULL) {
    *data = _conf;
    *size = _confSize;
    return Ok;
  }      
  do {
    if (!eeprom.read(0, (char*)&fh, sizeof(file_header_t))) {
      err = BiosStorageError;
      break;
    }
    
    if (fh.magic != BIOS_MAGIC) {
      err = BiosInvalidError;
      break;
    }
    
    if (fh.version != BIOS_VER) {
      err = BiosVersionError;
      break;
    }
    
    if ((fh.headerSize + fh.size) > BIOS_MAX_SIZE) {
      err = BiosInvalidError;
      break;
    }
    
    _confSize = fh.headerSize + fh.size;
    _conf = (uint8_t*)malloc(MAX(_confSize,BIOS_RESERVED_CHUNK));
    if (_conf == NULL) {
      _confSize = 0;
      err = MemoryError;
      break;
    }
    
    if (!eeprom.read(0, (char*)_conf, _confSize)) {
      err = BiosStorageError;
      break;
    }
    
    uint32_t crc = crc_Buffer((uint32_t*)(&_conf[fh.headerSize]), fh.size/4);
    if (crc != fh.crc) {
      err = BiosInvalidError;
      break;
    }
    
    // Bios header has been verified and seems ok
    *data = _conf;
    *size = _confSize;
    err = Ok;
  } while (false);
  
  if (err != Ok) {
    if (_conf != NULL) {
      free(_conf);
      _conf = NULL;
      _confSize = 0;
    }
  }

  return err;
}
#endif

/******************************************************************************
 * Public Functions
 *****************************************************************************/

DMBoard::BoardError DMBoard::init()
{
  BoardError err = Ok;
  if (!_initialized) {
    do {
      // Turn off the buzzer
      _buzzer.period_ms(1);
      _buzzer = 0;
      
      // Make sure the button is configured correctly
      _button.mode(PullUp);
    
      // Turn off all LEDs
      _led1 = 1;
      _led2 = 1;
      _led3 = 0;
      _led4 = 0;
        
      // Make sure that the logger is always initialized even if
      // other initialization tasks fail
      _logger.init();
        
#if defined(DM_BOARD_ENABLE_MEASSURING_PINS)
      _INTERNAL_INIT_MEAS();
#endif        

#if defined(DM_BOARD_DISABLE_STANDARD_PRINTF)
      // Kill all ouput of calls to printf() so that there is no
      // simultaneous calls into the non-thread-safe standard libraries.
      // User code should use the RtosLogger anyway.
      freopen("/null", "w", stdout);
#endif

#if defined(DM_BOARD_USE_QSPI) || defined(DM_BOARD_USE_QSPI_FS)
      if (SPIFI::instance().init() != SPIFI::Ok) {
        err = SpifiError;
        break;
      }
#endif
      
#if defined(DM_BOARD_USE_DISPLAY)
      if (BiosDisplayAndTouch::instance().initDisplay() != Display::DisplayError_Ok) {
        err = DisplayError;
        break;
      }
#endif
      
#if defined(DM_BOARD_USE_TOUCH)
      if (BiosDisplayAndTouch::instance().initTouchController() != TouchPanel::TouchError_Ok) {
        err = TouchError;
        break;
      }
#endif
      
      _initialized = true;
    } while(0);
  }
  return err;
}

void DMBoard::setLED(Leds led, bool on)
{
  switch(led) {
    case Led1:
      _led1 = (on ? 0 : 1);
      break;
    case Led2:
      _led2 = (on ? 0 : 1);
      break;
    case Led3:
      _led3 = (on ? 1 : 0);
      break;
    case Led4:
      _led4 = (on ? 1 : 0);
      break;
  }
}

void DMBoard::buzzer(int frequency, int duration_ms)
{
  if (frequency <= 0) {
    _buzzer = 0;
  } else {
    _buzzer.period_us(1000000/frequency);
    _buzzer = 0.5;
  }
  if (duration_ms > 0) {
    Thread::wait(duration_ms);
    _buzzer = 0;
  }
}

bool DMBoard::buttonPressed()
{ 
  return _button.read() == 0;
}

#if defined(DM_BOARD_USE_DISPLAY)
  TouchPanel* DMBoard::touchPanel()
  {
    if (BiosDisplayAndTouch::instance().isTouchSupported()) {
      return &BiosDisplayAndTouch::instance();
    }
    return NULL;
  }
#endif

#if defined(DM_BOARD_USE_DISPLAY)
  Display* DMBoard::display()
  {
    return &BiosDisplayAndTouch::instance();
  }
#endif