예전에 조사하여 만든 AVR / atmega용 MDF 화일 저장 코드
우선 필요한 건 MDF 화일 정보
구글링
필요한 파일 : ASAM 화일임 클릭해서 다운
ASAM MCD-2MC Version 1.6 Measurement and ... - Read
준비할 것 : FatFs (AVR용 FAT 시스템 모듈)
FatFs Module
October 14, 2019
MDF 화일 기록 예제
// --------------------------------------------------------------------------
void testMDF(FIL *fp){
UINT16 BitLoc, measTime = 0;
uint8_t bitWidthDummy, ndx, n;
uint8_t noFR = 20;
uint32_t tValueECU, tFRdataRecordsNo = 0;
writeMDFInfo(fp, cRuleFRxUDS, noFR);
tValueECU = 0;
for(int nMDF=0; nMDF<noFR; nMDF++){
BitLoc = 0;
ndx = 0;
n = 0;
writeMDFbuffClear();
// time is converted by P1/P2 in CC Block info
// smapling rate is not used (?)
measTime++;
writeMDFtime(fp, &measTime);
// time = 64 bit (uint64_t)
for(int nXUDS = 0; nXUDS<noFR; nXUDS++){
tValueECU++;
ndx = writeMDFData(cRuleFRxUDS[nXUDS], BitLoc, tValueECU);
BitLoc += ndx;
n++;
}
tFRdataRecordsNo++;
writeMDF2File(fp);
}
writeCGrecordsNo(fp, &tFRdataRecordsNo);
}
// ---------------------------------------------------------------------------
필요한 LIB 코드 : testMDF.c 내용중에서 writeXXX 관련 함수는 참조
// ---------------------------------------------------------------------------
// uCAN - HMC CAN / UDS (GM Lan later) / GST / CARB
// ---------------------------------------------------------------------------
#define FirmwareV "uCAN_V07AI0_20141025"
#define FIRMWAREHEADER "uCAN "
#define FIRMWAREVER "V07AI0"
// ---------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include "uart.h"
#include "clock.h"
#include "GKS0108E.h" // 2014.06.20
// ----------------------------------------------------------------------------
#define LINE_MAXLEN 100
#define BELL 7
#define CR 13
#define LR 10
// --------------------------------------------------------------------------
#define XUDS_NO 45 // V01AN2 : 50 strange / 40 OK
// --------------------------------------------------------------------------
typedef struct{ // Send y=(f*INT-c)/b as y=(f*INT-c) * 1/b
uint8_t ECUaddr[4]; // V07AD : store as 4 HEX not string
char RuleName[11]; // like "VB=", only for Flight Record
uint8_t TypeInfoA; // tt ff x ddd = tt(K=01,U=10), ff(A=0,B=1,C=2) x ddd(1,2,4)
float b_factor; // 1/b : long long = +/- x.xx * 10^xx
float c_factor; //
float f_factor; // if 1.0 --> use formula 'B'
}ConvRuleXUDS; // for CAN recording RAM cells
ConvRuleXUDS cRuleFRxUDS[XUDS_NO] ; // 40 = 1080 Bytes (27 bytes/message)
int noRuleFR; // received cRuleFRxUDS for 'FR'
ConvRuleXUDS cRuleFRxUDSEE[XUDS_NO] EEMEM;
const ConvRuleXUDS cRuleFRxUDSInit PROGMEM = // Just for EEMEM init
{{0xd0,0x7F,0xAC,0xA6}, "N", 0x52, 1.0, 0, 1.0};
// --------------------------------------------------------------------------
ConvRuleXUDS cRuleSnapShot; // V01AG - Only for snap shot
char SnapShotName[33]; // V01AN - snapshot name max len=32
// --------------------------------------------------------------------------
// MDF 3.0 related definitions
// --------------------------------------------------------------------------
// http://class.ece.iastate.edu/arun/CprE281_F05/ieee754/ie5.html
// http://stackoverflow.com/questions/16808069/
// how-to-convert-float-to-ieee754-double-precision-format-by-using-union-and-struc
// http://en.wikipedia.org/wiki/Double-precision_floating-point_format
// http://forum.pololu.com/viewtopic.php?f=23&t=1953
// --------------------------------------------------------------------------
// IEEE754 DP(64bit): sign exponent(11) fraction(52) NOTE : Intel is MSB first
// s eeeeeeeeeee fffffffff.........fffff
// IEEE754 SP(32bit): sign exponent(8) fraction(23)
// s eeeeeeee fffff.......fff
// --------------------------------------------------------------------------
union FloatDPieee754 { // IEEE 754, double precision (64 bits)
struct {
uint64_t mantissa : 52;
uint64_t exponent : 11;
uint64_t sign : 1;
} raw;
double d;
} numREAL; // for 'REAL'
// --------------------------------------------------------------------------
// CHAR, UINT8, UINT16, UINT32 ---> use : char, uint8_t, uint16_t, uint32_t
typedef uint16_t BOOL; // 16bit : 0 = FALSE, else TRUE
typedef uint16_t UINT16;
typedef uint32_t UINT32;
typedef int32_t LINK; // 32-bit signed integer, used as byte position
typedef long long REAL; // IEEE 754, double precision (64 bits)
unsigned int _ValueECU; // V01AP
// --------------------------------------------------------------------------
// http://forum.pololu.com/viewtopic.php?f=23&t=1953
// Generating a 64-bit Double on an AVR
// --------------------------------------------------------------------------
union floatBytes{
double f;
unsigned long b;
};
// ----------------------------------------------------------------------------
unsigned char parseHex(char * line, unsigned char len, unsigned long * value);
void parseLine(char * line);
int parseConvRule(char textLine[]);
//void OBD2Request(int menu);
void DisplayHex(int x, int y, char str[], int len, uint8_t fsize,uint8_t color);
void DisplayStr(uint8_t x,uint8_t y, char * str,uint8_t size,uint8_t color);
void sendByteHex(unsigned char value);
char *sendHex(unsigned long value, unsigned char len);
void InitPort(void);
// ----------------------------------------------------------------------------
// PORTC/D - GLCD, PORTG0/1/2 = SW
// ----------------------------------------------------------------------------
void InitPort(void){
// PB0 (SS) should be high to enable SPI master - done in mcp2515_init
DDRA = 0xFF; // PORTA for CRK/CAM out put
PORTA = 0x00;
DDRF = 0xFF; // PORTF output
PORTF = 0xFF;
DDRG = 0xF0; // PORTG 0.1.2.3 = SW In
PORTG = 0x0F; // in case of input, pull up - Bug fix
}
// ----------------------------------------------------------------------------
// To make easy to switch between LCDputsXY() and GLCD_WriteStr()
void DisplayStr(uint8_t x,uint8_t y, char * str,uint8_t size,uint8_t color){
// GLCD_GoTo(0,1); // x(col) = dot, y(row) = dot
GLCD_WriteStr(x, y, str, size, color); // SMALL/BIG, WHITE/BLACK
}
// ----------------------------------------------------------------------------
// To make easy to switch between LCDputsXY() and GLCD_WriteStr()
// ----------------------------------------------------------------------------
void DisplayHex(int x, int y, char str[], int len, uint8_t fsize,uint8_t color){
// GLCD_GoTo(0,1); // x(col) = dot, y(row) = dot
unsigned char i;
char s[21], buf[3];
strcpy(s, "");
if(len > 20) len = 10; // restrict the array size
for(i=0; i<len; i++){
sprintf_P(buf, PSTR("%02X"), str[i]);
strncat(s, buf, 2);
}
GLCD_WriteStr(x, y, s, fsize, color); // SMALL/BIG, WHITE/BLACK
}
// ---------------------------------------------------------------------------
/**
* Parse hex value of given string
*
* @param line Input string
* @param len Count of characters to interpret
* @param value Pointer to variable for the resulting decoded value
* @return 0 on error, 1 on success
*/
unsigned char parseHex(char * line, unsigned char len, unsigned long * value){
*value = 0;
while (len--) {
if (*line == 0) return 0;
*value <<= 4;
if ((*line >= '0') && (*line <= '9')) {
*value += *line - '0';
} else if ((*line >= 'A') && (*line <= 'F')) {
*value += *line - 'A' + 10;
} else if ((*line >= 'a') && (*line <= 'f')) {
*value += *line - 'a' + 10;
} else return 0;
line++;
}
return 1;
}
// ---------------------------------------------------------------------------
void parseLine(char * line){
unsigned long cnf1, cnf2, cnf3;
unsigned long am0, am1, am2, am3;
unsigned long ac0, ac1, ac2, ac3;
unsigned long stamping; // address, data,
unsigned char result = BELL; // flags, status, value
char Buffer[51];
int tempWinNo, makeRtn, CANBlockNo, errNo; // V01A9
tCAN canmsg, can_mM[10], canSendM[2]; // V06A5
uint8_t btValue;
switch(line[0]){
// ----------------------------------------------------------------------
// single char commands ... 'c@#xx\r'
// ----------------------------------------------------------------------
case 'c':
if(line[1] != '@' || line[2] != '#') break; // V01Ai
result = CR;
switch(line[3]){
case 'V': // Get versions
//usb_putch('V');
uart_puts(FirmwareV);
//sendByteHex(VERSION_HARDWARE);
//sendByteHex(VERSION_FIRMWARE_MAJOR);
result = CR;
break;
case 'O': // Open CAN channel // set normal operating mode
default: result = BELL;
break;
} // end inner switch for case 'c'
break; // end case 'c':
default: break;
} // End main switch
uart_putc(result);
//mcp2515_static_filter(can_filter_ALL);// V04B // set to receive all message
}
// --------------------------------------------------------------------------
REAL doubleUp(union floatBytes float32){
unsigned char sign = (float32.b>>31)&0x01;
unsigned long fraction = float32.b&0x007FFFFF;
unsigned long exponent = (float32.b>>23)&0xFF;
if((float32.b&0x7FFFFFFF)==0) //special case for +/- 0
return (((long long)sign)<<63);
if(exponent==0xFF) //special case for +/- infinity, NAN
return (((long long)sign)<<63)|0x7FF0000000000000|(((long long)fraction)<<29);
exponent = exponent+1023-127;
return (((long long)sign)<<63)|(((long long)exponent)<<52)|(((long long)fraction)<<29);
}
// --------------------------------------------------------------------------
// double float32 = -7.51e-32;
// long long float64 = doubleUp((union floatBytes)float32);
// --------------------------------------------------------------------------
void writeIDBlock(FIL fp){ // Block length = 64
UINT16 n, byteOrder, useFloat, versionNo, reserved;
UINT byteWrite;
char buff[10];
sprintf(buff, PSTR("MDF ")); // File ID
f_write(&fp, buff, 8, &byteWrite); // Write to file
sprintf(buff, PSTR("3.0 ")); // Format ID
f_write(&fp, buff, 8, &byteWrite); // Write to file
sprintf(buff, PSTR("uTFTCAN ")); // Program ID
f_write(&fp, buff, 8, &byteWrite); // Write to file
byteOrder = 0; // Little endian
f_write(&fp, &byteOrder, 2, &byteWrite);
useFloat = 0; // 0 = Floating-point format : IEEE 754 standard // Little endian
f_write(&fp, &useFloat, 2, &byteWrite);
versionNo = 300; // MDF version
f_write(&fp, &versionNo, 2, &byteWrite);
reserved = 0; // Reserved
f_write(&fp, &reserved, 2, &byteWrite);
for(n=0; n<32; n++) // Reserved 32 char
f_write(&fp, " ", 1, &byteWrite);
//f_lseek(&fp, f_size(&fp)); // move to end
//f_sync(&fp_uCAN);
}
// --------------------------------------------------------------------------
void writeHDBlock(FIL fp){
UINT byteWrite;
char buff[33];
UINT16 BlockSize = 0xA4; // Block size = 164
UINT16 DGroupsNo = 1; // Number of data groups
LINK ptr1stDGBlock = 0xA4 + 64; // aftr ID & HD
LINK ptrTXBlock = 0; // option - no use
LINK ptrPRBlock = 0; // option - no use
sprintf(buff, PSTR("HD")); // Block Type
f_write(&fp, buff, 2, &byteWrite);
f_write(&fp, &BlockSize, sizeof(UINT16), &byteWrite); // Block size
f_write(&fp, &ptr1stDGBlock, sizeof(LINK), &byteWrite);
f_write(&fp, &ptrTXBlock, sizeof(LINK), &byteWrite);
f_write(&fp, &ptrPRBlock, sizeof(LINK), &byteWrite);
f_write(&fp, &DGroupsNo, sizeof(UINT16), &byteWrite);
sprintf(buff, PSTR("31:10:2014")); // Date
f_write(&fp, buff, 10, &byteWrite);
sprintf(buff, PSTR("12:10:00")); // time
f_write(&fp, buff, 8, &byteWrite);
sprintf(buff, PSTR("xxxxxxxxxxx "));// Author’s name
f_write(&fp, buff, 32, &byteWrite);
sprintf(buff, PSTR("Test xxxxxx xxx "));// department
f_write(&fp, buff, 32, &byteWrite);
sprintf(buff, PSTR("CAN Protocol "));// Project name
f_write(&fp, buff, 32, &byteWrite);
sprintf(buff, PSTR("uTFTCAN "));// vehicle identification
f_write(&fp, buff, 32, &byteWrite);
}
// --------------------------------------------------------------------------
// no use TXBlock & PRBlock which are variable size
// Contains actual measurement data for one(“sorted”) or several(“unsorted”) channel groups.
// - Number of channel groups
// - Number of record Ids 0 (i.e., sorted writing)
// - Pointer to data records
// --------------------------------------------------------------------------
void writeDGBlock(FIL fp){
UINT byteWrite;
char buff[10];
UINT16 BlockSize = 0x1C; // Block size = 28
UINT16 CNGroupsNo = 1; // Number of channel groups
UINT16 RecordIDno = 0; // Number of record Ids : 0=sorted
UINT16 Reserved16 = 0;
LINK ptrNextDGBlock = 0; // no more DG Blocks
LINK ptr1stCGBlock = (64+0xA4+0x1C); // after ID+HD+DG
LINK ReservedLINK = 0;
// if other CC then adjust coz time channel is added
LINK ptrDataRecord = (64+0xA4+0x1C+0x1A) + (XUDS_NO+1)*(0xE4+0x3E);
sprintf(buff, PSTR("DG")); // Block Type
f_write(&fp, buff, 2, &byteWrite);
f_write(&fp, &BlockSize, sizeof(UINT16), &byteWrite); // Block size
f_write(&fp, &ptrNextDGBlock, sizeof(LINK), &byteWrite);
f_write(&fp, &ptr1stCGBlock, sizeof(LINK), &byteWrite);
f_write(&fp, &ReservedLINK, sizeof(LINK), &byteWrite);
f_write(&fp, &ptrDataRecord, sizeof(LINK), &byteWrite);
f_write(&fp, &CNGroupsNo, sizeof(UINT16), &byteWrite);
f_write(&fp, &RecordIDno, sizeof(UINT16), &byteWrite);
f_write(&fp, &Reserved16, sizeof(UINT16), &byteWrite); // reserved UINT32
f_write(&fp, &Reserved16, sizeof(UINT16), &byteWrite);
}
// --------------------------------------------------------------------------
// channel group : different ch's which measured jointly at the same rate
// - Pointer to first channel block (CNBLOCK) (NIL allowed)
// - Record ID : measured same rate --> same record ID
// - Number of channels : XUDS_NO
// - Record size in bytes : size of XUDS_NO ?? (bit ??)
// - Number of records : No of measured records of this CN Group
// IMPORTANT : as 'RecordsNo' is unknown at start, it should be corrected
// --------------------------------------------------------------------------
void writeCGBlock(FIL fp, UINT16 recordSize){ // start = 64+0xA4+0x1C
UINT byteWrite;
char buff[10];
UINT16 BlockSize = 0x1A; // Block size = 26
LINK ptrNextCGBlock = 0; // no more CG Blocks
LINK ptr1stCNBlock = (64+0xA4+0x1C+0x1A); // after ID+HD+DG+CG
LINK ptrCNcomment = 0;
UINT16 RecordID = 1; // Record ID
UINT16 ChannelNo = XUDS_NO;
UINT16 RecordSize = recordSize; // Record size in bytes
uint32_t RecordsNo; // Number of records
sprintf(buff, PSTR("CG")); // Block Type
f_write(&fp, buff, 2, &byteWrite);
f_write(&fp, &BlockSize, sizeof(UINT16), &byteWrite); // Block size
f_write(&fp, &ptrNextCGBlock, sizeof(LINK), &byteWrite);// no more CG
f_write(&fp, &ptr1stCNBlock, sizeof(LINK), &byteWrite);
f_write(&fp, &ptrCNcomment, sizeof(LINK), &byteWrite); // no use
f_write(&fp, &RecordID, sizeof(UINT16), &byteWrite);
f_write(&fp, &ChannelNo, sizeof(UINT16), &byteWrite);
f_write(&fp, &RecordSize, sizeof(UINT16), &byteWrite); // TO BE 'PRE' assigned
f_write(&fp, &RecordsNo, sizeof(uint32_t), &byteWrite); // TO BE 'PRE' assigned
}
// --------------------------------------------------------------------------
// Info for each signal channel : each FR --- nextCNB can be NULL
// Writing order : CNBlock/CCBlock ... ==> CN0CC0 CN1CC1 CN2CC2 ...
// chnType : 0 = data, 1 = time, 2 = dummy
// --------------------------------------------------------------------------
UINT16 writeCNBlock(FIL fp, ConvRuleXUDS xUDS, LINK thisCNB, LINK nextCNB, UINT16 chnType, UINT16 bitPos){
UINT byteWrite, n;
char buff[33];
UINT16 BlockSize = 0xE4; // Block size = 228
UINT16 BitWidth, SignalDataType = 0; // unsigned integer
UINT16 ByteOffset = 0;
LINK ptrCCBlock; // Conversion formula
LINK ReservedLINK = 0;
BOOL ValueRange = 0; // FALSE
REAL ValueMin, TimeInterval; // no use so skip Max
double f32VMin = 0, f32time = 0.01;
sprintf(buff, PSTR("CN")); // Block Type
f_write(&fp, buff, 2, &byteWrite);
f_write(&fp, &BlockSize, sizeof(UINT16), &byteWrite); // Block size
f_write(&fp, &nextCNB, sizeof(LINK), &byteWrite); // caller set it
// -----------------------------------------------------------------
ptrCCBlock = thisCNB + BlockSize; // CC position
f_write(&fp, &ptrCCBlock, sizeof(LINK), &byteWrite); //
f_write(&fp, &ReservedLINK, sizeof(LINK), &byteWrite); // reserved
f_write(&fp, &ReservedLINK, sizeof(LINK), &byteWrite); // reserved
f_write(&fp, &ReservedLINK, sizeof(LINK), &byteWrite); // CN comment - no use
f_write(&fp, &chnType, sizeof(UINT16), &byteWrite); // 0/1 : data or time
// -----------------------------------------------------------------
// write signal discription
if(chnType == 1) // ---------- Time channel ------------------
sprintf(buff, PSTR("time "));
else if(chnType == 2) // ---------- dummy channel ------------------
sprintf(buff, PSTR("dummy "));
else
sprintf(buff, PSTR("%10s "), xUDS.RuleName);
f_write(&fp, buff, 32, &byteWrite);
sprintf(buff, PSTR(" ")); // Signal description
for(n=0; n<10; n++) f_write(&fp, buff, 12, &byteWrite); // description
// -----------------------------------------------------------------
f_write(&fp, &bitPos, sizeof(UINT16), &byteWrite); // start bit position
// -----------------------------------------------------------------
// ETAS save 'time' as 'IEEE 754 floating-point format' in 64bit P1=1.0, P2=0
// but UINT64 can be used ??
// Here Type 'D' must be saved as one 'BIT'
// chnType : 0 = data, 1 = time, 2 = dummy
if(chnType == 1) BitWidth = 64;
else BitWidth = (UINT16) (xUDS.TypeInfoA & 0x07) * 8;
if(xUDS.TypeInfoA & 0x30) BitWidth = 1; // type 'D'
if(chnType == 2){
if(bitPos % 8) BitWidth = 8 - bitPos % 8; // dummy width
else BitWidth = 8; // no need but have to add
}
f_write(&fp, &BitWidth, sizeof(UINT16), &byteWrite);
// -----------------------------------------------------------------
// try use 'unsigned integer' for 'time' too : SignalDataType = 0
//if(chnType == 1) SignalDataType = 2; // IEEE 754 floating-point
//else SignalDataType = 0; // unsigned integer
f_write(&fp, &SignalDataType, sizeof(UINT16), &byteWrite);
// -----------------------------------------------------------------
f_write(&fp, &ValueRange, sizeof(BOOL), &byteWrite);
ValueMin = doubleUp((union floatBytes)f32VMin);
TimeInterval = doubleUp((union floatBytes)f32time);
f_write(&fp, &ValueMin, sizeof(REAL), &byteWrite);
f_write(&fp, &ValueMin, sizeof(REAL), &byteWrite);
f_write(&fp, &TimeInterval, sizeof(REAL), &byteWrite);
f_write(&fp, &ReservedLINK, sizeof(LINK), &byteWrite); // no ASAM-MCD unique name
f_write(&fp, &ReservedLINK, sizeof(LINK), &byteWrite); // no signal's display
// -----------------------------------------------------------------
f_write(&fp, &ByteOffset, sizeof(UINT16), &byteWrite);
return BitWidth;
}
// --------------------------------------------------------------------------
// Y=(f*INT-c)*b' -> b' = 1/b
// Y = f*INT*b' + (-c*b') = INT*(f*b) + (-c*b') --> so P1 = f*b', P2 = (-c*b')
// Now for Conversion formula 'Parametric, Linear' = INT * P1 + P2
// opt : 1 = RAT_FUNC, 0 = param
// chnType : 0 = data, 1 = time, 2 = dummy
// --------------------------------------------------------------------------
UINT16 writeCCBlock(FIL fp, ConvRuleXUDS xUDS, uint8_t opt, uint8_t chnType){
UINT byteWrite, n;
char buff[33];
UINT16 BlockSize = 0x3E; // Block size = 62
UINT16 ConvFormulaID = 0; // parametric, linear
UINT16 ParameterNo = 2;
BOOL ValueRange = 0; // FALSE
REAL Parameter; // for all 6 parameters
double f32VMin = 0;
if(opt == 1){ // ASAP2 Rational conversion
BlockSize = 0x5E;
ParameterNo = 6;
ConvFormulaID = 9;
}
sprintf(buff, PSTR("CC")); // Block Type
f_write(&fp, buff, 2, &byteWrite);
f_write(&fp, &BlockSize, sizeof(UINT16), &byteWrite); // Block size
f_write(&fp, &ValueRange, sizeof(BOOL), &byteWrite);
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // min
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // max
sprintf(buff, PSTR("- ")); // Physical unit
f_write(&fp, buff, 20, &byteWrite);
f_write(&fp, &ConvFormulaID, sizeof(UINT16), &byteWrite);
f_write(&fp, &ParameterNo, sizeof(UINT16), &byteWrite);
// 'time' or 'dummy' channel ----------------------------------------
// CCBLOCK : Parametric, Linear - Phys = Int * P 2 + P1
if(chnType != 0){
f32VMin = 0; // Parm 1 = 0
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite);
f32VMin = 1; // Parm 2 = x
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite);
}
else if(opt == 0){ // Parametric, linear
f32VMin = (double)(xUDS.f_factor * xUDS.b_factor); // Parm 1 = f*b'
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite);
f32VMin = (double)(-1*xUDS.c_factor*xUDS.b_factor); // Parm 2 = (-c*b')
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite);
}else{ // RAT function
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // Parm a = 0
f32VMin = (double) xUDS.b_factor;
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // Parm b
f32VMin = (double) xUDS.c_factor;
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // Parm c
f32VMin = 0;
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // Parm d = 0
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // Parm e = 0
f32VMin = (double) xUDS.f_factor;
Parameter = doubleUp((union floatBytes)f32VMin);
f_write(&fp, &Parameter, sizeof(REAL), &byteWrite); // Parm f
}
return BlockSize;
}
// --------------------------------------------------------------------------
// Write Header info as it is almost fixed
// CGBlock : as 'RecordsNo' is unknown at start, it should be corrected
// DGBolck = 1 & HDBlock = 1
// CGBlock = 1 for ALL CNBlock
// --------------------------------------------------------------------------
UINT16 MDFwriteInfo(FIL fp, ConvRuleXUDS xUDS[]){
LINK thisCNB = 64+0xA4+0x1C+0x1A; // offset for first CN block
LINK nextCNB;
UINT16 chnType, bitPos = 0;
UINT16 ccBlockSize = 0x3E; // Block size for time = 62
UINT16 BitWidth;
UINT16 recordSize = 64; // 64 = time width
uint8_t ndx;
writeIDBlock(fp); // no TX & PR block
writeHDBlock(fp);
writeDGBlock(fp);
for(ndx=0; ndx<XUDS_NO; ndx++){
BitWidth = (UINT16) (xUDS[ndx].TypeInfoA & 0x07) * 8;
if(xUDS[ndx].TypeInfoA & 0x30) BitWidth = 1; // type 'D'
recordSize = recordSize + BitWidth;
}
//if(recordSize % 8) recordSize = (recordSize/8 + 1)*8;
//else recordSize = (recordSize/8 + 1)*8;
recordSize = (recordSize/8 + 1)*8; // we need 'dummy'
writeCGBlock(fp, recordSize); // save total bitWidth for XUDS
// ----------------------------------------------------------------
// ETAS 'time' format
// width=0x40, data type=0x02(=IEEE754)
// Conversion formula identifier = 0x00, Number of value pairs = 0x02
// Grid in which the variable was sampled = 0x3FF00000 0000000 (=1.0E0)
// P1 = 0x00000000 00000000
// P2 = 0x3FF00000 0000000 (=1.0E0 and stored as 00000000 0000F03F)
// ----------------------------------------------------------------
chnType = 1; // 'time' channel at first
nextCNB = thisCNB + (0xE4 + ccBlockSize);
BitWidth = writeCNBlock(fp, xUDS[ndx], thisCNB, nextCNB, chnType, bitPos);
ccBlockSize = writeCCBlock(fp, xUDS[ndx], 0, chnType);
chnType = 0; // signal channel
bitPos = bitPos + BitWidth;
// ----------------------------------------------------------------
for(ndx=0; ndx<XUDS_NO; ndx++){
//if(ndx == (XUDS_NO-1)) nextCNB = 0; // last CNBlock
nextCNB += (0xE4 + ccBlockSize);
BitWidth = writeCNBlock(fp, xUDS[ndx], thisCNB, nextCNB, chnType, bitPos);
ccBlockSize = writeCCBlock(fp, xUDS[ndx], 0, chnType);
thisCNB = nextCNB;
bitPos = bitPos + BitWidth;
}
// ----------------------------------------------------------------
// due to bitwidth total width may be short & under 8 bits
// so add dummy bits at the end to make byte end
// ----------------------------------------------------------------
chnType = 2; // dummy bit Fields
nextCNB = 0; // last CNBlock
BitWidth = writeCNBlock(fp, xUDS[ndx], thisCNB, nextCNB, chnType, bitPos);
ccBlockSize = writeCCBlock(fp, xUDS[ndx], 0, chnType);
return (bitPos + BitWidth);
}
// --------------------------------------------------------------------------
// CGBlock : as 'RecordsNo' is unknown at start, it should be corrected
// Type 'D' must be saved as one 'BIT' after 'bit operation'
// bit wise saving ...??
// uint8_t xUDSBuff[XUDS_NO*2]; // Just make guess
// UINT32 recordNoMDF;
// Byte order : 0 = Little endian
// only max two byte 'measured value' is writen
// 'caller' : every initialization, clear xUDSBuff & set 4 byte time first
// --------------------------------------------------------------------------
void MDFwriteData(ConvRuleXUDS xUDS, UINT16 BitPosition){
uint8_t ByteIndex, temp;
UINT16 BitWidth;
ByteIndex = BitPosition/8;
if(xUDS.TypeInfoA & 0x30){ // type 'D'
BitWidth = 1;
if(_ValueECU == 0) return; // no need to write as '0'
temp = BitPosition - ByteIndex*8; // get BIT position
if(temp == 0) xUDSBuff[ByteIndex] |= 0x01;
else xUDSBuff[ByteIndex] |= (1 << temp);
return;
}
BitWidth = (UINT16) (xUDS.TypeInfoA & 0x07) * 8;
temp = (uint8_t) _ValueECU & 0x00FF;
_ValueECU
}
// ---------------------------------------------------------------------------
헤더화일 : MDF.h
// --------------------------------------------------------------------------
// MDF moudle :
// --------------------------------------------------------------------------
// V01B1 - 2014.11.25
// V01BX3 - 2014.11.27 : bitwidth for 'bit' value as 8 in 'writeCNBlock'
// V01BXE - 2014.12.09 : Bug fix wrong channel type in case HCAN(2-->0)
// --------------------------------------------------------------------------
#include "uTFTCAN.h"
#include "ff.h" // Declarations of FatFs API */
#define MDFTIMEWIDTH 8 // V01ASD
#define SIGNAL_UDS 0
#define SIGNAL_TIME 1 // type = 1 & INT*P2 + P1
#define SIGNAL_HCAN 2
#define ParamLINEAR 3 // INT*P2 + P1 (b,c,f_cactor)
#define LINEAR_HCAN 4 // INT*P2 + P1 (fac / offset)
#define RAT_FUNCTION 5
// --------------------------------------------------------------------------
// MDF 3.0 related definitions
// --------------------------------------------------------------------------
// http://class.ece.iastate.edu/arun/CprE281_F05/ieee754/ie5.html
// http://stackoverflow.com/questions/16808069/
// how-to-convert-float-to-ieee754-double-precision-format-by-using-union-and-struc
// http://en.wikipedia.org/wiki/Double-precision_floating-point_format
// http://forum.pololu.com/viewtopic.php?f=23&t=1953
// --------------------------------------------------------------------------
// IEEE754 DP(64bit): sign exponent(11) fraction(52) NOTE : Intel is MSB first
// s eeeeeeeeeee fffffffff.........fffff
// IEEE754 SP(32bit): sign exponent(8) fraction(23)
// s eeeeeeee fffff.......fff
// --------------------------------------------------------------------------
// CHAR, UINT8, UINT16, UINT32 ---> use : char, uint8_t, uint16_t, uint32_t
typedef uint16_t BOOL; // 16bit : 0 = FALSE, else TRUE
typedef uint16_t UINT16;
typedef uint32_t UINT32;
typedef int32_t LINK; // 32-bit signed integer, used as byte position
typedef long long REAL; // IEEE 754, double precision (64 bits)
// --------------------------------------------------------------------------
union ByteUint32{ // V01AS0 for writeMDFdata
uint8_t ByteValue[4];
uint32_t _Value32;
};
// --------------------------------------------------------------------------
// http://forum.pololu.com/viewtopic.php?f=23&t=1953
// Generating a 64-bit Double on an AVR
// --------------------------------------------------------------------------
union floatBytes{
double f;
unsigned long b;
};
// --------------------------------------------------------------------------
REAL doubleUp(union floatBytes float32);
void writeIDBlock(FIL *fp);
void writeHDBlock(FIL *fp);
void writeDGBlock(FIL *fp, uint8_t noFR);
void writeCGBlock(FIL *fp, UINT16 recordSizeMDF, uint8_t noFR);
UINT16 writeCNBlock(FIL *fp, uint8_t TypeInfoA, char RuleName[], LINK thisCNB, LINK nextCNB, UINT16 chnType, UINT16 bitPos);
UINT16 writeCCBlock(FIL *fp, float factor[], uint8_t formType);
UINT16 writeMDFInfo(FIL *fp, ConvRuleXUDS xUDS[], uint8_t noFR);
UINT16 writeMDFInfoHCAN(FIL *fp, ConvRuleHCAN xHCAN[], uint8_t noFR);
int writeMDFData(uint8_t TypeInf, UINT16 BitPos, uint32_t Value32, uint8_t xBuff[]);
void writeMDFtime(FIL *fp, uint16_t *_time);
void writeMDFdummy(UINT16 BitLocation, uint8_t widthDummyBit);
void writeCGrecordsNo(FIL *fp, uint32_t *FRdataRecordsNo); // V01AD3
void writeMDFbuffClear(uint8_t xBuff[]); // V01BX7
void writeMDF2File(FIL *fp, uint8_t xBuff[]);
void testMDF(FIL *fp);
// --------------------------------------------------------------------------
'uAVR' 카테고리의 다른 글
AVR : atmega MDF - ASAM (0) | 2019.11.02 |
---|---|
도트매트릭 LED 제어루틴 (0) | 2017.02.09 |
FAST AVR UTFT Library for C (Not CPP) - SSD1289 / HY32D (0) | 2017.01.21 |
GLCD FONT convert to use for LED DOT Matrix (0) | 2017.01.21 |
윤덕용 교수님의 한글 GLCD 라이브러리 - 하위 제어포트 살리기 (0) | 2017.01.21 |