fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

core/config.cpp

Committer:
gwappa
Date:
2018-12-13
Revision:
32:1416e015016c
Parent:
26:b4421d1ee57a

File content as of revision 32:1416e015016c:

#include "config.h"
#include "IO.h"

namespace config {
    
    struct HelpResponder: public CommandResponder
    {
        virtual ~HelpResponder() { }
        
        virtual bool parse(const char& c)
        {
            if (c != CMD_CHAR_HELP) {
                return false;
            }
            writeSettingsToSerial();
            return true;
        }
        
        virtual bool writeSettings() {
            return false;
        }
        
        virtual void echoback() {
            // do nothing
        }
    };
    
    HelpResponder* help_ = 0;
    
    struct CallbackHandler
    {
        char command;
        CommandResponder* responder;
        
        CallbackHandler* prev;
        CallbackHandler* next;
    
        
    private:
        
        CallbackHandler(const char& command, CommandResponder* resp):
            command(command), responder(resp), prev(0), next(0) { }
        
        static void append(CallbackHandler** list, CallbackHandler* item) {
                       
            if ((*list) == 0) {
                // no content
                (*list) = item;
                item->prev = 0;
                item->next = 0;
                
            } else {
                // search the end of the list
                CallbackHandler* current = *list;
                while(current->next != 0) {
                    current = current->next;
                }
                
                current->next = item;
                item->prev = current;
                item->next = 0;
            }
        }
        
        static void drop(CallbackHandler** head, CallbackHandler* item) {
            
            if (item == 0) {
                return;
            }
            
            if (item == *head) {
                *head = item->next;
            } else {
                item->prev->next = item->next;
            }
            if (item->next != 0) {
                item->next->prev = item->prev;
            }
            
            delete item;
        }
    
    public:
        
        static void append(CallbackHandler** list, const char& command, CommandResponder* resp) {
            append(list, new CallbackHandler(command, resp));
        }
        
        static void drop(CallbackHandler** head, const char& command) {
            CallbackHandler* current = *head;
            
            // check for `command` from the head to the tail
            while( current != 0 ){
                if (current->command == command) {
                    // drop this
                    drop(head, current);
                    return;
                }
                
                current = current->next;
            }
        }
        
        static CallbackHandler* helpCommand(const char& command) {
            return new CallbackHandler(command, help_);
        }
    };
    
    
    CallbackHandler* handlers_ = 0;
    
    void initialize_() {
        help_ = new HelpResponder();
        CallbackHandler::append(&handlers_, CMD_CHAR_HELP, help_);
    }
    
    void addCommand(const char& command, CommandResponder* resp)
    {
        if (handlers_ == 0) {
            initialize_();
        }
        CallbackHandler::append(&handlers_, command, resp);
    }
    
    void removeCommand(const char& command)
    {
        if (handlers_ == 0) {
            initialize_();
        }
        CallbackHandler::drop(&handlers_, command);
    }
    
    void handleSerial()
    {
        char in = IO::getc();
        
        if (isWhitespace(in)) {
            return;
        }
        
        CallbackHandler* current = handlers_;
        while(current != 0) {
            
            if ( current->responder->parse(in) ) {
                // the handler accepted the input character
                break;
            }
            current = current->next;
        }
        
        if (current != 0) {
            current->responder->echoback();
            
        } else {
            // no matched handler
            IO::error("%c",in);
        }
    }
    
    void writeSettingsToSerial() {
        IO::write(IO::CONFIG_HEADER);
        
        CallbackHandler* current = handlers_;
        
        while (current != 0) {
            if (current->responder->writeSettings()) {
                // some output occurred
                IO::write(STR_DELIMITER);
            }
            current = current->next;
        }
        IO::write(STR_NEWLINE);
    }
}

Action::Action(const char& command, Callback<void()> f):
    command_(command), handler_(f)
{
    config::addCommand(command_, this);
}

Action::~Action()
{
    config::removeCommand(command_);
}
    
bool Action::parse(const char& c)
{
    if (c != command_) {
        return false;
    }
    handler_();
    return true;
}
    
bool Action::writeSettings() { return false; }
    
void Action::echoback() {
    // IO::result("done");
}