blob: 84a97cd404b02262010e2d2a7dd60637fb75656b [file] [log] [blame]
/******************************************************************************
* @file app_i2c_slave.c
*
* @brief for TLSR chips
*
* @author public@telink-semi.com;
* @date Sep. 30, 2010
*
* @attention
*
* Copyright (C) 2019-2020 Telink Semiconductor (Shanghai) Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include "tl_common.h"
#include "drivers.h"
#if(DRIVER_TEST_MODE == TEST_IIC && I2C_DEMO_SELECT == I2C_DEMO_SLAVE)
/**************************************************************************************
8258 Demo Code Config
1. select i2c demo: master or slave( config it in app_config.h )
2. if i2c slave demo, select slave working mode: mapping mode or dma mode
3. if i2c master demo, select the peer device i2c slave address mode
*************************************************************************************/
#if(I2C_DEMO_SELECT == I2C_DEMO_SLAVE)
#define SLAVE_DMA_MODE 1 //i2c slave use dma mode
#define SLAVE_MAPPING_MODE 2 //i2c slave use mapping mode
//select i2c slave mode here(dma mode or mapping mode)
#define I2C_SLAVE_MODE SLAVE_DMA_MODE
#endif
/**************************************************************************************
*
*************************************************************************************/
/*************** i2c slave data buffer ****************/
#if(I2C_SLAVE_MODE == SLAVE_DMA_MODE)
//dma mode write & read buff
unsigned char * pBuf_slave_dma_for_write;
unsigned char * pBuf_slave_dma_for_read;
#elif(I2C_SLAVE_MODE == SLAVE_MAPPING_MODE)
//mapping mode, write buffer is the first half 64 byte, read buffer is last half 64 byte
_attribute_aligned_(128) volatile unsigned char slave_mapping_buff[128] = {0};
#endif
#define SLAVE_DMA_READ_DATA_CHANGE_EN 0 //1: read buff data changes; 0: read buff data stay unchanged
unsigned char slave_rx_buff_debug[DBG_DATA_LEN *DBG_DATA_NUM]; //store i2c master writing data here to debug
int slave_rx_index = 0;
#define IRQ_IIC_CLEAR 0
#define IRQ_IIC_READ BIT(0) //read
#define IRQ_IIC_WRITE BIT(1) //write
int i2c_irq_flag = IRQ_IIC_CLEAR;
void i2c_slave_test_init(void)
{
i2c_gpio_set(I2C_GPIO_SDA_C0,I2C_GPIO_SCL_C1); //SDA/CK : C0/C1
#if(I2C_SLAVE_MODE == SLAVE_DMA_MODE)
//slave device id 0x5C(write) 0x5D(read)
//i2c slave dma mode, master need send 3 byte sram address(0x40000~0x4ffff) on i2c bus in i2c reading/writing
i2c_slave_init(0x5C, I2C_SLAVE_DMA, NULL);
//write&read sram address in dma mode
//master write data to sram address SLAVE_DMA_MODE_ADDR_WRITE
//slave put data on sram address SLAVE_DMA_MODE_ADDR_READ
pBuf_slave_dma_for_write = (unsigned char *)(SLAVE_DMA_MODE_ADDR_WRITE | REG_BASE_ADDR);
pBuf_slave_dma_for_read = (unsigned char *)(SLAVE_DMA_MODE_ADDR_READ | REG_BASE_ADDR);
memset(pBuf_slave_dma_for_write, 0, DBG_DATA_LEN); //clear write buffer data
for(int i=0;i<DBG_DATA_LEN;i++){ //set read buffer initial data (1,2,3....16)
pBuf_slave_dma_for_read[i] = i+1;
}
#elif(I2C_SLAVE_MODE == SLAVE_MAPPING_MODE)
//slave device id 0x5C(write) 0x5D(read)
//i2c slave mapping mode, master no need send any address when reading/writing,
//for i2c master: writing data buffer is slave_mapping_buff,
//and reading data buffer is (slave_mapping_buff+64) (this offset 64 is managed by MCU hardware, user can not change it)
i2c_slave_init(0x5C, I2C_SLAVE_MAP, (unsigned char *)slave_mapping_buff);
//slave_mapping_buff + 64 is master reading data buffer in mapping mode, put some data here for master read
//initial data (1,2,3 ... 16)
for(int i=0;i<DBG_DATA_LEN;i++){
slave_mapping_buff[64+i] = i+1;
}
#endif
reg_i2c_map_host_status = (FLD_HOST_CMD_IRQ | FLD_HOST_READ_IRQ); //clean irq status
reg_irq_mask |= FLD_IRQ_HOST_CMD_EN; //enable i2c irq
irq_enable(); //enable system irq
}
void i2c_slave_mainloop(void)
{
#if(I2C_SLAVE_MODE == SLAVE_DMA_MODE) //8258 i2c slave dma mode
//in dma mode, write & read data buffer could be different
#if (SLAVE_DMA_READ_DATA_CHANGE_EN)
//i2c slave data changes, and i2c master can read different data
static u32 data_change_time = 0;
static u32 data_change_index = 0;
if(clock_time_exceed(data_change_time, 1000000)){
data_change_time = clock_time();
data_change_index ++;
for(int i=0;i<DBG_DATA_LEN;i++){
pBuf_slave_dma_for_read[i] = data_change_index;
}
}
#endif
#elif(I2C_SLAVE_MODE == SLAVE_MAPPING_MODE) //8258 i2c slave mapping mode
//in mapping mode, i2c master reading data from (slave_mapping_buff+64)
#if (SLAVE_DMA_READ_DATA_CHANGE_EN)
//i2c slave data changes, and i2c master can read different data
static u32 data_change_time = 0;
static u32 data_change_index = 0;
if(clock_time_exceed(data_change_time, 1000000)){
data_change_time = clock_time();
data_change_index ++;
}
if(i2c_irq_flag){ //i2c master write or read operation happens
if(i2c_irq_flag & IRQ_IIC_READ){ //i2c master has just read data
DBG_CHN2_TOGGLE;
for(int i=0;i<DBG_DATA_LEN;i++){
slave_mapping_buff[64 + i] = data_change_index;
}
}
i2c_irq_flag = IRQ_IIC_CLEAR; //clear
}
#endif
#endif
}
int irq_cnt = 0;
int i2c_read_cnt = 0; //for debug
int i2c_write_cnt = 0; //for debug
_attribute_ram_code_ void app_i2c_test_irq_proc(void)
{
irq_cnt ++; //for debug
u8 irq_status = reg_i2c_map_host_status;//i2c slave can distinguish the operation host write or read.
if(irq_status & FLD_HOST_CMD_IRQ){ //both host write & read trigger this status
reg_i2c_map_host_status = irq_status; //clear all irq status
if(irq_status & FLD_HOST_READ_IRQ){ //host read
i2c_read_cnt ++; //for debug
DBG_CHN0_TOGGLE; //for gpio debug
i2c_irq_flag |= IRQ_IIC_READ;
}
else{ //host write
i2c_write_cnt ++; //for debug
DBG_CHN1_TOGGLE; //for debug
i2c_irq_flag |= IRQ_IIC_WRITE;
/*********** copy the data written by i2c master to slave_rx_buff_debug for debug ****************/
#if (I2C_SLAVE_MODE == SLAVE_DMA_MODE)
memcpy( (unsigned char*)(slave_rx_buff_debug + slave_rx_index*DBG_DATA_LEN), (unsigned char*)pBuf_slave_dma_for_write, DBG_DATA_LEN);
#elif (I2C_SLAVE_MODE == SLAVE_MAPPING_MODE)
memcpy( (unsigned char*)(slave_rx_buff_debug + slave_rx_index*DBG_DATA_LEN), (unsigned char*)slave_mapping_buff, DBG_DATA_LEN);
#endif
slave_rx_index ++;
if(slave_rx_index>=DBG_DATA_NUM){
slave_rx_index = 0;
}
/******************************** end ****************************************************/
}
}
}
#endif