| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755 | 
							- /**
 
- * MIT License
 
- *
 
- * Copyright (c) 2018 Infineon Technologies AG
 
- *
 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
 
- * of this software and associated documentation files (the "Software"), to deal
 
- * in the Software without restriction, including without limitation the rights
 
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
- * copies of the Software, and to permit persons to whom the Software is
 
- * furnished to do so, subject to the following conditions:
 
- *
 
- * The above copyright notice and this permission notice shall be included in all
 
- * copies or substantial portions of the Software.
 
- *
 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
- * SOFTWARE
 
- *
 
- *
 
- * \file ifx_i2c_physical_layer.c
 
- *
 
- * \brief   This file implements the IFX I2C Physical Layer.
 
- *
 
- * \addtogroup  grIFXI2C
 
- * @{
 
- */
 
- /***********************************************************************************************************************
 
- * HEADER FILES
 
- **********************************************************************************************************************/
 
- #include "optiga/ifx_i2c/ifx_i2c_physical_layer.h"
 
- #include "optiga/pal/pal_os_event.h"
 
- /// @cond hidden
 
- /***********************************************************************************************************************
 
- * MACROS
 
- **********************************************************************************************************************/
 
- // Physical Layer Register addresses
 
- #define PL_REG_DATA                     (0x80)
 
- #define PL_REG_DATA_REG_LEN             (0x81)
 
- #define PL_REG_I2C_STATE                (0x82)
 
- #define PL_REG_BASE_ADDR                (0x83)
 
- #define PL_REG_MAX_SCL_FREQU            (0x84)
 
- #define PL_REG_SOFT_RESET               (0x88)
 
- #define PL_REG_I2C_MODE                 (0x89)
 
- // Physical Layer Register lengths
 
- #define PL_REG_LEN_I2C_STATE            (4)
 
- #define PL_REG_LEN_MAX_SCL_FREQU        (4)
 
- #define PL_REG_LEN_I2C_MODE             (2)
 
- #define PL_REG_LEN_DATA_REG_LEN         (2)
 
- #define PL_REG_LEN_SOFT_RESET			(2)
 
- #define PL_REG_LEN_BASE_ADDR			(2)
 
- // Physical Layer State Register masks
 
- #define PL_REG_I2C_STATE_RESPONSE_READY (0x40)
 
- #define PL_REG_I2C_STATE_SOFT_RESET     (0x08)
 
- // Physical Layer low level interface constants
 
- #define PL_ACTION_READ_REGISTER         (0x01)
 
- #define PL_ACTION_WRITE_REGISTER        (0x02)
 
- #define PL_I2C_CMD_WRITE                (0x01)
 
- #define PL_I2C_CMD_READ                 (0x02)
 
- // Physical Layer high level interface constants
 
- #define PL_ACTION_WRITE_FRAME           (0x01)
 
- #define PL_ACTION_READ_FRAME            (0x02)
 
- #define PL_STATE_UNINIT                 (0x00)
 
- #define PL_STATE_INIT                   (0x01)
 
- #define PL_STATE_READY                  (0x02)
 
- #define PL_STATE_DATA_AVAILABLE         (0x03)
 
- #define PL_STATE_RXTX                   (0x04)
 
- #define PL_STATE_SOFT_RESET             (0x05)
 
- //Physical Layer negotiation constants
 
- #define PL_INIT_SET_DATA_REG_LEN        (0x11)
 
- #define PL_INIT_GET_DATA_REG_LEN        (0x22)
 
- #define PL_INIT_GET_FREQ_REG            (0x33)
 
- #define PL_INIT_SET_FREQ_REG            (0x44)
 
- #define PL_INIT_READ_FREQ               (0x55)
 
- #define PL_INIT_VERIFY_FREQ             (0x66)
 
- #define PL_INIT_AGREE_FREQ              (0x77)
 
- #define PL_INIT_VERIFY_DATA_REG         (0x88)
 
- #define PL_INIT_GET_STATUS_REG          (0x99)
 
- #define PL_INIT_DONE                    (0xAA)
 
- #define PL_INIT_SET_FREQ_DEFAULT        (0xBB)
 
- //Physical layer soft reset states
 
- #define PL_RESET_INIT                   (0xA1)
 
- #define PL_RESET_WRITE                  (0xA2)
 
- #define PL_RESET_STARTUP                (0xA3)
 
- #define PL_REG_I2C_MODE_PERSISTANT      (0x80)
 
- #define PL_REG_I2C_MODE_SM_FM           (0x03)
 
- #define PL_REG_I2C_MODE_FM_PLUS         (0x04)
 
- #define PL_SM_FM_MAX_FREQUENCY          (0x190)
 
- #define PL_DEFAULT_FREQUENCY            (0x64)
 
- #define PL_REG_BASE_ADDR_PERSISTANT     (0x80)
 
- #define PL_REG_BASE_ADDR_VOLATILE       (0x00)
 
- // Physical Layer Base Address Register mask
 
- #define PL_REG_I2C_BASE_ADDRESS_MASK     (0x7F)
 
- // Setup debug log statements
 
- #if IFX_I2C_LOG_PL == 1
 
- #include "common/Log_api.h"
 
- #define LOG_PL(args...) ifx_debug_log(IFX_I2C_LOG_ID_PL, args)
 
- #else
 
- #define LOG_PL(...) //printf(__VA_ARGS__)
 
- #endif
 
- /***********************************************************************************************************************
 
- * ENUMS
 
- **********************************************************************************************************************/
 
- /***********************************************************************************************************************
 
- * DATA STRUCTURES
 
- ***********************************************************************************************************************/
 
- /***********************************************************************************************************************
 
- * GLOBAL
 
- ***********************************************************************************************************************/
 
- static host_lib_status_t pal_event_status;
 
- /***********************************************************************************************************************
 
- * LOCAL ROUTINES
 
- ***********************************************************************************************************************/
 
- /// Physical Layer low level interface function
 
- static void ifx_i2c_pl_read_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len);
 
- /// Physical Layer low level interface function
 
- static void ifx_i2c_pl_write_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len, const uint8_t* p_content);
 
- /// Physical Layer high level interface timer callback (Status register polling)
 
- static void ifx_i2c_pl_status_poll_callback(void *p_ctx);
 
- /// Physical Layer intermediate state machine (Negotiation with slave)
 
- static void ifx_i2c_pl_negotiation_event_handler(void *p_input_ctx);
 
- /// Physical Layer intermediate state machine(Set bit rate)
 
- static host_lib_status_t ifx_i2c_pl_set_bit_rate(ifx_i2c_context_t *p_ctx, uint16_t bitrate);
 
- /// Physical Layer intermediate state machine (soft reset)
 
- static void ifx_i2c_pl_soft_reset(ifx_i2c_context_t *p_ctx);
 
- /// Physical Layer high level interface state machine (read/write frames)
 
- static void ifx_i2c_pl_frame_event_handler(ifx_i2c_context_t *p_ctx,host_lib_status_t event);
 
- /// Physical Layer low level interface timer callback (I2C Nack/Busy polling)
 
- static void ifx_i2c_pal_poll_callback(void *p_ctx);
 
- /// Physical Layer low level guard time callback
 
- static void ifx_i2c_pl_guard_time_callback(void *p_ctx);
 
- /// Physical Layer low level interface state machine (read/write registers)
 
- static void ifx_i2c_pl_pal_event_handler(void *p_ctx, host_lib_status_t event);
 
- /// Physical layer low level event handler for set slave address
 
- static void ifx_i2c_pl_pal_slave_addr_event_handler(void *p_input_ctx, host_lib_status_t event);
 
- /// @endcond
 
- /***********************************************************************************************************************
 
- * API PROTOTYPES
 
- **********************************************************************************************************************/
 
- /// Physical Layer high level interface function
 
- host_lib_status_t ifx_i2c_pl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler)
 
- {
 
-     LOG_PL("[IFX-PL]: Init\n");
 
-     p_ctx->pl.upper_layer_event_handler = handler;
 
-     p_ctx->pl.frame_state = PL_STATE_UNINIT;
 
-     p_ctx->pl.negotiate_state = PL_INIT_SET_FREQ_DEFAULT;
 
-     p_ctx->p_pal_i2c_ctx->slave_address = p_ctx->slave_address;
 
-     p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = (void*)ifx_i2c_pl_pal_event_handler;
 
-     p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT;
 
-     if(TRUE == p_ctx->do_pal_init)
 
-     {
 
-         // Initialize I2C driver
 
-         if (PAL_STATUS_SUCCESS != pal_i2c_init(p_ctx->p_pal_i2c_ctx))
 
-         {
 
-             return IFX_I2C_STACK_ERROR;
 
-         }
 
-     }
 
-     // Set Physical Layer internal state
 
-     if(p_ctx->pl.request_soft_reset == (uint8_t)TRUE)
 
-     {
 
-         //Set the soft reset request to initial state to read register
 
-         p_ctx->pl.request_soft_reset = PL_INIT_GET_STATUS_REG;
 
-         p_ctx->pl.frame_state = PL_STATE_SOFT_RESET;
 
-     }
 
-     else
 
-     {
 
-         p_ctx->pl.frame_state = PL_STATE_INIT;
 
-     }
 
-     ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
 
-     return IFX_I2C_STACK_SUCCESS;
 
- }
 
- /// Physical Layer high level interface function
 
- host_lib_status_t ifx_i2c_pl_send_frame(ifx_i2c_context_t *p_ctx,uint8_t* p_frame, uint16_t frame_len)
 
- {
 
-     // Physical Layer must be idle, set requested action
 
-     if (p_ctx->pl.frame_state != PL_STATE_INIT && p_ctx->pl.frame_state != PL_STATE_READY)
 
-     {
 
-         return IFX_I2C_STACK_ERROR;
 
-     }
 
-     p_ctx->pl.frame_action = PL_ACTION_WRITE_FRAME;
 
-     // Store reference to frame for sending it later
 
-     p_ctx->pl.p_tx_frame   = p_frame;
 
-     p_ctx->pl.tx_frame_len = frame_len;
 
-     ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
 
-     return IFX_I2C_STACK_SUCCESS;
 
- }
 
- /// Physical Layer high level interface function
 
- host_lib_status_t ifx_i2c_pl_receive_frame(ifx_i2c_context_t *p_ctx)
 
- {
 
-     // Physical Layer must be idle, set requested action
 
-     if (p_ctx->pl.frame_state != PL_STATE_INIT && p_ctx->pl.frame_state != PL_STATE_READY)
 
-     {
 
-         return IFX_I2C_STACK_ERROR;
 
-     }
 
-     p_ctx->pl.frame_action = PL_ACTION_READ_FRAME;
 
-     ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
 
-     return IFX_I2C_STACK_SUCCESS;
 
- }
 
- host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent)
 
- {
 
-     host_lib_status_t status = IFX_I2C_STACK_ERROR;
 
-     app_event_handler_t * temp_upper_layer_event_handler;
 
-     /// @cond hidden
 
-     #define PAL_WRITE_INIT_STATUS      (0x00FF)
 
-     #define ADDRESS_OFFSET              (0x02)
 
-     #define BASE_ADDRESS_REG_OFFSET     (0x00)
 
-     #define MODE_OFFSET                 (0x01)
 
-     /// @endcond
 
-     //lint --e{611} suppress "void* function pointer is type casted to app_event_handler_t type"
 
-     //ifx i2c wrapper api for setting slave address in synchronous. hence the event handler is backed up.
 
-     temp_upper_layer_event_handler = (app_event_handler_t *)(p_ctx->p_pal_i2c_ctx->upper_layer_event_handler);
 
-     //since the lower level APIs are asynchronous, a temporary event handler for set slave address is assigned
 
-     p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = (void*)ifx_i2c_pl_pal_slave_addr_event_handler;
 
-     p_ctx->pl.buffer[BASE_ADDRESS_REG_OFFSET] = PL_REG_BASE_ADDR;
 
-     p_ctx->pl.buffer[MODE_OFFSET] = PL_REG_BASE_ADDR_VOLATILE;
 
-     //supported base addresses are 0x00 - 0x7F. Hence 8th bit is ignored
 
-     p_ctx->pl.buffer[ADDRESS_OFFSET] = slave_address & PL_REG_I2C_BASE_ADDRESS_MASK;
 
-     p_ctx->pl.buffer_tx_len = 1 + PL_REG_LEN_BASE_ADDR;
 
-     if(PL_REG_BASE_ADDR_VOLATILE != persistent)
 
-     {
 
-         p_ctx->pl.buffer[MODE_OFFSET] = PL_REG_BASE_ADDR_PERSISTANT;
 
-     }
 
-     p_ctx->pl.retry_counter   = PL_POLLING_MAX_CNT;
 
-     while(p_ctx->pl.retry_counter)
 
-     {
 
-         pal_event_status = PAL_WRITE_INIT_STATUS;
 
-         //lint --e{534} suppress "Return value is not required to be checked"
 
-         pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len);
 
-         while(PAL_WRITE_INIT_STATUS == pal_event_status){};
 
-         if(PAL_I2C_EVENT_SUCCESS == pal_event_status)
 
-         {
 
-             break;
 
-         }
 
-         p_ctx->pl.retry_counter--;
 
-         pal_os_timer_delay_in_milliseconds(PL_POLLING_INVERVAL_US);
 
-     }
 
-     if(PAL_I2C_EVENT_SUCCESS == pal_event_status)
 
-     {
 
-         p_ctx->p_pal_i2c_ctx->slave_address = p_ctx->pl.buffer[ADDRESS_OFFSET];
 
-         if(PL_REG_BASE_ADDR_VOLATILE != persistent)
 
-         {
 
-             p_ctx->slave_address = p_ctx->pl.buffer[ADDRESS_OFFSET];
 
-         }
 
-         status = IFX_I2C_STACK_SUCCESS;
 
-     }
 
-     //restoring the backed up event handler
 
-     p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = temp_upper_layer_event_handler;
 
-     /// @cond hidden
 
-     #undef PAL_WRITE_INIT_STATUS
 
-     #undef ADDRESS_OFFSET
 
-     #undef BASE_ADDRESS_REG_OFFSET
 
-     #undef MODE_OFFSET
 
-     /// @endcond
 
-     return status;
 
- }
 
- static void ifx_i2c_pl_read_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len)
 
- {
 
-     LOG_PL("[IFX-PL]: Read register %x len %d\n", reg_addr, reg_len);
 
-     // Prepare transmit buffer to write register address
 
-     p_ctx->pl.buffer[0]     = reg_addr;
 
-     p_ctx->pl.buffer_tx_len = 1;
 
-     // Set low level interface variables and start transmission
 
-     p_ctx->pl.buffer_rx_len   = reg_len;
 
-     p_ctx->pl.register_action = PL_ACTION_READ_REGISTER;
 
-     p_ctx->pl.retry_counter   = PL_POLLING_MAX_CNT;
 
-     p_ctx->pl.i2c_cmd         = PL_I2C_CMD_WRITE;
 
-     //lint --e{534} suppress "Return value is not required to be checked"
 
-     pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len);
 
- }
 
- static void ifx_i2c_pl_write_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len, const uint8_t* p_content)
 
- {
 
-     LOG_PL("[IFX-PL]: Write register %x len %d\n", reg_addr, reg_len);
 
-     // Prepare transmit buffer to write register address and content
 
-     p_ctx->pl.buffer[0] = reg_addr;
 
-     memcpy(p_ctx->pl.buffer + 1, p_content, reg_len);
 
-     p_ctx->pl.buffer_tx_len = 1 + reg_len;
 
-     // Set Physical Layer low level interface variables and start transmission
 
-     p_ctx->pl.register_action = PL_ACTION_WRITE_REGISTER;
 
-     p_ctx->pl.retry_counter   = PL_POLLING_MAX_CNT;
 
-     p_ctx->pl.i2c_cmd         = PL_I2C_CMD_WRITE;
 
-     //lint --e{534} suppress "Return value is not required to be checked"
 
-     pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len);
 
- }
 
- static void ifx_i2c_pl_status_poll_callback(void *p_ctx)
 
- {
 
-     LOG_PL("[IFX-PL]: Status poll Timer elapsed  -> Read STATUS register\n");
 
-     ifx_i2c_pl_read_register((ifx_i2c_context_t*)p_ctx,PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE);
 
- }
 
- static host_lib_status_t ifx_i2c_pl_set_bit_rate(ifx_i2c_context_t *p_ctx, uint16_t bitrate)
 
- {
 
-     host_lib_status_t status;
 
-     void* pal_ctx_upper_layer_handler;
 
-     // Save upper layer context in pal
 
-     pal_ctx_upper_layer_handler = p_ctx->p_pal_i2c_ctx->upper_layer_event_handler;
 
-     // Pass context as NULL to avoid callback invocation
 
-     p_ctx->p_pal_i2c_ctx->upper_layer_event_handler  = NULL;
 
-     status = pal_i2c_set_bitrate(p_ctx->p_pal_i2c_ctx , bitrate);
 
-     // Restore callback
 
-     p_ctx->p_pal_i2c_ctx->upper_layer_event_handler  = pal_ctx_upper_layer_handler;
 
-     if(PAL_I2C_EVENT_SUCCESS != status)
 
-     {
 
-         if (p_ctx->pl.retry_counter--)
 
-         {
 
-             LOG_PL("[IFX-PL]: Set bit rate failed, Retry setting.\n");
 
-             pal_os_event_register_callback_oneshot(ifx_i2c_pl_negotiation_event_handler,((void*)p_ctx),PL_POLLING_INVERVAL_US);
 
-             status = IFX_I2C_STACK_BUSY;
 
-         }
 
-         else
 
-         {
 
-            status = IFX_I2C_STACK_ERROR;
 
-         }
 
-     }
 
-     else
 
-     {
 
-         status = IFX_I2C_STACK_SUCCESS;
 
-     }
 
-     return status;
 
- }
 
- static void ifx_i2c_pl_negotiation_event_handler(void *p_input_ctx)
 
- {
 
-     host_lib_status_t event = (uint8_t)IFX_I2C_STACK_ERROR;
 
-     uint8_t continue_negotiation;
 
-     ifx_i2c_context_t* p_ctx = (ifx_i2c_context_t*)p_input_ctx;
 
-     uint8_t i2c_mode_value[2];
 
-     uint8_t max_frame_size[2] = { (uint8_t)(p_ctx->frame_size >> 8), (uint8_t)(p_ctx->frame_size) };
 
-     uint16_t buffer_len = 0;
 
-     uint16_t slave_frequency;
 
-     uint16_t slave_frame_len;
 
-     uint8_t* p_buffer = NULL;
 
-     do
 
-     {
 
-         continue_negotiation = FALSE;
 
-         LOG_PL("[IFX-PL]: Negotiation started\n");
 
-         switch(p_ctx->pl.negotiate_state)
 
-         {
 
-             // Set initial frequency to PL_DEFAULT_FREQUENCY to be able to negotiate with slave
 
-             case PL_INIT_SET_FREQ_DEFAULT:
 
-             {
 
-                 // Default frequency set to master
 
-                 event = ifx_i2c_pl_set_bit_rate(p_input_ctx,PL_DEFAULT_FREQUENCY);
 
-                 if(IFX_I2C_STACK_SUCCESS == event)
 
-                 {
 
-                     p_ctx->pl.negotiate_state = PL_INIT_GET_FREQ_REG;
 
-                     continue_negotiation = TRUE;
 
-                 }
 
-                 else if (IFX_I2C_STACK_ERROR == event)
 
-                 {
 
-                     p_ctx->pl.negotiate_state = PL_INIT_DONE;
 
-                     p_buffer = NULL;
 
-                     buffer_len = 0;
 
-                 }
 
-             }
 
-             break;
 
-             // Read the current Max frequency supported by slave
 
-             case PL_INIT_GET_FREQ_REG:
 
-             {
 
-                 p_ctx->pl.negotiate_state = PL_INIT_SET_FREQ_REG;
 
-                 ifx_i2c_pl_read_register(p_ctx,PL_REG_MAX_SCL_FREQU, PL_REG_LEN_MAX_SCL_FREQU);
 
-             }
 
-             break;
 
-             // Set the I2C mode register
 
-             case PL_INIT_SET_FREQ_REG:
 
-             {
 
-                 slave_frequency = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3];
 
-                 i2c_mode_value[0] = PL_REG_I2C_MODE_PERSISTANT;
 
-                 if((p_ctx->frequency > PL_SM_FM_MAX_FREQUENCY)&&(slave_frequency<=PL_SM_FM_MAX_FREQUENCY))
 
-                 {
 
-                     //Change to FM+ mode if slave's current supported frequency is below user's requested frequency
 
-                     i2c_mode_value[1] = PL_REG_I2C_MODE_FM_PLUS;
 
-                     p_ctx->pl.negotiate_state = PL_INIT_READ_FREQ;
 
-                     ifx_i2c_pl_write_register(p_ctx,PL_REG_I2C_MODE, PL_REG_LEN_I2C_MODE, i2c_mode_value);
 
-                 }
 
-                 else if((p_ctx->frequency <= PL_SM_FM_MAX_FREQUENCY)&&(slave_frequency>PL_SM_FM_MAX_FREQUENCY))
 
-                 {
 
-                     //Change to SM&FM mode if slave's current supported frequency is above user's requested frequency
 
-                     i2c_mode_value[1] = PL_REG_I2C_MODE_SM_FM;
 
-                     p_ctx->pl.negotiate_state = PL_INIT_READ_FREQ;
 
-                     ifx_i2c_pl_write_register(p_ctx,PL_REG_I2C_MODE, PL_REG_LEN_I2C_MODE, i2c_mode_value);
 
-                 }
 
-                 else
 
-                 {
 
-                     p_ctx->pl.negotiate_state = PL_INIT_VERIFY_FREQ;
 
-                     continue_negotiation = TRUE;
 
-                 }
 
-             }
 
-             break;
 
-             // After setting I2C mode register, read the slave's supported frequency
 
-             case PL_INIT_READ_FREQ:
 
-             {
 
-                 p_ctx->pl.negotiate_state = PL_INIT_VERIFY_FREQ;
 
-                 ifx_i2c_pl_read_register(p_ctx,PL_REG_MAX_SCL_FREQU, PL_REG_LEN_MAX_SCL_FREQU);
 
-             }
 
-             break;
 
-             // Verify the requested frequency and slave's supported frequency
 
-             case PL_INIT_VERIFY_FREQ:
 
-             {
 
-                 slave_frequency = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3];
 
-                 if(p_ctx->frequency > slave_frequency)
 
-                 {
 
-                     LOG_PL("[IFX-PL]: Unexpected frequency in MAX_SCL_FREQU\n");
 
-                     p_buffer = NULL;
 
-                     buffer_len = 0;
 
-                     p_ctx->pl.negotiate_state = PL_INIT_DONE;
 
-                 }
 
-                 else
 
-                 {
 
-                     p_ctx->pl.negotiate_state = PL_INIT_AGREE_FREQ;
 
-                 }
 
-                 continue_negotiation = TRUE;
 
-             }
 
-             break;
 
-             // Frequency negotiated, Set frequency at master
 
-             case PL_INIT_AGREE_FREQ:
 
-             {
 
-                 // Frequency negotiation between master and slave is complete
 
-                 event = ifx_i2c_pl_set_bit_rate(p_input_ctx, p_ctx->frequency);
 
-                 if(IFX_I2C_STACK_SUCCESS == event)
 
-                 {
 
-                     p_ctx->pl.negotiate_state = PL_INIT_SET_DATA_REG_LEN;
 
-                     continue_negotiation = TRUE;
 
-                 }
 
-                 else if (IFX_I2C_STACK_ERROR == event)
 
-                 {
 
-                     p_ctx->pl.negotiate_state = PL_INIT_DONE;
 
-                     p_buffer = NULL;
 
-                     buffer_len = 0;
 
-                 }
 
-             }
 
-             break;
 
-             // Start frame length negotiation by writing the requested frame length
 
-             case PL_INIT_SET_DATA_REG_LEN:
 
-             {
 
-                 p_ctx->pl.negotiate_state = PL_INIT_GET_DATA_REG_LEN;
 
-                 ifx_i2c_pl_write_register(p_ctx,PL_REG_DATA_REG_LEN, sizeof(max_frame_size), max_frame_size);
 
-             }
 
-             break;
 
-             // Read the frame length to verify
 
-             case PL_INIT_GET_DATA_REG_LEN:
 
-             {
 
-                 p_ctx->pl.negotiate_state = PL_INIT_VERIFY_DATA_REG;
 
-                 ifx_i2c_pl_read_register(p_ctx,PL_REG_DATA_REG_LEN,PL_REG_LEN_DATA_REG_LEN);
 
-             }
 
-             break;
 
-             // Check is slave accepted the new frame length
 
-             case PL_INIT_VERIFY_DATA_REG:
 
-             {
 
-                 p_ctx->pl.negotiate_state = PL_INIT_DONE;
 
-                 slave_frame_len = (p_ctx->pl.buffer[0] << 8) | p_ctx->pl.buffer[1];
 
-                 // Error if slave's frame length is more than requested frame length
 
-                 if(p_ctx->frame_size >= slave_frame_len)
 
-                 {
 
-                     p_ctx->frame_size = slave_frame_len;
 
-                     event = IFX_I2C_STACK_SUCCESS;
 
-                 }
 
-                 p_buffer = NULL;
 
-                 buffer_len = 0;
 
-                 continue_negotiation = TRUE;
 
-             }
 
-             break;
 
-             case PL_INIT_DONE:
 
-             {
 
-                 if(IFX_I2C_STACK_SUCCESS == event)
 
-                 {
 
-                     p_ctx->pl.frame_state = PL_STATE_READY;
 
-                 }
 
-                 else
 
-                 {
 
-                     p_ctx->pl.frame_state = PL_STATE_UNINIT;
 
-                 }
 
-                 // Negotiation between master and slave is complete
 
-                 p_ctx->pl.upper_layer_event_handler(p_ctx,event, p_buffer, buffer_len);
 
-             }
 
-             break;
 
-             default:
 
-                 break;
 
-         }
 
-     }while(continue_negotiation);
 
- }
 
- static void ifx_i2c_pl_frame_event_handler(ifx_i2c_context_t *p_ctx,host_lib_status_t event)
 
- {
 
-     uint16_t frame_size;
 
-     if (event != IFX_I2C_STACK_SUCCESS)
 
-     {
 
-         p_ctx->pl.frame_state = PL_STATE_READY;
 
-         // I2C read or write failed, report to upper layer
 
-         p_ctx->pl.upper_layer_event_handler(p_ctx,event, 0, 0);
 
-     }
 
-     else
 
-     {
 
-         switch(p_ctx->pl.frame_state)
 
-         {
 
-             // Perform soft reset
 
-             case PL_STATE_SOFT_RESET:
 
-             {
 
-                 ifx_i2c_pl_soft_reset(p_ctx);
 
-             }
 
-             break;
 
-             // Negotiate frame and frequency with slave
 
-             case PL_STATE_INIT:
 
-             {
 
-                 ifx_i2c_pl_negotiation_event_handler(p_ctx);
 
-             }
 
-             break;
 
-             // Check status of slave data
 
-             case PL_STATE_READY:
 
-             {
 
-                 // Start polling status register
 
-                 p_ctx->pl.frame_state			= PL_STATE_DATA_AVAILABLE;
 
-                 ifx_i2c_pl_read_register(p_ctx,PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE);
 
-             }
 
-             break;
 
-             // Do read/write frame
 
-             case PL_STATE_DATA_AVAILABLE:
 
-             {
 
-                 // Read frame, if response is ready. Ignore busy flag
 
-                 if ((p_ctx->pl.frame_action == PL_ACTION_READ_FRAME)
 
-                 && (p_ctx->pl.buffer[0] & PL_REG_I2C_STATE_RESPONSE_READY))
 
-                 {
 
-                     frame_size = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3];
 
-                     if ((frame_size > 0) && (frame_size <= p_ctx->frame_size))
 
-                     {
 
-                         p_ctx->pl.frame_state = PL_STATE_RXTX;
 
-                         ifx_i2c_pl_read_register(p_ctx,PL_REG_DATA, frame_size);
 
-                     }
 
-                     else
 
-                     {
 
-                         // Continue polling STATUS register if retry limit is not reached
 
-                         if ((pal_os_timer_get_time_in_milliseconds() - p_ctx->dl.frame_start_time) < p_ctx->dl.data_poll_timeout)
 
-                         {
 
-                             pal_os_event_register_callback_oneshot(ifx_i2c_pl_status_poll_callback, (void *)p_ctx, PL_DATA_POLLING_INVERVAL_US);
 
-                         }
 
-                         else
 
-                         {
 
-                             p_ctx->pl.frame_state = PL_STATE_READY;
 
-                             p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_ERROR, 0, 0);
 
-                         }
 
-                     }
 
-                 }
 
-                 // Write frame is slave is not busy
 
-                 else if (p_ctx->pl.frame_action == PL_ACTION_WRITE_FRAME)
 
-                 {
 
-                     // Write frame if device is not busy, otherwise wait and poll STATUS again later
 
-                     p_ctx->pl.frame_state = PL_STATE_RXTX;
 
-                     ifx_i2c_pl_write_register(p_ctx,PL_REG_DATA, p_ctx->pl.tx_frame_len, (uint8_t*)p_ctx->pl.p_tx_frame);
 
-                 }
 
-                 // Continue checking the slave status register
 
-                 else
 
-                 {
 
-                     // Continue polling STATUS register if retry limit is not reached
 
-                     if ((pal_os_timer_get_time_in_milliseconds() - p_ctx->dl.frame_start_time) < p_ctx->dl.data_poll_timeout)
 
-                     {
 
-                         pal_os_event_register_callback_oneshot(ifx_i2c_pl_status_poll_callback, (void *)p_ctx, PL_DATA_POLLING_INVERVAL_US);
 
-                     }
 
-                     else
 
-                     {
 
-                         p_ctx->pl.frame_state = PL_STATE_READY;
 
-                         p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_ERROR, 0, 0);
 
-                     }
 
-                 }
 
-             }
 
-             break;
 
-             // Frame reading is complete
 
-             case PL_STATE_RXTX:
 
-             {
 
-                 // Writing/reading of frame to/from DATA register complete
 
-                 p_ctx->pl.frame_state = PL_STATE_READY;
 
-                 p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, p_ctx->pl.buffer, p_ctx->pl.buffer_rx_len);
 
-             }
 
-             break;
 
-             default:
 
-                 break;
 
-         }
 
-     }
 
- }
 
- static void ifx_i2c_pal_poll_callback(void *p_ctx)
 
- {
 
-     ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t *)p_ctx;
 
-     if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_WRITE)
 
-     {
 
-         LOG_PL("[IFX-PL]: Poll Timer elapsed -> Restart TX\n");
 
-         //lint --e{534} suppress "Return value is not required to be checked"
 
-         pal_i2c_write(p_local_ctx->p_pal_i2c_ctx, p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_tx_len);
 
-     }
 
-     else if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_READ)
 
-     {
 
-         LOG_PL("[IFX-PL]: Poll Timer elapsed  -> Restart Read Register -> Start TX\n");
 
-         //lint --e{534} suppress "Return value is not required to be checked"
 
-         pal_i2c_read(p_local_ctx->p_pal_i2c_ctx,p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_rx_len);
 
-     }
 
- }
 
- static void ifx_i2c_pl_guard_time_callback(void *p_ctx)
 
- {
 
-     ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t*)p_ctx;
 
-     if (p_local_ctx->pl.register_action == PL_ACTION_READ_REGISTER)
 
-     {
 
-         if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_WRITE)
 
-         {
 
-             LOG_PL("[IFX-PL]: GT done-> Start RX\n");
 
-             p_local_ctx->pl.i2c_cmd = PL_I2C_CMD_READ;
 
-             //lint --e{534} suppress "Return value is not required to be checked"
 
-             pal_i2c_read(p_local_ctx->p_pal_i2c_ctx,p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_rx_len);
 
-         }
 
-         else if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_READ)
 
-         {
 
-             LOG_PL("[IFX-PL]: GT done -> REG is read\n");
 
-             ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_STACK_SUCCESS);
 
-         }
 
-     }
 
-     else if (p_local_ctx->pl.register_action == PL_ACTION_WRITE_REGISTER)
 
-     {
 
-         LOG_PL("[IFX-PL]: GT done -> REG written\n");
 
-         ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_STACK_SUCCESS);
 
-     }
 
- }
 
- static void ifx_i2c_pl_pal_event_handler(void *p_ctx, host_lib_status_t event)
 
- {
 
-     ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t*)p_ctx;
 
-     switch (event)
 
-     {
 
-         case PAL_I2C_EVENT_ERROR:
 
-         case PAL_I2C_EVENT_BUSY:
 
-             // Error event usually occurs when the device is in sleep mode and needs time to wake up
 
-             if (p_local_ctx->pl.retry_counter--)
 
-             {
 
-                 LOG_PL("[IFX-PL]: PAL Error -> Continue polling\n");
 
-                 pal_os_event_register_callback_oneshot(ifx_i2c_pal_poll_callback,p_local_ctx,PL_POLLING_INVERVAL_US);
 
-             }
 
-             else
 
-             {
 
-                 LOG_PL("[IFX-PL]: PAL Error -> Stop\n");
 
-                 ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_FATAL_ERROR);
 
-             }
 
-             break;
 
-         case PAL_I2C_EVENT_SUCCESS:
 
-             LOG_PL("[IFX-PL]: PAL Success -> Wait Guard Time\n");
 
-             pal_os_event_register_callback_oneshot(ifx_i2c_pl_guard_time_callback,p_local_ctx,PL_GUARD_TIME_INTERVAL_US);
 
-             break;
 
-         default:
 
-             break;
 
-     }
 
- }
 
- static void ifx_i2c_pl_soft_reset(ifx_i2c_context_t *p_ctx)
 
- {
 
-     uint8_t i2c_mode_value[2] = {0};
 
-     switch(p_ctx->pl.request_soft_reset)
 
-     {
 
-         case PL_INIT_GET_STATUS_REG:
 
-             p_ctx->pl.request_soft_reset = PL_RESET_WRITE;
 
-             //Read the status register to check if soft reset is supported
 
-             ifx_i2c_pl_read_register(p_ctx, PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE);
 
-             break;
 
-         case PL_RESET_WRITE:
 
-             //Mask for soft reset bit(5th bit) from the 1st byte of status register
 
-             p_ctx->pl.buffer[0] &= PL_REG_I2C_STATE_SOFT_RESET;
 
-             if(p_ctx->pl.buffer[0] == PL_REG_I2C_STATE_SOFT_RESET)
 
-             {
 
-                 p_ctx->pl.request_soft_reset = PL_RESET_STARTUP;
 
-                 //Write 88 register with 0 value
 
-                 ifx_i2c_pl_write_register(p_ctx, PL_REG_SOFT_RESET, PL_REG_LEN_SOFT_RESET, i2c_mode_value);
 
-             }
 
-             else
 
-             {
 
-                 //Soft reset is not supported by the slave
 
-                 p_ctx->pl.frame_state = PL_STATE_UNINIT;
 
-                 ifx_i2c_pl_frame_event_handler(p_ctx, IFX_I2C_STACK_ERROR);
 
-             }
 
-             break;
 
-         case PL_RESET_STARTUP:
 
-             p_ctx->pl.request_soft_reset= PL_RESET_INIT;
 
-             pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_pl_soft_reset, (void *)p_ctx, STARTUP_TIME_MSEC);
 
-             break;
 
-         case PL_RESET_INIT:
 
-             p_ctx->pl.frame_state = PL_STATE_INIT;
 
-             ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
 
-             break;
 
-         default:
 
-             break;
 
-     }
 
- }
 
- //lint --e{715} suppress "This is used for synchromous implementation, hence p_ctx not used"
 
- //lint --e{818} suppress "This is ignored as upper layer handler function prototype requires this argument"
 
- static void ifx_i2c_pl_pal_slave_addr_event_handler(void *p_ctx, host_lib_status_t event)
 
- {
 
-     pal_event_status = event;
 
- }
 
 
  |