/* file i3c_master_read_sensor_p3t1755_IBI.c * * Copyright (C) 2025 MACNICA,Inc. All Rights Reserved. * This software is licensed "AS IS". * Please perform use of this software by a user's own responsibility and expense. * It cannot guarantee in the maker side about the damage which occurred * by the ab-ility not to use or use this software, and all damage that occurred secondarily. * Created on: 2025/8/19 */ /* Standard C Included Files */ #include /* SDK Included Files */ #include "fsl_debug_console.h" #include "fsl_p3t1755.h" #include "fsl_i3c.h" #include "board.h" #include "app.h" #include "pin_mux.h" /******************************************************************************* * Definitions ******************************************************************************/ #define I3C_TIME_OUT_INDEX 100000000U #define SENSOR_ADDR 0x08U #define CCC_RSTDAA 0x06U #define CCC_SETDASA 0x87 #define CCC_ENEC 0x80U /* Enable Events (Direct CCC) */ #define ENINT_BYTE 0x01U /* bit0 = ENINT */ /******************************************************************************* * Prototypes ******************************************************************************/ static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData); static void i3c_master_ibi_callback(I3C_Type *base, i3c_master_handle_t *handle, i3c_ibi_type_t ibiType, i3c_ibi_state_t ibiState); /******************************************************************************* * Variables ******************************************************************************/ volatile status_t g_completionStatus; volatile bool g_masterCompletionFlag; i3c_master_handle_t g_i3c_m_handle; p3t1755_handle_t p3t1755Handle; const i3c_master_transfer_callback_t masterCallback = { .slave2Master = NULL, .ibiCallback = i3c_master_ibi_callback, .transferComplete = i3c_master_callback}; static volatile bool s_ibiRequest = false; static volatile uint8_t s_ibiAddr = 0; /******************************************************************************* * Code ******************************************************************************/ static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { g_masterCompletionFlag = true; } g_completionStatus = status; } static void i3c_master_ibi_callback(I3C_Type *base, i3c_master_handle_t *handle, i3c_ibi_type_t ibiType, i3c_ibi_state_t ibiState) { if (ibiState == kI3C_IbiAckNackPending) { I3C_MasterEmitIBIResponse(base, kI3C_IbiRespAck); // P3T1755はmandatory無し } else if (ibiState == kI3C_IbiReady) { s_ibiAddr = handle->ibiAddress; s_ibiRequest = true; // ここではフラグだけ LED_RED_ON(); // 任意: IBI受信インジケータ } } static void APP_I3C_RegisterIbiRule(uint8_t dynAddr) { i3c_register_ibi_addr_t rule = {0}; rule.address[0] = dynAddr; // 今回はP3T1755の動的アドレス rule.i3cFastStart = true; // 任意 rule.ibiHasPayload = false; // P3T1755はmandatoryペイロード無し I3C_MasterRegisterIBI(EXAMPLE_MASTER, &rule); } status_t I3C_WriteSensor(uint8_t deviceAddress, uint32_t regAddress, uint8_t *regData, size_t dataSize) { status_t result = kStatus_Success; i3c_master_transfer_t masterXfer = {0}; uint32_t timeout = 0U; masterXfer.slaveAddress = deviceAddress; masterXfer.direction = kI3C_Write; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.subaddress = regAddress; masterXfer.subaddressSize = 1; masterXfer.data = regData; masterXfer.dataSize = dataSize; masterXfer.flags = kI3C_TransferDefaultFlag; g_masterCompletionFlag = false; g_completionStatus = kStatus_Success; result = I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &g_i3c_m_handle, &masterXfer); if (kStatus_Success != result) { return result; } while (!g_masterCompletionFlag) { timeout++; if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX)) { break; } } if (timeout == I3C_TIME_OUT_INDEX) { result = kStatus_Timeout; } result = g_completionStatus; return result; } status_t I3C_ReadSensor(uint8_t deviceAddress, uint32_t regAddress, uint8_t *regData, size_t dataSize) { status_t result = kStatus_Success; i3c_master_transfer_t masterXfer = {0}; uint32_t timeout = 0U; masterXfer.slaveAddress = deviceAddress; masterXfer.direction = kI3C_Read; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.subaddress = regAddress; masterXfer.subaddressSize = 1; masterXfer.data = regData; masterXfer.dataSize = dataSize; masterXfer.flags = kI3C_TransferDefaultFlag; g_masterCompletionFlag = false; g_completionStatus = kStatus_Success; result = I3C_MasterTransferNonBlocking(EXAMPLE_MASTER, &g_i3c_m_handle, &masterXfer); if (kStatus_Success != result) { return result; } while (!g_masterCompletionFlag) { timeout++; if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX)) { break; } } if (timeout == I3C_TIME_OUT_INDEX) { result = kStatus_Timeout; } result = g_completionStatus; return result; } static void P3T1755_EncodeTemp(double c, uint8_t out[2]) { int16_t raw = (int16_t)(c / 0.0625); // 1 LSB = 0.0625°C out[0] = (uint8_t)((raw >> 4) & 0xFF); out[1] = (uint8_t)((raw & 0x0F) << 4); } static status_t P3T1755_SetThresholds(double tLowC, double tHighC) { uint8_t v[2]; status_t st; P3T1755_EncodeTemp(tLowC, v); st = I3C_WriteSensor(SENSOR_ADDR, P3T1755_TEMPERATURE_LOW_REG, v, 2); if (st) return st; P3T1755_EncodeTemp(tHighC, v); st = I3C_WriteSensor(SENSOR_ADDR, P3T1755_TEMPERATURE_HIGH_REG, v, 2); return st; } status_t p3t1755_set_thresholds_relative(p3t1755_handle_t *handle) { status_t result; double currentTemp; /* 現在の温度を取得 */ result = P3T1755_ReadTemperature(handle, ¤tTemp); if (result != kStatus_Success) { PRINTF("Failed to read current temperature.\r\n"); return result; } /* ±1℃ の閾値を設定 */ double lowThreshold = currentTemp + 1.0; double highThreshold = currentTemp + 2.0; result = P3T1755_SetThresholds(lowThreshold, highThreshold); if (result != kStatus_Success) { PRINTF("Failed to set thresholds.\r\n"); return result; } PRINTF("Thresholds set: Low=%.2f°C, High=%.2f°C\r\n", lowThreshold, highThreshold); return kStatus_Success; } status_t P3T1755_EnableTMMode(p3t1755_handle_t *handle) { status_t result = kStatus_Success; uint8_t conf; result = P3T1755_ReadReg(handle, P3T1755_CONFIG_REG, &conf, 1); if (result != kStatus_Success) { return result; } /* Interrupt Mode (TM=1) */ conf = (conf & ~0x02u) | 0x02u; result = P3T1755_WriteReg(handle, P3T1755_CONFIG_REG, &conf, 1); return result; } status_t p3t1755_set_dynamic_address(void) { status_t result = kStatus_Success; i3c_master_transfer_t masterXfer = {0}; uint8_t g_master_txBuff[1]; /* Reset dynamic address. */ g_master_txBuff[0] = CCC_RSTDAA; masterXfer.slaveAddress = 0x7E; masterXfer.data = g_master_txBuff; masterXfer.dataSize = 1; masterXfer.direction = kI3C_Write; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.flags = kI3C_TransferDefaultFlag; result = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer); if (result != kStatus_Success) { return result; } /* Assign dynmic address. */ memset(&masterXfer, 0, sizeof(masterXfer)); g_master_txBuff[0] = CCC_SETDASA; masterXfer.slaveAddress = 0x7E; masterXfer.data = g_master_txBuff; masterXfer.dataSize = 1; masterXfer.direction = kI3C_Write; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.flags = kI3C_TransferNoStopFlag; result = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer); if (result != kStatus_Success) { return result; } memset(&masterXfer, 0, sizeof(masterXfer)); g_master_txBuff[0] = SENSOR_ADDR << 1; masterXfer.slaveAddress = SENSOR_SLAVE_ADDR; masterXfer.data = g_master_txBuff; masterXfer.dataSize = 1; masterXfer.direction = kI3C_Write; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.flags = kI3C_TransferDefaultFlag; return I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer); } /* 動的アドレス(SENSOR_ADDR)に対して ENEC(ENINT) を発行して IBI を許可 */ status_t p3t1755_enable_enint(uint8_t sensorAddr) { status_t result = kStatus_Success; i3c_master_transfer_t masterXfer = {0}; uint8_t g_master_txBuff[1]; /* ENEC を 0x7E(Broadcast)へ送信(NoStopで次のターゲット書き込みに繋ぐ) */ g_master_txBuff[0] = CCC_ENEC; masterXfer.slaveAddress = 0x7E; masterXfer.data = g_master_txBuff; masterXfer.dataSize = 1; masterXfer.direction = kI3C_Write; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.flags = kI3C_TransferNoStopFlag; result = I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer); if (result != kStatus_Success) { return result; } /* 続けて、対象の動的アドレスに ENINT=1 を送信 */ memset(&masterXfer, 0, sizeof(masterXfer)); g_master_txBuff[0] = ENINT_BYTE; masterXfer.slaveAddress = sensorAddr; /* 引数で指定したアドレス */ masterXfer.data = g_master_txBuff; masterXfer.dataSize = 1; masterXfer.direction = kI3C_Write; masterXfer.busType = kI3C_TypeI3CSdr; masterXfer.flags = kI3C_TransferDefaultFlag; return I3C_MasterTransferBlocking(EXAMPLE_MASTER, &masterXfer); } /*! * @brief Main function */ int main(void) { status_t result = kStatus_Success; i3c_master_config_t masterConfig; p3t1755_config_t p3t1755Config; double temperature; BOARD_InitHardware(); gpio_pin_config_t led_config = { kGPIO_DigitalOutput, 0, }; BOARD_InitLEDsPins(); GPIO_PinInit(BOARD_LED_RED_GPIO,BOARD_LED_RED_GPIO_PIN, &led_config); GPIO_PinInit(BOARD_LED_BLUE_GPIO,BOARD_LED_BLUE_GPIO_PIN, &led_config); GPIO_PinInit(BOARD_LED_GREEN_GPIO,BOARD_LED_GREEN_GPIO_PIN, &led_config); LED_RED_INIT(LOGIC_LED_OFF); LED_BLUE_INIT(LOGIC_LED_OFF); LED_GREEN_INIT(LOGIC_LED_OFF); PRINTF("\r\nI3C master read sensor data example.\r\n"); I3C_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate_Hz.i2cBaud = EXAMPLE_I2C_BAUDRATE; masterConfig.baudRate_Hz.i3cPushPullBaud = EXAMPLE_I3C_PP_BAUDRATE; masterConfig.baudRate_Hz.i3cOpenDrainBaud = EXAMPLE_I3C_OD_BAUDRATE; masterConfig.enableOpenDrainStop = false; masterConfig.disableTimeout = true; I3C_MasterInit(EXAMPLE_MASTER, &masterConfig, I3C_MASTER_CLOCK_FREQUENCY); /* Create I3C handle. */ I3C_MasterTransferCreateHandle(EXAMPLE_MASTER, &g_i3c_m_handle, &masterCallback, NULL); result = p3t1755_set_dynamic_address(); if (result != kStatus_Success) { PRINTF("\r\nP3T1755 set dynamic address failed.\r\n"); } p3t1755Config.writeTransfer = I3C_WriteSensor; p3t1755Config.readTransfer = I3C_ReadSensor; p3t1755Config.sensorAddress = SENSOR_ADDR; P3T1755_Init(&p3t1755Handle, &p3t1755Config); APP_I3C_RegisterIbiRule(SENSOR_ADDR); //result = P3T1755_SetThresholds(25.0, 28.0); result = p3t1755_set_thresholds_relative(&p3t1755Handle); if (result != kStatus_Success) { PRINTF("Set p3t1755_set_thresholds_relative failed (%d)\r\n", (int)result); } result = P3T1755_EnableTMMode(&p3t1755Handle); if (result != kStatus_Success) { PRINTF("Set P3T1755_EnableIntMode failed (%d)\r\n", (int)result); } result = p3t1755_enable_enint(SENSOR_ADDR); if (result != kStatus_Success) { PRINTF("ENEC failed (%d)\r\n", (int)result); } while (1) { if (s_ibiRequest) { s_ibiRequest = false; PRINTF("[IBI] from 0x%02X\r\n", s_ibiAddr); double temperature; status_t result = P3T1755_ReadTemperature(&p3t1755Handle, &temperature); if (result != kStatus_Success) { PRINTF("P3T1755 read after IBI failed.\r\n"); } else { PRINTF("Temperature after IBI:%f \r\n", temperature); } SDK_DelayAtLeastUs(1000000, CLOCK_GetCoreSysClkFreq()); LED_RED_OFF(); // 消灯 }else{ result = P3T1755_ReadTemperature(&p3t1755Handle, &temperature); if (result != kStatus_Success) { PRINTF("\r\nP3T1755 read temperature failed.\r\n"); } else { PRINTF("\r\nTemperature:%f \r\n", temperature); } SDK_DelayAtLeastUs(1000000, CLOCK_GetCoreSysClkFreq()); } } }