![](/media/cache/group/download_IjbieK2.png.50x50_q85.png)
demo new haven display
Dependencies: LCD Menu ButtonCtrl TimeManagement EventLog AddressMap emic2
ESCM 2000 Control and Display application provides interface for the LPC1768 processor boards with the ECSM 2000 system.
This application implements SW interface : - RX 485 Receive from physical system - RX 485 Interface to send toECOM / ESCM board - CAN Interface to send to ECOM / ESCM board - 4x40 LCD with menu controls - RTC configuration -EMIC2 Sound Card - GPIO Extender to push buttons etc
main.cpp
- Committer:
- foxbrianr
- Date:
- 2019-09-17
- Revision:
- 7:0244f1a26545
- Parent:
- 6:010ceb99f7b0
- Child:
- 8:f15a5358883c
File content as of revision 7:0244f1a26545:
/************************************************************************** * @file main.cpp * @brief Main function for ESCM Control System * Application * @version: V1.0 * @date: 9/17/2019 * * @note * Copyright (C) 2019 E3 Design. All rights reserved. * * @par * E3 Designers LLC is supplying this software for use with Cortex-M3 LPC1768 * processor based microcontroller for the ESCM 2000 Monitor and Display. * * * @par * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. * ******************************************************************************/ #include "mbed.h" #include "rtos.h" #include "stats_report.h" #include "math.h" #include "LCD.h" #include "ButtonController.h" #include "ESCMControlApp.h" #include "Menu.h" #include "EditTimeMenu.h" #include "EditAddressMenu.h" #include "DisplayCodesMenu.h" #include "FactoryResetMenu.h" #define SLEEP_TIME 500 // (msec) #define PRINT_AFTER_N_LOOPS 10 DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); SystemReport *sys_state; /*------------------------------------------------------------------- * define displays *-------------------------------------------------------------------*/ Serial pc(USBTX, USBRX); // tx, rx #define MAX_THREADS 6 Thread * threads [MAX_THREADS]; /*------------------------------------------------------------------- * define displays *-------------------------------------------------------------------*/ LCD lcd; /*------------------------------------------------------------------- * define displays *-------------------------------------------------------------------*/ Menu rootMenu ("root menu"); EditTimeMenu editTime ("Edit Time"); EditAddressMenu editAddress ("Edit Addresses"); DisplayCodesMenu showEvents ("Display Events" ); FactoryResetMenu factoryReset("Factory Reset" ); /*------------------------------------------------------------------- * define display escmBtnController *-------------------------------------------------------------------*/ ButtonController escmBtnController; /*------------------------------------------------------------------- * define application *-------------------------------------------------------------------*/ ESCMControlApp escmController; static int dataRxCnt = 0; /*------------------------------------------------------------------- * define led toggles for diagnostics *-------------------------------------------------------------------*/ void toggleLed1(){ led1 = !led1;} void toggleLed2(){ led2 = !led2;} void toggleLed3(){ led3 = !led3;} void toggleLed4(){ led4 = !led4;} static volatile uint64_t idle; #if DEBUG OsTaskPerfData_t g_perfData; void InitPerfData() { for (int i=0;i<MAX_THREADS;i++) { g_perfData.task[i].counter = 0; g_perfData.task[i].deltaTime = 0; g_perfData.task[i].deltaTimeMax = 0; g_perfData.task[i].deltaTimeMin = 0xFFFFFFFFu; g_perfData.task[i].deltaTimeAve = 0; g_perfData.task[i].cycleTimeMax = 0; g_perfData.task[i].cycleTimeMin = 0xFFFFFFFFu; g_perfData.task[i].cycleTimeAve = 0; g_perfData.task[i].timeStamp = 0; g_perfData.task[i].lastTimeStamp = 0; } } void UpdatePerfDataStart(OsPerfData_t *data) { #if 1 if (data != NULL) { uint64_t now = Kernel::get_ms_count(); data->counter++; data->timeStamp = now; data->cycleTime = data->timeStamp - data->lastTimeStamp; if (data->cycleTime > data->cycleTimeMax ) data->cycleTimeMax = data->cycleTime; if (data->cycleTime < data->cycleTimeMin ) data->cycleTimeMin = data->cycleTime; data->cycleTimeAve = (data->cycleTime - data->cycleTimeAve)/2; data->lastTimeStamp = data->timeStamp; } #endif } void UpdatePerfDataStop(OsPerfData_t *data) { #if 1 if (data != NULL) { uint64_t now = Kernel::get_ms_count(); data->deltaTime = now - (data->timeStamp); if (data->deltaTime > data->deltaTimeMax ) data->deltaTimeMax = data->deltaTime; if (data->deltaTime < data->deltaTimeMin ) data->deltaTimeMin = data->deltaTime; data->deltaTimeAve = (data->deltaTime + data->deltaTimeAve)/2; data->timeStamp = now; } #endif } void ShowPerfData (OsPerfData_t *data) { } #endif /*********************************************************************** * Thread to read GPIO and handle events ***********************************************************************/ void ReadGPIOExtender(void) { uint8_t code = 0; Timer t; pc.printf("Starting escmBtnController task\n" ); toggleLed4(); while (true) { t.reset(); t.start(); escmBtnController.update(); toggleLed4(); ThisThread::sleep_for(50); t.stop(); //printf("<1> %d ms\n", t.read_ms()); } } /*********************************************************************** * Thread to read GPIO and handle events ***********************************************************************/ void ESCMController_Update(void) { pc.printf("Starting escmIOController task\n" ); while(1) { #if DEBUG UpdatePerfDataStart(&g_perfData.task[0]); #endif escmController.update(); #if DEBUG UpdatePerfDataStop(&g_perfData.task[0]); #endif ThisThread::sleep_for(200); } } /*********************************************************************** * Update LCD Display Thread ***********************************************************************/ void UpdateDisplay(void) { static int counter = 0; pc.printf("Starting escmDisplay task\n" ); lcd.init(); lcd.cls(); lcd.locate(0,0); lcd.printf ("Initializing System.."); toggleLed3(); Menu *activeMenu = Menu::setCurrentMenu (&showEvents); while (true) { #if DEBUG UpdatePerfDataStart(&g_perfData.task[2]); #endif #if AUTO_REFESH_ENABLED // note force a refresh if (counter==0) { activeMenu->update_needed = 1; counter = 100; } counter--; #endif if (activeMenu == NULL){ lcd.printf ("ERROR: Invalid Menu Selected.."); continue; } else { if ( activeMenu != Menu::getCurrentMenu() ) { activeMenu = Menu::getCurrentMenu() ; activeMenu->update_needed = 1; } else { escmBtnController.processCmdQueue(activeMenu); } activeMenu->DrawDisplay(&lcd); } toggleLed3(); #if DEBUG UpdatePerfDataStop(&g_perfData.task[2]); #endif ThisThread::sleep_for(10); } } /*********************************************************************** * Play sounds * TODO: should have its own queue. ***********************************************************************/ void PlaySound(void) // const *name) { led2 = 1; pc.printf("Starting escmSound task\n" ); while (1) { #if DEBUG UpdatePerfDataStart(&g_perfData.task[3]); #endif toggleLed2(); escmController.processSoundQueue(); #if DEBUG UpdatePerfDataStop(&g_perfData.task[3]); #endif Thread::wait(200); } } #if DEBUG /*********************************************************************** * Dumps thread stats ***********************************************************************/ void PrintSystemStats (void) { uint32_t frameCount = 0; while(1) { frameCount++; if ((0 == frameCount) || (PRINT_AFTER_N_LOOPS == frameCount)) { // Following the main thread wait, report on the current system status sys_state->report_state(); #if 1 pc.printf("IDLE=%d", idle); pc.printf("\nThread | cntr | T | Cycle Time | Delta Time "); pc.printf("\n-------------------------------------------------------------------- "); pc.printf("\n"); for(int i = 0; i<MAX_THREADS; i++) { pc.printf("%-8d | %-5d | %-5d | %-5d | %-5d | %-5d | %-5d | %-5d | %-5d \n\r", i , g_perfData.task[i].counter , g_perfData.task[i].timeStamp , g_perfData.task[i].cycleTimeAve , g_perfData.task[i].cycleTimeMax , g_perfData.task[i].cycleTimeMin , g_perfData.task[i].deltaTimeAve , g_perfData.task[i].deltaTimeMax , g_perfData.task[i].deltaTimeMin ); } #else pc.printf("\nThread | size | free | used | max | "); pc.printf("\n------------------------------------ "); pc.printf("\n"); for(int i = 0; i<MAX_THREADS; i++) { pc.printf("\n%-8d | %4d | %4d | %4d | %4d |", i, threads[i]->stack_size(), threads[i]->free_stack(), threads[i]->used_stack(), threads[i]->max_stack() ) ; } #endif pc.printf("\n------------------------------------ "); pc.printf("\n"); escmEventLog.save(); frameCount = 0; } Thread::wait(200); } } #endif #if TEST /*********************************************************************** * Handle Terminal Prompts * TODO: should have its own queue. ***********************************************************************/ void TerminalPrompt(void) // const *name) { pc.printf("Starting escmTerm task\n" ); while (1) { int c; pc.printf("\n>>"); pc.scanf("%d", &c); /* echo */ pc.printf("\n%0d",c); if ( c >= 0 && c < 99) { ESCMControlApp::postEvent((uint16_t)c,99); } else if (c==555) { addressMap.reset(); } else if (c==666) { escmEventLog.reset(); } else if (c==999) { pc.printf("\nThread | size | free | used | max | "); pc.printf("\n------------------------------------ "); for(int i = 0; i<MAX_THREADS; i++) { pc.printf("\n%-8d | %4d | %4d | %4d | %4d |", i, threads[i]->stack_size(), threads[i]->free_stack(), threads[i]->used_stack(), threads[i]->max_stack() ) ; } } else { } } } /*********************************************************************** * process incoming messages from rx485 serial (ISR) ***********************************************************************/ void rx485Message() { #if 1 dataRxCnt++; #else // Note: you need to actually read from the serial to clear the RX interrupt int dataRxBuffer[4]; int value = rs485port1.getc(); if (value){ dataRxBuffer[dataRxCnt++]=value; if(dataRxCnt==4) { cur_address = 10*(dataRxBuffer[0] -0x30) + (dataRxBuffer[1] -0x30); memset(dataRxBuffer,0,sizeof(dataRxBuffer)); dataRxCnt=0; } else { // do nothing } } #endif } #endif /*********************************************************************** * Main Loop ***********************************************************************/ void backgroundTask(void) { idle++; } /*********************************************************************** * Main Loop ***********************************************************************/ int main() { pc.printf("\n\r"); pc.printf("=====================================\n\r"); pc.printf("= ESCM 2000 =\n\r"); pc.printf("= %s %s =\n\r", __DATE__ , __TIME__); pc.printf("= v0.01 =\n\r"); pc.printf("=====================================\n\r"); sys_state = new SystemReport( SLEEP_TIME * PRINT_AFTER_N_LOOPS /* Loop delay time in ms */); Kernel::attach_idle_hook(&backgroundTask); led1=1; led1=!led1; #if DEBUG InitPerfData(); #endif lcd.init(); lcd.cls(); lcd.locate(0,0); lcd.printf ("Initializing System.."); // test speaker escmController.say("Welcome ESCM"); // initialize main controller escmController.init(); //escmRs485_Input.attach ( &rx485Message ); //addressMap.display(&pc); toggleLed1(); //Add any selections rootMenu.add(&showEvents); rootMenu.add(&editTime); rootMenu.add(&editAddress); rootMenu.add(&factoryReset); Menu::setCurrentMenu (&rootMenu); toggleLed1(); threads[0] = new Thread(osPriorityNormal5, 0x300 ); threads[1] = new Thread(osPriorityNormal4, 0x500 ); threads[2] = new Thread(osPriorityNormal3, 0x1000 ); threads[3] = new Thread(osPriorityNormal2, 0x400 ); #if DEBUG threads[4] = new Thread(osPriorityNormal1, 0x200 ); #endif #if TEST threads[5] = new Thread(osPriorityLow, 0x100 ); #endif threads[0]->start(ESCMController_Update); threads[1]->start(ReadGPIOExtender); threads[2]->start(UpdateDisplay); threads[3]->start(PlaySound); #if DEBUG //threads[4]->start(PrintSystemStats); #endif #if TEST threads[5]->start(TerminalPrompt); #endif while(1) { toggleLed1(); ThisThread::sleep_for(500); } }