예전에 조사하여 만든 AVR / atmega용 MDF 화일 저장 코드

우선 필요한 건 MDF 화일 정보

구글링

 

https://www.google.co.kr/search?newwindow=1&hl=en&source=hp&ei=suO8XaPzJY2xmAWT1YgI&q=ASAM+MCD-2+MC&oq=ASAM+MCD-2+MC&gs_l=psy-ab.3..0l2j0i22i30l6.1826.1826..2600...0.0..0.109.109.0j1......0....2j1..gws-wiz.....0.REcPrhziy-Q&ved=0ahUKEwijlJHLt8rlAhWNGKYKHZMqAgEQ4dUDCAY&uact=5

 

필요한 파일 : ASAM 화일임 클릭해서 다운

ASAM MCD-2MC Version 1.6 Measurement and ... - Read

준비할 것 : FatFs (AVR용 FAT 시스템 모듈)

 

               FatFs Module
               October 14, 2019

 

FatFs - Generic FAT Filesystem Module

FatFs is a generic FAT/exFAT filesystem module for small embedded systems. The FatFs module is written in compliance with ANSI C (C89) and completely separated from the disk I/O layer. Therefore it is independent of the platform. It can be incorporated int

elm-chan.org

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);
// --------------------------------------------------------------------------

 

 

 

블로그 이미지

DIYworld

,