/*
* File : I2CMgr.c
* Scope :
*
* Description: This contains implementations for I2C manager which handles
* the i2c protocol.
*
*
* Copyright 2003 ZiLOG Inc. ALL RIGHTS RESERVED.
*
* This file contains unpublished confidential and proprietary information
* of ZiLOG, Inc.
* NO PART OF THIS WORK MAY BE DUPLICATED, STORED, PUBLISHED OR DISCLOSED
* IN ANY FORM WITHOUT THE PRIOR WRITTEN CONSENT OF ZiLOG, INC.
* This is not a license and no use of any kind of this work is authorized
* in the absence of a written license granted by ZiLOG, Inc. in ZiLOG's
* sole discretion
*/
#ifdef _IAR_CODE
#ifdef _EZ80F91
#include <ioez80f91.h>
#endif
#ifdef _EZ80F92
#include <ioez80f92.h>
#endif
#ifdef _EZ80F93
#include <ioez80f92.h>
#endif
#ifdef _EZ80L92
#include <ioez80l92.h>
#endif
#ifdef _EZ80190
#include <ioez80190.h>
#endif
#else
#include <ez80.h>
#endif
#include <stdio.h>
#include "ZTypes.h"
#include "ZSysgen.h"
#include "ZInterrupt.h"
#include "ZThread.h"
#include "ZSemaphore.h"
#include "i2c.h"
extern UINT8 I2C_TASK_STACK[] ;
extern UINT8 i2cRxBuff[] ;
extern UINT8 i2cTxBuff[] ;
extern UINT I2C_TASK_STACK_SIZE ;
extern UINT8 I2C_TASK_PRIORITY ;
extern I2C_CONFIG_t i2cConfigParams ;
extern UINT I2C_RX_MAX_BUFF_SIZE ;
extern UINT I2C_TX_MAX_BUFF_SIZE ;
RZK_SEMAPHOREHANDLE_t hSem_I2C;
void I2cInterruptTask(void) ;
INT rxAvail ;
CQ_t rxCQ ;
CQ_t txCQ ;
RZK_THREADHANDLE_t i2cIntThreadHdl ;
void CQ_IN( CQ_t *pCQ, UINT8 ch )
{
if( pCQ->rear == pCQ->bufLen - 1 )
{
pCQ->rear = 0 ;
}
else
pCQ->rear++ ;
pCQ->pBuff[pCQ->rear] = ch ;
pCQ->avail++ ;
}
UINT8 CQ_OUT(CQ_t *pCQ)
{
UINT8 data = 0;
data = pCQ->pBuff[pCQ->front] ;
if ( pCQ->front == pCQ->bufLen - 1 )
pCQ->front = 0 ;
else
pCQ->front++ ;
pCQ->avail-- ;
return data ;
}
DDF_STATUS_t I2CPeek()
{
DDF_STATUS_t avail ;
UINTRMASK intmask ;
intmask = RZKDisableInterrupts() ;
avail = rxCQ.avail ;
RZKEnableInterrupts(intmask) ;
return avail ;
}
DDF_STATUS_t I2COpen( RZK_DEVICE_CB_t *pDCB, INT8 *devName, INT8 * devMode )
{
UINTRMASK intmask;
/** Opens the I2C bus by initializing the ports and
setting up the registers to a known state
* Creates interrupt thread
* Configures I2C based on whether it is a master or slave */
if(RZKDEV_OPENED == pDCB->InUse)
return I2CERR_SUCCESS ;
i2cConfigParams.mode = *devMode ;
I2CDev_Init();
hSem_I2C = RZKCreateSemaphore((RZK_NAME_t*)"hSem_I2C", 1, RECV_ORDER_PRIORITY) ;//KE_SemCreate( 1 );
if(hSem_I2C == NULL)
printf("\nI2C Semaphore creation error");
if(*devMode == I2C_SLAVE)
{
i2cIntThreadHdl = RZKCreateThreadEnhanced((RZK_NAME_t*)"I2C",
(RZK_PTR_t)I2cInterruptTask,
NULL,
I2C_TASK_STACK_SIZE,
I2C_TASK_PRIORITY,1,
RZK_THREAD_PREEMPTION|RZK_THREAD_INTERRUPT,0) ;
if(i2cIntThreadHdl == NULL)
{
return I2CERR_KERNELERROR ;
}
rxCQ.rear = -1 ;
rxCQ.front = 0 ;
txCQ.rear = -1 ;
txCQ.front = 0 ;
rxCQ.pBuff = i2cRxBuff ;
txCQ.pBuff = i2cTxBuff ;
rxCQ.bufLen = I2C_RX_MAX_BUFF_SIZE ;
txCQ.bufLen = I2C_TX_MAX_BUFF_SIZE ;
rxCQ.avail = 0 ;
txCQ.avail = 0 ;
}
intmask = RZKDisableInterrupts() ;
pDCB->InUse = RZKDEV_OPENED ;
RZKEnableInterrupts(intmask) ;
return I2CERR_SUCCESS ;
}
DDF_STATUS_t I2CClose( RZK_DEVICE_CB_t * pDCB)
{
UINTRMASK intmask ;
/** Close I2C bus
* Deletes interrupt thread
*/
if(RZKDEV_OPENED != pDCB->InUse)
return I2CERR_INVALID_OPERATION ;
RZKDeleteThreadEnhanced(i2cIntThreadHdl) ;
intmask = RZKDisableInterrupts() ;
pDCB->InUse &= ~RZKDEV_OPENED ;
RZKEnableInterrupts(intmask) ;
return I2CERR_SUCCESS ;
}
DDF_STATUS_t I2CWrite( RZK_DEVICE_CB_t * pDCB, INT8 * buf, RZK_DEV_BYTES_t size )
{
INT stat = 0 ;
INT32 i ; // INT changed to INT32
UINT8 slvaddr = i2cConfigParams.currSlaveAddr ;
UINT8 useSubAddr = i2cConfigParams.useSubAddr ;
UINT subAddr = i2cConfigParams.subAddr ;
// UINTRMASK intmask ; //Commented during IAR Porting
UINT16 count ;
/* If master
Send the start condition
Send slave address with write bit
Send data
Send STOP condn
If slave
write the data to the Tx circular buffer in the I2C
Actual transmission will happen from the interrupt thd context.
*/
if(RZKDEV_OPENED != pDCB->InUse)
return I2CERR_INVALID_OPERATION ;
if(I2C_BUS_BUSY == pDCB->InUse)
return I2CERR_BUSBUSY ;
else
{
RZKAcquireSemaphore(hSem_I2C,INFINITE_SUSPEND);
// mask = RZKDisablePreemption() ;
pDCB->InUse |= I2C_BUS_BUSY ;
if(I2C_MASTER == i2cConfigParams.mode)
{
stat = I2CDev_SendStart() ;
if(stat<0)
{
pDCB->InUse &= ~I2C_BUS_BUSY ;
RZKReleaseSemaphore(hSem_I2C);
// RZKRestorePreemption(mask) ;
return stat ;
}
slvaddr |= I2CMODE_TRANSMIT ;
stat = I2CDev_TransmitDataByte(slvaddr) ;
if(stat<0)
{
I2CDev_SendStop() ;
pDCB->InUse &= ~I2C_BUS_BUSY ;
RZKReleaseSemaphore(hSem_I2C);
// RZKRestorePreemption(mask) ;
return stat ;
}
if(useSubAddr == RZK_TRUE)
{
switch(i2cConfigParams.addrLen)
{
case 3:
stat = I2CDev_TransmitDataByte(subAddr) ;
if(stat<0)
break ;
subAddr >>= 8 ;
case 2:
stat = I2CDev_TransmitDataByte(subAddr) ;
if(stat<0)
break ;
subAddr >>= 8 ;
case 1:
stat = I2CDev_TransmitDataByte(subAddr) ;
break ;
}
if(stat<0)
{
I2CDev_SendStop() ;
pDCB->InUse &= ~I2C_BUS_BUSY ;
RZKReleaseSemaphore(hSem_I2C);
// RZKRestorePreemption(mask) ;
return stat ;
}
}
for(i=0; i<size; i++)
{
stat = I2CDev_TransmitDataByte(*buf) ;
if(stat<0)
{
I2CDev_SendStop() ;
pDCB->InUse &= ~I2C_BUS_BUSY ;
RZKReleaseSemaphore(hSem_I2C);
// RZKRestorePreemption(mask) ;
return stat ;
}
else
buf++ ;
}
I2CDev_SendStop() ;
count = COUNT_DELAY ;
I2C_Delay(count) ;
}
else
{
for(i=0; i<size; i++)
{
CQ_IN(&txCQ, *buf++) ;
}
}
}
pDCB->InUse &= ~I2C_BUS_BUSY ;
RZKReleaseSemaphore(hSem_I2C);
// RZKRestorePreemption(mask) ;
return size ;
}
DDF_STATUS_t I2CRead(RZK_DEVICE_CB_t * pDCB, INT8 * buf, RZK_DEV_BYTES_t size)
{
INT stat = 0 ;
INT32 i ; // INT changed to INT32
UINT8 slvaddr = i2cConfigParams.currSlaveAddr ;
UINT8 useSubAddr = i2cConfigParams.useSubAddr ;
UINT subAddr = i2cConfigParams.subAddr ;
// UINTRMASK intmask ; //Commented during IAR Porting
UINT16