Subdirectory provided by Embedded Artists

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

Dependents:   lpc4088_displaymodule_hello_world_Sept_2018

Fork of DMSupport by Embedded Artists

DMBoard.cpp

Committer:
embeddedartists
Date:
2014-12-19
Revision:
13:2c60e28503f8
Parent:
10:1ac4b213f0f7
Child:
17:4ea2509445ac

File content as of revision 13:2c60e28503f8:

/*
 *  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 "InternalEEPROM.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

/******************************************************************************
 * 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;
  }
}

DMBoard::BoardError DMBoard::readConfiguration()
{
  if (_conf == NULL) {
    InternalEEPROM mem;
    mem.init();
    
    _confSize = mem.memorySize();
    _conf = (uint8_t*)malloc(_confSize);
    if (_conf == NULL) {
      _confSize = 0;
      return MemoryError;
    }
    mem.read(0, 0, _conf, _confSize);
    mem.powerDown();
  }
#if 0  
  uint8_t* p = buff;
  _logger.printf("\n-------\nBEFORE:\n-------\n");
  for (int i = 0; i < 63; i++) {
    for (int j = 0; j < 4; j++) {
      _logger.printf("0x%04x  %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
        i,
        p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
        p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
      p += 16;
    }
    _logger.printf("\n");
  }
  
  // find first non-zero page and write to that
  for (int page = 0; page < mem.numPages(); page++) {
    bool zeroPage = true;
    for (int i = 0; i < mem.pageSize(); i++) {
      if (buff[i + page*mem.pageSize()] != 0) {
        zeroPage = false;
        break;
      }
    }
    if (zeroPage) {
      _logger.printf("Will fill page 0x%04x (%d) with 0x00..0x3f\n", page, page);
      p = buff;
      for (int i = 0; i < mem.pageSize(); i++) {
        *p++ = i;
      }
      mem.write(page, 0, buff, mem.pageSize());
      memset(buff, 0, mem.memorySize());
      mem.read(0, 0, buff, mem.memorySize());
      p = buff;
      _logger.printf("\n-------\nAFTER:\n-------\n");
      for (int i = 0; i < 63; i++) {
        for (int j = 0; j < 4; j++) {
          _logger.printf("0x%04x  %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
            i,
            p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
            p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
          p += 16;
        }
        _logger.printf("\n");
      }
      break;
    }
  }  
#endif
  return Ok;
}

#if defined(DM_BOARD_USE_DISPLAY)
DMBoard::BoardError DMBoard::readDisplayConfiguration(uint8_t** data, uint32_t* size)
{
  BoardError err = readConfiguration();
  do {
    if (err != Ok) {
      break;
    }
    
    file_header_t* fh = (file_header_t*)_conf;
    if (fh->magic != BIOS_MAGIC) {
      err = BiosInvalidError;
      break;
    }
    
    if (fh->version != BIOS_VER) {
      err = BiosVersionError;
      break;
    }
    
    if ((fh->headerSize + fh->size) > _confSize) {
      err = BiosInvalidError;
      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 = fh->headerSize + fh->size;
    err = Ok;
  } while (false);

  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
      
      readConfiguration();
      
#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