Demo for Embedded World 2015.

Dependencies:   DMBasicGUI DMSupport

Demo running on several LPC4088 Display Modules on the Embedded World 2015 exhibition.

Information

To run the demo first drag-n-drop the to_sync.fs3 file to the MBED drive and then drag-n-drop the demo itself. This way both the file system and software are up to date.

This is what the launcher will look like:

/media/uploads/embeddedartists/ew2015_cap_000.png /media/uploads/embeddedartists/ew2015_cap_002.png /media/uploads/embeddedartists/ew2015_cap_003.png /media/uploads/embeddedartists/ew2015_cap_004.png /media/uploads/embeddedartists/ew2015_cap_005.png /media/uploads/embeddedartists/ew2015_cap_006.png

main.cpp

Committer:
embeddedartists
Date:
2019-11-05
Revision:
1:1a01ef434a72
Parent:
0:6bd24cbb88a1

File content as of revision 1:1a01ef434a72:

/******************************************************************************
 * Includes
 *****************************************************************************/
 
#include "mbed.h"
#include "mbed_interface.h"
#include "rtos.h"
#include "EthernetInterface.h"
#include "HTTPServer.h"
#include "USBHostMSD.h"
#include "USBHostMouse.h"
#include "USBHostKeyboard.h"

#include "DMBoard.h"

#include "AppLauncherSpecial.h"
#include "meas.h"

#include "AppNetworkSettings.h"
#include "AppStatus.h"
#include "AppTouchCalibration.h"
#include "AppColorPicker.h"
#include "AppImageViewer.h"
#include "AppSlideShow.h"
#include "AppRTCSettings.h"
#include "AppUSBStatus.h"
#include "AppDraw.h"
#include "image_data.h"


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

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

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

EthernetInterface eth;
bool ethInitialized = false;
bool ethUsingDHCP = true;
bool haveUSBMSD = false;

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

void aliveTask(void)
{
  DMBoard* board = &DMBoard::instance();
    
  while(true)
  {
    board->setLED(DMBoard::Led4, false);
    board->setLED(DMBoard::Led1, true);
    ThisThread::sleep_for(300);
    board->setLED(DMBoard::Led1, false);
    board->setLED(DMBoard::Led2, true);
    ThisThread::sleep_for(300);
    board->setLED(DMBoard::Led2, false);
    board->setLED(DMBoard::Led3, true);
    ThisThread::sleep_for(300);
    board->setLED(DMBoard::Led3, false);
    board->setLED(DMBoard::Led4, true);
    ThisThread::sleep_for(300);
  }
}

#if defined(DM_BOARD_USE_DISPLAY)

typedef enum {
    ColorPickerApp,
    ImageViewerApp,
    SlideshowApp,
    SettingsApp, 
    StatusApp, 
    TouchTestApp,
    RtcApp,
    USBStatusApp,
    DrawingApp,
    CalibrationApp =  AppLauncherSpecial::CalibrationApp,
    Placeholder,
} myapps_t;

static App* launchApp(uint32_t id)
{
  App* a = NULL;
  switch ((myapps_t)id) {
      case CalibrationApp:
          a = new AppTouchCalibration();
          break;
      case SettingsApp:
          a = new AppNetworkSettings();
          break;
      case ColorPickerApp:
          a = new AppColorPicker();
          break;
      case ImageViewerApp:
          a = new AppImageViewer();
          break;
      case SlideshowApp:
          a = new AppSlideShow("/qspi/slides.txt", "/qspi", 0, 0);
          break;
      case StatusApp:
          a = new AppStatus();
          break;
      case RtcApp:
          a = new AppRTCSettings();
          break;
      case USBStatusApp:
          a = new AppUSBStatus();
          break;
      case DrawingApp:
          a = new AppDraw();
          break;
      default:
          break;
  }
  return a;
}

#define SWIM_TASK_PREFIX  "[SWIM] "
void swimTask(void)
{
  RtosLog* log = DMBoard::instance().logger();
    
  log->printf(SWIM_TASK_PREFIX"swimTask started\n");
  
  AppLauncherSpecial launcher;
    
    
  if (launcher.setup()) {
    launcher.addImageButton(SettingsApp, "Network", 0x2d5c, img_super_mono_3d_93, img_size_super_mono_3d_93);
    //launcher.addImageButton(Placeholder, "Logo Splash", 0x2d5c, img_super_mono_3d_part2_83, img_size_super_mono_3d_part2_83);
    launcher.addImageButton(DrawingApp, "Drawing", 0x2d5c, img_super_mono_3d_22, img_size_super_mono_3d_22);
    launcher.addImageButton(SlideshowApp, "Slideshow", 0x2d5c, img_super_mono_3d_87, img_size_super_mono_3d_87);
    launcher.addImageButton(ColorPickerApp, "Color Picker", 0x2d5c, img_super_mono_3d_part2_19, img_size_super_mono_3d_part2_19);
    launcher.addImageButton(ImageViewerApp, "Image Viewer", 0x2d5c, img_super_mono_3d_48, img_size_super_mono_3d_48);
    launcher.addImageButton(StatusApp, "About", 0x2d5c, img_super_mono_3d_part2_68, img_size_super_mono_3d_part2_68);
    launcher.addImageButton(USBStatusApp, "USB Status", 0x2d5c, img_super_mono_3d_57, img_size_super_mono_3d_57);
    launcher.addImageButton(RtcApp, "Clock", 0x2d5c, img_super_mono_3d_02, img_size_super_mono_3d_02);
      
    launcher.setAppCreatorFunc(launchApp);
    log->printf(SWIM_TASK_PREFIX"Starting menu system\n");
    launcher.runToCompletion();
    launcher.teardown();
  } else {
    log->printf(SWIM_TASK_PREFIX"Failed to prepare menu system\n");
  }
  
  // Should never end up here  
  mbed_die();
}

#endif //DM_BOARD_USE_DISPLAY


#define NET_TASK_PREFIX  "[NET] "

void netTask(void)
{
  RtosLog* log = DMBoard::instance().logger();
  log->printf(NET_TASK_PREFIX"EthernetInterface Setting up...\r\n");
  nsapi_error_t net_err = eth.connect();

  if (net_err != NSAPI_ERROR_OK) {
    log->printf(NET_TASK_PREFIX"EthernetInterface connect Error %d\r\n", net_err);
  }
  else {
  
    ethInitialized = true;
    ethUsingDHCP = true;
  
    log->printf(NET_TASK_PREFIX"IP Address is %s\r\n", eth.get_ip_address());
    log->printf(NET_TASK_PREFIX"NetMask is %s\r\n", eth.get_netmask());
    log->printf(NET_TASK_PREFIX"Gateway Address is %s\r\n", eth.get_gateway());
    log->printf(NET_TASK_PREFIX"Ethernet Setup OK\r\n");

    HTTPServerAddHandler<SimpleHandler>("/hello"); //Default handler
    FSHandler::mount("/mci", "/");
    HTTPServerAddHandler<FSHandler>("/");
    HTTPServerStart(80);
  }
}

static volatile int8_t mouse_button, mouse_x, mouse_y, mouse_z;
static uint16_t cursor_x=0, cursor_y=0;
void mouseEvent(uint8_t buttons, int8_t x, int8_t y, int8_t z)
{
    mouse_button = buttons;
    mouse_x = x;
    mouse_y = y;
    mouse_z = z;
    
    if (x < 0) {
        if (cursor_x > -x) {
            cursor_x += x;
        } else {
            cursor_x = 0;
        }
    } else {
        if ((cursor_x + x) >= 480) {
            cursor_x = 479;
        } else {
            cursor_x += x;
        }
    }
    y = y/8;
    if (y < 0) {
        if (cursor_y > -y) {
            cursor_y += y;
        } else {
            cursor_y = 0;
        }
    } else {
        if ((cursor_y + y) >= 272) {
            cursor_y = 271;
        } else {
            cursor_y += y;
        }
    }
    
    //Chip_LCD_Cursor_SetPos(LPC_LCD, cursor_x, cursor_y);
    LPC_LCD->CRSR_XY = (cursor_x & 0x3FF) | ((cursor_y & 0x3FF) << 16);
}

#define LCD_CURSOR_32x32 0
#define LCD_CURSOR_64x64 1
#define CURSOR_SIZE  LCD_CURSOR_32x32
#define CURSOR_H_SIZE 32
#define CURSOR_V_SIZE 32
#define CURSOR_NUM   0    
#define CURSOR_H_OFS (10)
#define CURSOR_V_OFS (6)

const unsigned char __attribute__ ((aligned(4))) Cursor[(CURSOR_H_SIZE / 4) * CURSOR_V_SIZE] =
{
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xFA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFF, 0xEA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA,
	0xAA, 0xAB, 0xFB, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAA, 0xBF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAA, 0xBF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAF, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
};

void prepareCursor(bool enable) {
	//Chip_LCD_Cursor_Disable(LPC_LCD, 0);
    LPC_LCD->CRSR_CTRL = (CURSOR_NUM << 4);
    
    if (enable) {
        //Chip_LCD_Cursor_Config(LPC_LCD, LCD_CURSOR_32x32, true);
        LPC_LCD->CRSR_CFG = ((true ? 1 : 0) << 1) | CURSOR_SIZE;
        
        //Chip_LCD_Cursor_WriteImage(LPC_LCD, 0, (void *) Cursor);
        {
            int i, j;
            uint32_t *fifoptr, *crsr_ptr = (uint32_t *) Cursor;

            /* Check if Cursor Size was configured as 32x32 or 64x64*/
            if (CURSOR_SIZE == LCD_CURSOR_32x32) {
                i = CURSOR_NUM * 64;
                j = i + 64;
            }
            else {
                i = 0;
                j = 256;
            }
            fifoptr = (uint32_t *) &(LPC_LCD->CRSR_IMG[0]);

            /* Copy Cursor Image content to FIFO */
            for (; i < j; i++) {

                *fifoptr = *crsr_ptr;
                crsr_ptr++;
                fifoptr++;
            }
        }
        
        //Chip_LCD_Cursor_SetClip(LPC_LCD, CURSOR_H_OFS, CURSOR_V_OFS);
        LPC_LCD->CRSR_CLIP = (CURSOR_H_OFS & 0x3F) | ((CURSOR_V_OFS & 0x3F) << 8);
        
        //Chip_LCD_Cursor_SetPos(LPC_LCD, cursor_x, cursor_y);
        
        //Chip_LCD_Cursor_Enable(LPC_LCD, 0);
        LPC_LCD->CRSR_CTRL = (CURSOR_NUM << 4) | 1;
    }
}


#define CIRCBUFF_SIZE 256
static volatile uint8_t circbuff[CIRCBUFF_SIZE];
static volatile uint32_t circbuff_read = 0;
static uint32_t circbuff_write = 0;
void keyEvent(uint8_t key)
{
    circbuff[circbuff_write%CIRCBUFF_SIZE] = key;
    circbuff_write++;
}

bool msdConnected = false;
bool keyboardConnected = false;
bool mouseConnected = false;

#define USB_TASK_PREFIX  "[USB] "
#define USB_CONNECTION_EVENT   (1<<4)
void usbTask(void)
{
  USBHostMSD* msd = new USBHostMSD("usb");
  USBHostKeyboard* keyboard = new USBHostKeyboard();
  USBHostMouse* mouse = new USBHostMouse();
  USBHost* host = USBHost::getHostInst();
  EventFlags connectionEvent;
  host->signalOnConnections(&connectionEvent, USB_CONNECTION_EVENT);

  RtosLog* log = DMBoard::instance().logger();
    
  log->printf(USB_TASK_PREFIX"usbTask started\n");
    
  prepareCursor(false);

  while (true) {
    // wait for connect/disconnect message from USBHost
    connectionEvent.wait_any(USB_CONNECTION_EVENT);
    log->printf(USB_TASK_PREFIX"got USB event\n");
      
    if (msd->connected()) {
      if (!msdConnected) {
        msdConnected = true;
        haveUSBMSD = true;
        log->printf(USB_TASK_PREFIX"USB MassStorage Device - Connected\n");
      }
    } else {
      if (msdConnected) {
        msdConnected = false;
        haveUSBMSD = false;
        log->printf(USB_TASK_PREFIX"USB MassStorage Device - Ejected\n");
      }
      
      if (msd->connect()) {
        msdConnected = true;
        haveUSBMSD = true;
        log->printf(USB_TASK_PREFIX"USB MassStorage Device - Connected\n");
      }      
    }
    
    if (keyboard->connected()) {
      if (!keyboardConnected) {
        keyboardConnected = true;
        log->printf(USB_TASK_PREFIX"USB Keyboard - Connected\n");
        keyboard->attach(keyEvent);
      }
    } else {
      if (keyboardConnected) {
        keyboardConnected = false;
        log->printf(USB_TASK_PREFIX"USB Keyboard - Ejected\n");
      }
      if (keyboard->connect()) {
        keyboardConnected = true;
        log->printf(USB_TASK_PREFIX"USB Keyboard - Connected\n");
        keyboard->attach(keyEvent);
      }
    }
    
    if (mouse->connected()) {
      if (!mouseConnected) {
        mouseConnected = true;
        log->printf(USB_TASK_PREFIX"USB Mouse - Connected\n");
        mouse->attachEvent(mouseEvent);
        prepareCursor(true);
      }
    } else {
      if (mouseConnected) {
        prepareCursor(false);
        mouseConnected = false;
        log->printf(USB_TASK_PREFIX"USB Mouse - Ejected\n");
      }
      if (mouse->connect()) {
        mouseConnected = true;
        log->printf(USB_TASK_PREFIX"USB Mouse - Connected\n");
        mouse->attachEvent(mouseEvent);
        prepareCursor(true);
      }
    }
  }
}



/******************************************************************************
 * Main function
 *****************************************************************************/
int main()
{
  DMBoard::BoardError err;
  DMBoard* board = &DMBoard::instance();
  RtosLog* log = board->logger();
  err = board->init();
  if (err != DMBoard::Ok) {
    log->printf("Failed to initialize the board, got error %d\r\n", err);
    log->printf("\nTERMINATING\n");
    ThisThread::sleep_for(2000); // allow RtosLog to flush messages
    mbed_die();
  }
  
  board->buzzer(440,50);
  ThisThread::sleep_for(30);
  board->buzzer(660,50);
  ThisThread::sleep_for(30);
  board->buzzer(440,50);
  
  log->printf("\n\n---\nDemo for Embedded World 2015\nBuilt: " __DATE__ " at " __TIME__ "\n\n");
  
 
  Thread tAlive;
  tAlive.start(aliveTask);
#if defined(DM_BOARD_USE_DISPLAY)
  Thread tSwim(osPriorityNormal, 8192);
  tSwim.start(swimTask);
#endif  
  Thread tNetwork(osPriorityNormal, 8192);
  tNetwork.start(netTask);
  Thread tUSBHandler(osPriorityNormal, 8192);
  tUSBHandler.start(usbTask);
  
  while(1) { 
    // Wait forever (in 1h increments) to prevent the tAlive, tSwim,
    // tNetwork and tUSBHandler thread from being garbage collected.
    ThisThread::sleep_for(3600*1000);
  }
}