Merge remote-tracking branch 'upstream/master' into reset-overlap
This commit is contained in:
commit
c7d6b7f6cd
|
@ -36,7 +36,15 @@ jobs:
|
||||||
git config --local user.email "action@github.com"
|
git config --local user.email "action@github.com"
|
||||||
git config --local user.name "GitHub build-firmware Action"
|
git config --local user.name "GitHub build-firmware Action"
|
||||||
git status
|
git status
|
||||||
git commit -am "Auto-generated configs and docs" 2>&1 | grep -E '(nothing to commit|changed)'
|
OUT=$(git commit -am "Auto-generated configs and docs" 2>&1) || echo "commit failed, finding out why"
|
||||||
|
if echo "$OUT" | grep 'nothing to commit'; then
|
||||||
|
echo "::set-env name=NOCOMMIT::true"
|
||||||
|
exit 0
|
||||||
|
elif echo "$OUT" | grep 'changed'; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# We need to know what branch this is in order to push to the correct branch
|
# We need to know what branch this is in order to push to the correct branch
|
||||||
- name: Extract branch name
|
- name: Extract branch name
|
||||||
|
@ -45,6 +53,7 @@ jobs:
|
||||||
id: extract_branch
|
id: extract_branch
|
||||||
|
|
||||||
- name: Push configs
|
- name: Push configs
|
||||||
|
if: ${{env.NOCOMMIT != 'true'"}}
|
||||||
uses: ad-m/github-push-action@master
|
uses: ad-m/github-push-action@master
|
||||||
with:
|
with:
|
||||||
github_token: ${{ github.token }}
|
github_token: ${{ github.token }}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* @file logicdata.cpp
|
* @file logicdata.cpp
|
||||||
*
|
*
|
||||||
|
* Based on LogicdataStreamFile.java by andreika
|
||||||
|
*
|
||||||
* Created on: Jul 19, 2020
|
* Created on: Jul 19, 2020
|
||||||
* @author Andrey Belomutskiy, (c) 2012-2020
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
||||||
*/
|
*/
|
||||||
|
@ -8,11 +10,474 @@
|
||||||
#include "logicdata.h"
|
#include "logicdata.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void writeFile() {
|
#define frequency 1000000
|
||||||
|
#define frequencyDiv 10
|
||||||
|
#define magic 0x7f
|
||||||
|
|
||||||
FILE *ptr = fopen("test.logicdata", "wb");
|
#define BLOCK 0x15
|
||||||
|
#define CHANNEL_BLOCK 0x16
|
||||||
|
#define SUB 0x54
|
||||||
|
|
||||||
|
#define title "Data save2"
|
||||||
|
|
||||||
|
#define FLAG_NOTEMPTY 2
|
||||||
|
#define FLAG_NOTEMPTY_LONG 3
|
||||||
|
#define FLAG_EMPTY 5
|
||||||
|
|
||||||
|
#define LOGIC4 0x40FD
|
||||||
|
#define LOGIC8 0x673B
|
||||||
|
|
||||||
|
#define SIGN_FLAG 0x80000000L
|
||||||
|
|
||||||
|
#define numChannels 6
|
||||||
|
#define reservedDurationInSamples 10
|
||||||
|
|
||||||
|
#define MAX_STRING_SIZE 40
|
||||||
|
|
||||||
|
static char channelNames[][MAX_STRING_SIZE] = { "Primary", "Secondary", "Trg",
|
||||||
|
"Sync", "Coil", "Injector", "Channel 6", "Channel 7" };
|
||||||
|
|
||||||
|
static int CHANNEL_FLAGS[] = { 0x13458b, 0x0000ff, 0x00a0f9, 0x00ffff, 0x00ff00,
|
||||||
|
0xff0000, 0xf020a0, };
|
||||||
|
|
||||||
|
static FILE *ptr;
|
||||||
|
|
||||||
|
static int realDurationInSamples;
|
||||||
|
static int scaledDurationInSamples;
|
||||||
|
|
||||||
|
static void writeByte(uint8_t value) {
|
||||||
|
fwrite(&value, 1, sizeof(value), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeAs(int64_t value, int numBytes) {
|
||||||
|
if (value == 0) {
|
||||||
|
writeByte(0);
|
||||||
|
} else {
|
||||||
|
writeByte(numBytes);
|
||||||
|
for (int i = 0; i < numBytes; i++) {
|
||||||
|
writeByte((uint8_t)((value >> (i * 8)) & 0xff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeString(const char *value) {
|
||||||
|
int len = strlen(value);
|
||||||
|
writeByte(len);
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
writeByte(value[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the main secret of this format! :)
|
||||||
|
static void write(int64_t value) {
|
||||||
|
if (value < 0 || value > 0xFFFFFFFFL) {
|
||||||
|
writeAs(value, 8);
|
||||||
|
} else if (value == 0) {
|
||||||
|
writeByte(0);
|
||||||
|
} else if (value <= 0xff) {
|
||||||
|
writeAs(value, 1);
|
||||||
|
} else if (value <= 0xffff) {
|
||||||
|
writeAs(value, 2);
|
||||||
|
} else if (value <= 0xffffff) {
|
||||||
|
writeAs(value, 3);
|
||||||
|
} else {
|
||||||
|
writeAs(value, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: some C++ magic would allow us to drop 'count' parameter
|
||||||
|
// todo: Look at efi::size in util
|
||||||
|
static void write(int values[], int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
write(values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(int value, int num) {
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeId(int i1, int i2) {
|
||||||
|
write((numChannels == 4) ? LOGIC4 : LOGIC8);
|
||||||
|
write(i1);
|
||||||
|
write(i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeHeader() {
|
||||||
|
writeByte(magic);
|
||||||
|
write(strlen(title));
|
||||||
|
writeString(title);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(SUB);
|
||||||
|
write(frequency);
|
||||||
|
write(0);
|
||||||
|
write(reservedDurationInSamples);
|
||||||
|
write(frequency / frequencyDiv);
|
||||||
|
write(0, 2);
|
||||||
|
write(numChannels);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
for (int i = 0; i < numChannels; i++) {
|
||||||
|
writeId(i, 1);
|
||||||
|
}
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
|
||||||
|
writeId(0, 0);
|
||||||
|
write(0);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeChannelHeader(int ch) {
|
||||||
|
write(0xff);
|
||||||
|
write(ch);
|
||||||
|
writeString(channelNames[ch]);
|
||||||
|
write(0, 2);
|
||||||
|
write(1.0);
|
||||||
|
write(0);
|
||||||
|
write(0.0);
|
||||||
|
write(1); // or 2
|
||||||
|
write(0.0); // or 1.0
|
||||||
|
|
||||||
|
// this part sounds like the 'next' pointer?
|
||||||
|
if (ch == numChannels - 1) {
|
||||||
|
write(0);
|
||||||
|
} else {
|
||||||
|
writeId(1 + ch, 1);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
write((CHANNEL_FLAGS[ch] >> (i * 8)) & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeEdges(int64_t *chDeltas, bool useLongDeltas, int numEdges) {
|
||||||
|
for (int i = 0; i < numEdges; i++) {
|
||||||
|
uint64_t d = chDeltas[i];
|
||||||
|
|
||||||
|
// set 16-bit 'sign' flag
|
||||||
|
if (!useLongDeltas && (d & SIGN_FLAG) == SIGN_FLAG)
|
||||||
|
d = (d & 0x7fff) | (SIGN_FLAG >> 16);
|
||||||
|
writeByte((uint8_t)(d & 0xff));
|
||||||
|
writeByte((uint8_t)((d >> 8) & 0xff));
|
||||||
|
if (useLongDeltas) {
|
||||||
|
writeByte((uint8_t)((d >> 16) & 0xff));
|
||||||
|
writeByte((uint8_t)((d >> 24) & 0xff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeByte(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeRaw(int value, int num) {
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
writeByte(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeChannelData(int ch, int64_t *chDeltas, int chLastState,
|
||||||
|
int lastRecord, bool useLongDeltas, int numEdges) {
|
||||||
|
if (numEdges == 0)
|
||||||
|
lastRecord = 0;
|
||||||
|
write(CHANNEL_BLOCK);
|
||||||
|
// channel#0 is somehow special...
|
||||||
|
if (ch == 0) {
|
||||||
|
write(SUB);
|
||||||
|
write(BLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(ch + 1);
|
||||||
|
write(0);
|
||||||
|
write(realDurationInSamples);
|
||||||
|
write(1);
|
||||||
|
write(lastRecord);
|
||||||
|
|
||||||
|
int numSamplesLeft = realDurationInSamples - lastRecord;
|
||||||
|
write(numSamplesLeft);
|
||||||
|
|
||||||
|
write(chLastState);
|
||||||
|
|
||||||
|
int chFlag =
|
||||||
|
(numEdges == 0) ?
|
||||||
|
FLAG_EMPTY :
|
||||||
|
(useLongDeltas ? FLAG_NOTEMPTY_LONG : FLAG_NOTEMPTY);
|
||||||
|
write(chFlag);
|
||||||
|
|
||||||
|
if (ch == 0) {
|
||||||
|
write(0);
|
||||||
|
write(BLOCK);
|
||||||
|
write(0, 11);
|
||||||
|
if (useLongDeltas) {
|
||||||
|
write(BLOCK);
|
||||||
|
write(0, 6);
|
||||||
|
}
|
||||||
|
write(BLOCK);
|
||||||
|
} else {
|
||||||
|
write(0, 10);
|
||||||
|
if (useLongDeltas) {
|
||||||
|
write(0, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write(numEdges);
|
||||||
|
write(0);
|
||||||
|
write(numEdges);
|
||||||
|
write(0);
|
||||||
|
write(numEdges);
|
||||||
|
|
||||||
|
writeEdges(chDeltas, useLongDeltas, numEdges);
|
||||||
|
|
||||||
|
if (ch == 0) {
|
||||||
|
write(BLOCK);
|
||||||
|
write(0, 6);
|
||||||
|
if (!useLongDeltas) {
|
||||||
|
write(BLOCK);
|
||||||
|
write(0, 6);
|
||||||
|
}
|
||||||
|
write(BLOCK);
|
||||||
|
} else {
|
||||||
|
write(0, 4);
|
||||||
|
if (!useLongDeltas) {
|
||||||
|
write(0, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numEdges == 0) {
|
||||||
|
write(0, 5);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(1);
|
||||||
|
write(0);
|
||||||
|
write(1);
|
||||||
|
write(0);
|
||||||
|
write(1);
|
||||||
|
write(0, 16);
|
||||||
|
|
||||||
|
writeRaw(0xFF, 8);
|
||||||
|
writeRaw(chFlag, 1);
|
||||||
|
writeRaw(0x00, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeChannelDataHeader() {
|
||||||
|
write(BLOCK);
|
||||||
|
write(scaledDurationInSamples);
|
||||||
|
write(0, 5);
|
||||||
|
write(numChannels);
|
||||||
|
write(0, 3);
|
||||||
|
writeId(0, 1);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0, 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < numChannels; i++) {
|
||||||
|
writeChannelHeader(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
int SUB_ARRAY[] = { SUB, SUB, 0, SUB, 0, SUB };
|
||||||
|
write(SUB_ARRAY, 6);
|
||||||
|
write(0, 6);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0, 2);
|
||||||
|
write(realDurationInSamples);
|
||||||
|
write(0);
|
||||||
|
write(SUB);
|
||||||
|
write(reservedDurationInSamples);
|
||||||
|
write(frequency / frequencyDiv);
|
||||||
|
write(0, 2);
|
||||||
|
write(SUB);
|
||||||
|
write(0, 2);
|
||||||
|
write(1);
|
||||||
|
write(0, 3);
|
||||||
|
writeId(0, 0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
int SAM_ARRAY[] = { realDurationInSamples, realDurationInSamples,
|
||||||
|
realDurationInSamples };
|
||||||
|
write(SAM_ARRAY, 3);
|
||||||
|
write(0);
|
||||||
|
write(SUB);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(SUB, 4);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(frequency);
|
||||||
|
write(0, 3);
|
||||||
|
write(1);
|
||||||
|
write(0, 3);
|
||||||
|
writeId(0, 0);
|
||||||
|
int ARR_6[] = { 0, 1, 1, 0, 1, 0x13 };
|
||||||
|
write(ARR_6, 6);
|
||||||
|
write(SUB);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0);
|
||||||
|
write(realDurationInSamples);
|
||||||
|
write(0, 2);
|
||||||
|
write(numChannels);
|
||||||
|
int ARR_3[] = { 1, 0, 1 };
|
||||||
|
write(ARR_3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeTimingMarker() {
|
||||||
|
write(BLOCK);
|
||||||
|
write(numChannels + 2);
|
||||||
|
write(0, 4);
|
||||||
|
writeString("Timing Marker Pair");
|
||||||
|
writeString("A1");
|
||||||
|
writeString("A2");
|
||||||
|
write(0, 2);
|
||||||
|
write(SUB);
|
||||||
|
write(0, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeChannelDataFooter() {
|
||||||
|
write(0, 3);
|
||||||
|
write(1);
|
||||||
|
write(1);
|
||||||
|
write(0);
|
||||||
|
write(numChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getChannelState(int ch, CompositeEvent *event) {
|
||||||
|
switch (ch) {
|
||||||
|
case 0:
|
||||||
|
return event->primaryTrigger;
|
||||||
|
case 1:
|
||||||
|
return event->secondaryTrigger;
|
||||||
|
case 2:
|
||||||
|
return event->trg;
|
||||||
|
case 3:
|
||||||
|
return event->sync;
|
||||||
|
case 4:
|
||||||
|
return event->coil;
|
||||||
|
case 5:
|
||||||
|
return event->injector;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeEvents(CompositeEvent *events, int count) {
|
||||||
|
// we need at least 2 records
|
||||||
|
if (count < 2)
|
||||||
|
return;
|
||||||
|
int firstRecordTs = events[1].timestamp;
|
||||||
|
int lastRecordTs = events[count - 1].timestamp;
|
||||||
|
// we don't know the total duration, so we create a margin after the last record which equals to the duration of the first event
|
||||||
|
realDurationInSamples = lastRecordTs + firstRecordTs;
|
||||||
|
scaledDurationInSamples = realDurationInSamples / 4;
|
||||||
|
|
||||||
|
writeChannelDataHeader();
|
||||||
|
|
||||||
|
int64_t *chDeltas = (int64_t*) malloc(sizeof(int64_t) * count);
|
||||||
|
int deltaCount = 0;
|
||||||
|
|
||||||
|
bool useLongDeltas = false;
|
||||||
|
for (int ch = 0; ch < numChannels; ch++) {
|
||||||
|
int chPrevState = -1;
|
||||||
|
int prevTs = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
CompositeEvent *event = &events[i];
|
||||||
|
|
||||||
|
int chState = getChannelState(ch, event);
|
||||||
|
int ts = event->timestamp;
|
||||||
|
|
||||||
|
if (chPrevState == -1) {
|
||||||
|
chPrevState = chState;
|
||||||
|
}
|
||||||
|
if (chState != chPrevState) {
|
||||||
|
long delta = ts - prevTs;
|
||||||
|
if (delta > 0x7fff) {
|
||||||
|
useLongDeltas = true;
|
||||||
|
}
|
||||||
|
// encode state
|
||||||
|
if (chState == 0)
|
||||||
|
delta |= SIGN_FLAG;
|
||||||
|
|
||||||
|
chDeltas[deltaCount++] = delta;
|
||||||
|
|
||||||
|
prevTs = ts;
|
||||||
|
chPrevState = chState;
|
||||||
|
}
|
||||||
|
writeChannelData(ch, chDeltas, chPrevState, prevTs, useLongDeltas,
|
||||||
|
deltaCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(chDeltas);
|
||||||
|
|
||||||
|
writeChannelDataFooter();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeFooter() {
|
||||||
|
write(BLOCK);
|
||||||
|
for (int i = 0; i < numChannels; i++) {
|
||||||
|
writeId(i, 1);
|
||||||
|
}
|
||||||
|
write(1);
|
||||||
|
writeId(numChannels, 0x15);
|
||||||
|
for (int i = 0; i < numChannels; i++) {
|
||||||
|
writeId(i, 1);
|
||||||
|
}
|
||||||
|
write(1);
|
||||||
|
write(0);
|
||||||
|
write(frequency);
|
||||||
|
write(0, 16);
|
||||||
|
write(0x01);
|
||||||
|
write(0x23); // ???
|
||||||
|
write(SUB);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(numChannels + 1);
|
||||||
|
write(0);
|
||||||
|
write(0xFFFFFFFFFFFFFFFFL);
|
||||||
|
write(0xFFFFFFFFL);
|
||||||
|
write(1);
|
||||||
|
write(0, 3);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0);
|
||||||
|
|
||||||
|
write(BLOCK);
|
||||||
|
write(0);
|
||||||
|
write(1.0);
|
||||||
|
write(SUB);
|
||||||
|
write(0, 6);
|
||||||
|
write(1);
|
||||||
|
write(0, 4);
|
||||||
|
|
||||||
|
write(1);
|
||||||
|
write(0x29); // ???
|
||||||
|
write(SUB);
|
||||||
|
|
||||||
|
writeTimingMarker();
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeFile(CompositeEvent *events, int count) {
|
||||||
|
|
||||||
|
ptr = fopen("test.logicdata", "wb");
|
||||||
|
|
||||||
|
writeHeader();
|
||||||
|
writeEvents(events, count);
|
||||||
|
writeFooter();
|
||||||
|
|
||||||
fclose(ptr);
|
fclose(ptr);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* @file logicdata.h
|
||||||
|
*
|
||||||
|
* Created on: Jul 19, 2020
|
||||||
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct CompositeEvent {
|
||||||
|
int timestamp;
|
||||||
|
bool primaryTrigger;
|
||||||
|
bool secondaryTrigger;
|
||||||
|
bool trg;
|
||||||
|
bool sync;
|
||||||
|
bool coil;
|
||||||
|
bool injector;
|
||||||
|
};
|
||||||
|
|
||||||
|
void writeFile(CompositeEvent *events, int count);
|
|
@ -2,10 +2,27 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "logicdata.h"
|
#include "logicdata.h"
|
||||||
|
|
||||||
|
static CompositeEvent events[100];
|
||||||
|
|
||||||
|
|
||||||
|
void setEvent(CompositeEvent *events, int index,
|
||||||
|
int timestamp, bool primaryTrigger, bool secondaryTrigger, bool trg, bool sync, bool coil, bool injector) {
|
||||||
|
events[index].timestamp = timestamp;
|
||||||
|
events[index].primaryTrigger = primaryTrigger;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
printf(".logicdata Sandbox 20200719\n");
|
printf(".logicdata Sandbox 20200719\n");
|
||||||
|
|
||||||
writeFile();
|
|
||||||
|
int index = 0;
|
||||||
|
setEvent(events, index++, 10, false, false, false, false, false, false);
|
||||||
|
setEvent(events, index++, 20, true, false, true, false, false, false);
|
||||||
|
setEvent(events, index++, 30, false, false, false, false, false, false);
|
||||||
|
setEvent(events, index++, 1000030, false, false, false, false, true, false);
|
||||||
|
setEvent(events, index++, 2000030, false, false, true, false, false, true);
|
||||||
|
|
||||||
|
writeFile(events, index);
|
||||||
|
|
||||||
printf("Done!\n");
|
printf("Done!\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue