Topic: tech dcc pc src prev next

tech dcc pc src > program_loco.c

#include "program_loco.h"

#include "dcc.h"
#include "lcd.h"
#include "menu.h"
#include "packet.h"
#include "pins.h"

#define SIZEOF_ARRAY(a) (sizeof(a)/sizeof(a[0]))

typedef unsigned char index_type;

bool cv_valid(cv_type cv)
{
    return (cv > 0 && cv <= 1024);
}

void program_loco()
{
    static const char *items[] = {
        "Address",
        "Acceleration",
        "Deceleration",
        "VStart",
        "VHigh",
        "Custom (Paged)",
        "Custom (Direct)",
        "Hard Reset"
    };

    index_type index = 0;

    void button(void *v, const switch_type sw)
    {
        index_type *index_ = (index_type*)v;

        if(HERMES_SWITCH_NO(sw) == HERMES_SWITCH_BACK)
            Menu_Finish();

        if(HERMES_SWITCH_NO(sw) == HERMES_RE_ACW)
        {
            *index_ = (unsigned char)((unsigned char)(SIZEOF_ARRAY(items) + *index_ - 1) % SIZEOF_ARRAY(items));
            Menu_Redraw();
        }

        if(HERMES_SWITCH_NO(sw) == HERMES_RE_CW)
        {
            *index_ = (unsigned char)((unsigned char)(*index_ + 1) % SIZEOF_ARRAY(items));
            Menu_Redraw();
        }

        if(HERMES_SWITCH_NO(sw) == HERMES_RE_SEL)
        {
            // Program a CV using the mode appropriate mode for the CV number.
            // Return true if the CV was written, false if there was a problem
            // (e.g. the operation was cancelled by the user).
            bool program_cv(cv_type cv, const char *name)
            {
                int value = Menu_GetInt(name, -1, HERMES_MAX_CV_VALUE);
                if(value != -1)
                {
                    DCC_AutoCvWrite(cv, (unsigned char)value);
                    return true;
                }
                return false;
            }

            switch(*index_)
            {
                case 0:
                    // Program address.
                    if(program_cv(1, items[0]))
                        Menu_Notice("Address written");
                    break;
                case 1:
                    // Program acceleration.
                    if(program_cv(3, items[1]))
                        Menu_Notice("Accel. written");
                    break;
                case 2:
                    // Program deceleration.
                    if(program_cv(4, items[2]))
                        Menu_Notice("Decel. written");
                    break;
                case 3:
                    // Program VStart.
                    if(program_cv(2, items[3]))
                        Menu_Notice("VStart written");
                    break;
                case 4:
                    // Program VHigh.
                    if(program_cv(5, items[4]))
                        Menu_Notice("VHigh written");
                    break;
                case 5:
                    {
                    // Custom (paged).
                    int cv = Menu_GetInt("CV No.", -1, HERMES_MAX_CV_NO);
                    if(!cv_valid(cv))
                    {
                        Menu_Notice("Invalid CV");
                        break;
                    }
                    if(cv == -1)
                        break;
                    int value = Menu_GetInt("Value", -1, HERMES_MAX_CV_VALUE);
                    if(value > 255)
                    {
                        Menu_Notice("Invalid value");
                        break;
                    }
                    if(value == -1)
                        break;
                    // Write the CV.
                    DCC_PagedCvWrite((cv_type)cv, (unsigned char)value);
                    Menu_Notice("CV Written");
                    }
                    break;
                case 6:
                    {
                    // Custom (direct).
                    int cv = Menu_GetInt("CV No.", -1, HERMES_MAX_CV_NO);
                    if(!cv_valid(cv))
                    {
                        Menu_Notice("Invalid CV");
                        break;
                    }
                    if(cv == -1)
                        break;
                    int value = Menu_GetInt("Value", -1, HERMES_MAX_CV_VALUE);
                    if(value > 255)
                    {
                        Menu_Notice("Invalid value");
                        break;
                    }
                    if(value == -1)
                        break;
                    // Write the CV.
                    DCC_DirectCvWrite((cv_type)cv, (unsigned char)value);
                    Menu_Notice("CV Written");
                    }
                    break;
                case 7:
                    // Hard reset
                    if(Menu_Question("Reset?"))
                        DCC_HardReset();
                    break;
            }
        }
    }

    void draw(void *v)
    {
        index_type *index_ = (index_type*)v;
        Menu_DrawList("Loco", items[*index_], *index_, SIZEOF_ARRAY(items));
    }

    Menu_EventLoop(button, draw, 0, &index);
}