Interference current stimulation program with kaji-lab ES device.

Dependencies:   mbed SerialInputReactionHandler AMPulseTrain SwArr16MOSFET StrCommandHandler KajiLabES

subroutines.cpp

Committer:
aktk
Date:
2020-02-03
Revision:
5:779d799b5c83
Parent:
4:8d73aaba879f

File content as of revision 5:779d799b5c83:

#include "subroutines.h"

#include "KajiLabES.h"
#include "AMPulseTrain.h"

#include "SwArr16MOSFET.h"

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

Serial pc(USBTX, USBRX, 921600); // tx, rx
Ticker ticker;
KajiLabES   stimulator;
static int const nofch = 5;
SwArr16MOSFET swBrd(nofch, p14, p13, p12, p11, p10);

void callback_PulseEdge(bool arg_pulsestate, PulseTrain*, AMSignal*);
uint16_t callback_AMSignalExpression (PulseTrain*, AMSignal* arg_SignalModel);
AMPulseTrain ampt (
    new PulseTrain(20000, 1.0, 100000),
    new AMSignal(50, 200)
);
static float const AMPLE_MAX_mA = 15.0;

StrCommandHandler command_handler;
SerialInputReactionHandler reactor;

static const int g_sample_size_imp = 100;
uint16_t g_retval[g_sample_size_imp];

static int g_ch = 1;
void * setch1(){g_ch = 1; return NULL;}
void * setch2(){g_ch = 2; return NULL;}
void * setch3(){g_ch = 3; return NULL;}
void * setch4(){g_ch = 4; return NULL;}
int signalvalue = 0;
int prevvalue = 0;

/// Wrapper to be attached to PulseTrain's Callback as pulse rising
void callback_PulseEdge(bool arg_pulsestate, AMPulseTrain* arg_ampt)
{
    //static int ch = 0;
    static int itr_sample = 0;
    prevvalue = signalvalue;
    signalvalue = arg_ampt->Signal->getAMSinalValue();
    if(prevvalue > 0&& signalvalue==0) pauseLoop();
    

    g_retval[itr_sample] = stimulator.DAAD(
                               signalvalue * arg_pulsestate
                           );
                           
    if(signalvalue > 0) {
        swBrd.setTwin(g_ch, nofch);
        //swBrd.setTwin(ch + 1, ((ch + nofch/2) % nofch) + 1);
        //swBrd.setTwin(ch + 1, ((ch + nofch/2 - 1) % nofch) + 1);
        itr_sample = (itr_sample + 1) % g_sample_size_imp;
    } else {
        swBrd.allGround();
    }
    #if 0
    do {
        ch = (ch + 1) % nofch;
    } while (
        //false
        ch + 1 >= 3
        //&&
        //ch + 1 == 1
        //||
        //ch + 1 >= 3
    );
    #endif
    //if (ch+1 == 2) ch = 6 -1;
    //if (ch+1 == 6) ch = 2 -1;
    //if (ch+1 == 5) ch = 2 - 1;
    //if (ch+1 == 6) ch = 1 - 1;


}

uint16_t callback_AMSignalExpression (AMPulseTrain* arg_ampt)
{
    static int itr = -1;
    uint16_t ph = (itr < arg_ampt->getPWidth_pPulse_Signal())
                  ? arg_ampt->Signal->getAmplitude_u16()
                  : 0;

    itr = (itr + 1) % arg_ampt->getPeriod_pPulse_Signal();
    return ph;
}

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

    NVIC_SetPriority(TIMER3_IRQn, 255);

    //void init_commands(void)
    {
        ampt.attachCallback_asPulseEdge(callback_PulseEdge);
        ampt.attachAMSignalExpression(callback_AMSignalExpression);
        command_handler.map("1",    &setch1);
        command_handler.map("2",    &setch2);
        command_handler.map("3",    &setch3);
        command_handler.map("4",    &setch4);
        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();
    wait(.1);
    myled2 = 1;
}




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(
        callback(&ampt, &AMPulseTrain::incrementClock),
        ampt.getClockperiod_us()
    );
    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 = ampt.Signal->getAmplitude_uf();
    if(lampl < 0.95)
        lampl += 0.05;
    else
        lampl = 1.0;
    ampt.Signal->setAmplitude(lampl);
    printStatus();
    return NULL;
}



void * decreaseCurrent(void)
{
    float lampl = ampt.Signal->getAmplitude_uf();
    if(0.05 <= lampl )
        lampl -= 0.05;
    else
        lampl = 0;
    ampt.Signal->setAmplitude(lampl);
    printStatus();
    return NULL;
}



void * increaseFrequency(void)
{
    uint32_t lfreq = ampt.Carrier->getFrequency();
    if(lfreq < ampt.Carrier->FREQ_MAX - 100)
        lfreq += 100;
    else
        lfreq  = ampt.Carrier->FREQ_MAX;
    ampt.setFrequency_Carrier(lfreq);
    printf("%d\n", ampt.getClockperiod_us());
    if(pstate == MAIN_ROUTINE)
        ticker.attach_us(
            callback(&ampt, &AMPulseTrain::incrementClock),
            ampt.getClockperiod_us()
        );
    printStatus();
    return NULL;
}



void * decreaseFrequency(void)
{
    uint32_t lfreq = ampt.Carrier->getFrequency();
    if(200 <= lfreq )
        lfreq -= 100;
    else
        lfreq = 100;
    ampt.setFrequency_Carrier(lfreq);
    if(pstate == MAIN_ROUTINE)
        ticker.attach_us(
            callback(&ampt, &AMPulseTrain::incrementClock),
            ampt.getClockperiod_us()
        );
    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 = AMPLE_MAX_mA * ampt.Signal->getAmplitude_uf();

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

    //  set values
    if( lampl < 0.0 || AMPLE_MAX_mA < lampl) lampl = AMPLE_MAX_mA * ampt.Signal->getAmplitude_uf();
    ampt.Signal->setAmplitude((float)(lampl / AMPLE_MAX_mA));

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

void * SetFrequency(char const * const arg_digits)
{
    uint32_t lfreq = ampt.Carrier->getFrequency();

    if (scanValue(arg_digits, &lfreq));

    if( lfreq < 500 || ampt.Carrier->FREQ_MAX < lfreq) lfreq = ampt.Carrier->getFrequency();
    ampt.Carrier->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:\n"
        "    ---\n"
        "    v: set all paramater by arbitrary value\n"
        "    ---\n"
        "    UP:     Amplitude + 5% of Max I(mA)\n"
        "    Down:   Amplitude - 5% of Max I(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)
{
    unsigned int l_max = 0, l_min = 0, l_mean = 0;
    for (int i = 0; i < g_sample_size_imp; i++) {
        l_mean += g_retval[i];
        if (l_max < g_retval[i]) l_max = g_retval[i];
        if (l_min > g_retval[i]) l_min = g_retval[i];
    }
    l_mean /= g_sample_size_imp;
    pc.printf(
        "Signal Amplitude:   %2.2f (MAX %2.2f)"
        "Carrier Frequency:  %06d  \n"
        "Z(min, mean, max)=(%d, %d, %d)\n"
        , AMPLE_MAX_mA * ampt.Signal->getAmplitude_uf()
        , AMPLE_MAX_mA
        , ampt.Carrier->getFrequency()
        , l_min, l_mean, l_max);
    return NULL;
}