Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BufferedSerial FatFileSystemCpp mbed
Diff: main.cpp
- 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
+ }
}