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
main.cpp
- Committer:
- AndyA
- Date:
- 2021-02-19
- Revision:
- 10:053bac3e326b
- Parent:
- 9:7214e3c3e5f8
- Child:
- 11:ef7f6591b776
File content as of revision 10:053bac3e326b:
#include "mbed.h"
#include "MSCFileSystem.h"
#include "LTCApp.h"
MSCFileSystem msc("msc");
//USBHostMSD msd("msc");
const int framesToCount = 300;
const int MaxTimeErrorUS = 150;
const int timerOverheadTime = 19;
BufferedSerial pc(USBTX, USBRX);
VIPSSerial VIPS(p28, p27);
BufferedSerial COM1(p13, p14);
FIZReader FIZPort(p9, p10);
DigitalOut logLED(LED1);
//DigitalOut PPS(p12);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut frameToggle(LED4);
DigitalOut second(p23);
LTCDecode LTCInput(p7);
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;
// used to start PPS at the correct point
Timeout PPSsyncTimer;
// used to generate PPS edges
Ticker PPSOutputTimer;
frameRates detectedRate;
bool ppsRunning = false; // set when PPS start has been scheduled
volatile bool ppsActive = false; // set when PPS is actuallt going (up to 1 second later)
volatile bool PPSHigh;
bool resync = false;
bool resyncDone = false;
uint32_t resyncPeriod;
bool OKToCheckSync = false;
volatile uint32_t VBOXTicks = 0; // time at the NEXT PPS edge
uint32_t lastPPSSecondStart;
#define _longPPMTrackLen_ 20
float PPMErrors[_longPPMTrackLen_];
float PPMTrackTotal;
int PPMTrackIndex;
float PPMHighAcc;
float remainingClockError;
bool ppmCorrection;
struct outputFormat_s {
uint32_t header; // 2 byte header + 2 byte length
uint32_t mask;
uint32_t time;
double x;
double y;
float z;
uint8_t beacons;
uint8_t solutionType;
uint16_t kfStatus;
float roll;
float pitch;
float yaw;
uint8_t accuracy[4];
uint32_t focus;
uint16_t iris;
uint16_t zoom;
uint16_t checksum;
} __attribute__((packed)) ;
struct outputFormat_s packetOut;
void prepPacketOut()
{
uint8_t bytes[4];
bytes[0]=0x24;
bytes[1]=0xd9;
*(uint16_t*)(bytes+2) = sizeof(struct outputFormat_s);
packetOut.header = *(uint32_t*)bytes;
packetOut.mask = 0x0446;
packetOut.accuracy[0] = 0;
packetOut.accuracy[1] = 0;
packetOut.accuracy[2] = 0;
packetOut.accuracy[3] = 0;
}
void sendPosition(position *posPtr)
{
if (posPtr) {
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.roll = posPtr->roll;
packetOut.pitch = posPtr->pitch;
packetOut.yaw = posPtr->yaw;
packetOut.accuracy[3] = posPtr->ID;
} else {
packetOut.x = 0;
packetOut.y = 0;
packetOut.z = 0;
packetOut.roll = 0;
packetOut.pitch = 0;
packetOut.yaw = 0;
packetOut.accuracy[3] = 0;
packetOut.beacons = 0;
packetOut.solutionType = 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));
if (logging) {
if (!fwrite(&packetOut, sizeof(struct outputFormat_s), 1, logFile)) { // write failed
logLED = 0;
logging = false;
fclose(logFile);
logFile = NULL;
}
}
}
//called once per frame to output the current postition
void framePositionOutput()
{
uint32_t outputTime = TimeSinceLastFrame.read_us();
TimeSinceLastFrame.reset();
sendPosition(VIPS.sendPositionForTime(outputTime));
FIZPort.requestCurrent();
}
int getNextFileNumber()
{
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;
}
FILE *nextBinaryFile(void)
{
char fileName[32];
int file = getNextFileNumber();
sprintf(fileName,"/msc/VIPS%04u.bin",file);
return fopen(fileName,"wb");
}
volatile bool NewFramePulse= false;
uint32_t FramePulseTime;
volatile int framesIn = 0;
void OnPPFInputStartup(void)
{
framesIn++;
}
volatile int SyncInCount = 0;
void OnSyncInputStartup(void)
{
SyncInCount++;
}
void OnPPFInput(void)
{
movieTime.nextFrame();
FramePulseTime = inputTimer.read_us();
NewFramePulse = true;
}
int main()
{
pc.baud(115200);
COM1.baud(115200);
inputTimer.reset();
inputTimer.start();
pc.printf("Startup\r\n");
logLED = 0;
prepPacketOut();
LTCInput.enable(true);
VIPS.run();
pc.printf("Startup\r\n");
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) {
if (SyncInCount == 100) {
LockToSync= true;
break;
}
if ((framesIn == 100) && (SyncInCount<45)) { // prefer frame sync
break;
}
}
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");
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);
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;
}
}
} else { // released
logButtonUpTime = inputTimer.read();
}
logButtonLastState = logButton;
}
}
}