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 );
    }
    
}