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
ESCMControlApp.cpp
- Committer:
- foxbrianr
- Date:
- 2019-09-12
- Revision:
- 5:65f21c0b6b79
- Parent:
- 3:ecaf9963341b
- Child:
- 6:010ceb99f7b0
File content as of revision 5:65f21c0b6b79:
#include "mbed.h" #include "ESCMControlApp.h" #include "SPI_MX25R.h" // --------------------------------------------------------------------- // External IO for the ESCM Control Board // // --------------------------------------------------------------------- Serial escmRs485_Input(p9, p10, 9600); //tx,rx,baud DigitalOut escmRs485_Mode (p11); //Transmit = 1, Receive = 0 Serial microCommRs485_Tx(p13, p14, 9600); //tx,rx,baud DigitalOut microCommRs485_Mode (p12); //Transmit = 1, Receive = 0 CAN microCommCanItf (p30, p29, 50000); // rx,tx DigitalOut microCommCan_Mode (p25); //Silent Mode = 1, Normal = 0 // --------------------------------------------------------------------- // External IO for the Speaker / EMIC2 board // --------------------------------------------------------------------- emic2 speaker(p28, p27); //serial RX,TX pins to emic // --------------------------------------------------------------------- // External MEMORY for the FAULT AND ADDRESS MAPS // --------------------------------------------------------------------- SPI_MX25R spi_memory (p5, p6, p7, p8); // --------------------------------------------------------------------- Mutex sound_mutex; ESCM_EventLog escmEventLog; AddressMap addressMap; RealTimeClock rtc; /* for incoming messages */ CircularBuffer<event_t, 64> message_queue; /* for button presses */ CircularBuffer<event_t, 64> event_queue; /* for playing sound */ CircularBuffer<playbackMessage_t, 10> playback_queue; void setCurrentTime (char* timeBuf) { time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); int hours = timeinfo->tm_hour; int mins = timeinfo->tm_min; int secs = timeinfo->tm_sec; int years = timeinfo->tm_year + 1900; int months = timeinfo->tm_mon + 1 ; int days = timeinfo->tm_mday; sprintf(timeBuf,"%0d/%0d/%04d %02d:%02d:%02d", months,days,years,hours,mins,secs ); printf("NEW %s\n", timeBuf); } void ESCMControlApp::init() { // set on power, should not change escmRs485_Mode = 0; // Receive microCommRs485_Mode = 1; // Transmit microCommCan_Mode = 0; // Normal mode (turn on CNA transeiver) //escmRs485_Input.attach(&rx485Message); escmEventLog.init(); addressMap.init(); if (escmEventLog.size()>0) { cur_address = escmEventLog.index(0)->address; } } void ESCMControlApp::update(void) { static int new_address = -1; static int rxCount = 0; static int counter = 0; char value; bool update_needed = 0; #if 1 if(escmRs485_Input.readable() ) { //rx485Message(); int dataRxBuffer[4]; while ( value = escmRs485_Input.getc() ) { dataRxBuffer[rxCount++]=value; if(rxCount==4) { // read 4 characters if (dataRxBuffer[2] == 0xd && dataRxBuffer[3] == 0xa) { new_address = 10*(dataRxBuffer[0] -0x30) + (dataRxBuffer[1] -0x30); printf("ADDR=%d\n",new_address); update_needed = 1; dataRxCnt++; break; } } } // reset cnt; rxCount = 0; memset(dataRxBuffer,0,sizeof(dataRxBuffer)); } #endif if (update_needed) { if (new_address >= 0 && new_address < 100 ) { cur_address = new_address; printf("ADDR=%d\n",cur_address); postEvent(cur_address,0); counter = 0; new_address = -1; } else { printf("ERROR: INVALID_ADDR=%d\n",new_address); } } if (cur_address >= 0 && cur_address < 100 ) { if (counter == 0 ) { tx485Message(cur_address); //send on rs485 #if 1 txCanMessage501(cur_address);//send on can txCanMessage502(cur_address); #else txCanMessage580(cur_address); #endif counter = 5; //send .5 sec dataTxCnt++; //printf("Current_Address is %d \n\r", cur_address ); } } else { printf("ERROR: INVALID_ADDR=%d\n",cur_address); } counter--; } /*************************************************************************/ void ESCMControlApp::processMessageQueue () { event_t e; if (message_queue.empty()) return; while (!message_queue.empty()) { message_queue.pop(e); tx485Message(e.event); Thread::wait(100); } } /*************************************************************************/ void ESCMControlApp::processSoundQueue () { playbackMessage_t e; if (playback_queue.empty()) return; while (!playback_queue.empty()) { playback_queue.pop(e); speaker.speakf("S"); //Speak command starts with "S" speaker.speakf(e.message); // Send the desired string to convert to speech speaker.speakf("\r"); //marks end of speak command speaker.ready(); //ready waits for speech to finish from last command with a ":" response } } /*************************************************************************/ void ESCMControlApp::say (char *format, ...) { playbackMessage_t e; char buffer[128]; va_list args; va_start(args, format); vsprintf(e.message,format,args); #if 0 speaker.speakf("S");//Speak command starts with "S" speaker.speakf(e.message); speaker.speakf("\r"); speaker.ready(); #else if (!playback_queue.full()) { playback_queue.push(e); } else { printf("Sound Queue Full\n"); } #endif va_end(args); } /*************************************************************************/ void ESCMControlApp::postEvent (uint16_t address) { event_t e; e.event = address; if (!message_queue.full()) { message_queue.push(e); } else { printf("Message Queue Full\n"); } } /************************************************************************* * The following function is called with a new event is received to * update the related parts *************************************************************************/ void ESCMControlApp::postEvent (uint16_t address, uint16_t source) { if ( address >= 0 && address < 100 ) { escmEventLog.add(address, source); //escmEventLog.save(); ESCMControlApp::refresh_display(); #if 0 ESCMControlApp::say("Unit %d is open", address); #else ESCMControlApp::say("%s is open", addressMap.getDescription(address)); #endif } else { //ignore it } } void ESCMControlApp::refresh_display(void) { printf("$"); Menu::getCurrentMenu()->update_needed=1; } /************************************************************************* * The following function get time *************************************************************************/ void ESCMControlApp::getTime(char *timeBuf) { time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); int hours = timeinfo->tm_hour; int mins = timeinfo->tm_min; int secs = timeinfo->tm_sec; int years = timeinfo->tm_year + 1900; int months = timeinfo->tm_mon + 1 ; int days = timeinfo->tm_mday; sprintf(timeBuf,"%0d/%0d/%04d %02d:%02d:%02d\0", months,days,years,hours,mins,secs ); printf("TIME: %s\n", timeBuf); } /************************************************************************* * The following functdion sets time which set the RTC *************************************************************************/ void ESCMControlApp::setTime(int hours, int mins, int sec, int months, int days, int years ) { struct tm t; t.tm_hour = hours; t.tm_min = mins; t.tm_sec = 0; t.tm_year = years - 1900; t.tm_mon = months - 1; t.tm_mday = days; // set the time set_time(mktime(&t)); } /************************************************************************* * The following information is from the MicroComm_gen_input.doc * * Message is always 12 bytes with Check Sum * Byte 1 : 40 * Byte 2 : Indictator * arrival_dn_arrow :1, bit 1 * arrival_up_arrow :1, bit 0 * * Byte 3 : Scan_slot. * Byte 4 : Message_number. * Byte 5 : Indictor * traveling dn arrow :1, bit 1 * traveling up arrow :1, bit 0 * * Byte 6 : ASCII floor char, msb * Byte 7 : ASCII floor char, * Byte 8 : ASCII floor char, lsb * Note: floor ASCII range is 0x30 through 0x5a (‘0’ – ‘Z’). * 0x3a through 0x40 are special characters with * 0x3b being the space or blank character(semicolon) * 0x3d is normally displayed as a minus character. * * * Byte 9 : ASCII msg char, msb * Byte 10 : ASCII msg char, * Byte 11 : ASCII msg char, lsb * Note: message ASCII range is 0x30 through 0x5b (‘0’ – ‘[’). * 0x3a through 0x40 are special characters with * 0x3b being the space or blank character(semicolon) * 0x5d is sent when there is no message (instead of spaces). * * * Byte 12 : checksum * * note messages are sent .5 - 1 sec using 485 Bus *************************************************************************/ void ESCMControlApp::tx485Message(int address) { int sum =0; char dataTxBuffer[12]; if (address >= 0 && address < 100 ) { sum += dataTxBuffer[0] = 0x40; // fixed value sum += dataTxBuffer[1] = 0x01; sum += dataTxBuffer[2] = address; // floor number sum += dataTxBuffer[3] = 0x0; sum += dataTxBuffer[4] = 0x0; //--- sum += dataTxBuffer[5] = 0x0; sum += dataTxBuffer[6] = (0x30 + address / 10); sum += dataTxBuffer[7] = (0x30 + address % 10); //--- sum += dataTxBuffer[8] = 0x0; sum += dataTxBuffer[9] = 'F'; sum += dataTxBuffer[10] = 'X'; sum += dataTxBuffer[11] = (char)(~sum +1); for(int i= 0; i<12; i++) { microCommRs485_Tx.putc(dataTxBuffer[i]); } } else { printf ("Error: invalid address %d",address ); } } /************************************************************************* * The following information is from the ElevCANtoMC * for CAN Message 0x501 * * Byte 1 * Front arrows * Bit 0 – Front arrival arrow up * Bit 1 – Front arrival arrow down * Bit 2 – Play Strobe * Bit 3-5 – Reserved * Bit 6 – Fire Warning Lamp * Byte 2 * Floor Number. A floor number of 0 is not a valid. * Byte 3 * Priority message number * Byte 4 * Travel and rear arrows * Bit 0 – Travel arrow up * Bit 1 – Travel arrow down * Bit 2 – unused * Bit 3 – Passing Chime * Bit 4 – Message Level Low Bit * Bit 5 – Message Level High Bit * Bit 6 – Rear arrival arrow up * Bit 7 – Rear arrival arrow down * Byte 5-8 * Reserved * * * note messages are to come .5 - 1 sec using 50K CAN Bus ********************************************************************/ void ESCMControlApp::txCanMessage501 (int address) { static int counterTx = 0; char data[8]; if (address >= 0 && address < 100 ) { data[0] = (counterTx%2)?0x1:0x2; // toggle arrow data[1] = (uint8_t)address; // numerical floor # data[2] = 0x0; data[3] = (counterTx%2)?0x1:0x2; // toggle travel arrow data[4] = 0x0; data[5] = 0x0; data[6] = 0x0; data[7] = 0x0; if(microCommCanItf.write(CANMessage(0x501, data, 8))) { //printf("Message 501:(%d) sent via CAN: %d\n\r",counterTx, address); counterTx++; } else { //printf("Message 501: Reset\n\r"); microCommCanItf.reset(); } } else { printf ("Error: invalid address %d",address ); } } /************************************************************************* * The following information is from the ElevCANtoMC * for CAN Message 0x502 * Byte 1 * Floor marking character (leftmost) * Byte 2 * Floor marking character * Byte 3 * Floor marking character (rightmost) * Byte 4 * Message marking character (leftmost) * Byte 5 * Message marking character * Byte 6 * Message marking character (rightmost) * Byte 7 * Lantern Position (ThyssenKrupp) * Byte 8 * Unused * * note messages are to come .5 - 1 sec using 50K CAN Bus ********************************************************************/ void ESCMControlApp::txCanMessage502 (int address) { static int counterTx = 0; char data[8]; if (address >= 0 && address < 100 ) { data[0] = 0x0; data[1] = (0x30 + address / 10); // assumes address is 0-9 range data[2] = (0x30 + address % 10); // assumes address is 0-9 range data[3] = 0x0; data[4] = (0x30 + address / 10); // assumes address is 0-9 range data[5] = (0x30 + address % 10); // assumes address is 0-9 range data[6] = 'F'; data[7] = 0x0; if(microCommCanItf.write(CANMessage(0x502, data, 8))) { printf("Message 502: (%d) sent via CAN: %d\n\r",counterTx, address); counterTx++; } else { //printf("Message 502: Reset\n\r"); microCommCanItf.reset(); } } else { printf ("Error: invalid address %d",address ); } } /************************************************************************* * The following information is from the ElevCANtoMC * for CAN Message 0x580 * Byte 1 * Floor Number. A floor number of 0 is not a valid floor position and should only be used when translating from a source that does not provide numeric position data. * Byte 2 * Floor marking character (leftmost) [the MICRO COMM® converter does not support this character] * Byte 3 * Floor marking character * Byte 4 * Floor marking character * Byte 5 * Floor marking character (rightmost) * Byte 6 * Bit 0 – Front in-car arrow up * Bit 1 – Front in-car arrow down * Bit 2 – Rear in-car arrow up * Bit 3 – Rear in-car arrow down * Bit 4 – Travel arrow up * Bit 5 – Travel arrow down * Bit 6 – Passing chime * Bit 7 – Unused * Byte 7 * Hall Arrows * Bit 0 – Front arrival arrow up * Bit 1 – Front arrival arrow down * Bit 2 – Front gong up * Bit 3 – Front gong down * Bit 4 – Rear arrival arrow up * Bit 5 – Rear arrival arrow down * Bit 6 – Rear gong up * Bit 7 – Rear gong down * Byte 8 * Target display number (This is not used by most controllers. * Just leave this set to 0xFF for basic controller operation). * If this is used, it only applies to data located in Byte 7. * * note messages are to come .5 - 1 sec using 50K CAN Bus ********************************************************************/ void ESCMControlApp::txCanMessage580 (int address) { static int counterTx = 0; char data[8]; if (address >= 0 && address < 100 ) { data[0] = address; data[1] = 0x0; data[2] = 0x0; data[3] = (0x30 + address / 10); data[4] = (0x30 + address % 10); data[5] = (counterTx%2)?0x1:0x2; data[6] = 0x0A;//front down and gong down data[7] = 0xFF; if(microCommCanItf.write(CANMessage(0x580, data, 8))) { //printf("Message 580: (%d) sent via CAN: %d\n\r",counterTx, address); counterTx++; } else { //printf("Message 580: Reset\n\r"); microCommCanItf.reset(); } } else { printf ("Error: invalid address %d",address ); } }