Driver Header file
#ifndef __MMD1100_H__
#define __MMD1100_H__
#include <stdint.h> /* types */
#define DEVICE_MMD1100 "/dev/ttyS5"
#define MMD1100_DEFAULT_BAUDRATE 9600
//#define MMD1100_DEFAULT_BAUDRATE 19200
//#define MMD1100_DEFAULT_BAUDRATE 38400
//#define MMD1100_DEFAULT_BAUDRATE 57600
//#define MMD1100_DEFAULT_BAUDRATE 115200
#define MMD1100_TIMEOUT_BETWEEN_SERIAL_INPUT_DATA 20 /*20 msec*/
typedef enum
{
MMD1100_COMMAND_GET_VERSION = 0,
MMD1100_COMMAND_LOAD_USER_PARAMETERS,
MMD1100_COMMAND_UART_CALIBRATION,
MMD1100_COMMAND_OTP_WRITE,
MMD1100_COMMAND_GET_STATUS,
MMD1100_COMMAND_READ_DATA_RETRY,
MMD1100_COMMAND_SOFTWARE_RESET
} MMD1100_Command_t;
typedef struct
{
/* */
uint8_t ErrorCodeForTrack1;
uint8_t ErrorCodeForTrack2;
uint8_t ErrorCodeForTrack3;
/* */
uint8_t LengthOfTrack1;
uint8_t LengthOfTrack2;
uint8_t LengthOfTrack3;
/* ISO7813 */
uint8_t pTrack1[79 * 2];
uint8_t pTrack2[40 * 2];
uint8_t pTrack3[107 * 2];
/* */
uint8_t LengthOfRaw1;
uint8_t LengthOfRaw2;
uint8_t LengthOfRaw3;
uint8_t pRaw1[79 * 2];
uint8_t pRaw2[40 * 2];
uint8_t pRaw3[107 * 2];
} MSRTrack_t;
typedef struct
{
MMD1100_Command_t Command;
uint8_t ErrorCode;
uint8_t pData[100];
} MMD1100Response_t;
/* open serial device for cummunication with MMD1100
return:
-1: Fail to operation
-2: Input Paramters Error
0: OK
*/
extern int mmd1100_open(int *pDeviceFileDescriptor);
/* close serial device for end of cummunication with MMD1100
return:
-1: Fail to operation
0: OK
*/
extern int mmd1100_close(void);
/* serial buffer flush for cummunication with MMD1100
*/
extern void mmd1100_serial_flush(void);
/* get serial device file descriptor for cummunication with MMD1100
return:
-1: Fail to operation
-2: Input Paramters Error
0: OK
*/
extern int mmd1100_get_device_file_descriptor(int *pDeviceFileDescriptor);
/* receive
return:
-1: Fail to operation
-2: Input Parameter Error
-4: Timeout or Not Ready
0: OK
*/
extern int mmd1100_receive(MSRTrack_t *pMSRTrack,
MMD1100Response_t *pResponse,
uint32_t *pIsNotTrack,
uint32_t ResponseTimeout);
/*
-1: invalid parameter
0 : OK
*/
extern int mmd1100_make_packet(uint8_t *pPacket,
uint32_t *pMakedPacketByteLength,
MMD1100_Command_t Command,
uint8_t pArguments[4]);
/*
-1: invalid parameter
-2: send error
0 : Not open
+ : Send length
*/
extern int mmd1100_send(uint8_t *pPacket,
uint8_t PacketByteLength);
#endif /* __MMD1100_H__ */
Driver Source File
#include <stdint.h> /* types */
#include <stdio.h> /* printf */
#include <string.h> /* memcpy, strlen... */
#include <termios.h> /* struct termios */
#include <unistd.h> /* for open/close .. */
#include <fcntl.h> /* for O_RDWR */
#include <sys/ioctl.h> /* for ioctl */
#include <poll.h> /* struct pollfd */
#include <time.h> /* struct timespec */
#include "CRC_LRC.h" /* lrc_xor() */
#include "MemoryControl.h" /* memory_pick_up_bit() */
#include "MMD1100.h" /* */
#define MMD1100_DEBUG(fmt, args ...) printf("DEBUG:%s(%d): " fmt, __FUNCTION__,__LINE__, ## args)
#define MMD1100_ERROR(fmt, args ...) printf("ERROR:%s(%d): " fmt, __FUNCTION__,__LINE__, ## args)
#define MMD1100_INFO(fmt, args ...) printf("INFOs:%s(%d): " fmt, __FUNCTION__,__LINE__, ## args)
#define MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL 512
#define MMD1100_BYTE_SIZE_OF_BUFFER_FOR_PACKET 1024
#define MMD1100_PACKET_POSITION_STX 0
#define MMD1100_PACKET_POSITION_CLASS 1
#define MMD1100_PACKET_POSITION_FUNCTION 2
#define MMD1100_PACKET_POSITION_LENGTH 3
#define MMD1100_PACKET_POSITION_STATUS 4
#define MMD1100_PACKET_POSITION_DATA_START 5
#define MMD1100_PACKET_POSITION_TRACK_ID 2
#define MMD1100_DEFINE_STX 0x02
#define MMD1100_DEFINE_ETX 0x03
#define MMD1100_DEFINE_TRACK_DATA 0x33
#define MMD1100_DEFINE_TRACK_ID_1 0x25
//#define MMD1100_DEFINE_TRACK_ID_2 0x3F
//#define MMD1100_DEFINE_TRACK_ID_3 0x5E
#define MMD1100_DEFINE_TRACK_ID_2 0x5E /*Bug Fix*/
#define MMD1100_DEFINE_TRACK_ID_3 0x3F /*Bug Fix*/
#define MMD1100_DEFINE_ACK 0x06
#define MMD1100_DEFINE_NAK 0x15
#define MMD1100_COMMAND_CLASS_GET_VERSION 0x10
#define MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS 0x12
#define MMD1100_COMMAND_CLASS_UART_CALIBRATION 0x13
#define MMD1100_COMMAND_CLASS_OTP_WRITE 0x15
#define MMD1100_COMMAND_CLASS_GET_STATUS 0x16
#define MMD1100_COMMAND_CLASS_READ_DATA_RETRY 0x17
#define MMD1100_COMMAND_CLASS_SOFTWARE_RESET 0x18
#define MMD1100_COMMAND_FUNCTION_GET_VERSION 0x31
#define MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS 0x31
#define MMD1100_COMMAND_FUNCTION_UART_CALIBRATION 0x31
#define MMD1100_COMMAND_FUNCTION_OTP_WRITE 0x33
#define MMD1100_COMMAND_FUNCTION_GET_STATUS 0x31
#define MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY 0x31
#define MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET 0x31
#define MMD1100_COMMAND_LENGTH_GET_VERSION 0x00
#define MMD1100_COMMAND_LENGTH_LOAD_USER_PARAMETERS 0x04
#define MMD1100_COMMAND_LENGTH_UART_CALIBRATION 0x05
#define MMD1100_COMMAND_LENGTH_OTP_WRITE 0x00
#define MMD1100_COMMAND_LENGTH_GET_STATUS 0x00
#define MMD1100_COMMAND_LENGTH_READ_DATA_RETRY 0x00
#define MMD1100_COMMAND_LENGTH_SOFTWARE_RESET 0x00
#define MMD1100_RESPONSE_ACK_LENGTH_GET_VERSION 0x10
#define MMD1100_RESPONSE_ACK_LENGTH_LOAD_USER_PARAMETERS 0x04
#define MMD1100_RESPONSE_ACK_LENGTH_UART_CALIBRATION 0x01
#define MMD1100_RESPONSE_ACK_LENGTH_OTP_WRITE 0x01
#define MMD1100_RESPONSE_ACK_LENGTH_GET_STATUS 0x06
#define MMD1100_RESPONSE_NAK_LENGTH 0x01
typedef enum
{
MMD1100_PACKET_CHECK_STATE_STX = 0,
MMD1100_PACKET_CHECK_STATE_MODE_CLASS,
MMD1100_PACKET_CHECK_STATE_TRACK_ID,
MMD1100_PACKET_CHECK_STATE_TRACK_LENGTH,
MMD1100_PACKET_CHECK_STATE_TRACK_STATE,
MMD1100_PACKET_CHECK_STATE_TRACK_DATA,
MMD1100_PACKET_CHECK_STATE_FUNCTION,
MMD1100_PACKET_CHECK_STATE_LENGTH,
MMD1100_PACKET_CHECK_STATE_STATUS,
MMD1100_PACKET_CHECK_STATE_DATA,
MMD1100_PACKET_CHECK_STATE_ETX,
MMD1100_PACKET_CHECK_STATE_BCC
} MMD1100PacketCheckState_t;
typedef struct
{
/* Device File Descriptor */
int Device;
struct termios BackupTerminalInfo;
/* Serial Receive Buffer */
uint8_t pBufferForSerial[MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL];
uint32_t HeadPointerForSerial;
uint32_t TailPointerForSerial;
/* Received Packet Buffer */
uint8_t pBufferForPacket[MMD1100_BYTE_SIZE_OF_BUFFER_FOR_PACKET];
uint32_t PacketOffset;
MMD1100PacketCheckState_t PacketCheckState;
uint32_t DataLengthInPacket;
uint32_t PacketLength;
} MMD1100context_t;
static MMD1100context_t MMD1100context =
{
/* Device File Descriptor */
.Device = -1,
/* struct termios BackupTerminalInfo*/
/* Serial Receive Buffer */
.pBufferForSerial = {0},
.HeadPointerForSerial = 0,
.TailPointerForSerial = 0,
/* Received Packet Buffer */
.pBufferForPacket = {0},
.PacketOffset = 0,
.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STX,
.DataLengthInPacket = 0,
.PacketLength = 0
};
/* 5 bit (Data + Parity) ANSI/ISO BCD Data Format convert to 8 bit ASCII */
static const uint8_t pDataFormatTableForISO_BCD[] =
{
/* 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 */
' ', '1', '2', ' ', '4', ' ', ' ', '7',
/* 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F */
'8', ' ', ' ', ';', ' ', '=', '>', ' ',
/* 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 */
'0', ' ', ' ', '3', ' ', '5', '6', ' ',
/* 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F */
' ', '9', ':', ' ', '<', ' ', ' ', '?'
};
/* 7 bit (Data + Parity) ANSI/ISO ALPHA Data Format convert to 8 bit ASCII */
static const uint8_t pDataFormatTableForISO_ALPHA[] =
{
/* 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 */
0x00, '!', '"', 0x00, '$', 0x00, 0x00, '\'',
/* 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F */
'(', 0x00, 0x00, '+', 0x00, '-', '.', 0x00,
/* 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 */
'0', 0x00, 0x00, '3', 0x00, '5', '6', 0x00,
/* 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F */
0x00, '9', ':', 0x00, '<', 0x00, 0x00, '?',
/* 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 */
'@', 0x00, 0x00, 'C', 0x00, 'E', 'F', 0x00,
/* 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F */
0x00, 'I', 'J', 0x00, 'L', 0x00, 0x00, 'O',
/* 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 */
0x00, 'Q', 'R', 0x00, 'T', 0x00, 0x00, 'W',
/* 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F */
'X', 0x00, 0x00, '[', 0x00, 'D', '^', 0x00,
/* 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 */
' ', 0x00, 0x00, '#', 0x00, '%', '&', 0x00,
/* 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 0x4F */
0x00, ')', '*', 0x00, ',', 0x00, 0x00, '/',
/* 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 */
0x00, '1', '2', 0x00, '4', 0x00, 0x00, '7',
/* 0x58 0x59 0x5A 0x5B 0x5C 0x5D 0x5E 0x5F */
'8', 0x00, 0x00, 0x00, 0x00, '=', '>', 0x00,
/* 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 */
0x00, 'A', 'B', 0x00, 'D', 0x00, 0x00, 'G',
/* 0x68 0x69 0x6A 0x6B 0x6C 0x6D 0x6E 0x6F */
'H', 0x00, 0x00, 'K', 0x00, 'M', 'N', 0x00,
/* 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 */
'P', 0x00, 0x00, 'S', 0x00, 'U', 'V', 0x00,
/* 0x78 0x79 0x7A 0x7B 0x7C 0x7D 0x7E 0x7F */
0x00, 'Y', 'Z', 0x00, '\\', 0x00, 0x00, '_'
};
static int mmd100_convert_rawdata_to_bcd( uint8_t *pTarget,
uint8_t *pSource,
uint32_t ByteLengthOfSource,
int StartFromLast)
{
uint32_t TotalBitInMemory;
uint32_t BitPositionInMemory;
uint32_t BitPositionInBCD;
int ByteLengthOfConvertedBCD;
int FirstHighBitPosition;
int IsERROR;
uint8_t BCD;
if ( ( pTarget == (uint8_t *)0) || ( pSource == (uint8_t *)0 ) )
{
return -1;
}
FirstHighBitPosition = -1;
TotalBitInMemory = ByteLengthOfSource * 8;
BCD = 0;
IsERROR = 0;
for ( BitPositionInMemory = 0; BitPositionInMemory < TotalBitInMemory; BitPositionInMemory++)
{
BCD >>= 1;
if ( memory_pick_up_bit( (void *)pSource,
TotalBitInMemory,
BitPositionInMemory,
StartFromLast) == 1 )
{
if ( FirstHighBitPosition == -1 )
{
FirstHighBitPosition = BitPositionInMemory;
}
BCD |= 0x10;
}
else
{
BCD &= 0xEF;
}
BCD &= 0x1F;
if ( BCD == 0x0B/* ';' = SS */ )
{
if (FirstHighBitPosition + 4 != BitPositionInMemory)
{
IsERROR = 1; /* SS error */
}
/* get sync */
break;
}
}
BitPositionInMemory++; /* skip parity bit for sync char */
if(BitPositionInMemory >= TotalBitInMemory)
{
return -2; /* Not find SS */
}
ByteLengthOfConvertedBCD = 0;
pTarget[ByteLengthOfConvertedBCD++] = pDataFormatTableForISO_BCD[0x0B]; /* ';' = SS */
/* gather data */
BitPositionInBCD=0;
BCD = 0;
for ( ; BitPositionInMemory < TotalBitInMemory; BitPositionInMemory++)
{
BCD |= (memory_pick_up_bit( (void *)pSource,
TotalBitInMemory,
BitPositionInMemory,
StartFromLast) << BitPositionInBCD);
BitPositionInBCD ++;
if ( BitPositionInBCD == 5 )
{
pTarget[ByteLengthOfConvertedBCD++] = pDataFormatTableForISO_BCD[BCD];
BitPositionInBCD=0;
BCD = 0;
}
}
return ByteLengthOfConvertedBCD;
}
static void mmd1100_packet_flush_buffer(void);
/* open serial device for cummunication with MMD1100
return:
-1: Fail to operation
-2: Input Paramters Error
0: OK
*/
int mmd1100_open(int *pDeviceFileDescriptor)
{
struct termios TerminalInfo;
if ( pDeviceFileDescriptor == (int *)0 )
{
return -2;
}
if ( MMD1100context.Device < 0 )
{
/* Initial Serial Receive Buffer */
MMD1100context.HeadPointerForSerial = 0;
MMD1100context.TailPointerForSerial = 0;
/* Initial Received Packet Buffer */
mmd1100_packet_flush_buffer();
/* 화일을 연다. */
MMD1100context.Device = open( DEVICE_MMD1100, (O_RDWR | O_NOCTTY) );
if ( MMD1100context.Device < 0 )
{
/* 화일 열기 실패 */
MMD1100_ERROR( "failed to open %s\n", DEVICE_MMD1100 );
MMD1100context.Device = -1;
*pDeviceFileDescriptor = MMD1100context.Device;
return -1;
}
/* 현재 설정을 BackupTerminalInfo에 저장 */
tcgetattr( MMD1100context.Device, &MMD1100context.BackupTerminalInfo );
memset( &TerminalInfo, 0, sizeof(TerminalInfo) );
switch( MMD1100_DEFAULT_BAUDRATE )
{
case 19200:
TerminalInfo.c_cflag = B19200 | CS8 | CSTOPB | CLOCAL | CREAD ;
break;
case 38400:
TerminalInfo.c_cflag = B38400 | CS8 | CSTOPB | CLOCAL | CREAD ;
break;
case 57600:
TerminalInfo.c_cflag = B57600 | CS8 | CSTOPB | CLOCAL | CREAD ;
break;
case 115200:
TerminalInfo.c_cflag = B115200 | CS8 | CSTOPB | CLOCAL | CREAD ;
break;
case 9600:
default:
TerminalInfo.c_cflag = B9600 | CS8 | CSTOPB | CLOCAL | CREAD ;
break;
}
TerminalInfo.c_iflag = 0; /* IGNPAR? */
TerminalInfo.c_oflag = 0;
//set input mode (non-canonical, no echo,.....)
TerminalInfo.c_lflag = 0;
TerminalInfo.c_cc[VTIME] = 30; /* time-out 값으로 사용된다. time-out 값은 TIME*0.1초 이다. */
TerminalInfo.c_cc[VMIN] = 0; /* MIN은 read가 리턴되기 위한 최소한의 문자 개수 */
tcflush(MMD1100context.Device, TCIFLUSH);
tcsetattr(MMD1100context.Device, TCSANOW, &TerminalInfo);
// raw mode
fcntl(MMD1100context.Device, F_SETFL, O_NONBLOCK);
}
else
{
MMD1100_DEBUG("%s already opened\n", DEVICE_MMD1100);
}
*pDeviceFileDescriptor = MMD1100context.Device;
return 0;
}
/* close serial device for end of cummunication with MMD1100
return:
-1: Fail to operation
0: OK
*/
int mmd1100_close(void)
{
if ( MMD1100context.Device < 0 )
{
MMD1100_ERROR("%s already closed\n", DEVICE_MMD1100);
return -1;
}
/* 이전 상태로 되돌린다. */
tcsetattr( MMD1100context.Device, TCSANOW, &MMD1100context.BackupTerminalInfo );
close(MMD1100context.Device);
MMD1100context.Device = -1;
return 0;
}
/* get serial device file descriptor for cummunication with MMD1100
return:
-1: Fail to operation
-2: Input Paramters Error
0: OK
*/
int mmd1100_get_device_file_descriptor(int *pDeviceFileDescriptor)
{
if ( pDeviceFileDescriptor == (int *)0 )
{
return -2;
}
if ( MMD1100context.Device != -1 )
{
*pDeviceFileDescriptor = MMD1100context.Device;
return 0;
}
MMD1100_ERROR("%s is closed\n", DEVICE_MMD1100);
return -1;
}
/* serial buffer flush for cummunication with MMD1100
*/
void mmd1100_serial_flush(void)
{
struct pollfd PollFileDescriptor;
int Result;
uint8_t ReceivedByte;
if ( MMD1100context.Device != -1 )
{
memset( &PollFileDescriptor, 0, sizeof(struct pollfd) );
while(1)
{
PollFileDescriptor.fd = MMD1100context.Device;
PollFileDescriptor.events = POLLIN;
PollFileDescriptor.revents = 0;
Result = poll( &PollFileDescriptor, 1, 2 ); // 2 msec
if ( (Result == 1) && ((PollFileDescriptor.revents & POLLIN) != 0) )
{
read(MMD1100context.Device, &ReceivedByte, 1);
}
else
{
break;
}
}
}
else
{
MMD1100_ERROR("%s is closed\n", DEVICE_MMD1100);
}
MMD1100context.HeadPointerForSerial = 0;
MMD1100context.TailPointerForSerial = 0;
}
/* send data(n byte) to MMD1100 through serial device
*/
static void mmd1100_serial_transmit_data(uint8_t *pData, uint32_t ByteLengthOfData)
{
int Result;
uint8_t Byte;
while(ByteLengthOfData--)
{
Byte = *pData++;
do
{
Result = write(MMD1100context.Device, &Byte, 1);
} while( Result != 1 );
}
}
/* polling serial device to save input data from MMD1100
*/
static void mmd1100_serial_polling(void)
{
struct pollfd PollFileDescriptor;
uint32_t Temp;
int Result;
uint8_t ReceivedByte;
memset( &PollFileDescriptor, 0, sizeof(struct pollfd) );
PollFileDescriptor.fd = MMD1100context.Device;
PollFileDescriptor.events = POLLIN;
PollFileDescriptor.revents = 0;
Result = poll( (struct pollfd *)&PollFileDescriptor, 1, 20); // 20 msec
if ( (Result == 1) && ((PollFileDescriptor.revents & POLLIN) != 0) )
{
if ( read(MMD1100context.Device, &ReceivedByte, 1) == 1 )
{
MMD1100context.pBufferForSerial[MMD1100context.HeadPointerForSerial] = ReceivedByte;
Temp = (MMD1100context.HeadPointerForSerial + 1) % MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL;
if ( Temp != MMD1100context.TailPointerForSerial )
{
MMD1100context.HeadPointerForSerial = Temp;
}
}
}
}
/* check serial buffer to find received data from MMD1100
return:
0: Data is not received
1: Data received
*/
static int mmd1100_serial_check_buffer(void)
{
// check lowlevel serial data, if we have no data
if ( MMD1100context.HeadPointerForSerial == MMD1100context.TailPointerForSerial )
{
mmd1100_serial_polling();
}
if ( MMD1100context.HeadPointerForSerial != MMD1100context.TailPointerForSerial )
{
return 1;
}
return 0;
}
/* get data from serial buffer
return:
-1: Fail to operation
-2: Input Paramters Error
0: OK
*/
static int mmd1100_serial_get_data_from_buffer(uint8_t *pData)
{
if ( pData == (uint8_t *)0 )
{
return -2;
}
if ( MMD1100context.TailPointerForSerial == MMD1100context.HeadPointerForSerial)
{
return -1;
}
*pData = MMD1100context.pBufferForSerial[MMD1100context.TailPointerForSerial];
MMD1100context.TailPointerForSerial++;
MMD1100context.TailPointerForSerial %= MMD1100_BYTE_SIZE_OF_BUFFER_FOR_SERIAL;
return 0;
}
/* flush received packet buffer
*/
static void mmd1100_packet_flush_buffer(void)
{
MMD1100context.PacketOffset = 0;
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STX;
}
/*
-1: invalid
0 : OK
*/
static int mmd1100_check_response(uint8_t Class,
uint8_t Function,
uint8_t Length,
uint8_t Status)
{
switch (Class)
{
case MMD1100_COMMAND_CLASS_GET_VERSION:
if ( Function == MMD1100_COMMAND_FUNCTION_GET_VERSION )
{
if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_GET_VERSION ) )
|| ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) )
{
return 0;
}
}
break;
case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS:
if ( Function == MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS )
{
if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_LOAD_USER_PARAMETERS ) )
|| ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) )
{
return 0;
}
}
break;
case MMD1100_COMMAND_CLASS_UART_CALIBRATION:
if ( Function == MMD1100_COMMAND_FUNCTION_UART_CALIBRATION )
{
if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_UART_CALIBRATION ) )
|| ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) )
{
return 0;
}
}
break;
case MMD1100_COMMAND_CLASS_OTP_WRITE:
if ( Function == MMD1100_COMMAND_FUNCTION_OTP_WRITE )
{
if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_OTP_WRITE ) )
|| ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) )
{
return 0;
}
}
break;
case MMD1100_COMMAND_CLASS_GET_STATUS:
if ( Function == MMD1100_COMMAND_FUNCTION_GET_STATUS )
{
if ( ( ( Status == MMD1100_DEFINE_ACK ) && ( Length == MMD1100_RESPONSE_ACK_LENGTH_GET_STATUS ) )
|| ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) ) )
{
return 0;
}
}
break;
case MMD1100_COMMAND_CLASS_READ_DATA_RETRY:
if ( Function == MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY )
{
if ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) )
{
return 0;
}
}
break;
case MMD1100_COMMAND_CLASS_SOFTWARE_RESET:
if ( Function == MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET )
{
if ( ( Status == MMD1100_DEFINE_NAK ) && ( Length == MMD1100_RESPONSE_NAK_LENGTH ) )
{
return 0;
}
}
break;
default:
break;
}
return -1;
}
/* make response packet form serial buffer
return:
2: Notify Packet
1: Need Time Wait
-1: Fail to operation
-2: Packet LRC Error
-3: Packet Data is too Big
-4: Timeout or Not Ready
0: OK
*/
static int mmd1100_packet_make_response_from_serial_buffer(void)
{
struct timespec CurrentTime;
struct timespec GetTimeToLastData;
uint8_t Data;
while( mmd1100_serial_check_buffer() == 1 )
{ /* Serial buffer has data */
mmd1100_serial_get_data_from_buffer( &Data );
clock_gettime( CLOCK_REALTIME, &GetTimeToLastData );
/* Push Data to Packet Buffer */
MMD1100context.pBufferForPacket[MMD1100context.PacketOffset] = Data;
/*
printf("0x%02X ", Data);
*/
if ( MMD1100context.PacketOffset < MMD1100_BYTE_SIZE_OF_BUFFER_FOR_PACKET )
{
MMD1100context.PacketOffset++;
}
switch( MMD1100context.PacketCheckState )
{
case MMD1100_PACKET_CHECK_STATE_STX:
if ( Data == MMD1100_DEFINE_STX )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_MODE_CLASS;
}
else
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG( "invalid received Data : 0x%02X\n", Data );
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_MODE_CLASS:
MMD1100context.PacketLength = 0;
if ( Data == MMD1100_DEFINE_TRACK_DATA )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_ID;
}
else
{
switch ( Data )
{
case MMD1100_COMMAND_CLASS_GET_VERSION:
case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS:
case MMD1100_COMMAND_CLASS_UART_CALIBRATION:
case MMD1100_COMMAND_CLASS_OTP_WRITE:
case MMD1100_COMMAND_CLASS_GET_STATUS:
case MMD1100_COMMAND_CLASS_READ_DATA_RETRY:
case MMD1100_COMMAND_CLASS_SOFTWARE_RESET:
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_FUNCTION;
break;
default:
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG( "invalid received Data : 0x%02X\n", Data );
return -1;
break;
}
}
break;
case MMD1100_PACKET_CHECK_STATE_TRACK_ID:
if ( ( Data == MMD1100_DEFINE_TRACK_ID_1 )
|| ( Data == MMD1100_DEFINE_TRACK_ID_2 )
|| ( Data == MMD1100_DEFINE_TRACK_ID_3 ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_LENGTH;
}
else if ( Data == MMD1100_DEFINE_ETX )
{
MMD1100context.PacketLength += 3;
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_BCC;
}
else
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data);
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_TRACK_LENGTH:
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_STATE;
MMD1100context.DataLengthInPacket = Data;
break;
case MMD1100_PACKET_CHECK_STATE_TRACK_STATE:
if ( ( Data == MMD1100_DEFINE_ACK ) || ( Data == MMD1100_DEFINE_NAK ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_DATA;
MMD1100context.PacketLength += (MMD1100context.DataLengthInPacket + 3);
}
else
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data);
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_TRACK_DATA:
MMD1100context.DataLengthInPacket--;
if ( MMD1100context.DataLengthInPacket == 0 )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_TRACK_ID;
}
break;
case MMD1100_PACKET_CHECK_STATE_FUNCTION:
switch ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] )
{
case MMD1100_COMMAND_CLASS_GET_VERSION:
if ( Data == MMD1100_COMMAND_FUNCTION_GET_VERSION )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS:
if ( Data == MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
case MMD1100_COMMAND_CLASS_UART_CALIBRATION:
if ( Data == MMD1100_COMMAND_FUNCTION_UART_CALIBRATION )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
case MMD1100_COMMAND_CLASS_OTP_WRITE:
if ( Data == MMD1100_COMMAND_FUNCTION_OTP_WRITE )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
case MMD1100_COMMAND_CLASS_GET_STATUS:
if ( Data == MMD1100_COMMAND_FUNCTION_GET_STATUS )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
case MMD1100_COMMAND_CLASS_READ_DATA_RETRY:
if ( Data == MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
case MMD1100_COMMAND_CLASS_SOFTWARE_RESET:
if ( Data == MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_LENGTH;
}
break;
default:
break;
}
if ( MMD1100context.PacketCheckState != MMD1100_PACKET_CHECK_STATE_LENGTH )
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data);
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_LENGTH:
switch ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] )
{
case MMD1100_COMMAND_CLASS_GET_VERSION:
if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_GET_VERSION )
|| ( Data == MMD1100_RESPONSE_NAK_LENGTH ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS:
if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_LOAD_USER_PARAMETERS )
|| ( Data == MMD1100_RESPONSE_NAK_LENGTH ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
case MMD1100_COMMAND_CLASS_UART_CALIBRATION:
if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_UART_CALIBRATION )
|| ( Data == MMD1100_RESPONSE_NAK_LENGTH ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
case MMD1100_COMMAND_CLASS_OTP_WRITE:
if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_OTP_WRITE )
|| ( Data == MMD1100_RESPONSE_NAK_LENGTH ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
case MMD1100_COMMAND_CLASS_GET_STATUS:
if ( ( Data == MMD1100_RESPONSE_ACK_LENGTH_GET_STATUS )
|| ( Data == MMD1100_RESPONSE_NAK_LENGTH ) )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
case MMD1100_COMMAND_CLASS_READ_DATA_RETRY:
if ( Data == MMD1100_RESPONSE_NAK_LENGTH )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
case MMD1100_COMMAND_CLASS_SOFTWARE_RESET:
if ( Data == MMD1100_RESPONSE_NAK_LENGTH )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_STATUS;
}
break;
default:
break;
}
if ( MMD1100context.PacketCheckState != MMD1100_PACKET_CHECK_STATE_STATUS )
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data);
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_STATUS:
if ( mmd1100_check_response(MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS]/*Class*/,
MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_FUNCTION]/*Function*/,
MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH]/*Length*/,
Data/*Status*/) == 0 )
{
MMD1100context.DataLengthInPacket = MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH];
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_DATA;
}
else
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_DEBUG("invalid received Data : 0x%02X\n", Data);
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_DATA:
MMD1100context.DataLengthInPacket--;
if ( MMD1100context.DataLengthInPacket == 0 )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_ETX;
}
break;
case MMD1100_PACKET_CHECK_STATE_ETX:
if ( Data == MMD1100_DEFINE_ETX )
{
MMD1100context.PacketCheckState = MMD1100_PACKET_CHECK_STATE_BCC;
MMD1100context.PacketLength = 6 + MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH];
}
else
{
mmd1100_packet_flush_buffer();
// invaild command sequence
MMD1100_INFO("invalid received Data : 0x%02X\n", Data);
return -1;
}
break;
case MMD1100_PACKET_CHECK_STATE_BCC:
mmd1100_packet_flush_buffer();
MMD1100_DEBUG("received lenght : %d\n", MMD1100context.PacketLength);
if ( Data == lrc_xor(MMD1100context.pBufferForPacket, MMD1100context.PacketLength) )
{
MMD1100_INFO("BCC : OK\n");
return 0;
}
else
{
MMD1100_ERROR("BCC : Fail\n");
return -2;
}
break;
}
}
// check inter-character timeout
if ( MMD1100context.PacketCheckState != MMD1100_PACKET_CHECK_STATE_STX )
{
clock_gettime(CLOCK_REALTIME, &CurrentTime);
if ( (CurrentTime.tv_nsec - GetTimeToLastData.tv_nsec) > (MMD1100_TIMEOUT_BETWEEN_SERIAL_INPUT_DATA * 1000)/**/ )
{
mmd1100_packet_flush_buffer();
// return -4; /* Time out */
}
}
return -4; /* Not Ready */
}
/* receive
return:
-1: Fail to operation
-2: Input Parameter Error
-4: Timeout or Not Ready
0: OK
*/
int mmd1100_receive(MSRTrack_t *pMSRTrack,
MMD1100Response_t *pResponse,
uint32_t *pIsNotTrack,
uint32_t ResponseMilisecondTimeout)
{
struct timespec Start;
struct timespec Current;
uint32_t Position;
int Result;
if ( pIsNotTrack == (uint32_t *)0 )
{
return -2;
}
clock_gettime(CLOCK_REALTIME, &Start);
while(1)
{
Result = mmd1100_packet_make_response_from_serial_buffer();
if ( Result == -4 ) /* Not ready or time-out */
{
clock_gettime(CLOCK_REALTIME, &Current);
if ( (Current.tv_nsec - Start.tv_nsec) > (ResponseMilisecondTimeout * 1000) )
{
// MMD1100_DEBUG("time-out :start - %d nsec, cur = %d nsec, timeout = %d nsec \n", Start, Current, (ResponseMilisecondTimeout * 1000) );
return -4;
}
continue;
}
if ( Result != 0 )
{
MMD1100_DEBUG("response_check() return - %d\n", Result);
return -1;
}
break;
}
if( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] == MMD1100_DEFINE_TRACK_DATA)
{ /* Track Data */
*pIsNotTrack = 0;
if ( pMSRTrack == (MSRTrack_t *)0 )
{
return -2;
}
memset( pMSRTrack, 0, sizeof(MSRTrack_t) );
{
Position = MMD1100_PACKET_POSITION_TRACK_ID;
while ( MMD1100context.pBufferForPacket[Position] != MMD1100_DEFINE_ETX )
{
int i;
if ( MMD1100context.pBufferForPacket[Position] == MMD1100_DEFINE_TRACK_ID_1 )
{
if ( MMD1100context.pBufferForPacket[Position + 2] == MMD1100_DEFINE_NAK)
{
pMSRTrack->ErrorCodeForTrack1 = MMD1100context.pBufferForPacket[Position + 3];
pMSRTrack->LengthOfTrack1 = 0;
}
else
{
int temp;
pMSRTrack->ErrorCodeForTrack1 = 0;
pMSRTrack->LengthOfTrack1 = 0;
pMSRTrack->LengthOfRaw1 = MMD1100context.pBufferForPacket[Position + 1];
memcpy( pMSRTrack->pRaw1, &MMD1100context.pBufferForPacket[Position + 3], pMSRTrack->LengthOfRaw1 );
temp = mmd100_convert_rawdata_to_bcd( pMSRTrack->pTrack1,
&MMD1100context.pBufferForPacket[Position + 3],
MMD1100context.pBufferForPacket[Position + 1],
1);
if (temp > 0)
{
pMSRTrack->LengthOfTrack1 = temp;
}
}
}
if ( MMD1100context.pBufferForPacket[Position] == MMD1100_DEFINE_TRACK_ID_2 )
{
if ( MMD1100context.pBufferForPacket[Position + 2] == MMD1100_DEFINE_NAK)
{
pMSRTrack->ErrorCodeForTrack2 = MMD1100context.pBufferForPacket[Position + 3];
pMSRTrack->LengthOfTrack2 = 0;
}
else
{
int temp;
pMSRTrack->ErrorCodeForTrack2 = 0;
pMSRTrack->LengthOfTrack2 = 0;
pMSRTrack->LengthOfRaw2 = MMD1100context.pBufferForPacket[Position + 1];
memcpy( pMSRTrack->pRaw2, &MMD1100context.pBufferForPacket[Position + 3], pMSRTrack->LengthOfRaw2 );
temp = mmd100_convert_rawdata_to_bcd( pMSRTrack->pTrack2,
&MMD1100context.pBufferForPacket[Position + 3],
MMD1100context.pBufferForPacket[Position + 1],
1);
if (temp > 0)
{
pMSRTrack->LengthOfTrack2 = temp;
}
else
{
MMD1100_ERROR( " mmd100_convert_rawdata_to_bcd() = -%d", -temp);
}
}
}
if ( MMD1100context.pBufferForPacket[Position] == MMD1100_DEFINE_TRACK_ID_3 )
{
if ( MMD1100context.pBufferForPacket[Position + 2] == MMD1100_DEFINE_NAK)
{
pMSRTrack->ErrorCodeForTrack3 = MMD1100context.pBufferForPacket[Position + 3];
pMSRTrack->LengthOfTrack3 = 0;
}
else
{
int temp;
pMSRTrack->ErrorCodeForTrack3 = 0;
pMSRTrack->LengthOfTrack3 = 0;
pMSRTrack->LengthOfRaw3 = MMD1100context.pBufferForPacket[Position + 1];
memcpy( pMSRTrack->pRaw3, &MMD1100context.pBufferForPacket[Position + 3], pMSRTrack->LengthOfRaw3 );
temp = mmd100_convert_rawdata_to_bcd( pMSRTrack->pTrack3,
&MMD1100context.pBufferForPacket[Position + 3],
MMD1100context.pBufferForPacket[Position + 1],
1);
if (temp > 0)
{
pMSRTrack->LengthOfTrack3 = temp;
}
else
{
MMD1100_ERROR( " mmd100_convert_rawdata_to_bcd() = -%d", -temp);
}
}
}
Position += (3 + MMD1100context.pBufferForPacket[Position + 1]);
}
}
}
else /* Response */
{
*pIsNotTrack = 1;
if ( pResponse == (MMD1100Response_t *)0 )
{
return -2;
}
memset( pResponse, 0, sizeof(MMD1100Response_t) );
switch ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_CLASS] )
{
case MMD1100_COMMAND_CLASS_GET_VERSION:
pResponse->Command = MMD1100_COMMAND_GET_VERSION;
break;
case MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS:
pResponse->Command = MMD1100_COMMAND_LOAD_USER_PARAMETERS;
break;
case MMD1100_COMMAND_CLASS_UART_CALIBRATION:
pResponse->Command = MMD1100_COMMAND_UART_CALIBRATION;
break;
case MMD1100_COMMAND_CLASS_OTP_WRITE:
pResponse->Command = MMD1100_COMMAND_OTP_WRITE;
break;
case MMD1100_COMMAND_CLASS_GET_STATUS:
pResponse->Command = MMD1100_COMMAND_GET_STATUS;
break;
case MMD1100_COMMAND_CLASS_READ_DATA_RETRY:
pResponse->Command = MMD1100_COMMAND_READ_DATA_RETRY;
break;
case MMD1100_COMMAND_CLASS_SOFTWARE_RESET:
pResponse->Command = MMD1100_COMMAND_SOFTWARE_RESET;
break;
}
if ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_STATUS] == MMD1100_DEFINE_NAK )
{
pResponse->ErrorCode = MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_DATA_START];
}
else /* ( MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_STATUS] == MMD1100_DEFINE_ACK ) */
{
pResponse->ErrorCode = 0;
memcpy( pResponse->pData, &MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_DATA_START], MMD1100context.pBufferForPacket[MMD1100_PACKET_POSITION_LENGTH] );
}
}
return 0;
}
/*
-1: invalid parameter
0 : OK
*/
int mmd1100_make_packet(uint8_t *pPacket,
uint32_t *pMakedPacketByteLength,
MMD1100_Command_t Command,
uint8_t pArguments[4])
{
if((pPacket == (uint8_t *)0) || (pMakedPacketByteLength == (uint32_t *)0))
{
return -1;
}
pPacket[0] = MMD1100_DEFINE_STX; /* STX */
switch(Command)
{
case MMD1100_COMMAND_GET_VERSION:
pPacket[1] = MMD1100_COMMAND_CLASS_GET_VERSION; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_GET_VERSION; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_GET_VERSION; /* Length */
pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 6;
pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */
break;
case MMD1100_COMMAND_LOAD_USER_PARAMETERS:
if(pArguments == (uint8_t *)0)
{
return -1;
}
pPacket[1] = MMD1100_COMMAND_CLASS_LOAD_USER_PARAMETERS; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_LOAD_USER_PARAMETERS; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_LOAD_USER_PARAMETERS; /* Length */
pPacket[4] = pArguments[0]; /* Tx Mode 1 Byte */
pPacket[5] = pArguments[1]; /* Reserved 1 Byte */
pPacket[6] = pArguments[2]; /* All Track Error 1 Byte */
pPacket[7] = pArguments[3]; /* Reserved 1 Byte */
pPacket[8] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 10;
pPacket[9] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */
break;
case MMD1100_COMMAND_UART_CALIBRATION:
pPacket[1] = MMD1100_COMMAND_CLASS_UART_CALIBRATION; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_UART_CALIBRATION; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_UART_CALIBRATION; /* Length */
pPacket[4] = 0xAA; /* */
pPacket[5] = 0xAA; /* */
pPacket[6] = 0xAA; /* */
pPacket[7] = 0xAA; /* */
pPacket[8] = 0xAA; /* */
pPacket[9] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 11;
pPacket[10] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */
break;
case MMD1100_COMMAND_OTP_WRITE:
pPacket[1] = MMD1100_COMMAND_CLASS_OTP_WRITE; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_OTP_WRITE; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_OTP_WRITE; /* Length */
pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 6;
pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1)); /* BCC */
break;
case MMD1100_COMMAND_GET_STATUS:
pPacket[1] = MMD1100_COMMAND_CLASS_GET_STATUS; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_GET_STATUS; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_GET_STATUS; /* Length */
pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 6;
pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1) ); /* BCC */
break;
case MMD1100_COMMAND_READ_DATA_RETRY:
pPacket[1] = MMD1100_COMMAND_CLASS_READ_DATA_RETRY; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_READ_DATA_RETRY; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_READ_DATA_RETRY; /* Length */
pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 6;
pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1) ); /* BCC */
break;
case MMD1100_COMMAND_SOFTWARE_RESET:
pPacket[1] = MMD1100_COMMAND_CLASS_SOFTWARE_RESET; /* Class */
pPacket[2] = MMD1100_COMMAND_FUNCTION_SOFTWARE_RESET; /* Function */
pPacket[3] = MMD1100_COMMAND_LENGTH_SOFTWARE_RESET; /* Length */
pPacket[4] = MMD1100_DEFINE_ETX; /* ETX */
*pMakedPacketByteLength = 6;
pPacket[5] = lrc_xor(pPacket, (*pMakedPacketByteLength - 1) ); /* BCC */
break;
default:
return -1;
break;
}
return 0;
}
/*
-1: invalid parameter
-2: send error
0 : Not open
+ : Send length
*/
int mmd1100_send(uint8_t *pPacket,
uint8_t PacketByteLength)
{
uint32_t Index;
if ( ( pPacket == (uint8_t *)0 ) || ( PacketByteLength == 0 ) )
{
return -1;
}
if ( MMD1100context.Device == -1 )
{
return 0;
}
mmd1100_serial_flush();
for ( Index = 0; Index < PacketByteLength; Index ++ )
{
if ( write( MMD1100context.Device, &pPacket[Index], 1 ) != 1 )
{
MMD1100_ERROR( "failed to send packet to MSR controller(MMD1100) %s\n", DEVICE_MMD1100 );
return -2;
}
}
tcdrain( MMD1100context.Device );
return Index;
}
Test App Source
int DeviceFileDescriptorForMSR;
MSRTrack_t MSRTrack;
MMD1100Response_t MSRResponse;
uint32_t IsNotTrack;
uint8_t pVersion[1024];
int ConvertLength;
....
if ( mmd1100_open( &DeviceFileDescriptorForMSR ) != 0 )
{
printf("Fail to mmd1100_open\n");
}
else
{
printf("OK to mmd1100_open\n");
}
....
while( ?? )
{
....
if ( mmd1100_receive( &MSRTrack, &MSRResponse, &IsNotTrack, 10000/*10ms ResponseTimeout*/) == 0 )
{
printf("MSR IN\n");
if ( IsNotTrack == 1 )
{
switch ( MSRResponse.Command )
{
case MMD1100_COMMAND_GET_VERSION:
if ( MSRResponse.ErrorCode == 0 )
{
printf(" MMD1100_COMMAND_GET_VERSION : %s\n", MSRResponse.pData );
}
else
{
printf(" MMD1100_COMMAND_GET_VERSION : Error = 0x%02X\n", MSRResponse.ErrorCode );
}
break;
case MMD1100_COMMAND_LOAD_USER_PARAMETERS:
break;
case MMD1100_COMMAND_UART_CALIBRATION:
break;
case MMD1100_COMMAND_OTP_WRITE:
break;
case MMD1100_COMMAND_GET_STATUS:
break;
case MMD1100_COMMAND_READ_DATA_RETRY:
break;
case MMD1100_COMMAND_SOFTWARE_RESET:
break;
default:
break;
}
}
else
{
int i;
if ( MSRTrack.ErrorCodeForTrack1 == 0 )
{
printf( " Track 1 : " );
for ( i = 0; i < MSRTrack.LengthOfTrack1; i++ )
{
printf( "%c", MSRTrack.pTrack1[i] );
}
printf( "\n" );
if ( ( (MSRTrack.LengthOfTrack1 * 8) % 7 ) == 0 )
{
printf( " Length OK \n" );
}
}
else
{
printf(" Track 1 : ErrorCode = 0x%02X\n", MSRTrack.ErrorCodeForTrack1 );
}
if ( MSRTrack.ErrorCodeForTrack2 == 0 )
{
printf( " Track 2 Raw Data : (Length = %d)\n ", MSRTrack.LengthOfRaw2 );
for ( i = 0; i < MSRTrack.LengthOfRaw2; i++ )
{
printf( "%02X ", MSRTrack.pRaw2[i] );
}
printf( "\n" );
printf( " Track 2 : (Length = %d)\n ", MSRTrack.LengthOfTrack2 );
for ( i = 0; i < MSRTrack.LengthOfTrack2; i++ )
{
printf( "%c", MSRTrack.pTrack2[i] );
}
printf( "\n" );
}
else
{
printf(" Track 2 : ErrorCode = 0x%02X\n", MSRTrack.ErrorCodeForTrack2 );
}
if ( MSRTrack.ErrorCodeForTrack3 == 0 )
{
printf( " Track 3 Raw Data : (Length = %d)\n ", MSRTrack.LengthOfRaw3 );
for ( i = 0; i < MSRTrack.LengthOfRaw3; i++ )
{
printf( "%02X ", MSRTrack.pRaw3[i] );
}
printf( "\n" );
printf( " Track 3 : (Length = %d)\n ", MSRTrack.LengthOfTrack3 );
for ( i = 0; i < MSRTrack.LengthOfTrack3; i++ )
{
printf( "%c", MSRTrack.pTrack3[i] );
}
printf( "\n" );
}
else
{
printf(" Track 3 : ErrorCode = 0x%02X\n", MSRTrack.ErrorCodeForTrack3 );
}
}
}
....
}
Result …
MSR IN Track 1 : ErrorCode = 0x55 Track 2 Raw Data : (Length = 31) 00 00 00 F0 7F 08 21 84 19 C8 14 8D 40 88 10 09 13 DA D9 08 27 61 92 16 02 22 2D 13 0D 00 00 Track 2 : (Length = 45) ;4364200649047469=19042211468940900000?? Track 3 Raw Data : (Length = 88) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 1F 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 10 42 08 21 84 A0 01 00 00 00 00 00 20 Track 3 : (Length = 129) ;00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000?4
필요 라이브러리 소스
int memory_pick_up_bit( void *pMemory,
uint32_t TotalBitInMemory,
uint32_t BitPositionInMemory,
int StartFromLast)
{
uint8_t * pByte;
if ( pMemory == (void *)0 )
{
return -1;
}
pByte = (uint8_t *)pMemory;
if (StartFromLast == 0)
{
if ( ( pByte[BitPositionInMemory >> 3] & (0x01 << ( BitPositionInMemory & 0x07 ) ) ) != 0 )
{
return 1;
}
else
{
return 0;
}
}
else
{
BitPositionInMemory = TotalBitInMemory - BitPositionInMemory;
if ( ( pByte[BitPositionInMemory >> 3] & (0x01 << ( BitPositionInMemory & 0x07 ) ) ) != 0 )
{
return 1;
}
else
{
return 0;
}
}
}
uint8_t lrc_xor(uint8_t *pData, uint32_t ByteLength)
{
uint8_t LRC = 0;
while(ByteLength--)
LRC ^= *pData++;
return LRC;
}