#include #include #include #include #include // 딜레이 함수 이용을 위해 #include //Sleep(1); // 1ms 딜레이 //Sleep(10); // 10ms 딜레이 //Sleep(100); // 100ms 딜레이 // FT4222 헤더 #include "ftd2xx.h" #include "LibFT4222.h" uint8_t PMIC_I2C_SLAVE_ADDR = 0x55; // 현재 시간을 "HH:MM:SS" 형식으로 buf에 저장 void currentTime(char* buf, size_t len) { if (buf == nullptr || len == 0) return; time_t now = time(nullptr); struct tm tm_buf; #ifdef _WIN32 localtime_s(&tm_buf, &now); // Windows 안전 버전 #else localtime_r(&now, &tm_buf); // Linux/Unix 안전 버전 #endif strftime(buf, len, "%H:%M:%S", &tm_buf); } // 로그 출력 (커스텀 포맷) void logPacket(const char* dir, uint8_t* data, int size, int hasCrc) { if (dir == nullptr || data == nullptr || size <= 0) return; char timeBuf[32]; currentTime(timeBuf, sizeof(timeBuf)); // PMIC I2C WRITE if (strcmp(dir, "PMIC I2C WRITE") == 0 && size >= 3) { printf("[%s] [%s] len=%d [Address: 0x%02X] [Value: 0x%02X] [CRC: 0x%02X]\n", timeBuf, dir, size, data[0], data[1], data[2]); return; } // PMIC I2C READ if (strcmp(dir, "PMIC I2C READ") == 0 && size >= 2) { printf("[%s] [%s] len=%d [Value: 0x%02X] [CRC: 0x%02X]\n", timeBuf, dir, size, data[0], data[1]); return; } // 기본 출력 (기타 상황) printf("[%s] [%s] len=%d ", timeBuf, dir, size); for (int i = 0; i < size; i++) { if (hasCrc && i == size - 1) printf("[CRC: %02X] ", data[i]); else printf("%02X ", data[i]); } printf("\n"); } // CRC8 계산 (다항식 0x07, 초기값 0x00) uint8_t calcCRC8(uint8_t addrWithRw, uint8_t* data, int len) { uint8_t crc = 0x00; for (int j = -1; j < len; j++) { uint8_t b = (j == -1) ? addrWithRw : data[j]; crc ^= b; for (int i = 0; i < 8; i++) { if (crc & 0x80) crc = (crc << 1) ^ 0x07; else crc <<= 1; } } return crc; } // 명령어 판별 (I2C_WRITE/w, I2C_READ/r) int parseCommand(const char* dir) { if (strcmp(dir, "I2C_WRITE") == 0 || strcmp(dir, "W") == 0) return 1; if (strcmp(dir, "I2C_READ") == 0 || strcmp(dir, "R") == 0) return 2; return 0; } // Address에 1바이트 Write with CRC, 그리고 Address를 Read해서 Write한 값과 비교 void PMIC_I2C_Write(FT_HANDLE ftHandle, uint8_t slaveAddr, uint8_t regAddr, uint8_t value) { uint8_t bytes[3]; int len = 0; // Write 패킷: [RegAddr] [Value] [CRC] bytes[len++] = regAddr; bytes[len++] = value; uint8_t addrWithRw = (slaveAddr << 1) | 0x00; // Write 주소 uint8_t crc = calcCRC8(addrWithRw, bytes, len); bytes[len++] = crc; uint16 transferred = 0; FT4222_STATUS st = FT4222_I2CMaster_Write(ftHandle, slaveAddr, bytes, (uint16)len, &transferred); if (st != FT4222_OK) { printf("I2C Write 실패\n"); return; } else { logPacket("PMIC I2C WRITE", bytes, len, 1); } // Register Address 다시 Write (Read 시작 위치 지정) uint8_t regOnly[1] = { regAddr }; st = FT4222_I2CMaster_Write(ftHandle, slaveAddr, regOnly, 1, &transferred); if (st != FT4222_OK) { printf("Read용 Address Write 실패\n"); return; } // Register Address에서 2바이트 Read uint8_t rx[2] = { 0 }; st = FT4222_I2CMaster_Read(ftHandle, slaveAddr, rx, 2, &transferred); if (st != FT4222_OK) { printf("I2C Read 실패\n"); return; } else { logPacket("PMIC I2C READ ", rx, transferred, 0); // 첫 번째 바이트와 Write 값 비교 if (rx[0] == value) { printf("확인 성공: [Write Value = 0x%02X], [Read Value = 0x%02X]\n", value, rx[0]); } else { printf("불일치: [Write Value = 0x%02X], [Read Value = 0x%02X]\n", value, rx[0]); } } } // Address에서 1바이트 Read (CRC 계산 없음) void PMIC_I2C_Read(FT_HANDLE ftHandle, uint8_t slaveAddr, uint8_t regAddr) { uint16 transferred = 0; FT4222_STATUS st; // 🔹 Register Address를 먼저 Write (Read 시작 위치 지정) uint8_t regOnly[1] = { regAddr }; st = FT4222_I2CMaster_Write(ftHandle, slaveAddr, regOnly, 1, &transferred); if (st != FT4222_OK) { printf("Read용 Address Write 실패\n"); return; } // 🔹 Register Address에서 2바이트 Read (Value + CRC) uint8_t rx[2] = { 0 }; st = FT4222_I2CMaster_Read(ftHandle, slaveAddr, rx, 2, &transferred); if (st != FT4222_OK) { printf("I2C Read 실패\n"); return; } else { printf("Read 결과: [Address = 0x%02X], [Value = 0x%02X], [CRC = 0x%02X]\n", regAddr, rx[0], rx[1]); } } int main() { printf("PMIC I2C Packet Logger with FT4222\n \n"); char addrInput[16]; unsigned int tempAddr = 0; uint8_t I2C_SLAVE_ADDR = 0; unsigned long log_counter = 0; char timeStr[16]; // 시간을 저장할 버퍼 (HH:MM:SS면 9바이트면 충분) currentTime(timeStr, sizeof(timeStr)); //printf("현재 시간: %s\n", timeStr); #if 0 printf("I2C Address\n Regulation Register is 0x54\n Protection Register is 0x55\n \nEnter 7-bit I2C Slave Address (hex): "); if (scanf_s("%15s", addrInput, (unsigned)_countof(addrInput)) != 1) { printf("입력 오류\n"); return -1; } if (sscanf_s(addrInput, "%x", &tempAddr) != 1) { printf("잘못된 주소 입력\n"); return -1; } I2C_SLAVE_ADDR = (uint8_t)tempAddr; printf("슬레이브 주소 설정됨: 0x%02X\n", I2C_SLAVE_ADDR); getchar(); // 버퍼 클리어 printf("사용법: I2C_WRITE 또는 w \n"); printf(" I2C_READ (항상 2바이트 읽음) 또는 r\n"); printf("exit 또틑 e 입력 시 종료\n"); #endif printf("Read Regulation 0x54, Page 0x02, Address 0x23 : 0x66 이면 OK\n "); FT_HANDLE ftHandle = NULL; FT_STATUS ftStatus; DWORD numDevs = 0; ftStatus = FT_CreateDeviceInfoList(&numDevs); if (ftStatus != FT_OK || numDevs == 0) { printf("FT4222 장치를 찾을 수 없습니다.\n"); return -1; } ftStatus = FT_Open(0, &ftHandle); if (ftStatus != FT_OK) { printf("FT4222 장치 열기 실패\n"); return -1; } FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, 400); // 400kHz if (ft4222Status != FT4222_OK) { printf("I2C Master 초기화 실패\n"); FT_Close(ftHandle); return -1; } //Fault register data: 0x010 ~0x014, 0x019 ~0x021 //0x010 - FUSA_STATUS_1 //0x011 - FUSA_STATUS_2 //0x012 - FUSA_STATUS_2A //0x013 - FUSA_STATUS_3 //0x014 - FUSA_STATUS_4 //0x019 - FLT_RECORD_A //0x01A - FLT_RECORD_B //0x01B - FLT_RECORD_GND_AVIN //0x01C - FLT_RECORD_BG_Temp //0x01D - FLT_RECORD_IntLDOs //0x01E - FLT_RECORD_ExtLDOs //0x01F - FLT_RECORD_BUCKS_B //0x020 - FLT_RECORD_BUCKS_A //0x021 - FLT_RECORD_ExtINPs_7_0 //printf("=================================================================================\n"); /******************************************************************************************** I2C Write PMIC_I2C_Write(FT_HANDLE ftHandle, uint8_t slaveAddr, uint8_t regAddr, uint8_t value) PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0xAA, 0xBB); ********************************************************************************************/ //printf("=================================================================================\n"); /******************************************************************************************** I2C Read PMIC_I2C_Read(FT_HANDLE ftHandle, uint8_t slaveAddr, uint8_t regAddr) PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0xAA); ********************************************************************************************/ //for (int i = 0; i < 10000000; i++) { //while (1) { //} //for (int i = 0; i < 10000000; i++) { //while (log_counter < 10 ){ // 예: 10번 while에 한 번만 실행 //if (log_counter % 10 == 0) { // 30ms 딜레이 //Sleep(30); printf("실행하려면 Enter 키를 누르세요...\n"); getchar(); //Regulation Register // Page00 PMIC_I2C_Write(ftHandle, 0x54, 0x00, 0x00); PMIC_I2C_Write(ftHandle, 0x54, 0x00, 0x00); PMIC_I2C_Read(ftHandle, 0x54, 0x00); //0x000 - IO_PAGE_REGU PMIC_I2C_Read(ftHandle, 0x54, 0x01); //0x001 - IO_CHIPNAME_REGU PMIC_I2C_Read(ftHandle, 0x54, 0x02); //0x002 - IO_CHIPVERSION_REGU PMIC_I2C_Read(ftHandle, 0x54, 0x03); //0x003 - IO_DIEID3_REGU //PMIC_I2C_Read(ftHandle, 0x54, 0x04); //0x004 //PMIC_I2C_Read(ftHandle, 0x54, 0x05); //0x005 //PMIC_I2C_Write(ftHandle, 0x54, 0x00, 0x02); //PMIC_I2C_Write(ftHandle, 0x54, 0x00, 0x02); //PMIC_I2C_Read(ftHandle, 0x54, 0x23); // 30ms 딜레이 //Sleep(30); // Page02 PMIC_I2C_Write(ftHandle, 0x54, 0x00, 0x02); PMIC_I2C_Write(ftHandle, 0x54, 0x00, 0x02); //PMIC_I2C_Read(ftHandle, 0x54, 0x20); //PMIC_I2C_Read(ftHandle, 0x54, 0x21); PMIC_I2C_Read(ftHandle, 0x54, 0x22); //0x222 - I_OTP_VERSION PMIC_I2C_Read(ftHandle, 0x54, 0x23); //0x223 - I_OTP_INTERNALVERSION //PMIC_I2C_Read(ftHandle, 0x54, 0x24); //PMIC_I2C_Read(ftHandle, 0x54, 0x25); // 30ms 딜레이 //Sleep(30); //Protection Register // Page01 PMIC_I2C_Write(ftHandle, 0x55, 0x00, 0x01); PMIC_I2C_Write(ftHandle, 0x55, 0x00, 0x01); PMIC_I2C_Read(ftHandle, 0x55, 0x02); //0x102 - IO_MODECTRL Read시 디폴트 0x65 PMIC_I2C_Write(ftHandle, 0x55, 0x02, 0x25); //0x102 - IO_MODECTRL // 10s 딜레이 Sleep(10000); PMIC_I2C_Write(ftHandle, 0x55, 0x02, 0x65); //0x102 - IO_MODECTRL //} //log_counter++; //} #if 0 //Protection Register //Regulation Register printf("[Page-0]=================================================================================\n"); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x00); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x00); PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00); //0x000 - IO_PAGE_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x01); //0x001 - IO_CHIPNAME_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x02); //0x002 - IO_CHIPVERSION_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x03); //0x003 - IO_DIEID3_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x04); //0x004 - IO_DIEID2_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x05); //0x005 - IO_DIEID1_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x06); //0x006 - IO_DIEID0_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x0A); //0x00A - OTP_VERSION_REGU PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x10); //0x010 - FUSA_STATUS_1 PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x11); //0x011 - FUSA_STATUS_2 PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x12); //0x012 - FUSA_STATUS_2A PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x13); //0x013 - FUSA_STATUS_3 PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x14); //0x014 - FUSA_STATUS_4 PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x19); //0x019 - FLT_RECORD_A PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x1A); //0x01A - FLT_RECORD_B PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x1B); //0x01B - FLT_RECORD_GND_AVIN PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x1C); //0x01C - FLT_RECORD_BG_Temp PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x1D); //0x01D - FLT_RECORD_IntLDOs PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x1E); //0x01E - FLT_RECORD_ExtLDOs PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x1F); //0x01F - FLT_RECORD_BUCKS_B printf("[Page-1]=================================================================================\n"); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x01); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x01); printf("[Page-2]=================================================================================\n"); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x02); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x02); PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x20); //0x020 - FLT_RECORD_BUCKS_A PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x21); //0x021 - FLT_RECORD_ExtINPs_7_0 printf("[PMIC_RAA271005_INIT]====================================================================\n"); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x01); PMIC_I2C_Write(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x00, 0x01); PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x07); //0x107 - WDT_CFG0 (OTP) PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x08); //0x108 - WDT_CFG1 (OTP) //WDT_ULCNT, WDT_LLCNT PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x09); //0x109 - WDT_CFG2 (OTP) PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x16); //0x116 - FUSA_TIMER_1 (OTP) PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x17); //0x117 - FUSA_TIMER_2 (OTP) PMIC_I2C_Read(ftHandle, PMIC_I2C_SLAVE_ADDR, 0x2C); //0x12C - FLT_MASK_B (OTP) #endif char line[256]; while (1) { printf("> "); if (!fgets(line, sizeof(line), stdin)) break; line[strcspn(line, "\r\n")] = 0; // 개행 제거 if (strcmp(line, "exit") == 0) break; if (strcmp(line, "e") == 0) break; if (strlen(line) == 0) continue; char* context = NULL; char* token = strtok_s(line, " ", &context); if (!token) continue; for (char* p = token; *p; p++) *p = toupper(*p); int command = parseCommand(token); if (command == 1) { // I2C_WRITE uint8_t bytes[256]; int len = 0; while ((token = strtok_s(NULL, " ", &context)) != NULL) { unsigned int val; if (sscanf_s(token, "%x", &val) == 1) { bytes[len++] = (uint8_t)val; } else { printf("잘못된 HEX 값: %s\n", token); } } if (len == 0) { printf("전송할 데이터가 없습니다.\n"); continue; } uint8_t addrWithRw = (I2C_SLAVE_ADDR << 1) | 0x00; uint8_t crc = calcCRC8(addrWithRw, bytes, len); bytes[len++] = crc; uint16 transferred = 0; ft4222Status = FT4222_I2CMaster_Write(ftHandle, I2C_SLAVE_ADDR, bytes, (uint16)len, &transferred); if (ft4222Status != FT4222_OK) { printf("I2C Write 실패\n"); } else { logPacket("I2C_WRITE", bytes, len, 1); } } else if (command == 2) { // I2C_READ uint8_t bytes[256]; uint16 transferred = 0; FT4222_STATUS st; int len = 0; while ((token = strtok_s(NULL, " ", &context)) != NULL) { unsigned int val; if (sscanf_s(token, "%x", &val) == 1) { bytes[len++] = (uint8_t)val; } else { printf("잘못된 HEX 값: %s\n", token); } } if (len == 0) { printf("전송할 데이터가 없습니다.\n"); continue; } uint8_t addrWithRw = (I2C_SLAVE_ADDR << 1) | 0x00; uint8_t crc = calcCRC8(addrWithRw, bytes, len); bytes[len++] = crc; st = FT4222_I2CMaster_Write(ftHandle, I2C_SLAVE_ADDR, bytes, (uint16)len, &transferred); if (st != FT4222_OK) { printf("Read용 Address Write 실패\n"); return 0; } // 🔹 Register Address에서 2바이트 Read (Value + CRC) uint8_t rx[2] = { 0 }; st = FT4222_I2CMaster_Read(ftHandle, I2C_SLAVE_ADDR, rx, 2, &transferred); if (st != FT4222_OK) { printf("I2C Read 실패\n"); return 0; } else { printf("Read 결과: [Address = 0x%02X], [Value = 0x%02X], [CRC = 0x%02X]\n", bytes[0], rx[0], rx[1]); } } else { printf("첫 단어는 I2C_WRITE(w) 또는 I2C_READ(r) 여야 합니다.\n"); } } FT_Close(ftHandle); return 0; }