fork of StateScript

Dependencies:   mbed SOMO_II

Fork of stateScript_v2 by Mattias Karlsson

mbedInterface/mbedInterface.cpp

Committer:
alustig3
Date:
2017-04-28
Revision:
10:f65649c13b5b
Parent:
9:f783bce314cd

File content as of revision 10:f65649c13b5b:

#include "mbedInterface.h"
#include "mbed.h"

//--------------------------------------------------------------
//--------------------------------------------------------------
//This section is required for all custom harware interfaces

//globals defined in hardwareInterface.cpp
extern uint32_t timeKeeper; //the master clock
uint32_t uSec_SinceLastClockInc = 0;
uint32_t uSec_SinceLastReset = 0;

extern bool resetTimer;
extern bool clockSlave;
extern bool changeToSlave;
extern bool changeToStandAlone;
extern outputStream textDisplay;

int externalIncrementMod = 1;
int externalIncrementCounter = 0;


#ifdef MBED_RF
//We are listening to an RF signal for hardware syncing----------------------------------------
//Uses DB9->RJ45 connector to map the following channels:
//1: P28    Clock Signal In
//2: P27    Data Signal In
//3: P20    FiberLED Out Signal
//4: 5V
//5: GND
//6: P6     NC
//7: P7     NC
//8: P8     NC

DigitalOut mainLED(LED1);
DigitalOut secondaryLED(LED2);

bool lightOn = false;
bool lightOn2 = false;
int pulseCounter = 0;
uint32_t lastPulse = 0;
uint32_t currentRFTime = 0;
uint32_t lastRFTime = 0;
uint32_t timeKeeperAtCurrentRFTime = 0;
uint32_t timeKeeperAtLastRFTime = 0;
int RFSyncCounter = 0;
bool RFSyncReadable = false;
bool RFSyncWritable = true;

#ifdef LPC1768
//Recieve clock signal from RF system
InterruptIn RFClock(p28);
DigitalIn RFData(p27);
#endif

#ifdef K64
InterruptIn RFClock(PTA1);
DigitalIn RFData(PTB9);
#endif


void callback_RFClock(void) {

    //if this amount of time has passed since the last pulse, we have a new timestamp
    if ((timeKeeper-lastPulse) > 4) {

        //make sure the previous timestamp was 32 pulses
        //if so, update lastRFTime
        //we only process every 100th stamp (once every 10 seconds with 10 Hz timestamps)
        if ((pulseCounter == 31) && (RFSyncCounter == 99)){
            if (RFSyncWritable) {
                lastRFTime = currentRFTime;
                timeKeeperAtLastRFTime = timeKeeperAtCurrentRFTime;
                RFSyncReadable = true;
                RFSyncWritable = false;
            }
        }

        pulseCounter = 0;
        currentRFTime = 0;
        timeKeeperAtCurrentRFTime = timeKeeper;
        RFSyncCounter = (RFSyncCounter+1)%100;


        if (lightOn) {
            mainLED = 0;
            lightOn = false;
        } else {
            mainLED = 1;
            lightOn = true;
        }
    } else {
        if (pulseCounter < 32) {
            currentRFTime = (currentRFTime | ( RFData.read() << pulseCounter));
            pulseCounter++;
        }
    }
    lastPulse = timeKeeper;
}

//------------------------------------------------------------
#endif

void externalClockIncDown() {

    //The external clock increment signal pulse has come back down.  If the pulse was long
    //enough, then we condsider it a valid pulse (the pulses should be 0.5 ms long)
    if ((clockSlave)&&(uSec_SinceLastClockInc >= 300)) {
        uSec_SinceLastClockInc = 0;
        timeKeeper++;

        //Clock resets happen upon update so we dont get a partial first ms
        if (resetTimer) {
            uSec_SinceLastReset = 0;
            timeKeeper = 0;
            resetTimer = false;
        }
    }

}

void externalResetDown() {

    //The external clock reset signal pulse has come back down.  If the pulse was long
    //enough, then we condsider it a valid pulse (the pulses should be 1 ms long)
    /*
    textDisplay << uSec_SinceLastReset;
    if ((clockSlave)&&(uSec_SinceLastReset >= 700)) {
        uSec_SinceLastReset = 0;
        timeKeeper = 1; //It has been 1ms since the reset pulse went up
        textDisplay << timeKeeper << " Clock reset\r\n";
    }*/
}

//------------------------------------------------------------------------
//------------------------------------------------------------------------

//MBED-specific stuff
//---------------------------------------------------------------------

//translate pin numbers to hardware pins

#ifdef LPC1768
PinName dInPins[NUMDIGINPORTS] = {p5,p14,p16,p17,p22,p24,p26,p30};
PinName dOutPins[NUMDIGOUTPORTS] = {p7,p15,p13,p11,p29,p25,p23,p21}; //With analog pins
PinName aInPins[NUMANINPORTS] = {p20};
PinName aOutPins[NUMANOUTPORTS] = {p18};
// SOMO II sound module  http://www.4dsystems.com.au/product/SOMO_II/
// Datasheet http://www.4dsystems.com.au/productpages/SOMO-II/downloads/SOMO-II_datasheet_R_1_2.pdf
SOMO audio(p9,p10);        //(TX,RX)
#endif

#ifdef K64
PinName dInPins[NUMDIGINPORTS]  =  {PTB2, PTB9, PTC10, PTA1, PTD1};
PinName dOutPins[NUMDIGOUTPORTS] = {PTB11, PTC14, PTC11, PTC15,  PTE24, PTD4, PTC9, PTB18, PTD0};
PinName aInPins[NUMANINPORTS] = {};
PinName aOutPins[NUMANOUTPORTS] = {};

SOMO audio(PTC17,PTC16);        //(TX,RX,Reset)
#endif


#ifdef LPC1768
//This is the callback for the MBED timer
extern "C" void TIMER0_IRQHandler (void) {
    //The function is called every 1 ms
    if((LPC_TIM0->IR & 0x01) == 0x01) {  // if MR0 interrupt, proceed
        LPC_TIM0->IR |= 1 << 0;         // Clear MR0 interrupt flag
        timeKeeper++;

        if (resetTimer) {
            timeKeeper = 0;
            resetTimer = false;
        }
    }
}
//-----------------------------------------------------------------------
#endif


MBEDSystem::MBEDSystem():
    #ifdef LPC1768
    clockResetInt(p5),
    clockExternalIncrement(p8) {
    clockResetInt.rise(this, &MBEDSystem::externalClockReset);

    #endif
    #ifdef K64
    clockResetInt(PTD4),
    clockExternalIncrement(PTD6) {
    clockResetInt.rise(callback(this, &MBEDSystem::externalClockReset));
    #endif

    clockResetInt.fall(&externalResetDown);
    clockResetInt.mode(PullDown);

    clockExternalIncrement.mode(PullDown);

    #ifdef MBED_RF
    //Karpova version-------------
    //Set up callbacks for RF clock signal
    RFClock.rise(&callback_RFClock);
    RFClock.mode(PullDown);
    #endif

    //-------------------------------

    for (int i=0; i < NUMDIGINPORTS; i++) {
        dIn[i].init(i);
    }
    for (int i=0; i < NUMDIGOUTPORTS; i++) {
        dOut[i].init(i);
    }
    for (int i=0; i < NUMANINPORTS; i++) {
        aIn[i].init(i);
    }
    for (int i=0; i < NUMANOUTPORTS; i++) {
        aOut[i].init(i);
    }



    audio.reset();

}

void MBEDSystem::timerinit() {
    #ifdef LPC1768
    //intiatiation of timer (specific to the LPC17xx chip). This is used in
    //standalone mode to increment the clock every ms.
    //----------------------------------------------------
    //LPC_SC->PCLKSEL1 &= (3 << 12); //mask
    //LPC_SC->PCLKSEL1 |= (1 << 12); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual)
    //LPC_SC->PCLKSEL0 &= (3 << 3); //mask
    //LPC_SC->PCLKSEL0 |= (1 << 3); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual)
    LPC_SC->PCONP |=1<1;            //timer0 power on


    LPC_TIM0->MR0 = 23980;        //1 msec


    //LPC_TIM0->PR  = (SystemCoreClock / 1000000); //microsecond steps
    //LPC_TIM0->MR0 = 1000;        //100 msec
    //LPC_TIM0->MR0  = (SystemCoreClock / 1000000); //microsecond steps
    LPC_TIM0->MCR = 3;              //interrupt and reset control
    //3 = Interrupt & reset timer0 on match
    //1 = Interrupt only, no reset of timer0
    NVIC_EnableIRQ(TIMER0_IRQn);    //enable timer0 interrupt
    LPC_TIM0->TCR = 1;              //enable Timer0
    //--------------------------------------------------------------
    #endif
}

void MBEDSystem::pauseInterrupts() {
    __disable_irq();
}

void MBEDSystem::resumeInterrupts() {
    __enable_irq();
}

void MBEDSystem::mainLoopToDo() {
    #ifdef MBED_RF
    //Karpova version--------------------------
    //Karpova lab RF addition. Print out time sync.
    if (RFSyncReadable) {
           /*
           ostringstream RFTimeConvert;
           RFTimeConvert << timeKeeperAtLastRFTime << " " << "RFsync " << lastRFTime << "         "; //broadcast the earliest timestamp when a change occured

           textDisplay.send(RFTimeConvert.str() + "\r\n");
           RFTimeConvert.clear();
           RFTimeConvert.seekp(0);
           */

           textDisplay << timeKeeperAtLastRFTime << " RFsync " << lastRFTime << "\r\n";

           RFSyncReadable = false;
           RFSyncWritable = true;
    }
    //------------------------------------------------------------
    #endif
}

sDigitalOut* MBEDSystem::getDigitalOutPtr(int portNum){
    if (portNum < NUMDIGOUTPORTS) {
        return &dOut[portNum];
    } else {
        return NULL;
    }
}

sDigitalIn* MBEDSystem::getDigitalInPtr(int portNum) {
    if (portNum < NUMDIGINPORTS) {
        return &dIn[portNum];
    } else {
        return NULL;
    }
}

sAnalogOut* MBEDSystem::getAnalogOutPtr(int portNum){
    if (portNum < NUMANOUTPORTS) {
        return &aOut[portNum];
    } else {
        return NULL;
    }
}

sAnalogIn* MBEDSystem::getAnalogInPtr(int portNum) {
    if (portNum < NUMANINPORTS) {
        return &aIn[portNum];
    } else {
        return NULL;
    }
}

sSound* MBEDSystem::createNewSoundAction() {
    MBEDSound *tmpSound = new MBEDSound();
    return tmpSound;
}


void MBEDSystem::externalClockReset() {

    //The pulse has gone high.  When the pulse comes down we will check to see if it was long enough to be valid.
    uSec_SinceLastReset = 0;



    if (clockSlave) {
    #ifdef LPC1768
        LPC_TIM0->TCR = 0x02;    // reset timer
    #endif
        externalIncrementCounter = 0;

        immediateClockReset();
    }

}

void MBEDSystem::setStandAloneClock() {
    clockSlave = false;
#ifdef LPC1768
    NVIC_DisableIRQ(TIMER0_IRQn); // Disable the interrupt
#endif
    timerinit(); //set up and enable interrupt
    clockExternalIncrement.rise(NULL); //remove the callback to the external interrupt
    //clockExternalIncrement.fall(NULL);
    changeToSlave = false;
    changeToStandAlone = false;
}

void MBEDSystem::setSlaveClock() {
    clockSlave = true;
#ifdef LPC1768
    NVIC_DisableIRQ(TIMER0_IRQn); // Disable the interrupt
    clockExternalIncrement.rise(this, &MBEDSystem::incrementClock);
#endif
#ifdef K64
    clockExternalIncrement.rise(callback(this, &MBEDSystem::incrementClock));
#endif

    clockSlave = true;
    changeToSlave = false;
    changeToStandAlone = false;
}

void MBEDSystem::incrementClock() {

    if (clockSlave) {
        //The pulse has gone high.  When the pulse comes down we will check to see if it was long enough to be valid.
        //uSec_SinceLastClockInc = 0;


        //The clock is incremented

        externalIncrementCounter = (externalIncrementCounter+1) % externalIncrementMod;
        if (externalIncrementCounter==0) {
            timeKeeper++;
        }

    } else {
        timeKeeper++;
    }
    //Clock resets happen upon update so we dont get a partial first ms
    /*
    if (resetTimer) {
        uSec_SinceLastReset = 0;
        timeKeeper = 0;
        resetTimer = false;
    }*/
}

//-----------------------------------------------------

MBEDSound::MBEDSound() {

}

void MBEDSound::execute() {
    if (reset) {
        audio.reset();
    } else if (!play) {
        audio.stopTrack();
    } else {
        if (volume > -1) {
            audio.volume(volume);
        } else if (volumePtr != NULL) {
            audio.volume(*volumePtr);
        }

        if (fileNameExists) {
            //audio.playTracks();
            audio.stopTrack();
            audio.playTrackName(fileName);
        }
    }
}

//-----------------------------------------------------
MBEDAnalogOut::MBEDAnalogOut() {

}

void MBEDAnalogOut::init(int pin) {
    if (pin < NUMANOUTPORTS) {
        outpin = new AnalogOut(aOutPins[pin]);
        pinExists = true;
    }
}

int MBEDAnalogOut::read() {

    if (pinExists) {
        return outpin->read()*3300.0; //read value is a float between 0 and 1.0 (max voltage).  Convert to mV integer value.
    } else {
        return 0;
    }

}

void MBEDAnalogOut::write(int value) {

    if (pinExists) {

        outpin->write((float)value / 3300.0);//should be a float input (percentage).  We convert from integer mV value.

    }


}
//--------------------------------------------------------

MBEDAnalogIn::MBEDAnalogIn() {

}

void MBEDAnalogIn::init(int pin) {

    if (pin < NUMANINPORTS) {
        inpin = new AnalogIn(aInPins[pin]);
        pinExists = true;
    }

}

int MBEDAnalogIn::read() {

    if (pinExists) {
        return inpin->read()*3300.0; //read value is a fload between 0 and 1.0 (max voltage).  Convert to mV integer value.
    } else {
        return 0;
    }
}


//-----------------------------------------------------
MBEDDigitalOut::MBEDDigitalOut() {
    pinExists = false;
}

void MBEDDigitalOut::init(int pin) {
    if (pin < NUMDIGOUTPORTS) {
        outpin = new DigitalOut(dOutPins[pin]);
        pinExists = true;
    }
}

int MBEDDigitalOut::read() {
    if (pinExists) {
        return outpin->read();
    } else {
        return 0;
    }
}

void MBEDDigitalOut::write(int value) {
    if (pinExists) {

        outpin->write(value);
    }
}
//--------------------------------------------------------

MBEDDigitalIn::MBEDDigitalIn() {
    pinExists = false;
}

void MBEDDigitalIn::init(int pin) {

    if (pin < NUMDIGINPORTS) {
        inpin = new DigitalIn(dInPins[pin]);
        inpin_interrupt = new InterruptIn(dInPins[pin]);
        inpin->mode(PullDown);
        //Set up callbacks for the port interrupts
    #ifdef LPC1768
        inpin_interrupt->rise(this, &MBEDDigitalIn::interrupt_up_callback);
        inpin_interrupt->fall(this, &MBEDDigitalIn::interrupt_down_callback);
    #endif
    #ifdef K64
        inpin_interrupt->rise(callback(this, &MBEDDigitalIn::interrupt_up_callback));
        inpin_interrupt->fall(callback(this, &MBEDDigitalIn::interrupt_down_callback));
    #endif
        pinExists = true;
    }
}

int MBEDDigitalIn::read() {
    if (pinExists) {
        return inpin->read();
    } else {
        return 0;
    }
}

void MBEDDigitalIn::interrupt_up_callback() {
    addStateChange(1, timeKeeper);
}

void MBEDDigitalIn::interrupt_down_callback() {
    addStateChange(0, timeKeeper);
}

//----------------------------------------------------------
MBEDSerialPort::MBEDSerialPort() {

}

void MBEDSerialPort::init() {
    //Initialize serial communication
    serialToPC = new Serial(USBTX, USBRX); // tx, rx
    serialToPC->baud(115200);


}

bool MBEDSerialPort::readable() {
    return serialToPC->readable();
}

char MBEDSerialPort::readChar() {
    return serialToPC->getc();
}

void MBEDSerialPort::writeChar(char s) {
    serialToPC->printf("%c", s);
}

int MBEDSerialPort::requestToWriteString(char *s, int numBytesRequested) {
    //request to print a string to the serial output buffer
    //function returns the number of chars actually accepted for output
    int numBytesAccepted = 0;
    while (numBytesAccepted < numBytesRequested) {

        writeChar(*(s+numBytesAccepted));
        numBytesAccepted++;
    }

    return numBytesAccepted;
}