This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
msr_test [2017/09/12 21:25] 1.241.172.144 created |
msr_test [2017/09/12 21:35] (current) 1.241.172.144 |
||
|---|---|---|---|
| Line 127: | Line 127: | ||
| | | ||
| #endif /* __MMD1100_H__ */ | #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; | ||
| + | } | ||
| + | |||