This program shows how to use the MODSERIAL library by Andy Kirkham to do canonical input processing. This allows you to enter and edit a command line (in the same way that you do in DOS or Linux) without tying up your main routine.

Dependencies:   mbed

main.cpp

Committer:
paulg
Date:
2011-04-21
Revision:
0:b77c715e027c

File content as of revision 0:b77c715e027c:

/* Test of canonical input processing using MODSERIAL library by Andy Kirkham.
 *
 * The RX callback feature is used to echo input and perform basic line editing.
 * This happens outside of the main routine which is free to do other things.
 *
 * Backspace removes previous character from buffer and updates terminal.
 * Delete flushes the buffer and updates terminal.
 * CR or LF causes an "end of line" flag to be set.
 * Other characters are put into the buffer and echoed on terminal.
 */

#define DATE "21 Apr 2011"
#define VERSION "1.00"
 
#include "mbed.h"
#include "MODSERIAL.h"

void serial_command_handler(void);
void flashes3(void);
void flashes4(void);
void rxCallback(MODSERIAL_IRQ_INFO *info);

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

MODSERIAL pc(USBTX, USBRX);

bool eol_flag = false;
char buf[100];

int main() {

    pc.printf("%c[2J", 0x1B);    //VT100 erase screen
    pc.printf("%c[H", 0x1B);     //VT100 home
    pc.printf("MODSERIAL test program (Version %s, %s)\n", VERSION, DATE);

    //set up serial rx callback
    pc.baud(9600);
    pc.attach(&rxCallback, MODSERIAL::RxIrq);

    pc.printf("> ");
    while(1) {      //main loop
        if (eol_flag) {     //service command line
            serial_command_handler();
            eol_flag = false;
        }
        //service an "event"
        flashes3();
        //and service another one
        flashes4();
    }
}

// Serial command handler

void serial_command_handler(void) {
    char *cp;
    
    led2 = 1;       //light LED2 to show command processing
    pc.printf("\n");
    //read input into buffer (gets() does not seem to be supported!)
    cp = buf;
    while (pc.readable() ) {
        *cp++ = pc.getc();
    }
    --cp;           //move back to CR or LF
    *cp = '\0';     //terminate buffer
    //print buffer length and contents in both ASCII and hex
    int i = (int) (cp - buf);
    pc.printf("cnt = %d, buf = <%s>\n", i, buf);
    cp = buf;
    while (i--) {
        pc.printf("%02x ", (int) *cp++);
    }
    pc.printf("\n> ");
    led2 = 0;
}

// Dummy event handlers - flash LED3 or LED4 for a few seconds

void flashes3(void) {
    for (int i = 4; i > 0; i--) {
        led3 = 1;
        wait(0.25);
        led3 = 0;
        wait(0.25);
    }
}

void flashes4(void) {
    for (int i = 3; i > 0; i--) {
        led4 = 1;
        wait(0.4);
        led4 = 0;
        wait(0.4);
    }
}

// Rx callback routine

void rxCallback(MODSERIAL_IRQ_INFO *info) {

    MODSERIAL *pc = info->serial;

    led1 = !led1;   //toggle LED1 to show char received
    char c = pc->rxGetLastChar();
    if (c == 0x7f) {    //flush input buffer and erase line on terminal
        int i = pc->rxBufferGetCount();
        pc->rxBufferFlush();
        while (i--) {
            pc->putc(0x8);
            pc->putc(' ');
            pc->putc(0x8);
        }
    }
    else if (c == 0x8) { //remove last char from buffer and erase on terminal
        //remove the BS and the previous char
        info->rxDiscardLastChar();
        info->rxDiscardLastChar();
        pc->putc(0x8);
        pc->putc(' ');
        pc->putc(0x8);
    }
    else if (c == '\n' || c == '\r') { //end of line, signal command available
        eol_flag = true;
    }
    else {   //echo char on terminal
        pc->putc(c);
    }
}

// END