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

Dependencies:   SMARTWAV mbed

Files at this revision

API Documentation at this revision

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

behave.cpp Show annotated file Show diff for this revision Revisions of this file
behave.h Show annotated file Show diff for this revision Revisions of this file
hardwareInterface.cpp Show annotated file Show diff for this revision Revisions of this file
hardwareInterface.h Show annotated file Show diff for this revision Revisions of this file
mbedInterface/mbedInterface.cpp Show annotated file Show diff for this revision Revisions of this file
mbedInterface/mbedInterface.h Show annotated file Show diff for this revision Revisions of this file
--- 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];