Interference current stimulation program with kaji-lab ES device.

Dependencies:   mbed SerialInputReactionHandler AMPulseTrain SwArr16MOSFET StrCommandHandler KajiLabES

subroutines.cpp

Committer:
aktk
Date:
2019-11-27
Revision:
2:5cb68cc8ecaa
Child:
3:ef730909a664

File content as of revision 2:5cb68cc8ecaa:

#include "subroutines.h"

#include "KajiLabES.h"

#include "SwArr16MOSFET.h"

#include "DSinGenerator.h"
#include "StrCommandHandler.h"
#include "SerialInputReactionHandler.h"

Serial pc(USBTX, USBRX, 921600); // tx, rx
Ticker ticker;
KajiLabES   stimulator;
SwArr16MOSFET swBrd(4, p11, p12, p13, p14, p10);
DSinGenerator singen ( 
    /*Initial Amplitude*/ 0,
    /*Initial Frequency*/ 4000,
    /*Discret.-fineness*/ 16
);
StrCommandHandler command_handler;
SerialInputReactionHandler reactor; //todo: implement function replace sigbind.cpp/h


void init (void)
{
    //void init_Hardware(void)
    {
        stimulator.init();
        swBrd.allHiZ();
        swBrd.setPol(SwArr16MOSFET::Cathodic);
        swBrd.setTwin(1,2);
    }
    myled1 = 1;

    NVIC_SetPriority(TIMER3_IRQn, 1);

    //void init_commands(void)
    {
        command_handler.map("a",    &switchState);
        command_handler.map("E",    &terminateLoop);
        command_handler.map("S",    &startLoop);
        command_handler.map("P",    &pauseLoop);
        command_handler.map("v",    &beginParamsSetting);
        command_handler.map("p",    &printStatus);
        command_handler.map(StrCommandHandler::ARROW_UP,    &increaseCurrent);
        command_handler.map(StrCommandHandler::ARROW_DOWN,  &decreaseCurrent);
        command_handler.map(StrCommandHandler::ARROW_RIGHT, &increaseFrequency);
        command_handler.map(StrCommandHandler::ARROW_LEFT,  &decreaseFrequency);
        reactor.attach(callback(&command_handler, &StrCommandHandler::exe));
        reactor.attach_PostProc(&calleddefault);
        reactor.startReception(&pc, SerialInputReactionHandler::KB_SINGLE_INPUT);
    }
    printKBManual();
    printDSinSamples();
    wait(.1);
    myled2 = 1;
}



void loop()
{
    static int ph = 0;
    static int ph_sign = 0;

    myled4 = 1;

    ph = singen.getValue_p16m16();
    if(ph > 0) {
        ph_sign = 1;
    }
    //  when ph is negaive, make it positive
    else if (ph < 0) {
        ph = -ph;
        ph_sign = -1;
    }
    stimulator.DAAD(ph);

    if(ph == 0) {
        if (ph_sign > 0)
            swBrd.setTwin(1, 4);

        else if (ph_sign < 0)
            swBrd.setTwin(4, 1);
        else;
        ph_sign = 0;
    }

    myled4 = 0;
}



void calleddefault(char const * const arg_command, void * arg_errorcode)
{
    int errorcode = *(int*)arg_errorcode;
    if (errorcode != 0xFFFFFFFC) return;
    printKBManual();
    pc.printf("Sent data was: %d(%c)(%s)\n", arg_command[0], arg_command[0], arg_command);
}


void * switchState()
{
    if (pstate == MAIN_ROUTINE)
        pauseLoop();
    else if (pstate == WAIT_A_CERTAIN_KEY) {
        startLoop();

    }
    return NULL;
}


void * startLoop(void)
{
    if (pstate != WAIT_A_CERTAIN_KEY) return NULL;

    ticker.attach_us(loop, singen.getPulseWidth());
    pstate = MAIN_ROUTINE;
    pc.printf("start\n");
    return NULL;
}



void * pauseLoop(void)
{
    if (pstate != MAIN_ROUTINE) return NULL;

    stimulator.DAAD(0);
    ticker.detach();
    pstate = WAIT_A_CERTAIN_KEY;
    pc.printf("stop\n");
    return NULL;
}



void * terminateLoop(void)
{
    stimulator.DAAD(0);
    ticker.detach();
    pstate = TERMINATED;
    pc.puts("TERMINATED");
    return NULL;
}



void * increaseCurrent(void)
{
    float lampl = singen.getAmplitude();
    if(lampl < singen.ampl_max - 0.5)
        lampl += 0.5;
    else
        lampl = singen.ampl_max;
    singen.setAmplitude(lampl);
    printStatus();
    return NULL;
}



void * decreaseCurrent(void)
{
    float lampl = singen.getAmplitude();
    if(1 <= lampl )
        lampl -= 0.5;
    else
        lampl = 0;
    singen.setAmplitude(lampl);
    printStatus();
    return NULL;
}



void * increaseFrequency(void)
{
    uint16_t lfreq = singen.getFrequency();
    if(lfreq < singen.freq_max - 10)
        lfreq += 10;
    else
        lfreq  = 5000;
    singen.setFrequency(lfreq);
    ticker.attach_us(loop, singen.getPulseWidth());
    printStatus();
    return NULL;
}



void * decreaseFrequency(void)
{
    uint16_t lfreq = singen.getFrequency();
    if(20 <= lfreq )
        lfreq -= 10;
    else
        lfreq = 10;
    singen.setFrequency(lfreq);
    ticker.attach_us(loop, singen.getPulseWidth());
    printStatus();
    return NULL;
}



template <typename T>
bool scanValue(char const * const arg_digits, T * const arg_dest)
{
    int l_len = 0;
    int l_digit = 0;
    int l_value = 0;
    bool l_isfloat = false;

    while (arg_digits[l_len] != '\0') {

        if (l_len > 50) {
            pc.puts("\nerror: too long number of digits\n");
            return false;
        }

        if ('0' <= arg_digits[l_len] && arg_digits[l_len] <= '9')
            l_digit = arg_digits[l_len] - '0';
        else if(arg_digits[l_len] != '.')
            if(l_isfloat)
                return false;
            else
                l_isfloat = true;
        else return false;

        if(l_isfloat) l_digit /= 10;
        else l_value *= 10;

        l_value += l_digit;
        l_len++;
    }

    *arg_dest = static_cast<T>(l_value);
    return true;
}




void * beginParamsSetting(void)
{
    pauseLoop();
    reactor.changeMode(SerialInputReactionHandler::KB_TILL_ENTER);

    pc.puts("---\n");
    pc.printf("set amplitude:");
    reactor.attach(SetAmplitude);
    return NULL;
}

void * SetAmplitude(char const * const arg_digits)
{
    float lampl = singen.getAmplitude();

    //  read values
    if (scanValue(arg_digits, &lampl));

    //  set values
    if( lampl <   0 || singen.ampl_max < lampl) lampl = singen.getAmplitude();
    singen.setAmplitude(lampl);

    pc.puts("===\n");
    pc.printf("set frequency:");
    reactor.attach(SetFrequency);
    return NULL;
}

void * SetFrequency(char const * const arg_digits)
{
    uint16_t lfreq = singen.getFrequency();

    if (scanValue(arg_digits, &lfreq));

    if( lfreq < 500 || singen.freq_max < lfreq) lfreq = singen.getFrequency();
    singen.setFrequency(lfreq);

    pc.puts("...\n");
    printStatus();
    endParamsSetting();
    return NULL;
}

void * endParamsSetting(void)
{
    reactor.changeMode(SerialInputReactionHandler::KB_SINGLE_INPUT);
    reactor.attach(callback(&command_handler, &StrCommandHandler::exe));
    startLoop();
    return NULL;
}



void * printKBManual(void)
{
    pc.puts(
        "\n"
        "keybind are following:\n"
        "    ---\n"
        "    v: set all paramater by arbitrary value\n"
        "    ---\n"
        "    UP:     Amplitude + 1(mA)\n"
        "    Down:   Amplitude - 1(mA)\n"
        "    Right:  Frequency +10(Hz)\n"
        "    Left:   Frequency -10(Hz)\n"
        "    ---\n"
        "    p:  print wave parameter\n"
        "    ---\n"
        "    a:  Start or Pause main loop\n"
        "    S:  Start or Resume Stimulation\n"
        "    P:  Pause Stimulation\n"
        "    E(shift+a): terminate the loop\n"
        "\n");
    return NULL;
}

void * printStatus(void)
{
    pc.printf(
        "Amplitude:  %2.3f  "
        "Frequency:  %05d  "
        "Pulse Width:%05d\n"
        , singen.getAmplitude(), singen.getFrequency(), singen.getPulseWidth());
    return NULL;
}

void * printDSinSamples(void)
{
    pc.printf("resolution of sin: %d\n", singen.resolution_ofsin);

    float dsin[singen.resolution_ofsin];
    singen.getValueofSamplePoints(dsin);
    for ( int i = 0; i < singen.resolution_ofsin; i++ )
        pc.printf("sin[%02d]: %2.2f\n", i, dsin[i]);

    return NULL;
}