
Microcontroller firmware that uses a simple, yet powerful scripting language to control the timing of input and output events with high temporal resolution. Written by Mattias Karlsson
Revision 3:d7b0a0890d96, committed 2015-10-10
- Comitter:
- mkarlsso
- Date:
- Sat Oct 10 22:37:17 2015 +0000
- Parent:
- 2:35266b266eaa
- Child:
- 4:abee20c0bf2a
- Commit message:
- Changes ports for new PCB board
Changed in this revision
--- a/behave.cpp Wed Jun 03 23:41:16 2015 +0000 +++ b/behave.cpp Sat Oct 10 22:37:17 2015 +0000 @@ -2,8 +2,8 @@ #include "hardwareInterface.h" #include <ctype.h> #include <sstream> -#include <string.h> -#include <cstdlib> +//#include <string.h> +//#include <cstdlib> using namespace std; @@ -119,6 +119,7 @@ void mainLoop::exec() { bool digitalInChanged = false; bool digitalOutChanged = false; + bool *ignoreUpdatePorts = hardware->getIgnoreUpdates(); uint32_t changeTime; timeKeeper = 0; //set main clock to 0; @@ -218,11 +219,15 @@ digitalInChanged = false; digitalOutChanged = false; changeTime = timeKeeper; + for (int i = 0; i < NUMPORTS; i++) { if (ports[i].update()) { - digitalInChanged = true; + if (!ignoreUpdatePorts[i]) { + //Only trigger an output update to the serial port if ignore is false + digitalInChanged = true; + } changeTime = min(changeTime,ports[i].lastChangeTime); @@ -287,8 +292,10 @@ //check for shortcut triggers numTriggersToProcess = hardware->getPendingFunctionTriggers(shortcutTriggers); for (int i = 0; i < numTriggersToProcess; i++) { - if (shortcutTriggers[i] < NUMTRIGGERACTIONS && functionSpotTaken[i]) { - functionEventArray[i]->execute(); + textDisplay << "Trigger function " << shortcutTriggers[i]+1 << "\r\n"; + if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]]) { + //textDisplay << "Executing function array index " << shortcutTriggers[i] << "\r\n"; + functionEventArray[shortcutTriggers[i]]->execute(); } } @@ -510,16 +517,17 @@ if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();} } } - + lastInState = inState; inPin->lastUpEvent.triggered = false; inPin->lastDownEvent.triggered = false; - + inPin->setUpdate(false); //This also checks if there were any buffered changes that occured + } - + } @@ -582,9 +590,9 @@ void displayAction::execute() { if (dVariable != NULL) { - textDisplay << timeKeeper << " " << dText << " = " << *dVariable << "\r\n"; + textDisplay << timeKeeper << " " << dText.c_str() << " = " << *dVariable << "\r\n"; } else { - textDisplay << timeKeeper << " " << dText << "\r\n"; + textDisplay << timeKeeper << " " << dText.c_str() << "\r\n"; } } @@ -2280,7 +2288,7 @@ blockDepth = blockDepth - 1; } - while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4)){ + while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4) || (tmpEventPtrArray.back()->blockType == 6) || (tmpEventPtrArray.back()->blockType == 7) || (tmpEventPtrArray.back()->blockType == 8)){ tmpEventPtrArray.pop_back(); //recursively remove the pointers to all else blocks } tmpEventPtrArray.pop_back(); //remove the pointer to the finished block @@ -2526,10 +2534,10 @@ textDisplay <<"Error: expected a ) character\r\n"; lineError = true; } - + if (!lineError) { string dispVar = tmpLine.substr(pos1,pos2-pos1); - + int* tmpVar = findIntVariable(dispVar); bool isText = false; if (tmpVar == NULL) { @@ -2545,10 +2553,10 @@ textDisplay << "Error: no memory slots available.\r\n"; lineError = true; } - + if (!lineError && (blockDepth == 0)) { //we are not inside a block structure, so display now - + if (isText) { //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr); dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2)); @@ -2562,7 +2570,7 @@ //delete dPtr; dPtr->release(); } - + } else if (!lineError && (blockDepth > 0) ){ //the disp function was put inside a block textDisplay.debug("Display statement\r\n"); @@ -2584,8 +2592,8 @@ //action* tmpAction = new action(dPtr); tmpEventPtrArray.back()->addAction(tmpAction); } - - + + } } //---------------------------------------------- @@ -2788,6 +2796,7 @@ lineError = true; } bool stream = true; + int specifiedPort = -1; if ((!lineError)&&(i+1 < sz)){ if (tokens[i+1].compare("on") == 0) { stream = true; @@ -2798,14 +2807,47 @@ lineError = true; } } + if ((!lineError) && (i+2 < sz)) { + //There is a port specified + //int pos1 = tmpLine.find("trigger(")+8; + //int pos2 = tmpLine.find_first_of(")",pos1); + int tempPort = atoi(tokens[i+2].data()); + + if (tempPort > 0) { + specifiedPort = tempPort-1; + } else { + textDisplay << "Error: 'updates' useage: 'updates on [port]' or 'updates off [port]'\r\n"; + lineError = true; + } + i++; + } i++; if ((!lineError) && (blockDepth == 0)) { if (stream) { + //applies to all; broadCastStateChanges = true; + if (specifiedPort > -1) { + system->setPortUpdatesOn(specifiedPort); + } else { + for (int i=0;i<NUMPORTS;i++) { + system->setPortUpdatesOn(i); + } + } } else { - broadCastStateChanges = false; + if (specifiedPort > -1) { + system->setPortUpdatesOff(specifiedPort); + } else { + //applies to all + //broadCastStateChanges = false; + for (int i=0;i<NUMPORTS;i++) { + system->setPortUpdatesOff(i); + } + } + } } else if ((!lineError) && (blockDepth > 0)) { + //Inside a block-- current no support here to specify a port + if (stream) { //action* tmpAction = new action(3); //code 3 = turn on updates action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); @@ -2882,6 +2924,10 @@ delete globalVariables.back(); globalVariables.pop_back(); } + broadCastStateChanges = true; + for (int i=0;i<NUMPORTS;i++) { + system->setPortUpdatesOn(i); + } } //clear callbacks, functions, and queue @@ -3576,17 +3622,20 @@ //if there was an error, we quit compiling the code if (lineError) { + textDisplay << "Line text: "; while (!tokens.empty()) { textDisplay << tokens.front()<< " "; tokens.erase(tokens.begin()); } textDisplay << "\r\n"; + currentBlock.resetBuffer(); while (!tokens.empty()) { tokens.pop_back(); } - delete tmpEvent; + //delete tmpEvent; + tmpEvent->release(); } else { while (!tokens.empty()) { @@ -3766,7 +3815,7 @@ multiplierInt = -1; } - + tmpVar = findIntVariable(expression,0,beforeEqualLoc); //returns pointer to the variable if (findStringLoc(expression,"portout[",0,beforeEqualLoc) != -1) { //set the output of a digital port textDisplay.debug("Portout assignment\r\n");
--- a/behave.h Wed Jun 03 23:41:16 2015 +0000 +++ b/behave.h Sat Oct 10 22:37:17 2015 +0000 @@ -25,7 +25,7 @@ #include "fpgaInterface.h" #endif - +/* #define NUMEVENTS 50 #define NUMCONDITIONS 150 #define NUMINTCOMPARE 150 @@ -34,13 +34,15 @@ #define NUMINTOPERATIONS 150 #define NUMDISPLAYACTIONS 30 #define NUMTRIGGERACTIONS 30 +#define NUMFUNCTIONS 50 +#define INPUTCHARBUFFERSIZE 3072 +*/ #define ARITHMATIC_CONDITION 0 #define OR_CONDITION 1 #define AND_CONDITION 2 -#define NUMFUNCTIONS 50 -#define INPUTCHARBUFFERSIZE 3072 + using namespace std;
--- a/hardwareInterface.cpp Wed Jun 03 23:41:16 2015 +0000 +++ b/hardwareInterface.cpp Sat Oct 10 22:37:17 2015 +0000 @@ -32,7 +32,23 @@ //--------------------------------------------------------- sSystem::sSystem() { + for (int i=0;i<32;i++) { + ignorePortUpdates[i] = false; + } +} +//The user can toggle whether a particular port triggers a state update report every time it changes +//This is useful for inputs that toggle continuously. +void sSystem::setPortUpdatesOff(int portNum) { + ignorePortUpdates[portNum] = true; +} + +void sSystem::setPortUpdatesOn(int portNum) { + ignorePortUpdates[portNum] = false; +} + +bool* sSystem::getIgnoreUpdates() { + return ignorePortUpdates; } void sSystem::immediateClockReset() { @@ -207,7 +223,7 @@ } //adds text to the buffer -void outputStream::send(string outputString) { +void outputStream::send(const string &outputString) { int strLen = outputString.size(); int total = 0; @@ -230,6 +246,38 @@ } } +//adds text to the buffer +void outputStream::send(const char *s) { + int strLen = strlen(s); + + int total = 0; + //int chunk = 0; + if (totalWriteHead+strLen > (totalReadHead + bufferSize)) { + //We don't have enough space in the buffer, so flush it + flush(); + } + if (!(totalWriteHead+strLen > (totalReadHead + bufferSize))) { + while (strLen - total > 0) { + strncpy(outputBuffer + writeHead, s+total,1); + total++; + writeHead = (writeHead + 1) % bufferSize; + totalWriteHead += 1; + + /* + chunk = min((bufferSize - writeHead), strLen - total); + strncpy(outputBuffer + writeHead,); + outputString.copy(outputBuffer + writeHead, chunk, total); + writeHead = (writeHead + chunk) % bufferSize; + totalWriteHead += chunk; + total += chunk; + */ + } + if (total > 0) { + unsentData = true; + } + } +} + void outputStream::debug(const char *s) { //send to serial immediately, but only if debugOut is true if (debugOut) { @@ -241,14 +289,16 @@ //Overloaded << operator to for debugging output. This eliminates the //need for printf statements -outputStream& outputStream::operator<<(string outputString) { +outputStream& outputStream::operator<<(const string &outputString) { send(outputString); + return *this; } outputStream& outputStream::operator<<(const char* s) { - string tmpString = string(s); - send(tmpString); + //string tmpString = string(s); + //send(tmpString); + send(s); return *this; }
--- a/hardwareInterface.h Wed Jun 03 23:41:16 2015 +0000 +++ b/hardwareInterface.h Sat Oct 10 22:37:17 2015 +0000 @@ -3,6 +3,8 @@ #include <stdint.h> #include <string> +#include <cstdlib> +#include <string.h> #define PENDINGTRIGGERBUFFERSIZE 10 @@ -63,6 +65,8 @@ virtual bool readable() = 0; virtual char readChar() = 0; virtual void writeChar(char s)= 0; + virtual int requestToWriteString(char *s, int numBytes) = 0; + protected: @@ -106,17 +110,22 @@ virtual int getPendingFunctionTriggers(uint16_t *bufferPtr); //Returns the number of pending shortcut triggers virtual uint32_t getDigitalOutputChangeFlags(); virtual uint32_t getDigitalInputChangeFlags(); + void setPortUpdatesOn(int portNum); + void setPortUpdatesOff(int portNum); + bool* getIgnoreUpdates(); + protected: //virtual void timerInterrupt() = 0; - void immediateClockReset(); + void immediateClockReset(); int currentDINPin; int currentDOUTPin; uint32_t currentDigitalOuputStates; uint32_t currentDigitalInputStates; + bool ignorePortUpdates[32]; @@ -134,9 +143,10 @@ outputStream(int bufferSizeIn); ~outputStream(); void setSerial(sSerialPort *s); - void send(string outputString); + void send(const string &outputString); + void send(const char* s); void debug(const char* s); - outputStream &operator<<(string outputString); + outputStream &operator<<(const string &outputString); outputStream &operator<<(int outputNum); outputStream &operator<<(uint32_t outputNum); outputStream &operator<<(const char* s);
--- a/mbedInterface/mbedInterface.cpp Wed Jun 03 23:41:16 2015 +0000 +++ b/mbedInterface/mbedInterface.cpp Sat Oct 10 22:37:17 2015 +0000 @@ -9,6 +9,9 @@ //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; @@ -20,7 +23,7 @@ #ifdef MBED_RF -//Karpova version---------------------------------------- +//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 @@ -93,7 +96,34 @@ //------------------------------------------------------------ #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) + 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"; + } +} //------------------------------------------------------------------------ //------------------------------------------------------------------------ @@ -102,27 +132,37 @@ //--------------------------------------------------------------------- //translate pin numbers to hardware pins -PinName outPins[NUMPORTS] = {p11,p13,p15,p18,p21,p23,p25,p29,p20}; +//PinName outPins[NUMPORTS] = {p11,p13,p15,p18,p21,p23,p25,p29,p20}; +PinName outPins[NUMPORTS] = {p18,p15,p13,p11,p29,p25,p23,p21,p20}; PinName inPins[NUMPORTS] = {p12,p14,p16,p17,p22,p24,p26,p30,p7}; + //The sound output uses a SmartWav device and their simple serial library SMARTWAV sWav(p9,p10,p19); //(TX,RX,Reset); //This is the callback for the MBED timer extern "C" void TIMER0_IRQHandler (void) { - if((LPC_TIM0->IR & 0x01) == 0x01) { // if MR0 interrupt, proceed + if (clockSlave) { + //The function is called every 100 us + uSec_SinceLastClockInc = uSec_SinceLastClockInc+100; + uSec_SinceLastReset = uSec_SinceLastReset+100; + } else { + //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++; + LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag + timeKeeper++; - if (resetTimer) { - timeKeeper = 0; - resetTimer = false; + if (resetTimer) { + timeKeeper = 0; + resetTimer = false; + } } } + } //----------------------------------------------------------------------- @@ -133,6 +173,7 @@ clockExternalIncrement(p8) { clockResetInt.rise(this, &MBEDSystem::externalClockReset); + clockResetInt.fall(&externalResetDown); clockResetInt.mode(PullDown); clockExternalIncrement.mode(PullDown); @@ -165,8 +206,9 @@ //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_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 @@ -178,6 +220,14 @@ //-------------------------------------------------------------- } +void MBEDSystem::pauseInterrupts() { + __disable_irq(); +} + +void MBEDSystem::resumeInterrupts() { + __enable_irq(); +} + void MBEDSystem::mainLoopToDo() { #ifdef MBED_RF //Karpova version-------------------------- @@ -225,25 +275,35 @@ 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) { LPC_TIM0->TCR = 0x02; // reset timer externalIncrementCounter = 0; immediateClockReset(); - } + }*/ } void MBEDSystem::setStandAloneClock() { - timerinit(); + clockSlave = false; + NVIC_DisableIRQ(TIMER0_IRQn); // Disable the interrupt + timerinit(); //set up and enable interrupt clockExternalIncrement.rise(NULL); //remove the callback to the external interrupt - clockSlave = false; + //clockExternalIncrement.fall(NULL); changeToSlave = false; changeToStandAlone = false; } void MBEDSystem::setSlaveClock() { + clockSlave = true; NVIC_DisableIRQ(TIMER0_IRQn); // Disable the interrupt + //timerinit(); //set up and enable interrupt clockExternalIncrement.rise(this, &MBEDSystem::incrementClock); + //clockExternalIncrement.fall(&externalClockIncDown); clockSlave = true; changeToSlave = false; changeToStandAlone = false; @@ -252,6 +312,12 @@ 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++; @@ -261,10 +327,12 @@ timeKeeper++; } //Clock resets happen upon update so we dont get a partial first ms + /* if (resetTimer) { + uSec_SinceLastReset = 0; timeKeeper = 0; resetTimer = false; - } + }*/ } //----------------------------------------------------- @@ -360,3 +428,16 @@ 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; +}
--- a/mbedInterface/mbedInterface.h Wed Jun 03 23:41:16 2015 +0000 +++ b/mbedInterface/mbedInterface.h Sat Oct 10 22:37:17 2015 +0000 @@ -17,6 +17,17 @@ #define NUMPORTS 9 //the number of ports available on this hardware +#define NUMEVENTS 50 +#define NUMCONDITIONS 150 +#define NUMINTCOMPARE 150 +#define NUMACTIONS 150 +#define NUMPORTMESSAGES 150 +#define NUMINTOPERATIONS 150 +#define NUMDISPLAYACTIONS 30 +#define NUMTRIGGERACTIONS 30 +#define NUMFUNCTIONS 50 +#define INPUTCHARBUFFERSIZE 3072 + /* @@ -65,8 +76,8 @@ void interrupt_up_callback(); void interrupt_down_callback(); protected: - - + + private: DigitalIn *inpin; @@ -83,11 +94,12 @@ bool readable(); char readChar(); void writeChar(char s); + int requestToWriteString(char *s, int numBytes); Serial *serialToPC; private: //Serial communication - + }; @@ -111,16 +123,18 @@ sDigitalOut* getDigitalOutPtr(int portNum); sDigitalIn* getDigitalInPtr(int portNum); sSound* createNewSoundAction(); + void pauseInterrupts(); + void resumeInterrupts(); void incrementClock(); void externalClockReset(); //needs to reset harware timer before calling immediateClockReset(); void mainLoopToDo(); - + protected: - + //Pins for clock syncing InterruptIn clockResetInt; InterruptIn clockExternalIncrement; - + private: MBEDDigitalIn dIn[NUMPORTS]; MBEDDigitalOut dOut[NUMPORTS];