Racelogic / Mbed 2 deprecated VIPS_LTC_RAW_IMU

Dependencies:   BufferedSerial FatFileSystemCpp mbed

Revision:
9:7214e3c3e5f8
Parent:
8:961bb15570a1
Child:
10:053bac3e326b
--- a/main.cpp	Tue Feb 16 09:53:54 2021 +0000
+++ b/main.cpp	Thu Feb 18 18:15:48 2021 +0000
@@ -1,6 +1,10 @@
 #include "mbed.h"
+#include "MSCFileSystem.h"
 #include "LTCApp.h"
 
+#define FSNAME "msc"
+MSCFileSystem msc(FSNAME);
+
 const int framesToCount = 300;
 const int MaxTimeErrorUS = 150;
 const int timerOverheadTime = 19;
@@ -10,7 +14,7 @@
 BufferedSerial COM1(p13, p14);
 FIZReader FIZPort(p9, p10);
 
-DigitalOut led1(LED1);
+DigitalOut logLED(LED1);
 DigitalOut PPS(p12);
 
 DigitalOut led2(LED2);
@@ -23,9 +27,21 @@
 InterruptIn PPFin(p29);
 InterruptIn Syncin(p8);
 
+DigitalIn logButton(p21);
+
+frameclock movieTime;
+
 // clock to time everything with
 Timer inputTimer;
 
+float logButtonDownTime;
+float logButtonUpTime;
+int logButtonLastState;
+
+bool logging = false;
+FILE *logFile = NULL;
+
+
 // Time since last frame event, used for position output interpolation
 Timer TimeSinceLastFrame;
 uint32_t TimeSinceLastFrameWrap;
@@ -56,6 +72,7 @@
 float remainingClockError;
 bool ppmCorrection;
 
+
 struct outputFormat_s {
     uint32_t header; // 2 byte header + 2 byte length
     uint32_t mask;
@@ -95,19 +112,17 @@
 void sendPosition(position *posPtr)
 {
     if (posPtr) {
-        packetOut.time = posPtr->time;
         packetOut.x = posPtr->X;
         packetOut.y = posPtr->Y;
         packetOut.z = posPtr->Height;
         packetOut.beacons = posPtr->beacons;
         packetOut.solutionType = posPtr->solutionType;
-        packetOut.kfStatus = posPtr->KFStatus;       
+        packetOut.kfStatus = posPtr->KFStatus;
         packetOut.roll = posPtr->roll;
         packetOut.pitch = posPtr->pitch;
         packetOut.yaw = posPtr->yaw;
         packetOut.accuracy[3] = posPtr->ID;
     } else {
-        packetOut.time = 0;
         packetOut.x = 0;
         packetOut.y = 0;
         packetOut.z = 0;
@@ -117,150 +132,18 @@
         packetOut.accuracy[3] = 0;
         packetOut.beacons = 0;
         packetOut.solutionType = 0;
-        packetOut.kfStatus = 0;   
+        packetOut.kfStatus = 0;
     }
+    packetOut.time = movieTime.getTimeMS();
     FIZPort.getMostRecent(&packetOut.focus, &packetOut.iris, &packetOut.zoom);
     VIPSSerial::getCRC((void *)&packetOut, sizeof(struct outputFormat_s)-2, (void *)&packetOut.checksum);
     COM1.write(&packetOut, sizeof(struct outputFormat_s));
-}
-
-
-void OnPPSEdge()
-{
-    if (PPSHigh) {
-        PPS = 0;
-        led3=1;
-        PPSHigh = false;
-    } else {
-        led3=0;
-        PPS = 1;
-        PPSHigh = true;
-
-        if (resync && !ppmCorrection) {
-            PPSOutputTimer.detach();
-            PPSOutputTimer.attach_us(callback(OnPPSEdge), resyncPeriod);
-            resync = false;
-            resyncDone = true;
-        } else if (resyncDone) {
-            resyncDone = false;
-            PPSOutputTimer.detach();
-            PPSOutputTimer.attach_us(callback(OnPPSEdge), 5000);
-            remainingClockError = 0;
-        }
-
-        if ((VBOXTicks % 100) == 0) {
-            lastPPSSecondStart = inputTimer.read_us();
-            second = 1;
-            remainingClockError+=PPMHighAcc;
-            int adjustment = (int)(remainingClockError/2);
-            if (!resyncDone && ((adjustment > 2)|| (adjustment <-2))) {
-                PPSOutputTimer.detach();
-                PPSOutputTimer.attach_us(callback(OnPPSEdge), 5000+adjustment-timerOverheadTime);
-                ppmCorrection=true;
-                remainingClockError-=2*adjustment;
-            }
-        } else {
-            if ((VBOXTicks % 100) == 1) {
-                second = 0;
-                if (ppmCorrection) {
-                    PPSOutputTimer.detach();
-                    PPSOutputTimer.attach_us(callback(OnPPSEdge), 5000);
-                    ppmCorrection=false;
-                }
-            }
-        }
-
-        VBOXTicks++;
-        if (VBOXTicks >= (24 * 60 * 60 * 100))
-            VBOXTicks -= (24 * 60 * 60 * 100);
-    }
-}
-
-void OnPPSCync()
-{
-    PPS = 1;
-    led3=0;
-    PPSOutputTimer.detach();
-    PPSOutputTimer.attach_us(callback(OnPPSEdge), 5000);
-    PPSHigh = true;
-    VBOXTicks++;
-    ppsActive = true;
-    led1 = 1;
-}
-
-const char *ticksToTime(unsigned long vboxTickCount)
-{
-    static char timeString[32];
-    int hours = vboxTickCount / 360000;
-    int minutes = (vboxTickCount / 6000) % 60;
-    int seconds = (vboxTickCount / 100) % 60;
-    int ms = 10 * (vboxTickCount % 100);
-    sprintf(timeString, "%02d:%02d:%02d.%03d", hours, minutes, seconds, ms);
-    return timeString;
-}
-
-bool isStartOfSecond(int minutes, int seconds, int frame, bool dropFrame)
-{
-    if (frame == 0)
-        return true;
-    if (dropFrame && (2 == frame) && (0 == seconds) && (minutes % 10 != 0))
-        return true;
-    return false;
-}
-
-
-int getClosestRateIndex(long int framePeriodUS)
-{
-    int indexOver = 1;
-    while (framePeriodUS <= frameRateInfo::FramePeriods[indexOver])
-        indexOver++;
-    float amountOver = framePeriodUS - frameRateInfo::FramePeriods[indexOver];
-    float amountUnder = frameRateInfo::FramePeriods[indexOver - 1] - framePeriodUS;
-    if (amountOver > amountUnder)
-        return indexOver - 1;
-    return indexOver;
-}
-
-// frame rate and clock error calculation
-void frameRateMeasure(uint32_t frameStartTime, bool dropFrame=false)
-{
-    frameToggle =!frameToggle;
-    static int frameRateCount = 0;
-    static uint32_t rateCalcStartTime;
-    if (frameRateCount == 0) {
-        rateCalcStartTime = frameStartTime;
-        frameRateCount = 1;
-    } else {
-        if (frameRateCount == framesToCount) {
-            uint32_t timeTaken = frameStartTime - rateCalcStartTime;
-            long int timePerFrame = timeTaken / framesToCount;
-            detectedRate.setRate(getClosestRateIndex(timePerFrame));
-            float TrueSeconds = framesToCount / detectedRate.currentRate();
-            // +ve PPM means I counted more than real time = my clock is fast.
-            float ppmError = (timeTaken - (1000000 * TrueSeconds)) / TrueSeconds;
-            if ((ppmError<250) && (ppmError>-250)) { // something went very wrong with ppm calculation.
-                if (PPMHighAcc!=0) {
-                    PPMTrackTotal -= PPMErrors[PPMTrackIndex];
-                    PPMTrackTotal += ppmError;
-                    PPMErrors[PPMTrackIndex++] = ppmError;
-                    PPMHighAcc = PPMTrackTotal / _longPPMTrackLen_;
-                } else { // first time
-                    for (int i=0; i<_longPPMTrackLen_; i++)
-                        PPMErrors[i] = ppmError;
-                    PPMTrackTotal = ppmError*_longPPMTrackLen_;
-                    PPMHighAcc = ppmError;
-                }
-                if (PPMTrackIndex == _longPPMTrackLen_)
-                    PPMTrackIndex = 0;
-                // printf("Frame rate detected as %s. My clock is %.4f ppm fast\r\n", detectedRate.frameRateString(), PPMHighAcc);
-            } else {
-                printf("Frame rate unclear\r\n");
-                PPMHighAcc=0;
-                detectedRate.setRate(0);
-            }
-            frameRateCount = 0;
-        } else {
-            frameRateCount++;
+    if (logging) {
+        if (!fwrite(&packetOut, sizeof(struct outputFormat_s), 1, logFile)) { // write failed
+            logLED = 0;
+            logging = false;
+            fclose(logFile);
+            logFile = NULL;
         }
     }
 }
@@ -269,100 +152,34 @@
 //called once per frame to output the current postition
 void framePositionOutput()
 {
-    sendPosition(VIPS.sendPositionForTime(TimeSinceLastFrame.read_us()));
+    uint32_t outputTime = TimeSinceLastFrame.read_us();
     TimeSinceLastFrame.reset();
+    sendPosition(VIPS.sendPositionForTime(outputTime));
     FIZPort.requestCurrent();
 }
 
-// called by background loop at the end of each frame
-// frameStartTime = time of inputTimer at the start of the first bit of the
-// frame. dropFrame = true if the protocol includes frameDrops
-void frameComplete(int hours, int minutes, int seconds, int frame,
-                   bool dropFrame, uint32_t frameStartTime)
+int getNextFileNumber()
 {
-    static int lastFrame = 0;
-    static float ppmError=0;
-    static int outCount = 0;
-    if ((frame != (lastFrame + 1)) && detectedRate.currentRate()) {
-        long timeSinceSecondStart = detectedRate.getOffsetFromSecondStart(minutes, seconds, frame);
-//    printf("Time Code %02d:%02d:%02d:%02d - VBOX time %s\r", hours, minutes, seconds, frame, ticksToTime(VBOXTicks));
-        uint32_t ThisSecondStart = frameStartTime - timeSinceSecondStart;
-        if (!ppsRunning) {
-            uint32_t nextSecondStart = ThisSecondStart + 1000000 + (int)(ppmError + 0.5);
-            ppsRunning = true;
-            __disable_irq();
-            uint32_t nextSec =  nextSecondStart - inputTimer.read_us();
-            PPSsyncTimer.attach_us(callback(OnPPSCync), nextSec);
-            __enable_irq();
-            printf("PPS start scheduled for %0.3f seconds.\r\n", nextSec / 1000000.0f);
-            VBOXTicks = (hours * 3600 + minutes * 60 + (seconds + 1)) * 100;
-        } else if (detectedRate.isSyncable()) { // PPS running and from a syncable source
-            long timeError = (lastPPSSecondStart - ThisSecondStart);
-            if (timeError < -500000)
-                timeError += 1000000;
-            timeError = timeError % 1000000;
-//      printf("PPS error measured as %ld us.\r", timeError);
-
-            if ((timeError > MaxTimeErrorUS) || (timeError < -MaxTimeErrorUS)) {
-                outCount++;
-                if (outCount > 3) {
-                    int newPeriod = 5000 - timeError / 2;
-                    if (newPeriod < 4500)
-                        newPeriod = 4500;
-                    if (newPeriod > 5500)
-                        newPeriod = 5500;
-
-                    //      printf("Resync attempt. Error was %ld. 1 cycle at %d us\r\n", timeError, newPeriod);
-                    __disable_irq();
-                    resyncPeriod = newPeriod - timerOverheadTime;
-                    resync = true;
-                    __enable_irq();
-                }
-            } else
-                outCount = 0;
-        } // either no PPS and can't start it yet or running from unsyncable source
-        // so just free run.
-    }
-    lastFrame = frame;
-
-    // frame rate and clock error calculation
-    frameRateMeasure(frameStartTime, dropFrame);
-    framePositionOutput();
+    static unsigned int fileNbr = 0;
+    char fileName[32];
+    FILE *filePtr = NULL;
+    do {
+        if (filePtr != NULL)
+            fclose(filePtr);
+        sprintf(fileName,"/msc/VIPS%04u.bin",fileNbr++);
+        filePtr = fopen(fileName,"rb");
+    } while (filePtr != NULL);
+    return fileNbr-1;
 }
 
-// called by background loop at the end of each frame when running from a sync signal not timecode
-void framePulse(uint32_t frameStartTime)
+FILE *nextBinaryFile(void)
 {
-    static int outCount = 0;
-    uint32_t patternStartTime;
-    if (detectedRate.isValid()) {
-        if (!ppsRunning) {
-            LTCInput.readWaitingData();
-            if (outCount<20) {
-                outCount++;
-            } else {
-                const LTCDecode::LTCData_t *frameData = LTCInput.getLastFrame();
-                detectedRate.setDrop(frameData->frameDrop);
-                uint32_t ThisSecondStart = frameStartTime - detectedRate.getOffsetFromSecondStart(frameData->minutes, frameData->seconds, frameData->frame);
-                uint32_t nextSecondStart = ThisSecondStart + 1000000;
-                ppsRunning = true;
-                __disable_irq();
-                uint32_t nextSec =  nextSecondStart - inputTimer.read_us();
-                PPSsyncTimer.attach_us(callback(OnPPSCync), nextSec);
-                __enable_irq();
-                printf("PPS start scheduled for %0.3f seconds.\r\n", nextSec / 1000000.0f);
+    char fileName[32];
+    int file = getNextFileNumber();
+    sprintf(fileName,"/msc/VIPS%04u.bin",file);
+    return fopen(fileName,"wb");
+}
 
-                VBOXTicks = (frameData->hours * 3600 + frameData->minutes * 60 + (frameData->seconds + 1)) * 100;
-                LTCInput.disable();
-            }
-        } else {
-            framePositionOutput();
-        }
-    }
-
-// frame rate and clock error calculation
-    frameRateMeasure(frameStartTime, false);
-}
 
 volatile bool NewFramePulse= false;
 uint32_t FramePulseTime;
@@ -381,6 +198,7 @@
 
 void OnPPFInput(void)
 {
+    movieTime.nextFrame();
     FramePulseTime = inputTimer.read_us();
     NewFramePulse = true;
 }
@@ -394,106 +212,109 @@
     inputTimer.start();
 
     pc.printf("Startup\r\n");
-    led1 = 1;
+    logLED = 0;
 
     prepPacketOut();
 
-    LTCInput.setInputTimer(&inputTimer);
-
-    PPFin.rise(callback(&OnPPFInputStartup));
+    LTCInput.enable(true);
 
     VIPS.run();
 
-    pc.printf("armed\r\n");
-    led2 = 1;
-
-    for (int i = 0; i < _longPPMTrackLen_; i++)
-        PPMErrors[i] = 0;
     pc.printf("Startup\r\n");
-    PPMTrackIndex = 0;
-    PPMTrackTotal = 0;
-    remainingClockError = 0;
-    bool GenLockOnlyMode = false;
-    bool GenLockToSync = false;
 
     TimeSinceLastFrame.reset();
     TimeSinceLastFrame.start();
+
+    pc.printf("Waiting for sync input clock\r\n");
+    PPFin.rise(callback(&OnPPFInputStartup));
+    Syncin.rise(callback(&OnSyncInputStartup));
+    framesIn = 0;
+    SyncInCount = 0;
+    bool LockToSync = false;
+
     while (true) {
-        pc.printf("Waiting for sync\r\n");
-        PPFin.rise(callback(&OnPPFInputStartup));
-        Syncin.rise(callback(&OnSyncInputStartup));
-        framesIn = 0;
-        SyncInCount = 0;
-        GenLockOnlyMode = false;
-        GenLockToSync = false;
-        while (!LTCInput.searchForSync()) {
-            if (framesIn == 100) {
-                GenLockOnlyMode = true;
-                break;
-            }
-            if ((SyncInCount == 100) && (framesIn<45)) { // prefer frame input pin, sync may be twice as high for interlaced systems.
-                GenLockOnlyMode = true;
-                GenLockToSync= true;
-                break;
-            }
+        if (framesIn == 100) {
+            break;
+        }
+        if ((SyncInCount == 100) && (framesIn<45)) { // prefer frame input pin, sync may be twice as high for interlaced systems.
+            LockToSync= true;
+            break;
+        }
+    }
 
-            int message = VIPS.getStatusMessage();
-            if (message)
-                pc.printf("%s\r\n",VIPSStatusMessages[message-1]);
+    if (LockToSync) {
+        pc.printf("Using Genlock sync input\r\n");
+        Syncin.rise(callback(&OnPPFInputStartup));
+        PPFin.rise(NULL);
+    } else {
+        pc.printf("Using pulse per frame input\r\n");
+        Syncin.rise(NULL);
+    }
+
+    pc.printf("Measuring frame rate\r\n");
 
-        }
-        if (true) { // GenLockOnlyMode) {
-            if (GenLockToSync) {
-                pc.printf("No LTC detected for 100 frames. Falling back to genlock on sync input\r\n");
-                Syncin.rise(callback(&OnPPFInput));
-                PPFin.rise(NULL);
-            } else {
-                pc.printf("No LTC detected for 100 frames. Falling back to genlock on frame input\r\n");
-                PPFin.rise(callback(&OnPPFInput));
-                Syncin.rise(NULL);
-            }
-            uint32_t lastframeTime = inputTimer.read_us();
+    int currentFrames = framesIn;
+    while (framesIn == currentFrames);  // wait for next frame;
+    inputTimer.reset();
+    framesIn = 0;
+
+    while (framesIn < 100);  // wait for 100 frames;
+    uint32_t frameTime = inputTimer.read_us()/100;
+
+    int framesPerSecond = frameRates::getClosestRate(frameTime);
+
+    pc.printf("Detected frame rate %d\r\n",framesPerSecond);
 
-            while (true) {
-                if (!ppsRunning)
-                  LTCInput.readWaitingData();
-                
-                if (NewFramePulse) { // running on a frame
-//            printf("frame\r");
-                    lastframeTime = FramePulseTime;
-                    framePulse(lastframeTime);
-                    NewFramePulse = false;
+    if (LTCInput.synced()) { // getting LTC so set the clock.
+        currentFrames = framesIn;
+        while (framesIn == currentFrames);  // wait for next frame;
+        wait_us (frameTime/4); // ensure the LTC decode for the last frame is done.
+        int hour,minute,second,frame;
+        bool drop = LTCInput.isFrameDrop();
+        LTCInput.getTime(&hour,&minute,&second,&frame);
+        movieTime.setMode(framesPerSecond,drop);
+        movieTime.setTime(hour,minute,second,frame);
+    } else { // no time code so clock time doesn't matter
+        movieTime.setMode(framesPerSecond,false);
+    }
+
+    if (LockToSync)
+        Syncin.rise(callback(&OnPPFInput));
+    else
+        PPFin.rise(callback(&OnPPFInput));
+
+    pc.printf("Current time is %02d:%02d:%02d %02d\r\n",movieTime.hours(),movieTime.minutes(),movieTime.seconds(),movieTime.frame());
+    LTCInput.enable(false);
+
+    pc.printf("Running\r\n",framesPerSecond);
+
+    getNextFileNumber();
+
+    while (true) {
+        if (NewFramePulse) { // New frame. Output data.
+            //framePulse(FramePulseTime);
+            framePositionOutput();
+            NewFramePulse = false;
+        }
+
+        if (logButtonLastState != logButton) {
+            if (logButton) { // pressed
+                logButtonDownTime = inputTimer.read();
+                if (logging) {
+                    logLED = 0;
+                    logging=false;
+                    fclose(logFile);
+                } else {
+                    logFile = nextBinaryFile();
+                    if(logFile) {
+                        logLED = 1;
+                        logging = true;
+                    }
                 }
-                if ((inputTimer.read_us()-lastframeTime) > 1000000) {
-                    pc.printf("No frames for > 1 second\r\n");
-                    break;
-                }
-                int message = VIPS.getStatusMessage();
-                if (message)
-                    pc.printf("%s\r\n",VIPSStatusMessages[message-1]);
+            } else { // released
+                logButtonUpTime = inputTimer.read();
             }
-        } else { // not genlock
-            pc.printf("Got LTC sync\r\n");
-            PPFin.rise(NULL);
-            while (LTCInput.synced()) {
-                position *posPtr = VIPS.getWaitingPostion();
-                if (posPtr) {
-                    sendPosition(posPtr);
-                }
-                if (LTCInput.readWaitingData()) {
-                    if (LTCInput.synced()) {
-                        const LTCDecode::LTCData_t *frameData = LTCInput.getLastFrame();
-                        detectedRate.setDrop(frameData->frameDrop);
-                        frameComplete(frameData->hours, frameData->minutes,
-                                      frameData->seconds, frameData->frame,
-                                      frameData->frameDrop, frameData->frameStartTime);
-                    } // end if good frame
-                }   // end if new data
-                int message = VIPS.getStatusMessage();
-                if (message)
-                    pc.printf("%s\r\n",VIPSStatusMessages[message-1]);
-            }     // end while synced
-            pc.printf("Sync lost\r");
+            logButtonLastState = logButton;
         }
-    } // end while true
+    }
 }